aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/mtdcore.c37
-rw-r--r--include/linux/mtd/mtd.h7
2 files changed, 37 insertions, 7 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 06ec9f836ae5..f11f55f02413 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -214,12 +214,23 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
214 ret = NULL; 214 ret = NULL;
215 } 215 }
216 216
217 if (ret && !try_module_get(ret->owner)) 217 if (!ret)
218 goto out_unlock;
219
220 if (!try_module_get(ret->owner)) {
221 ret = NULL;
222 goto out_unlock;
223 }
224
225 if (ret->get_device && ret->get_device(ret)) {
226 module_put(ret->owner);
218 ret = NULL; 227 ret = NULL;
228 goto out_unlock;
229 }
219 230
220 if (ret) 231 ret->usecount++;
221 ret->usecount++;
222 232
233out_unlock:
223 mutex_unlock(&mtd_table_mutex); 234 mutex_unlock(&mtd_table_mutex);
224 return ret; 235 return ret;
225} 236}
@@ -235,8 +246,8 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
235 246
236struct mtd_info *get_mtd_device_nm(const char *name) 247struct mtd_info *get_mtd_device_nm(const char *name)
237{ 248{
238 int i; 249 int i, err = -ENODEV;
239 struct mtd_info *mtd = ERR_PTR(-ENODEV); 250 struct mtd_info *mtd = NULL;
240 251
241 mutex_lock(&mtd_table_mutex); 252 mutex_lock(&mtd_table_mutex);
242 253
@@ -247,17 +258,27 @@ struct mtd_info *get_mtd_device_nm(const char *name)
247 } 258 }
248 } 259 }
249 260
250 if (i == MAX_MTD_DEVICES) 261 if (!mtd)
251 goto out_unlock; 262 goto out_unlock;
252 263
253 if (!try_module_get(mtd->owner)) 264 if (!try_module_get(mtd->owner))
254 goto out_unlock; 265 goto out_unlock;
255 266
267 if (mtd->get_device) {
268 err = mtd->get_device(mtd);
269 if (err)
270 goto out_put;
271 }
272
256 mtd->usecount++; 273 mtd->usecount++;
274 mutex_unlock(&mtd_table_mutex);
275 return mtd;
257 276
277out_put:
278 module_put(mtd->owner);
258out_unlock: 279out_unlock:
259 mutex_unlock(&mtd_table_mutex); 280 mutex_unlock(&mtd_table_mutex);
260 return mtd; 281 return ERR_PTR(err);
261} 282}
262 283
263void put_mtd_device(struct mtd_info *mtd) 284void put_mtd_device(struct mtd_info *mtd)
@@ -266,6 +287,8 @@ void put_mtd_device(struct mtd_info *mtd)
266 287
267 mutex_lock(&mtd_table_mutex); 288 mutex_lock(&mtd_table_mutex);
268 c = --mtd->usecount; 289 c = --mtd->usecount;
290 if (mtd->put_device)
291 mtd->put_device(mtd);
269 mutex_unlock(&mtd_table_mutex); 292 mutex_unlock(&mtd_table_mutex);
270 BUG_ON(c < 0); 293 BUG_ON(c < 0);
271 294
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 89e937dfef55..d644e57703ad 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -207,6 +207,13 @@ struct mtd_info {
207 207
208 struct module *owner; 208 struct module *owner;
209 int usecount; 209 int usecount;
210
211 /* If the driver is something smart, like UBI, it may need to maintain
212 * its own reference counting. The below functions are only for driver.
213 * The driver may register its callbacks. These callbacks are not
214 * supposed to be called by MTD users */
215 int (*get_device) (struct mtd_info *mtd);
216 void (*put_device) (struct mtd_info *mtd);
210}; 217};
211 218
212 219