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

Commit b9978769 authored by Andrew Vasquez's avatar Andrew Vasquez Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Ensure the timer and DPC routines complete prior to midlayer tear-down.



Since the routines can/will use resources such as devices and
rports that aren't valid after midlayer tear-down, correct this
potential race, by stopping the offending during the early stages
of the remove() callback.

Signed-off-by: default avatarAndrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent e612d465
Loading
Loading
Loading
Loading
+30 −19
Original line number Diff line number Diff line
@@ -1890,6 +1890,16 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
	ha->max_queues = 0;

probe_failed:
	if (base_vha->timer_active)
		qla2x00_stop_timer(base_vha);
	base_vha->flags.online = 0;
	if (ha->dpc_thread) {
		struct task_struct *t = ha->dpc_thread;

		ha->dpc_thread = NULL;
		kthread_stop(t);
	}

	qla2x00_free_device(base_vha);

	scsi_host_put(base_vha->host);
@@ -1923,10 +1933,30 @@ qla2x00_remove_one(struct pci_dev *pdev)

	set_bit(UNLOADING, &base_vha->dpc_flags);

	qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);

	qla2x00_dfs_remove(base_vha);

	qla84xx_put_chip(base_vha);

	/* Disable timer */
	if (base_vha->timer_active)
		qla2x00_stop_timer(base_vha);

	base_vha->flags.online = 0;

	/* Kill the kernel thread for this host */
	if (ha->dpc_thread) {
		struct task_struct *t = ha->dpc_thread;

		/*
		 * qla2xxx_wake_dpc checks for ->dpc_thread
		 * so we need to zero it out.
		 */
		ha->dpc_thread = NULL;
		kthread_stop(t);
	}

	qla2x00_free_sysfs_attr(base_vha);

	fc_remove_host(base_vha->host);
@@ -1955,25 +1985,6 @@ static void
qla2x00_free_device(scsi_qla_host_t *vha)
{
	struct qla_hw_data *ha = vha->hw;
	qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);

	/* Disable timer */
	if (vha->timer_active)
		qla2x00_stop_timer(vha);

	vha->flags.online = 0;

	/* Kill the kernel thread for this host */
	if (ha->dpc_thread) {
		struct task_struct *t = ha->dpc_thread;

		/*
		 * qla2xxx_wake_dpc checks for ->dpc_thread
		 * so we need to zero it out.
		 */
		ha->dpc_thread = NULL;
		kthread_stop(t);
	}

	if (ha->flags.fce_enabled)
		qla2x00_disable_fce_trace(vha, NULL, NULL);