[][OpenWrt Dev][nmbm: change the api of reading page from lower device]

[Description]
Change the return value of the lower read page API to make
sure bitflip information can be passed to upper layer.

The return value of reading page now is:
0 for success, positive for corrected bitflip(s),
-EBADMSG for uncorrectable bitflips, other positive for error

[Release-log]
N/A

Change-Id: I9657e6b07abe6c130ccd5e1670ed247e1a0c83db
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/4649342
diff --git a/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c b/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c
index 8bbef3f..16a2d01 100644
--- a/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c
+++ b/target/linux/generic/files-5.4/drivers/mtd/nmbm/nmbm-core.c
@@ -200,8 +200,8 @@
  *
  * Read a page for at most NMBM_TRY_COUNT times.
  *
- * Return 0 for success, positive value for ecc error,
- * negative value for other errors
+ * Return 0 for success, positive value for corrected bitflip count,
+ * -EBADMSG for ecc error, other negative values for other errors
  */
 static int nmbm_read_phys_page(struct nmbm_instance *ni, uint64_t addr,
 			       void *data, void *oob, enum nmbm_oob_mode mode)
@@ -210,13 +210,13 @@
 
 	for (tries = 0; tries < NMBM_TRY_COUNT; tries++) {
 		ret = ni->lower.read_page(ni->lower.arg, addr, data, oob, mode);
-		if (!ret)
-			return 0;
+		if (ret >= 0)
+			return ret;
 
 		nmbm_reset_chip(ni);
 	}
 
-	if (ret < 0)
+	if (ret != -EBADMSG)
 		nlog_err(ni, "Page read failed at address 0x%08llx\n", addr);
 
 	return ret;
@@ -292,7 +292,7 @@
 	ret = nmbm_read_phys_page(ni, addr, NULL,
 				  ni->page_cache + ni->lower.writesize,
 				  NMBM_MODE_RAW);
-	if (ret < 0)
+	if (ret < 0 && ret != -EBADMSG)
 		return true;
 
 	return ni->page_cache[ni->lower.writesize] != 0xff;
@@ -699,7 +699,7 @@
 		/* Verify the data just written. ECC error indicates failure */
 		ret = nmbm_read_phys_page(ni, addr + off, ni->page_cache, NULL,
 					  NMBM_MODE_PLACE_OOB);
-		if (ret)
+		if (ret < 0)
 			return false;
 
 		if (memcmp(ni->page_cache, data, size))
@@ -772,8 +772,8 @@
  * Read data range.
  * Every page will be tried for at most NMBM_TRY_COUNT times.
  *
- * Return 0 for success, positive value for ecc error,
- * negative value for other errors
+ * Return 0 for success, positive value for corrected bitflip count,
+ * -EBADMSG for ecc error, other negative values for other errors
  */
 static int nmbn_read_data(struct nmbm_instance *ni, uint64_t addr, void *data,
 			  uint32_t size)
@@ -794,13 +794,13 @@
 		if (chunksize == ni->lower.writesize) {
 			ret = nmbm_read_phys_page(ni, off - leading, ptr, NULL,
 						  NMBM_MODE_PLACE_OOB);
-			if (ret)
+			if (ret < 0)
 				return ret;
 		} else {
 			ret = nmbm_read_phys_page(ni, off - leading,
 						  ni->page_cache, NULL,
 						  NMBM_MODE_PLACE_OOB);
-			if (ret)
+			if (ret < 0)
 				return ret;
 
 			memcpy(ptr, ni->page_cache + leading, chunksize);
@@ -854,7 +854,7 @@
 		/* Verify the data just written. ECC error indicates failure */
 		ret = nmbm_read_phys_page(ni, off - leading, ni->page_cache,
 					  NULL, NMBM_MODE_PLACE_OOB);
-		if (ret)
+		if (ret < 0)
 			return false;
 
 		if (memcmp(ni->page_cache + leading, ptr, chunksize))
@@ -2439,6 +2439,9 @@
  * @data: buffer to store main data. optional.
  * @oob: buffer to store oob data. optional.
  * @mode: read mode
+ *
+ * Return 0 for success, positive value for corrected bitflip count,
+ * -EBADMSG for ecc error, other negative values for other errors
  */
 static int nmbm_read_logic_page(struct nmbm_instance *ni, uint64_t addr,
 				void *data, void *oob, enum nmbm_oob_mode mode)
@@ -2468,12 +2471,8 @@
 	paddr = ba2addr(ni, pb) + offset;
 
 	ret = nmbm_read_phys_page(ni, paddr, data, oob, mode);
-	if (!ret)
-		return 0;
-
-	/* For ECC error, return positive value only */
-	if (ret > 0)
-		return 1;
+	if (ret >= 0 || ret == -EBADMSG)
+		return ret;
 
 	/*
 	 * Do not remap bad block here. Just mark this block in state table.
@@ -2482,7 +2481,7 @@
 	nmbm_set_block_state(ni, pb, BLOCK_ST_NEED_REMAP);
 	nmbm_update_info_table(ni);
 
-	return -EIO;
+	return ret;
 }
 
 /*
@@ -2492,6 +2491,9 @@
  * @data: buffer to store main data. optional.
  * @oob: buffer to store oob data. optional.
  * @mode: read mode
+ *
+ * Return 0 for success, positive value for corrected bitflip count,
+ * -EBADMSG for ecc error, other negative values for other errors
  */
 int nmbm_read_single_page(struct nmbm_instance *ni, uint64_t addr, void *data,
 			  void *oob, enum nmbm_oob_mode mode)
@@ -2521,6 +2523,9 @@
  * @data: buffer to store main data to be read
  * @mode: read mode
  * @retlen: return actual data size read
+ *
+ * Return 0 for success, positive value for corrected bitflip count,
+ * -EBADMSG for ecc error, other negative values for other errors
  */
 int nmbm_read_range(struct nmbm_instance *ni, uint64_t addr, size_t size,
 		    void *data, enum nmbm_oob_mode mode, size_t *retlen)
@@ -2528,7 +2533,8 @@
 	uint64_t off = addr;
 	uint8_t *ptr = data;
 	size_t sizeremain = size, chunksize, leading;
-	int ret;
+	bool has_ecc_err = false;
+	int ret, max_bitflips = 0;
 
 	if (!ni)
 		return -EINVAL;
@@ -2565,18 +2571,24 @@
 		if (chunksize == ni->lower.writesize) {
 			ret = nmbm_read_logic_page(ni, off - leading, ptr,
 							NULL, mode);
-			if (ret)
+			if (ret < 0 && ret != -EBADMSG)
 				break;
 		} else {
 			ret = nmbm_read_logic_page(ni, off - leading,
 							ni->page_cache, NULL,
 							mode);
-			if (ret)
+			if (ret < 0 && ret != -EBADMSG)
 				break;
 
 			memcpy(ptr, ni->page_cache + leading, chunksize);
 		}
 
+		if (ret == -EBADMSG)
+			has_ecc_err = true;
+
+		if (ret > max_bitflips)
+			max_bitflips = ret;
+
 		off += chunksize;
 		ptr += chunksize;
 		sizeremain -= chunksize;
@@ -2585,7 +2597,13 @@
 	if (retlen)
 		*retlen = size - sizeremain;
 
-	return ret;
+	if (ret < 0 && ret != -EBADMSG)
+		return ret;
+
+	if (has_ecc_err)
+		return -EBADMSG;
+
+	return max_bitflips;
 }
 
 /*