Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core-2.6: (46 commits) UIO: Fix mapping of logical and virtual memory UIO: add automata sercos3 pci card support UIO: Change driver name of uio_pdrv UIO: Add alignment warnings for uio-mem Driver core: add bus_sort_breadthfirst() function NET: convert the phy_device file to use bus_find_device_by_name kobject: Cleanup kobject_rename and !CONFIG_SYSFS kobject: Fix kobject_rename and !CONFIG_SYSFS sysfs: Make dir and name args to sysfs_notify() const platform: add new device registration helper sysfs: use ilookup5() instead of ilookup5_nowait() PNP: create device attributes via default device attributes Driver core: make bus_find_device_by_name() more robust usb: turn dev_warn+WARN_ON combos into dev_WARN debug: use dev_WARN() rather than WARN_ON() in device_pm_add() debug: Introduce a dev_WARN() function sysfs: fix deadlock device model: Do a quickcheck for driver binding before doing an expensive check Driver core: Fix cleanup in device_create_vargs(). Driver core: Clarify device cleanup. ...
This commit is contained in:
+51
-3
@@ -333,9 +333,7 @@ static int match_name(struct device *dev, void *data)
|
||||
{
|
||||
const char *name = data;
|
||||
|
||||
if (strcmp(name, dev->bus_id) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
return sysfs_streq(name, dev->bus_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -982,6 +980,56 @@ struct klist *bus_get_device_klist(struct bus_type *bus)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bus_get_device_klist);
|
||||
|
||||
/*
|
||||
* Yes, this forcably breaks the klist abstraction temporarily. It
|
||||
* just wants to sort the klist, not change reference counts and
|
||||
* take/drop locks rapidly in the process. It does all this while
|
||||
* holding the lock for the list, so objects can't otherwise be
|
||||
* added/removed while we're swizzling.
|
||||
*/
|
||||
static void device_insertion_sort_klist(struct device *a, struct list_head *list,
|
||||
int (*compare)(const struct device *a,
|
||||
const struct device *b))
|
||||
{
|
||||
struct list_head *pos;
|
||||
struct klist_node *n;
|
||||
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);
|
||||
if (compare(a, b) <= 0) {
|
||||
list_move_tail(&a->knode_bus.n_node,
|
||||
&b->knode_bus.n_node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
list_move_tail(&a->knode_bus.n_node, list);
|
||||
}
|
||||
|
||||
void bus_sort_breadthfirst(struct bus_type *bus,
|
||||
int (*compare)(const struct device *a,
|
||||
const struct device *b))
|
||||
{
|
||||
LIST_HEAD(sorted_devices);
|
||||
struct list_head *pos, *tmp;
|
||||
struct klist_node *n;
|
||||
struct device *dev;
|
||||
struct klist *device_klist;
|
||||
|
||||
device_klist = bus_get_device_klist(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);
|
||||
device_insertion_sort_klist(dev, &sorted_devices, compare);
|
||||
}
|
||||
list_splice(&sorted_devices, &device_klist->k_list);
|
||||
spin_unlock(&device_klist->k_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(bus_sort_breadthfirst);
|
||||
|
||||
int __init buses_init(void)
|
||||
{
|
||||
bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL);
|
||||
|
||||
+24
-6
@@ -523,11 +523,16 @@ static void klist_children_put(struct klist_node *n)
|
||||
* device_initialize - init device structure.
|
||||
* @dev: device.
|
||||
*
|
||||
* This prepares the device for use by other layers,
|
||||
* including adding it to the device hierarchy.
|
||||
* This prepares the device for use by other layers by initializing
|
||||
* its fields.
|
||||
* It is the first half of device_register(), if called by
|
||||
* that, though it can also be called separately, so one
|
||||
* may use @dev's fields (e.g. the refcount).
|
||||
* that function, though it can also be called separately, so one
|
||||
* may use @dev's fields. In particular, get_device()/put_device()
|
||||
* may be used for reference counting of @dev after calling this
|
||||
* function.
|
||||
*
|
||||
* NOTE: Use put_device() to give up your reference instead of freeing
|
||||
* @dev directly once you have called this function.
|
||||
*/
|
||||
void device_initialize(struct device *dev)
|
||||
{
|
||||
@@ -835,9 +840,13 @@ static void device_remove_sys_dev_entry(struct device *dev)
|
||||
* This is part 2 of device_register(), though may be called
|
||||
* separately _iff_ device_initialize() has been called separately.
|
||||
*
|
||||
* This adds it to the kobject hierarchy via kobject_add(), adds it
|
||||
* This adds @dev to the kobject hierarchy via kobject_add(), adds it
|
||||
* to the global and sibling lists for the device, then
|
||||
* adds it to the other relevant subsystems of the driver model.
|
||||
*
|
||||
* NOTE: _Never_ directly free @dev after calling this function, even
|
||||
* if it returned an error! Always use put_device() to give up your
|
||||
* reference instead.
|
||||
*/
|
||||
int device_add(struct device *dev)
|
||||
{
|
||||
@@ -965,6 +974,10 @@ done:
|
||||
* I.e. you should only call the two helpers separately if
|
||||
* have a clearly defined need to use and refcount the device
|
||||
* before it is added to the hierarchy.
|
||||
*
|
||||
* NOTE: _Never_ directly free @dev after calling this function, even
|
||||
* if it returned an error! Always use put_device() to give up the
|
||||
* reference initialized in this function instead.
|
||||
*/
|
||||
int device_register(struct device *dev)
|
||||
{
|
||||
@@ -1243,7 +1256,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent,
|
||||
return dev;
|
||||
|
||||
error:
|
||||
kfree(dev);
|
||||
put_device(dev);
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_create_vargs);
|
||||
@@ -1314,6 +1327,11 @@ EXPORT_SYMBOL_GPL(device_destroy);
|
||||
* device_rename - renames a device
|
||||
* @dev: the pointer to the struct device to be renamed
|
||||
* @new_name: the new name of the device
|
||||
*
|
||||
* It is the responsibility of the caller to provide mutual
|
||||
* exclusion between two different calls of device_rename
|
||||
* on the same device to ensure that new_name is valid and
|
||||
* won't conflict with other devices.
|
||||
*/
|
||||
int device_rename(struct device *dev, char *new_name)
|
||||
{
|
||||
|
||||
@@ -257,6 +257,9 @@ static int __driver_attach(struct device *dev, void *data)
|
||||
* is an error.
|
||||
*/
|
||||
|
||||
if (drv->bus->match && !drv->bus->match(dev, drv))
|
||||
return 0;
|
||||
|
||||
if (dev->parent) /* Needed for USB */
|
||||
down(&dev->parent->sem);
|
||||
down(&dev->sem);
|
||||
|
||||
+48
-1
@@ -394,6 +394,53 @@ error:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(platform_device_register_simple);
|
||||
|
||||
/**
|
||||
* platform_device_register_data
|
||||
* @parent: parent device for the device we're adding
|
||||
* @name: base name of the device we're adding
|
||||
* @id: instance id
|
||||
* @data: platform specific data for this platform device
|
||||
* @size: size of platform specific data
|
||||
*
|
||||
* 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 without waiting for the last reference to the device to be
|
||||
* dropped.
|
||||
*/
|
||||
struct platform_device *platform_device_register_data(
|
||||
struct device *parent,
|
||||
const char *name, int id,
|
||||
const void *data, size_t size)
|
||||
{
|
||||
struct platform_device *pdev;
|
||||
int retval;
|
||||
|
||||
pdev = platform_device_alloc(name, id);
|
||||
if (!pdev) {
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
pdev->dev.parent = parent;
|
||||
|
||||
if (size) {
|
||||
retval = platform_device_add_data(pdev, data, size);
|
||||
if (retval)
|
||||
goto error;
|
||||
}
|
||||
|
||||
retval = platform_device_add(pdev);
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
return pdev;
|
||||
|
||||
error:
|
||||
platform_device_put(pdev);
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
|
||||
static int platform_drv_probe(struct device *_dev)
|
||||
{
|
||||
struct platform_driver *drv = to_platform_driver(_dev->driver);
|
||||
@@ -865,7 +912,7 @@ static int platform_pm_restore_noirq(struct device *dev)
|
||||
|
||||
#endif /* !CONFIG_HIBERNATION */
|
||||
|
||||
struct pm_ext_ops platform_pm_ops = {
|
||||
static struct pm_ext_ops platform_pm_ops = {
|
||||
.base = {
|
||||
.prepare = platform_pm_prepare,
|
||||
.complete = platform_pm_complete,
|
||||
|
||||
@@ -83,7 +83,7 @@ void device_pm_add(struct device *dev)
|
||||
* transition is in progress in order to avoid leaving them
|
||||
* unhandled down the road
|
||||
*/
|
||||
WARN_ON(true);
|
||||
dev_WARN(dev, "Parentless device registered during a PM transaction\n");
|
||||
}
|
||||
|
||||
list_add_tail(&dev->power.entry, &dpm_list);
|
||||
|
||||
Reference in New Issue
Block a user