aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2006-03-07 01:50:44 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-03-20 04:14:21 -0500
commitee29074d3bd23848905f52c515974e0cd0219faa (patch)
treed5306446b2e26d9e45f65467b4f3b3f3b0c8494c /arch
parenta77754b4d0731321db266c6c60ffcd7c62757da5 (diff)
[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>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/devices.c2
-rw-r--r--arch/sparc64/kernel/pci_psycho.c14
-rw-r--r--arch/sparc64/kernel/pci_sabre.c14
-rw-r--r--arch/sparc64/kernel/pci_schizo.c12
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c6
-rw-r--r--arch/sparc64/kernel/sbus.c10
-rw-r--r--arch/sparc64/kernel/smp.c39
-rw-r--r--arch/sparc64/kernel/ttable.S3
-rw-r--r--arch/sparc64/mm/ultra.S5
9 files changed, 60 insertions, 45 deletions
diff --git a/arch/sparc64/kernel/devices.c b/arch/sparc64/kernel/devices.c
index 1341b99ca7aa..007e8922cd16 100644
--- a/arch/sparc64/kernel/devices.c
+++ b/arch/sparc64/kernel/devices.c
@@ -157,7 +157,7 @@ unsigned int sun4v_vdev_device_interrupt(unsigned int dev_node)
157 return 0; 157 return 0;
158 } 158 }
159 159
160 return sun4v_build_irq(sun4v_vdev_devhandle, irq, 4, 0); 160 return sun4v_build_irq(sun4v_vdev_devhandle, irq, 5, 0);
161} 161}
162 162
163static const char *cpu_mid_prop(void) 163static const char *cpu_mid_prop(void)
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index f7b16e49c28b..d17878b145c2 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -286,17 +286,17 @@ static unsigned char psycho_pil_table[] = {
286/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */ 286/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */
287/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */ 287/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */
288/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */ 288/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */
289/*0x20*/4, /* SCSI */ 289/*0x20*/5, /* SCSI */
290/*0x21*/5, /* Ethernet */ 290/*0x21*/5, /* Ethernet */
291/*0x22*/8, /* Parallel Port */ 291/*0x22*/8, /* Parallel Port */
292/*0x23*/13, /* Audio Record */ 292/*0x23*/13, /* Audio Record */
293/*0x24*/14, /* Audio Playback */ 293/*0x24*/14, /* Audio Playback */
294/*0x25*/15, /* PowerFail */ 294/*0x25*/15, /* PowerFail */
295/*0x26*/4, /* second SCSI */ 295/*0x26*/5, /* second SCSI */
296/*0x27*/11, /* Floppy */ 296/*0x27*/11, /* Floppy */
297/*0x28*/4, /* Spare Hardware */ 297/*0x28*/5, /* Spare Hardware */
298/*0x29*/9, /* Keyboard */ 298/*0x29*/9, /* Keyboard */
299/*0x2a*/4, /* Mouse */ 299/*0x2a*/5, /* Mouse */
300/*0x2b*/12, /* Serial */ 300/*0x2b*/12, /* Serial */
301/*0x2c*/10, /* Timer 0 */ 301/*0x2c*/10, /* Timer 0 */
302/*0x2d*/11, /* Timer 1 */ 302/*0x2d*/11, /* Timer 1 */
@@ -313,11 +313,11 @@ static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
313 313
314 ret = psycho_pil_table[ino]; 314 ret = psycho_pil_table[ino];
315 if (ret == 0 && pdev == NULL) { 315 if (ret == 0 && pdev == NULL) {
316 ret = 4; 316 ret = 5;
317 } else if (ret == 0) { 317 } else if (ret == 0) {
318 switch ((pdev->class >> 16) & 0xff) { 318 switch ((pdev->class >> 16) & 0xff) {
319 case PCI_BASE_CLASS_STORAGE: 319 case PCI_BASE_CLASS_STORAGE:
320 ret = 4; 320 ret = 5;
321 break; 321 break;
322 322
323 case PCI_BASE_CLASS_NETWORK: 323 case PCI_BASE_CLASS_NETWORK:
@@ -336,7 +336,7 @@ static int psycho_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
336 break; 336 break;
337 337
338 default: 338 default:
339 ret = 4; 339 ret = 5;
340 break; 340 break;
341 }; 341 };
342 } 342 }
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 5ddc92931976..f67bb7f078cf 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -533,17 +533,17 @@ static unsigned char sabre_pil_table[] = {
533/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */ 533/*0x14*/0, 0, 0, 0, /* PCI B slot 1 Int A, B, C, D */
534/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */ 534/*0x18*/0, 0, 0, 0, /* PCI B slot 2 Int A, B, C, D */
535/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */ 535/*0x1c*/0, 0, 0, 0, /* PCI B slot 3 Int A, B, C, D */
536/*0x20*/4, /* SCSI */ 536/*0x20*/5, /* SCSI */
537/*0x21*/5, /* Ethernet */ 537/*0x21*/5, /* Ethernet */
538/*0x22*/8, /* Parallel Port */ 538/*0x22*/8, /* Parallel Port */
539/*0x23*/13, /* Audio Record */ 539/*0x23*/13, /* Audio Record */
540/*0x24*/14, /* Audio Playback */ 540/*0x24*/14, /* Audio Playback */
541/*0x25*/15, /* PowerFail */ 541/*0x25*/15, /* PowerFail */
542/*0x26*/4, /* second SCSI */ 542/*0x26*/5, /* second SCSI */
543/*0x27*/11, /* Floppy */ 543/*0x27*/11, /* Floppy */
544/*0x28*/4, /* Spare Hardware */ 544/*0x28*/5, /* Spare Hardware */
545/*0x29*/9, /* Keyboard */ 545/*0x29*/9, /* Keyboard */
546/*0x2a*/4, /* Mouse */ 546/*0x2a*/5, /* Mouse */
547/*0x2b*/12, /* Serial */ 547/*0x2b*/12, /* Serial */
548/*0x2c*/10, /* Timer 0 */ 548/*0x2c*/10, /* Timer 0 */
549/*0x2d*/11, /* Timer 1 */ 549/*0x2d*/11, /* Timer 1 */
@@ -565,11 +565,11 @@ static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
565 565
566 ret = sabre_pil_table[ino]; 566 ret = sabre_pil_table[ino];
567 if (ret == 0 && pdev == NULL) { 567 if (ret == 0 && pdev == NULL) {
568 ret = 4; 568 ret = 5;
569 } else if (ret == 0) { 569 } else if (ret == 0) {
570 switch ((pdev->class >> 16) & 0xff) { 570 switch ((pdev->class >> 16) & 0xff) {
571 case PCI_BASE_CLASS_STORAGE: 571 case PCI_BASE_CLASS_STORAGE:
572 ret = 4; 572 ret = 5;
573 break; 573 break;
574 574
575 case PCI_BASE_CLASS_NETWORK: 575 case PCI_BASE_CLASS_NETWORK:
@@ -588,7 +588,7 @@ static int sabre_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
588 break; 588 break;
589 589
590 default: 590 default:
591 ret = 4; 591 ret = 5;
592 break; 592 break;
593 }; 593 };
594 } 594 }
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
index 3a89f29e27d6..7fe4de03ac2e 100644
--- a/arch/sparc64/kernel/pci_schizo.c
+++ b/arch/sparc64/kernel/pci_schizo.c
@@ -243,8 +243,8 @@ static unsigned char schizo_pil_table[] = {
243/*0x0c*/0, 0, 0, 0, /* PCI slot 3 Int A, B, C, D */ 243/*0x0c*/0, 0, 0, 0, /* PCI slot 3 Int A, B, C, D */
244/*0x10*/0, 0, 0, 0, /* PCI slot 4 Int A, B, C, D */ 244/*0x10*/0, 0, 0, 0, /* PCI slot 4 Int A, B, C, D */
245/*0x14*/0, 0, 0, 0, /* PCI slot 5 Int A, B, C, D */ 245/*0x14*/0, 0, 0, 0, /* PCI slot 5 Int A, B, C, D */
246/*0x18*/4, /* SCSI */ 246/*0x18*/5, /* SCSI */
247/*0x19*/4, /* second SCSI */ 247/*0x19*/5, /* second SCSI */
248/*0x1a*/0, /* UNKNOWN */ 248/*0x1a*/0, /* UNKNOWN */
249/*0x1b*/0, /* UNKNOWN */ 249/*0x1b*/0, /* UNKNOWN */
250/*0x1c*/8, /* Parallel */ 250/*0x1c*/8, /* Parallel */
@@ -254,7 +254,7 @@ static unsigned char schizo_pil_table[] = {
254/*0x20*/13, /* Audio Record */ 254/*0x20*/13, /* Audio Record */
255/*0x21*/14, /* Audio Playback */ 255/*0x21*/14, /* Audio Playback */
256/*0x22*/12, /* Serial */ 256/*0x22*/12, /* Serial */
257/*0x23*/4, /* EBUS I2C */ 257/*0x23*/5, /* EBUS I2C */
258/*0x24*/10, /* RTC Clock */ 258/*0x24*/10, /* RTC Clock */
259/*0x25*/11, /* Floppy */ 259/*0x25*/11, /* Floppy */
260/*0x26*/0, /* UNKNOWN */ 260/*0x26*/0, /* UNKNOWN */
@@ -296,11 +296,11 @@ static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
296 296
297 ret = schizo_pil_table[ino]; 297 ret = schizo_pil_table[ino];
298 if (ret == 0 && pdev == NULL) { 298 if (ret == 0 && pdev == NULL) {
299 ret = 4; 299 ret = 5;
300 } else if (ret == 0) { 300 } else if (ret == 0) {
301 switch ((pdev->class >> 16) & 0xff) { 301 switch ((pdev->class >> 16) & 0xff) {
302 case PCI_BASE_CLASS_STORAGE: 302 case PCI_BASE_CLASS_STORAGE:
303 ret = 4; 303 ret = 5;
304 break; 304 break;
305 305
306 case PCI_BASE_CLASS_NETWORK: 306 case PCI_BASE_CLASS_NETWORK:
@@ -319,7 +319,7 @@ static int schizo_ino_to_pil(struct pci_dev *pdev, unsigned int ino)
319 break; 319 break;
320 320
321 default: 321 default:
322 ret = 4; 322 ret = 5;
323 break; 323 break;
324 }; 324 };
325 } 325 }
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index a9c44c0ae0a7..9372d4f376d5 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -735,11 +735,11 @@ static unsigned int pci_sun4v_irq_build(struct pci_pbm_info *pbm,
735 u32 devhandle = pbm->devhandle; 735 u32 devhandle = pbm->devhandle;
736 int pil; 736 int pil;
737 737
738 pil = 4; 738 pil = 5;
739 if (pdev) { 739 if (pdev) {
740 switch ((pdev->class >> 16) & 0xff) { 740 switch ((pdev->class >> 16) & 0xff) {
741 case PCI_BASE_CLASS_STORAGE: 741 case PCI_BASE_CLASS_STORAGE:
742 pil = 4; 742 pil = 5;
743 break; 743 break;
744 744
745 case PCI_BASE_CLASS_NETWORK: 745 case PCI_BASE_CLASS_NETWORK:
@@ -758,7 +758,7 @@ static unsigned int pci_sun4v_irq_build(struct pci_pbm_info *pbm,
758 break; 758 break;
759 759
760 default: 760 default:
761 pil = 4; 761 pil = 5;
762 break; 762 break;
763 }; 763 };
764 } 764 }
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index d95a1bcf163d..1d6ffdeabd4c 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -693,11 +693,11 @@ void sbus_set_sbus64(struct sbus_dev *sdev, int bursts)
693 693
694/* SBUS SYSIO INO number to Sparc PIL level. */ 694/* SBUS SYSIO INO number to Sparc PIL level. */
695static unsigned char sysio_ino_to_pil[] = { 695static unsigned char sysio_ino_to_pil[] = {
696 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 0 */ 696 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 0 */
697 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 1 */ 697 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 1 */
698 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 2 */ 698 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 2 */
699 0, 4, 4, 7, 5, 7, 8, 9, /* SBUS slot 3 */ 699 0, 5, 5, 7, 5, 7, 8, 9, /* SBUS slot 3 */
700 4, /* Onboard SCSI */ 700 5, /* Onboard SCSI */
701 5, /* Onboard Ethernet */ 701 5, /* Onboard Ethernet */
702/*XXX*/ 8, /* Onboard BPP */ 702/*XXX*/ 8, /* Onboard BPP */
703 0, /* Bogon */ 703 0, /* Bogon */
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index c4548a88953c..cf56128097c8 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -760,12 +760,9 @@ static int smp_call_function_mask(void (*func)(void *info), void *info,
760 int nonatomic, int wait, cpumask_t mask) 760 int nonatomic, int wait, cpumask_t mask)
761{ 761{
762 struct call_data_struct data; 762 struct call_data_struct data;
763 int cpus = cpus_weight(mask) - 1; 763 int cpus;
764 long timeout; 764 long timeout;
765 765
766 if (!cpus)
767 return 0;
768
769 /* Can deadlock when called with interrupts disabled */ 766 /* Can deadlock when called with interrupts disabled */
770 WARN_ON(irqs_disabled()); 767 WARN_ON(irqs_disabled());
771 768
@@ -776,6 +773,11 @@ static int smp_call_function_mask(void (*func)(void *info), void *info,
776 773
777 spin_lock(&call_lock); 774 spin_lock(&call_lock);
778 775
776 cpu_clear(smp_processor_id(), mask);
777 cpus = cpus_weight(mask);
778 if (!cpus)
779 goto out_unlock;
780
779 call_data = &data; 781 call_data = &data;
780 782
781 smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask); 783 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,
792 udelay(1); 794 udelay(1);
793 } 795 }
794 796
797out_unlock:
795 spin_unlock(&call_lock); 798 spin_unlock(&call_lock);
796 799
797 return 0; 800 return 0;
@@ -845,6 +848,7 @@ extern unsigned long xcall_flush_tlb_pending;
845extern unsigned long xcall_flush_tlb_kernel_range; 848extern unsigned long xcall_flush_tlb_kernel_range;
846extern unsigned long xcall_report_regs; 849extern unsigned long xcall_report_regs;
847extern unsigned long xcall_receive_signal; 850extern unsigned long xcall_receive_signal;
851extern unsigned long xcall_new_mmu_context_version;
848 852
849#ifdef DCACHE_ALIASING_POSSIBLE 853#ifdef DCACHE_ALIASING_POSSIBLE
850extern unsigned long xcall_flush_dcache_page_cheetah; 854extern unsigned long xcall_flush_dcache_page_cheetah;
@@ -974,7 +978,13 @@ void smp_receive_signal(int cpu)
974 978
975void smp_receive_signal_client(int irq, struct pt_regs *regs) 979void smp_receive_signal_client(int irq, struct pt_regs *regs)
976{ 980{
981 clear_softint(1 << irq);
982}
983
984void smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
985{
977 struct mm_struct *mm; 986 struct mm_struct *mm;
987 unsigned long flags;
978 988
979 clear_softint(1 << irq); 989 clear_softint(1 << irq);
980 990
@@ -982,25 +992,24 @@ void smp_receive_signal_client(int irq, struct pt_regs *regs)
982 * the version of the one we are using is now out of date. 992 * the version of the one we are using is now out of date.
983 */ 993 */
984 mm = current->active_mm; 994 mm = current->active_mm;
985 if (likely(mm)) { 995 if (unlikely(!mm || (mm == &init_mm)))
986 unsigned long flags; 996 return;
987 997
988 spin_lock_irqsave(&mm->context.lock, flags); 998 spin_lock_irqsave(&mm->context.lock, flags);
989 999
990 if (unlikely(!CTX_VALID(mm->context))) 1000 if (unlikely(!CTX_VALID(mm->context)))
991 get_new_mmu_context(mm); 1001 get_new_mmu_context(mm);
992 1002
993 load_secondary_context(mm); 1003 spin_unlock_irqrestore(&mm->context.lock, flags);
994 __flush_tlb_mm(CTX_HWBITS(mm->context),
995 SECONDARY_CONTEXT);
996 1004
997 spin_unlock_irqrestore(&mm->context.lock, flags); 1005 load_secondary_context(mm);
998 } 1006 __flush_tlb_mm(CTX_HWBITS(mm->context),
1007 SECONDARY_CONTEXT);
999} 1008}
1000 1009
1001void smp_new_mmu_context_version(void) 1010void smp_new_mmu_context_version(void)
1002{ 1011{
1003 __smp_receive_signal_mask(cpu_online_map); 1012 smp_cross_call(&xcall_new_mmu_context_version, 0, 0, 0);
1004} 1013}
1005 1014
1006void smp_report_regs(void) 1015void smp_report_regs(void)
diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S
index d5a8dd52d1f8..5d901519db55 100644
--- a/arch/sparc64/kernel/ttable.S
+++ b/arch/sparc64/kernel/ttable.S
@@ -51,12 +51,13 @@ tl0_resv03e: BTRAP(0x3e) BTRAP(0x3f) BTRAP(0x40)
51tl0_irq1: TRAP_IRQ(smp_call_function_client, 1) 51tl0_irq1: TRAP_IRQ(smp_call_function_client, 1)
52tl0_irq2: TRAP_IRQ(smp_receive_signal_client, 2) 52tl0_irq2: TRAP_IRQ(smp_receive_signal_client, 2)
53tl0_irq3: TRAP_IRQ(smp_penguin_jailcell, 3) 53tl0_irq3: TRAP_IRQ(smp_penguin_jailcell, 3)
54tl0_irq4: TRAP_IRQ(smp_new_mmu_context_version_client, 4)
54#else 55#else
55tl0_irq1: BTRAP(0x41) 56tl0_irq1: BTRAP(0x41)
56tl0_irq2: BTRAP(0x42) 57tl0_irq2: BTRAP(0x42)
57tl0_irq3: BTRAP(0x43) 58tl0_irq3: BTRAP(0x43)
59tl0_irq4: BTRAP(0x44)
58#endif 60#endif
59tl0_irq4: TRAP_IRQ(handler_irq, 4)
60tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6) 61tl0_irq5: TRAP_IRQ(handler_irq, 5) TRAP_IRQ(handler_irq, 6)
61tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8) 62tl0_irq7: TRAP_IRQ(handler_irq, 7) TRAP_IRQ(handler_irq, 8)
62tl0_irq9: TRAP_IRQ(handler_irq, 9) TRAP_IRQ(handler_irq, 10) 63tl0_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 bd8b0b4f878f..f8479fad4047 100644
--- a/arch/sparc64/mm/ultra.S
+++ b/arch/sparc64/mm/ultra.S
@@ -673,6 +673,11 @@ xcall_capture:
673 wr %g0, (1 << PIL_SMP_CAPTURE), %set_softint 673 wr %g0, (1 << PIL_SMP_CAPTURE), %set_softint
674 retry 674 retry
675 675
676 .globl xcall_new_mmu_context_version
677xcall_new_mmu_context_version:
678 wr %g0, (1 << PIL_SMP_CTX_NEW_VERSION), %set_softint
679 retry
680
676#endif /* CONFIG_SMP */ 681#endif /* CONFIG_SMP */
677 682
678 683