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

Pull USB fixes from Greg KH:
 "Here are some small USB driver fixes for reported problems and
  regressions. Include in here are:

   - xhci driver fixes

   - cdns3 driver fixes

   - usb gadget driver fixes for syzbot found problems

   - typec driver fixes for broken hardware and other bugs found

   - kernel data leaks in mdc800 driver

   - usb storage driver fixes

   - other small USB driver fixes

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

* tag 'usb-7.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (25 commits)
  usb: typec: qcom-pmic-typec: drain cc_debounce_dwork if port_start() fails
  usb: typec: qcom-pmic-typec: disable cc_debounce_dwork on stop
  usb: gadget: fix null pointer dereference in usb_put_function_instance()
  usb: typec: qcom-pmic: cancel reset_work on stop
  usb: gadget: f_mass_storage: fix null pointer dereference in fsg_common_set_num_buffers()
  usb: f_mass_storage: Bump local buffer size in fsg_common_create_luns()
  usb: storage: realtek_cr: fix use-after-free on disconnect
  usb: cdnsp: fix wakeup from S3 after controller context loss
  usb-storage: ene_ub6250: fix race between scan work and probe
  USB: gadget: fix NULL pointer dereference in gadget_dev_ioctl()
  usb: gadget: f_midi: initialize work in f_midi_alloc()
  usb: gadget: f_midi2: fix use-after-free in string attribute show path
  usb: typec: tipd: Fix Thunderbolt altmode VDOs for cd321x
  usb: gadget: midi2: Fix null-pointer dereference in f_midi2_free_ep_reqs
  usb: typec: hd3ss3220: track VBUS enable state per consumer
  usb: dwc3: clear forceRM when issuing EndTransfer
  usb: dwc3: google: Initialise probe properties with DWC3_DEFAULT_PROPERTIES
  usb: typec: mux: avoid duplicated mux switches
  usb: typec: mux: Fix typec_switch_match()
  usb: image: mdc800: change kmalloc() to kzalloc()
  ...
This commit is contained in:
Linus Torvalds
2026-09-06 08:50:20 -07:00
24 changed files with 284 additions and 127 deletions
+106 -5
View File
@@ -1338,7 +1338,6 @@ static int cdnsp_run(struct cdnsp_device *pdev,
cdnsp_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512);
ret = cdnsp_start(pdev);
if (ret) {
ret = -ENODEV;
@@ -1837,6 +1836,82 @@ static void cdnsp_get_rev_cap(struct cdnsp_device *pdev)
readl(&pdev->rev_cap->tx_buff_size));
}
static void cdnsp_set_event_deq(struct cdnsp_device *pdev)
{
dma_addr_t deq;
u64 temp;
deq = cdnsp_trb_virt_to_dma(pdev->event_ring->deq_seg,
pdev->event_ring->dequeue);
/* Update controller event ring dequeue pointer */
temp = cdnsp_read_64(&pdev->ir_set->erst_dequeue);
temp &= ERST_PTR_MASK;
/*
* Don't clear the EHB bit (which is RW1C) because
* there might be more events to service.
*/
temp &= ~ERST_EHB;
cdnsp_write_64(((u64)deq & (u64)~ERST_PTR_MASK) | temp,
&pdev->ir_set->erst_dequeue);
}
static void cdnsp_add_interrupter(struct cdnsp_device *pdev)
{
u64 erst_base;
u32 erst_size;
/* Set ERST count with the number of entries in the segment table. */
erst_size = readl(&pdev->ir_set->erst_size);
erst_size &= ERST_SIZE_MASK;
erst_size |= ERST_NUM_SEGS;
writel(erst_size, &pdev->ir_set->erst_size);
/* Set the segment table base address. */
erst_base = cdnsp_read_64(&pdev->ir_set->erst_base);
erst_base &= ERST_PTR_MASK;
erst_base |= (pdev->erst.erst_dma_addr & (u64)~ERST_PTR_MASK);
cdnsp_write_64(erst_base, &pdev->ir_set->erst_base);
/* Set the event ring dequeue address. */
cdnsp_set_event_deq(pdev);
}
/* Set up basic CDNSP registers */
static void cdnsp_init(struct cdnsp_device *pdev)
{
unsigned int val;
u64 val_64;
val = readl(&pdev->op_regs->config_reg);
val |= ((val & ~MAX_DEVS) | CDNSP_DEV_MAX_SLOTS) | CONFIG_U3E;
writel(val, &pdev->op_regs->config_reg);
/* Initialize the Command ring */
cdnsp_ring_init(pdev, pdev->cmd_ring);
/* Set the address in the Command Ring Control register */
val_64 = cdnsp_read_64(&pdev->op_regs->cmd_ring);
val_64 = (val_64 & (u64)CMD_RING_RSVD_BITS) |
(pdev->cmd_ring->first_seg->dma & (u64)~CMD_RING_RSVD_BITS) |
pdev->cmd_ring->cycle_state;
cdnsp_write_64(val_64, &pdev->op_regs->cmd_ring);
/* Set Device Context Base Address Array pointer */
cdnsp_write_64(pdev->dcbaa->dma, &pdev->op_regs->dcbaa_ptr);
/* Set Doorbell array pointer */
val = readl(&pdev->cap_regs->db_off);
val &= DBOFF_MASK;
pdev->dba = (void __iomem *)pdev->cap_regs + val;
/* Initialize the Primary interrupter */
cdnsp_ring_init(pdev, pdev->event_ring);
cdnsp_add_interrupter(pdev);
}
static int cdnsp_gen_setup(struct cdnsp_device *pdev)
{
int ret;
@@ -1902,6 +1977,8 @@ static int cdnsp_gen_setup(struct cdnsp_device *pdev)
if (ret)
return ret;
cdnsp_init(pdev);
/*
* Software workaround for U1: after transition
* to U1 the controller starts gating clock, and in some cases,
@@ -2031,9 +2108,6 @@ static int cdnsp_gadget_suspend(struct cdns *cdns, bool do_wakeup)
struct cdnsp_device *pdev = cdns->gadget_dev;
unsigned long flags;
if (pdev->link_state == XDEV_U3)
return 0;
spin_lock_irqsave(&pdev->lock, flags);
cdnsp_disconnect_gadget(pdev);
cdnsp_stop(pdev);
@@ -2047,12 +2121,38 @@ static int cdnsp_gadget_resume(struct cdns *cdns, bool lost_power)
struct cdnsp_device *pdev = cdns->gadget_dev;
enum usb_device_speed max_speed;
unsigned long flags;
bool context_lost;
u32 val;
int ret;
if (!pdev->gadget_driver)
return 0;
spin_lock_irqsave(&pdev->lock, flags);
val = readl(&pdev->port3x_regs->mode_2);
context_lost = !!(val & CFG_3XPORT_U1_PIPE_CLK_GATE_EN) || lost_power;
if (context_lost) {
cdnsp_halt(pdev);
cdnsp_set_apb_timeout_value(pdev);
/* Reset the internal controller memory state and registers. */
ret = cdnsp_reset(pdev);
if (ret)
goto unlock;
val = readl(&pdev->port3x_regs->mode_2);
val &= ~CFG_3XPORT_U1_PIPE_CLK_GATE_EN;
writel(val, &pdev->port3x_regs->mode_2);
cdnsp_clear_cmd_ring(pdev);
memset(pdev->event_ring->first_seg->trbs, 0,
sizeof(union cdnsp_trb) * (TRBS_PER_SEGMENT));
cdnsp_init(pdev);
}
max_speed = pdev->gadget_driver->max_speed;
/* Limit speed if necessary. */
@@ -2060,9 +2160,10 @@ static int cdnsp_gadget_resume(struct cdns *cdns, bool lost_power)
ret = cdnsp_run(pdev, max_speed);
if (pdev->link_state == XDEV_U3)
if (!context_lost && pdev->link_state == XDEV_U3)
__cdnsp_gadget_wakeup(pdev);
unlock:
spin_unlock_irqrestore(&pdev->lock, flags);
return ret;
+1
View File
@@ -1510,6 +1510,7 @@ int cdnsp_endpoint_init(struct cdnsp_device *pdev,
int cdnsp_ring_expansion(struct cdnsp_device *pdev,
struct cdnsp_ring *ring,
unsigned int num_trbs, gfp_t flags);
void cdnsp_ring_init(struct cdnsp_device *pdev, struct cdnsp_ring *ring);
struct cdnsp_ring *cdnsp_dma_to_transfer_ring(struct cdnsp_ep *ep, u64 address);
int cdnsp_alloc_stream_info(struct cdnsp_device *pdev,
struct cdnsp_ep *pep,
+35 -63
View File
@@ -394,13 +394,6 @@ static struct cdnsp_ring *cdnsp_ring_alloc(struct cdnsp_device *pdev,
if (ret)
goto fail;
/* Only event ring does not use link TRB. */
if (type != TYPE_EVENT)
ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |=
cpu_to_le32(LINK_TOGGLE);
cdnsp_initialize_ring_info(ring);
trace_cdnsp_ring_alloc(ring);
return ring;
fail:
kfree(ring);
@@ -603,6 +596,7 @@ int cdnsp_alloc_stream_info(struct cdnsp_device *pdev,
if (!cur_ring)
goto cleanup_rings;
cdnsp_ring_init(pdev, cur_ring);
cur_ring->stream_id = cur_stream;
cur_ring->trb_address_map = &stream_info->trb_address_map;
@@ -698,6 +692,8 @@ static int cdnsp_alloc_priv_device(struct cdnsp_device *pdev)
if (!pdev->eps[0].ring)
goto fail;
cdnsp_ring_init(pdev, pdev->eps[0].ring);
/* Point to output device context in dcbaa. */
pdev->dcbaa->dev_context_ptrs[1] = cpu_to_le64(pdev->out_ctx.dma);
pdev->cmd.in_ctx = &pdev->in_ctx;
@@ -991,6 +987,8 @@ int cdnsp_endpoint_init(struct cdnsp_device *pdev,
if (!pep->ring)
return -ENOMEM;
cdnsp_ring_init(pdev, pep->ring);
pep->skip = false;
/* Fill the endpoint context */
@@ -1096,28 +1094,6 @@ void cdnsp_mem_cleanup(struct cdnsp_device *pdev)
pdev->active_port = NULL;
}
static void cdnsp_set_event_deq(struct cdnsp_device *pdev)
{
dma_addr_t deq;
u64 temp;
deq = cdnsp_trb_virt_to_dma(pdev->event_ring->deq_seg,
pdev->event_ring->dequeue);
/* Update controller event ring dequeue pointer */
temp = cdnsp_read_64(&pdev->ir_set->erst_dequeue);
temp &= ERST_PTR_MASK;
/*
* Don't clear the EHB bit (which is RW1C) because
* there might be more events to service.
*/
temp &= ~ERST_EHB;
cdnsp_write_64(((u64)deq & (u64)~ERST_PTR_MASK) | temp,
&pdev->ir_set->erst_dequeue);
}
static void cdnsp_add_in_port(struct cdnsp_device *pdev,
struct cdnsp_port *port,
__le32 __iomem *addr)
@@ -1226,6 +1202,36 @@ static int cdnsp_setup_port_arrays(struct cdnsp_device *pdev)
return 0;
}
static void cdnsp_initialize_ring_segments(struct cdnsp_device *pdev, struct cdnsp_ring *ring)
{
struct cdnsp_segment *seg;
/* Only event ring does not use link TRB. */
if (ring->type == TYPE_EVENT)
return;
seg = ring->first_seg;
while (seg) {
struct cdnsp_segment *next = seg->next;
cdnsp_link_segments(pdev, seg, next, ring->type);
if (next == ring->first_seg)
break;
seg = next;
}
ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |= cpu_to_le32(LINK_TOGGLE);
}
void cdnsp_ring_init(struct cdnsp_device *pdev, struct cdnsp_ring *ring)
{
cdnsp_initialize_ring_segments(pdev, ring);
cdnsp_initialize_ring_info(ring);
trace_cdnsp_ring_alloc(ring);
}
/*
* Initialize memory for CDNSP (one-time init).
*
@@ -1237,10 +1243,8 @@ int cdnsp_mem_init(struct cdnsp_device *pdev)
{
struct device *dev = pdev->dev;
int ret = -ENOMEM;
unsigned int val;
dma_addr_t dma;
u32 page_size;
u64 val_64;
/*
* Use 4K pages, since that's common and the minimum the
@@ -1248,10 +1252,6 @@ int cdnsp_mem_init(struct cdnsp_device *pdev)
*/
page_size = 1 << 12;
val = readl(&pdev->op_regs->config_reg);
val |= ((val & ~MAX_DEVS) | CDNSP_DEV_MAX_SLOTS) | CONFIG_U3E;
writel(val, &pdev->op_regs->config_reg);
/*
* Doorbell array must be physically contiguous
* and 64-byte (cache line) aligned.
@@ -1263,8 +1263,6 @@ int cdnsp_mem_init(struct cdnsp_device *pdev)
pdev->dcbaa->dma = dma;
cdnsp_write_64(dma, &pdev->op_regs->dcbaa_ptr);
/*
* Initialize the ring segment pool. The ring must be a contiguous
* structure comprised of TRBs. The TRBs must be 16 byte aligned,
@@ -1290,17 +1288,6 @@ int cdnsp_mem_init(struct cdnsp_device *pdev)
if (!pdev->cmd_ring)
goto destroy_device_pool;
/* Set the address in the Command Ring Control register */
val_64 = cdnsp_read_64(&pdev->op_regs->cmd_ring);
val_64 = (val_64 & (u64)CMD_RING_RSVD_BITS) |
(pdev->cmd_ring->first_seg->dma & (u64)~CMD_RING_RSVD_BITS) |
pdev->cmd_ring->cycle_state;
cdnsp_write_64(val_64, &pdev->op_regs->cmd_ring);
val = readl(&pdev->cap_regs->db_off);
val &= DBOFF_MASK;
pdev->dba = (void __iomem *)pdev->cap_regs + val;
/* Set ir_set to interrupt register set 0 */
pdev->ir_set = &pdev->run_regs->ir_set[0];
@@ -1317,21 +1304,6 @@ int cdnsp_mem_init(struct cdnsp_device *pdev)
if (ret)
goto free_event_ring;
/* Set ERST count with the number of entries in the segment table. */
val = readl(&pdev->ir_set->erst_size);
val &= ERST_SIZE_MASK;
val |= ERST_NUM_SEGS;
writel(val, &pdev->ir_set->erst_size);
/* Set the segment table base address. */
val_64 = cdnsp_read_64(&pdev->ir_set->erst_base);
val_64 &= ERST_PTR_MASK;
val_64 |= (pdev->erst.erst_dma_addr & (u64)~ERST_PTR_MASK);
cdnsp_write_64(val_64, &pdev->ir_set->erst_base);
/* Set the event ring dequeue address. */
cdnsp_set_event_deq(pdev);
ret = cdnsp_setup_port_arrays(pdev);
if (ret)
goto free_erst;
+1
View File
@@ -442,6 +442,7 @@ static int dwc3_google_probe(struct platform_device *pdev)
probe_data.dwc = &google->dwc;
probe_data.res = res;
probe_data.ignore_clocks_and_resets = true;
probe_data.properties = DWC3_DEFAULT_PROPERTIES;
ret = dwc3_core_probe(&probe_data);
if (ret) {
ret = dev_err_probe(dev, ret, "failed to register DWC3 Core\n");
+1 -1
View File
@@ -304,7 +304,7 @@ void dwc3_ep0_out_start(struct dwc3 *dwc)
dwc3_ep->flags &= ~DWC3_EP_DELAY_STOP;
if (dwc->connected)
dwc3_stop_active_transfer(dwc3_ep, true, true);
dwc3_stop_active_transfer(dwc3_ep, false, true);
else
dwc3_remove_requests(dwc, dwc3_ep, -ESHUTDOWN);
}
+13 -8
View File
@@ -1004,7 +1004,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action)
* controller to generate an ERDY to initiate the
* stream.
*/
dwc3_stop_active_transfer(dep, true, true);
dwc3_stop_active_transfer(dep, false, true);
/*
* All stream eps will reinitiate stream on NoStream
@@ -1032,7 +1032,7 @@ void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep, int status)
{
struct dwc3_request *req;
dwc3_stop_active_transfer(dep, true, false);
dwc3_stop_active_transfer(dep, false, false);
/* If endxfer is delayed, avoid unmapping requests */
if (dep->flags & DWC3_EP_DELAY_STOP)
@@ -1720,7 +1720,7 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep)
if (ret == -EAGAIN)
return ret;
dwc3_stop_active_transfer(dep, true, true);
dwc3_stop_active_transfer(dep, false, true);
list_for_each_entry_safe(req, tmp, &dep->started_list, list)
dwc3_gadget_move_cancelled_request(req, DWC3_REQUEST_STATUS_DEQUEUED);
@@ -1757,6 +1757,11 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc)
* the controller won't update the TRB progress on command
* completion. It also won't clear the HWO bit in the TRB.
* The command will also not complete immediately in that case.
*
* Older programming guide revisions recommended setting ForceRM to 1
* when ending a transfer. Newer programming guide revisions now
* recommend keeping ForceRM cleared, and TRBs are properly updated
* on command completion.
*/
static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool interrupt)
{
@@ -1882,7 +1887,7 @@ static int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep)
* to wait for the next XferNotReady to test the command again
*/
if (cmd_status == 0) {
dwc3_stop_active_transfer(dep, true, true);
dwc3_stop_active_transfer(dep, false, true);
return 0;
}
}
@@ -2165,7 +2170,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
struct dwc3_request *t;
/* wait until it is processed */
dwc3_stop_active_transfer(dep, true, true);
dwc3_stop_active_transfer(dep, false, true);
/*
* Remove any started request if the transfer is
@@ -2242,7 +2247,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
return 0;
}
dwc3_stop_active_transfer(dep, true, true);
dwc3_stop_active_transfer(dep, false, true);
list_for_each_entry_safe(req, tmp, &dep->started_list, list)
dwc3_gadget_move_cancelled_request(req, DWC3_REQUEST_STATUS_STALLED);
@@ -3368,7 +3373,7 @@ static void dwc3_nostream_work(struct work_struct *work)
dwc3_send_gadget_generic_command(dwc, cmd, dep->number);
} else {
dep->flags |= DWC3_EP_DELAY_START;
dwc3_stop_active_transfer(dep, true, true);
dwc3_stop_active_transfer(dep, false, true);
spin_unlock_irqrestore(&dwc->lock, flags);
return;
}
@@ -3726,7 +3731,7 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep,
if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
list_empty(&dep->started_list) &&
(list_empty(&dep->pending_list) || status == -EXDEV))
dwc3_stop_active_transfer(dep, true, true);
dwc3_stop_active_transfer(dep, false, true);
else if (dwc3_gadget_ep_should_continue(dep))
if (__dwc3_gadget_kick_transfer(dep) == 0)
no_started_trb = false;
+4 -1
View File
@@ -2747,6 +2747,9 @@ int fsg_common_set_num_buffers(struct fsg_common *common, unsigned int n)
struct fsg_buffhd *bh, *buffhds;
int i;
if (n < 2)
return -EINVAL;
buffhds = kzalloc_objs(*buffhds, n);
if (!buffhds)
return -ENOMEM;
@@ -2960,7 +2963,7 @@ EXPORT_SYMBOL_GPL(fsg_common_create_lun);
int fsg_common_create_luns(struct fsg_common *common, struct fsg_config *cfg)
{
char buf[8]; /* enough for 100000000 different numbers, decimal */
char buf[14];
int i, rc;
fsg_common_remove_luns(common);
+1 -1
View File
@@ -879,7 +879,6 @@ static int f_midi_bind(struct usb_configuration *c, struct usb_function *f)
int status, n, jack = 1, i = 0, endpoint_descriptor_index = 0;
midi->gadget = cdev->gadget;
INIT_WORK(&midi->work, f_midi_in_work);
status = f_midi_register_card(midi);
if (status < 0)
goto fail_register;
@@ -1377,6 +1376,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi)
status = -ENOMEM;
goto midi_free;
}
INIT_WORK(&midi->work, f_midi_in_work);
midi->out_ports = opts->out_ports;
midi->index = opts->index;
midi->buflen = opts->buflen;
+8 -9
View File
@@ -1145,7 +1145,7 @@ static int f_midi2_alloc_ep_reqs(struct f_midi2_usb_ep *usb_ep)
if (!usb_ep->reqs)
return -EINVAL;
for (i = 0; i < midi2->info.num_reqs; i++) {
for (i = 0; i < usb_ep->num_reqs; i++) {
if (usb_ep->reqs[i].req)
continue;
usb_ep->reqs[i].req = alloc_ep_req(usb_ep->usb_ep,
@@ -1160,10 +1160,9 @@ static int f_midi2_alloc_ep_reqs(struct f_midi2_usb_ep *usb_ep)
/* Free allocated requests */
static void f_midi2_free_ep_reqs(struct f_midi2_usb_ep *usb_ep)
{
struct f_midi2 *midi2 = usb_ep->card;
int i;
for (i = 0; i < midi2->info.num_reqs; i++) {
for (i = 0; i < usb_ep->num_reqs; i++) {
if (!usb_ep->reqs[i].req)
continue;
free_ep_req(usb_ep->usb_ep, usb_ep->reqs[i].req);
@@ -2178,13 +2177,13 @@ end:
/* generic show/store for string */
static ssize_t f_midi2_opts_str_show(struct f_midi2_opts *opts,
const char *str, char *page)
const char **strp, char *page)
{
int result = 0;
mutex_lock(&opts->lock);
if (str)
result = scnprintf(page, PAGE_SIZE, "%s\n", str);
if (*strp)
result = scnprintf(page, PAGE_SIZE, "%s\n", *strp);
mutex_unlock(&opts->lock);
return result;
}
@@ -2278,7 +2277,7 @@ static ssize_t f_midi2_block_opts_name_show(struct config_item *item,
{
struct f_midi2_block_opts *opts = to_f_midi2_block_opts(item);
return f_midi2_opts_str_show(opts->ep->opts, opts->info.name, page);
return f_midi2_opts_str_show(opts->ep->opts, &opts->info.name, page);
}
static ssize_t f_midi2_block_opts_name_store(struct config_item *item,
@@ -2435,7 +2434,7 @@ static ssize_t f_midi2_ep_opts_##name##_show(struct config_item *item, \
char *page) \
{ \
struct f_midi2_ep_opts *opts = to_f_midi2_ep_opts(item); \
return f_midi2_opts_str_show(opts->opts, opts->info.name, page);\
return f_midi2_opts_str_show(opts->opts, &opts->info.name, page);\
} \
\
static ssize_t f_midi2_ep_opts_##name##_store(struct config_item *item, \
@@ -2590,7 +2589,7 @@ static ssize_t f_midi2_opts_iface_name_show(struct config_item *item,
{
struct f_midi2_opts *opts = to_f_midi2_opts(item);
return f_midi2_opts_str_show(opts, opts->info.iface_name, page);
return f_midi2_opts_str_show(opts, &opts->info.iface_name, page);
}
static ssize_t f_midi2_opts_iface_name_store(struct config_item *item,
+1 -1
View File
@@ -70,7 +70,7 @@ void usb_put_function_instance(struct usb_function_instance *fi)
{
struct module *mod;
if (!fi)
if (!fi || !fi->fd)
return;
mod = fi->fd->mod;
+2 -1
View File
@@ -1260,10 +1260,11 @@ out:
static long gadget_dev_ioctl (struct file *fd, unsigned code, unsigned long value)
{
struct dev_data *dev = fd->private_data;
struct usb_gadget *gadget = dev->gadget;
struct usb_gadget *gadget;
long ret = -ENOTTY;
spin_lock_irq(&dev->lock);
gadget = dev->gadget;
if (dev->state == STATE_DEV_OPENED ||
dev->state == STATE_DEV_UNBOUND) {
/* Not bound to a UDC */
+1 -1
View File
@@ -2301,7 +2301,7 @@ xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int segs, gfp_t flags)
if (!segs)
segs = ERST_DEFAULT_SEGS;
max_segs = FIELD_GET(HCS_ERST_MAX, xhci->hcs_params2) << 2;
max_segs = BIT(FIELD_GET(HCS_ERST_MAX, xhci->hcs_params2));
segs = min(segs, max_segs);
ir = kzalloc_node(sizeof(*ir), flags, dev_to_node(dev));
+32 -11
View File
@@ -824,21 +824,18 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,
usb_hcd_giveback_urb(hcd, urb, status);
}
static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
struct xhci_ring *ring, struct xhci_td *td)
static void xhci_unmap_one_bounce_buffer(struct xhci_hcd *xhci,
struct xhci_ring *ring, struct xhci_td *td,
struct xhci_segment *seg)
{
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
struct xhci_segment *seg = td->bounce_seg;
struct urb *urb = td->urb;
size_t len;
if (!ring || !seg || !urb)
return;
if (usb_urb_dir_out(urb)) {
dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
DMA_TO_DEVICE);
return;
goto done;
}
dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
@@ -854,10 +851,29 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
memcpy(urb->transfer_buffer + seg->bounce_offs, seg->bounce_buf,
seg->bounce_len);
}
done:
seg->bounce_len = 0;
seg->bounce_offs = 0;
}
static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
struct xhci_ring *ring, struct xhci_td *td)
{
struct xhci_segment *seg;
int i = 0;
if (!td->bounce_seg || !ring || !td->urb)
return;
/* td->bounce_seg is the last one bounced, unmap them all */
for (seg = td->start_seg; i++ < ring->num_segs; seg = seg->next) {
if (seg->bounce_len)
xhci_unmap_one_bounce_buffer(xhci, ring, td, seg);
if (seg == td->bounce_seg)
break;
}
}
static void xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
struct xhci_ring *ep_ring, int status)
{
@@ -3685,7 +3701,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
&trb_buff_len,
ring->enq_seg)) {
send_addr = ring->enq_seg->bounce_dma;
/* assuming TD won't span 2 segs */
/* TD bounced at least, and last on this seg */
td->bounce_seg = ring->enq_seg;
}
}
@@ -4312,11 +4328,16 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
check_interval(urb, ep_ctx);
/*
* Check if this starts the isoc data flow. Relies on hw setting ep ctx
* state after doorbell ring. Consider adding list_empty(td_list) check
* Schedule the URB discontiguously if all previous URBs have completed.
* XXX core can't tell if completions are pending but not running yet.
*/
if (GET_EP_CTX_STATE(ep_ctx) != EP_STATE_RUNNING)
if (list_empty(&ep_ring->td_list) &&
!hcd_periodic_completion_in_progress(xhci_to_hcd(xhci), urb->ep)) {
if (GET_EP_CTX_STATE(ep_ctx) == EP_STATE_RUNNING)
xhci_dbg(xhci, "Unexpected running ring at isoc stream start, uframe: %d\n",
xep->next_uframe);
xep->next_uframe = -1;
}
return xhci_queue_isoc_tx(xhci, mem_flags, urb, slot_id, ep_index);
}
+2 -2
View File
@@ -1000,13 +1000,13 @@ static int __init usb_mdc800_init (void)
mdc800->downloaded = 0;
mdc800->written = 0;
mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL);
mdc800->irq_urb_buffer=kzalloc (8, GFP_KERNEL);
if (!mdc800->irq_urb_buffer)
goto cleanup_on_fail;
mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL);
if (!mdc800->write_urb_buffer)
goto cleanup_on_fail;
mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL);
mdc800->download_urb_buffer=kzalloc (64, GFP_KERNEL);
if (!mdc800->download_urb_buffer)
goto cleanup_on_fail;
+2
View File
@@ -2357,7 +2357,9 @@ static int ene_ub6250_probe(struct usb_interface *intf,
return result;
/* probe card type */
mutex_lock(&us->dev_mutex);
result = ene_get_card_type(us, REG_CARD_STATUS, info->bbuf);
mutex_unlock(&us->dev_mutex);
if (result != USB_STOR_XFER_GOOD) {
usb_stor_disconnect(intf);
return USB_STOR_TRANSPORT_ERROR;
+4 -5
View File
@@ -916,7 +916,6 @@ static int realtek_cr_autosuspend_setup(struct us_data *us)
us->proto_handler = rts51x_invoke_transport;
chip->timer_expires = 0;
timer_setup(&chip->rts51x_suspend_timer, rts51x_suspend_timer_fn, 0);
fw5895_init(us);
/* enable autosuspend function of the usb device */
@@ -934,10 +933,7 @@ static void realtek_cr_destructor(void *extra)
return;
#ifdef CONFIG_REALTEK_AUTOPM
if (ss_en) {
timer_delete(&chip->rts51x_suspend_timer);
chip->timer_expires = 0;
}
timer_shutdown_sync(&chip->rts51x_suspend_timer);
#endif
kfree(chip->status);
}
@@ -982,6 +978,9 @@ static int init_realtek_cr(struct us_data *us)
us->extra = chip;
us->extra_destructor = realtek_cr_destructor;
#ifdef CONFIG_REALTEK_AUTOPM
timer_setup(&chip->rts51x_suspend_timer, rts51x_suspend_timer_fn, 0);
#endif
us->max_lun = chip->max_lun = rts51x_get_max_lun(us);
chip->us = us;
+7 -2
View File
@@ -62,6 +62,7 @@ struct hd3ss3220 {
int id_irq;
struct regulator *vbus;
bool vbus_enabled;
};
static int hd3ss3220_set_power_opmode(struct hd3ss3220 *hd3ss3220, int power_opmode)
@@ -208,7 +209,7 @@ static void hd3ss3220_regulator_control(struct hd3ss3220 *hd3ss3220, bool on)
{
int ret;
if (regulator_is_enabled(hd3ss3220->vbus) == on)
if (hd3ss3220->vbus_enabled == on)
return;
if (on)
@@ -216,9 +217,13 @@ static void hd3ss3220_regulator_control(struct hd3ss3220 *hd3ss3220, bool on)
else
ret = regulator_disable(hd3ss3220->vbus);
if (ret)
if (ret) {
dev_err(hd3ss3220->dev,
"vbus regulator %s failed: %d\n", on ? "enable" : "disable", ret);
return;
}
hd3ss3220->vbus_enabled = on;
}
static void hd3ss3220_set_role(struct hd3ss3220 *hd3ss3220)
+18 -3
View File
@@ -57,6 +57,8 @@ static void *typec_switch_match(const struct fwnode_handle *fwnode,
*/
dev = class_find_device(&typec_mux_class, NULL, fwnode,
switch_fwnode_match);
if (!dev)
return ERR_PTR(-EPROBE_DEFER);
/* Skip duplicates */
for (i = 0; i < TYPEC_MUX_MAX_DEVS; i++)
@@ -65,7 +67,7 @@ static void *typec_switch_match(const struct fwnode_handle *fwnode,
return NULL;
}
return dev ? to_typec_switch_dev(dev) : ERR_PTR(-EPROBE_DEFER);
return to_typec_switch_dev(dev);
}
/**
@@ -275,7 +277,9 @@ static int mux_fwnode_match(struct device *dev, const void *fwnode)
static void *typec_mux_match(const struct fwnode_handle *fwnode,
const char *id, void *data)
{
struct typec_mux_dev **mux_devs = data;
struct device *dev;
int i;
/*
* Device graph (OF graph) does not give any means to identify the
@@ -290,8 +294,18 @@ static void *typec_mux_match(const struct fwnode_handle *fwnode,
dev = class_find_device(&typec_mux_class, NULL, fwnode,
mux_fwnode_match);
if (!dev)
return ERR_PTR(-EPROBE_DEFER);
return dev ? to_typec_mux_dev(dev) : ERR_PTR(-EPROBE_DEFER);
/* Skip duplicates */
for (i = 0; i < TYPEC_MUX_MAX_DEVS; i++)
if (to_typec_mux_dev(dev) == mux_devs[i]) {
put_device(dev);
return NULL;
}
return to_typec_mux_dev(dev);
}
/**
@@ -316,7 +330,8 @@ struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode)
return ERR_PTR(-ENOMEM);
count = fwnode_connection_find_matches(fwnode, "mode-switch",
NULL, typec_mux_match,
(void **)mux_devs,
typec_mux_match,
(void **)mux_devs,
ARRAY_SIZE(mux_devs));
if (count <= 0) {
@@ -543,6 +543,8 @@ static void qcom_pmic_typec_pdphy_stop(struct pmic_typec *tcpm)
for (i = 0; i < pmic_typec_pdphy->nr_irqs; i++)
disable_irq(pmic_typec_pdphy->irq_data[i].irq);
cancel_work_sync(&pmic_typec_pdphy->reset_work);
qcom_pmic_typec_pdphy_reset_on(pmic_typec_pdphy);
regulator_disable(pmic_typec_pdphy->vdd_pdphy);
@@ -683,6 +683,9 @@ static int qcom_pmic_typec_port_start(struct pmic_typec *tcpm,
enable_irq(pmic_typec_port->irq_data[i].irq);
done:
if (ret)
disable_delayed_work_sync(&pmic_typec_port->cc_debounce_dwork);
return ret;
}
@@ -693,6 +696,8 @@ static void qcom_pmic_typec_port_stop(struct pmic_typec *tcpm)
for (i = 0; i < pmic_typec_port->nr_irqs; i++)
disable_irq(pmic_typec_port->irq_data[i].irq);
disable_delayed_work_sync(&pmic_typec_port->cc_debounce_dwork);
}
int qcom_pmic_typec_port_probe(struct platform_device *pdev,
+22 -6
View File
@@ -7119,16 +7119,32 @@ static void tcpm_pd_event_handler(struct kthread_work *work)
}
}
if (events & TCPM_SOURCING_VBUS) {
tcpm_log(port, "sourcing vbus");
/*
* In fast role swap case TCPC autonomously sources vbus. Set vbus_source
* true as TCPM wouldn't have called tcpm_set_vbus.
* true conditionally as TCPM wouldn't have called tcpm_set_vbus.
* If TCPM calls tcpm_set_vbus to source vbus, vbus_source would already
* be true.
*
* When vbus is sourced on the command on TCPM i.e. TCPM called
* tcpm_set_vbus to source vbus, vbus_source would already be true.
* When TCPM_FRS_EVENT and TCPM_SOURCING_VBUS arrive simultaneously,
* handling TCPM_FRS_EVENT above transitions the state to AMS_START
* with upcoming_state FR_SWAP_SEND.
*/
port->vbus_source = true;
_tcpm_pd_vbus_on(port);
if (tcpm_port_is_source(port) ||
tcpm_port_is_debug_source(port) ||
(port->state == AMS_START && port->upcoming_state == FR_SWAP_SEND) ||
port->state == FR_SWAP_SEND ||
port->state == FR_SWAP_SEND_TIMEOUT ||
port->state == FR_SWAP_SNK_SRC_TRANSITION_TO_OFF ||
port->state == FR_SWAP_SNK_SRC_NEW_SINK_READY ||
port->state == FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED) {
tcpm_log(port, "sourcing vbus");
port->vbus_source = true;
_tcpm_pd_vbus_on(port);
} else {
tcpm_log(port, "Discarding sourcing vbus! Invalid state %s",
tcpm_states[port->state]);
}
}
if (events & TCPM_PORT_CLEAN) {
tcpm_log(port, "port clean");
+13 -4
View File
@@ -114,7 +114,6 @@ struct tps6598x_intel_vid_status_reg {
__le32 attention_vdo;
__le16 enter_vdo;
__le16 device_mode;
__le16 cable_mode;
} __packed;
/* Standard Task return codes */
@@ -731,9 +730,19 @@ static void cd321x_typec_update_mode(struct tps6598x *tps, struct cd321x_status
cd321x->state.mode == TYPEC_TBT_MODE)
return;
tbt_data.cable_mode = le16_to_cpu(st->intel_vid_status.cable_mode);
tbt_data.device_mode = le16_to_cpu(st->intel_vid_status.device_mode);
tbt_data.enter_vdo = le16_to_cpu(st->intel_vid_status.enter_vdo);
tbt_data.cable_mode = TBT_MODE |
TBT_SET_CABLE_SPEED(TPS_DATA_STATUS_TBT_CABLE_SPEED(st->data_status)) |
TBT_SET_CABLE_ROUNDED(TPS_DATA_STATUS_TBT_CABLE_GEN(st->data_status));
if (st->data_status & TPS_DATA_STATUS_OPTICAL_CABLE)
tbt_data.cable_mode |= TBT_CABLE_OPTICAL;
if (st->data_status & TPS_DATA_STATUS_ACTIVE_LINK_TRAIN)
tbt_data.cable_mode |= TBT_CABLE_LINK_TRAINING;
if (st->data_status & TPS_DATA_STATUS_ACTIVE_CABLE)
tbt_data.cable_mode |= TBT_CABLE_ACTIVE_PASSIVE;
tbt_data.device_mode = TBT_MODE |
(u32)le16_to_cpu(st->intel_vid_status.device_mode) << 16;
tbt_data.enter_vdo =
(u32)le16_to_cpu(st->intel_vid_status.enter_vdo) << 16;
cd321x->state.alt = cd321x->port_altmode_tbt;
cd321x->state.mode = TYPEC_TBT_MODE;
cd321x->state.data = &tbt_data;
+2 -2
View File
@@ -210,10 +210,10 @@
#define TPS_DATA_STATUS_DP_PIN_ASSIGNMENT(x) \
TPS_FIELD_GET(TPS_DATA_STATUS_DP_PIN_ASSIGNMENT_MASK, (x))
#define TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK GENMASK(27, 25)
#define TPS_DATA_STATUS_TBT_CABLE_SPEED \
#define TPS_DATA_STATUS_TBT_CABLE_SPEED(x) \
TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_SPEED_MASK, (x))
#define TPS_DATA_STATUS_TBT_CABLE_GEN_MASK GENMASK(29, 28)
#define TPS_DATA_STATUS_TBT_CABLE_GEN \
#define TPS_DATA_STATUS_TBT_CABLE_GEN(x) \
TPS_FIELD_GET(TPS_DATA_STATUS_TBT_CABLE_GEN_MASK, (x))
/* Map data status to DP spec assignments */
+1 -1
View File
@@ -74,7 +74,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
cur = 0xff;
}
if (cur != 0xff) {
if (cur < UCSI_MAX_ALTMODES) {
ret = dp->con->port_altmode[cur] == alt ? 0 : -EBUSY;
goto err_unlock;
}