device_create_groups lets callers create devices as well as associated sysfs attributes with a single call. This avoids race conditions seen if sysfs attributes on new devices are created later. [fixed up comment block placement and add checks for printk buffer formats - gregkh]
Unified · Split
| @@ -1667,34 +1667,11 @@ static void device_create_release(struct device *dev) · 1666 unmodified lines | |||
| 1667 | kfree(dev); | 1667 | kfree(dev); |
| 1668 | } | 1668 | } |
| 1669 | 1669 | ||
| 1670 | /** | 1670 | static struct device * |
| 1671 | * device_create_vargs - creates a device and registers it with sysfs | 1671 | device_create_groups_vargs(struct class *class, struct device *parent, |
| 1672 | * @class: pointer to the struct class that this device should be registered to | 1672 | dev_t devt, void *drvdata, |
| 1673 | * @parent: pointer to the parent struct device of this new device, if any | 1673 | const struct attribute_group **groups, |
| 1674 | * @devt: the dev_t for the char device to be added | 1674 | const char *fmt, va_list args) |
| 1675 | * @drvdata: the data to be added to the device for callbacks | ||
| 1676 | * @fmt: string for the device's name | ||
| 1677 | * @args: va_list for the device's name | ||
| 1678 | * | ||
| 1679 | * This function can be used by char device classes. A struct device | ||
| 1680 | * will be created in sysfs, registered to the specified class. | ||
| 1681 | * | ||
| 1682 | * A "dev" file will be created, showing the dev_t for the device, if | ||
| 1683 | * the dev_t is not 0,0. | ||
| 1684 | * If a pointer to a parent struct device is passed in, the newly created | ||
| 1685 | * struct device will be a child of that device in sysfs. | ||
| 1686 | * The pointer to the struct device will be returned from the call. | ||
| 1687 | * Any further sysfs files that might be required can be created using this | ||
| 1688 | * pointer. | ||
| 1689 | * | ||
| 1690 | * Returns &struct device pointer on success, or ERR_PTR() on error. | ||
| 1691 | * | ||
| 1692 | * Note: the struct class passed to this function must have previously | ||
| 1693 | * been created with a call to class_create(). | ||
| 1694 | */ | ||
| 1695 | struct device *device_create_vargs(struct class *class, struct device *parent, | ||
| 1696 | dev_t devt, void *drvdata, const char *fmt, | ||
| 1697 | va_list args) | ||
| 1698 | { | 1675 | { |
| 1699 | struct device *dev = NULL; | 1676 | struct device *dev = NULL; |
| 1700 | int retval = -ENODEV; | 1677 | int retval = -ENODEV; |
| @@ -1711,6 +1688,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent, · 10 unmodified lines | |||
| 1711 | dev->devt = devt; | 1688 | dev->devt = devt; |
| 1712 | dev->class = class; | 1689 | dev->class = class; |
| 1713 | dev->parent = parent; | 1690 | dev->parent = parent; |
| 1691 | dev->groups = groups; | ||
| 1714 | dev->release = device_create_release; | 1692 | dev->release = device_create_release; |
| 1715 | dev_set_drvdata(dev, drvdata); | 1693 | dev_set_drvdata(dev, drvdata); |
| 1716 | 1694 | ||
| @@ -1728,6 +1706,39 @@ error: · 11 unmodified lines | |||
| 1728 | put_device(dev); | 1706 | put_device(dev); |
| 1729 | return ERR_PTR(retval); | 1707 | return ERR_PTR(retval); |
| 1730 | } | 1708 | } |
| 1709 | |||
| 1710 | /** | ||
| 1711 | * device_create_vargs - creates a device and registers it with sysfs | ||
| 1712 | * @class: pointer to the struct class that this device should be registered to | ||
| 1713 | * @parent: pointer to the parent struct device of this new device, if any | ||
| 1714 | * @devt: the dev_t for the char device to be added | ||
| 1715 | * @drvdata: the data to be added to the device for callbacks | ||
| 1716 | * @fmt: string for the device's name | ||
| 1717 | * @args: va_list for the device's name | ||
| 1718 | * | ||
| 1719 | * This function can be used by char device classes. A struct device | ||
| 1720 | * will be created in sysfs, registered to the specified class. | ||
| 1721 | * | ||
| 1722 | * A "dev" file will be created, showing the dev_t for the device, if | ||
| 1723 | * the dev_t is not 0,0. | ||
| 1724 | * If a pointer to a parent struct device is passed in, the newly created | ||
| 1725 | * struct device will be a child of that device in sysfs. | ||
| 1726 | * The pointer to the struct device will be returned from the call. | ||
| 1727 | * Any further sysfs files that might be required can be created using this | ||
| 1728 | * pointer. | ||
| 1729 | * | ||
| 1730 | * Returns &struct device pointer on success, or ERR_PTR() on error. | ||
| 1731 | * | ||
| 1732 | * Note: the struct class passed to this function must have previously | ||
| 1733 | * been created with a call to class_create(). | ||
| 1734 | */ | ||
| 1735 | struct device *device_create_vargs(struct class *class, struct device *parent, | ||
| 1736 | dev_t devt, void *drvdata, const char *fmt, | ||
| 1737 | va_list args) | ||
| 1738 | { | ||
| 1739 | return device_create_groups_vargs(class, parent, devt, drvdata, NULL, | ||
| 1740 | fmt, args); | ||
| 1741 | } | ||
| 1731 | EXPORT_SYMBOL_GPL(device_create_vargs); | 1742 | EXPORT_SYMBOL_GPL(device_create_vargs); |
| 1732 | 1743 | ||
| 1733 | /** | 1744 | /** |
| @@ -1767,6 +1778,50 @@ struct device *device_create(struct class *class, struct device *parent, · 33 unmodified lines | |||
| 1767 | } | 1778 | } |
| 1768 | EXPORT_SYMBOL_GPL(device_create); | 1779 | EXPORT_SYMBOL_GPL(device_create); |
| 1769 | 1780 | ||
| 1781 | /** | ||
| 1782 | * device_create_with_groups - creates a device and registers it with sysfs | ||
| 1783 | * @class: pointer to the struct class that this device should be registered to | ||
| 1784 | * @parent: pointer to the parent struct device of this new device, if any | ||
| 1785 | * @devt: the dev_t for the char device to be added | ||
| 1786 | * @drvdata: the data to be added to the device for callbacks | ||
| 1787 | * @groups: NULL-terminated list of attribute groups to be created | ||
| 1788 | * @fmt: string for the device's name | ||
| 1789 | * | ||
| 1790 | * This function can be used by char device classes. A struct device | ||
| 1791 | * will be created in sysfs, registered to the specified class. | ||
| 1792 | * Additional attributes specified in the groups parameter will also | ||
| 1793 | * be created automatically. | ||
| 1794 | * | ||
| 1795 | * A "dev" file will be created, showing the dev_t for the device, if | ||
| 1796 | * the dev_t is not 0,0. | ||
| 1797 | * If a pointer to a parent struct device is passed in, the newly created | ||
| 1798 | * struct device will be a child of that device in sysfs. | ||
| 1799 | * The pointer to the struct device will be returned from the call. | ||
| 1800 | * Any further sysfs files that might be required can be created using this | ||
| 1801 | * pointer. | ||
| 1802 | * | ||
| 1803 | * Returns &struct device pointer on success, or ERR_PTR() on error. | ||
| 1804 | * | ||
| 1805 | * Note: the struct class passed to this function must have previously | ||
| 1806 | * been created with a call to class_create(). | ||
| 1807 | */ | ||
| 1808 | struct device *device_create_with_groups(struct class *class, | ||
| 1809 | struct device *parent, dev_t devt, | ||
| 1810 | void *drvdata, | ||
| 1811 | const struct attribute_group **groups, | ||
| 1812 | const char *fmt, ...) | ||
| 1813 | { | ||
| 1814 | va_list vargs; | ||
| 1815 | struct device *dev; | ||
| 1816 | |||
| 1817 | va_start(vargs, fmt); | ||
| 1818 | dev = device_create_groups_vargs(class, parent, devt, drvdata, groups, | ||
| 1819 | fmt, vargs); | ||
| 1820 | va_end(vargs); | ||
| 1821 | return dev; | ||
| 1822 | } | ||
| 1823 | EXPORT_SYMBOL_GPL(device_create_with_groups); | ||
| 1824 | |||
| 1770 | static int __match_devt(struct device *dev, const void *data) | 1825 | static int __match_devt(struct device *dev, const void *data) |
| 1771 | { | 1826 | { |
| 1772 | const dev_t *devt = data; | 1827 | const dev_t *devt = data; |
| @@ -938,6 +938,11 @@ extern __printf(5, 6) · 937 unmodified lines | |||
| 938 | struct device *device_create(struct class *cls, struct device *parent, | 938 | struct device *device_create(struct class *cls, struct device *parent, |
| 939 | dev_t devt, void *drvdata, | 939 | dev_t devt, void *drvdata, |
| 940 | const char *fmt, ...); | 940 | const char *fmt, ...); |
| 941 | extern __printf(6, 7) | ||
| 942 | struct device *device_create_with_groups(struct class *cls, | ||
| 943 | struct device *parent, dev_t devt, void *drvdata, | ||
| 944 | const struct attribute_group **groups, | ||
| 945 | const char *fmt, ...); | ||
| 941 | extern void device_destroy(struct class *cls, dev_t devt); | 946 | extern void device_destroy(struct class *cls, dev_t devt); |
| 942 | 947 | ||
| 943 | /* | 948 | /* |