Commit 36208530 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge kroah.com:/home/greg/linux/BK/bleed-2.6

into kroah.com:/home/greg/linux/BK/driver-2.6
parents 9e9c96de 3b08aa64
...@@ -471,6 +471,37 @@ void bus_remove_device(struct device * dev) ...@@ -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. * bus_add_driver - Add a driver to the bus.
...@@ -499,6 +530,7 @@ int bus_add_driver(struct device_driver * drv) ...@@ -499,6 +530,7 @@ int bus_add_driver(struct device_driver * drv)
driver_attach(drv); driver_attach(drv);
up_write(&bus->subsys.rwsem); up_write(&bus->subsys.rwsem);
driver_add_attrs(bus, drv);
} }
return error; return error;
} }
...@@ -516,6 +548,7 @@ int bus_add_driver(struct device_driver * drv) ...@@ -516,6 +548,7 @@ int bus_add_driver(struct device_driver * drv)
void bus_remove_driver(struct device_driver * drv) void bus_remove_driver(struct device_driver * drv)
{ {
if (drv->bus) { if (drv->bus) {
driver_remove_attrs(drv->bus, drv);
down_write(&drv->bus->subsys.rwsem); down_write(&drv->bus->subsys.rwsem);
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
driver_detach(drv); driver_detach(drv);
...@@ -574,6 +607,8 @@ void put_bus(struct bus_type * bus) ...@@ -574,6 +607,8 @@ void put_bus(struct bus_type * bus)
* *
* Call kset_find_obj() to iterate over list of buses to * Call kset_find_obj() to iterate over list of buses to
* find a bus by name. Return bus if found. * 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) struct bus_type * find_bus(char * name)
......
...@@ -378,6 +378,16 @@ int device_for_each_child(struct device * dev, void * data, ...@@ -378,6 +378,16 @@ int device_for_each_child(struct device * dev, void * data,
return error; 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 device *device_find(const char *name, struct bus_type *bus)
{ {
struct kobject *k = kset_find_obj(&bus->devices, name); struct kobject *k = kset_find_obj(&bus->devices, name);
......
...@@ -111,10 +111,29 @@ void driver_unregister(struct device_driver * drv) ...@@ -111,10 +111,29 @@ void driver_unregister(struct device_driver * drv)
up(&drv->unload_sem); 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_register);
EXPORT_SYMBOL(driver_unregister); EXPORT_SYMBOL(driver_unregister);
EXPORT_SYMBOL(get_driver); EXPORT_SYMBOL(get_driver);
EXPORT_SYMBOL(put_driver); EXPORT_SYMBOL(put_driver);
EXPORT_SYMBOL(driver_find);
EXPORT_SYMBOL(driver_create_file); EXPORT_SYMBOL(driver_create_file);
EXPORT_SYMBOL(driver_remove_file); EXPORT_SYMBOL(driver_remove_file);
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
#include <linux/bootmem.h> #include <linux/bootmem.h>
#include <linux/err.h>
struct device platform_bus = { struct device platform_bus = {
.bus_id = "platform", .bus_id = "platform",
...@@ -133,21 +134,87 @@ int platform_device_register(struct platform_device * pdev) ...@@ -133,21 +134,87 @@ int platform_device_register(struct platform_device * pdev)
return ret; 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) void platform_device_unregister(struct platform_device * pdev)
{ {
int i; int i;
if (pdev) { if (pdev) {
device_unregister(&pdev->dev);
for (i = 0; i < pdev->num_resources; i++) { for (i = 0; i < pdev->num_resources; i++) {
struct resource *r = &pdev->resource[i]; struct resource *r = &pdev->resource[i];
if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO)) if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO))
release_resource(r); 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. * platform_match - bind platform device to platform driver.
...@@ -237,6 +304,7 @@ EXPORT_SYMBOL(dma_get_required_mask); ...@@ -237,6 +304,7 @@ EXPORT_SYMBOL(dma_get_required_mask);
EXPORT_SYMBOL(platform_bus); EXPORT_SYMBOL(platform_bus);
EXPORT_SYMBOL(platform_bus_type); EXPORT_SYMBOL(platform_bus_type);
EXPORT_SYMBOL(platform_device_register); EXPORT_SYMBOL(platform_device_register);
EXPORT_SYMBOL(platform_device_register_simple);
EXPORT_SYMBOL(platform_device_unregister); EXPORT_SYMBOL(platform_device_unregister);
EXPORT_SYMBOL(platform_get_irq); EXPORT_SYMBOL(platform_get_irq);
EXPORT_SYMBOL(platform_get_resource); EXPORT_SYMBOL(platform_get_resource);
...@@ -352,6 +352,12 @@ static ssize_t disk_range_read(struct gendisk * disk, char *page) ...@@ -352,6 +352,12 @@ static ssize_t disk_range_read(struct gendisk * disk, char *page)
{ {
return sprintf(page, "%d\n", disk->minors); 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) static ssize_t disk_size_read(struct gendisk * disk, char *page)
{ {
return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk)); return sprintf(page, "%llu\n", (unsigned long long)get_capacity(disk));
...@@ -384,6 +390,10 @@ static struct disk_attribute disk_attr_range = { ...@@ -384,6 +390,10 @@ static struct disk_attribute disk_attr_range = {
.attr = {.name = "range", .mode = S_IRUGO }, .attr = {.name = "range", .mode = S_IRUGO },
.show = disk_range_read .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 = { static struct disk_attribute disk_attr_size = {
.attr = {.name = "size", .mode = S_IRUGO }, .attr = {.name = "size", .mode = S_IRUGO },
.show = disk_size_read .show = disk_size_read
...@@ -396,6 +406,7 @@ static struct disk_attribute disk_attr_stat = { ...@@ -396,6 +406,7 @@ static struct disk_attribute disk_attr_stat = {
static struct attribute * default_attrs[] = { static struct attribute * default_attrs[] = {
&disk_attr_dev.attr, &disk_attr_dev.attr,
&disk_attr_range.attr, &disk_attr_range.attr,
&disk_attr_removable.attr,
&disk_attr_size.attr, &disk_attr_size.attr,
&disk_attr_stat.attr, &disk_attr_stat.attr,
NULL, NULL,
......
...@@ -125,11 +125,11 @@ raw_ioctl(struct inode *inode, struct file *filp, ...@@ -125,11 +125,11 @@ raw_ioctl(struct inode *inode, struct file *filp,
return ioctl_by_bdev(bdev, command, arg); 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_remove(MKDEV(RAW_MAJOR, rq->raw_minor));
class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq.raw_minor), class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
NULL, "raw%d", rq.raw_minor); NULL, "raw%d", rq->raw_minor);
} }
/* /*
...@@ -200,14 +200,15 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp, ...@@ -200,14 +200,15 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
if (rq.block_major == 0 && rq.block_minor == 0) { if (rq.block_major == 0 && rq.block_minor == 0) {
/* unbind */ /* unbind */
rawdev->binding = NULL; rawdev->binding = NULL;
class_simple_device_remove(MKDEV(RAW_MAJOR, rq.raw_minor)); class_simple_device_remove(MKDEV(RAW_MAJOR,
rq.raw_minor));
} else { } else {
rawdev->binding = bdget(dev); rawdev->binding = bdget(dev);
if (rawdev->binding == NULL) if (rawdev->binding == NULL)
err = -ENOMEM; err = -ENOMEM;
else { else {
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
bind_device(rq); bind_device(&rq);
} }
} }
up(&raw_mutex); up(&raw_mutex);
......
...@@ -86,7 +86,14 @@ int register_vio_slot(struct device_node *dn) ...@@ -86,7 +86,14 @@ int register_vio_slot(struct device_node *dn)
} }
slot->dev_type = VIO_DEV; slot->dev_type = VIO_DEV;
slot->dev.vio_dev = vio_find_node(dn); 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); slot->dev.vio_dev = vio_register_device_node(dn);
if (slot->dev.vio_dev) if (slot->dev.vio_dev)
slot->state = CONFIGURED; slot->state = CONFIGURED;
......
...@@ -56,6 +56,7 @@ struct bus_type { ...@@ -56,6 +56,7 @@ struct bus_type {
struct bus_attribute * bus_attrs; struct bus_attribute * bus_attrs;
struct device_attribute * dev_attrs; struct device_attribute * dev_attrs;
struct driver_attribute * drv_attrs;
int (*match)(struct device * dev, struct device_driver * drv); int (*match)(struct device * dev, struct device_driver * drv);
struct device * (*add) (struct device * parent, char * bus_id); struct device * (*add) (struct device * parent, char * bus_id);
...@@ -119,6 +120,7 @@ extern void driver_unregister(struct device_driver * drv); ...@@ -119,6 +120,7 @@ extern void driver_unregister(struct device_driver * drv);
extern struct device_driver * get_driver(struct device_driver * drv); extern struct device_driver * get_driver(struct device_driver * drv);
extern void put_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 */ /* driverfs interface for exporting driver attributes */
...@@ -381,6 +383,8 @@ extern struct resource *platform_get_resource(struct platform_device *, unsigned ...@@ -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_get_irq(struct platform_device *, unsigned int);
extern int platform_add_devices(struct platform_device **, 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 */ /* drivers/base/power.c */
extern void device_shutdown(void); extern void device_shutdown(void);
......
...@@ -537,7 +537,8 @@ void kset_unregister(struct kset * k) ...@@ -537,7 +537,8 @@ void kset_unregister(struct kset * k)
* @name: object's name. * @name: object's name.
* *
* Lock kset via @kset->subsys, and iterate over @kset->list, * 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) 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) ...@@ -548,8 +549,8 @@ struct kobject * kset_find_obj(struct kset * kset, const char * name)
down_read(&kset->subsys->rwsem); down_read(&kset->subsys->rwsem);
list_for_each(entry,&kset->list) { list_for_each(entry,&kset->list) {
struct kobject * k = to_kobj(entry); struct kobject * k = to_kobj(entry);
if (kobject_name(k) && (!strcmp(kobject_name(k),name))) { if (kobject_name(k) && !strcmp(kobject_name(k),name)) {
ret = k; ret = kobject_get(k);
break; break;
} }
} }
......
...@@ -36,16 +36,16 @@ static int secondary; ...@@ -36,16 +36,16 @@ static int secondary;
static int vendor_id = 0x0557; static int vendor_id = 0x0557;
static int product_id = 0x2008; 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_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"); MODULE_PARM_DESC(product_id, "USB Product ID of device to look for");
/* should we print out debug messages */ /* should we print out debug messages */
static int debug = 0; static int debug = 0;
MODULE_PARM(debug, "i"); module_param(debug, bool, 0600);
MODULE_PARM_DESC(debug, "Debug enabled or not"); MODULE_PARM_DESC(debug, "Debug enabled or not");
#if defined(CONFIG_SECURITY_ROOTPLUG_MODULE) #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