From: David Somayajulu Subject: qla4xxx driver SLES 11 Beta6 update References: bnc#458186 This updates the qla4xxx driver with the following bug fixes: 1. Fix the handling of qla4xxx firmware Device DataBase Entry removal. 2. Fix the pass thru scsi_cmnd handling. This prevented our configuration tool SanSurfer from operating properly. 3. updates version to 5.01.00-k8_sles11-04 and quite some whitespace fixes. Signed-off-by: David Somayajulu Signed-off-by: Hannes Reinecke diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h index 5764a25..2b5af89 100644 --- a/drivers/scsi/qla4xxx/ql4_def.h +++ b/drivers/scsi/qla4xxx/ql4_def.h @@ -144,7 +144,6 @@ #define RESET_FIRMWARE_TOV 30 #define LOGOUT_TOV 10 #define IOCB_TOV_MARGIN 10 -#define ISNS_DEREG_TOV 5 #define MAX_RESET_HA_RETRIES 2 @@ -232,6 +231,8 @@ struct ddb_entry { uint8_t ip_addr[ISCSI_IPADDR_SIZE]; uint8_t iscsi_name[ISCSI_NAME_SIZE]; /* 72 x48 */ uint8_t iscsi_alias[0x20]; + uint8_t isid[6]; + uint8_t rsrvd[2]; }; /* @@ -243,6 +244,8 @@ struct ddb_entry { * commands */ #define DDB_STATE_MISSING 2 /* Device logged off, trying * to re-login */ +#define DDB_STATE_REMOVED 3 /* The fw ddb_entry is freed + * the session can be destroyed */ /* * DDB flags. @@ -252,7 +255,7 @@ struct ddb_entry { * logged it out */ #define DF_SCAN_ISSUED 2 #define DF_OFFLINE 3 /* Offline Device */ -#define DF_DELETED 4 /* Device has been removed */ +#define DF_REMOVE 4 /* FW DDB is destroyed */ /* * Asynchronous Event Queue structure @@ -305,11 +308,10 @@ struct scsi_qla_host { #define DPC_RELOGIN_DEVICE 3 /* 0x00000008 */ #define DPC_RESET_HA_DESTROY_DDB_LIST 4 /* 0x00000010 */ #define DPC_RESET_HA_INTR 5 /* 0x00000020 */ -#define DPC_ISNS_RESTART 7 /* 0x00000080 */ #define DPC_AEN 9 /* 0x00000200 */ #define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */ #define DPC_OFFLINE_DEVICE 16 /* 0x00010000 */ -#define DPC_DELETE_DEVICE 17 /* 0x00020000 */ +#define DPC_REMOVE_DEVICE 17 /* 0x00020000 */ uint16_t iocb_cnt; uint16_t iocb_hiwat; diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 3b38d79..cc17469 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -14,7 +14,7 @@ /* link auto negotiation normally takes roughly 2s. */ /* If we don't have link in 3 times that period quit. */ -#define QLA4XXX_LINK_UP_DELAY 6 +#define QLA4XXX_LINK_UP_DELAY 6 /* * QLogic ISP4xxx Hardware Support Function Prototypes. @@ -63,8 +63,10 @@ void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry) list_del_init(&ddb_entry->list); /* Remove device pointer from index mapping arrays */ - ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = NULL; - ha->tot_ddbs--; + if (!QL_DDB_STATE_REMOVED(ddb_entry)) { + ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = NULL; + ha->tot_ddbs--; + } /* Free memory and scsi-ml struct for device entry */ qla4xxx_destroy_sess(ddb_entry); @@ -267,14 +269,6 @@ static int qla4xxx_fw_ready(struct scsi_qla_host *ha) (ha->addl_fw_state & FW_ADDSTATE_LINK_UP) != 0 ? "UP" : "DOWN")); - DEBUG2(dev_info(&ha->pdev->dev, - "scsi%ld: %s: iSNS Service " - "Started %s\n", - ha->host_no, __func__, - (ha->addl_fw_state & - FW_ADDSTATE_ISNS_SVC_ENABLED) != 0 ? - "YES" : "NO")); - ready = 1; break; } @@ -341,6 +335,7 @@ static void qla4xxx_fill_ddb(struct ddb_entry *ddb_entry, ddb_entry->port = le16_to_cpu(fw_ddb_entry->port); ddb_entry->tpgt = le32_to_cpu(fw_ddb_entry->tgt_portal_grp); + memcpy(ddb_entry->isid, fw_ddb_entry->isid, sizeof(ddb_entry->isid)); memcpy(&ddb_entry->iscsi_name[0], &fw_ddb_entry->iscsi_name[0], min(sizeof(ddb_entry->iscsi_name), sizeof(fw_ddb_entry->iscsi_name))); @@ -396,7 +391,7 @@ struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha, * @ha: Pointer to host adapter structure. * * This routine searches for all valid firmware ddb entries and builds - * an internal ddb list. Ddbs that are considered valid are those with + * an internal ddb list. Ddbs that are considered valid are those with * a device state of SESSION_ACTIVE. **/ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) @@ -486,19 +481,6 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) qla4xxx_fill_ddb(ddb_entry, fw_ddb_entry); ddb_entry->fw_ddb_device_state = ddb_state; - if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { - atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); - dev_info(&ha->pdev->dev, - "scsi%ld: %s: ddb[%d] os[%d] marked ONLINE\n", - ha->host_no, __func__, ddb_entry->fw_ddb_index, - ddb_entry->os_target_id); - } else { - atomic_set(&ddb_entry->state, DDB_STATE_MISSING); - dev_info(&ha->pdev->dev, - "scsi%ld: %s: ddb[%d] os[%d] marked MISSING\n", - ha->host_no, __func__, ddb_entry->fw_ddb_index, - ddb_entry->os_target_id); - } DEBUG6(dev_info(&ha->pdev->dev, "%s: DDB[%d] osIdx = %d State %04x" " ConnErr %08x %d.%d.%d.%d:%04d \"%s\"\n", __func__, fw_ddb_index, ddb_entry->os_target_id, ddb_state, conn_err, @@ -714,7 +696,7 @@ static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha) } /** - * qla4xxx_update_ddb_list - update the driver ddb list + * qla4xxx_reinitialize_ddb_list - update the driver ddb list * @ha: pointer to host adapter structure. * * This routine obtains device information from the F/W database after @@ -735,11 +717,12 @@ int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host *ha) /* Update the device information for all devices. */ list_for_each_entry_safe(ddb_entry, detemp, &ha->ddb_list, list) { - if (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, - fw_ddb_entry, fw_ddb_entry_dma, NULL, NULL, - &ddb_entry->fw_ddb_device_state, NULL, - &ddb_entry->tcp_source_port_num, - &ddb_entry->connection_id) == QLA_SUCCESS) { + if (!QL_DDB_STATE_REMOVED(ddb_entry) && + (qla4xxx_get_fwddb_entry(ha, ddb_entry->fw_ddb_index, + fw_ddb_entry, fw_ddb_entry_dma, NULL, NULL, + &ddb_entry->fw_ddb_device_state, NULL, + &ddb_entry->tcp_source_port_num, + &ddb_entry->connection_id) == QLA_SUCCESS)) { qla4xxx_fill_ddb(ddb_entry, fw_ddb_entry); @@ -1192,8 +1175,13 @@ static void qla4xxx_add_device_dynamically(struct scsi_qla_host *ha, } list_for_each_entry(ddb_entry, &ha->ddb_list, list) { - if (memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name, - ISCSI_NAME_SIZE) == 0) { + if ((memcmp(ddb_entry->iscsi_name, fw_ddb_entry->iscsi_name, + ISCSI_NAME_SIZE) == 0) && + (ddb_entry->tpgt == + le32_to_cpu(fw_ddb_entry->tgt_portal_grp)) && + (memcmp(ddb_entry->isid, fw_ddb_entry->isid, + sizeof(ddb_entry->isid)) == 0) && + !QL_DDB_STATE_REMOVED(ddb_entry)) { found = 1; DEBUG6(dev_info(&ha->pdev->dev, "%s found target ddb = 0x%p" diff --git a/drivers/scsi/qla4xxx/ql4_inline.h b/drivers/scsi/qla4xxx/ql4_inline.h index bdf2475..a93b817 100644 --- a/drivers/scsi/qla4xxx/ql4_inline.h +++ b/drivers/scsi/qla4xxx/ql4_inline.h @@ -55,8 +55,8 @@ static inline void qla4xxx_check_for_clear_ddb(struct scsi_qla_host *ha, dev_info(&ha->pdev->dev, "%s: ddb[%d] os[%d] freed\n", __func__, ddb_entry->fw_ddb_index, ddb_entry->os_target_id); - set_bit(DF_DELETED, &ddb_entry->flags); - set_bit(DPC_DELETE_DEVICE, &ha->dpc_flags); + set_bit(DF_REMOVE, &ddb_entry->flags); + set_bit(DPC_REMOVE_DEVICE, &ha->dpc_flags); queue_work(ha->dpc_thread, &ha->dpc_work); } } diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index bfe4d1e..67071d6 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -27,12 +27,6 @@ static void qla4xxx_build_scsi_iocbs(struct srb *srb, cmd = srb->cmd; ha = srb->ha; - if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { - /* No data being transferred */ - cmd_entry->ttlByteCnt = __constant_cpu_to_le32(0); - return; - } - avail_dsds = COMMAND_SEG; cur_dsd = (struct data_seg_a64 *) & (cmd_entry->dataseg[0]); @@ -43,6 +37,12 @@ static void qla4xxx_build_scsi_iocbs(struct srb *srb, return; } + if (!scsi_bufflen(cmd) || cmd->sc_data_direction == DMA_NONE) { + /* No data being transferred */ + cmd_entry->ttlByteCnt = __constant_cpu_to_le32(0); + return; + } + scsi_for_each_sg(cmd, sg, tot_dsds, i) { dma_addr_t sle_dma; @@ -155,7 +155,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) int_to_scsilun(cmd->device->lun, &cmd_entry->lun); cmd_entry->cmdSeqNum = cpu_to_le32(ddb_entry->CmdSn); - cmd_entry->ttlByteCnt = cpu_to_le32(scsi_bufflen(cmd)); + memcpy(cmd_entry->cdb, cmd->cmnd, cmd->cmd_len); cmd_entry->dataSegCnt = cpu_to_le16(tot_dsds); cmd_entry->hdr.entryCount = req_cnt; @@ -165,6 +165,9 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) * transferred, as the data direction bit is sometimed filled * in when there is no data to be transferred */ cmd_entry->control_flags = CF_NO_DATA; + + cmd_entry->ttlByteCnt = cpu_to_le32(scsi_bufflen(cmd)); + if (scsi_bufflen(cmd)) { if (cmd->sc_data_direction == DMA_TO_DEVICE) cmd_entry->control_flags = CF_WRITE; @@ -203,7 +206,7 @@ int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb) wmb(); /* - * Check to see if adapter is online before placing request on + * Check to see if adapter is online before placing request on * request queue. If a reset occurs and a request is in the queue, * the firmware will still attempt to process the request, retrieving * garbage for pointers. @@ -243,4 +246,3 @@ queuing_error: return QLA_ERROR; } - diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 2efcc20..a5cd40d 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -111,6 +111,8 @@ static struct scsi_host_template qla4xxx_driver_template = { .slave_alloc = qla4xxx_slave_alloc, .slave_destroy = qla4xxx_slave_destroy, + .target_destroy = qla4xxx_target_destroy, + .this_id = -1, .cmd_per_lun = 3, .use_clustering = ENABLE_CLUSTERING, @@ -290,7 +292,8 @@ void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry) if (ddb_entry->conn) { QL_ISCSI_IF_DESTROY_SESSION_DONE(ddb_entry); QL_ISCSI_DESTROY_CONN(ddb_entry); - iscsi_remove_session(ddb_entry->sess); + if (!QL_DDB_STATE_REMOVED(ddb_entry)) + iscsi_remove_session(ddb_entry->sess); } iscsi_free_session(ddb_entry->sess); } @@ -385,7 +388,8 @@ void qla4xxx_mark_device_missing(struct scsi_qla_host *ha, dev_info(&ha->pdev->dev, "%s: ddb[%d] os[%d] marked MISSING\n", __func__, ddb_entry->fw_ddb_index, ddb_entry->os_target_id); - qla4xxx_conn_stop(ddb_entry->conn, STOP_CONN_RECOVER); + if (ddb_entry->conn) + qla4xxx_conn_stop(ddb_entry->conn, STOP_CONN_RECOVER); } static struct srb* qla4xxx_get_new_srb(struct scsi_qla_host *ha, @@ -444,7 +448,8 @@ static int qla4xxx_queuecommand(struct scsi_cmnd *cmd, int rval; if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { - if (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD) { + if ((atomic_read(&ddb_entry->state) == DDB_STATE_DEAD) || + QL_DDB_STATE_REMOVED(ddb_entry)) { cmd->result = DID_NO_CONNECT << 16; goto qc_fail_command; } @@ -602,8 +607,9 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) { /* Count down time between sending relogins */ if (adapter_up(ha) && - !test_bit(DF_RELOGIN, &ddb_entry->flags) && - atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { + !test_bit(DF_RELOGIN, &ddb_entry->flags) && + !QL_DDB_STATE_REMOVED(ddb_entry) && + atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { if (atomic_read(&ddb_entry->retry_relogin_timer) != INVALID_ENTRY) { if (atomic_read(&ddb_entry->retry_relogin_timer) @@ -626,15 +632,16 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) /* Wait for relogin to timeout */ if (atomic_read(&ddb_entry->relogin_timer) && - (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) { + (atomic_dec_and_test(&ddb_entry->relogin_timer) != 0)) { /* * If the relogin times out and the device is * still NOT ONLINE then try and relogin again. */ if (atomic_read(&ddb_entry->state) != - DDB_STATE_ONLINE && - ddb_entry->fw_ddb_device_state == - DDB_DS_SESSION_FAILED) { + DDB_STATE_ONLINE && + !QL_DDB_STATE_REMOVED(ddb_entry) && + ddb_entry->fw_ddb_device_state == + DDB_DS_SESSION_FAILED) { /* Reset retry relogin timer */ atomic_inc(&ddb_entry->relogin_retry_count); DEBUG2(printk("scsi%ld: index[%d] relogin" @@ -678,6 +685,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || + test_bit(DPC_REMOVE_DEVICE, &ha->dpc_flags) || QL_DPC_OFFLINE_SET(ha) || test_bit(DPC_AEN, &ha->dpc_flags)) && ha->dpc_thread) { @@ -1061,31 +1069,7 @@ static QL_DECLARE_DPC(qla4xxx_do_dpc, data) qla4xxx_check_dev_offline(ha); - if (test_and_clear_bit(DPC_DELETE_DEVICE, &ha->dpc_flags)) { - list_for_each_entry_safe(ddb_entry, dtemp, - &ha->ddb_list, list) { - if (test_and_clear_bit(DF_DELETED, - &ddb_entry->flags)) { - if (atomic_read(&ddb_entry->state) == - DDB_STATE_DEAD) { - dev_info(&ha->pdev->dev, - "%s: ddb[%d] os[%d] - " - "delete\n", - __func__, - ddb_entry->fw_ddb_index, - ddb_entry->os_target_id); - } else { - dev_info(&ha->pdev->dev, - "%s: ddb[%d] os[%d] - " - "ddb state not dead but" - " marked for delete\n", - __func__, - ddb_entry->fw_ddb_index, - ddb_entry->os_target_id); - } - } - } - } + qla4xxx_remove_device(ha); /* ---- relogin device? --- */ if (adapter_up(ha) && @@ -1093,6 +1077,7 @@ static QL_DECLARE_DPC(qla4xxx_do_dpc, data) list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) { if (test_and_clear_bit(DF_RELOGIN, &ddb_entry->flags) && + !QL_DDB_STATE_REMOVED(ddb_entry) && (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)) qla4xxx_relogin_device(ha, ddb_entry); @@ -1181,7 +1166,6 @@ static int qla4xxx_iospace_config(struct scsi_qla_host *ha) if (!(mmio_flags & IORESOURCE_MEM)) { dev_err(&ha->pdev->dev, "region #0 not an MMIO resource, aborting\n"); - goto iospace_error_exit; } if (mmio_len < MIN_IOBASE_LEN) { @@ -1336,7 +1320,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, /* Start timer thread. */ qla4xxx_start_timer(ha, qla4xxx_timer, 1); - set_bit(AF_INIT_DONE, &ha->flags); +// set_bit(AF_INIT_DONE, &ha->flags); pci_set_drvdata(pdev, ha); @@ -1382,7 +1366,7 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, DEBUG2(dev_info(&ha->pdev->dev, "listhead=%p, done adding ha=%p i=%d\n", &qla4xxx_hostlist, &ha->node, ha->instance)); -// set_bit(AF_INIT_DONE, &ha->flags); + set_bit(AF_INIT_DONE, &ha->flags); dev_info(&ha->pdev->dev, "%s: AF_INIT_DONE\n", __func__); return 0; @@ -1465,6 +1449,7 @@ static int qla4xxx_slave_alloc(struct scsi_device *sdev) if (sess) { sdev->hostdata = sess->dd_data; + QL_SET_SDEV_HOSTDATA(sdev, sess); return 0; } return FAILED; diff --git a/drivers/scsi/qla4xxx/ql4_os.h b/drivers/scsi/qla4xxx/ql4_os.h index 71c3da0..c96ab8f 100644 --- a/drivers/scsi/qla4xxx/ql4_os.h +++ b/drivers/scsi/qla4xxx/ql4_os.h @@ -44,13 +44,16 @@ iscsi_unblock_session(ddb_entry->sess) #define QL_ISCSI_ALLOC_SESSION(ha, trans) \ iscsi_alloc_session(ha->host, trans, sizeof(struct ddb_entry)) +#define QL_SET_SDEV_HOSTDATA(sdev, sess) +#define QL_DDB_STATE_REMOVED(ddb_entry) 0 #define QL_MISC_INIT 0 #define QL_MISC_EXIT #define qla4xxx_check_dev_offline(ha) #define qla4xxx_proc_info NULL +#define qla4xxx_target_destroy NULL #define QL_SET_SCSI_RESID(cmd, residual) scsi_set_resid(cmd, residual) #define QL_SCSI_BUFFLEN(cmd) scsi_bufflen(cmd) @@ -69,10 +72,8 @@ void dpc_func(struct work_struct *data) #define QL_INIT_SESSION_DATASIZE(sessiondata_size) -// .sessiondata_size = sizeof(struct ddb_entry), #define QL_INIT_HOST_TEMPLATE(host_template) -// .host_template = &qla4xxx_driver_template, QL_DECLARE_INTR_HANDLER(qla4xxx_intr_handler, irq, dev_id, regs); @@ -122,4 +123,22 @@ static inline void qla4xxx_srb_free_dma(struct scsi_qla_host *ha, cmd->SCp.ptr = NULL; } +static inline void qla4xxx_remove_device(struct scsi_qla_host *ha) +{ + struct ddb_entry *ddb_entry, *dtemp; + + if (test_and_clear_bit(DPC_REMOVE_DEVICE, &ha->dpc_flags)) { + list_for_each_entry_safe(ddb_entry, dtemp, + &ha->ddb_list, list) { + if (test_and_clear_bit(DF_REMOVE, &ddb_entry->flags)) { + dev_info(&ha->pdev->dev, + "%s: ddb[%d] os[%d] - removed\n", + __func__, ddb_entry->fw_ddb_index, + ddb_entry->os_target_id); + qla4xxx_free_ddb(ha, ddb_entry); + } + } + } +} + #endif /* _QLA4x_OS_H */ diff --git a/drivers/scsi/qla4xxx/ql4_version.h b/drivers/scsi/qla4xxx/ql4_version.h index d6ff1b7..073e401 100644 --- a/drivers/scsi/qla4xxx/ql4_version.h +++ b/drivers/scsi/qla4xxx/ql4_version.h @@ -5,5 +5,5 @@ * See LICENSE.qla4xxx for copyright and licensing details. */ -#define QLA4XXX_DRIVER_VERSION "5.01.00-k8_sles11-03" +#define QLA4XXX_DRIVER_VERSION "5.01.00-k8_sles11-04"