diff options
Diffstat (limited to 'drivers/mtd/mtdconcat.c')
-rw-r--r-- | drivers/mtd/mtdconcat.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 3dbb1b38db66..792b547786b8 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/types.h> | 15 | #include <linux/types.h> |
16 | #include <linux/backing-dev.h> | ||
16 | 17 | ||
17 | #include <linux/mtd/mtd.h> | 18 | #include <linux/mtd/mtd.h> |
18 | #include <linux/mtd/concat.h> | 19 | #include <linux/mtd/concat.h> |
@@ -684,6 +685,40 @@ static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
684 | } | 685 | } |
685 | 686 | ||
686 | /* | 687 | /* |
688 | * try to support NOMMU mmaps on concatenated devices | ||
689 | * - we don't support subdev spanning as we can't guarantee it'll work | ||
690 | */ | ||
691 | static unsigned long concat_get_unmapped_area(struct mtd_info *mtd, | ||
692 | unsigned long len, | ||
693 | unsigned long offset, | ||
694 | unsigned long flags) | ||
695 | { | ||
696 | struct mtd_concat *concat = CONCAT(mtd); | ||
697 | int i; | ||
698 | |||
699 | for (i = 0; i < concat->num_subdev; i++) { | ||
700 | struct mtd_info *subdev = concat->subdev[i]; | ||
701 | |||
702 | if (offset >= subdev->size) { | ||
703 | offset -= subdev->size; | ||
704 | continue; | ||
705 | } | ||
706 | |||
707 | /* we've found the subdev over which the mapping will reside */ | ||
708 | if (offset + len > subdev->size) | ||
709 | return (unsigned long) -EINVAL; | ||
710 | |||
711 | if (subdev->get_unmapped_area) | ||
712 | return subdev->get_unmapped_area(subdev, len, offset, | ||
713 | flags); | ||
714 | |||
715 | break; | ||
716 | } | ||
717 | |||
718 | return (unsigned long) -ENOSYS; | ||
719 | } | ||
720 | |||
721 | /* | ||
687 | * This function constructs a virtual MTD device by concatenating | 722 | * This function constructs a virtual MTD device by concatenating |
688 | * num_devs MTD devices. A pointer to the new device object is | 723 | * num_devs MTD devices. A pointer to the new device object is |
689 | * stored to *new_dev upon success. This function does _not_ | 724 | * stored to *new_dev upon success. This function does _not_ |
@@ -740,6 +775,8 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c | |||
740 | 775 | ||
741 | concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks; | 776 | concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks; |
742 | 777 | ||
778 | concat->mtd.backing_dev_info = subdev[0]->backing_dev_info; | ||
779 | |||
743 | concat->subdev[0] = subdev[0]; | 780 | concat->subdev[0] = subdev[0]; |
744 | 781 | ||
745 | for (i = 1; i < num_devs; i++) { | 782 | for (i = 1; i < num_devs; i++) { |
@@ -766,6 +803,15 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c | |||
766 | concat->mtd.flags |= | 803 | concat->mtd.flags |= |
767 | subdev[i]->flags & MTD_WRITEABLE; | 804 | subdev[i]->flags & MTD_WRITEABLE; |
768 | } | 805 | } |
806 | |||
807 | /* only permit direct mapping if the BDIs are all the same | ||
808 | * - copy-mapping is still permitted | ||
809 | */ | ||
810 | if (concat->mtd.backing_dev_info != | ||
811 | subdev[i]->backing_dev_info) | ||
812 | concat->mtd.backing_dev_info = | ||
813 | &default_backing_dev_info; | ||
814 | |||
769 | concat->mtd.size += subdev[i]->size; | 815 | concat->mtd.size += subdev[i]->size; |
770 | concat->mtd.ecc_stats.badblocks += | 816 | concat->mtd.ecc_stats.badblocks += |
771 | subdev[i]->ecc_stats.badblocks; | 817 | subdev[i]->ecc_stats.badblocks; |
@@ -796,6 +842,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c | |||
796 | concat->mtd.unlock = concat_unlock; | 842 | concat->mtd.unlock = concat_unlock; |
797 | concat->mtd.suspend = concat_suspend; | 843 | concat->mtd.suspend = concat_suspend; |
798 | concat->mtd.resume = concat_resume; | 844 | concat->mtd.resume = concat_resume; |
845 | concat->mtd.get_unmapped_area = concat_get_unmapped_area; | ||
799 | 846 | ||
800 | /* | 847 | /* |
801 | * Combine the erase block size info of the subdevices: | 848 | * Combine the erase block size info of the subdevices: |