Pull MMC host fixes from Ulf Hansson: - alcor: Stabilize data write requests - sdhci-omap: Fix command error path during tuning * tag 'mmc-v5.1-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: mmc: sdhci-omap: Don't finish_mrq() on a command error during tuning mmc: alcor: don't write data before command has completed
Unified · Split
| @@ -48,7 +48,6 @@ struct alcor_sdmmc_host { · 47 unmodified lines | ||
| 48 | 48 | struct mmc_command *cmd; |
| 49 | 49 | struct mmc_data *data; |
| 50 | 50 | unsigned int dma_on:1; |
| 51 | − unsigned int early_data:1; | |
| 52 | 51 | |
| 53 | 52 | struct mutex cmd_mutex; |
| 54 | 53 | |
| @@ -144,8 +143,7 @@ static void alcor_data_set_dma(struct alcor_sdmmc_host *host) · 89 unmodified lines | ||
| 144 | 143 | host->sg_count--; |
| 145 | 144 | } |
| 146 | 145 | |
| 147 | −static void alcor_trigger_data_transfer(struct alcor_sdmmc_host *host, | |
| 148 | − bool early) | |
| 146 | +static void alcor_trigger_data_transfer(struct alcor_sdmmc_host *host) | |
| 149 | 147 | { |
| 150 | 148 | struct alcor_pci_priv *priv = host->alcor_pci; |
| 151 | 149 | struct mmc_data *data = host->data; |
| @@ -155,13 +153,6 @@ static void alcor_trigger_data_transfer(struct alcor_sdmmc_host *host, · 3 unmodified lines | ||
| 155 | 153 | ctrl |= AU6601_DATA_WRITE; |
| 156 | 154 | |
| 157 | 155 | if (data->host_cookie == COOKIE_MAPPED) { |
| 158 | − if (host->early_data) { | |
| 159 | − host->early_data = false; | |
| 160 | − return; | |
| 161 | − } | |
| 162 | − | |
| 163 | − host->early_data = early; | |
| 164 | − | |
| 165 | 156 | alcor_data_set_dma(host); |
| 166 | 157 | ctrl |= AU6601_DATA_DMA_MODE; |
| 167 | 158 | host->dma_on = 1; |
| @@ -231,6 +222,7 @@ static void alcor_prepare_sg_miter(struct alcor_sdmmc_host *host) · 63 unmodified lines | ||
| 231 | 222 | static void alcor_prepare_data(struct alcor_sdmmc_host *host, |
| 232 | 223 | struct mmc_command *cmd) |
| 233 | 224 | { |
| 225 | + struct alcor_pci_priv *priv = host->alcor_pci; | |
| 234 | 226 | struct mmc_data *data = cmd->data; |
| 235 | 227 | |
| 236 | 228 | if (!data) |
| @@ -248,7 +240,7 @@ static void alcor_prepare_data(struct alcor_sdmmc_host *host, · 11 unmodified lines | ||
| 248 | 240 | if (data->host_cookie != COOKIE_MAPPED) |
| 249 | 241 | alcor_prepare_sg_miter(host); |
| 250 | 242 | |
| 251 | − alcor_trigger_data_transfer(host, true); | |
| 243 | + alcor_write8(priv, 0, AU6601_DATA_XFER_CTRL); | |
| 252 | 244 | } |
| 253 | 245 | |
| 254 | 246 | static void alcor_send_cmd(struct alcor_sdmmc_host *host, |
| @@ -435,7 +427,7 @@ static int alcor_cmd_irq_done(struct alcor_sdmmc_host *host, u32 intmask) · 180 unmodified lines | ||
| 435 | 427 | if (!host->data) |
| 436 | 428 | return false; |
| 437 | 429 | |
| 438 | − alcor_trigger_data_transfer(host, false); | |
| 430 | + alcor_trigger_data_transfer(host); | |
| 439 | 431 | host->cmd = NULL; |
| 440 | 432 | return true; |
| 441 | 433 | } |
| @@ -456,7 +448,7 @@ static void alcor_cmd_irq_thread(struct alcor_sdmmc_host *host, u32 intmask) · 14 unmodified lines | ||
| 456 | 448 | if (!host->data) |
| 457 | 449 | alcor_request_complete(host, 1); |
| 458 | 450 | else |
| 459 | − alcor_trigger_data_transfer(host, false); | |
| 451 | + alcor_trigger_data_transfer(host); | |
| 460 | 452 | host->cmd = NULL; |
| 461 | 453 | } |
| 462 | 454 | |
| @@ -487,15 +479,9 @@ static int alcor_data_irq_done(struct alcor_sdmmc_host *host, u32 intmask) · 24 unmodified lines | ||
| 487 | 479 | break; |
| 488 | 480 | case AU6601_INT_READ_BUF_RDY: |
| 489 | 481 | alcor_trf_block_pio(host, true); |
| 490 | − if (!host->blocks) | |
| 491 | − break; | |
| 492 | − alcor_trigger_data_transfer(host, false); | |
| 493 | 482 | return 1; |
| 494 | 483 | case AU6601_INT_WRITE_BUF_RDY: |
| 495 | 484 | alcor_trf_block_pio(host, false); |
| 496 | − if (!host->blocks) | |
| 497 | − break; | |
| 498 | − alcor_trigger_data_transfer(host, false); | |
| 499 | 485 | return 1; |
| 500 | 486 | case AU6601_INT_DMA_END: |
| 501 | 487 | if (!host->sg_count) |
| @@ -508,8 +494,14 @@ static int alcor_data_irq_done(struct alcor_sdmmc_host *host, u32 intmask) · 6 unmodified lines | ||
| 508 | 494 | break; |
| 509 | 495 | } |
| 510 | 496 | |
| 511 | − if (intmask & AU6601_INT_DATA_END) | |
| 512 | − return 0; | |
| 497 | + if (intmask & AU6601_INT_DATA_END) { | |
| 498 | + if (!host->dma_on && host->blocks) { | |
| 499 | + alcor_trigger_data_transfer(host); | |
| 500 | + return 1; | |
| 501 | + } else { | |
| 502 | + return 0; | |
| 503 | + } | |
| 504 | + } | |
| 513 | 505 | |
| 514 | 506 | return 1; |
| 515 | 507 | } |
| @@ -797,6 +797,43 @@ void sdhci_omap_reset(struct sdhci_host *host, u8 mask) · 796 unmodified lines | ||
| 797 | 797 | sdhci_reset(host, mask); |
| 798 | 798 | } |
| 799 | 799 | |
| 800 | +#define CMD_ERR_MASK (SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX |\ | |
| 801 | + SDHCI_INT_TIMEOUT) | |
| 802 | +#define CMD_MASK (CMD_ERR_MASK | SDHCI_INT_RESPONSE) | |
| 803 | + | |
| 804 | +static u32 sdhci_omap_irq(struct sdhci_host *host, u32 intmask) | |
| 805 | +{ | |
| 806 | + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | |
| 807 | + struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host); | |
| 808 | + | |
| 809 | + if (omap_host->is_tuning && host->cmd && !host->data_early && | |
| 810 | + (intmask & CMD_ERR_MASK)) { | |
| 811 | + | |
| 812 | + /* | |
| 813 | + * Since we are not resetting data lines during tuning | |
| 814 | + * operation, data error or data complete interrupts | |
| 815 | + * might still arrive. Mark this request as a failure | |
| 816 | + * but still wait for the data interrupt | |
| 817 | + */ | |
| 818 | + if (intmask & SDHCI_INT_TIMEOUT) | |
| 819 | + host->cmd->error = -ETIMEDOUT; | |
| 820 | + else | |
| 821 | + host->cmd->error = -EILSEQ; | |
| 822 | + | |
| 823 | + host->cmd = NULL; | |
| 824 | + | |
| 825 | + /* | |
| 826 | + * Sometimes command error interrupts and command complete | |
| 827 | + * interrupt will arrive together. Clear all command related | |
| 828 | + * interrupts here. | |
| 829 | + */ | |
| 830 | + sdhci_writel(host, intmask & CMD_MASK, SDHCI_INT_STATUS); | |
| 831 | + intmask &= ~CMD_MASK; | |
| 832 | + } | |
| 833 | + | |
| 834 | + return intmask; | |
| 835 | +} | |
| 836 | + | |
| 800 | 837 | static struct sdhci_ops sdhci_omap_ops = { |
| 801 | 838 | .set_clock = sdhci_omap_set_clock, |
| 802 | 839 | .set_power = sdhci_omap_set_power, |
| @@ -807,6 +844,7 @@ static struct sdhci_ops sdhci_omap_ops = { · 4 unmodified lines | ||
| 807 | 844 | .platform_send_init_74_clocks = sdhci_omap_init_74_clocks, |
| 808 | 845 | .reset = sdhci_omap_reset, |
| 809 | 846 | .set_uhs_signaling = sdhci_omap_set_uhs_signaling, |
| 847 | + .irq = sdhci_omap_irq, | |
| 810 | 848 | }; |
| 811 | 849 | |
| 812 | 850 | static int sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host) |