aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-07-20 05:58:28 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-20 20:14:55 -0400
commit93b3238ef8b04f1383b2aa7704487fb3c0e44193 (patch)
tree5ed0bf1f712655591e625da70cebfca50c308ed1 /arch
parente83fb17f9ba6ea0c64d084cca0c557d7e7dc9693 (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>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/irq.c44
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
90static unsigned int virt_to_real_irq_table[NR_IRQS]; 90static 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
92static unsigned char virt_irq_alloc(unsigned int real_irq) 96static 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
127static unsigned int virt_to_real_irq(unsigned char virt_irq) 131static 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)
418static void sun4v_virq_enable(unsigned int virt_irq) 422static 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)
452static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) 455static 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)
474static void sun4v_virq_disable(unsigned int virt_irq) 476static 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)
495static void sun4v_virq_end(unsigned int virt_irq) 496static 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)
700unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) 700unsigned 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