summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/filesystems/driverfs.txt336
-rw-r--r--arch/i386/kernel/edd.c193
-rw-r--r--drivers/acpi/Makefile2
-rw-r--r--drivers/acpi/acpi_bus.h5
-rw-r--r--drivers/acpi/bus.c5
-rw-r--r--drivers/acpi/driverfs.c46
-rw-r--r--drivers/acpi/scan.c84
-rw-r--r--drivers/base/Makefile5
-rw-r--r--drivers/base/base.h29
-rw-r--r--drivers/base/bus.c142
-rw-r--r--drivers/base/class.c112
-rw-r--r--drivers/base/core.c90
-rw-r--r--drivers/base/driver.c32
-rw-r--r--drivers/base/firmware.c32
-rw-r--r--drivers/base/fs/Makefile4
-rw-r--r--drivers/base/fs/bus.c123
-rw-r--r--drivers/base/fs/class.c215
-rw-r--r--drivers/base/fs/device.c195
-rw-r--r--drivers/base/fs/driver.c100
-rw-r--r--drivers/base/fs/fs.h2
-rw-r--r--drivers/base/fs/intf.c54
-rw-r--r--drivers/base/interface.c6
-rw-r--r--drivers/base/intf.c29
-rw-r--r--drivers/block/genhd.c126
-rw-r--r--fs/Makefile2
-rw-r--r--fs/driverfs/Makefile9
-rw-r--r--fs/driverfs/inode.c708
-rw-r--r--fs/partitions/check.c251
-rw-r--r--include/linux/device.h29
-rw-r--r--include/linux/driverfs_fs.h68
-rw-r--r--include/linux/genhd.h6
-rw-r--r--include/linux/kobject.h4
-rw-r--r--include/linux/sysfs.h12
-rw-r--r--init/do_mounts.c6
34 files changed, 732 insertions, 2330 deletions
diff --git a/Documentation/filesystems/driverfs.txt b/Documentation/filesystems/driverfs.txt
deleted file mode 100644
index 15dedc22a8ba..000000000000
--- a/Documentation/filesystems/driverfs.txt
+++ /dev/null
@@ -1,336 +0,0 @@
-
-driverfs - The Device Driver Filesystem
-
-Patrick Mochel <mochel@osdl.org>
-
-2 August 2002
-
-
-What it is:
-~~~~~~~~~~~
-driverfs is a ram-based filesystem. It was created by copying
-ramfs/inode.c to driverfs/inode.c and doing a little search-and-replace.
-
-driverfs is a means to export kernel data structures, their
-attributes, and the linkages between them to userspace.
-
-driverfs provides a unified interface for exporting attributes to
-userspace. Currently, this interface is available only to device and
-bus drivers.
-
-
-Using driverfs
-~~~~~~~~~~~~~~
-driverfs is always compiled in. You can access it by doing something like:
-
- mount -t driverfs driverfs /devices
-
-
-Top Level Directory Layout
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-The driverfs directory arrangement exposes the relationship of kernel
-data structures.
-
-The top level driverfs diretory looks like:
-
-bus/
-root/
-
-root/ contains a filesystem representation of the device tree. It maps
-directly to the internal kernel device tree, which is a hierarchy of
-struct device.
-
-bus/ contains flat directory layout of the various bus types in the
-kernel. Each bus's directory contains two subdirectories:
-
- devices/
- drivers/
-
-devices/ contains symlinks for each device discovered in the system
-that point to the device's directory under root/.
-
-drivers/ contains a directory for each device driver that is loaded
-for devices on that particular bus (this assmumes that drivers do not
-span multiple bus types).
-
-
-More information can device-model specific features can be found in
-Documentation/device-model/.
-
-
-Directory Contents
-~~~~~~~~~~~~~~~~~~
-Each object that is represented in driverfs gets a directory, rather
-than a file, to make it simple to export attributes of that object.
-Attributes are exported via ASCII text files. The programming
-interface is discussed below.
-
-Instead of having monolithic files that are difficult to parse, all
-files are intended to export one attribute. The name of the attribute
-is the name of the file. The value of the attribute are the contents
-of the file.
-
-There should be few, if any, exceptions to this rule. You should not
-violate it, for fear of public humilation.
-
-
-The Two-Tier Model
-~~~~~~~~~~~~~~~~~~
-
-driverfs is a very simple, low-level interface. In order for kernel
-objects to use it, there must be an intermediate layer in place for
-each object type.
-
-All calls in driverfs are intended to be as type-safe as possible.
-In order to extend driverfs to support multiple data types, a layer of
-abstraction was required. This intermediate layer converts between the
-generic calls and data structures of the driverfs core to the
-subsystem-specific objects and calls.
-
-
-The Subsystem Interface
-~~~~~~~~~~~~~~~~~~~~~~~
-
-The subsystems bear the responsibility of implementing driverfs
-extensions for the objects they control. Fortunately, it's intended to
-be really easy to do so.
-
-It's divided into three sections: directories, files, and operations.
-
-
-Directories
-~~~~~~~~~~~
-
-struct driver_dir_entry {
- char * name;
- struct dentry * dentry;
- mode_t mode;
- struct driverfs_ops * ops;
-};
-
-
-int
-driverfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);
-
-void
-driverfs_remove_dir(struct driver_dir_entry * entry);
-
-The directory structure should be statically allocated, and reside in
-a subsystem-specific data structure:
-
-struct device {
- ...
- struct driver_dir_entry dir;
-};
-
-The subsystem is responsible for initializing the name, mode, and ops
-fields of the directory entry. (More on struct driverfs_ops later)
-
-
-Files
-~~~~~
-
-struct attribute {
- char * name;
- mode_t mode;
-};
-
-
-int
-driverfs_create_file(struct attribute * attr, struct driver_dir_entry * parent);
-
-void
-driverfs_remove_file(struct driver_dir_entry *, const char * name);
-
-
-The attribute structure is a simple, common token that the driverfs
-core handles. It has little use on its own outside of the
-core. Objects cannot use a plain struct attribute to export
-attributes, since there are no callbacks for reading and writing data.
-
-Therefore, the subsystem is required to define a data structure that
-encapsulates the attribute structure, and provides type-safe callbacks
-for reading and writing data.
-
-An example looks like this:
-
-struct device_attribute {
- struct attribute attr;
- ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
- ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
-};
-
-
-Note that there is a struct attribute embedded in the structure. In
-order to relieve pain in declaring attributes, the subsystem should
-also define a macro, like:
-
-#define DEVICE_ATTR(_name,_mode,_show,_store) \
-struct device_attribute dev_attr_##_name = { \
- .attr = {.name = __stringify(_name) , .mode = _mode }, \
- .show = _show, \
- .store = _store, \
-};
-
-This hides the initialization of the embedded struct, and in general,
-the internals of each structure. It yields a structure by the name of
-dev_attr_<name>.
-
-In order for objects to create files, the subsystem should create
-wrapper functions, like this:
-
-int device_create_file(struct device *device, struct device_attribute * entry);
-void device_remove_file(struct device * dev, struct device_attribute * attr);
-
-..and forward the call on to the driverfs functions.
-
-Note that there is no unique information in the attribute structures,
-so the same structure can be used to describe files of several
-different object instances.
-
-
-Operations
-~~~~~~~~~~
-
-struct driverfs_ops {
- int (*open)(struct driver_dir_entry *);
- int (*close)(struct driver_dir_entry *);
- ssize_t (*show)(struct driver_dir_entry *, struct attribute *,char *, size_t, loff_t);
- ssize_t (*store)(struct driver_dir_entry *,struct attribute *,const char *, size_t, loff_t);
-};
-
-
-Subsystems are required to implement this set of callbacks. Their
-purpose is to translate the generic data structures into the specific
-objects, and operate on them. This can be done by defining macros like
-this:
-
-#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
-
-#define to_device(d) container_of(d, struct device, dir)
-
-
-Since the directories are statically allocated in the object, you can
-derive the pointer to the object that owns the file. Ditto for the
-attribute structures.
-
-Current Interfaces
-~~~~~~~~~~~~~~~~~~
-
-The following interface layers currently exist in driverfs:
-
-
-- devices (include/linux/device.h)
-----------------------------------
-Structure:
-
-struct device_attribute {
- struct attribute attr;
- ssize_t (*show)(struct device * dev, char * buf, size_t count, loff_t off);
- ssize_t (*store)(struct device * dev, const char * buf, size_t count, loff_t off);
-};
-
-Declaring:
-
-DEVICE_ATTR(_name,_str,_mode,_show,_store);
-
-Creation/Removal:
-
-int device_create_file(struct device *device, struct device_attribute * entry);
-void device_remove_file(struct device * dev, struct device_attribute * attr);
-
-
-- bus drivers (include/linux/device.h)
---------------------------------------
-Structure:
-
-struct bus_attribute {
- struct attribute attr;
- ssize_t (*show)(struct bus_type *, char * buf, size_t count, loff_t off);
- ssize_t (*store)(struct bus_type *, const char * buf, size_t count, loff_t off);
-};
-
-Declaring:
-
-BUS_ATTR(_name,_mode,_show,_store)
-
-Creation/Removal:
-
-int bus_create_file(struct bus_type *, struct bus_attribute *);
-void bus_remove_file(struct bus_type *, struct bus_attribute *);
-
-
-- device drivers (include/linux/device.h)
------------------------------------------
-
-Structure:
-
-struct driver_attribute {
- struct attribute attr;
- ssize_t (*show)(struct device_driver *, char * buf, size_t count, loff_t off);
- ssize_t (*store)(struct device_driver *, const char * buf, size_t count, loff_t off);
-};
-
-Declaring:
-
-DRIVER_ATTR(_name,_mode,_show,_store)
-
-Creation/Removal:
-
-int driver_create_file(struct device_driver *, struct driver_attribute *);
-void driver_remove_file(struct device_driver *, struct driver_attribute *);
-
-
-Reading/Writing Data
-~~~~~~~~~~~~~~~~~~~~
-The callback functionality is similar to the way procfs works. When a
-user performs a read(2) or write(2) on the file, it first calls a
-driverfs function. This calls to the subsystem, which then calls to
-the object's show() or store() function.
-
-The buffer pointer, offset, and length should be passed to each
-function. The downstream callback should fill the buffer and return
-the number of bytes read/written.
-
-
-What driverfs is not:
-~~~~~~~~~~~~~~~~~~~~~
-It is not a replacement for either devfs or procfs.
-
-It does not handle device nodes, like devfs is intended to do. I think
-this functionality is possible, but indeed think that integration of
-the device nodes and control files should be done. Whether driverfs or
-devfs, or something else, is the place to do it, I don't know.
-
-It is not intended to be a replacement for all of the procfs
-functionality. I think that many of the driver files should be moved
-out of /proc (and maybe a few other things as well ;).
-
-
-
-Limitations:
-~~~~~~~~~~~~
-The driverfs functions assume that at most a page is being either read
-or written each time.
-
-There is a race condition that is really, really hard to fix; if not
-impossible. There exists a race between a driverfs file being opened
-and the object that owns the file going away. During the driverfs
-open() callback, the reference count for the owning object needs to be
-incremented.
-
-For drivers, we can put a struct module * owner in struct driver_dir_entry
-and do try_inc_mod_count() when we open a file. However, this won't
-work for devices, that aren't tied to a module. And, it is still not
-guaranteed to solve the race.
-
-I'm looking into fixing this, but it may not be doable without making
-a separate filesystem instance for each object. It's fun stuff. Please
-mail me with creative ideas that you know will work.
-
-
-Possible bugs:
-~~~~~~~~~~~~~~
-It may not deal with offsets and/or seeks very well, especially if
-they cross a page boundary.
-
diff --git a/arch/i386/kernel/edd.c b/arch/i386/kernel/edd.c
index f178bdb1e125..94a7c4cac2e4 100644
--- a/arch/i386/kernel/edd.c
+++ b/arch/i386/kernel/edd.c
@@ -44,7 +44,7 @@
#include <linux/ctype.h>
#include <linux/slab.h>
#include <linux/limits.h>
-#include <linux/driverfs_fs.h>
+#include <linux/device.h>
#include <linux/pci.h>
#include <asm/edd.h>
#include <linux/device.h>
@@ -63,20 +63,9 @@ MODULE_LICENSE("GPL");
#define left (count - (p - buf) - 1)
-/*
- * bios_dir may go away completely,
- * and it definitely won't be at the root
- * of driverfs forever.
- */
-static struct driver_dir_entry bios_dir = {
- .name = "bios",
- .mode = (S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO),
-};
-
struct edd_device {
- char name[EDD_DEVICE_NAME_SIZE];
struct edd_info *info;
- struct driver_dir_entry dir;
+ struct kobject kobj;
};
struct edd_attribute {
@@ -112,13 +101,13 @@ edd_dev_set_info(struct edd_device *edev, struct edd_info *info)
}
#define to_edd_attr(_attr) container_of(_attr,struct edd_attribute,attr)
-#define to_edd_device(_dir) container_of(_dir,struct edd_device,dir)
+#define to_edd_device(obj) container_of(obj,struct edd_device,kobj)
static ssize_t
-edd_attr_show(struct driver_dir_entry *dir, struct attribute *attr,
+edd_attr_show(struct kobject * kobj, struct attribute *attr,
char *buf, size_t count, loff_t off)
{
- struct edd_device *dev = to_edd_device(dir);
+ struct edd_device *dev = to_edd_device(kobj);
struct edd_attribute *edd_attr = to_edd_attr(attr);
ssize_t ret = 0;
@@ -127,7 +116,7 @@ edd_attr_show(struct driver_dir_entry *dir, struct attribute *attr,
return ret;
}
-static struct driverfs_ops edd_attr_ops = {
+static struct sysfs_ops edd_attr_ops = {
.show = edd_attr_show,
};
@@ -586,89 +575,26 @@ static EDD_DEVICE_ATTR(interface, 0444, edd_show_interface, edd_has_edd30);
static EDD_DEVICE_ATTR(host_bus, 0444, edd_show_host_bus, edd_has_edd30);
-static struct edd_attribute * def_attrs[] = {
- &edd_attr_raw_data,
- &edd_attr_version,
- &edd_attr_extensions,
- &edd_attr_info_flags,
- &edd_attr_sectors,
- &edd_attr_default_cylinders,
- &edd_attr_default_heads,
- &edd_attr_default_sectors_per_track,
- &edd_attr_interface,
- &edd_attr_host_bus,
+static struct attribute * def_attrs[] = {
+ &edd_attr_raw_data.attr,
+ &edd_attr_version.attr,
+ &edd_attr_extensions.attr,
+ &edd_attr_info_flags.attr,
+ &edd_attr_sectors.attr,
+ &edd_attr_default_cylinders.attr,
+ &edd_attr_default_heads.attr,
+ &edd_attr_default_sectors_per_track.attr,
+ &edd_attr_interface.attr,
+ &edd_attr_host_bus.attr,
NULL,
};
-/* edd_get_devpath_length(), edd_fill_devpath(), and edd_device_link()
- were taken from linux/drivers/base/fs/device.c. When these
- or similar are exported to generic code, remove these.
-*/
-
-static int
-edd_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
-edd_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) = '/';
- }
-}
-
-static int
-edd_device_symlink(struct edd_device *edev, struct device *dev, char *name)
-{
- char *path;
- int length;
- int error = 0;
-
- if (!dev->bus || !name)
- return 0;
-
- length = edd_get_devpath_length(dev);
-
- /* now add the path from the edd_device directory
- * It should be '../..' (one to get to the 'bios' directory,
- * and one to get to the root of the fs.)
- */
- length += strlen("../../root");
-
- if (length > PATH_MAX)
- return -ENAMETOOLONG;
-
- if (!(path = kmalloc(length, GFP_KERNEL)))
- return -ENOMEM;
- memset(path, 0, length);
+static struct subsystem edd_subsys = {
+ .kobj = { .name = "edd" },
+ .sysfs_ops = &edd_attr_ops,
+ .default_attrs = def_attrs,
+};
- /* our relative position */
- strcpy(path, "../../root");
-
- edd_fill_devpath(dev, path, length);
- error = driverfs_create_symlink(&edev->dir, name, path);
- kfree(path);
- return error;
-}
/**
* edd_dev_is_type() - is this EDD device a 'type' device?
@@ -721,7 +647,7 @@ edd_create_symlink_to_pcidev(struct edd_device *edev)
struct pci_dev *pci_dev = edd_get_pci_dev(edev);
if (!pci_dev)
return 1;
- return edd_device_symlink(edev, &pci_dev->dev, "pci_dev");
+ return sysfs_create_link(&edev->kobj,&pci_dev->dev.kobj,"pci_dev");
}
/**
@@ -833,61 +759,16 @@ edd_create_symlink_to_scsidev(struct edd_device *edev)
return 1;
get_device(&sdev->sdev_driverfs_dev);
- rc = edd_device_symlink(edev, &sdev->sdev_driverfs_dev, "disc");
+ rc = sysfs_create_link(&edev->kobj,&sdev->sdev_driverfs_dev.kobj, "disc");
put_device(&sdev->sdev_driverfs_dev);
return rc;
}
-static inline int
-edd_create_file(struct edd_device *edev, struct edd_attribute *attr)
-{
- return driverfs_create_file(&attr->attr, &edev->dir);
-}
-
static inline void
edd_device_unregister(struct edd_device *edev)
{
- driverfs_remove_dir(&edev->dir);
-}
-
-static int
-edd_populate_dir(struct edd_device *edev)
-{
- struct edd_attribute *attr;
- int i;
- int error = 0;
-
- for (i = 0; (attr=def_attrs[i]); i++) {
- if (!attr->test || (attr->test && !attr->test(edev))) {
- if ((error = edd_create_file(edev, attr))) {
- break;
- }
- }
- }
-
- if (error)
- return error;
-
- edd_create_symlink_to_pcidev(edev);
- edd_create_symlink_to_scsidev(edev);
-
- return 0;
-}
-
-static int
-edd_make_dir(struct edd_device *edev)
-{
- int error;
-
- edev->dir.name = edev->name;
- edev->dir.mode = (S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO);
- edev->dir.ops = &edd_attr_ops;
-
- error = driverfs_create_dir(&edev->dir, &bios_dir);
- if (!error)
- error = edd_populate_dir(edev);
- return error;
+ kobject_unregister(&edev->kobj);
}
static int
@@ -899,9 +780,15 @@ edd_device_register(struct edd_device *edev, int i)
return 1;
memset(edev, 0, sizeof (*edev));
edd_dev_set_info(edev, &edd[i]);
- snprintf(edev->name, EDD_DEVICE_NAME_SIZE, "int13_dev%02x",
+ kobject_init(&edev->kobj);
+ snprintf(edev->kobj.name, EDD_DEVICE_NAME_SIZE, "int13_dev%02x",
edd[i].device);
- error = edd_make_dir(edev);
+ edev->kobj.subsys = &edd_subsys;
+ error = kobject_register(&edev->kobj);
+ if (!error) {
+ edd_create_symlink_to_pcidev(edev);
+ edd_create_symlink_to_scsidev(edev);
+ }
return error;
}
@@ -926,7 +813,7 @@ edd_init(void)
return 1;
}
- rc = driverfs_create_dir(&bios_dir, NULL);
+ rc = firmware_register(&edd_subsys);
if (rc)
return rc;
@@ -943,12 +830,9 @@ edd_init(void)
edd_devices[i] = edev;
}
- if (rc) {
- driverfs_remove_dir(&bios_dir);
- return rc;
- }
-
- return 0;
+ if (rc)
+ firmware_unregister(&edd_subsys);
+ return rc;
}
static void __exit
@@ -963,8 +847,7 @@ edd_exit(void)
kfree(edev);
}
}
-
- driverfs_remove_dir(&bios_dir);
+ firmware_unregister(&edd_subsys);
}
late_initcall(edd_init);
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index d4b67800a629..9311d367e96e 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -32,7 +32,7 @@ obj-$(CONFIG_ACPI_INTERPRETER) += osl.o utils.o \
#
# ACPI Bus and Device Drivers
#
-obj-$(CONFIG_ACPI_BUS) += bus.o driverfs.o
+obj-$(CONFIG_ACPI_BUS) += bus.o
obj-$(CONFIG_ACPI_AC) += ac.o
obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_BUTTON) += button.o
diff --git a/drivers/acpi/acpi_bus.h b/drivers/acpi/acpi_bus.h
index 8ad14bfb7360..50c8374094e6 100644
--- a/drivers/acpi/acpi_bus.h
+++ b/drivers/acpi/acpi_bus.h
@@ -27,7 +27,7 @@
#define __ACPI_BUS_H__
#include <linux/version.h>
-#include <linux/driverfs_fs.h>
+#include <linux/kobject.h>
#include "include/acpi.h"
@@ -255,7 +255,7 @@ struct acpi_device {
struct acpi_device_ops ops;
struct acpi_driver *driver;
void *driver_data;
- struct driver_dir_entry driverfs_dir;
+ struct kobject kobj;
};
#define acpi_driver_data(d) ((d)->driver_data)
@@ -274,6 +274,7 @@ struct acpi_bus_event {
u32 data;
};
+extern struct subsystem acpi_subsys;
/*
* External Functions
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 3c89b289651c..12423b6d5d5c 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -675,6 +675,9 @@ error0:
return_VALUE(-ENODEV);
}
+struct subsystem acpi_subsys = {
+ .kobj = { .name = "acpi" },
+};
static int __init acpi_init (void)
{
@@ -693,6 +696,8 @@ static int __init acpi_init (void)
return -ENODEV;
}
+ firmware_register(&acpi_subsys);
+
result = acpi_bus_init();
if (!result) {
diff --git a/drivers/acpi/driverfs.c b/drivers/acpi/driverfs.c
deleted file mode 100644
index 0c61f97933b7..000000000000
--- a/drivers/acpi/driverfs.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * driverfs.c - ACPI bindings for driverfs.
- *
- * Copyright (c) 2002 Patrick Mochel
- * Copyright (c) 2002 The Open Source Development Lab
- *
- */
-
-#include <linux/stat.h>
-#include <linux/init.h>
-#include <linux/driverfs_fs.h>
-
-#include "acpi_bus.h"
-
-static struct driver_dir_entry acpi_dir = {
- .name = "acpi",
- .mode = (S_IRWXU | S_IRUGO | S_IXUGO),
-};
-
-/* driverfs ops for ACPI attribute files go here, when/if
- * there are ACPI attribute files.
- * For now, we just have directory creation and removal.
- */
-
-void acpi_remove_dir(struct acpi_device * dev)
-{
- if (dev)
- driverfs_remove_dir(&dev->driverfs_dir);
-}
-
-int acpi_create_dir(struct acpi_device * dev)
-{
- struct driver_dir_entry * parent;
-
- parent = dev->parent ? &dev->parent->driverfs_dir : &acpi_dir;
- dev->driverfs_dir.name = dev->pnp.bus_id;
- dev->driverfs_dir.mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
- return driverfs_create_dir(&dev->driverfs_dir,parent);
-}
-
-static int __init acpi_driverfs_init(void)
-{
- return driverfs_create_dir(&acpi_dir,NULL);
-}
-
-subsys_initcall(acpi_driverfs_init);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index c5b8a92514e6..7bc3fd86ac03 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -25,20 +25,52 @@ extern struct acpi_device *acpi_root;
static LIST_HEAD(acpi_device_list);
static spinlock_t acpi_device_lock = SPIN_LOCK_UNLOCKED;
-static int
-acpi_device_register (
- struct acpi_device *device,
- struct acpi_device *parent)
+static void acpi_device_release(struct kobject * kobj)
{
- return acpi_create_dir(device);
+ struct acpi_device * dev = container_of(kobj,struct acpi_device,kobj);
+ kfree(dev);
}
+static struct subsystem acpi_namespace_subsys = {
+ .kobj = { .name = "namespace" },
+ .parent = &acpi_subsys,
+ .release = acpi_device_release,
+};
+
+
+static void acpi_device_register(struct acpi_device * device, struct acpi_device * parent)
+{
+ /*
+ * Linkage
+ * -------
+ * Link this device to its parent and siblings.
+ */
+ INIT_LIST_HEAD(&device->children);
+ INIT_LIST_HEAD(&device->node);
+ INIT_LIST_HEAD(&device->g_list);
+
+ spin_lock(&acpi_device_lock);
+ if (device->parent) {
+ list_add_tail(&device->node, &device->parent->children);
+ list_add_tail(&device->g_list,&device->parent->g_list);
+ } else
+ list_add_tail(&device->g_list,&acpi_device_list);
+ spin_unlock(&acpi_device_lock);
+
+ kobject_init(&device->kobj);
+ strncpy(device->kobj.name,device->pnp.bus_id,KOBJ_NAME_LEN);
+ if (parent)
+ device->kobj.parent = &parent->kobj;
+ device->kobj.subsys = &acpi_namespace_subsys;
+ kobject_register(&device->kobj);
+}
static int
acpi_device_unregister (
- struct acpi_device *device)
+ struct acpi_device *device,
+ int type)
{
- acpi_remove_dir(device);
+ kobject_unregister(&device->kobj);
return 0;
}
@@ -443,16 +475,6 @@ acpi_bus_get_flags (
return_VALUE(0);
}
-static int
-acpi_bus_remove (
- struct acpi_device *device,
- int type)
-{
- acpi_device_unregister(device);
- kfree(device);
- return 0;
-}
-
static void acpi_device_get_busid(struct acpi_device * device, acpi_handle handle, int type)
{
char bus_id[5] = {'?',0};
@@ -621,28 +643,6 @@ void acpi_device_get_debug_info(struct acpi_device * device, acpi_handle handle,
#endif /*CONFIG_ACPI_DEBUG*/
}
-static void acpi_device_attach(struct acpi_device * device, struct acpi_device * parent)
-{
- /*
- * Linkage
- * -------
- * Link this device to its parent and siblings.
- */
- INIT_LIST_HEAD(&device->children);
- INIT_LIST_HEAD(&device->node);
- INIT_LIST_HEAD(&device->g_list);
-
- spin_lock(&acpi_device_lock);
- if (device->parent) {
- list_add_tail(&device->node, &device->parent->children);
- list_add_tail(&device->g_list,&device->parent->g_list);
- } else
- list_add_tail(&device->g_list,&acpi_device_list);
- spin_unlock(&acpi_device_lock);
-
- acpi_device_register(device, parent);
-}
-
static int
acpi_bus_add (
struct acpi_device **child,
@@ -741,7 +741,7 @@ acpi_bus_add (
acpi_device_get_debug_info(device,handle,type);
- acpi_device_attach(device,parent);
+ acpi_device_register(device,parent);
/*
* Bind _ADR-Based Devices
@@ -919,6 +919,8 @@ static int __init acpi_scan_init(void)
if (acpi_disabled)
return_VALUE(0);
+ subsystem_register(&acpi_namespace_subsys);
+
/*
* Create the root device in the bus's device tree
*/
@@ -935,7 +937,7 @@ static int __init acpi_scan_init(void)
result = acpi_bus_scan(acpi_root);
if (result)
- acpi_bus_remove(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
+ acpi_device_unregister(acpi_root, ACPI_BUS_REMOVAL_NORMAL);
Done:
return_VALUE(result);
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index a3e459cc1f6e..6fcb7331ddef 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -2,13 +2,14 @@
obj-y := core.o sys.o interface.o power.o bus.o \
driver.o class.o intf.o platform.o \
- cpu.o
+ cpu.o firmware.o
obj-y += fs/
obj-$(CONFIG_HOTPLUG) += hotplug.o
export-objs := core.o power.o sys.o bus.o driver.o \
- class.o intf.o platform.o cpu.o
+ class.o intf.o platform.o cpu.o \
+ firmware.o
include $(TOPDIR)/Rules.make
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 8fd09addc1f8..c6f4b2f47bf6 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -10,44 +10,15 @@ extern struct list_head global_device_list;
extern spinlock_t device_lock;
extern struct semaphore device_sem;
-extern struct device * get_device_locked(struct device *);
-
extern int bus_add_device(struct device * dev);
extern void bus_remove_device(struct device * dev);
-extern int device_make_dir(struct device * dev);
-extern void device_remove_dir(struct device * dev);
-
-extern int bus_make_dir(struct bus_type * bus);
-extern void bus_remove_dir(struct bus_type * bus);
-
extern int bus_add_driver(struct device_driver *);
extern void bus_remove_driver(struct device_driver *);
-extern int driver_make_dir(struct device_driver * drv);
-extern void driver_remove_dir(struct device_driver * drv);
-
-extern int device_bus_link(struct device * dev);
-extern void device_remove_symlink(struct driver_dir_entry * dir, const char * name);
-
-extern int devclass_make_dir(struct device_class *);
-extern void devclass_remove_dir(struct device_class *);
-
-extern int devclass_drv_link(struct device_driver *);
-extern void devclass_drv_unlink(struct device_driver *);
-
-extern int devclass_dev_link(struct device_class *, struct device *);
-extern void devclass_dev_unlink(struct device_class *, struct device *);
-
extern int devclass_add_device(struct device *);
extern void devclass_remove_device(struct device *);
-extern int intf_make_dir(struct device_interface *);
-extern void intf_remove_dir(struct device_interface *);
-
-extern int intf_dev_link(struct intf_data *);
-extern void intf_dev_unlink(struct intf_data *);
-
extern int interface_add(struct device_class *, struct device *);
extern void interface_remove(struct device_class *, struct device *);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 8d0bbb5c9256..08db6a58ead3 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -12,6 +12,7 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/errno.h>
+#include <linux/init.h>
#include "base.h"
static LIST_HEAD(bus_driver_list);
@@ -19,6 +20,109 @@ static LIST_HEAD(bus_driver_list);
#define to_dev(node) container_of(node,struct device,bus_list)
#define to_drv(node) container_of(node,struct device_driver,bus_list)
+#define to_bus_attr(_attr) container_of(_attr,struct bus_attribute,attr)
+#define to_bus(obj) container_of(obj,struct bus_type,subsys.kobj)
+
+/*
+ * sysfs bindings for drivers
+ */
+
+#define to_drv_attr(_attr) container_of(_attr,struct driver_attribute,attr)
+#define to_driver(obj) container_of(obj, struct device_driver, kobj)
+
+
+static ssize_t
+drv_attr_show(struct kobject * kobj, struct attribute * attr,
+ char * buf, size_t count, loff_t off)
+{
+ struct driver_attribute * drv_attr = to_drv_attr(attr);
+ struct device_driver * drv = to_driver(kobj);
+ ssize_t ret = 0;
+
+ if (drv_attr->show)
+ ret = drv_attr->show(drv,buf,count,off);
+ return ret;
+}
+
+static ssize_t
+drv_attr_store(struct kobject * kobj, struct attribute * attr,
+ const char * buf, size_t count, loff_t off)
+{
+ struct driver_attribute * drv_attr = to_drv_attr(attr);
+ struct device_driver * drv = to_driver(kobj);
+ ssize_t ret = 0;
+
+ if (drv_attr->store)
+ ret = drv_attr->store(drv,buf,count,off);
+ return ret;
+}
+
+static struct sysfs_ops driver_sysfs_ops = {
+ .show = drv_attr_show,
+ .store = drv_attr_store,
+};
+
+
+/*
+ * sysfs bindings for drivers
+ */
+
+
+static ssize_t
+bus_attr_show(struct kobject * kobj, struct attribute * attr,
+ char * buf, size_t count, loff_t off)
+{
+ struct bus_attribute * bus_attr = to_bus_attr(attr);
+ struct bus_type * bus = to_bus(kobj);
+ ssize_t ret = 0;
+
+ if (bus_attr->show)
+ ret = bus_attr->show(bus,buf,count,off);
+ return ret;
+}
+
+static ssize_t
+bus_attr_store(struct kobject * kobj, struct attribute * attr,
+ const char * buf, size_t count, loff_t off)
+{
+ struct bus_attribute * bus_attr = to_bus_attr(attr);
+ struct bus_type * bus = to_bus(kobj);
+ ssize_t ret = 0;
+
+ if (bus_attr->store)
+ ret = bus_attr->store(bus,buf,count,off);
+ return ret;
+}
+
+static struct sysfs_ops bus_sysfs_ops = {
+ .show = bus_attr_show,
+ .store = bus_attr_store,
+};
+
+int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
+{
+ int error;
+ if (get_bus(bus)) {
+ error = sysfs_create_file(&bus->subsys.kobj,&attr->attr);
+ put_bus(bus);
+ } else
+ error = -EINVAL;
+ return error;
+}
+
+void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
+{
+ if (get_bus(bus)) {
+ sysfs_remove_file(&bus->subsys.kobj,&attr->attr);
+ put_bus(bus);
+ }
+}
+
+struct subsystem bus_subsys = {
+ .kobj = { .name = "bus" },
+ .sysfs_ops = &bus_sysfs_ops,
+};
+
/**
* bus_for_each_dev - walk list of devices and do something to each
* @bus: bus in question
@@ -92,6 +196,7 @@ static void attach(struct device * dev)
pr_debug("bound device '%s' to driver '%s'\n",
dev->bus_id,dev->driver->name);
list_add_tail(&dev->driver_list,&dev->driver->devices);
+ sysfs_create_link(&dev->driver->kobj,&dev->kobj,dev->kobj.name);
}
static int bus_match(struct device * dev, struct device_driver * drv)
@@ -162,6 +267,7 @@ static int driver_attach(struct device_driver * drv)
static void detach(struct device * dev, struct device_driver * drv)
{
if (drv) {
+ sysfs_remove_link(&drv->kobj,dev->kobj.name);
list_del_init(&dev->driver_list);
devclass_remove_device(dev);
if (drv->remove)
@@ -206,7 +312,7 @@ int bus_add_device(struct device * dev)
list_add_tail(&dev->bus_list,&dev->bus->devices);
device_attach(dev);
up_write(&dev->bus->rwsem);
- device_bus_link(dev);
+ sysfs_create_link(&bus->devsubsys.kobj,&dev->kobj,dev->bus_id);
}
return 0;
}
@@ -221,9 +327,9 @@ int bus_add_device(struct device * dev)
void bus_remove_device(struct device * dev)
{
if (dev->bus) {
+ sysfs_remove_link(&dev->bus->devsubsys.kobj,dev->bus_id);
down_write(&dev->bus->rwsem);
pr_debug("bus %s: remove device %s\n",dev->bus->name,dev->bus_id);
- device_remove_symlink(&dev->bus->device_dir,dev->bus_id);
device_detach(dev);
list_del_init(&dev->bus_list);
up_write(&dev->bus->rwsem);
@@ -240,7 +346,6 @@ int bus_add_driver(struct device_driver * drv)
list_add_tail(&drv->bus_list,&bus->drivers);
driver_attach(drv);
up_write(&bus->rwsem);
- driver_make_dir(drv);
}
return 0;
}
@@ -275,7 +380,6 @@ void put_bus(struct bus_type * bus)
list_del_init(&bus->node);
spin_unlock(&device_lock);
WARN_ON(bus->present);
- bus_remove_dir(bus);
}
int bus_register(struct bus_type * bus)
@@ -286,16 +390,25 @@ int bus_register(struct bus_type * bus)
atomic_set(&bus->refcount,2);
bus->present = 1;
+ strncpy(bus->subsys.kobj.name,bus->name,KOBJ_NAME_LEN);
+ bus->subsys.parent = &bus_subsys;
+ subsystem_register(&bus->subsys);
+
+ snprintf(bus->devsubsys.kobj.name,KOBJ_NAME_LEN,"devices");
+ bus->devsubsys.parent = &bus->subsys;
+ subsystem_register(&bus->devsubsys);
+
+ snprintf(bus->drvsubsys.kobj.name,KOBJ_NAME_LEN,"drivers");
+ bus->drvsubsys.parent = &bus->subsys;
+ bus->drvsubsys.sysfs_ops = &driver_sysfs_ops;
+ subsystem_register(&bus->drvsubsys);
+
spin_lock(&device_lock);
list_add_tail(&bus->node,&bus_driver_list);
spin_unlock(&device_lock);
pr_debug("bus type '%s' registered\n",bus->name);
-
- /* give it some driverfs entities */
- bus_make_dir(bus);
put_bus(bus);
-
return 0;
}
@@ -306,9 +419,19 @@ void bus_unregister(struct bus_type * bus)
spin_unlock(&device_lock);
pr_debug("bus %s: unregistering\n",bus->name);
+ subsystem_unregister(&bus->drvsubsys);
+ subsystem_unregister(&bus->devsubsys);
+ subsystem_unregister(&bus->subsys);
put_bus(bus);
}
+static int __init bus_subsys_init(void)
+{
+ return subsystem_register(&bus_subsys);
+}
+
+core_initcall(bus_subsys_init);
+
EXPORT_SYMBOL(bus_for_each_dev);
EXPORT_SYMBOL(bus_for_each_drv);
EXPORT_SYMBOL(bus_add_device);
@@ -317,3 +440,6 @@ EXPORT_SYMBOL(bus_register);
EXPORT_SYMBOL(bus_unregister);
EXPORT_SYMBOL(get_bus);
EXPORT_SYMBOL(put_bus);
+
+EXPORT_SYMBOL(bus_create_file);
+EXPORT_SYMBOL(bus_remove_file);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index e1e6081cf110..8a22d34d82d9 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -4,10 +4,98 @@
#include <linux/device.h>
#include <linux/module.h>
+#include <linux/init.h>
#include "base.h"
static LIST_HEAD(class_list);
+#define to_class_attr(_attr) container_of(_attr,struct devclass_attribute,attr)
+#define to_class(obj) container_of(obj,struct device_class,subsys.kobj)
+
+static ssize_t
+devclass_attr_show(struct kobject * kobj, struct attribute * attr,
+ char * buf, size_t count, loff_t off)
+{
+ struct devclass_attribute * class_attr = to_class_attr(attr);
+ struct device_class * dc = to_class(kobj);
+ ssize_t ret = 0;
+
+ if (class_attr->show)
+ ret = class_attr->show(dc,buf,count,off);
+ return ret;
+}
+
+static ssize_t
+devclass_attr_store(struct kobject * kobj, struct attribute * attr,
+ const char * buf, size_t count, loff_t off)
+{
+ struct devclass_attribute * class_attr = to_class_attr(attr);
+ struct device_class * dc = to_class(kobj);
+ ssize_t ret = 0;
+
+ if (class_attr->store)
+ ret = class_attr->store(dc,buf,count,off);
+ return ret;
+}
+
+static struct sysfs_ops class_sysfs_ops = {
+ show: devclass_attr_show,
+ store: devclass_attr_store,
+};
+
+static struct subsystem class_subsys = {
+ .kobj = { .name = "class", },
+ .sysfs_ops = &class_sysfs_ops,
+};
+
+
+static int devclass_dev_link(struct device_class * cls, struct device * dev)
+{
+ char linkname[16];
+ snprintf(linkname,16,"%u",dev->class_num);
+ return sysfs_create_link(&cls->devsubsys.kobj,&dev->kobj,linkname);
+}
+
+static void devclass_dev_unlink(struct device_class * cls, struct device * dev)
+{
+ char linkname[16];
+ snprintf(linkname,16,"%u",dev->class_num);
+ sysfs_remove_link(&cls->devsubsys.kobj,linkname);
+}
+
+static int devclass_drv_link(struct device_driver * drv)
+{
+ char name[KOBJ_NAME_LEN * 3];
+ snprintf(name,KOBJ_NAME_LEN * 3,"%s:%s",drv->bus->name,drv->name);
+ return sysfs_create_link(&drv->devclass->drvsubsys.kobj,&drv->kobj,name);
+}
+
+static void devclass_drv_unlink(struct device_driver * drv)
+{
+ char name[KOBJ_NAME_LEN * 3];
+ snprintf(name,KOBJ_NAME_LEN * 3,"%s:%s",drv->bus->name,drv->name);
+ return sysfs_remove_link(&drv->devclass->drvsubsys.kobj,name);
+}
+
+
+int devclass_create_file(struct device_class * cls, struct devclass_attribute * attr)
+{
+ int error;
+ if (cls) {
+ error = sysfs_create_file(&cls->subsys.kobj,&attr->attr);
+ } else
+ error = -EINVAL;
+ return error;
+}
+
+void devclass_remove_file(struct device_class * cls, struct devclass_attribute * attr)
+{
+ if (cls)
+ sysfs_remove_file(&cls->subsys.kobj,&attr->attr);
+}
+
+
+
int devclass_add_driver(struct device_driver * drv)
{
struct device_class * cls = get_devclass(drv->devclass);
@@ -136,7 +224,6 @@ void put_devclass(struct device_class * cls)
if (atomic_dec_and_lock(&cls->refcount,&device_lock)) {
list_del_init(&cls->node);
spin_unlock(&device_lock);
- devclass_remove_dir(cls);
}
}
@@ -150,10 +237,21 @@ int devclass_register(struct device_class * cls)
cls->present = 1;
pr_debug("device class '%s': registering\n",cls->name);
+ strncpy(cls->subsys.kobj.name,cls->name,KOBJ_NAME_LEN);
+ cls->subsys.parent = &class_subsys;
+ subsystem_register(&cls->subsys);
+
+ snprintf(cls->devsubsys.kobj.name,KOBJ_NAME_LEN,"devices");
+ cls->devsubsys.parent = &cls->subsys;
+ subsystem_register(&cls->devsubsys);
+
+ snprintf(cls->drvsubsys.kobj.name,KOBJ_NAME_LEN,"drivers");
+ cls->drvsubsys.parent = &cls->subsys;
+ subsystem_register(&cls->drvsubsys);
+
spin_lock(&device_lock);
list_add_tail(&cls->node,&class_list);
spin_unlock(&device_lock);
- devclass_make_dir(cls);
put_devclass(cls);
return 0;
}
@@ -164,9 +262,19 @@ void devclass_unregister(struct device_class * cls)
cls->present = 0;
spin_unlock(&device_lock);
pr_debug("device class '%s': unregistering\n",cls->name);
+ subsystem_unregister(&cls->drvsubsys);
+ subsystem_unregister(&cls->devsubsys);
+ subsystem_unregister(&cls->subsys);
put_devclass(cls);
}
+static int __init class_subsys_init(void)
+{
+ return subsystem_register(&class_subsys);
+}
+
+core_initcall(class_subsys_init);
+
EXPORT_SYMBOL(devclass_register);
EXPORT_SYMBOL(devclass_unregister);
EXPORT_SYMBOL(get_devclass);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 23ce66f60063..b68299c45c0b 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -23,7 +23,74 @@ DECLARE_MUTEX(device_sem);
spinlock_t device_lock = SPIN_LOCK_UNLOCKED;
-#define to_dev(node) container_of(node,struct device,driver_list)
+#define to_dev(obj) container_of(obj,struct device,kobj)
+
+
+/*
+ * sysfs bindings for devices.
+ */
+
+#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
+
+extern struct attribute * dev_default_attrs[];
+
+static ssize_t
+dev_attr_show(struct kobject * kobj, struct attribute * attr,
+ char * buf, size_t count, loff_t off)
+{
+ struct device_attribute * dev_attr = to_dev_attr(attr);
+ struct device * dev = to_dev(kobj);
+ ssize_t ret = 0;
+
+ if (dev_attr->show)
+ ret = dev_attr->show(dev,buf,count,off);
+ return ret;
+}
+
+static ssize_t
+dev_attr_store(struct kobject * kobj, struct attribute * attr,
+ const char * buf, size_t count, loff_t off)
+{
+ struct device_attribute * dev_attr = to_dev_attr(attr);
+ struct device * dev = to_dev(kobj);
+ ssize_t ret = 0;
+
+ if (dev_attr->store)
+ ret = dev_attr->store(dev,buf,count,off);
+ return ret;
+}
+
+static struct sysfs_ops dev_sysfs_ops = {
+ .show = dev_attr_show,
+ .store = dev_attr_store,
+};
+
+struct subsystem device_subsys = {
+ .kobj = {
+ .name = "devices",
+ },
+ .sysfs_ops = &dev_sysfs_ops,
+ .default_attrs = dev_default_attrs,
+};
+
+
+int device_create_file(struct device * dev, struct device_attribute * attr)
+{
+ int error = 0;
+ if (get_device(dev)) {
+ error = sysfs_create_file(&dev->kobj,&attr->attr);
+ put_device(dev);
+ }
+ return error;
+}
+
+void device_remove_file(struct device * dev, struct device_attribute * attr)
+{
+ if (get_device(dev)) {
+ sysfs_remove_file(&dev->kobj,&attr->attr);
+ put_device(dev);
+ }
+}
int device_add(struct device *dev)
{
@@ -44,7 +111,11 @@ int device_add(struct device *dev)
pr_debug("DEV: registering device: ID = '%s', name = %s\n",
dev->bus_id, dev->name);
- if ((error = device_make_dir(dev)))
+ strncpy(dev->kobj.name,dev->bus_id,KOBJ_NAME_LEN);
+ if (dev->parent)
+ dev->kobj.parent = &dev->parent->kobj;
+ dev->kobj.subsys = &device_subsys;
+ if ((error = kobject_register(&dev->kobj)))
goto register_done;
bus_add_device(dev);
@@ -69,6 +140,7 @@ int device_add(struct device *dev)
void device_initialize(struct device *dev)
{
+ kobject_init(&dev->kobj);
INIT_LIST_HEAD(&dev->node);
INIT_LIST_HEAD(&dev->children);
INIT_LIST_HEAD(&dev->g_list);
@@ -157,9 +229,6 @@ void device_del(struct device * dev)
bus_remove_device(dev);
- /* remove the driverfs directory */
- device_remove_dir(dev);
-
if (dev->release)
dev->release(dev);
@@ -184,10 +253,21 @@ void device_unregister(struct device * dev)
pr_debug("DEV: Unregistering device. ID = '%s', name = '%s'\n",
dev->bus_id,dev->name);
+ kobject_unregister(&dev->kobj);
put_device(dev);
}
+static int __init device_subsys_init(void)
+{
+ return subsystem_register(&device_subsys);
+}
+
+core_initcall(device_subsys_init);
+
EXPORT_SYMBOL(device_register);
EXPORT_SYMBOL(device_unregister);
EXPORT_SYMBOL(get_device);
EXPORT_SYMBOL(put_device);
+
+EXPORT_SYMBOL(device_create_file);
+EXPORT_SYMBOL(device_remove_file);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 4bf4a005b918..f940cc4c5165 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -12,6 +12,29 @@
#define to_dev(node) container_of(node,struct device,driver_list)
+/*
+ * helpers for creating driver attributes in sysfs
+ */
+
+int driver_create_file(struct device_driver * drv, struct driver_attribute * attr)
+{
+ int error;
+ if (get_driver(drv)) {
+ error = sysfs_create_file(&drv->kobj,&attr->attr);
+ put_driver(drv);
+ } else
+ error = -EINVAL;
+ return error;
+}
+
+void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
+{
+ if (get_driver(drv)) {
+ sysfs_remove_file(&drv->kobj,&attr->attr);
+ put_driver(drv);
+ }
+}
+
int driver_for_each_dev(struct device_driver * drv, void * data,
int (*callback)(struct device *, void * ))
{
@@ -65,7 +88,6 @@ void put_driver(struct device_driver * drv)
return;
spin_unlock(&device_lock);
BUG_ON(drv->present);
- bus_remove_driver(drv);
if (drv->release)
drv->release(drv);
put_bus(bus);
@@ -84,6 +106,11 @@ int driver_register(struct device_driver * drv)
pr_debug("driver %s:%s: registering\n",drv->bus->name,drv->name);
+ kobject_init(&drv->kobj);
+ strncpy(drv->kobj.name,drv->name,KOBJ_NAME_LEN);
+ drv->kobj.subsys = &drv->bus->drvsubsys;
+ kobject_register(&drv->kobj);
+
get_bus(drv->bus);
atomic_set(&drv->refcount,2);
rwlock_init(&drv->lock);
@@ -108,3 +135,6 @@ EXPORT_SYMBOL(driver_register);
EXPORT_SYMBOL(driver_unregister);
EXPORT_SYMBOL(get_driver);
EXPORT_SYMBOL(put_driver);
+
+EXPORT_SYMBOL(driver_create_file);
+EXPORT_SYMBOL(driver_remove_file);
diff --git a/drivers/base/firmware.c b/drivers/base/firmware.c
new file mode 100644
index 000000000000..8e146ebfdd91
--- /dev/null
+++ b/drivers/base/firmware.c
@@ -0,0 +1,32 @@
+/*
+ * firmware.c - firmware subsystem hoohaw.
+ */
+
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+static struct subsystem firmware_subsys = {
+ .kobj = { .name = "firmware" },
+};
+
+int firmware_register(struct subsystem * s)
+{
+ s->parent = &firmware_subsys;
+ return subsystem_register(s);
+}
+
+void firmware_unregister(struct subsystem * s)
+{
+ subsystem_unregister(s);
+}
+
+static int __init firmware_init(void)
+{
+ return subsystem_register(&firmware_subsys);
+}
+
+core_initcall(firmware_init);
+
+EXPORT_SYMBOL(firmware_register);
+EXPORT_SYMBOL(firmware_unregister);
diff --git a/drivers/base/fs/Makefile b/drivers/base/fs/Makefile
index d4bcde25fda2..f94c734b258f 100644
--- a/drivers/base/fs/Makefile
+++ b/drivers/base/fs/Makefile
@@ -1,5 +1,5 @@
-obj-y := device.o bus.o driver.o class.o intf.o
+obj-y := device.o
-export-objs := device.o bus.o driver.o class.o
+export-objs := device.o
include $(TOPDIR)/Rules.make
diff --git a/drivers/base/fs/bus.c b/drivers/base/fs/bus.c
deleted file mode 100644
index bd6b92442f81..000000000000
--- a/drivers/base/fs/bus.c
+++ /dev/null
@@ -1,123 +0,0 @@
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/init.h>
-#include <linux/stat.h>
-#include "fs.h"
-
-static struct driver_dir_entry bus_dir;
-
-#define to_bus_attr(_attr) container_of(_attr,struct bus_attribute,attr)
-
-#define to_bus(dir) container_of(dir,struct bus_type,dir)
-
-
-/* driverfs ops for device attribute files */
-
-static int
-bus_attr_open(struct driver_dir_entry * dir)
-{
- struct bus_type * bus = to_bus(dir);
- get_bus(bus);
- return 0;
-}
-
-static int
-bus_attr_close(struct driver_dir_entry * dir)
-{
- struct bus_type * bus = to_bus(dir);
- put_bus(bus);
- return 0;
-}
-
-static ssize_t
-bus_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
- char * buf, size_t count, loff_t off)
-{
- struct bus_attribute * bus_attr = to_bus_attr(attr);
- struct bus_type * bus = to_bus(dir);
- ssize_t ret = 0;
-
- if (bus_attr->show)
- ret = bus_attr->show(bus,buf,count,off);
- return ret;
-}
-
-static ssize_t
-bus_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
- const char * buf, size_t count, loff_t off)
-{
- struct bus_attribute * bus_attr = to_bus_attr(attr);
- struct bus_type * bus = to_bus(dir);
- ssize_t ret = 0;
-
- if (bus_attr->store)
- ret = bus_attr->store(bus,buf,count,off);
- return ret;
-}
-
-static struct driverfs_ops bus_attr_ops = {
- .open = bus_attr_open,
- .close = bus_attr_close,
- .show = bus_attr_show,
- .store = bus_attr_store,
-};
-
-int bus_create_file(struct bus_type * bus, struct bus_attribute * attr)
-{
- int error;
- if (get_bus(bus)) {
- error = driverfs_create_file(&attr->attr,&bus->dir);
- put_bus(bus);
- } else
- error = -EINVAL;
- return error;
-}
-
-void bus_remove_file(struct bus_type * bus, struct bus_attribute * attr)
-{
- if (get_bus(bus)) {
- driverfs_remove_file(&bus->dir,attr->attr.name);
- put_bus(bus);
- }
-}
-
-int bus_make_dir(struct bus_type * bus)
-{
- int error;
- bus->dir.name = bus->name;
- bus->dir.ops = &bus_attr_ops;
-
- error = device_create_dir(&bus->dir,&bus_dir);
- if (!error) {
- bus->device_dir.name = "devices";
- device_create_dir(&bus->device_dir,&bus->dir);
-
- bus->driver_dir.name = "drivers";
- device_create_dir(&bus->driver_dir,&bus->dir);
- }
- return error;
-}
-
-void bus_remove_dir(struct bus_type * bus)
-{
- /* remove driverfs entries */
- driverfs_remove_dir(&bus->driver_dir);
- driverfs_remove_dir(&bus->device_dir);
- driverfs_remove_dir(&bus->dir);
-}
-
-static struct driver_dir_entry bus_dir = {
- .name = "bus",
- .mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO),
-};
-
-static int __init bus_init(void)
-{
- /* make 'bus' driverfs directory */
- return driverfs_create_dir(&bus_dir,NULL);
-}
-
-core_initcall(bus_init);
-
-EXPORT_SYMBOL(bus_create_file);
-EXPORT_SYMBOL(bus_remove_file);
diff --git a/drivers/base/fs/class.c b/drivers/base/fs/class.c
deleted file mode 100644
index 1713000f0c37..000000000000
--- a/drivers/base/fs/class.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * class.c - driverfs bindings for device classes.
- */
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/err.h>
-#include "fs.h"
-
-static struct driver_dir_entry class_dir;
-
-
-#define to_class_attr(_attr) container_of(_attr,struct devclass_attribute,attr)
-
-#define to_class(d) container_of(d,struct device_class,dir)
-
-
-static ssize_t
-devclass_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
- char * buf, size_t count, loff_t off)
-{
- struct devclass_attribute * class_attr = to_class_attr(attr);
- struct device_class * dc = to_class(dir);
- ssize_t ret = 0;
-
- if (class_attr->show)
- ret = class_attr->show(dc,buf,count,off);
- return ret;
-}
-
-static ssize_t
-devclass_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
- const char * buf, size_t count, loff_t off)
-{
- struct devclass_attribute * class_attr = to_class_attr(attr);
- struct device_class * dc = to_class(dir);
- ssize_t ret = 0;
-
- if (class_attr->store)
- ret = class_attr->store(dc,buf,count,off);
- return ret;
-}
-
-static struct driverfs_ops devclass_attr_ops = {
- show: devclass_attr_show,
- store: devclass_attr_store,
-};
-
-int devclass_create_file(struct device_class * dc, struct devclass_attribute * attr)
-{
- int error;
- if (dc) {
- error = driverfs_create_file(&attr->attr,&dc->dir);
- } else
- error = -EINVAL;
- return error;
-}
-
-void devclass_remove_file(struct device_class * dc, struct devclass_attribute * attr)
-{
- if (dc)
- driverfs_remove_file(&dc->dir,attr->attr.name);
-}
-
-/**
- * devclass_dev_link - create symlink to device's directory
- * @cls - device class we're a part of
- * @dev - device we're linking to
- *
- * Create a symlink in the class's devices/ directory to @dev's
- * directory in the physical hierarchy. The name is the device's
- * class-enumerated value (struct device::class_num). We're
- * creating:
- * class/<class name>/devices/<link name> ->
- * root/<path to device>/<device's dir>
- * So, the link looks like:
- * ../../../root/<path to device>/
- */
-int devclass_dev_link(struct device_class * cls, struct device * dev)
-{
- char linkname[16];
- char * path;
- int length;
- int error;
-
- length = get_devpath_length(dev);
- length += strlen("../../../root");
-
- if (length > PATH_MAX)
- return -ENAMETOOLONG;
-
- if (!(path = kmalloc(length,GFP_KERNEL)))
- return -ENOMEM;
- memset(path,0,length);
- strcpy(path,"../../../root");
- fill_devpath(dev,path,length);
-
- snprintf(linkname,16,"%u",dev->class_num);
- error = driverfs_create_symlink(&cls->device_dir,linkname,path);
- kfree(path);
- return error;
-}
-
-void devclass_dev_unlink(struct device_class * cls, struct device * dev)
-{
- char linkname[16];
-
- snprintf(linkname,16,"%u",dev->class_num);
- driverfs_remove_file(&cls->device_dir,linkname);
-}
-
-/**
- * devclass_drv_link - create symlink to driver's directory
- * @drv: driver we're linking up
- *
- * Create a symlink in the class's drivers/ directory to @drv's
- * directory (in the bus's directory). It's name is <bus>:<driver>
- * to prevent naming conflicts.
- *
- * We're creating
- * class/<class name>/drivers/<link name> ->
- * bus/<bus name>/drivers/<driver name>/
- * So, the link looks like:
- * ../../../bus/<bus name>/drivers/<driver name>
- */
-int devclass_drv_link(struct device_driver * drv)
-{
- char * name;
- char * path;
- int namelen;
- int pathlen;
- int error = 0;
-
- namelen = strlen(drv->name) + strlen(drv->bus->name) + 2;
- name = kmalloc(namelen,GFP_KERNEL);
- if (!name)
- return -ENOMEM;
- snprintf(name,namelen,"%s:%s",drv->bus->name,drv->name);
-
- pathlen = strlen("../../../bus/") +
- strlen(drv->bus->name) +
- strlen("/drivers/") +
- strlen(drv->name) + 1;
- if (!(path = kmalloc(pathlen,GFP_KERNEL))) {
- error = -ENOMEM;
- goto Done;
- }
- snprintf(path,pathlen,"%s%s%s%s",
- "../../../bus/",
- drv->bus->name,
- "/drivers/",
- drv->name);
-
- error = driverfs_create_symlink(&drv->devclass->driver_dir,name,path);
- Done:
- kfree(name);
- kfree(path);
- return error;
-}
-
-void devclass_drv_unlink(struct device_driver * drv)
-{
- char * name;
- int length;
-
- length = strlen(drv->name) + strlen(drv->bus->name) + 2;
- if ((name = kmalloc(length,GFP_KERNEL))) {
- driverfs_remove_file(&drv->devclass->driver_dir,name);
- kfree(name);
- }
-}
-
-void devclass_remove_dir(struct device_class * dc)
-{
- driverfs_remove_dir(&dc->device_dir);
- driverfs_remove_dir(&dc->driver_dir);
- driverfs_remove_dir(&dc->dir);
-}
-
-int devclass_make_dir(struct device_class * dc)
-{
- int error;
-
- dc->dir.name = dc->name;
- dc->dir.ops = &devclass_attr_ops;
- error = device_create_dir(&dc->dir,&class_dir);
- if (!error) {
- dc->driver_dir.name = "drivers";
- error = device_create_dir(&dc->driver_dir,&dc->dir);
- if (!error) {
- dc->device_dir.name = "devices";
- error = device_create_dir(&dc->device_dir,&dc->dir);
- }
- if (error)
- driverfs_remove_dir(&dc->dir);
- }
- return error;
-}
-
-static struct driver_dir_entry class_dir = {
- name: "class",
- mode: (S_IRWXU | S_IRUGO | S_IXUGO),
-};
-
-static int __init devclass_driverfs_init(void)
-{
- return driverfs_create_dir(&class_dir,NULL);
-}
-
-core_initcall(devclass_driverfs_init);
-
-EXPORT_SYMBOL(devclass_create_file);
-EXPORT_SYMBOL(devclass_remove_file);
diff --git a/drivers/base/fs/device.c b/drivers/base/fs/device.c
index 06984c469a18..faaf687507cb 100644
--- a/drivers/base/fs/device.c
+++ b/drivers/base/fs/device.c
@@ -16,112 +16,6 @@
#include <linux/stat.h>
#include <linux/limits.h>
-static struct driver_dir_entry device_root_dir = {
- .name = "root",
- .mode = (S_IRWXU | S_IRUGO | S_IXUGO),
-};
-
-extern struct device_attribute * device_default_files[];
-
-#define to_dev_attr(_attr) container_of(_attr,struct device_attribute,attr)
-
-#define to_device(d) container_of(d, struct device, dir)
-
-
-/* driverfs ops for device attribute files */
-
-static int
-dev_attr_open(struct driver_dir_entry * dir)
-{
- struct device * dev = to_device(dir);
- get_device(dev);
- return 0;
-}
-
-static int
-dev_attr_close(struct driver_dir_entry * dir)
-{
- struct device * dev = to_device(dir);
- put_device(dev);
- return 0;
-}
-
-static ssize_t
-dev_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
- char * buf, size_t count, loff_t off)
-{
- struct device_attribute * dev_attr = to_dev_attr(attr);
- struct device * dev = to_device(dir);
- ssize_t ret = 0;
-
- if (dev_attr->show)
- ret = dev_attr->show(dev,buf,count,off);
- return ret;
-}
-
-static ssize_t
-dev_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
- const char * buf, size_t count, loff_t off)
-{
- struct device_attribute * dev_attr = to_dev_attr(attr);
- struct device * dev = to_device(dir);
- ssize_t ret = 0;
-
- if (dev_attr->store)
- ret = dev_attr->store(dev,buf,count,off);
- return ret;
-}
-
-static struct driverfs_ops dev_attr_ops = {
- .open = dev_attr_open,
- .close = dev_attr_close,
- .show = dev_attr_show,
- .store = dev_attr_store,
-};
-
-/**
- * device_create_file - create a driverfs file for a device
- * @dev: device requesting file
- * @entry: entry describing file
- *
- * Allocate space for file entry, copy descriptor, and create.
- */
-int device_create_file(struct device * dev, struct device_attribute * entry)
-{
- int error = -EINVAL;
-
- if (get_device(dev)) {
- error = driverfs_create_file(&entry->attr,&dev->dir);
- put_device(dev);
- }
- return error;
-}
-
-/**
- * device_remove_file - remove a device's file by name
- * @dev: device requesting removal
- * @name: name of the file
- *
- */
-void device_remove_file(struct device * dev, struct device_attribute * attr)
-{
- if (dev) {
- get_device(dev);
- driverfs_remove_file(&dev->dir,attr->attr.name);
- put_device(dev);
- }
-}
-
-/**
- * device_remove_dir - remove a device's directory
- * @dev: device in question
- */
-void device_remove_dir(struct device * dev)
-{
- if (dev)
- driverfs_remove_dir(&dev->dir);
-}
-
int get_devpath_length(struct device * dev)
{
int length = 1;
@@ -153,92 +47,3 @@ void fill_devpath(struct device * dev, char * path, int length)
pr_debug("%s: path = '%s'\n",__FUNCTION__,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's directory,
- * one to get to the 'bus' directory, and one to get to the root
- * of the fs.)
- */
- length += strlen("../../../root");
-
- if (length > PATH_MAX)
- return -ENAMETOOLONG;
-
- if (!(path = kmalloc(length,GFP_KERNEL)))
- return -ENOMEM;
- memset(path,0,length);
-
- /* our relative position */
- strcpy(path,"../../../root");
-
- fill_devpath(dev,path,length);
- error = driverfs_create_symlink(&dev->bus->device_dir,dev->bus_id,path);
- kfree(path);
- return error;
-}
-
-void device_remove_symlink(struct driver_dir_entry * dir, const char * name)
-{
- driverfs_remove_file(dir,name);
-}
-
-int device_create_dir(struct driver_dir_entry * dir, struct driver_dir_entry * parent)
-{
- dir->mode = (S_IFDIR| S_IRWXU | S_IRUGO | S_IXUGO);
- return driverfs_create_dir(dir,parent);
-}
-
-/**
- * device_make_dir - create a driverfs directory
- * @name: name of directory
- * @parent: dentry for the parent directory
- *
- * Do the initial creation of the device's driverfs directory
- * and populate it with the one default file.
- *
- * This is just a helper for device_register(), as we
- * don't export this function. (Yes, that means we don't allow
- * devices to create subdirectories).
- */
-int device_make_dir(struct device * dev)
-{
- struct driver_dir_entry * parent;
- struct device_attribute * entry;
- int error;
- int i;
-
- parent = dev->parent ? &dev->parent->dir : &device_root_dir;
- dev->dir.name = dev->bus_id;
- dev->dir.ops = &dev_attr_ops;
-
- if ((error = device_create_dir(&dev->dir,parent)))
- return error;
-
- for (i = 0; (entry = *(device_default_files + i)); i++) {
- if ((error = device_create_file(dev,entry))) {
- device_remove_dir(dev);
- break;
- }
- }
- return error;
-}
-
-static int device_driverfs_init(void)
-{
- return driverfs_create_dir(&device_root_dir,NULL);
-}
-
-core_initcall(device_driverfs_init);
-
-EXPORT_SYMBOL(device_create_file);
-EXPORT_SYMBOL(device_remove_file);
diff --git a/drivers/base/fs/driver.c b/drivers/base/fs/driver.c
deleted file mode 100644
index c70834d738fc..000000000000
--- a/drivers/base/fs/driver.c
+++ /dev/null
@@ -1,100 +0,0 @@
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/stat.h>
-#include <linux/err.h>
-#include "fs.h"
-
-#define to_drv_attr(_attr) container_of(_attr,struct driver_attribute,attr)
-
-#define to_drv(d) container_of(d, struct device_driver, dir)
-
-
-/* driverfs ops for device attribute files */
-
-static int
-drv_attr_open(struct driver_dir_entry * dir)
-{
- struct device_driver * drv = to_drv(dir);
- get_driver(drv);
- return 0;
-}
-
-static int
-drv_attr_close(struct driver_dir_entry * dir)
-{
- struct device_driver * drv = to_drv(dir);
- put_driver(drv);
- return 0;
-}
-
-static ssize_t
-drv_attr_show(struct driver_dir_entry * dir, struct attribute * attr,
- char * buf, size_t count, loff_t off)
-{
- struct driver_attribute * drv_attr = to_drv_attr(attr);
- struct device_driver * drv = to_drv(dir);
- ssize_t ret = 0;
-
- if (drv_attr->show)
- ret = drv_attr->show(drv,buf,count,off);
- return ret;
-}
-
-static ssize_t
-drv_attr_store(struct driver_dir_entry * dir, struct attribute * attr,
- const char * buf, size_t count, loff_t off)
-{
- struct driver_attribute * drv_attr = to_drv_attr(attr);
- struct device_driver * drv = to_drv(dir);
- ssize_t ret = 0;
-
- if (drv_attr->store)
- ret = drv_attr->store(drv,buf,count,off);
- return ret;
-}
-
-static struct driverfs_ops drv_attr_ops = {
- .open = drv_attr_open,
- .close = drv_attr_close,
- .show = drv_attr_show,
- .store = drv_attr_store,
-};
-
-int driver_create_file(struct device_driver * drv, struct driver_attribute * attr)
-{
- int error;
- if (get_driver(drv)) {
- error = driverfs_create_file(&attr->attr,&drv->dir);
- put_driver(drv);
- } else
- error = -EINVAL;
- return error;
-}
-
-void driver_remove_file(struct device_driver * drv, struct driver_attribute * attr)
-{
- if (get_driver(drv)) {
- driverfs_remove_file(&drv->dir,attr->attr.name);
- put_driver(drv);
- }
-}
-
-/**
- * driver_make_dir - create a driverfs directory for a driver
- * @drv: driver in question
- */
-int driver_make_dir(struct device_driver * drv)
-{
- drv->dir.name = drv->name;
- drv->dir.ops = &drv_attr_ops;
-
- return device_create_dir(&drv->dir,&drv->bus->driver_dir);
-}
-
-void driver_remove_dir(struct device_driver * drv)
-{
- driverfs_remove_dir(&drv->dir);
-}
-
-EXPORT_SYMBOL(driver_create_file);
-EXPORT_SYMBOL(driver_remove_file);
diff --git a/drivers/base/fs/fs.h b/drivers/base/fs/fs.h
index c072bd604137..863c2cd5ab59 100644
--- a/drivers/base/fs/fs.h
+++ b/drivers/base/fs/fs.h
@@ -1,6 +1,4 @@
-extern int device_create_dir(struct driver_dir_entry * dir, struct driver_dir_entry * parent);
-
int get_devpath_length(struct device * dev);
void fill_devpath(struct device * dev, char * path, int length);
diff --git a/drivers/base/fs/intf.c b/drivers/base/fs/intf.c
deleted file mode 100644
index 151f60d42b73..000000000000
--- a/drivers/base/fs/intf.c
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * intf.c - driverfs glue for device interfaces
- */
-
-#include <linux/device.h>
-#include <linux/slab.h>
-#include "fs.h"
-
-/**
- * intf_dev_link - symlink from interface's directory to device's directory
- *
- */
-int intf_dev_link(struct intf_data * data)
-{
- char linkname[16];
- char * path;
- int length;
- int error;
-
- length = get_devpath_length(data->dev);
- length += strlen("../../../root");
-
- if (length > PATH_MAX)
- return -ENAMETOOLONG;
-
- if (!(path = kmalloc(length,GFP_KERNEL)))
- return -ENOMEM;
- memset(path,0,length);
- strcpy(path,"../../../root");
- fill_devpath(data->dev,path,length);
-
- snprintf(linkname,16,"%u",data->intf_num);
- error = driverfs_create_symlink(&data->intf->dir,linkname,path);
- kfree(path);
- return error;
-}
-
-void intf_dev_unlink(struct intf_data * data)
-{
- char linkname[16];
- snprintf(linkname,16,"%u",data->intf_num);
- driverfs_remove_file(&data->intf->dir,linkname);
-}
-
-void intf_remove_dir(struct device_interface * intf)
-{
- driverfs_remove_dir(&intf->dir);
-}
-
-int intf_make_dir(struct device_interface * intf)
-{
- intf->dir.name = intf->name;
- return device_create_dir(&intf->dir,&intf->devclass->dir);
-}
diff --git a/drivers/base/interface.c b/drivers/base/interface.c
index 8a5c6e6bc226..a6e0c73d043f 100644
--- a/drivers/base/interface.c
+++ b/drivers/base/interface.c
@@ -88,8 +88,8 @@ device_write_power(struct device * dev, const char * buf, size_t count, loff_t o
static DEVICE_ATTR(power,S_IWUSR | S_IRUGO,
device_read_power,device_write_power);
-struct device_attribute * device_default_files[] = {
- &dev_attr_name,
- &dev_attr_power,
+struct attribute * dev_default_attrs[] = {
+ &dev_attr_name.attr,
+ &dev_attr_power.attr,
NULL,
};
diff --git a/drivers/base/intf.c b/drivers/base/intf.c
index f73a43a7567c..b025d53ee142 100644
--- a/drivers/base/intf.c
+++ b/drivers/base/intf.c
@@ -11,6 +11,26 @@
#define to_intf(node) container_of(node,struct device_interface,node)
+/**
+ * intf_dev_link - symlink from interface's directory to device's directory
+ *
+ */
+static int intf_dev_link(struct intf_data * data)
+{
+ char linkname[16];
+
+ snprintf(linkname,16,"%u",data->intf_num);
+ return sysfs_create_link(&data->intf->kobj,&data->dev->kobj,linkname);
+}
+
+static void intf_dev_unlink(struct intf_data * data)
+{
+ char linkname[16];
+ snprintf(linkname,16,"%u",data->intf_num);
+ sysfs_remove_link(&data->intf->kobj,linkname);
+}
+
+
int interface_register(struct device_interface * intf)
{
struct device_class * cls = intf->devclass;
@@ -18,7 +38,11 @@ int interface_register(struct device_interface * intf)
if (cls) {
pr_debug("register interface '%s' with class '%s\n",
intf->name,cls->name);
- intf_make_dir(intf);
+ kobject_init(&intf->kobj);
+ strncpy(intf->kobj.name,intf->name,KOBJ_NAME_LEN);
+ intf->kobj.subsys = &cls->subsys;
+ kobject_register(&intf->kobj);
+
spin_lock(&device_lock);
list_add_tail(&intf->node,&cls->intf_list);
spin_unlock(&device_lock);
@@ -31,11 +55,10 @@ void interface_unregister(struct device_interface * intf)
{
pr_debug("unregistering interface '%s' from class '%s'\n",
intf->name,intf->devclass->name);
+ kobject_unregister(&intf->kobj);
spin_lock(&device_lock);
list_del_init(&intf->node);
spin_unlock(&device_lock);
-
- intf_remove_dir(intf);
}
int interface_add(struct device_class * cls, struct device * dev)
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 955fa3dedf78..cac3b1acf103 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -252,14 +252,6 @@ struct seq_operations partitions_op = {
extern int blk_dev_init(void);
-struct device_class disk_devclass = {
- .name = "disk",
-};
-
-static struct bus_type disk_bus = {
- name: "block",
-};
-
static struct gendisk *base_probe(dev_t dev, int *part, void *data)
{
char name[20];
@@ -268,6 +260,8 @@ static struct gendisk *base_probe(dev_t dev, int *part, void *data)
return NULL;
}
+struct subsystem block_subsys;
+
int __init device_init(void)
{
struct blk_probe *base = kmalloc(sizeof(struct blk_probe), GFP_KERNEL);
@@ -280,23 +274,116 @@ int __init device_init(void)
for (i = 1; i < MAX_BLKDEV; i++)
probes[i] = base;
blk_dev_init();
- devclass_register(&disk_devclass);
- bus_register(&disk_bus);
+ subsystem_register(&block_subsys);
return 0;
}
-__initcall(device_init);
+subsys_initcall(device_init);
+
+
+
+/*
+ * kobject & sysfs bindings for block devices
+ */
+
+#define to_disk(obj) container_of(obj,struct gendisk,kobj)
+
+struct disk_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct gendisk *, char *, size_t, loff_t);
+};
+
+static ssize_t disk_attr_show(struct kobject * kobj, struct attribute * attr,
+ char * page, size_t count, loff_t off)
+{
+ struct gendisk * disk = to_disk(kobj);
+ struct disk_attribute * disk_attr = container_of(attr,struct disk_attribute,attr);
+ ssize_t ret = 0;
+ if (disk_attr->show)
+ ret = disk_attr->show(disk,page,count,off);
+ return ret;
+}
+
+static struct sysfs_ops disk_sysfs_ops = {
+ .show = &disk_attr_show,
+};
+
+static ssize_t disk_dev_read(struct gendisk * disk,
+ char *page, size_t count, loff_t off)
+{
+ dev_t base = MKDEV(disk->major, disk->first_minor);
+ return off ? 0 : sprintf(page, "%04x\n",base);
+}
+static ssize_t disk_range_read(struct gendisk * disk,
+ char *page, size_t count, loff_t off)
+{
+ return off ? 0 : sprintf(page, "%d\n",disk->minors);
+}
+static ssize_t disk_size_read(struct gendisk * disk,
+ char *page, size_t count, loff_t off)
+{
+ return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)get_capacity(disk));
+}
+static inline unsigned MSEC(unsigned x)
+{
+ return x * 1000 / HZ;
+}
+static ssize_t disk_stat_read(struct gendisk * disk,
+ char *page, size_t count, loff_t off)
+{
+ disk_round_stats(disk);
+ return off ? 0 : sprintf(page,
+ "%8u %8u %8llu %8u "
+ "%8u %8u %8llu %8u "
+ "%8u %8u %8u"
+ "\n",
+ disk->reads, disk->read_merges, (u64)disk->read_sectors,
+ MSEC(disk->read_ticks),
+ disk->writes, disk->write_merges, (u64)disk->write_sectors,
+ MSEC(disk->write_ticks),
+ disk->in_flight, MSEC(disk->io_ticks),
+ MSEC(disk->time_in_queue));
+}
+static struct disk_attribute disk_attr_dev = {
+ .attr = {.name = "dev", .mode = S_IRUGO },
+ .show = disk_dev_read
+};
+static struct disk_attribute disk_attr_range = {
+ .attr = {.name = "range", .mode = S_IRUGO },
+ .show = disk_range_read
+};
+static struct disk_attribute disk_attr_size = {
+ .attr = {.name = "size", .mode = S_IRUGO },
+ .show = disk_size_read
+};
+static struct disk_attribute disk_attr_stat = {
+ .attr = {.name = "stat", .mode = S_IRUGO },
+ .show = disk_stat_read
+};
-EXPORT_SYMBOL(disk_devclass);
+static struct attribute * default_attrs[] = {
+ &disk_attr_dev.attr,
+ &disk_attr_range.attr,
+ &disk_attr_size.attr,
+ &disk_attr_stat.attr,
+ NULL,
+};
-static void disk_release(struct device *dev)
+static void disk_release(struct kobject * kobj)
{
- struct gendisk *disk = dev->driver_data;
+ struct gendisk *disk = to_disk(kobj);
kfree(disk->random);
kfree(disk->part);
kfree(disk);
}
+struct subsystem block_subsys = {
+ .kobj = { .name = "block" },
+ .release = disk_release,
+ .sysfs_ops = &disk_sysfs_ops,
+ .default_attrs = default_attrs,
+};
+
struct gendisk *alloc_disk(int minors)
{
struct gendisk *disk = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
@@ -314,11 +401,9 @@ struct gendisk *alloc_disk(int minors)
disk->minors = minors;
while (minors >>= 1)
disk->minor_shift++;
+ kobject_init(&disk->kobj);
+ disk->kobj.subsys = &block_subsys;
INIT_LIST_HEAD(&disk->full_list);
- disk->disk_dev.bus = &disk_bus;
- disk->disk_dev.release = disk_release;
- disk->disk_dev.driver_data = disk;
- device_initialize(&disk->disk_dev);
}
rand_initialize_disk(disk);
return disk;
@@ -332,14 +417,13 @@ struct gendisk *get_disk(struct gendisk *disk)
owner = disk->fops->owner;
if (owner && !try_inc_mod_count(owner))
return NULL;
- atomic_inc(&disk->disk_dev.refcount);
- return disk;
+ return to_disk(kobject_get(&disk->kobj));
}
void put_disk(struct gendisk *disk)
{
if (disk)
- put_device(&disk->disk_dev);
+ kobject_put(&disk->kobj);
}
EXPORT_SYMBOL(alloc_disk);
diff --git a/fs/Makefile b/fs/Makefile
index 38aa365a53c5..1a61b1b42cc2 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -41,7 +41,7 @@ obj-$(CONFIG_QUOTACTL) += quota.o
obj-$(CONFIG_PROC_FS) += proc/
obj-y += partitions/
-obj-y += driverfs/ sysfs/
+obj-y += sysfs/
obj-y += devpts/
obj-$(CONFIG_PROFILING) += dcookies.o
diff --git a/fs/driverfs/Makefile b/fs/driverfs/Makefile
deleted file mode 100644
index 43c770cee388..000000000000
--- a/fs/driverfs/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-#
-# Makefile for the driverfs virtual filesystem.
-#
-
-export-objs := inode.o
-
-obj-y := inode.o
-
-include $(TOPDIR)/Rules.make
diff --git a/fs/driverfs/inode.c b/fs/driverfs/inode.c
deleted file mode 100644
index b4b5aa9f6a55..000000000000
--- a/fs/driverfs/inode.c
+++ /dev/null
@@ -1,708 +0,0 @@
-/*
- * driverfs.c - The device driver file system
- *
- * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * This is a simple, ram-based filesystem, which allows kernel
- * callbacks for read/write of files.
- *
- * Please see Documentation/filesystems/driverfs.txt for more information.
- */
-
-#include <linux/list.h>
-#include <linux/init.h>
-#include <linux/pagemap.h>
-#include <linux/stat.h>
-#include <linux/fs.h>
-#include <linux/dcache.h>
-#include <linux/namei.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/backing-dev.h>
-#include <linux/driverfs_fs.h>
-
-#include <asm/uaccess.h>
-
-#undef DEBUG
-
-#ifdef DEBUG
-# define DBG(x...) printk(x)
-#else
-# define DBG(x...)
-#endif
-
-/* Random magic number */
-#define DRIVERFS_MAGIC 0x42454552
-
-static struct super_operations driverfs_ops;
-static struct file_operations driverfs_file_operations;
-static struct inode_operations driverfs_dir_inode_operations;
-static struct address_space_operations driverfs_aops;
-
-static struct vfsmount *driverfs_mount;
-static spinlock_t mount_lock = SPIN_LOCK_UNLOCKED;
-static int mount_count = 0;
-
-static struct backing_dev_info driverfs_backing_dev_info = {
- .ra_pages = 0, /* No readahead */
- .memory_backed = 1, /* Does not contribute to dirty memory */
-};
-
-static int driverfs_readpage(struct file *file, struct page * page)
-{
- if (!PageUptodate(page)) {
- void *kaddr = kmap_atomic(page, KM_USER0);
-
- memset(kaddr, 0, PAGE_CACHE_SIZE);
- flush_dcache_page(page);
- kunmap_atomic(kaddr, KM_USER0);
- SetPageUptodate(page);
- }
- unlock_page(page);
- return 0;
-}
-
-static int driverfs_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
-{
- if (!PageUptodate(page)) {
- void *kaddr = kmap_atomic(page, KM_USER0);
-
- memset(kaddr, 0, PAGE_CACHE_SIZE);
- flush_dcache_page(page);
- kunmap_atomic(kaddr, KM_USER0);
- SetPageUptodate(page);
- }
- return 0;
-}
-
-static int driverfs_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
-{
- struct inode *inode = page->mapping->host;
- loff_t pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + to;
-
- set_page_dirty(page);
- if (pos > inode->i_size)
- inode->i_size = pos;
- return 0;
-}
-
-
-struct inode *driverfs_get_inode(struct super_block *sb, int mode, int dev)
-{
- struct inode *inode = new_inode(sb);
-
- if (inode) {
- inode->i_mode = mode;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
- inode->i_blksize = PAGE_CACHE_SIZE;
- inode->i_blocks = 0;
- inode->i_rdev = NODEV;
- inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
- inode->i_mapping->a_ops = &driverfs_aops;
- inode->i_mapping->backing_dev_info = &driverfs_backing_dev_info;
- switch (mode & S_IFMT) {
- default:
- init_special_inode(inode, mode, dev);
- break;
- case S_IFREG:
- inode->i_fop = &driverfs_file_operations;
- break;
- case S_IFDIR:
- inode->i_op = &driverfs_dir_inode_operations;
- inode->i_fop = &simple_dir_operations;
-
- /* directory inodes start off with i_nlink == 2 (for "." entry) */
- inode->i_nlink++;
- break;
- case S_IFLNK:
- inode->i_op = &page_symlink_inode_operations;
- break;
- }
- }
- return inode;
-}
-
-static int driverfs_mknod(struct inode *dir, struct dentry *dentry, int mode, int dev)
-{
- struct inode *inode;
- int error = -ENOSPC;
-
- if (dentry->d_inode)
- return -EEXIST;
-
- /* only allow create if ->d_fsdata is not NULL (so we can assume it
- * comes from the driverfs API below. */
- inode = driverfs_get_inode(dir->i_sb, mode, dev);
- if (inode) {
- d_instantiate(dentry, inode);
- error = 0;
- }
- return error;
-}
-
-static int driverfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
- int res;
- mode = (mode & (S_IRWXUGO|S_ISVTX)) | S_IFDIR;
- res = driverfs_mknod(dir, dentry, mode, 0);
- if (!res)
- dir->i_nlink++;
- return res;
-}
-
-static int driverfs_create(struct inode *dir, struct dentry *dentry, int mode)
-{
- int res;
- mode = (mode & S_IALLUGO) | S_IFREG;
- res = driverfs_mknod(dir, dentry, mode, 0);
- return res;
-}
-
-static int driverfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
-{
- struct inode *inode;
- int error = -ENOSPC;
-
- if (dentry->d_inode)
- return -EEXIST;
-
- inode = driverfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
- if (inode) {
- int l = strlen(symname)+1;
- error = page_symlink(inode, symname, l);
- if (!error) {
- d_instantiate(dentry, inode);
- dget(dentry);
- } else
- iput(inode);
- }
- return error;
-}
-
-static inline int driverfs_positive(struct dentry *dentry)
-{
- return (dentry->d_inode && !d_unhashed(dentry));
-}
-
-static int driverfs_empty(struct dentry *dentry)
-{
- struct list_head *list;
-
- spin_lock(&dcache_lock);
-
- list_for_each(list, &dentry->d_subdirs) {
- struct dentry *de = list_entry(list, struct dentry, d_child);
- if (driverfs_positive(de)) {
- spin_unlock(&dcache_lock);
- return 0;
- }
- }
-
- spin_unlock(&dcache_lock);
- return 1;
-}
-
-static int driverfs_unlink(struct inode *dir, struct dentry *dentry)
-{
- struct inode *inode = dentry->d_inode;
- down(&inode->i_sem);
- dentry->d_inode->i_nlink--;
- up(&inode->i_sem);
- d_invalidate(dentry);
- dput(dentry);
- return 0;
-}
-
-/**
- * driverfs_read_file - "read" data from a file.
- * @file: file pointer
- * @buf: buffer to fill
- * @count: number of bytes to read
- * @ppos: starting offset in file
- *
- * Userspace wants data from a file. It is up to the creator of the file to
- * provide that data.
- * There is a struct device_attribute embedded in file->private_data. We
- * obtain that and check if the read callback is implemented. If so, we call
- * it, passing the data field of the file entry.
- * Said callback is responsible for filling the buffer and returning the number
- * of bytes it put in it. We update @ppos correctly.
- */
-static ssize_t
-driverfs_read_file(struct file *file, char *buf, size_t count, loff_t *ppos)
-{
- struct attribute * attr = file->f_dentry->d_fsdata;
- struct driver_dir_entry * dir;
- unsigned char *page;
- ssize_t retval = 0;
-
- dir = file->f_dentry->d_parent->d_fsdata;
- if (!dir->ops->show)
- return 0;
-
- if (count > PAGE_SIZE)
- count = PAGE_SIZE;
-
- page = (unsigned char*)__get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- while (count > 0) {
- ssize_t len;
-
- len = dir->ops->show(dir,attr,page,count,*ppos);
-
- if (len <= 0) {
- if (len < 0)
- retval = len;
- break;
- } else if (len > count)
- len = count;
-
- if (copy_to_user(buf,page,len)) {
- retval = -EFAULT;
- break;
- }
-
- *ppos += len;
- count -= len;
- buf += len;
- retval += len;
- }
- free_page((unsigned long)page);
- return retval;
-}
-
-/**
- * driverfs_write_file - "write" to a file
- * @file: file pointer
- * @buf: data to write
- * @count: number of bytes
- * @ppos: starting offset
- *
- * Similarly to driverfs_read_file, we act essentially as a bit pipe.
- * We check for a "write" callback in file->private_data, and pass
- * @buffer, @count, @ppos, and the file entry's data to the callback.
- * The number of bytes written is returned, and we handle updating
- * @ppos properly.
- */
-static ssize_t
-driverfs_write_file(struct file *file, const char *buf, size_t count, loff_t *ppos)
-{
- struct attribute * attr = file->f_dentry->d_fsdata;
- struct driver_dir_entry * dir;
- ssize_t retval = 0;
- char * page;
-
- dir = file->f_dentry->d_parent->d_fsdata;
-
- page = (char *)__get_free_page(GFP_KERNEL);
- if (!page)
- return -ENOMEM;
-
- if (count >= PAGE_SIZE)
- count = PAGE_SIZE - 1;
- if (copy_from_user(page,buf,count))
- goto done;
- *(page + count) = '\0';
-
- while (count > 0) {
- ssize_t len;
-
- len = dir->ops->store(dir,attr,page + retval,count,*ppos);
-
- if (len <= 0) {
- if (len < 0)
- retval = len;
- break;
- }
- retval += len;
- count -= len;
- *ppos += len;
- buf += len;
- }
- done:
- free_page((unsigned long)page);
- return retval;
-}
-
-static loff_t
-driverfs_file_lseek(struct file *file, loff_t offset, int orig)
-{
- loff_t retval = -EINVAL;
-
- down(&file->f_dentry->d_inode->i_sem);
- switch(orig) {
- case 0:
- if (offset > 0) {
- file->f_pos = offset;
- retval = file->f_pos;
- }
- break;
- case 1:
- if ((offset + file->f_pos) > 0) {
- file->f_pos += offset;
- retval = file->f_pos;
- }
- break;
- default:
- break;
- }
- up(&file->f_dentry->d_inode->i_sem);
- return retval;
-}
-
-static int driverfs_open_file(struct inode * inode, struct file * filp)
-{
- struct driver_dir_entry * dir;
- int error = 0;
-
- dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata;
- if (dir) {
- struct attribute * attr = filp->f_dentry->d_fsdata;
- if (attr && dir->ops) {
- if (dir->ops->open)
- error = dir->ops->open(dir);
- goto Done;
- }
- }
- error = -EINVAL;
- Done:
- return error;
-}
-
-static int driverfs_release(struct inode * inode, struct file * filp)
-{
- struct driver_dir_entry * dir;
- dir = (struct driver_dir_entry *)filp->f_dentry->d_parent->d_fsdata;
- if (dir->ops->close)
- dir->ops->close(dir);
- return 0;
-}
-
-static struct file_operations driverfs_file_operations = {
- .read = driverfs_read_file,
- .write = driverfs_write_file,
- .llseek = driverfs_file_lseek,
- .open = driverfs_open_file,
- .release = driverfs_release,
-};
-
-static struct inode_operations driverfs_dir_inode_operations = {
- .lookup = simple_lookup,
-};
-
-static struct address_space_operations driverfs_aops = {
- .readpage = driverfs_readpage,
- .writepage = fail_writepage,
- .prepare_write = driverfs_prepare_write,
- .commit_write = driverfs_commit_write
-};
-
-static struct super_operations driverfs_ops = {
- .statfs = simple_statfs,
- .drop_inode = generic_delete_inode,
-};
-
-static int driverfs_fill_super(struct super_block *sb, void *data, int silent)
-{
- struct inode *inode;
- struct dentry *root;
-
- sb->s_blocksize = PAGE_CACHE_SIZE;
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
- sb->s_magic = DRIVERFS_MAGIC;
- sb->s_op = &driverfs_ops;
- inode = driverfs_get_inode(sb, S_IFDIR | 0755, 0);
-
- if (!inode) {
- DBG("%s: could not get inode!\n",__FUNCTION__);
- return -ENOMEM;
- }
-
- root = d_alloc_root(inode);
- if (!root) {
- DBG("%s: could not get root dentry!\n",__FUNCTION__);
- iput(inode);
- return -ENOMEM;
- }
- sb->s_root = root;
- return 0;
-}
-
-static struct super_block *driverfs_get_sb(struct file_system_type *fs_type,
- int flags, char *dev_name, void *data)
-{
- return get_sb_single(fs_type, flags, data, driverfs_fill_super);
-}
-
-static struct file_system_type driverfs_fs_type = {
- .owner = THIS_MODULE,
- .name = "driverfs",
- .get_sb = driverfs_get_sb,
- .kill_sb = kill_litter_super,
-};
-
-static int get_mount(void)
-{
- struct vfsmount * mnt;
-
- spin_lock(&mount_lock);
- if (driverfs_mount) {
- mntget(driverfs_mount);
- ++mount_count;
- spin_unlock(&mount_lock);
- goto go_ahead;
- }
-
- spin_unlock(&mount_lock);
- mnt = kern_mount(&driverfs_fs_type);
-
- if (IS_ERR(mnt)) {
- printk(KERN_ERR "driverfs: could not mount!\n");
- return -ENODEV;
- }
-
- spin_lock(&mount_lock);
- if (!driverfs_mount) {
- driverfs_mount = mnt;
- ++mount_count;
- spin_unlock(&mount_lock);
- goto go_ahead;
- }
-
- mntget(driverfs_mount);
- ++mount_count;
- spin_unlock(&mount_lock);
-
- go_ahead:
- DBG("driverfs: mount_count = %d\n",mount_count);
- return 0;
-}
-
-static void put_mount(void)
-{
- struct vfsmount * mnt;
-
- spin_lock(&mount_lock);
- mnt = driverfs_mount;
- --mount_count;
- if (!mount_count)
- driverfs_mount = NULL;
- spin_unlock(&mount_lock);
- mntput(mnt);
- DBG("driverfs: mount_count = %d\n",mount_count);
-}
-
-static int __init driverfs_init(void)
-{
- return register_filesystem(&driverfs_fs_type);
-}
-
-core_initcall(driverfs_init);
-
-static struct dentry * get_dentry(struct dentry * parent, const char * name)
-{
- struct qstr qstr;
-
- qstr.name = name;
- qstr.len = strlen(name);
- qstr.hash = full_name_hash(name,qstr.len);
- return lookup_hash(&qstr,parent);
-}
-
-/**
- * driverfs_create_dir - create a directory in the filesystem
- * @entry: directory entry
- * @parent: parent directory entry
- */
-int
-driverfs_create_dir(struct driver_dir_entry * entry,
- struct driver_dir_entry * parent)
-{
- struct dentry * dentry = NULL;
- struct dentry * parent_dentry;
- int error = 0;
-
- if (!entry)
- return -EINVAL;
-
- get_mount();
-
- parent_dentry = parent ? parent->dentry : NULL;
-
- if (!parent_dentry)
- if (driverfs_mount && driverfs_mount->mnt_sb)
- parent_dentry = driverfs_mount->mnt_sb->s_root;
-
- if (!parent_dentry) {
- put_mount();
- return -EFAULT;
- }
-
- down(&parent_dentry->d_inode->i_sem);
- dentry = get_dentry(parent_dentry,entry->name);
- if (!IS_ERR(dentry)) {
- dentry->d_fsdata = (void *) entry;
- entry->dentry = dentry;
- error = driverfs_mkdir(parent_dentry->d_inode,dentry,entry->mode);
- } else
- error = PTR_ERR(dentry);
- up(&parent_dentry->d_inode->i_sem);
-
- if (error)
- put_mount();
- return error;
-}
-
-/**
- * driverfs_create_file - create a file
- * @entry: structure describing the file
- * @parent: directory to create it in
- */
-int
-driverfs_create_file(struct attribute * entry,
- struct driver_dir_entry * parent)
-{
- struct dentry * dentry;
- int error = 0;
-
- if (!entry || !parent)
- return -EINVAL;
-
- if (!parent->dentry) {
- put_mount();
- return -EINVAL;
- }
-
- down(&parent->dentry->d_inode->i_sem);
- dentry = get_dentry(parent->dentry,entry->name);
- if (!IS_ERR(dentry)) {
- dentry->d_fsdata = (void *)entry;
- error = driverfs_create(parent->dentry->d_inode,dentry,entry->mode);
- } else
- error = PTR_ERR(dentry);
- up(&parent->dentry->d_inode->i_sem);
- return error;
-}
-
-/**
- * driverfs_create_symlink - make a symlink
- * @parent: directory we're creating in
- * @entry: entry describing link
- * @target: place we're symlinking to
- *
- */
-int driverfs_create_symlink(struct driver_dir_entry * parent,
- char * name, char * target)
-{
- struct dentry * dentry;
- int error = 0;
-
- if (!parent)
- return -EINVAL;
-
- if (!parent->dentry) {
- put_mount();
- return -EINVAL;
- }
- down(&parent->dentry->d_inode->i_sem);
- dentry = get_dentry(parent->dentry,name);
- if (!IS_ERR(dentry))
- error = driverfs_symlink(parent->dentry->d_inode,dentry,target);
- else
- error = PTR_ERR(dentry);
- up(&parent->dentry->d_inode->i_sem);
- return error;
-}
-
-/**
- * driverfs_remove_file - exported file removal
- * @dir: directory the file supposedly resides in
- * @name: name of the file
- *
- * Try and find the file in the dir's list.
- * If it's there, call __remove_file() (above) for the dentry.
- */
-void driverfs_remove_file(struct driver_dir_entry * dir, const char * name)
-{
- struct dentry * dentry;
-
- if (!dir->dentry)
- return;
-
- down(&dir->dentry->d_inode->i_sem);
- dentry = get_dentry(dir->dentry,name);
- if (!IS_ERR(dentry)) {
- /* make sure dentry is really there */
- if (dentry->d_inode &&
- (dentry->d_parent->d_inode == dir->dentry->d_inode)) {
- driverfs_unlink(dir->dentry->d_inode,dentry);
- }
- }
- up(&dir->dentry->d_inode->i_sem);
-}
-
-/**
- * driverfs_remove_dir - exportable directory removal
- * @dir: directory to remove
- *
- * To make sure we don't orphan anyone, first remove
- * all the children in the list, then do clean up the directory.
- */
-void driverfs_remove_dir(struct driver_dir_entry * dir)
-{
- struct list_head * node, * next;
- struct dentry * dentry = dir->dentry;
- struct dentry * parent;
-
- if (!dentry)
- goto done;
-
- parent = dget(dentry->d_parent);
- down(&parent->d_inode->i_sem);
- down(&dentry->d_inode->i_sem);
-
- list_for_each_safe(node,next,&dentry->d_subdirs) {
- struct dentry * d = list_entry(node,struct dentry,d_child);
- /* make sure dentry is still there */
- if (d->d_inode)
- driverfs_unlink(dentry->d_inode,d);
- }
-
- d_invalidate(dentry);
- if (driverfs_empty(dentry)) {
- dentry->d_inode->i_nlink -= 2;
- dentry->d_inode->i_flags |= S_DEAD;
- parent->d_inode->i_nlink--;
- }
- up(&dentry->d_inode->i_sem);
- dput(dentry);
-
- up(&parent->d_inode->i_sem);
- dput(parent);
- done:
- put_mount();
-}
-
-EXPORT_SYMBOL(driverfs_create_file);
-EXPORT_SYMBOL(driverfs_create_symlink);
-EXPORT_SYMBOL(driverfs_create_dir);
-EXPORT_SYMBOL(driverfs_remove_file);
-EXPORT_SYMBOL(driverfs_remove_dir);
-MODULE_LICENSE("GPL");
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 068559518ba5..a414496bf6cf 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -277,231 +277,147 @@ static void devfs_remove_partitions(struct gendisk *dev)
#endif
}
-static ssize_t part_dev_read(struct device *dev,
- char *page, size_t count, loff_t off)
+
+/*
+ * sysfs bindings for partitions
+ */
+
+struct part_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct hd_struct *,char *,size_t,loff_t);
+};
+
+static ssize_t part_attr_show(struct kobject * kobj, struct attribute * attr,
+ char * page, size_t count, loff_t off)
+{
+ struct hd_struct * p = container_of(kobj,struct hd_struct,kobj);
+ struct part_attribute * part_attr = container_of(attr,struct part_attribute,attr);
+ ssize_t ret = 0;
+ if (part_attr->show)
+ part_attr->show(p,page,count,off);
+ return ret;
+}
+
+static struct sysfs_ops part_sysfs_ops = {
+ .show part_attr_show,
+};
+
+static ssize_t part_dev_read(struct hd_struct * p,
+ char *page, size_t count, loff_t off)
{
- struct gendisk *disk = dev->parent->driver_data;
- struct hd_struct *p = dev->driver_data;
+ struct gendisk *disk = container_of(p->kobj.parent,struct gendisk,kobj);
int part = p - disk->part + 1;
dev_t base = MKDEV(disk->major, disk->first_minor);
return off ? 0 : sprintf(page, "%04x\n",base + part);
}
-static ssize_t part_start_read(struct device *dev,
- char *page, size_t count, loff_t off)
+static ssize_t part_start_read(struct hd_struct * p,
+ char *page, size_t count, loff_t off)
{
- struct hd_struct *p = dev->driver_data;
return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)p->start_sect);
}
-static ssize_t part_size_read(struct device *dev,
- char *page, size_t count, loff_t off)
+static ssize_t part_size_read(struct hd_struct * p,
+ char *page, size_t count, loff_t off)
{
- struct hd_struct *p = dev->driver_data;
return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)p->nr_sects);
}
-static ssize_t part_stat_read(struct device *dev,
- char *page, size_t count, loff_t off)
+static ssize_t part_stat_read(struct hd_struct * p,
+ char *page, size_t count, loff_t off)
{
- struct hd_struct *p = dev->driver_data;
return off ? 0 : sprintf(page, "%8u %8llu %8u %8llu\n",
p->reads, (u64)p->read_sectors,
p->writes, (u64)p->write_sectors);
}
-static struct device_attribute part_attr_dev = {
+static struct part_attribute part_attr_dev = {
.attr = {.name = "dev", .mode = S_IRUGO },
.show = part_dev_read
};
-static struct device_attribute part_attr_start = {
+static struct part_attribute part_attr_start = {
.attr = {.name = "start", .mode = S_IRUGO },
.show = part_start_read
};
-static struct device_attribute part_attr_size = {
+static struct part_attribute part_attr_size = {
.attr = {.name = "size", .mode = S_IRUGO },
.show = part_size_read
};
-static struct device_attribute part_attr_stat = {
+static struct part_attribute part_attr_stat = {
.attr = {.name = "stat", .mode = S_IRUGO },
.show = part_stat_read
};
+static struct attribute * default_attrs[] = {
+ &part_attr_dev.attr,
+ &part_attr_start.attr,
+ &part_attr_size.attr,
+ &part_attr_stat.attr,
+ NULL,
+};
+
+extern struct subsystem block_subsys;
+
+static struct subsystem part_subsys = {
+ .kobj = { .name = "part" },
+ .parent = &block_subsys,
+ .default_attrs = default_attrs,
+ .sysfs_ops = &part_sysfs_ops,
+};
+
+static int __init part_subsys_init(void)
+{
+ return subsystem_register(&part_subsys);
+}
+
+__initcall(part_subsys_init);
+
void delete_partition(struct gendisk *disk, int part)
{
struct hd_struct *p = disk->part + part - 1;
- struct device *dev;
if (!p->nr_sects)
return;
p->start_sect = 0;
p->nr_sects = 0;
p->reads = p->writes = p->read_sectors = p->write_sectors = 0;
devfs_unregister(p->de);
- dev = p->hd_driverfs_dev;
- p->hd_driverfs_dev = NULL;
- if (dev) {
- device_remove_file(dev, &part_attr_stat);
- device_remove_file(dev, &part_attr_size);
- device_remove_file(dev, &part_attr_start);
- device_remove_file(dev, &part_attr_dev);
- device_unregister(dev);
- }
-}
-
-static void part_release(struct device *dev)
-{
- kfree(dev);
+ kobject_unregister(&p->kobj);
}
void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len)
{
struct hd_struct *p = disk->part + part - 1;
- struct device *parent = &disk->disk_dev;
- struct device *dev;
p->start_sect = start;
p->nr_sects = len;
devfs_register_partition(disk, part);
- dev = kmalloc(sizeof(struct device), GFP_KERNEL);
- if (!dev)
- return;
- memset(dev, 0, sizeof(struct device));
- dev->parent = parent;
- sprintf(dev->bus_id, "p%d", part);
- dev->release = part_release;
- dev->driver_data = p;
- device_register(dev);
- device_create_file(dev, &part_attr_dev);
- device_create_file(dev, &part_attr_start);
- device_create_file(dev, &part_attr_size);
- device_create_file(dev, &part_attr_stat);
- p->hd_driverfs_dev = dev;
+ kobject_init(&p->kobj);
+ snprintf(p->kobj.name,KOBJ_NAME_LEN,"%s%d",disk->disk_name,part);
+ p->kobj.parent = &disk->kobj;
+ p->kobj.subsys = &part_subsys;
+ kobject_register(&p->kobj);
}
-static ssize_t disk_dev_read(struct device *dev,
- char *page, size_t count, loff_t off)
-{
- struct gendisk *disk = dev->driver_data;
- dev_t base = MKDEV(disk->major, disk->first_minor);
- return off ? 0 : sprintf(page, "%04x\n",base);
-}
-static ssize_t disk_range_read(struct device *dev,
- char *page, size_t count, loff_t off)
-{
- struct gendisk *disk = dev->driver_data;
- return off ? 0 : sprintf(page, "%d\n",disk->minors);
-}
-static ssize_t disk_size_read(struct device *dev,
- char *page, size_t count, loff_t off)
-{
- struct gendisk *disk = dev->driver_data;
- return off ? 0 : sprintf(page, "%llu\n",(unsigned long long)get_capacity(disk));
-}
-static inline unsigned MSEC(unsigned x)
+static void disk_sysfs_symlinks(struct gendisk *disk)
{
- return x * 1000 / HZ;
-}
-static ssize_t disk_stat_read(struct device *dev,
- char *page, size_t count, loff_t off)
-{
- struct gendisk *disk = dev->driver_data;
- disk_round_stats(disk);
- return off ? 0 : sprintf(page,
- "%8u %8u %8llu %8u "
- "%8u %8u %8llu %8u "
- "%8u %8u %8u"
- "\n",
- disk->reads, disk->read_merges, (u64)disk->read_sectors,
- MSEC(disk->read_ticks),
- disk->writes, disk->write_merges, (u64)disk->write_sectors,
- MSEC(disk->write_ticks),
- disk->in_flight, MSEC(disk->io_ticks),
- MSEC(disk->time_in_queue));
-}
-static struct device_attribute disk_attr_dev = {
- .attr = {.name = "dev", .mode = S_IRUGO },
- .show = disk_dev_read
-};
-static struct device_attribute disk_attr_range = {
- .attr = {.name = "range", .mode = S_IRUGO },
- .show = disk_range_read
-};
-static struct device_attribute disk_attr_size = {
- .attr = {.name = "size", .mode = S_IRUGO },
- .show = disk_size_read
-};
-static struct device_attribute disk_attr_stat = {
- .attr = {.name = "stat", .mode = S_IRUGO },
- .show = disk_stat_read
-};
-
-static void disk_driverfs_symlinks(struct gendisk *disk)
-{
- struct device *target = disk->driverfs_dev;
- struct device *dev = &disk->disk_dev;
- struct device *p;
- char *path;
- char *s;
- int length;
- int depth;
-
- if (!target)
- return;
-
- get_device(target);
-
- length = get_devpath_length(target);
- length += strlen("..");
-
- if (length > PATH_MAX)
- return;
-
- if (!(path = kmalloc(length,GFP_KERNEL)))
- return;
- memset(path,0,length);
-
- /* our relative position */
- strcpy(path,"..");
-
- fill_devpath(target, path, length);
- driverfs_create_symlink(&dev->dir, "device", path);
- kfree(path);
-
- for (p = target, depth = 0; p; p = p->parent, depth++)
- ;
- length = get_devpath_length(dev);
- length += 3 * depth - 1;
-
- if (length > PATH_MAX)
- return;
-
- if (!(path = kmalloc(length,GFP_KERNEL)))
- return;
- memset(path,0,length);
- for (s = path; depth--; s += 3)
- strcpy(s, "../");
-
- fill_devpath(dev, path, length);
- driverfs_create_symlink(&target->dir, "block", path);
- kfree(path);
+ struct device *target = get_device(disk->driverfs_dev);
+ if (target) {
+ sysfs_create_link(&disk->kobj,&target->kobj,"device");
+ sysfs_create_link(&target->kobj,&disk->kobj,"block");
+ }
}
/* Not exported, helper to add_disk(). */
void register_disk(struct gendisk *disk)
{
- struct device *dev = &disk->disk_dev;
struct parsed_partitions *state;
struct block_device *bdev;
char *s;
int j;
- strcpy(dev->bus_id, disk->disk_name);
+ strncpy(disk->kobj.name,disk->disk_name,KOBJ_NAME_LEN);
/* ewww... some of these buggers have / in name... */
- s = strchr(dev->bus_id, '/');
+ s = strchr(disk->kobj.name, '/');
if (s)
*s = '!';
- device_add(dev);
- device_create_file(dev, &disk_attr_dev);
- device_create_file(dev, &disk_attr_range);
- device_create_file(dev, &disk_attr_size);
- device_create_file(dev, &disk_attr_stat);
- disk_driverfs_symlinks(disk);
+ kobject_register(&disk->kobj);
+ disk_sysfs_symlinks(disk);
if (disk->flags & GENHD_FL_CD)
devfs_create_cdrom(disk);
@@ -620,16 +536,12 @@ void del_gendisk(struct gendisk *disk)
disk->time_in_queue = 0;
disk->stamp = disk->stamp_idle = 0;
devfs_remove_partitions(disk);
- device_remove_file(&disk->disk_dev, &disk_attr_dev);
- device_remove_file(&disk->disk_dev, &disk_attr_range);
- device_remove_file(&disk->disk_dev, &disk_attr_size);
- device_remove_file(&disk->disk_dev, &disk_attr_stat);
- driverfs_remove_file(&disk->disk_dev.dir, "device");
+ kobject_unregister(&disk->kobj);
+ sysfs_remove_link(&disk->kobj, "device");
if (disk->driverfs_dev) {
- driverfs_remove_file(&disk->driverfs_dev->dir, "block");
+ sysfs_remove_link(&disk->driverfs_dev->kobj, "block");
put_device(disk->driverfs_dev);
}
- device_del(&disk->disk_dev);
}
struct dev_name {
@@ -680,3 +592,4 @@ char *partition_name(dev_t dev)
return dname->name;
}
+
diff --git a/include/linux/device.h b/include/linux/device.h
index 2e0948e96d68..0bea391871ae 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -28,7 +28,7 @@
#include <linux/ioport.h>
#include <linux/list.h>
#include <linux/sched.h>
-#include <linux/driverfs_fs.h>
+#include <linux/kobject.h>
#define DEVICE_NAME_SIZE 80
#define DEVICE_ID_SIZE 32
@@ -65,14 +65,13 @@ struct bus_type {
atomic_t refcount;
u32 present;
+ struct subsystem subsys;
+ struct subsystem drvsubsys;
+ struct subsystem devsubsys;
struct list_head node;
struct list_head devices;
struct list_head drivers;
- struct driver_dir_entry dir;
- struct driver_dir_entry device_dir;
- struct driver_dir_entry driver_dir;
-
int (*match)(struct device * dev, struct device_driver * drv);
struct device * (*add) (struct device * parent, char * bus_id);
int (*hotplug) (struct device *dev, char **envp,
@@ -119,12 +118,11 @@ struct device_driver {
atomic_t refcount;
u32 present;
+ struct kobject kobj;
struct list_head bus_list;
struct list_head class_list;
struct list_head devices;
- struct driver_dir_entry dir;
-
int (*probe) (struct device * dev);
int (*remove) (struct device * dev);
void (*shutdown) (struct device * dev);
@@ -177,14 +175,13 @@ struct device_class {
u32 devnum;
+ struct subsystem subsys;
+ struct subsystem devsubsys;
+ struct subsystem drvsubsys;
struct list_head node;
struct list_head drivers;
struct list_head intf_list;
- struct driver_dir_entry dir;
- struct driver_dir_entry driver_dir;
- struct driver_dir_entry device_dir;
-
int (*add_device)(struct device *);
void (*remove_device)(struct device *);
int (*hotplug)(struct device *dev, char **envp,
@@ -232,9 +229,9 @@ struct device_interface {
char * name;
struct device_class * devclass;
+ struct kobject kobj;
struct list_head node;
struct list_head devices;
- struct driver_dir_entry dir;
u32 devnum;
@@ -275,6 +272,7 @@ struct device {
struct list_head intf_list;
struct device * parent;
+ struct kobject kobj;
char name[DEVICE_NAME_SIZE]; /* descriptive ascii string */
char bus_id[BUS_ID_SIZE]; /* position on parent bus */
@@ -285,8 +283,6 @@ struct device {
* persists for the right amount of time */
struct bus_type * bus; /* type of bus device is on */
- struct driver_dir_entry dir;
-
struct device_driver *driver; /* which driver has allocated this
device */
void *driver_data; /* data private to the driver */
@@ -438,6 +434,11 @@ extern int device_suspend(u32 state, u32 level);
extern void device_resume(u32 level);
extern void device_shutdown(void);
+
+/* drivrs/base/firmware.c */
+extern int firmware_register(struct subsystem *);
+extern void firmware_uregister(struct subsystem *);
+
/* debugging and troubleshooting/diagnostic helpers. */
#ifdef DEBUG
#define dev_dbg(dev, format, arg...) \
diff --git a/include/linux/driverfs_fs.h b/include/linux/driverfs_fs.h
deleted file mode 100644
index b4270e947a1e..000000000000
--- a/include/linux/driverfs_fs.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * driverfs_fs.h - definitions for the device driver filesystem
- *
- * Copyright (c) 2001 Patrick Mochel <mochel@osdl.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * This is a simple, ram-based filesystem, which allows kernel
- * callbacks for read/write of files.
- *
- * Please see Documentation/filesystems/driverfs.txt for more information.
- */
-
-#ifndef _DRIVER_FS_H_
-#define _DRIVER_FS_H_
-
-struct driver_dir_entry;
-struct attribute;
-
-struct driverfs_ops {
- int (*open)(struct driver_dir_entry *);
- int (*close)(struct driver_dir_entry *);
- ssize_t (*show)(struct driver_dir_entry *, struct attribute *,char *, size_t, loff_t);
- ssize_t (*store)(struct driver_dir_entry *,struct attribute *,const char *, size_t, loff_t);
-};
-
-struct driver_dir_entry {
- char * name;
- struct dentry * dentry;
- mode_t mode;
- struct driverfs_ops * ops;
-};
-
-struct attribute {
- char * name;
- mode_t mode;
-};
-
-extern int
-driverfs_create_dir(struct driver_dir_entry *, struct driver_dir_entry *);
-
-extern void
-driverfs_remove_dir(struct driver_dir_entry * entry);
-
-extern int
-driverfs_create_file(struct attribute * attr,
- struct driver_dir_entry * parent);
-
-extern int
-driverfs_create_symlink(struct driver_dir_entry * parent,
- char * name, char * target);
-
-extern void
-driverfs_remove_file(struct driver_dir_entry *, const char * name);
-
-#endif /* _DDFS_H_ */
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index ff1885251c12..548e477daa4b 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -62,7 +62,7 @@ struct hd_struct {
sector_t start_sect;
sector_t nr_sects;
devfs_handle_t de; /* primary (master) devfs entry */
- struct device *hd_driverfs_dev; /* support driverfs hiearchy */
+ struct kobject kobj;
unsigned reads, read_sectors, writes, write_sectors;
int policy;
};
@@ -93,7 +93,7 @@ struct gendisk {
devfs_handle_t de; /* more of the same */
devfs_handle_t disk_de; /* piled higher and deeper */
struct device *driverfs_dev;
- struct device disk_dev;
+ struct kobject kobj;
struct timer_rand_state *random;
int policy;
@@ -130,8 +130,6 @@ static inline void set_capacity(struct gendisk *disk, sector_t size)
disk->capacity = size;
}
-extern struct device_class disk_devclass;
-
#endif /* __KERNEL__ */
#ifdef CONFIG_SOLARIS_X86_PARTITION
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index d2f0629a6189..40de16d0a227 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -12,8 +12,10 @@
#include <linux/rwsem.h>
#include <asm/atomic.h>
+#define KOBJ_NAME_LEN 16
+
struct kobject {
- char name[16];
+ char name[KOBJ_NAME_LEN];
atomic_t refcount;
struct list_head entry;
struct kobject * parent;
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index 7a46c9f0c308..29c3eb8d2c9e 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -9,20 +9,18 @@
#ifndef _SYSFS_H_
#define _SYSFS_H_
-struct driver_dir_entry;
-struct attribute;
struct kobject;
-struct sysfs_ops {
- ssize_t (*show)(struct kobject *, struct attribute *,char *, size_t, loff_t);
- ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t, loff_t);
-};
-
struct attribute {
char * name;
mode_t mode;
};
+struct sysfs_ops {
+ ssize_t (*show)(struct kobject *, struct attribute *,char *, size_t, loff_t);
+ ssize_t (*store)(struct kobject *,struct attribute *,const char *, size_t, loff_t);
+};
+
extern int
sysfs_create_dir(struct kobject *);
diff --git a/init/do_mounts.c b/init/do_mounts.c
index 2a8fb51550ca..040e8671d449 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -101,7 +101,7 @@ static __init dev_t try_name(char *name, int part)
/* read device number from .../dev */
- sprintf(path, "/sys/bus/block/devices/%s/dev", name);
+ sprintf(path, "/sys/block/%s/dev", name);
fd = open(path, 0, 0);
if (fd < 0)
goto fail;
@@ -119,7 +119,7 @@ static __init dev_t try_name(char *name, int part)
return res;
/* otherwise read range from .../range */
- sprintf(path, "/sys/bus/block/devices/%s/range", name);
+ sprintf(path, "/sys/block/%s/range", name);
fd = open(path, 0, 0);
if (fd < 0)
goto fail;
@@ -166,7 +166,7 @@ __init dev_t name_to_dev_t(char *name)
int part;
sys_mkdir("/sys", 0700);
- if (sys_mount("driverfs", "/sys", "driverfs", 0, NULL) < 0)
+ if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0)
goto out;
if (strncmp(name, "/dev/", 5) != 0) {