diff --git a/include/vfn/nvme/ctrl.h b/include/vfn/nvme/ctrl.h index 36d2dcb..bcc86ce 100644 --- a/include/vfn/nvme/ctrl.h +++ b/include/vfn/nvme/ctrl.h @@ -158,6 +158,38 @@ int nvme_init(struct nvme_ctrl *ctrl, const char *bdf, const struct nvme_ctrl_op */ void nvme_close(struct nvme_ctrl *ctrl); +/** + * nvme_get_ctrl - Get nvme_ctrl instance initialized + * @bdf: PCI device identifier ("bus:device:function") + * + * Return nvme_ctrl instance initialized by the application. + * + * Return: nvme_ctrl instance pointer on success, ``NULL`` on error. + */ +struct nvme_ctrl *nvme_get_ctrl(const char *bdf); + +/** + * nvme_add_ctrl - Add nvme_ctrl instance to library + * @ctrl: Controller to keep in the library + * + * Add initialized nvme_ctrl instance to library for application can + * ask to retrieve the controller instance back. If application keeps the + * instance list, it's not required to call this function. + * + * Return: ``0`` on success, ``-1`` on error and set ``errno``. + */ +int nvme_add_ctrl(struct nvme_ctrl *ctrl); + +/** + * nvme_del_ctrl - Delete nvme_ctrl instance from library + * @ctrl: Controller to delete from the library + * + * Delete added nvme_ctrl instance from library. + * + * Return: ``0`` on success, ``-1`` on error and set ``errno``. + */ +int nvme_del_ctrl(struct nvme_ctrl *ctrl); + /** * nvme_reset - Reset controller * @ctrl: Controller to reset diff --git a/src/nvme/core.c b/src/nvme/core.c index b06bf86..6bb2bca 100644 --- a/src/nvme/core.c +++ b/src/nvme/core.c @@ -40,6 +40,7 @@ #include "ccan/compiler/compiler.h" #include "ccan/minmax/minmax.h" #include "ccan/time/time.h" +#include "ccan/list/list.h" #include "types.h" @@ -49,6 +50,66 @@ #define sqtdbl(doorbells, qid, dstrd) \ (doorbells + (2 * qid) * (4 << dstrd)) +struct nvme_ctrl_handle { + struct nvme_ctrl *ctrl; + struct list_node list; +}; + +static LIST_HEAD(nvme_ctrl_handles); + +static struct nvme_ctrl_handle *nvme_get_ctrl_handle(const char *bdf) +{ + struct nvme_ctrl_handle *handle; + + list_for_each(&nvme_ctrl_handles, handle, list) { + if (streq(handle->ctrl->pci.bdf, bdf)) + return handle; + } + + return NULL; +} + + +struct nvme_ctrl *nvme_get_ctrl(const char *bdf) +{ + struct nvme_ctrl_handle *handle = nvme_get_ctrl_handle(bdf); + + if (!handle) + return NULL; + + return handle->ctrl; +} + +int nvme_add_ctrl(struct nvme_ctrl *ctrl) +{ + struct nvme_ctrl_handle *handle; + + if (nvme_get_ctrl(ctrl->pci.bdf)) { + errno = EEXIST; + return -1; + } + + handle = znew_t(struct nvme_ctrl_handle, 1); + handle->ctrl = ctrl; + list_add_tail(&nvme_ctrl_handles, &handle->list); + return 0; +} + +int nvme_del_ctrl(struct nvme_ctrl *ctrl) +{ + struct nvme_ctrl_handle *handle; + + handle = nvme_get_ctrl_handle(ctrl->pci.bdf); + if (!handle) { + errno = ENODEV; + return -1; + } + + list_del(&handle->list); + free(handle); + return 0; +} + static int nvme_configure_cq(struct nvme_ctrl *ctrl, int qid, int qsize, int vector) { struct nvme_cq *cq = &ctrl->cq[qid];