aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sgi-gru/grukservices.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/sgi-gru/grukservices.c')
-rw-r--r--drivers/misc/sgi-gru/grukservices.c39
1 files changed, 24 insertions, 15 deletions
diff --git a/drivers/misc/sgi-gru/grukservices.c b/drivers/misc/sgi-gru/grukservices.c
index bfbf8fdbcd37..34749ee88dfa 100644
--- a/drivers/misc/sgi-gru/grukservices.c
+++ b/drivers/misc/sgi-gru/grukservices.c
@@ -31,6 +31,7 @@
31#include <linux/interrupt.h> 31#include <linux/interrupt.h>
32#include <linux/uaccess.h> 32#include <linux/uaccess.h>
33#include <linux/delay.h> 33#include <linux/delay.h>
34#include <asm/io_apic.h>
34#include "gru.h" 35#include "gru.h"
35#include "grulib.h" 36#include "grulib.h"
36#include "grutables.h" 37#include "grutables.h"
@@ -566,7 +567,7 @@ int gru_create_message_queue(struct gru_message_queue_desc *mqd,
566 mqd->mq = mq; 567 mqd->mq = mq;
567 mqd->mq_gpa = uv_gpa(mq); 568 mqd->mq_gpa = uv_gpa(mq);
568 mqd->qlines = qlines; 569 mqd->qlines = qlines;
569 mqd->interrupt_pnode = UV_NASID_TO_PNODE(nasid); 570 mqd->interrupt_pnode = nasid >> 1;
570 mqd->interrupt_vector = vector; 571 mqd->interrupt_vector = vector;
571 mqd->interrupt_apicid = apicid; 572 mqd->interrupt_apicid = apicid;
572 return 0; 573 return 0;
@@ -703,18 +704,6 @@ cberr:
703} 704}
704 705
705/* 706/*
706 * Send a cross-partition interrupt to the SSI that contains the target
707 * message queue. Normally, the interrupt is automatically delivered by hardware
708 * but some error conditions require explicit delivery.
709 */
710static void send_message_queue_interrupt(struct gru_message_queue_desc *mqd)
711{
712 if (mqd->interrupt_vector)
713 uv_hub_send_ipi(mqd->interrupt_pnode, mqd->interrupt_apicid,
714 mqd->interrupt_vector);
715}
716
717/*
718 * Handle a PUT failure. Note: if message was a 2-line message, one of the 707 * Handle a PUT failure. Note: if message was a 2-line message, one of the
719 * lines might have successfully have been written. Before sending the 708 * lines might have successfully have been written. Before sending the
720 * message, "present" must be cleared in BOTH lines to prevent the receiver 709 * message, "present" must be cleared in BOTH lines to prevent the receiver
@@ -723,7 +712,8 @@ static void send_message_queue_interrupt(struct gru_message_queue_desc *mqd)
723static int send_message_put_nacked(void *cb, struct gru_message_queue_desc *mqd, 712static int send_message_put_nacked(void *cb, struct gru_message_queue_desc *mqd,
724 void *mesg, int lines) 713 void *mesg, int lines)
725{ 714{
726 unsigned long m; 715 unsigned long m, *val = mesg, gpa, save;
716 int ret;
727 717
728 m = mqd->mq_gpa + (gru_get_amo_value_head(cb) << 6); 718 m = mqd->mq_gpa + (gru_get_amo_value_head(cb) << 6);
729 if (lines == 2) { 719 if (lines == 2) {
@@ -734,7 +724,26 @@ static int send_message_put_nacked(void *cb, struct gru_message_queue_desc *mqd,
734 gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, lines, 1, IMA); 724 gru_vstore(cb, m, gru_get_tri(mesg), XTYPE_CL, lines, 1, IMA);
735 if (gru_wait(cb) != CBS_IDLE) 725 if (gru_wait(cb) != CBS_IDLE)
736 return MQE_UNEXPECTED_CB_ERR; 726 return MQE_UNEXPECTED_CB_ERR;
737 send_message_queue_interrupt(mqd); 727
728 if (!mqd->interrupt_vector)
729 return MQE_OK;
730
731 /*
732 * Send a cross-partition interrupt to the SSI that contains the target
733 * message queue. Normally, the interrupt is automatically delivered by
734 * hardware but some error conditions require explicit delivery.
735 * Use the GRU to deliver the interrupt. Otherwise partition failures
736 * could cause unrecovered errors.
737 */
738 gpa = uv_global_gru_mmr_address(mqd->interrupt_pnode, UVH_IPI_INT);
739 save = *val;
740 *val = uv_hub_ipi_value(mqd->interrupt_apicid, mqd->interrupt_vector,
741 dest_Fixed);
742 gru_vstore_phys(cb, gpa, gru_get_tri(mesg), IAA_REGISTER, IMA);
743 ret = gru_wait(cb);
744 *val = save;
745 if (ret != CBS_IDLE)
746 return MQE_UNEXPECTED_CB_ERR;
738 return MQE_OK; 747 return MQE_OK;
739} 748}
740 749