diff options
| author | Guenter Roeck <linux@roeck-us.net> | 2013-07-14 19:05:57 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-16 13:57:37 -0400 |
| commit | 39ef311204941ddd01ea2950d6220c8ccc710d15 (patch) | |
| tree | ff043a79a7864d0e50367bcbca80f6562a282ae5 /drivers | |
| parent | 388a8c353d671d4ea2f638be84cfcbb912afdcf2 (diff) | |
driver core: Introduce device_create_groups
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]
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Cc: Jean Delvare <khali@linux-fr.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/base/core.c | 111 |
1 files changed, 83 insertions, 28 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index dc3ea237f086..a8aae1823f73 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -1667,34 +1667,11 @@ static void device_create_release(struct device *dev) | |||
| 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, | |||
| 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: | |||
| 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, | |||
| 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; |
