1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/ptrace.h>
27#include <linux/seq_file.h>
28#include <linux/string.h>
29#include <linux/timer.h>
30#include <linux/major.h>
31#include <linux/fs.h>
32#include <linux/err.h>
33#include <linux/ioctl.h>
34#include <linux/init.h>
35#include <linux/proc_fs.h>
36#include <linux/idr.h>
37#include <linux/backing-dev.h>
38#include <linux/gfp.h>
39
40#include <linux/mtd/mtd.h>
41#include <linux/mtd/partitions.h>
42
43#include "mtdcore.h"
44
45
46
47
48static struct backing_dev_info mtd_bdi_unmappable = {
49 .capabilities = BDI_CAP_MAP_COPY,
50};
51
52
53
54
55
56
57static struct backing_dev_info mtd_bdi_ro_mappable = {
58 .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
59 BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP),
60};
61
62
63
64
65
66
67static struct backing_dev_info mtd_bdi_rw_mappable = {
68 .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
69 BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP |
70 BDI_CAP_WRITE_MAP),
71};
72
73static int mtd_cls_suspend(struct device *dev, pm_message_t state);
74static int mtd_cls_resume(struct device *dev);
75
76static struct class mtd_class = {
77 .name = "mtd",
78 .owner = THIS_MODULE,
79 .suspend = mtd_cls_suspend,
80 .resume = mtd_cls_resume,
81};
82
83static DEFINE_IDR(mtd_idr);
84
85
86
87DEFINE_MUTEX(mtd_table_mutex);
88EXPORT_SYMBOL_GPL(mtd_table_mutex);
89
90struct mtd_info *__mtd_next_device(int i)
91{
92 return idr_get_next(&mtd_idr, &i);
93}
94EXPORT_SYMBOL_GPL(__mtd_next_device);
95
96static LIST_HEAD(mtd_notifiers);
97
98
99#if defined(CONFIG_MTD_CHAR) || defined(CONFIG_MTD_CHAR_MODULE)
100#define MTD_DEVT(index) MKDEV(MTD_CHAR_MAJOR, (index)*2)
101#else
102#define MTD_DEVT(index) 0
103#endif
104
105
106
107
108static void mtd_release(struct device *dev)
109{
110 struct mtd_info __maybe_unused *mtd = dev_get_drvdata(dev);
111 dev_t index = MTD_DEVT(mtd->index);
112
113
114 if (index)
115 device_destroy(&mtd_class, index + 1);
116}
117
118static int mtd_cls_suspend(struct device *dev, pm_message_t state)
119{
120 struct mtd_info *mtd = dev_get_drvdata(dev);
121
122 return mtd ? mtd_suspend(mtd) : 0;
123}
124
125static int mtd_cls_resume(struct device *dev)
126{
127 struct mtd_info *mtd = dev_get_drvdata(dev);
128
129 if (mtd)
130 mtd_resume(mtd);
131 return 0;
132}
133
134static ssize_t mtd_type_show(struct device *dev,
135 struct device_attribute *attr, char *buf)
136{
137 struct mtd_info *mtd = dev_get_drvdata(dev);
138 char *type;
139
140 switch (mtd->type) {
141 case MTD_ABSENT:
142 type = "absent";
143 break;
144 case MTD_RAM:
145 type = "ram";
146 break;
147 case MTD_ROM:
148 type = "rom";
149 break;
150 case MTD_NORFLASH:
151 type = "nor";
152 break;
153 case MTD_NANDFLASH:
154 type = "nand";
155 break;
156 case MTD_DATAFLASH:
157 type = "dataflash";
158 break;
159 case MTD_UBIVOLUME:
160 type = "ubi";
161 break;
162 default:
163 type = "unknown";
164 }
165
166 return snprintf(buf, PAGE_SIZE, "%s\n", type);
167}
168static DEVICE_ATTR(type, S_IRUGO, mtd_type_show, NULL);
169
170static ssize_t mtd_flags_show(struct device *dev,
171 struct device_attribute *attr, char *buf)
172{
173 struct mtd_info *mtd = dev_get_drvdata(dev);
174
175 return snprintf(buf, PAGE_SIZE, "0x%lx\n", (unsigned long)mtd->flags);
176
177}
178static DEVICE_ATTR(flags, S_IRUGO, mtd_flags_show, NULL);
179
180static ssize_t mtd_size_show(struct device *dev,
181 struct device_attribute *attr, char *buf)
182{
183 struct mtd_info *mtd = dev_get_drvdata(dev);
184
185 return snprintf(buf, PAGE_SIZE, "%llu\n",
186 (unsigned long long)mtd->size);
187
188}
189static DEVICE_ATTR(size, S_IRUGO, mtd_size_show, NULL);
190
191static ssize_t mtd_erasesize_show(struct device *dev,
192 struct device_attribute *attr, char *buf)
193{
194 struct mtd_info *mtd = dev_get_drvdata(dev);
195
196 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->erasesize);
197
198}
199static DEVICE_ATTR(erasesize, S_IRUGO, mtd_erasesize_show, NULL);
200
201static ssize_t mtd_writesize_show(struct device *dev,
202 struct device_attribute *attr, char *buf)
203{
204 struct mtd_info *mtd = dev_get_drvdata(dev);
205
206 return snprintf(buf, PAGE_SIZE, "%lu\n", (unsigned long)mtd->writesize);
207
208}
209static DEVICE_ATTR(writesize, S_IRUGO, mtd_writesize_show, NULL);
210
211static ssize_t mtd_subpagesize_show(struct device *dev,
212 struct device_attribute *attr, char *buf)
213{
214 struct mtd_info *mtd = dev_get_drvdata(dev);
215 unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft;
216
217 return snprintf(buf, PAGE_SIZE, "%u\n", subpagesize);
218
219}
220static DEVICE_ATTR(subpagesize, S_IRUGO, mtd_subpagesize_show, NULL);
221
222static ssize_t mtd_oobsize_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, "%lu\n", (unsigned long)mtd->oobsize);
228
229}
230static DEVICE_ATTR(oobsize, S_IRUGO, mtd_oobsize_show, NULL);
231
232static ssize_t mtd_numeraseregions_show(struct device *dev,
233 struct device_attribute *attr, char *buf)
234{
235 struct mtd_info *mtd = dev_get_drvdata(dev);
236
237 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->numeraseregions);
238
239}
240static DEVICE_ATTR(numeraseregions, S_IRUGO, mtd_numeraseregions_show,
241 NULL);
242
243static ssize_t mtd_name_show(struct device *dev,
244 struct device_attribute *attr, char *buf)
245{
246 struct mtd_info *mtd = dev_get_drvdata(dev);
247
248 return snprintf(buf, PAGE_SIZE, "%s\n", mtd->name);
249
250}
251static DEVICE_ATTR(name, S_IRUGO, mtd_name_show, NULL);
252
253static ssize_t mtd_ecc_strength_show(struct device *dev,
254 struct device_attribute *attr, char *buf)
255{
256 struct mtd_info *mtd = dev_get_drvdata(dev);
257
258 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->ecc_strength);
259}
260static DEVICE_ATTR(ecc_strength, S_IRUGO, mtd_ecc_strength_show, NULL);
261
262static ssize_t mtd_bitflip_threshold_show(struct device *dev,
263 struct device_attribute *attr,
264 char *buf)
265{
266 struct mtd_info *mtd = dev_get_drvdata(dev);
267
268 return snprintf(buf, PAGE_SIZE, "%u\n", mtd->bitflip_threshold);
269}
270
271static ssize_t mtd_bitflip_threshold_store(struct device *dev,
272 struct device_attribute *attr,
273 const char *buf, size_t count)
274{
275 struct mtd_info *mtd = dev_get_drvdata(dev);
276 unsigned int bitflip_threshold;
277 int retval;
278
279 retval = kstrtouint(buf, 0, &bitflip_threshold);
280 if (retval)
281 return retval;
282
283 mtd->bitflip_threshold = bitflip_threshold;
284 return count;
285}
286static DEVICE_ATTR(bitflip_threshold, S_IRUGO | S_IWUSR,
287 mtd_bitflip_threshold_show,
288 mtd_bitflip_threshold_store);
289
290static struct attribute *mtd_attrs[] = {
291 &dev_attr_type.attr,
292 &dev_attr_flags.attr,
293 &dev_attr_size.attr,
294 &dev_attr_erasesize.attr,
295 &dev_attr_writesize.attr,
296 &dev_attr_subpagesize.attr,
297 &dev_attr_oobsize.attr,
298 &dev_attr_numeraseregions.attr,
299 &dev_attr_name.attr,
300 &dev_attr_ecc_strength.attr,
301 &dev_attr_bitflip_threshold.attr,
302 NULL,
303};
304
305static struct attribute_group mtd_group = {
306 .attrs = mtd_attrs,
307};
308
309static const struct attribute_group *mtd_groups[] = {
310 &mtd_group,
311 NULL,
312};
313
314static struct device_type mtd_devtype = {
315 .name = "mtd",
316 .groups = mtd_groups,
317 .release = mtd_release,
318};
319
320
321
322
323
324
325
326
327
328
329
330int add_mtd_device(struct mtd_info *mtd)
331{
332 struct mtd_notifier *not;
333 int i, error;
334
335 if (!mtd->backing_dev_info) {
336 switch (mtd->type) {
337 case MTD_RAM:
338 mtd->backing_dev_info = &mtd_bdi_rw_mappable;
339 break;
340 case MTD_ROM:
341 mtd->backing_dev_info = &mtd_bdi_ro_mappable;
342 break;
343 default:
344 mtd->backing_dev_info = &mtd_bdi_unmappable;
345 break;
346 }
347 }
348
349 BUG_ON(mtd->writesize == 0);
350 mutex_lock(&mtd_table_mutex);
351
352 do {
353 if (!idr_pre_get(&mtd_idr, GFP_KERNEL))
354 goto fail_locked;
355 error = idr_get_new(&mtd_idr, mtd, &i);
356 } while (error == -EAGAIN);
357
358 if (error)
359 goto fail_locked;
360
361 mtd->index = i;
362 mtd->usecount = 0;
363
364
365 if (mtd->bitflip_threshold == 0)
366 mtd->bitflip_threshold = mtd->ecc_strength;
367
368 if (is_power_of_2(mtd->erasesize))
369 mtd->erasesize_shift = ffs(mtd->erasesize) - 1;
370 else
371 mtd->erasesize_shift = 0;
372
373 if (is_power_of_2(mtd->writesize))
374 mtd->writesize_shift = ffs(mtd->writesize) - 1;
375 else
376 mtd->writesize_shift = 0;
377
378 mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1;
379 mtd->writesize_mask = (1 << mtd->writesize_shift) - 1;
380
381
382 if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) {
383 error = mtd_unlock(mtd, 0, mtd->size);
384 if (error && error != -EOPNOTSUPP)
385 printk(KERN_WARNING
386 "%s: unlock failed, writes may not work\n",
387 mtd->name);
388 }
389
390
391
392
393 mtd->dev.type = &mtd_devtype;
394 mtd->dev.class = &mtd_class;
395 mtd->dev.devt = MTD_DEVT(i);
396 dev_set_name(&mtd->dev, "mtd%d", i);
397 dev_set_drvdata(&mtd->dev, mtd);
398 if (device_register(&mtd->dev) != 0)
399 goto fail_added;
400
401 if (MTD_DEVT(i))
402 device_create(&mtd_class, mtd->dev.parent,
403 MTD_DEVT(i) + 1,
404 NULL, "mtd%dro", i);
405
406 pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name);
407
408
409 list_for_each_entry(not, &mtd_notifiers, list)
410 not->add(mtd);
411
412 mutex_unlock(&mtd_table_mutex);
413
414
415
416
417 __module_get(THIS_MODULE);
418 return 0;
419
420fail_added:
421 idr_remove(&mtd_idr, i);
422fail_locked:
423 mutex_unlock(&mtd_table_mutex);
424 return 1;
425}
426
427
428
429
430
431
432
433
434
435
436
437int del_mtd_device(struct mtd_info *mtd)
438{
439 int ret;
440 struct mtd_notifier *not;
441
442 mutex_lock(&mtd_table_mutex);
443
444 if (idr_find(&mtd_idr, mtd->index) != mtd) {
445 ret = -ENODEV;
446 goto out_error;
447 }
448
449
450
451 list_for_each_entry(not, &mtd_notifiers, list)
452 not->remove(mtd);
453
454 if (mtd->usecount) {
455 printk(KERN_NOTICE "Removing MTD device #%d (%s) with use count %d\n",
456 mtd->index, mtd->name, mtd->usecount);
457 ret = -EBUSY;
458 } else {
459 device_unregister(&mtd->dev);
460
461 idr_remove(&mtd_idr, mtd->index);
462
463 module_put(THIS_MODULE);
464 ret = 0;
465 }
466
467out_error:
468 mutex_unlock(&mtd_table_mutex);
469 return ret;
470}
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500int mtd_device_parse_register(struct mtd_info *mtd, const char **types,
501 struct mtd_part_parser_data *parser_data,
502 const struct mtd_partition *parts,
503 int nr_parts)
504{
505 int err;
506 struct mtd_partition *real_parts;
507
508 err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
509 if (err <= 0 && nr_parts && parts) {
510 real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
511 GFP_KERNEL);
512 if (!real_parts)
513 err = -ENOMEM;
514 else
515 err = nr_parts;
516 }
517
518 if (err > 0) {
519 err = add_mtd_partitions(mtd, real_parts, err);
520 kfree(real_parts);
521 } else if (err == 0) {
522 err = add_mtd_device(mtd);
523 if (err == 1)
524 err = -ENODEV;
525 }
526
527 return err;
528}
529EXPORT_SYMBOL_GPL(mtd_device_parse_register);
530
531
532
533
534
535
536
537int mtd_device_unregister(struct mtd_info *master)
538{
539 int err;
540
541 err = del_mtd_partitions(master);
542 if (err)
543 return err;
544
545 if (!device_is_registered(&master->dev))
546 return 0;
547
548 return del_mtd_device(master);
549}
550EXPORT_SYMBOL_GPL(mtd_device_unregister);
551
552
553
554
555
556
557
558
559
560void register_mtd_user (struct mtd_notifier *new)
561{
562 struct mtd_info *mtd;
563
564 mutex_lock(&mtd_table_mutex);
565
566 list_add(&new->list, &mtd_notifiers);
567
568 __module_get(THIS_MODULE);
569
570 mtd_for_each_device(mtd)
571 new->add(mtd);
572
573 mutex_unlock(&mtd_table_mutex);
574}
575EXPORT_SYMBOL_GPL(register_mtd_user);
576
577
578
579
580
581
582
583
584
585
586int unregister_mtd_user (struct mtd_notifier *old)
587{
588 struct mtd_info *mtd;
589
590 mutex_lock(&mtd_table_mutex);
591
592 module_put(THIS_MODULE);
593
594 mtd_for_each_device(mtd)
595 old->remove(mtd);
596
597 list_del(&old->list);
598 mutex_unlock(&mtd_table_mutex);
599 return 0;
600}
601EXPORT_SYMBOL_GPL(unregister_mtd_user);
602
603
604
605
606
607
608
609
610
611
612
613
614struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num)
615{
616 struct mtd_info *ret = NULL, *other;
617 int err = -ENODEV;
618
619 mutex_lock(&mtd_table_mutex);
620
621 if (num == -1) {
622 mtd_for_each_device(other) {
623 if (other == mtd) {
624 ret = mtd;
625 break;
626 }
627 }
628 } else if (num >= 0) {
629 ret = idr_find(&mtd_idr, num);
630 if (mtd && mtd != ret)
631 ret = NULL;
632 }
633
634 if (!ret) {
635 ret = ERR_PTR(err);
636 goto out;
637 }
638
639 err = __get_mtd_device(ret);
640 if (err)
641 ret = ERR_PTR(err);
642out:
643 mutex_unlock(&mtd_table_mutex);
644 return ret;
645}
646EXPORT_SYMBOL_GPL(get_mtd_device);
647
648
649int __get_mtd_device(struct mtd_info *mtd)
650{
651 int err;
652
653 if (!try_module_get(mtd->owner))
654 return -ENODEV;
655
656 if (mtd->_get_device) {
657 err = mtd->_get_device(mtd);
658
659 if (err) {
660 module_put(mtd->owner);
661 return err;
662 }
663 }
664 mtd->usecount++;
665 return 0;
666}
667EXPORT_SYMBOL_GPL(__get_mtd_device);
668
669
670
671
672
673
674
675
676
677struct mtd_info *get_mtd_device_nm(const char *name)
678{
679 int err = -ENODEV;
680 struct mtd_info *mtd = NULL, *other;
681
682 mutex_lock(&mtd_table_mutex);
683
684 mtd_for_each_device(other) {
685 if (!strcmp(name, other->name)) {
686 mtd = other;
687 break;
688 }
689 }
690
691 if (!mtd)
692 goto out_unlock;
693
694 err = __get_mtd_device(mtd);
695 if (err)
696 goto out_unlock;
697
698 mutex_unlock(&mtd_table_mutex);
699 return mtd;
700
701out_unlock:
702 mutex_unlock(&mtd_table_mutex);
703 return ERR_PTR(err);
704}
705EXPORT_SYMBOL_GPL(get_mtd_device_nm);
706
707void put_mtd_device(struct mtd_info *mtd)
708{
709 mutex_lock(&mtd_table_mutex);
710 __put_mtd_device(mtd);
711 mutex_unlock(&mtd_table_mutex);
712
713}
714EXPORT_SYMBOL_GPL(put_mtd_device);
715
716void __put_mtd_device(struct mtd_info *mtd)
717{
718 --mtd->usecount;
719 BUG_ON(mtd->usecount < 0);
720
721 if (mtd->_put_device)
722 mtd->_put_device(mtd);
723
724 module_put(mtd->owner);
725}
726EXPORT_SYMBOL_GPL(__put_mtd_device);
727
728
729
730
731
732
733
734
735int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
736{
737 if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr)
738 return -EINVAL;
739 if (!(mtd->flags & MTD_WRITEABLE))
740 return -EROFS;
741 instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN;
742 if (!instr->len) {
743 instr->state = MTD_ERASE_DONE;
744 mtd_erase_callback(instr);
745 return 0;
746 }
747 return mtd->_erase(mtd, instr);
748}
749EXPORT_SYMBOL_GPL(mtd_erase);
750
751
752
753
754int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
755 void **virt, resource_size_t *phys)
756{
757 *retlen = 0;
758 *virt = NULL;
759 if (phys)
760 *phys = 0;
761 if (!mtd->_point)
762 return -EOPNOTSUPP;
763 if (from < 0 || from > mtd->size || len > mtd->size - from)
764 return -EINVAL;
765 if (!len)
766 return 0;
767 return mtd->_point(mtd, from, len, retlen, virt, phys);
768}
769EXPORT_SYMBOL_GPL(mtd_point);
770
771
772int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len)
773{
774 if (!mtd->_point)
775 return -EOPNOTSUPP;
776 if (from < 0 || from > mtd->size || len > mtd->size - from)
777 return -EINVAL;
778 if (!len)
779 return 0;
780 return mtd->_unpoint(mtd, from, len);
781}
782EXPORT_SYMBOL_GPL(mtd_unpoint);
783
784
785
786
787
788
789unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
790 unsigned long offset, unsigned long flags)
791{
792 if (!mtd->_get_unmapped_area)
793 return -EOPNOTSUPP;
794 if (offset > mtd->size || len > mtd->size - offset)
795 return -EINVAL;
796 return mtd->_get_unmapped_area(mtd, len, offset, flags);
797}
798EXPORT_SYMBOL_GPL(mtd_get_unmapped_area);
799
800int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
801 u_char *buf)
802{
803 int ret_code;
804 *retlen = 0;
805 if (from < 0 || from > mtd->size || len > mtd->size - from)
806 return -EINVAL;
807 if (!len)
808 return 0;
809
810
811
812
813
814
815 ret_code = mtd->_read(mtd, from, len, retlen, buf);
816 if (unlikely(ret_code < 0))
817 return ret_code;
818 if (mtd->ecc_strength == 0)
819 return 0;
820 return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0;
821}
822EXPORT_SYMBOL_GPL(mtd_read);
823
824int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
825 const u_char *buf)
826{
827 *retlen = 0;
828 if (to < 0 || to > mtd->size || len > mtd->size - to)
829 return -EINVAL;
830 if (!mtd->_write || !(mtd->flags & MTD_WRITEABLE))
831 return -EROFS;
832 if (!len)
833 return 0;
834 return mtd->_write(mtd, to, len, retlen, buf);
835}
836EXPORT_SYMBOL_GPL(mtd_write);
837
838
839
840
841
842
843
844
845int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
846 const u_char *buf)
847{
848 *retlen = 0;
849 if (!mtd->_panic_write)
850 return -EOPNOTSUPP;
851 if (to < 0 || to > mtd->size || len > mtd->size - to)
852 return -EINVAL;
853 if (!(mtd->flags & MTD_WRITEABLE))
854 return -EROFS;
855 if (!len)
856 return 0;
857 return mtd->_panic_write(mtd, to, len, retlen, buf);
858}
859EXPORT_SYMBOL_GPL(mtd_panic_write);
860
861
862
863
864
865
866int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf,
867 size_t len)
868{
869 if (!mtd->_get_fact_prot_info)
870 return -EOPNOTSUPP;
871 if (!len)
872 return 0;
873 return mtd->_get_fact_prot_info(mtd, buf, len);
874}
875EXPORT_SYMBOL_GPL(mtd_get_fact_prot_info);
876
877int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
878 size_t *retlen, u_char *buf)
879{
880 *retlen = 0;
881 if (!mtd->_read_fact_prot_reg)
882 return -EOPNOTSUPP;
883 if (!len)
884 return 0;
885 return mtd->_read_fact_prot_reg(mtd, from, len, retlen, buf);
886}
887EXPORT_SYMBOL_GPL(mtd_read_fact_prot_reg);
888
889int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf,
890 size_t len)
891{
892 if (!mtd->_get_user_prot_info)
893 return -EOPNOTSUPP;
894 if (!len)
895 return 0;
896 return mtd->_get_user_prot_info(mtd, buf, len);
897}
898EXPORT_SYMBOL_GPL(mtd_get_user_prot_info);
899
900int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
901 size_t *retlen, u_char *buf)
902{
903 *retlen = 0;
904 if (!mtd->_read_user_prot_reg)
905 return -EOPNOTSUPP;
906 if (!len)
907 return 0;
908 return mtd->_read_user_prot_reg(mtd, from, len, retlen, buf);
909}
910EXPORT_SYMBOL_GPL(mtd_read_user_prot_reg);
911
912int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
913 size_t *retlen, u_char *buf)
914{
915 *retlen = 0;
916 if (!mtd->_write_user_prot_reg)
917 return -EOPNOTSUPP;
918 if (!len)
919 return 0;
920 return mtd->_write_user_prot_reg(mtd, to, len, retlen, buf);
921}
922EXPORT_SYMBOL_GPL(mtd_write_user_prot_reg);
923
924int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len)
925{
926 if (!mtd->_lock_user_prot_reg)
927 return -EOPNOTSUPP;
928 if (!len)
929 return 0;
930 return mtd->_lock_user_prot_reg(mtd, from, len);
931}
932EXPORT_SYMBOL_GPL(mtd_lock_user_prot_reg);
933
934
935int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
936{
937 if (!mtd->_lock)
938 return -EOPNOTSUPP;
939 if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs)
940 return -EINVAL;
941 if (!len)
942 return 0;
943 return mtd->_lock(mtd, ofs, len);
944}
945EXPORT_SYMBOL_GPL(mtd_lock);
946
947int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
948{
949 if (!mtd->_unlock)
950 return -EOPNOTSUPP;
951 if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs)
952 return -EINVAL;
953 if (!len)
954 return 0;
955 return mtd->_unlock(mtd, ofs, len);
956}
957EXPORT_SYMBOL_GPL(mtd_unlock);
958
959int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len)
960{
961 if (!mtd->_is_locked)
962 return -EOPNOTSUPP;
963 if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs)
964 return -EINVAL;
965 if (!len)
966 return 0;
967 return mtd->_is_locked(mtd, ofs, len);
968}
969EXPORT_SYMBOL_GPL(mtd_is_locked);
970
971int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs)
972{
973 if (!mtd->_block_isbad)
974 return 0;
975 if (ofs < 0 || ofs > mtd->size)
976 return -EINVAL;
977 return mtd->_block_isbad(mtd, ofs);
978}
979EXPORT_SYMBOL_GPL(mtd_block_isbad);
980
981int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
982{
983 if (!mtd->_block_markbad)
984 return -EOPNOTSUPP;
985 if (ofs < 0 || ofs > mtd->size)
986 return -EINVAL;
987 if (!(mtd->flags & MTD_WRITEABLE))
988 return -EROFS;
989 return mtd->_block_markbad(mtd, ofs);
990}
991EXPORT_SYMBOL_GPL(mtd_block_markbad);
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004static int default_mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
1005 unsigned long count, loff_t to, size_t *retlen)
1006{
1007 unsigned long i;
1008 size_t totlen = 0, thislen;
1009 int ret = 0;
1010
1011 for (i = 0; i < count; i++) {
1012 if (!vecs[i].iov_len)
1013 continue;
1014 ret = mtd_write(mtd, to, vecs[i].iov_len, &thislen,
1015 vecs[i].iov_base);
1016 totlen += thislen;
1017 if (ret || thislen != vecs[i].iov_len)
1018 break;
1019 to += vecs[i].iov_len;
1020 }
1021 *retlen = totlen;
1022 return ret;
1023}
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
1037 unsigned long count, loff_t to, size_t *retlen)
1038{
1039 *retlen = 0;
1040 if (!(mtd->flags & MTD_WRITEABLE))
1041 return -EROFS;
1042 if (!mtd->_writev)
1043 return default_mtd_writev(mtd, vecs, count, to, retlen);
1044 return mtd->_writev(mtd, vecs, count, to, retlen);
1045}
1046EXPORT_SYMBOL_GPL(mtd_writev);
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size)
1073{
1074 gfp_t flags = __GFP_NOWARN | __GFP_WAIT |
1075 __GFP_NORETRY | __GFP_NO_KSWAPD;
1076 size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE);
1077 void *kbuf;
1078
1079 *size = min_t(size_t, *size, KMALLOC_MAX_SIZE);
1080
1081 while (*size > min_alloc) {
1082 kbuf = kmalloc(*size, flags);
1083 if (kbuf)
1084 return kbuf;
1085
1086 *size >>= 1;
1087 *size = ALIGN(*size, mtd->writesize);
1088 }
1089
1090
1091
1092
1093
1094 return kmalloc(*size, GFP_KERNEL);
1095}
1096EXPORT_SYMBOL_GPL(mtd_kmalloc_up_to);
1097
1098#ifdef CONFIG_PROC_FS
1099
1100
1101
1102
1103static struct proc_dir_entry *proc_mtd;
1104
1105static int mtd_proc_show(struct seq_file *m, void *v)
1106{
1107 struct mtd_info *mtd;
1108
1109 seq_puts(m, "dev: size erasesize name\n");
1110 mutex_lock(&mtd_table_mutex);
1111 mtd_for_each_device(mtd) {
1112 seq_printf(m, "mtd%d: %8.8llx %8.8x \"%s\"\n",
1113 mtd->index, (unsigned long long)mtd->size,
1114 mtd->erasesize, mtd->name);
1115 }
1116 mutex_unlock(&mtd_table_mutex);
1117 return 0;
1118}
1119
1120static int mtd_proc_open(struct inode *inode, struct file *file)
1121{
1122 return single_open(file, mtd_proc_show, NULL);
1123}
1124
1125static const struct file_operations mtd_proc_ops = {
1126 .open = mtd_proc_open,
1127 .read = seq_read,
1128 .llseek = seq_lseek,
1129 .release = single_release,
1130};
1131#endif
1132
1133
1134
1135
1136static int __init mtd_bdi_init(struct backing_dev_info *bdi, const char *name)
1137{
1138 int ret;
1139
1140 ret = bdi_init(bdi);
1141 if (!ret)
1142 ret = bdi_register(bdi, NULL, name);
1143
1144 if (ret)
1145 bdi_destroy(bdi);
1146
1147 return ret;
1148}
1149
1150static int __init init_mtd(void)
1151{
1152 int ret;
1153
1154 ret = class_register(&mtd_class);
1155 if (ret)
1156 goto err_reg;
1157
1158 ret = mtd_bdi_init(&mtd_bdi_unmappable, "mtd-unmap");
1159 if (ret)
1160 goto err_bdi1;
1161
1162 ret = mtd_bdi_init(&mtd_bdi_ro_mappable, "mtd-romap");
1163 if (ret)
1164 goto err_bdi2;
1165
1166 ret = mtd_bdi_init(&mtd_bdi_rw_mappable, "mtd-rwmap");
1167 if (ret)
1168 goto err_bdi3;
1169
1170#ifdef CONFIG_PROC_FS
1171 proc_mtd = proc_create("mtd", 0, NULL, &mtd_proc_ops);
1172#endif
1173 return 0;
1174
1175err_bdi3:
1176 bdi_destroy(&mtd_bdi_ro_mappable);
1177err_bdi2:
1178 bdi_destroy(&mtd_bdi_unmappable);
1179err_bdi1:
1180 class_unregister(&mtd_class);
1181err_reg:
1182 pr_err("Error registering mtd class or bdi: %d\n", ret);
1183 return ret;
1184}
1185
1186static void __exit cleanup_mtd(void)
1187{
1188#ifdef CONFIG_PROC_FS
1189 if (proc_mtd)
1190 remove_proc_entry( "mtd", NULL);
1191#endif
1192 class_unregister(&mtd_class);
1193 bdi_destroy(&mtd_bdi_unmappable);
1194 bdi_destroy(&mtd_bdi_ro_mappable);
1195 bdi_destroy(&mtd_bdi_rw_mappable);
1196}
1197
1198module_init(init_mtd);
1199module_exit(cleanup_mtd);
1200
1201MODULE_LICENSE("GPL");
1202MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
1203MODULE_DESCRIPTION("Core MTD registration and access routines");
1204