aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/base/bus.c16
-rw-r--r--drivers/base/dd.c8
-rw-r--r--drivers/usb/core/driver.c1
-rw-r--r--include/linux/device.h3
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);
770int device_reprobe(struct device *dev) 770int 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
143extern int __must_check bus_register(struct bus_type *bus); 146extern int __must_check bus_register(struct bus_type *bus);