From 064b40754291f95121bbdb05645a3a110d0ae346 Mon Sep 17 00:00:00 2001 From: Luc Van Oostenryck Date: Tue, 24 Apr 2018 15:18:41 +0200 Subject: usb: gadget: f_phonet: fix pn_net_xmit()'s return type The method ndo_start_xmit() is defined as returning an 'netdev_tx_t', which is a typedef for an enum type, but the implementation in this driver returns an 'int'. Fix this by returning 'netdev_tx_t' in this driver too. Signed-off-by: Luc Van Oostenryck Signed-off-by: Felipe Balbi --- drivers/usb/gadget/function/f_phonet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c index 7889bcc0509a..8b72b192c747 100644 --- a/drivers/usb/gadget/function/f_phonet.c +++ b/drivers/usb/gadget/function/f_phonet.c @@ -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; -- cgit v1.2.3 From 438fea2a6325933868aebc20279e2669c9a21207 Mon Sep 17 00:00:00 2001 From: Tomeu Vizoso Date: Mon, 26 Mar 2018 11:00:01 +0200 Subject: usb: dwc2: dwc2_vbus_supply_init: fix error check devm_regulator_get_optional returns -ENODEV if the regulator isn't there, so if that's the case we have to make sure not to leave -ENODEV in the regulator pointer. Also, make sure we return 0 in that case, but correctly propagate any other errors. Also propagate the error from _dwc2_hcd_start. Fixes: 531ef5ebea96 ("usb: dwc2: add support for host mode external vbus supply") Cc: Amelie Delaunay Reviewed-by: Amelie Delaunay Reviewed-by: Heiko Stuebner Reviewed-by: Grigor Tovmasyan Tested-by: Heiko Stuebner Acked-by: Minas Harutyunyan Signed-off-by: Tomeu Vizoso Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/hcd.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 190f95964000..c51b73b3e048 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -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); } /* -- cgit v1.2.3 From 0ebf2a2c02b0976e939e795b1b9a53d32aeac8bc Mon Sep 17 00:00:00 2001 From: Artur Petrosyan Date: Mon, 16 Apr 2018 08:45:31 -0400 Subject: usb: dwc2: WA for Full speed ISOC IN in DDMA mode. By clearing NAK status of EP, core will send ZLP to IN token and assert NAK interrupt relying on TxFIFO status only. 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. Signed-off-by: Artur Petrosyan Signed-off-by: Minas Harutyunyan Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/core.h | 2 ++ drivers/usb/dwc2/gadget.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index d83be5651f87..a666e0758a99 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -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 diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 6c32bf26e48e..83cb5577a52f 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -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); -- cgit v1.2.3 From a53097c2319c9df16dff6109392c50aa422265bf Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 28 Mar 2018 13:41:13 +0000 Subject: usb: dwc2: pci: Fix error return code in dwc2_pci_probe() Fix to return error code -ENOMEM from the alloc fail error handling case instead of 0, as done elsewhere in this function. Fixes: ecd29dabb2ba ("usb: dwc2: pci: Handle error cleanup in probe") Reviewed-by: Grigor Tovmasyan Acked-by: Minas Harutyunyan Signed-off-by: Wei Yongjun Signed-off-by: Felipe Balbi --- drivers/usb/dwc2/pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c index 7f21747007f1..bea2e8ec0369 100644 --- a/drivers/usb/dwc2/pci.c +++ b/drivers/usb/dwc2/pci.c @@ -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) { -- cgit v1.2.3 From 9cffd15de0c322c574085759793dbbcfafa91746 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Thu, 29 Mar 2018 02:20:10 +0000 Subject: usb: dwc3: gadget: dwc3_gadget_del_and_unmap_request() can be static Fixes the following sparse warning: drivers/usb/dwc3/gadget.c:169:6: warning: symbol 'dwc3_gadget_del_and_unmap_request' was not declared. Should it be static? Signed-off-by: Wei Yongjun Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8796a5ee9bb9..206ecc7428da 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -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; -- cgit v1.2.3 From 96bd39df29c29d348d65311e5954c0b7d3a2a790 Mon Sep 17 00:00:00 2001 From: Mayank Rana Date: Fri, 23 Mar 2018 10:05:33 -0700 Subject: usb: dwc3: gadget: Fix list_del corruption in dwc3_ep_dequeue dwc3_ep_dequeue() waits for completion of End Transfer command using wait_event_lock_irq(), which will release the dwc3->lock while waiting and reacquire after completion. This allows a potential race condition with ep_disable() which also removes all requests from started_list and pending_list. The check for NULL r->trb should catch this but currently it exits to the wrong 'out1' label which calls dwc3_gadget_giveback(). Since its list entry was already removed, if CONFIG_DEBUG_LIST is enabled a 'list_del corruption' bug is thrown since its next/prev pointers are already LIST_POISON1/2. If r->trb is NULL it should simply exit to 'out0'. Fixes: cf3113d893d4 ("usb: dwc3: gadget: properly increment dequeue pointer on ep_dequeue") Cc: stable@vger.kernel.org # v4.12+ Signed-off-by: Mayank Rana Signed-off-by: Jack Pham Signed-off-by: Felipe Balbi --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 206ecc7428da..0dedf8a799f4 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -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; -- cgit v1.2.3 From 2b63f1329df2cd814c1f8353fae4853ace6521d1 Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Mon, 30 Apr 2018 11:20:53 -0500 Subject: usb: musb: host: fix potential NULL pointer dereference musb_start_urb() doesn't check the pass-in parameter if it is NULL. But in musb_bulk_nak_timeout() the parameter passed to musb_start_urb() is returned from first_qh(), which could be NULL. So wrap the musb_start_urb() call here with a if condition check to avoid the potential NULL pointer dereference. Fixes: f283862f3b5c ("usb: musb: NAK timeout scheme on bulk TX endpoint") Cc: stable@vger.kernel.org # v3.7+ Signed-off-by: Bin Liu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 4fa372c845e1..e7f99d55922a 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -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); } } -- cgit v1.2.3 From 9aea9b6cc78d2b99b23d84fb2e0bc6e464c6569e Mon Sep 17 00:00:00 2001 From: Bin Liu Date: Mon, 30 Apr 2018 11:20:54 -0500 Subject: usb: musb: trace: fix NULL pointer dereference in musb_g_tx() The usb_request pointer could be NULL in musb_g_tx(), where the tracepoint call would trigger the NULL pointer dereference failure when parsing the members of the usb_request pointer. Move the tracepoint call to where the usb_request pointer is already checked to solve the issue. Fixes: fc78003e5345 ("usb: musb: gadget: add usb-request tracepoints") Cc: stable@vger.kernel.org # v4.8+ Signed-off-by: Bin Liu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index e564695c6c8d..71c5835ea9cd 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -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; -- cgit v1.2.3 From 4205cb01f6e9ef2ae6daa7be4e8ac1edeb4c9d64 Mon Sep 17 00:00:00 2001 From: "SZ Lin (林上智)" Date: Thu, 26 Apr 2018 14:28:31 +0800 Subject: USB: serial: option: adding support for ublox R410M MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds support for ublox R410M PID 0x90b2 USB modem to option driver, this module supports LTE Cat M1 / NB1. Interface layout: 0: QCDM/DIAG 1: ADB 2: AT 3: RMNET Signed-off-by: SZ Lin (林上智) Cc: stable Signed-off-by: Johan Hovold --- drivers/usb/serial/option.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index c3f252283ab9..2058852a87fa 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -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) }, -- cgit v1.2.3 From 4842ed5bfcb9daf6660537d70503c18d38dbdbb8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 29 Apr 2018 17:41:55 +0200 Subject: USB: serial: visor: handle potential invalid device configuration If we get an invalid device configuration from a palm 3 type device, we might incorrectly parse things, and we have the potential to crash in "interesting" ways. Fix this up by verifying the size of the configuration passed to us by the device, and only if it is correct, will we handle it. Note that this also fixes an information leak of slab data. Reported-by: Andrey Konovalov Reviewed-by: Andrey Konovalov Signed-off-by: Greg Kroah-Hartman [ johan: add comment about the info leak ] Cc: stable Signed-off-by: Johan Hovold --- drivers/usb/serial/visor.c | 69 +++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index f5373ed2cd45..8ddbecc25d89 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -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); -- cgit v1.2.3 From 44a182b9d17765514fa2b1cc911e4e65134eef93 Mon Sep 17 00:00:00 2001 From: Mathias Nyman Date: Thu, 3 May 2018 17:30:07 +0300 Subject: xhci: Fix use-after-free in xhci_free_virt_device KASAN found a use-after-free in xhci_free_virt_device+0x33b/0x38e where xhci_free_virt_device() sets slot id to 0 if udev exists: if (dev->udev && dev->udev->slot_id) dev->udev->slot_id = 0; dev->udev will be true even if udev is freed because dev->udev is not set to NULL. set dev->udev pointer to NULL in xhci_free_dev() The original patch went to stable so this fix needs to be applied there as well. Fixes: a400efe455f7 ("xhci: zero usb device slot_id member when disabling and freeing a xhci slot") Cc: Reported-by: Guenter Roeck Reviewed-by: Guenter Roeck Tested-by: Guenter Roeck Signed-off-by: Mathias Nyman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 9b27798ecce5..711da3306b14 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -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); -- cgit v1.2.3 From fb5ee84ea72c5f1b6cabdd1c9d6e8648995ca7c6 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 3 May 2018 11:04:48 -0400 Subject: USB: Accept bulk endpoints with 1024-byte maxpacket Some non-compliant high-speed USB devices have bulk endpoints with a 1024-byte maxpacket size. Although such endpoints don't work with xHCI host controllers, they do work with EHCI controllers. We used to accept these invalid sizes (with a warning), but we no longer do because of an unintentional change introduced by commit aed9d65ac327 ("USB: validate wMaxPacketValue entries in endpoint descriptors"). This patch restores the old behavior, so that people with these peculiar devices can use them without patching their kernels by hand. Signed-off-by: Alan Stern Suggested-by: Elvinas Fixes: aed9d65ac327 ("USB: validate wMaxPacketValue entries in endpoint descriptors") CC: Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/config.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index c821b4b9647e..7b5cb28ffb35 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -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] = { -- cgit v1.2.3 From 5671a4608c326b8ec16dec2f0f32e64a33cdd317 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Mon, 30 Apr 2018 15:41:56 +0300 Subject: usb: typec: tcpm: Release the role mux when exiting The ref count for the USB role switch device must be released after we are done using the switch. Fixes: c6962c29729c ("usb: typec: tcpm: Set USB role switch to device mode when configured as such") Signed-off-by: Heikki Krogerus Reviewed-by: Hans de Goede Reviewed-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tcpm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/typec/tcpm.c b/drivers/usb/typec/tcpm.c index 677d12138dbd..ded49e3bf2b0 100644 --- a/drivers/usb/typec/tcpm.c +++ b/drivers/usb/typec/tcpm.c @@ -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); } -- cgit v1.2.3 From 1a2f474d328f292ee706414824ec4ca690cdf5ba Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 25 Apr 2018 17:22:09 +0300 Subject: usb: typec: tps6598x: handle block reads separately with plain-I2C adapters If the I2C adapter that the PD controller is attached to does not support SMBus protocol, the driver needs to handle block reads separately. The first byte returned in block read protocol will show the total number of bytes. It needs to be stripped away. This is handled separately in the driver only because right now we have no way of requesting the used protocol with regmap-i2c. This is in practice a workaround for what is really a problem in regmap-i2c. The other option would have been to register custom regmap, or not use regmap at all, however, since the solution is very simple, I choose to use it in this case for convenience. It is easy to remove once we figure out how to handle this kind of cases in regmap-i2c. Fixes: 0a4c005bd171 ("usb: typec: driver for TI TPS6598x USB Power Delivery controllers") Reviewed-by: Guenter Roeck Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/usb/typec/tps6598x.c | 47 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/typec/tps6598x.c b/drivers/usb/typec/tps6598x.c index 8b8406867c02..4b4c8d271b27 100644 --- a/drivers/usb/typec/tps6598x.c +++ b/drivers/usb/typec/tps6598x.c @@ -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; -- cgit v1.2.3 From 43b78f1155c868208a413082179251f5fba78153 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 4 May 2018 14:35:12 -0700 Subject: Revert "usb: host: ehci: Use dma_pool_zalloc()" This reverts commit 22072e83ebd510fb6a090aef9d65ccfda9b1e7e4 as it is broken. Alan writes: What you can't see just from reading the patch is that in both cases (ehci->itd_pool and ehci->sitd_pool) there are two allocation paths -- the two branches of an "if" statement -- and only one of the paths calls dma_pool_[z]alloc. However, the memset is needed for both paths, and so it can't be eliminated. Given that it must be present, there's no advantage to calling dma_pool_zalloc rather than dma_pool_alloc. Reported-by: Erick Cafferata Cc: Alan Stern Cc: Souptick Joarder Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-mem.c | 3 ++- drivers/usb/host/ehci-sched.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-mem.c b/drivers/usb/host/ehci-mem.c index 4c6c08b675b5..21307d862af6 100644 --- a/drivers/usb/host/ehci-mem.c +++ b/drivers/usb/host/ehci-mem.c @@ -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); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 28e2a338b481..e56db44708bc 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -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); -- cgit v1.2.3