]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.4
authorSasha Levin <sashal@kernel.org>
Tue, 24 Aug 2021 02:59:54 +0000 (22:59 -0400)
committerSasha Levin <sashal@kernel.org>
Tue, 24 Aug 2021 02:59:54 +0000 (22:59 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.4/alsa-hda-fix-the-capture-switch-value-change-notific.patch [new file with mode: 0644]
queue-4.4/asoc-intel-atom-fix-breakage-for-pcm-buffer-address-.patch [new file with mode: 0644]
queue-4.4/ipack-tpci200-fix-many-double-free-issues-in-tpci200.patch [new file with mode: 0644]
queue-4.4/mmc-dw_mmc-call-the-dw_mci_prep_stop_abort-by-defaul.patch [new file with mode: 0644]
queue-4.4/mmc-dw_mmc-fix-hang-on-data-crc-error.patch [new file with mode: 0644]
queue-4.4/mmc-dw_mmc-wait-for-data-transfer-after-response-err.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/alsa-hda-fix-the-capture-switch-value-change-notific.patch b/queue-4.4/alsa-hda-fix-the-capture-switch-value-change-notific.patch
new file mode 100644 (file)
index 0000000..33d5655
--- /dev/null
@@ -0,0 +1,57 @@
+From e32f5cdf39c88203c875e3e873f22a12630e38d8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 11 Aug 2021 18:14:41 +0200
+Subject: ALSA: hda - fix the 'Capture Switch' value change notifications
+
+From: Jaroslav Kysela <perex@perex.cz>
+
+[ Upstream commit a2befe9380dd04ee76c871568deca00eedf89134 ]
+
+The original code in the cap_put_caller() function does not
+handle correctly the positive values returned from the passed
+function for multiple iterations. It means that the change
+notifications may be lost.
+
+Fixes: 352f7f914ebb ("ALSA: hda - Merge Realtek parser code to generic parser")
+BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=213851
+Cc: <stable@kernel.org>
+Signed-off-by: Jaroslav Kysela <perex@perex.cz>
+Link: https://lore.kernel.org/r/20210811161441.1325250-1-perex@perex.cz
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/pci/hda/hda_generic.c | 10 +++++++---
+ 1 file changed, 7 insertions(+), 3 deletions(-)
+
+diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
+index 7fed8d1bb79c..5c708d9851b8 100644
+--- a/sound/pci/hda/hda_generic.c
++++ b/sound/pci/hda/hda_generic.c
+@@ -3442,7 +3442,7 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
+       struct hda_gen_spec *spec = codec->spec;
+       const struct hda_input_mux *imux;
+       struct nid_path *path;
+-      int i, adc_idx, err = 0;
++      int i, adc_idx, ret, err = 0;
+       imux = &spec->input_mux;
+       adc_idx = kcontrol->id.index;
+@@ -3452,9 +3452,13 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
+               if (!path || !path->ctls[type])
+                       continue;
+               kcontrol->private_value = path->ctls[type];
+-              err = func(kcontrol, ucontrol);
+-              if (err < 0)
++              ret = func(kcontrol, ucontrol);
++              if (ret < 0) {
++                      err = ret;
+                       break;
++              }
++              if (ret > 0)
++                      err = 1;
+       }
+       mutex_unlock(&codec->control_mutex);
+       if (err >= 0 && spec->cap_sync_hook)
+-- 
+2.30.2
+
diff --git a/queue-4.4/asoc-intel-atom-fix-breakage-for-pcm-buffer-address-.patch b/queue-4.4/asoc-intel-atom-fix-breakage-for-pcm-buffer-address-.patch
new file mode 100644 (file)
index 0000000..1371bda
--- /dev/null
@@ -0,0 +1,48 @@
+From ed26a3147fd06f86db1f793be7cb34368050194f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 19 Aug 2021 17:29:45 +0200
+Subject: ASoC: intel: atom: Fix breakage for PCM buffer address setup
+
+From: Takashi Iwai <tiwai@suse.de>
+
+[ Upstream commit 65ca89c2b12cca0d473f3dd54267568ad3af55cc ]
+
+The commit 2e6b836312a4 ("ASoC: intel: atom: Fix reference to PCM
+buffer address") changed the reference of PCM buffer address to
+substream->runtime->dma_addr as the buffer address may change
+dynamically.  However, I forgot that the dma_addr field is still not
+set up for the CONTINUOUS buffer type (that this driver uses) yet in
+5.14 and earlier kernels, and it resulted in garbage I/O.  The problem
+will be fixed in 5.15, but we need to address it quickly for now.
+
+The fix is to deduce the address again from the DMA pointer with
+virt_to_phys(), but from the right one, substream->runtime->dma_area.
+
+Fixes: 2e6b836312a4 ("ASoC: intel: atom: Fix reference to PCM buffer address")
+Reported-and-tested-by: Hans de Goede <hdegoede@redhat.com>
+Cc: <stable@vger.kernel.org>
+Acked-by: Mark Brown <broonie@kernel.org>
+Link: https://lore.kernel.org/r/2048c6aa-2187-46bd-6772-36a4fb3c5aeb@redhat.com
+Link: https://lore.kernel.org/r/20210819152945.8510-1-tiwai@suse.de
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ sound/soc/intel/atom/sst-mfld-platform-pcm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sound/soc/intel/atom/sst-mfld-platform-pcm.c b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+index 64079423b298..d0d338533eb6 100644
+--- a/sound/soc/intel/atom/sst-mfld-platform-pcm.c
++++ b/sound/soc/intel/atom/sst-mfld-platform-pcm.c
+@@ -134,7 +134,7 @@ static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
+       snd_pcm_uframes_t period_size;
+       ssize_t periodbytes;
+       ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
+-      u32 buffer_addr = substream->runtime->dma_addr;
++      u32 buffer_addr = virt_to_phys(substream->runtime->dma_area);
+       channels = substream->runtime->channels;
+       period_size = substream->runtime->period_size;
+-- 
+2.30.2
+
diff --git a/queue-4.4/ipack-tpci200-fix-many-double-free-issues-in-tpci200.patch b/queue-4.4/ipack-tpci200-fix-many-double-free-issues-in-tpci200.patch
new file mode 100644 (file)
index 0000000..717ab67
--- /dev/null
@@ -0,0 +1,140 @@
+From 4c277d407bde44d220875990db2089d0be0ea4af Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 10 Aug 2021 18:03:18 +0800
+Subject: ipack: tpci200: fix many double free issues in tpci200_pci_probe
+
+From: Dongliang Mu <mudongliangabcd@gmail.com>
+
+[ Upstream commit 57a1681095f912239c7fb4d66683ab0425973838 ]
+
+The function tpci200_register called by tpci200_install and
+tpci200_unregister called by tpci200_uninstall are in pair. However,
+tpci200_unregister has some cleanup operations not in the
+tpci200_register. So the error handling code of tpci200_pci_probe has
+many different double free issues.
+
+Fix this problem by moving those cleanup operations out of
+tpci200_unregister, into tpci200_pci_remove and reverting
+the previous commit 9272e5d0028d ("ipack/carriers/tpci200:
+Fix a double free in tpci200_pci_probe").
+
+Fixes: 9272e5d0028d ("ipack/carriers/tpci200: Fix a double free in tpci200_pci_probe")
+Cc: stable@vger.kernel.org
+Reported-by: Dongliang Mu <mudongliangabcd@gmail.com>
+Signed-off-by: Dongliang Mu <mudongliangabcd@gmail.com>
+Link: https://lore.kernel.org/r/20210810100323.3938492-1-mudongliangabcd@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ipack/carriers/tpci200.c | 36 ++++++++++++++++----------------
+ 1 file changed, 18 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c
+index 7ba1a94497f5..4294523bede5 100644
+--- a/drivers/ipack/carriers/tpci200.c
++++ b/drivers/ipack/carriers/tpci200.c
+@@ -94,16 +94,13 @@ static void tpci200_unregister(struct tpci200_board *tpci200)
+       free_irq(tpci200->info->pdev->irq, (void *) tpci200);
+       pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
+-      pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
+       pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
+       pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
+       pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
+       pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
+-      pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
+       pci_disable_device(tpci200->info->pdev);
+-      pci_dev_put(tpci200->info->pdev);
+ }
+ static void tpci200_enable_irq(struct tpci200_board *tpci200,
+@@ -524,7 +521,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
+       tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
+       if (!tpci200->info) {
+               ret = -ENOMEM;
+-              goto out_err_info;
++              goto err_tpci200;
+       }
+       pci_dev_get(pdev);
+@@ -535,7 +532,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
+               ret = -EBUSY;
+-              goto out_err_pci_request;
++              goto err_tpci200_info;
+       }
+       tpci200->info->cfg_regs = ioremap_nocache(
+                       pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
+@@ -543,7 +540,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
+       if (!tpci200->info->cfg_regs) {
+               dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
+               ret = -EFAULT;
+-              goto out_err_ioremap;
++              goto err_request_region;
+       }
+       /* Disable byte swapping for 16 bit IP module access. This will ensure
+@@ -566,7 +563,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
+       if (ret) {
+               dev_err(&pdev->dev, "error during tpci200 install\n");
+               ret = -ENODEV;
+-              goto out_err_install;
++              goto err_cfg_regs;
+       }
+       /* Register the carrier in the industry pack bus driver */
+@@ -578,7 +575,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
+               dev_err(&pdev->dev,
+                       "error registering the carrier on ipack driver\n");
+               ret = -EFAULT;
+-              goto out_err_bus_register;
++              goto err_tpci200_install;
+       }
+       /* save the bus number given by ipack to logging purpose */
+@@ -589,19 +586,16 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
+               tpci200_create_device(tpci200, i);
+       return 0;
+-out_err_bus_register:
++err_tpci200_install:
+       tpci200_uninstall(tpci200);
+-      /* tpci200->info->cfg_regs is unmapped in tpci200_uninstall */
+-      tpci200->info->cfg_regs = NULL;
+-out_err_install:
+-      if (tpci200->info->cfg_regs)
+-              iounmap(tpci200->info->cfg_regs);
+-out_err_ioremap:
++err_cfg_regs:
++      pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
++err_request_region:
+       pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
+-out_err_pci_request:
+-      pci_dev_put(pdev);
++err_tpci200_info:
+       kfree(tpci200->info);
+-out_err_info:
++      pci_dev_put(pdev);
++err_tpci200:
+       kfree(tpci200);
+       return ret;
+ }
+@@ -611,6 +605,12 @@ static void __tpci200_pci_remove(struct tpci200_board *tpci200)
+       ipack_bus_unregister(tpci200->info->ipack_bus);
+       tpci200_uninstall(tpci200);
++      pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
++
++      pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
++
++      pci_dev_put(tpci200->info->pdev);
++
+       kfree(tpci200->info);
+       kfree(tpci200);
+ }
+-- 
+2.30.2
+
diff --git a/queue-4.4/mmc-dw_mmc-call-the-dw_mci_prep_stop_abort-by-defaul.patch b/queue-4.4/mmc-dw_mmc-call-the-dw_mci_prep_stop_abort-by-defaul.patch
new file mode 100644 (file)
index 0000000..d45f309
--- /dev/null
@@ -0,0 +1,80 @@
+From 14a6ee326ee6d20cfb878713e5876d6e0a11d8ab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Nov 2016 16:40:37 +0900
+Subject: mmc: dw_mmc: call the dw_mci_prep_stop_abort() by default
+
+From: Jaehoon Chung <jh80.chung@samsung.com>
+
+[ Upstream commit e13c3c081845b51e8ba71a90e91c52679cfdbf89 ]
+
+stop_cmdr should be set to values relevant to stop command.
+It migth be assigned to values whatever there is mrq->stop or not.
+Then it doesn't need to use dw_mci_prepare_command().
+It's enough to use the prep_stop_abort for preparing stop command.
+
+Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
+Tested-by: Heiko Stuebner <heiko@sntech.de>
+Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/dw_mmc.c | 15 +++++----------
+ 1 file changed, 5 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
+index afdf539e06e9..72ab0623293c 100644
+--- a/drivers/mmc/host/dw_mmc.c
++++ b/drivers/mmc/host/dw_mmc.c
+@@ -380,7 +380,7 @@ static void dw_mci_start_command(struct dw_mci *host,
+ static inline void send_stop_abort(struct dw_mci *host, struct mmc_data *data)
+ {
+-      struct mmc_command *stop = data->stop ? data->stop : &host->stop_abort;
++      struct mmc_command *stop = &host->stop_abort;
+       dw_mci_start_command(host, stop, host->stop_cmdr);
+ }
+@@ -1202,10 +1202,7 @@ static void __dw_mci_start_request(struct dw_mci *host,
+               spin_unlock_irqrestore(&host->irq_lock, irqflags);
+       }
+-      if (mrq->stop)
+-              host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop);
+-      else
+-              host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
++      host->stop_cmdr = dw_mci_prep_stop_abort(host, cmd);
+ }
+ static void dw_mci_start_request(struct dw_mci *host,
+@@ -1797,8 +1794,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
+                       if (test_and_clear_bit(EVENT_DATA_ERROR,
+                                              &host->pending_events)) {
+                               dw_mci_stop_dma(host);
+-                              if (data->stop ||
+-                                  !(host->data_status & (SDMMC_INT_DRTO |
++                              if (!(host->data_status & (SDMMC_INT_DRTO |
+                                                          SDMMC_INT_EBE)))
+                                       send_stop_abort(host, data);
+                               state = STATE_DATA_ERROR;
+@@ -1835,8 +1831,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
+                       if (test_and_clear_bit(EVENT_DATA_ERROR,
+                                              &host->pending_events)) {
+                               dw_mci_stop_dma(host);
+-                              if (data->stop ||
+-                                  !(host->data_status & (SDMMC_INT_DRTO |
++                              if (!(host->data_status & (SDMMC_INT_DRTO |
+                                                          SDMMC_INT_EBE)))
+                                       send_stop_abort(host, data);
+                               state = STATE_DATA_ERROR;
+@@ -1913,7 +1908,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
+                       host->cmd = NULL;
+                       host->data = NULL;
+-                      if (mrq->stop)
++                      if (!mrq->sbc && mrq->stop)
+                               dw_mci_command_complete(host, mrq->stop);
+                       else
+                               host->cmd_status = 0;
+-- 
+2.30.2
+
diff --git a/queue-4.4/mmc-dw_mmc-fix-hang-on-data-crc-error.patch b/queue-4.4/mmc-dw_mmc-fix-hang-on-data-crc-error.patch
new file mode 100644 (file)
index 0000000..da915cc
--- /dev/null
@@ -0,0 +1,73 @@
+From e97d2e43b5f56d0f98f2fb622ac4aaa333db823a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Jun 2021 12:22:32 +0200
+Subject: mmc: dw_mmc: Fix hang on data CRC error
+
+From: Vincent Whitchurch <vincent.whitchurch@axis.com>
+
+[ Upstream commit 25f8203b4be1937c4939bb98623e67dcfd7da4d1 ]
+
+When a Data CRC interrupt is received, the driver disables the DMA, then
+sends the stop/abort command and then waits for Data Transfer Over.
+
+However, sometimes, when a data CRC error is received in the middle of a
+multi-block write transfer, the Data Transfer Over interrupt is never
+received, and the driver hangs and never completes the request.
+
+The driver sets the BMOD.SWR bit (SDMMC_IDMAC_SWRESET) when stopping the
+DMA, but according to the manual CMD.STOP_ABORT_CMD should be programmed
+"before assertion of SWR".  Do these operations in the recommended
+order.  With this change the Data Transfer Over is always received
+correctly in my tests.
+
+Signed-off-by: Vincent Whitchurch <vincent.whitchurch@axis.com>
+Reviewed-by: Jaehoon Chung <jh80.chung@samsung.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210630102232.16011-1-vincent.whitchurch@axis.com
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/dw_mmc.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
+index 72ab0623293c..7bfe9ce03944 100644
+--- a/drivers/mmc/host/dw_mmc.c
++++ b/drivers/mmc/host/dw_mmc.c
+@@ -1768,8 +1768,8 @@ static void dw_mci_tasklet_func(unsigned long priv)
+                                       continue;
+                               }
+-                              dw_mci_stop_dma(host);
+                               send_stop_abort(host, data);
++                              dw_mci_stop_dma(host);
+                               state = STATE_SENDING_STOP;
+                               break;
+                       }
+@@ -1793,10 +1793,10 @@ static void dw_mci_tasklet_func(unsigned long priv)
+                        */
+                       if (test_and_clear_bit(EVENT_DATA_ERROR,
+                                              &host->pending_events)) {
+-                              dw_mci_stop_dma(host);
+                               if (!(host->data_status & (SDMMC_INT_DRTO |
+                                                          SDMMC_INT_EBE)))
+                                       send_stop_abort(host, data);
++                              dw_mci_stop_dma(host);
+                               state = STATE_DATA_ERROR;
+                               break;
+                       }
+@@ -1830,10 +1830,10 @@ static void dw_mci_tasklet_func(unsigned long priv)
+                        */
+                       if (test_and_clear_bit(EVENT_DATA_ERROR,
+                                              &host->pending_events)) {
+-                              dw_mci_stop_dma(host);
+                               if (!(host->data_status & (SDMMC_INT_DRTO |
+                                                          SDMMC_INT_EBE)))
+                                       send_stop_abort(host, data);
++                              dw_mci_stop_dma(host);
+                               state = STATE_DATA_ERROR;
+                               break;
+                       }
+-- 
+2.30.2
+
diff --git a/queue-4.4/mmc-dw_mmc-wait-for-data-transfer-after-response-err.patch b/queue-4.4/mmc-dw_mmc-wait-for-data-transfer-after-response-err.patch
new file mode 100644 (file)
index 0000000..bd52bc0
--- /dev/null
@@ -0,0 +1,100 @@
+From 8219d09226b9bad2f8b2cb409ba82e7fbbf8d1ba Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 26 Apr 2016 10:03:58 +0200
+Subject: mmc: dw_mmc: Wait for data transfer after response errors.
+
+From: Doug Anderson <dianders@chromium.org>
+
+[ Upstream commit 46d179525a1f6d16957dcb4624517bc04142b3e7 ]
+
+According to the DesignWare state machine description, after we get a
+"response error" or "response CRC error" we move into data transfer
+mode. That means that we don't necessarily need to special case
+trying to deal with the failure right away. We can wait until we are
+notified that the data transfer is complete (with or without errors)
+and then we can deal with the failure.
+
+It may sound strange to defer dealing with a command that we know will
+fail anyway, but this appears to fix a bug. During tuning (CMD19) on
+a specific card on an rk3288-based system, we found that we could get
+a "response CRC error". Sending the stop command after the "response
+CRC error" would then throw the system into a confused state causing
+all future tuning phases to report failure.
+
+When in the confused state, the controller would show these (hex codes
+are interrupt status register):
+ CMD ERR: 0x00000046 (cmd=19)
+ CMD ERR: 0x0000004e (cmd=12)
+ DATA ERR: 0x00000208
+ DATA ERR: 0x0000020c
+ CMD ERR: 0x00000104 (cmd=19)
+ CMD ERR: 0x00000104 (cmd=12)
+ DATA ERR: 0x00000208
+ DATA ERR: 0x0000020c
+ ...
+ ...
+
+It is inherently difficult to deal with the complexity of trying to
+correctly send a stop command while a data transfer is taking place
+since you need to deal with different corner cases caused by the fact
+that the data transfer could complete (with errors or without errors)
+during various places in sending the stop command (dw_mci_stop_dma,
+send_stop_abort, etc)
+
+Instead of adding a bunch of extra complexity to deal with this, it
+seems much simpler to just use the more straightforward (and less
+error-prone) path of letting the data transfer finish. There
+shouldn't be any huge benefit to sending the stop command slightly
+earlier, anyway.
+
+Signed-off-by: Doug Anderson <dianders@chromium.org>
+Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
+Cc: Alim Akhtar <alim.akhtar@gmail.com>
+Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com>
+Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mmc/host/dw_mmc.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
+index 581f5d0271f4..afdf539e06e9 100644
+--- a/drivers/mmc/host/dw_mmc.c
++++ b/drivers/mmc/host/dw_mmc.c
+@@ -1744,6 +1744,33 @@ static void dw_mci_tasklet_func(unsigned long priv)
+                       }
+                       if (cmd->data && err) {
++                              /*
++                               * During UHS tuning sequence, sending the stop
++                               * command after the response CRC error would
++                               * throw the system into a confused state
++                               * causing all future tuning phases to report
++                               * failure.
++                               *
++                               * In such case controller will move into a data
++                               * transfer state after a response error or
++                               * response CRC error. Let's let that finish
++                               * before trying to send a stop, so we'll go to
++                               * STATE_SENDING_DATA.
++                               *
++                               * Although letting the data transfer take place
++                               * will waste a bit of time (we already know
++                               * the command was bad), it can't cause any
++                               * errors since it's possible it would have
++                               * taken place anyway if this tasklet got
++                               * delayed. Allowing the transfer to take place
++                               * avoids races and keeps things simple.
++                               */
++                              if ((err != -ETIMEDOUT) &&
++                                  (cmd->opcode == MMC_SEND_TUNING_BLOCK)) {
++                                      state = STATE_SENDING_DATA;
++                                      continue;
++                              }
++
+                               dw_mci_stop_dma(host);
+                               send_stop_abort(host, data);
+                               state = STATE_SENDING_STOP;
+-- 
+2.30.2
+
index 212bb2cdce9351c2434100725372d17bc09af8c9..2671e91edd86b980ea39da829e6ee404831aa826 100644 (file)
@@ -22,3 +22,9 @@ bluetooth-hidp-use-correct-wait-queue-when-removing-.patch
 dccp-add-do-while-0-stubs-for-dccp_pr_debug-macros.patch
 net-6pack-fix-slab-out-of-bounds-in-decode_data.patch
 net-qlcnic-add-missed-unlock-in-qlcnic_83xx_flash_re.patch
+mmc-dw_mmc-wait-for-data-transfer-after-response-err.patch
+mmc-dw_mmc-call-the-dw_mci_prep_stop_abort-by-defaul.patch
+mmc-dw_mmc-fix-hang-on-data-crc-error.patch
+alsa-hda-fix-the-capture-switch-value-change-notific.patch
+ipack-tpci200-fix-many-double-free-issues-in-tpci200.patch
+asoc-intel-atom-fix-breakage-for-pcm-buffer-address-.patch