aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeith Busch <keith.busch@intel.com>2013-04-09 19:13:20 -0400
committerMatthew Wilcox <matthew.r.wilcox@intel.com>2013-05-02 14:41:05 -0400
commit159b67d7aefe3902df91075be5d80943c1570aa8 (patch)
tree8c830202c7bc95727ecfc4e6dace6a5d8f4a1ea8
parent427e97080196548557b288517537ab7eb48c309f (diff)
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: Keith Busch <keith.busch@intel.com> Signed-off-by: Matthew Wilcox <matthew.r.wilcox@intel.com>
-rw-r--r--drivers/block/nvme-core.c19
-rw-r--r--include/linux/nvme.h1
2 files changed, 16 insertions, 4 deletions
diff --git a/drivers/block/nvme-core.c b/drivers/block/nvme-core.c
index f81280663a4b..4151a3d26e2d 100644
--- a/drivers/block/nvme-core.c
+++ b/drivers/block/nvme-core.c
@@ -519,7 +519,11 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod,
519{ 519{
520 struct bio_vec *bvec, *bvprv = NULL; 520 struct bio_vec *bvec, *bvprv = NULL;
521 struct scatterlist *sg = NULL; 521 struct scatterlist *sg = NULL;
522 int i, length = 0, nsegs = 0; 522 int i, length = 0, nsegs = 0, split_len = bio->bi_size;
523
524 if (nvmeq->dev->stripe_size)
525 split_len = nvmeq->dev->stripe_size -
526 ((bio->bi_sector << 9) & (nvmeq->dev->stripe_size - 1));
523 527
524 sg_init_table(iod->sg, psegs); 528 sg_init_table(iod->sg, psegs);
525 bio_for_each_segment(bvec, bio, i) { 529 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 bvec->bv_offset); 539 bvec->bv_offset);
536 nsegs++; 540 nsegs++;
537 } 541 }
542
543 if (split_len - length < bvec->bv_len)
544 return nvme_split_and_submit(bio, nvmeq, i, split_len,
545 split_len - length);
538 length += bvec->bv_len; 546 length += bvec->bv_len;
539 bvprv = bvec; 547 bvprv = bvec;
540 } 548 }
@@ -543,6 +551,7 @@ static int nvme_map_bio(struct nvme_queue *nvmeq, struct nvme_iod *iod,
543 if (dma_map_sg(nvmeq->q_dmadev, iod->sg, iod->nents, dma_dir) == 0) 551 if (dma_map_sg(nvmeq->q_dmadev, iod->sg, iod->nents, dma_dir) == 0)
544 return -ENOMEM; 552 return -ENOMEM;
545 553
554 BUG_ON(length != bio->bi_size);
546 return length; 555 return length;
547} 556}
548 557
@@ -1612,6 +1621,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
1612 struct nvme_id_ns *id_ns; 1621 struct nvme_id_ns *id_ns;
1613 void *mem; 1622 void *mem;
1614 dma_addr_t dma_addr; 1623 dma_addr_t dma_addr;
1624 int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
1615 1625
1616 res = nvme_setup_io_queues(dev); 1626 res = nvme_setup_io_queues(dev);
1617 if (res) 1627 if (res)
@@ -1634,10 +1644,11 @@ static int nvme_dev_add(struct nvme_dev *dev)
1634 memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn)); 1644 memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
1635 memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn)); 1645 memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
1636 memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr)); 1646 memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
1637 if (ctrl->mdts) { 1647 if (ctrl->mdts)
1638 int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
1639 dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9); 1648 dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9);
1640 } 1649 if ((dev->pci_dev->vendor == PCI_VENDOR_ID_INTEL) &&
1650 (dev->pci_dev->device == 0x0953) && ctrl->vs[3])
1651 dev->stripe_size = 1 << (ctrl->vs[3] + shift);
1641 1652
1642 id_ns = mem; 1653 id_ns = mem;
1643 for (i = 1; i <= nn; i++) { 1654 for (i = 1; i <= nn; i++) {
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 9b6fba872f47..af29b0e0b092 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -536,6 +536,7 @@ struct nvme_dev {
536 char model[40]; 536 char model[40];
537 char firmware_rev[8]; 537 char firmware_rev[8];
538 u32 max_hw_sectors; 538 u32 max_hw_sectors;
539 u32 stripe_size;
539 u16 oncs; 540 u16 oncs;
540}; 541};
541 542