|
@@ -123,6 +123,26 @@ void nvm_unregister_mgr(struct nvmm_type *mt)
|
|
|
}
|
|
|
EXPORT_SYMBOL(nvm_unregister_mgr);
|
|
|
|
|
|
+/* register with device with a supported manager */
|
|
|
+static int register_mgr(struct nvm_dev *dev)
|
|
|
+{
|
|
|
+ struct nvmm_type *mt;
|
|
|
+ int ret = 0;
|
|
|
+
|
|
|
+ list_for_each_entry(mt, &nvm_mgrs, list) {
|
|
|
+ ret = mt->register_mgr(dev);
|
|
|
+ if (ret > 0) {
|
|
|
+ dev->mt = mt;
|
|
|
+ break; /* successfully initialized */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ret)
|
|
|
+ pr_info("nvm: no compatible nvm manager found.\n");
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
static struct nvm_dev *nvm_find_nvm_dev(const char *name)
|
|
|
{
|
|
|
struct nvm_dev *dev;
|
|
@@ -221,7 +241,6 @@ static void nvm_free(struct nvm_dev *dev)
|
|
|
|
|
|
static int nvm_init(struct nvm_dev *dev)
|
|
|
{
|
|
|
- struct nvmm_type *mt;
|
|
|
int ret = -EINVAL;
|
|
|
|
|
|
if (!dev->q || !dev->ops)
|
|
@@ -252,21 +271,13 @@ static int nvm_init(struct nvm_dev *dev)
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
- /* register with device with a supported manager */
|
|
|
- list_for_each_entry(mt, &nvm_mgrs, list) {
|
|
|
- ret = mt->register_mgr(dev);
|
|
|
- if (ret < 0)
|
|
|
- goto err; /* initialization failed */
|
|
|
- if (ret > 0) {
|
|
|
- dev->mt = mt;
|
|
|
- break; /* successfully initialized */
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!ret) {
|
|
|
- pr_info("nvm: no compatible manager found.\n");
|
|
|
+ down_write(&nvm_lock);
|
|
|
+ ret = register_mgr(dev);
|
|
|
+ up_write(&nvm_lock);
|
|
|
+ if (ret < 0)
|
|
|
+ goto err;
|
|
|
+ if (!ret)
|
|
|
return 0;
|
|
|
- }
|
|
|
|
|
|
pr_info("nvm: registered %s [%u/%u/%u/%u/%u/%u]\n",
|
|
|
dev->name, dev->sec_per_pg, dev->nr_planes,
|
|
@@ -337,15 +348,17 @@ EXPORT_SYMBOL(nvm_register);
|
|
|
|
|
|
void nvm_unregister(char *disk_name)
|
|
|
{
|
|
|
- struct nvm_dev *dev = nvm_find_nvm_dev(disk_name);
|
|
|
+ struct nvm_dev *dev;
|
|
|
|
|
|
+ down_write(&nvm_lock);
|
|
|
+ dev = nvm_find_nvm_dev(disk_name);
|
|
|
if (!dev) {
|
|
|
pr_err("nvm: could not find device %s to unregister\n",
|
|
|
disk_name);
|
|
|
+ up_write(&nvm_lock);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- down_write(&nvm_lock);
|
|
|
list_del(&dev->devices);
|
|
|
up_write(&nvm_lock);
|
|
|
|
|
@@ -363,38 +376,30 @@ static int nvm_create_target(struct nvm_dev *dev,
|
|
|
{
|
|
|
struct nvm_ioctl_create_simple *s = &create->conf.s;
|
|
|
struct request_queue *tqueue;
|
|
|
- struct nvmm_type *mt;
|
|
|
struct gendisk *tdisk;
|
|
|
struct nvm_tgt_type *tt;
|
|
|
struct nvm_target *t;
|
|
|
void *targetdata;
|
|
|
int ret = 0;
|
|
|
|
|
|
+ down_write(&nvm_lock);
|
|
|
if (!dev->mt) {
|
|
|
- /* register with device with a supported NVM manager */
|
|
|
- list_for_each_entry(mt, &nvm_mgrs, list) {
|
|
|
- ret = mt->register_mgr(dev);
|
|
|
- if (ret < 0)
|
|
|
- return ret; /* initialization failed */
|
|
|
- if (ret > 0) {
|
|
|
- dev->mt = mt;
|
|
|
- break; /* successfully initialized */
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!ret) {
|
|
|
- pr_info("nvm: no compatible nvm manager found.\n");
|
|
|
- return -ENODEV;
|
|
|
+ ret = register_mgr(dev);
|
|
|
+ if (!ret)
|
|
|
+ ret = -ENODEV;
|
|
|
+ if (ret < 0) {
|
|
|
+ up_write(&nvm_lock);
|
|
|
+ return ret;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
tt = nvm_find_target_type(create->tgttype);
|
|
|
if (!tt) {
|
|
|
pr_err("nvm: target type %s not found\n", create->tgttype);
|
|
|
+ up_write(&nvm_lock);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- down_write(&nvm_lock);
|
|
|
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");
|
|
@@ -478,7 +483,9 @@ static int __nvm_configure_create(struct nvm_ioctl_create *create)
|
|
|
struct nvm_dev *dev;
|
|
|
struct nvm_ioctl_create_simple *s;
|
|
|
|
|
|
+ down_write(&nvm_lock);
|
|
|
dev = nvm_find_nvm_dev(create->dev);
|
|
|
+ up_write(&nvm_lock);
|
|
|
if (!dev) {
|
|
|
pr_err("nvm: device not found\n");
|
|
|
return -EINVAL;
|
|
@@ -537,7 +544,9 @@ static int nvm_configure_show(const char *val)
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ down_write(&nvm_lock);
|
|
|
dev = nvm_find_nvm_dev(devname);
|
|
|
+ up_write(&nvm_lock);
|
|
|
if (!dev) {
|
|
|
pr_err("nvm: device not found\n");
|
|
|
return -EINVAL;
|