aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/driver.c')
-rw-r--r--drivers/usb/core/driver.c75
1 files changed, 47 insertions, 28 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 69e5773abfce..4f864472c5c4 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -207,6 +207,9 @@ static int usb_probe_interface(struct device *dev)
207 207
208 intf->needs_binding = 0; 208 intf->needs_binding = 0;
209 209
210 if (usb_device_is_owned(udev))
211 return -ENODEV;
212
210 if (udev->authorized == 0) { 213 if (udev->authorized == 0) {
211 dev_err(&intf->dev, "Device is not authorized for usage\n"); 214 dev_err(&intf->dev, "Device is not authorized for usage\n");
212 return -ENODEV; 215 return -ENODEV;
@@ -232,28 +235,35 @@ static int usb_probe_interface(struct device *dev)
232 /* The interface should always appear to be in use 235 /* The interface should always appear to be in use
233 * unless the driver suports autosuspend. 236 * unless the driver suports autosuspend.
234 */ 237 */
235 intf->pm_usage_cnt = !(driver->supports_autosuspend); 238 atomic_set(&intf->pm_usage_cnt, !driver->supports_autosuspend);
236 239
237 /* Carry out a deferred switch to altsetting 0 */ 240 /* Carry out a deferred switch to altsetting 0 */
238 if (intf->needs_altsetting0) { 241 if (intf->needs_altsetting0) {
239 usb_set_interface(udev, intf->altsetting[0]. 242 error = usb_set_interface(udev, intf->altsetting[0].
240 desc.bInterfaceNumber, 0); 243 desc.bInterfaceNumber, 0);
244 if (error < 0)
245 goto err;
246
241 intf->needs_altsetting0 = 0; 247 intf->needs_altsetting0 = 0;
242 } 248 }
243 249
244 error = driver->probe(intf, id); 250 error = driver->probe(intf, id);
245 if (error) { 251 if (error)
246 mark_quiesced(intf); 252 goto err;
247 intf->needs_remote_wakeup = 0;
248 intf->condition = USB_INTERFACE_UNBOUND;
249 usb_cancel_queued_reset(intf);
250 } else
251 intf->condition = USB_INTERFACE_BOUND;
252 253
254 intf->condition = USB_INTERFACE_BOUND;
253 usb_autosuspend_device(udev); 255 usb_autosuspend_device(udev);
254 } 256 }
255 257
256 return error; 258 return error;
259
260err:
261 mark_quiesced(intf);
262 intf->needs_remote_wakeup = 0;
263 intf->condition = USB_INTERFACE_UNBOUND;
264 usb_cancel_queued_reset(intf);
265 usb_autosuspend_device(udev);
266 return error;
257} 267}
258 268
259/* called from driver core with dev locked */ 269/* called from driver core with dev locked */
@@ -262,7 +272,7 @@ static int usb_unbind_interface(struct device *dev)
262 struct usb_driver *driver = to_usb_driver(dev->driver); 272 struct usb_driver *driver = to_usb_driver(dev->driver);
263 struct usb_interface *intf = to_usb_interface(dev); 273 struct usb_interface *intf = to_usb_interface(dev);
264 struct usb_device *udev; 274 struct usb_device *udev;
265 int error; 275 int error, r;
266 276
267 intf->condition = USB_INTERFACE_UNBINDING; 277 intf->condition = USB_INTERFACE_UNBINDING;
268 278
@@ -290,11 +300,14 @@ static int usb_unbind_interface(struct device *dev)
290 * Just re-enable it without affecting the endpoint toggles. 300 * Just re-enable it without affecting the endpoint toggles.
291 */ 301 */
292 usb_enable_interface(udev, intf, false); 302 usb_enable_interface(udev, intf, false);
293 } else if (!error && intf->dev.power.status == DPM_ON) 303 } else if (!error && intf->dev.power.status == DPM_ON) {
294 usb_set_interface(udev, intf->altsetting[0]. 304 r = usb_set_interface(udev, intf->altsetting[0].
295 desc.bInterfaceNumber, 0); 305 desc.bInterfaceNumber, 0);
296 else 306 if (r < 0)
307 intf->needs_altsetting0 = 1;
308 } else {
297 intf->needs_altsetting0 = 1; 309 intf->needs_altsetting0 = 1;
310 }
298 usb_set_intfdata(intf, NULL); 311 usb_set_intfdata(intf, NULL);
299 312
300 intf->condition = USB_INTERFACE_UNBOUND; 313 intf->condition = USB_INTERFACE_UNBOUND;
@@ -344,7 +357,7 @@ int usb_driver_claim_interface(struct usb_driver *driver,
344 usb_pm_lock(udev); 357 usb_pm_lock(udev);
345 iface->condition = USB_INTERFACE_BOUND; 358 iface->condition = USB_INTERFACE_BOUND;
346 mark_active(iface); 359 mark_active(iface);
347 iface->pm_usage_cnt = !(driver->supports_autosuspend); 360 atomic_set(&iface->pm_usage_cnt, !driver->supports_autosuspend);
348 usb_pm_unlock(udev); 361 usb_pm_unlock(udev);
349 362
350 /* if interface was already added, bind now; else let 363 /* if interface was already added, bind now; else let
@@ -1065,7 +1078,7 @@ static int autosuspend_check(struct usb_device *udev, int reschedule)
1065 intf = udev->actconfig->interface[i]; 1078 intf = udev->actconfig->interface[i];
1066 if (!is_active(intf)) 1079 if (!is_active(intf))
1067 continue; 1080 continue;
1068 if (intf->pm_usage_cnt > 0) 1081 if (atomic_read(&intf->pm_usage_cnt) > 0)
1069 return -EBUSY; 1082 return -EBUSY;
1070 if (intf->needs_remote_wakeup && 1083 if (intf->needs_remote_wakeup &&
1071 !udev->do_remote_wakeup) { 1084 !udev->do_remote_wakeup) {
@@ -1461,17 +1474,19 @@ static int usb_autopm_do_interface(struct usb_interface *intf,
1461 status = -ENODEV; 1474 status = -ENODEV;
1462 else { 1475 else {
1463 udev->auto_pm = 1; 1476 udev->auto_pm = 1;
1464 intf->pm_usage_cnt += inc_usage_cnt; 1477 atomic_add(inc_usage_cnt, &intf->pm_usage_cnt);
1465 udev->last_busy = jiffies; 1478 udev->last_busy = jiffies;
1466 if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) { 1479 if (inc_usage_cnt >= 0 &&
1480 atomic_read(&intf->pm_usage_cnt) > 0) {
1467 if (udev->state == USB_STATE_SUSPENDED) 1481 if (udev->state == USB_STATE_SUSPENDED)
1468 status = usb_resume_both(udev, 1482 status = usb_resume_both(udev,
1469 PMSG_AUTO_RESUME); 1483 PMSG_AUTO_RESUME);
1470 if (status != 0) 1484 if (status != 0)
1471 intf->pm_usage_cnt -= inc_usage_cnt; 1485 atomic_sub(inc_usage_cnt, &intf->pm_usage_cnt);
1472 else 1486 else
1473 udev->last_busy = jiffies; 1487 udev->last_busy = jiffies;
1474 } else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) { 1488 } else if (inc_usage_cnt <= 0 &&
1489 atomic_read(&intf->pm_usage_cnt) <= 0) {
1475 status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); 1490 status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND);
1476 } 1491 }
1477 } 1492 }
@@ -1516,7 +1531,7 @@ void usb_autopm_put_interface(struct usb_interface *intf)
1516 1531
1517 status = usb_autopm_do_interface(intf, -1); 1532 status = usb_autopm_do_interface(intf, -1);
1518 dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", 1533 dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
1519 __func__, status, intf->pm_usage_cnt); 1534 __func__, status, atomic_read(&intf->pm_usage_cnt));
1520} 1535}
1521EXPORT_SYMBOL_GPL(usb_autopm_put_interface); 1536EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
1522 1537
@@ -1544,10 +1559,10 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
1544 status = -ENODEV; 1559 status = -ENODEV;
1545 } else { 1560 } else {
1546 udev->last_busy = jiffies; 1561 udev->last_busy = jiffies;
1547 --intf->pm_usage_cnt; 1562 atomic_dec(&intf->pm_usage_cnt);
1548 if (udev->autosuspend_disabled || udev->autosuspend_delay < 0) 1563 if (udev->autosuspend_disabled || udev->autosuspend_delay < 0)
1549 status = -EPERM; 1564 status = -EPERM;
1550 else if (intf->pm_usage_cnt <= 0 && 1565 else if (atomic_read(&intf->pm_usage_cnt) <= 0 &&
1551 !timer_pending(&udev->autosuspend.timer)) { 1566 !timer_pending(&udev->autosuspend.timer)) {
1552 queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, 1567 queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
1553 round_jiffies_up_relative( 1568 round_jiffies_up_relative(
@@ -1555,7 +1570,7 @@ void usb_autopm_put_interface_async(struct usb_interface *intf)
1555 } 1570 }
1556 } 1571 }
1557 dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", 1572 dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
1558 __func__, status, intf->pm_usage_cnt); 1573 __func__, status, atomic_read(&intf->pm_usage_cnt));
1559} 1574}
1560EXPORT_SYMBOL_GPL(usb_autopm_put_interface_async); 1575EXPORT_SYMBOL_GPL(usb_autopm_put_interface_async);
1561 1576
@@ -1599,7 +1614,7 @@ int usb_autopm_get_interface(struct usb_interface *intf)
1599 1614
1600 status = usb_autopm_do_interface(intf, 1); 1615 status = usb_autopm_do_interface(intf, 1);
1601 dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", 1616 dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
1602 __func__, status, intf->pm_usage_cnt); 1617 __func__, status, atomic_read(&intf->pm_usage_cnt));
1603 return status; 1618 return status;
1604} 1619}
1605EXPORT_SYMBOL_GPL(usb_autopm_get_interface); 1620EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
@@ -1627,10 +1642,14 @@ int usb_autopm_get_interface_async(struct usb_interface *intf)
1627 status = -ENODEV; 1642 status = -ENODEV;
1628 else if (udev->autoresume_disabled) 1643 else if (udev->autoresume_disabled)
1629 status = -EPERM; 1644 status = -EPERM;
1630 else if (++intf->pm_usage_cnt > 0 && udev->state == USB_STATE_SUSPENDED) 1645 else {
1631 queue_work(ksuspend_usb_wq, &udev->autoresume); 1646 atomic_inc(&intf->pm_usage_cnt);
1647 if (atomic_read(&intf->pm_usage_cnt) > 0 &&
1648 udev->state == USB_STATE_SUSPENDED)
1649 queue_work(ksuspend_usb_wq, &udev->autoresume);
1650 }
1632 dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", 1651 dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
1633 __func__, status, intf->pm_usage_cnt); 1652 __func__, status, atomic_read(&intf->pm_usage_cnt));
1634 return status; 1653 return status;
1635} 1654}
1636EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async); 1655EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async);
@@ -1652,7 +1671,7 @@ int usb_autopm_set_interface(struct usb_interface *intf)
1652 1671
1653 status = usb_autopm_do_interface(intf, 0); 1672 status = usb_autopm_do_interface(intf, 0);
1654 dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", 1673 dev_vdbg(&intf->dev, "%s: status %d cnt %d\n",
1655 __func__, status, intf->pm_usage_cnt); 1674 __func__, status, atomic_read(&intf->pm_usage_cnt));
1656 return status; 1675 return status;
1657} 1676}
1658EXPORT_SYMBOL_GPL(usb_autopm_set_interface); 1677EXPORT_SYMBOL_GPL(usb_autopm_set_interface);