Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'usb-6.8-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB driver fixes from Greg KH:
"Here are a bunch of small USB driver fixes for 6.8-rc3. Included in
here are:

- new usb-serial driver ids

- new dwc3 driver id added

- typec driver change revert

- ncm gadget driver endian bugfix

- xhci bugfixes for a number of reported issues

- usb hub bugfix for alternate settings

- ulpi driver debugfs memory leak fix

- chipidea driver bugfix

- usb gadget driver fixes

All of these have been in linux-next for a while with no reported
issues"

* tag 'usb-6.8-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (24 commits)
USB: serial: option: add Fibocom FM101-GL variant
USB: serial: qcserial: add new usb-id for Dell Wireless DW5826e
USB: serial: cp210x: add ID for IMST iM871A-USB
usb: typec: tcpm: fix the PD disabled case
usb: ucsi_acpi: Quirk to ack a connector change ack cmd
usb: ucsi_acpi: Fix command completion handling
usb: ucsi: Add missing ppm_lock
usb: ulpi: Fix debugfs directory leak
Revert "usb: typec: tcpm: fix cc role at port reset"
usb: gadget: pch_udc: fix an Excess kernel-doc warning
usb: f_mass_storage: forbid async queue when shutdown happen
USB: hub: check for alternate port before enabling A_ALT_HNP_SUPPORT
usb: chipidea: core: handle power lost in workqueue
usb: dwc3: gadget: Fix NULL pointer dereference in dwc3_gadget_suspend
usb: dwc3: pci: add support for the Intel Arrow Lake-H
usb: core: Prevent null pointer dereference in update_port_device_state
xhci: handle isoc Babble and Buffer Overrun events properly
xhci: process isoc TD properly when there was a transaction error mid TD.
xhci: fix off by one check when adding a secondary interrupter.
xhci: fix possible null pointer dereference at secondary interrupter removal
...

+268 -91
+11 -11
Documentation/usb/gadget-testing.rst
··· 448 448 The function name to use when creating the function directory is "ncm". 449 449 The NCM function provides these attributes in its function directory: 450 450 451 - =============== ================================================== 452 - ifname network device interface name associated with this 453 - function instance 454 - qmult queue length multiplier for high and super speed 455 - host_addr MAC address of host's end of this 456 - Ethernet over USB link 457 - dev_addr MAC address of device's end of this 458 - Ethernet over USB link 459 - max_segment_size Segment size required for P2P connections. This 460 - will set MTU to (max_segment_size - 14 bytes) 461 - =============== ================================================== 451 + ======================= ================================================== 452 + ifname network device interface name associated with this 453 + function instance 454 + qmult queue length multiplier for high and super speed 455 + host_addr MAC address of host's end of this 456 + Ethernet over USB link 457 + dev_addr MAC address of device's end of this 458 + Ethernet over USB link 459 + max_segment_size Segment size required for P2P connections. This 460 + will set MTU to 14 bytes 461 + ======================= ================================================== 462 462 463 463 and after creating the functions/ncm.<instance name> they contain default 464 464 values: qmult is 5, dev_addr and host_addr are randomly selected.
+2
drivers/usb/chipidea/ci.h
··· 176 176 * @enabled_otg_timer_bits: bits of enabled otg timers 177 177 * @next_otg_timer: next nearest enabled timer to be expired 178 178 * @work: work for role changing 179 + * @power_lost_work: work for power lost handling 179 180 * @wq: workqueue thread 180 181 * @qh_pool: allocation pool for queue heads 181 182 * @td_pool: allocation pool for transfer descriptors ··· 227 226 enum otg_fsm_timer next_otg_timer; 228 227 struct usb_role_switch *role_switch; 229 228 struct work_struct work; 229 + struct work_struct power_lost_work; 230 230 struct workqueue_struct *wq; 231 231 232 232 struct dma_pool *qh_pool;
+24 -20
drivers/usb/chipidea/core.c
··· 856 856 return 0; 857 857 } 858 858 859 + static void ci_power_lost_work(struct work_struct *work) 860 + { 861 + struct ci_hdrc *ci = container_of(work, struct ci_hdrc, power_lost_work); 862 + enum ci_role role; 863 + 864 + disable_irq_nosync(ci->irq); 865 + pm_runtime_get_sync(ci->dev); 866 + if (!ci_otg_is_fsm_mode(ci)) { 867 + role = ci_get_role(ci); 868 + 869 + if (ci->role != role) { 870 + ci_handle_id_switch(ci); 871 + } else if (role == CI_ROLE_GADGET) { 872 + if (ci->is_otg && hw_read_otgsc(ci, OTGSC_BSV)) 873 + usb_gadget_vbus_connect(&ci->gadget); 874 + } 875 + } 876 + pm_runtime_put_sync(ci->dev); 877 + enable_irq(ci->irq); 878 + } 879 + 859 880 static DEFINE_IDA(ci_ida); 860 881 861 882 struct platform_device *ci_hdrc_add_device(struct device *dev, ··· 1066 1045 1067 1046 spin_lock_init(&ci->lock); 1068 1047 mutex_init(&ci->mutex); 1048 + INIT_WORK(&ci->power_lost_work, ci_power_lost_work); 1049 + 1069 1050 ci->dev = dev; 1070 1051 ci->platdata = dev_get_platdata(dev); 1071 1052 ci->imx28_write_fix = !!(ci->platdata->flags & ··· 1419 1396 return 0; 1420 1397 } 1421 1398 1422 - static void ci_handle_power_lost(struct ci_hdrc *ci) 1423 - { 1424 - enum ci_role role; 1425 - 1426 - disable_irq_nosync(ci->irq); 1427 - if (!ci_otg_is_fsm_mode(ci)) { 1428 - role = ci_get_role(ci); 1429 - 1430 - if (ci->role != role) { 1431 - ci_handle_id_switch(ci); 1432 - } else if (role == CI_ROLE_GADGET) { 1433 - if (ci->is_otg && hw_read_otgsc(ci, OTGSC_BSV)) 1434 - usb_gadget_vbus_connect(&ci->gadget); 1435 - } 1436 - } 1437 - 1438 - enable_irq(ci->irq); 1439 - } 1440 - 1441 1399 static int ci_resume(struct device *dev) 1442 1400 { 1443 1401 struct ci_hdrc *ci = dev_get_drvdata(dev); ··· 1450 1446 ci_role(ci)->resume(ci, power_lost); 1451 1447 1452 1448 if (power_lost) 1453 - ci_handle_power_lost(ci); 1449 + queue_work(system_freezable_wq, &ci->power_lost_work); 1454 1450 1455 1451 if (ci->supports_runtime_pm) { 1456 1452 pm_runtime_disable(dev);
+1 -1
drivers/usb/common/ulpi.c
··· 301 301 return ret; 302 302 } 303 303 304 - root = debugfs_create_dir(dev_name(dev), ulpi_root); 304 + root = debugfs_create_dir(dev_name(&ulpi->dev), ulpi_root); 305 305 debugfs_create_file("regs", 0444, root, ulpi, &ulpi_regs_fops); 306 306 307 307 dev_dbg(&ulpi->dev, "registered ULPI PHY: vendor %04x, product %04x\n",
+32 -14
drivers/usb/core/hub.c
··· 2053 2053 2054 2054 if (udev->parent) { 2055 2055 hub = usb_hub_to_struct_hub(udev->parent); 2056 - port_dev = hub->ports[udev->portnum - 1]; 2057 - WRITE_ONCE(port_dev->state, udev->state); 2058 - sysfs_notify_dirent(port_dev->state_kn); 2056 + 2057 + /* 2058 + * The Link Layer Validation System Driver (lvstest) 2059 + * has a test step to unbind the hub before running the 2060 + * rest of the procedure. This triggers hub_disconnect 2061 + * which will set the hub's maxchild to 0, further 2062 + * resulting in usb_hub_to_struct_hub returning NULL. 2063 + */ 2064 + if (hub) { 2065 + port_dev = hub->ports[udev->portnum - 1]; 2066 + WRITE_ONCE(port_dev->state, udev->state); 2067 + sysfs_notify_dirent(port_dev->state_kn); 2068 + } 2059 2069 } 2060 2070 } 2061 2071 ··· 2398 2388 } 2399 2389 } else if (desc->bLength == sizeof 2400 2390 (struct usb_otg_descriptor)) { 2401 - /* Set a_alt_hnp_support for legacy otg device */ 2402 - err = usb_control_msg(udev, 2403 - usb_sndctrlpipe(udev, 0), 2404 - USB_REQ_SET_FEATURE, 0, 2405 - USB_DEVICE_A_ALT_HNP_SUPPORT, 2406 - 0, NULL, 0, 2407 - USB_CTRL_SET_TIMEOUT); 2408 - if (err < 0) 2409 - dev_err(&udev->dev, 2410 - "set a_alt_hnp_support failed: %d\n", 2411 - err); 2391 + /* 2392 + * We are operating on a legacy OTP device 2393 + * These should be told that they are operating 2394 + * on the wrong port if we have another port that does 2395 + * support HNP 2396 + */ 2397 + if (bus->otg_port != 0) { 2398 + /* Set a_alt_hnp_support for legacy otg device */ 2399 + err = usb_control_msg(udev, 2400 + usb_sndctrlpipe(udev, 0), 2401 + USB_REQ_SET_FEATURE, 0, 2402 + USB_DEVICE_A_ALT_HNP_SUPPORT, 2403 + 0, NULL, 0, 2404 + USB_CTRL_SET_TIMEOUT); 2405 + if (err < 0) 2406 + dev_err(&udev->dev, 2407 + "set a_alt_hnp_support failed: %d\n", 2408 + err); 2409 + } 2412 2410 } 2413 2411 } 2414 2412 #endif
+4
drivers/usb/dwc3/dwc3-pci.c
··· 51 51 #define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 52 52 #define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f 53 53 #define PCI_DEVICE_ID_INTEL_MTL 0x7e7e 54 + #define PCI_DEVICE_ID_INTEL_ARLH 0x7ec1 55 + #define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e 54 56 #define PCI_DEVICE_ID_INTEL_TGL 0x9a15 55 57 #define PCI_DEVICE_ID_AMD_MR 0x163a 56 58 ··· 423 421 { PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) }, 424 422 { PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) }, 425 423 { PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) }, 424 + { PCI_DEVICE_DATA(INTEL, ARLH, &dwc3_pci_intel_swnode) }, 425 + { PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) }, 426 426 { PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) }, 427 427 428 428 { PCI_DEVICE_DATA(AMD, NL_USB, &dwc3_pci_amd_swnode) },
+2 -4
drivers/usb/dwc3/gadget.c
··· 4709 4709 unsigned long flags; 4710 4710 int ret; 4711 4711 4712 - if (!dwc->gadget_driver) 4713 - return 0; 4714 - 4715 4712 ret = dwc3_gadget_soft_disconnect(dwc); 4716 4713 if (ret) 4717 4714 goto err; 4718 4715 4719 4716 spin_lock_irqsave(&dwc->lock, flags); 4720 - dwc3_disconnect_gadget(dwc); 4717 + if (dwc->gadget_driver) 4718 + dwc3_disconnect_gadget(dwc); 4721 4719 spin_unlock_irqrestore(&dwc->lock, flags); 4722 4720 4723 4721 return 0;
+3 -1
drivers/usb/dwc3/host.c
··· 61 61 62 62 int dwc3_host_init(struct dwc3 *dwc) 63 63 { 64 - struct property_entry props[4]; 64 + struct property_entry props[5]; 65 65 struct platform_device *xhci; 66 66 int ret, irq; 67 67 int prop_idx = 0; ··· 88 88 } 89 89 90 90 memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props)); 91 + 92 + props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-sg-trb-cache-size-quirk"); 91 93 92 94 if (dwc->usb3_lpm_capable) 93 95 props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb3-lpm-capable");
+18 -2
drivers/usb/gadget/function/f_mass_storage.c
··· 545 545 546 546 static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh) 547 547 { 548 + int rc; 549 + 548 550 if (!fsg_is_set(common)) 549 551 return false; 550 552 bh->state = BUF_STATE_SENDING; 551 - if (start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq)) 553 + rc = start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq); 554 + if (rc) { 552 555 bh->state = BUF_STATE_EMPTY; 556 + if (rc == -ESHUTDOWN) { 557 + common->running = 0; 558 + return false; 559 + } 560 + } 553 561 return true; 554 562 } 555 563 556 564 static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh) 557 565 { 566 + int rc; 567 + 558 568 if (!fsg_is_set(common)) 559 569 return false; 560 570 bh->state = BUF_STATE_RECEIVING; 561 - if (start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq)) 571 + rc = start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq); 572 + if (rc) { 562 573 bh->state = BUF_STATE_FULL; 574 + if (rc == -ESHUTDOWN) { 575 + common->running = 0; 576 + return false; 577 + } 578 + } 563 579 return true; 564 580 } 565 581
+4 -4
drivers/usb/gadget/function/f_ncm.c
··· 105 105 106 106 /* 107 107 * Although max mtu as dictated by u_ether is 15412 bytes, setting 108 - * max_segment_sizeto 15426 would not be efficient. If user chooses segment 109 - * size to be (>= 8192), then we can't aggregate more than one buffer in each 108 + * max_segment_size to 15426 would not be efficient. If user chooses segment 109 + * size to be (>= 8192), then we can't aggregate more than one buffer in each 110 110 * NTB (assuming each packet coming from network layer is >= 8192 bytes) as ep 111 111 * maxpacket limit is 16384. So let max_segment_size be limited to 8000 to allow 112 112 * at least 2 packets to be aggregated reducing wastage of NTB buffer space ··· 1489 1489 ncm_data_intf.bInterfaceNumber = status; 1490 1490 ncm_union_desc.bSlaveInterface0 = status; 1491 1491 1492 - ecm_desc.wMaxSegmentSize = ncm_opts->max_segment_size; 1492 + ecm_desc.wMaxSegmentSize = cpu_to_le16(ncm_opts->max_segment_size); 1493 1493 1494 1494 status = -ENODEV; 1495 1495 ··· 1685 1685 kfree(opts); 1686 1686 return ERR_CAST(net); 1687 1687 } 1688 - opts->max_segment_size = cpu_to_le16(ETH_FRAME_LEN); 1688 + opts->max_segment_size = ETH_FRAME_LEN; 1689 1689 INIT_LIST_HEAD(&opts->ncm_os_desc.ext_prop); 1690 1690 1691 1691 descs[0] = &opts->ncm_os_desc;
-1
drivers/usb/gadget/udc/pch_udc.c
··· 274 274 * @td_data: for data request 275 275 * @dev: reference to device struct 276 276 * @offset_addr: offset address of ep register 277 - * @desc: for this ep 278 277 * @queue: queue for requests 279 278 * @num: endpoint number 280 279 * @in: endpoint is IN
+8 -8
drivers/usb/host/xhci-mem.c
··· 1861 1861 struct xhci_hcd *xhci = hcd_to_xhci(hcd); 1862 1862 unsigned int intr_num; 1863 1863 1864 - /* interrupter 0 is primary interrupter, don't touch it */ 1865 - if (!ir || !ir->intr_num || ir->intr_num >= xhci->max_interrupters) 1866 - xhci_dbg(xhci, "Invalid secondary interrupter, can't remove\n"); 1867 - 1868 - /* fixme, should we check xhci->interrupter[intr_num] == ir */ 1869 - /* fixme locking */ 1870 - 1871 1864 spin_lock_irq(&xhci->lock); 1865 + 1866 + /* interrupter 0 is primary interrupter, don't touch it */ 1867 + if (!ir || !ir->intr_num || ir->intr_num >= xhci->max_interrupters) { 1868 + xhci_dbg(xhci, "Invalid secondary interrupter, can't remove\n"); 1869 + spin_unlock_irq(&xhci->lock); 1870 + return; 1871 + } 1872 1872 1873 1873 intr_num = ir->intr_num; 1874 1874 ··· 2322 2322 u64 erst_base; 2323 2323 u32 erst_size; 2324 2324 2325 - if (intr_num > xhci->max_interrupters) { 2325 + if (intr_num >= xhci->max_interrupters) { 2326 2326 xhci_warn(xhci, "Can't add interrupter %d, max interrupters %d\n", 2327 2327 intr_num, xhci->max_interrupters); 2328 2328 return -EINVAL;
+3
drivers/usb/host/xhci-plat.c
··· 253 253 if (device_property_read_bool(tmpdev, "quirk-broken-port-ped")) 254 254 xhci->quirks |= XHCI_BROKEN_PORT_PED; 255 255 256 + if (device_property_read_bool(tmpdev, "xhci-sg-trb-cache-size-quirk")) 257 + xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK; 258 + 256 259 device_property_read_u32(tmpdev, "imod-interval-ns", 257 260 &xhci->imod_interval); 258 261 }
+65 -15
drivers/usb/host/xhci-ring.c
··· 2376 2376 /* handle completion code */ 2377 2377 switch (trb_comp_code) { 2378 2378 case COMP_SUCCESS: 2379 + /* Don't overwrite status if TD had an error, see xHCI 4.9.1 */ 2380 + if (td->error_mid_td) 2381 + break; 2379 2382 if (remaining) { 2380 2383 frame->status = short_framestatus; 2381 2384 if (xhci->quirks & XHCI_TRUST_TX_LENGTH) ··· 2394 2391 case COMP_BANDWIDTH_OVERRUN_ERROR: 2395 2392 frame->status = -ECOMM; 2396 2393 break; 2397 - case COMP_ISOCH_BUFFER_OVERRUN: 2398 2394 case COMP_BABBLE_DETECTED_ERROR: 2395 + sum_trbs_for_length = true; 2396 + fallthrough; 2397 + case COMP_ISOCH_BUFFER_OVERRUN: 2399 2398 frame->status = -EOVERFLOW; 2399 + if (ep_trb != td->last_trb) 2400 + td->error_mid_td = true; 2400 2401 break; 2401 2402 case COMP_INCOMPATIBLE_DEVICE_ERROR: 2402 2403 case COMP_STALL_ERROR: ··· 2408 2401 break; 2409 2402 case COMP_USB_TRANSACTION_ERROR: 2410 2403 frame->status = -EPROTO; 2404 + sum_trbs_for_length = true; 2411 2405 if (ep_trb != td->last_trb) 2412 - return 0; 2406 + td->error_mid_td = true; 2413 2407 break; 2414 2408 case COMP_STOPPED: 2415 2409 sum_trbs_for_length = true; ··· 2430 2422 break; 2431 2423 } 2432 2424 2425 + if (td->urb_length_set) 2426 + goto finish_td; 2427 + 2433 2428 if (sum_trbs_for_length) 2434 2429 frame->actual_length = sum_trb_lengths(xhci, ep->ring, ep_trb) + 2435 2430 ep_trb_len - remaining; ··· 2440 2429 frame->actual_length = requested; 2441 2430 2442 2431 td->urb->actual_length += frame->actual_length; 2432 + 2433 + finish_td: 2434 + /* Don't give back TD yet if we encountered an error mid TD */ 2435 + if (td->error_mid_td && ep_trb != td->last_trb) { 2436 + xhci_dbg(xhci, "Error mid isoc TD, wait for final completion event\n"); 2437 + td->urb_length_set = true; 2438 + return 0; 2439 + } 2443 2440 2444 2441 return finish_td(xhci, ep, ep_ring, td, trb_comp_code); 2445 2442 } ··· 2827 2808 } 2828 2809 2829 2810 if (!ep_seg) { 2830 - if (!ep->skip || 2831 - !usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { 2832 - /* Some host controllers give a spurious 2833 - * successful event after a short transfer. 2834 - * Ignore it. 2835 - */ 2836 - if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) && 2837 - ep_ring->last_td_was_short) { 2838 - ep_ring->last_td_was_short = false; 2839 - goto cleanup; 2811 + 2812 + if (ep->skip && usb_endpoint_xfer_isoc(&td->urb->ep->desc)) { 2813 + skip_isoc_td(xhci, td, ep, status); 2814 + goto cleanup; 2815 + } 2816 + 2817 + /* 2818 + * Some hosts give a spurious success event after a short 2819 + * transfer. Ignore it. 2820 + */ 2821 + if ((xhci->quirks & XHCI_SPURIOUS_SUCCESS) && 2822 + ep_ring->last_td_was_short) { 2823 + ep_ring->last_td_was_short = false; 2824 + goto cleanup; 2825 + } 2826 + 2827 + /* 2828 + * xhci 4.10.2 states isoc endpoints should continue 2829 + * processing the next TD if there was an error mid TD. 2830 + * So host like NEC don't generate an event for the last 2831 + * isoc TRB even if the IOC flag is set. 2832 + * xhci 4.9.1 states that if there are errors in mult-TRB 2833 + * TDs xHC should generate an error for that TRB, and if xHC 2834 + * proceeds to the next TD it should genete an event for 2835 + * any TRB with IOC flag on the way. Other host follow this. 2836 + * So this event might be for the next TD. 2837 + */ 2838 + if (td->error_mid_td && 2839 + !list_is_last(&td->td_list, &ep_ring->td_list)) { 2840 + struct xhci_td *td_next = list_next_entry(td, td_list); 2841 + 2842 + ep_seg = trb_in_td(xhci, td_next->start_seg, td_next->first_trb, 2843 + td_next->last_trb, ep_trb_dma, false); 2844 + if (ep_seg) { 2845 + /* give back previous TD, start handling new */ 2846 + xhci_dbg(xhci, "Missing TD completion event after mid TD error\n"); 2847 + ep_ring->dequeue = td->last_trb; 2848 + ep_ring->deq_seg = td->last_trb_seg; 2849 + inc_deq(xhci, ep_ring); 2850 + xhci_td_cleanup(xhci, td, ep_ring, td->status); 2851 + td = td_next; 2840 2852 } 2853 + } 2854 + 2855 + if (!ep_seg) { 2841 2856 /* HC is busted, give up! */ 2842 2857 xhci_err(xhci, 2843 2858 "ERROR Transfer event TRB DMA ptr not " ··· 2883 2830 ep_trb_dma, true); 2884 2831 return -ESHUTDOWN; 2885 2832 } 2886 - 2887 - skip_isoc_td(xhci, td, ep, status); 2888 - goto cleanup; 2889 2833 } 2890 2834 if (trb_comp_code == COMP_SHORT_PACKET) 2891 2835 ep_ring->last_td_was_short = true;
+1
drivers/usb/host/xhci.h
··· 1549 1549 struct xhci_segment *bounce_seg; 1550 1550 /* actual_length of the URB has already been set */ 1551 1551 bool urb_length_set; 1552 + bool error_mid_td; 1552 1553 unsigned int num_trbs; 1553 1554 }; 1554 1555
+1
drivers/usb/serial/cp210x.c
··· 146 146 { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ 147 147 { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ 148 148 { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ 149 + { USB_DEVICE(0x10C4, 0x87ED) }, /* IMST USB-Stick for Smart Meter */ 149 150 { USB_DEVICE(0x10C4, 0x8856) }, /* CEL EM357 ZigBee USB Stick - LR */ 150 151 { USB_DEVICE(0x10C4, 0x8857) }, /* CEL EM357 ZigBee USB Stick */ 151 152 { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */
+1
drivers/usb/serial/option.c
··· 2269 2269 { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0111, 0xff) }, /* Fibocom FM160 (MBIM mode) */ 2270 2270 { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */ 2271 2271 { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */ 2272 + { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a3, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */ 2272 2273 { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */ 2273 2274 .driver_info = RSVD(4) }, 2274 2275 { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */
+2
drivers/usb/serial/qcserial.c
··· 184 184 {DEVICE_SWI(0x413c, 0x81d0)}, /* Dell Wireless 5819 */ 185 185 {DEVICE_SWI(0x413c, 0x81d1)}, /* Dell Wireless 5818 */ 186 186 {DEVICE_SWI(0x413c, 0x81d2)}, /* Dell Wireless 5818 */ 187 + {DEVICE_SWI(0x413c, 0x8217)}, /* Dell Wireless DW5826e */ 188 + {DEVICE_SWI(0x413c, 0x8218)}, /* Dell Wireless DW5826e QDL */ 187 189 188 190 /* Huawei devices */ 189 191 {DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */
+3 -3
drivers/usb/typec/tcpm/tcpm.c
··· 4876 4876 break; 4877 4877 case PORT_RESET: 4878 4878 tcpm_reset_port(port); 4879 - tcpm_set_cc(port, tcpm_default_state(port) == SNK_UNATTACHED ? 4880 - TYPEC_CC_RD : tcpm_rp_cc(port)); 4879 + tcpm_set_cc(port, TYPEC_CC_OPEN); 4881 4880 tcpm_set_state(port, PORT_RESET_WAIT_OFF, 4882 4881 PD_T_ERROR_RECOVERY); 4883 4882 break; ··· 6847 6848 if (err) 6848 6849 goto out_role_sw_put; 6849 6850 6850 - port->typec_caps.pd = port->pds[0]; 6851 + if (port->pds) 6852 + port->typec_caps.pd = port->pds[0]; 6851 6853 6852 6854 port->typec_port = typec_register_port(port->dev, &port->typec_caps); 6853 6855 if (IS_ERR(port->typec_port)) {
+2
drivers/usb/typec/ucsi/ucsi.c
··· 938 938 939 939 clear_bit(EVENT_PENDING, &con->ucsi->flags); 940 940 941 + mutex_lock(&ucsi->ppm_lock); 941 942 ret = ucsi_acknowledge_connector_change(ucsi); 943 + mutex_unlock(&ucsi->ppm_lock); 942 944 if (ret) 943 945 dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret); 944 946
+81 -7
drivers/usb/typec/ucsi/ucsi_acpi.c
··· 25 25 unsigned long flags; 26 26 guid_t guid; 27 27 u64 cmd; 28 + bool dell_quirk_probed; 29 + bool dell_quirk_active; 28 30 }; 29 31 30 32 static int ucsi_acpi_dsm(struct ucsi_acpi *ua, int func) ··· 75 73 const void *val, size_t val_len) 76 74 { 77 75 struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); 76 + bool ack = UCSI_COMMAND(*(u64 *)val) == UCSI_ACK_CC_CI; 78 77 int ret; 79 78 80 - set_bit(COMMAND_PENDING, &ua->flags); 79 + if (ack) 80 + set_bit(ACK_PENDING, &ua->flags); 81 + else 82 + set_bit(COMMAND_PENDING, &ua->flags); 81 83 82 84 ret = ucsi_acpi_async_write(ucsi, offset, val, val_len); 83 85 if (ret) ··· 91 85 ret = -ETIMEDOUT; 92 86 93 87 out_clear_bit: 94 - clear_bit(COMMAND_PENDING, &ua->flags); 88 + if (ack) 89 + clear_bit(ACK_PENDING, &ua->flags); 90 + else 91 + clear_bit(COMMAND_PENDING, &ua->flags); 95 92 96 93 return ret; 97 94 } ··· 128 119 .async_write = ucsi_acpi_async_write 129 120 }; 130 121 131 - static const struct dmi_system_id zenbook_dmi_id[] = { 122 + /* 123 + * Some Dell laptops expect that an ACK command with the 124 + * UCSI_ACK_CONNECTOR_CHANGE bit set is followed by a (separate) 125 + * ACK command that only has the UCSI_ACK_COMMAND_COMPLETE bit set. 126 + * If this is not done events are not delivered to OSPM and 127 + * subsequent commands will timeout. 128 + */ 129 + static int 130 + ucsi_dell_sync_write(struct ucsi *ucsi, unsigned int offset, 131 + const void *val, size_t val_len) 132 + { 133 + struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi); 134 + u64 cmd = *(u64 *)val, ack = 0; 135 + int ret; 136 + 137 + if (UCSI_COMMAND(cmd) == UCSI_ACK_CC_CI && 138 + cmd & UCSI_ACK_CONNECTOR_CHANGE) 139 + ack = UCSI_ACK_CC_CI | UCSI_ACK_COMMAND_COMPLETE; 140 + 141 + ret = ucsi_acpi_sync_write(ucsi, offset, val, val_len); 142 + if (ret != 0) 143 + return ret; 144 + if (ack == 0) 145 + return ret; 146 + 147 + if (!ua->dell_quirk_probed) { 148 + ua->dell_quirk_probed = true; 149 + 150 + cmd = UCSI_GET_CAPABILITY; 151 + ret = ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &cmd, 152 + sizeof(cmd)); 153 + if (ret == 0) 154 + return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, 155 + &ack, sizeof(ack)); 156 + if (ret != -ETIMEDOUT) 157 + return ret; 158 + 159 + ua->dell_quirk_active = true; 160 + dev_err(ua->dev, "Firmware bug: Additional ACK required after ACKing a connector change.\n"); 161 + dev_err(ua->dev, "Firmware bug: Enabling workaround\n"); 162 + } 163 + 164 + if (!ua->dell_quirk_active) 165 + return ret; 166 + 167 + return ucsi_acpi_sync_write(ucsi, UCSI_CONTROL, &ack, sizeof(ack)); 168 + } 169 + 170 + static const struct ucsi_operations ucsi_dell_ops = { 171 + .read = ucsi_acpi_read, 172 + .sync_write = ucsi_dell_sync_write, 173 + .async_write = ucsi_acpi_async_write 174 + }; 175 + 176 + static const struct dmi_system_id ucsi_acpi_quirks[] = { 132 177 { 133 178 .matches = { 134 179 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 135 180 DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"), 136 181 }, 182 + .driver_data = (void *)&ucsi_zenbook_ops, 183 + }, 184 + { 185 + .matches = { 186 + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 187 + }, 188 + .driver_data = (void *)&ucsi_dell_ops, 137 189 }, 138 190 { } 139 191 }; ··· 212 142 if (UCSI_CCI_CONNECTOR(cci)) 213 143 ucsi_connector_change(ua->ucsi, UCSI_CCI_CONNECTOR(cci)); 214 144 215 - if (test_bit(COMMAND_PENDING, &ua->flags) && 216 - cci & (UCSI_CCI_ACK_COMPLETE | UCSI_CCI_COMMAND_COMPLETE)) 145 + if (cci & UCSI_CCI_ACK_COMPLETE && test_bit(ACK_PENDING, &ua->flags)) 146 + complete(&ua->complete); 147 + if (cci & UCSI_CCI_COMMAND_COMPLETE && 148 + test_bit(COMMAND_PENDING, &ua->flags)) 217 149 complete(&ua->complete); 218 150 } 219 151 ··· 223 151 { 224 152 struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); 225 153 const struct ucsi_operations *ops = &ucsi_acpi_ops; 154 + const struct dmi_system_id *id; 226 155 struct ucsi_acpi *ua; 227 156 struct resource *res; 228 157 acpi_status status; ··· 253 180 init_completion(&ua->complete); 254 181 ua->dev = &pdev->dev; 255 182 256 - if (dmi_check_system(zenbook_dmi_id)) 257 - ops = &ucsi_zenbook_ops; 183 + id = dmi_first_match(ucsi_acpi_quirks); 184 + if (id) 185 + ops = id->driver_data; 258 186 259 187 ua->ucsi = ucsi_create(&pdev->dev, ops); 260 188 if (IS_ERR(ua->ucsi))