|
@@ -97,15 +97,47 @@ static struct nvmm_type *nvm_find_mgr_type(const char *name)
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
+struct nvmm_type *nvm_init_mgr(struct nvm_dev *dev)
|
|
|
+{
|
|
|
+ struct nvmm_type *mt;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ lockdep_assert_held(&nvm_lock);
|
|
|
+
|
|
|
+ list_for_each_entry(mt, &nvm_mgrs, list) {
|
|
|
+ ret = mt->register_mgr(dev);
|
|
|
+ if (ret < 0) {
|
|
|
+ pr_err("nvm: media mgr failed to init (%d) on dev %s\n",
|
|
|
+ ret, dev->name);
|
|
|
+ return NULL; /* initialization failed */
|
|
|
+ } else if (ret > 0)
|
|
|
+ return mt;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
int nvm_register_mgr(struct nvmm_type *mt)
|
|
|
{
|
|
|
+ struct nvm_dev *dev;
|
|
|
int ret = 0;
|
|
|
|
|
|
down_write(&nvm_lock);
|
|
|
- if (nvm_find_mgr_type(mt->name))
|
|
|
+ if (nvm_find_mgr_type(mt->name)) {
|
|
|
ret = -EEXIST;
|
|
|
- else
|
|
|
+ goto finish;
|
|
|
+ } else {
|
|
|
list_add(&mt->list, &nvm_mgrs);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* try to register media mgr if any device have none configured */
|
|
|
+ list_for_each_entry(dev, &nvm_devices, devices) {
|
|
|
+ if (dev->mt)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ dev->mt = nvm_init_mgr(dev);
|
|
|
+ }
|
|
|
+finish:
|
|
|
up_write(&nvm_lock);
|
|
|
|
|
|
return ret;
|
|
@@ -123,26 +155,6 @@ 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;
|
|
@@ -271,14 +283,6 @@ static int nvm_init(struct nvm_dev *dev)
|
|
|
goto err;
|
|
|
}
|
|
|
|
|
|
- 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,
|
|
|
dev->pgs_per_blk, dev->blks_per_lun, dev->nr_luns,
|
|
@@ -334,7 +338,9 @@ int nvm_register(struct request_queue *q, char *disk_name,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /* register device with a supported media manager */
|
|
|
down_write(&nvm_lock);
|
|
|
+ dev->mt = nvm_init_mgr(dev);
|
|
|
list_add(&dev->devices, &nvm_devices);
|
|
|
up_write(&nvm_lock);
|
|
|
|
|
@@ -379,19 +385,13 @@ static int nvm_create_target(struct nvm_dev *dev,
|
|
|
struct nvm_tgt_type *tt;
|
|
|
struct nvm_target *t;
|
|
|
void *targetdata;
|
|
|
- int ret = 0;
|
|
|
|
|
|
- down_write(&nvm_lock);
|
|
|
if (!dev->mt) {
|
|
|
- ret = register_mgr(dev);
|
|
|
- if (!ret)
|
|
|
- ret = -ENODEV;
|
|
|
- if (ret < 0) {
|
|
|
- up_write(&nvm_lock);
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ pr_info("nvm: device has no media manager registered.\n");
|
|
|
+ return -ENODEV;
|
|
|
}
|
|
|
|
|
|
+ down_write(&nvm_lock);
|
|
|
tt = nvm_find_target_type(create->tgttype);
|
|
|
if (!tt) {
|
|
|
pr_err("nvm: target type %s not found\n", create->tgttype);
|