diff options
Diffstat (limited to 'drivers/mtd/mtdcore.c')
-rw-r--r-- | drivers/mtd/mtdcore.c | 93 |
1 files changed, 78 insertions, 15 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index c4d26de74349..7070110aba2a 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/timer.h> | 15 | #include <linux/timer.h> |
16 | #include <linux/major.h> | 16 | #include <linux/major.h> |
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/err.h> | ||
18 | #include <linux/ioctl.h> | 19 | #include <linux/ioctl.h> |
19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
20 | #include <linux/mtd/compatmac.h> | 21 | #include <linux/mtd/compatmac.h> |
@@ -192,14 +193,14 @@ int unregister_mtd_user (struct mtd_notifier *old) | |||
192 | * Given a number and NULL address, return the num'th entry in the device | 193 | * Given a number and NULL address, return the num'th entry in the device |
193 | * table, if any. Given an address and num == -1, search the device table | 194 | * table, if any. Given an address and num == -1, search the device table |
194 | * for a device with that address and return if it's still present. Given | 195 | * for a device with that address and return if it's still present. Given |
195 | * both, return the num'th driver only if its address matches. Return NULL | 196 | * both, return the num'th driver only if its address matches. Return |
196 | * if not. | 197 | * error code if not. |
197 | */ | 198 | */ |
198 | 199 | ||
199 | struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) | 200 | struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) |
200 | { | 201 | { |
201 | struct mtd_info *ret = NULL; | 202 | struct mtd_info *ret = NULL; |
202 | int i; | 203 | int i, err = -ENODEV; |
203 | 204 | ||
204 | mutex_lock(&mtd_table_mutex); | 205 | mutex_lock(&mtd_table_mutex); |
205 | 206 | ||
@@ -213,14 +214,73 @@ struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) | |||
213 | ret = NULL; | 214 | ret = NULL; |
214 | } | 215 | } |
215 | 216 | ||
216 | if (ret && !try_module_get(ret->owner)) | 217 | if (!ret) |
217 | ret = NULL; | 218 | goto out_unlock; |
219 | |||
220 | if (!try_module_get(ret->owner)) | ||
221 | goto out_unlock; | ||
218 | 222 | ||
219 | if (ret) | 223 | if (ret->get_device) { |
220 | ret->usecount++; | 224 | err = ret->get_device(ret); |
225 | if (err) | ||
226 | goto out_put; | ||
227 | } | ||
221 | 228 | ||
229 | ret->usecount++; | ||
222 | mutex_unlock(&mtd_table_mutex); | 230 | mutex_unlock(&mtd_table_mutex); |
223 | return ret; | 231 | return ret; |
232 | |||
233 | out_put: | ||
234 | module_put(ret->owner); | ||
235 | out_unlock: | ||
236 | mutex_unlock(&mtd_table_mutex); | ||
237 | return ERR_PTR(err); | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * get_mtd_device_nm - obtain a validated handle for an MTD device by | ||
242 | * device name | ||
243 | * @name: MTD device name to open | ||
244 | * | ||
245 | * This function returns MTD device description structure in case of | ||
246 | * success and an error code in case of failure. | ||
247 | */ | ||
248 | |||
249 | struct mtd_info *get_mtd_device_nm(const char *name) | ||
250 | { | ||
251 | int i, err = -ENODEV; | ||
252 | struct mtd_info *mtd = NULL; | ||
253 | |||
254 | mutex_lock(&mtd_table_mutex); | ||
255 | |||
256 | for (i = 0; i < MAX_MTD_DEVICES; i++) { | ||
257 | if (mtd_table[i] && !strcmp(name, mtd_table[i]->name)) { | ||
258 | mtd = mtd_table[i]; | ||
259 | break; | ||
260 | } | ||
261 | } | ||
262 | |||
263 | if (!mtd) | ||
264 | goto out_unlock; | ||
265 | |||
266 | if (!try_module_get(mtd->owner)) | ||
267 | goto out_unlock; | ||
268 | |||
269 | if (mtd->get_device) { | ||
270 | err = mtd->get_device(mtd); | ||
271 | if (err) | ||
272 | goto out_put; | ||
273 | } | ||
274 | |||
275 | mtd->usecount++; | ||
276 | mutex_unlock(&mtd_table_mutex); | ||
277 | return mtd; | ||
278 | |||
279 | out_put: | ||
280 | module_put(mtd->owner); | ||
281 | out_unlock: | ||
282 | mutex_unlock(&mtd_table_mutex); | ||
283 | return ERR_PTR(err); | ||
224 | } | 284 | } |
225 | 285 | ||
226 | void put_mtd_device(struct mtd_info *mtd) | 286 | void put_mtd_device(struct mtd_info *mtd) |
@@ -229,6 +289,8 @@ void put_mtd_device(struct mtd_info *mtd) | |||
229 | 289 | ||
230 | mutex_lock(&mtd_table_mutex); | 290 | mutex_lock(&mtd_table_mutex); |
231 | c = --mtd->usecount; | 291 | c = --mtd->usecount; |
292 | if (mtd->put_device) | ||
293 | mtd->put_device(mtd); | ||
232 | mutex_unlock(&mtd_table_mutex); | 294 | mutex_unlock(&mtd_table_mutex); |
233 | BUG_ON(c < 0); | 295 | BUG_ON(c < 0); |
234 | 296 | ||
@@ -236,7 +298,7 @@ void put_mtd_device(struct mtd_info *mtd) | |||
236 | } | 298 | } |
237 | 299 | ||
238 | /* default_mtd_writev - default mtd writev method for MTD devices that | 300 | /* default_mtd_writev - default mtd writev method for MTD devices that |
239 | * dont implement their own | 301 | * don't implement their own |
240 | */ | 302 | */ |
241 | 303 | ||
242 | int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, | 304 | int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, |
@@ -264,13 +326,14 @@ int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, | |||
264 | return ret; | 326 | return ret; |
265 | } | 327 | } |
266 | 328 | ||
267 | EXPORT_SYMBOL(add_mtd_device); | 329 | EXPORT_SYMBOL_GPL(add_mtd_device); |
268 | EXPORT_SYMBOL(del_mtd_device); | 330 | EXPORT_SYMBOL_GPL(del_mtd_device); |
269 | EXPORT_SYMBOL(get_mtd_device); | 331 | EXPORT_SYMBOL_GPL(get_mtd_device); |
270 | EXPORT_SYMBOL(put_mtd_device); | 332 | EXPORT_SYMBOL_GPL(get_mtd_device_nm); |
271 | EXPORT_SYMBOL(register_mtd_user); | 333 | EXPORT_SYMBOL_GPL(put_mtd_device); |
272 | EXPORT_SYMBOL(unregister_mtd_user); | 334 | EXPORT_SYMBOL_GPL(register_mtd_user); |
273 | EXPORT_SYMBOL(default_mtd_writev); | 335 | EXPORT_SYMBOL_GPL(unregister_mtd_user); |
336 | EXPORT_SYMBOL_GPL(default_mtd_writev); | ||
274 | 337 | ||
275 | #ifdef CONFIG_PROC_FS | 338 | #ifdef CONFIG_PROC_FS |
276 | 339 | ||