From e8f1e1630b0a98685d1a3521e8aba0dc7e68082c Mon Sep 17 00:00:00 2001 From: Sagi Grimberg Date: Thu, 10 Mar 2016 13:58:49 +0200 Subject: blk-mq: Make blk_mq_all_tag_busy_iter static No caller outside the blk-mq code so we can settle with it static. Signed-off-by: Sagi Grimberg Reviewed-by: Christoph Hellwig Reviewed-by: Johannes Thumshirn Signed-off-by: Jens Axboe --- include/linux/blk-mq.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/linux/blk-mq.h b/include/linux/blk-mq.h index c808fec1ce44..2498fdf3a503 100644 --- a/include/linux/blk-mq.h +++ b/include/linux/blk-mq.h @@ -238,8 +238,6 @@ void blk_mq_start_hw_queues(struct request_queue *q); void blk_mq_start_stopped_hw_queues(struct request_queue *q, bool async); void blk_mq_run_hw_queues(struct request_queue *q, bool async); void blk_mq_delay_queue(struct blk_mq_hw_ctx *hctx, unsigned long msecs); -void blk_mq_all_tag_busy_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn, - void *priv); void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, busy_tag_iter_fn *fn, void *priv); void blk_mq_freeze_queue(struct request_queue *q); -- cgit v1.2.3 From 2245f6de6c68b225986229a2de78c240536f7f38 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 30 Mar 2016 10:19:30 -0600 Subject: block: kill blk_queue_flush() We don't have any drivers left using it, so kill it off. Update documentation to use the newer blk_queue_write_cache(). Signed-off-by: Jens Axboe Reviewed-by: Christoph Hellwig --- Documentation/block/writeback_cache_control.txt | 4 ++-- block/blk-settings.c | 20 -------------------- include/linux/blkdev.h | 1 - 3 files changed, 2 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/Documentation/block/writeback_cache_control.txt b/Documentation/block/writeback_cache_control.txt index 83407d36630a..59e0516cbf6b 100644 --- a/Documentation/block/writeback_cache_control.txt +++ b/Documentation/block/writeback_cache_control.txt @@ -71,7 +71,7 @@ requests that have a payload. For devices with volatile write caches the driver needs to tell the block layer that it supports flushing caches by doing: - blk_queue_flush(sdkp->disk->queue, REQ_FLUSH); + blk_queue_write_cache(sdkp->disk->queue, true, false); and handle empty REQ_FLUSH requests in its prep_fn/request_fn. Note that REQ_FLUSH requests with a payload are automatically turned into a sequence @@ -79,7 +79,7 @@ of an empty REQ_FLUSH request followed by the actual write by the block layer. For devices that also support the FUA bit the block layer needs to be told to pass through the REQ_FUA bit using: - blk_queue_flush(sdkp->disk->queue, REQ_FLUSH | REQ_FUA); + blk_queue_write_cache(sdkp->disk->queue, true, true); and the driver must handle write requests that have the REQ_FUA bit set in prep_fn/request_fn. If the FUA bit is not natively supported the block diff --git a/block/blk-settings.c b/block/blk-settings.c index c903bee43cf8..80d9327a214b 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -820,26 +820,6 @@ void blk_queue_update_dma_alignment(struct request_queue *q, int mask) } EXPORT_SYMBOL(blk_queue_update_dma_alignment); -/** - * blk_queue_flush - configure queue's cache flush capability - * @q: the request queue for the device - * @flush: 0, REQ_FLUSH or REQ_FLUSH | REQ_FUA - * - * Tell block layer cache flush capability of @q. If it supports - * flushing, REQ_FLUSH should be set. If it supports bypassing - * write cache for individual writes, REQ_FUA should be set. - */ -void blk_queue_flush(struct request_queue *q, unsigned int flush) -{ - WARN_ON_ONCE(flush & ~(REQ_FLUSH | REQ_FUA)); - - if (WARN_ON_ONCE(!(flush & REQ_FLUSH) && (flush & REQ_FUA))) - flush &= ~REQ_FUA; - - q->flush_flags = flush & (REQ_FLUSH | REQ_FUA); -} -EXPORT_SYMBOL_GPL(blk_queue_flush); - void blk_queue_flush_queueable(struct request_queue *q, bool queueable) { q->flush_not_queueable = !queueable; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index ba72687c5654..f3f232fa505d 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1009,7 +1009,6 @@ extern void blk_queue_update_dma_alignment(struct request_queue *, int); extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *); extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *); extern void blk_queue_rq_timeout(struct request_queue *, unsigned int); -extern void blk_queue_flush(struct request_queue *q, unsigned int flush); extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable); extern void blk_queue_write_cache(struct request_queue *q, bool enabled, bool fua); extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev); -- cgit v1.2.3 From c888a8f95ae5b1067855235b3b71c1ebccf504f5 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Wed, 13 Apr 2016 13:33:19 -0600 Subject: block: kill off q->flush_flags Now that we converted everything to the newer block write cache interface, kill off the queue flush_flags and queueable flush entries. Signed-off-by: Jens Axboe --- block/blk-core.c | 3 ++- block/blk-flush.c | 11 ++++++----- block/blk-settings.c | 18 ++++++++++-------- drivers/block/xen-blkback/xenbus.c | 2 +- drivers/md/dm-table.c | 12 ++++++------ drivers/md/raid5-cache.c | 3 ++- drivers/target/target_core_iblock.c | 6 +++--- include/linux/blkdev.h | 5 ++--- 8 files changed, 32 insertions(+), 28 deletions(-) (limited to 'include') diff --git a/block/blk-core.c b/block/blk-core.c index c50227796a26..2475b1c72773 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1964,7 +1964,8 @@ generic_make_request_checks(struct bio *bio) * drivers without flush support don't have to worry * about them. */ - if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && !q->flush_flags) { + if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && + !test_bit(QUEUE_FLAG_WC, &q->queue_flags)) { bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA); if (!nr_sectors) { err = 0; diff --git a/block/blk-flush.c b/block/blk-flush.c index 9c423e53324a..b1c91d229e5e 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -95,17 +95,18 @@ enum { static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq); -static unsigned int blk_flush_policy(unsigned int fflags, struct request *rq) +static unsigned int blk_flush_policy(unsigned long fflags, struct request *rq) { unsigned int policy = 0; if (blk_rq_sectors(rq)) policy |= REQ_FSEQ_DATA; - if (fflags & REQ_FLUSH) { + if (fflags & (1UL << QUEUE_FLAG_WC)) { if (rq->cmd_flags & REQ_FLUSH) policy |= REQ_FSEQ_PREFLUSH; - if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA)) + if (!(fflags & (1UL << QUEUE_FLAG_FUA)) && + (rq->cmd_flags & REQ_FUA)) policy |= REQ_FSEQ_POSTFLUSH; } return policy; @@ -384,7 +385,7 @@ static void mq_flush_data_end_io(struct request *rq, int error) void blk_insert_flush(struct request *rq) { struct request_queue *q = rq->q; - unsigned int fflags = q->flush_flags; /* may change, cache */ + unsigned long fflags = q->queue_flags; /* may change, cache */ unsigned int policy = blk_flush_policy(fflags, rq); struct blk_flush_queue *fq = blk_get_flush_queue(q, rq->mq_ctx); @@ -393,7 +394,7 @@ void blk_insert_flush(struct request *rq) * REQ_FLUSH and FUA for the driver. */ rq->cmd_flags &= ~REQ_FLUSH; - if (!(fflags & REQ_FUA)) + if (!(fflags & (1UL << QUEUE_FLAG_FUA))) rq->cmd_flags &= ~REQ_FUA; /* diff --git a/block/blk-settings.c b/block/blk-settings.c index 80d9327a214b..f679ae122843 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -822,7 +822,12 @@ EXPORT_SYMBOL(blk_queue_update_dma_alignment); void blk_queue_flush_queueable(struct request_queue *q, bool queueable) { - q->flush_not_queueable = !queueable; + spin_lock_irq(q->queue_lock); + if (queueable) + clear_bit(QUEUE_FLAG_FLUSH_NQ, &q->queue_flags); + else + set_bit(QUEUE_FLAG_FLUSH_NQ, &q->queue_flags); + spin_unlock_irq(q->queue_lock); } EXPORT_SYMBOL_GPL(blk_queue_flush_queueable); @@ -837,16 +842,13 @@ EXPORT_SYMBOL_GPL(blk_queue_flush_queueable); void blk_queue_write_cache(struct request_queue *q, bool wc, bool fua) { spin_lock_irq(q->queue_lock); - if (wc) { + if (wc) queue_flag_set(QUEUE_FLAG_WC, q); - q->flush_flags = REQ_FLUSH; - } else + else queue_flag_clear(QUEUE_FLAG_WC, q); - if (fua) { - if (wc) - q->flush_flags |= REQ_FUA; + if (fua) queue_flag_set(QUEUE_FLAG_FUA, q); - } else + else queue_flag_clear(QUEUE_FLAG_FUA, q); spin_unlock_irq(q->queue_lock); } diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 26aa080e243c..3355f1cdd4e5 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -477,7 +477,7 @@ static int xen_vbd_create(struct xen_blkif *blkif, blkif_vdev_t handle, vbd->type |= VDISK_REMOVABLE; q = bdev_get_queue(bdev); - if (q && q->flush_flags) + if (q && test_bit(QUEUE_FLAG_WC, &q->queue_flags)) vbd->flush_support = true; if (q && blk_queue_secdiscard(q)) diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 4b1ffc0abe11..626a5ec04466 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -1348,13 +1348,13 @@ static void dm_table_verify_integrity(struct dm_table *t) static int device_flush_capable(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { - unsigned flush = (*(unsigned *)data); + unsigned long flush = (unsigned long) data; struct request_queue *q = bdev_get_queue(dev->bdev); - return q && (q->flush_flags & flush); + return q && (q->queue_flags & flush); } -static bool dm_table_supports_flush(struct dm_table *t, unsigned flush) +static bool dm_table_supports_flush(struct dm_table *t, unsigned long flush) { struct dm_target *ti; unsigned i = 0; @@ -1375,7 +1375,7 @@ static bool dm_table_supports_flush(struct dm_table *t, unsigned flush) return true; if (ti->type->iterate_devices && - ti->type->iterate_devices(ti, device_flush_capable, &flush)) + ti->type->iterate_devices(ti, device_flush_capable, (void *) flush)) return true; } @@ -1518,9 +1518,9 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, else queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q); - if (dm_table_supports_flush(t, REQ_FLUSH)) { + if (dm_table_supports_flush(t, (1UL << QUEUE_FLAG_WC))) { wc = true; - if (dm_table_supports_flush(t, REQ_FUA)) + if (dm_table_supports_flush(t, (1UL << QUEUE_FLAG_FUA))) fua = true; } blk_queue_write_cache(q, wc, fua); diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 9531f5f05b93..26f14970a858 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -1188,6 +1188,7 @@ ioerr: int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev) { + struct request_queue *q = bdev_get_queue(rdev->bdev); struct r5l_log *log; if (PAGE_SIZE != 4096) @@ -1197,7 +1198,7 @@ int r5l_init_log(struct r5conf *conf, struct md_rdev *rdev) return -ENOMEM; log->rdev = rdev; - log->need_cache_flush = (rdev->bdev->bd_disk->queue->flush_flags != 0); + log->need_cache_flush = test_bit(QUEUE_FLAG_WC, &q->queue_flags) != 0; log->uuid_checksum = crc32c_le(~0, rdev->mddev->uuid, sizeof(rdev->mddev->uuid)); diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 026a758e5778..7c4efb4417b0 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -687,10 +687,10 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, * Force writethrough using WRITE_FUA if a volatile write cache * is not enabled, or if initiator set the Force Unit Access bit. */ - if (q->flush_flags & REQ_FUA) { + if (test_bit(QUEUE_FLAG_FUA, &q->queue_flags)) { if (cmd->se_cmd_flags & SCF_FUA) rw = WRITE_FUA; - else if (!(q->flush_flags & REQ_FLUSH)) + else if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) rw = WRITE_FUA; else rw = WRITE; @@ -836,7 +836,7 @@ static bool iblock_get_write_cache(struct se_device *dev) struct block_device *bd = ib_dev->ibd_bd; struct request_queue *q = bdev_get_queue(bd); - return q->flush_flags & REQ_FLUSH; + return test_bit(QUEUE_FLAG_WC, &q->queue_flags); } static const struct target_backend_ops iblock_ops = { diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index f3f232fa505d..57c085917da6 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -433,8 +433,6 @@ struct request_queue { /* * for flush operations */ - unsigned int flush_flags; - unsigned int flush_not_queueable:1; struct blk_flush_queue *fq; struct list_head requeue_list; @@ -493,6 +491,7 @@ struct request_queue { #define QUEUE_FLAG_POLL 22 /* IO polling enabled if set */ #define QUEUE_FLAG_WC 23 /* Write back caching */ #define QUEUE_FLAG_FUA 24 /* device supports FUA writes */ +#define QUEUE_FLAG_FLUSH_NQ 25 /* flush not queueuable */ #define QUEUE_FLAG_DEFAULT ((1 << QUEUE_FLAG_IO_STAT) | \ (1 << QUEUE_FLAG_STACKABLE) | \ @@ -1365,7 +1364,7 @@ static inline unsigned int block_size(struct block_device *bdev) static inline bool queue_flush_queueable(struct request_queue *q) { - return !q->flush_not_queueable; + return !test_bit(QUEUE_FLAG_FLUSH_NQ, &q->queue_flags); } typedef struct {struct page *v;} Sector; -- cgit v1.2.3 From a5b714ad395803a6aa91793b9e52a81b176b8ba9 Mon Sep 17 00:00:00 2001 From: Wang Sheng-Hui Date: Wed, 27 Apr 2016 20:10:16 +0800 Subject: NVMe: correct comment for offset enum of controller registers in nvme.h Section 3.1 gives the comment for the offset of controller registers in the specification 1.2a. Some are mis-copied in the header file nvme.h. Correct them. Signed-off-by: Wang Sheng-Hui Reviewed-by: Christoph Hellwig Reviewed-by: Sagi Grimberg Signed-off-by: Jens Axboe --- include/linux/nvme.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/nvme.h b/include/linux/nvme.h index a55986f6fe38..7d51b2904cb7 100644 --- a/include/linux/nvme.h +++ b/include/linux/nvme.h @@ -21,13 +21,13 @@ enum { NVME_REG_CAP = 0x0000, /* Controller Capabilities */ NVME_REG_VS = 0x0008, /* Version */ NVME_REG_INTMS = 0x000c, /* Interrupt Mask Set */ - NVME_REG_INTMC = 0x0010, /* Interrupt Mask Set */ + NVME_REG_INTMC = 0x0010, /* Interrupt Mask Clear */ NVME_REG_CC = 0x0014, /* Controller Configuration */ NVME_REG_CSTS = 0x001c, /* Controller Status */ NVME_REG_NSSR = 0x0020, /* NVM Subsystem Reset */ NVME_REG_AQA = 0x0024, /* Admin Queue Attributes */ NVME_REG_ASQ = 0x0028, /* Admin SQ Base Address */ - NVME_REG_ACQ = 0x0030, /* Admin SQ Base Address */ + NVME_REG_ACQ = 0x0030, /* Admin CQ Base Address */ NVME_REG_CMBLOC = 0x0038, /* Controller Memory Buffer Location */ NVME_REG_CMBSZ = 0x003c, /* Controller Memory Buffer Size */ }; -- cgit v1.2.3 From 1145e6351a9fefe0965df4c6dba2a04156dc47d2 Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Fri, 6 May 2016 20:02:56 +0200 Subject: lightnvm: implement nvm_submit_ppa_list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nvm_submit_ppa function assumes that users manage all plane blocks as a single block. Extend the API with nvm_submit_ppa_list to allow the user to send its own ppa list. If the user submits more than a single PPA, the user must take care to allocate and free the corresponding ppa list. Reviewed by: Johannes Thumshirn Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 88 +++++++++++++++++++++++++++++++++++++----------- include/linux/lightnvm.h | 2 ++ 2 files changed, 71 insertions(+), 19 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index c2ef53a0d7f8..f4e04a505859 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -322,11 +322,10 @@ static void nvm_end_io_sync(struct nvm_rq *rqd) complete(waiting); } -int nvm_submit_ppa(struct nvm_dev *dev, struct ppa_addr *ppa, int nr_ppas, - int opcode, int flags, void *buf, int len) +int __nvm_submit_ppa(struct nvm_dev *dev, struct nvm_rq *rqd, int opcode, + int flags, void *buf, int len) { DECLARE_COMPLETION_ONSTACK(wait); - struct nvm_rq rqd; struct bio *bio; int ret; unsigned long hang_check; @@ -335,24 +334,17 @@ int nvm_submit_ppa(struct nvm_dev *dev, struct ppa_addr *ppa, int nr_ppas, if (IS_ERR_OR_NULL(bio)) return -ENOMEM; - memset(&rqd, 0, sizeof(struct nvm_rq)); - ret = nvm_set_rqd_ppalist(dev, &rqd, ppa, nr_ppas); - if (ret) { - bio_put(bio); - return ret; - } + nvm_generic_to_addr_mode(dev, rqd); - rqd.opcode = opcode; - rqd.bio = bio; - rqd.wait = &wait; - rqd.dev = dev; - rqd.end_io = nvm_end_io_sync; - rqd.flags = flags; - nvm_generic_to_addr_mode(dev, &rqd); + rqd->dev = dev; + rqd->opcode = opcode; + rqd->flags = flags; + rqd->bio = bio; + rqd->wait = &wait; + rqd->end_io = nvm_end_io_sync; - ret = dev->ops->submit_io(dev, &rqd); + ret = dev->ops->submit_io(dev, rqd); if (ret) { - nvm_free_rqd_ppalist(dev, &rqd); bio_put(bio); return ret; } @@ -364,9 +356,67 @@ int nvm_submit_ppa(struct nvm_dev *dev, struct ppa_addr *ppa, int nr_ppas, else wait_for_completion_io(&wait); + return rqd->error; +} + +/** + * nvm_submit_ppa_list - submit user-defined ppa list to device. The user must + * take to free ppa list if necessary. + * @dev: device + * @ppa_list: user created ppa_list + * @nr_ppas: length of ppa_list + * @opcode: device opcode + * @flags: device flags + * @buf: data buffer + * @len: data buffer length + */ +int nvm_submit_ppa_list(struct nvm_dev *dev, struct ppa_addr *ppa_list, + int nr_ppas, int opcode, int flags, void *buf, int len) +{ + struct nvm_rq rqd; + + if (dev->ops->max_phys_sect < nr_ppas) + return -EINVAL; + + memset(&rqd, 0, sizeof(struct nvm_rq)); + + rqd.nr_pages = nr_ppas; + if (nr_ppas > 1) + rqd.ppa_list = ppa_list; + else + rqd.ppa_addr = ppa_list[0]; + + return __nvm_submit_ppa(dev, &rqd, opcode, flags, buf, len); +} +EXPORT_SYMBOL(nvm_submit_ppa_list); + +/** + * nvm_submit_ppa - submit PPAs to device. PPAs will automatically be unfolded + * as single, dual, quad plane PPAs depending on device type. + * @dev: device + * @ppa: user created ppa_list + * @nr_ppas: length of ppa_list + * @opcode: device opcode + * @flags: device flags + * @buf: data buffer + * @len: data buffer length + */ +int nvm_submit_ppa(struct nvm_dev *dev, struct ppa_addr *ppa, int nr_ppas, + int opcode, int flags, void *buf, int len) +{ + struct nvm_rq rqd; + int ret; + + memset(&rqd, 0, sizeof(struct nvm_rq)); + ret = nvm_set_rqd_ppalist(dev, &rqd, ppa, nr_ppas); + if (ret) + return ret; + + ret = __nvm_submit_ppa(dev, &rqd, opcode, flags, buf, len); + nvm_free_rqd_ppalist(dev, &rqd); - return rqd.error; + return ret; } EXPORT_SYMBOL(nvm_submit_ppa); diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index cdcb2ccbefa8..38814e262872 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -534,6 +534,8 @@ extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *); extern void nvm_end_io(struct nvm_rq *, int); extern int nvm_submit_ppa(struct nvm_dev *, struct ppa_addr *, int, int, int, void *, int); +extern int nvm_submit_ppa_list(struct nvm_dev *, struct ppa_addr *, int, int, + int, void *, int); /* sysblk.c */ #define NVM_SYSBLK_MAGIC 0x4E564D53 /* "NVMS" */ -- cgit v1.2.3 From 4891d120b9cd419f4350b11e1231083745dcdc8b Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Fri, 6 May 2016 20:02:57 +0200 Subject: lightnvm: add fpg_size and pfpg_size to struct nvm_dev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The flash page size (fpg) and size across planes (pfpg) are convenient to know when allocating buffer sizes. This has previously been a calculated in various places. Replace with the pre-calculated values. Reviewed by: Johannes Thumshirn Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 2 ++ drivers/lightnvm/sysblk.c | 17 +++++++---------- include/linux/lightnvm.h | 2 ++ 3 files changed, 11 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index f4e04a505859..652b8c7673ee 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -476,6 +476,8 @@ static int nvm_core_init(struct nvm_dev *dev) dev->pgs_per_blk = grp->num_pg; dev->blks_per_lun = grp->num_blk; dev->nr_planes = grp->num_pln; + dev->fpg_size = grp->fpg_sz; + dev->pfpg_size = grp->fpg_sz * grp->num_pln; dev->sec_size = grp->csecs; dev->oob_size = grp->sos; dev->sec_per_pg = grp->fpg_sz / grp->csecs; diff --git a/drivers/lightnvm/sysblk.c b/drivers/lightnvm/sysblk.c index b1e1404e6951..b6971f8ae3c0 100644 --- a/drivers/lightnvm/sysblk.c +++ b/drivers/lightnvm/sysblk.c @@ -154,13 +154,12 @@ static int nvm_scan_block(struct nvm_dev *dev, struct ppa_addr *ppa, struct nvm_system_block *sblk) { struct nvm_system_block *cur; - int pg, cursz, ret, found = 0; + int pg, ret, found = 0; /* the full buffer for a flash page is allocated. Only the first of it * contains the system block information */ - cursz = dev->sec_size * dev->sec_per_pg * dev->nr_planes; - cur = kmalloc(cursz, GFP_KERNEL); + cur = kmalloc(dev->pfpg_size, GFP_KERNEL); if (!cur) return -ENOMEM; @@ -169,7 +168,7 @@ static int nvm_scan_block(struct nvm_dev *dev, struct ppa_addr *ppa, ppa->g.pg = ppa_to_slc(dev, pg); ret = nvm_submit_ppa(dev, ppa, 1, NVM_OP_PREAD, NVM_IO_SLC_MODE, - cur, cursz); + cur, dev->pfpg_size); if (ret) { if (ret == NVM_RSP_ERR_EMPTYPAGE) { pr_debug("nvm: sysblk scan empty ppa (%u %u %u %u)\n", @@ -272,14 +271,12 @@ static int nvm_write_and_verify(struct nvm_dev *dev, struct nvm_sb_info *info, { struct nvm_system_block nvmsb; void *buf; - int i, sect, ret = 0, bufsz; + int i, sect, ret = 0; struct ppa_addr *ppas; nvm_cpu_to_sysblk(&nvmsb, info); - /* buffer for flash page */ - bufsz = dev->sec_size * dev->sec_per_pg * dev->nr_planes; - buf = kzalloc(bufsz, GFP_KERNEL); + buf = kzalloc(dev->pfpg_size, GFP_KERNEL); if (!buf) return -ENOMEM; memcpy(buf, &nvmsb, sizeof(struct nvm_system_block)); @@ -309,7 +306,7 @@ static int nvm_write_and_verify(struct nvm_dev *dev, struct nvm_sb_info *info, } ret = nvm_submit_ppa(dev, ppas, dev->sec_per_pg, NVM_OP_PWRITE, - NVM_IO_SLC_MODE, buf, bufsz); + NVM_IO_SLC_MODE, buf, dev->pfpg_size); if (ret) { pr_err("nvm: sysblk failed program (%u %u %u)\n", ppas[0].g.ch, @@ -319,7 +316,7 @@ static int nvm_write_and_verify(struct nvm_dev *dev, struct nvm_sb_info *info, } ret = nvm_submit_ppa(dev, ppas, dev->sec_per_pg, NVM_OP_PREAD, - NVM_IO_SLC_MODE, buf, bufsz); + NVM_IO_SLC_MODE, buf, dev->pfpg_size); if (ret) { pr_err("nvm: sysblk failed read (%u %u %u)\n", ppas[0].g.ch, diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 38814e262872..f7c607f96858 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -323,6 +323,8 @@ struct nvm_dev { int sec_per_pg; /* only sectors for a single page */ int pgs_per_blk; int blks_per_lun; + int fpg_size; + int pfpg_size; /* size of buffer if all pages are to be read */ int sec_size; int oob_size; int mccap; -- cgit v1.2.3 From 22e8c9766a669d49cf3749d397082a5cd93374a9 Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Fri, 6 May 2016 20:02:58 +0200 Subject: lightnvm: move block fold outside of get_bb_tbl() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The get block table command returns a list of blocks and planes with their associated state. Users, such as gennvm and sysblk, manages all planes as a single virtual block. It was therefore natural to fold the bad block list before it is returned. However, to allow users, which manages on a per-plane block level, to also use the interface, the get_bb_tbl interface is changed to not fold by default and instead let the caller fold if necessary. Reviewed by: Johannes Thumshirn Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 35 +++++++++++++++++++++++++++++++++ drivers/lightnvm/gennvm.c | 14 +++++++------ drivers/lightnvm/sysblk.c | 29 ++++++++++++++++++--------- drivers/nvme/host/lightnvm.c | 47 ++++++-------------------------------------- include/linux/lightnvm.h | 6 ++++-- 5 files changed, 73 insertions(+), 58 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 652b8c7673ee..4cadbe0cd537 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -420,6 +420,41 @@ int nvm_submit_ppa(struct nvm_dev *dev, struct ppa_addr *ppa, int nr_ppas, } EXPORT_SYMBOL(nvm_submit_ppa); +/* + * folds a bad block list from its plane representation to its virtual + * block representation. The fold is done in place and reduced size is + * returned. + * + * If any of the planes status are bad or grown bad block, the virtual block + * is marked bad. If not bad, the first plane state acts as the block state. + */ +int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks) +{ + int blk, offset, pl, blktype; + + if (nr_blks != dev->blks_per_lun * dev->plane_mode) + return -EINVAL; + + for (blk = 0; blk < dev->blks_per_lun; blk++) { + offset = blk * dev->plane_mode; + blktype = blks[offset]; + + /* Bad blocks on any planes take precedence over other types */ + for (pl = 0; pl < dev->plane_mode; pl++) { + if (blks[offset + pl] & + (NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) { + blktype = blks[offset + pl]; + break; + } + } + + blks[blk] = blktype; + } + + return dev->blks_per_lun; +} +EXPORT_SYMBOL(nvm_bb_tbl_fold); + static int nvm_init_slc_tbl(struct nvm_dev *dev, struct nvm_id_group *grp) { int i; diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c index 72e124a3927d..6096077c5dde 100644 --- a/drivers/lightnvm/gennvm.c +++ b/drivers/lightnvm/gennvm.c @@ -129,18 +129,21 @@ static int gennvm_luns_init(struct nvm_dev *dev, struct gen_nvm *gn) return 0; } -static int gennvm_block_bb(struct ppa_addr ppa, int nr_blocks, u8 *blks, - void *private) +static int gennvm_block_bb(struct nvm_dev *dev, struct ppa_addr ppa, + u8 *blks, int nr_blks, void *private) { struct gen_nvm *gn = private; - struct nvm_dev *dev = gn->dev; struct gen_lun *lun; struct nvm_block *blk; int i; + nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); + if (nr_blks < 0) + return nr_blks; + lun = &gn->luns[(dev->luns_per_chnl * ppa.g.ch) + ppa.g.lun]; - for (i = 0; i < nr_blocks; i++) { + for (i = 0; i < nr_blks; i++) { if (blks[i] == 0) continue; @@ -250,8 +253,7 @@ static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn) ppa = generic_to_dev_addr(dev, ppa); ret = dev->ops->get_bb_tbl(dev, ppa, - dev->blks_per_lun, - gennvm_block_bb, gn); + gennvm_block_bb, gn); if (ret) pr_err("gennvm: could not read BB table\n"); } diff --git a/drivers/lightnvm/sysblk.c b/drivers/lightnvm/sysblk.c index b6971f8ae3c0..7fce58833a07 100644 --- a/drivers/lightnvm/sysblk.c +++ b/drivers/lightnvm/sysblk.c @@ -93,12 +93,16 @@ void nvm_setup_sysblk_scan(struct nvm_dev *dev, struct sysblk_scan *s, s->nr_rows = nvm_setup_sysblks(dev, sysblk_ppas); } -static int sysblk_get_host_blks(struct ppa_addr ppa, int nr_blks, u8 *blks, - void *private) +static int sysblk_get_host_blks(struct nvm_dev *dev, struct ppa_addr ppa, + u8 *blks, int nr_blks, void *private) { struct sysblk_scan *s = private; int i, nr_sysblk = 0; + nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); + if (nr_blks < 0) + return nr_blks; + for (i = 0; i < nr_blks; i++) { if (blks[i] != NVM_BLK_T_HOST) continue; @@ -130,7 +134,7 @@ static int nvm_get_all_sysblks(struct nvm_dev *dev, struct sysblk_scan *s, dppa = generic_to_dev_addr(dev, ppas[i]); s->row = i; - ret = dev->ops->get_bb_tbl(dev, dppa, dev->blks_per_lun, fn, s); + ret = dev->ops->get_bb_tbl(dev, dppa, fn, s); if (ret) { pr_err("nvm: failed bb tbl for ppa (%u %u)\n", ppas[i].g.ch, @@ -235,13 +239,17 @@ static int nvm_set_bb_tbl(struct nvm_dev *dev, struct sysblk_scan *s, int type) return 0; } -static int sysblk_get_free_blks(struct ppa_addr ppa, int nr_blks, u8 *blks, - void *private) +static int sysblk_get_free_blks(struct nvm_dev *dev, struct ppa_addr ppa, + u8 *blks, int nr_blks, void *private) { struct sysblk_scan *s = private; struct ppa_addr *sppa; int i, blkid = 0; + nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); + if (nr_blks < 0) + return nr_blks; + for (i = 0; i < nr_blks; i++) { if (blks[i] == NVM_BLK_T_HOST) return -EEXIST; @@ -578,13 +586,16 @@ static unsigned int factory_blk_offset(struct nvm_dev *dev, int ch, int lun) BITS_PER_LONG; } -static int nvm_factory_blks(struct ppa_addr ppa, int nr_blks, u8 *blks, - void *private) +static int nvm_factory_blks(struct nvm_dev *dev, struct ppa_addr ppa, + u8 *blks, int nr_blks, void *private) { struct factory_blks *f = private; - struct nvm_dev *dev = f->dev; int i, lunoff; + nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); + if (nr_blks < 0) + return nr_blks; + lunoff = factory_blk_offset(dev, ppa.g.ch, ppa.g.lun); /* non-set bits correspond to the block must be erased */ @@ -661,7 +672,7 @@ static int nvm_fact_get_bb_tbl(struct nvm_dev *dev, struct ppa_addr ppa, dev_ppa = generic_to_dev_addr(dev, ppa); - ret = dev->ops->get_bb_tbl(dev, dev_ppa, dev->blks_per_lun, fn, priv); + ret = dev->ops->get_bb_tbl(dev, dev_ppa, fn, priv); if (ret) pr_err("nvm: failed bb tbl for ch%u lun%u\n", ppa.g.ch, ppa.g.blk); diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index 9461dd639acd..d289980d2bc8 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c @@ -387,41 +387,16 @@ out: return ret; } -static void nvme_nvm_bb_tbl_fold(struct nvm_dev *nvmdev, - int nr_dst_blks, u8 *dst_blks, - int nr_src_blks, u8 *src_blks) -{ - int blk, offset, pl, blktype; - - for (blk = 0; blk < nr_dst_blks; blk++) { - offset = blk * nvmdev->plane_mode; - blktype = src_blks[offset]; - - /* Bad blocks on any planes take precedence over other types */ - for (pl = 0; pl < nvmdev->plane_mode; pl++) { - if (src_blks[offset + pl] & - (NVM_BLK_T_BAD|NVM_BLK_T_GRWN_BAD)) { - blktype = src_blks[offset + pl]; - break; - } - } - - dst_blks[blk] = blktype; - } -} - static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa, - int nr_dst_blks, nvm_bb_update_fn *update_bbtbl, - void *priv) + nvm_bb_update_fn *update_bbtbl, void *priv) { struct request_queue *q = nvmdev->q; struct nvme_ns *ns = q->queuedata; struct nvme_ctrl *ctrl = ns->ctrl; struct nvme_nvm_command c = {}; struct nvme_nvm_bb_tbl *bb_tbl; - u8 *dst_blks = NULL; - int nr_src_blks = nr_dst_blks * nvmdev->plane_mode; - int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_src_blks; + int nr_blks = nvmdev->blks_per_lun * nvmdev->plane_mode; + int tblsz = sizeof(struct nvme_nvm_bb_tbl) + nr_blks; int ret = 0; c.get_bb.opcode = nvme_nvm_admin_get_bb_tbl; @@ -432,12 +407,6 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa, if (!bb_tbl) return -ENOMEM; - dst_blks = kzalloc(nr_dst_blks, GFP_KERNEL); - if (!dst_blks) { - ret = -ENOMEM; - goto out; - } - ret = nvme_submit_sync_cmd(ctrl->admin_q, (struct nvme_command *)&c, bb_tbl, tblsz); if (ret) { @@ -459,21 +428,17 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa, goto out; } - if (le32_to_cpu(bb_tbl->tblks) != nr_src_blks) { + if (le32_to_cpu(bb_tbl->tblks) != nr_blks) { ret = -EINVAL; dev_err(ctrl->dev, "bbt unsuspected blocks returned (%u!=%u)", - le32_to_cpu(bb_tbl->tblks), nr_src_blks); + le32_to_cpu(bb_tbl->tblks), nr_blks); goto out; } - nvme_nvm_bb_tbl_fold(nvmdev, nr_dst_blks, dst_blks, - nr_src_blks, bb_tbl->blk); - ppa = dev_to_generic_addr(nvmdev, ppa); - ret = update_bbtbl(ppa, nr_dst_blks, dst_blks, priv); + ret = update_bbtbl(nvmdev, ppa, bb_tbl->blk, nr_blks, priv); out: - kfree(dst_blks); kfree(bb_tbl); return ret; } diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index f7c607f96858..dacaa2850428 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -41,11 +41,12 @@ struct nvm_id; struct nvm_dev; typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *); -typedef int (nvm_bb_update_fn)(struct ppa_addr, int, u8 *, void *); +typedef int (nvm_bb_update_fn)(struct nvm_dev *, struct ppa_addr, u8 *, int, + void *); typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *); typedef int (nvm_get_l2p_tbl_fn)(struct nvm_dev *, u64, u32, nvm_l2p_update_fn *, void *); -typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, int, +typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, nvm_bb_update_fn *, void *); typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct nvm_rq *, int); typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); @@ -538,6 +539,7 @@ extern int nvm_submit_ppa(struct nvm_dev *, struct ppa_addr *, int, int, int, void *, int); extern int nvm_submit_ppa_list(struct nvm_dev *, struct ppa_addr *, int, int, int, void *, int); +extern int nvm_bb_tbl_fold(struct nvm_dev *, u8 *, int); /* sysblk.c */ #define NVM_SYSBLK_MAGIC 0x4E564D53 /* "NVMS" */ -- cgit v1.2.3 From 6063fe399d0913e7bd4462650cd4f31b479a83c9 Mon Sep 17 00:00:00 2001 From: "Simon A. F. Lund" Date: Fri, 6 May 2016 20:03:02 +0200 Subject: lightnvm: rename nvm_targets to nvm_tgt_type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The functions nvm_register_target(), nvm_unregister_target() and associated list refers to a target type that is being registered by a target type module. Rename nvm_*_targets() to nvm_*_tgt_type(), so that the intension is clear. This enables target instances to use the _nvm_*_targets() naming. Signed-off-by: Simon A. F. Lund Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 16 ++++++++-------- drivers/lightnvm/rrpc.c | 4 ++-- include/linux/lightnvm.h | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 74fb049e0b83..240b4731c35e 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -30,7 +30,7 @@ #include #include -static LIST_HEAD(nvm_targets); +static LIST_HEAD(nvm_tgt_types); static LIST_HEAD(nvm_mgrs); static LIST_HEAD(nvm_devices); static DECLARE_RWSEM(nvm_lock); @@ -39,14 +39,14 @@ static struct nvm_tgt_type *nvm_find_target_type(const char *name) { struct nvm_tgt_type *tt; - list_for_each_entry(tt, &nvm_targets, list) + list_for_each_entry(tt, &nvm_tgt_types, list) if (!strcmp(name, tt->name)) return tt; return NULL; } -int nvm_register_target(struct nvm_tgt_type *tt) +int nvm_register_tgt_type(struct nvm_tgt_type *tt) { int ret = 0; @@ -54,14 +54,14 @@ int nvm_register_target(struct nvm_tgt_type *tt) if (nvm_find_target_type(tt->name)) ret = -EEXIST; else - list_add(&tt->list, &nvm_targets); + list_add(&tt->list, &nvm_tgt_types); up_write(&nvm_lock); return ret; } -EXPORT_SYMBOL(nvm_register_target); +EXPORT_SYMBOL(nvm_register_tgt_type); -void nvm_unregister_target(struct nvm_tgt_type *tt) +void nvm_unregister_tgt_type(struct nvm_tgt_type *tt) { if (!tt) return; @@ -70,7 +70,7 @@ void nvm_unregister_target(struct nvm_tgt_type *tt) list_del(&tt->list); up_write(&nvm_lock); } -EXPORT_SYMBOL(nvm_unregister_target); +EXPORT_SYMBOL(nvm_unregister_tgt_type); void *nvm_dev_dma_alloc(struct nvm_dev *dev, gfp_t mem_flags, dma_addr_t *dma_handler) @@ -1020,7 +1020,7 @@ static long nvm_ioctl_info(struct file *file, void __user *arg) info->version[2] = NVM_VERSION_PATCH; down_write(&nvm_lock); - list_for_each_entry(tt, &nvm_targets, list) { + list_for_each_entry(tt, &nvm_tgt_types, list) { struct nvm_ioctl_info_tgt *tgt = &info->tgts[tgt_iter]; tgt->version[0] = tt->version[0]; diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c index 3143b980ac06..c7fef71f4276 100644 --- a/drivers/lightnvm/rrpc.c +++ b/drivers/lightnvm/rrpc.c @@ -1469,12 +1469,12 @@ static struct nvm_tgt_type tt_rrpc = { static int __init rrpc_module_init(void) { - return nvm_register_target(&tt_rrpc); + return nvm_register_tgt_type(&tt_rrpc); } static void rrpc_module_exit(void) { - nvm_unregister_target(&tt_rrpc); + nvm_unregister_tgt_type(&tt_rrpc); } module_init(rrpc_module_init); diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index dacaa2850428..497da91510b2 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -453,8 +453,8 @@ struct nvm_tgt_type { struct list_head list; }; -extern int nvm_register_target(struct nvm_tgt_type *); -extern void nvm_unregister_target(struct nvm_tgt_type *); +extern int nvm_register_tgt_type(struct nvm_tgt_type *); +extern void nvm_unregister_tgt_type(struct nvm_tgt_type *); extern void *nvm_dev_dma_alloc(struct nvm_dev *, gfp_t, dma_addr_t *); extern void nvm_dev_dma_free(struct nvm_dev *, void *, dma_addr_t); -- cgit v1.2.3 From 6f8645cba54a4b2983bbd46f462b5891ffbd72fc Mon Sep 17 00:00:00 2001 From: "Simon A. F. Lund" Date: Fri, 6 May 2016 20:03:03 +0200 Subject: lightnvm: refactor dev->online_target to global nvm_targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A target name must be unique. However, a per-device registration of targets is maintained on a dev->online_targets list, with a per-device search for targets upon registration. This results in a name collision when two targets, with the same name, are created on two different targets, where the per-device list is not shared. Signed-off-by: Simon A. F. Lund Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 47 +++++++++++++++++++++++++---------------------- include/linux/lightnvm.h | 1 - 2 files changed, 25 insertions(+), 23 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 240b4731c35e..0296223392f7 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -33,8 +33,20 @@ static LIST_HEAD(nvm_tgt_types); static LIST_HEAD(nvm_mgrs); static LIST_HEAD(nvm_devices); +static LIST_HEAD(nvm_targets); static DECLARE_RWSEM(nvm_lock); +static struct nvm_target *nvm_find_target(const char *name) +{ + struct nvm_target *tgt; + + list_for_each_entry(tgt, &nvm_targets, list) + if (!strcmp(name, tgt->disk->disk_name)) + return tgt; + + return NULL; +} + static struct nvm_tgt_type *nvm_find_target_type(const char *name) { struct nvm_tgt_type *tt; @@ -564,7 +576,6 @@ static int nvm_core_init(struct nvm_dev *dev) goto err_fmtype; } - INIT_LIST_HEAD(&dev->online_targets); mutex_init(&dev->mlock); spin_lock_init(&dev->lock); @@ -744,12 +755,11 @@ static int nvm_create_target(struct nvm_dev *dev, return -EINVAL; } - list_for_each_entry(t, &dev->online_targets, list) { - if (!strcmp(create->tgtname, t->disk->disk_name)) { - pr_err("nvm: target name already exists.\n"); - up_write(&nvm_lock); - return -EINVAL; - } + t = nvm_find_target(create->tgtname); + if (t) { + pr_err("nvm: target name already exists.\n"); + up_write(&nvm_lock); + return -EINVAL; } up_write(&nvm_lock); @@ -789,7 +799,7 @@ static int nvm_create_target(struct nvm_dev *dev, t->disk = tdisk; down_write(&nvm_lock); - list_add_tail(&t->list, &dev->online_targets); + list_add_tail(&t->list, &nvm_targets); up_write(&nvm_lock); return 0; @@ -852,26 +862,19 @@ static int __nvm_configure_create(struct nvm_ioctl_create *create) static int __nvm_configure_remove(struct nvm_ioctl_remove *remove) { - struct nvm_target *t = NULL; - struct nvm_dev *dev; - int ret = -1; + struct nvm_target *t; down_write(&nvm_lock); - list_for_each_entry(dev, &nvm_devices, devices) - list_for_each_entry(t, &dev->online_targets, list) { - if (!strcmp(remove->tgtname, t->disk->disk_name)) { - nvm_remove_target(t); - ret = 0; - break; - } - } - up_write(&nvm_lock); - - if (ret) { + t = nvm_find_target(remove->tgtname); + if (!t) { pr_err("nvm: target \"%s\" doesn't exist.\n", remove->tgtname); + up_write(&nvm_lock); return -EINVAL; } + nvm_remove_target(t); + up_write(&nvm_lock); + return 0; } diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 497da91510b2..5eabdbaa87bc 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -308,7 +308,6 @@ struct nvm_dev { struct nvm_dev_ops *ops; struct list_head devices; - struct list_head online_targets; /* Media manager */ struct nvmm_type *mt; -- cgit v1.2.3 From 5136061ce705210b501ed9ecd673a67b74ebe017 Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Fri, 6 May 2016 20:03:04 +0200 Subject: lightnvm: introduce nvm_for_each_lun_ppa() macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Users that wish to iterate all luns on a device. Must create a struct ppa_addr and separate iterators for channels and luns. To set the iterators, two loops are required, one to iterate channels, and another to iterate luns. This leads to decrease in readability. Introduce nvm_for_each_lun_ppa, which implements the nested loop and sets ppa, channel, and lun variable for each loop body, eliminating the boilerplate code. Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/sysblk.c | 64 +++++++++++++++++++---------------------------- include/linux/lightnvm.h | 7 ++++++ 2 files changed, 33 insertions(+), 38 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/sysblk.c b/drivers/lightnvm/sysblk.c index 7fce58833a07..a48093d17fea 100644 --- a/drivers/lightnvm/sysblk.c +++ b/drivers/lightnvm/sysblk.c @@ -631,33 +631,28 @@ static int nvm_fact_get_blks(struct nvm_dev *dev, struct ppa_addr *erase_list, while (!done) { done = 1; - for (ch = 0; ch < dev->nr_chnls; ch++) { - for (lun = 0; lun < dev->luns_per_chnl; lun++) { - idx = factory_blk_offset(dev, ch, lun); - offset = &f->blks[idx]; - - blkid = find_first_zero_bit(offset, - dev->blks_per_lun); - if (blkid >= dev->blks_per_lun) - continue; - set_bit(blkid, offset); - - ppa.ppa = 0; - ppa.g.ch = ch; - ppa.g.lun = lun; - ppa.g.blk = blkid; - pr_debug("nvm: erase ppa (%u %u %u)\n", - ppa.g.ch, - ppa.g.lun, - ppa.g.blk); - - erase_list[ppa_cnt] = ppa; - ppa_cnt++; - done = 0; - - if (ppa_cnt == max_ppas) - return ppa_cnt; - } + nvm_for_each_lun_ppa(dev, ppa, ch, lun) { + idx = factory_blk_offset(dev, ch, lun); + offset = &f->blks[idx]; + + blkid = find_first_zero_bit(offset, + dev->blks_per_lun); + if (blkid >= dev->blks_per_lun) + continue; + set_bit(blkid, offset); + + ppa.g.blk = blkid; + pr_debug("nvm: erase ppa (%u %u %u)\n", + ppa.g.ch, + ppa.g.lun, + ppa.g.blk); + + erase_list[ppa_cnt] = ppa; + ppa_cnt++; + done = 0; + + if (ppa_cnt == max_ppas) + return ppa_cnt; } } @@ -684,17 +679,10 @@ static int nvm_fact_select_blks(struct nvm_dev *dev, struct factory_blks *f) int ch, lun, ret; struct ppa_addr ppa; - ppa.ppa = 0; - for (ch = 0; ch < dev->nr_chnls; ch++) { - for (lun = 0; lun < dev->luns_per_chnl; lun++) { - ppa.g.ch = ch; - ppa.g.lun = lun; - - ret = nvm_fact_get_bb_tbl(dev, ppa, nvm_factory_blks, - f); - if (ret) - return ret; - } + nvm_for_each_lun_ppa(dev, ppa, ch, lun) { + ret = nvm_fact_get_bb_tbl(dev, ppa, nvm_factory_blks, f); + if (ret) + return ret; } return 0; diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 5eabdbaa87bc..3f256355b9fa 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -559,6 +559,13 @@ extern int nvm_update_sysblock(struct nvm_dev *, struct nvm_sb_info *); extern int nvm_init_sysblock(struct nvm_dev *, struct nvm_sb_info *); extern int nvm_dev_factory(struct nvm_dev *, int flags); + +#define nvm_for_each_lun_ppa(dev, ppa, chid, lunid) \ + for ((chid) = 0, (ppa).ppa = 0; (chid) < (dev)->nr_chnls; \ + (chid)++, (ppa).g.ch = (chid)) \ + for ((lunid) = 0; (lunid) < (dev)->luns_per_chnl; \ + (lunid)++, (ppa).g.lun = (lunid)) + #else /* CONFIG_NVM */ struct nvm_dev_ops; -- cgit v1.2.3 From e11903f5dfeb4f59fe93316d47f2ee5982e91e60 Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Fri, 6 May 2016 20:03:05 +0200 Subject: lightnvm: refactor device ops->get_bb_tbl() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The device ops->get_bb_tbl() takes a callback, that allows the caller to use its own callback function to update its data structures in the returning function. This makes it difficult to send parameters to the callback, and usually is circumvented by small private structures, that both carry the callers state and any flags needed to fulfill the update. Refactor ops->get_bb_tbl() to fill a data buffer with the status of the blocks returned, and let the user call the callback function manually. That will provide the necessary flags and data structures and simplify the logic around ops->get_bb_tbl(). Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 8 +++ drivers/lightnvm/gennvm.c | 29 ++++++--- drivers/lightnvm/sysblk.c | 146 +++++++++++++++++++++++-------------------- drivers/nvme/host/lightnvm.c | 6 +- include/linux/lightnvm.h | 6 +- 5 files changed, 111 insertions(+), 84 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 0296223392f7..e6d7a98baeb2 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -467,6 +467,14 @@ int nvm_bb_tbl_fold(struct nvm_dev *dev, u8 *blks, int nr_blks) } EXPORT_SYMBOL(nvm_bb_tbl_fold); +int nvm_get_bb_tbl(struct nvm_dev *dev, struct ppa_addr ppa, u8 *blks) +{ + ppa = generic_to_dev_addr(dev, ppa); + + return dev->ops->get_bb_tbl(dev, ppa, blks); +} +EXPORT_SYMBOL(nvm_get_bb_tbl); + static int nvm_init_slc_tbl(struct nvm_dev *dev, struct nvm_id_group *grp) { int i; diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c index 6096077c5dde..9c6b141606e9 100644 --- a/drivers/lightnvm/gennvm.c +++ b/drivers/lightnvm/gennvm.c @@ -129,10 +129,10 @@ static int gennvm_luns_init(struct nvm_dev *dev, struct gen_nvm *gn) return 0; } -static int gennvm_block_bb(struct nvm_dev *dev, struct ppa_addr ppa, - u8 *blks, int nr_blks, void *private) +static int gennvm_block_bb(struct gen_nvm *gn, struct ppa_addr ppa, + u8 *blks, int nr_blks) { - struct gen_nvm *gn = private; + struct nvm_dev *dev = gn->dev; struct gen_lun *lun; struct nvm_block *blk; int i; @@ -219,13 +219,21 @@ static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn) struct gen_lun *lun; struct nvm_block *block; sector_t lun_iter, blk_iter, cur_block_id = 0; - int ret; + int ret, nr_blks; + u8 *blks; + + nr_blks = dev->blks_per_lun * dev->plane_mode; + blks = kmalloc(nr_blks, GFP_KERNEL); + if (!blks) + return -ENOMEM; gennvm_for_each_lun(gn, lun, lun_iter) { lun->vlun.blocks = vzalloc(sizeof(struct nvm_block) * dev->blks_per_lun); - if (!lun->vlun.blocks) + if (!lun->vlun.blocks) { + kfree(blks); return -ENOMEM; + } for (blk_iter = 0; blk_iter < dev->blks_per_lun; blk_iter++) { block = &lun->vlun.blocks[blk_iter]; @@ -250,12 +258,14 @@ static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn) ppa.ppa = 0; ppa.g.ch = lun->vlun.chnl_id; ppa.g.lun = lun->vlun.id; - ppa = generic_to_dev_addr(dev, ppa); - ret = dev->ops->get_bb_tbl(dev, ppa, - gennvm_block_bb, gn); + ret = nvm_get_bb_tbl(dev, ppa, blks); + if (ret) + pr_err("gennvm: could not get BB table\n"); + + ret = gennvm_block_bb(gn, ppa, blks, nr_blks); if (ret) - pr_err("gennvm: could not read BB table\n"); + pr_err("gennvm: BB table map failed\n"); } } @@ -268,6 +278,7 @@ static int gennvm_blocks_init(struct nvm_dev *dev, struct gen_nvm *gn) } } + kfree(blks); return 0; } diff --git a/drivers/lightnvm/sysblk.c b/drivers/lightnvm/sysblk.c index a48093d17fea..dc99c0ac8701 100644 --- a/drivers/lightnvm/sysblk.c +++ b/drivers/lightnvm/sysblk.c @@ -93,10 +93,45 @@ void nvm_setup_sysblk_scan(struct nvm_dev *dev, struct sysblk_scan *s, s->nr_rows = nvm_setup_sysblks(dev, sysblk_ppas); } +static int sysblk_get_free_blks(struct nvm_dev *dev, struct ppa_addr ppa, + u8 *blks, int nr_blks, + struct sysblk_scan *s) +{ + struct ppa_addr *sppa; + int i, blkid = 0; + + nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); + if (nr_blks < 0) + return nr_blks; + + for (i = 0; i < nr_blks; i++) { + if (blks[i] == NVM_BLK_T_HOST) + return -EEXIST; + + if (blks[i] != NVM_BLK_T_FREE) + continue; + + sppa = &s->ppas[scan_ppa_idx(s->row, blkid)]; + sppa->g.ch = ppa.g.ch; + sppa->g.lun = ppa.g.lun; + sppa->g.blk = i; + s->nr_ppas++; + blkid++; + + pr_debug("nvm: use (%u %u %u) as sysblk\n", + sppa->g.ch, sppa->g.lun, sppa->g.blk); + if (blkid > MAX_BLKS_PR_SYSBLK - 1) + return 0; + } + + pr_err("nvm: sysblk failed get sysblk\n"); + return -EINVAL; +} + static int sysblk_get_host_blks(struct nvm_dev *dev, struct ppa_addr ppa, - u8 *blks, int nr_blks, void *private) + u8 *blks, int nr_blks, + struct sysblk_scan *s) { - struct sysblk_scan *s = private; int i, nr_sysblk = 0; nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); @@ -123,26 +158,42 @@ static int sysblk_get_host_blks(struct nvm_dev *dev, struct ppa_addr ppa, } static int nvm_get_all_sysblks(struct nvm_dev *dev, struct sysblk_scan *s, - struct ppa_addr *ppas, nvm_bb_update_fn *fn) + struct ppa_addr *ppas, int get_free) { - struct ppa_addr dppa; - int i, ret = 0; + int i, nr_blks, ret = 0; + u8 *blks; s->nr_ppas = 0; + nr_blks = dev->blks_per_lun * dev->plane_mode; + + blks = kmalloc(nr_blks, GFP_KERNEL); + if (!blks) + return -ENOMEM; for (i = 0; i < s->nr_rows; i++) { - dppa = generic_to_dev_addr(dev, ppas[i]); s->row = i; - ret = dev->ops->get_bb_tbl(dev, dppa, fn, s); + ret = nvm_get_bb_tbl(dev, ppas[i], blks); if (ret) { pr_err("nvm: failed bb tbl for ppa (%u %u)\n", ppas[i].g.ch, ppas[i].g.blk); - return ret; + goto err_get; } + + if (get_free) + ret = sysblk_get_free_blks(dev, ppas[i], blks, nr_blks, + s); + else + ret = sysblk_get_host_blks(dev, ppas[i], blks, nr_blks, + s); + + if (ret) + goto err_get; } +err_get: + kfree(blks); return ret; } @@ -239,41 +290,6 @@ static int nvm_set_bb_tbl(struct nvm_dev *dev, struct sysblk_scan *s, int type) return 0; } -static int sysblk_get_free_blks(struct nvm_dev *dev, struct ppa_addr ppa, - u8 *blks, int nr_blks, void *private) -{ - struct sysblk_scan *s = private; - struct ppa_addr *sppa; - int i, blkid = 0; - - nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); - if (nr_blks < 0) - return nr_blks; - - for (i = 0; i < nr_blks; i++) { - if (blks[i] == NVM_BLK_T_HOST) - return -EEXIST; - - if (blks[i] != NVM_BLK_T_FREE) - continue; - - sppa = &s->ppas[scan_ppa_idx(s->row, blkid)]; - sppa->g.ch = ppa.g.ch; - sppa->g.lun = ppa.g.lun; - sppa->g.blk = i; - s->nr_ppas++; - blkid++; - - pr_debug("nvm: use (%u %u %u) as sysblk\n", - sppa->g.ch, sppa->g.lun, sppa->g.blk); - if (blkid > MAX_BLKS_PR_SYSBLK - 1) - return 0; - } - - pr_err("nvm: sysblk failed get sysblk\n"); - return -EINVAL; -} - static int nvm_write_and_verify(struct nvm_dev *dev, struct nvm_sb_info *info, struct sysblk_scan *s) { @@ -393,7 +409,7 @@ int nvm_get_sysblock(struct nvm_dev *dev, struct nvm_sb_info *info) nvm_setup_sysblk_scan(dev, &s, sysblk_ppas); mutex_lock(&dev->mlock); - ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, sysblk_get_host_blks); + ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, 0); if (ret) goto err_sysblk; @@ -453,7 +469,7 @@ int nvm_update_sysblock(struct nvm_dev *dev, struct nvm_sb_info *new) nvm_setup_sysblk_scan(dev, &s, sysblk_ppas); mutex_lock(&dev->mlock); - ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, sysblk_get_host_blks); + ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, 0); if (ret) goto err_sysblk; @@ -551,7 +567,7 @@ int nvm_init_sysblock(struct nvm_dev *dev, struct nvm_sb_info *info) nvm_setup_sysblk_scan(dev, &s, sysblk_ppas); mutex_lock(&dev->mlock); - ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, sysblk_get_free_blks); + ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, 1); if (ret) goto err_mark; @@ -587,9 +603,9 @@ static unsigned int factory_blk_offset(struct nvm_dev *dev, int ch, int lun) } static int nvm_factory_blks(struct nvm_dev *dev, struct ppa_addr ppa, - u8 *blks, int nr_blks, void *private) + u8 *blks, int nr_blks, + struct factory_blks *f) { - struct factory_blks *f = private; int i, lunoff; nr_blks = nvm_bb_tbl_fold(dev, blks, nr_blks); @@ -659,32 +675,29 @@ static int nvm_fact_get_blks(struct nvm_dev *dev, struct ppa_addr *erase_list, return ppa_cnt; } -static int nvm_fact_get_bb_tbl(struct nvm_dev *dev, struct ppa_addr ppa, - nvm_bb_update_fn *fn, void *priv) -{ - struct ppa_addr dev_ppa; - int ret; - - dev_ppa = generic_to_dev_addr(dev, ppa); - - ret = dev->ops->get_bb_tbl(dev, dev_ppa, fn, priv); - if (ret) - pr_err("nvm: failed bb tbl for ch%u lun%u\n", - ppa.g.ch, ppa.g.blk); - return ret; -} - static int nvm_fact_select_blks(struct nvm_dev *dev, struct factory_blks *f) { - int ch, lun, ret; struct ppa_addr ppa; + int ch, lun, nr_blks, ret; + u8 *blks; + + nr_blks = dev->blks_per_lun * dev->plane_mode; + blks = kmalloc(nr_blks, GFP_KERNEL); + if (!blks) + return -ENOMEM; nvm_for_each_lun_ppa(dev, ppa, ch, lun) { - ret = nvm_fact_get_bb_tbl(dev, ppa, nvm_factory_blks, f); + ret = nvm_get_bb_tbl(dev, ppa, blks); + if (ret) + pr_err("nvm: failed bb tbl for ch%u lun%u\n", + ppa.g.ch, ppa.g.blk); + + ret = nvm_factory_blks(dev, ppa, blks, nr_blks, f); if (ret) return ret; } + kfree(blks); return 0; } @@ -722,8 +735,7 @@ int nvm_dev_factory(struct nvm_dev *dev, int flags) if (flags & NVM_FACTORY_RESET_HOST_BLKS) { nvm_setup_sysblk_scan(dev, &s, sysblk_ppas); mutex_lock(&dev->mlock); - ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, - sysblk_get_host_blks); + ret = nvm_get_all_sysblks(dev, &s, sysblk_ppas, 0); if (!ret) ret = nvm_set_bb_tbl(dev, &s, NVM_BLK_T_FREE); mutex_unlock(&dev->mlock); diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index d289980d2bc8..45e3511d5d3d 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c @@ -388,7 +388,7 @@ out: } static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa, - nvm_bb_update_fn *update_bbtbl, void *priv) + u8 *blks) { struct request_queue *q = nvmdev->q; struct nvme_ns *ns = q->queuedata; @@ -435,9 +435,7 @@ static int nvme_nvm_get_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr ppa, goto out; } - ppa = dev_to_generic_addr(nvmdev, ppa); - ret = update_bbtbl(nvmdev, ppa, bb_tbl->blk, nr_blks, priv); - + memcpy(blks, bb_tbl->blk, nvmdev->blks_per_lun * nvmdev->plane_mode); out: kfree(bb_tbl); return ret; diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 3f256355b9fa..16d4f2edf5b4 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -41,13 +41,10 @@ struct nvm_id; struct nvm_dev; typedef int (nvm_l2p_update_fn)(u64, u32, __le64 *, void *); -typedef int (nvm_bb_update_fn)(struct nvm_dev *, struct ppa_addr, u8 *, int, - void *); typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *); typedef int (nvm_get_l2p_tbl_fn)(struct nvm_dev *, u64, u32, nvm_l2p_update_fn *, void *); -typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, - nvm_bb_update_fn *, void *); +typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *); typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct nvm_rq *, int); typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); typedef int (nvm_erase_blk_fn)(struct nvm_dev *, struct nvm_rq *); @@ -539,6 +536,7 @@ extern int nvm_submit_ppa(struct nvm_dev *, struct ppa_addr *, int, int, int, extern int nvm_submit_ppa_list(struct nvm_dev *, struct ppa_addr *, int, int, int, void *, int); extern int nvm_bb_tbl_fold(struct nvm_dev *, u8 *, int); +extern int nvm_get_bb_tbl(struct nvm_dev *, struct ppa_addr, u8 *); /* sysblk.c */ #define NVM_SYSBLK_MAGIC 0x4E564D53 /* "NVMS" */ -- cgit v1.2.3 From 5ebc7d9fe13ff9bd3622d0be3cd39c8751459be6 Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Fri, 6 May 2016 20:03:07 +0200 Subject: lightnvm: make nvm_set_rqd_ppalist() aware of vblks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A virtual block enables a block to identify multiple physical blocks. This is useful for metadata where a device media supports multiple planes. In that case, a block, with multiple planes can be managed as a single vblk. Reducing the metadata required by one forth. nvm_set_rqd_ppalist() takes care of expanding a ppa_list with vblks automatically. However, for some use-cases, where only a single physical block is required, the ppa_list should not be expanded. Therefore, add a vblk parameter to nvm_set_rqd_ppalist(), and only expand the ppa_list if vblk is set. Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 31 +++++++++++++++++-------------- drivers/lightnvm/sysblk.c | 2 +- include/linux/lightnvm.h | 2 +- 3 files changed, 19 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index e6d7a98baeb2..de5db7b2c456 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -251,33 +251,36 @@ void nvm_generic_to_addr_mode(struct nvm_dev *dev, struct nvm_rq *rqd) EXPORT_SYMBOL(nvm_generic_to_addr_mode); int nvm_set_rqd_ppalist(struct nvm_dev *dev, struct nvm_rq *rqd, - struct ppa_addr *ppas, int nr_ppas) + struct ppa_addr *ppas, int nr_ppas, int vblk) { int i, plane_cnt, pl_idx; - if (dev->plane_mode == NVM_PLANE_SINGLE && nr_ppas == 1) { - rqd->nr_pages = 1; + if ((!vblk || dev->plane_mode == NVM_PLANE_SINGLE) && nr_ppas == 1) { + rqd->nr_pages = nr_ppas; rqd->ppa_addr = ppas[0]; return 0; } - plane_cnt = dev->plane_mode; - rqd->nr_pages = plane_cnt * nr_ppas; - - if (dev->ops->max_phys_sect < rqd->nr_pages) - return -EINVAL; - + rqd->nr_pages = nr_ppas; rqd->ppa_list = nvm_dev_dma_alloc(dev, GFP_KERNEL, &rqd->dma_ppa_list); if (!rqd->ppa_list) { pr_err("nvm: failed to allocate dma memory\n"); return -ENOMEM; } - for (pl_idx = 0; pl_idx < plane_cnt; pl_idx++) { + if (!vblk) { + for (i = 0; i < nr_ppas; i++) + rqd->ppa_list[i] = ppas[i]; + } else { + plane_cnt = dev->plane_mode; + rqd->nr_pages *= plane_cnt; + for (i = 0; i < nr_ppas; i++) { - ppas[i].g.pl = pl_idx; - rqd->ppa_list[(pl_idx * nr_ppas) + i] = ppas[i]; + for (pl_idx = 0; pl_idx < plane_cnt; pl_idx++) { + ppas[i].g.pl = pl_idx; + rqd->ppa_list[(pl_idx * nr_ppas) + i] = ppas[i]; + } } } @@ -304,7 +307,7 @@ int nvm_erase_ppa(struct nvm_dev *dev, struct ppa_addr *ppas, int nr_ppas) memset(&rqd, 0, sizeof(struct nvm_rq)); - ret = nvm_set_rqd_ppalist(dev, &rqd, ppas, nr_ppas); + ret = nvm_set_rqd_ppalist(dev, &rqd, ppas, nr_ppas, 1); if (ret) return ret; @@ -420,7 +423,7 @@ int nvm_submit_ppa(struct nvm_dev *dev, struct ppa_addr *ppa, int nr_ppas, int ret; memset(&rqd, 0, sizeof(struct nvm_rq)); - ret = nvm_set_rqd_ppalist(dev, &rqd, ppa, nr_ppas); + ret = nvm_set_rqd_ppalist(dev, &rqd, ppa, nr_ppas, 1); if (ret) return ret; diff --git a/drivers/lightnvm/sysblk.c b/drivers/lightnvm/sysblk.c index bca690248bd7..737fbc3c5cf1 100644 --- a/drivers/lightnvm/sysblk.c +++ b/drivers/lightnvm/sysblk.c @@ -277,7 +277,7 @@ static int nvm_set_bb_tbl(struct nvm_dev *dev, struct sysblk_scan *s, int type) memset(&rqd, 0, sizeof(struct nvm_rq)); - nvm_set_rqd_ppalist(dev, &rqd, s->ppas, s->nr_ppas); + nvm_set_rqd_ppalist(dev, &rqd, s->ppas, s->nr_ppas, 1); nvm_generic_to_addr_mode(dev, &rqd); ret = dev->ops->set_bb_tbl(dev, &rqd, type); diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 16d4f2edf5b4..9ae0b7c6deb2 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -526,7 +526,7 @@ extern int nvm_submit_io(struct nvm_dev *, struct nvm_rq *); extern void nvm_generic_to_addr_mode(struct nvm_dev *, struct nvm_rq *); extern void nvm_addr_to_generic_mode(struct nvm_dev *, struct nvm_rq *); extern int nvm_set_rqd_ppalist(struct nvm_dev *, struct nvm_rq *, - struct ppa_addr *, int); + struct ppa_addr *, int, int); extern void nvm_free_rqd_ppalist(struct nvm_dev *, struct nvm_rq *); extern int nvm_erase_ppa(struct nvm_dev *, struct ppa_addr *, int); extern int nvm_erase_blk(struct nvm_dev *, struct nvm_block *); -- cgit v1.2.3 From 00ee6cc3b74bdb4dfb71838046517beb6839647c Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Fri, 6 May 2016 20:03:09 +0200 Subject: lightnvm: refactor set_bb_tbl for accepting ppa list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The set_bb_tbl takes struct nvm_rq and only uses its ppa_list and nr_pages internally. Instead, make these two variables explicit. This allows a user to call it without initializing a struct nvm_rq first. Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/sysblk.c | 2 +- drivers/nvme/host/lightnvm.c | 8 ++++---- include/linux/lightnvm.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/sysblk.c b/drivers/lightnvm/sysblk.c index 737fbc3c5cf1..b98ca1998da5 100644 --- a/drivers/lightnvm/sysblk.c +++ b/drivers/lightnvm/sysblk.c @@ -280,7 +280,7 @@ static int nvm_set_bb_tbl(struct nvm_dev *dev, struct sysblk_scan *s, int type) nvm_set_rqd_ppalist(dev, &rqd, s->ppas, s->nr_ppas, 1); nvm_generic_to_addr_mode(dev, &rqd); - ret = dev->ops->set_bb_tbl(dev, &rqd, type); + ret = dev->ops->set_bb_tbl(dev, &rqd.ppa_addr, rqd.nr_pages, type); nvm_free_rqd_ppalist(dev, &rqd); if (ret) { pr_err("nvm: sysblk failed bb mark\n"); diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index 45e3511d5d3d..d426d95c9eaa 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c @@ -441,8 +441,8 @@ out: return ret; } -static int nvme_nvm_set_bb_tbl(struct nvm_dev *nvmdev, struct nvm_rq *rqd, - int type) +static int nvme_nvm_set_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr *ppas, + int nr_ppas, int type) { struct nvme_ns *ns = nvmdev->q->queuedata; struct nvme_nvm_command c = {}; @@ -450,8 +450,8 @@ static int nvme_nvm_set_bb_tbl(struct nvm_dev *nvmdev, struct nvm_rq *rqd, c.set_bb.opcode = nvme_nvm_admin_set_bb_tbl; c.set_bb.nsid = cpu_to_le32(ns->ns_id); - c.set_bb.spba = cpu_to_le64(rqd->ppa_addr.ppa); - c.set_bb.nlb = cpu_to_le16(rqd->nr_pages - 1); + c.set_bb.spba = cpu_to_le64(ppas->ppa); + c.set_bb.nlb = cpu_to_le16(nr_ppas - 1); c.set_bb.value = type; ret = nvme_submit_sync_cmd(ns->ctrl->admin_q, (struct nvme_command *)&c, diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 9ae0b7c6deb2..af72ca75dced 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -45,7 +45,7 @@ typedef int (nvm_id_fn)(struct nvm_dev *, struct nvm_id *); typedef int (nvm_get_l2p_tbl_fn)(struct nvm_dev *, u64, u32, nvm_l2p_update_fn *, void *); typedef int (nvm_op_bb_tbl_fn)(struct nvm_dev *, struct ppa_addr, u8 *); -typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct nvm_rq *, int); +typedef int (nvm_op_set_bb_fn)(struct nvm_dev *, struct ppa_addr *, int, int); typedef int (nvm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); typedef int (nvm_erase_blk_fn)(struct nvm_dev *, struct nvm_rq *); typedef void *(nvm_create_dma_pool_fn)(struct nvm_dev *, char *); -- cgit v1.2.3 From 003fad376b924fc3a61c659f38da70356ec144fa Mon Sep 17 00:00:00 2001 From: Javier González Date: Fri, 6 May 2016 20:03:12 +0200 Subject: lightnvm: enable metadata to be sent to device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable metadata buffer to be sent to the device through the metadata field on the physical rw nvme command. The size of the metadata buffer must follow dev->oob_size * # of PPAs. Signed-off-by: Javier González Updated description. Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/nvme/host/lightnvm.c | 1 + include/linux/lightnvm.h | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index d426d95c9eaa..69a47fb2b6e3 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c @@ -467,6 +467,7 @@ static inline void nvme_nvm_rqtocmd(struct request *rq, struct nvm_rq *rqd, c->ph_rw.opcode = rqd->opcode; c->ph_rw.nsid = cpu_to_le32(ns->ns_id); c->ph_rw.spba = cpu_to_le64(rqd->ppa_addr.ppa); + c->ph_rw.metadata = cpu_to_le64(rqd->meta_list); c->ph_rw.control = cpu_to_le16(rqd->flags); c->ph_rw.length = cpu_to_le16(rqd->nr_pages - 1); diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index af72ca75dced..678df4d4354d 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -230,8 +230,8 @@ struct nvm_rq { struct ppa_addr *ppa_list; - void *metadata; - dma_addr_t dma_metadata; + void *meta_list; + dma_addr_t dma_meta_list; struct completion *wait; nvm_end_io_fn *end_io; -- cgit v1.2.3 From 75b8564932ef646e8620deffacbe134846333948 Mon Sep 17 00:00:00 2001 From: Javier González Date: Fri, 6 May 2016 20:03:13 +0200 Subject: lightnvm: rename dma helper functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Until now, the dma pool have been exclusively used to allocate the ppa list being sent to the device. In pblk (upcoming), we use these pools to allocate metadata too. Thus, we generalize the names of some variables on the dma helper functions to make the code more readable. Signed-off-by: Javier González Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 16 ++++++++-------- drivers/nvme/host/lightnvm.c | 4 ++-- include/linux/lightnvm.h | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index de5db7b2c456..1873a3bc913d 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -87,15 +87,15 @@ EXPORT_SYMBOL(nvm_unregister_tgt_type); void *nvm_dev_dma_alloc(struct nvm_dev *dev, gfp_t mem_flags, dma_addr_t *dma_handler) { - return dev->ops->dev_dma_alloc(dev, dev->ppalist_pool, mem_flags, + return dev->ops->dev_dma_alloc(dev, dev->dma_pool, mem_flags, dma_handler); } EXPORT_SYMBOL(nvm_dev_dma_alloc); -void nvm_dev_dma_free(struct nvm_dev *dev, void *ppa_list, +void nvm_dev_dma_free(struct nvm_dev *dev, void *addr, dma_addr_t dma_handler) { - dev->ops->dev_dma_free(dev->ppalist_pool, ppa_list, dma_handler); + dev->ops->dev_dma_free(dev->dma_pool, addr, dma_handler); } EXPORT_SYMBOL(nvm_dev_dma_free); @@ -652,8 +652,8 @@ err: static void nvm_exit(struct nvm_dev *dev) { - if (dev->ppalist_pool) - dev->ops->destroy_dma_pool(dev->ppalist_pool); + if (dev->dma_pool) + dev->ops->destroy_dma_pool(dev->dma_pool); nvm_free(dev); pr_info("nvm: successfully unloaded\n"); @@ -687,9 +687,9 @@ int nvm_register(struct request_queue *q, char *disk_name, } if (dev->ops->max_phys_sect > 1) { - dev->ppalist_pool = dev->ops->create_dma_pool(dev, "ppalist"); - if (!dev->ppalist_pool) { - pr_err("nvm: could not create ppa pool\n"); + dev->dma_pool = dev->ops->create_dma_pool(dev, "ppalist"); + if (!dev->dma_pool) { + pr_err("nvm: could not create dma pool\n"); ret = -ENOMEM; goto err_init; } diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index 69a47fb2b6e3..8461f5a36d14 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c @@ -565,10 +565,10 @@ static void *nvme_nvm_dev_dma_alloc(struct nvm_dev *dev, void *pool, return dma_pool_alloc(pool, mem_flags, dma_handler); } -static void nvme_nvm_dev_dma_free(void *pool, void *ppa_list, +static void nvme_nvm_dev_dma_free(void *pool, void *addr, dma_addr_t dma_handler) { - dma_pool_free(pool, ppa_list, dma_handler); + dma_pool_free(pool, addr, dma_handler); } static struct nvm_dev_ops nvme_nvm_dev_ops = { diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 678df4d4354d..0e8e01956325 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -347,7 +347,7 @@ struct nvm_dev { unsigned max_pages_per_blk; unsigned long *lun_map; - void *ppalist_pool; + void *dma_pool; struct nvm_id identity; -- cgit v1.2.3 From 976bdfcae32ea10c2c8c2ecaeb0d85873f634dad Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Fri, 6 May 2016 20:03:17 +0200 Subject: lightnvm: remove mgt targets on mgt removal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Targets associated with a device manager are not freed on device removal. They have to be manually removed before shutdown. Make sure any outstanding targets are freed upon shutdown. Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 69 ++++++++++++++++++++++++++++++------------------ include/linux/lightnvm.h | 1 + 2 files changed, 44 insertions(+), 26 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index 1873a3bc913d..d3af77102e47 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -596,13 +596,52 @@ err_fmtype: return ret; } +static void nvm_remove_target(struct nvm_target *t) +{ + struct nvm_tgt_type *tt = t->type; + struct gendisk *tdisk = t->disk; + struct request_queue *q = tdisk->queue; + + lockdep_assert_held(&nvm_lock); + + del_gendisk(tdisk); + blk_cleanup_queue(q); + + if (tt->exit) + tt->exit(tdisk->private_data); + + put_disk(tdisk); + + list_del(&t->list); + kfree(t); +} + +static void nvm_free_mgr(struct nvm_dev *dev) +{ + struct nvm_target *tgt, *tmp; + + if (!dev->mt) + return; + + down_write(&nvm_lock); + list_for_each_entry_safe(tgt, tmp, &nvm_targets, list) { + if (tgt->dev != dev) + continue; + + nvm_remove_target(tgt); + } + up_write(&nvm_lock); + + dev->mt->unregister_mgr(dev); + dev->mt = NULL; +} + static void nvm_free(struct nvm_dev *dev) { if (!dev) return; - if (dev->mt) - dev->mt->unregister_mgr(dev); + nvm_free_mgr(dev); kfree(dev->lptbl); kfree(dev->lun_map); @@ -808,6 +847,7 @@ static int nvm_create_target(struct nvm_dev *dev, t->type = tt; t->disk = tdisk; + t->dev = dev; down_write(&nvm_lock); list_add_tail(&t->list, &nvm_targets); @@ -823,26 +863,6 @@ err_t: return -ENOMEM; } -static void nvm_remove_target(struct nvm_target *t) -{ - struct nvm_tgt_type *tt = t->type; - struct gendisk *tdisk = t->disk; - struct request_queue *q = tdisk->queue; - - lockdep_assert_held(&nvm_lock); - - del_gendisk(tdisk); - blk_cleanup_queue(q); - - if (tt->exit) - tt->exit(tdisk->private_data); - - put_disk(tdisk); - - list_del(&t->list); - kfree(t); -} - static int __nvm_configure_create(struct nvm_ioctl_create *create) { struct nvm_dev *dev; @@ -1231,10 +1251,7 @@ static long nvm_ioctl_dev_factory(struct file *file, void __user *arg) return -EINVAL; } - if (dev->mt) { - dev->mt->unregister_mgr(dev); - dev->mt = NULL; - } + nvm_free_mgr(dev); if (dev->identity.cap & NVM_ID_DCAP_BBLKMGMT) return nvm_dev_factory(dev, fact.flags); diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 0e8e01956325..cde31ffe2d62 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -200,6 +200,7 @@ struct nvm_id { struct nvm_target { struct list_head list; + struct nvm_dev *dev; struct nvm_tgt_type *type; struct gendisk *disk; }; -- cgit v1.2.3 From 04a8aa173bd9410849526a80dcf733da9c3e142d Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Fri, 6 May 2016 20:03:18 +0200 Subject: lightnvm: expose gennvm_mark_blk to targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Targets can update a block state when having a reference to an in-memory virtual block. In the case that a target does not keep the block metadata in memory, it does not have a way to update this structure. Therefore, expose gennvm_mark_blk() through the media managers ->mark_blk() callback and let targets update the state structure through this callback. Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/gennvm.c | 27 ++++++++++++++------------- include/linux/lightnvm.h | 4 ++++ 2 files changed, 18 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c index 61790aebb8da..33a66d8c039d 100644 --- a/drivers/lightnvm/gennvm.c +++ b/drivers/lightnvm/gennvm.c @@ -407,29 +407,28 @@ static void gennvm_put_blk(struct nvm_dev *dev, struct nvm_block *blk) spin_unlock(&vlun->lock); } -static void gennvm_blk_set_type(struct nvm_dev *dev, struct ppa_addr *ppa, - int type) +static void gennvm_mark_blk(struct nvm_dev *dev, struct ppa_addr ppa, int type) { struct gen_nvm *gn = dev->mp; struct gen_lun *lun; struct nvm_block *blk; pr_debug("gennvm: ppa (ch: %u lun: %u blk: %u pg: %u) -> %u\n", - ppa->g.ch, ppa->g.lun, ppa->g.blk, ppa->g.pg, type); + ppa.g.ch, ppa.g.lun, ppa.g.blk, ppa.g.pg, type); - if (unlikely(ppa->g.ch > dev->nr_chnls || - ppa->g.lun > dev->luns_per_chnl || - ppa->g.blk > dev->blks_per_lun)) { + if (unlikely(ppa.g.ch > dev->nr_chnls || + ppa.g.lun > dev->luns_per_chnl || + ppa.g.blk > dev->blks_per_lun)) { WARN_ON_ONCE(1); pr_err("gennvm: ppa broken (ch: %u > %u lun: %u > %u blk: %u > %u", - ppa->g.ch, dev->nr_chnls, - ppa->g.lun, dev->luns_per_chnl, - ppa->g.blk, dev->blks_per_lun); + ppa.g.ch, dev->nr_chnls, + ppa.g.lun, dev->luns_per_chnl, + ppa.g.blk, dev->blks_per_lun); return; } - lun = &gn->luns[ppa->g.lun * ppa->g.ch]; - blk = &lun->vlun.blocks[ppa->g.blk]; + lun = &gn->luns[ppa.g.lun * ppa.g.ch]; + blk = &lun->vlun.blocks[ppa.g.blk]; /* will be moved to bb list on put_blk from target */ blk->state = type; @@ -448,12 +447,12 @@ static void gennvm_mark_blk_bad(struct nvm_dev *dev, struct nvm_rq *rqd) /* look up blocks and mark them as bad */ if (rqd->nr_pages == 1) { - gennvm_blk_set_type(dev, &rqd->ppa_addr, NVM_BLK_ST_BAD); + gennvm_mark_blk(dev, rqd->ppa_addr, NVM_BLK_ST_BAD); return; } while ((bit = find_next_bit(comp_bits, max_secs, bit + 1)) < max_secs) - gennvm_blk_set_type(dev, &rqd->ppa_list[bit], NVM_BLK_ST_BAD); + gennvm_mark_blk(dev, rqd->ppa_list[bit], NVM_BLK_ST_BAD); } static void gennvm_end_io(struct nvm_rq *rqd) @@ -544,6 +543,8 @@ static struct nvmm_type gennvm = { .submit_io = gennvm_submit_io, .erase_blk = gennvm_erase_blk, + .mark_blk = gennvm_mark_blk, + .get_lun = gennvm_get_lun, .reserve_lun = gennvm_reserve_lun, .release_lun = gennvm_release_lun, diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index cde31ffe2d62..3c53911e5758 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -467,6 +467,7 @@ typedef void (nvmm_flush_blk_fn)(struct nvm_dev *, struct nvm_block *); typedef int (nvmm_submit_io_fn)(struct nvm_dev *, struct nvm_rq *); typedef int (nvmm_erase_blk_fn)(struct nvm_dev *, struct nvm_block *, unsigned long); +typedef void (nvmm_mark_blk_fn)(struct nvm_dev *, struct ppa_addr, int); typedef struct nvm_lun *(nvmm_get_lun_fn)(struct nvm_dev *, int); typedef int (nvmm_reserve_lun)(struct nvm_dev *, int); typedef void (nvmm_release_lun)(struct nvm_dev *, int); @@ -494,6 +495,9 @@ struct nvmm_type { nvmm_submit_io_fn *submit_io; nvmm_erase_blk_fn *erase_blk; + /* Bad block mgmt */ + nvmm_mark_blk_fn *mark_blk; + /* Configuration management */ nvmm_get_lun_fn *get_lun; nvmm_reserve_lun *reserve_lun; -- cgit v1.2.3 From df414b33bb1eb3a0ae52ccd4ecfec9323a4f89dc Mon Sep 17 00:00:00 2001 From: Matias Bjørling Date: Fri, 6 May 2016 20:03:19 +0200 Subject: lightnvm: add is_cached entry to struct ppa_addr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A target requires a method to identify PPAs that are either cached in memory or on disk. This can efficiently be maintained within the PPA. The target host-side translation table can then lookup a PPA and know from the PPA if it is cached or on disk. In the case it is cached, it is the responsibility of the target to maintain this cache. Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- include/linux/lightnvm.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 3c53911e5758..3a810d7bd25e 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -18,7 +18,7 @@ enum { #define NVM_SEC_BITS (8) #define NVM_PL_BITS (8) #define NVM_LUN_BITS (8) -#define NVM_CH_BITS (8) +#define NVM_CH_BITS (7) struct ppa_addr { /* Generic structure for all addresses */ @@ -30,8 +30,14 @@ struct ppa_addr { u64 pl : NVM_PL_BITS; u64 lun : NVM_LUN_BITS; u64 ch : NVM_CH_BITS; + u64 reserved : 1; } g; + struct { + u64 line : 63; + u64 is_cached : 1; + } c; + u64 ppa; }; }; -- cgit v1.2.3 From 6d5be9590b5e15124e3c8b319c8d7ce01abcf07d Mon Sep 17 00:00:00 2001 From: Javier González Date: Fri, 6 May 2016 20:03:20 +0200 Subject: lightnvm: rename nr_pages to nr_ppas on nvm_rq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The number of ppas contained on a request is not necessarily the number of pages that it maps to neither on the target nor on the device side. In order to avoid confusion, rename nr_pages to nr_ppas since it is what the variable actually contains. Signed-off-by: Javier González Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/core.c | 16 ++++++++-------- drivers/lightnvm/gennvm.c | 2 +- drivers/lightnvm/rrpc.c | 6 +++--- drivers/lightnvm/rrpc.h | 2 +- drivers/lightnvm/sysblk.c | 2 +- drivers/nvme/host/lightnvm.c | 4 ++-- include/linux/lightnvm.h | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index d3af77102e47..160c1a6838e1 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -226,8 +226,8 @@ void nvm_addr_to_generic_mode(struct nvm_dev *dev, struct nvm_rq *rqd) { int i; - if (rqd->nr_pages > 1) { - for (i = 0; i < rqd->nr_pages; i++) + if (rqd->nr_ppas > 1) { + for (i = 0; i < rqd->nr_ppas; i++) rqd->ppa_list[i] = dev_to_generic_addr(dev, rqd->ppa_list[i]); } else { @@ -240,8 +240,8 @@ void nvm_generic_to_addr_mode(struct nvm_dev *dev, struct nvm_rq *rqd) { int i; - if (rqd->nr_pages > 1) { - for (i = 0; i < rqd->nr_pages; i++) + if (rqd->nr_ppas > 1) { + for (i = 0; i < rqd->nr_ppas; i++) rqd->ppa_list[i] = generic_to_dev_addr(dev, rqd->ppa_list[i]); } else { @@ -256,13 +256,13 @@ int nvm_set_rqd_ppalist(struct nvm_dev *dev, struct nvm_rq *rqd, int i, plane_cnt, pl_idx; if ((!vblk || dev->plane_mode == NVM_PLANE_SINGLE) && nr_ppas == 1) { - rqd->nr_pages = nr_ppas; + rqd->nr_ppas = nr_ppas; rqd->ppa_addr = ppas[0]; return 0; } - rqd->nr_pages = nr_ppas; + rqd->nr_ppas = nr_ppas; rqd->ppa_list = nvm_dev_dma_alloc(dev, GFP_KERNEL, &rqd->dma_ppa_list); if (!rqd->ppa_list) { pr_err("nvm: failed to allocate dma memory\n"); @@ -274,7 +274,7 @@ int nvm_set_rqd_ppalist(struct nvm_dev *dev, struct nvm_rq *rqd, rqd->ppa_list[i] = ppas[i]; } else { plane_cnt = dev->plane_mode; - rqd->nr_pages *= plane_cnt; + rqd->nr_ppas *= plane_cnt; for (i = 0; i < nr_ppas; i++) { for (pl_idx = 0; pl_idx < plane_cnt; pl_idx++) { @@ -395,7 +395,7 @@ int nvm_submit_ppa_list(struct nvm_dev *dev, struct ppa_addr *ppa_list, memset(&rqd, 0, sizeof(struct nvm_rq)); - rqd.nr_pages = nr_ppas; + rqd.nr_ppas = nr_ppas; if (nr_ppas > 1) rqd.ppa_list = ppa_list; else diff --git a/drivers/lightnvm/gennvm.c b/drivers/lightnvm/gennvm.c index 33a66d8c039d..ec9fb6876e38 100644 --- a/drivers/lightnvm/gennvm.c +++ b/drivers/lightnvm/gennvm.c @@ -446,7 +446,7 @@ static void gennvm_mark_blk_bad(struct nvm_dev *dev, struct nvm_rq *rqd) nvm_addr_to_generic_mode(dev, rqd); /* look up blocks and mark them as bad */ - if (rqd->nr_pages == 1) { + if (rqd->nr_ppas == 1) { gennvm_mark_blk(dev, rqd->ppa_addr, NVM_BLK_ST_BAD); return; } diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c index 48862ead7c99..72aca96f467b 100644 --- a/drivers/lightnvm/rrpc.c +++ b/drivers/lightnvm/rrpc.c @@ -695,7 +695,7 @@ static void rrpc_end_io(struct nvm_rq *rqd) { struct rrpc *rrpc = container_of(rqd->ins, struct rrpc, instance); struct rrpc_rq *rrqd = nvm_rq_to_pdu(rqd); - uint8_t npages = rqd->nr_pages; + uint8_t npages = rqd->nr_ppas; sector_t laddr = rrpc_get_laddr(rqd->bio) - npages; if (bio_data_dir(rqd->bio) == WRITE) @@ -883,7 +883,7 @@ static int rrpc_submit_io(struct rrpc *rrpc, struct bio *bio, bio_get(bio); rqd->bio = bio; rqd->ins = &rrpc->instance; - rqd->nr_pages = nr_pages; + rqd->nr_ppas = nr_pages; rrq->flags = flags; err = nvm_submit_io(rrpc->dev, rqd); @@ -892,7 +892,7 @@ static int rrpc_submit_io(struct rrpc *rrpc, struct bio *bio, bio_put(bio); if (!(flags & NVM_IOTYPE_GC)) { rrpc_unlock_rq(rrpc, rqd); - if (rqd->nr_pages > 1) + if (rqd->nr_ppas > 1) nvm_dev_dma_free(rrpc->dev, rqd->ppa_list, rqd->dma_ppa_list); } diff --git a/drivers/lightnvm/rrpc.h b/drivers/lightnvm/rrpc.h index 2653484a3b40..87e84b5fc1cc 100644 --- a/drivers/lightnvm/rrpc.h +++ b/drivers/lightnvm/rrpc.h @@ -251,7 +251,7 @@ static inline void rrpc_unlock_laddr(struct rrpc *rrpc, static inline void rrpc_unlock_rq(struct rrpc *rrpc, struct nvm_rq *rqd) { struct rrpc_inflight_rq *r = rrpc_get_inflight_rq(rqd); - uint8_t pages = rqd->nr_pages; + uint8_t pages = rqd->nr_ppas; BUG_ON((r->l_start + pages) > rrpc->nr_sects); diff --git a/drivers/lightnvm/sysblk.c b/drivers/lightnvm/sysblk.c index b98ca1998da5..994697ac786e 100644 --- a/drivers/lightnvm/sysblk.c +++ b/drivers/lightnvm/sysblk.c @@ -280,7 +280,7 @@ static int nvm_set_bb_tbl(struct nvm_dev *dev, struct sysblk_scan *s, int type) nvm_set_rqd_ppalist(dev, &rqd, s->ppas, s->nr_ppas, 1); nvm_generic_to_addr_mode(dev, &rqd); - ret = dev->ops->set_bb_tbl(dev, &rqd.ppa_addr, rqd.nr_pages, type); + ret = dev->ops->set_bb_tbl(dev, &rqd.ppa_addr, rqd.nr_ppas, type); nvm_free_rqd_ppalist(dev, &rqd); if (ret) { pr_err("nvm: sysblk failed bb mark\n"); diff --git a/drivers/nvme/host/lightnvm.c b/drivers/nvme/host/lightnvm.c index 65de1e56e59a..a0af0558354c 100644 --- a/drivers/nvme/host/lightnvm.c +++ b/drivers/nvme/host/lightnvm.c @@ -471,7 +471,7 @@ static inline void nvme_nvm_rqtocmd(struct request *rq, struct nvm_rq *rqd, c->ph_rw.spba = cpu_to_le64(rqd->ppa_addr.ppa); c->ph_rw.metadata = cpu_to_le64(rqd->dma_meta_list); c->ph_rw.control = cpu_to_le16(rqd->flags); - c->ph_rw.length = cpu_to_le16(rqd->nr_pages - 1); + c->ph_rw.length = cpu_to_le16(rqd->nr_ppas - 1); if (rqd->opcode == NVM_OP_HBWRITE || rqd->opcode == NVM_OP_HBREAD) c->hb_rw.slba = cpu_to_le64(nvme_block_nr(ns, @@ -542,7 +542,7 @@ static int nvme_nvm_erase_block(struct nvm_dev *dev, struct nvm_rq *rqd) c.erase.opcode = NVM_OP_ERASE; c.erase.nsid = cpu_to_le32(ns->ns_id); c.erase.spba = cpu_to_le64(rqd->ppa_addr.ppa); - c.erase.length = cpu_to_le16(rqd->nr_pages - 1); + c.erase.length = cpu_to_le16(rqd->nr_ppas - 1); return nvme_submit_sync_cmd(q, (struct nvme_command *)&c, NULL, 0); } diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index 3a810d7bd25e..b2991c724640 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -244,7 +244,7 @@ struct nvm_rq { nvm_end_io_fn *end_io; uint8_t opcode; - uint16_t nr_pages; + uint16_t nr_ppas; uint16_t flags; u64 ppa_status; /* ppa media status */ -- cgit v1.2.3 From 116f7d4a21fe450efc652c4850eb27cda36c9db0 Mon Sep 17 00:00:00 2001 From: Javier González Date: Fri, 6 May 2016 20:03:21 +0200 Subject: lightnvm: reserved space calculation incorrect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nvm_dev->max_pages_per_blk variable was removed in favor of the new nvm->sec_per_blk variable. The ->max_pages_per_blk variable was still used in rrpc_capacity, reporting the reserved capacity to zero. Replace with ->sec_per_blk to calculate the reserved area again. Signed-off-by: Javier González Updated patch description. Was "lightnvm: eliminate redundant variable" Signed-off-by: Matias Bjørling Signed-off-by: Jens Axboe --- drivers/lightnvm/rrpc.c | 2 +- include/linux/lightnvm.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'include') diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c index 72aca96f467b..2103e97a974f 100644 --- a/drivers/lightnvm/rrpc.c +++ b/drivers/lightnvm/rrpc.c @@ -1264,7 +1264,7 @@ static sector_t rrpc_capacity(void *private) sector_t reserved, provisioned; /* cur, gc, and two emergency blocks for each lun */ - reserved = rrpc->nr_luns * dev->max_pages_per_blk * 4; + reserved = rrpc->nr_luns * dev->sec_per_blk * 4; provisioned = rrpc->nr_sects - reserved; if (reserved > rrpc->nr_sects) { diff --git a/include/linux/lightnvm.h b/include/linux/lightnvm.h index b2991c724640..ef2c7d2e76c4 100644 --- a/include/linux/lightnvm.h +++ b/include/linux/lightnvm.h @@ -351,7 +351,6 @@ struct nvm_dev { unsigned long total_blocks; unsigned long total_secs; int nr_luns; - unsigned max_pages_per_blk; unsigned long *lun_map; void *dma_pool; -- cgit v1.2.3