Commit 159b67d7 authored by Keith Busch's avatar Keith Busch Committed by Matthew Wilcox

NVMe: Device specific stripe size handling

We have an nvme device that has a concept of a stripe size. IO requests
that do not transfer data crossing a stripe boundary has greater
performance compared to IO that does cross it. This patch sets the
stripe size for the device if the device and vendor ids match one with
this feature and splits IO requests that cross the stripe boundary.
Signed-off-by: default avatarKeith Busch <keith.busch@intel.com>
Signed-off-by: default avatarMatthew Wilcox <matthew.r.wilcox@intel.com>
parent 427e9708
...@@ -519,7 +519,11 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod, ...@@ -519,7 +519,11 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod,
{ {
struct bio_vec *bvec, *bvprv = NULL; struct bio_vec *bvec, *bvprv = NULL;
struct scatterlist *sg = NULL; struct scatterlist *sg = NULL;
int i, length = 0, nsegs = 0; int i, length = 0, nsegs = 0, split_len = bio->bi_size;
if (nvmeq->dev->stripe_size)
split_len = nvmeq->dev->stripe_size -
((bio->bi_sector << 9) & (nvmeq->dev->stripe_size - 1));
sg_init_table(iod->sg, psegs); sg_init_table(iod->sg, psegs);
bio_for_each_segment(bvec, bio, i) { bio_for_each_segment(bvec, bio, i) {
...@@ -535,6 +539,10 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod, ...@@ -535,6 +539,10 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod,
bvec->bv_offset); bvec->bv_offset);
nsegs++; nsegs++;
} }
if (split_len - length < bvec->bv_len)
return nvme_split_and_submit(bio, nvmeq, i, split_len,
split_len - length);
length += bvec->bv_len; length += bvec->bv_len;
bvprv = bvec; bvprv = bvec;
} }
...@@ -543,6 +551,7 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod, ...@@ -543,6 +551,7 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod,
if (dma_map_sg(nvmeq->q_dmadev, iod->sg, iod->nents, dma_dir) == 0) if (dma_map_sg(nvmeq->q_dmadev, iod->sg, iod->nents, dma_dir) == 0)
return -ENOMEM; return -ENOMEM;
BUG_ON(length != bio->bi_size);
return length; return length;
} }
...@@ -1612,6 +1621,7 @@ static int nvme_dev_add(struct nvme_dev *dev) ...@@ -1612,6 +1621,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
struct nvme_id_ns *id_ns; struct nvme_id_ns *id_ns;
void *mem; void *mem;
dma_addr_t dma_addr; dma_addr_t dma_addr;
int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
res = nvme_setup_io_queues(dev); res = nvme_setup_io_queues(dev);
if (res) if (res)
...@@ -1634,10 +1644,11 @@ static int nvme_dev_add(struct nvme_dev *dev) ...@@ -1634,10 +1644,11 @@ static int nvme_dev_add(struct nvme_dev *dev)
memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn)); memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn)); memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr)); memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
if (ctrl->mdts) { if (ctrl->mdts)
int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9); dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9);
} if ((dev->pci_dev->vendor == PCI_VENDOR_ID_INTEL) &&
(dev->pci_dev->device == 0x0953) && ctrl->vs[3])
dev->stripe_size = 1 << (ctrl->vs[3] + shift);
id_ns = mem; id_ns = mem;
for (i = 1; i <= nn; i++) { for (i = 1; i <= nn; i++) {
......
...@@ -536,6 +536,7 @@ struct nvme_dev { ...@@ -536,6 +536,7 @@ struct nvme_dev {
char model[40]; char model[40];
char firmware_rev[8]; char firmware_rev[8];
u32 max_hw_sectors; u32 max_hw_sectors;
u32 stripe_size;
u16 oncs; u16 oncs;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment