aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r--drivers/base/core.c108
1 files changed, 32 insertions, 76 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index ec86d6fc2360..c1343414d285 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -108,7 +108,7 @@ static void device_release(struct kobject * kobj)
108 } 108 }
109} 109}
110 110
111static struct kobj_type ktype_device = { 111static struct kobj_type device_ktype = {
112 .release = device_release, 112 .release = device_release,
113 .sysfs_ops = &dev_sysfs_ops, 113 .sysfs_ops = &dev_sysfs_ops,
114}; 114};
@@ -118,7 +118,7 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
118{ 118{
119 struct kobj_type *ktype = get_ktype(kobj); 119 struct kobj_type *ktype = get_ktype(kobj);
120 120
121 if (ktype == &ktype_device) { 121 if (ktype == &device_ktype) {
122 struct device *dev = to_dev(kobj); 122 struct device *dev = to_dev(kobj);
123 if (dev->uevent_suppress) 123 if (dev->uevent_suppress)
124 return 0; 124 return 0;
@@ -141,33 +141,23 @@ static const char *dev_uevent_name(struct kset *kset, struct kobject *kobj)
141 return NULL; 141 return NULL;
142} 142}
143 143
144static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp, 144static int dev_uevent(struct kset *kset, struct kobject *kobj,
145 int num_envp, char *buffer, int buffer_size) 145 struct kobj_uevent_env *env)
146{ 146{
147 struct device *dev = to_dev(kobj); 147 struct device *dev = to_dev(kobj);
148 int i = 0;
149 int length = 0;
150 int retval = 0; 148 int retval = 0;
151 149
152 /* add the major/minor if present */ 150 /* add the major/minor if present */
153 if (MAJOR(dev->devt)) { 151 if (MAJOR(dev->devt)) {
154 add_uevent_var(envp, num_envp, &i, 152 add_uevent_var(env, "MAJOR=%u", MAJOR(dev->devt));
155 buffer, buffer_size, &length, 153 add_uevent_var(env, "MINOR=%u", MINOR(dev->devt));
156 "MAJOR=%u", MAJOR(dev->devt));
157 add_uevent_var(envp, num_envp, &i,
158 buffer, buffer_size, &length,
159 "MINOR=%u", MINOR(dev->devt));
160 } 154 }
161 155
162 if (dev->type && dev->type->name) 156 if (dev->type && dev->type->name)
163 add_uevent_var(envp, num_envp, &i, 157 add_uevent_var(env, "DEVTYPE=%s", dev->type->name);
164 buffer, buffer_size, &length,
165 "DEVTYPE=%s", dev->type->name);
166 158
167 if (dev->driver) 159 if (dev->driver)
168 add_uevent_var(envp, num_envp, &i, 160 add_uevent_var(env, "DRIVER=%s", dev->driver->name);
169 buffer, buffer_size, &length,
170 "DRIVER=%s", dev->driver->name);
171 161
172#ifdef CONFIG_SYSFS_DEPRECATED 162#ifdef CONFIG_SYSFS_DEPRECATED
173 if (dev->class) { 163 if (dev->class) {
@@ -181,59 +171,43 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
181 171
182 path = kobject_get_path(&parent->kobj, GFP_KERNEL); 172 path = kobject_get_path(&parent->kobj, GFP_KERNEL);
183 if (path) { 173 if (path) {
184 add_uevent_var(envp, num_envp, &i, 174 add_uevent_var(env, "PHYSDEVPATH=%s", path);
185 buffer, buffer_size, &length,
186 "PHYSDEVPATH=%s", path);
187 kfree(path); 175 kfree(path);
188 } 176 }
189 177
190 add_uevent_var(envp, num_envp, &i, 178 add_uevent_var(env, "PHYSDEVBUS=%s", parent->bus->name);
191 buffer, buffer_size, &length,
192 "PHYSDEVBUS=%s", parent->bus->name);
193 179
194 if (parent->driver) 180 if (parent->driver)
195 add_uevent_var(envp, num_envp, &i, 181 add_uevent_var(env, "PHYSDEVDRIVER=%s",
196 buffer, buffer_size, &length, 182 parent->driver->name);
197 "PHYSDEVDRIVER=%s", parent->driver->name);
198 } 183 }
199 } else if (dev->bus) { 184 } else if (dev->bus) {
200 add_uevent_var(envp, num_envp, &i, 185 add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
201 buffer, buffer_size, &length,
202 "PHYSDEVBUS=%s", dev->bus->name);
203 186
204 if (dev->driver) 187 if (dev->driver)
205 add_uevent_var(envp, num_envp, &i, 188 add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
206 buffer, buffer_size, &length,
207 "PHYSDEVDRIVER=%s", dev->driver->name);
208 } 189 }
209#endif 190#endif
210 191
211 /* terminate, set to next free slot, shrink available space */ 192 /* have the bus specific function add its stuff */
212 envp[i] = NULL;
213 envp = &envp[i];
214 num_envp -= i;
215 buffer = &buffer[length];
216 buffer_size -= length;
217
218 if (dev->bus && dev->bus->uevent) { 193 if (dev->bus && dev->bus->uevent) {
219 /* have the bus specific function add its stuff */ 194 retval = dev->bus->uevent(dev, env);
220 retval = dev->bus->uevent(dev, envp, num_envp, buffer, buffer_size);
221 if (retval) 195 if (retval)
222 pr_debug ("%s: bus uevent() returned %d\n", 196 pr_debug ("%s: bus uevent() returned %d\n",
223 __FUNCTION__, retval); 197 __FUNCTION__, retval);
224 } 198 }
225 199
200 /* have the class specific function add its stuff */
226 if (dev->class && dev->class->dev_uevent) { 201 if (dev->class && dev->class->dev_uevent) {
227 /* have the class specific function add its stuff */ 202 retval = dev->class->dev_uevent(dev, env);
228 retval = dev->class->dev_uevent(dev, envp, num_envp, buffer, buffer_size);
229 if (retval) 203 if (retval)
230 pr_debug("%s: class uevent() returned %d\n", 204 pr_debug("%s: class uevent() returned %d\n",
231 __FUNCTION__, retval); 205 __FUNCTION__, retval);
232 } 206 }
233 207
208 /* have the device type specific fuction add its stuff */
234 if (dev->type && dev->type->uevent) { 209 if (dev->type && dev->type->uevent) {
235 /* have the device type specific fuction add its stuff */ 210 retval = dev->type->uevent(dev, env);
236 retval = dev->type->uevent(dev, envp, num_envp, buffer, buffer_size);
237 if (retval) 211 if (retval)
238 pr_debug("%s: dev_type uevent() returned %d\n", 212 pr_debug("%s: dev_type uevent() returned %d\n",
239 __FUNCTION__, retval); 213 __FUNCTION__, retval);
@@ -253,22 +227,18 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
253{ 227{
254 struct kobject *top_kobj; 228 struct kobject *top_kobj;
255 struct kset *kset; 229 struct kset *kset;
256 char *envp[32]; 230 struct kobj_uevent_env *env = NULL;
257 char *data = NULL;
258 char *pos;
259 int i; 231 int i;
260 size_t count = 0; 232 size_t count = 0;
261 int retval; 233 int retval;
262 234
263 /* search the kset, the device belongs to */ 235 /* search the kset, the device belongs to */
264 top_kobj = &dev->kobj; 236 top_kobj = &dev->kobj;
265 if (!top_kobj->kset && top_kobj->parent) { 237 while (!top_kobj->kset && top_kobj->parent)
266 do { 238 top_kobj = top_kobj->parent;
267 top_kobj = top_kobj->parent;
268 } while (!top_kobj->kset && top_kobj->parent);
269 }
270 if (!top_kobj->kset) 239 if (!top_kobj->kset)
271 goto out; 240 goto out;
241
272 kset = top_kobj->kset; 242 kset = top_kobj->kset;
273 if (!kset->uevent_ops || !kset->uevent_ops->uevent) 243 if (!kset->uevent_ops || !kset->uevent_ops->uevent)
274 goto out; 244 goto out;
@@ -278,43 +248,29 @@ static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
278 if (!kset->uevent_ops->filter(kset, &dev->kobj)) 248 if (!kset->uevent_ops->filter(kset, &dev->kobj))
279 goto out; 249 goto out;
280 250
281 data = (char *)get_zeroed_page(GFP_KERNEL); 251 env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
282 if (!data) 252 if (!env)
283 return -ENOMEM; 253 return -ENOMEM;
284 254
285 /* let the kset specific function add its keys */ 255 /* let the kset specific function add its keys */
286 pos = data; 256 retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
287 memset(envp, 0, sizeof(envp));
288 retval = kset->uevent_ops->uevent(kset, &dev->kobj,
289 envp, ARRAY_SIZE(envp),
290 pos, PAGE_SIZE);
291 if (retval) 257 if (retval)
292 goto out; 258 goto out;
293 259
294 /* copy keys to file */ 260 /* copy keys to file */
295 for (i = 0; envp[i]; i++) { 261 for (i = 0; i < env->envp_idx; i++)
296 pos = &buf[count]; 262 count += sprintf(&buf[count], "%s\n", env->envp[i]);
297 count += sprintf(pos, "%s\n", envp[i]);
298 }
299out: 263out:
300 free_page((unsigned long)data); 264 kfree(env);
301 return count; 265 return count;
302} 266}
303 267
304static ssize_t store_uevent(struct device *dev, struct device_attribute *attr, 268static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
305 const char *buf, size_t count) 269 const char *buf, size_t count)
306{ 270{
307 size_t len = count;
308 enum kobject_action action; 271 enum kobject_action action;
309 272
310 if (len && buf[len-1] == '\n') 273 if (kobject_action_type(buf, count, &action) == 0) {
311 len--;
312
313 for (action = 0; action < KOBJ_MAX; action++) {
314 if (strncmp(kobject_actions[action], buf, len) != 0)
315 continue;
316 if (kobject_actions[action][len] != '\0')
317 continue;
318 kobject_uevent(&dev->kobj, action); 274 kobject_uevent(&dev->kobj, action);
319 goto out; 275 goto out;
320 } 276 }
@@ -449,7 +405,7 @@ static struct device_attribute devt_attr =
449 * devices_subsys - structure to be registered with kobject core. 405 * devices_subsys - structure to be registered with kobject core.
450 */ 406 */
451 407
452decl_subsys(devices, &ktype_device, &device_uevent_ops); 408decl_subsys(devices, &device_ktype, &device_uevent_ops);
453 409
454 410
455/** 411/**