diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 7e2690d92df6..32ded7b548fb 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -7,6 +7,7 @@ // Authors: Daniel Mack, Juergen Beisert. // Copyright (C) 2004-2010 Freescale Semiconductor, Inc. All Rights Reserved. +#include #include #include #include @@ -68,11 +69,11 @@ struct mxc_gpio_port { struct irq_domain *domain; struct gpio_generic_chip gen_gc; struct device *dev; - u32 both_edges; + unsigned long both_edges; struct mxc_gpio_reg_saved gpio_saved_reg; bool power_off; - u32 wakeup_pads; bool is_pad_wakeup; + unsigned long wakeup_pads; u32 pad_type[32]; const struct mxc_gpio_hwdata *hwdata; }; @@ -168,7 +169,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) int edge; void __iomem *reg = port->base; - port->both_edges &= ~(1 << gpio_idx); + clear_bit(gpio_idx, &port->both_edges); switch (type) { case IRQ_TYPE_EDGE_RISING: edge = GPIO_INT_RISE_EDGE; @@ -188,7 +189,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type) edge = GPIO_INT_HIGH_LEV; pr_debug("mxc: set GPIO %d to high trigger\n", gpio_idx); } - port->both_edges |= 1 << gpio_idx; + set_bit(gpio_idx, &port->both_edges); } break; case IRQ_TYPE_LEVEL_LOW: @@ -259,7 +260,7 @@ static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat) while (irq_stat != 0) { int irqoffset = fls(irq_stat) - 1; - if (port->both_edges & (1 << irqoffset)) + if (test_bit(irqoffset, &port->both_edges)) mxc_flip_edge(port, irqoffset); generic_handle_domain_irq(port->domain, irqoffset); @@ -330,16 +331,18 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable) ret = enable_irq_wake(port->irq_high); else ret = enable_irq_wake(port->irq); - port->wakeup_pads |= BIT(gpio_idx); } else { if (port->irq_high && (gpio_idx >= 16)) ret = disable_irq_wake(port->irq_high); else ret = disable_irq_wake(port->irq); - port->wakeup_pads &= ~BIT(gpio_idx); } + if (ret) + return ret; - return ret; + assign_bit(gpio_idx, &port->wakeup_pads, enable); + + return 0; } static int mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base) @@ -474,8 +477,6 @@ static int mxc_gpio_probe(struct platform_device *pdev) } else port->mx_irq_handler = mx3_gpio_irq_handler; - mxc_update_irq_chained_handler(port, true); - config.dev = &pdev->dev; config.sz = 4; config.dat = port->base + GPIO_PSR; @@ -499,10 +500,6 @@ static int mxc_gpio_probe(struct platform_device *pdev) else /* silence boot time warning */ port->gen_gc.gc.base = -1; - err = devm_gpiochip_add_data(&pdev->dev, &port->gen_gc.gc, port); - if (err) - goto out_bgio; - irq_base = devm_irq_alloc_descs(&pdev->dev, -1, 0, 32, numa_node_id()); if (irq_base < 0) { err = irq_base; @@ -523,8 +520,19 @@ static int mxc_gpio_probe(struct platform_device *pdev) if (err < 0) goto out_irqdomain_remove; + /* + * Register the GPIO chip last: devm_gpiochip_add_data() makes the + * chip visible to consumers immediately, so the IRQ domain and + * generic irq chip must be ready before any to_irq() call. + */ + err = devm_gpiochip_add_data(&pdev->dev, &port->gen_gc.gc, port); + if (err) + goto out_irqdomain_remove; + list_add_tail(&port->node, &mxc_gpio_ports); + mxc_update_irq_chained_handler(port, true); + platform_set_drvdata(pdev, port); pm_runtime_put_autosuspend(&pdev->dev); diff --git a/drivers/gpio/gpio-nct6694.c b/drivers/gpio/gpio-nct6694.c index a8607f0d9915..a38add1cde29 100644 --- a/drivers/gpio/gpio-nct6694.c +++ b/drivers/gpio/gpio-nct6694.c @@ -444,7 +444,7 @@ static int nct6694_gpio_probe(struct platform_device *pdev) data->gpio.set_config = nct6694_set_config; data->gpio.init_valid_mask = nct6694_init_valid_mask; data->gpio.base = -1; - data->gpio.can_sleep = false; + data->gpio.can_sleep = true; data->gpio.owner = THIS_MODULE; data->gpio.ngpio = NCT6694_NR_GPIO; diff --git a/drivers/gpio/gpiolib-kunit.c b/drivers/gpio/gpiolib-kunit.c index e6cb43a8df5b..6a2c8b34f34b 100644 --- a/drivers/gpio/gpiolib-kunit.c +++ b/drivers/gpio/gpiolib-kunit.c @@ -28,6 +28,8 @@ #define GPIO_TEST_PROVIDER_NGPIO 4 +KUNIT_DEFINE_ACTION_WRAPPER(gpio_device_put_wrapper, gpio_device_put, struct gpio_device *); + /* * The test provider tracks per-line direction and value so that lines can be * driven as both inputs and outputs - this is needed to exercise input as well @@ -770,6 +772,7 @@ static void gpio_hog_assert(struct kunit *test, unsigned int offset, struct property_entry properties[2]; struct platform_device *pdev; struct fwnode_handle *fwnode; + struct gpio_device *gdev; struct gpio_desc *desc; bool bound = true; int ret; @@ -789,10 +792,12 @@ static void gpio_hog_assert(struct kunit *test, unsigned int offset, wait_for_device_probe(); /* The hog must have configured the line with the expected direction. */ - struct gpio_device *gdev __free(gpio_device_put) = - gpio_device_find_by_label(GPIO_CONSUMER_NAME); + gdev = gpio_device_find_by_label(GPIO_CONSUMER_NAME); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gdev); + ret = kunit_add_action_or_reset(test, gpio_device_put_wrapper, gdev); + KUNIT_ASSERT_EQ(test, ret, 0); + desc = gpio_device_get_desc(gdev, offset); KUNIT_ASSERT_NOT_ERR_OR_NULL(test, desc); diff --git a/drivers/gpio/gpiolib-shared.c b/drivers/gpio/gpiolib-shared.c index 5f9623e40b0f..8c9ac9d93304 100644 --- a/drivers/gpio/gpiolib-shared.c +++ b/drivers/gpio/gpiolib-shared.c @@ -449,10 +449,14 @@ static bool gpio_shared_dev_is_reset_gpio(struct device *consumer, int gpio_shared_add_proxy_lookup(struct device *consumer, struct fwnode_handle *fwnode, const char *con_id, unsigned long lflags) { - const char *dev_id = dev_name(consumer); - struct gpiod_lookup_table *lookup; struct gpio_shared_entry *entry; struct gpio_shared_ref *ref; + const char *dev_id; + + if (!consumer) + return -EOPNOTSUPP; + + dev_id = dev_name(consumer); list_for_each_entry(entry, &gpio_shared_list, list) { list_for_each_entry(ref, &entry->refs, list) { @@ -480,18 +484,22 @@ int gpio_shared_add_proxy_lookup(struct device *consumer, struct fwnode_handle * if (!key) return -ENOMEM; - lookup = kzalloc_flex(*lookup, table, 2); + struct gpiod_lookup_table *lookup __free(kfree) = + kzalloc_flex(*lookup, table, 2); if (!lookup) return -ENOMEM; pr_debug("Adding machine lookup entry for a shared GPIO for consumer %s, with key '%s' and con_id '%s'\n", dev_id, key, ref->con_id ?: "none"); - lookup->dev_id = dev_id; + lookup->dev_id = kstrdup(dev_id, GFP_KERNEL); + if (!lookup->dev_id) + return -ENOMEM; + lookup->table[0] = GPIO_LOOKUP(no_free_ptr(key), 0, ref->con_id, lflags); - ref->lookup = lookup; + ref->lookup = no_free_ptr(lookup); gpiod_add_lookup_table(ref->lookup); return 0; @@ -611,6 +619,7 @@ void gpio_device_teardown_shared(struct gpio_device *gdev) if (ref->lookup) { gpiod_remove_lookup_table(ref->lookup); kfree(ref->lookup->table[0].key); + kfree(ref->lookup->dev_id); kfree(ref->lookup); ref->lookup = NULL; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 772c6f04f489..c0394c7d6279 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -3954,16 +3954,17 @@ int gpiod_set_array_value_complex(bool raw, bool can_sleep, } while ((i < array_size) && gpio_device_chip_cmp(desc_array[i]->gdev, guard.gc)); /* push collected bits to outputs */ - if (count != 0) { + ret = 0; + if (count != 0) ret = gpiochip_set_multiple(guard.gc, mask, bits); - if (ret) - return ret; - } if (mask != fastpath_mask) bitmap_free(mask); if (bits != fastpath_bits) bitmap_free(bits); + + if (ret) + return ret; } return 0; } diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile index 342e056c8c66..1cd7636b9cac 100644 --- a/tools/gpio/Makefile +++ b/tools/gpio/Makefile @@ -7,7 +7,13 @@ bindir ?= /usr/bin # isn't set and when invoked from selftests build, where srctree # is set to ".". building_out_of_srctree is undefined for in srctree # builds +ifeq ($(srctree),) +update_srctree := 1 +endif ifndef building_out_of_srctree +update_srctree := 1 +endif +ifeq ($(update_srctree),1) srctree := $(patsubst %/,%,$(dir $(CURDIR))) srctree := $(patsubst %/,%,$(dir $(srctree))) endif