Hi Frank, On Tue, Jan 7, 2020 at 12:34 AM Frank Rowand <frowand.list@xxxxxxxxx> wrote: > On 12/30/19 7:38 AM, Geert Uytterhoeven wrote: > > As GPIO hogs are configured at GPIO controller initialization time, > > adding/removing GPIO hogs in DT overlays does not work. > > > > Add support for GPIO hogs described in DT overlays by registering an OF > > reconfiguration notifier, to handle the addition and removal of GPIO hog > > subnodes to/from a GPIO controller device node. > > > > Note that when a GPIO hog device node is being removed, its "gpios" > > properties is no longer available, so we have to keep track of which > > node a hog belongs to, which is done by adding a pointer to the hog's > > device node to struct gpio_desc. > > If I have read the patches and the existing overlay source correctly, > then some observations: > > - A gpio hog node added in an overlay will be properly processed. > > - A gpio hog node already existing in the live devicetree, but with a > non-active status will be properly processed if the status of the > gpio hog node is changed to "ok" in the overlay. > > - If a gpio hog node already exists in the live devicetree with an > active status, then any updated or added properties in that gpio > hog node in the overlay will have no effect. > > There is a scenario where the updated property would have an effect: > apply a second overlay that sets the status to inactive, then apply > a third overlay that sets the status back to active. This is a > rather contrived example and I think it should be documented as > not supported and the result undefined. > > It would be good to document this explicitly. I didn't verify this in detail, but I believe the existing overlay support for platform, i2c, and SPI devices behaves the same. > > --- a/drivers/gpio/gpiolib-of.c > > +++ b/drivers/gpio/gpiolib-of.c > > +static int of_gpio_notify(struct notifier_block *nb, unsigned long action, > > + void *arg) > > +{ > > + struct of_reconfig_data *rd = arg; > > + struct gpio_chip *chip; > > + int ret; > > + > > + switch (of_reconfig_get_state_change(action, arg)) { > > + case OF_RECONFIG_CHANGE_ADD: > > + if (!of_property_read_bool(rd->dn, "gpio-hog")) > > + return NOTIFY_OK; /* not for us */ > > + > > + if (of_node_test_and_set_flag(rd->dn, OF_POPULATED)) > > + return NOTIFY_OK; > > I don't think OF_POPULATED could be already set. It seems to be a > bug if it is. For a real gpio-hog it indeed is not. But this function is called for every change made to the device tree (add a printk() and look at the output during boot). So this serves as a (cheap) line of defense. The of_find_gpiochip_by_node() call below is more expensive to call. > > + > > + chip = of_find_gpiochip_by_node(rd->dn->parent); > > + if (chip == NULL) > > + return NOTIFY_OK; /* not for us */ > > If I understand correctly, "not for us" is a misleading comment. > The notification is for the node rd->dn->parent, but the device > does not exist, so we can't do the hogging at the moment. (If the > device is created later, then the gpio hog child node will exist, > and the init will "do the right thing" with the hog node -- so > not a problem.) This function is called for all additions to the device tree. So rd->dn->parent may not even be a gpio controller node. Hence unless this is a gpio controller node for this hog, this notification is "not for us". > > + > > + ret = of_gpiochip_add_hog(chip, rd->dn); > > + if (ret < 0) { > > + pr_err("%s: failed to add hogs for %pOF\n", __func__, > > + rd->dn); > > + of_node_clear_flag(rd->dn, OF_POPULATED); > > + return notifier_from_errno(ret); > > + } > > + break; > > + > > + case OF_RECONFIG_CHANGE_REMOVE: > > + if (!of_node_check_flag(rd->dn, OF_POPULATED)) > > + return NOTIFY_OK; /* already depopulated */ > > I don't think OF_POPULATED could be already cleared. It seems to be a > bug if it is. Same here. First line of defense. > > + > > + chip = of_find_gpiochip_by_node(rd->dn->parent); > > + if (chip == NULL) > > + return NOTIFY_OK; /* not for us */ > > Again, a misleading comment. Same here. rd->dn->parent may be something else. > > + > > + of_gpiochip_remove_hog(chip, rd->dn); > > + of_node_clear_flag(rd->dn, OF_POPULATED); > > + break; > > + } > > + > > + return NOTIFY_OK; > > +} Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds