diff options
-rw-r--r-- | Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml | 1 | ||||
-rw-r--r-- | drivers/gpio/Kconfig | 3 | ||||
-rw-r--r-- | drivers/gpio/TODO | 4 | ||||
-rw-r--r-- | drivers/gpio/gpio-aggregator.c | 16 | ||||
-rw-r--r-- | drivers/gpio/gpio-dwapb.c | 4 | ||||
-rw-r--r-- | drivers/gpio/gpio-mvebu.c | 8 | ||||
-rw-r--r-- | drivers/gpio/gpio-sim.c | 7 | ||||
-rw-r--r-- | drivers/gpio/gpio-xilinx.c | 49 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-cdev.c | 82 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-sysfs.c | 10 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 50 |
11 files changed, 134 insertions, 100 deletions
diff --git a/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml b/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml index 38d37d8f7201..b3e8951959b5 100644 --- a/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml +++ b/Documentation/devicetree/bindings/gpio/st,nomadik-gpio.yaml @@ -89,6 +89,7 @@ examples: interrupts = <0 120 0x4>; #gpio-cells = <2>; gpio-controller; + #interrupt-cells = <2>; interrupt-controller; st,supports-sleepmode; gpio-bank = <1>; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 29d037c6083b..bfa6b5a2c537 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -487,7 +487,7 @@ config GPIO_MT7621 config GPIO_MVEBU def_bool y - depends on PLAT_ORION || ARCH_MVEBU + depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST depends on OF_GPIO select GENERIC_IRQ_CHIP select REGMAP_MMIO @@ -796,7 +796,6 @@ config GPIO_XGENE_SB config GPIO_XILINX tristate "Xilinx GPIO support" select GPIOLIB_IRQCHIP - depends on OF_GPIO help Say yes here to support the Xilinx FPGA GPIO device. diff --git a/drivers/gpio/TODO b/drivers/gpio/TODO index 189c3abe7e79..942d1cd2bd3c 100644 --- a/drivers/gpio/TODO +++ b/drivers/gpio/TODO @@ -61,8 +61,8 @@ Work items: - Change all consumer drivers that #include <linux/of_gpio.h> to #include <linux/gpio/consumer.h> and stop doing custom parsing of the - GPIO lines from the device tree. This can be tricky and often ivolves - changing boardfiles, etc. + GPIO lines from the device tree. This can be tricky and often involves + changing board files, etc. - Pull semantics for legacy device tree (OF) GPIO lookups into gpiolib-of.c: in some cases subsystems are doing custom flags and diff --git a/drivers/gpio/gpio-aggregator.c b/drivers/gpio/gpio-aggregator.c index 38e0fff9afe7..65f41cc3eafc 100644 --- a/drivers/gpio/gpio-aggregator.c +++ b/drivers/gpio/gpio-aggregator.c @@ -65,11 +65,11 @@ static int aggr_parse(struct gpio_aggregator *aggr) { char *args = skip_spaces(aggr->args); char *name, *offsets, *p; - unsigned long *bitmap; unsigned int i, n = 0; int error = 0; - bitmap = bitmap_alloc(AGGREGATOR_MAX_GPIOS, GFP_KERNEL); + unsigned long *bitmap __free(bitmap) = + bitmap_alloc(AGGREGATOR_MAX_GPIOS, GFP_KERNEL); if (!bitmap) return -ENOMEM; @@ -82,7 +82,7 @@ static int aggr_parse(struct gpio_aggregator *aggr) /* Named GPIO line */ error = aggr_add_gpio(aggr, name, U16_MAX, &n); if (error) - goto free_bitmap; + return error; name = offsets; continue; @@ -92,13 +92,13 @@ static int aggr_parse(struct gpio_aggregator *aggr) error = bitmap_parselist(offsets, bitmap, AGGREGATOR_MAX_GPIOS); if (error) { pr_err("Cannot parse %s: %d\n", offsets, error); - goto free_bitmap; + return error; } for_each_set_bit(i, bitmap, AGGREGATOR_MAX_GPIOS) { error = aggr_add_gpio(aggr, name, i, &n); if (error) - goto free_bitmap; + return error; } args = next_arg(args, &name, &p); @@ -106,12 +106,10 @@ static int aggr_parse(struct gpio_aggregator *aggr) if (!n) { pr_err("No GPIOs specified\n"); - error = -EINVAL; + return -EINVAL; } -free_bitmap: - bitmap_free(bitmap); - return error; + return 0; } static ssize_t new_device_store(struct device_driver *driver, const char *buf, diff --git a/drivers/gpio/gpio-dwapb.c b/drivers/gpio/gpio-dwapb.c index 798235791f70..bd374fc27174 100644 --- a/drivers/gpio/gpio-dwapb.c +++ b/drivers/gpio/gpio-dwapb.c @@ -571,7 +571,6 @@ static void dwapb_get_irq(struct device *dev, struct fwnode_handle *fwnode, static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev) { - struct fwnode_handle *fwnode; struct dwapb_platform_data *pdata; struct dwapb_port_property *pp; int nports; @@ -592,7 +591,7 @@ static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev) pdata->nports = nports; i = 0; - device_for_each_child_node(dev, fwnode) { + device_for_each_child_node_scoped(dev, fwnode) { pp = &pdata->properties[i++]; pp->fwnode = fwnode; @@ -600,7 +599,6 @@ static struct dwapb_platform_data *dwapb_gpio_get_pdata(struct device *dev) pp->idx >= DWAPB_MAX_PORTS) { dev_err(dev, "missing/invalid port index for port%d\n", i); - fwnode_handle_put(fwnode); return ERR_PTR(-EINVAL); } diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 8cfd3a89c018..5ffb332e9849 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -794,8 +794,8 @@ static int mvebu_pwm_probe(struct platform_device *pdev, u32 set; if (mvchip->soc_variant == MVEBU_GPIO_SOC_VARIANT_A8K) { - int ret = of_property_read_u32(dev->of_node, - "marvell,pwm-offset", &offset); + int ret = device_property_read_u32(dev, "marvell,pwm-offset", + &offset); if (ret < 0) return 0; } else { @@ -1106,7 +1106,7 @@ static int mvebu_gpio_probe_syscon(struct platform_device *pdev, if (IS_ERR(mvchip->regs)) return PTR_ERR(mvchip->regs); - if (of_property_read_u32(pdev->dev.of_node, "offset", &mvchip->offset)) + if (device_property_read_u32(&pdev->dev, "offset", &mvchip->offset)) return -EINVAL; return 0; @@ -1147,7 +1147,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mvchip); - if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { + if (device_property_read_u32(&pdev->dev, "ngpios", &ngpios)) { dev_err(&pdev->dev, "Missing ngpios OF property\n"); return -ENODEV; } diff --git a/drivers/gpio/gpio-sim.c b/drivers/gpio/gpio-sim.c index dcca1d7f173e..f387dad81f29 100644 --- a/drivers/gpio/gpio-sim.c +++ b/drivers/gpio/gpio-sim.c @@ -520,15 +520,12 @@ static int gpio_sim_add_bank(struct fwnode_handle *swnode, struct device *dev) static int gpio_sim_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct fwnode_handle *swnode; int ret; - device_for_each_child_node(dev, swnode) { + device_for_each_child_node_scoped(dev, swnode) { ret = gpio_sim_add_bank(swnode, dev); - if (ret) { - fwnode_handle_put(swnode); + if (ret) return ret; - } } return 0; diff --git a/drivers/gpio/gpio-xilinx.c b/drivers/gpio/gpio-xilinx.c index afcf432a1573..31bb02e133fa 100644 --- a/drivers/gpio/gpio-xilinx.c +++ b/drivers/gpio/gpio-xilinx.c @@ -15,9 +15,9 @@ #include <linux/io.h> #include <linux/irq.h> #include <linux/module.h> -#include <linux/of.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/property.h> #include <linux/slab.h> /* Register Offset Definitions */ @@ -561,9 +561,9 @@ static const struct irq_chip xgpio_irq_chip = { */ static int xgpio_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct xgpio_instance *chip; int status = 0; - struct device_node *np = pdev->dev.of_node; u32 is_dual = 0; u32 width[2]; u32 state[2]; @@ -571,14 +571,14 @@ static int xgpio_probe(struct platform_device *pdev) struct gpio_irq_chip *girq; u32 temp; - chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); + chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL); if (!chip) return -ENOMEM; platform_set_drvdata(pdev, chip); /* First, check if the device is dual-channel */ - of_property_read_u32(np, "xlnx,is-dual", &is_dual); + device_property_read_u32(dev, "xlnx,is-dual", &is_dual); /* Setup defaults */ memset32(width, 0, ARRAY_SIZE(width)); @@ -586,14 +586,14 @@ static int xgpio_probe(struct platform_device *pdev) memset32(dir, 0xFFFFFFFF, ARRAY_SIZE(dir)); /* Update GPIO state shadow register with default value */ - of_property_read_u32(np, "xlnx,dout-default", &state[0]); - of_property_read_u32(np, "xlnx,dout-default-2", &state[1]); + device_property_read_u32(dev, "xlnx,dout-default", &state[0]); + device_property_read_u32(dev, "xlnx,dout-default-2", &state[1]); bitmap_from_arr32(chip->state, state, 64); /* Update GPIO direction shadow register with default value */ - of_property_read_u32(np, "xlnx,tri-default", &dir[0]); - of_property_read_u32(np, "xlnx,tri-default-2", &dir[1]); + device_property_read_u32(dev, "xlnx,tri-default", &dir[0]); + device_property_read_u32(dev, "xlnx,tri-default-2", &dir[1]); bitmap_from_arr32(chip->dir, dir, 64); @@ -601,13 +601,13 @@ static int xgpio_probe(struct platform_device *pdev) * Check device node and parent device node for device width * and assume default width of 32 */ - if (of_property_read_u32(np, "xlnx,gpio-width", &width[0])) + if (device_property_read_u32(dev, "xlnx,gpio-width", &width[0])) width[0] = 32; if (width[0] > 32) return -EINVAL; - if (is_dual && of_property_read_u32(np, "xlnx,gpio2-width", &width[1])) + if (is_dual && device_property_read_u32(dev, "xlnx,gpio2-width", &width[1])) width[1] = 32; if (width[1] > 32) @@ -624,7 +624,7 @@ static int xgpio_probe(struct platform_device *pdev) chip->gc.base = -1; chip->gc.ngpio = bitmap_weight(chip->hw_map, 64); - chip->gc.parent = &pdev->dev; + chip->gc.parent = dev; chip->gc.direction_input = xgpio_dir_in; chip->gc.direction_output = xgpio_dir_out; chip->gc.get = xgpio_get; @@ -633,21 +633,21 @@ static int xgpio_probe(struct platform_device *pdev) chip->gc.free = xgpio_free; chip->gc.set_multiple = xgpio_set_multiple; - chip->gc.label = dev_name(&pdev->dev); + chip->gc.label = dev_name(dev); chip->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chip->regs)) { - dev_err(&pdev->dev, "failed to ioremap memory resource\n"); + dev_err(dev, "failed to ioremap memory resource\n"); return PTR_ERR(chip->regs); } - chip->clk = devm_clk_get_optional_enabled(&pdev->dev, NULL); + chip->clk = devm_clk_get_optional_enabled(dev, NULL); if (IS_ERR(chip->clk)) - return dev_err_probe(&pdev->dev, PTR_ERR(chip->clk), "input clock not found.\n"); + return dev_err_probe(dev, PTR_ERR(chip->clk), "input clock not found.\n"); - pm_runtime_get_noresume(&pdev->dev); - pm_runtime_set_active(&pdev->dev); - pm_runtime_enable(&pdev->dev); + pm_runtime_get_noresume(dev); + pm_runtime_set_active(dev); + pm_runtime_enable(dev); xgpio_save_regs(chip); @@ -667,8 +667,7 @@ static int xgpio_probe(struct platform_device *pdev) gpio_irq_chip_set_chip(girq, &xgpio_irq_chip); girq->parent_handler = xgpio_irqhandler; girq->num_parents = 1; - girq->parents = devm_kcalloc(&pdev->dev, 1, - sizeof(*girq->parents), + girq->parents = devm_kcalloc(dev, 1, sizeof(*girq->parents), GFP_KERNEL); if (!girq->parents) { status = -ENOMEM; @@ -679,18 +678,18 @@ static int xgpio_probe(struct platform_device *pdev) girq->handler = handle_bad_irq; skip_irq: - status = devm_gpiochip_add_data(&pdev->dev, &chip->gc, chip); + status = devm_gpiochip_add_data(dev, &chip->gc, chip); if (status) { - dev_err(&pdev->dev, "failed to add GPIO chip\n"); + dev_err(dev, "failed to add GPIO chip\n"); goto err_pm_put; } - pm_runtime_put(&pdev->dev); + pm_runtime_put(dev); return 0; err_pm_put: - pm_runtime_disable(&pdev->dev); - pm_runtime_put_noidle(&pdev->dev); + pm_runtime_disable(dev); + pm_runtime_put_noidle(dev); return status; } diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index 78c9d9ed3d68..b0050250ac3a 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -143,18 +143,22 @@ static int linehandle_validate_flags(u32 flags) static void linehandle_flags_to_desc_flags(u32 lflags, unsigned long *flagsp) { - assign_bit(FLAG_ACTIVE_LOW, flagsp, + unsigned long flags = READ_ONCE(*flagsp); + + assign_bit(FLAG_ACTIVE_LOW, &flags, lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW); - assign_bit(FLAG_OPEN_DRAIN, flagsp, + assign_bit(FLAG_OPEN_DRAIN, &flags, lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN); - assign_bit(FLAG_OPEN_SOURCE, flagsp, + assign_bit(FLAG_OPEN_SOURCE, &flags, lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE); - assign_bit(FLAG_PULL_UP, flagsp, + assign_bit(FLAG_PULL_UP, &flags, lflags & GPIOHANDLE_REQUEST_BIAS_PULL_UP); - assign_bit(FLAG_PULL_DOWN, flagsp, + assign_bit(FLAG_PULL_DOWN, &flags, lflags & GPIOHANDLE_REQUEST_BIAS_PULL_DOWN); - assign_bit(FLAG_BIAS_DISABLE, flagsp, + assign_bit(FLAG_BIAS_DISABLE, &flags, lflags & GPIOHANDLE_REQUEST_BIAS_DISABLE); + + WRITE_ONCE(*flagsp, flags); } static long linehandle_set_config(struct linehandle_state *lh, @@ -450,7 +454,7 @@ struct line { * The flags for the active edge detector configuration. * * edflags is set by linereq_create(), linereq_free(), and - * linereq_set_config_unlocked(), which are themselves mutually + * linereq_set_config(), which are themselves mutually * exclusive, and is accessed by edge_irq_thread(), * process_hw_ts_thread() and debounce_work_func(), * which can all live with a slightly stale value. @@ -1348,38 +1352,42 @@ static int gpio_v2_line_config_validate(struct gpio_v2_line_config *lc, return 0; } -static void gpio_v2_line_config_flags_to_desc_flags(u64 flags, +static void gpio_v2_line_config_flags_to_desc_flags(u64 lflags, unsigned long *flagsp) { - assign_bit(FLAG_ACTIVE_LOW, flagsp, - flags & GPIO_V2_LINE_FLAG_ACTIVE_LOW); - - if (flags & GPIO_V2_LINE_FLAG_OUTPUT) - set_bit(FLAG_IS_OUT, flagsp); - else if (flags & GPIO_V2_LINE_FLAG_INPUT) - clear_bit(FLAG_IS_OUT, flagsp); - - assign_bit(FLAG_EDGE_RISING, flagsp, - flags & GPIO_V2_LINE_FLAG_EDGE_RISING); - assign_bit(FLAG_EDGE_FALLING, flagsp, - flags & GPIO_V2_LINE_FLAG_EDGE_FALLING); - - assign_bit(FLAG_OPEN_DRAIN, flagsp, - flags & GPIO_V2_LINE_FLAG_OPEN_DRAIN); - assign_bit(FLAG_OPEN_SOURCE, flagsp, - flags & GPIO_V2_LINE_FLAG_OPEN_SOURCE); - - assign_bit(FLAG_PULL_UP, flagsp, - flags & GPIO_V2_LINE_FLAG_BIAS_PULL_UP); - assign_bit(FLAG_PULL_DOWN, flagsp, - flags & GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN); - assign_bit(FLAG_BIAS_DISABLE, flagsp, - flags & GPIO_V2_LINE_FLAG_BIAS_DISABLED); - - assign_bit(FLAG_EVENT_CLOCK_REALTIME, flagsp, - flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME); - assign_bit(FLAG_EVENT_CLOCK_HTE, flagsp, - flags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE); + unsigned long flags = READ_ONCE(*flagsp); + + assign_bit(FLAG_ACTIVE_LOW, &flags, + lflags & GPIO_V2_LINE_FLAG_ACTIVE_LOW); + + if (lflags & GPIO_V2_LINE_FLAG_OUTPUT) + set_bit(FLAG_IS_OUT, &flags); + else if (lflags & GPIO_V2_LINE_FLAG_INPUT) + clear_bit(FLAG_IS_OUT, &flags); + + assign_bit(FLAG_EDGE_RISING, &flags, + lflags & GPIO_V2_LINE_FLAG_EDGE_RISING); + assign_bit(FLAG_EDGE_FALLING, &flags, + lflags & GPIO_V2_LINE_FLAG_EDGE_FALLING); + + assign_bit(FLAG_OPEN_DRAIN, &flags, + lflags & GPIO_V2_LINE_FLAG_OPEN_DRAIN); + assign_bit(FLAG_OPEN_SOURCE, &flags, + lflags & GPIO_V2_LINE_FLAG_OPEN_SOURCE); + + assign_bit(FLAG_PULL_UP, &flags, + lflags & GPIO_V2_LINE_FLAG_BIAS_PULL_UP); + assign_bit(FLAG_PULL_DOWN, &flags, + lflags & GPIO_V2_LINE_FLAG_BIAS_PULL_DOWN); + assign_bit(FLAG_BIAS_DISABLE, &flags, + lflags & GPIO_V2_LINE_FLAG_BIAS_DISABLED); + + assign_bit(FLAG_EVENT_CLOCK_REALTIME, &flags, + lflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_REALTIME); + assign_bit(FLAG_EVENT_CLOCK_HTE, &flags, + lflags & GPIO_V2_LINE_FLAG_EVENT_CLOCK_HTE); + + WRITE_ONCE(*flagsp, flags); } static long linereq_get_values(struct linereq *lr, void __user *ip) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 17ed229412af..20426d6e04d5 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -573,11 +573,10 @@ static struct class gpio_class = { */ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) { - const char *ioname = NULL; struct gpio_device *gdev; struct gpiod_data *data; struct device *dev; - int status, offset; + int status; /* can't export until sysfs is available ... */ if (!class_is_registered(&gpio_class)) { @@ -626,14 +625,9 @@ int gpiod_export(struct gpio_desc *desc, bool direction_may_change) else data->direction_can_change = false; - offset = gpio_chip_hwgpio(desc); - if (guard.gc->names && guard.gc->names[offset]) - ioname = guard.gc->names[offset]; - dev = device_create_with_groups(&gpio_class, &gdev->dev, MKDEV(0, 0), data, gpio_groups, - ioname ? ioname : "gpio%u", - desc_to_gpio(desc)); + "gpio%u", desc_to_gpio(desc)); if (IS_ERR(dev)) { status = PTR_ERR(dev); goto err_free_data; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index c6afbf434366..0d1e10654d4c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -14,6 +14,7 @@ #include <linux/idr.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <linux/irqdesc.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/lockdep.h> @@ -713,6 +714,45 @@ bool gpiochip_line_is_valid(const struct gpio_chip *gc, } EXPORT_SYMBOL_GPL(gpiochip_line_is_valid); +static void gpiod_free_irqs(struct gpio_desc *desc) +{ + int irq = gpiod_to_irq(desc); + struct irq_desc *irqd = irq_to_desc(irq); + void *cookie; + + for (;;) { + /* + * Make sure the action doesn't go away while we're + * dereferencing it. Retrieve and store the cookie value. + * If the irq is freed after we release the lock, that's + * alright - the underlying maple tree lookup will return NULL + * and nothing will happen in free_irq(). + */ + scoped_guard(mutex, &irqd->request_mutex) { + if (!irq_desc_has_action(irqd)) + return; + + cookie = irqd->action->dev_id; + } + + free_irq(irq, cookie); + } +} + +/* + * The chip is going away but there may be users who had requested interrupts + * on its GPIO lines who have no idea about its removal and have no way of + * being notified about it. We need to free any interrupts still in use here or + * we'll leak memory and resources (like procfs files). + */ +static void gpiochip_free_remaining_irqs(struct gpio_chip *gc) +{ + struct gpio_desc *desc; + + for_each_gpio_desc_with_flag(gc, desc, FLAG_USED_AS_IRQ) + gpiod_free_irqs(desc); +} + static void gpiodev_release(struct device *dev) { struct gpio_device *gdev = to_gpio_device(dev); @@ -986,9 +1026,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, } } - for (desc_index = 0; desc_index < gc->ngpio; desc_index++) - gdev->descs[desc_index].gdev = gdev; - BLOCKING_INIT_NOTIFIER_HEAD(&gdev->line_state_notifier); BLOCKING_INIT_NOTIFIER_HEAD(&gdev->device_notifier); @@ -1018,6 +1055,8 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, for (desc_index = 0; desc_index < gc->ngpio; desc_index++) { struct gpio_desc *desc = &gdev->descs[desc_index]; + desc->gdev = gdev; + if (gc->get_direction && gpiochip_line_is_valid(gc, desc_index)) { assign_bit(FLAG_IS_OUT, &desc->flags, !gc->get_direction(gc, desc_index)); @@ -1125,6 +1164,7 @@ void gpiochip_remove(struct gpio_chip *gc) /* FIXME: should the legacy sysfs handling be moved to gpio_device? */ gpiochip_sysfs_unregister(gdev); gpiochip_free_hogs(gc); + gpiochip_free_remaining_irqs(gc); scoped_guard(mutex, &gpio_devices_lock) list_del_rcu(&gdev->list); @@ -2393,7 +2433,7 @@ static void gpiod_free_commit(struct gpio_desc *desc) desc_set_label(desc, NULL); WRITE_ONCE(desc->flags, flags); - gpiod_line_state_notify(desc, GPIOLINE_CHANGED_RELEASED); + gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_RELEASED); } } @@ -4325,7 +4365,7 @@ struct gpio_desc *gpiod_find_and_request(struct device *consumer, return ERR_PTR(ret); } - gpiod_line_state_notify(desc, GPIOLINE_CHANGED_REQUESTED); + gpiod_line_state_notify(desc, GPIO_V2_LINE_CHANGED_REQUESTED); return desc; } |