USB fixes for 4.17-rc4
Here are some USB driver fixes for 4.17-rc4. The majority of them are some USB gadget fixes that missed my last pull request. The "largest" patch in here is a fix for the old visor driver that syzbot found 6 months or so ago and I finally remembered to fix it. All of these have been in linux-next with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCWu4/Kw8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ykQrwCdFtLciG+1aDp5lDc8wzlOPdsUa5cAoK2f+7Je stELc5F5nAEES/DMFG1c =CDZC -----END PGP SIGNATURE----- Merge tag 'usb-4.17-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb Pull USB fixes from Greg KH: "Here are some USB driver fixes for 4.17-rc4. The majority of them are some USB gadget fixes that missed my last pull request. The "largest" patch in here is a fix for the old visor driver that syzbot found 6 months or so ago and I finally remembered to fix it. All of these have been in linux-next with no reported issues" * tag 'usb-4.17-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: Revert "usb: host: ehci: Use dma_pool_zalloc()" usb: typec: tps6598x: handle block reads separately with plain-I2C adapters usb: typec: tcpm: Release the role mux when exiting USB: Accept bulk endpoints with 1024-byte maxpacket xhci: Fix use-after-free in xhci_free_virt_device USB: serial: visor: handle potential invalid device configuration USB: serial: option: adding support for ublox R410M usb: musb: trace: fix NULL pointer dereference in musb_g_tx() usb: musb: host: fix potential NULL pointer dereference usb: gadget: composite Allow for larger configuration descriptors usb: dwc3: gadget: Fix list_del corruption in dwc3_ep_dequeue usb: dwc3: gadget: dwc3_gadget_del_and_unmap_request() can be static usb: dwc2: pci: Fix error return code in dwc2_pci_probe() usb: dwc2: WA for Full speed ISOC IN in DDMA mode. usb: dwc2: dwc2_vbus_supply_init: fix error check usb: gadget: f_phonet: fix pn_net_xmit()'s return type
This commit is contained in:
Коммит
8e95cb336d
|
@ -191,7 +191,9 @@ static const unsigned short full_speed_maxpacket_maxes[4] = {
|
|||
static const unsigned short high_speed_maxpacket_maxes[4] = {
|
||||
[USB_ENDPOINT_XFER_CONTROL] = 64,
|
||||
[USB_ENDPOINT_XFER_ISOC] = 1024,
|
||||
[USB_ENDPOINT_XFER_BULK] = 512,
|
||||
|
||||
/* Bulk should be 512, but some devices use 1024: we will warn below */
|
||||
[USB_ENDPOINT_XFER_BULK] = 1024,
|
||||
[USB_ENDPOINT_XFER_INT] = 1024,
|
||||
};
|
||||
static const unsigned short super_speed_maxpacket_maxes[4] = {
|
||||
|
|
|
@ -985,6 +985,7 @@ struct dwc2_hsotg {
|
|||
|
||||
/* DWC OTG HW Release versions */
|
||||
#define DWC2_CORE_REV_2_71a 0x4f54271a
|
||||
#define DWC2_CORE_REV_2_72a 0x4f54272a
|
||||
#define DWC2_CORE_REV_2_80a 0x4f54280a
|
||||
#define DWC2_CORE_REV_2_90a 0x4f54290a
|
||||
#define DWC2_CORE_REV_2_91a 0x4f54291a
|
||||
|
@ -992,6 +993,7 @@ struct dwc2_hsotg {
|
|||
#define DWC2_CORE_REV_2_94a 0x4f54294a
|
||||
#define DWC2_CORE_REV_3_00a 0x4f54300a
|
||||
#define DWC2_CORE_REV_3_10a 0x4f54310a
|
||||
#define DWC2_CORE_REV_4_00a 0x4f54400a
|
||||
#define DWC2_FS_IOT_REV_1_00a 0x5531100a
|
||||
#define DWC2_HS_IOT_REV_1_00a 0x5532100a
|
||||
|
||||
|
|
|
@ -3928,6 +3928,27 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep,
|
|||
if (index && !hs_ep->isochronous)
|
||||
epctrl |= DXEPCTL_SETD0PID;
|
||||
|
||||
/* WA for Full speed ISOC IN in DDMA mode.
|
||||
* By Clear NAK status of EP, core will send ZLP
|
||||
* to IN token and assert NAK interrupt relying
|
||||
* on TxFIFO status only
|
||||
*/
|
||||
|
||||
if (hsotg->gadget.speed == USB_SPEED_FULL &&
|
||||
hs_ep->isochronous && dir_in) {
|
||||
/* The WA applies only to core versions from 2.72a
|
||||
* to 4.00a (including both). Also for FS_IOT_1.00a
|
||||
* and HS_IOT_1.00a.
|
||||
*/
|
||||
u32 gsnpsid = dwc2_readl(hsotg->regs + GSNPSID);
|
||||
|
||||
if ((gsnpsid >= DWC2_CORE_REV_2_72a &&
|
||||
gsnpsid <= DWC2_CORE_REV_4_00a) ||
|
||||
gsnpsid == DWC2_FS_IOT_REV_1_00a ||
|
||||
gsnpsid == DWC2_HS_IOT_REV_1_00a)
|
||||
epctrl |= DXEPCTL_CNAK;
|
||||
}
|
||||
|
||||
dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n",
|
||||
__func__, epctrl);
|
||||
|
||||
|
|
|
@ -358,9 +358,14 @@ static void dwc2_gusbcfg_init(struct dwc2_hsotg *hsotg)
|
|||
|
||||
static int dwc2_vbus_supply_init(struct dwc2_hsotg *hsotg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hsotg->vbus_supply = devm_regulator_get_optional(hsotg->dev, "vbus");
|
||||
if (IS_ERR(hsotg->vbus_supply))
|
||||
return 0;
|
||||
if (IS_ERR(hsotg->vbus_supply)) {
|
||||
ret = PTR_ERR(hsotg->vbus_supply);
|
||||
hsotg->vbus_supply = NULL;
|
||||
return ret == -ENODEV ? 0 : ret;
|
||||
}
|
||||
|
||||
return regulator_enable(hsotg->vbus_supply);
|
||||
}
|
||||
|
@ -4342,9 +4347,7 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
|
|||
|
||||
spin_unlock_irqrestore(&hsotg->lock, flags);
|
||||
|
||||
dwc2_vbus_supply_init(hsotg);
|
||||
|
||||
return 0;
|
||||
return dwc2_vbus_supply_init(hsotg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -141,8 +141,10 @@ static int dwc2_pci_probe(struct pci_dev *pci,
|
|||
goto err;
|
||||
|
||||
glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
|
||||
if (!glue)
|
||||
if (!glue) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = platform_device_add(dwc2);
|
||||
if (ret) {
|
||||
|
|
|
@ -166,7 +166,7 @@ static void dwc3_ep_inc_deq(struct dwc3_ep *dep)
|
|||
dwc3_ep_inc_trb(&dep->trb_dequeue);
|
||||
}
|
||||
|
||||
void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
|
||||
static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
|
||||
struct dwc3_request *req, int status)
|
||||
{
|
||||
struct dwc3 *dwc = dep->dwc;
|
||||
|
@ -1424,7 +1424,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
|
|||
dwc->lock);
|
||||
|
||||
if (!r->trb)
|
||||
goto out1;
|
||||
goto out0;
|
||||
|
||||
if (r->num_pending_sgs) {
|
||||
struct dwc3_trb *trb;
|
||||
|
|
|
@ -221,7 +221,7 @@ static void pn_tx_complete(struct usb_ep *ep, struct usb_request *req)
|
|||
netif_wake_queue(dev);
|
||||
}
|
||||
|
||||
static int pn_net_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
static netdev_tx_t pn_net_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
{
|
||||
struct phonet_port *port = netdev_priv(dev);
|
||||
struct f_phonet *fp;
|
||||
|
|
|
@ -73,9 +73,10 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags)
|
|||
if (!qh)
|
||||
goto done;
|
||||
qh->hw = (struct ehci_qh_hw *)
|
||||
dma_pool_zalloc(ehci->qh_pool, flags, &dma);
|
||||
dma_pool_alloc(ehci->qh_pool, flags, &dma);
|
||||
if (!qh->hw)
|
||||
goto fail;
|
||||
memset(qh->hw, 0, sizeof *qh->hw);
|
||||
qh->qh_dma = dma;
|
||||
// INIT_LIST_HEAD (&qh->qh_list);
|
||||
INIT_LIST_HEAD (&qh->qtd_list);
|
||||
|
|
|
@ -1287,7 +1287,7 @@ itd_urb_transaction(
|
|||
} else {
|
||||
alloc_itd:
|
||||
spin_unlock_irqrestore(&ehci->lock, flags);
|
||||
itd = dma_pool_zalloc(ehci->itd_pool, mem_flags,
|
||||
itd = dma_pool_alloc(ehci->itd_pool, mem_flags,
|
||||
&itd_dma);
|
||||
spin_lock_irqsave(&ehci->lock, flags);
|
||||
if (!itd) {
|
||||
|
@ -1297,6 +1297,7 @@ itd_urb_transaction(
|
|||
}
|
||||
}
|
||||
|
||||
memset(itd, 0, sizeof(*itd));
|
||||
itd->itd_dma = itd_dma;
|
||||
itd->frame = NO_FRAME;
|
||||
list_add(&itd->itd_list, &sched->td_list);
|
||||
|
@ -2080,7 +2081,7 @@ sitd_urb_transaction(
|
|||
} else {
|
||||
alloc_sitd:
|
||||
spin_unlock_irqrestore(&ehci->lock, flags);
|
||||
sitd = dma_pool_zalloc(ehci->sitd_pool, mem_flags,
|
||||
sitd = dma_pool_alloc(ehci->sitd_pool, mem_flags,
|
||||
&sitd_dma);
|
||||
spin_lock_irqsave(&ehci->lock, flags);
|
||||
if (!sitd) {
|
||||
|
@ -2090,6 +2091,7 @@ sitd_urb_transaction(
|
|||
}
|
||||
}
|
||||
|
||||
memset(sitd, 0, sizeof(*sitd));
|
||||
sitd->sitd_dma = sitd_dma;
|
||||
sitd->frame = NO_FRAME;
|
||||
list_add(&sitd->sitd_list, &iso_sched->td_list);
|
||||
|
|
|
@ -3621,6 +3621,7 @@ static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
|
|||
del_timer_sync(&virt_dev->eps[i].stop_cmd_timer);
|
||||
}
|
||||
xhci_debugfs_remove_slot(xhci, udev->slot_id);
|
||||
virt_dev->udev = NULL;
|
||||
ret = xhci_disable_slot(xhci, udev->slot_id);
|
||||
if (ret)
|
||||
xhci_free_virt_device(xhci, udev->slot_id);
|
||||
|
|
|
@ -417,7 +417,6 @@ void musb_g_tx(struct musb *musb, u8 epnum)
|
|||
req = next_request(musb_ep);
|
||||
request = &req->request;
|
||||
|
||||
trace_musb_req_tx(req);
|
||||
csr = musb_readw(epio, MUSB_TXCSR);
|
||||
musb_dbg(musb, "<== %s, txcsr %04x", musb_ep->end_point.name, csr);
|
||||
|
||||
|
@ -456,6 +455,8 @@ void musb_g_tx(struct musb *musb, u8 epnum)
|
|||
u8 is_dma = 0;
|
||||
bool short_packet = false;
|
||||
|
||||
trace_musb_req_tx(req);
|
||||
|
||||
if (dma && (csr & MUSB_TXCSR_DMAENAB)) {
|
||||
is_dma = 1;
|
||||
csr |= MUSB_TXCSR_P_WZC_BITS;
|
||||
|
|
|
@ -990,7 +990,9 @@ static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep,
|
|||
/* set tx_reinit and schedule the next qh */
|
||||
ep->tx_reinit = 1;
|
||||
}
|
||||
musb_start_urb(musb, is_in, next_qh);
|
||||
|
||||
if (next_qh)
|
||||
musb_start_urb(musb, is_in, next_qh);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -233,6 +233,8 @@ static void option_instat_callback(struct urb *urb);
|
|||
/* These Quectel products use Qualcomm's vendor ID */
|
||||
#define QUECTEL_PRODUCT_UC20 0x9003
|
||||
#define QUECTEL_PRODUCT_UC15 0x9090
|
||||
/* These u-blox products use Qualcomm's vendor ID */
|
||||
#define UBLOX_PRODUCT_R410M 0x90b2
|
||||
/* These Yuga products use Qualcomm's vendor ID */
|
||||
#define YUGA_PRODUCT_CLM920_NC5 0x9625
|
||||
|
||||
|
@ -1065,6 +1067,9 @@ static const struct usb_device_id option_ids[] = {
|
|||
/* Yuga products use Qualcomm vendor ID */
|
||||
{ USB_DEVICE(QUALCOMM_VENDOR_ID, YUGA_PRODUCT_CLM920_NC5),
|
||||
.driver_info = RSVD(1) | RSVD(4) },
|
||||
/* u-blox products using Qualcomm vendor ID */
|
||||
{ USB_DEVICE(QUALCOMM_VENDOR_ID, UBLOX_PRODUCT_R410M),
|
||||
.driver_info = RSVD(1) | RSVD(3) },
|
||||
/* Quectel products using Quectel vendor ID */
|
||||
{ USB_DEVICE(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC21),
|
||||
.driver_info = RSVD(4) },
|
||||
|
|
|
@ -335,47 +335,48 @@ static int palm_os_3_probe(struct usb_serial *serial,
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (retval == sizeof(*connection_info)) {
|
||||
connection_info = (struct visor_connection_info *)
|
||||
transfer_buffer;
|
||||
|
||||
num_ports = le16_to_cpu(connection_info->num_ports);
|
||||
for (i = 0; i < num_ports; ++i) {
|
||||
switch (
|
||||
connection_info->connections[i].port_function_id) {
|
||||
case VISOR_FUNCTION_GENERIC:
|
||||
string = "Generic";
|
||||
break;
|
||||
case VISOR_FUNCTION_DEBUGGER:
|
||||
string = "Debugger";
|
||||
break;
|
||||
case VISOR_FUNCTION_HOTSYNC:
|
||||
string = "HotSync";
|
||||
break;
|
||||
case VISOR_FUNCTION_CONSOLE:
|
||||
string = "Console";
|
||||
break;
|
||||
case VISOR_FUNCTION_REMOTE_FILE_SYS:
|
||||
string = "Remote File System";
|
||||
break;
|
||||
default:
|
||||
string = "unknown";
|
||||
break;
|
||||
}
|
||||
dev_info(dev, "%s: port %d, is for %s use\n",
|
||||
serial->type->description,
|
||||
connection_info->connections[i].port, string);
|
||||
}
|
||||
if (retval != sizeof(*connection_info)) {
|
||||
dev_err(dev, "Invalid connection information received from device\n");
|
||||
retval = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
/*
|
||||
* Handle devices that report invalid stuff here.
|
||||
*/
|
||||
|
||||
connection_info = (struct visor_connection_info *)transfer_buffer;
|
||||
|
||||
num_ports = le16_to_cpu(connection_info->num_ports);
|
||||
|
||||
/* Handle devices that report invalid stuff here. */
|
||||
if (num_ports == 0 || num_ports > 2) {
|
||||
dev_warn(dev, "%s: No valid connect info available\n",
|
||||
serial->type->description);
|
||||
num_ports = 2;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_ports; ++i) {
|
||||
switch (connection_info->connections[i].port_function_id) {
|
||||
case VISOR_FUNCTION_GENERIC:
|
||||
string = "Generic";
|
||||
break;
|
||||
case VISOR_FUNCTION_DEBUGGER:
|
||||
string = "Debugger";
|
||||
break;
|
||||
case VISOR_FUNCTION_HOTSYNC:
|
||||
string = "HotSync";
|
||||
break;
|
||||
case VISOR_FUNCTION_CONSOLE:
|
||||
string = "Console";
|
||||
break;
|
||||
case VISOR_FUNCTION_REMOTE_FILE_SYS:
|
||||
string = "Remote File System";
|
||||
break;
|
||||
default:
|
||||
string = "unknown";
|
||||
break;
|
||||
}
|
||||
dev_info(dev, "%s: port %d, is for %s use\n",
|
||||
serial->type->description,
|
||||
connection_info->connections[i].port, string);
|
||||
}
|
||||
dev_info(dev, "%s: Number of ports: %d\n", serial->type->description,
|
||||
num_ports);
|
||||
|
||||
|
|
|
@ -3725,6 +3725,7 @@ void tcpm_unregister_port(struct tcpm_port *port)
|
|||
for (i = 0; i < ARRAY_SIZE(port->port_altmode); i++)
|
||||
typec_unregister_altmode(port->port_altmode[i]);
|
||||
typec_unregister_port(port->typec_port);
|
||||
usb_role_switch_put(port->role_sw);
|
||||
tcpm_debugfs_exit(port);
|
||||
destroy_workqueue(port->wq);
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ struct tps6598x {
|
|||
struct device *dev;
|
||||
struct regmap *regmap;
|
||||
struct mutex lock; /* device lock */
|
||||
u8 i2c_protocol:1;
|
||||
|
||||
struct typec_port *port;
|
||||
struct typec_partner *partner;
|
||||
|
@ -80,19 +81,39 @@ struct tps6598x {
|
|||
struct typec_capability typec_cap;
|
||||
};
|
||||
|
||||
static int
|
||||
tps6598x_block_read(struct tps6598x *tps, u8 reg, void *val, size_t len)
|
||||
{
|
||||
u8 data[len + 1];
|
||||
int ret;
|
||||
|
||||
if (!tps->i2c_protocol)
|
||||
return regmap_raw_read(tps->regmap, reg, val, len);
|
||||
|
||||
ret = regmap_raw_read(tps->regmap, reg, data, sizeof(data));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (data[0] < len)
|
||||
return -EIO;
|
||||
|
||||
memcpy(val, &data[1], len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int tps6598x_read16(struct tps6598x *tps, u8 reg, u16 *val)
|
||||
{
|
||||
return regmap_raw_read(tps->regmap, reg, val, sizeof(u16));
|
||||
return tps6598x_block_read(tps, reg, val, sizeof(u16));
|
||||
}
|
||||
|
||||
static inline int tps6598x_read32(struct tps6598x *tps, u8 reg, u32 *val)
|
||||
{
|
||||
return regmap_raw_read(tps->regmap, reg, val, sizeof(u32));
|
||||
return tps6598x_block_read(tps, reg, val, sizeof(u32));
|
||||
}
|
||||
|
||||
static inline int tps6598x_read64(struct tps6598x *tps, u8 reg, u64 *val)
|
||||
{
|
||||
return regmap_raw_read(tps->regmap, reg, val, sizeof(u64));
|
||||
return tps6598x_block_read(tps, reg, val, sizeof(u64));
|
||||
}
|
||||
|
||||
static inline int tps6598x_write16(struct tps6598x *tps, u8 reg, u16 val)
|
||||
|
@ -121,8 +142,8 @@ static int tps6598x_read_partner_identity(struct tps6598x *tps)
|
|||
struct tps6598x_rx_identity_reg id;
|
||||
int ret;
|
||||
|
||||
ret = regmap_raw_read(tps->regmap, TPS_REG_RX_IDENTITY_SOP,
|
||||
&id, sizeof(id));
|
||||
ret = tps6598x_block_read(tps, TPS_REG_RX_IDENTITY_SOP,
|
||||
&id, sizeof(id));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -224,13 +245,13 @@ static int tps6598x_exec_cmd(struct tps6598x *tps, const char *cmd,
|
|||
} while (val);
|
||||
|
||||
if (out_len) {
|
||||
ret = regmap_raw_read(tps->regmap, TPS_REG_DATA1,
|
||||
out_data, out_len);
|
||||
ret = tps6598x_block_read(tps, TPS_REG_DATA1,
|
||||
out_data, out_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
val = out_data[0];
|
||||
} else {
|
||||
ret = regmap_read(tps->regmap, TPS_REG_DATA1, &val);
|
||||
ret = tps6598x_block_read(tps, TPS_REG_DATA1, &val, sizeof(u8));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
@ -385,6 +406,16 @@ static int tps6598x_probe(struct i2c_client *client)
|
|||
if (!vid)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* Checking can the adapter handle SMBus protocol. If it can not, the
|
||||
* driver needs to take care of block reads separately.
|
||||
*
|
||||
* FIXME: Testing with I2C_FUNC_I2C. regmap-i2c uses I2C protocol
|
||||
* unconditionally if the adapter has I2C_FUNC_I2C set.
|
||||
*/
|
||||
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
|
||||
tps->i2c_protocol = true;
|
||||
|
||||
ret = tps6598x_read32(tps, TPS_REG_STATUS, &status);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
#define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */
|
||||
|
||||
/* big enough to hold our biggest descriptor */
|
||||
#define USB_COMP_EP0_BUFSIZ 1024
|
||||
#define USB_COMP_EP0_BUFSIZ 4096
|
||||
|
||||
/* OS feature descriptor length <= 4kB */
|
||||
#define USB_COMP_EP0_OS_DESC_BUFSIZ 4096
|
||||
|
|
Загрузка…
Ссылка в новой задаче