aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/base/core.c53
-rw-r--r--include/linux/device.h4
2 files changed, 57 insertions, 0 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 5c91d0d81e7..f1228f25efe 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -94,6 +94,8 @@ static void device_release(struct kobject * kobj)
if (dev->release)
dev->release(dev);
+ else if (dev->class && dev->class->dev_release)
+ dev->class->dev_release(dev);
else {
printk(KERN_ERR "Device '%s' does not have a release() function, "
"it is broken and must be fixed.\n",
@@ -183,6 +185,15 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
}
}
+ if (dev->class && dev->class->dev_uevent) {
+ /* have the class specific function add its stuff */
+ retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size);
+ if (retval) {
+ pr_debug("%s - dev_uevent() returned %d\n",
+ __FUNCTION__, retval);
+ }
+ }
+
return retval;
}
@@ -228,6 +239,43 @@ static void device_remove_groups(struct device *dev)
}
}
+static int device_add_attrs(struct device *dev)
+{
+ struct class *class = dev->class;
+ int error = 0;
+ int i;
+
+ if (!class)
+ return 0;
+
+ if (class->dev_attrs) {
+ for (i = 0; attr_name(class->dev_attrs[i]); i++) {
+ error = device_create_file(dev, &class->dev_attrs[i]);
+ if (error)
+ break;
+ }
+ }
+ if (error)
+ while (--i >= 0)
+ device_remove_file(dev, &class->dev_attrs[i]);
+ return error;
+}
+
+static void device_remove_attrs(struct device *dev)
+{
+ struct class *class = dev->class;
+ int i;
+
+ if (!class)
+ return;
+
+ if (class->dev_attrs) {
+ for (i = 0; attr_name(class->dev_attrs[i]); i++)
+ device_remove_file(dev, &class->dev_attrs[i]);
+ }
+}
+
+
static ssize_t show_dev(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -382,6 +430,8 @@ int device_add(struct device *dev)
}
}
+ if ((error = device_add_attrs(dev)))
+ goto AttrsError;
if ((error = device_add_groups(dev)))
goto GroupError;
if ((error = device_pm_add(dev)))
@@ -412,6 +462,8 @@ int device_add(struct device *dev)
PMError:
device_remove_groups(dev);
GroupError:
+ device_remove_attrs(dev);
+ AttrsError:
if (dev->devt_attr) {
device_remove_file(dev, dev->devt_attr);
kfree(dev->devt_attr);
@@ -509,6 +561,7 @@ void device_del(struct device * dev)
}
device_remove_file(dev, &dev->uevent_attr);
device_remove_groups(dev);
+ device_remove_attrs(dev);
/* Notify the platform of the removal, in case they
* need to do anything...
diff --git a/include/linux/device.h b/include/linux/device.h
index 994d3ebd53f..3122bd25ce4 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -151,12 +151,16 @@ struct class {
struct class_attribute * class_attrs;
struct class_device_attribute * class_dev_attrs;
+ struct device_attribute * dev_attrs;
int (*uevent)(struct class_device *dev, char **envp,
int num_envp, char *buffer, int buffer_size);
+ int (*dev_uevent)(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size);
void (*release)(struct class_device *dev);
void (*class_release)(struct class *class);
+ void (*dev_release)(struct device *dev);
int (*suspend)(struct device *, pm_message_t state);
int (*resume)(struct device *);