Merge branch 'linus' into cpumask-for-linus
Conflicts: arch/x86/kernel/cpu/common.c
This commit is contained in:
@@ -63,6 +63,32 @@ struct class_private {
|
||||
#define to_class(obj) \
|
||||
container_of(obj, struct class_private, class_subsys.kobj)
|
||||
|
||||
/**
|
||||
* struct device_private - structure to hold the private to the driver core portions of the device structure.
|
||||
*
|
||||
* @klist_children - klist containing all children of this device
|
||||
* @knode_parent - node in sibling list
|
||||
* @knode_driver - node in driver list
|
||||
* @knode_bus - node in bus list
|
||||
* @device - pointer back to the struct class that this structure is
|
||||
* associated with.
|
||||
*
|
||||
* Nothing outside of the driver core should ever touch these fields.
|
||||
*/
|
||||
struct device_private {
|
||||
struct klist klist_children;
|
||||
struct klist_node knode_parent;
|
||||
struct klist_node knode_driver;
|
||||
struct klist_node knode_bus;
|
||||
struct device *device;
|
||||
};
|
||||
#define to_device_private_parent(obj) \
|
||||
container_of(obj, struct device_private, knode_parent)
|
||||
#define to_device_private_driver(obj) \
|
||||
container_of(obj, struct device_private, knode_driver)
|
||||
#define to_device_private_bus(obj) \
|
||||
container_of(obj, struct device_private, knode_bus)
|
||||
|
||||
/* initialisation functions */
|
||||
extern int devices_init(void);
|
||||
extern int buses_init(void);
|
||||
@@ -86,6 +112,11 @@ extern void bus_remove_driver(struct device_driver *drv);
|
||||
|
||||
extern void driver_detach(struct device_driver *drv);
|
||||
extern int driver_probe_device(struct device_driver *drv, struct device *dev);
|
||||
static inline int driver_match_device(struct device_driver *drv,
|
||||
struct device *dev)
|
||||
{
|
||||
return drv->bus->match && drv->bus->match(dev, drv);
|
||||
}
|
||||
|
||||
extern void sysdev_shutdown(void);
|
||||
|
||||
|
@@ -198,7 +198,7 @@ static ssize_t driver_bind(struct device_driver *drv,
|
||||
int err = -ENODEV;
|
||||
|
||||
dev = bus_find_device_by_name(bus, NULL, buf);
|
||||
if (dev && dev->driver == NULL) {
|
||||
if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
|
||||
if (dev->parent) /* Needed for USB */
|
||||
down(&dev->parent->sem);
|
||||
down(&dev->sem);
|
||||
@@ -253,7 +253,14 @@ static ssize_t store_drivers_probe(struct bus_type *bus,
|
||||
static struct device *next_device(struct klist_iter *i)
|
||||
{
|
||||
struct klist_node *n = klist_next(i);
|
||||
return n ? container_of(n, struct device, knode_bus) : NULL;
|
||||
struct device *dev = NULL;
|
||||
struct device_private *dev_prv;
|
||||
|
||||
if (n) {
|
||||
dev_prv = to_device_private_bus(n);
|
||||
dev = dev_prv->device;
|
||||
}
|
||||
return dev;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,7 +293,7 @@ int bus_for_each_dev(struct bus_type *bus, struct device *start,
|
||||
return -EINVAL;
|
||||
|
||||
klist_iter_init_node(&bus->p->klist_devices, &i,
|
||||
(start ? &start->knode_bus : NULL));
|
||||
(start ? &start->p->knode_bus : NULL));
|
||||
while ((dev = next_device(&i)) && !error)
|
||||
error = fn(dev, data);
|
||||
klist_iter_exit(&i);
|
||||
@@ -320,7 +327,7 @@ struct device *bus_find_device(struct bus_type *bus,
|
||||
return NULL;
|
||||
|
||||
klist_iter_init_node(&bus->p->klist_devices, &i,
|
||||
(start ? &start->knode_bus : NULL));
|
||||
(start ? &start->p->knode_bus : NULL));
|
||||
while ((dev = next_device(&i)))
|
||||
if (match(dev, data) && get_device(dev))
|
||||
break;
|
||||
@@ -507,7 +514,8 @@ void bus_attach_device(struct device *dev)
|
||||
ret = device_attach(dev);
|
||||
WARN_ON(ret < 0);
|
||||
if (ret >= 0)
|
||||
klist_add_tail(&dev->knode_bus, &bus->p->klist_devices);
|
||||
klist_add_tail(&dev->p->knode_bus,
|
||||
&bus->p->klist_devices);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,8 +536,8 @@ void bus_remove_device(struct device *dev)
|
||||
sysfs_remove_link(&dev->bus->p->devices_kset->kobj,
|
||||
dev_name(dev));
|
||||
device_remove_attrs(dev->bus, dev);
|
||||
if (klist_node_attached(&dev->knode_bus))
|
||||
klist_del(&dev->knode_bus);
|
||||
if (klist_node_attached(&dev->p->knode_bus))
|
||||
klist_del(&dev->p->knode_bus);
|
||||
|
||||
pr_debug("bus: '%s': remove device %s\n",
|
||||
dev->bus->name, dev_name(dev));
|
||||
@@ -831,14 +839,16 @@ static void bus_remove_attrs(struct bus_type *bus)
|
||||
|
||||
static void klist_devices_get(struct klist_node *n)
|
||||
{
|
||||
struct device *dev = container_of(n, struct device, knode_bus);
|
||||
struct device_private *dev_prv = to_device_private_bus(n);
|
||||
struct device *dev = dev_prv->device;
|
||||
|
||||
get_device(dev);
|
||||
}
|
||||
|
||||
static void klist_devices_put(struct klist_node *n)
|
||||
{
|
||||
struct device *dev = container_of(n, struct device, knode_bus);
|
||||
struct device_private *dev_prv = to_device_private_bus(n);
|
||||
struct device *dev = dev_prv->device;
|
||||
|
||||
put_device(dev);
|
||||
}
|
||||
@@ -932,6 +942,7 @@ bus_uevent_fail:
|
||||
kset_unregister(&bus->p->subsys);
|
||||
kfree(bus->p);
|
||||
out:
|
||||
bus->p = NULL;
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bus_register);
|
||||
@@ -953,6 +964,7 @@ void bus_unregister(struct bus_type *bus)
|
||||
bus_remove_file(bus, &bus_attr_uevent);
|
||||
kset_unregister(&bus->p->subsys);
|
||||
kfree(bus->p);
|
||||
bus->p = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bus_unregister);
|
||||
|
||||
@@ -993,18 +1005,20 @@ static void device_insertion_sort_klist(struct device *a, struct list_head *list
|
||||
{
|
||||
struct list_head *pos;
|
||||
struct klist_node *n;
|
||||
struct device_private *dev_prv;
|
||||
struct device *b;
|
||||
|
||||
list_for_each(pos, list) {
|
||||
n = container_of(pos, struct klist_node, n_node);
|
||||
b = container_of(n, struct device, knode_bus);
|
||||
dev_prv = to_device_private_bus(n);
|
||||
b = dev_prv->device;
|
||||
if (compare(a, b) <= 0) {
|
||||
list_move_tail(&a->knode_bus.n_node,
|
||||
&b->knode_bus.n_node);
|
||||
list_move_tail(&a->p->knode_bus.n_node,
|
||||
&b->p->knode_bus.n_node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
list_move_tail(&a->knode_bus.n_node, list);
|
||||
list_move_tail(&a->p->knode_bus.n_node, list);
|
||||
}
|
||||
|
||||
void bus_sort_breadthfirst(struct bus_type *bus,
|
||||
@@ -1014,6 +1028,7 @@ void bus_sort_breadthfirst(struct bus_type *bus,
|
||||
LIST_HEAD(sorted_devices);
|
||||
struct list_head *pos, *tmp;
|
||||
struct klist_node *n;
|
||||
struct device_private *dev_prv;
|
||||
struct device *dev;
|
||||
struct klist *device_klist;
|
||||
|
||||
@@ -1022,7 +1037,8 @@ void bus_sort_breadthfirst(struct bus_type *bus,
|
||||
spin_lock(&device_klist->k_lock);
|
||||
list_for_each_safe(pos, tmp, &device_klist->k_list) {
|
||||
n = container_of(pos, struct klist_node, n_node);
|
||||
dev = container_of(n, struct device, knode_bus);
|
||||
dev_prv = to_device_private_bus(n);
|
||||
dev = dev_prv->device;
|
||||
device_insertion_sort_klist(dev, &sorted_devices, compare);
|
||||
}
|
||||
list_splice(&sorted_devices, &device_klist->k_list);
|
||||
|
@@ -109,6 +109,7 @@ static struct sysfs_ops dev_sysfs_ops = {
|
||||
static void device_release(struct kobject *kobj)
|
||||
{
|
||||
struct device *dev = to_dev(kobj);
|
||||
struct device_private *p = dev->p;
|
||||
|
||||
if (dev->release)
|
||||
dev->release(dev);
|
||||
@@ -120,6 +121,7 @@ static void device_release(struct kobject *kobj)
|
||||
WARN(1, KERN_ERR "Device '%s' does not have a release() "
|
||||
"function, it is broken and must be fixed.\n",
|
||||
dev_name(dev));
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
static struct kobj_type device_ktype = {
|
||||
@@ -134,8 +136,6 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
|
||||
|
||||
if (ktype == &device_ktype) {
|
||||
struct device *dev = to_dev(kobj);
|
||||
if (dev->uevent_suppress)
|
||||
return 0;
|
||||
if (dev->bus)
|
||||
return 1;
|
||||
if (dev->class)
|
||||
@@ -507,14 +507,16 @@ EXPORT_SYMBOL_GPL(device_schedule_callback_owner);
|
||||
|
||||
static void klist_children_get(struct klist_node *n)
|
||||
{
|
||||
struct device *dev = container_of(n, struct device, knode_parent);
|
||||
struct device_private *p = to_device_private_parent(n);
|
||||
struct device *dev = p->device;
|
||||
|
||||
get_device(dev);
|
||||
}
|
||||
|
||||
static void klist_children_put(struct klist_node *n)
|
||||
{
|
||||
struct device *dev = container_of(n, struct device, knode_parent);
|
||||
struct device_private *p = to_device_private_parent(n);
|
||||
struct device *dev = p->device;
|
||||
|
||||
put_device(dev);
|
||||
}
|
||||
@@ -538,8 +540,6 @@ void device_initialize(struct device *dev)
|
||||
{
|
||||
dev->kobj.kset = devices_kset;
|
||||
kobject_init(&dev->kobj, &device_ktype);
|
||||
klist_init(&dev->klist_children, klist_children_get,
|
||||
klist_children_put);
|
||||
INIT_LIST_HEAD(&dev->dma_pools);
|
||||
init_MUTEX(&dev->sem);
|
||||
spin_lock_init(&dev->devres_lock);
|
||||
@@ -777,17 +777,12 @@ static void device_remove_class_symlinks(struct device *dev)
|
||||
int dev_set_name(struct device *dev, const char *fmt, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
char *s;
|
||||
int err;
|
||||
|
||||
va_start(vargs, fmt);
|
||||
vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs);
|
||||
err = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
|
||||
va_end(vargs);
|
||||
|
||||
/* ewww... some of these buggers have / in the name... */
|
||||
while ((s = strchr(dev->bus_id, '/')))
|
||||
*s = '!';
|
||||
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_set_name);
|
||||
|
||||
@@ -864,12 +859,26 @@ int device_add(struct device *dev)
|
||||
if (!dev)
|
||||
goto done;
|
||||
|
||||
/* Temporarily support init_name if it is set.
|
||||
* It will override bus_id for now */
|
||||
if (dev->init_name)
|
||||
dev_set_name(dev, "%s", dev->init_name);
|
||||
dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL);
|
||||
if (!dev->p) {
|
||||
error = -ENOMEM;
|
||||
goto done;
|
||||
}
|
||||
dev->p->device = dev;
|
||||
klist_init(&dev->p->klist_children, klist_children_get,
|
||||
klist_children_put);
|
||||
|
||||
if (!strlen(dev->bus_id))
|
||||
/*
|
||||
* for statically allocated devices, which should all be converted
|
||||
* some day, we need to initialize the name. We prevent reading back
|
||||
* the name, and force the use of dev_name()
|
||||
*/
|
||||
if (dev->init_name) {
|
||||
dev_set_name(dev, dev->init_name);
|
||||
dev->init_name = NULL;
|
||||
}
|
||||
|
||||
if (!dev_name(dev))
|
||||
goto done;
|
||||
|
||||
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
|
||||
@@ -928,7 +937,8 @@ int device_add(struct device *dev)
|
||||
kobject_uevent(&dev->kobj, KOBJ_ADD);
|
||||
bus_attach_device(dev);
|
||||
if (parent)
|
||||
klist_add_tail(&dev->knode_parent, &parent->klist_children);
|
||||
klist_add_tail(&dev->p->knode_parent,
|
||||
&parent->p->klist_children);
|
||||
|
||||
if (dev->class) {
|
||||
mutex_lock(&dev->class->p->class_mutex);
|
||||
@@ -1042,7 +1052,7 @@ void device_del(struct device *dev)
|
||||
device_pm_remove(dev);
|
||||
dpm_sysfs_remove(dev);
|
||||
if (parent)
|
||||
klist_del(&dev->knode_parent);
|
||||
klist_del(&dev->p->knode_parent);
|
||||
if (MAJOR(dev->devt)) {
|
||||
device_remove_sys_dev_entry(dev);
|
||||
device_remove_file(dev, &devt_attr);
|
||||
@@ -1103,7 +1113,14 @@ void device_unregister(struct device *dev)
|
||||
static struct device *next_device(struct klist_iter *i)
|
||||
{
|
||||
struct klist_node *n = klist_next(i);
|
||||
return n ? container_of(n, struct device, knode_parent) : NULL;
|
||||
struct device *dev = NULL;
|
||||
struct device_private *p;
|
||||
|
||||
if (n) {
|
||||
p = to_device_private_parent(n);
|
||||
dev = p->device;
|
||||
}
|
||||
return dev;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1125,7 +1142,7 @@ int device_for_each_child(struct device *parent, void *data,
|
||||
struct device *child;
|
||||
int error = 0;
|
||||
|
||||
klist_iter_init(&parent->klist_children, &i);
|
||||
klist_iter_init(&parent->p->klist_children, &i);
|
||||
while ((child = next_device(&i)) && !error)
|
||||
error = fn(child, data);
|
||||
klist_iter_exit(&i);
|
||||
@@ -1156,7 +1173,7 @@ struct device *device_find_child(struct device *parent, void *data,
|
||||
if (!parent)
|
||||
return NULL;
|
||||
|
||||
klist_iter_init(&parent->klist_children, &i);
|
||||
klist_iter_init(&parent->p->klist_children, &i);
|
||||
while ((child = next_device(&i)))
|
||||
if (match(child, data) && get_device(child))
|
||||
break;
|
||||
@@ -1348,7 +1365,10 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
|
||||
dev->release = device_create_release;
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
|
||||
vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
|
||||
retval = kobject_set_name_vargs(&dev->kobj, fmt, args);
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
retval = device_register(dev);
|
||||
if (retval)
|
||||
goto error;
|
||||
@@ -1452,19 +1472,15 @@ int device_rename(struct device *dev, char *new_name)
|
||||
old_class_name = make_class_name(dev->class->name, &dev->kobj);
|
||||
#endif
|
||||
|
||||
old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL);
|
||||
old_device_name = kstrdup(dev_name(dev), GFP_KERNEL);
|
||||
if (!old_device_name) {
|
||||
error = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE);
|
||||
strlcpy(dev->bus_id, new_name, BUS_ID_SIZE);
|
||||
|
||||
error = kobject_rename(&dev->kobj, new_name);
|
||||
if (error) {
|
||||
strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE);
|
||||
if (error)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSFS_DEPRECATED
|
||||
if (old_class_name) {
|
||||
@@ -1545,8 +1561,10 @@ out:
|
||||
* device_move - moves a device to a new parent
|
||||
* @dev: the pointer to the struct device to be moved
|
||||
* @new_parent: the new parent of the device (can by NULL)
|
||||
* @dpm_order: how to reorder the dpm_list
|
||||
*/
|
||||
int device_move(struct device *dev, struct device *new_parent)
|
||||
int device_move(struct device *dev, struct device *new_parent,
|
||||
enum dpm_order dpm_order)
|
||||
{
|
||||
int error;
|
||||
struct device *old_parent;
|
||||
@@ -1556,6 +1574,7 @@ int device_move(struct device *dev, struct device *new_parent)
|
||||
if (!dev)
|
||||
return -EINVAL;
|
||||
|
||||
device_pm_lock();
|
||||
new_parent = get_device(new_parent);
|
||||
new_parent_kobj = get_device_parent(dev, new_parent);
|
||||
|
||||
@@ -1570,9 +1589,10 @@ int device_move(struct device *dev, struct device *new_parent)
|
||||
old_parent = dev->parent;
|
||||
dev->parent = new_parent;
|
||||
if (old_parent)
|
||||
klist_remove(&dev->knode_parent);
|
||||
klist_remove(&dev->p->knode_parent);
|
||||
if (new_parent) {
|
||||
klist_add_tail(&dev->knode_parent, &new_parent->klist_children);
|
||||
klist_add_tail(&dev->p->knode_parent,
|
||||
&new_parent->p->klist_children);
|
||||
set_dev_node(dev, dev_to_node(new_parent));
|
||||
}
|
||||
|
||||
@@ -1584,11 +1604,11 @@ int device_move(struct device *dev, struct device *new_parent)
|
||||
device_move_class_links(dev, new_parent, old_parent);
|
||||
if (!kobject_move(&dev->kobj, &old_parent->kobj)) {
|
||||
if (new_parent)
|
||||
klist_remove(&dev->knode_parent);
|
||||
klist_remove(&dev->p->knode_parent);
|
||||
dev->parent = old_parent;
|
||||
if (old_parent) {
|
||||
klist_add_tail(&dev->knode_parent,
|
||||
&old_parent->klist_children);
|
||||
klist_add_tail(&dev->p->knode_parent,
|
||||
&old_parent->p->klist_children);
|
||||
set_dev_node(dev, dev_to_node(old_parent));
|
||||
}
|
||||
}
|
||||
@@ -1596,9 +1616,23 @@ int device_move(struct device *dev, struct device *new_parent)
|
||||
put_device(new_parent);
|
||||
goto out;
|
||||
}
|
||||
switch (dpm_order) {
|
||||
case DPM_ORDER_NONE:
|
||||
break;
|
||||
case DPM_ORDER_DEV_AFTER_PARENT:
|
||||
device_pm_move_after(dev, new_parent);
|
||||
break;
|
||||
case DPM_ORDER_PARENT_BEFORE_DEV:
|
||||
device_pm_move_before(new_parent, dev);
|
||||
break;
|
||||
case DPM_ORDER_DEV_LAST:
|
||||
device_pm_move_last(dev);
|
||||
break;
|
||||
}
|
||||
out_put:
|
||||
put_device(old_parent);
|
||||
out:
|
||||
device_pm_unlock();
|
||||
put_device(dev);
|
||||
return error;
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@
|
||||
|
||||
static void driver_bound(struct device *dev)
|
||||
{
|
||||
if (klist_node_attached(&dev->knode_driver)) {
|
||||
if (klist_node_attached(&dev->p->knode_driver)) {
|
||||
printk(KERN_WARNING "%s: device %s already bound\n",
|
||||
__func__, kobject_name(&dev->kobj));
|
||||
return;
|
||||
@@ -43,7 +43,7 @@ static void driver_bound(struct device *dev)
|
||||
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
|
||||
BUS_NOTIFY_BOUND_DRIVER, dev);
|
||||
|
||||
klist_add_tail(&dev->knode_driver, &dev->driver->p->klist_devices);
|
||||
klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);
|
||||
}
|
||||
|
||||
static int driver_sysfs_add(struct device *dev)
|
||||
@@ -172,16 +172,12 @@ int driver_probe_done(void)
|
||||
/**
|
||||
* wait_for_device_probe
|
||||
* Wait for device probing to be completed.
|
||||
*
|
||||
* Note: this function polls at 100 msec intervals.
|
||||
*/
|
||||
int wait_for_device_probe(void)
|
||||
void wait_for_device_probe(void)
|
||||
{
|
||||
/* wait for the known devices to complete their probing */
|
||||
while (driver_probe_done() != 0)
|
||||
msleep(100);
|
||||
wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
|
||||
async_synchronize_full();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,14 +185,8 @@ int wait_for_device_probe(void)
|
||||
* @drv: driver to bind a device to
|
||||
* @dev: device to try to bind to the driver
|
||||
*
|
||||
* First, we call the bus's match function, if one present, which should
|
||||
* compare the device IDs the driver supports with the device IDs of the
|
||||
* device. Note we don't do this ourselves because we don't know the
|
||||
* format of the ID structures, nor what is to be considered a match and
|
||||
* what is not.
|
||||
*
|
||||
* This function returns 1 if a match is found, -ENODEV if the device is
|
||||
* not registered, and 0 otherwise.
|
||||
* This function returns -ENODEV if the device is not registered,
|
||||
* 1 if the device is bound sucessfully and 0 otherwise.
|
||||
*
|
||||
* This function must be called with @dev->sem held. When called for a
|
||||
* USB interface, @dev->parent->sem must be held as well.
|
||||
@@ -207,21 +197,22 @@ int driver_probe_device(struct device_driver *drv, struct device *dev)
|
||||
|
||||
if (!device_is_registered(dev))
|
||||
return -ENODEV;
|
||||
if (drv->bus->match && !drv->bus->match(dev, drv))
|
||||
goto done;
|
||||
|
||||
pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
|
||||
drv->bus->name, __func__, dev_name(dev), drv->name);
|
||||
|
||||
ret = really_probe(dev, drv);
|
||||
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __device_attach(struct device_driver *drv, void *data)
|
||||
{
|
||||
struct device *dev = data;
|
||||
|
||||
if (!driver_match_device(drv, dev))
|
||||
return 0;
|
||||
|
||||
return driver_probe_device(drv, dev);
|
||||
}
|
||||
|
||||
@@ -274,7 +265,7 @@ static int __driver_attach(struct device *dev, void *data)
|
||||
* is an error.
|
||||
*/
|
||||
|
||||
if (drv->bus->match && !drv->bus->match(dev, drv))
|
||||
if (!driver_match_device(drv, dev))
|
||||
return 0;
|
||||
|
||||
if (dev->parent) /* Needed for USB */
|
||||
@@ -327,7 +318,7 @@ static void __device_release_driver(struct device *dev)
|
||||
drv->remove(dev);
|
||||
devres_release_all(dev);
|
||||
dev->driver = NULL;
|
||||
klist_remove(&dev->knode_driver);
|
||||
klist_remove(&dev->p->knode_driver);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -357,6 +348,7 @@ EXPORT_SYMBOL_GPL(device_release_driver);
|
||||
*/
|
||||
void driver_detach(struct device_driver *drv)
|
||||
{
|
||||
struct device_private *dev_prv;
|
||||
struct device *dev;
|
||||
|
||||
for (;;) {
|
||||
@@ -365,8 +357,10 @@ void driver_detach(struct device_driver *drv)
|
||||
spin_unlock(&drv->p->klist_devices.k_lock);
|
||||
break;
|
||||
}
|
||||
dev = list_entry(drv->p->klist_devices.k_list.prev,
|
||||
struct device, knode_driver.n_node);
|
||||
dev_prv = list_entry(drv->p->klist_devices.k_list.prev,
|
||||
struct device_private,
|
||||
knode_driver.n_node);
|
||||
dev = dev_prv->device;
|
||||
get_device(dev);
|
||||
spin_unlock(&drv->p->klist_devices.k_lock);
|
||||
|
||||
|
@@ -19,7 +19,14 @@
|
||||
static struct device *next_device(struct klist_iter *i)
|
||||
{
|
||||
struct klist_node *n = klist_next(i);
|
||||
return n ? container_of(n, struct device, knode_driver) : NULL;
|
||||
struct device *dev = NULL;
|
||||
struct device_private *dev_prv;
|
||||
|
||||
if (n) {
|
||||
dev_prv = to_device_private_driver(n);
|
||||
dev = dev_prv->device;
|
||||
}
|
||||
return dev;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,7 +49,7 @@ int driver_for_each_device(struct device_driver *drv, struct device *start,
|
||||
return -EINVAL;
|
||||
|
||||
klist_iter_init_node(&drv->p->klist_devices, &i,
|
||||
start ? &start->knode_driver : NULL);
|
||||
start ? &start->p->knode_driver : NULL);
|
||||
while ((dev = next_device(&i)) && !error)
|
||||
error = fn(dev, data);
|
||||
klist_iter_exit(&i);
|
||||
@@ -76,7 +83,7 @@ struct device *driver_find_device(struct device_driver *drv,
|
||||
return NULL;
|
||||
|
||||
klist_iter_init_node(&drv->p->klist_devices, &i,
|
||||
(start ? &start->knode_driver : NULL));
|
||||
(start ? &start->p->knode_driver : NULL));
|
||||
while ((dev = next_device(&i)))
|
||||
if (match(dev, data) && get_device(dev))
|
||||
break;
|
||||
@@ -216,6 +223,8 @@ int driver_register(struct device_driver *drv)
|
||||
int ret;
|
||||
struct device_driver *other;
|
||||
|
||||
BUG_ON(!drv->bus->p);
|
||||
|
||||
if ((drv->bus->probe && drv->probe) ||
|
||||
(drv->bus->remove && drv->remove) ||
|
||||
(drv->bus->shutdown && drv->shutdown))
|
||||
|
@@ -319,7 +319,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
|
||||
f_dev->parent = device;
|
||||
f_dev->class = &firmware_class;
|
||||
dev_set_drvdata(f_dev, fw_priv);
|
||||
f_dev->uevent_suppress = 1;
|
||||
dev_set_uevent_suppress(f_dev, 1);
|
||||
retval = device_register(f_dev);
|
||||
if (retval) {
|
||||
dev_err(device, "%s: device_register failed\n", __func__);
|
||||
@@ -366,7 +366,7 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p,
|
||||
}
|
||||
|
||||
if (uevent)
|
||||
f_dev->uevent_suppress = 0;
|
||||
dev_set_uevent_suppress(f_dev, 0);
|
||||
*dev_p = f_dev;
|
||||
goto out;
|
||||
|
||||
|
@@ -31,7 +31,7 @@ void register_iommu(struct iommu_ops *ops)
|
||||
iommu_ops = ops;
|
||||
}
|
||||
|
||||
bool iommu_found()
|
||||
bool iommu_found(void)
|
||||
{
|
||||
return iommu_ops != NULL;
|
||||
}
|
||||
|
@@ -217,6 +217,7 @@ int platform_device_add_data(struct platform_device *pdev, const void *data,
|
||||
if (d) {
|
||||
memcpy(d, data, size);
|
||||
pdev->dev.platform_data = d;
|
||||
pdev->platform_data = d;
|
||||
}
|
||||
return d ? 0 : -ENOMEM;
|
||||
}
|
||||
@@ -246,6 +247,21 @@ int platform_device_add(struct platform_device *pdev)
|
||||
else
|
||||
dev_set_name(&pdev->dev, pdev->name);
|
||||
|
||||
/* We will remove platform_data field from struct device
|
||||
* if all platform devices pass its platform specific data
|
||||
* from platform_device. The conversion is going to be a
|
||||
* long time, so we allow the two cases coexist to make
|
||||
* this kind of fix more easily*/
|
||||
if (pdev->platform_data && pdev->dev.platform_data) {
|
||||
printk(KERN_ERR
|
||||
"%s: use which platform_data?\n",
|
||||
dev_name(&pdev->dev));
|
||||
} else if (pdev->platform_data) {
|
||||
pdev->dev.platform_data = pdev->platform_data;
|
||||
} else if (pdev->dev.platform_data) {
|
||||
pdev->platform_data = pdev->dev.platform_data;
|
||||
}
|
||||
|
||||
for (i = 0; i < pdev->num_resources; i++) {
|
||||
struct resource *p, *r = &pdev->resource[i];
|
||||
|
||||
@@ -584,10 +600,25 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
|
||||
add_uevent_var(env, "MODALIAS=platform:%s", pdev->name);
|
||||
add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX,
|
||||
(pdev->id_entry) ? pdev->id_entry->name : pdev->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct platform_device_id *platform_match_id(
|
||||
struct platform_device_id *id,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
while (id->name[0]) {
|
||||
if (strcmp(pdev->name, id->name) == 0) {
|
||||
pdev->id_entry = id;
|
||||
return id;
|
||||
}
|
||||
id++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* platform_match - bind platform device to platform driver.
|
||||
* @dev: device.
|
||||
@@ -603,9 +634,14 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
*/
|
||||
static int platform_match(struct device *dev, struct device_driver *drv)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct platform_driver *pdrv = to_platform_driver(drv);
|
||||
|
||||
pdev = container_of(dev, struct platform_device, dev);
|
||||
/* match against the id table first */
|
||||
if (pdrv->id_table)
|
||||
return platform_match_id(pdrv->id_table, pdev) != NULL;
|
||||
|
||||
/* fall-back to driver name match */
|
||||
return (strcmp(pdev->name, drv->name) == 0);
|
||||
}
|
||||
|
||||
@@ -623,26 +659,24 @@ static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
|
||||
|
||||
static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg)
|
||||
{
|
||||
struct platform_driver *drv = to_platform_driver(dev->driver);
|
||||
struct platform_device *pdev;
|
||||
struct platform_driver *pdrv = to_platform_driver(dev->driver);
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
int ret = 0;
|
||||
|
||||
pdev = container_of(dev, struct platform_device, dev);
|
||||
if (dev->driver && drv->suspend_late)
|
||||
ret = drv->suspend_late(pdev, mesg);
|
||||
if (dev->driver && pdrv->suspend_late)
|
||||
ret = pdrv->suspend_late(pdev, mesg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int platform_legacy_resume_early(struct device *dev)
|
||||
{
|
||||
struct platform_driver *drv = to_platform_driver(dev->driver);
|
||||
struct platform_device *pdev;
|
||||
struct platform_driver *pdrv = to_platform_driver(dev->driver);
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
int ret = 0;
|
||||
|
||||
pdev = container_of(dev, struct platform_device, dev);
|
||||
if (dev->driver && drv->resume_early)
|
||||
ret = drv->resume_early(pdev);
|
||||
if (dev->driver && pdrv->resume_early)
|
||||
ret = pdrv->resume_early(pdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -106,6 +106,50 @@ void device_pm_remove(struct device *dev)
|
||||
mutex_unlock(&dpm_list_mtx);
|
||||
}
|
||||
|
||||
/**
|
||||
* device_pm_move_before - move device in dpm_list
|
||||
* @deva: Device to move in dpm_list
|
||||
* @devb: Device @deva should come before
|
||||
*/
|
||||
void device_pm_move_before(struct device *deva, struct device *devb)
|
||||
{
|
||||
pr_debug("PM: Moving %s:%s before %s:%s\n",
|
||||
deva->bus ? deva->bus->name : "No Bus",
|
||||
kobject_name(&deva->kobj),
|
||||
devb->bus ? devb->bus->name : "No Bus",
|
||||
kobject_name(&devb->kobj));
|
||||
/* Delete deva from dpm_list and reinsert before devb. */
|
||||
list_move_tail(&deva->power.entry, &devb->power.entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* device_pm_move_after - move device in dpm_list
|
||||
* @deva: Device to move in dpm_list
|
||||
* @devb: Device @deva should come after
|
||||
*/
|
||||
void device_pm_move_after(struct device *deva, struct device *devb)
|
||||
{
|
||||
pr_debug("PM: Moving %s:%s after %s:%s\n",
|
||||
deva->bus ? deva->bus->name : "No Bus",
|
||||
kobject_name(&deva->kobj),
|
||||
devb->bus ? devb->bus->name : "No Bus",
|
||||
kobject_name(&devb->kobj));
|
||||
/* Delete deva from dpm_list and reinsert after devb. */
|
||||
list_move(&deva->power.entry, &devb->power.entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* device_pm_move_last - move device to end of dpm_list
|
||||
* @dev: Device to move in dpm_list
|
||||
*/
|
||||
void device_pm_move_last(struct device *dev)
|
||||
{
|
||||
pr_debug("PM: Moving %s:%s to end of list\n",
|
||||
dev->bus ? dev->bus->name : "No Bus",
|
||||
kobject_name(&dev->kobj));
|
||||
list_move_tail(&dev->power.entry, &dpm_list);
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_op - execute the PM operation appropiate for given PM event
|
||||
* @dev: Device.
|
||||
|
@@ -18,11 +18,19 @@ static inline struct device *to_device(struct list_head *entry)
|
||||
|
||||
extern void device_pm_add(struct device *);
|
||||
extern void device_pm_remove(struct device *);
|
||||
extern void device_pm_move_before(struct device *, struct device *);
|
||||
extern void device_pm_move_after(struct device *, struct device *);
|
||||
extern void device_pm_move_last(struct device *);
|
||||
|
||||
#else /* CONFIG_PM_SLEEP */
|
||||
|
||||
static inline void device_pm_add(struct device *dev) {}
|
||||
static inline void device_pm_remove(struct device *dev) {}
|
||||
static inline void device_pm_move_before(struct device *deva,
|
||||
struct device *devb) {}
|
||||
static inline void device_pm_move_after(struct device *deva,
|
||||
struct device *devb) {}
|
||||
static inline void device_pm_move_last(struct device *dev) {}
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -30,10 +30,10 @@
|
||||
|
||||
|
||||
static ssize_t
|
||||
sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer)
|
||||
sysdev_show(struct kobject *kobj, struct attribute *attr, char *buffer)
|
||||
{
|
||||
struct sys_device * sysdev = to_sysdev(kobj);
|
||||
struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
|
||||
struct sys_device *sysdev = to_sysdev(kobj);
|
||||
struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
|
||||
|
||||
if (sysdev_attr->show)
|
||||
return sysdev_attr->show(sysdev, sysdev_attr, buffer);
|
||||
@@ -42,11 +42,11 @@ sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer)
|
||||
|
||||
|
||||
static ssize_t
|
||||
sysdev_store(struct kobject * kobj, struct attribute * attr,
|
||||
const char * buffer, size_t count)
|
||||
sysdev_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buffer, size_t count)
|
||||
{
|
||||
struct sys_device * sysdev = to_sysdev(kobj);
|
||||
struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr);
|
||||
struct sys_device *sysdev = to_sysdev(kobj);
|
||||
struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr);
|
||||
|
||||
if (sysdev_attr->store)
|
||||
return sysdev_attr->store(sysdev, sysdev_attr, buffer, count);
|
||||
@@ -63,13 +63,13 @@ static struct kobj_type ktype_sysdev = {
|
||||
};
|
||||
|
||||
|
||||
int sysdev_create_file(struct sys_device * s, struct sysdev_attribute * a)
|
||||
int sysdev_create_file(struct sys_device *s, struct sysdev_attribute *a)
|
||||
{
|
||||
return sysfs_create_file(&s->kobj, &a->attr);
|
||||
}
|
||||
|
||||
|
||||
void sysdev_remove_file(struct sys_device * s, struct sysdev_attribute * a)
|
||||
void sysdev_remove_file(struct sys_device *s, struct sysdev_attribute *a)
|
||||
{
|
||||
sysfs_remove_file(&s->kobj, &a->attr);
|
||||
}
|
||||
@@ -84,7 +84,7 @@ EXPORT_SYMBOL_GPL(sysdev_remove_file);
|
||||
static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *buffer)
|
||||
{
|
||||
struct sysdev_class * class = to_sysdev_class(kobj);
|
||||
struct sysdev_class *class = to_sysdev_class(kobj);
|
||||
struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
|
||||
|
||||
if (class_attr->show)
|
||||
@@ -95,8 +95,8 @@ static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr,
|
||||
static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *buffer, size_t count)
|
||||
{
|
||||
struct sysdev_class * class = to_sysdev_class(kobj);
|
||||
struct sysdev_class_attribute * class_attr = to_sysdev_class_attr(attr);
|
||||
struct sysdev_class *class = to_sysdev_class(kobj);
|
||||
struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr);
|
||||
|
||||
if (class_attr->store)
|
||||
return class_attr->store(class, buffer, count);
|
||||
@@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(sysdev_class_remove_file);
|
||||
|
||||
static struct kset *system_kset;
|
||||
|
||||
int sysdev_class_register(struct sysdev_class * cls)
|
||||
int sysdev_class_register(struct sysdev_class *cls)
|
||||
{
|
||||
pr_debug("Registering sysdev class '%s'\n", cls->name);
|
||||
|
||||
@@ -141,7 +141,7 @@ int sysdev_class_register(struct sysdev_class * cls)
|
||||
return kset_register(&cls->kset);
|
||||
}
|
||||
|
||||
void sysdev_class_unregister(struct sysdev_class * cls)
|
||||
void sysdev_class_unregister(struct sysdev_class *cls)
|
||||
{
|
||||
pr_debug("Unregistering sysdev class '%s'\n",
|
||||
kobject_name(&cls->kset.kobj));
|
||||
@@ -203,8 +203,8 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
|
||||
* @cls: Class driver belongs to.
|
||||
* @drv: Driver.
|
||||
*/
|
||||
void sysdev_driver_unregister(struct sysdev_class * cls,
|
||||
struct sysdev_driver * drv)
|
||||
void sysdev_driver_unregister(struct sysdev_class *cls,
|
||||
struct sysdev_driver *drv)
|
||||
{
|
||||
mutex_lock(&sysdev_drivers_lock);
|
||||
list_del_init(&drv->entry);
|
||||
@@ -229,10 +229,10 @@ EXPORT_SYMBOL_GPL(sysdev_driver_unregister);
|
||||
* @sysdev: device in question
|
||||
*
|
||||
*/
|
||||
int sysdev_register(struct sys_device * sysdev)
|
||||
int sysdev_register(struct sys_device *sysdev)
|
||||
{
|
||||
int error;
|
||||
struct sysdev_class * cls = sysdev->cls;
|
||||
struct sysdev_class *cls = sysdev->cls;
|
||||
|
||||
if (!cls)
|
||||
return -EINVAL;
|
||||
@@ -252,7 +252,7 @@ int sysdev_register(struct sys_device * sysdev)
|
||||
sysdev->id);
|
||||
|
||||
if (!error) {
|
||||
struct sysdev_driver * drv;
|
||||
struct sysdev_driver *drv;
|
||||
|
||||
pr_debug("Registering sys device '%s'\n",
|
||||
kobject_name(&sysdev->kobj));
|
||||
@@ -274,9 +274,9 @@ int sysdev_register(struct sys_device * sysdev)
|
||||
return error;
|
||||
}
|
||||
|
||||
void sysdev_unregister(struct sys_device * sysdev)
|
||||
void sysdev_unregister(struct sys_device *sysdev)
|
||||
{
|
||||
struct sysdev_driver * drv;
|
||||
struct sysdev_driver *drv;
|
||||
|
||||
mutex_lock(&sysdev_drivers_lock);
|
||||
list_for_each_entry(drv, &sysdev->cls->drivers, entry) {
|
||||
@@ -305,19 +305,19 @@ void sysdev_unregister(struct sys_device * sysdev)
|
||||
*/
|
||||
void sysdev_shutdown(void)
|
||||
{
|
||||
struct sysdev_class * cls;
|
||||
struct sysdev_class *cls;
|
||||
|
||||
pr_debug("Shutting Down System Devices\n");
|
||||
|
||||
mutex_lock(&sysdev_drivers_lock);
|
||||
list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) {
|
||||
struct sys_device * sysdev;
|
||||
struct sys_device *sysdev;
|
||||
|
||||
pr_debug("Shutting down type '%s':\n",
|
||||
kobject_name(&cls->kset.kobj));
|
||||
|
||||
list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
|
||||
struct sysdev_driver * drv;
|
||||
struct sysdev_driver *drv;
|
||||
pr_debug(" %s\n", kobject_name(&sysdev->kobj));
|
||||
|
||||
/* Call auxillary drivers first */
|
||||
@@ -364,7 +364,7 @@ static void __sysdev_resume(struct sys_device *dev)
|
||||
*/
|
||||
int sysdev_suspend(pm_message_t state)
|
||||
{
|
||||
struct sysdev_class * cls;
|
||||
struct sysdev_class *cls;
|
||||
struct sys_device *sysdev, *err_dev;
|
||||
struct sysdev_driver *drv, *err_drv;
|
||||
int ret;
|
||||
@@ -442,12 +442,12 @@ EXPORT_SYMBOL_GPL(sysdev_suspend);
|
||||
*/
|
||||
int sysdev_resume(void)
|
||||
{
|
||||
struct sysdev_class * cls;
|
||||
struct sysdev_class *cls;
|
||||
|
||||
pr_debug("Resuming System Devices\n");
|
||||
|
||||
list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) {
|
||||
struct sys_device * sysdev;
|
||||
struct sys_device *sysdev;
|
||||
|
||||
pr_debug("Resuming type '%s':\n",
|
||||
kobject_name(&cls->kset.kobj));
|
||||
|
Reference in New Issue
Block a user