Commit 50a5528a authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB fixes from Greg KH:
 "Here are some small USB fixes for 4.20-rc6

  The "largest" here are some xhci fixes for reported issues. Also here
  is a USB core fix, some quirk additions, and a usb-serial fix which
  required the export of one of the tty layer's functions to prevent
  code duplication. The tty maintainer agreed with this change.

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

* tag 'usb-4.20-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  xhci: Prevent U1/U2 link pm states if exit latency is too long
  xhci: workaround CSS timeout on AMD SNPS 3.0 xHC
  USB: check usb_get_extra_descriptor for proper size
  USB: serial: console: fix reported terminal settings
  usb: quirk: add no-LPM quirk on SanDisk Ultra Flair device
  USB: Fix invalid-free bug in port_over_current_notify()
  usb: appledisplay: Add 27" Apple Cinema Display
parents bc4caf18 3caad34e
...@@ -1373,7 +1373,13 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx) ...@@ -1373,7 +1373,13 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
return ERR_PTR(retval); return ERR_PTR(retval);
} }
static void tty_free_termios(struct tty_struct *tty) /**
* tty_save_termios() - save tty termios data in driver table
* @tty: tty whose termios data to save
*
* Locking: Caller guarantees serialisation with tty_init_termios().
*/
void tty_save_termios(struct tty_struct *tty)
{ {
struct ktermios *tp; struct ktermios *tp;
int idx = tty->index; int idx = tty->index;
...@@ -1392,6 +1398,7 @@ static void tty_free_termios(struct tty_struct *tty) ...@@ -1392,6 +1398,7 @@ static void tty_free_termios(struct tty_struct *tty)
} }
*tp = tty->termios; *tp = tty->termios;
} }
EXPORT_SYMBOL_GPL(tty_save_termios);
/** /**
* tty_flush_works - flush all works of a tty/pty pair * tty_flush_works - flush all works of a tty/pty pair
...@@ -1491,7 +1498,7 @@ static void release_tty(struct tty_struct *tty, int idx) ...@@ -1491,7 +1498,7 @@ static void release_tty(struct tty_struct *tty, int idx)
WARN_ON(!mutex_is_locked(&tty_mutex)); WARN_ON(!mutex_is_locked(&tty_mutex));
if (tty->ops->shutdown) if (tty->ops->shutdown)
tty->ops->shutdown(tty); tty->ops->shutdown(tty);
tty_free_termios(tty); tty_save_termios(tty);
tty_driver_remove_tty(tty->driver, tty); tty_driver_remove_tty(tty->driver, tty);
tty->port->itty = NULL; tty->port->itty = NULL;
if (tty->link) if (tty->link)
......
...@@ -2251,7 +2251,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev) ...@@ -2251,7 +2251,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev)
/* descriptor may appear anywhere in config */ /* descriptor may appear anywhere in config */
err = __usb_get_extra_descriptor(udev->rawdescriptors[0], err = __usb_get_extra_descriptor(udev->rawdescriptors[0],
le16_to_cpu(udev->config[0].desc.wTotalLength), le16_to_cpu(udev->config[0].desc.wTotalLength),
USB_DT_OTG, (void **) &desc); USB_DT_OTG, (void **) &desc, sizeof(*desc));
if (err || !(desc->bmAttributes & USB_OTG_HNP)) if (err || !(desc->bmAttributes & USB_OTG_HNP))
return 0; return 0;
...@@ -5163,7 +5163,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, ...@@ -5163,7 +5163,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
/* Handle notifying userspace about hub over-current events */ /* Handle notifying userspace about hub over-current events */
static void port_over_current_notify(struct usb_port *port_dev) static void port_over_current_notify(struct usb_port *port_dev)
{ {
static char *envp[] = { NULL, NULL, NULL }; char *envp[3];
struct device *hub_dev; struct device *hub_dev;
char *port_dev_path; char *port_dev_path;
...@@ -5187,6 +5187,7 @@ static void port_over_current_notify(struct usb_port *port_dev) ...@@ -5187,6 +5187,7 @@ static void port_over_current_notify(struct usb_port *port_dev)
if (!envp[1]) if (!envp[1])
goto exit; goto exit;
envp[2] = NULL;
kobject_uevent_env(&hub_dev->kobj, KOBJ_CHANGE, envp); kobject_uevent_env(&hub_dev->kobj, KOBJ_CHANGE, envp);
kfree(envp[1]); kfree(envp[1]);
......
...@@ -333,6 +333,10 @@ static const struct usb_device_id usb_quirk_list[] = { ...@@ -333,6 +333,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Midiman M-Audio Keystation 88es */ /* Midiman M-Audio Keystation 88es */
{ USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME }, { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME },
/* SanDisk Ultra Fit and Ultra Flair */
{ USB_DEVICE(0x0781, 0x5583), .driver_info = USB_QUIRK_NO_LPM },
{ USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM },
/* M-Systems Flash Disk Pioneers */ /* M-Systems Flash Disk Pioneers */
{ USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME },
......
...@@ -832,14 +832,14 @@ EXPORT_SYMBOL_GPL(usb_get_current_frame_number); ...@@ -832,14 +832,14 @@ EXPORT_SYMBOL_GPL(usb_get_current_frame_number);
*/ */
int __usb_get_extra_descriptor(char *buffer, unsigned size, int __usb_get_extra_descriptor(char *buffer, unsigned size,
unsigned char type, void **ptr) unsigned char type, void **ptr, size_t minsize)
{ {
struct usb_descriptor_header *header; struct usb_descriptor_header *header;
while (size >= sizeof(struct usb_descriptor_header)) { while (size >= sizeof(struct usb_descriptor_header)) {
header = (struct usb_descriptor_header *)buffer; header = (struct usb_descriptor_header *)buffer;
if (header->bLength < 2) { if (header->bLength < 2 || header->bLength > size) {
printk(KERN_ERR printk(KERN_ERR
"%s: bogus descriptor, type %d length %d\n", "%s: bogus descriptor, type %d length %d\n",
usbcore_name, usbcore_name,
...@@ -848,7 +848,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, ...@@ -848,7 +848,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size,
return -1; return -1;
} }
if (header->bDescriptorType == type) { if (header->bDescriptorType == type && header->bLength >= minsize) {
*ptr = header; *ptr = header;
return 0; return 0;
} }
......
...@@ -640,7 +640,7 @@ static int hwahc_security_create(struct hwahc *hwahc) ...@@ -640,7 +640,7 @@ static int hwahc_security_create(struct hwahc *hwahc)
top = itr + itr_size; top = itr + itr_size;
result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index], result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index],
le16_to_cpu(usb_dev->actconfig->desc.wTotalLength), le16_to_cpu(usb_dev->actconfig->desc.wTotalLength),
USB_DT_SECURITY, (void **) &secd); USB_DT_SECURITY, (void **) &secd, sizeof(*secd));
if (result == -1) { if (result == -1) {
dev_warn(dev, "BUG? WUSB host has no security descriptors\n"); dev_warn(dev, "BUG? WUSB host has no security descriptors\n");
return 0; return 0;
......
...@@ -139,6 +139,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) ...@@ -139,6 +139,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == 0x43bb)) pdev->device == 0x43bb))
xhci->quirks |= XHCI_SUSPEND_DELAY; xhci->quirks |= XHCI_SUSPEND_DELAY;
if (pdev->vendor == PCI_VENDOR_ID_AMD &&
(pdev->device == 0x15e0 || pdev->device == 0x15e1))
xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND;
if (pdev->vendor == PCI_VENDOR_ID_AMD) if (pdev->vendor == PCI_VENDOR_ID_AMD)
xhci->quirks |= XHCI_TRUST_TX_LENGTH; xhci->quirks |= XHCI_TRUST_TX_LENGTH;
......
...@@ -968,6 +968,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) ...@@ -968,6 +968,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
unsigned int delay = XHCI_MAX_HALT_USEC; unsigned int delay = XHCI_MAX_HALT_USEC;
struct usb_hcd *hcd = xhci_to_hcd(xhci); struct usb_hcd *hcd = xhci_to_hcd(xhci);
u32 command; u32 command;
u32 res;
if (!hcd->state) if (!hcd->state)
return 0; return 0;
...@@ -1021,11 +1022,28 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) ...@@ -1021,11 +1022,28 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
command = readl(&xhci->op_regs->command); command = readl(&xhci->op_regs->command);
command |= CMD_CSS; command |= CMD_CSS;
writel(command, &xhci->op_regs->command); writel(command, &xhci->op_regs->command);
xhci->broken_suspend = 0;
if (xhci_handshake(&xhci->op_regs->status, if (xhci_handshake(&xhci->op_regs->status,
STS_SAVE, 0, 10 * 1000)) { STS_SAVE, 0, 10 * 1000)) {
xhci_warn(xhci, "WARN: xHC save state timeout\n"); /*
spin_unlock_irq(&xhci->lock); * AMD SNPS xHC 3.0 occasionally does not clear the
return -ETIMEDOUT; * SSS bit of USBSTS and when driver tries to poll
* to see if the xHC clears BIT(8) which never happens
* and driver assumes that controller is not responding
* and times out. To workaround this, its good to check
* if SRE and HCE bits are not set (as per xhci
* Section 5.4.2) and bypass the timeout.
*/
res = readl(&xhci->op_regs->status);
if ((xhci->quirks & XHCI_SNPS_BROKEN_SUSPEND) &&
(((res & STS_SRE) == 0) &&
((res & STS_HCE) == 0))) {
xhci->broken_suspend = 1;
} else {
xhci_warn(xhci, "WARN: xHC save state timeout\n");
spin_unlock_irq(&xhci->lock);
return -ETIMEDOUT;
}
} }
spin_unlock_irq(&xhci->lock); spin_unlock_irq(&xhci->lock);
...@@ -1078,7 +1096,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) ...@@ -1078,7 +1096,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
spin_lock_irq(&xhci->lock); spin_lock_irq(&xhci->lock);
if (xhci->quirks & XHCI_RESET_ON_RESUME) if ((xhci->quirks & XHCI_RESET_ON_RESUME) || xhci->broken_suspend)
hibernated = true; hibernated = true;
if (!hibernated) { if (!hibernated) {
...@@ -4496,6 +4514,14 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci, ...@@ -4496,6 +4514,14 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci,
{ {
unsigned long long timeout_ns; unsigned long long timeout_ns;
/* Prevent U1 if service interval is shorter than U1 exit latency */
if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) {
if (xhci_service_interval_to_ns(desc) <= udev->u1_params.mel) {
dev_dbg(&udev->dev, "Disable U1, ESIT shorter than exit latency\n");
return USB3_LPM_DISABLED;
}
}
if (xhci->quirks & XHCI_INTEL_HOST) if (xhci->quirks & XHCI_INTEL_HOST)
timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc); timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
else else
...@@ -4552,6 +4578,14 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci, ...@@ -4552,6 +4578,14 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci,
{ {
unsigned long long timeout_ns; unsigned long long timeout_ns;
/* Prevent U2 if service interval is shorter than U2 exit latency */
if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) {
if (xhci_service_interval_to_ns(desc) <= udev->u2_params.mel) {
dev_dbg(&udev->dev, "Disable U2, ESIT shorter than exit latency\n");
return USB3_LPM_DISABLED;
}
}
if (xhci->quirks & XHCI_INTEL_HOST) if (xhci->quirks & XHCI_INTEL_HOST)
timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc); timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
else else
......
...@@ -1850,6 +1850,7 @@ struct xhci_hcd { ...@@ -1850,6 +1850,7 @@ struct xhci_hcd {
#define XHCI_ZERO_64B_REGS BIT_ULL(32) #define XHCI_ZERO_64B_REGS BIT_ULL(32)
#define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33) #define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33)
#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34) #define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
#define XHCI_SNPS_BROKEN_SUSPEND BIT_ULL(35)
unsigned int num_active_eps; unsigned int num_active_eps;
unsigned int limit_active_eps; unsigned int limit_active_eps;
...@@ -1879,6 +1880,8 @@ struct xhci_hcd { ...@@ -1879,6 +1880,8 @@ struct xhci_hcd {
void *dbc; void *dbc;
/* platform-specific data -- must come last */ /* platform-specific data -- must come last */
unsigned long priv[0] __aligned(sizeof(s64)); unsigned long priv[0] __aligned(sizeof(s64));
/* Broken Suspend flag for SNPS Suspend resume issue */
u8 broken_suspend;
}; };
/* Platform specific overrides to generic XHCI hc_driver ops */ /* Platform specific overrides to generic XHCI hc_driver ops */
......
...@@ -51,6 +51,7 @@ static const struct usb_device_id appledisplay_table[] = { ...@@ -51,6 +51,7 @@ static const struct usb_device_id appledisplay_table[] = {
{ APPLEDISPLAY_DEVICE(0x921c) }, { APPLEDISPLAY_DEVICE(0x921c) },
{ APPLEDISPLAY_DEVICE(0x921d) }, { APPLEDISPLAY_DEVICE(0x921d) },
{ APPLEDISPLAY_DEVICE(0x9222) }, { APPLEDISPLAY_DEVICE(0x9222) },
{ APPLEDISPLAY_DEVICE(0x9226) },
{ APPLEDISPLAY_DEVICE(0x9236) }, { APPLEDISPLAY_DEVICE(0x9236) },
/* Terminating entry */ /* Terminating entry */
......
...@@ -101,7 +101,6 @@ static int usb_console_setup(struct console *co, char *options) ...@@ -101,7 +101,6 @@ static int usb_console_setup(struct console *co, char *options)
cflag |= PARENB; cflag |= PARENB;
break; break;
} }
co->cflag = cflag;
/* /*
* no need to check the index here: if the index is wrong, console * no need to check the index here: if the index is wrong, console
...@@ -164,6 +163,7 @@ static int usb_console_setup(struct console *co, char *options) ...@@ -164,6 +163,7 @@ static int usb_console_setup(struct console *co, char *options)
serial->type->set_termios(tty, port, &dummy); serial->type->set_termios(tty, port, &dummy);
tty_port_tty_set(&port->port, NULL); tty_port_tty_set(&port->port, NULL);
tty_save_termios(tty);
tty_kref_put(tty); tty_kref_put(tty);
} }
tty_port_set_initialized(&port->port, 1); tty_port_set_initialized(&port->port, 1);
......
...@@ -556,6 +556,7 @@ extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx); ...@@ -556,6 +556,7 @@ extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
extern void tty_release_struct(struct tty_struct *tty, int idx); extern void tty_release_struct(struct tty_struct *tty, int idx);
extern int tty_release(struct inode *inode, struct file *filp); extern int tty_release(struct inode *inode, struct file *filp);
extern void tty_init_termios(struct tty_struct *tty); extern void tty_init_termios(struct tty_struct *tty);
extern void tty_save_termios(struct tty_struct *tty);
extern int tty_standard_install(struct tty_driver *driver, extern int tty_standard_install(struct tty_driver *driver,
struct tty_struct *tty); struct tty_struct *tty);
......
...@@ -407,11 +407,11 @@ struct usb_host_bos { ...@@ -407,11 +407,11 @@ struct usb_host_bos {
}; };
int __usb_get_extra_descriptor(char *buffer, unsigned size, int __usb_get_extra_descriptor(char *buffer, unsigned size,
unsigned char type, void **ptr); unsigned char type, void **ptr, size_t min);
#define usb_get_extra_descriptor(ifpoint, type, ptr) \ #define usb_get_extra_descriptor(ifpoint, type, ptr) \
__usb_get_extra_descriptor((ifpoint)->extra, \ __usb_get_extra_descriptor((ifpoint)->extra, \
(ifpoint)->extralen, \ (ifpoint)->extralen, \
type, (void **)ptr) type, (void **)ptr, sizeof(**(ptr)))
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment