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

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
Loading
Loading
Loading
Loading
+23 −55
Original line number Diff line number Diff line
@@ -113,8 +113,29 @@ MODULE_DEVICE_TABLE(i2c, pca953x_id);
#ifdef CONFIG_GPIO_PCA953X_IRQ

#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[] = {
	{
@@ -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

static const struct acpi_device_id pca953x_acpi_ids[] = {
+15 −6
Original line number Diff line number Diff line
@@ -174,7 +174,7 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
	int ret, value;

	ret = request_threaded_irq(event->irq, NULL, event->handler,
				   event->irqflags, "ACPI:Event", event);
				   event->irqflags | IRQF_ONESHOT, "ACPI:Event", event);
	if (ret) {
		dev_err(acpi_gpio->chip->parent,
			"Failed to setup interrupt handler for %d\n",
@@ -677,6 +677,7 @@ static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
	if (!lookup->desc) {
		const struct acpi_resource_gpio *agpio = &ares->data.gpio;
		bool gpioint = agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
		struct gpio_desc *desc;
		u16 pin_index;

		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)
		if (pin_index >= agpio->pin_table_length)
			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]);
		lookup->desc = desc;
		lookup->info.pin_config = agpio->pin_config;
		lookup->info.debounce = agpio->debounce_timeout;
		lookup->info.gpioint = gpioint;
@@ -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
 * @name: optional name of GpioInt resource
 * @index: index of GpioInt resource (starting from %0)
 *
 * 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,
 * The function is idempotent, though each time it runs it will configure GPIO
 * 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.
 */
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;
	unsigned int irq_flags;
@@ -963,7 +972,7 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
		struct acpi_gpio_info info;
		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 */
		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)
	}
	return -ENOENT;
}
EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get);
EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get_by);

static acpi_status
acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
+9 −10
Original line number Diff line number Diff line
@@ -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
 * 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.
 */
static int devprop_gpiochip_set_names(struct gpio_chip *chip)
{
	struct gpio_device *gdev = chip->gpiodev;
	struct device *dev = chip->parent;
	struct fwnode_handle *fwnode = dev_fwnode(&gdev->dev);
	const char **names;
	int ret, i;
	int count;

	/* GPIO chip may not have a parent device whose properties we inspect. */
	if (!dev)
		return 0;

	count = device_property_string_array_count(dev, "gpio-line-names");
	count = fwnode_property_string_array_count(fwnode, "gpio-line-names");
	if (count < 0)
		return 0;

@@ -396,7 +392,7 @@ static int devprop_gpiochip_set_names(struct gpio_chip *chip)
	if (!names)
		return -ENOMEM;

	ret = device_property_read_string_array(dev, "gpio-line-names",
	ret = fwnode_property_read_string_array(fwnode, "gpio-line-names",
						names, count);
	if (ret < 0) {
		dev_warn(&gdev->dev, "failed to read GPIO line names\n");
@@ -474,9 +470,13 @@ EXPORT_SYMBOL_GPL(gpiochip_line_is_valid);

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);
	spin_unlock_irqrestore(&gpio_lock, flags);

	ida_free(&gpio_ida, gdev->id);
	kfree_const(gdev->label);
	kfree(gdev->descs);
@@ -605,7 +605,6 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
		goto err_free_ida;

	device_initialize(&gdev->dev);
	dev_set_drvdata(&gdev->dev, gdev);
	if (gc->parent && gc->parent->driver)
		gdev->owner = gc->parent->driver->owner;
	else if (gc->owner)
+8 −2
Original line number Diff line number Diff line
@@ -1079,19 +1079,25 @@ void __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, const c
#if defined(CONFIG_ACPI) && defined(CONFIG_GPIOLIB)
bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
				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
static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
					      struct acpi_resource_gpio **agpio)
{
	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;
}
#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 */

#ifdef CONFIG_ACPI
+2 −0
Original line number Diff line number Diff line
@@ -674,6 +674,8 @@ struct acpi_gpio_mapping {
 * get GpioIo type explicitly, this quirk may be used.
 */
#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;
};
Loading