aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/cdns3/cdnsp-gadget.h3
-rw-r--r--drivers/usb/cdns3/cdnsp-ring.c30
-rw-r--r--drivers/usb/class/cdc-acm.c3
-rw-r--r--drivers/usb/core/sysfs.c1
-rw-r--r--drivers/usb/dwc3/core.c8
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c4
-rw-r--r--drivers/usb/dwc3/dwc3-st.c16
-rw-r--r--drivers/usb/dwc3/dwc3-xilinx.c7
-rw-r--r--drivers/usb/dwc3/ep0.c3
-rw-r--r--drivers/usb/gadget/function/f_fs.c32
-rw-r--r--drivers/usb/gadget/function/f_midi2.c21
-rw-r--r--drivers/usb/gadget/function/u_audio.c42
-rw-r--r--drivers/usb/gadget/function/u_serial.c1
-rw-r--r--drivers/usb/gadget/function/uvc_video.c1
-rw-r--r--drivers/usb/gadget/udc/core.c10
-rw-r--r--drivers/usb/host/xhci-mem.c2
-rw-r--r--drivers/usb/host/xhci-ring.c1
-rw-r--r--drivers/usb/host/xhci.c8
-rw-r--r--drivers/usb/misc/usb-ljca.c1
-rw-r--r--drivers/usb/serial/ch341.c1
-rw-r--r--drivers/usb/serial/garmin_gps.c5
-rw-r--r--drivers/usb/serial/mxuport.c1
-rw-r--r--drivers/usb/serial/navman.c1
-rw-r--r--drivers/usb/serial/option.c5
-rw-r--r--drivers/usb/serial/qcaux.c1
-rw-r--r--drivers/usb/serial/spcp8x5.c10
-rw-r--r--drivers/usb/serial/symbolserial.c1
-rw-r--r--drivers/usb/serial/usb-serial-simple.c1
-rw-r--r--drivers/usb/serial/usb_debug.c8
-rw-r--r--drivers/usb/typec/mux/fsa4480.c14
-rw-r--r--drivers/usb/typec/tcpm/tcpci.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c3
-rw-r--r--drivers/usb/typec/tipd/core.c4
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c13
-rw-r--r--drivers/usb/typec/ucsi/ucsi_glink.c43
-rw-r--r--drivers/usb/usbip/vhci_hcd.c9
36 files changed, 227 insertions, 89 deletions
diff --git a/drivers/usb/cdns3/cdnsp-gadget.h b/drivers/usb/cdns3/cdnsp-gadget.h
index dbee6f085277..84887dfea763 100644
--- a/drivers/usb/cdns3/cdnsp-gadget.h
+++ b/drivers/usb/cdns3/cdnsp-gadget.h
@@ -811,6 +811,7 @@ struct cdnsp_stream_info {
* generate Missed Service Error Event.
* Set skip flag when receive a Missed Service Error Event and
* process the missed tds on the endpoint ring.
+ * @wa1_nop_trb: hold pointer to NOP trb.
*/
struct cdnsp_ep {
struct usb_ep endpoint;
@@ -838,6 +839,8 @@ struct cdnsp_ep {
#define EP_UNCONFIGURED BIT(7)
bool skip;
+ union cdnsp_trb *wa1_nop_trb;
+
};
/**
diff --git a/drivers/usb/cdns3/cdnsp-ring.c b/drivers/usb/cdns3/cdnsp-ring.c
index 02f297f5637d..dbd83d321bca 100644
--- a/drivers/usb/cdns3/cdnsp-ring.c
+++ b/drivers/usb/cdns3/cdnsp-ring.c
@@ -402,7 +402,7 @@ static u64 cdnsp_get_hw_deq(struct cdnsp_device *pdev,
struct cdnsp_stream_ctx *st_ctx;
struct cdnsp_ep *pep;
- pep = &pdev->eps[stream_id];
+ pep = &pdev->eps[ep_index];
if (pep->ep_state & EP_HAS_STREAMS) {
st_ctx = &pep->stream_info.stream_ctx_array[stream_id];
@@ -1905,6 +1905,23 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
return ret;
/*
+ * workaround 1: STOP EP command on LINK TRB with TC bit set to 1
+ * causes that internal cycle bit can have incorrect state after
+ * command complete. In consequence empty transfer ring can be
+ * incorrectly detected when EP is resumed.
+ * NOP TRB before LINK TRB avoid such scenario. STOP EP command is
+ * then on NOP TRB and internal cycle bit is not changed and have
+ * correct value.
+ */
+ if (pep->wa1_nop_trb) {
+ field = le32_to_cpu(pep->wa1_nop_trb->trans_event.flags);
+ field ^= TRB_CYCLE;
+
+ pep->wa1_nop_trb->trans_event.flags = cpu_to_le32(field);
+ pep->wa1_nop_trb = NULL;
+ }
+
+ /*
* Don't give the first TRB to the hardware (by toggling the cycle bit)
* until we've finished creating all the other TRBs. The ring's cycle
* state may change as we enqueue the other TRBs, so save it too.
@@ -1999,6 +2016,17 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
send_addr = addr;
}
+ if (cdnsp_trb_is_link(ring->enqueue + 1)) {
+ field = TRB_TYPE(TRB_TR_NOOP) | TRB_IOC;
+ if (!ring->cycle_state)
+ field |= TRB_CYCLE;
+
+ pep->wa1_nop_trb = ring->enqueue;
+
+ cdnsp_queue_trb(pdev, ring, 0, 0x0, 0x0,
+ TRB_INTR_TARGET(0), field);
+ }
+
cdnsp_check_trb_math(preq, enqd_len);
ret = cdnsp_giveback_first_trb(pdev, pep, preq->request.stream_id,
start_cycle, start_trb);
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 0e7439dba8fe..0c1b69d944ca 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1761,6 +1761,9 @@ static const struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0x11ca, 0x0201), /* VeriFone Mx870 Gadget Serial */
.driver_info = SINGLE_RX_URB,
},
+ { USB_DEVICE(0x1901, 0x0006), /* GE Healthcare Patient Monitor UI Controller */
+ .driver_info = DISABLE_ECHO, /* DISABLE ECHO in termios flag */
+ },
{ USB_DEVICE(0x1965, 0x0018), /* Uniden UBC125XLT */
.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
},
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index d83231d6736a..61b6d978892c 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -670,6 +670,7 @@ static int add_power_attributes(struct device *dev)
static void remove_power_attributes(struct device *dev)
{
+ sysfs_unmerge_group(&dev->kobj, &usb3_hardware_lpm_attr_group);
sysfs_unmerge_group(&dev->kobj, &usb2_hardware_lpm_attr_group);
sysfs_unmerge_group(&dev->kobj, &power_attr_group);
}
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 734de2a8bd21..ccc3895dbd7f 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -564,9 +564,17 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc)
void dwc3_event_buffers_cleanup(struct dwc3 *dwc)
{
struct dwc3_event_buffer *evt;
+ u32 reg;
if (!dwc->ev_buf)
return;
+ /*
+ * Exynos platforms may not be able to access event buffer if the
+ * controller failed to halt on dwc3_core_exit().
+ */
+ reg = dwc3_readl(dwc->regs, DWC3_DSTS);
+ if (!(reg & DWC3_DSTS_DEVCTRLHLT))
+ return;
evt = dwc->ev_buf;
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index d5c77db4daa9..2a11fc0ee84f 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -522,11 +522,13 @@ static int dwc3_omap_probe(struct platform_device *pdev)
if (ret) {
dev_err(dev, "failed to request IRQ #%d --> %d\n",
omap->irq, ret);
- goto err1;
+ goto err2;
}
dwc3_omap_enable_irqs(omap);
return 0;
+err2:
+ of_platform_depopulate(dev);
err1:
pm_runtime_put_sync(dev);
pm_runtime_disable(dev);
diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c
index 211360eee95a..c8c7cd0c1796 100644
--- a/drivers/usb/dwc3/dwc3-st.c
+++ b/drivers/usb/dwc3/dwc3-st.c
@@ -219,10 +219,8 @@ static int st_dwc3_probe(struct platform_device *pdev)
dwc3_data->regmap = regmap;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "syscfg-reg");
- if (!res) {
- ret = -ENXIO;
- goto undo_platform_dev_alloc;
- }
+ if (!res)
+ return -ENXIO;
dwc3_data->syscfg_reg_off = res->start;
@@ -233,8 +231,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
devm_reset_control_get_exclusive(dev, "powerdown");
if (IS_ERR(dwc3_data->rstc_pwrdn)) {
dev_err(&pdev->dev, "could not get power controller\n");
- ret = PTR_ERR(dwc3_data->rstc_pwrdn);
- goto undo_platform_dev_alloc;
+ return PTR_ERR(dwc3_data->rstc_pwrdn);
}
/* Manage PowerDown */
@@ -269,7 +266,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
if (!child_pdev) {
dev_err(dev, "failed to find dwc3 core device\n");
ret = -ENODEV;
- goto err_node_put;
+ goto depopulate;
}
dwc3_data->dr_mode = usb_get_dr_mode(&child_pdev->dev);
@@ -285,6 +282,7 @@ static int st_dwc3_probe(struct platform_device *pdev)
ret = st_dwc3_drd_init(dwc3_data);
if (ret) {
dev_err(dev, "drd initialisation failed\n");
+ of_platform_depopulate(dev);
goto undo_softreset;
}
@@ -294,14 +292,14 @@ static int st_dwc3_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dwc3_data);
return 0;
+depopulate:
+ of_platform_depopulate(dev);
err_node_put:
of_node_put(child);
undo_softreset:
reset_control_assert(dwc3_data->rstc_rst);
undo_powerdown:
reset_control_assert(dwc3_data->rstc_pwrdn);
-undo_platform_dev_alloc:
- platform_device_put(pdev);
return ret;
}
diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index bb4d894c16e9..f1298b1b4f84 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -327,9 +327,14 @@ static int dwc3_xlnx_probe(struct platform_device *pdev)
goto err_pm_set_suspended;
pm_suspend_ignore_children(dev, false);
- return pm_runtime_resume_and_get(dev);
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret < 0)
+ goto err_pm_set_suspended;
+
+ return 0;
err_pm_set_suspended:
+ of_platform_depopulate(dev);
pm_runtime_set_suspended(dev);
err_clk_put:
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index d96ffbe52039..c9533a99e47c 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -232,7 +232,8 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
/* stall is always issued on EP0 */
dep = dwc->eps[0];
__dwc3_gadget_ep_set_halt(dep, 1, false);
- dep->flags = DWC3_EP_ENABLED;
+ dep->flags &= DWC3_EP_RESOURCE_ALLOCATED;
+ dep->flags |= DWC3_EP_ENABLED;
dwc->delayed_status = false;
if (!list_empty(&dep->pending_list)) {
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index d8b096859337..e0ceaa721949 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -3734,11 +3734,9 @@ static int ffs_func_set_alt(struct usb_function *f,
if (alt > MAX_ALT_SETTINGS)
return -EINVAL;
- if (alt != (unsigned)-1) {
- intf = ffs_func_revmap_intf(func, interface);
- if (intf < 0)
- return intf;
- }
+ intf = ffs_func_revmap_intf(func, interface);
+ if (intf < 0)
+ return intf;
if (ffs->func)
ffs_func_eps_disable(ffs->func);
@@ -3753,12 +3751,6 @@ static int ffs_func_set_alt(struct usb_function *f,
if (ffs->state != FFS_ACTIVE)
return -ENODEV;
- if (alt == (unsigned)-1) {
- ffs->func = NULL;
- ffs_event_add(ffs, FUNCTIONFS_DISABLE);
- return 0;
- }
-
ffs->func = func;
ret = ffs_func_eps_enable(func);
if (ret >= 0) {
@@ -3770,7 +3762,23 @@ static int ffs_func_set_alt(struct usb_function *f,
static void ffs_func_disable(struct usb_function *f)
{
- ffs_func_set_alt(f, 0, (unsigned)-1);
+ struct ffs_function *func = ffs_func_from_usb(f);
+ struct ffs_data *ffs = func->ffs;
+
+ if (ffs->func)
+ ffs_func_eps_disable(ffs->func);
+
+ if (ffs->state == FFS_DEACTIVATED) {
+ ffs->state = FFS_CLOSING;
+ INIT_WORK(&ffs->reset_work, ffs_reset_work);
+ schedule_work(&ffs->reset_work);
+ return;
+ }
+
+ if (ffs->state == FFS_ACTIVE) {
+ ffs->func = NULL;
+ ffs_event_add(ffs, FUNCTIONFS_DISABLE);
+ }
}
static int ffs_func_setup(struct usb_function *f,
diff --git a/drivers/usb/gadget/function/f_midi2.c b/drivers/usb/gadget/function/f_midi2.c
index 38e8ed3144f0..3f63253ad3e0 100644
--- a/drivers/usb/gadget/function/f_midi2.c
+++ b/drivers/usb/gadget/function/f_midi2.c
@@ -642,12 +642,21 @@ static void process_ump_stream_msg(struct f_midi2_ep *ep, const u32 *data)
if (format)
return; // invalid
blk = (*data >> 8) & 0xff;
- if (blk >= ep->num_blks)
- return;
- if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO)
- reply_ump_stream_fb_info(ep, blk);
- if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME)
- reply_ump_stream_fb_name(ep, blk);
+ if (blk == 0xff) {
+ /* inquiry for all blocks */
+ for (blk = 0; blk < ep->num_blks; blk++) {
+ if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO)
+ reply_ump_stream_fb_info(ep, blk);
+ if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME)
+ reply_ump_stream_fb_name(ep, blk);
+ }
+ } else if (blk < ep->num_blks) {
+ /* only the specified block */
+ if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO)
+ reply_ump_stream_fb_info(ep, blk);
+ if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME)
+ reply_ump_stream_fb_name(ep, blk);
+ }
return;
}
}
diff --git a/drivers/usb/gadget/function/u_audio.c b/drivers/usb/gadget/function/u_audio.c
index 89af0feb7512..24299576972f 100644
--- a/drivers/usb/gadget/function/u_audio.c
+++ b/drivers/usb/gadget/function/u_audio.c
@@ -592,16 +592,25 @@ int u_audio_start_capture(struct g_audio *audio_dev)
struct usb_ep *ep, *ep_fback;
struct uac_rtd_params *prm;
struct uac_params *params = &audio_dev->params;
- int req_len, i;
+ int req_len, i, ret;
prm = &uac->c_prm;
dev_dbg(dev, "start capture with rate %d\n", prm->srate);
ep = audio_dev->out_ep;
- config_ep_by_speed(gadget, &audio_dev->func, ep);
+ ret = config_ep_by_speed(gadget, &audio_dev->func, ep);
+ if (ret < 0) {
+ dev_err(dev, "config_ep_by_speed for out_ep failed (%d)\n", ret);
+ return ret;
+ }
+
req_len = ep->maxpacket;
prm->ep_enabled = true;
- usb_ep_enable(ep);
+ ret = usb_ep_enable(ep);
+ if (ret < 0) {
+ dev_err(dev, "usb_ep_enable failed for out_ep (%d)\n", ret);
+ return ret;
+ }
for (i = 0; i < params->req_number; i++) {
if (!prm->reqs[i]) {
@@ -629,9 +638,18 @@ int u_audio_start_capture(struct g_audio *audio_dev)
return 0;
/* Setup feedback endpoint */
- config_ep_by_speed(gadget, &audio_dev->func, ep_fback);
+ ret = config_ep_by_speed(gadget, &audio_dev->func, ep_fback);
+ if (ret < 0) {
+ dev_err(dev, "config_ep_by_speed in_ep_fback failed (%d)\n", ret);
+ return ret; // TODO: Clean up out_ep
+ }
+
prm->fb_ep_enabled = true;
- usb_ep_enable(ep_fback);
+ ret = usb_ep_enable(ep_fback);
+ if (ret < 0) {
+ dev_err(dev, "usb_ep_enable failed for in_ep_fback (%d)\n", ret);
+ return ret; // TODO: Clean up out_ep
+ }
req_len = ep_fback->maxpacket;
req_fback = usb_ep_alloc_request(ep_fback, GFP_ATOMIC);
@@ -687,13 +705,17 @@ int u_audio_start_playback(struct g_audio *audio_dev)
struct uac_params *params = &audio_dev->params;
unsigned int factor;
const struct usb_endpoint_descriptor *ep_desc;
- int req_len, i;
+ int req_len, i, ret;
unsigned int p_pktsize;
prm = &uac->p_prm;
dev_dbg(dev, "start playback with rate %d\n", prm->srate);
ep = audio_dev->in_ep;
- config_ep_by_speed(gadget, &audio_dev->func, ep);
+ ret = config_ep_by_speed(gadget, &audio_dev->func, ep);
+ if (ret < 0) {
+ dev_err(dev, "config_ep_by_speed for in_ep failed (%d)\n", ret);
+ return ret;
+ }
ep_desc = ep->desc;
/*
@@ -720,7 +742,11 @@ int u_audio_start_playback(struct g_audio *audio_dev)
uac->p_residue_mil = 0;
prm->ep_enabled = true;
- usb_ep_enable(ep);
+ ret = usb_ep_enable(ep);
+ if (ret < 0) {
+ dev_err(dev, "usb_ep_enable failed for in_ep (%d)\n", ret);
+ return ret;
+ }
for (i = 0; i < params->req_number; i++) {
if (!prm->reqs[i]) {
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index eec7f7a2e40f..b394105e55d6 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -1441,6 +1441,7 @@ void gserial_suspend(struct gserial *gser)
spin_lock(&port->port_lock);
spin_unlock(&serial_port_lock);
port->suspended = true;
+ port->start_delayed = true;
spin_unlock_irqrestore(&port->port_lock, flags);
}
EXPORT_SYMBOL_GPL(gserial_suspend);
diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
index d41f5f31dadd..a9edd60fbbf7 100644
--- a/drivers/usb/gadget/function/uvc_video.c
+++ b/drivers/usb/gadget/function/uvc_video.c
@@ -753,6 +753,7 @@ int uvcg_video_enable(struct uvc_video *video)
video->req_int_count = 0;
uvc_video_ep_queue_initial_requests(video);
+ queue_work(video->async_wq, &video->pump);
return ret;
}
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index b0a613758414..cf6478f97f4a 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -118,12 +118,10 @@ int usb_ep_enable(struct usb_ep *ep)
goto out;
/* UDC drivers can't handle endpoints with maxpacket size 0 */
- if (usb_endpoint_maxp(ep->desc) == 0) {
- /*
- * We should log an error message here, but we can't call
- * dev_err() because there's no way to find the gadget
- * given only ep.
- */
+ if (!ep->desc || usb_endpoint_maxp(ep->desc) == 0) {
+ WARN_ONCE(1, "%s: ep%d (%s) has %s\n", __func__, ep->address, ep->name,
+ (!ep->desc) ? "NULL descriptor" : "maxpacket 0");
+
ret = -EINVAL;
goto out;
}
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index d7654f475daf..937ce5fd5809 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1872,7 +1872,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
cancel_delayed_work_sync(&xhci->cmd_timer);
- for (i = 0; i < xhci->max_interrupters; i++) {
+ for (i = 0; xhci->interrupters && i < xhci->max_interrupters; i++) {
if (xhci->interrupters[i]) {
xhci_remove_interrupter(xhci, xhci->interrupters[i]);
xhci_free_interrupter(xhci, xhci->interrupters[i]);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b7517c3c8059..4ea2c3e072a9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2910,6 +2910,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
process_isoc_td(xhci, ep, ep_ring, td, ep_trb, event);
else
process_bulk_intr_td(xhci, ep, ep_ring, td, ep_trb, event);
+ return 0;
check_endpoint_halted:
if (xhci_halted_host_endpoint(ep_ctx, trb_comp_code))
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 0a8cf6c17f82..efdf4c228b8c 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2837,7 +2837,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
xhci->num_active_eps);
return -ENOMEM;
}
- if ((xhci->quirks & XHCI_SW_BW_CHECKING) &&
+ if ((xhci->quirks & XHCI_SW_BW_CHECKING) && !ctx_change &&
xhci_reserve_bandwidth(xhci, virt_dev, command->in_ctx)) {
if ((xhci->quirks & XHCI_EP_LIMIT_QUIRK))
xhci_free_host_resources(xhci, ctrl_ctx);
@@ -4200,8 +4200,10 @@ static int xhci_setup_device(struct usb_hcd *hcd, struct usb_device *udev,
mutex_unlock(&xhci->mutex);
ret = xhci_disable_slot(xhci, udev->slot_id);
xhci_free_virt_device(xhci, udev->slot_id);
- if (!ret)
- xhci_alloc_dev(hcd, udev);
+ if (!ret) {
+ if (xhci_alloc_dev(hcd, udev) == 1)
+ xhci_setup_addressable_virt_dev(xhci, udev);
+ }
kfree(command->completion);
kfree(command);
return -EPROTO;
diff --git a/drivers/usb/misc/usb-ljca.c b/drivers/usb/misc/usb-ljca.c
index 2d30fc1be306..1a8d5e80b9ae 100644
--- a/drivers/usb/misc/usb-ljca.c
+++ b/drivers/usb/misc/usb-ljca.c
@@ -169,6 +169,7 @@ static const struct acpi_device_id ljca_gpio_hids[] = {
{ "INTC1096" },
{ "INTC100B" },
{ "INTC10D1" },
+ { "INTC10B5" },
{},
};
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c
index 612bea504d7a..0870c6533f80 100644
--- a/drivers/usb/serial/ch341.c
+++ b/drivers/usb/serial/ch341.c
@@ -863,4 +863,5 @@ static struct usb_serial_driver * const serial_drivers[] = {
module_usb_serial_driver(serial_drivers, id_table);
+MODULE_DESCRIPTION("Winchiphead CH341 USB Serial driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
index 670e942fdaaa..6d6ec7eed87c 100644
--- a/drivers/usb/serial/garmin_gps.c
+++ b/drivers/usb/serial/garmin_gps.c
@@ -104,7 +104,7 @@ struct garmin_packet {
int seq;
/* the real size of the data array, always > 0 */
int size;
- __u8 data[];
+ __u8 data[] __counted_by(size);
};
/* structure used to keep the current state of the driver */
@@ -267,8 +267,7 @@ static int pkt_add(struct garmin_data *garmin_data_p,
/* process only packets containing data ... */
if (data_length) {
- pkt = kmalloc(sizeof(struct garmin_packet)+data_length,
- GFP_ATOMIC);
+ pkt = kmalloc(struct_size(pkt, data, data_length), GFP_ATOMIC);
if (!pkt)
return 0;
diff --git a/drivers/usb/serial/mxuport.c b/drivers/usb/serial/mxuport.c
index 1f7bb3e4fcf2..942cb0153423 100644
--- a/drivers/usb/serial/mxuport.c
+++ b/drivers/usb/serial/mxuport.c
@@ -1315,4 +1315,5 @@ module_usb_serial_driver(serial_drivers, mxuport_idtable);
MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
MODULE_AUTHOR("<support@moxa.com>");
+MODULE_DESCRIPTION("Moxa UPORT USB Serial driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c
index 20277c52dded..82791fd67c46 100644
--- a/drivers/usb/serial/navman.c
+++ b/drivers/usb/serial/navman.c
@@ -112,4 +112,5 @@ static struct usb_serial_driver * const serial_drivers[] = {
module_usb_serial_driver(serial_drivers, id_table);
+MODULE_DESCRIPTION("Navman USB Serial driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 311040f9b935..176f38750ad5 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -619,6 +619,8 @@ static void option_instat_callback(struct urb *urb);
/* MeiG Smart Technology products */
#define MEIGSMART_VENDOR_ID 0x2dee
+/* MeiG Smart SRM825L based on Qualcomm 315 */
+#define MEIGSMART_PRODUCT_SRM825L 0x4d22
/* MeiG Smart SLM320 based on UNISOC UIS8910 */
#define MEIGSMART_PRODUCT_SLM320 0x4d41
@@ -2366,6 +2368,9 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x30) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x60) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c
index 929ffba663f2..015bb7c5d19d 100644
--- a/drivers/usb/serial/qcaux.c
+++ b/drivers/usb/serial/qcaux.c
@@ -84,4 +84,5 @@ static struct usb_serial_driver * const serial_drivers[] = {
};
module_usb_serial_driver(serial_drivers, id_table);
+MODULE_DESCRIPTION("Qualcomm USB Auxiliary Serial Port driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c
index 09a972a838ee..6b294bf8bc43 100644
--- a/drivers/usb/serial/spcp8x5.c
+++ b/drivers/usb/serial/spcp8x5.c
@@ -49,16 +49,6 @@ static const struct usb_device_id id_table[] = {
};
MODULE_DEVICE_TABLE(usb, id_table);
-struct spcp8x5_usb_ctrl_arg {
- u8 type;
- u8 cmd;
- u8 cmd_type;
- u16 value;
- u16 index;
- u16 length;
-};
-
-
/* spcp8x5 spec register define */
#define MCR_CONTROL_LINE_RTS 0x02
#define MCR_CONTROL_LINE_DTR 0x01
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c
index d7f73ad6e778..9aabb087f733 100644
--- a/drivers/usb/serial/symbolserial.c
+++ b/drivers/usb/serial/symbolserial.c
@@ -190,4 +190,5 @@ static struct usb_serial_driver * const serial_drivers[] = {
module_usb_serial_driver(serial_drivers, id_table);
+MODULE_DESCRIPTION("Symbol USB barcode to serial driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/serial/usb-serial-simple.c b/drivers/usb/serial/usb-serial-simple.c
index 24b8772a345e..82f4f0b992aa 100644
--- a/drivers/usb/serial/usb-serial-simple.c
+++ b/drivers/usb/serial/usb-serial-simple.c
@@ -163,4 +163,5 @@ static const struct usb_device_id id_table[] = {
MODULE_DEVICE_TABLE(usb, id_table);
module_usb_serial_driver(serial_drivers, id_table);
+MODULE_DESCRIPTION("USB Serial 'Simple' driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c
index 6934970f180d..61a8425b7762 100644
--- a/drivers/usb/serial/usb_debug.c
+++ b/drivers/usb/serial/usb_debug.c
@@ -76,6 +76,11 @@ static void usb_debug_process_read_urb(struct urb *urb)
usb_serial_generic_process_read_urb(urb);
}
+static void usb_debug_init_termios(struct tty_struct *tty)
+{
+ tty->termios.c_lflag &= ~(ECHO | ECHONL);
+}
+
static struct usb_serial_driver debug_device = {
.driver = {
.owner = THIS_MODULE,
@@ -85,6 +90,7 @@ static struct usb_serial_driver debug_device = {
.num_ports = 1,
.bulk_out_size = USB_DEBUG_MAX_PACKET_SIZE,
.break_ctl = usb_debug_break_ctl,
+ .init_termios = usb_debug_init_termios,
.process_read_urb = usb_debug_process_read_urb,
};
@@ -96,6 +102,7 @@ static struct usb_serial_driver dbc_device = {
.id_table = dbc_id_table,
.num_ports = 1,
.break_ctl = usb_debug_break_ctl,
+ .init_termios = usb_debug_init_termios,
.process_read_urb = usb_debug_process_read_urb,
};
@@ -104,4 +111,5 @@ static struct usb_serial_driver * const serial_drivers[] = {
};
module_usb_serial_driver(serial_drivers, id_table_combined);
+MODULE_DESCRIPTION("USB Debug cable driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/typec/mux/fsa4480.c b/drivers/usb/typec/mux/fsa4480.c
index cb7cdf90cb0a..f71dba8bf07c 100644
--- a/drivers/usb/typec/mux/fsa4480.c
+++ b/drivers/usb/typec/mux/fsa4480.c
@@ -13,6 +13,10 @@
#include <linux/usb/typec_dp.h>
#include <linux/usb/typec_mux.h>
+#define FSA4480_DEVICE_ID 0x00
+ #define FSA4480_DEVICE_ID_VENDOR_ID GENMASK(7, 6)
+ #define FSA4480_DEVICE_ID_VERSION_ID GENMASK(5, 3)
+ #define FSA4480_DEVICE_ID_REV_ID GENMASK(2, 0)
#define FSA4480_SWITCH_ENABLE 0x04
#define FSA4480_SWITCH_SELECT 0x05
#define FSA4480_SWITCH_STATUS1 0x07
@@ -251,6 +255,7 @@ static int fsa4480_probe(struct i2c_client *client)
struct typec_switch_desc sw_desc = { };
struct typec_mux_desc mux_desc = { };
struct fsa4480 *fsa;
+ int val = 0;
int ret;
fsa = devm_kzalloc(dev, sizeof(*fsa), GFP_KERNEL);
@@ -268,6 +273,15 @@ static int fsa4480_probe(struct i2c_client *client)
if (IS_ERR(fsa->regmap))
return dev_err_probe(dev, PTR_ERR(fsa->regmap), "failed to initialize regmap\n");
+ ret = regmap_read(fsa->regmap, FSA4480_DEVICE_ID, &val);
+ if (ret)
+ return dev_err_probe(dev, -ENODEV, "FSA4480 not found\n");
+
+ dev_dbg(dev, "Found FSA4480 v%lu.%lu (Vendor ID = %lu)\n",
+ FIELD_GET(FSA4480_DEVICE_ID_VERSION_ID, val),
+ FIELD_GET(FSA4480_DEVICE_ID_REV_ID, val),
+ FIELD_GET(FSA4480_DEVICE_ID_VENDOR_ID, val));
+
/* Safe mode */
fsa->cur_enable = FSA4480_ENABLE_DEVICE | FSA4480_ENABLE_USB;
fsa->mode = TYPEC_STATE_SAFE;
diff --git a/drivers/usb/typec/tcpm/tcpci.c b/drivers/usb/typec/tcpm/tcpci.c
index b862fdf3fe1d..3e3dcb983dde 100644
--- a/drivers/usb/typec/tcpm/tcpci.c
+++ b/drivers/usb/typec/tcpm/tcpci.c
@@ -67,7 +67,7 @@ static int tcpci_write16(struct tcpci *tcpci, unsigned int reg, u16 val)
return regmap_raw_write(tcpci->regmap, reg, &val, sizeof(u16));
}
-static bool tcpci_check_std_output_cap(struct regmap *regmap, u8 mask)
+static int tcpci_check_std_output_cap(struct regmap *regmap, u8 mask)
{
unsigned int reg;
int ret;
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 26f9006e95e1..4b02d6474259 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -4515,7 +4515,7 @@ static inline enum tcpm_state hard_reset_state(struct tcpm_port *port)
return ERROR_RECOVERY;
if (port->pwr_role == TYPEC_SOURCE)
return SRC_UNATTACHED;
- if (port->state == SNK_WAIT_CAPABILITIES)
+ if (port->state == SNK_WAIT_CAPABILITIES_TIMEOUT)
return SNK_READY;
return SNK_UNATTACHED;
}
@@ -5655,7 +5655,6 @@ static void run_state_machine(struct tcpm_port *port)
break;
case PORT_RESET:
tcpm_reset_port(port);
- port->pd_events = 0;
if (port->self_powered)
tcpm_set_cc(port, TYPEC_CC_OPEN);
else
diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c
index ea768b19a7f1..dd51a25480bf 100644
--- a/drivers/usb/typec/tipd/core.c
+++ b/drivers/usb/typec/tipd/core.c
@@ -1191,14 +1191,14 @@ static int tps6598x_apply_patch(struct tps6598x *tps)
dev_info(tps->dev, "Firmware update succeeded\n");
release_fw:
- release_firmware(fw);
if (ret) {
dev_err(tps->dev, "Failed to write patch %s of %zu bytes\n",
firmware_name, fw->size);
}
+ release_firmware(fw);
return ret;
-};
+}
static int cd321x_init(struct tps6598x *tps)
{
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index dcd3765cc1f5..4039851551c1 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -137,7 +137,7 @@ static int ucsi_run_command(struct ucsi *ucsi, u64 command, u32 *cci,
if (ret)
return ret;
- return err;
+ return err ?: UCSI_CCI_LENGTH(*cci);
}
static int ucsi_read_error(struct ucsi *ucsi, u8 connector_num)
@@ -238,13 +238,10 @@ static int ucsi_send_command_common(struct ucsi *ucsi, u64 cmd,
mutex_lock(&ucsi->ppm_lock);
ret = ucsi_run_command(ucsi, cmd, &cci, data, size, conn_ack);
- if (cci & UCSI_CCI_BUSY) {
- ret = ucsi_run_command(ucsi, UCSI_CANCEL, &cci, NULL, 0, false);
- return ret ? ret : -EBUSY;
- }
-
- if (cci & UCSI_CCI_ERROR)
- return ucsi_read_error(ucsi, connector_num);
+ if (cci & UCSI_CCI_BUSY)
+ ret = ucsi_run_command(ucsi, UCSI_CANCEL, &cci, NULL, 0, false) ?: -EBUSY;
+ else if (cci & UCSI_CCI_ERROR)
+ ret = ucsi_read_error(ucsi, connector_num);
mutex_unlock(&ucsi->ppm_lock);
return ret;
diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c
index 16c328497e0b..6aace19d595b 100644
--- a/drivers/usb/typec/ucsi/ucsi_glink.c
+++ b/drivers/usb/typec/ucsi/ucsi_glink.c
@@ -68,6 +68,9 @@ struct pmic_glink_ucsi {
struct work_struct notify_work;
struct work_struct register_work;
+ spinlock_t state_lock;
+ bool ucsi_registered;
+ bool pd_running;
u8 read_buf[UCSI_BUF_SIZE];
};
@@ -244,8 +247,20 @@ static void pmic_glink_ucsi_notify(struct work_struct *work)
static void pmic_glink_ucsi_register(struct work_struct *work)
{
struct pmic_glink_ucsi *ucsi = container_of(work, struct pmic_glink_ucsi, register_work);
+ unsigned long flags;
+ bool pd_running;
- ucsi_register(ucsi->ucsi);
+ spin_lock_irqsave(&ucsi->state_lock, flags);
+ pd_running = ucsi->pd_running;
+ spin_unlock_irqrestore(&ucsi->state_lock, flags);
+
+ if (!ucsi->ucsi_registered && pd_running) {
+ ucsi_register(ucsi->ucsi);
+ ucsi->ucsi_registered = true;
+ } else if (ucsi->ucsi_registered && !pd_running) {
+ ucsi_unregister(ucsi->ucsi);
+ ucsi->ucsi_registered = false;
+ }
}
static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv)
@@ -269,11 +284,12 @@ static void pmic_glink_ucsi_callback(const void *data, size_t len, void *priv)
static void pmic_glink_ucsi_pdr_notify(void *priv, int state)
{
struct pmic_glink_ucsi *ucsi = priv;
+ unsigned long flags;
- if (state == SERVREG_SERVICE_STATE_UP)
- schedule_work(&ucsi->register_work);
- else if (state == SERVREG_SERVICE_STATE_DOWN)
- ucsi_unregister(ucsi->ucsi);
+ spin_lock_irqsave(&ucsi->state_lock, flags);
+ ucsi->pd_running = (state == SERVREG_SERVICE_STATE_UP);
+ spin_unlock_irqrestore(&ucsi->state_lock, flags);
+ schedule_work(&ucsi->register_work);
}
static void pmic_glink_ucsi_destroy(void *data)
@@ -320,6 +336,7 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
INIT_WORK(&ucsi->register_work, pmic_glink_ucsi_register);
init_completion(&ucsi->read_ack);
init_completion(&ucsi->write_ack);
+ spin_lock_init(&ucsi->state_lock);
mutex_init(&ucsi->lock);
ucsi->ucsi = ucsi_create(dev, &pmic_glink_ucsi_ops);
@@ -367,12 +384,16 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
ucsi->port_orientation[port] = desc;
}
- ucsi->client = devm_pmic_glink_register_client(dev,
- PMIC_GLINK_OWNER_USBC,
- pmic_glink_ucsi_callback,
- pmic_glink_ucsi_pdr_notify,
- ucsi);
- return PTR_ERR_OR_ZERO(ucsi->client);
+ ucsi->client = devm_pmic_glink_client_alloc(dev, PMIC_GLINK_OWNER_USBC,
+ pmic_glink_ucsi_callback,
+ pmic_glink_ucsi_pdr_notify,
+ ucsi);
+ if (IS_ERR(ucsi->client))
+ return PTR_ERR(ucsi->client);
+
+ pmic_glink_client_register(ucsi->client);
+
+ return 0;
}
static void pmic_glink_ucsi_remove(struct auxiliary_device *adev)
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index 82650c11e451..302a89aeb258 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -745,6 +745,7 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
*
*/
if (usb_pipedevice(urb->pipe) == 0) {
+ struct usb_device *old;
__u8 type = usb_pipetype(urb->pipe);
struct usb_ctrlrequest *ctrlreq =
(struct usb_ctrlrequest *) urb->setup_packet;
@@ -755,14 +756,15 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
goto no_need_xmit;
}
+ old = vdev->udev;
switch (ctrlreq->bRequest) {
case USB_REQ_SET_ADDRESS:
/* set_address may come when a device is reset */
dev_info(dev, "SetAddress Request (%d) to port %d\n",
ctrlreq->wValue, vdev->rhport);
- usb_put_dev(vdev->udev);
vdev->udev = usb_get_dev(urb->dev);
+ usb_put_dev(old);
spin_lock(&vdev->ud.lock);
vdev->ud.status = VDEV_ST_USED;
@@ -781,8 +783,8 @@ static int vhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flag
usbip_dbg_vhci_hc(
"Not yet?:Get_Descriptor to device 0 (get max pipe size)\n");
- usb_put_dev(vdev->udev);
vdev->udev = usb_get_dev(urb->dev);
+ usb_put_dev(old);
goto out;
default:
@@ -1067,6 +1069,7 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
static void vhci_device_reset(struct usbip_device *ud)
{
struct vhci_device *vdev = container_of(ud, struct vhci_device, ud);
+ struct usb_device *old = vdev->udev;
unsigned long flags;
spin_lock_irqsave(&ud->lock, flags);
@@ -1074,8 +1077,8 @@ static void vhci_device_reset(struct usbip_device *ud)
vdev->speed = 0;
vdev->devid = 0;
- usb_put_dev(vdev->udev);
vdev->udev = NULL;
+ usb_put_dev(old);
if (ud->tcp_socket) {
sockfd_put(ud->tcp_socket);