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

Commit e717a62d authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'powercap'

* powercap:
  powercap / RAPL: Add support for Ivy Bridge server
  powercap / RAPL: add support for Denverton
  powercap / RAPL: handle missing MSRs
  powercap / RAPL: reduce message loglevel
parents e0a1e44c 7d188478
Loading
Loading
Loading
Loading
+82 −25
Original line number Diff line number Diff line
@@ -336,14 +336,14 @@ static int release_zone(struct powercap_zone *power_zone)

static int find_nr_power_limit(struct rapl_domain *rd)
{
	int i;
	int i, nr_pl = 0;

	for (i = 0; i < NR_POWER_LIMITS; i++) {
		if (rd->rpl[i].name == NULL)
			break;
		if (rd->rpl[i].name)
			nr_pl++;
	}

	return i;
	return nr_pl;
}

static int set_domain_enable(struct powercap_zone *power_zone, bool mode)
@@ -426,15 +426,38 @@ static const struct powercap_zone_ops zone_ops[] = {
	},
};

static int set_power_limit(struct powercap_zone *power_zone, int id,

/*
 * Constraint index used by powercap can be different than power limit (PL)
 * index in that some  PLs maybe missing due to non-existant MSRs. So we
 * need to convert here by finding the valid PLs only (name populated).
 */
static int contraint_to_pl(struct rapl_domain *rd, int cid)
{
	int i, j;

	for (i = 0, j = 0; i < NR_POWER_LIMITS; i++) {
		if ((rd->rpl[i].name) && j++ == cid) {
			pr_debug("%s: index %d\n", __func__, i);
			return i;
		}
	}

	return -EINVAL;
}

static int set_power_limit(struct powercap_zone *power_zone, int cid,
			u64 power_limit)
{
	struct rapl_domain *rd;
	struct rapl_package *rp;
	int ret = 0;
	int id;

	get_online_cpus();
	rd = power_zone_to_rapl_domain(power_zone);
	id = contraint_to_pl(rd, cid);

	rp = rd->rp;

	if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
@@ -461,16 +484,18 @@ static int set_power_limit(struct powercap_zone *power_zone, int id,
	return ret;
}

static int get_current_power_limit(struct powercap_zone *power_zone, int id,
static int get_current_power_limit(struct powercap_zone *power_zone, int cid,
					u64 *data)
{
	struct rapl_domain *rd;
	u64 val;
	int prim;
	int ret = 0;
	int id;

	get_online_cpus();
	rd = power_zone_to_rapl_domain(power_zone);
	id = contraint_to_pl(rd, cid);
	switch (rd->rpl[id].prim_id) {
	case PL1_ENABLE:
		prim = POWER_LIMIT1;
@@ -492,14 +517,17 @@ static int get_current_power_limit(struct powercap_zone *power_zone, int id,
	return ret;
}

static int set_time_window(struct powercap_zone *power_zone, int id,
static int set_time_window(struct powercap_zone *power_zone, int cid,
								u64 window)
{
	struct rapl_domain *rd;
	int ret = 0;
	int id;

	get_online_cpus();
	rd = power_zone_to_rapl_domain(power_zone);
	id = contraint_to_pl(rd, cid);

	switch (rd->rpl[id].prim_id) {
	case PL1_ENABLE:
		rapl_write_data_raw(rd, TIME_WINDOW1, window);
@@ -514,14 +542,17 @@ static int set_time_window(struct powercap_zone *power_zone, int id,
	return ret;
}

static int get_time_window(struct powercap_zone *power_zone, int id, u64 *data)
static int get_time_window(struct powercap_zone *power_zone, int cid, u64 *data)
{
	struct rapl_domain *rd;
	u64 val;
	int ret = 0;
	int id;

	get_online_cpus();
	rd = power_zone_to_rapl_domain(power_zone);
	id = contraint_to_pl(rd, cid);

	switch (rd->rpl[id].prim_id) {
	case PL1_ENABLE:
		ret = rapl_read_data_raw(rd, TIME_WINDOW1, true, &val);
@@ -540,15 +571,17 @@ static int get_time_window(struct powercap_zone *power_zone, int id, u64 *data)
	return ret;
}

static const char *get_constraint_name(struct powercap_zone *power_zone, int id)
static const char *get_constraint_name(struct powercap_zone *power_zone, int cid)
{
	struct rapl_power_limit *rpl;
	struct rapl_domain *rd;
	int id;

	rd = power_zone_to_rapl_domain(power_zone);
	rpl = (struct rapl_power_limit *) &rd->rpl[id];
	id = contraint_to_pl(rd, cid);
	if (id >= 0)
		return rd->rpl[id].name;

	return rpl->name;
	return NULL;
}


@@ -1101,6 +1134,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
	RAPL_CPU(INTEL_FAM6_SANDYBRIDGE_X,	rapl_defaults_core),

	RAPL_CPU(INTEL_FAM6_IVYBRIDGE,		rapl_defaults_core),
	RAPL_CPU(INTEL_FAM6_IVYBRIDGE_X,	rapl_defaults_core),

	RAPL_CPU(INTEL_FAM6_HASWELL_CORE,	rapl_defaults_core),
	RAPL_CPU(INTEL_FAM6_HASWELL_ULT,	rapl_defaults_core),
@@ -1123,6 +1157,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
	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_ATOM_DENVERTON,	rapl_defaults_core),

	RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL,	rapl_defaults_hsw_server),
	{}
@@ -1381,6 +1416,37 @@ static int rapl_check_domain(int cpu, int domain)
	return 0;
}


/*
 * Check if power limits are available. Two cases when they are not available:
 * 1. Locked by BIOS, in this case we still provide read-only access so that
 *    users can see what limit is set by the BIOS.
 * 2. Some CPUs make some domains monitoring only which means PLx MSRs may not
 *    exist at all. In this case, we do not show the contraints in powercap.
 *
 * Called after domains are detected and initialized.
 */
static void rapl_detect_powerlimit(struct rapl_domain *rd)
{
	u64 val64;
	int i;

	/* check if the domain is locked by BIOS, ignore if MSR doesn't exist */
	if (!rapl_read_data_raw(rd, FW_LOCK, false, &val64)) {
		if (val64) {
			pr_info("RAPL package %d domain %s locked by BIOS\n",
				rd->rp->id, rd->name);
			rd->state |= DOMAIN_STATE_BIOS_LOCKED;
		}
	}
	/* check if power limit MSRs exists, otherwise domain is monitoring only */
	for (i = 0; i < NR_POWER_LIMITS; i++) {
		int prim = rd->rpl[i].prim_id;
		if (rapl_read_data_raw(rd, prim, false, &val64))
			rd->rpl[i].name = NULL;
	}
}

/* Detect active and valid domains for the given CPU, caller must
 * ensure the CPU belongs to the targeted package and CPU hotlug is disabled.
 */
@@ -1389,7 +1455,6 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
	int i;
	int ret = 0;
	struct rapl_domain *rd;
	u64 locked;

	for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
		/* use physical package id to read counters */
@@ -1400,7 +1465,7 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
	}
	rp->nr_domains = bitmap_weight(&rp->domain_map,	RAPL_DOMAIN_MAX);
	if (!rp->nr_domains) {
		pr_err("no valid rapl domains found in package %d\n", rp->id);
		pr_debug("no valid rapl domains found in package %d\n", rp->id);
		ret = -ENODEV;
		goto done;
	}
@@ -1414,17 +1479,9 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
	}
	rapl_init_domains(rp);

	for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) {
		/* check if the domain is locked by BIOS */
		ret = rapl_read_data_raw(rd, FW_LOCK, false, &locked);
		if (ret)
			return ret;
		if (locked) {
			pr_info("RAPL package %d domain %s locked by BIOS\n",
				rp->id, rd->name);
			rd->state |= DOMAIN_STATE_BIOS_LOCKED;
		}
	}
	for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++)
		rapl_detect_powerlimit(rd);



done: