[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>
This commit is contained in:
Nilesh Javali 2012-09-20 07:35:10 -04:00 committed by James Bottomley
parent a9b0347f4d
commit 320a61de9d
7 changed files with 91 additions and 1 deletions

View File

@ -259,4 +259,12 @@ struct qla83xx_minidump_entry_pollrdmwr {
uint32_t data_size; 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 #endif

View File

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

View File

@ -454,6 +454,10 @@ struct qla_flt_region {
#define MBOX_CMD_GET_CRASH_RECORD 0x0076 /* 4010 only */ #define MBOX_CMD_GET_CRASH_RECORD 0x0076 /* 4010 only */
#define MBOX_CMD_GET_CONN_EVENT_LOG 0x0077 #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 */ /* Mailbox status definitions */
#define MBOX_COMPLETION_STATUS 4 #define MBOX_COMPLETION_STATUS 4
#define MBOX_STS_BUSY 0x0007 #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_ND_PREFIX_IGNORED 0x802C
#define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED 0x802D #define MBOX_ASTS_IPV6_LCL_PREFIX_IGNORED 0x802D
#define MBOX_ASTS_ICMPV6_ERROR_MSG_RCVD 0x802E #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_INSERTED 0x8130
#define MBOX_ASTS_TXSCVR_REMOVED 0x8131 #define MBOX_ASTS_TXSCVR_REMOVED 0x8131

View File

@ -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_mbx_intr_enable(struct scsi_qla_host *ha);
int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param); 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_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 ql4xextended_error_logging;
extern int ql4xdontresethba; extern int ql4xdontresethba;

View File

@ -806,6 +806,43 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
" removed\n", ha->host_no, mbox_sts[0])); " removed\n", ha->host_no, mbox_sts[0]));
break; 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: default:
DEBUG2(printk(KERN_WARNING DEBUG2(printk(KERN_WARNING
"scsi%ld: AEN %04x UNKNOWN\n", "scsi%ld: AEN %04x UNKNOWN\n",

View File

@ -1968,3 +1968,36 @@ int qla4_8xxx_set_param(struct scsi_qla_host *ha, int param)
exit_set_param: exit_set_param:
return status; 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;
}

View File

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