aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/mtdcore.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/mtdcore.c')
-rw-r--r--drivers/mtd/mtdcore.c148
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)
683EXPORT_SYMBOL_GPL(__put_mtd_device); 683EXPORT_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 */
692int 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}
698EXPORT_SYMBOL_GPL(mtd_erase);
699
700/*
701 * This stuff for eXecute-In-Place. phys is optional and may be set to NULL.
702 */
703int 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}
713EXPORT_SYMBOL_GPL(mtd_point);
714
715/* We probably shouldn't allow XIP if the unpoint isn't a NULL */
716int 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}
724EXPORT_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 */
731unsigned 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}
740EXPORT_SYMBOL_GPL(mtd_get_unmapped_area);
741
742int 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}
749EXPORT_SYMBOL_GPL(mtd_read);
750
751int 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}
761EXPORT_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 */
770int 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}
780EXPORT_SYMBOL_GPL(mtd_panic_write);
781
782/* Chip-supported device locking */
783int 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}
791EXPORT_SYMBOL_GPL(mtd_lock);
792
793int 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}
801EXPORT_SYMBOL_GPL(mtd_unlock);
802
803int 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}
811EXPORT_SYMBOL_GPL(mtd_is_locked);
812
813int 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}
821EXPORT_SYMBOL_GPL(mtd_block_isbad);
822
823int 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}
831EXPORT_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