diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_pmu.c | 93 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_pmu.h | 6 |
2 files changed, 84 insertions, 15 deletions
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 337eaa6ede52..e13859aaa2a3 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c | |||
@@ -409,7 +409,81 @@ static int i915_pmu_event_init(struct perf_event *event) | |||
409 | return 0; | 409 | return 0; |
410 | } | 410 | } |
411 | 411 | ||
412 | static u64 __i915_pmu_event_read(struct perf_event *event) | 412 | static u64 get_rc6(struct drm_i915_private *i915, bool locked) |
413 | { | ||
414 | unsigned long flags; | ||
415 | u64 val; | ||
416 | |||
417 | if (intel_runtime_pm_get_if_in_use(i915)) { | ||
418 | val = intel_rc6_residency_ns(i915, IS_VALLEYVIEW(i915) ? | ||
419 | VLV_GT_RENDER_RC6 : | ||
420 | GEN6_GT_GFX_RC6); | ||
421 | |||
422 | if (HAS_RC6p(i915)) | ||
423 | val += intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6p); | ||
424 | |||
425 | if (HAS_RC6pp(i915)) | ||
426 | val += intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6pp); | ||
427 | |||
428 | intel_runtime_pm_put(i915); | ||
429 | |||
430 | /* | ||
431 | * If we are coming back from being runtime suspended we must | ||
432 | * be careful not to report a larger value than returned | ||
433 | * previously. | ||
434 | */ | ||
435 | |||
436 | if (!locked) | ||
437 | spin_lock_irqsave(&i915->pmu.lock, flags); | ||
438 | |||
439 | if (val >= i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) { | ||
440 | i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = 0; | ||
441 | i915->pmu.sample[__I915_SAMPLE_RC6].cur = val; | ||
442 | } else { | ||
443 | val = i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur; | ||
444 | } | ||
445 | |||
446 | if (!locked) | ||
447 | spin_unlock_irqrestore(&i915->pmu.lock, flags); | ||
448 | } else { | ||
449 | struct pci_dev *pdev = i915->drm.pdev; | ||
450 | struct device *kdev = &pdev->dev; | ||
451 | unsigned long flags2; | ||
452 | |||
453 | /* | ||
454 | * We are runtime suspended. | ||
455 | * | ||
456 | * Report the delta from when the device was suspended to now, | ||
457 | * on top of the last known real value, as the approximated RC6 | ||
458 | * counter value. | ||
459 | */ | ||
460 | if (!locked) | ||
461 | spin_lock_irqsave(&i915->pmu.lock, flags); | ||
462 | |||
463 | spin_lock_irqsave(&kdev->power.lock, flags2); | ||
464 | |||
465 | if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) | ||
466 | i915->pmu.suspended_jiffies_last = | ||
467 | kdev->power.suspended_jiffies; | ||
468 | |||
469 | val = kdev->power.suspended_jiffies - | ||
470 | i915->pmu.suspended_jiffies_last; | ||
471 | val += jiffies - kdev->power.accounting_timestamp; | ||
472 | |||
473 | spin_unlock_irqrestore(&kdev->power.lock, flags2); | ||
474 | |||
475 | val = jiffies_to_nsecs(val); | ||
476 | val += i915->pmu.sample[__I915_SAMPLE_RC6].cur; | ||
477 | i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val; | ||
478 | |||
479 | if (!locked) | ||
480 | spin_unlock_irqrestore(&i915->pmu.lock, flags); | ||
481 | } | ||
482 | |||
483 | return val; | ||
484 | } | ||
485 | |||
486 | static u64 __i915_pmu_event_read(struct perf_event *event, bool locked) | ||
413 | { | 487 | { |
414 | struct drm_i915_private *i915 = | 488 | struct drm_i915_private *i915 = |
415 | container_of(event->pmu, typeof(*i915), pmu.base); | 489 | container_of(event->pmu, typeof(*i915), pmu.base); |
@@ -447,18 +521,7 @@ static u64 __i915_pmu_event_read(struct perf_event *event) | |||
447 | val = count_interrupts(i915); | 521 | val = count_interrupts(i915); |
448 | break; | 522 | break; |
449 | case I915_PMU_RC6_RESIDENCY: | 523 | case I915_PMU_RC6_RESIDENCY: |
450 | intel_runtime_pm_get(i915); | 524 | val = get_rc6(i915, locked); |
451 | val = intel_rc6_residency_ns(i915, | ||
452 | IS_VALLEYVIEW(i915) ? | ||
453 | VLV_GT_RENDER_RC6 : | ||
454 | GEN6_GT_GFX_RC6); | ||
455 | if (HAS_RC6p(i915)) | ||
456 | val += intel_rc6_residency_ns(i915, | ||
457 | GEN6_GT_GFX_RC6p); | ||
458 | if (HAS_RC6pp(i915)) | ||
459 | val += intel_rc6_residency_ns(i915, | ||
460 | GEN6_GT_GFX_RC6pp); | ||
461 | intel_runtime_pm_put(i915); | ||
462 | break; | 525 | break; |
463 | } | 526 | } |
464 | } | 527 | } |
@@ -473,7 +536,7 @@ static void i915_pmu_event_read(struct perf_event *event) | |||
473 | 536 | ||
474 | again: | 537 | again: |
475 | prev = local64_read(&hwc->prev_count); | 538 | prev = local64_read(&hwc->prev_count); |
476 | new = __i915_pmu_event_read(event); | 539 | new = __i915_pmu_event_read(event, false); |
477 | 540 | ||
478 | if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev) | 541 | if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev) |
479 | goto again; | 542 | goto again; |
@@ -528,7 +591,7 @@ static void i915_pmu_enable(struct perf_event *event) | |||
528 | * for all listeners. Even when the event was already enabled and has | 591 | * for all listeners. Even when the event was already enabled and has |
529 | * an existing non-zero value. | 592 | * an existing non-zero value. |
530 | */ | 593 | */ |
531 | local64_set(&event->hw.prev_count, __i915_pmu_event_read(event)); | 594 | local64_set(&event->hw.prev_count, __i915_pmu_event_read(event, true)); |
532 | 595 | ||
533 | spin_unlock_irqrestore(&i915->pmu.lock, flags); | 596 | spin_unlock_irqrestore(&i915->pmu.lock, flags); |
534 | } | 597 | } |
diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index 40c154d13565..bb62df15afa4 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h | |||
@@ -27,6 +27,8 @@ | |||
27 | enum { | 27 | enum { |
28 | __I915_SAMPLE_FREQ_ACT = 0, | 28 | __I915_SAMPLE_FREQ_ACT = 0, |
29 | __I915_SAMPLE_FREQ_REQ, | 29 | __I915_SAMPLE_FREQ_REQ, |
30 | __I915_SAMPLE_RC6, | ||
31 | __I915_SAMPLE_RC6_ESTIMATED, | ||
30 | __I915_NUM_PMU_SAMPLERS | 32 | __I915_NUM_PMU_SAMPLERS |
31 | }; | 33 | }; |
32 | 34 | ||
@@ -94,6 +96,10 @@ struct i915_pmu { | |||
94 | * struct intel_engine_cs. | 96 | * struct intel_engine_cs. |
95 | */ | 97 | */ |
96 | struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS]; | 98 | struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS]; |
99 | /** | ||
100 | * @suspended_jiffies_last: Cached suspend time from PM core. | ||
101 | */ | ||
102 | unsigned long suspended_jiffies_last; | ||
97 | }; | 103 | }; |
98 | 104 | ||
99 | #ifdef CONFIG_PERF_EVENTS | 105 | #ifdef CONFIG_PERF_EVENTS |