aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorInaky Perez-Gonzalez <inaky@linux.intel.com>2008-11-13 13:31:35 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-01-07 12:59:53 -0500
commitdc023dceec861c60bc1d1a17a2c6496ddac26ee7 (patch)
tree908529b3eb975acb2582f679d20a81bfadc95bf4 /drivers
parent9ac39f28b5237a629e41ccfc1f73d3a55723045c (diff)
USB: Introduce usb_queue_reset() to do resets from atomic contexts
This patch introduces a new call to be able to do a USB reset from an atomic contect. This is quite helpful in USB callbacks to handle errors (when the only thing that can be done is to do a device reset). It is done queuing a work struct that will do the actual reset. The struct is "attached" to an interface so pending requests from an interface are removed when said interface is unbound from the driver. The call flow then becomes: usb_queue_reset_device() __usb_queue_reset_device() [workqueue] usb_reset_device() usb_probe_interface() usb_cancel_queue_reset() [error path] usb_unbind_interface() usb_cancel_queue_reset() usb_driver_release_interface() usb_cancel_queue_reset() Note usb_cancel_queue_reset() needs smarts to try not to unqueue when it is actually being executed. This happens when we run the reset from the workqueue: usb_reset_device() is called and on interface unbind time, usb_cancel_queue_reset() would be called. That would deadlock on cancel_work_sync(). To avoid that, we set (before running usb_reset_device()) usb_intf->reset_running and clear it inmediately after returning. Patch is against 2.6.28-rc2 and depends on http://marc.info/?l=linux-usb&m=122581634925308&w=2 (as submitted by Alan Stern). Signed-off-by: Inaky Perez-Gonzalez <inaky@linux.intel.com> Cc: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/core/driver.c23
-rw-r--r--drivers/usb/core/hub.c43
-rw-r--r--drivers/usb/core/message.c41
3 files changed, 105 insertions, 2 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 23b3c7e79d4b..7e26fb3c2759 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -184,6 +184,20 @@ static int usb_unbind_device(struct device *dev)
184 return 0; 184 return 0;
185} 185}
186 186
187/*
188 * Cancel any pending scheduled resets
189 *
190 * [see usb_queue_reset_device()]
191 *
192 * Called after unconfiguring / when releasing interfaces. See
193 * comments in __usb_queue_reset_device() regarding
194 * udev->reset_running.
195 */
196static void usb_cancel_queued_reset(struct usb_interface *iface)
197{
198 if (iface->reset_running == 0)
199 cancel_work_sync(&iface->reset_ws);
200}
187 201
188/* called from driver core with dev locked */ 202/* called from driver core with dev locked */
189static int usb_probe_interface(struct device *dev) 203static int usb_probe_interface(struct device *dev)
@@ -242,6 +256,7 @@ static int usb_probe_interface(struct device *dev)
242 mark_quiesced(intf); 256 mark_quiesced(intf);
243 intf->needs_remote_wakeup = 0; 257 intf->needs_remote_wakeup = 0;
244 intf->condition = USB_INTERFACE_UNBOUND; 258 intf->condition = USB_INTERFACE_UNBOUND;
259 usb_cancel_queued_reset(intf);
245 } else 260 } else
246 intf->condition = USB_INTERFACE_BOUND; 261 intf->condition = USB_INTERFACE_BOUND;
247 262
@@ -272,6 +287,7 @@ static int usb_unbind_interface(struct device *dev)
272 usb_disable_interface(udev, intf); 287 usb_disable_interface(udev, intf);
273 288
274 driver->disconnect(intf); 289 driver->disconnect(intf);
290 usb_cancel_queued_reset(intf);
275 291
276 /* Reset other interface state. 292 /* Reset other interface state.
277 * We cannot do a Set-Interface if the device is suspended or 293 * We cannot do a Set-Interface if the device is suspended or
@@ -380,8 +396,10 @@ void usb_driver_release_interface(struct usb_driver *driver,
380 if (device_is_registered(dev)) { 396 if (device_is_registered(dev)) {
381 iface->condition = USB_INTERFACE_UNBINDING; 397 iface->condition = USB_INTERFACE_UNBINDING;
382 device_release_driver(dev); 398 device_release_driver(dev);
399 } else {
400 iface->condition = USB_INTERFACE_UNBOUND;
401 usb_cancel_queued_reset(iface);
383 } 402 }
384
385 dev->driver = NULL; 403 dev->driver = NULL;
386 usb_set_intfdata(iface, NULL); 404 usb_set_intfdata(iface, NULL);
387 405
@@ -942,7 +960,8 @@ static int usb_suspend_interface(struct usb_device *udev,
942 if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf)) 960 if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf))
943 goto done; 961 goto done;
944 962
945 if (intf->condition == USB_INTERFACE_UNBOUND) /* This can't happen */ 963 /* This can happen; see usb_driver_release_interface() */
964 if (intf->condition == USB_INTERFACE_UNBOUND)
946 goto done; 965 goto done;
947 driver = to_usb_driver(intf->dev.driver); 966 driver = to_usb_driver(intf->dev.driver);
948 967
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 95fb3104ba4f..e65881899c8f 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3518,3 +3518,46 @@ int usb_reset_device(struct usb_device *udev)
3518 return ret; 3518 return ret;
3519} 3519}
3520EXPORT_SYMBOL_GPL(usb_reset_device); 3520EXPORT_SYMBOL_GPL(usb_reset_device);
3521
3522
3523/**
3524 * usb_queue_reset_device - Reset a USB device from an atomic context
3525 * @iface: USB interface belonging to the device to reset
3526 *
3527 * This function can be used to reset a USB device from an atomic
3528 * context, where usb_reset_device() won't work (as it blocks).
3529 *
3530 * Doing a reset via this method is functionally equivalent to calling
3531 * usb_reset_device(), except for the fact that it is delayed to a
3532 * workqueue. This means that any drivers bound to other interfaces
3533 * might be unbound, as well as users from usbfs in user space.
3534 *
3535 * Corner cases:
3536 *
3537 * - Scheduling two resets at the same time from two different drivers
3538 * attached to two different interfaces of the same device is
3539 * possible; depending on how the driver attached to each interface
3540 * handles ->pre_reset(), the second reset might happen or not.
3541 *
3542 * - If a driver is unbound and it had a pending reset, the reset will
3543 * be cancelled.
3544 *
3545 * - This function can be called during .probe() or .disconnect()
3546 * times. On return from .disconnect(), any pending resets will be
3547 * cancelled.
3548 *
3549 * There is no no need to lock/unlock the @reset_ws as schedule_work()
3550 * does its own.
3551 *
3552 * NOTE: We don't do any reference count tracking because it is not
3553 * needed. The lifecycle of the work_struct is tied to the
3554 * usb_interface. Before destroying the interface we cancel the
3555 * work_struct, so the fact that work_struct is queued and or
3556 * running means the interface (and thus, the device) exist and
3557 * are referenced.
3558 */
3559void usb_queue_reset_device(struct usb_interface *iface)
3560{
3561 schedule_work(&iface->reset_ws);
3562}
3563EXPORT_SYMBOL_GPL(usb_queue_reset_device);
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index cc47d36798b1..aadf29f09c45 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1441,6 +1441,46 @@ static struct usb_interface_assoc_descriptor *find_iad(struct usb_device *dev,
1441 return retval; 1441 return retval;
1442} 1442}
1443 1443
1444
1445/*
1446 * Internal function to queue a device reset
1447 *
1448 * This is initialized into the workstruct in 'struct
1449 * usb_device->reset_ws' that is launched by
1450 * message.c:usb_set_configuration() when initializing each 'struct
1451 * usb_interface'.
1452 *
1453 * It is safe to get the USB device without reference counts because
1454 * the life cycle of @iface is bound to the life cycle of @udev. Then,
1455 * this function will be ran only if @iface is alive (and before
1456 * freeing it any scheduled instances of it will have been cancelled).
1457 *
1458 * We need to set a flag (usb_dev->reset_running) because when we call
1459 * the reset, the interfaces might be unbound. The current interface
1460 * cannot try to remove the queued work as it would cause a deadlock
1461 * (you cannot remove your work from within your executing
1462 * workqueue). This flag lets it know, so that
1463 * usb_cancel_queued_reset() doesn't try to do it.
1464 *
1465 * See usb_queue_reset_device() for more details
1466 */
1467void __usb_queue_reset_device(struct work_struct *ws)
1468{
1469 int rc;
1470 struct usb_interface *iface =
1471 container_of(ws, struct usb_interface, reset_ws);
1472 struct usb_device *udev = interface_to_usbdev(iface);
1473
1474 rc = usb_lock_device_for_reset(udev, iface);
1475 if (rc >= 0) {
1476 iface->reset_running = 1;
1477 usb_reset_device(udev);
1478 iface->reset_running = 0;
1479 usb_unlock_device(udev);
1480 }
1481}
1482
1483
1444/* 1484/*
1445 * usb_set_configuration - Makes a particular device setting be current 1485 * usb_set_configuration - Makes a particular device setting be current
1446 * @dev: the device whose configuration is being updated 1486 * @dev: the device whose configuration is being updated
@@ -1611,6 +1651,7 @@ free_interfaces:
1611 intf->dev.type = &usb_if_device_type; 1651 intf->dev.type = &usb_if_device_type;
1612 intf->dev.groups = usb_interface_groups; 1652 intf->dev.groups = usb_interface_groups;
1613 intf->dev.dma_mask = dev->dev.dma_mask; 1653 intf->dev.dma_mask = dev->dev.dma_mask;
1654 INIT_WORK(&intf->reset_ws, __usb_queue_reset_device);
1614 device_initialize(&intf->dev); 1655 device_initialize(&intf->dev);
1615 mark_quiesced(intf); 1656 mark_quiesced(intf);
1616 dev_set_name(&intf->dev, "%d-%s:%d.%d", 1657 dev_set_name(&intf->dev, "%d-%s:%d.%d",