Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86fbee86 authored by Lalit Chandivade's avatar Lalit Chandivade Committed by James Bottomley
Browse files

[SCSI] qla2xxx: ensure flash operation and host reset via sg_reset are mutually exclusive



The problem occurring is a hw-race where there's an outstanding read-flash
operation occurring while the chip is being reset (done via an sg_reset script).
After the chip is paused, the read-flash operation never completes and the
DPC thread, while trying to complete the reset, is never able to recover,
as the HW appears to be hung...

The fix is to wait for outstanding flash operation prior to doing a sg_reset -h.
And to wait for reset to complete before any flash operations.

Note, during the wait, if any of the operation (reset/flash) does not complete,
failure is returned to the upper layer. The upper layer either need to
fail or retry.

Signed-off-by: default avatarGiridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 1516ef44
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -281,6 +281,12 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
			return count;
		}

		if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
			qla_printk(KERN_WARNING, ha,
				"HBA not online, failing NVRAM update.\n");
			return -EAGAIN;
		}

		DEBUG2(qla_printk(KERN_INFO, ha,
		    "Reading flash region -- 0x%x/0x%x.\n",
		    ha->optrom_region_start, ha->optrom_region_size));
+45 −1
Original line number Diff line number Diff line
@@ -676,6 +676,50 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
	return (return_status);
}

/*
 * qla2x00_wait_for_reset_ready
 *    Wait till the HBA is online after going through
 *    <= MAX_RETRIES_OF_ISP_ABORT  or
 *    finally HBA is disabled ie marked offline or flash
 *    operations are in progress.
 *
 * Input:
 *     ha - pointer to host adapter structure
 *
 * Note:
 *    Does context switching-Release SPIN_LOCK
 *    (if any) before calling this routine.
 *
 * Return:
 *    Success (Adapter is online/no flash ops) : 0
 *    Failed  (Adapter is offline/disabled/flash ops in progress) : 1
 */
int
qla2x00_wait_for_reset_ready(scsi_qla_host_t *vha)
{
	int		return_status;
	unsigned long	wait_online;
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);

	wait_online = jiffies + (MAX_LOOP_TIMEOUT * HZ);
	while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
	    test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
	    test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
	    ha->optrom_state != QLA_SWAITING ||
	    ha->dpc_active) && time_before(jiffies, wait_online))
		msleep(1000);

	if (base_vha->flags.online &&  ha->optrom_state == QLA_SWAITING)
		return_status = QLA_SUCCESS;
	else
		return_status = QLA_FUNCTION_FAILED;

	DEBUG2(printk("%s return_status=%d\n", __func__, return_status));

	return return_status;
}

int
qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
{
@@ -1081,7 +1125,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
	qla_printk(KERN_INFO, ha,
	    "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun);

	if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS)
	if (qla2x00_wait_for_reset_ready(vha) != QLA_SUCCESS)
		goto eh_host_reset_lock;

	/*