From 70984c8d185d43d92410a40f55e0424a9b87e550 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 23 Jun 2019 13:57:27 +0200 Subject: [PATCH] 4.19-stable patches added patches: mmc-core-add-sdio_retune_hold_now-and-sdio_retune_release.patch mmc-core-api-to-temporarily-disable-retuning-for-sdio-crc-errors.patch mmc-core-prevent-processing-sdio-irqs-when-the-card-is-suspended.patch mmc-sdhci-sdhci-pci-o2micro-correctly-set-bus-width-when-tuning.patch scsi-ufs-avoid-runtime-suspend-possibly-being-blocked-forever.patch usb-chipidea-udc-workaround-for-endpoint-conflict-issue.patch usb-xhci-don-t-try-to-recover-an-endpoint-if-port-is-in-error-state.patch xhci-detect-usb-3.2-capable-host-controllers-correctly.patch --- ...une_hold_now-and-sdio_retune_release.patch | 89 ++++++++++++ ...disable-retuning-for-sdio-crc-errors.patch | 133 ++++++++++++++++++ ...sdio-irqs-when-the-card-is-suspended.patch | 77 ++++++++++ ...-correctly-set-bus-width-when-tuning.patch | 49 +++++++ ...spend-possibly-being-blocked-forever.patch | 69 +++++++++ queue-4.19/series | 8 ++ ...rkaround-for-endpoint-conflict-issue.patch | 76 ++++++++++ ...n-endpoint-if-port-is-in-error-state.patch | 118 ++++++++++++++++ ...2-capable-host-controllers-correctly.patch | 67 +++++++++ 9 files changed, 686 insertions(+) create mode 100644 queue-4.19/mmc-core-add-sdio_retune_hold_now-and-sdio_retune_release.patch create mode 100644 queue-4.19/mmc-core-api-to-temporarily-disable-retuning-for-sdio-crc-errors.patch create mode 100644 queue-4.19/mmc-core-prevent-processing-sdio-irqs-when-the-card-is-suspended.patch create mode 100644 queue-4.19/mmc-sdhci-sdhci-pci-o2micro-correctly-set-bus-width-when-tuning.patch create mode 100644 queue-4.19/scsi-ufs-avoid-runtime-suspend-possibly-being-blocked-forever.patch create mode 100644 queue-4.19/usb-chipidea-udc-workaround-for-endpoint-conflict-issue.patch create mode 100644 queue-4.19/usb-xhci-don-t-try-to-recover-an-endpoint-if-port-is-in-error-state.patch create mode 100644 queue-4.19/xhci-detect-usb-3.2-capable-host-controllers-correctly.patch diff --git a/queue-4.19/mmc-core-add-sdio_retune_hold_now-and-sdio_retune_release.patch b/queue-4.19/mmc-core-add-sdio_retune_hold_now-and-sdio_retune_release.patch new file mode 100644 index 00000000000..68e1995d82c --- /dev/null +++ b/queue-4.19/mmc-core-add-sdio_retune_hold_now-and-sdio_retune_release.patch @@ -0,0 +1,89 @@ +From b4c9f938d542d5f88c501744d2d12fad4fd2915f Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Mon, 17 Jun 2019 10:56:52 -0700 +Subject: mmc: core: Add sdio_retune_hold_now() and sdio_retune_release() + +From: Douglas Anderson + +commit b4c9f938d542d5f88c501744d2d12fad4fd2915f upstream. + +We want SDIO drivers to be able to temporarily stop retuning when the +driver knows that the SDIO card is not in a state where retuning will +work (maybe because the card is asleep). We'll move the relevant +functions to a place where drivers can call them. + +Cc: stable@vger.kernel.org #v4.18+ +Signed-off-by: Douglas Anderson +Acked-by: Adrian Hunter +Acked-by: Kalle Valo +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/core/sdio_io.c | 40 ++++++++++++++++++++++++++++++++++++++++ + include/linux/mmc/sdio_func.h | 3 +++ + 2 files changed, 43 insertions(+) + +--- a/drivers/mmc/core/sdio_io.c ++++ b/drivers/mmc/core/sdio_io.c +@@ -18,6 +18,7 @@ + #include "sdio_ops.h" + #include "core.h" + #include "card.h" ++#include "host.h" + + /** + * sdio_claim_host - exclusively claim a bus for a certain SDIO function +@@ -762,3 +763,42 @@ void sdio_retune_crc_enable(struct sdio_ + func->card->host->retune_crc_disable = false; + } + EXPORT_SYMBOL_GPL(sdio_retune_crc_enable); ++ ++/** ++ * sdio_retune_hold_now - start deferring retuning requests till release ++ * @func: SDIO function attached to host ++ * ++ * This function can be called if it's currently a bad time to do ++ * a retune of the SDIO card. Retune requests made during this time ++ * will be held and we'll actually do the retune sometime after the ++ * release. ++ * ++ * This function could be useful if an SDIO card is in a power state ++ * where it can respond to a small subset of commands that doesn't ++ * include the retuning command. Care should be taken when using ++ * this function since (presumably) the retuning request we might be ++ * deferring was made for a good reason. ++ * ++ * This function should be called while the host is claimed. ++ */ ++void sdio_retune_hold_now(struct sdio_func *func) ++{ ++ mmc_retune_hold_now(func->card->host); ++} ++EXPORT_SYMBOL_GPL(sdio_retune_hold_now); ++ ++/** ++ * sdio_retune_release - signal that it's OK to retune now ++ * @func: SDIO function attached to host ++ * ++ * This is the complement to sdio_retune_hold_now(). Calling this ++ * function won't make a retune happen right away but will allow ++ * them to be scheduled normally. ++ * ++ * This function should be called while the host is claimed. ++ */ ++void sdio_retune_release(struct sdio_func *func) ++{ ++ mmc_retune_release(func->card->host); ++} ++EXPORT_SYMBOL_GPL(sdio_retune_release); +--- a/include/linux/mmc/sdio_func.h ++++ b/include/linux/mmc/sdio_func.h +@@ -162,4 +162,7 @@ extern int sdio_set_host_pm_flags(struct + extern void sdio_retune_crc_disable(struct sdio_func *func); + extern void sdio_retune_crc_enable(struct sdio_func *func); + ++extern void sdio_retune_hold_now(struct sdio_func *func); ++extern void sdio_retune_release(struct sdio_func *func); ++ + #endif /* LINUX_MMC_SDIO_FUNC_H */ diff --git a/queue-4.19/mmc-core-api-to-temporarily-disable-retuning-for-sdio-crc-errors.patch b/queue-4.19/mmc-core-api-to-temporarily-disable-retuning-for-sdio-crc-errors.patch new file mode 100644 index 00000000000..680a9853fc2 --- /dev/null +++ b/queue-4.19/mmc-core-api-to-temporarily-disable-retuning-for-sdio-crc-errors.patch @@ -0,0 +1,133 @@ +From 0a55f4ab9678413a01e740c86e9367ba0c612b36 Mon Sep 17 00:00:00 2001 +From: Douglas Anderson +Date: Mon, 17 Jun 2019 10:56:50 -0700 +Subject: mmc: core: API to temporarily disable retuning for SDIO CRC errors + +From: Douglas Anderson + +commit 0a55f4ab9678413a01e740c86e9367ba0c612b36 upstream. + +Normally when the MMC core sees an "-EILSEQ" error returned by a host +controller then it will trigger a retuning of the card. This is +generally a good idea. + +However, if a command is expected to sometimes cause transfer errors +then these transfer errors shouldn't cause a re-tuning. This +re-tuning will be a needless waste of time. One example case where a +transfer is expected to cause errors is when transitioning between +idle (sometimes referred to as "sleep" in Broadcom code) and active +state on certain Broadcom WiFi SDIO cards. Specifically if the card +was already transitioning between states when the command was sent it +could cause an error on the SDIO bus. + +Let's add an API that the SDIO function drivers can call that will +temporarily disable the auto-tuning functionality. Then we can add a +call to this in the Broadcom WiFi driver and any other driver that +might have similar needs. + +NOTE: this makes the assumption that the card is already tuned well +enough that it's OK to disable the auto-retuning during one of these +error-prone situations. Presumably the driver code performing the +error-prone transfer knows how to recover / retry from errors. ...and +after we can get back to a state where transfers are no longer +error-prone then we can enable the auto-retuning again. If we truly +find ourselves in a case where the card needs to be retuned sometimes +to handle one of these error-prone transfers then we can always try a +few transfers first without auto-retuning and then re-try with +auto-retuning if the first few fail. + +Without this change on rk3288-veyron-minnie I periodically see this in +the logs of a machine just sitting there idle: + dwmmc_rockchip ff0d0000.dwmmc: Successfully tuned phase to XYZ + +Cc: stable@vger.kernel.org #v4.18+ +Signed-off-by: Douglas Anderson +Acked-by: Adrian Hunter +Acked-by: Kalle Valo +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/core/core.c | 5 +++-- + drivers/mmc/core/sdio_io.c | 37 +++++++++++++++++++++++++++++++++++++ + include/linux/mmc/host.h | 1 + + include/linux/mmc/sdio_func.h | 3 +++ + 4 files changed, 44 insertions(+), 2 deletions(-) + +--- a/drivers/mmc/core/core.c ++++ b/drivers/mmc/core/core.c +@@ -144,8 +144,9 @@ void mmc_request_done(struct mmc_host *h + int err = cmd->error; + + /* Flag re-tuning needed on CRC errors */ +- if ((cmd->opcode != MMC_SEND_TUNING_BLOCK && +- cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200) && ++ if (cmd->opcode != MMC_SEND_TUNING_BLOCK && ++ cmd->opcode != MMC_SEND_TUNING_BLOCK_HS200 && ++ !host->retune_crc_disable && + (err == -EILSEQ || (mrq->sbc && mrq->sbc->error == -EILSEQ) || + (mrq->data && mrq->data->error == -EILSEQ) || + (mrq->stop && mrq->stop->error == -EILSEQ))) +--- a/drivers/mmc/core/sdio_io.c ++++ b/drivers/mmc/core/sdio_io.c +@@ -725,3 +725,40 @@ int sdio_set_host_pm_flags(struct sdio_f + return 0; + } + EXPORT_SYMBOL_GPL(sdio_set_host_pm_flags); ++ ++/** ++ * sdio_retune_crc_disable - temporarily disable retuning on CRC errors ++ * @func: SDIO function attached to host ++ * ++ * If the SDIO card is known to be in a state where it might produce ++ * CRC errors on the bus in response to commands (like if we know it is ++ * transitioning between power states), an SDIO function driver can ++ * call this function to temporarily disable the SD/MMC core behavior of ++ * triggering an automatic retuning. ++ * ++ * This function should be called while the host is claimed and the host ++ * should remain claimed until sdio_retune_crc_enable() is called. ++ * Specifically, the expected sequence of calls is: ++ * - sdio_claim_host() ++ * - sdio_retune_crc_disable() ++ * - some number of calls like sdio_writeb() and sdio_readb() ++ * - sdio_retune_crc_enable() ++ * - sdio_release_host() ++ */ ++void sdio_retune_crc_disable(struct sdio_func *func) ++{ ++ func->card->host->retune_crc_disable = true; ++} ++EXPORT_SYMBOL_GPL(sdio_retune_crc_disable); ++ ++/** ++ * sdio_retune_crc_enable - re-enable retuning on CRC errors ++ * @func: SDIO function attached to host ++ * ++ * This is the compement to sdio_retune_crc_disable(). ++ */ ++void sdio_retune_crc_enable(struct sdio_func *func) ++{ ++ func->card->host->retune_crc_disable = false; ++} ++EXPORT_SYMBOL_GPL(sdio_retune_crc_enable); +--- a/include/linux/mmc/host.h ++++ b/include/linux/mmc/host.h +@@ -395,6 +395,7 @@ struct mmc_host { + unsigned int retune_now:1; /* do re-tuning at next req */ + unsigned int retune_paused:1; /* re-tuning is temporarily disabled */ + unsigned int use_blk_mq:1; /* use blk-mq */ ++ unsigned int retune_crc_disable:1; /* don't trigger retune upon crc */ + + int rescan_disable; /* disable card detection */ + int rescan_entered; /* used with nonremovable devices */ +--- a/include/linux/mmc/sdio_func.h ++++ b/include/linux/mmc/sdio_func.h +@@ -159,4 +159,7 @@ extern void sdio_f0_writeb(struct sdio_f + extern mmc_pm_flag_t sdio_get_host_pm_caps(struct sdio_func *func); + extern int sdio_set_host_pm_flags(struct sdio_func *func, mmc_pm_flag_t flags); + ++extern void sdio_retune_crc_disable(struct sdio_func *func); ++extern void sdio_retune_crc_enable(struct sdio_func *func); ++ + #endif /* LINUX_MMC_SDIO_FUNC_H */ diff --git a/queue-4.19/mmc-core-prevent-processing-sdio-irqs-when-the-card-is-suspended.patch b/queue-4.19/mmc-core-prevent-processing-sdio-irqs-when-the-card-is-suspended.patch new file mode 100644 index 00000000000..5c5e89e5173 --- /dev/null +++ b/queue-4.19/mmc-core-prevent-processing-sdio-irqs-when-the-card-is-suspended.patch @@ -0,0 +1,77 @@ +From 83293386bc95cf5e9f0c0175794455835bd1cb4a Mon Sep 17 00:00:00 2001 +From: Ulf Hansson +Date: Tue, 18 Jun 2019 14:05:17 +0200 +Subject: mmc: core: Prevent processing SDIO IRQs when the card is suspended + +From: Ulf Hansson + +commit 83293386bc95cf5e9f0c0175794455835bd1cb4a upstream. + +Processing of SDIO IRQs must obviously be prevented while the card is +system suspended, otherwise we may end up trying to communicate with an +uninitialized SDIO card. + +Reports throughout the years shows that this is not only a theoretical +problem, but a real issue. So, let's finally fix this problem, by keeping +track of the state for the card and bail out before processing the SDIO +IRQ, in case the card is suspended. + +Cc: stable@vger.kernel.org +Reported-by: Douglas Anderson +Tested-by: Douglas Anderson +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/core/sdio.c | 13 ++++++++++++- + drivers/mmc/core/sdio_irq.c | 4 ++++ + 2 files changed, 16 insertions(+), 1 deletion(-) + +--- a/drivers/mmc/core/sdio.c ++++ b/drivers/mmc/core/sdio.c +@@ -934,6 +934,10 @@ static int mmc_sdio_pre_suspend(struct m + */ + static int mmc_sdio_suspend(struct mmc_host *host) + { ++ /* Prevent processing of SDIO IRQs in suspended state. */ ++ mmc_card_set_suspended(host->card); ++ cancel_delayed_work_sync(&host->sdio_irq_work); ++ + mmc_claim_host(host); + + if (mmc_card_keep_power(host) && mmc_card_wake_sdio_irq(host)) +@@ -982,13 +986,20 @@ static int mmc_sdio_resume(struct mmc_ho + err = sdio_enable_4bit_bus(host->card); + } + +- if (!err && host->sdio_irqs) { ++ if (err) ++ goto out; ++ ++ /* Allow SDIO IRQs to be processed again. */ ++ mmc_card_clr_suspended(host->card); ++ ++ if (host->sdio_irqs) { + if (!(host->caps2 & MMC_CAP2_SDIO_IRQ_NOTHREAD)) + wake_up_process(host->sdio_irq_thread); + else if (host->caps & MMC_CAP_SDIO_IRQ) + host->ops->enable_sdio_irq(host, 1); + } + ++out: + mmc_release_host(host); + + host->pm_flags &= ~MMC_PM_KEEP_POWER; +--- a/drivers/mmc/core/sdio_irq.c ++++ b/drivers/mmc/core/sdio_irq.c +@@ -38,6 +38,10 @@ static int process_sdio_pending_irqs(str + unsigned char pending; + struct sdio_func *func; + ++ /* Don't process SDIO IRQs if the card is suspended. */ ++ if (mmc_card_suspended(card)) ++ return 0; ++ + /* + * Optimization, if there is only 1 function interrupt registered + * and we know an IRQ was signaled then call irq handler directly. diff --git a/queue-4.19/mmc-sdhci-sdhci-pci-o2micro-correctly-set-bus-width-when-tuning.patch b/queue-4.19/mmc-sdhci-sdhci-pci-o2micro-correctly-set-bus-width-when-tuning.patch new file mode 100644 index 00000000000..549d59eb87b --- /dev/null +++ b/queue-4.19/mmc-sdhci-sdhci-pci-o2micro-correctly-set-bus-width-when-tuning.patch @@ -0,0 +1,49 @@ +From 0f7b79a44e7d7dd3ef1f59758c1a341f217ff5e5 Mon Sep 17 00:00:00 2001 +From: Raul E Rangel +Date: Mon, 17 Jun 2019 14:10:12 -0600 +Subject: mmc: sdhci: sdhci-pci-o2micro: Correctly set bus width when tuning + +From: Raul E Rangel + +commit 0f7b79a44e7d7dd3ef1f59758c1a341f217ff5e5 upstream. + +The O2Micro controller only supports tuning at 4-bits. So the host driver +needs to change the bus width while tuning and then set it back when done. + +There was a bug in the original implementation in that mmc->ios.bus_width +also wasn't updated. Thus setting the incorrect blocksize in +sdhci_send_tuning which results in a tuning failure. + +Signed-off-by: Raul E Rangel +Fixes: 0086fc217d5d7 ("mmc: sdhci: Add support for O2 hardware tuning") +Acked-by: Adrian Hunter +Cc: stable@vger.kernel.org +Signed-off-by: Ulf Hansson +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/mmc/host/sdhci-pci-o2micro.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/mmc/host/sdhci-pci-o2micro.c ++++ b/drivers/mmc/host/sdhci-pci-o2micro.c +@@ -117,6 +117,7 @@ static int sdhci_o2_execute_tuning(struc + */ + if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) { + current_bus_width = mmc->ios.bus_width; ++ mmc->ios.bus_width = MMC_BUS_WIDTH_4; + sdhci_set_bus_width(host, MMC_BUS_WIDTH_4); + } + +@@ -128,8 +129,10 @@ static int sdhci_o2_execute_tuning(struc + + sdhci_end_tuning(host); + +- if (current_bus_width == MMC_BUS_WIDTH_8) ++ if (current_bus_width == MMC_BUS_WIDTH_8) { ++ mmc->ios.bus_width = MMC_BUS_WIDTH_8; + sdhci_set_bus_width(host, current_bus_width); ++ } + + host->flags &= ~SDHCI_HS400_TUNING; + return 0; diff --git a/queue-4.19/scsi-ufs-avoid-runtime-suspend-possibly-being-blocked-forever.patch b/queue-4.19/scsi-ufs-avoid-runtime-suspend-possibly-being-blocked-forever.patch new file mode 100644 index 00000000000..6af543f36d4 --- /dev/null +++ b/queue-4.19/scsi-ufs-avoid-runtime-suspend-possibly-being-blocked-forever.patch @@ -0,0 +1,69 @@ +From 24e2e7a19f7e4b83d0d5189040d997bce3596473 Mon Sep 17 00:00:00 2001 +From: Stanley Chu +Date: Wed, 12 Jun 2019 23:19:05 +0800 +Subject: scsi: ufs: Avoid runtime suspend possibly being blocked forever + +From: Stanley Chu + +commit 24e2e7a19f7e4b83d0d5189040d997bce3596473 upstream. + +UFS runtime suspend can be triggered after pm_runtime_enable() is invoked +in ufshcd_pltfrm_init(). However if the first runtime suspend is triggered +before binding ufs_hba structure to ufs device structure via +platform_set_drvdata(), then UFS runtime suspend will be no longer +triggered in the future because its dev->power.runtime_error was set in the +first triggering and does not have any chance to be cleared. + +To be more clear, dev->power.runtime_error is set if hba is NULL in +ufshcd_runtime_suspend() which returns -EINVAL to rpm_callback() where +dev->power.runtime_error is set as -EINVAL. In this case, any future +rpm_suspend() for UFS device fails because rpm_check_suspend_allowed() +fails due to non-zero +dev->power.runtime_error. + +To resolve this issue, make sure the first UFS runtime suspend get valid +"hba" in ufshcd_runtime_suspend(): Enable UFS runtime PM only after hba is +successfully bound to UFS device structure. + +Fixes: 62694735ca95 ([SCSI] ufs: Add runtime PM support for UFS host controller driver) +Cc: stable@vger.kernel.org +Signed-off-by: Stanley Chu +Reviewed-by: Avri Altman +Signed-off-by: Martin K. Petersen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/scsi/ufs/ufshcd-pltfrm.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +--- a/drivers/scsi/ufs/ufshcd-pltfrm.c ++++ b/drivers/scsi/ufs/ufshcd-pltfrm.c +@@ -340,24 +340,21 @@ int ufshcd_pltfrm_init(struct platform_d + goto dealloc_host; + } + +- pm_runtime_set_active(&pdev->dev); +- pm_runtime_enable(&pdev->dev); +- + ufshcd_init_lanes_per_dir(hba); + + err = ufshcd_init(hba, mmio_base, irq); + if (err) { + dev_err(dev, "Initialization failed\n"); +- goto out_disable_rpm; ++ goto dealloc_host; + } + + platform_set_drvdata(pdev, hba); + ++ pm_runtime_set_active(&pdev->dev); ++ pm_runtime_enable(&pdev->dev); ++ + return 0; + +-out_disable_rpm: +- pm_runtime_disable(&pdev->dev); +- pm_runtime_set_suspended(&pdev->dev); + dealloc_host: + ufshcd_dealloc_host(hba); + out: diff --git a/queue-4.19/series b/queue-4.19/series index 9b8bdec0f50..36bc07e6a3f 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -9,3 +9,11 @@ ovl-don-t-fail-with-disconnected-lower-nfs.patch ovl-fix-bogus-wmaybe-unitialized-warning.patch s390-jump_label-use-jdd-constraint-on-gcc9.patch s390-ap-rework-assembler-functions-to-use-unions-for.patch +mmc-sdhci-sdhci-pci-o2micro-correctly-set-bus-width-when-tuning.patch +mmc-core-api-to-temporarily-disable-retuning-for-sdio-crc-errors.patch +mmc-core-add-sdio_retune_hold_now-and-sdio_retune_release.patch +mmc-core-prevent-processing-sdio-irqs-when-the-card-is-suspended.patch +scsi-ufs-avoid-runtime-suspend-possibly-being-blocked-forever.patch +usb-chipidea-udc-workaround-for-endpoint-conflict-issue.patch +xhci-detect-usb-3.2-capable-host-controllers-correctly.patch +usb-xhci-don-t-try-to-recover-an-endpoint-if-port-is-in-error-state.patch diff --git a/queue-4.19/usb-chipidea-udc-workaround-for-endpoint-conflict-issue.patch b/queue-4.19/usb-chipidea-udc-workaround-for-endpoint-conflict-issue.patch new file mode 100644 index 00000000000..c5ee0c7a5eb --- /dev/null +++ b/queue-4.19/usb-chipidea-udc-workaround-for-endpoint-conflict-issue.patch @@ -0,0 +1,76 @@ +From c19dffc0a9511a7d7493ec21019aefd97e9a111b Mon Sep 17 00:00:00 2001 +From: Peter Chen +Date: Mon, 17 Jun 2019 09:49:07 +0800 +Subject: usb: chipidea: udc: workaround for endpoint conflict issue + +From: Peter Chen + +commit c19dffc0a9511a7d7493ec21019aefd97e9a111b upstream. + +An endpoint conflict occurs when the USB is working in device mode +during an isochronous communication. When the endpointA IN direction +is an isochronous IN endpoint, and the host sends an IN token to +endpointA on another device, then the OUT transaction may be missed +regardless the OUT endpoint number. Generally, this occurs when the +device is connected to the host through a hub and other devices are +connected to the same hub. + +The affected OUT endpoint can be either control, bulk, isochronous, or +an interrupt endpoint. After the OUT endpoint is primed, if an IN token +to the same endpoint number on another device is received, then the OUT +endpoint may be unprimed (cannot be detected by software), which causes +this endpoint to no longer respond to the host OUT token, and thus, no +corresponding interrupt occurs. + +There is no good workaround for this issue, the only thing the software +could do is numbering isochronous IN from the highest endpoint since we +have observed most of device number endpoint from the lowest. + +Cc: #v3.14+ +Cc: Fabio Estevam +Cc: Greg KH +Cc: Sergei Shtylyov +Cc: Jun Li +Signed-off-by: Peter Chen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/chipidea/udc.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/drivers/usb/chipidea/udc.c ++++ b/drivers/usb/chipidea/udc.c +@@ -1621,6 +1621,25 @@ static int ci_udc_pullup(struct usb_gadg + static int ci_udc_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); + static int ci_udc_stop(struct usb_gadget *gadget); ++ ++/* Match ISOC IN from the highest endpoint */ ++static struct usb_ep *ci_udc_match_ep(struct usb_gadget *gadget, ++ struct usb_endpoint_descriptor *desc, ++ struct usb_ss_ep_comp_descriptor *comp_desc) ++{ ++ struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); ++ struct usb_ep *ep; ++ ++ if (usb_endpoint_xfer_isoc(desc) && usb_endpoint_dir_in(desc)) { ++ list_for_each_entry_reverse(ep, &ci->gadget.ep_list, ep_list) { ++ if (ep->caps.dir_in && !ep->claimed) ++ return ep; ++ } ++ } ++ ++ return NULL; ++} ++ + /** + * Device operations part of the API to the USB controller hardware, + * which don't involve endpoints (or i/o) +@@ -1634,6 +1653,7 @@ static const struct usb_gadget_ops usb_g + .vbus_draw = ci_udc_vbus_draw, + .udc_start = ci_udc_start, + .udc_stop = ci_udc_stop, ++ .match_ep = ci_udc_match_ep, + }; + + static int init_eps(struct ci_hdrc *ci) diff --git a/queue-4.19/usb-xhci-don-t-try-to-recover-an-endpoint-if-port-is-in-error-state.patch b/queue-4.19/usb-xhci-don-t-try-to-recover-an-endpoint-if-port-is-in-error-state.patch new file mode 100644 index 00000000000..675f230602b --- /dev/null +++ b/queue-4.19/usb-xhci-don-t-try-to-recover-an-endpoint-if-port-is-in-error-state.patch @@ -0,0 +1,118 @@ +From b8c3b718087bf7c3c8e388eb1f72ac1108a4926e Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Tue, 18 Jun 2019 17:27:47 +0300 +Subject: usb: xhci: Don't try to recover an endpoint if port is in error state. + +From: Mathias Nyman + +commit b8c3b718087bf7c3c8e388eb1f72ac1108a4926e upstream. + +A USB3 device needs to be reset and re-enumarated if the port it +connects to goes to a error state, with link state inactive. + +There is no use in trying to recover failed transactions by resetting +endpoints at this stage. Tests show that in rare cases, after multiple +endpoint resets of a roothub port the whole host controller might stop +completely. + +Several retries to recover from transaction error can happen as +it can take a long time before the hub thread discovers the USB3 +port error and inactive link. + +We can't reliably detect the port error from slot or endpoint context +due to a limitation in xhci, see xhci specs section 4.8.3: +"There are several cases where the EP State field in the Output +Endpoint Context may not reflect the current state of an endpoint" +and +"Software should maintain an accurate value for EP State, by tracking it +with an internal variable that is driven by Events and Doorbell accesses" + +Same appears to be true for slot state. + +set a flag to the corresponding slot if a USB3 roothub port link goes +inactive to prevent both queueing new URBs and resetting endpoints. + +Reported-by: Rapolu Chiranjeevi +Tested-by: Rapolu Chiranjeevi +Cc: +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci-ring.c | 15 ++++++++++++++- + drivers/usb/host/xhci.c | 5 +++++ + drivers/usb/host/xhci.h | 9 +++++++++ + 3 files changed, 28 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci-ring.c ++++ b/drivers/usb/host/xhci-ring.c +@@ -1604,8 +1604,13 @@ static void handle_port_status(struct xh + usb_hcd_resume_root_hub(hcd); + } + +- if (hcd->speed >= HCD_USB3 && (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) ++ if (hcd->speed >= HCD_USB3 && ++ (portsc & PORT_PLS_MASK) == XDEV_INACTIVE) { ++ slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1); ++ if (slot_id && xhci->devs[slot_id]) ++ xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR; + bus_state->port_remote_wakeup &= ~(1 << hcd_portnum); ++ } + + if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) { + xhci_dbg(xhci, "port resume event for port %d\n", port_id); +@@ -1793,6 +1798,14 @@ static void xhci_cleanup_halted_endpoint + { + struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; + struct xhci_command *command; ++ ++ /* ++ * Avoid resetting endpoint if link is inactive. Can cause host hang. ++ * Device will be reset soon to recover the link so don't do anything ++ */ ++ if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR) ++ return; ++ + command = xhci_alloc_command(xhci, false, GFP_ATOMIC); + if (!command) + return; +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -1441,6 +1441,10 @@ static int xhci_urb_enqueue(struct usb_h + xhci_dbg(xhci, "urb submitted during PCI suspend\n"); + return -ESHUTDOWN; + } ++ if (xhci->devs[slot_id]->flags & VDEV_PORT_ERROR) { ++ xhci_dbg(xhci, "Can't queue urb, port error, link inactive\n"); ++ return -ENODEV; ++ } + + if (usb_endpoint_xfer_isoc(&urb->ep->desc)) + num_tds = urb->number_of_packets; +@@ -3724,6 +3728,7 @@ static int xhci_discover_or_reset_device + } + /* If necessary, update the number of active TTs on this root port */ + xhci_update_tt_active_eps(xhci, virt_dev, old_active_eps); ++ virt_dev->flags = 0; + ret = 0; + + command_cleanup: +--- a/drivers/usb/host/xhci.h ++++ b/drivers/usb/host/xhci.h +@@ -1010,6 +1010,15 @@ struct xhci_virt_device { + u8 real_port; + struct xhci_interval_bw_table *bw_table; + struct xhci_tt_bw_info *tt_info; ++ /* ++ * flags for state tracking based on events and issued commands. ++ * Software can not rely on states from output contexts because of ++ * latency between events and xHC updating output context values. ++ * See xhci 1.1 section 4.8.3 for more details ++ */ ++ unsigned long flags; ++#define VDEV_PORT_ERROR BIT(0) /* Port error, link inactive */ ++ + /* The current max exit latency for the enabled USB3 link states. */ + u16 current_mel; + /* Used for the debugfs interfaces. */ diff --git a/queue-4.19/xhci-detect-usb-3.2-capable-host-controllers-correctly.patch b/queue-4.19/xhci-detect-usb-3.2-capable-host-controllers-correctly.patch new file mode 100644 index 00000000000..ba6f024542d --- /dev/null +++ b/queue-4.19/xhci-detect-usb-3.2-capable-host-controllers-correctly.patch @@ -0,0 +1,67 @@ +From ddd57980a0fde30f7b5d14b888a2cc84d01610e8 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Tue, 18 Jun 2019 17:27:48 +0300 +Subject: xhci: detect USB 3.2 capable host controllers correctly + +From: Mathias Nyman + +commit ddd57980a0fde30f7b5d14b888a2cc84d01610e8 upstream. + +USB 3.2 capability in a host can be detected from the +xHCI Supported Protocol Capability major and minor revision fields. + +If major is 0x3 and minor 0x20 then the host is USB 3.2 capable. + +For USB 3.2 capable hosts set the root hub lane count to 2. + +The Major Revision and Minor Revision fields contain a BCD version number. +The value of the Major Revision field is JJh and the value of the Minor +Revision field is MNh for version JJ.M.N, where JJ = major revision number, +M - minor version number, N = sub-minor version number, +e.g. version 3.1 is represented with a value of 0310h. + +Also fix the extra whitespace printed out when announcing regular +SuperSpeed hosts. + +Cc: # v4.18+ +Signed-off-by: Mathias Nyman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/xhci.c | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -5030,16 +5030,26 @@ int xhci_gen_setup(struct usb_hcd *hcd, + } else { + /* + * Some 3.1 hosts return sbrn 0x30, use xhci supported protocol +- * minor revision instead of sbrn ++ * minor revision instead of sbrn. Minor revision is a two digit ++ * BCD containing minor and sub-minor numbers, only show minor. + */ +- minor_rev = xhci->usb3_rhub.min_rev; +- if (minor_rev) { ++ minor_rev = xhci->usb3_rhub.min_rev / 0x10; ++ ++ switch (minor_rev) { ++ case 2: ++ hcd->speed = HCD_USB32; ++ hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; ++ hcd->self.root_hub->rx_lanes = 2; ++ hcd->self.root_hub->tx_lanes = 2; ++ break; ++ case 1: + hcd->speed = HCD_USB31; + hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; ++ break; + } +- xhci_info(xhci, "Host supports USB 3.%x %s SuperSpeed\n", ++ xhci_info(xhci, "Host supports USB 3.%x %sSuperSpeed\n", + minor_rev, +- minor_rev ? "Enhanced" : ""); ++ minor_rev ? "Enhanced " : ""); + + xhci->usb3_rhub.hcd = hcd; + /* xHCI private pointer was set in xhci_pci_probe for the second -- 2.47.3