aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/mtdcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/mtdcore.c')
-rw-r--r--drivers/mtd/mtdcore.c93
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
199struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num) 200struct 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
233out_put:
234 module_put(ret->owner);
235out_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
249struct 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
279out_put:
280 module_put(mtd->owner);
281out_unlock:
282 mutex_unlock(&mtd_table_mutex);
283 return ERR_PTR(err);
224} 284}
225 285
226void put_mtd_device(struct mtd_info *mtd) 286void 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
242int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs, 304int 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
267EXPORT_SYMBOL(add_mtd_device); 329EXPORT_SYMBOL_GPL(add_mtd_device);
268EXPORT_SYMBOL(del_mtd_device); 330EXPORT_SYMBOL_GPL(del_mtd_device);
269EXPORT_SYMBOL(get_mtd_device); 331EXPORT_SYMBOL_GPL(get_mtd_device);
270EXPORT_SYMBOL(put_mtd_device); 332EXPORT_SYMBOL_GPL(get_mtd_device_nm);
271EXPORT_SYMBOL(register_mtd_user); 333EXPORT_SYMBOL_GPL(put_mtd_device);
272EXPORT_SYMBOL(unregister_mtd_user); 334EXPORT_SYMBOL_GPL(register_mtd_user);
273EXPORT_SYMBOL(default_mtd_writev); 335EXPORT_SYMBOL_GPL(unregister_mtd_user);
336EXPORT_SYMBOL_GPL(default_mtd_writev);
274 337
275#ifdef CONFIG_PROC_FS 338#ifdef CONFIG_PROC_FS
276 339