From: Greg Kroah-Hartman Date: Mon, 31 Aug 2020 12:31:56 +0000 (+0200) Subject: 5.8-stable patches X-Git-Tag: v4.4.235~29 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9ad4f85c18be01fca7fa6fd14a777794ce886c4a;p=thirdparty%2Fkernel%2Fstable-queue.git 5.8-stable patches added patches: usb-also-match-device-drivers-using-the-match-vfunc.patch usb-cdc-acm-rework-notification_buffer-resizing.patch usb-dwc3-gadget-don-t-setup-more-than-requested.patch usb-dwc3-gadget-fix-handling-zlp.patch usb-dwc3-gadget-handle-zlp-for-sg-requests.patch usb-fix-device-driver-race.patch usb-gadget-f_ncm-add-bounds-checks-to-ncm_unwrap_ntb.patch usb-gadget-u_f-add-overflow-checks-to-vla-macros.patch usb-gadget-u_f-unbreak-offset-calculation-in-vlas.patch usb-host-ohci-exynos-fix-error-handling-in-exynos_ohci_probe.patch usb-ignore-uas-for-jmicron-jms567-ata-atapi-bridge.patch usb-quirks-add-no-lpm-quirk-for-another-raydium-touchscreen.patch usb-quirks-ignore-duplicate-endpoint-on-sound-devices-mixpre-d.patch usb-storage-add-unusual_uas-entry-for-sony-psz-drives.patch usb-typec-tcpm-fix-fix-source-hard-reset-response-for-tda-2.3.1.1-and-tda-2.3.1.2-failures.patch usb-typec-ucsi-fix-2-unlocked-ucsi_run_command-calls.patch usb-typec-ucsi-fix-ab-ba-lock-inversion.patch usb-typec-ucsi-hold-con-lock-for-the-entire-duration-of-ucsi_register_port.patch usb-typec-ucsi-rework-ppm_lock-handling.patch usb-uas-add-quirk-for-pny-pro-elite.patch usb-yurex-fix-bad-gfp-argument.patch --- diff --git a/queue-5.8/series b/queue-5.8/series index 41a56284471..a0998eb8f04 100644 --- a/queue-5.8/series +++ b/queue-5.8/series @@ -219,3 +219,24 @@ drm-amd-pm-correct-vega10-swctf-limit-setting.patch drm-amd-pm-correct-vega12-swctf-limit-setting.patch drm-amd-pm-correct-vega20-swctf-limit-setting.patch drm-amd-pm-correct-the-thermal-alert-temperature-limit-settings.patch +usb-yurex-fix-bad-gfp-argument.patch +usb-uas-add-quirk-for-pny-pro-elite.patch +usb-quirks-add-no-lpm-quirk-for-another-raydium-touchscreen.patch +usb-quirks-ignore-duplicate-endpoint-on-sound-devices-mixpre-d.patch +usb-ignore-uas-for-jmicron-jms567-ata-atapi-bridge.patch +usb-host-ohci-exynos-fix-error-handling-in-exynos_ohci_probe.patch +usb-gadget-u_f-add-overflow-checks-to-vla-macros.patch +usb-gadget-f_ncm-add-bounds-checks-to-ncm_unwrap_ntb.patch +usb-gadget-u_f-unbreak-offset-calculation-in-vlas.patch +usb-dwc3-gadget-don-t-setup-more-than-requested.patch +usb-dwc3-gadget-fix-handling-zlp.patch +usb-dwc3-gadget-handle-zlp-for-sg-requests.patch +usb-cdc-acm-rework-notification_buffer-resizing.patch +usb-storage-add-unusual_uas-entry-for-sony-psz-drives.patch +usb-also-match-device-drivers-using-the-match-vfunc.patch +usb-fix-device-driver-race.patch +usb-typec-ucsi-fix-ab-ba-lock-inversion.patch +usb-typec-ucsi-fix-2-unlocked-ucsi_run_command-calls.patch +usb-typec-ucsi-rework-ppm_lock-handling.patch +usb-typec-ucsi-hold-con-lock-for-the-entire-duration-of-ucsi_register_port.patch +usb-typec-tcpm-fix-fix-source-hard-reset-response-for-tda-2.3.1.1-and-tda-2.3.1.2-failures.patch diff --git a/queue-5.8/usb-also-match-device-drivers-using-the-match-vfunc.patch b/queue-5.8/usb-also-match-device-drivers-using-the-match-vfunc.patch new file mode 100644 index 00000000000..abc7ac2ef14 --- /dev/null +++ b/queue-5.8/usb-also-match-device-drivers-using-the-match-vfunc.patch @@ -0,0 +1,37 @@ +From adb6e6ac20eedcf1dce19dc75b224e63c0828ea1 Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Tue, 18 Aug 2020 13:04:43 +0200 +Subject: USB: Also match device drivers using the ->match vfunc + +From: Bastien Nocera + +commit adb6e6ac20eedcf1dce19dc75b224e63c0828ea1 upstream. + +We only ever used the ID table matching before, but we should also support +open-coded match functions. + +Fixes: 88b7381a939de ("USB: Select better matching USB drivers when available") +Signed-off-by: Bastien Nocera +Cc: stable +Acked-by: Alan Stern +Link: https://lore.kernel.org/r/20200818110445.509668-1-hadess@hadess.net +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/generic.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/drivers/usb/core/generic.c ++++ b/drivers/usb/core/generic.c +@@ -207,8 +207,9 @@ static int __check_usb_generic(struct de + return 0; + if (!udrv->id_table) + return 0; +- +- return usb_device_match_id(udev, udrv->id_table) != NULL; ++ if (usb_device_match_id(udev, udrv->id_table) != NULL) ++ return 1; ++ return (udrv->match && udrv->match(udev)); + } + + static bool usb_generic_driver_match(struct usb_device *udev) diff --git a/queue-5.8/usb-cdc-acm-rework-notification_buffer-resizing.patch b/queue-5.8/usb-cdc-acm-rework-notification_buffer-resizing.patch new file mode 100644 index 00000000000..d4a40ef4f8c --- /dev/null +++ b/queue-5.8/usb-cdc-acm-rework-notification_buffer-resizing.patch @@ -0,0 +1,99 @@ +From f4b9d8a582f738c24ebeabce5cc15f4b8159d74e Mon Sep 17 00:00:00 2001 +From: Tom Rix +Date: Sat, 1 Aug 2020 08:21:54 -0700 +Subject: USB: cdc-acm: rework notification_buffer resizing + +From: Tom Rix + +commit f4b9d8a582f738c24ebeabce5cc15f4b8159d74e upstream. + +Clang static analysis reports this error + +cdc-acm.c:409:3: warning: Use of memory after it is freed + acm_process_notification(acm, (unsigned char *)dr); + +There are three problems, the first one is that dr is not reset + +The variable dr is set with + +if (acm->nb_index) + dr = (struct usb_cdc_notification *)acm->notification_buffer; + +But if the notification_buffer is too small it is resized with + + if (acm->nb_size) { + kfree(acm->notification_buffer); + acm->nb_size = 0; + } + alloc_size = roundup_pow_of_two(expected_size); + /* + * kmalloc ensures a valid notification_buffer after a + * use of kfree in case the previous allocation was too + * small. Final freeing is done on disconnect. + */ + acm->notification_buffer = + kmalloc(alloc_size, GFP_ATOMIC); + +dr should point to the new acm->notification_buffer. + +The second problem is any data in the notification_buffer is lost +when the pointer is freed. In the normal case, the current data +is accumulated in the notification_buffer here. + + memcpy(&acm->notification_buffer[acm->nb_index], + urb->transfer_buffer, copy_size); + +When a resize happens, anything before +notification_buffer[acm->nb_index] is garbage. + +The third problem is the acm->nb_index is not reset on a +resizing buffer error. + +So switch resizing to using krealloc and reassign dr and +reset nb_index. + +Fixes: ea2583529cd1 ("cdc-acm: reassemble fragmented notifications") +Signed-off-by: Tom Rix +Cc: stable +Acked-by: Oliver Neukum +Link: https://lore.kernel.org/r/20200801152154.20683-1-trix@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/class/cdc-acm.c | 22 ++++++++++------------ + 1 file changed, 10 insertions(+), 12 deletions(-) + +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -378,21 +378,19 @@ static void acm_ctrl_irq(struct urb *urb + if (current_size < expected_size) { + /* notification is transmitted fragmented, reassemble */ + if (acm->nb_size < expected_size) { +- if (acm->nb_size) { +- kfree(acm->notification_buffer); +- acm->nb_size = 0; +- } ++ u8 *new_buffer; + alloc_size = roundup_pow_of_two(expected_size); +- /* +- * kmalloc ensures a valid notification_buffer after a +- * use of kfree in case the previous allocation was too +- * small. Final freeing is done on disconnect. +- */ +- acm->notification_buffer = +- kmalloc(alloc_size, GFP_ATOMIC); +- if (!acm->notification_buffer) ++ /* Final freeing is done on disconnect. */ ++ new_buffer = krealloc(acm->notification_buffer, ++ alloc_size, GFP_ATOMIC); ++ if (!new_buffer) { ++ acm->nb_index = 0; + goto exit; ++ } ++ ++ acm->notification_buffer = new_buffer; + acm->nb_size = alloc_size; ++ dr = (struct usb_cdc_notification *)acm->notification_buffer; + } + + copy_size = min(current_size, diff --git a/queue-5.8/usb-dwc3-gadget-don-t-setup-more-than-requested.patch b/queue-5.8/usb-dwc3-gadget-don-t-setup-more-than-requested.patch new file mode 100644 index 00000000000..3a360287281 --- /dev/null +++ b/queue-5.8/usb-dwc3-gadget-don-t-setup-more-than-requested.patch @@ -0,0 +1,171 @@ +From 5d187c0454ef4c5e046a81af36882d4d515922ec Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Thu, 6 Aug 2020 19:46:23 -0700 +Subject: usb: dwc3: gadget: Don't setup more than requested + +From: Thinh Nguyen + +commit 5d187c0454ef4c5e046a81af36882d4d515922ec upstream. + +The SG list may be set up with entry size more than the requested +length. Check the usb_request->length and make sure that we don't setup +the TRBs to send/receive more than requested. This case may occur when +the SG entry is allocated up to a certain minimum size, but the request +length is less than that. It can also occur when the request is reused +for a different request length. + +Cc: # v4.18+ +Fixes: a31e63b608ff ("usb: dwc3: gadget: Correct handling of scattergather lists") +Signed-off-by: Thinh Nguyen +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/dwc3/gadget.c | 51 +++++++++++++++++++++++++++++++--------------- + 1 file changed, 35 insertions(+), 16 deletions(-) + +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1054,27 +1054,25 @@ static void __dwc3_prepare_one_trb(struc + * dwc3_prepare_one_trb - setup one TRB from one request + * @dep: endpoint for which this request is prepared + * @req: dwc3_request pointer ++ * @trb_length: buffer size of the TRB + * @chain: should this TRB be chained to the next? + * @node: only for isochronous endpoints. First TRB needs different type. + */ + static void dwc3_prepare_one_trb(struct dwc3_ep *dep, +- struct dwc3_request *req, unsigned chain, unsigned node) ++ struct dwc3_request *req, unsigned int trb_length, ++ unsigned chain, unsigned node) + { + struct dwc3_trb *trb; +- unsigned int length; + dma_addr_t dma; + unsigned stream_id = req->request.stream_id; + unsigned short_not_ok = req->request.short_not_ok; + unsigned no_interrupt = req->request.no_interrupt; + unsigned is_last = req->request.is_last; + +- if (req->request.num_sgs > 0) { +- length = sg_dma_len(req->start_sg); ++ if (req->request.num_sgs > 0) + dma = sg_dma_address(req->start_sg); +- } else { +- length = req->request.length; ++ else + dma = req->request.dma; +- } + + trb = &dep->trb_pool[dep->trb_enqueue]; + +@@ -1086,7 +1084,7 @@ static void dwc3_prepare_one_trb(struct + + req->num_trbs++; + +- __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node, ++ __dwc3_prepare_one_trb(dep, trb, dma, trb_length, chain, node, + stream_id, short_not_ok, no_interrupt, is_last); + } + +@@ -1096,16 +1094,27 @@ static void dwc3_prepare_one_trb_sg(stru + struct scatterlist *sg = req->start_sg; + struct scatterlist *s; + int i; +- ++ unsigned int length = req->request.length; + unsigned int remaining = req->request.num_mapped_sgs + - req->num_queued_sgs; + ++ /* ++ * If we resume preparing the request, then get the remaining length of ++ * the request and resume where we left off. ++ */ ++ for_each_sg(req->request.sg, s, req->num_queued_sgs, i) ++ length -= sg_dma_len(s); ++ + for_each_sg(sg, s, remaining, i) { +- unsigned int length = req->request.length; + unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); + unsigned int rem = length % maxp; ++ unsigned int trb_length; + unsigned chain = true; + ++ trb_length = min_t(unsigned int, length, sg_dma_len(s)); ++ ++ length -= trb_length; ++ + /* + * IOMMU driver is coalescing the list of sgs which shares a + * page boundary into one and giving it to USB driver. With +@@ -1113,7 +1122,7 @@ static void dwc3_prepare_one_trb_sg(stru + * sgs passed. So mark the chain bit to false if it isthe last + * mapped sg. + */ +- if (i == remaining - 1) ++ if ((i == remaining - 1) || !length) + chain = false; + + if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) { +@@ -1123,7 +1132,7 @@ static void dwc3_prepare_one_trb_sg(stru + req->needs_extra_trb = true; + + /* prepare normal TRB */ +- dwc3_prepare_one_trb(dep, req, true, i); ++ dwc3_prepare_one_trb(dep, req, trb_length, true, i); + + /* Now prepare one extra TRB to align transfer size */ + trb = &dep->trb_pool[dep->trb_enqueue]; +@@ -1135,7 +1144,7 @@ static void dwc3_prepare_one_trb_sg(stru + req->request.no_interrupt, + req->request.is_last); + } else { +- dwc3_prepare_one_trb(dep, req, chain, i); ++ dwc3_prepare_one_trb(dep, req, trb_length, chain, i); + } + + /* +@@ -1150,6 +1159,16 @@ static void dwc3_prepare_one_trb_sg(stru + + req->num_queued_sgs++; + ++ /* ++ * The number of pending SG entries may not correspond to the ++ * number of mapped SG entries. If all the data are queued, then ++ * don't include unused SG entries. ++ */ ++ if (length == 0) { ++ req->num_pending_sgs -= req->request.num_mapped_sgs - req->num_queued_sgs; ++ break; ++ } ++ + if (!dwc3_calc_trbs_left(dep)) + break; + } +@@ -1169,7 +1188,7 @@ static void dwc3_prepare_one_trb_linear( + req->needs_extra_trb = true; + + /* prepare normal TRB */ +- dwc3_prepare_one_trb(dep, req, true, 0); ++ dwc3_prepare_one_trb(dep, req, length, true, 0); + + /* Now prepare one extra TRB to align transfer size */ + trb = &dep->trb_pool[dep->trb_enqueue]; +@@ -1187,7 +1206,7 @@ static void dwc3_prepare_one_trb_linear( + req->needs_extra_trb = true; + + /* prepare normal TRB */ +- dwc3_prepare_one_trb(dep, req, true, 0); ++ dwc3_prepare_one_trb(dep, req, length, true, 0); + + /* Now prepare one extra TRB to handle ZLP */ + trb = &dep->trb_pool[dep->trb_enqueue]; +@@ -1198,7 +1217,7 @@ static void dwc3_prepare_one_trb_linear( + req->request.no_interrupt, + req->request.is_last); + } else { +- dwc3_prepare_one_trb(dep, req, false, 0); ++ dwc3_prepare_one_trb(dep, req, length, false, 0); + } + } + diff --git a/queue-5.8/usb-dwc3-gadget-fix-handling-zlp.patch b/queue-5.8/usb-dwc3-gadget-fix-handling-zlp.patch new file mode 100644 index 00000000000..d0731a6157f --- /dev/null +++ b/queue-5.8/usb-dwc3-gadget-fix-handling-zlp.patch @@ -0,0 +1,81 @@ +From d2ee3ff79e6a3d4105e684021017d100524dc560 Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Thu, 6 Aug 2020 19:46:29 -0700 +Subject: usb: dwc3: gadget: Fix handling ZLP + +From: Thinh Nguyen + +commit d2ee3ff79e6a3d4105e684021017d100524dc560 upstream. + +The usb_request->zero doesn't apply for isoc. Also, if we prepare a +0-length (ZLP) TRB for the OUT direction, we need to prepare an extra +TRB to pad up to the MPS alignment. Use the same bounce buffer for the +ZLP TRB and the extra pad TRB. + +Cc: # v4.5+ +Fixes: d6e5a549cc4d ("usb: dwc3: simplify ZLP handling") +Fixes: 04c03d10e507 ("usb: dwc3: gadget: handle request->zero") +Signed-off-by: Thinh Nguyen +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/dwc3/gadget.c | 25 +++++++++++++++++++++++-- + 1 file changed, 23 insertions(+), 2 deletions(-) + +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1199,6 +1199,7 @@ static void dwc3_prepare_one_trb_linear( + req->request.no_interrupt, + req->request.is_last); + } else if (req->request.zero && req->request.length && ++ !usb_endpoint_xfer_isoc(dep->endpoint.desc) && + (IS_ALIGNED(req->request.length, maxp))) { + struct dwc3 *dwc = dep->dwc; + struct dwc3_trb *trb; +@@ -1208,14 +1209,25 @@ static void dwc3_prepare_one_trb_linear( + /* prepare normal TRB */ + dwc3_prepare_one_trb(dep, req, length, true, 0); + +- /* Now prepare one extra TRB to handle ZLP */ ++ /* Prepare one extra TRB to handle ZLP */ + trb = &dep->trb_pool[dep->trb_enqueue]; + req->num_trbs++; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, +- false, 1, req->request.stream_id, ++ !req->direction, 1, req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt, + req->request.is_last); ++ ++ /* Prepare one more TRB to handle MPS alignment for OUT */ ++ if (!req->direction) { ++ trb = &dep->trb_pool[dep->trb_enqueue]; ++ req->num_trbs++; ++ __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp, ++ false, 1, req->request.stream_id, ++ req->request.short_not_ok, ++ req->request.no_interrupt, ++ req->request.is_last); ++ } + } else { + dwc3_prepare_one_trb(dep, req, length, false, 0); + } +@@ -2668,8 +2680,17 @@ static int dwc3_gadget_ep_cleanup_comple + status); + + if (req->needs_extra_trb) { ++ unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); ++ + ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, + status); ++ ++ /* Reclaim MPS padding TRB for ZLP */ ++ if (!req->direction && req->request.zero && req->request.length && ++ !usb_endpoint_xfer_isoc(dep->endpoint.desc) && ++ (IS_ALIGNED(req->request.length, maxp))) ++ ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event, status); ++ + req->needs_extra_trb = false; + } + diff --git a/queue-5.8/usb-dwc3-gadget-handle-zlp-for-sg-requests.patch b/queue-5.8/usb-dwc3-gadget-handle-zlp-for-sg-requests.patch new file mode 100644 index 00000000000..1a362352111 --- /dev/null +++ b/queue-5.8/usb-dwc3-gadget-handle-zlp-for-sg-requests.patch @@ -0,0 +1,62 @@ +From bc9a2e226ea95e1699f7590845554de095308b75 Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Thu, 6 Aug 2020 19:46:35 -0700 +Subject: usb: dwc3: gadget: Handle ZLP for sg requests + +From: Thinh Nguyen + +commit bc9a2e226ea95e1699f7590845554de095308b75 upstream. + +Currently dwc3 doesn't handle usb_request->zero for SG requests. This +change checks and prepares extra TRBs for the ZLP for SG requests. + +Cc: # v4.5+ +Fixes: 04c03d10e507 ("usb: dwc3: gadget: handle request->zero") +Signed-off-by: Thinh Nguyen +Signed-off-by: Felipe Balbi +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/dwc3/gadget.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1143,6 +1143,37 @@ static void dwc3_prepare_one_trb_sg(stru + req->request.short_not_ok, + req->request.no_interrupt, + req->request.is_last); ++ } else if (req->request.zero && req->request.length && ++ !usb_endpoint_xfer_isoc(dep->endpoint.desc) && ++ !rem && !chain) { ++ struct dwc3 *dwc = dep->dwc; ++ struct dwc3_trb *trb; ++ ++ req->needs_extra_trb = true; ++ ++ /* Prepare normal TRB */ ++ dwc3_prepare_one_trb(dep, req, trb_length, true, i); ++ ++ /* Prepare one extra TRB to handle ZLP */ ++ trb = &dep->trb_pool[dep->trb_enqueue]; ++ req->num_trbs++; ++ __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, ++ !req->direction, 1, ++ req->request.stream_id, ++ req->request.short_not_ok, ++ req->request.no_interrupt, ++ req->request.is_last); ++ ++ /* Prepare one more TRB to handle MPS alignment */ ++ if (!req->direction) { ++ trb = &dep->trb_pool[dep->trb_enqueue]; ++ req->num_trbs++; ++ __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp, ++ false, 1, req->request.stream_id, ++ req->request.short_not_ok, ++ req->request.no_interrupt, ++ req->request.is_last); ++ } + } else { + dwc3_prepare_one_trb(dep, req, trb_length, chain, i); + } diff --git a/queue-5.8/usb-fix-device-driver-race.patch b/queue-5.8/usb-fix-device-driver-race.patch new file mode 100644 index 00000000000..1fd049193b1 --- /dev/null +++ b/queue-5.8/usb-fix-device-driver-race.patch @@ -0,0 +1,91 @@ +From d5643d2249b279077427b2c2b2ffae9b70c95b0b Mon Sep 17 00:00:00 2001 +From: Bastien Nocera +Date: Tue, 18 Aug 2020 13:04:45 +0200 +Subject: USB: Fix device driver race + +From: Bastien Nocera + +commit d5643d2249b279077427b2c2b2ffae9b70c95b0b upstream. + +When a new device with a specialised device driver is plugged in, the +new driver will be modprobe()'d but the driver core will attach the +"generic" driver to the device. + +After that, nothing will trigger a reprobe when the modprobe()'d device +driver has finished initialising, as the device has the "generic" +driver attached to it. + +Trigger a reprobe ourselves when new specialised drivers get registered. + +Fixes: 88b7381a939d ("USB: Select better matching USB drivers when available") +Signed-off-by: Bastien Nocera +Cc: stable +Acked-by: Alan Stern +Link: https://lore.kernel.org/r/20200818110445.509668-3-hadess@hadess.net +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/driver.c | 40 ++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 38 insertions(+), 2 deletions(-) + +--- a/drivers/usb/core/driver.c ++++ b/drivers/usb/core/driver.c +@@ -905,6 +905,35 @@ static int usb_uevent(struct device *dev + return 0; + } + ++static bool is_dev_usb_generic_driver(struct device *dev) ++{ ++ struct usb_device_driver *udd = dev->driver ? ++ to_usb_device_driver(dev->driver) : NULL; ++ ++ return udd == &usb_generic_driver; ++} ++ ++static int __usb_bus_reprobe_drivers(struct device *dev, void *data) ++{ ++ struct usb_device_driver *new_udriver = data; ++ struct usb_device *udev; ++ int ret; ++ ++ if (!is_dev_usb_generic_driver(dev)) ++ 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)) ++ return 0; ++ ++ ret = device_reprobe(dev); ++ if (ret && ret != -EPROBE_DEFER) ++ dev_err(dev, "Failed to reprobe device (error %d)\n", ret); ++ ++ return 0; ++} ++ + /** + * usb_register_device_driver - register a USB device (not interface) driver + * @new_udriver: USB operations for the device driver +@@ -934,13 +963,20 @@ int usb_register_device_driver(struct us + + retval = driver_register(&new_udriver->drvwrap.driver); + +- if (!retval) ++ if (!retval) { + pr_info("%s: registered new device driver %s\n", + usbcore_name, new_udriver->name); +- else ++ /* ++ * Check whether any device could be better served with ++ * this new driver ++ */ ++ bus_for_each_dev(&usb_bus_type, NULL, new_udriver, ++ __usb_bus_reprobe_drivers); ++ } else { + printk(KERN_ERR "%s: error %d registering device " + " driver %s\n", + usbcore_name, retval, new_udriver->name); ++ } + + return retval; + } diff --git a/queue-5.8/usb-gadget-f_ncm-add-bounds-checks-to-ncm_unwrap_ntb.patch b/queue-5.8/usb-gadget-f_ncm-add-bounds-checks-to-ncm_unwrap_ntb.patch new file mode 100644 index 00000000000..3a4a4814824 --- /dev/null +++ b/queue-5.8/usb-gadget-f_ncm-add-bounds-checks-to-ncm_unwrap_ntb.patch @@ -0,0 +1,178 @@ +From 2b74b0a04d3e9f9f08ff026e5663dce88ff94e52 Mon Sep 17 00:00:00 2001 +From: Brooke Basile +Date: Tue, 25 Aug 2020 09:07:27 -0400 +Subject: USB: gadget: f_ncm: add bounds checks to ncm_unwrap_ntb() + +From: Brooke Basile + +commit 2b74b0a04d3e9f9f08ff026e5663dce88ff94e52 upstream. + +Some values extracted by ncm_unwrap_ntb() could possibly lead to several +different out of bounds reads of memory. Specifically the values passed +to netdev_alloc_skb_ip_align() need to be checked so that memory is not +overflowed. + +Resolve this by applying bounds checking to a number of different +indexes and lengths of the structure parsing logic. + +Reported-by: Ilja Van Sprundel +Signed-off-by: Brooke Basile +Acked-by: Felipe Balbi +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/function/f_ncm.c | 81 ++++++++++++++++++++++++++++++------ + 1 file changed, 69 insertions(+), 12 deletions(-) + +--- a/drivers/usb/gadget/function/f_ncm.c ++++ b/drivers/usb/gadget/function/f_ncm.c +@@ -1181,12 +1181,15 @@ static int ncm_unwrap_ntb(struct gether + int ndp_index; + unsigned dg_len, dg_len2; + unsigned ndp_len; ++ unsigned block_len; + struct sk_buff *skb2; + int ret = -EINVAL; +- unsigned max_size = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize); ++ unsigned ntb_max = le32_to_cpu(ntb_parameters.dwNtbOutMaxSize); ++ unsigned frame_max = le16_to_cpu(ecm_desc.wMaxSegmentSize); + const struct ndp_parser_opts *opts = ncm->parser_opts; + unsigned crc_len = ncm->is_crc ? sizeof(uint32_t) : 0; + int dgram_counter; ++ bool ndp_after_header; + + /* dwSignature */ + if (get_unaligned_le32(tmp) != opts->nth_sign) { +@@ -1205,25 +1208,37 @@ static int ncm_unwrap_ntb(struct gether + } + tmp++; /* skip wSequence */ + ++ block_len = get_ncm(&tmp, opts->block_length); + /* (d)wBlockLength */ +- if (get_ncm(&tmp, opts->block_length) > max_size) { ++ if (block_len > ntb_max) { + INFO(port->func.config->cdev, "OUT size exceeded\n"); + goto err; + } + + ndp_index = get_ncm(&tmp, opts->ndp_index); ++ ndp_after_header = false; + + /* Run through all the NDP's in the NTB */ + do { +- /* NCM 3.2 */ +- if (((ndp_index % 4) != 0) && +- (ndp_index < opts->nth_size)) { ++ /* ++ * NCM 3.2 ++ * dwNdpIndex ++ */ ++ if (((ndp_index % 4) != 0) || ++ (ndp_index < opts->nth_size) || ++ (ndp_index > (block_len - ++ opts->ndp_size))) { + INFO(port->func.config->cdev, "Bad index: %#X\n", + ndp_index); + goto err; + } ++ if (ndp_index == opts->nth_size) ++ ndp_after_header = true; + +- /* walk through NDP */ ++ /* ++ * walk through NDP ++ * dwSignature ++ */ + tmp = (void *)(skb->data + ndp_index); + if (get_unaligned_le32(tmp) != ncm->ndp_sign) { + INFO(port->func.config->cdev, "Wrong NDP SIGN\n"); +@@ -1234,14 +1249,15 @@ static int ncm_unwrap_ntb(struct gether + ndp_len = get_unaligned_le16(tmp++); + /* + * NCM 3.3.1 ++ * wLength + * entry is 2 items + * item size is 16/32 bits, opts->dgram_item_len * 2 bytes + * minimal: struct usb_cdc_ncm_ndpX + normal entry + zero entry + * Each entry is a dgram index and a dgram length. + */ + if ((ndp_len < opts->ndp_size +- + 2 * 2 * (opts->dgram_item_len * 2)) +- || (ndp_len % opts->ndplen_align != 0)) { ++ + 2 * 2 * (opts->dgram_item_len * 2)) || ++ (ndp_len % opts->ndplen_align != 0)) { + INFO(port->func.config->cdev, "Bad NDP length: %#X\n", + ndp_len); + goto err; +@@ -1258,8 +1274,21 @@ static int ncm_unwrap_ntb(struct gether + + do { + index = index2; ++ /* wDatagramIndex[0] */ ++ if ((index < opts->nth_size) || ++ (index > block_len - opts->dpe_size)) { ++ INFO(port->func.config->cdev, ++ "Bad index: %#X\n", index); ++ goto err; ++ } ++ + dg_len = dg_len2; +- if (dg_len < 14 + crc_len) { /* ethernet hdr + crc */ ++ /* ++ * wDatagramLength[0] ++ * ethernet hdr + crc or larger than max frame size ++ */ ++ if ((dg_len < 14 + crc_len) || ++ (dg_len > frame_max)) { + INFO(port->func.config->cdev, + "Bad dgram length: %#X\n", dg_len); + goto err; +@@ -1283,6 +1312,37 @@ static int ncm_unwrap_ntb(struct gether + index2 = get_ncm(&tmp, opts->dgram_item_len); + dg_len2 = get_ncm(&tmp, opts->dgram_item_len); + ++ if (index2 == 0 || dg_len2 == 0) ++ break; ++ ++ /* wDatagramIndex[1] */ ++ if (ndp_after_header) { ++ if (index2 < opts->nth_size + opts->ndp_size) { ++ INFO(port->func.config->cdev, ++ "Bad index: %#X\n", index2); ++ goto err; ++ } ++ } else { ++ if (index2 < opts->nth_size + opts->dpe_size) { ++ INFO(port->func.config->cdev, ++ "Bad index: %#X\n", index2); ++ goto err; ++ } ++ } ++ if (index2 > block_len - opts->dpe_size) { ++ INFO(port->func.config->cdev, ++ "Bad index: %#X\n", index2); ++ goto err; ++ } ++ ++ /* wDatagramLength[1] */ ++ if ((dg_len2 < 14 + crc_len) || ++ (dg_len2 > frame_max)) { ++ INFO(port->func.config->cdev, ++ "Bad dgram length: %#X\n", dg_len); ++ goto err; ++ } ++ + /* + * Copy the data into a new skb. + * This ensures the truesize is correct +@@ -1299,9 +1359,6 @@ static int ncm_unwrap_ntb(struct gether + ndp_len -= 2 * (opts->dgram_item_len * 2); + + dgram_counter++; +- +- if (index2 == 0 || dg_len2 == 0) +- break; + } while (ndp_len > 2 * (opts->dgram_item_len * 2)); + } while (ndp_index); + diff --git a/queue-5.8/usb-gadget-u_f-add-overflow-checks-to-vla-macros.patch b/queue-5.8/usb-gadget-u_f-add-overflow-checks-to-vla-macros.patch new file mode 100644 index 00000000000..66b2843d241 --- /dev/null +++ b/queue-5.8/usb-gadget-u_f-add-overflow-checks-to-vla-macros.patch @@ -0,0 +1,85 @@ +From b1cd1b65afba95971fa457dfdb2c941c60d38c5b Mon Sep 17 00:00:00 2001 +From: Brooke Basile +Date: Tue, 25 Aug 2020 09:05:08 -0400 +Subject: USB: gadget: u_f: add overflow checks to VLA macros + +From: Brooke Basile + +commit b1cd1b65afba95971fa457dfdb2c941c60d38c5b upstream. + +size can potentially hold an overflowed value if its assigned expression +is left unchecked, leading to a smaller than needed allocation when +vla_group_size() is used by callers to allocate memory. +To fix this, add a test for saturation before declaring variables and an +overflow check to (n) * sizeof(type). +If the expression results in overflow, vla_group_size() will return SIZE_MAX. + +Reported-by: Ilja Van Sprundel +Suggested-by: Kees Cook +Signed-off-by: Brooke Basile +Acked-by: Felipe Balbi +Cc: stable +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/u_f.h | 38 +++++++++++++++++++++++++++----------- + 1 file changed, 27 insertions(+), 11 deletions(-) + +--- a/drivers/usb/gadget/u_f.h ++++ b/drivers/usb/gadget/u_f.h +@@ -14,6 +14,7 @@ + #define __U_F_H__ + + #include ++#include + + /* Variable Length Array Macros **********************************************/ + #define vla_group(groupname) size_t groupname##__next = 0 +@@ -21,21 +22,36 @@ + + #define vla_item(groupname, type, name, n) \ + size_t groupname##_##name##__offset = ({ \ +- size_t align_mask = __alignof__(type) - 1; \ +- size_t offset = (groupname##__next + align_mask) & ~align_mask;\ +- size_t size = (n) * sizeof(type); \ +- groupname##__next = offset + size; \ ++ size_t offset = 0; \ ++ if (groupname##__next != SIZE_MAX) { \ ++ size_t align_mask = __alignof__(type) - 1; \ ++ size_t offset = (groupname##__next + align_mask) \ ++ & ~align_mask; \ ++ size_t size = array_size(n, sizeof(type)); \ ++ if (check_add_overflow(offset, size, \ ++ &groupname##__next)) { \ ++ groupname##__next = SIZE_MAX; \ ++ offset = 0; \ ++ } \ ++ } \ + offset; \ + }) + + #define vla_item_with_sz(groupname, type, name, n) \ +- size_t groupname##_##name##__sz = (n) * sizeof(type); \ +- size_t groupname##_##name##__offset = ({ \ +- size_t align_mask = __alignof__(type) - 1; \ +- size_t offset = (groupname##__next + align_mask) & ~align_mask;\ +- size_t size = groupname##_##name##__sz; \ +- groupname##__next = offset + size; \ +- offset; \ ++ size_t groupname##_##name##__sz = array_size(n, sizeof(type)); \ ++ size_t groupname##_##name##__offset = ({ \ ++ size_t offset = 0; \ ++ if (groupname##__next != SIZE_MAX) { \ ++ size_t align_mask = __alignof__(type) - 1; \ ++ size_t offset = (groupname##__next + align_mask) \ ++ & ~align_mask; \ ++ if (check_add_overflow(offset, groupname##_##name##__sz,\ ++ &groupname##__next)) { \ ++ groupname##__next = SIZE_MAX; \ ++ offset = 0; \ ++ } \ ++ } \ ++ offset; \ + }) + + #define vla_ptr(ptr, groupname, name) \ diff --git a/queue-5.8/usb-gadget-u_f-unbreak-offset-calculation-in-vlas.patch b/queue-5.8/usb-gadget-u_f-unbreak-offset-calculation-in-vlas.patch new file mode 100644 index 00000000000..4fc880659fc --- /dev/null +++ b/queue-5.8/usb-gadget-u_f-unbreak-offset-calculation-in-vlas.patch @@ -0,0 +1,51 @@ +From bfd08d06d978d0304eb6f7855b548aa2cd1c5486 Mon Sep 17 00:00:00 2001 +From: Andy Shevchenko +Date: Wed, 26 Aug 2020 22:21:19 +0300 +Subject: USB: gadget: u_f: Unbreak offset calculation in VLAs + +From: Andy Shevchenko + +commit bfd08d06d978d0304eb6f7855b548aa2cd1c5486 upstream. + +Inadvertently the commit b1cd1b65afba ("USB: gadget: u_f: add overflow checks +to VLA macros") makes VLA macros to always return 0 due to different scope of +two variables of the same name. Obviously we need to have only one. + +Fixes: b1cd1b65afba ("USB: gadget: u_f: add overflow checks to VLA macros") +Reported-by: Marek Szyprowski +Tested-by: Marek Szyprowski +Signed-off-by: Andy Shevchenko +Cc: Brooke Basile +Cc: stable +Link: https://lore.kernel.org/r/20200826192119.56450-1-andriy.shevchenko@linux.intel.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/gadget/u_f.h | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/usb/gadget/u_f.h ++++ b/drivers/usb/gadget/u_f.h +@@ -25,9 +25,9 @@ + size_t offset = 0; \ + if (groupname##__next != SIZE_MAX) { \ + size_t align_mask = __alignof__(type) - 1; \ +- size_t offset = (groupname##__next + align_mask) \ +- & ~align_mask; \ + size_t size = array_size(n, sizeof(type)); \ ++ offset = (groupname##__next + align_mask) & \ ++ ~align_mask; \ + if (check_add_overflow(offset, size, \ + &groupname##__next)) { \ + groupname##__next = SIZE_MAX; \ +@@ -43,8 +43,8 @@ + size_t offset = 0; \ + if (groupname##__next != SIZE_MAX) { \ + size_t align_mask = __alignof__(type) - 1; \ +- size_t offset = (groupname##__next + align_mask) \ +- & ~align_mask; \ ++ offset = (groupname##__next + align_mask) & \ ++ ~align_mask; \ + if (check_add_overflow(offset, groupname##_##name##__sz,\ + &groupname##__next)) { \ + groupname##__next = SIZE_MAX; \ diff --git a/queue-5.8/usb-host-ohci-exynos-fix-error-handling-in-exynos_ohci_probe.patch b/queue-5.8/usb-host-ohci-exynos-fix-error-handling-in-exynos_ohci_probe.patch new file mode 100644 index 00000000000..9008119fd4f --- /dev/null +++ b/queue-5.8/usb-host-ohci-exynos-fix-error-handling-in-exynos_ohci_probe.patch @@ -0,0 +1,41 @@ +From 1d4169834628d18b2392a2da92b7fbf5e8e2ce89 Mon Sep 17 00:00:00 2001 +From: Tang Bin +Date: Wed, 26 Aug 2020 22:49:31 +0800 +Subject: usb: host: ohci-exynos: Fix error handling in exynos_ohci_probe() + +From: Tang Bin + +commit 1d4169834628d18b2392a2da92b7fbf5e8e2ce89 upstream. + +If the function platform_get_irq() failed, the negative value +returned will not be detected here. So fix error handling in +exynos_ohci_probe(). And when get irq failed, the function +platform_get_irq() logs an error message, so remove redundant +message here. + +Fixes: 62194244cf87 ("USB: Add Samsung Exynos OHCI diver") +Signed-off-by: Zhang Shengju +Cc: stable +Signed-off-by: Tang Bin +Reviewed-by: Krzysztof Kozlowski +Link: https://lore.kernel.org/r/20200826144931.1828-1-tangbin@cmss.chinamobile.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/host/ohci-exynos.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +--- a/drivers/usb/host/ohci-exynos.c ++++ b/drivers/usb/host/ohci-exynos.c +@@ -171,9 +171,8 @@ static int exynos_ohci_probe(struct plat + hcd->rsrc_len = resource_size(res); + + irq = platform_get_irq(pdev, 0); +- if (!irq) { +- dev_err(&pdev->dev, "Failed to get IRQ\n"); +- err = -ENODEV; ++ if (irq < 0) { ++ err = irq; + goto fail_io; + } + diff --git a/queue-5.8/usb-ignore-uas-for-jmicron-jms567-ata-atapi-bridge.patch b/queue-5.8/usb-ignore-uas-for-jmicron-jms567-ata-atapi-bridge.patch new file mode 100644 index 00000000000..946547e5a60 --- /dev/null +++ b/queue-5.8/usb-ignore-uas-for-jmicron-jms567-ata-atapi-bridge.patch @@ -0,0 +1,37 @@ +From 9aa37788e7ebb3f489fb4b71ce07adadd444264a Mon Sep 17 00:00:00 2001 +From: Cyril Roelandt +Date: Tue, 25 Aug 2020 23:22:31 +0200 +Subject: USB: Ignore UAS for JMicron JMS567 ATA/ATAPI Bridge + +From: Cyril Roelandt + +commit 9aa37788e7ebb3f489fb4b71ce07adadd444264a upstream. + +This device does not support UAS properly and a similar entry already +exists in drivers/usb/storage/unusual_uas.h. Without this patch, +storage_probe() defers the handling of this device to UAS, which cannot +handle it either. + +Tested-by: Brice Goglin +Fixes: bc3bdb12bbb3 ("usb-storage: Disable UAS on JMicron SATA enclosure") +Acked-by: Alan Stern +CC: +Signed-off-by: Cyril Roelandt +Link: https://lore.kernel.org/r/20200825212231.46309-1-tipecaml@gmail.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/storage/unusual_devs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/storage/unusual_devs.h ++++ b/drivers/usb/storage/unusual_devs.h +@@ -2328,7 +2328,7 @@ UNUSUAL_DEV( 0x357d, 0x7788, 0x0114, 0x + "JMicron", + "USB to ATA/ATAPI Bridge", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, +- US_FL_BROKEN_FUA ), ++ US_FL_BROKEN_FUA | US_FL_IGNORE_UAS ), + + /* Reported by Andrey Rahmatullin */ + UNUSUAL_DEV( 0x4102, 0x1020, 0x0100, 0x0100, diff --git a/queue-5.8/usb-quirks-add-no-lpm-quirk-for-another-raydium-touchscreen.patch b/queue-5.8/usb-quirks-add-no-lpm-quirk-for-another-raydium-touchscreen.patch new file mode 100644 index 00000000000..80194e95991 --- /dev/null +++ b/queue-5.8/usb-quirks-add-no-lpm-quirk-for-another-raydium-touchscreen.patch @@ -0,0 +1,38 @@ +From 5967116e8358899ebaa22702d09b0af57fef23e1 Mon Sep 17 00:00:00 2001 +From: Kai-Heng Feng +Date: Fri, 31 Jul 2020 13:16:20 +0800 +Subject: USB: quirks: Add no-lpm quirk for another Raydium touchscreen + +From: Kai-Heng Feng + +commit 5967116e8358899ebaa22702d09b0af57fef23e1 upstream. + +There's another Raydium touchscreen needs the no-lpm quirk: +[ 1.339149] usb 1-9: New USB device found, idVendor=2386, idProduct=350e, bcdDevice= 0.00 +[ 1.339150] usb 1-9: New USB device strings: Mfr=1, Product=2, SerialNumber=0 +[ 1.339151] usb 1-9: Product: Raydium Touch System +[ 1.339152] usb 1-9: Manufacturer: Raydium Corporation +... +[ 6.450497] usb 1-9: can't set config #1, error -110 + +BugLink: https://bugs.launchpad.net/bugs/1889446 +Signed-off-by: Kai-Heng Feng +Cc: stable +Link: https://lore.kernel.org/r/20200731051622.28643-1-kai.heng.feng@canonical.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/quirks.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -465,6 +465,8 @@ static const struct usb_device_id usb_qu + + { USB_DEVICE(0x2386, 0x3119), .driver_info = USB_QUIRK_NO_LPM }, + ++ { USB_DEVICE(0x2386, 0x350e), .driver_info = USB_QUIRK_NO_LPM }, ++ + /* DJI CineSSD */ + { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM }, + diff --git a/queue-5.8/usb-quirks-ignore-duplicate-endpoint-on-sound-devices-mixpre-d.patch b/queue-5.8/usb-quirks-ignore-duplicate-endpoint-on-sound-devices-mixpre-d.patch new file mode 100644 index 00000000000..70341669248 --- /dev/null +++ b/queue-5.8/usb-quirks-ignore-duplicate-endpoint-on-sound-devices-mixpre-d.patch @@ -0,0 +1,53 @@ +From 068834a2773b6a12805105cfadbb3d4229fc6e0a Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Wed, 26 Aug 2020 15:46:24 -0400 +Subject: USB: quirks: Ignore duplicate endpoint on Sound Devices MixPre-D + +From: Alan Stern + +commit 068834a2773b6a12805105cfadbb3d4229fc6e0a upstream. + +The Sound Devices MixPre-D audio card suffers from the same defect +as the Sound Devices USBPre2: an endpoint shared between a normal +audio interface and a vendor-specific interface, in violation of the +USB spec. Since the USB core now treats duplicated endpoints as bugs +and ignores them, the audio endpoint isn't available and the card +can't be used for audio capture. + +Along the same lines as commit bdd1b147b802 ("USB: quirks: blacklist +duplicate ep on Sound Devices USBPre2"), this patch adds a quirks +entry saying to ignore ep5in for interface 1, leaving it available for +use with standard audio interface 2. + +Reported-and-tested-by: Jean-Christophe Barnoud +Signed-off-by: Alan Stern +CC: +Fixes: 3e4f8e21c4f2 ("USB: core: fix check for duplicate endpoints") +Link: https://lore.kernel.org/r/20200826194624.GA412633@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/core/quirks.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -370,6 +370,10 @@ static const struct usb_device_id usb_qu + { USB_DEVICE(0x0926, 0x0202), .driver_info = + USB_QUIRK_ENDPOINT_BLACKLIST }, + ++ /* Sound Devices MixPre-D */ ++ { USB_DEVICE(0x0926, 0x0208), .driver_info = ++ USB_QUIRK_ENDPOINT_BLACKLIST }, ++ + /* Keytouch QWERTY Panel keyboard */ + { USB_DEVICE(0x0926, 0x3333), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, +@@ -511,6 +515,7 @@ static const struct usb_device_id usb_am + */ + static const struct usb_device_id usb_endpoint_blacklist[] = { + { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 }, ++ { USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0208, 1), .driver_info = 0x85 }, + { } + }; + diff --git a/queue-5.8/usb-storage-add-unusual_uas-entry-for-sony-psz-drives.patch b/queue-5.8/usb-storage-add-unusual_uas-entry-for-sony-psz-drives.patch new file mode 100644 index 00000000000..adc63da755b --- /dev/null +++ b/queue-5.8/usb-storage-add-unusual_uas-entry-for-sony-psz-drives.patch @@ -0,0 +1,42 @@ +From 20934c0de13b49a072fb1e0ca79fe0fe0e40eae5 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Wed, 26 Aug 2020 10:32:29 -0400 +Subject: usb: storage: Add unusual_uas entry for Sony PSZ drives +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Alan Stern + +commit 20934c0de13b49a072fb1e0ca79fe0fe0e40eae5 upstream. + +The PSZ-HA* family of USB disk drives from Sony can't handle the +REPORT OPCODES command when using the UAS protocol. This patch adds +an appropriate quirks entry. + +Reported-and-tested-by: Till Dörges +Signed-off-by: Alan Stern +CC: +Link: https://lore.kernel.org/r/20200826143229.GB400430@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/storage/unusual_uas.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/usb/storage/unusual_uas.h ++++ b/drivers/usb/storage/unusual_uas.h +@@ -28,6 +28,13 @@ + * and don't forget to CC: the USB development list + */ + ++/* Reported-by: Till Dörges */ ++UNUSUAL_DEV(0x054c, 0x087d, 0x0000, 0x9999, ++ "Sony", ++ "PSZ-HA*", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_NO_REPORT_OPCODES), ++ + /* Reported-by: Julian Groß */ + UNUSUAL_DEV(0x059f, 0x105f, 0x0000, 0x9999, + "LaCie", diff --git a/queue-5.8/usb-typec-tcpm-fix-fix-source-hard-reset-response-for-tda-2.3.1.1-and-tda-2.3.1.2-failures.patch b/queue-5.8/usb-typec-tcpm-fix-fix-source-hard-reset-response-for-tda-2.3.1.1-and-tda-2.3.1.2-failures.patch new file mode 100644 index 00000000000..e6543c033ea --- /dev/null +++ b/queue-5.8/usb-typec-tcpm-fix-fix-source-hard-reset-response-for-tda-2.3.1.1-and-tda-2.3.1.2-failures.patch @@ -0,0 +1,139 @@ +From 23e26d0577535f5ffe4ff8ed6d06e009553c0bca Mon Sep 17 00:00:00 2001 +From: Badhri Jagan Sridharan +Date: Mon, 17 Aug 2020 11:46:01 -0700 +Subject: usb: typec: tcpm: Fix Fix source hard reset response for TDA 2.3.1.1 and TDA 2.3.1.2 failures + +From: Badhri Jagan Sridharan + +commit 23e26d0577535f5ffe4ff8ed6d06e009553c0bca upstream. + +The patch addresses the compliance test failures while running TDA +2.3.1.1 and TDA 2.3.1.2 of the "PD Communications Engine USB PD +Compliance MOI" test plan published in https://www.usb.org/usbc. +For a product to be Type-C compliant, it's expected that these tests +are run on usb.org certified Type-C compliance tester as mentioned in +https://www.usb.org/usbc. + +While the purpose of TDA 2.3.1.1 and TDA 2.3.1.2 is to verify that +the static and dynamic electrical capabilities of a Source meet the +requirements for each PDO offered, while doing so, the tests also +monitor that the timing of the VBUS waveform versus the messages meets +the requirements for Hard Reset defined in PROT-PROC-HR-TSTR as +mentioned in step 11 of TDA.2.3.1.1 and step 15 of TDA.2.3.1.2. + +TDB.2.2.13.1: PROT-PROC-HR-TSTR Procedure and Checks for Tester +Originated Hard Reset +Purpose: To perform the appropriate protocol checks relating to any +circumstance in which the Hard Reset signal is sent by the Tester. + +UUT is behaving as source: +The Tester sends a Hard Reset signal. +1. Check VBUS stays within present valid voltage range for +tPSHardReset min (25ms) after last bit of Hard Reset signal. +[PROT_PROC_HR_TSTR_1] +2. Check that VBUS starts to fall below present valid voltage range by +tPSHardReset max (35ms). [PROT_PROC_HR_TSTR_2] +3. Check that VBUS reaches vSafe0V within tSafe0v max (650 ms). +[PROT_PROC_HR_TSTR_3] +4. Check that VBUS starts rising to vSafe5V after a delay of +tSrcRecover (0.66s - 1s) from reaching vSafe0V. [PROT_PROC_HR_TSTR_4] +5. Check that VBUS reaches vSafe5V within tSrcTurnOn max (275ms) of +rising above vSafe0v max (0.8V). [PROT_PROC_HR_TSTR_5] Power Delivery +Compliance Plan 139 6. Check that Source Capabilities are finished +sending within tFirstSourceCap max (250ms) of VBUS reaching vSafe5v +min. [PROT_PROC_HR_TSTR_6]. + +This is in line with 7.1.5 Response to Hard Resets of the USB Power +Delivery Specification Revision 3.0, Version 1.2, +"Hard Reset Signaling indicates a communication failure has occurred +and the Source Shall stop driving VCONN, Shall remove Rp from the +VCONN pin and Shall drive VBUS to vSafe0V as shown in Figure 7-9. The +USB connection May reset during a Hard Reset since the VBUS voltage +will be less than vSafe5V for an extended period of time. After +establishing the vSafe0V voltage condition on VBUS, the Source Shall +wait tSrcRecover before re-applying VCONN and restoring VBUS to +vSafe5V. A Source Shall conform to the VCONN timing as specified in +[USB Type-C 1.3]." + +With the above guidelines from the spec in mind, TCPM does not turn +off VCONN while entering SRC_HARD_RESET_VBUS_OFF. The patch makes TCPM +turn off VCONN while entering SRC_HARD_RESET_VBUS_OFF and turn it back +on while entering SRC_HARD_RESET_VBUS_ON along with vbus instead of +having VCONN on through hardreset. + +Also, the spec clearly states that "After establishing the vSafe0V +voltage condition on VBUS", the Source Shall wait tSrcRecover before +re-applying VCONN and restoring VBUS to vSafe5V. +TCPM does not conform to this requirement. If the TCPC driver calls +tcpm_vbus_change with vbus off signal, TCPM right away enters +SRC_HARD_RESET_VBUS_ON without waiting for tSrcRecover. +For TCPC's which are buggy/does not call tcpm_vbus_change, TCPM +assumes that the vsafe0v is instantaneous as TCPM only waits +tSrcRecover instead of waiting for tSafe0v + tSrcRecover. +This patch also fixes this behavior by making sure that TCPM waits for +tSrcRecover before transitioning into SRC_HARD_RESET_VBUS_ON when +tcpm_vbus_change is called by TCPC. +When TCPC does not call tcpm_vbus_change, TCPM assumes the worst case +i.e. tSafe0v + tSrcRecover before transitioning into +SRC_HARD_RESET_VBUS_ON. + +Signed-off-by: Badhri Jagan Sridharan +Reviewed-by: Guenter Roeck +Reviewed-by: Heikki Krogerus +Cc: stable +Link: https://lore.kernel.org/r/20200817184601.1899929-1-badhri@google.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/typec/tcpm/tcpm.c | 28 +++++++++++++++++++++++++--- + 1 file changed, 25 insertions(+), 3 deletions(-) + +--- a/drivers/usb/typec/tcpm/tcpm.c ++++ b/drivers/usb/typec/tcpm/tcpm.c +@@ -3321,13 +3321,31 @@ static void run_state_machine(struct tcp + tcpm_set_state(port, SNK_HARD_RESET_SINK_OFF, 0); + break; + case SRC_HARD_RESET_VBUS_OFF: +- tcpm_set_vconn(port, true); ++ /* ++ * 7.1.5 Response to Hard Resets ++ * Hard Reset Signaling indicates a communication failure has occurred and the ++ * Source Shall stop driving VCONN, Shall remove Rp from the VCONN pin and Shall ++ * drive VBUS to vSafe0V as shown in Figure 7-9. ++ */ ++ tcpm_set_vconn(port, false); + tcpm_set_vbus(port, false); + tcpm_set_roles(port, port->self_powered, TYPEC_SOURCE, + tcpm_data_role_for_source(port)); +- tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER); ++ /* ++ * If tcpc fails to notify vbus off, TCPM will wait for PD_T_SAFE_0V + ++ * PD_T_SRC_RECOVER before turning vbus back on. ++ * From Table 7-12 Sequence Description for a Source Initiated Hard Reset: ++ * 4. Policy Engine waits tPSHardReset after sending Hard Reset Signaling and then ++ * tells the Device Policy Manager to instruct the power supply to perform a ++ * Hard Reset. The transition to vSafe0V Shall occur within tSafe0V (t2). ++ * 5. After tSrcRecover the Source applies power to VBUS in an attempt to ++ * re-establish communication with the Sink and resume USB Default Operation. ++ * The transition to vSafe5V Shall occur within tSrcTurnOn(t4). ++ */ ++ tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SAFE_0V + PD_T_SRC_RECOVER); + break; + case SRC_HARD_RESET_VBUS_ON: ++ tcpm_set_vconn(port, true); + tcpm_set_vbus(port, true); + port->tcpc->set_pd_rx(port->tcpc, true); + tcpm_set_attached_state(port, true); +@@ -3887,7 +3905,11 @@ static void _tcpm_pd_vbus_off(struct tcp + tcpm_set_state(port, SNK_HARD_RESET_WAIT_VBUS, 0); + break; + case SRC_HARD_RESET_VBUS_OFF: +- tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, 0); ++ /* ++ * After establishing the vSafe0V voltage condition on VBUS, the Source Shall wait ++ * tSrcRecover before re-applying VCONN and restoring VBUS to vSafe5V. ++ */ ++ tcpm_set_state(port, SRC_HARD_RESET_VBUS_ON, PD_T_SRC_RECOVER); + break; + case HARD_RESET_SEND: + break; diff --git a/queue-5.8/usb-typec-ucsi-fix-2-unlocked-ucsi_run_command-calls.patch b/queue-5.8/usb-typec-ucsi-fix-2-unlocked-ucsi_run_command-calls.patch new file mode 100644 index 00000000000..da61adcb113 --- /dev/null +++ b/queue-5.8/usb-typec-ucsi-fix-2-unlocked-ucsi_run_command-calls.patch @@ -0,0 +1,65 @@ +From 7e90057f125c8c852940b848e06e7a72f050fc6f Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 9 Aug 2020 16:19:02 +0200 +Subject: usb: typec: ucsi: Fix 2 unlocked ucsi_run_command calls + +From: Hans de Goede + +commit 7e90057f125c8c852940b848e06e7a72f050fc6f upstream. + +Fix 2 unlocked ucsi_run_command calls: + +1. ucsi_handle_connector_change() contains one ucsi_send_command() call, +which takes the ppm_lock for it; and one ucsi_run_command() call which +relies on the caller have taking the ppm_lock. +ucsi_handle_connector_change() does not take the lock, so the +second (ucsi_run_command) calls should also be ucsi_send_command(). + +2. ucsi_get_pdos() gets called from ucsi_handle_connector_change() which +does not hold the ppm_lock, so it also must use ucsi_send_command(). + +This commit also adds a WARN_ON(!mutex_is_locked(&ucsi->ppm_lock)); to +ucsi_run_command() to avoid similar problems getting re-introduced in +the future. + +Cc: stable@vger.kernel.org +Signed-off-by: Hans de Goede +Acked-by: Heikki Krogerus +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20200809141904.4317-3-hdegoede@redhat.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/typec/ucsi/ucsi.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -152,6 +152,8 @@ static int ucsi_run_command(struct ucsi + u8 length; + int ret; + ++ WARN_ON(!mutex_is_locked(&ucsi->ppm_lock)); ++ + ret = ucsi_exec_command(ucsi, command); + if (ret < 0) + return ret; +@@ -502,7 +504,7 @@ static void ucsi_get_pdos(struct ucsi_co + command |= UCSI_GET_PDOS_PARTNER_PDO(is_partner); + command |= UCSI_GET_PDOS_NUM_PDOS(UCSI_MAX_PDOS - 1); + command |= UCSI_GET_PDOS_SRC_PDOS; +- ret = ucsi_run_command(ucsi, command, con->src_pdos, ++ ret = ucsi_send_command(ucsi, command, con->src_pdos, + sizeof(con->src_pdos)); + if (ret < 0) { + dev_err(ucsi->dev, "UCSI_GET_PDOS failed (%d)\n", ret); +@@ -681,7 +683,7 @@ static void ucsi_handle_connector_change + */ + command = UCSI_GET_CAM_SUPPORTED; + command |= UCSI_CONNECTOR_NUMBER(con->num); +- ucsi_run_command(con->ucsi, command, NULL, 0); ++ ucsi_send_command(con->ucsi, command, NULL, 0); + } + + if (con->status.change & UCSI_CONSTAT_PARTNER_CHANGE) diff --git a/queue-5.8/usb-typec-ucsi-fix-ab-ba-lock-inversion.patch b/queue-5.8/usb-typec-ucsi-fix-ab-ba-lock-inversion.patch new file mode 100644 index 00000000000..992b8a4e551 --- /dev/null +++ b/queue-5.8/usb-typec-ucsi-fix-ab-ba-lock-inversion.patch @@ -0,0 +1,132 @@ +From 0ff0705a2ef2929e9326c95df48bdbebb0dafaad Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 9 Aug 2020 16:19:01 +0200 +Subject: usb: typec: ucsi: Fix AB BA lock inversion + +From: Hans de Goede + +commit 0ff0705a2ef2929e9326c95df48bdbebb0dafaad upstream. + +Lockdep reports an AB BA lock inversion between ucsi_init() and +ucsi_handle_connector_change(): + +AB order: + +1. ucsi_init takes ucsi->ppm_lock (it runs with that locked for the + duration of the function) +2. usci_init eventually end up calling ucsi_register_displayport, + which takes ucsi_connector->lock + +BA order: + +1. ucsi_handle_connector_change work is started, takes ucsi_connector->lock +2. ucsi_handle_connector_change calls ucsi_send_command which takes + ucsi->ppm_lock + +The ppm_lock really only needs to be hold during 2 functions: +ucsi_reset_ppm() and ucsi_run_command(). + +This commit fixes the AB BA lock inversion by making ucsi_init drop the +ucsi->ppm_lock before it starts registering ports; and replacing any +ucsi_run_command() calls after this point with ucsi_send_command() +(which is a wrapper around run_command taking the lock while handling +the command). + +Some of the replacing of ucsi_run_command with ucsi_send_command +in the helpers used during port registration also fixes a number of +code paths after registration which call ucsi_run_command() without +holding the ppm_lock: +1. ucsi_altmode_update_active() call in ucsi/displayport.c +2. ucsi_register_altmodes() call from ucsi_handle_connector_change() + (through ucsi_partner_change()) + +Cc: stable@vger.kernel.org +Signed-off-by: Hans de Goede +Acked-by: Heikki Krogerus +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20200809141904.4317-2-hdegoede@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/typec/ucsi/ucsi.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -205,7 +205,7 @@ void ucsi_altmode_update_active(struct u + int i; + + command = UCSI_GET_CURRENT_CAM | UCSI_CONNECTOR_NUMBER(con->num); +- ret = ucsi_run_command(con->ucsi, command, &cur, sizeof(cur)); ++ ret = ucsi_send_command(con->ucsi, command, &cur, sizeof(cur)); + if (ret < 0) { + if (con->ucsi->version > 0x0100) { + dev_err(con->ucsi->dev, +@@ -354,7 +354,7 @@ ucsi_register_altmodes_nvidia(struct ucs + command |= UCSI_GET_ALTMODE_RECIPIENT(recipient); + command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num); + command |= UCSI_GET_ALTMODE_OFFSET(i); +- len = ucsi_run_command(con->ucsi, command, &alt, sizeof(alt)); ++ len = ucsi_send_command(con->ucsi, command, &alt, sizeof(alt)); + /* + * We are collecting all altmodes first and then registering. + * Some type-C device will return zero length data beyond last +@@ -431,7 +431,7 @@ static int ucsi_register_altmodes(struct + command |= UCSI_GET_ALTMODE_RECIPIENT(recipient); + command |= UCSI_GET_ALTMODE_CONNECTOR_NUMBER(con->num); + command |= UCSI_GET_ALTMODE_OFFSET(i); +- len = ucsi_run_command(con->ucsi, command, alt, sizeof(alt)); ++ len = ucsi_send_command(con->ucsi, command, alt, sizeof(alt)); + if (len <= 0) + return len; + +@@ -904,7 +904,7 @@ static int ucsi_register_port(struct ucs + /* Get connector capability */ + command = UCSI_GET_CONNECTOR_CAPABILITY; + command |= UCSI_CONNECTOR_NUMBER(con->num); +- ret = ucsi_run_command(ucsi, command, &con->cap, sizeof(con->cap)); ++ ret = ucsi_send_command(ucsi, command, &con->cap, sizeof(con->cap)); + if (ret < 0) + return ret; + +@@ -953,8 +953,7 @@ static int ucsi_register_port(struct ucs + + /* Get the status */ + command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); +- ret = ucsi_run_command(ucsi, command, &con->status, +- sizeof(con->status)); ++ ret = ucsi_send_command(ucsi, command, &con->status, sizeof(con->status)); + if (ret < 0) { + dev_err(ucsi->dev, "con%d: failed to get status\n", con->num); + return 0; +@@ -1044,6 +1043,8 @@ int ucsi_init(struct ucsi *ucsi) + goto err_reset; + } + ++ mutex_unlock(&ucsi->ppm_lock); ++ + /* Register all connectors */ + for (i = 0; i < ucsi->cap.num_connectors; i++) { + ret = ucsi_register_port(ucsi, i); +@@ -1054,12 +1055,10 @@ int ucsi_init(struct ucsi *ucsi) + /* Enable all notifications */ + ucsi->ntfy = UCSI_ENABLE_NTFY_ALL; + command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; +- ret = ucsi_run_command(ucsi, command, NULL, 0); ++ ret = ucsi_send_command(ucsi, command, NULL, 0); + if (ret < 0) + goto err_unregister; + +- mutex_unlock(&ucsi->ppm_lock); +- + return 0; + + err_unregister: +@@ -1071,6 +1070,7 @@ err_unregister: + con->port = NULL; + } + ++ mutex_lock(&ucsi->ppm_lock); + err_reset: + ucsi_reset_ppm(ucsi); + err: diff --git a/queue-5.8/usb-typec-ucsi-hold-con-lock-for-the-entire-duration-of-ucsi_register_port.patch b/queue-5.8/usb-typec-ucsi-hold-con-lock-for-the-entire-duration-of-ucsi_register_port.patch new file mode 100644 index 00000000000..d779d85b4da --- /dev/null +++ b/queue-5.8/usb-typec-ucsi-hold-con-lock-for-the-entire-duration-of-ucsi_register_port.patch @@ -0,0 +1,149 @@ +From bed97b30968ba354035a020989df0623e52b5536 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 9 Aug 2020 16:19:04 +0200 +Subject: usb: typec: ucsi: Hold con->lock for the entire duration of ucsi_register_port() + +From: Hans de Goede + +commit bed97b30968ba354035a020989df0623e52b5536 upstream. + +Commit 081da1325d35 ("usb: typec: ucsi: displayport: Fix a potential race +during registration") made the ucsi code hold con->lock in +ucsi_register_displayport(). But we really don't want any interactions +with the connector to run before the port-registration process is fully +complete. + +This commit moves the taking of con->lock from ucsi_register_displayport() +into ucsi_register_port() to achieve this. + +Cc: stable@vger.kernel.org +Fixes: 081da1325d35 ("usb: typec: ucsi: displayport: Fix a potential race during registration") +Signed-off-by: Hans de Goede +Acked-by: Heikki Krogerus +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20200809141904.4317-5-hdegoede@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/typec/ucsi/displayport.c | 9 +-------- + drivers/usb/typec/ucsi/ucsi.c | 31 ++++++++++++++++++++++--------- + 2 files changed, 23 insertions(+), 17 deletions(-) + +--- a/drivers/usb/typec/ucsi/displayport.c ++++ b/drivers/usb/typec/ucsi/displayport.c +@@ -288,8 +288,6 @@ struct typec_altmode *ucsi_register_disp + struct typec_altmode *alt; + struct ucsi_dp *dp; + +- mutex_lock(&con->lock); +- + /* We can't rely on the firmware with the capabilities. */ + desc->vdo |= DP_CAP_DP_SIGNALING | DP_CAP_RECEPTACLE; + +@@ -298,15 +296,12 @@ struct typec_altmode *ucsi_register_disp + desc->vdo |= all_assignments << 16; + + alt = typec_port_register_altmode(con->port, desc); +- if (IS_ERR(alt)) { +- mutex_unlock(&con->lock); ++ if (IS_ERR(alt)) + return alt; +- } + + dp = devm_kzalloc(&alt->dev, sizeof(*dp), GFP_KERNEL); + if (!dp) { + typec_unregister_altmode(alt); +- mutex_unlock(&con->lock); + return ERR_PTR(-ENOMEM); + } + +@@ -319,7 +314,5 @@ struct typec_altmode *ucsi_register_disp + alt->ops = &ucsi_displayport_ops; + typec_altmode_set_drvdata(alt, dp); + +- mutex_unlock(&con->lock); +- + return alt; + } +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -898,12 +898,15 @@ static int ucsi_register_port(struct ucs + con->num = index + 1; + con->ucsi = ucsi; + ++ /* Delay other interactions with the con until registration is complete */ ++ mutex_lock(&con->lock); ++ + /* Get connector capability */ + command = UCSI_GET_CONNECTOR_CAPABILITY; + command |= UCSI_CONNECTOR_NUMBER(con->num); + ret = ucsi_send_command(ucsi, command, &con->cap, sizeof(con->cap)); + if (ret < 0) +- return ret; ++ goto out; + + if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP) + cap->data = TYPEC_PORT_DRD; +@@ -935,26 +938,32 @@ static int ucsi_register_port(struct ucs + + ret = ucsi_register_port_psy(con); + if (ret) +- return ret; ++ goto out; + + /* Register the connector */ + con->port = typec_register_port(ucsi->dev, cap); +- if (IS_ERR(con->port)) +- return PTR_ERR(con->port); ++ if (IS_ERR(con->port)) { ++ ret = PTR_ERR(con->port); ++ goto out; ++ } + + /* Alternate modes */ + ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_CON); +- if (ret) ++ if (ret) { + dev_err(ucsi->dev, "con%d: failed to register alt modes\n", + con->num); ++ goto out; ++ } + + /* Get the status */ + command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num); + ret = ucsi_send_command(ucsi, command, &con->status, sizeof(con->status)); + if (ret < 0) { + dev_err(ucsi->dev, "con%d: failed to get status\n", con->num); +- return 0; ++ ret = 0; ++ goto out; + } ++ ret = 0; /* ucsi_send_command() returns length on success */ + + switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) { + case UCSI_CONSTAT_PARTNER_TYPE_UFP: +@@ -979,17 +988,21 @@ static int ucsi_register_port(struct ucs + + if (con->partner) { + ret = ucsi_register_altmodes(con, UCSI_RECIPIENT_SOP); +- if (ret) ++ if (ret) { + dev_err(ucsi->dev, + "con%d: failed to register alternate modes\n", + con->num); +- else ++ ret = 0; ++ } else { + ucsi_altmode_update_active(con); ++ } + } + + trace_ucsi_register_port(con->num, &con->status); + +- return 0; ++out: ++ mutex_unlock(&con->lock); ++ return ret; + } + + /** diff --git a/queue-5.8/usb-typec-ucsi-rework-ppm_lock-handling.patch b/queue-5.8/usb-typec-ucsi-rework-ppm_lock-handling.patch new file mode 100644 index 00000000000..ec1289e9116 --- /dev/null +++ b/queue-5.8/usb-typec-ucsi-rework-ppm_lock-handling.patch @@ -0,0 +1,188 @@ +From 25794e3079d2a98547b6bf5764ef0240aa89b798 Mon Sep 17 00:00:00 2001 +From: Hans de Goede +Date: Sun, 9 Aug 2020 16:19:03 +0200 +Subject: usb: typec: ucsi: Rework ppm_lock handling + +From: Hans de Goede + +commit 25794e3079d2a98547b6bf5764ef0240aa89b798 upstream. + +The ppm_lock really only needs to be hold during 2 functions: +ucsi_reset_ppm() and ucsi_run_command(). + +Push the taking of the lock down into these 2 functions, renaming +ucsi_run_command() to ucsi_send_command() which was an existing +wrapper already taking the lock for its callers. + +This simplifies things for the callers and removes the difference +between ucsi_send_command() and ucsi_run_command() which has led +to various locking bugs in the past. + +Cc: stable@vger.kernel.org +Signed-off-by: Hans de Goede +Acked-by: Heikki Krogerus +Reviewed-by: Guenter Roeck +Link: https://lore.kernel.org/r/20200809141904.4317-4-hdegoede@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/typec/ucsi/ucsi.c | 56 ++++++++++++++++-------------------------- + 1 file changed, 22 insertions(+), 34 deletions(-) + +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -146,42 +146,33 @@ static int ucsi_exec_command(struct ucsi + return UCSI_CCI_LENGTH(cci); + } + +-static int ucsi_run_command(struct ucsi *ucsi, u64 command, +- void *data, size_t size) ++int ucsi_send_command(struct ucsi *ucsi, u64 command, ++ void *data, size_t size) + { + u8 length; + int ret; + +- WARN_ON(!mutex_is_locked(&ucsi->ppm_lock)); ++ mutex_lock(&ucsi->ppm_lock); + + ret = ucsi_exec_command(ucsi, command); + if (ret < 0) +- return ret; ++ goto out; + + length = ret; + + if (data) { + ret = ucsi->ops->read(ucsi, UCSI_MESSAGE_IN, data, size); + if (ret) +- return ret; ++ goto out; + } + + ret = ucsi_acknowledge_command(ucsi); + if (ret) +- return ret; +- +- return length; +-} ++ goto out; + +-int ucsi_send_command(struct ucsi *ucsi, u64 command, +- void *retval, size_t size) +-{ +- int ret; +- +- mutex_lock(&ucsi->ppm_lock); +- ret = ucsi_run_command(ucsi, command, retval, size); ++ ret = length; ++out: + mutex_unlock(&ucsi->ppm_lock); +- + return ret; + } + EXPORT_SYMBOL_GPL(ucsi_send_command); +@@ -738,20 +729,24 @@ static int ucsi_reset_ppm(struct ucsi *u + u32 cci; + int ret; + ++ mutex_lock(&ucsi->ppm_lock); ++ + ret = ucsi->ops->async_write(ucsi, UCSI_CONTROL, &command, + sizeof(command)); + if (ret < 0) +- return ret; ++ goto out; + + tmo = jiffies + msecs_to_jiffies(UCSI_TIMEOUT_MS); + + do { +- if (time_is_before_jiffies(tmo)) +- return -ETIMEDOUT; ++ if (time_is_before_jiffies(tmo)) { ++ ret = -ETIMEDOUT; ++ goto out; ++ } + + ret = ucsi->ops->read(ucsi, UCSI_CCI, &cci, sizeof(cci)); + if (ret) +- return ret; ++ goto out; + + /* If the PPM is still doing something else, reset it again. */ + if (cci & ~UCSI_CCI_RESET_COMPLETE) { +@@ -759,13 +754,15 @@ static int ucsi_reset_ppm(struct ucsi *u + &command, + sizeof(command)); + if (ret < 0) +- return ret; ++ goto out; + } + + msleep(20); + } while (!(cci & UCSI_CCI_RESET_COMPLETE)); + +- return 0; ++out: ++ mutex_unlock(&ucsi->ppm_lock); ++ return ret; + } + + static int ucsi_role_cmd(struct ucsi_connector *con, u64 command) +@@ -777,9 +774,7 @@ static int ucsi_role_cmd(struct ucsi_con + u64 c; + + /* PPM most likely stopped responding. Resetting everything. */ +- mutex_lock(&con->ucsi->ppm_lock); + ucsi_reset_ppm(con->ucsi); +- mutex_unlock(&con->ucsi->ppm_lock); + + c = UCSI_SET_NOTIFICATION_ENABLE | con->ucsi->ntfy; + ucsi_send_command(con->ucsi, c, NULL, 0); +@@ -1010,8 +1005,6 @@ int ucsi_init(struct ucsi *ucsi) + int ret; + int i; + +- mutex_lock(&ucsi->ppm_lock); +- + /* Reset the PPM */ + ret = ucsi_reset_ppm(ucsi); + if (ret) { +@@ -1022,13 +1015,13 @@ int ucsi_init(struct ucsi *ucsi) + /* Enable basic notifications */ + ucsi->ntfy = UCSI_ENABLE_NTFY_CMD_COMPLETE | UCSI_ENABLE_NTFY_ERROR; + command = UCSI_SET_NOTIFICATION_ENABLE | ucsi->ntfy; +- ret = ucsi_run_command(ucsi, command, NULL, 0); ++ ret = ucsi_send_command(ucsi, command, NULL, 0); + if (ret < 0) + goto err_reset; + + /* Get PPM capabilities */ + command = UCSI_GET_CAPABILITY; +- ret = ucsi_run_command(ucsi, command, &ucsi->cap, sizeof(ucsi->cap)); ++ ret = ucsi_send_command(ucsi, command, &ucsi->cap, sizeof(ucsi->cap)); + if (ret < 0) + goto err_reset; + +@@ -1045,8 +1038,6 @@ int ucsi_init(struct ucsi *ucsi) + goto err_reset; + } + +- mutex_unlock(&ucsi->ppm_lock); +- + /* Register all connectors */ + for (i = 0; i < ucsi->cap.num_connectors; i++) { + ret = ucsi_register_port(ucsi, i); +@@ -1072,12 +1063,9 @@ err_unregister: + con->port = NULL; + } + +- mutex_lock(&ucsi->ppm_lock); + err_reset: + ucsi_reset_ppm(ucsi); + err: +- mutex_unlock(&ucsi->ppm_lock); +- + return ret; + } + EXPORT_SYMBOL_GPL(ucsi_init); diff --git a/queue-5.8/usb-uas-add-quirk-for-pny-pro-elite.patch b/queue-5.8/usb-uas-add-quirk-for-pny-pro-elite.patch new file mode 100644 index 00000000000..4e87b377b15 --- /dev/null +++ b/queue-5.8/usb-uas-add-quirk-for-pny-pro-elite.patch @@ -0,0 +1,39 @@ +From 9a469bc9f32dd33c7aac5744669d21a023a719cd Mon Sep 17 00:00:00 2001 +From: Thinh Nguyen +Date: Tue, 18 Aug 2020 19:27:47 -0700 +Subject: usb: uas: Add quirk for PNY Pro Elite + +From: Thinh Nguyen + +commit 9a469bc9f32dd33c7aac5744669d21a023a719cd upstream. + +PNY Pro Elite USB 3.1 Gen 2 device (SSD) doesn't respond to ATA_12 +pass-through command (i.e. it just hangs). If it doesn't support this +command, it should respond properly to the host. Let's just add a quirk +to be able to move forward with other operations. + +Cc: stable@vger.kernel.org +Signed-off-by: Thinh Nguyen +Link: https://lore.kernel.org/r/2b0585228b003eedcc82db84697b31477df152e0.1597803605.git.thinhn@synopsys.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/storage/unusual_uas.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/drivers/usb/storage/unusual_uas.h ++++ b/drivers/usb/storage/unusual_uas.h +@@ -80,6 +80,13 @@ UNUSUAL_DEV(0x152d, 0x0578, 0x0000, 0x99 + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_BROKEN_FUA), + ++/* Reported-by: Thinh Nguyen */ ++UNUSUAL_DEV(0x154b, 0xf00d, 0x0000, 0x9999, ++ "PNY", ++ "Pro Elite SSD", ++ USB_SC_DEVICE, USB_PR_DEVICE, NULL, ++ US_FL_NO_ATA_1X), ++ + /* Reported-by: Hans de Goede */ + UNUSUAL_DEV(0x2109, 0x0711, 0x0000, 0x9999, + "VIA", diff --git a/queue-5.8/usb-yurex-fix-bad-gfp-argument.patch b/queue-5.8/usb-yurex-fix-bad-gfp-argument.patch new file mode 100644 index 00000000000..86f97f5e81f --- /dev/null +++ b/queue-5.8/usb-yurex-fix-bad-gfp-argument.patch @@ -0,0 +1,72 @@ +From f176ede3a3bde5b398a6777a7f9ff091baa2d3ff Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Mon, 10 Aug 2020 14:29:54 -0400 +Subject: USB: yurex: Fix bad gfp argument + +From: Alan Stern + +commit f176ede3a3bde5b398a6777a7f9ff091baa2d3ff upstream. + +The syzbot fuzzer identified a bug in the yurex driver: It passes +GFP_KERNEL as a memory-allocation flag to usb_submit_urb() at a time +when its state is TASK_INTERRUPTIBLE, not TASK_RUNNING: + +do not call blocking ops when !TASK_RUNNING; state=1 set at [<00000000370c7c68>] prepare_to_wait+0xb1/0x2a0 kernel/sched/wait.c:247 +WARNING: CPU: 1 PID: 340 at kernel/sched/core.c:7253 __might_sleep+0x135/0x190 +kernel/sched/core.c:7253 +Kernel panic - not syncing: panic_on_warn set ... +CPU: 1 PID: 340 Comm: syz-executor677 Not tainted 5.8.0-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google +01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0xf6/0x16e lib/dump_stack.c:118 + panic+0x2aa/0x6e1 kernel/panic.c:231 + __warn.cold+0x20/0x50 kernel/panic.c:600 + report_bug+0x1bd/0x210 lib/bug.c:198 + handle_bug+0x41/0x80 arch/x86/kernel/traps.c:234 + exc_invalid_op+0x14/0x40 arch/x86/kernel/traps.c:254 + asm_exc_invalid_op+0x12/0x20 arch/x86/include/asm/idtentry.h:536 +RIP: 0010:__might_sleep+0x135/0x190 kernel/sched/core.c:7253 +Code: 65 48 8b 1c 25 40 ef 01 00 48 8d 7b 10 48 89 fe 48 c1 ee 03 80 3c 06 00 75 +2b 48 8b 73 10 48 c7 c7 e0 9e 06 86 e8 ed 12 f6 ff <0f> 0b e9 46 ff ff ff e8 1f +b2 4b 00 e9 29 ff ff ff e8 15 b2 4b 00 +RSP: 0018:ffff8881cdb77a28 EFLAGS: 00010282 +RAX: 0000000000000000 RBX: ffff8881c6458000 RCX: 0000000000000000 +RDX: ffff8881c6458000 RSI: ffffffff8129ec93 RDI: ffffed1039b6ef37 +RBP: ffffffff86fdade2 R08: 0000000000000001 R09: ffff8881db32f54f +R10: 0000000000000000 R11: 0000000030343354 R12: 00000000000001f2 +R13: 0000000000000000 R14: 0000000000000068 R15: ffffffff83c1b1aa + slab_pre_alloc_hook.constprop.0+0xea/0x200 mm/slab.h:498 + slab_alloc_node mm/slub.c:2816 [inline] + slab_alloc mm/slub.c:2900 [inline] + kmem_cache_alloc_trace+0x46/0x220 mm/slub.c:2917 + kmalloc include/linux/slab.h:554 [inline] + dummy_urb_enqueue+0x7a/0x880 drivers/usb/gadget/udc/dummy_hcd.c:1251 + usb_hcd_submit_urb+0x2b2/0x22d0 drivers/usb/core/hcd.c:1547 + usb_submit_urb+0xb4e/0x13e0 drivers/usb/core/urb.c:570 + yurex_write+0x3ea/0x820 drivers/usb/misc/yurex.c:495 + +This patch changes the call to use GFP_ATOMIC instead of GFP_KERNEL. + +Reported-and-tested-by: syzbot+c2c3302f9c601a4b1be2@syzkaller.appspotmail.com +Signed-off-by: Alan Stern +CC: +Link: https://lore.kernel.org/r/20200810182954.GB307778@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/misc/yurex.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/misc/yurex.c ++++ b/drivers/usb/misc/yurex.c +@@ -492,7 +492,7 @@ static ssize_t yurex_write(struct file * + prepare_to_wait(&dev->waitq, &wait, TASK_INTERRUPTIBLE); + dev_dbg(&dev->interface->dev, "%s - submit %c\n", __func__, + dev->cntl_buffer[0]); +- retval = usb_submit_urb(dev->cntl_urb, GFP_KERNEL); ++ retval = usb_submit_urb(dev->cntl_urb, GFP_ATOMIC); + if (retval >= 0) + timeout = schedule_timeout(YUREX_WRITE_TIMEOUT); + finish_wait(&dev->waitq, &wait);