Skip to content

Commit

Permalink
Merge tag 'usb-6.8-rc3' 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 driver fixes from Greg KH:
 "Here are a bunch of small USB driver fixes for 6.8-rc3. Included in
  here are:

   - new usb-serial driver ids

   - new dwc3 driver id added

   - typec driver change revert

   - ncm gadget driver endian bugfix

   - xhci bugfixes for a number of reported issues

   - usb hub bugfix for alternate settings

   - ulpi driver debugfs memory leak fix

   - chipidea driver bugfix

   - usb gadget driver fixes

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

* tag 'usb-6.8-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (24 commits)
  USB: serial: option: add Fibocom FM101-GL variant
  USB: serial: qcserial: add new usb-id for Dell Wireless DW5826e
  USB: serial: cp210x: add ID for IMST iM871A-USB
  usb: typec: tcpm: fix the PD disabled case
  usb: ucsi_acpi: Quirk to ack a connector change ack cmd
  usb: ucsi_acpi: Fix command completion handling
  usb: ucsi: Add missing ppm_lock
  usb: ulpi: Fix debugfs directory leak
  Revert "usb: typec: tcpm: fix cc role at port reset"
  usb: gadget: pch_udc: fix an Excess kernel-doc warning
  usb: f_mass_storage: forbid async queue when shutdown happen
  USB: hub: check for alternate port before enabling A_ALT_HNP_SUPPORT
  usb: chipidea: core: handle power lost in workqueue
  usb: dwc3: gadget: Fix NULL pointer dereference in dwc3_gadget_suspend
  usb: dwc3: pci: add support for the Intel Arrow Lake-H
  usb: core: Prevent null pointer dereference in update_port_device_state
  xhci: handle isoc Babble and Buffer Overrun events properly
  xhci: process isoc TD properly when there was a transaction error mid TD.
  xhci: fix off by one check when adding a secondary interrupter.
  xhci: fix possible null pointer dereference at secondary interrupter removal
  ...
  • Loading branch information
Linus Torvalds committed Feb 4, 2024
2 parents bdda52c + ad834c7 commit 809be62
Show file tree
Hide file tree
Showing 21 changed files with 267 additions and 90 deletions.
22 changes: 11 additions & 11 deletions Documentation/usb/gadget-testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -448,17 +448,17 @@ Function-specific configfs interface
The function name to use when creating the function directory is "ncm".
The NCM function provides these attributes in its function directory:

=============== ==================================================
ifname network device interface name associated with this
function instance
qmult queue length multiplier for high and super speed
host_addr MAC address of host's end of this
Ethernet over USB link
dev_addr MAC address of device's end of this
Ethernet over USB link
max_segment_size Segment size required for P2P connections. This
will set MTU to (max_segment_size - 14 bytes)
=============== ==================================================
======================= ==================================================
ifname network device interface name associated with this
function instance
qmult queue length multiplier for high and super speed
host_addr MAC address of host's end of this
Ethernet over USB link
dev_addr MAC address of device's end of this
Ethernet over USB link
max_segment_size Segment size required for P2P connections. This
will set MTU to 14 bytes
======================= ==================================================

and after creating the functions/ncm.<instance name> they contain default
values: qmult is 5, dev_addr and host_addr are randomly selected.
Expand Down
2 changes: 2 additions & 0 deletions drivers/usb/chipidea/ci.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ struct hw_bank {
* @enabled_otg_timer_bits: bits of enabled otg timers
* @next_otg_timer: next nearest enabled timer to be expired
* @work: work for role changing
* @power_lost_work: work for power lost handling
* @wq: workqueue thread
* @qh_pool: allocation pool for queue heads
* @td_pool: allocation pool for transfer descriptors
Expand Down Expand Up @@ -226,6 +227,7 @@ struct ci_hdrc {
enum otg_fsm_timer next_otg_timer;
struct usb_role_switch *role_switch;
struct work_struct work;
struct work_struct power_lost_work;
struct workqueue_struct *wq;

struct dma_pool *qh_pool;
Expand Down
44 changes: 24 additions & 20 deletions drivers/usb/chipidea/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,27 @@ static int ci_extcon_register(struct ci_hdrc *ci)
return 0;
}

static void ci_power_lost_work(struct work_struct *work)
{
struct ci_hdrc *ci = container_of(work, struct ci_hdrc, power_lost_work);
enum ci_role role;

disable_irq_nosync(ci->irq);
pm_runtime_get_sync(ci->dev);
if (!ci_otg_is_fsm_mode(ci)) {
role = ci_get_role(ci);

if (ci->role != role) {
ci_handle_id_switch(ci);
} else if (role == CI_ROLE_GADGET) {
if (ci->is_otg && hw_read_otgsc(ci, OTGSC_BSV))
usb_gadget_vbus_connect(&ci->gadget);
}
}
pm_runtime_put_sync(ci->dev);
enable_irq(ci->irq);
}

static DEFINE_IDA(ci_ida);

struct platform_device *ci_hdrc_add_device(struct device *dev,
Expand Down Expand Up @@ -1045,6 +1066,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)

spin_lock_init(&ci->lock);
mutex_init(&ci->mutex);
INIT_WORK(&ci->power_lost_work, ci_power_lost_work);

ci->dev = dev;
ci->platdata = dev_get_platdata(dev);
ci->imx28_write_fix = !!(ci->platdata->flags &
Expand Down Expand Up @@ -1396,25 +1419,6 @@ static int ci_suspend(struct device *dev)
return 0;
}

static void ci_handle_power_lost(struct ci_hdrc *ci)
{
enum ci_role role;

disable_irq_nosync(ci->irq);
if (!ci_otg_is_fsm_mode(ci)) {
role = ci_get_role(ci);

if (ci->role != role) {
ci_handle_id_switch(ci);
} else if (role == CI_ROLE_GADGET) {
if (ci->is_otg && hw_read_otgsc(ci, OTGSC_BSV))
usb_gadget_vbus_connect(&ci->gadget);
}
}

enable_irq(ci->irq);
}

static int ci_resume(struct device *dev)
{
struct ci_hdrc *ci = dev_get_drvdata(dev);
Expand Down Expand Up @@ -1446,7 +1450,7 @@ static int ci_resume(struct device *dev)
ci_role(ci)->resume(ci, power_lost);

if (power_lost)
ci_handle_power_lost(ci);
queue_work(system_freezable_wq, &ci->power_lost_work);

if (ci->supports_runtime_pm) {
pm_runtime_disable(dev);
Expand Down
2 changes: 1 addition & 1 deletion drivers/usb/common/ulpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi)
return ret;
}

root = debugfs_create_dir(dev_name(dev), ulpi_root);
root = debugfs_create_dir(dev_name(&ulpi->dev), ulpi_root);
debugfs_create_file("regs", 0444, root, ulpi, &ulpi_regs_fops);

dev_dbg(&ulpi->dev, "registered ULPI PHY: vendor %04x, product %04x\n",
Expand Down
46 changes: 32 additions & 14 deletions drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -2053,9 +2053,19 @@ static void update_port_device_state(struct usb_device *udev)

if (udev->parent) {
hub = usb_hub_to_struct_hub(udev->parent);
port_dev = hub->ports[udev->portnum - 1];
WRITE_ONCE(port_dev->state, udev->state);
sysfs_notify_dirent(port_dev->state_kn);

/*
* The Link Layer Validation System Driver (lvstest)
* has a test step to unbind the hub before running the
* rest of the procedure. This triggers hub_disconnect
* which will set the hub's maxchild to 0, further
* resulting in usb_hub_to_struct_hub returning NULL.
*/
if (hub) {
port_dev = hub->ports[udev->portnum - 1];
WRITE_ONCE(port_dev->state, udev->state);
sysfs_notify_dirent(port_dev->state_kn);
}
}
}

Expand Down Expand Up @@ -2388,17 +2398,25 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
}
} else if (desc->bLength == sizeof
(struct usb_otg_descriptor)) {
/* Set a_alt_hnp_support for legacy otg device */
err = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
USB_REQ_SET_FEATURE, 0,
USB_DEVICE_A_ALT_HNP_SUPPORT,
0, NULL, 0,
USB_CTRL_SET_TIMEOUT);
if (err < 0)
dev_err(&udev->dev,
"set a_alt_hnp_support failed: %d\n",
err);
/*
* We are operating on a legacy OTP device
* These should be told that they are operating
* on the wrong port if we have another port that does
* support HNP
*/
if (bus->otg_port != 0) {
/* Set a_alt_hnp_support for legacy otg device */
err = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
USB_REQ_SET_FEATURE, 0,
USB_DEVICE_A_ALT_HNP_SUPPORT,
0, NULL, 0,
USB_CTRL_SET_TIMEOUT);
if (err < 0)
dev_err(&udev->dev,
"set a_alt_hnp_support failed: %d\n",
err);
}
}
}
#endif
Expand Down
4 changes: 4 additions & 0 deletions drivers/usb/dwc3/dwc3-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#define PCI_DEVICE_ID_INTEL_MTLP 0x7ec1
#define PCI_DEVICE_ID_INTEL_MTLS 0x7f6f
#define PCI_DEVICE_ID_INTEL_MTL 0x7e7e
#define PCI_DEVICE_ID_INTEL_ARLH 0x7ec1
#define PCI_DEVICE_ID_INTEL_ARLH_PCH 0x777e
#define PCI_DEVICE_ID_INTEL_TGL 0x9a15
#define PCI_DEVICE_ID_AMD_MR 0x163a

Expand Down Expand Up @@ -421,6 +423,8 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
{ PCI_DEVICE_DATA(INTEL, MTLP, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, MTL, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, MTLS, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ARLH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, ARLH_PCH, &dwc3_pci_intel_swnode) },
{ PCI_DEVICE_DATA(INTEL, TGL, &dwc3_pci_intel_swnode) },

{ PCI_DEVICE_DATA(AMD, NL_USB, &dwc3_pci_amd_swnode) },
Expand Down
6 changes: 2 additions & 4 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -4709,15 +4709,13 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
unsigned long flags;
int ret;

if (!dwc->gadget_driver)
return 0;

ret = dwc3_gadget_soft_disconnect(dwc);
if (ret)
goto err;

spin_lock_irqsave(&dwc->lock, flags);
dwc3_disconnect_gadget(dwc);
if (dwc->gadget_driver)
dwc3_disconnect_gadget(dwc);
spin_unlock_irqrestore(&dwc->lock, flags);

return 0;
Expand Down
4 changes: 3 additions & 1 deletion drivers/usb/dwc3/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ static int dwc3_host_get_irq(struct dwc3 *dwc)

int dwc3_host_init(struct dwc3 *dwc)
{
struct property_entry props[4];
struct property_entry props[5];
struct platform_device *xhci;
int ret, irq;
int prop_idx = 0;
Expand Down Expand Up @@ -89,6 +89,8 @@ int dwc3_host_init(struct dwc3 *dwc)

memset(props, 0, sizeof(struct property_entry) * ARRAY_SIZE(props));

props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-sg-trb-cache-size-quirk");

if (dwc->usb3_lpm_capable)
props[prop_idx++] = PROPERTY_ENTRY_BOOL("usb3-lpm-capable");

Expand Down
20 changes: 18 additions & 2 deletions drivers/usb/gadget/function/f_mass_storage.c
Original file line number Diff line number Diff line change
Expand Up @@ -545,21 +545,37 @@ static int start_transfer(struct fsg_dev *fsg, struct usb_ep *ep,

static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
{
int rc;

if (!fsg_is_set(common))
return false;
bh->state = BUF_STATE_SENDING;
if (start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq))
rc = start_transfer(common->fsg, common->fsg->bulk_in, bh->inreq);
if (rc) {
bh->state = BUF_STATE_EMPTY;
if (rc == -ESHUTDOWN) {
common->running = 0;
return false;
}
}
return true;
}

static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh)
{
int rc;

if (!fsg_is_set(common))
return false;
bh->state = BUF_STATE_RECEIVING;
if (start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq))
rc = start_transfer(common->fsg, common->fsg->bulk_out, bh->outreq);
if (rc) {
bh->state = BUF_STATE_FULL;
if (rc == -ESHUTDOWN) {
common->running = 0;
return false;
}
}
return true;
}

Expand Down
8 changes: 4 additions & 4 deletions drivers/usb/gadget/function/f_ncm.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ static inline struct f_ncm *func_to_ncm(struct usb_function *f)

/*
* Although max mtu as dictated by u_ether is 15412 bytes, setting
* max_segment_sizeto 15426 would not be efficient. If user chooses segment
* size to be (>= 8192), then we can't aggregate more than one buffer in each
* max_segment_size to 15426 would not be efficient. If user chooses segment
* size to be (>= 8192), then we can't aggregate more than one buffer in each
* NTB (assuming each packet coming from network layer is >= 8192 bytes) as ep
* maxpacket limit is 16384. So let max_segment_size be limited to 8000 to allow
* at least 2 packets to be aggregated reducing wastage of NTB buffer space
Expand Down Expand Up @@ -1489,7 +1489,7 @@ static int ncm_bind(struct usb_configuration *c, struct usb_function *f)
ncm_data_intf.bInterfaceNumber = status;
ncm_union_desc.bSlaveInterface0 = status;

ecm_desc.wMaxSegmentSize = ncm_opts->max_segment_size;
ecm_desc.wMaxSegmentSize = cpu_to_le16(ncm_opts->max_segment_size);

status = -ENODEV;

Expand Down Expand Up @@ -1685,7 +1685,7 @@ static struct usb_function_instance *ncm_alloc_inst(void)
kfree(opts);
return ERR_CAST(net);
}
opts->max_segment_size = cpu_to_le16(ETH_FRAME_LEN);
opts->max_segment_size = ETH_FRAME_LEN;
INIT_LIST_HEAD(&opts->ncm_os_desc.ext_prop);

descs[0] = &opts->ncm_os_desc;
Expand Down
1 change: 0 additions & 1 deletion drivers/usb/gadget/udc/pch_udc.c
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,6 @@ struct pch_udc_cfg_data {
* @td_data: for data request
* @dev: reference to device struct
* @offset_addr: offset address of ep register
* @desc: for this ep
* @queue: queue for requests
* @num: endpoint number
* @in: endpoint is IN
Expand Down
14 changes: 7 additions & 7 deletions drivers/usb/host/xhci-mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1861,14 +1861,14 @@ void xhci_remove_secondary_interrupter(struct usb_hcd *hcd, struct xhci_interrup
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
unsigned int intr_num;

spin_lock_irq(&xhci->lock);

/* interrupter 0 is primary interrupter, don't touch it */
if (!ir || !ir->intr_num || ir->intr_num >= xhci->max_interrupters)
if (!ir || !ir->intr_num || ir->intr_num >= xhci->max_interrupters) {
xhci_dbg(xhci, "Invalid secondary interrupter, can't remove\n");

/* fixme, should we check xhci->interrupter[intr_num] == ir */
/* fixme locking */

spin_lock_irq(&xhci->lock);
spin_unlock_irq(&xhci->lock);
return;
}

intr_num = ir->intr_num;

Expand Down Expand Up @@ -2322,7 +2322,7 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir,
u64 erst_base;
u32 erst_size;

if (intr_num > xhci->max_interrupters) {
if (intr_num >= xhci->max_interrupters) {
xhci_warn(xhci, "Can't add interrupter %d, max interrupters %d\n",
intr_num, xhci->max_interrupters);
return -EINVAL;
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/host/xhci-plat.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,9 @@ int xhci_plat_probe(struct platform_device *pdev, struct device *sysdev, const s
if (device_property_read_bool(tmpdev, "quirk-broken-port-ped"))
xhci->quirks |= XHCI_BROKEN_PORT_PED;

if (device_property_read_bool(tmpdev, "xhci-sg-trb-cache-size-quirk"))
xhci->quirks |= XHCI_SG_TRB_CACHE_SIZE_QUIRK;

device_property_read_u32(tmpdev, "imod-interval-ns",
&xhci->imod_interval);
}
Expand Down
Loading

0 comments on commit 809be62

Please sign in to comment.