From 768308400f5b4ce665a072eb976a851978b7706e Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 10 Feb 2011 13:55:39 -0500 Subject: [PATCH] NVMe: Handle physical merging of bvec entries In order to not overrun the sg array, we have to merge physically contiguous pages into a single sg entry. Signed-off-by: Matthew Wilcox --- drivers/block/nvme.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index bfdca3a3a41a..c0e84b688f50 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -392,19 +392,25 @@ static struct nvme_prps *nvme_setup_prps(struct nvme_dev *dev, static int nvme_map_bio(struct device *dev, struct nvme_bio *nbio, struct bio *bio, enum dma_data_direction dma_dir, int psegs) { - struct bio_vec *bvec; - struct scatterlist *sg = nbio->sg; - int i, nsegs; + struct bio_vec *bvec, *bvprv = NULL; + struct scatterlist *sg = NULL; + int i, nsegs = 0; - sg_init_table(sg, psegs); + sg_init_table(nbio->sg, psegs); bio_for_each_segment(bvec, bio, i) { - sg_set_page(sg, bvec->bv_page, bvec->bv_len, bvec->bv_offset); - sg++; - /* XXX: handle non-mergable here */ - nsegs++; + if (bvprv && BIOVEC_PHYS_MERGEABLE(bvprv, bvec)) { + sg->length += bvec->bv_len; + } else { + /* Check bvprv && offset == 0 */ + sg = sg ? sg + 1 : nbio->sg; + sg_set_page(sg, bvec->bv_page, bvec->bv_len, + bvec->bv_offset); + nsegs++; + } + bvprv = bvec; } nbio->nents = nsegs; - + sg_mark_end(sg); return dma_map_sg(dev, nbio->sg, nbio->nents, dma_dir); } -- 2.34.1