MMC core:

- Further fix thread wake-up for requests
  - Use a bounce buffer to fix DMA issue for SSR register read
 
 MMC host:
  - sdhci: Fix a regression for runtime PM
  - sdhci-cadence: Add a proper SoC specific DT compatible
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJYWjTHAAoJEP4mhCVzWIwpQGIP/iYBC90rFPhoq8ba8fdngFuD
 RBuuw+yW+ueCcFuogrm7eSHnOS/FWWl4iYDnX6CJOuto4HYh+rexzLT3YlA2wbid
 jEFi59lVA3xDEP9hpBGavp1IJV7XVh4uCH4NsVbceQ9MoIpJwFkUxDY5zMdPmKG6
 Pt4jaXsoxhcAYro5ORH5q4BzX4bfluUKSYsgBBUsQMxhOQy02CKgvfJ3/aR7+Tqg
 3f/3tQVOXMmI+NhLC5y++VoxL5YoTos6WHgIoA7kuXPvVkVV89jxvLWZKzbsNVHC
 iZ6DNdaMwmSSK5BwfSzSXReAA4zce+yw55O0j/dTc+EKdJJ7/oW3y/fpda6lrGy7
 dRG4RXumBrVUqOAobx6J/KibM94gIsdaOZ4sCptn48x1NeRafsGc4fq+76tpIvHe
 16dn9xIqcz4hZU4GsQSgNpo4DFJCE6K4yuYgtuKP+qvUGBFyRoGzwo5mf6hxJovT
 YviqLmqsOjaZ6F202HMaJtYgSQBv/lScL9vp40H7T5yrIbR2mx4ww2FyNWLWXqRY
 4IJ6F8gwu1xUafCi5LUNk+pU1J1bjIKTSeR3enRIpudEzmy9/oroQDOtLh+1T4Z6
 CVkdxmgd6jrs7sK9pPURKhDuMgZH7hUAuFxg3JMRMEdCOzsTwuAHnDq0DtrjSOC9
 hYw+dqDJHut0To290N5r
 =PDPZ
 -----END PGP SIGNATURE-----

Merge tag 'mmc-v4.10-3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc

Pull MMC fixes from Ulf Hansson:
 "MMC core:
   - further fix thread wake-up for requests
   - use a bounce buffer to fix DMA issue for SSR register read

  MMC host:
   - sdhci: Fix a regression for runtime PM
   - sdhci-cadence: Add a proper SoC specific DT compatible"

* tag 'mmc-v4.10-3' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: sd: Meet alignment requirements for raw_ssr DMA
  mmc: core: Further fix thread wake-up
  mmc: sdhci: Fix to handle MMC_POWER_UNDEFINED
  mmc: sdhci-cadence: add Socionext UniPhier specific compatible string
This commit is contained in:
Linus Torvalds 2016-12-22 10:13:04 -08:00
commit 8d86cf8879
5 changed files with 39 additions and 25 deletions

View File

@ -1,7 +1,9 @@
* Cadence SD/SDIO/eMMC Host Controller * Cadence SD/SDIO/eMMC Host Controller
Required properties: Required properties:
- compatible: should be "cdns,sd4hc". - compatible: should be one of the following:
"cdns,sd4hc" - default of the IP
"socionext,uniphier-sd4hc" - for Socionext UniPhier SoCs
- reg: offset and length of the register set for the device. - reg: offset and length of the register set for the device.
- interrupts: a single interrupt specifier. - interrupts: a single interrupt specifier.
- clocks: phandle to the input clock. - clocks: phandle to the input clock.
@ -19,7 +21,7 @@ if supported. See mmc.txt for details.
Example: Example:
emmc: sdhci@5a000000 { emmc: sdhci@5a000000 {
compatible = "cdns,sd4hc"; compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
reg = <0x5a000000 0x400>; reg = <0x5a000000 0x400>;
interrupts = <0 78 4>; interrupts = <0 78 4>;
clocks = <&clk 4>; clocks = <&clk 4>;

View File

@ -496,8 +496,7 @@ static int __mmc_start_req(struct mmc_host *host, struct mmc_request *mrq)
* Returns enum mmc_blk_status after checking errors. * Returns enum mmc_blk_status after checking errors.
*/ */
static enum mmc_blk_status mmc_wait_for_data_req_done(struct mmc_host *host, static enum mmc_blk_status mmc_wait_for_data_req_done(struct mmc_host *host,
struct mmc_request *mrq, struct mmc_request *mrq)
struct mmc_async_req *next_req)
{ {
struct mmc_command *cmd; struct mmc_command *cmd;
struct mmc_context_info *context_info = &host->context_info; struct mmc_context_info *context_info = &host->context_info;
@ -507,7 +506,7 @@ static enum mmc_blk_status mmc_wait_for_data_req_done(struct mmc_host *host,
wait_event_interruptible(context_info->wait, wait_event_interruptible(context_info->wait,
(context_info->is_done_rcv || (context_info->is_done_rcv ||
context_info->is_new_req)); context_info->is_new_req));
context_info->is_waiting_last_req = false;
if (context_info->is_done_rcv) { if (context_info->is_done_rcv) {
context_info->is_done_rcv = false; context_info->is_done_rcv = false;
cmd = mrq->cmd; cmd = mrq->cmd;
@ -527,10 +526,9 @@ static enum mmc_blk_status mmc_wait_for_data_req_done(struct mmc_host *host,
__mmc_start_request(host, mrq); __mmc_start_request(host, mrq);
continue; /* wait for done/new event again */ continue; /* wait for done/new event again */
} }
} else if (context_info->is_new_req) {
if (!next_req)
return MMC_BLK_NEW_REQUEST;
} }
return MMC_BLK_NEW_REQUEST;
} }
mmc_retune_release(host); mmc_retune_release(host);
return status; return status;
@ -660,7 +658,7 @@ struct mmc_async_req *mmc_start_req(struct mmc_host *host,
mmc_pre_req(host, areq->mrq); mmc_pre_req(host, areq->mrq);
if (host->areq) { if (host->areq) {
status = mmc_wait_for_data_req_done(host, host->areq->mrq, areq); status = mmc_wait_for_data_req_done(host, host->areq->mrq);
if (status == MMC_BLK_NEW_REQUEST) { if (status == MMC_BLK_NEW_REQUEST) {
if (ret_stat) if (ret_stat)
*ret_stat = status; *ret_stat = status;

View File

@ -223,6 +223,7 @@ static int mmc_decode_scr(struct mmc_card *card)
static int mmc_read_ssr(struct mmc_card *card) static int mmc_read_ssr(struct mmc_card *card)
{ {
unsigned int au, es, et, eo; unsigned int au, es, et, eo;
u32 *raw_ssr;
int i; int i;
if (!(card->csd.cmdclass & CCC_APP_SPEC)) { if (!(card->csd.cmdclass & CCC_APP_SPEC)) {
@ -231,14 +232,21 @@ static int mmc_read_ssr(struct mmc_card *card)
return 0; return 0;
} }
if (mmc_app_sd_status(card, card->raw_ssr)) { raw_ssr = kmalloc(sizeof(card->raw_ssr), GFP_KERNEL);
if (!raw_ssr)
return -ENOMEM;
if (mmc_app_sd_status(card, raw_ssr)) {
pr_warn("%s: problem reading SD Status register\n", pr_warn("%s: problem reading SD Status register\n",
mmc_hostname(card->host)); mmc_hostname(card->host));
kfree(raw_ssr);
return 0; return 0;
} }
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
card->raw_ssr[i] = be32_to_cpu(card->raw_ssr[i]); card->raw_ssr[i] = be32_to_cpu(raw_ssr[i]);
kfree(raw_ssr);
/* /*
* UNSTUFF_BITS only works with four u32s so we have to offset the * UNSTUFF_BITS only works with four u32s so we have to offset the

View File

@ -262,6 +262,7 @@ static int sdhci_cdns_probe(struct platform_device *pdev)
} }
static const struct of_device_id sdhci_cdns_match[] = { static const struct of_device_id sdhci_cdns_match[] = {
{ .compatible = "socionext,uniphier-sd4hc" },
{ .compatible = "cdns,sd4hc" }, { .compatible = "cdns,sd4hc" },
{ /* sentinel */ } { /* sentinel */ }
}; };

View File

@ -1576,6 +1576,9 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
unsigned long flags; unsigned long flags;
u8 ctrl; u8 ctrl;
if (ios->power_mode == MMC_POWER_UNDEFINED)
return;
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
if (host->flags & SDHCI_DEVICE_DEAD) { if (host->flags & SDHCI_DEVICE_DEAD) {
@ -2938,23 +2941,25 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
sdhci_init(host, 0); sdhci_init(host, 0);
/* Force clock and power re-program */ if (mmc->ios.power_mode != MMC_POWER_UNDEFINED) {
host->pwr = 0; /* Force clock and power re-program */
host->clock = 0; host->pwr = 0;
mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios); host->clock = 0;
mmc->ops->set_ios(mmc, &mmc->ios); mmc->ops->start_signal_voltage_switch(mmc, &mmc->ios);
mmc->ops->set_ios(mmc, &mmc->ios);
if ((host_flags & SDHCI_PV_ENABLED) && if ((host_flags & SDHCI_PV_ENABLED) &&
!(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) { !(host->quirks2 & SDHCI_QUIRK2_PRESET_VALUE_BROKEN)) {
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
sdhci_enable_preset_value(host, true); sdhci_enable_preset_value(host, true);
spin_unlock_irqrestore(&host->lock, flags); spin_unlock_irqrestore(&host->lock, flags);
}
if ((mmc->caps2 & MMC_CAP2_HS400_ES) &&
mmc->ops->hs400_enhanced_strobe)
mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios);
} }
if ((mmc->caps2 & MMC_CAP2_HS400_ES) &&
mmc->ops->hs400_enhanced_strobe)
mmc->ops->hs400_enhanced_strobe(mmc, &mmc->ios);
spin_lock_irqsave(&host->lock, flags); spin_lock_irqsave(&host->lock, flags);
host->runtime_suspended = false; host->runtime_suspended = false;