aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJack Steiner <steiner@sgi.com>2009-06-17 19:28:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-18 16:04:00 -0400
commit17b49a67a6a59f0e9f3c22e67ddb602410e8e182 (patch)
treec12156560f6ed549d008ce4d630d791be11f4999 /drivers
parent3eac2e95d7bb92222e185e445eca1fe3f695050f (diff)
gru: fix handling of mesq failures
Fix endcase in handling GRU message queue failures due to NACKs of PUT requests. Must ensure that the "present" bits are cleared before resending the message. Signed-off-by: Jack Steiner <steiner@sgi.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/sgi-gru/grukservices.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c
index 50b4dd8b0c9f..a0f981022a6c 100644
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -503,6 +503,29 @@ static void send_message_queue_interrupt(struct gru_message_queue_desc *mqd)
503 mqd->interrupt_vector); 503 mqd->interrupt_vector);
504} 504}
505 505
506/*
507 * Handle a PUT failure. Note: if message was a 2-line message, one of the
508 * lines might have successfully have been written. Before sending the
509 * message, "present" must be cleared in BOTH lines to prevent the receiver
510 * from prematurely seeing the full message.
511 */
512static int send_message_put_nacked(void *cb, struct gru_message_queue_desc *mqd,
513 void *mesg, int lines)
514{
515 unsigned long m;
516
517 m = mqd->mq_gpa + (gru_get_amo_value_head(cb) << 6);
518 if (lines == 2) {
519 gru_vset(cb, m, 0, XTYPE_CL, lines, 1, IMA);
520 if (gru_wait(cb) != CBS_IDLE)
521 return MQE_UNEXPECTED_CB_ERR;
522 }
523 gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, lines, 1, IMA);
524 if (gru_wait(cb) != CBS_IDLE)
525 return MQE_UNEXPECTED_CB_ERR;
526 send_message_queue_interrupt(mqd);
527 return MQE_OK;
528}
506 529
507/* 530/*
508 * Handle a gru_mesq failure. Some of these failures are software recoverable 531 * Handle a gru_mesq failure. Some of these failures are software recoverable
@@ -512,7 +535,6 @@ static int send_message_failure(void *cb, struct gru_message_queue_desc *mqd,
512 void *mesg, int lines) 535 void *mesg, int lines)
513{ 536{
514 int substatus, ret = 0; 537 int substatus, ret = 0;
515 unsigned long m;
516 538
517 substatus = gru_get_cb_message_queue_substatus(cb); 539 substatus = gru_get_cb_message_queue_substatus(cb);
518 switch (substatus) { 540 switch (substatus) {
@@ -534,14 +556,7 @@ static int send_message_failure(void *cb, struct gru_message_queue_desc *mqd,
534 break; 556 break;
535 case CBSS_PUT_NACKED: 557 case CBSS_PUT_NACKED:
536 STAT(mesq_send_put_nacked); 558 STAT(mesq_send_put_nacked);
537 m = mqd->mq_gpa + (gru_get_amo_value_head(cb) << 6); 559 ret = send_message_put_nacked(cb, mqd, mesg, lines);
538 gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, lines, 1, IMA);
539 if (gru_wait(cb) == CBS_IDLE) {
540 ret = MQE_OK;
541 send_message_queue_interrupt(mqd);
542 } else {
543 ret = MQE_UNEXPECTED_CB_ERR;
544 }
545 break; 560 break;
546 default: 561 default:
547 BUG(); 562 BUG();