Skip to content

Commit

Permalink
Merge tag 'usb-5.6-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/Thunderbolt fixes from Greg KH:
 "Here are a number of small USB driver fixes for 5.6-rc3.

  Included in here are:
  - MAINTAINER file updates
  - USB gadget driver fixes
  - usb core quirk additions and fixes for regressions
  - xhci driver fixes
  - usb serial driver id additions and fixes
  - thunderbolt bugfix

  Thunderbolt patches come in through here now that USB4 is really
  thunderbolt.

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

* tag 'usb-5.6-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (34 commits)
  USB: misc: iowarrior: add support for the 100 device
  thunderbolt: Prevent crash if non-active NVMem file is read
  usb: gadget: udc-xilinx: Fix xudc_stop() kernel-doc format
  USB: misc: iowarrior: add support for the 28 and 28L devices
  USB: misc: iowarrior: add support for 2 OEMed devices
  USB: Fix novation SourceControl XL after suspend
  xhci: Fix memory leak when caching protocol extended capability PSI tables - take 2
  Revert "xhci: Fix memory leak when caching protocol extended capability PSI tables"
  MAINTAINERS: Sort entries in database for THUNDERBOLT
  usb: dwc3: debug: fix string position formatting mixup with ret and len
  usb: gadget: serial: fix Tx stall after buffer overflow
  usb: gadget: ffs: ffs_aio_cancel(): Save/restore IRQ flags
  usb: dwc2: Fix SET/CLEAR_FEATURE and GET_STATUS flows
  usb: dwc2: Fix in ISOC request length checking
  usb: gadget: composite: Support more than 500mA MaxPower
  usb: gadget: composite: Fix bMaxPower for SuperSpeedPlus
  usb: gadget: u_audio: Fix high-speed max packet size
  usb: dwc3: gadget: Check for IOC/LST bit in TRB->ctrl fields
  USB: core: clean up endpoint-descriptor parsing
  USB: quirks: blacklist duplicate ep on Sound Devices USBPre2
  ...
  • Loading branch information
torvalds committed Feb 21, 2020
2 parents 88f8bbf + 8b978be commit cee853e
Show file tree
Hide file tree
Showing 26 changed files with 327 additions and 140 deletions.
20 changes: 10 additions & 10 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -16552,8 +16552,8 @@ M: Michael Jamet <[email protected]>
M: Mika Westerberg <[email protected]>
M: Yehezkel Bernat <[email protected]>
L: [email protected]
T: git git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt.git
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/westeri/thunderbolt.git
F: Documentation/admin-guide/thunderbolt.rst
F: drivers/thunderbolt/
F: include/linux/thunderbolt.h
Expand Down Expand Up @@ -17392,11 +17392,14 @@ F: drivers/usb/
F: include/linux/usb.h
F: include/linux/usb/

USB TYPEC PI3USB30532 MUX DRIVER
M: Hans de Goede <hdegoede@redhat.com>
USB TYPEC BUS FOR ALTERNATE MODES
M: Heikki Krogerus <[email protected].com>
L: [email protected]
S: Maintained
F: drivers/usb/typec/mux/pi3usb30532.c
F: Documentation/ABI/testing/sysfs-bus-typec
F: Documentation/driver-api/usb/typec_bus.rst
F: drivers/usb/typec/altmodes/
F: include/linux/usb/typec_altmode.h

USB TYPEC CLASS
M: Heikki Krogerus <[email protected]>
Expand All @@ -17407,14 +17410,11 @@ F: Documentation/driver-api/usb/typec.rst
F: drivers/usb/typec/
F: include/linux/usb/typec.h

USB TYPEC BUS FOR ALTERNATE MODES
M: Heikki Krogerus <[email protected].com>
USB TYPEC PI3USB30532 MUX DRIVER
M: Hans de Goede <hdegoede@redhat.com>
L: [email protected]
S: Maintained
F: Documentation/ABI/testing/sysfs-bus-typec
F: Documentation/driver-api/usb/typec_bus.rst
F: drivers/usb/typec/altmodes/
F: include/linux/usb/typec_altmode.h
F: drivers/usb/typec/mux/pi3usb30532.c

USB TYPEC PORT CONTROLLER DRIVERS
M: Guenter Roeck <[email protected]>
Expand Down
7 changes: 7 additions & 0 deletions drivers/thunderbolt/switch.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,12 @@ static int tb_switch_nvm_read(void *priv, unsigned int offset, void *val,
return ret;
}

static int tb_switch_nvm_no_read(void *priv, unsigned int offset, void *val,
size_t bytes)
{
return -EPERM;
}

static int tb_switch_nvm_write(void *priv, unsigned int offset, void *val,
size_t bytes)
{
Expand Down Expand Up @@ -393,6 +399,7 @@ static struct nvmem_device *register_nvmem(struct tb_switch *sw, int id,
config.read_only = true;
} else {
config.name = "nvm_non_active";
config.reg_read = tb_switch_nvm_no_read;
config.reg_write = tb_switch_nvm_write;
config.root_only = true;
}
Expand Down
31 changes: 19 additions & 12 deletions drivers/usb/core/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
struct usb_host_interface *ifp, int num_ep,
unsigned char *buffer, int size)
{
struct usb_device *udev = to_usb_device(ddev);
unsigned char *buffer0 = buffer;
struct usb_endpoint_descriptor *d;
struct usb_host_endpoint *endpoint;
Expand Down Expand Up @@ -297,6 +298,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
goto skip_to_next_endpoint_or_interface_descriptor;
}

/* Ignore blacklisted endpoints */
if (udev->quirks & USB_QUIRK_ENDPOINT_BLACKLIST) {
if (usb_endpoint_is_blacklisted(udev, ifp, d)) {
dev_warn(ddev, "config %d interface %d altsetting %d has a blacklisted endpoint with address 0x%X, skipping\n",
cfgno, inum, asnum,
d->bEndpointAddress);
goto skip_to_next_endpoint_or_interface_descriptor;
}
}

endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
++ifp->desc.bNumEndpoints;

Expand All @@ -311,7 +322,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
j = 255;
if (usb_endpoint_xfer_int(d)) {
i = 1;
switch (to_usb_device(ddev)->speed) {
switch (udev->speed) {
case USB_SPEED_SUPER_PLUS:
case USB_SPEED_SUPER:
case USB_SPEED_HIGH:
Expand All @@ -332,17 +343,15 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
/*
* This quirk fixes bIntervals reported in ms.
*/
if (to_usb_device(ddev)->quirks &
USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL) {
if (udev->quirks & USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL) {
n = clamp(fls(d->bInterval) + 3, i, j);
i = j = n;
}
/*
* This quirk fixes bIntervals reported in
* linear microframes.
*/
if (to_usb_device(ddev)->quirks &
USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL) {
if (udev->quirks & USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL) {
n = clamp(fls(d->bInterval), i, j);
i = j = n;
}
Expand All @@ -359,7 +368,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
} else if (usb_endpoint_xfer_isoc(d)) {
i = 1;
j = 16;
switch (to_usb_device(ddev)->speed) {
switch (udev->speed) {
case USB_SPEED_HIGH:
n = 7; /* 8 ms = 2^(7-1) uframes */
break;
Expand All @@ -381,8 +390,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
* explicitly forbidden by the USB spec. In an attempt to make
* them usable, we will try treating them as Interrupt endpoints.
*/
if (to_usb_device(ddev)->speed == USB_SPEED_LOW &&
usb_endpoint_xfer_bulk(d)) {
if (udev->speed == USB_SPEED_LOW && usb_endpoint_xfer_bulk(d)) {
dev_warn(ddev, "config %d interface %d altsetting %d "
"endpoint 0x%X is Bulk; changing to Interrupt\n",
cfgno, inum, asnum, d->bEndpointAddress);
Expand All @@ -406,7 +414,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,

/* Find the highest legal maxpacket size for this endpoint */
i = 0; /* additional transactions per microframe */
switch (to_usb_device(ddev)->speed) {
switch (udev->speed) {
case USB_SPEED_LOW:
maxpacket_maxes = low_speed_maxpacket_maxes;
break;
Expand Down Expand Up @@ -442,8 +450,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
* maxpacket sizes other than 512. High speed HCDs may not
* be able to handle that particular bug, so let's warn...
*/
if (to_usb_device(ddev)->speed == USB_SPEED_HIGH
&& usb_endpoint_xfer_bulk(d)) {
if (udev->speed == USB_SPEED_HIGH && usb_endpoint_xfer_bulk(d)) {
if (maxp != 512)
dev_warn(ddev, "config %d interface %d altsetting %d "
"bulk endpoint 0x%X has invalid maxpacket %d\n",
Expand All @@ -452,7 +459,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
}

/* Parse a possible SuperSpeed endpoint companion descriptor */
if (to_usb_device(ddev)->speed >= USB_SPEED_SUPER)
if (udev->speed >= USB_SPEED_SUPER)
usb_parse_ss_endpoint_companion(ddev, cfgno,
inum, asnum, endpoint, buffer, size);

Expand Down
20 changes: 15 additions & 5 deletions drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
#include "otg_whitelist.h"

#define USB_VENDOR_GENESYS_LOGIC 0x05e3
#define USB_VENDOR_SMSC 0x0424
#define HUB_QUIRK_CHECK_PORT_AUTOSUSPEND 0x01
#define HUB_QUIRK_DISABLE_AUTOSUSPEND 0x02

#define USB_TP_TRANSMISSION_DELAY 40 /* ns */
#define USB_TP_TRANSMISSION_DELAY_MAX 65535 /* ns */
Expand Down Expand Up @@ -1217,11 +1219,6 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
#ifdef CONFIG_PM
udev->reset_resume = 1;
#endif
/* Don't set the change_bits when the device
* was powered off.
*/
if (test_bit(port1, hub->power_bits))
set_bit(port1, hub->change_bits);

} else {
/* The power session is gone; tell hub_wq */
Expand Down Expand Up @@ -1731,6 +1728,10 @@ static void hub_disconnect(struct usb_interface *intf)
kfree(hub->buffer);

pm_suspend_ignore_children(&intf->dev, false);

if (hub->quirk_disable_autosuspend)
usb_autopm_put_interface(intf);

kref_put(&hub->kref, hub_release);
}

Expand Down Expand Up @@ -1863,6 +1864,11 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
hub->quirk_check_port_auto_suspend = 1;

if (id->driver_info & HUB_QUIRK_DISABLE_AUTOSUSPEND) {
hub->quirk_disable_autosuspend = 1;
usb_autopm_get_interface(intf);
}

if (hub_configure(hub, &desc->endpoint[0].desc) >= 0)
return 0;

Expand Down Expand Up @@ -5599,6 +5605,10 @@ static void hub_event(struct work_struct *work)
}

static const struct usb_device_id hub_id_table[] = {
{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS,
.idVendor = USB_VENDOR_SMSC,
.bInterfaceClass = USB_CLASS_HUB,
.driver_info = HUB_QUIRK_DISABLE_AUTOSUSPEND},
{ .match_flags = USB_DEVICE_ID_MATCH_VENDOR
| USB_DEVICE_ID_MATCH_INT_CLASS,
.idVendor = USB_VENDOR_GENESYS_LOGIC,
Expand Down
1 change: 1 addition & 0 deletions drivers/usb/core/hub.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ struct usb_hub {
unsigned quiescing:1;
unsigned disconnected:1;
unsigned in_reset:1;
unsigned quirk_disable_autosuspend:1;

unsigned quirk_check_port_auto_suspend:1;

Expand Down
40 changes: 40 additions & 0 deletions drivers/usb/core/quirks.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x0904, 0x6103), .driver_info =
USB_QUIRK_LINEAR_FRAME_INTR_BINTERVAL },

/* Sound Devices USBPre2 */
{ USB_DEVICE(0x0926, 0x0202), .driver_info =
USB_QUIRK_ENDPOINT_BLACKLIST },

/* Keytouch QWERTY Panel keyboard */
{ USB_DEVICE(0x0926, 0x3333), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
Expand Down Expand Up @@ -445,6 +449,9 @@ static const struct usb_device_id usb_quirk_list[] = {
/* INTEL VALUE SSD */
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },

/* novation SoundControl XL */
{ USB_DEVICE(0x1235, 0x0061), .driver_info = USB_QUIRK_RESET_RESUME },

{ } /* terminating entry must be last */
};

Expand Down Expand Up @@ -472,6 +479,39 @@ static const struct usb_device_id usb_amd_resume_quirk_list[] = {
{ } /* terminating entry must be last */
};

/*
* Entries for blacklisted endpoints that should be ignored when parsing
* configuration descriptors.
*
* Matched for devices with USB_QUIRK_ENDPOINT_BLACKLIST.
*/
static const struct usb_device_id usb_endpoint_blacklist[] = {
{ USB_DEVICE_INTERFACE_NUMBER(0x0926, 0x0202, 1), .driver_info = 0x85 },
{ }
};

bool usb_endpoint_is_blacklisted(struct usb_device *udev,
struct usb_host_interface *intf,
struct usb_endpoint_descriptor *epd)
{
const struct usb_device_id *id;
unsigned int address;

for (id = usb_endpoint_blacklist; id->match_flags; ++id) {
if (!usb_match_device(udev, id))
continue;

if (!usb_match_one_id_intf(udev, intf, id))
continue;

address = id->driver_info;
if (address == epd->bEndpointAddress)
return true;
}

return false;
}

static bool usb_match_any_interface(struct usb_device *udev,
const struct usb_device_id *id)
{
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/core/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ extern void usb_authorize_interface(struct usb_interface *);
extern void usb_detect_quirks(struct usb_device *udev);
extern void usb_detect_interface_quirks(struct usb_device *udev);
extern void usb_release_quirk_list(void);
extern bool usb_endpoint_is_blacklisted(struct usb_device *udev,
struct usb_host_interface *intf,
struct usb_endpoint_descriptor *epd);
extern int usb_remove_device(struct usb_device *udev);

extern int usb_get_device_descriptor(struct usb_device *dev,
Expand Down
40 changes: 23 additions & 17 deletions drivers/usb/dwc2/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -1083,11 +1083,6 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
else
packets = 1; /* send one packet if length is zero. */

if (hs_ep->isochronous && length > (hs_ep->mc * hs_ep->ep.maxpacket)) {
dev_err(hsotg->dev, "req length > maxpacket*mc\n");
return;
}

if (dir_in && index != 0)
if (hs_ep->isochronous)
epsize = DXEPTSIZ_MC(packets);
Expand Down Expand Up @@ -1391,6 +1386,13 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req,
req->actual = 0;
req->status = -EINPROGRESS;

/* Don't queue ISOC request if length greater than mps*mc */
if (hs_ep->isochronous &&
req->length > (hs_ep->mc * hs_ep->ep.maxpacket)) {
dev_err(hs->dev, "req length > maxpacket*mc\n");
return -EINVAL;
}

/* In DDMA mode for ISOC's don't queue request if length greater
* than descriptor limits.
*/
Expand Down Expand Up @@ -1632,6 +1634,7 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,
struct dwc2_hsotg_ep *ep0 = hsotg->eps_out[0];
struct dwc2_hsotg_ep *ep;
__le16 reply;
u16 status;
int ret;

dev_dbg(hsotg->dev, "%s: USB_REQ_GET_STATUS\n", __func__);
Expand All @@ -1643,11 +1646,10 @@ static int dwc2_hsotg_process_req_status(struct dwc2_hsotg *hsotg,

switch (ctrl->bRequestType & USB_RECIP_MASK) {
case USB_RECIP_DEVICE:
/*
* bit 0 => self powered
* bit 1 => remote wakeup
*/
reply = cpu_to_le16(0);
status = 1 << USB_DEVICE_SELF_POWERED;
status |= hsotg->remote_wakeup_allowed <<
USB_DEVICE_REMOTE_WAKEUP;
reply = cpu_to_le16(status);
break;

case USB_RECIP_INTERFACE:
Expand Down Expand Up @@ -1758,7 +1760,10 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
case USB_RECIP_DEVICE:
switch (wValue) {
case USB_DEVICE_REMOTE_WAKEUP:
hsotg->remote_wakeup_allowed = 1;
if (set)
hsotg->remote_wakeup_allowed = 1;
else
hsotg->remote_wakeup_allowed = 0;
break;

case USB_DEVICE_TEST_MODE:
Expand All @@ -1768,16 +1773,17 @@ static int dwc2_hsotg_process_req_feature(struct dwc2_hsotg *hsotg,
return -EINVAL;

hsotg->test_mode = wIndex >> 8;
ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
if (ret) {
dev_err(hsotg->dev,
"%s: failed to send reply\n", __func__);
return ret;
}
break;
default:
return -ENOENT;
}

ret = dwc2_hsotg_send_reply(hsotg, ep0, NULL, 0);
if (ret) {
dev_err(hsotg->dev,
"%s: failed to send reply\n", __func__);
return ret;
}
break;

case USB_RECIP_ENDPOINT:
Expand Down
Loading

0 comments on commit cee853e

Please sign in to comment.