Commit 29b6d1fb authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/driver-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 918953bc 36208530
......@@ -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)
......
......@@ -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);
......
......@@ -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);
......@@ -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);
......@@ -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,
......
......@@ -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,14 +200,15 @@ 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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
}
}
......
......@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment