Commit d0373c14 authored by Linus Torvalds's avatar Linus Torvalds

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

Pull USB/Thunderbolt fixes from Greg KH:
 "Here are some small USB and one Thunderbolt driver fixes.

  Nothing major at all, just some fixes for reported issues, and a quirk
  addition:

   - typec fixes

   - UAS disconnect fix

   - usblp race fix

   - ehci-hcd modversions build fix

   - ignore wakeup quirk table addition

   - thunderbolt DROM read fix

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

* tag 'usb-5.9-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb:
  usblp: fix race between disconnect() and read()
  ehci-hcd: Move include to keep CRC stable
  usb: typec: intel_pmc_mux: Handle SCU IPC error conditions
  USB: quirks: Add USB_QUIRK_IGNORE_REMOTE_WAKEUP quirk for BYD zhaoxin notebook
  USB: UAS: fix disconnect by unplugging a hub
  usb: typec: ucsi: Prevent mode overrun
  usb: typec: ucsi: acpi: Increase command completion timeout value
  thunderbolt: Retry DROM read once if parsing fails
parents f44f3f83 9cdabcb3
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
*/ */
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/delay.h>
#include <linux/property.h> #include <linux/property.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "tb.h" #include "tb.h"
...@@ -389,8 +390,8 @@ static int tb_drom_parse_entries(struct tb_switch *sw) ...@@ -389,8 +390,8 @@ static int tb_drom_parse_entries(struct tb_switch *sw)
struct tb_drom_entry_header *entry = (void *) (sw->drom + pos); struct tb_drom_entry_header *entry = (void *) (sw->drom + pos);
if (pos + 1 == drom_size || pos + entry->len > drom_size if (pos + 1 == drom_size || pos + entry->len > drom_size
|| !entry->len) { || !entry->len) {
tb_sw_warn(sw, "drom buffer overrun, aborting\n"); tb_sw_warn(sw, "DROM buffer overrun\n");
return -EIO; return -EILSEQ;
} }
switch (entry->type) { switch (entry->type) {
...@@ -526,7 +527,8 @@ int tb_drom_read(struct tb_switch *sw) ...@@ -526,7 +527,8 @@ int tb_drom_read(struct tb_switch *sw)
u16 size; u16 size;
u32 crc; u32 crc;
struct tb_drom_header *header; struct tb_drom_header *header;
int res; int res, retries = 1;
if (sw->drom) if (sw->drom)
return 0; return 0;
...@@ -612,7 +614,17 @@ int tb_drom_read(struct tb_switch *sw) ...@@ -612,7 +614,17 @@ int tb_drom_read(struct tb_switch *sw)
tb_sw_warn(sw, "drom device_rom_revision %#x unknown\n", tb_sw_warn(sw, "drom device_rom_revision %#x unknown\n",
header->device_rom_revision); header->device_rom_revision);
return tb_drom_parse_entries(sw); res = tb_drom_parse_entries(sw);
/* If the DROM parsing fails, wait a moment and retry once */
if (res == -EILSEQ && retries--) {
tb_sw_warn(sw, "parsing DROM failed, retrying\n");
msleep(100);
res = tb_drom_read_n(sw, 0, sw->drom, size);
if (!res)
goto parse;
}
return res;
err: err:
kfree(sw->drom); kfree(sw->drom);
sw->drom = NULL; sw->drom = NULL;
......
...@@ -827,6 +827,11 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t len, lo ...@@ -827,6 +827,11 @@ static ssize_t usblp_read(struct file *file, char __user *buffer, size_t len, lo
if (rv < 0) if (rv < 0)
return rv; return rv;
if (!usblp->present) {
count = -ENODEV;
goto done;
}
if ((avail = usblp->rstatus) < 0) { if ((avail = usblp->rstatus) < 0) {
printk(KERN_ERR "usblp%d: error %d reading from printer\n", printk(KERN_ERR "usblp%d: error %d reading from printer\n",
usblp->minor, (int)avail); usblp->minor, (int)avail);
......
...@@ -397,6 +397,10 @@ static const struct usb_device_id usb_quirk_list[] = { ...@@ -397,6 +397,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* Generic RTL8153 based ethernet adapters */ /* Generic RTL8153 based ethernet adapters */
{ USB_DEVICE(0x0bda, 0x8153), .driver_info = USB_QUIRK_NO_LPM }, { USB_DEVICE(0x0bda, 0x8153), .driver_info = USB_QUIRK_NO_LPM },
/* SONiX USB DEVICE Touchpad */
{ USB_DEVICE(0x0c45, 0x7056), .driver_info =
USB_QUIRK_IGNORE_REMOTE_WAKEUP },
/* Action Semiconductor flash disk */ /* Action Semiconductor flash disk */
{ USB_DEVICE(0x10d6, 0x2200), .driver_info = { USB_DEVICE(0x10d6, 0x2200), .driver_info =
USB_QUIRK_STRING_FETCH_255 }, USB_QUIRK_STRING_FETCH_255 },
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/hcd.h> #include <linux/usb/hcd.h>
#include <linux/usb/otg.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
*/ */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#include <linux/usb/otg.h>
#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E)
......
...@@ -662,8 +662,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, ...@@ -662,8 +662,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
if (devinfo->resetting) { if (devinfo->resetting) {
cmnd->result = DID_ERROR << 16; cmnd->result = DID_ERROR << 16;
cmnd->scsi_done(cmnd); cmnd->scsi_done(cmnd);
spin_unlock_irqrestore(&devinfo->lock, flags); goto zombie;
return 0;
} }
/* Find a free uas-tag */ /* Find a free uas-tag */
...@@ -699,6 +698,16 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, ...@@ -699,6 +698,16 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB); cmdinfo->state &= ~(SUBMIT_DATA_IN_URB | SUBMIT_DATA_OUT_URB);
err = uas_submit_urbs(cmnd, devinfo); err = uas_submit_urbs(cmnd, devinfo);
/*
* in case of fatal errors the SCSI layer is peculiar
* a command that has finished is a success for the purpose
* of queueing, no matter how fatal the error
*/
if (err == -ENODEV) {
cmnd->result = DID_ERROR << 16;
cmnd->scsi_done(cmnd);
goto zombie;
}
if (err) { if (err) {
/* If we did nothing, give up now */ /* If we did nothing, give up now */
if (cmdinfo->state & SUBMIT_STATUS_URB) { if (cmdinfo->state & SUBMIT_STATUS_URB) {
...@@ -709,6 +718,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, ...@@ -709,6 +718,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd,
} }
devinfo->cmnd[idx] = cmnd; devinfo->cmnd[idx] = cmnd;
zombie:
spin_unlock_irqrestore(&devinfo->lock, flags); spin_unlock_irqrestore(&devinfo->lock, flags);
return 0; return 0;
} }
......
...@@ -125,13 +125,19 @@ static int hsl_orientation(struct pmc_usb_port *port) ...@@ -125,13 +125,19 @@ static int hsl_orientation(struct pmc_usb_port *port)
static int pmc_usb_command(struct pmc_usb_port *port, u8 *msg, u32 len) static int pmc_usb_command(struct pmc_usb_port *port, u8 *msg, u32 len)
{ {
u8 response[4]; u8 response[4];
int ret;
/* /*
* Error bit will always be 0 with the USBC command. * Error bit will always be 0 with the USBC command.
* Status can be checked from the response message. * Status can be checked from the response message if the
* function intel_scu_ipc_dev_command succeeds.
*/ */
intel_scu_ipc_dev_command(port->pmc->ipc, PMC_USBC_CMD, 0, msg, len, ret = intel_scu_ipc_dev_command(port->pmc->ipc, PMC_USBC_CMD, 0, msg,
response, sizeof(response)); len, response, sizeof(response));
if (ret)
return ret;
if (response[2] & PMC_USB_RESP_STATUS_FAILURE) { if (response[2] & PMC_USB_RESP_STATUS_FAILURE) {
if (response[2] & PMC_USB_RESP_STATUS_FATAL) if (response[2] & PMC_USB_RESP_STATUS_FATAL)
return -EIO; return -EIO;
......
...@@ -216,14 +216,18 @@ void ucsi_altmode_update_active(struct ucsi_connector *con) ...@@ -216,14 +216,18 @@ void ucsi_altmode_update_active(struct ucsi_connector *con)
con->partner_altmode[i] == altmode); con->partner_altmode[i] == altmode);
} }
static u8 ucsi_altmode_next_mode(struct typec_altmode **alt, u16 svid) static int ucsi_altmode_next_mode(struct typec_altmode **alt, u16 svid)
{ {
u8 mode = 1; u8 mode = 1;
int i; int i;
for (i = 0; alt[i]; i++) for (i = 0; alt[i]; i++) {
if (i > MODE_DISCOVERY_MAX)
return -ERANGE;
if (alt[i]->svid == svid) if (alt[i]->svid == svid)
mode++; mode++;
}
return mode; return mode;
} }
...@@ -258,8 +262,11 @@ static int ucsi_register_altmode(struct ucsi_connector *con, ...@@ -258,8 +262,11 @@ static int ucsi_register_altmode(struct ucsi_connector *con,
goto err; goto err;
} }
desc->mode = ucsi_altmode_next_mode(con->port_altmode, ret = ucsi_altmode_next_mode(con->port_altmode, desc->svid);
desc->svid); if (ret < 0)
return ret;
desc->mode = ret;
switch (desc->svid) { switch (desc->svid) {
case USB_TYPEC_DP_SID: case USB_TYPEC_DP_SID:
...@@ -292,8 +299,11 @@ static int ucsi_register_altmode(struct ucsi_connector *con, ...@@ -292,8 +299,11 @@ static int ucsi_register_altmode(struct ucsi_connector *con,
goto err; goto err;
} }
desc->mode = ucsi_altmode_next_mode(con->partner_altmode, ret = ucsi_altmode_next_mode(con->partner_altmode, desc->svid);
desc->svid); if (ret < 0)
return ret;
desc->mode = ret;
alt = typec_partner_register_altmode(con->partner, desc); alt = typec_partner_register_altmode(con->partner, desc);
if (IS_ERR(alt)) { if (IS_ERR(alt)) {
......
...@@ -78,7 +78,7 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset, ...@@ -78,7 +78,7 @@ static int ucsi_acpi_sync_write(struct ucsi *ucsi, unsigned int offset,
if (ret) if (ret)
goto out_clear_bit; goto out_clear_bit;
if (!wait_for_completion_timeout(&ua->complete, msecs_to_jiffies(5000))) if (!wait_for_completion_timeout(&ua->complete, 60 * HZ))
ret = -ETIMEDOUT; ret = -ETIMEDOUT;
out_clear_bit: out_clear_bit:
......
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