From 7edd9a7b28f57d8a5bcdb1a0def2aa09d1dd49d4 Mon Sep 17 00:00:00 2001 From: Karen Higgins Date: Mon, 21 Mar 2011 03:34:27 -0700 Subject: [SCSI] qla4xxx: cleanup DDB relogin logic during initialization Driver has capability to add device dynamically and present them to OS, driver no longer need to wait for DDBs to come online during driver initialization. Driver still issues a relogin for DDBs that are not online, but no longer wait for DDB to come online. Signed-off-by: Vikas Chaudhary Signed-off-by: Karen Higgins Reviewed-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/qla4xxx/ql4_init.c | 183 +++++++--------------------------------- 1 file changed, 31 insertions(+), 152 deletions(-) (limited to 'drivers/scsi/qla4xxx/ql4_init.c') diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 22fc57e2bc05..bf1c30b17a82 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c @@ -723,13 +723,38 @@ int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err) return relogin; } +static void qla4xxx_flush_AENS(struct scsi_qla_host *ha) +{ + unsigned long wtime; + + /* Flush the 0x8014 AEN from the firmware as a result of + * Auto connect. We are basically doing get_firmware_ddb() + * to determine whether we need to log back in or not. + * Trying to do a set ddb before we have processed 0x8014 + * will result in another set_ddb() for the same ddb. In other + * words there will be stale entries in the aen_q. + */ + wtime = jiffies + (2 * HZ); + do { + if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS) + if (ha->firmware_state & (BIT_2 | BIT_0)) + return; + + if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) + qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); + + msleep(1000); + } while (!time_after_eq(jiffies, wtime)); +} + /** - * qla4xxx_configure_ddbs - builds driver ddb list + * qla4xxx_build_ddb_list - builds driver ddb list * @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 * a device state of SESSION_ACTIVE. + * A relogin (set_ddb) is issued for DDBs that are not online. **/ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) { @@ -744,6 +769,8 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) uint32_t ipv6_device; uint32_t new_tgt; + qla4xxx_flush_AENS(ha); + fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), &fw_ddb_entry_dma, GFP_KERNEL); if (fw_ddb_entry == NULL) { @@ -847,144 +874,6 @@ exit_build_ddb_list_no_free: return status; } -struct qla4_relog_scan { - int halt_wait; - uint32_t conn_err; - uint32_t fw_ddb_index; - uint32_t next_fw_ddb_index; - uint32_t fw_ddb_device_state; -}; - -static int qla4_test_rdy(struct scsi_qla_host *ha, struct qla4_relog_scan *rs) -{ - struct ddb_entry *ddb_entry; - - if (qla4_is_relogin_allowed(ha, rs->conn_err)) { - /* We either have a device that is in - * the process of relogging in or a - * device that is waiting to be - * relogged in */ - rs->halt_wait = 0; - - ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, - rs->fw_ddb_index); - if (ddb_entry == NULL) - return QLA_ERROR; - - if (ddb_entry->dev_scan_wait_to_start_relogin != 0 - && time_after_eq(jiffies, - ddb_entry-> - dev_scan_wait_to_start_relogin)) - { - ddb_entry->dev_scan_wait_to_start_relogin = 0; - qla4xxx_set_ddb_entry(ha, rs->fw_ddb_index, 0); - } - } - return QLA_SUCCESS; -} - -static int qla4_scan_for_relogin(struct scsi_qla_host *ha, - struct qla4_relog_scan *rs) -{ - int error; - - /* scan for relogins - * ----------------- */ - for (rs->fw_ddb_index = 0; rs->fw_ddb_index < MAX_DDB_ENTRIES; - rs->fw_ddb_index = rs->next_fw_ddb_index) { - if (qla4xxx_get_fwddb_entry(ha, rs->fw_ddb_index, NULL, 0, - NULL, &rs->next_fw_ddb_index, - &rs->fw_ddb_device_state, - &rs->conn_err, NULL, NULL) - == QLA_ERROR) - return QLA_ERROR; - - if (rs->fw_ddb_device_state == DDB_DS_LOGIN_IN_PROCESS) - rs->halt_wait = 0; - - if (rs->fw_ddb_device_state == DDB_DS_SESSION_FAILED || - rs->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE) { - error = qla4_test_rdy(ha, rs); - if (error) - return error; - } - - /* We know we've reached the last device when - * next_fw_ddb_index is 0 */ - if (rs->next_fw_ddb_index == 0) - break; - } - return QLA_SUCCESS; -} - -/** - * qla4xxx_devices_ready - wait for target devices to be logged in - * @ha: pointer to adapter structure - * - * This routine waits up to ql4xdiscoverywait seconds - * F/W database during driver load time. - **/ -static int qla4xxx_devices_ready(struct scsi_qla_host *ha) -{ - int error; - unsigned long discovery_wtime; - struct qla4_relog_scan rs; - - discovery_wtime = jiffies + (ql4xdiscoverywait * HZ); - - DEBUG(printk("Waiting (%d) for devices ...\n", ql4xdiscoverywait)); - do { - /* poll for AEN. */ - qla4xxx_get_firmware_state(ha); - if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) { - /* Set time-between-relogin timer */ - qla4xxx_process_aen(ha, RELOGIN_DDB_CHANGED_AENS); - } - - /* if no relogins active or needed, halt discvery wait */ - rs.halt_wait = 1; - - error = qla4_scan_for_relogin(ha, &rs); - - if (rs.halt_wait) { - DEBUG2(printk("scsi%ld: %s: Delay halted. Devices " - "Ready.\n", ha->host_no, __func__)); - return QLA_SUCCESS; - } - - msleep(2000); - } while (!time_after_eq(jiffies, discovery_wtime)); - - DEBUG3(qla4xxx_get_conn_event_log(ha)); - - return QLA_SUCCESS; -} - -static void qla4xxx_flush_AENS(struct scsi_qla_host *ha) -{ - unsigned long wtime; - - /* Flush the 0x8014 AEN from the firmware as a result of - * Auto connect. We are basically doing get_firmware_ddb() - * to determine whether we need to log back in or not. - * Trying to do a set ddb before we have processed 0x8014 - * will result in another set_ddb() for the same ddb. In other - * words there will be stale entries in the aen_q. - */ - wtime = jiffies + (2 * HZ); - do { - if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS) - if (ha->firmware_state & (BIT_2 | BIT_0)) - return; - - if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) - qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); - - msleep(1000); - } while (!time_after_eq(jiffies, wtime)); - -} - static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha) { uint16_t fw_ddb_index; @@ -996,22 +885,12 @@ static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha) for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; fw_ddb_index++) ha->fw_ddb_index_map[fw_ddb_index] = - (struct ddb_entry *)INVALID_ENTRY; + (struct ddb_entry *)INVALID_ENTRY; ha->tot_ddbs = 0; - qla4xxx_flush_AENS(ha); - - /* Wait for an AEN */ - qla4xxx_devices_ready(ha); - - /* - * First perform device discovery for active - * fw ddb indexes and build - * ddb list. - */ - if ((status = qla4xxx_build_ddb_list(ha)) == QLA_ERROR) - return status; + /* Perform device discovery and build ddb list. */ + status = qla4xxx_build_ddb_list(ha); return status; } -- cgit v1.2.3