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

Commit 0aca7784 authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Reduce holding sess_lock to prevent CPU lock-up



- Reduce sess_lock holding to prevent CPU Lock up. sess_lock was held across
  fc_port registration and deletion.  These calls can be blocked by upper
  layer. Sess_lock is also being accessed by interrupt thread.

- Reduce number of loops in processing work_list to prevent kernel complaint
  of CPU lockup or holding sess_lock.

Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 6a629468
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -262,8 +262,8 @@ struct name_list_extended {
	struct get_name_list_extended *l;
	dma_addr_t		ldma;
	struct list_head	fcports;
	spinlock_t		fcports_lock;
	u32			size;
	u8			sent;
};
/*
 * Timeout timer counts in seconds
+12 −6
Original line number Diff line number Diff line
@@ -3946,11 +3946,10 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
			if ((qla_dual_mode_enabled(vha) ||
				qla_ini_mode_enabled(vha)) &&
			    atomic_read(&fcport->state) == FCS_ONLINE) {
				qla2x00_mark_device_lost(vha, fcport,
				    ql2xplogiabsentdevice, 0);
				if (fcport->loop_id != FC_NO_LOOP_ID) {
					if (fcport->flags & FCF_FCP2_DEVICE)
						fcport->logout_on_delete = 0;

				if (fcport->loop_id != FC_NO_LOOP_ID &&
				    (fcport->flags & FCF_FCP2_DEVICE) == 0) {
					ql_dbg(ql_dbg_disc, vha, 0x20f0,
					    "%s %d %8phC post del sess\n",
					    __func__, __LINE__,
@@ -4188,12 +4187,13 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)

		sp->rc = res;
		rc = qla2x00_post_nvme_gpnft_done_work(vha, sp, QLA_EVT_GPNFT);
		if (!rc) {
		if (rc) {
			qla24xx_sp_unmap(vha, sp);
			set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
			set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
			return;
		}
		return;
	}

	if (cmd == GPN_FT_CMD) {
@@ -4243,6 +4243,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
		vha->scan.scan_flags &= ~SF_SCANNING;
		spin_unlock_irqrestore(&vha->work_lock, flags);
		WARN_ON(1);
		set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
		set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
		goto done_free_sp;
	}

@@ -4276,8 +4278,12 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
	sp->done = qla2x00_async_gpnft_gnnft_sp_done;

	rval = qla2x00_start_sp(sp);
	if (rval != QLA_SUCCESS)
	if (rval != QLA_SUCCESS) {
		spin_lock_irqsave(&vha->work_lock, flags);
		vha->scan.scan_flags &= ~SF_SCANNING;
		spin_unlock_irqrestore(&vha->work_lock, flags);
		goto done_free_sp;
	}

	ql_dbg(ql_dbg_disc, vha, 0xffff,
	    "Async-%s hdl=%x FC4Type %x.\n", sp->name,
+17 −16
Original line number Diff line number Diff line
@@ -790,6 +790,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
	    sp->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1],
	    sp->u.iocb_cmd.u.mbx.in_mb[2]);

	sp->fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
	memset(&ea, 0, sizeof(ea));
	ea.sp = sp;
	ea.rc = res;
@@ -817,25 +818,24 @@ qla24xx_async_gnl_sp_done(void *s, int res)
		    (loop_id & 0x7fff));
	}

	spin_lock_irqsave(&vha->gnl.fcports_lock, flags);
	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);

	INIT_LIST_HEAD(&h);
	fcport = tf = NULL;
	if (!list_empty(&vha->gnl.fcports))
		list_splice_init(&vha->gnl.fcports, &h);
	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);

	list_for_each_entry_safe(fcport, tf, &h, gnl_entry) {
		list_del_init(&fcport->gnl_entry);
		spin_lock(&vha->hw->tgt.sess_lock);
		spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
		fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
		spin_unlock(&vha->hw->tgt.sess_lock);
		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
		ea.fcport = fcport;

		qla2x00_fcport_event_handler(vha, &ea);
	}
	spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);

	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
	/* create new fcport if fw has knowledge of new sessions */
	for (i = 0; i < n; i++) {
		port_id_t id;
@@ -868,6 +868,8 @@ qla24xx_async_gnl_sp_done(void *s, int res)
		}
	}

	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
	vha->gnl.sent = 0;
	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);

	sp->free(sp);
@@ -887,27 +889,24 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
	ql_dbg(ql_dbg_disc, vha, 0x20d9,
	    "Async-gnlist WWPN %8phC \n", fcport->port_name);

	spin_lock_irqsave(&vha->gnl.fcports_lock, flags);
	if (!list_empty(&fcport->gnl_entry)) {
		spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
		rval = QLA_SUCCESS;
		goto done;
	}

	spin_lock(&vha->hw->tgt.sess_lock);
	spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
	fcport->flags |= FCF_ASYNC_SENT;
	fcport->disc_state = DSC_GNL;
	fcport->last_rscn_gen = fcport->rscn_gen;
	fcport->last_login_gen = fcport->login_gen;
	spin_unlock(&vha->hw->tgt.sess_lock);

	list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports);
	spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
	if (vha->gnl.sent) {
		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
		return QLA_SUCCESS;
	}
	vha->gnl.sent = 1;
	spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);

	sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
	if (!sp)
		goto done;

	fcport->flags |= FCF_ASYNC_SENT;
	sp->type = SRB_MB_IOCB;
	sp->name = "gnlist";
	sp->gen1 = fcport->rscn_gen;
@@ -1185,7 +1184,9 @@ void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
		vha->fcport_count++;
		ea->fcport->login_succ = 1;

		spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
		qla24xx_sched_upd_fcport(ea->fcport);
		spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
	} else if (ea->fcport->login_succ) {
		/*
		 * We have an existing session. A late RSCN delivery
+1 −2
Original line number Diff line number Diff line
@@ -2730,7 +2730,7 @@ static void qla2x00_iocb_work_fn(struct work_struct *work)
		struct scsi_qla_host, iocb_work);
	struct qla_hw_data *ha = vha->hw;
	struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
	int i = 20;
	int i = 2;
	unsigned long flags;

	if (test_bit(UNLOADING, &base_vha->dpc_flags))
@@ -4603,7 +4603,6 @@ struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *sht,

	spin_lock_init(&vha->work_lock);
	spin_lock_init(&vha->cmd_list_lock);
	spin_lock_init(&vha->gnl.fcports_lock);
	init_waitqueue_head(&vha->fcport_waitQ);
	init_waitqueue_head(&vha->vref_waitq);

+2 −0
Original line number Diff line number Diff line
@@ -601,7 +601,9 @@ void qla2x00_async_nack_sp_done(void *s, int res)
			sp->fcport->login_succ = 1;

			vha->fcport_count++;
			spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
			qla24xx_sched_upd_fcport(sp->fcport);
			spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
		} else {
			sp->fcport->login_retry = 0;
			sp->fcport->disc_state = DSC_LOGIN_COMPLETE;