Skip to content

Commit

Permalink
[SPARC64]: Kill ino_bucket->pil
Browse files Browse the repository at this point in the history
And reuse that struct member for virt_irq, which will
be used in future changesets for the implementation of
mapping between real and virtual IRQ numbers.

This nicely kills off a ton of SBUS and PCI controller
PIL assignment code which is no longer necessary.

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jun 20, 2006
1 parent c6387a4 commit 37cdcd9
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 381 deletions.
2 changes: 1 addition & 1 deletion arch/sparc64/kernel/devices.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node)
return 0;
}

return sun4v_build_irq(sun4v_vdev_devhandle, irq, 5, 0);
return sun4v_build_irq(sun4v_vdev_devhandle, irq, 0);
}

static const char *cpu_mid_prop(void)
Expand Down
70 changes: 26 additions & 44 deletions arch/sparc64/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY
*/
#define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist)

static struct irqaction *irq_action[NR_IRQS+1];
static struct irqaction *irq_action[NR_IRQS];

/* This only synchronizes entities which modify IRQ handler
* state and some selected user-level spots that want to
Expand Down Expand Up @@ -116,12 +116,9 @@ int show_interrupts(struct seq_file *p, void *v)
kstat_cpu(j).irqs[i]);
}
#endif
seq_printf(p, " %s:%lx", action->name,
get_ino_in_irqaction(action));
for (action = action->next; action; action = action->next) {
seq_printf(p, ", %s:%lx", action->name,
get_ino_in_irqaction(action));
}
seq_printf(p, " %s", action->name);
for (action = action->next; action; action = action->next)
seq_printf(p, ", %s", action->name);
seq_putc(p, '\n');
}
out_unlock:
Expand Down Expand Up @@ -245,48 +242,47 @@ void disable_irq(unsigned int irq)
}
}

static void build_irq_error(const char *msg, unsigned int ino, int pil, int inofixup,
static void build_irq_error(const char *msg, unsigned int ino, int inofixup,
unsigned long iclr, unsigned long imap,
struct ino_bucket *bucket)
{
prom_printf("IRQ: INO %04x (%d:%016lx:%016lx) --> "
"(%d:%d:%016lx:%016lx), halting...\n",
ino, bucket->pil, bucket->iclr, bucket->imap,
pil, inofixup, iclr, imap);
prom_printf("IRQ: INO %04x (%016lx:%016lx) --> "
"(%d:%016lx:%016lx), halting...\n",
ino, bucket->iclr, bucket->imap,
inofixup, iclr, imap);
prom_halt();
}

unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long imap)
unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
{
struct ino_bucket *bucket;
int ino;

BUG_ON(pil == 0);
BUG_ON(tlb_type == hypervisor);

/* RULE: Both must be specified in all other cases. */
if (iclr == 0UL || imap == 0UL) {
prom_printf("Invalid build_irq %d %d %016lx %016lx\n",
pil, inofixup, iclr, imap);
prom_printf("Invalid build_irq %d %016lx %016lx\n",
inofixup, iclr, imap);
prom_halt();
}

ino = (upa_readl(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
if (ino > NUM_IVECS) {
prom_printf("Invalid INO %04x (%d:%d:%016lx:%016lx)\n",
ino, pil, inofixup, iclr, imap);
prom_printf("Invalid INO %04x (%d:%016lx:%016lx)\n",
ino, inofixup, iclr, imap);
prom_halt();
}

bucket = &ivector_table[ino];
if (bucket->flags & IBF_ACTIVE)
build_irq_error("IRQ: Trying to build active INO bucket.\n",
ino, pil, inofixup, iclr, imap, bucket);
ino, inofixup, iclr, imap, bucket);

if (bucket->irq_info) {
if (bucket->imap != imap || bucket->iclr != iclr)
build_irq_error("IRQ: Trying to reinit INO bucket.\n",
ino, pil, inofixup, iclr, imap, bucket);
ino, inofixup, iclr, imap, bucket);

goto out;
}
Expand All @@ -302,14 +298,13 @@ unsigned int build_irq(int pil, int inofixup, unsigned long iclr, unsigned long
*/
bucket->imap = imap;
bucket->iclr = iclr;
bucket->pil = pil;
bucket->flags = 0;

out:
return __irq(bucket);
}

unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsigned char flags)
unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, unsigned char flags)
{
struct ino_bucket *bucket;
unsigned long sysino;
Expand All @@ -328,7 +323,6 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino, int pil, unsign
bucket->imap = ~0UL - sysino;
bucket->iclr = ~0UL - sysino;

bucket->pil = pil;
bucket->flags = flags;

bucket->irq_info = kzalloc(sizeof(struct irq_desc), GFP_ATOMIC);
Expand Down Expand Up @@ -356,16 +350,12 @@ static void atomic_bucket_insert(struct ino_bucket *bucket)

static int check_irq_sharing(int pil, unsigned long irqflags)
{
struct irqaction *action, *tmp;
struct irqaction *action;

action = *(irq_action + pil);
if (action) {
if ((action->flags & SA_SHIRQ) && (irqflags & SA_SHIRQ)) {
for (tmp = action; tmp->next; tmp = tmp->next)
;
} else {
if (!(action->flags & SA_SHIRQ) || !(irqflags & SA_SHIRQ))
return -EBUSY;
}
}
return 0;
}
Expand Down Expand Up @@ -425,12 +415,12 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_
* installing a new handler, but is this really a problem,
* only the sysadmin is able to do this.
*/
rand_initialize_irq(irq);
rand_initialize_irq(PIL_DEVICE_IRQ);
}

spin_lock_irqsave(&irq_action_lock, flags);

if (check_irq_sharing(bucket->pil, irqflags)) {
if (check_irq_sharing(PIL_DEVICE_IRQ, irqflags)) {
spin_unlock_irqrestore(&irq_action_lock, flags);
return -EBUSY;
}
Expand All @@ -454,7 +444,7 @@ int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_
put_ino_in_irqaction(action, irq);
put_smpaff_in_irqaction(action, CPU_MASK_NONE);

append_irq_action(bucket->pil, action);
append_irq_action(PIL_DEVICE_IRQ, action);

enable_irq(irq);

Expand All @@ -478,16 +468,15 @@ EXPORT_SYMBOL(request_irq);

static struct irqaction *unlink_irq_action(unsigned int irq, void *dev_id)
{
struct ino_bucket *bucket = __bucket(irq);
struct irqaction *action, **pp;

pp = irq_action + bucket->pil;
pp = irq_action + PIL_DEVICE_IRQ;
action = *pp;
if (unlikely(!action))
return NULL;

if (unlikely(!action->handler)) {
printk("Freeing free IRQ %d\n", bucket->pil);
printk("Freeing free IRQ %d\n", PIL_DEVICE_IRQ);
return NULL;
}

Expand Down Expand Up @@ -648,7 +637,7 @@ static void process_bucket(struct ino_bucket *bp, struct pt_regs *regs)

/* Test and add entropy */
if (random & SA_SAMPLE_RANDOM)
add_interrupt_randomness(bp->pil);
add_interrupt_randomness(PIL_DEVICE_IRQ);
out:
bp->flags &= ~IBF_INPROGRESS;
}
Expand Down Expand Up @@ -691,7 +680,7 @@ void handler_irq(int irq, struct pt_regs *regs)
while (bp) {
struct ino_bucket *nbp = __bucket(bp->irq_chain);

kstat_this_cpu.irqs[bp->pil]++;
kstat_this_cpu.irqs[bp->virt_irq]++;

bp->irq_chain = 0;
process_bucket(bp, regs);
Expand Down Expand Up @@ -817,16 +806,9 @@ static void distribute_irqs(void)
spin_lock_irqsave(&irq_action_lock, flags);
cpu = 0;

/*
* Skip the timer at [0], and very rare error/power intrs at [15].
* Also level [12], it causes problems on Ex000 systems.
*/
for (level = 1; level < NR_IRQS; level++) {
struct irqaction *p = irq_action[level];

if (level == 12)
continue;

while(p) {
cpu = retarget_one_irq(p, cpu);
p = p->next;
Expand Down
77 changes: 2 additions & 75 deletions arch/sparc64/kernel/pci_psycho.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,82 +276,14 @@ static unsigned long __onboard_imap_off[] = {
((ino & 0x20) ? (PSYCHO_ICLR_SCSI + (((ino) & 0x1f) << 3)) : \
(PSYCHO_ICLR_A_SLOT0 + (((ino) & 0x1f)<<3)))

/* PCI PSYCHO INO number to Sparc PIL level. */
static unsigned char psycho_pil_table[] = {
/*0x00*/0, 0, 0, 0, /* PCI A slot 0 Int A, B, C, D */
/*0x04*/0, 0, 0, 0, /* PCI A slot 1 Int A, B, C, D */
/*0x08*/0, 0, 0, 0, /* PCI A slot 2 Int A, B, C, D */
/*0x0c*/0, 0, 0, 0, /* PCI A slot 3 Int A, B, C, D */
/*0x10*/0, 0, 0, 0, /* PCI B slot 0 Int A, B, C, D */
/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */
/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */
/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */
/*0x20*/5, /* SCSI */
/*0x21*/5, /* Ethernet */
/*0x22*/8, /* Parallel Port */
/*0x23*/13, /* Audio Record */
/*0x24*/14, /* Audio Playback */
/*0x25*/15, /* PowerFail */
/*0x26*/5, /* second SCSI */
/*0x27*/11, /* Floppy */
/*0x28*/5, /* Spare Hardware */
/*0x29*/9, /* Keyboard */
/*0x2a*/5, /* Mouse */
/*0x2b*/12, /* Serial */
/*0x2c*/10, /* Timer 0 */
/*0x2d*/11, /* Timer 1 */
/*0x2e*/15, /* Uncorrectable ECC */
/*0x2f*/15, /* Correctable ECC */
/*0x30*/15, /* PCI Bus A Error */
/*0x31*/15, /* PCI Bus B Error */
/*0x32*/15, /* Power Management */
};

static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
{
int ret;

ret = psycho_pil_table[ino];
if (ret == 0 && pdev == NULL) {
ret = 5;
} else if (ret == 0) {
switch ((pdev->class >> 16) & 0xff) {
case PCI_BASE_CLASS_STORAGE:
ret = 5;
break;

case PCI_BASE_CLASS_NETWORK:
ret = 6;
break;

case PCI_BASE_CLASS_DISPLAY:
ret = 9;
break;

case PCI_BASE_CLASS_MULTIMEDIA:
case PCI_BASE_CLASS_MEMORY:
case PCI_BASE_CLASS_BRIDGE:
case PCI_BASE_CLASS_SERIAL:
ret = 10;
break;

default:
ret = 5;
break;
};
}

return ret;
}

static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
struct pci_dev *pdev,
unsigned int ino)
{
struct ino_bucket *bucket;
unsigned long imap, iclr;
unsigned long imap_off, iclr_off;
int pil, inofixup = 0;
int inofixup = 0;

ino &= PCI_IRQ_INO;
if (ino < PSYCHO_ONBOARD_IRQ_BASE) {
Expand All @@ -367,11 +299,6 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
}

/* Now build the IRQ bucket. */
pil = psycho_ino_to_pil(pdev, ino);

if (PIL_RESERVED(pil))
BUG();

imap = pbm->controller_regs + imap_off;
imap += 4;

Expand All @@ -382,7 +309,7 @@ static unsigned int psycho_irq_build(struct pci_pbm_info *pbm,
if ((ino & 0x20) == 0)
inofixup = ino & 0x03;

bucket = __bucket(build_irq(pil, inofixup, iclr, imap));
bucket = __bucket(build_irq(inofixup, iclr, imap));
bucket->flags |= IBF_PCI;

return __irq(bucket);
Expand Down
Loading

0 comments on commit 37cdcd9

Please sign in to comment.