diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 65626c1..98abae8 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -638,6 +638,12 @@ out_si:
  */
 static int io_init(struct ubi_device *ubi)
 {
+	struct ubi_ec_hdr ec_hdr;
+	int ret;
+	loff_t offset;
+	size_t retlen;
+	uint64_t sz, sz_temp;
+
 	if (ubi->mtd->numeraseregions != 0) {
 		/*
 		 * Some flashes have several erase regions. Different regions
@@ -656,13 +662,56 @@ static int io_init(struct ubi_device *ubi)
 		return -EINVAL;
 
 	/*
+	 * Attempt to determine the PEB size of this volume. The
+	 * default is the erase size. If the volume does not have a
+	 * size written, then it is an old volume, and it must be the
+	 * erase size. If the volume reads back FF, then it has not
+	 * been initialized, so use the erase size. Otherwise, if there
+	 * is a non-zero value, use that.
+	 */
+
+	ubi->peb_size = ubi->mtd->erasesize;
+	for (offset = 0; offset < ubi->mtd->size;
+	     offset += ubi->mtd->erasesize) {
+		if (ubi->mtd->block_isbad &&
+		    (*ubi->mtd->block_isbad)(ubi->mtd, offset))
+			continue;
+		ret = ubi->mtd->read(ubi->mtd, offset, sizeof(ec_hdr), &retlen,
+				     (uint8_t *)&ec_hdr);
+		if (ret)
+			continue;
+		if (retlen != sizeof(ec_hdr))
+			continue;
+		if (be32_to_cpu(ec_hdr.magic) != UBI_EC_HDR_MAGIC)
+			break;
+		if (ec_hdr.version > UBI_VERSION)
+			break;
+		if (!ec_hdr.peb_size)
+			break;
+		ubi->peb_size = be32_to_cpu(ec_hdr.peb_size);
+		if (ubi->peb_size % ubi->mtd->erasesize) {
+			ubi_err("peb_size %d is not a multiple of erasesize %d",
+				ubi->peb_size, ubi->mtd->erasesize);
+			return -EINVAL;
+		}
+		sz_temp = offset;
+		if (do_div(sz_temp, ubi->peb_size)) {
+			ubi_err("peb_size %d is not a multiple of offset %llu",
+				ubi->peb_size, offset);
+			return -EINVAL;
+		}
+		break;
+	}
+
+	/*
 	 * Note, in this implementation we support MTD devices with 0x7FFFFFFF
 	 * physical eraseblocks maximum.
 	 */
 
-	ubi->peb_size   = ubi->mtd->erasesize;
-	ubi->peb_count  = mtd_div_by_eb(ubi->mtd->size, ubi->mtd);
-	ubi->flash_size = ubi->mtd->size;
+	sz = ubi->mtd->size;
+	ubi->flash_size = sz;
+	do_div(sz, ubi->peb_size);
+	ubi->peb_count  = sz;
 
 	if (ubi->mtd->block_isbad && ubi->mtd->block_markbad)
 		ubi->bad_allowed = 1;
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 8c1b1c7..aa3fe4c 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -629,19 +629,26 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture)
 int ubi_io_is_bad(const struct ubi_device *ubi, int pnum)
 {
 	struct mtd_info *mtd = ubi->mtd;
+	loff_t offset;
 
 	ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
 
 	if (ubi->bad_allowed) {
-		int ret;
-
-		ret = mtd->block_isbad(mtd, (loff_t)pnum * ubi->peb_size);
-		if (ret < 0)
-			ubi_err("error %d while checking if PEB %d is bad",
-				ret, pnum);
-		else if (ret)
-			dbg_io("PEB %d is bad", pnum);
-		return ret;
+		for (offset = 0; offset < ubi->peb_size;
+		     offset += mtd->erasesize) {
+			int ret;
+
+			ret = mtd->block_isbad(mtd,
+					       (loff_t)pnum * ubi->peb_size +
+					       offset);
+			if (ret < 0)
+				ubi_err("error %d while checking if PEB %d "
+					"is bad",
+					ret, pnum);
+			else if (ret)
+				dbg_io("PEB %d is bad", pnum);
+			return ret;
+		}
 	}
 
 	return 0;
@@ -657,8 +664,9 @@ int ubi_io_is_bad(const struct ubi_device *ubi, int pnum)
  */
 int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum)
 {
-	int err;
+	int err, last_err = 0;
 	struct mtd_info *mtd = ubi->mtd;
+	loff_t offset;
 
 	ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
 
@@ -670,10 +678,15 @@ int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum)
 	if (!ubi->bad_allowed)
 		return 0;
 
-	err = mtd->block_markbad(mtd, (loff_t)pnum * ubi->peb_size);
-	if (err)
-		ubi_err("cannot mark PEB %d bad, error %d", pnum, err);
-	return err;
+	for (offset = 0; offset < ubi->peb_size; offset += mtd->erasesize) {
+		err = mtd->block_markbad(mtd, (loff_t)pnum * ubi->peb_size +
+			offset);
+		if (err) {
+			ubi_err("cannot mark PEB %d bad, error %d", pnum, err);
+			last_err = err;
+		}
+	}
+	return last_err;
 }
 
 /**
@@ -872,6 +885,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
 	ec_hdr->vid_hdr_offset = cpu_to_be32(ubi->vid_hdr_offset);
 	ec_hdr->data_offset = cpu_to_be32(ubi->leb_start);
 	ec_hdr->image_seq = cpu_to_be32(ubi->image_seq);
+	ec_hdr->peb_size = cpu_to_be32(ubi->peb_size);
 	crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
 	ec_hdr->hdr_crc = cpu_to_be32(crc);
 
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index 2135a53..8cc1be6 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -892,6 +892,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
 
 	if (!ec_err) {
 		int image_seq;
+		int peb_size;
 
 		/* Make sure UBI version is OK */
 		if (ech->version != UBI_VERSION) {
@@ -936,6 +937,21 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
 			ubi_dbg_dump_ec_hdr(ech);
 			return -EINVAL;
 		}
+
+		/*
+		 * Make sure that all PEBs have the same PEB size. This
+		 * is a validity check similar in function to the image
+		 * sequence number. As this field was also added after the
+		 * on-FLASH format, a value of zero is acceptable here.
+		 */
+
+		peb_size = be32_to_cpu(ech->peb_size);
+		if (peb_size && (peb_size != ubi->peb_size)) {
+			ubi_err("bad peb size %d in PEB %d, "
+				"expected %d", peb_size, pnum, ubi->peb_size);
+			ubi_dbg_dump_ec_hdr(ech);
+			return -EINVAL;
+		}
 	}
 
 	/* OK, we've done with the EC header, let's look at the VID header */
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index 6fb8ec2..58bece0 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -130,6 +130,7 @@ enum {
  * @vid_hdr_offset: where the VID header starts
  * @data_offset: where the user data start
  * @image_seq: image sequence number
+ * @peb_size: size of PEB, must be multiple of erase size
  * @padding2: reserved for future, zeroes
  * @hdr_crc: erase counter header CRC checksum
  *
@@ -162,7 +163,8 @@ struct ubi_ec_hdr {
 	__be32  vid_hdr_offset;
 	__be32  data_offset;
 	__be32  image_seq;
-	__u8    padding2[32];
+	__be32	peb_size;
+	__u8    padding2[28];
 	__be32  hdr_crc;
 } __packed;
 
