Commit f246122c authored by Andrew Vasquez's avatar Andrew Vasquez Committed by James Bottomley

[PATCH] PATCH [8/15] qla2xxx: Volatile topology fixes

  Fix problem where during ISP initialization in a volatile topology
  (i.e. fabric environment with large number of streaming RSCNs) the
  driver would loop indefinitely or hang due to termination of an
  invalid thread pid.

 drivers/scsi/qla2xxx/qla_init.c |  142 ++++++++++++++++------------------------
 drivers/scsi/qla2xxx/qla_os.c   |    1
 2 files changed, 60 insertions(+), 83 deletions(-)
parent c2e5b0c5
...@@ -102,9 +102,9 @@ int ...@@ -102,9 +102,9 @@ int
qla2x00_initialize_adapter(scsi_qla_host_t *ha) qla2x00_initialize_adapter(scsi_qla_host_t *ha)
{ {
int rval; int rval;
uint8_t isp_init = 0;
uint8_t restart_risc = 0; uint8_t restart_risc = 0;
uint8_t retry; uint8_t retry;
uint32_t wait_time;
/* Clear adapter flags. */ /* Clear adapter flags. */
ha->flags.online = FALSE; ha->flags.online = FALSE;
...@@ -136,8 +136,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ...@@ -136,8 +136,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n"); qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
qla2x00_nvram_config(ha); qla2x00_nvram_config(ha);
ha->retry_count = ql2xretrycount;
qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n"); qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n");
#if 0 #if 0
...@@ -158,7 +156,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ...@@ -158,7 +156,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
*/ */
do { do {
restart_risc = 0; restart_risc = 0;
isp_init = 0;
/* If firmware needs to be loaded */ /* If firmware needs to be loaded */
if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) { if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) {
...@@ -177,21 +174,22 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ...@@ -177,21 +174,22 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
* value OR a minimum of 4 seconds OR If no * value OR a minimum of 4 seconds OR If no
* cable, only 5 seconds. * cable, only 5 seconds.
*/ */
if (!qla2x00_fw_ready(ha)) { rval = qla2x00_fw_ready(ha);
if (rval == QLA_SUCCESS) {
clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags); clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
/* /*
* Go setup flash database devices with proper * Wait at most MAX_TARGET RSCNs for a stable
* Loop ID's. * link.
*/ */
wait_time = 256;
do { do {
clear_bit(LOOP_RESYNC_NEEDED, clear_bit(LOOP_RESYNC_NEEDED,
&ha->dpc_flags); &ha->dpc_flags);
rval = qla2x00_configure_loop(ha); rval = qla2x00_configure_loop(ha);
if (test_bit(ISP_ABORT_NEEDED, if (test_and_clear_bit(ISP_ABORT_NEEDED,
&ha->dpc_flags)) { &ha->dpc_flags)) {
restart_risc = 1; restart_risc = 1;
break; break;
} }
...@@ -206,20 +204,22 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ...@@ -206,20 +204,22 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
LOOP_DOWN && retry--) { LOOP_DOWN && retry--) {
goto check_fw_ready_again; goto check_fw_ready_again;
} }
wait_time--;
} while (!atomic_read(&ha->loop_down_timer) && } while (!atomic_read(&ha->loop_down_timer) &&
retry && retry &&
(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))); wait_time &&
} (test_bit(LOOP_RESYNC_NEEDED,
&ha->dpc_flags)));
if (ha->mem_err) {
restart_risc = 1; if (wait_time == 0)
rval = QLA_FUNCTION_FAILED;
if (ha->mem_err)
restart_risc = 1;
} }
isp_init = 1;
} }
} while (restart_risc && retry--); } while (restart_risc && retry--);
if (isp_init) { if (rval == QLA_SUCCESS) {
/* Retrieve firmware information */ /* Retrieve firmware information */
qla2x00_get_fw_version(ha, &ha->fw_major_version, qla2x00_get_fw_version(ha, &ha->fw_major_version,
&ha->fw_minor_version, &ha->fw_subminor_version, &ha->fw_minor_version, &ha->fw_subminor_version,
...@@ -231,9 +231,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha) ...@@ -231,9 +231,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
ha->marker_needed = 0; ha->marker_needed = 0;
ha->flags.online = TRUE; ha->flags.online = TRUE;
} } else {
if (rval) {
DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__)); DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__));
} }
...@@ -1515,24 +1513,24 @@ static int ...@@ -1515,24 +1513,24 @@ static int
qla2x00_configure_loop(scsi_qla_host_t *ha) qla2x00_configure_loop(scsi_qla_host_t *ha)
{ {
int rval; int rval;
uint8_t rval1 = 0;
unsigned long flags, save_flags; unsigned long flags, save_flags;
rval = QLA_SUCCESS; rval = QLA_SUCCESS;
/* Get Initiator ID */ /* Get Initiator ID */
if (qla2x00_configure_hba(ha)) { if (test_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags)) {
DEBUG(printk("scsi(%ld): Unable to configure HBA.\n", rval = qla2x00_configure_hba(ha);
ha->host_no)); if (rval != QLA_SUCCESS) {
return (QLA_FUNCTION_FAILED); DEBUG(printk("scsi(%ld): Unable to configure HBA.\n",
ha->host_no));
return (rval);
}
} }
save_flags = flags = ha->dpc_flags; save_flags = flags = ha->dpc_flags;
DEBUG(printk("scsi(%ld): Configure loop -- dpc flags =0x%lx\n", DEBUG(printk("scsi(%ld): Configure loop -- dpc flags =0x%lx\n",
ha->host_no, flags)); ha->host_no, flags));
/* dg 02/26/02 ha->dpc_flags &= ~(LOCAL_LOOP_UPDATE | RSCN_UPDATE); */
/* /*
* If we have both an RSCN and PORT UPDATE pending then handle them * If we have both an RSCN and PORT UPDATE pending then handle them
* both at the same time. * both at the same time.
...@@ -1563,50 +1561,32 @@ qla2x00_configure_loop(scsi_qla_host_t *ha) ...@@ -1563,50 +1561,32 @@ qla2x00_configure_loop(scsi_qla_host_t *ha)
set_bit(LOCAL_LOOP_UPDATE, &flags); set_bit(LOCAL_LOOP_UPDATE, &flags);
} }
do { if (test_bit(LOCAL_LOOP_UPDATE, &flags)) {
if (test_bit(LOCAL_LOOP_UPDATE, &flags)) { if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
rval = rval | qla2x00_configure_local_loop(ha); rval = QLA_FUNCTION_FAILED;
} } else {
rval = qla2x00_configure_local_loop(ha);
if (test_bit(RSCN_UPDATE, &flags)) {
rval1 = qla2x00_configure_fabric(ha);
if ((rval1 & BIT_0) && ha->sns_retry_cnt < 8) {
ha->sns_retry_cnt++;
set_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags);
}
} }
}
/* Isolate error status. */ if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) {
if (rval & BIT_0) { if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
rval = 1; rval = QLA_FUNCTION_FAILED;
} else { } else {
rval = QLA_SUCCESS; rval = qla2x00_configure_fabric(ha);
} }
}
} while (rval != QLA_SUCCESS); if (rval == QLA_SUCCESS) {
if (atomic_read(&ha->loop_down_timer) ||
if (!atomic_read(&ha->loop_down_timer) && test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
!(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))) { rval = QLA_FUNCTION_FAILED;
} else {
qla2x00_config_os(ha); qla2x00_config_os(ha);
/* If we found all devices then go ready */
if (!(test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags))) {
atomic_set(&ha->loop_state, LOOP_READY); atomic_set(&ha->loop_state, LOOP_READY);
DEBUG(printk("scsi(%ld): LOOP READY\n", ha->host_no)); DEBUG(printk("scsi(%ld): LOOP READY\n", ha->host_no));
} else {
if (test_bit(LOCAL_LOOP_UPDATE, &save_flags))
set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
if (test_bit(RSCN_UPDATE, &save_flags))
set_bit(RSCN_UPDATE, &ha->dpc_flags);
} }
} else {
DEBUG(printk("scsi(%ld): Loop down counter running= %d or "
"Resync needed- dpc flags= %ld\n",
ha->host_no,
atomic_read(&ha->loop_down_timer), ha->dpc_flags));
/* ???? dg 02/26/02 rval = 1; */
} }
if (rval) { if (rval) {
...@@ -1638,7 +1618,6 @@ qla2x00_configure_loop(scsi_qla_host_t *ha) ...@@ -1638,7 +1618,6 @@ qla2x00_configure_loop(scsi_qla_host_t *ha)
* *
* Returns: * Returns:
* 0 = success. * 0 = success.
* BIT_0 = error.
*/ */
static int static int
qla2x00_configure_local_loop(scsi_qla_host_t *ha) qla2x00_configure_local_loop(scsi_qla_host_t *ha)
...@@ -1663,19 +1642,9 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) ...@@ -1663,19 +1642,9 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
uint16_t loop_id; uint16_t loop_id;
uint8_t domain, area, al_pa; uint8_t domain, area, al_pa;
rval = QLA_SUCCESS;
found_devs = 0; found_devs = 0;
new_fcport = NULL; new_fcport = NULL;
/*
* No point in continuing if the loop is in a volatile state --
* reschedule LOCAL_LOOP_UPDATE for later processing
*/
if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
return (rval);
}
entries = MAX_FIBRE_DEVICES; entries = MAX_FIBRE_DEVICES;
id_list = pci_alloc_consistent(ha->pdev, MAX_ID_LIST_SIZE, id_list = pci_alloc_consistent(ha->pdev, MAX_ID_LIST_SIZE,
&id_list_dma); &id_list_dma);
...@@ -1687,7 +1656,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) ...@@ -1687,7 +1656,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
"Memory Allocation failed - port_list"); "Memory Allocation failed - port_list");
ha->mem_err++; ha->mem_err++;
return (BIT_0); return (QLA_MEMORY_ALLOC_FAILED);
} }
memset(id_list, 0, MAX_ID_LIST_SIZE); memset(id_list, 0, MAX_ID_LIST_SIZE);
...@@ -1696,8 +1665,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) ...@@ -1696,8 +1665,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
/* Get list of logged in devices. */ /* Get list of logged in devices. */
rval = qla2x00_get_id_list(ha, id_list, id_list_dma, &entries); rval = qla2x00_get_id_list(ha, id_list, id_list_dma, &entries);
if (rval) { if (rval != QLA_SUCCESS) {
rval = BIT_0;
goto cleanup_allocation; goto cleanup_allocation;
} }
...@@ -1709,7 +1677,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) ...@@ -1709,7 +1677,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
/* Allocate temporary fcport for any new fcports discovered. */ /* Allocate temporary fcport for any new fcports discovered. */
new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL); new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL);
if (new_fcport == NULL) { if (new_fcport == NULL) {
rval = BIT_0; rval = QLA_MEMORY_ALLOC_FAILED;
goto cleanup_allocation; goto cleanup_allocation;
} }
new_fcport->flags &= ~FCF_FABRIC_DEVICE; new_fcport->flags &= ~FCF_FABRIC_DEVICE;
...@@ -1802,7 +1770,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) ...@@ -1802,7 +1770,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
fcport = new_fcport; fcport = new_fcport;
new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL); new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL);
if (new_fcport == NULL) { if (new_fcport == NULL) {
rval = BIT_0; rval = QLA_MEMORY_ALLOC_FAILED;
goto cleanup_allocation; goto cleanup_allocation;
} }
new_fcport->flags &= ~FCF_FABRIC_DEVICE; new_fcport->flags &= ~FCF_FABRIC_DEVICE;
...@@ -1819,7 +1787,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha) ...@@ -1819,7 +1787,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
if (new_fcport) if (new_fcport)
kfree(new_fcport); kfree(new_fcport);
if (rval & BIT_0) { if (rval != QLA_SUCCESS) {
DEBUG2(printk("scsi(%ld): Configure local loop error exit: " DEBUG2(printk("scsi(%ld): Configure local loop error exit: "
"rval=%x\n", ha->host_no, rval)); "rval=%x\n", ha->host_no, rval));
} }
...@@ -2358,7 +2326,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) ...@@ -2358,7 +2326,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
/* Mark devices that need re-synchronization. */ /* Mark devices that need re-synchronization. */
rval2 = qla2x00_device_resync(ha); rval2 = qla2x00_device_resync(ha);
if (rval2 == QLA_RSCNS_HANDLED) { if (rval2 == QLA_RSCNS_HANDLED) {
/* No, point doing the scan, just continue. */ /* No point doing the scan, just continue. */
return (QLA_SUCCESS); return (QLA_SUCCESS);
} }
do { do {
...@@ -2508,7 +2476,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha) ...@@ -2508,7 +2476,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
* *
* Returns: * Returns:
* 0 = success. * 0 = success.
* BIT_0 = error.
* *
* Context: * Context:
* Kernel context. * Kernel context.
...@@ -3101,6 +3068,7 @@ int ...@@ -3101,6 +3068,7 @@ int
qla2x00_loop_resync(scsi_qla_host_t *ha) qla2x00_loop_resync(scsi_qla_host_t *ha)
{ {
int rval; int rval;
uint32_t wait_time;
rval = QLA_SUCCESS; rval = QLA_SUCCESS;
...@@ -3109,6 +3077,8 @@ qla2x00_loop_resync(scsi_qla_host_t *ha) ...@@ -3109,6 +3077,8 @@ qla2x00_loop_resync(scsi_qla_host_t *ha)
clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags); clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
if (ha->flags.online) { if (ha->flags.online) {
if (!(rval = qla2x00_fw_ready(ha))) { if (!(rval = qla2x00_fw_ready(ha))) {
/* Wait at most MAX_TARGET RSCNs for a stable link. */
wait_time = 256;
do { do {
/* v2.19.05b6 */ /* v2.19.05b6 */
atomic_set(&ha->loop_state, LOOP_UPDATE); atomic_set(&ha->loop_state, LOOP_UPDATE);
...@@ -3123,12 +3093,13 @@ qla2x00_loop_resync(scsi_qla_host_t *ha) ...@@ -3123,12 +3093,13 @@ qla2x00_loop_resync(scsi_qla_host_t *ha)
clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
qla2x00_configure_loop(ha); qla2x00_configure_loop(ha);
wait_time--;
} while (!atomic_read(&ha->loop_down_timer) && } while (!atomic_read(&ha->loop_down_timer) &&
!(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) && !(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) &&
wait_time &&
(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))); (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)));
} }
qla2x00_restart_queues(ha,TRUE); qla2x00_restart_queues(ha, TRUE);
} }
if (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) { if (test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) {
...@@ -4260,6 +4231,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) ...@@ -4260,6 +4231,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
uint8_t status = 0; uint8_t status = 0;
device_reg_t *reg; device_reg_t *reg;
unsigned long flags = 0; unsigned long flags = 0;
uint32_t wait_time;
/* If firmware needs to be loaded */ /* If firmware needs to be loaded */
if (qla2x00_isp_firmware(ha)) { if (qla2x00_isp_firmware(ha)) {
...@@ -4303,11 +4275,15 @@ qla2x00_restart_isp(scsi_qla_host_t *ha) ...@@ -4303,11 +4275,15 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
__func__, __func__,
status);) status);)
ha->flags.online = TRUE; ha->flags.online = TRUE;
/* Wait at most MAX_TARGET RSCNs for a stable link. */
wait_time = 256;
do { do {
clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
qla2x00_configure_loop(ha); qla2x00_configure_loop(ha);
wait_time--;
} while (!atomic_read(&ha->loop_down_timer) && } while (!atomic_read(&ha->loop_down_timer) &&
!(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) && !(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) &&
wait_time &&
(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))); (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)));
} }
......
...@@ -2024,6 +2024,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info) ...@@ -2024,6 +2024,7 @@ int qla2x00_probe_one(struct pci_dev *pdev, struct qla_board_info *brd_info)
spin_lock_init(&ha->mbx_reg_lock); spin_lock_init(&ha->mbx_reg_lock);
spin_lock_init(&ha->list_lock); spin_lock_init(&ha->list_lock);
ha->dpc_pid = -1;
init_completion(&ha->dpc_inited); init_completion(&ha->dpc_inited);
init_completion(&ha->dpc_exited); init_completion(&ha->dpc_exited);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment