aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h15
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c133
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h11
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c12
4 files changed, 167 insertions, 4 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 8fa8172fcfbb..41191f11af60 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -902,6 +902,12 @@ struct vlv_s0ix_state {
902 u32 clock_gate_dis2; 902 u32 clock_gate_dis2;
903}; 903};
904 904
905struct intel_rps_ei_calc {
906 u32 cz_ts_ei;
907 u32 render_ei_c0;
908 u32 media_ei_c0;
909};
910
905struct intel_gen6_power_mgmt { 911struct intel_gen6_power_mgmt {
906 /* work and pm_iir are protected by dev_priv->irq_lock */ 912 /* work and pm_iir are protected by dev_priv->irq_lock */
907 struct work_struct work; 913 struct work_struct work;
@@ -926,6 +932,8 @@ struct intel_gen6_power_mgmt {
926 u8 rp1_freq; /* "less than" RP0 power/freqency */ 932 u8 rp1_freq; /* "less than" RP0 power/freqency */
927 u8 rp0_freq; /* Non-overclocked max frequency. */ 933 u8 rp0_freq; /* Non-overclocked max frequency. */
928 934
935 u32 ei_interrupt_count;
936
929 int last_adj; 937 int last_adj;
930 enum { LOW_POWER, BETWEEN, HIGH_POWER } power; 938 enum { LOW_POWER, BETWEEN, HIGH_POWER } power;
931 939
@@ -1527,6 +1535,13 @@ struct drm_i915_private {
1527 /* gen6+ rps state */ 1535 /* gen6+ rps state */
1528 struct intel_gen6_power_mgmt rps; 1536 struct intel_gen6_power_mgmt rps;
1529 1537
1538 /* rps wa up ei calculation */
1539 struct intel_rps_ei_calc rps_up_ei;
1540
1541 /* rps wa down ei calculation */
1542 struct intel_rps_ei_calc rps_down_ei;
1543
1544
1530 /* ilk-only ips/rps state. Everything in here is protected by the global 1545 /* ilk-only ips/rps state. Everything in here is protected by the global
1531 * mchdev_lock in intel_pm.c */ 1546 * mchdev_lock in intel_pm.c */
1532 struct intel_ilk_power_mgmt ips; 1547 struct intel_ilk_power_mgmt ips;
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index d672053fdb10..0b4a8ed76a54 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1272,6 +1272,131 @@ static void notify_ring(struct drm_device *dev,
1272 i915_queue_hangcheck(dev); 1272 i915_queue_hangcheck(dev);
1273} 1273}
1274 1274
1275static u32 vlv_c0_residency(struct drm_i915_private *dev_priv,
1276 struct intel_rps_ei_calc *rps_ei)
1277{
1278 u32 cz_ts, cz_freq_khz;
1279 u32 render_count, media_count;
1280 u32 elapsed_render, elapsed_media, elapsed_time;
1281 u32 residency = 0;
1282
1283 cz_ts = vlv_punit_read(dev_priv, PUNIT_REG_CZ_TIMESTAMP);
1284 cz_freq_khz = DIV_ROUND_CLOSEST(dev_priv->mem_freq * 1000, 4);
1285
1286 render_count = I915_READ(VLV_RENDER_C0_COUNT_REG);
1287 media_count = I915_READ(VLV_MEDIA_C0_COUNT_REG);
1288
1289 if (rps_ei->cz_ts_ei == 0) {
1290 rps_ei->cz_ts_ei = cz_ts;
1291 rps_ei->render_ei_c0 = render_count;
1292 rps_ei->media_ei_c0 = media_count;
1293
1294 return dev_priv->rps.cur_freq;
1295 }
1296
1297 elapsed_time = cz_ts - rps_ei->cz_ts_ei;
1298 rps_ei->cz_ts_ei = cz_ts;
1299
1300 elapsed_render = render_count - rps_ei->render_ei_c0;
1301 rps_ei->render_ei_c0 = render_count;
1302
1303 elapsed_media = media_count - rps_ei->media_ei_c0;
1304 rps_ei->media_ei_c0 = media_count;
1305
1306 /* Convert all the counters into common unit of milli sec */
1307 elapsed_time /= VLV_CZ_CLOCK_TO_MILLI_SEC;
1308 elapsed_render /= cz_freq_khz;
1309 elapsed_media /= cz_freq_khz;
1310
1311 /*
1312 * Calculate overall C0 residency percentage
1313 * only if elapsed time is non zero
1314 */
1315 if (elapsed_time) {
1316 residency =
1317 ((max(elapsed_render, elapsed_media) * 100)
1318 / elapsed_time);
1319 }
1320
1321 return residency;
1322}
1323
1324/**
1325 * vlv_calc_delay_from_C0_counters - Increase/Decrease freq based on GPU
1326 * busy-ness calculated from C0 counters of render & media power wells
1327 * @dev_priv: DRM device private
1328 *
1329 */
1330static u32 vlv_calc_delay_from_C0_counters(struct drm_i915_private *dev_priv)
1331{
1332 u32 residency_C0_up = 0, residency_C0_down = 0;
1333 u8 new_delay, adj;
1334
1335 dev_priv->rps.ei_interrupt_count++;
1336
1337 WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock));
1338
1339
1340 if (dev_priv->rps_up_ei.cz_ts_ei == 0) {
1341 vlv_c0_residency(dev_priv, &dev_priv->rps_up_ei);
1342 vlv_c0_residency(dev_priv, &dev_priv->rps_down_ei);
1343 return dev_priv->rps.cur_freq;
1344 }
1345
1346
1347 /*
1348 * To down throttle, C0 residency should be less than down threshold
1349 * for continous EI intervals. So calculate down EI counters
1350 * once in VLV_INT_COUNT_FOR_DOWN_EI
1351 */
1352 if (dev_priv->rps.ei_interrupt_count == VLV_INT_COUNT_FOR_DOWN_EI) {
1353
1354 dev_priv->rps.ei_interrupt_count = 0;
1355
1356 residency_C0_down = vlv_c0_residency(dev_priv,
1357 &dev_priv->rps_down_ei);
1358 } else {
1359 residency_C0_up = vlv_c0_residency(dev_priv,
1360 &dev_priv->rps_up_ei);
1361 }
1362
1363 new_delay = dev_priv->rps.cur_freq;
1364
1365 adj = dev_priv->rps.last_adj;
1366 /* C0 residency is greater than UP threshold. Increase Frequency */
1367 if (residency_C0_up >= VLV_RP_UP_EI_THRESHOLD) {
1368 if (adj > 0)
1369 adj *= 2;
1370 else
1371 adj = 1;
1372
1373 if (dev_priv->rps.cur_freq < dev_priv->rps.max_freq_softlimit)
1374 new_delay = dev_priv->rps.cur_freq + adj;
1375
1376 /*
1377 * For better performance, jump directly
1378 * to RPe if we're below it.
1379 */
1380 if (new_delay < dev_priv->rps.efficient_freq)
1381 new_delay = dev_priv->rps.efficient_freq;
1382
1383 } else if (!dev_priv->rps.ei_interrupt_count &&
1384 (residency_C0_down < VLV_RP_DOWN_EI_THRESHOLD)) {
1385 if (adj < 0)
1386 adj *= 2;
1387 else
1388 adj = -1;
1389 /*
1390 * This means, C0 residency is less than down threshold over
1391 * a period of VLV_INT_COUNT_FOR_DOWN_EI. So, reduce the freq
1392 */
1393 if (dev_priv->rps.cur_freq > dev_priv->rps.min_freq_softlimit)
1394 new_delay = dev_priv->rps.cur_freq + adj;
1395 }
1396
1397 return new_delay;
1398}
1399
1275static void gen6_pm_rps_work(struct work_struct *work) 1400static void gen6_pm_rps_work(struct work_struct *work)
1276{ 1401{
1277 struct drm_i915_private *dev_priv = 1402 struct drm_i915_private *dev_priv =
@@ -1320,6 +1445,8 @@ static void gen6_pm_rps_work(struct work_struct *work)
1320 else 1445 else
1321 new_delay = dev_priv->rps.min_freq_softlimit; 1446 new_delay = dev_priv->rps.min_freq_softlimit;
1322 adj = 0; 1447 adj = 0;
1448 } else if (pm_iir & GEN6_PM_RP_UP_EI_EXPIRED) {
1449 new_delay = vlv_calc_delay_from_C0_counters(dev_priv);
1323 } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) { 1450 } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) {
1324 if (adj < 0) 1451 if (adj < 0)
1325 adj *= 2; 1452 adj *= 2;
@@ -4511,7 +4638,11 @@ void intel_irq_init(struct drm_device *dev)
4511 INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); 4638 INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work);
4512 4639
4513 /* Let's track the enabled rps events */ 4640 /* Let's track the enabled rps events */
4514 dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; 4641 if (IS_VALLEYVIEW(dev))
4642 /* WaGsvRC0ResidenncyMethod:VLV */
4643 dev_priv->pm_rps_events = GEN6_PM_RP_UP_EI_EXPIRED;
4644 else
4645 dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
4515 4646
4516 setup_timer(&dev_priv->gpu_error.hangcheck_timer, 4647 setup_timer(&dev_priv->gpu_error.hangcheck_timer,
4517 i915_hangcheck_elapsed, 4648 i915_hangcheck_elapsed,
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 8c0f70de9fd7..190d4bb5ad53 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -531,6 +531,7 @@ enum punit_power_well {
531#define PUNIT_REG_GPU_FREQ_STS 0xd8 531#define PUNIT_REG_GPU_FREQ_STS 0xd8
532#define GENFREQSTATUS (1<<0) 532#define GENFREQSTATUS (1<<0)
533#define PUNIT_REG_MEDIA_TURBO_FREQ_REQ 0xdc 533#define PUNIT_REG_MEDIA_TURBO_FREQ_REQ 0xdc
534#define PUNIT_REG_CZ_TIMESTAMP 0xce
534 535
535#define PUNIT_FUSE_BUS2 0xf6 /* bits 47:40 */ 536#define PUNIT_FUSE_BUS2 0xf6 /* bits 47:40 */
536#define PUNIT_FUSE_BUS1 0xf5 /* bits 55:48 */ 537#define PUNIT_FUSE_BUS1 0xf5 /* bits 55:48 */
@@ -556,6 +557,11 @@ enum punit_power_well {
556#define FB_FMAX_VMIN_FREQ_LO_SHIFT 27 557#define FB_FMAX_VMIN_FREQ_LO_SHIFT 27
557#define FB_FMAX_VMIN_FREQ_LO_MASK 0xf8000000 558#define FB_FMAX_VMIN_FREQ_LO_MASK 0xf8000000
558 559
560#define VLV_CZ_CLOCK_TO_MILLI_SEC 100000
561#define VLV_RP_UP_EI_THRESHOLD 90
562#define VLV_RP_DOWN_EI_THRESHOLD 70
563#define VLV_INT_COUNT_FOR_DOWN_EI 5
564
559/* vlv2 north clock has */ 565/* vlv2 north clock has */
560#define CCK_FUSE_REG 0x8 566#define CCK_FUSE_REG 0x8
561#define CCK_FUSE_HPLL_FREQ_MASK 0x3 567#define CCK_FUSE_HPLL_FREQ_MASK 0x3
@@ -5394,6 +5400,7 @@ enum punit_power_well {
5394#define VLV_GTLC_ALLOWWAKEERR (1 << 1) 5400#define VLV_GTLC_ALLOWWAKEERR (1 << 1)
5395#define VLV_GTLC_PW_MEDIA_STATUS_MASK (1 << 5) 5401#define VLV_GTLC_PW_MEDIA_STATUS_MASK (1 << 5)
5396#define VLV_GTLC_PW_RENDER_STATUS_MASK (1 << 7) 5402#define VLV_GTLC_PW_RENDER_STATUS_MASK (1 << 7)
5403#define VLV_GTLC_SURVIVABILITY_REG 0x130098
5397#define FORCEWAKE_MT 0xa188 /* multi-threaded */ 5404#define FORCEWAKE_MT 0xa188 /* multi-threaded */
5398#define FORCEWAKE_KERNEL 0x1 5405#define FORCEWAKE_KERNEL 0x1
5399#define FORCEWAKE_USER 0x2 5406#define FORCEWAKE_USER 0x2
@@ -5541,6 +5548,8 @@ enum punit_power_well {
5541#define GEN6_GT_GFX_RC6_LOCKED 0x138104 5548#define GEN6_GT_GFX_RC6_LOCKED 0x138104
5542#define VLV_COUNTER_CONTROL 0x138104 5549#define VLV_COUNTER_CONTROL 0x138104
5543#define VLV_COUNT_RANGE_HIGH (1<<15) 5550#define VLV_COUNT_RANGE_HIGH (1<<15)
5551#define VLV_MEDIA_RC0_COUNT_EN (1<<5)
5552#define VLV_RENDER_RC0_COUNT_EN (1<<4)
5544#define VLV_MEDIA_RC6_COUNT_EN (1<<1) 5553#define VLV_MEDIA_RC6_COUNT_EN (1<<1)
5545#define VLV_RENDER_RC6_COUNT_EN (1<<0) 5554#define VLV_RENDER_RC6_COUNT_EN (1<<0)
5546#define GEN6_GT_GFX_RC6 0x138108 5555#define GEN6_GT_GFX_RC6 0x138108
@@ -5549,6 +5558,8 @@ enum punit_power_well {
5549 5558
5550#define GEN6_GT_GFX_RC6p 0x13810C 5559#define GEN6_GT_GFX_RC6p 0x13810C
5551#define GEN6_GT_GFX_RC6pp 0x138110 5560#define GEN6_GT_GFX_RC6pp 0x138110
5561#define VLV_RENDER_C0_COUNT_REG 0x138118
5562#define VLV_MEDIA_C0_COUNT_REG 0x13811C
5552 5563
5553#define GEN6_PCODE_MAILBOX 0x138124 5564#define GEN6_PCODE_MAILBOX 0x138124
5554#define GEN6_PCODE_READY (1<<31) 5565#define GEN6_PCODE_READY (1<<31)
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index f2a40565ef98..d1af6419ec78 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3282,8 +3282,11 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv)
3282 3282
3283 vlv_force_gfx_clock(dev_priv, false); 3283 vlv_force_gfx_clock(dev_priv, false);
3284 3284
3285 I915_WRITE(GEN6_PMINTRMSK, 3285 if (dev_priv->pm_rps_events & GEN6_PM_RP_UP_EI_EXPIRED)
3286 gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq)); 3286 I915_WRITE(GEN6_PMINTRMSK, ~dev_priv->pm_rps_events);
3287 else
3288 I915_WRITE(GEN6_PMINTRMSK,
3289 gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq));
3287} 3290}
3288 3291
3289void gen6_rps_idle(struct drm_i915_private *dev_priv) 3292void gen6_rps_idle(struct drm_i915_private *dev_priv)
@@ -4125,6 +4128,7 @@ static void valleyview_enable_rps(struct drm_device *dev)
4125 I915_WRITE(GEN6_RP_DOWN_EI, 350000); 4128 I915_WRITE(GEN6_RP_DOWN_EI, 350000);
4126 4129
4127 I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); 4130 I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
4131 I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 0xf4240);
4128 4132
4129 I915_WRITE(GEN6_RP_CONTROL, 4133 I915_WRITE(GEN6_RP_CONTROL,
4130 GEN6_RP_MEDIA_TURBO | 4134 GEN6_RP_MEDIA_TURBO |
@@ -4145,9 +4149,11 @@ static void valleyview_enable_rps(struct drm_device *dev)
4145 4149
4146 /* allows RC6 residency counter to work */ 4150 /* allows RC6 residency counter to work */
4147 I915_WRITE(VLV_COUNTER_CONTROL, 4151 I915_WRITE(VLV_COUNTER_CONTROL,
4148 _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH | 4152 _MASKED_BIT_ENABLE(VLV_MEDIA_RC0_COUNT_EN |
4153 VLV_RENDER_RC0_COUNT_EN |
4149 VLV_MEDIA_RC6_COUNT_EN | 4154 VLV_MEDIA_RC6_COUNT_EN |
4150 VLV_RENDER_RC6_COUNT_EN)); 4155 VLV_RENDER_RC6_COUNT_EN));
4156
4151 if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) 4157 if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE)
4152 rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL; 4158 rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL;
4153 4159