diff options
-rw-r--r-- | drivers/base/core.c | 51 | ||||
-rw-r--r-- | include/linux/device.h | 3 |
2 files changed, 53 insertions, 1 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 4d59975c24a8..7ecb1938e590 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -162,10 +162,18 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, | |||
162 | struct device *dev = to_dev(kobj); | 162 | struct device *dev = to_dev(kobj); |
163 | int retval = 0; | 163 | int retval = 0; |
164 | 164 | ||
165 | /* add the major/minor if present */ | 165 | /* add device node properties if present */ |
166 | if (MAJOR(dev->devt)) { | 166 | if (MAJOR(dev->devt)) { |
167 | const char *tmp; | ||
168 | const char *name; | ||
169 | |||
167 | add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); | 170 | add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt)); |
168 | add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); | 171 | add_uevent_var(env, "MINOR=%u", MINOR(dev->devt)); |
172 | name = device_get_nodename(dev, &tmp); | ||
173 | if (name) { | ||
174 | add_uevent_var(env, "DEVNAME=%s", name); | ||
175 | kfree(tmp); | ||
176 | } | ||
169 | } | 177 | } |
170 | 178 | ||
171 | if (dev->type && dev->type->name) | 179 | if (dev->type && dev->type->name) |
@@ -1129,6 +1137,47 @@ static struct device *next_device(struct klist_iter *i) | |||
1129 | } | 1137 | } |
1130 | 1138 | ||
1131 | /** | 1139 | /** |
1140 | * device_get_nodename - path of device node file | ||
1141 | * @dev: device | ||
1142 | * @tmp: possibly allocated string | ||
1143 | * | ||
1144 | * Return the relative path of a possible device node. | ||
1145 | * Non-default names may need to allocate a memory to compose | ||
1146 | * a name. This memory is returned in tmp and needs to be | ||
1147 | * freed by the caller. | ||
1148 | */ | ||
1149 | const char *device_get_nodename(struct device *dev, const char **tmp) | ||
1150 | { | ||
1151 | char *s; | ||
1152 | |||
1153 | *tmp = NULL; | ||
1154 | |||
1155 | /* the device type may provide a specific name */ | ||
1156 | if (dev->type && dev->type->nodename) | ||
1157 | *tmp = dev->type->nodename(dev); | ||
1158 | if (*tmp) | ||
1159 | return *tmp; | ||
1160 | |||
1161 | /* the class may provide a specific name */ | ||
1162 | if (dev->class && dev->class->nodename) | ||
1163 | *tmp = dev->class->nodename(dev); | ||
1164 | if (*tmp) | ||
1165 | return *tmp; | ||
1166 | |||
1167 | /* return name without allocation, tmp == NULL */ | ||
1168 | if (strchr(dev_name(dev), '!') == NULL) | ||
1169 | return dev_name(dev); | ||
1170 | |||
1171 | /* replace '!' in the name with '/' */ | ||
1172 | *tmp = kstrdup(dev_name(dev), GFP_KERNEL); | ||
1173 | if (!*tmp) | ||
1174 | return NULL; | ||
1175 | while ((s = strchr(*tmp, '!'))) | ||
1176 | s[0] = '/'; | ||
1177 | return *tmp; | ||
1178 | } | ||
1179 | |||
1180 | /** | ||
1132 | * device_for_each_child - device child iterator. | 1181 | * device_for_each_child - device child iterator. |
1133 | * @parent: parent struct device. | 1182 | * @parent: parent struct device. |
1134 | * @data: data for the callback. | 1183 | * @data: data for the callback. |
diff --git a/include/linux/device.h b/include/linux/device.h index 4410464b134a..ed4e39f2c423 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
@@ -194,6 +194,7 @@ struct class { | |||
194 | struct kobject *dev_kobj; | 194 | struct kobject *dev_kobj; |
195 | 195 | ||
196 | int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); | 196 | int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env); |
197 | char *(*nodename)(struct device *dev); | ||
197 | 198 | ||
198 | void (*class_release)(struct class *class); | 199 | void (*class_release)(struct class *class); |
199 | void (*dev_release)(struct device *dev); | 200 | void (*dev_release)(struct device *dev); |
@@ -289,6 +290,7 @@ struct device_type { | |||
289 | const char *name; | 290 | const char *name; |
290 | struct attribute_group **groups; | 291 | struct attribute_group **groups; |
291 | int (*uevent)(struct device *dev, struct kobj_uevent_env *env); | 292 | int (*uevent)(struct device *dev, struct kobj_uevent_env *env); |
293 | char *(*nodename)(struct device *dev); | ||
292 | void (*release)(struct device *dev); | 294 | void (*release)(struct device *dev); |
293 | 295 | ||
294 | struct dev_pm_ops *pm; | 296 | struct dev_pm_ops *pm; |
@@ -488,6 +490,7 @@ extern struct device *device_find_child(struct device *dev, void *data, | |||
488 | extern int device_rename(struct device *dev, char *new_name); | 490 | extern int device_rename(struct device *dev, char *new_name); |
489 | extern int device_move(struct device *dev, struct device *new_parent, | 491 | extern int device_move(struct device *dev, struct device *new_parent, |
490 | enum dpm_order dpm_order); | 492 | enum dpm_order dpm_order); |
493 | extern const char *device_get_nodename(struct device *dev, const char **tmp); | ||
491 | 494 | ||
492 | /* | 495 | /* |
493 | * Root device objects for grouping under /sys/devices | 496 | * Root device objects for grouping under /sys/devices |