aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2015-02-10 13:59:55 -0500
committerBrian Norris <computersforpeace@gmail.com>2015-03-11 18:20:11 -0400
commite35d1d8a1d16e9f56a9b54c96d0cb85ed621bb89 (patch)
tree522c08163cb128d8575d6734c2d7d3ab3fd6bae7 /drivers/mtd/nand
parent111573ccd89b67fdef64d945cc0e611df85a6ac8 (diff)
mtd: mxc-nand: Add a timeout when waiting for interrupt
While extending the mxc-nand driver it happend to me a few times that the device was stuck and this made the machine hang during boot. So implement a timeout and print a stack trace the first time this happens to make it debuggable. The return type of the waiting function is also changed to int to be able to handle the timeout in the caller. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r--drivers/mtd/nand/mxc_nand.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index a8f550fec35e..27ba07c07966 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -386,26 +386,51 @@ static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
386/* This function polls the NANDFC to wait for the basic operation to 386/* This function polls the NANDFC to wait for the basic operation to
387 * complete by checking the INT bit of config2 register. 387 * complete by checking the INT bit of config2 register.
388 */ 388 */
389static void wait_op_done(struct mxc_nand_host *host, int useirq) 389static int wait_op_done(struct mxc_nand_host *host, int useirq)
390{ 390{
391 int max_retries = 8000; 391 int ret = 0;
392
393 /*
394 * If operation is already complete, don't bother to setup an irq or a
395 * loop.
396 */
397 if (host->devtype_data->check_int(host))
398 return 0;
392 399
393 if (useirq) { 400 if (useirq) {
394 if (!host->devtype_data->check_int(host)) { 401 unsigned long timeout;
395 reinit_completion(&host->op_completion); 402
396 irq_control(host, 1); 403 reinit_completion(&host->op_completion);
397 wait_for_completion(&host->op_completion); 404
405 irq_control(host, 1);
406
407 timeout = wait_for_completion_timeout(&host->op_completion, HZ);
408 if (!timeout && !host->devtype_data->check_int(host)) {
409 dev_dbg(host->dev, "timeout waiting for irq\n");
410 ret = -ETIMEDOUT;
398 } 411 }
399 } else { 412 } else {
400 while (max_retries-- > 0) { 413 int max_retries = 8000;
401 if (host->devtype_data->check_int(host)) 414 int done;
402 break;
403 415
416 do {
404 udelay(1); 417 udelay(1);
418
419 done = host->devtype_data->check_int(host);
420 if (done)
421 break;
422
423 } while (--max_retries);
424
425 if (!done) {
426 dev_dbg(host->dev, "timeout polling for completion\n");
427 ret = -ETIMEDOUT;
405 } 428 }
406 if (max_retries < 0)
407 pr_debug("%s: INT not set\n", __func__);
408 } 429 }
430
431 WARN_ONCE(ret < 0, "timeout! useirq=%d\n", useirq);
432
433 return ret;
409} 434}
410 435
411static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq) 436static void send_cmd_v3(struct mxc_nand_host *host, uint16_t cmd, int useirq)