diff options
-rw-r--r-- | drivers/usb/core/hcd.c | 13 | ||||
-rw-r--r-- | drivers/usb/core/urb.c | 65 | ||||
-rw-r--r-- | include/linux/usb.h | 26 |
3 files changed, 65 insertions, 39 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 42ef1d5f6c8a..fb82c500caf4 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -962,14 +962,14 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) | |||
962 | spin_lock_irqsave(&hcd_urb_list_lock, flags); | 962 | spin_lock_irqsave(&hcd_urb_list_lock, flags); |
963 | ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out) | 963 | ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out) |
964 | [usb_pipeendpoint(urb->pipe)]; | 964 | [usb_pipeendpoint(urb->pipe)]; |
965 | if (unlikely (!ep)) | 965 | if (unlikely(ep != urb->ep)) |
966 | status = -ENOENT; | 966 | status = -ENOENT; |
967 | else if (unlikely (urb->reject)) | 967 | else if (unlikely (urb->reject)) |
968 | status = -EPERM; | 968 | status = -EPERM; |
969 | else switch (hcd->state) { | 969 | else switch (hcd->state) { |
970 | case HC_STATE_RUNNING: | 970 | case HC_STATE_RUNNING: |
971 | case HC_STATE_RESUMING: | 971 | case HC_STATE_RESUMING: |
972 | list_add_tail (&urb->urb_list, &ep->urb_list); | 972 | list_add_tail (&urb->urb_list, &urb->ep->urb_list); |
973 | status = 0; | 973 | status = 0; |
974 | break; | 974 | break; |
975 | default: | 975 | default: |
@@ -1022,7 +1022,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags) | |||
1022 | : DMA_TO_DEVICE); | 1022 | : DMA_TO_DEVICE); |
1023 | } | 1023 | } |
1024 | 1024 | ||
1025 | status = hcd->driver->urb_enqueue (hcd, ep, urb, mem_flags); | 1025 | status = hcd->driver->urb_enqueue (hcd, urb->ep, urb, mem_flags); |
1026 | done: | 1026 | done: |
1027 | if (unlikely (status)) { | 1027 | if (unlikely (status)) { |
1028 | urb_unlink(hcd, urb); | 1028 | urb_unlink(hcd, urb); |
@@ -1071,7 +1071,6 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb) | |||
1071 | */ | 1071 | */ |
1072 | int usb_hcd_unlink_urb (struct urb *urb, int status) | 1072 | int usb_hcd_unlink_urb (struct urb *urb, int status) |
1073 | { | 1073 | { |
1074 | struct usb_host_endpoint *ep; | ||
1075 | struct usb_hcd *hcd = NULL; | 1074 | struct usb_hcd *hcd = NULL; |
1076 | struct device *sys = NULL; | 1075 | struct device *sys = NULL; |
1077 | unsigned long flags; | 1076 | unsigned long flags; |
@@ -1082,10 +1081,6 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) | |||
1082 | return -EINVAL; | 1081 | return -EINVAL; |
1083 | if (!urb->dev || !urb->dev->bus) | 1082 | if (!urb->dev || !urb->dev->bus) |
1084 | return -ENODEV; | 1083 | return -ENODEV; |
1085 | ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out) | ||
1086 | [usb_pipeendpoint(urb->pipe)]; | ||
1087 | if (!ep) | ||
1088 | return -ENODEV; | ||
1089 | 1084 | ||
1090 | /* | 1085 | /* |
1091 | * we contend for urb->status with the hcd core, | 1086 | * we contend for urb->status with the hcd core, |
@@ -1109,7 +1104,7 @@ int usb_hcd_unlink_urb (struct urb *urb, int status) | |||
1109 | } | 1104 | } |
1110 | 1105 | ||
1111 | /* insist the urb is still queued */ | 1106 | /* insist the urb is still queued */ |
1112 | list_for_each(tmp, &ep->urb_list) { | 1107 | list_for_each(tmp, &urb->ep->urb_list) { |
1113 | if (tmp == &urb->urb_list) | 1108 | if (tmp == &urb->urb_list) |
1114 | break; | 1109 | break; |
1115 | } | 1110 | } |
diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index be630228461c..ff53acb4fab2 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c | |||
@@ -277,9 +277,10 @@ EXPORT_SYMBOL_GPL(usb_unanchor_urb); | |||
277 | */ | 277 | */ |
278 | int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | 278 | int usb_submit_urb(struct urb *urb, gfp_t mem_flags) |
279 | { | 279 | { |
280 | int pipe, temp, max; | 280 | int xfertype, max; |
281 | struct usb_device *dev; | 281 | struct usb_device *dev; |
282 | int is_out; | 282 | struct usb_host_endpoint *ep; |
283 | int is_out; | ||
283 | 284 | ||
284 | if (!urb || urb->hcpriv || !urb->complete) | 285 | if (!urb || urb->hcpriv || !urb->complete) |
285 | return -EINVAL; | 286 | return -EINVAL; |
@@ -291,30 +292,34 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
291 | || dev->state == USB_STATE_SUSPENDED) | 292 | || dev->state == USB_STATE_SUSPENDED) |
292 | return -EHOSTUNREACH; | 293 | return -EHOSTUNREACH; |
293 | 294 | ||
295 | /* For now, get the endpoint from the pipe. Eventually drivers | ||
296 | * will be required to set urb->ep directly and we will eliminate | ||
297 | * urb->pipe. | ||
298 | */ | ||
299 | ep = (usb_pipein(urb->pipe) ? dev->ep_in : dev->ep_out) | ||
300 | [usb_pipeendpoint(urb->pipe)]; | ||
301 | if (!ep) | ||
302 | return -ENOENT; | ||
303 | |||
304 | urb->ep = ep; | ||
294 | urb->status = -EINPROGRESS; | 305 | urb->status = -EINPROGRESS; |
295 | urb->actual_length = 0; | 306 | urb->actual_length = 0; |
296 | 307 | ||
297 | /* Lots of sanity checks, so HCDs can rely on clean data | 308 | /* Lots of sanity checks, so HCDs can rely on clean data |
298 | * and don't need to duplicate tests | 309 | * and don't need to duplicate tests |
299 | */ | 310 | */ |
300 | pipe = urb->pipe; | 311 | xfertype = usb_endpoint_type(&ep->desc); |
301 | temp = usb_pipetype(pipe); | 312 | is_out = usb_pipeout(urb->pipe); |
302 | is_out = usb_pipeout(pipe); | ||
303 | 313 | ||
304 | if (!usb_pipecontrol(pipe) && dev->state < USB_STATE_CONFIGURED) | 314 | if (xfertype != USB_ENDPOINT_XFER_CONTROL && |
315 | dev->state < USB_STATE_CONFIGURED) | ||
305 | return -ENODEV; | 316 | return -ENODEV; |
306 | 317 | ||
307 | /* FIXME there should be a sharable lock protecting us against | 318 | max = le16_to_cpu(ep->desc.wMaxPacketSize); |
308 | * config/altsetting changes and disconnects, kicking in here. | ||
309 | * (here == before maxpacket, and eventually endpoint type, | ||
310 | * checks get made.) | ||
311 | */ | ||
312 | |||
313 | max = usb_maxpacket(dev, pipe, is_out); | ||
314 | if (max <= 0) { | 319 | if (max <= 0) { |
315 | dev_dbg(&dev->dev, | 320 | dev_dbg(&dev->dev, |
316 | "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n", | 321 | "bogus endpoint ep%d%s in %s (bad maxpacket %d)\n", |
317 | usb_pipeendpoint(pipe), is_out ? "out" : "in", | 322 | usb_endpoint_num(&ep->desc), is_out ? "out" : "in", |
318 | __FUNCTION__, max); | 323 | __FUNCTION__, max); |
319 | return -EMSGSIZE; | 324 | return -EMSGSIZE; |
320 | } | 325 | } |
@@ -323,7 +328,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
323 | * but drivers only control those sizes for ISO. | 328 | * but drivers only control those sizes for ISO. |
324 | * while we're checking, initialize return status. | 329 | * while we're checking, initialize return status. |
325 | */ | 330 | */ |
326 | if (temp == PIPE_ISOCHRONOUS) { | 331 | if (xfertype == USB_ENDPOINT_XFER_ISOC) { |
327 | int n, len; | 332 | int n, len; |
328 | 333 | ||
329 | /* "high bandwidth" mode, 1-3 packets/uframe? */ | 334 | /* "high bandwidth" mode, 1-3 packets/uframe? */ |
@@ -359,19 +364,19 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
359 | /* enforce simple/standard policy */ | 364 | /* enforce simple/standard policy */ |
360 | allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | | 365 | allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP | |
361 | URB_NO_INTERRUPT); | 366 | URB_NO_INTERRUPT); |
362 | switch (temp) { | 367 | switch (xfertype) { |
363 | case PIPE_BULK: | 368 | case USB_ENDPOINT_XFER_BULK: |
364 | if (is_out) | 369 | if (is_out) |
365 | allowed |= URB_ZERO_PACKET; | 370 | allowed |= URB_ZERO_PACKET; |
366 | /* FALLTHROUGH */ | 371 | /* FALLTHROUGH */ |
367 | case PIPE_CONTROL: | 372 | case USB_ENDPOINT_XFER_CONTROL: |
368 | allowed |= URB_NO_FSBR; /* only affects UHCI */ | 373 | allowed |= URB_NO_FSBR; /* only affects UHCI */ |
369 | /* FALLTHROUGH */ | 374 | /* FALLTHROUGH */ |
370 | default: /* all non-iso endpoints */ | 375 | default: /* all non-iso endpoints */ |
371 | if (!is_out) | 376 | if (!is_out) |
372 | allowed |= URB_SHORT_NOT_OK; | 377 | allowed |= URB_SHORT_NOT_OK; |
373 | break; | 378 | break; |
374 | case PIPE_ISOCHRONOUS: | 379 | case USB_ENDPOINT_XFER_ISOC: |
375 | allowed |= URB_ISO_ASAP; | 380 | allowed |= URB_ISO_ASAP; |
376 | break; | 381 | break; |
377 | } | 382 | } |
@@ -393,9 +398,9 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
393 | * supports different values... this uses EHCI/UHCI defaults (and | 398 | * supports different values... this uses EHCI/UHCI defaults (and |
394 | * EHCI can use smaller non-default values). | 399 | * EHCI can use smaller non-default values). |
395 | */ | 400 | */ |
396 | switch (temp) { | 401 | switch (xfertype) { |
397 | case PIPE_ISOCHRONOUS: | 402 | case USB_ENDPOINT_XFER_ISOC: |
398 | case PIPE_INTERRUPT: | 403 | case USB_ENDPOINT_XFER_INT: |
399 | /* too small? */ | 404 | /* too small? */ |
400 | if (urb->interval <= 0) | 405 | if (urb->interval <= 0) |
401 | return -EINVAL; | 406 | return -EINVAL; |
@@ -405,29 +410,29 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) | |||
405 | // NOTE usb handles 2^15 | 410 | // NOTE usb handles 2^15 |
406 | if (urb->interval > (1024 * 8)) | 411 | if (urb->interval > (1024 * 8)) |
407 | urb->interval = 1024 * 8; | 412 | urb->interval = 1024 * 8; |
408 | temp = 1024 * 8; | 413 | max = 1024 * 8; |
409 | break; | 414 | break; |
410 | case USB_SPEED_FULL: /* units are frames/msec */ | 415 | case USB_SPEED_FULL: /* units are frames/msec */ |
411 | case USB_SPEED_LOW: | 416 | case USB_SPEED_LOW: |
412 | if (temp == PIPE_INTERRUPT) { | 417 | if (xfertype == USB_ENDPOINT_XFER_INT) { |
413 | if (urb->interval > 255) | 418 | if (urb->interval > 255) |
414 | return -EINVAL; | 419 | return -EINVAL; |
415 | // NOTE ohci only handles up to 32 | 420 | // NOTE ohci only handles up to 32 |
416 | temp = 128; | 421 | max = 128; |
417 | } else { | 422 | } else { |
418 | if (urb->interval > 1024) | 423 | if (urb->interval > 1024) |
419 | urb->interval = 1024; | 424 | urb->interval = 1024; |
420 | // NOTE usb and ohci handle up to 2^15 | 425 | // NOTE usb and ohci handle up to 2^15 |
421 | temp = 1024; | 426 | max = 1024; |
422 | } | 427 | } |
423 | break; | 428 | break; |
424 | default: | 429 | default: |
425 | return -EINVAL; | 430 | return -EINVAL; |
426 | } | 431 | } |
427 | /* power of two? */ | 432 | /* power of two? */ |
428 | while (temp > urb->interval) | 433 | while (max > urb->interval) |
429 | temp >>= 1; | 434 | max >>= 1; |
430 | urb->interval = temp; | 435 | urb->interval = max; |
431 | } | 436 | } |
432 | 437 | ||
433 | return usb_hcd_submit_urb(urb, mem_flags); | 438 | return usb_hcd_submit_urb(urb, mem_flags); |
diff --git a/include/linux/usb.h b/include/linux/usb.h index 4f33a58fa9d1..105e3e9362d0 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h | |||
@@ -555,6 +555,29 @@ static inline int usb_make_path (struct usb_device *dev, char *buf, | |||
555 | /*-------------------------------------------------------------------------*/ | 555 | /*-------------------------------------------------------------------------*/ |
556 | 556 | ||
557 | /** | 557 | /** |
558 | * usb_endpoint_num - get the endpoint's number | ||
559 | * @epd: endpoint to be checked | ||
560 | * | ||
561 | * Returns @epd's number: 0 to 15. | ||
562 | */ | ||
563 | static inline int usb_endpoint_num(const struct usb_endpoint_descriptor *epd) | ||
564 | { | ||
565 | return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; | ||
566 | } | ||
567 | |||
568 | /** | ||
569 | * usb_endpoint_type - get the endpoint's transfer type | ||
570 | * @epd: endpoint to be checked | ||
571 | * | ||
572 | * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according | ||
573 | * to @epd's transfer type. | ||
574 | */ | ||
575 | static inline int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) | ||
576 | { | ||
577 | return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; | ||
578 | } | ||
579 | |||
580 | /** | ||
558 | * usb_endpoint_dir_in - check if the endpoint has IN direction | 581 | * usb_endpoint_dir_in - check if the endpoint has IN direction |
559 | * @epd: endpoint to be checked | 582 | * @epd: endpoint to be checked |
560 | * | 583 | * |
@@ -1037,6 +1060,8 @@ typedef void (*usb_complete_t)(struct urb *); | |||
1037 | * @urb_list: For use by current owner of the URB. | 1060 | * @urb_list: For use by current owner of the URB. |
1038 | * @anchor_list: membership in the list of an anchor | 1061 | * @anchor_list: membership in the list of an anchor |
1039 | * @anchor: to anchor URBs to a common mooring | 1062 | * @anchor: to anchor URBs to a common mooring |
1063 | * @ep: Points to the endpoint's data structure. Will eventually | ||
1064 | * replace @pipe. | ||
1040 | * @pipe: Holds endpoint number, direction, type, and more. | 1065 | * @pipe: Holds endpoint number, direction, type, and more. |
1041 | * Create these values with the eight macros available; | 1066 | * Create these values with the eight macros available; |
1042 | * usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl" | 1067 | * usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl" |
@@ -1212,6 +1237,7 @@ struct urb | |||
1212 | struct list_head anchor_list; /* the URB may be anchored by the driver */ | 1237 | struct list_head anchor_list; /* the URB may be anchored by the driver */ |
1213 | struct usb_anchor *anchor; | 1238 | struct usb_anchor *anchor; |
1214 | struct usb_device *dev; /* (in) pointer to associated device */ | 1239 | struct usb_device *dev; /* (in) pointer to associated device */ |
1240 | struct usb_host_endpoint *ep; /* (internal) pointer to endpoint struct */ | ||
1215 | unsigned int pipe; /* (in) pipe information */ | 1241 | unsigned int pipe; /* (in) pipe information */ |
1216 | int status; /* (return) non-ISO status */ | 1242 | int status; /* (return) non-ISO status */ |
1217 | unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ | 1243 | unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/ |