[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>
This commit is contained in:
parent
a77754b4d0
commit
ee29074d3b
|
@ -157,7 +157,7 @@ unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node)
|
||||||
return 0;
|
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)
|
static const char *cpu_mid_prop(void)
|
||||||
|
|
|
@ -286,17 +286,17 @@ static unsigned char psycho_pil_table[] = {
|
||||||
/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */
|
/*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 */
|
/*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 */
|
/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */
|
||||||
/*0x20*/4, /* SCSI */
|
/*0x20*/5, /* SCSI */
|
||||||
/*0x21*/5, /* Ethernet */
|
/*0x21*/5, /* Ethernet */
|
||||||
/*0x22*/8, /* Parallel Port */
|
/*0x22*/8, /* Parallel Port */
|
||||||
/*0x23*/13, /* Audio Record */
|
/*0x23*/13, /* Audio Record */
|
||||||
/*0x24*/14, /* Audio Playback */
|
/*0x24*/14, /* Audio Playback */
|
||||||
/*0x25*/15, /* PowerFail */
|
/*0x25*/15, /* PowerFail */
|
||||||
/*0x26*/4, /* second SCSI */
|
/*0x26*/5, /* second SCSI */
|
||||||
/*0x27*/11, /* Floppy */
|
/*0x27*/11, /* Floppy */
|
||||||
/*0x28*/4, /* Spare Hardware */
|
/*0x28*/5, /* Spare Hardware */
|
||||||
/*0x29*/9, /* Keyboard */
|
/*0x29*/9, /* Keyboard */
|
||||||
/*0x2a*/4, /* Mouse */
|
/*0x2a*/5, /* Mouse */
|
||||||
/*0x2b*/12, /* Serial */
|
/*0x2b*/12, /* Serial */
|
||||||
/*0x2c*/10, /* Timer 0 */
|
/*0x2c*/10, /* Timer 0 */
|
||||||
/*0x2d*/11, /* Timer 1 */
|
/*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];
|
ret = psycho_pil_table[ino];
|
||||||
if (ret == 0 && pdev == NULL) {
|
if (ret == 0 && pdev == NULL) {
|
||||||
ret = 4;
|
ret = 5;
|
||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
switch ((pdev->class >> 16) & 0xff) {
|
switch ((pdev->class >> 16) & 0xff) {
|
||||||
case PCI_BASE_CLASS_STORAGE:
|
case PCI_BASE_CLASS_STORAGE:
|
||||||
ret = 4;
|
ret = 5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCI_BASE_CLASS_NETWORK:
|
case PCI_BASE_CLASS_NETWORK:
|
||||||
|
@ -336,7 +336,7 @@ static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ret = 4;
|
ret = 5;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -533,17 +533,17 @@ static unsigned char sabre_pil_table[] = {
|
||||||
/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */
|
/*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 */
|
/*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 */
|
/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */
|
||||||
/*0x20*/4, /* SCSI */
|
/*0x20*/5, /* SCSI */
|
||||||
/*0x21*/5, /* Ethernet */
|
/*0x21*/5, /* Ethernet */
|
||||||
/*0x22*/8, /* Parallel Port */
|
/*0x22*/8, /* Parallel Port */
|
||||||
/*0x23*/13, /* Audio Record */
|
/*0x23*/13, /* Audio Record */
|
||||||
/*0x24*/14, /* Audio Playback */
|
/*0x24*/14, /* Audio Playback */
|
||||||
/*0x25*/15, /* PowerFail */
|
/*0x25*/15, /* PowerFail */
|
||||||
/*0x26*/4, /* second SCSI */
|
/*0x26*/5, /* second SCSI */
|
||||||
/*0x27*/11, /* Floppy */
|
/*0x27*/11, /* Floppy */
|
||||||
/*0x28*/4, /* Spare Hardware */
|
/*0x28*/5, /* Spare Hardware */
|
||||||
/*0x29*/9, /* Keyboard */
|
/*0x29*/9, /* Keyboard */
|
||||||
/*0x2a*/4, /* Mouse */
|
/*0x2a*/5, /* Mouse */
|
||||||
/*0x2b*/12, /* Serial */
|
/*0x2b*/12, /* Serial */
|
||||||
/*0x2c*/10, /* Timer 0 */
|
/*0x2c*/10, /* Timer 0 */
|
||||||
/*0x2d*/11, /* Timer 1 */
|
/*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];
|
ret = sabre_pil_table[ino];
|
||||||
if (ret == 0 && pdev == NULL) {
|
if (ret == 0 && pdev == NULL) {
|
||||||
ret = 4;
|
ret = 5;
|
||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
switch ((pdev->class >> 16) & 0xff) {
|
switch ((pdev->class >> 16) & 0xff) {
|
||||||
case PCI_BASE_CLASS_STORAGE:
|
case PCI_BASE_CLASS_STORAGE:
|
||||||
ret = 4;
|
ret = 5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCI_BASE_CLASS_NETWORK:
|
case PCI_BASE_CLASS_NETWORK:
|
||||||
|
@ -588,7 +588,7 @@ static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ret = 4;
|
ret = 5;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -243,8 +243,8 @@ static unsigned char schizo_pil_table[] = {
|
||||||
/*0x0c*/0, 0, 0, 0, /* PCI slot 3 Int A, B, C, D */
|
/*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 */
|
/*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 */
|
/*0x14*/0, 0, 0, 0, /* PCI slot 5 Int A, B, C, D */
|
||||||
/*0x18*/4, /* SCSI */
|
/*0x18*/5, /* SCSI */
|
||||||
/*0x19*/4, /* second SCSI */
|
/*0x19*/5, /* second SCSI */
|
||||||
/*0x1a*/0, /* UNKNOWN */
|
/*0x1a*/0, /* UNKNOWN */
|
||||||
/*0x1b*/0, /* UNKNOWN */
|
/*0x1b*/0, /* UNKNOWN */
|
||||||
/*0x1c*/8, /* Parallel */
|
/*0x1c*/8, /* Parallel */
|
||||||
|
@ -254,7 +254,7 @@ static unsigned char schizo_pil_table[] = {
|
||||||
/*0x20*/13, /* Audio Record */
|
/*0x20*/13, /* Audio Record */
|
||||||
/*0x21*/14, /* Audio Playback */
|
/*0x21*/14, /* Audio Playback */
|
||||||
/*0x22*/12, /* Serial */
|
/*0x22*/12, /* Serial */
|
||||||
/*0x23*/4, /* EBUS I2C */
|
/*0x23*/5, /* EBUS I2C */
|
||||||
/*0x24*/10, /* RTC Clock */
|
/*0x24*/10, /* RTC Clock */
|
||||||
/*0x25*/11, /* Floppy */
|
/*0x25*/11, /* Floppy */
|
||||||
/*0x26*/0, /* UNKNOWN */
|
/*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];
|
ret = schizo_pil_table[ino];
|
||||||
if (ret == 0 && pdev == NULL) {
|
if (ret == 0 && pdev == NULL) {
|
||||||
ret = 4;
|
ret = 5;
|
||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
switch ((pdev->class >> 16) & 0xff) {
|
switch ((pdev->class >> 16) & 0xff) {
|
||||||
case PCI_BASE_CLASS_STORAGE:
|
case PCI_BASE_CLASS_STORAGE:
|
||||||
ret = 4;
|
ret = 5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCI_BASE_CLASS_NETWORK:
|
case PCI_BASE_CLASS_NETWORK:
|
||||||
|
@ -319,7 +319,7 @@ static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ret = 4;
|
ret = 5;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -735,11 +735,11 @@ static unsigned int pci_sun4v_irq_build(struct pci_pbm_info *pbm,
|
||||||
u32 devhandle = pbm->devhandle;
|
u32 devhandle = pbm->devhandle;
|
||||||
int pil;
|
int pil;
|
||||||
|
|
||||||
pil = 4;
|
pil = 5;
|
||||||
if (pdev) {
|
if (pdev) {
|
||||||
switch ((pdev->class >> 16) & 0xff) {
|
switch ((pdev->class >> 16) & 0xff) {
|
||||||
case PCI_BASE_CLASS_STORAGE:
|
case PCI_BASE_CLASS_STORAGE:
|
||||||
pil = 4;
|
pil = 5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCI_BASE_CLASS_NETWORK:
|
case PCI_BASE_CLASS_NETWORK:
|
||||||
|
@ -758,7 +758,7 @@ static unsigned int pci_sun4v_irq_build(struct pci_pbm_info *pbm,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
pil = 4;
|
pil = 5;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -693,11 +693,11 @@ void sbus_set_sbus64(struct sbus_dev *sdev, int bursts)
|
||||||
|
|
||||||
/* SBUS SYSIO INO number to Sparc PIL level. */
|
/* SBUS SYSIO INO number to Sparc PIL level. */
|
||||||
static unsigned char sysio_ino_to_pil[] = {
|
static unsigned char sysio_ino_to_pil[] = {
|
||||||
0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 0 */
|
0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 0 */
|
||||||
0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 1 */
|
0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 1 */
|
||||||
0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 2 */
|
0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 2 */
|
||||||
0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 3 */
|
0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 3 */
|
||||||
4, /* Onboard SCSI */
|
5, /* Onboard SCSI */
|
||||||
5, /* Onboard Ethernet */
|
5, /* Onboard Ethernet */
|
||||||
/*XXX*/ 8, /* Onboard BPP */
|
/*XXX*/ 8, /* Onboard BPP */
|
||||||
0, /* Bogon */
|
0, /* Bogon */
|
||||||
|
|
|
@ -760,12 +760,9 @@ static int smp_call_function_mask(void (*func)(void *info), void *info,
|
||||||
int nonatomic, int wait, cpumask_t mask)
|
int nonatomic, int wait, cpumask_t mask)
|
||||||
{
|
{
|
||||||
struct call_data_struct data;
|
struct call_data_struct data;
|
||||||
int cpus = cpus_weight(mask) - 1;
|
int cpus;
|
||||||
long timeout;
|
long timeout;
|
||||||
|
|
||||||
if (!cpus)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Can deadlock when called with interrupts disabled */
|
/* Can deadlock when called with interrupts disabled */
|
||||||
WARN_ON(irqs_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);
|
spin_lock(&call_lock);
|
||||||
|
|
||||||
|
cpu_clear(smp_processor_id(), mask);
|
||||||
|
cpus = cpus_weight(mask);
|
||||||
|
if (!cpus)
|
||||||
|
goto out_unlock;
|
||||||
|
|
||||||
call_data = &data;
|
call_data = &data;
|
||||||
|
|
||||||
smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask);
|
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);
|
udelay(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
spin_unlock(&call_lock);
|
spin_unlock(&call_lock);
|
||||||
|
|
||||||
return 0;
|
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_flush_tlb_kernel_range;
|
||||||
extern unsigned long xcall_report_regs;
|
extern unsigned long xcall_report_regs;
|
||||||
extern unsigned long xcall_receive_signal;
|
extern unsigned long xcall_receive_signal;
|
||||||
|
extern unsigned long xcall_new_mmu_context_version;
|
||||||
|
|
||||||
#ifdef DCACHE_ALIASING_POSSIBLE
|
#ifdef DCACHE_ALIASING_POSSIBLE
|
||||||
extern unsigned long xcall_flush_dcache_page_cheetah;
|
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)
|
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;
|
struct mm_struct *mm;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
clear_softint(1 << irq);
|
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.
|
* the version of the one we are using is now out of date.
|
||||||
*/
|
*/
|
||||||
mm = current->active_mm;
|
mm = current->active_mm;
|
||||||
if (likely(mm)) {
|
if (unlikely(!mm || (mm == &init_mm)))
|
||||||
unsigned long flags;
|
return;
|
||||||
|
|
||||||
spin_lock_irqsave(&mm->context.lock, flags);
|
spin_lock_irqsave(&mm->context.lock, flags);
|
||||||
|
|
||||||
if (unlikely(!CTX_VALID(mm->context)))
|
if (unlikely(!CTX_VALID(mm->context)))
|
||||||
get_new_mmu_context(mm);
|
get_new_mmu_context(mm);
|
||||||
|
|
||||||
load_secondary_context(mm);
|
spin_unlock_irqrestore(&mm->context.lock, flags);
|
||||||
__flush_tlb_mm(CTX_HWBITS(mm->context),
|
|
||||||
SECONDARY_CONTEXT);
|
|
||||||
|
|
||||||
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)
|
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)
|
void smp_report_regs(void)
|
||||||
|
|
|
@ -51,12 +51,13 @@ tl0_resv03e: BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40)
|
||||||
tl0_irq1: TRAP_IRQ(smp_call_function_client, 1)
|
tl0_irq1: TRAP_IRQ(smp_call_function_client, 1)
|
||||||
tl0_irq2: TRAP_IRQ(smp_receive_signal_client, 2)
|
tl0_irq2: TRAP_IRQ(smp_receive_signal_client, 2)
|
||||||
tl0_irq3: TRAP_IRQ(smp_penguin_jailcell, 3)
|
tl0_irq3: TRAP_IRQ(smp_penguin_jailcell, 3)
|
||||||
|
tl0_irq4: TRAP_IRQ(smp_new_mmu_context_version_client, 4)
|
||||||
#else
|
#else
|
||||||
tl0_irq1: BTRAP(0x41)
|
tl0_irq1: BTRAP(0x41)
|
||||||
tl0_irq2: BTRAP(0x42)
|
tl0_irq2: BTRAP(0x42)
|
||||||
tl0_irq3: BTRAP(0x43)
|
tl0_irq3: BTRAP(0x43)
|
||||||
|
tl0_irq4: BTRAP(0x44)
|
||||||
#endif
|
#endif
|
||||||
tl0_irq4: TRAP_IRQ(handler_irq, 4)
|
|
||||||
tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6)
|
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_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8)
|
||||||
tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10)
|
tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10)
|
||||||
|
|
|
@ -673,6 +673,11 @@ xcall_capture:
|
||||||
wr %g0, (1 << PIL_SMP_CAPTURE), %set_softint
|
wr %g0, (1 << PIL_SMP_CAPTURE), %set_softint
|
||||||
retry
|
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 */
|
#endif /* CONFIG_SMP */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,13 @@
|
||||||
#define PIL_SMP_CALL_FUNC 1
|
#define PIL_SMP_CALL_FUNC 1
|
||||||
#define PIL_SMP_RECEIVE_SIGNAL 2
|
#define PIL_SMP_RECEIVE_SIGNAL 2
|
||||||
#define PIL_SMP_CAPTURE 3
|
#define PIL_SMP_CAPTURE 3
|
||||||
|
#define PIL_SMP_CTX_NEW_VERSION 4
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
#define PIL_RESERVED(PIL) ((PIL) == PIL_SMP_CALL_FUNC || \
|
#define PIL_RESERVED(PIL) ((PIL) == PIL_SMP_CALL_FUNC || \
|
||||||
(PIL) == PIL_SMP_RECEIVE_SIGNAL || \
|
(PIL) == PIL_SMP_RECEIVE_SIGNAL || \
|
||||||
(PIL) == PIL_SMP_CAPTURE)
|
(PIL) == PIL_SMP_CAPTURE || \
|
||||||
|
(PIL) == PIL_SMP_CTX_NEW_VERSION)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* !(_SPARC64_PIL_H) */
|
#endif /* !(_SPARC64_PIL_H) */
|
||||||
|
|
Loading…
Reference in New Issue