From 4e75e1d7dac9d7c95c57eceb451d01f2afcc8626 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 6 Jun 2017 17:59:00 +0200 Subject: driver core: add helper to reuse a device-tree node Add a helper function to be used when reusing the device-tree node of another device. It is fairly common for drivers to reuse the device-tree node of a parent (or other ancestor) device when creating class or bus devices (e.g. gpio chips, i2c adapters, iio chips, spi masters, serdev, phys, usb root hubs). But reusing a device-tree node may cause problems if the new device is later probed as for example driver core would currently attempt to reinitialise an already active associated pinmux configuration. Other potential issues include the platform-bus code unconditionally dropping the device-tree node reference in its device destructor, reinitialisation of other bus-managed resources such as clocks, and the recently added DMA-setup in driver core. Note that for most examples above this is currently not an issue as the devices are never probed, but this is a problem for the USB bus which has recently gained device-tree support. This was discovered and worked-around in a rather ad-hoc fashion by commit dc5878abf49c ("usb: core: move root hub's device node assignment after it is added to bus") by not setting the of_node pointer until after the root-hub device has been registered. Instead we can allow devices to reuse a device-tree node by setting a flag in their struct device that can be used by core, bus and driver code to avoid resources from being over-allocated. Note that the helper also grabs an extra reference to the device node, which specifically balances the unconditional put in the platform-device destructor. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/core.c b/drivers/base/core.c index bbecaf9293be..c3064ff09af5 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2884,3 +2884,19 @@ void set_secondary_fwnode(struct device *dev, struct fwnode_handle *fwnode) else dev->fwnode = fwnode; } + +/** + * device_set_of_node_from_dev - reuse device-tree node of another device + * @dev: device whose device-tree node is being set + * @dev2: device whose device-tree node is being reused + * + * Takes another reference to the new device-tree node after first dropping + * any reference held to the old node. + */ +void device_set_of_node_from_dev(struct device *dev, const struct device *dev2) +{ + of_node_put(dev->of_node); + dev->of_node = of_node_get(dev2->of_node); + dev->of_node_reused = true; +} +EXPORT_SYMBOL_GPL(device_set_of_node_from_dev); -- cgit v1.2.3 From ed032c1bede83ec9bd5f7e803e663cb7f76e5947 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Tue, 6 Jun 2017 17:59:01 +0200 Subject: driver core: fix automatic pinctrl management Commit ab78029ecc34 ("drivers/pinctrl: grab default handles from device core") added automatic pin-control management to driver core by looking up and setting any default pinctrl state found in device tree while a device is being probed. This obviously runs into problems as soon as device-tree nodes are reused for child devices which are later also probed as pins would already have been claimed by the ancestor device. For example if a USB host controller claims a pin, its root hub would consequently fail to probe when its device-tree node is set to the node of the controller: pinctrl-single 48002030.pinmux: pin PIN204 already requested by 48064800.ehci; cannot claim for usb1 pinctrl-single 48002030.pinmux: pin-204 (usb1) status -22 pinctrl-single 48002030.pinmux: could not request pin 204 (PIN204) from group usb_dbg_pins on device pinctrl-single usb usb1: Error applying setting, reverse things back usb: probe of usb1 failed with error -22 Fix this by checking the new of_node_reused flag and skipping automatic pinctrl configuration during probe if set. Note that the flag is checked in driver core rather than in pinctrl (e.g. in pinctrl_dt_to_map()) which would specifically have prevented intentional use of a parent's pinctrl properties by a child device (should such a need ever arise). Fixes: ab78029ecc34 ("drivers/pinctrl: grab default handles from device core") Acked-by: Linus Walleij Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- drivers/base/pinctrl.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/pinctrl.c b/drivers/base/pinctrl.c index 5917b4b5fb99..eb929dd6ef1e 100644 --- a/drivers/base/pinctrl.c +++ b/drivers/base/pinctrl.c @@ -23,6 +23,9 @@ int pinctrl_bind_pins(struct device *dev) { int ret; + if (dev->of_node_reused) + return 0; + dev->pins = devm_kzalloc(dev, sizeof(*(dev->pins)), GFP_KERNEL); if (!dev->pins) return -ENOMEM; -- cgit v1.2.3