summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <greg@kroah.com>2004-07-14 03:00:00 -0700
committerGreg Kroah-Hartman <greg@kroah.com>2004-07-14 03:00:00 -0700
commit36208530bd9ed3758095549d77542ddd2f932bf0 (patch)
tree8a7703ac0095894567a6da5aa9c8b72445c95dfe
parent9e9c96deae089852ac33db3066be53b1060355ac (diff)
parent3b08aa6456c9046529ed38556b1950145eb7aa7a (diff)
Merge kroah.com:/home/greg/linux/BK/bleed-2.6
into kroah.com:/home/greg/linux/BK/driver-2.6
-rw-r--r--drivers/base/Kconfig2
-rw-r--r--drivers/base/bus.c39
-rw-r--r--drivers/base/core.c10
-rw-r--r--drivers/base/driver.c19
-rw-r--r--drivers/base/platform.c72
-rw-r--r--drivers/block/genhd.c11
-rw-r--r--drivers/char/raw.c15
-rw-r--r--drivers/pci/hotplug/rpaphp_vio.c9
-rw-r--r--include/linux/device.h4
-rw-r--r--lib/kobject.c7
-rw-r--r--security/root_plug.c6
11 files changed, 175 insertions, 19 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 99b633899211..c3ae0c59baa9 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -18,7 +18,7 @@ config FW_LOADER
the kernel tree does.
config DEBUG_DRIVER
- bool "Driver Core verbose debug messages"
+ bool "Driver Core verbose debug messages"
depends on DEBUG_KERNEL
help
Say Y here if you want the Driver core to produce a bunch of
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 02ff97df6dee..12701407bda3 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -415,7 +415,7 @@ static int device_add_attrs(struct bus_type * bus, struct device * dev)
static void device_remove_attrs(struct bus_type * bus, struct device * dev)
{
int i;
-
+
if (bus->dev_attrs) {
for (i = 0; attr_name(bus->dev_attrs[i]); i++)
device_remove_file(dev,&bus->dev_attrs[i]);
@@ -471,6 +471,37 @@ void bus_remove_device(struct device * dev)
}
}
+static int driver_add_attrs(struct bus_type * bus, struct device_driver * drv)
+{
+ int error = 0;
+ int i;
+
+ if (bus->drv_attrs) {
+ for (i = 0; attr_name(bus->drv_attrs[i]); i++) {
+ error = driver_create_file(drv, &bus->drv_attrs[i]);
+ if (error)
+ goto Err;
+ }
+ }
+ Done:
+ return error;
+ Err:
+ while (--i >= 0)
+ driver_remove_file(drv, &bus->drv_attrs[i]);
+ goto Done;
+}
+
+
+static void driver_remove_attrs(struct bus_type * bus, struct device_driver * drv)
+{
+ int i;
+
+ if (bus->drv_attrs) {
+ for (i = 0; attr_name(bus->drv_attrs[i]); i++)
+ driver_remove_file(drv, &bus->drv_attrs[i]);
+ }
+}
+
/**
* bus_add_driver - Add a driver to the bus.
@@ -499,6 +530,7 @@ int bus_add_driver(struct device_driver * drv)
driver_attach(drv);
up_write(&bus->subsys.rwsem);
+ driver_add_attrs(bus, drv);
}
return error;
}
@@ -516,6 +548,7 @@ int bus_add_driver(struct device_driver * drv)
void bus_remove_driver(struct device_driver * drv)
{
if (drv->bus) {
+ driver_remove_attrs(drv->bus, drv);
down_write(&drv->bus->subsys.rwsem);
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
driver_detach(drv);
@@ -574,6 +607,8 @@ void put_bus(struct bus_type * bus)
*
* Call kset_find_obj() to iterate over list of buses to
* find a bus by name. Return bus if found.
+ *
+ * Note that kset_find_obj increments bus' reference count.
*/
struct bus_type * find_bus(char * name)
@@ -610,7 +645,7 @@ static int bus_add_attrs(struct bus_type * bus)
static void bus_remove_attrs(struct bus_type * bus)
{
int i;
-
+
if (bus->bus_attrs) {
for (i = 0; attr_name(bus->bus_attrs[i]); i++)
bus_remove_file(bus,&bus->bus_attrs[i]);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 3325810c42ab..153cdc48bed7 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -378,6 +378,16 @@ int device_for_each_child(struct device * dev, void * data,
return error;
}
+/**
+ * device_find - locate device on a bus by name.
+ * @name: name of the device.
+ * @bus: bus to scan for the device.
+ *
+ * Call kset_find_obj() to iterate over list of devices on
+ * a bus to find device by name. Return device if found.
+ *
+ * Note that kset_find_obj increments device's reference count.
+ */
struct device *device_find(const char *name, struct bus_type *bus)
{
struct kobject *k = kset_find_obj(&bus->devices, name);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 0604b2b20e6f..735bd1702c40 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -111,10 +111,29 @@ void driver_unregister(struct device_driver * drv)
up(&drv->unload_sem);
}
+/**
+ * driver_find - locate driver on a bus by its name.
+ * @name: name of the driver.
+ * @bus: bus to scan for the driver.
+ *
+ * Call kset_find_obj() to iterate over list of drivers on
+ * a bus to find driver by name. Return driver if found.
+ *
+ * Note that kset_find_obj increments driver's reference count.
+ */
+struct device_driver *driver_find(const char *name, struct bus_type *bus)
+{
+ struct kobject *k = kset_find_obj(&bus->drivers, name);
+ if (k)
+ return to_drv(k);
+ return NULL;
+}
+
EXPORT_SYMBOL(driver_register);
EXPORT_SYMBOL(driver_unregister);
EXPORT_SYMBOL(get_driver);
EXPORT_SYMBOL(put_driver);
+EXPORT_SYMBOL(driver_find);
EXPORT_SYMBOL(driver_create_file);
EXPORT_SYMBOL(driver_remove_file);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 78fc67f26279..9f285ed4e29f 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/dma-mapping.h>
#include <linux/bootmem.h>
+#include <linux/err.h>
struct device platform_bus = {
.bus_id = "platform",
@@ -133,21 +134,87 @@ int platform_device_register(struct platform_device * pdev)
return ret;
}
+/**
+ * platform_device_unregister - remove a platform-level device
+ * @dev: platform device we're removing
+ *
+ * Note that this function will also release all memory- and port-based
+ * resources owned by the device (@dev->resource).
+ */
void platform_device_unregister(struct platform_device * pdev)
{
int i;
if (pdev) {
- device_unregister(&pdev->dev);
-
for (i = 0; i < pdev->num_resources; i++) {
struct resource *r = &pdev->resource[i];
if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO))
release_resource(r);
}
+
+ device_unregister(&pdev->dev);
}
}
+struct platform_object {
+ struct platform_device pdev;
+ struct resource resources[0];
+};
+
+static void platform_device_release_simple(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+
+ kfree(container_of(pdev, struct platform_object, pdev));
+}
+
+/**
+ * platform_device_register_simple
+ * @name: base name of the device we're adding
+ * @id: instance id
+ * @res: set of resources that needs to be allocated for the device
+ * @num: number of resources
+ *
+ * This function creates a simple platform device that requires minimal
+ * resource and memory management. Canned release function freeing
+ * memory allocated for the device allows drivers using such devices
+ * to be unloaded iwithout waiting for the last reference to the device
+ * to be dropped.
+ */
+struct platform_device *platform_device_register_simple(char *name, unsigned int id,
+ struct resource *res, unsigned int num)
+{
+ struct platform_object *pobj;
+ int retval;
+
+ pobj = kmalloc(sizeof(struct platform_object) + sizeof(struct resource) * num, GFP_KERNEL);
+ if (!pobj) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ memset(pobj, 0, sizeof(*pobj));
+ pobj->pdev.name = name;
+ pobj->pdev.id = id;
+ pobj->pdev.dev.release = platform_device_release_simple;
+
+ if (num) {
+ memcpy(pobj->resources, res, sizeof(struct resource) * num);
+ pobj->pdev.resource = pobj->resources;
+ pobj->pdev.num_resources = num;
+ }
+
+ retval = platform_device_register(&pobj->pdev);
+ if (retval)
+ goto error;
+
+ return &pobj->pdev;
+
+error:
+ kfree(pobj);
+ return ERR_PTR(retval);
+}
+
/**
* platform_match - bind platform device to platform driver.
@@ -237,6 +304,7 @@ EXPORT_SYMBOL(dma_get_required_mask);
EXPORT_SYMBOL(platform_bus);
EXPORT_SYMBOL(platform_bus_type);
EXPORT_SYMBOL(platform_device_register);
+EXPORT_SYMBOL(platform_device_register_simple);
EXPORT_SYMBOL(platform_device_unregister);
EXPORT_SYMBOL(platform_get_irq);
EXPORT_SYMBOL(platform_get_resource);
diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c
index 00a5bfa133b2..e82caa224d1f 100644
--- a/drivers/block/genhd.c
+++ b/drivers/block/genhd.c
@@ -352,6 +352,12 @@ static ssize_t disk_range_read(struct gendisk * disk, char *page)
{
return sprintf(page, "%d\n", disk->minors);
}
+static ssize_t disk_removable_read(struct gendisk * disk, char *page)
+{
+ return sprintf(page, "%d\n",
+ (disk->flags & GENHD_FL_REMOVABLE ? 1 : 0));
+
+}
static ssize_t disk_size_read(struct gendisk * disk, char *page)
{
return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk));
@@ -384,6 +390,10 @@ static struct disk_attribute disk_attr_range = {
.attr = {.name = "range", .mode = S_IRUGO },
.show = disk_range_read
};
+static struct disk_attribute disk_attr_removable = {
+ .attr = {.name = "removable", .mode = S_IRUGO },
+ .show = disk_removable_read
+};
static struct disk_attribute disk_attr_size = {
.attr = {.name = "size", .mode = S_IRUGO },
.show = disk_size_read
@@ -396,6 +406,7 @@ static struct disk_attribute disk_attr_stat = {
static struct attribute * default_attrs[] = {
&disk_attr_dev.attr,
&disk_attr_range.attr,
+ &disk_attr_removable.attr,
&disk_attr_size.attr,
&disk_attr_stat.attr,
NULL,
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index b416bdf57080..a2e33ec79615 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -125,11 +125,11 @@ raw_ioctl(struct inode *inode, struct file *filp,
return ioctl_by_bdev(bdev, command, arg);
}
-static void bind_device(struct raw_config_request rq)
+static void bind_device(struct raw_config_request *rq)
{
- class_simple_device_remove(MKDEV(RAW_MAJOR, rq.raw_minor));
- class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq.raw_minor),
- NULL, "raw%d", rq.raw_minor);
+ class_simple_device_remove(MKDEV(RAW_MAJOR, rq->raw_minor));
+ class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
+ NULL, "raw%d", rq->raw_minor);
}
/*
@@ -200,15 +200,16 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
if (rq.block_major == 0 && rq.block_minor == 0) {
/* unbind */
rawdev->binding = NULL;
- class_simple_device_remove(MKDEV(RAW_MAJOR, rq.raw_minor));
+ class_simple_device_remove(MKDEV(RAW_MAJOR,
+ rq.raw_minor));
} else {
rawdev->binding = bdget(dev);
if (rawdev->binding == NULL)
err = -ENOMEM;
else {
__module_get(THIS_MODULE);
- bind_device(rq);
- }
+ bind_device(&rq);
+ }
}
up(&raw_mutex);
} else {
diff --git a/drivers/pci/hotplug/rpaphp_vio.c b/drivers/pci/hotplug/rpaphp_vio.c
index 314680609032..d82b6649ed8c 100644
--- a/drivers/pci/hotplug/rpaphp_vio.c
+++ b/drivers/pci/hotplug/rpaphp_vio.c
@@ -86,7 +86,14 @@ int register_vio_slot(struct device_node *dn)
}
slot->dev_type = VIO_DEV;
slot->dev.vio_dev = vio_find_node(dn);
- if (!slot->dev.vio_dev)
+ if (slot->dev.vio_dev) {
+ /*
+ * rpaphp is the only owner of vio devices and
+ * does not need extra reference taken by
+ * vio_find_node
+ */
+ put_device(&slot->dev.vio_dev->dev);
+ } else
slot->dev.vio_dev = vio_register_device_node(dn);
if (slot->dev.vio_dev)
slot->state = CONFIGURED;
diff --git a/include/linux/device.h b/include/linux/device.h
index 3f6e14c099e2..49d3865aa27b 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -56,6 +56,7 @@ struct bus_type {
struct bus_attribute * bus_attrs;
struct device_attribute * dev_attrs;
+ struct driver_attribute * drv_attrs;
int (*match)(struct device * dev, struct device_driver * drv);
struct device * (*add) (struct device * parent, char * bus_id);
@@ -119,6 +120,7 @@ extern void driver_unregister(struct device_driver * drv);
extern struct device_driver * get_driver(struct device_driver * drv);
extern void put_driver(struct device_driver * drv);
+extern struct device_driver *driver_find(const char *name, struct bus_type *bus);
/* driverfs interface for exporting driver attributes */
@@ -381,6 +383,8 @@ extern struct resource *platform_get_resource(struct platform_device *, unsigned
extern int platform_get_irq(struct platform_device *, unsigned int);
extern int platform_add_devices(struct platform_device **, int);
+extern struct platform_device *platform_device_register_simple(char *, unsigned int, struct resource *, unsigned int);
+
/* drivers/base/power.c */
extern void device_shutdown(void);
diff --git a/lib/kobject.c b/lib/kobject.c
index bcf4a9be0dcd..781f3e896695 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -537,7 +537,8 @@ void kset_unregister(struct kset * k)
* @name: object's name.
*
* Lock kset via @kset->subsys, and iterate over @kset->list,
- * looking for a matching kobject. Return object if found.
+ * looking for a matching kobject. If matching object is found
+ * take a reference and return the object.
*/
struct kobject * kset_find_obj(struct kset * kset, const char * name)
@@ -548,8 +549,8 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
down_read(&kset->subsys->rwsem);
list_for_each(entry,&kset->list) {
struct kobject * k = to_kobj(entry);
- if (kobject_name(k) && (!strcmp(kobject_name(k),name))) {
- ret = k;
+ if (kobject_name(k) && !strcmp(kobject_name(k),name)) {
+ ret = kobject_get(k);
break;
}
}
diff --git a/security/root_plug.c b/security/root_plug.c
index ec8955dcba29..07651def2f78 100644
--- a/security/root_plug.c
+++ b/security/root_plug.c
@@ -36,16 +36,16 @@ static int secondary;
static int vendor_id = 0x0557;
static int product_id = 0x2008;
-MODULE_PARM(vendor_id, "h");
+module_param(vendor_id, uint, 0400);
MODULE_PARM_DESC(vendor_id, "USB Vendor ID of device to look for");
-MODULE_PARM(product_id, "h");
+module_param(product_id, uint, 0400);
MODULE_PARM_DESC(product_id, "USB Product ID of device to look for");
/* should we print out debug messages */
static int debug = 0;
-MODULE_PARM(debug, "i");
+module_param(debug, bool, 0600);
MODULE_PARM_DESC(debug, "Debug enabled or not");
#if defined(CONFIG_SECURITY_ROOTPLUG_MODULE)