diff options
author | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-01-12 11:53:55 -0500 |
---|---|---|
committer | Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> | 2012-01-12 11:53:55 -0500 |
commit | d3b7737f2b70ed2fb7cef985e70d04fb5dee7b7c (patch) | |
tree | 190e42f90d152ebad1c077809422c366cdf0577b /drivers/base/core.c | |
parent | dc6821e0cfe74802aefd2067b40fcdc03fc4599e (diff) | |
parent | 070680218379e15c1901f4bf21b98e3cbf12b527 (diff) |
Merge commit '070680218379e15c1901f4bf21b98e3cbf12b527' into stable/for-linus-fixes-3.3
* commit '070680218379e15c1901f4bf21b98e3cbf12b527': (50 commits)
xen-balloon: convert sysdev_class to a regular subsystem
clocksource: convert sysdev_class to a regular subsystem
ibm_rtl: convert sysdev_class to a regular subsystem
edac: convert sysdev_class to a regular subsystem
rtmutex-tester: convert sysdev_class to a regular subsystem
driver-core: implement 'sysdev' functionality for regular devices and buses
kref: fix up the kfree build problems
kref: Remove the memory barriers
kref: Implement kref_put in terms of kref_sub
kref: Inline all functions
Drivers: hv: Get rid of an unnecessary check in hv.c
Drivers: hv: Make the vmbus driver unloadable
Drivers: hv: Fix a memory leak
Documentation: Update stable address
MAINTAINERS: stable: Update address
w1: add fast search for single slave bus
driver-core: skip uevent generation when nobody is listening
drivers: hv: Don't OOPS when you cannot init vmbus
firmware: google: fix gsmi.c build warning
drivers_base: make argument to platform_device_register_full const
...
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r-- | drivers/base/core.c | 85 |
1 files changed, 69 insertions, 16 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index d8b3d89db04..2dbe801c6ae 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -118,6 +118,56 @@ static const struct sysfs_ops dev_sysfs_ops = { .store = dev_attr_store, }; +#define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr) + +ssize_t device_store_ulong(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct dev_ext_attribute *ea = to_ext_attr(attr); + char *end; + unsigned long new = simple_strtoul(buf, &end, 0); + if (end == buf) + return -EINVAL; + *(unsigned long *)(ea->var) = new; + /* Always return full write size even if we didn't consume all */ + return size; +} +EXPORT_SYMBOL_GPL(device_store_ulong); + +ssize_t device_show_ulong(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct dev_ext_attribute *ea = to_ext_attr(attr); + return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); +} +EXPORT_SYMBOL_GPL(device_show_ulong); + +ssize_t device_store_int(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct dev_ext_attribute *ea = to_ext_attr(attr); + char *end; + long new = simple_strtol(buf, &end, 0); + if (end == buf || new > INT_MAX || new < INT_MIN) + return -EINVAL; + *(int *)(ea->var) = new; + /* Always return full write size even if we didn't consume all */ + return size; +} +EXPORT_SYMBOL_GPL(device_store_int); + +ssize_t device_show_int(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct dev_ext_attribute *ea = to_ext_attr(attr); + + return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); +} +EXPORT_SYMBOL_GPL(device_show_int); /** * device_release - free device structure. @@ -464,7 +514,7 @@ static ssize_t show_dev(struct device *dev, struct device_attribute *attr, static struct device_attribute devt_attr = __ATTR(dev, S_IRUGO, show_dev, NULL); -/* kset to create /sys/devices/ */ +/* /sys/devices/ */ struct kset *devices_kset; /** @@ -711,6 +761,10 @@ static struct kobject *get_device_parent(struct device *dev, return k; } + /* subsystems can specify a default root directory for their devices */ + if (!parent && dev->bus && dev->bus->dev_root) + return &dev->bus->dev_root->kobj; + if (parent) return &parent->kobj; return NULL; @@ -731,14 +785,6 @@ static void cleanup_device_parent(struct device *dev) cleanup_glue_dir(dev, dev->kobj.parent); } -static void setup_parent(struct device *dev, struct device *parent) -{ - struct kobject *kobj; - kobj = get_device_parent(dev, parent); - if (kobj) - dev->kobj.parent = kobj; -} - static int device_add_class_symlinks(struct device *dev) { int error; @@ -891,6 +937,7 @@ int device_private_init(struct device *dev) int device_add(struct device *dev) { struct device *parent = NULL; + struct kobject *kobj; struct class_interface *class_intf; int error = -EINVAL; @@ -914,6 +961,10 @@ int device_add(struct device *dev) dev->init_name = NULL; } + /* subsystems can specify simple device enumeration */ + if (!dev_name(dev) && dev->bus && dev->bus->dev_name) + dev_set_name(dev, "%s%u", dev->bus->dev_name, dev->id); + if (!dev_name(dev)) { error = -EINVAL; goto name_error; @@ -922,7 +973,9 @@ int device_add(struct device *dev) pr_debug("device: '%s': %s\n", dev_name(dev), __func__); parent = get_device(dev->parent); - setup_parent(dev, parent); + kobj = get_device_parent(dev, parent); + if (kobj) + dev->kobj.parent = kobj; /* use parent numa_node */ if (parent) @@ -982,17 +1035,17 @@ int device_add(struct device *dev) &parent->p->klist_children); if (dev->class) { - mutex_lock(&dev->class->p->class_mutex); + mutex_lock(&dev->class->p->mutex); /* tie the class to the device */ klist_add_tail(&dev->knode_class, &dev->class->p->klist_devices); /* notify any interfaces that the device is here */ list_for_each_entry(class_intf, - &dev->class->p->class_interfaces, node) + &dev->class->p->interfaces, node) if (class_intf->add_dev) class_intf->add_dev(dev, class_intf); - mutex_unlock(&dev->class->p->class_mutex); + mutex_unlock(&dev->class->p->mutex); } done: put_device(dev); @@ -1107,15 +1160,15 @@ void device_del(struct device *dev) if (dev->class) { device_remove_class_symlinks(dev); - mutex_lock(&dev->class->p->class_mutex); + mutex_lock(&dev->class->p->mutex); /* notify any interfaces that the device is now gone */ list_for_each_entry(class_intf, - &dev->class->p->class_interfaces, node) + &dev->class->p->interfaces, node) if (class_intf->remove_dev) class_intf->remove_dev(dev, class_intf); /* remove the device from the class list */ klist_del(&dev->knode_class); - mutex_unlock(&dev->class->p->class_mutex); + mutex_unlock(&dev->class->p->mutex); } device_remove_file(dev, &uevent_attr); device_remove_attrs(dev); |