aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorVenkatraman S <svenkatr@ti.com>2012-06-22 02:12:36 -0400
committerChris Ball <cjb@laptop.org>2012-07-10 23:04:04 -0400
commit6af9e96e052a6d1a760c60cb340c5a6584cb92db (patch)
tree60ff946a87bcedf6a3e3eccafa994f468f955b75 /drivers/mmc
parentfd0ea65d3e675e479e022b6cfc9ebe1864c76afc (diff)
mmc: core: Fix the HPI execution sequence
mmc_execute_hpi should send the HPI command only once, and only if the card is in PRG state. According to eMMC spec, the command's completion time is not dependent on OUT_OF_INTERRUPT_TIME. Only the transition out of PRG STATE is guarded by OUT_OF_INTERRUPT_TIME - which is defined to begin at the end of sending the command itself. Specify the default timeout for the actual sending of HPI command, and then use OUT_OF_INTERRUPT_TIME to wait for the transition out of PRG state. Reported-by: Alex Lemberg <Alex.Lemberg@sandisk.com> Signed-off-by: Venkatraman S <svenkatr@ti.com> Reviewed-by: Namjae Jeon <linkinjeon@gmail.com> Reviewed-by: Subhash Jadavani <subhashj@codeaurora.org> Acked-by: Jaehoon Chung <jh80.chung@samsung.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/core.c55
-rw-r--r--drivers/mmc/core/mmc_ops.c1
2 files changed, 32 insertions, 24 deletions
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 0b6141d29dbd..a7e2c4b2f18c 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -404,6 +404,7 @@ int mmc_interrupt_hpi(struct mmc_card *card)
404{ 404{
405 int err; 405 int err;
406 u32 status; 406 u32 status;
407 unsigned long prg_wait;
407 408
408 BUG_ON(!card); 409 BUG_ON(!card);
409 410
@@ -419,30 +420,38 @@ int mmc_interrupt_hpi(struct mmc_card *card)
419 goto out; 420 goto out;
420 } 421 }
421 422
422 /* 423 switch (R1_CURRENT_STATE(status)) {
423 * If the card status is in PRG-state, we can send the HPI command. 424 case R1_STATE_IDLE:
424 */ 425 case R1_STATE_READY:
425 if (R1_CURRENT_STATE(status) == R1_STATE_PRG) { 426 case R1_STATE_STBY:
426 do { 427 /*
427 /* 428 * In idle states, HPI is not needed and the caller
428 * We don't know when the HPI command will finish 429 * can issue the next intended command immediately
429 * processing, so we need to resend HPI until out 430 */
430 * of prg-state, and keep checking the card status 431 goto out;
431 * with SEND_STATUS. If a timeout error occurs when 432 case R1_STATE_PRG:
432 * sending the HPI command, we are already out of 433 break;
433 * prg-state. 434 default:
434 */ 435 /* In all other states, it's illegal to issue HPI */
435 err = mmc_send_hpi_cmd(card, &status); 436 pr_debug("%s: HPI cannot be sent. Card state=%d\n",
436 if (err) 437 mmc_hostname(card->host), R1_CURRENT_STATE(status));
437 pr_debug("%s: abort HPI (%d error)\n", 438 err = -EINVAL;
438 mmc_hostname(card->host), err); 439 goto out;
440 }
439 441
440 err = mmc_send_status(card, &status); 442 err = mmc_send_hpi_cmd(card, &status);
441 if (err) 443 if (err)
442 break; 444 goto out;
443 } while (R1_CURRENT_STATE(status) == R1_STATE_PRG); 445
444 } else 446 prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time);
445 pr_debug("%s: Left prg-state\n", mmc_hostname(card->host)); 447 do {
448 err = mmc_send_status(card, &status);
449
450 if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN)
451 break;
452 if (time_after(jiffies, prg_wait))
453 err = -ETIMEDOUT;
454 } while (!err);
446 455
447out: 456out:
448 mmc_release_host(card->host); 457 mmc_release_host(card->host);
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 69370f494e05..0ed2cc5f35b6 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -569,7 +569,6 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)
569 569
570 cmd.opcode = opcode; 570 cmd.opcode = opcode;
571 cmd.arg = card->rca << 16 | 1; 571 cmd.arg = card->rca << 16 | 1;
572 cmd.cmd_timeout_ms = card->ext_csd.out_of_int_time;
573 572
574 err = mmc_wait_for_cmd(card->host, &cmd, 0); 573 err = mmc_wait_for_cmd(card->host, &cmd, 0);
575 if (err) { 574 if (err) {