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

Commit fe1b806f authored by Chad Dupuis's avatar Chad Dupuis Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Refactor shutdown code so some functionality can be reused.

parent 50280c01
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -862,7 +862,7 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha)
}

void
qla2x00_free_sysfs_attr(scsi_qla_host_t *vha)
qla2x00_free_sysfs_attr(scsi_qla_host_t *vha, bool stop_beacon)
{
	struct Scsi_Host *host = vha->host;
	struct sysfs_entry *iter;
@@ -880,7 +880,7 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha)
		    iter->attr);
	}

	if (ha->beacon_blink_led == 1)
	if (stop_beacon && ha->beacon_blink_led == 1)
		ha->isp_ops->beacon_off(vha);
}

+1 −2
Original line number Diff line number Diff line
@@ -540,10 +540,9 @@ struct fc_function_template;
extern struct fc_function_template qla2xxx_transport_functions;
extern struct fc_function_template qla2xxx_transport_vport_functions;
extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *, bool);
extern void qla2x00_init_host_attr(scsi_qla_host_t *);
extern void qla2x00_alloc_sysfs_attr(scsi_qla_host_t *);
extern void qla2x00_free_sysfs_attr(scsi_qla_host_t *);
extern int qla2x00_loopback_test(scsi_qla_host_t *, struct msg_echo_lb *, uint16_t *);
extern int qla2x00_echo_test(scsi_qla_host_t *,
	struct msg_echo_lb *, uint16_t *);
+93 −77
Original line number Diff line number Diff line
@@ -2905,22 +2905,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
	return ret;
}

static void
qla2x00_stop_dpc_thread(scsi_qla_host_t *vha)
{
	struct qla_hw_data *ha = vha->hw;
	struct task_struct *t = ha->dpc_thread;

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

static void
qla2x00_shutdown(struct pci_dev *pdev)
{
@@ -2964,29 +2948,14 @@ qla2x00_shutdown(struct pci_dev *pdev)
	qla2x00_free_fw_dump(ha);
}

/* Deletes all the virtual ports for a given ha */
static void
qla2x00_remove_one(struct pci_dev *pdev)
qla2x00_delete_all_vps(struct qla_hw_data *ha, scsi_qla_host_t *base_vha)
{
	scsi_qla_host_t *base_vha, *vha;
	struct qla_hw_data  *ha;
	struct Scsi_Host *scsi_host;
	scsi_qla_host_t *vha;
	unsigned long flags;

	/*
	 * If the PCI device is disabled that means that probe failed and any
	 * resources should be have cleaned up on probe exit.
	 */
	if (!atomic_read(&pdev->enable_cnt))
		return;

	base_vha = pci_get_drvdata(pdev);
	ha = base_vha->hw;

	ha->flags.host_shutting_down = 1;

	set_bit(UNLOADING, &base_vha->dpc_flags);
	if (IS_QLAFX00(ha))
		qlafx00_driver_shutdown(base_vha, 20);

	mutex_lock(&ha->vport_lock);
	while (ha->cur_vport_count) {
		spin_lock_irqsave(&ha->vport_slock, flags);
@@ -2994,7 +2963,7 @@ qla2x00_remove_one(struct pci_dev *pdev)
		BUG_ON(base_vha->list.next == &ha->vp_list);
		/* This assumes first entry in ha->vp_list is always base vha */
		vha = list_first_entry(&base_vha->list, scsi_qla_host_t, list);
		scsi_host_get(vha->host);
		scsi_host = scsi_host_get(vha->host);

		spin_unlock_irqrestore(&ha->vport_slock, flags);
		mutex_unlock(&ha->vport_lock);
@@ -3005,27 +2974,12 @@ qla2x00_remove_one(struct pci_dev *pdev)
		mutex_lock(&ha->vport_lock);
	}
	mutex_unlock(&ha->vport_lock);

	if (IS_QLA8031(ha)) {
		ql_dbg(ql_dbg_p3p, base_vha, 0xb07e,
		    "Clearing fcoe driver presence.\n");
		if (qla83xx_clear_drv_presence(base_vha) != QLA_SUCCESS)
			ql_dbg(ql_dbg_p3p, base_vha, 0xb079,
			    "Error while clearing DRV-Presence.\n");
}

	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;

/* Stops all deferred work threads */
static void
qla2x00_destroy_deferred_work(struct qla_hw_data *ha)
{
	/* Flush the work queue and remove it */
	if (ha->wq) {
		flush_workqueue(ha->wq);
@@ -3059,27 +3013,12 @@ qla2x00_remove_one(struct pci_dev *pdev)
		ha->dpc_thread = NULL;
		kthread_stop(t);
	}
	qlt_remove_target(ha, base_vha);

	qla2x00_free_sysfs_attr(base_vha);

	fc_remove_host(base_vha->host);

	scsi_remove_host(base_vha->host);

	qla2x00_free_device(base_vha);

	scsi_host_put(base_vha->host);

	if (IS_QLA8044(ha)) {
		qla8044_idc_lock(ha);
		qla8044_clear_drv_active(base_vha);
		qla8044_idc_unlock(ha);
}

static void
qla2x00_unmap_iobases(struct qla_hw_data *ha)
{
	if (IS_QLA82XX(ha)) {
		qla82xx_idc_lock(ha);
		qla82xx_clear_drv_active(ha);
		qla82xx_idc_unlock(ha);

		iounmap((device_reg_t __iomem *)ha->nx_pcibase);
		if (!ql2xdbwr)
@@ -3097,6 +3036,84 @@ qla2x00_remove_one(struct pci_dev *pdev)
		if (IS_QLA83XX(ha) && ha->msixbase)
			iounmap(ha->msixbase);
	}
}

static void
qla2x00_clear_drv_active(scsi_qla_host_t *vha)
{
	struct qla_hw_data *ha = vha->hw;

	if (IS_QLA8044(ha)) {
		qla8044_idc_lock(ha);
		qla8044_clear_drv_active(vha);
		qla8044_idc_unlock(ha);
	} else if (IS_QLA82XX(ha)) {
		qla82xx_idc_lock(ha);
		qla82xx_clear_drv_active(ha);
		qla82xx_idc_unlock(ha);
	}
}

static void
qla2x00_remove_one(struct pci_dev *pdev)
{
	scsi_qla_host_t *base_vha;
	struct qla_hw_data  *ha;

	/*
	 * If the PCI device is disabled that means that probe failed and any
	 * resources should be have cleaned up on probe exit.
	 */
	if (!atomic_read(&pdev->enable_cnt))
		return;

	base_vha = pci_get_drvdata(pdev);
	ha = base_vha->hw;

	set_bit(UNLOADING, &base_vha->dpc_flags);

	if (IS_QLAFX00(ha))
		qlafx00_driver_shutdown(base_vha, 20);

	qla2x00_delete_all_vps(ha, base_vha);

	if (IS_QLA8031(ha)) {
		ql_dbg(ql_dbg_p3p, base_vha, 0xb07e,
		    "Clearing fcoe driver presence.\n");
		if (qla83xx_clear_drv_presence(base_vha) != QLA_SUCCESS)
			ql_dbg(ql_dbg_p3p, base_vha, 0xb079,
			    "Error while clearing DRV-Presence.\n");
	}

	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;

	qla2x00_destroy_deferred_work(ha);

	qlt_remove_target(ha, base_vha);

	qla2x00_free_sysfs_attr(base_vha, true);

	fc_remove_host(base_vha->host);

	scsi_remove_host(base_vha->host);

	qla2x00_free_device(base_vha);

	scsi_host_put(base_vha->host);

	qla2x00_clear_drv_active(base_vha);

	qla2x00_unmap_iobases(ha);

	pci_release_selected_regions(ha->pdev, ha->bars);
	kfree(ha);
@@ -3118,9 +3135,8 @@ qla2x00_free_device(scsi_qla_host_t *vha)
	if (vha->timer_active)
		qla2x00_stop_timer(vha);

	qla2x00_stop_dpc_thread(vha);

	qla25xx_delete_queues(vha);

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