Pull USB/Thunderbolt driver fixes from Greg KH: "Here are a lot of small USB and Thunderbolt driver fixes for 6.0-rc4 for reported problems. Included in here are: - new usb-serial driver ids - dwc3 driver bugfixes for reported problems with 6.0-rc1 - new device quirks, and reverts of some quirks that were incorrect - gadget driver bugfixes for reported problems - USB host controller bugfixes (xhci and others) - other small USB fixes, details in the shortlog - small thunderbolt driver fixes All of these have been in linux-next with no reported issues" * tag 'usb-6.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (51 commits) Revert "usb: gadget: udc-xilinx: replace memcpy with memcpy_toio" usb: storage: Add ASUS <0x0b05:0x1932> to IGNORE_UAS USB: serial: ch341: fix disabled rx timer on older devices USB: serial: ch341: fix lost character on LCR updates USB: serial: cp210x: add Decagon UCA device id Revert "usb: add quirks for Lenovo OneLink+ Dock" usb: cdns3: fix issue with rearming ISO OUT endpoint usb: cdns3: fix incorrect handling TRB_SMM flag for ISOC transfer usb: gadget: mass_storage: Fix cdrom data transfers on MAC-OS media: mceusb: Use new usb_control_msg_*() routines USB: core: Prevent nested device-reset calls USB: gadget: Fix obscure lockdep violation for udc_mutex usb: dwc2: fix wrong order of phy_power_on and phy_init usb: gadget: udc-xilinx: replace memcpy with memcpy_toio usb: typec: Remove retimers properly usb: dwc3: disable USB core PHY management usb: add quirks for Lenovo OneLink+ Dock USB: serial: option: add support for Cinterion MV32-WA/WB RmNet mode USB: serial: ftdi_sio: add Omron CS1W-CIF31 device id USB: serial: option: add Quectel EM060K modem ...
Unified · Split
| @@ -24,6 +24,7 @@ properties: · 23 unmodified lines | ||
| 24 | 24 | - mediatek,mt2712-mtu3 |
| 25 | 25 | - mediatek,mt8173-mtu3 |
| 26 | 26 | - mediatek,mt8183-mtu3 |
| 27 | + - mediatek,mt8188-mtu3 | |
| 27 | 28 | - mediatek,mt8192-mtu3 |
| 28 | 29 | - mediatek,mt8195-mtu3 |
| 29 | 30 | - const: mediatek,mtu3 |
| @@ -33,6 +33,7 @@ properties: · 32 unmodified lines | ||
| 33 | 33 | - qcom,sm6115-dwc3 |
| 34 | 34 | - qcom,sm6125-dwc3 |
| 35 | 35 | - qcom,sm6350-dwc3 |
| 36 | + - qcom,sm6375-dwc3 | |
| 36 | 37 | - qcom,sm8150-dwc3 |
| 37 | 38 | - qcom,sm8250-dwc3 |
| 38 | 39 | - qcom,sm8350-dwc3 |
| @@ -108,12 +109,17 @@ properties: · 69 unmodified lines | ||
| 108 | 109 | HS/FS/LS modes are supported. |
| 109 | 110 | type: boolean |
| 110 | 111 | |
| 112 | + wakeup-source: true | |
| 113 | + | |
| 111 | 114 | # Required child node: |
| 112 | 115 | |
| 113 | 116 | patternProperties: |
| 114 | 117 | "^usb@[0-9a-f]+$": |
| 115 | 118 | $ref: snps,dwc3.yaml# |
| 116 | 119 | |
| 120 | + properties: | |
| 121 | + wakeup-source: false | |
| 122 | + | |
| 117 | 123 | required: |
| 118 | 124 | - compatible |
| 119 | 125 | - reg |
| @@ -1416,42 +1416,37 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) · 1415 unmodified lines | ||
| 1416 | 1416 | { |
| 1417 | 1417 | int ret; |
| 1418 | 1418 | struct device *dev = ir->dev; |
| 1419 | − char *data; | |
| 1420 | − | |
| 1421 | − data = kzalloc(USB_CTRL_MSG_SZ, GFP_KERNEL); | |
| 1422 | − if (!data) { | |
| 1423 | − dev_err(dev, "%s: memory allocation failed!", __func__); | |
| 1424 | − return; | |
| 1425 | − } | |
| 1419 | + char data[USB_CTRL_MSG_SZ]; | |
| 1426 | 1420 | |
| 1427 | 1421 | /* |
| 1428 | 1422 | * This is a strange one. Windows issues a set address to the device |
| 1429 | 1423 | * on the receive control pipe and expect a certain value pair back |
| 1430 | 1424 | */ |
| 1431 | − ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0), | |
| 1432 | − USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0, | |
| 1433 | − data, USB_CTRL_MSG_SZ, 3000); | |
| 1425 | + ret = usb_control_msg_recv(ir->usbdev, 0, USB_REQ_SET_ADDRESS, | |
| 1426 | + USB_DIR_IN | USB_TYPE_VENDOR, | |
| 1427 | + 0, 0, data, USB_CTRL_MSG_SZ, 3000, | |
| 1428 | + GFP_KERNEL); | |
| 1434 | 1429 | dev_dbg(dev, "set address - ret = %d", ret); |
| 1435 | 1430 | dev_dbg(dev, "set address - data[0] = %d, data[1] = %d", |
| 1436 | 1431 | data[0], data[1]); |
| 1437 | 1432 | |
| 1438 | 1433 | /* set feature: bit rate 38400 bps */ |
| 1439 | − ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), | |
| 1440 | − USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, | |
| 1441 | − 0xc04e, 0x0000, NULL, 0, 3000); | |
| 1434 | + ret = usb_control_msg_send(ir->usbdev, 0, | |
| 1435 | + USB_REQ_SET_FEATURE, USB_TYPE_VENDOR, | |
| 1436 | + 0xc04e, 0x0000, NULL, 0, 3000, GFP_KERNEL); | |
| 1442 | 1437 | |
| 1443 | 1438 | dev_dbg(dev, "set feature - ret = %d", ret); |
| 1444 | 1439 | |
| 1445 | 1440 | /* bRequest 4: set char length to 8 bits */ |
| 1446 | − ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), | |
| 1447 | − 4, USB_TYPE_VENDOR, | |
| 1448 | − 0x0808, 0x0000, NULL, 0, 3000); | |
| 1441 | + ret = usb_control_msg_send(ir->usbdev, 0, | |
| 1442 | + 4, USB_TYPE_VENDOR, | |
| 1443 | + 0x0808, 0x0000, NULL, 0, 3000, GFP_KERNEL); | |
| 1449 | 1444 | dev_dbg(dev, "set char length - retB = %d", ret); |
| 1450 | 1445 | |
| 1451 | 1446 | /* bRequest 2: set handshaking to use DTR/DSR */ |
| 1452 | − ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0), | |
| 1453 | − 2, USB_TYPE_VENDOR, | |
| 1454 | − 0x0000, 0x0100, NULL, 0, 3000); | |
| 1447 | + ret = usb_control_msg_send(ir->usbdev, 0, | |
| 1448 | + 2, USB_TYPE_VENDOR, | |
| 1449 | + 0x0000, 0x0100, NULL, 0, 3000, GFP_KERNEL); | |
| 1455 | 1450 | dev_dbg(dev, "set handshake - retC = %d", ret); |
| 1456 | 1451 | |
| 1457 | 1452 | /* device resume */ |
| @@ -1459,8 +1454,6 @@ static void mceusb_gen1_init(struct mceusb_dev *ir) · 1 unmodified line | ||
| 1459 | 1454 | |
| 1460 | 1455 | /* get hw/sw revision? */ |
| 1461 | 1456 | mce_command_out(ir, GET_REVISION, sizeof(GET_REVISION)); |
| 1462 | − | |
| 1463 | − kfree(data); | |
| 1464 | 1457 | } |
| 1465 | 1458 | |
| 1466 | 1459 | static void mceusb_gen2_init(struct mceusb_dev *ir) |
| @@ -407,7 +407,7 @@ static void tb_ctl_rx_submit(struct ctl_pkg *pkg) · 406 unmodified lines | ||
| 407 | 407 | |
| 408 | 408 | static int tb_async_error(const struct ctl_pkg *pkg) |
| 409 | 409 | { |
| 410 | − const struct cfg_error_pkg *error = (const struct cfg_error_pkg *)pkg; | |
| 410 | + const struct cfg_error_pkg *error = pkg->buffer; | |
| 411 | 411 | |
| 412 | 412 | if (pkg->frame.eof != TB_CFG_PKG_ERROR) |
| 413 | 413 | return false; |
| @@ -3786,14 +3786,18 @@ int tb_switch_pcie_l1_enable(struct tb_switch *sw) · 3785 unmodified lines | ||
| 3786 | 3786 | */ |
| 3787 | 3787 | int tb_switch_xhci_connect(struct tb_switch *sw) |
| 3788 | 3788 | { |
| 3789 | − bool usb_port1, usb_port3, xhci_port1, xhci_port3; | |
| 3790 | 3789 | struct tb_port *port1, *port3; |
| 3791 | 3790 | int ret; |
| 3792 | 3791 | |
| 3792 | + if (sw->generation != 3) | |
| 3793 | + return 0; | |
| 3794 | + | |
| 3793 | 3795 | port1 = &sw->ports[1]; |
| 3794 | 3796 | port3 = &sw->ports[3]; |
| 3795 | 3797 | |
| 3796 | 3798 | if (tb_switch_is_alpine_ridge(sw)) { |
| 3799 | + bool usb_port1, usb_port3, xhci_port1, xhci_port3; | |
| 3800 | + | |
| 3797 | 3801 | usb_port1 = tb_lc_is_usb_plugged(port1); |
| 3798 | 3802 | usb_port3 = tb_lc_is_usb_plugged(port3); |
| 3799 | 3803 | xhci_port1 = tb_lc_is_xhci_connected(port1); |
| @@ -1530,7 +1530,8 @@ static void cdns3_transfer_completed(struct cdns3_device *priv_dev, · 1529 unmodified lines | ||
| 1530 | 1530 | TRB_LEN(le32_to_cpu(trb->length)); |
| 1531 | 1531 | |
| 1532 | 1532 | if (priv_req->num_of_trb > 1 && |
| 1533 | − le32_to_cpu(trb->control) & TRB_SMM) | |
| 1533 | + le32_to_cpu(trb->control) & TRB_SMM && | |
| 1534 | + le32_to_cpu(trb->control) & TRB_CHAIN) | |
| 1534 | 1535 | transfer_end = true; |
| 1535 | 1536 | |
| 1536 | 1537 | cdns3_ep_inc_deq(priv_ep); |
| @@ -1690,6 +1691,7 @@ static int cdns3_check_ep_interrupt_proceed(struct cdns3_endpoint *priv_ep) · 153 unmodified lines | ||
| 1690 | 1691 | ep_cfg &= ~EP_CFG_ENABLE; |
| 1691 | 1692 | writel(ep_cfg, &priv_dev->regs->ep_cfg); |
| 1692 | 1693 | priv_ep->flags &= ~EP_QUIRK_ISO_OUT_EN; |
| 1694 | + priv_ep->flags |= EP_UPDATE_EP_TRBADDR; | |
| 1693 | 1695 | } |
| 1694 | 1696 | cdns3_transfer_completed(priv_dev, priv_ep); |
| 1695 | 1697 | } else if (!(priv_ep->flags & EP_STALLED) && |
| @@ -1810,6 +1810,9 @@ static const struct usb_device_id acm_ids[] = { · 1809 unmodified lines | ||
| 1810 | 1810 | { USB_DEVICE(0x09d8, 0x0320), /* Elatec GmbH TWN3 */ |
| 1811 | 1811 | .driver_info = NO_UNION_NORMAL, /* has misplaced union descriptor */ |
| 1812 | 1812 | }, |
| 1813 | + { USB_DEVICE(0x0c26, 0x0020), /* Icom ICF3400 Serie */ | |
| 1814 | + .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ | |
| 1815 | + }, | |
| 1813 | 1816 | { USB_DEVICE(0x0ca6, 0xa050), /* Castles VEGA3000 */ |
| 1814 | 1817 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ |
| 1815 | 1818 | }, |
| @@ -6038,6 +6038,11 @@ re_enumerate: · 6037 unmodified lines | ||
| 6038 | 6038 | * the reset is over (using their post_reset method). |
| 6039 | 6039 | * |
| 6040 | 6040 | * Return: The same as for usb_reset_and_verify_device(). |
| 6041 | + * However, if a reset is already in progress (for instance, if a | |
| 6042 | + * driver doesn't have pre_ or post_reset() callbacks, and while | |
| 6043 | + * being unbound or re-bound during the ongoing reset its disconnect() | |
| 6044 | + * or probe() routine tries to perform a second, nested reset), the | |
| 6045 | + * routine returns -EINPROGRESS. | |
| 6041 | 6046 | * |
| 6042 | 6047 | * Note: |
| 6043 | 6048 | * The caller must own the device lock. For example, it's safe to use |
| @@ -6071,6 +6076,10 @@ int usb_reset_device(struct usb_device *udev) · 27 unmodified lines | ||
| 6071 | 6076 | return -EISDIR; |
| 6072 | 6077 | } |
| 6073 | 6078 | |
| 6079 | + if (udev->reset_in_progress) | |
| 6080 | + return -EINPROGRESS; | |
| 6081 | + udev->reset_in_progress = 1; | |
| 6082 | + | |
| 6074 | 6083 | port_dev = hub->ports[udev->portnum - 1]; |
| 6075 | 6084 | |
| 6076 | 6085 | /* |
| @@ -6135,6 +6144,7 @@ int usb_reset_device(struct usb_device *udev) · 58 unmodified lines | ||
| 6135 | 6144 | |
| 6136 | 6145 | usb_autosuspend_device(udev); |
| 6137 | 6146 | memalloc_noio_restore(noio_flag); |
| 6147 | + udev->reset_in_progress = 0; | |
| 6138 | 6148 | return ret; |
| 6139 | 6149 | } |
| 6140 | 6150 | EXPORT_SYMBOL_GPL(usb_reset_device); |
| @@ -154,9 +154,9 @@ static int __dwc2_lowlevel_hw_enable(struct dwc2_hsotg *hsotg) · 153 unmodified lines | ||
| 154 | 154 | } else if (hsotg->plat && hsotg->plat->phy_init) { |
| 155 | 155 | ret = hsotg->plat->phy_init(pdev, hsotg->plat->phy_type); |
| 156 | 156 | } else { |
| 157 | − ret = phy_power_on(hsotg->phy); | |
| 157 | + ret = phy_init(hsotg->phy); | |
| 158 | 158 | if (ret == 0) |
| 159 | − ret = phy_init(hsotg->phy); | |
| 159 | + ret = phy_power_on(hsotg->phy); | |
| 160 | 160 | } |
| 161 | 161 | |
| 162 | 162 | return ret; |
| @@ -188,9 +188,9 @@ static int __dwc2_lowlevel_hw_disable(struct dwc2_hsotg *hsotg) · 25 unmodified lines | ||
| 188 | 188 | } else if (hsotg->plat && hsotg->plat->phy_exit) { |
| 189 | 189 | ret = hsotg->plat->phy_exit(pdev, hsotg->plat->phy_type); |
| 190 | 190 | } else { |
| 191 | − ret = phy_exit(hsotg->phy); | |
| 191 | + ret = phy_power_off(hsotg->phy); | |
| 192 | 192 | if (ret == 0) |
| 193 | − ret = phy_power_off(hsotg->phy); | |
| 193 | + ret = phy_exit(hsotg->phy); | |
| 194 | 194 | } |
| 195 | 195 | if (ret) |
| 196 | 196 | return ret; |
| @@ -833,15 +833,16 @@ static void dwc3_core_exit(struct dwc3 *dwc) · 832 unmodified lines | ||
| 833 | 833 | { |
| 834 | 834 | dwc3_event_buffers_cleanup(dwc); |
| 835 | 835 | |
| 836 | + usb_phy_set_suspend(dwc->usb2_phy, 1); | |
| 837 | + usb_phy_set_suspend(dwc->usb3_phy, 1); | |
| 838 | + phy_power_off(dwc->usb2_generic_phy); | |
| 839 | + phy_power_off(dwc->usb3_generic_phy); | |
| 840 | + | |
| 836 | 841 | usb_phy_shutdown(dwc->usb2_phy); |
| 837 | 842 | usb_phy_shutdown(dwc->usb3_phy); |
| 838 | 843 | phy_exit(dwc->usb2_generic_phy); |
| 839 | 844 | phy_exit(dwc->usb3_generic_phy); |
| 840 | 845 | |
| 841 | − usb_phy_set_suspend(dwc->usb2_phy, 1); | |
| 842 | − usb_phy_set_suspend(dwc->usb3_phy, 1); | |
| 843 | − phy_power_off(dwc->usb2_generic_phy); | |
| 844 | − phy_power_off(dwc->usb3_generic_phy); | |
| 845 | 846 | dwc3_clk_disable(dwc); |
| 846 | 847 | reset_control_assert(dwc->reset); |
| 847 | 848 | } |
| @@ -1821,7 +1822,6 @@ static int dwc3_probe(struct platform_device *pdev) · 973 unmodified lines | ||
| 1821 | 1822 | |
| 1822 | 1823 | platform_set_drvdata(pdev, dwc); |
| 1823 | 1824 | dwc3_cache_hwparams(dwc); |
| 1824 | − device_init_wakeup(&pdev->dev, of_property_read_bool(dev->of_node, "wakeup-source")); | |
| 1825 | 1825 | |
| 1826 | 1826 | spin_lock_init(&dwc->lock); |
| 1827 | 1827 | mutex_init(&dwc->mutex); |
| @@ -1879,16 +1879,16 @@ err5: · 51 unmodified lines | ||
| 1879 | 1879 | dwc3_debugfs_exit(dwc); |
| 1880 | 1880 | dwc3_event_buffers_cleanup(dwc); |
| 1881 | 1881 | |
| 1882 | − usb_phy_shutdown(dwc->usb2_phy); | |
| 1883 | − usb_phy_shutdown(dwc->usb3_phy); | |
| 1884 | − phy_exit(dwc->usb2_generic_phy); | |
| 1885 | − phy_exit(dwc->usb3_generic_phy); | |
| 1886 | − | |
| 1887 | 1882 | usb_phy_set_suspend(dwc->usb2_phy, 1); |
| 1888 | 1883 | usb_phy_set_suspend(dwc->usb3_phy, 1); |
| 1889 | 1884 | phy_power_off(dwc->usb2_generic_phy); |
| 1890 | 1885 | phy_power_off(dwc->usb3_generic_phy); |
| 1891 | 1886 | |
| 1887 | + usb_phy_shutdown(dwc->usb2_phy); | |
| 1888 | + usb_phy_shutdown(dwc->usb3_phy); | |
| 1889 | + phy_exit(dwc->usb2_generic_phy); | |
| 1890 | + phy_exit(dwc->usb3_generic_phy); | |
| 1891 | + | |
| 1892 | 1892 | dwc3_ulpi_exit(dwc); |
| 1893 | 1893 | |
| 1894 | 1894 | err4: |
| @@ -1983,7 +1983,7 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) · 88 unmodified lines | ||
| 1983 | 1983 | dwc3_core_exit(dwc); |
| 1984 | 1984 | break; |
| 1985 | 1985 | case DWC3_GCTL_PRTCAP_HOST: |
| 1986 | − if (!PMSG_IS_AUTO(msg) && !device_can_wakeup(dwc->dev)) { | |
| 1986 | + if (!PMSG_IS_AUTO(msg) && !device_may_wakeup(dwc->dev)) { | |
| 1987 | 1987 | dwc3_core_exit(dwc); |
| 1988 | 1988 | break; |
| 1989 | 1989 | } |
| @@ -2044,7 +2044,7 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) · 54 unmodified lines | ||
| 2044 | 2044 | spin_unlock_irqrestore(&dwc->lock, flags); |
| 2045 | 2045 | break; |
| 2046 | 2046 | case DWC3_GCTL_PRTCAP_HOST: |
| 2047 | − if (!PMSG_IS_AUTO(msg) && !device_can_wakeup(dwc->dev)) { | |
| 2047 | + if (!PMSG_IS_AUTO(msg) && !device_may_wakeup(dwc->dev)) { | |
| 2048 | 2048 | ret = dwc3_core_init_for_resume(dwc); |
| 2049 | 2049 | if (ret) |
| 2050 | 2050 | return ret; |
| @@ -44,6 +44,7 @@ · 43 unmodified lines | ||
| 44 | 44 | #define PCI_DEVICE_ID_INTEL_ADLP 0x51ee |
| 45 | 45 | #define PCI_DEVICE_ID_INTEL_ADLM 0x54ee |
| 46 | 46 | #define PCI_DEVICE_ID_INTEL_ADLS 0x7ae1 |
| 47 | +#define PCI_DEVICE_ID_INTEL_RPL 0x460e | |
| 47 | 48 | #define PCI_DEVICE_ID_INTEL_RPLS 0x7a61 |
| 48 | 49 | #define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1 |
| 49 | 50 | #define PCI_DEVICE_ID_INTEL_MTL 0x7e7e |
| @@ -456,6 +457,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = { · 406 unmodified lines | ||
| 456 | 457 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_ADLS), |
| 457 | 458 | (kernel_ulong_t) &dwc3_pci_intel_swnode, }, |
| 458 | 459 | |
| 460 | + { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPL), | |
| 461 | + (kernel_ulong_t) &dwc3_pci_intel_swnode, }, | |
| 462 | + | |
| 459 | 463 | { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_RPLS), |
| 460 | 464 | (kernel_ulong_t) &dwc3_pci_intel_swnode, }, |
| 461 | 465 | |
| @@ -17,7 +17,6 @@ · 16 unmodified lines | ||
| 17 | 17 | #include <linux/of_platform.h> |
| 18 | 18 | #include <linux/platform_device.h> |
| 19 | 19 | #include <linux/phy/phy.h> |
| 20 | −#include <linux/pm_domain.h> | |
| 21 | 20 | #include <linux/usb/of.h> |
| 22 | 21 | #include <linux/reset.h> |
| 23 | 22 | #include <linux/iopoll.h> |
| @@ -299,11 +298,24 @@ static void dwc3_qcom_interconnect_exit(struct dwc3_qcom *qcom) · 275 unmodified lines | ||
| 299 | 298 | icc_put(qcom->icc_path_apps); |
| 300 | 299 | } |
| 301 | 300 | |
| 301 | +/* Only usable in contexts where the role can not change. */ | |
| 302 | +static bool dwc3_qcom_is_host(struct dwc3_qcom *qcom) | |
| 303 | +{ | |
| 304 | + struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3); | |
| 305 | + | |
| 306 | + return dwc->xhci; | |
| 307 | +} | |
| 308 | + | |
| 302 | 309 | static enum usb_device_speed dwc3_qcom_read_usb2_speed(struct dwc3_qcom *qcom) |
| 303 | 310 | { |
| 304 | 311 | struct dwc3 *dwc = platform_get_drvdata(qcom->dwc3); |
| 305 | − struct usb_hcd *hcd = platform_get_drvdata(dwc->xhci); | |
| 306 | 312 | struct usb_device *udev; |
| 313 | + struct usb_hcd __maybe_unused *hcd; | |
| 314 | + | |
| 315 | + /* | |
| 316 | + * FIXME: Fix this layering violation. | |
| 317 | + */ | |
| 318 | + hcd = platform_get_drvdata(dwc->xhci); | |
| 307 | 319 | |
| 308 | 320 | /* |
| 309 | 321 | * It is possible to query the speed of all children of |
| @@ -311,8 +323,11 @@ static enum usb_device_speed dwc3_qcom_read_usb2_speed(struct dwc3_qcom *qcom) · 1 unmodified line | ||
| 311 | 323 | * currently supports only 1 port per controller. So |
| 312 | 324 | * this is sufficient. |
| 313 | 325 | */ |
| 326 | +#ifdef CONFIG_USB | |
| 314 | 327 | udev = usb_hub_find_child(hcd->self.root_hub, 1); |
| 315 | − | |
| 328 | +#else | |
| 329 | + udev = NULL; | |
| 330 | +#endif | |
| 316 | 331 | if (!udev) |
| 317 | 332 | return USB_SPEED_UNKNOWN; |
| 318 | 333 | |
| @@ -387,7 +402,7 @@ static void dwc3_qcom_enable_interrupts(struct dwc3_qcom *qcom) · 68 unmodified lines | ||
| 387 | 402 | dwc3_qcom_enable_wakeup_irq(qcom->ss_phy_irq, 0); |
| 388 | 403 | } |
| 389 | 404 | |
| 390 | −static int dwc3_qcom_suspend(struct dwc3_qcom *qcom) | |
| 405 | +static int dwc3_qcom_suspend(struct dwc3_qcom *qcom, bool wakeup) | |
| 391 | 406 | { |
| 392 | 407 | u32 val; |
| 393 | 408 | int i, ret; |
| @@ -406,7 +421,11 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom) · 12 unmodified lines | ||
| 406 | 421 | if (ret) |
| 407 | 422 | dev_warn(qcom->dev, "failed to disable interconnect: %d\n", ret); |
| 408 | 423 | |
| 409 | − if (device_may_wakeup(qcom->dev)) { | |
| 424 | + /* | |
| 425 | + * The role is stable during suspend as role switching is done from a | |
| 426 | + * freezable workqueue. | |
| 427 | + */ | |
| 428 | + if (dwc3_qcom_is_host(qcom) && wakeup) { | |
| 410 | 429 | qcom->usb2_speed = dwc3_qcom_read_usb2_speed(qcom); |
| 411 | 430 | dwc3_qcom_enable_interrupts(qcom); |
| 412 | 431 | } |
| @@ -416,7 +435,7 @@ static int dwc3_qcom_suspend(struct dwc3_qcom *qcom) · 3 unmodified lines | ||
| 416 | 435 | return 0; |
| 417 | 436 | } |
| 418 | 437 | |
| 419 | −static int dwc3_qcom_resume(struct dwc3_qcom *qcom) | |
| 438 | +static int dwc3_qcom_resume(struct dwc3_qcom *qcom, bool wakeup) | |
| 420 | 439 | { |
| 421 | 440 | int ret; |
| 422 | 441 | int i; |
| @@ -424,7 +443,7 @@ static int dwc3_qcom_resume(struct dwc3_qcom *qcom) · 1 unmodified line | ||
| 424 | 443 | if (!qcom->is_suspended) |
| 425 | 444 | return 0; |
| 426 | 445 | |
| 427 | − if (device_may_wakeup(qcom->dev)) | |
| 446 | + if (dwc3_qcom_is_host(qcom) && wakeup) | |
| 428 | 447 | dwc3_qcom_disable_interrupts(qcom); |
| 429 | 448 | |
| 430 | 449 | for (i = 0; i < qcom->num_clocks; i++) { |
| @@ -458,7 +477,11 @@ static irqreturn_t qcom_dwc3_resume_irq(int irq, void *data) · 27 unmodified lines | ||
| 458 | 477 | if (qcom->pm_suspended) |
| 459 | 478 | return IRQ_HANDLED; |
| 460 | 479 | |
| 461 | − if (dwc->xhci) | |
| 480 | + /* | |
| 481 | + * This is safe as role switching is done from a freezable workqueue | |
| 482 | + * and the wakeup interrupts are disabled as part of resume. | |
| 483 | + */ | |
| 484 | + if (dwc3_qcom_is_host(qcom)) | |
| 462 | 485 | pm_runtime_resume(&dwc->xhci->dev); |
| 463 | 486 | |
| 464 | 487 | return IRQ_HANDLED; |
| @@ -757,13 +780,13 @@ dwc3_qcom_create_urs_usb_platdev(struct device *dev) · 292 unmodified lines | ||
| 757 | 780 | |
| 758 | 781 | static int dwc3_qcom_probe(struct platform_device *pdev) |
| 759 | 782 | { |
| 760 | − struct device_node *np = pdev->dev.of_node; | |
| 761 | − struct device *dev = &pdev->dev; | |
| 762 | − struct dwc3_qcom *qcom; | |
| 763 | − struct resource *res, *parent_res = NULL; | |
| 764 | − int ret, i; | |
| 765 | − bool ignore_pipe_clk; | |
| 766 | − struct generic_pm_domain *genpd; | |
| 783 | + struct device_node *np = pdev->dev.of_node; | |
| 784 | + struct device *dev = &pdev->dev; | |
| 785 | + struct dwc3_qcom *qcom; | |
| 786 | + struct resource *res, *parent_res = NULL; | |
| 787 | + int ret, i; | |
| 788 | + bool ignore_pipe_clk; | |
| 789 | + bool wakeup_source; | |
| 767 | 790 | |
| 768 | 791 | qcom = devm_kzalloc(&pdev->dev, sizeof(*qcom), GFP_KERNEL); |
| 769 | 792 | if (!qcom) |
| @@ -772,8 +795,6 @@ static int dwc3_qcom_probe(struct platform_device *pdev) · 2 unmodified lines | ||
| 772 | 795 | platform_set_drvdata(pdev, qcom); |
| 773 | 796 | qcom->dev = &pdev->dev; |
| 774 | 797 | |
| 775 | − genpd = pd_to_genpd(qcom->dev->pm_domain); | |
| 776 | − | |
| 777 | 798 | if (has_acpi_companion(dev)) { |
| 778 | 799 | qcom->acpi_pdata = acpi_device_get_match_data(dev); |
| 779 | 800 | if (!qcom->acpi_pdata) { |
| @@ -881,16 +902,9 @@ static int dwc3_qcom_probe(struct platform_device *pdev) · 101 unmodified lines | ||
| 881 | 902 | if (ret) |
| 882 | 903 | goto interconnect_exit; |
| 883 | 904 | |
| 884 | − if (device_can_wakeup(&qcom->dwc3->dev)) { | |
| 885 | − /* | |
| 886 | − * Setting GENPD_FLAG_ALWAYS_ON flag takes care of keeping | |
| 887 | − * genpd on in both runtime suspend and system suspend cases. | |
| 888 | − */ | |
| 889 | − genpd->flags |= GENPD_FLAG_ALWAYS_ON; | |
| 890 | − device_init_wakeup(&pdev->dev, true); | |
| 891 | − } else { | |
| 892 | − genpd->flags |= GENPD_FLAG_RPM_ALWAYS_ON; | |
| 893 | − } | |
| 905 | + wakeup_source = of_property_read_bool(dev->of_node, "wakeup-source"); | |
| 906 | + device_init_wakeup(&pdev->dev, wakeup_source); | |
| 907 | + device_init_wakeup(&qcom->dwc3->dev, wakeup_source); | |
| 894 | 908 | |
| 895 | 909 | qcom->is_suspended = false; |
| 896 | 910 | pm_runtime_set_active(dev); |
| @@ -944,39 +958,45 @@ static int dwc3_qcom_remove(struct platform_device *pdev) · 47 unmodified lines | ||
| 944 | 958 | static int __maybe_unused dwc3_qcom_pm_suspend(struct device *dev) |
| 945 | 959 | { |
| 946 | 960 | struct dwc3_qcom *qcom = dev_get_drvdata(dev); |
| 947 | − int ret = 0; | |
| 961 | + bool wakeup = device_may_wakeup(dev); | |
| 962 | + int ret; | |
| 948 | 963 | |
| 949 | − ret = dwc3_qcom_suspend(qcom); | |
| 950 | − if (!ret) | |
| 951 | − qcom->pm_suspended = true; | |
| 964 | + ret = dwc3_qcom_suspend(qcom, wakeup); | |
| 965 | + if (ret) | |
| 966 | + return ret; | |
| 952 | 967 | |
| 953 | − return ret; | |
| 968 | + qcom->pm_suspended = true; | |
| 969 | + | |
| 970 | + return 0; | |
| 954 | 971 | } |
| 955 | 972 | |
| 956 | 973 | static int __maybe_unused dwc3_qcom_pm_resume(struct device *dev) |
| 957 | 974 | { |
| 958 | 975 | struct dwc3_qcom *qcom = dev_get_drvdata(dev); |
| 976 | + bool wakeup = device_may_wakeup(dev); | |
| 959 | 977 | int ret; |
| 960 | 978 | |
| 961 | − ret = dwc3_qcom_resume(qcom); | |
| 962 | − if (!ret) | |
| 963 | − qcom->pm_suspended = false; | |
| 979 | + ret = dwc3_qcom_resume(qcom, wakeup); | |
| 980 | + if (ret) | |
| 981 | + return ret; | |
| 964 | 982 | |
| 965 | − return ret; | |
| 983 | + qcom->pm_suspended = false; | |
| 984 | + | |
| 985 | + return 0; | |
| 966 | 986 | } |
| 967 | 987 | |
| 968 | 988 | static int __maybe_unused dwc3_qcom_runtime_suspend(struct device *dev) |
| 969 | 989 | { |
| 970 | 990 | struct dwc3_qcom *qcom = dev_get_drvdata(dev); |
| 971 | 991 | |
| 972 | − return dwc3_qcom_suspend(qcom); | |
| 992 | + return dwc3_qcom_suspend(qcom, true); | |
| 973 | 993 | } |
| 974 | 994 | |
| 975 | 995 | static int __maybe_unused dwc3_qcom_runtime_resume(struct device *dev) |
| 976 | 996 | { |
| 977 | 997 | struct dwc3_qcom *qcom = dev_get_drvdata(dev); |
| 978 | 998 | |
| 979 | − return dwc3_qcom_resume(qcom); | |
| 999 | + return dwc3_qcom_resume(qcom, true); | |
| 980 | 1000 | } |
| 981 | 1001 | |
| 982 | 1002 | static const struct dev_pm_ops dwc3_qcom_dev_pm_ops = { |
| @@ -2539,9 +2539,6 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) · 2538 unmodified lines | ||
| 2539 | 2539 | |
| 2540 | 2540 | is_on = !!is_on; |
| 2541 | 2541 | |
| 2542 | − if (dwc->pullups_connected == is_on) | |
| 2543 | − return 0; | |
| 2544 | − | |
| 2545 | 2542 | dwc->softconnect = is_on; |
| 2546 | 2543 | |
| 2547 | 2544 | /* |
| @@ -2566,6 +2563,11 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) · 18 unmodified lines | ||
| 2566 | 2563 | return 0; |
| 2567 | 2564 | } |
| 2568 | 2565 | |
| 2566 | + if (dwc->pullups_connected == is_on) { | |
| 2567 | + pm_runtime_put(dwc->dev); | |
| 2568 | + return 0; | |
| 2569 | + } | |
| 2570 | + | |
| 2569 | 2571 | if (!is_on) { |
| 2570 | 2572 | ret = dwc3_gadget_soft_disconnect(dwc); |
| 2571 | 2573 | } else { |
| @@ -11,8 +11,13 @@ · 10 unmodified lines | ||
| 11 | 11 | #include <linux/of.h> |
| 12 | 12 | #include <linux/platform_device.h> |
| 13 | 13 | |
| 14 | +#include "../host/xhci-plat.h" | |
| 14 | 15 | #include "core.h" |
| 15 | 16 | |
| 17 | +static const struct xhci_plat_priv dwc3_xhci_plat_priv = { | |
| 18 | + .quirks = XHCI_SKIP_PHY_INIT, | |
| 19 | +}; | |
| 20 | + | |
| 16 | 21 | static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc, |
| 17 | 22 | int irq, char *name) |
| 18 | 23 | { |
| @@ -92,6 +97,11 @@ int dwc3_host_init(struct dwc3 *dwc) · 73 unmodified lines | ||
| 92 | 97 | goto err; |
| 93 | 98 | } |
| 94 | 99 | |
| 100 | + ret = platform_device_add_data(xhci, &dwc3_xhci_plat_priv, | |
| 101 | + sizeof(dwc3_xhci_plat_priv)); | |
| 102 | + if (ret) | |
| 103 | + goto err; | |
| 104 | + | |
| 95 | 105 | memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props)); |
| 96 | 106 | |
| 97 | 107 | if (dwc->usb3_lpm_capable) |
| @@ -135,4 +145,5 @@ err: · 37 unmodified lines | ||
| 135 | 145 | void dwc3_host_exit(struct dwc3 *dwc) |
| 136 | 146 | { |
| 137 | 147 | platform_device_unregister(dwc->xhci); |
| 148 | + dwc->xhci = NULL; | |
| 138 | 149 | } |
| @@ -291,6 +291,12 @@ static struct usb_endpoint_descriptor ss_ep_int_desc = { · 290 unmodified lines | ||
| 291 | 291 | .bInterval = 4, |
| 292 | 292 | }; |
| 293 | 293 | |
| 294 | +static struct usb_ss_ep_comp_descriptor ss_ep_int_desc_comp = { | |
| 295 | + .bLength = sizeof(ss_ep_int_desc_comp), | |
| 296 | + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, | |
| 297 | + .wBytesPerInterval = cpu_to_le16(6), | |
| 298 | +}; | |
| 299 | + | |
| 294 | 300 | /* Audio Streaming OUT Interface - Alt0 */ |
| 295 | 301 | static struct usb_interface_descriptor std_as_out_if0_desc = { |
| 296 | 302 | .bLength = sizeof std_as_out_if0_desc, |
| @@ -604,7 +610,8 @@ static struct usb_descriptor_header *ss_audio_desc[] = { · 307 unmodified lines | ||
| 604 | 610 | (struct usb_descriptor_header *)&in_feature_unit_desc, |
| 605 | 611 | (struct usb_descriptor_header *)&io_out_ot_desc, |
| 606 | 612 | |
| 607 | − (struct usb_descriptor_header *)&ss_ep_int_desc, | |
| 613 | + (struct usb_descriptor_header *)&ss_ep_int_desc, | |
| 614 | + (struct usb_descriptor_header *)&ss_ep_int_desc_comp, | |
| 608 | 615 | |
| 609 | 616 | (struct usb_descriptor_header *)&std_as_out_if0_desc, |
| 610 | 617 | (struct usb_descriptor_header *)&std_as_out_if1_desc, |
| @@ -800,6 +807,7 @@ static void setup_headers(struct f_uac2_opts *opts, · 189 unmodified lines | ||
| 800 | 807 | struct usb_ss_ep_comp_descriptor *epout_desc_comp = NULL; |
| 801 | 808 | struct usb_ss_ep_comp_descriptor *epin_desc_comp = NULL; |
| 802 | 809 | struct usb_ss_ep_comp_descriptor *epin_fback_desc_comp = NULL; |
| 810 | + struct usb_ss_ep_comp_descriptor *ep_int_desc_comp = NULL; | |
| 803 | 811 | struct usb_endpoint_descriptor *epout_desc; |
| 804 | 812 | struct usb_endpoint_descriptor *epin_desc; |
| 805 | 813 | struct usb_endpoint_descriptor *epin_fback_desc; |
| @@ -827,6 +835,7 @@ static void setup_headers(struct f_uac2_opts *opts, · 21 unmodified lines | ||
| 827 | 835 | epin_fback_desc = &ss_epin_fback_desc; |
| 828 | 836 | epin_fback_desc_comp = &ss_epin_fback_desc_comp; |
| 829 | 837 | ep_int_desc = &ss_ep_int_desc; |
| 838 | + ep_int_desc_comp = &ss_ep_int_desc_comp; | |
| 830 | 839 | } |
| 831 | 840 | |
| 832 | 841 | i = 0; |
| @@ -855,8 +864,11 @@ static void setup_headers(struct f_uac2_opts *opts, · 22 unmodified lines | ||
| 855 | 864 | if (EPOUT_EN(opts)) |
| 856 | 865 | headers[i++] = USBDHDR(&io_out_ot_desc); |
| 857 | 866 | |
| 858 | − if (FUOUT_EN(opts) || FUIN_EN(opts)) | |
| 867 | + if (FUOUT_EN(opts) || FUIN_EN(opts)) { | |
| 859 | 868 | headers[i++] = USBDHDR(ep_int_desc); |
| 869 | + if (ep_int_desc_comp) | |
| 870 | + headers[i++] = USBDHDR(ep_int_desc_comp); | |
| 871 | + } | |
| 860 | 872 | |
| 861 | 873 | if (EPOUT_EN(opts)) { |
| 862 | 874 | headers[i++] = USBDHDR(&std_as_out_if0_desc); |
| @@ -294,8 +294,10 @@ EXPORT_SYMBOL_GPL(fsg_lun_fsync_sub); · 293 unmodified lines | ||
| 294 | 294 | void store_cdrom_address(u8 *dest, int msf, u32 addr) |
| 295 | 295 | { |
| 296 | 296 | if (msf) { |
| 297 | − /* Convert to Minutes-Seconds-Frames */ | |
| 298 | − addr >>= 2; /* Convert to 2048-byte frames */ | |
| 297 | + /* | |
| 298 | + * Convert to Minutes-Seconds-Frames. | |
| 299 | + * Sector size is already set to 2048 bytes. | |
| 300 | + */ | |
| 299 | 301 | addr += 2*75; /* Lead-in occupies 2 seconds */ |
| 300 | 302 | dest[3] = addr % 75; /* Frames */ |
| 301 | 303 | addr /= 75; |
| @@ -736,7 +736,10 @@ int usb_gadget_disconnect(struct usb_gadget *gadget) · 735 unmodified lines | ||
| 736 | 736 | ret = gadget->ops->pullup(gadget, 0); |
| 737 | 737 | if (!ret) { |
| 738 | 738 | gadget->connected = 0; |
| 739 | − gadget->udc->driver->disconnect(gadget); | |
| 739 | + mutex_lock(&udc_lock); | |
| 740 | + if (gadget->udc->driver) | |
| 741 | + gadget->udc->driver->disconnect(gadget); | |
| 742 | + mutex_unlock(&udc_lock); | |
| 740 | 743 | } |
| 741 | 744 | |
| 742 | 745 | out: |
| @@ -1489,7 +1492,6 @@ static int gadget_bind_driver(struct device *dev) · 746 unmodified lines | ||
| 1489 | 1492 | |
| 1490 | 1493 | usb_gadget_udc_set_speed(udc, driver->max_speed); |
| 1491 | 1494 | |
| 1492 | − mutex_lock(&udc_lock); | |
| 1493 | 1495 | ret = driver->bind(udc->gadget, driver); |
| 1494 | 1496 | if (ret) |
| 1495 | 1497 | goto err_bind; |
| @@ -1499,7 +1501,6 @@ static int gadget_bind_driver(struct device *dev) · 3 unmodified lines | ||
| 1499 | 1501 | goto err_start; |
| 1500 | 1502 | usb_gadget_enable_async_callbacks(udc); |
| 1501 | 1503 | usb_udc_connect_control(udc); |
| 1502 | − mutex_unlock(&udc_lock); | |
| 1503 | 1504 | |
| 1504 | 1505 | kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); |
| 1505 | 1506 | return 0; |
| @@ -1512,6 +1513,7 @@ static int gadget_bind_driver(struct device *dev) · 6 unmodified lines | ||
| 1512 | 1513 | dev_err(&udc->dev, "failed to start %s: %d\n", |
| 1513 | 1514 | driver->function, ret); |
| 1514 | 1515 | |
| 1516 | + mutex_lock(&udc_lock); | |
| 1515 | 1517 | udc->driver = NULL; |
| 1516 | 1518 | driver->is_bound = false; |
| 1517 | 1519 | mutex_unlock(&udc_lock); |
| @@ -1529,7 +1531,6 @@ static void gadget_unbind_driver(struct device *dev) · 11 unmodified lines | ||
| 1529 | 1531 | |
| 1530 | 1532 | kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); |
| 1531 | 1533 | |
| 1532 | − mutex_lock(&udc_lock); | |
| 1533 | 1534 | usb_gadget_disconnect(gadget); |
| 1534 | 1535 | usb_gadget_disable_async_callbacks(udc); |
| 1535 | 1536 | if (gadget->irq) |
| @@ -1537,6 +1538,7 @@ static void gadget_unbind_driver(struct device *dev) · 1 unmodified line | ||
| 1537 | 1538 | udc->driver->unbind(gadget); |
| 1538 | 1539 | usb_gadget_udc_stop(udc); |
| 1539 | 1540 | |
| 1541 | + mutex_lock(&udc_lock); | |
| 1540 | 1542 | driver->is_bound = false; |
| 1541 | 1543 | udc->driver = NULL; |
| 1542 | 1544 | mutex_unlock(&udc_lock); |
| @@ -1612,7 +1614,7 @@ static ssize_t soft_connect_store(struct device *dev, · 69 unmodified lines | ||
| 1612 | 1614 | struct usb_udc *udc = container_of(dev, struct usb_udc, dev); |
| 1613 | 1615 | ssize_t ret; |
| 1614 | 1616 | |
| 1615 | − mutex_lock(&udc_lock); | |
| 1617 | + device_lock(&udc->gadget->dev); | |
| 1616 | 1618 | if (!udc->driver) { |
| 1617 | 1619 | dev_err(dev, "soft-connect without a gadget driver\n"); |
| 1618 | 1620 | ret = -EOPNOTSUPP; |
| @@ -1633,7 +1635,7 @@ static ssize_t soft_connect_store(struct device *dev, · 14 unmodified lines | ||
| 1633 | 1635 | |
| 1634 | 1636 | ret = n; |
| 1635 | 1637 | out: |
| 1636 | − mutex_unlock(&udc_lock); | |
| 1638 | + device_unlock(&udc->gadget->dev); | |
| 1637 | 1639 | return ret; |
| 1638 | 1640 | } |
| 1639 | 1641 | static DEVICE_ATTR_WO(soft_connect); |
| @@ -1652,11 +1654,15 @@ static ssize_t function_show(struct device *dev, struct device_attribute *attr, · 12 unmodified lines | ||
| 1652 | 1654 | char *buf) |
| 1653 | 1655 | { |
| 1654 | 1656 | struct usb_udc *udc = container_of(dev, struct usb_udc, dev); |
| 1655 | − struct usb_gadget_driver *drv = udc->driver; | |
| 1657 | + struct usb_gadget_driver *drv; | |
| 1658 | + int rc = 0; | |
| 1656 | 1659 | |
| 1657 | − if (!drv || !drv->function) | |
| 1658 | − return 0; | |
| 1659 | − return scnprintf(buf, PAGE_SIZE, "%s\n", drv->function); | |
| 1660 | + mutex_lock(&udc_lock); | |
| 1661 | + drv = udc->driver; | |
| 1662 | + if (drv && drv->function) | |
| 1663 | + rc = scnprintf(buf, PAGE_SIZE, "%s\n", drv->function); | |
| 1664 | + mutex_unlock(&udc_lock); | |
| 1665 | + return rc; | |
| 1660 | 1666 | } |
| 1661 | 1667 | static DEVICE_ATTR_RO(function); |
| 1662 | 1668 | |
| @@ -652,7 +652,7 @@ struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd) · 651 unmodified lines | ||
| 652 | 652 | * It will release and re-aquire the lock while calling ACPI |
| 653 | 653 | * method. |
| 654 | 654 | */ |
| 655 | −void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, | |
| 655 | +static void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, | |
| 656 | 656 | u16 index, bool on, unsigned long *flags) |
| 657 | 657 | __must_hold(&xhci->lock) |
| 658 | 658 | { |
| @@ -1648,6 +1648,17 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) · 989 unmodified lines | ||
| 1648 | 1648 | |
| 1649 | 1649 | status = bus_state->resuming_ports; |
| 1650 | 1650 | |
| 1651 | + /* | |
| 1652 | + * SS devices are only visible to roothub after link training completes. | |
| 1653 | + * Keep polling roothubs for a grace period after xHC start | |
| 1654 | + */ | |
| 1655 | + if (xhci->run_graceperiod) { | |
| 1656 | + if (time_before(jiffies, xhci->run_graceperiod)) | |
| 1657 | + status = 1; | |
| 1658 | + else | |
| 1659 | + xhci->run_graceperiod = 0; | |
| 1660 | + } | |
| 1661 | + | |
| 1651 | 1662 | mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC | PORT_CEC; |
| 1652 | 1663 | |
| 1653 | 1664 | /* For each port, did anything change? If so, set that bit in buf. */ |
| @@ -425,7 +425,6 @@ static int check_fs_bus_bw(struct mu3h_sch_ep_info *sch_ep, int offset) · 424 unmodified lines | ||
| 425 | 425 | |
| 426 | 426 | static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset) |
| 427 | 427 | { |
| 428 | − u32 extra_cs_count; | |
| 429 | 428 | u32 start_ss, last_ss; |
| 430 | 429 | u32 start_cs, last_cs; |
| 431 | 430 | |
| @@ -461,18 +460,12 @@ static int check_sch_tt(struct mu3h_sch_ep_info *sch_ep, u32 offset) · 29 unmodified lines | ||
| 461 | 460 | if (last_cs > 7) |
| 462 | 461 | return -ESCH_CS_OVERFLOW; |
| 463 | 462 | |
| 464 | − if (sch_ep->ep_type == ISOC_IN_EP) | |
| 465 | − extra_cs_count = (last_cs == 7) ? 1 : 2; | |
| 466 | − else /* ep_type : INTR IN / INTR OUT */ | |
| 467 | − extra_cs_count = 1; | |
| 468 | − | |
| 469 | − cs_count += extra_cs_count; | |
| 470 | 463 | if (cs_count > 7) |
| 471 | 464 | cs_count = 7; /* HW limit */ |
| 472 | 465 | |
| 473 | 466 | sch_ep->cs_count = cs_count; |
| 474 | − /* one for ss, the other for idle */ | |
| 475 | − sch_ep->num_budget_microframes = cs_count + 2; | |
| 467 | + /* ss, idle are ignored */ | |
| 468 | + sch_ep->num_budget_microframes = cs_count; | |
| 476 | 469 | |
| 477 | 470 | /* |
| 478 | 471 | * if interval=1, maxp >752, num_budge_micoframe is larger |
| @@ -771,8 +764,8 @@ int xhci_mtk_drop_ep(struct usb_hcd *hcd, struct usb_device *udev, · 292 unmodified lines | ||
| 771 | 764 | if (ret) |
| 772 | 765 | return ret; |
| 773 | 766 | |
| 774 | − if (ep->hcpriv) | |
| 775 | − drop_ep_quirk(hcd, udev, ep); | |
| 767 | + /* needn't check @ep->hcpriv, xhci_endpoint_disable set it NULL */ | |
| 768 | + drop_ep_quirk(hcd, udev, ep); | |
| 776 | 769 | |
| 777 | 770 | return 0; |
| 778 | 771 | } |
| @@ -398,12 +398,17 @@ static int xhci_plat_remove(struct platform_device *dev) · 397 unmodified lines | ||
| 398 | 398 | pm_runtime_get_sync(&dev->dev); |
| 399 | 399 | xhci->xhc_state |= XHCI_STATE_REMOVING; |
| 400 | 400 | |
| 401 | − usb_remove_hcd(shared_hcd); | |
| 402 | − xhci->shared_hcd = NULL; | |
| 401 | + if (shared_hcd) { | |
| 402 | + usb_remove_hcd(shared_hcd); | |
| 403 | + xhci->shared_hcd = NULL; | |
| 404 | + } | |
| 405 | + | |
| 403 | 406 | usb_phy_shutdown(hcd->usb_phy); |
| 404 | 407 | |
| 405 | 408 | usb_remove_hcd(hcd); |
| 406 | − usb_put_hcd(shared_hcd); | |
| 409 | + | |
| 410 | + if (shared_hcd) | |
| 411 | + usb_put_hcd(shared_hcd); | |
| 407 | 412 | |
| 408 | 413 | clk_disable_unprepare(clk); |
| 409 | 414 | clk_disable_unprepare(reg_clk); |
| @@ -151,9 +151,11 @@ int xhci_start(struct xhci_hcd *xhci) · 150 unmodified lines | ||
| 151 | 151 | xhci_err(xhci, "Host took too long to start, " |
| 152 | 152 | "waited %u microseconds.\n", |
| 153 | 153 | XHCI_MAX_HALT_USEC); |
| 154 | − if (!ret) | |
| 154 | + if (!ret) { | |
| 155 | 155 | /* clear state flags. Including dying, halted or removing */ |
| 156 | 156 | xhci->xhc_state = 0; |
| 157 | + xhci->run_graceperiod = jiffies + msecs_to_jiffies(500); | |
| 158 | + } | |
| 157 | 159 | |
| 158 | 160 | return ret; |
| 159 | 161 | } |
| @@ -791,8 +793,6 @@ static void xhci_stop(struct usb_hcd *hcd) · 631 unmodified lines | ||
| 791 | 793 | void xhci_shutdown(struct usb_hcd *hcd) |
| 792 | 794 | { |
| 793 | 795 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
| 794 | − unsigned long flags; | |
| 795 | − int i; | |
| 796 | 796 | |
| 797 | 797 | if (xhci->quirks & XHCI_SPURIOUS_REBOOT) |
| 798 | 798 | usb_disable_xhci_ports(to_pci_dev(hcd->self.sysdev)); |
| @@ -808,21 +808,12 @@ void xhci_shutdown(struct usb_hcd *hcd) · 9 unmodified lines | ||
| 808 | 808 | del_timer_sync(&xhci->shared_hcd->rh_timer); |
| 809 | 809 | } |
| 810 | 810 | |
| 811 | − spin_lock_irqsave(&xhci->lock, flags); | |
| 811 | + spin_lock_irq(&xhci->lock); | |
| 812 | 812 | xhci_halt(xhci); |
| 813 | − | |
| 814 | − /* Power off USB2 ports*/ | |
| 815 | − for (i = 0; i < xhci->usb2_rhub.num_ports; i++) | |
| 816 | − xhci_set_port_power(xhci, xhci->main_hcd, i, false, &flags); | |
| 817 | − | |
| 818 | − /* Power off USB3 ports*/ | |
| 819 | − for (i = 0; i < xhci->usb3_rhub.num_ports; i++) | |
| 820 | − xhci_set_port_power(xhci, xhci->shared_hcd, i, false, &flags); | |
| 821 | − | |
| 822 | 813 | /* Workaround for spurious wakeups at shutdown with HSW */ |
| 823 | 814 | if (xhci->quirks & XHCI_SPURIOUS_WAKEUP) |
| 824 | 815 | xhci_reset(xhci, XHCI_RESET_SHORT_USEC); |
| 825 | − spin_unlock_irqrestore(&xhci->lock, flags); | |
| 816 | + spin_unlock_irq(&xhci->lock); | |
| 826 | 817 | |
| 827 | 818 | xhci_cleanup_msix(xhci); |
| 828 | 819 | |
| @@ -1826,7 +1826,7 @@ struct xhci_hcd { · 1825 unmodified lines | ||
| 1826 | 1826 | |
| 1827 | 1827 | /* Host controller watchdog timer structures */ |
| 1828 | 1828 | unsigned int xhc_state; |
| 1829 | − | |
| 1829 | + unsigned long run_graceperiod; | |
| 1830 | 1830 | u32 command; |
| 1831 | 1831 | struct s3_save s3; |
| 1832 | 1832 | /* Host controller is dying - not responding to commands. "I'm not dead yet!" |
| @@ -2196,8 +2196,6 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, · 363 unmodified lines | ||
| 2196 | 2196 | int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); |
| 2197 | 2197 | int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); |
| 2198 | 2198 | struct xhci_hub *xhci_get_rhub(struct usb_hcd *hcd); |
| 2199 | −void xhci_set_port_power(struct xhci_hcd *xhci, struct usb_hcd *hcd, u16 index, | |
| 2200 | − bool on, unsigned long *flags); | |
| 2201 | 2199 | |
| 2202 | 2200 | void xhci_hc_died(struct xhci_hcd *xhci); |
| 2203 | 2201 | |
| @@ -71,10 +71,7 @@ static int onboard_hub_power_off(struct onboard_hub *hub) · 70 unmodified lines | ||
| 71 | 71 | { |
| 72 | 72 | int err; |
| 73 | 73 | |
| 74 | − if (hub->reset_gpio) { | |
| 75 | − gpiod_set_value_cansleep(hub->reset_gpio, 1); | |
| 76 | − fsleep(hub->pdata->reset_us); | |
| 77 | − } | |
| 74 | + gpiod_set_value_cansleep(hub->reset_gpio, 1); | |
| 78 | 75 | |
| 79 | 76 | err = regulator_disable(hub->vdd); |
| 80 | 77 | if (err) { |
| @@ -86,7 +86,7 @@ config USB_MUSB_TUSB6010 · 85 unmodified lines | ||
| 86 | 86 | tristate "TUSB6010" |
| 87 | 87 | depends on HAS_IOMEM |
| 88 | 88 | depends on ARCH_OMAP2PLUS || COMPILE_TEST |
| 89 | − depends on NOP_USB_XCEIV = USB_MUSB_HDRC # both built-in or both modules | |
| 89 | + depends on NOP_USB_XCEIV!=m || USB_MUSB_HDRC=m | |
| 90 | 90 | |
| 91 | 91 | config USB_MUSB_OMAP2PLUS |
| 92 | 92 | tristate "OMAP2430 and onwards" |
| @@ -97,7 +97,10 @@ struct ch341_private { · 96 unmodified lines | ||
| 97 | 97 | u8 mcr; |
| 98 | 98 | u8 msr; |
| 99 | 99 | u8 lcr; |
| 100 | + | |
| 100 | 101 | unsigned long quirks; |
| 102 | + u8 version; | |
| 103 | + | |
| 101 | 104 | unsigned long break_end; |
| 102 | 105 | }; |
| 103 | 106 | |
| @@ -250,8 +253,12 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev, · 146 unmodified lines | ||
| 250 | 253 | /* |
| 251 | 254 | * CH341A buffers data until a full endpoint-size packet (32 bytes) |
| 252 | 255 | * has been received unless bit 7 is set. |
| 256 | + * | |
| 257 | + * At least one device with version 0x27 appears to have this bit | |
| 258 | + * inverted. | |
| 253 | 259 | */ |
| 254 | − val |= BIT(7); | |
| 260 | + if (priv->version > 0x27) | |
| 261 | + val |= BIT(7); | |
| 255 | 262 | |
| 256 | 263 | r = ch341_control_out(dev, CH341_REQ_WRITE_REG, |
| 257 | 264 | CH341_REG_DIVISOR << 8 | CH341_REG_PRESCALER, |
| @@ -265,6 +272,9 @@ static int ch341_set_baudrate_lcr(struct usb_device *dev, · 7 unmodified lines | ||
| 265 | 272 | * (stop bits, parity and word length). Version 0x30 and above use |
| 266 | 273 | * CH341_REG_LCR only and CH341_REG_LCR2 is always set to zero. |
| 267 | 274 | */ |
| 275 | + if (priv->version < 0x30) | |
| 276 | + return 0; | |
| 277 | + | |
| 268 | 278 | r = ch341_control_out(dev, CH341_REQ_WRITE_REG, |
| 269 | 279 | CH341_REG_LCR2 << 8 | CH341_REG_LCR, lcr); |
| 270 | 280 | if (r) |
| @@ -308,7 +318,9 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) · 37 unmodified lines | ||
| 308 | 318 | r = ch341_control_in(dev, CH341_REQ_READ_VERSION, 0, 0, buffer, size); |
| 309 | 319 | if (r) |
| 310 | 320 | return r; |
| 311 | − dev_dbg(&dev->dev, "Chip version: 0x%02x\n", buffer[0]); | |
| 321 | + | |
| 322 | + priv->version = buffer[0]; | |
| 323 | + dev_dbg(&dev->dev, "Chip version: 0x%02x\n", priv->version); | |
| 312 | 324 | |
| 313 | 325 | r = ch341_control_out(dev, CH341_REQ_SERIAL_INIT, 0, 0); |
| 314 | 326 | if (r < 0) |
| @@ -130,6 +130,7 @@ static const struct usb_device_id id_table[] = { · 129 unmodified lines | ||
| 130 | 130 | { USB_DEVICE(0x10C4, 0x83AA) }, /* Mark-10 Digital Force Gauge */ |
| 131 | 131 | { USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */ |
| 132 | 132 | { USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */ |
| 133 | + { USB_DEVICE(0x10C4, 0x8414) }, /* Decagon USB Cable Adapter */ | |
| 133 | 134 | { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */ |
| 134 | 135 | { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ |
| 135 | 136 | { USB_DEVICE(0x10C4, 0x8470) }, /* Juniper Networks BX Series System Console */ |
| @@ -1045,6 +1045,8 @@ static const struct usb_device_id id_table_combined[] = { · 1044 unmodified lines | ||
| 1045 | 1045 | /* IDS GmbH devices */ |
| 1046 | 1046 | { USB_DEVICE(IDS_VID, IDS_SI31A_PID) }, |
| 1047 | 1047 | { USB_DEVICE(IDS_VID, IDS_CM31A_PID) }, |
| 1048 | + /* Omron devices */ | |
| 1049 | + { USB_DEVICE(OMRON_VID, OMRON_CS1W_CIF31_PID) }, | |
| 1048 | 1050 | /* U-Blox devices */ |
| 1049 | 1051 | { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ZED_PID) }, |
| 1050 | 1052 | { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) }, |
| @@ -661,6 +661,12 @@ · 660 unmodified lines | ||
| 661 | 661 | #define INFINEON_TRIBOARD_TC1798_PID 0x0028 /* DAS JTAG TriBoard TC1798 V1.0 */ |
| 662 | 662 | #define INFINEON_TRIBOARD_TC2X7_PID 0x0043 /* DAS JTAG TriBoard TC2X7 V1.0 */ |
| 663 | 663 | |
| 664 | +/* | |
| 665 | + * Omron corporation (https://www.omron.com) | |
| 666 | + */ | |
| 667 | + #define OMRON_VID 0x0590 | |
| 668 | + #define OMRON_CS1W_CIF31_PID 0x00b2 | |
| 669 | + | |
| 664 | 670 | /* |
| 665 | 671 | * Acton Research Corp. |
| 666 | 672 | */ |
| @@ -253,6 +253,7 @@ static void option_instat_callback(struct urb *urb); · 252 unmodified lines | ||
| 253 | 253 | #define QUECTEL_PRODUCT_BG96 0x0296 |
| 254 | 254 | #define QUECTEL_PRODUCT_EP06 0x0306 |
| 255 | 255 | #define QUECTEL_PRODUCT_EM05G 0x030a |
| 256 | +#define QUECTEL_PRODUCT_EM060K 0x030b | |
| 256 | 257 | #define QUECTEL_PRODUCT_EM12 0x0512 |
| 257 | 258 | #define QUECTEL_PRODUCT_RM500Q 0x0800 |
| 258 | 259 | #define QUECTEL_PRODUCT_EC200S_CN 0x6002 |
| @@ -438,6 +439,8 @@ static void option_instat_callback(struct urb *urb); · 179 unmodified lines | ||
| 438 | 439 | #define CINTERION_PRODUCT_MV31_2_RMNET 0x00b9 |
| 439 | 440 | #define CINTERION_PRODUCT_MV32_WA 0x00f1 |
| 440 | 441 | #define CINTERION_PRODUCT_MV32_WB 0x00f2 |
| 442 | +#define CINTERION_PRODUCT_MV32_WA_RMNET 0x00f3 | |
| 443 | +#define CINTERION_PRODUCT_MV32_WB_RMNET 0x00f4 | |
| 441 | 444 | |
| 442 | 445 | /* Olivetti products */ |
| 443 | 446 | #define OLIVETTI_VENDOR_ID 0x0b3c |
| @@ -573,6 +576,10 @@ static void option_instat_callback(struct urb *urb); · 129 unmodified lines | ||
| 573 | 576 | #define WETELECOM_PRODUCT_6802 0x6802 |
| 574 | 577 | #define WETELECOM_PRODUCT_WMD300 0x6803 |
| 575 | 578 | |
| 579 | +/* OPPO products */ | |
| 580 | +#define OPPO_VENDOR_ID 0x22d9 | |
| 581 | +#define OPPO_PRODUCT_R11 0x276c | |
| 582 | + | |
| 576 | 583 | |
| 577 | 584 | /* Device flags */ |
| 578 | 585 | |
| @@ -1138,6 +1145,9 @@ static const struct usb_device_id option_ids[] = { · 559 unmodified lines | ||
| 1138 | 1145 | { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EP06, 0xff, 0, 0) }, |
| 1139 | 1146 | { USB_DEVICE_INTERFACE_CLASS(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM05G, 0xff), |
| 1140 | 1147 | .driver_info = RSVD(6) | ZLP }, |
| 1148 | + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) }, | |
| 1149 | + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x30) }, | |
| 1150 | + { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x40) }, | |
| 1141 | 1151 | { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0xff, 0xff), |
| 1142 | 1152 | .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 }, |
| 1143 | 1153 | { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) }, |
| @@ -1993,8 +2003,12 @@ static const struct usb_device_id option_ids[] = { · 849 unmodified lines | ||
| 1993 | 2003 | .driver_info = RSVD(0)}, |
| 1994 | 2004 | { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA, 0xff), |
| 1995 | 2005 | .driver_info = RSVD(3)}, |
| 2006 | + { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WA_RMNET, 0xff), | |
| 2007 | + .driver_info = RSVD(0) }, | |
| 1996 | 2008 | { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB, 0xff), |
| 1997 | 2009 | .driver_info = RSVD(3)}, |
| 2010 | + { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_MV32_WB_RMNET, 0xff), | |
| 2011 | + .driver_info = RSVD(0) }, | |
| 1998 | 2012 | { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100), |
| 1999 | 2013 | .driver_info = RSVD(4) }, |
| 2000 | 2014 | { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD120), |
| @@ -2155,6 +2169,7 @@ static const struct usb_device_id option_ids[] = { · 154 unmodified lines | ||
| 2155 | 2169 | { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ |
| 2156 | 2170 | { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */ |
| 2157 | 2171 | { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1406, 0xff) }, /* GosunCn GM500 ECM/NCM */ |
| 2172 | + { USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) }, | |
| 2158 | 2173 | { } /* Terminating entry */ |
| 2159 | 2174 | }; |
| 2160 | 2175 | MODULE_DEVICE_TABLE(usb, option_ids); |
| @@ -2294,6 +2294,13 @@ UNUSUAL_DEV( 0x1e74, 0x4621, 0x0000, 0x0000, · 2293 unmodified lines | ||
| 2294 | 2294 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, |
| 2295 | 2295 | US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ), |
| 2296 | 2296 | |
| 2297 | +/* Reported by Witold Lipieta <witold.lipieta@thaumatec.com> */ | |
| 2298 | +UNUSUAL_DEV( 0x1fc9, 0x0117, 0x0100, 0x0100, | |
| 2299 | + "NXP Semiconductors", | |
| 2300 | + "PN7462AU", | |
| 2301 | + USB_SC_DEVICE, USB_PR_DEVICE, NULL, | |
| 2302 | + US_FL_IGNORE_RESIDUE ), | |
| 2303 | + | |
| 2297 | 2304 | /* Supplied with some Castlewood ORB removable drives */ |
| 2298 | 2305 | UNUSUAL_DEV( 0x2027, 0xa001, 0x0000, 0x9999, |
| 2299 | 2306 | "Double-H Technology", |
| @@ -62,6 +62,13 @@ UNUSUAL_DEV(0x0984, 0x0301, 0x0128, 0x0128, · 61 unmodified lines | ||
| 62 | 62 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, |
| 63 | 63 | US_FL_IGNORE_UAS), |
| 64 | 64 | |
| 65 | +/* Reported-by: Tom Hu <huxiaoying@kylinos.cn> */ | |
| 66 | +UNUSUAL_DEV(0x0b05, 0x1932, 0x0000, 0x9999, | |
| 67 | + "ASUS", | |
| 68 | + "External HDD", | |
| 69 | + USB_SC_DEVICE, USB_PR_DEVICE, NULL, | |
| 70 | + US_FL_IGNORE_UAS), | |
| 71 | + | |
| 65 | 72 | /* Reported-by: David Webb <djw@noc.ac.uk> */ |
| 66 | 73 | UNUSUAL_DEV(0x0bc2, 0x331a, 0x0000, 0x9999, |
| 67 | 74 | "Seagate", |
| @@ -99,8 +99,8 @@ static int dp_altmode_configure(struct dp_altmode *dp, u8 con) · 98 unmodified lines | ||
| 99 | 99 | case DP_STATUS_CON_UFP_D: |
| 100 | 100 | case DP_STATUS_CON_BOTH: /* NOTE: First acting as DP source */ |
| 101 | 101 | conf |= DP_CONF_UFP_U_AS_UFP_D; |
| 102 | − pin_assign = DP_CAP_DFP_D_PIN_ASSIGN(dp->alt->vdo) & | |
| 103 | − DP_CAP_UFP_D_PIN_ASSIGN(dp->port->vdo); | |
| 102 | + pin_assign = DP_CAP_PIN_ASSIGN_UFP_D(dp->alt->vdo) & | |
| 103 | + DP_CAP_PIN_ASSIGN_DFP_D(dp->port->vdo); | |
| 104 | 104 | break; |
| 105 | 105 | default: |
| 106 | 106 | break; |
| @@ -2346,6 +2346,7 @@ static void __exit typec_exit(void) · 2345 unmodified lines | ||
| 2346 | 2346 | ida_destroy(&typec_index_ida); |
| 2347 | 2347 | bus_unregister(&typec_bus); |
| 2348 | 2348 | class_unregister(&typec_mux_class); |
| 2349 | + class_unregister(&retimer_class); | |
| 2349 | 2350 | } |
| 2350 | 2351 | module_exit(typec_exit); |
| 2351 | 2352 | |
| @@ -571,9 +571,11 @@ err_unregister_switch: · 570 unmodified lines | ||
| 571 | 571 | |
| 572 | 572 | static int is_memory(struct acpi_resource *res, void *data) |
| 573 | 573 | { |
| 574 | − struct resource r; | |
| 574 | + struct resource_win win = {}; | |
| 575 | + struct resource *r = &win.res; | |
| 575 | 576 | |
| 576 | − return !acpi_dev_resource_memory(res, &r); | |
| 577 | + return !(acpi_dev_resource_memory(res, r) || | |
| 578 | + acpi_dev_resource_address_space(res, &win)); | |
| 577 | 579 | } |
| 578 | 580 | |
| 579 | 581 | /* IOM ACPI IDs and IOM_PORT_STATUS_OFFSET */ |
| @@ -583,6 +585,9 @@ static const struct acpi_device_id iom_acpi_ids[] = { · 3 unmodified lines | ||
| 583 | 585 | |
| 584 | 586 | /* AlderLake */ |
| 585 | 587 | { "INTC1079", 0x160, }, |
| 588 | + | |
| 589 | + /* Meteor Lake */ | |
| 590 | + { "INTC107A", 0x160, }, | |
| 586 | 591 | {} |
| 587 | 592 | }; |
| 588 | 593 | |
| @@ -6320,6 +6320,13 @@ static int tcpm_psy_set_prop(struct power_supply *psy, · 6319 unmodified lines | ||
| 6320 | 6320 | struct tcpm_port *port = power_supply_get_drvdata(psy); |
| 6321 | 6321 | int ret; |
| 6322 | 6322 | |
| 6323 | + /* | |
| 6324 | + * All the properties below are related to USB PD. The check needs to be | |
| 6325 | + * property specific when a non-pd related property is added. | |
| 6326 | + */ | |
| 6327 | + if (!port->pd_supported) | |
| 6328 | + return -EOPNOTSUPP; | |
| 6329 | + | |
| 6323 | 6330 | switch (psp) { |
| 6324 | 6331 | case POWER_SUPPLY_PROP_ONLINE: |
| 6325 | 6332 | ret = tcpm_psy_set_online(port, val); |
| @@ -1200,32 +1200,6 @@ out_unlock: · 1199 unmodified lines | ||
| 1200 | 1200 | return ret; |
| 1201 | 1201 | } |
| 1202 | 1202 | |
| 1203 | −static void ucsi_unregister_connectors(struct ucsi *ucsi) | |
| 1204 | −{ | |
| 1205 | − struct ucsi_connector *con; | |
| 1206 | − int i; | |
| 1207 | − | |
| 1208 | − if (!ucsi->connector) | |
| 1209 | − return; | |
| 1210 | − | |
| 1211 | − for (i = 0; i < ucsi->cap.num_connectors; i++) { | |
| 1212 | − con = &ucsi->connector[i]; | |
| 1213 | − | |
| 1214 | − if (!con->wq) | |
| 1215 | − break; | |
| 1216 | − | |
| 1217 | − cancel_work_sync(&con->work); | |
| 1218 | − ucsi_unregister_partner(con); | |
| 1219 | − ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON); | |
| 1220 | − ucsi_unregister_port_psy(con); | |
| 1221 | − destroy_workqueue(con->wq); | |
| 1222 | − typec_unregister_port(con->port); | |
| 1223 | − } | |
| 1224 | − | |
| 1225 | − kfree(ucsi->connector); | |
| 1226 | − ucsi->connector = NULL; | |
| 1227 | −} | |
| 1228 | − | |
| 1229 | 1203 | /** |
| 1230 | 1204 | * ucsi_init - Initialize UCSI interface |
| 1231 | 1205 | * @ucsi: UCSI to be initialized |
| @@ -1234,6 +1208,7 @@ static void ucsi_unregister_connectors(struct ucsi *ucsi) · 2 unmodified lines | ||
| 1234 | 1208 | */ |
| 1235 | 1209 | static int ucsi_init(struct ucsi *ucsi) |
| 1236 | 1210 | { |
| 1211 | + struct ucsi_connector *con; | |
| 1237 | 1212 | u64 command; |
| 1238 | 1213 | int ret; |
| 1239 | 1214 | int i; |
| @@ -1264,7 +1239,7 @@ static int ucsi_init(struct ucsi *ucsi) · 24 unmodified lines | ||
| 1264 | 1239 | } |
| 1265 | 1240 | |
| 1266 | 1241 | /* Allocate the connectors. Released in ucsi_unregister() */ |
| 1267 | − ucsi->connector = kcalloc(ucsi->cap.num_connectors, | |
| 1242 | + ucsi->connector = kcalloc(ucsi->cap.num_connectors + 1, | |
| 1268 | 1243 | sizeof(*ucsi->connector), GFP_KERNEL); |
| 1269 | 1244 | if (!ucsi->connector) { |
| 1270 | 1245 | ret = -ENOMEM; |
| @@ -1288,7 +1263,15 @@ static int ucsi_init(struct ucsi *ucsi) · 17 unmodified lines | ||
| 1288 | 1263 | return 0; |
| 1289 | 1264 | |
| 1290 | 1265 | err_unregister: |
| 1291 | − ucsi_unregister_connectors(ucsi); | |
| 1266 | + for (con = ucsi->connector; con->port; con++) { | |
| 1267 | + ucsi_unregister_partner(con); | |
| 1268 | + ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON); | |
| 1269 | + ucsi_unregister_port_psy(con); | |
| 1270 | + if (con->wq) | |
| 1271 | + destroy_workqueue(con->wq); | |
| 1272 | + typec_unregister_port(con->port); | |
| 1273 | + con->port = NULL; | |
| 1274 | + } | |
| 1292 | 1275 | |
| 1293 | 1276 | err_reset: |
| 1294 | 1277 | memset(&ucsi->cap, 0, sizeof(ucsi->cap)); |
| @@ -1402,6 +1385,7 @@ EXPORT_SYMBOL_GPL(ucsi_register); · 107 unmodified lines | ||
| 1402 | 1385 | void ucsi_unregister(struct ucsi *ucsi) |
| 1403 | 1386 | { |
| 1404 | 1387 | u64 cmd = UCSI_SET_NOTIFICATION_ENABLE; |
| 1388 | + int i; | |
| 1405 | 1389 | |
| 1406 | 1390 | /* Make sure that we are not in the middle of driver initialization */ |
| 1407 | 1391 | cancel_delayed_work_sync(&ucsi->work); |
| @@ -1409,7 +1393,18 @@ void ucsi_unregister(struct ucsi *ucsi) · 1 unmodified line | ||
| 1409 | 1393 | /* Disable notifications */ |
| 1410 | 1394 | ucsi->ops->async_write(ucsi, UCSI_CONTROL, &cmd, sizeof(cmd)); |
| 1411 | 1395 | |
| 1412 | − ucsi_unregister_connectors(ucsi); | |
| 1396 | + for (i = 0; i < ucsi->cap.num_connectors; i++) { | |
| 1397 | + cancel_work_sync(&ucsi->connector[i].work); | |
| 1398 | + ucsi_unregister_partner(&ucsi->connector[i]); | |
| 1399 | + ucsi_unregister_altmodes(&ucsi->connector[i], | |
| 1400 | + UCSI_RECIPIENT_CON); | |
| 1401 | + ucsi_unregister_port_psy(&ucsi->connector[i]); | |
| 1402 | + if (ucsi->connector[i].wq) | |
| 1403 | + destroy_workqueue(ucsi->connector[i].wq); | |
| 1404 | + typec_unregister_port(ucsi->connector[i].port); | |
| 1405 | + } | |
| 1406 | + | |
| 1407 | + kfree(ucsi->connector); | |
| 1413 | 1408 | } |
| 1414 | 1409 | EXPORT_SYMBOL_GPL(ucsi_unregister); |
| 1415 | 1410 | |
| @@ -575,6 +575,7 @@ struct usb3_lpm_parameters { · 574 unmodified lines | ||
| 575 | 575 | * @devaddr: device address, XHCI: assigned by HW, others: same as devnum |
| 576 | 576 | * @can_submit: URBs may be submitted |
| 577 | 577 | * @persist_enabled: USB_PERSIST enabled for this device |
| 578 | + * @reset_in_progress: the device is being reset | |
| 578 | 579 | * @have_langid: whether string_langid is valid |
| 579 | 580 | * @authorized: policy has said we can use it; |
| 580 | 581 | * (user space) policy determines if we authorize this device to be |
| @@ -662,6 +663,7 @@ struct usb_device { · 81 unmodified lines | ||
| 662 | 663 | |
| 663 | 664 | unsigned can_submit:1; |
| 664 | 665 | unsigned persist_enabled:1; |
| 666 | + unsigned reset_in_progress:1; | |
| 665 | 667 | unsigned have_langid:1; |
| 666 | 668 | unsigned authorized:1; |
| 667 | 669 | unsigned authenticated:1; |
| @@ -73,6 +73,11 @@ enum { · 72 unmodified lines | ||
| 73 | 73 | #define DP_CAP_USB BIT(7) |
| 74 | 74 | #define DP_CAP_DFP_D_PIN_ASSIGN(_cap_) (((_cap_) & GENMASK(15, 8)) >> 8) |
| 75 | 75 | #define DP_CAP_UFP_D_PIN_ASSIGN(_cap_) (((_cap_) & GENMASK(23, 16)) >> 16) |
| 76 | +/* Get pin assignment taking plug & receptacle into consideration */ | |
| 77 | +#define DP_CAP_PIN_ASSIGN_UFP_D(_cap_) ((_cap_ & DP_CAP_RECEPTACLE) ? \ | |
| 78 | + DP_CAP_UFP_D_PIN_ASSIGN(_cap_) : DP_CAP_DFP_D_PIN_ASSIGN(_cap_)) | |
| 79 | +#define DP_CAP_PIN_ASSIGN_DFP_D(_cap_) ((_cap_ & DP_CAP_RECEPTACLE) ? \ | |
| 80 | + DP_CAP_DFP_D_PIN_ASSIGN(_cap_) : DP_CAP_UFP_D_PIN_ASSIGN(_cap_)) | |
| 76 | 81 | |
| 77 | 82 | /* DisplayPort Status Update VDO bits */ |
| 78 | 83 | #define DP_STATUS_CONNECTION(_status_) ((_status_) & 3) |