diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-07-20 05:58:28 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-20 20:14:55 -0400 |
commit | 93b3238ef8b04f1383b2aa7704487fb3c0e44193 (patch) | |
tree | 5ed0bf1f712655591e625da70cebfca50c308ed1 | |
parent | e83fb17f9ba6ea0c64d084cca0c557d7e7dc9693 (diff) |
[SPARC64]: Fix virq decomposition.
The dev_handle and dev_ino fields don't match up exactly to
the traditional IMAP_IGN and IMAP_INO masks.
So store them away in a table and look them up directly.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | arch/sparc64/kernel/irq.c | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index edd530fb4e37..db31bf6b42db 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c | |||
@@ -87,7 +87,11 @@ struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BY | |||
87 | */ | 87 | */ |
88 | #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) | 88 | #define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) |
89 | 89 | ||
90 | static unsigned int virt_to_real_irq_table[NR_IRQS]; | 90 | static struct { |
91 | unsigned int irq; | ||
92 | unsigned int dev_handle; | ||
93 | unsigned int dev_ino; | ||
94 | } virt_to_real_irq_table[NR_IRQS]; | ||
91 | 95 | ||
92 | static unsigned char virt_irq_alloc(unsigned int real_irq) | 96 | static unsigned char virt_irq_alloc(unsigned int real_irq) |
93 | { | 97 | { |
@@ -96,7 +100,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq) | |||
96 | BUILD_BUG_ON(NR_IRQS >= 256); | 100 | BUILD_BUG_ON(NR_IRQS >= 256); |
97 | 101 | ||
98 | for (ent = 1; ent < NR_IRQS; ent++) { | 102 | for (ent = 1; ent < NR_IRQS; ent++) { |
99 | if (!virt_to_real_irq_table[ent]) | 103 | if (!virt_to_real_irq_table[ent].irq) |
100 | break; | 104 | break; |
101 | } | 105 | } |
102 | if (ent >= NR_IRQS) { | 106 | if (ent >= NR_IRQS) { |
@@ -104,7 +108,7 @@ static unsigned char virt_irq_alloc(unsigned int real_irq) | |||
104 | return 0; | 108 | return 0; |
105 | } | 109 | } |
106 | 110 | ||
107 | virt_to_real_irq_table[ent] = real_irq; | 111 | virt_to_real_irq_table[ent].irq = real_irq; |
108 | 112 | ||
109 | return ent; | 113 | return ent; |
110 | } | 114 | } |
@@ -117,8 +121,8 @@ static void virt_irq_free(unsigned int virt_irq) | |||
117 | if (virt_irq >= NR_IRQS) | 121 | if (virt_irq >= NR_IRQS) |
118 | return; | 122 | return; |
119 | 123 | ||
120 | real_irq = virt_to_real_irq_table[virt_irq]; | 124 | real_irq = virt_to_real_irq_table[virt_irq].irq; |
121 | virt_to_real_irq_table[virt_irq] = 0; | 125 | virt_to_real_irq_table[virt_irq].irq = 0; |
122 | 126 | ||
123 | __bucket(real_irq)->virt_irq = 0; | 127 | __bucket(real_irq)->virt_irq = 0; |
124 | } | 128 | } |
@@ -126,7 +130,7 @@ static void virt_irq_free(unsigned int virt_irq) | |||
126 | 130 | ||
127 | static unsigned int virt_to_real_irq(unsigned char virt_irq) | 131 | static unsigned int virt_to_real_irq(unsigned char virt_irq) |
128 | { | 132 | { |
129 | return virt_to_real_irq_table[virt_irq]; | 133 | return virt_to_real_irq_table[virt_irq].irq; |
130 | } | 134 | } |
131 | 135 | ||
132 | /* | 136 | /* |
@@ -418,7 +422,6 @@ static void sun4v_irq_end(unsigned int virt_irq) | |||
418 | static void sun4v_virq_enable(unsigned int virt_irq) | 422 | static void sun4v_virq_enable(unsigned int virt_irq) |
419 | { | 423 | { |
420 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 424 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
421 | unsigned int ino = bucket - &ivector_table[0]; | ||
422 | 425 | ||
423 | if (likely(bucket)) { | 426 | if (likely(bucket)) { |
424 | unsigned long cpuid, dev_handle, dev_ino; | 427 | unsigned long cpuid, dev_handle, dev_ino; |
@@ -426,8 +429,8 @@ static void sun4v_virq_enable(unsigned int virt_irq) | |||
426 | 429 | ||
427 | cpuid = irq_choose_cpu(virt_irq); | 430 | cpuid = irq_choose_cpu(virt_irq); |
428 | 431 | ||
429 | dev_handle = ino & IMAP_IGN; | 432 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
430 | dev_ino = ino & IMAP_INO; | 433 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
431 | 434 | ||
432 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); | 435 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); |
433 | if (err != HV_EOK) | 436 | if (err != HV_EOK) |
@@ -452,7 +455,6 @@ static void sun4v_virq_enable(unsigned int virt_irq) | |||
452 | static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) | 455 | static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) |
453 | { | 456 | { |
454 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 457 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
455 | unsigned int ino = bucket - &ivector_table[0]; | ||
456 | 458 | ||
457 | if (likely(bucket)) { | 459 | if (likely(bucket)) { |
458 | unsigned long cpuid, dev_handle, dev_ino; | 460 | unsigned long cpuid, dev_handle, dev_ino; |
@@ -460,8 +462,8 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) | |||
460 | 462 | ||
461 | cpuid = irq_choose_cpu(virt_irq); | 463 | cpuid = irq_choose_cpu(virt_irq); |
462 | 464 | ||
463 | dev_handle = ino & IMAP_IGN; | 465 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
464 | dev_ino = ino & IMAP_INO; | 466 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
465 | 467 | ||
466 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); | 468 | err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); |
467 | if (err != HV_EOK) | 469 | if (err != HV_EOK) |
@@ -474,14 +476,13 @@ static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) | |||
474 | static void sun4v_virq_disable(unsigned int virt_irq) | 476 | static void sun4v_virq_disable(unsigned int virt_irq) |
475 | { | 477 | { |
476 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 478 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
477 | unsigned int ino = bucket - &ivector_table[0]; | ||
478 | 479 | ||
479 | if (likely(bucket)) { | 480 | if (likely(bucket)) { |
480 | unsigned long dev_handle, dev_ino; | 481 | unsigned long dev_handle, dev_ino; |
481 | int err; | 482 | int err; |
482 | 483 | ||
483 | dev_handle = ino & IMAP_IGN; | 484 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
484 | dev_ino = ino & IMAP_INO; | 485 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
485 | 486 | ||
486 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, | 487 | err = sun4v_vintr_set_valid(dev_handle, dev_ino, |
487 | HV_INTR_DISABLED); | 488 | HV_INTR_DISABLED); |
@@ -495,7 +496,6 @@ static void sun4v_virq_disable(unsigned int virt_irq) | |||
495 | static void sun4v_virq_end(unsigned int virt_irq) | 496 | static void sun4v_virq_end(unsigned int virt_irq) |
496 | { | 497 | { |
497 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); | 498 | struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); |
498 | unsigned int ino = bucket - &ivector_table[0]; | ||
499 | struct irq_desc *desc = irq_desc + virt_irq; | 499 | struct irq_desc *desc = irq_desc + virt_irq; |
500 | 500 | ||
501 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) | 501 | if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
@@ -505,8 +505,8 @@ static void sun4v_virq_end(unsigned int virt_irq) | |||
505 | unsigned long dev_handle, dev_ino; | 505 | unsigned long dev_handle, dev_ino; |
506 | int err; | 506 | int err; |
507 | 507 | ||
508 | dev_handle = ino & IMAP_IGN; | 508 | dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; |
509 | dev_ino = ino & IMAP_INO; | 509 | dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; |
510 | 510 | ||
511 | err = sun4v_vintr_set_state(dev_handle, dev_ino, | 511 | err = sun4v_vintr_set_state(dev_handle, dev_ino, |
512 | HV_INTR_STATE_IDLE); | 512 | HV_INTR_STATE_IDLE); |
@@ -700,6 +700,7 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) | |||
700 | unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | 700 | unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) |
701 | { | 701 | { |
702 | unsigned long sysino, hv_err; | 702 | unsigned long sysino, hv_err; |
703 | unsigned int virq; | ||
703 | 704 | ||
704 | BUG_ON(devhandle & devino); | 705 | BUG_ON(devhandle & devino); |
705 | 706 | ||
@@ -713,7 +714,12 @@ unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) | |||
713 | prom_halt(); | 714 | prom_halt(); |
714 | } | 715 | } |
715 | 716 | ||
716 | return sun4v_build_common(sysino, &sun4v_virq); | 717 | virq = sun4v_build_common(sysino, &sun4v_virq); |
718 | |||
719 | virt_to_real_irq_table[virq].dev_handle = devhandle; | ||
720 | virt_to_real_irq_table[virq].dev_ino = devino; | ||
721 | |||
722 | return virq; | ||
717 | } | 723 | } |
718 | 724 | ||
719 | #ifdef CONFIG_PCI_MSI | 725 | #ifdef CONFIG_PCI_MSI |