aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r--arch/s390/kernel/smp.c73
1 files changed, 27 insertions, 46 deletions
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index b2e6f4c8d382..a8e6199755d4 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -63,7 +63,7 @@ static void smp_ext_bitcall(int, ec_bit_sig);
63static void smp_ext_bitcall_others(ec_bit_sig); 63static void smp_ext_bitcall_others(ec_bit_sig);
64 64
65/* 65/*
66 * Structure and data for smp_call_function(). This is designed to minimise 665B * Structure and data for smp_call_function(). This is designed to minimise
67 * static memory requirements. It also looks cleaner. 67 * static memory requirements. It also looks cleaner.
68 */ 68 */
69static DEFINE_SPINLOCK(call_lock); 69static DEFINE_SPINLOCK(call_lock);
@@ -418,59 +418,49 @@ void smp_send_reschedule(int cpu)
418/* 418/*
419 * parameter area for the set/clear control bit callbacks 419 * parameter area for the set/clear control bit callbacks
420 */ 420 */
421typedef struct 421struct ec_creg_mask_parms {
422{
423 __u16 start_ctl;
424 __u16 end_ctl;
425 unsigned long orvals[16]; 422 unsigned long orvals[16];
426 unsigned long andvals[16]; 423 unsigned long andvals[16];
427} ec_creg_mask_parms; 424};
428 425
429/* 426/*
430 * callback for setting/clearing control bits 427 * callback for setting/clearing control bits
431 */ 428 */
432void smp_ctl_bit_callback(void *info) { 429void smp_ctl_bit_callback(void *info) {
433 ec_creg_mask_parms *pp; 430 struct ec_creg_mask_parms *pp = info;
434 unsigned long cregs[16]; 431 unsigned long cregs[16];
435 int i; 432 int i;
436 433
437 pp = (ec_creg_mask_parms *) info; 434 __ctl_store(cregs, 0, 15);
438 __ctl_store(cregs[pp->start_ctl], pp->start_ctl, pp->end_ctl); 435 for (i = 0; i <= 15; i++)
439 for (i = pp->start_ctl; i <= pp->end_ctl; i++)
440 cregs[i] = (cregs[i] & pp->andvals[i]) | pp->orvals[i]; 436 cregs[i] = (cregs[i] & pp->andvals[i]) | pp->orvals[i];
441 __ctl_load(cregs[pp->start_ctl], pp->start_ctl, pp->end_ctl); 437 __ctl_load(cregs, 0, 15);
442} 438}
443 439
444/* 440/*
445 * Set a bit in a control register of all cpus 441 * Set a bit in a control register of all cpus
446 */ 442 */
447void smp_ctl_set_bit(int cr, int bit) { 443void smp_ctl_set_bit(int cr, int bit)
448 ec_creg_mask_parms parms; 444{
445 struct ec_creg_mask_parms parms;
449 446
450 parms.start_ctl = cr; 447 memset(&parms.orvals, 0, sizeof(parms.orvals));
451 parms.end_ctl = cr; 448 memset(&parms.andvals, 0xff, sizeof(parms.andvals));
452 parms.orvals[cr] = 1 << bit; 449 parms.orvals[cr] = 1 << bit;
453 parms.andvals[cr] = -1L; 450 on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
454 preempt_disable();
455 smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
456 __ctl_set_bit(cr, bit);
457 preempt_enable();
458} 451}
459 452
460/* 453/*
461 * Clear a bit in a control register of all cpus 454 * Clear a bit in a control register of all cpus
462 */ 455 */
463void smp_ctl_clear_bit(int cr, int bit) { 456void smp_ctl_clear_bit(int cr, int bit)
464 ec_creg_mask_parms parms; 457{
458 struct ec_creg_mask_parms parms;
465 459
466 parms.start_ctl = cr; 460 memset(&parms.orvals, 0, sizeof(parms.orvals));
467 parms.end_ctl = cr; 461 memset(&parms.andvals, 0xff, sizeof(parms.andvals));
468 parms.orvals[cr] = 0;
469 parms.andvals[cr] = ~(1L << bit); 462 parms.andvals[cr] = ~(1L << bit);
470 preempt_disable(); 463 on_each_cpu(smp_ctl_bit_callback, &parms, 0, 1);
471 smp_call_function(smp_ctl_bit_callback, &parms, 0, 1);
472 __ctl_clear_bit(cr, bit);
473 preempt_enable();
474} 464}
475 465
476/* 466/*
@@ -650,9 +640,9 @@ __cpu_up(unsigned int cpu)
650 sf->gprs[9] = (unsigned long) sf; 640 sf->gprs[9] = (unsigned long) sf;
651 cpu_lowcore->save_area[15] = (unsigned long) sf; 641 cpu_lowcore->save_area[15] = (unsigned long) sf;
652 __ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15); 642 __ctl_store(cpu_lowcore->cregs_save_area[0], 0, 15);
653 __asm__ __volatile__("stam 0,15,0(%0)" 643 asm volatile(
654 : : "a" (&cpu_lowcore->access_regs_save_area) 644 " stam 0,15,0(%0)"
655 : "memory"); 645 : : "a" (&cpu_lowcore->access_regs_save_area) : "memory");
656 cpu_lowcore->percpu_offset = __per_cpu_offset[cpu]; 646 cpu_lowcore->percpu_offset = __per_cpu_offset[cpu];
657 cpu_lowcore->current_task = (unsigned long) idle; 647 cpu_lowcore->current_task = (unsigned long) idle;
658 cpu_lowcore->cpu_data.cpu_nr = cpu; 648 cpu_lowcore->cpu_data.cpu_nr = cpu;
@@ -708,7 +698,7 @@ int
708__cpu_disable(void) 698__cpu_disable(void)
709{ 699{
710 unsigned long flags; 700 unsigned long flags;
711 ec_creg_mask_parms cr_parms; 701 struct ec_creg_mask_parms cr_parms;
712 int cpu = smp_processor_id(); 702 int cpu = smp_processor_id();
713 703
714 spin_lock_irqsave(&smp_reserve_lock, flags); 704 spin_lock_irqsave(&smp_reserve_lock, flags);
@@ -724,30 +714,21 @@ __cpu_disable(void)
724 pfault_fini(); 714 pfault_fini();
725#endif 715#endif
726 716
727 /* disable all external interrupts */ 717 memset(&cr_parms.orvals, 0, sizeof(cr_parms.orvals));
718 memset(&cr_parms.andvals, 0xff, sizeof(cr_parms.andvals));
728 719
729 cr_parms.start_ctl = 0; 720 /* disable all external interrupts */
730 cr_parms.end_ctl = 0;
731 cr_parms.orvals[0] = 0; 721 cr_parms.orvals[0] = 0;
732 cr_parms.andvals[0] = ~(1<<15 | 1<<14 | 1<<13 | 1<<12 | 722 cr_parms.andvals[0] = ~(1<<15 | 1<<14 | 1<<13 | 1<<12 |
733 1<<11 | 1<<10 | 1<< 6 | 1<< 4); 723 1<<11 | 1<<10 | 1<< 6 | 1<< 4);
734 smp_ctl_bit_callback(&cr_parms);
735
736 /* disable all I/O interrupts */ 724 /* disable all I/O interrupts */
737
738 cr_parms.start_ctl = 6;
739 cr_parms.end_ctl = 6;
740 cr_parms.orvals[6] = 0; 725 cr_parms.orvals[6] = 0;
741 cr_parms.andvals[6] = ~(1<<31 | 1<<30 | 1<<29 | 1<<28 | 726 cr_parms.andvals[6] = ~(1<<31 | 1<<30 | 1<<29 | 1<<28 |
742 1<<27 | 1<<26 | 1<<25 | 1<<24); 727 1<<27 | 1<<26 | 1<<25 | 1<<24);
743 smp_ctl_bit_callback(&cr_parms);
744
745 /* disable most machine checks */ 728 /* disable most machine checks */
746
747 cr_parms.start_ctl = 14;
748 cr_parms.end_ctl = 14;
749 cr_parms.orvals[14] = 0; 729 cr_parms.orvals[14] = 0;
750 cr_parms.andvals[14] = ~(1<<28 | 1<<27 | 1<<26 | 1<<25 | 1<<24); 730 cr_parms.andvals[14] = ~(1<<28 | 1<<27 | 1<<26 | 1<<25 | 1<<24);
731
751 smp_ctl_bit_callback(&cr_parms); 732 smp_ctl_bit_callback(&cr_parms);
752 733
753 spin_unlock_irqrestore(&smp_reserve_lock, flags); 734 spin_unlock_irqrestore(&smp_reserve_lock, flags);