Drives with MDTS set to zero
Paul Grabinar
paul.grabinar at ranbarg.com
Tue Nov 17 12:51:50 PST 2015
Hi,
I have a drive that sets MDTS to zero. According to the NVMe
specification, that is valid and means that the drive does not have a
limit on the transfer size.
In the current 4.4 kernel driver, we detect this and set
dev->max_hw_sectors to UINT_MAX.
Later, when a namespace is allocated, we set the block level
max_hw_sectors and max_segments based on dev->max_hw_sectors. This
operations perform shifts on the value, but we are already at UINT_MAX,
so end up with strange results.
I'm not entirely sure what is supposed to happen. The following patch
sets max_hw_sectors to
BLK_DEF_MAX_SECTORS and max_segments to BLK_MAX_SEGMENTS, but this still does not seem right, as drives with a large MDTS will set max_segments higher than this.
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 8187df2..be35401 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -2265,11 +2265,12 @@ static void nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid)
list_add_tail(&ns->list, &dev->namespaces);
blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift);
- if (dev->max_hw_sectors) {
- blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors);
- blk_queue_max_segments(ns->queue,
- ((dev->max_hw_sectors << 9) / dev->page_size) + 1);
- }
+ blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors ?
+ dev->max_hw_sectors : BLK_DEF_MAX_SECTORS);
+ blk_queue_max_segments(ns->queue,
+ dev->max_hw_sectors ?
+ ((dev->max_hw_sectors << 9) / dev->page_size) + 1 :
+ BLK_MAX_SEGMENTS);
if (dev->stripe_size)
blk_queue_chunk_sectors(ns->queue, dev->stripe_size >> 9);
if (dev->vwc & NVME_CTRL_VWC_PRESENT)
@@ -2622,8 +2623,6 @@ static int nvme_dev_add(struct nvme_dev *dev)
memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
if (ctrl->mdts)
dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9);
- else
- dev->max_hw_sectors = UINT_MAX;
if ((pdev->vendor == PCI_VENDOR_ID_INTEL) &&
(pdev->device == 0x0953) && ctrl->vs[3]) {
unsigned int max_hw_sectors;
More information about the Linux-nvme
mailing list