From: Greg Kroah-Hartman Date: Tue, 3 Nov 2020 14:19:50 +0000 (+0100) Subject: 5.9-stable patches X-Git-Tag: v4.14.204~32 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4ec70c8e31fc86e6c4c7cf7de118c804c4fa8873;p=thirdparty%2Fkernel%2Fstable-queue.git 5.9-stable patches added patches: drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch usb-apple-mfi-fastcharge-don-t-probe-unhandled-devices.patch usb-cdc-acm-fix-cooldown-mechanism.patch usb-cdns3-fix-on-chip-memory-overflow-issue.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-ep0-fix-zlp-for-out-ep0-requests.patch usb-dwc3-gadget-check-mps-of-the-request-length.patch usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch usb-dwc3-gadget-reclaim-extra-trbs-after-request-completion.patch usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch usbcore-check-both-id_table-and-match-when-both-available.patch vt-keyboard-extend-func_buf_lock-to-readers.patch vt-keyboard-simplify-vt_kdgkbsent.patch vt_ioctl-fix-gio_unimap-regression.patch x86-mce-allow-for-copy_mc_fragile-symbol-checksum-to-be-generated.patch --- diff --git a/queue-5.9/drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch b/queue-5.9/drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch new file mode 100644 index 00000000000..1a59267c037 --- /dev/null +++ b/queue-5.9/drm-i915-force-vt-d-workarounds-when-running-as-a-guest-os.patch @@ -0,0 +1,55 @@ +From 8195400f7ea95399f721ad21f4d663a62c65036f Mon Sep 17 00:00:00 2001 +From: Chris Wilson +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 + +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 +Suggested-by: Stefan Fritsch +Signed-off-by: Chris Wilson +Cc: Zhenyu Wang +Cc: Joonas Lahtinen +Cc: Stefan Fritsch +Cc: stable@vger.kernel.org +Tested-by: Stefan Fritsch +Reviewed-by: Zhenyu Wang +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 +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + #include + ++#include ++ + #include + #include + #include +@@ -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) diff --git a/queue-5.9/hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch b/queue-5.9/hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch new file mode 100644 index 00000000000..7de8bc3a0cb --- /dev/null +++ b/queue-5.9/hid-wacom-avoid-entering-wacom_wac_pen_report-for-pad-battery.patch @@ -0,0 +1,61 @@ +From d9216d753b2b1406b801243b12aaf00a5ce5b861 Mon Sep 17 00:00:00 2001 +From: Jason Gerecke +Date: Wed, 23 Sep 2020 13:14:56 -0700 +Subject: HID: wacom: Avoid entering wacom_wac_pen_report for pad / battery + +From: Jason Gerecke + +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 +Reviewed-by: Ping Cheng +Tested-by: Ping Cheng +Signed-off-by: Jiri Kosina +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-5.9/series b/queue-5.9/series index 171954010d4..ece81c8a72d 100644 --- a/queue-5.9/series +++ b/queue-5.9/series @@ -235,3 +235,24 @@ btrfs-tree-checker-validate-number-of-chunk-stripes-and-parity.patch 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 diff --git a/queue-5.9/usb-apple-mfi-fastcharge-don-t-probe-unhandled-devices.patch b/queue-5.9/usb-apple-mfi-fastcharge-don-t-probe-unhandled-devices.patch new file mode 100644 index 00000000000..c95ab5dcaee --- /dev/null +++ b/queue-5.9/usb-apple-mfi-fastcharge-don-t-probe-unhandled-devices.patch @@ -0,0 +1,80 @@ +From 0cb686692fd200db12dcfb8231e793c1c98aec41 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Thu, 22 Oct 2020 09:55:21 -0400 +Subject: USB: apple-mfi-fastcharge: don't probe unhandled devices + +From: Bastien Nocera + +commit 0cb686692fd200db12dcfb8231e793c1c98aec41 upstream. + +From: Bastien Nocera + +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: # 5.8 +Cc: Greg Kroah-Hartman +Cc: Alan Stern +[m.v.b: Add Link and Reported-by tags to the commit message] +Reported-by: Pany +Tested-by: Pan (Pany) YUAN +Tested-by: Bastien Nocera +Signed-off-by: Bastien Nocera +Signed-off-by: M. Vefa Bicakci +Link: https://lore.kernel.org/r/20201022135521.375211-3-m.v.b@runbox.com +Signed-off-by: Greg Kroah-Hartman + +--- + 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, + }; + diff --git a/queue-5.9/usb-cdc-acm-fix-cooldown-mechanism.patch b/queue-5.9/usb-cdc-acm-fix-cooldown-mechanism.patch new file mode 100644 index 00000000000..19be0b63535 --- /dev/null +++ b/queue-5.9/usb-cdc-acm-fix-cooldown-mechanism.patch @@ -0,0 +1,126 @@ +From 38203b8385bf6283537162bde7d499f830964711 Mon Sep 17 00:00:00 2001 +From: Jerome Brunet +Date: Mon, 19 Oct 2020 19:07:02 +0200 +Subject: usb: cdc-acm: fix cooldown mechanism + +From: Jerome Brunet + +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 +Reported-by: Pascal Vizeli +Acked-by: Oliver Neukum +Signed-off-by: Jerome Brunet +Link: https://lore.kernel.org/r/20201019170702.150534-1-jbrunet@baylibre.com +Cc: stable +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman + +--- + 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 */ diff --git a/queue-5.9/usb-cdns3-fix-on-chip-memory-overflow-issue.patch b/queue-5.9/usb-cdns3-fix-on-chip-memory-overflow-issue.patch new file mode 100644 index 00000000000..80f6b4ffd11 --- /dev/null +++ b/queue-5.9/usb-cdns3-fix-on-chip-memory-overflow-issue.patch @@ -0,0 +1,367 @@ +From 52d3967704aea6cb316d419a33a5e1d56d33a3c1 Mon Sep 17 00:00:00 2001 +From: Pawel Laszczak +Date: Thu, 22 Oct 2020 08:55:05 +0800 +Subject: usb: cdns3: Fix on-chip memory overflow issue + +From: Pawel Laszczak + +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 +Signed-off-by: Pawel Laszczak +Signed-off-by: Peter Chen +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + diff --git a/queue-5.9/usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch b/queue-5.9/usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch new file mode 100644 index 00000000000..1f2c9d3d55e --- /dev/null +++ b/queue-5.9/usb-dwc3-core-add-phy-cleanup-for-probe-error-handling.patch @@ -0,0 +1,42 @@ +From 03c1fd622f72c7624c81b64fdba4a567ae5ee9cb Mon Sep 17 00:00:00 2001 +From: Li Jun +Date: Tue, 28 Jul 2020 20:42:41 +0800 +Subject: usb: dwc3: core: add phy cleanup for probe error handling + +From: Li Jun + +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: +Signed-off-by: Li Jun +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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: diff --git a/queue-5.9/usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch b/queue-5.9/usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch new file mode 100644 index 00000000000..b5470b81b38 --- /dev/null +++ b/queue-5.9/usb-dwc3-core-don-t-trigger-runtime-pm-when-remove-driver.patch @@ -0,0 +1,106 @@ +From 266d0493900ac5d6a21cdbe6b1624ed2da94d47a Mon Sep 17 00:00:00 2001 +From: Li Jun +Date: Tue, 28 Jul 2020 20:42:40 +0800 +Subject: usb: dwc3: core: don't trigger runtime pm when remove driver + +From: Li Jun + +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: +Signed-off-by: Li Jun +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-5.9/usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch b/queue-5.9/usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch new file mode 100644 index 00000000000..705aae7377d --- /dev/null +++ b/queue-5.9/usb-dwc3-ep0-fix-zlp-for-out-ep0-requests.patch @@ -0,0 +1,63 @@ +From 66706077dc89c66a4777a4c6298273816afb848c Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Thu, 24 Sep 2020 01:21:43 -0700 +Subject: usb: dwc3: ep0: Fix ZLP for OUT ep0 requests + +From: Thinh Nguyen + +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 +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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 { diff --git a/queue-5.9/usb-dwc3-gadget-check-mps-of-the-request-length.patch b/queue-5.9/usb-dwc3-gadget-check-mps-of-the-request-length.patch new file mode 100644 index 00000000000..ad9a4ac1dfa --- /dev/null +++ b/queue-5.9/usb-dwc3-gadget-check-mps-of-the-request-length.patch @@ -0,0 +1,43 @@ +From ca3df3468eec87f6374662f7de425bc44c3810c1 Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Thu, 24 Sep 2020 01:21:18 -0700 +Subject: usb: dwc3: gadget: Check MPS of the request length + +From: Thinh Nguyen + +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 +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + diff --git a/queue-5.9/usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch b/queue-5.9/usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch new file mode 100644 index 00000000000..44957c85156 --- /dev/null +++ b/queue-5.9/usb-dwc3-gadget-end_transfer-before-clear_stall-command.patch @@ -0,0 +1,145 @@ +From d97c78a1908e59a1fdbcbece87cd0440b5d7a1f2 Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Wed, 2 Sep 2020 18:43:04 -0700 +Subject: usb: dwc3: gadget: END_TRANSFER before CLEAR_STALL command + +From: Thinh Nguyen + +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 +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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 diff --git a/queue-5.9/usb-dwc3-gadget-reclaim-extra-trbs-after-request-completion.patch b/queue-5.9/usb-dwc3-gadget-reclaim-extra-trbs-after-request-completion.patch new file mode 100644 index 00000000000..92afc0c037b --- /dev/null +++ b/queue-5.9/usb-dwc3-gadget-reclaim-extra-trbs-after-request-completion.patch @@ -0,0 +1,50 @@ +From 690e5c2dc29f8891fcfd30da67e0d5837c2c9df5 Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Thu, 24 Sep 2020 01:21:24 -0700 +Subject: usb: dwc3: gadget: Reclaim extra TRBs after request completion + +From: Thinh Nguyen + +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 +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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: diff --git a/queue-5.9/usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch b/queue-5.9/usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch new file mode 100644 index 00000000000..7d14dc6573c --- /dev/null +++ b/queue-5.9/usb-dwc3-gadget-resume-pending-requests-after-clear_stall.patch @@ -0,0 +1,66 @@ +From c503672abe1348f10f5a54a662336358c6e1a297 Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Wed, 2 Sep 2020 18:42:58 -0700 +Subject: usb: dwc3: gadget: Resume pending requests after CLEAR_STALL + +From: Thinh Nguyen + +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 +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-5.9/usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch b/queue-5.9/usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch new file mode 100644 index 00000000000..b9b3dc2ebf1 --- /dev/null +++ b/queue-5.9/usb-dwc3-pci-allow-elkhart-lake-to-utilize-dsm-method-for-pm-functionality.patch @@ -0,0 +1,40 @@ +From a609ce2a13360d639b384b6ca783b38c1247f2db Mon Sep 17 00:00:00 2001 +From: Raymond Tan +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 + +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 +Signed-off-by: Heikki Krogerus +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } diff --git a/queue-5.9/usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch b/queue-5.9/usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch new file mode 100644 index 00000000000..3aaecbfe6e8 --- /dev/null +++ b/queue-5.9/usb-host-fsl-mph-dr-of-check-return-of-dma_set_mask.patch @@ -0,0 +1,42 @@ +From 3cd54a618834430a26a648d880dd83d740f2ae30 Mon Sep 17 00:00:00 2001 +From: Ran Wang +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 + +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 +Signed-off-by: Ran Wang +Link: https://lore.kernel.org/r/20201010060308.33693-1-ran.wang_1@nxp.com +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + 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) diff --git a/queue-5.9/usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch b/queue-5.9/usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch new file mode 100644 index 00000000000..e83502d8d6f --- /dev/null +++ b/queue-5.9/usb-typec-tcpm-reset-hard_reset_count-for-any-disconnect.patch @@ -0,0 +1,103 @@ +From 2d9c6442a9c81f4f8dee678d0b3c183173ab1e2d Mon Sep 17 00:00:00 2001 +From: Li Jun +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 + +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 +Reviewed-by: Guenter Roeck +Reviewed-by: Heikki Krogerus +Signed-off-by: Li Jun +Link: https://lore.kernel.org/r/1602500592-3817-1-git-send-email-jun.li@nxp.com +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + } + diff --git a/queue-5.9/usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch b/queue-5.9/usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch new file mode 100644 index 00000000000..1182a93fdaa --- /dev/null +++ b/queue-5.9/usb-xhci-workaround-for-s3-issue-on-amd-snps-3.0-xhc.patch @@ -0,0 +1,81 @@ +From 2a632815683d2d34df52b701a36fe5ac6654e719 Mon Sep 17 00:00:00 2001 +From: Sandeep Singh +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 + +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 +Signed-off-by: Sandeep Singh +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20201028203124.375344-3-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-5.9/usbcore-check-both-id_table-and-match-when-both-available.patch b/queue-5.9/usbcore-check-both-id_table-and-match-when-both-available.patch new file mode 100644 index 00000000000..c3590fa3ffc --- /dev/null +++ b/queue-5.9/usbcore-check-both-id_table-and-match-when-both-available.patch @@ -0,0 +1,117 @@ +From 0942d59b0af46511d59dbf5bd69ec4a64d1a854c Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Thu, 22 Oct 2020 09:55:20 -0400 +Subject: usbcore: Check both id_table and match() when both available + +From: Bastien Nocera + +commit 0942d59b0af46511d59dbf5bd69ec4a64d1a854c upstream. + +From: Bastien Nocera + +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: # 5.8 +Cc: Greg Kroah-Hartman +Cc: Alan Stern +Co-developed-by: M. Vefa Bicakci +Tested-by: Bastien Nocera +Signed-off-by: Bastien Nocera +Signed-off-by: M. Vefa Bicakci +Tested-by: Pan (Pany) YUAN +Link: https://lore.kernel.org/r/20201022135521.375211-2-m.v.b@runbox.com +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + diff --git a/queue-5.9/vt-keyboard-extend-func_buf_lock-to-readers.patch b/queue-5.9/vt-keyboard-extend-func_buf_lock-to-readers.patch new file mode 100644 index 00000000000..4fd8238dee0 --- /dev/null +++ b/queue-5.9/vt-keyboard-extend-func_buf_lock-to-readers.patch @@ -0,0 +1,94 @@ +From 82e61c3909db51d91b9d3e2071557b6435018b80 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Mon, 19 Oct 2020 10:55:17 +0200 +Subject: vt: keyboard, extend func_buf_lock to readers + +From: Jiri Slaby + +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: +Reported-by: Minh Yuan +Signed-off-by: Jiri Slaby +Link: https://lore.kernel.org/r/20201019085517.10176-2-jslaby@suse.cz +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } diff --git a/queue-5.9/vt-keyboard-simplify-vt_kdgkbsent.patch b/queue-5.9/vt-keyboard-simplify-vt_kdgkbsent.patch new file mode 100644 index 00000000000..f03a1ccf822 --- /dev/null +++ b/queue-5.9/vt-keyboard-simplify-vt_kdgkbsent.patch @@ -0,0 +1,73 @@ +From 6ca03f90527e499dd5e32d6522909e2ad390896b Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Mon, 19 Oct 2020 10:55:16 +0200 +Subject: vt: keyboard, simplify vt_kdgkbsent + +From: Jiri Slaby + +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: +Signed-off-by: Jiri Slaby +Link: https://lore.kernel.org/r/20201019085517.10176-1-jslaby@suse.cz +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-5.9/vt_ioctl-fix-gio_unimap-regression.patch b/queue-5.9/vt_ioctl-fix-gio_unimap-regression.patch new file mode 100644 index 00000000000..cd922980212 --- /dev/null +++ b/queue-5.9/vt_ioctl-fix-gio_unimap-regression.patch @@ -0,0 +1,64 @@ +From d54654790302ccaa72589380dce060d376ef8716 Mon Sep 17 00:00:00 2001 +From: Jiri Slaby +Date: Mon, 26 Oct 2020 06:54:19 +0100 +Subject: vt_ioctl: fix GIO_UNIMAP regression + +From: Jiri Slaby + +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 +Signed-off-by: Jiri Slaby +Link: https://lore.kernel.org/r/20201026055419.30518-1-jslaby@suse.cz +Signed-off-by: Greg Kroah-Hartman + +--- + 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; diff --git a/queue-5.9/x86-mce-allow-for-copy_mc_fragile-symbol-checksum-to-be-generated.patch b/queue-5.9/x86-mce-allow-for-copy_mc_fragile-symbol-checksum-to-be-generated.patch new file mode 100644 index 00000000000..1e1fae29410 --- /dev/null +++ b/queue-5.9/x86-mce-allow-for-copy_mc_fragile-symbol-checksum-to-be-generated.patch @@ -0,0 +1,39 @@ +From b3149ffcdb31a8eb854cc442a389ae0b539bf28a Mon Sep 17 00:00:00 2001 +From: Borislav Petkov +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 + +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 +Link: https://lkml.kernel.org/r/20201007111447.GA23257@zn.tnic +Signed-off-by: Greg Kroah-Hartman + +--- + 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 + #include + #include ++#include + + #include +