1
2
3
4
5
6
7
8
9
10#include <linux/module.h>
11#include <linux/kernel.h>
12#include <linux/ptrace.h>
13#include <linux/seq_file.h>
14#include <linux/string.h>
15#include <linux/timer.h>
16#include <linux/major.h>
17#include <linux/fs.h>
18#include <linux/err.h>
19#include <linux/ioctl.h>
20#include <linux/init.h>
21#include <linux/of.h>
22#include <linux/proc_fs.h>
23#include <linux/idr.h>
24#include <linux/backing-dev.h>
25#include <linux/gfp.h>
26#include <linux/slab.h>
27#include <linux/reboot.h>
28#include <linux/leds.h>
29#include <linux/debugfs.h>
30#include <linux/nvmem-provider.h>
31
32#include <linux/mtd/mtd.h>
33#include <linux/mtd/partitions.h>
34
35#include "mtdcore.h"
36
37struct backing_dev_info *mtd_bdi;
38
39#ifdef CONFIG_PM_SLEEP
40
41static int mtd_cls_suspend(struct device *dev)
42{
43 struct mtd_info *mtd = dev_get_drvdata(dev);
44
45 return mtd ? mtd_suspend(mtd) : 0;
46}
47
48static int mtd_cls_resume(struct device *dev)
49{
50 struct mtd_info *mtd = dev_get_drvdata(dev);
51
52 if (mtd)
53 mtd_resume(mtd);
54 return 0;
55}
56
57static SIMPLE_DEV_PM_OPS(mtd_cls_pm_ops, mtd_cls_suspend, mtd_cls_resume);
58#define MTD_CLS_PM_OPS (&mtd_cls_pm_ops)
59#else
60#define MTD_CLS_PM_OPS NULL
61#endif
62
63static struct class mtd_class = {
64 .name = "mtd",
65 .owner = THIS_MODULE,
66 .pm = MTD_CLS_PM_OPS,
67};
68
69static DEFINE_IDR(mtd_idr);
70
71
72
73DEFINE_MUTEX(mtd_table_mutex);
74EXPORT_SYMBOL_GPL(mtd_table_mutex);
75
76struct mtd_info *__mtd_next_device(int i)
77{
78 return idr_get_next(&mtd_idr, &i);
79}
80EXPORT_SYMBOL_GPL(__mtd_next_device);
81
82static LIST_HEAD(mtd_notifiers);
83
84
85#define MTD_DEVT(index) MKDEV(MTD_CHAR_MAJOR, (index)*2)
86
87
88
89
90static void mtd_release(struct device *dev)
91{
92 struct mtd_info *mtd = dev_get_drvdata(dev);
93 dev_t index = MTD_DEVT(mtd->index);
94
95
96 device_destroy(&mtd_class, index + 1);
97}
98
99static ssize_t mtd_type_show(struct device *dev,
100 struct device_attribute *attr, char *buf)
101{
102 struct mtd_info *mtd = dev_get_drvdata(dev);
103 char *type;
104
105 switch (mtd->type) {
106 case MTD_ABSENT:
107 type = "absent";
108 break;
109 case MTD_RAM:
110 type = "ram";
111 break;
112 case MTD_ROM:
113 type = "rom";
114 break;
115 case MTD_NORFLASH:
116 type = "nor";
117 break;
118 case MTD_NANDFLASH:
119 type = "nand";
120 break;
121 case MTD_DATAFLASH:
122 type = "dataflash";
123 break;
124 case MTD_UBIVOLUME:
125 type = "ubi";
126 break;
127 case MTD_MLCNANDFLASH:
128 type = "mlc-nand";
129 break;
130 default:
131 type = "unknown";
132 }
133
134 return snprintf(buf, PAGE_SIZE, "%s\n", type);
135}
136static DEVICE_ATTR(type, S_IRUGO, mtd_type_show, NULL);
137
138static ssize_t mtd_flags_show(struct device *dev,
139 struct device_attribute *attr, char *buf)
140{
141 struct mtd_info *mtd = dev_get_drvdata(dev);
142
143 return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags);
144}
145static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL);
146
147static ssize_t mtd_size_show(struct device *dev,
148 struct device_attribute *attr, char *buf)
149{
150 struct mtd_info *mtd = dev_get_drvdata(dev);
151
152 return snprintf(buf, PAGE_SIZE, "%llu\n",
153 (unsigned long long)mtd->size);
154}
155static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL);
156
157static ssize_t mtd_erasesize_show(struct device *dev,
158 struct device_attribute *attr, char *buf)
159{
160 struct mtd_info *mtd = dev_get_drvdata(dev);
161
162 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize);
163}
164static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL);
165
166static ssize_t mtd_writesize_show(struct device *dev,
167 struct device_attribute *attr, char *buf)
168{
169 struct mtd_info *mtd = dev_get_drvdata(dev);
170
171 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize);
172}
173static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL);
174
175static ssize_t mtd_subpagesize_show(struct device *dev,
176 struct device_attribute *attr, char *buf)
177{
178 struct mtd_info *mtd = dev_get_drvdata(dev);
179 unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft;
180
181 return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize);
182}
183static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL);
184
185static ssize_t mtd_oobsize_show(struct device *dev,
186 struct device_attribute *attr, char *buf)
187{
188 struct mtd_info *mtd = dev_get_drvdata(dev);
189
190 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->oobsize);
191}
192static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL);
193
194static ssize_t mtd_oobavail_show(struct device *dev,
195 struct device_attribute *attr, char *buf)
196{
197 struct mtd_info *mtd = dev_get_drvdata(dev);
198
199 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->oobavail);
200}
201static DEVICE_ATTR(oobavail, S_IRUGO, mtd_oobavail_show, NULL);
202
203static ssize_t mtd_numeraseregions_show(struct device *dev,
204 struct device_attribute *attr, char *buf)
205{
206 struct mtd_info *mtd = dev_get_drvdata(dev);
207
208 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions);
209}
210static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show,
211 NULL);
212
213static ssize_t mtd_name_show(struct device *dev,
214 struct device_attribute *attr, char *buf)
215{
216 struct mtd_info *mtd = dev_get_drvdata(dev);
217
218 return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name);
219}
220static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL);
221
222static ssize_t mtd_ecc_strength_show(struct device *dev,
223 struct device_attribute *attr, char *buf)
224{
225 struct mtd_info *mtd = dev_get_drvdata(dev);
226
227 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->ecc_strength);
228}
229static DEVICE_ATTR(ecc_strength, S_IRUGO, mtd_ecc_strength_show, NULL);
230
231static ssize_t mtd_bitflip_threshold_show(struct device *dev,
232 struct device_attribute *attr,
233 char *buf)
234{
235 struct mtd_info *mtd = dev_get_drvdata(dev);
236
237 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->bitflip_threshold);
238}
239
240static ssize_t mtd_bitflip_threshold_store(struct device *dev,
241 struct device_attribute *attr,
242 const char *buf, size_t count)
243{
244 struct mtd_info *mtd = dev_get_drvdata(dev);
245 unsigned int bitflip_threshold;
246 int retval;
247
248 retval = kstrtouint(buf, 0, &bitflip_threshold);
249 if (retval)
250 return retval;
251
252 mtd->bitflip_threshold = bitflip_threshold;
253 return count;
254}
255static DEVICE_ATTR(bitflip_threshold, S_IRUGO | S_IWUSR,
256 mtd_bitflip_threshold_show,
257 mtd_bitflip_threshold_store);
258
259static ssize_t mtd_ecc_step_size_show(struct device *dev,
260 struct device_attribute *attr, char *buf)
261{
262 struct mtd_info *mtd = dev_get_drvdata(dev);
263
264 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->ecc_step_size);
265
266}
267static DEVICE_ATTR(ecc_step_size, S_IRUGO, mtd_ecc_step_size_show, NULL);
268
269static ssize_t mtd_ecc_stats_corrected_show(struct device *dev,
270 struct device_attribute *attr, char *buf)
271{
272 struct mtd_info *mtd = dev_get_drvdata(dev);
273 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
274
275 return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->corrected);
276}
277static DEVICE_ATTR(corrected_bits, S_IRUGO,
278 mtd_ecc_stats_corrected_show, NULL);
279
280static ssize_t mtd_ecc_stats_errors_show(struct device *dev,
281 struct device_attribute *attr, char *buf)
282{
283 struct mtd_info *mtd = dev_get_drvdata(dev);
284 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
285
286 return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->failed);
287}
288static DEVICE_ATTR(ecc_failures, S_IRUGO, mtd_ecc_stats_errors_show, NULL);
289
290static ssize_t mtd_badblocks_show(struct device *dev,
291 struct device_attribute *attr, char *buf)
292{
293 struct mtd_info *mtd = dev_get_drvdata(dev);
294 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
295
296 return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->badblocks);
297}
298static DEVICE_ATTR(bad_blocks, S_IRUGO, mtd_badblocks_show, NULL);
299
300static ssize_t mtd_bbtblocks_show(struct device *dev,
301 struct device_attribute *attr, char *buf)
302{
303 struct mtd_info *mtd = dev_get_drvdata(dev);
304 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats;
305
306 return snprintf(buf, PAGE_SIZE, "%u\n", ecc_stats->bbtblocks);
307}
308static DEVICE_ATTR(bbt_blocks, S_IRUGO, mtd_bbtblocks_show, NULL);
309
310static struct attribute *mtd_attrs[] = {
311 &dev_attr_type.attr,
312 &dev_attr_flags.attr,
313 &dev_attr_size.attr,
314 &dev_attr_erasesize.attr,
315 &dev_attr_writesize.attr,
316 &dev_attr_subpagesize.attr,
317 &dev_attr_oobsize.attr,
318 &dev_attr_oobavail.attr,
319 &dev_attr_numeraseregions.attr,
320 &dev_attr_name.attr,
321 &dev_attr_ecc_strength.attr,
322 &dev_attr_ecc_step_size.attr,
323 &dev_attr_corrected_bits.attr,
324 &dev_attr_ecc_failures.attr,
325 &dev_attr_bad_blocks.attr,
326 &dev_attr_bbt_blocks.attr,
327 &dev_attr_bitflip_threshold.attr,
328 NULL,
329};
330ATTRIBUTE_GROUPS(mtd);
331
332static const struct device_type mtd_devtype = {
333 .name = "mtd",
334 .groups = mtd_groups,
335 .release = mtd_release,
336};
337
338#ifndef CONFIG_MMU
339unsigned mtd_mmap_capabilities(struct mtd_info *mtd)
340{
341 switch (mtd->type) {
342 case MTD_RAM:
343 return NOMMU_MAP_COPY | NOMMU_MAP_DIRECT | NOMMU_MAP_EXEC |
344 NOMMU_MAP_READ | NOMMU_MAP_WRITE;
345 case MTD_ROM:
346 return NOMMU_MAP_COPY | NOMMU_MAP_DIRECT | NOMMU_MAP_EXEC |
347 NOMMU_MAP_READ;
348 default:
349 return NOMMU_MAP_COPY;
350 }
351}
352EXPORT_SYMBOL_GPL(mtd_mmap_capabilities);
353#endif
354
355static int mtd_reboot_notifier(struct notifier_block *n, unsigned long state,
356 void *cmd)
357{
358 struct mtd_info *mtd;
359
360 mtd = container_of(n, struct mtd_info, reboot_notifier);
361 mtd->_reboot(mtd);
362
363 return NOTIFY_DONE;
364}
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392int mtd_wunit_to_pairing_info(struct mtd_info *mtd, int wunit,
393 struct mtd_pairing_info *info)
394{
395 int npairs = mtd_wunit_per_eb(mtd) / mtd_pairing_groups(mtd);
396
397 if (wunit < 0 || wunit >= npairs)
398 return -EINVAL;
399
400 if (mtd->pairing && mtd->pairing->get_info)
401 return mtd->pairing->get_info(mtd, wunit, info);
402
403 info->group = 0;
404 info->pair = wunit;
405
406 return 0;
407}
408EXPORT_SYMBOL_GPL(mtd_wunit_to_pairing_info);
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434int mtd_pairing_info_to_wunit(struct mtd_info *mtd,
435 const struct mtd_pairing_info *info)
436{
437 int ngroups = mtd_pairing_groups(mtd);
438 int npairs = mtd_wunit_per_eb(mtd) / ngroups;
439
440 if (!info || info->pair < 0 || info->pair >= npairs ||
441 info->group < 0 || info->group >= ngroups)
442 return -EINVAL;
443
444 if (mtd->pairing && mtd->pairing->get_wunit)
445 return mtd->pairing->get_wunit(mtd, info);
446
447 return info->pair;
448}
449EXPORT_SYMBOL_GPL(mtd_pairing_info_to_wunit);
450
451
452
453
454
455
456
457
458
459
460
461int mtd_pairing_groups(struct mtd_info *mtd)
462{
463 if (!mtd->pairing || !mtd->pairing->ngroups)
464 return 1;
465
466 return mtd->pairing->ngroups;
467}
468EXPORT_SYMBOL_GPL(mtd_pairing_groups);
469
470static int mtd_nvmem_reg_read(void *priv, unsigned int offset,
471 void *val, size_t bytes)
472{
473 struct mtd_info *mtd = priv;
474 size_t retlen;
475 int err;
476
477 err = mtd_read(mtd, offset, bytes, &retlen, val);
478 if (err && err != -EUCLEAN)
479 return err;
480
481 return retlen == bytes ? 0 : -EIO;
482}
483
484static int mtd_nvmem_add(struct mtd_info *mtd)
485{
486 struct nvmem_config config = {};
487
488 config.id = -1;
489 config.dev = &mtd->dev;
490 config.name = mtd->name;
491 config.owner = THIS_MODULE;
492 config.reg_read = mtd_nvmem_reg_read;
493 config.size = mtd->size;
494 config.word_size = 1;
495 config.stride = 1;
496 config.read_only = true;
497 config.root_only = true;
498 config.no_of_node = true;
499 config.priv = mtd;
500
501 mtd->nvmem = nvmem_register(&config);
502 if (IS_ERR(mtd->nvmem)) {
503
504 if (PTR_ERR(mtd->nvmem) == -EOPNOTSUPP) {
505 mtd->nvmem = NULL;
506 } else {
507 dev_err(&mtd->dev, "Failed to register NVMEM device\n");
508 return PTR_ERR(mtd->nvmem);
509 }
510 }
511
512 return 0;
513}
514
515static struct dentry *dfs_dir_mtd;
516
517
518
519
520
521
522
523
524
525
526int add_mtd_device(struct mtd_info *mtd)
527{
528 struct mtd_notifier *not;
529 int i, error;
530
531
532
533
534
535
536 if (WARN_ONCE(mtd->dev.type, "MTD already registered\n"))
537 return -EEXIST;
538
539 BUG_ON(mtd->writesize == 0);
540
541
542
543
544
545 if (WARN_ON((mtd->_write && mtd->_write_oob) ||
546 (mtd->_read && mtd->_read_oob)))
547 return -EINVAL;
548
549 if (WARN_ON((!mtd->erasesize || !mtd->_erase) &&
550 !(mtd->flags & MTD_NO_ERASE)))
551 return -EINVAL;
552
553 mutex_lock(&mtd_table_mutex);
554
555 i = idr_alloc(&mtd_idr, mtd, 0, 0, GFP_KERNEL);
556 if (i < 0) {
557 error = i;
558 goto fail_locked;
559 }
560
561 mtd->index = i;
562 mtd->usecount = 0;
563
564
565 if (mtd->bitflip_threshold == 0)
566 mtd->bitflip_threshold = mtd->ecc_strength;
567
568 if (is_power_of_2(mtd->erasesize))
569 mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
570 else
571 mtd->erasesize_shift = 0;
572
573 if (is_power_of_2(mtd->writesize))
574 mtd->writesize_shift = ffs(mtd->writesize) - 1;
575 else
576 mtd->writesize_shift = 0;
577
578 mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
579 mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
580
581
582 if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) {
583 error = mtd_unlock(mtd, 0, mtd->size);
584 if (error && error != -EOPNOTSUPP)
585 printk(KERN_WARNING
586 "%s: unlock failed, writes may not work\n",
587 mtd->name);
588
589 error = 0;
590 }
591
592
593
594
595 mtd->dev.type = &mtd_devtype;
596 mtd->dev.class = &mtd_class;
597 mtd->dev.devt = MTD_DEVT(i);
598 dev_set_name(&mtd->dev, "mtd%d", i);
599 dev_set_drvdata(&mtd->dev, mtd);
600 of_node_get(mtd_get_of_node(mtd));
601 error = device_register(&mtd->dev);
602 if (error)
603 goto fail_added;
604
605
606 error = mtd_nvmem_add(mtd);
607 if (error)
608 goto fail_nvmem_add;
609
610 if (!IS_ERR_OR_NULL(dfs_dir_mtd)) {
611 mtd->dbg.dfs_dir = debugfs_create_dir(dev_name(&mtd->dev), dfs_dir_mtd);
612 if (IS_ERR_OR_NULL(mtd->dbg.dfs_dir)) {
613 pr_debug("mtd device %s won't show data in debugfs\n",
614 dev_name(&mtd->dev));
615 }
616 }
617
618 device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL,
619 "mtd%dro", i);
620
621 pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name);
622
623
624 list_for_each_entry(not, &mtd_notifiers, list)
625 not->add(mtd);
626
627 mutex_unlock(&mtd_table_mutex);
628
629
630
631
632 __module_get(THIS_MODULE);
633 return 0;
634
635fail_nvmem_add:
636 device_unregister(&mtd->dev);
637fail_added:
638 of_node_put(mtd_get_of_node(mtd));
639 idr_remove(&mtd_idr, i);
640fail_locked:
641 mutex_unlock(&mtd_table_mutex);
642 return error;
643}
644
645
646
647
648
649
650
651
652
653
654
655int del_mtd_device(struct mtd_info *mtd)
656{
657 int ret;
658 struct mtd_notifier *not;
659
660 mutex_lock(&mtd_table_mutex);
661
662 debugfs_remove_recursive(mtd->dbg.dfs_dir);
663
664 if (idr_find(&mtd_idr, mtd->index) != mtd) {
665 ret = -ENODEV;
666 goto out_error;
667 }
668
669
670
671 list_for_each_entry(not, &mtd_notifiers, list)
672 not->remove(mtd);
673
674 if (mtd->usecount) {
675 printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n",
676 mtd->index, mtd->name, mtd->usecount);
677 ret = -EBUSY;
678 } else {
679
680 if (mtd->nvmem)
681 nvmem_unregister(mtd->nvmem);
682
683 device_unregister(&mtd->dev);
684
685 idr_remove(&mtd_idr, mtd->index);
686 of_node_put(mtd_get_of_node(mtd));
687
688 module_put(THIS_MODULE);
689 ret = 0;
690 }
691
692out_error:
693 mutex_unlock(&mtd_table_mutex);
694 return ret;
695}
696
697
698
699
700
701static void mtd_set_dev_defaults(struct mtd_info *mtd)
702{
703 if (mtd->dev.parent) {
704 if (!mtd->owner && mtd->dev.parent->driver)
705 mtd->owner = mtd->dev.parent->driver->owner;
706 if (!mtd->name)
707 mtd->name = dev_name(mtd->dev.parent);
708 } else {
709 pr_debug("mtd device won't show a device symlink in sysfs\n");
710 }
711
712 mtd->orig_flags = mtd->flags;
713}
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
744 struct mtd_part_parser_data *parser_data,
745 const struct mtd_partition *parts,
746 int nr_parts)
747{
748 int ret;
749
750 mtd_set_dev_defaults(mtd);
751
752 if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER)) {
753 ret = add_mtd_device(mtd);
754 if (ret)
755 return ret;
756 }
757
758
759 ret = parse_mtd_partitions(mtd, types, parser_data);
760 if (ret > 0)
761 ret = 0;
762 else if (nr_parts)
763 ret = add_mtd_partitions(mtd, parts, nr_parts);
764 else if (!device_is_registered(&mtd->dev))
765 ret = add_mtd_device(mtd);
766 else
767 ret = 0;
768
769 if (ret)
770 goto out;
771
772
773
774
775
776
777
778
779
780 WARN_ONCE(mtd->_reboot && mtd->reboot_notifier.notifier_call,
781 "MTD already registered\n");
782 if (mtd->_reboot && !mtd->reboot_notifier.notifier_call) {
783 mtd->reboot_notifier.notifier_call = mtd_reboot_notifier;
784 register_reboot_notifier(&mtd->reboot_notifier);
785 }
786
787out:
788 if (ret && device_is_registered(&mtd->dev))
789 del_mtd_device(mtd);
790
791 return ret;
792}
793EXPORT_SYMBOL_GPL(mtd_device_parse_register);
794
795
796
797
798
799
800
801int mtd_device_unregister(struct mtd_info *master)
802{
803 int err;
804
805 if (master->_reboot)
806 unregister_reboot_notifier(&master->reboot_notifier);
807
808 err = del_mtd_partitions(master);
809 if (err)
810 return err;
811
812 if (!device_is_registered(&master->dev))
813 return 0;
814
815 return del_mtd_device(master);
816}
817EXPORT_SYMBOL_GPL(mtd_device_unregister);
818
819
820
821
822
823
824
825
826
827void register_mtd_user (struct mtd_notifier *new)
828{
829 struct mtd_info *mtd;
830
831 mutex_lock(&mtd_table_mutex);
832
833 list_add(&new->list, &mtd_notifiers);
834
835 __module_get(THIS_MODULE);
836
837 mtd_for_each_device(mtd)
838 new->add(mtd);
839
840 mutex_unlock(&mtd_table_mutex);
841}
842EXPORT_SYMBOL_GPL(register_mtd_user);
843
844
845
846
847
848
849
850
851
852
853int unregister_mtd_user (struct mtd_notifier *old)
854{
855 struct mtd_info *mtd;
856
857 mutex_lock(&mtd_table_mutex);
858
859 module_put(THIS_MODULE);
860
861 mtd_for_each_device(mtd)
862 old->remove(mtd);
863
864 list_del(&old->list);
865 mutex_unlock(&mtd_table_mutex);
866 return 0;
867}
868EXPORT_SYMBOL_GPL(unregister_mtd_user);
869
870
871
872
873
874
875
876
877
878
879
880
881struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
882{
883 struct mtd_info *ret = NULL, *other;
884 int err = -ENODEV;
885
886 mutex_lock(&mtd_table_mutex);
887
888 if (num == -1) {
889 mtd_for_each_device(other) {
890 if (other == mtd) {
891 ret = mtd;
892 break;
893 }
894 }
895 } else if (num >= 0) {
896 ret = idr_find(&mtd_idr, num);
897 if (mtd && mtd != ret)
898 ret = NULL;
899 }
900
901 if (!ret) {
902 ret = ERR_PTR(err);
903 goto out;
904 }
905
906 err = __get_mtd_device(ret);
907 if (err)
908 ret = ERR_PTR(err);
909out:
910 mutex_unlock(&mtd_table_mutex);
911 return ret;
912}
913EXPORT_SYMBOL_GPL(get_mtd_device);
914
915
916int __get_mtd_device(struct mtd_info *mtd)
917{
918 int err;
919
920 if (!try_module_get(mtd->owner))
921 return -ENODEV;
922
923 if (mtd->_get_device) {
924 err = mtd->_get_device(mtd);
925
926 if (err) {
927 module_put(mtd->owner);
928 return err;
929 }
930 }
931 mtd->usecount++;
932 return 0;
933}
934EXPORT_SYMBOL_GPL(__get_mtd_device);
935
936
937
938
939
940
941
942
943
944struct mtd_info *get_mtd_device_nm(const char *name)
945{
946 int err = -ENODEV;
947 struct mtd_info *mtd = NULL, *other;
948
949 mutex_lock(&mtd_table_mutex);
950
951 mtd_for_each_device(other) {
952 if (!strcmp(name, other->name)) {
953 mtd = other;
954 break;
955 }
956 }
957
958 if (!mtd)
959 goto out_unlock;
960
961 err = __get_mtd_device(mtd);
962 if (err)
963 goto out_unlock;
964
965 mutex_unlock(&mtd_table_mutex);
966 return mtd;
967
968out_unlock:
969 mutex_unlock(&mtd_table_mutex);
970 return ERR_PTR(err);
971}
972EXPORT_SYMBOL_GPL(get_mtd_device_nm);
973
974void put_mtd_device(struct mtd_info *mtd)
975{
976 mutex_lock(&mtd_table_mutex);
977 __put_mtd_device(mtd);
978 mutex_unlock(&mtd_table_mutex);
979
980}
981EXPORT_SYMBOL_GPL(put_mtd_device);
982
983void __put_mtd_device(struct mtd_info *mtd)
984{
985 --mtd->usecount;
986 BUG_ON(mtd->usecount < 0);
987
988 if (mtd->_put_device)
989 mtd->_put_device(mtd);
990
991 module_put(mtd->owner);
992}
993EXPORT_SYMBOL_GPL(__put_mtd_device);
994
995
996
997
998
999
1000int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
1001{
1002 instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
1003
1004 if (!mtd->erasesize || !mtd->_erase)
1005 return -ENOTSUPP;
1006
1007 if (instr->addr >= mtd->size || instr->len > mtd->size - instr->addr)
1008 return -EINVAL;
1009 if (!(mtd->flags & MTD_WRITEABLE))
1010 return -EROFS;
1011
1012 if (!instr->len)
1013 return 0;
1014
1015 ledtrig_mtd_activity();
1016 return mtd->_erase(mtd, instr);
1017}
1018EXPORT_SYMBOL_GPL(mtd_erase);
1019
1020
1021
1022
1023int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
1024 void **virt, resource_size_t *phys)
1025{
1026 *retlen = 0;
1027 *virt = NULL;
1028 if (phys)
1029 *phys = 0;
1030 if (!mtd->_point)
1031 return -EOPNOTSUPP;
1032 if (from < 0 || from >= mtd->size || len > mtd->size - from)
1033 return -EINVAL;
1034 if (!len)
1035 return 0;
1036 return mtd->_point(mtd, from, len, retlen, virt, phys);
1037}
1038EXPORT_SYMBOL_GPL(mtd_point);
1039
1040
1041int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
1042{
1043 if (!mtd->_unpoint)
1044 return -EOPNOTSUPP;
1045 if (from < 0 || from >= mtd->size || len > mtd->size - from)
1046 return -EINVAL;
1047 if (!len)
1048 return 0;
1049 return mtd->_unpoint(mtd, from, len);
1050}
1051EXPORT_SYMBOL_GPL(mtd_unpoint);
1052
1053
1054
1055
1056
1057
1058unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
1059 unsigned long offset, unsigned long flags)
1060{
1061 size_t retlen;
1062 void *virt;
1063 int ret;
1064
1065 ret = mtd_point(mtd, offset, len, &retlen, &virt, NULL);
1066 if (ret)
1067 return ret;
1068 if (retlen != len) {
1069 mtd_unpoint(mtd, offset, retlen);
1070 return -ENOSYS;
1071 }
1072 return (unsigned long)virt;
1073}
1074EXPORT_SYMBOL_GPL(mtd_get_unmapped_area);
1075
1076int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
1077 u_char *buf)
1078{
1079 struct mtd_oob_ops ops = {
1080 .len = len,
1081 .datbuf = buf,
1082 };
1083 int ret;
1084
1085 ret = mtd_read_oob(mtd, from, &ops);
1086 *retlen = ops.retlen;
1087
1088 return ret;
1089}
1090EXPORT_SYMBOL_GPL(mtd_read);
1091
1092int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
1093 const u_char *buf)
1094{
1095 struct mtd_oob_ops ops = {
1096 .len = len,
1097 .datbuf = (u8 *)buf,
1098 };
1099 int ret;
1100
1101 ret = mtd_write_oob(mtd, to, &ops);
1102 *retlen = ops.retlen;
1103
1104 return ret;
1105}
1106EXPORT_SYMBOL_GPL(mtd_write);
1107
1108
1109
1110
1111
1112
1113
1114
1115int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
1116 const u_char *buf)
1117{
1118 *retlen = 0;
1119 if (!mtd->_panic_write)
1120 return -EOPNOTSUPP;
1121 if (to < 0 || to >= mtd->size || len > mtd->size - to)
1122 return -EINVAL;
1123 if (!(mtd->flags & MTD_WRITEABLE))
1124 return -EROFS;
1125 if (!len)
1126 return 0;
1127 if (!mtd->oops_panic_write)
1128 mtd->oops_panic_write = true;
1129
1130 return mtd->_panic_write(mtd, to, len, retlen, buf);
1131}
1132EXPORT_SYMBOL_GPL(mtd_panic_write);
1133
1134static int mtd_check_oob_ops(struct mtd_info *mtd, loff_t offs,
1135 struct mtd_oob_ops *ops)
1136{
1137
1138
1139
1140
1141
1142 if (!ops->datbuf)
1143 ops->len = 0;
1144
1145 if (!ops->oobbuf)
1146 ops->ooblen = 0;
1147
1148 if (offs < 0 || offs + ops->len > mtd->size)
1149 return -EINVAL;
1150
1151 if (ops->ooblen) {
1152 size_t maxooblen;
1153
1154 if (ops->ooboffs >= mtd_oobavail(mtd, ops))
1155 return -EINVAL;
1156
1157 maxooblen = ((size_t)(mtd_div_by_ws(mtd->size, mtd) -
1158 mtd_div_by_ws(offs, mtd)) *
1159 mtd_oobavail(mtd, ops)) - ops->ooboffs;
1160 if (ops->ooblen > maxooblen)
1161 return -EINVAL;
1162 }
1163
1164 return 0;
1165}
1166
1167int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
1168{
1169 int ret_code;
1170 ops->retlen = ops->oobretlen = 0;
1171
1172 ret_code = mtd_check_oob_ops(mtd, from, ops);
1173 if (ret_code)
1174 return ret_code;
1175
1176 ledtrig_mtd_activity();
1177
1178
1179 if (!mtd->_read_oob && (!mtd->_read || ops->oobbuf))
1180 return -EOPNOTSUPP;
1181
1182 if (mtd->_read_oob)
1183 ret_code = mtd->_read_oob(mtd, from, ops);
1184 else
1185 ret_code = mtd->_read(mtd, from, ops->len, &ops->retlen,
1186 ops->datbuf);
1187
1188
1189
1190
1191
1192
1193
1194 if (unlikely(ret_code < 0))
1195 return ret_code;
1196 if (mtd->ecc_strength == 0)
1197 return 0;
1198 return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0;
1199}
1200EXPORT_SYMBOL_GPL(mtd_read_oob);
1201
1202int mtd_write_oob(struct mtd_info *mtd, loff_t to,
1203 struct mtd_oob_ops *ops)
1204{
1205 int ret;
1206
1207 ops->retlen = ops->oobretlen = 0;
1208
1209 if (!(mtd->flags & MTD_WRITEABLE))
1210 return -EROFS;
1211
1212 ret = mtd_check_oob_ops(mtd, to, ops);
1213 if (ret)
1214 return ret;
1215
1216 ledtrig_mtd_activity();
1217
1218
1219 if (!mtd->_write_oob && (!mtd->_write || ops->oobbuf))
1220 return -EOPNOTSUPP;
1221
1222 if (mtd->_write_oob)
1223 return mtd->_write_oob(mtd, to, ops);
1224 else
1225 return mtd->_write(mtd, to, ops->len, &ops->retlen,
1226 ops->datbuf);
1227}
1228EXPORT_SYMBOL_GPL(mtd_write_oob);
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
1247 struct mtd_oob_region *oobecc)
1248{
1249 memset(oobecc, 0, sizeof(*oobecc));
1250
1251 if (!mtd || section < 0)
1252 return -EINVAL;
1253
1254 if (!mtd->ooblayout || !mtd->ooblayout->ecc)
1255 return -ENOTSUPP;
1256
1257 return mtd->ooblayout->ecc(mtd, section, oobecc);
1258}
1259EXPORT_SYMBOL_GPL(mtd_ooblayout_ecc);
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278int mtd_ooblayout_free(struct mtd_info *mtd, int section,
1279 struct mtd_oob_region *oobfree)
1280{
1281 memset(oobfree, 0, sizeof(*oobfree));
1282
1283 if (!mtd || section < 0)
1284 return -EINVAL;
1285
1286 if (!mtd->ooblayout || !mtd->ooblayout->free)
1287 return -ENOTSUPP;
1288
1289 return mtd->ooblayout->free(mtd, section, oobfree);
1290}
1291EXPORT_SYMBOL_GPL(mtd_ooblayout_free);
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310static int mtd_ooblayout_find_region(struct mtd_info *mtd, int byte,
1311 int *sectionp, struct mtd_oob_region *oobregion,
1312 int (*iter)(struct mtd_info *,
1313 int section,
1314 struct mtd_oob_region *oobregion))
1315{
1316 int pos = 0, ret, section = 0;
1317
1318 memset(oobregion, 0, sizeof(*oobregion));
1319
1320 while (1) {
1321 ret = iter(mtd, section, oobregion);
1322 if (ret)
1323 return ret;
1324
1325 if (pos + oobregion->length > byte)
1326 break;
1327
1328 pos += oobregion->length;
1329 section++;
1330 }
1331
1332
1333
1334
1335
1336 oobregion->offset += byte - pos;
1337 oobregion->length -= byte - pos;
1338 *sectionp = section;
1339
1340 return 0;
1341}
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
1357 int *section,
1358 struct mtd_oob_region *oobregion)
1359{
1360 return mtd_ooblayout_find_region(mtd, eccbyte, section, oobregion,
1361 mtd_ooblayout_ecc);
1362}
1363EXPORT_SYMBOL_GPL(mtd_ooblayout_find_eccregion);
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379static int mtd_ooblayout_get_bytes(struct mtd_info *mtd, u8 *buf,
1380 const u8 *oobbuf, int start, int nbytes,
1381 int (*iter)(struct mtd_info *,
1382 int section,
1383 struct mtd_oob_region *oobregion))
1384{
1385 struct mtd_oob_region oobregion;
1386 int section, ret;
1387
1388 ret = mtd_ooblayout_find_region(mtd, start, §ion,
1389 &oobregion, iter);
1390
1391 while (!ret) {
1392 int cnt;
1393
1394 cnt = min_t(int, nbytes, oobregion.length);
1395 memcpy(buf, oobbuf + oobregion.offset, cnt);
1396 buf += cnt;
1397 nbytes -= cnt;
1398
1399 if (!nbytes)
1400 break;
1401
1402 ret = iter(mtd, ++section, &oobregion);
1403 }
1404
1405 return ret;
1406}
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422static int mtd_ooblayout_set_bytes(struct mtd_info *mtd, const u8 *buf,
1423 u8 *oobbuf, int start, int nbytes,
1424 int (*iter)(struct mtd_info *,
1425 int section,
1426 struct mtd_oob_region *oobregion))
1427{
1428 struct mtd_oob_region oobregion;
1429 int section, ret;
1430
1431 ret = mtd_ooblayout_find_region(mtd, start, §ion,
1432 &oobregion, iter);
1433
1434 while (!ret) {
1435 int cnt;
1436
1437 cnt = min_t(int, nbytes, oobregion.length);
1438 memcpy(oobbuf + oobregion.offset, buf, cnt);
1439 buf += cnt;
1440 nbytes -= cnt;
1441
1442 if (!nbytes)
1443 break;
1444
1445 ret = iter(mtd, ++section, &oobregion);
1446 }
1447
1448 return ret;
1449}
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460static int mtd_ooblayout_count_bytes(struct mtd_info *mtd,
1461 int (*iter)(struct mtd_info *,
1462 int section,
1463 struct mtd_oob_region *oobregion))
1464{
1465 struct mtd_oob_region oobregion;
1466 int section = 0, ret, nbytes = 0;
1467
1468 while (1) {
1469 ret = iter(mtd, section++, &oobregion);
1470 if (ret) {
1471 if (ret == -ERANGE)
1472 ret = nbytes;
1473 break;
1474 }
1475
1476 nbytes += oobregion.length;
1477 }
1478
1479 return ret;
1480}
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf,
1495 const u8 *oobbuf, int start, int nbytes)
1496{
1497 return mtd_ooblayout_get_bytes(mtd, eccbuf, oobbuf, start, nbytes,
1498 mtd_ooblayout_ecc);
1499}
1500EXPORT_SYMBOL_GPL(mtd_ooblayout_get_eccbytes);
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf,
1515 u8 *oobbuf, int start, int nbytes)
1516{
1517 return mtd_ooblayout_set_bytes(mtd, eccbuf, oobbuf, start, nbytes,
1518 mtd_ooblayout_ecc);
1519}
1520EXPORT_SYMBOL_GPL(mtd_ooblayout_set_eccbytes);
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf,
1535 const u8 *oobbuf, int start, int nbytes)
1536{
1537 return mtd_ooblayout_get_bytes(mtd, databuf, oobbuf, start, nbytes,
1538 mtd_ooblayout_free);
1539}
1540EXPORT_SYMBOL_GPL(mtd_ooblayout_get_databytes);
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf,
1555 u8 *oobbuf, int start, int nbytes)
1556{
1557 return mtd_ooblayout_set_bytes(mtd, databuf, oobbuf, start, nbytes,
1558 mtd_ooblayout_free);
1559}
1560EXPORT_SYMBOL_GPL(mtd_ooblayout_set_databytes);
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570int mtd_ooblayout_count_freebytes(struct mtd_info *mtd)
1571{
1572 return mtd_ooblayout_count_bytes(mtd, mtd_ooblayout_free);
1573}
1574EXPORT_SYMBOL_GPL(mtd_ooblayout_count_freebytes);
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd)
1585{
1586 return mtd_ooblayout_count_bytes(mtd, mtd_ooblayout_ecc);
1587}
1588EXPORT_SYMBOL_GPL(mtd_ooblayout_count_eccbytes);
1589
1590
1591
1592
1593
1594
1595int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
1596 struct otp_info *buf)
1597{
1598 if (!mtd->_get_fact_prot_info)
1599 return -EOPNOTSUPP;
1600 if (!len)
1601 return 0;
1602 return mtd->_get_fact_prot_info(mtd, len, retlen, buf);
1603}
1604EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info);
1605
1606int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
1607 size_t *retlen, u_char *buf)
1608{
1609 *retlen = 0;
1610 if (!mtd->_read_fact_prot_reg)
1611 return -EOPNOTSUPP;
1612 if (!len)
1613 return 0;
1614 return mtd->_read_fact_prot_reg(mtd, from, len, retlen, buf);
1615}
1616EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg);
1617
1618int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
1619 struct otp_info *buf)
1620{
1621 if (!mtd->_get_user_prot_info)
1622 return -EOPNOTSUPP;
1623 if (!len)
1624 return 0;
1625 return mtd->_get_user_prot_info(mtd, len, retlen, buf);
1626}
1627EXPORT_SYMBOL_GPL(mtd_get_user_prot_info);
1628
1629int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
1630 size_t *retlen, u_char *buf)
1631{
1632 *retlen = 0;
1633 if (!mtd->_read_user_prot_reg)
1634 return -EOPNOTSUPP;
1635 if (!len)
1636 return 0;
1637 return mtd->_read_user_prot_reg(mtd, from, len, retlen, buf);
1638}
1639EXPORT_SYMBOL_GPL(mtd_read_user_prot_reg);
1640
1641int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
1642 size_t *retlen, u_char *buf)
1643{
1644 int ret;
1645
1646 *retlen = 0;
1647 if (!mtd->_write_user_prot_reg)
1648 return -EOPNOTSUPP;
1649 if (!len)
1650 return 0;
1651 ret = mtd->_write_user_prot_reg(mtd, to, len, retlen, buf);
1652 if (ret)
1653 return ret;
1654
1655
1656
1657
1658
1659 return (*retlen) ? 0 : -ENOSPC;
1660}
1661EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg);
1662
1663int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
1664{
1665 if (!mtd->_lock_user_prot_reg)
1666 return -EOPNOTSUPP;
1667 if (!len)
1668 return 0;
1669 return mtd->_lock_user_prot_reg(mtd, from, len);
1670}
1671EXPORT_SYMBOL_GPL(mtd_lock_user_prot_reg);
1672
1673
1674int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
1675{
1676 if (!mtd->_lock)
1677 return -EOPNOTSUPP;
1678 if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs)
1679 return -EINVAL;
1680 if (!len)
1681 return 0;
1682 return mtd->_lock(mtd, ofs, len);
1683}
1684EXPORT_SYMBOL_GPL(mtd_lock);
1685
1686int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
1687{
1688 if (!mtd->_unlock)
1689 return -EOPNOTSUPP;
1690 if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs)
1691 return -EINVAL;
1692 if (!len)
1693 return 0;
1694 return mtd->_unlock(mtd, ofs, len);
1695}
1696EXPORT_SYMBOL_GPL(mtd_unlock);
1697
1698int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
1699{
1700 if (!mtd->_is_locked)
1701 return -EOPNOTSUPP;
1702 if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs)
1703 return -EINVAL;
1704 if (!len)
1705 return 0;
1706 return mtd->_is_locked(mtd, ofs, len);
1707}
1708EXPORT_SYMBOL_GPL(mtd_is_locked);
1709
1710int mtd_block_isreserved(struct mtd_info *mtd, loff_t ofs)
1711{
1712 if (ofs < 0 || ofs >= mtd->size)
1713 return -EINVAL;
1714 if (!mtd->_block_isreserved)
1715 return 0;
1716 return mtd->_block_isreserved(mtd, ofs);
1717}
1718EXPORT_SYMBOL_GPL(mtd_block_isreserved);
1719
1720int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
1721{
1722 if (ofs < 0 || ofs >= mtd->size)
1723 return -EINVAL;
1724 if (!mtd->_block_isbad)
1725 return 0;
1726 return mtd->_block_isbad(mtd, ofs);
1727}
1728EXPORT_SYMBOL_GPL(mtd_block_isbad);
1729
1730int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
1731{
1732 if (!mtd->_block_markbad)
1733 return -EOPNOTSUPP;
1734 if (ofs < 0 || ofs >= mtd->size)
1735 return -EINVAL;
1736 if (!(mtd->flags & MTD_WRITEABLE))
1737 return -EROFS;
1738 return mtd->_block_markbad(mtd, ofs);
1739}
1740EXPORT_SYMBOL_GPL(mtd_block_markbad);
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753static int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
1754 unsigned long count, loff_t to, size_t *retlen)
1755{
1756 unsigned long i;
1757 size_t totlen = 0, thislen;
1758 int ret = 0;
1759
1760 for (i = 0; i < count; i++) {
1761 if (!vecs[i].iov_len)
1762 continue;
1763 ret = mtd_write(mtd, to, vecs[i].iov_len, &thislen,
1764 vecs[i].iov_base);
1765 totlen += thislen;
1766 if (ret || thislen != vecs[i].iov_len)
1767 break;
1768 to += vecs[i].iov_len;
1769 }
1770 *retlen = totlen;
1771 return ret;
1772}
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
1786 unsigned long count, loff_t to, size_t *retlen)
1787{
1788 *retlen = 0;
1789 if (!(mtd->flags & MTD_WRITEABLE))
1790 return -EROFS;
1791 if (!mtd->_writev)
1792 return default_mtd_writev(mtd, vecs, count, to, retlen);
1793 return mtd->_writev(mtd, vecs, count, to, retlen);
1794}
1795EXPORT_SYMBOL_GPL(mtd_writev);
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size)
1822{
1823 gfp_t flags = __GFP_NOWARN | __GFP_DIRECT_RECLAIM | __GFP_NORETRY;
1824 size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE);
1825 void *kbuf;
1826
1827 *size = min_t(size_t, *size, KMALLOC_MAX_SIZE);
1828
1829 while (*size > min_alloc) {
1830 kbuf = kmalloc(*size, flags);
1831 if (kbuf)
1832 return kbuf;
1833
1834 *size >>= 1;
1835 *size = ALIGN(*size, mtd->writesize);
1836 }
1837
1838
1839
1840
1841
1842 return kmalloc(*size, GFP_KERNEL);
1843}
1844EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to);
1845
1846#ifdef CONFIG_PROC_FS
1847
1848
1849
1850
1851static int mtd_proc_show(struct seq_file *m, void *v)
1852{
1853 struct mtd_info *mtd;
1854
1855 seq_puts(m, "dev: size erasesize name\n");
1856 mutex_lock(&mtd_table_mutex);
1857 mtd_for_each_device(mtd) {
1858 seq_printf(m, "mtd%d: %8.8llx %8.8x \"%s\"\n",
1859 mtd->index, (unsigned long long)mtd->size,
1860 mtd->erasesize, mtd->name);
1861 }
1862 mutex_unlock(&mtd_table_mutex);
1863 return 0;
1864}
1865#endif
1866
1867
1868
1869
1870static struct backing_dev_info * __init mtd_bdi_init(char *name)
1871{
1872 struct backing_dev_info *bdi;
1873 int ret;
1874
1875 bdi = bdi_alloc(GFP_KERNEL);
1876 if (!bdi)
1877 return ERR_PTR(-ENOMEM);
1878
1879 bdi->name = name;
1880
1881
1882
1883
1884 ret = bdi_register(bdi, "%.28s-0", name);
1885 if (ret)
1886 bdi_put(bdi);
1887
1888 return ret ? ERR_PTR(ret) : bdi;
1889}
1890
1891static struct proc_dir_entry *proc_mtd;
1892
1893static int __init init_mtd(void)
1894{
1895 int ret;
1896
1897 ret = class_register(&mtd_class);
1898 if (ret)
1899 goto err_reg;
1900
1901 mtd_bdi = mtd_bdi_init("mtd");
1902 if (IS_ERR(mtd_bdi)) {
1903 ret = PTR_ERR(mtd_bdi);
1904 goto err_bdi;
1905 }
1906
1907 proc_mtd = proc_create_single("mtd", 0, NULL, mtd_proc_show);
1908
1909 ret = init_mtdchar();
1910 if (ret)
1911 goto out_procfs;
1912
1913 dfs_dir_mtd = debugfs_create_dir("mtd", NULL);
1914
1915 return 0;
1916
1917out_procfs:
1918 if (proc_mtd)
1919 remove_proc_entry("mtd", NULL);
1920 bdi_put(mtd_bdi);
1921err_bdi:
1922 class_unregister(&mtd_class);
1923err_reg:
1924 pr_err("Error registering mtd class or bdi: %d\n", ret);
1925 return ret;
1926}
1927
1928static void __exit cleanup_mtd(void)
1929{
1930 debugfs_remove_recursive(dfs_dir_mtd);
1931 cleanup_mtdchar();
1932 if (proc_mtd)
1933 remove_proc_entry("mtd", NULL);
1934 class_unregister(&mtd_class);
1935 bdi_put(mtd_bdi);
1936 idr_destroy(&mtd_idr);
1937}
1938
1939module_init(init_mtd);
1940module_exit(cleanup_mtd);
1941
1942MODULE_LICENSE("GPL");
1943MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
1944MODULE_DESCRIPTION("Core MTD registration and access routines");
1945