mtdcore.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. /*
  2. * Core registration and callback routines for MTD
  3. * drivers and users.
  4. *
  5. * bdi bits are:
  6. * Copyright © 2006 Red Hat, Inc. All Rights Reserved.
  7. * Written by David Howells (dhowells@redhat.com)
  8. */
  9. #include <linux/module.h>
  10. #include <linux/kernel.h>
  11. #include <linux/ptrace.h>
  12. #include <linux/string.h>
  13. #include <linux/timer.h>
  14. #include <linux/major.h>
  15. #include <linux/fs.h>
  16. #include <linux/err.h>
  17. #include <linux/ioctl.h>
  18. #include <linux/init.h>
  19. #include <linux/mtd/compatmac.h>
  20. #include <linux/proc_fs.h>
  21. #include <linux/backing-dev.h>
  22. #include <linux/mtd/mtd.h>
  23. #include "mtdcore.h"
  24. /*
  25. * backing device capabilities for non-mappable devices (such as NAND flash)
  26. * - permits private mappings, copies are taken of the data
  27. */
  28. struct backing_dev_info mtd_bdi_unmappable = {
  29. .capabilities = BDI_CAP_MAP_COPY,
  30. };
  31. /*
  32. * backing device capabilities for R/O mappable devices (such as ROM)
  33. * - permits private mappings, copies are taken of the data
  34. * - permits non-writable shared mappings
  35. */
  36. struct backing_dev_info mtd_bdi_ro_mappable = {
  37. .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
  38. BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP),
  39. };
  40. /*
  41. * backing device capabilities for writable mappable devices (such as RAM)
  42. * - permits private mappings, copies are taken of the data
  43. * - permits non-writable shared mappings
  44. */
  45. struct backing_dev_info mtd_bdi_rw_mappable = {
  46. .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
  47. BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP |
  48. BDI_CAP_WRITE_MAP),
  49. };
  50. static int mtd_cls_suspend(struct device *dev, pm_message_t state);
  51. static int mtd_cls_resume(struct device *dev);
  52. static struct class mtd_class = {
  53. .name = "mtd",
  54. .owner = THIS_MODULE,
  55. .suspend = mtd_cls_suspend,
  56. .resume = mtd_cls_resume,
  57. };
  58. /* These are exported solely for the purpose of mtd_blkdevs.c. You
  59. should not use them for _anything_ else */
  60. DEFINE_MUTEX(mtd_table_mutex);
  61. struct mtd_info *mtd_table[MAX_MTD_DEVICES];
  62. EXPORT_SYMBOL_GPL(mtd_table_mutex);
  63. EXPORT_SYMBOL_GPL(mtd_table);
  64. static LIST_HEAD(mtd_notifiers);
  65. #if defined(CONFIG_MTD_CHAR) || defined(CONFIG_MTD_CHAR_MODULE)
  66. #define MTD_DEVT(index) MKDEV(MTD_CHAR_MAJOR, (index)*2)
  67. #else
  68. #define MTD_DEVT(index) 0
  69. #endif
  70. /* REVISIT once MTD uses the driver model better, whoever allocates
  71. * the mtd_info will probably want to use the release() hook...
  72. */
  73. static void mtd_release(struct device *dev)
  74. {
  75. dev_t index = MTD_DEVT(dev_to_mtd(dev)->index);
  76. /* remove /dev/mtdXro node if needed */
  77. if (index)
  78. device_destroy(&mtd_class, index + 1);
  79. }
  80. static int mtd_cls_suspend(struct device *dev, pm_message_t state)
  81. {
  82. struct mtd_info *mtd = dev_to_mtd(dev);
  83. if (mtd && mtd->suspend)
  84. return mtd->suspend(mtd);
  85. else
  86. return 0;
  87. }
  88. static int mtd_cls_resume(struct device *dev)
  89. {
  90. struct mtd_info *mtd = dev_to_mtd(dev);
  91. if (mtd && mtd->resume)
  92. mtd->resume(mtd);
  93. return 0;
  94. }
  95. static ssize_t mtd_type_show(struct device *dev,
  96. struct device_attribute *attr, char *buf)
  97. {
  98. struct mtd_info *mtd = dev_to_mtd(dev);
  99. char *type;
  100. switch (mtd->type) {
  101. case MTD_ABSENT:
  102. type = "absent";
  103. break;
  104. case MTD_RAM:
  105. type = "ram";
  106. break;
  107. case MTD_ROM:
  108. type = "rom";
  109. break;
  110. case MTD_NORFLASH:
  111. type = "nor";
  112. break;
  113. case MTD_NANDFLASH:
  114. type = "nand";
  115. break;
  116. case MTD_DATAFLASH:
  117. type = "dataflash";
  118. break;
  119. case MTD_UBIVOLUME:
  120. type = "ubi";
  121. break;
  122. default:
  123. type = "unknown";
  124. }
  125. return snprintf(buf, PAGE_SIZE, "%s\n", type);
  126. }
  127. static DEVICE_ATTR(type, S_IRUGO, mtd_type_show, NULL);
  128. static ssize_t mtd_flags_show(struct device *dev,
  129. struct device_attribute *attr, char *buf)
  130. {
  131. struct mtd_info *mtd = dev_to_mtd(dev);
  132. return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags);
  133. }
  134. static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL);
  135. static ssize_t mtd_size_show(struct device *dev,
  136. struct device_attribute *attr, char *buf)
  137. {
  138. struct mtd_info *mtd = dev_to_mtd(dev);
  139. return snprintf(buf, PAGE_SIZE, "%llu\n",
  140. (unsigned long long)mtd->size);
  141. }
  142. static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL);
  143. static ssize_t mtd_erasesize_show(struct device *dev,
  144. struct device_attribute *attr, char *buf)
  145. {
  146. struct mtd_info *mtd = dev_to_mtd(dev);
  147. return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize);
  148. }
  149. static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL);
  150. static ssize_t mtd_writesize_show(struct device *dev,
  151. struct device_attribute *attr, char *buf)
  152. {
  153. struct mtd_info *mtd = dev_to_mtd(dev);
  154. return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize);
  155. }
  156. static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL);
  157. static ssize_t mtd_subpagesize_show(struct device *dev,
  158. struct device_attribute *attr, char *buf)
  159. {
  160. struct mtd_info *mtd = dev_to_mtd(dev);
  161. unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft;
  162. return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize);
  163. }
  164. static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL);
  165. static ssize_t mtd_oobsize_show(struct device *dev,
  166. struct device_attribute *attr, char *buf)
  167. {
  168. struct mtd_info *mtd = dev_to_mtd(dev);
  169. return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize);
  170. }
  171. static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL);
  172. static ssize_t mtd_numeraseregions_show(struct device *dev,
  173. struct device_attribute *attr, char *buf)
  174. {
  175. struct mtd_info *mtd = dev_to_mtd(dev);
  176. return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions);
  177. }
  178. static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show,
  179. NULL);
  180. static ssize_t mtd_name_show(struct device *dev,
  181. struct device_attribute *attr, char *buf)
  182. {
  183. struct mtd_info *mtd = dev_to_mtd(dev);
  184. return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name);
  185. }
  186. static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL);
  187. static struct attribute *mtd_attrs[] = {
  188. &dev_attr_type.attr,
  189. &dev_attr_flags.attr,
  190. &dev_attr_size.attr,
  191. &dev_attr_erasesize.attr,
  192. &dev_attr_writesize.attr,
  193. &dev_attr_subpagesize.attr,
  194. &dev_attr_oobsize.attr,
  195. &dev_attr_numeraseregions.attr,
  196. &dev_attr_name.attr,
  197. NULL,
  198. };
  199. static struct attribute_group mtd_group = {
  200. .attrs = mtd_attrs,
  201. };
  202. static const struct attribute_group *mtd_groups[] = {
  203. &mtd_group,
  204. NULL,
  205. };
  206. static struct device_type mtd_devtype = {
  207. .name = "mtd",
  208. .groups = mtd_groups,
  209. .release = mtd_release,
  210. };
  211. /**
  212. * add_mtd_device - register an MTD device
  213. * @mtd: pointer to new MTD device info structure
  214. *
  215. * Add a device to the list of MTD devices present in the system, and
  216. * notify each currently active MTD 'user' of its arrival. Returns
  217. * zero on success or 1 on failure, which currently will only happen
  218. * if the number of present devices exceeds MAX_MTD_DEVICES (i.e. 16)
  219. * or there's a sysfs error.
  220. */
  221. int add_mtd_device(struct mtd_info *mtd)
  222. {
  223. int i;
  224. if (!mtd->backing_dev_info) {
  225. switch (mtd->type) {
  226. case MTD_RAM:
  227. mtd->backing_dev_info = &mtd_bdi_rw_mappable;
  228. break;
  229. case MTD_ROM:
  230. mtd->backing_dev_info = &mtd_bdi_ro_mappable;
  231. break;
  232. default:
  233. mtd->backing_dev_info = &mtd_bdi_unmappable;
  234. break;
  235. }
  236. }
  237. BUG_ON(mtd->writesize == 0);
  238. mutex_lock(&mtd_table_mutex);
  239. for (i=0; i < MAX_MTD_DEVICES; i++)
  240. if (!mtd_table[i]) {
  241. struct mtd_notifier *not;
  242. mtd_table[i] = mtd;
  243. mtd->index = i;
  244. mtd->usecount = 0;
  245. if (is_power_of_2(mtd->erasesize))
  246. mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
  247. else
  248. mtd->erasesize_shift = 0;
  249. if (is_power_of_2(mtd->writesize))
  250. mtd->writesize_shift = ffs(mtd->writesize) - 1;
  251. else
  252. mtd->writesize_shift = 0;
  253. mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
  254. mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
  255. /* Some chips always power up locked. Unlock them now */
  256. if ((mtd->flags & MTD_WRITEABLE)
  257. && (mtd->flags & MTD_POWERUP_LOCK) && mtd->unlock) {
  258. if (mtd->unlock(mtd, 0, mtd->size))
  259. printk(KERN_WARNING
  260. "%s: unlock failed, "
  261. "writes may not work\n",
  262. mtd->name);
  263. }
  264. /* Caller should have set dev.parent to match the
  265. * physical device.
  266. */
  267. mtd->dev.type = &mtd_devtype;
  268. mtd->dev.class = &mtd_class;
  269. mtd->dev.devt = MTD_DEVT(i);
  270. dev_set_name(&mtd->dev, "mtd%d", i);
  271. dev_set_drvdata(&mtd->dev, mtd);
  272. if (device_register(&mtd->dev) != 0) {
  273. mtd_table[i] = NULL;
  274. break;
  275. }
  276. if (MTD_DEVT(i))
  277. device_create(&mtd_class, mtd->dev.parent,
  278. MTD_DEVT(i) + 1,
  279. NULL, "mtd%dro", i);
  280. DEBUG(0, "mtd: Giving out device %d to %s\n",i, mtd->name);
  281. /* No need to get a refcount on the module containing
  282. the notifier, since we hold the mtd_table_mutex */
  283. list_for_each_entry(not, &mtd_notifiers, list)
  284. not->add(mtd);
  285. mutex_unlock(&mtd_table_mutex);
  286. /* We _know_ we aren't being removed, because
  287. our caller is still holding us here. So none
  288. of this try_ nonsense, and no bitching about it
  289. either. :) */
  290. __module_get(THIS_MODULE);
  291. return 0;
  292. }
  293. mutex_unlock(&mtd_table_mutex);
  294. return 1;
  295. }
  296. /**
  297. * del_mtd_device - unregister an MTD device
  298. * @mtd: pointer to MTD device info structure
  299. *
  300. * Remove a device from the list of MTD devices present in the system,
  301. * and notify each currently active MTD 'user' of its departure.
  302. * Returns zero on success or 1 on failure, which currently will happen
  303. * if the requested device does not appear to be present in the list.
  304. */
  305. int del_mtd_device (struct mtd_info *mtd)
  306. {
  307. int ret;
  308. mutex_lock(&mtd_table_mutex);
  309. if (mtd_table[mtd->index] != mtd) {
  310. ret = -ENODEV;
  311. } else if (mtd->usecount) {
  312. printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n",
  313. mtd->index, mtd->name, mtd->usecount);
  314. ret = -EBUSY;
  315. } else {
  316. struct mtd_notifier *not;
  317. device_unregister(&mtd->dev);
  318. /* No need to get a refcount on the module containing
  319. the notifier, since we hold the mtd_table_mutex */
  320. list_for_each_entry(not, &mtd_notifiers, list)
  321. not->remove(mtd);
  322. mtd_table[mtd->index] = NULL;
  323. module_put(THIS_MODULE);
  324. ret = 0;
  325. }
  326. mutex_unlock(&mtd_table_mutex);
  327. return ret;
  328. }
  329. /**
  330. * register_mtd_user - register a 'user' of MTD devices.
  331. * @new: pointer to notifier info structure
  332. *
  333. * Registers a pair of callbacks function to be called upon addition
  334. * or removal of MTD devices. Causes the 'add' callback to be immediately
  335. * invoked for each MTD device currently present in the system.
  336. */
  337. void register_mtd_user (struct mtd_notifier *new)
  338. {
  339. int i;
  340. mutex_lock(&mtd_table_mutex);
  341. list_add(&new->list, &mtd_notifiers);
  342. __module_get(THIS_MODULE);
  343. for (i=0; i< MAX_MTD_DEVICES; i++)
  344. if (mtd_table[i])
  345. new->add(mtd_table[i]);
  346. mutex_unlock(&mtd_table_mutex);
  347. }
  348. /**
  349. * unregister_mtd_user - unregister a 'user' of MTD devices.
  350. * @old: pointer to notifier info structure
  351. *
  352. * Removes a callback function pair from the list of 'users' to be
  353. * notified upon addition or removal of MTD devices. Causes the
  354. * 'remove' callback to be immediately invoked for each MTD device
  355. * currently present in the system.
  356. */
  357. int unregister_mtd_user (struct mtd_notifier *old)
  358. {
  359. int i;
  360. mutex_lock(&mtd_table_mutex);
  361. module_put(THIS_MODULE);
  362. for (i=0; i< MAX_MTD_DEVICES; i++)
  363. if (mtd_table[i])
  364. old->remove(mtd_table[i]);
  365. list_del(&old->list);
  366. mutex_unlock(&mtd_table_mutex);
  367. return 0;
  368. }
  369. /**
  370. * get_mtd_device - obtain a validated handle for an MTD device
  371. * @mtd: last known address of the required MTD device
  372. * @num: internal device number of the required MTD device
  373. *
  374. * Given a number and NULL address, return the num'th entry in the device
  375. * table, if any. Given an address and num == -1, search the device table
  376. * for a device with that address and return if it's still present. Given
  377. * both, return the num'th driver only if its address matches. Return
  378. * error code if not.
  379. */
  380. struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
  381. {
  382. struct mtd_info *ret = NULL;
  383. int i, err = -ENODEV;
  384. mutex_lock(&mtd_table_mutex);
  385. if (num == -1) {
  386. for (i=0; i< MAX_MTD_DEVICES; i++)
  387. if (mtd_table[i] == mtd)
  388. ret = mtd_table[i];
  389. } else if (num >= 0 && num < MAX_MTD_DEVICES) {
  390. ret = mtd_table[num];
  391. if (mtd && mtd != ret)
  392. ret = NULL;
  393. }
  394. if (!ret)
  395. goto out_unlock;
  396. if (!try_module_get(ret->owner))
  397. goto out_unlock;
  398. if (ret->get_device) {
  399. err = ret->get_device(ret);
  400. if (err)
  401. goto out_put;
  402. }
  403. ret->usecount++;
  404. mutex_unlock(&mtd_table_mutex);
  405. return ret;
  406. out_put:
  407. module_put(ret->owner);
  408. out_unlock:
  409. mutex_unlock(&mtd_table_mutex);
  410. return ERR_PTR(err);
  411. }
  412. /**
  413. * get_mtd_device_nm - obtain a validated handle for an MTD device by
  414. * device name
  415. * @name: MTD device name to open
  416. *
  417. * This function returns MTD device description structure in case of
  418. * success and an error code in case of failure.
  419. */
  420. struct mtd_info *get_mtd_device_nm(const char *name)
  421. {
  422. int i, err = -ENODEV;
  423. struct mtd_info *mtd = NULL;
  424. mutex_lock(&mtd_table_mutex);
  425. for (i = 0; i < MAX_MTD_DEVICES; i++) {
  426. if (mtd_table[i] && !strcmp(name, mtd_table[i]->name)) {
  427. mtd = mtd_table[i];
  428. break;
  429. }
  430. }
  431. if (!mtd)
  432. goto out_unlock;
  433. if (!try_module_get(mtd->owner))
  434. goto out_unlock;
  435. if (mtd->get_device) {
  436. err = mtd->get_device(mtd);
  437. if (err)
  438. goto out_put;
  439. }
  440. mtd->usecount++;
  441. mutex_unlock(&mtd_table_mutex);
  442. return mtd;
  443. out_put:
  444. module_put(mtd->owner);
  445. out_unlock:
  446. mutex_unlock(&mtd_table_mutex);
  447. return ERR_PTR(err);
  448. }
  449. void put_mtd_device(struct mtd_info *mtd)
  450. {
  451. int c;
  452. mutex_lock(&mtd_table_mutex);
  453. c = --mtd->usecount;
  454. if (mtd->put_device)
  455. mtd->put_device(mtd);
  456. mutex_unlock(&mtd_table_mutex);
  457. BUG_ON(c < 0);
  458. module_put(mtd->owner);
  459. }
  460. /* default_mtd_writev - default mtd writev method for MTD devices that
  461. * don't implement their own
  462. */
  463. int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
  464. unsigned long count, loff_t to, size_t *retlen)
  465. {
  466. unsigned long i;
  467. size_t totlen = 0, thislen;
  468. int ret = 0;
  469. if(!mtd->write) {
  470. ret = -EROFS;
  471. } else {
  472. for (i=0; i<count; i++) {
  473. if (!vecs[i].iov_len)
  474. continue;
  475. ret = mtd->write(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base);
  476. totlen += thislen;
  477. if (ret || thislen != vecs[i].iov_len)
  478. break;
  479. to += vecs[i].iov_len;
  480. }
  481. }
  482. if (retlen)
  483. *retlen = totlen;
  484. return ret;
  485. }
  486. EXPORT_SYMBOL_GPL(add_mtd_device);
  487. EXPORT_SYMBOL_GPL(del_mtd_device);
  488. EXPORT_SYMBOL_GPL(get_mtd_device);
  489. EXPORT_SYMBOL_GPL(get_mtd_device_nm);
  490. EXPORT_SYMBOL_GPL(put_mtd_device);
  491. EXPORT_SYMBOL_GPL(register_mtd_user);
  492. EXPORT_SYMBOL_GPL(unregister_mtd_user);
  493. EXPORT_SYMBOL_GPL(default_mtd_writev);
  494. #ifdef CONFIG_PROC_FS
  495. /*====================================================================*/
  496. /* Support for /proc/mtd */
  497. static struct proc_dir_entry *proc_mtd;
  498. static inline int mtd_proc_info (char *buf, int i)
  499. {
  500. struct mtd_info *this = mtd_table[i];
  501. if (!this)
  502. return 0;
  503. return sprintf(buf, "mtd%d: %8.8llx %8.8x \"%s\"\n", i,
  504. (unsigned long long)this->size,
  505. this->erasesize, this->name);
  506. }
  507. static int mtd_read_proc (char *page, char **start, off_t off, int count,
  508. int *eof, void *data_unused)
  509. {
  510. int len, l, i;
  511. off_t begin = 0;
  512. mutex_lock(&mtd_table_mutex);
  513. len = sprintf(page, "dev: size erasesize name\n");
  514. for (i=0; i< MAX_MTD_DEVICES; i++) {
  515. l = mtd_proc_info(page + len, i);
  516. len += l;
  517. if (len+begin > off+count)
  518. goto done;
  519. if (len+begin < off) {
  520. begin += len;
  521. len = 0;
  522. }
  523. }
  524. *eof = 1;
  525. done:
  526. mutex_unlock(&mtd_table_mutex);
  527. if (off >= len+begin)
  528. return 0;
  529. *start = page + (off-begin);
  530. return ((count < begin+len-off) ? count : begin+len-off);
  531. }
  532. #endif /* CONFIG_PROC_FS */
  533. /*====================================================================*/
  534. /* Init code */
  535. static int __init mtd_bdi_init(struct backing_dev_info *bdi, const char *name)
  536. {
  537. int ret;
  538. ret = bdi_init(bdi);
  539. if (!ret)
  540. ret = bdi_register(bdi, NULL, name);
  541. if (ret)
  542. bdi_destroy(bdi);
  543. return ret;
  544. }
  545. static int __init init_mtd(void)
  546. {
  547. int ret;
  548. ret = class_register(&mtd_class);
  549. if (ret)
  550. goto err_reg;
  551. ret = mtd_bdi_init(&mtd_bdi_unmappable, "mtd-unmap");
  552. if (ret)
  553. goto err_bdi1;
  554. ret = mtd_bdi_init(&mtd_bdi_ro_mappable, "mtd-romap");
  555. if (ret)
  556. goto err_bdi2;
  557. ret = mtd_bdi_init(&mtd_bdi_rw_mappable, "mtd-rwmap");
  558. if (ret)
  559. goto err_bdi3;
  560. #ifdef CONFIG_PROC_FS
  561. if ((proc_mtd = create_proc_entry( "mtd", 0, NULL )))
  562. proc_mtd->read_proc = mtd_read_proc;
  563. #endif /* CONFIG_PROC_FS */
  564. return 0;
  565. err_bdi3:
  566. bdi_destroy(&mtd_bdi_ro_mappable);
  567. err_bdi2:
  568. bdi_destroy(&mtd_bdi_unmappable);
  569. err_bdi1:
  570. class_unregister(&mtd_class);
  571. err_reg:
  572. pr_err("Error registering mtd class or bdi: %d\n", ret);
  573. return ret;
  574. }
  575. static void __exit cleanup_mtd(void)
  576. {
  577. #ifdef CONFIG_PROC_FS
  578. if (proc_mtd)
  579. remove_proc_entry( "mtd", NULL);
  580. #endif /* CONFIG_PROC_FS */
  581. class_unregister(&mtd_class);
  582. bdi_destroy(&mtd_bdi_unmappable);
  583. bdi_destroy(&mtd_bdi_ro_mappable);
  584. bdi_destroy(&mtd_bdi_rw_mappable);
  585. }
  586. module_init(init_mtd);
  587. module_exit(cleanup_mtd);
  588. MODULE_LICENSE("GPL");
  589. MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
  590. MODULE_DESCRIPTION("Core MTD registration and access routines");