diff options
Diffstat (limited to 'drivers/mtd/mtdcore.c')
-rw-r--r-- | drivers/mtd/mtdcore.c | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 5ea22cf357fb..8d5e103695f9 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c | |||
@@ -683,6 +683,154 @@ void __put_mtd_device(struct mtd_info *mtd) | |||
683 | EXPORT_SYMBOL_GPL(__put_mtd_device); | 683 | EXPORT_SYMBOL_GPL(__put_mtd_device); |
684 | 684 | ||
685 | /* | 685 | /* |
686 | * Erase is an asynchronous operation. Device drivers are supposed | ||
687 | * to call instr->callback() whenever the operation completes, even | ||
688 | * if it completes with a failure. | ||
689 | * Callers are supposed to pass a callback function and wait for it | ||
690 | * to be called before writing to the block. | ||
691 | */ | ||
692 | int mtd_erase(struct mtd_info *mtd, struct erase_info *instr) | ||
693 | { | ||
694 | if (instr->addr > mtd->size || instr->len > mtd->size - instr->addr) | ||
695 | return -EINVAL; | ||
696 | return mtd->_erase(mtd, instr); | ||
697 | } | ||
698 | EXPORT_SYMBOL_GPL(mtd_erase); | ||
699 | |||
700 | /* | ||
701 | * This stuff for eXecute-In-Place. phys is optional and may be set to NULL. | ||
702 | */ | ||
703 | int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, | ||
704 | void **virt, resource_size_t *phys) | ||
705 | { | ||
706 | *retlen = 0; | ||
707 | if (!mtd->_point) | ||
708 | return -EOPNOTSUPP; | ||
709 | if (from < 0 || from > mtd->size || len > mtd->size - from) | ||
710 | return -EINVAL; | ||
711 | return mtd->_point(mtd, from, len, retlen, virt, phys); | ||
712 | } | ||
713 | EXPORT_SYMBOL_GPL(mtd_point); | ||
714 | |||
715 | /* We probably shouldn't allow XIP if the unpoint isn't a NULL */ | ||
716 | int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len) | ||
717 | { | ||
718 | if (!mtd->_point) | ||
719 | return -EOPNOTSUPP; | ||
720 | if (from < 0 || from > mtd->size || len > mtd->size - from) | ||
721 | return -EINVAL; | ||
722 | return mtd->_unpoint(mtd, from, len); | ||
723 | } | ||
724 | EXPORT_SYMBOL_GPL(mtd_unpoint); | ||
725 | |||
726 | /* | ||
727 | * Allow NOMMU mmap() to directly map the device (if not NULL) | ||
728 | * - return the address to which the offset maps | ||
729 | * - return -ENOSYS to indicate refusal to do the mapping | ||
730 | */ | ||
731 | unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len, | ||
732 | unsigned long offset, unsigned long flags) | ||
733 | { | ||
734 | if (!mtd->_get_unmapped_area) | ||
735 | return -EOPNOTSUPP; | ||
736 | if (offset > mtd->size || len > mtd->size - offset) | ||
737 | return -EINVAL; | ||
738 | return mtd->_get_unmapped_area(mtd, len, offset, flags); | ||
739 | } | ||
740 | EXPORT_SYMBOL_GPL(mtd_get_unmapped_area); | ||
741 | |||
742 | int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, | ||
743 | u_char *buf) | ||
744 | { | ||
745 | if (from < 0 || from > mtd->size || len > mtd->size - from) | ||
746 | return -EINVAL; | ||
747 | return mtd->_read(mtd, from, len, retlen, buf); | ||
748 | } | ||
749 | EXPORT_SYMBOL_GPL(mtd_read); | ||
750 | |||
751 | int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, | ||
752 | const u_char *buf) | ||
753 | { | ||
754 | *retlen = 0; | ||
755 | if (!mtd->_write) | ||
756 | return -EROFS; | ||
757 | if (to < 0 || to > mtd->size || len > mtd->size - to) | ||
758 | return -EINVAL; | ||
759 | return mtd->_write(mtd, to, len, retlen, buf); | ||
760 | } | ||
761 | EXPORT_SYMBOL_GPL(mtd_write); | ||
762 | |||
763 | /* | ||
764 | * In blackbox flight recorder like scenarios we want to make successful writes | ||
765 | * in interrupt context. panic_write() is only intended to be called when its | ||
766 | * known the kernel is about to panic and we need the write to succeed. Since | ||
767 | * the kernel is not going to be running for much longer, this function can | ||
768 | * break locks and delay to ensure the write succeeds (but not sleep). | ||
769 | */ | ||
770 | int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, | ||
771 | const u_char *buf) | ||
772 | { | ||
773 | *retlen = 0; | ||
774 | if (!mtd->_panic_write) | ||
775 | return -EOPNOTSUPP; | ||
776 | if (to < 0 || to > mtd->size || len > mtd->size - to) | ||
777 | return -EINVAL; | ||
778 | return mtd->_panic_write(mtd, to, len, retlen, buf); | ||
779 | } | ||
780 | EXPORT_SYMBOL_GPL(mtd_panic_write); | ||
781 | |||
782 | /* Chip-supported device locking */ | ||
783 | int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | ||
784 | { | ||
785 | if (!mtd->_lock) | ||
786 | return -EOPNOTSUPP; | ||
787 | if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs) | ||
788 | return -EINVAL; | ||
789 | return mtd->_lock(mtd, ofs, len); | ||
790 | } | ||
791 | EXPORT_SYMBOL_GPL(mtd_lock); | ||
792 | |||
793 | int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | ||
794 | { | ||
795 | if (!mtd->_unlock) | ||
796 | return -EOPNOTSUPP; | ||
797 | if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs) | ||
798 | return -EINVAL; | ||
799 | return mtd->_unlock(mtd, ofs, len); | ||
800 | } | ||
801 | EXPORT_SYMBOL_GPL(mtd_unlock); | ||
802 | |||
803 | int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) | ||
804 | { | ||
805 | if (!mtd->_is_locked) | ||
806 | return -EOPNOTSUPP; | ||
807 | if (ofs < 0 || ofs > mtd->size || len > mtd->size - ofs) | ||
808 | return -EINVAL; | ||
809 | return mtd->_is_locked(mtd, ofs, len); | ||
810 | } | ||
811 | EXPORT_SYMBOL_GPL(mtd_is_locked); | ||
812 | |||
813 | int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) | ||
814 | { | ||
815 | if (!mtd->_block_isbad) | ||
816 | return 0; | ||
817 | if (ofs < 0 || ofs > mtd->size) | ||
818 | return -EINVAL; | ||
819 | return mtd->_block_isbad(mtd, ofs); | ||
820 | } | ||
821 | EXPORT_SYMBOL_GPL(mtd_block_isbad); | ||
822 | |||
823 | int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) | ||
824 | { | ||
825 | if (!mtd->_block_markbad) | ||
826 | return -EOPNOTSUPP; | ||
827 | if (ofs < 0 || ofs > mtd->size) | ||
828 | return -EINVAL; | ||
829 | return mtd->_block_markbad(mtd, ofs); | ||
830 | } | ||
831 | EXPORT_SYMBOL_GPL(mtd_block_markbad); | ||
832 | |||
833 | /* | ||
686 | * default_mtd_writev - the default writev method | 834 | * default_mtd_writev - the default writev method |
687 | * @mtd: mtd device description object pointer | 835 | * @mtd: mtd device description object pointer |
688 | * @vecs: the vectors to write | 836 | * @vecs: the vectors to write |