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

Commit 3d7a6db5 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 (PCI/ACPI resources and at91
  RTC locking), a stable-candidate powercap RAPL driver fix and two ARM
  cpuidle fixes (one stable-candidate too).

  Specifics:

   - Revert a recent PCI commit related to IRQ resources management that
     introduced a regression for drivers attempting to bind to devices
     whose previous drivers did not balance pci_enable_device() and
     pci_disable_device() as expected (Rafael J Wysocki).

   - Fix a deadlock in at91_rtc_interrupt() introduced by a typo in a
     recent commit related to wakeup interrupt handling (Dan Carpenter).

   - Allow the power capping RAPL (Running-Average Power Limit) driver
     to use different energy units for domains within one CPU package
     which is necessary to handle Intel Haswell EP processors correctly
     (Jacob Pan).

   - Improve the cpuidle mvebu driver's handling of Armada XP SoCs by
     updating the target residency and exit latency numbers for those
     chips (Sebastien Rannou).

   - Prevent the cpuidle mvebu driver from calling cpu_pm_enter() twice
     in a row before cpu_pm_exit() is called on the same CPU which
     breaks the core's assumptions regarding the usage of those
     functions (Gregory Clement)"

* tag 'pm+acpi-4.0-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  Revert "x86/PCI: Refine the way to release PCI IRQ resources"
  rtc: at91rm9200: double locking bug in at91_rtc_interrupt()
  powercap / RAPL: handle domains with different energy units
  cpuidle: mvebu: Update cpuidle thresholds for Armada XP SOCs
  cpuidle: mvebu: Fix the CPU PM notifier usage
parents 97448d5b 9c86286a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ extern raw_spinlock_t pci_config_lock;
extern int (*pcibios_enable_irq)(struct pci_dev *dev);
extern void (*pcibios_disable_irq)(struct pci_dev *dev);

extern bool mp_should_keep_irq(struct device *dev);

struct pci_raw_ops {
	int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
						int reg, int len, u32 *val);
+6 −28
Original line number Diff line number Diff line
@@ -513,31 +513,6 @@ void __init pcibios_set_cache_line_size(void)
	}
}

/*
 * Some device drivers assume dev->irq won't change after calling
 * pci_disable_device(). So delay releasing of IRQ resource to driver
 * unbinding time. Otherwise it will break PM subsystem and drivers
 * like xen-pciback etc.
 */
static int pci_irq_notifier(struct notifier_block *nb, unsigned long action,
			    void *data)
{
	struct pci_dev *dev = to_pci_dev(data);

	if (action != BUS_NOTIFY_UNBOUND_DRIVER)
		return NOTIFY_DONE;

	if (pcibios_disable_irq)
		pcibios_disable_irq(dev);

	return NOTIFY_OK;
}

static struct notifier_block pci_irq_nb = {
	.notifier_call = pci_irq_notifier,
	.priority = INT_MIN,
};

int __init pcibios_init(void)
{
	if (!raw_pci_ops) {
@@ -550,9 +525,6 @@ int __init pcibios_init(void)

	if (pci_bf_sort >= pci_force_bf)
		pci_sort_breadthfirst();

	bus_register_notifier(&pci_bus_type, &pci_irq_nb);

	return 0;
}

@@ -711,6 +683,12 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
	return 0;
}

void pcibios_disable_device (struct pci_dev *dev)
{
	if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
		pcibios_disable_irq(dev);
}

int pci_ext_cfg_avail(void)
{
	if (raw_pci_ext_ops)
+2 −2
Original line number Diff line number Diff line
@@ -234,10 +234,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)

static void intel_mid_pci_irq_disable(struct pci_dev *dev)
{
	if (dev->irq_managed && dev->irq > 0) {
	if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
	    dev->irq > 0) {
		mp_unmap_irq(dev->irq);
		dev->irq_managed = 0;
		dev->irq = 0;
	}
}

+14 −1
Original line number Diff line number Diff line
@@ -1256,9 +1256,22 @@ static int pirq_enable_irq(struct pci_dev *dev)
	return 0;
}

bool mp_should_keep_irq(struct device *dev)
{
	if (dev->power.is_prepared)
		return true;
#ifdef CONFIG_PM
	if (dev->power.runtime_status == RPM_SUSPENDING)
		return true;
#endif

	return false;
}

static void pirq_disable_irq(struct pci_dev *dev)
{
	if (io_apic_assign_pci_irqs && dev->irq_managed && dev->irq) {
	if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
	    dev->irq_managed && dev->irq) {
		mp_unmap_irq(dev->irq);
		dev->irq = 0;
		dev->irq_managed = 0;
+8 −1
Original line number Diff line number Diff line
@@ -485,6 +485,14 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
	if (!pin || !dev->irq_managed || dev->irq <= 0)
		return;

	/* Keep IOAPIC pin configuration when suspending */
	if (dev->dev.power.is_prepared)
		return;
#ifdef	CONFIG_PM
	if (dev->dev.power.runtime_status == RPM_SUSPENDING)
		return;
#endif

	entry = acpi_pci_irq_lookup(dev, pin);
	if (!entry)
		return;
@@ -505,6 +513,5 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
	if (gsi >= 0) {
		acpi_unregister_gsi(gsi);
		dev->irq_managed = 0;
		dev->irq = 0;
	}
}
Loading