1
0
Fork 0

pinctrl: Initialize pinctrl_dev.node

The struct pinctrl_dev's node field is not properly set up, which means
the .prev and .next fields will be NULL. That's not something that the
linked list code can deal with, so extra care must be taken when using
these fields. An example of this is introduced in commit 3429fb3cda
("pinctrl: Fix panic when pinctrl devices with hogs are unregistered")
where list_del() is made conditional on the pinctrl device being part
of the pinctrl device list. This is to ensure that list_del() won't
crash upon encountering a NULL pointer in .prev and/or .next.

After initializing the list head there's no need to jump through these
extra hoops and list_del() will work unconditionally. This is because
the initialized list head points to itself and therefore the .prev and
.next fields can be properly dereferenced.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Acked-by: Jon Hunter <jonathanh@nvidia.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
hifive-unleashed-5.1
Thierry Reding 2017-01-12 17:03:34 +01:00 committed by Linus Walleij
parent 950b0d91dc
commit 46daed6ebd
1 changed files with 2 additions and 4 deletions

View File

@ -1938,6 +1938,7 @@ struct pinctrl_dev *pinctrl_init_controller(struct pinctrl_desc *pctldesc,
INIT_RADIX_TREE(&pctldev->pin_function_tree, GFP_KERNEL);
#endif
INIT_LIST_HEAD(&pctldev->gpio_ranges);
INIT_LIST_HEAD(&pctldev->node);
pctldev->dev = dev;
mutex_init(&pctldev->mutex);
@ -2089,7 +2090,6 @@ EXPORT_SYMBOL_GPL(pinctrl_register_and_init);
void pinctrl_unregister(struct pinctrl_dev *pctldev)
{
struct pinctrl_gpio_range *range, *n;
struct pinctrl_dev *p, *p1;
if (pctldev == NULL)
return;
@ -2104,9 +2104,7 @@ void pinctrl_unregister(struct pinctrl_dev *pctldev)
mutex_lock(&pinctrldev_list_mutex);
mutex_lock(&pctldev->mutex);
/* TODO: check that no pinmuxes are still active? */
list_for_each_entry_safe(p, p1, &pinctrldev_list, node)
if (p == pctldev)
list_del(&p->node);
list_del(&pctldev->node);
pinmux_generic_free_functions(pctldev);
pinctrl_generic_free_groups(pctldev);
/* Destroy descriptor tree */