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 /drivers | |
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>
Diffstat (limited to 'drivers')
-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 | ||