Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 39ed853a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull power management and ACPI fixes from Rafael Wysocki:
 "These are fixes for recent regressions (ACPI resources management,
  suspend-to-idle), stable-candidate fixes (ACPI backlight), fixes
  related to the wakeup IRQ management changes made in v3.18, other
  fixes (suspend-to-idle, cpufreq ppc driver) and a couple of cleanups
  (suspend-to-idle, generic power domains, ACPI backlight).

  Specifics:

   - Fix ACPI resources management problems introduced by the recent
     rework of the code in question (Jiang Liu) and a build issue
     introduced by those changes (Joachim Nilsson).

   - Fix a recent suspend-to-idle regression on systems where entering
     idle states causes local timers to stop, prevent suspend-to-idle
     from crashing in restricted configurations (no cpuidle driver,
     cpuidle disabled etc.) and clean up the idle loop somewhat while at
     it (Rafael J Wysocki).

   - Fix build problem in the cpufreq ppc driver (Geert Uytterhoeven).

   - Allow the ACPI backlight driver module to be loaded if ACPI is
     disabled which helps the i915 driver in those configurations
     (stable-candidate) and change the code to help debug unusual use
     cases (Chris Wilson).

   - Wakeup IRQ management changes in v3.18 caused some drivers on the
     at91 platform to trigger a warning from the IRQ core related to an
     unexpected combination of interrupt action handler flags.  However,
     on at91 a timer IRQ is shared with some other devices (including
     system wakeup ones) and that leads to the unusual combination of
     flags in question.

     To make it possible to avoid the warning introduce a new interrupt
     action handler flag (which can be used by drivers to indicate the
     special case to the core) and rework the problematic at91 drivers
     to use it and work as expected during system suspend/resume.  From
     Boris Brezillon, Rafael J Wysocki and Mark Rutland.

   - Clean up the generic power domains subsystem's debugfs interface
     (Kevin Hilman)"

* tag 'pm+acpi-4.0-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  genirq / PM: describe IRQF_COND_SUSPEND
  tty: serial: atmel: rework interrupt and wakeup handling
  watchdog: at91sam9: request the irq with IRQF_NO_SUSPEND
  cpuidle / sleep: Use broadcast timer for states that stop local timer
  clk: at91: implement suspend/resume for the PMC irqchip
  rtc: at91rm9200: rework wakeup and interrupt handling
  rtc: at91sam9: rework wakeup and interrupt handling
  PM / wakeup: export pm_system_wakeup symbol
  genirq / PM: Add flag for shared NO_SUSPEND interrupt lines
  ACPI / video: Propagate the error code for acpi_video_register
  ACPI / video: Load the module even if ACPI is disabled
  PM / Domains: cleanup: rename gpd -> genpd in debugfs interface
  cpufreq: ppc: Add missing #include <asm/smp.h>
  x86/PCI/ACPI: Relax ACPI resource descriptor checks to work around BIOS bugs
  x86/PCI/ACPI: Ignore resources consumed by host bridge itself
  cpuidle: Clean up fallback handling in cpuidle_idle_call()
  cpuidle / sleep: Do sanity checks in cpuidle_enter_freeze() too
  idle / sleep: Avoid excessive disabling and enabling interrupts
  PCI: versatile: Update for list_for_each_entry() API change
  genirq / PM: better describe IRQF_NO_SUSPEND semantics
parents 7c5bde7a e178e7d6
Loading
Loading
Loading
Loading
+17 −5
Original line number Diff line number Diff line
@@ -40,8 +40,10 @@ but also to IPIs and to some other special-purpose interrupts.

The IRQF_NO_SUSPEND flag is used to indicate that to the IRQ subsystem when
requesting a special-purpose interrupt.  It causes suspend_device_irqs() to
leave the corresponding IRQ enabled so as to allow the interrupt to work all
the time as expected.
leave the corresponding IRQ enabled so as to allow the interrupt to work as
expected during the suspend-resume cycle, but does not guarantee that the
interrupt will wake the system from a suspended state -- for such cases it is
necessary to use enable_irq_wake().

Note that the IRQF_NO_SUSPEND flag affects the entire IRQ and not just one
user of it.  Thus, if the IRQ is shared, all of the interrupt handlers installed
@@ -110,8 +112,9 @@ any special interrupt handling logic for it to work.
IRQF_NO_SUSPEND and enable_irq_wake()
-------------------------------------

There are no valid reasons to use both enable_irq_wake() and the IRQF_NO_SUSPEND
flag on the same IRQ.
There are very few valid reasons to use both enable_irq_wake() and the
IRQF_NO_SUSPEND flag on the same IRQ, and it is never valid to use both for the
same device.

First of all, if the IRQ is not shared, the rules for handling IRQF_NO_SUSPEND
interrupts (interrupt handlers are invoked after suspend_device_irqs()) are
@@ -120,4 +123,13 @@ handlers are not invoked after suspend_device_irqs()).

Second, both enable_irq_wake() and IRQF_NO_SUSPEND apply to entire IRQs and not
to individual interrupt handlers, so sharing an IRQ between a system wakeup
interrupt source and an IRQF_NO_SUSPEND interrupt source does not make sense.
interrupt source and an IRQF_NO_SUSPEND interrupt source does not generally
make sense.

In rare cases an IRQ can be shared between a wakeup device driver and an
IRQF_NO_SUSPEND user. In order for this to be safe, the wakeup device driver
must be able to discern spurious IRQs from genuine wakeup events (signalling
the latter to the core with pm_system_wakeup()), must use enable_irq_wake() to
ensure that the IRQ will function as a wakeup source, and must request the IRQ
with IRQF_COND_SUSPEND to tell the core that it meets these requirements. If
these requirements are not met, it is not valid to use IRQF_COND_SUSPEND.
+8 −3
Original line number Diff line number Diff line
@@ -331,7 +331,7 @@ static void probe_pci_root_info(struct pci_root_info *info,
				struct list_head *list)
{
	int ret;
	struct resource_entry *entry;
	struct resource_entry *entry, *tmp;

	sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
	info->bridge = device;
@@ -345,9 +345,14 @@ static void probe_pci_root_info(struct pci_root_info *info,
		dev_dbg(&device->dev,
			"no IO and memory resources present in _CRS\n");
	else
		resource_list_for_each_entry(entry, list)
		resource_list_for_each_entry_safe(entry, tmp, list) {
			if ((entry->res->flags & IORESOURCE_WINDOW) == 0 ||
			    (entry->res->flags & IORESOURCE_DISABLED))
				resource_list_destroy_entry(entry);
			else
				entry->res->name = info->name;
		}
}

struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
{
+3 −1
Original line number Diff line number Diff line
@@ -42,8 +42,10 @@ static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
	 * CHECKME: len might be required to check versus a minimum
	 * length as well. 1 for io is fine, but for memory it does
	 * not make any sense at all.
	 * Note: some BIOSes report incorrect length for ACPI address space
	 * descriptor, so remove check of 'reslen == len' to avoid regression.
	 */
	if (len && reslen && reslen == len && start <= end)
	if (len && reslen && start <= end)
		return true;

	pr_debug("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
+16 −4
Original line number Diff line number Diff line
@@ -2110,7 +2110,8 @@ static int __init intel_opregion_present(void)

int acpi_video_register(void)
{
	int result = 0;
	int ret;

	if (register_count) {
		/*
		 * if the function of acpi_video_register is already called,
@@ -2122,9 +2123,9 @@ int acpi_video_register(void)
	mutex_init(&video_list_lock);
	INIT_LIST_HEAD(&video_bus_head);

	result = acpi_bus_register_driver(&acpi_video_bus);
	if (result < 0)
		return -ENODEV;
	ret = acpi_bus_register_driver(&acpi_video_bus);
	if (ret)
		return ret;

	/*
	 * When the acpi_video_bus is loaded successfully, increase
@@ -2176,6 +2177,17 @@ EXPORT_SYMBOL(acpi_video_unregister_backlight);

static int __init acpi_video_init(void)
{
	/*
	 * Let the module load even if ACPI is disabled (e.g. due to
	 * a broken BIOS) so that i915.ko can still be loaded on such
	 * old systems without an AcpiOpRegion.
	 *
	 * acpi_video_register() will report -ENODEV later as well due
	 * to acpi_disabled when i915.ko tries to register itself afterwards.
	 */
	if (acpi_disabled)
		return 0;

	dmi_check_system(video_dmi_table);

	if (intel_opregion_present())
+12 −12
Original line number Diff line number Diff line
@@ -2242,7 +2242,7 @@ static void rtpm_status_str(struct seq_file *s, struct device *dev)
}

static int pm_genpd_summary_one(struct seq_file *s,
		struct generic_pm_domain *gpd)
				struct generic_pm_domain *genpd)
{
	static const char * const status_lookup[] = {
		[GPD_STATE_ACTIVE] = "on",
@@ -2256,26 +2256,26 @@ static int pm_genpd_summary_one(struct seq_file *s,
	struct gpd_link *link;
	int ret;

	ret = mutex_lock_interruptible(&gpd->lock);
	ret = mutex_lock_interruptible(&genpd->lock);
	if (ret)
		return -ERESTARTSYS;

	if (WARN_ON(gpd->status >= ARRAY_SIZE(status_lookup)))
	if (WARN_ON(genpd->status >= ARRAY_SIZE(status_lookup)))
		goto exit;
	seq_printf(s, "%-30s  %-15s  ", gpd->name, status_lookup[gpd->status]);
	seq_printf(s, "%-30s  %-15s  ", genpd->name, status_lookup[genpd->status]);

	/*
	 * Modifications on the list require holding locks on both
	 * master and slave, so we are safe.
	 * Also gpd->name is immutable.
	 * Also genpd->name is immutable.
	 */
	list_for_each_entry(link, &gpd->master_links, master_node) {
	list_for_each_entry(link, &genpd->master_links, master_node) {
		seq_printf(s, "%s", link->slave->name);
		if (!list_is_last(&link->master_node, &gpd->master_links))
		if (!list_is_last(&link->master_node, &genpd->master_links))
			seq_puts(s, ", ");
	}

	list_for_each_entry(pm_data, &gpd->dev_list, list_node) {
	list_for_each_entry(pm_data, &genpd->dev_list, list_node) {
		kobj_path = kobject_get_path(&pm_data->dev->kobj, GFP_KERNEL);
		if (kobj_path == NULL)
			continue;
@@ -2287,14 +2287,14 @@ static int pm_genpd_summary_one(struct seq_file *s,

	seq_puts(s, "\n");
exit:
	mutex_unlock(&gpd->lock);
	mutex_unlock(&genpd->lock);

	return 0;
}

static int pm_genpd_summary_show(struct seq_file *s, void *data)
{
	struct generic_pm_domain *gpd;
	struct generic_pm_domain *genpd;
	int ret = 0;

	seq_puts(s, "    domain                      status         slaves\n");
@@ -2305,8 +2305,8 @@ static int pm_genpd_summary_show(struct seq_file *s, void *data)
	if (ret)
		return -ERESTARTSYS;

	list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
		ret = pm_genpd_summary_one(s, gpd);
	list_for_each_entry(genpd, &gpd_list, gpd_list_node) {
		ret = pm_genpd_summary_one(s, genpd);
		if (ret)
			break;
	}
Loading