diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2009-03-04 06:44:00 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-03-24 19:38:26 -0400 |
commit | ffa6a7054d172a2f57248dff2de600ca795c5656 (patch) | |
tree | f93c6234bb90295c52fcef09e367ed77ff6c3645 /drivers/base/core.c | |
parent | 60530afe1ee8a5532cb09d0ab5bc3f1a6495b780 (diff) |
Driver core: Fix device_move() vs. dpm list ordering, v2
dpm_list currently relies on the fact that child devices will
be registered after their parents to get a correct suspend
order. Using device_move() however destroys this assumption, as
an already registered device may be moved under a newly registered
one.
This patch adds a new argument to device_move(), allowing callers
to specify how dpm_list should be adapted.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/base/core.c')
-rw-r--r-- | drivers/base/core.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index 95c67ffd71da..e73c92d13a23 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -1561,8 +1561,10 @@ out: | |||
1561 | * device_move - moves a device to a new parent | 1561 | * device_move - moves a device to a new parent |
1562 | * @dev: the pointer to the struct device to be moved | 1562 | * @dev: the pointer to the struct device to be moved |
1563 | * @new_parent: the new parent of the device (can by NULL) | 1563 | * @new_parent: the new parent of the device (can by NULL) |
1564 | * @dpm_order: how to reorder the dpm_list | ||
1564 | */ | 1565 | */ |
1565 | int device_move(struct device *dev, struct device *new_parent) | 1566 | int device_move(struct device *dev, struct device *new_parent, |
1567 | enum dpm_order dpm_order) | ||
1566 | { | 1568 | { |
1567 | int error; | 1569 | int error; |
1568 | struct device *old_parent; | 1570 | struct device *old_parent; |
@@ -1572,6 +1574,7 @@ int device_move(struct device *dev, struct device *new_parent) | |||
1572 | if (!dev) | 1574 | if (!dev) |
1573 | return -EINVAL; | 1575 | return -EINVAL; |
1574 | 1576 | ||
1577 | device_pm_lock(); | ||
1575 | new_parent = get_device(new_parent); | 1578 | new_parent = get_device(new_parent); |
1576 | new_parent_kobj = get_device_parent(dev, new_parent); | 1579 | new_parent_kobj = get_device_parent(dev, new_parent); |
1577 | 1580 | ||
@@ -1613,9 +1616,23 @@ int device_move(struct device *dev, struct device *new_parent) | |||
1613 | put_device(new_parent); | 1616 | put_device(new_parent); |
1614 | goto out; | 1617 | goto out; |
1615 | } | 1618 | } |
1619 | switch (dpm_order) { | ||
1620 | case DPM_ORDER_NONE: | ||
1621 | break; | ||
1622 | case DPM_ORDER_DEV_AFTER_PARENT: | ||
1623 | device_pm_move_after(dev, new_parent); | ||
1624 | break; | ||
1625 | case DPM_ORDER_PARENT_BEFORE_DEV: | ||
1626 | device_pm_move_before(new_parent, dev); | ||
1627 | break; | ||
1628 | case DPM_ORDER_DEV_LAST: | ||
1629 | device_pm_move_last(dev); | ||
1630 | break; | ||
1631 | } | ||
1616 | out_put: | 1632 | out_put: |
1617 | put_device(old_parent); | 1633 | put_device(old_parent); |
1618 | out: | 1634 | out: |
1635 | device_pm_unlock(); | ||
1619 | put_device(dev); | 1636 | put_device(dev); |
1620 | return error; | 1637 | return error; |
1621 | } | 1638 | } |