aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/base/base.h1
-rw-r--r--drivers/base/bus.c117
-rw-r--r--drivers/base/core.c2
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/driver.c35
-rw-r--r--drivers/char/tpm/tpm.c2
-rw-r--r--drivers/ide/legacy/hd.c4
-rw-r--r--drivers/input/gameport/gameport.c3
-rw-r--r--drivers/input/joystick/analog.c4
-rw-r--r--drivers/pcmcia/ds.c2
-rw-r--r--drivers/serial/8250.c3
11 files changed, 149 insertions, 26 deletions
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 645f6269292..783752b68a9 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -5,6 +5,7 @@ extern int bus_add_driver(struct device_driver *);
extern void bus_remove_driver(struct device_driver *);
extern void driver_detach(struct device_driver * drv);
+extern int driver_probe_device(struct device_driver *, struct device *);
static inline struct class_device *to_class_dev(struct kobject *obj)
{
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index c3fac7fd555..96fe2f95675 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -133,6 +133,58 @@ static struct kobj_type ktype_bus = {
decl_subsys(bus, &ktype_bus, NULL);
+/* Manually detach a device from it's associated driver. */
+static int driver_helper(struct device *dev, void *data)
+{
+ const char *name = data;
+
+ if (strcmp(name, dev->bus_id) == 0)
+ return 1;
+ return 0;
+}
+
+static ssize_t driver_unbind(struct device_driver *drv,
+ const char *buf, size_t count)
+{
+ struct bus_type *bus = get_bus(drv->bus);
+ struct device *dev;
+ int err = -ENODEV;
+
+ dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
+ if ((dev) &&
+ (dev->driver == drv)) {
+ device_release_driver(dev);
+ err = count;
+ }
+ return err;
+}
+static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
+
+/*
+ * Manually attach a device to a driver.
+ * Note: the driver must want to bind to the device,
+ * it is not possible to override the driver's id table.
+ */
+static ssize_t driver_bind(struct device_driver *drv,
+ const char *buf, size_t count)
+{
+ struct bus_type *bus = get_bus(drv->bus);
+ struct device *dev;
+ int err = -ENODEV;
+
+ dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
+ if ((dev) &&
+ (dev->driver == NULL)) {
+ down(&dev->sem);
+ err = driver_probe_device(drv, dev);
+ up(&dev->sem);
+ put_device(dev);
+ }
+ return err;
+}
+static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
+
+
static struct device * next_device(struct klist_iter * i)
{
struct klist_node * n = klist_next(i);
@@ -177,6 +229,39 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start,
return error;
}
+/**
+ * bus_find_device - device iterator for locating a particular device.
+ * @bus: bus type
+ * @start: Device to begin with
+ * @data: Data to pass to match function
+ * @match: Callback function to check device
+ *
+ * This is similar to the bus_for_each_dev() function above, but it
+ * returns a reference to a device that is 'found' for later use, as
+ * determined by the @match callback.
+ *
+ * The callback should return 0 if the device doesn't match and non-zero
+ * if it does. If the callback returns non-zero, this function will
+ * return to the caller and not iterate over any more devices.
+ */
+struct device * bus_find_device(struct bus_type *bus,
+ struct device *start, void *data,
+ int (*match)(struct device *, void *))
+{
+ struct klist_iter i;
+ struct device *dev;
+
+ if (!bus)
+ return NULL;
+
+ klist_iter_init_node(&bus->klist_devices, &i,
+ (start ? &start->knode_bus : NULL));
+ while ((dev = next_device(&i)))
+ if (match(dev, data) && get_device(dev))
+ break;
+ klist_iter_exit(&i);
+ return dev;
+}
static struct device_driver * next_driver(struct klist_iter * i)
@@ -363,6 +448,8 @@ int bus_add_driver(struct device_driver * drv)
module_add_driver(drv->owner, drv);
driver_add_attrs(bus, drv);
+ driver_create_file(drv, &driver_attr_unbind);
+ driver_create_file(drv, &driver_attr_bind);
}
return error;
}
@@ -380,6 +467,8 @@ int bus_add_driver(struct device_driver * drv)
void bus_remove_driver(struct device_driver * drv)
{
if (drv->bus) {
+ driver_remove_file(drv, &driver_attr_bind);
+ driver_remove_file(drv, &driver_attr_unbind);
driver_remove_attrs(drv->bus, drv);
klist_remove(&drv->knode_bus);
pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name);
@@ -394,31 +483,22 @@ void bus_remove_driver(struct device_driver * drv)
/* Helper for bus_rescan_devices's iter */
static int bus_rescan_devices_helper(struct device *dev, void *data)
{
- int *count = data;
-
- if (!dev->driver && (device_attach(dev) > 0))
- (*count)++;
-
+ if (!dev->driver)
+ device_attach(dev);
return 0;
}
-
/**
- * bus_rescan_devices - rescan devices on the bus for possible drivers
- * @bus: the bus to scan.
+ * bus_rescan_devices - rescan devices on the bus for possible drivers
+ * @bus: the bus to scan.
*
- * This function will look for devices on the bus with no driver
- * attached and rescan it against existing drivers to see if it
- * matches any. Calls device_attach(). Returns the number of devices
- * that were sucessfully bound to a driver.
+ * This function will look for devices on the bus with no driver
+ * attached and rescan it against existing drivers to see if it matches
+ * any by calling device_attach() for the unbound devices.
*/
-int bus_rescan_devices(struct bus_type * bus)
+void bus_rescan_devices(struct bus_type * bus)
{
- int count = 0;
-
- bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper);
-
- return count;
+ bus_for_each_dev(bus, NULL, NULL, bus_rescan_devices_helper);
}
@@ -557,6 +637,7 @@ int __init buses_init(void)
EXPORT_SYMBOL_GPL(bus_for_each_dev);
+EXPORT_SYMBOL_GPL(bus_find_device);
EXPORT_SYMBOL_GPL(bus_for_each_drv);
EXPORT_SYMBOL_GPL(bus_add_device);
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 86d79755fbf..efe03a024a5 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -333,7 +333,7 @@ void device_del(struct device * dev)
struct device * parent = dev->parent;
if (parent)
- klist_remove(&dev->knode_parent);
+ klist_del(&dev->knode_parent);
/* Notify the platform of the removal, in case they
* need to do anything...
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 6db3a789c54..16323f9cbff 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -65,7 +65,7 @@ void device_bind_driver(struct device * dev)
*
* This function must be called with @dev->sem held.
*/
-static int driver_probe_device(struct device_driver * drv, struct device * dev)
+int driver_probe_device(struct device_driver * drv, struct device * dev)
{
int ret = 0;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 1b645886e9e..291c5954a3a 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -56,6 +56,41 @@ EXPORT_SYMBOL_GPL(driver_for_each_device);
/**
+ * driver_find_device - device iterator for locating a particular device.
+ * @driver: The device's driver
+ * @start: Device to begin with
+ * @data: Data to pass to match function
+ * @match: Callback function to check device
+ *
+ * This is similar to the driver_for_each_device() function above, but
+ * it returns a reference to a device that is 'found' for later use, as
+ * determined by the @match callback.
+ *
+ * The callback should return 0 if the device doesn't match and non-zero
+ * if it does. If the callback returns non-zero, this function will
+ * return to the caller and not iterate over any more devices.
+ */
+struct device * driver_find_device(struct device_driver *drv,
+ struct device * start, void * data,
+ int (*match)(struct device *, void *))
+{
+ struct klist_iter i;
+ struct device *dev;
+
+ if (!drv)
+ return NULL;
+
+ klist_iter_init_node(&drv->klist_devices, &i,
+ (start ? &start->knode_driver : NULL));
+ while ((dev = next_device(&i)))
+ if (match(dev, data) && get_device(dev))
+ break;
+ klist_iter_exit(&i);
+ return dev;
+}
+EXPORT_SYMBOL_GPL(driver_find_device);
+
+/**
* driver_create_file - create sysfs file for driver.
* @drv: driver.
* @attr: driver attribute descriptor.
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 854475c54f0..049d128ae7f 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -464,7 +464,7 @@ void __devexit tpm_remove(struct pci_dev *pci_dev)
pci_set_drvdata(pci_dev, NULL);
misc_deregister(&chip->vendor->miscdev);
- kfree(&chip->vendor->miscdev.name);
+ kfree(chip->vendor->miscdev.name);
sysfs_remove_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
diff --git a/drivers/ide/legacy/hd.c b/drivers/ide/legacy/hd.c
index e884cd4b22f..242029c9c0c 100644
--- a/drivers/ide/legacy/hd.c
+++ b/drivers/ide/legacy/hd.c
@@ -156,11 +156,13 @@ else \
#if (HD_DELAY > 0)
+
+#include <asm/i8253.h>
+
unsigned long last_req;
unsigned long read_timer(void)
{
- extern spinlock_t i8253_lock;
unsigned long t, flags;
int i;
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 3e72c9b1461..ab09cf4093e 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -60,12 +60,13 @@ static void gameport_disconnect_port(struct gameport *gameport);
#if defined(__i386__)
+#include <asm/i8253.h>
+
#define DELTA(x,y) ((y)-(x)+((y)<(x)?1193182/HZ:0))
#define GET_TIME(x) do { x = get_time_pit(); } while (0)
static unsigned int get_time_pit(void)
{
- extern spinlock_t i8253_lock;
unsigned long flags;
unsigned int count;
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
index 504b7d55056..c3a5739030c 100644
--- a/drivers/input/joystick/analog.c
+++ b/drivers/input/joystick/analog.c
@@ -140,12 +140,14 @@ struct analog_port {
*/
#ifdef __i386__
+
+#include <asm/i8253.h>
+
#define GET_TIME(x) do { if (cpu_has_tsc) rdtscl(x); else x = get_time_pit(); } while (0)
#define DELTA(x,y) (cpu_has_tsc ? ((y) - (x)) : ((x) - (y) + ((x) < (y) ? CLOCK_TICK_RATE / HZ : 0)))
#define TIME_NAME (cpu_has_tsc?"TSC":"PIT")
static unsigned int get_time_pit(void)
{
- extern spinlock_t i8253_lock;
unsigned long flags;
unsigned int count;
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index cabddd49f6f..d5afd557fe3 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -847,7 +847,7 @@ pcmcia_device_stringattr(prod_id2, prod_id[1]);
pcmcia_device_stringattr(prod_id3, prod_id[2]);
pcmcia_device_stringattr(prod_id4, prod_id[3]);
-static ssize_t modalias_show(struct device *dev, char *buf)
+static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
int i;
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 9224fc3184e..7e8fc7c1d4c 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2061,7 +2061,8 @@ static void __init serial8250_isa_init_ports(void)
up->port.ops = &serial8250_pops;
}
- for (i = 0, up = serial8250_ports; i < ARRAY_SIZE(old_serial_port);
+ for (i = 0, up = serial8250_ports;
+ i < ARRAY_SIZE(old_serial_port) && i < UART_NR;
i++, up++) {
up->port.iobase = old_serial_port[i].port;
up->port.irq = irq_canonicalize(old_serial_port[i].irq);