Commit 5a3e2055 authored by Deng-Cheng Zhu's avatar Deng-Cheng Zhu Committed by Greg Kroah-Hartman

USB/host: Bugfix: Return length of copied buffer in uhci_hub_control()

In addition to the error statuses -ETIMEDOUT and -EPIPE, uhci_hub_control()
needs to return the length of copied buffer when appropriate, so that the
returned status of ->hub_control() in rh_call_control() in the USB core
HCD can be properly handled.

This patch also removes the OK() macro to make the code more readable.
Reviewed-by: default avatarJames Hogan <james.hogan@imgtec.com>
Signed-off-by: default avatarDeng-Cheng Zhu <dengcheng.zhu@imgtec.com>
Acked-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cae9160d
...@@ -75,8 +75,6 @@ static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf) ...@@ -75,8 +75,6 @@ static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf)
return !!*buf; return !!*buf;
} }
#define OK(x) len = (x); break
#define CLR_RH_PORTSTAT(x) \ #define CLR_RH_PORTSTAT(x) \
status = uhci_readw(uhci, port_addr); \ status = uhci_readw(uhci, port_addr); \
status &= ~(RWC_BITS|WZ_BITS); \ status &= ~(RWC_BITS|WZ_BITS); \
...@@ -244,7 +242,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -244,7 +242,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
u16 wIndex, char *buf, u16 wLength) u16 wIndex, char *buf, u16 wLength)
{ {
struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
int status, lstatus, retval = 0, len = 0; int status, lstatus, retval = 0;
unsigned int port = wIndex - 1; unsigned int port = wIndex - 1;
unsigned long port_addr = USBPORTSC1 + 2 * port; unsigned long port_addr = USBPORTSC1 + 2 * port;
u16 wPortChange, wPortStatus; u16 wPortChange, wPortStatus;
...@@ -258,7 +256,8 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -258,7 +256,8 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case GetHubStatus: case GetHubStatus:
*(__le32 *)buf = cpu_to_le32(0); *(__le32 *)buf = cpu_to_le32(0);
OK(4); /* hub power */ retval = 4; /* hub power */
break;
case GetPortStatus: case GetPortStatus:
if (port >= uhci->rh_numports) if (port >= uhci->rh_numports)
goto err; goto err;
...@@ -311,13 +310,14 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -311,13 +310,14 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
*(__le16 *)buf = cpu_to_le16(wPortStatus); *(__le16 *)buf = cpu_to_le16(wPortStatus);
*(__le16 *)(buf + 2) = cpu_to_le16(wPortChange); *(__le16 *)(buf + 2) = cpu_to_le16(wPortChange);
OK(4); retval = 4;
break;
case SetHubFeature: /* We don't implement these */ case SetHubFeature: /* We don't implement these */
case ClearHubFeature: case ClearHubFeature:
switch (wValue) { switch (wValue) {
case C_HUB_OVER_CURRENT: case C_HUB_OVER_CURRENT:
case C_HUB_LOCAL_POWER: case C_HUB_LOCAL_POWER:
OK(0); break;
default: default:
goto err; goto err;
} }
...@@ -329,7 +329,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -329,7 +329,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
switch (wValue) { switch (wValue) {
case USB_PORT_FEAT_SUSPEND: case USB_PORT_FEAT_SUSPEND:
SET_RH_PORTSTAT(USBPORTSC_SUSP); SET_RH_PORTSTAT(USBPORTSC_SUSP);
OK(0); break;
case USB_PORT_FEAT_RESET: case USB_PORT_FEAT_RESET:
SET_RH_PORTSTAT(USBPORTSC_PR); SET_RH_PORTSTAT(USBPORTSC_PR);
...@@ -338,10 +338,10 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -338,10 +338,10 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/* USB v2.0 7.1.7.5 */ /* USB v2.0 7.1.7.5 */
uhci->ports_timeout = jiffies + msecs_to_jiffies(50); uhci->ports_timeout = jiffies + msecs_to_jiffies(50);
OK(0); break;
case USB_PORT_FEAT_POWER: case USB_PORT_FEAT_POWER:
/* UHCI has no power switching */ /* UHCI has no power switching */
OK(0); break;
default: default:
goto err; goto err;
} }
...@@ -356,10 +356,10 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -356,10 +356,10 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
/* Disable terminates Resume signalling */ /* Disable terminates Resume signalling */
uhci_finish_suspend(uhci, port, port_addr); uhci_finish_suspend(uhci, port, port_addr);
OK(0); break;
case USB_PORT_FEAT_C_ENABLE: case USB_PORT_FEAT_C_ENABLE:
CLR_RH_PORTSTAT(USBPORTSC_PEC); CLR_RH_PORTSTAT(USBPORTSC_PEC);
OK(0); break;
case USB_PORT_FEAT_SUSPEND: case USB_PORT_FEAT_SUSPEND:
if (!(uhci_readw(uhci, port_addr) & USBPORTSC_SUSP)) { if (!(uhci_readw(uhci, port_addr) & USBPORTSC_SUSP)) {
...@@ -382,32 +382,32 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, ...@@ -382,32 +382,32 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
uhci->ports_timeout = jiffies + uhci->ports_timeout = jiffies +
msecs_to_jiffies(20); msecs_to_jiffies(20);
} }
OK(0); break;
case USB_PORT_FEAT_C_SUSPEND: case USB_PORT_FEAT_C_SUSPEND:
clear_bit(port, &uhci->port_c_suspend); clear_bit(port, &uhci->port_c_suspend);
OK(0); break;
case USB_PORT_FEAT_POWER: case USB_PORT_FEAT_POWER:
/* UHCI has no power switching */ /* UHCI has no power switching */
goto err; goto err;
case USB_PORT_FEAT_C_CONNECTION: case USB_PORT_FEAT_C_CONNECTION:
CLR_RH_PORTSTAT(USBPORTSC_CSC); CLR_RH_PORTSTAT(USBPORTSC_CSC);
OK(0); break;
case USB_PORT_FEAT_C_OVER_CURRENT: case USB_PORT_FEAT_C_OVER_CURRENT:
CLR_RH_PORTSTAT(USBPORTSC_OCC); CLR_RH_PORTSTAT(USBPORTSC_OCC);
OK(0); break;
case USB_PORT_FEAT_C_RESET: case USB_PORT_FEAT_C_RESET:
/* this driver won't report these */ /* this driver won't report these */
OK(0); break;
default: default:
goto err; goto err;
} }
break; break;
case GetHubDescriptor: case GetHubDescriptor:
len = min_t(unsigned int, sizeof(root_hub_hub_des), wLength); retval = min_t(unsigned int, sizeof(root_hub_hub_des), wLength);
memcpy(buf, root_hub_hub_des, len); memcpy(buf, root_hub_hub_des, retval);
if (len > 2) if (retval > 2)
buf[2] = uhci->rh_numports; buf[2] = uhci->rh_numports;
OK(len); break;
default: default:
err: err:
retval = -EPIPE; retval = -EPIPE;
......
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