Commit fb7d0829 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB fixes from Greg KH:
 "Here are a number of small USB driver fixes for reported problems.
  They include:

   - dwc2 driver fixes

   - xhci driver fixes

   - cdnsp driver fixes

   - typec driver fix

   - gadget u_ether driver fix

   - new quirk additions

   - usb gadget endpoint calculation fix

   - usb serial new device ids

   - revert of a xhci-dbg change that broke early debug booting

  All changes, except for the revert, have been in linux-next with no
  reported problems. The revert was from yesterday, and it was reported
  by the developers affected that it resolved their problem"

* tag 'usb-5.16-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  Revert "usb: early: convert to readl_poll_timeout_atomic()"
  usb: typec: tcpm: fix tcpm unregister port but leave a pending timer
  usb: cdnsp: Fix lack of spin_lock_irqsave/spin_lock_restore
  USB: NO_LPM quirk Lenovo USB-C to Ethernet Adapher(RTL8153-04)
  usb: xhci: Extend support for runtime power management for AMD's Yellow carp.
  usb: dwc2: fix STM ID/VBUS detection startup delay in dwc2_driver_probe
  USB: gadget: bRequestType is a bitfield, not a enum
  USB: serial: option: add Telit FN990 compositions
  USB: serial: cp210x: fix CP2105 GPIO registration
  usb: cdnsp: Fix incorrect status for control request
  usb: cdnsp: Fix issue in cdnsp_log_ep trace event
  usb: cdnsp: Fix incorrect calling of cdnsp_died function
  usb: xhci-mtk: fix list_del warning when enable list debug
  usb: gadget: u_ether: fix race in setting MAC address in setup phase
parents 0f03adcc c4d936ef
...@@ -1541,15 +1541,27 @@ static int cdnsp_gadget_pullup(struct usb_gadget *gadget, int is_on) ...@@ -1541,15 +1541,27 @@ static int cdnsp_gadget_pullup(struct usb_gadget *gadget, int is_on)
{ {
struct cdnsp_device *pdev = gadget_to_cdnsp(gadget); struct cdnsp_device *pdev = gadget_to_cdnsp(gadget);
struct cdns *cdns = dev_get_drvdata(pdev->dev); struct cdns *cdns = dev_get_drvdata(pdev->dev);
unsigned long flags;
trace_cdnsp_pullup(is_on); trace_cdnsp_pullup(is_on);
/*
* Disable events handling while controller is being
* enabled/disabled.
*/
disable_irq(cdns->dev_irq);
spin_lock_irqsave(&pdev->lock, flags);
if (!is_on) { if (!is_on) {
cdnsp_reset_device(pdev); cdnsp_reset_device(pdev);
cdns_clear_vbus(cdns); cdns_clear_vbus(cdns);
} else { } else {
cdns_set_vbus(cdns); cdns_set_vbus(cdns);
} }
spin_unlock_irqrestore(&pdev->lock, flags);
enable_irq(cdns->dev_irq);
return 0; return 0;
} }
......
...@@ -1029,6 +1029,8 @@ static void cdnsp_process_ctrl_td(struct cdnsp_device *pdev, ...@@ -1029,6 +1029,8 @@ static void cdnsp_process_ctrl_td(struct cdnsp_device *pdev,
return; return;
} }
*status = 0;
cdnsp_finish_td(pdev, td, event, pep, status); cdnsp_finish_td(pdev, td, event, pep, status);
} }
...@@ -1523,7 +1525,14 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data) ...@@ -1523,7 +1525,14 @@ irqreturn_t cdnsp_thread_irq_handler(int irq, void *data)
spin_lock_irqsave(&pdev->lock, flags); spin_lock_irqsave(&pdev->lock, flags);
if (pdev->cdnsp_state & (CDNSP_STATE_HALTED | CDNSP_STATE_DYING)) { if (pdev->cdnsp_state & (CDNSP_STATE_HALTED | CDNSP_STATE_DYING)) {
/*
* While removing or stopping driver there may still be deferred
* not handled interrupt which should not be treated as error.
* Driver should simply ignore it.
*/
if (pdev->gadget_driver)
cdnsp_died(pdev); cdnsp_died(pdev);
spin_unlock_irqrestore(&pdev->lock, flags); spin_unlock_irqrestore(&pdev->lock, flags);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
...@@ -57,9 +57,9 @@ DECLARE_EVENT_CLASS(cdnsp_log_ep, ...@@ -57,9 +57,9 @@ DECLARE_EVENT_CLASS(cdnsp_log_ep,
__entry->first_prime_det = pep->stream_info.first_prime_det; __entry->first_prime_det = pep->stream_info.first_prime_det;
__entry->drbls_count = pep->stream_info.drbls_count; __entry->drbls_count = pep->stream_info.drbls_count;
), ),
TP_printk("%s: SID: %08x ep state: %x stream: enabled: %d num %d " TP_printk("%s: SID: %08x, ep state: %x, stream: enabled: %d num %d "
"tds %d, first prime: %d drbls %d", "tds %d, first prime: %d drbls %d",
__get_str(name), __entry->state, __entry->stream_id, __get_str(name), __entry->stream_id, __entry->state,
__entry->enabled, __entry->num_streams, __entry->td_count, __entry->enabled, __entry->num_streams, __entry->td_count,
__entry->first_prime_det, __entry->drbls_count) __entry->first_prime_det, __entry->drbls_count)
); );
......
...@@ -434,6 +434,9 @@ static const struct usb_device_id usb_quirk_list[] = { ...@@ -434,6 +434,9 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x1532, 0x0116), .driver_info = { USB_DEVICE(0x1532, 0x0116), .driver_info =
USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL },
/* Lenovo USB-C to Ethernet Adapter RTL8153-04 */
{ USB_DEVICE(0x17ef, 0x720c), .driver_info = USB_QUIRK_NO_LPM },
/* Lenovo Powered USB-C Travel Hub (4X90S92381, RTL8153 GigE) */ /* Lenovo Powered USB-C Travel Hub (4X90S92381, RTL8153 GigE) */
{ USB_DEVICE(0x17ef, 0x721e), .driver_info = USB_QUIRK_NO_LPM }, { USB_DEVICE(0x17ef, 0x721e), .driver_info = USB_QUIRK_NO_LPM },
......
...@@ -575,6 +575,9 @@ static int dwc2_driver_probe(struct platform_device *dev) ...@@ -575,6 +575,9 @@ static int dwc2_driver_probe(struct platform_device *dev)
ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN; ggpio |= GGPIO_STM32_OTG_GCCFG_IDEN;
ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN; ggpio |= GGPIO_STM32_OTG_GCCFG_VBDEN;
dwc2_writel(hsotg, ggpio, GGPIO); dwc2_writel(hsotg, ggpio, GGPIO);
/* ID/VBUS detection startup time */
usleep_range(5000, 7000);
} }
retval = dwc2_drd_init(hsotg); retval = dwc2_drd_init(hsotg);
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include <linux/pci_ids.h> #include <linux/pci_ids.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/iopoll.h>
#include <asm/pci-direct.h> #include <asm/pci-direct.h>
#include <asm/fixmap.h> #include <asm/fixmap.h>
#include <linux/bcd.h> #include <linux/bcd.h>
...@@ -136,9 +135,17 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, int wait, int delay) ...@@ -136,9 +135,17 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, int wait, int delay)
{ {
u32 result; u32 result;
return readl_poll_timeout_atomic(ptr, result, /* Can not use readl_poll_timeout_atomic() for early boot things */
((result & mask) == done), do {
delay, wait); result = readl(ptr);
result &= mask;
if (result == done)
return 0;
udelay(delay);
wait -= delay;
} while (wait > 0);
return -ETIMEDOUT;
} }
static void __init xdbc_bios_handoff(void) static void __init xdbc_bios_handoff(void)
......
...@@ -1680,14 +1680,14 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1680,14 +1680,14 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
u8 endp; u8 endp;
if (w_length > USB_COMP_EP0_BUFSIZ) { if (w_length > USB_COMP_EP0_BUFSIZ) {
if (ctrl->bRequestType == USB_DIR_OUT) { if (ctrl->bRequestType & USB_DIR_IN) {
goto done;
} else {
/* Cast away the const, we are going to overwrite on purpose. */ /* Cast away the const, we are going to overwrite on purpose. */
__le16 *temp = (__le16 *)&ctrl->wLength; __le16 *temp = (__le16 *)&ctrl->wLength;
*temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ); *temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ);
w_length = USB_COMP_EP0_BUFSIZ; w_length = USB_COMP_EP0_BUFSIZ;
} else {
goto done;
} }
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include <linux/if_vlan.h> #include <linux/if_vlan.h>
#include <linux/etherdevice.h>
#include "u_ether.h" #include "u_ether.h"
...@@ -863,19 +864,23 @@ int gether_register_netdev(struct net_device *net) ...@@ -863,19 +864,23 @@ int gether_register_netdev(struct net_device *net)
{ {
struct eth_dev *dev; struct eth_dev *dev;
struct usb_gadget *g; struct usb_gadget *g;
struct sockaddr sa;
int status; int status;
if (!net->dev.parent) if (!net->dev.parent)
return -EINVAL; return -EINVAL;
dev = netdev_priv(net); dev = netdev_priv(net);
g = dev->gadget; g = dev->gadget;
net->addr_assign_type = NET_ADDR_RANDOM;
eth_hw_addr_set(net, dev->dev_mac);
status = register_netdev(net); status = register_netdev(net);
if (status < 0) { if (status < 0) {
dev_dbg(&g->dev, "register_netdev failed, %d\n", status); dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
return status; return status;
} else { } else {
INFO(dev, "HOST MAC %pM\n", dev->host_mac); INFO(dev, "HOST MAC %pM\n", dev->host_mac);
INFO(dev, "MAC %pM\n", dev->dev_mac);
/* two kinds of host-initiated state changes: /* two kinds of host-initiated state changes:
* - iff DATA transfer is active, carrier is "on" * - iff DATA transfer is active, carrier is "on"
...@@ -883,15 +888,6 @@ int gether_register_netdev(struct net_device *net) ...@@ -883,15 +888,6 @@ int gether_register_netdev(struct net_device *net)
*/ */
netif_carrier_off(net); netif_carrier_off(net);
} }
sa.sa_family = net->type;
memcpy(sa.sa_data, dev->dev_mac, ETH_ALEN);
rtnl_lock();
status = dev_set_mac_address(net, &sa, NULL);
rtnl_unlock();
if (status)
pr_warn("cannot set self ethernet address: %d\n", status);
else
INFO(dev, "MAC %pM\n", dev->dev_mac);
return status; return status;
} }
......
...@@ -346,14 +346,14 @@ static int dbgp_setup(struct usb_gadget *gadget, ...@@ -346,14 +346,14 @@ static int dbgp_setup(struct usb_gadget *gadget,
u16 len = 0; u16 len = 0;
if (length > DBGP_REQ_LEN) { if (length > DBGP_REQ_LEN) {
if (ctrl->bRequestType == USB_DIR_OUT) { if (ctrl->bRequestType & USB_DIR_IN) {
return err;
} else {
/* Cast away the const, we are going to overwrite on purpose. */ /* Cast away the const, we are going to overwrite on purpose. */
__le16 *temp = (__le16 *)&ctrl->wLength; __le16 *temp = (__le16 *)&ctrl->wLength;
*temp = cpu_to_le16(DBGP_REQ_LEN); *temp = cpu_to_le16(DBGP_REQ_LEN);
length = DBGP_REQ_LEN; length = DBGP_REQ_LEN;
} else {
return err;
} }
} }
......
...@@ -1334,14 +1334,14 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1334,14 +1334,14 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
u16 w_length = le16_to_cpu(ctrl->wLength); u16 w_length = le16_to_cpu(ctrl->wLength);
if (w_length > RBUF_SIZE) { if (w_length > RBUF_SIZE) {
if (ctrl->bRequestType == USB_DIR_OUT) { if (ctrl->bRequestType & USB_DIR_IN) {
return value;
} else {
/* Cast away the const, we are going to overwrite on purpose. */ /* Cast away the const, we are going to overwrite on purpose. */
__le16 *temp = (__le16 *)&ctrl->wLength; __le16 *temp = (__le16 *)&ctrl->wLength;
*temp = cpu_to_le16(RBUF_SIZE); *temp = cpu_to_le16(RBUF_SIZE);
w_length = RBUF_SIZE; w_length = RBUF_SIZE;
} else {
return value;
} }
} }
......
...@@ -781,7 +781,7 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) ...@@ -781,7 +781,7 @@ int xhci_mtk_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
ret = xhci_check_bandwidth(hcd, udev); ret = xhci_check_bandwidth(hcd, udev);
if (!ret) if (!ret)
INIT_LIST_HEAD(&mtk->bw_ep_chk_list); list_del_init(&mtk->bw_ep_chk_list);
return ret; return ret;
} }
......
...@@ -71,6 +71,8 @@ ...@@ -71,6 +71,8 @@
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 0x161e #define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 0x161e
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 0x15d6 #define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 0x15d6
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 0x15d7 #define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 0x15d7
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 0x161c
#define PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8 0x161f
#define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042 #define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042
#define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142
...@@ -330,7 +332,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -330,7 +332,9 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 || pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_3 ||
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 || pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_4 ||
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 || pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_5 ||
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6)) pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_6 ||
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_7 ||
pdev->device == PCI_DEVICE_ID_AMD_YELLOW_CARP_XHCI_8))
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW; xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
if (xhci->quirks & XHCI_RESET_ON_RESUME) if (xhci->quirks & XHCI_RESET_ON_RESUME)
......
...@@ -1635,6 +1635,8 @@ static int cp2105_gpioconf_init(struct usb_serial *serial) ...@@ -1635,6 +1635,8 @@ static int cp2105_gpioconf_init(struct usb_serial *serial)
/* 2 banks of GPIO - One for the pins taken from each serial port */ /* 2 banks of GPIO - One for the pins taken from each serial port */
if (intf_num == 0) { if (intf_num == 0) {
priv->gc.ngpio = 2;
if (mode.eci == CP210X_PIN_MODE_MODEM) { if (mode.eci == CP210X_PIN_MODE_MODEM) {
/* mark all GPIOs of this interface as reserved */ /* mark all GPIOs of this interface as reserved */
priv->gpio_altfunc = 0xff; priv->gpio_altfunc = 0xff;
...@@ -1645,8 +1647,9 @@ static int cp2105_gpioconf_init(struct usb_serial *serial) ...@@ -1645,8 +1647,9 @@ static int cp2105_gpioconf_init(struct usb_serial *serial)
priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) & priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) &
CP210X_ECI_GPIO_MODE_MASK) >> CP210X_ECI_GPIO_MODE_MASK) >>
CP210X_ECI_GPIO_MODE_OFFSET); CP210X_ECI_GPIO_MODE_OFFSET);
priv->gc.ngpio = 2;
} else if (intf_num == 1) { } else if (intf_num == 1) {
priv->gc.ngpio = 3;
if (mode.sci == CP210X_PIN_MODE_MODEM) { if (mode.sci == CP210X_PIN_MODE_MODEM) {
/* mark all GPIOs of this interface as reserved */ /* mark all GPIOs of this interface as reserved */
priv->gpio_altfunc = 0xff; priv->gpio_altfunc = 0xff;
...@@ -1657,7 +1660,6 @@ static int cp2105_gpioconf_init(struct usb_serial *serial) ...@@ -1657,7 +1660,6 @@ static int cp2105_gpioconf_init(struct usb_serial *serial)
priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) & priv->gpio_pushpull = (u8)((le16_to_cpu(config.gpio_mode) &
CP210X_SCI_GPIO_MODE_MASK) >> CP210X_SCI_GPIO_MODE_MASK) >>
CP210X_SCI_GPIO_MODE_OFFSET); CP210X_SCI_GPIO_MODE_OFFSET);
priv->gc.ngpio = 3;
} else { } else {
return -ENODEV; return -ENODEV;
} }
......
...@@ -1219,6 +1219,14 @@ static const struct usb_device_id option_ids[] = { ...@@ -1219,6 +1219,14 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(2) | RSVD(3) }, .driver_info = NCTRL(2) | RSVD(3) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1063, 0xff), /* Telit LN920 (ECM) */
.driver_info = NCTRL(0) | RSVD(1) }, .driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1070, 0xff), /* Telit FN990 (rmnet) */
.driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1071, 0xff), /* Telit FN990 (MBIM) */
.driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1072, 0xff), /* Telit FN990 (RNDIS) */
.driver_info = NCTRL(2) | RSVD(3) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1073, 0xff), /* Telit FN990 (ECM) */
.driver_info = NCTRL(0) | RSVD(1) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910), { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) }, .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM), { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
......
...@@ -324,6 +324,7 @@ struct tcpm_port { ...@@ -324,6 +324,7 @@ struct tcpm_port {
bool attached; bool attached;
bool connected; bool connected;
bool registered;
bool pd_supported; bool pd_supported;
enum typec_port_type port_type; enum typec_port_type port_type;
...@@ -6291,6 +6292,7 @@ static enum hrtimer_restart state_machine_timer_handler(struct hrtimer *timer) ...@@ -6291,6 +6292,7 @@ static enum hrtimer_restart state_machine_timer_handler(struct hrtimer *timer)
{ {
struct tcpm_port *port = container_of(timer, struct tcpm_port, state_machine_timer); struct tcpm_port *port = container_of(timer, struct tcpm_port, state_machine_timer);
if (port->registered)
kthread_queue_work(port->wq, &port->state_machine); kthread_queue_work(port->wq, &port->state_machine);
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
} }
...@@ -6299,6 +6301,7 @@ static enum hrtimer_restart vdm_state_machine_timer_handler(struct hrtimer *time ...@@ -6299,6 +6301,7 @@ static enum hrtimer_restart vdm_state_machine_timer_handler(struct hrtimer *time
{ {
struct tcpm_port *port = container_of(timer, struct tcpm_port, vdm_state_machine_timer); struct tcpm_port *port = container_of(timer, struct tcpm_port, vdm_state_machine_timer);
if (port->registered)
kthread_queue_work(port->wq, &port->vdm_state_machine); kthread_queue_work(port->wq, &port->vdm_state_machine);
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
} }
...@@ -6307,6 +6310,7 @@ static enum hrtimer_restart enable_frs_timer_handler(struct hrtimer *timer) ...@@ -6307,6 +6310,7 @@ static enum hrtimer_restart enable_frs_timer_handler(struct hrtimer *timer)
{ {
struct tcpm_port *port = container_of(timer, struct tcpm_port, enable_frs_timer); struct tcpm_port *port = container_of(timer, struct tcpm_port, enable_frs_timer);
if (port->registered)
kthread_queue_work(port->wq, &port->enable_frs); kthread_queue_work(port->wq, &port->enable_frs);
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
} }
...@@ -6315,6 +6319,7 @@ static enum hrtimer_restart send_discover_timer_handler(struct hrtimer *timer) ...@@ -6315,6 +6319,7 @@ static enum hrtimer_restart send_discover_timer_handler(struct hrtimer *timer)
{ {
struct tcpm_port *port = container_of(timer, struct tcpm_port, send_discover_timer); struct tcpm_port *port = container_of(timer, struct tcpm_port, send_discover_timer);
if (port->registered)
kthread_queue_work(port->wq, &port->send_discover_work); kthread_queue_work(port->wq, &port->send_discover_work);
return HRTIMER_NORESTART; return HRTIMER_NORESTART;
} }
...@@ -6403,6 +6408,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc) ...@@ -6403,6 +6408,7 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
typec_port_register_altmodes(port->typec_port, typec_port_register_altmodes(port->typec_port,
&tcpm_altmode_ops, port, &tcpm_altmode_ops, port,
port->port_altmode, ALTMODE_DISCOVERY_MAX); port->port_altmode, ALTMODE_DISCOVERY_MAX);
port->registered = true;
mutex_lock(&port->lock); mutex_lock(&port->lock);
tcpm_init(port); tcpm_init(port);
...@@ -6424,6 +6430,9 @@ void tcpm_unregister_port(struct tcpm_port *port) ...@@ -6424,6 +6430,9 @@ void tcpm_unregister_port(struct tcpm_port *port)
{ {
int i; int i;
port->registered = false;
kthread_destroy_worker(port->wq);
hrtimer_cancel(&port->send_discover_timer); hrtimer_cancel(&port->send_discover_timer);
hrtimer_cancel(&port->enable_frs_timer); hrtimer_cancel(&port->enable_frs_timer);
hrtimer_cancel(&port->vdm_state_machine_timer); hrtimer_cancel(&port->vdm_state_machine_timer);
...@@ -6435,7 +6444,6 @@ void tcpm_unregister_port(struct tcpm_port *port) ...@@ -6435,7 +6444,6 @@ void tcpm_unregister_port(struct tcpm_port *port)
typec_unregister_port(port->typec_port); typec_unregister_port(port->typec_port);
usb_role_switch_put(port->role_sw); usb_role_switch_put(port->role_sw);
tcpm_debugfs_exit(port); tcpm_debugfs_exit(port);
kthread_destroy_worker(port->wq);
} }
EXPORT_SYMBOL_GPL(tcpm_unregister_port); EXPORT_SYMBOL_GPL(tcpm_unregister_port);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment