Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 31862
b: refs/heads/master
c: b9e5b4e
h: refs/heads/master
v: v3
  • Loading branch information
Benjamin Herrenschmidt authored and Paul Mackerras committed Jul 3, 2006
1 parent e953f89 commit 2471287
Show file tree
Hide file tree
Showing 18 changed files with 674 additions and 617 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5a43a066b11ac2fe84cf67307f20b83bea390f83
refs/heads/master: b9e5b4e6a991a5a6d521f2e20a65835404b4169f
30 changes: 12 additions & 18 deletions trunk/arch/powerpc/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,28 +62,27 @@
#endif

int __irq_offset_value;
#ifdef CONFIG_PPC32
EXPORT_SYMBOL(__irq_offset_value);
#endif

static int ppc_spurious_interrupts;

#ifdef CONFIG_PPC32
#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
EXPORT_SYMBOL(__irq_offset_value);
atomic_t ppc_n_lost_interrupts;

#ifndef CONFIG_PPC_MERGE
#define NR_MASK_WORDS ((NR_IRQS + 31) / 32)
unsigned long ppc_cached_irq_mask[NR_MASK_WORDS];
atomic_t ppc_n_lost_interrupts;
#endif

#ifdef CONFIG_TAU_INT
extern int tau_initialized;
extern int tau_interrupts(int);
#endif
#endif /* CONFIG_PPC32 */

#if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE)
extern atomic_t ipi_recv;
extern atomic_t ipi_sent;
#endif
#endif /* CONFIG_PPC32 */

#ifdef CONFIG_PPC64
EXPORT_SYMBOL(irq_desc);
Expand Down Expand Up @@ -219,15 +218,19 @@ void do_IRQ(struct pt_regs *regs)
curtp = current_thread_info();
irqtp = hardirq_ctx[smp_processor_id()];
if (curtp != irqtp) {
struct irq_desc *desc = irq_desc + irq;
void *handler = desc->handle_irq;
if (handler == NULL)
handler = &__do_IRQ;
irqtp->task = curtp->task;
irqtp->flags = 0;
call___do_IRQ(irq, regs, irqtp);
call_handle_irq(irq, desc, regs, irqtp, handler);
irqtp->task = NULL;
if (irqtp->flags)
set_bits(irqtp->flags, &curtp->flags);
} else
#endif
__do_IRQ(irq, regs);
generic_handle_irq(irq, regs);
} else if (irq != -2)
/* That's not SMP safe ... but who cares ? */
ppc_spurious_interrupts++;
Expand All @@ -245,15 +248,6 @@ void do_IRQ(struct pt_regs *regs)

void __init init_IRQ(void)
{
#ifdef CONFIG_PPC64
static int once = 0;

if (once)
return;

once++;

#endif
ppc_md.init_IRQ();
#ifdef CONFIG_PPC64
irq_ctx_init();
Expand Down
10 changes: 6 additions & 4 deletions trunk/arch/powerpc/kernel/misc_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,14 @@ _GLOBAL(call_do_softirq)
mtlr r0
blr

_GLOBAL(call___do_IRQ)
_GLOBAL(call_handle_irq)
ld r8,0(r7)
mflr r0
std r0,16(r1)
stdu r1,THREAD_SIZE-112(r5)
mr r1,r5
bl .__do_IRQ
mtctr r8
stdu r1,THREAD_SIZE-112(r6)
mr r1,r6
bctrl
ld r1,0(r1)
ld r0,16(r1)
mtlr r0
Expand Down
111 changes: 56 additions & 55 deletions trunk/arch/powerpc/platforms/cell/interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,64 +37,51 @@
struct iic {
struct cbe_iic_thread_regs __iomem *regs;
u8 target_id;
u8 eoi_stack[16];
int eoi_ptr;
};

static DEFINE_PER_CPU(struct iic, iic);

void iic_local_enable(void)
static void iic_mask(unsigned int irq)
{
struct iic *iic = &__get_cpu_var(iic);
u64 tmp;

/*
* There seems to be a bug that is present in DD2.x CPUs
* and still only partially fixed in DD3.1.
* This bug causes a value written to the priority register
* not to make it there, resulting in a system hang unless we
* write it again.
* Masking with 0xf0 is done because the Cell BE does not
* implement the lower four bits of the interrupt priority,
* they always read back as zeroes, although future CPUs
* might implement different bits.
*/
do {
out_be64(&iic->regs->prio, 0xff);
tmp = in_be64(&iic->regs->prio);
} while ((tmp & 0xf0) != 0xf0);
}

void iic_local_disable(void)
{
out_be64(&__get_cpu_var(iic).regs->prio, 0x0);
}

static unsigned int iic_startup(unsigned int irq)
{
return 0;
}

static void iic_enable(unsigned int irq)
{
iic_local_enable();
}

static void iic_disable(unsigned int irq)
static void iic_unmask(unsigned int irq)
{
}

static void iic_end(unsigned int irq)
static void iic_eoi(unsigned int irq)
{
iic_local_enable();
struct iic *iic = &__get_cpu_var(iic);
out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]);
BUG_ON(iic->eoi_ptr < 0);
}

static struct hw_interrupt_type iic_pic = {
static struct irq_chip iic_chip = {
.typename = " CELL-IIC ",
.startup = iic_startup,
.enable = iic_enable,
.disable = iic_disable,
.end = iic_end,
.mask = iic_mask,
.unmask = iic_unmask,
.eoi = iic_eoi,
};

/* XXX All of this has to be reworked completely. We need to assign a real
* interrupt numbers to the external interrupts and remove all the hard coded
* interrupt maps (rely on the device-tree whenever possible).
*
* Basically, my scheme is to define the "pendings" bits to be the HW interrupt
* number (ignoring the data and flags here). That means we can sort-of split
* external sources based on priority, and we can use request_irq() on pretty
* much anything.
*
* For spider or axon, they have their own interrupt space. spider will just have
* local "hardward" interrupts 0...xx * node stride. The node stride is not
* necessary (separate interrupt chips will have separate HW number space), but
* will allow to be compatible with existing device-trees.
*
* All of thise little world will get a standard remapping scheme to map those HW
* numbers into the linux flat irq number space.
*/
static int iic_external_get_irq(struct cbe_iic_pending_bits pending)
{
int irq;
Expand All @@ -118,9 +105,10 @@ static int iic_external_get_irq(struct cbe_iic_pending_bits pending)
*/
if (pending.class != 2)
break;
irq = IIC_EXT_OFFSET
+ spider_get_irq(node)
+ node * IIC_NODE_STRIDE;
/* TODO: We might want to silently ignore cascade interrupts
* when no cascade handler exist yet
*/
irq = IIC_EXT_CASCADE + node * IIC_NODE_STRIDE;
break;
case 0x01 ... 0x04:
case 0x07 ... 0x0a:
Expand Down Expand Up @@ -152,6 +140,8 @@ int iic_get_irq(struct pt_regs *regs)
iic = &__get_cpu_var(iic);
*(unsigned long *) &pending =
in_be64((unsigned long __iomem *) &iic->regs->pending_destr);
iic->eoi_stack[++iic->eoi_ptr] = pending.prio;
BUG_ON(iic->eoi_ptr > 15);

irq = -1;
if (pending.flags & CBE_IIC_IRQ_VALID) {
Expand All @@ -172,7 +162,7 @@ int iic_get_irq(struct pt_regs *regs)

/* hardcoded part to be compatible with older firmware */

static int setup_iic_hardcoded(void)
static int __init setup_iic_hardcoded(void)
{
struct device_node *np;
int nodeid, cpu;
Expand Down Expand Up @@ -207,12 +197,13 @@ static int setup_iic_hardcoded(void)
printk(KERN_INFO "IIC for CPU %d at %lx\n", cpu, regs);
iic->regs = ioremap(regs, sizeof(struct cbe_iic_thread_regs));
iic->target_id = (nodeid << 4) + ((cpu & 1) ? 0xf : 0xe);
iic->eoi_stack[0] = 0xff;
}

return 0;
}

static int setup_iic(void)
static int __init setup_iic(void)
{
struct device_node *dn;
unsigned long *regs;
Expand Down Expand Up @@ -248,11 +239,14 @@ static int setup_iic(void)
iic = &per_cpu(iic, np[0]);
iic->regs = ioremap(regs[0], sizeof(struct cbe_iic_thread_regs));
iic->target_id = ((np[0] & 2) << 3) + ((np[0] & 1) ? 0xf : 0xe);
iic->eoi_stack[0] = 0xff;
printk("IIC for CPU %d at %lx mapped to %p\n", np[0], regs[0], iic->regs);

iic = &per_cpu(iic, np[1]);
iic->regs = ioremap(regs[2], sizeof(struct cbe_iic_thread_regs));
iic->target_id = ((np[1] & 2) << 3) + ((np[1] & 1) ? 0xf : 0xe);
iic->eoi_stack[0] = 0xff;

printk("IIC for CPU %d at %lx mapped to %p\n", np[1], regs[2], iic->regs);

found++;
Expand Down Expand Up @@ -304,10 +298,10 @@ static void iic_request_ipi(int ipi, const char *name)
int irq;

irq = iic_ipi_to_irq(ipi);

/* IPIs are marked IRQF_DISABLED as they must run with irqs
* disabled */
get_irq_desc(irq)->chip = &iic_pic;
get_irq_desc(irq)->status |= IRQ_PER_CPU;
set_irq_chip_and_handler(irq, &iic_chip, handle_percpu_irq);
request_irq(irq, iic_ipi_action, IRQF_DISABLED, name, NULL);
}

Expand All @@ -321,20 +315,26 @@ void iic_request_IPIs(void)
}
#endif /* CONFIG_SMP */

static void iic_setup_spe_handlers(void)
static void __init iic_setup_builtin_handlers(void)
{
int be, isrc;

/* Assume two threads per BE are present */
/* XXX FIXME: Assume two threads per BE are present */
for (be=0; be < num_present_cpus() / 2; be++) {
int irq;

/* setup SPE chip and handlers */
for (isrc = 0; isrc < IIC_CLASS_STRIDE * 3; isrc++) {
int irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc;
get_irq_desc(irq)->chip = &iic_pic;
irq = IIC_NODE_STRIDE * be + IIC_SPE_OFFSET + isrc;
set_irq_chip_and_handler(irq, &iic_chip, handle_fasteoi_irq);
}
/* setup cascade chip */
irq = IIC_EXT_CASCADE + be * IIC_NODE_STRIDE;
set_irq_chip_and_handler(irq, &iic_chip, handle_fasteoi_irq);
}
}

void iic_init_IRQ(void)
void __init iic_init_IRQ(void)
{
int cpu, irq_offset;
struct iic *iic;
Expand All @@ -348,5 +348,6 @@ void iic_init_IRQ(void)
if (iic->regs)
out_be64(&iic->regs->prio, 0xff);
}
iic_setup_spe_handlers();
iic_setup_builtin_handlers();

}
4 changes: 1 addition & 3 deletions trunk/arch/powerpc/platforms/cell/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

enum {
IIC_EXT_OFFSET = 0x00, /* Start of south bridge IRQs */
IIC_EXT_CASCADE = 0x20, /* There is no interrupt 32 on spider */
IIC_NUM_EXT = 0x40, /* Number of south bridge IRQs */
IIC_SPE_OFFSET = 0x40, /* Start of SPE interrupts */
IIC_CLASS_STRIDE = 0x10, /* SPE IRQs per class */
Expand All @@ -51,13 +52,10 @@ extern int iic_get_irq(struct pt_regs *regs);
extern void iic_cause_IPI(int cpu, int mesg);
extern void iic_request_IPIs(void);
extern void iic_setup_cpu(void);
extern void iic_local_enable(void);
extern void iic_local_disable(void);

extern u8 iic_get_target_id(int cpu);

extern void spider_init_IRQ(void);
extern int spider_get_irq(int node);

#endif
#endif /* ASM_CELL_PIC_H */
12 changes: 9 additions & 3 deletions trunk/arch/powerpc/platforms/cell/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,14 @@ static void cell_progress(char *s, unsigned short hex)
printk("*** %04x : %s\n", hex, s ? s : "");
}

static void __init cell_init_irq(void)
{
iic_init_IRQ();
spider_init_IRQ();
}

static void __init cell_setup_arch(void)
{
ppc_md.init_IRQ = iic_init_IRQ;
ppc_md.get_irq = iic_get_irq;
#ifdef CONFIG_SPU_BASE
spu_priv1_ops = &spu_priv1_mmio_ops;
#endif
Expand All @@ -109,7 +113,6 @@ static void __init cell_setup_arch(void)
/* Find and initialize PCI host bridges */
init_pci_config_tokens();
find_and_init_phbs();
spider_init_IRQ();
cbe_pervasive_init();
#ifdef CONFIG_DUMMY_CONSOLE
conswitchp = &dummy_con;
Expand Down Expand Up @@ -174,6 +177,9 @@ define_machine(cell) {
.calibrate_decr = generic_calibrate_decr,
.check_legacy_ioport = cell_check_legacy_ioport,
.progress = cell_progress,
.init_IRQ = cell_init_irq,
.get_irq = iic_get_irq,

#ifdef CONFIG_KEXEC
.machine_kexec = default_machine_kexec,
.machine_kexec_prepare = default_machine_kexec_prepare,
Expand Down
Loading

0 comments on commit 2471287

Please sign in to comment.