Merge branch 'x86/cpu' from tip
[cascardo/linux.git] / drivers / powercap / intel_rapl.c
index 8fad0a7..2e8f2be 100644 (file)
 
 #include <asm/processor.h>
 #include <asm/cpu_device_id.h>
+#include <asm/intel-family.h>
+
+/* Local defines */
+#define MSR_PLATFORM_POWER_LIMIT       0x0000065C
 
 /* bitmasks for RAPL MSRs, used by primitive access functions */
 #define ENERGY_STATUS_MASK      0xffffffff
@@ -86,6 +90,7 @@ enum rapl_domain_type {
        RAPL_DOMAIN_PP0, /* core power plane */
        RAPL_DOMAIN_PP1, /* graphics uncore */
        RAPL_DOMAIN_DRAM,/* DRAM control_type */
+       RAPL_DOMAIN_PLATFORM, /* PSys control_type */
        RAPL_DOMAIN_MAX,
 };
 
@@ -251,9 +256,11 @@ static const char * const rapl_domain_names[] = {
        "core",
        "uncore",
        "dram",
+       "psys",
 };
 
 static struct powercap_control_type *control_type; /* PowerCap Controller */
+static struct rapl_domain *platform_rapl_domain; /* Platform (PSys) domain */
 
 /* caller to ensure CPU hotplug lock is held */
 static struct rapl_package *find_package_by_id(int id)
@@ -409,6 +416,14 @@ static const struct powercap_zone_ops zone_ops[] = {
                .set_enable = set_domain_enable,
                .get_enable = get_domain_enable,
        },
+       /* RAPL_DOMAIN_PLATFORM */
+       {
+               .get_energy_uj = get_energy_counter,
+               .get_max_energy_range_uj = get_max_energy_counter,
+               .release = release_zone,
+               .set_enable = set_domain_enable,
+               .get_enable = get_domain_enable,
+       },
 };
 
 static int set_power_limit(struct powercap_zone *power_zone, int id,
@@ -1082,25 +1097,34 @@ static const struct rapl_defaults rapl_defaults_cht = {
                }
 
 static const struct x86_cpu_id rapl_ids[] __initconst = {
-       RAPL_CPU(0x2a, rapl_defaults_core),/* Sandy Bridge */
-       RAPL_CPU(0x2d, rapl_defaults_core),/* Sandy Bridge EP */
-       RAPL_CPU(0x37, rapl_defaults_byt),/* Valleyview */
-       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_hsw_server),/* Haswell servers */
-       RAPL_CPU(0x4f, rapl_defaults_hsw_server),/* Broadwell servers */
-       RAPL_CPU(0x45, rapl_defaults_core),/* Haswell ULT */
-       RAPL_CPU(0x46, rapl_defaults_core),/* Haswell */
-       RAPL_CPU(0x47, rapl_defaults_core),/* Broadwell-H */
-       RAPL_CPU(0x4E, rapl_defaults_core),/* Skylake */
-       RAPL_CPU(0x4C, rapl_defaults_cht),/* Braswell/Cherryview */
-       RAPL_CPU(0x4A, rapl_defaults_tng),/* Tangier */
-       RAPL_CPU(0x56, rapl_defaults_core),/* Future Xeon */
-       RAPL_CPU(0x5A, rapl_defaults_ann),/* Annidale */
-       RAPL_CPU(0X5C, rapl_defaults_core),/* Broxton */
-       RAPL_CPU(0x5E, rapl_defaults_core),/* Skylake-H/S */
-       RAPL_CPU(0x57, rapl_defaults_hsw_server),/* Knights Landing */
+       RAPL_CPU(INTEL_FAM6_SANDYBRIDGE,        rapl_defaults_core),
+       RAPL_CPU(INTEL_FAM6_SANDYBRIDGE_X,      rapl_defaults_core),
+
+       RAPL_CPU(INTEL_FAM6_IVYBRIDGE,          rapl_defaults_core),
+
+       RAPL_CPU(INTEL_FAM6_HASWELL_CORE,       rapl_defaults_core),
+       RAPL_CPU(INTEL_FAM6_HASWELL_ULT,        rapl_defaults_core),
+       RAPL_CPU(INTEL_FAM6_HASWELL_GT3E,       rapl_defaults_core),
+       RAPL_CPU(INTEL_FAM6_HASWELL_X,          rapl_defaults_hsw_server),
+
+       RAPL_CPU(INTEL_FAM6_BROADWELL_CORE,     rapl_defaults_core),
+       RAPL_CPU(INTEL_FAM6_BROADWELL_GT3E,     rapl_defaults_core),
+       RAPL_CPU(INTEL_FAM6_BROADWELL_XEON_D,   rapl_defaults_core),
+       RAPL_CPU(INTEL_FAM6_BROADWELL_X,        rapl_defaults_hsw_server),
+
+       RAPL_CPU(INTEL_FAM6_SKYLAKE_DESKTOP,    rapl_defaults_core),
+       RAPL_CPU(INTEL_FAM6_SKYLAKE_MOBILE,     rapl_defaults_core),
+       RAPL_CPU(INTEL_FAM6_SKYLAKE_X,          rapl_defaults_hsw_server),
+       RAPL_CPU(INTEL_FAM6_KABYLAKE_MOBILE,    rapl_defaults_core),
+       RAPL_CPU(INTEL_FAM6_KABYLAKE_DESKTOP,   rapl_defaults_core),
+
+       RAPL_CPU(INTEL_FAM6_ATOM_SILVERMONT1,   rapl_defaults_byt),
+       RAPL_CPU(INTEL_FAM6_ATOM_AIRMONT,       rapl_defaults_cht),
+       RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD1,   rapl_defaults_tng),
+       RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD2,   rapl_defaults_ann),
+       RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT,      rapl_defaults_core),
+
+       RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL,       rapl_defaults_hsw_server),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, rapl_ids);
@@ -1160,6 +1184,13 @@ static int rapl_unregister_powercap(void)
                        powercap_unregister_zone(control_type,
                                                &rd_package->power_zone);
        }
+
+       if (platform_rapl_domain) {
+               powercap_unregister_zone(control_type,
+                                        &platform_rapl_domain->power_zone);
+               kfree(platform_rapl_domain);
+       }
+
        powercap_unregister_control_type(control_type);
 
        return 0;
@@ -1239,6 +1270,47 @@ err_cleanup:
        return ret;
 }
 
+static int rapl_register_psys(void)
+{
+       struct rapl_domain *rd;
+       struct powercap_zone *power_zone;
+       u64 val;
+
+       if (rdmsrl_safe_on_cpu(0, MSR_PLATFORM_ENERGY_STATUS, &val) || !val)
+               return -ENODEV;
+
+       if (rdmsrl_safe_on_cpu(0, MSR_PLATFORM_POWER_LIMIT, &val) || !val)
+               return -ENODEV;
+
+       rd = kzalloc(sizeof(*rd), GFP_KERNEL);
+       if (!rd)
+               return -ENOMEM;
+
+       rd->name = rapl_domain_names[RAPL_DOMAIN_PLATFORM];
+       rd->id = RAPL_DOMAIN_PLATFORM;
+       rd->msrs[0] = MSR_PLATFORM_POWER_LIMIT;
+       rd->msrs[1] = MSR_PLATFORM_ENERGY_STATUS;
+       rd->rpl[0].prim_id = PL1_ENABLE;
+       rd->rpl[0].name = pl1_name;
+       rd->rpl[1].prim_id = PL2_ENABLE;
+       rd->rpl[1].name = pl2_name;
+       rd->rp = find_package_by_id(0);
+
+       power_zone = powercap_register_zone(&rd->power_zone, control_type,
+                                           "psys", NULL,
+                                           &zone_ops[RAPL_DOMAIN_PLATFORM],
+                                           2, &constraint_ops);
+
+       if (IS_ERR(power_zone)) {
+               kfree(rd);
+               return PTR_ERR(power_zone);
+       }
+
+       platform_rapl_domain = rd;
+
+       return 0;
+}
+
 static int rapl_register_powercap(void)
 {
        struct rapl_domain *rd;
@@ -1255,6 +1327,10 @@ static int rapl_register_powercap(void)
        list_for_each_entry(rp, &rapl_packages, plist)
                if (rapl_package_register_powercap(rp))
                        goto err_cleanup_package;
+
+       /* Don't bail out if PSys is not supported */
+       rapl_register_psys();
+
        return ret;
 
 err_cleanup_package:
@@ -1289,6 +1365,9 @@ static int rapl_check_domain(int cpu, int domain)
        case RAPL_DOMAIN_DRAM:
                msr = MSR_DRAM_ENERGY_STATUS;
                break;
+       case RAPL_DOMAIN_PLATFORM:
+               /* PSYS(PLATFORM) is not a CPU domain, so avoid printng error */
+               return -EINVAL;
        default:
                pr_err("invalid domain id %d\n", domain);
                return -EINVAL;