From 3b4d33414135a050dfd42bcf6f87b6d3dc966eb1 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Thu, 30 Apr 2009 15:23:42 +0200 Subject: [PATCH] --- yaml --- r: 151255 b: refs/heads/master c: 6fcf53acccf85b4b0d0260e66c692a341760f464 h: refs/heads/master i: 151253: f25251a4eb4c19782d0876519fbab638a3ec39bb 151251: 8c70a6ba82a0e0a076817ecba3133d4f26dbf701 151247: 0083a2d26fba0eb1acfe555e24efe0419e955d9b v: v3 --- [refs] | 2 +- trunk/drivers/base/core.c | 51 +++++++++++++++++++++++++++++++++++- trunk/include/linux/device.h | 3 +++ 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 0d547fea3cef..dced7c2e24db 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: acc0e90fbccbc6e4d48184cba0983ea044e131af +refs/heads/master: 6fcf53acccf85b4b0d0260e66c692a341760f464 diff --git a/trunk/drivers/base/core.c b/trunk/drivers/base/core.c index 4d59975c24a8..7ecb1938e590 100644 --- a/trunk/drivers/base/core.c +++ b/trunk/drivers/base/core.c @@ -162,10 +162,18 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, struct device *dev = to_dev(kobj); int retval = 0; - /* add the major/minor if present */ + /* add device node properties if present */ if (MAJOR(dev->devt)) { + const char *tmp; + const char *name; + add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); + name = device_get_nodename(dev, &tmp); + if (name) { + add_uevent_var(env, "DEVNAME=%s", name); + kfree(tmp); + } } if (dev->type && dev->type->name) @@ -1128,6 +1136,47 @@ static struct device *next_device(struct klist_iter *i) return dev; } +/** + * device_get_nodename - path of device node file + * @dev: device + * @tmp: possibly allocated string + * + * Return the relative path of a possible device node. + * Non-default names may need to allocate a memory to compose + * a name. This memory is returned in tmp and needs to be + * freed by the caller. + */ +const char *device_get_nodename(struct device *dev, const char **tmp) +{ + char *s; + + *tmp = NULL; + + /* the device type may provide a specific name */ + if (dev->type && dev->type->nodename) + *tmp = dev->type->nodename(dev); + if (*tmp) + return *tmp; + + /* the class may provide a specific name */ + if (dev->class && dev->class->nodename) + *tmp = dev->class->nodename(dev); + if (*tmp) + return *tmp; + + /* return name without allocation, tmp == NULL */ + if (strchr(dev_name(dev), '!') == NULL) + return dev_name(dev); + + /* replace '!' in the name with '/' */ + *tmp = kstrdup(dev_name(dev), GFP_KERNEL); + if (!*tmp) + return NULL; + while ((s = strchr(*tmp, '!'))) + s[0] = '/'; + return *tmp; +} + /** * device_for_each_child - device child iterator. * @parent: parent struct device. diff --git a/trunk/include/linux/device.h b/trunk/include/linux/device.h index 4410464b134a..ed4e39f2c423 100644 --- a/trunk/include/linux/device.h +++ b/trunk/include/linux/device.h @@ -194,6 +194,7 @@ struct class { struct kobject *dev_kobj; int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); + char *(*nodename)(struct device *dev); void (*class_release)(struct class *class); void (*dev_release)(struct device *dev); @@ -289,6 +290,7 @@ struct device_type { const char *name; struct attribute_group **groups; int (*uevent)(struct device *dev, struct kobj_uevent_env *env); + char *(*nodename)(struct device *dev); void (*release)(struct device *dev); struct dev_pm_ops *pm; @@ -488,6 +490,7 @@ extern struct device *device_find_child(struct device *dev, void *data, extern int device_rename(struct device *dev, char *new_name); extern int device_move(struct device *dev, struct device *new_parent, enum dpm_order dpm_order); +extern const char *device_get_nodename(struct device *dev, const char **tmp); /* * Root device objects for grouping under /sys/devices