Skip to content

Commit

Permalink
Merge tag 'usb-6.9-rc5' 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 / Thunderbolt driver fixes from Greg KH:
 "Here are some small USB and Thunderbolt driver fixes for 6.9-rc5.
  Included in here are:

   - MAINTAINER file update for invalid email address

   - usb-serial device id updates

   - typec driver fixes

   - thunderbolt / usb4 driver fixes

   - usb core shutdown fixes

   - cdc-wdm driver revert for reported problem in -rc1

   - usb gadget driver fixes

   - xhci driver fixes

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

* tag 'usb-6.9-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (25 commits)
  USB: serial: option: add Telit FN920C04 rmnet compositions
  usb: dwc3: ep0: Don't reset resource alloc flag
  Revert "usb: cdc-wdm: close race between read and workqueue"
  USB: serial: option: add Rolling RW101-GL and RW135-GL support
  USB: serial: option: add Lonsung U8300/U9300 product
  USB: serial: option: add support for Fibocom FM650/FG650
  USB: serial: option: support Quectel EM060K sub-models
  USB: serial: option: add Fibocom FM135-GL variants
  usb: misc: onboard_usb_hub: Disable the USB hub clock on failure
  thunderbolt: Avoid notify PM core about runtime PM resume
  thunderbolt: Fix wake configurations after device unplug
  usb: dwc2: host: Fix dereference issue in DDMA completion flow.
  usb: typec: mux: it5205: Fix ChipID value typo
  MAINTAINERS: Drop Li Yang as their email address stopped working
  usb: gadget: fsl: Initialize udc before using it
  usb: Disable USB3 LPM at shutdown
  usb: gadget: f_ncm: Fix UAF ncm object at re-bind after usb ep transport error
  usb: typec: tcpm: Correct the PDO counting in pd_set
  usb: gadget: functionfs: Wait for fences before enqueueing DMABUF
  usb: gadget: functionfs: Fix inverted DMA fence direction
  ...
  • Loading branch information
Linus Torvalds committed Apr 21, 2024
2 parents 3b68086 + 7a9a304 commit 5fa0ab4
Show file tree
Hide file tree
Showing 19 changed files with 147 additions and 64 deletions.
3 changes: 1 addition & 2 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -8746,10 +8746,9 @@ S: Orphan
F: drivers/usb/gadget/udc/fsl*

FREESCALE USB PHY DRIVER
M: Ran Wang <ran.wang_1@nxp.com>
L: linux-usb@vger.kernel.org
L: linuxppc-dev@lists.ozlabs.org
S: Maintained
S: Orphan
F: drivers/usb/phy/phy-fsl-usb*

FREEVXFS FILESYSTEM
Expand Down
48 changes: 39 additions & 9 deletions drivers/thunderbolt/switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -3180,22 +3180,29 @@ void tb_switch_unconfigure_link(struct tb_switch *sw)
{
struct tb_port *up, *down;

if (sw->is_unplugged)
return;
if (!tb_route(sw) || tb_switch_is_icm(sw))
return;

/*
* Unconfigure downstream port so that wake-on-connect can be
* configured after router unplug. No need to unconfigure upstream port
* since its router is unplugged.
*/
up = tb_upstream_port(sw);
if (tb_switch_is_usb4(up->sw))
usb4_port_unconfigure(up);
else
tb_lc_unconfigure_port(up);

down = up->remote;
if (tb_switch_is_usb4(down->sw))
usb4_port_unconfigure(down);
else
tb_lc_unconfigure_port(down);

if (sw->is_unplugged)
return;

up = tb_upstream_port(sw);
if (tb_switch_is_usb4(up->sw))
usb4_port_unconfigure(up);
else
tb_lc_unconfigure_port(up);
}

static void tb_switch_credits_init(struct tb_switch *sw)
Expand Down Expand Up @@ -3441,7 +3448,26 @@ static int tb_switch_set_wake(struct tb_switch *sw, unsigned int flags)
return tb_lc_set_wake(sw, flags);
}

int tb_switch_resume(struct tb_switch *sw)
static void tb_switch_check_wakes(struct tb_switch *sw)
{
if (device_may_wakeup(&sw->dev)) {
if (tb_switch_is_usb4(sw))
usb4_switch_check_wakes(sw);
}
}

/**
* tb_switch_resume() - Resume a switch after sleep
* @sw: Switch to resume
* @runtime: Is this resume from runtime suspend or system sleep
*
* Resumes and re-enumerates router (and all its children), if still plugged
* after suspend. Don't enumerate device router whose UID was changed during
* suspend. If this is resume from system sleep, notifies PM core about the
* wakes occurred during suspend. Disables all wakes, except USB4 wake of
* upstream port for USB4 routers that shall be always enabled.
*/
int tb_switch_resume(struct tb_switch *sw, bool runtime)
{
struct tb_port *port;
int err;
Expand Down Expand Up @@ -3490,6 +3516,9 @@ int tb_switch_resume(struct tb_switch *sw)
if (err)
return err;

if (!runtime)
tb_switch_check_wakes(sw);

/* Disable wakes */
tb_switch_set_wake(sw, 0);

Expand Down Expand Up @@ -3519,7 +3548,8 @@ int tb_switch_resume(struct tb_switch *sw)
*/
if (tb_port_unlock(port))
tb_port_warn(port, "failed to unlock port\n");
if (port->remote && tb_switch_resume(port->remote->sw)) {
if (port->remote &&
tb_switch_resume(port->remote->sw, runtime)) {
tb_port_warn(port,
"lost during suspend, disconnecting\n");
tb_sw_set_unplugged(port->remote->sw);
Expand Down
10 changes: 8 additions & 2 deletions drivers/thunderbolt/tb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1801,6 +1801,12 @@ static struct tb_port *tb_find_dp_out(struct tb *tb, struct tb_port *in)
continue;
}

/* Needs to be on different routers */
if (in->sw == port->sw) {
tb_port_dbg(port, "skipping DP OUT on same router\n");
continue;
}

tb_port_dbg(port, "DP OUT available\n");

/*
Expand Down Expand Up @@ -2936,7 +2942,7 @@ static int tb_resume_noirq(struct tb *tb)
if (!tb_switch_is_usb4(tb->root_switch))
tb_switch_reset(tb->root_switch);

tb_switch_resume(tb->root_switch);
tb_switch_resume(tb->root_switch, false);
tb_free_invalid_tunnels(tb);
tb_free_unplugged_children(tb->root_switch);
tb_restore_children(tb->root_switch);
Expand Down Expand Up @@ -3062,7 +3068,7 @@ static int tb_runtime_resume(struct tb *tb)
struct tb_tunnel *tunnel, *n;

mutex_lock(&tb->lock);
tb_switch_resume(tb->root_switch);
tb_switch_resume(tb->root_switch, true);
tb_free_invalid_tunnels(tb);
tb_restore_children(tb->root_switch);
list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list)
Expand Down
3 changes: 2 additions & 1 deletion drivers/thunderbolt/tb.h
Original file line number Diff line number Diff line change
Expand Up @@ -827,7 +827,7 @@ int tb_switch_configuration_valid(struct tb_switch *sw);
int tb_switch_add(struct tb_switch *sw);
void tb_switch_remove(struct tb_switch *sw);
void tb_switch_suspend(struct tb_switch *sw, bool runtime);
int tb_switch_resume(struct tb_switch *sw);
int tb_switch_resume(struct tb_switch *sw, bool runtime);
int tb_switch_reset(struct tb_switch *sw);
int tb_switch_wait_for_bit(struct tb_switch *sw, u32 offset, u32 bit,
u32 value, int timeout_msec);
Expand Down Expand Up @@ -1288,6 +1288,7 @@ static inline bool tb_switch_is_usb4(const struct tb_switch *sw)
return usb4_switch_version(sw) > 0;
}

void usb4_switch_check_wakes(struct tb_switch *sw);
int usb4_switch_setup(struct tb_switch *sw);
int usb4_switch_configuration_valid(struct tb_switch *sw);
int usb4_switch_read_uid(struct tb_switch *sw, u64 *uid);
Expand Down
13 changes: 7 additions & 6 deletions drivers/thunderbolt/usb4.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,20 @@ static inline int usb4_switch_op_data(struct tb_switch *sw, u16 opcode,
tx_dwords, rx_data, rx_dwords);
}

static void usb4_switch_check_wakes(struct tb_switch *sw)
/**
* usb4_switch_check_wakes() - Check for wakes and notify PM core about them
* @sw: Router whose wakes to check
*
* Checks wakes occurred during suspend and notify the PM core about them.
*/
void usb4_switch_check_wakes(struct tb_switch *sw)
{
bool wakeup_usb4 = false;
struct usb4_port *usb4;
struct tb_port *port;
bool wakeup = false;
u32 val;

if (!device_may_wakeup(&sw->dev))
return;

if (tb_route(sw)) {
if (tb_sw_read(sw, &val, TB_CFG_SWITCH, ROUTER_CS_6, 1))
return;
Expand Down Expand Up @@ -244,8 +247,6 @@ int usb4_switch_setup(struct tb_switch *sw)
u32 val = 0;
int ret;

usb4_switch_check_wakes(sw);

if (!tb_route(sw))
return 0;

Expand Down
6 changes: 1 addition & 5 deletions drivers/usb/class/cdc-wdm.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,6 @@ static ssize_t wdm_write
static int service_outstanding_interrupt(struct wdm_device *desc)
{
int rv = 0;
int used;

/* submit read urb only if the device is waiting for it */
if (!desc->resp_count || !--desc->resp_count)
Expand All @@ -500,10 +499,7 @@ static int service_outstanding_interrupt(struct wdm_device *desc)
goto out;
}

used = test_and_set_bit(WDM_RESPONDING, &desc->flags);
if (used)
goto out;

set_bit(WDM_RESPONDING, &desc->flags);
spin_unlock_irq(&desc->iuspin);
rv = usb_submit_urb(desc->response, GFP_KERNEL);
spin_lock_irq(&desc->iuspin);
Expand Down
4 changes: 3 additions & 1 deletion drivers/usb/core/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,10 @@ static void usb_port_shutdown(struct device *dev)
{
struct usb_port *port_dev = to_usb_port(dev);

if (port_dev->child)
if (port_dev->child) {
usb_disable_usb2_hardware_lpm(port_dev->child);
usb_unlocked_disable_lpm(port_dev->child);
}
}

static const struct dev_pm_ops usb_port_pm_ops = {
Expand Down
4 changes: 3 additions & 1 deletion drivers/usb/dwc2/hcd_ddma.c
Original file line number Diff line number Diff line change
Expand Up @@ -867,13 +867,15 @@ static int dwc2_cmpl_host_isoc_dma_desc(struct dwc2_hsotg *hsotg,
struct dwc2_dma_desc *dma_desc;
struct dwc2_hcd_iso_packet_desc *frame_desc;
u16 frame_desc_idx;
struct urb *usb_urb = qtd->urb->priv;
struct urb *usb_urb;
u16 remain = 0;
int rc = 0;

if (!qtd->urb)
return -EINVAL;

usb_urb = qtd->urb->priv;

dma_sync_single_for_cpu(hsotg->dev, qh->desc_list_dma + (idx *
sizeof(struct dwc2_dma_desc)),
sizeof(struct dwc2_dma_desc),
Expand Down
3 changes: 2 additions & 1 deletion drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)

/* reinitialize physical ep1 */
dep = dwc->eps[1];
dep->flags = DWC3_EP_ENABLED;
dep->flags &= DWC3_EP_RESOURCE_ALLOCATED;
dep->flags |= DWC3_EP_ENABLED;

/* stall is always issued on EP0 */
dep = dwc->eps[0];
Expand Down
29 changes: 16 additions & 13 deletions drivers/usb/gadget/function/f_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@

#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */

#define DMABUF_ENQUEUE_TIMEOUT_MS 5000

MODULE_IMPORT_NS(DMA_BUF);

/* Reference counter handling */
Expand Down Expand Up @@ -1578,10 +1580,13 @@ static int ffs_dmabuf_transfer(struct file *file,
struct ffs_dmabuf_priv *priv;
struct ffs_dma_fence *fence;
struct usb_request *usb_req;
enum dma_resv_usage resv_dir;
struct dma_buf *dmabuf;
unsigned long timeout;
struct ffs_ep *ep;
bool cookie;
u32 seqno;
long retl;
int ret;

if (req->flags & ~USB_FFS_DMABUF_TRANSFER_MASK)
Expand Down Expand Up @@ -1615,17 +1620,14 @@ static int ffs_dmabuf_transfer(struct file *file,
goto err_attachment_put;

/* Make sure we don't have writers */
if (!dma_resv_test_signaled(dmabuf->resv, DMA_RESV_USAGE_WRITE)) {
pr_vdebug("FFS WRITE fence is not signaled\n");
ret = -EBUSY;
goto err_resv_unlock;
}

/* If we're writing to the DMABUF, make sure we don't have readers */
if (epfile->in &&
!dma_resv_test_signaled(dmabuf->resv, DMA_RESV_USAGE_READ)) {
pr_vdebug("FFS READ fence is not signaled\n");
ret = -EBUSY;
timeout = nonblock ? 0 : msecs_to_jiffies(DMABUF_ENQUEUE_TIMEOUT_MS);
retl = dma_resv_wait_timeout(dmabuf->resv,
dma_resv_usage_rw(epfile->in),
true, timeout);
if (retl == 0)
retl = -EBUSY;
if (retl < 0) {
ret = (int)retl;
goto err_resv_unlock;
}

Expand Down Expand Up @@ -1665,8 +1667,9 @@ static int ffs_dmabuf_transfer(struct file *file,
dma_fence_init(&fence->base, &ffs_dmabuf_fence_ops,
&priv->lock, priv->context, seqno);

dma_resv_add_fence(dmabuf->resv, &fence->base,
dma_resv_usage_rw(epfile->in));
resv_dir = epfile->in ? DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_READ;

dma_resv_add_fence(dmabuf->resv, &fence->base, resv_dir);
dma_resv_unlock(dmabuf->resv);

/* Now that the dma_fence is in place, queue the transfer. */
Expand Down
4 changes: 2 additions & 2 deletions drivers/usb/gadget/function/f_ncm.c
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ static int ncm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
if (alt > 1)
goto fail;

if (ncm->port.in_ep->enabled) {
if (ncm->netdev) {
DBG(cdev, "reset ncm\n");
ncm->netdev = NULL;
gether_disconnect(&ncm->port);
Expand Down Expand Up @@ -1367,7 +1367,7 @@ static void ncm_disable(struct usb_function *f)

DBG(cdev, "ncm deactivated\n");

if (ncm->port.in_ep->enabled) {
if (ncm->netdev) {
ncm->netdev = NULL;
gether_disconnect(&ncm->port);
}
Expand Down
5 changes: 2 additions & 3 deletions drivers/usb/gadget/udc/fsl_udc_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
{
struct fsl_ep *ep = container_of(_ep, struct fsl_ep, ep);
struct fsl_req *req = container_of(_req, struct fsl_req, req);
struct fsl_udc *udc;
struct fsl_udc *udc = ep->udc;
unsigned long flags;
int ret;

Expand All @@ -878,7 +878,7 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
dev_vdbg(&udc->gadget.dev, "%s, bad params\n", __func__);
return -EINVAL;
}
if (unlikely(!_ep || !ep->ep.desc)) {
if (unlikely(!ep->ep.desc)) {
dev_vdbg(&udc->gadget.dev, "%s, bad ep\n", __func__);
return -EINVAL;
}
Expand All @@ -887,7 +887,6 @@ fsl_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
return -EMSGSIZE;
}

udc = ep->udc;
if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
return -ESHUTDOWN;

Expand Down
9 changes: 4 additions & 5 deletions drivers/usb/host/xhci-ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -3133,20 +3133,21 @@ static int xhci_handle_events(struct xhci_hcd *xhci, struct xhci_interrupter *ir
irqreturn_t xhci_irq(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
irqreturn_t ret = IRQ_NONE;
irqreturn_t ret = IRQ_HANDLED;
u32 status;

spin_lock(&xhci->lock);
/* Check if the xHC generated the interrupt, or the irq is shared */
status = readl(&xhci->op_regs->status);
if (status == ~(u32)0) {
xhci_hc_died(xhci);
ret = IRQ_HANDLED;
goto out;
}

if (!(status & STS_EINT))
if (!(status & STS_EINT)) {
ret = IRQ_NONE;
goto out;
}

if (status & STS_HCE) {
xhci_warn(xhci, "WARNING: Host Controller Error\n");
Expand All @@ -3156,7 +3157,6 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
if (status & STS_FATAL) {
xhci_warn(xhci, "WARNING: Host System Error\n");
xhci_halt(xhci);
ret = IRQ_HANDLED;
goto out;
}

Expand All @@ -3167,7 +3167,6 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
*/
status |= STS_EINT;
writel(status, &xhci->op_regs->status);
ret = IRQ_HANDLED;

/* This is the handler of the primary interrupter */
xhci_handle_events(xhci, xhci->interrupters[0]);
Expand Down
Loading

0 comments on commit 5fa0ab4

Please sign in to comment.