aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/powercap
diff options
context:
space:
mode:
authorJacob Pan <jacob.jun.pan@linux.intel.com>2016-05-31 16:41:29 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-06-14 19:33:50 -0400
commite1399ba20eeef7ff07d58a15f403d718e0dbf94d (patch)
treefae110df58132fada5df51f981703a97ef266570 /drivers/powercap
parente1a27e87a35cd6bb1087bd8f95a4be5a11e95f76 (diff)
powercap / RAPL: handle missing MSRs
Some RAPL MSRs may not exist on some CPUs, we need to continue the topology detection and enumerate what is available. This patch handles the missing MSRs, then reports to the powercap layer only the features available. Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/powercap')
-rw-r--r--drivers/powercap/intel_rapl.c103
1 files changed, 79 insertions, 24 deletions
diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c
index 91dfbe6433d6..8b4b8a376120 100644
--- a/drivers/powercap/intel_rapl.c
+++ b/drivers/powercap/intel_rapl.c
@@ -335,14 +335,14 @@ static int release_zone(struct powercap_zone *power_zone)
335 335
336static int find_nr_power_limit(struct rapl_domain *rd) 336static int find_nr_power_limit(struct rapl_domain *rd)
337{ 337{
338 int i; 338 int i, nr_pl = 0;
339 339
340 for (i = 0; i < NR_POWER_LIMITS; i++) { 340 for (i = 0; i < NR_POWER_LIMITS; i++) {
341 if (rd->rpl[i].name == NULL) 341 if (rd->rpl[i].name)
342 break; 342 nr_pl++;
343 } 343 }
344 344
345 return i; 345 return nr_pl;
346} 346}
347 347
348static int set_domain_enable(struct powercap_zone *power_zone, bool mode) 348static int set_domain_enable(struct powercap_zone *power_zone, bool mode)
@@ -425,15 +425,38 @@ static const struct powercap_zone_ops zone_ops[] = {
425 }, 425 },
426}; 426};
427 427
428static int set_power_limit(struct powercap_zone *power_zone, int id, 428
429/*
430 * Constraint index used by powercap can be different than power limit (PL)
431 * index in that some PLs maybe missing due to non-existant MSRs. So we
432 * need to convert here by finding the valid PLs only (name populated).
433 */
434static int contraint_to_pl(struct rapl_domain *rd, int cid)
435{
436 int i, j;
437
438 for (i = 0, j = 0; i < NR_POWER_LIMITS; i++) {
439 if ((rd->rpl[i].name) && j++ == cid) {
440 pr_debug("%s: index %d\n", __func__, i);
441 return i;
442 }
443 }
444
445 return -EINVAL;
446}
447
448static int set_power_limit(struct powercap_zone *power_zone, int cid,
429 u64 power_limit) 449 u64 power_limit)
430{ 450{
431 struct rapl_domain *rd; 451 struct rapl_domain *rd;
432 struct rapl_package *rp; 452 struct rapl_package *rp;
433 int ret = 0; 453 int ret = 0;
454 int id;
434 455
435 get_online_cpus(); 456 get_online_cpus();
436 rd = power_zone_to_rapl_domain(power_zone); 457 rd = power_zone_to_rapl_domain(power_zone);
458 id = contraint_to_pl(rd, cid);
459
437 rp = rd->rp; 460 rp = rd->rp;
438 461
439 if (rd->state & DOMAIN_STATE_BIOS_LOCKED) { 462 if (rd->state & DOMAIN_STATE_BIOS_LOCKED) {
@@ -460,16 +483,18 @@ set_exit:
460 return ret; 483 return ret;
461} 484}
462 485
463static int get_current_power_limit(struct powercap_zone *power_zone, int id, 486static int get_current_power_limit(struct powercap_zone *power_zone, int cid,
464 u64 *data) 487 u64 *data)
465{ 488{
466 struct rapl_domain *rd; 489 struct rapl_domain *rd;
467 u64 val; 490 u64 val;
468 int prim; 491 int prim;
469 int ret = 0; 492 int ret = 0;
493 int id;
470 494
471 get_online_cpus(); 495 get_online_cpus();
472 rd = power_zone_to_rapl_domain(power_zone); 496 rd = power_zone_to_rapl_domain(power_zone);
497 id = contraint_to_pl(rd, cid);
473 switch (rd->rpl[id].prim_id) { 498 switch (rd->rpl[id].prim_id) {
474 case PL1_ENABLE: 499 case PL1_ENABLE:
475 prim = POWER_LIMIT1; 500 prim = POWER_LIMIT1;
@@ -491,14 +516,17 @@ static int get_current_power_limit(struct powercap_zone *power_zone, int id,
491 return ret; 516 return ret;
492} 517}
493 518
494static int set_time_window(struct powercap_zone *power_zone, int id, 519static int set_time_window(struct powercap_zone *power_zone, int cid,
495 u64 window) 520 u64 window)
496{ 521{
497 struct rapl_domain *rd; 522 struct rapl_domain *rd;
498 int ret = 0; 523 int ret = 0;
524 int id;
499 525
500 get_online_cpus(); 526 get_online_cpus();
501 rd = power_zone_to_rapl_domain(power_zone); 527 rd = power_zone_to_rapl_domain(power_zone);
528 id = contraint_to_pl(rd, cid);
529
502 switch (rd->rpl[id].prim_id) { 530 switch (rd->rpl[id].prim_id) {
503 case PL1_ENABLE: 531 case PL1_ENABLE:
504 rapl_write_data_raw(rd, TIME_WINDOW1, window); 532 rapl_write_data_raw(rd, TIME_WINDOW1, window);
@@ -513,14 +541,17 @@ static int set_time_window(struct powercap_zone *power_zone, int id,
513 return ret; 541 return ret;
514} 542}
515 543
516static int get_time_window(struct powercap_zone *power_zone, int id, u64 *data) 544static int get_time_window(struct powercap_zone *power_zone, int cid, u64 *data)
517{ 545{
518 struct rapl_domain *rd; 546 struct rapl_domain *rd;
519 u64 val; 547 u64 val;
520 int ret = 0; 548 int ret = 0;
549 int id;
521 550
522 get_online_cpus(); 551 get_online_cpus();
523 rd = power_zone_to_rapl_domain(power_zone); 552 rd = power_zone_to_rapl_domain(power_zone);
553 id = contraint_to_pl(rd, cid);
554
524 switch (rd->rpl[id].prim_id) { 555 switch (rd->rpl[id].prim_id) {
525 case PL1_ENABLE: 556 case PL1_ENABLE:
526 ret = rapl_read_data_raw(rd, TIME_WINDOW1, true, &val); 557 ret = rapl_read_data_raw(rd, TIME_WINDOW1, true, &val);
@@ -539,15 +570,17 @@ static int get_time_window(struct powercap_zone *power_zone, int id, u64 *data)
539 return ret; 570 return ret;
540} 571}
541 572
542static const char *get_constraint_name(struct powercap_zone *power_zone, int id) 573static const char *get_constraint_name(struct powercap_zone *power_zone, int cid)
543{ 574{
544 struct rapl_power_limit *rpl;
545 struct rapl_domain *rd; 575 struct rapl_domain *rd;
576 int id;
546 577
547 rd = power_zone_to_rapl_domain(power_zone); 578 rd = power_zone_to_rapl_domain(power_zone);
548 rpl = (struct rapl_power_limit *) &rd->rpl[id]; 579 id = contraint_to_pl(rd, cid);
580 if (id >= 0)
581 return rd->rpl[id].name;
549 582
550 return rpl->name; 583 return NULL;
551} 584}
552 585
553 586
@@ -1373,6 +1406,37 @@ static int rapl_check_domain(int cpu, int domain)
1373 return 0; 1406 return 0;
1374} 1407}
1375 1408
1409
1410/*
1411 * Check if power limits are available. Two cases when they are not available:
1412 * 1. Locked by BIOS, in this case we still provide read-only access so that
1413 * users can see what limit is set by the BIOS.
1414 * 2. Some CPUs make some domains monitoring only which means PLx MSRs may not
1415 * exist at all. In this case, we do not show the contraints in powercap.
1416 *
1417 * Called after domains are detected and initialized.
1418 */
1419static void rapl_detect_powerlimit(struct rapl_domain *rd)
1420{
1421 u64 val64;
1422 int i;
1423
1424 /* check if the domain is locked by BIOS, ignore if MSR doesn't exist */
1425 if (!rapl_read_data_raw(rd, FW_LOCK, false, &val64)) {
1426 if (val64) {
1427 pr_info("RAPL package %d domain %s locked by BIOS\n",
1428 rd->rp->id, rd->name);
1429 rd->state |= DOMAIN_STATE_BIOS_LOCKED;
1430 }
1431 }
1432 /* check if power limit MSRs exists, otherwise domain is monitoring only */
1433 for (i = 0; i < NR_POWER_LIMITS; i++) {
1434 int prim = rd->rpl[i].prim_id;
1435 if (rapl_read_data_raw(rd, prim, false, &val64))
1436 rd->rpl[i].name = NULL;
1437 }
1438}
1439
1376/* Detect active and valid domains for the given CPU, caller must 1440/* Detect active and valid domains for the given CPU, caller must
1377 * ensure the CPU belongs to the targeted package and CPU hotlug is disabled. 1441 * ensure the CPU belongs to the targeted package and CPU hotlug is disabled.
1378 */ 1442 */
@@ -1381,7 +1445,6 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
1381 int i; 1445 int i;
1382 int ret = 0; 1446 int ret = 0;
1383 struct rapl_domain *rd; 1447 struct rapl_domain *rd;
1384 u64 locked;
1385 1448
1386 for (i = 0; i < RAPL_DOMAIN_MAX; i++) { 1449 for (i = 0; i < RAPL_DOMAIN_MAX; i++) {
1387 /* use physical package id to read counters */ 1450 /* use physical package id to read counters */
@@ -1406,17 +1469,9 @@ static int rapl_detect_domains(struct rapl_package *rp, int cpu)
1406 } 1469 }
1407 rapl_init_domains(rp); 1470 rapl_init_domains(rp);
1408 1471
1409 for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++) { 1472 for (rd = rp->domains; rd < rp->domains + rp->nr_domains; rd++)
1410 /* check if the domain is locked by BIOS */ 1473 rapl_detect_powerlimit(rd);
1411 ret = rapl_read_data_raw(rd, FW_LOCK, false, &locked); 1474
1412 if (ret)
1413 return ret;
1414 if (locked) {
1415 pr_info("RAPL package %d domain %s locked by BIOS\n",
1416 rp->id, rd->name);
1417 rd->state |= DOMAIN_STATE_BIOS_LOCKED;
1418 }
1419 }
1420 1475
1421 1476
1422done: 1477done: