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
extern int device_make_dir(struct device * dev);
extern void device_remove_dir(struct device * dev);
extern int device_bus_link(struct device * dev);
......@@ -7,6 +7,8 @@
*
*/
#define DEBUG 0
#include <linux/device.h>
#include <linux/module.h>
#include <linux/errno.h>
......@@ -32,10 +34,12 @@ static struct driver_dir_entry bus_dir = {
int bus_add_device(struct device * dev)
{
if (dev->bus) {
pr_debug("registering %s with bus '%s'\n",dev->bus_id,dev->bus->name);
get_bus(dev->bus);
write_lock(&dev->bus->lock);
list_add_tail(&dev->bus_list,&dev->bus->devices);
write_unlock(&dev->bus->lock);
device_bus_link(dev);
}
return 0;
}
......@@ -50,6 +54,7 @@ int bus_add_device(struct device * dev)
void bus_remove_device(struct device * dev)
{
if (dev->bus) {
driverfs_remove_file(&dev->bus->device_dir,dev->bus_id);
write_lock(&dev->bus->lock);
list_del_init(&dev->bus_list);
write_unlock(&dev->bus->lock);
......@@ -112,7 +117,7 @@ static int __init bus_init(void)
return driverfs_create_dir(&bus_dir,NULL);
}
subsys_initcall(bus_init);
core_initcall(bus_init);
EXPORT_SYMBOL(bus_add_device);
EXPORT_SYMBOL(bus_remove_device);
......
......@@ -5,12 +5,15 @@
* 2002 Open Source Development Lab
*/
#define DEBUG 0
#include <linux/device.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/stat.h>
#include <linux/limits.h>
extern struct driver_file_entry * device_default_files[];
......@@ -68,6 +71,84 @@ void device_remove_dir(struct device * dev)
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)
{
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