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.9-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb

Pull USB driver fixes from Greg KH:
"Here are some small USB driver fixes for reported problems for
6.9-rc7. Included in here are:

- usb core fixes for found issues

- typec driver fixes for reported problems

- usb gadget driver fixes for reported problems

- xhci build fixes

- dwc3 driver fixes for reported issues

All of these have been in linux-next this past week with no reported
problems"

* tag 'usb-6.9-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
usb: typec: tcpm: Check for port partner validity before consuming it
usb: typec: tcpm: enforce ready state when queueing alt mode vdm
usb: typec: tcpm: unregister existing source caps before re-registration
usb: typec: tcpm: clear pd_event queue in PORT_RESET
usb: typec: tcpm: queue correct sop type in tcpm_queue_vdm_unlocked
usb: Fix regression caused by invalid ep0 maxpacket in virtual SuperSpeed device
usb: ohci: Prevent missed ohci interrupts
usb: typec: qcom-pmic: fix pdphy start() error handling
usb: typec: qcom-pmic: fix use-after-free on late probe errors
usb: gadget: f_fs: Fix a race condition when processing setup packets.
USB: core: Fix access violation during port device removal
usb: dwc3: core: Prevent phy suspend during init
usb: xhci-plat: Don't include xhci.h
usb: gadget: uvc: use correct buffer size when parsing configfs lists
usb: gadget: composite: fix OS descriptors w_value logic
usb: gadget: f_fs: Fix race between aio_cancel() and AIO request complete

+147 -79
+3 -2
drivers/usb/core/hub.c
··· 5110 5110 } 5111 5111 if (usb_endpoint_maxp(&udev->ep0.desc) == i) { 5112 5112 ; /* Initial ep0 maxpacket guess is right */ 5113 - } else if ((udev->speed == USB_SPEED_FULL || 5113 + } else if (((udev->speed == USB_SPEED_FULL || 5114 5114 udev->speed == USB_SPEED_HIGH) && 5115 - (i == 8 || i == 16 || i == 32 || i == 64)) { 5115 + (i == 8 || i == 16 || i == 32 || i == 64)) || 5116 + (udev->speed >= USB_SPEED_SUPER && i > 0)) { 5116 5117 /* Initial guess is wrong; use the descriptor's value */ 5117 5118 if (udev->speed == USB_SPEED_FULL) 5118 5119 dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
+6 -2
drivers/usb/core/port.c
··· 51 51 struct usb_port *port_dev = to_usb_port(dev); 52 52 struct usb_device *hdev = to_usb_device(dev->parent->parent); 53 53 struct usb_hub *hub = usb_hub_to_struct_hub(hdev); 54 - struct usb_interface *intf = to_usb_interface(hub->intfdev); 54 + struct usb_interface *intf = to_usb_interface(dev->parent); 55 55 int port1 = port_dev->portnum; 56 56 u16 portstatus, unused; 57 57 bool disabled; 58 58 int rc; 59 59 struct kernfs_node *kn; 60 60 61 + if (!hub) 62 + return -ENODEV; 61 63 hub_get(hub); 62 64 rc = usb_autopm_get_interface(intf); 63 65 if (rc < 0) ··· 103 101 struct usb_port *port_dev = to_usb_port(dev); 104 102 struct usb_device *hdev = to_usb_device(dev->parent->parent); 105 103 struct usb_hub *hub = usb_hub_to_struct_hub(hdev); 106 - struct usb_interface *intf = to_usb_interface(hub->intfdev); 104 + struct usb_interface *intf = to_usb_interface(dev->parent); 107 105 int port1 = port_dev->portnum; 108 106 bool disabled; 109 107 int rc; 110 108 struct kernfs_node *kn; 111 109 110 + if (!hub) 111 + return -ENODEV; 112 112 rc = kstrtobool(buf, &disabled); 113 113 if (rc) 114 114 return rc;
+38 -52
drivers/usb/dwc3/core.c
··· 104 104 return 0; 105 105 } 106 106 107 + void dwc3_enable_susphy(struct dwc3 *dwc, bool enable) 108 + { 109 + u32 reg; 110 + 111 + reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 112 + if (enable && !dwc->dis_u3_susphy_quirk) 113 + reg |= DWC3_GUSB3PIPECTL_SUSPHY; 114 + else 115 + reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 116 + 117 + dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 118 + 119 + reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 120 + if (enable && !dwc->dis_u2_susphy_quirk) 121 + reg |= DWC3_GUSB2PHYCFG_SUSPHY; 122 + else 123 + reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 124 + 125 + dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 126 + } 127 + 107 128 void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode) 108 129 { 109 130 u32 reg; ··· 606 585 */ 607 586 static int dwc3_phy_setup(struct dwc3 *dwc) 608 587 { 609 - unsigned int hw_mode; 610 588 u32 reg; 611 - 612 - hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); 613 589 614 590 reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 615 591 ··· 617 599 reg &= ~DWC3_GUSB3PIPECTL_UX_EXIT_PX; 618 600 619 601 /* 620 - * Above 1.94a, it is recommended to set DWC3_GUSB3PIPECTL_SUSPHY 621 - * to '0' during coreConsultant configuration. So default value 622 - * will be '0' when the core is reset. Application needs to set it 623 - * to '1' after the core initialization is completed. 602 + * Above DWC_usb3.0 1.94a, it is recommended to set 603 + * DWC3_GUSB3PIPECTL_SUSPHY to '0' during coreConsultant configuration. 604 + * So default value will be '0' when the core is reset. Application 605 + * needs to set it to '1' after the core initialization is completed. 606 + * 607 + * Similarly for DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be 608 + * cleared after power-on reset, and it can be set after core 609 + * initialization. 624 610 */ 625 - if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) 626 - reg |= DWC3_GUSB3PIPECTL_SUSPHY; 627 - 628 - /* 629 - * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE must be cleared after 630 - * power-on reset, and it can be set after core initialization, which is 631 - * after device soft-reset during initialization. 632 - */ 633 - if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD) 634 - reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 611 + reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 635 612 636 613 if (dwc->u2ss_inp3_quirk) 637 614 reg |= DWC3_GUSB3PIPECTL_U2SSINP3OK; ··· 651 638 652 639 if (dwc->tx_de_emphasis_quirk) 653 640 reg |= DWC3_GUSB3PIPECTL_TX_DEEPH(dwc->tx_de_emphasis); 654 - 655 - if (dwc->dis_u3_susphy_quirk) 656 - reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; 657 641 658 642 if (dwc->dis_del_phy_power_chg_quirk) 659 643 reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE; ··· 699 689 } 700 690 701 691 /* 702 - * Above 1.94a, it is recommended to set DWC3_GUSB2PHYCFG_SUSPHY to 703 - * '0' during coreConsultant configuration. So default value will 704 - * be '0' when the core is reset. Application needs to set it to 705 - * '1' after the core initialization is completed. 692 + * Above DWC_usb3.0 1.94a, it is recommended to set 693 + * DWC3_GUSB2PHYCFG_SUSPHY to '0' during coreConsultant configuration. 694 + * So default value will be '0' when the core is reset. Application 695 + * needs to set it to '1' after the core initialization is completed. 696 + * 697 + * Similarly for DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared 698 + * after power-on reset, and it can be set after core initialization. 706 699 */ 707 - if (!DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) 708 - reg |= DWC3_GUSB2PHYCFG_SUSPHY; 709 - 710 - /* 711 - * For DRD controllers, GUSB2PHYCFG.SUSPHY must be cleared after 712 - * power-on reset, and it can be set after core initialization, which is 713 - * after device soft-reset during initialization. 714 - */ 715 - if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD) 716 - reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 717 - 718 - if (dwc->dis_u2_susphy_quirk) 719 - reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 700 + reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; 720 701 721 702 if (dwc->dis_enblslpm_quirk) 722 703 reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; ··· 1227 1226 ret = dwc3_core_soft_reset(dwc); 1228 1227 if (ret) 1229 1228 goto err_exit_phy; 1230 - 1231 - if (hw_mode == DWC3_GHWPARAMS0_MODE_DRD && 1232 - !DWC3_VER_IS_WITHIN(DWC3, ANY, 194A)) { 1233 - if (!dwc->dis_u3_susphy_quirk) { 1234 - reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)); 1235 - reg |= DWC3_GUSB3PIPECTL_SUSPHY; 1236 - dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg); 1237 - } 1238 - 1239 - if (!dwc->dis_u2_susphy_quirk) { 1240 - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); 1241 - reg |= DWC3_GUSB2PHYCFG_SUSPHY; 1242 - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); 1243 - } 1244 - } 1245 1229 1246 1230 dwc3_core_setup_global_control(dwc); 1247 1231 dwc3_core_num_eps(dwc);
+1
drivers/usb/dwc3/core.h
··· 1580 1580 void dwc3_event_buffers_cleanup(struct dwc3 *dwc); 1581 1581 1582 1582 int dwc3_core_soft_reset(struct dwc3 *dwc); 1583 + void dwc3_enable_susphy(struct dwc3 *dwc, bool enable); 1583 1584 1584 1585 #if IS_ENABLED(CONFIG_USB_DWC3_HOST) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE) 1585 1586 int dwc3_host_init(struct dwc3 *dwc);
+2
drivers/usb/dwc3/gadget.c
··· 2924 2924 dwc3_ep0_out_start(dwc); 2925 2925 2926 2926 dwc3_gadget_enable_irq(dwc); 2927 + dwc3_enable_susphy(dwc, true); 2927 2928 2928 2929 return 0; 2929 2930 ··· 4691 4690 if (!dwc->gadget) 4692 4691 return; 4693 4692 4693 + dwc3_enable_susphy(dwc, false); 4694 4694 usb_del_gadget(dwc->gadget); 4695 4695 dwc3_gadget_free_endpoints(dwc); 4696 4696 usb_put_gadget(dwc->gadget);
+27
drivers/usb/dwc3/host.c
··· 10 10 #include <linux/irq.h> 11 11 #include <linux/of.h> 12 12 #include <linux/platform_device.h> 13 + #include <linux/usb.h> 14 + #include <linux/usb/hcd.h> 13 15 14 16 #include "../host/xhci-port.h" 15 17 #include "../host/xhci-ext-caps.h" 16 18 #include "../host/xhci-caps.h" 19 + #include "../host/xhci-plat.h" 17 20 #include "core.h" 18 21 19 22 #define XHCI_HCSPARAMS1 0x4 ··· 59 56 dev_err(dwc->dev, "xhci base reg invalid\n"); 60 57 } 61 58 } 59 + 60 + static void dwc3_xhci_plat_start(struct usb_hcd *hcd) 61 + { 62 + struct platform_device *pdev; 63 + struct dwc3 *dwc; 64 + 65 + if (!usb_hcd_is_primary_hcd(hcd)) 66 + return; 67 + 68 + pdev = to_platform_device(hcd->self.controller); 69 + dwc = dev_get_drvdata(pdev->dev.parent); 70 + 71 + dwc3_enable_susphy(dwc, true); 72 + } 73 + 74 + static const struct xhci_plat_priv dwc3_xhci_plat_quirk = { 75 + .plat_start = dwc3_xhci_plat_start, 76 + }; 62 77 63 78 static void dwc3_host_fill_xhci_irq_res(struct dwc3 *dwc, 64 79 int irq, char *name) ··· 188 167 } 189 168 } 190 169 170 + ret = platform_device_add_data(xhci, &dwc3_xhci_plat_quirk, 171 + sizeof(struct xhci_plat_priv)); 172 + if (ret) 173 + goto err; 174 + 191 175 ret = platform_device_add(xhci); 192 176 if (ret) { 193 177 dev_err(dwc->dev, "failed to register xHCI device\n"); ··· 218 192 if (dwc->sys_wakeup) 219 193 device_init_wakeup(&dwc->xhci->dev, false); 220 194 195 + dwc3_enable_susphy(dwc, false); 221 196 platform_device_unregister(dwc->xhci); 222 197 dwc->xhci = NULL; 223 198 }
+3 -3
drivers/usb/gadget/composite.c
··· 2112 2112 buf[5] = 0x01; 2113 2113 switch (ctrl->bRequestType & USB_RECIP_MASK) { 2114 2114 case USB_RECIP_DEVICE: 2115 - if (w_index != 0x4 || (w_value >> 8)) 2115 + if (w_index != 0x4 || (w_value & 0xff)) 2116 2116 break; 2117 2117 buf[6] = w_index; 2118 2118 /* Number of ext compat interfaces */ ··· 2128 2128 } 2129 2129 break; 2130 2130 case USB_RECIP_INTERFACE: 2131 - if (w_index != 0x5 || (w_value >> 8)) 2131 + if (w_index != 0x5 || (w_value & 0xff)) 2132 2132 break; 2133 - interface = w_value & 0xFF; 2133 + interface = w_value >> 8; 2134 2134 if (interface >= MAX_CONFIG_INTERFACES || 2135 2135 !os_desc_cfg->interface[interface]) 2136 2136 break;
+7 -2
drivers/usb/gadget/function/f_fs.c
··· 852 852 work); 853 853 int ret = io_data->status; 854 854 bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD; 855 + unsigned long flags; 855 856 856 857 if (io_data->read && ret > 0) { 857 858 kthread_use_mm(io_data->mm); ··· 864 863 865 864 if (io_data->ffs->ffs_eventfd && !kiocb_has_eventfd) 866 865 eventfd_signal(io_data->ffs->ffs_eventfd); 866 + 867 + spin_lock_irqsave(&io_data->ffs->eps_lock, flags); 868 + usb_ep_free_request(io_data->ep, io_data->req); 869 + io_data->req = NULL; 870 + spin_unlock_irqrestore(&io_data->ffs->eps_lock, flags); 867 871 868 872 if (io_data->read) 869 873 kfree(io_data->to_free); ··· 883 877 struct ffs_data *ffs = io_data->ffs; 884 878 885 879 io_data->status = req->status ? req->status : req->actual; 886 - usb_ep_free_request(_ep, req); 887 880 888 881 INIT_WORK(&io_data->work, ffs_user_copy_worker); 889 882 queue_work(ffs->io_completion_wq, &io_data->work); ··· 3811 3806 __ffs_event_add(ffs, FUNCTIONFS_SETUP); 3812 3807 spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags); 3813 3808 3814 - return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0; 3809 + return ffs->ev.setup.wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0; 3815 3810 } 3816 3811 3817 3812 static bool ffs_func_req_match(struct usb_function *f,
+2 -2
drivers/usb/gadget/function/uvc_configfs.c
··· 92 92 93 93 while (pg - page < len) { 94 94 i = 0; 95 - while (i < sizeof(buf) && (pg - page < len) && 95 + while (i < bufsize && (pg - page < len) && 96 96 *pg != '\0' && *pg != '\n') 97 97 buf[i++] = *pg++; 98 - if (i == sizeof(buf)) { 98 + if (i == bufsize) { 99 99 ret = -EINVAL; 100 100 goto out_free_buf; 101 101 }
+8
drivers/usb/host/ohci-hcd.c
··· 888 888 /* Check for an all 1's result which is a typical consequence 889 889 * of dead, unclocked, or unplugged (CardBus...) devices 890 890 */ 891 + again: 891 892 if (ints == ~(u32)0) { 892 893 ohci->rh_state = OHCI_RH_HALTED; 893 894 ohci_dbg (ohci, "device removed!\n"); ··· 982 981 (void) ohci_readl (ohci, &ohci->regs->control); 983 982 } 984 983 spin_unlock(&ohci->lock); 984 + 985 + /* repeat until all enabled interrupts are handled */ 986 + if (ohci->rh_state != OHCI_RH_HALTED) { 987 + ints = ohci_readl(ohci, &regs->intrstatus); 988 + if (ints && (ints & ohci_readl(ohci, &regs->intrenable))) 989 + goto again; 990 + } 985 991 986 992 return IRQ_HANDLED; 987 993 }
+3 -1
drivers/usb/host/xhci-plat.h
··· 8 8 #ifndef _XHCI_PLAT_H 9 9 #define _XHCI_PLAT_H 10 10 11 - #include "xhci.h" /* for hcd_to_xhci() */ 11 + struct device; 12 + struct platform_device; 13 + struct usb_hcd; 12 14 13 15 struct xhci_plat_priv { 14 16 const char *firmware_name;
+1
drivers/usb/host/xhci-rzv2m.c
··· 6 6 */ 7 7 8 8 #include <linux/usb/rzv2m_usb3drd.h> 9 + #include "xhci.h" 9 10 #include "xhci-plat.h" 10 11 #include "xhci-rzv2m.h" 11 12
+6 -2
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
··· 104 104 105 105 ret = tcpm->port_start(tcpm, tcpm->tcpm_port); 106 106 if (ret) 107 - goto fwnode_remove; 107 + goto port_unregister; 108 108 109 109 ret = tcpm->pdphy_start(tcpm, tcpm->tcpm_port); 110 110 if (ret) 111 - goto fwnode_remove; 111 + goto port_stop; 112 112 113 113 return 0; 114 114 115 + port_stop: 116 + tcpm->port_stop(tcpm); 117 + port_unregister: 118 + tcpm_unregister_port(tcpm->tcpm_port); 115 119 fwnode_remove: 116 120 fwnode_remove_software_node(tcpm->tcpc.fwnode); 117 121
+7 -4
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec_pdphy.c
··· 475 475 476 476 qcom_pmic_typec_pdphy_reset_off(pmic_typec_pdphy); 477 477 done: 478 - if (ret) { 479 - regulator_disable(pmic_typec_pdphy->vdd_pdphy); 478 + if (ret) 480 479 dev_err(dev, "pdphy_enable fail %d\n", ret); 481 - } 482 480 483 481 return ret; 484 482 } ··· 522 524 523 525 ret = pmic_typec_pdphy_reset(pmic_typec_pdphy); 524 526 if (ret) 525 - return ret; 527 + goto err_disable_vdd_pdhy; 526 528 527 529 for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++) 528 530 enable_irq(pmic_typec_pdphy->irq_data[i].irq); 529 531 530 532 return 0; 533 + 534 + err_disable_vdd_pdhy: 535 + regulator_disable(pmic_typec_pdphy->vdd_pdphy); 536 + 537 + return ret; 531 538 } 532 539 533 540 static void qcom_pmic_typec_pdphy_stop(struct pmic_typec *tcpm)
+33 -9
drivers/usb/typec/tcpm/tcpm.c
··· 1564 1564 static void tcpm_queue_vdm_unlocked(struct tcpm_port *port, const u32 header, 1565 1565 const u32 *data, int cnt, enum tcpm_transmit_type tx_sop_type) 1566 1566 { 1567 + if (port->state != SRC_READY && port->state != SNK_READY && 1568 + port->state != SRC_VDM_IDENTITY_REQUEST) 1569 + return; 1570 + 1567 1571 mutex_lock(&port->lock); 1568 - tcpm_queue_vdm(port, header, data, cnt, TCPC_TX_SOP); 1572 + tcpm_queue_vdm(port, header, data, cnt, tx_sop_type); 1569 1573 mutex_unlock(&port->lock); 1570 1574 } 1571 1575 ··· 1584 1580 port->partner_ident.cert_stat = p[VDO_INDEX_CSTAT]; 1585 1581 port->partner_ident.product = product; 1586 1582 1587 - typec_partner_set_identity(port->partner); 1583 + if (port->partner) 1584 + typec_partner_set_identity(port->partner); 1588 1585 1589 1586 tcpm_log(port, "Identity: %04x:%04x.%04x", 1590 1587 PD_IDH_VID(vdo), ··· 1746 1741 struct pd_mode_data *modep = &port->mode_data; 1747 1742 struct typec_altmode *altmode; 1748 1743 int i; 1744 + 1745 + if (!port->partner) 1746 + return; 1749 1747 1750 1748 for (i = 0; i < modep->altmodes; i++) { 1751 1749 altmode = typec_partner_register_altmode(port->partner, ··· 3004 2996 { 3005 2997 struct usb_power_delivery_desc desc = { port->negotiated_rev }; 3006 2998 struct usb_power_delivery_capabilities_desc caps = { }; 3007 - struct usb_power_delivery_capabilities *cap; 2999 + struct usb_power_delivery_capabilities *cap = port->partner_source_caps; 3008 3000 3009 3001 if (!port->partner_pd) 3010 3002 port->partner_pd = usb_power_delivery_register(NULL, &desc); ··· 3013 3005 3014 3006 memcpy(caps.pdo, port->source_caps, sizeof(u32) * port->nr_source_caps); 3015 3007 caps.role = TYPEC_SOURCE; 3008 + 3009 + if (cap) 3010 + usb_power_delivery_unregister_capabilities(cap); 3016 3011 3017 3012 cap = usb_power_delivery_register_capabilities(port->partner_pd, &caps); 3018 3013 if (IS_ERR(cap)) ··· 4242 4231 4243 4232 static void tcpm_typec_connect(struct tcpm_port *port) 4244 4233 { 4234 + struct typec_partner *partner; 4235 + 4245 4236 if (!port->connected) { 4237 + port->connected = true; 4246 4238 /* Make sure we don't report stale identity information */ 4247 4239 memset(&port->partner_ident, 0, sizeof(port->partner_ident)); 4248 4240 port->partner_desc.usb_pd = port->pd_capable; ··· 4255 4241 port->partner_desc.accessory = TYPEC_ACCESSORY_AUDIO; 4256 4242 else 4257 4243 port->partner_desc.accessory = TYPEC_ACCESSORY_NONE; 4258 - port->partner = typec_register_partner(port->typec_port, 4259 - &port->partner_desc); 4260 - port->connected = true; 4244 + partner = typec_register_partner(port->typec_port, &port->partner_desc); 4245 + if (IS_ERR(partner)) { 4246 + dev_err(port->dev, "Failed to register partner (%ld)\n", PTR_ERR(partner)); 4247 + return; 4248 + } 4249 + 4250 + port->partner = partner; 4261 4251 typec_partner_set_usb_power_delivery(port->partner, port->partner_pd); 4262 4252 } 4263 4253 } ··· 4341 4323 port->plug_prime = NULL; 4342 4324 port->cable = NULL; 4343 4325 if (port->connected) { 4344 - typec_partner_set_usb_power_delivery(port->partner, NULL); 4345 - typec_unregister_partner(port->partner); 4346 - port->partner = NULL; 4326 + if (port->partner) { 4327 + typec_partner_set_usb_power_delivery(port->partner, NULL); 4328 + typec_unregister_partner(port->partner); 4329 + port->partner = NULL; 4330 + } 4347 4331 port->connected = false; 4348 4332 } 4349 4333 } ··· 4569 4549 4570 4550 static void tcpm_set_initial_svdm_version(struct tcpm_port *port) 4571 4551 { 4552 + if (!port->partner) 4553 + return; 4554 + 4572 4555 switch (port->negotiated_rev) { 4573 4556 case PD_REV30: 4574 4557 break; ··· 5628 5605 break; 5629 5606 case PORT_RESET: 5630 5607 tcpm_reset_port(port); 5608 + port->pd_events = 0; 5631 5609 if (port->self_powered) 5632 5610 tcpm_set_cc(port, TYPEC_CC_OPEN); 5633 5611 else