Browse Source

[SCSI] qla4xxx: IDC implementation for Loopback

Handle IDC Request Notify AEN and post IDC Acknowledgement
while participating in Loopback IDC.

Signed-off-by: Nilesh Javali <nilesh.javali@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Nilesh Javali 12 years ago
parent
commit
320a61de9d

+ 8 - 0
drivers/scsi/qla4xxx/ql4_83xx.h

@@ -259,4 +259,12 @@ struct qla83xx_minidump_entry_pollrdmwr {
 	uint32_t data_size;
 };
 
+/* IDC additional information */
+struct qla4_83xx_idc_information {
+	uint32_t request_desc;  /* IDC request descriptor */
+	uint32_t info1; /* IDC additional info */
+	uint32_t info2; /* IDC additional info */
+	uint32_t info3; /* IDC additional info */
+};
+
 #endif

+ 2 - 1
drivers/scsi/qla4xxx/ql4_def.h

@@ -531,7 +531,7 @@ struct scsi_qla_host {
 #define DPC_RESET_ACTIVE		20 /* 0x00040000 */
 #define DPC_HA_UNRECOVERABLE		21 /* 0x00080000 ISP-82xx only*/
 #define DPC_HA_NEED_QUIESCENT		22 /* 0x00100000 ISP-82xx only*/
-
+#define DPC_POST_IDC_ACK		23 /* 0x00200000 */
 
 	struct Scsi_Host *host; /* pointer to host data */
 	uint32_t tot_ddbs;
@@ -756,6 +756,7 @@ struct scsi_qla_host {
 	struct device_reg_83xx  __iomem *qla4_83xx_reg; /* Base I/O address
 							   for ISP8324 */
 	uint32_t pf_bit;
+	struct qla4_83xx_idc_information idc_info;
 };
 
 struct ql4_task_data {

+ 6 - 0
drivers/scsi/qla4xxx/ql4_fw.h

@@ -454,6 +454,10 @@ struct qla_flt_region {
 #define MBOX_CMD_GET_CRASH_RECORD		0x0076	/* 4010 only */
 #define MBOX_CMD_GET_CONN_EVENT_LOG		0x0077
 
+#define MBOX_CMD_IDC_ACK			0x0101
+#define MBOX_CMD_PORT_RESET			0x0120
+#define MBOX_CMD_SET_PORT_CONFIG		0x0122
+
 /*  Mailbox status definitions */
 #define MBOX_COMPLETION_STATUS			4
 #define MBOX_STS_BUSY				0x0007
@@ -490,6 +494,8 @@ struct qla_flt_region {
 #define MBOX_ASTS_IPV6_ND_PREFIX_IGNORED	0x802C
 #define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED	0x802D
 #define MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD		0x802E
+#define MBOX_ASTS_IDC_COMPLETE			0x8100
+#define MBOX_ASTS_IDC_NOTIFY			0x8101
 #define MBOX_ASTS_TXSCVR_INSERTED		0x8130
 #define MBOX_ASTS_TXSCVR_REMOVED		0x8131
 

+ 1 - 0
drivers/scsi/qla4xxx/ql4_glbl.h

@@ -257,6 +257,7 @@ int qla4_8xxx_mbx_intr_disable(struct scsi_qla_host *ha);
 int qla4_8xxx_mbx_intr_enable(struct scsi_qla_host *ha);
 int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param);
 int qla4_8xxx_update_idc_reg(struct scsi_qla_host *ha);
+int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha);
 
 extern int ql4xextended_error_logging;
 extern int ql4xdontresethba;

+ 37 - 0
drivers/scsi/qla4xxx/ql4_isr.c

@@ -806,6 +806,43 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
 			    " removed\n",  ha->host_no, mbox_sts[0]));
 			break;
 
+		case MBOX_ASTS_IDC_NOTIFY:
+		{
+			uint32_t opcode;
+			if (is_qla8032(ha)) {
+				DEBUG2(ql4_printk(KERN_INFO, ha,
+						  "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x\n",
+						  ha->host_no, mbox_sts[0],
+						  mbox_sts[1], mbox_sts[2],
+						  mbox_sts[3], mbox_sts[4]));
+				opcode = mbox_sts[1] >> 16;
+				if ((opcode == MBOX_CMD_SET_PORT_CONFIG) ||
+				    (opcode == MBOX_CMD_PORT_RESET)) {
+					set_bit(DPC_POST_IDC_ACK,
+						&ha->dpc_flags);
+					ha->idc_info.request_desc = mbox_sts[1];
+					ha->idc_info.info1 = mbox_sts[2];
+					ha->idc_info.info2 = mbox_sts[3];
+					ha->idc_info.info3 = mbox_sts[4];
+					qla4xxx_wake_dpc(ha);
+				}
+			}
+			break;
+		}
+
+		case MBOX_ASTS_IDC_COMPLETE:
+			if (is_qla8032(ha)) {
+				DEBUG2(ql4_printk(KERN_INFO, ha,
+						  "scsi%ld: AEN %04x, mbox_sts[1]=%08x, mbox_sts[2]=%08x, mbox_sts[3]=%08x, mbox_sts[4]=%08x\n",
+						  ha->host_no, mbox_sts[0],
+						  mbox_sts[1], mbox_sts[2],
+						  mbox_sts[3], mbox_sts[4]));
+				DEBUG2(ql4_printk(KERN_INFO, ha,
+						  "scsi:%ld: AEN %04x IDC Complete notification\n",
+						  ha->host_no, mbox_sts[0]));
+			}
+			break;
+
 		default:
 			DEBUG2(printk(KERN_WARNING
 				      "scsi%ld: AEN %04x UNKNOWN\n",

+ 33 - 0
drivers/scsi/qla4xxx/ql4_mbx.c

@@ -1968,3 +1968,36 @@ int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param)
 exit_set_param:
 	return status;
 }
+
+/**
+ * qla4_83xx_post_idc_ack - post IDC ACK
+ * @ha: Pointer to host adapter structure.
+ *
+ * Posts IDC ACK for IDC Request Notification AEN.
+ **/
+int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha)
+{
+	uint32_t mbox_cmd[MBOX_REG_COUNT];
+	uint32_t mbox_sts[MBOX_REG_COUNT];
+	int status;
+
+	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
+	memset(&mbox_sts, 0, sizeof(mbox_sts));
+
+	mbox_cmd[0] = MBOX_CMD_IDC_ACK;
+	mbox_cmd[1] = ha->idc_info.request_desc;
+	mbox_cmd[2] = ha->idc_info.info1;
+	mbox_cmd[3] = ha->idc_info.info2;
+	mbox_cmd[4] = ha->idc_info.info3;
+
+	status = qla4xxx_mailbox_command(ha, MBOX_REG_COUNT, MBOX_REG_COUNT,
+					 mbox_cmd, mbox_sts);
+	if (status == QLA_ERROR)
+		ql4_printk(KERN_ERR, ha, "%s: failed status %04X\n", __func__,
+			   mbox_sts[0]);
+	else
+	       DEBUG2(ql4_printk(KERN_INFO, ha, "%s: IDC ACK posted\n",
+				 __func__));
+
+	return status;
+}

+ 4 - 0
drivers/scsi/qla4xxx/ql4_os.c

@@ -3398,6 +3398,10 @@ static void qla4xxx_do_dpc(struct work_struct *work)
 			ql4_printk(KERN_INFO, ha, "HW State: FAILED\n");
 			qla4_8xxx_device_state_handler(ha);
 		}
+
+		if (test_and_clear_bit(DPC_POST_IDC_ACK, &ha->dpc_flags))
+			qla4_83xx_post_idc_ack(ha);
+
 		if (test_and_clear_bit(DPC_HA_NEED_QUIESCENT, &ha->dpc_flags)) {
 			qla4_8xxx_need_qsnt_handler(ha);
 		}