allocate_partition() aligns a partition on the erase size of its master
and checks the offset and the size against it with mtd_mod_by_eb(). A
device which cannot erase has no erase size, so that check divides by
zero, "mtd list" shows
### ERROR ### Please RESET the board ###
Linux aligns the partition of such a device on the write size instead,
see wr_alignment in allocate_partition() in drivers/mtd/mtdpart.c. Do
the same here, and take the alignment for the MTDPART_OFS_NXTBLK
rounding from the same place, which divided by the erase size as well.
Signed-off-by: Heiko Schocher <[email protected]>
---
checkpatch reports two warnings and four checks on the two
printk(KERN_WARNING"mtd: partition ... force read-only\n") lines.
This patch only changes s|erase block|erase/write block in the
string of the print, so ignoring the warnings.
Changes in v2:
- New patch mtd: align a partition on the write size if the device cannot erase
Testing on the board dropped for "mtd list" command:
### ERROR ### Please RESET the board ###
This is because division by erase_size, which the SPI RAM driver
sets to 0. Added for this case also sandbox test.
drivers/mtd/mtdpart.c | 35 ++++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index a3003cf44b0..eed0add71ff 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -563,8 +563,12 @@ static struct mtd_info *allocate_partition(struct mtd_info
*master,
const struct mtd_partition *part,
int partno, uint64_t cur_offset)
{
+ u32 wr_alignment = (master->flags & MTD_NO_ERASE) ? master->writesize :
+ master->erasesize;
struct mtd_info *slave;
+ u32 remainder;
char *name;
+ u64 tmp;
/* allocate the partition structure */
slave = kzalloc(sizeof(*slave), GFP_KERNEL);
@@ -665,9 +669,11 @@ static struct mtd_info *allocate_partition(struct mtd_info
*master,
slave->offset = cur_offset;
if (slave->offset == MTDPART_OFS_NXTBLK) {
slave->offset = cur_offset;
- if (mtd_mod_by_eb(cur_offset, master) != 0) {
- /* Round up to next erasesize */
- slave->offset = (mtd_div_by_eb(cur_offset, master) + 1)
* master->erasesize;
+ tmp = cur_offset;
+ remainder = do_div(tmp, wr_alignment);
+ if (remainder) {
+ /* Round up to the next alignment boundary */
+ slave->offset += wr_alignment - remainder;
debug("Moving partition %d: "
"0x%012llx -> 0x%012llx\n", partno,
(unsigned long long)cur_offset, (unsigned long
long)slave->offset);
@@ -731,19 +737,30 @@ static struct mtd_info *allocate_partition(struct
mtd_info *master,
slave->erasesize = master->erasesize;
}
- if ((slave->flags & MTD_WRITEABLE) &&
- mtd_mod_by_eb(slave->offset, slave)) {
+ /*
+ * The erase size of the partition may differ from the one of the
+ * master if the master exposes several erase regions. Align to the
+ * one the partition ended up with.
+ */
+ if (!(slave->flags & MTD_NO_ERASE))
+ wr_alignment = slave->erasesize;
+
+ tmp = slave->offset;
+ remainder = do_div(tmp, wr_alignment);
+ if ((slave->flags & MTD_WRITEABLE) && remainder) {
/* Doesn't start on a boundary of major erase size */
/* FIXME: Let it be writable if it is on a boundary of
* _minor_ erase size though */
slave->flags &= ~MTD_WRITEABLE;
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an
erase block boundary -- force read-only\n",
+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an
erase/write block boundary -- force read-only\n",
part->name);
}
- if ((slave->flags & MTD_WRITEABLE) &&
- mtd_mod_by_eb(slave->size, slave)) {
+
+ tmp = slave->size;
+ remainder = do_div(tmp, wr_alignment);
+ if ((slave->flags & MTD_WRITEABLE) && remainder) {
slave->flags &= ~MTD_WRITEABLE;
- printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an
erase block -- force read-only\n",
+ printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an
erase/write block -- force read-only\n",
part->name);
}
--
2.55.0