Skip to content

Commit

Permalink
NVMe: Device specific stripe size handling
Browse files Browse the repository at this point in the history
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: Keith Busch <keith.busch@intel.com>
Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
  • Loading branch information
Keith Busch authored and Matthew Wilcox committed May 2, 2013
1 parent 427e970 commit 159b67d
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 4 deletions.
19 changes: 15 additions & 4 deletions drivers/block/nvme-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,11 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod,
{
struct bio_vec *bvec, *bvprv = 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);
bio_for_each_segment(bvec, bio, i) {
Expand All @@ -535,6 +539,10 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod,
bvec->bv_offset);
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;
bvprv = bvec;
}
Expand All @@ -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)
return -ENOMEM;

BUG_ON(length != bio->bi_size);
return length;
}

Expand Down Expand Up @@ -1612,6 +1621,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
struct nvme_id_ns *id_ns;
void *mem;
dma_addr_t dma_addr;
int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;

res = nvme_setup_io_queues(dev);
if (res)
Expand All @@ -1634,10 +1644,11 @@ static int nvme_dev_add(struct nvme_dev *dev)
memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
if (ctrl->mdts) {
int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
if (ctrl->mdts)
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;
for (i = 1; i <= nn; i++) {
Expand Down
1 change: 1 addition & 0 deletions include/linux/nvme.h
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ struct nvme_dev {
char model[40];
char firmware_rev[8];
u32 max_hw_sectors;
u32 stripe_size;
u16 oncs;
};

Expand Down

0 comments on commit 159b67d

Please sign in to comment.