mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 09:20:13 -04:00
scsi: ibmvfc: process NVMe/FC rports in work thread
Add an NVMe-specific remote-port add helper and update the rport worker thread to walk the NVMe target list, register new NVMe remote ports, and rescan existing ones through the NVMe-FC midlayer. Also handle delete and delete-with-logout transitions for NVMe remote ports in the same worker context used for SCSI rports. This keeps remote-port registration serialized in the existing worker model while allowing NVMe targets to participate in the common target state machine. Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com> Link: https://patch.msgid.link/20260723000149.969416-26-tyreld@linux.ibm.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
committed by
Martin K. Petersen
parent
3831863f9f
commit
696d1cc2aa
@@ -5856,6 +5856,51 @@ static void ibmvfc_log_ae(struct ibmvfc_host *vhost, int events)
|
||||
fc_host_post_event(vhost->host, fc_get_event_number(), FCH_EVT_LINKUP, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* ibmvfc_tgt_add_nvme_rport - Tell the FC transport about a new remote port
|
||||
* @tgt: ibmvfc target struct
|
||||
*
|
||||
**/
|
||||
static void ibmvfc_tgt_add_nvme_rport(struct ibmvfc_target *tgt)
|
||||
{
|
||||
struct ibmvfc_host *vhost = tgt->vhost;
|
||||
struct nvme_fc_remote_port *rport;
|
||||
unsigned long flags;
|
||||
|
||||
tgt_dbg(tgt, "Adding NVMe rport\n");
|
||||
ibmvfc_nvme_register_remoteport(tgt);
|
||||
spin_lock_irqsave(vhost->host->host_lock, flags);
|
||||
rport = tgt->nvme_remote_port;
|
||||
|
||||
if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) {
|
||||
tgt_dbg(tgt, "Deleting NVMe rport\n");
|
||||
list_del(&tgt->queue);
|
||||
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT);
|
||||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
ibmvfc_nvme_unregister_remoteport(tgt);
|
||||
timer_delete_sync(&tgt->timer);
|
||||
kref_put(&tgt->kref, ibmvfc_release_tgt);
|
||||
return;
|
||||
} else if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) {
|
||||
tgt_dbg(tgt, "Deleting NVMe rport with outstanding I/O\n");
|
||||
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT);
|
||||
tgt->init_retries = 0;
|
||||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
ibmvfc_nvme_unregister_remoteport(tgt);
|
||||
return;
|
||||
} else if (rport && tgt->action == IBMVFC_TGT_ACTION_DELETED_RPORT) {
|
||||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rport) {
|
||||
tgt_dbg(tgt, "NVMe rport add succeeded\n");
|
||||
tgt->target_id = tgt->nvme_remote_port->port_id;
|
||||
} else
|
||||
tgt_dbg(tgt, "NVMe rport add failed\n");
|
||||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* ibmvfc_tgt_add_rport - Tell the FC transport about a new remote port
|
||||
* @tgt: ibmvfc target struct
|
||||
@@ -5920,6 +5965,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
|
||||
struct ibmvfc_target *tgt;
|
||||
unsigned long flags;
|
||||
struct fc_rport *rport;
|
||||
struct nvme_fc_remote_port *nvme_rport;
|
||||
LIST_HEAD(purge);
|
||||
int rc;
|
||||
|
||||
@@ -6073,6 +6119,30 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(tgt, &vhost->nvme_scrqs.targets, queue) {
|
||||
if (tgt->action == IBMVFC_TGT_ACTION_DEL_RPORT) {
|
||||
tgt_dbg(tgt, "Deleteing NVMe rport\n");
|
||||
nvme_rport = tgt->nvme_remote_port;
|
||||
list_del(&tgt->queue);
|
||||
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DELETED_RPORT);
|
||||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
if (nvme_rport)
|
||||
ibmvfc_nvme_unregister_remoteport(tgt);
|
||||
timer_delete_sync(&tgt->timer);
|
||||
kref_put(&tgt->kref, ibmvfc_release_tgt);
|
||||
return;
|
||||
} else if (rport && tgt->action == IBMVFC_TGT_ACTION_DEL_AND_LOGOUT_RPORT) {
|
||||
tgt_dbg(tgt, "Deleting NVMe rport with outstanding I/O\n");
|
||||
nvme_rport = tgt->nvme_remote_port;
|
||||
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_LOGOUT_DELETED_RPORT);
|
||||
tgt->init_retries = 0;
|
||||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
if (nvme_rport)
|
||||
ibmvfc_nvme_unregister_remoteport(tgt);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (vhost->state == IBMVFC_INITIALIZING) {
|
||||
if (vhost->action == IBMVFC_HOST_ACTION_TGT_DEL_FAILED) {
|
||||
if (vhost->reinit) {
|
||||
@@ -6658,6 +6728,7 @@ static void ibmvfc_rport_add_thread(struct work_struct *work)
|
||||
rport_add_work_q);
|
||||
struct ibmvfc_target *tgt;
|
||||
struct fc_rport *rport;
|
||||
struct nvme_fc_remote_port *nvme_rport;
|
||||
unsigned long flags;
|
||||
int did_work;
|
||||
|
||||
@@ -6691,7 +6762,28 @@ static void ibmvfc_rport_add_thread(struct work_struct *work)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while(did_work);
|
||||
|
||||
list_for_each_entry(tgt, &vhost->nvme_scrqs.targets, queue) {
|
||||
if (tgt->add_rport) {
|
||||
did_work = 1;
|
||||
tgt->add_rport = 0;
|
||||
kref_get(&tgt->kref);
|
||||
nvme_rport = tgt->nvme_remote_port;
|
||||
if (!nvme_rport) {
|
||||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
ibmvfc_tgt_add_nvme_rport(tgt);
|
||||
} else {
|
||||
spin_unlock_irqrestore(vhost->host->host_lock, flags);
|
||||
if (IS_ENABLED(CONFIG_NVME_FC))
|
||||
nvme_fc_rescan_remoteport(nvme_rport);
|
||||
}
|
||||
|
||||
kref_put(&tgt->kref, ibmvfc_release_tgt);
|
||||
spin_lock_irqsave(vhost->host->host_lock, flags);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (did_work);
|
||||
|
||||
if (vhost->state == IBMVFC_ACTIVE)
|
||||
vhost->scan_complete = 1;
|
||||
|
||||
Reference in New Issue
Block a user