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

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
...@@ -262,8 +262,8 @@ struct name_list_extended { ...@@ -262,8 +262,8 @@ struct name_list_extended {
struct get_name_list_extended *l; struct get_name_list_extended *l;
dma_addr_t ldma; dma_addr_t ldma;
struct list_head fcports; struct list_head fcports;
spinlock_t fcports_lock;
u32 size; u32 size;
u8 sent;
}; };
/* /*
* Timeout timer counts in seconds * Timeout timer counts in seconds
......
...@@ -3946,11 +3946,10 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp) ...@@ -3946,11 +3946,10 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
if ((qla_dual_mode_enabled(vha) || if ((qla_dual_mode_enabled(vha) ||
qla_ini_mode_enabled(vha)) && qla_ini_mode_enabled(vha)) &&
atomic_read(&fcport->state) == FCS_ONLINE) { atomic_read(&fcport->state) == FCS_ONLINE) {
qla2x00_mark_device_lost(vha, fcport, if (fcport->loop_id != FC_NO_LOOP_ID) {
ql2xplogiabsentdevice, 0); 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, ql_dbg(ql_dbg_disc, vha, 0x20f0,
"%s %d %8phC post del sess\n", "%s %d %8phC post del sess\n",
__func__, __LINE__, __func__, __LINE__,
...@@ -4188,12 +4187,13 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res) ...@@ -4188,12 +4187,13 @@ static void qla2x00_async_gpnft_gnnft_sp_done(void *s, int res)
sp->rc = res; sp->rc = res;
rc = qla2x00_post_nvme_gpnft_done_work(vha, sp, QLA_EVT_GPNFT); rc = qla2x00_post_nvme_gpnft_done_work(vha, sp, QLA_EVT_GPNFT);
if (!rc) { if (rc) {
qla24xx_sp_unmap(vha, sp); qla24xx_sp_unmap(vha, sp);
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags); set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
return; return;
} }
return;
} }
if (cmd == GPN_FT_CMD) { if (cmd == GPN_FT_CMD) {
...@@ -4243,6 +4243,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp, ...@@ -4243,6 +4243,8 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *sp,
vha->scan.scan_flags &= ~SF_SCANNING; vha->scan.scan_flags &= ~SF_SCANNING;
spin_unlock_irqrestore(&vha->work_lock, flags); spin_unlock_irqrestore(&vha->work_lock, flags);
WARN_ON(1); WARN_ON(1);
set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
goto done_free_sp; goto done_free_sp;
} }
...@@ -4276,8 +4278,12 @@ static int qla24xx_async_gnnft(scsi_qla_host_t *vha, struct srb *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; sp->done = qla2x00_async_gpnft_gnnft_sp_done;
rval = qla2x00_start_sp(sp); 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; goto done_free_sp;
}
ql_dbg(ql_dbg_disc, vha, 0xffff, ql_dbg(ql_dbg_disc, vha, 0xffff,
"Async-%s hdl=%x FC4Type %x.\n", sp->name, "Async-%s hdl=%x FC4Type %x.\n", sp->name,
......
...@@ -790,6 +790,7 @@ qla24xx_async_gnl_sp_done(void *s, int res) ...@@ -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->name, res, sp->u.iocb_cmd.u.mbx.in_mb[1],
sp->u.iocb_cmd.u.mbx.in_mb[2]); sp->u.iocb_cmd.u.mbx.in_mb[2]);
sp->fcport->flags &= ~(FCF_ASYNC_SENT|FCF_ASYNC_ACTIVE);
memset(&ea, 0, sizeof(ea)); memset(&ea, 0, sizeof(ea));
ea.sp = sp; ea.sp = sp;
ea.rc = res; ea.rc = res;
...@@ -817,25 +818,24 @@ qla24xx_async_gnl_sp_done(void *s, int res) ...@@ -817,25 +818,24 @@ qla24xx_async_gnl_sp_done(void *s, int res)
(loop_id & 0x7fff)); (loop_id & 0x7fff));
} }
spin_lock_irqsave(&vha->gnl.fcports_lock, flags); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
INIT_LIST_HEAD(&h); INIT_LIST_HEAD(&h);
fcport = tf = NULL; fcport = tf = NULL;
if (!list_empty(&vha->gnl.fcports)) if (!list_empty(&vha->gnl.fcports))
list_splice_init(&vha->gnl.fcports, &h); 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_for_each_entry_safe(fcport, tf, &h, gnl_entry) {
list_del_init(&fcport->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); 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; ea.fcport = fcport;
qla2x00_fcport_event_handler(vha, &ea); 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 */ /* create new fcport if fw has knowledge of new sessions */
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
port_id_t id; port_id_t id;
...@@ -868,6 +868,8 @@ qla24xx_async_gnl_sp_done(void *s, int res) ...@@ -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); spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
sp->free(sp); sp->free(sp);
...@@ -887,27 +889,24 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport) ...@@ -887,27 +889,24 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, fc_port_t *fcport)
ql_dbg(ql_dbg_disc, vha, 0x20d9, ql_dbg(ql_dbg_disc, vha, 0x20d9,
"Async-gnlist WWPN %8phC \n", fcport->port_name); "Async-gnlist WWPN %8phC \n", fcport->port_name);
spin_lock_irqsave(&vha->gnl.fcports_lock, flags); spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
if (!list_empty(&fcport->gnl_entry)) { fcport->flags |= FCF_ASYNC_SENT;
spin_unlock_irqrestore(&vha->gnl.fcports_lock, flags);
rval = QLA_SUCCESS;
goto done;
}
spin_lock(&vha->hw->tgt.sess_lock);
fcport->disc_state = DSC_GNL; fcport->disc_state = DSC_GNL;
fcport->last_rscn_gen = fcport->rscn_gen; fcport->last_rscn_gen = fcport->rscn_gen;
fcport->last_login_gen = fcport->login_gen; fcport->last_login_gen = fcport->login_gen;
spin_unlock(&vha->hw->tgt.sess_lock);
list_add_tail(&fcport->gnl_entry, &vha->gnl.fcports); 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); sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp) if (!sp)
goto done; goto done;
fcport->flags |= FCF_ASYNC_SENT;
sp->type = SRB_MB_IOCB; sp->type = SRB_MB_IOCB;
sp->name = "gnlist"; sp->name = "gnlist";
sp->gen1 = fcport->rscn_gen; sp->gen1 = fcport->rscn_gen;
...@@ -1185,7 +1184,9 @@ void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea) ...@@ -1185,7 +1184,9 @@ void __qla24xx_handle_gpdb_event(scsi_qla_host_t *vha, struct event_arg *ea)
vha->fcport_count++; vha->fcport_count++;
ea->fcport->login_succ = 1; ea->fcport->login_succ = 1;
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
qla24xx_sched_upd_fcport(ea->fcport); qla24xx_sched_upd_fcport(ea->fcport);
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
} else if (ea->fcport->login_succ) { } else if (ea->fcport->login_succ) {
/* /*
* We have an existing session. A late RSCN delivery * We have an existing session. A late RSCN delivery
......
...@@ -2730,7 +2730,7 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) ...@@ -2730,7 +2730,7 @@ static void qla2x00_iocb_work_fn(struct work_struct *work)
struct scsi_qla_host, iocb_work); struct scsi_qla_host, iocb_work);
struct qla_hw_data *ha = vha->hw; struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev); struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
int i = 20; int i = 2;
unsigned long flags; unsigned long flags;
if (test_bit(UNLOADING, &base_vha->dpc_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, ...@@ -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->work_lock);
spin_lock_init(&vha->cmd_list_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->fcport_waitQ);
init_waitqueue_head(&vha->vref_waitq); init_waitqueue_head(&vha->vref_waitq);
......
...@@ -601,7 +601,9 @@ void qla2x00_async_nack_sp_done(void *s, int res) ...@@ -601,7 +601,9 @@ void qla2x00_async_nack_sp_done(void *s, int res)
sp->fcport->login_succ = 1; sp->fcport->login_succ = 1;
vha->fcport_count++; vha->fcport_count++;
spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
qla24xx_sched_upd_fcport(sp->fcport); qla24xx_sched_upd_fcport(sp->fcport);
spin_lock_irqsave(&vha->hw->tgt.sess_lock, flags);
} else { } else {
sp->fcport->login_retry = 0; sp->fcport->login_retry = 0;
sp->fcport->disc_state = DSC_LOGIN_COMPLETE; sp->fcport->disc_state = DSC_LOGIN_COMPLETE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment