diff options
| -rw-r--r-- | drivers/base/bus.c | 16 | ||||
| -rw-r--r-- | drivers/base/dd.c | 8 | ||||
| -rw-r--r-- | drivers/usb/core/driver.c | 1 | ||||
| -rw-r--r-- | include/linux/device.h | 3 |
4 files changed, 16 insertions, 12 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index ef6183306b40..8bfd27ec73d6 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
| @@ -184,10 +184,10 @@ static ssize_t unbind_store(struct device_driver *drv, const char *buf, | |||
| 184 | 184 | ||
| 185 | dev = bus_find_device_by_name(bus, NULL, buf); | 185 | dev = bus_find_device_by_name(bus, NULL, buf); |
| 186 | if (dev && dev->driver == drv) { | 186 | if (dev && dev->driver == drv) { |
| 187 | if (dev->parent) /* Needed for USB */ | 187 | if (dev->parent && dev->bus->need_parent_lock) |
| 188 | device_lock(dev->parent); | 188 | device_lock(dev->parent); |
| 189 | device_release_driver(dev); | 189 | device_release_driver(dev); |
| 190 | if (dev->parent) | 190 | if (dev->parent && dev->bus->need_parent_lock) |
| 191 | device_unlock(dev->parent); | 191 | device_unlock(dev->parent); |
| 192 | err = count; | 192 | err = count; |
| 193 | } | 193 | } |
| @@ -211,12 +211,12 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf, | |||
| 211 | 211 | ||
| 212 | dev = bus_find_device_by_name(bus, NULL, buf); | 212 | dev = bus_find_device_by_name(bus, NULL, buf); |
| 213 | if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { | 213 | if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { |
| 214 | if (dev->parent) /* Needed for USB */ | 214 | if (dev->parent && bus->need_parent_lock) |
| 215 | device_lock(dev->parent); | 215 | device_lock(dev->parent); |
| 216 | device_lock(dev); | 216 | device_lock(dev); |
| 217 | err = driver_probe_device(drv, dev); | 217 | err = driver_probe_device(drv, dev); |
| 218 | device_unlock(dev); | 218 | device_unlock(dev); |
| 219 | if (dev->parent) | 219 | if (dev->parent && bus->need_parent_lock) |
| 220 | device_unlock(dev->parent); | 220 | device_unlock(dev->parent); |
| 221 | 221 | ||
| 222 | if (err > 0) { | 222 | if (err > 0) { |
| @@ -735,10 +735,10 @@ static int __must_check bus_rescan_devices_helper(struct device *dev, | |||
| 735 | int ret = 0; | 735 | int ret = 0; |
| 736 | 736 | ||
| 737 | if (!dev->driver) { | 737 | if (!dev->driver) { |
| 738 | if (dev->parent) /* Needed for USB */ | 738 | if (dev->parent && dev->bus->need_parent_lock) |
| 739 | device_lock(dev->parent); | 739 | device_lock(dev->parent); |
| 740 | ret = device_attach(dev); | 740 | ret = device_attach(dev); |
| 741 | if (dev->parent) | 741 | if (dev->parent && dev->bus->need_parent_lock) |
| 742 | device_unlock(dev->parent); | 742 | device_unlock(dev->parent); |
| 743 | } | 743 | } |
| 744 | return ret < 0 ? ret : 0; | 744 | return ret < 0 ? ret : 0; |
| @@ -770,10 +770,10 @@ EXPORT_SYMBOL_GPL(bus_rescan_devices); | |||
| 770 | int device_reprobe(struct device *dev) | 770 | int device_reprobe(struct device *dev) |
| 771 | { | 771 | { |
| 772 | if (dev->driver) { | 772 | if (dev->driver) { |
| 773 | if (dev->parent) /* Needed for USB */ | 773 | if (dev->parent && dev->bus->need_parent_lock) |
| 774 | device_lock(dev->parent); | 774 | device_lock(dev->parent); |
| 775 | device_release_driver(dev); | 775 | device_release_driver(dev); |
| 776 | if (dev->parent) | 776 | if (dev->parent && dev->bus->need_parent_lock) |
| 777 | device_unlock(dev->parent); | 777 | device_unlock(dev->parent); |
| 778 | } | 778 | } |
| 779 | return bus_rescan_devices_helper(dev, NULL); | 779 | return bus_rescan_devices_helper(dev, NULL); |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index c9f54089429b..7c09f73b96f3 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c | |||
| @@ -817,13 +817,13 @@ static int __driver_attach(struct device *dev, void *data) | |||
| 817 | return ret; | 817 | return ret; |
| 818 | } /* ret > 0 means positive match */ | 818 | } /* ret > 0 means positive match */ |
| 819 | 819 | ||
| 820 | if (dev->parent) /* Needed for USB */ | 820 | if (dev->parent && dev->bus->need_parent_lock) |
| 821 | device_lock(dev->parent); | 821 | device_lock(dev->parent); |
| 822 | device_lock(dev); | 822 | device_lock(dev); |
| 823 | if (!dev->driver) | 823 | if (!dev->driver) |
| 824 | driver_probe_device(drv, dev); | 824 | driver_probe_device(drv, dev); |
| 825 | device_unlock(dev); | 825 | device_unlock(dev); |
| 826 | if (dev->parent) | 826 | if (dev->parent && dev->bus->need_parent_lock) |
| 827 | device_unlock(dev->parent); | 827 | device_unlock(dev->parent); |
| 828 | 828 | ||
| 829 | return 0; | 829 | return 0; |
| @@ -919,7 +919,7 @@ void device_release_driver_internal(struct device *dev, | |||
| 919 | struct device_driver *drv, | 919 | struct device_driver *drv, |
| 920 | struct device *parent) | 920 | struct device *parent) |
| 921 | { | 921 | { |
| 922 | if (parent) | 922 | if (parent && dev->bus->need_parent_lock) |
| 923 | device_lock(parent); | 923 | device_lock(parent); |
| 924 | 924 | ||
| 925 | device_lock(dev); | 925 | device_lock(dev); |
| @@ -927,7 +927,7 @@ void device_release_driver_internal(struct device *dev, | |||
| 927 | __device_release_driver(dev, parent); | 927 | __device_release_driver(dev, parent); |
| 928 | 928 | ||
| 929 | device_unlock(dev); | 929 | device_unlock(dev); |
| 930 | if (parent) | 930 | if (parent && dev->bus->need_parent_lock) |
| 931 | device_unlock(parent); | 931 | device_unlock(parent); |
| 932 | } | 932 | } |
| 933 | 933 | ||
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 9792cedfc351..e76e95f62f76 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
| @@ -1922,4 +1922,5 @@ struct bus_type usb_bus_type = { | |||
| 1922 | .name = "usb", | 1922 | .name = "usb", |
| 1923 | .match = usb_device_match, | 1923 | .match = usb_device_match, |
| 1924 | .uevent = usb_uevent, | 1924 | .uevent = usb_uevent, |
| 1925 | .need_parent_lock = true, | ||
| 1925 | }; | 1926 | }; |
diff --git a/include/linux/device.h b/include/linux/device.h index 477956990f5e..beca424395dd 100644 --- a/include/linux/device.h +++ b/include/linux/device.h | |||
| @@ -98,6 +98,8 @@ extern void bus_remove_file(struct bus_type *, struct bus_attribute *); | |||
| 98 | * @lock_key: Lock class key for use by the lock validator | 98 | * @lock_key: Lock class key for use by the lock validator |
| 99 | * @force_dma: Assume devices on this bus should be set up by dma_configure() | 99 | * @force_dma: Assume devices on this bus should be set up by dma_configure() |
| 100 | * even if DMA capability is not explicitly described by firmware. | 100 | * even if DMA capability is not explicitly described by firmware. |
| 101 | * @need_parent_lock: When probing or removing a device on this bus, the | ||
| 102 | * device core should lock the device's parent. | ||
| 101 | * | 103 | * |
| 102 | * A bus is a channel between the processor and one or more devices. For the | 104 | * A bus is a channel between the processor and one or more devices. For the |
| 103 | * purposes of the device model, all devices are connected via a bus, even if | 105 | * purposes of the device model, all devices are connected via a bus, even if |
| @@ -138,6 +140,7 @@ struct bus_type { | |||
| 138 | struct lock_class_key lock_key; | 140 | struct lock_class_key lock_key; |
| 139 | 141 | ||
| 140 | bool force_dma; | 142 | bool force_dma; |
| 143 | bool need_parent_lock; | ||
| 141 | }; | 144 | }; |
| 142 | 145 | ||
| 143 | extern int __must_check bus_register(struct bus_type *bus); | 146 | extern int __must_check bus_register(struct bus_type *bus); |
