mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 09:11:27 +00:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user