ChangeSet 1.1123.18.3, 2003/08/11 15:12:01-07:00, [EMAIL PROTECTED]
[PATCH] USB: correct error handling in usb_driver_claim_interface()
this function races with itself, doesn't return errors and races with
releasing interfaces. This patch fixes it by changing the function
prototype, introducing locking and having a correct order in
releasing interfaces.
- API change to check errors in usb_driver_claim_interface and
fix a race condition between releasing and reclaiming an interface
drivers/usb/core/usb.c | 27 +++++++++++++++------------
include/linux/usb.h | 2 +-
2 files changed, 16 insertions(+), 13 deletions(-)
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c Fri Aug 15 10:48:26 2003
+++ b/drivers/usb/core/usb.c Fri Aug 15 10:48:26 2003
@@ -261,24 +261,27 @@
*
* Few drivers should need to use this routine, since the most natural
* way to bind to an interface is to return the private data from
- * the driver's probe() method. Any driver that does use this must
- * first be sure that no other driver has claimed the interface, by
- * checking with usb_interface_claimed().
+ * the driver's probe() method.
*/
-void usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface
*iface, void* priv)
+int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface
*iface, void* priv)
{
if (!iface || !driver)
- return;
+ return -EINVAL;
- // FIXME change API to report an error in this case
- if (iface->driver)
- err ("%s driver booted %s off interface %p",
- driver->name, iface->driver->name, iface);
- else
+ lock_kernel();
+ if (iface->driver) {
+ unlock_kernel();
+ err ("%s driver booted %s off interface %p",
+ driver->name, iface->driver->name, iface);
+ return -EBUSY;
+ } else {
dbg("%s driver claimed interface %p", driver->name, iface);
+ }
iface->driver = driver;
usb_set_intfdata(iface, priv);
+ unlock_kernel();
+ return 0;
}
/**
@@ -324,11 +327,11 @@
if (iface->driver && iface->driver != driver)
return;
- iface->driver = NULL;
- usb_set_intfdata(iface, NULL);
usb_set_interface(interface_to_usbdev(iface),
iface->altsetting[0].desc.bInterfaceNumber,
0);
+ usb_set_intfdata(iface, NULL);
+ iface->driver = NULL;
}
/**
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h Fri Aug 15 10:48:26 2003
+++ b/include/linux/usb.h Fri Aug 15 10:48:26 2003
@@ -290,7 +290,7 @@
extern int usb_get_current_frame_number (struct usb_device *usb_dev);
/* used these for multi-interface device registration */
-extern void usb_driver_claim_interface(struct usb_driver *driver,
+extern int usb_driver_claim_interface(struct usb_driver *driver,
struct usb_interface *iface, void* priv);
extern int usb_interface_claimed(struct usb_interface *iface);
extern void usb_driver_release_interface(struct usb_driver *driver,
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel