diff options
Diffstat (limited to 'drivers/usb/core/devio.c')
-rw-r--r-- | drivers/usb/core/devio.c | 109 |
1 files changed, 52 insertions, 57 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 36e7a843bf91..927a181120a9 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -57,7 +57,6 @@ | |||
57 | 57 | ||
58 | #define USB_MAXBUS 64 | 58 | #define USB_MAXBUS 64 |
59 | #define USB_DEVICE_MAX USB_MAXBUS * 128 | 59 | #define USB_DEVICE_MAX USB_MAXBUS * 128 |
60 | static struct class *usb_device_class; | ||
61 | 60 | ||
62 | /* Mutual exclusion for removal, open, and release */ | 61 | /* Mutual exclusion for removal, open, and release */ |
63 | DEFINE_MUTEX(usbfs_mutex); | 62 | DEFINE_MUTEX(usbfs_mutex); |
@@ -421,14 +420,11 @@ static int claimintf(struct dev_state *ps, unsigned int ifnum) | |||
421 | if (test_bit(ifnum, &ps->ifclaimed)) | 420 | if (test_bit(ifnum, &ps->ifclaimed)) |
422 | return 0; | 421 | return 0; |
423 | 422 | ||
424 | /* lock against other changes to driver bindings */ | ||
425 | down_write(&usb_bus_type.subsys.rwsem); | ||
426 | intf = usb_ifnum_to_if(dev, ifnum); | 423 | intf = usb_ifnum_to_if(dev, ifnum); |
427 | if (!intf) | 424 | if (!intf) |
428 | err = -ENOENT; | 425 | err = -ENOENT; |
429 | else | 426 | else |
430 | err = usb_driver_claim_interface(&usbfs_driver, intf, ps); | 427 | err = usb_driver_claim_interface(&usbfs_driver, intf, ps); |
431 | up_write(&usb_bus_type.subsys.rwsem); | ||
432 | if (err == 0) | 428 | if (err == 0) |
433 | set_bit(ifnum, &ps->ifclaimed); | 429 | set_bit(ifnum, &ps->ifclaimed); |
434 | return err; | 430 | return err; |
@@ -444,8 +440,6 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum) | |||
444 | if (ifnum >= 8*sizeof(ps->ifclaimed)) | 440 | if (ifnum >= 8*sizeof(ps->ifclaimed)) |
445 | return err; | 441 | return err; |
446 | dev = ps->dev; | 442 | dev = ps->dev; |
447 | /* lock against other changes to driver bindings */ | ||
448 | down_write(&usb_bus_type.subsys.rwsem); | ||
449 | intf = usb_ifnum_to_if(dev, ifnum); | 443 | intf = usb_ifnum_to_if(dev, ifnum); |
450 | if (!intf) | 444 | if (!intf) |
451 | err = -ENOENT; | 445 | err = -ENOENT; |
@@ -453,7 +447,6 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum) | |||
453 | usb_driver_release_interface(&usbfs_driver, intf); | 447 | usb_driver_release_interface(&usbfs_driver, intf); |
454 | err = 0; | 448 | err = 0; |
455 | } | 449 | } |
456 | up_write(&usb_bus_type.subsys.rwsem); | ||
457 | return err; | 450 | return err; |
458 | } | 451 | } |
459 | 452 | ||
@@ -520,22 +513,25 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, unsig | |||
520 | return ret; | 513 | return ret; |
521 | } | 514 | } |
522 | 515 | ||
523 | static struct usb_device *usbdev_lookup_minor(int minor) | 516 | static int __match_minor(struct device *dev, void *data) |
524 | { | 517 | { |
525 | struct device *device; | 518 | int minor = *((int *)data); |
526 | struct usb_device *udev = NULL; | ||
527 | 519 | ||
528 | down(&usb_device_class->sem); | 520 | if (dev->devt == MKDEV(USB_DEVICE_MAJOR, minor)) |
529 | list_for_each_entry(device, &usb_device_class->devices, node) { | 521 | return 1; |
530 | if (device->devt == MKDEV(USB_DEVICE_MAJOR, minor)) { | 522 | return 0; |
531 | udev = device->platform_data; | 523 | } |
532 | break; | ||
533 | } | ||
534 | } | ||
535 | up(&usb_device_class->sem); | ||
536 | 524 | ||
537 | return udev; | 525 | static struct usb_device *usbdev_lookup_by_minor(int minor) |
538 | }; | 526 | { |
527 | struct device *dev; | ||
528 | |||
529 | dev = bus_find_device(&usb_bus_type, NULL, &minor, __match_minor); | ||
530 | if (!dev) | ||
531 | return NULL; | ||
532 | put_device(dev); | ||
533 | return container_of(dev, struct usb_device, dev); | ||
534 | } | ||
539 | 535 | ||
540 | /* | 536 | /* |
541 | * file operations | 537 | * file operations |
@@ -554,11 +550,14 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
554 | goto out; | 550 | goto out; |
555 | 551 | ||
556 | ret = -ENOENT; | 552 | ret = -ENOENT; |
557 | /* check if we are called from a real node or usbfs */ | 553 | /* usbdev device-node */ |
558 | if (imajor(inode) == USB_DEVICE_MAJOR) | 554 | if (imajor(inode) == USB_DEVICE_MAJOR) |
559 | dev = usbdev_lookup_minor(iminor(inode)); | 555 | dev = usbdev_lookup_by_minor(iminor(inode)); |
556 | #ifdef CONFIG_USB_DEVICEFS | ||
557 | /* procfs file */ | ||
560 | if (!dev) | 558 | if (!dev) |
561 | dev = inode->i_private; | 559 | dev = inode->i_private; |
560 | #endif | ||
562 | if (!dev) | 561 | if (!dev) |
563 | goto out; | 562 | goto out; |
564 | ret = usb_autoresume_device(dev); | 563 | ret = usb_autoresume_device(dev); |
@@ -581,7 +580,7 @@ static int usbdev_open(struct inode *inode, struct file *file) | |||
581 | ps->disccontext = NULL; | 580 | ps->disccontext = NULL; |
582 | ps->ifclaimed = 0; | 581 | ps->ifclaimed = 0; |
583 | security_task_getsecid(current, &ps->secid); | 582 | security_task_getsecid(current, &ps->secid); |
584 | wmb(); | 583 | smp_wmb(); |
585 | list_add_tail(&ps->list, &dev->filelist); | 584 | list_add_tail(&ps->list, &dev->filelist); |
586 | file->private_data = ps; | 585 | file->private_data = ps; |
587 | out: | 586 | out: |
@@ -813,7 +812,6 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg) | |||
813 | 812 | ||
814 | if (copy_from_user(&gd, arg, sizeof(gd))) | 813 | if (copy_from_user(&gd, arg, sizeof(gd))) |
815 | return -EFAULT; | 814 | return -EFAULT; |
816 | down_read(&usb_bus_type.subsys.rwsem); | ||
817 | intf = usb_ifnum_to_if(ps->dev, gd.interface); | 815 | intf = usb_ifnum_to_if(ps->dev, gd.interface); |
818 | if (!intf || !intf->dev.driver) | 816 | if (!intf || !intf->dev.driver) |
819 | ret = -ENODATA; | 817 | ret = -ENODATA; |
@@ -822,7 +820,6 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg) | |||
822 | sizeof(gd.driver)); | 820 | sizeof(gd.driver)); |
823 | ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0); | 821 | ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0); |
824 | } | 822 | } |
825 | up_read(&usb_bus_type.subsys.rwsem); | ||
826 | return ret; | 823 | return ret; |
827 | } | 824 | } |
828 | 825 | ||
@@ -1351,15 +1348,12 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) | |||
1351 | 1348 | ||
1352 | /* disconnect kernel driver from interface */ | 1349 | /* disconnect kernel driver from interface */ |
1353 | case USBDEVFS_DISCONNECT: | 1350 | case USBDEVFS_DISCONNECT: |
1354 | |||
1355 | down_write(&usb_bus_type.subsys.rwsem); | ||
1356 | if (intf->dev.driver) { | 1351 | if (intf->dev.driver) { |
1357 | driver = to_usb_driver(intf->dev.driver); | 1352 | driver = to_usb_driver(intf->dev.driver); |
1358 | dev_dbg (&intf->dev, "disconnect by usbfs\n"); | 1353 | dev_dbg (&intf->dev, "disconnect by usbfs\n"); |
1359 | usb_driver_release_interface(driver, intf); | 1354 | usb_driver_release_interface(driver, intf); |
1360 | } else | 1355 | } else |
1361 | retval = -ENODATA; | 1356 | retval = -ENODATA; |
1362 | up_write(&usb_bus_type.subsys.rwsem); | ||
1363 | break; | 1357 | break; |
1364 | 1358 | ||
1365 | /* let kernel drivers try to (re)bind to the interface */ | 1359 | /* let kernel drivers try to (re)bind to the interface */ |
@@ -1371,7 +1365,6 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) | |||
1371 | 1365 | ||
1372 | /* talk directly to the interface's driver */ | 1366 | /* talk directly to the interface's driver */ |
1373 | default: | 1367 | default: |
1374 | down_read(&usb_bus_type.subsys.rwsem); | ||
1375 | if (intf->dev.driver) | 1368 | if (intf->dev.driver) |
1376 | driver = to_usb_driver(intf->dev.driver); | 1369 | driver = to_usb_driver(intf->dev.driver); |
1377 | if (driver == NULL || driver->ioctl == NULL) { | 1370 | if (driver == NULL || driver->ioctl == NULL) { |
@@ -1381,7 +1374,6 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl) | |||
1381 | if (retval == -ENOIOCTLCMD) | 1374 | if (retval == -ENOIOCTLCMD) |
1382 | retval = -ENOTTY; | 1375 | retval = -ENOTTY; |
1383 | } | 1376 | } |
1384 | up_read(&usb_bus_type.subsys.rwsem); | ||
1385 | } | 1377 | } |
1386 | 1378 | ||
1387 | /* cleanup and return */ | 1379 | /* cleanup and return */ |
@@ -1583,7 +1575,7 @@ static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wai | |||
1583 | return mask; | 1575 | return mask; |
1584 | } | 1576 | } |
1585 | 1577 | ||
1586 | const struct file_operations usbfs_device_file_operations = { | 1578 | const struct file_operations usbdev_file_operations = { |
1587 | .llseek = usbdev_lseek, | 1579 | .llseek = usbdev_lseek, |
1588 | .read = usbdev_read, | 1580 | .read = usbdev_read, |
1589 | .poll = usbdev_poll, | 1581 | .poll = usbdev_poll, |
@@ -1592,50 +1584,53 @@ const struct file_operations usbfs_device_file_operations = { | |||
1592 | .release = usbdev_release, | 1584 | .release = usbdev_release, |
1593 | }; | 1585 | }; |
1594 | 1586 | ||
1595 | static int usbdev_add(struct usb_device *dev) | 1587 | #ifdef CONFIG_USB_DEVICE_CLASS |
1588 | static struct class *usb_classdev_class; | ||
1589 | |||
1590 | static int usb_classdev_add(struct usb_device *dev) | ||
1596 | { | 1591 | { |
1597 | int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); | 1592 | int minor = ((dev->bus->busnum-1) * 128) + (dev->devnum-1); |
1598 | 1593 | ||
1599 | dev->usbfs_dev = device_create(usb_device_class, &dev->dev, | 1594 | dev->usb_classdev = device_create(usb_classdev_class, &dev->dev, |
1600 | MKDEV(USB_DEVICE_MAJOR, minor), | 1595 | MKDEV(USB_DEVICE_MAJOR, minor), |
1601 | "usbdev%d.%d", dev->bus->busnum, dev->devnum); | 1596 | "usbdev%d.%d", dev->bus->busnum, dev->devnum); |
1602 | if (IS_ERR(dev->usbfs_dev)) | 1597 | if (IS_ERR(dev->usb_classdev)) |
1603 | return PTR_ERR(dev->usbfs_dev); | 1598 | return PTR_ERR(dev->usb_classdev); |
1604 | 1599 | ||
1605 | dev->usbfs_dev->platform_data = dev; | ||
1606 | return 0; | 1600 | return 0; |
1607 | } | 1601 | } |
1608 | 1602 | ||
1609 | static void usbdev_remove(struct usb_device *dev) | 1603 | static void usb_classdev_remove(struct usb_device *dev) |
1610 | { | 1604 | { |
1611 | device_unregister(dev->usbfs_dev); | 1605 | device_unregister(dev->usb_classdev); |
1612 | } | 1606 | } |
1613 | 1607 | ||
1614 | static int usbdev_notify(struct notifier_block *self, unsigned long action, | 1608 | static int usb_classdev_notify(struct notifier_block *self, |
1615 | void *dev) | 1609 | unsigned long action, void *dev) |
1616 | { | 1610 | { |
1617 | switch (action) { | 1611 | switch (action) { |
1618 | case USB_DEVICE_ADD: | 1612 | case USB_DEVICE_ADD: |
1619 | if (usbdev_add(dev)) | 1613 | if (usb_classdev_add(dev)) |
1620 | return NOTIFY_BAD; | 1614 | return NOTIFY_BAD; |
1621 | break; | 1615 | break; |
1622 | case USB_DEVICE_REMOVE: | 1616 | case USB_DEVICE_REMOVE: |
1623 | usbdev_remove(dev); | 1617 | usb_classdev_remove(dev); |
1624 | break; | 1618 | break; |
1625 | } | 1619 | } |
1626 | return NOTIFY_OK; | 1620 | return NOTIFY_OK; |
1627 | } | 1621 | } |
1628 | 1622 | ||
1629 | static struct notifier_block usbdev_nb = { | 1623 | static struct notifier_block usbdev_nb = { |
1630 | .notifier_call = usbdev_notify, | 1624 | .notifier_call = usb_classdev_notify, |
1631 | }; | 1625 | }; |
1626 | #endif | ||
1632 | 1627 | ||
1633 | static struct cdev usb_device_cdev = { | 1628 | static struct cdev usb_device_cdev = { |
1634 | .kobj = {.name = "usb_device", }, | 1629 | .kobj = {.name = "usb_device", }, |
1635 | .owner = THIS_MODULE, | 1630 | .owner = THIS_MODULE, |
1636 | }; | 1631 | }; |
1637 | 1632 | ||
1638 | int __init usbdev_init(void) | 1633 | int __init usb_devio_init(void) |
1639 | { | 1634 | { |
1640 | int retval; | 1635 | int retval; |
1641 | 1636 | ||
@@ -1645,38 +1640,38 @@ int __init usbdev_init(void) | |||
1645 | err("unable to register minors for usb_device"); | 1640 | err("unable to register minors for usb_device"); |
1646 | goto out; | 1641 | goto out; |
1647 | } | 1642 | } |
1648 | cdev_init(&usb_device_cdev, &usbfs_device_file_operations); | 1643 | cdev_init(&usb_device_cdev, &usbdev_file_operations); |
1649 | retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); | 1644 | retval = cdev_add(&usb_device_cdev, USB_DEVICE_DEV, USB_DEVICE_MAX); |
1650 | if (retval) { | 1645 | if (retval) { |
1651 | err("unable to get usb_device major %d", USB_DEVICE_MAJOR); | 1646 | err("unable to get usb_device major %d", USB_DEVICE_MAJOR); |
1652 | goto error_cdev; | 1647 | goto error_cdev; |
1653 | } | 1648 | } |
1654 | usb_device_class = class_create(THIS_MODULE, "usb_device"); | 1649 | #ifdef CONFIG_USB_DEVICE_CLASS |
1655 | if (IS_ERR(usb_device_class)) { | 1650 | usb_classdev_class = class_create(THIS_MODULE, "usb_device"); |
1651 | if (IS_ERR(usb_classdev_class)) { | ||
1656 | err("unable to register usb_device class"); | 1652 | err("unable to register usb_device class"); |
1657 | retval = PTR_ERR(usb_device_class); | 1653 | retval = PTR_ERR(usb_classdev_class); |
1658 | goto error_class; | 1654 | cdev_del(&usb_device_cdev); |
1655 | usb_classdev_class = NULL; | ||
1656 | goto out; | ||
1659 | } | 1657 | } |
1660 | 1658 | ||
1661 | usb_register_notify(&usbdev_nb); | 1659 | usb_register_notify(&usbdev_nb); |
1662 | 1660 | #endif | |
1663 | out: | 1661 | out: |
1664 | return retval; | 1662 | return retval; |
1665 | 1663 | ||
1666 | error_class: | ||
1667 | usb_device_class = NULL; | ||
1668 | cdev_del(&usb_device_cdev); | ||
1669 | |||
1670 | error_cdev: | 1664 | error_cdev: |
1671 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); | 1665 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); |
1672 | goto out; | 1666 | goto out; |
1673 | } | 1667 | } |
1674 | 1668 | ||
1675 | void usbdev_cleanup(void) | 1669 | void usb_devio_cleanup(void) |
1676 | { | 1670 | { |
1671 | #ifdef CONFIG_USB_DEVICE_CLASS | ||
1677 | usb_unregister_notify(&usbdev_nb); | 1672 | usb_unregister_notify(&usbdev_nb); |
1678 | class_destroy(usb_device_class); | 1673 | class_destroy(usb_classdev_class); |
1674 | #endif | ||
1679 | cdev_del(&usb_device_cdev); | 1675 | cdev_del(&usb_device_cdev); |
1680 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); | 1676 | unregister_chrdev_region(USB_DEVICE_DEV, USB_DEVICE_MAX); |
1681 | } | 1677 | } |
1682 | |||