Loading Documentation/usb/URB.txt +31 −43 Original line number Diff line number Diff line Revised: 2000-Dec-05. Again: 2002-Jul-06 Again: 2005-Sep-19 NOTE: Loading @@ -18,8 +19,8 @@ called USB Request Block, or URB for short. and deliver the data and status back. - Execution of an URB is inherently an asynchronous operation, i.e. the usb_submit_urb(urb) call returns immediately after it has successfully queued the requested action. usb_submit_urb(urb) call returns immediately after it has successfully queued the requested action. - Transfers for one URB can be canceled with usb_unlink_urb(urb) at any time. Loading Loading @@ -94,8 +95,9 @@ To free an URB, use void usb_free_urb(struct urb *urb) You may not free an urb that you've submitted, but which hasn't yet been returned to you in a completion callback. You may free an urb that you've submitted, but which hasn't yet been returned to you in a completion callback. It will automatically be deallocated when it is no longer in use. 1.4. What has to be filled in? Loading Loading @@ -145,30 +147,36 @@ to get seamless ISO streaming. 1.6. How to cancel an already running URB? For an URB which you've submitted, but which hasn't been returned to your driver by the host controller, call There are two ways to cancel an URB you've submitted but which hasn't been returned to your driver yet. For an asynchronous cancel, call int usb_unlink_urb(struct urb *urb) It removes the urb from the internal list and frees all allocated HW descriptors. The status is changed to reflect unlinking. After usb_unlink_urb() returns with that status code, you can free the URB with usb_free_urb(). HW descriptors. The status is changed to reflect unlinking. Note that the URB will not normally have finished when usb_unlink_urb() returns; you must still wait for the completion handler to be called. There is also an asynchronous unlink mode. To use this, set the the URB_ASYNC_UNLINK flag in urb->transfer flags before calling usb_unlink_urb(). When using async unlinking, the URB will not normally be unlinked when usb_unlink_urb() returns. Instead, wait for the completion handler to be called. To cancel an URB synchronously, call void usb_kill_urb(struct urb *urb) It does everything usb_unlink_urb does, and in addition it waits until after the URB has been returned and the completion handler has finished. It also marks the URB as temporarily unusable, so that if the completion handler or anyone else tries to resubmit it they will get a -EPERM error. Thus you can be sure that when usb_kill_urb() returns, the URB is totally idle. 1.7. What about the completion handler? The handler is of the following type: typedef void (*usb_complete_t)(struct urb *); typedef void (*usb_complete_t)(struct urb *, struct pt_regs *) i.e. it gets just the URB that caused the completion call. I.e., it gets the URB that caused the completion call, plus the register values at the time of the corresponding interrupt (if any). In the completion handler, you should have a look at urb->status to detect any USB errors. Since the context parameter is included in the URB, you can pass information to the completion handler. Loading @@ -176,17 +184,11 @@ you can pass information to the completion handler. Note that even when an error (or unlink) is reported, data may have been transferred. That's because USB transfers are packetized; it might take sixteen packets to transfer your 1KByte buffer, and ten of them might have transferred succesfully before the completion is called. have transferred succesfully before the completion was called. NOTE: ***** WARNING ***** Don't use urb->dev field in your completion handler; it's cleared as part of giving urbs back to drivers. (Addressing an issue with ownership of periodic URBs, which was otherwise ambiguous.) Instead, use urb->context to hold all the data your driver needs. NOTE: ***** WARNING ***** Also, NEVER SLEEP IN A COMPLETION HANDLER. These are normally called NEVER SLEEP IN A COMPLETION HANDLER. These are normally called during hardware interrupt processing. If you can, defer substantial work to a tasklet (bottom half) to keep system latencies low. You'll probably need to use spinlocks to protect data structures you manipulate Loading Loading @@ -229,24 +231,10 @@ ISO data with some other event stream. Interrupt transfers, like isochronous transfers, are periodic, and happen in intervals that are powers of two (1, 2, 4 etc) units. Units are frames for full and low speed devices, and microframes for high speed ones. Currently, after you submit one interrupt URB, that urb is owned by the host controller driver until you cancel it with usb_unlink_urb(). You may unlink interrupt urbs in their completion handlers, if you need to. After a transfer completion is called, the URB is automagically resubmitted. THIS BEHAVIOR IS EXPECTED TO BE REMOVED!! Interrupt transfers may only send (or receive) the "maxpacket" value for the given interrupt endpoint; if you need more data, you will need to copy that data out of (or into) another buffer. Similarly, you can't queue interrupt transfers. THESE RESTRICTIONS ARE EXPECTED TO BE REMOVED!! Note that this automagic resubmission model does make it awkward to use interrupt OUT transfers. The portable solution involves unlinking those OUT urbs after the data is transferred, and perhaps submitting a final URB for a short packet. The usb_submit_urb() call modifies urb->interval to the implemented interval value that is less than or equal to the requested interval value. In Linux 2.6, unlike earlier versions, interrupt URBs are not automagically restarted when they complete. They end when the completion handler is called, just like other URBs. If you want an interrupt URB to be restarted, your completion handler must resubmit it. MAINTAINERS +0 −2 Original line number Diff line number Diff line Loading @@ -1063,8 +1063,6 @@ M: wli@holomorphy.com S: Maintained I2C SUBSYSTEM P: Greg Kroah-Hartman M: greg@kroah.com P: Jean Delvare M: khali@linux-fr.org L: lm-sensors@lm-sensors.org Loading arch/ppc/syslib/ppc85xx_setup.c +4 −4 Original line number Diff line number Diff line Loading @@ -184,8 +184,8 @@ mpc85xx_setup_pci1(struct pci_controller *hose) pci->powar1 = 0x80044000 | (__ilog2(MPC85XX_PCI1_UPPER_MEM - MPC85XX_PCI1_LOWER_MEM + 1) - 1); /* Setup outboud IO windows @ MPC85XX_PCI1_IO_BASE */ pci->potar2 = 0x00000000; /* Setup outbound IO windows @ MPC85XX_PCI1_IO_BASE */ pci->potar2 = (MPC85XX_PCI1_LOWER_IO >> 12) & 0x000fffff; pci->potear2 = 0x00000000; pci->powbar2 = (MPC85XX_PCI1_IO_BASE >> 12) & 0x000fffff; /* Enable, IO R/W */ Loading Loading @@ -235,8 +235,8 @@ mpc85xx_setup_pci2(struct pci_controller *hose) pci->powar1 = 0x80044000 | (__ilog2(MPC85XX_PCI2_UPPER_MEM - MPC85XX_PCI2_LOWER_MEM + 1) - 1); /* Setup outboud IO windows @ MPC85XX_PCI2_IO_BASE */ pci->potar2 = 0x00000000; /* Setup outbound IO windows @ MPC85XX_PCI2_IO_BASE */ pci->potar2 = (MPC85XX_PCI2_LOWER_IO >> 12) & 0x000fffff;; pci->potear2 = 0x00000000; pci->powbar2 = (MPC85XX_PCI2_IO_BASE >> 12) & 0x000fffff; /* Enable, IO R/W */ Loading drivers/base/class.c +13 −0 Original line number Diff line number Diff line Loading @@ -669,6 +669,7 @@ void class_device_destroy(struct class *cls, dev_t devt) int class_device_rename(struct class_device *class_dev, char *new_name) { int error = 0; char *old_class_name = NULL, *new_class_name = NULL; class_dev = class_device_get(class_dev); if (!class_dev) Loading @@ -677,12 +678,24 @@ int class_device_rename(struct class_device *class_dev, char *new_name) pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id, new_name); if (class_dev->dev) old_class_name = make_class_name(class_dev); strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); error = kobject_rename(&class_dev->kobj, new_name); if (class_dev->dev) { new_class_name = make_class_name(class_dev); sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, new_class_name); sysfs_remove_link(&class_dev->dev->kobj, old_class_name); } class_device_put(class_dev); kfree(old_class_name); kfree(new_class_name); return error; } Loading drivers/base/dd.c +3 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,9 @@ */ void device_bind_driver(struct device * dev) { if (klist_node_attached(&dev->knode_driver)) return; pr_debug("bound device '%s' to driver '%s'\n", dev->bus_id, dev->driver->name); klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); Loading Loading
Documentation/usb/URB.txt +31 −43 Original line number Diff line number Diff line Revised: 2000-Dec-05. Again: 2002-Jul-06 Again: 2005-Sep-19 NOTE: Loading @@ -18,8 +19,8 @@ called USB Request Block, or URB for short. and deliver the data and status back. - Execution of an URB is inherently an asynchronous operation, i.e. the usb_submit_urb(urb) call returns immediately after it has successfully queued the requested action. usb_submit_urb(urb) call returns immediately after it has successfully queued the requested action. - Transfers for one URB can be canceled with usb_unlink_urb(urb) at any time. Loading Loading @@ -94,8 +95,9 @@ To free an URB, use void usb_free_urb(struct urb *urb) You may not free an urb that you've submitted, but which hasn't yet been returned to you in a completion callback. You may free an urb that you've submitted, but which hasn't yet been returned to you in a completion callback. It will automatically be deallocated when it is no longer in use. 1.4. What has to be filled in? Loading Loading @@ -145,30 +147,36 @@ to get seamless ISO streaming. 1.6. How to cancel an already running URB? For an URB which you've submitted, but which hasn't been returned to your driver by the host controller, call There are two ways to cancel an URB you've submitted but which hasn't been returned to your driver yet. For an asynchronous cancel, call int usb_unlink_urb(struct urb *urb) It removes the urb from the internal list and frees all allocated HW descriptors. The status is changed to reflect unlinking. After usb_unlink_urb() returns with that status code, you can free the URB with usb_free_urb(). HW descriptors. The status is changed to reflect unlinking. Note that the URB will not normally have finished when usb_unlink_urb() returns; you must still wait for the completion handler to be called. There is also an asynchronous unlink mode. To use this, set the the URB_ASYNC_UNLINK flag in urb->transfer flags before calling usb_unlink_urb(). When using async unlinking, the URB will not normally be unlinked when usb_unlink_urb() returns. Instead, wait for the completion handler to be called. To cancel an URB synchronously, call void usb_kill_urb(struct urb *urb) It does everything usb_unlink_urb does, and in addition it waits until after the URB has been returned and the completion handler has finished. It also marks the URB as temporarily unusable, so that if the completion handler or anyone else tries to resubmit it they will get a -EPERM error. Thus you can be sure that when usb_kill_urb() returns, the URB is totally idle. 1.7. What about the completion handler? The handler is of the following type: typedef void (*usb_complete_t)(struct urb *); typedef void (*usb_complete_t)(struct urb *, struct pt_regs *) i.e. it gets just the URB that caused the completion call. I.e., it gets the URB that caused the completion call, plus the register values at the time of the corresponding interrupt (if any). In the completion handler, you should have a look at urb->status to detect any USB errors. Since the context parameter is included in the URB, you can pass information to the completion handler. Loading @@ -176,17 +184,11 @@ you can pass information to the completion handler. Note that even when an error (or unlink) is reported, data may have been transferred. That's because USB transfers are packetized; it might take sixteen packets to transfer your 1KByte buffer, and ten of them might have transferred succesfully before the completion is called. have transferred succesfully before the completion was called. NOTE: ***** WARNING ***** Don't use urb->dev field in your completion handler; it's cleared as part of giving urbs back to drivers. (Addressing an issue with ownership of periodic URBs, which was otherwise ambiguous.) Instead, use urb->context to hold all the data your driver needs. NOTE: ***** WARNING ***** Also, NEVER SLEEP IN A COMPLETION HANDLER. These are normally called NEVER SLEEP IN A COMPLETION HANDLER. These are normally called during hardware interrupt processing. If you can, defer substantial work to a tasklet (bottom half) to keep system latencies low. You'll probably need to use spinlocks to protect data structures you manipulate Loading Loading @@ -229,24 +231,10 @@ ISO data with some other event stream. Interrupt transfers, like isochronous transfers, are periodic, and happen in intervals that are powers of two (1, 2, 4 etc) units. Units are frames for full and low speed devices, and microframes for high speed ones. Currently, after you submit one interrupt URB, that urb is owned by the host controller driver until you cancel it with usb_unlink_urb(). You may unlink interrupt urbs in their completion handlers, if you need to. After a transfer completion is called, the URB is automagically resubmitted. THIS BEHAVIOR IS EXPECTED TO BE REMOVED!! Interrupt transfers may only send (or receive) the "maxpacket" value for the given interrupt endpoint; if you need more data, you will need to copy that data out of (or into) another buffer. Similarly, you can't queue interrupt transfers. THESE RESTRICTIONS ARE EXPECTED TO BE REMOVED!! Note that this automagic resubmission model does make it awkward to use interrupt OUT transfers. The portable solution involves unlinking those OUT urbs after the data is transferred, and perhaps submitting a final URB for a short packet. The usb_submit_urb() call modifies urb->interval to the implemented interval value that is less than or equal to the requested interval value. In Linux 2.6, unlike earlier versions, interrupt URBs are not automagically restarted when they complete. They end when the completion handler is called, just like other URBs. If you want an interrupt URB to be restarted, your completion handler must resubmit it.
MAINTAINERS +0 −2 Original line number Diff line number Diff line Loading @@ -1063,8 +1063,6 @@ M: wli@holomorphy.com S: Maintained I2C SUBSYSTEM P: Greg Kroah-Hartman M: greg@kroah.com P: Jean Delvare M: khali@linux-fr.org L: lm-sensors@lm-sensors.org Loading
arch/ppc/syslib/ppc85xx_setup.c +4 −4 Original line number Diff line number Diff line Loading @@ -184,8 +184,8 @@ mpc85xx_setup_pci1(struct pci_controller *hose) pci->powar1 = 0x80044000 | (__ilog2(MPC85XX_PCI1_UPPER_MEM - MPC85XX_PCI1_LOWER_MEM + 1) - 1); /* Setup outboud IO windows @ MPC85XX_PCI1_IO_BASE */ pci->potar2 = 0x00000000; /* Setup outbound IO windows @ MPC85XX_PCI1_IO_BASE */ pci->potar2 = (MPC85XX_PCI1_LOWER_IO >> 12) & 0x000fffff; pci->potear2 = 0x00000000; pci->powbar2 = (MPC85XX_PCI1_IO_BASE >> 12) & 0x000fffff; /* Enable, IO R/W */ Loading Loading @@ -235,8 +235,8 @@ mpc85xx_setup_pci2(struct pci_controller *hose) pci->powar1 = 0x80044000 | (__ilog2(MPC85XX_PCI2_UPPER_MEM - MPC85XX_PCI2_LOWER_MEM + 1) - 1); /* Setup outboud IO windows @ MPC85XX_PCI2_IO_BASE */ pci->potar2 = 0x00000000; /* Setup outbound IO windows @ MPC85XX_PCI2_IO_BASE */ pci->potar2 = (MPC85XX_PCI2_LOWER_IO >> 12) & 0x000fffff;; pci->potear2 = 0x00000000; pci->powbar2 = (MPC85XX_PCI2_IO_BASE >> 12) & 0x000fffff; /* Enable, IO R/W */ Loading
drivers/base/class.c +13 −0 Original line number Diff line number Diff line Loading @@ -669,6 +669,7 @@ void class_device_destroy(struct class *cls, dev_t devt) int class_device_rename(struct class_device *class_dev, char *new_name) { int error = 0; char *old_class_name = NULL, *new_class_name = NULL; class_dev = class_device_get(class_dev); if (!class_dev) Loading @@ -677,12 +678,24 @@ int class_device_rename(struct class_device *class_dev, char *new_name) pr_debug("CLASS: renaming '%s' to '%s'\n", class_dev->class_id, new_name); if (class_dev->dev) old_class_name = make_class_name(class_dev); strlcpy(class_dev->class_id, new_name, KOBJ_NAME_LEN); error = kobject_rename(&class_dev->kobj, new_name); if (class_dev->dev) { new_class_name = make_class_name(class_dev); sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj, new_class_name); sysfs_remove_link(&class_dev->dev->kobj, old_class_name); } class_device_put(class_dev); kfree(old_class_name); kfree(new_class_name); return error; } Loading
drivers/base/dd.c +3 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,9 @@ */ void device_bind_driver(struct device * dev) { if (klist_node_attached(&dev->knode_driver)) return; pr_debug("bound device '%s' to driver '%s'\n", dev->bus_id, dev->driver->name); klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices); Loading