[SPARC64]: Fix new context version SMP handling.
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>
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c
index 1341b99..007e892 100644
--- a/arch/sparc64/kernel/devices.c
+++ b/arch/sparc64/kernel/devices.c
@@ -157,7 +157,7 @@
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)
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index f7b16e4..d17878b 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -286,17 +286,17 @@
/*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 @@
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 @@
break;
default:
- ret = 4;
+ ret = 5;
break;
};
}
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 5ddc929..f67bb7f 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -533,17 +533,17 @@
/*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 @@
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 @@
break;
default:
- ret = 4;
+ ret = 5;
break;
};
}
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index 3a89f29..7fe4de0 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -243,8 +243,8 @@
/*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 @@
/*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 @@
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 @@
break;
default:
- ret = 4;
+ ret = 5;
break;
};
}
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index a9c44c0..9372d4f 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -735,11 +735,11 @@
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 @@
break;
default:
- pil = 4;
+ pil = 5;
break;
};
}
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index d95a1bc..1d6ffde 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -693,11 +693,11 @@
/* 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 */
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index c4548a8..cf56128 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -760,12 +760,9 @@
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 @@
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 @@
udelay(1);
}
+out_unlock:
spin_unlock(&call_lock);
return 0;
@@ -845,6 +848,7 @@
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;
@@ -974,7 +978,13 @@
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 @@
* 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)
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index d5a8dd5..5d90151 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -51,12 +51,13 @@
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)
diff --git a/arch/sparc64/mm/ultra.S b/arch/sparc64/mm/ultra.S
index bd8b0b4..f8479fa 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -673,6 +673,11 @@
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 */
diff --git a/include/asm-sparc64/pil.h b/include/asm-sparc64/pil.h
index 8f87750..79f827e 100644
--- a/include/asm-sparc64/pil.h
+++ b/include/asm-sparc64/pil.h
@@ -16,11 +16,13 @@
#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) */