diff options
Diffstat (limited to 'arch/sparc64/kernel/smp.c')
-rw-r--r-- | arch/sparc64/kernel/smp.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index f7fa873c800d..c550bba3490a 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c | |||
@@ -400,7 +400,7 @@ static __inline__ void spitfire_xcall_deliver(u64 data0, u64 data1, u64 data2, c | |||
400 | static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask) | 400 | static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask) |
401 | { | 401 | { |
402 | u64 pstate, ver; | 402 | u64 pstate, ver; |
403 | int nack_busy_id, is_jbus; | 403 | int nack_busy_id, is_jbus, need_more; |
404 | 404 | ||
405 | if (cpus_empty(mask)) | 405 | if (cpus_empty(mask)) |
406 | return; | 406 | return; |
@@ -416,6 +416,7 @@ static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mas | |||
416 | __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); | 416 | __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); |
417 | 417 | ||
418 | retry: | 418 | retry: |
419 | need_more = 0; | ||
419 | __asm__ __volatile__("wrpr %0, %1, %%pstate\n\t" | 420 | __asm__ __volatile__("wrpr %0, %1, %%pstate\n\t" |
420 | : : "r" (pstate), "i" (PSTATE_IE)); | 421 | : : "r" (pstate), "i" (PSTATE_IE)); |
421 | 422 | ||
@@ -444,6 +445,10 @@ retry: | |||
444 | : /* no outputs */ | 445 | : /* no outputs */ |
445 | : "r" (target), "i" (ASI_INTR_W)); | 446 | : "r" (target), "i" (ASI_INTR_W)); |
446 | nack_busy_id++; | 447 | nack_busy_id++; |
448 | if (nack_busy_id == 32) { | ||
449 | need_more = 1; | ||
450 | break; | ||
451 | } | ||
447 | } | 452 | } |
448 | } | 453 | } |
449 | 454 | ||
@@ -460,6 +465,16 @@ retry: | |||
460 | if (dispatch_stat == 0UL) { | 465 | if (dispatch_stat == 0UL) { |
461 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" | 466 | __asm__ __volatile__("wrpr %0, 0x0, %%pstate" |
462 | : : "r" (pstate)); | 467 | : : "r" (pstate)); |
468 | if (unlikely(need_more)) { | ||
469 | int i, cnt = 0; | ||
470 | for_each_cpu_mask(i, mask) { | ||
471 | cpu_clear(i, mask); | ||
472 | cnt++; | ||
473 | if (cnt == 32) | ||
474 | break; | ||
475 | } | ||
476 | goto retry; | ||
477 | } | ||
463 | return; | 478 | return; |
464 | } | 479 | } |
465 | if (!--stuck) | 480 | if (!--stuck) |
@@ -497,6 +512,8 @@ retry: | |||
497 | if ((dispatch_stat & check_mask) == 0) | 512 | if ((dispatch_stat & check_mask) == 0) |
498 | cpu_clear(i, mask); | 513 | cpu_clear(i, mask); |
499 | this_busy_nack += 2; | 514 | this_busy_nack += 2; |
515 | if (this_busy_nack == 64) | ||
516 | break; | ||
500 | } | 517 | } |
501 | 518 | ||
502 | goto retry; | 519 | goto retry; |