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
qla2x00_initialize_adapter(scsi_qla_host_t *ha)
{
int rval;
uint8_t isp_init = 0;
uint8_t restart_risc = 0;
uint8_t retry;
uint32_t wait_time;
/* Clear adapter flags. */
ha->flags.online = FALSE;
......@@ -136,8 +136,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
qla_printk(KERN_INFO, ha, "Configure NVRAM parameters...\n");
qla2x00_nvram_config(ha);
ha->retry_count = ql2xretrycount;
qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n");
#if 0
......@@ -158,7 +156,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
*/
do {
restart_risc = 0;
isp_init = 0;
/* If firmware needs to be loaded */
if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) {
......@@ -177,21 +174,22 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
* value OR a minimum of 4 seconds OR If no
* 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);
/*
* Go setup flash database devices with proper
* Loop ID's.
* Wait at most MAX_TARGET RSCNs for a stable
* link.
*/
wait_time = 256;
do {
clear_bit(LOOP_RESYNC_NEEDED,
&ha->dpc_flags);
rval = qla2x00_configure_loop(ha);
if (test_bit(ISP_ABORT_NEEDED,
if (test_and_clear_bit(ISP_ABORT_NEEDED,
&ha->dpc_flags)) {
restart_risc = 1;
break;
}
......@@ -206,20 +204,22 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
LOOP_DOWN && retry--) {
goto check_fw_ready_again;
}
wait_time--;
} while (!atomic_read(&ha->loop_down_timer) &&
retry &&
(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)));
}
if (ha->mem_err) {
restart_risc = 1;
wait_time &&
(test_bit(LOOP_RESYNC_NEEDED,
&ha->dpc_flags)));
if (wait_time == 0)
rval = QLA_FUNCTION_FAILED;
if (ha->mem_err)
restart_risc = 1;
}
isp_init = 1;
}
} while (restart_risc && retry--);
if (isp_init) {
if (rval == QLA_SUCCESS) {
/* Retrieve firmware information */
qla2x00_get_fw_version(ha, &ha->fw_major_version,
&ha->fw_minor_version, &ha->fw_subminor_version,
......@@ -231,9 +231,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
ha->marker_needed = 0;
ha->flags.online = TRUE;
}
if (rval) {
} else {
DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__));
}
......@@ -1515,24 +1513,24 @@ static int
qla2x00_configure_loop(scsi_qla_host_t *ha)
{
int rval;
uint8_t rval1 = 0;
unsigned long flags, save_flags;
rval = QLA_SUCCESS;
/* Get Initiator ID */
if (qla2x00_configure_hba(ha)) {
DEBUG(printk("scsi(%ld): Unable to configure HBA.\n",
ha->host_no));
return (QLA_FUNCTION_FAILED);
if (test_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags)) {
rval = qla2x00_configure_hba(ha);
if (rval != QLA_SUCCESS) {
DEBUG(printk("scsi(%ld): Unable to configure HBA.\n",
ha->host_no));
return (rval);
}
}
save_flags = flags = ha->dpc_flags;
DEBUG(printk("scsi(%ld): Configure loop -- dpc flags =0x%lx\n",
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
* both at the same time.
......@@ -1563,50 +1561,32 @@ qla2x00_configure_loop(scsi_qla_host_t *ha)
set_bit(LOCAL_LOOP_UPDATE, &flags);
}
do {
if (test_bit(LOCAL_LOOP_UPDATE, &flags)) {
rval = 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);
}
if (test_bit(LOCAL_LOOP_UPDATE, &flags)) {
if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
rval = QLA_FUNCTION_FAILED;
} else {
rval = qla2x00_configure_local_loop(ha);
}
}
/* Isolate error status. */
if (rval & BIT_0) {
rval = 1;
if (rval == QLA_SUCCESS && test_bit(RSCN_UPDATE, &flags)) {
if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
rval = QLA_FUNCTION_FAILED;
} else {
rval = QLA_SUCCESS;
rval = qla2x00_configure_fabric(ha);
}
}
} while (rval != QLA_SUCCESS);
if (!atomic_read(&ha->loop_down_timer) &&
!(test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags))) {
qla2x00_config_os(ha);
/* If we found all devices then go ready */
if (!(test_bit(LOGIN_RETRY_NEEDED, &ha->dpc_flags))) {
if (rval == QLA_SUCCESS) {
if (atomic_read(&ha->loop_down_timer) ||
test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) {
rval = QLA_FUNCTION_FAILED;
} else {
qla2x00_config_os(ha);
atomic_set(&ha->loop_state, LOOP_READY);
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) {
......@@ -1638,7 +1618,6 @@ qla2x00_configure_loop(scsi_qla_host_t *ha)
*
* Returns:
* 0 = success.
* BIT_0 = error.
*/
static int
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;
uint8_t domain, area, al_pa;
rval = QLA_SUCCESS;
found_devs = 0;
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;
id_list = pci_alloc_consistent(ha->pdev, MAX_ID_LIST_SIZE,
&id_list_dma);
......@@ -1687,7 +1656,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
"Memory Allocation failed - port_list");
ha->mem_err++;
return (BIT_0);
return (QLA_MEMORY_ALLOC_FAILED);
}
memset(id_list, 0, MAX_ID_LIST_SIZE);
......@@ -1696,8 +1665,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
/* Get list of logged in devices. */
rval = qla2x00_get_id_list(ha, id_list, id_list_dma, &entries);
if (rval) {
rval = BIT_0;
if (rval != QLA_SUCCESS) {
goto cleanup_allocation;
}
......@@ -1709,7 +1677,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
/* Allocate temporary fcport for any new fcports discovered. */
new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL);
if (new_fcport == NULL) {
rval = BIT_0;
rval = QLA_MEMORY_ALLOC_FAILED;
goto cleanup_allocation;
}
new_fcport->flags &= ~FCF_FABRIC_DEVICE;
......@@ -1802,7 +1770,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
fcport = new_fcport;
new_fcport = qla2x00_alloc_fcport(ha, GFP_KERNEL);
if (new_fcport == NULL) {
rval = BIT_0;
rval = QLA_MEMORY_ALLOC_FAILED;
goto cleanup_allocation;
}
new_fcport->flags &= ~FCF_FABRIC_DEVICE;
......@@ -1819,7 +1787,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *ha)
if (new_fcport)
kfree(new_fcport);
if (rval & BIT_0) {
if (rval != QLA_SUCCESS) {
DEBUG2(printk("scsi(%ld): Configure local loop error exit: "
"rval=%x\n", ha->host_no, rval));
}
......@@ -2358,7 +2326,7 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
/* Mark devices that need re-synchronization. */
rval2 = qla2x00_device_resync(ha);
if (rval2 == QLA_RSCNS_HANDLED) {
/* No, point doing the scan, just continue. */
/* No point doing the scan, just continue. */
return (QLA_SUCCESS);
}
do {
......@@ -2508,7 +2476,6 @@ qla2x00_configure_fabric(scsi_qla_host_t *ha)
*
* Returns:
* 0 = success.
* BIT_0 = error.
*
* Context:
* Kernel context.
......@@ -3101,6 +3068,7 @@ int
qla2x00_loop_resync(scsi_qla_host_t *ha)
{
int rval;
uint32_t wait_time;
rval = QLA_SUCCESS;
......@@ -3109,6 +3077,8 @@ qla2x00_loop_resync(scsi_qla_host_t *ha)
clear_bit(ISP_ABORT_RETRY, &ha->dpc_flags);
if (ha->flags.online) {
if (!(rval = qla2x00_fw_ready(ha))) {
/* Wait at most MAX_TARGET RSCNs for a stable link. */
wait_time = 256;
do {
/* v2.19.05b6 */
atomic_set(&ha->loop_state, LOOP_UPDATE);
......@@ -3123,12 +3093,13 @@ qla2x00_loop_resync(scsi_qla_host_t *ha)
clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
qla2x00_configure_loop(ha);
wait_time--;
} while (!atomic_read(&ha->loop_down_timer) &&
!(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) &&
wait_time &&
(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)) {
......@@ -4260,6 +4231,7 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
uint8_t status = 0;
device_reg_t *reg;
unsigned long flags = 0;
uint32_t wait_time;
/* If firmware needs to be loaded */
if (qla2x00_isp_firmware(ha)) {
......@@ -4303,11 +4275,15 @@ qla2x00_restart_isp(scsi_qla_host_t *ha)
__func__,
status);)
ha->flags.online = TRUE;
/* Wait at most MAX_TARGET RSCNs for a stable link. */
wait_time = 256;
do {
clear_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
qla2x00_configure_loop(ha);
wait_time--;
} while (!atomic_read(&ha->loop_down_timer) &&
!(test_bit(ISP_ABORT_NEEDED, &ha->dpc_flags)) &&
wait_time &&
(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)
spin_lock_init(&ha->mbx_reg_lock);
spin_lock_init(&ha->list_lock);
ha->dpc_pid = -1;
init_completion(&ha->dpc_inited);
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