mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-18 18:23:53 +08:00
USB fixes for 5.6-rc3
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. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXk+/zw8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ynQywCeOlklNLcTKw/JkbsbtMlY/yTl4W8AoLLoEgSy GyUV8E67wZNdXLKH+n14 =o97t -----END PGP SIGNATURE----- Merge tag 'usb-5.6-rc3' of git://git.kernel.org/pub/scm/linux/kernel/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 ...
This commit is contained in:
commit
cee853e825
20
MAINTAINERS
20
MAINTAINERS
@ -16552,8 +16552,8 @@ M: Michael Jamet <michael.jamet@intel.com>
|
||||
M: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
M: Yehezkel Bernat <YehezkelShB@gmail.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
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
|
||||
@ -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 <heikki.krogerus@linux.intel.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
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 <heikki.krogerus@linux.intel.com>
|
||||
@ -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 <heikki.krogerus@linux.intel.com>
|
||||
USB TYPEC PI3USB30532 MUX DRIVER
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
L: linux-usb@vger.kernel.org
|
||||
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 <linux@roeck-us.net>
|
||||
|
@ -348,6 +348,12 @@ out:
|
||||
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)
|
||||
{
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
@ -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;
|
||||
|
||||
@ -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:
|
||||
@ -332,8 +343,7 @@ 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;
|
||||
}
|
||||
@ -341,8 +351,7 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno,
|
||||
* 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;
|
||||
}
|
||||
@ -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;
|
||||
@ -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);
|
||||
@ -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;
|
||||
@ -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",
|
||||
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
@ -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 */
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -5599,6 +5605,10 @@ out_hdev_lock:
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 },
|
||||
@ -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 */
|
||||
};
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
@ -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.
|
||||
*/
|
||||
@ -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__);
|
||||
@ -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:
|
||||
@ -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:
|
||||
@ -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:
|
||||
|
@ -256,86 +256,77 @@ static inline const char *dwc3_ep_event_string(char *str, size_t size,
|
||||
u8 epnum = event->endpoint_number;
|
||||
size_t len;
|
||||
int status;
|
||||
int ret;
|
||||
|
||||
ret = snprintf(str, size, "ep%d%s: ", epnum >> 1,
|
||||
len = scnprintf(str, size, "ep%d%s: ", epnum >> 1,
|
||||
(epnum & 1) ? "in" : "out");
|
||||
if (ret < 0)
|
||||
return "UNKNOWN";
|
||||
|
||||
status = event->status;
|
||||
|
||||
switch (event->endpoint_event) {
|
||||
case DWC3_DEPEVT_XFERCOMPLETE:
|
||||
len = strlen(str);
|
||||
snprintf(str + len, size - len, "Transfer Complete (%c%c%c)",
|
||||
len += scnprintf(str + len, size - len,
|
||||
"Transfer Complete (%c%c%c)",
|
||||
status & DEPEVT_STATUS_SHORT ? 'S' : 's',
|
||||
status & DEPEVT_STATUS_IOC ? 'I' : 'i',
|
||||
status & DEPEVT_STATUS_LST ? 'L' : 'l');
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
if (epnum <= 1)
|
||||
snprintf(str + len, size - len, " [%s]",
|
||||
scnprintf(str + len, size - len, " [%s]",
|
||||
dwc3_ep0_state_string(ep0state));
|
||||
break;
|
||||
case DWC3_DEPEVT_XFERINPROGRESS:
|
||||
len = strlen(str);
|
||||
|
||||
snprintf(str + len, size - len, "Transfer In Progress [%d] (%c%c%c)",
|
||||
scnprintf(str + len, size - len,
|
||||
"Transfer In Progress [%d] (%c%c%c)",
|
||||
event->parameters,
|
||||
status & DEPEVT_STATUS_SHORT ? 'S' : 's',
|
||||
status & DEPEVT_STATUS_IOC ? 'I' : 'i',
|
||||
status & DEPEVT_STATUS_LST ? 'M' : 'm');
|
||||
break;
|
||||
case DWC3_DEPEVT_XFERNOTREADY:
|
||||
len = strlen(str);
|
||||
|
||||
snprintf(str + len, size - len, "Transfer Not Ready [%d]%s",
|
||||
len += scnprintf(str + len, size - len,
|
||||
"Transfer Not Ready [%d]%s",
|
||||
event->parameters,
|
||||
status & DEPEVT_STATUS_TRANSFER_ACTIVE ?
|
||||
" (Active)" : " (Not Active)");
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
/* Control Endpoints */
|
||||
if (epnum <= 1) {
|
||||
int phase = DEPEVT_STATUS_CONTROL_PHASE(event->status);
|
||||
|
||||
switch (phase) {
|
||||
case DEPEVT_STATUS_CONTROL_DATA:
|
||||
snprintf(str + ret, size - ret,
|
||||
scnprintf(str + len, size - len,
|
||||
" [Data Phase]");
|
||||
break;
|
||||
case DEPEVT_STATUS_CONTROL_STATUS:
|
||||
snprintf(str + ret, size - ret,
|
||||
scnprintf(str + len, size - len,
|
||||
" [Status Phase]");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DWC3_DEPEVT_RXTXFIFOEVT:
|
||||
snprintf(str + ret, size - ret, "FIFO");
|
||||
scnprintf(str + len, size - len, "FIFO");
|
||||
break;
|
||||
case DWC3_DEPEVT_STREAMEVT:
|
||||
status = event->status;
|
||||
|
||||
switch (status) {
|
||||
case DEPEVT_STREAMEVT_FOUND:
|
||||
snprintf(str + ret, size - ret, " Stream %d Found",
|
||||
scnprintf(str + len, size - len, " Stream %d Found",
|
||||
event->parameters);
|
||||
break;
|
||||
case DEPEVT_STREAMEVT_NOTFOUND:
|
||||
default:
|
||||
snprintf(str + ret, size - ret, " Stream Not Found");
|
||||
scnprintf(str + len, size - len, " Stream Not Found");
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case DWC3_DEPEVT_EPCMDCMPLT:
|
||||
snprintf(str + ret, size - ret, "Endpoint Command Complete");
|
||||
scnprintf(str + len, size - len, "Endpoint Command Complete");
|
||||
break;
|
||||
default:
|
||||
snprintf(str, size, "UNKNOWN");
|
||||
scnprintf(str + len, size - len, "UNKNOWN");
|
||||
}
|
||||
|
||||
return str;
|
||||
|
@ -2429,7 +2429,8 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,
|
||||
if (event->status & DEPEVT_STATUS_SHORT && !chain)
|
||||
return 1;
|
||||
|
||||
if (event->status & DEPEVT_STATUS_IOC)
|
||||
if ((trb->ctrl & DWC3_TRB_CTRL_IOC) ||
|
||||
(trb->ctrl & DWC3_TRB_CTRL_LST))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
@ -437,12 +437,14 @@ static u8 encode_bMaxPower(enum usb_device_speed speed,
|
||||
val = CONFIG_USB_GADGET_VBUS_DRAW;
|
||||
if (!val)
|
||||
return 0;
|
||||
switch (speed) {
|
||||
case USB_SPEED_SUPER:
|
||||
return DIV_ROUND_UP(val, 8);
|
||||
default:
|
||||
return DIV_ROUND_UP(val, 2);
|
||||
}
|
||||
if (speed < USB_SPEED_SUPER)
|
||||
return min(val, 500U) / 2;
|
||||
else
|
||||
/*
|
||||
* USB 3.x supports up to 900mA, but since 900 isn't divisible
|
||||
* by 8 the integral division will effectively cap to 896mA.
|
||||
*/
|
||||
return min(val, 900U) / 8;
|
||||
}
|
||||
|
||||
static int config_buf(struct usb_configuration *config,
|
||||
@ -854,6 +856,10 @@ static int set_config(struct usb_composite_dev *cdev,
|
||||
|
||||
/* when we return, be sure our power usage is valid */
|
||||
power = c->MaxPower ? c->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
|
||||
if (gadget->speed < USB_SPEED_SUPER)
|
||||
power = min(power, 500U);
|
||||
else
|
||||
power = min(power, 900U);
|
||||
done:
|
||||
usb_gadget_vbus_draw(gadget, power);
|
||||
if (result >= 0 && cdev->delayed_status)
|
||||
@ -2280,7 +2286,7 @@ void composite_resume(struct usb_gadget *gadget)
|
||||
{
|
||||
struct usb_composite_dev *cdev = get_gadget_data(gadget);
|
||||
struct usb_function *f;
|
||||
u16 maxpower;
|
||||
unsigned maxpower;
|
||||
|
||||
/* REVISIT: should we have config level
|
||||
* suspend/resume callbacks?
|
||||
@ -2294,10 +2300,14 @@ void composite_resume(struct usb_gadget *gadget)
|
||||
f->resume(f);
|
||||
}
|
||||
|
||||
maxpower = cdev->config->MaxPower;
|
||||
maxpower = cdev->config->MaxPower ?
|
||||
cdev->config->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
|
||||
if (gadget->speed < USB_SPEED_SUPER)
|
||||
maxpower = min(maxpower, 500U);
|
||||
else
|
||||
maxpower = min(maxpower, 900U);
|
||||
|
||||
usb_gadget_vbus_draw(gadget, maxpower ?
|
||||
maxpower : CONFIG_USB_GADGET_VBUS_DRAW);
|
||||
usb_gadget_vbus_draw(gadget, maxpower);
|
||||
}
|
||||
|
||||
cdev->suspended = 0;
|
||||
|
@ -1162,18 +1162,19 @@ static int ffs_aio_cancel(struct kiocb *kiocb)
|
||||
{
|
||||
struct ffs_io_data *io_data = kiocb->private;
|
||||
struct ffs_epfile *epfile = kiocb->ki_filp->private_data;
|
||||
unsigned long flags;
|
||||
int value;
|
||||
|
||||
ENTER();
|
||||
|
||||
spin_lock_irq(&epfile->ffs->eps_lock);
|
||||
spin_lock_irqsave(&epfile->ffs->eps_lock, flags);
|
||||
|
||||
if (likely(io_data && io_data->ep && io_data->req))
|
||||
value = usb_ep_dequeue(io_data->ep, io_data->req);
|
||||
else
|
||||
value = -EINVAL;
|
||||
|
||||
spin_unlock_irq(&epfile->ffs->eps_lock);
|
||||
spin_unlock_irqrestore(&epfile->ffs->eps_lock, flags);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -361,7 +361,7 @@ int u_audio_start_capture(struct g_audio *audio_dev)
|
||||
ep = audio_dev->out_ep;
|
||||
prm = &uac->c_prm;
|
||||
config_ep_by_speed(gadget, &audio_dev->func, ep);
|
||||
req_len = prm->max_psize;
|
||||
req_len = ep->maxpacket;
|
||||
|
||||
prm->ep_enabled = true;
|
||||
usb_ep_enable(ep);
|
||||
@ -379,7 +379,7 @@ int u_audio_start_capture(struct g_audio *audio_dev)
|
||||
req->context = &prm->ureq[i];
|
||||
req->length = req_len;
|
||||
req->complete = u_audio_iso_complete;
|
||||
req->buf = prm->rbuf + i * prm->max_psize;
|
||||
req->buf = prm->rbuf + i * ep->maxpacket;
|
||||
}
|
||||
|
||||
if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
|
||||
@ -430,9 +430,9 @@ int u_audio_start_playback(struct g_audio *audio_dev)
|
||||
uac->p_pktsize = min_t(unsigned int,
|
||||
uac->p_framesize *
|
||||
(params->p_srate / uac->p_interval),
|
||||
prm->max_psize);
|
||||
ep->maxpacket);
|
||||
|
||||
if (uac->p_pktsize < prm->max_psize)
|
||||
if (uac->p_pktsize < ep->maxpacket)
|
||||
uac->p_pktsize_residue = uac->p_framesize *
|
||||
(params->p_srate % uac->p_interval);
|
||||
else
|
||||
@ -457,7 +457,7 @@ int u_audio_start_playback(struct g_audio *audio_dev)
|
||||
req->context = &prm->ureq[i];
|
||||
req->length = req_len;
|
||||
req->complete = u_audio_iso_complete;
|
||||
req->buf = prm->rbuf + i * prm->max_psize;
|
||||
req->buf = prm->rbuf + i * ep->maxpacket;
|
||||
}
|
||||
|
||||
if (usb_ep_queue(ep, prm->ureq[i].req, GFP_ATOMIC))
|
||||
|
@ -561,8 +561,10 @@ static int gs_start_io(struct gs_port *port)
|
||||
port->n_read = 0;
|
||||
started = gs_start_rx(port);
|
||||
|
||||
/* unblock any pending writes into our circular buffer */
|
||||
if (started) {
|
||||
gs_start_tx(port);
|
||||
/* Unblock any pending writes into our circular buffer, in case
|
||||
* we didn't in gs_start_tx() */
|
||||
tty_wakeup(port->port.tty);
|
||||
} else {
|
||||
gs_free_requests(ep, head, &port->read_allocated);
|
||||
|
@ -1399,7 +1399,6 @@ err:
|
||||
/**
|
||||
* xudc_stop - stops the device.
|
||||
* @gadget: pointer to the usb gadget structure
|
||||
* @driver: pointer to usb gadget driver structure
|
||||
*
|
||||
* Return: zero always
|
||||
*/
|
||||
|
@ -55,6 +55,7 @@ static u8 usb_bos_descriptor [] = {
|
||||
static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
|
||||
u16 wLength)
|
||||
{
|
||||
struct xhci_port_cap *port_cap = NULL;
|
||||
int i, ssa_count;
|
||||
u32 temp;
|
||||
u16 desc_size, ssp_cap_size, ssa_size = 0;
|
||||
@ -64,16 +65,24 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
|
||||
ssp_cap_size = sizeof(usb_bos_descriptor) - desc_size;
|
||||
|
||||
/* does xhci support USB 3.1 Enhanced SuperSpeed */
|
||||
if (xhci->usb3_rhub.min_rev >= 0x01) {
|
||||
for (i = 0; i < xhci->num_port_caps; i++) {
|
||||
if (xhci->port_caps[i].maj_rev == 0x03 &&
|
||||
xhci->port_caps[i].min_rev >= 0x01) {
|
||||
usb3_1 = true;
|
||||
port_cap = &xhci->port_caps[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (usb3_1) {
|
||||
/* does xhci provide a PSI table for SSA speed attributes? */
|
||||
if (xhci->usb3_rhub.psi_count) {
|
||||
if (port_cap->psi_count) {
|
||||
/* two SSA entries for each unique PSI ID, RX and TX */
|
||||
ssa_count = xhci->usb3_rhub.psi_uid_count * 2;
|
||||
ssa_count = port_cap->psi_uid_count * 2;
|
||||
ssa_size = ssa_count * sizeof(u32);
|
||||
ssp_cap_size -= 16; /* skip copying the default SSA */
|
||||
}
|
||||
desc_size += ssp_cap_size;
|
||||
usb3_1 = true;
|
||||
}
|
||||
memcpy(buf, &usb_bos_descriptor, min(desc_size, wLength));
|
||||
|
||||
@ -99,7 +108,7 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
|
||||
}
|
||||
|
||||
/* If PSI table exists, add the custom speed attributes from it */
|
||||
if (usb3_1 && xhci->usb3_rhub.psi_count) {
|
||||
if (usb3_1 && port_cap->psi_count) {
|
||||
u32 ssp_cap_base, bm_attrib, psi, psi_mant, psi_exp;
|
||||
int offset;
|
||||
|
||||
@ -111,7 +120,7 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
|
||||
|
||||
/* attribute count SSAC bits 4:0 and ID count SSIC bits 8:5 */
|
||||
bm_attrib = (ssa_count - 1) & 0x1f;
|
||||
bm_attrib |= (xhci->usb3_rhub.psi_uid_count - 1) << 5;
|
||||
bm_attrib |= (port_cap->psi_uid_count - 1) << 5;
|
||||
put_unaligned_le32(bm_attrib, &buf[ssp_cap_base + 4]);
|
||||
|
||||
if (wLength < desc_size + ssa_size)
|
||||
@ -124,8 +133,8 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf,
|
||||
* USB 3.1 requires two SSA entries (RX and TX) for every link
|
||||
*/
|
||||
offset = desc_size;
|
||||
for (i = 0; i < xhci->usb3_rhub.psi_count; i++) {
|
||||
psi = xhci->usb3_rhub.psi[i];
|
||||
for (i = 0; i < port_cap->psi_count; i++) {
|
||||
psi = port_cap->psi[i];
|
||||
psi &= ~USB_SSP_SUBLINK_SPEED_RSVD;
|
||||
psi_exp = XHCI_EXT_PORT_PSIE(psi);
|
||||
psi_mant = XHCI_EXT_PORT_PSIM(psi);
|
||||
|
@ -1475,9 +1475,15 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
|
||||
/* Allow 3 retries for everything but isoc, set CErr = 3 */
|
||||
if (!usb_endpoint_xfer_isoc(&ep->desc))
|
||||
err_count = 3;
|
||||
/* Some devices get this wrong */
|
||||
if (usb_endpoint_xfer_bulk(&ep->desc) && udev->speed == USB_SPEED_HIGH)
|
||||
max_packet = 512;
|
||||
/* HS bulk max packet should be 512, FS bulk supports 8, 16, 32 or 64 */
|
||||
if (usb_endpoint_xfer_bulk(&ep->desc)) {
|
||||
if (udev->speed == USB_SPEED_HIGH)
|
||||
max_packet = 512;
|
||||
if (udev->speed == USB_SPEED_FULL) {
|
||||
max_packet = rounddown_pow_of_two(max_packet);
|
||||
max_packet = clamp_val(max_packet, 8, 64);
|
||||
}
|
||||
}
|
||||
/* xHCI 1.0 and 1.1 indicates that ctrl ep avg TRB Length should be 8 */
|
||||
if (usb_endpoint_xfer_control(&ep->desc) && xhci->hci_version >= 0x100)
|
||||
avg_trb_len = 8;
|
||||
@ -1909,17 +1915,17 @@ no_bw:
|
||||
xhci->usb3_rhub.num_ports = 0;
|
||||
xhci->num_active_eps = 0;
|
||||
kfree(xhci->usb2_rhub.ports);
|
||||
kfree(xhci->usb2_rhub.psi);
|
||||
kfree(xhci->usb3_rhub.ports);
|
||||
kfree(xhci->usb3_rhub.psi);
|
||||
kfree(xhci->hw_ports);
|
||||
kfree(xhci->rh_bw);
|
||||
kfree(xhci->ext_caps);
|
||||
for (i = 0; i < xhci->num_port_caps; i++)
|
||||
kfree(xhci->port_caps[i].psi);
|
||||
kfree(xhci->port_caps);
|
||||
xhci->num_port_caps = 0;
|
||||
|
||||
xhci->usb2_rhub.ports = NULL;
|
||||
xhci->usb2_rhub.psi = NULL;
|
||||
xhci->usb3_rhub.ports = NULL;
|
||||
xhci->usb3_rhub.psi = NULL;
|
||||
xhci->hw_ports = NULL;
|
||||
xhci->rh_bw = NULL;
|
||||
xhci->ext_caps = NULL;
|
||||
@ -2120,6 +2126,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
|
||||
u8 major_revision, minor_revision;
|
||||
struct xhci_hub *rhub;
|
||||
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
|
||||
struct xhci_port_cap *port_cap;
|
||||
|
||||
temp = readl(addr);
|
||||
major_revision = XHCI_EXT_PORT_MAJOR(temp);
|
||||
@ -2154,31 +2161,39 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
|
||||
/* WTF? "Valid values are ‘1’ to MaxPorts" */
|
||||
return;
|
||||
|
||||
rhub->psi_count = XHCI_EXT_PORT_PSIC(temp);
|
||||
if (rhub->psi_count) {
|
||||
rhub->psi = kcalloc_node(rhub->psi_count, sizeof(*rhub->psi),
|
||||
GFP_KERNEL, dev_to_node(dev));
|
||||
if (!rhub->psi)
|
||||
rhub->psi_count = 0;
|
||||
port_cap = &xhci->port_caps[xhci->num_port_caps++];
|
||||
if (xhci->num_port_caps > max_caps)
|
||||
return;
|
||||
|
||||
rhub->psi_uid_count++;
|
||||
for (i = 0; i < rhub->psi_count; i++) {
|
||||
rhub->psi[i] = readl(addr + 4 + i);
|
||||
port_cap->maj_rev = major_revision;
|
||||
port_cap->min_rev = minor_revision;
|
||||
port_cap->psi_count = XHCI_EXT_PORT_PSIC(temp);
|
||||
|
||||
if (port_cap->psi_count) {
|
||||
port_cap->psi = kcalloc_node(port_cap->psi_count,
|
||||
sizeof(*port_cap->psi),
|
||||
GFP_KERNEL, dev_to_node(dev));
|
||||
if (!port_cap->psi)
|
||||
port_cap->psi_count = 0;
|
||||
|
||||
port_cap->psi_uid_count++;
|
||||
for (i = 0; i < port_cap->psi_count; i++) {
|
||||
port_cap->psi[i] = readl(addr + 4 + i);
|
||||
|
||||
/* count unique ID values, two consecutive entries can
|
||||
* have the same ID if link is assymetric
|
||||
*/
|
||||
if (i && (XHCI_EXT_PORT_PSIV(rhub->psi[i]) !=
|
||||
XHCI_EXT_PORT_PSIV(rhub->psi[i - 1])))
|
||||
rhub->psi_uid_count++;
|
||||
if (i && (XHCI_EXT_PORT_PSIV(port_cap->psi[i]) !=
|
||||
XHCI_EXT_PORT_PSIV(port_cap->psi[i - 1])))
|
||||
port_cap->psi_uid_count++;
|
||||
|
||||
xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
|
||||
XHCI_EXT_PORT_PSIV(rhub->psi[i]),
|
||||
XHCI_EXT_PORT_PSIE(rhub->psi[i]),
|
||||
XHCI_EXT_PORT_PLT(rhub->psi[i]),
|
||||
XHCI_EXT_PORT_PFD(rhub->psi[i]),
|
||||
XHCI_EXT_PORT_LP(rhub->psi[i]),
|
||||
XHCI_EXT_PORT_PSIM(rhub->psi[i]));
|
||||
XHCI_EXT_PORT_PSIV(port_cap->psi[i]),
|
||||
XHCI_EXT_PORT_PSIE(port_cap->psi[i]),
|
||||
XHCI_EXT_PORT_PLT(port_cap->psi[i]),
|
||||
XHCI_EXT_PORT_PFD(port_cap->psi[i]),
|
||||
XHCI_EXT_PORT_LP(port_cap->psi[i]),
|
||||
XHCI_EXT_PORT_PSIM(port_cap->psi[i]));
|
||||
}
|
||||
}
|
||||
/* cache usb2 port capabilities */
|
||||
@ -2213,6 +2228,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
|
||||
continue;
|
||||
}
|
||||
hw_port->rhub = rhub;
|
||||
hw_port->port_cap = port_cap;
|
||||
rhub->num_ports++;
|
||||
}
|
||||
/* FIXME: Should we disable ports not in the Extended Capabilities? */
|
||||
@ -2303,6 +2319,11 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
|
||||
if (!xhci->ext_caps)
|
||||
return -ENOMEM;
|
||||
|
||||
xhci->port_caps = kcalloc_node(cap_count, sizeof(*xhci->port_caps),
|
||||
flags, dev_to_node(dev));
|
||||
if (!xhci->port_caps)
|
||||
return -ENOMEM;
|
||||
|
||||
offset = cap_start;
|
||||
|
||||
while (offset) {
|
||||
|
@ -49,6 +49,7 @@
|
||||
#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_XHCI 0x15ec
|
||||
#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI 0x15f0
|
||||
#define PCI_DEVICE_ID_INTEL_ICE_LAKE_XHCI 0x8a13
|
||||
#define PCI_DEVICE_ID_INTEL_CML_XHCI 0xa3af
|
||||
|
||||
#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9
|
||||
#define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba
|
||||
@ -187,7 +188,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
||||
pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI)) {
|
||||
pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI ||
|
||||
pdev->device == PCI_DEVICE_ID_INTEL_CML_XHCI)) {
|
||||
xhci->quirks |= XHCI_PME_STUCK_QUIRK;
|
||||
}
|
||||
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
|
||||
@ -302,6 +304,9 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
|
||||
if (!usb_hcd_is_primary_hcd(hcd))
|
||||
return 0;
|
||||
|
||||
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
||||
xhci_pme_acpi_rtd3_enable(pdev);
|
||||
|
||||
xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
|
||||
|
||||
/* Find any debug ports */
|
||||
@ -359,9 +364,6 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
HCC_MAX_PSA(xhci->hcc_params) >= 4)
|
||||
xhci->shared_hcd->can_do_streams = 1;
|
||||
|
||||
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
|
||||
xhci_pme_acpi_rtd3_enable(dev);
|
||||
|
||||
/* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
|
||||
pm_runtime_put_noidle(&dev->dev);
|
||||
|
||||
|
@ -1702,12 +1702,20 @@ struct xhci_bus_state {
|
||||
* Intel Lynx Point LP xHCI host.
|
||||
*/
|
||||
#define XHCI_MAX_REXIT_TIMEOUT_MS 20
|
||||
struct xhci_port_cap {
|
||||
u32 *psi; /* array of protocol speed ID entries */
|
||||
u8 psi_count;
|
||||
u8 psi_uid_count;
|
||||
u8 maj_rev;
|
||||
u8 min_rev;
|
||||
};
|
||||
|
||||
struct xhci_port {
|
||||
__le32 __iomem *addr;
|
||||
int hw_portnum;
|
||||
int hcd_portnum;
|
||||
struct xhci_hub *rhub;
|
||||
struct xhci_port_cap *port_cap;
|
||||
};
|
||||
|
||||
struct xhci_hub {
|
||||
@ -1719,9 +1727,6 @@ struct xhci_hub {
|
||||
/* supported prococol extended capabiliy values */
|
||||
u8 maj_rev;
|
||||
u8 min_rev;
|
||||
u32 *psi; /* array of protocol speed ID entries */
|
||||
u8 psi_count;
|
||||
u8 psi_uid_count;
|
||||
};
|
||||
|
||||
/* There is one xhci_hcd structure per controller */
|
||||
@ -1880,6 +1885,9 @@ struct xhci_hcd {
|
||||
/* cached usb2 extened protocol capabilites */
|
||||
u32 *ext_caps;
|
||||
unsigned int num_ext_caps;
|
||||
/* cached extended protocol port capabilities */
|
||||
struct xhci_port_cap *port_caps;
|
||||
unsigned int num_port_caps;
|
||||
/* Compliance Mode Recovery Data */
|
||||
struct timer_list comp_mode_recovery_timer;
|
||||
u32 port_status_u0;
|
||||
|
@ -33,6 +33,14 @@
|
||||
#define USB_DEVICE_ID_CODEMERCS_IOWPV2 0x1512
|
||||
/* full speed iowarrior */
|
||||
#define USB_DEVICE_ID_CODEMERCS_IOW56 0x1503
|
||||
/* fuller speed iowarrior */
|
||||
#define USB_DEVICE_ID_CODEMERCS_IOW28 0x1504
|
||||
#define USB_DEVICE_ID_CODEMERCS_IOW28L 0x1505
|
||||
#define USB_DEVICE_ID_CODEMERCS_IOW100 0x1506
|
||||
|
||||
/* OEMed devices */
|
||||
#define USB_DEVICE_ID_CODEMERCS_IOW24SAG 0x158a
|
||||
#define USB_DEVICE_ID_CODEMERCS_IOW56AM 0x158b
|
||||
|
||||
/* Get a minor range for your devices from the usb maintainer */
|
||||
#ifdef CONFIG_USB_DYNAMIC_MINORS
|
||||
@ -133,6 +141,11 @@ static const struct usb_device_id iowarrior_ids[] = {
|
||||
{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV1)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOWPV2)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24SAG)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW56AM)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28L)},
|
||||
{USB_DEVICE(USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW100)},
|
||||
{} /* Terminating entry */
|
||||
};
|
||||
MODULE_DEVICE_TABLE(usb, iowarrior_ids);
|
||||
@ -357,6 +370,7 @@ static ssize_t iowarrior_write(struct file *file,
|
||||
}
|
||||
switch (dev->product_id) {
|
||||
case USB_DEVICE_ID_CODEMERCS_IOW24:
|
||||
case USB_DEVICE_ID_CODEMERCS_IOW24SAG:
|
||||
case USB_DEVICE_ID_CODEMERCS_IOWPV1:
|
||||
case USB_DEVICE_ID_CODEMERCS_IOWPV2:
|
||||
case USB_DEVICE_ID_CODEMERCS_IOW40:
|
||||
@ -371,6 +385,10 @@ static ssize_t iowarrior_write(struct file *file,
|
||||
goto exit;
|
||||
break;
|
||||
case USB_DEVICE_ID_CODEMERCS_IOW56:
|
||||
case USB_DEVICE_ID_CODEMERCS_IOW56AM:
|
||||
case USB_DEVICE_ID_CODEMERCS_IOW28:
|
||||
case USB_DEVICE_ID_CODEMERCS_IOW28L:
|
||||
case USB_DEVICE_ID_CODEMERCS_IOW100:
|
||||
/* The IOW56 uses asynchronous IO and more urbs */
|
||||
if (atomic_read(&dev->write_busy) == MAX_WRITES_IN_FLIGHT) {
|
||||
/* Wait until we are below the limit for submitted urbs */
|
||||
@ -493,6 +511,7 @@ static long iowarrior_ioctl(struct file *file, unsigned int cmd,
|
||||
switch (cmd) {
|
||||
case IOW_WRITE:
|
||||
if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24 ||
|
||||
dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW24SAG ||
|
||||
dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV1 ||
|
||||
dev->product_id == USB_DEVICE_ID_CODEMERCS_IOWPV2 ||
|
||||
dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW40) {
|
||||
@ -767,7 +786,11 @@ static int iowarrior_probe(struct usb_interface *interface,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) {
|
||||
if ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) ||
|
||||
(dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) ||
|
||||
(dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) ||
|
||||
(dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L) ||
|
||||
(dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW100)) {
|
||||
res = usb_find_last_int_out_endpoint(iface_desc,
|
||||
&dev->int_out_endpoint);
|
||||
if (res) {
|
||||
@ -780,7 +803,11 @@ static int iowarrior_probe(struct usb_interface *interface,
|
||||
/* we have to check the report_size often, so remember it in the endianness suitable for our machine */
|
||||
dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint);
|
||||
if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) &&
|
||||
(dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56))
|
||||
((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) ||
|
||||
(dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) ||
|
||||
(dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) ||
|
||||
(dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L) ||
|
||||
(dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW100)))
|
||||
/* IOWarrior56 has wMaxPacketSize different from report size */
|
||||
dev->report_size = 7;
|
||||
|
||||
|
@ -969,6 +969,10 @@ static int utmi_phy_probe(struct tegra_usb_phy *tegra_phy,
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that UTMI pad registers are shared by all PHYs, therefore
|
||||
* devm_platform_ioremap_resource() can't be used here.
|
||||
*/
|
||||
tegra_phy->pad_regs = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!tegra_phy->pad_regs) {
|
||||
@ -1087,6 +1091,10 @@ static int tegra_usb_phy_probe(struct platform_device *pdev)
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that PHY and USB controller are using shared registers,
|
||||
* therefore devm_platform_ioremap_resource() can't be used here.
|
||||
*/
|
||||
tegra_phy->regs = devm_ioremap(&pdev->dev, res->start,
|
||||
resource_size(res));
|
||||
if (!tegra_phy->regs) {
|
||||
|
@ -205,6 +205,16 @@ static int ch341_get_divisor(speed_t speed)
|
||||
16 * speed - 16 * CH341_CLKRATE / (clk_div * (div + 1)))
|
||||
div++;
|
||||
|
||||
/*
|
||||
* Prefer lower base clock (fact = 0) if even divisor.
|
||||
*
|
||||
* Note that this makes the receiver more tolerant to errors.
|
||||
*/
|
||||
if (fact == 1 && div % 2 == 0) {
|
||||
div /= 2;
|
||||
fact = 0;
|
||||
}
|
||||
|
||||
return (0x100 - div) << 8 | fact << 2 | ps;
|
||||
}
|
||||
|
||||
|
@ -448,7 +448,7 @@ static void ir_set_termios(struct tty_struct *tty,
|
||||
usb_sndbulkpipe(udev, port->bulk_out_endpointAddress),
|
||||
transfer_buffer, 1, &actual_length, 5000);
|
||||
if (ret || actual_length != 1) {
|
||||
if (actual_length != 1)
|
||||
if (!ret)
|
||||
ret = -EIO;
|
||||
dev_err(&port->dev, "failed to change line speed: %d\n", ret);
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ struct uas_dev_info {
|
||||
struct scsi_cmnd *cmnd[MAX_CMNDS];
|
||||
spinlock_t lock;
|
||||
struct work_struct work;
|
||||
struct work_struct scan_work; /* for async scanning */
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -114,6 +115,17 @@ out:
|
||||
spin_unlock_irqrestore(&devinfo->lock, flags);
|
||||
}
|
||||
|
||||
static void uas_scan_work(struct work_struct *work)
|
||||
{
|
||||
struct uas_dev_info *devinfo =
|
||||
container_of(work, struct uas_dev_info, scan_work);
|
||||
struct Scsi_Host *shost = usb_get_intfdata(devinfo->intf);
|
||||
|
||||
dev_dbg(&devinfo->intf->dev, "starting scan\n");
|
||||
scsi_scan_host(shost);
|
||||
dev_dbg(&devinfo->intf->dev, "scan complete\n");
|
||||
}
|
||||
|
||||
static void uas_add_work(struct uas_cmd_info *cmdinfo)
|
||||
{
|
||||
struct scsi_pointer *scp = (void *)cmdinfo;
|
||||
@ -982,6 +994,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
init_usb_anchor(&devinfo->data_urbs);
|
||||
spin_lock_init(&devinfo->lock);
|
||||
INIT_WORK(&devinfo->work, uas_do_work);
|
||||
INIT_WORK(&devinfo->scan_work, uas_scan_work);
|
||||
|
||||
result = uas_configure_endpoints(devinfo);
|
||||
if (result)
|
||||
@ -998,7 +1011,9 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
if (result)
|
||||
goto free_streams;
|
||||
|
||||
scsi_scan_host(shost);
|
||||
/* Submit the delayed_work for SCSI-device scanning */
|
||||
schedule_work(&devinfo->scan_work);
|
||||
|
||||
return result;
|
||||
|
||||
free_streams:
|
||||
@ -1166,6 +1181,12 @@ static void uas_disconnect(struct usb_interface *intf)
|
||||
usb_kill_anchored_urbs(&devinfo->data_urbs);
|
||||
uas_zap_pending(devinfo, DID_NO_CONNECT);
|
||||
|
||||
/*
|
||||
* Prevent SCSI scanning (if it hasn't started yet)
|
||||
* or wait for the SCSI-scanning routine to stop.
|
||||
*/
|
||||
cancel_work_sync(&devinfo->scan_work);
|
||||
|
||||
scsi_remove_host(shost);
|
||||
uas_free_streams(devinfo);
|
||||
scsi_host_put(shost);
|
||||
|
@ -69,4 +69,7 @@
|
||||
/* Hub needs extra delay after resetting its port. */
|
||||
#define USB_QUIRK_HUB_SLOW_RESET BIT(14)
|
||||
|
||||
/* device has blacklisted endpoints */
|
||||
#define USB_QUIRK_ENDPOINT_BLACKLIST BIT(15)
|
||||
|
||||
#endif /* __LINUX_USB_QUIRKS_H */
|
||||
|
@ -14,18 +14,18 @@
|
||||
* ACA (Accessory Charger Adapters)
|
||||
*/
|
||||
enum usb_charger_type {
|
||||
UNKNOWN_TYPE,
|
||||
SDP_TYPE,
|
||||
DCP_TYPE,
|
||||
CDP_TYPE,
|
||||
ACA_TYPE,
|
||||
UNKNOWN_TYPE = 0,
|
||||
SDP_TYPE = 1,
|
||||
DCP_TYPE = 2,
|
||||
CDP_TYPE = 3,
|
||||
ACA_TYPE = 4,
|
||||
};
|
||||
|
||||
/* USB charger state */
|
||||
enum usb_charger_state {
|
||||
USB_CHARGER_DEFAULT,
|
||||
USB_CHARGER_PRESENT,
|
||||
USB_CHARGER_ABSENT,
|
||||
USB_CHARGER_DEFAULT = 0,
|
||||
USB_CHARGER_PRESENT = 1,
|
||||
USB_CHARGER_ABSENT = 2,
|
||||
};
|
||||
|
||||
#endif /* _UAPI__LINUX_USB_CHARGER_H */
|
||||
|
Loading…
Reference in New Issue
Block a user