Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mtd: nand: teach write_page and write_page_raw return an error code

There is an implemention of hardware ECC write page function which may return an
error indication.
For instance, using Atmel HW PMECC to write one page into a nand flash, the hardware
engine will compute the BCH ecc code for this page. so we need read a the
status register to theck whether the ecc code is generated.
But we cannot assume the status register always can be ready, for example,
incorrect hardware configuration or hardware issue, in such case we need
write_page() to return a error code.

Since the definition of 'write_page' function in struct nand_ecc_ctrl is 'void'.
So this patch will:
1. add return 'int' value for 'write_page' function.
2. to be consitent, add return 'int' value for 'write_page_raw' fuctions too.
3. add code to test the return value, and if negative, indicate an
error happend when write page with ECC.
4. fix the compile warning in all impacted nand flash driver.

Note: I couldn't compile-test all of these easily, as some had ARCH dependencies.

Signed-off-by: Josh Wu <josh.wu@atmel.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

authored by

Josh Wu and committed by
David Woodhouse
fdbad98d 3dfe41a4

+64 -31
+4 -2
drivers/mtd/nand/bcm_umi_bch.c
··· 23 23 /* ---- Private Function Prototypes -------------------------------------- */ 24 24 static int bcm_umi_bch_read_page_hwecc(struct mtd_info *mtd, 25 25 struct nand_chip *chip, uint8_t *buf, int oob_required, int page); 26 - static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, 26 + static int bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, 27 27 struct nand_chip *chip, const uint8_t *buf, int oob_required); 28 28 29 29 /* ---- Private Variables ------------------------------------------------ */ ··· 194 194 * @oob_required: must write chip->oob_poi to OOB 195 195 * 196 196 ***************************************************************************/ 197 - static void bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, 197 + static int bcm_umi_bch_write_page_hwecc(struct mtd_info *mtd, 198 198 struct nand_chip *chip, const uint8_t *buf, int oob_required) 199 199 { 200 200 int sectorIdx = 0; ··· 214 214 } 215 215 216 216 bcm_umi_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); 217 + 218 + return 0; 217 219 }
+4 -2
drivers/mtd/nand/bf5xx_nand.c
··· 566 566 return 0; 567 567 } 568 568 569 - static void bf5xx_nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, 570 - const uint8_t *buf, int oob_required) 569 + static int bf5xx_nand_write_page_raw(struct mtd_info *mtd, 570 + struct nand_chip *chip, const uint8_t *buf, int oob_required) 571 571 { 572 572 bf5xx_nand_write_buf(mtd, buf, mtd->writesize); 573 573 bf5xx_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize); 574 + 575 + return 0; 574 576 } 575 577 576 578 /*
+8 -3
drivers/mtd/nand/cafe_nand.c
··· 520 520 }; 521 521 522 522 523 - static void cafe_nand_write_page_lowlevel(struct mtd_info *mtd, 523 + static int cafe_nand_write_page_lowlevel(struct mtd_info *mtd, 524 524 struct nand_chip *chip, 525 525 const uint8_t *buf, int oob_required) 526 526 { ··· 531 531 532 532 /* Set up ECC autogeneration */ 533 533 cafe->ctl2 |= (1<<30); 534 + 535 + return 0; 534 536 } 535 537 536 538 static int cafe_nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, ··· 544 542 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); 545 543 546 544 if (unlikely(raw)) 547 - chip->ecc.write_page_raw(mtd, chip, buf, oob_required); 545 + status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required); 548 546 else 549 - chip->ecc.write_page(mtd, chip, buf, oob_required); 547 + status = chip->ecc.write_page(mtd, chip, buf, oob_required); 548 + 549 + if (status < 0) 550 + return status; 550 551 551 552 /* 552 553 * Cached progamming disabled for now, Not sure if its worth the
+7 -5
drivers/mtd/nand/denali.c
··· 1028 1028 1029 1029 /* writes a page. user specifies type, and this function handles the 1030 1030 * configuration details. */ 1031 - static void write_page(struct mtd_info *mtd, struct nand_chip *chip, 1031 + static int write_page(struct mtd_info *mtd, struct nand_chip *chip, 1032 1032 const uint8_t *buf, bool raw_xfer) 1033 1033 { 1034 1034 struct denali_nand_info *denali = mtd_to_denali(mtd); ··· 1078 1078 1079 1079 denali_enable_dma(denali, false); 1080 1080 dma_sync_single_for_cpu(denali->dev, addr, size, DMA_TO_DEVICE); 1081 + 1082 + return 0; 1081 1083 } 1082 1084 1083 1085 /* NAND core entry points */ ··· 1088 1086 * writing a page with ECC or without is similar, all the work is done 1089 1087 * by write_page above. 1090 1088 * */ 1091 - static void denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, 1089 + static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, 1092 1090 const uint8_t *buf, int oob_required) 1093 1091 { 1094 1092 /* for regular page writes, we let HW handle all the ECC 1095 1093 * data written to the device. */ 1096 - write_page(mtd, chip, buf, false); 1094 + return write_page(mtd, chip, buf, false); 1097 1095 } 1098 1096 1099 1097 /* This is the callback that the NAND core calls to write a page without ECC. 1100 1098 * raw access is similar to ECC page writes, so all the work is done in the 1101 1099 * write_page() function above. 1102 1100 */ 1103 - static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, 1101 + static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, 1104 1102 const uint8_t *buf, int oob_required) 1105 1103 { 1106 1104 /* for raw page writes, we want to disable ECC and simply write 1107 1105 whatever data is in the buffer. */ 1108 - write_page(mtd, chip, buf, true); 1106 + return write_page(mtd, chip, buf, true); 1109 1107 } 1110 1108 1111 1109 static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip,
+5 -3
drivers/mtd/nand/docg4.c
··· 898 898 write_nop(docptr); 899 899 } 900 900 901 - static void write_page(struct mtd_info *mtd, struct nand_chip *nand, 901 + static int write_page(struct mtd_info *mtd, struct nand_chip *nand, 902 902 const uint8_t *buf, bool use_ecc) 903 903 { 904 904 struct docg4_priv *doc = nand->priv; ··· 950 950 write_nop(docptr); 951 951 writew(0, docptr + DOC_DATAEND); 952 952 write_nop(docptr); 953 + 954 + return 0; 953 955 } 954 956 955 - static void docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand, 957 + static int docg4_write_page_raw(struct mtd_info *mtd, struct nand_chip *nand, 956 958 const uint8_t *buf, int oob_required) 957 959 { 958 960 return write_page(mtd, nand, buf, false); 959 961 } 960 962 961 - static void docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand, 963 + static int docg4_write_page(struct mtd_info *mtd, struct nand_chip *nand, 962 964 const uint8_t *buf, int oob_required) 963 965 { 964 966 return write_page(mtd, nand, buf, true);
+3 -1
drivers/mtd/nand/fsl_elbc_nand.c
··· 766 766 /* ECC will be calculated automatically, and errors will be detected in 767 767 * waitfunc. 768 768 */ 769 - static void fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, 769 + static int fsl_elbc_write_page(struct mtd_info *mtd, struct nand_chip *chip, 770 770 const uint8_t *buf, int oob_required) 771 771 { 772 772 fsl_elbc_write_buf(mtd, buf, mtd->writesize); 773 773 fsl_elbc_write_buf(mtd, chip->oob_poi, mtd->oobsize); 774 + 775 + return 0; 774 776 } 775 777 776 778 static int fsl_elbc_chip_init(struct fsl_elbc_mtd *priv)
+3 -1
drivers/mtd/nand/fsl_ifc_nand.c
··· 721 721 /* ECC will be calculated automatically, and errors will be detected in 722 722 * waitfunc. 723 723 */ 724 - static void fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, 724 + static int fsl_ifc_write_page(struct mtd_info *mtd, struct nand_chip *chip, 725 725 const uint8_t *buf, int oob_required) 726 726 { 727 727 fsl_ifc_write_buf(mtd, buf, mtd->writesize); 728 728 fsl_ifc_write_buf(mtd, chip->oob_poi, mtd->oobsize); 729 + 730 + return 0; 729 731 } 730 732 731 733 static int fsl_ifc_chip_init_tail(struct mtd_info *mtd)
+4 -2
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
··· 930 930 return ret; 931 931 } 932 932 933 - static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, 933 + static int gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip, 934 934 const uint8_t *buf, int oob_required) 935 935 { 936 936 struct gpmi_nand_data *this = chip->priv; ··· 972 972 &payload_virt, &payload_phys); 973 973 if (ret) { 974 974 pr_err("Inadequate payload DMA buffer\n"); 975 - return; 975 + return 0; 976 976 } 977 977 978 978 ret = send_page_prepare(this, ··· 1002 1002 nfc_geo->payload_size, 1003 1003 payload_virt, payload_phys); 1004 1004 } 1005 + 1006 + return 0; 1005 1007 } 1006 1008 1007 1009 /*
+19 -8
drivers/mtd/nand/nand_base.c
··· 1911 1911 * 1912 1912 * Not for syndrome calculating ECC controllers, which use a special oob layout. 1913 1913 */ 1914 - static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, 1914 + static int nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, 1915 1915 const uint8_t *buf, int oob_required) 1916 1916 { 1917 1917 chip->write_buf(mtd, buf, mtd->writesize); 1918 1918 if (oob_required) 1919 1919 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 1920 + 1921 + return 0; 1920 1922 } 1921 1923 1922 1924 /** ··· 1930 1928 * 1931 1929 * We need a special oob layout and handling even when ECC isn't checked. 1932 1930 */ 1933 - static void nand_write_page_raw_syndrome(struct mtd_info *mtd, 1931 + static int nand_write_page_raw_syndrome(struct mtd_info *mtd, 1934 1932 struct nand_chip *chip, 1935 1933 const uint8_t *buf, int oob_required) 1936 1934 { ··· 1960 1958 size = mtd->oobsize - (oob - chip->oob_poi); 1961 1959 if (size) 1962 1960 chip->write_buf(mtd, oob, size); 1961 + 1962 + return 0; 1963 1963 } 1964 1964 /** 1965 1965 * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function ··· 1970 1966 * @buf: data buffer 1971 1967 * @oob_required: must write chip->oob_poi to OOB 1972 1968 */ 1973 - static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, 1969 + static int nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, 1974 1970 const uint8_t *buf, int oob_required) 1975 1971 { 1976 1972 int i, eccsize = chip->ecc.size; ··· 1987 1983 for (i = 0; i < chip->ecc.total; i++) 1988 1984 chip->oob_poi[eccpos[i]] = ecc_calc[i]; 1989 1985 1990 - chip->ecc.write_page_raw(mtd, chip, buf, 1); 1986 + return chip->ecc.write_page_raw(mtd, chip, buf, 1); 1991 1987 } 1992 1988 1993 1989 /** ··· 1997 1993 * @buf: data buffer 1998 1994 * @oob_required: must write chip->oob_poi to OOB 1999 1995 */ 2000 - static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, 1996 + static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, 2001 1997 const uint8_t *buf, int oob_required) 2002 1998 { 2003 1999 int i, eccsize = chip->ecc.size; ··· 2017 2013 chip->oob_poi[eccpos[i]] = ecc_calc[i]; 2018 2014 2019 2015 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 2016 + 2017 + return 0; 2020 2018 } 2021 2019 2022 2020 /** ··· 2031 2025 * The hw generator calculates the error syndrome automatically. Therefore we 2032 2026 * need a special oob layout and handling. 2033 2027 */ 2034 - static void nand_write_page_syndrome(struct mtd_info *mtd, 2028 + static int nand_write_page_syndrome(struct mtd_info *mtd, 2035 2029 struct nand_chip *chip, 2036 2030 const uint8_t *buf, int oob_required) 2037 2031 { ··· 2065 2059 i = mtd->oobsize - (oob - chip->oob_poi); 2066 2060 if (i) 2067 2061 chip->write_buf(mtd, oob, i); 2062 + 2063 + return 0; 2068 2064 } 2069 2065 2070 2066 /** ··· 2088 2080 chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); 2089 2081 2090 2082 if (unlikely(raw)) 2091 - chip->ecc.write_page_raw(mtd, chip, buf, oob_required); 2083 + status = chip->ecc.write_page_raw(mtd, chip, buf, oob_required); 2092 2084 else 2093 - chip->ecc.write_page(mtd, chip, buf, oob_required); 2085 + status = chip->ecc.write_page(mtd, chip, buf, oob_required); 2086 + 2087 + if (status < 0) 2088 + return status; 2094 2089 2095 2090 /* 2096 2091 * Cached progamming disabled for now. Not sure if it's worth the
+3 -1
drivers/mtd/nand/pxa3xx_nand.c
··· 681 681 info->state = STATE_IDLE; 682 682 } 683 683 684 - static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, 684 + static int pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, 685 685 struct nand_chip *chip, const uint8_t *buf, int oob_required) 686 686 { 687 687 chip->write_buf(mtd, buf, mtd->writesize); 688 688 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 689 + 690 + return 0; 689 691 } 690 692 691 693 static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
+2 -1
drivers/mtd/nand/sh_flctl.c
··· 399 399 return 0; 400 400 } 401 401 402 - static void flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, 402 + static int flctl_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, 403 403 const uint8_t *buf, int oob_required) 404 404 { 405 405 chip->write_buf(mtd, buf, mtd->writesize); 406 406 chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); 407 + return 0; 407 408 } 408 409 409 410 static void execmd_read_page_sector(struct mtd_info *mtd, int page_addr)
+2 -2
include/linux/mtd/nand.h
··· 355 355 uint8_t *calc_ecc); 356 356 int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, 357 357 uint8_t *buf, int oob_required, int page); 358 - void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, 358 + int (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip, 359 359 const uint8_t *buf, int oob_required); 360 360 int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip, 361 361 uint8_t *buf, int oob_required, int page); 362 362 int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip, 363 363 uint32_t offs, uint32_t len, uint8_t *buf); 364 - void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, 364 + int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip, 365 365 const uint8_t *buf, int oob_required); 366 366 int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, 367 367 int page);