diff options
-rw-r--r-- | drivers/block/nvme-core.c | 19 | ||||
-rw-r--r-- | include/linux/nvme.h | 1 |
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 | ||