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: James Hogan <james.hogan@imgtec.com> Signed-off-by: Deng-Cheng Zhu <dengcheng.zhu@imgtec.com> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
cae9160d9b
commit
5a3e2055c5
@ -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,
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
*(__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,
|
|||||||
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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
|
|
||||||
/* 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,
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user