diff options
Diffstat (limited to 'arch/s390/kernel/smp.c')
-rw-r--r-- | arch/s390/kernel/smp.c | 73 |
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); | |||
63 | static void smp_ext_bitcall_others(ec_bit_sig); | 63 | static 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 | 66 | 5B * 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 | */ |
69 | static DEFINE_SPINLOCK(call_lock); | 69 | static 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 | */ |
421 | typedef struct | 421 | struct 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 | */ |
432 | void smp_ctl_bit_callback(void *info) { | 429 | void 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 | */ |
447 | void smp_ctl_set_bit(int cr, int bit) { | 443 | void 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 | */ |
463 | void smp_ctl_clear_bit(int cr, int bit) { | 456 | void 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); |