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:
Tyrel Datwyler
2026-07-22 17:01:41 -07:00
committed by Martin K. Petersen
parent 3831863f9f
commit 696d1cc2aa

View File

@@ -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;