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 Signed-off-by: Max Gurtovoy Signed-off-by: Chaitanya Kulkarni --- 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