Commit 593e7b23 authored by Patrick Mochel's avatar Patrick Mochel

device model: Create symlinks in bus's 'devices' dir for a device when its registered

parent 77f881c3
...@@ -16,3 +16,4 @@ extern int device_create_dir(struct driver_dir_entry * dir, struct driver_dir_en ...@@ -16,3 +16,4 @@ extern int device_create_dir(struct driver_dir_entry * dir, struct driver_dir_en
extern int device_make_dir(struct device * dev); extern int device_make_dir(struct device * dev);
extern void device_remove_dir(struct device * dev); extern void device_remove_dir(struct device * dev);
extern int device_bus_link(struct device * dev);
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
* *
*/ */
#define DEBUG 0
#include <linux/device.h> #include <linux/device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/errno.h> #include <linux/errno.h>
...@@ -32,10 +34,12 @@ static struct driver_dir_entry bus_dir = { ...@@ -32,10 +34,12 @@ static struct driver_dir_entry bus_dir = {
int bus_add_device(struct device * dev) int bus_add_device(struct device * dev)
{ {
if (dev->bus) { if (dev->bus) {
pr_debug("registering %s with bus '%s'\n",dev->bus_id,dev->bus->name);
get_bus(dev->bus); get_bus(dev->bus);
write_lock(&dev->bus->lock); write_lock(&dev->bus->lock);
list_add_tail(&dev->bus_list,&dev->bus->devices); list_add_tail(&dev->bus_list,&dev->bus->devices);
write_unlock(&dev->bus->lock); write_unlock(&dev->bus->lock);
device_bus_link(dev);
} }
return 0; return 0;
} }
...@@ -50,6 +54,7 @@ int bus_add_device(struct device * dev) ...@@ -50,6 +54,7 @@ int bus_add_device(struct device * dev)
void bus_remove_device(struct device * dev) void bus_remove_device(struct device * dev)
{ {
if (dev->bus) { if (dev->bus) {
driverfs_remove_file(&dev->bus->device_dir,dev->bus_id);
write_lock(&dev->bus->lock); write_lock(&dev->bus->lock);
list_del_init(&dev->bus_list); list_del_init(&dev->bus_list);
write_unlock(&dev->bus->lock); write_unlock(&dev->bus->lock);
...@@ -112,7 +117,7 @@ static int __init bus_init(void) ...@@ -112,7 +117,7 @@ static int __init bus_init(void)
return driverfs_create_dir(&bus_dir,NULL); return driverfs_create_dir(&bus_dir,NULL);
} }
subsys_initcall(bus_init); core_initcall(bus_init);
EXPORT_SYMBOL(bus_add_device); EXPORT_SYMBOL(bus_add_device);
EXPORT_SYMBOL(bus_remove_device); EXPORT_SYMBOL(bus_remove_device);
......
...@@ -5,12 +5,15 @@ ...@@ -5,12 +5,15 @@
* 2002 Open Source Development Lab * 2002 Open Source Development Lab
*/ */
#define DEBUG 0
#include <linux/device.h> #include <linux/device.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/limits.h>
extern struct driver_file_entry * device_default_files[]; extern struct driver_file_entry * device_default_files[];
...@@ -68,6 +71,84 @@ void device_remove_dir(struct device * dev) ...@@ -68,6 +71,84 @@ void device_remove_dir(struct device * dev)
driverfs_remove_dir(&dev->dir); driverfs_remove_dir(&dev->dir);
} }
static int get_devpath_length(struct device * dev)
{
int length = 1;
struct device * parent = dev;
/* walk up the ancestors until we hit the root.
* Add 1 to strlen for leading '/' of each level.
*/
do {
length += strlen(parent->bus_id) + 1;
parent = parent->parent;
} while (parent);
return length;
}
static void fill_devpath(struct device * dev, char * path, int length)
{
struct device * parent;
--length;
for (parent = dev; parent; parent = parent->parent) {
int cur = strlen(parent->bus_id);
/* back up enough to print this bus id with '/' */
length -= cur;
strncpy(path + length,parent->bus_id,cur);
*(path + --length) = '/';
}
pr_debug("%s: path = '%s'\n",__FUNCTION__,path);
}
static int create_symlink(struct driver_dir_entry * parent, char * name, char * path)
{
struct driver_file_entry * entry;
entry = kmalloc(sizeof(struct driver_file_entry),GFP_KERNEL);
if (!entry)
return -ENOMEM;
entry->name = name;
entry->mode = S_IRUGO;
return driverfs_create_symlink(parent,entry,path);
}
int device_bus_link(struct device * dev)
{
char * path;
int length;
int error = 0;
if (!dev->bus)
return 0;
length = get_devpath_length(dev);
/* now add the path from the bus directory
* It should be '../..' (one to get to the 'bus' directory,
* and one to get to the root of the fs.
*/
length += strlen("../..");
if (length > PATH_MAX)
return -ENAMETOOLONG;
if (!(path = kmalloc(length,GFP_KERNEL)))
return -ENOMEM;
memset(path,0,length);
/* our relative position */
strcpy(path,"../..");
fill_devpath(dev,path,length);
error = create_symlink(&dev->bus->device_dir,dev->bus_id,path);
kfree(path);
return error;
}
int device_create_dir(struct driver_dir_entry * dir, struct driver_dir_entry * parent) int device_create_dir(struct driver_dir_entry * dir, struct driver_dir_entry * parent)
{ {
INIT_LIST_HEAD(&dir->files); INIT_LIST_HEAD(&dir->files);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment