Skip to content

Commit

Permalink
Merge tag 'usb-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/gregkh/usb

Pull USB fixes from Greg KH:
 "Here are a number of small USB fixes for reported problems for
  5.16-rc3

  They include:

   - typec driver fixes

   - new usb-serial driver ids

   - usb hub enumeration issues that were much reported

   - gadget driver fixes

   - dwc3 driver fix

   - chipidea driver fixe

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

* tag 'usb-5.16-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  USB: serial: option: add Fibocom FM101-GL variants
  usb: typec: tipd: Fix initialization sequence for cd321x
  usb: typec: tipd: Fix typo in cd321x_switch_power_state
  usb: hub: Fix locking issues with address0_mutex
  USB: serial: pl2303: fix GC type detection
  USB: serial: option: add Telit LE910S1 0x9200 composition
  usb: chipidea: ci_hdrc_imx: fix potential error pointer dereference in probe
  usb: hub: Fix usb enumeration issue due to address0 race
  usb: typec: fusb302: Fix masking of comparator and bc_lvl interrupts
  usb: dwc3: leave default DMA for PCI devices
  usb: dwc2: hcd_queue: Fix use of floating point literal
  usb: dwc3: gadget: Fix null pointer exception
  usb: gadget: udc-xilinx: Fix an error handling path in 'xudc_probe()'
  usb: xhci: tegra: Check padctrl interrupt presence in device tree
  usb: dwc2: gadget: Fix ISOC flow for elapsed frames
  usb: dwc3: gadget: Check for L1/L2/U3 for Start Transfer
  usb: dwc3: gadget: Ignore NoStream after End Transfer
  usb: dwc3: core: Revise GHWPARAMS9 offset
  • Loading branch information
Linus Torvalds committed Nov 26, 2021
2 parents d3e6479 + a88db2e commit ba2cacc
Show file tree
Hide file tree
Showing 13 changed files with 136 additions and 67 deletions.
18 changes: 9 additions & 9 deletions drivers/usb/chipidea/ci_hdrc_imx.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,15 +420,15 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
data->phy = devm_usb_get_phy_by_phandle(dev, "fsl,usbphy", 0);
if (IS_ERR(data->phy)) {
ret = PTR_ERR(data->phy);
if (ret == -ENODEV) {
data->phy = devm_usb_get_phy_by_phandle(dev, "phys", 0);
if (IS_ERR(data->phy)) {
ret = PTR_ERR(data->phy);
if (ret == -ENODEV)
data->phy = NULL;
else
goto err_clk;
}
if (ret != -ENODEV)
goto err_clk;
data->phy = devm_usb_get_phy_by_phandle(dev, "phys", 0);
if (IS_ERR(data->phy)) {
ret = PTR_ERR(data->phy);
if (ret == -ENODEV)
data->phy = NULL;
else
goto err_clk;
}
}

Expand Down
24 changes: 18 additions & 6 deletions drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -4700,8 +4700,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
if (oldspeed == USB_SPEED_LOW)
delay = HUB_LONG_RESET_TIME;

mutex_lock(hcd->address0_mutex);

/* Reset the device; full speed may morph to high speed */
/* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */
retval = hub_port_reset(hub, port1, udev, delay, false);
Expand Down Expand Up @@ -5016,7 +5014,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
hub_port_disable(hub, port1, 0);
update_devnum(udev, devnum); /* for disconnect processing */
}
mutex_unlock(hcd->address0_mutex);
return retval;
}

Expand Down Expand Up @@ -5191,6 +5188,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
struct usb_port *port_dev = hub->ports[port1 - 1];
struct usb_device *udev = port_dev->child;
static int unreliable_port = -1;
bool retry_locked;

/* Disconnect any existing devices under this port */
if (udev) {
Expand Down Expand Up @@ -5246,15 +5244,20 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
unit_load = 100;

status = 0;
for (i = 0; i < PORT_INIT_TRIES; i++) {

for (i = 0; i < PORT_INIT_TRIES; i++) {
usb_lock_port(port_dev);
mutex_lock(hcd->address0_mutex);
retry_locked = true;
/* reallocate for each attempt, since references
* to the previous one can escape in various ways
*/
udev = usb_alloc_dev(hdev, hdev->bus, port1);
if (!udev) {
dev_err(&port_dev->dev,
"couldn't allocate usb_device\n");
mutex_unlock(hcd->address0_mutex);
usb_unlock_port(port_dev);
goto done;
}

Expand All @@ -5276,12 +5279,14 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
}

/* reset (non-USB 3.0 devices) and get descriptor */
usb_lock_port(port_dev);
status = hub_port_init(hub, udev, port1, i);
usb_unlock_port(port_dev);
if (status < 0)
goto loop;

mutex_unlock(hcd->address0_mutex);
usb_unlock_port(port_dev);
retry_locked = false;

if (udev->quirks & USB_QUIRK_DELAY_INIT)
msleep(2000);

Expand Down Expand Up @@ -5374,6 +5379,10 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
usb_ep0_reinit(udev);
release_devnum(udev);
hub_free_dev(udev);
if (retry_locked) {
mutex_unlock(hcd->address0_mutex);
usb_unlock_port(port_dev);
}
usb_put_dev(udev);
if ((status == -ENOTCONN) || (status == -ENOTSUPP))
break;
Expand Down Expand Up @@ -5915,6 +5924,8 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
bos = udev->bos;
udev->bos = NULL;

mutex_lock(hcd->address0_mutex);

for (i = 0; i < PORT_INIT_TRIES; ++i) {

/* ep0 maxpacket size may change; let the HCD know about it.
Expand All @@ -5924,6 +5935,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
break;
}
mutex_unlock(hcd->address0_mutex);

if (ret < 0)
goto re_enumerate;
Expand Down
17 changes: 14 additions & 3 deletions drivers/usb/dwc2/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,8 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
}
ctrl |= DXEPCTL_CNAK;
} else {
hs_req->req.frame_number = hs_ep->target_frame;
hs_req->req.actual = 0;
dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, -ENODATA);
return;
}
Expand Down Expand Up @@ -2857,9 +2859,12 @@ static void dwc2_gadget_handle_ep_disabled(struct dwc2_hsotg_ep *hs_ep)

do {
hs_req = get_ep_head(hs_ep);
if (hs_req)
if (hs_req) {
hs_req->req.frame_number = hs_ep->target_frame;
hs_req->req.actual = 0;
dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req,
-ENODATA);
}
dwc2_gadget_incr_frame_num(hs_ep);
/* Update current frame number value. */
hsotg->frame_number = dwc2_hsotg_read_frameno(hsotg);
Expand Down Expand Up @@ -2912,8 +2917,11 @@ static void dwc2_gadget_handle_out_token_ep_disabled(struct dwc2_hsotg_ep *ep)

while (dwc2_gadget_target_frame_elapsed(ep)) {
hs_req = get_ep_head(ep);
if (hs_req)
if (hs_req) {
hs_req->req.frame_number = ep->target_frame;
hs_req->req.actual = 0;
dwc2_hsotg_complete_request(hsotg, ep, hs_req, -ENODATA);
}

dwc2_gadget_incr_frame_num(ep);
/* Update current frame number value. */
Expand Down Expand Up @@ -3002,8 +3010,11 @@ static void dwc2_gadget_handle_nak(struct dwc2_hsotg_ep *hs_ep)

while (dwc2_gadget_target_frame_elapsed(hs_ep)) {
hs_req = get_ep_head(hs_ep);
if (hs_req)
if (hs_req) {
hs_req->req.frame_number = hs_ep->target_frame;
hs_req->req.actual = 0;
dwc2_hsotg_complete_request(hsotg, hs_ep, hs_req, -ENODATA);
}

dwc2_gadget_incr_frame_num(hs_ep);
/* Update current frame number value. */
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/dwc2/hcd_queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
#define DWC2_UNRESERVE_DELAY (msecs_to_jiffies(5))

/* If we get a NAK, wait this long before retrying */
#define DWC2_RETRY_WAIT_DELAY (1 * 1E6L)
#define DWC2_RETRY_WAIT_DELAY (1 * NSEC_PER_MSEC)

/**
* dwc2_periodic_channel_available() - Checks that a channel is available for a
Expand Down
8 changes: 5 additions & 3 deletions drivers/usb/dwc3/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1594,9 +1594,11 @@ static int dwc3_probe(struct platform_device *pdev)

dwc3_get_properties(dwc);

ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64));
if (ret)
return ret;
if (!dwc->sysdev_is_parent) {
ret = dma_set_mask_and_coherent(dwc->sysdev, DMA_BIT_MASK(64));
if (ret)
return ret;
}

dwc->reset = devm_reset_control_array_get_optional_shared(dev);
if (IS_ERR(dwc->reset))
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/dwc3/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
#define DWC3_GHWPARAMS8 0xc600
#define DWC3_GUCTL3 0xc60c
#define DWC3_GFLADJ 0xc630
#define DWC3_GHWPARAMS9 0xc680
#define DWC3_GHWPARAMS9 0xc6e0

/* Device Registers */
#define DWC3_DCFG 0xc700
Expand Down
39 changes: 28 additions & 11 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,13 +310,24 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd,
if (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_STARTTRANSFER) {
int link_state;

/*
* Initiate remote wakeup if the link state is in U3 when
* operating in SS/SSP or L1/L2 when operating in HS/FS. If the
* link state is in U1/U2, no remote wakeup is needed. The Start
* Transfer command will initiate the link recovery.
*/
link_state = dwc3_gadget_get_link_state(dwc);
if (link_state == DWC3_LINK_STATE_U1 ||
link_state == DWC3_LINK_STATE_U2 ||
link_state == DWC3_LINK_STATE_U3) {
switch (link_state) {
case DWC3_LINK_STATE_U2:
if (dwc->gadget->speed >= USB_SPEED_SUPER)
break;

fallthrough;
case DWC3_LINK_STATE_U3:
ret = __dwc3_gadget_wakeup(dwc);
dev_WARN_ONCE(dwc->dev, ret, "wakeup failed --> %d\n",
ret);
break;
}
}

Expand Down Expand Up @@ -3252,6 +3263,9 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep,
struct dwc3 *dwc = dep->dwc;
bool no_started_trb = true;

if (!dep->endpoint.desc)
return no_started_trb;

dwc3_gadget_ep_cleanup_completed_requests(dep, event, status);

if (dep->flags & DWC3_EP_END_TRANSFER_PENDING)
Expand Down Expand Up @@ -3299,6 +3313,9 @@ static void dwc3_gadget_endpoint_transfer_in_progress(struct dwc3_ep *dep,
{
int status = 0;

if (!dep->endpoint.desc)
return;

if (usb_endpoint_xfer_isoc(dep->endpoint.desc))
dwc3_gadget_endpoint_frame_from_event(dep, event);

Expand Down Expand Up @@ -3352,6 +3369,14 @@ static void dwc3_gadget_endpoint_command_complete(struct dwc3_ep *dep,
if (cmd != DWC3_DEPCMD_ENDTRANSFER)
return;

/*
* The END_TRANSFER command will cause the controller to generate a
* NoStream Event, and it's not due to the host DP NoStream rejection.
* Ignore the next NoStream event.
*/
if (dep->stream_capable)
dep->flags |= DWC3_EP_IGNORE_NEXT_NOSTREAM;

dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
dwc3_gadget_ep_cleanup_cancelled_requests(dep);
Expand Down Expand Up @@ -3574,14 +3599,6 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
WARN_ON_ONCE(ret);
dep->resource_index = 0;

/*
* The END_TRANSFER command will cause the controller to generate a
* NoStream Event, and it's not due to the host DP NoStream rejection.
* Ignore the next NoStream event.
*/
if (dep->stream_capable)
dep->flags |= DWC3_EP_IGNORE_NEXT_NOSTREAM;

if (!interrupt)
dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
else
Expand Down
5 changes: 4 additions & 1 deletion drivers/usb/gadget/udc/udc-xilinx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2136,7 +2136,7 @@ static int xudc_probe(struct platform_device *pdev)

ret = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
if (ret)
goto fail;
goto err_disable_unprepare_clk;

udc->dev = &udc->gadget.dev;

Expand All @@ -2155,6 +2155,9 @@ static int xudc_probe(struct platform_device *pdev)
udc->dma_enabled ? "with DMA" : "without DMA");

return 0;

err_disable_unprepare_clk:
clk_disable_unprepare(udc->clk);
fail:
dev_err(&pdev->dev, "probe failed, %d\n", ret);
return ret;
Expand Down
41 changes: 29 additions & 12 deletions drivers/usb/host/xhci-tegra.c
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,7 @@ static void tegra_xusb_deinit_usb_phy(struct tegra_xusb *tegra)

static int tegra_xusb_probe(struct platform_device *pdev)
{
struct of_phandle_args args;
struct tegra_xusb *tegra;
struct device_node *np;
struct resource *regs;
Expand Down Expand Up @@ -1454,10 +1455,17 @@ static int tegra_xusb_probe(struct platform_device *pdev)
goto put_padctl;
}

tegra->padctl_irq = of_irq_get(np, 0);
if (tegra->padctl_irq <= 0) {
err = (tegra->padctl_irq == 0) ? -ENODEV : tegra->padctl_irq;
goto put_padctl;
/* Older device-trees don't have padctrl interrupt */
err = of_irq_parse_one(np, 0, &args);
if (!err) {
tegra->padctl_irq = of_irq_get(np, 0);
if (tegra->padctl_irq <= 0) {
err = (tegra->padctl_irq == 0) ? -ENODEV : tegra->padctl_irq;
goto put_padctl;
}
} else {
dev_dbg(&pdev->dev,
"%pOF is missing an interrupt, disabling PM support\n", np);
}

tegra->host_clk = devm_clk_get(&pdev->dev, "xusb_host");
Expand Down Expand Up @@ -1696,11 +1704,15 @@ static int tegra_xusb_probe(struct platform_device *pdev)
goto remove_usb3;
}

err = devm_request_threaded_irq(&pdev->dev, tegra->padctl_irq, NULL, tegra_xusb_padctl_irq,
IRQF_ONESHOT, dev_name(&pdev->dev), tegra);
if (err < 0) {
dev_err(&pdev->dev, "failed to request padctl IRQ: %d\n", err);
goto remove_usb3;
if (tegra->padctl_irq) {
err = devm_request_threaded_irq(&pdev->dev, tegra->padctl_irq,
NULL, tegra_xusb_padctl_irq,
IRQF_ONESHOT, dev_name(&pdev->dev),
tegra);
if (err < 0) {
dev_err(&pdev->dev, "failed to request padctl IRQ: %d\n", err);
goto remove_usb3;
}
}

err = tegra_xusb_enable_firmware_messages(tegra);
Expand All @@ -1718,13 +1730,16 @@ static int tegra_xusb_probe(struct platform_device *pdev)
/* Enable wake for both USB 2.0 and USB 3.0 roothubs */
device_init_wakeup(&tegra->hcd->self.root_hub->dev, true);
device_init_wakeup(&xhci->shared_hcd->self.root_hub->dev, true);
device_init_wakeup(tegra->dev, true);

pm_runtime_use_autosuspend(tegra->dev);
pm_runtime_set_autosuspend_delay(tegra->dev, 2000);
pm_runtime_mark_last_busy(tegra->dev);
pm_runtime_set_active(tegra->dev);
pm_runtime_enable(tegra->dev);

if (tegra->padctl_irq) {
device_init_wakeup(tegra->dev, true);
pm_runtime_enable(tegra->dev);
}

return 0;

Expand Down Expand Up @@ -1772,7 +1787,9 @@ static int tegra_xusb_remove(struct platform_device *pdev)
dma_free_coherent(&pdev->dev, tegra->fw.size, tegra->fw.virt,
tegra->fw.phys);

pm_runtime_disable(&pdev->dev);
if (tegra->padctl_irq)
pm_runtime_disable(&pdev->dev);

pm_runtime_put(&pdev->dev);

tegra_xusb_powergate_partitions(tegra);
Expand Down
5 changes: 5 additions & 0 deletions drivers/usb/serial/option.c
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(2) },
{ USB_DEVICE(TELIT_VENDOR_ID, 0x9010), /* Telit SBL FN980 flashing device */
.driver_info = NCTRL(0) | ZLP },
{ USB_DEVICE(TELIT_VENDOR_ID, 0x9200), /* Telit LE910S1 flashing device */
.driver_info = NCTRL(0) | ZLP },
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
.driver_info = RSVD(1) },
Expand Down Expand Up @@ -2094,6 +2096,9 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) }, /* Fibocom FG150 Diag */
{ USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) }, /* Fibocom FG150 AT */
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) }, /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a2, 0xff) }, /* Fibocom FM101-GL (laptop MBIM) */
{ USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a4, 0xff), /* Fibocom FM101-GL (laptop MBIM) */
.driver_info = RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */
{ USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
Expand Down
Loading

0 comments on commit ba2cacc

Please sign in to comment.