diff options
| author | Greg Kroah-Hartman <greg@kroah.com> | 2004-07-14 03:00:00 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <greg@kroah.com> | 2004-07-14 03:00:00 -0700 |
| commit | 36208530bd9ed3758095549d77542ddd2f932bf0 (patch) | |
| tree | 8a7703ac0095894567a6da5aa9c8b72445c95dfe | |
| parent | 9e9c96deae089852ac33db3066be53b1060355ac (diff) | |
| parent | 3b08aa6456c9046529ed38556b1950145eb7aa7a (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/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/base/bus.c | 39 | ||||
| -rw-r--r-- | drivers/base/core.c | 10 | ||||
| -rw-r--r-- | drivers/base/driver.c | 19 | ||||
| -rw-r--r-- | drivers/base/platform.c | 72 | ||||
| -rw-r--r-- | drivers/block/genhd.c | 11 | ||||
| -rw-r--r-- | drivers/char/raw.c | 15 | ||||
| -rw-r--r-- | drivers/pci/hotplug/rpaphp_vio.c | 9 | ||||
| -rw-r--r-- | include/linux/device.h | 4 | ||||
| -rw-r--r-- | lib/kobject.c | 7 | ||||
| -rw-r--r-- | security/root_plug.c | 6 |
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) |
