[U-Boot] [PATCH 0/3] usb: ss: Fixes for super speed framework

This patch series fixes changes for Super speed framework which got pulled-in 'u-boot-usb/next'. First patch fixes Port Status and Port feature macro constants, then next patch parallelizes power-cycling of power on root-hub ports. 3rd patch in this series also sync the min3/max3 definitions with Linux kernel.
Based on u-boot-usb/next branch with following patch reverted: usb: hub: Reset only usb 2.0 ports
Vivek Gautam (3): usb: hub: Parallelize power-cycling of root-hub ports usb: fix: Fixing Port status and feature number constants usb: common: Use a global definition for 'min3'
common/usb_hub.c | 63 ++++++++++++++++++++++++++++-------------- drivers/usb/host/ehci-hcd.c | 10 ------- include/common.h | 25 ++++++++++++++--- include/usb_defs.h | 39 +++++++++++++++----------- 4 files changed, 86 insertions(+), 51 deletions(-)

Untill now we power-cycle (aka: disable power on a port and re-enabling again) one port at a time. Delay of 20ms for Port-power to change multiplies with number of ports in this case. So better we parallelize this process: disable power on all ports, wait for port-power to stabilize and then re-enable the power subsequently.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- common/usb_hub.c | 23 ++++++++++++++--------- 1 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/common/usb_hub.c b/common/usb_hub.c index 1e225e6..dad0409 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -105,22 +105,25 @@ static void usb_hub_power_on(struct usb_hub_device *hub) int ret;
dev = hub->pusb_dev; - /* Enable power to the ports */ + + /* + * Enable power to the ports: + * Here we Power-cycle the ports: aka, + * turning them off and turning on again. + */ debug("enabling power on all ports\n"); for (i = 0; i < dev->maxchild; i++) { - /* - * Power-cycle the ports here: aka, - * turning them off and turning on again. - */ usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); debug("port %d returns %lX\n", i + 1, dev->status); + }
- /* Wait at least 2*bPwrOn2PwrGood for PP to change */ - mdelay(pgood_delay); + /* Wait at least 2*bPwrOn2PwrGood for PP to change */ + mdelay(pgood_delay);
+ for (i = 0; i < dev->maxchild; i++) { ret = usb_get_port_status(dev, i + 1, portsts); if (ret < 0) { - debug("port %d: get_port_status failed\n", i + 1); + printf("port %d: get_port_status failed\n", i + 1); return; }
@@ -135,10 +138,12 @@ static void usb_hub_power_on(struct usb_hub_device *hub) */ portstatus = le16_to_cpu(portsts->wPortStatus); if (portstatus & (USB_PORT_STAT_POWER << 1)) { - debug("port %d: Port power change failed\n", i + 1); + printf("port %d: Port power change failed\n", i + 1); return; } + }
+ for (i = 0; i < dev->maxchild; i++) { usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER); debug("port %d returns %lX\n", i + 1, dev->status); }

Fix the Port status bit constants and Port feature number constants as a part of USB 2.0 and USB 3.0 Hub class.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- common/usb_hub.c | 40 ++++++++++++++++++++++++++++------------ include/usb_defs.h | 39 +++++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 28 deletions(-)
diff --git a/common/usb_hub.c b/common/usb_hub.c index dad0409..d9816e4 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -170,14 +170,24 @@ static struct usb_hub_device *usb_hub_allocate(void)
static inline char *portspeed(int portstatus) { - if (portstatus & (1 << USB_PORT_FEAT_SUPERSPEED)) - return "5 Gb/s"; - else if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED)) - return "480 Mb/s"; - else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED)) - return "1.5 Mb/s"; - else - return "12 Mb/s"; + char *speed_str; + + switch (portstatus & USB_PORT_STAT_SPEED_MASK) { + case USB_PORT_STAT_SUPER_SPEED: + speed_str = "5 Gb/s"; + break; + case USB_PORT_STAT_HIGH_SPEED: + speed_str = "480 Mb/s"; + break; + case USB_PORT_STAT_LOW_SPEED: + speed_str = "1.5 Mb/s"; + break; + default: + speed_str = "12 Mb/s"; + break; + } + + return speed_str; }
int hub_port_reset(struct usb_device *dev, int port, @@ -275,14 +285,20 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port) /* Allocate a new device struct for it */ usb = usb_alloc_new_device(dev->controller);
- if (portstatus & USB_PORT_STAT_SUPER_SPEED) + switch (portstatus & USB_PORT_STAT_SPEED_MASK) { + case USB_PORT_STAT_SUPER_SPEED: usb->speed = USB_SPEED_SUPER; - else if (portstatus & USB_PORT_STAT_HIGH_SPEED) + break; + case USB_PORT_STAT_HIGH_SPEED: usb->speed = USB_SPEED_HIGH; - else if (portstatus & USB_PORT_STAT_LOW_SPEED) + break; + case USB_PORT_STAT_LOW_SPEED: usb->speed = USB_SPEED_LOW; - else + break; + default: usb->speed = USB_SPEED_FULL; + break; + }
dev->children[port] = usb; usb->parent = dev; diff --git a/include/usb_defs.h b/include/usb_defs.h index 6ce6791..4f3601a 100644 --- a/include/usb_defs.h +++ b/include/usb_defs.h @@ -215,8 +215,6 @@ #define USB_PORT_FEAT_POWER 8 #define USB_PORT_FEAT_LOWSPEED 9 #define USB_PORT_FEAT_HIGHSPEED 10 -#define USB_PORT_FEAT_FULLSPEED 11 -#define USB_PORT_FEAT_SUPERSPEED 12 #define USB_PORT_FEAT_C_CONNECTION 16 #define USB_PORT_FEAT_C_ENABLE 17 #define USB_PORT_FEAT_C_SUSPEND 18 @@ -224,6 +222,17 @@ #define USB_PORT_FEAT_C_RESET 20 #define USB_PORT_FEAT_TEST 21
+/* + * Changes to Port feature numbers for Super speed, + * from USB 3.0 spec Table 10-8 + */ +#define USB_SS_PORT_FEAT_U1_TIMEOUT 23 +#define USB_SS_PORT_FEAT_U2_TIMEOUT 24 +#define USB_SS_PORT_FEAT_C_LINK_STATE 25 +#define USB_SS_PORT_FEAT_C_CONFIG_ERROR 26 +#define USB_SS_PORT_FEAT_BH_RESET 28 +#define USB_SS_PORT_FEAT_C_BH_RESET 29 + /* wPortStatus bits */ #define USB_PORT_STAT_CONNECTION 0x0001 #define USB_PORT_STAT_ENABLE 0x0002 @@ -233,20 +242,18 @@ #define USB_PORT_STAT_POWER 0x0100 #define USB_PORT_STAT_LOW_SPEED 0x0200 #define USB_PORT_STAT_HIGH_SPEED 0x0400 /* support for EHCI */ -#define USB_PORT_STAT_FULL_SPEED 0x0800 -#define USB_PORT_STAT_SUPER_SPEED 0x1000 /* support for XHCI */ -#define USB_PORT_STAT_SPEED \ - (USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED | \ - USB_PORT_STAT_FULL_SPEED | USB_PORT_STAT_SUPER_SPEED) +#define USB_PORT_STAT_SUPER_SPEED 0x0600 /* faking support to XHCI */ +#define USB_PORT_STAT_SPEED_MASK \ + (USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED)
/* - * Additions to wPortStatus bit field from USB 3.0 - * See USB 3.0 spec Table 10-10 + * Changes to wPortStatus bit field in USB 3.0 + * See USB 3.0 spec Table 10-11 */ -#define USB_PORT_STAT_LINK_STATE 0x01e0 +#define USB_SS_PORT_STAT_LINK_STATE 0x01e0 #define USB_SS_PORT_STAT_POWER 0x0200 #define USB_SS_PORT_STAT_SPEED 0x1c00 -#define USB_PORT_STAT_SPEED_5GBPS 0x0000 +#define USB_SS_PORT_STAT_SPEED_5GBPS 0x0000
/* wPortChange bits */ #define USB_PORT_STAT_C_CONNECTION 0x0001 @@ -256,12 +263,12 @@ #define USB_PORT_STAT_C_RESET 0x0010
/* - * Addition to wPortChange bit fields form USB 3.0 - * See USB 3.0 spec Table 10-11 + * Changes to wPortChange bit fields in USB 3.0 + * See USB 3.0 spec Table 10-12 */ -#define USB_PORT_STAT_C_BH_RESET 0x0020 -#define USB_PORT_STAT_C_LINK_STATE 0x0040 -#define USB_PORT_STAT_C_CONFIG_ERROR 0x0080 +#define USB_SS_PORT_STAT_C_BH_RESET 0x0020 +#define USB_SS_PORT_STAT_C_LINK_STATE 0x0040 +#define USB_SS_PORT_STAT_C_CONFIG_ERROR 0x0080
/* wHubCharacteristics (masks) */ #define HUB_CHAR_LPSM 0x0003

On Wed, Apr 24, 2013 at 5:50 AM, Vivek Gautam gautam.vivek@samsung.com wrote:
Fix the Port status bit constants and Port feature number constants as a part of USB 2.0 and USB 3.0 Hub class.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com
common/usb_hub.c | 40 ++++++++++++++++++++++++++++------------ include/usb_defs.h | 39 +++++++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 28 deletions(-)
diff --git a/common/usb_hub.c b/common/usb_hub.c index dad0409..d9816e4 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -170,14 +170,24 @@ static struct usb_hub_device *usb_hub_allocate(void)
static inline char *portspeed(int portstatus) {
if (portstatus & (1 << USB_PORT_FEAT_SUPERSPEED))
return "5 Gb/s";
else if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED))
return "480 Mb/s";
else if (portstatus & (1 << USB_PORT_FEAT_LOWSPEED))
return "1.5 Mb/s";
else
return "12 Mb/s";
char *speed_str;
switch (portstatus & USB_PORT_STAT_SPEED_MASK) {
case USB_PORT_STAT_SUPER_SPEED:
speed_str = "5 Gb/s";
break;
case USB_PORT_STAT_HIGH_SPEED:
speed_str = "480 Mb/s";
break;
case USB_PORT_STAT_LOW_SPEED:
speed_str = "1.5 Mb/s";
break;
default:
speed_str = "12 Mb/s";
break;
}
return speed_str;
}
Just a nitpick... you could save 8 lines here by moving the return into the case blocks. Rest of the patch set LGTM.
int hub_port_reset(struct usb_device *dev, int port, @@ -275,14 +285,20 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port) /* Allocate a new device struct for it */ usb = usb_alloc_new_device(dev->controller);
if (portstatus & USB_PORT_STAT_SUPER_SPEED)
switch (portstatus & USB_PORT_STAT_SPEED_MASK) {
case USB_PORT_STAT_SUPER_SPEED: usb->speed = USB_SPEED_SUPER;
else if (portstatus & USB_PORT_STAT_HIGH_SPEED)
break;
case USB_PORT_STAT_HIGH_SPEED: usb->speed = USB_SPEED_HIGH;
else if (portstatus & USB_PORT_STAT_LOW_SPEED)
break;
case USB_PORT_STAT_LOW_SPEED: usb->speed = USB_SPEED_LOW;
else
break;
default: usb->speed = USB_SPEED_FULL;
break;
} dev->children[port] = usb; usb->parent = dev;
diff --git a/include/usb_defs.h b/include/usb_defs.h index 6ce6791..4f3601a 100644 --- a/include/usb_defs.h +++ b/include/usb_defs.h @@ -215,8 +215,6 @@ #define USB_PORT_FEAT_POWER 8 #define USB_PORT_FEAT_LOWSPEED 9 #define USB_PORT_FEAT_HIGHSPEED 10 -#define USB_PORT_FEAT_FULLSPEED 11 -#define USB_PORT_FEAT_SUPERSPEED 12 #define USB_PORT_FEAT_C_CONNECTION 16 #define USB_PORT_FEAT_C_ENABLE 17 #define USB_PORT_FEAT_C_SUSPEND 18 @@ -224,6 +222,17 @@ #define USB_PORT_FEAT_C_RESET 20 #define USB_PORT_FEAT_TEST 21
+/*
- Changes to Port feature numbers for Super speed,
- from USB 3.0 spec Table 10-8
- */
+#define USB_SS_PORT_FEAT_U1_TIMEOUT 23 +#define USB_SS_PORT_FEAT_U2_TIMEOUT 24 +#define USB_SS_PORT_FEAT_C_LINK_STATE 25 +#define USB_SS_PORT_FEAT_C_CONFIG_ERROR 26 +#define USB_SS_PORT_FEAT_BH_RESET 28 +#define USB_SS_PORT_FEAT_C_BH_RESET 29
/* wPortStatus bits */ #define USB_PORT_STAT_CONNECTION 0x0001 #define USB_PORT_STAT_ENABLE 0x0002 @@ -233,20 +242,18 @@ #define USB_PORT_STAT_POWER 0x0100 #define USB_PORT_STAT_LOW_SPEED 0x0200 #define USB_PORT_STAT_HIGH_SPEED 0x0400 /* support for EHCI */ -#define USB_PORT_STAT_FULL_SPEED 0x0800 -#define USB_PORT_STAT_SUPER_SPEED 0x1000 /* support for XHCI */ -#define USB_PORT_STAT_SPEED \
(USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED | \
USB_PORT_STAT_FULL_SPEED | USB_PORT_STAT_SUPER_SPEED)
+#define USB_PORT_STAT_SUPER_SPEED 0x0600 /* faking support to XHCI */ +#define USB_PORT_STAT_SPEED_MASK \
(USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED)
/*
- Additions to wPortStatus bit field from USB 3.0
- See USB 3.0 spec Table 10-10
- Changes to wPortStatus bit field in USB 3.0
*/
- See USB 3.0 spec Table 10-11
-#define USB_PORT_STAT_LINK_STATE 0x01e0 +#define USB_SS_PORT_STAT_LINK_STATE 0x01e0 #define USB_SS_PORT_STAT_POWER 0x0200 #define USB_SS_PORT_STAT_SPEED 0x1c00 -#define USB_PORT_STAT_SPEED_5GBPS 0x0000 +#define USB_SS_PORT_STAT_SPEED_5GBPS 0x0000
/* wPortChange bits */ #define USB_PORT_STAT_C_CONNECTION 0x0001 @@ -256,12 +263,12 @@ #define USB_PORT_STAT_C_RESET 0x0010
/*
- Addition to wPortChange bit fields form USB 3.0
- See USB 3.0 spec Table 10-11
- Changes to wPortChange bit fields in USB 3.0
*/
- See USB 3.0 spec Table 10-12
-#define USB_PORT_STAT_C_BH_RESET 0x0020 -#define USB_PORT_STAT_C_LINK_STATE 0x0040 -#define USB_PORT_STAT_C_CONFIG_ERROR 0x0080 +#define USB_SS_PORT_STAT_C_BH_RESET 0x0020 +#define USB_SS_PORT_STAT_C_LINK_STATE 0x0040 +#define USB_SS_PORT_STAT_C_CONFIG_ERROR 0x0080
/* wHubCharacteristics (masks) */
#define HUB_CHAR_LPSM 0x0003
1.7.6.5

We can use a common global method for calculating minimum of 3 numbers. Put the same in 'common header' and let 'ehci' use it.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com --- drivers/usb/host/ehci-hcd.c | 10 ---------- include/common.h | 25 +++++++++++++++++++++---- 2 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 19d4352..e0f3e4b 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -603,16 +603,6 @@ fail: return -1; }
-static inline int min3(int a, int b, int c) -{ - - if (b < a) - a = b; - if (c < a) - a = c; - return a; -} - int ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) diff --git a/include/common.h b/include/common.h index 0cfa6a8..b0258a0 100644 --- a/include/common.h +++ b/include/common.h @@ -199,18 +199,35 @@ typedef void (interrupt_handler_t)(void *); * General Purpose Utilities */ #define min(X, Y) \ - ({ typeof (X) __x = (X); \ - typeof (Y) __y = (Y); \ + ({ typeof(X) __x = (X); \ + typeof(Y) __y = (Y); \ (__x < __y) ? __x : __y; })
#define max(X, Y) \ - ({ typeof (X) __x = (X); \ - typeof (Y) __y = (Y); \ + ({ typeof(X) __x = (X); \ + typeof(Y) __y = (Y); \ (__x > __y) ? __x : __y; })
#define MIN(x, y) min(x, y) #define MAX(x, y) max(x, y)
+#define min3(X, Y, Z) \ + ({ typeof(X) __x = (X); \ + typeof(Y) __y = (Y); \ + typeof(Z) __z = (Z); \ + __x < __y ? (__x < __z ? __x : __z) : \ + (__y < __z ? __y : __z); }) + +#define max3(X, Y, Z) \ + ({ typeof(X) __x = (X); \ + typeof(Y) __y = (Y); \ + typeof(Z) __z = (Z); \ + __x > __y ? (__x > __z ? __x : __z) : \ + (__y > __z ? __y : __z); }) + +#define MIN3(x, y, z) min3(x, y, z) +#define MAX3(x, y, z) max3(x, y, z) + /* * Return the absolute value of a number. *

CC: Tom Rini
On Wed, Apr 24, 2013 at 6:20 PM, Vivek Gautam gautam.vivek@samsung.com wrote:
We can use a common global method for calculating minimum of 3 numbers. Put the same in 'common header' and let 'ehci' use it.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com
drivers/usb/host/ehci-hcd.c | 10 ---------- include/common.h | 25 +++++++++++++++++++++---- 2 files changed, 21 insertions(+), 14 deletions(-)
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 19d4352..e0f3e4b 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -603,16 +603,6 @@ fail: return -1; }
-static inline int min3(int a, int b, int c) -{
if (b < a)
a = b;
if (c < a)
a = c;
return a;
-}
int ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) diff --git a/include/common.h b/include/common.h index 0cfa6a8..b0258a0 100644 --- a/include/common.h +++ b/include/common.h @@ -199,18 +199,35 @@ typedef void (interrupt_handler_t)(void *);
- General Purpose Utilities
*/ #define min(X, Y) \
({ typeof (X) __x = (X); \
typeof (Y) __y = (Y); \
({ typeof(X) __x = (X); \
typeof(Y) __y = (Y); \ (__x < __y) ? __x : __y; })
#define max(X, Y) \
({ typeof (X) __x = (X); \
typeof (Y) __y = (Y); \
({ typeof(X) __x = (X); \
typeof(Y) __y = (Y); \ (__x > __y) ? __x : __y; })
#define MIN(x, y) min(x, y) #define MAX(x, y) max(x, y)
+#define min3(X, Y, Z) \
({ typeof(X) __x = (X); \
typeof(Y) __y = (Y); \
typeof(Z) __z = (Z); \
__x < __y ? (__x < __z ? __x : __z) : \
(__y < __z ? __y : __z); })
+#define max3(X, Y, Z) \
({ typeof(X) __x = (X); \
typeof(Y) __y = (Y); \
typeof(Z) __z = (Z); \
__x > __y ? (__x > __z ? __x : __z) : \
(__y > __z ? __y : __z); })
+#define MIN3(x, y, z) min3(x, y, z) +#define MAX3(x, y, z) max3(x, y, z)
/*
- Return the absolute value of a number.
-- 1.7.6.5

On Wed, Apr 24, 2013 at 06:20:13PM +0530, Vivek Gautam wrote:
We can use a common global method for calculating minimum of 3 numbers. Put the same in 'common header' and let 'ehci' use it.
Signed-off-by: Vivek Gautam gautam.vivek@samsung.com
Acked-by: Tom Rini trini@ti.com

Dear Vivek Gautam,
This patch series fixes changes for Super speed framework which got pulled-in 'u-boot-usb/next'. First patch fixes Port Status and Port feature macro constants, then next patch parallelizes power-cycling of power on root-hub ports. 3rd patch in this series also sync the min3/max3 definitions with Linux kernel.
Based on u-boot-usb/next branch with following patch reverted: usb: hub: Reset only usb 2.0 ports
Fixed Julius's comment , applied and pushed.
Best regards, Marek Vasut

Hi Marek,
On Thu, Apr 25, 2013 at 8:32 AM, Marek Vasut marex@denx.de wrote:
Dear Vivek Gautam,
This patch series fixes changes for Super speed framework which got pulled-in 'u-boot-usb/next'. First patch fixes Port Status and Port feature macro constants, then next patch parallelizes power-cycling of power on root-hub ports. 3rd patch in this series also sync the min3/max3 definitions with Linux kernel.
Based on u-boot-usb/next branch with following patch reverted: usb: hub: Reset only usb 2.0 ports
Fixed Julius's comment , applied and pushed.
Thanks :-)
participants (5)
-
Julius Werner
-
Marek Vasut
-
Tom Rini
-
Vivek Gautam
-
Vivek Gautam