From cdd1015de1656fcc770318f9e1bd9039dffbee1b Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Mon, 12 Oct 2015 10:30:53 -0400 Subject: [PATCH 1/3] usb: hub: add error into to connect --- drivers/usb/core/hub.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b649fef2e35d4a..d78adb3dbbf8a0 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4621,6 +4621,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, struct usb_port *port_dev = hub->ports[port1 - 1]; struct usb_device *udev = port_dev->child; static int unreliable_port = -1; + unsigned long speed = USB_SPEED_SUPER; /* Disconnect any existing devices under this port */ if (udev) { @@ -4704,6 +4705,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, /* reset (non-USB 3.0 devices) and get descriptor */ usb_lock_port(port_dev); status = hub_port_init(hub, udev, port1, i); + speed = udev->speed; usb_unlock_port(port_dev); if (status < 0) goto loop; @@ -4808,9 +4810,13 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, if (hub->hdev->parent || !hcd->driver->port_handed_over || !(hcd->driver->port_handed_over)(hcd, port1)) { - if (status != -ENOTCONN && status != -ENODEV) - dev_err(&port_dev->dev, - "unable to enumerate USB device\n"); + if (status != -ENOTCONN && status != -ENODEV) { + dev_err(&port_dev->dev, "unable to enumerate USB device" + " at %s while bus at %s \n", + usb_speed_string(speed), + hdev->descriptor.bDeviceProtocol == USB_HUB_PR_FS ? + "FULL_SPEED" : "HIGH_SPEED"); + } } done: From a9f17284e124e78c48a7d6195dcffa5545e6425e Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Mon, 12 Oct 2015 10:53:29 -0400 Subject: [PATCH 2/3] usb: hub: add debug info at disconnect --- drivers/usb/core/hub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d78adb3dbbf8a0..fd356db14c5048 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2131,8 +2131,8 @@ void usb_disconnect(struct usb_device **pdev) * this quiesces everything except pending urbs. */ usb_set_device_state(udev, USB_STATE_NOTATTACHED); - dev_info(&udev->dev, "USB disconnect, device number %d\n", - udev->devnum); + dev_info(&udev->dev, "USB disconnect, device number %d running at %s\n", + udev->devnum, usb_speed_string(udev->speed)); usb_lock_device(udev); From 66869c654a62c91104daf9e17c2d75c057c38bdc Mon Sep 17 00:00:00 2001 From: Jorge Ramirez-Ortiz Date: Mon, 12 Oct 2015 12:07:34 -0400 Subject: [PATCH 3/3] hikey: handle usb bus speed switch --- drivers/usb/core/hub.c | 11 ++++++++++ drivers/usb/dwc2/hcd.c | 43 ++++++++++++++++++++++++++----------- drivers/usb/dwc2/platform.c | 4 ++-- include/linux/usb/hcd.h | 1 + 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index fd356db14c5048..755bfe32f395f8 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2134,6 +2134,12 @@ void usb_disconnect(struct usb_device **pdev) dev_info(&udev->dev, "USB disconnect, device number %d running at %s\n", udev->devnum, usb_speed_string(udev->speed)); + if (udev->speed < USB_SPEED_HIGH ) { + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + if (hcd->driver->change_bus_speed) + hcd->driver->change_bus_speed(hcd, 0); + } + usb_lock_device(udev); hub_disconnect_children(udev); @@ -4816,6 +4822,11 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, usb_speed_string(speed), hdev->descriptor.bDeviceProtocol == USB_HUB_PR_FS ? "FULL_SPEED" : "HIGH_SPEED"); + + if (speed < USB_SPEED_HIGH && + hdev->descriptor.bDeviceProtocol > USB_HUB_PR_FS && + hcd->driver->change_bus_speed) + hcd->driver->change_bus_speed(hcd, 1); } } diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index af8ab9506a1623..82f617800f6a06 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -54,6 +54,19 @@ #include "core.h" #include "hcd.h" +struct wrapper_priv_data { + struct dwc2_hsotg *hsotg; +}; + +/* Gets the dwc2_hsotg from a usb_hcd */ +static struct dwc2_hsotg *dwc2_hcd_to_hsotg(struct usb_hcd *hcd) +{ + struct wrapper_priv_data *p; + + p = (struct wrapper_priv_data *) &hcd->hcd_priv; + return p->hsotg; +} + /** * dwc2_dump_channel_info() - Prints the state of a host channel * @@ -1339,6 +1352,23 @@ void dwc2_hcd_queue_transactions(struct dwc2_hsotg *hsotg, } } } +/* + * 0: high speed + * 1: full speed + */ +static void dwc2_change_bus_speed(struct usb_hcd* hcd, int speed) +{ + struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd); + static int last_speed = 0; + + if (speed == last_speed) + return; + + hsotg->core_params->speed = speed; + queue_work(hsotg->wq_otg, &hsotg->wf_otg); + + last_speed = speed; +} static void dwc2_conn_id_status_change(struct work_struct *work) { @@ -2064,18 +2094,6 @@ void dwc2_hcd_dump_frrem(struct dwc2_hsotg *hsotg) #endif } -struct wrapper_priv_data { - struct dwc2_hsotg *hsotg; -}; - -/* Gets the dwc2_hsotg from a usb_hcd */ -static struct dwc2_hsotg *dwc2_hcd_to_hsotg(struct usb_hcd *hcd) -{ - struct wrapper_priv_data *p; - - p = (struct wrapper_priv_data *) &hcd->hcd_priv; - return p->hsotg; -} static int _dwc2_hcd_start(struct usb_hcd *hcd); @@ -2676,6 +2694,7 @@ static struct hc_driver dwc2_hc_driver = { .hub_status_data = _dwc2_hcd_hub_status_data, .hub_control = _dwc2_hcd_hub_control, .clear_tt_buffer_complete = _dwc2_hcd_clear_tt_buffer_complete, + .change_bus_speed = dwc2_change_bus_speed, }; /* diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 61ccb537034593..8fef5b793bd64a 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -55,8 +55,8 @@ static const struct dwc2_core_params params_hisi = { .otg_ver = 0, /* 1.3 */ .dma_enable = 1, .dma_desc_enable = 0, -// .speed = 0, /* High Speed */ - .speed = 1, /* Full Speed */ + .speed = 0, /* High Speed */ +// .speed = 1, /* Full Speed */ .enable_dynamic_fifo = 1, .en_multiple_tx_fifo = 1, .host_rx_fifo_size = 512, diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index cd96a2bc338897..2f8c9b71005085 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -379,6 +379,7 @@ struct hc_driver { int (*disable_usb3_lpm_timeout)(struct usb_hcd *, struct usb_device *, enum usb3_link_state state); int (*find_raw_port_number)(struct usb_hcd *, int); + void (*change_bus_speed)(struct usb_hcd*, int); }; static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)