From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: stable@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
patches@lists.linux.dev, Hans de Goede <hdegoede@redhat.com>,
Mika Westerberg <mika.westerberg@linux.intel.com>,
Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.12 519/567] gpiolib: acpi: Move quirks to a separate file
Date: Tue, 6 Jan 2026 18:05:01 +0100 [thread overview]
Message-ID: <20260106170510.584316139@linuxfoundation.org> (raw)
In-Reply-To: <20260106170451.332875001@linuxfoundation.org>
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
[ Upstream commit 92dc572852ddcae687590cb159189004d58e382e ]
The gpiolib-acpi.c is huge enough even without DMI quirks.
Move them to a separate file for a better maintenance.
No functional change intended.
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Stable-dep-of: 2d967310c49e ("gpiolib: acpi: Add quirk for Dell Precision 7780")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/gpio/Makefile | 1
drivers/gpio/gpiolib-acpi-core.c | 1419 +++++++++++++++++++++++++++++
drivers/gpio/gpiolib-acpi-quirks.c | 363 +++++++
drivers/gpio/gpiolib-acpi.c | 1765 -------------------------------------
4 files changed, 1783 insertions(+), 1765 deletions(-)
rename drivers/gpio/{gpiolib-acpi.c => gpiolib-acpi-core.c} (79%)
create mode 100644 drivers/gpio/gpiolib-acpi-quirks.c
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
obj-$(CONFIG_GPIO_CDEV) += gpiolib-cdev.o
obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o
obj-$(CONFIG_GPIO_ACPI) += gpiolib-acpi.o
+gpiolib-acpi-y := gpiolib-acpi-core.o gpiolib-acpi-quirks.o
obj-$(CONFIG_GPIOLIB) += gpiolib-swnode.o
# Device drivers. Generally keep list sorted alphabetically
--- /dev/null
+++ b/drivers/gpio/gpiolib-acpi-core.c
@@ -0,0 +1,1419 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ACPI helpers for GPIO API
+ *
+ * Copyright (C) 2012, Intel Corporation
+ * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
+ * Mika Westerberg <mika.westerberg@linux.intel.com>
+ */
+
+#include <linux/acpi.h>
+#include <linux/dmi.h>
+#include <linux/errno.h>
+#include <linux/export.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/mutex.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
+
+#include "gpiolib.h"
+#include "gpiolib-acpi.h"
+
+/**
+ * struct acpi_gpio_event - ACPI GPIO event handler data
+ *
+ * @node: list-entry of the events list of the struct acpi_gpio_chip
+ * @handle: handle of ACPI method to execute when the IRQ triggers
+ * @handler: handler function to pass to request_irq() when requesting the IRQ
+ * @pin: GPIO pin number on the struct gpio_chip
+ * @irq: Linux IRQ number for the event, for request_irq() / free_irq()
+ * @irqflags: flags to pass to request_irq() when requesting the IRQ
+ * @irq_is_wake: If the ACPI flags indicate the IRQ is a wakeup source
+ * @irq_requested:True if request_irq() has been done
+ * @desc: struct gpio_desc for the GPIO pin for this event
+ */
+struct acpi_gpio_event {
+ struct list_head node;
+ acpi_handle handle;
+ irq_handler_t handler;
+ unsigned int pin;
+ unsigned int irq;
+ unsigned long irqflags;
+ bool irq_is_wake;
+ bool irq_requested;
+ struct gpio_desc *desc;
+};
+
+struct acpi_gpio_connection {
+ struct list_head node;
+ unsigned int pin;
+ struct gpio_desc *desc;
+};
+
+struct acpi_gpio_chip {
+ /*
+ * ACPICA requires that the first field of the context parameter
+ * passed to acpi_install_address_space_handler() is large enough
+ * to hold struct acpi_connection_info.
+ */
+ struct acpi_connection_info conn_info;
+ struct list_head conns;
+ struct mutex conn_lock;
+ struct gpio_chip *chip;
+ struct list_head events;
+ struct list_head deferred_req_irqs_list_entry;
+};
+
+/**
+ * struct acpi_gpio_info - ACPI GPIO specific information
+ * @adev: reference to ACPI device which consumes GPIO resource
+ * @flags: GPIO initialization flags
+ * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
+ * @pin_config: pin bias as provided by ACPI
+ * @polarity: interrupt polarity as provided by ACPI
+ * @triggering: triggering type as provided by ACPI
+ * @wake_capable: wake capability as provided by ACPI
+ * @debounce: debounce timeout as provided by ACPI
+ * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
+ */
+struct acpi_gpio_info {
+ struct acpi_device *adev;
+ enum gpiod_flags flags;
+ bool gpioint;
+ int pin_config;
+ int polarity;
+ int triggering;
+ bool wake_capable;
+ unsigned int debounce;
+ unsigned int quirks;
+};
+
+static int acpi_gpiochip_find(struct gpio_chip *gc, const void *data)
+{
+ /* First check the actual GPIO device */
+ if (device_match_acpi_handle(&gc->gpiodev->dev, data))
+ return true;
+
+ /*
+ * When the ACPI device is artificially split to the banks of GPIOs,
+ * where each of them is represented by a separate GPIO device,
+ * the firmware node of the physical device may not be shared among
+ * the banks as they may require different values for the same property,
+ * e.g., number of GPIOs in a certain bank. In such case the ACPI handle
+ * of a GPIO device is NULL and can not be used. Hence we have to check
+ * the parent device to be sure that there is no match before bailing
+ * out.
+ */
+ if (gc->parent)
+ return device_match_acpi_handle(gc->parent, data);
+
+ return false;
+}
+
+/**
+ * acpi_get_gpiod() - Translate ACPI GPIO pin to GPIO descriptor usable with GPIO API
+ * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
+ * @pin: ACPI GPIO pin number (0-based, controller-relative)
+ *
+ * Returns:
+ * GPIO descriptor to use with Linux generic GPIO API.
+ * If the GPIO cannot be translated or there is an error an ERR_PTR is
+ * returned.
+ *
+ * Specifically returns %-EPROBE_DEFER if the referenced GPIO
+ * controller does not have GPIO chip registered at the moment. This is to
+ * support probe deferral.
+ */
+static struct gpio_desc *acpi_get_gpiod(char *path, unsigned int pin)
+{
+ acpi_handle handle;
+ acpi_status status;
+
+ status = acpi_get_handle(NULL, path, &handle);
+ if (ACPI_FAILURE(status))
+ return ERR_PTR(-ENODEV);
+
+ struct gpio_device *gdev __free(gpio_device_put) =
+ gpio_device_find(handle, acpi_gpiochip_find);
+ if (!gdev)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ /*
+ * FIXME: keep track of the reference to the GPIO device somehow
+ * instead of putting it here.
+ */
+ return gpio_device_get_desc(gdev, pin);
+}
+
+static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
+{
+ struct acpi_gpio_event *event = data;
+
+ acpi_evaluate_object(event->handle, NULL, NULL, NULL);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data)
+{
+ struct acpi_gpio_event *event = data;
+
+ acpi_execute_simple_method(event->handle, NULL, event->pin);
+
+ return IRQ_HANDLED;
+}
+
+static void acpi_gpio_chip_dh(acpi_handle handle, void *data)
+{
+ /* The address of this function is used as a key. */
+}
+
+bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
+ struct acpi_resource_gpio **agpio)
+{
+ struct acpi_resource_gpio *gpio;
+
+ if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
+ return false;
+
+ gpio = &ares->data.gpio;
+ if (gpio->connection_type != ACPI_RESOURCE_GPIO_TYPE_INT)
+ return false;
+
+ *agpio = gpio;
+ return true;
+}
+EXPORT_SYMBOL_GPL(acpi_gpio_get_irq_resource);
+
+/**
+ * acpi_gpio_get_io_resource - Fetch details of an ACPI resource if it is a GPIO
+ * I/O resource or return False if not.
+ * @ares: Pointer to the ACPI resource to fetch
+ * @agpio: Pointer to a &struct acpi_resource_gpio to store the output pointer
+ *
+ * Returns:
+ * %true if GpioIo resource is found, %false otherwise.
+ */
+bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
+ struct acpi_resource_gpio **agpio)
+{
+ struct acpi_resource_gpio *gpio;
+
+ if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
+ return false;
+
+ gpio = &ares->data.gpio;
+ if (gpio->connection_type != ACPI_RESOURCE_GPIO_TYPE_IO)
+ return false;
+
+ *agpio = gpio;
+ return true;
+}
+EXPORT_SYMBOL_GPL(acpi_gpio_get_io_resource);
+
+static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
+ struct acpi_gpio_event *event)
+{
+ struct device *parent = acpi_gpio->chip->parent;
+ int ret, value;
+
+ ret = request_threaded_irq(event->irq, NULL, event->handler,
+ event->irqflags | IRQF_ONESHOT, "ACPI:Event", event);
+ if (ret) {
+ dev_err(parent, "Failed to setup interrupt handler for %d\n", event->irq);
+ return;
+ }
+
+ if (event->irq_is_wake)
+ enable_irq_wake(event->irq);
+
+ event->irq_requested = true;
+
+ /* Make sure we trigger the initial state of edge-triggered IRQs */
+ if (acpi_gpio_need_run_edge_events_on_boot() &&
+ (event->irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))) {
+ value = gpiod_get_raw_value_cansleep(event->desc);
+ if (((event->irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
+ ((event->irqflags & IRQF_TRIGGER_FALLING) && value == 0))
+ event->handler(event->irq, event);
+ }
+}
+
+static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio)
+{
+ struct acpi_gpio_event *event;
+
+ list_for_each_entry(event, &acpi_gpio->events, node)
+ acpi_gpiochip_request_irq(acpi_gpio, event);
+}
+
+static enum gpiod_flags
+acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio, int polarity)
+{
+ /* GpioInt() implies input configuration */
+ if (agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT)
+ return GPIOD_IN;
+
+ switch (agpio->io_restriction) {
+ case ACPI_IO_RESTRICT_INPUT:
+ return GPIOD_IN;
+ case ACPI_IO_RESTRICT_OUTPUT:
+ /*
+ * ACPI GPIO resources don't contain an initial value for the
+ * GPIO. Therefore we deduce that value from the pull field
+ * and the polarity instead. If the pin is pulled up we assume
+ * default to be high, if it is pulled down we assume default
+ * to be low, otherwise we leave pin untouched. For active low
+ * polarity values will be switched. See also
+ * Documentation/firmware-guide/acpi/gpio-properties.rst.
+ */
+ switch (agpio->pin_config) {
+ case ACPI_PIN_CONFIG_PULLUP:
+ return polarity == GPIO_ACTIVE_LOW ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH;
+ case ACPI_PIN_CONFIG_PULLDOWN:
+ return polarity == GPIO_ACTIVE_LOW ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Assume that the BIOS has configured the direction and pull
+ * accordingly.
+ */
+ return GPIOD_ASIS;
+}
+
+static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip,
+ struct acpi_resource_gpio *agpio,
+ unsigned int index,
+ const char *label)
+{
+ int polarity = GPIO_ACTIVE_HIGH;
+ enum gpiod_flags flags = acpi_gpio_to_gpiod_flags(agpio, polarity);
+ unsigned int pin = agpio->pin_table[index];
+ struct gpio_desc *desc;
+ int ret;
+
+ desc = gpiochip_request_own_desc(chip, pin, label, polarity, flags);
+ if (IS_ERR(desc))
+ return desc;
+
+ /* ACPI uses hundredths of milliseconds units */
+ ret = gpio_set_debounce_timeout(desc, agpio->debounce_timeout * 10);
+ if (ret)
+ dev_warn(chip->parent,
+ "Failed to set debounce-timeout for pin 0x%04X, err %d\n",
+ pin, ret);
+
+ return desc;
+}
+
+static bool acpi_gpio_irq_is_wake(struct device *parent,
+ const struct acpi_resource_gpio *agpio)
+{
+ unsigned int pin = agpio->pin_table[0];
+
+ if (agpio->wake_capable != ACPI_WAKE_CAPABLE)
+ return false;
+
+ if (acpi_gpio_in_ignore_list(ACPI_GPIO_IGNORE_WAKE, dev_name(parent), pin)) {
+ dev_info(parent, "Ignoring wakeup on pin %u\n", pin);
+ return false;
+ }
+
+ return true;
+}
+
+/* Always returns AE_OK so that we keep looping over the resources */
+static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
+ void *context)
+{
+ struct acpi_gpio_chip *acpi_gpio = context;
+ struct gpio_chip *chip = acpi_gpio->chip;
+ struct acpi_resource_gpio *agpio;
+ acpi_handle handle, evt_handle;
+ struct acpi_gpio_event *event;
+ irq_handler_t handler = NULL;
+ struct gpio_desc *desc;
+ unsigned int pin;
+ int ret, irq;
+
+ if (!acpi_gpio_get_irq_resource(ares, &agpio))
+ return AE_OK;
+
+ handle = ACPI_HANDLE(chip->parent);
+ pin = agpio->pin_table[0];
+
+ if (pin <= 255) {
+ char ev_name[8];
+ sprintf(ev_name, "_%c%02X",
+ agpio->triggering == ACPI_EDGE_SENSITIVE ? 'E' : 'L',
+ pin);
+ if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle)))
+ handler = acpi_gpio_irq_handler;
+ }
+ if (!handler) {
+ if (ACPI_SUCCESS(acpi_get_handle(handle, "_EVT", &evt_handle)))
+ handler = acpi_gpio_irq_handler_evt;
+ }
+ if (!handler)
+ return AE_OK;
+
+ if (acpi_gpio_in_ignore_list(ACPI_GPIO_IGNORE_INTERRUPT, dev_name(chip->parent), pin)) {
+ dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin);
+ return AE_OK;
+ }
+
+ desc = acpi_request_own_gpiod(chip, agpio, 0, "ACPI:Event");
+ if (IS_ERR(desc)) {
+ dev_err(chip->parent,
+ "Failed to request GPIO for pin 0x%04X, err %ld\n",
+ pin, PTR_ERR(desc));
+ return AE_OK;
+ }
+
+ ret = gpiochip_lock_as_irq(chip, pin);
+ if (ret) {
+ dev_err(chip->parent,
+ "Failed to lock GPIO pin 0x%04X as interrupt, err %d\n",
+ pin, ret);
+ goto fail_free_desc;
+ }
+
+ irq = gpiod_to_irq(desc);
+ if (irq < 0) {
+ dev_err(chip->parent,
+ "Failed to translate GPIO pin 0x%04X to IRQ, err %d\n",
+ pin, irq);
+ goto fail_unlock_irq;
+ }
+
+ event = kzalloc(sizeof(*event), GFP_KERNEL);
+ if (!event)
+ goto fail_unlock_irq;
+
+ event->irqflags = IRQF_ONESHOT;
+ if (agpio->triggering == ACPI_LEVEL_SENSITIVE) {
+ if (agpio->polarity == ACPI_ACTIVE_HIGH)
+ event->irqflags |= IRQF_TRIGGER_HIGH;
+ else
+ event->irqflags |= IRQF_TRIGGER_LOW;
+ } else {
+ switch (agpio->polarity) {
+ case ACPI_ACTIVE_HIGH:
+ event->irqflags |= IRQF_TRIGGER_RISING;
+ break;
+ case ACPI_ACTIVE_LOW:
+ event->irqflags |= IRQF_TRIGGER_FALLING;
+ break;
+ default:
+ event->irqflags |= IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING;
+ break;
+ }
+ }
+
+ event->handle = evt_handle;
+ event->handler = handler;
+ event->irq = irq;
+ event->irq_is_wake = acpi_gpio_irq_is_wake(chip->parent, agpio);
+ event->pin = pin;
+ event->desc = desc;
+
+ list_add_tail(&event->node, &acpi_gpio->events);
+
+ return AE_OK;
+
+fail_unlock_irq:
+ gpiochip_unlock_as_irq(chip, pin);
+fail_free_desc:
+ gpiochip_free_own_desc(desc);
+
+ return AE_OK;
+}
+
+/**
+ * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events
+ * @chip: GPIO chip
+ *
+ * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
+ * handled by ACPI event methods which need to be called from the GPIO
+ * chip's interrupt handler. acpi_gpiochip_request_interrupts() finds out which
+ * GPIO pins have ACPI event methods and assigns interrupt handlers that calls
+ * the ACPI event methods for those pins.
+ */
+void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
+{
+ struct acpi_gpio_chip *acpi_gpio;
+ acpi_handle handle;
+ acpi_status status;
+
+ if (!chip->parent || !chip->to_irq)
+ return;
+
+ handle = ACPI_HANDLE(chip->parent);
+ if (!handle)
+ return;
+
+ status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
+ if (ACPI_FAILURE(status))
+ return;
+
+ if (acpi_quirk_skip_gpio_event_handlers())
+ return;
+
+ acpi_walk_resources(handle, METHOD_NAME__AEI,
+ acpi_gpiochip_alloc_event, acpi_gpio);
+
+ if (acpi_gpio_add_to_deferred_list(&acpi_gpio->deferred_req_irqs_list_entry))
+ return;
+
+ acpi_gpiochip_request_irqs(acpi_gpio);
+}
+EXPORT_SYMBOL_GPL(acpi_gpiochip_request_interrupts);
+
+/**
+ * acpi_gpiochip_free_interrupts() - Free GPIO ACPI event interrupts.
+ * @chip: GPIO chip
+ *
+ * Free interrupts associated with GPIO ACPI event method for the given
+ * GPIO chip.
+ */
+void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
+{
+ struct acpi_gpio_chip *acpi_gpio;
+ struct acpi_gpio_event *event, *ep;
+ acpi_handle handle;
+ acpi_status status;
+
+ if (!chip->parent || !chip->to_irq)
+ return;
+
+ handle = ACPI_HANDLE(chip->parent);
+ if (!handle)
+ return;
+
+ status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
+ if (ACPI_FAILURE(status))
+ return;
+
+ acpi_gpio_remove_from_deferred_list(&acpi_gpio->deferred_req_irqs_list_entry);
+
+ list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
+ if (event->irq_requested) {
+ if (event->irq_is_wake)
+ disable_irq_wake(event->irq);
+
+ free_irq(event->irq, event);
+ }
+
+ gpiochip_unlock_as_irq(chip, event->pin);
+ gpiochip_free_own_desc(event->desc);
+ list_del(&event->node);
+ kfree(event);
+ }
+}
+EXPORT_SYMBOL_GPL(acpi_gpiochip_free_interrupts);
+
+void __init acpi_gpio_process_deferred_list(struct list_head *list)
+{
+ struct acpi_gpio_chip *acpi_gpio, *tmp;
+
+ list_for_each_entry_safe(acpi_gpio, tmp, list, deferred_req_irqs_list_entry)
+ acpi_gpiochip_request_irqs(acpi_gpio);
+}
+
+int acpi_dev_add_driver_gpios(struct acpi_device *adev,
+ const struct acpi_gpio_mapping *gpios)
+{
+ if (adev && gpios) {
+ adev->driver_gpios = gpios;
+ return 0;
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios);
+
+void acpi_dev_remove_driver_gpios(struct acpi_device *adev)
+{
+ if (adev)
+ adev->driver_gpios = NULL;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_remove_driver_gpios);
+
+static void acpi_dev_release_driver_gpios(void *adev)
+{
+ acpi_dev_remove_driver_gpios(adev);
+}
+
+int devm_acpi_dev_add_driver_gpios(struct device *dev,
+ const struct acpi_gpio_mapping *gpios)
+{
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+ int ret;
+
+ ret = acpi_dev_add_driver_gpios(adev, gpios);
+ if (ret)
+ return ret;
+
+ return devm_add_action_or_reset(dev, acpi_dev_release_driver_gpios, adev);
+}
+EXPORT_SYMBOL_GPL(devm_acpi_dev_add_driver_gpios);
+
+static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
+ const char *name, int index,
+ struct fwnode_reference_args *args,
+ unsigned int *quirks)
+{
+ const struct acpi_gpio_mapping *gm;
+
+ if (!adev || !adev->driver_gpios)
+ return false;
+
+ for (gm = adev->driver_gpios; gm->name; gm++)
+ if (!strcmp(name, gm->name) && gm->data && index < gm->size) {
+ const struct acpi_gpio_params *par = gm->data + index;
+
+ args->fwnode = acpi_fwnode_handle(adev);
+ args->args[0] = par->crs_entry_index;
+ args->args[1] = par->line_index;
+ args->args[2] = par->active_low;
+ args->nargs = 3;
+
+ *quirks = gm->quirks;
+ return true;
+ }
+
+ return false;
+}
+
+static int
+__acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update)
+{
+ const enum gpiod_flags mask =
+ GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT |
+ GPIOD_FLAGS_BIT_DIR_VAL;
+ int ret = 0;
+
+ /*
+ * Check if the BIOS has IoRestriction with explicitly set direction
+ * and update @flags accordingly. Otherwise use whatever caller asked
+ * for.
+ */
+ if (update & GPIOD_FLAGS_BIT_DIR_SET) {
+ enum gpiod_flags diff = *flags ^ update;
+
+ /*
+ * Check if caller supplied incompatible GPIO initialization
+ * flags.
+ *
+ * Return %-EINVAL to notify that firmware has different
+ * settings and we are going to use them.
+ */
+ if (((*flags & GPIOD_FLAGS_BIT_DIR_SET) && (diff & GPIOD_FLAGS_BIT_DIR_OUT)) ||
+ ((*flags & GPIOD_FLAGS_BIT_DIR_OUT) && (diff & GPIOD_FLAGS_BIT_DIR_VAL)))
+ ret = -EINVAL;
+ *flags = (*flags & ~mask) | (update & mask);
+ }
+ return ret;
+}
+
+static int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags,
+ struct acpi_gpio_info *info)
+{
+ struct device *dev = &info->adev->dev;
+ enum gpiod_flags old = *flags;
+ int ret;
+
+ ret = __acpi_gpio_update_gpiod_flags(&old, info->flags);
+ if (info->quirks & ACPI_GPIO_QUIRK_NO_IO_RESTRICTION) {
+ if (ret)
+ dev_warn(dev, FW_BUG "GPIO not in correct mode, fixing\n");
+ } else {
+ if (ret)
+ dev_dbg(dev, "Override GPIO initialization flags\n");
+ *flags = old;
+ }
+
+ return ret;
+}
+
+static int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
+ struct acpi_gpio_info *info)
+{
+ switch (info->pin_config) {
+ case ACPI_PIN_CONFIG_PULLUP:
+ *lookupflags |= GPIO_PULL_UP;
+ break;
+ case ACPI_PIN_CONFIG_PULLDOWN:
+ *lookupflags |= GPIO_PULL_DOWN;
+ break;
+ case ACPI_PIN_CONFIG_NOPULL:
+ *lookupflags |= GPIO_PULL_DISABLE;
+ break;
+ default:
+ break;
+ }
+
+ if (info->polarity == GPIO_ACTIVE_LOW)
+ *lookupflags |= GPIO_ACTIVE_LOW;
+
+ return 0;
+}
+
+struct acpi_gpio_lookup {
+ struct acpi_gpio_info info;
+ int index;
+ u16 pin_index;
+ bool active_low;
+ struct gpio_desc *desc;
+ int n;
+};
+
+static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
+{
+ struct acpi_gpio_lookup *lookup = data;
+
+ if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
+ return 1;
+
+ 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)
+ lookup->index++;
+
+ if (lookup->n++ != lookup->index)
+ return 1;
+
+ pin_index = lookup->pin_index;
+ if (pin_index >= agpio->pin_table_length)
+ return 1;
+
+ 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;
+ lookup->info.wake_capable = acpi_gpio_irq_is_wake(&lookup->info.adev->dev, agpio);
+
+ /*
+ * Polarity and triggering are only specified for GpioInt
+ * resource.
+ * Note: we expect here:
+ * - ACPI_ACTIVE_LOW == GPIO_ACTIVE_LOW
+ * - ACPI_ACTIVE_HIGH == GPIO_ACTIVE_HIGH
+ */
+ if (lookup->info.gpioint) {
+ lookup->info.polarity = agpio->polarity;
+ lookup->info.triggering = agpio->triggering;
+ } else {
+ lookup->info.polarity = lookup->active_low;
+ }
+
+ lookup->info.flags = acpi_gpio_to_gpiod_flags(agpio, lookup->info.polarity);
+ }
+
+ return 1;
+}
+
+static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
+ struct acpi_gpio_info *info)
+{
+ struct acpi_device *adev = lookup->info.adev;
+ struct list_head res_list;
+ int ret;
+
+ INIT_LIST_HEAD(&res_list);
+
+ ret = acpi_dev_get_resources(adev, &res_list,
+ acpi_populate_gpio_lookup,
+ lookup);
+ if (ret < 0)
+ return ret;
+
+ acpi_dev_free_resource_list(&res_list);
+
+ if (!lookup->desc)
+ return -ENOENT;
+
+ if (info)
+ *info = lookup->info;
+ return 0;
+}
+
+static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
+ const char *propname, int index,
+ struct acpi_gpio_lookup *lookup)
+{
+ struct fwnode_reference_args args;
+ unsigned int quirks = 0;
+ int ret;
+
+ memset(&args, 0, sizeof(args));
+ ret = __acpi_node_get_property_reference(fwnode, propname, index, 3,
+ &args);
+ if (ret) {
+ struct acpi_device *adev;
+
+ adev = to_acpi_device_node(fwnode);
+ if (!acpi_get_driver_gpio_data(adev, propname, index, &args, &quirks))
+ return ret;
+ }
+ /*
+ * The property was found and resolved, so need to lookup the GPIO based
+ * on returned args.
+ */
+ if (!to_acpi_device_node(args.fwnode))
+ return -EINVAL;
+ if (args.nargs != 3)
+ return -EPROTO;
+
+ lookup->index = args.args[0];
+ lookup->pin_index = args.args[1];
+ lookup->active_low = !!args.args[2];
+
+ lookup->info.adev = to_acpi_device_node(args.fwnode);
+ lookup->info.quirks = quirks;
+
+ return 0;
+}
+
+/**
+ * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
+ * @adev: pointer to a ACPI device to get GPIO from
+ * @propname: Property name of the GPIO (optional)
+ * @index: index of GpioIo/GpioInt resource (starting from %0)
+ * @info: info pointer to fill in (optional)
+ *
+ * Function goes through ACPI resources for @adev and based on @index looks
+ * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor,
+ * and returns it. @index matches GpioIo/GpioInt resources only so if there
+ * are total %3 GPIO resources, the index goes from %0 to %2.
+ *
+ * If @propname is specified the GPIO is looked using device property. In
+ * that case @index is used to select the GPIO entry in the property value
+ * (in case of multiple).
+ *
+ * Returns:
+ * GPIO descriptor to use with Linux generic GPIO API.
+ * If the GPIO cannot be translated or there is an error an ERR_PTR is
+ * returned.
+ *
+ * Note: if the GPIO resource has multiple entries in the pin list, this
+ * function only returns the first.
+ */
+static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
+ const char *propname,
+ int index,
+ struct acpi_gpio_info *info)
+{
+ struct acpi_gpio_lookup lookup;
+ int ret;
+
+ memset(&lookup, 0, sizeof(lookup));
+ lookup.index = index;
+
+ if (propname) {
+ dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname);
+
+ ret = acpi_gpio_property_lookup(acpi_fwnode_handle(adev),
+ propname, index, &lookup);
+ if (ret)
+ return ERR_PTR(ret);
+
+ dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %u %u\n",
+ dev_name(&lookup.info.adev->dev), lookup.index,
+ lookup.pin_index, lookup.active_low);
+ } else {
+ dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index);
+ lookup.info.adev = adev;
+ }
+
+ ret = acpi_gpio_resource_lookup(&lookup, info);
+ return ret ? ERR_PTR(ret) : lookup.desc;
+}
+
+/**
+ * acpi_get_gpiod_from_data() - get a GPIO descriptor from ACPI data node
+ * @fwnode: pointer to an ACPI firmware node to get the GPIO information from
+ * @propname: Property name of the GPIO
+ * @index: index of GpioIo/GpioInt resource (starting from %0)
+ * @info: info pointer to fill in (optional)
+ *
+ * This function uses the property-based GPIO lookup to get to the GPIO
+ * resource with the relevant information from a data-only ACPI firmware node
+ * and uses that to obtain the GPIO descriptor to return.
+ *
+ * Returns:
+ * GPIO descriptor to use with Linux generic GPIO API.
+ * If the GPIO cannot be translated or there is an error an ERR_PTR is
+ * returned.
+ */
+static struct gpio_desc *acpi_get_gpiod_from_data(struct fwnode_handle *fwnode,
+ const char *propname,
+ int index,
+ struct acpi_gpio_info *info)
+{
+ struct acpi_gpio_lookup lookup;
+ int ret;
+
+ if (!is_acpi_data_node(fwnode))
+ return ERR_PTR(-ENODEV);
+
+ if (!propname)
+ return ERR_PTR(-EINVAL);
+
+ memset(&lookup, 0, sizeof(lookup));
+ lookup.index = index;
+
+ ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = acpi_gpio_resource_lookup(&lookup, info);
+ return ret ? ERR_PTR(ret) : lookup.desc;
+}
+
+static bool acpi_can_fallback_to_crs(struct acpi_device *adev,
+ const char *con_id)
+{
+ /* If there is no ACPI device, there is no _CRS to fall back to */
+ if (!adev)
+ return false;
+
+ /* Never allow fallback if the device has properties */
+ if (acpi_dev_has_props(adev) || adev->driver_gpios)
+ return false;
+
+ return con_id == NULL;
+}
+
+static struct gpio_desc *
+__acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id, unsigned int idx,
+ bool can_fallback, struct acpi_gpio_info *info)
+{
+ struct acpi_device *adev = to_acpi_device_node(fwnode);
+ struct gpio_desc *desc;
+ char propname[32];
+
+ /* Try first from _DSD */
+ for_each_gpio_property_name(propname, con_id) {
+ if (adev)
+ desc = acpi_get_gpiod_by_index(adev,
+ propname, idx, info);
+ else
+ desc = acpi_get_gpiod_from_data(fwnode,
+ propname, idx, info);
+ if (PTR_ERR(desc) == -EPROBE_DEFER)
+ return ERR_CAST(desc);
+
+ if (!IS_ERR(desc))
+ return desc;
+ }
+
+ /* Then from plain _CRS GPIOs */
+ if (can_fallback)
+ return acpi_get_gpiod_by_index(adev, NULL, idx, info);
+
+ return ERR_PTR(-ENOENT);
+}
+
+struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode,
+ const char *con_id,
+ unsigned int idx,
+ enum gpiod_flags *dflags,
+ unsigned long *lookupflags)
+{
+ struct acpi_device *adev = to_acpi_device_node(fwnode);
+ bool can_fallback = acpi_can_fallback_to_crs(adev, con_id);
+ struct acpi_gpio_info info;
+ struct gpio_desc *desc;
+
+ desc = __acpi_find_gpio(fwnode, con_id, idx, can_fallback, &info);
+ if (IS_ERR(desc))
+ return desc;
+
+ if (info.gpioint &&
+ (*dflags == GPIOD_OUT_LOW || *dflags == GPIOD_OUT_HIGH)) {
+ dev_dbg(&adev->dev, "refusing GpioInt() entry when doing GPIOD_OUT_* lookup\n");
+ return ERR_PTR(-ENOENT);
+ }
+
+ acpi_gpio_update_gpiod_flags(dflags, &info);
+ acpi_gpio_update_gpiod_lookup_flags(lookupflags, &info);
+ return desc;
+}
+
+/**
+ * acpi_dev_gpio_irq_wake_get_by() - Find GpioInt and translate it to Linux IRQ number
+ * @adev: pointer to a ACPI device to get IRQ from
+ * @con_id: optional name of GpioInt resource
+ * @index: index of GpioInt resource (starting from %0)
+ * @wake_capable: Set to true if the IRQ is wake capable
+ *
+ * If the device has one or more GpioInt resources, this function can be
+ * used to translate from the GPIO offset in the resource to the Linux IRQ
+ * number.
+ *
+ * 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 @con_id parameter. If the resource has
+ * a @con_id in a property, then only those will be taken into account.
+ *
+ * The GPIO is considered wake capable if the GpioInt resource specifies
+ * SharedAndWake or ExclusiveAndWake.
+ *
+ * Returns:
+ * Linux IRQ number (> 0) on success, negative errno on failure.
+ */
+int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *con_id, int index,
+ bool *wake_capable)
+{
+ struct fwnode_handle *fwnode = acpi_fwnode_handle(adev);
+ int idx, i;
+ unsigned int irq_flags;
+ int ret;
+
+ for (i = 0, idx = 0; idx <= index; i++) {
+ struct acpi_gpio_info info;
+ struct gpio_desc *desc;
+
+ /* Ignore -EPROBE_DEFER, it only matters if idx matches */
+ desc = __acpi_find_gpio(fwnode, con_id, i, true, &info);
+ if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER)
+ return PTR_ERR(desc);
+
+ if (info.gpioint && idx++ == index) {
+ unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
+ enum gpiod_flags dflags = GPIOD_ASIS;
+ char label[32];
+ int irq;
+
+ if (IS_ERR(desc))
+ return PTR_ERR(desc);
+
+ irq = gpiod_to_irq(desc);
+ if (irq < 0)
+ return irq;
+
+ acpi_gpio_update_gpiod_flags(&dflags, &info);
+ acpi_gpio_update_gpiod_lookup_flags(&lflags, &info);
+
+ snprintf(label, sizeof(label), "%pfwP GpioInt(%d)", fwnode, index);
+ ret = gpiod_set_consumer_name(desc, con_id ?: label);
+ if (ret)
+ return ret;
+
+ ret = gpiod_configure_flags(desc, label, lflags, dflags);
+ if (ret < 0)
+ return ret;
+
+ /* ACPI uses hundredths of milliseconds units */
+ ret = gpio_set_debounce_timeout(desc, info.debounce * 10);
+ if (ret)
+ return ret;
+
+ irq_flags = acpi_dev_get_irq_type(info.triggering,
+ info.polarity);
+
+ /*
+ * If the IRQ is not already in use then set type
+ * if specified and different than the current one.
+ */
+ if (can_request_irq(irq, irq_flags)) {
+ if (irq_flags != IRQ_TYPE_NONE &&
+ irq_flags != irq_get_trigger_type(irq))
+ irq_set_irq_type(irq, irq_flags);
+ } else {
+ dev_dbg(&adev->dev, "IRQ %d already in use\n", irq);
+ }
+
+ /* avoid suspend issues with GPIOs when systems are using S3 */
+ if (wake_capable && acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)
+ *wake_capable = info.wake_capable;
+
+ return irq;
+ }
+
+ }
+ return -ENOENT;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_wake_get_by);
+
+static acpi_status
+acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
+ u32 bits, u64 *value, void *handler_context,
+ void *region_context)
+{
+ struct acpi_gpio_chip *achip = region_context;
+ struct gpio_chip *chip = achip->chip;
+ struct acpi_resource_gpio *agpio;
+ struct acpi_resource *ares;
+ u16 pin_index = address;
+ acpi_status status;
+ int length;
+ int i;
+
+ status = acpi_buffer_to_resource(achip->conn_info.connection,
+ achip->conn_info.length, &ares);
+ if (ACPI_FAILURE(status))
+ return status;
+
+ if (WARN_ON(ares->type != ACPI_RESOURCE_TYPE_GPIO)) {
+ ACPI_FREE(ares);
+ return AE_BAD_PARAMETER;
+ }
+
+ agpio = &ares->data.gpio;
+
+ if (WARN_ON(agpio->io_restriction == ACPI_IO_RESTRICT_INPUT &&
+ function == ACPI_WRITE)) {
+ ACPI_FREE(ares);
+ return AE_BAD_PARAMETER;
+ }
+
+ length = min_t(u16, agpio->pin_table_length, pin_index + bits);
+ for (i = pin_index; i < length; ++i) {
+ unsigned int pin = agpio->pin_table[i];
+ struct acpi_gpio_connection *conn;
+ struct gpio_desc *desc;
+ bool found;
+
+ mutex_lock(&achip->conn_lock);
+
+ found = false;
+ list_for_each_entry(conn, &achip->conns, node) {
+ if (conn->pin == pin) {
+ found = true;
+ desc = conn->desc;
+ break;
+ }
+ }
+
+ /*
+ * The same GPIO can be shared between operation region and
+ * event but only if the access here is ACPI_READ. In that
+ * case we "borrow" the event GPIO instead.
+ */
+ if (!found && agpio->shareable == ACPI_SHARED &&
+ function == ACPI_READ) {
+ struct acpi_gpio_event *event;
+
+ list_for_each_entry(event, &achip->events, node) {
+ if (event->pin == pin) {
+ desc = event->desc;
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ desc = acpi_request_own_gpiod(chip, agpio, i, "ACPI:OpRegion");
+ if (IS_ERR(desc)) {
+ mutex_unlock(&achip->conn_lock);
+ status = AE_ERROR;
+ goto out;
+ }
+
+ conn = kzalloc(sizeof(*conn), GFP_KERNEL);
+ if (!conn) {
+ gpiochip_free_own_desc(desc);
+ mutex_unlock(&achip->conn_lock);
+ status = AE_NO_MEMORY;
+ goto out;
+ }
+
+ conn->pin = pin;
+ conn->desc = desc;
+ list_add_tail(&conn->node, &achip->conns);
+ }
+
+ mutex_unlock(&achip->conn_lock);
+
+ if (function == ACPI_WRITE)
+ gpiod_set_raw_value_cansleep(desc, !!(*value & BIT(i)));
+ else
+ *value |= (u64)gpiod_get_raw_value_cansleep(desc) << i;
+ }
+
+out:
+ ACPI_FREE(ares);
+ return status;
+}
+
+static void acpi_gpiochip_request_regions(struct acpi_gpio_chip *achip)
+{
+ struct gpio_chip *chip = achip->chip;
+ acpi_handle handle = ACPI_HANDLE(chip->parent);
+ acpi_status status;
+
+ INIT_LIST_HEAD(&achip->conns);
+ mutex_init(&achip->conn_lock);
+ status = acpi_install_address_space_handler(handle, ACPI_ADR_SPACE_GPIO,
+ acpi_gpio_adr_space_handler,
+ NULL, achip);
+ if (ACPI_FAILURE(status))
+ dev_err(chip->parent,
+ "Failed to install GPIO OpRegion handler\n");
+}
+
+static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip)
+{
+ struct gpio_chip *chip = achip->chip;
+ acpi_handle handle = ACPI_HANDLE(chip->parent);
+ struct acpi_gpio_connection *conn, *tmp;
+ acpi_status status;
+
+ status = acpi_remove_address_space_handler(handle, ACPI_ADR_SPACE_GPIO,
+ acpi_gpio_adr_space_handler);
+ if (ACPI_FAILURE(status)) {
+ dev_err(chip->parent,
+ "Failed to remove GPIO OpRegion handler\n");
+ return;
+ }
+
+ list_for_each_entry_safe_reverse(conn, tmp, &achip->conns, node) {
+ gpiochip_free_own_desc(conn->desc);
+ list_del(&conn->node);
+ kfree(conn);
+ }
+}
+
+static struct gpio_desc *
+acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip,
+ struct fwnode_handle *fwnode,
+ const char **name,
+ unsigned long *lflags,
+ enum gpiod_flags *dflags)
+{
+ struct gpio_chip *chip = achip->chip;
+ struct gpio_desc *desc;
+ u32 gpios[2];
+ int ret;
+
+ *lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
+ *dflags = GPIOD_ASIS;
+ *name = NULL;
+
+ ret = fwnode_property_read_u32_array(fwnode, "gpios", gpios,
+ ARRAY_SIZE(gpios));
+ if (ret < 0)
+ return ERR_PTR(ret);
+
+ desc = gpiochip_get_desc(chip, gpios[0]);
+ if (IS_ERR(desc))
+ return desc;
+
+ if (gpios[1])
+ *lflags |= GPIO_ACTIVE_LOW;
+
+ if (fwnode_property_present(fwnode, "input"))
+ *dflags |= GPIOD_IN;
+ else if (fwnode_property_present(fwnode, "output-low"))
+ *dflags |= GPIOD_OUT_LOW;
+ else if (fwnode_property_present(fwnode, "output-high"))
+ *dflags |= GPIOD_OUT_HIGH;
+ else
+ return ERR_PTR(-EINVAL);
+
+ fwnode_property_read_string(fwnode, "line-name", name);
+
+ return desc;
+}
+
+static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip)
+{
+ struct gpio_chip *chip = achip->chip;
+ struct fwnode_handle *fwnode;
+
+ device_for_each_child_node(chip->parent, fwnode) {
+ unsigned long lflags;
+ enum gpiod_flags dflags;
+ struct gpio_desc *desc;
+ const char *name;
+ int ret;
+
+ if (!fwnode_property_present(fwnode, "gpio-hog"))
+ continue;
+
+ desc = acpi_gpiochip_parse_own_gpio(achip, fwnode, &name,
+ &lflags, &dflags);
+ if (IS_ERR(desc))
+ continue;
+
+ ret = gpiod_hog(desc, name, lflags, dflags);
+ if (ret) {
+ dev_err(chip->parent, "Failed to hog GPIO\n");
+ fwnode_handle_put(fwnode);
+ return;
+ }
+ }
+}
+
+void acpi_gpiochip_add(struct gpio_chip *chip)
+{
+ struct acpi_gpio_chip *acpi_gpio;
+ struct acpi_device *adev;
+ acpi_status status;
+
+ if (!chip || !chip->parent)
+ return;
+
+ adev = ACPI_COMPANION(chip->parent);
+ if (!adev)
+ return;
+
+ acpi_gpio = kzalloc(sizeof(*acpi_gpio), GFP_KERNEL);
+ if (!acpi_gpio) {
+ dev_err(chip->parent,
+ "Failed to allocate memory for ACPI GPIO chip\n");
+ return;
+ }
+
+ acpi_gpio->chip = chip;
+ INIT_LIST_HEAD(&acpi_gpio->events);
+ INIT_LIST_HEAD(&acpi_gpio->deferred_req_irqs_list_entry);
+
+ status = acpi_attach_data(adev->handle, acpi_gpio_chip_dh, acpi_gpio);
+ if (ACPI_FAILURE(status)) {
+ dev_err(chip->parent, "Failed to attach ACPI GPIO chip\n");
+ kfree(acpi_gpio);
+ return;
+ }
+
+ acpi_gpiochip_request_regions(acpi_gpio);
+ acpi_gpiochip_scan_gpios(acpi_gpio);
+ acpi_dev_clear_dependencies(adev);
+}
+
+void acpi_gpiochip_remove(struct gpio_chip *chip)
+{
+ struct acpi_gpio_chip *acpi_gpio;
+ acpi_handle handle;
+ acpi_status status;
+
+ if (!chip || !chip->parent)
+ return;
+
+ handle = ACPI_HANDLE(chip->parent);
+ if (!handle)
+ return;
+
+ status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
+ if (ACPI_FAILURE(status)) {
+ dev_warn(chip->parent, "Failed to retrieve ACPI GPIO chip\n");
+ return;
+ }
+
+ acpi_gpiochip_free_regions(acpi_gpio);
+
+ acpi_detach_data(handle, acpi_gpio_chip_dh);
+ kfree(acpi_gpio);
+}
+
+static int acpi_gpio_package_count(const union acpi_object *obj)
+{
+ const union acpi_object *element = obj->package.elements;
+ const union acpi_object *end = element + obj->package.count;
+ unsigned int count = 0;
+
+ while (element < end) {
+ switch (element->type) {
+ case ACPI_TYPE_LOCAL_REFERENCE:
+ element += 3;
+ fallthrough;
+ case ACPI_TYPE_INTEGER:
+ element++;
+ count++;
+ break;
+
+ default:
+ return -EPROTO;
+ }
+ }
+
+ return count;
+}
+
+static int acpi_find_gpio_count(struct acpi_resource *ares, void *data)
+{
+ unsigned int *count = data;
+
+ if (ares->type == ACPI_RESOURCE_TYPE_GPIO)
+ *count += ares->data.gpio.pin_table_length;
+
+ return 1;
+}
+
+/**
+ * acpi_gpio_count - count the GPIOs associated with a firmware node / function
+ * @fwnode: firmware node of the GPIO consumer
+ * @con_id: function within the GPIO consumer
+ *
+ * Returns:
+ * The number of GPIOs associated with a firmware node / function or %-ENOENT,
+ * if no GPIO has been assigned to the requested function.
+ */
+int acpi_gpio_count(const struct fwnode_handle *fwnode, const char *con_id)
+{
+ struct acpi_device *adev = to_acpi_device_node(fwnode);
+ const union acpi_object *obj;
+ const struct acpi_gpio_mapping *gm;
+ int count = -ENOENT;
+ int ret;
+ char propname[32];
+
+ /* Try first from _DSD */
+ for_each_gpio_property_name(propname, con_id) {
+ ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY, &obj);
+ if (ret == 0) {
+ if (obj->type == ACPI_TYPE_LOCAL_REFERENCE)
+ count = 1;
+ else if (obj->type == ACPI_TYPE_PACKAGE)
+ count = acpi_gpio_package_count(obj);
+ } else if (adev->driver_gpios) {
+ for (gm = adev->driver_gpios; gm->name; gm++)
+ if (strcmp(propname, gm->name) == 0) {
+ count = gm->size;
+ break;
+ }
+ }
+ if (count > 0)
+ break;
+ }
+
+ /* Then from plain _CRS GPIOs */
+ if (count < 0) {
+ struct list_head resource_list;
+ unsigned int crs_count = 0;
+
+ if (!acpi_can_fallback_to_crs(adev, con_id))
+ return count;
+
+ INIT_LIST_HEAD(&resource_list);
+ acpi_dev_get_resources(adev, &resource_list,
+ acpi_find_gpio_count, &crs_count);
+ acpi_dev_free_resource_list(&resource_list);
+ if (crs_count > 0)
+ count = crs_count;
+ }
+ return count ? count : -ENOENT;
+}
--- /dev/null
+++ b/drivers/gpio/gpiolib-acpi-quirks.c
@@ -0,0 +1,363 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ACPI quirks for GPIO ACPI helpers
+ *
+ * Author: Hans de Goede <hdegoede@redhat.com>
+ */
+
+#include <linux/dmi.h>
+#include <linux/kstrtox.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/printk.h>
+#include <linux/string.h>
+#include <linux/types.h>
+
+#include "gpiolib-acpi.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");
+
+static char *ignore_wake;
+module_param(ignore_wake, charp, 0444);
+MODULE_PARM_DESC(ignore_wake,
+ "controller@pin combos on which to ignore the ACPI wake flag "
+ "ignore_wake=controller@pin[,controller@pin[,...]]");
+
+static char *ignore_interrupt;
+module_param(ignore_interrupt, charp, 0444);
+MODULE_PARM_DESC(ignore_interrupt,
+ "controller@pin combos on which to ignore interrupt "
+ "ignore_interrupt=controller@pin[,controller@pin[,...]]");
+
+/*
+ * For GPIO chips which call acpi_gpiochip_request_interrupts() before late_init
+ * (so builtin drivers) we register the ACPI GpioInt IRQ handlers from a
+ * late_initcall_sync() handler, so that other builtin drivers can register their
+ * OpRegions before the event handlers can run. This list contains GPIO chips
+ * for which the acpi_gpiochip_request_irqs() call has been deferred.
+ */
+static DEFINE_MUTEX(acpi_gpio_deferred_req_irqs_lock);
+static LIST_HEAD(acpi_gpio_deferred_req_irqs_list);
+static bool acpi_gpio_deferred_req_irqs_done;
+
+bool acpi_gpio_add_to_deferred_list(struct list_head *list)
+{
+ bool defer;
+
+ mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
+ defer = !acpi_gpio_deferred_req_irqs_done;
+ if (defer)
+ list_add(list, &acpi_gpio_deferred_req_irqs_list);
+ mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
+
+ return defer;
+}
+
+void acpi_gpio_remove_from_deferred_list(struct list_head *list)
+{
+ mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
+ if (!list_empty(list))
+ list_del_init(list);
+ mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
+}
+
+int acpi_gpio_need_run_edge_events_on_boot(void)
+{
+ return run_edge_events_on_boot;
+}
+
+bool acpi_gpio_in_ignore_list(enum acpi_gpio_ignore_list list,
+ const char *controller_in, unsigned int pin_in)
+{
+ const char *ignore_list, *controller, *pin_str;
+ unsigned int pin;
+ char *endp;
+ int len;
+
+ switch (list) {
+ case ACPI_GPIO_IGNORE_WAKE:
+ ignore_list = ignore_wake;
+ break;
+ case ACPI_GPIO_IGNORE_INTERRUPT:
+ ignore_list = ignore_interrupt;
+ break;
+ default:
+ return false;
+ }
+
+ controller = ignore_list;
+ while (controller) {
+ pin_str = strchr(controller, '@');
+ if (!pin_str)
+ goto err;
+
+ len = pin_str - controller;
+ if (len == strlen(controller_in) &&
+ strncmp(controller, controller_in, len) == 0) {
+ pin = simple_strtoul(pin_str + 1, &endp, 10);
+ if (*endp != 0 && *endp != ',')
+ goto err;
+
+ if (pin == pin_in)
+ return true;
+ }
+
+ controller = strchr(controller, ',');
+ if (controller)
+ controller++;
+ }
+
+ return false;
+err:
+ pr_err_once("Error: Invalid value for gpiolib_acpi.ignore_...: %s\n", ignore_list);
+ return false;
+}
+
+/* Run deferred acpi_gpiochip_request_irqs() */
+static int __init acpi_gpio_handle_deferred_request_irqs(void)
+{
+ mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
+ acpi_gpio_process_deferred_list(&acpi_gpio_deferred_req_irqs_list);
+ acpi_gpio_deferred_req_irqs_done = true;
+ mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
+
+ return 0;
+}
+/* We must use _sync so that this runs after the first deferred_probe run */
+late_initcall_sync(acpi_gpio_handle_deferred_request_irqs);
+
+struct acpi_gpiolib_dmi_quirk {
+ bool no_edge_events_on_boot;
+ char *ignore_wake;
+ char *ignore_interrupt;
+};
+
+static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
+ {
+ /*
+ * The Minix Neo Z83-4 has a micro-USB-B id-pin handler for
+ * a non existing micro-USB-B connector which puts the HDMI
+ * DDC pins in GPIO mode, breaking HDMI support.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .no_edge_events_on_boot = true,
+ },
+ },
+ {
+ /*
+ * The Terra Pad 1061 has a micro-USB-B id-pin handler, which
+ * instead of controlling the actual micro-USB-B turns the 5V
+ * boost for its USB-A connector off. The actual micro-USB-B
+ * connector is wired for charging only.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Wortmann_AG"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "TERRA_PAD_1061"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .no_edge_events_on_boot = true,
+ },
+ },
+ {
+ /*
+ * The Dell Venue 10 Pro 5055, with Bay Trail SoC + TI PMIC uses an
+ * external embedded-controller connected via I2C + an ACPI GPIO
+ * event handler on INT33FFC:02 pin 12, causing spurious wakeups.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Venue 10 Pro 5055"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_wake = "INT33FC:02@12",
+ },
+ },
+ {
+ /*
+ * HP X2 10 models with Cherry Trail SoC + TI PMIC use an
+ * external embedded-controller connected via I2C + an ACPI GPIO
+ * event handler on INT33FF:01 pin 0, causing spurious wakeups.
+ * When suspending by closing the LID, the power to the USB
+ * keyboard is turned off, causing INT0002 ACPI events to
+ * trigger once the XHCI controller notices the keyboard is
+ * gone. So INT0002 events cause spurious wakeups too. Ignoring
+ * EC wakes breaks wakeup when opening the lid, the user needs
+ * to press the power-button to wakeup the system. The
+ * alternative is suspend simply not working, which is worse.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_wake = "INT33FF:01@0,INT0002:00@2",
+ },
+ },
+ {
+ /*
+ * HP X2 10 models with Bay Trail SoC + AXP288 PMIC use an
+ * external embedded-controller connected via I2C + an ACPI GPIO
+ * event handler on INT33FC:02 pin 28, causing spurious wakeups.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
+ DMI_MATCH(DMI_BOARD_NAME, "815D"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_wake = "INT33FC:02@28",
+ },
+ },
+ {
+ /*
+ * HP X2 10 models with Cherry Trail SoC + AXP288 PMIC use an
+ * external embedded-controller connected via I2C + an ACPI GPIO
+ * event handler on INT33FF:01 pin 0, causing spurious wakeups.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
+ DMI_MATCH(DMI_BOARD_NAME, "813E"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_wake = "INT33FF:01@0",
+ },
+ },
+ {
+ /*
+ * Interrupt storm caused from edge triggered floating pin
+ * Found in BIOS UX325UAZ.300
+ * https://bugzilla.kernel.org/show_bug.cgi?id=216208
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UAZ_UM325UAZ"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_interrupt = "AMDI0030:00@18",
+ },
+ },
+ {
+ /*
+ * Spurious wakeups from TP_ATTN# pin
+ * Found in BIOS 1.7.8
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/1722#note_1720627
+ */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_wake = "ELAN0415:00@9",
+ },
+ },
+ {
+ /*
+ * Spurious wakeups from TP_ATTN# pin
+ * Found in BIOS 1.7.8
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/1722#note_1720627
+ */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_wake = "ELAN0415:00@9",
+ },
+ },
+ {
+ /*
+ * Spurious wakeups from TP_ATTN# pin
+ * Found in BIOS 1.7.7
+ */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "NH5xAx"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_wake = "SYNA1202:00@16",
+ },
+ },
+ {
+ /*
+ * On the Peaq C1010 2-in-1 INT33FC:00 pin 3 is connected to
+ * a "dolby" button. At the ACPI level an _AEI event-handler
+ * is connected which sets an ACPI variable to 1 on both
+ * edges. This variable can be polled + cleared to 0 using
+ * WMI. But since the variable is set on both edges the WMI
+ * interface is pretty useless even when polling.
+ * So instead the x86-android-tablets code instantiates
+ * a gpio-keys platform device for it.
+ * Ignore the _AEI handler for the pin, so that it is not busy.
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PEAQ PMM C1010 MD99187"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_interrupt = "INT33FC:00@3",
+ },
+ },
+ {
+ /*
+ * Spurious wakeups from TP_ATTN# pin
+ * Found in BIOS 0.35
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/3073
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GPD"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "G1619-04"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_wake = "PNP0C50:00@8",
+ },
+ },
+ {
+ /*
+ * Spurious wakeups from GPIO 11
+ * Found in BIOS 1.04
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/3954
+ */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
+ DMI_MATCH(DMI_PRODUCT_FAMILY, "Acer Nitro V 14"),
+ },
+ .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
+ .ignore_interrupt = "AMDI0030:00@11",
+ },
+ },
+ {} /* Terminating entry */
+};
+
+static int __init acpi_gpio_setup_params(void)
+{
+ const struct acpi_gpiolib_dmi_quirk *quirk = NULL;
+ const struct dmi_system_id *id;
+
+ id = dmi_first_match(gpiolib_acpi_quirks);
+ if (id)
+ quirk = id->driver_data;
+
+ if (run_edge_events_on_boot < 0) {
+ if (quirk && quirk->no_edge_events_on_boot)
+ run_edge_events_on_boot = 0;
+ else
+ run_edge_events_on_boot = 1;
+ }
+
+ if (ignore_wake == NULL && quirk && quirk->ignore_wake)
+ ignore_wake = quirk->ignore_wake;
+
+ if (ignore_interrupt == NULL && quirk && quirk->ignore_interrupt)
+ ignore_interrupt = quirk->ignore_interrupt;
+
+ return 0;
+}
+
+/* Directly after dmi_setup() which runs as core_initcall() */
+postcore_initcall(acpi_gpio_setup_params);
--- a/drivers/gpio/gpiolib-acpi.c
+++ /dev/null
@@ -1,1765 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * ACPI helpers for GPIO API
- *
- * Copyright (C) 2012, Intel Corporation
- * Authors: Mathias Nyman <mathias.nyman@linux.intel.com>
- * Mika Westerberg <mika.westerberg@linux.intel.com>
- */
-
-#include <linux/acpi.h>
-#include <linux/dmi.h>
-#include <linux/errno.h>
-#include <linux/export.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/mutex.h>
-#include <linux/pinctrl/pinctrl.h>
-
-#include <linux/gpio/consumer.h>
-#include <linux/gpio/driver.h>
-#include <linux/gpio/machine.h>
-
-#include "gpiolib.h"
-#include "gpiolib-acpi.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");
-
-static char *ignore_wake;
-module_param(ignore_wake, charp, 0444);
-MODULE_PARM_DESC(ignore_wake,
- "controller@pin combos on which to ignore the ACPI wake flag "
- "ignore_wake=controller@pin[,controller@pin[,...]]");
-
-static char *ignore_interrupt;
-module_param(ignore_interrupt, charp, 0444);
-MODULE_PARM_DESC(ignore_interrupt,
- "controller@pin combos on which to ignore interrupt "
- "ignore_interrupt=controller@pin[,controller@pin[,...]]");
-
-struct acpi_gpiolib_dmi_quirk {
- bool no_edge_events_on_boot;
- char *ignore_wake;
- char *ignore_interrupt;
-};
-
-/**
- * struct acpi_gpio_event - ACPI GPIO event handler data
- *
- * @node: list-entry of the events list of the struct acpi_gpio_chip
- * @handle: handle of ACPI method to execute when the IRQ triggers
- * @handler: handler function to pass to request_irq() when requesting the IRQ
- * @pin: GPIO pin number on the struct gpio_chip
- * @irq: Linux IRQ number for the event, for request_irq() / free_irq()
- * @irqflags: flags to pass to request_irq() when requesting the IRQ
- * @irq_is_wake: If the ACPI flags indicate the IRQ is a wakeup source
- * @irq_requested:True if request_irq() has been done
- * @desc: struct gpio_desc for the GPIO pin for this event
- */
-struct acpi_gpio_event {
- struct list_head node;
- acpi_handle handle;
- irq_handler_t handler;
- unsigned int pin;
- unsigned int irq;
- unsigned long irqflags;
- bool irq_is_wake;
- bool irq_requested;
- struct gpio_desc *desc;
-};
-
-struct acpi_gpio_connection {
- struct list_head node;
- unsigned int pin;
- struct gpio_desc *desc;
-};
-
-struct acpi_gpio_chip {
- /*
- * ACPICA requires that the first field of the context parameter
- * passed to acpi_install_address_space_handler() is large enough
- * to hold struct acpi_connection_info.
- */
- struct acpi_connection_info conn_info;
- struct list_head conns;
- struct mutex conn_lock;
- struct gpio_chip *chip;
- struct list_head events;
- struct list_head deferred_req_irqs_list_entry;
-};
-
-/**
- * struct acpi_gpio_info - ACPI GPIO specific information
- * @adev: reference to ACPI device which consumes GPIO resource
- * @flags: GPIO initialization flags
- * @gpioint: if %true this GPIO is of type GpioInt otherwise type is GpioIo
- * @pin_config: pin bias as provided by ACPI
- * @polarity: interrupt polarity as provided by ACPI
- * @triggering: triggering type as provided by ACPI
- * @wake_capable: wake capability as provided by ACPI
- * @debounce: debounce timeout as provided by ACPI
- * @quirks: Linux specific quirks as provided by struct acpi_gpio_mapping
- */
-struct acpi_gpio_info {
- struct acpi_device *adev;
- enum gpiod_flags flags;
- bool gpioint;
- int pin_config;
- int polarity;
- int triggering;
- bool wake_capable;
- unsigned int debounce;
- unsigned int quirks;
-};
-
-/*
- * For GPIO chips which call acpi_gpiochip_request_interrupts() before late_init
- * (so builtin drivers) we register the ACPI GpioInt IRQ handlers from a
- * late_initcall_sync() handler, so that other builtin drivers can register their
- * OpRegions before the event handlers can run. This list contains GPIO chips
- * for which the acpi_gpiochip_request_irqs() call has been deferred.
- */
-static DEFINE_MUTEX(acpi_gpio_deferred_req_irqs_lock);
-static LIST_HEAD(acpi_gpio_deferred_req_irqs_list);
-static bool acpi_gpio_deferred_req_irqs_done;
-
-static int acpi_gpiochip_find(struct gpio_chip *gc, const void *data)
-{
- /* First check the actual GPIO device */
- if (device_match_acpi_handle(&gc->gpiodev->dev, data))
- return true;
-
- /*
- * When the ACPI device is artificially split to the banks of GPIOs,
- * where each of them is represented by a separate GPIO device,
- * the firmware node of the physical device may not be shared among
- * the banks as they may require different values for the same property,
- * e.g., number of GPIOs in a certain bank. In such case the ACPI handle
- * of a GPIO device is NULL and can not be used. Hence we have to check
- * the parent device to be sure that there is no match before bailing
- * out.
- */
- if (gc->parent)
- return device_match_acpi_handle(gc->parent, data);
-
- return false;
-}
-
-/**
- * acpi_get_gpiod() - Translate ACPI GPIO pin to GPIO descriptor usable with GPIO API
- * @path: ACPI GPIO controller full path name, (e.g. "\\_SB.GPO1")
- * @pin: ACPI GPIO pin number (0-based, controller-relative)
- *
- * Returns:
- * GPIO descriptor to use with Linux generic GPIO API.
- * If the GPIO cannot be translated or there is an error an ERR_PTR is
- * returned.
- *
- * Specifically returns %-EPROBE_DEFER if the referenced GPIO
- * controller does not have GPIO chip registered at the moment. This is to
- * support probe deferral.
- */
-static struct gpio_desc *acpi_get_gpiod(char *path, unsigned int pin)
-{
- acpi_handle handle;
- acpi_status status;
-
- status = acpi_get_handle(NULL, path, &handle);
- if (ACPI_FAILURE(status))
- return ERR_PTR(-ENODEV);
-
- struct gpio_device *gdev __free(gpio_device_put) =
- gpio_device_find(handle, acpi_gpiochip_find);
- if (!gdev)
- return ERR_PTR(-EPROBE_DEFER);
-
- /*
- * FIXME: keep track of the reference to the GPIO device somehow
- * instead of putting it here.
- */
- return gpio_device_get_desc(gdev, pin);
-}
-
-static irqreturn_t acpi_gpio_irq_handler(int irq, void *data)
-{
- struct acpi_gpio_event *event = data;
-
- acpi_evaluate_object(event->handle, NULL, NULL, NULL);
-
- return IRQ_HANDLED;
-}
-
-static irqreturn_t acpi_gpio_irq_handler_evt(int irq, void *data)
-{
- struct acpi_gpio_event *event = data;
-
- acpi_execute_simple_method(event->handle, NULL, event->pin);
-
- return IRQ_HANDLED;
-}
-
-static void acpi_gpio_chip_dh(acpi_handle handle, void *data)
-{
- /* The address of this function is used as a key. */
-}
-
-bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
- struct acpi_resource_gpio **agpio)
-{
- struct acpi_resource_gpio *gpio;
-
- if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
- return false;
-
- gpio = &ares->data.gpio;
- if (gpio->connection_type != ACPI_RESOURCE_GPIO_TYPE_INT)
- return false;
-
- *agpio = gpio;
- return true;
-}
-EXPORT_SYMBOL_GPL(acpi_gpio_get_irq_resource);
-
-/**
- * acpi_gpio_get_io_resource - Fetch details of an ACPI resource if it is a GPIO
- * I/O resource or return False if not.
- * @ares: Pointer to the ACPI resource to fetch
- * @agpio: Pointer to a &struct acpi_resource_gpio to store the output pointer
- *
- * Returns:
- * %true if GpioIo resource is found, %false otherwise.
- */
-bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
- struct acpi_resource_gpio **agpio)
-{
- struct acpi_resource_gpio *gpio;
-
- if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
- return false;
-
- gpio = &ares->data.gpio;
- if (gpio->connection_type != ACPI_RESOURCE_GPIO_TYPE_IO)
- return false;
-
- *agpio = gpio;
- return true;
-}
-EXPORT_SYMBOL_GPL(acpi_gpio_get_io_resource);
-
-static void acpi_gpiochip_request_irq(struct acpi_gpio_chip *acpi_gpio,
- struct acpi_gpio_event *event)
-{
- struct device *parent = acpi_gpio->chip->parent;
- int ret, value;
-
- ret = request_threaded_irq(event->irq, NULL, event->handler,
- event->irqflags | IRQF_ONESHOT, "ACPI:Event", event);
- if (ret) {
- dev_err(parent, "Failed to setup interrupt handler for %d\n", event->irq);
- return;
- }
-
- if (event->irq_is_wake)
- enable_irq_wake(event->irq);
-
- event->irq_requested = true;
-
- /* Make sure we trigger the initial state of edge-triggered IRQs */
- if (acpi_gpio_need_run_edge_events_on_boot() &&
- (event->irqflags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))) {
- value = gpiod_get_raw_value_cansleep(event->desc);
- if (((event->irqflags & IRQF_TRIGGER_RISING) && value == 1) ||
- ((event->irqflags & IRQF_TRIGGER_FALLING) && value == 0))
- event->handler(event->irq, event);
- }
-}
-
-static void acpi_gpiochip_request_irqs(struct acpi_gpio_chip *acpi_gpio)
-{
- struct acpi_gpio_event *event;
-
- list_for_each_entry(event, &acpi_gpio->events, node)
- acpi_gpiochip_request_irq(acpi_gpio, event);
-}
-
-static enum gpiod_flags
-acpi_gpio_to_gpiod_flags(const struct acpi_resource_gpio *agpio, int polarity)
-{
- /* GpioInt() implies input configuration */
- if (agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT)
- return GPIOD_IN;
-
- switch (agpio->io_restriction) {
- case ACPI_IO_RESTRICT_INPUT:
- return GPIOD_IN;
- case ACPI_IO_RESTRICT_OUTPUT:
- /*
- * ACPI GPIO resources don't contain an initial value for the
- * GPIO. Therefore we deduce that value from the pull field
- * and the polarity instead. If the pin is pulled up we assume
- * default to be high, if it is pulled down we assume default
- * to be low, otherwise we leave pin untouched. For active low
- * polarity values will be switched. See also
- * Documentation/firmware-guide/acpi/gpio-properties.rst.
- */
- switch (agpio->pin_config) {
- case ACPI_PIN_CONFIG_PULLUP:
- return polarity == GPIO_ACTIVE_LOW ? GPIOD_OUT_LOW : GPIOD_OUT_HIGH;
- case ACPI_PIN_CONFIG_PULLDOWN:
- return polarity == GPIO_ACTIVE_LOW ? GPIOD_OUT_HIGH : GPIOD_OUT_LOW;
- default:
- break;
- }
- break;
- default:
- break;
- }
-
- /*
- * Assume that the BIOS has configured the direction and pull
- * accordingly.
- */
- return GPIOD_ASIS;
-}
-
-static struct gpio_desc *acpi_request_own_gpiod(struct gpio_chip *chip,
- struct acpi_resource_gpio *agpio,
- unsigned int index,
- const char *label)
-{
- int polarity = GPIO_ACTIVE_HIGH;
- enum gpiod_flags flags = acpi_gpio_to_gpiod_flags(agpio, polarity);
- unsigned int pin = agpio->pin_table[index];
- struct gpio_desc *desc;
- int ret;
-
- desc = gpiochip_request_own_desc(chip, pin, label, polarity, flags);
- if (IS_ERR(desc))
- return desc;
-
- /* ACPI uses hundredths of milliseconds units */
- ret = gpio_set_debounce_timeout(desc, agpio->debounce_timeout * 10);
- if (ret)
- dev_warn(chip->parent,
- "Failed to set debounce-timeout for pin 0x%04X, err %d\n",
- pin, ret);
-
- return desc;
-}
-
-bool acpi_gpio_add_to_deferred_list(struct list_head *list)
-{
- bool defer;
-
- mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
- defer = !acpi_gpio_deferred_req_irqs_done;
- if (defer)
- list_add(list, &acpi_gpio_deferred_req_irqs_list);
- mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
-
- return defer;
-}
-
-void acpi_gpio_remove_from_deferred_list(struct list_head *list)
-{
- mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
- if (!list_empty(list))
- list_del_init(list);
- mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
-}
-
-int acpi_gpio_need_run_edge_events_on_boot(void)
-{
- return run_edge_events_on_boot;
-}
-
-bool acpi_gpio_in_ignore_list(enum acpi_gpio_ignore_list list, const char *controller_in,
- unsigned int pin_in)
-{
- const char *ignore_list, *controller, *pin_str;
- unsigned int pin;
- char *endp;
- int len;
-
- switch (list) {
- case ACPI_GPIO_IGNORE_WAKE:
- ignore_list = ignore_wake;
- break;
- case ACPI_GPIO_IGNORE_INTERRUPT:
- ignore_list = ignore_interrupt;
- break;
- default:
- return false;
- }
-
- controller = ignore_list;
- while (controller) {
- pin_str = strchr(controller, '@');
- if (!pin_str)
- goto err;
-
- len = pin_str - controller;
- if (len == strlen(controller_in) &&
- strncmp(controller, controller_in, len) == 0) {
- pin = simple_strtoul(pin_str + 1, &endp, 10);
- if (*endp != 0 && *endp != ',')
- goto err;
-
- if (pin == pin_in)
- return true;
- }
-
- controller = strchr(controller, ',');
- if (controller)
- controller++;
- }
-
- return false;
-err:
- pr_err_once("Error: Invalid value for gpiolib_acpi.ignore_...: %s\n", ignore_list);
- return false;
-}
-
-static bool acpi_gpio_irq_is_wake(struct device *parent,
- const struct acpi_resource_gpio *agpio)
-{
- unsigned int pin = agpio->pin_table[0];
-
- if (agpio->wake_capable != ACPI_WAKE_CAPABLE)
- return false;
-
- if (acpi_gpio_in_ignore_list(ACPI_GPIO_IGNORE_WAKE, dev_name(parent), pin)) {
- dev_info(parent, "Ignoring wakeup on pin %u\n", pin);
- return false;
- }
-
- return true;
-}
-
-/* Always returns AE_OK so that we keep looping over the resources */
-static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
- void *context)
-{
- struct acpi_gpio_chip *acpi_gpio = context;
- struct gpio_chip *chip = acpi_gpio->chip;
- struct acpi_resource_gpio *agpio;
- acpi_handle handle, evt_handle;
- struct acpi_gpio_event *event;
- irq_handler_t handler = NULL;
- struct gpio_desc *desc;
- unsigned int pin;
- int ret, irq;
-
- if (!acpi_gpio_get_irq_resource(ares, &agpio))
- return AE_OK;
-
- handle = ACPI_HANDLE(chip->parent);
- pin = agpio->pin_table[0];
-
- if (pin <= 255) {
- char ev_name[8];
- sprintf(ev_name, "_%c%02X",
- agpio->triggering == ACPI_EDGE_SENSITIVE ? 'E' : 'L',
- pin);
- if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle)))
- handler = acpi_gpio_irq_handler;
- }
- if (!handler) {
- if (ACPI_SUCCESS(acpi_get_handle(handle, "_EVT", &evt_handle)))
- handler = acpi_gpio_irq_handler_evt;
- }
- if (!handler)
- return AE_OK;
-
- if (acpi_gpio_in_ignore_list(ACPI_GPIO_IGNORE_INTERRUPT, dev_name(chip->parent), pin)) {
- dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin);
- return AE_OK;
- }
-
- desc = acpi_request_own_gpiod(chip, agpio, 0, "ACPI:Event");
- if (IS_ERR(desc)) {
- dev_err(chip->parent,
- "Failed to request GPIO for pin 0x%04X, err %ld\n",
- pin, PTR_ERR(desc));
- return AE_OK;
- }
-
- ret = gpiochip_lock_as_irq(chip, pin);
- if (ret) {
- dev_err(chip->parent,
- "Failed to lock GPIO pin 0x%04X as interrupt, err %d\n",
- pin, ret);
- goto fail_free_desc;
- }
-
- irq = gpiod_to_irq(desc);
- if (irq < 0) {
- dev_err(chip->parent,
- "Failed to translate GPIO pin 0x%04X to IRQ, err %d\n",
- pin, irq);
- goto fail_unlock_irq;
- }
-
- event = kzalloc(sizeof(*event), GFP_KERNEL);
- if (!event)
- goto fail_unlock_irq;
-
- event->irqflags = IRQF_ONESHOT;
- if (agpio->triggering == ACPI_LEVEL_SENSITIVE) {
- if (agpio->polarity == ACPI_ACTIVE_HIGH)
- event->irqflags |= IRQF_TRIGGER_HIGH;
- else
- event->irqflags |= IRQF_TRIGGER_LOW;
- } else {
- switch (agpio->polarity) {
- case ACPI_ACTIVE_HIGH:
- event->irqflags |= IRQF_TRIGGER_RISING;
- break;
- case ACPI_ACTIVE_LOW:
- event->irqflags |= IRQF_TRIGGER_FALLING;
- break;
- default:
- event->irqflags |= IRQF_TRIGGER_RISING |
- IRQF_TRIGGER_FALLING;
- break;
- }
- }
-
- event->handle = evt_handle;
- event->handler = handler;
- event->irq = irq;
- event->irq_is_wake = acpi_gpio_irq_is_wake(chip->parent, agpio);
- event->pin = pin;
- event->desc = desc;
-
- list_add_tail(&event->node, &acpi_gpio->events);
-
- return AE_OK;
-
-fail_unlock_irq:
- gpiochip_unlock_as_irq(chip, pin);
-fail_free_desc:
- gpiochip_free_own_desc(desc);
-
- return AE_OK;
-}
-
-/**
- * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events
- * @chip: GPIO chip
- *
- * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
- * handled by ACPI event methods which need to be called from the GPIO
- * chip's interrupt handler. acpi_gpiochip_request_interrupts() finds out which
- * GPIO pins have ACPI event methods and assigns interrupt handlers that calls
- * the ACPI event methods for those pins.
- */
-void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
-{
- struct acpi_gpio_chip *acpi_gpio;
- acpi_handle handle;
- acpi_status status;
-
- if (!chip->parent || !chip->to_irq)
- return;
-
- handle = ACPI_HANDLE(chip->parent);
- if (!handle)
- return;
-
- status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
- if (ACPI_FAILURE(status))
- return;
-
- if (acpi_quirk_skip_gpio_event_handlers())
- return;
-
- acpi_walk_resources(handle, METHOD_NAME__AEI,
- acpi_gpiochip_alloc_event, acpi_gpio);
-
- if (acpi_gpio_add_to_deferred_list(&acpi_gpio->deferred_req_irqs_list_entry))
- return;
-
- acpi_gpiochip_request_irqs(acpi_gpio);
-}
-EXPORT_SYMBOL_GPL(acpi_gpiochip_request_interrupts);
-
-/**
- * acpi_gpiochip_free_interrupts() - Free GPIO ACPI event interrupts.
- * @chip: GPIO chip
- *
- * Free interrupts associated with GPIO ACPI event method for the given
- * GPIO chip.
- */
-void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
-{
- struct acpi_gpio_chip *acpi_gpio;
- struct acpi_gpio_event *event, *ep;
- acpi_handle handle;
- acpi_status status;
-
- if (!chip->parent || !chip->to_irq)
- return;
-
- handle = ACPI_HANDLE(chip->parent);
- if (!handle)
- return;
-
- status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
- if (ACPI_FAILURE(status))
- return;
-
- acpi_gpio_remove_from_deferred_list(&acpi_gpio->deferred_req_irqs_list_entry);
-
- list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
- if (event->irq_requested) {
- if (event->irq_is_wake)
- disable_irq_wake(event->irq);
-
- free_irq(event->irq, event);
- }
-
- gpiochip_unlock_as_irq(chip, event->pin);
- gpiochip_free_own_desc(event->desc);
- list_del(&event->node);
- kfree(event);
- }
-}
-EXPORT_SYMBOL_GPL(acpi_gpiochip_free_interrupts);
-
-void __init acpi_gpio_process_deferred_list(struct list_head *list)
-{
- struct acpi_gpio_chip *acpi_gpio, *tmp;
-
- list_for_each_entry_safe(acpi_gpio, tmp, list, deferred_req_irqs_list_entry)
- acpi_gpiochip_request_irqs(acpi_gpio);
-}
-
-int acpi_dev_add_driver_gpios(struct acpi_device *adev,
- const struct acpi_gpio_mapping *gpios)
-{
- if (adev && gpios) {
- adev->driver_gpios = gpios;
- return 0;
- }
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(acpi_dev_add_driver_gpios);
-
-void acpi_dev_remove_driver_gpios(struct acpi_device *adev)
-{
- if (adev)
- adev->driver_gpios = NULL;
-}
-EXPORT_SYMBOL_GPL(acpi_dev_remove_driver_gpios);
-
-static void acpi_dev_release_driver_gpios(void *adev)
-{
- acpi_dev_remove_driver_gpios(adev);
-}
-
-int devm_acpi_dev_add_driver_gpios(struct device *dev,
- const struct acpi_gpio_mapping *gpios)
-{
- struct acpi_device *adev = ACPI_COMPANION(dev);
- int ret;
-
- ret = acpi_dev_add_driver_gpios(adev, gpios);
- if (ret)
- return ret;
-
- return devm_add_action_or_reset(dev, acpi_dev_release_driver_gpios, adev);
-}
-EXPORT_SYMBOL_GPL(devm_acpi_dev_add_driver_gpios);
-
-static bool acpi_get_driver_gpio_data(struct acpi_device *adev,
- const char *name, int index,
- struct fwnode_reference_args *args,
- unsigned int *quirks)
-{
- const struct acpi_gpio_mapping *gm;
-
- if (!adev || !adev->driver_gpios)
- return false;
-
- for (gm = adev->driver_gpios; gm->name; gm++)
- if (!strcmp(name, gm->name) && gm->data && index < gm->size) {
- const struct acpi_gpio_params *par = gm->data + index;
-
- args->fwnode = acpi_fwnode_handle(adev);
- args->args[0] = par->crs_entry_index;
- args->args[1] = par->line_index;
- args->args[2] = par->active_low;
- args->nargs = 3;
-
- *quirks = gm->quirks;
- return true;
- }
-
- return false;
-}
-
-static int
-__acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags, enum gpiod_flags update)
-{
- const enum gpiod_flags mask =
- GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT |
- GPIOD_FLAGS_BIT_DIR_VAL;
- int ret = 0;
-
- /*
- * Check if the BIOS has IoRestriction with explicitly set direction
- * and update @flags accordingly. Otherwise use whatever caller asked
- * for.
- */
- if (update & GPIOD_FLAGS_BIT_DIR_SET) {
- enum gpiod_flags diff = *flags ^ update;
-
- /*
- * Check if caller supplied incompatible GPIO initialization
- * flags.
- *
- * Return %-EINVAL to notify that firmware has different
- * settings and we are going to use them.
- */
- if (((*flags & GPIOD_FLAGS_BIT_DIR_SET) && (diff & GPIOD_FLAGS_BIT_DIR_OUT)) ||
- ((*flags & GPIOD_FLAGS_BIT_DIR_OUT) && (diff & GPIOD_FLAGS_BIT_DIR_VAL)))
- ret = -EINVAL;
- *flags = (*flags & ~mask) | (update & mask);
- }
- return ret;
-}
-
-static int acpi_gpio_update_gpiod_flags(enum gpiod_flags *flags,
- struct acpi_gpio_info *info)
-{
- struct device *dev = &info->adev->dev;
- enum gpiod_flags old = *flags;
- int ret;
-
- ret = __acpi_gpio_update_gpiod_flags(&old, info->flags);
- if (info->quirks & ACPI_GPIO_QUIRK_NO_IO_RESTRICTION) {
- if (ret)
- dev_warn(dev, FW_BUG "GPIO not in correct mode, fixing\n");
- } else {
- if (ret)
- dev_dbg(dev, "Override GPIO initialization flags\n");
- *flags = old;
- }
-
- return ret;
-}
-
-static int acpi_gpio_update_gpiod_lookup_flags(unsigned long *lookupflags,
- struct acpi_gpio_info *info)
-{
- switch (info->pin_config) {
- case ACPI_PIN_CONFIG_PULLUP:
- *lookupflags |= GPIO_PULL_UP;
- break;
- case ACPI_PIN_CONFIG_PULLDOWN:
- *lookupflags |= GPIO_PULL_DOWN;
- break;
- case ACPI_PIN_CONFIG_NOPULL:
- *lookupflags |= GPIO_PULL_DISABLE;
- break;
- default:
- break;
- }
-
- if (info->polarity == GPIO_ACTIVE_LOW)
- *lookupflags |= GPIO_ACTIVE_LOW;
-
- return 0;
-}
-
-struct acpi_gpio_lookup {
- struct acpi_gpio_info info;
- int index;
- u16 pin_index;
- bool active_low;
- struct gpio_desc *desc;
- int n;
-};
-
-static int acpi_populate_gpio_lookup(struct acpi_resource *ares, void *data)
-{
- struct acpi_gpio_lookup *lookup = data;
-
- if (ares->type != ACPI_RESOURCE_TYPE_GPIO)
- return 1;
-
- 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)
- lookup->index++;
-
- if (lookup->n++ != lookup->index)
- return 1;
-
- pin_index = lookup->pin_index;
- if (pin_index >= agpio->pin_table_length)
- return 1;
-
- 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;
- lookup->info.wake_capable = acpi_gpio_irq_is_wake(&lookup->info.adev->dev, agpio);
-
- /*
- * Polarity and triggering are only specified for GpioInt
- * resource.
- * Note: we expect here:
- * - ACPI_ACTIVE_LOW == GPIO_ACTIVE_LOW
- * - ACPI_ACTIVE_HIGH == GPIO_ACTIVE_HIGH
- */
- if (lookup->info.gpioint) {
- lookup->info.polarity = agpio->polarity;
- lookup->info.triggering = agpio->triggering;
- } else {
- lookup->info.polarity = lookup->active_low;
- }
-
- lookup->info.flags = acpi_gpio_to_gpiod_flags(agpio, lookup->info.polarity);
- }
-
- return 1;
-}
-
-static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup,
- struct acpi_gpio_info *info)
-{
- struct acpi_device *adev = lookup->info.adev;
- struct list_head res_list;
- int ret;
-
- INIT_LIST_HEAD(&res_list);
-
- ret = acpi_dev_get_resources(adev, &res_list,
- acpi_populate_gpio_lookup,
- lookup);
- if (ret < 0)
- return ret;
-
- acpi_dev_free_resource_list(&res_list);
-
- if (!lookup->desc)
- return -ENOENT;
-
- if (info)
- *info = lookup->info;
- return 0;
-}
-
-static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
- const char *propname, int index,
- struct acpi_gpio_lookup *lookup)
-{
- struct fwnode_reference_args args;
- unsigned int quirks = 0;
- int ret;
-
- memset(&args, 0, sizeof(args));
- ret = __acpi_node_get_property_reference(fwnode, propname, index, 3,
- &args);
- if (ret) {
- struct acpi_device *adev;
-
- adev = to_acpi_device_node(fwnode);
- if (!acpi_get_driver_gpio_data(adev, propname, index, &args, &quirks))
- return ret;
- }
- /*
- * The property was found and resolved, so need to lookup the GPIO based
- * on returned args.
- */
- if (!to_acpi_device_node(args.fwnode))
- return -EINVAL;
- if (args.nargs != 3)
- return -EPROTO;
-
- lookup->index = args.args[0];
- lookup->pin_index = args.args[1];
- lookup->active_low = !!args.args[2];
-
- lookup->info.adev = to_acpi_device_node(args.fwnode);
- lookup->info.quirks = quirks;
-
- return 0;
-}
-
-/**
- * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
- * @adev: pointer to a ACPI device to get GPIO from
- * @propname: Property name of the GPIO (optional)
- * @index: index of GpioIo/GpioInt resource (starting from %0)
- * @info: info pointer to fill in (optional)
- *
- * Function goes through ACPI resources for @adev and based on @index looks
- * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor,
- * and returns it. @index matches GpioIo/GpioInt resources only so if there
- * are total %3 GPIO resources, the index goes from %0 to %2.
- *
- * If @propname is specified the GPIO is looked using device property. In
- * that case @index is used to select the GPIO entry in the property value
- * (in case of multiple).
- *
- * Returns:
- * GPIO descriptor to use with Linux generic GPIO API.
- * If the GPIO cannot be translated or there is an error an ERR_PTR is
- * returned.
- *
- * Note: if the GPIO resource has multiple entries in the pin list, this
- * function only returns the first.
- */
-static struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
- const char *propname,
- int index,
- struct acpi_gpio_info *info)
-{
- struct acpi_gpio_lookup lookup;
- int ret;
-
- memset(&lookup, 0, sizeof(lookup));
- lookup.index = index;
-
- if (propname) {
- dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname);
-
- ret = acpi_gpio_property_lookup(acpi_fwnode_handle(adev),
- propname, index, &lookup);
- if (ret)
- return ERR_PTR(ret);
-
- dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %u %u\n",
- dev_name(&lookup.info.adev->dev), lookup.index,
- lookup.pin_index, lookup.active_low);
- } else {
- dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index);
- lookup.info.adev = adev;
- }
-
- ret = acpi_gpio_resource_lookup(&lookup, info);
- return ret ? ERR_PTR(ret) : lookup.desc;
-}
-
-/**
- * acpi_get_gpiod_from_data() - get a GPIO descriptor from ACPI data node
- * @fwnode: pointer to an ACPI firmware node to get the GPIO information from
- * @propname: Property name of the GPIO
- * @index: index of GpioIo/GpioInt resource (starting from %0)
- * @info: info pointer to fill in (optional)
- *
- * This function uses the property-based GPIO lookup to get to the GPIO
- * resource with the relevant information from a data-only ACPI firmware node
- * and uses that to obtain the GPIO descriptor to return.
- *
- * Returns:
- * GPIO descriptor to use with Linux generic GPIO API.
- * If the GPIO cannot be translated or there is an error an ERR_PTR is
- * returned.
- */
-static struct gpio_desc *acpi_get_gpiod_from_data(struct fwnode_handle *fwnode,
- const char *propname,
- int index,
- struct acpi_gpio_info *info)
-{
- struct acpi_gpio_lookup lookup;
- int ret;
-
- if (!is_acpi_data_node(fwnode))
- return ERR_PTR(-ENODEV);
-
- if (!propname)
- return ERR_PTR(-EINVAL);
-
- memset(&lookup, 0, sizeof(lookup));
- lookup.index = index;
-
- ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup);
- if (ret)
- return ERR_PTR(ret);
-
- ret = acpi_gpio_resource_lookup(&lookup, info);
- return ret ? ERR_PTR(ret) : lookup.desc;
-}
-
-static bool acpi_can_fallback_to_crs(struct acpi_device *adev,
- const char *con_id)
-{
- /* If there is no ACPI device, there is no _CRS to fall back to */
- if (!adev)
- return false;
-
- /* Never allow fallback if the device has properties */
- if (acpi_dev_has_props(adev) || adev->driver_gpios)
- return false;
-
- return con_id == NULL;
-}
-
-static struct gpio_desc *
-__acpi_find_gpio(struct fwnode_handle *fwnode, const char *con_id, unsigned int idx,
- bool can_fallback, struct acpi_gpio_info *info)
-{
- struct acpi_device *adev = to_acpi_device_node(fwnode);
- struct gpio_desc *desc;
- char propname[32];
-
- /* Try first from _DSD */
- for_each_gpio_property_name(propname, con_id) {
- if (adev)
- desc = acpi_get_gpiod_by_index(adev,
- propname, idx, info);
- else
- desc = acpi_get_gpiod_from_data(fwnode,
- propname, idx, info);
- if (PTR_ERR(desc) == -EPROBE_DEFER)
- return ERR_CAST(desc);
-
- if (!IS_ERR(desc))
- return desc;
- }
-
- /* Then from plain _CRS GPIOs */
- if (can_fallback)
- return acpi_get_gpiod_by_index(adev, NULL, idx, info);
-
- return ERR_PTR(-ENOENT);
-}
-
-struct gpio_desc *acpi_find_gpio(struct fwnode_handle *fwnode,
- const char *con_id,
- unsigned int idx,
- enum gpiod_flags *dflags,
- unsigned long *lookupflags)
-{
- struct acpi_device *adev = to_acpi_device_node(fwnode);
- bool can_fallback = acpi_can_fallback_to_crs(adev, con_id);
- struct acpi_gpio_info info;
- struct gpio_desc *desc;
-
- desc = __acpi_find_gpio(fwnode, con_id, idx, can_fallback, &info);
- if (IS_ERR(desc))
- return desc;
-
- if (info.gpioint &&
- (*dflags == GPIOD_OUT_LOW || *dflags == GPIOD_OUT_HIGH)) {
- dev_dbg(&adev->dev, "refusing GpioInt() entry when doing GPIOD_OUT_* lookup\n");
- return ERR_PTR(-ENOENT);
- }
-
- acpi_gpio_update_gpiod_flags(dflags, &info);
- acpi_gpio_update_gpiod_lookup_flags(lookupflags, &info);
- return desc;
-}
-
-/**
- * acpi_dev_gpio_irq_wake_get_by() - Find GpioInt and translate it to Linux IRQ number
- * @adev: pointer to a ACPI device to get IRQ from
- * @con_id: optional name of GpioInt resource
- * @index: index of GpioInt resource (starting from %0)
- * @wake_capable: Set to true if the IRQ is wake capable
- *
- * If the device has one or more GpioInt resources, this function can be
- * used to translate from the GPIO offset in the resource to the Linux IRQ
- * number.
- *
- * 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 @con_id parameter. If the resource has
- * a @con_id in a property, then only those will be taken into account.
- *
- * The GPIO is considered wake capable if the GpioInt resource specifies
- * SharedAndWake or ExclusiveAndWake.
- *
- * Returns:
- * Linux IRQ number (> 0) on success, negative errno on failure.
- */
-int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *con_id, int index,
- bool *wake_capable)
-{
- struct fwnode_handle *fwnode = acpi_fwnode_handle(adev);
- int idx, i;
- unsigned int irq_flags;
- int ret;
-
- for (i = 0, idx = 0; idx <= index; i++) {
- struct acpi_gpio_info info;
- struct gpio_desc *desc;
-
- /* Ignore -EPROBE_DEFER, it only matters if idx matches */
- desc = __acpi_find_gpio(fwnode, con_id, i, true, &info);
- if (IS_ERR(desc) && PTR_ERR(desc) != -EPROBE_DEFER)
- return PTR_ERR(desc);
-
- if (info.gpioint && idx++ == index) {
- unsigned long lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
- enum gpiod_flags dflags = GPIOD_ASIS;
- char label[32];
- int irq;
-
- if (IS_ERR(desc))
- return PTR_ERR(desc);
-
- irq = gpiod_to_irq(desc);
- if (irq < 0)
- return irq;
-
- acpi_gpio_update_gpiod_flags(&dflags, &info);
- acpi_gpio_update_gpiod_lookup_flags(&lflags, &info);
-
- snprintf(label, sizeof(label), "%pfwP GpioInt(%d)", fwnode, index);
- ret = gpiod_set_consumer_name(desc, con_id ?: label);
- if (ret)
- return ret;
-
- ret = gpiod_configure_flags(desc, label, lflags, dflags);
- if (ret < 0)
- return ret;
-
- /* ACPI uses hundredths of milliseconds units */
- ret = gpio_set_debounce_timeout(desc, info.debounce * 10);
- if (ret)
- return ret;
-
- irq_flags = acpi_dev_get_irq_type(info.triggering,
- info.polarity);
-
- /*
- * If the IRQ is not already in use then set type
- * if specified and different than the current one.
- */
- if (can_request_irq(irq, irq_flags)) {
- if (irq_flags != IRQ_TYPE_NONE &&
- irq_flags != irq_get_trigger_type(irq))
- irq_set_irq_type(irq, irq_flags);
- } else {
- dev_dbg(&adev->dev, "IRQ %d already in use\n", irq);
- }
-
- /* avoid suspend issues with GPIOs when systems are using S3 */
- if (wake_capable && acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0)
- *wake_capable = info.wake_capable;
-
- return irq;
- }
-
- }
- return -ENOENT;
-}
-EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_wake_get_by);
-
-static acpi_status
-acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
- u32 bits, u64 *value, void *handler_context,
- void *region_context)
-{
- struct acpi_gpio_chip *achip = region_context;
- struct gpio_chip *chip = achip->chip;
- struct acpi_resource_gpio *agpio;
- struct acpi_resource *ares;
- u16 pin_index = address;
- acpi_status status;
- int length;
- int i;
-
- status = acpi_buffer_to_resource(achip->conn_info.connection,
- achip->conn_info.length, &ares);
- if (ACPI_FAILURE(status))
- return status;
-
- if (WARN_ON(ares->type != ACPI_RESOURCE_TYPE_GPIO)) {
- ACPI_FREE(ares);
- return AE_BAD_PARAMETER;
- }
-
- agpio = &ares->data.gpio;
-
- if (WARN_ON(agpio->io_restriction == ACPI_IO_RESTRICT_INPUT &&
- function == ACPI_WRITE)) {
- ACPI_FREE(ares);
- return AE_BAD_PARAMETER;
- }
-
- length = min_t(u16, agpio->pin_table_length, pin_index + bits);
- for (i = pin_index; i < length; ++i) {
- unsigned int pin = agpio->pin_table[i];
- struct acpi_gpio_connection *conn;
- struct gpio_desc *desc;
- bool found;
-
- mutex_lock(&achip->conn_lock);
-
- found = false;
- list_for_each_entry(conn, &achip->conns, node) {
- if (conn->pin == pin) {
- found = true;
- desc = conn->desc;
- break;
- }
- }
-
- /*
- * The same GPIO can be shared between operation region and
- * event but only if the access here is ACPI_READ. In that
- * case we "borrow" the event GPIO instead.
- */
- if (!found && agpio->shareable == ACPI_SHARED &&
- function == ACPI_READ) {
- struct acpi_gpio_event *event;
-
- list_for_each_entry(event, &achip->events, node) {
- if (event->pin == pin) {
- desc = event->desc;
- found = true;
- break;
- }
- }
- }
-
- if (!found) {
- desc = acpi_request_own_gpiod(chip, agpio, i, "ACPI:OpRegion");
- if (IS_ERR(desc)) {
- mutex_unlock(&achip->conn_lock);
- status = AE_ERROR;
- goto out;
- }
-
- conn = kzalloc(sizeof(*conn), GFP_KERNEL);
- if (!conn) {
- gpiochip_free_own_desc(desc);
- mutex_unlock(&achip->conn_lock);
- status = AE_NO_MEMORY;
- goto out;
- }
-
- conn->pin = pin;
- conn->desc = desc;
- list_add_tail(&conn->node, &achip->conns);
- }
-
- mutex_unlock(&achip->conn_lock);
-
- if (function == ACPI_WRITE)
- gpiod_set_raw_value_cansleep(desc, !!(*value & BIT(i)));
- else
- *value |= (u64)gpiod_get_raw_value_cansleep(desc) << i;
- }
-
-out:
- ACPI_FREE(ares);
- return status;
-}
-
-static void acpi_gpiochip_request_regions(struct acpi_gpio_chip *achip)
-{
- struct gpio_chip *chip = achip->chip;
- acpi_handle handle = ACPI_HANDLE(chip->parent);
- acpi_status status;
-
- INIT_LIST_HEAD(&achip->conns);
- mutex_init(&achip->conn_lock);
- status = acpi_install_address_space_handler(handle, ACPI_ADR_SPACE_GPIO,
- acpi_gpio_adr_space_handler,
- NULL, achip);
- if (ACPI_FAILURE(status))
- dev_err(chip->parent,
- "Failed to install GPIO OpRegion handler\n");
-}
-
-static void acpi_gpiochip_free_regions(struct acpi_gpio_chip *achip)
-{
- struct gpio_chip *chip = achip->chip;
- acpi_handle handle = ACPI_HANDLE(chip->parent);
- struct acpi_gpio_connection *conn, *tmp;
- acpi_status status;
-
- status = acpi_remove_address_space_handler(handle, ACPI_ADR_SPACE_GPIO,
- acpi_gpio_adr_space_handler);
- if (ACPI_FAILURE(status)) {
- dev_err(chip->parent,
- "Failed to remove GPIO OpRegion handler\n");
- return;
- }
-
- list_for_each_entry_safe_reverse(conn, tmp, &achip->conns, node) {
- gpiochip_free_own_desc(conn->desc);
- list_del(&conn->node);
- kfree(conn);
- }
-}
-
-static struct gpio_desc *
-acpi_gpiochip_parse_own_gpio(struct acpi_gpio_chip *achip,
- struct fwnode_handle *fwnode,
- const char **name,
- unsigned long *lflags,
- enum gpiod_flags *dflags)
-{
- struct gpio_chip *chip = achip->chip;
- struct gpio_desc *desc;
- u32 gpios[2];
- int ret;
-
- *lflags = GPIO_LOOKUP_FLAGS_DEFAULT;
- *dflags = GPIOD_ASIS;
- *name = NULL;
-
- ret = fwnode_property_read_u32_array(fwnode, "gpios", gpios,
- ARRAY_SIZE(gpios));
- if (ret < 0)
- return ERR_PTR(ret);
-
- desc = gpiochip_get_desc(chip, gpios[0]);
- if (IS_ERR(desc))
- return desc;
-
- if (gpios[1])
- *lflags |= GPIO_ACTIVE_LOW;
-
- if (fwnode_property_present(fwnode, "input"))
- *dflags |= GPIOD_IN;
- else if (fwnode_property_present(fwnode, "output-low"))
- *dflags |= GPIOD_OUT_LOW;
- else if (fwnode_property_present(fwnode, "output-high"))
- *dflags |= GPIOD_OUT_HIGH;
- else
- return ERR_PTR(-EINVAL);
-
- fwnode_property_read_string(fwnode, "line-name", name);
-
- return desc;
-}
-
-static void acpi_gpiochip_scan_gpios(struct acpi_gpio_chip *achip)
-{
- struct gpio_chip *chip = achip->chip;
- struct fwnode_handle *fwnode;
-
- device_for_each_child_node(chip->parent, fwnode) {
- unsigned long lflags;
- enum gpiod_flags dflags;
- struct gpio_desc *desc;
- const char *name;
- int ret;
-
- if (!fwnode_property_present(fwnode, "gpio-hog"))
- continue;
-
- desc = acpi_gpiochip_parse_own_gpio(achip, fwnode, &name,
- &lflags, &dflags);
- if (IS_ERR(desc))
- continue;
-
- ret = gpiod_hog(desc, name, lflags, dflags);
- if (ret) {
- dev_err(chip->parent, "Failed to hog GPIO\n");
- fwnode_handle_put(fwnode);
- return;
- }
- }
-}
-
-void acpi_gpiochip_add(struct gpio_chip *chip)
-{
- struct acpi_gpio_chip *acpi_gpio;
- struct acpi_device *adev;
- acpi_status status;
-
- if (!chip || !chip->parent)
- return;
-
- adev = ACPI_COMPANION(chip->parent);
- if (!adev)
- return;
-
- acpi_gpio = kzalloc(sizeof(*acpi_gpio), GFP_KERNEL);
- if (!acpi_gpio) {
- dev_err(chip->parent,
- "Failed to allocate memory for ACPI GPIO chip\n");
- return;
- }
-
- acpi_gpio->chip = chip;
- INIT_LIST_HEAD(&acpi_gpio->events);
- INIT_LIST_HEAD(&acpi_gpio->deferred_req_irqs_list_entry);
-
- status = acpi_attach_data(adev->handle, acpi_gpio_chip_dh, acpi_gpio);
- if (ACPI_FAILURE(status)) {
- dev_err(chip->parent, "Failed to attach ACPI GPIO chip\n");
- kfree(acpi_gpio);
- return;
- }
-
- acpi_gpiochip_request_regions(acpi_gpio);
- acpi_gpiochip_scan_gpios(acpi_gpio);
- acpi_dev_clear_dependencies(adev);
-}
-
-void acpi_gpiochip_remove(struct gpio_chip *chip)
-{
- struct acpi_gpio_chip *acpi_gpio;
- acpi_handle handle;
- acpi_status status;
-
- if (!chip || !chip->parent)
- return;
-
- handle = ACPI_HANDLE(chip->parent);
- if (!handle)
- return;
-
- status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio);
- if (ACPI_FAILURE(status)) {
- dev_warn(chip->parent, "Failed to retrieve ACPI GPIO chip\n");
- return;
- }
-
- acpi_gpiochip_free_regions(acpi_gpio);
-
- acpi_detach_data(handle, acpi_gpio_chip_dh);
- kfree(acpi_gpio);
-}
-
-static int acpi_gpio_package_count(const union acpi_object *obj)
-{
- const union acpi_object *element = obj->package.elements;
- const union acpi_object *end = element + obj->package.count;
- unsigned int count = 0;
-
- while (element < end) {
- switch (element->type) {
- case ACPI_TYPE_LOCAL_REFERENCE:
- element += 3;
- fallthrough;
- case ACPI_TYPE_INTEGER:
- element++;
- count++;
- break;
-
- default:
- return -EPROTO;
- }
- }
-
- return count;
-}
-
-static int acpi_find_gpio_count(struct acpi_resource *ares, void *data)
-{
- unsigned int *count = data;
-
- if (ares->type == ACPI_RESOURCE_TYPE_GPIO)
- *count += ares->data.gpio.pin_table_length;
-
- return 1;
-}
-
-/**
- * acpi_gpio_count - count the GPIOs associated with a firmware node / function
- * @fwnode: firmware node of the GPIO consumer
- * @con_id: function within the GPIO consumer
- *
- * Returns:
- * The number of GPIOs associated with a firmware node / function or %-ENOENT,
- * if no GPIO has been assigned to the requested function.
- */
-int acpi_gpio_count(const struct fwnode_handle *fwnode, const char *con_id)
-{
- struct acpi_device *adev = to_acpi_device_node(fwnode);
- const union acpi_object *obj;
- const struct acpi_gpio_mapping *gm;
- int count = -ENOENT;
- int ret;
- char propname[32];
-
- /* Try first from _DSD */
- for_each_gpio_property_name(propname, con_id) {
- ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY, &obj);
- if (ret == 0) {
- if (obj->type == ACPI_TYPE_LOCAL_REFERENCE)
- count = 1;
- else if (obj->type == ACPI_TYPE_PACKAGE)
- count = acpi_gpio_package_count(obj);
- } else if (adev->driver_gpios) {
- for (gm = adev->driver_gpios; gm->name; gm++)
- if (strcmp(propname, gm->name) == 0) {
- count = gm->size;
- break;
- }
- }
- if (count > 0)
- break;
- }
-
- /* Then from plain _CRS GPIOs */
- if (count < 0) {
- struct list_head resource_list;
- unsigned int crs_count = 0;
-
- if (!acpi_can_fallback_to_crs(adev, con_id))
- return count;
-
- INIT_LIST_HEAD(&resource_list);
- acpi_dev_get_resources(adev, &resource_list,
- acpi_find_gpio_count, &crs_count);
- acpi_dev_free_resource_list(&resource_list);
- if (crs_count > 0)
- count = crs_count;
- }
- return count ? count : -ENOENT;
-}
-
-/* Run deferred acpi_gpiochip_request_irqs() */
-static int __init acpi_gpio_handle_deferred_request_irqs(void)
-{
- mutex_lock(&acpi_gpio_deferred_req_irqs_lock);
- acpi_gpio_process_deferred_list(&acpi_gpio_deferred_req_irqs_list);
- acpi_gpio_deferred_req_irqs_done = true;
- mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
-
- return 0;
-}
-/* We must use _sync so that this runs after the first deferred_probe run */
-late_initcall_sync(acpi_gpio_handle_deferred_request_irqs);
-
-static const struct dmi_system_id gpiolib_acpi_quirks[] __initconst = {
- {
- /*
- * The Minix Neo Z83-4 has a micro-USB-B id-pin handler for
- * a non existing micro-USB-B connector which puts the HDMI
- * DDC pins in GPIO mode, breaking HDMI support.
- */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .no_edge_events_on_boot = true,
- },
- },
- {
- /*
- * The Terra Pad 1061 has a micro-USB-B id-pin handler, which
- * instead of controlling the actual micro-USB-B turns the 5V
- * boost for its USB-A connector off. The actual micro-USB-B
- * connector is wired for charging only.
- */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Wortmann_AG"),
- DMI_MATCH(DMI_PRODUCT_NAME, "TERRA_PAD_1061"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .no_edge_events_on_boot = true,
- },
- },
- {
- /*
- * The Dell Venue 10 Pro 5055, with Bay Trail SoC + TI PMIC uses an
- * external embedded-controller connected via I2C + an ACPI GPIO
- * event handler on INT33FFC:02 pin 12, causing spurious wakeups.
- */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
- DMI_MATCH(DMI_PRODUCT_NAME, "Venue 10 Pro 5055"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .ignore_wake = "INT33FC:02@12",
- },
- },
- {
- /*
- * HP X2 10 models with Cherry Trail SoC + TI PMIC use an
- * external embedded-controller connected via I2C + an ACPI GPIO
- * event handler on INT33FF:01 pin 0, causing spurious wakeups.
- * When suspending by closing the LID, the power to the USB
- * keyboard is turned off, causing INT0002 ACPI events to
- * trigger once the XHCI controller notices the keyboard is
- * gone. So INT0002 events cause spurious wakeups too. Ignoring
- * EC wakes breaks wakeup when opening the lid, the user needs
- * to press the power-button to wakeup the system. The
- * alternative is suspend simply not working, which is worse.
- */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "HP"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .ignore_wake = "INT33FF:01@0,INT0002:00@2",
- },
- },
- {
- /*
- * HP X2 10 models with Bay Trail SoC + AXP288 PMIC use an
- * external embedded-controller connected via I2C + an ACPI GPIO
- * event handler on INT33FC:02 pin 28, causing spurious wakeups.
- */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
- DMI_MATCH(DMI_BOARD_NAME, "815D"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .ignore_wake = "INT33FC:02@28",
- },
- },
- {
- /*
- * HP X2 10 models with Cherry Trail SoC + AXP288 PMIC use an
- * external embedded-controller connected via I2C + an ACPI GPIO
- * event handler on INT33FF:01 pin 0, causing spurious wakeups.
- */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "HP"),
- DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion x2 Detachable"),
- DMI_MATCH(DMI_BOARD_NAME, "813E"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .ignore_wake = "INT33FF:01@0",
- },
- },
- {
- /*
- * Interrupt storm caused from edge triggered floating pin
- * Found in BIOS UX325UAZ.300
- * https://bugzilla.kernel.org/show_bug.cgi?id=216208
- */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UAZ_UM325UAZ"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .ignore_interrupt = "AMDI0030:00@18",
- },
- },
- {
- /*
- * Spurious wakeups from TP_ATTN# pin
- * Found in BIOS 1.7.8
- * https://gitlab.freedesktop.org/drm/amd/-/issues/1722#note_1720627
- */
- .matches = {
- DMI_MATCH(DMI_BOARD_NAME, "NL5xNU"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .ignore_wake = "ELAN0415:00@9",
- },
- },
- {
- /*
- * Spurious wakeups from TP_ATTN# pin
- * Found in BIOS 1.7.8
- * https://gitlab.freedesktop.org/drm/amd/-/issues/1722#note_1720627
- */
- .matches = {
- DMI_MATCH(DMI_BOARD_NAME, "NL5xRU"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .ignore_wake = "ELAN0415:00@9",
- },
- },
- {
- /*
- * Spurious wakeups from TP_ATTN# pin
- * Found in BIOS 1.7.7
- */
- .matches = {
- DMI_MATCH(DMI_BOARD_NAME, "NH5xAx"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .ignore_wake = "SYNA1202:00@16",
- },
- },
- {
- /*
- * On the Peaq C1010 2-in-1 INT33FC:00 pin 3 is connected to
- * a "dolby" button. At the ACPI level an _AEI event-handler
- * is connected which sets an ACPI variable to 1 on both
- * edges. This variable can be polled + cleared to 0 using
- * WMI. But since the variable is set on both edges the WMI
- * interface is pretty useless even when polling.
- * So instead the x86-android-tablets code instantiates
- * a gpio-keys platform device for it.
- * Ignore the _AEI handler for the pin, so that it is not busy.
- */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "PEAQ"),
- DMI_MATCH(DMI_PRODUCT_NAME, "PEAQ PMM C1010 MD99187"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .ignore_interrupt = "INT33FC:00@3",
- },
- },
- {
- /*
- * Spurious wakeups from TP_ATTN# pin
- * Found in BIOS 0.35
- * https://gitlab.freedesktop.org/drm/amd/-/issues/3073
- */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GPD"),
- DMI_MATCH(DMI_PRODUCT_NAME, "G1619-04"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .ignore_wake = "PNP0C50:00@8",
- },
- },
- {
- /*
- * Spurious wakeups from GPIO 11
- * Found in BIOS 1.04
- * https://gitlab.freedesktop.org/drm/amd/-/issues/3954
- */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
- DMI_MATCH(DMI_PRODUCT_FAMILY, "Acer Nitro V 14"),
- },
- .driver_data = &(struct acpi_gpiolib_dmi_quirk) {
- .ignore_interrupt = "AMDI0030:00@11",
- },
- },
- {} /* Terminating entry */
-};
-
-static int __init acpi_gpio_setup_params(void)
-{
- const struct acpi_gpiolib_dmi_quirk *quirk = NULL;
- const struct dmi_system_id *id;
-
- id = dmi_first_match(gpiolib_acpi_quirks);
- if (id)
- quirk = id->driver_data;
-
- if (run_edge_events_on_boot < 0) {
- if (quirk && quirk->no_edge_events_on_boot)
- run_edge_events_on_boot = 0;
- else
- run_edge_events_on_boot = 1;
- }
-
- if (ignore_wake == NULL && quirk && quirk->ignore_wake)
- ignore_wake = quirk->ignore_wake;
-
- if (ignore_interrupt == NULL && quirk && quirk->ignore_interrupt)
- ignore_interrupt = quirk->ignore_interrupt;
-
- return 0;
-}
-
-/* Directly after dmi_setup() which runs as core_initcall() */
-postcore_initcall(acpi_gpio_setup_params);
next prev parent reply other threads:[~2026-01-06 17:43 UTC|newest]
Thread overview: 587+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-06 16:56 [PATCH 6.12 000/567] 6.12.64-rc1 review Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 001/567] btrfs: do not skip logging new dentries when logging a new name Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 002/567] btrfs: fix a potential path leak in print_data_reloc_error() Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 003/567] bpf, arm64: Do not audit capability check in do_jit() Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 004/567] btrfs: fix memory leak of fs_devices in degraded seed device path Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 005/567] shmem: fix recovery on rename failures Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 006/567] iomap: adjust read range correctly for non-block-aligned positions Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 007/567] iomap: account for unaligned end offsets when truncating read range Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 008/567] scripts/faddr2line: Fix "Argument list too long" error Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 009/567] perf/x86/amd: Check event before enable to avoid GPF Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 010/567] sched/deadline: only set free_cpus for online runqueues Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 011/567] sched/fair: Revert max_newidle_lb_cost bump Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 012/567] x86/ptrace: Always inline trivial accessors Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 013/567] ACPICA: Avoid walking the Namespace if start_node is NULL Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 014/567] ACPI: property: Use ACPI functions in acpi_graph_get_next_endpoint() only Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 015/567] cpufreq: dt-platdev: Add JH7110S SOC to the allowlist Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 016/567] ACPI: fan: Workaround for 64-bit firmware bug Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 017/567] cpufreq: s5pv210: fix refcount leak Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 018/567] cpuidle: menu: Use residency threshold in polling state override decisions Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 019/567] livepatch: Match old_sympos 0 and 1 in klp_find_func() Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 020/567] fs/ntfs3: Support timestamps prior to epoch Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 021/567] kbuild: Use objtree for module signing key path Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 022/567] ntfs: set dummy blocksize to read boot_block when mounting Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 023/567] hfsplus: fix volume corruption issue for generic/070 Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 024/567] hfsplus: fix missing hfs_bnode_get() in __hfs_bnode_create Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 025/567] hfsplus: Verify inode mode when loading from disk Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 026/567] hfsplus: fix volume corruption issue for generic/073 Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 027/567] fs/ntfs3: check for shutdown in fsync Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 028/567] wifi: rtl8xxxu: Fix HT40 channel config for RTL8192CU, RTL8723AU Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 029/567] wifi: cfg80211: stop radar detection in cfg80211_leave() Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 030/567] wifi: cfg80211: use cfg80211_leave() in iftype change Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 031/567] wifi: mt76: mt792x: fix wifi init fail by setting MCU_RUNNING after CLC load Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 032/567] wifi: brcmfmac: Add DMI nvram filename quirk for Acer A1 840 tablet Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 033/567] btrfs: scrub: always update btrfs_scrub_progress::last_physical Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 034/567] gfs2: fix remote evict for read-only filesystems Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 035/567] gfs2: Fix "gfs2: Switch to wait_event in gfs2_quotad" Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 036/567] smb/server: fix return value of smb2_ioctl() Greg Kroah-Hartman
2026-01-06 16:56 ` [PATCH 6.12 037/567] ksmbd: fix use-after-free in ksmbd_tree_connect_put under concurrency Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 038/567] ksmbd: vfs: fix race on m_flags in vfs_cache Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 039/567] Bluetooth: btusb: Add new VID/PID 2b89/6275 for RTL8761BUV Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 040/567] Bluetooth: btusb: MT7922: Add VID/PID 0489/e170 Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 041/567] Bluetooth: btusb: MT7920: Add VID/PID 0489/e135 Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 042/567] Bluetooth: btusb: Add new VID/PID 13d3/3533 for RTL8821CE Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 043/567] Bluetooth: btusb: Add new VID/PID 0x0489/0xE12F for RTL8852BE-VT Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 044/567] gfs2: Fix use of bio_chain Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 045/567] net: fec: ERR007885 Workaround for XDP TX path Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 046/567] netrom: Fix memory leak in nr_sendmsg() Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 047/567] net/sched: ets: Always remove class from active list before deleting in ets_qdisc_change Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 048/567] ipvlan: Ignore PACKET_LOOPBACK in handle_mode_l2() Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 049/567] mlxsw: spectrum_router: Fix possible neighbour reference count leak Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 050/567] mlxsw: spectrum_router: Fix neighbour use-after-free Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 051/567] mlxsw: spectrum_mr: Fix use-after-free when updating multicast route stats Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 052/567] bnxt_en: Fix XDP_TX path Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 053/567] net: openvswitch: fix middle attribute validation in push_nsh() action Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 054/567] broadcom: b44: prevent uninitialized value usage Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 055/567] netfilter: nf_conncount: fix leaked ct in error paths Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 056/567] ipvs: fix ipv4 null-ptr-deref in route error path Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 057/567] caif: fix integer underflow in cffrml_receive() Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 058/567] net/sched: ets: Remove drr class from the active list if it changes to strict Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 059/567] nfc: pn533: Fix error code in pn533_acr122_poweron_rdr() Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 060/567] netfilter: nf_nat: remove bogus direction check Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 061/567] netfilter: nf_tables: remove redundant chain validation on register store Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 062/567] selftests: netfilter: packetdrill: avoid failure on HZ=100 kernel Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 063/567] iommufd/selftest: Add coverage for reporting max_pasid_log2 via IOMMU_HW_INFO Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 064/567] iommufd/selftest: Update hw_info coverage for an input data_type Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 065/567] iommufd/selftest: Make it clearer to gcc that the access is not out of bounds Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 066/567] iommufd/selftest: Check for overflow in IOMMU_TEST_OP_ADD_RESERVED Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 067/567] ethtool: Avoid overflowing userspace buffer on stats query Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 068/567] net/mlx5: fw reset, clear reset requested on drain_fw_reset Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 069/567] net/mlx5: Drain firmware reset in shutdown callback Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 070/567] net/mlx5: fw_tracer, Validate format string parameters Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 071/567] net/mlx5: fw_tracer, Handle escaped percent properly Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 072/567] net/mlx5: Serialize firmware reset with devlink Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 073/567] net/handshake: duplicate handshake cancellations leak socket Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 074/567] net: enetc: do not transmit redirected XDP frames when the link is down Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 075/567] net: hns3: using the num_tqps in the vf driver to apply for resources Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 076/567] net: hns3: using the num_tqps to check whether tqp_index is out of range when vf get ring info from mbx Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 077/567] net: hns3: add VLAN id validation before using Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 078/567] hwmon: (dell-smm) Limit fan multiplier to avoid overflow Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 079/567] hwmon: (ibmpex) fix use-after-free in high/low store Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 080/567] hwmon: (tmp401) fix overflow caused by default conversion rate value Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 081/567] drm/me/gsc: mei interrupt top half should be in irq disabled context Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 082/567] drm/xe: Restore engine registers before restarting schedulers after GT reset Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 083/567] MIPS: Fix a reference leak bug in ip22_check_gio() Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 084/567] drm/panel: sony-td4353-jdi: Enable prepare_prev_first Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 085/567] x86/xen: Move Xen upcall handler Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 086/567] x86/xen: Fix sparse warning in enlighten_pv.c Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 087/567] arm64: kdump: Fix elfcorehdr overlap caused by reserved memory processing reorder Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 088/567] spi: cadence-quadspi: Fix clock disable on probe failure path Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 089/567] block: rnbd-clt: Fix leaked ID in init_dev() Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 090/567] drm/xe: Limit num_syncs to prevent oversized allocations Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 091/567] drm/xe/oa: " Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 092/567] hwmon: (ltc4282): Fix reset_history file permissions Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 093/567] ksmbd: skip lock-range check on equal size to avoid size==0 underflow Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 094/567] ksmbd: Fix refcount leak when invalid session is found on session lookup Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 095/567] ksmbd: fix buffer validation by including null terminator size in EA length Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 096/567] HID: input: map HID_GD_Z to ABS_DISTANCE for stylus/pen Greg Kroah-Hartman
2026-01-06 16:57 ` [PATCH 6.12 097/567] Input: ti_am335x_tsc - fix off-by-one error in wire_order validation Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 098/567] Input: lkkbd - disable pending work before freeing device Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 099/567] Input: alps - fix use-after-free bugs caused by dev3_register_work Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 100/567] Input: i8042 - add TUXEDO InfinityBook Max Gen10 AMD to i8042 quirk table Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 101/567] xfs: dont leak a locked dquot when xfs_dquot_attach_buf fails Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 102/567] can: gs_usb: gs_can_open(): fix error handling Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 103/567] soc/tegra: fuse: Do not register SoC device on ACPI boot Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 104/567] ACPI: PCC: Fix race condition by removing static qualifier Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 105/567] ACPI: CPPC: Fix missing PCC check for guaranteed_perf Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 106/567] spi: fsl-cpm: Check length parity before switching to 16 bit mode Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 107/567] mmc: sdhci-esdhc-imx: add alternate ARCH_S32 dependency to Kconfig Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 108/567] mmc: sdhci-of-arasan: Increase CD stable timeout to 2 seconds Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 109/567] dt-bindings: mmc: sdhci-of-aspeed: Switch ref to sdhci-common.yaml Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 110/567] net/hsr: fix NULL pointer dereference in prp_get_untagged_frame() Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 111/567] x86/fpu: Fix FPU state core dump truncation on CPUs with no extended xfeatures Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 112/567] ALSA: vxpocket: Fix resource leak in vxpocket_probe error path Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 113/567] ALSA: pcmcia: Fix resource leak in snd_pdacf_probe " Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 114/567] ALSA: usb-mixer: us16x08: validate meter packet indices Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 115/567] ASoC: ak4458: remove the reset operation in probe and remove Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 116/567] nfsd: update percpu_ref to manage references on nfsd_net Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 117/567] nfsd: rename nfsd_serv_ prefixed methods and variables with nfsd_net_ Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 118/567] nfsd: fix memory leak in nfsd_create_serv error paths Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 119/567] ipmi: Fix the race between __scan_channels() and deliver_response() Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 120/567] ipmi: Fix __scan_channels() failing to rescan channels Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 121/567] scsi: ufs: host: mediatek: Fix shutdown/suspend race condition Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 122/567] firmware: imx: scu-irq: Init workqueue before request mbox channel Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 123/567] ti-sysc: allow OMAP2 and OMAP4 timers to be reserved on AM33xx Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 124/567] scsi: smartpqi: Add support for Hurray Data new controller PCI device Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 125/567] clk: mvebu: cp110 add CLK_IGNORE_UNUSED to pcie_x10, pcie_x11 & pcie_x4 Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 126/567] powerpc/addnote: Fix overflow on 32-bit builds Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 127/567] scsi: qla2xxx: Fix lost interrupts with qlini_mode=disabled Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 128/567] scsi: qla2xxx: Fix initiator mode with qlini_mode=exclusive Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 129/567] scsi: qla2xxx: Use reinit_completion on mbx_intr_comp Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 130/567] fuse: Always flush the page cache before FOPEN_DIRECT_IO write Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 131/567] fuse: Invalidate the page cache after " Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 132/567] via_wdt: fix critical boot hang due to unnamed resource allocation Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 133/567] reset: fix BIT macro reference Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 134/567] exfat: fix remount failure in different process environments Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 135/567] exfat: zero out post-EOF page cache on file extension Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 136/567] usbip: Fix locking bug in RT-enabled kernels Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 137/567] usb: typec: ucsi: Handle incorrect num_connectors capability Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 138/567] iio: adc: ti_am335x_adc: Limit step_avg to valid range for gcc complains Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 139/567] usb: xhci: limit run_graceperiod for only usb 3.0 devices Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 140/567] usb: usb-storage: No additional quirks need to be added to the EL-R12 optical drive Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 141/567] serial: sprd: Return -EPROBE_DEFER when uart clock is not ready Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 142/567] libperf cpumap: Fix perf_cpu_map__max for an empty/NULL map Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 143/567] clk: qcom: dispcc-sm7150: Fix dispcc_mdss_pclk0_clk_src Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 144/567] i2c: designware: Disable SMBus interrupts to prevent storms from mis-configured firmware Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 145/567] nvme-fc: dont hold rport lock when putting ctrl Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 146/567] nvme-fabrics: add ENOKEY to no retry criteria for authentication failures Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 147/567] platform/x86/intel/hid: Add Dell Pro Rugged 10/12 tablet to VGBS DMI quirks Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 148/567] MIPS: ftrace: Fix memory corruption when kernel is located beyond 32 bits Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 149/567] scsi: scsi_debug: Fix atomic write enable module param description Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 150/567] block: rnbd-clt: Fix signedness bug in init_dev() Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 151/567] vhost/vsock: improve RCU read sections around vhost_vsock_get() Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 152/567] cifs: Fix memory and information leak in smb3_reconfigure() Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 153/567] KEYS: trusted: Fix a memory leak in tpm2_load_cmd Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 154/567] io_uring: fix filename leak in __io_openat_prep() Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 155/567] x86/mce: Do not clear banks poll bit in mce_poll_banks on AMD SMCA systems Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 156/567] mmc: sdhci-msm: Avoid early clock doubling during HS400 transition Greg Kroah-Hartman
2026-01-06 16:58 ` [PATCH 6.12 157/567] perf: arm_cspmu: fix error handling in arm_cspmu_impl_unregister() Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 158/567] lib/crypto: x86/blake2s: Fix 32-bit arg treated as 64-bit Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 159/567] s390/dasd: Fix gendisk parent after copy pair swap Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 160/567] wifi: mt76: Fix DTS power-limits on little endian systems Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 161/567] block: rate-limit capacity change info log Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 162/567] floppy: fix for PAGE_SIZE != 4KB Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 163/567] kallsyms: Fix wrong "big" kernel symbol type read from procfs Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 164/567] fs/ntfs3: fix mount failure for sparse runs in run_unpack() Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 165/567] ktest.pl: Fix uninitialized var in config-bisect.pl Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 166/567] tpm: Cap the number of PCR banks Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 167/567] ext4: fix string copying in parse_apply_sb_mount_options() Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 168/567] ext4: xattr: fix null pointer deref in ext4_raw_inode() Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 169/567] ext4: clear i_state_flags when alloc inode Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 170/567] ext4: fix incorrect group number assertion in mb_check_buddy Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 171/567] ext4: align max orphan file size with e2fsprogs limit Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 172/567] jbd2: use a per-journal lock_class_key for jbd2_trans_commit_key Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 173/567] jbd2: use a weaker annotation in journal handling Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 174/567] media: v4l2-mem2mem: Fix outdated documentation Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 175/567] selftests: mptcp: pm: ensure unknown flags are ignored Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 176/567] mptcp: schedule rtx timer only after pushing data Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 177/567] mptcp: avoid deadlock on fallback while reinjecting Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 178/567] usb: usb-storage: Maintain minimal modifications to the bcdDevice range Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 179/567] media: dvb-usb: dtv5100: fix out-of-bounds in dtv5100_i2c_msg() Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 180/567] media: pvrusb2: Fix incorrect variable used in trace message Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 181/567] phy: broadcom: bcm63xx-usbh: fix section mismatches Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 182/567] usb: ohci-nxp: fix device leak on probe failure Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 183/567] usb: typec: altmodes/displayport: Drop the device reference in dp_altmode_probe() Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 184/567] USB: lpc32xx_udc: Fix error handling in probe Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 185/567] usb: phy: fsl-usb: Fix use-after-free in delayed work during device removal Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 186/567] usb: phy: isp1301: fix non-OF device reference imbalance Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 187/567] usb: gadget: lpc32xx_udc: fix clock imbalance in error path Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 188/567] usb: dwc3: of-simple: fix clock resource leak in dwc3_of_simple_probe Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 189/567] usb: dwc3: keep susphy enabled during exit to avoid controller faults Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 190/567] usb: renesas_usbhs: Fix a resource leak in usbhs_pipe_malloc() Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 191/567] char: applicom: fix NULL pointer dereference in ac_ioctl Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 192/567] intel_th: Fix error handling in intel_th_output_open Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 193/567] mei: gsc: add dependency on Xe driver Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 194/567] serial: sh-sci: Check that the DMA cookie is valid Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 195/567] cpuidle: governors: teo: Drop misguided target residency check Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 196/567] cpufreq: nforce2: fix reference count leak in nforce2 Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 197/567] scsi: Revert "scsi: qla2xxx: Perform lockless command completion in abort path" Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 198/567] scsi: aic94xx: fix use-after-free in device removal path Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 199/567] NFSD: use correct reservation type in nfsd4_scsi_fence_client Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 200/567] scsi: target: Reset t_task_cdb pointer in error case Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 201/567] scsi: mpi3mr: Read missing IOCFacts flag for reply queue full overflow Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 202/567] scsi: ufs: core: Add ufshcd_update_evt_hist() for UFS suspend error Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 203/567] f2fs: ensure node page reads complete before f2fs_put_super() finishes Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 204/567] f2fs: fix to avoid potential deadlock Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 205/567] f2fs: fix to avoid updating zero-sized extent in extent cache Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 206/567] f2fs: invalidate dentry cache on failed whiteout creation Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 207/567] f2fs: fix age extent cache insertion skip on counter overflow Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 208/567] f2fs: fix uninitialized one_time_gc in victim_sel_policy Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 209/567] f2fs: fix return value of f2fs_recover_fsync_data() Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 210/567] tools/testing/nvdimm: Use per-DIMM device handle Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 211/567] KVM: Disallow toggling KVM_MEM_GUEST_MEMFD on an existing memslot Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 212/567] media: vidtv: initialize local pointers upon transfer of memory ownership Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 213/567] ocfs2: fix kernel BUG in ocfs2_find_victim_chain Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 214/567] KVM: x86: Dont clear async #PF queue when CR0.PG is disabled (e.g. on #SMI) Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 215/567] platform/chrome: cros_ec_ishtp: Fix UAF after unbinding driver Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 216/567] scs: fix a wrong parameter in __scs_magic Greg Kroah-Hartman
2026-01-06 16:59 ` [PATCH 6.12 217/567] parisc: Do not reprogram affinitiy on ASP chip Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 218/567] libceph: make decode_pool() more resilient against corrupted osdmaps Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 219/567] powerpc: Add reloc_offset() to font bitmap pointer used for bootx_printf() Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 220/567] KVM: x86: WARN if hrtimer callback for periodic APIC timer fires with period=0 Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 221/567] KVM: x86: Explicitly set new periodic hrtimer expiration in apic_timer_fn() Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 222/567] KVM: x86: Fix VM hard lockup after prolonged inactivity with periodic HV timer Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 223/567] KVM: nSVM: Avoid incorrect injection of SVM_EXIT_CR0_SEL_WRITE Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 224/567] KVM: SVM: Mark VMCB_NPT as dirty on nested VMRUN Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 225/567] KVM: nSVM: Propagate SVM_EXIT_CR0_SEL_WRITE correctly for LMSW emulation Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 226/567] KVM: SVM: Mark VMCB_PERM_MAP as dirty on nested VMRUN Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 227/567] KVM: nVMX: Immediately refresh APICv controls as needed on nested VM-Exit Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 228/567] KVM: nSVM: Set exit_code_hi to -1 when synthesizing SVM_EXIT_ERR (failed VMRUN) Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 229/567] KVM: nSVM: Clear exit_code_hi in VMCB when synthesizing nested VM-Exits Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 230/567] xfs: fix a memory leak in xfs_buf_item_init() Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 231/567] xfs: fix stupid compiler warning Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 232/567] xfs: fix a UAF problem in xattr repair Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 233/567] tracing: Do not register unsupported perf events Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 234/567] PM: runtime: Do not clear needs_force_resume with enabled runtime PM Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 235/567] r8169: fix RTL8117 Wake-on-Lan in DASH mode Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 236/567] net: phy: marvell-88q2xxx: Fix clamped value in mv88q2xxx_hwmon_write Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 237/567] fsnotify: do not generate ACCESS/MODIFY events on child for special files Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 238/567] net/handshake: restore destructor on submit failure Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 239/567] NFSD: Clear SECLABEL in the suppattr_exclcreat bitmap Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 240/567] NFSD: NFSv4 file creation neglects setting ACL Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 241/567] nfsd: Mark variable __maybe_unused to avoid W=1 build break Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 242/567] svcrdma: return 0 on success from svc_rdma_copy_inline_range Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 243/567] svcrdma: use rc_pageoff for memcpy byte offset Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 244/567] SUNRPC: svcauth_gss: avoid NULL deref on zero length gss_token in gss_read_proxy_verf Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 245/567] powerpc/kexec: Enable SMT before waking offline CPUs Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 246/567] btrfs: dont log conflicting inode if its a dir moved in the current transaction Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 247/567] s390/ipl: Clear SBP flag when bootprog is set Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 248/567] gpio: regmap: Fix memleak in error path in gpio_regmap_register() Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 249/567] io_uring/poll: correctly handle io_poll_add() return value on update Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 250/567] io_uring: fix min_wait wakeups for SQPOLL Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 251/567] Revert "drm/amd/display: Fix pbn to kbps Conversion" Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 252/567] drm/amd/display: Use GFP_ATOMIC in dc_create_plane_state() Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 253/567] drm/amd/display: Fix scratch registers offsets for DCN35 Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 254/567] drm/amd/display: Fix scratch registers offsets for DCN351 Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 255/567] drm/displayid: pass iter to drm_find_displayid_extension() Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 256/567] ALSA: hda: cs35l41: Fix NULL pointer dereference in cs35l41_hda_read_acpi() Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 257/567] ALSA: wavefront: Use guard() for spin locks Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 258/567] ALSA: wavefront: Clear substream pointers on close Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 259/567] pinctrl: renesas: rzg2l: Fix ISEL restore on resume Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 260/567] hsr: hold rcu and dev lock for hsr_get_port_ndev Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 261/567] sched/rt: Fix race in push_rt_task Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 262/567] KVM: arm64: Initialize HCR_EL2.E2H early Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 263/567] KVM: arm64: Initialize SCTLR_EL1 in __kvm_hyp_init_cpu() Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 264/567] arm64: Revamp HCR_EL2.E2H RES1 detection Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 265/567] dt-bindings: PCI: qcom,pcie-sc7280: Add missing required power-domains and resets Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 266/567] dt-bindings: PCI: qcom,pcie-sc8280xp: " Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 267/567] dt-bindings: PCI: qcom,pcie-sm8150: " Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 268/567] dt-bindings: PCI: qcom,pcie-sm8250: " Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 269/567] dt-bindings: PCI: qcom,pcie-sm8350: " Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 270/567] dt-bindings: PCI: qcom,pcie-sm8450: " Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 271/567] dt-bindings: PCI: qcom,pcie-sm8550: " Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 272/567] crypto: af_alg - zero initialize memory allocated via sock_kmalloc Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 273/567] crypto: caam - Add check for kcalloc() in test_len() Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 274/567] amba: tegra-ahb: Fix device leak on SMMU enable Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 275/567] virtio: vdpa: Fix reference count leak in octep_sriov_enable() Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 276/567] tracing: Fix fixed array of synthetic event Greg Kroah-Hartman
2026-01-06 17:00 ` [PATCH 6.12 277/567] soc: samsung: exynos-pmu: fix device leak on regmap lookup Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 278/567] soc: qcom: pbs: fix device leak on lookup Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 279/567] soc: qcom: ocmem: " Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 280/567] soc: apple: mailbox: " Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 281/567] soc: amlogic: canvas: " Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 282/567] rpmsg: glink: fix rpmsg device leak Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 283/567] platform/x86: intel: chtwc_int33fe: dont dereference swnode args Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 284/567] i2c: amd-mp2: fix reference leak in MP2 PCI device Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 285/567] interconnect: qcom: sdx75: Drop QPIC interconnect and BCM nodes Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 286/567] hwmon: (max16065) Use local variable to avoid TOCTOU Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 287/567] hwmon: (max6697) fix regmap leak on probe failure Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 288/567] hwmon: (w83791d) Convert macros to functions to avoid TOCTOU Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 289/567] hwmon: (w83l786ng) " Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 290/567] ARM: dts: microchip: sama5d2: fix spi flexcom fifo size to 32 Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 291/567] x86/msi: Make irq_retrigger() functional for posted MSI Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 292/567] iommu/mediatek: fix use-after-free on probe deferral Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 293/567] fuse: fix readahead reclaim deadlock Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 294/567] wifi: rtw88: limit indirect IO under powered off for RTL8822CS Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 295/567] wifi: rtlwifi: 8192cu: fix tid out of range in rtl92cu_tx_fill_desc() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 296/567] wifi: cfg80211: sme: store capped length in __cfg80211_connect_result() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 297/567] wifi: mac80211: do not use old MBSSID elements Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 298/567] i40e: fix scheduling in set_rx_mode Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 299/567] i40e: validate ring_len parameter against hardware-specific values Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 300/567] iavf: fix off-by-one issues in iavf_config_rss_reg() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 301/567] idpf: reduce mbx_task schedule delay to 300us Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 302/567] crypto: seqiv - Do not use req->iv after crypto_aead_encrypt Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 303/567] Bluetooth: btusb: revert use of devm_kzalloc in btusb Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 304/567] net: mdio: aspeed: add dummy read to avoid read-after-write issue Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 305/567] net: openvswitch: Avoid needlessly taking the RTNL on vport destroy Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 306/567] ip6_gre: make ip6gre_header() robust Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 307/567] platform/mellanox: mlxbf-pmc: Remove trailing whitespaces from event names Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 308/567] platform/x86: msi-laptop: add missing sysfs_remove_group() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 309/567] platform/x86: ibm_rtl: fix EBDA signature search pointer arithmetic Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 310/567] team: fix check for port enabled in team_queue_override_port_prio_changed() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 311/567] net: dsa: fix missing put_device() in dsa_tree_find_first_conduit() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 312/567] amd-xgbe: reset retries and mode on RX adapt failures Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 313/567] net: usb: rtl8150: fix memory leak on usb_submit_urb() failure Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 314/567] selftests: net: fix "buffer overflow detected" for tap.c Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 315/567] smc91x: fix broken irq-context in PREEMPT_RT Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 316/567] genalloc.h: fix htmldocs warning Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 317/567] firewire: nosy: Fix dma_free_coherent() size Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 318/567] net: dsa: b53: skip multicast entries for fdb_dump() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 319/567] kbuild: fix compilation of dtb specified on command-line without make rule Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 320/567] net: usb: asix: validate PHY address before use Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 321/567] net: bridge: Describe @tunnel_hash member in net_bridge_vlan_group struct Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 322/567] vfio/pds: Fix memory leak in pds_vfio_dirty_enable() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 323/567] platform/x86: hp-bioscfg: Fix out-of-bounds array access in ACPI package parsing Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 324/567] octeontx2-pf: fix "UBSAN: shift-out-of-bounds error" Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 325/567] net: stmmac: fix the crash issue for zero copy XDP_TX action Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 326/567] ipv6: BUG() in pskb_expand_head() as part of calipso_skbuff_setattr() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 327/567] ipv4: Fix reference count leak when using error routes with nexthop objects Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 328/567] net: rose: fix invalid array index in rose_kill_by_device() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 329/567] ipv6: fix a BUG in rt6_get_pcpu_route() under PREEMPT_RT Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 330/567] RDMA/irdma: avoid invalid read in irdma_net_event Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 331/567] RDMA/efa: Remove possible negative shift Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 332/567] RDMA/core: Fix logic error in ib_get_gids_from_rdma_hdr() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 333/567] RDMA/bnxt_re: Fix incorrect BAR check in bnxt_qplib_map_creq_db() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 334/567] RDMA/core: always drop device refcount in ib_del_sub_device_and_put() Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 335/567] RDMA/bnxt_re: Fix IB_SEND_IP_CSUM handling in post_send Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 336/567] RDMA/bnxt_re: Fix to use correct page size for PDE table Greg Kroah-Hartman
2026-01-06 17:01 ` [PATCH 6.12 337/567] md: Fix static checker warning in analyze_sbs Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 338/567] md/raid5: fix possible null-pointer dereferences in raid5_store_group_thread_cnt() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 339/567] ksmbd: Fix memory leak in get_file_all_info() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 340/567] RDMA/rtrs: Fix clt_path::max_pages_per_mr calculation Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 341/567] RDMA/bnxt_re: fix dma_free_coherent() pointer Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 342/567] blk-mq: skip CPU offline notify on unmapped hctx Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 343/567] selftests/ftrace: traceonoff_triggers: strip off names Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 344/567] ntfs: Do not overwrite uptodate pages Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 345/567] ASoC: codecs: wcd939x: fix regmap leak on probe failure Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 346/567] ASoC: stm32: sai: fix device leak on probe Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 347/567] ASoC: stm32: sai: fix clk prepare imbalance on probe failure Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 348/567] ASoC: stm32: sai: fix OF node leak on probe Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 349/567] ASoC: codecs: lpass-tx-macro: fix SM6115 support Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 350/567] ASoC: qcom: q6apm-dai: set flags to reflect correct operation of appl_ptr Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 351/567] ASoC: qcom: q6asm-dai: perform correct state check before closing Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 352/567] ASoC: qcom: q6adm: the the copp device only during last instance Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 353/567] ASoC: qcom: qdsp6: q6asm-dai: set 10 ms period and buffer alignment Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 354/567] iommu/amd: Fix pci_segment memleak in alloc_pci_segment() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 355/567] iommu/amd: Propagate the error code returned by __modify_irte_ga() in modify_irte_ga() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 356/567] iommu/apple-dart: fix device leak on of_xlate() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 357/567] iommu/exynos: " Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 358/567] iommu/ipmmu-vmsa: " Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 359/567] iommu/mediatek-v1: fix device leak on probe_device() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 360/567] iommu/mediatek-v1: fix device leaks on probe() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 361/567] iommu/mediatek: fix device leak on of_xlate() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 362/567] iommu/omap: fix device leaks on probe_device() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 363/567] iommu/qcom: fix device leak on of_xlate() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 364/567] iommu/sun50i: " Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 365/567] iommu/tegra: fix device leak on probe_device() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 366/567] iommu: disable SVA when CONFIG_X86 is set Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 367/567] HID: logitech-dj: Remove duplicate error logging Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 368/567] fgraph: Initialize ftrace_ops->private for function graph ops Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 369/567] fgraph: Check ftrace_pids_enabled on registration for early filtering Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 370/567] PCI/PM: Reinstate clearing state_saved in legacy and !PM codepaths Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 371/567] arm64: dts: ti: k3-j721e-sk: Fix pinmux for pin Y1 used by power regulator Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 372/567] powerpc, mm: Fix mprotect on book3s 32-bit Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 373/567] powerpc/64s/slb: Fix SLB multihit issue during SLB preload Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 374/567] leds: leds-cros_ec: Skip LEDs without color components Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 375/567] leds: leds-lp50xx: Allow LED 0 to be added to module bank Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 376/567] leds: leds-lp50xx: LP5009 supports 3 modules for a total of 9 LEDs Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 377/567] leds: leds-lp50xx: Enable chip before any communication Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 378/567] block: Clear BLK_ZONE_WPLUG_PLUGGED when aborting plugged BIOs Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 379/567] clk: samsung: exynos-clkout: Assign .num before accessing .hws Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 380/567] mfd: altera-sysmgr: Fix device leak on sysmgr regmap lookup Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 381/567] mfd: max77620: Fix potential IRQ chip conflict when probing two devices Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 382/567] media: rc: st_rc: Fix reset control resource leak Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 383/567] media: verisilicon: Fix CPU stalls on G2 bus error Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 384/567] mtd: mtdpart: ignore error -ENOENT from parsers on subpartitions Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 385/567] mtd: spi-nor: winbond: Add support for W25Q01NWxxIQ chips Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 386/567] mtd: spi-nor: winbond: Add support for W25Q01NWxxIM chips Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 387/567] mtd: spi-nor: winbond: Add support for W25Q02NWxxIM chips Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 388/567] mtd: spi-nor: winbond: Add support for W25H512NWxxAM chips Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 389/567] mtd: spi-nor: winbond: Add support for W25H01NWxxAM chips Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 390/567] mtd: spi-nor: winbond: Add support for W25H02NWxxAM chips Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 391/567] parisc: entry.S: fix space adjustment on interruption for 64-bit userspace Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 392/567] parisc: entry: set W bit for !compat tasks in syscall_restore_rfi() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 393/567] perf/x86/amd/uncore: Fix the return value of amd_uncore_df_event_init() on error Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 394/567] powerpc/pseries/cmm: call balloon_devinfo_init() also without CONFIG_BALLOON_COMPACTION Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 395/567] media: adv7842: Avoid possible out-of-bounds array accesses in adv7842_cp_log_status() Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 396/567] firmware: stratix10-svc: Add mutex in stratix10 memory management Greg Kroah-Hartman
2026-01-06 17:02 ` [PATCH 6.12 397/567] dm-ebs: Mark full buffer dirty even on partial write Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 398/567] dm-bufio: align write boundary on physical block size Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 399/567] fbdev: gbefb: fix to use physical address instead of dma address Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 400/567] fbdev: pxafb: Fix multiple clamped values in pxafb_adjust_timing Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 401/567] fbdev: tcx.c fix mem_map to correct smem_start offset Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 402/567] media: cec: Fix debugfs leak on bus_register() failure Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 403/567] media: msp3400: Avoid possible out-of-bounds array accesses in msp3400c_thread() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 404/567] media: platform: mtk-mdp3: fix device leaks at probe Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 405/567] media: renesas: rcar_drif: fix device node reference leak in rcar_drif_bond_enabled Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 406/567] media: samsung: exynos4-is: fix potential ABBA deadlock on init Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 407/567] media: TDA1997x: Remove redundant cancel_delayed_work in probe Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 408/567] media: verisilicon: Protect G2 HEVC decoder against invalid DPB index Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 409/567] media: videobuf2: Fix device reference leak in vb2_dc_alloc error path Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 410/567] media: vpif_capture: fix section mismatch Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 411/567] media: vpif_display: " Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 412/567] media: amphion: Cancel message work before releasing the VPU core Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 413/567] media: i2c: ADV7604: Remove redundant cancel_delayed_work in probe Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 414/567] media: i2c: adv7842: " Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 415/567] media: mediatek: vcodec: Fix a reference leak in mtk_vcodec_fw_vpu_init() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 416/567] LoongArch: Add new PCI ID for pci_fixup_vgadev() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 417/567] LoongArch: Correct the calculation logic of thread_count Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 418/567] LoongArch: Fix build errors for CONFIG_RANDSTRUCT Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 419/567] LoongArch: Use __pmd()/__pte() for swap entry conversions Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 420/567] LoongArch: Use unsigned long for _end and _text Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 421/567] mm/damon/tests/sysfs-kunit: handle alloc failures on damon_sysfs_test_add_targets() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 422/567] mm/damon/tests/vaddr-kunit: handle alloc failures in damon_test_split_evenly_fail() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 423/567] mm/damon/tests/vaddr-kunit: handle alloc failures on damon_test_split_evenly_succ() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 424/567] mm/damon/tests/core-kunit: handle alloc failures on damon_test_split_at() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 425/567] mm/damon/tests/core-kunit: handle allocation failures in damon_test_regions() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 426/567] mm/damon/tests/core-kunit: handle memory failure from damon_test_target() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 427/567] mm/damon/tests/core-kunit: handle memory alloc failure from damon_test_aggregate() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 428/567] mm/damon/tests/core-kunit: handle alloc failures on dasmon_test_merge_regions_of() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 429/567] mm/damon/tests/core-kunit: handle alloc failures on damon_test_merge_two() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 430/567] mm/damon/tests/core-kunit: handle alloc failures in damon_test_set_regions() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 431/567] mm/damon/tests/core-kunit: handle alloc failures in damon_test_update_monitoring_result() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 432/567] mm/damon/tests/core-kunit: handle alloc failures in damon_test_ops_registration() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 433/567] mm/damon/tests/core-kunit: handle alloc failure on damon_test_set_attrs() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 434/567] pmdomain: imx: Fix reference count leak in imx_gpc_probe() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 435/567] compiler_types.h: add "auto" as a macro for "__auto_type" Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 436/567] mm/kasan: fix incorrect unpoisoning in vrealloc for KASAN Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 437/567] kasan: refactor pcpu kasan vmalloc unpoison Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 438/567] kasan: unpoison vms[area] addresses with a common tag Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 439/567] lockd: fix vfs_test_lock() calls Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 440/567] idr: fix idr_alloc() returning an ID out of range Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 441/567] mm/page_owner: fix memory leak in page_owner_stack_fops->release() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 442/567] x86/microcode/AMD: Fix Entrysign revision check for Zen5/Strix Halo Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 443/567] tools/mm/page_owner_sort: fix timestamp comparison for stable sorting Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 444/567] samples/ftrace: Adjust LoongArch register restore order in direct calls Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 445/567] RDMA/core: Check for the presence of LS_NLA_TYPE_DGID correctly Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 446/567] RDMA/cm: Fix leaking the multicast GID table reference Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 447/567] e1000: fix OOB in e1000_tbi_should_accept() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 448/567] fjes: Add missing iounmap in fjes_hw_init() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 449/567] LoongArch: Refactor register restoration in ftrace_common_return Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 450/567] LoongArch: BPF: Zero-extend bpf_tail_call() index Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 451/567] LoongArch: BPF: Sign extend kfunc call arguments Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 452/567] nfsd: Drop the client reference in client_states_open() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 453/567] net: usb: sr9700: fix incorrect command used to write single register Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 454/567] net: nfc: fix deadlock between nfc_unregister_device and rfkill_fop_write Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 455/567] net: macb: Relocate mog_init_rings() callback from macb_mac_link_up() to macb_open() Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 456/567] Revert "drm/amd: Skip power ungate during suspend for VPE" Greg Kroah-Hartman
2026-01-06 17:03 ` [PATCH 6.12 457/567] drm/amdgpu/gmc12: add amdgpu_vm_handle_fault() handling Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 458/567] drm/amdgpu: add missing lock to amdgpu_ttm_access_memory_sdma Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 459/567] drm/amdgpu/gmc11: add amdgpu_vm_handle_fault() handling Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 460/567] drm/msm/a6xx: Fix out of bound IO access in a6xx_get_gmu_registers Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 461/567] drm/buddy: Optimize free block management with RB tree Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 462/567] drm/buddy: Separate clear and dirty free block trees Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 463/567] drm/gma500: Remove unused helper psb_fbdev_fb_setcolreg() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 464/567] drm/edid: add DRM_EDID_IDENT_INIT() to initialize struct drm_edid_ident Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 465/567] drm/xe/oa: Fix potential UAF in xe_oa_add_config_ioctl() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 466/567] drm/mediatek: Fix device node reference leak in mtk_dp_dt_parse() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 467/567] drm/mediatek: Fix probe resource leaks Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 468/567] drm/mediatek: Fix probe memory leak Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 469/567] drm/mediatek: Fix probe device leaks Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 470/567] drm/amdkfd: Export the cwsr_size and ctl_stack_size to userspace Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 471/567] drm/amdkfd: bump minimum vgpr size for gfx1151 Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 472/567] drm/amdkfd: Trap handler support for expert scheduling mode Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 473/567] drm/i915: Fix format string truncation warning Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 474/567] drm/ttm: Avoid NULL pointer deref for evicted BOs Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 475/567] drm/mgag200: Fix big-endian support Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 476/567] drm/xe/bo: Dont include the CCS metadata in the dma-buf sg-table Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 477/567] drm/xe/oa: Disallow 0 OA property values Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 478/567] drm/xe: Adjust long-running workload timeslices to reasonable values Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 479/567] drm/xe: Use usleep_range for accurate long-running workload timeslicing Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 480/567] drm/xe: Drop preempt-fences when destroying imported dma-bufs Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 481/567] drm/msm/dpu: Add missing NULL pointer check for pingpong interface Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 482/567] drm/i915/gem: Zero-initialize the eb.vma array in i915_gem_do_execbuffer Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 483/567] drm/nouveau/dispnv50: Dont call drm_atomic_get_crtc_state() in prepare_fb Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 484/567] drm/imagination: Disallow exporting of PM/FW protected objects Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 485/567] lib/crypto: riscv/chacha: Avoid s0/fp register Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 486/567] gfs2: fix freeze error handling Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 487/567] btrfs: dont rewrite ret from inode_permission Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 488/567] sched/eevdf: Fix min_vruntime vs avg_vruntime Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 489/567] erofs: fix unexpected EIO under memory pressure Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 490/567] sched_ext: Fix incorrect sched_class settings for per-cpu migration tasks Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 491/567] jbd2: fix the inconsistency between checksum and data in memory for journal sb Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 492/567] tty: introduce and use tty_port_tty_vhangup() helper Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 493/567] xhci: dbgtty: fix device unregister: fixup Greg Kroah-Hartman
2026-01-07 0:04 ` Łukasz Bartosik
2026-01-08 9:12 ` Greg Kroah-Hartman
2026-01-08 9:45 ` Łukasz Bartosik
2026-01-06 17:04 ` [PATCH 6.12 494/567] f2fs: fix to detect recoverable inode during dryrun of find_fsync_dnodes() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 495/567] f2fs: use global inline_xattr_slab instead of per-sb slab cache Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 496/567] f2fs: drop inode from the donation list when the last file is closed Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 497/567] f2fs: fix to avoid updating compression context during writeback Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 498/567] serial: core: fix OF node leak Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 499/567] serial: core: Restore sysfs fwnode information Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 500/567] mptcp: pm: ignore unknown endpoint flags Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 501/567] mm/ksm: fix exec/fork inheritance support for prctl Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 502/567] svcrdma: bound check rq_pages index in inline path Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 503/567] ARM: dts: microchip: sama7g5: fix uart fifo size to 32 Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 504/567] block: freeze queue when updating zone resources Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 505/567] tpm2-sessions: Fix tpm2_read_public range checks Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 506/567] sched_ext: Factor out local_dsq_post_enq() from dispatch_enqueue() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 507/567] sched_ext: Fix missing post-enqueue handling in move_local_task_to_local_dsq() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 508/567] drm/displayid: add quirk to ignore DisplayID checksum errors Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 509/567] hrtimers: Introduce hrtimer_update_function() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 510/567] serial: xilinx_uartps: Use helper function hrtimer_update_function() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 511/567] serial: xilinx_uartps: fix rs485 delay_rts_after_send Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 512/567] f2fs: clear SBI_POR_DOING before initing inmem curseg Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 513/567] f2fs: add timeout in f2fs_enable_checkpoint() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 514/567] f2fs: dump more information for f2fs_{enable,disable}_checkpoint() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 515/567] f2fs: fix to propagate error from f2fs_enable_checkpoint() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 516/567] gpiolib: acpi: Switch to use enum in acpi_gpio_in_ignore_list() Greg Kroah-Hartman
2026-01-06 17:04 ` [PATCH 6.12 517/567] gpiolib: acpi: Handle deferred list via new API Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 518/567] gpiolib: acpi: Add acpi_gpio_need_run_edge_events_on_boot() getter Greg Kroah-Hartman
2026-01-06 17:05 ` Greg Kroah-Hartman [this message]
2026-02-10 16:06 ` [PATCH 6.12 519/567] gpiolib: acpi: Move quirks to a separate file Ben Hutchings
2026-02-11 11:36 ` Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 520/567] gpiolib: acpi: Add a quirk for Acer Nitro V15 Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 521/567] gpiolib: acpi: Add quirk for ASUS ProArt PX13 Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 522/567] gpiolib: acpi: Add quirk for Dell Precision 7780 Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 523/567] netfilter: nft_ct: add seqadj extension for natted connections Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 524/567] md/raid10: wait barrier before returning discard request with REQ_NOWAIT Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 525/567] drm/panthor: Flush shmem writes before mapping buffers CPU-uncached Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 526/567] net: ipv6: ioam6: use consistent dst names Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 527/567] ipv6: adopt dst_dev() helper Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 528/567] net: use dst_dev_rcu() in sk_setup_caps() Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 529/567] usbnet: Fix using smp_processor_id() in preemptible code warnings Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 530/567] serial: core: Fix serial device initialization Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 531/567] tty: fix tty_port_tty_*hangup() kernel-doc Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 532/567] x86/microcode/AMD: Select which microcode patch to load Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 533/567] media: i2c: imx219: Fix 1920x1080 mode to use 1:1 pixel aspect ratio Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 534/567] wifi: mt76: mt7925: fix the unfinished command of regd_notifier before suspend Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 535/567] wifi: mt76: mt7925: fix CLC command timeout when suspend/resume Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 536/567] wifi: mt76: mt7925: add handler to hif suspend/resume event Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 537/567] idpf: add support for SW triggered interrupts Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 538/567] idpf: trigger SW interrupt when exiting wb_on_itr mode Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 539/567] idpf: add support for Tx refillqs in flow scheduling mode Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 540/567] idpf: improve when to set RE bit logic Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 541/567] idpf: simplify and fix splitq Tx packet rollback error path Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 542/567] idpf: replace flow scheduling buffer ring with buffer pool Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 543/567] idpf: stop Tx if there are insufficient buffer resources Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 544/567] idpf: remove obsolete stashing code Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 545/567] hrtimers: Make hrtimer_update_function() less expensive Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 546/567] gve: defer interrupt enabling until NAPI registration Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 547/567] ASoC: renesas: rz-ssi: Fix channel swap issue in full duplex mode Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 548/567] block: handle zone management operations completions Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 549/567] soundwire: stream: extend sdw_alloc_stream() to take type parameter Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 550/567] ASoC: qcom: sdw: fix memory leak for sdw_stream_runtime Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 551/567] ASoC: renesas: rz-ssi: Fix rz_ssi_priv::hw_params_cache::sample_width Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 552/567] PCI: brcmstb: Reuse pcie_cfg_data structure Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 553/567] PCI: brcmstb: Set MLW based on "num-lanes" DT property if present Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 554/567] PCI: brcmstb: Fix disabling L0s capability Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 555/567] mm/balloon_compaction: we cannot have isolated pages in the balloon list Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 556/567] mm/balloon_compaction: convert balloon_page_delete() to balloon_page_finalize() Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 557/567] powerpc/pseries/cmm: adjust BALLOON_MIGRATE when migrating pages Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 558/567] media: mediatek: vcodec: Use spinlock for context list protection lock Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 559/567] media: amphion: Add a frame flush mode for decoder Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 560/567] media: amphion: Make some vpu_v4l2 functions static Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 561/567] media: amphion: Remove vpu_vb_is_codecconfig Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 562/567] vfio/pci: Disable qword access to the PCI ROM bar Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 563/567] mm/damon/tests/core-kunit: handle alloc failures on damon_test_split_regions_of() Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 564/567] mm/damon/tests/core-kunit: handle alloc failres in damon_test_new_filter() Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 565/567] mm/damon/tests/vaddr-kunit: handle alloc failures on damon_do_test_apply_three_regions() Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 566/567] iomap: allocate s_dio_done_wq for async reads as well Greg Kroah-Hartman
2026-01-06 17:05 ` [PATCH 6.12 567/567] block: fix NULL pointer dereference in blk_zone_reset_all_bio_endio() Greg Kroah-Hartman
2026-01-06 19:22 ` [PATCH 6.12 000/567] 6.12.64-rc1 review Brett A C Sheffield
2026-01-06 22:00 ` Pavel Machek
2026-01-06 22:56 ` Shuah Khan
2026-01-07 0:08 ` Peter Schneider
2026-01-07 0:35 ` Florian Fainelli
2026-01-07 10:28 ` Ron Economos
2026-01-07 11:49 ` Mark Brown
2026-01-07 11:53 ` Francesco Dolcini
2026-01-07 12:32 ` Jeffrin Thalakkottoor
2026-01-07 13:44 ` Harshit Mogalapalli
2026-01-07 15:26 ` Miguel Ojeda
2026-01-07 20:05 ` Brett Mastbergen
2026-01-07 20:13 ` Jon Hunter
2026-01-07 20:43 ` Hardik Garg
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260106170510.584316139@linuxfoundation.org \
--to=gregkh@linuxfoundation.org \
--cc=andriy.shevchenko@linux.intel.com \
--cc=hdegoede@redhat.com \
--cc=mika.westerberg@linux.intel.com \
--cc=patches@lists.linux.dev \
--cc=sashal@kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox