aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHaren Myneni <haren@us.ibm.com>2006-07-27 17:29:00 -0400
committerPaul Mackerras <paulus@samba.org>2006-08-08 02:00:11 -0400
commit81b73dd92b97423b8f5324a59044da478c04f4c4 (patch)
tree032f8415eb980d7f231e8e2490fba3c5356aadf9 /arch
parentdcc42f483d6808ba4d04af9da35e7e47b711f6c2 (diff)
[POWERPC] Fix might-sleep warning on removing cpus
Noticing the following might_sleep warning (dump_stack()) during kdump testing when CONFIG_DEBUG_SPINLOCK_SLEEP is enabled. All secondary CPUs will be calling rtas_set_indicator with interrupts disabled to remove them from global interrupt queue. BUG: sleeping function called from invalid context at arch/powerpc/kernel/rtas.c:463 in_atomic():1, irqs_disabled():1 Call Trace: [C00000000FFFB970] [C000000000010234] .show_stack+0x68/0x1b0 (unreliable) [C00000000FFFBA10] [C000000000059354] .__might_sleep+0xd8/0xf4 [C00000000FFFBA90] [C00000000001D1BC] .rtas_busy_delay+0x20/0x5c [C00000000FFFBB20] [C00000000001D8A8] .rtas_set_indicator+0x6c/0xcc [C00000000FFFBBC0] [C000000000048BF4] .xics_teardown_cpu+0x118/0x134 [C00000000FFFBC40] [C00000000004539C] .pseries_kexec_cpu_down_xics+0x74/0x8c [C00000000FFFBCC0] [C00000000002DF08] .crash_ipi_callback+0x15c/0x188 [C00000000FFFBD50] [C0000000000296EC] .smp_message_recv+0x84/0xdc [C00000000FFFBDC0] [C000000000048E08] .xics_ipi_dispatch+0xf0/0x130 [C00000000FFFBE50] [C00000000009EF10] .handle_IRQ_event+0x7c/0xf8 [C00000000FFFBF00] [C0000000000A0A14] .handle_percpu_irq+0x90/0x10c [C00000000FFFBF90] [C00000000002659C] .call_handle_irq+0x1c/0x2c [C00000000058B9C0] [C00000000000CA10] .do_IRQ+0xf4/0x1a4 [C00000000058BA50] [C0000000000044EC] hardware_interrupt_entry+0xc/0x10 --- Exception: 501 at .plpar_hcall_norets+0x14/0x1c LR = .pseries_dedicated_idle_sleep+0x190/0x1d4 [C00000000058BD40] [C00000000058BDE0] 0xc00000000058bde0 (unreliable) [C00000000058BDF0] [C00000000001270C] .cpu_idle+0x10c/0x1e0 [C00000000058BE70] [C000000000009274] .rest_init+0x44/0x5c To fix this issue, rtas_set_indicator_fast() is added so that will not wait for RTAS 'busy' delay and this new function is used for kdump (in xics_teardown_cpu()) and for CPU hotplug ( xics_migrate_irqs_away() and xics_setup_cpu()). Note that the platform architecture spec says that set-indicator on the indicator we're using here is not permitted to return the busy or extended busy status codes. Signed-off-by: Haren Myneni <haren@us.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/kernel/rtas.c21
-rw-r--r--arch/powerpc/platforms/pseries/xics.c6
2 files changed, 24 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 4a4cb559840..77f1e06d208 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -569,6 +569,27 @@ int rtas_set_indicator(int indicator, int index, int new_value)
569} 569}
570EXPORT_SYMBOL(rtas_set_indicator); 570EXPORT_SYMBOL(rtas_set_indicator);
571 571
572/*
573 * Ignoring RTAS extended delay
574 */
575int rtas_set_indicator_fast(int indicator, int index, int new_value)
576{
577 int rc;
578 int token = rtas_token("set-indicator");
579
580 if (token == RTAS_UNKNOWN_SERVICE)
581 return -ENOENT;
582
583 rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
584
585 WARN_ON(rc == -2 || (rc >= 9900 && rc <= 9905));
586
587 if (rc < 0)
588 return rtas_error_rc(rc);
589
590 return rc;
591}
592
572void rtas_restart(char *cmd) 593void rtas_restart(char *cmd)
573{ 594{
574 if (rtas_flash_term_hook) 595 if (rtas_flash_term_hook)
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 2d0da6f9e24..e9886302572 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -467,7 +467,7 @@ void xics_setup_cpu(void)
467 * 467 *
468 * XXX: undo of teardown on kexec needs this too, as may hotplug 468 * XXX: undo of teardown on kexec needs this too, as may hotplug
469 */ 469 */
470 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, 470 rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
471 (1UL << interrupt_server_size) - 1 - default_distrib_server, 1); 471 (1UL << interrupt_server_size) - 1 - default_distrib_server, 1);
472} 472}
473 473
@@ -796,7 +796,7 @@ void xics_teardown_cpu(int secondary)
796 * so leave the master cpu in the group. 796 * so leave the master cpu in the group.
797 */ 797 */
798 if (secondary) 798 if (secondary)
799 rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, 799 rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
800 (1UL << interrupt_server_size) - 1 - 800 (1UL << interrupt_server_size) - 1 -
801 default_distrib_server, 0); 801 default_distrib_server, 0);
802} 802}
@@ -813,7 +813,7 @@ void xics_migrate_irqs_away(void)
813 xics_set_cpu_priority(cpu, 0); 813 xics_set_cpu_priority(cpu, 0);
814 814
815 /* remove ourselves from the global interrupt queue */ 815 /* remove ourselves from the global interrupt queue */
816 status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE, 816 status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE,
817 (1UL << interrupt_server_size) - 1 - default_distrib_server, 0); 817 (1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
818 WARN_ON(status < 0); 818 WARN_ON(status < 0);
819 819