aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJagdish Gediya <jagdish.gediya@nxp.com>2018-03-20 20:21:46 -0400
committerBoris Brezillon <boris.brezillon@bootlin.com>2018-03-21 05:18:34 -0400
commit843c3a59997f18060848b8632607dd04781b52d1 (patch)
tree9fabe393f0ceb368ece5f53242376d1def8391f5
parentfa8e6d58c5bc260f4369c6699683d69695daed0a (diff)
mtd: nand: fsl_ifc: Fix eccstat array overflow for IFC ver >= 2.0.0
Number of ECC status registers i.e. (ECCSTATx) has been increased in IFC version 2.0.0 due to increase in SRAM size. This is causing eccstat array to over flow. So, replace eccstat array with u32 variable to make it fail-safe and independent of number of ECC status registers or SRAM size. Fixes: bccb06c353af ("mtd: nand: ifc: update bufnum mask for ver >= 2.0.0") Cc: stable@vger.kernel.org # 3.18+ Signed-off-by: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com> Signed-off-by: Jagdish Gediya <jagdish.gediya@nxp.com> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-rw-r--r--drivers/mtd/nand/fsl_ifc_nand.c23
1 files changed, 10 insertions, 13 deletions
diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c
index b6a3ba445cfb..fae01b04abc7 100644
--- a/drivers/mtd/nand/fsl_ifc_nand.c
+++ b/drivers/mtd/nand/fsl_ifc_nand.c
@@ -173,14 +173,9 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
173 173
174/* returns nonzero if entire page is blank */ 174/* returns nonzero if entire page is blank */
175static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl, 175static int check_read_ecc(struct mtd_info *mtd, struct fsl_ifc_ctrl *ctrl,
176 u32 *eccstat, unsigned int bufnum) 176 u32 eccstat, unsigned int bufnum)
177{ 177{
178 u32 reg = eccstat[bufnum / 4]; 178 return (eccstat >> ((3 - bufnum % 4) * 8)) & 15;
179 int errors;
180
181 errors = (reg >> ((3 - bufnum % 4) * 8)) & 15;
182
183 return errors;
184} 179}
185 180
186/* 181/*
@@ -193,7 +188,7 @@ static void fsl_ifc_run_command(struct mtd_info *mtd)
193 struct fsl_ifc_ctrl *ctrl = priv->ctrl; 188 struct fsl_ifc_ctrl *ctrl = priv->ctrl;
194 struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl; 189 struct fsl_ifc_nand_ctrl *nctrl = ifc_nand_ctrl;
195 struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs; 190 struct fsl_ifc_runtime __iomem *ifc = ctrl->rregs;
196 u32 eccstat[4]; 191 u32 eccstat;
197 int i; 192 int i;
198 193
199 /* set the chip select for NAND Transaction */ 194 /* set the chip select for NAND Transaction */
@@ -228,8 +223,8 @@ static void fsl_ifc_run_command(struct mtd_info *mtd)
228 if (nctrl->eccread) { 223 if (nctrl->eccread) {
229 int errors; 224 int errors;
230 int bufnum = nctrl->page & priv->bufnum_mask; 225 int bufnum = nctrl->page & priv->bufnum_mask;
231 int sector = bufnum * chip->ecc.steps; 226 int sector_start = bufnum * chip->ecc.steps;
232 int sector_end = sector + chip->ecc.steps - 1; 227 int sector_end = sector_start + chip->ecc.steps - 1;
233 __be32 *eccstat_regs; 228 __be32 *eccstat_regs;
234 229
235 if (ctrl->version >= FSL_IFC_VERSION_2_0_0) 230 if (ctrl->version >= FSL_IFC_VERSION_2_0_0)
@@ -237,10 +232,12 @@ static void fsl_ifc_run_command(struct mtd_info *mtd)
237 else 232 else
238 eccstat_regs = ifc->ifc_nand.v1_nand_eccstat; 233 eccstat_regs = ifc->ifc_nand.v1_nand_eccstat;
239 234
240 for (i = sector / 4; i <= sector_end / 4; i++) 235 eccstat = ifc_in32(&eccstat_regs[sector_start / 4]);
241 eccstat[i] = ifc_in32(&eccstat_regs[i]); 236
237 for (i = sector_start; i <= sector_end; i++) {
238 if (i != sector_start && !(i % 4))
239 eccstat = ifc_in32(&eccstat_regs[i / 4]);
242 240
243 for (i = sector; i <= sector_end; i++) {
244 errors = check_read_ecc(mtd, ctrl, eccstat, i); 241 errors = check_read_ecc(mtd, ctrl, eccstat, i);
245 242
246 if (errors == 15) { 243 if (errors == 15) {