Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=b80e6998120eecec00781658bc43702494117ea8
Commit:     b80e6998120eecec00781658bc43702494117ea8
Parent:     10397e4069bbcc8219537e7c1e0d6a6935432156
Author:     David S. Miller <[EMAIL PROTECTED]>
AuthorDate: Sat Oct 13 21:51:37 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Sat Oct 13 21:53:16 2007 -0700

    [SPARC64]: Use sun4v VIRQ interfaces as intended.
    
    We were simply concatenating the devhandle and devino and using that
    as the cookie, which defeats the entire purpose of the VIRQ hypervisor
    interfaces.
    
    Now that we use physical addresses for the INO buckets, we can
    allocate them dynamically for VIRQs and encode the cookies as
    ~__pa(bucket).  This allows us to test for and decode the cookie with
    a simple:
    
        brlz    $reg1, 1f
         xnor   $reg1, %g0, $reg2
    
    sequence.
    
    This works because bit 64 is never set in traditional
    INO vectors, and it is also never set in a physical
    address.  So xnor'ing the physical address of the bucket
    always gives us a negative number, and thus a unique
    condition we can test cheaply.
    
    Inspired by ideas from Greg Onufer.
    
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 arch/sparc64/kernel/irq.c        |   37 ++++++++++++++++++++++++++-----------
 arch/sparc64/kernel/sun4v_ivec.S |    6 +++++-
 2 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 5a92851..4e9537c 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -643,27 +643,42 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int 
devino)
 
 unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
 {
-       unsigned long sysino, hv_err;
-       unsigned int virq;
+       struct irq_handler_data *data;
+       struct ino_bucket *bucket;
+       unsigned long hv_err, cookie;
+
+       bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
+       if (unlikely(!bucket))
+               return 0;
+
+       bucket->virt_irq = virt_irq_alloc(__irq(bucket));
+       set_irq_chip(bucket->virt_irq, &sun4v_virq);
 
-       BUG_ON(devhandle & devino);
+       data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+       if (unlikely(!data))
+               return 0;
 
-       sysino = devhandle | devino;
-       BUG_ON(sysino & ~(IMAP_IGN | IMAP_INO));
+       set_irq_chip_data(bucket->virt_irq, data);
 
-       hv_err = sun4v_vintr_set_cookie(devhandle, devino, sysino);
+       /* Catch accidental accesses to these things.  IMAP/ICLR handling
+        * is done by hypervisor calls on sun4v platforms, not by direct
+        * register accesses.
+        */
+       data->imap = ~0UL;
+       data->iclr = ~0UL;
+
+       cookie = ~__pa(bucket);
+       hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie);
        if (hv_err) {
                prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] "
                            "err=%lu\n", devhandle, devino, hv_err);
                prom_halt();
        }
 
-       virq = sun4v_build_common(sysino, &sun4v_virq);
-
-       virt_to_real_irq_table[virq].dev_handle = devhandle;
-       virt_to_real_irq_table[virq].dev_ino = devino;
+       virt_to_real_irq_table[bucket->virt_irq].dev_handle = devhandle;
+       virt_to_real_irq_table[bucket->virt_irq].dev_ino = devino;
 
-       return virq;
+       return bucket->virt_irq;
 }
 
 void ack_bad_irq(unsigned int virt_irq)
diff --git a/arch/sparc64/kernel/sun4v_ivec.S b/arch/sparc64/kernel/sun4v_ivec.S
index 16d3064..e2f8e1b 100644
--- a/arch/sparc64/kernel/sun4v_ivec.S
+++ b/arch/sparc64/kernel/sun4v_ivec.S
@@ -98,13 +98,17 @@ sun4v_dev_mondo:
 
        TRAP_LOAD_IRQ_WORK_PA(%g1, %g4)
 
+       /* For VIRQs, cookie is encoded as ~bucket_phys_addr  */
+       brlz,pt %g3, 1f
+        xnor   %g3, %g0, %g4
+
        /* Get __pa(&ivector_table[IVEC]) into %g4.  */
        sethi   %hi(ivector_table_pa), %g4
        ldx     [%g4 + %lo(ivector_table_pa)], %g4
        sllx    %g3, 4, %g3
        add     %g4, %g3, %g4
 
-       ldx     [%g1], %g2
+1:     ldx     [%g1], %g2
        stxa    %g2, [%g4] ASI_PHYS_USE_EC
        stx     %g4, [%g1]
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to