diff options
author | Deng-Cheng Zhu <dengcheng.zhu@imgtec.com> | 2013-10-06 02:08:17 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-10-07 03:07:17 -0400 |
commit | 5a3e2055c56c7c32b51d47bde78c7f7508ffea98 (patch) | |
tree | 5bf3a633e6d37f2aa694277276442b6dc604201e /drivers/usb/host | |
parent | cae9160d9b074a75c5ae4b08a8552155b1607b9b (diff) |
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>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/uhci-hub.c | 40 |
1 files changed, 20 insertions, 20 deletions
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 9189bc984c98..93e17b12fb33 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
@@ -75,8 +75,6 @@ static inline int get_hub_status_data(struct uhci_hcd *uhci, char *buf) | |||
75 | return !!*buf; | 75 | return !!*buf; |
76 | } | 76 | } |
77 | 77 | ||
78 | #define OK(x) len = (x); break | ||
79 | |||
80 | #define CLR_RH_PORTSTAT(x) \ | 78 | #define CLR_RH_PORTSTAT(x) \ |
81 | status = uhci_readw(uhci, port_addr); \ | 79 | status = uhci_readw(uhci, port_addr); \ |
82 | status &= ~(RWC_BITS|WZ_BITS); \ | 80 | status &= ~(RWC_BITS|WZ_BITS); \ |
@@ -244,7 +242,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
244 | u16 wIndex, char *buf, u16 wLength) | 242 | u16 wIndex, char *buf, u16 wLength) |
245 | { | 243 | { |
246 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 244 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
247 | int status, lstatus, retval = 0, len = 0; | 245 | int status, lstatus, retval = 0; |
248 | unsigned int port = wIndex - 1; | 246 | unsigned int port = wIndex - 1; |
249 | unsigned long port_addr = USBPORTSC1 + 2 * port; | 247 | unsigned long port_addr = USBPORTSC1 + 2 * port; |
250 | u16 wPortChange, wPortStatus; | 248 | u16 wPortChange, wPortStatus; |
@@ -258,7 +256,8 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
258 | 256 | ||
259 | case GetHubStatus: | 257 | case GetHubStatus: |
260 | *(__le32 *)buf = cpu_to_le32(0); | 258 | *(__le32 *)buf = cpu_to_le32(0); |
261 | OK(4); /* hub power */ | 259 | retval = 4; /* hub power */ |
260 | break; | ||
262 | case GetPortStatus: | 261 | case GetPortStatus: |
263 | if (port >= uhci->rh_numports) | 262 | if (port >= uhci->rh_numports) |
264 | goto err; | 263 | goto err; |
@@ -311,13 +310,14 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
311 | 310 | ||
312 | *(__le16 *)buf = cpu_to_le16(wPortStatus); | 311 | *(__le16 *)buf = cpu_to_le16(wPortStatus); |
313 | *(__le16 *)(buf + 2) = cpu_to_le16(wPortChange); | 312 | *(__le16 *)(buf + 2) = cpu_to_le16(wPortChange); |
314 | OK(4); | 313 | retval = 4; |
314 | break; | ||
315 | case SetHubFeature: /* We don't implement these */ | 315 | case SetHubFeature: /* We don't implement these */ |
316 | case ClearHubFeature: | 316 | case ClearHubFeature: |
317 | switch (wValue) { | 317 | switch (wValue) { |
318 | case C_HUB_OVER_CURRENT: | 318 | case C_HUB_OVER_CURRENT: |
319 | case C_HUB_LOCAL_POWER: | 319 | case C_HUB_LOCAL_POWER: |
320 | OK(0); | 320 | break; |
321 | default: | 321 | default: |
322 | goto err; | 322 | goto err; |
323 | } | 323 | } |
@@ -329,7 +329,7 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
329 | switch (wValue) { | 329 | switch (wValue) { |
330 | case USB_PORT_FEAT_SUSPEND: | 330 | case USB_PORT_FEAT_SUSPEND: |
331 | SET_RH_PORTSTAT(USBPORTSC_SUSP); | 331 | SET_RH_PORTSTAT(USBPORTSC_SUSP); |
332 | OK(0); | 332 | break; |
333 | case USB_PORT_FEAT_RESET: | 333 | case USB_PORT_FEAT_RESET: |
334 | SET_RH_PORTSTAT(USBPORTSC_PR); | 334 | SET_RH_PORTSTAT(USBPORTSC_PR); |
335 | 335 | ||
@@ -338,10 +338,10 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
338 | 338 | ||
339 | /* USB v2.0 7.1.7.5 */ | 339 | /* USB v2.0 7.1.7.5 */ |
340 | uhci->ports_timeout = jiffies + msecs_to_jiffies(50); | 340 | uhci->ports_timeout = jiffies + msecs_to_jiffies(50); |
341 | OK(0); | 341 | break; |
342 | case USB_PORT_FEAT_POWER: | 342 | case USB_PORT_FEAT_POWER: |
343 | /* UHCI has no power switching */ | 343 | /* UHCI has no power switching */ |
344 | OK(0); | 344 | break; |
345 | default: | 345 | default: |
346 | goto err; | 346 | goto err; |
347 | } | 347 | } |
@@ -356,10 +356,10 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
356 | 356 | ||
357 | /* Disable terminates Resume signalling */ | 357 | /* Disable terminates Resume signalling */ |
358 | uhci_finish_suspend(uhci, port, port_addr); | 358 | uhci_finish_suspend(uhci, port, port_addr); |
359 | OK(0); | 359 | break; |
360 | case USB_PORT_FEAT_C_ENABLE: | 360 | case USB_PORT_FEAT_C_ENABLE: |
361 | CLR_RH_PORTSTAT(USBPORTSC_PEC); | 361 | CLR_RH_PORTSTAT(USBPORTSC_PEC); |
362 | OK(0); | 362 | break; |
363 | case USB_PORT_FEAT_SUSPEND: | 363 | case USB_PORT_FEAT_SUSPEND: |
364 | if (!(uhci_readw(uhci, port_addr) & USBPORTSC_SUSP)) { | 364 | if (!(uhci_readw(uhci, port_addr) & USBPORTSC_SUSP)) { |
365 | 365 | ||
@@ -382,32 +382,32 @@ static int uhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
382 | uhci->ports_timeout = jiffies + | 382 | uhci->ports_timeout = jiffies + |
383 | msecs_to_jiffies(20); | 383 | msecs_to_jiffies(20); |
384 | } | 384 | } |
385 | OK(0); | 385 | break; |
386 | case USB_PORT_FEAT_C_SUSPEND: | 386 | case USB_PORT_FEAT_C_SUSPEND: |
387 | clear_bit(port, &uhci->port_c_suspend); | 387 | clear_bit(port, &uhci->port_c_suspend); |
388 | OK(0); | 388 | break; |
389 | case USB_PORT_FEAT_POWER: | 389 | case USB_PORT_FEAT_POWER: |
390 | /* UHCI has no power switching */ | 390 | /* UHCI has no power switching */ |
391 | goto err; | 391 | goto err; |
392 | case USB_PORT_FEAT_C_CONNECTION: | 392 | case USB_PORT_FEAT_C_CONNECTION: |
393 | CLR_RH_PORTSTAT(USBPORTSC_CSC); | 393 | CLR_RH_PORTSTAT(USBPORTSC_CSC); |
394 | OK(0); | 394 | break; |
395 | case USB_PORT_FEAT_C_OVER_CURRENT: | 395 | case USB_PORT_FEAT_C_OVER_CURRENT: |
396 | CLR_RH_PORTSTAT(USBPORTSC_OCC); | 396 | CLR_RH_PORTSTAT(USBPORTSC_OCC); |
397 | OK(0); | 397 | break; |
398 | case USB_PORT_FEAT_C_RESET: | 398 | case USB_PORT_FEAT_C_RESET: |
399 | /* this driver won't report these */ | 399 | /* this driver won't report these */ |
400 | OK(0); | 400 | break; |
401 | default: | 401 | default: |
402 | goto err; | 402 | goto err; |
403 | } | 403 | } |
404 | break; | 404 | break; |
405 | case GetHubDescriptor: | 405 | case GetHubDescriptor: |
406 | len = min_t(unsigned int, sizeof(root_hub_hub_des), wLength); | 406 | retval = min_t(unsigned int, sizeof(root_hub_hub_des), wLength); |
407 | memcpy(buf, root_hub_hub_des, len); | 407 | memcpy(buf, root_hub_hub_des, retval); |
408 | if (len > 2) | 408 | if (retval > 2) |
409 | buf[2] = uhci->rh_numports; | 409 | buf[2] = uhci->rh_numports; |
410 | OK(len); | 410 | break; |
411 | default: | 411 | default: |
412 | err: | 412 | err: |
413 | retval = -EPIPE; | 413 | retval = -EPIPE; |