[RFC PATCH 3/4] nvme: export helpers to implement vfio-nvme lm
Chaitanya Kulkarni
kch at nvidia.com
Sat Aug 2 19:47:04 PDT 2025
Export the nvme_error_status() function to allow error status
translation from external modules such as VFIO-based drivers.
Add helper functions in nvme-pci to support virtual function (VF)
command submission and controller ID retrieval:
- nvme_submit_vf_cmd() submits a synchronous admin command
from a VF context using the PF's admin queue.
- nvme_get_ctrl_id() returns the controller ID associated
with a PCI device.
These changes support VFIO NVMe Live Migration workflows and
infrastructure by enabling necessary low-level admin command access.
Signed-off-by: Lei Rao <lei.rao at intel.com>
Signed-off-by: Max Gurtovoy <mgurtovoy at nvidia.com>
Signed-off-by: Chaitanya Kulkarni <kch at nvidia.com>
---
drivers/nvme/host/core.c | 3 ++-
drivers/nvme/host/nvme.h | 5 +++++
drivers/nvme/host/pci.c | 34 ++++++++++++++++++++++++++++++++++
3 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 2445862ac7d4..3620e7cb21d1 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -278,7 +278,7 @@ void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl)
nvme_put_ctrl(ctrl);
}
-static blk_status_t nvme_error_status(u16 status)
+blk_status_t nvme_error_status(u16 status)
{
switch (status & NVME_SCT_SC_MASK) {
case NVME_SC_SUCCESS:
@@ -318,6 +318,7 @@ static blk_status_t nvme_error_status(u16 status)
return BLK_STS_IOERR;
}
}
+EXPORT_SYMBOL_GPL(nvme_error_status);
static void nvme_retry_req(struct request *req)
{
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index cfd2b5b90b91..5549c7e3bcd3 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -1218,4 +1218,9 @@ static inline bool nvme_multi_css(struct nvme_ctrl *ctrl)
return (ctrl->ctrl_config & NVME_CC_CSS_MASK) == NVME_CC_CSS_CSI;
}
+blk_status_t nvme_error_status(u16 status);
+int nvme_submit_vf_cmd(struct pci_dev *dev, struct nvme_command *cmd,
+ size_t *result, void *buffer, unsigned int bufflen);
+u16 nvme_get_ctrl_id(struct pci_dev *dev);
+
#endif /* _NVME_H */
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 4cf87fb5d857..b239d38485ee 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -3936,6 +3936,40 @@ static struct pci_driver nvme_driver = {
.err_handler = &nvme_err_handler,
};
+u16 nvme_get_ctrl_id(struct pci_dev *dev)
+{
+ struct nvme_dev *ndev = pci_iov_get_pf_drvdata(dev, &nvme_driver);
+
+ return ndev->ctrl.cntlid;
+}
+EXPORT_SYMBOL_GPL(nvme_get_ctrl_id);
+
+int nvme_submit_vf_cmd(struct pci_dev *dev, struct nvme_command *cmd,
+ size_t *result, void *buffer, unsigned int bufflen)
+{
+ struct nvme_dev *ndev = NULL;
+ union nvme_result res = { };
+ int ret;
+
+ ndev = pci_iov_get_pf_drvdata(dev, &nvme_driver);
+ if (IS_ERR(ndev))
+ return PTR_ERR(ndev);
+ ret = __nvme_submit_sync_cmd(ndev->ctrl.admin_q, cmd, &res, buffer,
+ bufflen, NVME_QID_ANY, 0);
+ if (ret < 0)
+ return ret;
+
+ if (ret > 0) {
+ ret = blk_status_to_errno(nvme_error_status(ret));
+ return ret;
+ }
+
+ if (result)
+ *result = le32_to_cpu(res.u32);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(nvme_submit_vf_cmd);
+
static int __init nvme_init(void)
{
BUILD_BUG_ON(sizeof(struct nvme_create_cq) != 64);
--
2.40.0
More information about the Linux-nvme
mailing list