Commit 080909503664641432cc8adf2ee2084775fd992a
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge tag 'mmc-fixes-for-3.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc
Pull MMC fixes from Chris Ball: - a firmware bug on several Samsung MoviNAND eMMC models causes permanent corruption on the device when secure erase and secure trim requests are made, so we disable those requests on these eMMC devices. - atmel-mci: fix a hang with some SD cards by waiting for not-busy flag. - dw_mmc: low-power mode breaks SDIO interrupts; fix PIO error handling; fix handling of error interrupts. - mxs-mmc: fix deadlocks; fix compile error due to dma.h arch change. - omap: fix broken PIO mode causing memory corruption. - sdhci-esdhc: fix card detection. * tag 'mmc-fixes-for-3.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: mmc: omap: fix broken PIO mode mmc: card: Skip secure erase on MoviNAND; causes unrecoverable corruption. mmc: dw_mmc: Disable low power mode if SDIO interrupts are used mmc: dw_mmc: fix error handling in PIO mode mmc: dw_mmc: correct mishandling error interrupt mmc: dw_mmc: amend using error interrupt status mmc: atmel-mci: not busy flag has also to be used for read operations mmc: sdhci-esdhc: break out early if clock is 0 mmc: mxs-mmc: fix deadlock caused by recursion loop mmc: mxs-mmc: fix deadlock in SDIO IRQ case mmc: bfin_sdh: fix dma_desc_array build error
Showing 8 changed files Side-by-side Diff
drivers/mmc/card/block.c
... | ... | @@ -1411,7 +1411,8 @@ |
1411 | 1411 | /* complete ongoing async transfer before issuing discard */ |
1412 | 1412 | if (card->host->areq) |
1413 | 1413 | mmc_blk_issue_rw_rq(mq, NULL); |
1414 | - if (req->cmd_flags & REQ_SECURE) | |
1414 | + if (req->cmd_flags & REQ_SECURE && | |
1415 | + !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN)) | |
1415 | 1416 | ret = mmc_blk_issue_secdiscard_rq(mq, req); |
1416 | 1417 | else |
1417 | 1418 | ret = mmc_blk_issue_discard_rq(mq, req); |
... | ... | @@ -1716,6 +1717,7 @@ |
1716 | 1717 | #define CID_MANFID_SANDISK 0x2 |
1717 | 1718 | #define CID_MANFID_TOSHIBA 0x11 |
1718 | 1719 | #define CID_MANFID_MICRON 0x13 |
1720 | +#define CID_MANFID_SAMSUNG 0x15 | |
1719 | 1721 | |
1720 | 1722 | static const struct mmc_fixup blk_fixups[] = |
1721 | 1723 | { |
... | ... | @@ -1751,6 +1753,28 @@ |
1751 | 1753 | */ |
1752 | 1754 | MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc, |
1753 | 1755 | MMC_QUIRK_LONG_READ_TIME), |
1756 | + | |
1757 | + /* | |
1758 | + * On these Samsung MoviNAND parts, performing secure erase or | |
1759 | + * secure trim can result in unrecoverable corruption due to a | |
1760 | + * firmware bug. | |
1761 | + */ | |
1762 | + MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | |
1763 | + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | |
1764 | + MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | |
1765 | + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | |
1766 | + MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | |
1767 | + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | |
1768 | + MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | |
1769 | + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | |
1770 | + MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | |
1771 | + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | |
1772 | + MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | |
1773 | + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | |
1774 | + MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | |
1775 | + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | |
1776 | + MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc, | |
1777 | + MMC_QUIRK_SEC_ERASE_TRIM_BROKEN), | |
1754 | 1778 | |
1755 | 1779 | END_FIXUP |
1756 | 1780 | }; |
drivers/mmc/host/atmel-mci.c
... | ... | @@ -81,6 +81,7 @@ |
81 | 81 | bool has_bad_data_ordering; |
82 | 82 | bool need_reset_after_xfer; |
83 | 83 | bool need_blksz_mul_4; |
84 | + bool need_notbusy_for_read_ops; | |
84 | 85 | }; |
85 | 86 | |
86 | 87 | struct atmel_mci_dma { |
... | ... | @@ -1625,7 +1626,8 @@ |
1625 | 1626 | __func__); |
1626 | 1627 | atmci_set_completed(host, EVENT_XFER_COMPLETE); |
1627 | 1628 | |
1628 | - if (host->data->flags & MMC_DATA_WRITE) { | |
1629 | + if (host->caps.need_notbusy_for_read_ops || | |
1630 | + (host->data->flags & MMC_DATA_WRITE)) { | |
1629 | 1631 | atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY); |
1630 | 1632 | state = STATE_WAITING_NOTBUSY; |
1631 | 1633 | } else if (host->mrq->stop) { |
... | ... | @@ -2218,6 +2220,7 @@ |
2218 | 2220 | host->caps.has_bad_data_ordering = 1; |
2219 | 2221 | host->caps.need_reset_after_xfer = 1; |
2220 | 2222 | host->caps.need_blksz_mul_4 = 1; |
2223 | + host->caps.need_notbusy_for_read_ops = 0; | |
2221 | 2224 | |
2222 | 2225 | /* keep only major version number */ |
2223 | 2226 | switch (version & 0xf00) { |
... | ... | @@ -2238,6 +2241,7 @@ |
2238 | 2241 | case 0x200: |
2239 | 2242 | host->caps.has_rwproof = 1; |
2240 | 2243 | host->caps.need_blksz_mul_4 = 0; |
2244 | + host->caps.need_notbusy_for_read_ops = 1; | |
2241 | 2245 | case 0x100: |
2242 | 2246 | host->caps.has_bad_data_ordering = 0; |
2243 | 2247 | host->caps.need_reset_after_xfer = 0; |
drivers/mmc/host/bfin_sdh.c
... | ... | @@ -49,13 +49,6 @@ |
49 | 49 | #define bfin_write_SDH_CFG bfin_write_RSI_CFG |
50 | 50 | #endif |
51 | 51 | |
52 | -struct dma_desc_array { | |
53 | - unsigned long start_addr; | |
54 | - unsigned short cfg; | |
55 | - unsigned short x_count; | |
56 | - short x_modify; | |
57 | -} __packed; | |
58 | - | |
59 | 52 | struct sdh_host { |
60 | 53 | struct mmc_host *mmc; |
61 | 54 | spinlock_t lock; |
drivers/mmc/host/dw_mmc.c
... | ... | @@ -627,6 +627,7 @@ |
627 | 627 | { |
628 | 628 | struct dw_mci *host = slot->host; |
629 | 629 | u32 div; |
630 | + u32 clk_en_a; | |
630 | 631 | |
631 | 632 | if (slot->clock != host->current_speed) { |
632 | 633 | div = host->bus_hz / slot->clock; |
... | ... | @@ -659,9 +660,11 @@ |
659 | 660 | mci_send_cmd(slot, |
660 | 661 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); |
661 | 662 | |
662 | - /* enable clock */ | |
663 | - mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE | | |
664 | - SDMMC_CLKEN_LOW_PWR) << slot->id)); | |
663 | + /* enable clock; only low power if no SDIO */ | |
664 | + clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; | |
665 | + if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id))) | |
666 | + clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id; | |
667 | + mci_writel(host, CLKENA, clk_en_a); | |
665 | 668 | |
666 | 669 | /* inform CIU */ |
667 | 670 | mci_send_cmd(slot, |
... | ... | @@ -862,6 +865,30 @@ |
862 | 865 | return present; |
863 | 866 | } |
864 | 867 | |
868 | +/* | |
869 | + * Disable lower power mode. | |
870 | + * | |
871 | + * Low power mode will stop the card clock when idle. According to the | |
872 | + * description of the CLKENA register we should disable low power mode | |
873 | + * for SDIO cards if we need SDIO interrupts to work. | |
874 | + * | |
875 | + * This function is fast if low power mode is already disabled. | |
876 | + */ | |
877 | +static void dw_mci_disable_low_power(struct dw_mci_slot *slot) | |
878 | +{ | |
879 | + struct dw_mci *host = slot->host; | |
880 | + u32 clk_en_a; | |
881 | + const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id; | |
882 | + | |
883 | + clk_en_a = mci_readl(host, CLKENA); | |
884 | + | |
885 | + if (clk_en_a & clken_low_pwr) { | |
886 | + mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr); | |
887 | + mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | | |
888 | + SDMMC_CMD_PRV_DAT_WAIT, 0); | |
889 | + } | |
890 | +} | |
891 | + | |
865 | 892 | static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb) |
866 | 893 | { |
867 | 894 | struct dw_mci_slot *slot = mmc_priv(mmc); |
... | ... | @@ -871,6 +898,14 @@ |
871 | 898 | /* Enable/disable Slot Specific SDIO interrupt */ |
872 | 899 | int_mask = mci_readl(host, INTMASK); |
873 | 900 | if (enb) { |
901 | + /* | |
902 | + * Turn off low power mode if it was enabled. This is a bit of | |
903 | + * a heavy operation and we disable / enable IRQs a lot, so | |
904 | + * we'll leave low power mode disabled and it will get | |
905 | + * re-enabled again in dw_mci_setup_bus(). | |
906 | + */ | |
907 | + dw_mci_disable_low_power(slot); | |
908 | + | |
874 | 909 | mci_writel(host, INTMASK, |
875 | 910 | (int_mask | SDMMC_INT_SDIO(slot->id))); |
876 | 911 | } else { |
877 | 912 | |
878 | 913 | |
... | ... | @@ -1429,22 +1464,10 @@ |
1429 | 1464 | nbytes += len; |
1430 | 1465 | remain -= len; |
1431 | 1466 | } while (remain); |
1432 | - sg_miter->consumed = offset; | |
1433 | 1467 | |
1468 | + sg_miter->consumed = offset; | |
1434 | 1469 | status = mci_readl(host, MINTSTS); |
1435 | 1470 | 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 | 1471 | } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ |
1449 | 1472 | data->bytes_xfered += nbytes; |
1450 | 1473 | |
1451 | 1474 | |
1452 | 1475 | |
... | ... | @@ -1497,23 +1520,10 @@ |
1497 | 1520 | nbytes += len; |
1498 | 1521 | remain -= len; |
1499 | 1522 | } while (remain); |
1500 | - sg_miter->consumed = offset; | |
1501 | 1523 | |
1524 | + sg_miter->consumed = offset; | |
1502 | 1525 | status = mci_readl(host, MINTSTS); |
1503 | 1526 | 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 | 1527 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ |
1518 | 1528 | data->bytes_xfered += nbytes; |
1519 | 1529 | |
1520 | 1530 | |
... | ... | @@ -1547,12 +1557,11 @@ |
1547 | 1557 | static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) |
1548 | 1558 | { |
1549 | 1559 | struct dw_mci *host = dev_id; |
1550 | - u32 status, pending; | |
1560 | + u32 pending; | |
1551 | 1561 | unsigned int pass_count = 0; |
1552 | 1562 | int i; |
1553 | 1563 | |
1554 | 1564 | do { |
1555 | - status = mci_readl(host, RINTSTS); | |
1556 | 1565 | pending = mci_readl(host, MINTSTS); /* read-only mask reg */ |
1557 | 1566 | |
1558 | 1567 | /* |
... | ... | @@ -1570,7 +1579,7 @@ |
1570 | 1579 | |
1571 | 1580 | if (pending & DW_MCI_CMD_ERROR_FLAGS) { |
1572 | 1581 | mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); |
1573 | - host->cmd_status = status; | |
1582 | + host->cmd_status = pending; | |
1574 | 1583 | smp_wmb(); |
1575 | 1584 | set_bit(EVENT_CMD_COMPLETE, &host->pending_events); |
1576 | 1585 | } |
1577 | 1586 | |
1578 | 1587 | |
... | ... | @@ -1578,18 +1587,16 @@ |
1578 | 1587 | if (pending & DW_MCI_DATA_ERROR_FLAGS) { |
1579 | 1588 | /* if there is an error report DATA_ERROR */ |
1580 | 1589 | mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); |
1581 | - host->data_status = status; | |
1590 | + host->data_status = pending; | |
1582 | 1591 | smp_wmb(); |
1583 | 1592 | set_bit(EVENT_DATA_ERROR, &host->pending_events); |
1584 | - if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC | | |
1585 | - SDMMC_INT_SBE | SDMMC_INT_EBE))) | |
1586 | - tasklet_schedule(&host->tasklet); | |
1593 | + tasklet_schedule(&host->tasklet); | |
1587 | 1594 | } |
1588 | 1595 | |
1589 | 1596 | if (pending & SDMMC_INT_DATA_OVER) { |
1590 | 1597 | mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); |
1591 | 1598 | if (!host->data_status) |
1592 | - host->data_status = status; | |
1599 | + host->data_status = pending; | |
1593 | 1600 | smp_wmb(); |
1594 | 1601 | if (host->dir_status == DW_MCI_RECV_STATUS) { |
1595 | 1602 | if (host->sg != NULL) |
... | ... | @@ -1613,7 +1620,7 @@ |
1613 | 1620 | |
1614 | 1621 | if (pending & SDMMC_INT_CMD_DONE) { |
1615 | 1622 | mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); |
1616 | - dw_mci_cmd_interrupt(host, status); | |
1623 | + dw_mci_cmd_interrupt(host, pending); | |
1617 | 1624 | } |
1618 | 1625 | |
1619 | 1626 | if (pending & SDMMC_INT_CD) { |
drivers/mmc/host/mxs-mmc.c
... | ... | @@ -285,11 +285,11 @@ |
285 | 285 | writel(stat & MXS_MMC_IRQ_BITS, |
286 | 286 | host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR); |
287 | 287 | |
288 | + spin_unlock(&host->lock); | |
289 | + | |
288 | 290 | if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) |
289 | 291 | mmc_signal_sdio_irq(host->mmc); |
290 | 292 | |
291 | - spin_unlock(&host->lock); | |
292 | - | |
293 | 293 | if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ) |
294 | 294 | cmd->error = -ETIMEDOUT; |
295 | 295 | else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ) |
... | ... | @@ -644,11 +644,6 @@ |
644 | 644 | host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); |
645 | 645 | writel(BM_SSP_CTRL1_SDIO_IRQ_EN, |
646 | 646 | host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET); |
647 | - | |
648 | - if (readl(host->base + HW_SSP_STATUS(host)) & | |
649 | - BM_SSP_STATUS_SDIO_IRQ) | |
650 | - mmc_signal_sdio_irq(host->mmc); | |
651 | - | |
652 | 647 | } else { |
653 | 648 | writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, |
654 | 649 | host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); |
... | ... | @@ -657,6 +652,11 @@ |
657 | 652 | } |
658 | 653 | |
659 | 654 | spin_unlock_irqrestore(&host->lock, flags); |
655 | + | |
656 | + if (enable && readl(host->base + HW_SSP_STATUS(host)) & | |
657 | + BM_SSP_STATUS_SDIO_IRQ) | |
658 | + mmc_signal_sdio_irq(host->mmc); | |
659 | + | |
660 | 660 | } |
661 | 661 | |
662 | 662 | static const struct mmc_host_ops mxs_mmc_ops = { |
drivers/mmc/host/omap.c
... | ... | @@ -668,7 +668,7 @@ |
668 | 668 | static void |
669 | 669 | mmc_omap_xfer_data(struct mmc_omap_host *host, int write) |
670 | 670 | { |
671 | - int n; | |
671 | + int n, nwords; | |
672 | 672 | |
673 | 673 | if (host->buffer_bytes_left == 0) { |
674 | 674 | host->sg_idx++; |
675 | 675 | |
676 | 676 | |
677 | 677 | |
... | ... | @@ -678,15 +678,23 @@ |
678 | 678 | n = 64; |
679 | 679 | if (n > host->buffer_bytes_left) |
680 | 680 | n = host->buffer_bytes_left; |
681 | + | |
682 | + nwords = n / 2; | |
683 | + nwords += n & 1; /* handle odd number of bytes to transfer */ | |
684 | + | |
681 | 685 | host->buffer_bytes_left -= n; |
682 | 686 | host->total_bytes_left -= n; |
683 | 687 | host->data->bytes_xfered += n; |
684 | 688 | |
685 | 689 | if (write) { |
686 | - __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); | |
690 | + __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), | |
691 | + host->buffer, nwords); | |
687 | 692 | } else { |
688 | - __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); | |
693 | + __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), | |
694 | + host->buffer, nwords); | |
689 | 695 | } |
696 | + | |
697 | + host->buffer += nwords; | |
690 | 698 | } |
691 | 699 | |
692 | 700 | static inline void mmc_omap_report_irq(u16 status) |
drivers/mmc/host/sdhci-esdhc.h
... | ... | @@ -48,13 +48,13 @@ |
48 | 48 | int div = 1; |
49 | 49 | u32 temp; |
50 | 50 | |
51 | + if (clock == 0) | |
52 | + goto out; | |
53 | + | |
51 | 54 | temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); |
52 | 55 | temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN |
53 | 56 | | ESDHC_CLOCK_MASK); |
54 | 57 | sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); |
55 | - | |
56 | - if (clock == 0) | |
57 | - goto out; | |
58 | 58 | |
59 | 59 | while (host->max_clk / pre_div / 16 > clock && pre_div < 256) |
60 | 60 | pre_div *= 2; |
include/linux/mmc/card.h
... | ... | @@ -239,6 +239,7 @@ |
239 | 239 | #define MMC_QUIRK_BLK_NO_CMD23 (1<<7) /* Avoid CMD23 for regular multiblock */ |
240 | 240 | #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8) /* Avoid sending 512 bytes in */ |
241 | 241 | #define MMC_QUIRK_LONG_READ_TIME (1<<9) /* Data read time > CSD says */ |
242 | +#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10) /* Skip secure for erase/trim */ | |
242 | 243 | /* byte mode */ |
243 | 244 | unsigned int poweroff_notify_state; /* eMMC4.5 notify feature */ |
244 | 245 | #define MMC_NO_POWER_NOTIFICATION 0 |