NVMe: Do not set queue depth beyond device max
Subsystems (2)
PATCH 1/1 NVMe: Do not set queue depth beyond device max
Set the depth to the device maximum if the requested depth exceeds the device's capabilities.
Signed-off-by Keith Busch <keith.busch at intel.com>
--- drivers/block/nvme.c | 8 ++++++-- include/linux/nvme.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-)
drivers/block/nvme.c +6 -2
@@ -892,8 +892,12 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth, int vector) {struct device *dmadev = &dev->pci_dev->dev; -unsigned extra = (depth /8 ) + (depth *sizeof (struct nvme_cmd_info )); -struct nvme_queue *nvmeq =kzalloc (sizeof (*nvmeq) + extra,GFP_KERNEL ); +unsigned extra; +struct nvme_queue *nvmeq; + + depth =min_t (int,NVME_CAP_MQES (readq (&dev->bar->cap)) +1 , depth); + extra =DIV_ROUND_UP (depth,8 ) + (depth *sizeof (struct nvme_cmd_info )); + nvmeq =kzalloc (sizeof (*nvmeq) + extra,GFP_KERNEL );if (!nvmeq)return NULL ;
include/linux/nvme.h +1 -0
@@ -35,6 +35,7 @@ struct nvme_bar {__u64 acq;/* Admin CQ Base Address */ }; +#define NVME_CAP_MQES (cap) (cap & 0xffff)#define NVME_CAP_TIMEOUT (cap) (((cap) >> 24) & 0xff)#define NVME_CAP_STRIDE (cap) (((cap) >> 32) & 0xf)
Signature · 1 line
1.7.0.4
PATCH 1/1 NVMe: Do not set queue depth beyond device max
Quoted 2 lines · Keith Busch
Set the depth to the device maximum if the requested depth exceeds the device's capabilities.
The problem is that nvme_alloc_queue is called for both IO queues and the admin queue, but MQES only applies to the IO queues.
I think we need to read it in nvme_setup_io_queues() instead. This also has the advantage of only reading MQES once instead of once per queue.
Quoted 15 lines
drivers/block/nvme.c +6
-2@@ -892,8 +892,12 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth, int vector) {struct device *dmadev = &dev->pci_dev->dev; -unsigned extra = (depth /8 ) + (depth *sizeof (struct nvme_cmd_info )); -struct nvme_queue *nvmeq =kzalloc (sizeof (*nvmeq) + extra,GFP_KERNEL ); +unsigned extra; +struct nvme_queue *nvmeq; + + depth =min_t (int,NVME_CAP_MQES (readq (&dev->bar->cap)) +1 , depth); + extra =DIV_ROUND_UP (depth,8 ) + (depth *sizeof (struct nvme_cmd_info )); + nvmeq =kzalloc (sizeof (*nvmeq) + extra,GFP_KERNEL );if (!nvmeq)return NULL ;