aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-01-15 23:09:59 +0200
committerAdrian Bunk <bunk@kernel.org>2008-01-16 01:11:38 +0200
commit3902b59254456107f77820ad42c7f27640f648e9 (patch)
tree2550b935f833404e7a3f3de42cb8fe4c33bb87ae /arch
parent35336fa51a17088020720aa2dc4e5677227a4185 (diff)
[SPARC64]: Fix endless loop in cheetah_xcall_deliver().
[ Upsteam commit: 0de56d1ab83323d604d95ca193dcbd28388dbabb ] We need to mask out the proper bits when testing the dispatch status register else we can see unrelated NACK bits from previous cross call sends. Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Adrian Bunk <bunk@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc64/kernel/smp.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
index 1f7ad8a69052..39f95217518d 100644
--- a/arch/sparc64/kernel/smp.c
+++ b/arch/sparc64/kernel/smp.c
@@ -440,7 +440,7 @@ static __inline__ void spitfire_xcall_deliver(u64 data0, u64 data1, u64 data2, c
*/
static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mask)
{
- u64 pstate, ver;
+ u64 pstate, ver, busy_mask;
int nack_busy_id, is_jalapeno;
if (cpus_empty(mask))
@@ -470,14 +470,20 @@ retry:
"i" (ASI_INTR_W));
nack_busy_id = 0;
+ busy_mask = 0;
{
int i;
for_each_cpu_mask(i, mask) {
u64 target = (i << 14) | 0x70;
- if (!is_jalapeno)
+ if (is_jalapeno) {
+ busy_mask |= (0x1UL << (i * 2));
+ } else {
target |= (nack_busy_id << 24);
+ busy_mask |= (0x1UL <<
+ (nack_busy_id * 2));
+ }
__asm__ __volatile__(
"stxa %%g0, [%0] %1\n\t"
"membar #Sync\n\t"
@@ -489,27 +495,28 @@ retry:
/* Now, poll for completion. */
{
- u64 dispatch_stat;
+ u64 dispatch_stat, nack_mask;
long stuck;
stuck = 100000 * nack_busy_id;
+ nack_mask = busy_mask << 1;
do {
__asm__ __volatile__("ldxa [%%g0] %1, %0"
: "=r" (dispatch_stat)
: "i" (ASI_INTR_DISPATCH_STAT));
- if (dispatch_stat == 0UL) {
+ if (!(dispatch_stat & (busy_mask | nack_mask))) {
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: : "r" (pstate));
return;
}
if (!--stuck)
break;
- } while (dispatch_stat & 0x5555555555555555UL);
+ } while (dispatch_stat & busy_mask);
__asm__ __volatile__("wrpr %0, 0x0, %%pstate"
: : "r" (pstate));
- if ((dispatch_stat & ~(0x5555555555555555UL)) == 0) {
+ if (dispatch_stat & busy_mask) {
/* Busy bits will not clear, continue instead
* of freezing up on this cpu.
*/