diff options
Diffstat (limited to 'drivers/mtd/mtdconcat.c')
-rw-r--r-- | drivers/mtd/mtdconcat.c | 106 |
1 files changed, 24 insertions, 82 deletions
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c index 1ed5103b219b..b9000563b9f4 100644 --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c | |||
@@ -72,8 +72,6 @@ concat_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
72 | int ret = 0, err; | 72 | int ret = 0, err; |
73 | int i; | 73 | int i; |
74 | 74 | ||
75 | *retlen = 0; | ||
76 | |||
77 | for (i = 0; i < concat->num_subdev; i++) { | 75 | for (i = 0; i < concat->num_subdev; i++) { |
78 | struct mtd_info *subdev = concat->subdev[i]; | 76 | struct mtd_info *subdev = concat->subdev[i]; |
79 | size_t size, retsize; | 77 | size_t size, retsize; |
@@ -126,11 +124,6 @@ concat_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
126 | int err = -EINVAL; | 124 | int err = -EINVAL; |
127 | int i; | 125 | int i; |
128 | 126 | ||
129 | if (!(mtd->flags & MTD_WRITEABLE)) | ||
130 | return -EROFS; | ||
131 | |||
132 | *retlen = 0; | ||
133 | |||
134 | for (i = 0; i < concat->num_subdev; i++) { | 127 | for (i = 0; i < concat->num_subdev; i++) { |
135 | struct mtd_info *subdev = concat->subdev[i]; | 128 | struct mtd_info *subdev = concat->subdev[i]; |
136 | size_t size, retsize; | 129 | size_t size, retsize; |
@@ -145,11 +138,7 @@ concat_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
145 | else | 138 | else |
146 | size = len; | 139 | size = len; |
147 | 140 | ||
148 | if (!(subdev->flags & MTD_WRITEABLE)) | 141 | err = mtd_write(subdev, to, size, &retsize, buf); |
149 | err = -EROFS; | ||
150 | else | ||
151 | err = mtd_write(subdev, to, size, &retsize, buf); | ||
152 | |||
153 | if (err) | 142 | if (err) |
154 | break; | 143 | break; |
155 | 144 | ||
@@ -176,19 +165,10 @@ concat_writev(struct mtd_info *mtd, const struct kvec *vecs, | |||
176 | int i; | 165 | int i; |
177 | int err = -EINVAL; | 166 | int err = -EINVAL; |
178 | 167 | ||
179 | if (!(mtd->flags & MTD_WRITEABLE)) | ||
180 | return -EROFS; | ||
181 | |||
182 | *retlen = 0; | ||
183 | |||
184 | /* Calculate total length of data */ | 168 | /* Calculate total length of data */ |
185 | for (i = 0; i < count; i++) | 169 | for (i = 0; i < count; i++) |
186 | total_len += vecs[i].iov_len; | 170 | total_len += vecs[i].iov_len; |
187 | 171 | ||
188 | /* Do not allow write past end of device */ | ||
189 | if ((to + total_len) > mtd->size) | ||
190 | return -EINVAL; | ||
191 | |||
192 | /* Check alignment */ | 172 | /* Check alignment */ |
193 | if (mtd->writesize > 1) { | 173 | if (mtd->writesize > 1) { |
194 | uint64_t __to = to; | 174 | uint64_t __to = to; |
@@ -224,12 +204,8 @@ concat_writev(struct mtd_info *mtd, const struct kvec *vecs, | |||
224 | old_iov_len = vecs_copy[entry_high].iov_len; | 204 | old_iov_len = vecs_copy[entry_high].iov_len; |
225 | vecs_copy[entry_high].iov_len = size; | 205 | vecs_copy[entry_high].iov_len = size; |
226 | 206 | ||
227 | if (!(subdev->flags & MTD_WRITEABLE)) | 207 | err = mtd_writev(subdev, &vecs_copy[entry_low], |
228 | err = -EROFS; | 208 | entry_high - entry_low + 1, to, &retsize); |
229 | else | ||
230 | err = mtd_writev(subdev, &vecs_copy[entry_low], | ||
231 | entry_high - entry_low + 1, to, | ||
232 | &retsize); | ||
233 | 209 | ||
234 | vecs_copy[entry_high].iov_len = old_iov_len - size; | 210 | vecs_copy[entry_high].iov_len = old_iov_len - size; |
235 | vecs_copy[entry_high].iov_base += size; | 211 | vecs_copy[entry_high].iov_base += size; |
@@ -403,15 +379,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
403 | uint64_t length, offset = 0; | 379 | uint64_t length, offset = 0; |
404 | struct erase_info *erase; | 380 | struct erase_info *erase; |
405 | 381 | ||
406 | if (!(mtd->flags & MTD_WRITEABLE)) | ||
407 | return -EROFS; | ||
408 | |||
409 | if (instr->addr > concat->mtd.size) | ||
410 | return -EINVAL; | ||
411 | |||
412 | if (instr->len + instr->addr > concat->mtd.size) | ||
413 | return -EINVAL; | ||
414 | |||
415 | /* | 382 | /* |
416 | * Check for proper erase block alignment of the to-be-erased area. | 383 | * Check for proper erase block alignment of the to-be-erased area. |
417 | * It is easier to do this based on the super device's erase | 384 | * It is easier to do this based on the super device's erase |
@@ -459,8 +426,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
459 | return -EINVAL; | 426 | return -EINVAL; |
460 | } | 427 | } |
461 | 428 | ||
462 | instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; | ||
463 | |||
464 | /* make a local copy of instr to avoid modifying the caller's struct */ | 429 | /* make a local copy of instr to avoid modifying the caller's struct */ |
465 | erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL); | 430 | erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL); |
466 | 431 | ||
@@ -499,10 +464,6 @@ static int concat_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
499 | else | 464 | else |
500 | erase->len = length; | 465 | erase->len = length; |
501 | 466 | ||
502 | if (!(subdev->flags & MTD_WRITEABLE)) { | ||
503 | err = -EROFS; | ||
504 | break; | ||
505 | } | ||
506 | length -= erase->len; | 467 | length -= erase->len; |
507 | if ((err = concat_dev_erase(subdev, erase))) { | 468 | if ((err = concat_dev_erase(subdev, erase))) { |
508 | /* sanity check: should never happen since | 469 | /* sanity check: should never happen since |
@@ -538,9 +499,6 @@ static int concat_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
538 | struct mtd_concat *concat = CONCAT(mtd); | 499 | struct mtd_concat *concat = CONCAT(mtd); |
539 | int i, err = -EINVAL; | 500 | int i, err = -EINVAL; |
540 | 501 | ||
541 | if ((len + ofs) > mtd->size) | ||
542 | return -EINVAL; | ||
543 | |||
544 | for (i = 0; i < concat->num_subdev; i++) { | 502 | for (i = 0; i < concat->num_subdev; i++) { |
545 | struct mtd_info *subdev = concat->subdev[i]; | 503 | struct mtd_info *subdev = concat->subdev[i]; |
546 | uint64_t size; | 504 | uint64_t size; |
@@ -575,9 +533,6 @@ static int concat_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) | |||
575 | struct mtd_concat *concat = CONCAT(mtd); | 533 | struct mtd_concat *concat = CONCAT(mtd); |
576 | int i, err = 0; | 534 | int i, err = 0; |
577 | 535 | ||
578 | if ((len + ofs) > mtd->size) | ||
579 | return -EINVAL; | ||
580 | |||
581 | for (i = 0; i < concat->num_subdev; i++) { | 536 | for (i = 0; i < concat->num_subdev; i++) { |
582 | struct mtd_info *subdev = concat->subdev[i]; | 537 | struct mtd_info *subdev = concat->subdev[i]; |
583 | uint64_t size; | 538 | uint64_t size; |
@@ -650,9 +605,6 @@ static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs) | |||
650 | if (!mtd_can_have_bb(concat->subdev[0])) | 605 | if (!mtd_can_have_bb(concat->subdev[0])) |
651 | return res; | 606 | return res; |
652 | 607 | ||
653 | if (ofs > mtd->size) | ||
654 | return -EINVAL; | ||
655 | |||
656 | for (i = 0; i < concat->num_subdev; i++) { | 608 | for (i = 0; i < concat->num_subdev; i++) { |
657 | struct mtd_info *subdev = concat->subdev[i]; | 609 | struct mtd_info *subdev = concat->subdev[i]; |
658 | 610 | ||
@@ -673,12 +625,6 @@ static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs) | |||
673 | struct mtd_concat *concat = CONCAT(mtd); | 625 | struct mtd_concat *concat = CONCAT(mtd); |
674 | int i, err = -EINVAL; | 626 | int i, err = -EINVAL; |
675 | 627 | ||
676 | if (!mtd_can_have_bb(concat->subdev[0])) | ||
677 | return 0; | ||
678 | |||
679 | if (ofs > mtd->size) | ||
680 | return -EINVAL; | ||
681 | |||
682 | for (i = 0; i < concat->num_subdev; i++) { | 628 | for (i = 0; i < concat->num_subdev; i++) { |
683 | struct mtd_info *subdev = concat->subdev[i]; | 629 | struct mtd_info *subdev = concat->subdev[i]; |
684 | 630 | ||
@@ -716,10 +662,6 @@ static unsigned long concat_get_unmapped_area(struct mtd_info *mtd, | |||
716 | continue; | 662 | continue; |
717 | } | 663 | } |
718 | 664 | ||
719 | /* we've found the subdev over which the mapping will reside */ | ||
720 | if (offset + len > subdev->size) | ||
721 | return (unsigned long) -EINVAL; | ||
722 | |||
723 | return mtd_get_unmapped_area(subdev, len, offset, flags); | 665 | return mtd_get_unmapped_area(subdev, len, offset, flags); |
724 | } | 666 | } |
725 | 667 | ||
@@ -777,16 +719,16 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c | |||
777 | concat->mtd.subpage_sft = subdev[0]->subpage_sft; | 719 | concat->mtd.subpage_sft = subdev[0]->subpage_sft; |
778 | concat->mtd.oobsize = subdev[0]->oobsize; | 720 | concat->mtd.oobsize = subdev[0]->oobsize; |
779 | concat->mtd.oobavail = subdev[0]->oobavail; | 721 | concat->mtd.oobavail = subdev[0]->oobavail; |
780 | if (subdev[0]->writev) | 722 | if (subdev[0]->_writev) |
781 | concat->mtd.writev = concat_writev; | 723 | concat->mtd._writev = concat_writev; |
782 | if (subdev[0]->read_oob) | 724 | if (subdev[0]->_read_oob) |
783 | concat->mtd.read_oob = concat_read_oob; | 725 | concat->mtd._read_oob = concat_read_oob; |
784 | if (subdev[0]->write_oob) | 726 | if (subdev[0]->_write_oob) |
785 | concat->mtd.write_oob = concat_write_oob; | 727 | concat->mtd._write_oob = concat_write_oob; |
786 | if (subdev[0]->block_isbad) | 728 | if (subdev[0]->_block_isbad) |
787 | concat->mtd.block_isbad = concat_block_isbad; | 729 | concat->mtd._block_isbad = concat_block_isbad; |
788 | if (subdev[0]->block_markbad) | 730 | if (subdev[0]->_block_markbad) |
789 | concat->mtd.block_markbad = concat_block_markbad; | 731 | concat->mtd._block_markbad = concat_block_markbad; |
790 | 732 | ||
791 | concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks; | 733 | concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks; |
792 | 734 | ||
@@ -833,8 +775,8 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c | |||
833 | if (concat->mtd.writesize != subdev[i]->writesize || | 775 | if (concat->mtd.writesize != subdev[i]->writesize || |
834 | concat->mtd.subpage_sft != subdev[i]->subpage_sft || | 776 | concat->mtd.subpage_sft != subdev[i]->subpage_sft || |
835 | concat->mtd.oobsize != subdev[i]->oobsize || | 777 | concat->mtd.oobsize != subdev[i]->oobsize || |
836 | !concat->mtd.read_oob != !subdev[i]->read_oob || | 778 | !concat->mtd._read_oob != !subdev[i]->_read_oob || |
837 | !concat->mtd.write_oob != !subdev[i]->write_oob) { | 779 | !concat->mtd._write_oob != !subdev[i]->_write_oob) { |
838 | kfree(concat); | 780 | kfree(concat); |
839 | printk("Incompatible OOB or ECC data on \"%s\"\n", | 781 | printk("Incompatible OOB or ECC data on \"%s\"\n", |
840 | subdev[i]->name); | 782 | subdev[i]->name); |
@@ -849,15 +791,15 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c | |||
849 | concat->num_subdev = num_devs; | 791 | concat->num_subdev = num_devs; |
850 | concat->mtd.name = name; | 792 | concat->mtd.name = name; |
851 | 793 | ||
852 | concat->mtd.erase = concat_erase; | 794 | concat->mtd._erase = concat_erase; |
853 | concat->mtd.read = concat_read; | 795 | concat->mtd._read = concat_read; |
854 | concat->mtd.write = concat_write; | 796 | concat->mtd._write = concat_write; |
855 | concat->mtd.sync = concat_sync; | 797 | concat->mtd._sync = concat_sync; |
856 | concat->mtd.lock = concat_lock; | 798 | concat->mtd._lock = concat_lock; |
857 | concat->mtd.unlock = concat_unlock; | 799 | concat->mtd._unlock = concat_unlock; |
858 | concat->mtd.suspend = concat_suspend; | 800 | concat->mtd._suspend = concat_suspend; |
859 | concat->mtd.resume = concat_resume; | 801 | concat->mtd._resume = concat_resume; |
860 | concat->mtd.get_unmapped_area = concat_get_unmapped_area; | 802 | concat->mtd._get_unmapped_area = concat_get_unmapped_area; |
861 | 803 | ||
862 | /* | 804 | /* |
863 | * Combine the erase block size info of the subdevices: | 805 | * Combine the erase block size info of the subdevices: |