Skip to content

Commit

Permalink
[SPARC64]: Fix endless loop in cheetah_xcall_deliver().
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
David S. Miller committed Dec 12, 2007
1 parent 58d784a commit 0de56d1
Showing 1 changed file with 13 additions and 6 deletions.
19 changes: 13 additions & 6 deletions arch/sparc64/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ static inline void spitfire_xcall_deliver(u64 data0, u64 data1, u64 data2, cpuma
*/
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_jbus, need_more;

if (cpus_empty(mask))
Expand Down Expand Up @@ -508,14 +508,20 @@ static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mas
"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_jbus)
if (is_jbus) {
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"
Expand All @@ -531,15 +537,16 @@ static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mas

/* 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));
if (unlikely(need_more)) {
Expand All @@ -556,12 +563,12 @@ static void cheetah_xcall_deliver(u64 data0, u64 data1, u64 data2, cpumask_t mas
}
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.
*/
Expand Down

0 comments on commit 0de56d1

Please sign in to comment.