Messages in this thread Patch in this message | | | From | Logan Gunthorpe <> | Date | Fri, 25 Oct 2019 14:25:35 -0600 | Subject | [RFC PATCH 3/3] nvme: Introduce nvme_execute_passthru_rq_nowait() |
| |
This function is similar to nvme_execute_passthru_rq() but does not wait and will call a callback when the request is complete.
The new function can also be called in interrupt context, so if there are side effects, the request will be executed in a work queue to avoid sleeping.
Signed-off-by: Logan Gunthorpe <logang@deltatee.com> --- drivers/nvme/host/core.c | 42 ++++++++++++++++++++++++++++++++++++++++ drivers/nvme/host/nvme.h | 7 +++++++ 2 files changed, 49 insertions(+)
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 2b4f0ea55f8d..6d3cade0e63d 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -4211,6 +4211,48 @@ void nvme_sync_queues(struct nvme_ctrl *ctrl) } EXPORT_SYMBOL_GPL(nvme_sync_queues); +#ifdef CONFIG_NVME_TARGET_PASSTHRU +static void nvme_execute_passthru_rq_work(struct work_struct *w) +{ + struct nvme_request *req = container_of(w, struct nvme_request, work); + struct request *rq = blk_mq_rq_from_pdu(req); + rq_end_io_fn *done = rq->end_io; + void *end_io_data = rq->end_io_data; + + nvme_execute_passthru_rq(rq); + + if (done) { + rq->end_io_data = end_io_data; + done(rq, 0); + } +} + +void nvme_execute_passthru_rq_nowait(struct request *rq, rq_end_io_fn *done) +{ + struct nvme_command *cmd = nvme_req(rq)->cmd; + struct nvme_ctrl *ctrl = nvme_req(rq)->ctrl; + struct nvme_ns *ns = rq->q->queuedata; + struct gendisk *disk = ns ? ns->disk : NULL; + u32 effects; + + /* + * This function may be called in interrupt context, so we cannot sleep + * but nvme_passthru_[start|end]() may sleep so we need to execute + * the command in a work queue. + */ + effects = nvme_command_effects(ctrl, ns, cmd->common.opcode); + if (effects) { + rq->end_io = done; + INIT_WORK(&nvme_req(rq)->work, nvme_execute_passthru_rq_work); + queue_work(nvme_wq, &nvme_req(rq)->work); + return; + } + + blk_execute_rq_nowait(rq->q, disk, rq, 0, done); +} +EXPORT_SYMBOL_GPL(nvme_execute_passthru_rq_nowait); +#endif /* CONFIG_NVME_TARGET_PASSTHRU */ + /* * Check we didn't inadvertently grow the command structure sizes: */ diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 22e8401352c2..9523779de662 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -128,6 +128,9 @@ struct nvme_request { u8 flags; u16 status; struct nvme_ctrl *ctrl; +#ifdef CONFIG_NVME_TARGET_PASSTHRU + struct work_struct work; +#endif }; /* @@ -652,4 +655,8 @@ static inline struct nvme_ns *nvme_get_ns_from_dev(struct device *dev) return dev_to_disk(dev)->private_data; } +#ifdef CONFIG_NVME_TARGET_PASSTHRU +void nvme_execute_passthru_rq_nowait(struct request *rq, rq_end_io_fn *done); +#endif /* CONFIG_NVME_TARGET_PASSTHRU */ + #endif /* _NVME_H */ -- 2.20.1
| |