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

Commit feafb7b1 authored by Arun Easi's avatar Arun Easi Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Fix vport delete issues

parent 2e4c3329
Loading
Loading
Loading
Loading
+15 −8
Original line number Diff line number Diff line
@@ -1838,26 +1838,33 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)

	qla24xx_disable_vp(vha);

	vha->flags.delete_progress = 1;

	fc_remove_host(vha->host);

	scsi_remove_host(vha->host);

	qla2x00_free_fcports(vha);
	if (vha->timer_active) {
		qla2x00_vp_stop_timer(vha);
		DEBUG15(printk(KERN_INFO "scsi(%ld): timer for the vport[%d]"
		" = %p has stopped\n", vha->host_no, vha->vp_idx, vha));
	}

	qla24xx_deallocate_vp_id(vha);

	/* No pending activities shall be there on the vha now */
	DEBUG(msleep(random32()%10));  /* Just to see if something falls on
					* the net we have placed below */

	BUG_ON(atomic_read(&vha->vref_count));

	qla2x00_free_fcports(vha);

	mutex_lock(&ha->vport_lock);
	ha->cur_vport_count--;
	clear_bit(vha->vp_idx, ha->vp_idx_map);
	mutex_unlock(&ha->vport_lock);

	if (vha->timer_active) {
		qla2x00_vp_stop_timer(vha);
		DEBUG15(printk ("scsi(%ld): timer for the vport[%d] = %p "
		    "has stopped\n",
		    vha->host_no, vha->vp_idx, vha));
        }

	if (vha->req->id && !ha->flags.cpu_affinity_enabled) {
		if (qla25xx_delete_req_que(vha, vha->req) != QLA_SUCCESS)
			qla_printk(KERN_WARNING, ha,
+0 −2
Original line number Diff line number Diff line
@@ -29,8 +29,6 @@
/* #define QL_DEBUG_LEVEL_17 */ /* Output EEH trace messages */
/* #define QL_DEBUG_LEVEL_18 */ /* Output T10 CRC trace messages */

/* #define QL_PRINTK_BUF */ /* Captures printk to buffer */

/*
* Macros use for debugging the driver.
*/
+20 −0
Original line number Diff line number Diff line
@@ -2641,6 +2641,7 @@ struct qla_hw_data {
#define MBX_UPDATE_FLASH_ACTIVE	3

	struct mutex vport_lock;        /* Virtual port synchronization */
	spinlock_t vport_slock; /* order is hardware_lock, then vport_slock */
	struct completion mbx_cmd_comp; /* Serialize mbx access */
	struct completion mbx_intr_comp;  /* Used for completion notification */
	struct completion dcbx_comp;	/* For set port config notification */
@@ -2828,6 +2829,7 @@ typedef struct scsi_qla_host {
		uint32_t	management_server_logged_in :1;
		uint32_t	process_response_queue	:1;
		uint32_t	difdix_supported:1;
		uint32_t	delete_progress:1;
	} flags;

	atomic_t	loop_state;
@@ -2922,6 +2924,8 @@ typedef struct scsi_qla_host {
	struct req_que *req;
	int		fw_heartbeat_counter;
	int		seconds_since_last_heartbeat;

	atomic_t	vref_count;
} scsi_qla_host_t;

/*
@@ -2932,6 +2936,22 @@ typedef struct scsi_qla_host {
	 test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \
	 atomic_read(&ha->loop_state) == LOOP_DOWN)

#define QLA_VHA_MARK_BUSY(__vha, __bail) do {		     \
	atomic_inc(&__vha->vref_count);			     \
	mb();						     \
	if (__vha->flags.delete_progress) {		     \
		atomic_dec(&__vha->vref_count);		     \
		__bail = 1;				     \
	} else {					     \
		__bail = 0;				     \
	}						     \
} while (0)

#define QLA_VHA_MARK_NOT_BUSY(__vha) do {		     \
	atomic_dec(&__vha->vref_count);			     \
} while (0)


#define qla_printk(level, ha, format, arg...) \
	dev_printk(level , &((ha)->pdev->dev) , format , ## arg)

+81 −13
Original line number Diff line number Diff line
@@ -69,21 +69,29 @@ qla2x00_ctx_sp_free(srb_t *sp)
{
	struct srb_ctx *ctx = sp->ctx;
	struct srb_iocb *iocb = ctx->u.iocb_cmd;
	struct scsi_qla_host *vha = sp->fcport->vha;

	del_timer_sync(&iocb->timer);
	kfree(iocb);
	kfree(ctx);
	mempool_free(sp, sp->fcport->vha->hw->srb_mempool);

	QLA_VHA_MARK_NOT_BUSY(vha);
}

inline srb_t *
qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
    unsigned long tmo)
{
	srb_t *sp;
	srb_t *sp = NULL;
	struct qla_hw_data *ha = vha->hw;
	struct srb_ctx *ctx;
	struct srb_iocb *iocb;
	uint8_t bail;

	QLA_VHA_MARK_BUSY(vha, bail);
	if (bail)
		return NULL;

	sp = mempool_alloc(ha->srb_mempool, GFP_KERNEL);
	if (!sp)
@@ -116,6 +124,8 @@ qla2x00_get_ctx_sp(scsi_qla_host_t *vha, fc_port_t *fcport, size_t size,
	iocb->timer.function = qla2x00_ctx_sp_timeout;
	add_timer(&iocb->timer);
done:
	if (!sp)
		QLA_VHA_MARK_NOT_BUSY(vha);
	return sp;
}

@@ -1777,11 +1787,15 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
		qla2x00_init_response_q_entries(rsp);
	}

	spin_lock_irqsave(&ha->vport_slock, flags);
	/* Clear RSCN queue. */
	list_for_each_entry(vp, &ha->vp_list, list) {
		vp->rscn_in_ptr = 0;
		vp->rscn_out_ptr = 0;
	}

	spin_unlock_irqrestore(&ha->vport_slock, flags);

	ha->isp_ops->config_rings(vha);

	spin_unlock_irqrestore(&ha->hardware_lock, flags);
@@ -3218,12 +3232,17 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
		/* Bypass virtual ports of the same host. */
		found = 0;
		if (ha->num_vhosts) {
			unsigned long flags;

			spin_lock_irqsave(&ha->vport_slock, flags);
			list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
				if (new_fcport->d_id.b24 == vp->d_id.b24) {
					found = 1;
					break;
				}
			}
			spin_unlock_irqrestore(&ha->vport_slock, flags);

			if (found)
				continue;
		}
@@ -3343,6 +3362,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
	struct qla_hw_data *ha = vha->hw;
	struct scsi_qla_host *vp;
	struct scsi_qla_host *tvp;
	unsigned long flags = 0;

	rval = QLA_SUCCESS;

@@ -3367,6 +3387,8 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
		/* Check for loop ID being already in use. */
		found = 0;
		fcport = NULL;

		spin_lock_irqsave(&ha->vport_slock, flags);
		list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
			list_for_each_entry(fcport, &vp->vp_fcports, list) {
				if (fcport->loop_id == dev->loop_id &&
@@ -3379,6 +3401,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
			if (found)
				break;
		}
		spin_unlock_irqrestore(&ha->vport_slock, flags);

		/* If not in use then it is free to use. */
		if (!found) {
@@ -3791,14 +3814,27 @@ void
qla2x00_update_fcports(scsi_qla_host_t *base_vha)
{
	fc_port_t *fcport;
	struct scsi_qla_host *tvp, *vha;
	struct scsi_qla_host *vha;
	struct qla_hw_data *ha = base_vha->hw;
	unsigned long flags;

	spin_lock_irqsave(&ha->vport_slock, flags);
	/* Go with deferred removal of rport references. */
	list_for_each_entry_safe(vha, tvp, &base_vha->hw->vp_list, list)
		list_for_each_entry(fcport, &vha->vp_fcports, list)
	list_for_each_entry(vha, &base_vha->hw->vp_list, list) {
		atomic_inc(&vha->vref_count);
		list_for_each_entry(fcport, &vha->vp_fcports, list) {
			if (fcport && fcport->drport &&
			    atomic_read(&fcport->state) != FCS_UNCONFIGURED)
			    atomic_read(&fcport->state) != FCS_UNCONFIGURED) {
				spin_unlock_irqrestore(&ha->vport_slock, flags);

				qla2x00_rport_del(fcport);

				spin_lock_irqsave(&ha->vport_slock, flags);
			}
		}
		atomic_dec(&vha->vref_count);
	}
	spin_unlock_irqrestore(&ha->vport_slock, flags);
}

void
@@ -3806,7 +3842,7 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
{
	struct qla_hw_data *ha = vha->hw;
	struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev);
	struct scsi_qla_host *tvp;
	unsigned long flags;

	vha->flags.online = 0;
	ha->flags.chip_reset_done = 0;
@@ -3824,8 +3860,18 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
	if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
		atomic_set(&vha->loop_state, LOOP_DOWN);
		qla2x00_mark_all_devices_lost(vha, 0);
		list_for_each_entry_safe(vp, tvp, &base_vha->hw->vp_list, list)

		spin_lock_irqsave(&ha->vport_slock, flags);
		list_for_each_entry(vp, &base_vha->hw->vp_list, list) {
			atomic_inc(&vp->vref_count);
			spin_unlock_irqrestore(&ha->vport_slock, flags);

			qla2x00_mark_all_devices_lost(vp, 0);

			spin_lock_irqsave(&ha->vport_slock, flags);
			atomic_dec(&vp->vref_count);
		}
		spin_unlock_irqrestore(&ha->vport_slock, flags);
	} else {
		if (!atomic_read(&vha->loop_down_timer))
			atomic_set(&vha->loop_down_timer,
@@ -3862,8 +3908,8 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
	uint8_t        status = 0;
	struct qla_hw_data *ha = vha->hw;
	struct scsi_qla_host *vp;
	struct scsi_qla_host *tvp;
	struct req_que *req = ha->req_q_map[0];
	unsigned long flags;

	if (vha->flags.online) {
		qla2x00_abort_isp_cleanup(vha);
@@ -3970,10 +4016,21 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
		DEBUG(printk(KERN_INFO
				"qla2x00_abort_isp(%ld): succeeded.\n",
				vha->host_no));
		list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
			if (vp->vp_idx)

		spin_lock_irqsave(&ha->vport_slock, flags);
		list_for_each_entry(vp, &ha->vp_list, list) {
			if (vp->vp_idx) {
				atomic_inc(&vp->vref_count);
				spin_unlock_irqrestore(&ha->vport_slock, flags);

				qla2x00_vp_abort_isp(vp);

				spin_lock_irqsave(&ha->vport_slock, flags);
				atomic_dec(&vp->vref_count);
			}
		}
		spin_unlock_irqrestore(&ha->vport_slock, flags);

	} else {
		qla_printk(KERN_INFO, ha,
			"qla2x00_abort_isp: **** FAILED ****\n");
@@ -5185,7 +5242,7 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
	struct req_que *req = ha->req_q_map[0];
	struct rsp_que *rsp = ha->rsp_q_map[0];
	struct scsi_qla_host *vp;
	struct scsi_qla_host *tvp;
	unsigned long flags;

	status = qla2x00_init_rings(vha);
	if (!status) {
@@ -5272,10 +5329,21 @@ qla82xx_restart_isp(scsi_qla_host_t *vha)
		DEBUG(printk(KERN_INFO
			"qla82xx_restart_isp(%ld): succeeded.\n",
			vha->host_no));
		list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
			if (vp->vp_idx)

		spin_lock_irqsave(&ha->vport_slock, flags);
		list_for_each_entry(vp, &ha->vp_list, list) {
			if (vp->vp_idx) {
				atomic_inc(&vp->vref_count);
				spin_unlock_irqrestore(&ha->vport_slock, flags);

				qla2x00_vp_abort_isp(vp);

				spin_lock_irqsave(&ha->vport_slock, flags);
				atomic_dec(&vp->vref_count);
			}
		}
		spin_unlock_irqrestore(&ha->vport_slock, flags);

	} else {
		qla_printk(KERN_INFO, ha,
			"qla82xx_restart_isp: **** FAILED ****\n");
+5 −2
Original line number Diff line number Diff line
@@ -2913,7 +2913,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
	uint16_t stat = le16_to_cpu(rptid_entry->vp_idx);
	struct qla_hw_data *ha = vha->hw;
	scsi_qla_host_t *vp;
	scsi_qla_host_t *tvp;
	unsigned long   flags;

	if (rptid_entry->entry_status != 0)
		return;
@@ -2945,9 +2945,12 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
			return;
		}

		list_for_each_entry_safe(vp, tvp, &ha->vp_list, list)
		spin_lock_irqsave(&ha->vport_slock, flags);
		list_for_each_entry(vp, &ha->vp_list, list)
			if (vp_idx == vp->vp_idx)
				break;
		spin_unlock_irqrestore(&ha->vport_slock, flags);

		if (!vp)
			return;

Loading