Commit 4b3d9f9c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-fixes-for-v5.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio fixes from Bartosz Golaszewski:
 "A bunch of fixes for the GPIO subsystem. We have two regressions in
  the core code spotted right after the merge window, a series of fixes
  for ACPI GPIO and a subsequent fix for a related regression in
  gpio-pca953x + a minor tweak in .gitignore and a rework of handling of
  the gpio-line-names to remedy a regression in stm32mp151.

  Summary:

   - fix two regressions in core GPIO subsystem code: one NULL-pointer
     dereference and one list corruption

   - read GPIO line names from fwnode instead of using the generic
     device properties to fix a regression on stm32mp151

   - fixes to ACPI GPIO and gpio-pca953x to handle a regression in IRQ
     handling on Intel Galileo

   - update .gitignore in GPIO selftests"

* tag 'gpio-fixes-for-v5.12-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
  gpiolib: Read "gpio-line-names" from a firmware node
  gpio: pca953x: Set IRQ type when handle Intel Galileo Gen 2
  gpiolib: acpi: Allow to find GpioInt() resource by name and index
  gpiolib: acpi: Add ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER quirk
  gpiolib: acpi: Add missing IRQF_ONESHOT
  gpio: fix gpio-device list corruption
  gpio: fix NULL-deref-on-deregistration regression
  selftests: gpio: update .gitignore
parents 9c39198a b41ba2ec
...@@ -113,8 +113,29 @@ MODULE_DEVICE_TABLE(i2c, pca953x_id); ...@@ -113,8 +113,29 @@ MODULE_DEVICE_TABLE(i2c, pca953x_id);
#ifdef CONFIG_GPIO_PCA953X_IRQ #ifdef CONFIG_GPIO_PCA953X_IRQ
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/gpio.h>
#include <linux/list.h> static const struct acpi_gpio_params pca953x_irq_gpios = { 0, 0, true };
static const struct acpi_gpio_mapping pca953x_acpi_irq_gpios[] = {
{ "irq-gpios", &pca953x_irq_gpios, 1, ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER },
{ }
};
static int pca953x_acpi_get_irq(struct device *dev)
{
int ret;
ret = devm_acpi_dev_add_driver_gpios(dev, pca953x_acpi_irq_gpios);
if (ret)
dev_warn(dev, "can't add GPIO ACPI mapping\n");
ret = acpi_dev_gpio_irq_get_by(ACPI_COMPANION(dev), "irq-gpios", 0);
if (ret < 0)
return ret;
dev_info(dev, "ACPI interrupt quirk (IRQ %d)\n", ret);
return ret;
}
static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = { static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = {
{ {
...@@ -133,59 +154,6 @@ static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = { ...@@ -133,59 +154,6 @@ static const struct dmi_system_id pca953x_dmi_acpi_irq_info[] = {
}, },
{} {}
}; };
#ifdef CONFIG_ACPI
static int pca953x_acpi_get_pin(struct acpi_resource *ares, void *data)
{
struct acpi_resource_gpio *agpio;
int *pin = data;
if (acpi_gpio_get_irq_resource(ares, &agpio))
*pin = agpio->pin_table[0];
return 1;
}
static int pca953x_acpi_find_pin(struct device *dev)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
int pin = -ENOENT, ret;
LIST_HEAD(r);
ret = acpi_dev_get_resources(adev, &r, pca953x_acpi_get_pin, &pin);
acpi_dev_free_resource_list(&r);
if (ret < 0)
return ret;
return pin;
}
#else
static inline int pca953x_acpi_find_pin(struct device *dev) { return -ENXIO; }
#endif
static int pca953x_acpi_get_irq(struct device *dev)
{
int pin, ret;
pin = pca953x_acpi_find_pin(dev);
if (pin < 0)
return pin;
dev_info(dev, "Applying ACPI interrupt quirk (GPIO %d)\n", pin);
if (!gpio_is_valid(pin))
return -EINVAL;
ret = gpio_request(pin, "pca953x interrupt");
if (ret)
return ret;
ret = gpio_to_irq(pin);
/* When pin is used as an IRQ, no need to keep it requested */
gpio_free(pin);
return ret;
}
#endif #endif
static const struct acpi_device_id pca953x_acpi_ids[] = { static const struct acpi_device_id pca953x_acpi_ids[] = {
......
...@@ -174,7 +174,7 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio, ...@@ -174,7 +174,7 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
int ret, value; int ret, value;
ret = request_threaded_irq(event->irq, NULL, event->handler, ret = request_threaded_irq(event->irq, NULL, event->handler,
event->irqflags, "ACPI:Event", event); event->irqflags | IRQF_ONESHOT, "ACPI:Event", event);
if (ret) { if (ret) {
dev_err(acpi_gpio->chip->parent, dev_err(acpi_gpio->chip->parent,
"Failed to setup interrupt handler for %d\n", "Failed to setup interrupt handler for %d\n",
...@@ -677,6 +677,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data) ...@@ -677,6 +677,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
if (!lookup->desc) { if (!lookup->desc) {
const struct acpi_resource_gpio *agpio = &ares->data.gpio; const struct acpi_resource_gpio *agpio = &ares->data.gpio;
bool gpioint = agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT; bool gpioint = agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
struct gpio_desc *desc;
u16 pin_index; u16 pin_index;
if (lookup->info.quirks & ACPI_GPIO_QUIRK_ONLY_GPIOIO && gpioint) if (lookup->info.quirks & ACPI_GPIO_QUIRK_ONLY_GPIOIO && gpioint)
...@@ -689,8 +690,12 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data) ...@@ -689,8 +690,12 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
if (pin_index >= agpio->pin_table_length) if (pin_index >= agpio->pin_table_length)
return 1; return 1;
lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr, if (lookup->info.quirks & ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER)
desc = gpio_to_desc(agpio->pin_table[pin_index]);
else
desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
agpio->pin_table[pin_index]); agpio->pin_table[pin_index]);
lookup->desc = desc;
lookup->info.pin_config = agpio->pin_config; lookup->info.pin_config = agpio->pin_config;
lookup->info.debounce = agpio->debounce_timeout; lookup->info.debounce = agpio->debounce_timeout;
lookup->info.gpioint = gpioint; lookup->info.gpioint = gpioint;
...@@ -940,8 +945,9 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, ...@@ -940,8 +945,9 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
} }
/** /**
* acpi_dev_gpio_irq_get() - Find GpioInt and translate it to Linux IRQ number * acpi_dev_gpio_irq_get_by() - Find GpioInt and translate it to Linux IRQ number
* @adev: pointer to a ACPI device to get IRQ from * @adev: pointer to a ACPI device to get IRQ from
* @name: optional name of GpioInt resource
* @index: index of GpioInt resource (starting from %0) * @index: index of GpioInt resource (starting from %0)
* *
* If the device has one or more GpioInt resources, this function can be * If the device has one or more GpioInt resources, this function can be
...@@ -951,9 +957,12 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, ...@@ -951,9 +957,12 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode,
* The function is idempotent, though each time it runs it will configure GPIO * The function is idempotent, though each time it runs it will configure GPIO
* pin direction according to the flags in GpioInt resource. * pin direction according to the flags in GpioInt resource.
* *
* The function takes optional @name parameter. If the resource has a property
* name, then only those will be taken into account.
*
* Return: Linux IRQ number (> %0) on success, negative errno on failure. * Return: Linux IRQ number (> %0) on success, negative errno on failure.
*/ */
int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int index)
{ {
int idx, i; int idx, i;
unsigned int irq_flags; unsigned int irq_flags;
...@@ -963,7 +972,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) ...@@ -963,7 +972,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
struct acpi_gpio_info info; struct acpi_gpio_info info;
struct gpio_desc *desc; struct gpio_desc *desc;
desc = acpi_get_gpiod_by_index(adev, NULL, i, &info); desc = acpi_get_gpiod_by_index(adev, name, i, &info);
/* Ignore -EPROBE_DEFER, it only matters if idx matches */ /* Ignore -EPROBE_DEFER, it only matters if idx matches */
if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER) if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER)
...@@ -1008,7 +1017,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) ...@@ -1008,7 +1017,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
} }
return -ENOENT; return -ENOENT;
} }
EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get); EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get_by);
static acpi_status static acpi_status
acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address, acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
......
...@@ -367,22 +367,18 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc) ...@@ -367,22 +367,18 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)
* *
* Looks for device property "gpio-line-names" and if it exists assigns * Looks for device property "gpio-line-names" and if it exists assigns
* GPIO line names for the chip. The memory allocated for the assigned * GPIO line names for the chip. The memory allocated for the assigned
* names belong to the underlying software node and should not be released * names belong to the underlying firmware node and should not be released
* by the caller. * by the caller.
*/ */
static int devprop_gpiochip_set_names(struct gpio_chip *chip) static int devprop_gpiochip_set_names(struct gpio_chip *chip)
{ {
struct gpio_device *gdev = chip->gpiodev; struct gpio_device *gdev = chip->gpiodev;
struct device *dev = chip->parent; struct fwnode_handle *fwnode = dev_fwnode(&gdev->dev);
const char **names; const char **names;
int ret, i; int ret, i;
int count; int count;
/* GPIO chip may not have a parent device whose properties we inspect. */ count = fwnode_property_string_array_count(fwnode, "gpio-line-names");
if (!dev)
return 0;
count = device_property_string_array_count(dev, "gpio-line-names");
if (count < 0) if (count < 0)
return 0; return 0;
...@@ -396,7 +392,7 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip) ...@@ -396,7 +392,7 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)
if (!names) if (!names)
return -ENOMEM; return -ENOMEM;
ret = device_property_read_string_array(dev, "gpio-line-names", ret = fwnode_property_read_string_array(fwnode, "gpio-line-names",
names, count); names, count);
if (ret < 0) { if (ret < 0) {
dev_warn(&gdev->dev, "failed to read GPIO line names\n"); dev_warn(&gdev->dev, "failed to read GPIO line names\n");
...@@ -474,9 +470,13 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_valid); ...@@ -474,9 +470,13 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);
static void gpiodevice_release(struct device *dev) static void gpiodevice_release(struct device *dev)
{ {
struct gpio_device *gdev = dev_get_drvdata(dev); struct gpio_device *gdev = container_of(dev, struct gpio_device, dev);
unsigned long flags;
spin_lock_irqsave(&gpio_lock, flags);
list_del(&gdev->list); list_del(&gdev->list);
spin_unlock_irqrestore(&gpio_lock, flags);
ida_free(&gpio_ida, gdev->id); ida_free(&gpio_ida, gdev->id);
kfree_const(gdev->label); kfree_const(gdev->label);
kfree(gdev->descs); kfree(gdev->descs);
...@@ -605,7 +605,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data, ...@@ -605,7 +605,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
goto err_free_ida; goto err_free_ida;
device_initialize(&gdev->dev); device_initialize(&gdev->dev);
dev_set_drvdata(&gdev->dev, gdev);
if (gc->parent && gc->parent->driver) if (gc->parent && gc->parent->driver)
gdev->owner = gc->parent->driver->owner; gdev->owner = gc->parent->driver->owner;
else if (gc->owner) else if (gc->owner)
......
...@@ -1079,19 +1079,25 @@ void __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, const c ...@@ -1079,19 +1079,25 @@ void __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, const c
#if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB) #if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB)
bool acpi_gpio_get_irq_resource(struct acpi_resource *ares, bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
struct acpi_resource_gpio **agpio); struct acpi_resource_gpio **agpio);
int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index); int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int index);
#else #else
static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares, static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
struct acpi_resource_gpio **agpio) struct acpi_resource_gpio **agpio)
{ {
return false; return false;
} }
static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) static inline int acpi_dev_gpio_irq_get_by(struct acpi_device *adev,
const char *name, int index)
{ {
return -ENXIO; return -ENXIO;
} }
#endif #endif
static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
{
return acpi_dev_gpio_irq_get_by(adev, NULL, index);
}
/* Device properties */ /* Device properties */
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
......
...@@ -674,6 +674,8 @@ struct acpi_gpio_mapping { ...@@ -674,6 +674,8 @@ struct acpi_gpio_mapping {
* get GpioIo type explicitly, this quirk may be used. * get GpioIo type explicitly, this quirk may be used.
*/ */
#define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1) #define ACPI_GPIO_QUIRK_ONLY_GPIOIO BIT(1)
/* Use given pin as an absolute GPIO number in the system */
#define ACPI_GPIO_QUIRK_ABSOLUTE_NUMBER BIT(2)
unsigned int quirks; unsigned int quirks;
}; };
......
# SPDX-License-Identifier: GPL-2.0-only # SPDX-License-Identifier: GPL-2.0-only
gpio-mockup-chardev gpio-mockup-cdev
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment