qla2x00t-32gbit: Fix crash during deregistering an NPIV port

NPIV port deregistering processing is different from physical port
processing. We use the same handling for both of them, which causes
the crash when it's an NPIV port. Hence separate the common processing
logic depending on the type of port.

Reported-by: Rob Turk <robtu@rtist.nl>
This commit is contained in:
Gleb Chesnokov
2022-05-09 22:52:32 +03:00
parent c20d0edef8
commit fa4cb77a87
2 changed files with 51 additions and 12 deletions

View File

@@ -47,9 +47,10 @@
size_t qlt_add_vtarget(u64 port_name, u64 node_name, u64 parent_host)
{
struct fc_vport *vport;
struct Scsi_Host *shost = NULL;
scsi_qla_host_t *vha = NULL, *npiv_vha;
struct qla_tgt *tgt;
scsi_qla_host_t *vha = NULL;
struct fc_vport_identifiers vid;
uint8_t parent_wwn[WWN_SIZE];
@@ -78,8 +79,14 @@ size_t qlt_add_vtarget(u64 port_name, u64 node_name, u64 parent_host)
vid.disable = false; /* always enabled */
/* We only allow support on Channel 0 !!! */
if (!fc_vport_create(shost, 0, &vid))
vport = fc_vport_create(shost, 0, &vid);
if (!vport) {
pr_err("fc_vport_create failed for qla2xxx_npiv\n");
return -EINVAL;
}
npiv_vha = (struct scsi_qla_host *) vport->dd_data;
scsi_host_get(npiv_vha->host);
return 0;
}

View File

@@ -1437,6 +1437,39 @@ static void sqa_qla2xxx_remove_target(struct scsi_qla_host *vha)
scst_unregister_target(sqa_tgt->scst_tgt);
TRACE_EXIT();
}
static void sqa_qla2xxx_drop_lport(struct qla_tgt *tgt)
{
struct scsi_qla_host *vha = tgt->vha;
TRACE_ENTRY();
if (vha->vha_tgt.qla_tgt->tgt_stop &&
!vha->vha_tgt.qla_tgt->tgt_stopped) {
PRINT_INFO("sqatgt(%ld/%d): calling qlt_stop_phase2.\n",
vha->host_no, vha->vp_idx);
qlt_stop_phase2(vha->vha_tgt.qla_tgt);
}
qlt_lport_deregister(vha);
TRACE_EXIT();
}
static void sqa_qla2xxx_npiv_drop_lport(struct qla_tgt *tgt)
{
struct scsi_qla_host *npiv_vha = tgt->vha;
struct qla_hw_data *ha = npiv_vha->hw;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
TRACE_ENTRY();
scsi_host_put(npiv_vha->host);
scsi_host_put(base_vha->host);
TRACE_EXIT();
}
/*
* Must be called under tgt_host_action_mutex or sqa_unreg_rwsem write
* locked.
@@ -1450,21 +1483,20 @@ static int sqa_target_release(struct scst_tgt *scst_tgt)
TRACE_ENTRY();
if (vha->vha_tgt.target_lport_ptr) {
if (!vha->vha_tgt.qla_tgt->tgt_stop &&
!vha->vha_tgt.qla_tgt->tgt_stopped) {
!vha->vha_tgt.qla_tgt->tgt_stopped) {
PRINT_INFO("sqatgt(%ld:%d: calling qlt_stop_phase1.\n",
vha->host_no, vha->vp_idx);
vha->host_no, vha->vp_idx);
qlt_stop_phase1(vha->vha_tgt.qla_tgt);
}
if (vha->vha_tgt.qla_tgt->tgt_stop &&
!vha->vha_tgt.qla_tgt->tgt_stopped) {
PRINT_INFO("sqatgt(%ld/%d): calling qlt_stop_phase2.\n",
vha->host_no, vha->vp_idx);
qlt_stop_phase2(vha->vha_tgt.qla_tgt);
}
qlt_lport_deregister(tgt->vha);
if (vha->vp_idx)
sqa_qla2xxx_npiv_drop_lport(tgt);
else
sqa_qla2xxx_drop_lport(tgt);
}
scst_tgt_set_tgt_priv(scst_tgt, NULL);
mutex_lock(&sqa_mutex);
@@ -1473,7 +1505,7 @@ static int sqa_target_release(struct scst_tgt *scst_tgt)
mutex_unlock(&sqa_mutex);
TRACE(TRACE_MGMT, "sqatgt(%ld/%d): Target release finished sqa_tgt %p",
vha->host_no, tgt->vha->vp_idx, sqa_tgt);
vha->host_no, vha->vp_idx, sqa_tgt);
kfree(sqa_tgt);