Commit 9c09f623 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'gpio-v5.3-6' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio

Pull GPIO fixes from Linus Walleij:
 "I don't really like to send so many fixes at the very last minute, but
  the bug-sport activity is unpredictable.

  Four fixes, three are -stable material that will go everywhere, one is
  for the current cycle:

   - An ACPI DSDT error fixup of the type we always see and Hans
     invariably gets to fix.

   - A OF quirk fix for the current release (v5.3)

   - Some consistency checks on the userspace ABI.

   - A memory leak"

* tag 'gpio-v5.3-6' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
  gpiolib: acpi: Add gpiolib_acpi_run_edge_events_on_boot option and blacklist
  gpiolib: of: fix fallback quirks handling
  gpio: fix line flag validation in lineevent_create
  gpio: fix line flag validation in linehandle_create
  gpio: mockup: add missing single_release()
parents 3120b9a6 61f7f7c8
...@@ -309,6 +309,7 @@ static const struct file_operations gpio_mockup_debugfs_ops = { ...@@ -309,6 +309,7 @@ static const struct file_operations gpio_mockup_debugfs_ops = {
.read = gpio_mockup_debugfs_read, .read = gpio_mockup_debugfs_read,
.write = gpio_mockup_debugfs_write, .write = gpio_mockup_debugfs_write,
.llseek = no_llseek, .llseek = no_llseek,
.release = single_release,
}; };
static void gpio_mockup_debugfs_setup(struct device *dev, static void gpio_mockup_debugfs_setup(struct device *dev,
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
* Mika Westerberg <mika.westerberg@linux.intel.com> * Mika Westerberg <mika.westerberg@linux.intel.com>
*/ */
#include <linux/dmi.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h> #include <linux/gpio/driver.h>
...@@ -19,6 +20,11 @@ ...@@ -19,6 +20,11 @@
#include "gpiolib.h" #include "gpiolib.h"
static int run_edge_events_on_boot = -1;
module_param(run_edge_events_on_boot, int, 0444);
MODULE_PARM_DESC(run_edge_events_on_boot,
"Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto");
/** /**
* struct acpi_gpio_event - ACPI GPIO event handler data * struct acpi_gpio_event - ACPI GPIO event handler data
* *
...@@ -170,10 +176,13 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio, ...@@ -170,10 +176,13 @@ static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
event->irq_requested = true; event->irq_requested = true;
/* Make sure we trigger the initial state of edge-triggered IRQs */ /* Make sure we trigger the initial state of edge-triggered IRQs */
if (run_edge_events_on_boot &&
(event->irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))) {
value = gpiod_get_raw_value_cansleep(event->desc); value = gpiod_get_raw_value_cansleep(event->desc);
if (((event->irqflags & IRQF_TRIGGER_RISING) && value == 1) || if (((event->irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
((event->irqflags & IRQF_TRIGGER_FALLING) && value == 0)) ((event->irqflags & IRQF_TRIGGER_FALLING) && value == 0))
event->handler(event->irq, event); event->handler(event->irq, event);
}
} }
static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio) static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio)
...@@ -1283,3 +1292,28 @@ static int acpi_gpio_handle_deferred_request_irqs(void) ...@@ -1283,3 +1292,28 @@ static int acpi_gpio_handle_deferred_request_irqs(void)
} }
/* We must use _sync so that this runs after the first deferred_probe run */ /* We must use _sync so that this runs after the first deferred_probe run */
late_initcall_sync(acpi_gpio_handle_deferred_request_irqs); late_initcall_sync(acpi_gpio_handle_deferred_request_irqs);
static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
{
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
}
},
{} /* Terminating entry */
};
static int acpi_gpio_setup_params(void)
{
if (run_edge_events_on_boot < 0) {
if (dmi_check_system(run_edge_events_on_boot_blacklist))
run_edge_events_on_boot = 0;
else
run_edge_events_on_boot = 1;
}
return 0;
}
/* Directly after dmi_setup() which runs as core_initcall() */
postcore_initcall(acpi_gpio_setup_params);
...@@ -343,36 +343,27 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id, ...@@ -343,36 +343,27 @@ struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx, desc = of_get_named_gpiod_flags(dev->of_node, prop_name, idx,
&of_flags); &of_flags);
/*
* -EPROBE_DEFER in our case means that we found a
* valid GPIO property, but no controller has been
* registered so far.
*
* This means we don't need to look any further for
* alternate name conventions, and we should really
* preserve the return code for our user to be able to
* retry probing later.
*/
if (IS_ERR(desc) && PTR_ERR(desc) == -EPROBE_DEFER)
return desc;
if (!IS_ERR(desc) || (PTR_ERR(desc) != -ENOENT)) if (!IS_ERR(desc) || PTR_ERR(desc) != -ENOENT)
break; break;
} }
if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
/* Special handling for SPI GPIOs if used */ /* Special handling for SPI GPIOs if used */
if (IS_ERR(desc))
desc = of_find_spi_gpio(dev, con_id, &of_flags); desc = of_find_spi_gpio(dev, con_id, &of_flags);
if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER) { }
if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
/* This quirk looks up flags and all */ /* This quirk looks up flags and all */
desc = of_find_spi_cs_gpio(dev, con_id, idx, flags); desc = of_find_spi_cs_gpio(dev, con_id, idx, flags);
if (!IS_ERR(desc)) if (!IS_ERR(desc))
return desc; return desc;
} }
if (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) {
/* Special handling for regulator GPIOs if used */ /* Special handling for regulator GPIOs if used */
if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER)
desc = of_find_regulator_gpio(dev, con_id, &of_flags); desc = of_find_regulator_gpio(dev, con_id, &of_flags);
}
if (IS_ERR(desc)) if (IS_ERR(desc))
return desc; return desc;
......
...@@ -535,6 +535,14 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip) ...@@ -535,6 +535,14 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)
if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS) if (lflags & ~GPIOHANDLE_REQUEST_VALID_FLAGS)
return -EINVAL; return -EINVAL;
/*
* Do not allow both INPUT & OUTPUT flags to be set as they are
* contradictory.
*/
if ((lflags & GPIOHANDLE_REQUEST_INPUT) &&
(lflags & GPIOHANDLE_REQUEST_OUTPUT))
return -EINVAL;
/* /*
* Do not allow OPEN_SOURCE & OPEN_DRAIN flags in a single request. If * Do not allow OPEN_SOURCE & OPEN_DRAIN flags in a single request. If
* the hardware actually supports enabling both at the same time the * the hardware actually supports enabling both at the same time the
...@@ -926,7 +934,9 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) ...@@ -926,7 +934,9 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
} }
/* This is just wrong: we don't look for events on output lines */ /* This is just wrong: we don't look for events on output lines */
if (lflags & GPIOHANDLE_REQUEST_OUTPUT) { if ((lflags & GPIOHANDLE_REQUEST_OUTPUT) ||
(lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN) ||
(lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)) {
ret = -EINVAL; ret = -EINVAL;
goto out_free_label; goto out_free_label;
} }
...@@ -940,10 +950,6 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip) ...@@ -940,10 +950,6 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)
if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW) if (lflags & GPIOHANDLE_REQUEST_ACTIVE_LOW)
set_bit(FLAG_ACTIVE_LOW, &desc->flags); set_bit(FLAG_ACTIVE_LOW, &desc->flags);
if (lflags & GPIOHANDLE_REQUEST_OPEN_DRAIN)
set_bit(FLAG_OPEN_DRAIN, &desc->flags);
if (lflags & GPIOHANDLE_REQUEST_OPEN_SOURCE)
set_bit(FLAG_OPEN_SOURCE, &desc->flags);
ret = gpiod_direction_input(desc); ret = gpiod_direction_input(desc);
if (ret) if (ret)
......
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