diff options
Diffstat (limited to 'drivers/misc/sgi-gru/grukservices.c')
-rw-r--r-- | drivers/misc/sgi-gru/grukservices.c | 33 |
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 | */ | ||
512 | static 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(); |