Merge branches 'pm-cpuidle', 'powercap', 'irq-pm' and 'acpi-resources'
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 20 Mar 2015 23:39:12 +0000 (00:39 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 20 Mar 2015 23:39:12 +0000 (00:39 +0100)
* pm-cpuidle:
  cpuidle: mvebu: Update cpuidle thresholds for Armada XP SOCs
  cpuidle: mvebu: Fix the CPU PM notifier usage

* powercap:
  powercap / RAPL: handle domains with different energy units

* irq-pm:
  rtc: at91rm9200: double locking bug in at91_rtc_interrupt()

* acpi-resources:
  Revert "x86/PCI: Refine the way to release PCI IRQ resources"

arch/x86/include/asm/pci_x86.h
arch/x86/pci/common.c
arch/x86/pci/intel_mid_pci.c
arch/x86/pci/irq.c
drivers/acpi/pci_irq.c
drivers/cpuidle/cpuidle-mvebu-v7.c
drivers/powercap/intel_rapl.c

index fa1195d..164e3f8 100644 (file)
@@ -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);
index 3d2612b..2fb3847 100644 (file)
@@ -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)
index efb8493..852aa4c 100644 (file)
@@ -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;
        }
 }
 
index e71b3db..5dc6ca5 100644 (file)
@@ -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;
index e7f718d..b1def41 100644 (file)
@@ -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;
        }
 }
index 38e6861..980151f 100644 (file)
@@ -37,11 +37,11 @@ static int mvebu_v7_enter_idle(struct cpuidle_device *dev,
                deepidle = true;
 
        ret = mvebu_v7_cpu_suspend(deepidle);
+       cpu_pm_exit();
+
        if (ret)
                return ret;
 
-       cpu_pm_exit();
-
        return index;
 }
 
@@ -50,17 +50,17 @@ static struct cpuidle_driver armadaxp_idle_driver = {
        .states[0]              = ARM_CPUIDLE_WFI_STATE,
        .states[1]              = {
                .enter                  = mvebu_v7_enter_idle,
-               .exit_latency           = 10,
+               .exit_latency           = 100,
                .power_usage            = 50,
-               .target_residency       = 100,
+               .target_residency       = 1000,
                .name                   = "MV CPU IDLE",
                .desc                   = "CPU power down",
        },
        .states[2]              = {
                .enter                  = mvebu_v7_enter_idle,
-               .exit_latency           = 100,
+               .exit_latency           = 1000,
                .power_usage            = 5,
-               .target_residency       = 1000,
+               .target_residency       = 10000,
                .flags                  = MVEBU_V7_FLAG_DEEP_IDLE,
                .name                   = "MV CPU DEEP IDLE",
                .desc                   = "CPU and L2 Fabric power down",
index 97b5e4e..63d4033 100644 (file)
@@ -73,7 +73,7 @@
 
 #define TIME_WINDOW_MAX_MSEC 40000
 #define TIME_WINDOW_MIN_MSEC 250
-
+#define ENERGY_UNIT_SCALE    1000 /* scale from driver unit to powercap unit */
 enum unit_type {
        ARBITRARY_UNIT, /* no translation */
        POWER_UNIT,
@@ -158,6 +158,7 @@ struct rapl_domain {
        struct rapl_power_limit rpl[NR_POWER_LIMITS];
        u64 attr_map; /* track capabilities */
        unsigned int state;
+       unsigned int domain_energy_unit;
        int package_id;
 };
 #define power_zone_to_rapl_domain(_zone) \
@@ -190,6 +191,7 @@ struct rapl_defaults {
        void (*set_floor_freq)(struct rapl_domain *rd, bool mode);
        u64 (*compute_time_window)(struct rapl_package *rp, u64 val,
                                bool to_raw);
+       unsigned int dram_domain_energy_unit;
 };
 static struct rapl_defaults *rapl_defaults;
 
@@ -227,7 +229,8 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
 static int rapl_write_data_raw(struct rapl_domain *rd,
                        enum rapl_primitives prim,
                        unsigned long long value);
-static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
+static u64 rapl_unit_xlate(struct rapl_domain *rd, int package,
+                       enum unit_type type, u64 value,
                        int to_raw);
 static void package_power_limit_irq_save(int package_id);
 
@@ -305,7 +308,9 @@ static int get_energy_counter(struct powercap_zone *power_zone, u64 *energy_raw)
 
 static int get_max_energy_counter(struct powercap_zone *pcd_dev, u64 *energy)
 {
-       *energy = rapl_unit_xlate(0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
+       struct rapl_domain *rd = power_zone_to_rapl_domain(pcd_dev);
+
+       *energy = rapl_unit_xlate(rd, 0, ENERGY_UNIT, ENERGY_STATUS_MASK, 0);
        return 0;
 }
 
@@ -639,6 +644,11 @@ static void rapl_init_domains(struct rapl_package *rp)
                        rd->msrs[4] = MSR_DRAM_POWER_INFO;
                        rd->rpl[0].prim_id = PL1_ENABLE;
                        rd->rpl[0].name = pl1_name;
+                       rd->domain_energy_unit =
+                               rapl_defaults->dram_domain_energy_unit;
+                       if (rd->domain_energy_unit)
+                               pr_info("DRAM domain energy unit %dpj\n",
+                                       rd->domain_energy_unit);
                        break;
                }
                if (mask) {
@@ -648,11 +658,13 @@ static void rapl_init_domains(struct rapl_package *rp)
        }
 }
 
-static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
+static u64 rapl_unit_xlate(struct rapl_domain *rd, int package,
+                       enum unit_type type, u64 value,
                        int to_raw)
 {
        u64 units = 1;
        struct rapl_package *rp;
+       u64 scale = 1;
 
        rp = find_package_by_id(package);
        if (!rp)
@@ -663,7 +675,12 @@ static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
                units = rp->power_unit;
                break;
        case ENERGY_UNIT:
-               units = rp->energy_unit;
+               scale = ENERGY_UNIT_SCALE;
+               /* per domain unit takes precedence */
+               if (rd && rd->domain_energy_unit)
+                       units = rd->domain_energy_unit;
+               else
+                       units = rp->energy_unit;
                break;
        case TIME_UNIT:
                return rapl_defaults->compute_time_window(rp, value, to_raw);
@@ -673,11 +690,11 @@ static u64 rapl_unit_xlate(int package, enum unit_type type, u64 value,
        };
 
        if (to_raw)
-               return div64_u64(value, units);
+               return div64_u64(value, units) * scale;
 
        value *= units;
 
-       return value;
+       return div64_u64(value, scale);
 }
 
 /* in the order of enum rapl_primitives */
@@ -773,7 +790,7 @@ static int rapl_read_data_raw(struct rapl_domain *rd,
        final = value & rp->mask;
        final = final >> rp->shift;
        if (xlate)
-               *data = rapl_unit_xlate(rd->package_id, rp->unit, final, 0);
+               *data = rapl_unit_xlate(rd, rd->package_id, rp->unit, final, 0);
        else
                *data = final;
 
@@ -799,7 +816,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
                        "failed to read msr 0x%x on cpu %d\n", msr, cpu);
                return -EIO;
        }
-       value = rapl_unit_xlate(rd->package_id, rp->unit, value, 1);
+       value = rapl_unit_xlate(rd, rd->package_id, rp->unit, value, 1);
        msr_val &= ~rp->mask;
        msr_val |= value << rp->shift;
        if (wrmsrl_safe_on_cpu(cpu, msr, msr_val)) {
@@ -818,7 +835,7 @@ static int rapl_write_data_raw(struct rapl_domain *rd,
  * calculate units differ on different CPUs.
  * We convert the units to below format based on CPUs.
  * i.e.
- * energy unit: microJoules : Represented in microJoules by default
+ * energy unit: picoJoules  : Represented in picoJoules by default
  * power unit : microWatts  : Represented in milliWatts by default
  * time unit  : microseconds: Represented in seconds by default
  */
@@ -834,7 +851,7 @@ static int rapl_check_unit_core(struct rapl_package *rp, int cpu)
        }
 
        value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
-       rp->energy_unit = 1000000 / (1 << value);
+       rp->energy_unit = ENERGY_UNIT_SCALE * 1000000 / (1 << value);
 
        value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
        rp->power_unit = 1000000 / (1 << value);
@@ -842,7 +859,7 @@ static int rapl_check_unit_core(struct rapl_package *rp, int cpu)
        value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
        rp->time_unit = 1000000 / (1 << value);
 
-       pr_debug("Core CPU package %d energy=%duJ, time=%dus, power=%duW\n",
+       pr_debug("Core CPU package %d energy=%dpJ, time=%dus, power=%duW\n",
                rp->id, rp->energy_unit, rp->time_unit, rp->power_unit);
 
        return 0;
@@ -859,7 +876,7 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
                return -ENODEV;
        }
        value = (msr_val & ENERGY_UNIT_MASK) >> ENERGY_UNIT_OFFSET;
-       rp->energy_unit = 1 << value;
+       rp->energy_unit = ENERGY_UNIT_SCALE * 1 << value;
 
        value = (msr_val & POWER_UNIT_MASK) >> POWER_UNIT_OFFSET;
        rp->power_unit = (1 << value) * 1000;
@@ -867,7 +884,7 @@ static int rapl_check_unit_atom(struct rapl_package *rp, int cpu)
        value = (msr_val & TIME_UNIT_MASK) >> TIME_UNIT_OFFSET;
        rp->time_unit = 1000000 / (1 << value);
 
-       pr_debug("Atom package %d energy=%duJ, time=%dus, power=%duW\n",
+       pr_debug("Atom package %d energy=%dpJ, time=%dus, power=%duW\n",
                rp->id, rp->energy_unit, rp->time_unit, rp->power_unit);
 
        return 0;
@@ -1017,6 +1034,13 @@ static const struct rapl_defaults rapl_defaults_core = {
        .compute_time_window = rapl_compute_time_window_core,
 };
 
+static const struct rapl_defaults rapl_defaults_hsw_server = {
+       .check_unit = rapl_check_unit_core,
+       .set_floor_freq = set_floor_freq_default,
+       .compute_time_window = rapl_compute_time_window_core,
+       .dram_domain_energy_unit = 15300,
+};
+
 static const struct rapl_defaults rapl_defaults_atom = {
        .check_unit = rapl_check_unit_atom,
        .set_floor_freq = set_floor_freq_atom,
@@ -1037,7 +1061,7 @@ static const struct x86_cpu_id rapl_ids[] = {
        RAPL_CPU(0x3a, rapl_defaults_core),/* Ivy Bridge */
        RAPL_CPU(0x3c, rapl_defaults_core),/* Haswell */
        RAPL_CPU(0x3d, rapl_defaults_core),/* Broadwell */
-       RAPL_CPU(0x3f, rapl_defaults_core),/* Haswell */
+       RAPL_CPU(0x3f, rapl_defaults_hsw_server),/* Haswell servers */
        RAPL_CPU(0x45, rapl_defaults_core),/* Haswell ULT */
        RAPL_CPU(0x4C, rapl_defaults_atom),/* Braswell */
        RAPL_CPU(0x4A, rapl_defaults_atom),/* Tangier */