diff options
Diffstat (limited to 'drivers/lightnvm/core.c')
-rw-r--r-- | drivers/lightnvm/core.c | 97 |
1 files changed, 63 insertions, 34 deletions
diff --git a/drivers/lightnvm/core.c b/drivers/lightnvm/core.c index a600934fdd9c..7543e395a2c6 100644 --- a/drivers/lightnvm/core.c +++ b/drivers/lightnvm/core.c @@ -4,6 +4,8 @@ * Initial release: Matias Bjorling <m@bjorling.me> */ +#define pr_fmt(fmt) "nvm: " fmt + #include <linux/list.h> #include <linux/types.h> #include <linux/sem.h> @@ -74,7 +76,7 @@ static int nvm_reserve_luns(struct nvm_dev *dev, int lun_begin, int lun_end) for (i = lun_begin; i <= lun_end; i++) { if (test_and_set_bit(i, dev->lun_map)) { - pr_err("nvm: lun %d already allocated\n", i); + pr_err("lun %d already allocated\n", i); goto err; } } @@ -264,7 +266,7 @@ static int nvm_config_check_luns(struct nvm_geo *geo, int lun_begin, int lun_end) { if (lun_begin > lun_end || lun_end >= geo->all_luns) { - pr_err("nvm: lun out of bound (%u:%u > %u)\n", + pr_err("lun out of bound (%u:%u > %u)\n", lun_begin, lun_end, geo->all_luns - 1); return -EINVAL; } @@ -297,7 +299,7 @@ static int __nvm_config_extended(struct nvm_dev *dev, if (e->op == 0xFFFF) { e->op = NVM_TARGET_DEFAULT_OP; } else if (e->op < NVM_TARGET_MIN_OP || e->op > NVM_TARGET_MAX_OP) { - pr_err("nvm: invalid over provisioning value\n"); + pr_err("invalid over provisioning value\n"); return -EINVAL; } @@ -334,23 +336,23 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create) e = create->conf.e; break; default: - pr_err("nvm: config type not valid\n"); + pr_err("config type not valid\n"); return -EINVAL; } tt = nvm_find_target_type(create->tgttype); if (!tt) { - pr_err("nvm: target type %s not found\n", create->tgttype); + pr_err("target type %s not found\n", create->tgttype); return -EINVAL; } if ((tt->flags & NVM_TGT_F_HOST_L2P) != (dev->geo.dom & NVM_RSP_L2P)) { - pr_err("nvm: device is incompatible with target L2P type.\n"); + pr_err("device is incompatible with target L2P type.\n"); return -EINVAL; } if (nvm_target_exists(create->tgtname)) { - pr_err("nvm: target name already exists (%s)\n", + pr_err("target name already exists (%s)\n", create->tgtname); return -EINVAL; } @@ -367,7 +369,7 @@ static int nvm_create_tgt(struct nvm_dev *dev, struct nvm_ioctl_create *create) tgt_dev = nvm_create_tgt_dev(dev, e.lun_begin, e.lun_end, e.op); if (!tgt_dev) { - pr_err("nvm: could not create target device\n"); + pr_err("could not create target device\n"); ret = -ENOMEM; goto err_t; } @@ -493,8 +495,11 @@ static int nvm_remove_tgt(struct nvm_ioctl_remove *remove) } up_read(&nvm_lock); - if (!t) + if (!t) { + pr_err("failed to remove target %s\n", + remove->tgtname); return 1; + } __nvm_remove_target(t, true); kref_put(&dev->ref, nvm_free); @@ -686,7 +691,7 @@ static int nvm_set_rqd_ppalist(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd, 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"); + pr_err("failed to allocate dma memory\n"); return -ENOMEM; } @@ -731,7 +736,7 @@ static int nvm_set_flags(struct nvm_geo *geo, struct nvm_rq *rqd) return flags; } -int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd) +int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd, void *buf) { struct nvm_dev *dev = tgt_dev->parent; int ret; @@ -745,19 +750,45 @@ int nvm_submit_io(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd) rqd->flags = nvm_set_flags(&tgt_dev->geo, rqd); /* In case of error, fail with right address format */ - ret = dev->ops->submit_io(dev, rqd); + ret = dev->ops->submit_io(dev, rqd, buf); if (ret) nvm_rq_dev_to_tgt(tgt_dev, rqd); return ret; } EXPORT_SYMBOL(nvm_submit_io); -int nvm_submit_io_sync(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd) +static void nvm_sync_end_io(struct nvm_rq *rqd) +{ + struct completion *waiting = rqd->private; + + complete(waiting); +} + +static int nvm_submit_io_wait(struct nvm_dev *dev, struct nvm_rq *rqd, + void *buf) +{ + DECLARE_COMPLETION_ONSTACK(wait); + int ret = 0; + + rqd->end_io = nvm_sync_end_io; + rqd->private = &wait; + + ret = dev->ops->submit_io(dev, rqd, buf); + if (ret) + return ret; + + wait_for_completion_io(&wait); + + return 0; +} + +int nvm_submit_io_sync(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd, + void *buf) { struct nvm_dev *dev = tgt_dev->parent; int ret; - if (!dev->ops->submit_io_sync) + if (!dev->ops->submit_io) return -ENODEV; nvm_rq_tgt_to_dev(tgt_dev, rqd); @@ -765,9 +796,7 @@ int nvm_submit_io_sync(struct nvm_tgt_dev *tgt_dev, struct nvm_rq *rqd) rqd->dev = tgt_dev; rqd->flags = nvm_set_flags(&tgt_dev->geo, rqd); - /* In case of error, fail with right address format */ - ret = dev->ops->submit_io_sync(dev, rqd); - nvm_rq_dev_to_tgt(tgt_dev, rqd); + ret = nvm_submit_io_wait(dev, rqd, buf); return ret; } @@ -788,12 +817,13 @@ EXPORT_SYMBOL(nvm_end_io); static int nvm_submit_io_sync_raw(struct nvm_dev *dev, struct nvm_rq *rqd) { - if (!dev->ops->submit_io_sync) + if (!dev->ops->submit_io) return -ENODEV; + rqd->dev = NULL; rqd->flags = nvm_set_flags(&dev->geo, rqd); - return dev->ops->submit_io_sync(dev, rqd); + return nvm_submit_io_wait(dev, rqd, NULL); } static int nvm_bb_chunk_sense(struct nvm_dev *dev, struct ppa_addr ppa) @@ -1048,7 +1078,7 @@ int nvm_set_chunk_meta(struct nvm_tgt_dev *tgt_dev, struct ppa_addr *ppas, return 0; if (nr_ppas > NVM_MAX_VLBA) { - pr_err("nvm: unable to update all blocks atomically\n"); + pr_err("unable to update all blocks atomically\n"); return -EINVAL; } @@ -1111,27 +1141,26 @@ static int nvm_init(struct nvm_dev *dev) int ret = -EINVAL; if (dev->ops->identity(dev)) { - pr_err("nvm: device could not be identified\n"); + pr_err("device could not be identified\n"); goto err; } - pr_debug("nvm: ver:%u.%u nvm_vendor:%x\n", - geo->major_ver_id, geo->minor_ver_id, - geo->vmnt); + pr_debug("ver:%u.%u nvm_vendor:%x\n", geo->major_ver_id, + geo->minor_ver_id, geo->vmnt); ret = nvm_core_init(dev); if (ret) { - pr_err("nvm: could not initialize core structures.\n"); + pr_err("could not initialize core structures.\n"); goto err; } - pr_info("nvm: registered %s [%u/%u/%u/%u/%u]\n", + pr_info("registered %s [%u/%u/%u/%u/%u]\n", dev->name, dev->geo.ws_min, dev->geo.ws_opt, dev->geo.num_chk, dev->geo.all_luns, dev->geo.num_ch); return 0; err: - pr_err("nvm: failed to initialize nvm\n"); + pr_err("failed to initialize nvm\n"); return ret; } @@ -1169,7 +1198,7 @@ int nvm_register(struct nvm_dev *dev) dev->dma_pool = dev->ops->create_dma_pool(dev, "ppalist", exp_pool_size); if (!dev->dma_pool) { - pr_err("nvm: could not create dma pool\n"); + pr_err("could not create dma pool\n"); kref_put(&dev->ref, nvm_free); return -ENOMEM; } @@ -1214,7 +1243,7 @@ static int __nvm_configure_create(struct nvm_ioctl_create *create) up_write(&nvm_lock); if (!dev) { - pr_err("nvm: device not found\n"); + pr_err("device not found\n"); return -EINVAL; } @@ -1288,7 +1317,7 @@ static long nvm_ioctl_get_devices(struct file *file, void __user *arg) i++; if (i > 31) { - pr_err("nvm: max 31 devices can be reported.\n"); + pr_err("max 31 devices can be reported.\n"); break; } } @@ -1315,7 +1344,7 @@ static long nvm_ioctl_dev_create(struct file *file, void __user *arg) if (create.conf.type == NVM_CONFIG_TYPE_EXTENDED && create.conf.e.rsv != 0) { - pr_err("nvm: reserved config field in use\n"); + pr_err("reserved config field in use\n"); return -EINVAL; } @@ -1331,7 +1360,7 @@ static long nvm_ioctl_dev_create(struct file *file, void __user *arg) flags &= ~NVM_TARGET_FACTORY; if (flags) { - pr_err("nvm: flag not supported\n"); + pr_err("flag not supported\n"); return -EINVAL; } } @@ -1349,7 +1378,7 @@ static long nvm_ioctl_dev_remove(struct file *file, void __user *arg) remove.tgtname[DISK_NAME_LEN - 1] = '\0'; if (remove.flags != 0) { - pr_err("nvm: no flags supported\n"); + pr_err("no flags supported\n"); return -EINVAL; } @@ -1365,7 +1394,7 @@ static long nvm_ioctl_dev_init(struct file *file, void __user *arg) return -EFAULT; if (init.flags != 0) { - pr_err("nvm: no flags supported\n"); + pr_err("no flags supported\n"); return -EINVAL; } |