[][OpenWrt Dev][nmbm: update the mtd wrapper due to lower read page API changed]
[Description]
Change the lower API of read page, to meet the requirement of the NMBN core.
Change the upper API of read, to meet the requirement of the MTD framework.
[Release-log]
N/A
Change-Id: I398098b522f315b2b90ae8e08a9d909ba342c518
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/4649345
diff --git a/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-mtd.c b/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-mtd.c
index 85dab65..a3e9e18 100644
--- a/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-mtd.c
+++ b/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-mtd.c
@@ -84,12 +84,24 @@
nm->upper.ecc_stats.corrected = nm->lower->ecc_stats.corrected;
nm->upper.ecc_stats.failed = nm->lower->ecc_stats.failed;
- if (ret == -EBADMSG)
- return 1;
-
- if (ret && ret != -EUCLEAN)
+ /* Report error on failure (including ecc error) */
+ if (ret < 0 && ret != -EUCLEAN)
return ret;
+ /*
+ * Since mtd_read_oob() won't report exact bitflips, what we can know
+ * is whether bitflips exceeds the threshold.
+ * We want the -EUCLEAN to be passed to the upper layer, but not the
+ * error value itself. To achieve this, report bitflips above the
+ * threshold.
+ */
+
+ if (ret == -EUCLEAN) {
+ return min_t(u32, nm->lower->bitflip_threshold + 1,
+ nm->lower->ecc_strength);
+ }
+
+ /* For bitflips less than the threshold, return 0 */
return 0;
}
@@ -251,7 +263,8 @@
size_t len, ooblen, maxooblen, chklen;
uint32_t col, ooboffs;
uint8_t *datcache, *oobcache;
- int ret;
+ bool has_ecc_err = false;
+ int ret, max_bitflips = 0;
col = addr & nm->lower->writesize_mask;
addr &= ~nm->lower->writesize_mask;
@@ -269,11 +282,16 @@
while (len || ooblen) {
ret = nmbm_read_single_page(nm->ni, addr, datcache, oobcache,
mode);
- if (ret) {
- if (ret > 0)
- return -EBADMSG;
- return -EIO;
- }
+ if (ret < 0 && ret != -EBADMSG)
+ return ret;
+
+ /* Continue reading on ecc error */
+ if (ret == -EBADMSG)
+ has_ecc_err = true;
+
+ /* Record the maximum bitflips between pages */
+ if (ret > max_bitflips)
+ max_bitflips = ret;
if (len) {
/* Move data */
@@ -304,7 +322,10 @@
addr += nm->lower->writesize;
}
- return 0;
+ if (has_ecc_err)
+ return -EBADMSG;
+
+ return max_bitflips;
}
static int nmbm_mtd_read_oob(struct mtd_info *mtd, loff_t from,
@@ -355,12 +376,7 @@
nmbm_release_device(nm);
- if (ret > 0)
- return -EBADMSG;
- else if (ret)
- return -EIO;
-
- return 0;
+ return ret;
}
if (unlikely(ops->ooboffs >= maxooblen)) {
@@ -557,11 +573,11 @@
{
struct device_node *mtd_np, *np = pdev->dev.of_node;
uint32_t max_ratio, max_reserved_blocks, alloc_size;
+ bool forced_create, empty_page_ecc_ok;
struct nmbm_lower_device nld;
struct mtd_info *lower, *mtd;
struct nmbm_mtd *nm;
const char *mtdname;
- bool forced_create;
int ret;
mtd_np = of_parse_phandle(np, "lower-mtd-device", 0);
@@ -594,10 +610,19 @@
max_reserved_blocks = NMBM_MAX_BLOCKS_DEFAULT;
forced_create = of_property_read_bool(np, "forced-create");
+ empty_page_ecc_ok = of_property_read_bool(np,
+ "empty-page-ecc-protected");
memset(&nld, 0, sizeof(nld));
+ nld.flags = 0;
+
+ if (forced_create)
+ nld.flags |= NMBM_F_CREATE;
+
+ if (empty_page_ecc_ok)
+ nld.flags |= NMBM_F_EMPTY_PAGE_ECC_OK;
+
- nld.flags = forced_create ? NMBM_F_CREATE : 0;
nld.max_ratio = max_ratio;
nld.max_reserved_blocks = max_reserved_blocks;