diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 133 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 12 |
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 | ||
905 | struct intel_rps_ei_calc { | ||
906 | u32 cz_ts_ei; | ||
907 | u32 render_ei_c0; | ||
908 | u32 media_ei_c0; | ||
909 | }; | ||
910 | |||
905 | struct intel_gen6_power_mgmt { | 911 | struct 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 | ||
1275 | static 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 | */ | ||
1330 | static 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 | |||
1275 | static void gen6_pm_rps_work(struct work_struct *work) | 1400 | static 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 | ||
3289 | void gen6_rps_idle(struct drm_i915_private *dev_priv) | 3292 | void 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 | ||