From: Keith Busch <kbusch@xxxxxxxxxx> Maps a user requested write stream to an FDP placement ID if possible. Reviewed-by: Hannes Reinecke <hare@xxxxxxx> Reviewed-by: Nitesh Shetty <nj.shetty@xxxxxxxxxxx> Signed-off-by: Keith Busch <kbusch@xxxxxxxxxx> --- drivers/nvme/host/core.c | 31 ++++++++++++++++++++++++++++++- drivers/nvme/host/nvme.h | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index c8bc58b8ee3aa..d14c23916671d 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -674,6 +674,7 @@ static void nvme_free_ns_head(struct kref *ref) ida_free(&head->subsys->ns_ida, head->instance); cleanup_srcu_struct(&head->srcu); nvme_put_subsystem(head->subsys); + kfree(head->plids); kfree(head); } @@ -997,6 +998,18 @@ static inline blk_status_t nvme_setup_rw(struct nvme_ns *ns, if (req->cmd_flags & REQ_RAHEAD) dsmgmt |= NVME_RW_DSM_FREQ_PREFETCH; + if (op == nvme_cmd_write && ns->head->nr_plids) { + u16 write_stream = req->bio->bi_write_stream; + + if (WARN_ON_ONCE(write_stream > ns->head->nr_plids)) + return BLK_STS_INVAL; + + if (write_stream) { + dsmgmt |= ns->head->plids[write_stream - 1] << 16; + control |= NVME_RW_DTYPE_DPLCMT; + } + } + if (req->cmd_flags & REQ_ATOMIC && !nvme_valid_atomic_write(req)) return BLK_STS_INVAL; @@ -2241,7 +2254,7 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info) struct nvme_fdp_config fdp; struct nvme_command c = {}; size_t size; - int ret; + int i, ret; /* * The FDP configuration is static for the lifetime of the namespace, @@ -2281,6 +2294,22 @@ static int nvme_query_fdp_info(struct nvme_ns *ns, struct nvme_ns_info *info) } head->nr_plids = le16_to_cpu(ruhs->nruhsd); + if (!head->nr_plids) + goto free; + + head->plids = kcalloc(head->nr_plids, sizeof(head->plids), + GFP_KERNEL); + if (!head->plids) { + dev_warn(ctrl->device, + "failed to allocate %u FDP placement IDs\n", + head->nr_plids); + head->nr_plids = 0; + ret = -ENOMEM; + goto free; + } + + for (i = 0; i < head->nr_plids; i++) + head->plids[i] = le16_to_cpu(ruhs->ruhsd[i].pid); free: kfree(ruhs); return ret; diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index b63164cf6b274..59ba31c48cf66 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -498,6 +498,7 @@ struct nvme_ns_head { struct gendisk *disk; u16 nr_plids; + u16 *plids; #ifdef CONFIG_NVME_MULTIPATH struct bio_list requeue_list; spinlock_t requeue_lock; -- 2.43.5