]> Git Repo - linux.git/commitdiff
Merge tag 'acpi-6.1-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
authorLinus Torvalds <[email protected]>
Mon, 10 Oct 2022 20:28:06 +0000 (13:28 -0700)
committerLinus Torvalds <[email protected]>
Mon, 10 Oct 2022 20:28:06 +0000 (13:28 -0700)
Pull more ACPI updates from Rafael Wysocki:
 "These fix two issues, in APEI and in the int3472 driver, clean up the
  ACPI thermal driver, add ACPI support for non-GPE system wakeup events
  and make the system reboot code use the S5 (system off) state by
  default.

  Specifics:

   - Fix ACPI device object reference counting in (recently updated)
     skl_int3472_fill_clk_pdata() (Andy Shevchenko).

   - Fix a memory leak in APEI by avoiding to add a task_work to kernel
     threads running when an asynchronous error is detected (Shuai Xue).

   - Add ACPI support for handling system wakeups via GPIO wake capable
     IRQs in addition to GPEs (Raul E Rangel).

   - Make the system reboot code put ACPI-enabled systems into the S5
     (system off) state which is necessary for some platforms to work as
     expected (Kai-Heng Feng).

   - Make the white space usage in the ACPI thermal driver more
     consistent and drop redundant code from it (Rafael Wysocki)"

* tag 'acpi-6.1-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  ACPI: thermal: Drop some redundant code
  ACPI: thermal: Drop redundant parens from expressions
  ACPI: thermal: Use white space more consistently
  platform/x86: int3472: Don't leak reference on error
  ACPI: APEI: do not add task_work to kernel thread to avoid memory leak
  PM: ACPI: reboot: Reinstate S5 for reboot
  kernel/reboot: Add SYS_OFF_MODE_RESTART_PREPARE mode
  ACPI: PM: Take wake IRQ into consideration when entering suspend-to-idle
  i2c: acpi: Use ACPI wake capability bit to set wake_irq
  ACPI: resources: Add wake_capable parameter to acpi_dev_irq_flags
  gpiolib: acpi: Add wake_capable variants of acpi_dev_gpio_irq_get

1  2 
drivers/gpio/gpiolib-acpi.c
drivers/i2c/i2c-core-acpi.c
drivers/i2c/i2c-core-base.c
drivers/platform/x86/intel/int3472/tps68470.c
include/linux/acpi.h
include/linux/ioport.h

index 285ecbf107c959788326d5310b430d5bde3d8038,1f2ade475b36cb2e92eb2a2d7ea354fe57b059b8..a7d2358736fe761bfdd08bc30f9c8b611f80fdb2
@@@ -32,16 -32,9 +32,16 @@@ 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;
  };
  
  /**
@@@ -324,15 -317,14 +324,15 @@@ static struct gpio_desc *acpi_request_o
        return desc;
  }
  
 -static bool acpi_gpio_in_ignore_list(const char *controller_in, unsigned int pin_in)
 +static bool acpi_gpio_in_ignore_list(const char *ignore_list, const char *controller_in,
 +                                   unsigned int pin_in)
  {
        const char *controller, *pin_str;
        unsigned int pin;
        char *endp;
        int len;
  
 -      controller = ignore_wake;
 +      controller = ignore_list;
        while (controller) {
                pin_str = strchr(controller, '@');
                if (!pin_str)
  
        return false;
  err:
 -      pr_err_once("Error: Invalid value for gpiolib_acpi.ignore_wake: %s\n", ignore_wake);
 +      pr_err_once("Error: Invalid value for gpiolib_acpi.ignore_...: %s\n", ignore_list);
        return false;
  }
  
@@@ -368,7 -360,7 +368,7 @@@ static bool acpi_gpio_irq_is_wake(struc
        if (agpio->wake_capable != ACPI_WAKE_CAPABLE)
                return false;
  
 -      if (acpi_gpio_in_ignore_list(dev_name(parent), pin)) {
 +      if (acpi_gpio_in_ignore_list(ignore_wake, dev_name(parent), pin)) {
                dev_info(parent, "Ignoring wakeup on pin %u\n", pin);
                return false;
        }
@@@ -435,11 -427,6 +435,11 @@@ static acpi_status acpi_gpiochip_alloc_
                goto fail_unlock_irq;
        }
  
 +      if (acpi_gpio_in_ignore_list(ignore_interrupt, dev_name(chip->parent), pin)) {
 +              dev_info(chip->parent, "Ignoring interrupt on pin %u\n", pin);
 +              return AE_OK;
 +      }
 +
        event = kzalloc(sizeof(*event), GFP_KERNEL);
        if (!event)
                goto fail_unlock_irq;
@@@ -754,6 -741,7 +754,7 @@@ static int acpi_populate_gpio_lookup(st
                lookup->info.pin_config = agpio->pin_config;
                lookup->info.debounce = agpio->debounce_timeout;
                lookup->info.gpioint = gpioint;
+               lookup->info.wake_capable = agpio->wake_capable == ACPI_WAKE_CAPABLE;
  
                /*
                 * Polarity and triggering are only specified for GpioInt
@@@ -1000,10 -988,11 +1001,11 @@@ struct gpio_desc *acpi_node_get_gpiod(s
  }
  
  /**
-  * acpi_dev_gpio_irq_get_by() - Find GpioInt and translate it to Linux IRQ number
+  * 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
   * @name: 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
   * The function takes optional @name parameter. If the resource has a property
   * name, then only those will be taken into account.
   *
+  * The GPIO is considered wake capable if the GpioInt resource specifies
+  * SharedAndWake or ExclusiveAndWake.
+  *
   * Return: Linux IRQ number (> %0) on success, negative errno on failure.
   */
- int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int index)
+ int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name, int index,
+                                 bool *wake_capable)
  {
        int idx, i;
        unsigned int irq_flags;
                                dev_dbg(&adev->dev, "IRQ %d already in use\n", irq);
                        }
  
+                       if (wake_capable)
+                               *wake_capable = info.wake_capable;
                        return irq;
                }
  
        }
        return -ENOENT;
  }
- EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_get_by);
+ EXPORT_SYMBOL_GPL(acpi_dev_gpio_irq_wake_get_by);
  
  static acpi_status
  acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
@@@ -1576,20 -1572,6 +1585,20 @@@ static const struct dmi_system_id gpiol
                        .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",
 +              },
 +      },
        {} /* Terminating entry */
  };
  
@@@ -1612,9 -1594,6 +1621,9 @@@ static int __init acpi_gpio_setup_param
        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;
  }
  
index da6568a20177bfef8093d26ec857389c47a289ab,f88386d732d2b39a51e357c66ba16d8df8b5638c..4dd777cc0c89f8a7675ae2d77b84c9761b6b8301
@@@ -26,7 -26,7 +26,7 @@@ struct gsb_buffer 
        union {
                u16     wdata;
                u8      bdata;
 -              u8      data[0];
 +              DECLARE_FLEX_ARRAY(u8, data);
        };
  } __packed;
  
@@@ -137,6 -137,11 +137,11 @@@ static const struct acpi_device_id i2c_
        {}
  };
  
+ struct i2c_acpi_irq_context {
+       int irq;
+       bool wake_capable;
+ };
  static int i2c_acpi_do_lookup(struct acpi_device *adev,
                              struct i2c_acpi_lookup *lookup)
  {
        return 0;
  }
  
- static int i2c_acpi_add_resource(struct acpi_resource *ares, void *data)
+ static int i2c_acpi_add_irq_resource(struct acpi_resource *ares, void *data)
  {
-       int *irq = data;
+       struct i2c_acpi_irq_context *irq_ctx = data;
        struct resource r;
  
-       if (*irq <= 0 && acpi_dev_resource_interrupt(ares, 0, &r))
-               *irq = i2c_dev_irq_from_resources(&r, 1);
+       if (irq_ctx->irq > 0)
+               return 1;
+       if (!acpi_dev_resource_interrupt(ares, 0, &r))
+               return 1;
+       irq_ctx->irq = i2c_dev_irq_from_resources(&r, 1);
+       irq_ctx->wake_capable = r.flags & IORESOURCE_IRQ_WAKECAPABLE;
  
        return 1; /* No need to add resource to the list */
  }
  /**
   * i2c_acpi_get_irq - get device IRQ number from ACPI
   * @client: Pointer to the I2C client device
+  * @wake_capable: Set to true if the IRQ is wake capable
   *
   * Find the IRQ number used by a specific client device.
   *
   * Return: The IRQ number or an error code.
   */
- int i2c_acpi_get_irq(struct i2c_client *client)
+ int i2c_acpi_get_irq(struct i2c_client *client, bool *wake_capable)
  {
        struct acpi_device *adev = ACPI_COMPANION(&client->dev);
        struct list_head resource_list;
-       int irq = -ENOENT;
+       struct i2c_acpi_irq_context irq_ctx = {
+               .irq = -ENOENT,
+       };
        int ret;
  
        INIT_LIST_HEAD(&resource_list);
  
        ret = acpi_dev_get_resources(adev, &resource_list,
-                                    i2c_acpi_add_resource, &irq);
+                                    i2c_acpi_add_irq_resource, &irq_ctx);
        if (ret < 0)
                return ret;
  
        acpi_dev_free_resource_list(&resource_list);
  
-       if (irq == -ENOENT)
-               irq = acpi_dev_gpio_irq_get(adev, 0);
+       if (irq_ctx.irq == -ENOENT)
+               irq_ctx.irq = acpi_dev_gpio_irq_wake_get(adev, 0, &irq_ctx.wake_capable);
+       if (irq_ctx.irq < 0)
+               return irq_ctx.irq;
+       if (wake_capable)
+               *wake_capable = irq_ctx.wake_capable;
  
-       return irq;
+       return irq_ctx.irq;
  }
  
  static int i2c_acpi_get_info(struct acpi_device *adev,
index 8c7e3494ca5ffbde44698bca5ec29f42a85599da,fc4b85fb90b1b7bff38f576c293c87dc60fa8fa2..b4edf10e8fd06a575bb1e8f8f494b9a2839c54e7
@@@ -487,7 -487,11 +487,11 @@@ static int i2c_device_probe(struct devi
                        if (irq == -EINVAL || irq == -ENODATA)
                                irq = of_irq_get(dev->of_node, 0);
                } else if (ACPI_COMPANION(dev)) {
-                       irq = i2c_acpi_get_irq(client);
+                       bool wake_capable;
+                       irq = i2c_acpi_get_irq(client, &wake_capable);
+                       if (irq > 0 && wake_capable)
+                               client->flags |= I2C_CLIENT_WAKE;
                }
                if (irq == -EPROBE_DEFER) {
                        status = irq;
@@@ -599,9 -603,13 +603,9 @@@ static void i2c_device_remove(struct de
  
        driver = to_i2c_driver(dev->driver);
        if (driver->remove) {
 -              int status;
 -
                dev_dbg(dev, "remove\n");
  
 -              status = driver->remove(client);
 -              if (status)
 -                      dev_warn(dev, "remove failed (%pe), will be ignored\n", ERR_PTR(status));
 +              driver->remove(client);
        }
  
        devres_release_group(&client->dev, client->devres_group_id);
index f83e9c393f31b3a356f9465803975b0bc293a09f,62093fde187f82c173080f296286c2ee6ea822fe..5b8d1a9620a5d06e0193fa16a9d832e17775dbc3
@@@ -128,15 -128,15 +128,15 @@@ skl_int3472_fill_clk_pdata(struct devic
        for_each_acpi_consumer_dev(adev, consumer) {
                sensor_name = devm_kasprintf(dev, GFP_KERNEL, I2C_DEV_NAME_FORMAT,
                                             acpi_dev_name(consumer));
-               if (!sensor_name)
+               if (!sensor_name) {
+                       acpi_dev_put(consumer);
                        return -ENOMEM;
+               }
  
                (*clk_pdata)->consumers[i].consumer_dev_name = sensor_name;
                i++;
        }
  
-       acpi_dev_put(consumer);
        return n_consumers;
  }
  
@@@ -227,7 -227,7 +227,7 @@@ static int skl_int3472_tps68470_probe(s
        return ret;
  }
  
 -static int skl_int3472_tps68470_remove(struct i2c_client *client)
 +static void skl_int3472_tps68470_remove(struct i2c_client *client)
  {
        const struct int3472_tps68470_board_data *board_data;
        int i;
                for (i = 0; i < board_data->n_gpiod_lookups; i++)
                        gpiod_remove_lookup_table(board_data->tps68470_gpio_lookup_tables[i]);
        }
 -
 -      return 0;
  }
  
  static const struct acpi_device_id int3472_device_id[] = {
diff --combined include/linux/acpi.h
index 729cff1ee3f8192fdcd97ce62c8080a5ae1124a1,83a4ffbbbfd6f8c340d10b85183088db7c61a1b8..3015235d65e317b4e53c93030fce27816f902b26
@@@ -498,7 -498,7 +498,7 @@@ bool acpi_dev_resource_address_space(st
                                     struct resource_win *win);
  bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
                                         struct resource_win *win);
- unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
+ unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable, u8 wake_capable);
  unsigned int acpi_dev_get_irq_type(int triggering, int polarity);
  bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
                                 struct resource *res);
@@@ -1083,7 -1083,6 +1083,7 @@@ acpi_status acpi_os_prepare_extended_sl
  struct acpi_s2idle_dev_ops {
        struct list_head list_node;
        void (*prepare)(void);
 +      void (*check)(void);
        void (*restore)(void);
  };
  int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg);
@@@ -1211,7 -1210,8 +1211,8 @@@ bool acpi_gpio_get_irq_resource(struct 
                                struct acpi_resource_gpio **agpio);
  bool acpi_gpio_get_io_resource(struct acpi_resource *ares,
                               struct acpi_resource_gpio **agpio);
- int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name, int index);
+ int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name, int index,
+                                 bool *wake_capable);
  #else
  static inline bool acpi_gpio_get_irq_resource(struct acpi_resource *ares,
                                              struct acpi_resource_gpio **agpio)
@@@ -1223,16 -1223,28 +1224,28 @@@ static inline bool acpi_gpio_get_io_res
  {
        return false;
  }
- static inline int acpi_dev_gpio_irq_get_by(struct acpi_device *adev,
-                                          const char *name, int index)
+ static inline int acpi_dev_gpio_irq_wake_get_by(struct acpi_device *adev, const char *name,
+                                               int index, bool *wake_capable)
  {
        return -ENXIO;
  }
  #endif
  
+ static inline int acpi_dev_gpio_irq_wake_get(struct acpi_device *adev, int index,
+                                            bool *wake_capable)
+ {
+       return acpi_dev_gpio_irq_wake_get_by(adev, NULL, index, wake_capable);
+ }
+ static inline int acpi_dev_gpio_irq_get_by(struct acpi_device *adev, const char *name,
+                                          int index)
+ {
+       return acpi_dev_gpio_irq_wake_get_by(adev, name, index, NULL);
+ }
  static inline int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
  {
-       return acpi_dev_gpio_irq_get_by(adev, NULL, index);
+       return acpi_dev_gpio_irq_wake_get_by(adev, NULL, index, NULL);
  }
  
  /* Device properties */
diff --combined include/linux/ioport.h
index 8a76dca9deee792339287e5c1a057818f1f8ad7d,3baeea4d903bfd1212083fce0d11913931b1e30a..27642ca15d932f22823ef7b0a003a2d1ca1333f8
@@@ -79,7 -79,8 +79,8 @@@ struct resource 
  #define IORESOURCE_IRQ_HIGHLEVEL      (1<<2)
  #define IORESOURCE_IRQ_LOWLEVEL               (1<<3)
  #define IORESOURCE_IRQ_SHAREABLE      (1<<4)
- #define IORESOURCE_IRQ_OPTIONAL       (1<<5)
+ #define IORESOURCE_IRQ_OPTIONAL               (1<<5)
+ #define IORESOURCE_IRQ_WAKECAPABLE    (1<<6)
  
  /* PnP DMA specific bits (IORESOURCE_BITS) */
  #define IORESOURCE_DMA_TYPE_MASK      (3<<0)
@@@ -172,11 -173,6 +173,11 @@@ enum 
  #define DEFINE_RES_MEM(_start, _size)                                 \
        DEFINE_RES_MEM_NAMED((_start), (_size), NULL)
  
 +#define DEFINE_RES_REG_NAMED(_start, _size, _name)                    \
 +      DEFINE_RES_NAMED((_start), (_size), (_name), IORESOURCE_REG)
 +#define DEFINE_RES_REG(_start, _size)                                 \
 +      DEFINE_RES_REG_NAMED((_start), (_size), NULL)
 +
  #define DEFINE_RES_IRQ_NAMED(_irq, _name)                             \
        DEFINE_RES_NAMED((_irq), 1, (_name), IORESOURCE_IRQ)
  #define DEFINE_RES_IRQ(_irq)                                          \
This page took 0.097342 seconds and 4 git commands to generate.