--- /dev/null
+From 8195400f7ea95399f721ad21f4d663a62c65036f Mon Sep 17 00:00:00 2001
+From: Chris Wilson <chris@chris-wilson.co.uk>
+Date: Mon, 19 Oct 2020 11:15:23 +0100
+Subject: drm/i915: Force VT'd workarounds when running as a guest OS
+
+From: Chris Wilson <chris@chris-wilson.co.uk>
+
+commit 8195400f7ea95399f721ad21f4d663a62c65036f upstream.
+
+If i915.ko is being used as a passthrough device, it does not know if
+the host is using intel_iommu. Mixing the iommu and gfx causes a few
+issues (such as scanout overfetch) which we need to workaround inside
+the driver, so if we detect we are running under a hypervisor, also
+assume the device access is being virtualised.
+
+Reported-by: Stefan Fritsch <sf@sfritsch.de>
+Suggested-by: Stefan Fritsch <sf@sfritsch.de>
+Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
+Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
+Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
+Cc: Stefan Fritsch <sf@sfritsch.de>
+Cc: stable@vger.kernel.org
+Tested-by: Stefan Fritsch <sf@sfritsch.de>
+Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20201019101523.4145-1-chris@chris-wilson.co.uk
+(cherry picked from commit f566fdcd6cc49a9d5b5d782f56e3e7cb243f01b8)
+Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/gpu/drm/i915/i915_drv.h | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/i915/i915_drv.h
++++ b/drivers/gpu/drm/i915/i915_drv.h
+@@ -33,6 +33,8 @@
+ #include <uapi/drm/i915_drm.h>
+ #include <uapi/drm/drm_fourcc.h>
+
++#include <asm/hypervisor.h>
++
+ #include <linux/io-mapping.h>
+ #include <linux/i2c.h>
+ #include <linux/i2c-algo-bit.h>
+@@ -1716,7 +1718,9 @@ static inline bool intel_vtd_active(void
+ if (intel_iommu_gfx_mapped)
+ return true;
+ #endif
+- return false;
++
++ /* Running as a guest, we assume the host is enforcing VT'd */
++ return !hypervisor_is_type(X86_HYPER_NATIVE);
+ }
+
+ static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv)
--- /dev/null
+From d9216d753b2b1406b801243b12aaf00a5ce5b861 Mon Sep 17 00:00:00 2001
+From: Jason Gerecke <jason.gerecke@wacom.com>
+Date: Wed, 23 Sep 2020 13:14:56 -0700
+Subject: HID: wacom: Avoid entering wacom_wac_pen_report for pad / battery
+
+From: Jason Gerecke <jason.gerecke@wacom.com>
+
+commit d9216d753b2b1406b801243b12aaf00a5ce5b861 upstream.
+
+It has recently been reported that the "heartbeat" report from devices
+like the 2nd-gen Intuos Pro (PTH-460, PTH-660, PTH-860) or the 2nd-gen
+Bluetooth-enabled Intuos tablets (CTL-4100WL, CTL-6100WL) can cause the
+driver to send a spurious BTN_TOUCH=0 once per second in the middle of
+drawing. This can result in broken lines while drawing on Chrome OS.
+
+The source of the issue has been traced back to a change which modified
+the driver to only call `wacom_wac_pad_report()` once per report instead
+of once per collection. As part of this change, pad-handling code was
+removed from `wacom_wac_collection()` under the assumption that the
+`WACOM_PEN_FIELD` and `WACOM_TOUCH_FIELD` checks would not be satisfied
+when a pad or battery collection was being processed.
+
+To be clear, the macros `WACOM_PAD_FIELD` and `WACOM_PEN_FIELD` do not
+currently check exclusive conditions. In fact, most "pad" fields will
+also appear to be "pen" fields simply due to their presence inside of
+a Digitizer application collection. Because of this, the removal of
+the check from `wacom_wac_collection()` just causes pad / battery
+collections to instead trigger a call to `wacom_wac_pen_report()`
+instead. The pen report function in turn resets the tip switch state
+just prior to exiting, resulting in the observed BTN_TOUCH=0 symptom.
+
+To correct this, we restore a version of the `WACOM_PAD_FIELD` check
+in `wacom_wac_collection()` and return early. This effectively prevents
+pad / battery collections from being reported until the very end of the
+report as originally intended.
+
+Fixes: d4b8efeb46d9 ("HID: wacom: generic: Correct pad syncing")
+Cc: stable@vger.kernel.org # v4.17+
+Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
+Reviewed-by: Ping Cheng <ping.cheng@wacom.com>
+Tested-by: Ping Cheng <ping.cheng@wacom.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/wacom_wac.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/hid/wacom_wac.c
++++ b/drivers/hid/wacom_wac.c
+@@ -2773,7 +2773,9 @@ static int wacom_wac_collection(struct h
+ if (report->type != HID_INPUT_REPORT)
+ return -1;
+
+- if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
++ if (WACOM_PAD_FIELD(field))
++ return 0;
++ else if (WACOM_PEN_FIELD(field) && wacom->wacom_wac.pen_input)
+ wacom_wac_pen_report(hdev, report);
+ else if (WACOM_FINGER_FIELD(field) && wacom->wacom_wac.touch_input)
+ wacom_wac_finger_report(hdev, report);
btrfs-fix-use-after-free-on-readahead-extent-after-failure-to-create-it.patch
btrfs-fix-readahead-hang-and-use-after-free-after-removing-a-device.patch
btrfs-drop-the-path-before-adding-block-group-sysfs-files.patch
+usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch
+usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch
+usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch
+usb-dwc3-gadget-check-mps-of-the-request-length.patch
+usb-dwc3-gadget-reclaim-extra-trbs-after-request-completion.patch
+usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch
+usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch
+usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch
+usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch
+usb-cdns3-fix-on-chip-memory-overflow-issue.patch
+usb-cdc-acm-fix-cooldown-mechanism.patch
+usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch
+usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch
+usbcore-check-both-id_table-and-match-when-both-available.patch
+usb-apple-mfi-fastcharge-don-t-probe-unhandled-devices.patch
+drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch
+vt-keyboard-simplify-vt_kdgkbsent.patch
+vt-keyboard-extend-func_buf_lock-to-readers.patch
+vt_ioctl-fix-gio_unimap-regression.patch
+hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch
+x86-mce-allow-for-copy_mc_fragile-symbol-checksum-to-be-generated.patch
--- /dev/null
+From 0cb686692fd200db12dcfb8231e793c1c98aec41 Mon Sep 17 00:00:00 2001
+From: Bastien Nocera <hadess@hadess.net>
+Date: Thu, 22 Oct 2020 09:55:21 -0400
+Subject: USB: apple-mfi-fastcharge: don't probe unhandled devices
+
+From: Bastien Nocera <hadess@hadess.net>
+
+commit 0cb686692fd200db12dcfb8231e793c1c98aec41 upstream.
+
+From: Bastien Nocera <hadess@hadess.net>
+
+Contrary to the comment above the id table, we didn't implement a match
+function. This meant that every single Apple device that was already
+plugged in to the computer would have its device driver reprobed
+when the apple-mfi-fastcharge driver was loaded, eg. the SD card reader
+could be reprobed when the apple-mfi-fastcharge after pivoting root
+during boot up and the module became available.
+
+Make sure that the driver probe isn't being run for unsupported
+devices by adding a match function that checks the product ID, in
+addition to the id_table checking the vendor ID.
+
+Link: https://bugzilla.redhat.com/show_bug.cgi?id=1878347
+Link: https://lore.kernel.org/linux-usb/CAE3RAxt0WhBEz8zkHrVO5RiyEOasayy1QUAjsv-pB0fAbY1GSw@mail.gmail.com/
+Fixes: 249fa8217b84 ("USB: Add driver to control USB fast charge for iOS devices")
+Cc: <stable@vger.kernel.org> # 5.8
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+[m.v.b: Add Link and Reported-by tags to the commit message]
+Reported-by: Pany <pany@fedoraproject.org>
+Tested-by: Pan (Pany) YUAN <pany@fedoraproject.org>
+Tested-by: Bastien Nocera <hadess@hadess.net>
+Signed-off-by: Bastien Nocera <hadess@hadess.net>
+Signed-off-by: M. Vefa Bicakci <m.v.b@runbox.com>
+Link: https://lore.kernel.org/r/20201022135521.375211-3-m.v.b@runbox.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/misc/apple-mfi-fastcharge.c | 17 ++++++++++++-----
+ 1 file changed, 12 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/misc/apple-mfi-fastcharge.c
++++ b/drivers/usb/misc/apple-mfi-fastcharge.c
+@@ -163,17 +163,23 @@ static const struct power_supply_desc ap
+ .property_is_writeable = apple_mfi_fc_property_is_writeable
+ };
+
++static bool mfi_fc_match(struct usb_device *udev)
++{
++ int idProduct;
++
++ idProduct = le16_to_cpu(udev->descriptor.idProduct);
++ /* See comment above mfi_fc_id_table[] */
++ return (idProduct >= 0x1200 && idProduct <= 0x12ff);
++}
++
+ static int mfi_fc_probe(struct usb_device *udev)
+ {
+ struct power_supply_config battery_cfg = {};
+ struct mfi_device *mfi = NULL;
+- int err, idProduct;
++ int err;
+
+- idProduct = le16_to_cpu(udev->descriptor.idProduct);
+- /* See comment above mfi_fc_id_table[] */
+- if (idProduct < 0x1200 || idProduct > 0x12ff) {
++ if (!mfi_fc_match(udev))
+ return -ENODEV;
+- }
+
+ mfi = kzalloc(sizeof(struct mfi_device), GFP_KERNEL);
+ if (!mfi) {
+@@ -220,6 +226,7 @@ static struct usb_device_driver mfi_fc_d
+ .probe = mfi_fc_probe,
+ .disconnect = mfi_fc_disconnect,
+ .id_table = mfi_fc_id_table,
++ .match = mfi_fc_match,
+ .generic_subclass = 1,
+ };
+
--- /dev/null
+From 38203b8385bf6283537162bde7d499f830964711 Mon Sep 17 00:00:00 2001
+From: Jerome Brunet <jbrunet@baylibre.com>
+Date: Mon, 19 Oct 2020 19:07:02 +0200
+Subject: usb: cdc-acm: fix cooldown mechanism
+
+From: Jerome Brunet <jbrunet@baylibre.com>
+
+commit 38203b8385bf6283537162bde7d499f830964711 upstream.
+
+Commit a4e7279cd1d1 ("cdc-acm: introduce a cool down") is causing
+regression if there is some USB error, such as -EPROTO.
+
+This has been reported on some samples of the Odroid-N2 using the Combee II
+Zibgee USB dongle.
+
+> struct acm *acm = container_of(work, struct acm, work)
+
+is incorrect in case of a delayed work and causes warnings, usually from
+the workqueue:
+
+> WARNING: CPU: 0 PID: 0 at kernel/workqueue.c:1474 __queue_work+0x480/0x528.
+
+When this happens, USB eventually stops working completely after a while.
+Also the ACM_ERROR_DELAY bit is never set, so the cooldown mechanism
+previously introduced cannot be triggered and acm_submit_read_urb() is
+never called.
+
+This changes makes the cdc-acm driver use a single delayed work, fixing the
+pointer arithmetic in acm_softint() and set the ACM_ERROR_DELAY when the
+cooldown mechanism appear to be needed.
+
+Fixes: a4e7279cd1d1 ("cdc-acm: introduce a cool down")
+Cc: Oliver Neukum <oneukum@suse.com>
+Reported-by: Pascal Vizeli <pascal.vizeli@nabucasa.com>
+Acked-by: Oliver Neukum <oneukum@suse.com>
+Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
+Link: https://lore.kernel.org/r/20201019170702.150534-1-jbrunet@baylibre.com
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/class/cdc-acm.c | 12 +++++-------
+ drivers/usb/class/cdc-acm.h | 3 +--
+ 2 files changed, 6 insertions(+), 9 deletions(-)
+
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -507,6 +507,7 @@ static void acm_read_bulk_callback(struc
+ "%s - cooling babbling device\n", __func__);
+ usb_mark_last_busy(acm->dev);
+ set_bit(rb->index, &acm->urbs_in_error_delay);
++ set_bit(ACM_ERROR_DELAY, &acm->flags);
+ cooldown = true;
+ break;
+ default:
+@@ -532,7 +533,7 @@ static void acm_read_bulk_callback(struc
+
+ if (stopped || stalled || cooldown) {
+ if (stalled)
+- schedule_work(&acm->work);
++ schedule_delayed_work(&acm->dwork, 0);
+ else if (cooldown)
+ schedule_delayed_work(&acm->dwork, HZ / 2);
+ return;
+@@ -562,13 +563,13 @@ static void acm_write_bulk(struct urb *u
+ acm_write_done(acm, wb);
+ spin_unlock_irqrestore(&acm->write_lock, flags);
+ set_bit(EVENT_TTY_WAKEUP, &acm->flags);
+- schedule_work(&acm->work);
++ schedule_delayed_work(&acm->dwork, 0);
+ }
+
+ static void acm_softint(struct work_struct *work)
+ {
+ int i;
+- struct acm *acm = container_of(work, struct acm, work);
++ struct acm *acm = container_of(work, struct acm, dwork.work);
+
+ if (test_bit(EVENT_RX_STALL, &acm->flags)) {
+ smp_mb(); /* against acm_suspend() */
+@@ -584,7 +585,7 @@ static void acm_softint(struct work_stru
+ if (test_and_clear_bit(ACM_ERROR_DELAY, &acm->flags)) {
+ for (i = 0; i < acm->rx_buflimit; i++)
+ if (test_and_clear_bit(i, &acm->urbs_in_error_delay))
+- acm_submit_read_urb(acm, i, GFP_NOIO);
++ acm_submit_read_urb(acm, i, GFP_KERNEL);
+ }
+
+ if (test_and_clear_bit(EVENT_TTY_WAKEUP, &acm->flags))
+@@ -1364,7 +1365,6 @@ made_compressed_probe:
+ acm->ctrlsize = ctrlsize;
+ acm->readsize = readsize;
+ acm->rx_buflimit = num_rx_buf;
+- INIT_WORK(&acm->work, acm_softint);
+ INIT_DELAYED_WORK(&acm->dwork, acm_softint);
+ init_waitqueue_head(&acm->wioctl);
+ spin_lock_init(&acm->write_lock);
+@@ -1574,7 +1574,6 @@ static void acm_disconnect(struct usb_in
+ }
+
+ acm_kill_urbs(acm);
+- cancel_work_sync(&acm->work);
+ cancel_delayed_work_sync(&acm->dwork);
+
+ tty_unregister_device(acm_tty_driver, acm->minor);
+@@ -1617,7 +1616,6 @@ static int acm_suspend(struct usb_interf
+ return 0;
+
+ acm_kill_urbs(acm);
+- cancel_work_sync(&acm->work);
+ cancel_delayed_work_sync(&acm->dwork);
+ acm->urbs_in_error_delay = 0;
+
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -112,8 +112,7 @@ struct acm {
+ # define ACM_ERROR_DELAY 3
+ unsigned long urbs_in_error_delay; /* these need to be restarted after a delay */
+ struct usb_cdc_line_coding line; /* bits, stop, parity */
+- struct work_struct work; /* work queue entry for various purposes*/
+- struct delayed_work dwork; /* for cool downs needed in error recovery */
++ struct delayed_work dwork; /* work queue entry for various purposes */
+ unsigned int ctrlin; /* input control lines (DCD, DSR, RI, break, overruns) */
+ unsigned int ctrlout; /* output control lines (DTR, RTS) */
+ struct async_icount iocount; /* counters for control line changes */
--- /dev/null
+From 52d3967704aea6cb316d419a33a5e1d56d33a3c1 Mon Sep 17 00:00:00 2001
+From: Pawel Laszczak <pawell@cadence.com>
+Date: Thu, 22 Oct 2020 08:55:05 +0800
+Subject: usb: cdns3: Fix on-chip memory overflow issue
+
+From: Pawel Laszczak <pawell@cadence.com>
+
+commit 52d3967704aea6cb316d419a33a5e1d56d33a3c1 upstream.
+
+Patch fixes issue caused setting On-chip memory overflow bit in usb_sts
+register. The issue occurred because EP_CFG register was set twice
+before USB_STS.CFGSTS was set. Every write operation on EP_CFG.BUFFERING
+causes that controller increases internal counter holding the number
+of reserved on-chip buffers. First time this register was updated in
+function cdns3_ep_config before delegating SET_CONFIGURATION request
+to class driver and again it was updated when class wanted to enable
+endpoint. This patch fixes this issue by configuring endpoints
+enabled by class driver in cdns3_gadget_ep_enable and others just
+before status stage.
+
+Cc: stable@vger.kernel.org#v5.8+
+Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
+Reported-and-tested-by: Peter Chen <peter.chen@nxp.com>
+Signed-off-by: Pawel Laszczak <pawell@cadence.com>
+Signed-off-by: Peter Chen <peter.chen@nxp.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/cdns3/ep0.c | 65 +++++++++++++++-------------
+ drivers/usb/cdns3/gadget.c | 102 +++++++++++++++++++++++++--------------------
+ drivers/usb/cdns3/gadget.h | 3 -
+ 3 files changed, 94 insertions(+), 76 deletions(-)
+
+--- a/drivers/usb/cdns3/ep0.c
++++ b/drivers/usb/cdns3/ep0.c
+@@ -137,48 +137,36 @@ static int cdns3_req_ep0_set_configurati
+ struct usb_ctrlrequest *ctrl_req)
+ {
+ enum usb_device_state device_state = priv_dev->gadget.state;
+- struct cdns3_endpoint *priv_ep;
+ u32 config = le16_to_cpu(ctrl_req->wValue);
+ int result = 0;
+- int i;
+
+ switch (device_state) {
+ case USB_STATE_ADDRESS:
+- /* Configure non-control EPs */
+- for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) {
+- priv_ep = priv_dev->eps[i];
+- if (!priv_ep)
+- continue;
+-
+- if (priv_ep->flags & EP_CLAIMED)
+- cdns3_ep_config(priv_ep);
+- }
+-
+ result = cdns3_ep0_delegate_req(priv_dev, ctrl_req);
+
+- if (result)
+- return result;
+-
+- if (!config) {
+- cdns3_hw_reset_eps_config(priv_dev);
+- usb_gadget_set_state(&priv_dev->gadget,
+- USB_STATE_ADDRESS);
+- }
++ if (result || !config)
++ goto reset_config;
+
+ break;
+ case USB_STATE_CONFIGURED:
+ result = cdns3_ep0_delegate_req(priv_dev, ctrl_req);
++ if (!config && !result)
++ goto reset_config;
+
+- if (!config && !result) {
+- cdns3_hw_reset_eps_config(priv_dev);
+- usb_gadget_set_state(&priv_dev->gadget,
+- USB_STATE_ADDRESS);
+- }
+ break;
+ default:
+- result = -EINVAL;
++ return -EINVAL;
+ }
+
++ return 0;
++
++reset_config:
++ if (result != USB_GADGET_DELAYED_STATUS)
++ cdns3_hw_reset_eps_config(priv_dev);
++
++ usb_gadget_set_state(&priv_dev->gadget,
++ USB_STATE_ADDRESS);
++
+ return result;
+ }
+
+@@ -705,6 +693,7 @@ static int cdns3_gadget_ep0_queue(struct
+ unsigned long flags;
+ int ret = 0;
+ u8 zlp = 0;
++ int i;
+
+ spin_lock_irqsave(&priv_dev->lock, flags);
+ trace_cdns3_ep0_queue(priv_dev, request);
+@@ -718,6 +707,17 @@ static int cdns3_gadget_ep0_queue(struct
+ /* send STATUS stage. Should be called only for SET_CONFIGURATION */
+ if (priv_dev->ep0_stage == CDNS3_STATUS_STAGE) {
+ cdns3_select_ep(priv_dev, 0x00);
++
++ /*
++ * Configure all non-control EPs which are not enabled by class driver
++ */
++ for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++) {
++ priv_ep = priv_dev->eps[i];
++ if (priv_ep && priv_ep->flags & EP_CLAIMED &&
++ !(priv_ep->flags & EP_ENABLED))
++ cdns3_ep_config(priv_ep, 0);
++ }
++
+ cdns3_set_hw_configuration(priv_dev);
+ cdns3_ep0_complete_setup(priv_dev, 0, 1);
+ request->actual = 0;
+@@ -803,6 +803,7 @@ void cdns3_ep0_config(struct cdns3_devic
+ struct cdns3_usb_regs __iomem *regs;
+ struct cdns3_endpoint *priv_ep;
+ u32 max_packet_size = 64;
++ u32 ep_cfg;
+
+ regs = priv_dev->regs;
+
+@@ -834,8 +835,10 @@ void cdns3_ep0_config(struct cdns3_devic
+ BIT(0) | BIT(16));
+ }
+
+- writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size),
+- ®s->ep_cfg);
++ ep_cfg = EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size);
++
++ if (!(priv_ep->flags & EP_CONFIGURED))
++ writel(ep_cfg, ®s->ep_cfg);
+
+ writel(EP_STS_EN_SETUPEN | EP_STS_EN_DESCMISEN | EP_STS_EN_TRBERREN,
+ ®s->ep_sts_en);
+@@ -843,8 +846,10 @@ void cdns3_ep0_config(struct cdns3_devic
+ /* init ep in */
+ cdns3_select_ep(priv_dev, USB_DIR_IN);
+
+- writel(EP_CFG_ENABLE | EP_CFG_MAXPKTSIZE(max_packet_size),
+- ®s->ep_cfg);
++ if (!(priv_ep->flags & EP_CONFIGURED))
++ writel(ep_cfg, ®s->ep_cfg);
++
++ priv_ep->flags |= EP_CONFIGURED;
+
+ writel(EP_STS_EN_SETUPEN | EP_STS_EN_TRBERREN, ®s->ep_sts_en);
+
+--- a/drivers/usb/cdns3/gadget.c
++++ b/drivers/usb/cdns3/gadget.c
+@@ -296,6 +296,8 @@ static void cdns3_ep_stall_flush(struct
+ */
+ void cdns3_hw_reset_eps_config(struct cdns3_device *priv_dev)
+ {
++ int i;
++
+ writel(USB_CONF_CFGRST, &priv_dev->regs->usb_conf);
+
+ cdns3_allow_enable_l1(priv_dev, 0);
+@@ -304,6 +306,10 @@ void cdns3_hw_reset_eps_config(struct cd
+ priv_dev->out_mem_is_allocated = 0;
+ priv_dev->wait_for_setup = 0;
+ priv_dev->using_streams = 0;
++
++ for (i = 0; i < CDNS3_ENDPOINTS_MAX_COUNT; i++)
++ if (priv_dev->eps[i])
++ priv_dev->eps[i]->flags &= ~EP_CONFIGURED;
+ }
+
+ /**
+@@ -1907,27 +1913,6 @@ static int cdns3_ep_onchip_buffer_reserv
+ return 0;
+ }
+
+-static void cdns3_stream_ep_reconfig(struct cdns3_device *priv_dev,
+- struct cdns3_endpoint *priv_ep)
+-{
+- if (!priv_ep->use_streams || priv_dev->gadget.speed < USB_SPEED_SUPER)
+- return;
+-
+- if (priv_dev->dev_ver >= DEV_VER_V3) {
+- u32 mask = BIT(priv_ep->num + (priv_ep->dir ? 16 : 0));
+-
+- /*
+- * Stream capable endpoints are handled by using ep_tdl
+- * register. Other endpoints use TDL from TRB feature.
+- */
+- cdns3_clear_register_bit(&priv_dev->regs->tdl_from_trb, mask);
+- }
+-
+- /* Enable Stream Bit TDL chk and SID chk */
+- cdns3_set_register_bit(&priv_dev->regs->ep_cfg, EP_CFG_STREAM_EN |
+- EP_CFG_TDL_CHK | EP_CFG_SID_CHK);
+-}
+-
+ static void cdns3_configure_dmult(struct cdns3_device *priv_dev,
+ struct cdns3_endpoint *priv_ep)
+ {
+@@ -1965,8 +1950,9 @@ static void cdns3_configure_dmult(struct
+ /**
+ * cdns3_ep_config Configure hardware endpoint
+ * @priv_ep: extended endpoint object
++ * @enable: set EP_CFG_ENABLE bit in ep_cfg register.
+ */
+-void cdns3_ep_config(struct cdns3_endpoint *priv_ep)
++int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
+ {
+ bool is_iso_ep = (priv_ep->type == USB_ENDPOINT_XFER_ISOC);
+ struct cdns3_device *priv_dev = priv_ep->cdns3_dev;
+@@ -2027,7 +2013,7 @@ void cdns3_ep_config(struct cdns3_endpoi
+ break;
+ default:
+ /* all other speed are not supported */
+- return;
++ return -EINVAL;
+ }
+
+ if (max_packet_size == 1024)
+@@ -2037,11 +2023,33 @@ void cdns3_ep_config(struct cdns3_endpoi
+ else
+ priv_ep->trb_burst_size = 16;
+
+- ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1,
+- !!priv_ep->dir);
+- if (ret) {
+- dev_err(priv_dev->dev, "onchip mem is full, ep is invalid\n");
+- return;
++ /* onchip buffer is only allocated before configuration */
++ if (!priv_dev->hw_configured_flag) {
++ ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1,
++ !!priv_ep->dir);
++ if (ret) {
++ dev_err(priv_dev->dev, "onchip mem is full, ep is invalid\n");
++ return ret;
++ }
++ }
++
++ if (enable)
++ ep_cfg |= EP_CFG_ENABLE;
++
++ if (priv_ep->use_streams && priv_dev->gadget.speed >= USB_SPEED_SUPER) {
++ if (priv_dev->dev_ver >= DEV_VER_V3) {
++ u32 mask = BIT(priv_ep->num + (priv_ep->dir ? 16 : 0));
++
++ /*
++ * Stream capable endpoints are handled by using ep_tdl
++ * register. Other endpoints use TDL from TRB feature.
++ */
++ cdns3_clear_register_bit(&priv_dev->regs->tdl_from_trb,
++ mask);
++ }
++
++ /* Enable Stream Bit TDL chk and SID chk */
++ ep_cfg |= EP_CFG_STREAM_EN | EP_CFG_TDL_CHK | EP_CFG_SID_CHK;
+ }
+
+ ep_cfg |= EP_CFG_MAXPKTSIZE(max_packet_size) |
+@@ -2051,9 +2059,12 @@ void cdns3_ep_config(struct cdns3_endpoi
+
+ cdns3_select_ep(priv_dev, bEndpointAddress);
+ writel(ep_cfg, &priv_dev->regs->ep_cfg);
++ priv_ep->flags |= EP_CONFIGURED;
+
+ dev_dbg(priv_dev->dev, "Configure %s: with val %08x\n",
+ priv_ep->name, ep_cfg);
++
++ return 0;
+ }
+
+ /* Find correct direction for HW endpoint according to description */
+@@ -2194,7 +2205,7 @@ static int cdns3_gadget_ep_enable(struct
+ u32 bEndpointAddress;
+ unsigned long flags;
+ int enable = 1;
+- int ret;
++ int ret = 0;
+ int val;
+
+ priv_ep = ep_to_cdns3_ep(ep);
+@@ -2233,6 +2244,17 @@ static int cdns3_gadget_ep_enable(struct
+ bEndpointAddress = priv_ep->num | priv_ep->dir;
+ cdns3_select_ep(priv_dev, bEndpointAddress);
+
++ /*
++ * For some versions of controller at some point during ISO OUT traffic
++ * DMA reads Transfer Ring for the EP which has never got doorbell.
++ * This issue was detected only on simulation, but to avoid this issue
++ * driver add protection against it. To fix it driver enable ISO OUT
++ * endpoint before setting DRBL. This special treatment of ISO OUT
++ * endpoints are recommended by controller specification.
++ */
++ if (priv_ep->type == USB_ENDPOINT_XFER_ISOC && !priv_ep->dir)
++ enable = 0;
++
+ if (usb_ss_max_streams(comp_desc) && usb_endpoint_xfer_bulk(desc)) {
+ /*
+ * Enable stream support (SS mode) related interrupts
+@@ -2243,13 +2265,17 @@ static int cdns3_gadget_ep_enable(struct
+ EP_STS_EN_SIDERREN | EP_STS_EN_MD_EXITEN |
+ EP_STS_EN_STREAMREN;
+ priv_ep->use_streams = true;
+- cdns3_stream_ep_reconfig(priv_dev, priv_ep);
++ ret = cdns3_ep_config(priv_ep, enable);
+ priv_dev->using_streams |= true;
+ }
++ } else {
++ ret = cdns3_ep_config(priv_ep, enable);
+ }
+
+- ret = cdns3_allocate_trb_pool(priv_ep);
++ if (ret)
++ goto exit;
+
++ ret = cdns3_allocate_trb_pool(priv_ep);
+ if (ret)
+ goto exit;
+
+@@ -2279,20 +2305,6 @@ static int cdns3_gadget_ep_enable(struct
+
+ writel(reg, &priv_dev->regs->ep_sts_en);
+
+- /*
+- * For some versions of controller at some point during ISO OUT traffic
+- * DMA reads Transfer Ring for the EP which has never got doorbell.
+- * This issue was detected only on simulation, but to avoid this issue
+- * driver add protection against it. To fix it driver enable ISO OUT
+- * endpoint before setting DRBL. This special treatment of ISO OUT
+- * endpoints are recommended by controller specification.
+- */
+- if (priv_ep->type == USB_ENDPOINT_XFER_ISOC && !priv_ep->dir)
+- enable = 0;
+-
+- if (enable)
+- cdns3_set_register_bit(&priv_dev->regs->ep_cfg, EP_CFG_ENABLE);
+-
+ ep->desc = desc;
+ priv_ep->flags &= ~(EP_PENDING_REQUEST | EP_STALLED | EP_STALL_PENDING |
+ EP_QUIRK_ISO_OUT_EN | EP_QUIRK_EXTRA_BUF_EN);
+--- a/drivers/usb/cdns3/gadget.h
++++ b/drivers/usb/cdns3/gadget.h
+@@ -1154,6 +1154,7 @@ struct cdns3_endpoint {
+ #define EP_QUIRK_EXTRA_BUF_DET BIT(12)
+ #define EP_QUIRK_EXTRA_BUF_EN BIT(13)
+ #define EP_TDLCHK_EN BIT(15)
++#define EP_CONFIGURED BIT(16)
+ u32 flags;
+
+ struct cdns3_request *descmis_req;
+@@ -1351,7 +1352,7 @@ void cdns3_gadget_giveback(struct cdns3_
+ int cdns3_init_ep0(struct cdns3_device *priv_dev,
+ struct cdns3_endpoint *priv_ep);
+ void cdns3_ep0_config(struct cdns3_device *priv_dev);
+-void cdns3_ep_config(struct cdns3_endpoint *priv_ep);
++int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable);
+ void cdns3_check_ep0_interrupt_proceed(struct cdns3_device *priv_dev, int dir);
+ int __cdns3_gadget_wakeup(struct cdns3_device *priv_dev);
+
--- /dev/null
+From 03c1fd622f72c7624c81b64fdba4a567ae5ee9cb Mon Sep 17 00:00:00 2001
+From: Li Jun <jun.li@nxp.com>
+Date: Tue, 28 Jul 2020 20:42:41 +0800
+Subject: usb: dwc3: core: add phy cleanup for probe error handling
+
+From: Li Jun <jun.li@nxp.com>
+
+commit 03c1fd622f72c7624c81b64fdba4a567ae5ee9cb upstream.
+
+Add the phy cleanup if dwc3 mode init fail, which is the missing part of
+de-init for dwc3 core init.
+
+Fixes: c499ff71ff2a ("usb: dwc3: core: re-factor init and exit paths")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Li Jun <jun.li@nxp.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/core.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -1564,6 +1564,17 @@ static int dwc3_probe(struct platform_de
+
+ err5:
+ dwc3_event_buffers_cleanup(dwc);
++
++ usb_phy_shutdown(dwc->usb2_phy);
++ usb_phy_shutdown(dwc->usb3_phy);
++ phy_exit(dwc->usb2_generic_phy);
++ phy_exit(dwc->usb3_generic_phy);
++
++ usb_phy_set_suspend(dwc->usb2_phy, 1);
++ usb_phy_set_suspend(dwc->usb3_phy, 1);
++ phy_power_off(dwc->usb2_generic_phy);
++ phy_power_off(dwc->usb3_generic_phy);
++
+ dwc3_ulpi_exit(dwc);
+
+ err4:
--- /dev/null
+From 266d0493900ac5d6a21cdbe6b1624ed2da94d47a Mon Sep 17 00:00:00 2001
+From: Li Jun <jun.li@nxp.com>
+Date: Tue, 28 Jul 2020 20:42:40 +0800
+Subject: usb: dwc3: core: don't trigger runtime pm when remove driver
+
+From: Li Jun <jun.li@nxp.com>
+
+commit 266d0493900ac5d6a21cdbe6b1624ed2da94d47a upstream.
+
+No need to trigger runtime pm in driver removal, otherwise if user
+disable auto suspend via sys file, runtime suspend may be entered,
+which will call dwc3_core_exit() again and there will be clock disable
+not balance warning:
+
+[ 2026.820154] xhci-hcd xhci-hcd.0.auto: remove, state 4
+[ 2026.825268] usb usb2: USB disconnect, device number 1
+[ 2026.831017] xhci-hcd xhci-hcd.0.auto: USB bus 2 deregistered
+[ 2026.836806] xhci-hcd xhci-hcd.0.auto: remove, state 4
+[ 2026.842029] usb usb1: USB disconnect, device number 1
+[ 2026.848029] xhci-hcd xhci-hcd.0.auto: USB bus 1 deregistered
+[ 2026.865889] ------------[ cut here ]------------
+[ 2026.870506] usb2_ctrl_root_clk already disabled
+[ 2026.875082] WARNING: CPU: 0 PID: 731 at drivers/clk/clk.c:958
+clk_core_disable+0xa0/0xa8
+[ 2026.883170] Modules linked in: dwc3(-) phy_fsl_imx8mq_usb [last
+unloaded: dwc3]
+[ 2026.890488] CPU: 0 PID: 731 Comm: rmmod Not tainted
+5.8.0-rc7-00280-g9d08cca-dirty #245
+[ 2026.898489] Hardware name: NXP i.MX8MQ EVK (DT)
+[ 2026.903020] pstate: 20000085 (nzCv daIf -PAN -UAO BTYPE=--)
+[ 2026.908594] pc : clk_core_disable+0xa0/0xa8
+[ 2026.912777] lr : clk_core_disable+0xa0/0xa8
+[ 2026.916958] sp : ffff8000121b39a0
+[ 2026.920271] x29: ffff8000121b39a0 x28: ffff0000b11f3700
+[ 2026.925583] x27: 0000000000000000 x26: ffff0000b539c700
+[ 2026.930895] x25: 000001d7e44e1232 x24: ffff0000b76fa800
+[ 2026.936208] x23: ffff0000b76fa6f8 x22: ffff800008d01040
+[ 2026.941520] x21: ffff0000b539ce00 x20: ffff0000b7105000
+[ 2026.946832] x19: ffff0000b7105000 x18: 0000000000000010
+[ 2026.952144] x17: 0000000000000001 x16: 0000000000000000
+[ 2026.957456] x15: ffff0000b11f3b70 x14: ffffffffffffffff
+[ 2026.962768] x13: ffff8000921b36f7 x12: ffff8000121b36ff
+[ 2026.968080] x11: ffff8000119e1000 x10: ffff800011bf26d0
+[ 2026.973392] x9 : 0000000000000000 x8 : ffff800011bf3000
+[ 2026.978704] x7 : ffff800010695d68 x6 : 0000000000000252
+[ 2026.984016] x5 : ffff0000bb9881f0 x4 : 0000000000000000
+[ 2026.989327] x3 : 0000000000000027 x2 : 0000000000000023
+[ 2026.994639] x1 : ac2fa471aa7cab00 x0 : 0000000000000000
+[ 2026.999951] Call trace:
+[ 2027.002401] clk_core_disable+0xa0/0xa8
+[ 2027.006238] clk_core_disable_lock+0x20/0x38
+[ 2027.010508] clk_disable+0x1c/0x28
+[ 2027.013911] clk_bulk_disable+0x34/0x50
+[ 2027.017758] dwc3_core_exit+0xec/0x110 [dwc3]
+[ 2027.022122] dwc3_suspend_common+0x84/0x188 [dwc3]
+[ 2027.026919] dwc3_runtime_suspend+0x74/0x9c [dwc3]
+[ 2027.031712] pm_generic_runtime_suspend+0x28/0x40
+[ 2027.036419] genpd_runtime_suspend+0xa0/0x258
+[ 2027.040777] __rpm_callback+0x88/0x140
+[ 2027.044526] rpm_callback+0x20/0x80
+[ 2027.048015] rpm_suspend+0xd0/0x418
+[ 2027.051503] __pm_runtime_suspend+0x58/0xa0
+[ 2027.055693] dwc3_runtime_idle+0x7c/0x90 [dwc3]
+[ 2027.060224] __rpm_callback+0x88/0x140
+[ 2027.063973] rpm_idle+0x78/0x150
+[ 2027.067201] __pm_runtime_idle+0x58/0xa0
+[ 2027.071130] dwc3_remove+0x64/0xc0 [dwc3]
+[ 2027.075140] platform_drv_remove+0x28/0x48
+[ 2027.079239] device_release_driver_internal+0xf4/0x1c0
+[ 2027.084377] driver_detach+0x4c/0xd8
+[ 2027.087954] bus_remove_driver+0x54/0xa8
+[ 2027.091877] driver_unregister+0x2c/0x58
+[ 2027.095799] platform_driver_unregister+0x10/0x18
+[ 2027.100509] dwc3_driver_exit+0x14/0x1408 [dwc3]
+[ 2027.105129] __arm64_sys_delete_module+0x178/0x218
+[ 2027.109922] el0_svc_common.constprop.0+0x68/0x160
+[ 2027.114714] do_el0_svc+0x20/0x80
+[ 2027.118031] el0_sync_handler+0x88/0x190
+[ 2027.121953] el0_sync+0x140/0x180
+[ 2027.125267] ---[ end trace 027f4f8189958f1f ]---
+[ 2027.129976] ------------[ cut here ]------------
+
+Fixes: fc8bb91bc83e ("usb: dwc3: implement runtime PM")
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Li Jun <jun.li@nxp.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/core.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -1610,9 +1610,9 @@ static int dwc3_remove(struct platform_d
+ dwc3_core_exit(dwc);
+ dwc3_ulpi_exit(dwc);
+
+- pm_runtime_put_sync(&pdev->dev);
+- pm_runtime_allow(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
++ pm_runtime_put_noidle(&pdev->dev);
++ pm_runtime_set_suspended(&pdev->dev);
+
+ dwc3_free_event_buffers(dwc);
+ dwc3_free_scratch_buffers(dwc);
--- /dev/null
+From 66706077dc89c66a4777a4c6298273816afb848c Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Thu, 24 Sep 2020 01:21:43 -0700
+Subject: usb: dwc3: ep0: Fix ZLP for OUT ep0 requests
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit 66706077dc89c66a4777a4c6298273816afb848c upstream.
+
+The current ZLP handling for ep0 requests is only for control IN
+requests. For OUT direction, DWC3 needs to check and setup for MPS
+alignment.
+
+Usually, control OUT requests can indicate its transfer size via the
+wLength field of the control message. So usb_request->zero is usually
+not needed for OUT direction. To handle ZLP OUT for control endpoint,
+make sure the TRB is MPS size.
+
+Cc: stable@vger.kernel.org
+Fixes: c7fcdeb2627c ("usb: dwc3: ep0: simplify EP0 state machine")
+Fixes: d6e5a549cc4d ("usb: dwc3: simplify ZLP handling")
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/ep0.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/dwc3/ep0.c
++++ b/drivers/usb/dwc3/ep0.c
+@@ -942,12 +942,16 @@ static void dwc3_ep0_xfer_complete(struc
+ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
+ struct dwc3_ep *dep, struct dwc3_request *req)
+ {
++ unsigned int trb_length = 0;
+ int ret;
+
+ req->direction = !!dep->number;
+
+ if (req->request.length == 0) {
+- dwc3_ep0_prepare_one_trb(dep, dwc->ep0_trb_addr, 0,
++ if (!req->direction)
++ trb_length = dep->endpoint.maxpacket;
++
++ dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, trb_length,
+ DWC3_TRBCTL_CONTROL_DATA, false);
+ ret = dwc3_ep0_start_trans(dep);
+ } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
+@@ -994,9 +998,12 @@ static void __dwc3_ep0_do_control_data(s
+
+ req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1];
+
++ if (!req->direction)
++ trb_length = dep->endpoint.maxpacket;
++
+ /* Now prepare one extra TRB to align transfer size */
+ dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr,
+- 0, DWC3_TRBCTL_CONTROL_DATA,
++ trb_length, DWC3_TRBCTL_CONTROL_DATA,
+ false);
+ ret = dwc3_ep0_start_trans(dep);
+ } else {
--- /dev/null
+From ca3df3468eec87f6374662f7de425bc44c3810c1 Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Thu, 24 Sep 2020 01:21:18 -0700
+Subject: usb: dwc3: gadget: Check MPS of the request length
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit ca3df3468eec87f6374662f7de425bc44c3810c1 upstream.
+
+When preparing for SG, not all the entries are prepared at once. When
+resume, don't use the remaining request length to calculate for MPS
+alignment. Use the entire request->length to do that.
+
+Cc: stable@vger.kernel.org
+Fixes: 5d187c0454ef ("usb: dwc3: gadget: Don't setup more than requested")
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/gadget.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1095,6 +1095,8 @@ static void dwc3_prepare_one_trb_sg(stru
+ struct scatterlist *s;
+ int i;
+ unsigned int length = req->request.length;
++ unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
++ unsigned int rem = length % maxp;
+ unsigned int remaining = req->request.num_mapped_sgs
+ - req->num_queued_sgs;
+
+@@ -1106,8 +1108,6 @@ static void dwc3_prepare_one_trb_sg(stru
+ length -= sg_dma_len(s);
+
+ for_each_sg(sg, s, remaining, i) {
+- unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
+- unsigned int rem = length % maxp;
+ unsigned int trb_length;
+ unsigned chain = true;
+
--- /dev/null
+From d97c78a1908e59a1fdbcbece87cd0440b5d7a1f2 Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Wed, 2 Sep 2020 18:43:04 -0700
+Subject: usb: dwc3: gadget: END_TRANSFER before CLEAR_STALL command
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit d97c78a1908e59a1fdbcbece87cd0440b5d7a1f2 upstream.
+
+According the programming guide (for all DWC3 IPs), when the driver
+handles ClearFeature(halt) request, it should issue CLEAR_STALL command
+_after_ the END_TRANSFER command completes. The END_TRANSFER command may
+take some time to complete. So, delay the ClearFeature(halt) request
+control status stage and wait for END_TRANSFER command completion
+interrupt. Only after END_TRANSFER command completes that the driver
+may issue CLEAR_STALL command.
+
+Cc: stable@vger.kernel.org
+Fixes: cb11ea56f37a ("usb: dwc3: gadget: Properly handle ClearFeature(halt)")
+Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/core.h | 1 +
+ drivers/usb/dwc3/ep0.c | 16 ++++++++++++++++
+ drivers/usb/dwc3/gadget.c | 40 ++++++++++++++++++++++++++++++++--------
+ drivers/usb/dwc3/gadget.h | 1 +
+ 4 files changed, 50 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/dwc3/core.h
++++ b/drivers/usb/dwc3/core.h
+@@ -710,6 +710,7 @@ struct dwc3_ep {
+ #define DWC3_EP_IGNORE_NEXT_NOSTREAM BIT(8)
+ #define DWC3_EP_FORCE_RESTART_STREAM BIT(9)
+ #define DWC3_EP_FIRST_STREAM_PRIMED BIT(10)
++#define DWC3_EP_PENDING_CLEAR_STALL BIT(11)
+
+ /* This last one is specific to EP0 */
+ #define DWC3_EP0_DIR_IN BIT(31)
+--- a/drivers/usb/dwc3/ep0.c
++++ b/drivers/usb/dwc3/ep0.c
+@@ -524,6 +524,11 @@ static int dwc3_ep0_handle_endpoint(stru
+ ret = __dwc3_gadget_ep_set_halt(dep, set, true);
+ if (ret)
+ return -EINVAL;
++
++ /* ClearFeature(Halt) may need delayed status */
++ if (!set && (dep->flags & DWC3_EP_END_TRANSFER_PENDING))
++ return USB_GADGET_DELAYED_STATUS;
++
+ break;
+ default:
+ return -EINVAL;
+@@ -1049,6 +1054,17 @@ static void dwc3_ep0_do_control_status(s
+ __dwc3_ep0_do_control_status(dwc, dep);
+ }
+
++void dwc3_ep0_send_delayed_status(struct dwc3 *dwc)
++{
++ unsigned int direction = !dwc->ep0_expect_in;
++
++ if (dwc->ep0state != EP0_STATUS_PHASE)
++ return;
++
++ dwc->delayed_status = false;
++ __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]);
++}
++
+ static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep)
+ {
+ struct dwc3_gadget_ep_cmd_params params;
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1827,6 +1827,18 @@ int __dwc3_gadget_ep_set_halt(struct dwc
+ return 0;
+ }
+
++ dwc3_stop_active_transfer(dep, true, true);
++
++ list_for_each_entry_safe(req, tmp, &dep->started_list, list)
++ dwc3_gadget_move_cancelled_request(req);
++
++ if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) {
++ dep->flags |= DWC3_EP_PENDING_CLEAR_STALL;
++ return 0;
++ }
++
++ dwc3_gadget_ep_cleanup_cancelled_requests(dep);
++
+ ret = dwc3_send_clear_stall_ep_cmd(dep);
+ if (ret) {
+ dev_err(dwc->dev, "failed to clear STALL on %s\n",
+@@ -1836,14 +1848,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc
+
+ dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
+
+- dwc3_stop_active_transfer(dep, true, true);
+-
+- list_for_each_entry_safe(req, tmp, &dep->started_list, list)
+- dwc3_gadget_move_cancelled_request(req);
+-
+- if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
+- dwc3_gadget_ep_cleanup_cancelled_requests(dep);
+-
+ if ((dep->flags & DWC3_EP_DELAY_START) &&
+ !usb_endpoint_xfer_isoc(dep->endpoint.desc))
+ __dwc3_gadget_kick_transfer(dep);
+@@ -3003,6 +3007,26 @@ static void dwc3_endpoint_interrupt(stru
+ dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
+ dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
+ dwc3_gadget_ep_cleanup_cancelled_requests(dep);
++
++ if (dep->flags & DWC3_EP_PENDING_CLEAR_STALL) {
++ struct dwc3 *dwc = dep->dwc;
++
++ dep->flags &= ~DWC3_EP_PENDING_CLEAR_STALL;
++ if (dwc3_send_clear_stall_ep_cmd(dep)) {
++ struct usb_ep *ep0 = &dwc->eps[0]->endpoint;
++
++ dev_err(dwc->dev, "failed to clear STALL on %s\n",
++ dep->name);
++ if (dwc->delayed_status)
++ __dwc3_gadget_ep0_set_halt(ep0, 1);
++ return;
++ }
++
++ dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE);
++ if (dwc->delayed_status)
++ dwc3_ep0_send_delayed_status(dwc);
++ }
++
+ if ((dep->flags & DWC3_EP_DELAY_START) &&
+ !usb_endpoint_xfer_isoc(dep->endpoint.desc))
+ __dwc3_gadget_kick_transfer(dep);
+--- a/drivers/usb/dwc3/gadget.h
++++ b/drivers/usb/dwc3/gadget.h
+@@ -113,6 +113,7 @@ int dwc3_gadget_ep0_set_halt(struct usb_
+ int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request,
+ gfp_t gfp_flags);
+ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol);
++void dwc3_ep0_send_delayed_status(struct dwc3 *dwc);
+
+ /**
+ * dwc3_gadget_ep_get_transfer_index - Gets transfer index from HW
--- /dev/null
+From 690e5c2dc29f8891fcfd30da67e0d5837c2c9df5 Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Thu, 24 Sep 2020 01:21:24 -0700
+Subject: usb: dwc3: gadget: Reclaim extra TRBs after request completion
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit 690e5c2dc29f8891fcfd30da67e0d5837c2c9df5 upstream.
+
+An SG request may be partially completed (due to no available TRBs).
+Don't reclaim extra TRBs and clear the needs_extra_trb flag until the
+request is fully completed. Otherwise, the driver will reclaim the wrong
+TRB.
+
+Cc: stable@vger.kernel.org
+Fixes: 1f512119a08c ("usb: dwc3: gadget: add remaining sg entries to ring")
+Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/gadget.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -2732,6 +2732,11 @@ static int dwc3_gadget_ep_cleanup_comple
+ ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
+ status);
+
++ req->request.actual = req->request.length - req->remaining;
++
++ if (!dwc3_gadget_ep_request_completed(req))
++ goto out;
++
+ if (req->needs_extra_trb) {
+ unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
+
+@@ -2747,11 +2752,6 @@ static int dwc3_gadget_ep_cleanup_comple
+ req->needs_extra_trb = false;
+ }
+
+- req->request.actual = req->request.length - req->remaining;
+-
+- if (!dwc3_gadget_ep_request_completed(req))
+- goto out;
+-
+ dwc3_gadget_giveback(dep, req, status);
+
+ out:
--- /dev/null
+From c503672abe1348f10f5a54a662336358c6e1a297 Mon Sep 17 00:00:00 2001
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Date: Wed, 2 Sep 2020 18:42:58 -0700
+Subject: usb: dwc3: gadget: Resume pending requests after CLEAR_STALL
+
+From: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+
+commit c503672abe1348f10f5a54a662336358c6e1a297 upstream.
+
+The function driver may queue new requests right after halting the
+endpoint (i.e. queue new requests while the endpoint is stalled).
+There's no restriction preventing it from doing so. However, dwc3
+currently drops those requests after CLEAR_STALL. The driver should only
+drop started requests. Keep the pending requests in the pending list to
+resume and process them after the host issues ClearFeature(Halt) to the
+endpoint.
+
+Cc: stable@vger.kernel.org
+Fixes: cb11ea56f37a ("usb: dwc3: gadget: Properly handle ClearFeature(halt)")
+Signed-off-by: Thinh Nguyen <thinhn@synopsys.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/gadget.c | 22 ++++++++++++++--------
+ 1 file changed, 14 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -1628,8 +1628,13 @@ static int __dwc3_gadget_ep_queue(struct
+ if (dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE)
+ return 0;
+
+- /* Start the transfer only after the END_TRANSFER is completed */
+- if (dep->flags & DWC3_EP_END_TRANSFER_PENDING) {
++ /*
++ * Start the transfer only after the END_TRANSFER is completed
++ * and endpoint STALL is cleared.
++ */
++ if ((dep->flags & DWC3_EP_END_TRANSFER_PENDING) ||
++ (dep->flags & DWC3_EP_WEDGE) ||
++ (dep->flags & DWC3_EP_STALL)) {
+ dep->flags |= DWC3_EP_DELAY_START;
+ return 0;
+ }
+@@ -1836,13 +1841,14 @@ int __dwc3_gadget_ep_set_halt(struct dwc
+ list_for_each_entry_safe(req, tmp, &dep->started_list, list)
+ dwc3_gadget_move_cancelled_request(req);
+
+- list_for_each_entry_safe(req, tmp, &dep->pending_list, list)
+- dwc3_gadget_move_cancelled_request(req);
+-
+- if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) {
+- dep->flags &= ~DWC3_EP_DELAY_START;
++ if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
+ dwc3_gadget_ep_cleanup_cancelled_requests(dep);
+- }
++
++ if ((dep->flags & DWC3_EP_DELAY_START) &&
++ !usb_endpoint_xfer_isoc(dep->endpoint.desc))
++ __dwc3_gadget_kick_transfer(dep);
++
++ dep->flags &= ~DWC3_EP_DELAY_START;
+ }
+
+ return ret;
--- /dev/null
+From a609ce2a13360d639b384b6ca783b38c1247f2db Mon Sep 17 00:00:00 2001
+From: Raymond Tan <raymond.tan@intel.com>
+Date: Fri, 21 Aug 2020 16:11:01 +0300
+Subject: usb: dwc3: pci: Allow Elkhart Lake to utilize DSM method for PM functionality
+
+From: Raymond Tan <raymond.tan@intel.com>
+
+commit a609ce2a13360d639b384b6ca783b38c1247f2db upstream.
+
+Similar to some other IA platforms, Elkhart Lake too depends on the
+PMU register write to request transition of Dx power state.
+
+Thus, we add the PCI_DEVICE_ID_INTEL_EHLLP to the list of devices that
+shall execute the ACPI _DSM method during D0/D3 sequence.
+
+[heikki.krogerus@linux.intel.com: included Fixes tag]
+
+Fixes: dbb0569de852 ("usb: dwc3: pci: Add Support for Intel Elkhart Lake Devices")
+Cc: stable@vger.kernel.org
+Signed-off-by: Raymond Tan <raymond.tan@intel.com>
+Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Felipe Balbi <balbi@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/dwc3/dwc3-pci.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/usb/dwc3/dwc3-pci.c
++++ b/drivers/usb/dwc3/dwc3-pci.c
+@@ -147,7 +147,8 @@ static int dwc3_pci_quirks(struct dwc3_p
+
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL) {
+ if (pdev->device == PCI_DEVICE_ID_INTEL_BXT ||
+- pdev->device == PCI_DEVICE_ID_INTEL_BXT_M) {
++ pdev->device == PCI_DEVICE_ID_INTEL_BXT_M ||
++ pdev->device == PCI_DEVICE_ID_INTEL_EHLLP) {
+ guid_parse(PCI_INTEL_BXT_DSM_GUID, &dwc->guid);
+ dwc->has_dsm_for_pm = true;
+ }
--- /dev/null
+From 3cd54a618834430a26a648d880dd83d740f2ae30 Mon Sep 17 00:00:00 2001
+From: Ran Wang <ran.wang_1@nxp.com>
+Date: Sat, 10 Oct 2020 14:03:08 +0800
+Subject: usb: host: fsl-mph-dr-of: check return of dma_set_mask()
+
+From: Ran Wang <ran.wang_1@nxp.com>
+
+commit 3cd54a618834430a26a648d880dd83d740f2ae30 upstream.
+
+fsl_usb2_device_register() should stop init if dma_set_mask() return
+error.
+
+Fixes: cae058610465 ("drivers/usb/host: fsl: Set DMA_MASK of usb platform device")
+Reviewed-by: Peter Chen <peter.chen@nxp.com>
+Signed-off-by: Ran Wang <ran.wang_1@nxp.com>
+Link: https://lore.kernel.org/r/20201010060308.33693-1-ran.wang_1@nxp.com
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/fsl-mph-dr-of.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/host/fsl-mph-dr-of.c
++++ b/drivers/usb/host/fsl-mph-dr-of.c
+@@ -94,10 +94,13 @@ static struct platform_device *fsl_usb2_
+
+ pdev->dev.coherent_dma_mask = ofdev->dev.coherent_dma_mask;
+
+- if (!pdev->dev.dma_mask)
++ if (!pdev->dev.dma_mask) {
+ pdev->dev.dma_mask = &ofdev->dev.coherent_dma_mask;
+- else
+- dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
++ } else {
++ retval = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
++ if (retval)
++ goto error;
++ }
+
+ retval = platform_device_add_data(pdev, pdata, sizeof(*pdata));
+ if (retval)
--- /dev/null
+From 2d9c6442a9c81f4f8dee678d0b3c183173ab1e2d Mon Sep 17 00:00:00 2001
+From: Li Jun <jun.li@nxp.com>
+Date: Mon, 12 Oct 2020 19:03:12 +0800
+Subject: usb: typec: tcpm: reset hard_reset_count for any disconnect
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Li Jun <jun.li@nxp.com>
+
+commit 2d9c6442a9c81f4f8dee678d0b3c183173ab1e2d upstream.
+
+Current tcpm_detach() only reset hard_reset_count if port->attached
+is true, this may cause this counter clear is missed if the CC
+disconnect event is generated after tcpm_port_reset() is done
+by other events, e.g. VBUS off comes first before CC disconect for
+a power sink, in that case the first tcpm_detach() will only clear
+port->attached flag but leave hard_reset_count there because
+tcpm_port_is_disconnected() is still false, then later tcpm_detach()
+by CC disconnect will directly return due to port->attached is cleared,
+finally this will result tcpm will not try hard reset or error recovery
+for later attach.
+
+ChiYuan reported this issue on his platform with below tcpm trace:
+After power sink session setup after hard reset 2 times, detach
+from the power source and then attach:
+[ 4848.046358] VBUS off
+[ 4848.046384] state change SNK_READY -> SNK_UNATTACHED
+[ 4848.050908] Setting voltage/current limit 0 mV 0 mA
+[ 4848.050936] polarity 0
+[ 4848.052593] Requesting mux state 0, usb-role 0, orientation 0
+[ 4848.053222] Start toggling
+[ 4848.086500] state change SNK_UNATTACHED -> TOGGLING
+[ 4848.089983] CC1: 0 -> 0, CC2: 3 -> 3 [state TOGGLING, polarity 0, connected]
+[ 4848.089993] state change TOGGLING -> SNK_ATTACH_WAIT
+[ 4848.090031] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms
+[ 4848.141162] CC1: 0 -> 0, CC2: 3 -> 0 [state SNK_ATTACH_WAIT, polarity 0, disconnected]
+[ 4848.141170] state change SNK_ATTACH_WAIT -> SNK_ATTACH_WAIT
+[ 4848.141184] pending state change SNK_ATTACH_WAIT -> SNK_UNATTACHED @20 ms
+[ 4848.163156] state change SNK_ATTACH_WAIT -> SNK_UNATTACHED [delayed 20 ms]
+[ 4848.163162] Start toggling
+[ 4848.216918] CC1: 0 -> 0, CC2: 0 -> 3 [state TOGGLING, polarity 0, connected]
+[ 4848.216954] state change TOGGLING -> SNK_ATTACH_WAIT
+[ 4848.217080] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms
+[ 4848.231771] CC1: 0 -> 0, CC2: 3 -> 0 [state SNK_ATTACH_WAIT, polarity 0, disconnected]
+[ 4848.231800] state change SNK_ATTACH_WAIT -> SNK_ATTACH_WAIT
+[ 4848.231857] pending state change SNK_ATTACH_WAIT -> SNK_UNATTACHED @20 ms
+[ 4848.256022] state change SNK_ATTACH_WAIT -> SNK_UNATTACHED [delayed20 ms]
+[ 4848.256049] Start toggling
+[ 4848.871148] VBUS on
+[ 4848.885324] CC1: 0 -> 0, CC2: 0 -> 3 [state TOGGLING, polarity 0, connected]
+[ 4848.885372] state change TOGGLING -> SNK_ATTACH_WAIT
+[ 4848.885548] pending state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED @200 ms
+[ 4849.088240] state change SNK_ATTACH_WAIT -> SNK_DEBOUNCED [delayed200 ms]
+[ 4849.088284] state change SNK_DEBOUNCED -> SNK_ATTACHED
+[ 4849.088291] polarity 1
+[ 4849.088769] Requesting mux state 1, usb-role 2, orientation 2
+[ 4849.088895] state change SNK_ATTACHED -> SNK_STARTUP
+[ 4849.088907] state change SNK_STARTUP -> SNK_DISCOVERY
+[ 4849.088915] Setting voltage/current limit 5000 mV 0 mA
+[ 4849.088927] vbus=0 charge:=1
+[ 4849.090505] state change SNK_DISCOVERY -> SNK_WAIT_CAPABILITIES
+[ 4849.090828] pending state change SNK_WAIT_CAPABILITIES -> SNK_READY @240 ms
+[ 4849.335878] state change SNK_WAIT_CAPABILITIES -> SNK_READY [delayed240 ms]
+
+this patch fix this issue by clear hard_reset_count at any cases
+of cc disconnect, í.e. don't check port->attached flag.
+
+Fixes: 4b4e02c83167 ("typec: tcpm: Move out of staging")
+Cc: stable@vger.kernel.org
+Reported-and-tested-by: ChiYuan Huang <cy_huang@richtek.com>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Signed-off-by: Li Jun <jun.li@nxp.com>
+Link: https://lore.kernel.org/r/1602500592-3817-1-git-send-email-jun.li@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/typec/tcpm/tcpm.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -2789,6 +2789,9 @@ static void tcpm_reset_port(struct tcpm_
+
+ static void tcpm_detach(struct tcpm_port *port)
+ {
++ if (tcpm_port_is_disconnected(port))
++ port->hard_reset_count = 0;
++
+ if (!port->attached)
+ return;
+
+@@ -2797,9 +2800,6 @@ static void tcpm_detach(struct tcpm_port
+ port->tcpc->set_bist_data(port->tcpc, false);
+ }
+
+- if (tcpm_port_is_disconnected(port))
+- port->hard_reset_count = 0;
+-
+ tcpm_reset_port(port);
+ }
+
--- /dev/null
+From 2a632815683d2d34df52b701a36fe5ac6654e719 Mon Sep 17 00:00:00 2001
+From: Sandeep Singh <sandeep.singh@amd.com>
+Date: Wed, 28 Oct 2020 22:31:23 +0200
+Subject: usb: xhci: Workaround for S3 issue on AMD SNPS 3.0 xHC
+
+From: Sandeep Singh <sandeep.singh@amd.com>
+
+commit 2a632815683d2d34df52b701a36fe5ac6654e719 upstream.
+
+On some platform of AMD, S3 fails with HCE and SRE errors. To fix this,
+need to disable a bit which is enable in sparse controller.
+
+Cc: stable@vger.kernel.org #v4.19+
+Signed-off-by: Sanket Goswami <Sanket.Goswami@amd.com>
+Signed-off-by: Sandeep Singh <sandeep.singh@amd.com>
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20201028203124.375344-3-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/host/xhci-pci.c | 17 +++++++++++++++++
+ drivers/usb/host/xhci.h | 1 +
+ 2 files changed, 18 insertions(+)
+
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -22,6 +22,8 @@
+ #define SSIC_PORT_CFG2_OFFSET 0x30
+ #define PROG_DONE (1 << 30)
+ #define SSIC_PORT_UNUSED (1 << 31)
++#define SPARSE_DISABLE_BIT 17
++#define SPARSE_CNTL_ENABLE 0xC12C
+
+ /* Device for a quirk */
+ #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
+@@ -160,6 +162,9 @@ static void xhci_pci_quirks(struct devic
+ (pdev->device == 0x15e0 || pdev->device == 0x15e1))
+ xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND;
+
++ if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == 0x15e5)
++ xhci->quirks |= XHCI_DISABLE_SPARSE;
++
+ if (pdev->vendor == PCI_VENDOR_ID_AMD)
+ xhci->quirks |= XHCI_TRUST_TX_LENGTH;
+
+@@ -490,6 +495,15 @@ static void xhci_pme_quirk(struct usb_hc
+ readl(reg);
+ }
+
++static void xhci_sparse_control_quirk(struct usb_hcd *hcd)
++{
++ u32 reg;
++
++ reg = readl(hcd->regs + SPARSE_CNTL_ENABLE);
++ reg &= ~BIT(SPARSE_DISABLE_BIT);
++ writel(reg, hcd->regs + SPARSE_CNTL_ENABLE);
++}
++
+ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
+ {
+ struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+@@ -509,6 +523,9 @@ static int xhci_pci_suspend(struct usb_h
+ if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
+ xhci_ssic_port_unused_quirk(hcd, true);
+
++ if (xhci->quirks & XHCI_DISABLE_SPARSE)
++ xhci_sparse_control_quirk(hcd);
++
+ ret = xhci_suspend(xhci, do_wakeup);
+ if (ret && (xhci->quirks & XHCI_SSIC_PORT_UNUSED))
+ xhci_ssic_port_unused_quirk(hcd, false);
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -1874,6 +1874,7 @@ struct xhci_hcd {
+ #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
+ #define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
+ #define XHCI_RENESAS_FW_QUIRK BIT_ULL(36)
++#define XHCI_DISABLE_SPARSE BIT_ULL(38)
+
+ unsigned int num_active_eps;
+ unsigned int limit_active_eps;
--- /dev/null
+From 0942d59b0af46511d59dbf5bd69ec4a64d1a854c Mon Sep 17 00:00:00 2001
+From: Bastien Nocera <hadess@hadess.net>
+Date: Thu, 22 Oct 2020 09:55:20 -0400
+Subject: usbcore: Check both id_table and match() when both available
+
+From: Bastien Nocera <hadess@hadess.net>
+
+commit 0942d59b0af46511d59dbf5bd69ec4a64d1a854c upstream.
+
+From: Bastien Nocera <hadess@hadess.net>
+
+When a USB device driver has both an id_table and a match() function, make
+sure to check both to find a match, first matching the id_table, then
+checking the match() function.
+
+This makes it possible to have module autoloading done through the
+id_table when devices are plugged in, before checking for further
+device eligibility in the match() function.
+
+Cc: <stable@vger.kernel.org> # 5.8
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Co-developed-by: M. Vefa Bicakci <m.v.b@runbox.com>
+Tested-by: Bastien Nocera <hadess@hadess.net>
+Signed-off-by: Bastien Nocera <hadess@hadess.net>
+Signed-off-by: M. Vefa Bicakci <m.v.b@runbox.com>
+Tested-by: Pan (Pany) YUAN <pany@fedoraproject.org>
+Link: https://lore.kernel.org/r/20201022135521.375211-2-m.v.b@runbox.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/driver.c | 30 +++++++++++++++++++++---------
+ drivers/usb/core/generic.c | 4 +---
+ drivers/usb/core/usb.h | 2 ++
+ 3 files changed, 24 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -839,6 +839,22 @@ const struct usb_device_id *usb_device_m
+ return NULL;
+ }
+
++bool usb_driver_applicable(struct usb_device *udev,
++ struct usb_device_driver *udrv)
++{
++ if (udrv->id_table && udrv->match)
++ return usb_device_match_id(udev, udrv->id_table) != NULL &&
++ udrv->match(udev);
++
++ if (udrv->id_table)
++ return usb_device_match_id(udev, udrv->id_table) != NULL;
++
++ if (udrv->match)
++ return udrv->match(udev);
++
++ return false;
++}
++
+ static int usb_device_match(struct device *dev, struct device_driver *drv)
+ {
+ /* devices and interfaces are handled separately */
+@@ -853,17 +869,14 @@ static int usb_device_match(struct devic
+ udev = to_usb_device(dev);
+ udrv = to_usb_device_driver(drv);
+
+- if (udrv->id_table)
+- return usb_device_match_id(udev, udrv->id_table) != NULL;
+-
+- if (udrv->match)
+- return udrv->match(udev);
+-
+ /* If the device driver under consideration does not have a
+ * id_table or a match function, then let the driver's probe
+ * function decide.
+ */
+- return 1;
++ if (!udrv->id_table && !udrv->match)
++ return 1;
++
++ return usb_driver_applicable(udev, udrv);
+
+ } else if (is_usb_interface(dev)) {
+ struct usb_interface *intf;
+@@ -941,8 +954,7 @@ static int __usb_bus_reprobe_drivers(str
+ return 0;
+
+ udev = to_usb_device(dev);
+- if (usb_device_match_id(udev, new_udriver->id_table) == NULL &&
+- (!new_udriver->match || new_udriver->match(udev) == 0))
++ if (!usb_driver_applicable(udev, new_udriver))
+ return 0;
+
+ ret = device_reprobe(dev);
+--- a/drivers/usb/core/generic.c
++++ b/drivers/usb/core/generic.c
+@@ -205,9 +205,7 @@ static int __check_usb_generic(struct de
+ udrv = to_usb_device_driver(drv);
+ if (udrv == &usb_generic_driver)
+ return 0;
+- if (usb_device_match_id(udev, udrv->id_table) != NULL)
+- return 1;
+- return (udrv->match && udrv->match(udev));
++ return usb_driver_applicable(udev, udrv);
+ }
+
+ static bool usb_generic_driver_match(struct usb_device *udev)
+--- a/drivers/usb/core/usb.h
++++ b/drivers/usb/core/usb.h
+@@ -74,6 +74,8 @@ extern int usb_match_device(struct usb_d
+ const struct usb_device_id *id);
+ extern const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
+ const struct usb_device_id *id);
++extern bool usb_driver_applicable(struct usb_device *udev,
++ struct usb_device_driver *udrv);
+ extern void usb_forced_unbind_intf(struct usb_interface *intf);
+ extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev);
+
--- /dev/null
+From 82e61c3909db51d91b9d3e2071557b6435018b80 Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jirislaby@kernel.org>
+Date: Mon, 19 Oct 2020 10:55:17 +0200
+Subject: vt: keyboard, extend func_buf_lock to readers
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+commit 82e61c3909db51d91b9d3e2071557b6435018b80 upstream.
+
+Both read-side users of func_table/func_buf need locking. Without that,
+one can easily confuse the code by repeatedly setting altering strings
+like:
+while (1)
+ for (a = 0; a < 2; a++) {
+ struct kbsentry kbs = {};
+ strcpy((char *)kbs.kb_string, a ? ".\n" : "88888\n");
+ ioctl(fd, KDSKBSENT, &kbs);
+ }
+
+When that program runs, one can get unexpected output by holding F1
+(note the unxpected period on the last line):
+.
+88888
+.8888
+
+So protect all accesses to 'func_table' (and func_buf) by preexisting
+'func_buf_lock'.
+
+It is easy in 'k_fn' handler as 'puts_queue' is expected not to sleep.
+On the other hand, KDGKBSENT needs a local (atomic) copy of the string
+because copy_to_user can sleep. Use already allocated, but unused
+'kbs->kb_string' for that purpose.
+
+Note that the program above needs at least CAP_SYS_TTY_CONFIG.
+
+This depends on the previous patch and on the func_buf_lock lock added
+in commit 46ca3f735f34 (tty/vt: fix write/write race in ioctl(KDSKBSENT)
+handler) in 5.2.
+
+Likely fixes CVE-2020-25656.
+
+Cc: <stable@vger.kernel.org>
+Reported-by: Minh Yuan <yuanmingbuaa@gmail.com>
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Link: https://lore.kernel.org/r/20201019085517.10176-2-jslaby@suse.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/vt/keyboard.c | 17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+--- a/drivers/tty/vt/keyboard.c
++++ b/drivers/tty/vt/keyboard.c
+@@ -743,8 +743,13 @@ static void k_fn(struct vc_data *vc, uns
+ return;
+
+ if ((unsigned)value < ARRAY_SIZE(func_table)) {
++ unsigned long flags;
++
++ spin_lock_irqsave(&func_buf_lock, flags);
+ if (func_table[value])
+ puts_queue(vc, func_table[value]);
++ spin_unlock_irqrestore(&func_buf_lock, flags);
++
+ } else
+ pr_err("k_fn called with value=%d\n", value);
+ }
+@@ -1991,7 +1996,7 @@ out:
+ #undef s
+ #undef v
+
+-/* FIXME: This one needs untangling and locking */
++/* FIXME: This one needs untangling */
+ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
+ {
+ struct kbsentry *kbs;
+@@ -2023,10 +2028,14 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb
+ switch (cmd) {
+ case KDGKBSENT: {
+ /* size should have been a struct member */
+- unsigned char *from = func_table[i] ? : "";
++ ssize_t len = sizeof(user_kdgkb->kb_string);
++
++ spin_lock_irqsave(&func_buf_lock, flags);
++ len = strlcpy(kbs->kb_string, func_table[i] ? : "", len);
++ spin_unlock_irqrestore(&func_buf_lock, flags);
+
+- ret = copy_to_user(user_kdgkb->kb_string, from,
+- strlen(from) + 1) ? -EFAULT : 0;
++ ret = copy_to_user(user_kdgkb->kb_string, kbs->kb_string,
++ len + 1) ? -EFAULT : 0;
+
+ goto reterr;
+ }
--- /dev/null
+From 6ca03f90527e499dd5e32d6522909e2ad390896b Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jirislaby@kernel.org>
+Date: Mon, 19 Oct 2020 10:55:16 +0200
+Subject: vt: keyboard, simplify vt_kdgkbsent
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+commit 6ca03f90527e499dd5e32d6522909e2ad390896b upstream.
+
+Use 'strlen' of the string, add one for NUL terminator and simply do
+'copy_to_user' instead of the explicit 'for' loop. This makes the
+KDGKBSENT case more compact.
+
+The only thing we need to take care about is NULL 'func_table[i]'. Use
+an empty string in that case.
+
+The original check for overflow could never trigger as the func_buf
+strings are always shorter or equal to 'struct kbsentry's.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Link: https://lore.kernel.org/r/20201019085517.10176-1-jslaby@suse.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/vt/keyboard.c | 28 +++++++++-------------------
+ 1 file changed, 9 insertions(+), 19 deletions(-)
+
+--- a/drivers/tty/vt/keyboard.c
++++ b/drivers/tty/vt/keyboard.c
+@@ -1995,9 +1995,7 @@ out:
+ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm)
+ {
+ struct kbsentry *kbs;
+- char *p;
+ u_char *q;
+- u_char __user *up;
+ int sz, fnw_sz;
+ int delta;
+ char *first_free, *fj, *fnw;
+@@ -2023,23 +2021,15 @@ int vt_do_kdgkb_ioctl(int cmd, struct kb
+ i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC);
+
+ switch (cmd) {
+- case KDGKBSENT:
+- sz = sizeof(kbs->kb_string) - 1; /* sz should have been
+- a struct member */
+- up = user_kdgkb->kb_string;
+- p = func_table[i];
+- if(p)
+- for ( ; *p && sz; p++, sz--)
+- if (put_user(*p, up++)) {
+- ret = -EFAULT;
+- goto reterr;
+- }
+- if (put_user('\0', up)) {
+- ret = -EFAULT;
+- goto reterr;
+- }
+- kfree(kbs);
+- return ((p && *p) ? -EOVERFLOW : 0);
++ case KDGKBSENT: {
++ /* size should have been a struct member */
++ unsigned char *from = func_table[i] ? : "";
++
++ ret = copy_to_user(user_kdgkb->kb_string, from,
++ strlen(from) + 1) ? -EFAULT : 0;
++
++ goto reterr;
++ }
+ case KDSKBSENT:
+ if (!perm) {
+ ret = -EPERM;
--- /dev/null
+From d54654790302ccaa72589380dce060d376ef8716 Mon Sep 17 00:00:00 2001
+From: Jiri Slaby <jirislaby@kernel.org>
+Date: Mon, 26 Oct 2020 06:54:19 +0100
+Subject: vt_ioctl: fix GIO_UNIMAP regression
+
+From: Jiri Slaby <jslaby@suse.cz>
+
+commit d54654790302ccaa72589380dce060d376ef8716 upstream.
+
+In commit 5ba127878722, we shuffled with the check of 'perm'. But my
+brain somehow inverted the condition in 'do_unimap_ioctl' (I thought
+it is ||, not &&), so GIO_UNIMAP stopped working completely.
+
+Move the 'perm' checks back to do_unimap_ioctl and do them right again.
+In fact, this reverts this part of code to the pre-5ba127878722 state.
+Except 'perm' is now a bool.
+
+Fixes: 5ba127878722 ("vt_ioctl: move perm checks level up")
+Cc: stable@vger.kernel.org
+Reported-by: Fabian Vogt <fvogt@suse.com>
+Signed-off-by: Jiri Slaby <jslaby@suse.cz>
+Link: https://lore.kernel.org/r/20201026055419.30518-1-jslaby@suse.cz
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/vt/vt_ioctl.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+--- a/drivers/tty/vt/vt_ioctl.c
++++ b/drivers/tty/vt/vt_ioctl.c
+@@ -550,7 +550,7 @@ static int vt_io_fontreset(struct consol
+ }
+
+ static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud,
+- struct vc_data *vc)
++ bool perm, struct vc_data *vc)
+ {
+ struct unimapdesc tmp;
+
+@@ -558,9 +558,11 @@ static inline int do_unimap_ioctl(int cm
+ return -EFAULT;
+ switch (cmd) {
+ case PIO_UNIMAP:
++ if (!perm)
++ return -EPERM;
+ return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
+ case GIO_UNIMAP:
+- if (fg_console != vc->vc_num)
++ if (!perm && fg_console != vc->vc_num)
+ return -EPERM;
+ return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
+ tmp.entries);
+@@ -640,10 +642,7 @@ static int vt_io_ioctl(struct vc_data *v
+
+ case PIO_UNIMAP:
+ case GIO_UNIMAP:
+- if (!perm)
+- return -EPERM;
+-
+- return do_unimap_ioctl(cmd, up, vc);
++ return do_unimap_ioctl(cmd, up, perm, vc);
+
+ default:
+ return -ENOIOCTLCMD;
--- /dev/null
+From b3149ffcdb31a8eb854cc442a389ae0b539bf28a Mon Sep 17 00:00:00 2001
+From: Borislav Petkov <bp@suse.de>
+Date: Wed, 7 Oct 2020 18:55:35 +0200
+Subject: x86/mce: Allow for copy_mc_fragile symbol checksum to be generated
+
+From: Borislav Petkov <bp@suse.de>
+
+commit b3149ffcdb31a8eb854cc442a389ae0b539bf28a upstream.
+
+Add asm/mce.h to asm/asm-prototypes.h so that that asm symbol's checksum
+can be generated in order to support CONFIG_MODVERSIONS with it and fix:
+
+ WARNING: modpost: EXPORT symbol "copy_mc_fragile" [vmlinux] version \
+ generation failed, symbol will not be versioned.
+
+For reference see:
+
+ 4efca4ed05cb ("kbuild: modversions for EXPORT_SYMBOL() for asm")
+ 334bb7738764 ("x86/kbuild: enable modversions for symbols exported from asm")
+
+Fixes: ec6347bb4339 ("x86, powerpc: Rename memcpy_mcsafe() to copy_mc_to_{user, kernel}()")
+Signed-off-by: Borislav Petkov <bp@suse.de>
+Link: https://lkml.kernel.org/r/20201007111447.GA23257@zn.tnic
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/include/asm/asm-prototypes.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/x86/include/asm/asm-prototypes.h
++++ b/arch/x86/include/asm/asm-prototypes.h
+@@ -5,6 +5,7 @@
+ #include <asm/string.h>
+ #include <asm/page.h>
+ #include <asm/checksum.h>
++#include <asm/mce.h>
+
+ #include <asm-generic/asm-prototypes.h>
+