diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-24 10:13:55 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-02-24 10:13:55 -0800 |
commit | 7ac1161c2789be25d0d206e831b051f43028866e (patch) | |
tree | b9e79ea15b34f9be500539beeeeb20d298628ac0 /drivers/gpio | |
parent | a4dec04c7ff4307973ba502ce7b27330d9fe04b7 (diff) | |
parent | 3e4c982f1ce75faf5314477b8da296d2d00919df (diff) |
Merge tag 'driver-core-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core
Pull driver core / debugfs update from Greg KH:
"Here is the "big" driver core and debugfs update for 5.12-rc1
This set of driver core patches caused a bunch of problems in
linux-next for the past few weeks, when Saravana tried to set
fw_devlink=on as the default functionality. This caused a number of
systems to stop booting, and lots of bugs were fixed in this area for
almost all of the reported systems, but this option is not ready to be
turned on just yet for the default operation based on this testing, so
I've reverted that change at the very end so we don't have to worry
about regressions in 5.12
We will try to turn this on for 5.13 if testing goes better over the
next few months.
Other than the fixes caused by the fw_devlink testing in here, there's
not much more:
- debugfs fixes for invalid input into debugfs_lookup()
- kerneldoc cleanups
- warn message if platform drivers return an error on their remove
callback (a futile effort, but good to catch).
All of these have been in linux-next for a while now, and the
regressions have gone away with the revert of the fw_devlink change"
* tag 'driver-core-5.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core: (35 commits)
Revert "driver core: Set fw_devlink=on by default"
of: property: fw_devlink: Ignore interrupts property for some configs
debugfs: do not attempt to create a new file before the filesystem is initalized
debugfs: be more robust at handling improper input in debugfs_lookup()
driver core: auxiliary bus: Fix calling stage for auxiliary bus init
of: irq: Fix the return value for of_irq_parse_one() stub
of: irq: make a stub for of_irq_parse_one()
clk: Mark fwnodes when their clock provider is added/removed
PM: domains: Mark fwnodes when their powerdomain is added/removed
irqdomain: Mark fwnodes when their irqdomain is added/removed
driver core: fw_devlink: Handle suppliers that don't use driver core
of: property: Add fw_devlink support for optional properties
driver core: Add fw_devlink.strict kernel param
of: property: Don't add links to absent suppliers
driver core: fw_devlink: Detect supplier devices that will never be added
driver core: platform: Emit a warning if a remove callback returned non-zero
of: property: Fix fw_devlink handling of interrupts/interrupts-extended
gpiolib: Don't probe gpio_device if it's not the primary device
device.h: Remove bogus "the" in kerneldoc
gpiolib: Bind gpio_device to a driver to enable fw_devlink=on by default
...
Diffstat (limited to 'drivers/gpio')
-rw-r--r-- | drivers/gpio/gpiolib-of.c | 11 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-of.h | 5 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 52 |
3 files changed, 61 insertions, 7 deletions
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index b4a71119a4b0..baf0153b7bca 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -1039,3 +1039,14 @@ void of_gpiochip_remove(struct gpio_chip *chip) { of_node_put(chip->of_node); } + +void of_gpio_dev_init(struct gpio_chip *gc, struct gpio_device *gdev) +{ + /* If the gpiochip has an assigned OF node this takes precedence */ + if (gc->of_node) + gdev->dev.of_node = gc->of_node; + else + gc->of_node = gdev->dev.of_node; + if (gdev->dev.of_node) + gdev->dev.fwnode = of_fwnode_handle(gdev->dev.of_node); +} diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h index ed26664f1537..8af2bc899aab 100644 --- a/drivers/gpio/gpiolib-of.h +++ b/drivers/gpio/gpiolib-of.h @@ -15,6 +15,7 @@ int of_gpiochip_add(struct gpio_chip *gc); void of_gpiochip_remove(struct gpio_chip *gc); int of_gpio_get_count(struct device *dev, const char *con_id); bool of_gpio_need_valid_mask(const struct gpio_chip *gc); +void of_gpio_dev_init(struct gpio_chip *gc, struct gpio_device *gdev); #else static inline struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, @@ -33,6 +34,10 @@ static inline bool of_gpio_need_valid_mask(const struct gpio_chip *gc) { return false; } +static inline void of_gpio_dev_init(struct gpio_chip *gc, + struct gpio_device *gdev) +{ +} #endif /* CONFIG_OF_GPIO */ extern struct notifier_block gpio_of_notifier; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 844198cb4e31..adf55db080d8 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -56,8 +56,10 @@ static DEFINE_IDA(gpio_ida); static dev_t gpio_devt; #define GPIO_DEV_MAX 256 /* 256 GPIO chip devices supported */ +static int gpio_bus_match(struct device *dev, struct device_driver *drv); static struct bus_type gpio_bus_type = { .name = "gpio", + .match = gpio_bus_match, }; /* @@ -590,13 +592,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, gdev->dev.of_node = gc->parent->of_node; } -#ifdef CONFIG_OF_GPIO - /* If the gpiochip has an assigned OF node this takes precedence */ - if (gc->of_node) - gdev->dev.of_node = gc->of_node; - else - gc->of_node = gdev->dev.of_node; -#endif + of_gpio_dev_init(gc, gdev); gdev->id = ida_alloc(&gpio_ida, GFP_KERNEL); if (gdev->id < 0) { @@ -4215,6 +4211,41 @@ void gpiod_put_array(struct gpio_descs *descs) } EXPORT_SYMBOL_GPL(gpiod_put_array); + +static int gpio_bus_match(struct device *dev, struct device_driver *drv) +{ + /* + * Only match if the fwnode doesn't already have a proper struct device + * created for it. + */ + if (dev->fwnode && dev->fwnode->dev != dev) + return 0; + return 1; +} + +static int gpio_stub_drv_probe(struct device *dev) +{ + /* + * The DT node of some GPIO chips have a "compatible" property, but + * never have a struct device added and probed by a driver to register + * the GPIO chip with gpiolib. In such cases, fw_devlink=on will cause + * the consumers of the GPIO chip to get probe deferred forever because + * they will be waiting for a device associated with the GPIO chip + * firmware node to get added and bound to a driver. + * + * To allow these consumers to probe, we associate the struct + * gpio_device of the GPIO chip with the firmware node and then simply + * bind it to this stub driver. + */ + return 0; +} + +static struct device_driver gpio_stub_drv = { + .name = "gpio_stub_drv", + .bus = &gpio_bus_type, + .probe = gpio_stub_drv_probe, +}; + static int __init gpiolib_dev_init(void) { int ret; @@ -4226,9 +4257,16 @@ static int __init gpiolib_dev_init(void) return ret; } + if (driver_register(&gpio_stub_drv) < 0) { + pr_err("gpiolib: could not register GPIO stub driver\n"); + bus_unregister(&gpio_bus_type); + return ret; + } + ret = alloc_chrdev_region(&gpio_devt, 0, GPIO_DEV_MAX, GPIOCHIP_NAME); if (ret < 0) { pr_err("gpiolib: failed to allocate char dev region\n"); + driver_unregister(&gpio_stub_drv); bus_unregister(&gpio_bus_type); return ret; } |