1
0
Fork 0

gpio fixes for v5.12-rc3

- 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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAmBHk9AACgkQEacuoBRx
 13Kd8RAAzU2lPguxO0DjbLfOfYObqV6fODcPiMSk58LCsojz2AVrS/Kba6oSIsur
 OGdUQf4wNNMZsr81+DmBbk/4efd8lF1zqkIa6+serBjK+QONGd7Am0Oc3QiXgk6l
 ZnD51FUAHHdsiHVHmlnCYRg2w93kpu1PHDQCOl4/96xSr1BrRAhC8uV2ImVm+0XS
 z5ddHEe9qITsVhlD2MEpKm3wZEhhJHGtzxD7mjO3iAXzSQcCwpjD37Y5DDkzrgal
 gkLEYCXWeaexOHsLxPmfyDO0GMNTWL8ai8GpRMJCJwGTRataf0hVZZ7TVSGhE8+e
 Ms3hOxKj6AJKbfQVsSy+mJyHTF+ef4UqUp4+CqGdLoz6S5+JkQ9TxPdYNzaNCPeD
 Vk4htVUEYx0M8xHJhMA5siXLWTfDGRGU5ILNcwCKHA3iAMtQw/H2+SKzNgQARGgo
 D1LdFVXzfW278zWv1OGybLh2al8CW/Mi2ybg/kmLsXLJFCpj5kzy2/H2BznBJmPT
 HjU61iiaVlnt7kH3aFd92D+Sr33f7r1kxjonq8aNK3mhMoqOQUxQRtduZp9goJZN
 Kt0uHBMfz/YiyoGlM/Y3SA9C3b7O0ClYA/0DyJ6Qt/6NTDRMMfwAXEjd1n7dYLH1
 ZSOKe1S82GbsVdDQP0qSzzLoziX4U/ttbHxN+RCv4hs67+U5Uw4=
 =nVo+
 -----END PGP SIGNATURE-----

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
master
Linus Torvalds 2021-03-09 12:02:18 -08:00
commit 4b3d9f9cf1
6 changed files with 58 additions and 74 deletions

View File

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

View File

@ -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,

View File

@ -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)

View File

@ -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

View File

@ -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;
};

View File

@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
gpio-mockup-chardev
gpio-mockup-cdev