From mboxrd@z Thu Jan 1 00:00:00 1970 From: Roger Quadros To: Subject: [PATCH] mtd: nand: Prevent possible kernel lockup in nand_command() Date: Mon, 23 Feb 2015 17:26:39 +0200 Message-ID: <1424705199-11337-1-git-send-email-rogerq@ti.com> MIME-Version: 1.0 Content-Type: text/plain Cc: nm@ti.com, nsekhar@ti.com, linux-kernel@vger.kernel.org, linux-mtd@lists.infradead.org, ezequiel.garcia@free-electrons.com, dwmw2@infradead.org, Roger Quadros List-Id: Linux MTD discussion mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , If a NAND device is not really present or pin muxes are not correctly configured we can lock up the kernel waiting infinitely for NAND_STATUS to be ready. This can be easily reproduced on TI's DRA7-evm board by booting it without NAND support in u-boot and disabling NAND pin muxes in the kernel. Add timeout when waiting for NAND_CMD_RESET completion. As per ONFi v4.0 tRST can be upto 250ms for EZ-NAND and 5ms for raw NAND. Signed-off-by: Roger Quadros Tested-by: Nishanth Menon --- drivers/mtd/nand/nand_base.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index df7eb4f..d1e6695 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -566,6 +566,25 @@ void nand_wait_ready(struct mtd_info *mtd) EXPORT_SYMBOL_GPL(nand_wait_ready); /** + * nand_wait_status_ready - [GENERIC] Wait for the ready status after commands. + * @mtd: MTD device structure + * @timeo: Timeout in ms + * + * Wait for status ready (i.e. command done) or timeout. + */ +static void nand_wait_status_ready(struct mtd_info *mtd, unsigned long timeo) +{ + register struct nand_chip *chip = mtd->priv; + + timeo = jiffies + msecs_to_jiffies(timeo); + do { + if ((chip->read_byte(mtd) & NAND_STATUS_READY)) + break; + touch_softlockup_watchdog(); + } while (time_before(jiffies, timeo)); +}; + +/** * nand_command - [DEFAULT] Send command to NAND device * @mtd: MTD device structure * @command: the command to be sent @@ -643,8 +662,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command, NAND_CTRL_CLE | NAND_CTRL_CHANGE); chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); - while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) - ; + /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ + nand_wait_status_ready(mtd, 250); return; /* This applies to read commands */ @@ -740,8 +759,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command, NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE); chip->cmd_ctrl(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE); - while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) - ; + /* EZ-NAND can take upto 250ms as per ONFi v4.0 */ + nand_wait_status_ready(mtd, 250); return; case NAND_CMD_RNDOUT: -- 2.1.0