[Skiboot] [PATCH V2 1/7] libflash/ecc: Simplify and cleanup ecc code.

Cyril Bur cyril.bur at au1.ibm.com
Tue Jun 16 19:01:04 AEST 2015


The ecc 'memcpy' style functions return success or fail in terms of the ECC
enum. This doesn't really make sense, use true or false. As the result the
ecc enum doesn't need to be exposed anymore, which makes more sense, not
clear why it was exposed in the first place.

Convert some of the ecc #defines to static inlines, shouldn't make any
difference but feels safer.

Fix minor stylistic and typo issues.

Signed-off-by: Cyril Bur <cyril.bur at au1.ibm.com>
---
 core/flash.c             | 10 +++++-----
 external/gard/gard.c     |  2 +-
 libflash/ecc.c           | 51 +++++++++++++++++++++++++++++++-----------------
 libflash/ecc.h           | 44 +++++++++++++++++++++--------------------
 libflash/libflash.c      | 27 +++++++++++++------------
 libflash/test/test-ecc.c | 16 +++++++--------
 6 files changed, 84 insertions(+), 66 deletions(-)

diff --git a/core/flash.c b/core/flash.c
index 7cd9153..c65aefa 100644
--- a/core/flash.c
+++ b/core/flash.c
@@ -418,7 +418,7 @@ static int flash_find_subpartition(struct blocklevel_device *bl, uint32_t subid,
 	/* Get raw partition size without ECC */
 	partsize = *total_size;
 	if (ecc)
-		partsize = BUFFER_SIZE_MINUS_ECC(*total_size);
+		partsize = ecc_buffer_size_minus_ecc(*total_size);
 
 	/* Get the TOC */
 	rc = flash_read_corrected(bl, *start, header,
@@ -483,8 +483,8 @@ static int flash_find_subpartition(struct blocklevel_device *bl, uint32_t subid,
 		*start += offset;
 		*total_size = size;
 		if (ecc) {
-			*start += ECC_SIZE(offset);
-			*total_size += ECC_SIZE(size);
+			*start += ecc_size(offset);
+			*total_size += ecc_size(size);
 		}
 		rc = 0;
 		goto end;
@@ -577,12 +577,12 @@ static int flash_load_resource(enum resource_id id, uint32_t subid,
 	/* Work out what the final size of buffer will be without ECC */
 	size = part_size;
 	if (ecc) {
-		if ECC_BUFFER_SIZE_CHECK(part_size) {
+		if (ecc_buffer_size_check(part_size)) {
 			prerror("FLASH: %s image invalid size for ECC %d\n",
 				name, part_size);
 			goto out_free_ffs;
 		}
-		size = BUFFER_SIZE_MINUS_ECC(part_size);
+		size = ecc_buffer_size_minus_ecc(part_size);
 	}
 
 	if (size > *len) {
diff --git a/external/gard/gard.c b/external/gard/gard.c
index c43e05a..864c500 100644
--- a/external/gard/gard.c
+++ b/external/gard/gard.c
@@ -63,7 +63,7 @@ struct gard_ctx {
  */
 static inline size_t sizeof_gard(struct gard_ctx *ctx)
 {
-	return ctx->ecc ? ECC_BUFFER_SIZE(sizeof(struct gard_record)) : sizeof(struct gard_record);
+	return ctx->ecc ? ecc_buffer_size(sizeof(struct gard_record)) : sizeof(struct gard_record);
 }
 
 static void show_flash_err(int rc)
diff --git a/libflash/ecc.c b/libflash/ecc.c
index 8ab1f31..b3c49cf 100644
--- a/libflash/ecc.c
+++ b/libflash/ecc.c
@@ -23,6 +23,22 @@
 #include "libflash.h"
 #include "ecc.h"
 
+/* Bit field identifiers for syndrome calculations. */
+enum eccbitfields
+{
+        GD = 0xff,      //< Good, ECC matches.
+        UE = 0xfe,      //< Uncorrectable.
+        E0 = 71,        //< Error in ECC bit 0
+        E1 = 70,        //< Error in ECC bit 1
+        E2 = 69,        //< Error in ECC bit 2
+        E3 = 68,        //< Error in ECC bit 3
+        E4 = 67,        //< Error in ECC bit 4
+        E5 = 66,        //< Error in ECC bit 5
+        E6 = 65,        //< Error in ECC bit 6
+        E7 = 64         //< Error in ECC bit 7
+        /* 0-63 Correctable bit in byte */
+};
+
 /*
  * Matrix used for ECC calculation.
  *
@@ -73,7 +89,7 @@ static uint64_t eccmatrix[] = {
  *
  *  Bits are in MSB order.
  */
-static uint8_t syndromematrix[] = {
+static enum eccbitfields syndromematrix[] = {
         GD, E7, E6, UE, E5, UE, UE, 47, E4, UE, UE, 37, UE, 35, 39, UE,
         E3, UE, UE, 48, UE, 30, 29, UE, UE, 57, 27, UE, 31, UE, UE, UE,
         E2, UE, UE, 17, UE, 18, 40, UE, UE, 58, 22, UE, 21, UE, UE, UE,
@@ -121,7 +137,7 @@ static uint8_t eccgenerate(uint64_t data)
  * @retval UE - Indicates the data is uncorrectable.
  * @retval all others - Indication of which bit is incorrect.
  */
-static uint8_t eccverify(uint64_t data, uint8_t ecc)
+static enum eccbitfields eccverify(uint64_t data, uint8_t ecc)
 {
 	return syndromematrix[eccgenerate(data) ^ ecc];
 }
@@ -142,15 +158,14 @@ static inline uint64_t eccflipbit(uint64_t data, uint8_t bit)
  * @dst:	destination buffer without ECC
  * @src:	source buffer with ECC
  * @len:	number of bytes of data to copy (without ecc).
-                     Must be 8 byte aligned.
+ *                   Must be 8 byte aligned.
  *
- * @return:	eccBitfield or 0-64.
+ * @return:	Success or error
  *
- * @retval GD - Data is good.
- * @retval UE - Data is uncorrectable.
- * @retval all others - which bit was corrected.
+ * @retval: 0 - success
+ * @retfal: other - fail
  */
-uint8_t memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len)
+int memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len)
 {
 	beint64_t data;
 	uint8_t ecc;
@@ -161,7 +176,7 @@ uint8_t memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len)
 		/* TODO: we could probably handle this */
 		FL_ERR("ECC data length must be 8 byte aligned length:%i\n",
 			len);
-		return UE;
+		return -1;
 	}
 
 	/* Handle in chunks of 8 bytes, so adjust the length */
@@ -184,7 +199,7 @@ uint8_t memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len)
 			*dst = (uint64_t)be64_to_cpu(eccflipbit(be64_to_cpu(data), badbit));
 		dst++;
 	}
-	return GD;
+	return 0;
 }
 
 /**
@@ -194,23 +209,23 @@ uint8_t memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len)
  * @src:	source buffer without ECC
  * @len:	number of bytes of data to copy (without ecc, length of src).
  *       Note: dst must be big enough to hold ecc bytes as well.
-                     Must be 8 byte aligned.
+ *                   Must be 8 byte aligned.
  *
- * @return:	eccBitfield.
+ * @return:	success or failure
  *
- * @retval GD - Success.
- * @retval UE - Length is not 8 byte aligned.
+ * @retval: 0 - success
+ * @retfal: other - fail
  */
-uint8_t memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t len)
+int memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t len)
 {
 	struct ecc64 ecc_word;
 	uint32_t i;
 
 	if (len & 0x7) {
-		/* TODO: we could problably handle this */
+		/* TODO: we could probably handle this */
 		FL_ERR("Data to add ECC bytes to must be 8 byte aligned length: %i\n",
 				len);
-		return UE;
+		return -1;
 	}
 
 	/* Handle in chunks of 8 bytes, so adjust the length */
@@ -223,5 +238,5 @@ uint8_t memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t len)
 		*(dst + i) = ecc_word;
 	}
 
-	return GD;
+	return 0;
 }
diff --git a/libflash/ecc.h b/libflash/ecc.h
index d58ec3e..1e14724 100644
--- a/libflash/ecc.h
+++ b/libflash/ecc.h
@@ -22,29 +22,14 @@
 #include <stdint.h>
 #include <ccan/endian/endian.h>
 
-/* Bit field identifiers for syndrome calculations. */
-enum eccbitfields
-{
-        GD = 0xff,      //< Good, ECC matches.
-        UE = 0xfe,      //< Uncorrectable.
-        E0 = 71,        //< Error in ECC bit 0
-        E1 = 70,        //< Error in ECC bit 1
-        E2 = 69,        //< Error in ECC bit 2
-        E3 = 68,        //< Error in ECC bit 3
-        E4 = 67,        //< Error in ECC bit 4
-        E5 = 66,        //< Error in ECC bit 5
-        E6 = 65,        //< Error in ECC bit 6
-        E7 = 64         //< Error in ECC bit 7
-};
-
 struct ecc64 {
 	beint64_t data;
 	uint8_t ecc;
 } __attribute__((__packed__));
 
-extern uint8_t memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len);
+extern int memcpy_from_ecc(uint64_t *dst, struct ecc64 *src, uint32_t len);
 
-extern uint8_t memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t len);
+extern int memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t len);
 
 /*
  * Calculate the size of a buffer if ECC is added
@@ -56,9 +41,26 @@ extern uint8_t memcpy_to_ecc(struct ecc64 *dst, const uint64_t *src, uint32_t le
 #define ALIGN_UP(_v, _a)	(((_v) + (_a) - 1) & ~((_a) - 1))
 #endif
 
-#define ECC_SIZE(len) (ALIGN_UP((len), 8) >> 3)
-#define ECC_BUFFER_SIZE(len) (ALIGN_UP((len), 8) + ECC_SIZE(len))
-#define ECC_BUFFER_SIZE_CHECK(len) ((len) % 9)
-#define BUFFER_SIZE_MINUS_ECC(len) ((len) * 8 / 9)
+#define BYTES_PER_ECC 8
+
+static inline uint32_t ecc_size(uint32_t len)
+{
+	return ALIGN_UP(len, BYTES_PER_ECC) >> 3;
+}
+
+static inline uint32_t ecc_buffer_size(uint32_t len)
+{
+	return ALIGN_UP(len, BYTES_PER_ECC) + ecc_size(len);
+}
+
+static inline int ecc_buffer_size_check(uint32_t len)
+{
+	return len % (BYTES_PER_ECC + 1);
+}
+
+static inline uint32_t ecc_buffer_size_minus_ecc(uint32_t len)
+{
+	return len * BYTES_PER_ECC / (BYTES_PER_ECC + 1);
+}
 
 #endif
diff --git a/libflash/libflash.c b/libflash/libflash.c
index e7b3c8e..a142e17 100644
--- a/libflash/libflash.c
+++ b/libflash/libflash.c
@@ -153,7 +153,7 @@ int flash_read_corrected(struct blocklevel_device *bl, uint32_t pos, void *buf,
 		return flash_read(bl, pos, buf, len);
 
 	/* Copy the buffer in chunks */
-	bufecc = malloc(ECC_BUFFER_SIZE(COPY_BUFFER_LENGTH));
+	bufecc = malloc(ecc_buffer_size(COPY_BUFFER_LENGTH));
 	if (!bufecc)
 		return FLASH_ERR_MALLOC_FAILED;
 
@@ -162,13 +162,13 @@ int flash_read_corrected(struct blocklevel_device *bl, uint32_t pos, void *buf,
 		copylen = MIN(len, COPY_BUFFER_LENGTH);
 
 		/* Read ECCed data from flash */
-		rc = flash_read(bl, pos, bufecc, ECC_BUFFER_SIZE(copylen));
+		rc = flash_read(bl, pos, bufecc, ecc_buffer_size(copylen));
 		if (rc)
 			goto err;
 
 		/* Extract data from ECCed data */
 		ret = memcpy_from_ecc(buf, bufecc, copylen);
-		if (ret == UE) {
+		if (ret) {
 			rc = FLASH_ERR_ECC_INVALID;
 			goto err;
 		}
@@ -176,7 +176,7 @@ int flash_read_corrected(struct blocklevel_device *bl, uint32_t pos, void *buf,
 		/* Update for next copy */
 		len -= copylen;
 		buf = (uint8_t *)buf + copylen;
-		pos += ECC_BUFFER_SIZE(copylen);
+		pos += ecc_buffer_size(copylen);
 	}
 
 	rc = 0;
@@ -397,7 +397,7 @@ int flash_write_corrected(struct blocklevel_device *bl, uint32_t pos, const void
 		uint32_t len, bool verify, bool ecc)
 {
 	struct ecc64 *bufecc;
-	uint32_t copylen;
+	uint32_t copylen, copylen_minus_ecc;
 	int rc;
 	uint8_t ret;
 
@@ -405,17 +405,18 @@ int flash_write_corrected(struct blocklevel_device *bl, uint32_t pos, const void
 		return flash_write(bl, pos, buf, len, verify);
 
 	/* Copy the buffer in chunks */
-	bufecc = malloc(ECC_BUFFER_SIZE(COPY_BUFFER_LENGTH));
+	bufecc = malloc(ecc_buffer_size(COPY_BUFFER_LENGTH));
 	if (!bufecc)
 		return FLASH_ERR_MALLOC_FAILED;
 
 	while (len > 0) {
 		/* What's left to copy? */
 		copylen = MIN(len, COPY_BUFFER_LENGTH);
+		copylen_minus_ecc = ecc_buffer_size_minus_ecc(copylen);
 
 		/* Add the ecc byte to the data */
-		ret = memcpy_to_ecc(bufecc, buf, BUFFER_SIZE_MINUS_ECC(copylen));
-		if (ret == UE) {
+		ret = memcpy_to_ecc(bufecc, buf, copylen_minus_ecc);
+		if (ret) {
 			rc = FLASH_ERR_ECC_INVALID;
 			goto err;
 		}
@@ -426,8 +427,8 @@ int flash_write_corrected(struct blocklevel_device *bl, uint32_t pos, const void
 			goto err;
 
 		/* Update for next copy */
-		len -= BUFFER_SIZE_MINUS_ECC(copylen);
-		buf = (uint8_t *)buf + BUFFER_SIZE_MINUS_ECC(copylen);
+		len -= copylen_minus_ecc;
+		buf = (uint8_t *)buf + copylen_minus_ecc;
 		pos += copylen;
 	}
 
@@ -554,17 +555,17 @@ int flash_smart_write_corrected(struct blocklevel_device *bl, uint32_t dst, cons
 	if (!ecc)
 		return flash_smart_write(bl, dst, src, size);
 
-	buf = malloc(ECC_BUFFER_SIZE(size));
+	buf = malloc(ecc_buffer_size(size));
 	if (!buf)
 		return FLASH_ERR_MALLOC_FAILED;
 
 	rc = memcpy_to_ecc(buf, src, size);
-	if (rc != GD) {
+	if (rc) {
 		rc = FLASH_ERR_ECC_INVALID;
 		goto out;
 	}
 
-	rc = flash_smart_write(bl, dst, buf, ECC_BUFFER_SIZE(size));
+	rc = flash_smart_write(bl, dst, buf, ecc_buffer_size(size));
 
 out:
 	free(buf);
diff --git a/libflash/test/test-ecc.c b/libflash/test/test-ecc.c
index 8bbce9d..9d5a43a 100644
--- a/libflash/test/test-ecc.c
+++ b/libflash/test/test-ecc.c
@@ -389,7 +389,7 @@ int main(void)
 	printf("Testing bitflip recovery\n");
 	for (i = 0; i < 64; i++) {
 		ret_memcpy = memcpy_from_ecc(&dst, &ecc_data[i], 8);
-		if (dst != 0xffffffffffffffff || ret_memcpy != GD) {
+		if (dst != 0xffffffffffffffff || ret_memcpy) {
 			ERR("ECC code didn't correct bad bit %d in 0x%016lx\n", 63 - i, be64toh(ecc_data[i].data));
 			exit(1);
 		}
@@ -412,7 +412,7 @@ int main(void)
 	/* Test a large memcpy */
 	printf("Testing a large(ish) memcpy_from_ecc()\n");
 	ret_memcpy = memcpy_from_ecc(buf, ecc_data, NUM_ECC_ROWS * sizeof(*buf));
-	if (ret_memcpy != GD) {
+	if (ret_memcpy) {
 		ERR("ECC Couldn't memcpy entire buffer\n");
 		exit(1);
 	}
@@ -436,14 +436,14 @@ int main(void)
 
 	/* Test a memcpy to add ecc data */
 	printf("Testing a large(ish) memcpy_to_ecc()\n");
-	ret_buf = malloc(ECC_BUFFER_SIZE(NUM_ECC_ROWS * sizeof(*buf)));
+	ret_buf = malloc(ecc_buffer_size(NUM_ECC_ROWS * sizeof(*buf)));
 	if (!buf) {
 		ERR("malloc #2 failed during ecc test\n");
 		exit(1);
 	}
 
 	ret_memcpy = memcpy_to_ecc(ret_buf, buf, NUM_ECC_ROWS * sizeof(*buf));
-	if (ret_memcpy != GD) {
+	if (ret_memcpy) {
 		ERR("ECC Couldn't memcpy entire buffer\n");
 		exit(1);
 	}
@@ -466,20 +466,20 @@ int main(void)
 	printf("ECC tests pass\n");
 
 	printf("ECC test error conditions\n");
-	if (memcpy_to_ecc(ret_buf, buf, 7) != UE) {
+	if (memcpy_to_ecc(ret_buf, buf, 7) == 0) {
 		ERR("memcpy_to_ecc didn't detect bad size 7\n");
 		exit(1);
 	}
 
-	if (memcpy_to_ecc(ret_buf, buf, 15) != UE) {
+	if (memcpy_to_ecc(ret_buf, buf, 15) == 0) {
 		ERR("memcpy_to_ecc didn't detect bad size 15\n");
 		exit(1);
 	}
-	if (memcpy_from_ecc(buf, ret_buf, 7) != UE) {
+	if (memcpy_from_ecc(buf, ret_buf, 7) == 0) {
 		ERR("memcpy_from_ecc didn't detect bad size 7\n");
 		exit(1);
 	}
-	if (memcpy_from_ecc(buf, ret_buf, 15) != UE) {
+	if (memcpy_from_ecc(buf, ret_buf, 15) == 0) {
 		ERR("memcpy_from_ecc didn't detect bad size 15\n");
 		exit(1);
 	}
-- 
2.4.3



More information about the Skiboot mailing list