diff options
| author | Seungwon Jeon <tgih.jun@samsung.com> | 2012-07-31 20:30:46 -0400 |
|---|---|---|
| committer | Chris Ball <cjb@laptop.org> | 2012-09-04 13:58:09 -0400 |
| commit | e74f3a9c993a088f0a067e13941075e4acb7300a (patch) | |
| tree | 451f7589d217d85607c5e6eb8567fa77a40ec329 | |
| parent | 9b2026a12511439d906a5d8d302ae285ebe7378a (diff) | |
mmc: dw_mmc: fix error handling in PIO mode
Data transfer will be continued until all the bytes are transmitted,
even if data crc error occurs during a multiple-block data transfer.
This means RXDR/TXDR interrupts will occurs until data transfer is
terminated. Early setting of host->sg to NULL prevents going into
xxx_data_pio functions, hence permanent unhandled RXDR/TXDR interrupts
occurs. And checking error interrupt status in the xxx_data_pio functions
is no need because dw_mci_interrupt does do the same. This patch also
removes it.
Signed-off-by: Seungwon Jeon <tgih.jun@samsung.com>
Acked-by: Jaehoon Chung <jh80.chung@samsung.com>
Acked-by: Will Newton <will.newton@imgtec.com>
Signed-off-by: Chris Ball <cjb@laptop.org>
| -rw-r--r-- | drivers/mmc/host/dw_mmc.c | 29 |
1 files changed, 2 insertions, 27 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 1a5db20133ee..cf8511b80782 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
| @@ -1429,22 +1429,10 @@ static void dw_mci_read_data_pio(struct dw_mci *host) | |||
| 1429 | nbytes += len; | 1429 | nbytes += len; |
| 1430 | remain -= len; | 1430 | remain -= len; |
| 1431 | } while (remain); | 1431 | } while (remain); |
| 1432 | sg_miter->consumed = offset; | ||
| 1433 | 1432 | ||
| 1433 | sg_miter->consumed = offset; | ||
| 1434 | status = mci_readl(host, MINTSTS); | 1434 | status = mci_readl(host, MINTSTS); |
| 1435 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); | 1435 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); |
| 1436 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | ||
| 1437 | host->data_status = status; | ||
| 1438 | data->bytes_xfered += nbytes; | ||
| 1439 | sg_miter_stop(sg_miter); | ||
| 1440 | host->sg = NULL; | ||
| 1441 | smp_wmb(); | ||
| 1442 | |||
| 1443 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | ||
| 1444 | |||
| 1445 | tasklet_schedule(&host->tasklet); | ||
| 1446 | return; | ||
| 1447 | } | ||
| 1448 | } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ | 1436 | } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ |
| 1449 | data->bytes_xfered += nbytes; | 1437 | data->bytes_xfered += nbytes; |
| 1450 | 1438 | ||
| @@ -1497,23 +1485,10 @@ static void dw_mci_write_data_pio(struct dw_mci *host) | |||
| 1497 | nbytes += len; | 1485 | nbytes += len; |
| 1498 | remain -= len; | 1486 | remain -= len; |
| 1499 | } while (remain); | 1487 | } while (remain); |
| 1500 | sg_miter->consumed = offset; | ||
| 1501 | 1488 | ||
| 1489 | sg_miter->consumed = offset; | ||
| 1502 | status = mci_readl(host, MINTSTS); | 1490 | status = mci_readl(host, MINTSTS); |
| 1503 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); | 1491 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); |
| 1504 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | ||
| 1505 | host->data_status = status; | ||
| 1506 | data->bytes_xfered += nbytes; | ||
| 1507 | sg_miter_stop(sg_miter); | ||
| 1508 | host->sg = NULL; | ||
| 1509 | |||
| 1510 | smp_wmb(); | ||
| 1511 | |||
| 1512 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | ||
| 1513 | |||
| 1514 | tasklet_schedule(&host->tasklet); | ||
| 1515 | return; | ||
| 1516 | } | ||
| 1517 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ | 1492 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ |
| 1518 | data->bytes_xfered += nbytes; | 1493 | data->bytes_xfered += nbytes; |
| 1519 | 1494 | ||
