[SPARC64]: Fix new context version SMP handling.
authorDavid S. Miller <davem@sunset.davemloft.net>
Tue, 7 Mar 2006 06:50:44 +0000 (22:50 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Mon, 20 Mar 2006 09:14:21 +0000 (01:14 -0800)
Don't piggy back the SMP receive signal code to do the
context version change handling.

Instead allocate another fixed PIL number for this
asynchronous cross-call.  We can't use smp_call_function()
because this thing is invoked with interrupts disabled
and a few spinlocks held.

Also, fix smp_call_function_mask() to count "cpus" correctly.
There is no guarentee that the local cpu is in the mask
yet that is exactly what this code was assuming.

Signed-off-by: David S. Miller <davem@davemloft.net>
arch/sparc64/kernel/devices.c
arch/sparc64/kernel/pci_psycho.c
arch/sparc64/kernel/pci_sabre.c
arch/sparc64/kernel/pci_schizo.c
arch/sparc64/kernel/pci_sun4v.c
arch/sparc64/kernel/sbus.c
arch/sparc64/kernel/smp.c
arch/sparc64/kernel/ttable.S
arch/sparc64/mm/ultra.S
include/asm-sparc64/pil.h

index 1341b99..007e892 100644 (file)
@@ -157,7 +157,7 @@ unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node)
                return 0;
        }
 
-       return sun4v_build_irq(sun4v_vdev_devhandle, irq, 4, 0);
+       return sun4v_build_irq(sun4v_vdev_devhandle, irq, 5, 0);
 }
 
 static const char *cpu_mid_prop(void)
index f7b16e4..d17878b 100644 (file)
@@ -286,17 +286,17 @@ static unsigned char psycho_pil_table[] = {
 /*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*/4,             /* SCSI                         */
+/*0x20*/5,             /* SCSI                         */
 /*0x21*/5,             /* Ethernet                     */
 /*0x22*/8,             /* Parallel Port                */
 /*0x23*/13,            /* Audio Record                 */
 /*0x24*/14,            /* Audio Playback               */
 /*0x25*/15,            /* PowerFail                    */
-/*0x26*/4,             /* second SCSI                  */
+/*0x26*/5,             /* second SCSI                  */
 /*0x27*/11,            /* Floppy                       */
-/*0x28*/4,             /* Spare Hardware               */
+/*0x28*/5,             /* Spare Hardware               */
 /*0x29*/9,             /* Keyboard                     */
-/*0x2a*/4,             /* Mouse                        */
+/*0x2a*/5,             /* Mouse                        */
 /*0x2b*/12,            /* Serial                       */
 /*0x2c*/10,            /* Timer 0                      */
 /*0x2d*/11,            /* Timer 1                      */
@@ -313,11 +313,11 @@ static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
 
        ret = psycho_pil_table[ino];
        if (ret == 0 && pdev == NULL) {
-               ret = 4;
+               ret = 5;
        } else if (ret == 0) {
                switch ((pdev->class >> 16) & 0xff) {
                case PCI_BASE_CLASS_STORAGE:
-                       ret = 4;
+                       ret = 5;
                        break;
 
                case PCI_BASE_CLASS_NETWORK:
@@ -336,7 +336,7 @@ static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
                        break;
 
                default:
-                       ret = 4;
+                       ret = 5;
                        break;
                };
        }
index 5ddc929..f67bb7f 100644 (file)
@@ -533,17 +533,17 @@ static unsigned char sabre_pil_table[] = {
 /*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*/4,             /* SCSI                         */
+/*0x20*/5,             /* SCSI                         */
 /*0x21*/5,             /* Ethernet                     */
 /*0x22*/8,             /* Parallel Port                */
 /*0x23*/13,            /* Audio Record                 */
 /*0x24*/14,            /* Audio Playback               */
 /*0x25*/15,            /* PowerFail                    */
-/*0x26*/4,             /* second SCSI                  */
+/*0x26*/5,             /* second SCSI                  */
 /*0x27*/11,            /* Floppy                       */
-/*0x28*/4,             /* Spare Hardware               */
+/*0x28*/5,             /* Spare Hardware               */
 /*0x29*/9,             /* Keyboard                     */
-/*0x2a*/4,             /* Mouse                        */
+/*0x2a*/5,             /* Mouse                        */
 /*0x2b*/12,            /* Serial                       */
 /*0x2c*/10,            /* Timer 0                      */
 /*0x2d*/11,            /* Timer 1                      */
@@ -565,11 +565,11 @@ static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
 
        ret = sabre_pil_table[ino];
        if (ret == 0 && pdev == NULL) {
-               ret = 4;
+               ret = 5;
        } else if (ret == 0) {
                switch ((pdev->class >> 16) & 0xff) {
                case PCI_BASE_CLASS_STORAGE:
-                       ret = 4;
+                       ret = 5;
                        break;
 
                case PCI_BASE_CLASS_NETWORK:
@@ -588,7 +588,7 @@ static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
                        break;
 
                default:
-                       ret = 4;
+                       ret = 5;
                        break;
                };
        }
index 3a89f29..7fe4de0 100644 (file)
@@ -243,8 +243,8 @@ static unsigned char schizo_pil_table[] = {
 /*0x0c*/0, 0, 0, 0,    /* PCI slot 3  Int A, B, C, D   */
 /*0x10*/0, 0, 0, 0,    /* PCI slot 4  Int A, B, C, D   */
 /*0x14*/0, 0, 0, 0,    /* PCI slot 5  Int A, B, C, D   */
-/*0x18*/4,             /* SCSI                         */
-/*0x19*/4,             /* second SCSI                  */
+/*0x18*/5,             /* SCSI                         */
+/*0x19*/5,             /* second SCSI                  */
 /*0x1a*/0,             /* UNKNOWN                      */
 /*0x1b*/0,             /* UNKNOWN                      */
 /*0x1c*/8,             /* Parallel                     */
@@ -254,7 +254,7 @@ static unsigned char schizo_pil_table[] = {
 /*0x20*/13,            /* Audio Record                 */
 /*0x21*/14,            /* Audio Playback               */
 /*0x22*/12,            /* Serial                       */
-/*0x23*/4,             /* EBUS I2C                     */
+/*0x23*/5,             /* EBUS I2C                     */
 /*0x24*/10,            /* RTC Clock                    */
 /*0x25*/11,            /* Floppy                       */
 /*0x26*/0,             /* UNKNOWN                      */
@@ -296,11 +296,11 @@ static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
 
        ret = schizo_pil_table[ino];
        if (ret == 0 && pdev == NULL) {
-               ret = 4;
+               ret = 5;
        } else if (ret == 0) {
                switch ((pdev->class >> 16) & 0xff) {
                case PCI_BASE_CLASS_STORAGE:
-                       ret = 4;
+                       ret = 5;
                        break;
 
                case PCI_BASE_CLASS_NETWORK:
@@ -319,7 +319,7 @@ static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
                        break;
 
                default:
-                       ret = 4;
+                       ret = 5;
                        break;
                };
        }
index a9c44c0..9372d4f 100644 (file)
@@ -735,11 +735,11 @@ static unsigned int pci_sun4v_irq_build(struct pci_pbm_info *pbm,
        u32 devhandle = pbm->devhandle;
        int pil;
 
-       pil = 4;
+       pil = 5;
        if (pdev) {
                switch ((pdev->class >> 16) & 0xff) {
                case PCI_BASE_CLASS_STORAGE:
-                       pil = 4;
+                       pil = 5;
                        break;
 
                case PCI_BASE_CLASS_NETWORK:
@@ -758,7 +758,7 @@ static unsigned int pci_sun4v_irq_build(struct pci_pbm_info *pbm,
                        break;
 
                default:
-                       pil = 4;
+                       pil = 5;
                        break;
                };
        }
index d95a1bc..1d6ffde 100644 (file)
@@ -693,11 +693,11 @@ void sbus_set_sbus64(struct sbus_dev *sdev, int bursts)
 
 /* SBUS SYSIO INO number to Sparc PIL level. */
 static unsigned char sysio_ino_to_pil[] = {
-       0, 4, 4, 7, 5, 7, 8, 9,         /* SBUS slot 0 */
-       0, 4, 4, 7, 5, 7, 8, 9,         /* SBUS slot 1 */
-       0, 4, 4, 7, 5, 7, 8, 9,         /* SBUS slot 2 */
-       0, 4, 4, 7, 5, 7, 8, 9,         /* SBUS slot 3 */
-       4, /* Onboard SCSI */
+       0, 5, 5, 7, 5, 7, 8, 9,         /* SBUS slot 0 */
+       0, 5, 5, 7, 5, 7, 8, 9,         /* SBUS slot 1 */
+       0, 5, 5, 7, 5, 7, 8, 9,         /* SBUS slot 2 */
+       0, 5, 5, 7, 5, 7, 8, 9,         /* SBUS slot 3 */
+       5, /* Onboard SCSI */
        5, /* Onboard Ethernet */
 /*XXX*/        8, /* Onboard BPP */
        0, /* Bogon */
index c4548a8..cf56128 100644 (file)
@@ -760,12 +760,9 @@ static int smp_call_function_mask(void (*func)(void *info), void *info,
                                  int nonatomic, int wait, cpumask_t mask)
 {
        struct call_data_struct data;
-       int cpus = cpus_weight(mask) - 1;
+       int cpus;
        long timeout;
 
-       if (!cpus)
-               return 0;
-
        /* Can deadlock when called with interrupts disabled */
        WARN_ON(irqs_disabled());
 
@@ -776,6 +773,11 @@ static int smp_call_function_mask(void (*func)(void *info), void *info,
 
        spin_lock(&call_lock);
 
+       cpu_clear(smp_processor_id(), mask);
+       cpus = cpus_weight(mask);
+       if (!cpus)
+               goto out_unlock;
+
        call_data = &data;
 
        smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask);
@@ -792,6 +794,7 @@ static int smp_call_function_mask(void (*func)(void *info), void *info,
                udelay(1);
        }
 
+out_unlock:
        spin_unlock(&call_lock);
 
        return 0;
@@ -845,6 +848,7 @@ extern unsigned long xcall_flush_tlb_pending;
 extern unsigned long xcall_flush_tlb_kernel_range;
 extern unsigned long xcall_report_regs;
 extern unsigned long xcall_receive_signal;
+extern unsigned long xcall_new_mmu_context_version;
 
 #ifdef DCACHE_ALIASING_POSSIBLE
 extern unsigned long xcall_flush_dcache_page_cheetah;
@@ -973,8 +977,14 @@ void smp_receive_signal(int cpu)
 }
 
 void smp_receive_signal_client(int irq, struct pt_regs *regs)
+{
+       clear_softint(1 << irq);
+}
+
+void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
 {
        struct mm_struct *mm;
+       unsigned long flags;
 
        clear_softint(1 << irq);
 
@@ -982,25 +992,24 @@ void smp_receive_signal_client(int irq, struct pt_regs *regs)
         * the version of the one we are using is now out of date.
         */
        mm = current->active_mm;
-       if (likely(mm)) {
-               unsigned long flags;
+       if (unlikely(!mm || (mm == &init_mm)))
+               return;
 
-               spin_lock_irqsave(&mm->context.lock, flags);
+       spin_lock_irqsave(&mm->context.lock, flags);
 
-               if (unlikely(!CTX_VALID(mm->context)))
-                       get_new_mmu_context(mm);
+       if (unlikely(!CTX_VALID(mm->context)))
+               get_new_mmu_context(mm);
 
-               load_secondary_context(mm);
-               __flush_tlb_mm(CTX_HWBITS(mm->context),
-                              SECONDARY_CONTEXT);
+       spin_unlock_irqrestore(&mm->context.lock, flags);
 
-               spin_unlock_irqrestore(&mm->context.lock, flags);
-       }
+       load_secondary_context(mm);
+       __flush_tlb_mm(CTX_HWBITS(mm->context),
+                      SECONDARY_CONTEXT);
 }
 
 void smp_new_mmu_context_version(void)
 {
-       __smp_receive_signal_mask(cpu_online_map);
+       smp_cross_call(&xcall_new_mmu_context_version, 0, 0, 0);
 }
 
 void smp_report_regs(void)
index d5a8dd5..5d90151 100644 (file)
@@ -51,12 +51,13 @@ tl0_resv03e:        BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40)
 tl0_irq1:      TRAP_IRQ(smp_call_function_client, 1)
 tl0_irq2:      TRAP_IRQ(smp_receive_signal_client, 2)
 tl0_irq3:      TRAP_IRQ(smp_penguin_jailcell, 3)
+tl0_irq4:      TRAP_IRQ(smp_new_mmu_context_version_client, 4)
 #else
 tl0_irq1:      BTRAP(0x41)
 tl0_irq2:      BTRAP(0x42)
 tl0_irq3:      BTRAP(0x43)
+tl0_irq4:      BTRAP(0x44)
 #endif
-tl0_irq4:      TRAP_IRQ(handler_irq, 4)
 tl0_irq5:      TRAP_IRQ(handler_irq, 5)  TRAP_IRQ(handler_irq, 6)
 tl0_irq7:      TRAP_IRQ(handler_irq, 7)  TRAP_IRQ(handler_irq, 8)
 tl0_irq9:      TRAP_IRQ(handler_irq, 9)  TRAP_IRQ(handler_irq, 10)
index bd8b0b4..f8479fa 100644 (file)
@@ -673,6 +673,11 @@ xcall_capture:
        wr              %g0, (1 << PIL_SMP_CAPTURE), %set_softint
        retry
 
+       .globl          xcall_new_mmu_context_version
+xcall_new_mmu_context_version:
+       wr              %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint
+       retry
+
 #endif /* CONFIG_SMP */
 
 
index 8f87750..79f827e 100644 (file)
 #define PIL_SMP_CALL_FUNC      1
 #define PIL_SMP_RECEIVE_SIGNAL 2
 #define PIL_SMP_CAPTURE                3
+#define PIL_SMP_CTX_NEW_VERSION        4
 
 #ifndef __ASSEMBLY__
 #define PIL_RESERVED(PIL)      ((PIL) == PIL_SMP_CALL_FUNC || \
                                 (PIL) == PIL_SMP_RECEIVE_SIGNAL || \
-                                (PIL) == PIL_SMP_CAPTURE)
+                                (PIL) == PIL_SMP_CAPTURE || \
+                                (PIL) == PIL_SMP_CTX_NEW_VERSION)
 #endif
 
 #endif /* !(_SPARC64_PIL_H) */