diff options
| author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-10-25 04:06:04 -0400 |
|---|---|---|
| committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2016-10-25 04:06:04 -0400 |
| commit | 0fc4f78f44e6c6148cee32456f0d0023ec1c1fd8 (patch) | |
| tree | 71c906207227dd8753a0191db9304035ec3471a4 /drivers/gpu | |
| parent | 78010cd9736ec571796f4404524ed575b81238b9 (diff) | |
| parent | 5481e27f6fd06b7cb902072e81d6b083db8155eb (diff) | |
Merge remote-tracking branch 'airlied/drm-next' into topic/drm-misc
Backmerge latest drm-next to have a baseline for the
s/fence/dma_fence/ patch from Chris.
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'drivers/gpu')
182 files changed, 21397 insertions, 3622 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig index 53cf3971dfc3..61360e27715f 100644 --- a/drivers/gpu/drm/amd/amdgpu/Kconfig +++ b/drivers/gpu/drm/amd/amdgpu/Kconfig | |||
| @@ -32,5 +32,4 @@ config DRM_AMDGPU_GART_DEBUGFS | |||
| 32 | Selecting this option creates a debugfs file to inspect the mapped | 32 | Selecting this option creates a debugfs file to inspect the mapped |
| 33 | pages. Uses more memory for housekeeping, enable only for debugging. | 33 | pages. Uses more memory for housekeeping, enable only for debugging. |
| 34 | 34 | ||
| 35 | source "drivers/gpu/drm/amd/powerplay/Kconfig" | ||
| 36 | source "drivers/gpu/drm/amd/acp/Kconfig" | 35 | source "drivers/gpu/drm/amd/acp/Kconfig" |
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 9ec262d4b8a2..248a05d02917 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile | |||
| @@ -111,14 +111,10 @@ amdgpu-$(CONFIG_VGA_SWITCHEROO) += amdgpu_atpx_handler.o | |||
| 111 | amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o | 111 | amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o |
| 112 | amdgpu-$(CONFIG_MMU_NOTIFIER) += amdgpu_mn.o | 112 | amdgpu-$(CONFIG_MMU_NOTIFIER) += amdgpu_mn.o |
| 113 | 113 | ||
| 114 | ifneq ($(CONFIG_DRM_AMD_POWERPLAY),) | ||
| 115 | |||
| 116 | include $(FULL_AMD_PATH)/powerplay/Makefile | 114 | include $(FULL_AMD_PATH)/powerplay/Makefile |
| 117 | 115 | ||
| 118 | amdgpu-y += $(AMD_POWERPLAY_FILES) | 116 | amdgpu-y += $(AMD_POWERPLAY_FILES) |
| 119 | 117 | ||
| 120 | endif | ||
| 121 | |||
| 122 | obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o | 118 | obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o |
| 123 | 119 | ||
| 124 | CFLAGS_amdgpu_trace_points.o := -I$(src) | 120 | CFLAGS_amdgpu_trace_points.o := -I$(src) |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 235f3902643a..039b57e4644c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h | |||
| @@ -1943,6 +1943,7 @@ struct amdgpu_ip_block_status { | |||
| 1943 | bool valid; | 1943 | bool valid; |
| 1944 | bool sw; | 1944 | bool sw; |
| 1945 | bool hw; | 1945 | bool hw; |
| 1946 | bool late_initialized; | ||
| 1946 | bool hang; | 1947 | bool hang; |
| 1947 | }; | 1948 | }; |
| 1948 | 1949 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 22c11e7698c8..e3281d4e3e41 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | |||
| @@ -765,12 +765,20 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force) | |||
| 765 | return ret; | 765 | return ret; |
| 766 | } | 766 | } |
| 767 | 767 | ||
| 768 | static void amdgpu_connector_destroy(struct drm_connector *connector) | 768 | static void amdgpu_connector_unregister(struct drm_connector *connector) |
| 769 | { | 769 | { |
| 770 | struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); | 770 | struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); |
| 771 | 771 | ||
| 772 | if (amdgpu_connector->ddc_bus->has_aux) | 772 | if (amdgpu_connector->ddc_bus->has_aux) { |
| 773 | drm_dp_aux_unregister(&amdgpu_connector->ddc_bus->aux); | 773 | drm_dp_aux_unregister(&amdgpu_connector->ddc_bus->aux); |
| 774 | amdgpu_connector->ddc_bus->has_aux = false; | ||
| 775 | } | ||
| 776 | } | ||
| 777 | |||
| 778 | static void amdgpu_connector_destroy(struct drm_connector *connector) | ||
| 779 | { | ||
| 780 | struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); | ||
| 781 | |||
| 774 | amdgpu_connector_free_edid(connector); | 782 | amdgpu_connector_free_edid(connector); |
| 775 | kfree(amdgpu_connector->con_priv); | 783 | kfree(amdgpu_connector->con_priv); |
| 776 | drm_connector_unregister(connector); | 784 | drm_connector_unregister(connector); |
| @@ -824,6 +832,7 @@ static const struct drm_connector_funcs amdgpu_connector_lvds_funcs = { | |||
| 824 | .dpms = drm_helper_connector_dpms, | 832 | .dpms = drm_helper_connector_dpms, |
| 825 | .detect = amdgpu_connector_lvds_detect, | 833 | .detect = amdgpu_connector_lvds_detect, |
| 826 | .fill_modes = drm_helper_probe_single_connector_modes, | 834 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 835 | .early_unregister = amdgpu_connector_unregister, | ||
| 827 | .destroy = amdgpu_connector_destroy, | 836 | .destroy = amdgpu_connector_destroy, |
| 828 | .set_property = amdgpu_connector_set_lcd_property, | 837 | .set_property = amdgpu_connector_set_lcd_property, |
| 829 | }; | 838 | }; |
| @@ -934,6 +943,7 @@ static const struct drm_connector_funcs amdgpu_connector_vga_funcs = { | |||
| 934 | .dpms = drm_helper_connector_dpms, | 943 | .dpms = drm_helper_connector_dpms, |
| 935 | .detect = amdgpu_connector_vga_detect, | 944 | .detect = amdgpu_connector_vga_detect, |
| 936 | .fill_modes = drm_helper_probe_single_connector_modes, | 945 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 946 | .early_unregister = amdgpu_connector_unregister, | ||
| 937 | .destroy = amdgpu_connector_destroy, | 947 | .destroy = amdgpu_connector_destroy, |
| 938 | .set_property = amdgpu_connector_set_property, | 948 | .set_property = amdgpu_connector_set_property, |
| 939 | }; | 949 | }; |
| @@ -1201,6 +1211,7 @@ static const struct drm_connector_funcs amdgpu_connector_dvi_funcs = { | |||
| 1201 | .detect = amdgpu_connector_dvi_detect, | 1211 | .detect = amdgpu_connector_dvi_detect, |
| 1202 | .fill_modes = drm_helper_probe_single_connector_modes, | 1212 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1203 | .set_property = amdgpu_connector_set_property, | 1213 | .set_property = amdgpu_connector_set_property, |
| 1214 | .early_unregister = amdgpu_connector_unregister, | ||
| 1204 | .destroy = amdgpu_connector_destroy, | 1215 | .destroy = amdgpu_connector_destroy, |
| 1205 | .force = amdgpu_connector_dvi_force, | 1216 | .force = amdgpu_connector_dvi_force, |
| 1206 | }; | 1217 | }; |
| @@ -1491,6 +1502,7 @@ static const struct drm_connector_funcs amdgpu_connector_dp_funcs = { | |||
| 1491 | .detect = amdgpu_connector_dp_detect, | 1502 | .detect = amdgpu_connector_dp_detect, |
| 1492 | .fill_modes = drm_helper_probe_single_connector_modes, | 1503 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1493 | .set_property = amdgpu_connector_set_property, | 1504 | .set_property = amdgpu_connector_set_property, |
| 1505 | .early_unregister = amdgpu_connector_unregister, | ||
| 1494 | .destroy = amdgpu_connector_destroy, | 1506 | .destroy = amdgpu_connector_destroy, |
| 1495 | .force = amdgpu_connector_dvi_force, | 1507 | .force = amdgpu_connector_dvi_force, |
| 1496 | }; | 1508 | }; |
| @@ -1500,6 +1512,7 @@ static const struct drm_connector_funcs amdgpu_connector_edp_funcs = { | |||
| 1500 | .detect = amdgpu_connector_dp_detect, | 1512 | .detect = amdgpu_connector_dp_detect, |
| 1501 | .fill_modes = drm_helper_probe_single_connector_modes, | 1513 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1502 | .set_property = amdgpu_connector_set_lcd_property, | 1514 | .set_property = amdgpu_connector_set_lcd_property, |
| 1515 | .early_unregister = amdgpu_connector_unregister, | ||
| 1503 | .destroy = amdgpu_connector_destroy, | 1516 | .destroy = amdgpu_connector_destroy, |
| 1504 | .force = amdgpu_connector_dvi_force, | 1517 | .force = amdgpu_connector_dvi_force, |
| 1505 | }; | 1518 | }; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index e203e5561107..a5e2fcbef0f0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | |||
| @@ -43,6 +43,9 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, struct amdgpu_ctx *ctx) | |||
| 43 | ctx->rings[i].sequence = 1; | 43 | ctx->rings[i].sequence = 1; |
| 44 | ctx->rings[i].fences = &ctx->fences[amdgpu_sched_jobs * i]; | 44 | ctx->rings[i].fences = &ctx->fences[amdgpu_sched_jobs * i]; |
| 45 | } | 45 | } |
| 46 | |||
| 47 | ctx->reset_counter = atomic_read(&adev->gpu_reset_counter); | ||
| 48 | |||
| 46 | /* create context entity for each ring */ | 49 | /* create context entity for each ring */ |
| 47 | for (i = 0; i < adev->num_rings; i++) { | 50 | for (i = 0; i < adev->num_rings; i++) { |
| 48 | struct amdgpu_ring *ring = adev->rings[i]; | 51 | struct amdgpu_ring *ring = adev->rings[i]; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 99a15cad6789..b4f4a9239069 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
| @@ -1408,22 +1408,25 @@ static int amdgpu_late_init(struct amdgpu_device *adev) | |||
| 1408 | for (i = 0; i < adev->num_ip_blocks; i++) { | 1408 | for (i = 0; i < adev->num_ip_blocks; i++) { |
| 1409 | if (!adev->ip_block_status[i].valid) | 1409 | if (!adev->ip_block_status[i].valid) |
| 1410 | continue; | 1410 | continue; |
| 1411 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_UVD || | ||
| 1412 | adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_VCE) | ||
| 1413 | continue; | ||
| 1414 | /* enable clockgating to save power */ | ||
| 1415 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, | ||
| 1416 | AMD_CG_STATE_GATE); | ||
| 1417 | if (r) { | ||
| 1418 | DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); | ||
| 1419 | return r; | ||
| 1420 | } | ||
| 1421 | if (adev->ip_blocks[i].funcs->late_init) { | 1411 | if (adev->ip_blocks[i].funcs->late_init) { |
| 1422 | r = adev->ip_blocks[i].funcs->late_init((void *)adev); | 1412 | r = adev->ip_blocks[i].funcs->late_init((void *)adev); |
| 1423 | if (r) { | 1413 | if (r) { |
| 1424 | DRM_ERROR("late_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); | 1414 | DRM_ERROR("late_init of IP block <%s> failed %d\n", adev->ip_blocks[i].funcs->name, r); |
| 1425 | return r; | 1415 | return r; |
| 1426 | } | 1416 | } |
| 1417 | adev->ip_block_status[i].late_initialized = true; | ||
| 1418 | } | ||
| 1419 | /* skip CG for VCE/UVD, it's handled specially */ | ||
| 1420 | if (adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_UVD && | ||
| 1421 | adev->ip_blocks[i].type != AMD_IP_BLOCK_TYPE_VCE) { | ||
| 1422 | /* enable clockgating to save power */ | ||
| 1423 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, | ||
| 1424 | AMD_CG_STATE_GATE); | ||
| 1425 | if (r) { | ||
| 1426 | DRM_ERROR("set_clockgating_state(gate) of IP block <%s> failed %d\n", | ||
| 1427 | adev->ip_blocks[i].funcs->name, r); | ||
| 1428 | return r; | ||
| 1429 | } | ||
| 1427 | } | 1430 | } |
| 1428 | } | 1431 | } |
| 1429 | 1432 | ||
| @@ -1434,6 +1437,30 @@ static int amdgpu_fini(struct amdgpu_device *adev) | |||
| 1434 | { | 1437 | { |
| 1435 | int i, r; | 1438 | int i, r; |
| 1436 | 1439 | ||
| 1440 | /* need to disable SMC first */ | ||
| 1441 | for (i = 0; i < adev->num_ip_blocks; i++) { | ||
| 1442 | if (!adev->ip_block_status[i].hw) | ||
| 1443 | continue; | ||
| 1444 | if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) { | ||
| 1445 | /* ungate blocks before hw fini so that we can shutdown the blocks safely */ | ||
| 1446 | r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, | ||
| 1447 | AMD_CG_STATE_UNGATE); | ||
| 1448 | if (r) { | ||
| 1449 | DRM_ERROR("set_clockgating_state(ungate) of IP block <%s> failed %d\n", | ||
| 1450 | adev->ip_blocks[i].funcs->name, r); | ||
| 1451 | return r; | ||
| 1452 | } | ||
| 1453 | r = adev->ip_blocks[i].funcs->hw_fini((void *)adev); | ||
| 1454 | /* XXX handle errors */ | ||
| 1455 | if (r) { | ||
| 1456 | DRM_DEBUG("hw_fini of IP block <%s> failed %d\n", | ||
| 1457 | adev->ip_blocks[i].funcs->name, r); | ||
| 1458 | } | ||
| 1459 | adev->ip_block_status[i].hw = false; | ||
| 1460 | break; | ||
| 1461 | } | ||
| 1462 | } | ||
| 1463 | |||
| 1437 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { | 1464 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { |
| 1438 | if (!adev->ip_block_status[i].hw) | 1465 | if (!adev->ip_block_status[i].hw) |
| 1439 | continue; | 1466 | continue; |
| @@ -1469,8 +1496,11 @@ static int amdgpu_fini(struct amdgpu_device *adev) | |||
| 1469 | } | 1496 | } |
| 1470 | 1497 | ||
| 1471 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { | 1498 | for (i = adev->num_ip_blocks - 1; i >= 0; i--) { |
| 1499 | if (!adev->ip_block_status[i].late_initialized) | ||
| 1500 | continue; | ||
| 1472 | if (adev->ip_blocks[i].funcs->late_fini) | 1501 | if (adev->ip_blocks[i].funcs->late_fini) |
| 1473 | adev->ip_blocks[i].funcs->late_fini((void *)adev); | 1502 | adev->ip_blocks[i].funcs->late_fini((void *)adev); |
| 1503 | adev->ip_block_status[i].late_initialized = false; | ||
| 1474 | } | 1504 | } |
| 1475 | 1505 | ||
| 1476 | return 0; | 1506 | return 0; |
| @@ -1822,11 +1852,11 @@ void amdgpu_device_fini(struct amdgpu_device *adev) | |||
| 1822 | 1852 | ||
| 1823 | DRM_INFO("amdgpu: finishing device.\n"); | 1853 | DRM_INFO("amdgpu: finishing device.\n"); |
| 1824 | adev->shutdown = true; | 1854 | adev->shutdown = true; |
| 1855 | drm_crtc_force_disable_all(adev->ddev); | ||
| 1825 | /* evict vram memory */ | 1856 | /* evict vram memory */ |
| 1826 | amdgpu_bo_evict_vram(adev); | 1857 | amdgpu_bo_evict_vram(adev); |
| 1827 | amdgpu_ib_pool_fini(adev); | 1858 | amdgpu_ib_pool_fini(adev); |
| 1828 | amdgpu_fence_driver_fini(adev); | 1859 | amdgpu_fence_driver_fini(adev); |
| 1829 | drm_crtc_force_disable_all(adev->ddev); | ||
| 1830 | amdgpu_fbdev_fini(adev); | 1860 | amdgpu_fbdev_fini(adev); |
| 1831 | r = amdgpu_fini(adev); | 1861 | r = amdgpu_fini(adev); |
| 1832 | kfree(adev->ip_block_status); | 1862 | kfree(adev->ip_block_status); |
| @@ -2069,7 +2099,8 @@ static bool amdgpu_check_soft_reset(struct amdgpu_device *adev) | |||
| 2069 | if (!adev->ip_block_status[i].valid) | 2099 | if (!adev->ip_block_status[i].valid) |
| 2070 | continue; | 2100 | continue; |
| 2071 | if (adev->ip_blocks[i].funcs->check_soft_reset) | 2101 | if (adev->ip_blocks[i].funcs->check_soft_reset) |
| 2072 | adev->ip_blocks[i].funcs->check_soft_reset(adev); | 2102 | adev->ip_block_status[i].hang = |
| 2103 | adev->ip_blocks[i].funcs->check_soft_reset(adev); | ||
| 2073 | if (adev->ip_block_status[i].hang) { | 2104 | if (adev->ip_block_status[i].hang) { |
| 2074 | DRM_INFO("IP block:%d is hang!\n", i); | 2105 | DRM_INFO("IP block:%d is hang!\n", i); |
| 2075 | asic_hang = true; | 2106 | asic_hang = true; |
| @@ -2098,12 +2129,20 @@ static int amdgpu_pre_soft_reset(struct amdgpu_device *adev) | |||
| 2098 | 2129 | ||
| 2099 | static bool amdgpu_need_full_reset(struct amdgpu_device *adev) | 2130 | static bool amdgpu_need_full_reset(struct amdgpu_device *adev) |
| 2100 | { | 2131 | { |
| 2101 | if (adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang || | 2132 | int i; |
| 2102 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_SMC].hang || | 2133 | |
| 2103 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_ACP].hang || | 2134 | for (i = 0; i < adev->num_ip_blocks; i++) { |
| 2104 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang) { | 2135 | if (!adev->ip_block_status[i].valid) |
| 2105 | DRM_INFO("Some block need full reset!\n"); | 2136 | continue; |
| 2106 | return true; | 2137 | if ((adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) || |
| 2138 | (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_SMC) || | ||
| 2139 | (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_ACP) || | ||
| 2140 | (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_DCE)) { | ||
| 2141 | if (adev->ip_block_status[i].hang) { | ||
| 2142 | DRM_INFO("Some block need full reset!\n"); | ||
| 2143 | return true; | ||
| 2144 | } | ||
| 2145 | } | ||
| 2107 | } | 2146 | } |
| 2108 | return false; | 2147 | return false; |
| 2109 | } | 2148 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c index fe36caf1b7d7..14f57d9915e3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.c | |||
| @@ -113,24 +113,26 @@ void amdgpu_dpm_print_ps_status(struct amdgpu_device *adev, | |||
| 113 | printk("\n"); | 113 | printk("\n"); |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | |||
| 116 | u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) | 117 | u32 amdgpu_dpm_get_vblank_time(struct amdgpu_device *adev) |
| 117 | { | 118 | { |
| 118 | struct drm_device *dev = adev->ddev; | 119 | struct drm_device *dev = adev->ddev; |
| 119 | struct drm_crtc *crtc; | 120 | struct drm_crtc *crtc; |
| 120 | struct amdgpu_crtc *amdgpu_crtc; | 121 | struct amdgpu_crtc *amdgpu_crtc; |
| 121 | u32 line_time_us, vblank_lines; | 122 | u32 vblank_in_pixels; |
| 122 | u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */ | 123 | u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */ |
| 123 | 124 | ||
| 124 | if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { | 125 | if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { |
| 125 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 126 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
| 126 | amdgpu_crtc = to_amdgpu_crtc(crtc); | 127 | amdgpu_crtc = to_amdgpu_crtc(crtc); |
| 127 | if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { | 128 | if (crtc->enabled && amdgpu_crtc->enabled && amdgpu_crtc->hw_mode.clock) { |
| 128 | line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) / | 129 | vblank_in_pixels = |
| 129 | amdgpu_crtc->hw_mode.clock; | 130 | amdgpu_crtc->hw_mode.crtc_htotal * |
| 130 | vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end - | 131 | (amdgpu_crtc->hw_mode.crtc_vblank_end - |
| 131 | amdgpu_crtc->hw_mode.crtc_vdisplay + | 132 | amdgpu_crtc->hw_mode.crtc_vdisplay + |
| 132 | (amdgpu_crtc->v_border * 2); | 133 | (amdgpu_crtc->v_border * 2)); |
| 133 | vblank_time_us = vblank_lines * line_time_us; | 134 | |
| 135 | vblank_time_us = vblank_in_pixels * 1000 / amdgpu_crtc->hw_mode.clock; | ||
| 134 | break; | 136 | break; |
| 135 | } | 137 | } |
| 136 | } | 138 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index dbe89fb25694..71ed27eb3dde 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | |||
| @@ -174,7 +174,6 @@ module_param_named(sched_jobs, amdgpu_sched_jobs, int, 0444); | |||
| 174 | MODULE_PARM_DESC(sched_hw_submission, "the max number of HW submissions (default 2)"); | 174 | MODULE_PARM_DESC(sched_hw_submission, "the max number of HW submissions (default 2)"); |
| 175 | module_param_named(sched_hw_submission, amdgpu_sched_hw_submission, int, 0444); | 175 | module_param_named(sched_hw_submission, amdgpu_sched_hw_submission, int, 0444); |
| 176 | 176 | ||
| 177 | #ifdef CONFIG_DRM_AMD_POWERPLAY | ||
| 178 | MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 = auto (default))"); | 177 | MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 = auto (default))"); |
| 179 | module_param_named(powerplay, amdgpu_powerplay, int, 0444); | 178 | module_param_named(powerplay, amdgpu_powerplay, int, 0444); |
| 180 | 179 | ||
| @@ -183,7 +182,6 @@ module_param_named(powercontainment, amdgpu_powercontainment, int, 0444); | |||
| 183 | 182 | ||
| 184 | MODULE_PARM_DESC(ppfeaturemask, "all power features enabled (default))"); | 183 | MODULE_PARM_DESC(ppfeaturemask, "all power features enabled (default))"); |
| 185 | module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, int, 0444); | 184 | module_param_named(ppfeaturemask, amdgpu_pp_feature_mask, int, 0444); |
| 186 | #endif | ||
| 187 | 185 | ||
| 188 | MODULE_PARM_DESC(sclkdeepsleep, "SCLK Deep Sleep (1 = enable (default), 0 = disable)"); | 186 | MODULE_PARM_DESC(sclkdeepsleep, "SCLK Deep Sleep (1 = enable (default), 0 = disable)"); |
| 189 | module_param_named(sclkdeepsleep, amdgpu_sclk_deep_sleep_en, int, 0444); | 187 | module_param_named(sclkdeepsleep, amdgpu_sclk_deep_sleep_en, int, 0444); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c index 34bab616588c..91d367399956 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_i2c.c | |||
| @@ -220,6 +220,7 @@ void amdgpu_i2c_destroy(struct amdgpu_i2c_chan *i2c) | |||
| 220 | { | 220 | { |
| 221 | if (!i2c) | 221 | if (!i2c) |
| 222 | return; | 222 | return; |
| 223 | WARN_ON(i2c->has_aux); | ||
| 223 | i2c_del_adapter(&i2c->adapter); | 224 | i2c_del_adapter(&i2c->adapter); |
| 224 | kfree(i2c); | 225 | kfree(i2c); |
| 225 | } | 226 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c index 68ad24101a36..7532ff822aa7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c | |||
| @@ -42,7 +42,6 @@ static int amdgpu_powerplay_init(struct amdgpu_device *adev) | |||
| 42 | amd_pp = &(adev->powerplay); | 42 | amd_pp = &(adev->powerplay); |
| 43 | 43 | ||
| 44 | if (adev->pp_enabled) { | 44 | if (adev->pp_enabled) { |
| 45 | #ifdef CONFIG_DRM_AMD_POWERPLAY | ||
| 46 | struct amd_pp_init *pp_init; | 45 | struct amd_pp_init *pp_init; |
| 47 | 46 | ||
| 48 | pp_init = kzalloc(sizeof(struct amd_pp_init), GFP_KERNEL); | 47 | pp_init = kzalloc(sizeof(struct amd_pp_init), GFP_KERNEL); |
| @@ -55,7 +54,6 @@ static int amdgpu_powerplay_init(struct amdgpu_device *adev) | |||
| 55 | pp_init->device = amdgpu_cgs_create_device(adev); | 54 | pp_init->device = amdgpu_cgs_create_device(adev); |
| 56 | ret = amd_powerplay_init(pp_init, amd_pp); | 55 | ret = amd_powerplay_init(pp_init, amd_pp); |
| 57 | kfree(pp_init); | 56 | kfree(pp_init); |
| 58 | #endif | ||
| 59 | } else { | 57 | } else { |
| 60 | amd_pp->pp_handle = (void *)adev; | 58 | amd_pp->pp_handle = (void *)adev; |
| 61 | 59 | ||
| @@ -97,7 +95,6 @@ static int amdgpu_pp_early_init(void *handle) | |||
| 97 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 95 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 98 | int ret = 0; | 96 | int ret = 0; |
| 99 | 97 | ||
| 100 | #ifdef CONFIG_DRM_AMD_POWERPLAY | ||
| 101 | switch (adev->asic_type) { | 98 | switch (adev->asic_type) { |
| 102 | case CHIP_POLARIS11: | 99 | case CHIP_POLARIS11: |
| 103 | case CHIP_POLARIS10: | 100 | case CHIP_POLARIS10: |
| @@ -120,9 +117,6 @@ static int amdgpu_pp_early_init(void *handle) | |||
| 120 | adev->pp_enabled = false; | 117 | adev->pp_enabled = false; |
| 121 | break; | 118 | break; |
| 122 | } | 119 | } |
| 123 | #else | ||
| 124 | adev->pp_enabled = false; | ||
| 125 | #endif | ||
| 126 | 120 | ||
| 127 | ret = amdgpu_powerplay_init(adev); | 121 | ret = amdgpu_powerplay_init(adev); |
| 128 | if (ret) | 122 | if (ret) |
| @@ -144,12 +138,11 @@ static int amdgpu_pp_late_init(void *handle) | |||
| 144 | ret = adev->powerplay.ip_funcs->late_init( | 138 | ret = adev->powerplay.ip_funcs->late_init( |
| 145 | adev->powerplay.pp_handle); | 139 | adev->powerplay.pp_handle); |
| 146 | 140 | ||
| 147 | #ifdef CONFIG_DRM_AMD_POWERPLAY | ||
| 148 | if (adev->pp_enabled && adev->pm.dpm_enabled) { | 141 | if (adev->pp_enabled && adev->pm.dpm_enabled) { |
| 149 | amdgpu_pm_sysfs_init(adev); | 142 | amdgpu_pm_sysfs_init(adev); |
| 150 | amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_COMPLETE_INIT, NULL, NULL); | 143 | amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_COMPLETE_INIT, NULL, NULL); |
| 151 | } | 144 | } |
| 152 | #endif | 145 | |
| 153 | return ret; | 146 | return ret; |
| 154 | } | 147 | } |
| 155 | 148 | ||
| @@ -162,10 +155,8 @@ static int amdgpu_pp_sw_init(void *handle) | |||
| 162 | ret = adev->powerplay.ip_funcs->sw_init( | 155 | ret = adev->powerplay.ip_funcs->sw_init( |
| 163 | adev->powerplay.pp_handle); | 156 | adev->powerplay.pp_handle); |
| 164 | 157 | ||
| 165 | #ifdef CONFIG_DRM_AMD_POWERPLAY | ||
| 166 | if (adev->pp_enabled) | 158 | if (adev->pp_enabled) |
| 167 | adev->pm.dpm_enabled = true; | 159 | adev->pm.dpm_enabled = true; |
| 168 | #endif | ||
| 169 | 160 | ||
| 170 | return ret; | 161 | return ret; |
| 171 | } | 162 | } |
| @@ -216,7 +207,6 @@ static int amdgpu_pp_hw_fini(void *handle) | |||
| 216 | 207 | ||
| 217 | static void amdgpu_pp_late_fini(void *handle) | 208 | static void amdgpu_pp_late_fini(void *handle) |
| 218 | { | 209 | { |
| 219 | #ifdef CONFIG_DRM_AMD_POWERPLAY | ||
| 220 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 210 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 221 | 211 | ||
| 222 | if (adev->pp_enabled) { | 212 | if (adev->pp_enabled) { |
| @@ -227,7 +217,6 @@ static void amdgpu_pp_late_fini(void *handle) | |||
| 227 | if (adev->powerplay.ip_funcs->late_fini) | 217 | if (adev->powerplay.ip_funcs->late_fini) |
| 228 | adev->powerplay.ip_funcs->late_fini( | 218 | adev->powerplay.ip_funcs->late_fini( |
| 229 | adev->powerplay.pp_handle); | 219 | adev->powerplay.pp_handle); |
| 230 | #endif | ||
| 231 | } | 220 | } |
| 232 | 221 | ||
| 233 | static int amdgpu_pp_suspend(void *handle) | 222 | static int amdgpu_pp_suspend(void *handle) |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index e1fa8731d1e2..3cb5e903cd62 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | |||
| @@ -345,8 +345,8 @@ static int amdgpu_debugfs_ring_init(struct amdgpu_device *adev, | |||
| 345 | ent = debugfs_create_file(name, | 345 | ent = debugfs_create_file(name, |
| 346 | S_IFREG | S_IRUGO, root, | 346 | S_IFREG | S_IRUGO, root, |
| 347 | ring, &amdgpu_debugfs_ring_fops); | 347 | ring, &amdgpu_debugfs_ring_fops); |
| 348 | if (IS_ERR(ent)) | 348 | if (!ent) |
| 349 | return PTR_ERR(ent); | 349 | return -ENOMEM; |
| 350 | 350 | ||
| 351 | i_size_write(ent->d_inode, ring->ring_size + 12); | 351 | i_size_write(ent->d_inode, ring->ring_size + 12); |
| 352 | ring->ent = ent; | 352 | ring->ent = ent; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 887483b8b818..dcaf691f56b5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | |||
| @@ -555,10 +555,13 @@ struct amdgpu_ttm_tt { | |||
| 555 | int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) | 555 | int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) |
| 556 | { | 556 | { |
| 557 | struct amdgpu_ttm_tt *gtt = (void *)ttm; | 557 | struct amdgpu_ttm_tt *gtt = (void *)ttm; |
| 558 | int write = !(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY); | 558 | unsigned int flags = 0; |
| 559 | unsigned pinned = 0; | 559 | unsigned pinned = 0; |
| 560 | int r; | 560 | int r; |
| 561 | 561 | ||
| 562 | if (!(gtt->userflags & AMDGPU_GEM_USERPTR_READONLY)) | ||
| 563 | flags |= FOLL_WRITE; | ||
| 564 | |||
| 562 | if (gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) { | 565 | if (gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) { |
| 563 | /* check that we only use anonymous memory | 566 | /* check that we only use anonymous memory |
| 564 | to prevent problems with writeback */ | 567 | to prevent problems with writeback */ |
| @@ -581,7 +584,7 @@ int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages) | |||
| 581 | list_add(&guptask.list, >t->guptasks); | 584 | list_add(&guptask.list, >t->guptasks); |
| 582 | spin_unlock(>t->guptasklock); | 585 | spin_unlock(>t->guptasklock); |
| 583 | 586 | ||
| 584 | r = get_user_pages(userptr, num_pages, write, 0, p, NULL); | 587 | r = get_user_pages(userptr, num_pages, flags, p, NULL); |
| 585 | 588 | ||
| 586 | spin_lock(>t->guptasklock); | 589 | spin_lock(>t->guptasklock); |
| 587 | list_del(&guptask.list); | 590 | list_del(&guptask.list); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c index 7a05f79818f1..cb3d252f3c78 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c | |||
| @@ -273,7 +273,6 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev) | |||
| 273 | 273 | ||
| 274 | amdgpu_bo_unreserve(*bo); | 274 | amdgpu_bo_unreserve(*bo); |
| 275 | 275 | ||
| 276 | fw_offset = 0; | ||
| 277 | for (i = 0; i < AMDGPU_UCODE_ID_MAXIMUM; i++) { | 276 | for (i = 0; i < AMDGPU_UCODE_ID_MAXIMUM; i++) { |
| 278 | ucode = &adev->firmware.ucode[i]; | 277 | ucode = &adev->firmware.ucode[i]; |
| 279 | if (ucode->fw) { | 278 | if (ucode->fw) { |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index 3b03558ddb01..7fe8fd884f06 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | |||
| @@ -699,6 +699,20 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) | |||
| 699 | case 0x05000009: /* clock table */ | 699 | case 0x05000009: /* clock table */ |
| 700 | break; | 700 | break; |
| 701 | 701 | ||
| 702 | case 0x0500000c: /* hw config */ | ||
| 703 | switch (p->adev->asic_type) { | ||
| 704 | #ifdef CONFIG_DRM_AMDGPU_CIK | ||
| 705 | case CHIP_KAVERI: | ||
| 706 | case CHIP_MULLINS: | ||
| 707 | #endif | ||
| 708 | case CHIP_CARRIZO: | ||
| 709 | break; | ||
| 710 | default: | ||
| 711 | r = -EINVAL; | ||
| 712 | goto out; | ||
| 713 | } | ||
| 714 | break; | ||
| 715 | |||
| 702 | case 0x03000001: /* encode */ | 716 | case 0x03000001: /* encode */ |
| 703 | r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 10, idx + 9, | 717 | r = amdgpu_vce_cs_reloc(p, ib_idx, idx + 10, idx + 9, |
| 704 | *size, 0); | 718 | *size, 0); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index bc4b22c6fc08..06f24322e7c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
| @@ -878,13 +878,13 @@ static void amdgpu_vm_frag_ptes(struct amdgpu_pte_update_params *params, | |||
| 878 | * allocation size to the fragment size. | 878 | * allocation size to the fragment size. |
| 879 | */ | 879 | */ |
| 880 | 880 | ||
| 881 | const uint64_t frag_align = 1 << AMDGPU_LOG2_PAGES_PER_FRAG; | 881 | /* SI and newer are optimized for 64KB */ |
| 882 | uint64_t frag_flags = AMDGPU_PTE_FRAG(AMDGPU_LOG2_PAGES_PER_FRAG); | ||
| 883 | uint64_t frag_align = 1 << AMDGPU_LOG2_PAGES_PER_FRAG; | ||
| 882 | 884 | ||
| 883 | uint64_t frag_start = ALIGN(start, frag_align); | 885 | uint64_t frag_start = ALIGN(start, frag_align); |
| 884 | uint64_t frag_end = end & ~(frag_align - 1); | 886 | uint64_t frag_end = end & ~(frag_align - 1); |
| 885 | 887 | ||
| 886 | uint32_t frag; | ||
| 887 | |||
| 888 | /* system pages are non continuously */ | 888 | /* system pages are non continuously */ |
| 889 | if (params->src || !(flags & AMDGPU_PTE_VALID) || | 889 | if (params->src || !(flags & AMDGPU_PTE_VALID) || |
| 890 | (frag_start >= frag_end)) { | 890 | (frag_start >= frag_end)) { |
| @@ -893,10 +893,6 @@ static void amdgpu_vm_frag_ptes(struct amdgpu_pte_update_params *params, | |||
| 893 | return; | 893 | return; |
| 894 | } | 894 | } |
| 895 | 895 | ||
| 896 | /* use more than 64KB fragment size if possible */ | ||
| 897 | frag = lower_32_bits(frag_start | frag_end); | ||
| 898 | frag = likely(frag) ? __ffs(frag) : 31; | ||
| 899 | |||
| 900 | /* handle the 4K area at the beginning */ | 896 | /* handle the 4K area at the beginning */ |
| 901 | if (start != frag_start) { | 897 | if (start != frag_start) { |
| 902 | amdgpu_vm_update_ptes(params, vm, start, frag_start, | 898 | amdgpu_vm_update_ptes(params, vm, start, frag_start, |
| @@ -906,7 +902,7 @@ static void amdgpu_vm_frag_ptes(struct amdgpu_pte_update_params *params, | |||
| 906 | 902 | ||
| 907 | /* handle the area in the middle */ | 903 | /* handle the area in the middle */ |
| 908 | amdgpu_vm_update_ptes(params, vm, frag_start, frag_end, dst, | 904 | amdgpu_vm_update_ptes(params, vm, frag_start, frag_end, dst, |
| 909 | flags | AMDGPU_PTE_FRAG(frag)); | 905 | flags | frag_flags); |
| 910 | 906 | ||
| 911 | /* handle the 4K area at the end */ | 907 | /* handle the 4K area at the end */ |
| 912 | if (frag_end != end) { | 908 | if (frag_end != end) { |
diff --git a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c index f80a0834e889..3c082e143730 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_dpm.c | |||
| @@ -1514,14 +1514,16 @@ static int cz_dpm_set_powergating_state(void *handle, | |||
| 1514 | return 0; | 1514 | return 0; |
| 1515 | } | 1515 | } |
| 1516 | 1516 | ||
| 1517 | /* borrowed from KV, need future unify */ | ||
| 1518 | static int cz_dpm_get_temperature(struct amdgpu_device *adev) | 1517 | static int cz_dpm_get_temperature(struct amdgpu_device *adev) |
| 1519 | { | 1518 | { |
| 1520 | int actual_temp = 0; | 1519 | int actual_temp = 0; |
| 1521 | uint32_t temp = RREG32_SMC(0xC0300E0C); | 1520 | uint32_t val = RREG32_SMC(ixTHM_TCON_CUR_TMP); |
| 1521 | uint32_t temp = REG_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP); | ||
| 1522 | 1522 | ||
| 1523 | if (temp) | 1523 | if (REG_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP_RANGE_SEL)) |
| 1524 | actual_temp = 1000 * ((temp / 8) - 49); | 1524 | actual_temp = 1000 * ((temp / 8) - 49); |
| 1525 | else | ||
| 1526 | actual_temp = 1000 * (temp / 8); | ||
| 1525 | 1527 | ||
| 1526 | return actual_temp; | 1528 | return actual_temp; |
| 1527 | } | 1529 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 613ebb7ed50f..4108c686aa7c 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c | |||
| @@ -3188,16 +3188,11 @@ static int dce_v10_0_wait_for_idle(void *handle) | |||
| 3188 | return 0; | 3188 | return 0; |
| 3189 | } | 3189 | } |
| 3190 | 3190 | ||
| 3191 | static int dce_v10_0_check_soft_reset(void *handle) | 3191 | static bool dce_v10_0_check_soft_reset(void *handle) |
| 3192 | { | 3192 | { |
| 3193 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 3193 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 3194 | 3194 | ||
| 3195 | if (dce_v10_0_is_display_hung(adev)) | 3195 | return dce_v10_0_is_display_hung(adev); |
| 3196 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang = true; | ||
| 3197 | else | ||
| 3198 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang = false; | ||
| 3199 | |||
| 3200 | return 0; | ||
| 3201 | } | 3196 | } |
| 3202 | 3197 | ||
| 3203 | static int dce_v10_0_soft_reset(void *handle) | 3198 | static int dce_v10_0_soft_reset(void *handle) |
| @@ -3205,9 +3200,6 @@ static int dce_v10_0_soft_reset(void *handle) | |||
| 3205 | u32 srbm_soft_reset = 0, tmp; | 3200 | u32 srbm_soft_reset = 0, tmp; |
| 3206 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 3201 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 3207 | 3202 | ||
| 3208 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_DCE].hang) | ||
| 3209 | return 0; | ||
| 3210 | |||
| 3211 | if (dce_v10_0_is_display_hung(adev)) | 3203 | if (dce_v10_0_is_display_hung(adev)) |
| 3212 | srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK; | 3204 | srbm_soft_reset |= SRBM_SOFT_RESET__SOFT_RESET_DC_MASK; |
| 3213 | 3205 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index 678f5eb6cbc2..f264b8f17ad1 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c | |||
| @@ -3159,6 +3159,7 @@ static int dce_v11_0_sw_fini(void *handle) | |||
| 3159 | 3159 | ||
| 3160 | dce_v11_0_afmt_fini(adev); | 3160 | dce_v11_0_afmt_fini(adev); |
| 3161 | 3161 | ||
| 3162 | drm_mode_config_cleanup(adev->ddev); | ||
| 3162 | adev->mode_info.mode_config_initialized = false; | 3163 | adev->mode_info.mode_config_initialized = false; |
| 3163 | 3164 | ||
| 3164 | return 0; | 3165 | return 0; |
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index a754f2522ba2..c2bd9f045532 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c | |||
| @@ -99,15 +99,15 @@ static void dce_virtual_stop_mc_access(struct amdgpu_device *adev, | |||
| 99 | struct amdgpu_mode_mc_save *save) | 99 | struct amdgpu_mode_mc_save *save) |
| 100 | { | 100 | { |
| 101 | switch (adev->asic_type) { | 101 | switch (adev->asic_type) { |
| 102 | #ifdef CONFIG_DRM_AMDGPU_CIK | ||
| 102 | case CHIP_BONAIRE: | 103 | case CHIP_BONAIRE: |
| 103 | case CHIP_HAWAII: | 104 | case CHIP_HAWAII: |
| 104 | case CHIP_KAVERI: | 105 | case CHIP_KAVERI: |
| 105 | case CHIP_KABINI: | 106 | case CHIP_KABINI: |
| 106 | case CHIP_MULLINS: | 107 | case CHIP_MULLINS: |
| 107 | #ifdef CONFIG_DRM_AMDGPU_CIK | ||
| 108 | dce_v8_0_disable_dce(adev); | 108 | dce_v8_0_disable_dce(adev); |
| 109 | #endif | ||
| 110 | break; | 109 | break; |
| 110 | #endif | ||
| 111 | case CHIP_FIJI: | 111 | case CHIP_FIJI: |
| 112 | case CHIP_TONGA: | 112 | case CHIP_TONGA: |
| 113 | dce_v10_0_disable_dce(adev); | 113 | dce_v10_0_disable_dce(adev); |
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 6c6ff57b1c95..ee6a48a09214 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | |||
| @@ -4087,14 +4087,21 @@ static int gfx_v8_0_rlc_load_microcode(struct amdgpu_device *adev) | |||
| 4087 | static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev) | 4087 | static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev) |
| 4088 | { | 4088 | { |
| 4089 | int r; | 4089 | int r; |
| 4090 | u32 tmp; | ||
| 4090 | 4091 | ||
| 4091 | gfx_v8_0_rlc_stop(adev); | 4092 | gfx_v8_0_rlc_stop(adev); |
| 4092 | 4093 | ||
| 4093 | /* disable CG */ | 4094 | /* disable CG */ |
| 4094 | WREG32(mmRLC_CGCG_CGLS_CTRL, 0); | 4095 | tmp = RREG32(mmRLC_CGCG_CGLS_CTRL); |
| 4096 | tmp &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | | ||
| 4097 | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK); | ||
| 4098 | WREG32(mmRLC_CGCG_CGLS_CTRL, tmp); | ||
| 4095 | if (adev->asic_type == CHIP_POLARIS11 || | 4099 | if (adev->asic_type == CHIP_POLARIS11 || |
| 4096 | adev->asic_type == CHIP_POLARIS10) | 4100 | adev->asic_type == CHIP_POLARIS10) { |
| 4097 | WREG32(mmRLC_CGCG_CGLS_CTRL_3D, 0); | 4101 | tmp = RREG32(mmRLC_CGCG_CGLS_CTRL_3D); |
| 4102 | tmp &= ~0x3; | ||
| 4103 | WREG32(mmRLC_CGCG_CGLS_CTRL_3D, tmp); | ||
| 4104 | } | ||
| 4098 | 4105 | ||
| 4099 | /* disable PG */ | 4106 | /* disable PG */ |
| 4100 | WREG32(mmRLC_PG_CNTL, 0); | 4107 | WREG32(mmRLC_PG_CNTL, 0); |
| @@ -5137,7 +5144,7 @@ static int gfx_v8_0_wait_for_idle(void *handle) | |||
| 5137 | return -ETIMEDOUT; | 5144 | return -ETIMEDOUT; |
| 5138 | } | 5145 | } |
| 5139 | 5146 | ||
| 5140 | static int gfx_v8_0_check_soft_reset(void *handle) | 5147 | static bool gfx_v8_0_check_soft_reset(void *handle) |
| 5141 | { | 5148 | { |
| 5142 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 5149 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 5143 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | 5150 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; |
| @@ -5189,16 +5196,14 @@ static int gfx_v8_0_check_soft_reset(void *handle) | |||
| 5189 | SRBM_SOFT_RESET, SOFT_RESET_SEM, 1); | 5196 | SRBM_SOFT_RESET, SOFT_RESET_SEM, 1); |
| 5190 | 5197 | ||
| 5191 | if (grbm_soft_reset || srbm_soft_reset) { | 5198 | if (grbm_soft_reset || srbm_soft_reset) { |
| 5192 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang = true; | ||
| 5193 | adev->gfx.grbm_soft_reset = grbm_soft_reset; | 5199 | adev->gfx.grbm_soft_reset = grbm_soft_reset; |
| 5194 | adev->gfx.srbm_soft_reset = srbm_soft_reset; | 5200 | adev->gfx.srbm_soft_reset = srbm_soft_reset; |
| 5201 | return true; | ||
| 5195 | } else { | 5202 | } else { |
| 5196 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang = false; | ||
| 5197 | adev->gfx.grbm_soft_reset = 0; | 5203 | adev->gfx.grbm_soft_reset = 0; |
| 5198 | adev->gfx.srbm_soft_reset = 0; | 5204 | adev->gfx.srbm_soft_reset = 0; |
| 5205 | return false; | ||
| 5199 | } | 5206 | } |
| 5200 | |||
| 5201 | return 0; | ||
| 5202 | } | 5207 | } |
| 5203 | 5208 | ||
| 5204 | static void gfx_v8_0_inactive_hqd(struct amdgpu_device *adev, | 5209 | static void gfx_v8_0_inactive_hqd(struct amdgpu_device *adev, |
| @@ -5226,7 +5231,8 @@ static int gfx_v8_0_pre_soft_reset(void *handle) | |||
| 5226 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 5231 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 5227 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | 5232 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; |
| 5228 | 5233 | ||
| 5229 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang) | 5234 | if ((!adev->gfx.grbm_soft_reset) && |
| 5235 | (!adev->gfx.srbm_soft_reset)) | ||
| 5230 | return 0; | 5236 | return 0; |
| 5231 | 5237 | ||
| 5232 | grbm_soft_reset = adev->gfx.grbm_soft_reset; | 5238 | grbm_soft_reset = adev->gfx.grbm_soft_reset; |
| @@ -5264,7 +5270,8 @@ static int gfx_v8_0_soft_reset(void *handle) | |||
| 5264 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | 5270 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; |
| 5265 | u32 tmp; | 5271 | u32 tmp; |
| 5266 | 5272 | ||
| 5267 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang) | 5273 | if ((!adev->gfx.grbm_soft_reset) && |
| 5274 | (!adev->gfx.srbm_soft_reset)) | ||
| 5268 | return 0; | 5275 | return 0; |
| 5269 | 5276 | ||
| 5270 | grbm_soft_reset = adev->gfx.grbm_soft_reset; | 5277 | grbm_soft_reset = adev->gfx.grbm_soft_reset; |
| @@ -5334,7 +5341,8 @@ static int gfx_v8_0_post_soft_reset(void *handle) | |||
| 5334 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 5341 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 5335 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; | 5342 | u32 grbm_soft_reset = 0, srbm_soft_reset = 0; |
| 5336 | 5343 | ||
| 5337 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GFX].hang) | 5344 | if ((!adev->gfx.grbm_soft_reset) && |
| 5345 | (!adev->gfx.srbm_soft_reset)) | ||
| 5338 | return 0; | 5346 | return 0; |
| 5339 | 5347 | ||
| 5340 | grbm_soft_reset = adev->gfx.grbm_soft_reset; | 5348 | grbm_soft_reset = adev->gfx.grbm_soft_reset; |
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 1b319f5bc696..c22ef140a542 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | |||
| @@ -1099,7 +1099,7 @@ static int gmc_v8_0_wait_for_idle(void *handle) | |||
| 1099 | 1099 | ||
| 1100 | } | 1100 | } |
| 1101 | 1101 | ||
| 1102 | static int gmc_v8_0_check_soft_reset(void *handle) | 1102 | static bool gmc_v8_0_check_soft_reset(void *handle) |
| 1103 | { | 1103 | { |
| 1104 | u32 srbm_soft_reset = 0; | 1104 | u32 srbm_soft_reset = 0; |
| 1105 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1105 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| @@ -1116,20 +1116,19 @@ static int gmc_v8_0_check_soft_reset(void *handle) | |||
| 1116 | SRBM_SOFT_RESET, SOFT_RESET_MC, 1); | 1116 | SRBM_SOFT_RESET, SOFT_RESET_MC, 1); |
| 1117 | } | 1117 | } |
| 1118 | if (srbm_soft_reset) { | 1118 | if (srbm_soft_reset) { |
| 1119 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang = true; | ||
| 1120 | adev->mc.srbm_soft_reset = srbm_soft_reset; | 1119 | adev->mc.srbm_soft_reset = srbm_soft_reset; |
| 1120 | return true; | ||
| 1121 | } else { | 1121 | } else { |
| 1122 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang = false; | ||
| 1123 | adev->mc.srbm_soft_reset = 0; | 1122 | adev->mc.srbm_soft_reset = 0; |
| 1123 | return false; | ||
| 1124 | } | 1124 | } |
| 1125 | return 0; | ||
| 1126 | } | 1125 | } |
| 1127 | 1126 | ||
| 1128 | static int gmc_v8_0_pre_soft_reset(void *handle) | 1127 | static int gmc_v8_0_pre_soft_reset(void *handle) |
| 1129 | { | 1128 | { |
| 1130 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1129 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1131 | 1130 | ||
| 1132 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang) | 1131 | if (!adev->mc.srbm_soft_reset) |
| 1133 | return 0; | 1132 | return 0; |
| 1134 | 1133 | ||
| 1135 | gmc_v8_0_mc_stop(adev, &adev->mc.save); | 1134 | gmc_v8_0_mc_stop(adev, &adev->mc.save); |
| @@ -1145,7 +1144,7 @@ static int gmc_v8_0_soft_reset(void *handle) | |||
| 1145 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1144 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1146 | u32 srbm_soft_reset; | 1145 | u32 srbm_soft_reset; |
| 1147 | 1146 | ||
| 1148 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang) | 1147 | if (!adev->mc.srbm_soft_reset) |
| 1149 | return 0; | 1148 | return 0; |
| 1150 | srbm_soft_reset = adev->mc.srbm_soft_reset; | 1149 | srbm_soft_reset = adev->mc.srbm_soft_reset; |
| 1151 | 1150 | ||
| @@ -1175,7 +1174,7 @@ static int gmc_v8_0_post_soft_reset(void *handle) | |||
| 1175 | { | 1174 | { |
| 1176 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1175 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1177 | 1176 | ||
| 1178 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_GMC].hang) | 1177 | if (!adev->mc.srbm_soft_reset) |
| 1179 | return 0; | 1178 | return 0; |
| 1180 | 1179 | ||
| 1181 | gmc_v8_0_mc_resume(adev, &adev->mc.save); | 1180 | gmc_v8_0_mc_resume(adev, &adev->mc.save); |
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index f325fd86430b..a9d10941fb53 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | |||
| @@ -1268,7 +1268,7 @@ static int sdma_v3_0_wait_for_idle(void *handle) | |||
| 1268 | return -ETIMEDOUT; | 1268 | return -ETIMEDOUT; |
| 1269 | } | 1269 | } |
| 1270 | 1270 | ||
| 1271 | static int sdma_v3_0_check_soft_reset(void *handle) | 1271 | static bool sdma_v3_0_check_soft_reset(void *handle) |
| 1272 | { | 1272 | { |
| 1273 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1273 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1274 | u32 srbm_soft_reset = 0; | 1274 | u32 srbm_soft_reset = 0; |
| @@ -1281,14 +1281,12 @@ static int sdma_v3_0_check_soft_reset(void *handle) | |||
| 1281 | } | 1281 | } |
| 1282 | 1282 | ||
| 1283 | if (srbm_soft_reset) { | 1283 | if (srbm_soft_reset) { |
| 1284 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang = true; | ||
| 1285 | adev->sdma.srbm_soft_reset = srbm_soft_reset; | 1284 | adev->sdma.srbm_soft_reset = srbm_soft_reset; |
| 1285 | return true; | ||
| 1286 | } else { | 1286 | } else { |
| 1287 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang = false; | ||
| 1288 | adev->sdma.srbm_soft_reset = 0; | 1287 | adev->sdma.srbm_soft_reset = 0; |
| 1288 | return false; | ||
| 1289 | } | 1289 | } |
| 1290 | |||
| 1291 | return 0; | ||
| 1292 | } | 1290 | } |
| 1293 | 1291 | ||
| 1294 | static int sdma_v3_0_pre_soft_reset(void *handle) | 1292 | static int sdma_v3_0_pre_soft_reset(void *handle) |
| @@ -1296,7 +1294,7 @@ static int sdma_v3_0_pre_soft_reset(void *handle) | |||
| 1296 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1294 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1297 | u32 srbm_soft_reset = 0; | 1295 | u32 srbm_soft_reset = 0; |
| 1298 | 1296 | ||
| 1299 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang) | 1297 | if (!adev->sdma.srbm_soft_reset) |
| 1300 | return 0; | 1298 | return 0; |
| 1301 | 1299 | ||
| 1302 | srbm_soft_reset = adev->sdma.srbm_soft_reset; | 1300 | srbm_soft_reset = adev->sdma.srbm_soft_reset; |
| @@ -1315,7 +1313,7 @@ static int sdma_v3_0_post_soft_reset(void *handle) | |||
| 1315 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1313 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1316 | u32 srbm_soft_reset = 0; | 1314 | u32 srbm_soft_reset = 0; |
| 1317 | 1315 | ||
| 1318 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang) | 1316 | if (!adev->sdma.srbm_soft_reset) |
| 1319 | return 0; | 1317 | return 0; |
| 1320 | 1318 | ||
| 1321 | srbm_soft_reset = adev->sdma.srbm_soft_reset; | 1319 | srbm_soft_reset = adev->sdma.srbm_soft_reset; |
| @@ -1335,7 +1333,7 @@ static int sdma_v3_0_soft_reset(void *handle) | |||
| 1335 | u32 srbm_soft_reset = 0; | 1333 | u32 srbm_soft_reset = 0; |
| 1336 | u32 tmp; | 1334 | u32 tmp; |
| 1337 | 1335 | ||
| 1338 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_SDMA].hang) | 1336 | if (!adev->sdma.srbm_soft_reset) |
| 1339 | return 0; | 1337 | return 0; |
| 1340 | 1338 | ||
| 1341 | srbm_soft_reset = adev->sdma.srbm_soft_reset; | 1339 | srbm_soft_reset = adev->sdma.srbm_soft_reset; |
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 8bd08925b370..3de7bca5854b 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c | |||
| @@ -3499,6 +3499,12 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev, | |||
| 3499 | max_sclk = 75000; | 3499 | max_sclk = 75000; |
| 3500 | max_mclk = 80000; | 3500 | max_mclk = 80000; |
| 3501 | } | 3501 | } |
| 3502 | /* Limit clocks for some HD8600 parts */ | ||
| 3503 | if (adev->pdev->device == 0x6660 && | ||
| 3504 | adev->pdev->revision == 0x83) { | ||
| 3505 | max_sclk = 75000; | ||
| 3506 | max_mclk = 80000; | ||
| 3507 | } | ||
| 3502 | 3508 | ||
| 3503 | if (rps->vce_active) { | 3509 | if (rps->vce_active) { |
| 3504 | rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk; | 3510 | rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk; |
diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c index d127d59f953a..b4ea229bb449 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c | |||
| @@ -373,7 +373,7 @@ static int tonga_ih_wait_for_idle(void *handle) | |||
| 373 | return -ETIMEDOUT; | 373 | return -ETIMEDOUT; |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | static int tonga_ih_check_soft_reset(void *handle) | 376 | static bool tonga_ih_check_soft_reset(void *handle) |
| 377 | { | 377 | { |
| 378 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 378 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 379 | u32 srbm_soft_reset = 0; | 379 | u32 srbm_soft_reset = 0; |
| @@ -384,21 +384,19 @@ static int tonga_ih_check_soft_reset(void *handle) | |||
| 384 | SOFT_RESET_IH, 1); | 384 | SOFT_RESET_IH, 1); |
| 385 | 385 | ||
| 386 | if (srbm_soft_reset) { | 386 | if (srbm_soft_reset) { |
| 387 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang = true; | ||
| 388 | adev->irq.srbm_soft_reset = srbm_soft_reset; | 387 | adev->irq.srbm_soft_reset = srbm_soft_reset; |
| 388 | return true; | ||
| 389 | } else { | 389 | } else { |
| 390 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang = false; | ||
| 391 | adev->irq.srbm_soft_reset = 0; | 390 | adev->irq.srbm_soft_reset = 0; |
| 391 | return false; | ||
| 392 | } | 392 | } |
| 393 | |||
| 394 | return 0; | ||
| 395 | } | 393 | } |
| 396 | 394 | ||
| 397 | static int tonga_ih_pre_soft_reset(void *handle) | 395 | static int tonga_ih_pre_soft_reset(void *handle) |
| 398 | { | 396 | { |
| 399 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 397 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 400 | 398 | ||
| 401 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang) | 399 | if (!adev->irq.srbm_soft_reset) |
| 402 | return 0; | 400 | return 0; |
| 403 | 401 | ||
| 404 | return tonga_ih_hw_fini(adev); | 402 | return tonga_ih_hw_fini(adev); |
| @@ -408,7 +406,7 @@ static int tonga_ih_post_soft_reset(void *handle) | |||
| 408 | { | 406 | { |
| 409 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 407 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 410 | 408 | ||
| 411 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang) | 409 | if (!adev->irq.srbm_soft_reset) |
| 412 | return 0; | 410 | return 0; |
| 413 | 411 | ||
| 414 | return tonga_ih_hw_init(adev); | 412 | return tonga_ih_hw_init(adev); |
| @@ -419,7 +417,7 @@ static int tonga_ih_soft_reset(void *handle) | |||
| 419 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 417 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 420 | u32 srbm_soft_reset; | 418 | u32 srbm_soft_reset; |
| 421 | 419 | ||
| 422 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_IH].hang) | 420 | if (!adev->irq.srbm_soft_reset) |
| 423 | return 0; | 421 | return 0; |
| 424 | srbm_soft_reset = adev->irq.srbm_soft_reset; | 422 | srbm_soft_reset = adev->irq.srbm_soft_reset; |
| 425 | 423 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index e0fd9f21ed95..ab3df6d75656 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | |||
| @@ -770,7 +770,7 @@ static int uvd_v6_0_wait_for_idle(void *handle) | |||
| 770 | } | 770 | } |
| 771 | 771 | ||
| 772 | #define AMDGPU_UVD_STATUS_BUSY_MASK 0xfd | 772 | #define AMDGPU_UVD_STATUS_BUSY_MASK 0xfd |
| 773 | static int uvd_v6_0_check_soft_reset(void *handle) | 773 | static bool uvd_v6_0_check_soft_reset(void *handle) |
| 774 | { | 774 | { |
| 775 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 775 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 776 | u32 srbm_soft_reset = 0; | 776 | u32 srbm_soft_reset = 0; |
| @@ -782,19 +782,19 @@ static int uvd_v6_0_check_soft_reset(void *handle) | |||
| 782 | srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_UVD, 1); | 782 | srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_UVD, 1); |
| 783 | 783 | ||
| 784 | if (srbm_soft_reset) { | 784 | if (srbm_soft_reset) { |
| 785 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang = true; | ||
| 786 | adev->uvd.srbm_soft_reset = srbm_soft_reset; | 785 | adev->uvd.srbm_soft_reset = srbm_soft_reset; |
| 786 | return true; | ||
| 787 | } else { | 787 | } else { |
| 788 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang = false; | ||
| 789 | adev->uvd.srbm_soft_reset = 0; | 788 | adev->uvd.srbm_soft_reset = 0; |
| 789 | return false; | ||
| 790 | } | 790 | } |
| 791 | return 0; | ||
| 792 | } | 791 | } |
| 792 | |||
| 793 | static int uvd_v6_0_pre_soft_reset(void *handle) | 793 | static int uvd_v6_0_pre_soft_reset(void *handle) |
| 794 | { | 794 | { |
| 795 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 795 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 796 | 796 | ||
| 797 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang) | 797 | if (!adev->uvd.srbm_soft_reset) |
| 798 | return 0; | 798 | return 0; |
| 799 | 799 | ||
| 800 | uvd_v6_0_stop(adev); | 800 | uvd_v6_0_stop(adev); |
| @@ -806,7 +806,7 @@ static int uvd_v6_0_soft_reset(void *handle) | |||
| 806 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 806 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 807 | u32 srbm_soft_reset; | 807 | u32 srbm_soft_reset; |
| 808 | 808 | ||
| 809 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang) | 809 | if (!adev->uvd.srbm_soft_reset) |
| 810 | return 0; | 810 | return 0; |
| 811 | srbm_soft_reset = adev->uvd.srbm_soft_reset; | 811 | srbm_soft_reset = adev->uvd.srbm_soft_reset; |
| 812 | 812 | ||
| @@ -836,7 +836,7 @@ static int uvd_v6_0_post_soft_reset(void *handle) | |||
| 836 | { | 836 | { |
| 837 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 837 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 838 | 838 | ||
| 839 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_UVD].hang) | 839 | if (!adev->uvd.srbm_soft_reset) |
| 840 | return 0; | 840 | return 0; |
| 841 | 841 | ||
| 842 | mdelay(5); | 842 | mdelay(5); |
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 3f6db4ec0102..8533269ec160 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | |||
| @@ -561,7 +561,7 @@ static int vce_v3_0_wait_for_idle(void *handle) | |||
| 561 | #define AMDGPU_VCE_STATUS_BUSY_MASK (VCE_STATUS_VCPU_REPORT_AUTO_BUSY_MASK | \ | 561 | #define AMDGPU_VCE_STATUS_BUSY_MASK (VCE_STATUS_VCPU_REPORT_AUTO_BUSY_MASK | \ |
| 562 | VCE_STATUS_VCPU_REPORT_RB0_BUSY_MASK) | 562 | VCE_STATUS_VCPU_REPORT_RB0_BUSY_MASK) |
| 563 | 563 | ||
| 564 | static int vce_v3_0_check_soft_reset(void *handle) | 564 | static bool vce_v3_0_check_soft_reset(void *handle) |
| 565 | { | 565 | { |
| 566 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 566 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 567 | u32 srbm_soft_reset = 0; | 567 | u32 srbm_soft_reset = 0; |
| @@ -591,16 +591,15 @@ static int vce_v3_0_check_soft_reset(void *handle) | |||
| 591 | srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1); | 591 | srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1); |
| 592 | } | 592 | } |
| 593 | WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0); | 593 | WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0); |
| 594 | mutex_unlock(&adev->grbm_idx_mutex); | ||
| 594 | 595 | ||
| 595 | if (srbm_soft_reset) { | 596 | if (srbm_soft_reset) { |
| 596 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang = true; | ||
| 597 | adev->vce.srbm_soft_reset = srbm_soft_reset; | 597 | adev->vce.srbm_soft_reset = srbm_soft_reset; |
| 598 | return true; | ||
| 598 | } else { | 599 | } else { |
| 599 | adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang = false; | ||
| 600 | adev->vce.srbm_soft_reset = 0; | 600 | adev->vce.srbm_soft_reset = 0; |
| 601 | return false; | ||
| 601 | } | 602 | } |
| 602 | mutex_unlock(&adev->grbm_idx_mutex); | ||
| 603 | return 0; | ||
| 604 | } | 603 | } |
| 605 | 604 | ||
| 606 | static int vce_v3_0_soft_reset(void *handle) | 605 | static int vce_v3_0_soft_reset(void *handle) |
| @@ -608,7 +607,7 @@ static int vce_v3_0_soft_reset(void *handle) | |||
| 608 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 607 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 609 | u32 srbm_soft_reset; | 608 | u32 srbm_soft_reset; |
| 610 | 609 | ||
| 611 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang) | 610 | if (!adev->vce.srbm_soft_reset) |
| 612 | return 0; | 611 | return 0; |
| 613 | srbm_soft_reset = adev->vce.srbm_soft_reset; | 612 | srbm_soft_reset = adev->vce.srbm_soft_reset; |
| 614 | 613 | ||
| @@ -638,7 +637,7 @@ static int vce_v3_0_pre_soft_reset(void *handle) | |||
| 638 | { | 637 | { |
| 639 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 638 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 640 | 639 | ||
| 641 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang) | 640 | if (!adev->vce.srbm_soft_reset) |
| 642 | return 0; | 641 | return 0; |
| 643 | 642 | ||
| 644 | mdelay(5); | 643 | mdelay(5); |
| @@ -651,7 +650,7 @@ static int vce_v3_0_post_soft_reset(void *handle) | |||
| 651 | { | 650 | { |
| 652 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 651 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 653 | 652 | ||
| 654 | if (!adev->ip_block_status[AMD_IP_BLOCK_TYPE_VCE].hang) | 653 | if (!adev->vce.srbm_soft_reset) |
| 655 | return 0; | 654 | return 0; |
| 656 | 655 | ||
| 657 | mdelay(5); | 656 | mdelay(5); |
diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index c934b78c9e2f..bec8125bceb0 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h | |||
| @@ -165,7 +165,7 @@ struct amd_ip_funcs { | |||
| 165 | /* poll for idle */ | 165 | /* poll for idle */ |
| 166 | int (*wait_for_idle)(void *handle); | 166 | int (*wait_for_idle)(void *handle); |
| 167 | /* check soft reset the IP block */ | 167 | /* check soft reset the IP block */ |
| 168 | int (*check_soft_reset)(void *handle); | 168 | bool (*check_soft_reset)(void *handle); |
| 169 | /* pre soft reset the IP block */ | 169 | /* pre soft reset the IP block */ |
| 170 | int (*pre_soft_reset)(void *handle); | 170 | int (*pre_soft_reset)(void *handle); |
| 171 | /* soft reset the IP block */ | 171 | /* soft reset the IP block */ |
diff --git a/drivers/gpu/drm/amd/powerplay/Kconfig b/drivers/gpu/drm/amd/powerplay/Kconfig deleted file mode 100644 index af380335b425..000000000000 --- a/drivers/gpu/drm/amd/powerplay/Kconfig +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | config DRM_AMD_POWERPLAY | ||
| 2 | bool "Enable AMD powerplay component" | ||
| 3 | depends on DRM_AMDGPU | ||
| 4 | default n | ||
| 5 | help | ||
| 6 | select this option will enable AMD powerplay component. | ||
diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c index 92b117843875..8cee4e0f9fde 100644 --- a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c | |||
| @@ -49,6 +49,7 @@ static const pem_event_action * const uninitialize_event[] = { | |||
| 49 | uninitialize_display_phy_access_tasks, | 49 | uninitialize_display_phy_access_tasks, |
| 50 | disable_gfx_voltage_island_power_gating_tasks, | 50 | disable_gfx_voltage_island_power_gating_tasks, |
| 51 | disable_gfx_clock_gating_tasks, | 51 | disable_gfx_clock_gating_tasks, |
| 52 | uninitialize_thermal_controller_tasks, | ||
| 52 | set_boot_state_tasks, | 53 | set_boot_state_tasks, |
| 53 | adjust_power_state_tasks, | 54 | adjust_power_state_tasks, |
| 54 | disable_dynamic_state_management_tasks, | 55 | disable_dynamic_state_management_tasks, |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index 7e4fcbbbe086..960424913496 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c | |||
| @@ -1785,6 +1785,21 @@ static int cz_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_c | |||
| 1785 | return 0; | 1785 | return 0; |
| 1786 | } | 1786 | } |
| 1787 | 1787 | ||
| 1788 | static int cz_thermal_get_temperature(struct pp_hwmgr *hwmgr) | ||
| 1789 | { | ||
| 1790 | int actual_temp = 0; | ||
| 1791 | uint32_t val = cgs_read_ind_register(hwmgr->device, | ||
| 1792 | CGS_IND_REG__SMC, ixTHM_TCON_CUR_TMP); | ||
| 1793 | uint32_t temp = PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP); | ||
| 1794 | |||
| 1795 | if (PHM_GET_FIELD(val, THM_TCON_CUR_TMP, CUR_TEMP_RANGE_SEL)) | ||
| 1796 | actual_temp = ((temp / 8) - 49) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; | ||
| 1797 | else | ||
| 1798 | actual_temp = (temp / 8) * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; | ||
| 1799 | |||
| 1800 | return actual_temp; | ||
| 1801 | } | ||
| 1802 | |||
| 1788 | static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) | 1803 | static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) |
| 1789 | { | 1804 | { |
| 1790 | struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); | 1805 | struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); |
| @@ -1881,6 +1896,9 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, int32_t *value) | |||
| 1881 | case AMDGPU_PP_SENSOR_VCE_POWER: | 1896 | case AMDGPU_PP_SENSOR_VCE_POWER: |
| 1882 | *value = cz_hwmgr->vce_power_gated ? 0 : 1; | 1897 | *value = cz_hwmgr->vce_power_gated ? 0 : 1; |
| 1883 | return 0; | 1898 | return 0; |
| 1899 | case AMDGPU_PP_SENSOR_GPU_TEMP: | ||
| 1900 | *value = cz_thermal_get_temperature(hwmgr); | ||
| 1901 | return 0; | ||
| 1884 | default: | 1902 | default: |
| 1885 | return -EINVAL; | 1903 | return -EINVAL; |
| 1886 | } | 1904 | } |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 508245d49d33..609996c84ad5 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | |||
| @@ -1030,20 +1030,19 @@ static int smu7_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) | |||
| 1030 | struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); | 1030 | struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); |
| 1031 | 1031 | ||
| 1032 | /* disable SCLK dpm */ | 1032 | /* disable SCLK dpm */ |
| 1033 | if (!data->sclk_dpm_key_disabled) | 1033 | if (!data->sclk_dpm_key_disabled) { |
| 1034 | PP_ASSERT_WITH_CODE( | 1034 | PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), |
| 1035 | (smum_send_msg_to_smc(hwmgr->smumgr, | 1035 | "Trying to disable SCLK DPM when DPM is disabled", |
| 1036 | PPSMC_MSG_DPM_Disable) == 0), | 1036 | return 0); |
| 1037 | "Failed to disable SCLK DPM!", | 1037 | smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DPM_Disable); |
| 1038 | return -EINVAL); | 1038 | } |
| 1039 | 1039 | ||
| 1040 | /* disable MCLK dpm */ | 1040 | /* disable MCLK dpm */ |
| 1041 | if (!data->mclk_dpm_key_disabled) { | 1041 | if (!data->mclk_dpm_key_disabled) { |
| 1042 | PP_ASSERT_WITH_CODE( | 1042 | PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), |
| 1043 | (smum_send_msg_to_smc(hwmgr->smumgr, | 1043 | "Trying to disable MCLK DPM when DPM is disabled", |
| 1044 | PPSMC_MSG_MCLKDPM_Disable) == 0), | 1044 | return 0); |
| 1045 | "Failed to disable MCLK DPM!", | 1045 | smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_MCLKDPM_Disable); |
| 1046 | return -EINVAL); | ||
| 1047 | } | 1046 | } |
| 1048 | 1047 | ||
| 1049 | return 0; | 1048 | return 0; |
| @@ -1069,10 +1068,13 @@ static int smu7_stop_dpm(struct pp_hwmgr *hwmgr) | |||
| 1069 | return -EINVAL); | 1068 | return -EINVAL); |
| 1070 | } | 1069 | } |
| 1071 | 1070 | ||
| 1072 | if (smu7_disable_sclk_mclk_dpm(hwmgr)) { | 1071 | smu7_disable_sclk_mclk_dpm(hwmgr); |
| 1073 | printk(KERN_ERR "Failed to disable Sclk DPM and Mclk DPM!"); | 1072 | |
| 1074 | return -EINVAL; | 1073 | PP_ASSERT_WITH_CODE(true == smum_is_dpm_running(hwmgr), |
| 1075 | } | 1074 | "Trying to disable voltage DPM when DPM is disabled", |
| 1075 | return 0); | ||
| 1076 | |||
| 1077 | smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Voltage_Cntl_Disable); | ||
| 1076 | 1078 | ||
| 1077 | return 0; | 1079 | return 0; |
| 1078 | } | 1080 | } |
| @@ -1226,7 +1228,7 @@ int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr) | |||
| 1226 | PP_ASSERT_WITH_CODE((0 == tmp_result), | 1228 | PP_ASSERT_WITH_CODE((0 == tmp_result), |
| 1227 | "Failed to enable VR hot GPIO interrupt!", result = tmp_result); | 1229 | "Failed to enable VR hot GPIO interrupt!", result = tmp_result); |
| 1228 | 1230 | ||
| 1229 | smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)PPSMC_HasDisplay); | 1231 | smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)PPSMC_NoDisplay); |
| 1230 | 1232 | ||
| 1231 | tmp_result = smu7_enable_sclk_control(hwmgr); | 1233 | tmp_result = smu7_enable_sclk_control(hwmgr); |
| 1232 | PP_ASSERT_WITH_CODE((0 == tmp_result), | 1234 | PP_ASSERT_WITH_CODE((0 == tmp_result), |
| @@ -1306,6 +1308,12 @@ int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr) | |||
| 1306 | PP_ASSERT_WITH_CODE((tmp_result == 0), | 1308 | PP_ASSERT_WITH_CODE((tmp_result == 0), |
| 1307 | "Failed to disable thermal auto throttle!", result = tmp_result); | 1309 | "Failed to disable thermal auto throttle!", result = tmp_result); |
| 1308 | 1310 | ||
| 1311 | if (1 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, FEATURE_STATUS, AVS_ON)) { | ||
| 1312 | PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DisableAvfs)), | ||
| 1313 | "Failed to disable AVFS!", | ||
| 1314 | return -EINVAL); | ||
| 1315 | } | ||
| 1316 | |||
| 1309 | tmp_result = smu7_stop_dpm(hwmgr); | 1317 | tmp_result = smu7_stop_dpm(hwmgr); |
| 1310 | PP_ASSERT_WITH_CODE((tmp_result == 0), | 1318 | PP_ASSERT_WITH_CODE((tmp_result == 0), |
| 1311 | "Failed to stop DPM!", result = tmp_result); | 1319 | "Failed to stop DPM!", result = tmp_result); |
| @@ -1452,8 +1460,10 @@ static int smu7_get_evv_voltages(struct pp_hwmgr *hwmgr) | |||
| 1452 | struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL; | 1460 | struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = NULL; |
| 1453 | 1461 | ||
| 1454 | 1462 | ||
| 1455 | if (table_info != NULL) | 1463 | if (table_info == NULL) |
| 1456 | sclk_table = table_info->vdd_dep_on_sclk; | 1464 | return -EINVAL; |
| 1465 | |||
| 1466 | sclk_table = table_info->vdd_dep_on_sclk; | ||
| 1457 | 1467 | ||
| 1458 | for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) { | 1468 | for (i = 0; i < SMU7_MAX_LEAKAGE_COUNT; i++) { |
| 1459 | vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; | 1469 | vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; |
| @@ -3802,13 +3812,15 @@ static inline bool smu7_are_power_levels_equal(const struct smu7_performance_lev | |||
| 3802 | 3812 | ||
| 3803 | int smu7_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal) | 3813 | int smu7_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal) |
| 3804 | { | 3814 | { |
| 3805 | const struct smu7_power_state *psa = cast_const_phw_smu7_power_state(pstate1); | 3815 | const struct smu7_power_state *psa; |
| 3806 | const struct smu7_power_state *psb = cast_const_phw_smu7_power_state(pstate2); | 3816 | const struct smu7_power_state *psb; |
| 3807 | int i; | 3817 | int i; |
| 3808 | 3818 | ||
| 3809 | if (pstate1 == NULL || pstate2 == NULL || equal == NULL) | 3819 | if (pstate1 == NULL || pstate2 == NULL || equal == NULL) |
| 3810 | return -EINVAL; | 3820 | return -EINVAL; |
| 3811 | 3821 | ||
| 3822 | psa = cast_const_phw_smu7_power_state(pstate1); | ||
| 3823 | psb = cast_const_phw_smu7_power_state(pstate2); | ||
| 3812 | /* If the two states don't even have the same number of performance levels they cannot be the same state. */ | 3824 | /* If the two states don't even have the same number of performance levels they cannot be the same state. */ |
| 3813 | if (psa->performance_level_count != psb->performance_level_count) { | 3825 | if (psa->performance_level_count != psb->performance_level_count) { |
| 3814 | *equal = false; | 3826 | *equal = false; |
| @@ -4324,6 +4336,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = { | |||
| 4324 | .set_mclk_od = smu7_set_mclk_od, | 4336 | .set_mclk_od = smu7_set_mclk_od, |
| 4325 | .get_clock_by_type = smu7_get_clock_by_type, | 4337 | .get_clock_by_type = smu7_get_clock_by_type, |
| 4326 | .read_sensor = smu7_read_sensor, | 4338 | .read_sensor = smu7_read_sensor, |
| 4339 | .dynamic_state_management_disable = smu7_disable_dpm_tasks, | ||
| 4327 | }; | 4340 | }; |
| 4328 | 4341 | ||
| 4329 | uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, | 4342 | uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, |
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c index eda802bc63c8..8c889caba420 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c | |||
| @@ -2458,7 +2458,7 @@ static int iceland_set_mc_special_registers(struct pp_hwmgr *hwmgr, | |||
| 2458 | PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), | 2458 | PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), |
| 2459 | "Invalid VramInfo table.", return -EINVAL); | 2459 | "Invalid VramInfo table.", return -EINVAL); |
| 2460 | 2460 | ||
| 2461 | if (!data->is_memory_gddr5) { | 2461 | if (!data->is_memory_gddr5 && j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE) { |
| 2462 | table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; | 2462 | table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; |
| 2463 | table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; | 2463 | table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; |
| 2464 | for (k = 0; k < table->num_entries; k++) { | 2464 | for (k = 0; k < table->num_entries; k++) { |
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index 2f58e9e2a59c..a51f8cbcfe26 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c | |||
| @@ -332,17 +332,19 @@ static void armada_drm_crtc_dpms(struct drm_crtc *crtc, int dpms) | |||
| 332 | { | 332 | { |
| 333 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); | 333 | struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); |
| 334 | 334 | ||
| 335 | if (dcrtc->dpms != dpms) { | 335 | if (dpms_blanked(dcrtc->dpms) != dpms_blanked(dpms)) { |
| 336 | dcrtc->dpms = dpms; | ||
| 337 | if (!IS_ERR(dcrtc->clk) && !dpms_blanked(dpms)) | ||
| 338 | WARN_ON(clk_prepare_enable(dcrtc->clk)); | ||
| 339 | armada_drm_crtc_update(dcrtc); | ||
| 340 | if (!IS_ERR(dcrtc->clk) && dpms_blanked(dpms)) | ||
| 341 | clk_disable_unprepare(dcrtc->clk); | ||
| 342 | if (dpms_blanked(dpms)) | 336 | if (dpms_blanked(dpms)) |
| 343 | armada_drm_vblank_off(dcrtc); | 337 | armada_drm_vblank_off(dcrtc); |
| 344 | else | 338 | else if (!IS_ERR(dcrtc->clk)) |
| 339 | WARN_ON(clk_prepare_enable(dcrtc->clk)); | ||
| 340 | dcrtc->dpms = dpms; | ||
| 341 | armada_drm_crtc_update(dcrtc); | ||
| 342 | if (!dpms_blanked(dpms)) | ||
| 345 | drm_crtc_vblank_on(&dcrtc->crtc); | 343 | drm_crtc_vblank_on(&dcrtc->crtc); |
| 344 | else if (!IS_ERR(dcrtc->clk)) | ||
| 345 | clk_disable_unprepare(dcrtc->clk); | ||
| 346 | } else if (dcrtc->dpms != dpms) { | ||
| 347 | dcrtc->dpms = dpms; | ||
| 346 | } | 348 | } |
| 347 | } | 349 | } |
| 348 | 350 | ||
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index a5e428d27d2f..806791897304 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c | |||
| @@ -387,7 +387,7 @@ int armada_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
| 387 | if (!access_ok(VERIFY_READ, ptr, args->size)) | 387 | if (!access_ok(VERIFY_READ, ptr, args->size)) |
| 388 | return -EFAULT; | 388 | return -EFAULT; |
| 389 | 389 | ||
| 390 | ret = fault_in_multipages_readable(ptr, args->size); | 390 | ret = fault_in_pages_readable(ptr, args->size); |
| 391 | if (ret) | 391 | if (ret) |
| 392 | return ret; | 392 | return ret; |
| 393 | 393 | ||
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 8ea72d821525..800055c39cdb 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c | |||
| @@ -104,8 +104,8 @@ int drm_debugfs_create_files(const struct drm_info_list *files, int count, | |||
| 104 | ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO, | 104 | ent = debugfs_create_file(files[i].name, S_IFREG | S_IRUGO, |
| 105 | root, tmp, &drm_debugfs_fops); | 105 | root, tmp, &drm_debugfs_fops); |
| 106 | if (!ent) { | 106 | if (!ent) { |
| 107 | DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/%s\n", | 107 | DRM_ERROR("Cannot create /sys/kernel/debug/dri/%pd/%s\n", |
| 108 | root->d_name.name, files[i].name); | 108 | root, files[i].name); |
| 109 | kfree(tmp); | 109 | kfree(tmp); |
| 110 | ret = -1; | 110 | ret = -1; |
| 111 | goto fail; | 111 | goto fail; |
diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c index a7b2a751f6fe..488355bdafb9 100644 --- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c +++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c | |||
| @@ -148,6 +148,14 @@ static bool is_type2_adaptor(uint8_t adaptor_id) | |||
| 148 | DP_DUAL_MODE_REV_TYPE2); | 148 | DP_DUAL_MODE_REV_TYPE2); |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | static bool is_lspcon_adaptor(const char hdmi_id[DP_DUAL_MODE_HDMI_ID_LEN], | ||
| 152 | const uint8_t adaptor_id) | ||
| 153 | { | ||
| 154 | return is_hdmi_adaptor(hdmi_id) && | ||
| 155 | (adaptor_id == (DP_DUAL_MODE_TYPE_TYPE2 | | ||
| 156 | DP_DUAL_MODE_TYPE_HAS_DPCD)); | ||
| 157 | } | ||
| 158 | |||
| 151 | /** | 159 | /** |
| 152 | * drm_dp_dual_mode_detect - Identify the DP dual mode adaptor | 160 | * drm_dp_dual_mode_detect - Identify the DP dual mode adaptor |
| 153 | * @adapter: I2C adapter for the DDC bus | 161 | * @adapter: I2C adapter for the DDC bus |
| @@ -203,6 +211,8 @@ enum drm_dp_dual_mode_type drm_dp_dual_mode_detect(struct i2c_adapter *adapter) | |||
| 203 | ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_ADAPTOR_ID, | 211 | ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_ADAPTOR_ID, |
| 204 | &adaptor_id, sizeof(adaptor_id)); | 212 | &adaptor_id, sizeof(adaptor_id)); |
| 205 | if (ret == 0) { | 213 | if (ret == 0) { |
| 214 | if (is_lspcon_adaptor(hdmi_id, adaptor_id)) | ||
| 215 | return DRM_DP_DUAL_MODE_LSPCON; | ||
| 206 | if (is_type2_adaptor(adaptor_id)) { | 216 | if (is_type2_adaptor(adaptor_id)) { |
| 207 | if (is_hdmi_adaptor(hdmi_id)) | 217 | if (is_hdmi_adaptor(hdmi_id)) |
| 208 | return DRM_DP_DUAL_MODE_TYPE2_HDMI; | 218 | return DRM_DP_DUAL_MODE_TYPE2_HDMI; |
| @@ -364,3 +374,96 @@ const char *drm_dp_get_dual_mode_type_name(enum drm_dp_dual_mode_type type) | |||
| 364 | } | 374 | } |
| 365 | } | 375 | } |
| 366 | EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name); | 376 | EXPORT_SYMBOL(drm_dp_get_dual_mode_type_name); |
| 377 | |||
| 378 | /** | ||
| 379 | * drm_lspcon_get_mode: Get LSPCON's current mode of operation by | ||
| 380 | * reading offset (0x80, 0x41) | ||
| 381 | * @adapter: I2C-over-aux adapter | ||
| 382 | * @mode: current lspcon mode of operation output variable | ||
| 383 | * | ||
| 384 | * Returns: | ||
| 385 | * 0 on success, sets the current_mode value to appropriate mode | ||
| 386 | * -error on failure | ||
| 387 | */ | ||
| 388 | int drm_lspcon_get_mode(struct i2c_adapter *adapter, | ||
| 389 | enum drm_lspcon_mode *mode) | ||
| 390 | { | ||
| 391 | u8 data; | ||
| 392 | int ret = 0; | ||
| 393 | |||
| 394 | if (!mode) { | ||
| 395 | DRM_ERROR("NULL input\n"); | ||
| 396 | return -EINVAL; | ||
| 397 | } | ||
| 398 | |||
| 399 | /* Read Status: i2c over aux */ | ||
| 400 | ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_LSPCON_CURRENT_MODE, | ||
| 401 | &data, sizeof(data)); | ||
| 402 | if (ret < 0) { | ||
| 403 | DRM_ERROR("LSPCON read(0x80, 0x41) failed\n"); | ||
| 404 | return -EFAULT; | ||
| 405 | } | ||
| 406 | |||
| 407 | if (data & DP_DUAL_MODE_LSPCON_MODE_PCON) | ||
| 408 | *mode = DRM_LSPCON_MODE_PCON; | ||
| 409 | else | ||
| 410 | *mode = DRM_LSPCON_MODE_LS; | ||
| 411 | return 0; | ||
| 412 | } | ||
| 413 | EXPORT_SYMBOL(drm_lspcon_get_mode); | ||
| 414 | |||
| 415 | /** | ||
| 416 | * drm_lspcon_set_mode: Change LSPCON's mode of operation by | ||
| 417 | * writing offset (0x80, 0x40) | ||
| 418 | * @adapter: I2C-over-aux adapter | ||
| 419 | * @mode: required mode of operation | ||
| 420 | * | ||
| 421 | * Returns: | ||
| 422 | * 0 on success, -error on failure/timeout | ||
| 423 | */ | ||
| 424 | int drm_lspcon_set_mode(struct i2c_adapter *adapter, | ||
| 425 | enum drm_lspcon_mode mode) | ||
| 426 | { | ||
| 427 | u8 data = 0; | ||
| 428 | int ret; | ||
| 429 | int time_out = 200; | ||
| 430 | enum drm_lspcon_mode current_mode; | ||
| 431 | |||
| 432 | if (mode == DRM_LSPCON_MODE_PCON) | ||
| 433 | data = DP_DUAL_MODE_LSPCON_MODE_PCON; | ||
| 434 | |||
| 435 | /* Change mode */ | ||
| 436 | ret = drm_dp_dual_mode_write(adapter, DP_DUAL_MODE_LSPCON_MODE_CHANGE, | ||
| 437 | &data, sizeof(data)); | ||
| 438 | if (ret < 0) { | ||
| 439 | DRM_ERROR("LSPCON mode change failed\n"); | ||
| 440 | return ret; | ||
| 441 | } | ||
| 442 | |||
| 443 | /* | ||
| 444 | * Confirm mode change by reading the status bit. | ||
| 445 | * Sometimes, it takes a while to change the mode, | ||
| 446 | * so wait and retry until time out or done. | ||
| 447 | */ | ||
| 448 | do { | ||
| 449 | ret = drm_lspcon_get_mode(adapter, ¤t_mode); | ||
| 450 | if (ret) { | ||
| 451 | DRM_ERROR("can't confirm LSPCON mode change\n"); | ||
| 452 | return ret; | ||
| 453 | } else { | ||
| 454 | if (current_mode != mode) { | ||
| 455 | msleep(10); | ||
| 456 | time_out -= 10; | ||
| 457 | } else { | ||
| 458 | DRM_DEBUG_KMS("LSPCON mode changed to %s\n", | ||
| 459 | mode == DRM_LSPCON_MODE_LS ? | ||
| 460 | "LS" : "PCON"); | ||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | } | ||
| 464 | } while (time_out); | ||
| 465 | |||
| 466 | DRM_ERROR("LSPCON mode change timed out\n"); | ||
| 467 | return -ETIMEDOUT; | ||
| 468 | } | ||
| 469 | EXPORT_SYMBOL(drm_lspcon_set_mode); | ||
diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index ac3924a877e0..3e6fe82c6d64 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c | |||
| @@ -975,6 +975,12 @@ static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags) | |||
| 975 | mutex_unlock(&i2c_to_aux(i2c)->hw_mutex); | 975 | mutex_unlock(&i2c_to_aux(i2c)->hw_mutex); |
| 976 | } | 976 | } |
| 977 | 977 | ||
| 978 | static const struct i2c_lock_operations drm_dp_i2c_lock_ops = { | ||
| 979 | .lock_bus = lock_bus, | ||
| 980 | .trylock_bus = trylock_bus, | ||
| 981 | .unlock_bus = unlock_bus, | ||
| 982 | }; | ||
| 983 | |||
| 978 | /** | 984 | /** |
| 979 | * drm_dp_aux_init() - minimally initialise an aux channel | 985 | * drm_dp_aux_init() - minimally initialise an aux channel |
| 980 | * @aux: DisplayPort AUX channel | 986 | * @aux: DisplayPort AUX channel |
| @@ -992,9 +998,7 @@ void drm_dp_aux_init(struct drm_dp_aux *aux) | |||
| 992 | aux->ddc.algo_data = aux; | 998 | aux->ddc.algo_data = aux; |
| 993 | aux->ddc.retries = 3; | 999 | aux->ddc.retries = 3; |
| 994 | 1000 | ||
| 995 | aux->ddc.lock_bus = lock_bus; | 1001 | aux->ddc.lock_ops = &drm_dp_i2c_lock_ops; |
| 996 | aux->ddc.trylock_bus = trylock_bus; | ||
| 997 | aux->ddc.unlock_bus = unlock_bus; | ||
| 998 | } | 1002 | } |
| 999 | EXPORT_SYMBOL(drm_dp_aux_init); | 1003 | EXPORT_SYMBOL(drm_dp_aux_init); |
| 1000 | 1004 | ||
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 1df2d33d0b40..ffb2ab389d1d 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c | |||
| @@ -54,9 +54,6 @@ int drm_name_info(struct seq_file *m, void *data) | |||
| 54 | 54 | ||
| 55 | mutex_lock(&dev->master_mutex); | 55 | mutex_lock(&dev->master_mutex); |
| 56 | master = dev->master; | 56 | master = dev->master; |
| 57 | if (!master) | ||
| 58 | goto out_unlock; | ||
| 59 | |||
| 60 | seq_printf(m, "%s", dev->driver->name); | 57 | seq_printf(m, "%s", dev->driver->name); |
| 61 | if (dev->dev) | 58 | if (dev->dev) |
| 62 | seq_printf(m, " dev=%s", dev_name(dev->dev)); | 59 | seq_printf(m, " dev=%s", dev_name(dev->dev)); |
| @@ -65,7 +62,6 @@ int drm_name_info(struct seq_file *m, void *data) | |||
| 65 | if (dev->unique) | 62 | if (dev->unique) |
| 66 | seq_printf(m, " unique=%s", dev->unique); | 63 | seq_printf(m, " unique=%s", dev->unique); |
| 67 | seq_printf(m, "\n"); | 64 | seq_printf(m, "\n"); |
| 68 | out_unlock: | ||
| 69 | mutex_unlock(&dev->master_mutex); | 65 | mutex_unlock(&dev->master_mutex); |
| 70 | 66 | ||
| 71 | return 0; | 67 | return 0; |
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c index cb86c7e5495c..d9230132dfbc 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c | |||
| @@ -329,20 +329,34 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, | |||
| 329 | /* | 329 | /* |
| 330 | * Append a LINK to the submitted command buffer to return to | 330 | * Append a LINK to the submitted command buffer to return to |
| 331 | * the ring buffer. return_target is the ring target address. | 331 | * the ring buffer. return_target is the ring target address. |
| 332 | * We need three dwords: event, wait, link. | 332 | * We need at most 7 dwords in the return target: 2 cache flush + |
| 333 | * 2 semaphore stall + 1 event + 1 wait + 1 link. | ||
| 333 | */ | 334 | */ |
| 334 | return_dwords = 3; | 335 | return_dwords = 7; |
| 335 | return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords); | 336 | return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords); |
| 336 | CMD_LINK(cmdbuf, return_dwords, return_target); | 337 | CMD_LINK(cmdbuf, return_dwords, return_target); |
| 337 | 338 | ||
| 338 | /* | 339 | /* |
| 339 | * Append event, wait and link pointing back to the wait | 340 | * Append a cache flush, stall, event, wait and link pointing back to |
| 340 | * command to the ring buffer. | 341 | * the wait command to the ring buffer. |
| 341 | */ | 342 | */ |
| 343 | if (gpu->exec_state == ETNA_PIPE_2D) { | ||
| 344 | CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, | ||
| 345 | VIVS_GL_FLUSH_CACHE_PE2D); | ||
| 346 | } else { | ||
| 347 | CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, | ||
| 348 | VIVS_GL_FLUSH_CACHE_DEPTH | | ||
| 349 | VIVS_GL_FLUSH_CACHE_COLOR); | ||
| 350 | CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE, | ||
| 351 | VIVS_TS_FLUSH_CACHE_FLUSH); | ||
| 352 | } | ||
| 353 | CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); | ||
| 354 | CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); | ||
| 342 | CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | | 355 | CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | |
| 343 | VIVS_GL_EVENT_FROM_PE); | 356 | VIVS_GL_EVENT_FROM_PE); |
| 344 | CMD_WAIT(buffer); | 357 | CMD_WAIT(buffer); |
| 345 | CMD_LINK(buffer, 2, return_target + 8); | 358 | CMD_LINK(buffer, 2, etnaviv_iommu_get_cmdbuf_va(gpu, buffer) + |
| 359 | buffer->user_size - 4); | ||
| 346 | 360 | ||
| 347 | if (drm_debug & DRM_UT_DRIVER) | 361 | if (drm_debug & DRM_UT_DRIVER) |
| 348 | pr_info("stream link to 0x%08x @ 0x%08x %p\n", | 362 | pr_info("stream link to 0x%08x @ 0x%08x %p\n", |
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 9ffca2478e02..3755ef935af4 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c | |||
| @@ -744,19 +744,22 @@ static struct page **etnaviv_gem_userptr_do_get_pages( | |||
| 744 | int ret = 0, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT; | 744 | int ret = 0, pinned, npages = etnaviv_obj->base.size >> PAGE_SHIFT; |
| 745 | struct page **pvec; | 745 | struct page **pvec; |
| 746 | uintptr_t ptr; | 746 | uintptr_t ptr; |
| 747 | unsigned int flags = 0; | ||
| 747 | 748 | ||
| 748 | pvec = drm_malloc_ab(npages, sizeof(struct page *)); | 749 | pvec = drm_malloc_ab(npages, sizeof(struct page *)); |
| 749 | if (!pvec) | 750 | if (!pvec) |
| 750 | return ERR_PTR(-ENOMEM); | 751 | return ERR_PTR(-ENOMEM); |
| 751 | 752 | ||
| 753 | if (!etnaviv_obj->userptr.ro) | ||
| 754 | flags |= FOLL_WRITE; | ||
| 755 | |||
| 752 | pinned = 0; | 756 | pinned = 0; |
| 753 | ptr = etnaviv_obj->userptr.ptr; | 757 | ptr = etnaviv_obj->userptr.ptr; |
| 754 | 758 | ||
| 755 | down_read(&mm->mmap_sem); | 759 | down_read(&mm->mmap_sem); |
| 756 | while (pinned < npages) { | 760 | while (pinned < npages) { |
| 757 | ret = get_user_pages_remote(task, mm, ptr, npages - pinned, | 761 | ret = get_user_pages_remote(task, mm, ptr, npages - pinned, |
| 758 | !etnaviv_obj->userptr.ro, 0, | 762 | flags, pvec + pinned, NULL); |
| 759 | pvec + pinned, NULL); | ||
| 760 | if (ret < 0) | 763 | if (ret < 0) |
| 761 | break; | 764 | break; |
| 762 | 765 | ||
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c index d3796ed8d8c5..169ac96e8f08 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c | |||
| @@ -330,7 +330,8 @@ u32 etnaviv_iommu_get_cmdbuf_va(struct etnaviv_gpu *gpu, | |||
| 330 | return (u32)buf->vram_node.start; | 330 | return (u32)buf->vram_node.start; |
| 331 | 331 | ||
| 332 | mutex_lock(&mmu->lock); | 332 | mutex_lock(&mmu->lock); |
| 333 | ret = etnaviv_iommu_find_iova(mmu, &buf->vram_node, buf->size); | 333 | ret = etnaviv_iommu_find_iova(mmu, &buf->vram_node, |
| 334 | buf->size + SZ_64K); | ||
| 334 | if (ret < 0) { | 335 | if (ret < 0) { |
| 335 | mutex_unlock(&mmu->lock); | 336 | mutex_unlock(&mmu->lock); |
| 336 | return 0; | 337 | return 0; |
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 83f61c513b7e..465d344f3391 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig | |||
| @@ -38,7 +38,6 @@ config DRM_EXYNOS7_DECON | |||
| 38 | 38 | ||
| 39 | config DRM_EXYNOS_MIXER | 39 | config DRM_EXYNOS_MIXER |
| 40 | bool "Mixer" | 40 | bool "Mixer" |
| 41 | depends on !VIDEO_SAMSUNG_S5P_TV | ||
| 42 | help | 41 | help |
| 43 | Choose this option if you want to use Exynos Mixer for DRM. | 42 | Choose this option if you want to use Exynos Mixer for DRM. |
| 44 | 43 | ||
| @@ -77,7 +76,7 @@ config DRM_EXYNOS_DP | |||
| 77 | 76 | ||
| 78 | config DRM_EXYNOS_HDMI | 77 | config DRM_EXYNOS_HDMI |
| 79 | bool "HDMI" | 78 | bool "HDMI" |
| 80 | depends on !VIDEO_SAMSUNG_S5P_TV && (DRM_EXYNOS_MIXER || DRM_EXYNOS5433_DECON) | 79 | depends on DRM_EXYNOS_MIXER || DRM_EXYNOS5433_DECON |
| 81 | help | 80 | help |
| 82 | Choose this option if you want to use Exynos HDMI for DRM. | 81 | Choose this option if you want to use Exynos HDMI for DRM. |
| 83 | 82 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index aa92decf4233..fbd13fabdf2d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c | |||
| @@ -488,7 +488,8 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, | |||
| 488 | goto err_free; | 488 | goto err_free; |
| 489 | } | 489 | } |
| 490 | 490 | ||
| 491 | ret = get_vaddr_frames(start, npages, true, true, g2d_userptr->vec); | 491 | ret = get_vaddr_frames(start, npages, FOLL_FORCE | FOLL_WRITE, |
| 492 | g2d_userptr->vec); | ||
| 492 | if (ret != npages) { | 493 | if (ret != npages) { |
| 493 | DRM_ERROR("failed to get user pages from userptr.\n"); | 494 | DRM_ERROR("failed to get user pages from userptr.\n"); |
| 494 | if (ret < 0) | 495 | if (ret < 0) |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_iommu.h b/drivers/gpu/drm/exynos/exynos_drm_iommu.h index c8de4913fdbe..87f6b5672e11 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_iommu.h +++ b/drivers/gpu/drm/exynos/exynos_drm_iommu.h | |||
| @@ -66,7 +66,7 @@ static inline int __exynos_iommu_create_mapping(struct exynos_drm_private *priv, | |||
| 66 | if (ret) | 66 | if (ret) |
| 67 | goto free_domain; | 67 | goto free_domain; |
| 68 | 68 | ||
| 69 | ret = iommu_dma_init_domain(domain, start, size); | 69 | ret = iommu_dma_init_domain(domain, start, size, NULL); |
| 70 | if (ret) | 70 | if (ret) |
| 71 | goto put_cookie; | 71 | goto put_cookie; |
| 72 | 72 | ||
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c index 3371635cd4d7..b2d5e188b1b8 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c | |||
| @@ -51,6 +51,7 @@ static void fsl_dcu_drm_disable_crtc(struct drm_crtc *crtc) | |||
| 51 | DCU_MODE_DCU_MODE(DCU_MODE_OFF)); | 51 | DCU_MODE_DCU_MODE(DCU_MODE_OFF)); |
| 52 | regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, | 52 | regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, |
| 53 | DCU_UPDATE_MODE_READREG); | 53 | DCU_UPDATE_MODE_READREG); |
| 54 | clk_disable_unprepare(fsl_dev->pix_clk); | ||
| 54 | } | 55 | } |
| 55 | 56 | ||
| 56 | static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc) | 57 | static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc) |
| @@ -58,6 +59,7 @@ static void fsl_dcu_drm_crtc_enable(struct drm_crtc *crtc) | |||
| 58 | struct drm_device *dev = crtc->dev; | 59 | struct drm_device *dev = crtc->dev; |
| 59 | struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; | 60 | struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; |
| 60 | 61 | ||
| 62 | clk_prepare_enable(fsl_dev->pix_clk); | ||
| 61 | regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE, | 63 | regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE, |
| 62 | DCU_MODE_DCU_MODE_MASK, | 64 | DCU_MODE_DCU_MODE_MASK, |
| 63 | DCU_MODE_DCU_MODE(DCU_MODE_NORMAL)); | 65 | DCU_MODE_DCU_MODE(DCU_MODE_NORMAL)); |
| @@ -116,8 +118,6 @@ static void fsl_dcu_drm_crtc_mode_set_nofb(struct drm_crtc *crtc) | |||
| 116 | DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) | | 118 | DCU_THRESHOLD_LS_BF_VS(BF_VS_VAL) | |
| 117 | DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) | | 119 | DCU_THRESHOLD_OUT_BUF_HIGH(BUF_MAX_VAL) | |
| 118 | DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL)); | 120 | DCU_THRESHOLD_OUT_BUF_LOW(BUF_MIN_VAL)); |
| 119 | regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, | ||
| 120 | DCU_UPDATE_MODE_READREG); | ||
| 121 | return; | 121 | return; |
| 122 | } | 122 | } |
| 123 | 123 | ||
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index 0884c45aefe8..e04efbed1a54 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c | |||
| @@ -267,12 +267,8 @@ static int fsl_dcu_drm_pm_resume(struct device *dev) | |||
| 267 | return ret; | 267 | return ret; |
| 268 | } | 268 | } |
| 269 | 269 | ||
| 270 | ret = clk_prepare_enable(fsl_dev->pix_clk); | 270 | if (fsl_dev->tcon) |
| 271 | if (ret < 0) { | 271 | fsl_tcon_bypass_enable(fsl_dev->tcon); |
| 272 | dev_err(dev, "failed to enable pix clk\n"); | ||
| 273 | goto disable_dcu_clk; | ||
| 274 | } | ||
| 275 | |||
| 276 | fsl_dcu_drm_init_planes(fsl_dev->drm); | 272 | fsl_dcu_drm_init_planes(fsl_dev->drm); |
| 277 | drm_atomic_helper_resume(fsl_dev->drm, fsl_dev->state); | 273 | drm_atomic_helper_resume(fsl_dev->drm, fsl_dev->state); |
| 278 | 274 | ||
| @@ -284,10 +280,6 @@ static int fsl_dcu_drm_pm_resume(struct device *dev) | |||
| 284 | enable_irq(fsl_dev->irq); | 280 | enable_irq(fsl_dev->irq); |
| 285 | 281 | ||
| 286 | return 0; | 282 | return 0; |
| 287 | |||
| 288 | disable_dcu_clk: | ||
| 289 | clk_disable_unprepare(fsl_dev->clk); | ||
| 290 | return ret; | ||
| 291 | } | 283 | } |
| 292 | #endif | 284 | #endif |
| 293 | 285 | ||
| @@ -401,18 +393,12 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev) | |||
| 401 | goto disable_clk; | 393 | goto disable_clk; |
| 402 | } | 394 | } |
| 403 | 395 | ||
| 404 | ret = clk_prepare_enable(fsl_dev->pix_clk); | ||
| 405 | if (ret < 0) { | ||
| 406 | dev_err(dev, "failed to enable pix clk\n"); | ||
| 407 | goto unregister_pix_clk; | ||
| 408 | } | ||
| 409 | |||
| 410 | fsl_dev->tcon = fsl_tcon_init(dev); | 396 | fsl_dev->tcon = fsl_tcon_init(dev); |
| 411 | 397 | ||
| 412 | drm = drm_dev_alloc(driver, dev); | 398 | drm = drm_dev_alloc(driver, dev); |
| 413 | if (IS_ERR(drm)) { | 399 | if (IS_ERR(drm)) { |
| 414 | ret = PTR_ERR(drm); | 400 | ret = PTR_ERR(drm); |
| 415 | goto disable_pix_clk; | 401 | goto unregister_pix_clk; |
| 416 | } | 402 | } |
| 417 | 403 | ||
| 418 | fsl_dev->dev = dev; | 404 | fsl_dev->dev = dev; |
| @@ -433,8 +419,6 @@ static int fsl_dcu_drm_probe(struct platform_device *pdev) | |||
| 433 | 419 | ||
| 434 | unref: | 420 | unref: |
| 435 | drm_dev_unref(drm); | 421 | drm_dev_unref(drm); |
| 436 | disable_pix_clk: | ||
| 437 | clk_disable_unprepare(fsl_dev->pix_clk); | ||
| 438 | unregister_pix_clk: | 422 | unregister_pix_clk: |
| 439 | clk_unregister(fsl_dev->pix_clk); | 423 | clk_unregister(fsl_dev->pix_clk); |
| 440 | disable_clk: | 424 | disable_clk: |
| @@ -447,7 +431,6 @@ static int fsl_dcu_drm_remove(struct platform_device *pdev) | |||
| 447 | struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev); | 431 | struct fsl_dcu_drm_device *fsl_dev = platform_get_drvdata(pdev); |
| 448 | 432 | ||
| 449 | clk_disable_unprepare(fsl_dev->clk); | 433 | clk_disable_unprepare(fsl_dev->clk); |
| 450 | clk_disable_unprepare(fsl_dev->pix_clk); | ||
| 451 | clk_unregister(fsl_dev->pix_clk); | 434 | clk_unregister(fsl_dev->pix_clk); |
| 452 | drm_put_dev(fsl_dev->drm); | 435 | drm_put_dev(fsl_dev->drm); |
| 453 | 436 | ||
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index a7e5486bd1e9..9e6f7d8112b3 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c | |||
| @@ -211,11 +211,6 @@ void fsl_dcu_drm_init_planes(struct drm_device *dev) | |||
| 211 | for (j = 1; j <= fsl_dev->soc->layer_regs; j++) | 211 | for (j = 1; j <= fsl_dev->soc->layer_regs; j++) |
| 212 | regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0); | 212 | regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(i, j), 0); |
| 213 | } | 213 | } |
| 214 | regmap_update_bits(fsl_dev->regmap, DCU_DCU_MODE, | ||
| 215 | DCU_MODE_DCU_MODE_MASK, | ||
| 216 | DCU_MODE_DCU_MODE(DCU_MODE_OFF)); | ||
| 217 | regmap_write(fsl_dev->regmap, DCU_UPDATE_MODE, | ||
| 218 | DCU_UPDATE_MODE_READREG); | ||
| 219 | } | 214 | } |
| 220 | 215 | ||
| 221 | struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev) | 216 | struct drm_plane *fsl_dcu_drm_primary_create_plane(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c index 26edcc899712..e1dd75b18118 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | |||
| @@ -20,38 +20,6 @@ | |||
| 20 | #include "fsl_dcu_drm_drv.h" | 20 | #include "fsl_dcu_drm_drv.h" |
| 21 | #include "fsl_tcon.h" | 21 | #include "fsl_tcon.h" |
| 22 | 22 | ||
| 23 | static int | ||
| 24 | fsl_dcu_drm_encoder_atomic_check(struct drm_encoder *encoder, | ||
| 25 | struct drm_crtc_state *crtc_state, | ||
| 26 | struct drm_connector_state *conn_state) | ||
| 27 | { | ||
| 28 | return 0; | ||
| 29 | } | ||
| 30 | |||
| 31 | static void fsl_dcu_drm_encoder_disable(struct drm_encoder *encoder) | ||
| 32 | { | ||
| 33 | struct drm_device *dev = encoder->dev; | ||
| 34 | struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; | ||
| 35 | |||
| 36 | if (fsl_dev->tcon) | ||
| 37 | fsl_tcon_bypass_disable(fsl_dev->tcon); | ||
| 38 | } | ||
| 39 | |||
| 40 | static void fsl_dcu_drm_encoder_enable(struct drm_encoder *encoder) | ||
| 41 | { | ||
| 42 | struct drm_device *dev = encoder->dev; | ||
| 43 | struct fsl_dcu_drm_device *fsl_dev = dev->dev_private; | ||
| 44 | |||
| 45 | if (fsl_dev->tcon) | ||
| 46 | fsl_tcon_bypass_enable(fsl_dev->tcon); | ||
| 47 | } | ||
| 48 | |||
| 49 | static const struct drm_encoder_helper_funcs encoder_helper_funcs = { | ||
| 50 | .atomic_check = fsl_dcu_drm_encoder_atomic_check, | ||
| 51 | .disable = fsl_dcu_drm_encoder_disable, | ||
| 52 | .enable = fsl_dcu_drm_encoder_enable, | ||
| 53 | }; | ||
| 54 | |||
| 55 | static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder) | 23 | static void fsl_dcu_drm_encoder_destroy(struct drm_encoder *encoder) |
| 56 | { | 24 | { |
| 57 | drm_encoder_cleanup(encoder); | 25 | drm_encoder_cleanup(encoder); |
| @@ -68,13 +36,16 @@ int fsl_dcu_drm_encoder_create(struct fsl_dcu_drm_device *fsl_dev, | |||
| 68 | int ret; | 36 | int ret; |
| 69 | 37 | ||
| 70 | encoder->possible_crtcs = 1; | 38 | encoder->possible_crtcs = 1; |
| 39 | |||
| 40 | /* Use bypass mode for parallel RGB/LVDS encoder */ | ||
| 41 | if (fsl_dev->tcon) | ||
| 42 | fsl_tcon_bypass_enable(fsl_dev->tcon); | ||
| 43 | |||
| 71 | ret = drm_encoder_init(fsl_dev->drm, encoder, &encoder_funcs, | 44 | ret = drm_encoder_init(fsl_dev->drm, encoder, &encoder_funcs, |
| 72 | DRM_MODE_ENCODER_LVDS, NULL); | 45 | DRM_MODE_ENCODER_LVDS, NULL); |
| 73 | if (ret < 0) | 46 | if (ret < 0) |
| 74 | return ret; | 47 | return ret; |
| 75 | 48 | ||
| 76 | drm_encoder_helper_add(encoder, &encoder_helper_funcs); | ||
| 77 | |||
| 78 | return 0; | 49 | return 0; |
| 79 | } | 50 | } |
| 80 | 51 | ||
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 7769e469118f..1c1b19ccb92f 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig | |||
| @@ -46,6 +46,31 @@ config DRM_I915_PRELIMINARY_HW_SUPPORT | |||
| 46 | 46 | ||
| 47 | If in doubt, say "N". | 47 | If in doubt, say "N". |
| 48 | 48 | ||
| 49 | config DRM_I915_CAPTURE_ERROR | ||
| 50 | bool "Enable capturing GPU state following a hang" | ||
| 51 | depends on DRM_I915 | ||
| 52 | default y | ||
| 53 | help | ||
| 54 | This option enables capturing the GPU state when a hang is detected. | ||
| 55 | This information is vital for triaging hangs and assists in debugging. | ||
| 56 | Please report any hang to | ||
| 57 | https://bugs.freedesktop.org/enter_bug.cgi?product=DRI | ||
| 58 | for triaging. | ||
| 59 | |||
| 60 | If in doubt, say "Y". | ||
| 61 | |||
| 62 | config DRM_I915_COMPRESS_ERROR | ||
| 63 | bool "Compress GPU error state" | ||
| 64 | depends on DRM_I915_CAPTURE_ERROR | ||
| 65 | select ZLIB_DEFLATE | ||
| 66 | default y | ||
| 67 | help | ||
| 68 | This option selects ZLIB_DEFLATE if it isn't already | ||
| 69 | selected and causes any error state captured upon a GPU hang | ||
| 70 | to be compressed using zlib. | ||
| 71 | |||
| 72 | If in doubt, say "Y". | ||
| 73 | |||
| 49 | config DRM_I915_USERPTR | 74 | config DRM_I915_USERPTR |
| 50 | bool "Always enable userptr support" | 75 | bool "Always enable userptr support" |
| 51 | depends on DRM_I915 | 76 | depends on DRM_I915 |
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index a998c2bce70a..612340097f4b 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile | |||
| @@ -42,7 +42,6 @@ i915-y += i915_cmd_parser.o \ | |||
| 42 | i915_gem_stolen.o \ | 42 | i915_gem_stolen.o \ |
| 43 | i915_gem_tiling.o \ | 43 | i915_gem_tiling.o \ |
| 44 | i915_gem_userptr.o \ | 44 | i915_gem_userptr.o \ |
| 45 | i915_gpu_error.o \ | ||
| 46 | i915_trace_points.o \ | 45 | i915_trace_points.o \ |
| 47 | intel_breadcrumbs.o \ | 46 | intel_breadcrumbs.o \ |
| 48 | intel_engine_cs.o \ | 47 | intel_engine_cs.o \ |
| @@ -102,11 +101,15 @@ i915-y += dvo_ch7017.o \ | |||
| 102 | intel_dvo.o \ | 101 | intel_dvo.o \ |
| 103 | intel_hdmi.o \ | 102 | intel_hdmi.o \ |
| 104 | intel_i2c.o \ | 103 | intel_i2c.o \ |
| 104 | intel_lspcon.o \ | ||
| 105 | intel_lvds.o \ | 105 | intel_lvds.o \ |
| 106 | intel_panel.o \ | 106 | intel_panel.o \ |
| 107 | intel_sdvo.o \ | 107 | intel_sdvo.o \ |
| 108 | intel_tv.o | 108 | intel_tv.o |
| 109 | 109 | ||
| 110 | # Post-mortem debug and GPU hang state capture | ||
| 111 | i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o | ||
| 112 | |||
| 110 | # virtual gpu code | 113 | # virtual gpu code |
| 111 | i915-y += i915_vgpu.o | 114 | i915-y += i915_vgpu.o |
| 112 | 115 | ||
diff --git a/drivers/gpu/drm/i915/gvt/Makefile b/drivers/gpu/drm/i915/gvt/Makefile index d0f21a6ad60d..34ea4776af70 100644 --- a/drivers/gpu/drm/i915/gvt/Makefile +++ b/drivers/gpu/drm/i915/gvt/Makefile | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | GVT_DIR := gvt | 1 | GVT_DIR := gvt |
| 2 | GVT_SOURCE := gvt.o | 2 | GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \ |
| 3 | interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \ | ||
| 4 | execlist.o scheduler.o sched_policy.o render.o cmd_parser.o | ||
| 3 | 5 | ||
| 4 | ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall | 6 | ccflags-y += -I$(src) -I$(src)/$(GVT_DIR) -Wall |
| 5 | i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) | 7 | i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE)) |
diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c new file mode 100644 index 000000000000..0d41ebc4aea6 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c | |||
| @@ -0,0 +1,352 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Kevin Tian <kevin.tian@intel.com> | ||
| 25 | * Dexuan Cui | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Pei Zhang <pei.zhang@intel.com> | ||
| 29 | * Min He <min.he@intel.com> | ||
| 30 | * Niu Bing <bing.niu@intel.com> | ||
| 31 | * Yulei Zhang <yulei.zhang@intel.com> | ||
| 32 | * Zhenyu Wang <zhenyuw@linux.intel.com> | ||
| 33 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 34 | * | ||
| 35 | */ | ||
| 36 | |||
| 37 | #include "i915_drv.h" | ||
| 38 | #include "gvt.h" | ||
| 39 | |||
| 40 | #define MB_TO_BYTES(mb) ((mb) << 20ULL) | ||
| 41 | #define BYTES_TO_MB(b) ((b) >> 20ULL) | ||
| 42 | |||
| 43 | #define HOST_LOW_GM_SIZE MB_TO_BYTES(128) | ||
| 44 | #define HOST_HIGH_GM_SIZE MB_TO_BYTES(384) | ||
| 45 | #define HOST_FENCE 4 | ||
| 46 | |||
| 47 | static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm) | ||
| 48 | { | ||
| 49 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 50 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
| 51 | u32 alloc_flag, search_flag; | ||
| 52 | u64 start, end, size; | ||
| 53 | struct drm_mm_node *node; | ||
| 54 | int retried = 0; | ||
| 55 | int ret; | ||
| 56 | |||
| 57 | if (high_gm) { | ||
| 58 | search_flag = DRM_MM_SEARCH_BELOW; | ||
| 59 | alloc_flag = DRM_MM_CREATE_TOP; | ||
| 60 | node = &vgpu->gm.high_gm_node; | ||
| 61 | size = vgpu_hidden_sz(vgpu); | ||
| 62 | start = gvt_hidden_gmadr_base(gvt); | ||
| 63 | end = gvt_hidden_gmadr_end(gvt); | ||
| 64 | } else { | ||
| 65 | search_flag = DRM_MM_SEARCH_DEFAULT; | ||
| 66 | alloc_flag = DRM_MM_CREATE_DEFAULT; | ||
| 67 | node = &vgpu->gm.low_gm_node; | ||
| 68 | size = vgpu_aperture_sz(vgpu); | ||
| 69 | start = gvt_aperture_gmadr_base(gvt); | ||
| 70 | end = gvt_aperture_gmadr_end(gvt); | ||
| 71 | } | ||
| 72 | |||
| 73 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
| 74 | search_again: | ||
| 75 | ret = drm_mm_insert_node_in_range_generic(&dev_priv->ggtt.base.mm, | ||
| 76 | node, size, 4096, 0, | ||
| 77 | start, end, search_flag, | ||
| 78 | alloc_flag); | ||
| 79 | if (ret) { | ||
| 80 | ret = i915_gem_evict_something(&dev_priv->ggtt.base, | ||
| 81 | size, 4096, 0, start, end, 0); | ||
| 82 | if (ret == 0 && ++retried < 3) | ||
| 83 | goto search_again; | ||
| 84 | |||
| 85 | gvt_err("fail to alloc %s gm space from host, retried %d\n", | ||
| 86 | high_gm ? "high" : "low", retried); | ||
| 87 | } | ||
| 88 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
| 89 | return ret; | ||
| 90 | } | ||
| 91 | |||
| 92 | static int alloc_vgpu_gm(struct intel_vgpu *vgpu) | ||
| 93 | { | ||
| 94 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 95 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
| 96 | int ret; | ||
| 97 | |||
| 98 | ret = alloc_gm(vgpu, false); | ||
| 99 | if (ret) | ||
| 100 | return ret; | ||
| 101 | |||
| 102 | ret = alloc_gm(vgpu, true); | ||
| 103 | if (ret) | ||
| 104 | goto out_free_aperture; | ||
| 105 | |||
| 106 | gvt_dbg_core("vgpu%d: alloc low GM start %llx size %llx\n", vgpu->id, | ||
| 107 | vgpu_aperture_offset(vgpu), vgpu_aperture_sz(vgpu)); | ||
| 108 | |||
| 109 | gvt_dbg_core("vgpu%d: alloc high GM start %llx size %llx\n", vgpu->id, | ||
| 110 | vgpu_hidden_offset(vgpu), vgpu_hidden_sz(vgpu)); | ||
| 111 | |||
| 112 | return 0; | ||
| 113 | out_free_aperture: | ||
| 114 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
| 115 | drm_mm_remove_node(&vgpu->gm.low_gm_node); | ||
| 116 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
| 117 | return ret; | ||
| 118 | } | ||
| 119 | |||
| 120 | static void free_vgpu_gm(struct intel_vgpu *vgpu) | ||
| 121 | { | ||
| 122 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 123 | |||
| 124 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
| 125 | drm_mm_remove_node(&vgpu->gm.low_gm_node); | ||
| 126 | drm_mm_remove_node(&vgpu->gm.high_gm_node); | ||
| 127 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
| 128 | } | ||
| 129 | |||
| 130 | /** | ||
| 131 | * intel_vgpu_write_fence - write fence registers owned by a vGPU | ||
| 132 | * @vgpu: vGPU instance | ||
| 133 | * @fence: vGPU fence register number | ||
| 134 | * @value: Fence register value to be written | ||
| 135 | * | ||
| 136 | * This function is used to write fence registers owned by a vGPU. The vGPU | ||
| 137 | * fence register number will be translated into HW fence register number. | ||
| 138 | * | ||
| 139 | */ | ||
| 140 | void intel_vgpu_write_fence(struct intel_vgpu *vgpu, | ||
| 141 | u32 fence, u64 value) | ||
| 142 | { | ||
| 143 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 144 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
| 145 | struct drm_i915_fence_reg *reg; | ||
| 146 | i915_reg_t fence_reg_lo, fence_reg_hi; | ||
| 147 | |||
| 148 | assert_rpm_wakelock_held(dev_priv); | ||
| 149 | |||
| 150 | if (WARN_ON(fence > vgpu_fence_sz(vgpu))) | ||
| 151 | return; | ||
| 152 | |||
| 153 | reg = vgpu->fence.regs[fence]; | ||
| 154 | if (WARN_ON(!reg)) | ||
| 155 | return; | ||
| 156 | |||
| 157 | fence_reg_lo = FENCE_REG_GEN6_LO(reg->id); | ||
| 158 | fence_reg_hi = FENCE_REG_GEN6_HI(reg->id); | ||
| 159 | |||
| 160 | I915_WRITE(fence_reg_lo, 0); | ||
| 161 | POSTING_READ(fence_reg_lo); | ||
| 162 | |||
| 163 | I915_WRITE(fence_reg_hi, upper_32_bits(value)); | ||
| 164 | I915_WRITE(fence_reg_lo, lower_32_bits(value)); | ||
| 165 | POSTING_READ(fence_reg_lo); | ||
| 166 | } | ||
| 167 | |||
| 168 | static void free_vgpu_fence(struct intel_vgpu *vgpu) | ||
| 169 | { | ||
| 170 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 171 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
| 172 | struct drm_i915_fence_reg *reg; | ||
| 173 | u32 i; | ||
| 174 | |||
| 175 | if (WARN_ON(!vgpu_fence_sz(vgpu))) | ||
| 176 | return; | ||
| 177 | |||
| 178 | intel_runtime_pm_get(dev_priv); | ||
| 179 | |||
| 180 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
| 181 | for (i = 0; i < vgpu_fence_sz(vgpu); i++) { | ||
| 182 | reg = vgpu->fence.regs[i]; | ||
| 183 | intel_vgpu_write_fence(vgpu, i, 0); | ||
| 184 | list_add_tail(®->link, | ||
| 185 | &dev_priv->mm.fence_list); | ||
| 186 | } | ||
| 187 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
| 188 | |||
| 189 | intel_runtime_pm_put(dev_priv); | ||
| 190 | } | ||
| 191 | |||
| 192 | static int alloc_vgpu_fence(struct intel_vgpu *vgpu) | ||
| 193 | { | ||
| 194 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 195 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
| 196 | struct drm_i915_fence_reg *reg; | ||
| 197 | int i; | ||
| 198 | struct list_head *pos, *q; | ||
| 199 | |||
| 200 | intel_runtime_pm_get(dev_priv); | ||
| 201 | |||
| 202 | /* Request fences from host */ | ||
| 203 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
| 204 | i = 0; | ||
| 205 | list_for_each_safe(pos, q, &dev_priv->mm.fence_list) { | ||
| 206 | reg = list_entry(pos, struct drm_i915_fence_reg, link); | ||
| 207 | if (reg->pin_count || reg->vma) | ||
| 208 | continue; | ||
| 209 | list_del(pos); | ||
| 210 | vgpu->fence.regs[i] = reg; | ||
| 211 | intel_vgpu_write_fence(vgpu, i, 0); | ||
| 212 | if (++i == vgpu_fence_sz(vgpu)) | ||
| 213 | break; | ||
| 214 | } | ||
| 215 | if (i != vgpu_fence_sz(vgpu)) | ||
| 216 | goto out_free_fence; | ||
| 217 | |||
| 218 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
| 219 | intel_runtime_pm_put(dev_priv); | ||
| 220 | return 0; | ||
| 221 | out_free_fence: | ||
| 222 | /* Return fences to host, if fail */ | ||
| 223 | for (i = 0; i < vgpu_fence_sz(vgpu); i++) { | ||
| 224 | reg = vgpu->fence.regs[i]; | ||
| 225 | if (!reg) | ||
| 226 | continue; | ||
| 227 | list_add_tail(®->link, | ||
| 228 | &dev_priv->mm.fence_list); | ||
| 229 | } | ||
| 230 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
| 231 | intel_runtime_pm_put(dev_priv); | ||
| 232 | return -ENOSPC; | ||
| 233 | } | ||
| 234 | |||
| 235 | static void free_resource(struct intel_vgpu *vgpu) | ||
| 236 | { | ||
| 237 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 238 | |||
| 239 | gvt->gm.vgpu_allocated_low_gm_size -= vgpu_aperture_sz(vgpu); | ||
| 240 | gvt->gm.vgpu_allocated_high_gm_size -= vgpu_hidden_sz(vgpu); | ||
| 241 | gvt->fence.vgpu_allocated_fence_num -= vgpu_fence_sz(vgpu); | ||
| 242 | } | ||
| 243 | |||
| 244 | static int alloc_resource(struct intel_vgpu *vgpu, | ||
| 245 | struct intel_vgpu_creation_params *param) | ||
| 246 | { | ||
| 247 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 248 | unsigned long request, avail, max, taken; | ||
| 249 | const char *item; | ||
| 250 | |||
| 251 | if (!param->low_gm_sz || !param->high_gm_sz || !param->fence_sz) { | ||
| 252 | gvt_err("Invalid vGPU creation params\n"); | ||
| 253 | return -EINVAL; | ||
| 254 | } | ||
| 255 | |||
| 256 | item = "low GM space"; | ||
| 257 | max = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE; | ||
| 258 | taken = gvt->gm.vgpu_allocated_low_gm_size; | ||
| 259 | avail = max - taken; | ||
| 260 | request = MB_TO_BYTES(param->low_gm_sz); | ||
| 261 | |||
| 262 | if (request > avail) | ||
| 263 | goto no_enough_resource; | ||
| 264 | |||
| 265 | vgpu_aperture_sz(vgpu) = request; | ||
| 266 | |||
| 267 | item = "high GM space"; | ||
| 268 | max = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE; | ||
| 269 | taken = gvt->gm.vgpu_allocated_high_gm_size; | ||
| 270 | avail = max - taken; | ||
| 271 | request = MB_TO_BYTES(param->high_gm_sz); | ||
| 272 | |||
| 273 | if (request > avail) | ||
| 274 | goto no_enough_resource; | ||
| 275 | |||
| 276 | vgpu_hidden_sz(vgpu) = request; | ||
| 277 | |||
| 278 | item = "fence"; | ||
| 279 | max = gvt_fence_sz(gvt) - HOST_FENCE; | ||
| 280 | taken = gvt->fence.vgpu_allocated_fence_num; | ||
| 281 | avail = max - taken; | ||
| 282 | request = param->fence_sz; | ||
| 283 | |||
| 284 | if (request > avail) | ||
| 285 | goto no_enough_resource; | ||
| 286 | |||
| 287 | vgpu_fence_sz(vgpu) = request; | ||
| 288 | |||
| 289 | gvt->gm.vgpu_allocated_low_gm_size += MB_TO_BYTES(param->low_gm_sz); | ||
| 290 | gvt->gm.vgpu_allocated_high_gm_size += MB_TO_BYTES(param->high_gm_sz); | ||
| 291 | gvt->fence.vgpu_allocated_fence_num += param->fence_sz; | ||
| 292 | return 0; | ||
| 293 | |||
| 294 | no_enough_resource: | ||
| 295 | gvt_err("vgpu%d: fail to allocate resource %s\n", vgpu->id, item); | ||
| 296 | gvt_err("vgpu%d: request %luMB avail %luMB max %luMB taken %luMB\n", | ||
| 297 | vgpu->id, BYTES_TO_MB(request), BYTES_TO_MB(avail), | ||
| 298 | BYTES_TO_MB(max), BYTES_TO_MB(taken)); | ||
| 299 | return -ENOSPC; | ||
| 300 | } | ||
| 301 | |||
| 302 | /** | ||
| 303 | * inte_gvt_free_vgpu_resource - free HW resource owned by a vGPU | ||
| 304 | * @vgpu: a vGPU | ||
| 305 | * | ||
| 306 | * This function is used to free the HW resource owned by a vGPU. | ||
| 307 | * | ||
| 308 | */ | ||
| 309 | void intel_vgpu_free_resource(struct intel_vgpu *vgpu) | ||
| 310 | { | ||
| 311 | free_vgpu_gm(vgpu); | ||
| 312 | free_vgpu_fence(vgpu); | ||
| 313 | free_resource(vgpu); | ||
| 314 | } | ||
| 315 | |||
| 316 | /** | ||
| 317 | * intel_alloc_vgpu_resource - allocate HW resource for a vGPU | ||
| 318 | * @vgpu: vGPU | ||
| 319 | * @param: vGPU creation params | ||
| 320 | * | ||
| 321 | * This function is used to allocate HW resource for a vGPU. User specifies | ||
| 322 | * the resource configuration through the creation params. | ||
| 323 | * | ||
| 324 | * Returns: | ||
| 325 | * zero on success, negative error code if failed. | ||
| 326 | * | ||
| 327 | */ | ||
| 328 | int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu, | ||
| 329 | struct intel_vgpu_creation_params *param) | ||
| 330 | { | ||
| 331 | int ret; | ||
| 332 | |||
| 333 | ret = alloc_resource(vgpu, param); | ||
| 334 | if (ret) | ||
| 335 | return ret; | ||
| 336 | |||
| 337 | ret = alloc_vgpu_gm(vgpu); | ||
| 338 | if (ret) | ||
| 339 | goto out_free_resource; | ||
| 340 | |||
| 341 | ret = alloc_vgpu_fence(vgpu); | ||
| 342 | if (ret) | ||
| 343 | goto out_free_vgpu_gm; | ||
| 344 | |||
| 345 | return 0; | ||
| 346 | |||
| 347 | out_free_vgpu_gm: | ||
| 348 | free_vgpu_gm(vgpu); | ||
| 349 | out_free_resource: | ||
| 350 | free_resource(vgpu); | ||
| 351 | return ret; | ||
| 352 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c new file mode 100644 index 000000000000..4c687740f5f1 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c | |||
| @@ -0,0 +1,288 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Eddie Dong <eddie.dong@intel.com> | ||
| 25 | * Jike Song <jike.song@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 29 | * Min He <min.he@intel.com> | ||
| 30 | * Bing Niu <bing.niu@intel.com> | ||
| 31 | * | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include "i915_drv.h" | ||
| 35 | #include "gvt.h" | ||
| 36 | |||
| 37 | enum { | ||
| 38 | INTEL_GVT_PCI_BAR_GTTMMIO = 0, | ||
| 39 | INTEL_GVT_PCI_BAR_APERTURE, | ||
| 40 | INTEL_GVT_PCI_BAR_PIO, | ||
| 41 | INTEL_GVT_PCI_BAR_MAX, | ||
| 42 | }; | ||
| 43 | |||
| 44 | /** | ||
| 45 | * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space read | ||
| 46 | * | ||
| 47 | * Returns: | ||
| 48 | * Zero on success, negative error code if failed. | ||
| 49 | */ | ||
| 50 | int intel_vgpu_emulate_cfg_read(void *__vgpu, unsigned int offset, | ||
| 51 | void *p_data, unsigned int bytes) | ||
| 52 | { | ||
| 53 | struct intel_vgpu *vgpu = __vgpu; | ||
| 54 | |||
| 55 | if (WARN_ON(bytes > 4)) | ||
| 56 | return -EINVAL; | ||
| 57 | |||
| 58 | if (WARN_ON(offset + bytes > INTEL_GVT_MAX_CFG_SPACE_SZ)) | ||
| 59 | return -EINVAL; | ||
| 60 | |||
| 61 | memcpy(p_data, vgpu_cfg_space(vgpu) + offset, bytes); | ||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static int map_aperture(struct intel_vgpu *vgpu, bool map) | ||
| 66 | { | ||
| 67 | u64 first_gfn, first_mfn; | ||
| 68 | u64 val; | ||
| 69 | int ret; | ||
| 70 | |||
| 71 | if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked) | ||
| 72 | return 0; | ||
| 73 | |||
| 74 | val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2]; | ||
| 75 | if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) | ||
| 76 | val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); | ||
| 77 | else | ||
| 78 | val = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); | ||
| 79 | |||
| 80 | first_gfn = (val + vgpu_aperture_offset(vgpu)) >> PAGE_SHIFT; | ||
| 81 | first_mfn = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT; | ||
| 82 | |||
| 83 | ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, first_gfn, | ||
| 84 | first_mfn, | ||
| 85 | vgpu_aperture_sz(vgpu) | ||
| 86 | >> PAGE_SHIFT, map, | ||
| 87 | GVT_MAP_APERTURE); | ||
| 88 | if (ret) | ||
| 89 | return ret; | ||
| 90 | |||
| 91 | vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map; | ||
| 92 | return 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | static int trap_gttmmio(struct intel_vgpu *vgpu, bool trap) | ||
| 96 | { | ||
| 97 | u64 start, end; | ||
| 98 | u64 val; | ||
| 99 | int ret; | ||
| 100 | |||
| 101 | if (trap == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked) | ||
| 102 | return 0; | ||
| 103 | |||
| 104 | val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_0]; | ||
| 105 | if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) | ||
| 106 | start = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0); | ||
| 107 | else | ||
| 108 | start = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0); | ||
| 109 | |||
| 110 | start &= ~GENMASK(3, 0); | ||
| 111 | end = start + vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size - 1; | ||
| 112 | |||
| 113 | ret = intel_gvt_hypervisor_set_trap_area(vgpu, start, end, trap); | ||
| 114 | if (ret) | ||
| 115 | return ret; | ||
| 116 | |||
| 117 | vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].tracked = trap; | ||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | static int emulate_pci_command_write(struct intel_vgpu *vgpu, | ||
| 122 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 123 | { | ||
| 124 | u8 old = vgpu_cfg_space(vgpu)[offset]; | ||
| 125 | u8 new = *(u8 *)p_data; | ||
| 126 | u8 changed = old ^ new; | ||
| 127 | int ret; | ||
| 128 | |||
| 129 | if (!(changed & PCI_COMMAND_MEMORY)) | ||
| 130 | return 0; | ||
| 131 | |||
| 132 | if (old & PCI_COMMAND_MEMORY) { | ||
| 133 | ret = trap_gttmmio(vgpu, false); | ||
| 134 | if (ret) | ||
| 135 | return ret; | ||
| 136 | ret = map_aperture(vgpu, false); | ||
| 137 | if (ret) | ||
| 138 | return ret; | ||
| 139 | } else { | ||
| 140 | ret = trap_gttmmio(vgpu, true); | ||
| 141 | if (ret) | ||
| 142 | return ret; | ||
| 143 | ret = map_aperture(vgpu, true); | ||
| 144 | if (ret) | ||
| 145 | return ret; | ||
| 146 | } | ||
| 147 | |||
| 148 | memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes); | ||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 153 | void *p_data, unsigned int bytes) | ||
| 154 | { | ||
| 155 | unsigned int bar_index = | ||
| 156 | (rounddown(offset, 8) % PCI_BASE_ADDRESS_0) / 8; | ||
| 157 | u32 new = *(u32 *)(p_data); | ||
| 158 | bool lo = IS_ALIGNED(offset, 8); | ||
| 159 | u64 size; | ||
| 160 | int ret = 0; | ||
| 161 | bool mmio_enabled = | ||
| 162 | vgpu_cfg_space(vgpu)[PCI_COMMAND] & PCI_COMMAND_MEMORY; | ||
| 163 | |||
| 164 | if (WARN_ON(bar_index >= INTEL_GVT_PCI_BAR_MAX)) | ||
| 165 | return -EINVAL; | ||
| 166 | |||
| 167 | if (new == 0xffffffff) { | ||
| 168 | /* | ||
| 169 | * Power-up software can determine how much address | ||
| 170 | * space the device requires by writing a value of | ||
| 171 | * all 1's to the register and then reading the value | ||
| 172 | * back. The device will return 0's in all don't-care | ||
| 173 | * address bits. | ||
| 174 | */ | ||
| 175 | size = vgpu->cfg_space.bar[bar_index].size; | ||
| 176 | if (lo) { | ||
| 177 | new = rounddown(new, size); | ||
| 178 | } else { | ||
| 179 | u32 val = vgpu_cfg_space(vgpu)[rounddown(offset, 8)]; | ||
| 180 | /* for 32bit mode bar it returns all-0 in upper 32 | ||
| 181 | * bit, for 64bit mode bar it will calculate the | ||
| 182 | * size with lower 32bit and return the corresponding | ||
| 183 | * value | ||
| 184 | */ | ||
| 185 | if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) | ||
| 186 | new &= (~(size-1)) >> 32; | ||
| 187 | else | ||
| 188 | new = 0; | ||
| 189 | } | ||
| 190 | /* | ||
| 191 | * Unmapp & untrap the BAR, since guest hasn't configured a | ||
| 192 | * valid GPA | ||
| 193 | */ | ||
| 194 | switch (bar_index) { | ||
| 195 | case INTEL_GVT_PCI_BAR_GTTMMIO: | ||
| 196 | ret = trap_gttmmio(vgpu, false); | ||
| 197 | break; | ||
| 198 | case INTEL_GVT_PCI_BAR_APERTURE: | ||
| 199 | ret = map_aperture(vgpu, false); | ||
| 200 | break; | ||
| 201 | } | ||
| 202 | intel_vgpu_write_pci_bar(vgpu, offset, new, lo); | ||
| 203 | } else { | ||
| 204 | /* | ||
| 205 | * Unmapp & untrap the old BAR first, since guest has | ||
| 206 | * re-configured the BAR | ||
| 207 | */ | ||
| 208 | switch (bar_index) { | ||
| 209 | case INTEL_GVT_PCI_BAR_GTTMMIO: | ||
| 210 | ret = trap_gttmmio(vgpu, false); | ||
| 211 | break; | ||
| 212 | case INTEL_GVT_PCI_BAR_APERTURE: | ||
| 213 | ret = map_aperture(vgpu, false); | ||
| 214 | break; | ||
| 215 | } | ||
| 216 | intel_vgpu_write_pci_bar(vgpu, offset, new, lo); | ||
| 217 | /* Track the new BAR */ | ||
| 218 | if (mmio_enabled) { | ||
| 219 | switch (bar_index) { | ||
| 220 | case INTEL_GVT_PCI_BAR_GTTMMIO: | ||
| 221 | ret = trap_gttmmio(vgpu, true); | ||
| 222 | break; | ||
| 223 | case INTEL_GVT_PCI_BAR_APERTURE: | ||
| 224 | ret = map_aperture(vgpu, true); | ||
| 225 | break; | ||
| 226 | } | ||
| 227 | } | ||
| 228 | } | ||
| 229 | return ret; | ||
| 230 | } | ||
| 231 | |||
| 232 | /** | ||
| 233 | * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space write | ||
| 234 | * | ||
| 235 | * Returns: | ||
| 236 | * Zero on success, negative error code if failed. | ||
| 237 | */ | ||
| 238 | int intel_vgpu_emulate_cfg_write(void *__vgpu, unsigned int offset, | ||
| 239 | void *p_data, unsigned int bytes) | ||
| 240 | { | ||
| 241 | struct intel_vgpu *vgpu = __vgpu; | ||
| 242 | int ret; | ||
| 243 | |||
| 244 | if (WARN_ON(bytes > 4)) | ||
| 245 | return -EINVAL; | ||
| 246 | |||
| 247 | if (WARN_ON(offset + bytes >= INTEL_GVT_MAX_CFG_SPACE_SZ)) | ||
| 248 | return -EINVAL; | ||
| 249 | |||
| 250 | /* First check if it's PCI_COMMAND */ | ||
| 251 | if (IS_ALIGNED(offset, 2) && offset == PCI_COMMAND) { | ||
| 252 | if (WARN_ON(bytes > 2)) | ||
| 253 | return -EINVAL; | ||
| 254 | return emulate_pci_command_write(vgpu, offset, p_data, bytes); | ||
| 255 | } | ||
| 256 | |||
| 257 | switch (rounddown(offset, 4)) { | ||
| 258 | case PCI_BASE_ADDRESS_0: | ||
| 259 | case PCI_BASE_ADDRESS_1: | ||
| 260 | case PCI_BASE_ADDRESS_2: | ||
| 261 | case PCI_BASE_ADDRESS_3: | ||
| 262 | if (WARN_ON(!IS_ALIGNED(offset, 4))) | ||
| 263 | return -EINVAL; | ||
| 264 | return emulate_pci_bar_write(vgpu, offset, p_data, bytes); | ||
| 265 | |||
| 266 | case INTEL_GVT_PCI_SWSCI: | ||
| 267 | if (WARN_ON(!IS_ALIGNED(offset, 4))) | ||
| 268 | return -EINVAL; | ||
| 269 | ret = intel_vgpu_emulate_opregion_request(vgpu, *(u32 *)p_data); | ||
| 270 | if (ret) | ||
| 271 | return ret; | ||
| 272 | break; | ||
| 273 | |||
| 274 | case INTEL_GVT_PCI_OPREGION: | ||
| 275 | if (WARN_ON(!IS_ALIGNED(offset, 4))) | ||
| 276 | return -EINVAL; | ||
| 277 | ret = intel_vgpu_init_opregion(vgpu, *(u32 *)p_data); | ||
| 278 | if (ret) | ||
| 279 | return ret; | ||
| 280 | |||
| 281 | memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes); | ||
| 282 | break; | ||
| 283 | default: | ||
| 284 | memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes); | ||
| 285 | break; | ||
| 286 | } | ||
| 287 | return 0; | ||
| 288 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c new file mode 100644 index 000000000000..aafb57e26288 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c | |||
| @@ -0,0 +1,2831 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Ke Yu | ||
| 25 | * Kevin Tian <kevin.tian@intel.com> | ||
| 26 | * Zhiyuan Lv <zhiyuan.lv@intel.com> | ||
| 27 | * | ||
| 28 | * Contributors: | ||
| 29 | * Min He <min.he@intel.com> | ||
| 30 | * Ping Gao <ping.a.gao@intel.com> | ||
| 31 | * Tina Zhang <tina.zhang@intel.com> | ||
| 32 | * Yulei Zhang <yulei.zhang@intel.com> | ||
| 33 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 34 | * | ||
| 35 | */ | ||
| 36 | |||
| 37 | #include <linux/slab.h> | ||
| 38 | #include "i915_drv.h" | ||
| 39 | #include "gvt.h" | ||
| 40 | #include "i915_pvinfo.h" | ||
| 41 | #include "trace.h" | ||
| 42 | |||
| 43 | #define INVALID_OP (~0U) | ||
| 44 | |||
| 45 | #define OP_LEN_MI 9 | ||
| 46 | #define OP_LEN_2D 10 | ||
| 47 | #define OP_LEN_3D_MEDIA 16 | ||
| 48 | #define OP_LEN_MFX_VC 16 | ||
| 49 | #define OP_LEN_VEBOX 16 | ||
| 50 | |||
| 51 | #define CMD_TYPE(cmd) (((cmd) >> 29) & 7) | ||
| 52 | |||
| 53 | struct sub_op_bits { | ||
| 54 | int hi; | ||
| 55 | int low; | ||
| 56 | }; | ||
| 57 | struct decode_info { | ||
| 58 | char *name; | ||
| 59 | int op_len; | ||
| 60 | int nr_sub_op; | ||
| 61 | struct sub_op_bits *sub_op; | ||
| 62 | }; | ||
| 63 | |||
| 64 | #define MAX_CMD_BUDGET 0x7fffffff | ||
| 65 | #define MI_WAIT_FOR_PLANE_C_FLIP_PENDING (1<<15) | ||
| 66 | #define MI_WAIT_FOR_PLANE_B_FLIP_PENDING (1<<9) | ||
| 67 | #define MI_WAIT_FOR_PLANE_A_FLIP_PENDING (1<<1) | ||
| 68 | |||
| 69 | #define MI_WAIT_FOR_SPRITE_C_FLIP_PENDING (1<<20) | ||
| 70 | #define MI_WAIT_FOR_SPRITE_B_FLIP_PENDING (1<<10) | ||
| 71 | #define MI_WAIT_FOR_SPRITE_A_FLIP_PENDING (1<<2) | ||
| 72 | |||
| 73 | /* Render Command Map */ | ||
| 74 | |||
| 75 | /* MI_* command Opcode (28:23) */ | ||
| 76 | #define OP_MI_NOOP 0x0 | ||
| 77 | #define OP_MI_SET_PREDICATE 0x1 /* HSW+ */ | ||
| 78 | #define OP_MI_USER_INTERRUPT 0x2 | ||
| 79 | #define OP_MI_WAIT_FOR_EVENT 0x3 | ||
| 80 | #define OP_MI_FLUSH 0x4 | ||
| 81 | #define OP_MI_ARB_CHECK 0x5 | ||
| 82 | #define OP_MI_RS_CONTROL 0x6 /* HSW+ */ | ||
| 83 | #define OP_MI_REPORT_HEAD 0x7 | ||
| 84 | #define OP_MI_ARB_ON_OFF 0x8 | ||
| 85 | #define OP_MI_URB_ATOMIC_ALLOC 0x9 /* HSW+ */ | ||
| 86 | #define OP_MI_BATCH_BUFFER_END 0xA | ||
| 87 | #define OP_MI_SUSPEND_FLUSH 0xB | ||
| 88 | #define OP_MI_PREDICATE 0xC /* IVB+ */ | ||
| 89 | #define OP_MI_TOPOLOGY_FILTER 0xD /* IVB+ */ | ||
| 90 | #define OP_MI_SET_APPID 0xE /* IVB+ */ | ||
| 91 | #define OP_MI_RS_CONTEXT 0xF /* HSW+ */ | ||
| 92 | #define OP_MI_LOAD_SCAN_LINES_INCL 0x12 /* HSW+ */ | ||
| 93 | #define OP_MI_DISPLAY_FLIP 0x14 | ||
| 94 | #define OP_MI_SEMAPHORE_MBOX 0x16 | ||
| 95 | #define OP_MI_SET_CONTEXT 0x18 | ||
| 96 | #define OP_MI_MATH 0x1A | ||
| 97 | #define OP_MI_URB_CLEAR 0x19 | ||
| 98 | #define OP_MI_SEMAPHORE_SIGNAL 0x1B /* BDW+ */ | ||
| 99 | #define OP_MI_SEMAPHORE_WAIT 0x1C /* BDW+ */ | ||
| 100 | |||
| 101 | #define OP_MI_STORE_DATA_IMM 0x20 | ||
| 102 | #define OP_MI_STORE_DATA_INDEX 0x21 | ||
| 103 | #define OP_MI_LOAD_REGISTER_IMM 0x22 | ||
| 104 | #define OP_MI_UPDATE_GTT 0x23 | ||
| 105 | #define OP_MI_STORE_REGISTER_MEM 0x24 | ||
| 106 | #define OP_MI_FLUSH_DW 0x26 | ||
| 107 | #define OP_MI_CLFLUSH 0x27 | ||
| 108 | #define OP_MI_REPORT_PERF_COUNT 0x28 | ||
| 109 | #define OP_MI_LOAD_REGISTER_MEM 0x29 /* HSW+ */ | ||
| 110 | #define OP_MI_LOAD_REGISTER_REG 0x2A /* HSW+ */ | ||
| 111 | #define OP_MI_RS_STORE_DATA_IMM 0x2B /* HSW+ */ | ||
| 112 | #define OP_MI_LOAD_URB_MEM 0x2C /* HSW+ */ | ||
| 113 | #define OP_MI_STORE_URM_MEM 0x2D /* HSW+ */ | ||
| 114 | #define OP_MI_2E 0x2E /* BDW+ */ | ||
| 115 | #define OP_MI_2F 0x2F /* BDW+ */ | ||
| 116 | #define OP_MI_BATCH_BUFFER_START 0x31 | ||
| 117 | |||
| 118 | /* Bit definition for dword 0 */ | ||
| 119 | #define _CMDBIT_BB_START_IN_PPGTT (1UL << 8) | ||
| 120 | |||
| 121 | #define OP_MI_CONDITIONAL_BATCH_BUFFER_END 0x36 | ||
| 122 | |||
| 123 | #define BATCH_BUFFER_ADDR_MASK ((1UL << 32) - (1U << 2)) | ||
| 124 | #define BATCH_BUFFER_ADDR_HIGH_MASK ((1UL << 16) - (1U)) | ||
| 125 | #define BATCH_BUFFER_ADR_SPACE_BIT(x) (((x) >> 8) & 1U) | ||
| 126 | #define BATCH_BUFFER_2ND_LEVEL_BIT(x) ((x) >> 22 & 1U) | ||
| 127 | |||
| 128 | /* 2D command: Opcode (28:22) */ | ||
| 129 | #define OP_2D(x) ((2<<7) | x) | ||
| 130 | |||
| 131 | #define OP_XY_SETUP_BLT OP_2D(0x1) | ||
| 132 | #define OP_XY_SETUP_CLIP_BLT OP_2D(0x3) | ||
| 133 | #define OP_XY_SETUP_MONO_PATTERN_SL_BLT OP_2D(0x11) | ||
| 134 | #define OP_XY_PIXEL_BLT OP_2D(0x24) | ||
| 135 | #define OP_XY_SCANLINES_BLT OP_2D(0x25) | ||
| 136 | #define OP_XY_TEXT_BLT OP_2D(0x26) | ||
| 137 | #define OP_XY_TEXT_IMMEDIATE_BLT OP_2D(0x31) | ||
| 138 | #define OP_XY_COLOR_BLT OP_2D(0x50) | ||
| 139 | #define OP_XY_PAT_BLT OP_2D(0x51) | ||
| 140 | #define OP_XY_MONO_PAT_BLT OP_2D(0x52) | ||
| 141 | #define OP_XY_SRC_COPY_BLT OP_2D(0x53) | ||
| 142 | #define OP_XY_MONO_SRC_COPY_BLT OP_2D(0x54) | ||
| 143 | #define OP_XY_FULL_BLT OP_2D(0x55) | ||
| 144 | #define OP_XY_FULL_MONO_SRC_BLT OP_2D(0x56) | ||
| 145 | #define OP_XY_FULL_MONO_PATTERN_BLT OP_2D(0x57) | ||
| 146 | #define OP_XY_FULL_MONO_PATTERN_MONO_SRC_BLT OP_2D(0x58) | ||
| 147 | #define OP_XY_MONO_PAT_FIXED_BLT OP_2D(0x59) | ||
| 148 | #define OP_XY_MONO_SRC_COPY_IMMEDIATE_BLT OP_2D(0x71) | ||
| 149 | #define OP_XY_PAT_BLT_IMMEDIATE OP_2D(0x72) | ||
| 150 | #define OP_XY_SRC_COPY_CHROMA_BLT OP_2D(0x73) | ||
| 151 | #define OP_XY_FULL_IMMEDIATE_PATTERN_BLT OP_2D(0x74) | ||
| 152 | #define OP_XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT OP_2D(0x75) | ||
| 153 | #define OP_XY_PAT_CHROMA_BLT OP_2D(0x76) | ||
| 154 | #define OP_XY_PAT_CHROMA_BLT_IMMEDIATE OP_2D(0x77) | ||
| 155 | |||
| 156 | /* 3D/Media Command: Pipeline Type(28:27) Opcode(26:24) Sub Opcode(23:16) */ | ||
| 157 | #define OP_3D_MEDIA(sub_type, opcode, sub_opcode) \ | ||
| 158 | ((3 << 13) | ((sub_type) << 11) | ((opcode) << 8) | (sub_opcode)) | ||
| 159 | |||
| 160 | #define OP_STATE_PREFETCH OP_3D_MEDIA(0x0, 0x0, 0x03) | ||
| 161 | |||
| 162 | #define OP_STATE_BASE_ADDRESS OP_3D_MEDIA(0x0, 0x1, 0x01) | ||
| 163 | #define OP_STATE_SIP OP_3D_MEDIA(0x0, 0x1, 0x02) | ||
| 164 | #define OP_3D_MEDIA_0_1_4 OP_3D_MEDIA(0x0, 0x1, 0x04) | ||
| 165 | |||
| 166 | #define OP_3DSTATE_VF_STATISTICS_GM45 OP_3D_MEDIA(0x1, 0x0, 0x0B) | ||
| 167 | |||
| 168 | #define OP_PIPELINE_SELECT OP_3D_MEDIA(0x1, 0x1, 0x04) | ||
| 169 | |||
| 170 | #define OP_MEDIA_VFE_STATE OP_3D_MEDIA(0x2, 0x0, 0x0) | ||
| 171 | #define OP_MEDIA_CURBE_LOAD OP_3D_MEDIA(0x2, 0x0, 0x1) | ||
| 172 | #define OP_MEDIA_INTERFACE_DESCRIPTOR_LOAD OP_3D_MEDIA(0x2, 0x0, 0x2) | ||
| 173 | #define OP_MEDIA_GATEWAY_STATE OP_3D_MEDIA(0x2, 0x0, 0x3) | ||
| 174 | #define OP_MEDIA_STATE_FLUSH OP_3D_MEDIA(0x2, 0x0, 0x4) | ||
| 175 | |||
| 176 | #define OP_MEDIA_OBJECT OP_3D_MEDIA(0x2, 0x1, 0x0) | ||
| 177 | #define OP_MEDIA_OBJECT_PRT OP_3D_MEDIA(0x2, 0x1, 0x2) | ||
| 178 | #define OP_MEDIA_OBJECT_WALKER OP_3D_MEDIA(0x2, 0x1, 0x3) | ||
| 179 | #define OP_GPGPU_WALKER OP_3D_MEDIA(0x2, 0x1, 0x5) | ||
| 180 | |||
| 181 | #define OP_3DSTATE_CLEAR_PARAMS OP_3D_MEDIA(0x3, 0x0, 0x04) /* IVB+ */ | ||
| 182 | #define OP_3DSTATE_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x05) /* IVB+ */ | ||
| 183 | #define OP_3DSTATE_STENCIL_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x06) /* IVB+ */ | ||
| 184 | #define OP_3DSTATE_HIER_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x07) /* IVB+ */ | ||
| 185 | #define OP_3DSTATE_VERTEX_BUFFERS OP_3D_MEDIA(0x3, 0x0, 0x08) | ||
| 186 | #define OP_3DSTATE_VERTEX_ELEMENTS OP_3D_MEDIA(0x3, 0x0, 0x09) | ||
| 187 | #define OP_3DSTATE_INDEX_BUFFER OP_3D_MEDIA(0x3, 0x0, 0x0A) | ||
| 188 | #define OP_3DSTATE_VF_STATISTICS OP_3D_MEDIA(0x3, 0x0, 0x0B) | ||
| 189 | #define OP_3DSTATE_VF OP_3D_MEDIA(0x3, 0x0, 0x0C) /* HSW+ */ | ||
| 190 | #define OP_3DSTATE_CC_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x0E) | ||
| 191 | #define OP_3DSTATE_SCISSOR_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x0F) | ||
| 192 | #define OP_3DSTATE_VS OP_3D_MEDIA(0x3, 0x0, 0x10) | ||
| 193 | #define OP_3DSTATE_GS OP_3D_MEDIA(0x3, 0x0, 0x11) | ||
| 194 | #define OP_3DSTATE_CLIP OP_3D_MEDIA(0x3, 0x0, 0x12) | ||
| 195 | #define OP_3DSTATE_SF OP_3D_MEDIA(0x3, 0x0, 0x13) | ||
| 196 | #define OP_3DSTATE_WM OP_3D_MEDIA(0x3, 0x0, 0x14) | ||
| 197 | #define OP_3DSTATE_CONSTANT_VS OP_3D_MEDIA(0x3, 0x0, 0x15) | ||
| 198 | #define OP_3DSTATE_CONSTANT_GS OP_3D_MEDIA(0x3, 0x0, 0x16) | ||
| 199 | #define OP_3DSTATE_CONSTANT_PS OP_3D_MEDIA(0x3, 0x0, 0x17) | ||
| 200 | #define OP_3DSTATE_SAMPLE_MASK OP_3D_MEDIA(0x3, 0x0, 0x18) | ||
| 201 | #define OP_3DSTATE_CONSTANT_HS OP_3D_MEDIA(0x3, 0x0, 0x19) /* IVB+ */ | ||
| 202 | #define OP_3DSTATE_CONSTANT_DS OP_3D_MEDIA(0x3, 0x0, 0x1A) /* IVB+ */ | ||
| 203 | #define OP_3DSTATE_HS OP_3D_MEDIA(0x3, 0x0, 0x1B) /* IVB+ */ | ||
| 204 | #define OP_3DSTATE_TE OP_3D_MEDIA(0x3, 0x0, 0x1C) /* IVB+ */ | ||
| 205 | #define OP_3DSTATE_DS OP_3D_MEDIA(0x3, 0x0, 0x1D) /* IVB+ */ | ||
| 206 | #define OP_3DSTATE_STREAMOUT OP_3D_MEDIA(0x3, 0x0, 0x1E) /* IVB+ */ | ||
| 207 | #define OP_3DSTATE_SBE OP_3D_MEDIA(0x3, 0x0, 0x1F) /* IVB+ */ | ||
| 208 | #define OP_3DSTATE_PS OP_3D_MEDIA(0x3, 0x0, 0x20) /* IVB+ */ | ||
| 209 | #define OP_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP OP_3D_MEDIA(0x3, 0x0, 0x21) /* IVB+ */ | ||
| 210 | #define OP_3DSTATE_VIEWPORT_STATE_POINTERS_CC OP_3D_MEDIA(0x3, 0x0, 0x23) /* IVB+ */ | ||
| 211 | #define OP_3DSTATE_BLEND_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x24) /* IVB+ */ | ||
| 212 | #define OP_3DSTATE_DEPTH_STENCIL_STATE_POINTERS OP_3D_MEDIA(0x3, 0x0, 0x25) /* IVB+ */ | ||
| 213 | #define OP_3DSTATE_BINDING_TABLE_POINTERS_VS OP_3D_MEDIA(0x3, 0x0, 0x26) /* IVB+ */ | ||
| 214 | #define OP_3DSTATE_BINDING_TABLE_POINTERS_HS OP_3D_MEDIA(0x3, 0x0, 0x27) /* IVB+ */ | ||
| 215 | #define OP_3DSTATE_BINDING_TABLE_POINTERS_DS OP_3D_MEDIA(0x3, 0x0, 0x28) /* IVB+ */ | ||
| 216 | #define OP_3DSTATE_BINDING_TABLE_POINTERS_GS OP_3D_MEDIA(0x3, 0x0, 0x29) /* IVB+ */ | ||
| 217 | #define OP_3DSTATE_BINDING_TABLE_POINTERS_PS OP_3D_MEDIA(0x3, 0x0, 0x2A) /* IVB+ */ | ||
| 218 | #define OP_3DSTATE_SAMPLER_STATE_POINTERS_VS OP_3D_MEDIA(0x3, 0x0, 0x2B) /* IVB+ */ | ||
| 219 | #define OP_3DSTATE_SAMPLER_STATE_POINTERS_HS OP_3D_MEDIA(0x3, 0x0, 0x2C) /* IVB+ */ | ||
| 220 | #define OP_3DSTATE_SAMPLER_STATE_POINTERS_DS OP_3D_MEDIA(0x3, 0x0, 0x2D) /* IVB+ */ | ||
| 221 | #define OP_3DSTATE_SAMPLER_STATE_POINTERS_GS OP_3D_MEDIA(0x3, 0x0, 0x2E) /* IVB+ */ | ||
| 222 | #define OP_3DSTATE_SAMPLER_STATE_POINTERS_PS OP_3D_MEDIA(0x3, 0x0, 0x2F) /* IVB+ */ | ||
| 223 | #define OP_3DSTATE_URB_VS OP_3D_MEDIA(0x3, 0x0, 0x30) /* IVB+ */ | ||
| 224 | #define OP_3DSTATE_URB_HS OP_3D_MEDIA(0x3, 0x0, 0x31) /* IVB+ */ | ||
| 225 | #define OP_3DSTATE_URB_DS OP_3D_MEDIA(0x3, 0x0, 0x32) /* IVB+ */ | ||
| 226 | #define OP_3DSTATE_URB_GS OP_3D_MEDIA(0x3, 0x0, 0x33) /* IVB+ */ | ||
| 227 | #define OP_3DSTATE_GATHER_CONSTANT_VS OP_3D_MEDIA(0x3, 0x0, 0x34) /* HSW+ */ | ||
| 228 | #define OP_3DSTATE_GATHER_CONSTANT_GS OP_3D_MEDIA(0x3, 0x0, 0x35) /* HSW+ */ | ||
| 229 | #define OP_3DSTATE_GATHER_CONSTANT_HS OP_3D_MEDIA(0x3, 0x0, 0x36) /* HSW+ */ | ||
| 230 | #define OP_3DSTATE_GATHER_CONSTANT_DS OP_3D_MEDIA(0x3, 0x0, 0x37) /* HSW+ */ | ||
| 231 | #define OP_3DSTATE_GATHER_CONSTANT_PS OP_3D_MEDIA(0x3, 0x0, 0x38) /* HSW+ */ | ||
| 232 | #define OP_3DSTATE_DX9_CONSTANTF_VS OP_3D_MEDIA(0x3, 0x0, 0x39) /* HSW+ */ | ||
| 233 | #define OP_3DSTATE_DX9_CONSTANTF_PS OP_3D_MEDIA(0x3, 0x0, 0x3A) /* HSW+ */ | ||
| 234 | #define OP_3DSTATE_DX9_CONSTANTI_VS OP_3D_MEDIA(0x3, 0x0, 0x3B) /* HSW+ */ | ||
| 235 | #define OP_3DSTATE_DX9_CONSTANTI_PS OP_3D_MEDIA(0x3, 0x0, 0x3C) /* HSW+ */ | ||
| 236 | #define OP_3DSTATE_DX9_CONSTANTB_VS OP_3D_MEDIA(0x3, 0x0, 0x3D) /* HSW+ */ | ||
| 237 | #define OP_3DSTATE_DX9_CONSTANTB_PS OP_3D_MEDIA(0x3, 0x0, 0x3E) /* HSW+ */ | ||
| 238 | #define OP_3DSTATE_DX9_LOCAL_VALID_VS OP_3D_MEDIA(0x3, 0x0, 0x3F) /* HSW+ */ | ||
| 239 | #define OP_3DSTATE_DX9_LOCAL_VALID_PS OP_3D_MEDIA(0x3, 0x0, 0x40) /* HSW+ */ | ||
| 240 | #define OP_3DSTATE_DX9_GENERATE_ACTIVE_VS OP_3D_MEDIA(0x3, 0x0, 0x41) /* HSW+ */ | ||
| 241 | #define OP_3DSTATE_DX9_GENERATE_ACTIVE_PS OP_3D_MEDIA(0x3, 0x0, 0x42) /* HSW+ */ | ||
| 242 | #define OP_3DSTATE_BINDING_TABLE_EDIT_VS OP_3D_MEDIA(0x3, 0x0, 0x43) /* HSW+ */ | ||
| 243 | #define OP_3DSTATE_BINDING_TABLE_EDIT_GS OP_3D_MEDIA(0x3, 0x0, 0x44) /* HSW+ */ | ||
| 244 | #define OP_3DSTATE_BINDING_TABLE_EDIT_HS OP_3D_MEDIA(0x3, 0x0, 0x45) /* HSW+ */ | ||
| 245 | #define OP_3DSTATE_BINDING_TABLE_EDIT_DS OP_3D_MEDIA(0x3, 0x0, 0x46) /* HSW+ */ | ||
| 246 | #define OP_3DSTATE_BINDING_TABLE_EDIT_PS OP_3D_MEDIA(0x3, 0x0, 0x47) /* HSW+ */ | ||
| 247 | |||
| 248 | #define OP_3DSTATE_VF_INSTANCING OP_3D_MEDIA(0x3, 0x0, 0x49) /* BDW+ */ | ||
| 249 | #define OP_3DSTATE_VF_SGVS OP_3D_MEDIA(0x3, 0x0, 0x4A) /* BDW+ */ | ||
| 250 | #define OP_3DSTATE_VF_TOPOLOGY OP_3D_MEDIA(0x3, 0x0, 0x4B) /* BDW+ */ | ||
| 251 | #define OP_3DSTATE_WM_CHROMAKEY OP_3D_MEDIA(0x3, 0x0, 0x4C) /* BDW+ */ | ||
| 252 | #define OP_3DSTATE_PS_BLEND OP_3D_MEDIA(0x3, 0x0, 0x4D) /* BDW+ */ | ||
| 253 | #define OP_3DSTATE_WM_DEPTH_STENCIL OP_3D_MEDIA(0x3, 0x0, 0x4E) /* BDW+ */ | ||
| 254 | #define OP_3DSTATE_PS_EXTRA OP_3D_MEDIA(0x3, 0x0, 0x4F) /* BDW+ */ | ||
| 255 | #define OP_3DSTATE_RASTER OP_3D_MEDIA(0x3, 0x0, 0x50) /* BDW+ */ | ||
| 256 | #define OP_3DSTATE_SBE_SWIZ OP_3D_MEDIA(0x3, 0x0, 0x51) /* BDW+ */ | ||
| 257 | #define OP_3DSTATE_WM_HZ_OP OP_3D_MEDIA(0x3, 0x0, 0x52) /* BDW+ */ | ||
| 258 | #define OP_3DSTATE_COMPONENT_PACKING OP_3D_MEDIA(0x3, 0x0, 0x55) /* SKL+ */ | ||
| 259 | |||
| 260 | #define OP_3DSTATE_DRAWING_RECTANGLE OP_3D_MEDIA(0x3, 0x1, 0x00) | ||
| 261 | #define OP_3DSTATE_SAMPLER_PALETTE_LOAD0 OP_3D_MEDIA(0x3, 0x1, 0x02) | ||
| 262 | #define OP_3DSTATE_CHROMA_KEY OP_3D_MEDIA(0x3, 0x1, 0x04) | ||
| 263 | #define OP_SNB_3DSTATE_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x05) | ||
| 264 | #define OP_3DSTATE_POLY_STIPPLE_OFFSET OP_3D_MEDIA(0x3, 0x1, 0x06) | ||
| 265 | #define OP_3DSTATE_POLY_STIPPLE_PATTERN OP_3D_MEDIA(0x3, 0x1, 0x07) | ||
| 266 | #define OP_3DSTATE_LINE_STIPPLE OP_3D_MEDIA(0x3, 0x1, 0x08) | ||
| 267 | #define OP_3DSTATE_AA_LINE_PARAMS OP_3D_MEDIA(0x3, 0x1, 0x0A) | ||
| 268 | #define OP_3DSTATE_GS_SVB_INDEX OP_3D_MEDIA(0x3, 0x1, 0x0B) | ||
| 269 | #define OP_3DSTATE_SAMPLER_PALETTE_LOAD1 OP_3D_MEDIA(0x3, 0x1, 0x0C) | ||
| 270 | #define OP_3DSTATE_MULTISAMPLE_BDW OP_3D_MEDIA(0x3, 0x0, 0x0D) | ||
| 271 | #define OP_SNB_3DSTATE_STENCIL_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x0E) | ||
| 272 | #define OP_SNB_3DSTATE_HIER_DEPTH_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x0F) | ||
| 273 | #define OP_SNB_3DSTATE_CLEAR_PARAMS OP_3D_MEDIA(0x3, 0x1, 0x10) | ||
| 274 | #define OP_3DSTATE_MONOFILTER_SIZE OP_3D_MEDIA(0x3, 0x1, 0x11) | ||
| 275 | #define OP_3DSTATE_PUSH_CONSTANT_ALLOC_VS OP_3D_MEDIA(0x3, 0x1, 0x12) /* IVB+ */ | ||
| 276 | #define OP_3DSTATE_PUSH_CONSTANT_ALLOC_HS OP_3D_MEDIA(0x3, 0x1, 0x13) /* IVB+ */ | ||
| 277 | #define OP_3DSTATE_PUSH_CONSTANT_ALLOC_DS OP_3D_MEDIA(0x3, 0x1, 0x14) /* IVB+ */ | ||
| 278 | #define OP_3DSTATE_PUSH_CONSTANT_ALLOC_GS OP_3D_MEDIA(0x3, 0x1, 0x15) /* IVB+ */ | ||
| 279 | #define OP_3DSTATE_PUSH_CONSTANT_ALLOC_PS OP_3D_MEDIA(0x3, 0x1, 0x16) /* IVB+ */ | ||
| 280 | #define OP_3DSTATE_SO_DECL_LIST OP_3D_MEDIA(0x3, 0x1, 0x17) | ||
| 281 | #define OP_3DSTATE_SO_BUFFER OP_3D_MEDIA(0x3, 0x1, 0x18) | ||
| 282 | #define OP_3DSTATE_BINDING_TABLE_POOL_ALLOC OP_3D_MEDIA(0x3, 0x1, 0x19) /* HSW+ */ | ||
| 283 | #define OP_3DSTATE_GATHER_POOL_ALLOC OP_3D_MEDIA(0x3, 0x1, 0x1A) /* HSW+ */ | ||
| 284 | #define OP_3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC OP_3D_MEDIA(0x3, 0x1, 0x1B) /* HSW+ */ | ||
| 285 | #define OP_3DSTATE_SAMPLE_PATTERN OP_3D_MEDIA(0x3, 0x1, 0x1C) | ||
| 286 | #define OP_PIPE_CONTROL OP_3D_MEDIA(0x3, 0x2, 0x00) | ||
| 287 | #define OP_3DPRIMITIVE OP_3D_MEDIA(0x3, 0x3, 0x00) | ||
| 288 | |||
| 289 | /* VCCP Command Parser */ | ||
| 290 | |||
| 291 | /* | ||
| 292 | * Below MFX and VBE cmd definition is from vaapi intel driver project (BSD License) | ||
| 293 | * git://anongit.freedesktop.org/vaapi/intel-driver | ||
| 294 | * src/i965_defines.h | ||
| 295 | * | ||
| 296 | */ | ||
| 297 | |||
| 298 | #define OP_MFX(pipeline, op, sub_opa, sub_opb) \ | ||
| 299 | (3 << 13 | \ | ||
| 300 | (pipeline) << 11 | \ | ||
| 301 | (op) << 8 | \ | ||
| 302 | (sub_opa) << 5 | \ | ||
| 303 | (sub_opb)) | ||
| 304 | |||
| 305 | #define OP_MFX_PIPE_MODE_SELECT OP_MFX(2, 0, 0, 0) /* ALL */ | ||
| 306 | #define OP_MFX_SURFACE_STATE OP_MFX(2, 0, 0, 1) /* ALL */ | ||
| 307 | #define OP_MFX_PIPE_BUF_ADDR_STATE OP_MFX(2, 0, 0, 2) /* ALL */ | ||
| 308 | #define OP_MFX_IND_OBJ_BASE_ADDR_STATE OP_MFX(2, 0, 0, 3) /* ALL */ | ||
| 309 | #define OP_MFX_BSP_BUF_BASE_ADDR_STATE OP_MFX(2, 0, 0, 4) /* ALL */ | ||
| 310 | #define OP_2_0_0_5 OP_MFX(2, 0, 0, 5) /* ALL */ | ||
| 311 | #define OP_MFX_STATE_POINTER OP_MFX(2, 0, 0, 6) /* ALL */ | ||
| 312 | #define OP_MFX_QM_STATE OP_MFX(2, 0, 0, 7) /* IVB+ */ | ||
| 313 | #define OP_MFX_FQM_STATE OP_MFX(2, 0, 0, 8) /* IVB+ */ | ||
| 314 | #define OP_MFX_PAK_INSERT_OBJECT OP_MFX(2, 0, 2, 8) /* IVB+ */ | ||
| 315 | #define OP_MFX_STITCH_OBJECT OP_MFX(2, 0, 2, 0xA) /* IVB+ */ | ||
| 316 | |||
| 317 | #define OP_MFD_IT_OBJECT OP_MFX(2, 0, 1, 9) /* ALL */ | ||
| 318 | |||
| 319 | #define OP_MFX_WAIT OP_MFX(1, 0, 0, 0) /* IVB+ */ | ||
| 320 | #define OP_MFX_AVC_IMG_STATE OP_MFX(2, 1, 0, 0) /* ALL */ | ||
| 321 | #define OP_MFX_AVC_QM_STATE OP_MFX(2, 1, 0, 1) /* ALL */ | ||
| 322 | #define OP_MFX_AVC_DIRECTMODE_STATE OP_MFX(2, 1, 0, 2) /* ALL */ | ||
| 323 | #define OP_MFX_AVC_SLICE_STATE OP_MFX(2, 1, 0, 3) /* ALL */ | ||
| 324 | #define OP_MFX_AVC_REF_IDX_STATE OP_MFX(2, 1, 0, 4) /* ALL */ | ||
| 325 | #define OP_MFX_AVC_WEIGHTOFFSET_STATE OP_MFX(2, 1, 0, 5) /* ALL */ | ||
| 326 | #define OP_MFD_AVC_PICID_STATE OP_MFX(2, 1, 1, 5) /* HSW+ */ | ||
| 327 | #define OP_MFD_AVC_DPB_STATE OP_MFX(2, 1, 1, 6) /* IVB+ */ | ||
| 328 | #define OP_MFD_AVC_SLICEADDR OP_MFX(2, 1, 1, 7) /* IVB+ */ | ||
| 329 | #define OP_MFD_AVC_BSD_OBJECT OP_MFX(2, 1, 1, 8) /* ALL */ | ||
| 330 | #define OP_MFC_AVC_PAK_OBJECT OP_MFX(2, 1, 2, 9) /* ALL */ | ||
| 331 | |||
| 332 | #define OP_MFX_VC1_PRED_PIPE_STATE OP_MFX(2, 2, 0, 1) /* ALL */ | ||
| 333 | #define OP_MFX_VC1_DIRECTMODE_STATE OP_MFX(2, 2, 0, 2) /* ALL */ | ||
| 334 | #define OP_MFD_VC1_SHORT_PIC_STATE OP_MFX(2, 2, 1, 0) /* IVB+ */ | ||
| 335 | #define OP_MFD_VC1_LONG_PIC_STATE OP_MFX(2, 2, 1, 1) /* IVB+ */ | ||
| 336 | #define OP_MFD_VC1_BSD_OBJECT OP_MFX(2, 2, 1, 8) /* ALL */ | ||
| 337 | |||
| 338 | #define OP_MFX_MPEG2_PIC_STATE OP_MFX(2, 3, 0, 0) /* ALL */ | ||
| 339 | #define OP_MFX_MPEG2_QM_STATE OP_MFX(2, 3, 0, 1) /* ALL */ | ||
| 340 | #define OP_MFD_MPEG2_BSD_OBJECT OP_MFX(2, 3, 1, 8) /* ALL */ | ||
| 341 | #define OP_MFC_MPEG2_SLICEGROUP_STATE OP_MFX(2, 3, 2, 3) /* ALL */ | ||
| 342 | #define OP_MFC_MPEG2_PAK_OBJECT OP_MFX(2, 3, 2, 9) /* ALL */ | ||
| 343 | |||
| 344 | #define OP_MFX_2_6_0_0 OP_MFX(2, 6, 0, 0) /* IVB+ */ | ||
| 345 | #define OP_MFX_2_6_0_8 OP_MFX(2, 6, 0, 8) /* IVB+ */ | ||
| 346 | #define OP_MFX_2_6_0_9 OP_MFX(2, 6, 0, 9) /* IVB+ */ | ||
| 347 | |||
| 348 | #define OP_MFX_JPEG_PIC_STATE OP_MFX(2, 7, 0, 0) | ||
| 349 | #define OP_MFX_JPEG_HUFF_TABLE_STATE OP_MFX(2, 7, 0, 2) | ||
| 350 | #define OP_MFD_JPEG_BSD_OBJECT OP_MFX(2, 7, 1, 8) | ||
| 351 | |||
| 352 | #define OP_VEB(pipeline, op, sub_opa, sub_opb) \ | ||
| 353 | (3 << 13 | \ | ||
| 354 | (pipeline) << 11 | \ | ||
| 355 | (op) << 8 | \ | ||
| 356 | (sub_opa) << 5 | \ | ||
| 357 | (sub_opb)) | ||
| 358 | |||
| 359 | #define OP_VEB_SURFACE_STATE OP_VEB(2, 4, 0, 0) | ||
| 360 | #define OP_VEB_STATE OP_VEB(2, 4, 0, 2) | ||
| 361 | #define OP_VEB_DNDI_IECP_STATE OP_VEB(2, 4, 0, 3) | ||
| 362 | |||
| 363 | struct parser_exec_state; | ||
| 364 | |||
| 365 | typedef int (*parser_cmd_handler)(struct parser_exec_state *s); | ||
| 366 | |||
| 367 | #define GVT_CMD_HASH_BITS 7 | ||
| 368 | |||
| 369 | /* which DWords need address fix */ | ||
| 370 | #define ADDR_FIX_1(x1) (1 << (x1)) | ||
| 371 | #define ADDR_FIX_2(x1, x2) (ADDR_FIX_1(x1) | ADDR_FIX_1(x2)) | ||
| 372 | #define ADDR_FIX_3(x1, x2, x3) (ADDR_FIX_1(x1) | ADDR_FIX_2(x2, x3)) | ||
| 373 | #define ADDR_FIX_4(x1, x2, x3, x4) (ADDR_FIX_1(x1) | ADDR_FIX_3(x2, x3, x4)) | ||
| 374 | #define ADDR_FIX_5(x1, x2, x3, x4, x5) (ADDR_FIX_1(x1) | ADDR_FIX_4(x2, x3, x4, x5)) | ||
| 375 | |||
| 376 | struct cmd_info { | ||
| 377 | char *name; | ||
| 378 | u32 opcode; | ||
| 379 | |||
| 380 | #define F_LEN_MASK (1U<<0) | ||
| 381 | #define F_LEN_CONST 1U | ||
| 382 | #define F_LEN_VAR 0U | ||
| 383 | |||
| 384 | /* | ||
| 385 | * command has its own ip advance logic | ||
| 386 | * e.g. MI_BATCH_START, MI_BATCH_END | ||
| 387 | */ | ||
| 388 | #define F_IP_ADVANCE_CUSTOM (1<<1) | ||
| 389 | |||
| 390 | #define F_POST_HANDLE (1<<2) | ||
| 391 | u32 flag; | ||
| 392 | |||
| 393 | #define R_RCS (1 << RCS) | ||
| 394 | #define R_VCS1 (1 << VCS) | ||
| 395 | #define R_VCS2 (1 << VCS2) | ||
| 396 | #define R_VCS (R_VCS1 | R_VCS2) | ||
| 397 | #define R_BCS (1 << BCS) | ||
| 398 | #define R_VECS (1 << VECS) | ||
| 399 | #define R_ALL (R_RCS | R_VCS | R_BCS | R_VECS) | ||
| 400 | /* rings that support this cmd: BLT/RCS/VCS/VECS */ | ||
| 401 | uint16_t rings; | ||
| 402 | |||
| 403 | /* devices that support this cmd: SNB/IVB/HSW/... */ | ||
| 404 | uint16_t devices; | ||
| 405 | |||
| 406 | /* which DWords are address that need fix up. | ||
| 407 | * bit 0 means a 32-bit non address operand in command | ||
| 408 | * bit 1 means address operand, which could be 32-bit | ||
| 409 | * or 64-bit depending on different architectures.( | ||
| 410 | * defined by "gmadr_bytes_in_cmd" in intel_gvt. | ||
| 411 | * No matter the address length, each address only takes | ||
| 412 | * one bit in the bitmap. | ||
| 413 | */ | ||
| 414 | uint16_t addr_bitmap; | ||
| 415 | |||
| 416 | /* flag == F_LEN_CONST : command length | ||
| 417 | * flag == F_LEN_VAR : length bias bits | ||
| 418 | * Note: length is in DWord | ||
| 419 | */ | ||
| 420 | uint8_t len; | ||
| 421 | |||
| 422 | parser_cmd_handler handler; | ||
| 423 | }; | ||
| 424 | |||
| 425 | struct cmd_entry { | ||
| 426 | struct hlist_node hlist; | ||
| 427 | struct cmd_info *info; | ||
| 428 | }; | ||
| 429 | |||
| 430 | enum { | ||
| 431 | RING_BUFFER_INSTRUCTION, | ||
| 432 | BATCH_BUFFER_INSTRUCTION, | ||
| 433 | BATCH_BUFFER_2ND_LEVEL, | ||
| 434 | }; | ||
| 435 | |||
| 436 | enum { | ||
| 437 | GTT_BUFFER, | ||
| 438 | PPGTT_BUFFER | ||
| 439 | }; | ||
| 440 | |||
| 441 | struct parser_exec_state { | ||
| 442 | struct intel_vgpu *vgpu; | ||
| 443 | int ring_id; | ||
| 444 | |||
| 445 | int buf_type; | ||
| 446 | |||
| 447 | /* batch buffer address type */ | ||
| 448 | int buf_addr_type; | ||
| 449 | |||
| 450 | /* graphics memory address of ring buffer start */ | ||
| 451 | unsigned long ring_start; | ||
| 452 | unsigned long ring_size; | ||
| 453 | unsigned long ring_head; | ||
| 454 | unsigned long ring_tail; | ||
| 455 | |||
| 456 | /* instruction graphics memory address */ | ||
| 457 | unsigned long ip_gma; | ||
| 458 | |||
| 459 | /* mapped va of the instr_gma */ | ||
| 460 | void *ip_va; | ||
| 461 | void *rb_va; | ||
| 462 | |||
| 463 | void *ret_bb_va; | ||
| 464 | /* next instruction when return from batch buffer to ring buffer */ | ||
| 465 | unsigned long ret_ip_gma_ring; | ||
| 466 | |||
| 467 | /* next instruction when return from 2nd batch buffer to batch buffer */ | ||
| 468 | unsigned long ret_ip_gma_bb; | ||
| 469 | |||
| 470 | /* batch buffer address type (GTT or PPGTT) | ||
| 471 | * used when ret from 2nd level batch buffer | ||
| 472 | */ | ||
| 473 | int saved_buf_addr_type; | ||
| 474 | |||
| 475 | struct cmd_info *info; | ||
| 476 | |||
| 477 | struct intel_vgpu_workload *workload; | ||
| 478 | }; | ||
| 479 | |||
| 480 | #define gmadr_dw_number(s) \ | ||
| 481 | (s->vgpu->gvt->device_info.gmadr_bytes_in_cmd >> 2) | ||
| 482 | |||
| 483 | static unsigned long bypass_scan_mask = 0; | ||
| 484 | static bool bypass_batch_buffer_scan = true; | ||
| 485 | |||
| 486 | /* ring ALL, type = 0 */ | ||
| 487 | static struct sub_op_bits sub_op_mi[] = { | ||
| 488 | {31, 29}, | ||
| 489 | {28, 23}, | ||
| 490 | }; | ||
| 491 | |||
| 492 | static struct decode_info decode_info_mi = { | ||
| 493 | "MI", | ||
| 494 | OP_LEN_MI, | ||
| 495 | ARRAY_SIZE(sub_op_mi), | ||
| 496 | sub_op_mi, | ||
| 497 | }; | ||
| 498 | |||
| 499 | /* ring RCS, command type 2 */ | ||
| 500 | static struct sub_op_bits sub_op_2d[] = { | ||
| 501 | {31, 29}, | ||
| 502 | {28, 22}, | ||
| 503 | }; | ||
| 504 | |||
| 505 | static struct decode_info decode_info_2d = { | ||
| 506 | "2D", | ||
| 507 | OP_LEN_2D, | ||
| 508 | ARRAY_SIZE(sub_op_2d), | ||
| 509 | sub_op_2d, | ||
| 510 | }; | ||
| 511 | |||
| 512 | /* ring RCS, command type 3 */ | ||
| 513 | static struct sub_op_bits sub_op_3d_media[] = { | ||
| 514 | {31, 29}, | ||
| 515 | {28, 27}, | ||
| 516 | {26, 24}, | ||
| 517 | {23, 16}, | ||
| 518 | }; | ||
| 519 | |||
| 520 | static struct decode_info decode_info_3d_media = { | ||
| 521 | "3D_Media", | ||
| 522 | OP_LEN_3D_MEDIA, | ||
| 523 | ARRAY_SIZE(sub_op_3d_media), | ||
| 524 | sub_op_3d_media, | ||
| 525 | }; | ||
| 526 | |||
| 527 | /* ring VCS, command type 3 */ | ||
| 528 | static struct sub_op_bits sub_op_mfx_vc[] = { | ||
| 529 | {31, 29}, | ||
| 530 | {28, 27}, | ||
| 531 | {26, 24}, | ||
| 532 | {23, 21}, | ||
| 533 | {20, 16}, | ||
| 534 | }; | ||
| 535 | |||
| 536 | static struct decode_info decode_info_mfx_vc = { | ||
| 537 | "MFX_VC", | ||
| 538 | OP_LEN_MFX_VC, | ||
| 539 | ARRAY_SIZE(sub_op_mfx_vc), | ||
| 540 | sub_op_mfx_vc, | ||
| 541 | }; | ||
| 542 | |||
| 543 | /* ring VECS, command type 3 */ | ||
| 544 | static struct sub_op_bits sub_op_vebox[] = { | ||
| 545 | {31, 29}, | ||
| 546 | {28, 27}, | ||
| 547 | {26, 24}, | ||
| 548 | {23, 21}, | ||
| 549 | {20, 16}, | ||
| 550 | }; | ||
| 551 | |||
| 552 | static struct decode_info decode_info_vebox = { | ||
| 553 | "VEBOX", | ||
| 554 | OP_LEN_VEBOX, | ||
| 555 | ARRAY_SIZE(sub_op_vebox), | ||
| 556 | sub_op_vebox, | ||
| 557 | }; | ||
| 558 | |||
| 559 | static struct decode_info *ring_decode_info[I915_NUM_ENGINES][8] = { | ||
| 560 | [RCS] = { | ||
| 561 | &decode_info_mi, | ||
| 562 | NULL, | ||
| 563 | NULL, | ||
| 564 | &decode_info_3d_media, | ||
| 565 | NULL, | ||
| 566 | NULL, | ||
| 567 | NULL, | ||
| 568 | NULL, | ||
| 569 | }, | ||
| 570 | |||
| 571 | [VCS] = { | ||
| 572 | &decode_info_mi, | ||
| 573 | NULL, | ||
| 574 | NULL, | ||
| 575 | &decode_info_mfx_vc, | ||
| 576 | NULL, | ||
| 577 | NULL, | ||
| 578 | NULL, | ||
| 579 | NULL, | ||
| 580 | }, | ||
| 581 | |||
| 582 | [BCS] = { | ||
| 583 | &decode_info_mi, | ||
| 584 | NULL, | ||
| 585 | &decode_info_2d, | ||
| 586 | NULL, | ||
| 587 | NULL, | ||
| 588 | NULL, | ||
| 589 | NULL, | ||
| 590 | NULL, | ||
| 591 | }, | ||
| 592 | |||
| 593 | [VECS] = { | ||
| 594 | &decode_info_mi, | ||
| 595 | NULL, | ||
| 596 | NULL, | ||
| 597 | &decode_info_vebox, | ||
| 598 | NULL, | ||
| 599 | NULL, | ||
| 600 | NULL, | ||
| 601 | NULL, | ||
| 602 | }, | ||
| 603 | |||
| 604 | [VCS2] = { | ||
| 605 | &decode_info_mi, | ||
| 606 | NULL, | ||
| 607 | NULL, | ||
| 608 | &decode_info_mfx_vc, | ||
| 609 | NULL, | ||
| 610 | NULL, | ||
| 611 | NULL, | ||
| 612 | NULL, | ||
| 613 | }, | ||
| 614 | }; | ||
| 615 | |||
| 616 | static inline u32 get_opcode(u32 cmd, int ring_id) | ||
| 617 | { | ||
| 618 | struct decode_info *d_info; | ||
| 619 | |||
| 620 | if (ring_id >= I915_NUM_ENGINES) | ||
| 621 | return INVALID_OP; | ||
| 622 | |||
| 623 | d_info = ring_decode_info[ring_id][CMD_TYPE(cmd)]; | ||
| 624 | if (d_info == NULL) | ||
| 625 | return INVALID_OP; | ||
| 626 | |||
| 627 | return cmd >> (32 - d_info->op_len); | ||
| 628 | } | ||
| 629 | |||
| 630 | static inline struct cmd_info *find_cmd_entry(struct intel_gvt *gvt, | ||
| 631 | unsigned int opcode, int ring_id) | ||
| 632 | { | ||
| 633 | struct cmd_entry *e; | ||
| 634 | |||
| 635 | hash_for_each_possible(gvt->cmd_table, e, hlist, opcode) { | ||
| 636 | if ((opcode == e->info->opcode) && | ||
| 637 | (e->info->rings & (1 << ring_id))) | ||
| 638 | return e->info; | ||
| 639 | } | ||
| 640 | return NULL; | ||
| 641 | } | ||
| 642 | |||
| 643 | static inline struct cmd_info *get_cmd_info(struct intel_gvt *gvt, | ||
| 644 | u32 cmd, int ring_id) | ||
| 645 | { | ||
| 646 | u32 opcode; | ||
| 647 | |||
| 648 | opcode = get_opcode(cmd, ring_id); | ||
| 649 | if (opcode == INVALID_OP) | ||
| 650 | return NULL; | ||
| 651 | |||
| 652 | return find_cmd_entry(gvt, opcode, ring_id); | ||
| 653 | } | ||
| 654 | |||
| 655 | static inline u32 sub_op_val(u32 cmd, u32 hi, u32 low) | ||
| 656 | { | ||
| 657 | return (cmd >> low) & ((1U << (hi - low + 1)) - 1); | ||
| 658 | } | ||
| 659 | |||
| 660 | static inline void print_opcode(u32 cmd, int ring_id) | ||
| 661 | { | ||
| 662 | struct decode_info *d_info; | ||
| 663 | int i; | ||
| 664 | |||
| 665 | if (ring_id >= I915_NUM_ENGINES) | ||
| 666 | return; | ||
| 667 | |||
| 668 | d_info = ring_decode_info[ring_id][CMD_TYPE(cmd)]; | ||
| 669 | if (d_info == NULL) | ||
| 670 | return; | ||
| 671 | |||
| 672 | gvt_err("opcode=0x%x %s sub_ops:", | ||
| 673 | cmd >> (32 - d_info->op_len), d_info->name); | ||
| 674 | |||
| 675 | for (i = 0; i < d_info->nr_sub_op; i++) | ||
| 676 | pr_err("0x%x ", sub_op_val(cmd, d_info->sub_op[i].hi, | ||
| 677 | d_info->sub_op[i].low)); | ||
| 678 | |||
| 679 | pr_err("\n"); | ||
| 680 | } | ||
| 681 | |||
| 682 | static inline u32 *cmd_ptr(struct parser_exec_state *s, int index) | ||
| 683 | { | ||
| 684 | return s->ip_va + (index << 2); | ||
| 685 | } | ||
| 686 | |||
| 687 | static inline u32 cmd_val(struct parser_exec_state *s, int index) | ||
| 688 | { | ||
| 689 | return *cmd_ptr(s, index); | ||
| 690 | } | ||
| 691 | |||
| 692 | static void parser_exec_state_dump(struct parser_exec_state *s) | ||
| 693 | { | ||
| 694 | int cnt = 0; | ||
| 695 | int i; | ||
| 696 | |||
| 697 | gvt_err(" vgpu%d RING%d: ring_start(%08lx) ring_end(%08lx)" | ||
| 698 | " ring_head(%08lx) ring_tail(%08lx)\n", s->vgpu->id, | ||
| 699 | s->ring_id, s->ring_start, s->ring_start + s->ring_size, | ||
| 700 | s->ring_head, s->ring_tail); | ||
| 701 | |||
| 702 | gvt_err(" %s %s ip_gma(%08lx) ", | ||
| 703 | s->buf_type == RING_BUFFER_INSTRUCTION ? | ||
| 704 | "RING_BUFFER" : "BATCH_BUFFER", | ||
| 705 | s->buf_addr_type == GTT_BUFFER ? | ||
| 706 | "GTT" : "PPGTT", s->ip_gma); | ||
| 707 | |||
| 708 | if (s->ip_va == NULL) { | ||
| 709 | gvt_err(" ip_va(NULL)"); | ||
| 710 | return; | ||
| 711 | } | ||
| 712 | |||
| 713 | gvt_err(" ip_va=%p: %08x %08x %08x %08x\n", | ||
| 714 | s->ip_va, cmd_val(s, 0), cmd_val(s, 1), | ||
| 715 | cmd_val(s, 2), cmd_val(s, 3)); | ||
| 716 | |||
| 717 | print_opcode(cmd_val(s, 0), s->ring_id); | ||
| 718 | |||
| 719 | /* print the whole page to trace */ | ||
| 720 | pr_err(" ip_va=%p: %08x %08x %08x %08x\n", | ||
| 721 | s->ip_va, cmd_val(s, 0), cmd_val(s, 1), | ||
| 722 | cmd_val(s, 2), cmd_val(s, 3)); | ||
| 723 | |||
| 724 | s->ip_va = (u32 *)((((u64)s->ip_va) >> 12) << 12); | ||
| 725 | |||
| 726 | while (cnt < 1024) { | ||
| 727 | pr_err("ip_va=%p: ", s->ip_va); | ||
| 728 | for (i = 0; i < 8; i++) | ||
| 729 | pr_err("%08x ", cmd_val(s, i)); | ||
| 730 | pr_err("\n"); | ||
| 731 | |||
| 732 | s->ip_va += 8 * sizeof(u32); | ||
| 733 | cnt += 8; | ||
| 734 | } | ||
| 735 | } | ||
| 736 | |||
| 737 | static inline void update_ip_va(struct parser_exec_state *s) | ||
| 738 | { | ||
| 739 | unsigned long len = 0; | ||
| 740 | |||
| 741 | if (WARN_ON(s->ring_head == s->ring_tail)) | ||
| 742 | return; | ||
| 743 | |||
| 744 | if (s->buf_type == RING_BUFFER_INSTRUCTION) { | ||
| 745 | unsigned long ring_top = s->ring_start + s->ring_size; | ||
| 746 | |||
| 747 | if (s->ring_head > s->ring_tail) { | ||
| 748 | if (s->ip_gma >= s->ring_head && s->ip_gma < ring_top) | ||
| 749 | len = (s->ip_gma - s->ring_head); | ||
| 750 | else if (s->ip_gma >= s->ring_start && | ||
| 751 | s->ip_gma <= s->ring_tail) | ||
| 752 | len = (ring_top - s->ring_head) + | ||
| 753 | (s->ip_gma - s->ring_start); | ||
| 754 | } else | ||
| 755 | len = (s->ip_gma - s->ring_head); | ||
| 756 | |||
| 757 | s->ip_va = s->rb_va + len; | ||
| 758 | } else {/* shadow batch buffer */ | ||
| 759 | s->ip_va = s->ret_bb_va; | ||
| 760 | } | ||
| 761 | } | ||
| 762 | |||
| 763 | static inline int ip_gma_set(struct parser_exec_state *s, | ||
| 764 | unsigned long ip_gma) | ||
| 765 | { | ||
| 766 | WARN_ON(!IS_ALIGNED(ip_gma, 4)); | ||
| 767 | |||
| 768 | s->ip_gma = ip_gma; | ||
| 769 | update_ip_va(s); | ||
| 770 | return 0; | ||
| 771 | } | ||
| 772 | |||
| 773 | static inline int ip_gma_advance(struct parser_exec_state *s, | ||
| 774 | unsigned int dw_len) | ||
| 775 | { | ||
| 776 | s->ip_gma += (dw_len << 2); | ||
| 777 | |||
| 778 | if (s->buf_type == RING_BUFFER_INSTRUCTION) { | ||
| 779 | if (s->ip_gma >= s->ring_start + s->ring_size) | ||
| 780 | s->ip_gma -= s->ring_size; | ||
| 781 | update_ip_va(s); | ||
| 782 | } else { | ||
| 783 | s->ip_va += (dw_len << 2); | ||
| 784 | } | ||
| 785 | |||
| 786 | return 0; | ||
| 787 | } | ||
| 788 | |||
| 789 | static inline int get_cmd_length(struct cmd_info *info, u32 cmd) | ||
| 790 | { | ||
| 791 | if ((info->flag & F_LEN_MASK) == F_LEN_CONST) | ||
| 792 | return info->len; | ||
| 793 | else | ||
| 794 | return (cmd & ((1U << info->len) - 1)) + 2; | ||
| 795 | return 0; | ||
| 796 | } | ||
| 797 | |||
| 798 | static inline int cmd_length(struct parser_exec_state *s) | ||
| 799 | { | ||
| 800 | return get_cmd_length(s->info, cmd_val(s, 0)); | ||
| 801 | } | ||
| 802 | |||
| 803 | /* do not remove this, some platform may need clflush here */ | ||
| 804 | #define patch_value(s, addr, val) do { \ | ||
| 805 | *addr = val; \ | ||
| 806 | } while (0) | ||
| 807 | |||
| 808 | static bool is_shadowed_mmio(unsigned int offset) | ||
| 809 | { | ||
| 810 | bool ret = false; | ||
| 811 | |||
| 812 | if ((offset == 0x2168) || /*BB current head register UDW */ | ||
| 813 | (offset == 0x2140) || /*BB current header register */ | ||
| 814 | (offset == 0x211c) || /*second BB header register UDW */ | ||
| 815 | (offset == 0x2114)) { /*second BB header register UDW */ | ||
| 816 | ret = true; | ||
| 817 | } | ||
| 818 | return ret; | ||
| 819 | } | ||
| 820 | |||
| 821 | static int cmd_reg_handler(struct parser_exec_state *s, | ||
| 822 | unsigned int offset, unsigned int index, char *cmd) | ||
| 823 | { | ||
| 824 | struct intel_vgpu *vgpu = s->vgpu; | ||
| 825 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 826 | |||
| 827 | if (offset + 4 > gvt->device_info.mmio_size) { | ||
| 828 | gvt_err("%s access to (%x) outside of MMIO range\n", | ||
| 829 | cmd, offset); | ||
| 830 | return -EINVAL; | ||
| 831 | } | ||
| 832 | |||
| 833 | if (!intel_gvt_mmio_is_cmd_access(gvt, offset)) { | ||
| 834 | gvt_err("vgpu%d: %s access to non-render register (%x)\n", | ||
| 835 | s->vgpu->id, cmd, offset); | ||
| 836 | return 0; | ||
| 837 | } | ||
| 838 | |||
| 839 | if (is_shadowed_mmio(offset)) { | ||
| 840 | gvt_err("vgpu%d: found access of shadowed MMIO %x\n", | ||
| 841 | s->vgpu->id, offset); | ||
| 842 | return 0; | ||
| 843 | } | ||
| 844 | |||
| 845 | if (offset == i915_mmio_reg_offset(DERRMR) || | ||
| 846 | offset == i915_mmio_reg_offset(FORCEWAKE_MT)) { | ||
| 847 | /* Writing to HW VGT_PVINFO_PAGE offset will be discarded */ | ||
| 848 | patch_value(s, cmd_ptr(s, index), VGT_PVINFO_PAGE); | ||
| 849 | } | ||
| 850 | |||
| 851 | /* TODO: Update the global mask if this MMIO is a masked-MMIO */ | ||
| 852 | intel_gvt_mmio_set_cmd_accessed(gvt, offset); | ||
| 853 | return 0; | ||
| 854 | } | ||
| 855 | |||
| 856 | #define cmd_reg(s, i) \ | ||
| 857 | (cmd_val(s, i) & GENMASK(22, 2)) | ||
| 858 | |||
| 859 | #define cmd_reg_inhibit(s, i) \ | ||
| 860 | (cmd_val(s, i) & GENMASK(22, 18)) | ||
| 861 | |||
| 862 | #define cmd_gma(s, i) \ | ||
| 863 | (cmd_val(s, i) & GENMASK(31, 2)) | ||
| 864 | |||
| 865 | #define cmd_gma_hi(s, i) \ | ||
| 866 | (cmd_val(s, i) & GENMASK(15, 0)) | ||
| 867 | |||
| 868 | static int cmd_handler_lri(struct parser_exec_state *s) | ||
| 869 | { | ||
| 870 | int i, ret = 0; | ||
| 871 | int cmd_len = cmd_length(s); | ||
| 872 | struct intel_gvt *gvt = s->vgpu->gvt; | ||
| 873 | |||
| 874 | for (i = 1; i < cmd_len; i += 2) { | ||
| 875 | if (IS_BROADWELL(gvt->dev_priv) && | ||
| 876 | (s->ring_id != RCS)) { | ||
| 877 | if (s->ring_id == BCS && | ||
| 878 | cmd_reg(s, i) == | ||
| 879 | i915_mmio_reg_offset(DERRMR)) | ||
| 880 | ret |= 0; | ||
| 881 | else | ||
| 882 | ret |= (cmd_reg_inhibit(s, i)) ? -EINVAL : 0; | ||
| 883 | } | ||
| 884 | if (ret) | ||
| 885 | break; | ||
| 886 | ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lri"); | ||
| 887 | } | ||
| 888 | return ret; | ||
| 889 | } | ||
| 890 | |||
| 891 | static int cmd_handler_lrr(struct parser_exec_state *s) | ||
| 892 | { | ||
| 893 | int i, ret = 0; | ||
| 894 | int cmd_len = cmd_length(s); | ||
| 895 | |||
| 896 | for (i = 1; i < cmd_len; i += 2) { | ||
| 897 | if (IS_BROADWELL(s->vgpu->gvt->dev_priv)) | ||
| 898 | ret |= ((cmd_reg_inhibit(s, i) || | ||
| 899 | (cmd_reg_inhibit(s, i + 1)))) ? | ||
| 900 | -EINVAL : 0; | ||
| 901 | if (ret) | ||
| 902 | break; | ||
| 903 | ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lrr-src"); | ||
| 904 | ret |= cmd_reg_handler(s, cmd_reg(s, i + 1), i, "lrr-dst"); | ||
| 905 | } | ||
| 906 | return ret; | ||
| 907 | } | ||
| 908 | |||
| 909 | static inline int cmd_address_audit(struct parser_exec_state *s, | ||
| 910 | unsigned long guest_gma, int op_size, bool index_mode); | ||
| 911 | |||
| 912 | static int cmd_handler_lrm(struct parser_exec_state *s) | ||
| 913 | { | ||
| 914 | struct intel_gvt *gvt = s->vgpu->gvt; | ||
| 915 | int gmadr_bytes = gvt->device_info.gmadr_bytes_in_cmd; | ||
| 916 | unsigned long gma; | ||
| 917 | int i, ret = 0; | ||
| 918 | int cmd_len = cmd_length(s); | ||
| 919 | |||
| 920 | for (i = 1; i < cmd_len;) { | ||
| 921 | if (IS_BROADWELL(gvt->dev_priv)) | ||
| 922 | ret |= (cmd_reg_inhibit(s, i)) ? -EINVAL : 0; | ||
| 923 | if (ret) | ||
| 924 | break; | ||
| 925 | ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "lrm"); | ||
| 926 | if (cmd_val(s, 0) & (1 << 22)) { | ||
| 927 | gma = cmd_gma(s, i + 1); | ||
| 928 | if (gmadr_bytes == 8) | ||
| 929 | gma |= (cmd_gma_hi(s, i + 2)) << 32; | ||
| 930 | ret |= cmd_address_audit(s, gma, sizeof(u32), false); | ||
| 931 | } | ||
| 932 | i += gmadr_dw_number(s) + 1; | ||
| 933 | } | ||
| 934 | return ret; | ||
| 935 | } | ||
| 936 | |||
| 937 | static int cmd_handler_srm(struct parser_exec_state *s) | ||
| 938 | { | ||
| 939 | int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; | ||
| 940 | unsigned long gma; | ||
| 941 | int i, ret = 0; | ||
| 942 | int cmd_len = cmd_length(s); | ||
| 943 | |||
| 944 | for (i = 1; i < cmd_len;) { | ||
| 945 | ret |= cmd_reg_handler(s, cmd_reg(s, i), i, "srm"); | ||
| 946 | if (cmd_val(s, 0) & (1 << 22)) { | ||
| 947 | gma = cmd_gma(s, i + 1); | ||
| 948 | if (gmadr_bytes == 8) | ||
| 949 | gma |= (cmd_gma_hi(s, i + 2)) << 32; | ||
| 950 | ret |= cmd_address_audit(s, gma, sizeof(u32), false); | ||
| 951 | } | ||
| 952 | i += gmadr_dw_number(s) + 1; | ||
| 953 | } | ||
| 954 | return ret; | ||
| 955 | } | ||
| 956 | |||
| 957 | struct cmd_interrupt_event { | ||
| 958 | int pipe_control_notify; | ||
| 959 | int mi_flush_dw; | ||
| 960 | int mi_user_interrupt; | ||
| 961 | }; | ||
| 962 | |||
| 963 | static struct cmd_interrupt_event cmd_interrupt_events[] = { | ||
| 964 | [RCS] = { | ||
| 965 | .pipe_control_notify = RCS_PIPE_CONTROL, | ||
| 966 | .mi_flush_dw = INTEL_GVT_EVENT_RESERVED, | ||
| 967 | .mi_user_interrupt = RCS_MI_USER_INTERRUPT, | ||
| 968 | }, | ||
| 969 | [BCS] = { | ||
| 970 | .pipe_control_notify = INTEL_GVT_EVENT_RESERVED, | ||
| 971 | .mi_flush_dw = BCS_MI_FLUSH_DW, | ||
| 972 | .mi_user_interrupt = BCS_MI_USER_INTERRUPT, | ||
| 973 | }, | ||
| 974 | [VCS] = { | ||
| 975 | .pipe_control_notify = INTEL_GVT_EVENT_RESERVED, | ||
| 976 | .mi_flush_dw = VCS_MI_FLUSH_DW, | ||
| 977 | .mi_user_interrupt = VCS_MI_USER_INTERRUPT, | ||
| 978 | }, | ||
| 979 | [VCS2] = { | ||
| 980 | .pipe_control_notify = INTEL_GVT_EVENT_RESERVED, | ||
| 981 | .mi_flush_dw = VCS2_MI_FLUSH_DW, | ||
| 982 | .mi_user_interrupt = VCS2_MI_USER_INTERRUPT, | ||
| 983 | }, | ||
| 984 | [VECS] = { | ||
| 985 | .pipe_control_notify = INTEL_GVT_EVENT_RESERVED, | ||
| 986 | .mi_flush_dw = VECS_MI_FLUSH_DW, | ||
| 987 | .mi_user_interrupt = VECS_MI_USER_INTERRUPT, | ||
| 988 | }, | ||
| 989 | }; | ||
| 990 | |||
| 991 | static int cmd_handler_pipe_control(struct parser_exec_state *s) | ||
| 992 | { | ||
| 993 | int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; | ||
| 994 | unsigned long gma; | ||
| 995 | bool index_mode = false; | ||
| 996 | unsigned int post_sync; | ||
| 997 | int ret = 0; | ||
| 998 | |||
| 999 | post_sync = (cmd_val(s, 1) & PIPE_CONTROL_POST_SYNC_OP_MASK) >> 14; | ||
| 1000 | |||
| 1001 | /* LRI post sync */ | ||
| 1002 | if (cmd_val(s, 1) & PIPE_CONTROL_MMIO_WRITE) | ||
| 1003 | ret = cmd_reg_handler(s, cmd_reg(s, 2), 1, "pipe_ctrl"); | ||
| 1004 | /* post sync */ | ||
| 1005 | else if (post_sync) { | ||
| 1006 | if (post_sync == 2) | ||
| 1007 | ret = cmd_reg_handler(s, 0x2350, 1, "pipe_ctrl"); | ||
| 1008 | else if (post_sync == 3) | ||
| 1009 | ret = cmd_reg_handler(s, 0x2358, 1, "pipe_ctrl"); | ||
| 1010 | else if (post_sync == 1) { | ||
| 1011 | /* check ggtt*/ | ||
| 1012 | if ((cmd_val(s, 2) & (1 << 2))) { | ||
| 1013 | gma = cmd_val(s, 2) & GENMASK(31, 3); | ||
| 1014 | if (gmadr_bytes == 8) | ||
| 1015 | gma |= (cmd_gma_hi(s, 3)) << 32; | ||
| 1016 | /* Store Data Index */ | ||
| 1017 | if (cmd_val(s, 1) & (1 << 21)) | ||
| 1018 | index_mode = true; | ||
| 1019 | ret |= cmd_address_audit(s, gma, sizeof(u64), | ||
| 1020 | index_mode); | ||
| 1021 | } | ||
| 1022 | } | ||
| 1023 | } | ||
| 1024 | |||
| 1025 | if (ret) | ||
| 1026 | return ret; | ||
| 1027 | |||
| 1028 | if (cmd_val(s, 1) & PIPE_CONTROL_NOTIFY) | ||
| 1029 | set_bit(cmd_interrupt_events[s->ring_id].pipe_control_notify, | ||
| 1030 | s->workload->pending_events); | ||
| 1031 | return 0; | ||
| 1032 | } | ||
| 1033 | |||
| 1034 | static int cmd_handler_mi_user_interrupt(struct parser_exec_state *s) | ||
| 1035 | { | ||
| 1036 | set_bit(cmd_interrupt_events[s->ring_id].mi_user_interrupt, | ||
| 1037 | s->workload->pending_events); | ||
| 1038 | return 0; | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | static int cmd_advance_default(struct parser_exec_state *s) | ||
| 1042 | { | ||
| 1043 | return ip_gma_advance(s, cmd_length(s)); | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | static int cmd_handler_mi_batch_buffer_end(struct parser_exec_state *s) | ||
| 1047 | { | ||
| 1048 | int ret; | ||
| 1049 | |||
| 1050 | if (s->buf_type == BATCH_BUFFER_2ND_LEVEL) { | ||
| 1051 | s->buf_type = BATCH_BUFFER_INSTRUCTION; | ||
| 1052 | ret = ip_gma_set(s, s->ret_ip_gma_bb); | ||
| 1053 | s->buf_addr_type = s->saved_buf_addr_type; | ||
| 1054 | } else { | ||
| 1055 | s->buf_type = RING_BUFFER_INSTRUCTION; | ||
| 1056 | s->buf_addr_type = GTT_BUFFER; | ||
| 1057 | if (s->ret_ip_gma_ring >= s->ring_start + s->ring_size) | ||
| 1058 | s->ret_ip_gma_ring -= s->ring_size; | ||
| 1059 | ret = ip_gma_set(s, s->ret_ip_gma_ring); | ||
| 1060 | } | ||
| 1061 | return ret; | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | struct mi_display_flip_command_info { | ||
| 1065 | int pipe; | ||
| 1066 | int plane; | ||
| 1067 | int event; | ||
| 1068 | i915_reg_t stride_reg; | ||
| 1069 | i915_reg_t ctrl_reg; | ||
| 1070 | i915_reg_t surf_reg; | ||
| 1071 | u64 stride_val; | ||
| 1072 | u64 tile_val; | ||
| 1073 | u64 surf_val; | ||
| 1074 | bool async_flip; | ||
| 1075 | }; | ||
| 1076 | |||
| 1077 | struct plane_code_mapping { | ||
| 1078 | int pipe; | ||
| 1079 | int plane; | ||
| 1080 | int event; | ||
| 1081 | }; | ||
| 1082 | |||
| 1083 | static int gen8_decode_mi_display_flip(struct parser_exec_state *s, | ||
| 1084 | struct mi_display_flip_command_info *info) | ||
| 1085 | { | ||
| 1086 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; | ||
| 1087 | struct plane_code_mapping gen8_plane_code[] = { | ||
| 1088 | [0] = {PIPE_A, PLANE_A, PRIMARY_A_FLIP_DONE}, | ||
| 1089 | [1] = {PIPE_B, PLANE_A, PRIMARY_B_FLIP_DONE}, | ||
| 1090 | [2] = {PIPE_A, PLANE_B, SPRITE_A_FLIP_DONE}, | ||
| 1091 | [3] = {PIPE_B, PLANE_B, SPRITE_B_FLIP_DONE}, | ||
| 1092 | [4] = {PIPE_C, PLANE_A, PRIMARY_C_FLIP_DONE}, | ||
| 1093 | [5] = {PIPE_C, PLANE_B, SPRITE_C_FLIP_DONE}, | ||
| 1094 | }; | ||
| 1095 | u32 dword0, dword1, dword2; | ||
| 1096 | u32 v; | ||
| 1097 | |||
| 1098 | dword0 = cmd_val(s, 0); | ||
| 1099 | dword1 = cmd_val(s, 1); | ||
| 1100 | dword2 = cmd_val(s, 2); | ||
| 1101 | |||
| 1102 | v = (dword0 & GENMASK(21, 19)) >> 19; | ||
| 1103 | if (WARN_ON(v >= ARRAY_SIZE(gen8_plane_code))) | ||
| 1104 | return -EINVAL; | ||
| 1105 | |||
| 1106 | info->pipe = gen8_plane_code[v].pipe; | ||
| 1107 | info->plane = gen8_plane_code[v].plane; | ||
| 1108 | info->event = gen8_plane_code[v].event; | ||
| 1109 | info->stride_val = (dword1 & GENMASK(15, 6)) >> 6; | ||
| 1110 | info->tile_val = (dword1 & 0x1); | ||
| 1111 | info->surf_val = (dword2 & GENMASK(31, 12)) >> 12; | ||
| 1112 | info->async_flip = ((dword2 & GENMASK(1, 0)) == 0x1); | ||
| 1113 | |||
| 1114 | if (info->plane == PLANE_A) { | ||
| 1115 | info->ctrl_reg = DSPCNTR(info->pipe); | ||
| 1116 | info->stride_reg = DSPSTRIDE(info->pipe); | ||
| 1117 | info->surf_reg = DSPSURF(info->pipe); | ||
| 1118 | } else if (info->plane == PLANE_B) { | ||
| 1119 | info->ctrl_reg = SPRCTL(info->pipe); | ||
| 1120 | info->stride_reg = SPRSTRIDE(info->pipe); | ||
| 1121 | info->surf_reg = SPRSURF(info->pipe); | ||
| 1122 | } else { | ||
| 1123 | WARN_ON(1); | ||
| 1124 | return -EINVAL; | ||
| 1125 | } | ||
| 1126 | return 0; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | static int skl_decode_mi_display_flip(struct parser_exec_state *s, | ||
| 1130 | struct mi_display_flip_command_info *info) | ||
| 1131 | { | ||
| 1132 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; | ||
| 1133 | u32 dword0 = cmd_val(s, 0); | ||
| 1134 | u32 dword1 = cmd_val(s, 1); | ||
| 1135 | u32 dword2 = cmd_val(s, 2); | ||
| 1136 | u32 plane = (dword0 & GENMASK(12, 8)) >> 8; | ||
| 1137 | |||
| 1138 | switch (plane) { | ||
| 1139 | case MI_DISPLAY_FLIP_SKL_PLANE_1_A: | ||
| 1140 | info->pipe = PIPE_A; | ||
| 1141 | info->event = PRIMARY_A_FLIP_DONE; | ||
| 1142 | break; | ||
| 1143 | case MI_DISPLAY_FLIP_SKL_PLANE_1_B: | ||
| 1144 | info->pipe = PIPE_B; | ||
| 1145 | info->event = PRIMARY_B_FLIP_DONE; | ||
| 1146 | break; | ||
| 1147 | case MI_DISPLAY_FLIP_SKL_PLANE_1_C: | ||
| 1148 | info->pipe = PIPE_B; | ||
| 1149 | info->event = PRIMARY_C_FLIP_DONE; | ||
| 1150 | break; | ||
| 1151 | default: | ||
| 1152 | gvt_err("unknown plane code %d\n", plane); | ||
| 1153 | return -EINVAL; | ||
| 1154 | } | ||
| 1155 | |||
| 1156 | info->pipe = PRIMARY_PLANE; | ||
| 1157 | info->stride_val = (dword1 & GENMASK(15, 6)) >> 6; | ||
| 1158 | info->tile_val = (dword1 & GENMASK(2, 0)); | ||
| 1159 | info->surf_val = (dword2 & GENMASK(31, 12)) >> 12; | ||
| 1160 | info->async_flip = ((dword2 & GENMASK(1, 0)) == 0x1); | ||
| 1161 | |||
| 1162 | info->ctrl_reg = DSPCNTR(info->pipe); | ||
| 1163 | info->stride_reg = DSPSTRIDE(info->pipe); | ||
| 1164 | info->surf_reg = DSPSURF(info->pipe); | ||
| 1165 | |||
| 1166 | return 0; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | static int gen8_check_mi_display_flip(struct parser_exec_state *s, | ||
| 1170 | struct mi_display_flip_command_info *info) | ||
| 1171 | { | ||
| 1172 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; | ||
| 1173 | u32 stride, tile; | ||
| 1174 | |||
| 1175 | if (!info->async_flip) | ||
| 1176 | return 0; | ||
| 1177 | |||
| 1178 | if (IS_SKYLAKE(dev_priv)) { | ||
| 1179 | stride = vgpu_vreg(s->vgpu, info->stride_reg) & GENMASK(9, 0); | ||
| 1180 | tile = (vgpu_vreg(s->vgpu, info->ctrl_reg) & | ||
| 1181 | GENMASK(12, 10)) >> 10; | ||
| 1182 | } else { | ||
| 1183 | stride = (vgpu_vreg(s->vgpu, info->stride_reg) & | ||
| 1184 | GENMASK(15, 6)) >> 6; | ||
| 1185 | tile = (vgpu_vreg(s->vgpu, info->ctrl_reg) & (1 << 10)) >> 10; | ||
| 1186 | } | ||
| 1187 | |||
| 1188 | if (stride != info->stride_val) | ||
| 1189 | gvt_dbg_cmd("cannot change stride during async flip\n"); | ||
| 1190 | |||
| 1191 | if (tile != info->tile_val) | ||
| 1192 | gvt_dbg_cmd("cannot change tile during async flip\n"); | ||
| 1193 | |||
| 1194 | return 0; | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | static int gen8_update_plane_mmio_from_mi_display_flip( | ||
| 1198 | struct parser_exec_state *s, | ||
| 1199 | struct mi_display_flip_command_info *info) | ||
| 1200 | { | ||
| 1201 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; | ||
| 1202 | struct intel_vgpu *vgpu = s->vgpu; | ||
| 1203 | |||
| 1204 | #define write_bits(reg, e, s, v) do { \ | ||
| 1205 | vgpu_vreg(vgpu, reg) &= ~GENMASK(e, s); \ | ||
| 1206 | vgpu_vreg(vgpu, reg) |= (v << s); \ | ||
| 1207 | } while (0) | ||
| 1208 | |||
| 1209 | write_bits(info->surf_reg, 31, 12, info->surf_val); | ||
| 1210 | if (IS_SKYLAKE(dev_priv)) | ||
| 1211 | write_bits(info->stride_reg, 9, 0, info->stride_val); | ||
| 1212 | else | ||
| 1213 | write_bits(info->stride_reg, 15, 6, info->stride_val); | ||
| 1214 | write_bits(info->ctrl_reg, IS_SKYLAKE(dev_priv) ? 12 : 10, | ||
| 1215 | 10, info->tile_val); | ||
| 1216 | |||
| 1217 | #undef write_bits | ||
| 1218 | |||
| 1219 | vgpu_vreg(vgpu, PIPE_FRMCOUNT_G4X(info->pipe))++; | ||
| 1220 | intel_vgpu_trigger_virtual_event(vgpu, info->event); | ||
| 1221 | return 0; | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | static int decode_mi_display_flip(struct parser_exec_state *s, | ||
| 1225 | struct mi_display_flip_command_info *info) | ||
| 1226 | { | ||
| 1227 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; | ||
| 1228 | |||
| 1229 | if (IS_BROADWELL(dev_priv)) | ||
| 1230 | return gen8_decode_mi_display_flip(s, info); | ||
| 1231 | if (IS_SKYLAKE(dev_priv)) | ||
| 1232 | return skl_decode_mi_display_flip(s, info); | ||
| 1233 | |||
| 1234 | return -ENODEV; | ||
| 1235 | } | ||
| 1236 | |||
| 1237 | static int check_mi_display_flip(struct parser_exec_state *s, | ||
| 1238 | struct mi_display_flip_command_info *info) | ||
| 1239 | { | ||
| 1240 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; | ||
| 1241 | |||
| 1242 | if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv)) | ||
| 1243 | return gen8_check_mi_display_flip(s, info); | ||
| 1244 | return -ENODEV; | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | static int update_plane_mmio_from_mi_display_flip( | ||
| 1248 | struct parser_exec_state *s, | ||
| 1249 | struct mi_display_flip_command_info *info) | ||
| 1250 | { | ||
| 1251 | struct drm_i915_private *dev_priv = s->vgpu->gvt->dev_priv; | ||
| 1252 | |||
| 1253 | if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv)) | ||
| 1254 | return gen8_update_plane_mmio_from_mi_display_flip(s, info); | ||
| 1255 | return -ENODEV; | ||
| 1256 | } | ||
| 1257 | |||
| 1258 | static int cmd_handler_mi_display_flip(struct parser_exec_state *s) | ||
| 1259 | { | ||
| 1260 | struct mi_display_flip_command_info info; | ||
| 1261 | int ret; | ||
| 1262 | int i; | ||
| 1263 | int len = cmd_length(s); | ||
| 1264 | |||
| 1265 | ret = decode_mi_display_flip(s, &info); | ||
| 1266 | if (ret) { | ||
| 1267 | gvt_err("fail to decode MI display flip command\n"); | ||
| 1268 | return ret; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | ret = check_mi_display_flip(s, &info); | ||
| 1272 | if (ret) { | ||
| 1273 | gvt_err("invalid MI display flip command\n"); | ||
| 1274 | return ret; | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | ret = update_plane_mmio_from_mi_display_flip(s, &info); | ||
| 1278 | if (ret) { | ||
| 1279 | gvt_err("fail to update plane mmio\n"); | ||
| 1280 | return ret; | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | for (i = 0; i < len; i++) | ||
| 1284 | patch_value(s, cmd_ptr(s, i), MI_NOOP); | ||
| 1285 | return 0; | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | static bool is_wait_for_flip_pending(u32 cmd) | ||
| 1289 | { | ||
| 1290 | return cmd & (MI_WAIT_FOR_PLANE_A_FLIP_PENDING | | ||
| 1291 | MI_WAIT_FOR_PLANE_B_FLIP_PENDING | | ||
| 1292 | MI_WAIT_FOR_PLANE_C_FLIP_PENDING | | ||
| 1293 | MI_WAIT_FOR_SPRITE_A_FLIP_PENDING | | ||
| 1294 | MI_WAIT_FOR_SPRITE_B_FLIP_PENDING | | ||
| 1295 | MI_WAIT_FOR_SPRITE_C_FLIP_PENDING); | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | static int cmd_handler_mi_wait_for_event(struct parser_exec_state *s) | ||
| 1299 | { | ||
| 1300 | u32 cmd = cmd_val(s, 0); | ||
| 1301 | |||
| 1302 | if (!is_wait_for_flip_pending(cmd)) | ||
| 1303 | return 0; | ||
| 1304 | |||
| 1305 | patch_value(s, cmd_ptr(s, 0), MI_NOOP); | ||
| 1306 | return 0; | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | static unsigned long get_gma_bb_from_cmd(struct parser_exec_state *s, int index) | ||
| 1310 | { | ||
| 1311 | unsigned long addr; | ||
| 1312 | unsigned long gma_high, gma_low; | ||
| 1313 | int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; | ||
| 1314 | |||
| 1315 | if (WARN_ON(gmadr_bytes != 4 && gmadr_bytes != 8)) | ||
| 1316 | return INTEL_GVT_INVALID_ADDR; | ||
| 1317 | |||
| 1318 | gma_low = cmd_val(s, index) & BATCH_BUFFER_ADDR_MASK; | ||
| 1319 | if (gmadr_bytes == 4) { | ||
| 1320 | addr = gma_low; | ||
| 1321 | } else { | ||
| 1322 | gma_high = cmd_val(s, index + 1) & BATCH_BUFFER_ADDR_HIGH_MASK; | ||
| 1323 | addr = (((unsigned long)gma_high) << 32) | gma_low; | ||
| 1324 | } | ||
| 1325 | return addr; | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | static inline int cmd_address_audit(struct parser_exec_state *s, | ||
| 1329 | unsigned long guest_gma, int op_size, bool index_mode) | ||
| 1330 | { | ||
| 1331 | struct intel_vgpu *vgpu = s->vgpu; | ||
| 1332 | u32 max_surface_size = vgpu->gvt->device_info.max_surface_size; | ||
| 1333 | int i; | ||
| 1334 | int ret; | ||
| 1335 | |||
| 1336 | if (op_size > max_surface_size) { | ||
| 1337 | gvt_err("command address audit fail name %s\n", s->info->name); | ||
| 1338 | return -EINVAL; | ||
| 1339 | } | ||
| 1340 | |||
| 1341 | if (index_mode) { | ||
| 1342 | if (guest_gma >= GTT_PAGE_SIZE / sizeof(u64)) { | ||
| 1343 | ret = -EINVAL; | ||
| 1344 | goto err; | ||
| 1345 | } | ||
| 1346 | } else if ((!vgpu_gmadr_is_valid(s->vgpu, guest_gma)) || | ||
| 1347 | (!vgpu_gmadr_is_valid(s->vgpu, | ||
| 1348 | guest_gma + op_size - 1))) { | ||
| 1349 | ret = -EINVAL; | ||
| 1350 | goto err; | ||
| 1351 | } | ||
| 1352 | return 0; | ||
| 1353 | err: | ||
| 1354 | gvt_err("cmd_parser: Malicious %s detected, addr=0x%lx, len=%d!\n", | ||
| 1355 | s->info->name, guest_gma, op_size); | ||
| 1356 | |||
| 1357 | pr_err("cmd dump: "); | ||
| 1358 | for (i = 0; i < cmd_length(s); i++) { | ||
| 1359 | if (!(i % 4)) | ||
| 1360 | pr_err("\n%08x ", cmd_val(s, i)); | ||
| 1361 | else | ||
| 1362 | pr_err("%08x ", cmd_val(s, i)); | ||
| 1363 | } | ||
| 1364 | pr_err("\nvgpu%d: aperture 0x%llx - 0x%llx, hidden 0x%llx - 0x%llx\n", | ||
| 1365 | vgpu->id, | ||
| 1366 | vgpu_aperture_gmadr_base(vgpu), | ||
| 1367 | vgpu_aperture_gmadr_end(vgpu), | ||
| 1368 | vgpu_hidden_gmadr_base(vgpu), | ||
| 1369 | vgpu_hidden_gmadr_end(vgpu)); | ||
| 1370 | return ret; | ||
| 1371 | } | ||
| 1372 | |||
| 1373 | static int cmd_handler_mi_store_data_imm(struct parser_exec_state *s) | ||
| 1374 | { | ||
| 1375 | int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; | ||
| 1376 | int op_size = (cmd_length(s) - 3) * sizeof(u32); | ||
| 1377 | int core_id = (cmd_val(s, 2) & (1 << 0)) ? 1 : 0; | ||
| 1378 | unsigned long gma, gma_low, gma_high; | ||
| 1379 | int ret = 0; | ||
| 1380 | |||
| 1381 | /* check ppggt */ | ||
| 1382 | if (!(cmd_val(s, 0) & (1 << 22))) | ||
| 1383 | return 0; | ||
| 1384 | |||
| 1385 | gma = cmd_val(s, 2) & GENMASK(31, 2); | ||
| 1386 | |||
| 1387 | if (gmadr_bytes == 8) { | ||
| 1388 | gma_low = cmd_val(s, 1) & GENMASK(31, 2); | ||
| 1389 | gma_high = cmd_val(s, 2) & GENMASK(15, 0); | ||
| 1390 | gma = (gma_high << 32) | gma_low; | ||
| 1391 | core_id = (cmd_val(s, 1) & (1 << 0)) ? 1 : 0; | ||
| 1392 | } | ||
| 1393 | ret = cmd_address_audit(s, gma + op_size * core_id, op_size, false); | ||
| 1394 | return ret; | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | static inline int unexpected_cmd(struct parser_exec_state *s) | ||
| 1398 | { | ||
| 1399 | gvt_err("vgpu%d: Unexpected %s in command buffer!\n", | ||
| 1400 | s->vgpu->id, s->info->name); | ||
| 1401 | return -EINVAL; | ||
| 1402 | } | ||
| 1403 | |||
| 1404 | static int cmd_handler_mi_semaphore_wait(struct parser_exec_state *s) | ||
| 1405 | { | ||
| 1406 | return unexpected_cmd(s); | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | static int cmd_handler_mi_report_perf_count(struct parser_exec_state *s) | ||
| 1410 | { | ||
| 1411 | return unexpected_cmd(s); | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | static int cmd_handler_mi_op_2e(struct parser_exec_state *s) | ||
| 1415 | { | ||
| 1416 | return unexpected_cmd(s); | ||
| 1417 | } | ||
| 1418 | |||
| 1419 | static int cmd_handler_mi_op_2f(struct parser_exec_state *s) | ||
| 1420 | { | ||
| 1421 | int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; | ||
| 1422 | int op_size = ((1 << (cmd_val(s, 0) & GENMASK(20, 19) >> 19)) * | ||
| 1423 | sizeof(u32)); | ||
| 1424 | unsigned long gma, gma_high; | ||
| 1425 | int ret = 0; | ||
| 1426 | |||
| 1427 | if (!(cmd_val(s, 0) & (1 << 22))) | ||
| 1428 | return ret; | ||
| 1429 | |||
| 1430 | gma = cmd_val(s, 1) & GENMASK(31, 2); | ||
| 1431 | if (gmadr_bytes == 8) { | ||
| 1432 | gma_high = cmd_val(s, 2) & GENMASK(15, 0); | ||
| 1433 | gma = (gma_high << 32) | gma; | ||
| 1434 | } | ||
| 1435 | ret = cmd_address_audit(s, gma, op_size, false); | ||
| 1436 | return ret; | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | static int cmd_handler_mi_store_data_index(struct parser_exec_state *s) | ||
| 1440 | { | ||
| 1441 | return unexpected_cmd(s); | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | static int cmd_handler_mi_clflush(struct parser_exec_state *s) | ||
| 1445 | { | ||
| 1446 | return unexpected_cmd(s); | ||
| 1447 | } | ||
| 1448 | |||
| 1449 | static int cmd_handler_mi_conditional_batch_buffer_end( | ||
| 1450 | struct parser_exec_state *s) | ||
| 1451 | { | ||
| 1452 | return unexpected_cmd(s); | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | static int cmd_handler_mi_update_gtt(struct parser_exec_state *s) | ||
| 1456 | { | ||
| 1457 | return unexpected_cmd(s); | ||
| 1458 | } | ||
| 1459 | |||
| 1460 | static int cmd_handler_mi_flush_dw(struct parser_exec_state *s) | ||
| 1461 | { | ||
| 1462 | int gmadr_bytes = s->vgpu->gvt->device_info.gmadr_bytes_in_cmd; | ||
| 1463 | unsigned long gma; | ||
| 1464 | bool index_mode = false; | ||
| 1465 | int ret = 0; | ||
| 1466 | |||
| 1467 | /* Check post-sync and ppgtt bit */ | ||
| 1468 | if (((cmd_val(s, 0) >> 14) & 0x3) && (cmd_val(s, 1) & (1 << 2))) { | ||
| 1469 | gma = cmd_val(s, 1) & GENMASK(31, 3); | ||
| 1470 | if (gmadr_bytes == 8) | ||
| 1471 | gma |= (cmd_val(s, 2) & GENMASK(15, 0)) << 32; | ||
| 1472 | /* Store Data Index */ | ||
| 1473 | if (cmd_val(s, 0) & (1 << 21)) | ||
| 1474 | index_mode = true; | ||
| 1475 | ret = cmd_address_audit(s, gma, sizeof(u64), index_mode); | ||
| 1476 | } | ||
| 1477 | /* Check notify bit */ | ||
| 1478 | if ((cmd_val(s, 0) & (1 << 8))) | ||
| 1479 | set_bit(cmd_interrupt_events[s->ring_id].mi_flush_dw, | ||
| 1480 | s->workload->pending_events); | ||
| 1481 | return ret; | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | static void addr_type_update_snb(struct parser_exec_state *s) | ||
| 1485 | { | ||
| 1486 | if ((s->buf_type == RING_BUFFER_INSTRUCTION) && | ||
| 1487 | (BATCH_BUFFER_ADR_SPACE_BIT(cmd_val(s, 0)) == 1)) { | ||
| 1488 | s->buf_addr_type = PPGTT_BUFFER; | ||
| 1489 | } | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | |||
| 1493 | static int copy_gma_to_hva(struct intel_vgpu *vgpu, struct intel_vgpu_mm *mm, | ||
| 1494 | unsigned long gma, unsigned long end_gma, void *va) | ||
| 1495 | { | ||
| 1496 | unsigned long copy_len, offset; | ||
| 1497 | unsigned long len = 0; | ||
| 1498 | unsigned long gpa; | ||
| 1499 | |||
| 1500 | while (gma != end_gma) { | ||
| 1501 | gpa = intel_vgpu_gma_to_gpa(mm, gma); | ||
| 1502 | if (gpa == INTEL_GVT_INVALID_ADDR) { | ||
| 1503 | gvt_err("invalid gma address: %lx\n", gma); | ||
| 1504 | return -EFAULT; | ||
| 1505 | } | ||
| 1506 | |||
| 1507 | offset = gma & (GTT_PAGE_SIZE - 1); | ||
| 1508 | |||
| 1509 | copy_len = (end_gma - gma) >= (GTT_PAGE_SIZE - offset) ? | ||
| 1510 | GTT_PAGE_SIZE - offset : end_gma - gma; | ||
| 1511 | |||
| 1512 | intel_gvt_hypervisor_read_gpa(vgpu, gpa, va + len, copy_len); | ||
| 1513 | |||
| 1514 | len += copy_len; | ||
| 1515 | gma += copy_len; | ||
| 1516 | } | ||
| 1517 | return 0; | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | |||
| 1521 | /* | ||
| 1522 | * Check whether a batch buffer needs to be scanned. Currently | ||
| 1523 | * the only criteria is based on privilege. | ||
| 1524 | */ | ||
| 1525 | static int batch_buffer_needs_scan(struct parser_exec_state *s) | ||
| 1526 | { | ||
| 1527 | struct intel_gvt *gvt = s->vgpu->gvt; | ||
| 1528 | |||
| 1529 | if (bypass_batch_buffer_scan) | ||
| 1530 | return 0; | ||
| 1531 | |||
| 1532 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { | ||
| 1533 | /* BDW decides privilege based on address space */ | ||
| 1534 | if (cmd_val(s, 0) & (1 << 8)) | ||
| 1535 | return 0; | ||
| 1536 | } | ||
| 1537 | return 1; | ||
| 1538 | } | ||
| 1539 | |||
| 1540 | static uint32_t find_bb_size(struct parser_exec_state *s) | ||
| 1541 | { | ||
| 1542 | unsigned long gma = 0; | ||
| 1543 | struct cmd_info *info; | ||
| 1544 | uint32_t bb_size = 0; | ||
| 1545 | uint32_t cmd_len = 0; | ||
| 1546 | bool met_bb_end = false; | ||
| 1547 | u32 cmd; | ||
| 1548 | |||
| 1549 | /* get the start gm address of the batch buffer */ | ||
| 1550 | gma = get_gma_bb_from_cmd(s, 1); | ||
| 1551 | cmd = cmd_val(s, 0); | ||
| 1552 | |||
| 1553 | info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); | ||
| 1554 | if (info == NULL) { | ||
| 1555 | gvt_err("unknown cmd 0x%x, opcode=0x%x\n", | ||
| 1556 | cmd, get_opcode(cmd, s->ring_id)); | ||
| 1557 | return -EINVAL; | ||
| 1558 | } | ||
| 1559 | do { | ||
| 1560 | copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm, | ||
| 1561 | gma, gma + 4, &cmd); | ||
| 1562 | info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); | ||
| 1563 | if (info == NULL) { | ||
| 1564 | gvt_err("unknown cmd 0x%x, opcode=0x%x\n", | ||
| 1565 | cmd, get_opcode(cmd, s->ring_id)); | ||
| 1566 | return -EINVAL; | ||
| 1567 | } | ||
| 1568 | |||
| 1569 | if (info->opcode == OP_MI_BATCH_BUFFER_END) { | ||
| 1570 | met_bb_end = true; | ||
| 1571 | } else if (info->opcode == OP_MI_BATCH_BUFFER_START) { | ||
| 1572 | if (BATCH_BUFFER_2ND_LEVEL_BIT(cmd) == 0) { | ||
| 1573 | /* chained batch buffer */ | ||
| 1574 | met_bb_end = true; | ||
| 1575 | } | ||
| 1576 | } | ||
| 1577 | cmd_len = get_cmd_length(info, cmd) << 2; | ||
| 1578 | bb_size += cmd_len; | ||
| 1579 | gma += cmd_len; | ||
| 1580 | |||
| 1581 | } while (!met_bb_end); | ||
| 1582 | |||
| 1583 | return bb_size; | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | static int perform_bb_shadow(struct parser_exec_state *s) | ||
| 1587 | { | ||
| 1588 | struct intel_shadow_bb_entry *entry_obj; | ||
| 1589 | unsigned long gma = 0; | ||
| 1590 | uint32_t bb_size; | ||
| 1591 | void *dst = NULL; | ||
| 1592 | int ret = 0; | ||
| 1593 | |||
| 1594 | /* get the start gm address of the batch buffer */ | ||
| 1595 | gma = get_gma_bb_from_cmd(s, 1); | ||
| 1596 | |||
| 1597 | /* get the size of the batch buffer */ | ||
| 1598 | bb_size = find_bb_size(s); | ||
| 1599 | |||
| 1600 | /* allocate shadow batch buffer */ | ||
| 1601 | entry_obj = kmalloc(sizeof(*entry_obj), GFP_KERNEL); | ||
| 1602 | if (entry_obj == NULL) | ||
| 1603 | return -ENOMEM; | ||
| 1604 | |||
| 1605 | entry_obj->obj = | ||
| 1606 | i915_gem_object_create(&(s->vgpu->gvt->dev_priv->drm), | ||
| 1607 | roundup(bb_size, PAGE_SIZE)); | ||
| 1608 | if (IS_ERR(entry_obj->obj)) { | ||
| 1609 | ret = PTR_ERR(entry_obj->obj); | ||
| 1610 | goto free_entry; | ||
| 1611 | } | ||
| 1612 | entry_obj->len = bb_size; | ||
| 1613 | INIT_LIST_HEAD(&entry_obj->list); | ||
| 1614 | |||
| 1615 | dst = i915_gem_object_pin_map(entry_obj->obj, I915_MAP_WB); | ||
| 1616 | if (IS_ERR(dst)) { | ||
| 1617 | ret = PTR_ERR(dst); | ||
| 1618 | goto put_obj; | ||
| 1619 | } | ||
| 1620 | |||
| 1621 | ret = i915_gem_object_set_to_cpu_domain(entry_obj->obj, false); | ||
| 1622 | if (ret) { | ||
| 1623 | gvt_err("failed to set shadow batch to CPU\n"); | ||
| 1624 | goto unmap_src; | ||
| 1625 | } | ||
| 1626 | |||
| 1627 | entry_obj->va = dst; | ||
| 1628 | entry_obj->bb_start_cmd_va = s->ip_va; | ||
| 1629 | |||
| 1630 | /* copy batch buffer to shadow batch buffer*/ | ||
| 1631 | ret = copy_gma_to_hva(s->vgpu, s->vgpu->gtt.ggtt_mm, | ||
| 1632 | gma, gma + bb_size, | ||
| 1633 | dst); | ||
| 1634 | if (ret) { | ||
| 1635 | gvt_err("fail to copy guest ring buffer\n"); | ||
| 1636 | goto unmap_src; | ||
| 1637 | } | ||
| 1638 | |||
| 1639 | list_add(&entry_obj->list, &s->workload->shadow_bb); | ||
| 1640 | /* | ||
| 1641 | * ip_va saves the virtual address of the shadow batch buffer, while | ||
| 1642 | * ip_gma saves the graphics address of the original batch buffer. | ||
| 1643 | * As the shadow batch buffer is just a copy from the originial one, | ||
| 1644 | * it should be right to use shadow batch buffer'va and original batch | ||
| 1645 | * buffer's gma in pair. After all, we don't want to pin the shadow | ||
| 1646 | * buffer here (too early). | ||
| 1647 | */ | ||
| 1648 | s->ip_va = dst; | ||
| 1649 | s->ip_gma = gma; | ||
| 1650 | |||
| 1651 | return 0; | ||
| 1652 | |||
| 1653 | unmap_src: | ||
| 1654 | i915_gem_object_unpin_map(entry_obj->obj); | ||
| 1655 | put_obj: | ||
| 1656 | i915_gem_object_put(entry_obj->obj); | ||
| 1657 | free_entry: | ||
| 1658 | kfree(entry_obj); | ||
| 1659 | return ret; | ||
| 1660 | } | ||
| 1661 | |||
| 1662 | static int cmd_handler_mi_batch_buffer_start(struct parser_exec_state *s) | ||
| 1663 | { | ||
| 1664 | bool second_level; | ||
| 1665 | int ret = 0; | ||
| 1666 | |||
| 1667 | if (s->buf_type == BATCH_BUFFER_2ND_LEVEL) { | ||
| 1668 | gvt_err("Found MI_BATCH_BUFFER_START in 2nd level BB\n"); | ||
| 1669 | return -EINVAL; | ||
| 1670 | } | ||
| 1671 | |||
| 1672 | second_level = BATCH_BUFFER_2ND_LEVEL_BIT(cmd_val(s, 0)) == 1; | ||
| 1673 | if (second_level && (s->buf_type != BATCH_BUFFER_INSTRUCTION)) { | ||
| 1674 | gvt_err("Jumping to 2nd level BB from RB is not allowed\n"); | ||
| 1675 | return -EINVAL; | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | s->saved_buf_addr_type = s->buf_addr_type; | ||
| 1679 | addr_type_update_snb(s); | ||
| 1680 | if (s->buf_type == RING_BUFFER_INSTRUCTION) { | ||
| 1681 | s->ret_ip_gma_ring = s->ip_gma + cmd_length(s) * sizeof(u32); | ||
| 1682 | s->buf_type = BATCH_BUFFER_INSTRUCTION; | ||
| 1683 | } else if (second_level) { | ||
| 1684 | s->buf_type = BATCH_BUFFER_2ND_LEVEL; | ||
| 1685 | s->ret_ip_gma_bb = s->ip_gma + cmd_length(s) * sizeof(u32); | ||
| 1686 | s->ret_bb_va = s->ip_va + cmd_length(s) * sizeof(u32); | ||
| 1687 | } | ||
| 1688 | |||
| 1689 | if (batch_buffer_needs_scan(s)) { | ||
| 1690 | ret = perform_bb_shadow(s); | ||
| 1691 | if (ret < 0) | ||
| 1692 | gvt_err("invalid shadow batch buffer\n"); | ||
| 1693 | } else { | ||
| 1694 | /* emulate a batch buffer end to do return right */ | ||
| 1695 | ret = cmd_handler_mi_batch_buffer_end(s); | ||
| 1696 | if (ret < 0) | ||
| 1697 | return ret; | ||
| 1698 | } | ||
| 1699 | |||
| 1700 | return ret; | ||
| 1701 | } | ||
| 1702 | |||
| 1703 | static struct cmd_info cmd_info[] = { | ||
| 1704 | {"MI_NOOP", OP_MI_NOOP, F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL}, | ||
| 1705 | |||
| 1706 | {"MI_SET_PREDICATE", OP_MI_SET_PREDICATE, F_LEN_CONST, R_ALL, D_ALL, | ||
| 1707 | 0, 1, NULL}, | ||
| 1708 | |||
| 1709 | {"MI_USER_INTERRUPT", OP_MI_USER_INTERRUPT, F_LEN_CONST, R_ALL, D_ALL, | ||
| 1710 | 0, 1, cmd_handler_mi_user_interrupt}, | ||
| 1711 | |||
| 1712 | {"MI_WAIT_FOR_EVENT", OP_MI_WAIT_FOR_EVENT, F_LEN_CONST, R_RCS | R_BCS, | ||
| 1713 | D_ALL, 0, 1, cmd_handler_mi_wait_for_event}, | ||
| 1714 | |||
| 1715 | {"MI_FLUSH", OP_MI_FLUSH, F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL}, | ||
| 1716 | |||
| 1717 | {"MI_ARB_CHECK", OP_MI_ARB_CHECK, F_LEN_CONST, R_ALL, D_ALL, 0, 1, | ||
| 1718 | NULL}, | ||
| 1719 | |||
| 1720 | {"MI_RS_CONTROL", OP_MI_RS_CONTROL, F_LEN_CONST, R_RCS, D_ALL, 0, 1, | ||
| 1721 | NULL}, | ||
| 1722 | |||
| 1723 | {"MI_REPORT_HEAD", OP_MI_REPORT_HEAD, F_LEN_CONST, R_ALL, D_ALL, 0, 1, | ||
| 1724 | NULL}, | ||
| 1725 | |||
| 1726 | {"MI_ARB_ON_OFF", OP_MI_ARB_ON_OFF, F_LEN_CONST, R_ALL, D_ALL, 0, 1, | ||
| 1727 | NULL}, | ||
| 1728 | |||
| 1729 | {"MI_URB_ATOMIC_ALLOC", OP_MI_URB_ATOMIC_ALLOC, F_LEN_CONST, R_RCS, | ||
| 1730 | D_ALL, 0, 1, NULL}, | ||
| 1731 | |||
| 1732 | {"MI_BATCH_BUFFER_END", OP_MI_BATCH_BUFFER_END, | ||
| 1733 | F_IP_ADVANCE_CUSTOM | F_LEN_CONST, R_ALL, D_ALL, 0, 1, | ||
| 1734 | cmd_handler_mi_batch_buffer_end}, | ||
| 1735 | |||
| 1736 | {"MI_SUSPEND_FLUSH", OP_MI_SUSPEND_FLUSH, F_LEN_CONST, R_ALL, D_ALL, | ||
| 1737 | 0, 1, NULL}, | ||
| 1738 | |||
| 1739 | {"MI_PREDICATE", OP_MI_PREDICATE, F_LEN_CONST, R_RCS, D_ALL, 0, 1, | ||
| 1740 | NULL}, | ||
| 1741 | |||
| 1742 | {"MI_TOPOLOGY_FILTER", OP_MI_TOPOLOGY_FILTER, F_LEN_CONST, R_ALL, | ||
| 1743 | D_ALL, 0, 1, NULL}, | ||
| 1744 | |||
| 1745 | {"MI_SET_APPID", OP_MI_SET_APPID, F_LEN_CONST, R_ALL, D_ALL, 0, 1, | ||
| 1746 | NULL}, | ||
| 1747 | |||
| 1748 | {"MI_RS_CONTEXT", OP_MI_RS_CONTEXT, F_LEN_CONST, R_RCS, D_ALL, 0, 1, | ||
| 1749 | NULL}, | ||
| 1750 | |||
| 1751 | {"MI_DISPLAY_FLIP", OP_MI_DISPLAY_FLIP, F_LEN_VAR | F_POST_HANDLE, | ||
| 1752 | R_RCS | R_BCS, D_ALL, 0, 8, cmd_handler_mi_display_flip}, | ||
| 1753 | |||
| 1754 | {"MI_SEMAPHORE_MBOX", OP_MI_SEMAPHORE_MBOX, F_LEN_VAR, R_ALL, D_ALL, | ||
| 1755 | 0, 8, NULL}, | ||
| 1756 | |||
| 1757 | {"MI_MATH", OP_MI_MATH, F_LEN_VAR, R_ALL, D_ALL, 0, 8, NULL}, | ||
| 1758 | |||
| 1759 | {"MI_URB_CLEAR", OP_MI_URB_CLEAR, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1760 | |||
| 1761 | {"ME_SEMAPHORE_SIGNAL", OP_MI_SEMAPHORE_SIGNAL, F_LEN_VAR, R_ALL, | ||
| 1762 | D_BDW_PLUS, 0, 8, NULL}, | ||
| 1763 | |||
| 1764 | {"ME_SEMAPHORE_WAIT", OP_MI_SEMAPHORE_WAIT, F_LEN_VAR, R_ALL, D_BDW_PLUS, | ||
| 1765 | ADDR_FIX_1(2), 8, cmd_handler_mi_semaphore_wait}, | ||
| 1766 | |||
| 1767 | {"MI_STORE_DATA_IMM", OP_MI_STORE_DATA_IMM, F_LEN_VAR, R_ALL, D_BDW_PLUS, | ||
| 1768 | ADDR_FIX_1(1), 10, cmd_handler_mi_store_data_imm}, | ||
| 1769 | |||
| 1770 | {"MI_STORE_DATA_INDEX", OP_MI_STORE_DATA_INDEX, F_LEN_VAR, R_ALL, D_ALL, | ||
| 1771 | 0, 8, cmd_handler_mi_store_data_index}, | ||
| 1772 | |||
| 1773 | {"MI_LOAD_REGISTER_IMM", OP_MI_LOAD_REGISTER_IMM, F_LEN_VAR, R_ALL, | ||
| 1774 | D_ALL, 0, 8, cmd_handler_lri}, | ||
| 1775 | |||
| 1776 | {"MI_UPDATE_GTT", OP_MI_UPDATE_GTT, F_LEN_VAR, R_ALL, D_BDW_PLUS, 0, 10, | ||
| 1777 | cmd_handler_mi_update_gtt}, | ||
| 1778 | |||
| 1779 | {"MI_STORE_REGISTER_MEM", OP_MI_STORE_REGISTER_MEM, F_LEN_VAR, R_ALL, | ||
| 1780 | D_ALL, ADDR_FIX_1(2), 8, cmd_handler_srm}, | ||
| 1781 | |||
| 1782 | {"MI_FLUSH_DW", OP_MI_FLUSH_DW, F_LEN_VAR, R_ALL, D_ALL, 0, 6, | ||
| 1783 | cmd_handler_mi_flush_dw}, | ||
| 1784 | |||
| 1785 | {"MI_CLFLUSH", OP_MI_CLFLUSH, F_LEN_VAR, R_ALL, D_ALL, ADDR_FIX_1(1), | ||
| 1786 | 10, cmd_handler_mi_clflush}, | ||
| 1787 | |||
| 1788 | {"MI_REPORT_PERF_COUNT", OP_MI_REPORT_PERF_COUNT, F_LEN_VAR, R_ALL, | ||
| 1789 | D_ALL, ADDR_FIX_1(1), 6, cmd_handler_mi_report_perf_count}, | ||
| 1790 | |||
| 1791 | {"MI_LOAD_REGISTER_MEM", OP_MI_LOAD_REGISTER_MEM, F_LEN_VAR, R_ALL, | ||
| 1792 | D_ALL, ADDR_FIX_1(2), 8, cmd_handler_lrm}, | ||
| 1793 | |||
| 1794 | {"MI_LOAD_REGISTER_REG", OP_MI_LOAD_REGISTER_REG, F_LEN_VAR, R_ALL, | ||
| 1795 | D_ALL, 0, 8, cmd_handler_lrr}, | ||
| 1796 | |||
| 1797 | {"MI_RS_STORE_DATA_IMM", OP_MI_RS_STORE_DATA_IMM, F_LEN_VAR, R_RCS, | ||
| 1798 | D_ALL, 0, 8, NULL}, | ||
| 1799 | |||
| 1800 | {"MI_LOAD_URB_MEM", OP_MI_LOAD_URB_MEM, F_LEN_VAR, R_RCS, D_ALL, | ||
| 1801 | ADDR_FIX_1(2), 8, NULL}, | ||
| 1802 | |||
| 1803 | {"MI_STORE_URM_MEM", OP_MI_STORE_URM_MEM, F_LEN_VAR, R_RCS, D_ALL, | ||
| 1804 | ADDR_FIX_1(2), 8, NULL}, | ||
| 1805 | |||
| 1806 | {"MI_OP_2E", OP_MI_2E, F_LEN_VAR, R_ALL, D_BDW_PLUS, ADDR_FIX_2(1, 2), | ||
| 1807 | 8, cmd_handler_mi_op_2e}, | ||
| 1808 | |||
| 1809 | {"MI_OP_2F", OP_MI_2F, F_LEN_VAR, R_ALL, D_BDW_PLUS, ADDR_FIX_1(1), | ||
| 1810 | 8, cmd_handler_mi_op_2f}, | ||
| 1811 | |||
| 1812 | {"MI_BATCH_BUFFER_START", OP_MI_BATCH_BUFFER_START, | ||
| 1813 | F_IP_ADVANCE_CUSTOM, R_ALL, D_ALL, 0, 8, | ||
| 1814 | cmd_handler_mi_batch_buffer_start}, | ||
| 1815 | |||
| 1816 | {"MI_CONDITIONAL_BATCH_BUFFER_END", OP_MI_CONDITIONAL_BATCH_BUFFER_END, | ||
| 1817 | F_LEN_VAR, R_ALL, D_ALL, ADDR_FIX_1(2), 8, | ||
| 1818 | cmd_handler_mi_conditional_batch_buffer_end}, | ||
| 1819 | |||
| 1820 | {"MI_LOAD_SCAN_LINES_INCL", OP_MI_LOAD_SCAN_LINES_INCL, F_LEN_CONST, | ||
| 1821 | R_RCS | R_BCS, D_ALL, 0, 2, NULL}, | ||
| 1822 | |||
| 1823 | {"XY_SETUP_BLT", OP_XY_SETUP_BLT, F_LEN_VAR, R_BCS, D_ALL, | ||
| 1824 | ADDR_FIX_2(4, 7), 8, NULL}, | ||
| 1825 | |||
| 1826 | {"XY_SETUP_CLIP_BLT", OP_XY_SETUP_CLIP_BLT, F_LEN_VAR, R_BCS, D_ALL, | ||
| 1827 | 0, 8, NULL}, | ||
| 1828 | |||
| 1829 | {"XY_SETUP_MONO_PATTERN_SL_BLT", OP_XY_SETUP_MONO_PATTERN_SL_BLT, | ||
| 1830 | F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL}, | ||
| 1831 | |||
| 1832 | {"XY_PIXEL_BLT", OP_XY_PIXEL_BLT, F_LEN_VAR, R_BCS, D_ALL, 0, 8, NULL}, | ||
| 1833 | |||
| 1834 | {"XY_SCANLINES_BLT", OP_XY_SCANLINES_BLT, F_LEN_VAR, R_BCS, D_ALL, | ||
| 1835 | 0, 8, NULL}, | ||
| 1836 | |||
| 1837 | {"XY_TEXT_BLT", OP_XY_TEXT_BLT, F_LEN_VAR, R_BCS, D_ALL, | ||
| 1838 | ADDR_FIX_1(3), 8, NULL}, | ||
| 1839 | |||
| 1840 | {"XY_TEXT_IMMEDIATE_BLT", OP_XY_TEXT_IMMEDIATE_BLT, F_LEN_VAR, R_BCS, | ||
| 1841 | D_ALL, 0, 8, NULL}, | ||
| 1842 | |||
| 1843 | {"XY_COLOR_BLT", OP_XY_COLOR_BLT, F_LEN_VAR, R_BCS, D_ALL, | ||
| 1844 | ADDR_FIX_1(4), 8, NULL}, | ||
| 1845 | |||
| 1846 | {"XY_PAT_BLT", OP_XY_PAT_BLT, F_LEN_VAR, R_BCS, D_ALL, | ||
| 1847 | ADDR_FIX_2(4, 5), 8, NULL}, | ||
| 1848 | |||
| 1849 | {"XY_MONO_PAT_BLT", OP_XY_MONO_PAT_BLT, F_LEN_VAR, R_BCS, D_ALL, | ||
| 1850 | ADDR_FIX_1(4), 8, NULL}, | ||
| 1851 | |||
| 1852 | {"XY_SRC_COPY_BLT", OP_XY_SRC_COPY_BLT, F_LEN_VAR, R_BCS, D_ALL, | ||
| 1853 | ADDR_FIX_2(4, 7), 8, NULL}, | ||
| 1854 | |||
| 1855 | {"XY_MONO_SRC_COPY_BLT", OP_XY_MONO_SRC_COPY_BLT, F_LEN_VAR, R_BCS, | ||
| 1856 | D_ALL, ADDR_FIX_2(4, 5), 8, NULL}, | ||
| 1857 | |||
| 1858 | {"XY_FULL_BLT", OP_XY_FULL_BLT, F_LEN_VAR, R_BCS, D_ALL, 0, 8, NULL}, | ||
| 1859 | |||
| 1860 | {"XY_FULL_MONO_SRC_BLT", OP_XY_FULL_MONO_SRC_BLT, F_LEN_VAR, R_BCS, | ||
| 1861 | D_ALL, ADDR_FIX_3(4, 5, 8), 8, NULL}, | ||
| 1862 | |||
| 1863 | {"XY_FULL_MONO_PATTERN_BLT", OP_XY_FULL_MONO_PATTERN_BLT, F_LEN_VAR, | ||
| 1864 | R_BCS, D_ALL, ADDR_FIX_2(4, 7), 8, NULL}, | ||
| 1865 | |||
| 1866 | {"XY_FULL_MONO_PATTERN_MONO_SRC_BLT", | ||
| 1867 | OP_XY_FULL_MONO_PATTERN_MONO_SRC_BLT, | ||
| 1868 | F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 5), 8, NULL}, | ||
| 1869 | |||
| 1870 | {"XY_MONO_PAT_FIXED_BLT", OP_XY_MONO_PAT_FIXED_BLT, F_LEN_VAR, R_BCS, | ||
| 1871 | D_ALL, ADDR_FIX_1(4), 8, NULL}, | ||
| 1872 | |||
| 1873 | {"XY_MONO_SRC_COPY_IMMEDIATE_BLT", OP_XY_MONO_SRC_COPY_IMMEDIATE_BLT, | ||
| 1874 | F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL}, | ||
| 1875 | |||
| 1876 | {"XY_PAT_BLT_IMMEDIATE", OP_XY_PAT_BLT_IMMEDIATE, F_LEN_VAR, R_BCS, | ||
| 1877 | D_ALL, ADDR_FIX_1(4), 8, NULL}, | ||
| 1878 | |||
| 1879 | {"XY_SRC_COPY_CHROMA_BLT", OP_XY_SRC_COPY_CHROMA_BLT, F_LEN_VAR, R_BCS, | ||
| 1880 | D_ALL, ADDR_FIX_2(4, 7), 8, NULL}, | ||
| 1881 | |||
| 1882 | {"XY_FULL_IMMEDIATE_PATTERN_BLT", OP_XY_FULL_IMMEDIATE_PATTERN_BLT, | ||
| 1883 | F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 7), 8, NULL}, | ||
| 1884 | |||
| 1885 | {"XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT", | ||
| 1886 | OP_XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT, | ||
| 1887 | F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_2(4, 5), 8, NULL}, | ||
| 1888 | |||
| 1889 | {"XY_PAT_CHROMA_BLT", OP_XY_PAT_CHROMA_BLT, F_LEN_VAR, R_BCS, D_ALL, | ||
| 1890 | ADDR_FIX_2(4, 5), 8, NULL}, | ||
| 1891 | |||
| 1892 | {"XY_PAT_CHROMA_BLT_IMMEDIATE", OP_XY_PAT_CHROMA_BLT_IMMEDIATE, | ||
| 1893 | F_LEN_VAR, R_BCS, D_ALL, ADDR_FIX_1(4), 8, NULL}, | ||
| 1894 | |||
| 1895 | {"3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP", | ||
| 1896 | OP_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP, | ||
| 1897 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1898 | |||
| 1899 | {"3DSTATE_VIEWPORT_STATE_POINTERS_CC", | ||
| 1900 | OP_3DSTATE_VIEWPORT_STATE_POINTERS_CC, | ||
| 1901 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1902 | |||
| 1903 | {"3DSTATE_BLEND_STATE_POINTERS", | ||
| 1904 | OP_3DSTATE_BLEND_STATE_POINTERS, | ||
| 1905 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1906 | |||
| 1907 | {"3DSTATE_DEPTH_STENCIL_STATE_POINTERS", | ||
| 1908 | OP_3DSTATE_DEPTH_STENCIL_STATE_POINTERS, | ||
| 1909 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1910 | |||
| 1911 | {"3DSTATE_BINDING_TABLE_POINTERS_VS", | ||
| 1912 | OP_3DSTATE_BINDING_TABLE_POINTERS_VS, | ||
| 1913 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1914 | |||
| 1915 | {"3DSTATE_BINDING_TABLE_POINTERS_HS", | ||
| 1916 | OP_3DSTATE_BINDING_TABLE_POINTERS_HS, | ||
| 1917 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1918 | |||
| 1919 | {"3DSTATE_BINDING_TABLE_POINTERS_DS", | ||
| 1920 | OP_3DSTATE_BINDING_TABLE_POINTERS_DS, | ||
| 1921 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1922 | |||
| 1923 | {"3DSTATE_BINDING_TABLE_POINTERS_GS", | ||
| 1924 | OP_3DSTATE_BINDING_TABLE_POINTERS_GS, | ||
| 1925 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1926 | |||
| 1927 | {"3DSTATE_BINDING_TABLE_POINTERS_PS", | ||
| 1928 | OP_3DSTATE_BINDING_TABLE_POINTERS_PS, | ||
| 1929 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1930 | |||
| 1931 | {"3DSTATE_SAMPLER_STATE_POINTERS_VS", | ||
| 1932 | OP_3DSTATE_SAMPLER_STATE_POINTERS_VS, | ||
| 1933 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1934 | |||
| 1935 | {"3DSTATE_SAMPLER_STATE_POINTERS_HS", | ||
| 1936 | OP_3DSTATE_SAMPLER_STATE_POINTERS_HS, | ||
| 1937 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1938 | |||
| 1939 | {"3DSTATE_SAMPLER_STATE_POINTERS_DS", | ||
| 1940 | OP_3DSTATE_SAMPLER_STATE_POINTERS_DS, | ||
| 1941 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1942 | |||
| 1943 | {"3DSTATE_SAMPLER_STATE_POINTERS_GS", | ||
| 1944 | OP_3DSTATE_SAMPLER_STATE_POINTERS_GS, | ||
| 1945 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1946 | |||
| 1947 | {"3DSTATE_SAMPLER_STATE_POINTERS_PS", | ||
| 1948 | OP_3DSTATE_SAMPLER_STATE_POINTERS_PS, | ||
| 1949 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1950 | |||
| 1951 | {"3DSTATE_URB_VS", OP_3DSTATE_URB_VS, F_LEN_VAR, R_RCS, D_ALL, | ||
| 1952 | 0, 8, NULL}, | ||
| 1953 | |||
| 1954 | {"3DSTATE_URB_HS", OP_3DSTATE_URB_HS, F_LEN_VAR, R_RCS, D_ALL, | ||
| 1955 | 0, 8, NULL}, | ||
| 1956 | |||
| 1957 | {"3DSTATE_URB_DS", OP_3DSTATE_URB_DS, F_LEN_VAR, R_RCS, D_ALL, | ||
| 1958 | 0, 8, NULL}, | ||
| 1959 | |||
| 1960 | {"3DSTATE_URB_GS", OP_3DSTATE_URB_GS, F_LEN_VAR, R_RCS, D_ALL, | ||
| 1961 | 0, 8, NULL}, | ||
| 1962 | |||
| 1963 | {"3DSTATE_GATHER_CONSTANT_VS", OP_3DSTATE_GATHER_CONSTANT_VS, | ||
| 1964 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1965 | |||
| 1966 | {"3DSTATE_GATHER_CONSTANT_GS", OP_3DSTATE_GATHER_CONSTANT_GS, | ||
| 1967 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1968 | |||
| 1969 | {"3DSTATE_GATHER_CONSTANT_HS", OP_3DSTATE_GATHER_CONSTANT_HS, | ||
| 1970 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1971 | |||
| 1972 | {"3DSTATE_GATHER_CONSTANT_DS", OP_3DSTATE_GATHER_CONSTANT_DS, | ||
| 1973 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1974 | |||
| 1975 | {"3DSTATE_GATHER_CONSTANT_PS", OP_3DSTATE_GATHER_CONSTANT_PS, | ||
| 1976 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1977 | |||
| 1978 | {"3DSTATE_DX9_CONSTANTF_VS", OP_3DSTATE_DX9_CONSTANTF_VS, | ||
| 1979 | F_LEN_VAR, R_RCS, D_ALL, 0, 11, NULL}, | ||
| 1980 | |||
| 1981 | {"3DSTATE_DX9_CONSTANTF_PS", OP_3DSTATE_DX9_CONSTANTF_PS, | ||
| 1982 | F_LEN_VAR, R_RCS, D_ALL, 0, 11, NULL}, | ||
| 1983 | |||
| 1984 | {"3DSTATE_DX9_CONSTANTI_VS", OP_3DSTATE_DX9_CONSTANTI_VS, | ||
| 1985 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1986 | |||
| 1987 | {"3DSTATE_DX9_CONSTANTI_PS", OP_3DSTATE_DX9_CONSTANTI_PS, | ||
| 1988 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1989 | |||
| 1990 | {"3DSTATE_DX9_CONSTANTB_VS", OP_3DSTATE_DX9_CONSTANTB_VS, | ||
| 1991 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1992 | |||
| 1993 | {"3DSTATE_DX9_CONSTANTB_PS", OP_3DSTATE_DX9_CONSTANTB_PS, | ||
| 1994 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1995 | |||
| 1996 | {"3DSTATE_DX9_LOCAL_VALID_VS", OP_3DSTATE_DX9_LOCAL_VALID_VS, | ||
| 1997 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 1998 | |||
| 1999 | {"3DSTATE_DX9_LOCAL_VALID_PS", OP_3DSTATE_DX9_LOCAL_VALID_PS, | ||
| 2000 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2001 | |||
| 2002 | {"3DSTATE_DX9_GENERATE_ACTIVE_VS", OP_3DSTATE_DX9_GENERATE_ACTIVE_VS, | ||
| 2003 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2004 | |||
| 2005 | {"3DSTATE_DX9_GENERATE_ACTIVE_PS", OP_3DSTATE_DX9_GENERATE_ACTIVE_PS, | ||
| 2006 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2007 | |||
| 2008 | {"3DSTATE_BINDING_TABLE_EDIT_VS", OP_3DSTATE_BINDING_TABLE_EDIT_VS, | ||
| 2009 | F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL}, | ||
| 2010 | |||
| 2011 | {"3DSTATE_BINDING_TABLE_EDIT_GS", OP_3DSTATE_BINDING_TABLE_EDIT_GS, | ||
| 2012 | F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL}, | ||
| 2013 | |||
| 2014 | {"3DSTATE_BINDING_TABLE_EDIT_HS", OP_3DSTATE_BINDING_TABLE_EDIT_HS, | ||
| 2015 | F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL}, | ||
| 2016 | |||
| 2017 | {"3DSTATE_BINDING_TABLE_EDIT_DS", OP_3DSTATE_BINDING_TABLE_EDIT_DS, | ||
| 2018 | F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL}, | ||
| 2019 | |||
| 2020 | {"3DSTATE_BINDING_TABLE_EDIT_PS", OP_3DSTATE_BINDING_TABLE_EDIT_PS, | ||
| 2021 | F_LEN_VAR, R_RCS, D_ALL, 0, 9, NULL}, | ||
| 2022 | |||
| 2023 | {"3DSTATE_VF_INSTANCING", OP_3DSTATE_VF_INSTANCING, F_LEN_VAR, R_RCS, | ||
| 2024 | D_BDW_PLUS, 0, 8, NULL}, | ||
| 2025 | |||
| 2026 | {"3DSTATE_VF_SGVS", OP_3DSTATE_VF_SGVS, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8, | ||
| 2027 | NULL}, | ||
| 2028 | |||
| 2029 | {"3DSTATE_VF_TOPOLOGY", OP_3DSTATE_VF_TOPOLOGY, F_LEN_VAR, R_RCS, | ||
| 2030 | D_BDW_PLUS, 0, 8, NULL}, | ||
| 2031 | |||
| 2032 | {"3DSTATE_WM_CHROMAKEY", OP_3DSTATE_WM_CHROMAKEY, F_LEN_VAR, R_RCS, | ||
| 2033 | D_BDW_PLUS, 0, 8, NULL}, | ||
| 2034 | |||
| 2035 | {"3DSTATE_PS_BLEND", OP_3DSTATE_PS_BLEND, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, | ||
| 2036 | 8, NULL}, | ||
| 2037 | |||
| 2038 | {"3DSTATE_WM_DEPTH_STENCIL", OP_3DSTATE_WM_DEPTH_STENCIL, F_LEN_VAR, | ||
| 2039 | R_RCS, D_BDW_PLUS, 0, 8, NULL}, | ||
| 2040 | |||
| 2041 | {"3DSTATE_PS_EXTRA", OP_3DSTATE_PS_EXTRA, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, | ||
| 2042 | 8, NULL}, | ||
| 2043 | |||
| 2044 | {"3DSTATE_RASTER", OP_3DSTATE_RASTER, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8, | ||
| 2045 | NULL}, | ||
| 2046 | |||
| 2047 | {"3DSTATE_SBE_SWIZ", OP_3DSTATE_SBE_SWIZ, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8, | ||
| 2048 | NULL}, | ||
| 2049 | |||
| 2050 | {"3DSTATE_WM_HZ_OP", OP_3DSTATE_WM_HZ_OP, F_LEN_VAR, R_RCS, D_BDW_PLUS, 0, 8, | ||
| 2051 | NULL}, | ||
| 2052 | |||
| 2053 | {"3DSTATE_VERTEX_BUFFERS", OP_3DSTATE_VERTEX_BUFFERS, F_LEN_VAR, R_RCS, | ||
| 2054 | D_BDW_PLUS, 0, 8, NULL}, | ||
| 2055 | |||
| 2056 | {"3DSTATE_VERTEX_ELEMENTS", OP_3DSTATE_VERTEX_ELEMENTS, F_LEN_VAR, | ||
| 2057 | R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2058 | |||
| 2059 | {"3DSTATE_INDEX_BUFFER", OP_3DSTATE_INDEX_BUFFER, F_LEN_VAR, R_RCS, | ||
| 2060 | D_BDW_PLUS, ADDR_FIX_1(2), 8, NULL}, | ||
| 2061 | |||
| 2062 | {"3DSTATE_VF_STATISTICS", OP_3DSTATE_VF_STATISTICS, F_LEN_CONST, | ||
| 2063 | R_RCS, D_ALL, 0, 1, NULL}, | ||
| 2064 | |||
| 2065 | {"3DSTATE_VF", OP_3DSTATE_VF, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2066 | |||
| 2067 | {"3DSTATE_CC_STATE_POINTERS", OP_3DSTATE_CC_STATE_POINTERS, F_LEN_VAR, | ||
| 2068 | R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2069 | |||
| 2070 | {"3DSTATE_SCISSOR_STATE_POINTERS", OP_3DSTATE_SCISSOR_STATE_POINTERS, | ||
| 2071 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2072 | |||
| 2073 | {"3DSTATE_GS", OP_3DSTATE_GS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2074 | |||
| 2075 | {"3DSTATE_CLIP", OP_3DSTATE_CLIP, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2076 | |||
| 2077 | {"3DSTATE_WM", OP_3DSTATE_WM, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2078 | |||
| 2079 | {"3DSTATE_CONSTANT_GS", OP_3DSTATE_CONSTANT_GS, F_LEN_VAR, R_RCS, | ||
| 2080 | D_BDW_PLUS, 0, 8, NULL}, | ||
| 2081 | |||
| 2082 | {"3DSTATE_CONSTANT_PS", OP_3DSTATE_CONSTANT_PS, F_LEN_VAR, R_RCS, | ||
| 2083 | D_BDW_PLUS, 0, 8, NULL}, | ||
| 2084 | |||
| 2085 | {"3DSTATE_SAMPLE_MASK", OP_3DSTATE_SAMPLE_MASK, F_LEN_VAR, R_RCS, | ||
| 2086 | D_ALL, 0, 8, NULL}, | ||
| 2087 | |||
| 2088 | {"3DSTATE_CONSTANT_HS", OP_3DSTATE_CONSTANT_HS, F_LEN_VAR, R_RCS, | ||
| 2089 | D_BDW_PLUS, 0, 8, NULL}, | ||
| 2090 | |||
| 2091 | {"3DSTATE_CONSTANT_DS", OP_3DSTATE_CONSTANT_DS, F_LEN_VAR, R_RCS, | ||
| 2092 | D_BDW_PLUS, 0, 8, NULL}, | ||
| 2093 | |||
| 2094 | {"3DSTATE_HS", OP_3DSTATE_HS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2095 | |||
| 2096 | {"3DSTATE_TE", OP_3DSTATE_TE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2097 | |||
| 2098 | {"3DSTATE_DS", OP_3DSTATE_DS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2099 | |||
| 2100 | {"3DSTATE_STREAMOUT", OP_3DSTATE_STREAMOUT, F_LEN_VAR, R_RCS, | ||
| 2101 | D_ALL, 0, 8, NULL}, | ||
| 2102 | |||
| 2103 | {"3DSTATE_SBE", OP_3DSTATE_SBE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2104 | |||
| 2105 | {"3DSTATE_PS", OP_3DSTATE_PS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2106 | |||
| 2107 | {"3DSTATE_DRAWING_RECTANGLE", OP_3DSTATE_DRAWING_RECTANGLE, F_LEN_VAR, | ||
| 2108 | R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2109 | |||
| 2110 | {"3DSTATE_SAMPLER_PALETTE_LOAD0", OP_3DSTATE_SAMPLER_PALETTE_LOAD0, | ||
| 2111 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2112 | |||
| 2113 | {"3DSTATE_CHROMA_KEY", OP_3DSTATE_CHROMA_KEY, F_LEN_VAR, R_RCS, D_ALL, | ||
| 2114 | 0, 8, NULL}, | ||
| 2115 | |||
| 2116 | {"3DSTATE_DEPTH_BUFFER", OP_3DSTATE_DEPTH_BUFFER, F_LEN_VAR, R_RCS, | ||
| 2117 | D_ALL, ADDR_FIX_1(2), 8, NULL}, | ||
| 2118 | |||
| 2119 | {"3DSTATE_POLY_STIPPLE_OFFSET", OP_3DSTATE_POLY_STIPPLE_OFFSET, | ||
| 2120 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2121 | |||
| 2122 | {"3DSTATE_POLY_STIPPLE_PATTERN", OP_3DSTATE_POLY_STIPPLE_PATTERN, | ||
| 2123 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2124 | |||
| 2125 | {"3DSTATE_LINE_STIPPLE", OP_3DSTATE_LINE_STIPPLE, F_LEN_VAR, R_RCS, | ||
| 2126 | D_ALL, 0, 8, NULL}, | ||
| 2127 | |||
| 2128 | {"3DSTATE_AA_LINE_PARAMS", OP_3DSTATE_AA_LINE_PARAMS, F_LEN_VAR, R_RCS, | ||
| 2129 | D_ALL, 0, 8, NULL}, | ||
| 2130 | |||
| 2131 | {"3DSTATE_GS_SVB_INDEX", OP_3DSTATE_GS_SVB_INDEX, F_LEN_VAR, R_RCS, | ||
| 2132 | D_ALL, 0, 8, NULL}, | ||
| 2133 | |||
| 2134 | {"3DSTATE_SAMPLER_PALETTE_LOAD1", OP_3DSTATE_SAMPLER_PALETTE_LOAD1, | ||
| 2135 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2136 | |||
| 2137 | {"3DSTATE_MULTISAMPLE", OP_3DSTATE_MULTISAMPLE_BDW, F_LEN_VAR, R_RCS, | ||
| 2138 | D_BDW_PLUS, 0, 8, NULL}, | ||
| 2139 | |||
| 2140 | {"3DSTATE_STENCIL_BUFFER", OP_3DSTATE_STENCIL_BUFFER, F_LEN_VAR, R_RCS, | ||
| 2141 | D_ALL, ADDR_FIX_1(2), 8, NULL}, | ||
| 2142 | |||
| 2143 | {"3DSTATE_HIER_DEPTH_BUFFER", OP_3DSTATE_HIER_DEPTH_BUFFER, F_LEN_VAR, | ||
| 2144 | R_RCS, D_ALL, ADDR_FIX_1(2), 8, NULL}, | ||
| 2145 | |||
| 2146 | {"3DSTATE_CLEAR_PARAMS", OP_3DSTATE_CLEAR_PARAMS, F_LEN_VAR, | ||
| 2147 | R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2148 | |||
| 2149 | {"3DSTATE_PUSH_CONSTANT_ALLOC_VS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_VS, | ||
| 2150 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2151 | |||
| 2152 | {"3DSTATE_PUSH_CONSTANT_ALLOC_HS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_HS, | ||
| 2153 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2154 | |||
| 2155 | {"3DSTATE_PUSH_CONSTANT_ALLOC_DS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_DS, | ||
| 2156 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2157 | |||
| 2158 | {"3DSTATE_PUSH_CONSTANT_ALLOC_GS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_GS, | ||
| 2159 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2160 | |||
| 2161 | {"3DSTATE_PUSH_CONSTANT_ALLOC_PS", OP_3DSTATE_PUSH_CONSTANT_ALLOC_PS, | ||
| 2162 | F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2163 | |||
| 2164 | {"3DSTATE_MONOFILTER_SIZE", OP_3DSTATE_MONOFILTER_SIZE, F_LEN_VAR, | ||
| 2165 | R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2166 | |||
| 2167 | {"3DSTATE_SO_DECL_LIST", OP_3DSTATE_SO_DECL_LIST, F_LEN_VAR, R_RCS, | ||
| 2168 | D_ALL, 0, 9, NULL}, | ||
| 2169 | |||
| 2170 | {"3DSTATE_SO_BUFFER", OP_3DSTATE_SO_BUFFER, F_LEN_VAR, R_RCS, D_BDW_PLUS, | ||
| 2171 | ADDR_FIX_2(2, 4), 8, NULL}, | ||
| 2172 | |||
| 2173 | {"3DSTATE_BINDING_TABLE_POOL_ALLOC", | ||
| 2174 | OP_3DSTATE_BINDING_TABLE_POOL_ALLOC, | ||
| 2175 | F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL}, | ||
| 2176 | |||
| 2177 | {"3DSTATE_GATHER_POOL_ALLOC", OP_3DSTATE_GATHER_POOL_ALLOC, | ||
| 2178 | F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL}, | ||
| 2179 | |||
| 2180 | {"3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC", | ||
| 2181 | OP_3DSTATE_DX9_CONSTANT_BUFFER_POOL_ALLOC, | ||
| 2182 | F_LEN_VAR, R_RCS, D_BDW_PLUS, ADDR_FIX_1(1), 8, NULL}, | ||
| 2183 | |||
| 2184 | {"3DSTATE_SAMPLE_PATTERN", OP_3DSTATE_SAMPLE_PATTERN, F_LEN_VAR, R_RCS, | ||
| 2185 | D_BDW_PLUS, 0, 8, NULL}, | ||
| 2186 | |||
| 2187 | {"PIPE_CONTROL", OP_PIPE_CONTROL, F_LEN_VAR, R_RCS, D_ALL, | ||
| 2188 | ADDR_FIX_1(2), 8, cmd_handler_pipe_control}, | ||
| 2189 | |||
| 2190 | {"3DPRIMITIVE", OP_3DPRIMITIVE, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2191 | |||
| 2192 | {"PIPELINE_SELECT", OP_PIPELINE_SELECT, F_LEN_CONST, R_RCS, D_ALL, 0, | ||
| 2193 | 1, NULL}, | ||
| 2194 | |||
| 2195 | {"STATE_PREFETCH", OP_STATE_PREFETCH, F_LEN_VAR, R_RCS, D_ALL, | ||
| 2196 | ADDR_FIX_1(1), 8, NULL}, | ||
| 2197 | |||
| 2198 | {"STATE_SIP", OP_STATE_SIP, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2199 | |||
| 2200 | {"STATE_BASE_ADDRESS", OP_STATE_BASE_ADDRESS, F_LEN_VAR, R_RCS, D_BDW_PLUS, | ||
| 2201 | ADDR_FIX_5(1, 3, 4, 5, 6), 8, NULL}, | ||
| 2202 | |||
| 2203 | {"OP_3D_MEDIA_0_1_4", OP_3D_MEDIA_0_1_4, F_LEN_VAR, R_RCS, D_ALL, | ||
| 2204 | ADDR_FIX_1(1), 8, NULL}, | ||
| 2205 | |||
| 2206 | {"3DSTATE_VS", OP_3DSTATE_VS, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2207 | |||
| 2208 | {"3DSTATE_SF", OP_3DSTATE_SF, F_LEN_VAR, R_RCS, D_ALL, 0, 8, NULL}, | ||
| 2209 | |||
| 2210 | {"3DSTATE_CONSTANT_VS", OP_3DSTATE_CONSTANT_VS, F_LEN_VAR, R_RCS, D_BDW_PLUS, | ||
| 2211 | 0, 8, NULL}, | ||
| 2212 | |||
| 2213 | {"3DSTATE_COMPONENT_PACKING", OP_3DSTATE_COMPONENT_PACKING, F_LEN_VAR, R_RCS, | ||
| 2214 | D_SKL_PLUS, 0, 8, NULL}, | ||
| 2215 | |||
| 2216 | {"MEDIA_INTERFACE_DESCRIPTOR_LOAD", OP_MEDIA_INTERFACE_DESCRIPTOR_LOAD, | ||
| 2217 | F_LEN_VAR, R_RCS, D_ALL, 0, 16, NULL}, | ||
| 2218 | |||
| 2219 | {"MEDIA_GATEWAY_STATE", OP_MEDIA_GATEWAY_STATE, F_LEN_VAR, R_RCS, D_ALL, | ||
| 2220 | 0, 16, NULL}, | ||
| 2221 | |||
| 2222 | {"MEDIA_STATE_FLUSH", OP_MEDIA_STATE_FLUSH, F_LEN_VAR, R_RCS, D_ALL, | ||
| 2223 | 0, 16, NULL}, | ||
| 2224 | |||
| 2225 | {"MEDIA_OBJECT", OP_MEDIA_OBJECT, F_LEN_VAR, R_RCS, D_ALL, 0, 16, NULL}, | ||
| 2226 | |||
| 2227 | {"MEDIA_CURBE_LOAD", OP_MEDIA_CURBE_LOAD, F_LEN_VAR, R_RCS, D_ALL, | ||
| 2228 | 0, 16, NULL}, | ||
| 2229 | |||
| 2230 | {"MEDIA_OBJECT_PRT", OP_MEDIA_OBJECT_PRT, F_LEN_VAR, R_RCS, D_ALL, | ||
| 2231 | 0, 16, NULL}, | ||
| 2232 | |||
| 2233 | {"MEDIA_OBJECT_WALKER", OP_MEDIA_OBJECT_WALKER, F_LEN_VAR, R_RCS, D_ALL, | ||
| 2234 | 0, 16, NULL}, | ||
| 2235 | |||
| 2236 | {"GPGPU_WALKER", OP_GPGPU_WALKER, F_LEN_VAR, R_RCS, D_ALL, | ||
| 2237 | 0, 8, NULL}, | ||
| 2238 | |||
| 2239 | {"MEDIA_VFE_STATE", OP_MEDIA_VFE_STATE, F_LEN_VAR, R_RCS, D_ALL, 0, 16, | ||
| 2240 | NULL}, | ||
| 2241 | |||
| 2242 | {"3DSTATE_VF_STATISTICS_GM45", OP_3DSTATE_VF_STATISTICS_GM45, | ||
| 2243 | F_LEN_CONST, R_ALL, D_ALL, 0, 1, NULL}, | ||
| 2244 | |||
| 2245 | {"MFX_PIPE_MODE_SELECT", OP_MFX_PIPE_MODE_SELECT, F_LEN_VAR, | ||
| 2246 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2247 | |||
| 2248 | {"MFX_SURFACE_STATE", OP_MFX_SURFACE_STATE, F_LEN_VAR, | ||
| 2249 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2250 | |||
| 2251 | {"MFX_PIPE_BUF_ADDR_STATE", OP_MFX_PIPE_BUF_ADDR_STATE, F_LEN_VAR, | ||
| 2252 | R_VCS, D_BDW_PLUS, 0, 12, NULL}, | ||
| 2253 | |||
| 2254 | {"MFX_IND_OBJ_BASE_ADDR_STATE", OP_MFX_IND_OBJ_BASE_ADDR_STATE, | ||
| 2255 | F_LEN_VAR, R_VCS, D_BDW_PLUS, 0, 12, NULL}, | ||
| 2256 | |||
| 2257 | {"MFX_BSP_BUF_BASE_ADDR_STATE", OP_MFX_BSP_BUF_BASE_ADDR_STATE, | ||
| 2258 | F_LEN_VAR, R_VCS, D_BDW_PLUS, ADDR_FIX_3(1, 3, 5), 12, NULL}, | ||
| 2259 | |||
| 2260 | {"OP_2_0_0_5", OP_2_0_0_5, F_LEN_VAR, R_VCS, D_BDW_PLUS, 0, 12, NULL}, | ||
| 2261 | |||
| 2262 | {"MFX_STATE_POINTER", OP_MFX_STATE_POINTER, F_LEN_VAR, | ||
| 2263 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2264 | |||
| 2265 | {"MFX_QM_STATE", OP_MFX_QM_STATE, F_LEN_VAR, | ||
| 2266 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2267 | |||
| 2268 | {"MFX_FQM_STATE", OP_MFX_FQM_STATE, F_LEN_VAR, | ||
| 2269 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2270 | |||
| 2271 | {"MFX_PAK_INSERT_OBJECT", OP_MFX_PAK_INSERT_OBJECT, F_LEN_VAR, | ||
| 2272 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2273 | |||
| 2274 | {"MFX_STITCH_OBJECT", OP_MFX_STITCH_OBJECT, F_LEN_VAR, | ||
| 2275 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2276 | |||
| 2277 | {"MFD_IT_OBJECT", OP_MFD_IT_OBJECT, F_LEN_VAR, | ||
| 2278 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2279 | |||
| 2280 | {"MFX_WAIT", OP_MFX_WAIT, F_LEN_VAR, | ||
| 2281 | R_VCS, D_ALL, 0, 6, NULL}, | ||
| 2282 | |||
| 2283 | {"MFX_AVC_IMG_STATE", OP_MFX_AVC_IMG_STATE, F_LEN_VAR, | ||
| 2284 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2285 | |||
| 2286 | {"MFX_AVC_QM_STATE", OP_MFX_AVC_QM_STATE, F_LEN_VAR, | ||
| 2287 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2288 | |||
| 2289 | {"MFX_AVC_DIRECTMODE_STATE", OP_MFX_AVC_DIRECTMODE_STATE, F_LEN_VAR, | ||
| 2290 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2291 | |||
| 2292 | {"MFX_AVC_SLICE_STATE", OP_MFX_AVC_SLICE_STATE, F_LEN_VAR, | ||
| 2293 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2294 | |||
| 2295 | {"MFX_AVC_REF_IDX_STATE", OP_MFX_AVC_REF_IDX_STATE, F_LEN_VAR, | ||
| 2296 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2297 | |||
| 2298 | {"MFX_AVC_WEIGHTOFFSET_STATE", OP_MFX_AVC_WEIGHTOFFSET_STATE, F_LEN_VAR, | ||
| 2299 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2300 | |||
| 2301 | {"MFD_AVC_PICID_STATE", OP_MFD_AVC_PICID_STATE, F_LEN_VAR, | ||
| 2302 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2303 | {"MFD_AVC_DPB_STATE", OP_MFD_AVC_DPB_STATE, F_LEN_VAR, | ||
| 2304 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2305 | |||
| 2306 | {"MFD_AVC_BSD_OBJECT", OP_MFD_AVC_BSD_OBJECT, F_LEN_VAR, | ||
| 2307 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2308 | |||
| 2309 | {"MFD_AVC_SLICEADDR", OP_MFD_AVC_SLICEADDR, F_LEN_VAR, | ||
| 2310 | R_VCS, D_ALL, ADDR_FIX_1(2), 12, NULL}, | ||
| 2311 | |||
| 2312 | {"MFC_AVC_PAK_OBJECT", OP_MFC_AVC_PAK_OBJECT, F_LEN_VAR, | ||
| 2313 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2314 | |||
| 2315 | {"MFX_VC1_PRED_PIPE_STATE", OP_MFX_VC1_PRED_PIPE_STATE, F_LEN_VAR, | ||
| 2316 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2317 | |||
| 2318 | {"MFX_VC1_DIRECTMODE_STATE", OP_MFX_VC1_DIRECTMODE_STATE, F_LEN_VAR, | ||
| 2319 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2320 | |||
| 2321 | {"MFD_VC1_SHORT_PIC_STATE", OP_MFD_VC1_SHORT_PIC_STATE, F_LEN_VAR, | ||
| 2322 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2323 | |||
| 2324 | {"MFD_VC1_LONG_PIC_STATE", OP_MFD_VC1_LONG_PIC_STATE, F_LEN_VAR, | ||
| 2325 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2326 | |||
| 2327 | {"MFD_VC1_BSD_OBJECT", OP_MFD_VC1_BSD_OBJECT, F_LEN_VAR, | ||
| 2328 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2329 | |||
| 2330 | {"MFC_MPEG2_SLICEGROUP_STATE", OP_MFC_MPEG2_SLICEGROUP_STATE, F_LEN_VAR, | ||
| 2331 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2332 | |||
| 2333 | {"MFC_MPEG2_PAK_OBJECT", OP_MFC_MPEG2_PAK_OBJECT, F_LEN_VAR, | ||
| 2334 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2335 | |||
| 2336 | {"MFX_MPEG2_PIC_STATE", OP_MFX_MPEG2_PIC_STATE, F_LEN_VAR, | ||
| 2337 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2338 | |||
| 2339 | {"MFX_MPEG2_QM_STATE", OP_MFX_MPEG2_QM_STATE, F_LEN_VAR, | ||
| 2340 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2341 | |||
| 2342 | {"MFD_MPEG2_BSD_OBJECT", OP_MFD_MPEG2_BSD_OBJECT, F_LEN_VAR, | ||
| 2343 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2344 | |||
| 2345 | {"MFX_2_6_0_0", OP_MFX_2_6_0_0, F_LEN_VAR, R_VCS, D_ALL, | ||
| 2346 | 0, 16, NULL}, | ||
| 2347 | |||
| 2348 | {"MFX_2_6_0_9", OP_MFX_2_6_0_9, F_LEN_VAR, R_VCS, D_ALL, 0, 16, NULL}, | ||
| 2349 | |||
| 2350 | {"MFX_2_6_0_8", OP_MFX_2_6_0_8, F_LEN_VAR, R_VCS, D_ALL, 0, 16, NULL}, | ||
| 2351 | |||
| 2352 | {"MFX_JPEG_PIC_STATE", OP_MFX_JPEG_PIC_STATE, F_LEN_VAR, | ||
| 2353 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2354 | |||
| 2355 | {"MFX_JPEG_HUFF_TABLE_STATE", OP_MFX_JPEG_HUFF_TABLE_STATE, F_LEN_VAR, | ||
| 2356 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2357 | |||
| 2358 | {"MFD_JPEG_BSD_OBJECT", OP_MFD_JPEG_BSD_OBJECT, F_LEN_VAR, | ||
| 2359 | R_VCS, D_ALL, 0, 12, NULL}, | ||
| 2360 | |||
| 2361 | {"VEBOX_STATE", OP_VEB_STATE, F_LEN_VAR, R_VECS, D_ALL, 0, 12, NULL}, | ||
| 2362 | |||
| 2363 | {"VEBOX_SURFACE_STATE", OP_VEB_SURFACE_STATE, F_LEN_VAR, R_VECS, D_ALL, | ||
| 2364 | 0, 12, NULL}, | ||
| 2365 | |||
| 2366 | {"VEB_DI_IECP", OP_VEB_DNDI_IECP_STATE, F_LEN_VAR, R_VECS, D_BDW_PLUS, | ||
| 2367 | 0, 20, NULL}, | ||
| 2368 | }; | ||
| 2369 | |||
| 2370 | static void add_cmd_entry(struct intel_gvt *gvt, struct cmd_entry *e) | ||
| 2371 | { | ||
| 2372 | hash_add(gvt->cmd_table, &e->hlist, e->info->opcode); | ||
| 2373 | } | ||
| 2374 | |||
| 2375 | #define GVT_MAX_CMD_LENGTH 20 /* In Dword */ | ||
| 2376 | |||
| 2377 | static void trace_cs_command(struct parser_exec_state *s, | ||
| 2378 | cycles_t cost_pre_cmd_handler, cycles_t cost_cmd_handler) | ||
| 2379 | { | ||
| 2380 | /* This buffer is used by ftrace to store all commands copied from | ||
| 2381 | * guest gma space. Sometimes commands can cross pages, this should | ||
| 2382 | * not be handled in ftrace logic. So this is just used as a | ||
| 2383 | * 'bounce buffer' | ||
| 2384 | */ | ||
| 2385 | u32 cmd_trace_buf[GVT_MAX_CMD_LENGTH]; | ||
| 2386 | int i; | ||
| 2387 | u32 cmd_len = cmd_length(s); | ||
| 2388 | /* The chosen value of GVT_MAX_CMD_LENGTH are just based on | ||
| 2389 | * following two considerations: | ||
| 2390 | * 1) From observation, most common ring commands is not that long. | ||
| 2391 | * But there are execeptions. So it indeed makes sence to observe | ||
| 2392 | * longer commands. | ||
| 2393 | * 2) From the performance and debugging point of view, dumping all | ||
| 2394 | * contents of very commands is not necessary. | ||
| 2395 | * We mgith shrink GVT_MAX_CMD_LENGTH or remove this trace event in | ||
| 2396 | * future for performance considerations. | ||
| 2397 | */ | ||
| 2398 | if (unlikely(cmd_len > GVT_MAX_CMD_LENGTH)) { | ||
| 2399 | gvt_dbg_cmd("cmd length exceed tracing limitation!\n"); | ||
| 2400 | cmd_len = GVT_MAX_CMD_LENGTH; | ||
| 2401 | } | ||
| 2402 | |||
| 2403 | for (i = 0; i < cmd_len; i++) | ||
| 2404 | cmd_trace_buf[i] = cmd_val(s, i); | ||
| 2405 | |||
| 2406 | trace_gvt_command(s->vgpu->id, s->ring_id, s->ip_gma, cmd_trace_buf, | ||
| 2407 | cmd_len, s->buf_type == RING_BUFFER_INSTRUCTION, | ||
| 2408 | cost_pre_cmd_handler, cost_cmd_handler); | ||
| 2409 | } | ||
| 2410 | |||
| 2411 | /* call the cmd handler, and advance ip */ | ||
| 2412 | static int cmd_parser_exec(struct parser_exec_state *s) | ||
| 2413 | { | ||
| 2414 | struct cmd_info *info; | ||
| 2415 | u32 cmd; | ||
| 2416 | int ret = 0; | ||
| 2417 | cycles_t t0, t1, t2; | ||
| 2418 | struct parser_exec_state s_before_advance_custom; | ||
| 2419 | |||
| 2420 | t0 = get_cycles(); | ||
| 2421 | |||
| 2422 | cmd = cmd_val(s, 0); | ||
| 2423 | |||
| 2424 | info = get_cmd_info(s->vgpu->gvt, cmd, s->ring_id); | ||
| 2425 | if (info == NULL) { | ||
| 2426 | gvt_err("unknown cmd 0x%x, opcode=0x%x\n", | ||
| 2427 | cmd, get_opcode(cmd, s->ring_id)); | ||
| 2428 | return -EINVAL; | ||
| 2429 | } | ||
| 2430 | |||
| 2431 | gvt_dbg_cmd("%s\n", info->name); | ||
| 2432 | |||
| 2433 | s->info = info; | ||
| 2434 | |||
| 2435 | t1 = get_cycles(); | ||
| 2436 | |||
| 2437 | memcpy(&s_before_advance_custom, s, sizeof(struct parser_exec_state)); | ||
| 2438 | |||
| 2439 | if (info->handler) { | ||
| 2440 | ret = info->handler(s); | ||
| 2441 | if (ret < 0) { | ||
| 2442 | gvt_err("%s handler error\n", info->name); | ||
| 2443 | return ret; | ||
| 2444 | } | ||
| 2445 | } | ||
| 2446 | t2 = get_cycles(); | ||
| 2447 | |||
| 2448 | trace_cs_command(&s_before_advance_custom, t1 - t0, t2 - t1); | ||
| 2449 | |||
| 2450 | if (!(info->flag & F_IP_ADVANCE_CUSTOM)) { | ||
| 2451 | ret = cmd_advance_default(s); | ||
| 2452 | if (ret) { | ||
| 2453 | gvt_err("%s IP advance error\n", info->name); | ||
| 2454 | return ret; | ||
| 2455 | } | ||
| 2456 | } | ||
| 2457 | return 0; | ||
| 2458 | } | ||
| 2459 | |||
| 2460 | static inline bool gma_out_of_range(unsigned long gma, | ||
| 2461 | unsigned long gma_head, unsigned int gma_tail) | ||
| 2462 | { | ||
| 2463 | if (gma_tail >= gma_head) | ||
| 2464 | return (gma < gma_head) || (gma > gma_tail); | ||
| 2465 | else | ||
| 2466 | return (gma > gma_tail) && (gma < gma_head); | ||
| 2467 | } | ||
| 2468 | |||
| 2469 | static int command_scan(struct parser_exec_state *s, | ||
| 2470 | unsigned long rb_head, unsigned long rb_tail, | ||
| 2471 | unsigned long rb_start, unsigned long rb_len) | ||
| 2472 | { | ||
| 2473 | |||
| 2474 | unsigned long gma_head, gma_tail, gma_bottom; | ||
| 2475 | int ret = 0; | ||
| 2476 | |||
| 2477 | gma_head = rb_start + rb_head; | ||
| 2478 | gma_tail = rb_start + rb_tail; | ||
| 2479 | gma_bottom = rb_start + rb_len; | ||
| 2480 | |||
| 2481 | gvt_dbg_cmd("scan_start: start=%lx end=%lx\n", gma_head, gma_tail); | ||
| 2482 | |||
| 2483 | while (s->ip_gma != gma_tail) { | ||
| 2484 | if (s->buf_type == RING_BUFFER_INSTRUCTION) { | ||
| 2485 | if (!(s->ip_gma >= rb_start) || | ||
| 2486 | !(s->ip_gma < gma_bottom)) { | ||
| 2487 | gvt_err("ip_gma %lx out of ring scope." | ||
| 2488 | "(base:0x%lx, bottom: 0x%lx)\n", | ||
| 2489 | s->ip_gma, rb_start, | ||
| 2490 | gma_bottom); | ||
| 2491 | parser_exec_state_dump(s); | ||
| 2492 | return -EINVAL; | ||
| 2493 | } | ||
| 2494 | if (gma_out_of_range(s->ip_gma, gma_head, gma_tail)) { | ||
| 2495 | gvt_err("ip_gma %lx out of range." | ||
| 2496 | "base 0x%lx head 0x%lx tail 0x%lx\n", | ||
| 2497 | s->ip_gma, rb_start, | ||
| 2498 | rb_head, rb_tail); | ||
| 2499 | parser_exec_state_dump(s); | ||
| 2500 | break; | ||
| 2501 | } | ||
| 2502 | } | ||
| 2503 | ret = cmd_parser_exec(s); | ||
| 2504 | if (ret) { | ||
| 2505 | gvt_err("cmd parser error\n"); | ||
| 2506 | parser_exec_state_dump(s); | ||
| 2507 | break; | ||
| 2508 | } | ||
| 2509 | } | ||
| 2510 | |||
| 2511 | gvt_dbg_cmd("scan_end\n"); | ||
| 2512 | |||
| 2513 | return ret; | ||
| 2514 | } | ||
| 2515 | |||
| 2516 | static int scan_workload(struct intel_vgpu_workload *workload) | ||
| 2517 | { | ||
| 2518 | unsigned long gma_head, gma_tail, gma_bottom; | ||
| 2519 | struct parser_exec_state s; | ||
| 2520 | int ret = 0; | ||
| 2521 | |||
| 2522 | /* ring base is page aligned */ | ||
| 2523 | if (WARN_ON(!IS_ALIGNED(workload->rb_start, GTT_PAGE_SIZE))) | ||
| 2524 | return -EINVAL; | ||
| 2525 | |||
| 2526 | gma_head = workload->rb_start + workload->rb_head; | ||
| 2527 | gma_tail = workload->rb_start + workload->rb_tail; | ||
| 2528 | gma_bottom = workload->rb_start + _RING_CTL_BUF_SIZE(workload->rb_ctl); | ||
| 2529 | |||
| 2530 | s.buf_type = RING_BUFFER_INSTRUCTION; | ||
| 2531 | s.buf_addr_type = GTT_BUFFER; | ||
| 2532 | s.vgpu = workload->vgpu; | ||
| 2533 | s.ring_id = workload->ring_id; | ||
| 2534 | s.ring_start = workload->rb_start; | ||
| 2535 | s.ring_size = _RING_CTL_BUF_SIZE(workload->rb_ctl); | ||
| 2536 | s.ring_head = gma_head; | ||
| 2537 | s.ring_tail = gma_tail; | ||
| 2538 | s.rb_va = workload->shadow_ring_buffer_va; | ||
| 2539 | s.workload = workload; | ||
| 2540 | |||
| 2541 | if (bypass_scan_mask & (1 << workload->ring_id)) | ||
| 2542 | return 0; | ||
| 2543 | |||
| 2544 | ret = ip_gma_set(&s, gma_head); | ||
| 2545 | if (ret) | ||
| 2546 | goto out; | ||
| 2547 | |||
| 2548 | ret = command_scan(&s, workload->rb_head, workload->rb_tail, | ||
| 2549 | workload->rb_start, _RING_CTL_BUF_SIZE(workload->rb_ctl)); | ||
| 2550 | |||
| 2551 | out: | ||
| 2552 | return ret; | ||
| 2553 | } | ||
| 2554 | |||
| 2555 | static int scan_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | ||
| 2556 | { | ||
| 2557 | |||
| 2558 | unsigned long gma_head, gma_tail, gma_bottom, ring_size, ring_tail; | ||
| 2559 | struct parser_exec_state s; | ||
| 2560 | int ret = 0; | ||
| 2561 | |||
| 2562 | /* ring base is page aligned */ | ||
| 2563 | if (WARN_ON(!IS_ALIGNED(wa_ctx->indirect_ctx.guest_gma, GTT_PAGE_SIZE))) | ||
| 2564 | return -EINVAL; | ||
| 2565 | |||
| 2566 | ring_tail = wa_ctx->indirect_ctx.size + 3 * sizeof(uint32_t); | ||
| 2567 | ring_size = round_up(wa_ctx->indirect_ctx.size + CACHELINE_BYTES, | ||
| 2568 | PAGE_SIZE); | ||
| 2569 | gma_head = wa_ctx->indirect_ctx.guest_gma; | ||
| 2570 | gma_tail = wa_ctx->indirect_ctx.guest_gma + ring_tail; | ||
| 2571 | gma_bottom = wa_ctx->indirect_ctx.guest_gma + ring_size; | ||
| 2572 | |||
| 2573 | s.buf_type = RING_BUFFER_INSTRUCTION; | ||
| 2574 | s.buf_addr_type = GTT_BUFFER; | ||
| 2575 | s.vgpu = wa_ctx->workload->vgpu; | ||
| 2576 | s.ring_id = wa_ctx->workload->ring_id; | ||
| 2577 | s.ring_start = wa_ctx->indirect_ctx.guest_gma; | ||
| 2578 | s.ring_size = ring_size; | ||
| 2579 | s.ring_head = gma_head; | ||
| 2580 | s.ring_tail = gma_tail; | ||
| 2581 | s.rb_va = wa_ctx->indirect_ctx.shadow_va; | ||
| 2582 | s.workload = wa_ctx->workload; | ||
| 2583 | |||
| 2584 | ret = ip_gma_set(&s, gma_head); | ||
| 2585 | if (ret) | ||
| 2586 | goto out; | ||
| 2587 | |||
| 2588 | ret = command_scan(&s, 0, ring_tail, | ||
| 2589 | wa_ctx->indirect_ctx.guest_gma, ring_size); | ||
| 2590 | out: | ||
| 2591 | return ret; | ||
| 2592 | } | ||
| 2593 | |||
| 2594 | static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload) | ||
| 2595 | { | ||
| 2596 | struct intel_vgpu *vgpu = workload->vgpu; | ||
| 2597 | int ring_id = workload->ring_id; | ||
| 2598 | struct i915_gem_context *shadow_ctx = vgpu->shadow_ctx; | ||
| 2599 | struct intel_ring *ring = shadow_ctx->engine[ring_id].ring; | ||
| 2600 | unsigned long gma_head, gma_tail, gma_top, guest_rb_size; | ||
| 2601 | unsigned int copy_len = 0; | ||
| 2602 | int ret; | ||
| 2603 | |||
| 2604 | guest_rb_size = _RING_CTL_BUF_SIZE(workload->rb_ctl); | ||
| 2605 | |||
| 2606 | /* calculate workload ring buffer size */ | ||
| 2607 | workload->rb_len = (workload->rb_tail + guest_rb_size - | ||
| 2608 | workload->rb_head) % guest_rb_size; | ||
| 2609 | |||
| 2610 | gma_head = workload->rb_start + workload->rb_head; | ||
| 2611 | gma_tail = workload->rb_start + workload->rb_tail; | ||
| 2612 | gma_top = workload->rb_start + guest_rb_size; | ||
| 2613 | |||
| 2614 | /* allocate shadow ring buffer */ | ||
| 2615 | ret = intel_ring_begin(workload->req, workload->rb_len / 4); | ||
| 2616 | if (ret) | ||
| 2617 | return ret; | ||
| 2618 | |||
| 2619 | /* get shadow ring buffer va */ | ||
| 2620 | workload->shadow_ring_buffer_va = ring->vaddr + ring->tail; | ||
| 2621 | |||
| 2622 | /* head > tail --> copy head <-> top */ | ||
| 2623 | if (gma_head > gma_tail) { | ||
| 2624 | ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm, | ||
| 2625 | gma_head, gma_top, | ||
| 2626 | workload->shadow_ring_buffer_va); | ||
| 2627 | if (ret) { | ||
| 2628 | gvt_err("fail to copy guest ring buffer\n"); | ||
| 2629 | return ret; | ||
| 2630 | } | ||
| 2631 | copy_len = gma_top - gma_head; | ||
| 2632 | gma_head = workload->rb_start; | ||
| 2633 | } | ||
| 2634 | |||
| 2635 | /* copy head or start <-> tail */ | ||
| 2636 | ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm, | ||
| 2637 | gma_head, gma_tail, | ||
| 2638 | workload->shadow_ring_buffer_va + copy_len); | ||
| 2639 | if (ret) { | ||
| 2640 | gvt_err("fail to copy guest ring buffer\n"); | ||
| 2641 | return ret; | ||
| 2642 | } | ||
| 2643 | ring->tail += workload->rb_len; | ||
| 2644 | intel_ring_advance(ring); | ||
| 2645 | return 0; | ||
| 2646 | } | ||
| 2647 | |||
| 2648 | int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) | ||
| 2649 | { | ||
| 2650 | int ret; | ||
| 2651 | |||
| 2652 | ret = shadow_workload_ring_buffer(workload); | ||
| 2653 | if (ret) { | ||
| 2654 | gvt_err("fail to shadow workload ring_buffer\n"); | ||
| 2655 | return ret; | ||
| 2656 | } | ||
| 2657 | |||
| 2658 | ret = scan_workload(workload); | ||
| 2659 | if (ret) { | ||
| 2660 | gvt_err("scan workload error\n"); | ||
| 2661 | return ret; | ||
| 2662 | } | ||
| 2663 | return 0; | ||
| 2664 | } | ||
| 2665 | |||
| 2666 | static int shadow_indirect_ctx(struct intel_shadow_wa_ctx *wa_ctx) | ||
| 2667 | { | ||
| 2668 | struct drm_device *dev = &wa_ctx->workload->vgpu->gvt->dev_priv->drm; | ||
| 2669 | int ctx_size = wa_ctx->indirect_ctx.size; | ||
| 2670 | unsigned long guest_gma = wa_ctx->indirect_ctx.guest_gma; | ||
| 2671 | struct drm_i915_gem_object *obj; | ||
| 2672 | int ret = 0; | ||
| 2673 | void *map; | ||
| 2674 | |||
| 2675 | obj = i915_gem_object_create(dev, | ||
| 2676 | roundup(ctx_size + CACHELINE_BYTES, | ||
| 2677 | PAGE_SIZE)); | ||
| 2678 | if (IS_ERR(obj)) | ||
| 2679 | return PTR_ERR(obj); | ||
| 2680 | |||
| 2681 | /* get the va of the shadow batch buffer */ | ||
| 2682 | map = i915_gem_object_pin_map(obj, I915_MAP_WB); | ||
| 2683 | if (IS_ERR(map)) { | ||
| 2684 | gvt_err("failed to vmap shadow indirect ctx\n"); | ||
| 2685 | ret = PTR_ERR(map); | ||
| 2686 | goto put_obj; | ||
| 2687 | } | ||
| 2688 | |||
| 2689 | ret = i915_gem_object_set_to_cpu_domain(obj, false); | ||
| 2690 | if (ret) { | ||
| 2691 | gvt_err("failed to set shadow indirect ctx to CPU\n"); | ||
| 2692 | goto unmap_src; | ||
| 2693 | } | ||
| 2694 | |||
| 2695 | ret = copy_gma_to_hva(wa_ctx->workload->vgpu, | ||
| 2696 | wa_ctx->workload->vgpu->gtt.ggtt_mm, | ||
| 2697 | guest_gma, guest_gma + ctx_size, | ||
| 2698 | map); | ||
| 2699 | if (ret) { | ||
| 2700 | gvt_err("fail to copy guest indirect ctx\n"); | ||
| 2701 | goto unmap_src; | ||
| 2702 | } | ||
| 2703 | |||
| 2704 | wa_ctx->indirect_ctx.obj = obj; | ||
| 2705 | wa_ctx->indirect_ctx.shadow_va = map; | ||
| 2706 | return 0; | ||
| 2707 | |||
| 2708 | unmap_src: | ||
| 2709 | i915_gem_object_unpin_map(obj); | ||
| 2710 | put_obj: | ||
| 2711 | i915_gem_object_put(wa_ctx->indirect_ctx.obj); | ||
| 2712 | return ret; | ||
| 2713 | } | ||
| 2714 | |||
| 2715 | static int combine_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | ||
| 2716 | { | ||
| 2717 | uint32_t per_ctx_start[CACHELINE_DWORDS] = {0}; | ||
| 2718 | unsigned char *bb_start_sva; | ||
| 2719 | |||
| 2720 | per_ctx_start[0] = 0x18800001; | ||
| 2721 | per_ctx_start[1] = wa_ctx->per_ctx.guest_gma; | ||
| 2722 | |||
| 2723 | bb_start_sva = (unsigned char *)wa_ctx->indirect_ctx.shadow_va + | ||
| 2724 | wa_ctx->indirect_ctx.size; | ||
| 2725 | |||
| 2726 | memcpy(bb_start_sva, per_ctx_start, CACHELINE_BYTES); | ||
| 2727 | |||
| 2728 | return 0; | ||
| 2729 | } | ||
| 2730 | |||
| 2731 | int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | ||
| 2732 | { | ||
| 2733 | int ret; | ||
| 2734 | |||
| 2735 | if (wa_ctx->indirect_ctx.size == 0) | ||
| 2736 | return 0; | ||
| 2737 | |||
| 2738 | ret = shadow_indirect_ctx(wa_ctx); | ||
| 2739 | if (ret) { | ||
| 2740 | gvt_err("fail to shadow indirect ctx\n"); | ||
| 2741 | return ret; | ||
| 2742 | } | ||
| 2743 | |||
| 2744 | combine_wa_ctx(wa_ctx); | ||
| 2745 | |||
| 2746 | ret = scan_wa_ctx(wa_ctx); | ||
| 2747 | if (ret) { | ||
| 2748 | gvt_err("scan wa ctx error\n"); | ||
| 2749 | return ret; | ||
| 2750 | } | ||
| 2751 | |||
| 2752 | return 0; | ||
| 2753 | } | ||
| 2754 | |||
| 2755 | static struct cmd_info *find_cmd_entry_any_ring(struct intel_gvt *gvt, | ||
| 2756 | unsigned int opcode, int rings) | ||
| 2757 | { | ||
| 2758 | struct cmd_info *info = NULL; | ||
| 2759 | unsigned int ring; | ||
| 2760 | |||
| 2761 | for_each_set_bit(ring, (unsigned long *)&rings, I915_NUM_ENGINES) { | ||
| 2762 | info = find_cmd_entry(gvt, opcode, ring); | ||
| 2763 | if (info) | ||
| 2764 | break; | ||
| 2765 | } | ||
| 2766 | return info; | ||
| 2767 | } | ||
| 2768 | |||
| 2769 | static int init_cmd_table(struct intel_gvt *gvt) | ||
| 2770 | { | ||
| 2771 | int i; | ||
| 2772 | struct cmd_entry *e; | ||
| 2773 | struct cmd_info *info; | ||
| 2774 | unsigned int gen_type; | ||
| 2775 | |||
| 2776 | gen_type = intel_gvt_get_device_type(gvt); | ||
| 2777 | |||
| 2778 | for (i = 0; i < ARRAY_SIZE(cmd_info); i++) { | ||
| 2779 | if (!(cmd_info[i].devices & gen_type)) | ||
| 2780 | continue; | ||
| 2781 | |||
| 2782 | e = kzalloc(sizeof(*e), GFP_KERNEL); | ||
| 2783 | if (!e) | ||
| 2784 | return -ENOMEM; | ||
| 2785 | |||
| 2786 | e->info = &cmd_info[i]; | ||
| 2787 | info = find_cmd_entry_any_ring(gvt, | ||
| 2788 | e->info->opcode, e->info->rings); | ||
| 2789 | if (info) { | ||
| 2790 | gvt_err("%s %s duplicated\n", e->info->name, | ||
| 2791 | info->name); | ||
| 2792 | return -EEXIST; | ||
| 2793 | } | ||
| 2794 | |||
| 2795 | INIT_HLIST_NODE(&e->hlist); | ||
| 2796 | add_cmd_entry(gvt, e); | ||
| 2797 | gvt_dbg_cmd("add %-30s op %04x flag %x devs %02x rings %02x\n", | ||
| 2798 | e->info->name, e->info->opcode, e->info->flag, | ||
| 2799 | e->info->devices, e->info->rings); | ||
| 2800 | } | ||
| 2801 | return 0; | ||
| 2802 | } | ||
| 2803 | |||
| 2804 | static void clean_cmd_table(struct intel_gvt *gvt) | ||
| 2805 | { | ||
| 2806 | struct hlist_node *tmp; | ||
| 2807 | struct cmd_entry *e; | ||
| 2808 | int i; | ||
| 2809 | |||
| 2810 | hash_for_each_safe(gvt->cmd_table, i, tmp, e, hlist) | ||
| 2811 | kfree(e); | ||
| 2812 | |||
| 2813 | hash_init(gvt->cmd_table); | ||
| 2814 | } | ||
| 2815 | |||
| 2816 | void intel_gvt_clean_cmd_parser(struct intel_gvt *gvt) | ||
| 2817 | { | ||
| 2818 | clean_cmd_table(gvt); | ||
| 2819 | } | ||
| 2820 | |||
| 2821 | int intel_gvt_init_cmd_parser(struct intel_gvt *gvt) | ||
| 2822 | { | ||
| 2823 | int ret; | ||
| 2824 | |||
| 2825 | ret = init_cmd_table(gvt); | ||
| 2826 | if (ret) { | ||
| 2827 | intel_gvt_clean_cmd_parser(gvt); | ||
| 2828 | return ret; | ||
| 2829 | } | ||
| 2830 | return 0; | ||
| 2831 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.h b/drivers/gpu/drm/i915/gvt/cmd_parser.h new file mode 100644 index 000000000000..bed33514103c --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Ke Yu | ||
| 25 | * Kevin Tian <kevin.tian@intel.com> | ||
| 26 | * Zhiyuan Lv <zhiyuan.lv@intel.com> | ||
| 27 | * | ||
| 28 | * Contributors: | ||
| 29 | * Min He <min.he@intel.com> | ||
| 30 | * Ping Gao <ping.a.gao@intel.com> | ||
| 31 | * Tina Zhang <tina.zhang@intel.com> | ||
| 32 | * Yulei Zhang <yulei.zhang@intel.com> | ||
| 33 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 34 | * | ||
| 35 | */ | ||
| 36 | #ifndef _GVT_CMD_PARSER_H_ | ||
| 37 | #define _GVT_CMD_PARSER_H_ | ||
| 38 | |||
| 39 | #define GVT_CMD_HASH_BITS 7 | ||
| 40 | |||
| 41 | void intel_gvt_clean_cmd_parser(struct intel_gvt *gvt); | ||
| 42 | |||
| 43 | int intel_gvt_init_cmd_parser(struct intel_gvt *gvt); | ||
| 44 | |||
| 45 | int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload); | ||
| 46 | |||
| 47 | int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx); | ||
| 48 | |||
| 49 | #endif | ||
diff --git a/drivers/gpu/drm/i915/gvt/debug.h b/drivers/gpu/drm/i915/gvt/debug.h index 7ef412be665f..68cba7bd980a 100644 --- a/drivers/gpu/drm/i915/gvt/debug.h +++ b/drivers/gpu/drm/i915/gvt/debug.h | |||
| @@ -24,11 +24,34 @@ | |||
| 24 | #ifndef __GVT_DEBUG_H__ | 24 | #ifndef __GVT_DEBUG_H__ |
| 25 | #define __GVT_DEBUG_H__ | 25 | #define __GVT_DEBUG_H__ |
| 26 | 26 | ||
| 27 | #define gvt_err(fmt, args...) \ | ||
| 28 | DRM_ERROR("gvt: "fmt, ##args) | ||
| 29 | |||
| 27 | #define gvt_dbg_core(fmt, args...) \ | 30 | #define gvt_dbg_core(fmt, args...) \ |
| 28 | DRM_DEBUG_DRIVER("gvt: core: "fmt, ##args) | 31 | DRM_DEBUG_DRIVER("gvt: core: "fmt, ##args) |
| 29 | 32 | ||
| 30 | /* | 33 | #define gvt_dbg_irq(fmt, args...) \ |
| 31 | * Other GVT debug stuff will be introduced in the GVT device model patches. | 34 | DRM_DEBUG_DRIVER("gvt: irq: "fmt, ##args) |
| 32 | */ | 35 | |
| 36 | #define gvt_dbg_mm(fmt, args...) \ | ||
| 37 | DRM_DEBUG_DRIVER("gvt: mm: "fmt, ##args) | ||
| 38 | |||
| 39 | #define gvt_dbg_mmio(fmt, args...) \ | ||
| 40 | DRM_DEBUG_DRIVER("gvt: mmio: "fmt, ##args) | ||
| 41 | |||
| 42 | #define gvt_dbg_dpy(fmt, args...) \ | ||
| 43 | DRM_DEBUG_DRIVER("gvt: dpy: "fmt, ##args) | ||
| 44 | |||
| 45 | #define gvt_dbg_el(fmt, args...) \ | ||
| 46 | DRM_DEBUG_DRIVER("gvt: el: "fmt, ##args) | ||
| 47 | |||
| 48 | #define gvt_dbg_sched(fmt, args...) \ | ||
| 49 | DRM_DEBUG_DRIVER("gvt: sched: "fmt, ##args) | ||
| 50 | |||
| 51 | #define gvt_dbg_render(fmt, args...) \ | ||
| 52 | DRM_DEBUG_DRIVER("gvt: render: "fmt, ##args) | ||
| 53 | |||
| 54 | #define gvt_dbg_cmd(fmt, args...) \ | ||
| 55 | DRM_DEBUG_DRIVER("gvt: cmd: "fmt, ##args) | ||
| 33 | 56 | ||
| 34 | #endif | 57 | #endif |
diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c new file mode 100644 index 000000000000..c0c884aeb30e --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/display.c | |||
| @@ -0,0 +1,330 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Ke Yu | ||
| 25 | * Zhiyuan Lv <zhiyuan.lv@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Terrence Xu <terrence.xu@intel.com> | ||
| 29 | * Changbin Du <changbin.du@intel.com> | ||
| 30 | * Bing Niu <bing.niu@intel.com> | ||
| 31 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 32 | * | ||
| 33 | */ | ||
| 34 | |||
| 35 | #include "i915_drv.h" | ||
| 36 | #include "gvt.h" | ||
| 37 | |||
| 38 | static int get_edp_pipe(struct intel_vgpu *vgpu) | ||
| 39 | { | ||
| 40 | u32 data = vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP); | ||
| 41 | int pipe = -1; | ||
| 42 | |||
| 43 | switch (data & TRANS_DDI_EDP_INPUT_MASK) { | ||
| 44 | case TRANS_DDI_EDP_INPUT_A_ON: | ||
| 45 | case TRANS_DDI_EDP_INPUT_A_ONOFF: | ||
| 46 | pipe = PIPE_A; | ||
| 47 | break; | ||
| 48 | case TRANS_DDI_EDP_INPUT_B_ONOFF: | ||
| 49 | pipe = PIPE_B; | ||
| 50 | break; | ||
| 51 | case TRANS_DDI_EDP_INPUT_C_ONOFF: | ||
| 52 | pipe = PIPE_C; | ||
| 53 | break; | ||
| 54 | } | ||
| 55 | return pipe; | ||
| 56 | } | ||
| 57 | |||
| 58 | static int edp_pipe_is_enabled(struct intel_vgpu *vgpu) | ||
| 59 | { | ||
| 60 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 61 | |||
| 62 | if (!(vgpu_vreg(vgpu, PIPECONF(_PIPE_EDP)) & PIPECONF_ENABLE)) | ||
| 63 | return 0; | ||
| 64 | |||
| 65 | if (!(vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP) & TRANS_DDI_FUNC_ENABLE)) | ||
| 66 | return 0; | ||
| 67 | return 1; | ||
| 68 | } | ||
| 69 | |||
| 70 | static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe) | ||
| 71 | { | ||
| 72 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 73 | |||
| 74 | if (WARN_ON(pipe < PIPE_A || pipe >= I915_MAX_PIPES)) | ||
| 75 | return -EINVAL; | ||
| 76 | |||
| 77 | if (vgpu_vreg(vgpu, PIPECONF(pipe)) & PIPECONF_ENABLE) | ||
| 78 | return 1; | ||
| 79 | |||
| 80 | if (edp_pipe_is_enabled(vgpu) && | ||
| 81 | get_edp_pipe(vgpu) == pipe) | ||
| 82 | return 1; | ||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | /* EDID with 1024x768 as its resolution */ | ||
| 87 | static unsigned char virtual_dp_monitor_edid[] = { | ||
| 88 | /*Header*/ | ||
| 89 | 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, | ||
| 90 | /* Vendor & Product Identification */ | ||
| 91 | 0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17, | ||
| 92 | /* Version & Revision */ | ||
| 93 | 0x01, 0x04, | ||
| 94 | /* Basic Display Parameters & Features */ | ||
| 95 | 0xa5, 0x34, 0x20, 0x78, 0x23, | ||
| 96 | /* Color Characteristics */ | ||
| 97 | 0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54, | ||
| 98 | /* Established Timings: maximum resolution is 1024x768 */ | ||
| 99 | 0x21, 0x08, 0x00, | ||
| 100 | /* Standard Timings. All invalid */ | ||
| 101 | 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, | ||
| 102 | 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, | ||
| 103 | /* 18 Byte Data Blocks 1: invalid */ | ||
| 104 | 0x00, 0x00, 0x80, 0xa0, 0x70, 0xb0, | ||
| 105 | 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a, | ||
| 106 | /* 18 Byte Data Blocks 2: invalid */ | ||
| 107 | 0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a, | ||
| 108 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
| 109 | /* 18 Byte Data Blocks 3: invalid */ | ||
| 110 | 0x00, 0x00, 0x00, 0xfc, 0x00, 0x48, | ||
| 111 | 0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20, | ||
| 112 | /* 18 Byte Data Blocks 4: invalid */ | ||
| 113 | 0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30, | ||
| 114 | 0x44, 0x58, 0x51, 0x0a, 0x20, 0x20, | ||
| 115 | /* Extension Block Count */ | ||
| 116 | 0x00, | ||
| 117 | /* Checksum */ | ||
| 118 | 0xef, | ||
| 119 | }; | ||
| 120 | |||
| 121 | #define DPCD_HEADER_SIZE 0xb | ||
| 122 | |||
| 123 | static u8 dpcd_fix_data[DPCD_HEADER_SIZE] = { | ||
| 124 | 0x11, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||
| 125 | }; | ||
| 126 | |||
| 127 | static void emulate_monitor_status_change(struct intel_vgpu *vgpu) | ||
| 128 | { | ||
| 129 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 130 | vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTB_HOTPLUG_CPT | | ||
| 131 | SDE_PORTC_HOTPLUG_CPT | | ||
| 132 | SDE_PORTD_HOTPLUG_CPT); | ||
| 133 | |||
| 134 | if (IS_SKYLAKE(dev_priv)) | ||
| 135 | vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT | | ||
| 136 | SDE_PORTE_HOTPLUG_SPT); | ||
| 137 | |||
| 138 | if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) | ||
| 139 | vgpu_vreg(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT; | ||
| 140 | |||
| 141 | if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) | ||
| 142 | vgpu_vreg(vgpu, SDEISR) |= SDE_PORTC_HOTPLUG_CPT; | ||
| 143 | |||
| 144 | if (intel_vgpu_has_monitor_on_port(vgpu, PORT_D)) | ||
| 145 | vgpu_vreg(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT; | ||
| 146 | |||
| 147 | if (IS_SKYLAKE(dev_priv) && | ||
| 148 | intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) { | ||
| 149 | vgpu_vreg(vgpu, SDEISR) |= SDE_PORTE_HOTPLUG_SPT; | ||
| 150 | } | ||
| 151 | |||
| 152 | if (intel_vgpu_has_monitor_on_port(vgpu, PORT_A)) { | ||
| 153 | if (IS_BROADWELL(dev_priv)) | ||
| 154 | vgpu_vreg(vgpu, GEN8_DE_PORT_ISR) |= | ||
| 155 | GEN8_PORT_DP_A_HOTPLUG; | ||
| 156 | else | ||
| 157 | vgpu_vreg(vgpu, SDEISR) |= SDE_PORTA_HOTPLUG_SPT; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | static void clean_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num) | ||
| 162 | { | ||
| 163 | struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num); | ||
| 164 | |||
| 165 | kfree(port->edid); | ||
| 166 | port->edid = NULL; | ||
| 167 | |||
| 168 | kfree(port->dpcd); | ||
| 169 | port->dpcd = NULL; | ||
| 170 | } | ||
| 171 | |||
| 172 | static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num, | ||
| 173 | int type) | ||
| 174 | { | ||
| 175 | struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num); | ||
| 176 | |||
| 177 | port->edid = kzalloc(sizeof(*(port->edid)), GFP_KERNEL); | ||
| 178 | if (!port->edid) | ||
| 179 | return -ENOMEM; | ||
| 180 | |||
| 181 | port->dpcd = kzalloc(sizeof(*(port->dpcd)), GFP_KERNEL); | ||
| 182 | if (!port->dpcd) { | ||
| 183 | kfree(port->edid); | ||
| 184 | return -ENOMEM; | ||
| 185 | } | ||
| 186 | |||
| 187 | memcpy(port->edid->edid_block, virtual_dp_monitor_edid, | ||
| 188 | EDID_SIZE); | ||
| 189 | port->edid->data_valid = true; | ||
| 190 | |||
| 191 | memcpy(port->dpcd->data, dpcd_fix_data, DPCD_HEADER_SIZE); | ||
| 192 | port->dpcd->data_valid = true; | ||
| 193 | port->dpcd->data[DPCD_SINK_COUNT] = 0x1; | ||
| 194 | port->type = type; | ||
| 195 | |||
| 196 | emulate_monitor_status_change(vgpu); | ||
| 197 | return 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | /** | ||
| 201 | * intel_gvt_check_vblank_emulation - check if vblank emulation timer should | ||
| 202 | * be turned on/off when a virtual pipe is enabled/disabled. | ||
| 203 | * @gvt: a GVT device | ||
| 204 | * | ||
| 205 | * This function is used to turn on/off vblank timer according to currently | ||
| 206 | * enabled/disabled virtual pipes. | ||
| 207 | * | ||
| 208 | */ | ||
| 209 | void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt) | ||
| 210 | { | ||
| 211 | struct intel_gvt_irq *irq = &gvt->irq; | ||
| 212 | struct intel_vgpu *vgpu; | ||
| 213 | bool have_enabled_pipe = false; | ||
| 214 | int pipe, id; | ||
| 215 | |||
| 216 | if (WARN_ON(!mutex_is_locked(&gvt->lock))) | ||
| 217 | return; | ||
| 218 | |||
| 219 | hrtimer_cancel(&irq->vblank_timer.timer); | ||
| 220 | |||
| 221 | for_each_active_vgpu(gvt, vgpu, id) { | ||
| 222 | for (pipe = 0; pipe < I915_MAX_PIPES; pipe++) { | ||
| 223 | have_enabled_pipe = | ||
| 224 | pipe_is_enabled(vgpu, pipe); | ||
| 225 | if (have_enabled_pipe) | ||
| 226 | break; | ||
| 227 | } | ||
| 228 | } | ||
| 229 | |||
| 230 | if (have_enabled_pipe) | ||
| 231 | hrtimer_start(&irq->vblank_timer.timer, | ||
| 232 | ktime_add_ns(ktime_get(), irq->vblank_timer.period), | ||
| 233 | HRTIMER_MODE_ABS); | ||
| 234 | } | ||
| 235 | |||
| 236 | static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe) | ||
| 237 | { | ||
| 238 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 239 | struct intel_vgpu_irq *irq = &vgpu->irq; | ||
| 240 | int vblank_event[] = { | ||
| 241 | [PIPE_A] = PIPE_A_VBLANK, | ||
| 242 | [PIPE_B] = PIPE_B_VBLANK, | ||
| 243 | [PIPE_C] = PIPE_C_VBLANK, | ||
| 244 | }; | ||
| 245 | int event; | ||
| 246 | |||
| 247 | if (pipe < PIPE_A || pipe > PIPE_C) | ||
| 248 | return; | ||
| 249 | |||
| 250 | for_each_set_bit(event, irq->flip_done_event[pipe], | ||
| 251 | INTEL_GVT_EVENT_MAX) { | ||
| 252 | clear_bit(event, irq->flip_done_event[pipe]); | ||
| 253 | if (!pipe_is_enabled(vgpu, pipe)) | ||
| 254 | continue; | ||
| 255 | |||
| 256 | vgpu_vreg(vgpu, PIPE_FLIPCOUNT_G4X(pipe))++; | ||
| 257 | intel_vgpu_trigger_virtual_event(vgpu, event); | ||
| 258 | } | ||
| 259 | |||
| 260 | if (pipe_is_enabled(vgpu, pipe)) { | ||
| 261 | vgpu_vreg(vgpu, PIPE_FRMCOUNT_G4X(pipe))++; | ||
| 262 | intel_vgpu_trigger_virtual_event(vgpu, vblank_event[pipe]); | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | static void emulate_vblank(struct intel_vgpu *vgpu) | ||
| 267 | { | ||
| 268 | int pipe; | ||
| 269 | |||
| 270 | for_each_pipe(vgpu->gvt->dev_priv, pipe) | ||
| 271 | emulate_vblank_on_pipe(vgpu, pipe); | ||
| 272 | } | ||
| 273 | |||
| 274 | /** | ||
| 275 | * intel_gvt_emulate_vblank - trigger vblank events for vGPUs on GVT device | ||
| 276 | * @gvt: a GVT device | ||
| 277 | * | ||
| 278 | * This function is used to trigger vblank interrupts for vGPUs on GVT device | ||
| 279 | * | ||
| 280 | */ | ||
| 281 | void intel_gvt_emulate_vblank(struct intel_gvt *gvt) | ||
| 282 | { | ||
| 283 | struct intel_vgpu *vgpu; | ||
| 284 | int id; | ||
| 285 | |||
| 286 | if (WARN_ON(!mutex_is_locked(&gvt->lock))) | ||
| 287 | return; | ||
| 288 | |||
| 289 | for_each_active_vgpu(gvt, vgpu, id) | ||
| 290 | emulate_vblank(vgpu); | ||
| 291 | } | ||
| 292 | |||
| 293 | /** | ||
| 294 | * intel_vgpu_clean_display - clean vGPU virtual display emulation | ||
| 295 | * @vgpu: a vGPU | ||
| 296 | * | ||
| 297 | * This function is used to clean vGPU virtual display emulation stuffs | ||
| 298 | * | ||
| 299 | */ | ||
| 300 | void intel_vgpu_clean_display(struct intel_vgpu *vgpu) | ||
| 301 | { | ||
| 302 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 303 | |||
| 304 | if (IS_SKYLAKE(dev_priv)) | ||
| 305 | clean_virtual_dp_monitor(vgpu, PORT_D); | ||
| 306 | else | ||
| 307 | clean_virtual_dp_monitor(vgpu, PORT_B); | ||
| 308 | } | ||
| 309 | |||
| 310 | /** | ||
| 311 | * intel_vgpu_init_display- initialize vGPU virtual display emulation | ||
| 312 | * @vgpu: a vGPU | ||
| 313 | * | ||
| 314 | * This function is used to initialize vGPU virtual display emulation stuffs | ||
| 315 | * | ||
| 316 | * Returns: | ||
| 317 | * Zero on success, negative error code if failed. | ||
| 318 | * | ||
| 319 | */ | ||
| 320 | int intel_vgpu_init_display(struct intel_vgpu *vgpu) | ||
| 321 | { | ||
| 322 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 323 | |||
| 324 | intel_vgpu_init_i2c_edid(vgpu); | ||
| 325 | |||
| 326 | if (IS_SKYLAKE(dev_priv)) | ||
| 327 | return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D); | ||
| 328 | else | ||
| 329 | return setup_virtual_dp_monitor(vgpu, PORT_B, GVT_DP_B); | ||
| 330 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/display.h b/drivers/gpu/drm/i915/gvt/display.h new file mode 100644 index 000000000000..7a60cb848268 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/display.h | |||
| @@ -0,0 +1,163 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Ke Yu | ||
| 25 | * Zhiyuan Lv <zhiyuan.lv@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Terrence Xu <terrence.xu@intel.com> | ||
| 29 | * Changbin Du <changbin.du@intel.com> | ||
| 30 | * Bing Niu <bing.niu@intel.com> | ||
| 31 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 32 | * | ||
| 33 | */ | ||
| 34 | |||
| 35 | #ifndef _GVT_DISPLAY_H_ | ||
| 36 | #define _GVT_DISPLAY_H_ | ||
| 37 | |||
| 38 | #define SBI_REG_MAX 20 | ||
| 39 | #define DPCD_SIZE 0x700 | ||
| 40 | |||
| 41 | #define intel_vgpu_port(vgpu, port) \ | ||
| 42 | (&(vgpu->display.ports[port])) | ||
| 43 | |||
| 44 | #define intel_vgpu_has_monitor_on_port(vgpu, port) \ | ||
| 45 | (intel_vgpu_port(vgpu, port)->edid && \ | ||
| 46 | intel_vgpu_port(vgpu, port)->edid->data_valid) | ||
| 47 | |||
| 48 | #define intel_vgpu_port_is_dp(vgpu, port) \ | ||
| 49 | ((intel_vgpu_port(vgpu, port)->type == GVT_DP_A) || \ | ||
| 50 | (intel_vgpu_port(vgpu, port)->type == GVT_DP_B) || \ | ||
| 51 | (intel_vgpu_port(vgpu, port)->type == GVT_DP_C) || \ | ||
| 52 | (intel_vgpu_port(vgpu, port)->type == GVT_DP_D)) | ||
| 53 | |||
| 54 | #define INTEL_GVT_MAX_UEVENT_VARS 3 | ||
| 55 | |||
| 56 | /* DPCD start */ | ||
| 57 | #define DPCD_SIZE 0x700 | ||
| 58 | |||
| 59 | /* DPCD */ | ||
| 60 | #define DP_SET_POWER 0x600 | ||
| 61 | #define DP_SET_POWER_D0 0x1 | ||
| 62 | #define AUX_NATIVE_WRITE 0x8 | ||
| 63 | #define AUX_NATIVE_READ 0x9 | ||
| 64 | |||
| 65 | #define AUX_NATIVE_REPLY_MASK (0x3 << 4) | ||
| 66 | #define AUX_NATIVE_REPLY_ACK (0x0 << 4) | ||
| 67 | #define AUX_NATIVE_REPLY_NAK (0x1 << 4) | ||
| 68 | #define AUX_NATIVE_REPLY_DEFER (0x2 << 4) | ||
| 69 | |||
| 70 | #define AUX_BURST_SIZE 16 | ||
| 71 | |||
| 72 | /* DPCD addresses */ | ||
| 73 | #define DPCD_REV 0x000 | ||
| 74 | #define DPCD_MAX_LINK_RATE 0x001 | ||
| 75 | #define DPCD_MAX_LANE_COUNT 0x002 | ||
| 76 | |||
| 77 | #define DPCD_TRAINING_PATTERN_SET 0x102 | ||
| 78 | #define DPCD_SINK_COUNT 0x200 | ||
| 79 | #define DPCD_LANE0_1_STATUS 0x202 | ||
| 80 | #define DPCD_LANE2_3_STATUS 0x203 | ||
| 81 | #define DPCD_LANE_ALIGN_STATUS_UPDATED 0x204 | ||
| 82 | #define DPCD_SINK_STATUS 0x205 | ||
| 83 | |||
| 84 | /* link training */ | ||
| 85 | #define DPCD_TRAINING_PATTERN_SET_MASK 0x03 | ||
| 86 | #define DPCD_LINK_TRAINING_DISABLED 0x00 | ||
| 87 | #define DPCD_TRAINING_PATTERN_1 0x01 | ||
| 88 | #define DPCD_TRAINING_PATTERN_2 0x02 | ||
| 89 | |||
| 90 | #define DPCD_CP_READY_MASK (1 << 6) | ||
| 91 | |||
| 92 | /* lane status */ | ||
| 93 | #define DPCD_LANES_CR_DONE 0x11 | ||
| 94 | #define DPCD_LANES_EQ_DONE 0x22 | ||
| 95 | #define DPCD_SYMBOL_LOCKED 0x44 | ||
| 96 | |||
| 97 | #define DPCD_INTERLANE_ALIGN_DONE 0x01 | ||
| 98 | |||
| 99 | #define DPCD_SINK_IN_SYNC 0x03 | ||
| 100 | /* DPCD end */ | ||
| 101 | |||
| 102 | #define SBI_RESPONSE_MASK 0x3 | ||
| 103 | #define SBI_RESPONSE_SHIFT 0x1 | ||
| 104 | #define SBI_STAT_MASK 0x1 | ||
| 105 | #define SBI_STAT_SHIFT 0x0 | ||
| 106 | #define SBI_OPCODE_SHIFT 8 | ||
| 107 | #define SBI_OPCODE_MASK (0xff << SBI_OPCODE_SHIFT) | ||
| 108 | #define SBI_CMD_IORD 2 | ||
| 109 | #define SBI_CMD_IOWR 3 | ||
| 110 | #define SBI_CMD_CRRD 6 | ||
| 111 | #define SBI_CMD_CRWR 7 | ||
| 112 | #define SBI_ADDR_OFFSET_SHIFT 16 | ||
| 113 | #define SBI_ADDR_OFFSET_MASK (0xffff << SBI_ADDR_OFFSET_SHIFT) | ||
| 114 | |||
| 115 | struct intel_vgpu_sbi_register { | ||
| 116 | unsigned int offset; | ||
| 117 | u32 value; | ||
| 118 | }; | ||
| 119 | |||
| 120 | struct intel_vgpu_sbi { | ||
| 121 | int number; | ||
| 122 | struct intel_vgpu_sbi_register registers[SBI_REG_MAX]; | ||
| 123 | }; | ||
| 124 | |||
| 125 | enum intel_gvt_plane_type { | ||
| 126 | PRIMARY_PLANE = 0, | ||
| 127 | CURSOR_PLANE, | ||
| 128 | SPRITE_PLANE, | ||
| 129 | MAX_PLANE | ||
| 130 | }; | ||
| 131 | |||
| 132 | struct intel_vgpu_dpcd_data { | ||
| 133 | bool data_valid; | ||
| 134 | u8 data[DPCD_SIZE]; | ||
| 135 | }; | ||
| 136 | |||
| 137 | enum intel_vgpu_port_type { | ||
| 138 | GVT_CRT = 0, | ||
| 139 | GVT_DP_A, | ||
| 140 | GVT_DP_B, | ||
| 141 | GVT_DP_C, | ||
| 142 | GVT_DP_D, | ||
| 143 | GVT_HDMI_B, | ||
| 144 | GVT_HDMI_C, | ||
| 145 | GVT_HDMI_D, | ||
| 146 | GVT_PORT_MAX | ||
| 147 | }; | ||
| 148 | |||
| 149 | struct intel_vgpu_port { | ||
| 150 | /* per display EDID information */ | ||
| 151 | struct intel_vgpu_edid_data *edid; | ||
| 152 | /* per display DPCD information */ | ||
| 153 | struct intel_vgpu_dpcd_data *dpcd; | ||
| 154 | int type; | ||
| 155 | }; | ||
| 156 | |||
| 157 | void intel_gvt_emulate_vblank(struct intel_gvt *gvt); | ||
| 158 | void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt); | ||
| 159 | |||
| 160 | int intel_vgpu_init_display(struct intel_vgpu *vgpu); | ||
| 161 | void intel_vgpu_clean_display(struct intel_vgpu *vgpu); | ||
| 162 | |||
| 163 | #endif | ||
diff --git a/drivers/gpu/drm/i915/gvt/edid.c b/drivers/gpu/drm/i915/gvt/edid.c new file mode 100644 index 000000000000..7e1da1c563ca --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/edid.c | |||
| @@ -0,0 +1,532 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Ke Yu | ||
| 25 | * Zhiyuan Lv <zhiyuan.lv@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Terrence Xu <terrence.xu@intel.com> | ||
| 29 | * Changbin Du <changbin.du@intel.com> | ||
| 30 | * Bing Niu <bing.niu@intel.com> | ||
| 31 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 32 | * | ||
| 33 | */ | ||
| 34 | |||
| 35 | #include "i915_drv.h" | ||
| 36 | #include "gvt.h" | ||
| 37 | |||
| 38 | #define GMBUS1_TOTAL_BYTES_SHIFT 16 | ||
| 39 | #define GMBUS1_TOTAL_BYTES_MASK 0x1ff | ||
| 40 | #define gmbus1_total_byte_count(v) (((v) >> \ | ||
| 41 | GMBUS1_TOTAL_BYTES_SHIFT) & GMBUS1_TOTAL_BYTES_MASK) | ||
| 42 | #define gmbus1_slave_addr(v) (((v) & 0xff) >> 1) | ||
| 43 | #define gmbus1_slave_index(v) (((v) >> 8) & 0xff) | ||
| 44 | #define gmbus1_bus_cycle(v) (((v) >> 25) & 0x7) | ||
| 45 | |||
| 46 | /* GMBUS0 bits definitions */ | ||
| 47 | #define _GMBUS_PIN_SEL_MASK (0x7) | ||
| 48 | |||
| 49 | static unsigned char edid_get_byte(struct intel_vgpu *vgpu) | ||
| 50 | { | ||
| 51 | struct intel_vgpu_i2c_edid *edid = &vgpu->display.i2c_edid; | ||
| 52 | unsigned char chr = 0; | ||
| 53 | |||
| 54 | if (edid->state == I2C_NOT_SPECIFIED || !edid->slave_selected) { | ||
| 55 | gvt_err("Driver tries to read EDID without proper sequence!\n"); | ||
| 56 | return 0; | ||
| 57 | } | ||
| 58 | if (edid->current_edid_read >= EDID_SIZE) { | ||
| 59 | gvt_err("edid_get_byte() exceeds the size of EDID!\n"); | ||
| 60 | return 0; | ||
| 61 | } | ||
| 62 | |||
| 63 | if (!edid->edid_available) { | ||
| 64 | gvt_err("Reading EDID but EDID is not available!\n"); | ||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | if (intel_vgpu_has_monitor_on_port(vgpu, edid->port)) { | ||
| 69 | struct intel_vgpu_edid_data *edid_data = | ||
| 70 | intel_vgpu_port(vgpu, edid->port)->edid; | ||
| 71 | |||
| 72 | chr = edid_data->edid_block[edid->current_edid_read]; | ||
| 73 | edid->current_edid_read++; | ||
| 74 | } else { | ||
| 75 | gvt_err("No EDID available during the reading?\n"); | ||
| 76 | } | ||
| 77 | return chr; | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline int get_port_from_gmbus0(u32 gmbus0) | ||
| 81 | { | ||
| 82 | int port_select = gmbus0 & _GMBUS_PIN_SEL_MASK; | ||
| 83 | int port = -EINVAL; | ||
| 84 | |||
| 85 | if (port_select == 2) | ||
| 86 | port = PORT_E; | ||
| 87 | else if (port_select == 4) | ||
| 88 | port = PORT_C; | ||
| 89 | else if (port_select == 5) | ||
| 90 | port = PORT_B; | ||
| 91 | else if (port_select == 6) | ||
| 92 | port = PORT_D; | ||
| 93 | return port; | ||
| 94 | } | ||
| 95 | |||
| 96 | static void reset_gmbus_controller(struct intel_vgpu *vgpu) | ||
| 97 | { | ||
| 98 | vgpu_vreg(vgpu, PCH_GMBUS2) = GMBUS_HW_RDY; | ||
| 99 | if (!vgpu->display.i2c_edid.edid_available) | ||
| 100 | vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_SATOER; | ||
| 101 | vgpu->display.i2c_edid.gmbus.phase = GMBUS_IDLE_PHASE; | ||
| 102 | } | ||
| 103 | |||
| 104 | /* GMBUS0 */ | ||
| 105 | static int gmbus0_mmio_write(struct intel_vgpu *vgpu, | ||
| 106 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 107 | { | ||
| 108 | int port, pin_select; | ||
| 109 | |||
| 110 | memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes); | ||
| 111 | |||
| 112 | pin_select = vgpu_vreg(vgpu, offset) & _GMBUS_PIN_SEL_MASK; | ||
| 113 | |||
| 114 | intel_vgpu_init_i2c_edid(vgpu); | ||
| 115 | |||
| 116 | if (pin_select == 0) | ||
| 117 | return 0; | ||
| 118 | |||
| 119 | port = get_port_from_gmbus0(pin_select); | ||
| 120 | if (WARN_ON(port < 0)) | ||
| 121 | return 0; | ||
| 122 | |||
| 123 | vgpu->display.i2c_edid.state = I2C_GMBUS; | ||
| 124 | vgpu->display.i2c_edid.gmbus.phase = GMBUS_IDLE_PHASE; | ||
| 125 | |||
| 126 | vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_ACTIVE; | ||
| 127 | vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_HW_RDY | GMBUS_HW_WAIT_PHASE; | ||
| 128 | |||
| 129 | if (intel_vgpu_has_monitor_on_port(vgpu, port) && | ||
| 130 | !intel_vgpu_port_is_dp(vgpu, port)) { | ||
| 131 | vgpu->display.i2c_edid.port = port; | ||
| 132 | vgpu->display.i2c_edid.edid_available = true; | ||
| 133 | vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_SATOER; | ||
| 134 | } else | ||
| 135 | vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_SATOER; | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | |||
| 139 | static int gmbus1_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 140 | void *p_data, unsigned int bytes) | ||
| 141 | { | ||
| 142 | struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid; | ||
| 143 | u32 slave_addr; | ||
| 144 | u32 wvalue = *(u32 *)p_data; | ||
| 145 | |||
| 146 | if (vgpu_vreg(vgpu, offset) & GMBUS_SW_CLR_INT) { | ||
| 147 | if (!(wvalue & GMBUS_SW_CLR_INT)) { | ||
| 148 | vgpu_vreg(vgpu, offset) &= ~GMBUS_SW_CLR_INT; | ||
| 149 | reset_gmbus_controller(vgpu); | ||
| 150 | } | ||
| 151 | /* | ||
| 152 | * TODO: "This bit is cleared to zero when an event | ||
| 153 | * causes the HW_RDY bit transition to occur " | ||
| 154 | */ | ||
| 155 | } else { | ||
| 156 | /* | ||
| 157 | * per bspec setting this bit can cause: | ||
| 158 | * 1) INT status bit cleared | ||
| 159 | * 2) HW_RDY bit asserted | ||
| 160 | */ | ||
| 161 | if (wvalue & GMBUS_SW_CLR_INT) { | ||
| 162 | vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_INT; | ||
| 163 | vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_HW_RDY; | ||
| 164 | } | ||
| 165 | |||
| 166 | /* For virtualization, we suppose that HW is always ready, | ||
| 167 | * so GMBUS_SW_RDY should always be cleared | ||
| 168 | */ | ||
| 169 | if (wvalue & GMBUS_SW_RDY) | ||
| 170 | wvalue &= ~GMBUS_SW_RDY; | ||
| 171 | |||
| 172 | i2c_edid->gmbus.total_byte_count = | ||
| 173 | gmbus1_total_byte_count(wvalue); | ||
| 174 | slave_addr = gmbus1_slave_addr(wvalue); | ||
| 175 | |||
| 176 | /* vgpu gmbus only support EDID */ | ||
| 177 | if (slave_addr == EDID_ADDR) { | ||
| 178 | i2c_edid->slave_selected = true; | ||
| 179 | } else if (slave_addr != 0) { | ||
| 180 | gvt_dbg_dpy( | ||
| 181 | "vgpu%d: unsupported gmbus slave addr(0x%x)\n" | ||
| 182 | " gmbus operations will be ignored.\n", | ||
| 183 | vgpu->id, slave_addr); | ||
| 184 | } | ||
| 185 | |||
| 186 | if (wvalue & GMBUS_CYCLE_INDEX) | ||
| 187 | i2c_edid->current_edid_read = | ||
| 188 | gmbus1_slave_index(wvalue); | ||
| 189 | |||
| 190 | i2c_edid->gmbus.cycle_type = gmbus1_bus_cycle(wvalue); | ||
| 191 | switch (gmbus1_bus_cycle(wvalue)) { | ||
| 192 | case GMBUS_NOCYCLE: | ||
| 193 | break; | ||
| 194 | case GMBUS_STOP: | ||
| 195 | /* From spec: | ||
| 196 | * This can only cause a STOP to be generated | ||
| 197 | * if a GMBUS cycle is generated, the GMBUS is | ||
| 198 | * currently in a data/wait/idle phase, or it is in a | ||
| 199 | * WAIT phase | ||
| 200 | */ | ||
| 201 | if (gmbus1_bus_cycle(vgpu_vreg(vgpu, offset)) | ||
| 202 | != GMBUS_NOCYCLE) { | ||
| 203 | intel_vgpu_init_i2c_edid(vgpu); | ||
| 204 | /* After the 'stop' cycle, hw state would become | ||
| 205 | * 'stop phase' and then 'idle phase' after a | ||
| 206 | * few milliseconds. In emulation, we just set | ||
| 207 | * it as 'idle phase' ('stop phase' is not | ||
| 208 | * visible in gmbus interface) | ||
| 209 | */ | ||
| 210 | i2c_edid->gmbus.phase = GMBUS_IDLE_PHASE; | ||
| 211 | vgpu_vreg(vgpu, PCH_GMBUS2) &= ~GMBUS_ACTIVE; | ||
| 212 | } | ||
| 213 | break; | ||
| 214 | case NIDX_NS_W: | ||
| 215 | case IDX_NS_W: | ||
| 216 | case NIDX_STOP: | ||
| 217 | case IDX_STOP: | ||
| 218 | /* From hw spec the GMBUS phase | ||
| 219 | * transition like this: | ||
| 220 | * START (-->INDEX) -->DATA | ||
| 221 | */ | ||
| 222 | i2c_edid->gmbus.phase = GMBUS_DATA_PHASE; | ||
| 223 | vgpu_vreg(vgpu, PCH_GMBUS2) |= GMBUS_ACTIVE; | ||
| 224 | break; | ||
| 225 | default: | ||
| 226 | gvt_err("Unknown/reserved GMBUS cycle detected!\n"); | ||
| 227 | break; | ||
| 228 | } | ||
| 229 | /* | ||
| 230 | * From hw spec the WAIT state will be | ||
| 231 | * cleared: | ||
| 232 | * (1) in a new GMBUS cycle | ||
| 233 | * (2) by generating a stop | ||
| 234 | */ | ||
| 235 | vgpu_vreg(vgpu, offset) = wvalue; | ||
| 236 | } | ||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | static int gmbus3_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 241 | void *p_data, unsigned int bytes) | ||
| 242 | { | ||
| 243 | WARN_ON(1); | ||
| 244 | return 0; | ||
| 245 | } | ||
| 246 | |||
| 247 | static int gmbus3_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 248 | void *p_data, unsigned int bytes) | ||
| 249 | { | ||
| 250 | int i; | ||
| 251 | unsigned char byte_data; | ||
| 252 | struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid; | ||
| 253 | int byte_left = i2c_edid->gmbus.total_byte_count - | ||
| 254 | i2c_edid->current_edid_read; | ||
| 255 | int byte_count = byte_left; | ||
| 256 | u32 reg_data = 0; | ||
| 257 | |||
| 258 | /* Data can only be recevied if previous settings correct */ | ||
| 259 | if (vgpu_vreg(vgpu, PCH_GMBUS1) & GMBUS_SLAVE_READ) { | ||
| 260 | if (byte_left <= 0) { | ||
| 261 | memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); | ||
| 262 | return 0; | ||
| 263 | } | ||
| 264 | |||
| 265 | if (byte_count > 4) | ||
| 266 | byte_count = 4; | ||
| 267 | for (i = 0; i < byte_count; i++) { | ||
| 268 | byte_data = edid_get_byte(vgpu); | ||
| 269 | reg_data |= (byte_data << (i << 3)); | ||
| 270 | } | ||
| 271 | |||
| 272 | memcpy(&vgpu_vreg(vgpu, offset), ®_data, byte_count); | ||
| 273 | memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); | ||
| 274 | |||
| 275 | if (byte_left <= 4) { | ||
| 276 | switch (i2c_edid->gmbus.cycle_type) { | ||
| 277 | case NIDX_STOP: | ||
| 278 | case IDX_STOP: | ||
| 279 | i2c_edid->gmbus.phase = GMBUS_IDLE_PHASE; | ||
| 280 | break; | ||
| 281 | case NIDX_NS_W: | ||
| 282 | case IDX_NS_W: | ||
| 283 | default: | ||
| 284 | i2c_edid->gmbus.phase = GMBUS_WAIT_PHASE; | ||
| 285 | break; | ||
| 286 | } | ||
| 287 | intel_vgpu_init_i2c_edid(vgpu); | ||
| 288 | } | ||
| 289 | /* | ||
| 290 | * Read GMBUS3 during send operation, | ||
| 291 | * return the latest written value | ||
| 292 | */ | ||
| 293 | } else { | ||
| 294 | memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); | ||
| 295 | gvt_err("vgpu%d: warning: gmbus3 read with nothing returned\n", | ||
| 296 | vgpu->id); | ||
| 297 | } | ||
| 298 | return 0; | ||
| 299 | } | ||
| 300 | |||
| 301 | static int gmbus2_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 302 | void *p_data, unsigned int bytes) | ||
| 303 | { | ||
| 304 | u32 value = vgpu_vreg(vgpu, offset); | ||
| 305 | |||
| 306 | if (!(vgpu_vreg(vgpu, offset) & GMBUS_INUSE)) | ||
| 307 | vgpu_vreg(vgpu, offset) |= GMBUS_INUSE; | ||
| 308 | memcpy(p_data, (void *)&value, bytes); | ||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | static int gmbus2_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 313 | void *p_data, unsigned int bytes) | ||
| 314 | { | ||
| 315 | u32 wvalue = *(u32 *)p_data; | ||
| 316 | |||
| 317 | if (wvalue & GMBUS_INUSE) | ||
| 318 | vgpu_vreg(vgpu, offset) &= ~GMBUS_INUSE; | ||
| 319 | /* All other bits are read-only */ | ||
| 320 | return 0; | ||
| 321 | } | ||
| 322 | |||
| 323 | /** | ||
| 324 | * intel_gvt_i2c_handle_gmbus_read - emulate gmbus register mmio read | ||
| 325 | * @vgpu: a vGPU | ||
| 326 | * | ||
| 327 | * This function is used to emulate gmbus register mmio read | ||
| 328 | * | ||
| 329 | * Returns: | ||
| 330 | * Zero on success, negative error code if failed. | ||
| 331 | * | ||
| 332 | */ | ||
| 333 | int intel_gvt_i2c_handle_gmbus_read(struct intel_vgpu *vgpu, | ||
| 334 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 335 | { | ||
| 336 | if (WARN_ON(bytes > 8 && (offset & (bytes - 1)))) | ||
| 337 | return -EINVAL; | ||
| 338 | |||
| 339 | if (offset == i915_mmio_reg_offset(PCH_GMBUS2)) | ||
| 340 | return gmbus2_mmio_read(vgpu, offset, p_data, bytes); | ||
| 341 | else if (offset == i915_mmio_reg_offset(PCH_GMBUS3)) | ||
| 342 | return gmbus3_mmio_read(vgpu, offset, p_data, bytes); | ||
| 343 | |||
| 344 | memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); | ||
| 345 | return 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | /** | ||
| 349 | * intel_gvt_i2c_handle_gmbus_write - emulate gmbus register mmio write | ||
| 350 | * @vgpu: a vGPU | ||
| 351 | * | ||
| 352 | * This function is used to emulate gmbus register mmio write | ||
| 353 | * | ||
| 354 | * Returns: | ||
| 355 | * Zero on success, negative error code if failed. | ||
| 356 | * | ||
| 357 | */ | ||
| 358 | int intel_gvt_i2c_handle_gmbus_write(struct intel_vgpu *vgpu, | ||
| 359 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 360 | { | ||
| 361 | if (WARN_ON(bytes > 8 && (offset & (bytes - 1)))) | ||
| 362 | return -EINVAL; | ||
| 363 | |||
| 364 | if (offset == i915_mmio_reg_offset(PCH_GMBUS0)) | ||
| 365 | return gmbus0_mmio_write(vgpu, offset, p_data, bytes); | ||
| 366 | else if (offset == i915_mmio_reg_offset(PCH_GMBUS1)) | ||
| 367 | return gmbus1_mmio_write(vgpu, offset, p_data, bytes); | ||
| 368 | else if (offset == i915_mmio_reg_offset(PCH_GMBUS2)) | ||
| 369 | return gmbus2_mmio_write(vgpu, offset, p_data, bytes); | ||
| 370 | else if (offset == i915_mmio_reg_offset(PCH_GMBUS3)) | ||
| 371 | return gmbus3_mmio_write(vgpu, offset, p_data, bytes); | ||
| 372 | |||
| 373 | memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes); | ||
| 374 | return 0; | ||
| 375 | } | ||
| 376 | |||
| 377 | enum { | ||
| 378 | AUX_CH_CTL = 0, | ||
| 379 | AUX_CH_DATA1, | ||
| 380 | AUX_CH_DATA2, | ||
| 381 | AUX_CH_DATA3, | ||
| 382 | AUX_CH_DATA4, | ||
| 383 | AUX_CH_DATA5 | ||
| 384 | }; | ||
| 385 | |||
| 386 | static inline int get_aux_ch_reg(unsigned int offset) | ||
| 387 | { | ||
| 388 | int reg; | ||
| 389 | |||
| 390 | switch (offset & 0xff) { | ||
| 391 | case 0x10: | ||
| 392 | reg = AUX_CH_CTL; | ||
| 393 | break; | ||
| 394 | case 0x14: | ||
| 395 | reg = AUX_CH_DATA1; | ||
| 396 | break; | ||
| 397 | case 0x18: | ||
| 398 | reg = AUX_CH_DATA2; | ||
| 399 | break; | ||
| 400 | case 0x1c: | ||
| 401 | reg = AUX_CH_DATA3; | ||
| 402 | break; | ||
| 403 | case 0x20: | ||
| 404 | reg = AUX_CH_DATA4; | ||
| 405 | break; | ||
| 406 | case 0x24: | ||
| 407 | reg = AUX_CH_DATA5; | ||
| 408 | break; | ||
| 409 | default: | ||
| 410 | reg = -1; | ||
| 411 | break; | ||
| 412 | } | ||
| 413 | return reg; | ||
| 414 | } | ||
| 415 | |||
| 416 | #define AUX_CTL_MSG_LENGTH(reg) \ | ||
| 417 | ((reg & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >> \ | ||
| 418 | DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | ||
| 419 | |||
| 420 | /** | ||
| 421 | * intel_gvt_i2c_handle_aux_ch_write - emulate AUX channel register write | ||
| 422 | * @vgpu: a vGPU | ||
| 423 | * | ||
| 424 | * This function is used to emulate AUX channel register write | ||
| 425 | * | ||
| 426 | */ | ||
| 427 | void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu, | ||
| 428 | int port_idx, | ||
| 429 | unsigned int offset, | ||
| 430 | void *p_data) | ||
| 431 | { | ||
| 432 | struct intel_vgpu_i2c_edid *i2c_edid = &vgpu->display.i2c_edid; | ||
| 433 | int msg_length, ret_msg_size; | ||
| 434 | int msg, addr, ctrl, op; | ||
| 435 | u32 value = *(u32 *)p_data; | ||
| 436 | int aux_data_for_write = 0; | ||
| 437 | int reg = get_aux_ch_reg(offset); | ||
| 438 | |||
| 439 | if (reg != AUX_CH_CTL) { | ||
| 440 | vgpu_vreg(vgpu, offset) = value; | ||
| 441 | return; | ||
| 442 | } | ||
| 443 | |||
| 444 | msg_length = AUX_CTL_MSG_LENGTH(value); | ||
| 445 | // check the msg in DATA register. | ||
| 446 | msg = vgpu_vreg(vgpu, offset + 4); | ||
| 447 | addr = (msg >> 8) & 0xffff; | ||
| 448 | ctrl = (msg >> 24) & 0xff; | ||
| 449 | op = ctrl >> 4; | ||
| 450 | if (!(value & DP_AUX_CH_CTL_SEND_BUSY)) { | ||
| 451 | /* The ctl write to clear some states */ | ||
| 452 | return; | ||
| 453 | } | ||
| 454 | |||
| 455 | /* Always set the wanted value for vms. */ | ||
| 456 | ret_msg_size = (((op & 0x1) == GVT_AUX_I2C_READ) ? 2 : 1); | ||
| 457 | vgpu_vreg(vgpu, offset) = | ||
| 458 | DP_AUX_CH_CTL_DONE | | ||
| 459 | ((ret_msg_size << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) & | ||
| 460 | DP_AUX_CH_CTL_MESSAGE_SIZE_MASK); | ||
| 461 | |||
| 462 | if (msg_length == 3) { | ||
| 463 | if (!(op & GVT_AUX_I2C_MOT)) { | ||
| 464 | /* stop */ | ||
| 465 | intel_vgpu_init_i2c_edid(vgpu); | ||
| 466 | } else { | ||
| 467 | /* start or restart */ | ||
| 468 | i2c_edid->aux_ch.i2c_over_aux_ch = true; | ||
| 469 | i2c_edid->aux_ch.aux_ch_mot = true; | ||
| 470 | if (addr == 0) { | ||
| 471 | /* reset the address */ | ||
| 472 | intel_vgpu_init_i2c_edid(vgpu); | ||
| 473 | } else if (addr == EDID_ADDR) { | ||
| 474 | i2c_edid->state = I2C_AUX_CH; | ||
| 475 | i2c_edid->port = port_idx; | ||
| 476 | i2c_edid->slave_selected = true; | ||
| 477 | if (intel_vgpu_has_monitor_on_port(vgpu, | ||
| 478 | port_idx) && | ||
| 479 | intel_vgpu_port_is_dp(vgpu, port_idx)) | ||
| 480 | i2c_edid->edid_available = true; | ||
| 481 | } | ||
| 482 | } | ||
| 483 | } else if ((op & 0x1) == GVT_AUX_I2C_WRITE) { | ||
| 484 | /* TODO | ||
| 485 | * We only support EDID reading from I2C_over_AUX. And | ||
| 486 | * we do not expect the index mode to be used. Right now | ||
| 487 | * the WRITE operation is ignored. It is good enough to | ||
| 488 | * support the gfx driver to do EDID access. | ||
| 489 | */ | ||
| 490 | } else { | ||
| 491 | if (WARN_ON((op & 0x1) != GVT_AUX_I2C_READ)) | ||
| 492 | return; | ||
| 493 | if (WARN_ON(msg_length != 4)) | ||
| 494 | return; | ||
| 495 | if (i2c_edid->edid_available && i2c_edid->slave_selected) { | ||
| 496 | unsigned char val = edid_get_byte(vgpu); | ||
| 497 | |||
| 498 | aux_data_for_write = (val << 16); | ||
| 499 | } | ||
| 500 | } | ||
| 501 | /* write the return value in AUX_CH_DATA reg which includes: | ||
| 502 | * ACK of I2C_WRITE | ||
| 503 | * returned byte if it is READ | ||
| 504 | */ | ||
| 505 | |||
| 506 | aux_data_for_write |= (GVT_AUX_I2C_REPLY_ACK & 0xff) << 24; | ||
| 507 | vgpu_vreg(vgpu, offset + 4) = aux_data_for_write; | ||
| 508 | } | ||
| 509 | |||
| 510 | /** | ||
| 511 | * intel_vgpu_init_i2c_edid - initialize vGPU i2c edid emulation | ||
| 512 | * @vgpu: a vGPU | ||
| 513 | * | ||
| 514 | * This function is used to initialize vGPU i2c edid emulation stuffs | ||
| 515 | * | ||
| 516 | */ | ||
| 517 | void intel_vgpu_init_i2c_edid(struct intel_vgpu *vgpu) | ||
| 518 | { | ||
| 519 | struct intel_vgpu_i2c_edid *edid = &vgpu->display.i2c_edid; | ||
| 520 | |||
| 521 | edid->state = I2C_NOT_SPECIFIED; | ||
| 522 | |||
| 523 | edid->port = -1; | ||
| 524 | edid->slave_selected = false; | ||
| 525 | edid->edid_available = false; | ||
| 526 | edid->current_edid_read = 0; | ||
| 527 | |||
| 528 | memset(&edid->gmbus, 0, sizeof(struct intel_vgpu_i2c_gmbus)); | ||
| 529 | |||
| 530 | edid->aux_ch.i2c_over_aux_ch = false; | ||
| 531 | edid->aux_ch.aux_ch_mot = false; | ||
| 532 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/edid.h b/drivers/gpu/drm/i915/gvt/edid.h new file mode 100644 index 000000000000..de366b1d5196 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/edid.h | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Ke Yu | ||
| 25 | * Zhiyuan Lv <zhiyuan.lv@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Terrence Xu <terrence.xu@intel.com> | ||
| 29 | * Changbin Du <changbin.du@intel.com> | ||
| 30 | * Bing Niu <bing.niu@intel.com> | ||
| 31 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 32 | * | ||
| 33 | */ | ||
| 34 | |||
| 35 | #ifndef _GVT_EDID_H_ | ||
| 36 | #define _GVT_EDID_H_ | ||
| 37 | |||
| 38 | #define EDID_SIZE 128 | ||
| 39 | #define EDID_ADDR 0x50 /* Linux hvm EDID addr */ | ||
| 40 | |||
| 41 | #define GVT_AUX_NATIVE_WRITE 0x8 | ||
| 42 | #define GVT_AUX_NATIVE_READ 0x9 | ||
| 43 | #define GVT_AUX_I2C_WRITE 0x0 | ||
| 44 | #define GVT_AUX_I2C_READ 0x1 | ||
| 45 | #define GVT_AUX_I2C_STATUS 0x2 | ||
| 46 | #define GVT_AUX_I2C_MOT 0x4 | ||
| 47 | #define GVT_AUX_I2C_REPLY_ACK (0x0 << 6) | ||
| 48 | |||
| 49 | struct intel_vgpu_edid_data { | ||
| 50 | bool data_valid; | ||
| 51 | unsigned char edid_block[EDID_SIZE]; | ||
| 52 | }; | ||
| 53 | |||
| 54 | enum gmbus_cycle_type { | ||
| 55 | GMBUS_NOCYCLE = 0x0, | ||
| 56 | NIDX_NS_W = 0x1, | ||
| 57 | IDX_NS_W = 0x3, | ||
| 58 | GMBUS_STOP = 0x4, | ||
| 59 | NIDX_STOP = 0x5, | ||
| 60 | IDX_STOP = 0x7 | ||
| 61 | }; | ||
| 62 | |||
| 63 | /* | ||
| 64 | * States of GMBUS | ||
| 65 | * | ||
| 66 | * GMBUS0-3 could be related to the EDID virtualization. Another two GMBUS | ||
| 67 | * registers, GMBUS4 (interrupt mask) and GMBUS5 (2 byte indes register), are | ||
| 68 | * not considered here. Below describes the usage of GMBUS registers that are | ||
| 69 | * cared by the EDID virtualization | ||
| 70 | * | ||
| 71 | * GMBUS0: | ||
| 72 | * R/W | ||
| 73 | * port selection. value of bit0 - bit2 corresponds to the GPIO registers. | ||
| 74 | * | ||
| 75 | * GMBUS1: | ||
| 76 | * R/W Protect | ||
| 77 | * Command and Status. | ||
| 78 | * bit0 is the direction bit: 1 is read; 0 is write. | ||
| 79 | * bit1 - bit7 is slave 7-bit address. | ||
| 80 | * bit16 - bit24 total byte count (ignore?) | ||
| 81 | * | ||
| 82 | * GMBUS2: | ||
| 83 | * Most of bits are read only except bit 15 (IN_USE) | ||
| 84 | * Status register | ||
| 85 | * bit0 - bit8 current byte count | ||
| 86 | * bit 11: hardware ready; | ||
| 87 | * | ||
| 88 | * GMBUS3: | ||
| 89 | * Read/Write | ||
| 90 | * Data for transfer | ||
| 91 | */ | ||
| 92 | |||
| 93 | /* From hw specs, Other phases like START, ADDRESS, INDEX | ||
| 94 | * are invisible to GMBUS MMIO interface. So no definitions | ||
| 95 | * in below enum types | ||
| 96 | */ | ||
| 97 | enum gvt_gmbus_phase { | ||
| 98 | GMBUS_IDLE_PHASE = 0, | ||
| 99 | GMBUS_DATA_PHASE, | ||
| 100 | GMBUS_WAIT_PHASE, | ||
| 101 | //GMBUS_STOP_PHASE, | ||
| 102 | GMBUS_MAX_PHASE | ||
| 103 | }; | ||
| 104 | |||
| 105 | struct intel_vgpu_i2c_gmbus { | ||
| 106 | unsigned int total_byte_count; /* from GMBUS1 */ | ||
| 107 | enum gmbus_cycle_type cycle_type; | ||
| 108 | enum gvt_gmbus_phase phase; | ||
| 109 | }; | ||
| 110 | |||
| 111 | struct intel_vgpu_i2c_aux_ch { | ||
| 112 | bool i2c_over_aux_ch; | ||
| 113 | bool aux_ch_mot; | ||
| 114 | }; | ||
| 115 | |||
| 116 | enum i2c_state { | ||
| 117 | I2C_NOT_SPECIFIED = 0, | ||
| 118 | I2C_GMBUS = 1, | ||
| 119 | I2C_AUX_CH = 2 | ||
| 120 | }; | ||
| 121 | |||
| 122 | /* I2C sequences cannot interleave. | ||
| 123 | * GMBUS and AUX_CH sequences cannot interleave. | ||
| 124 | */ | ||
| 125 | struct intel_vgpu_i2c_edid { | ||
| 126 | enum i2c_state state; | ||
| 127 | |||
| 128 | unsigned int port; | ||
| 129 | bool slave_selected; | ||
| 130 | bool edid_available; | ||
| 131 | unsigned int current_edid_read; | ||
| 132 | |||
| 133 | struct intel_vgpu_i2c_gmbus gmbus; | ||
| 134 | struct intel_vgpu_i2c_aux_ch aux_ch; | ||
| 135 | }; | ||
| 136 | |||
| 137 | void intel_vgpu_init_i2c_edid(struct intel_vgpu *vgpu); | ||
| 138 | |||
| 139 | int intel_gvt_i2c_handle_gmbus_read(struct intel_vgpu *vgpu, | ||
| 140 | unsigned int offset, void *p_data, unsigned int bytes); | ||
| 141 | |||
| 142 | int intel_gvt_i2c_handle_gmbus_write(struct intel_vgpu *vgpu, | ||
| 143 | unsigned int offset, void *p_data, unsigned int bytes); | ||
| 144 | |||
| 145 | void intel_gvt_i2c_handle_aux_ch_write(struct intel_vgpu *vgpu, | ||
| 146 | int port_idx, | ||
| 147 | unsigned int offset, | ||
| 148 | void *p_data); | ||
| 149 | |||
| 150 | #endif /*_GVT_EDID_H_*/ | ||
diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c new file mode 100644 index 000000000000..c1f6019d8895 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/execlist.c | |||
| @@ -0,0 +1,860 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Zhiyuan Lv <zhiyuan.lv@intel.com> | ||
| 25 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Min He <min.he@intel.com> | ||
| 29 | * Bing Niu <bing.niu@intel.com> | ||
| 30 | * Ping Gao <ping.a.gao@intel.com> | ||
| 31 | * Tina Zhang <tina.zhang@intel.com> | ||
| 32 | * | ||
| 33 | */ | ||
| 34 | |||
| 35 | #include "i915_drv.h" | ||
| 36 | #include "gvt.h" | ||
| 37 | |||
| 38 | #define _EL_OFFSET_STATUS 0x234 | ||
| 39 | #define _EL_OFFSET_STATUS_BUF 0x370 | ||
| 40 | #define _EL_OFFSET_STATUS_PTR 0x3A0 | ||
| 41 | |||
| 42 | #define execlist_ring_mmio(gvt, ring_id, offset) \ | ||
| 43 | (gvt->dev_priv->engine[ring_id]->mmio_base + (offset)) | ||
| 44 | |||
| 45 | #define valid_context(ctx) ((ctx)->valid) | ||
| 46 | #define same_context(a, b) (((a)->context_id == (b)->context_id) && \ | ||
| 47 | ((a)->lrca == (b)->lrca)) | ||
| 48 | |||
| 49 | static int context_switch_events[] = { | ||
| 50 | [RCS] = RCS_AS_CONTEXT_SWITCH, | ||
| 51 | [BCS] = BCS_AS_CONTEXT_SWITCH, | ||
| 52 | [VCS] = VCS_AS_CONTEXT_SWITCH, | ||
| 53 | [VCS2] = VCS2_AS_CONTEXT_SWITCH, | ||
| 54 | [VECS] = VECS_AS_CONTEXT_SWITCH, | ||
| 55 | }; | ||
| 56 | |||
| 57 | static int ring_id_to_context_switch_event(int ring_id) | ||
| 58 | { | ||
| 59 | if (WARN_ON(ring_id < RCS && ring_id > | ||
| 60 | ARRAY_SIZE(context_switch_events))) | ||
| 61 | return -EINVAL; | ||
| 62 | |||
| 63 | return context_switch_events[ring_id]; | ||
| 64 | } | ||
| 65 | |||
| 66 | static void switch_virtual_execlist_slot(struct intel_vgpu_execlist *execlist) | ||
| 67 | { | ||
| 68 | gvt_dbg_el("[before] running slot %d/context %x pending slot %d\n", | ||
| 69 | execlist->running_slot ? | ||
| 70 | execlist->running_slot->index : -1, | ||
| 71 | execlist->running_context ? | ||
| 72 | execlist->running_context->context_id : 0, | ||
| 73 | execlist->pending_slot ? | ||
| 74 | execlist->pending_slot->index : -1); | ||
| 75 | |||
| 76 | execlist->running_slot = execlist->pending_slot; | ||
| 77 | execlist->pending_slot = NULL; | ||
| 78 | execlist->running_context = execlist->running_context ? | ||
| 79 | &execlist->running_slot->ctx[0] : NULL; | ||
| 80 | |||
| 81 | gvt_dbg_el("[after] running slot %d/context %x pending slot %d\n", | ||
| 82 | execlist->running_slot ? | ||
| 83 | execlist->running_slot->index : -1, | ||
| 84 | execlist->running_context ? | ||
| 85 | execlist->running_context->context_id : 0, | ||
| 86 | execlist->pending_slot ? | ||
| 87 | execlist->pending_slot->index : -1); | ||
| 88 | } | ||
| 89 | |||
| 90 | static void emulate_execlist_status(struct intel_vgpu_execlist *execlist) | ||
| 91 | { | ||
| 92 | struct intel_vgpu_execlist_slot *running = execlist->running_slot; | ||
| 93 | struct intel_vgpu_execlist_slot *pending = execlist->pending_slot; | ||
| 94 | struct execlist_ctx_descriptor_format *desc = execlist->running_context; | ||
| 95 | struct intel_vgpu *vgpu = execlist->vgpu; | ||
| 96 | struct execlist_status_format status; | ||
| 97 | int ring_id = execlist->ring_id; | ||
| 98 | u32 status_reg = execlist_ring_mmio(vgpu->gvt, | ||
| 99 | ring_id, _EL_OFFSET_STATUS); | ||
| 100 | |||
| 101 | status.ldw = vgpu_vreg(vgpu, status_reg); | ||
| 102 | status.udw = vgpu_vreg(vgpu, status_reg + 4); | ||
| 103 | |||
| 104 | if (running) { | ||
| 105 | status.current_execlist_pointer = !!running->index; | ||
| 106 | status.execlist_write_pointer = !!!running->index; | ||
| 107 | status.execlist_0_active = status.execlist_0_valid = | ||
| 108 | !!!(running->index); | ||
| 109 | status.execlist_1_active = status.execlist_1_valid = | ||
| 110 | !!(running->index); | ||
| 111 | } else { | ||
| 112 | status.context_id = 0; | ||
| 113 | status.execlist_0_active = status.execlist_0_valid = 0; | ||
| 114 | status.execlist_1_active = status.execlist_1_valid = 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | status.context_id = desc ? desc->context_id : 0; | ||
| 118 | status.execlist_queue_full = !!(pending); | ||
| 119 | |||
| 120 | vgpu_vreg(vgpu, status_reg) = status.ldw; | ||
| 121 | vgpu_vreg(vgpu, status_reg + 4) = status.udw; | ||
| 122 | |||
| 123 | gvt_dbg_el("vgpu%d: status reg offset %x ldw %x udw %x\n", | ||
| 124 | vgpu->id, status_reg, status.ldw, status.udw); | ||
| 125 | } | ||
| 126 | |||
| 127 | static void emulate_csb_update(struct intel_vgpu_execlist *execlist, | ||
| 128 | struct execlist_context_status_format *status, | ||
| 129 | bool trigger_interrupt_later) | ||
| 130 | { | ||
| 131 | struct intel_vgpu *vgpu = execlist->vgpu; | ||
| 132 | int ring_id = execlist->ring_id; | ||
| 133 | struct execlist_context_status_pointer_format ctx_status_ptr; | ||
| 134 | u32 write_pointer; | ||
| 135 | u32 ctx_status_ptr_reg, ctx_status_buf_reg, offset; | ||
| 136 | |||
| 137 | ctx_status_ptr_reg = execlist_ring_mmio(vgpu->gvt, ring_id, | ||
| 138 | _EL_OFFSET_STATUS_PTR); | ||
| 139 | ctx_status_buf_reg = execlist_ring_mmio(vgpu->gvt, ring_id, | ||
| 140 | _EL_OFFSET_STATUS_BUF); | ||
| 141 | |||
| 142 | ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg); | ||
| 143 | |||
| 144 | write_pointer = ctx_status_ptr.write_ptr; | ||
| 145 | |||
| 146 | if (write_pointer == 0x7) | ||
| 147 | write_pointer = 0; | ||
| 148 | else { | ||
| 149 | ++write_pointer; | ||
| 150 | write_pointer %= 0x6; | ||
| 151 | } | ||
| 152 | |||
| 153 | offset = ctx_status_buf_reg + write_pointer * 8; | ||
| 154 | |||
| 155 | vgpu_vreg(vgpu, offset) = status->ldw; | ||
| 156 | vgpu_vreg(vgpu, offset + 4) = status->udw; | ||
| 157 | |||
| 158 | ctx_status_ptr.write_ptr = write_pointer; | ||
| 159 | vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw; | ||
| 160 | |||
| 161 | gvt_dbg_el("vgpu%d: w pointer %u reg %x csb l %x csb h %x\n", | ||
| 162 | vgpu->id, write_pointer, offset, status->ldw, status->udw); | ||
| 163 | |||
| 164 | if (trigger_interrupt_later) | ||
| 165 | return; | ||
| 166 | |||
| 167 | intel_vgpu_trigger_virtual_event(vgpu, | ||
| 168 | ring_id_to_context_switch_event(execlist->ring_id)); | ||
| 169 | } | ||
| 170 | |||
| 171 | static int emulate_execlist_ctx_schedule_out( | ||
| 172 | struct intel_vgpu_execlist *execlist, | ||
| 173 | struct execlist_ctx_descriptor_format *ctx) | ||
| 174 | { | ||
| 175 | struct intel_vgpu_execlist_slot *running = execlist->running_slot; | ||
| 176 | struct intel_vgpu_execlist_slot *pending = execlist->pending_slot; | ||
| 177 | struct execlist_ctx_descriptor_format *ctx0 = &running->ctx[0]; | ||
| 178 | struct execlist_ctx_descriptor_format *ctx1 = &running->ctx[1]; | ||
| 179 | struct execlist_context_status_format status; | ||
| 180 | |||
| 181 | memset(&status, 0, sizeof(status)); | ||
| 182 | |||
| 183 | gvt_dbg_el("schedule out context id %x\n", ctx->context_id); | ||
| 184 | |||
| 185 | if (WARN_ON(!same_context(ctx, execlist->running_context))) { | ||
| 186 | gvt_err("schedule out context is not running context," | ||
| 187 | "ctx id %x running ctx id %x\n", | ||
| 188 | ctx->context_id, | ||
| 189 | execlist->running_context->context_id); | ||
| 190 | return -EINVAL; | ||
| 191 | } | ||
| 192 | |||
| 193 | /* ctx1 is valid, ctx0/ctx is scheduled-out -> element switch */ | ||
| 194 | if (valid_context(ctx1) && same_context(ctx0, ctx)) { | ||
| 195 | gvt_dbg_el("ctx 1 valid, ctx/ctx 0 is scheduled-out\n"); | ||
| 196 | |||
| 197 | execlist->running_context = ctx1; | ||
| 198 | |||
| 199 | emulate_execlist_status(execlist); | ||
| 200 | |||
| 201 | status.context_complete = status.element_switch = 1; | ||
| 202 | status.context_id = ctx->context_id; | ||
| 203 | |||
| 204 | emulate_csb_update(execlist, &status, false); | ||
| 205 | /* | ||
| 206 | * ctx1 is not valid, ctx == ctx0 | ||
| 207 | * ctx1 is valid, ctx1 == ctx | ||
| 208 | * --> last element is finished | ||
| 209 | * emulate: | ||
| 210 | * active-to-idle if there is *no* pending execlist | ||
| 211 | * context-complete if there *is* pending execlist | ||
| 212 | */ | ||
| 213 | } else if ((!valid_context(ctx1) && same_context(ctx0, ctx)) | ||
| 214 | || (valid_context(ctx1) && same_context(ctx1, ctx))) { | ||
| 215 | gvt_dbg_el("need to switch virtual execlist slot\n"); | ||
| 216 | |||
| 217 | switch_virtual_execlist_slot(execlist); | ||
| 218 | |||
| 219 | emulate_execlist_status(execlist); | ||
| 220 | |||
| 221 | status.context_complete = status.active_to_idle = 1; | ||
| 222 | status.context_id = ctx->context_id; | ||
| 223 | |||
| 224 | if (!pending) { | ||
| 225 | emulate_csb_update(execlist, &status, false); | ||
| 226 | } else { | ||
| 227 | emulate_csb_update(execlist, &status, true); | ||
| 228 | |||
| 229 | memset(&status, 0, sizeof(status)); | ||
| 230 | |||
| 231 | status.idle_to_active = 1; | ||
| 232 | status.context_id = 0; | ||
| 233 | |||
| 234 | emulate_csb_update(execlist, &status, false); | ||
| 235 | } | ||
| 236 | } else { | ||
| 237 | WARN_ON(1); | ||
| 238 | return -EINVAL; | ||
| 239 | } | ||
| 240 | |||
| 241 | return 0; | ||
| 242 | } | ||
| 243 | |||
| 244 | static struct intel_vgpu_execlist_slot *get_next_execlist_slot( | ||
| 245 | struct intel_vgpu_execlist *execlist) | ||
| 246 | { | ||
| 247 | struct intel_vgpu *vgpu = execlist->vgpu; | ||
| 248 | int ring_id = execlist->ring_id; | ||
| 249 | u32 status_reg = execlist_ring_mmio(vgpu->gvt, ring_id, | ||
| 250 | _EL_OFFSET_STATUS); | ||
| 251 | struct execlist_status_format status; | ||
| 252 | |||
| 253 | status.ldw = vgpu_vreg(vgpu, status_reg); | ||
| 254 | status.udw = vgpu_vreg(vgpu, status_reg + 4); | ||
| 255 | |||
| 256 | if (status.execlist_queue_full) { | ||
| 257 | gvt_err("virtual execlist slots are full\n"); | ||
| 258 | return NULL; | ||
| 259 | } | ||
| 260 | |||
| 261 | return &execlist->slot[status.execlist_write_pointer]; | ||
| 262 | } | ||
| 263 | |||
| 264 | static int emulate_execlist_schedule_in(struct intel_vgpu_execlist *execlist, | ||
| 265 | struct execlist_ctx_descriptor_format ctx[2]) | ||
| 266 | { | ||
| 267 | struct intel_vgpu_execlist_slot *running = execlist->running_slot; | ||
| 268 | struct intel_vgpu_execlist_slot *slot = | ||
| 269 | get_next_execlist_slot(execlist); | ||
| 270 | |||
| 271 | struct execlist_ctx_descriptor_format *ctx0, *ctx1; | ||
| 272 | struct execlist_context_status_format status; | ||
| 273 | |||
| 274 | gvt_dbg_el("emulate schedule-in\n"); | ||
| 275 | |||
| 276 | if (!slot) { | ||
| 277 | gvt_err("no available execlist slot\n"); | ||
| 278 | return -EINVAL; | ||
| 279 | } | ||
| 280 | |||
| 281 | memset(&status, 0, sizeof(status)); | ||
| 282 | memset(slot->ctx, 0, sizeof(slot->ctx)); | ||
| 283 | |||
| 284 | slot->ctx[0] = ctx[0]; | ||
| 285 | slot->ctx[1] = ctx[1]; | ||
| 286 | |||
| 287 | gvt_dbg_el("alloc slot index %d ctx 0 %x ctx 1 %x\n", | ||
| 288 | slot->index, ctx[0].context_id, | ||
| 289 | ctx[1].context_id); | ||
| 290 | |||
| 291 | /* | ||
| 292 | * no running execlist, make this write bundle as running execlist | ||
| 293 | * -> idle-to-active | ||
| 294 | */ | ||
| 295 | if (!running) { | ||
| 296 | gvt_dbg_el("no current running execlist\n"); | ||
| 297 | |||
| 298 | execlist->running_slot = slot; | ||
| 299 | execlist->pending_slot = NULL; | ||
| 300 | execlist->running_context = &slot->ctx[0]; | ||
| 301 | |||
| 302 | gvt_dbg_el("running slot index %d running context %x\n", | ||
| 303 | execlist->running_slot->index, | ||
| 304 | execlist->running_context->context_id); | ||
| 305 | |||
| 306 | emulate_execlist_status(execlist); | ||
| 307 | |||
| 308 | status.idle_to_active = 1; | ||
| 309 | status.context_id = 0; | ||
| 310 | |||
| 311 | emulate_csb_update(execlist, &status, false); | ||
| 312 | return 0; | ||
| 313 | } | ||
| 314 | |||
| 315 | ctx0 = &running->ctx[0]; | ||
| 316 | ctx1 = &running->ctx[1]; | ||
| 317 | |||
| 318 | gvt_dbg_el("current running slot index %d ctx 0 %x ctx 1 %x\n", | ||
| 319 | running->index, ctx0->context_id, ctx1->context_id); | ||
| 320 | |||
| 321 | /* | ||
| 322 | * already has an running execlist | ||
| 323 | * a. running ctx1 is valid, | ||
| 324 | * ctx0 is finished, and running ctx1 == new execlist ctx[0] | ||
| 325 | * b. running ctx1 is not valid, | ||
| 326 | * ctx0 == new execlist ctx[0] | ||
| 327 | * ----> lite-restore + preempted | ||
| 328 | */ | ||
| 329 | if ((valid_context(ctx1) && same_context(ctx1, &slot->ctx[0]) && | ||
| 330 | /* condition a */ | ||
| 331 | (!same_context(ctx0, execlist->running_context))) || | ||
| 332 | (!valid_context(ctx1) && | ||
| 333 | same_context(ctx0, &slot->ctx[0]))) { /* condition b */ | ||
| 334 | gvt_dbg_el("need to switch virtual execlist slot\n"); | ||
| 335 | |||
| 336 | execlist->pending_slot = slot; | ||
| 337 | switch_virtual_execlist_slot(execlist); | ||
| 338 | |||
| 339 | emulate_execlist_status(execlist); | ||
| 340 | |||
| 341 | status.lite_restore = status.preempted = 1; | ||
| 342 | status.context_id = ctx[0].context_id; | ||
| 343 | |||
| 344 | emulate_csb_update(execlist, &status, false); | ||
| 345 | } else { | ||
| 346 | gvt_dbg_el("emulate as pending slot\n"); | ||
| 347 | /* | ||
| 348 | * otherwise | ||
| 349 | * --> emulate pending execlist exist + but no preemption case | ||
| 350 | */ | ||
| 351 | execlist->pending_slot = slot; | ||
| 352 | emulate_execlist_status(execlist); | ||
| 353 | } | ||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | static void free_workload(struct intel_vgpu_workload *workload) | ||
| 358 | { | ||
| 359 | intel_vgpu_unpin_mm(workload->shadow_mm); | ||
| 360 | intel_gvt_mm_unreference(workload->shadow_mm); | ||
| 361 | kmem_cache_free(workload->vgpu->workloads, workload); | ||
| 362 | } | ||
| 363 | |||
| 364 | #define get_desc_from_elsp_dwords(ed, i) \ | ||
| 365 | ((struct execlist_ctx_descriptor_format *)&((ed)->data[i * 2])) | ||
| 366 | |||
| 367 | |||
| 368 | #define BATCH_BUFFER_ADDR_MASK ((1UL << 32) - (1U << 2)) | ||
| 369 | #define BATCH_BUFFER_ADDR_HIGH_MASK ((1UL << 16) - (1U)) | ||
| 370 | static int set_gma_to_bb_cmd(struct intel_shadow_bb_entry *entry_obj, | ||
| 371 | unsigned long add, int gmadr_bytes) | ||
| 372 | { | ||
| 373 | if (WARN_ON(gmadr_bytes != 4 && gmadr_bytes != 8)) | ||
| 374 | return -1; | ||
| 375 | |||
| 376 | *((u32 *)(entry_obj->bb_start_cmd_va + (1 << 2))) = add & | ||
| 377 | BATCH_BUFFER_ADDR_MASK; | ||
| 378 | if (gmadr_bytes == 8) { | ||
| 379 | *((u32 *)(entry_obj->bb_start_cmd_va + (2 << 2))) = | ||
| 380 | add & BATCH_BUFFER_ADDR_HIGH_MASK; | ||
| 381 | } | ||
| 382 | |||
| 383 | return 0; | ||
| 384 | } | ||
| 385 | |||
| 386 | static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) | ||
| 387 | { | ||
| 388 | int gmadr_bytes = workload->vgpu->gvt->device_info.gmadr_bytes_in_cmd; | ||
| 389 | |||
| 390 | /* pin the gem object to ggtt */ | ||
| 391 | if (!list_empty(&workload->shadow_bb)) { | ||
| 392 | struct intel_shadow_bb_entry *entry_obj = | ||
| 393 | list_first_entry(&workload->shadow_bb, | ||
| 394 | struct intel_shadow_bb_entry, | ||
| 395 | list); | ||
| 396 | struct intel_shadow_bb_entry *temp; | ||
| 397 | |||
| 398 | list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb, | ||
| 399 | list) { | ||
| 400 | struct i915_vma *vma; | ||
| 401 | |||
| 402 | vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0, | ||
| 403 | 4, 0); | ||
| 404 | if (IS_ERR(vma)) { | ||
| 405 | gvt_err("Cannot pin\n"); | ||
| 406 | return; | ||
| 407 | } | ||
| 408 | |||
| 409 | /* FIXME: we are not tracking our pinned VMA leaving it | ||
| 410 | * up to the core to fix up the stray pin_count upon | ||
| 411 | * free. | ||
| 412 | */ | ||
| 413 | |||
| 414 | /* update the relocate gma with shadow batch buffer*/ | ||
| 415 | set_gma_to_bb_cmd(entry_obj, | ||
| 416 | i915_ggtt_offset(vma), | ||
| 417 | gmadr_bytes); | ||
| 418 | } | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 422 | static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) | ||
| 423 | { | ||
| 424 | int ring_id = wa_ctx->workload->ring_id; | ||
| 425 | struct i915_gem_context *shadow_ctx = | ||
| 426 | wa_ctx->workload->vgpu->shadow_ctx; | ||
| 427 | struct drm_i915_gem_object *ctx_obj = | ||
| 428 | shadow_ctx->engine[ring_id].state->obj; | ||
| 429 | struct execlist_ring_context *shadow_ring_context; | ||
| 430 | struct page *page; | ||
| 431 | |||
| 432 | page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); | ||
| 433 | shadow_ring_context = kmap_atomic(page); | ||
| 434 | |||
| 435 | shadow_ring_context->bb_per_ctx_ptr.val = | ||
| 436 | (shadow_ring_context->bb_per_ctx_ptr.val & | ||
| 437 | (~PER_CTX_ADDR_MASK)) | wa_ctx->per_ctx.shadow_gma; | ||
| 438 | shadow_ring_context->rcs_indirect_ctx.val = | ||
| 439 | (shadow_ring_context->rcs_indirect_ctx.val & | ||
| 440 | (~INDIRECT_CTX_ADDR_MASK)) | wa_ctx->indirect_ctx.shadow_gma; | ||
| 441 | |||
| 442 | kunmap_atomic(shadow_ring_context); | ||
| 443 | return 0; | ||
| 444 | } | ||
| 445 | |||
| 446 | static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | ||
| 447 | { | ||
| 448 | struct i915_vma *vma; | ||
| 449 | unsigned char *per_ctx_va = | ||
| 450 | (unsigned char *)wa_ctx->indirect_ctx.shadow_va + | ||
| 451 | wa_ctx->indirect_ctx.size; | ||
| 452 | |||
| 453 | if (wa_ctx->indirect_ctx.size == 0) | ||
| 454 | return; | ||
| 455 | |||
| 456 | vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL, | ||
| 457 | 0, CACHELINE_BYTES, 0); | ||
| 458 | if (IS_ERR(vma)) { | ||
| 459 | gvt_err("Cannot pin indirect ctx obj\n"); | ||
| 460 | return; | ||
| 461 | } | ||
| 462 | |||
| 463 | /* FIXME: we are not tracking our pinned VMA leaving it | ||
| 464 | * up to the core to fix up the stray pin_count upon | ||
| 465 | * free. | ||
| 466 | */ | ||
| 467 | |||
| 468 | wa_ctx->indirect_ctx.shadow_gma = i915_ggtt_offset(vma); | ||
| 469 | |||
| 470 | wa_ctx->per_ctx.shadow_gma = *((unsigned int *)per_ctx_va + 1); | ||
| 471 | memset(per_ctx_va, 0, CACHELINE_BYTES); | ||
| 472 | |||
| 473 | update_wa_ctx_2_shadow_ctx(wa_ctx); | ||
| 474 | } | ||
| 475 | |||
| 476 | static int prepare_execlist_workload(struct intel_vgpu_workload *workload) | ||
| 477 | { | ||
| 478 | struct intel_vgpu *vgpu = workload->vgpu; | ||
| 479 | struct execlist_ctx_descriptor_format ctx[2]; | ||
| 480 | int ring_id = workload->ring_id; | ||
| 481 | |||
| 482 | intel_vgpu_pin_mm(workload->shadow_mm); | ||
| 483 | intel_vgpu_sync_oos_pages(workload->vgpu); | ||
| 484 | intel_vgpu_flush_post_shadow(workload->vgpu); | ||
| 485 | prepare_shadow_batch_buffer(workload); | ||
| 486 | prepare_shadow_wa_ctx(&workload->wa_ctx); | ||
| 487 | if (!workload->emulate_schedule_in) | ||
| 488 | return 0; | ||
| 489 | |||
| 490 | ctx[0] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 1); | ||
| 491 | ctx[1] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 0); | ||
| 492 | |||
| 493 | return emulate_execlist_schedule_in(&vgpu->execlist[ring_id], ctx); | ||
| 494 | } | ||
| 495 | |||
| 496 | static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload) | ||
| 497 | { | ||
| 498 | /* release all the shadow batch buffer */ | ||
| 499 | if (!list_empty(&workload->shadow_bb)) { | ||
| 500 | struct intel_shadow_bb_entry *entry_obj = | ||
| 501 | list_first_entry(&workload->shadow_bb, | ||
| 502 | struct intel_shadow_bb_entry, | ||
| 503 | list); | ||
| 504 | struct intel_shadow_bb_entry *temp; | ||
| 505 | |||
| 506 | list_for_each_entry_safe(entry_obj, temp, &workload->shadow_bb, | ||
| 507 | list) { | ||
| 508 | i915_gem_object_unpin_map(entry_obj->obj); | ||
| 509 | i915_gem_object_put(entry_obj->obj); | ||
| 510 | list_del(&entry_obj->list); | ||
| 511 | kfree(entry_obj); | ||
| 512 | } | ||
| 513 | } | ||
| 514 | } | ||
| 515 | |||
| 516 | static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) | ||
| 517 | { | ||
| 518 | if (wa_ctx->indirect_ctx.size == 0) | ||
| 519 | return; | ||
| 520 | |||
| 521 | i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj); | ||
| 522 | i915_gem_object_put(wa_ctx->indirect_ctx.obj); | ||
| 523 | } | ||
| 524 | |||
| 525 | static int complete_execlist_workload(struct intel_vgpu_workload *workload) | ||
| 526 | { | ||
| 527 | struct intel_vgpu *vgpu = workload->vgpu; | ||
| 528 | struct intel_vgpu_execlist *execlist = | ||
| 529 | &vgpu->execlist[workload->ring_id]; | ||
| 530 | struct intel_vgpu_workload *next_workload; | ||
| 531 | struct list_head *next = workload_q_head(vgpu, workload->ring_id)->next; | ||
| 532 | bool lite_restore = false; | ||
| 533 | int ret; | ||
| 534 | |||
| 535 | gvt_dbg_el("complete workload %p status %d\n", workload, | ||
| 536 | workload->status); | ||
| 537 | |||
| 538 | release_shadow_batch_buffer(workload); | ||
| 539 | release_shadow_wa_ctx(&workload->wa_ctx); | ||
| 540 | |||
| 541 | if (workload->status || vgpu->resetting) | ||
| 542 | goto out; | ||
| 543 | |||
| 544 | if (!list_empty(workload_q_head(vgpu, workload->ring_id))) { | ||
| 545 | struct execlist_ctx_descriptor_format *this_desc, *next_desc; | ||
| 546 | |||
| 547 | next_workload = container_of(next, | ||
| 548 | struct intel_vgpu_workload, list); | ||
| 549 | this_desc = &workload->ctx_desc; | ||
| 550 | next_desc = &next_workload->ctx_desc; | ||
| 551 | |||
| 552 | lite_restore = same_context(this_desc, next_desc); | ||
| 553 | } | ||
| 554 | |||
| 555 | if (lite_restore) { | ||
| 556 | gvt_dbg_el("next context == current - no schedule-out\n"); | ||
| 557 | free_workload(workload); | ||
| 558 | return 0; | ||
| 559 | } | ||
| 560 | |||
| 561 | ret = emulate_execlist_ctx_schedule_out(execlist, &workload->ctx_desc); | ||
| 562 | if (ret) | ||
| 563 | goto err; | ||
| 564 | out: | ||
| 565 | free_workload(workload); | ||
| 566 | return 0; | ||
| 567 | err: | ||
| 568 | free_workload(workload); | ||
| 569 | return ret; | ||
| 570 | } | ||
| 571 | |||
| 572 | #define RING_CTX_OFF(x) \ | ||
| 573 | offsetof(struct execlist_ring_context, x) | ||
| 574 | |||
| 575 | static void read_guest_pdps(struct intel_vgpu *vgpu, | ||
| 576 | u64 ring_context_gpa, u32 pdp[8]) | ||
| 577 | { | ||
| 578 | u64 gpa; | ||
| 579 | int i; | ||
| 580 | |||
| 581 | gpa = ring_context_gpa + RING_CTX_OFF(pdp3_UDW.val); | ||
| 582 | |||
| 583 | for (i = 0; i < 8; i++) | ||
| 584 | intel_gvt_hypervisor_read_gpa(vgpu, | ||
| 585 | gpa + i * 8, &pdp[7 - i], 4); | ||
| 586 | } | ||
| 587 | |||
| 588 | static int prepare_mm(struct intel_vgpu_workload *workload) | ||
| 589 | { | ||
| 590 | struct execlist_ctx_descriptor_format *desc = &workload->ctx_desc; | ||
| 591 | struct intel_vgpu_mm *mm; | ||
| 592 | int page_table_level; | ||
| 593 | u32 pdp[8]; | ||
| 594 | |||
| 595 | if (desc->addressing_mode == 1) { /* legacy 32-bit */ | ||
| 596 | page_table_level = 3; | ||
| 597 | } else if (desc->addressing_mode == 3) { /* legacy 64 bit */ | ||
| 598 | page_table_level = 4; | ||
| 599 | } else { | ||
| 600 | gvt_err("Advanced Context mode(SVM) is not supported!\n"); | ||
| 601 | return -EINVAL; | ||
| 602 | } | ||
| 603 | |||
| 604 | read_guest_pdps(workload->vgpu, workload->ring_context_gpa, pdp); | ||
| 605 | |||
| 606 | mm = intel_vgpu_find_ppgtt_mm(workload->vgpu, page_table_level, pdp); | ||
| 607 | if (mm) { | ||
| 608 | intel_gvt_mm_reference(mm); | ||
| 609 | } else { | ||
| 610 | |||
| 611 | mm = intel_vgpu_create_mm(workload->vgpu, INTEL_GVT_MM_PPGTT, | ||
| 612 | pdp, page_table_level, 0); | ||
| 613 | if (IS_ERR(mm)) { | ||
| 614 | gvt_err("fail to create mm object.\n"); | ||
| 615 | return PTR_ERR(mm); | ||
| 616 | } | ||
| 617 | } | ||
| 618 | workload->shadow_mm = mm; | ||
| 619 | return 0; | ||
| 620 | } | ||
| 621 | |||
| 622 | #define get_last_workload(q) \ | ||
| 623 | (list_empty(q) ? NULL : container_of(q->prev, \ | ||
| 624 | struct intel_vgpu_workload, list)) | ||
| 625 | |||
| 626 | static int submit_context(struct intel_vgpu *vgpu, int ring_id, | ||
| 627 | struct execlist_ctx_descriptor_format *desc, | ||
| 628 | bool emulate_schedule_in) | ||
| 629 | { | ||
| 630 | struct list_head *q = workload_q_head(vgpu, ring_id); | ||
| 631 | struct intel_vgpu_workload *last_workload = get_last_workload(q); | ||
| 632 | struct intel_vgpu_workload *workload = NULL; | ||
| 633 | u64 ring_context_gpa; | ||
| 634 | u32 head, tail, start, ctl, ctx_ctl, per_ctx, indirect_ctx; | ||
| 635 | int ret; | ||
| 636 | |||
| 637 | ring_context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, | ||
| 638 | (u32)((desc->lrca + 1) << GTT_PAGE_SHIFT)); | ||
| 639 | if (ring_context_gpa == INTEL_GVT_INVALID_ADDR) { | ||
| 640 | gvt_err("invalid guest context LRCA: %x\n", desc->lrca); | ||
| 641 | return -EINVAL; | ||
| 642 | } | ||
| 643 | |||
| 644 | intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | ||
| 645 | RING_CTX_OFF(ring_header.val), &head, 4); | ||
| 646 | |||
| 647 | intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | ||
| 648 | RING_CTX_OFF(ring_tail.val), &tail, 4); | ||
| 649 | |||
| 650 | head &= RB_HEAD_OFF_MASK; | ||
| 651 | tail &= RB_TAIL_OFF_MASK; | ||
| 652 | |||
| 653 | if (last_workload && same_context(&last_workload->ctx_desc, desc)) { | ||
| 654 | gvt_dbg_el("ring id %d cur workload == last\n", ring_id); | ||
| 655 | gvt_dbg_el("ctx head %x real head %lx\n", head, | ||
| 656 | last_workload->rb_tail); | ||
| 657 | /* | ||
| 658 | * cannot use guest context head pointer here, | ||
| 659 | * as it might not be updated at this time | ||
| 660 | */ | ||
| 661 | head = last_workload->rb_tail; | ||
| 662 | } | ||
| 663 | |||
| 664 | gvt_dbg_el("ring id %d begin a new workload\n", ring_id); | ||
| 665 | |||
| 666 | workload = kmem_cache_zalloc(vgpu->workloads, GFP_KERNEL); | ||
| 667 | if (!workload) | ||
| 668 | return -ENOMEM; | ||
| 669 | |||
| 670 | /* record some ring buffer register values for scan and shadow */ | ||
| 671 | intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | ||
| 672 | RING_CTX_OFF(rb_start.val), &start, 4); | ||
| 673 | intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | ||
| 674 | RING_CTX_OFF(rb_ctrl.val), &ctl, 4); | ||
| 675 | intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | ||
| 676 | RING_CTX_OFF(ctx_ctrl.val), &ctx_ctl, 4); | ||
| 677 | |||
| 678 | INIT_LIST_HEAD(&workload->list); | ||
| 679 | INIT_LIST_HEAD(&workload->shadow_bb); | ||
| 680 | |||
| 681 | init_waitqueue_head(&workload->shadow_ctx_status_wq); | ||
| 682 | atomic_set(&workload->shadow_ctx_active, 0); | ||
| 683 | |||
| 684 | workload->vgpu = vgpu; | ||
| 685 | workload->ring_id = ring_id; | ||
| 686 | workload->ctx_desc = *desc; | ||
| 687 | workload->ring_context_gpa = ring_context_gpa; | ||
| 688 | workload->rb_head = head; | ||
| 689 | workload->rb_tail = tail; | ||
| 690 | workload->rb_start = start; | ||
| 691 | workload->rb_ctl = ctl; | ||
| 692 | workload->prepare = prepare_execlist_workload; | ||
| 693 | workload->complete = complete_execlist_workload; | ||
| 694 | workload->status = -EINPROGRESS; | ||
| 695 | workload->emulate_schedule_in = emulate_schedule_in; | ||
| 696 | |||
| 697 | if (ring_id == RCS) { | ||
| 698 | intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | ||
| 699 | RING_CTX_OFF(bb_per_ctx_ptr.val), &per_ctx, 4); | ||
| 700 | intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa + | ||
| 701 | RING_CTX_OFF(rcs_indirect_ctx.val), &indirect_ctx, 4); | ||
| 702 | |||
| 703 | workload->wa_ctx.indirect_ctx.guest_gma = | ||
| 704 | indirect_ctx & INDIRECT_CTX_ADDR_MASK; | ||
| 705 | workload->wa_ctx.indirect_ctx.size = | ||
| 706 | (indirect_ctx & INDIRECT_CTX_SIZE_MASK) * | ||
| 707 | CACHELINE_BYTES; | ||
| 708 | workload->wa_ctx.per_ctx.guest_gma = | ||
| 709 | per_ctx & PER_CTX_ADDR_MASK; | ||
| 710 | workload->wa_ctx.workload = workload; | ||
| 711 | |||
| 712 | WARN_ON(workload->wa_ctx.indirect_ctx.size && !(per_ctx & 0x1)); | ||
| 713 | } | ||
| 714 | |||
| 715 | if (emulate_schedule_in) | ||
| 716 | memcpy(&workload->elsp_dwords, | ||
| 717 | &vgpu->execlist[ring_id].elsp_dwords, | ||
| 718 | sizeof(workload->elsp_dwords)); | ||
| 719 | |||
| 720 | gvt_dbg_el("workload %p ring id %d head %x tail %x start %x ctl %x\n", | ||
| 721 | workload, ring_id, head, tail, start, ctl); | ||
| 722 | |||
| 723 | gvt_dbg_el("workload %p emulate schedule_in %d\n", workload, | ||
| 724 | emulate_schedule_in); | ||
| 725 | |||
| 726 | ret = prepare_mm(workload); | ||
| 727 | if (ret) { | ||
| 728 | kmem_cache_free(vgpu->workloads, workload); | ||
| 729 | return ret; | ||
| 730 | } | ||
| 731 | |||
| 732 | queue_workload(workload); | ||
| 733 | return 0; | ||
| 734 | } | ||
| 735 | |||
| 736 | int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id) | ||
| 737 | { | ||
| 738 | struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id]; | ||
| 739 | struct execlist_ctx_descriptor_format *desc[2], valid_desc[2]; | ||
| 740 | unsigned long valid_desc_bitmap = 0; | ||
| 741 | bool emulate_schedule_in = true; | ||
| 742 | int ret; | ||
| 743 | int i; | ||
| 744 | |||
| 745 | memset(valid_desc, 0, sizeof(valid_desc)); | ||
| 746 | |||
| 747 | desc[0] = get_desc_from_elsp_dwords(&execlist->elsp_dwords, 1); | ||
| 748 | desc[1] = get_desc_from_elsp_dwords(&execlist->elsp_dwords, 0); | ||
| 749 | |||
| 750 | for (i = 0; i < 2; i++) { | ||
| 751 | if (!desc[i]->valid) | ||
| 752 | continue; | ||
| 753 | |||
| 754 | if (!desc[i]->privilege_access) { | ||
| 755 | gvt_err("vgpu%d: unexpected GGTT elsp submission\n", | ||
| 756 | vgpu->id); | ||
| 757 | return -EINVAL; | ||
| 758 | } | ||
| 759 | |||
| 760 | /* TODO: add another guest context checks here. */ | ||
| 761 | set_bit(i, &valid_desc_bitmap); | ||
| 762 | valid_desc[i] = *desc[i]; | ||
| 763 | } | ||
| 764 | |||
| 765 | if (!valid_desc_bitmap) { | ||
| 766 | gvt_err("vgpu%d: no valid desc in a elsp submission\n", | ||
| 767 | vgpu->id); | ||
| 768 | return -EINVAL; | ||
| 769 | } | ||
| 770 | |||
| 771 | if (!test_bit(0, (void *)&valid_desc_bitmap) && | ||
| 772 | test_bit(1, (void *)&valid_desc_bitmap)) { | ||
| 773 | gvt_err("vgpu%d: weird elsp submission, desc 0 is not valid\n", | ||
| 774 | vgpu->id); | ||
| 775 | return -EINVAL; | ||
| 776 | } | ||
| 777 | |||
| 778 | /* submit workload */ | ||
| 779 | for_each_set_bit(i, (void *)&valid_desc_bitmap, 2) { | ||
| 780 | ret = submit_context(vgpu, ring_id, &valid_desc[i], | ||
| 781 | emulate_schedule_in); | ||
| 782 | if (ret) { | ||
| 783 | gvt_err("vgpu%d: fail to schedule workload\n", | ||
| 784 | vgpu->id); | ||
| 785 | return ret; | ||
| 786 | } | ||
| 787 | emulate_schedule_in = false; | ||
| 788 | } | ||
| 789 | return 0; | ||
| 790 | } | ||
| 791 | |||
| 792 | static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id) | ||
| 793 | { | ||
| 794 | struct intel_vgpu_execlist *execlist = &vgpu->execlist[ring_id]; | ||
| 795 | struct execlist_context_status_pointer_format ctx_status_ptr; | ||
| 796 | u32 ctx_status_ptr_reg; | ||
| 797 | |||
| 798 | memset(execlist, 0, sizeof(*execlist)); | ||
| 799 | |||
| 800 | execlist->vgpu = vgpu; | ||
| 801 | execlist->ring_id = ring_id; | ||
| 802 | execlist->slot[0].index = 0; | ||
| 803 | execlist->slot[1].index = 1; | ||
| 804 | |||
| 805 | ctx_status_ptr_reg = execlist_ring_mmio(vgpu->gvt, ring_id, | ||
| 806 | _EL_OFFSET_STATUS_PTR); | ||
| 807 | |||
| 808 | ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg); | ||
| 809 | ctx_status_ptr.read_ptr = ctx_status_ptr.write_ptr = 0x7; | ||
| 810 | vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw; | ||
| 811 | } | ||
| 812 | |||
| 813 | void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu) | ||
| 814 | { | ||
| 815 | kmem_cache_destroy(vgpu->workloads); | ||
| 816 | } | ||
| 817 | |||
| 818 | int intel_vgpu_init_execlist(struct intel_vgpu *vgpu) | ||
| 819 | { | ||
| 820 | enum intel_engine_id i; | ||
| 821 | struct intel_engine_cs *engine; | ||
| 822 | |||
| 823 | /* each ring has a virtual execlist engine */ | ||
| 824 | for_each_engine(engine, vgpu->gvt->dev_priv, i) { | ||
| 825 | init_vgpu_execlist(vgpu, i); | ||
| 826 | INIT_LIST_HEAD(&vgpu->workload_q_head[i]); | ||
| 827 | } | ||
| 828 | |||
| 829 | vgpu->workloads = kmem_cache_create("gvt-g vgpu workload", | ||
| 830 | sizeof(struct intel_vgpu_workload), 0, | ||
| 831 | SLAB_HWCACHE_ALIGN, | ||
| 832 | NULL); | ||
| 833 | |||
| 834 | if (!vgpu->workloads) | ||
| 835 | return -ENOMEM; | ||
| 836 | |||
| 837 | return 0; | ||
| 838 | } | ||
| 839 | |||
| 840 | void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu, | ||
| 841 | unsigned long ring_bitmap) | ||
| 842 | { | ||
| 843 | int bit; | ||
| 844 | struct list_head *pos, *n; | ||
| 845 | struct intel_vgpu_workload *workload = NULL; | ||
| 846 | |||
| 847 | for_each_set_bit(bit, &ring_bitmap, sizeof(ring_bitmap) * 8) { | ||
| 848 | if (bit >= I915_NUM_ENGINES) | ||
| 849 | break; | ||
| 850 | /* free the unsubmited workload in the queue */ | ||
| 851 | list_for_each_safe(pos, n, &vgpu->workload_q_head[bit]) { | ||
| 852 | workload = container_of(pos, | ||
| 853 | struct intel_vgpu_workload, list); | ||
| 854 | list_del_init(&workload->list); | ||
| 855 | free_workload(workload); | ||
| 856 | } | ||
| 857 | |||
| 858 | init_vgpu_execlist(vgpu, bit); | ||
| 859 | } | ||
| 860 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/execlist.h b/drivers/gpu/drm/i915/gvt/execlist.h new file mode 100644 index 000000000000..635f31c6dcc1 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/execlist.h | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Zhiyuan Lv <zhiyuan.lv@intel.com> | ||
| 25 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Min He <min.he@intel.com> | ||
| 29 | * Bing Niu <bing.niu@intel.com> | ||
| 30 | * Ping Gao <ping.a.gao@intel.com> | ||
| 31 | * Tina Zhang <tina.zhang@intel.com> | ||
| 32 | * | ||
| 33 | */ | ||
| 34 | |||
| 35 | #ifndef _GVT_EXECLIST_H_ | ||
| 36 | #define _GVT_EXECLIST_H_ | ||
| 37 | |||
| 38 | struct execlist_ctx_descriptor_format { | ||
| 39 | union { | ||
| 40 | u32 udw; | ||
| 41 | u32 context_id; | ||
| 42 | }; | ||
| 43 | union { | ||
| 44 | u32 ldw; | ||
| 45 | struct { | ||
| 46 | u32 valid : 1; | ||
| 47 | u32 force_pd_restore : 1; | ||
| 48 | u32 force_restore : 1; | ||
| 49 | u32 addressing_mode : 2; | ||
| 50 | u32 llc_coherency : 1; | ||
| 51 | u32 fault_handling : 2; | ||
| 52 | u32 privilege_access : 1; | ||
| 53 | u32 reserved : 3; | ||
| 54 | u32 lrca : 20; | ||
| 55 | }; | ||
| 56 | }; | ||
| 57 | }; | ||
| 58 | |||
| 59 | struct execlist_status_format { | ||
| 60 | union { | ||
| 61 | u32 ldw; | ||
| 62 | struct { | ||
| 63 | u32 current_execlist_pointer :1; | ||
| 64 | u32 execlist_write_pointer :1; | ||
| 65 | u32 execlist_queue_full :1; | ||
| 66 | u32 execlist_1_valid :1; | ||
| 67 | u32 execlist_0_valid :1; | ||
| 68 | u32 last_ctx_switch_reason :9; | ||
| 69 | u32 current_active_elm_status :2; | ||
| 70 | u32 arbitration_enable :1; | ||
| 71 | u32 execlist_1_active :1; | ||
| 72 | u32 execlist_0_active :1; | ||
| 73 | u32 reserved :13; | ||
| 74 | }; | ||
| 75 | }; | ||
| 76 | union { | ||
| 77 | u32 udw; | ||
| 78 | u32 context_id; | ||
| 79 | }; | ||
| 80 | }; | ||
| 81 | |||
| 82 | struct execlist_context_status_pointer_format { | ||
| 83 | union { | ||
| 84 | u32 dw; | ||
| 85 | struct { | ||
| 86 | u32 write_ptr :3; | ||
| 87 | u32 reserved :5; | ||
| 88 | u32 read_ptr :3; | ||
| 89 | u32 reserved2 :5; | ||
| 90 | u32 mask :16; | ||
| 91 | }; | ||
| 92 | }; | ||
| 93 | }; | ||
| 94 | |||
| 95 | struct execlist_context_status_format { | ||
| 96 | union { | ||
| 97 | u32 ldw; | ||
| 98 | struct { | ||
| 99 | u32 idle_to_active :1; | ||
| 100 | u32 preempted :1; | ||
| 101 | u32 element_switch :1; | ||
| 102 | u32 active_to_idle :1; | ||
| 103 | u32 context_complete :1; | ||
| 104 | u32 wait_on_sync_flip :1; | ||
| 105 | u32 wait_on_vblank :1; | ||
| 106 | u32 wait_on_semaphore :1; | ||
| 107 | u32 wait_on_scanline :1; | ||
| 108 | u32 reserved :2; | ||
| 109 | u32 semaphore_wait_mode :1; | ||
| 110 | u32 display_plane :3; | ||
| 111 | u32 lite_restore :1; | ||
| 112 | u32 reserved_2 :16; | ||
| 113 | }; | ||
| 114 | }; | ||
| 115 | union { | ||
| 116 | u32 udw; | ||
| 117 | u32 context_id; | ||
| 118 | }; | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct execlist_mmio_pair { | ||
| 122 | u32 addr; | ||
| 123 | u32 val; | ||
| 124 | }; | ||
| 125 | |||
| 126 | /* The first 52 dwords in register state context */ | ||
| 127 | struct execlist_ring_context { | ||
| 128 | u32 nop1; | ||
| 129 | u32 lri_cmd_1; | ||
| 130 | struct execlist_mmio_pair ctx_ctrl; | ||
| 131 | struct execlist_mmio_pair ring_header; | ||
| 132 | struct execlist_mmio_pair ring_tail; | ||
| 133 | struct execlist_mmio_pair rb_start; | ||
| 134 | struct execlist_mmio_pair rb_ctrl; | ||
| 135 | struct execlist_mmio_pair bb_cur_head_UDW; | ||
| 136 | struct execlist_mmio_pair bb_cur_head_LDW; | ||
| 137 | struct execlist_mmio_pair bb_state; | ||
| 138 | struct execlist_mmio_pair second_bb_addr_UDW; | ||
| 139 | struct execlist_mmio_pair second_bb_addr_LDW; | ||
| 140 | struct execlist_mmio_pair second_bb_state; | ||
| 141 | struct execlist_mmio_pair bb_per_ctx_ptr; | ||
| 142 | struct execlist_mmio_pair rcs_indirect_ctx; | ||
| 143 | struct execlist_mmio_pair rcs_indirect_ctx_offset; | ||
| 144 | u32 nop2; | ||
| 145 | u32 nop3; | ||
| 146 | u32 nop4; | ||
| 147 | u32 lri_cmd_2; | ||
| 148 | struct execlist_mmio_pair ctx_timestamp; | ||
| 149 | struct execlist_mmio_pair pdp3_UDW; | ||
| 150 | struct execlist_mmio_pair pdp3_LDW; | ||
| 151 | struct execlist_mmio_pair pdp2_UDW; | ||
| 152 | struct execlist_mmio_pair pdp2_LDW; | ||
| 153 | struct execlist_mmio_pair pdp1_UDW; | ||
| 154 | struct execlist_mmio_pair pdp1_LDW; | ||
| 155 | struct execlist_mmio_pair pdp0_UDW; | ||
| 156 | struct execlist_mmio_pair pdp0_LDW; | ||
| 157 | }; | ||
| 158 | |||
| 159 | struct intel_vgpu_elsp_dwords { | ||
| 160 | u32 data[4]; | ||
| 161 | u32 index; | ||
| 162 | }; | ||
| 163 | |||
| 164 | struct intel_vgpu_execlist_slot { | ||
| 165 | struct execlist_ctx_descriptor_format ctx[2]; | ||
| 166 | u32 index; | ||
| 167 | }; | ||
| 168 | |||
| 169 | struct intel_vgpu_execlist { | ||
| 170 | struct intel_vgpu_execlist_slot slot[2]; | ||
| 171 | struct intel_vgpu_execlist_slot *running_slot; | ||
| 172 | struct intel_vgpu_execlist_slot *pending_slot; | ||
| 173 | struct execlist_ctx_descriptor_format *running_context; | ||
| 174 | int ring_id; | ||
| 175 | struct intel_vgpu *vgpu; | ||
| 176 | struct intel_vgpu_elsp_dwords elsp_dwords; | ||
| 177 | }; | ||
| 178 | |||
| 179 | void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu); | ||
| 180 | |||
| 181 | int intel_vgpu_init_execlist(struct intel_vgpu *vgpu); | ||
| 182 | |||
| 183 | int intel_vgpu_submit_execlist(struct intel_vgpu *vgpu, int ring_id); | ||
| 184 | |||
| 185 | void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu, | ||
| 186 | unsigned long ring_bitmap); | ||
| 187 | |||
| 188 | #endif /*_GVT_EXECLIST_H_*/ | ||
diff --git a/drivers/gpu/drm/i915/gvt/firmware.c b/drivers/gpu/drm/i915/gvt/firmware.c new file mode 100644 index 000000000000..2fae2a2ca96f --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/firmware.c | |||
| @@ -0,0 +1,312 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 25 | * | ||
| 26 | * Contributors: | ||
| 27 | * Changbin Du <changbin.du@intel.com> | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <linux/firmware.h> | ||
| 32 | #include <linux/crc32.h> | ||
| 33 | |||
| 34 | #include "i915_drv.h" | ||
| 35 | #include "gvt.h" | ||
| 36 | #include "i915_pvinfo.h" | ||
| 37 | |||
| 38 | #define FIRMWARE_VERSION (0x0) | ||
| 39 | |||
| 40 | struct gvt_firmware_header { | ||
| 41 | u64 magic; | ||
| 42 | u32 crc32; /* protect the data after this field */ | ||
| 43 | u32 version; | ||
| 44 | u64 cfg_space_size; | ||
| 45 | u64 cfg_space_offset; /* offset in the file */ | ||
| 46 | u64 mmio_size; | ||
| 47 | u64 mmio_offset; /* offset in the file */ | ||
| 48 | unsigned char data[1]; | ||
| 49 | }; | ||
| 50 | |||
| 51 | #define RD(offset) (readl(mmio + offset.reg)) | ||
| 52 | #define WR(v, offset) (writel(v, mmio + offset.reg)) | ||
| 53 | |||
| 54 | static void bdw_forcewake_get(void __iomem *mmio) | ||
| 55 | { | ||
| 56 | WR(_MASKED_BIT_DISABLE(0xffff), FORCEWAKE_MT); | ||
| 57 | |||
| 58 | RD(ECOBUS); | ||
| 59 | |||
| 60 | if (wait_for((RD(FORCEWAKE_ACK_HSW) & FORCEWAKE_KERNEL) == 0, 50)) | ||
| 61 | gvt_err("fail to wait forcewake idle\n"); | ||
| 62 | |||
| 63 | WR(_MASKED_BIT_ENABLE(FORCEWAKE_KERNEL), FORCEWAKE_MT); | ||
| 64 | |||
| 65 | if (wait_for((RD(FORCEWAKE_ACK_HSW) & FORCEWAKE_KERNEL), 50)) | ||
| 66 | gvt_err("fail to wait forcewake ack\n"); | ||
| 67 | |||
| 68 | if (wait_for((RD(GEN6_GT_THREAD_STATUS_REG) & | ||
| 69 | GEN6_GT_THREAD_STATUS_CORE_MASK) == 0, 50)) | ||
| 70 | gvt_err("fail to wait c0 wake up\n"); | ||
| 71 | } | ||
| 72 | |||
| 73 | #undef RD | ||
| 74 | #undef WR | ||
| 75 | |||
| 76 | #define dev_to_drm_minor(d) dev_get_drvdata((d)) | ||
| 77 | |||
| 78 | static ssize_t | ||
| 79 | gvt_firmware_read(struct file *filp, struct kobject *kobj, | ||
| 80 | struct bin_attribute *attr, char *buf, | ||
| 81 | loff_t offset, size_t count) | ||
| 82 | { | ||
| 83 | memcpy(buf, attr->private + offset, count); | ||
| 84 | return count; | ||
| 85 | } | ||
| 86 | |||
| 87 | static struct bin_attribute firmware_attr = { | ||
| 88 | .attr = {.name = "gvt_firmware", .mode = (S_IRUSR)}, | ||
| 89 | .read = gvt_firmware_read, | ||
| 90 | .write = NULL, | ||
| 91 | .mmap = NULL, | ||
| 92 | }; | ||
| 93 | |||
| 94 | static int expose_firmware_sysfs(struct intel_gvt *gvt, | ||
| 95 | void __iomem *mmio) | ||
| 96 | { | ||
| 97 | struct intel_gvt_device_info *info = &gvt->device_info; | ||
| 98 | struct pci_dev *pdev = gvt->dev_priv->drm.pdev; | ||
| 99 | struct intel_gvt_mmio_info *e; | ||
| 100 | struct gvt_firmware_header *h; | ||
| 101 | void *firmware; | ||
| 102 | void *p; | ||
| 103 | unsigned long size; | ||
| 104 | int i; | ||
| 105 | int ret; | ||
| 106 | |||
| 107 | size = sizeof(*h) + info->mmio_size + info->cfg_space_size - 1; | ||
| 108 | firmware = vmalloc(size); | ||
| 109 | if (!firmware) | ||
| 110 | return -ENOMEM; | ||
| 111 | |||
| 112 | h = firmware; | ||
| 113 | |||
| 114 | h->magic = VGT_MAGIC; | ||
| 115 | h->version = FIRMWARE_VERSION; | ||
| 116 | h->cfg_space_size = info->cfg_space_size; | ||
| 117 | h->cfg_space_offset = offsetof(struct gvt_firmware_header, data); | ||
| 118 | h->mmio_size = info->mmio_size; | ||
| 119 | h->mmio_offset = h->cfg_space_offset + h->cfg_space_size; | ||
| 120 | |||
| 121 | p = firmware + h->cfg_space_offset; | ||
| 122 | |||
| 123 | for (i = 0; i < h->cfg_space_size; i += 4) | ||
| 124 | pci_read_config_dword(pdev, i, p + i); | ||
| 125 | |||
| 126 | memcpy(gvt->firmware.cfg_space, p, info->cfg_space_size); | ||
| 127 | |||
| 128 | p = firmware + h->mmio_offset; | ||
| 129 | |||
| 130 | hash_for_each(gvt->mmio.mmio_info_table, i, e, node) { | ||
| 131 | int j; | ||
| 132 | |||
| 133 | for (j = 0; j < e->length; j += 4) | ||
| 134 | *(u32 *)(p + e->offset + j) = | ||
| 135 | readl(mmio + e->offset + j); | ||
| 136 | } | ||
| 137 | |||
| 138 | memcpy(gvt->firmware.mmio, p, info->mmio_size); | ||
| 139 | |||
| 140 | firmware_attr.size = size; | ||
| 141 | firmware_attr.private = firmware; | ||
| 142 | |||
| 143 | ret = device_create_bin_file(&pdev->dev, &firmware_attr); | ||
| 144 | if (ret) { | ||
| 145 | vfree(firmware); | ||
| 146 | return ret; | ||
| 147 | } | ||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | |||
| 151 | static void clean_firmware_sysfs(struct intel_gvt *gvt) | ||
| 152 | { | ||
| 153 | struct pci_dev *pdev = gvt->dev_priv->drm.pdev; | ||
| 154 | |||
| 155 | device_remove_bin_file(&pdev->dev, &firmware_attr); | ||
| 156 | vfree(firmware_attr.private); | ||
| 157 | } | ||
| 158 | |||
| 159 | /** | ||
| 160 | * intel_gvt_free_firmware - free GVT firmware | ||
| 161 | * @gvt: intel gvt device | ||
| 162 | * | ||
| 163 | */ | ||
| 164 | void intel_gvt_free_firmware(struct intel_gvt *gvt) | ||
| 165 | { | ||
| 166 | if (!gvt->firmware.firmware_loaded) | ||
| 167 | clean_firmware_sysfs(gvt); | ||
| 168 | |||
| 169 | kfree(gvt->firmware.cfg_space); | ||
| 170 | kfree(gvt->firmware.mmio); | ||
| 171 | } | ||
| 172 | |||
| 173 | static int verify_firmware(struct intel_gvt *gvt, | ||
| 174 | const struct firmware *fw) | ||
| 175 | { | ||
| 176 | struct intel_gvt_device_info *info = &gvt->device_info; | ||
| 177 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
| 178 | struct pci_dev *pdev = dev_priv->drm.pdev; | ||
| 179 | struct gvt_firmware_header *h; | ||
| 180 | unsigned long id, crc32_start; | ||
| 181 | const void *mem; | ||
| 182 | const char *item; | ||
| 183 | u64 file, request; | ||
| 184 | |||
| 185 | h = (struct gvt_firmware_header *)fw->data; | ||
| 186 | |||
| 187 | crc32_start = offsetof(struct gvt_firmware_header, crc32) + 4; | ||
| 188 | mem = fw->data + crc32_start; | ||
| 189 | |||
| 190 | #define VERIFY(s, a, b) do { \ | ||
| 191 | item = (s); file = (u64)(a); request = (u64)(b); \ | ||
| 192 | if ((a) != (b)) \ | ||
| 193 | goto invalid_firmware; \ | ||
| 194 | } while (0) | ||
| 195 | |||
| 196 | VERIFY("magic number", h->magic, VGT_MAGIC); | ||
| 197 | VERIFY("version", h->version, FIRMWARE_VERSION); | ||
| 198 | VERIFY("crc32", h->crc32, crc32_le(0, mem, fw->size - crc32_start)); | ||
| 199 | VERIFY("cfg space size", h->cfg_space_size, info->cfg_space_size); | ||
| 200 | VERIFY("mmio size", h->mmio_size, info->mmio_size); | ||
| 201 | |||
| 202 | mem = (fw->data + h->cfg_space_offset); | ||
| 203 | |||
| 204 | id = *(u16 *)(mem + PCI_VENDOR_ID); | ||
| 205 | VERIFY("vender id", id, pdev->vendor); | ||
| 206 | |||
| 207 | id = *(u16 *)(mem + PCI_DEVICE_ID); | ||
| 208 | VERIFY("device id", id, pdev->device); | ||
| 209 | |||
| 210 | id = *(u8 *)(mem + PCI_REVISION_ID); | ||
| 211 | VERIFY("revision id", id, pdev->revision); | ||
| 212 | |||
| 213 | #undef VERIFY | ||
| 214 | return 0; | ||
| 215 | |||
| 216 | invalid_firmware: | ||
| 217 | gvt_dbg_core("Invalid firmware: %s [file] 0x%llx [request] 0x%llx\n", | ||
| 218 | item, file, request); | ||
| 219 | return -EINVAL; | ||
| 220 | } | ||
| 221 | |||
| 222 | #define GVT_FIRMWARE_PATH "i915/gvt" | ||
| 223 | |||
| 224 | /** | ||
| 225 | * intel_gvt_load_firmware - load GVT firmware | ||
| 226 | * @gvt: intel gvt device | ||
| 227 | * | ||
| 228 | */ | ||
| 229 | int intel_gvt_load_firmware(struct intel_gvt *gvt) | ||
| 230 | { | ||
| 231 | struct intel_gvt_device_info *info = &gvt->device_info; | ||
| 232 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
| 233 | struct pci_dev *pdev = dev_priv->drm.pdev; | ||
| 234 | struct intel_gvt_firmware *firmware = &gvt->firmware; | ||
| 235 | struct gvt_firmware_header *h; | ||
| 236 | const struct firmware *fw; | ||
| 237 | char *path; | ||
| 238 | void __iomem *mmio; | ||
| 239 | void *mem; | ||
| 240 | int ret; | ||
| 241 | |||
| 242 | path = kmalloc(PATH_MAX, GFP_KERNEL); | ||
| 243 | if (!path) | ||
| 244 | return -ENOMEM; | ||
| 245 | |||
| 246 | mem = kmalloc(info->cfg_space_size, GFP_KERNEL); | ||
| 247 | if (!mem) { | ||
| 248 | kfree(path); | ||
| 249 | return -ENOMEM; | ||
| 250 | } | ||
| 251 | |||
| 252 | firmware->cfg_space = mem; | ||
| 253 | |||
| 254 | mem = kmalloc(info->mmio_size, GFP_KERNEL); | ||
| 255 | if (!mem) { | ||
| 256 | kfree(path); | ||
| 257 | kfree(firmware->cfg_space); | ||
| 258 | return -ENOMEM; | ||
| 259 | } | ||
| 260 | |||
| 261 | firmware->mmio = mem; | ||
| 262 | |||
| 263 | mmio = pci_iomap(pdev, info->mmio_bar, info->mmio_size); | ||
| 264 | if (!mmio) { | ||
| 265 | kfree(path); | ||
| 266 | kfree(firmware->cfg_space); | ||
| 267 | kfree(firmware->mmio); | ||
| 268 | return -EINVAL; | ||
| 269 | } | ||
| 270 | |||
| 271 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) | ||
| 272 | bdw_forcewake_get(mmio); | ||
| 273 | |||
| 274 | sprintf(path, "%s/vid_0x%04x_did_0x%04x_rid_0x%04x.golden_hw_state", | ||
| 275 | GVT_FIRMWARE_PATH, pdev->vendor, pdev->device, | ||
| 276 | pdev->revision); | ||
| 277 | |||
| 278 | gvt_dbg_core("request hw state firmware %s...\n", path); | ||
| 279 | |||
| 280 | ret = request_firmware(&fw, path, &dev_priv->drm.pdev->dev); | ||
| 281 | kfree(path); | ||
| 282 | |||
| 283 | if (ret) | ||
| 284 | goto expose_firmware; | ||
| 285 | |||
| 286 | gvt_dbg_core("success.\n"); | ||
| 287 | |||
| 288 | ret = verify_firmware(gvt, fw); | ||
| 289 | if (ret) | ||
| 290 | goto out_free_fw; | ||
| 291 | |||
| 292 | gvt_dbg_core("verified.\n"); | ||
| 293 | |||
| 294 | h = (struct gvt_firmware_header *)fw->data; | ||
| 295 | |||
| 296 | memcpy(firmware->cfg_space, fw->data + h->cfg_space_offset, | ||
| 297 | h->cfg_space_size); | ||
| 298 | memcpy(firmware->mmio, fw->data + h->mmio_offset, | ||
| 299 | h->mmio_size); | ||
| 300 | |||
| 301 | release_firmware(fw); | ||
| 302 | firmware->firmware_loaded = true; | ||
| 303 | pci_iounmap(pdev, mmio); | ||
| 304 | return 0; | ||
| 305 | |||
| 306 | out_free_fw: | ||
| 307 | release_firmware(fw); | ||
| 308 | expose_firmware: | ||
| 309 | expose_firmware_sysfs(gvt, mmio); | ||
| 310 | pci_iounmap(pdev, mmio); | ||
| 311 | return 0; | ||
| 312 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c new file mode 100644 index 000000000000..2cc761328569 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/gtt.c | |||
| @@ -0,0 +1,2232 @@ | |||
| 1 | /* | ||
| 2 | * GTT virtualization | ||
| 3 | * | ||
| 4 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 5 | * | ||
| 6 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 7 | * copy of this software and associated documentation files (the "Software"), | ||
| 8 | * to deal in the Software without restriction, including without limitation | ||
| 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 10 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 11 | * Software is furnished to do so, subject to the following conditions: | ||
| 12 | * | ||
| 13 | * The above copyright notice and this permission notice (including the next | ||
| 14 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 15 | * Software. | ||
| 16 | * | ||
| 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 23 | * SOFTWARE. | ||
| 24 | * | ||
| 25 | * Authors: | ||
| 26 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 27 | * Zhenyu Wang <zhenyuw@linux.intel.com> | ||
| 28 | * Xiao Zheng <xiao.zheng@intel.com> | ||
| 29 | * | ||
| 30 | * Contributors: | ||
| 31 | * Min He <min.he@intel.com> | ||
| 32 | * Bing Niu <bing.niu@intel.com> | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | #include "i915_drv.h" | ||
| 37 | #include "gvt.h" | ||
| 38 | #include "i915_pvinfo.h" | ||
| 39 | #include "trace.h" | ||
| 40 | |||
| 41 | static bool enable_out_of_sync = false; | ||
| 42 | static int preallocated_oos_pages = 8192; | ||
| 43 | |||
| 44 | /* | ||
| 45 | * validate a gm address and related range size, | ||
| 46 | * translate it to host gm address | ||
| 47 | */ | ||
| 48 | bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size) | ||
| 49 | { | ||
| 50 | if ((!vgpu_gmadr_is_valid(vgpu, addr)) || (size | ||
| 51 | && !vgpu_gmadr_is_valid(vgpu, addr + size - 1))) { | ||
| 52 | gvt_err("vgpu%d: invalid range gmadr 0x%llx size 0x%x\n", | ||
| 53 | vgpu->id, addr, size); | ||
| 54 | return false; | ||
| 55 | } | ||
| 56 | return true; | ||
| 57 | } | ||
| 58 | |||
| 59 | /* translate a guest gmadr to host gmadr */ | ||
| 60 | int intel_gvt_ggtt_gmadr_g2h(struct intel_vgpu *vgpu, u64 g_addr, u64 *h_addr) | ||
| 61 | { | ||
| 62 | if (WARN(!vgpu_gmadr_is_valid(vgpu, g_addr), | ||
| 63 | "invalid guest gmadr %llx\n", g_addr)) | ||
| 64 | return -EACCES; | ||
| 65 | |||
| 66 | if (vgpu_gmadr_is_aperture(vgpu, g_addr)) | ||
| 67 | *h_addr = vgpu_aperture_gmadr_base(vgpu) | ||
| 68 | + (g_addr - vgpu_aperture_offset(vgpu)); | ||
| 69 | else | ||
| 70 | *h_addr = vgpu_hidden_gmadr_base(vgpu) | ||
| 71 | + (g_addr - vgpu_hidden_offset(vgpu)); | ||
| 72 | return 0; | ||
| 73 | } | ||
| 74 | |||
| 75 | /* translate a host gmadr to guest gmadr */ | ||
| 76 | int intel_gvt_ggtt_gmadr_h2g(struct intel_vgpu *vgpu, u64 h_addr, u64 *g_addr) | ||
| 77 | { | ||
| 78 | if (WARN(!gvt_gmadr_is_valid(vgpu->gvt, h_addr), | ||
| 79 | "invalid host gmadr %llx\n", h_addr)) | ||
| 80 | return -EACCES; | ||
| 81 | |||
| 82 | if (gvt_gmadr_is_aperture(vgpu->gvt, h_addr)) | ||
| 83 | *g_addr = vgpu_aperture_gmadr_base(vgpu) | ||
| 84 | + (h_addr - gvt_aperture_gmadr_base(vgpu->gvt)); | ||
| 85 | else | ||
| 86 | *g_addr = vgpu_hidden_gmadr_base(vgpu) | ||
| 87 | + (h_addr - gvt_hidden_gmadr_base(vgpu->gvt)); | ||
| 88 | return 0; | ||
| 89 | } | ||
| 90 | |||
| 91 | int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index, | ||
| 92 | unsigned long *h_index) | ||
| 93 | { | ||
| 94 | u64 h_addr; | ||
| 95 | int ret; | ||
| 96 | |||
| 97 | ret = intel_gvt_ggtt_gmadr_g2h(vgpu, g_index << GTT_PAGE_SHIFT, | ||
| 98 | &h_addr); | ||
| 99 | if (ret) | ||
| 100 | return ret; | ||
| 101 | |||
| 102 | *h_index = h_addr >> GTT_PAGE_SHIFT; | ||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | |||
| 106 | int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index, | ||
| 107 | unsigned long *g_index) | ||
| 108 | { | ||
| 109 | u64 g_addr; | ||
| 110 | int ret; | ||
| 111 | |||
| 112 | ret = intel_gvt_ggtt_gmadr_h2g(vgpu, h_index << GTT_PAGE_SHIFT, | ||
| 113 | &g_addr); | ||
| 114 | if (ret) | ||
| 115 | return ret; | ||
| 116 | |||
| 117 | *g_index = g_addr >> GTT_PAGE_SHIFT; | ||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | #define gtt_type_is_entry(type) \ | ||
| 122 | (type > GTT_TYPE_INVALID && type < GTT_TYPE_PPGTT_ENTRY \ | ||
| 123 | && type != GTT_TYPE_PPGTT_PTE_ENTRY \ | ||
| 124 | && type != GTT_TYPE_PPGTT_ROOT_ENTRY) | ||
| 125 | |||
| 126 | #define gtt_type_is_pt(type) \ | ||
| 127 | (type >= GTT_TYPE_PPGTT_PTE_PT && type < GTT_TYPE_MAX) | ||
| 128 | |||
| 129 | #define gtt_type_is_pte_pt(type) \ | ||
| 130 | (type == GTT_TYPE_PPGTT_PTE_PT) | ||
| 131 | |||
| 132 | #define gtt_type_is_root_pointer(type) \ | ||
| 133 | (gtt_type_is_entry(type) && type > GTT_TYPE_PPGTT_ROOT_ENTRY) | ||
| 134 | |||
| 135 | #define gtt_init_entry(e, t, p, v) do { \ | ||
| 136 | (e)->type = t; \ | ||
| 137 | (e)->pdev = p; \ | ||
| 138 | memcpy(&(e)->val64, &v, sizeof(v)); \ | ||
| 139 | } while (0) | ||
| 140 | |||
| 141 | enum { | ||
| 142 | GTT_TYPE_INVALID = -1, | ||
| 143 | |||
| 144 | GTT_TYPE_GGTT_PTE, | ||
| 145 | |||
| 146 | GTT_TYPE_PPGTT_PTE_4K_ENTRY, | ||
| 147 | GTT_TYPE_PPGTT_PTE_2M_ENTRY, | ||
| 148 | GTT_TYPE_PPGTT_PTE_1G_ENTRY, | ||
| 149 | |||
| 150 | GTT_TYPE_PPGTT_PTE_ENTRY, | ||
| 151 | |||
| 152 | GTT_TYPE_PPGTT_PDE_ENTRY, | ||
| 153 | GTT_TYPE_PPGTT_PDP_ENTRY, | ||
| 154 | GTT_TYPE_PPGTT_PML4_ENTRY, | ||
| 155 | |||
| 156 | GTT_TYPE_PPGTT_ROOT_ENTRY, | ||
| 157 | |||
| 158 | GTT_TYPE_PPGTT_ROOT_L3_ENTRY, | ||
| 159 | GTT_TYPE_PPGTT_ROOT_L4_ENTRY, | ||
| 160 | |||
| 161 | GTT_TYPE_PPGTT_ENTRY, | ||
| 162 | |||
| 163 | GTT_TYPE_PPGTT_PTE_PT, | ||
| 164 | GTT_TYPE_PPGTT_PDE_PT, | ||
| 165 | GTT_TYPE_PPGTT_PDP_PT, | ||
| 166 | GTT_TYPE_PPGTT_PML4_PT, | ||
| 167 | |||
| 168 | GTT_TYPE_MAX, | ||
| 169 | }; | ||
| 170 | |||
| 171 | /* | ||
| 172 | * Mappings between GTT_TYPE* enumerations. | ||
| 173 | * Following information can be found according to the given type: | ||
| 174 | * - type of next level page table | ||
| 175 | * - type of entry inside this level page table | ||
| 176 | * - type of entry with PSE set | ||
| 177 | * | ||
| 178 | * If the given type doesn't have such a kind of information, | ||
| 179 | * e.g. give a l4 root entry type, then request to get its PSE type, | ||
| 180 | * give a PTE page table type, then request to get its next level page | ||
| 181 | * table type, as we know l4 root entry doesn't have a PSE bit, | ||
| 182 | * and a PTE page table doesn't have a next level page table type, | ||
| 183 | * GTT_TYPE_INVALID will be returned. This is useful when traversing a | ||
| 184 | * page table. | ||
| 185 | */ | ||
| 186 | |||
| 187 | struct gtt_type_table_entry { | ||
| 188 | int entry_type; | ||
| 189 | int next_pt_type; | ||
| 190 | int pse_entry_type; | ||
| 191 | }; | ||
| 192 | |||
| 193 | #define GTT_TYPE_TABLE_ENTRY(type, e_type, npt_type, pse_type) \ | ||
| 194 | [type] = { \ | ||
| 195 | .entry_type = e_type, \ | ||
| 196 | .next_pt_type = npt_type, \ | ||
| 197 | .pse_entry_type = pse_type, \ | ||
| 198 | } | ||
| 199 | |||
| 200 | static struct gtt_type_table_entry gtt_type_table[] = { | ||
| 201 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_ROOT_L4_ENTRY, | ||
| 202 | GTT_TYPE_PPGTT_ROOT_L4_ENTRY, | ||
| 203 | GTT_TYPE_PPGTT_PML4_PT, | ||
| 204 | GTT_TYPE_INVALID), | ||
| 205 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PML4_PT, | ||
| 206 | GTT_TYPE_PPGTT_PML4_ENTRY, | ||
| 207 | GTT_TYPE_PPGTT_PDP_PT, | ||
| 208 | GTT_TYPE_INVALID), | ||
| 209 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PML4_ENTRY, | ||
| 210 | GTT_TYPE_PPGTT_PML4_ENTRY, | ||
| 211 | GTT_TYPE_PPGTT_PDP_PT, | ||
| 212 | GTT_TYPE_INVALID), | ||
| 213 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDP_PT, | ||
| 214 | GTT_TYPE_PPGTT_PDP_ENTRY, | ||
| 215 | GTT_TYPE_PPGTT_PDE_PT, | ||
| 216 | GTT_TYPE_PPGTT_PTE_1G_ENTRY), | ||
| 217 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_ROOT_L3_ENTRY, | ||
| 218 | GTT_TYPE_PPGTT_ROOT_L3_ENTRY, | ||
| 219 | GTT_TYPE_PPGTT_PDE_PT, | ||
| 220 | GTT_TYPE_PPGTT_PTE_1G_ENTRY), | ||
| 221 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDP_ENTRY, | ||
| 222 | GTT_TYPE_PPGTT_PDP_ENTRY, | ||
| 223 | GTT_TYPE_PPGTT_PDE_PT, | ||
| 224 | GTT_TYPE_PPGTT_PTE_1G_ENTRY), | ||
| 225 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDE_PT, | ||
| 226 | GTT_TYPE_PPGTT_PDE_ENTRY, | ||
| 227 | GTT_TYPE_PPGTT_PTE_PT, | ||
| 228 | GTT_TYPE_PPGTT_PTE_2M_ENTRY), | ||
| 229 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PDE_ENTRY, | ||
| 230 | GTT_TYPE_PPGTT_PDE_ENTRY, | ||
| 231 | GTT_TYPE_PPGTT_PTE_PT, | ||
| 232 | GTT_TYPE_PPGTT_PTE_2M_ENTRY), | ||
| 233 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_PT, | ||
| 234 | GTT_TYPE_PPGTT_PTE_4K_ENTRY, | ||
| 235 | GTT_TYPE_INVALID, | ||
| 236 | GTT_TYPE_INVALID), | ||
| 237 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_4K_ENTRY, | ||
| 238 | GTT_TYPE_PPGTT_PTE_4K_ENTRY, | ||
| 239 | GTT_TYPE_INVALID, | ||
| 240 | GTT_TYPE_INVALID), | ||
| 241 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_2M_ENTRY, | ||
| 242 | GTT_TYPE_PPGTT_PDE_ENTRY, | ||
| 243 | GTT_TYPE_INVALID, | ||
| 244 | GTT_TYPE_PPGTT_PTE_2M_ENTRY), | ||
| 245 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_PPGTT_PTE_1G_ENTRY, | ||
| 246 | GTT_TYPE_PPGTT_PDP_ENTRY, | ||
| 247 | GTT_TYPE_INVALID, | ||
| 248 | GTT_TYPE_PPGTT_PTE_1G_ENTRY), | ||
| 249 | GTT_TYPE_TABLE_ENTRY(GTT_TYPE_GGTT_PTE, | ||
| 250 | GTT_TYPE_GGTT_PTE, | ||
| 251 | GTT_TYPE_INVALID, | ||
| 252 | GTT_TYPE_INVALID), | ||
| 253 | }; | ||
| 254 | |||
| 255 | static inline int get_next_pt_type(int type) | ||
| 256 | { | ||
| 257 | return gtt_type_table[type].next_pt_type; | ||
| 258 | } | ||
| 259 | |||
| 260 | static inline int get_entry_type(int type) | ||
| 261 | { | ||
| 262 | return gtt_type_table[type].entry_type; | ||
| 263 | } | ||
| 264 | |||
| 265 | static inline int get_pse_type(int type) | ||
| 266 | { | ||
| 267 | return gtt_type_table[type].pse_entry_type; | ||
| 268 | } | ||
| 269 | |||
| 270 | static u64 read_pte64(struct drm_i915_private *dev_priv, unsigned long index) | ||
| 271 | { | ||
| 272 | void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index; | ||
| 273 | u64 pte; | ||
| 274 | |||
| 275 | #ifdef readq | ||
| 276 | pte = readq(addr); | ||
| 277 | #else | ||
| 278 | pte = ioread32(addr); | ||
| 279 | pte |= ioread32(addr + 4) << 32; | ||
| 280 | #endif | ||
| 281 | return pte; | ||
| 282 | } | ||
| 283 | |||
| 284 | static void write_pte64(struct drm_i915_private *dev_priv, | ||
| 285 | unsigned long index, u64 pte) | ||
| 286 | { | ||
| 287 | void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index; | ||
| 288 | |||
| 289 | #ifdef writeq | ||
| 290 | writeq(pte, addr); | ||
| 291 | #else | ||
| 292 | iowrite32((u32)pte, addr); | ||
| 293 | iowrite32(pte >> 32, addr + 4); | ||
| 294 | #endif | ||
| 295 | I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); | ||
| 296 | POSTING_READ(GFX_FLSH_CNTL_GEN6); | ||
| 297 | } | ||
| 298 | |||
| 299 | static inline struct intel_gvt_gtt_entry *gtt_get_entry64(void *pt, | ||
| 300 | struct intel_gvt_gtt_entry *e, | ||
| 301 | unsigned long index, bool hypervisor_access, unsigned long gpa, | ||
| 302 | struct intel_vgpu *vgpu) | ||
| 303 | { | ||
| 304 | const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; | ||
| 305 | int ret; | ||
| 306 | |||
| 307 | if (WARN_ON(info->gtt_entry_size != 8)) | ||
| 308 | return e; | ||
| 309 | |||
| 310 | if (hypervisor_access) { | ||
| 311 | ret = intel_gvt_hypervisor_read_gpa(vgpu, gpa + | ||
| 312 | (index << info->gtt_entry_size_shift), | ||
| 313 | &e->val64, 8); | ||
| 314 | WARN_ON(ret); | ||
| 315 | } else if (!pt) { | ||
| 316 | e->val64 = read_pte64(vgpu->gvt->dev_priv, index); | ||
| 317 | } else { | ||
| 318 | e->val64 = *((u64 *)pt + index); | ||
| 319 | } | ||
| 320 | return e; | ||
| 321 | } | ||
| 322 | |||
| 323 | static inline struct intel_gvt_gtt_entry *gtt_set_entry64(void *pt, | ||
| 324 | struct intel_gvt_gtt_entry *e, | ||
| 325 | unsigned long index, bool hypervisor_access, unsigned long gpa, | ||
| 326 | struct intel_vgpu *vgpu) | ||
| 327 | { | ||
| 328 | const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; | ||
| 329 | int ret; | ||
| 330 | |||
| 331 | if (WARN_ON(info->gtt_entry_size != 8)) | ||
| 332 | return e; | ||
| 333 | |||
| 334 | if (hypervisor_access) { | ||
| 335 | ret = intel_gvt_hypervisor_write_gpa(vgpu, gpa + | ||
| 336 | (index << info->gtt_entry_size_shift), | ||
| 337 | &e->val64, 8); | ||
| 338 | WARN_ON(ret); | ||
| 339 | } else if (!pt) { | ||
| 340 | write_pte64(vgpu->gvt->dev_priv, index, e->val64); | ||
| 341 | } else { | ||
| 342 | *((u64 *)pt + index) = e->val64; | ||
| 343 | } | ||
| 344 | return e; | ||
| 345 | } | ||
| 346 | |||
| 347 | #define GTT_HAW 46 | ||
| 348 | |||
| 349 | #define ADDR_1G_MASK (((1UL << (GTT_HAW - 30 + 1)) - 1) << 30) | ||
| 350 | #define ADDR_2M_MASK (((1UL << (GTT_HAW - 21 + 1)) - 1) << 21) | ||
| 351 | #define ADDR_4K_MASK (((1UL << (GTT_HAW - 12 + 1)) - 1) << 12) | ||
| 352 | |||
| 353 | static unsigned long gen8_gtt_get_pfn(struct intel_gvt_gtt_entry *e) | ||
| 354 | { | ||
| 355 | unsigned long pfn; | ||
| 356 | |||
| 357 | if (e->type == GTT_TYPE_PPGTT_PTE_1G_ENTRY) | ||
| 358 | pfn = (e->val64 & ADDR_1G_MASK) >> 12; | ||
| 359 | else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY) | ||
| 360 | pfn = (e->val64 & ADDR_2M_MASK) >> 12; | ||
| 361 | else | ||
| 362 | pfn = (e->val64 & ADDR_4K_MASK) >> 12; | ||
| 363 | return pfn; | ||
| 364 | } | ||
| 365 | |||
| 366 | static void gen8_gtt_set_pfn(struct intel_gvt_gtt_entry *e, unsigned long pfn) | ||
| 367 | { | ||
| 368 | if (e->type == GTT_TYPE_PPGTT_PTE_1G_ENTRY) { | ||
| 369 | e->val64 &= ~ADDR_1G_MASK; | ||
| 370 | pfn &= (ADDR_1G_MASK >> 12); | ||
| 371 | } else if (e->type == GTT_TYPE_PPGTT_PTE_2M_ENTRY) { | ||
| 372 | e->val64 &= ~ADDR_2M_MASK; | ||
| 373 | pfn &= (ADDR_2M_MASK >> 12); | ||
| 374 | } else { | ||
| 375 | e->val64 &= ~ADDR_4K_MASK; | ||
| 376 | pfn &= (ADDR_4K_MASK >> 12); | ||
| 377 | } | ||
| 378 | |||
| 379 | e->val64 |= (pfn << 12); | ||
| 380 | } | ||
| 381 | |||
| 382 | static bool gen8_gtt_test_pse(struct intel_gvt_gtt_entry *e) | ||
| 383 | { | ||
| 384 | /* Entry doesn't have PSE bit. */ | ||
| 385 | if (get_pse_type(e->type) == GTT_TYPE_INVALID) | ||
| 386 | return false; | ||
| 387 | |||
| 388 | e->type = get_entry_type(e->type); | ||
| 389 | if (!(e->val64 & (1 << 7))) | ||
| 390 | return false; | ||
| 391 | |||
| 392 | e->type = get_pse_type(e->type); | ||
| 393 | return true; | ||
| 394 | } | ||
| 395 | |||
| 396 | static bool gen8_gtt_test_present(struct intel_gvt_gtt_entry *e) | ||
| 397 | { | ||
| 398 | /* | ||
| 399 | * i915 writes PDP root pointer registers without present bit, | ||
| 400 | * it also works, so we need to treat root pointer entry | ||
| 401 | * specifically. | ||
| 402 | */ | ||
| 403 | if (e->type == GTT_TYPE_PPGTT_ROOT_L3_ENTRY | ||
| 404 | || e->type == GTT_TYPE_PPGTT_ROOT_L4_ENTRY) | ||
| 405 | return (e->val64 != 0); | ||
| 406 | else | ||
| 407 | return (e->val64 & (1 << 0)); | ||
| 408 | } | ||
| 409 | |||
| 410 | static void gtt_entry_clear_present(struct intel_gvt_gtt_entry *e) | ||
| 411 | { | ||
| 412 | e->val64 &= ~(1 << 0); | ||
| 413 | } | ||
| 414 | |||
| 415 | /* | ||
| 416 | * Per-platform GMA routines. | ||
| 417 | */ | ||
| 418 | static unsigned long gma_to_ggtt_pte_index(unsigned long gma) | ||
| 419 | { | ||
| 420 | unsigned long x = (gma >> GTT_PAGE_SHIFT); | ||
| 421 | |||
| 422 | trace_gma_index(__func__, gma, x); | ||
| 423 | return x; | ||
| 424 | } | ||
| 425 | |||
| 426 | #define DEFINE_PPGTT_GMA_TO_INDEX(prefix, ename, exp) \ | ||
| 427 | static unsigned long prefix##_gma_to_##ename##_index(unsigned long gma) \ | ||
| 428 | { \ | ||
| 429 | unsigned long x = (exp); \ | ||
| 430 | trace_gma_index(__func__, gma, x); \ | ||
| 431 | return x; \ | ||
| 432 | } | ||
| 433 | |||
| 434 | DEFINE_PPGTT_GMA_TO_INDEX(gen8, pte, (gma >> 12 & 0x1ff)); | ||
| 435 | DEFINE_PPGTT_GMA_TO_INDEX(gen8, pde, (gma >> 21 & 0x1ff)); | ||
| 436 | DEFINE_PPGTT_GMA_TO_INDEX(gen8, l3_pdp, (gma >> 30 & 0x3)); | ||
| 437 | DEFINE_PPGTT_GMA_TO_INDEX(gen8, l4_pdp, (gma >> 30 & 0x1ff)); | ||
| 438 | DEFINE_PPGTT_GMA_TO_INDEX(gen8, pml4, (gma >> 39 & 0x1ff)); | ||
| 439 | |||
| 440 | static struct intel_gvt_gtt_pte_ops gen8_gtt_pte_ops = { | ||
| 441 | .get_entry = gtt_get_entry64, | ||
| 442 | .set_entry = gtt_set_entry64, | ||
| 443 | .clear_present = gtt_entry_clear_present, | ||
| 444 | .test_present = gen8_gtt_test_present, | ||
| 445 | .test_pse = gen8_gtt_test_pse, | ||
| 446 | .get_pfn = gen8_gtt_get_pfn, | ||
| 447 | .set_pfn = gen8_gtt_set_pfn, | ||
| 448 | }; | ||
| 449 | |||
| 450 | static struct intel_gvt_gtt_gma_ops gen8_gtt_gma_ops = { | ||
| 451 | .gma_to_ggtt_pte_index = gma_to_ggtt_pte_index, | ||
| 452 | .gma_to_pte_index = gen8_gma_to_pte_index, | ||
| 453 | .gma_to_pde_index = gen8_gma_to_pde_index, | ||
| 454 | .gma_to_l3_pdp_index = gen8_gma_to_l3_pdp_index, | ||
| 455 | .gma_to_l4_pdp_index = gen8_gma_to_l4_pdp_index, | ||
| 456 | .gma_to_pml4_index = gen8_gma_to_pml4_index, | ||
| 457 | }; | ||
| 458 | |||
| 459 | static int gtt_entry_p2m(struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *p, | ||
| 460 | struct intel_gvt_gtt_entry *m) | ||
| 461 | { | ||
| 462 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; | ||
| 463 | unsigned long gfn, mfn; | ||
| 464 | |||
| 465 | *m = *p; | ||
| 466 | |||
| 467 | if (!ops->test_present(p)) | ||
| 468 | return 0; | ||
| 469 | |||
| 470 | gfn = ops->get_pfn(p); | ||
| 471 | |||
| 472 | mfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gfn); | ||
| 473 | if (mfn == INTEL_GVT_INVALID_ADDR) { | ||
| 474 | gvt_err("fail to translate gfn: 0x%lx\n", gfn); | ||
| 475 | return -ENXIO; | ||
| 476 | } | ||
| 477 | |||
| 478 | ops->set_pfn(m, mfn); | ||
| 479 | return 0; | ||
| 480 | } | ||
| 481 | |||
| 482 | /* | ||
| 483 | * MM helpers. | ||
| 484 | */ | ||
| 485 | struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry(struct intel_vgpu_mm *mm, | ||
| 486 | void *page_table, struct intel_gvt_gtt_entry *e, | ||
| 487 | unsigned long index) | ||
| 488 | { | ||
| 489 | struct intel_gvt *gvt = mm->vgpu->gvt; | ||
| 490 | struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; | ||
| 491 | |||
| 492 | e->type = mm->page_table_entry_type; | ||
| 493 | |||
| 494 | ops->get_entry(page_table, e, index, false, 0, mm->vgpu); | ||
| 495 | ops->test_pse(e); | ||
| 496 | return e; | ||
| 497 | } | ||
| 498 | |||
| 499 | struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry(struct intel_vgpu_mm *mm, | ||
| 500 | void *page_table, struct intel_gvt_gtt_entry *e, | ||
| 501 | unsigned long index) | ||
| 502 | { | ||
| 503 | struct intel_gvt *gvt = mm->vgpu->gvt; | ||
| 504 | struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; | ||
| 505 | |||
| 506 | return ops->set_entry(page_table, e, index, false, 0, mm->vgpu); | ||
| 507 | } | ||
| 508 | |||
| 509 | /* | ||
| 510 | * PPGTT shadow page table helpers. | ||
| 511 | */ | ||
| 512 | static inline struct intel_gvt_gtt_entry *ppgtt_spt_get_entry( | ||
| 513 | struct intel_vgpu_ppgtt_spt *spt, | ||
| 514 | void *page_table, int type, | ||
| 515 | struct intel_gvt_gtt_entry *e, unsigned long index, | ||
| 516 | bool guest) | ||
| 517 | { | ||
| 518 | struct intel_gvt *gvt = spt->vgpu->gvt; | ||
| 519 | struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; | ||
| 520 | |||
| 521 | e->type = get_entry_type(type); | ||
| 522 | |||
| 523 | if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n")) | ||
| 524 | return e; | ||
| 525 | |||
| 526 | ops->get_entry(page_table, e, index, guest, | ||
| 527 | spt->guest_page.gfn << GTT_PAGE_SHIFT, | ||
| 528 | spt->vgpu); | ||
| 529 | ops->test_pse(e); | ||
| 530 | return e; | ||
| 531 | } | ||
| 532 | |||
| 533 | static inline struct intel_gvt_gtt_entry *ppgtt_spt_set_entry( | ||
| 534 | struct intel_vgpu_ppgtt_spt *spt, | ||
| 535 | void *page_table, int type, | ||
| 536 | struct intel_gvt_gtt_entry *e, unsigned long index, | ||
| 537 | bool guest) | ||
| 538 | { | ||
| 539 | struct intel_gvt *gvt = spt->vgpu->gvt; | ||
| 540 | struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; | ||
| 541 | |||
| 542 | if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n")) | ||
| 543 | return e; | ||
| 544 | |||
| 545 | return ops->set_entry(page_table, e, index, guest, | ||
| 546 | spt->guest_page.gfn << GTT_PAGE_SHIFT, | ||
| 547 | spt->vgpu); | ||
| 548 | } | ||
| 549 | |||
| 550 | #define ppgtt_get_guest_entry(spt, e, index) \ | ||
| 551 | ppgtt_spt_get_entry(spt, NULL, \ | ||
| 552 | spt->guest_page_type, e, index, true) | ||
| 553 | |||
| 554 | #define ppgtt_set_guest_entry(spt, e, index) \ | ||
| 555 | ppgtt_spt_set_entry(spt, NULL, \ | ||
| 556 | spt->guest_page_type, e, index, true) | ||
| 557 | |||
| 558 | #define ppgtt_get_shadow_entry(spt, e, index) \ | ||
| 559 | ppgtt_spt_get_entry(spt, spt->shadow_page.vaddr, \ | ||
| 560 | spt->shadow_page.type, e, index, false) | ||
| 561 | |||
| 562 | #define ppgtt_set_shadow_entry(spt, e, index) \ | ||
| 563 | ppgtt_spt_set_entry(spt, spt->shadow_page.vaddr, \ | ||
| 564 | spt->shadow_page.type, e, index, false) | ||
| 565 | |||
| 566 | /** | ||
| 567 | * intel_vgpu_init_guest_page - init a guest page data structure | ||
| 568 | * @vgpu: a vGPU | ||
| 569 | * @p: a guest page data structure | ||
| 570 | * @gfn: guest memory page frame number | ||
| 571 | * @handler: function will be called when target guest memory page has | ||
| 572 | * been modified. | ||
| 573 | * | ||
| 574 | * This function is called when user wants to track a guest memory page. | ||
| 575 | * | ||
| 576 | * Returns: | ||
| 577 | * Zero on success, negative error code if failed. | ||
| 578 | */ | ||
| 579 | int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu, | ||
| 580 | struct intel_vgpu_guest_page *p, | ||
| 581 | unsigned long gfn, | ||
| 582 | int (*handler)(void *, u64, void *, int), | ||
| 583 | void *data) | ||
| 584 | { | ||
| 585 | INIT_HLIST_NODE(&p->node); | ||
| 586 | |||
| 587 | p->writeprotection = false; | ||
| 588 | p->gfn = gfn; | ||
| 589 | p->handler = handler; | ||
| 590 | p->data = data; | ||
| 591 | p->oos_page = NULL; | ||
| 592 | p->write_cnt = 0; | ||
| 593 | |||
| 594 | hash_add(vgpu->gtt.guest_page_hash_table, &p->node, p->gfn); | ||
| 595 | return 0; | ||
| 596 | } | ||
| 597 | |||
| 598 | static int detach_oos_page(struct intel_vgpu *vgpu, | ||
| 599 | struct intel_vgpu_oos_page *oos_page); | ||
| 600 | |||
| 601 | /** | ||
| 602 | * intel_vgpu_clean_guest_page - release the resource owned by guest page data | ||
| 603 | * structure | ||
| 604 | * @vgpu: a vGPU | ||
| 605 | * @p: a tracked guest page | ||
| 606 | * | ||
| 607 | * This function is called when user tries to stop tracking a guest memory | ||
| 608 | * page. | ||
| 609 | */ | ||
| 610 | void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu, | ||
| 611 | struct intel_vgpu_guest_page *p) | ||
| 612 | { | ||
| 613 | if (!hlist_unhashed(&p->node)) | ||
| 614 | hash_del(&p->node); | ||
| 615 | |||
| 616 | if (p->oos_page) | ||
| 617 | detach_oos_page(vgpu, p->oos_page); | ||
| 618 | |||
| 619 | if (p->writeprotection) | ||
| 620 | intel_gvt_hypervisor_unset_wp_page(vgpu, p); | ||
| 621 | } | ||
| 622 | |||
| 623 | /** | ||
| 624 | * intel_vgpu_find_guest_page - find a guest page data structure by GFN. | ||
| 625 | * @vgpu: a vGPU | ||
| 626 | * @gfn: guest memory page frame number | ||
| 627 | * | ||
| 628 | * This function is called when emulation logic wants to know if a trapped GFN | ||
| 629 | * is a tracked guest page. | ||
| 630 | * | ||
| 631 | * Returns: | ||
| 632 | * Pointer to guest page data structure, NULL if failed. | ||
| 633 | */ | ||
| 634 | struct intel_vgpu_guest_page *intel_vgpu_find_guest_page( | ||
| 635 | struct intel_vgpu *vgpu, unsigned long gfn) | ||
| 636 | { | ||
| 637 | struct intel_vgpu_guest_page *p; | ||
| 638 | |||
| 639 | hash_for_each_possible(vgpu->gtt.guest_page_hash_table, | ||
| 640 | p, node, gfn) { | ||
| 641 | if (p->gfn == gfn) | ||
| 642 | return p; | ||
| 643 | } | ||
| 644 | return NULL; | ||
| 645 | } | ||
| 646 | |||
| 647 | static inline int init_shadow_page(struct intel_vgpu *vgpu, | ||
| 648 | struct intel_vgpu_shadow_page *p, int type) | ||
| 649 | { | ||
| 650 | p->vaddr = page_address(p->page); | ||
| 651 | p->type = type; | ||
| 652 | |||
| 653 | INIT_HLIST_NODE(&p->node); | ||
| 654 | |||
| 655 | p->mfn = intel_gvt_hypervisor_virt_to_mfn(p->vaddr); | ||
| 656 | if (p->mfn == INTEL_GVT_INVALID_ADDR) | ||
| 657 | return -EFAULT; | ||
| 658 | |||
| 659 | hash_add(vgpu->gtt.shadow_page_hash_table, &p->node, p->mfn); | ||
| 660 | return 0; | ||
| 661 | } | ||
| 662 | |||
| 663 | static inline void clean_shadow_page(struct intel_vgpu_shadow_page *p) | ||
| 664 | { | ||
| 665 | if (!hlist_unhashed(&p->node)) | ||
| 666 | hash_del(&p->node); | ||
| 667 | } | ||
| 668 | |||
| 669 | static inline struct intel_vgpu_shadow_page *find_shadow_page( | ||
| 670 | struct intel_vgpu *vgpu, unsigned long mfn) | ||
| 671 | { | ||
| 672 | struct intel_vgpu_shadow_page *p; | ||
| 673 | |||
| 674 | hash_for_each_possible(vgpu->gtt.shadow_page_hash_table, | ||
| 675 | p, node, mfn) { | ||
| 676 | if (p->mfn == mfn) | ||
| 677 | return p; | ||
| 678 | } | ||
| 679 | return NULL; | ||
| 680 | } | ||
| 681 | |||
| 682 | #define guest_page_to_ppgtt_spt(ptr) \ | ||
| 683 | container_of(ptr, struct intel_vgpu_ppgtt_spt, guest_page) | ||
| 684 | |||
| 685 | #define shadow_page_to_ppgtt_spt(ptr) \ | ||
| 686 | container_of(ptr, struct intel_vgpu_ppgtt_spt, shadow_page) | ||
| 687 | |||
| 688 | static void *alloc_spt(gfp_t gfp_mask) | ||
| 689 | { | ||
| 690 | struct intel_vgpu_ppgtt_spt *spt; | ||
| 691 | |||
| 692 | spt = kzalloc(sizeof(*spt), gfp_mask); | ||
| 693 | if (!spt) | ||
| 694 | return NULL; | ||
| 695 | |||
| 696 | spt->shadow_page.page = alloc_page(gfp_mask); | ||
| 697 | if (!spt->shadow_page.page) { | ||
| 698 | kfree(spt); | ||
| 699 | return NULL; | ||
| 700 | } | ||
| 701 | return spt; | ||
| 702 | } | ||
| 703 | |||
| 704 | static void free_spt(struct intel_vgpu_ppgtt_spt *spt) | ||
| 705 | { | ||
| 706 | __free_page(spt->shadow_page.page); | ||
| 707 | kfree(spt); | ||
| 708 | } | ||
| 709 | |||
| 710 | static void ppgtt_free_shadow_page(struct intel_vgpu_ppgtt_spt *spt) | ||
| 711 | { | ||
| 712 | trace_spt_free(spt->vgpu->id, spt, spt->shadow_page.type); | ||
| 713 | |||
| 714 | clean_shadow_page(&spt->shadow_page); | ||
| 715 | intel_vgpu_clean_guest_page(spt->vgpu, &spt->guest_page); | ||
| 716 | list_del_init(&spt->post_shadow_list); | ||
| 717 | |||
| 718 | free_spt(spt); | ||
| 719 | } | ||
| 720 | |||
| 721 | static void ppgtt_free_all_shadow_page(struct intel_vgpu *vgpu) | ||
| 722 | { | ||
| 723 | struct hlist_node *n; | ||
| 724 | struct intel_vgpu_shadow_page *sp; | ||
| 725 | int i; | ||
| 726 | |||
| 727 | hash_for_each_safe(vgpu->gtt.shadow_page_hash_table, i, n, sp, node) | ||
| 728 | ppgtt_free_shadow_page(shadow_page_to_ppgtt_spt(sp)); | ||
| 729 | } | ||
| 730 | |||
| 731 | static int ppgtt_handle_guest_write_page_table_bytes(void *gp, | ||
| 732 | u64 pa, void *p_data, int bytes); | ||
| 733 | |||
| 734 | static int ppgtt_write_protection_handler(void *gp, u64 pa, | ||
| 735 | void *p_data, int bytes) | ||
| 736 | { | ||
| 737 | struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp; | ||
| 738 | int ret; | ||
| 739 | |||
| 740 | if (bytes != 4 && bytes != 8) | ||
| 741 | return -EINVAL; | ||
| 742 | |||
| 743 | if (!gpt->writeprotection) | ||
| 744 | return -EINVAL; | ||
| 745 | |||
| 746 | ret = ppgtt_handle_guest_write_page_table_bytes(gp, | ||
| 747 | pa, p_data, bytes); | ||
| 748 | if (ret) | ||
| 749 | return ret; | ||
| 750 | return ret; | ||
| 751 | } | ||
| 752 | |||
| 753 | static int reclaim_one_mm(struct intel_gvt *gvt); | ||
| 754 | |||
| 755 | static struct intel_vgpu_ppgtt_spt *ppgtt_alloc_shadow_page( | ||
| 756 | struct intel_vgpu *vgpu, int type, unsigned long gfn) | ||
| 757 | { | ||
| 758 | struct intel_vgpu_ppgtt_spt *spt = NULL; | ||
| 759 | int ret; | ||
| 760 | |||
| 761 | retry: | ||
| 762 | spt = alloc_spt(GFP_KERNEL | __GFP_ZERO); | ||
| 763 | if (!spt) { | ||
| 764 | if (reclaim_one_mm(vgpu->gvt)) | ||
| 765 | goto retry; | ||
| 766 | |||
| 767 | gvt_err("fail to allocate ppgtt shadow page\n"); | ||
| 768 | return ERR_PTR(-ENOMEM); | ||
| 769 | } | ||
| 770 | |||
| 771 | spt->vgpu = vgpu; | ||
| 772 | spt->guest_page_type = type; | ||
| 773 | atomic_set(&spt->refcount, 1); | ||
| 774 | INIT_LIST_HEAD(&spt->post_shadow_list); | ||
| 775 | |||
| 776 | /* | ||
| 777 | * TODO: guest page type may be different with shadow page type, | ||
| 778 | * when we support PSE page in future. | ||
| 779 | */ | ||
| 780 | ret = init_shadow_page(vgpu, &spt->shadow_page, type); | ||
| 781 | if (ret) { | ||
| 782 | gvt_err("fail to initialize shadow page for spt\n"); | ||
| 783 | goto err; | ||
| 784 | } | ||
| 785 | |||
| 786 | ret = intel_vgpu_init_guest_page(vgpu, &spt->guest_page, | ||
| 787 | gfn, ppgtt_write_protection_handler, NULL); | ||
| 788 | if (ret) { | ||
| 789 | gvt_err("fail to initialize guest page for spt\n"); | ||
| 790 | goto err; | ||
| 791 | } | ||
| 792 | |||
| 793 | trace_spt_alloc(vgpu->id, spt, type, spt->shadow_page.mfn, gfn); | ||
| 794 | return spt; | ||
| 795 | err: | ||
| 796 | ppgtt_free_shadow_page(spt); | ||
| 797 | return ERR_PTR(ret); | ||
| 798 | } | ||
| 799 | |||
| 800 | static struct intel_vgpu_ppgtt_spt *ppgtt_find_shadow_page( | ||
| 801 | struct intel_vgpu *vgpu, unsigned long mfn) | ||
| 802 | { | ||
| 803 | struct intel_vgpu_shadow_page *p = find_shadow_page(vgpu, mfn); | ||
| 804 | |||
| 805 | if (p) | ||
| 806 | return shadow_page_to_ppgtt_spt(p); | ||
| 807 | |||
| 808 | gvt_err("vgpu%d: fail to find ppgtt shadow page: 0x%lx\n", | ||
| 809 | vgpu->id, mfn); | ||
| 810 | return NULL; | ||
| 811 | } | ||
| 812 | |||
| 813 | #define pt_entry_size_shift(spt) \ | ||
| 814 | ((spt)->vgpu->gvt->device_info.gtt_entry_size_shift) | ||
| 815 | |||
| 816 | #define pt_entries(spt) \ | ||
| 817 | (GTT_PAGE_SIZE >> pt_entry_size_shift(spt)) | ||
| 818 | |||
| 819 | #define for_each_present_guest_entry(spt, e, i) \ | ||
| 820 | for (i = 0; i < pt_entries(spt); i++) \ | ||
| 821 | if (spt->vgpu->gvt->gtt.pte_ops->test_present( \ | ||
| 822 | ppgtt_get_guest_entry(spt, e, i))) | ||
| 823 | |||
| 824 | #define for_each_present_shadow_entry(spt, e, i) \ | ||
| 825 | for (i = 0; i < pt_entries(spt); i++) \ | ||
| 826 | if (spt->vgpu->gvt->gtt.pte_ops->test_present( \ | ||
| 827 | ppgtt_get_shadow_entry(spt, e, i))) | ||
| 828 | |||
| 829 | static void ppgtt_get_shadow_page(struct intel_vgpu_ppgtt_spt *spt) | ||
| 830 | { | ||
| 831 | int v = atomic_read(&spt->refcount); | ||
| 832 | |||
| 833 | trace_spt_refcount(spt->vgpu->id, "inc", spt, v, (v + 1)); | ||
| 834 | |||
| 835 | atomic_inc(&spt->refcount); | ||
| 836 | } | ||
| 837 | |||
| 838 | static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt); | ||
| 839 | |||
| 840 | static int ppgtt_invalidate_shadow_page_by_shadow_entry(struct intel_vgpu *vgpu, | ||
| 841 | struct intel_gvt_gtt_entry *e) | ||
| 842 | { | ||
| 843 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; | ||
| 844 | struct intel_vgpu_ppgtt_spt *s; | ||
| 845 | |||
| 846 | if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(e->type)))) | ||
| 847 | return -EINVAL; | ||
| 848 | |||
| 849 | if (ops->get_pfn(e) == vgpu->gtt.scratch_page_mfn) | ||
| 850 | return 0; | ||
| 851 | |||
| 852 | s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e)); | ||
| 853 | if (!s) { | ||
| 854 | gvt_err("vgpu%d: fail to find shadow page: mfn: 0x%lx\n", | ||
| 855 | vgpu->id, ops->get_pfn(e)); | ||
| 856 | return -ENXIO; | ||
| 857 | } | ||
| 858 | return ppgtt_invalidate_shadow_page(s); | ||
| 859 | } | ||
| 860 | |||
| 861 | static int ppgtt_invalidate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) | ||
| 862 | { | ||
| 863 | struct intel_gvt_gtt_entry e; | ||
| 864 | unsigned long index; | ||
| 865 | int ret; | ||
| 866 | int v = atomic_read(&spt->refcount); | ||
| 867 | |||
| 868 | trace_spt_change(spt->vgpu->id, "die", spt, | ||
| 869 | spt->guest_page.gfn, spt->shadow_page.type); | ||
| 870 | |||
| 871 | trace_spt_refcount(spt->vgpu->id, "dec", spt, v, (v - 1)); | ||
| 872 | |||
| 873 | if (atomic_dec_return(&spt->refcount) > 0) | ||
| 874 | return 0; | ||
| 875 | |||
| 876 | if (gtt_type_is_pte_pt(spt->shadow_page.type)) | ||
| 877 | goto release; | ||
| 878 | |||
| 879 | for_each_present_shadow_entry(spt, &e, index) { | ||
| 880 | if (!gtt_type_is_pt(get_next_pt_type(e.type))) { | ||
| 881 | gvt_err("GVT doesn't support pse bit for now\n"); | ||
| 882 | return -EINVAL; | ||
| 883 | } | ||
| 884 | ret = ppgtt_invalidate_shadow_page_by_shadow_entry( | ||
| 885 | spt->vgpu, &e); | ||
| 886 | if (ret) | ||
| 887 | goto fail; | ||
| 888 | } | ||
| 889 | release: | ||
| 890 | trace_spt_change(spt->vgpu->id, "release", spt, | ||
| 891 | spt->guest_page.gfn, spt->shadow_page.type); | ||
| 892 | ppgtt_free_shadow_page(spt); | ||
| 893 | return 0; | ||
| 894 | fail: | ||
| 895 | gvt_err("vgpu%d: fail: shadow page %p shadow entry 0x%llx type %d\n", | ||
| 896 | spt->vgpu->id, spt, e.val64, e.type); | ||
| 897 | return ret; | ||
| 898 | } | ||
| 899 | |||
| 900 | static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt); | ||
| 901 | |||
| 902 | static struct intel_vgpu_ppgtt_spt *ppgtt_populate_shadow_page_by_guest_entry( | ||
| 903 | struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *we) | ||
| 904 | { | ||
| 905 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; | ||
| 906 | struct intel_vgpu_ppgtt_spt *s = NULL; | ||
| 907 | struct intel_vgpu_guest_page *g; | ||
| 908 | int ret; | ||
| 909 | |||
| 910 | if (WARN_ON(!gtt_type_is_pt(get_next_pt_type(we->type)))) { | ||
| 911 | ret = -EINVAL; | ||
| 912 | goto fail; | ||
| 913 | } | ||
| 914 | |||
| 915 | g = intel_vgpu_find_guest_page(vgpu, ops->get_pfn(we)); | ||
| 916 | if (g) { | ||
| 917 | s = guest_page_to_ppgtt_spt(g); | ||
| 918 | ppgtt_get_shadow_page(s); | ||
| 919 | } else { | ||
| 920 | int type = get_next_pt_type(we->type); | ||
| 921 | |||
| 922 | s = ppgtt_alloc_shadow_page(vgpu, type, ops->get_pfn(we)); | ||
| 923 | if (IS_ERR(s)) { | ||
| 924 | ret = PTR_ERR(s); | ||
| 925 | goto fail; | ||
| 926 | } | ||
| 927 | |||
| 928 | ret = intel_gvt_hypervisor_set_wp_page(vgpu, &s->guest_page); | ||
| 929 | if (ret) | ||
| 930 | goto fail; | ||
| 931 | |||
| 932 | ret = ppgtt_populate_shadow_page(s); | ||
| 933 | if (ret) | ||
| 934 | goto fail; | ||
| 935 | |||
| 936 | trace_spt_change(vgpu->id, "new", s, s->guest_page.gfn, | ||
| 937 | s->shadow_page.type); | ||
| 938 | } | ||
| 939 | return s; | ||
| 940 | fail: | ||
| 941 | gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", | ||
| 942 | vgpu->id, s, we->val64, we->type); | ||
| 943 | return ERR_PTR(ret); | ||
| 944 | } | ||
| 945 | |||
| 946 | static inline void ppgtt_generate_shadow_entry(struct intel_gvt_gtt_entry *se, | ||
| 947 | struct intel_vgpu_ppgtt_spt *s, struct intel_gvt_gtt_entry *ge) | ||
| 948 | { | ||
| 949 | struct intel_gvt_gtt_pte_ops *ops = s->vgpu->gvt->gtt.pte_ops; | ||
| 950 | |||
| 951 | se->type = ge->type; | ||
| 952 | se->val64 = ge->val64; | ||
| 953 | |||
| 954 | ops->set_pfn(se, s->shadow_page.mfn); | ||
| 955 | } | ||
| 956 | |||
| 957 | static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) | ||
| 958 | { | ||
| 959 | struct intel_vgpu *vgpu = spt->vgpu; | ||
| 960 | struct intel_vgpu_ppgtt_spt *s; | ||
| 961 | struct intel_gvt_gtt_entry se, ge; | ||
| 962 | unsigned long i; | ||
| 963 | int ret; | ||
| 964 | |||
| 965 | trace_spt_change(spt->vgpu->id, "born", spt, | ||
| 966 | spt->guest_page.gfn, spt->shadow_page.type); | ||
| 967 | |||
| 968 | if (gtt_type_is_pte_pt(spt->shadow_page.type)) { | ||
| 969 | for_each_present_guest_entry(spt, &ge, i) { | ||
| 970 | ret = gtt_entry_p2m(vgpu, &ge, &se); | ||
| 971 | if (ret) | ||
| 972 | goto fail; | ||
| 973 | ppgtt_set_shadow_entry(spt, &se, i); | ||
| 974 | } | ||
| 975 | return 0; | ||
| 976 | } | ||
| 977 | |||
| 978 | for_each_present_guest_entry(spt, &ge, i) { | ||
| 979 | if (!gtt_type_is_pt(get_next_pt_type(ge.type))) { | ||
| 980 | gvt_err("GVT doesn't support pse bit now\n"); | ||
| 981 | ret = -EINVAL; | ||
| 982 | goto fail; | ||
| 983 | } | ||
| 984 | |||
| 985 | s = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge); | ||
| 986 | if (IS_ERR(s)) { | ||
| 987 | ret = PTR_ERR(s); | ||
| 988 | goto fail; | ||
| 989 | } | ||
| 990 | ppgtt_get_shadow_entry(spt, &se, i); | ||
| 991 | ppgtt_generate_shadow_entry(&se, s, &ge); | ||
| 992 | ppgtt_set_shadow_entry(spt, &se, i); | ||
| 993 | } | ||
| 994 | return 0; | ||
| 995 | fail: | ||
| 996 | gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", | ||
| 997 | vgpu->id, spt, ge.val64, ge.type); | ||
| 998 | return ret; | ||
| 999 | } | ||
| 1000 | |||
| 1001 | static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt, | ||
| 1002 | struct intel_gvt_gtt_entry *we, unsigned long index) | ||
| 1003 | { | ||
| 1004 | struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt); | ||
| 1005 | struct intel_vgpu_shadow_page *sp = &spt->shadow_page; | ||
| 1006 | struct intel_vgpu *vgpu = spt->vgpu; | ||
| 1007 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; | ||
| 1008 | struct intel_gvt_gtt_entry e; | ||
| 1009 | int ret; | ||
| 1010 | |||
| 1011 | trace_gpt_change(spt->vgpu->id, "remove", spt, sp->type, | ||
| 1012 | we->val64, index); | ||
| 1013 | |||
| 1014 | ppgtt_get_shadow_entry(spt, &e, index); | ||
| 1015 | if (!ops->test_present(&e)) | ||
| 1016 | return 0; | ||
| 1017 | |||
| 1018 | if (ops->get_pfn(&e) == vgpu->gtt.scratch_page_mfn) | ||
| 1019 | return 0; | ||
| 1020 | |||
| 1021 | if (gtt_type_is_pt(get_next_pt_type(we->type))) { | ||
| 1022 | struct intel_vgpu_guest_page *g = | ||
| 1023 | intel_vgpu_find_guest_page(vgpu, ops->get_pfn(we)); | ||
| 1024 | if (!g) { | ||
| 1025 | gvt_err("fail to find guest page\n"); | ||
| 1026 | ret = -ENXIO; | ||
| 1027 | goto fail; | ||
| 1028 | } | ||
| 1029 | ret = ppgtt_invalidate_shadow_page(guest_page_to_ppgtt_spt(g)); | ||
| 1030 | if (ret) | ||
| 1031 | goto fail; | ||
| 1032 | } | ||
| 1033 | ops->set_pfn(&e, vgpu->gtt.scratch_page_mfn); | ||
| 1034 | ppgtt_set_shadow_entry(spt, &e, index); | ||
| 1035 | return 0; | ||
| 1036 | fail: | ||
| 1037 | gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d\n", | ||
| 1038 | vgpu->id, spt, we->val64, we->type); | ||
| 1039 | return ret; | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | static int ppgtt_handle_guest_entry_add(struct intel_vgpu_guest_page *gpt, | ||
| 1043 | struct intel_gvt_gtt_entry *we, unsigned long index) | ||
| 1044 | { | ||
| 1045 | struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt); | ||
| 1046 | struct intel_vgpu_shadow_page *sp = &spt->shadow_page; | ||
| 1047 | struct intel_vgpu *vgpu = spt->vgpu; | ||
| 1048 | struct intel_gvt_gtt_entry m; | ||
| 1049 | struct intel_vgpu_ppgtt_spt *s; | ||
| 1050 | int ret; | ||
| 1051 | |||
| 1052 | trace_gpt_change(spt->vgpu->id, "add", spt, sp->type, | ||
| 1053 | we->val64, index); | ||
| 1054 | |||
| 1055 | if (gtt_type_is_pt(get_next_pt_type(we->type))) { | ||
| 1056 | s = ppgtt_populate_shadow_page_by_guest_entry(vgpu, we); | ||
| 1057 | if (IS_ERR(s)) { | ||
| 1058 | ret = PTR_ERR(s); | ||
| 1059 | goto fail; | ||
| 1060 | } | ||
| 1061 | ppgtt_get_shadow_entry(spt, &m, index); | ||
| 1062 | ppgtt_generate_shadow_entry(&m, s, we); | ||
| 1063 | ppgtt_set_shadow_entry(spt, &m, index); | ||
| 1064 | } else { | ||
| 1065 | ret = gtt_entry_p2m(vgpu, we, &m); | ||
| 1066 | if (ret) | ||
| 1067 | goto fail; | ||
| 1068 | ppgtt_set_shadow_entry(spt, &m, index); | ||
| 1069 | } | ||
| 1070 | return 0; | ||
| 1071 | fail: | ||
| 1072 | gvt_err("vgpu%d: fail: spt %p guest entry 0x%llx type %d\n", vgpu->id, | ||
| 1073 | spt, we->val64, we->type); | ||
| 1074 | return ret; | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | static int sync_oos_page(struct intel_vgpu *vgpu, | ||
| 1078 | struct intel_vgpu_oos_page *oos_page) | ||
| 1079 | { | ||
| 1080 | const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; | ||
| 1081 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 1082 | struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; | ||
| 1083 | struct intel_vgpu_ppgtt_spt *spt = | ||
| 1084 | guest_page_to_ppgtt_spt(oos_page->guest_page); | ||
| 1085 | struct intel_gvt_gtt_entry old, new, m; | ||
| 1086 | int index; | ||
| 1087 | int ret; | ||
| 1088 | |||
| 1089 | trace_oos_change(vgpu->id, "sync", oos_page->id, | ||
| 1090 | oos_page->guest_page, spt->guest_page_type); | ||
| 1091 | |||
| 1092 | old.type = new.type = get_entry_type(spt->guest_page_type); | ||
| 1093 | old.val64 = new.val64 = 0; | ||
| 1094 | |||
| 1095 | for (index = 0; index < (GTT_PAGE_SIZE >> info->gtt_entry_size_shift); | ||
| 1096 | index++) { | ||
| 1097 | ops->get_entry(oos_page->mem, &old, index, false, 0, vgpu); | ||
| 1098 | ops->get_entry(NULL, &new, index, true, | ||
| 1099 | oos_page->guest_page->gfn << PAGE_SHIFT, vgpu); | ||
| 1100 | |||
| 1101 | if (old.val64 == new.val64 | ||
| 1102 | && !test_and_clear_bit(index, spt->post_shadow_bitmap)) | ||
| 1103 | continue; | ||
| 1104 | |||
| 1105 | trace_oos_sync(vgpu->id, oos_page->id, | ||
| 1106 | oos_page->guest_page, spt->guest_page_type, | ||
| 1107 | new.val64, index); | ||
| 1108 | |||
| 1109 | ret = gtt_entry_p2m(vgpu, &new, &m); | ||
| 1110 | if (ret) | ||
| 1111 | return ret; | ||
| 1112 | |||
| 1113 | ops->set_entry(oos_page->mem, &new, index, false, 0, vgpu); | ||
| 1114 | ppgtt_set_shadow_entry(spt, &m, index); | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | oos_page->guest_page->write_cnt = 0; | ||
| 1118 | list_del_init(&spt->post_shadow_list); | ||
| 1119 | return 0; | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | static int detach_oos_page(struct intel_vgpu *vgpu, | ||
| 1123 | struct intel_vgpu_oos_page *oos_page) | ||
| 1124 | { | ||
| 1125 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 1126 | struct intel_vgpu_ppgtt_spt *spt = | ||
| 1127 | guest_page_to_ppgtt_spt(oos_page->guest_page); | ||
| 1128 | |||
| 1129 | trace_oos_change(vgpu->id, "detach", oos_page->id, | ||
| 1130 | oos_page->guest_page, spt->guest_page_type); | ||
| 1131 | |||
| 1132 | oos_page->guest_page->write_cnt = 0; | ||
| 1133 | oos_page->guest_page->oos_page = NULL; | ||
| 1134 | oos_page->guest_page = NULL; | ||
| 1135 | |||
| 1136 | list_del_init(&oos_page->vm_list); | ||
| 1137 | list_move_tail(&oos_page->list, &gvt->gtt.oos_page_free_list_head); | ||
| 1138 | |||
| 1139 | return 0; | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | static int attach_oos_page(struct intel_vgpu *vgpu, | ||
| 1143 | struct intel_vgpu_oos_page *oos_page, | ||
| 1144 | struct intel_vgpu_guest_page *gpt) | ||
| 1145 | { | ||
| 1146 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 1147 | int ret; | ||
| 1148 | |||
| 1149 | ret = intel_gvt_hypervisor_read_gpa(vgpu, gpt->gfn << GTT_PAGE_SHIFT, | ||
| 1150 | oos_page->mem, GTT_PAGE_SIZE); | ||
| 1151 | if (ret) | ||
| 1152 | return ret; | ||
| 1153 | |||
| 1154 | oos_page->guest_page = gpt; | ||
| 1155 | gpt->oos_page = oos_page; | ||
| 1156 | |||
| 1157 | list_move_tail(&oos_page->list, &gvt->gtt.oos_page_use_list_head); | ||
| 1158 | |||
| 1159 | trace_oos_change(vgpu->id, "attach", gpt->oos_page->id, | ||
| 1160 | gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type); | ||
| 1161 | return 0; | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | static int ppgtt_set_guest_page_sync(struct intel_vgpu *vgpu, | ||
| 1165 | struct intel_vgpu_guest_page *gpt) | ||
| 1166 | { | ||
| 1167 | int ret; | ||
| 1168 | |||
| 1169 | ret = intel_gvt_hypervisor_set_wp_page(vgpu, gpt); | ||
| 1170 | if (ret) | ||
| 1171 | return ret; | ||
| 1172 | |||
| 1173 | trace_oos_change(vgpu->id, "set page sync", gpt->oos_page->id, | ||
| 1174 | gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type); | ||
| 1175 | |||
| 1176 | list_del_init(&gpt->oos_page->vm_list); | ||
| 1177 | return sync_oos_page(vgpu, gpt->oos_page); | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | static int ppgtt_allocate_oos_page(struct intel_vgpu *vgpu, | ||
| 1181 | struct intel_vgpu_guest_page *gpt) | ||
| 1182 | { | ||
| 1183 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 1184 | struct intel_gvt_gtt *gtt = &gvt->gtt; | ||
| 1185 | struct intel_vgpu_oos_page *oos_page = gpt->oos_page; | ||
| 1186 | int ret; | ||
| 1187 | |||
| 1188 | WARN(oos_page, "shadow PPGTT page has already has a oos page\n"); | ||
| 1189 | |||
| 1190 | if (list_empty(>t->oos_page_free_list_head)) { | ||
| 1191 | oos_page = container_of(gtt->oos_page_use_list_head.next, | ||
| 1192 | struct intel_vgpu_oos_page, list); | ||
| 1193 | ret = ppgtt_set_guest_page_sync(vgpu, oos_page->guest_page); | ||
| 1194 | if (ret) | ||
| 1195 | return ret; | ||
| 1196 | ret = detach_oos_page(vgpu, oos_page); | ||
| 1197 | if (ret) | ||
| 1198 | return ret; | ||
| 1199 | } else | ||
| 1200 | oos_page = container_of(gtt->oos_page_free_list_head.next, | ||
| 1201 | struct intel_vgpu_oos_page, list); | ||
| 1202 | return attach_oos_page(vgpu, oos_page, gpt); | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | static int ppgtt_set_guest_page_oos(struct intel_vgpu *vgpu, | ||
| 1206 | struct intel_vgpu_guest_page *gpt) | ||
| 1207 | { | ||
| 1208 | struct intel_vgpu_oos_page *oos_page = gpt->oos_page; | ||
| 1209 | |||
| 1210 | if (WARN(!oos_page, "shadow PPGTT page should have a oos page\n")) | ||
| 1211 | return -EINVAL; | ||
| 1212 | |||
| 1213 | trace_oos_change(vgpu->id, "set page out of sync", gpt->oos_page->id, | ||
| 1214 | gpt, guest_page_to_ppgtt_spt(gpt)->guest_page_type); | ||
| 1215 | |||
| 1216 | list_add_tail(&oos_page->vm_list, &vgpu->gtt.oos_page_list_head); | ||
| 1217 | return intel_gvt_hypervisor_unset_wp_page(vgpu, gpt); | ||
| 1218 | } | ||
| 1219 | |||
| 1220 | /** | ||
| 1221 | * intel_vgpu_sync_oos_pages - sync all the out-of-synced shadow for vGPU | ||
| 1222 | * @vgpu: a vGPU | ||
| 1223 | * | ||
| 1224 | * This function is called before submitting a guest workload to host, | ||
| 1225 | * to sync all the out-of-synced shadow for vGPU | ||
| 1226 | * | ||
| 1227 | * Returns: | ||
| 1228 | * Zero on success, negative error code if failed. | ||
| 1229 | */ | ||
| 1230 | int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu) | ||
| 1231 | { | ||
| 1232 | struct list_head *pos, *n; | ||
| 1233 | struct intel_vgpu_oos_page *oos_page; | ||
| 1234 | int ret; | ||
| 1235 | |||
| 1236 | if (!enable_out_of_sync) | ||
| 1237 | return 0; | ||
| 1238 | |||
| 1239 | list_for_each_safe(pos, n, &vgpu->gtt.oos_page_list_head) { | ||
| 1240 | oos_page = container_of(pos, | ||
| 1241 | struct intel_vgpu_oos_page, vm_list); | ||
| 1242 | ret = ppgtt_set_guest_page_sync(vgpu, oos_page->guest_page); | ||
| 1243 | if (ret) | ||
| 1244 | return ret; | ||
| 1245 | } | ||
| 1246 | return 0; | ||
| 1247 | } | ||
| 1248 | |||
| 1249 | /* | ||
| 1250 | * The heart of PPGTT shadow page table. | ||
| 1251 | */ | ||
| 1252 | static int ppgtt_handle_guest_write_page_table( | ||
| 1253 | struct intel_vgpu_guest_page *gpt, | ||
| 1254 | struct intel_gvt_gtt_entry *we, unsigned long index) | ||
| 1255 | { | ||
| 1256 | struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt); | ||
| 1257 | struct intel_vgpu *vgpu = spt->vgpu; | ||
| 1258 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; | ||
| 1259 | struct intel_gvt_gtt_entry ge; | ||
| 1260 | |||
| 1261 | int old_present, new_present; | ||
| 1262 | int ret; | ||
| 1263 | |||
| 1264 | ppgtt_get_guest_entry(spt, &ge, index); | ||
| 1265 | |||
| 1266 | old_present = ops->test_present(&ge); | ||
| 1267 | new_present = ops->test_present(we); | ||
| 1268 | |||
| 1269 | ppgtt_set_guest_entry(spt, we, index); | ||
| 1270 | |||
| 1271 | if (old_present) { | ||
| 1272 | ret = ppgtt_handle_guest_entry_removal(gpt, &ge, index); | ||
| 1273 | if (ret) | ||
| 1274 | goto fail; | ||
| 1275 | } | ||
| 1276 | if (new_present) { | ||
| 1277 | ret = ppgtt_handle_guest_entry_add(gpt, we, index); | ||
| 1278 | if (ret) | ||
| 1279 | goto fail; | ||
| 1280 | } | ||
| 1281 | return 0; | ||
| 1282 | fail: | ||
| 1283 | gvt_err("vgpu%d: fail: shadow page %p guest entry 0x%llx type %d.\n", | ||
| 1284 | vgpu->id, spt, we->val64, we->type); | ||
| 1285 | return ret; | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | static inline bool can_do_out_of_sync(struct intel_vgpu_guest_page *gpt) | ||
| 1289 | { | ||
| 1290 | return enable_out_of_sync | ||
| 1291 | && gtt_type_is_pte_pt( | ||
| 1292 | guest_page_to_ppgtt_spt(gpt)->guest_page_type) | ||
| 1293 | && gpt->write_cnt >= 2; | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | static void ppgtt_set_post_shadow(struct intel_vgpu_ppgtt_spt *spt, | ||
| 1297 | unsigned long index) | ||
| 1298 | { | ||
| 1299 | set_bit(index, spt->post_shadow_bitmap); | ||
| 1300 | if (!list_empty(&spt->post_shadow_list)) | ||
| 1301 | return; | ||
| 1302 | |||
| 1303 | list_add_tail(&spt->post_shadow_list, | ||
| 1304 | &spt->vgpu->gtt.post_shadow_list_head); | ||
| 1305 | } | ||
| 1306 | |||
| 1307 | /** | ||
| 1308 | * intel_vgpu_flush_post_shadow - flush the post shadow transactions | ||
| 1309 | * @vgpu: a vGPU | ||
| 1310 | * | ||
| 1311 | * This function is called before submitting a guest workload to host, | ||
| 1312 | * to flush all the post shadows for a vGPU. | ||
| 1313 | * | ||
| 1314 | * Returns: | ||
| 1315 | * Zero on success, negative error code if failed. | ||
| 1316 | */ | ||
| 1317 | int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu) | ||
| 1318 | { | ||
| 1319 | struct list_head *pos, *n; | ||
| 1320 | struct intel_vgpu_ppgtt_spt *spt; | ||
| 1321 | struct intel_gvt_gtt_entry ge, e; | ||
| 1322 | unsigned long index; | ||
| 1323 | int ret; | ||
| 1324 | |||
| 1325 | list_for_each_safe(pos, n, &vgpu->gtt.post_shadow_list_head) { | ||
| 1326 | spt = container_of(pos, struct intel_vgpu_ppgtt_spt, | ||
| 1327 | post_shadow_list); | ||
| 1328 | |||
| 1329 | for_each_set_bit(index, spt->post_shadow_bitmap, | ||
| 1330 | GTT_ENTRY_NUM_IN_ONE_PAGE) { | ||
| 1331 | ppgtt_get_guest_entry(spt, &ge, index); | ||
| 1332 | e = ge; | ||
| 1333 | e.val64 = 0; | ||
| 1334 | ppgtt_set_guest_entry(spt, &e, index); | ||
| 1335 | |||
| 1336 | ret = ppgtt_handle_guest_write_page_table( | ||
| 1337 | &spt->guest_page, &ge, index); | ||
| 1338 | if (ret) | ||
| 1339 | return ret; | ||
| 1340 | clear_bit(index, spt->post_shadow_bitmap); | ||
| 1341 | } | ||
| 1342 | list_del_init(&spt->post_shadow_list); | ||
| 1343 | } | ||
| 1344 | return 0; | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | static int ppgtt_handle_guest_write_page_table_bytes(void *gp, | ||
| 1348 | u64 pa, void *p_data, int bytes) | ||
| 1349 | { | ||
| 1350 | struct intel_vgpu_guest_page *gpt = (struct intel_vgpu_guest_page *)gp; | ||
| 1351 | struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt); | ||
| 1352 | struct intel_vgpu *vgpu = spt->vgpu; | ||
| 1353 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; | ||
| 1354 | const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; | ||
| 1355 | struct intel_gvt_gtt_entry we; | ||
| 1356 | unsigned long index; | ||
| 1357 | int ret; | ||
| 1358 | |||
| 1359 | index = (pa & (PAGE_SIZE - 1)) >> info->gtt_entry_size_shift; | ||
| 1360 | |||
| 1361 | ppgtt_get_guest_entry(spt, &we, index); | ||
| 1362 | memcpy((void *)&we.val64 + (pa & (info->gtt_entry_size - 1)), | ||
| 1363 | p_data, bytes); | ||
| 1364 | |||
| 1365 | ops->test_pse(&we); | ||
| 1366 | |||
| 1367 | if (bytes == info->gtt_entry_size) { | ||
| 1368 | ret = ppgtt_handle_guest_write_page_table(gpt, &we, index); | ||
| 1369 | if (ret) | ||
| 1370 | return ret; | ||
| 1371 | } else { | ||
| 1372 | struct intel_gvt_gtt_entry ge; | ||
| 1373 | |||
| 1374 | ppgtt_get_guest_entry(spt, &ge, index); | ||
| 1375 | |||
| 1376 | if (!test_bit(index, spt->post_shadow_bitmap)) { | ||
| 1377 | ret = ppgtt_handle_guest_entry_removal(gpt, | ||
| 1378 | &ge, index); | ||
| 1379 | if (ret) | ||
| 1380 | return ret; | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | ppgtt_set_post_shadow(spt, index); | ||
| 1384 | ppgtt_set_guest_entry(spt, &we, index); | ||
| 1385 | } | ||
| 1386 | |||
| 1387 | if (!enable_out_of_sync) | ||
| 1388 | return 0; | ||
| 1389 | |||
| 1390 | gpt->write_cnt++; | ||
| 1391 | |||
| 1392 | if (gpt->oos_page) | ||
| 1393 | ops->set_entry(gpt->oos_page->mem, &we, index, | ||
| 1394 | false, 0, vgpu); | ||
| 1395 | |||
| 1396 | if (can_do_out_of_sync(gpt)) { | ||
| 1397 | if (!gpt->oos_page) | ||
| 1398 | ppgtt_allocate_oos_page(vgpu, gpt); | ||
| 1399 | |||
| 1400 | ret = ppgtt_set_guest_page_oos(vgpu, gpt); | ||
| 1401 | if (ret < 0) | ||
| 1402 | return ret; | ||
| 1403 | } | ||
| 1404 | return 0; | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | /* | ||
| 1408 | * mm page table allocation policy for bdw+ | ||
| 1409 | * - for ggtt, only virtual page table will be allocated. | ||
| 1410 | * - for ppgtt, dedicated virtual/shadow page table will be allocated. | ||
| 1411 | */ | ||
| 1412 | static int gen8_mm_alloc_page_table(struct intel_vgpu_mm *mm) | ||
| 1413 | { | ||
| 1414 | struct intel_vgpu *vgpu = mm->vgpu; | ||
| 1415 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 1416 | const struct intel_gvt_device_info *info = &gvt->device_info; | ||
| 1417 | void *mem; | ||
| 1418 | |||
| 1419 | if (mm->type == INTEL_GVT_MM_PPGTT) { | ||
| 1420 | mm->page_table_entry_cnt = 4; | ||
| 1421 | mm->page_table_entry_size = mm->page_table_entry_cnt * | ||
| 1422 | info->gtt_entry_size; | ||
| 1423 | mem = kzalloc(mm->has_shadow_page_table ? | ||
| 1424 | mm->page_table_entry_size * 2 | ||
| 1425 | : mm->page_table_entry_size, | ||
| 1426 | GFP_ATOMIC); | ||
| 1427 | if (!mem) | ||
| 1428 | return -ENOMEM; | ||
| 1429 | mm->virtual_page_table = mem; | ||
| 1430 | if (!mm->has_shadow_page_table) | ||
| 1431 | return 0; | ||
| 1432 | mm->shadow_page_table = mem + mm->page_table_entry_size; | ||
| 1433 | } else if (mm->type == INTEL_GVT_MM_GGTT) { | ||
| 1434 | mm->page_table_entry_cnt = | ||
| 1435 | (gvt_ggtt_gm_sz(gvt) >> GTT_PAGE_SHIFT); | ||
| 1436 | mm->page_table_entry_size = mm->page_table_entry_cnt * | ||
| 1437 | info->gtt_entry_size; | ||
| 1438 | mem = vzalloc(mm->page_table_entry_size); | ||
| 1439 | if (!mem) | ||
| 1440 | return -ENOMEM; | ||
| 1441 | mm->virtual_page_table = mem; | ||
| 1442 | } | ||
| 1443 | return 0; | ||
| 1444 | } | ||
| 1445 | |||
| 1446 | static void gen8_mm_free_page_table(struct intel_vgpu_mm *mm) | ||
| 1447 | { | ||
| 1448 | if (mm->type == INTEL_GVT_MM_PPGTT) { | ||
| 1449 | kfree(mm->virtual_page_table); | ||
| 1450 | } else if (mm->type == INTEL_GVT_MM_GGTT) { | ||
| 1451 | if (mm->virtual_page_table) | ||
| 1452 | vfree(mm->virtual_page_table); | ||
| 1453 | } | ||
| 1454 | mm->virtual_page_table = mm->shadow_page_table = NULL; | ||
| 1455 | } | ||
| 1456 | |||
| 1457 | static void invalidate_mm(struct intel_vgpu_mm *mm) | ||
| 1458 | { | ||
| 1459 | struct intel_vgpu *vgpu = mm->vgpu; | ||
| 1460 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 1461 | struct intel_gvt_gtt *gtt = &gvt->gtt; | ||
| 1462 | struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops; | ||
| 1463 | struct intel_gvt_gtt_entry se; | ||
| 1464 | int i; | ||
| 1465 | |||
| 1466 | if (WARN_ON(!mm->has_shadow_page_table || !mm->shadowed)) | ||
| 1467 | return; | ||
| 1468 | |||
| 1469 | for (i = 0; i < mm->page_table_entry_cnt; i++) { | ||
| 1470 | ppgtt_get_shadow_root_entry(mm, &se, i); | ||
| 1471 | if (!ops->test_present(&se)) | ||
| 1472 | continue; | ||
| 1473 | ppgtt_invalidate_shadow_page_by_shadow_entry( | ||
| 1474 | vgpu, &se); | ||
| 1475 | se.val64 = 0; | ||
| 1476 | ppgtt_set_shadow_root_entry(mm, &se, i); | ||
| 1477 | |||
| 1478 | trace_gpt_change(vgpu->id, "destroy root pointer", | ||
| 1479 | NULL, se.type, se.val64, i); | ||
| 1480 | } | ||
| 1481 | mm->shadowed = false; | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | /** | ||
| 1485 | * intel_vgpu_destroy_mm - destroy a mm object | ||
| 1486 | * @mm: a kref object | ||
| 1487 | * | ||
| 1488 | * This function is used to destroy a mm object for vGPU | ||
| 1489 | * | ||
| 1490 | */ | ||
| 1491 | void intel_vgpu_destroy_mm(struct kref *mm_ref) | ||
| 1492 | { | ||
| 1493 | struct intel_vgpu_mm *mm = container_of(mm_ref, typeof(*mm), ref); | ||
| 1494 | struct intel_vgpu *vgpu = mm->vgpu; | ||
| 1495 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 1496 | struct intel_gvt_gtt *gtt = &gvt->gtt; | ||
| 1497 | |||
| 1498 | if (!mm->initialized) | ||
| 1499 | goto out; | ||
| 1500 | |||
| 1501 | list_del(&mm->list); | ||
| 1502 | list_del(&mm->lru_list); | ||
| 1503 | |||
| 1504 | if (mm->has_shadow_page_table) | ||
| 1505 | invalidate_mm(mm); | ||
| 1506 | |||
| 1507 | gtt->mm_free_page_table(mm); | ||
| 1508 | out: | ||
| 1509 | kfree(mm); | ||
| 1510 | } | ||
| 1511 | |||
| 1512 | static int shadow_mm(struct intel_vgpu_mm *mm) | ||
| 1513 | { | ||
| 1514 | struct intel_vgpu *vgpu = mm->vgpu; | ||
| 1515 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 1516 | struct intel_gvt_gtt *gtt = &gvt->gtt; | ||
| 1517 | struct intel_gvt_gtt_pte_ops *ops = gtt->pte_ops; | ||
| 1518 | struct intel_vgpu_ppgtt_spt *spt; | ||
| 1519 | struct intel_gvt_gtt_entry ge, se; | ||
| 1520 | int i; | ||
| 1521 | int ret; | ||
| 1522 | |||
| 1523 | if (WARN_ON(!mm->has_shadow_page_table || mm->shadowed)) | ||
| 1524 | return 0; | ||
| 1525 | |||
| 1526 | mm->shadowed = true; | ||
| 1527 | |||
| 1528 | for (i = 0; i < mm->page_table_entry_cnt; i++) { | ||
| 1529 | ppgtt_get_guest_root_entry(mm, &ge, i); | ||
| 1530 | if (!ops->test_present(&ge)) | ||
| 1531 | continue; | ||
| 1532 | |||
| 1533 | trace_gpt_change(vgpu->id, __func__, NULL, | ||
| 1534 | ge.type, ge.val64, i); | ||
| 1535 | |||
| 1536 | spt = ppgtt_populate_shadow_page_by_guest_entry(vgpu, &ge); | ||
| 1537 | if (IS_ERR(spt)) { | ||
| 1538 | gvt_err("fail to populate guest root pointer\n"); | ||
| 1539 | ret = PTR_ERR(spt); | ||
| 1540 | goto fail; | ||
| 1541 | } | ||
| 1542 | ppgtt_generate_shadow_entry(&se, spt, &ge); | ||
| 1543 | ppgtt_set_shadow_root_entry(mm, &se, i); | ||
| 1544 | |||
| 1545 | trace_gpt_change(vgpu->id, "populate root pointer", | ||
| 1546 | NULL, se.type, se.val64, i); | ||
| 1547 | } | ||
| 1548 | return 0; | ||
| 1549 | fail: | ||
| 1550 | invalidate_mm(mm); | ||
| 1551 | return ret; | ||
| 1552 | } | ||
| 1553 | |||
| 1554 | /** | ||
| 1555 | * intel_vgpu_create_mm - create a mm object for a vGPU | ||
| 1556 | * @vgpu: a vGPU | ||
| 1557 | * @mm_type: mm object type, should be PPGTT or GGTT | ||
| 1558 | * @virtual_page_table: page table root pointers. Could be NULL if user wants | ||
| 1559 | * to populate shadow later. | ||
| 1560 | * @page_table_level: describe the page table level of the mm object | ||
| 1561 | * @pde_base_index: pde root pointer base in GGTT MMIO. | ||
| 1562 | * | ||
| 1563 | * This function is used to create a mm object for a vGPU. | ||
| 1564 | * | ||
| 1565 | * Returns: | ||
| 1566 | * Zero on success, negative error code in pointer if failed. | ||
| 1567 | */ | ||
| 1568 | struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu, | ||
| 1569 | int mm_type, void *virtual_page_table, int page_table_level, | ||
| 1570 | u32 pde_base_index) | ||
| 1571 | { | ||
| 1572 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 1573 | struct intel_gvt_gtt *gtt = &gvt->gtt; | ||
| 1574 | struct intel_vgpu_mm *mm; | ||
| 1575 | int ret; | ||
| 1576 | |||
| 1577 | mm = kzalloc(sizeof(*mm), GFP_ATOMIC); | ||
| 1578 | if (!mm) { | ||
| 1579 | ret = -ENOMEM; | ||
| 1580 | goto fail; | ||
| 1581 | } | ||
| 1582 | |||
| 1583 | mm->type = mm_type; | ||
| 1584 | |||
| 1585 | if (page_table_level == 1) | ||
| 1586 | mm->page_table_entry_type = GTT_TYPE_GGTT_PTE; | ||
| 1587 | else if (page_table_level == 3) | ||
| 1588 | mm->page_table_entry_type = GTT_TYPE_PPGTT_ROOT_L3_ENTRY; | ||
| 1589 | else if (page_table_level == 4) | ||
| 1590 | mm->page_table_entry_type = GTT_TYPE_PPGTT_ROOT_L4_ENTRY; | ||
| 1591 | else { | ||
| 1592 | WARN_ON(1); | ||
| 1593 | ret = -EINVAL; | ||
| 1594 | goto fail; | ||
| 1595 | } | ||
| 1596 | |||
| 1597 | mm->page_table_level = page_table_level; | ||
| 1598 | mm->pde_base_index = pde_base_index; | ||
| 1599 | |||
| 1600 | mm->vgpu = vgpu; | ||
| 1601 | mm->has_shadow_page_table = !!(mm_type == INTEL_GVT_MM_PPGTT); | ||
| 1602 | |||
| 1603 | kref_init(&mm->ref); | ||
| 1604 | atomic_set(&mm->pincount, 0); | ||
| 1605 | INIT_LIST_HEAD(&mm->list); | ||
| 1606 | INIT_LIST_HEAD(&mm->lru_list); | ||
| 1607 | list_add_tail(&mm->list, &vgpu->gtt.mm_list_head); | ||
| 1608 | |||
| 1609 | ret = gtt->mm_alloc_page_table(mm); | ||
| 1610 | if (ret) { | ||
| 1611 | gvt_err("fail to allocate page table for mm\n"); | ||
| 1612 | goto fail; | ||
| 1613 | } | ||
| 1614 | |||
| 1615 | mm->initialized = true; | ||
| 1616 | |||
| 1617 | if (virtual_page_table) | ||
| 1618 | memcpy(mm->virtual_page_table, virtual_page_table, | ||
| 1619 | mm->page_table_entry_size); | ||
| 1620 | |||
| 1621 | if (mm->has_shadow_page_table) { | ||
| 1622 | ret = shadow_mm(mm); | ||
| 1623 | if (ret) | ||
| 1624 | goto fail; | ||
| 1625 | list_add_tail(&mm->lru_list, &gvt->gtt.mm_lru_list_head); | ||
| 1626 | } | ||
| 1627 | return mm; | ||
| 1628 | fail: | ||
| 1629 | gvt_err("fail to create mm\n"); | ||
| 1630 | if (mm) | ||
| 1631 | intel_gvt_mm_unreference(mm); | ||
| 1632 | return ERR_PTR(ret); | ||
| 1633 | } | ||
| 1634 | |||
| 1635 | /** | ||
| 1636 | * intel_vgpu_unpin_mm - decrease the pin count of a vGPU mm object | ||
| 1637 | * @mm: a vGPU mm object | ||
| 1638 | * | ||
| 1639 | * This function is called when user doesn't want to use a vGPU mm object | ||
| 1640 | */ | ||
| 1641 | void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm) | ||
| 1642 | { | ||
| 1643 | if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT)) | ||
| 1644 | return; | ||
| 1645 | |||
| 1646 | atomic_dec(&mm->pincount); | ||
| 1647 | } | ||
| 1648 | |||
| 1649 | /** | ||
| 1650 | * intel_vgpu_pin_mm - increase the pin count of a vGPU mm object | ||
| 1651 | * @vgpu: a vGPU | ||
| 1652 | * | ||
| 1653 | * This function is called when user wants to use a vGPU mm object. If this | ||
| 1654 | * mm object hasn't been shadowed yet, the shadow will be populated at this | ||
| 1655 | * time. | ||
| 1656 | * | ||
| 1657 | * Returns: | ||
| 1658 | * Zero on success, negative error code if failed. | ||
| 1659 | */ | ||
| 1660 | int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm) | ||
| 1661 | { | ||
| 1662 | int ret; | ||
| 1663 | |||
| 1664 | if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT)) | ||
| 1665 | return 0; | ||
| 1666 | |||
| 1667 | atomic_inc(&mm->pincount); | ||
| 1668 | |||
| 1669 | if (!mm->shadowed) { | ||
| 1670 | ret = shadow_mm(mm); | ||
| 1671 | if (ret) | ||
| 1672 | return ret; | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | list_del_init(&mm->lru_list); | ||
| 1676 | list_add_tail(&mm->lru_list, &mm->vgpu->gvt->gtt.mm_lru_list_head); | ||
| 1677 | return 0; | ||
| 1678 | } | ||
| 1679 | |||
| 1680 | static int reclaim_one_mm(struct intel_gvt *gvt) | ||
| 1681 | { | ||
| 1682 | struct intel_vgpu_mm *mm; | ||
| 1683 | struct list_head *pos, *n; | ||
| 1684 | |||
| 1685 | list_for_each_safe(pos, n, &gvt->gtt.mm_lru_list_head) { | ||
| 1686 | mm = container_of(pos, struct intel_vgpu_mm, lru_list); | ||
| 1687 | |||
| 1688 | if (mm->type != INTEL_GVT_MM_PPGTT) | ||
| 1689 | continue; | ||
| 1690 | if (atomic_read(&mm->pincount)) | ||
| 1691 | continue; | ||
| 1692 | |||
| 1693 | list_del_init(&mm->lru_list); | ||
| 1694 | invalidate_mm(mm); | ||
| 1695 | return 1; | ||
| 1696 | } | ||
| 1697 | return 0; | ||
| 1698 | } | ||
| 1699 | |||
| 1700 | /* | ||
| 1701 | * GMA translation APIs. | ||
| 1702 | */ | ||
| 1703 | static inline int ppgtt_get_next_level_entry(struct intel_vgpu_mm *mm, | ||
| 1704 | struct intel_gvt_gtt_entry *e, unsigned long index, bool guest) | ||
| 1705 | { | ||
| 1706 | struct intel_vgpu *vgpu = mm->vgpu; | ||
| 1707 | struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops; | ||
| 1708 | struct intel_vgpu_ppgtt_spt *s; | ||
| 1709 | |||
| 1710 | if (WARN_ON(!mm->has_shadow_page_table)) | ||
| 1711 | return -EINVAL; | ||
| 1712 | |||
| 1713 | s = ppgtt_find_shadow_page(vgpu, ops->get_pfn(e)); | ||
| 1714 | if (!s) | ||
| 1715 | return -ENXIO; | ||
| 1716 | |||
| 1717 | if (!guest) | ||
| 1718 | ppgtt_get_shadow_entry(s, e, index); | ||
| 1719 | else | ||
| 1720 | ppgtt_get_guest_entry(s, e, index); | ||
| 1721 | return 0; | ||
| 1722 | } | ||
| 1723 | |||
| 1724 | /** | ||
| 1725 | * intel_vgpu_gma_to_gpa - translate a gma to GPA | ||
| 1726 | * @mm: mm object. could be a PPGTT or GGTT mm object | ||
| 1727 | * @gma: graphics memory address in this mm object | ||
| 1728 | * | ||
| 1729 | * This function is used to translate a graphics memory address in specific | ||
| 1730 | * graphics memory space to guest physical address. | ||
| 1731 | * | ||
| 1732 | * Returns: | ||
| 1733 | * Guest physical address on success, INTEL_GVT_INVALID_ADDR if failed. | ||
| 1734 | */ | ||
| 1735 | unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma) | ||
| 1736 | { | ||
| 1737 | struct intel_vgpu *vgpu = mm->vgpu; | ||
| 1738 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 1739 | struct intel_gvt_gtt_pte_ops *pte_ops = gvt->gtt.pte_ops; | ||
| 1740 | struct intel_gvt_gtt_gma_ops *gma_ops = gvt->gtt.gma_ops; | ||
| 1741 | unsigned long gpa = INTEL_GVT_INVALID_ADDR; | ||
| 1742 | unsigned long gma_index[4]; | ||
| 1743 | struct intel_gvt_gtt_entry e; | ||
| 1744 | int i, index; | ||
| 1745 | int ret; | ||
| 1746 | |||
| 1747 | if (mm->type != INTEL_GVT_MM_GGTT && mm->type != INTEL_GVT_MM_PPGTT) | ||
| 1748 | return INTEL_GVT_INVALID_ADDR; | ||
| 1749 | |||
| 1750 | if (mm->type == INTEL_GVT_MM_GGTT) { | ||
| 1751 | if (!vgpu_gmadr_is_valid(vgpu, gma)) | ||
| 1752 | goto err; | ||
| 1753 | |||
| 1754 | ggtt_get_guest_entry(mm, &e, | ||
| 1755 | gma_ops->gma_to_ggtt_pte_index(gma)); | ||
| 1756 | gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT) | ||
| 1757 | + (gma & ~GTT_PAGE_MASK); | ||
| 1758 | |||
| 1759 | trace_gma_translate(vgpu->id, "ggtt", 0, 0, gma, gpa); | ||
| 1760 | return gpa; | ||
| 1761 | } | ||
| 1762 | |||
| 1763 | switch (mm->page_table_level) { | ||
| 1764 | case 4: | ||
| 1765 | ppgtt_get_shadow_root_entry(mm, &e, 0); | ||
| 1766 | gma_index[0] = gma_ops->gma_to_pml4_index(gma); | ||
| 1767 | gma_index[1] = gma_ops->gma_to_l4_pdp_index(gma); | ||
| 1768 | gma_index[2] = gma_ops->gma_to_pde_index(gma); | ||
| 1769 | gma_index[3] = gma_ops->gma_to_pte_index(gma); | ||
| 1770 | index = 4; | ||
| 1771 | break; | ||
| 1772 | case 3: | ||
| 1773 | ppgtt_get_shadow_root_entry(mm, &e, | ||
| 1774 | gma_ops->gma_to_l3_pdp_index(gma)); | ||
| 1775 | gma_index[0] = gma_ops->gma_to_pde_index(gma); | ||
| 1776 | gma_index[1] = gma_ops->gma_to_pte_index(gma); | ||
| 1777 | index = 2; | ||
| 1778 | break; | ||
| 1779 | case 2: | ||
| 1780 | ppgtt_get_shadow_root_entry(mm, &e, | ||
| 1781 | gma_ops->gma_to_pde_index(gma)); | ||
| 1782 | gma_index[0] = gma_ops->gma_to_pte_index(gma); | ||
| 1783 | index = 1; | ||
| 1784 | break; | ||
| 1785 | default: | ||
| 1786 | WARN_ON(1); | ||
| 1787 | goto err; | ||
| 1788 | } | ||
| 1789 | |||
| 1790 | /* walk into the shadow page table and get gpa from guest entry */ | ||
| 1791 | for (i = 0; i < index; i++) { | ||
| 1792 | ret = ppgtt_get_next_level_entry(mm, &e, gma_index[i], | ||
| 1793 | (i == index - 1)); | ||
| 1794 | if (ret) | ||
| 1795 | goto err; | ||
| 1796 | } | ||
| 1797 | |||
| 1798 | gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT) | ||
| 1799 | + (gma & ~GTT_PAGE_MASK); | ||
| 1800 | |||
| 1801 | trace_gma_translate(vgpu->id, "ppgtt", 0, | ||
| 1802 | mm->page_table_level, gma, gpa); | ||
| 1803 | return gpa; | ||
| 1804 | err: | ||
| 1805 | gvt_err("invalid mm type: %d gma %lx\n", mm->type, gma); | ||
| 1806 | return INTEL_GVT_INVALID_ADDR; | ||
| 1807 | } | ||
| 1808 | |||
| 1809 | static int emulate_gtt_mmio_read(struct intel_vgpu *vgpu, | ||
| 1810 | unsigned int off, void *p_data, unsigned int bytes) | ||
| 1811 | { | ||
| 1812 | struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm; | ||
| 1813 | const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; | ||
| 1814 | unsigned long index = off >> info->gtt_entry_size_shift; | ||
| 1815 | struct intel_gvt_gtt_entry e; | ||
| 1816 | |||
| 1817 | if (bytes != 4 && bytes != 8) | ||
| 1818 | return -EINVAL; | ||
| 1819 | |||
| 1820 | ggtt_get_guest_entry(ggtt_mm, &e, index); | ||
| 1821 | memcpy(p_data, (void *)&e.val64 + (off & (info->gtt_entry_size - 1)), | ||
| 1822 | bytes); | ||
| 1823 | return 0; | ||
| 1824 | } | ||
| 1825 | |||
| 1826 | /** | ||
| 1827 | * intel_vgpu_emulate_gtt_mmio_read - emulate GTT MMIO register read | ||
| 1828 | * @vgpu: a vGPU | ||
| 1829 | * @off: register offset | ||
| 1830 | * @p_data: data will be returned to guest | ||
| 1831 | * @bytes: data length | ||
| 1832 | * | ||
| 1833 | * This function is used to emulate the GTT MMIO register read | ||
| 1834 | * | ||
| 1835 | * Returns: | ||
| 1836 | * Zero on success, error code if failed. | ||
| 1837 | */ | ||
| 1838 | int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu, unsigned int off, | ||
| 1839 | void *p_data, unsigned int bytes) | ||
| 1840 | { | ||
| 1841 | const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; | ||
| 1842 | int ret; | ||
| 1843 | |||
| 1844 | if (bytes != 4 && bytes != 8) | ||
| 1845 | return -EINVAL; | ||
| 1846 | |||
| 1847 | off -= info->gtt_start_offset; | ||
| 1848 | ret = emulate_gtt_mmio_read(vgpu, off, p_data, bytes); | ||
| 1849 | return ret; | ||
| 1850 | } | ||
| 1851 | |||
| 1852 | static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, | ||
| 1853 | void *p_data, unsigned int bytes) | ||
| 1854 | { | ||
| 1855 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 1856 | const struct intel_gvt_device_info *info = &gvt->device_info; | ||
| 1857 | struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm; | ||
| 1858 | struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; | ||
| 1859 | unsigned long g_gtt_index = off >> info->gtt_entry_size_shift; | ||
| 1860 | unsigned long gma; | ||
| 1861 | struct intel_gvt_gtt_entry e, m; | ||
| 1862 | int ret; | ||
| 1863 | |||
| 1864 | if (bytes != 4 && bytes != 8) | ||
| 1865 | return -EINVAL; | ||
| 1866 | |||
| 1867 | gma = g_gtt_index << GTT_PAGE_SHIFT; | ||
| 1868 | |||
| 1869 | /* the VM may configure the whole GM space when ballooning is used */ | ||
| 1870 | if (WARN_ONCE(!vgpu_gmadr_is_valid(vgpu, gma), | ||
| 1871 | "vgpu%d: found oob ggtt write, offset %x\n", | ||
| 1872 | vgpu->id, off)) { | ||
| 1873 | return 0; | ||
| 1874 | } | ||
| 1875 | |||
| 1876 | ggtt_get_guest_entry(ggtt_mm, &e, g_gtt_index); | ||
| 1877 | |||
| 1878 | memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data, | ||
| 1879 | bytes); | ||
| 1880 | |||
| 1881 | if (ops->test_present(&e)) { | ||
| 1882 | ret = gtt_entry_p2m(vgpu, &e, &m); | ||
| 1883 | if (ret) { | ||
| 1884 | gvt_err("vgpu%d: fail to translate guest gtt entry\n", | ||
| 1885 | vgpu->id); | ||
| 1886 | return ret; | ||
| 1887 | } | ||
| 1888 | } else { | ||
| 1889 | m = e; | ||
| 1890 | m.val64 = 0; | ||
| 1891 | } | ||
| 1892 | |||
| 1893 | ggtt_set_shadow_entry(ggtt_mm, &m, g_gtt_index); | ||
| 1894 | ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index); | ||
| 1895 | return 0; | ||
| 1896 | } | ||
| 1897 | |||
| 1898 | /* | ||
| 1899 | * intel_vgpu_emulate_gtt_mmio_write - emulate GTT MMIO register write | ||
| 1900 | * @vgpu: a vGPU | ||
| 1901 | * @off: register offset | ||
| 1902 | * @p_data: data from guest write | ||
| 1903 | * @bytes: data length | ||
| 1904 | * | ||
| 1905 | * This function is used to emulate the GTT MMIO register write | ||
| 1906 | * | ||
| 1907 | * Returns: | ||
| 1908 | * Zero on success, error code if failed. | ||
| 1909 | */ | ||
| 1910 | int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, | ||
| 1911 | void *p_data, unsigned int bytes) | ||
| 1912 | { | ||
| 1913 | const struct intel_gvt_device_info *info = &vgpu->gvt->device_info; | ||
| 1914 | int ret; | ||
| 1915 | |||
| 1916 | if (bytes != 4 && bytes != 8) | ||
| 1917 | return -EINVAL; | ||
| 1918 | |||
| 1919 | off -= info->gtt_start_offset; | ||
| 1920 | ret = emulate_gtt_mmio_write(vgpu, off, p_data, bytes); | ||
| 1921 | return ret; | ||
| 1922 | } | ||
| 1923 | |||
| 1924 | static int create_scratch_page(struct intel_vgpu *vgpu) | ||
| 1925 | { | ||
| 1926 | struct intel_vgpu_gtt *gtt = &vgpu->gtt; | ||
| 1927 | void *p; | ||
| 1928 | void *vaddr; | ||
| 1929 | unsigned long mfn; | ||
| 1930 | |||
| 1931 | gtt->scratch_page = alloc_page(GFP_KERNEL); | ||
| 1932 | if (!gtt->scratch_page) { | ||
| 1933 | gvt_err("Failed to allocate scratch page.\n"); | ||
| 1934 | return -ENOMEM; | ||
| 1935 | } | ||
| 1936 | |||
| 1937 | /* set to zero */ | ||
| 1938 | p = kmap_atomic(gtt->scratch_page); | ||
| 1939 | memset(p, 0, PAGE_SIZE); | ||
| 1940 | kunmap_atomic(p); | ||
| 1941 | |||
| 1942 | /* translate page to mfn */ | ||
| 1943 | vaddr = page_address(gtt->scratch_page); | ||
| 1944 | mfn = intel_gvt_hypervisor_virt_to_mfn(vaddr); | ||
| 1945 | |||
| 1946 | if (mfn == INTEL_GVT_INVALID_ADDR) { | ||
| 1947 | gvt_err("fail to translate vaddr:0x%llx\n", (u64)vaddr); | ||
| 1948 | __free_page(gtt->scratch_page); | ||
| 1949 | gtt->scratch_page = NULL; | ||
| 1950 | return -ENXIO; | ||
| 1951 | } | ||
| 1952 | |||
| 1953 | gtt->scratch_page_mfn = mfn; | ||
| 1954 | gvt_dbg_core("vgpu%d create scratch page: mfn=0x%lx\n", vgpu->id, mfn); | ||
| 1955 | return 0; | ||
| 1956 | } | ||
| 1957 | |||
| 1958 | static void release_scratch_page(struct intel_vgpu *vgpu) | ||
| 1959 | { | ||
| 1960 | if (vgpu->gtt.scratch_page != NULL) { | ||
| 1961 | __free_page(vgpu->gtt.scratch_page); | ||
| 1962 | vgpu->gtt.scratch_page = NULL; | ||
| 1963 | vgpu->gtt.scratch_page_mfn = 0; | ||
| 1964 | } | ||
| 1965 | } | ||
| 1966 | |||
| 1967 | /** | ||
| 1968 | * intel_vgpu_init_gtt - initialize per-vGPU graphics memory virulization | ||
| 1969 | * @vgpu: a vGPU | ||
| 1970 | * | ||
| 1971 | * This function is used to initialize per-vGPU graphics memory virtualization | ||
| 1972 | * components. | ||
| 1973 | * | ||
| 1974 | * Returns: | ||
| 1975 | * Zero on success, error code if failed. | ||
| 1976 | */ | ||
| 1977 | int intel_vgpu_init_gtt(struct intel_vgpu *vgpu) | ||
| 1978 | { | ||
| 1979 | struct intel_vgpu_gtt *gtt = &vgpu->gtt; | ||
| 1980 | struct intel_vgpu_mm *ggtt_mm; | ||
| 1981 | |||
| 1982 | hash_init(gtt->guest_page_hash_table); | ||
| 1983 | hash_init(gtt->shadow_page_hash_table); | ||
| 1984 | |||
| 1985 | INIT_LIST_HEAD(>t->mm_list_head); | ||
| 1986 | INIT_LIST_HEAD(>t->oos_page_list_head); | ||
| 1987 | INIT_LIST_HEAD(>t->post_shadow_list_head); | ||
| 1988 | |||
| 1989 | ggtt_mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_GGTT, | ||
| 1990 | NULL, 1, 0); | ||
| 1991 | if (IS_ERR(ggtt_mm)) { | ||
| 1992 | gvt_err("fail to create mm for ggtt.\n"); | ||
| 1993 | return PTR_ERR(ggtt_mm); | ||
| 1994 | } | ||
| 1995 | |||
| 1996 | gtt->ggtt_mm = ggtt_mm; | ||
| 1997 | |||
| 1998 | return create_scratch_page(vgpu); | ||
| 1999 | } | ||
| 2000 | |||
| 2001 | /** | ||
| 2002 | * intel_vgpu_clean_gtt - clean up per-vGPU graphics memory virulization | ||
| 2003 | * @vgpu: a vGPU | ||
| 2004 | * | ||
| 2005 | * This function is used to clean up per-vGPU graphics memory virtualization | ||
| 2006 | * components. | ||
| 2007 | * | ||
| 2008 | * Returns: | ||
| 2009 | * Zero on success, error code if failed. | ||
| 2010 | */ | ||
| 2011 | void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu) | ||
| 2012 | { | ||
| 2013 | struct list_head *pos, *n; | ||
| 2014 | struct intel_vgpu_mm *mm; | ||
| 2015 | |||
| 2016 | ppgtt_free_all_shadow_page(vgpu); | ||
| 2017 | release_scratch_page(vgpu); | ||
| 2018 | |||
| 2019 | list_for_each_safe(pos, n, &vgpu->gtt.mm_list_head) { | ||
| 2020 | mm = container_of(pos, struct intel_vgpu_mm, list); | ||
| 2021 | vgpu->gvt->gtt.mm_free_page_table(mm); | ||
| 2022 | list_del(&mm->list); | ||
| 2023 | list_del(&mm->lru_list); | ||
| 2024 | kfree(mm); | ||
| 2025 | } | ||
| 2026 | } | ||
| 2027 | |||
| 2028 | static void clean_spt_oos(struct intel_gvt *gvt) | ||
| 2029 | { | ||
| 2030 | struct intel_gvt_gtt *gtt = &gvt->gtt; | ||
| 2031 | struct list_head *pos, *n; | ||
| 2032 | struct intel_vgpu_oos_page *oos_page; | ||
| 2033 | |||
| 2034 | WARN(!list_empty(>t->oos_page_use_list_head), | ||
| 2035 | "someone is still using oos page\n"); | ||
| 2036 | |||
| 2037 | list_for_each_safe(pos, n, >t->oos_page_free_list_head) { | ||
| 2038 | oos_page = container_of(pos, struct intel_vgpu_oos_page, list); | ||
| 2039 | list_del(&oos_page->list); | ||
| 2040 | kfree(oos_page); | ||
| 2041 | } | ||
| 2042 | } | ||
| 2043 | |||
| 2044 | static int setup_spt_oos(struct intel_gvt *gvt) | ||
| 2045 | { | ||
| 2046 | struct intel_gvt_gtt *gtt = &gvt->gtt; | ||
| 2047 | struct intel_vgpu_oos_page *oos_page; | ||
| 2048 | int i; | ||
| 2049 | int ret; | ||
| 2050 | |||
| 2051 | INIT_LIST_HEAD(>t->oos_page_free_list_head); | ||
| 2052 | INIT_LIST_HEAD(>t->oos_page_use_list_head); | ||
| 2053 | |||
| 2054 | for (i = 0; i < preallocated_oos_pages; i++) { | ||
| 2055 | oos_page = kzalloc(sizeof(*oos_page), GFP_KERNEL); | ||
| 2056 | if (!oos_page) { | ||
| 2057 | gvt_err("fail to pre-allocate oos page\n"); | ||
| 2058 | ret = -ENOMEM; | ||
| 2059 | goto fail; | ||
| 2060 | } | ||
| 2061 | |||
| 2062 | INIT_LIST_HEAD(&oos_page->list); | ||
| 2063 | INIT_LIST_HEAD(&oos_page->vm_list); | ||
| 2064 | oos_page->id = i; | ||
| 2065 | list_add_tail(&oos_page->list, >t->oos_page_free_list_head); | ||
| 2066 | } | ||
| 2067 | |||
| 2068 | gvt_dbg_mm("%d oos pages preallocated\n", i); | ||
| 2069 | |||
| 2070 | return 0; | ||
| 2071 | fail: | ||
| 2072 | clean_spt_oos(gvt); | ||
| 2073 | return ret; | ||
| 2074 | } | ||
| 2075 | |||
| 2076 | /** | ||
| 2077 | * intel_vgpu_find_ppgtt_mm - find a PPGTT mm object | ||
| 2078 | * @vgpu: a vGPU | ||
| 2079 | * @page_table_level: PPGTT page table level | ||
| 2080 | * @root_entry: PPGTT page table root pointers | ||
| 2081 | * | ||
| 2082 | * This function is used to find a PPGTT mm object from mm object pool | ||
| 2083 | * | ||
| 2084 | * Returns: | ||
| 2085 | * pointer to mm object on success, NULL if failed. | ||
| 2086 | */ | ||
| 2087 | struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu, | ||
| 2088 | int page_table_level, void *root_entry) | ||
| 2089 | { | ||
| 2090 | struct list_head *pos; | ||
| 2091 | struct intel_vgpu_mm *mm; | ||
| 2092 | u64 *src, *dst; | ||
| 2093 | |||
| 2094 | list_for_each(pos, &vgpu->gtt.mm_list_head) { | ||
| 2095 | mm = container_of(pos, struct intel_vgpu_mm, list); | ||
| 2096 | if (mm->type != INTEL_GVT_MM_PPGTT) | ||
| 2097 | continue; | ||
| 2098 | |||
| 2099 | if (mm->page_table_level != page_table_level) | ||
| 2100 | continue; | ||
| 2101 | |||
| 2102 | src = root_entry; | ||
| 2103 | dst = mm->virtual_page_table; | ||
| 2104 | |||
| 2105 | if (page_table_level == 3) { | ||
| 2106 | if (src[0] == dst[0] | ||
| 2107 | && src[1] == dst[1] | ||
| 2108 | && src[2] == dst[2] | ||
| 2109 | && src[3] == dst[3]) | ||
| 2110 | return mm; | ||
| 2111 | } else { | ||
| 2112 | if (src[0] == dst[0]) | ||
| 2113 | return mm; | ||
| 2114 | } | ||
| 2115 | } | ||
| 2116 | return NULL; | ||
| 2117 | } | ||
| 2118 | |||
| 2119 | /** | ||
| 2120 | * intel_vgpu_g2v_create_ppgtt_mm - create a PPGTT mm object from | ||
| 2121 | * g2v notification | ||
| 2122 | * @vgpu: a vGPU | ||
| 2123 | * @page_table_level: PPGTT page table level | ||
| 2124 | * | ||
| 2125 | * This function is used to create a PPGTT mm object from a guest to GVT-g | ||
| 2126 | * notification. | ||
| 2127 | * | ||
| 2128 | * Returns: | ||
| 2129 | * Zero on success, negative error code if failed. | ||
| 2130 | */ | ||
| 2131 | int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu, | ||
| 2132 | int page_table_level) | ||
| 2133 | { | ||
| 2134 | u64 *pdp = (u64 *)&vgpu_vreg64(vgpu, vgtif_reg(pdp[0])); | ||
| 2135 | struct intel_vgpu_mm *mm; | ||
| 2136 | |||
| 2137 | if (WARN_ON((page_table_level != 4) && (page_table_level != 3))) | ||
| 2138 | return -EINVAL; | ||
| 2139 | |||
| 2140 | mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp); | ||
| 2141 | if (mm) { | ||
| 2142 | intel_gvt_mm_reference(mm); | ||
| 2143 | } else { | ||
| 2144 | mm = intel_vgpu_create_mm(vgpu, INTEL_GVT_MM_PPGTT, | ||
| 2145 | pdp, page_table_level, 0); | ||
| 2146 | if (IS_ERR(mm)) { | ||
| 2147 | gvt_err("fail to create mm\n"); | ||
| 2148 | return PTR_ERR(mm); | ||
| 2149 | } | ||
| 2150 | } | ||
| 2151 | return 0; | ||
| 2152 | } | ||
| 2153 | |||
| 2154 | /** | ||
| 2155 | * intel_vgpu_g2v_destroy_ppgtt_mm - destroy a PPGTT mm object from | ||
| 2156 | * g2v notification | ||
| 2157 | * @vgpu: a vGPU | ||
| 2158 | * @page_table_level: PPGTT page table level | ||
| 2159 | * | ||
| 2160 | * This function is used to create a PPGTT mm object from a guest to GVT-g | ||
| 2161 | * notification. | ||
| 2162 | * | ||
| 2163 | * Returns: | ||
| 2164 | * Zero on success, negative error code if failed. | ||
| 2165 | */ | ||
| 2166 | int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, | ||
| 2167 | int page_table_level) | ||
| 2168 | { | ||
| 2169 | u64 *pdp = (u64 *)&vgpu_vreg64(vgpu, vgtif_reg(pdp[0])); | ||
| 2170 | struct intel_vgpu_mm *mm; | ||
| 2171 | |||
| 2172 | if (WARN_ON((page_table_level != 4) && (page_table_level != 3))) | ||
| 2173 | return -EINVAL; | ||
| 2174 | |||
| 2175 | mm = intel_vgpu_find_ppgtt_mm(vgpu, page_table_level, pdp); | ||
| 2176 | if (!mm) { | ||
| 2177 | gvt_err("fail to find ppgtt instance.\n"); | ||
| 2178 | return -EINVAL; | ||
| 2179 | } | ||
| 2180 | intel_gvt_mm_unreference(mm); | ||
| 2181 | return 0; | ||
| 2182 | } | ||
| 2183 | |||
| 2184 | /** | ||
| 2185 | * intel_gvt_init_gtt - initialize mm components of a GVT device | ||
| 2186 | * @gvt: GVT device | ||
| 2187 | * | ||
| 2188 | * This function is called at the initialization stage, to initialize | ||
| 2189 | * the mm components of a GVT device. | ||
| 2190 | * | ||
| 2191 | * Returns: | ||
| 2192 | * zero on success, negative error code if failed. | ||
| 2193 | */ | ||
| 2194 | int intel_gvt_init_gtt(struct intel_gvt *gvt) | ||
| 2195 | { | ||
| 2196 | int ret; | ||
| 2197 | |||
| 2198 | gvt_dbg_core("init gtt\n"); | ||
| 2199 | |||
| 2200 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { | ||
| 2201 | gvt->gtt.pte_ops = &gen8_gtt_pte_ops; | ||
| 2202 | gvt->gtt.gma_ops = &gen8_gtt_gma_ops; | ||
| 2203 | gvt->gtt.mm_alloc_page_table = gen8_mm_alloc_page_table; | ||
| 2204 | gvt->gtt.mm_free_page_table = gen8_mm_free_page_table; | ||
| 2205 | } else { | ||
| 2206 | return -ENODEV; | ||
| 2207 | } | ||
| 2208 | |||
| 2209 | if (enable_out_of_sync) { | ||
| 2210 | ret = setup_spt_oos(gvt); | ||
| 2211 | if (ret) { | ||
| 2212 | gvt_err("fail to initialize SPT oos\n"); | ||
| 2213 | return ret; | ||
| 2214 | } | ||
| 2215 | } | ||
| 2216 | INIT_LIST_HEAD(&gvt->gtt.mm_lru_list_head); | ||
| 2217 | return 0; | ||
| 2218 | } | ||
| 2219 | |||
| 2220 | /** | ||
| 2221 | * intel_gvt_clean_gtt - clean up mm components of a GVT device | ||
| 2222 | * @gvt: GVT device | ||
| 2223 | * | ||
| 2224 | * This function is called at the driver unloading stage, to clean up the | ||
| 2225 | * the mm components of a GVT device. | ||
| 2226 | * | ||
| 2227 | */ | ||
| 2228 | void intel_gvt_clean_gtt(struct intel_gvt *gvt) | ||
| 2229 | { | ||
| 2230 | if (enable_out_of_sync) | ||
| 2231 | clean_spt_oos(gvt); | ||
| 2232 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h new file mode 100644 index 000000000000..e4dcde78f3f9 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/gtt.h | |||
| @@ -0,0 +1,270 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 25 | * Zhenyu Wang <zhenyuw@linux.intel.com> | ||
| 26 | * Xiao Zheng <xiao.zheng@intel.com> | ||
| 27 | * | ||
| 28 | * Contributors: | ||
| 29 | * Min He <min.he@intel.com> | ||
| 30 | * Bing Niu <bing.niu@intel.com> | ||
| 31 | * | ||
| 32 | */ | ||
| 33 | |||
| 34 | #ifndef _GVT_GTT_H_ | ||
| 35 | #define _GVT_GTT_H_ | ||
| 36 | |||
| 37 | #define GTT_PAGE_SHIFT 12 | ||
| 38 | #define GTT_PAGE_SIZE (1UL << GTT_PAGE_SHIFT) | ||
| 39 | #define GTT_PAGE_MASK (~(GTT_PAGE_SIZE-1)) | ||
| 40 | |||
| 41 | struct intel_vgpu_mm; | ||
| 42 | |||
| 43 | #define INTEL_GVT_GTT_HASH_BITS 8 | ||
| 44 | #define INTEL_GVT_INVALID_ADDR (~0UL) | ||
| 45 | |||
| 46 | struct intel_gvt_gtt_entry { | ||
| 47 | u64 val64; | ||
| 48 | int type; | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct intel_gvt_gtt_pte_ops { | ||
| 52 | struct intel_gvt_gtt_entry *(*get_entry)(void *pt, | ||
| 53 | struct intel_gvt_gtt_entry *e, | ||
| 54 | unsigned long index, bool hypervisor_access, unsigned long gpa, | ||
| 55 | struct intel_vgpu *vgpu); | ||
| 56 | struct intel_gvt_gtt_entry *(*set_entry)(void *pt, | ||
| 57 | struct intel_gvt_gtt_entry *e, | ||
| 58 | unsigned long index, bool hypervisor_access, unsigned long gpa, | ||
| 59 | struct intel_vgpu *vgpu); | ||
| 60 | bool (*test_present)(struct intel_gvt_gtt_entry *e); | ||
| 61 | void (*clear_present)(struct intel_gvt_gtt_entry *e); | ||
| 62 | bool (*test_pse)(struct intel_gvt_gtt_entry *e); | ||
| 63 | void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn); | ||
| 64 | unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e); | ||
| 65 | }; | ||
| 66 | |||
| 67 | struct intel_gvt_gtt_gma_ops { | ||
| 68 | unsigned long (*gma_to_ggtt_pte_index)(unsigned long gma); | ||
| 69 | unsigned long (*gma_to_pte_index)(unsigned long gma); | ||
| 70 | unsigned long (*gma_to_pde_index)(unsigned long gma); | ||
| 71 | unsigned long (*gma_to_l3_pdp_index)(unsigned long gma); | ||
| 72 | unsigned long (*gma_to_l4_pdp_index)(unsigned long gma); | ||
| 73 | unsigned long (*gma_to_pml4_index)(unsigned long gma); | ||
| 74 | }; | ||
| 75 | |||
| 76 | struct intel_gvt_gtt { | ||
| 77 | struct intel_gvt_gtt_pte_ops *pte_ops; | ||
| 78 | struct intel_gvt_gtt_gma_ops *gma_ops; | ||
| 79 | int (*mm_alloc_page_table)(struct intel_vgpu_mm *mm); | ||
| 80 | void (*mm_free_page_table)(struct intel_vgpu_mm *mm); | ||
| 81 | struct list_head oos_page_use_list_head; | ||
| 82 | struct list_head oos_page_free_list_head; | ||
| 83 | struct list_head mm_lru_list_head; | ||
| 84 | }; | ||
| 85 | |||
| 86 | enum { | ||
| 87 | INTEL_GVT_MM_GGTT = 0, | ||
| 88 | INTEL_GVT_MM_PPGTT, | ||
| 89 | }; | ||
| 90 | |||
| 91 | struct intel_vgpu_mm { | ||
| 92 | int type; | ||
| 93 | bool initialized; | ||
| 94 | bool shadowed; | ||
| 95 | |||
| 96 | int page_table_entry_type; | ||
| 97 | u32 page_table_entry_size; | ||
| 98 | u32 page_table_entry_cnt; | ||
| 99 | void *virtual_page_table; | ||
| 100 | void *shadow_page_table; | ||
| 101 | |||
| 102 | int page_table_level; | ||
| 103 | bool has_shadow_page_table; | ||
| 104 | u32 pde_base_index; | ||
| 105 | |||
| 106 | struct list_head list; | ||
| 107 | struct kref ref; | ||
| 108 | atomic_t pincount; | ||
| 109 | struct list_head lru_list; | ||
| 110 | struct intel_vgpu *vgpu; | ||
| 111 | }; | ||
| 112 | |||
| 113 | extern struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry( | ||
| 114 | struct intel_vgpu_mm *mm, | ||
| 115 | void *page_table, struct intel_gvt_gtt_entry *e, | ||
| 116 | unsigned long index); | ||
| 117 | |||
| 118 | extern struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry( | ||
| 119 | struct intel_vgpu_mm *mm, | ||
| 120 | void *page_table, struct intel_gvt_gtt_entry *e, | ||
| 121 | unsigned long index); | ||
| 122 | |||
| 123 | #define ggtt_get_guest_entry(mm, e, index) \ | ||
| 124 | intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index) | ||
| 125 | |||
| 126 | #define ggtt_set_guest_entry(mm, e, index) \ | ||
| 127 | intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index) | ||
| 128 | |||
| 129 | #define ggtt_get_shadow_entry(mm, e, index) \ | ||
| 130 | intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index) | ||
| 131 | |||
| 132 | #define ggtt_set_shadow_entry(mm, e, index) \ | ||
| 133 | intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index) | ||
| 134 | |||
| 135 | #define ppgtt_get_guest_root_entry(mm, e, index) \ | ||
| 136 | intel_vgpu_mm_get_entry(mm, mm->virtual_page_table, e, index) | ||
| 137 | |||
| 138 | #define ppgtt_set_guest_root_entry(mm, e, index) \ | ||
| 139 | intel_vgpu_mm_set_entry(mm, mm->virtual_page_table, e, index) | ||
| 140 | |||
| 141 | #define ppgtt_get_shadow_root_entry(mm, e, index) \ | ||
| 142 | intel_vgpu_mm_get_entry(mm, mm->shadow_page_table, e, index) | ||
| 143 | |||
| 144 | #define ppgtt_set_shadow_root_entry(mm, e, index) \ | ||
| 145 | intel_vgpu_mm_set_entry(mm, mm->shadow_page_table, e, index) | ||
| 146 | |||
| 147 | extern struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu, | ||
| 148 | int mm_type, void *virtual_page_table, int page_table_level, | ||
| 149 | u32 pde_base_index); | ||
| 150 | extern void intel_vgpu_destroy_mm(struct kref *mm_ref); | ||
| 151 | |||
| 152 | struct intel_vgpu_guest_page; | ||
| 153 | |||
| 154 | struct intel_vgpu_gtt { | ||
| 155 | struct intel_vgpu_mm *ggtt_mm; | ||
| 156 | unsigned long active_ppgtt_mm_bitmap; | ||
| 157 | struct list_head mm_list_head; | ||
| 158 | DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS); | ||
| 159 | DECLARE_HASHTABLE(guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS); | ||
| 160 | atomic_t n_write_protected_guest_page; | ||
| 161 | struct list_head oos_page_list_head; | ||
| 162 | struct list_head post_shadow_list_head; | ||
| 163 | struct page *scratch_page; | ||
| 164 | unsigned long scratch_page_mfn; | ||
| 165 | }; | ||
| 166 | |||
| 167 | extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu); | ||
| 168 | extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu); | ||
| 169 | |||
| 170 | extern int intel_gvt_init_gtt(struct intel_gvt *gvt); | ||
| 171 | extern void intel_gvt_clean_gtt(struct intel_gvt *gvt); | ||
| 172 | |||
| 173 | extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu, | ||
| 174 | int page_table_level, void *root_entry); | ||
| 175 | |||
| 176 | struct intel_vgpu_oos_page; | ||
| 177 | |||
| 178 | struct intel_vgpu_shadow_page { | ||
| 179 | void *vaddr; | ||
| 180 | struct page *page; | ||
| 181 | int type; | ||
| 182 | struct hlist_node node; | ||
| 183 | unsigned long mfn; | ||
| 184 | }; | ||
| 185 | |||
| 186 | struct intel_vgpu_guest_page { | ||
| 187 | struct hlist_node node; | ||
| 188 | bool writeprotection; | ||
| 189 | unsigned long gfn; | ||
| 190 | int (*handler)(void *, u64, void *, int); | ||
| 191 | void *data; | ||
| 192 | unsigned long write_cnt; | ||
| 193 | struct intel_vgpu_oos_page *oos_page; | ||
| 194 | }; | ||
| 195 | |||
| 196 | struct intel_vgpu_oos_page { | ||
| 197 | struct intel_vgpu_guest_page *guest_page; | ||
| 198 | struct list_head list; | ||
| 199 | struct list_head vm_list; | ||
| 200 | int id; | ||
| 201 | unsigned char mem[GTT_PAGE_SIZE]; | ||
| 202 | }; | ||
| 203 | |||
| 204 | #define GTT_ENTRY_NUM_IN_ONE_PAGE 512 | ||
| 205 | |||
| 206 | struct intel_vgpu_ppgtt_spt { | ||
| 207 | struct intel_vgpu_shadow_page shadow_page; | ||
| 208 | struct intel_vgpu_guest_page guest_page; | ||
| 209 | int guest_page_type; | ||
| 210 | atomic_t refcount; | ||
| 211 | struct intel_vgpu *vgpu; | ||
| 212 | DECLARE_BITMAP(post_shadow_bitmap, GTT_ENTRY_NUM_IN_ONE_PAGE); | ||
| 213 | struct list_head post_shadow_list; | ||
| 214 | }; | ||
| 215 | |||
| 216 | int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu, | ||
| 217 | struct intel_vgpu_guest_page *guest_page, | ||
| 218 | unsigned long gfn, | ||
| 219 | int (*handler)(void *gp, u64, void *, int), | ||
| 220 | void *data); | ||
| 221 | |||
| 222 | void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu, | ||
| 223 | struct intel_vgpu_guest_page *guest_page); | ||
| 224 | |||
| 225 | int intel_vgpu_set_guest_page_writeprotection(struct intel_vgpu *vgpu, | ||
| 226 | struct intel_vgpu_guest_page *guest_page); | ||
| 227 | |||
| 228 | void intel_vgpu_clear_guest_page_writeprotection(struct intel_vgpu *vgpu, | ||
| 229 | struct intel_vgpu_guest_page *guest_page); | ||
| 230 | |||
| 231 | struct intel_vgpu_guest_page *intel_vgpu_find_guest_page( | ||
| 232 | struct intel_vgpu *vgpu, unsigned long gfn); | ||
| 233 | |||
| 234 | int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu); | ||
| 235 | |||
| 236 | int intel_vgpu_flush_post_shadow(struct intel_vgpu *vgpu); | ||
| 237 | |||
| 238 | static inline void intel_gvt_mm_reference(struct intel_vgpu_mm *mm) | ||
| 239 | { | ||
| 240 | kref_get(&mm->ref); | ||
| 241 | } | ||
| 242 | |||
| 243 | static inline void intel_gvt_mm_unreference(struct intel_vgpu_mm *mm) | ||
| 244 | { | ||
| 245 | kref_put(&mm->ref, intel_vgpu_destroy_mm); | ||
| 246 | } | ||
| 247 | |||
| 248 | int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm); | ||
| 249 | |||
| 250 | void intel_vgpu_unpin_mm(struct intel_vgpu_mm *mm); | ||
| 251 | |||
| 252 | unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, | ||
| 253 | unsigned long gma); | ||
| 254 | |||
| 255 | struct intel_vgpu_mm *intel_vgpu_find_ppgtt_mm(struct intel_vgpu *vgpu, | ||
| 256 | int page_table_level, void *root_entry); | ||
| 257 | |||
| 258 | int intel_vgpu_g2v_create_ppgtt_mm(struct intel_vgpu *vgpu, | ||
| 259 | int page_table_level); | ||
| 260 | |||
| 261 | int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu, | ||
| 262 | int page_table_level); | ||
| 263 | |||
| 264 | int intel_vgpu_emulate_gtt_mmio_read(struct intel_vgpu *vgpu, | ||
| 265 | unsigned int off, void *p_data, unsigned int bytes); | ||
| 266 | |||
| 267 | int intel_vgpu_emulate_gtt_mmio_write(struct intel_vgpu *vgpu, | ||
| 268 | unsigned int off, void *p_data, unsigned int bytes); | ||
| 269 | |||
| 270 | #endif /* _GVT_GTT_H_ */ | ||
diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index 927f4579f5b6..31b59d40f3fb 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c | |||
| @@ -19,12 +19,23 @@ | |||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 21 | * SOFTWARE. | 21 | * SOFTWARE. |
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Kevin Tian <kevin.tian@intel.com> | ||
| 25 | * Eddie Dong <eddie.dong@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Niu Bing <bing.niu@intel.com> | ||
| 29 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 30 | * | ||
| 22 | */ | 31 | */ |
| 23 | 32 | ||
| 24 | #include <linux/types.h> | 33 | #include <linux/types.h> |
| 25 | #include <xen/xen.h> | 34 | #include <xen/xen.h> |
| 35 | #include <linux/kthread.h> | ||
| 26 | 36 | ||
| 27 | #include "i915_drv.h" | 37 | #include "i915_drv.h" |
| 38 | #include "gvt.h" | ||
| 28 | 39 | ||
| 29 | struct intel_gvt_host intel_gvt_host; | 40 | struct intel_gvt_host intel_gvt_host; |
| 30 | 41 | ||
| @@ -33,6 +44,13 @@ static const char * const supported_hypervisors[] = { | |||
| 33 | [INTEL_GVT_HYPERVISOR_KVM] = "KVM", | 44 | [INTEL_GVT_HYPERVISOR_KVM] = "KVM", |
| 34 | }; | 45 | }; |
| 35 | 46 | ||
| 47 | struct intel_gvt_io_emulation_ops intel_gvt_io_emulation_ops = { | ||
| 48 | .emulate_cfg_read = intel_vgpu_emulate_cfg_read, | ||
| 49 | .emulate_cfg_write = intel_vgpu_emulate_cfg_write, | ||
| 50 | .emulate_mmio_read = intel_vgpu_emulate_mmio_read, | ||
| 51 | .emulate_mmio_write = intel_vgpu_emulate_mmio_write, | ||
| 52 | }; | ||
| 53 | |||
| 36 | /** | 54 | /** |
| 37 | * intel_gvt_init_host - Load MPT modules and detect if we're running in host | 55 | * intel_gvt_init_host - Load MPT modules and detect if we're running in host |
| 38 | * @gvt: intel gvt device | 56 | * @gvt: intel gvt device |
| @@ -84,9 +102,66 @@ int intel_gvt_init_host(void) | |||
| 84 | 102 | ||
| 85 | static void init_device_info(struct intel_gvt *gvt) | 103 | static void init_device_info(struct intel_gvt *gvt) |
| 86 | { | 104 | { |
| 87 | if (IS_BROADWELL(gvt->dev_priv)) | 105 | struct intel_gvt_device_info *info = &gvt->device_info; |
| 88 | gvt->device_info.max_support_vgpus = 8; | 106 | |
| 89 | /* This function will grow large in GVT device model patches. */ | 107 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { |
| 108 | info->max_support_vgpus = 8; | ||
| 109 | info->cfg_space_size = 256; | ||
| 110 | info->mmio_size = 2 * 1024 * 1024; | ||
| 111 | info->mmio_bar = 0; | ||
| 112 | info->msi_cap_offset = IS_SKYLAKE(gvt->dev_priv) ? 0xac : 0x90; | ||
| 113 | info->gtt_start_offset = 8 * 1024 * 1024; | ||
| 114 | info->gtt_entry_size = 8; | ||
| 115 | info->gtt_entry_size_shift = 3; | ||
| 116 | info->gmadr_bytes_in_cmd = 8; | ||
| 117 | info->max_surface_size = 36 * 1024 * 1024; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | |||
| 121 | static int gvt_service_thread(void *data) | ||
| 122 | { | ||
| 123 | struct intel_gvt *gvt = (struct intel_gvt *)data; | ||
| 124 | int ret; | ||
| 125 | |||
| 126 | gvt_dbg_core("service thread start\n"); | ||
| 127 | |||
| 128 | while (!kthread_should_stop()) { | ||
| 129 | ret = wait_event_interruptible(gvt->service_thread_wq, | ||
| 130 | kthread_should_stop() || gvt->service_request); | ||
| 131 | |||
| 132 | if (kthread_should_stop()) | ||
| 133 | break; | ||
| 134 | |||
| 135 | if (WARN_ONCE(ret, "service thread is waken up by signal.\n")) | ||
| 136 | continue; | ||
| 137 | |||
| 138 | if (test_and_clear_bit(INTEL_GVT_REQUEST_EMULATE_VBLANK, | ||
| 139 | (void *)&gvt->service_request)) { | ||
| 140 | mutex_lock(&gvt->lock); | ||
| 141 | intel_gvt_emulate_vblank(gvt); | ||
| 142 | mutex_unlock(&gvt->lock); | ||
| 143 | } | ||
| 144 | } | ||
| 145 | |||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | static void clean_service_thread(struct intel_gvt *gvt) | ||
| 150 | { | ||
| 151 | kthread_stop(gvt->service_thread); | ||
| 152 | } | ||
| 153 | |||
| 154 | static int init_service_thread(struct intel_gvt *gvt) | ||
| 155 | { | ||
| 156 | init_waitqueue_head(&gvt->service_thread_wq); | ||
| 157 | |||
| 158 | gvt->service_thread = kthread_run(gvt_service_thread, | ||
| 159 | gvt, "gvt_service_thread"); | ||
| 160 | if (IS_ERR(gvt->service_thread)) { | ||
| 161 | gvt_err("fail to start service thread.\n"); | ||
| 162 | return PTR_ERR(gvt->service_thread); | ||
| 163 | } | ||
| 164 | return 0; | ||
| 90 | } | 165 | } |
| 91 | 166 | ||
| 92 | /** | 167 | /** |
| @@ -99,14 +174,23 @@ static void init_device_info(struct intel_gvt *gvt) | |||
| 99 | */ | 174 | */ |
| 100 | void intel_gvt_clean_device(struct drm_i915_private *dev_priv) | 175 | void intel_gvt_clean_device(struct drm_i915_private *dev_priv) |
| 101 | { | 176 | { |
| 102 | struct intel_gvt *gvt = &dev_priv->gvt; | 177 | struct intel_gvt *gvt = to_gvt(dev_priv); |
| 103 | 178 | ||
| 104 | if (WARN_ON(!gvt->initialized)) | 179 | if (WARN_ON(!gvt)) |
| 105 | return; | 180 | return; |
| 106 | 181 | ||
| 107 | /* Other de-initialization of GVT components will be introduced. */ | 182 | clean_service_thread(gvt); |
| 183 | intel_gvt_clean_cmd_parser(gvt); | ||
| 184 | intel_gvt_clean_sched_policy(gvt); | ||
| 185 | intel_gvt_clean_workload_scheduler(gvt); | ||
| 186 | intel_gvt_clean_opregion(gvt); | ||
| 187 | intel_gvt_clean_gtt(gvt); | ||
| 188 | intel_gvt_clean_irq(gvt); | ||
| 189 | intel_gvt_clean_mmio_info(gvt); | ||
| 190 | intel_gvt_free_firmware(gvt); | ||
| 108 | 191 | ||
| 109 | gvt->initialized = false; | 192 | kfree(dev_priv->gvt); |
| 193 | dev_priv->gvt = NULL; | ||
| 110 | } | 194 | } |
| 111 | 195 | ||
| 112 | /** | 196 | /** |
| @@ -122,7 +206,9 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv) | |||
| 122 | */ | 206 | */ |
| 123 | int intel_gvt_init_device(struct drm_i915_private *dev_priv) | 207 | int intel_gvt_init_device(struct drm_i915_private *dev_priv) |
| 124 | { | 208 | { |
| 125 | struct intel_gvt *gvt = &dev_priv->gvt; | 209 | struct intel_gvt *gvt; |
| 210 | int ret; | ||
| 211 | |||
| 126 | /* | 212 | /* |
| 127 | * Cannot initialize GVT device without intel_gvt_host gets | 213 | * Cannot initialize GVT device without intel_gvt_host gets |
| 128 | * initialized first. | 214 | * initialized first. |
| @@ -130,16 +216,76 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv) | |||
| 130 | if (WARN_ON(!intel_gvt_host.initialized)) | 216 | if (WARN_ON(!intel_gvt_host.initialized)) |
| 131 | return -EINVAL; | 217 | return -EINVAL; |
| 132 | 218 | ||
| 133 | if (WARN_ON(gvt->initialized)) | 219 | if (WARN_ON(dev_priv->gvt)) |
| 134 | return -EEXIST; | 220 | return -EEXIST; |
| 135 | 221 | ||
| 222 | gvt = kzalloc(sizeof(struct intel_gvt), GFP_KERNEL); | ||
| 223 | if (!gvt) | ||
| 224 | return -ENOMEM; | ||
| 225 | |||
| 136 | gvt_dbg_core("init gvt device\n"); | 226 | gvt_dbg_core("init gvt device\n"); |
| 137 | 227 | ||
| 228 | mutex_init(&gvt->lock); | ||
| 229 | gvt->dev_priv = dev_priv; | ||
| 230 | |||
| 138 | init_device_info(gvt); | 231 | init_device_info(gvt); |
| 139 | /* | 232 | |
| 140 | * Other initialization of GVT components will be introduce here. | 233 | ret = intel_gvt_setup_mmio_info(gvt); |
| 141 | */ | 234 | if (ret) |
| 235 | return ret; | ||
| 236 | |||
| 237 | ret = intel_gvt_load_firmware(gvt); | ||
| 238 | if (ret) | ||
| 239 | goto out_clean_mmio_info; | ||
| 240 | |||
| 241 | ret = intel_gvt_init_irq(gvt); | ||
| 242 | if (ret) | ||
| 243 | goto out_free_firmware; | ||
| 244 | |||
| 245 | ret = intel_gvt_init_gtt(gvt); | ||
| 246 | if (ret) | ||
| 247 | goto out_clean_irq; | ||
| 248 | |||
| 249 | ret = intel_gvt_init_opregion(gvt); | ||
| 250 | if (ret) | ||
| 251 | goto out_clean_gtt; | ||
| 252 | |||
| 253 | ret = intel_gvt_init_workload_scheduler(gvt); | ||
| 254 | if (ret) | ||
| 255 | goto out_clean_opregion; | ||
| 256 | |||
| 257 | ret = intel_gvt_init_sched_policy(gvt); | ||
| 258 | if (ret) | ||
| 259 | goto out_clean_workload_scheduler; | ||
| 260 | |||
| 261 | ret = intel_gvt_init_cmd_parser(gvt); | ||
| 262 | if (ret) | ||
| 263 | goto out_clean_sched_policy; | ||
| 264 | |||
| 265 | ret = init_service_thread(gvt); | ||
| 266 | if (ret) | ||
| 267 | goto out_clean_cmd_parser; | ||
| 268 | |||
| 142 | gvt_dbg_core("gvt device creation is done\n"); | 269 | gvt_dbg_core("gvt device creation is done\n"); |
| 143 | gvt->initialized = true; | 270 | dev_priv->gvt = gvt; |
| 144 | return 0; | 271 | return 0; |
| 272 | |||
| 273 | out_clean_cmd_parser: | ||
| 274 | intel_gvt_clean_cmd_parser(gvt); | ||
| 275 | out_clean_sched_policy: | ||
| 276 | intel_gvt_clean_sched_policy(gvt); | ||
| 277 | out_clean_workload_scheduler: | ||
| 278 | intel_gvt_clean_workload_scheduler(gvt); | ||
| 279 | out_clean_opregion: | ||
| 280 | intel_gvt_clean_opregion(gvt); | ||
| 281 | out_clean_gtt: | ||
| 282 | intel_gvt_clean_gtt(gvt); | ||
| 283 | out_clean_irq: | ||
| 284 | intel_gvt_clean_irq(gvt); | ||
| 285 | out_free_firmware: | ||
| 286 | intel_gvt_free_firmware(gvt); | ||
| 287 | out_clean_mmio_info: | ||
| 288 | intel_gvt_clean_mmio_info(gvt); | ||
| 289 | kfree(gvt); | ||
| 290 | return ret; | ||
| 145 | } | 291 | } |
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index fb619a6e519d..11df62b542b1 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h | |||
| @@ -19,6 +19,15 @@ | |||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 21 | * SOFTWARE. | 21 | * SOFTWARE. |
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Kevin Tian <kevin.tian@intel.com> | ||
| 25 | * Eddie Dong <eddie.dong@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Niu Bing <bing.niu@intel.com> | ||
| 29 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 30 | * | ||
| 22 | */ | 31 | */ |
| 23 | 32 | ||
| 24 | #ifndef _GVT_H_ | 33 | #ifndef _GVT_H_ |
| @@ -26,6 +35,17 @@ | |||
| 26 | 35 | ||
| 27 | #include "debug.h" | 36 | #include "debug.h" |
| 28 | #include "hypercall.h" | 37 | #include "hypercall.h" |
| 38 | #include "mmio.h" | ||
| 39 | #include "reg.h" | ||
| 40 | #include "interrupt.h" | ||
| 41 | #include "gtt.h" | ||
| 42 | #include "display.h" | ||
| 43 | #include "edid.h" | ||
| 44 | #include "execlist.h" | ||
| 45 | #include "scheduler.h" | ||
| 46 | #include "sched_policy.h" | ||
| 47 | #include "render.h" | ||
| 48 | #include "cmd_parser.h" | ||
| 29 | 49 | ||
| 30 | #define GVT_MAX_VGPU 8 | 50 | #define GVT_MAX_VGPU 8 |
| 31 | 51 | ||
| @@ -45,25 +65,324 @@ extern struct intel_gvt_host intel_gvt_host; | |||
| 45 | /* Describe per-platform limitations. */ | 65 | /* Describe per-platform limitations. */ |
| 46 | struct intel_gvt_device_info { | 66 | struct intel_gvt_device_info { |
| 47 | u32 max_support_vgpus; | 67 | u32 max_support_vgpus; |
| 48 | /* This data structure will grow bigger in GVT device model patches */ | 68 | u32 cfg_space_size; |
| 69 | u32 mmio_size; | ||
| 70 | u32 mmio_bar; | ||
| 71 | unsigned long msi_cap_offset; | ||
| 72 | u32 gtt_start_offset; | ||
| 73 | u32 gtt_entry_size; | ||
| 74 | u32 gtt_entry_size_shift; | ||
| 75 | int gmadr_bytes_in_cmd; | ||
| 76 | u32 max_surface_size; | ||
| 77 | }; | ||
| 78 | |||
| 79 | /* GM resources owned by a vGPU */ | ||
| 80 | struct intel_vgpu_gm { | ||
| 81 | u64 aperture_sz; | ||
| 82 | u64 hidden_sz; | ||
| 83 | struct drm_mm_node low_gm_node; | ||
| 84 | struct drm_mm_node high_gm_node; | ||
| 85 | }; | ||
| 86 | |||
| 87 | #define INTEL_GVT_MAX_NUM_FENCES 32 | ||
| 88 | |||
| 89 | /* Fences owned by a vGPU */ | ||
| 90 | struct intel_vgpu_fence { | ||
| 91 | struct drm_i915_fence_reg *regs[INTEL_GVT_MAX_NUM_FENCES]; | ||
| 92 | u32 base; | ||
| 93 | u32 size; | ||
| 94 | }; | ||
| 95 | |||
| 96 | struct intel_vgpu_mmio { | ||
| 97 | void *vreg; | ||
| 98 | void *sreg; | ||
| 99 | bool disable_warn_untrack; | ||
| 100 | }; | ||
| 101 | |||
| 102 | #define INTEL_GVT_MAX_CFG_SPACE_SZ 256 | ||
| 103 | #define INTEL_GVT_MAX_BAR_NUM 4 | ||
| 104 | |||
| 105 | struct intel_vgpu_pci_bar { | ||
| 106 | u64 size; | ||
| 107 | bool tracked; | ||
| 108 | }; | ||
| 109 | |||
| 110 | struct intel_vgpu_cfg_space { | ||
| 111 | unsigned char virtual_cfg_space[INTEL_GVT_MAX_CFG_SPACE_SZ]; | ||
| 112 | struct intel_vgpu_pci_bar bar[INTEL_GVT_MAX_BAR_NUM]; | ||
| 113 | }; | ||
| 114 | |||
| 115 | #define vgpu_cfg_space(vgpu) ((vgpu)->cfg_space.virtual_cfg_space) | ||
| 116 | |||
| 117 | #define INTEL_GVT_MAX_PIPE 4 | ||
| 118 | |||
| 119 | struct intel_vgpu_irq { | ||
| 120 | bool irq_warn_once[INTEL_GVT_EVENT_MAX]; | ||
| 121 | DECLARE_BITMAP(flip_done_event[INTEL_GVT_MAX_PIPE], | ||
| 122 | INTEL_GVT_EVENT_MAX); | ||
| 123 | }; | ||
| 124 | |||
| 125 | struct intel_vgpu_opregion { | ||
| 126 | void *va; | ||
| 127 | u32 gfn[INTEL_GVT_OPREGION_PAGES]; | ||
| 128 | struct page *pages[INTEL_GVT_OPREGION_PAGES]; | ||
| 129 | }; | ||
| 130 | |||
| 131 | #define vgpu_opregion(vgpu) (&(vgpu->opregion)) | ||
| 132 | |||
| 133 | #define INTEL_GVT_MAX_PORT 5 | ||
| 134 | |||
| 135 | struct intel_vgpu_display { | ||
| 136 | struct intel_vgpu_i2c_edid i2c_edid; | ||
| 137 | struct intel_vgpu_port ports[INTEL_GVT_MAX_PORT]; | ||
| 138 | struct intel_vgpu_sbi sbi; | ||
| 49 | }; | 139 | }; |
| 50 | 140 | ||
| 51 | struct intel_vgpu { | 141 | struct intel_vgpu { |
| 52 | struct intel_gvt *gvt; | 142 | struct intel_gvt *gvt; |
| 53 | int id; | 143 | int id; |
| 54 | unsigned long handle; /* vGPU handle used by hypervisor MPT modules */ | 144 | unsigned long handle; /* vGPU handle used by hypervisor MPT modules */ |
| 145 | bool active; | ||
| 146 | bool resetting; | ||
| 147 | void *sched_data; | ||
| 148 | |||
| 149 | struct intel_vgpu_fence fence; | ||
| 150 | struct intel_vgpu_gm gm; | ||
| 151 | struct intel_vgpu_cfg_space cfg_space; | ||
| 152 | struct intel_vgpu_mmio mmio; | ||
| 153 | struct intel_vgpu_irq irq; | ||
| 154 | struct intel_vgpu_gtt gtt; | ||
| 155 | struct intel_vgpu_opregion opregion; | ||
| 156 | struct intel_vgpu_display display; | ||
| 157 | struct intel_vgpu_execlist execlist[I915_NUM_ENGINES]; | ||
| 158 | struct list_head workload_q_head[I915_NUM_ENGINES]; | ||
| 159 | struct kmem_cache *workloads; | ||
| 160 | atomic_t running_workload_num; | ||
| 161 | DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES); | ||
| 162 | struct i915_gem_context *shadow_ctx; | ||
| 163 | struct notifier_block shadow_ctx_notifier_block; | ||
| 164 | }; | ||
| 165 | |||
| 166 | struct intel_gvt_gm { | ||
| 167 | unsigned long vgpu_allocated_low_gm_size; | ||
| 168 | unsigned long vgpu_allocated_high_gm_size; | ||
| 169 | }; | ||
| 170 | |||
| 171 | struct intel_gvt_fence { | ||
| 172 | unsigned long vgpu_allocated_fence_num; | ||
| 173 | }; | ||
| 174 | |||
| 175 | #define INTEL_GVT_MMIO_HASH_BITS 9 | ||
| 176 | |||
| 177 | struct intel_gvt_mmio { | ||
| 178 | u32 *mmio_attribute; | ||
| 179 | DECLARE_HASHTABLE(mmio_info_table, INTEL_GVT_MMIO_HASH_BITS); | ||
| 180 | }; | ||
| 181 | |||
| 182 | struct intel_gvt_firmware { | ||
| 183 | void *cfg_space; | ||
| 184 | void *mmio; | ||
| 185 | bool firmware_loaded; | ||
| 186 | }; | ||
| 187 | |||
| 188 | struct intel_gvt_opregion { | ||
| 189 | void __iomem *opregion_va; | ||
| 190 | u32 opregion_pa; | ||
| 55 | }; | 191 | }; |
| 56 | 192 | ||
| 57 | struct intel_gvt { | 193 | struct intel_gvt { |
| 58 | struct mutex lock; | 194 | struct mutex lock; |
| 59 | bool initialized; | ||
| 60 | |||
| 61 | struct drm_i915_private *dev_priv; | 195 | struct drm_i915_private *dev_priv; |
| 62 | struct idr vgpu_idr; /* vGPU IDR pool */ | 196 | struct idr vgpu_idr; /* vGPU IDR pool */ |
| 63 | 197 | ||
| 64 | struct intel_gvt_device_info device_info; | 198 | struct intel_gvt_device_info device_info; |
| 199 | struct intel_gvt_gm gm; | ||
| 200 | struct intel_gvt_fence fence; | ||
| 201 | struct intel_gvt_mmio mmio; | ||
| 202 | struct intel_gvt_firmware firmware; | ||
| 203 | struct intel_gvt_irq irq; | ||
| 204 | struct intel_gvt_gtt gtt; | ||
| 205 | struct intel_gvt_opregion opregion; | ||
| 206 | struct intel_gvt_workload_scheduler scheduler; | ||
| 207 | DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS); | ||
| 208 | |||
| 209 | struct task_struct *service_thread; | ||
| 210 | wait_queue_head_t service_thread_wq; | ||
| 211 | unsigned long service_request; | ||
| 65 | }; | 212 | }; |
| 66 | 213 | ||
| 214 | static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915) | ||
| 215 | { | ||
| 216 | return i915->gvt; | ||
| 217 | } | ||
| 218 | |||
| 219 | enum { | ||
| 220 | INTEL_GVT_REQUEST_EMULATE_VBLANK = 0, | ||
| 221 | }; | ||
| 222 | |||
| 223 | static inline void intel_gvt_request_service(struct intel_gvt *gvt, | ||
| 224 | int service) | ||
| 225 | { | ||
| 226 | set_bit(service, (void *)&gvt->service_request); | ||
| 227 | wake_up(&gvt->service_thread_wq); | ||
| 228 | } | ||
| 229 | |||
| 230 | void intel_gvt_free_firmware(struct intel_gvt *gvt); | ||
| 231 | int intel_gvt_load_firmware(struct intel_gvt *gvt); | ||
| 232 | |||
| 233 | /* Aperture/GM space definitions for GVT device */ | ||
| 234 | #define gvt_aperture_sz(gvt) (gvt->dev_priv->ggtt.mappable_end) | ||
| 235 | #define gvt_aperture_pa_base(gvt) (gvt->dev_priv->ggtt.mappable_base) | ||
| 236 | |||
| 237 | #define gvt_ggtt_gm_sz(gvt) (gvt->dev_priv->ggtt.base.total) | ||
| 238 | #define gvt_ggtt_sz(gvt) \ | ||
| 239 | ((gvt->dev_priv->ggtt.base.total >> PAGE_SHIFT) << 3) | ||
| 240 | #define gvt_hidden_sz(gvt) (gvt_ggtt_gm_sz(gvt) - gvt_aperture_sz(gvt)) | ||
| 241 | |||
| 242 | #define gvt_aperture_gmadr_base(gvt) (0) | ||
| 243 | #define gvt_aperture_gmadr_end(gvt) (gvt_aperture_gmadr_base(gvt) \ | ||
| 244 | + gvt_aperture_sz(gvt) - 1) | ||
| 245 | |||
| 246 | #define gvt_hidden_gmadr_base(gvt) (gvt_aperture_gmadr_base(gvt) \ | ||
| 247 | + gvt_aperture_sz(gvt)) | ||
| 248 | #define gvt_hidden_gmadr_end(gvt) (gvt_hidden_gmadr_base(gvt) \ | ||
| 249 | + gvt_hidden_sz(gvt) - 1) | ||
| 250 | |||
| 251 | #define gvt_fence_sz(gvt) (gvt->dev_priv->num_fence_regs) | ||
| 252 | |||
| 253 | /* Aperture/GM space definitions for vGPU */ | ||
| 254 | #define vgpu_aperture_offset(vgpu) ((vgpu)->gm.low_gm_node.start) | ||
| 255 | #define vgpu_hidden_offset(vgpu) ((vgpu)->gm.high_gm_node.start) | ||
| 256 | #define vgpu_aperture_sz(vgpu) ((vgpu)->gm.aperture_sz) | ||
| 257 | #define vgpu_hidden_sz(vgpu) ((vgpu)->gm.hidden_sz) | ||
| 258 | |||
| 259 | #define vgpu_aperture_pa_base(vgpu) \ | ||
| 260 | (gvt_aperture_pa_base(vgpu->gvt) + vgpu_aperture_offset(vgpu)) | ||
| 261 | |||
| 262 | #define vgpu_ggtt_gm_sz(vgpu) ((vgpu)->gm.aperture_sz + (vgpu)->gm.hidden_sz) | ||
| 263 | |||
| 264 | #define vgpu_aperture_pa_end(vgpu) \ | ||
| 265 | (vgpu_aperture_pa_base(vgpu) + vgpu_aperture_sz(vgpu) - 1) | ||
| 266 | |||
| 267 | #define vgpu_aperture_gmadr_base(vgpu) (vgpu_aperture_offset(vgpu)) | ||
| 268 | #define vgpu_aperture_gmadr_end(vgpu) \ | ||
| 269 | (vgpu_aperture_gmadr_base(vgpu) + vgpu_aperture_sz(vgpu) - 1) | ||
| 270 | |||
| 271 | #define vgpu_hidden_gmadr_base(vgpu) (vgpu_hidden_offset(vgpu)) | ||
| 272 | #define vgpu_hidden_gmadr_end(vgpu) \ | ||
| 273 | (vgpu_hidden_gmadr_base(vgpu) + vgpu_hidden_sz(vgpu) - 1) | ||
| 274 | |||
| 275 | #define vgpu_fence_base(vgpu) (vgpu->fence.base) | ||
| 276 | #define vgpu_fence_sz(vgpu) (vgpu->fence.size) | ||
| 277 | |||
| 278 | struct intel_vgpu_creation_params { | ||
| 279 | __u64 handle; | ||
| 280 | __u64 low_gm_sz; /* in MB */ | ||
| 281 | __u64 high_gm_sz; /* in MB */ | ||
| 282 | __u64 fence_sz; | ||
| 283 | __s32 primary; | ||
| 284 | __u64 vgpu_id; | ||
| 285 | }; | ||
| 286 | |||
| 287 | int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu, | ||
| 288 | struct intel_vgpu_creation_params *param); | ||
| 289 | void intel_vgpu_free_resource(struct intel_vgpu *vgpu); | ||
| 290 | void intel_vgpu_write_fence(struct intel_vgpu *vgpu, | ||
| 291 | u32 fence, u64 value); | ||
| 292 | |||
| 293 | /* Macros for easily accessing vGPU virtual/shadow register */ | ||
| 294 | #define vgpu_vreg(vgpu, reg) \ | ||
| 295 | (*(u32 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg))) | ||
| 296 | #define vgpu_vreg8(vgpu, reg) \ | ||
| 297 | (*(u8 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg))) | ||
| 298 | #define vgpu_vreg16(vgpu, reg) \ | ||
| 299 | (*(u16 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg))) | ||
| 300 | #define vgpu_vreg64(vgpu, reg) \ | ||
| 301 | (*(u64 *)(vgpu->mmio.vreg + INTEL_GVT_MMIO_OFFSET(reg))) | ||
| 302 | #define vgpu_sreg(vgpu, reg) \ | ||
| 303 | (*(u32 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg))) | ||
| 304 | #define vgpu_sreg8(vgpu, reg) \ | ||
| 305 | (*(u8 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg))) | ||
| 306 | #define vgpu_sreg16(vgpu, reg) \ | ||
| 307 | (*(u16 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg))) | ||
| 308 | #define vgpu_sreg64(vgpu, reg) \ | ||
| 309 | (*(u64 *)(vgpu->mmio.sreg + INTEL_GVT_MMIO_OFFSET(reg))) | ||
| 310 | |||
| 311 | #define for_each_active_vgpu(gvt, vgpu, id) \ | ||
| 312 | idr_for_each_entry((&(gvt)->vgpu_idr), (vgpu), (id)) \ | ||
| 313 | for_each_if(vgpu->active) | ||
| 314 | |||
| 315 | static inline void intel_vgpu_write_pci_bar(struct intel_vgpu *vgpu, | ||
| 316 | u32 offset, u32 val, bool low) | ||
| 317 | { | ||
| 318 | u32 *pval; | ||
| 319 | |||
| 320 | /* BAR offset should be 32 bits algiend */ | ||
| 321 | offset = rounddown(offset, 4); | ||
| 322 | pval = (u32 *)(vgpu_cfg_space(vgpu) + offset); | ||
| 323 | |||
| 324 | if (low) { | ||
| 325 | /* | ||
| 326 | * only update bit 31 - bit 4, | ||
| 327 | * leave the bit 3 - bit 0 unchanged. | ||
| 328 | */ | ||
| 329 | *pval = (val & GENMASK(31, 4)) | (*pval & GENMASK(3, 0)); | ||
| 330 | } | ||
| 331 | } | ||
| 332 | |||
| 333 | struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, | ||
| 334 | struct intel_vgpu_creation_params * | ||
| 335 | param); | ||
| 336 | |||
| 337 | void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu); | ||
| 338 | |||
| 339 | /* validating GM functions */ | ||
| 340 | #define vgpu_gmadr_is_aperture(vgpu, gmadr) \ | ||
| 341 | ((gmadr >= vgpu_aperture_gmadr_base(vgpu)) && \ | ||
| 342 | (gmadr <= vgpu_aperture_gmadr_end(vgpu))) | ||
| 343 | |||
| 344 | #define vgpu_gmadr_is_hidden(vgpu, gmadr) \ | ||
| 345 | ((gmadr >= vgpu_hidden_gmadr_base(vgpu)) && \ | ||
| 346 | (gmadr <= vgpu_hidden_gmadr_end(vgpu))) | ||
| 347 | |||
| 348 | #define vgpu_gmadr_is_valid(vgpu, gmadr) \ | ||
| 349 | ((vgpu_gmadr_is_aperture(vgpu, gmadr) || \ | ||
| 350 | (vgpu_gmadr_is_hidden(vgpu, gmadr)))) | ||
| 351 | |||
| 352 | #define gvt_gmadr_is_aperture(gvt, gmadr) \ | ||
| 353 | ((gmadr >= gvt_aperture_gmadr_base(gvt)) && \ | ||
| 354 | (gmadr <= gvt_aperture_gmadr_end(gvt))) | ||
| 355 | |||
| 356 | #define gvt_gmadr_is_hidden(gvt, gmadr) \ | ||
| 357 | ((gmadr >= gvt_hidden_gmadr_base(gvt)) && \ | ||
| 358 | (gmadr <= gvt_hidden_gmadr_end(gvt))) | ||
| 359 | |||
| 360 | #define gvt_gmadr_is_valid(gvt, gmadr) \ | ||
| 361 | (gvt_gmadr_is_aperture(gvt, gmadr) || \ | ||
| 362 | gvt_gmadr_is_hidden(gvt, gmadr)) | ||
| 363 | |||
| 364 | bool intel_gvt_ggtt_validate_range(struct intel_vgpu *vgpu, u64 addr, u32 size); | ||
| 365 | int intel_gvt_ggtt_gmadr_g2h(struct intel_vgpu *vgpu, u64 g_addr, u64 *h_addr); | ||
| 366 | int intel_gvt_ggtt_gmadr_h2g(struct intel_vgpu *vgpu, u64 h_addr, u64 *g_addr); | ||
| 367 | int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index, | ||
| 368 | unsigned long *h_index); | ||
| 369 | int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index, | ||
| 370 | unsigned long *g_index); | ||
| 371 | |||
| 372 | int intel_vgpu_emulate_cfg_read(void *__vgpu, unsigned int offset, | ||
| 373 | void *p_data, unsigned int bytes); | ||
| 374 | |||
| 375 | int intel_vgpu_emulate_cfg_write(void *__vgpu, unsigned int offset, | ||
| 376 | void *p_data, unsigned int bytes); | ||
| 377 | |||
| 378 | void intel_gvt_clean_opregion(struct intel_gvt *gvt); | ||
| 379 | int intel_gvt_init_opregion(struct intel_gvt *gvt); | ||
| 380 | |||
| 381 | void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu); | ||
| 382 | int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa); | ||
| 383 | |||
| 384 | int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci); | ||
| 385 | |||
| 67 | #include "mpt.h" | 386 | #include "mpt.h" |
| 68 | 387 | ||
| 69 | #endif | 388 | #endif |
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c new file mode 100644 index 000000000000..3e74fb3d4aa9 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/handlers.c | |||
| @@ -0,0 +1,2797 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Kevin Tian <kevin.tian@intel.com> | ||
| 25 | * Eddie Dong <eddie.dong@intel.com> | ||
| 26 | * Zhiyuan Lv <zhiyuan.lv@intel.com> | ||
| 27 | * | ||
| 28 | * Contributors: | ||
| 29 | * Min He <min.he@intel.com> | ||
| 30 | * Tina Zhang <tina.zhang@intel.com> | ||
| 31 | * Pei Zhang <pei.zhang@intel.com> | ||
| 32 | * Niu Bing <bing.niu@intel.com> | ||
| 33 | * Ping Gao <ping.a.gao@intel.com> | ||
| 34 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 35 | * | ||
| 36 | |||
| 37 | */ | ||
| 38 | |||
| 39 | #include "i915_drv.h" | ||
| 40 | #include "gvt.h" | ||
| 41 | #include "i915_pvinfo.h" | ||
| 42 | |||
| 43 | /* XXX FIXME i915 has changed PP_XXX definition */ | ||
| 44 | #define PCH_PP_STATUS _MMIO(0xc7200) | ||
| 45 | #define PCH_PP_CONTROL _MMIO(0xc7204) | ||
| 46 | #define PCH_PP_ON_DELAYS _MMIO(0xc7208) | ||
| 47 | #define PCH_PP_OFF_DELAYS _MMIO(0xc720c) | ||
| 48 | #define PCH_PP_DIVISOR _MMIO(0xc7210) | ||
| 49 | |||
| 50 | /* Register contains RO bits */ | ||
| 51 | #define F_RO (1 << 0) | ||
| 52 | /* Register contains graphics address */ | ||
| 53 | #define F_GMADR (1 << 1) | ||
| 54 | /* Mode mask registers with high 16 bits as the mask bits */ | ||
| 55 | #define F_MODE_MASK (1 << 2) | ||
| 56 | /* This reg can be accessed by GPU commands */ | ||
| 57 | #define F_CMD_ACCESS (1 << 3) | ||
| 58 | /* This reg has been accessed by a VM */ | ||
| 59 | #define F_ACCESSED (1 << 4) | ||
| 60 | /* This reg has been accessed through GPU commands */ | ||
| 61 | #define F_CMD_ACCESSED (1 << 5) | ||
| 62 | /* This reg could be accessed by unaligned address */ | ||
| 63 | #define F_UNALIGN (1 << 6) | ||
| 64 | |||
| 65 | unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt) | ||
| 66 | { | ||
| 67 | if (IS_BROADWELL(gvt->dev_priv)) | ||
| 68 | return D_BDW; | ||
| 69 | else if (IS_SKYLAKE(gvt->dev_priv)) | ||
| 70 | return D_SKL; | ||
| 71 | |||
| 72 | return 0; | ||
| 73 | } | ||
| 74 | |||
| 75 | bool intel_gvt_match_device(struct intel_gvt *gvt, | ||
| 76 | unsigned long device) | ||
| 77 | { | ||
| 78 | return intel_gvt_get_device_type(gvt) & device; | ||
| 79 | } | ||
| 80 | |||
| 81 | static void read_vreg(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 82 | void *p_data, unsigned int bytes) | ||
| 83 | { | ||
| 84 | memcpy(p_data, &vgpu_vreg(vgpu, offset), bytes); | ||
| 85 | } | ||
| 86 | |||
| 87 | static void write_vreg(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 88 | void *p_data, unsigned int bytes) | ||
| 89 | { | ||
| 90 | memcpy(&vgpu_vreg(vgpu, offset), p_data, bytes); | ||
| 91 | } | ||
| 92 | |||
| 93 | static int new_mmio_info(struct intel_gvt *gvt, | ||
| 94 | u32 offset, u32 flags, u32 size, | ||
| 95 | u32 addr_mask, u32 ro_mask, u32 device, | ||
| 96 | void *read, void *write) | ||
| 97 | { | ||
| 98 | struct intel_gvt_mmio_info *info, *p; | ||
| 99 | u32 start, end, i; | ||
| 100 | |||
| 101 | if (!intel_gvt_match_device(gvt, device)) | ||
| 102 | return 0; | ||
| 103 | |||
| 104 | if (WARN_ON(!IS_ALIGNED(offset, 4))) | ||
| 105 | return -EINVAL; | ||
| 106 | |||
| 107 | start = offset; | ||
| 108 | end = offset + size; | ||
| 109 | |||
| 110 | for (i = start; i < end; i += 4) { | ||
| 111 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
| 112 | if (!info) | ||
| 113 | return -ENOMEM; | ||
| 114 | |||
| 115 | info->offset = i; | ||
| 116 | p = intel_gvt_find_mmio_info(gvt, info->offset); | ||
| 117 | if (p) | ||
| 118 | gvt_err("dup mmio definition offset %x\n", | ||
| 119 | info->offset); | ||
| 120 | info->size = size; | ||
| 121 | info->length = (i + 4) < end ? 4 : (end - i); | ||
| 122 | info->addr_mask = addr_mask; | ||
| 123 | info->device = device; | ||
| 124 | info->read = read ? read : intel_vgpu_default_mmio_read; | ||
| 125 | info->write = write ? write : intel_vgpu_default_mmio_write; | ||
| 126 | gvt->mmio.mmio_attribute[info->offset / 4] = flags; | ||
| 127 | INIT_HLIST_NODE(&info->node); | ||
| 128 | hash_add(gvt->mmio.mmio_info_table, &info->node, info->offset); | ||
| 129 | } | ||
| 130 | return 0; | ||
| 131 | } | ||
| 132 | |||
| 133 | static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg) | ||
| 134 | { | ||
| 135 | enum intel_engine_id id; | ||
| 136 | struct intel_engine_cs *engine; | ||
| 137 | |||
| 138 | reg &= ~GENMASK(11, 0); | ||
| 139 | for_each_engine(engine, gvt->dev_priv, id) { | ||
| 140 | if (engine->mmio_base == reg) | ||
| 141 | return id; | ||
| 142 | } | ||
| 143 | return -1; | ||
| 144 | } | ||
| 145 | |||
| 146 | #define offset_to_fence_num(offset) \ | ||
| 147 | ((offset - i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0))) >> 3) | ||
| 148 | |||
| 149 | #define fence_num_to_offset(num) \ | ||
| 150 | (num * 8 + i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0))) | ||
| 151 | |||
| 152 | static int sanitize_fence_mmio_access(struct intel_vgpu *vgpu, | ||
| 153 | unsigned int fence_num, void *p_data, unsigned int bytes) | ||
| 154 | { | ||
| 155 | if (fence_num >= vgpu_fence_sz(vgpu)) { | ||
| 156 | gvt_err("vgpu%d: found oob fence register access\n", | ||
| 157 | vgpu->id); | ||
| 158 | gvt_err("vgpu%d: total fence num %d access fence num %d\n", | ||
| 159 | vgpu->id, vgpu_fence_sz(vgpu), fence_num); | ||
| 160 | memset(p_data, 0, bytes); | ||
| 161 | } | ||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int fence_mmio_read(struct intel_vgpu *vgpu, unsigned int off, | ||
| 166 | void *p_data, unsigned int bytes) | ||
| 167 | { | ||
| 168 | int ret; | ||
| 169 | |||
| 170 | ret = sanitize_fence_mmio_access(vgpu, offset_to_fence_num(off), | ||
| 171 | p_data, bytes); | ||
| 172 | if (ret) | ||
| 173 | return ret; | ||
| 174 | read_vreg(vgpu, off, p_data, bytes); | ||
| 175 | return 0; | ||
| 176 | } | ||
| 177 | |||
| 178 | static int fence_mmio_write(struct intel_vgpu *vgpu, unsigned int off, | ||
| 179 | void *p_data, unsigned int bytes) | ||
| 180 | { | ||
| 181 | unsigned int fence_num = offset_to_fence_num(off); | ||
| 182 | int ret; | ||
| 183 | |||
| 184 | ret = sanitize_fence_mmio_access(vgpu, fence_num, p_data, bytes); | ||
| 185 | if (ret) | ||
| 186 | return ret; | ||
| 187 | write_vreg(vgpu, off, p_data, bytes); | ||
| 188 | |||
| 189 | intel_vgpu_write_fence(vgpu, fence_num, | ||
| 190 | vgpu_vreg64(vgpu, fence_num_to_offset(fence_num))); | ||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | #define CALC_MODE_MASK_REG(old, new) \ | ||
| 195 | (((new) & GENMASK(31, 16)) \ | ||
| 196 | | ((((old) & GENMASK(15, 0)) & ~((new) >> 16)) \ | ||
| 197 | | ((new) & ((new) >> 16)))) | ||
| 198 | |||
| 199 | static int mul_force_wake_write(struct intel_vgpu *vgpu, | ||
| 200 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 201 | { | ||
| 202 | u32 old, new; | ||
| 203 | uint32_t ack_reg_offset; | ||
| 204 | |||
| 205 | old = vgpu_vreg(vgpu, offset); | ||
| 206 | new = CALC_MODE_MASK_REG(old, *(u32 *)p_data); | ||
| 207 | |||
| 208 | if (IS_SKYLAKE(vgpu->gvt->dev_priv)) { | ||
| 209 | switch (offset) { | ||
| 210 | case FORCEWAKE_RENDER_GEN9_REG: | ||
| 211 | ack_reg_offset = FORCEWAKE_ACK_RENDER_GEN9_REG; | ||
| 212 | break; | ||
| 213 | case FORCEWAKE_BLITTER_GEN9_REG: | ||
| 214 | ack_reg_offset = FORCEWAKE_ACK_BLITTER_GEN9_REG; | ||
| 215 | break; | ||
| 216 | case FORCEWAKE_MEDIA_GEN9_REG: | ||
| 217 | ack_reg_offset = FORCEWAKE_ACK_MEDIA_GEN9_REG; | ||
| 218 | break; | ||
| 219 | default: | ||
| 220 | /*should not hit here*/ | ||
| 221 | gvt_err("invalid forcewake offset 0x%x\n", offset); | ||
| 222 | return 1; | ||
| 223 | } | ||
| 224 | } else { | ||
| 225 | ack_reg_offset = FORCEWAKE_ACK_HSW_REG; | ||
| 226 | } | ||
| 227 | |||
| 228 | vgpu_vreg(vgpu, offset) = new; | ||
| 229 | vgpu_vreg(vgpu, ack_reg_offset) = (new & GENMASK(15, 0)); | ||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | |||
| 233 | static int handle_device_reset(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 234 | void *p_data, unsigned int bytes, unsigned long bitmap) | ||
| 235 | { | ||
| 236 | struct intel_gvt_workload_scheduler *scheduler = | ||
| 237 | &vgpu->gvt->scheduler; | ||
| 238 | |||
| 239 | vgpu->resetting = true; | ||
| 240 | |||
| 241 | intel_vgpu_stop_schedule(vgpu); | ||
| 242 | if (scheduler->current_vgpu == vgpu) { | ||
| 243 | mutex_unlock(&vgpu->gvt->lock); | ||
| 244 | intel_gvt_wait_vgpu_idle(vgpu); | ||
| 245 | mutex_lock(&vgpu->gvt->lock); | ||
| 246 | } | ||
| 247 | |||
| 248 | intel_vgpu_reset_execlist(vgpu, bitmap); | ||
| 249 | |||
| 250 | vgpu->resetting = false; | ||
| 251 | |||
| 252 | return 0; | ||
| 253 | } | ||
| 254 | |||
| 255 | static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 256 | void *p_data, unsigned int bytes) | ||
| 257 | { | ||
| 258 | u32 data; | ||
| 259 | u64 bitmap = 0; | ||
| 260 | |||
| 261 | data = vgpu_vreg(vgpu, offset); | ||
| 262 | |||
| 263 | if (data & GEN6_GRDOM_FULL) { | ||
| 264 | gvt_dbg_mmio("vgpu%d: request full GPU reset\n", vgpu->id); | ||
| 265 | bitmap = 0xff; | ||
| 266 | } | ||
| 267 | if (data & GEN6_GRDOM_RENDER) { | ||
| 268 | gvt_dbg_mmio("vgpu%d: request RCS reset\n", vgpu->id); | ||
| 269 | bitmap |= (1 << RCS); | ||
| 270 | } | ||
| 271 | if (data & GEN6_GRDOM_MEDIA) { | ||
| 272 | gvt_dbg_mmio("vgpu%d: request VCS reset\n", vgpu->id); | ||
| 273 | bitmap |= (1 << VCS); | ||
| 274 | } | ||
| 275 | if (data & GEN6_GRDOM_BLT) { | ||
| 276 | gvt_dbg_mmio("vgpu%d: request BCS Reset\n", vgpu->id); | ||
| 277 | bitmap |= (1 << BCS); | ||
| 278 | } | ||
| 279 | if (data & GEN6_GRDOM_VECS) { | ||
| 280 | gvt_dbg_mmio("vgpu%d: request VECS Reset\n", vgpu->id); | ||
| 281 | bitmap |= (1 << VECS); | ||
| 282 | } | ||
| 283 | if (data & GEN8_GRDOM_MEDIA2) { | ||
| 284 | gvt_dbg_mmio("vgpu%d: request VCS2 Reset\n", vgpu->id); | ||
| 285 | if (HAS_BSD2(vgpu->gvt->dev_priv)) | ||
| 286 | bitmap |= (1 << VCS2); | ||
| 287 | } | ||
| 288 | return handle_device_reset(vgpu, offset, p_data, bytes, bitmap); | ||
| 289 | } | ||
| 290 | |||
| 291 | static int gmbus_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 292 | void *p_data, unsigned int bytes) | ||
| 293 | { | ||
| 294 | return intel_gvt_i2c_handle_gmbus_read(vgpu, offset, p_data, bytes); | ||
| 295 | } | ||
| 296 | |||
| 297 | static int gmbus_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 298 | void *p_data, unsigned int bytes) | ||
| 299 | { | ||
| 300 | return intel_gvt_i2c_handle_gmbus_write(vgpu, offset, p_data, bytes); | ||
| 301 | } | ||
| 302 | |||
| 303 | static int pch_pp_control_mmio_write(struct intel_vgpu *vgpu, | ||
| 304 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 305 | { | ||
| 306 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 307 | |||
| 308 | if (vgpu_vreg(vgpu, offset) & PANEL_POWER_ON) { | ||
| 309 | vgpu_vreg(vgpu, PCH_PP_STATUS) |= PP_ON; | ||
| 310 | vgpu_vreg(vgpu, PCH_PP_STATUS) |= PP_SEQUENCE_STATE_ON_IDLE; | ||
| 311 | vgpu_vreg(vgpu, PCH_PP_STATUS) &= ~PP_SEQUENCE_POWER_DOWN; | ||
| 312 | vgpu_vreg(vgpu, PCH_PP_STATUS) &= ~PP_CYCLE_DELAY_ACTIVE; | ||
| 313 | |||
| 314 | } else | ||
| 315 | vgpu_vreg(vgpu, PCH_PP_STATUS) &= | ||
| 316 | ~(PP_ON | PP_SEQUENCE_POWER_DOWN | ||
| 317 | | PP_CYCLE_DELAY_ACTIVE); | ||
| 318 | return 0; | ||
| 319 | } | ||
| 320 | |||
| 321 | static int transconf_mmio_write(struct intel_vgpu *vgpu, | ||
| 322 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 323 | { | ||
| 324 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 325 | |||
| 326 | if (vgpu_vreg(vgpu, offset) & TRANS_ENABLE) | ||
| 327 | vgpu_vreg(vgpu, offset) |= TRANS_STATE_ENABLE; | ||
| 328 | else | ||
| 329 | vgpu_vreg(vgpu, offset) &= ~TRANS_STATE_ENABLE; | ||
| 330 | return 0; | ||
| 331 | } | ||
| 332 | |||
| 333 | static int lcpll_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 334 | void *p_data, unsigned int bytes) | ||
| 335 | { | ||
| 336 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 337 | |||
| 338 | if (vgpu_vreg(vgpu, offset) & LCPLL_PLL_DISABLE) | ||
| 339 | vgpu_vreg(vgpu, offset) &= ~LCPLL_PLL_LOCK; | ||
| 340 | else | ||
| 341 | vgpu_vreg(vgpu, offset) |= LCPLL_PLL_LOCK; | ||
| 342 | |||
| 343 | if (vgpu_vreg(vgpu, offset) & LCPLL_CD_SOURCE_FCLK) | ||
| 344 | vgpu_vreg(vgpu, offset) |= LCPLL_CD_SOURCE_FCLK_DONE; | ||
| 345 | else | ||
| 346 | vgpu_vreg(vgpu, offset) &= ~LCPLL_CD_SOURCE_FCLK_DONE; | ||
| 347 | |||
| 348 | return 0; | ||
| 349 | } | ||
| 350 | |||
| 351 | static int dpy_reg_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 352 | void *p_data, unsigned int bytes) | ||
| 353 | { | ||
| 354 | *(u32 *)p_data = (1 << 17); | ||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static int dpy_reg_mmio_read_2(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 359 | void *p_data, unsigned int bytes) | ||
| 360 | { | ||
| 361 | *(u32 *)p_data = 3; | ||
| 362 | return 0; | ||
| 363 | } | ||
| 364 | |||
| 365 | static int dpy_reg_mmio_read_3(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 366 | void *p_data, unsigned int bytes) | ||
| 367 | { | ||
| 368 | *(u32 *)p_data = (0x2f << 16); | ||
| 369 | return 0; | ||
| 370 | } | ||
| 371 | |||
| 372 | static int pipeconf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 373 | void *p_data, unsigned int bytes) | ||
| 374 | { | ||
| 375 | u32 data; | ||
| 376 | |||
| 377 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 378 | data = vgpu_vreg(vgpu, offset); | ||
| 379 | |||
| 380 | if (data & PIPECONF_ENABLE) | ||
| 381 | vgpu_vreg(vgpu, offset) |= I965_PIPECONF_ACTIVE; | ||
| 382 | else | ||
| 383 | vgpu_vreg(vgpu, offset) &= ~I965_PIPECONF_ACTIVE; | ||
| 384 | intel_gvt_check_vblank_emulation(vgpu->gvt); | ||
| 385 | return 0; | ||
| 386 | } | ||
| 387 | |||
| 388 | static int ddi_buf_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 389 | void *p_data, unsigned int bytes) | ||
| 390 | { | ||
| 391 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 392 | |||
| 393 | if (vgpu_vreg(vgpu, offset) & DDI_BUF_CTL_ENABLE) { | ||
| 394 | vgpu_vreg(vgpu, offset) &= ~DDI_BUF_IS_IDLE; | ||
| 395 | } else { | ||
| 396 | vgpu_vreg(vgpu, offset) |= DDI_BUF_IS_IDLE; | ||
| 397 | if (offset == i915_mmio_reg_offset(DDI_BUF_CTL(PORT_E))) | ||
| 398 | vgpu_vreg(vgpu, DP_TP_STATUS(PORT_E)) | ||
| 399 | &= ~DP_TP_STATUS_AUTOTRAIN_DONE; | ||
| 400 | } | ||
| 401 | return 0; | ||
| 402 | } | ||
| 403 | |||
| 404 | static int fdi_rx_iir_mmio_write(struct intel_vgpu *vgpu, | ||
| 405 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 406 | { | ||
| 407 | vgpu_vreg(vgpu, offset) &= ~*(u32 *)p_data; | ||
| 408 | return 0; | ||
| 409 | } | ||
| 410 | |||
| 411 | #define FDI_LINK_TRAIN_PATTERN1 0 | ||
| 412 | #define FDI_LINK_TRAIN_PATTERN2 1 | ||
| 413 | |||
| 414 | static int fdi_auto_training_started(struct intel_vgpu *vgpu) | ||
| 415 | { | ||
| 416 | u32 ddi_buf_ctl = vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_E)); | ||
| 417 | u32 rx_ctl = vgpu_vreg(vgpu, _FDI_RXA_CTL); | ||
| 418 | u32 tx_ctl = vgpu_vreg(vgpu, DP_TP_CTL(PORT_E)); | ||
| 419 | |||
| 420 | if ((ddi_buf_ctl & DDI_BUF_CTL_ENABLE) && | ||
| 421 | (rx_ctl & FDI_RX_ENABLE) && | ||
| 422 | (rx_ctl & FDI_AUTO_TRAINING) && | ||
| 423 | (tx_ctl & DP_TP_CTL_ENABLE) && | ||
| 424 | (tx_ctl & DP_TP_CTL_FDI_AUTOTRAIN)) | ||
| 425 | return 1; | ||
| 426 | else | ||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 430 | static int check_fdi_rx_train_status(struct intel_vgpu *vgpu, | ||
| 431 | enum pipe pipe, unsigned int train_pattern) | ||
| 432 | { | ||
| 433 | i915_reg_t fdi_rx_imr, fdi_tx_ctl, fdi_rx_ctl; | ||
| 434 | unsigned int fdi_rx_check_bits, fdi_tx_check_bits; | ||
| 435 | unsigned int fdi_rx_train_bits, fdi_tx_train_bits; | ||
| 436 | unsigned int fdi_iir_check_bits; | ||
| 437 | |||
| 438 | fdi_rx_imr = FDI_RX_IMR(pipe); | ||
| 439 | fdi_tx_ctl = FDI_TX_CTL(pipe); | ||
| 440 | fdi_rx_ctl = FDI_RX_CTL(pipe); | ||
| 441 | |||
| 442 | if (train_pattern == FDI_LINK_TRAIN_PATTERN1) { | ||
| 443 | fdi_rx_train_bits = FDI_LINK_TRAIN_PATTERN_1_CPT; | ||
| 444 | fdi_tx_train_bits = FDI_LINK_TRAIN_PATTERN_1; | ||
| 445 | fdi_iir_check_bits = FDI_RX_BIT_LOCK; | ||
| 446 | } else if (train_pattern == FDI_LINK_TRAIN_PATTERN2) { | ||
| 447 | fdi_rx_train_bits = FDI_LINK_TRAIN_PATTERN_2_CPT; | ||
| 448 | fdi_tx_train_bits = FDI_LINK_TRAIN_PATTERN_2; | ||
| 449 | fdi_iir_check_bits = FDI_RX_SYMBOL_LOCK; | ||
| 450 | } else { | ||
| 451 | gvt_err("Invalid train pattern %d\n", train_pattern); | ||
| 452 | return -EINVAL; | ||
| 453 | } | ||
| 454 | |||
| 455 | fdi_rx_check_bits = FDI_RX_ENABLE | fdi_rx_train_bits; | ||
| 456 | fdi_tx_check_bits = FDI_TX_ENABLE | fdi_tx_train_bits; | ||
| 457 | |||
| 458 | /* If imr bit has been masked */ | ||
| 459 | if (vgpu_vreg(vgpu, fdi_rx_imr) & fdi_iir_check_bits) | ||
| 460 | return 0; | ||
| 461 | |||
| 462 | if (((vgpu_vreg(vgpu, fdi_tx_ctl) & fdi_tx_check_bits) | ||
| 463 | == fdi_tx_check_bits) | ||
| 464 | && ((vgpu_vreg(vgpu, fdi_rx_ctl) & fdi_rx_check_bits) | ||
| 465 | == fdi_rx_check_bits)) | ||
| 466 | return 1; | ||
| 467 | else | ||
| 468 | return 0; | ||
| 469 | } | ||
| 470 | |||
| 471 | #define INVALID_INDEX (~0U) | ||
| 472 | |||
| 473 | static unsigned int calc_index(unsigned int offset, unsigned int start, | ||
| 474 | unsigned int next, unsigned int end, i915_reg_t i915_end) | ||
| 475 | { | ||
| 476 | unsigned int range = next - start; | ||
| 477 | |||
| 478 | if (!end) | ||
| 479 | end = i915_mmio_reg_offset(i915_end); | ||
| 480 | if (offset < start || offset > end) | ||
| 481 | return INVALID_INDEX; | ||
| 482 | offset -= start; | ||
| 483 | return offset / range; | ||
| 484 | } | ||
| 485 | |||
| 486 | #define FDI_RX_CTL_TO_PIPE(offset) \ | ||
| 487 | calc_index(offset, _FDI_RXA_CTL, _FDI_RXB_CTL, 0, FDI_RX_CTL(PIPE_C)) | ||
| 488 | |||
| 489 | #define FDI_TX_CTL_TO_PIPE(offset) \ | ||
| 490 | calc_index(offset, _FDI_TXA_CTL, _FDI_TXB_CTL, 0, FDI_TX_CTL(PIPE_C)) | ||
| 491 | |||
| 492 | #define FDI_RX_IMR_TO_PIPE(offset) \ | ||
| 493 | calc_index(offset, _FDI_RXA_IMR, _FDI_RXB_IMR, 0, FDI_RX_IMR(PIPE_C)) | ||
| 494 | |||
| 495 | static int update_fdi_rx_iir_status(struct intel_vgpu *vgpu, | ||
| 496 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 497 | { | ||
| 498 | i915_reg_t fdi_rx_iir; | ||
| 499 | unsigned int index; | ||
| 500 | int ret; | ||
| 501 | |||
| 502 | if (FDI_RX_CTL_TO_PIPE(offset) != INVALID_INDEX) | ||
| 503 | index = FDI_RX_CTL_TO_PIPE(offset); | ||
| 504 | else if (FDI_TX_CTL_TO_PIPE(offset) != INVALID_INDEX) | ||
| 505 | index = FDI_TX_CTL_TO_PIPE(offset); | ||
| 506 | else if (FDI_RX_IMR_TO_PIPE(offset) != INVALID_INDEX) | ||
| 507 | index = FDI_RX_IMR_TO_PIPE(offset); | ||
| 508 | else { | ||
| 509 | gvt_err("Unsupport registers %x\n", offset); | ||
| 510 | return -EINVAL; | ||
| 511 | } | ||
| 512 | |||
| 513 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 514 | |||
| 515 | fdi_rx_iir = FDI_RX_IIR(index); | ||
| 516 | |||
| 517 | ret = check_fdi_rx_train_status(vgpu, index, FDI_LINK_TRAIN_PATTERN1); | ||
| 518 | if (ret < 0) | ||
| 519 | return ret; | ||
| 520 | if (ret) | ||
| 521 | vgpu_vreg(vgpu, fdi_rx_iir) |= FDI_RX_BIT_LOCK; | ||
| 522 | |||
| 523 | ret = check_fdi_rx_train_status(vgpu, index, FDI_LINK_TRAIN_PATTERN2); | ||
| 524 | if (ret < 0) | ||
| 525 | return ret; | ||
| 526 | if (ret) | ||
| 527 | vgpu_vreg(vgpu, fdi_rx_iir) |= FDI_RX_SYMBOL_LOCK; | ||
| 528 | |||
| 529 | if (offset == _FDI_RXA_CTL) | ||
| 530 | if (fdi_auto_training_started(vgpu)) | ||
| 531 | vgpu_vreg(vgpu, DP_TP_STATUS(PORT_E)) |= | ||
| 532 | DP_TP_STATUS_AUTOTRAIN_DONE; | ||
| 533 | return 0; | ||
| 534 | } | ||
| 535 | |||
| 536 | #define DP_TP_CTL_TO_PORT(offset) \ | ||
| 537 | calc_index(offset, _DP_TP_CTL_A, _DP_TP_CTL_B, 0, DP_TP_CTL(PORT_E)) | ||
| 538 | |||
| 539 | static int dp_tp_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 540 | void *p_data, unsigned int bytes) | ||
| 541 | { | ||
| 542 | i915_reg_t status_reg; | ||
| 543 | unsigned int index; | ||
| 544 | u32 data; | ||
| 545 | |||
| 546 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 547 | |||
| 548 | index = DP_TP_CTL_TO_PORT(offset); | ||
| 549 | data = (vgpu_vreg(vgpu, offset) & GENMASK(10, 8)) >> 8; | ||
| 550 | if (data == 0x2) { | ||
| 551 | status_reg = DP_TP_STATUS(index); | ||
| 552 | vgpu_vreg(vgpu, status_reg) |= (1 << 25); | ||
| 553 | } | ||
| 554 | return 0; | ||
| 555 | } | ||
| 556 | |||
| 557 | static int dp_tp_status_mmio_write(struct intel_vgpu *vgpu, | ||
| 558 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 559 | { | ||
| 560 | u32 reg_val; | ||
| 561 | u32 sticky_mask; | ||
| 562 | |||
| 563 | reg_val = *((u32 *)p_data); | ||
| 564 | sticky_mask = GENMASK(27, 26) | (1 << 24); | ||
| 565 | |||
| 566 | vgpu_vreg(vgpu, offset) = (reg_val & ~sticky_mask) | | ||
| 567 | (vgpu_vreg(vgpu, offset) & sticky_mask); | ||
| 568 | vgpu_vreg(vgpu, offset) &= ~(reg_val & sticky_mask); | ||
| 569 | return 0; | ||
| 570 | } | ||
| 571 | |||
| 572 | static int pch_adpa_mmio_write(struct intel_vgpu *vgpu, | ||
| 573 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 574 | { | ||
| 575 | u32 data; | ||
| 576 | |||
| 577 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 578 | data = vgpu_vreg(vgpu, offset); | ||
| 579 | |||
| 580 | if (data & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) | ||
| 581 | vgpu_vreg(vgpu, offset) &= ~ADPA_CRT_HOTPLUG_FORCE_TRIGGER; | ||
| 582 | return 0; | ||
| 583 | } | ||
| 584 | |||
| 585 | static int south_chicken2_mmio_write(struct intel_vgpu *vgpu, | ||
| 586 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 587 | { | ||
| 588 | u32 data; | ||
| 589 | |||
| 590 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 591 | data = vgpu_vreg(vgpu, offset); | ||
| 592 | |||
| 593 | if (data & FDI_MPHY_IOSFSB_RESET_CTL) | ||
| 594 | vgpu_vreg(vgpu, offset) |= FDI_MPHY_IOSFSB_RESET_STATUS; | ||
| 595 | else | ||
| 596 | vgpu_vreg(vgpu, offset) &= ~FDI_MPHY_IOSFSB_RESET_STATUS; | ||
| 597 | return 0; | ||
| 598 | } | ||
| 599 | |||
| 600 | #define DSPSURF_TO_PIPE(offset) \ | ||
| 601 | calc_index(offset, _DSPASURF, _DSPBSURF, 0, DSPSURF(PIPE_C)) | ||
| 602 | |||
| 603 | static int pri_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 604 | void *p_data, unsigned int bytes) | ||
| 605 | { | ||
| 606 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 607 | unsigned int index = DSPSURF_TO_PIPE(offset); | ||
| 608 | i915_reg_t surflive_reg = DSPSURFLIVE(index); | ||
| 609 | int flip_event[] = { | ||
| 610 | [PIPE_A] = PRIMARY_A_FLIP_DONE, | ||
| 611 | [PIPE_B] = PRIMARY_B_FLIP_DONE, | ||
| 612 | [PIPE_C] = PRIMARY_C_FLIP_DONE, | ||
| 613 | }; | ||
| 614 | |||
| 615 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 616 | vgpu_vreg(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset); | ||
| 617 | |||
| 618 | set_bit(flip_event[index], vgpu->irq.flip_done_event[index]); | ||
| 619 | return 0; | ||
| 620 | } | ||
| 621 | |||
| 622 | #define SPRSURF_TO_PIPE(offset) \ | ||
| 623 | calc_index(offset, _SPRA_SURF, _SPRB_SURF, 0, SPRSURF(PIPE_C)) | ||
| 624 | |||
| 625 | static int spr_surf_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 626 | void *p_data, unsigned int bytes) | ||
| 627 | { | ||
| 628 | unsigned int index = SPRSURF_TO_PIPE(offset); | ||
| 629 | i915_reg_t surflive_reg = SPRSURFLIVE(index); | ||
| 630 | int flip_event[] = { | ||
| 631 | [PIPE_A] = SPRITE_A_FLIP_DONE, | ||
| 632 | [PIPE_B] = SPRITE_B_FLIP_DONE, | ||
| 633 | [PIPE_C] = SPRITE_C_FLIP_DONE, | ||
| 634 | }; | ||
| 635 | |||
| 636 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 637 | vgpu_vreg(vgpu, surflive_reg) = vgpu_vreg(vgpu, offset); | ||
| 638 | |||
| 639 | set_bit(flip_event[index], vgpu->irq.flip_done_event[index]); | ||
| 640 | return 0; | ||
| 641 | } | ||
| 642 | |||
| 643 | static int trigger_aux_channel_interrupt(struct intel_vgpu *vgpu, | ||
| 644 | unsigned int reg) | ||
| 645 | { | ||
| 646 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 647 | enum intel_gvt_event_type event; | ||
| 648 | |||
| 649 | if (reg == _DPA_AUX_CH_CTL) | ||
| 650 | event = AUX_CHANNEL_A; | ||
| 651 | else if (reg == _PCH_DPB_AUX_CH_CTL || reg == _DPB_AUX_CH_CTL) | ||
| 652 | event = AUX_CHANNEL_B; | ||
| 653 | else if (reg == _PCH_DPC_AUX_CH_CTL || reg == _DPC_AUX_CH_CTL) | ||
| 654 | event = AUX_CHANNEL_C; | ||
| 655 | else if (reg == _PCH_DPD_AUX_CH_CTL || reg == _DPD_AUX_CH_CTL) | ||
| 656 | event = AUX_CHANNEL_D; | ||
| 657 | else { | ||
| 658 | WARN_ON(true); | ||
| 659 | return -EINVAL; | ||
| 660 | } | ||
| 661 | |||
| 662 | intel_vgpu_trigger_virtual_event(vgpu, event); | ||
| 663 | return 0; | ||
| 664 | } | ||
| 665 | |||
| 666 | static int dp_aux_ch_ctl_trans_done(struct intel_vgpu *vgpu, u32 value, | ||
| 667 | unsigned int reg, int len, bool data_valid) | ||
| 668 | { | ||
| 669 | /* mark transaction done */ | ||
| 670 | value |= DP_AUX_CH_CTL_DONE; | ||
| 671 | value &= ~DP_AUX_CH_CTL_SEND_BUSY; | ||
| 672 | value &= ~DP_AUX_CH_CTL_RECEIVE_ERROR; | ||
| 673 | |||
| 674 | if (data_valid) | ||
| 675 | value &= ~DP_AUX_CH_CTL_TIME_OUT_ERROR; | ||
| 676 | else | ||
| 677 | value |= DP_AUX_CH_CTL_TIME_OUT_ERROR; | ||
| 678 | |||
| 679 | /* message size */ | ||
| 680 | value &= ~(0xf << 20); | ||
| 681 | value |= (len << 20); | ||
| 682 | vgpu_vreg(vgpu, reg) = value; | ||
| 683 | |||
| 684 | if (value & DP_AUX_CH_CTL_INTERRUPT) | ||
| 685 | return trigger_aux_channel_interrupt(vgpu, reg); | ||
| 686 | return 0; | ||
| 687 | } | ||
| 688 | |||
| 689 | static void dp_aux_ch_ctl_link_training(struct intel_vgpu_dpcd_data *dpcd, | ||
| 690 | uint8_t t) | ||
| 691 | { | ||
| 692 | if ((t & DPCD_TRAINING_PATTERN_SET_MASK) == DPCD_TRAINING_PATTERN_1) { | ||
| 693 | /* training pattern 1 for CR */ | ||
| 694 | /* set LANE0_CR_DONE, LANE1_CR_DONE */ | ||
| 695 | dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_LANES_CR_DONE; | ||
| 696 | /* set LANE2_CR_DONE, LANE3_CR_DONE */ | ||
| 697 | dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_LANES_CR_DONE; | ||
| 698 | } else if ((t & DPCD_TRAINING_PATTERN_SET_MASK) == | ||
| 699 | DPCD_TRAINING_PATTERN_2) { | ||
| 700 | /* training pattern 2 for EQ */ | ||
| 701 | /* Set CHANNEL_EQ_DONE and SYMBOL_LOCKED for Lane0_1 */ | ||
| 702 | dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_LANES_EQ_DONE; | ||
| 703 | dpcd->data[DPCD_LANE0_1_STATUS] |= DPCD_SYMBOL_LOCKED; | ||
| 704 | /* Set CHANNEL_EQ_DONE and SYMBOL_LOCKED for Lane2_3 */ | ||
| 705 | dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_LANES_EQ_DONE; | ||
| 706 | dpcd->data[DPCD_LANE2_3_STATUS] |= DPCD_SYMBOL_LOCKED; | ||
| 707 | /* set INTERLANE_ALIGN_DONE */ | ||
| 708 | dpcd->data[DPCD_LANE_ALIGN_STATUS_UPDATED] |= | ||
| 709 | DPCD_INTERLANE_ALIGN_DONE; | ||
| 710 | } else if ((t & DPCD_TRAINING_PATTERN_SET_MASK) == | ||
| 711 | DPCD_LINK_TRAINING_DISABLED) { | ||
| 712 | /* finish link training */ | ||
| 713 | /* set sink status as synchronized */ | ||
| 714 | dpcd->data[DPCD_SINK_STATUS] = DPCD_SINK_IN_SYNC; | ||
| 715 | } | ||
| 716 | } | ||
| 717 | |||
| 718 | #define _REG_HSW_DP_AUX_CH_CTL(dp) \ | ||
| 719 | ((dp) ? (_PCH_DPB_AUX_CH_CTL + ((dp)-1)*0x100) : 0x64010) | ||
| 720 | |||
| 721 | #define _REG_SKL_DP_AUX_CH_CTL(dp) (0x64010 + (dp) * 0x100) | ||
| 722 | |||
| 723 | #define OFFSET_TO_DP_AUX_PORT(offset) (((offset) & 0xF00) >> 8) | ||
| 724 | |||
| 725 | #define dpy_is_valid_port(port) \ | ||
| 726 | (((port) >= PORT_A) && ((port) < I915_MAX_PORTS)) | ||
| 727 | |||
| 728 | static int dp_aux_ch_ctl_mmio_write(struct intel_vgpu *vgpu, | ||
| 729 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 730 | { | ||
| 731 | struct intel_vgpu_display *display = &vgpu->display; | ||
| 732 | int msg, addr, ctrl, op, len; | ||
| 733 | int port_index = OFFSET_TO_DP_AUX_PORT(offset); | ||
| 734 | struct intel_vgpu_dpcd_data *dpcd = NULL; | ||
| 735 | struct intel_vgpu_port *port = NULL; | ||
| 736 | u32 data; | ||
| 737 | |||
| 738 | if (!dpy_is_valid_port(port_index)) { | ||
| 739 | gvt_err("GVT(%d): Unsupported DP port access!\n", vgpu->id); | ||
| 740 | return 0; | ||
| 741 | } | ||
| 742 | |||
| 743 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 744 | data = vgpu_vreg(vgpu, offset); | ||
| 745 | |||
| 746 | if (IS_SKYLAKE(vgpu->gvt->dev_priv) && | ||
| 747 | offset != _REG_SKL_DP_AUX_CH_CTL(port_index)) { | ||
| 748 | /* SKL DPB/C/D aux ctl register changed */ | ||
| 749 | return 0; | ||
| 750 | } else if (IS_BROADWELL(vgpu->gvt->dev_priv) && | ||
| 751 | offset != _REG_HSW_DP_AUX_CH_CTL(port_index)) { | ||
| 752 | /* write to the data registers */ | ||
| 753 | return 0; | ||
| 754 | } | ||
| 755 | |||
| 756 | if (!(data & DP_AUX_CH_CTL_SEND_BUSY)) { | ||
| 757 | /* just want to clear the sticky bits */ | ||
| 758 | vgpu_vreg(vgpu, offset) = 0; | ||
| 759 | return 0; | ||
| 760 | } | ||
| 761 | |||
| 762 | port = &display->ports[port_index]; | ||
| 763 | dpcd = port->dpcd; | ||
| 764 | |||
| 765 | /* read out message from DATA1 register */ | ||
| 766 | msg = vgpu_vreg(vgpu, offset + 4); | ||
| 767 | addr = (msg >> 8) & 0xffff; | ||
| 768 | ctrl = (msg >> 24) & 0xff; | ||
| 769 | len = msg & 0xff; | ||
| 770 | op = ctrl >> 4; | ||
| 771 | |||
| 772 | if (op == GVT_AUX_NATIVE_WRITE) { | ||
| 773 | int t; | ||
| 774 | uint8_t buf[16]; | ||
| 775 | |||
| 776 | if ((addr + len + 1) >= DPCD_SIZE) { | ||
| 777 | /* | ||
| 778 | * Write request exceeds what we supported, | ||
| 779 | * DCPD spec: When a Source Device is writing a DPCD | ||
| 780 | * address not supported by the Sink Device, the Sink | ||
| 781 | * Device shall reply with AUX NACK and “M” equal to | ||
| 782 | * zero. | ||
| 783 | */ | ||
| 784 | |||
| 785 | /* NAK the write */ | ||
| 786 | vgpu_vreg(vgpu, offset + 4) = AUX_NATIVE_REPLY_NAK; | ||
| 787 | dp_aux_ch_ctl_trans_done(vgpu, data, offset, 2, true); | ||
| 788 | return 0; | ||
| 789 | } | ||
| 790 | |||
| 791 | /* | ||
| 792 | * Write request format: (command + address) occupies | ||
| 793 | * 3 bytes, followed by (len + 1) bytes of data. | ||
| 794 | */ | ||
| 795 | if (WARN_ON((len + 4) > AUX_BURST_SIZE)) | ||
| 796 | return -EINVAL; | ||
| 797 | |||
| 798 | /* unpack data from vreg to buf */ | ||
| 799 | for (t = 0; t < 4; t++) { | ||
| 800 | u32 r = vgpu_vreg(vgpu, offset + 8 + t * 4); | ||
| 801 | |||
| 802 | buf[t * 4] = (r >> 24) & 0xff; | ||
| 803 | buf[t * 4 + 1] = (r >> 16) & 0xff; | ||
| 804 | buf[t * 4 + 2] = (r >> 8) & 0xff; | ||
| 805 | buf[t * 4 + 3] = r & 0xff; | ||
| 806 | } | ||
| 807 | |||
| 808 | /* write to virtual DPCD */ | ||
| 809 | if (dpcd && dpcd->data_valid) { | ||
| 810 | for (t = 0; t <= len; t++) { | ||
| 811 | int p = addr + t; | ||
| 812 | |||
| 813 | dpcd->data[p] = buf[t]; | ||
| 814 | /* check for link training */ | ||
| 815 | if (p == DPCD_TRAINING_PATTERN_SET) | ||
| 816 | dp_aux_ch_ctl_link_training(dpcd, | ||
| 817 | buf[t]); | ||
| 818 | } | ||
| 819 | } | ||
| 820 | |||
| 821 | /* ACK the write */ | ||
| 822 | vgpu_vreg(vgpu, offset + 4) = 0; | ||
| 823 | dp_aux_ch_ctl_trans_done(vgpu, data, offset, 1, | ||
| 824 | dpcd && dpcd->data_valid); | ||
| 825 | return 0; | ||
| 826 | } | ||
| 827 | |||
| 828 | if (op == GVT_AUX_NATIVE_READ) { | ||
| 829 | int idx, i, ret = 0; | ||
| 830 | |||
| 831 | if ((addr + len + 1) >= DPCD_SIZE) { | ||
| 832 | /* | ||
| 833 | * read request exceeds what we supported | ||
| 834 | * DPCD spec: A Sink Device receiving a Native AUX CH | ||
| 835 | * read request for an unsupported DPCD address must | ||
| 836 | * reply with an AUX ACK and read data set equal to | ||
| 837 | * zero instead of replying with AUX NACK. | ||
| 838 | */ | ||
| 839 | |||
| 840 | /* ACK the READ*/ | ||
| 841 | vgpu_vreg(vgpu, offset + 4) = 0; | ||
| 842 | vgpu_vreg(vgpu, offset + 8) = 0; | ||
| 843 | vgpu_vreg(vgpu, offset + 12) = 0; | ||
| 844 | vgpu_vreg(vgpu, offset + 16) = 0; | ||
| 845 | vgpu_vreg(vgpu, offset + 20) = 0; | ||
| 846 | |||
| 847 | dp_aux_ch_ctl_trans_done(vgpu, data, offset, len + 2, | ||
| 848 | true); | ||
| 849 | return 0; | ||
| 850 | } | ||
| 851 | |||
| 852 | for (idx = 1; idx <= 5; idx++) { | ||
| 853 | /* clear the data registers */ | ||
| 854 | vgpu_vreg(vgpu, offset + 4 * idx) = 0; | ||
| 855 | } | ||
| 856 | |||
| 857 | /* | ||
| 858 | * Read reply format: ACK (1 byte) plus (len + 1) bytes of data. | ||
| 859 | */ | ||
| 860 | if (WARN_ON((len + 2) > AUX_BURST_SIZE)) | ||
| 861 | return -EINVAL; | ||
| 862 | |||
| 863 | /* read from virtual DPCD to vreg */ | ||
| 864 | /* first 4 bytes: [ACK][addr][addr+1][addr+2] */ | ||
| 865 | if (dpcd && dpcd->data_valid) { | ||
| 866 | for (i = 1; i <= (len + 1); i++) { | ||
| 867 | int t; | ||
| 868 | |||
| 869 | t = dpcd->data[addr + i - 1]; | ||
| 870 | t <<= (24 - 8 * (i % 4)); | ||
| 871 | ret |= t; | ||
| 872 | |||
| 873 | if ((i % 4 == 3) || (i == (len + 1))) { | ||
| 874 | vgpu_vreg(vgpu, offset + | ||
| 875 | (i / 4 + 1) * 4) = ret; | ||
| 876 | ret = 0; | ||
| 877 | } | ||
| 878 | } | ||
| 879 | } | ||
| 880 | dp_aux_ch_ctl_trans_done(vgpu, data, offset, len + 2, | ||
| 881 | dpcd && dpcd->data_valid); | ||
| 882 | return 0; | ||
| 883 | } | ||
| 884 | |||
| 885 | /* i2c transaction starts */ | ||
| 886 | intel_gvt_i2c_handle_aux_ch_write(vgpu, port_index, offset, p_data); | ||
| 887 | |||
| 888 | if (data & DP_AUX_CH_CTL_INTERRUPT) | ||
| 889 | trigger_aux_channel_interrupt(vgpu, offset); | ||
| 890 | return 0; | ||
| 891 | } | ||
| 892 | |||
| 893 | static int vga_control_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 894 | void *p_data, unsigned int bytes) | ||
| 895 | { | ||
| 896 | bool vga_disable; | ||
| 897 | |||
| 898 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 899 | vga_disable = vgpu_vreg(vgpu, offset) & VGA_DISP_DISABLE; | ||
| 900 | |||
| 901 | gvt_dbg_core("vgpu%d: %s VGA mode\n", vgpu->id, | ||
| 902 | vga_disable ? "Disable" : "Enable"); | ||
| 903 | return 0; | ||
| 904 | } | ||
| 905 | |||
| 906 | static u32 read_virtual_sbi_register(struct intel_vgpu *vgpu, | ||
| 907 | unsigned int sbi_offset) | ||
| 908 | { | ||
| 909 | struct intel_vgpu_display *display = &vgpu->display; | ||
| 910 | int num = display->sbi.number; | ||
| 911 | int i; | ||
| 912 | |||
| 913 | for (i = 0; i < num; ++i) | ||
| 914 | if (display->sbi.registers[i].offset == sbi_offset) | ||
| 915 | break; | ||
| 916 | |||
| 917 | if (i == num) | ||
| 918 | return 0; | ||
| 919 | |||
| 920 | return display->sbi.registers[i].value; | ||
| 921 | } | ||
| 922 | |||
| 923 | static void write_virtual_sbi_register(struct intel_vgpu *vgpu, | ||
| 924 | unsigned int offset, u32 value) | ||
| 925 | { | ||
| 926 | struct intel_vgpu_display *display = &vgpu->display; | ||
| 927 | int num = display->sbi.number; | ||
| 928 | int i; | ||
| 929 | |||
| 930 | for (i = 0; i < num; ++i) { | ||
| 931 | if (display->sbi.registers[i].offset == offset) | ||
| 932 | break; | ||
| 933 | } | ||
| 934 | |||
| 935 | if (i == num) { | ||
| 936 | if (num == SBI_REG_MAX) { | ||
| 937 | gvt_err("vgpu%d: SBI caching meets maximum limits\n", | ||
| 938 | vgpu->id); | ||
| 939 | return; | ||
| 940 | } | ||
| 941 | display->sbi.number++; | ||
| 942 | } | ||
| 943 | |||
| 944 | display->sbi.registers[i].offset = offset; | ||
| 945 | display->sbi.registers[i].value = value; | ||
| 946 | } | ||
| 947 | |||
| 948 | static int sbi_data_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 949 | void *p_data, unsigned int bytes) | ||
| 950 | { | ||
| 951 | if (((vgpu_vreg(vgpu, SBI_CTL_STAT) & SBI_OPCODE_MASK) >> | ||
| 952 | SBI_OPCODE_SHIFT) == SBI_CMD_CRRD) { | ||
| 953 | unsigned int sbi_offset = (vgpu_vreg(vgpu, SBI_ADDR) & | ||
| 954 | SBI_ADDR_OFFSET_MASK) >> SBI_ADDR_OFFSET_SHIFT; | ||
| 955 | vgpu_vreg(vgpu, offset) = read_virtual_sbi_register(vgpu, | ||
| 956 | sbi_offset); | ||
| 957 | } | ||
| 958 | read_vreg(vgpu, offset, p_data, bytes); | ||
| 959 | return 0; | ||
| 960 | } | ||
| 961 | |||
| 962 | static bool sbi_ctl_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 963 | void *p_data, unsigned int bytes) | ||
| 964 | { | ||
| 965 | u32 data; | ||
| 966 | |||
| 967 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 968 | data = vgpu_vreg(vgpu, offset); | ||
| 969 | |||
| 970 | data &= ~(SBI_STAT_MASK << SBI_STAT_SHIFT); | ||
| 971 | data |= SBI_READY; | ||
| 972 | |||
| 973 | data &= ~(SBI_RESPONSE_MASK << SBI_RESPONSE_SHIFT); | ||
| 974 | data |= SBI_RESPONSE_SUCCESS; | ||
| 975 | |||
| 976 | vgpu_vreg(vgpu, offset) = data; | ||
| 977 | |||
| 978 | if (((vgpu_vreg(vgpu, SBI_CTL_STAT) & SBI_OPCODE_MASK) >> | ||
| 979 | SBI_OPCODE_SHIFT) == SBI_CMD_CRWR) { | ||
| 980 | unsigned int sbi_offset = (vgpu_vreg(vgpu, SBI_ADDR) & | ||
| 981 | SBI_ADDR_OFFSET_MASK) >> SBI_ADDR_OFFSET_SHIFT; | ||
| 982 | |||
| 983 | write_virtual_sbi_register(vgpu, sbi_offset, | ||
| 984 | vgpu_vreg(vgpu, SBI_DATA)); | ||
| 985 | } | ||
| 986 | return 0; | ||
| 987 | } | ||
| 988 | |||
| 989 | #define _vgtif_reg(x) \ | ||
| 990 | (VGT_PVINFO_PAGE + offsetof(struct vgt_if, x)) | ||
| 991 | |||
| 992 | static int pvinfo_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 993 | void *p_data, unsigned int bytes) | ||
| 994 | { | ||
| 995 | bool invalid_read = false; | ||
| 996 | |||
| 997 | read_vreg(vgpu, offset, p_data, bytes); | ||
| 998 | |||
| 999 | switch (offset) { | ||
| 1000 | case _vgtif_reg(magic) ... _vgtif_reg(vgt_id): | ||
| 1001 | if (offset + bytes > _vgtif_reg(vgt_id) + 4) | ||
| 1002 | invalid_read = true; | ||
| 1003 | break; | ||
| 1004 | case _vgtif_reg(avail_rs.mappable_gmadr.base) ... | ||
| 1005 | _vgtif_reg(avail_rs.fence_num): | ||
| 1006 | if (offset + bytes > | ||
| 1007 | _vgtif_reg(avail_rs.fence_num) + 4) | ||
| 1008 | invalid_read = true; | ||
| 1009 | break; | ||
| 1010 | case 0x78010: /* vgt_caps */ | ||
| 1011 | case 0x7881c: | ||
| 1012 | break; | ||
| 1013 | default: | ||
| 1014 | invalid_read = true; | ||
| 1015 | break; | ||
| 1016 | } | ||
| 1017 | if (invalid_read) | ||
| 1018 | gvt_err("invalid pvinfo read: [%x:%x] = %x\n", | ||
| 1019 | offset, bytes, *(u32 *)p_data); | ||
| 1020 | return 0; | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | static int handle_g2v_notification(struct intel_vgpu *vgpu, int notification) | ||
| 1024 | { | ||
| 1025 | int ret = 0; | ||
| 1026 | |||
| 1027 | switch (notification) { | ||
| 1028 | case VGT_G2V_PPGTT_L3_PAGE_TABLE_CREATE: | ||
| 1029 | ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu, 3); | ||
| 1030 | break; | ||
| 1031 | case VGT_G2V_PPGTT_L3_PAGE_TABLE_DESTROY: | ||
| 1032 | ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, 3); | ||
| 1033 | break; | ||
| 1034 | case VGT_G2V_PPGTT_L4_PAGE_TABLE_CREATE: | ||
| 1035 | ret = intel_vgpu_g2v_create_ppgtt_mm(vgpu, 4); | ||
| 1036 | break; | ||
| 1037 | case VGT_G2V_PPGTT_L4_PAGE_TABLE_DESTROY: | ||
| 1038 | ret = intel_vgpu_g2v_destroy_ppgtt_mm(vgpu, 4); | ||
| 1039 | break; | ||
| 1040 | case VGT_G2V_EXECLIST_CONTEXT_CREATE: | ||
| 1041 | case VGT_G2V_EXECLIST_CONTEXT_DESTROY: | ||
| 1042 | case 1: /* Remove this in guest driver. */ | ||
| 1043 | break; | ||
| 1044 | default: | ||
| 1045 | gvt_err("Invalid PV notification %d\n", notification); | ||
| 1046 | } | ||
| 1047 | return ret; | ||
| 1048 | } | ||
| 1049 | |||
| 1050 | static int send_display_ready_uevent(struct intel_vgpu *vgpu, int ready) | ||
| 1051 | { | ||
| 1052 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 1053 | struct kobject *kobj = &dev_priv->drm.primary->kdev->kobj; | ||
| 1054 | char *env[3] = {NULL, NULL, NULL}; | ||
| 1055 | char vmid_str[20]; | ||
| 1056 | char display_ready_str[20]; | ||
| 1057 | |||
| 1058 | snprintf(display_ready_str, 20, "GVT_DISPLAY_READY=%d\n", ready); | ||
| 1059 | env[0] = display_ready_str; | ||
| 1060 | |||
| 1061 | snprintf(vmid_str, 20, "VMID=%d", vgpu->id); | ||
| 1062 | env[1] = vmid_str; | ||
| 1063 | |||
| 1064 | return kobject_uevent_env(kobj, KOBJ_ADD, env); | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | static int pvinfo_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 1068 | void *p_data, unsigned int bytes) | ||
| 1069 | { | ||
| 1070 | u32 data; | ||
| 1071 | int ret; | ||
| 1072 | |||
| 1073 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 1074 | data = vgpu_vreg(vgpu, offset); | ||
| 1075 | |||
| 1076 | switch (offset) { | ||
| 1077 | case _vgtif_reg(display_ready): | ||
| 1078 | send_display_ready_uevent(vgpu, data ? 1 : 0); | ||
| 1079 | break; | ||
| 1080 | case _vgtif_reg(g2v_notify): | ||
| 1081 | ret = handle_g2v_notification(vgpu, data); | ||
| 1082 | break; | ||
| 1083 | /* add xhot and yhot to handled list to avoid error log */ | ||
| 1084 | case 0x78830: | ||
| 1085 | case 0x78834: | ||
| 1086 | case _vgtif_reg(pdp[0].lo): | ||
| 1087 | case _vgtif_reg(pdp[0].hi): | ||
| 1088 | case _vgtif_reg(pdp[1].lo): | ||
| 1089 | case _vgtif_reg(pdp[1].hi): | ||
| 1090 | case _vgtif_reg(pdp[2].lo): | ||
| 1091 | case _vgtif_reg(pdp[2].hi): | ||
| 1092 | case _vgtif_reg(pdp[3].lo): | ||
| 1093 | case _vgtif_reg(pdp[3].hi): | ||
| 1094 | case _vgtif_reg(execlist_context_descriptor_lo): | ||
| 1095 | case _vgtif_reg(execlist_context_descriptor_hi): | ||
| 1096 | break; | ||
| 1097 | default: | ||
| 1098 | gvt_err("invalid pvinfo write offset %x bytes %x data %x\n", | ||
| 1099 | offset, bytes, data); | ||
| 1100 | break; | ||
| 1101 | } | ||
| 1102 | return 0; | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | static int pf_write(struct intel_vgpu *vgpu, | ||
| 1106 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 1107 | { | ||
| 1108 | u32 val = *(u32 *)p_data; | ||
| 1109 | |||
| 1110 | if ((offset == _PS_1A_CTRL || offset == _PS_2A_CTRL || | ||
| 1111 | offset == _PS_1B_CTRL || offset == _PS_2B_CTRL || | ||
| 1112 | offset == _PS_1C_CTRL) && (val & PS_PLANE_SEL_MASK) != 0) { | ||
| 1113 | WARN_ONCE(true, "VM(%d): guest is trying to scaling a plane\n", | ||
| 1114 | vgpu->id); | ||
| 1115 | return 0; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | return intel_vgpu_default_mmio_write(vgpu, offset, p_data, bytes); | ||
| 1119 | } | ||
| 1120 | |||
| 1121 | static int power_well_ctl_mmio_write(struct intel_vgpu *vgpu, | ||
| 1122 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 1123 | { | ||
| 1124 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 1125 | |||
| 1126 | if (vgpu_vreg(vgpu, offset) & HSW_PWR_WELL_ENABLE_REQUEST) | ||
| 1127 | vgpu_vreg(vgpu, offset) |= HSW_PWR_WELL_STATE_ENABLED; | ||
| 1128 | else | ||
| 1129 | vgpu_vreg(vgpu, offset) &= ~HSW_PWR_WELL_STATE_ENABLED; | ||
| 1130 | return 0; | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | static int fpga_dbg_mmio_write(struct intel_vgpu *vgpu, | ||
| 1134 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 1135 | { | ||
| 1136 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 1137 | |||
| 1138 | if (vgpu_vreg(vgpu, offset) & FPGA_DBG_RM_NOCLAIM) | ||
| 1139 | vgpu_vreg(vgpu, offset) &= ~FPGA_DBG_RM_NOCLAIM; | ||
| 1140 | return 0; | ||
| 1141 | } | ||
| 1142 | |||
| 1143 | static int dma_ctrl_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 1144 | void *p_data, unsigned int bytes) | ||
| 1145 | { | ||
| 1146 | u32 mode = *(u32 *)p_data; | ||
| 1147 | |||
| 1148 | if (GFX_MODE_BIT_SET_IN_MASK(mode, START_DMA)) { | ||
| 1149 | WARN_ONCE(1, "VM(%d): iGVT-g doesn't supporte GuC\n", | ||
| 1150 | vgpu->id); | ||
| 1151 | return 0; | ||
| 1152 | } | ||
| 1153 | |||
| 1154 | return 0; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | static int gen9_trtte_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 1158 | void *p_data, unsigned int bytes) | ||
| 1159 | { | ||
| 1160 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 1161 | u32 trtte = *(u32 *)p_data; | ||
| 1162 | |||
| 1163 | if ((trtte & 1) && (trtte & (1 << 1)) == 0) { | ||
| 1164 | WARN(1, "VM(%d): Use physical address for TRTT!\n", | ||
| 1165 | vgpu->id); | ||
| 1166 | return -EINVAL; | ||
| 1167 | } | ||
| 1168 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 1169 | /* TRTTE is not per-context */ | ||
| 1170 | I915_WRITE(_MMIO(offset), vgpu_vreg(vgpu, offset)); | ||
| 1171 | |||
| 1172 | return 0; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | static int gen9_trtt_chicken_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 1176 | void *p_data, unsigned int bytes) | ||
| 1177 | { | ||
| 1178 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 1179 | u32 val = *(u32 *)p_data; | ||
| 1180 | |||
| 1181 | if (val & 1) { | ||
| 1182 | /* unblock hw logic */ | ||
| 1183 | I915_WRITE(_MMIO(offset), val); | ||
| 1184 | } | ||
| 1185 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 1186 | return 0; | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | static int dpll_status_read(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 1190 | void *p_data, unsigned int bytes) | ||
| 1191 | { | ||
| 1192 | u32 v = 0; | ||
| 1193 | |||
| 1194 | if (vgpu_vreg(vgpu, 0x46010) & (1 << 31)) | ||
| 1195 | v |= (1 << 0); | ||
| 1196 | |||
| 1197 | if (vgpu_vreg(vgpu, 0x46014) & (1 << 31)) | ||
| 1198 | v |= (1 << 8); | ||
| 1199 | |||
| 1200 | if (vgpu_vreg(vgpu, 0x46040) & (1 << 31)) | ||
| 1201 | v |= (1 << 16); | ||
| 1202 | |||
| 1203 | if (vgpu_vreg(vgpu, 0x46060) & (1 << 31)) | ||
| 1204 | v |= (1 << 24); | ||
| 1205 | |||
| 1206 | vgpu_vreg(vgpu, offset) = v; | ||
| 1207 | |||
| 1208 | return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes); | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | static int mailbox_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 1212 | void *p_data, unsigned int bytes) | ||
| 1213 | { | ||
| 1214 | u32 value = *(u32 *)p_data; | ||
| 1215 | u32 cmd = value & 0xff; | ||
| 1216 | u32 *data0 = &vgpu_vreg(vgpu, GEN6_PCODE_DATA); | ||
| 1217 | |||
| 1218 | switch (cmd) { | ||
| 1219 | case 0x6: | ||
| 1220 | /** | ||
| 1221 | * "Read memory latency" command on gen9. | ||
| 1222 | * Below memory latency values are read | ||
| 1223 | * from skylake platform. | ||
| 1224 | */ | ||
| 1225 | if (!*data0) | ||
| 1226 | *data0 = 0x1e1a1100; | ||
| 1227 | else | ||
| 1228 | *data0 = 0x61514b3d; | ||
| 1229 | break; | ||
| 1230 | case 0x5: | ||
| 1231 | *data0 |= 0x1; | ||
| 1232 | break; | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | gvt_dbg_core("VM(%d) write %x to mailbox, return data0 %x\n", | ||
| 1236 | vgpu->id, value, *data0); | ||
| 1237 | |||
| 1238 | value &= ~(1 << 31); | ||
| 1239 | return intel_vgpu_default_mmio_write(vgpu, offset, &value, bytes); | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static int skl_power_well_ctl_write(struct intel_vgpu *vgpu, | ||
| 1243 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 1244 | { | ||
| 1245 | u32 v = *(u32 *)p_data; | ||
| 1246 | |||
| 1247 | v &= (1 << 31) | (1 << 29) | (1 << 9) | | ||
| 1248 | (1 << 7) | (1 << 5) | (1 << 3) | (1 << 1); | ||
| 1249 | v |= (v >> 1); | ||
| 1250 | |||
| 1251 | return intel_vgpu_default_mmio_write(vgpu, offset, &v, bytes); | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | static int skl_misc_ctl_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 1255 | void *p_data, unsigned int bytes) | ||
| 1256 | { | ||
| 1257 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 1258 | i915_reg_t reg = {.reg = offset}; | ||
| 1259 | |||
| 1260 | switch (offset) { | ||
| 1261 | case 0x4ddc: | ||
| 1262 | vgpu_vreg(vgpu, offset) = 0x8000003c; | ||
| 1263 | break; | ||
| 1264 | case 0x42080: | ||
| 1265 | vgpu_vreg(vgpu, offset) = 0x8000; | ||
| 1266 | break; | ||
| 1267 | default: | ||
| 1268 | return -EINVAL; | ||
| 1269 | } | ||
| 1270 | |||
| 1271 | /** | ||
| 1272 | * TODO: need detect stepping info after gvt contain such information | ||
| 1273 | * 0x4ddc enabled after C0, 0x42080 enabled after E0. | ||
| 1274 | */ | ||
| 1275 | I915_WRITE(reg, vgpu_vreg(vgpu, offset)); | ||
| 1276 | return 0; | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | static int skl_lcpll_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 1280 | void *p_data, unsigned int bytes) | ||
| 1281 | { | ||
| 1282 | u32 v = *(u32 *)p_data; | ||
| 1283 | |||
| 1284 | /* other bits are MBZ. */ | ||
| 1285 | v &= (1 << 31) | (1 << 30); | ||
| 1286 | v & (1 << 31) ? (v |= (1 << 30)) : (v &= ~(1 << 30)); | ||
| 1287 | |||
| 1288 | vgpu_vreg(vgpu, offset) = v; | ||
| 1289 | |||
| 1290 | return 0; | ||
| 1291 | } | ||
| 1292 | |||
| 1293 | static int ring_timestamp_mmio_read(struct intel_vgpu *vgpu, | ||
| 1294 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 1295 | { | ||
| 1296 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 1297 | |||
| 1298 | vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset)); | ||
| 1299 | return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes); | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 1303 | void *p_data, unsigned int bytes) | ||
| 1304 | { | ||
| 1305 | int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset); | ||
| 1306 | struct intel_vgpu_execlist *execlist; | ||
| 1307 | u32 data = *(u32 *)p_data; | ||
| 1308 | int ret; | ||
| 1309 | |||
| 1310 | if (WARN_ON(ring_id < 0 || ring_id > I915_NUM_ENGINES - 1)) | ||
| 1311 | return -EINVAL; | ||
| 1312 | |||
| 1313 | execlist = &vgpu->execlist[ring_id]; | ||
| 1314 | |||
| 1315 | execlist->elsp_dwords.data[execlist->elsp_dwords.index] = data; | ||
| 1316 | if (execlist->elsp_dwords.index == 3) | ||
| 1317 | ret = intel_vgpu_submit_execlist(vgpu, ring_id); | ||
| 1318 | |||
| 1319 | ++execlist->elsp_dwords.index; | ||
| 1320 | execlist->elsp_dwords.index &= 0x3; | ||
| 1321 | return 0; | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 1325 | void *p_data, unsigned int bytes) | ||
| 1326 | { | ||
| 1327 | u32 data = *(u32 *)p_data; | ||
| 1328 | int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset); | ||
| 1329 | bool enable_execlist; | ||
| 1330 | |||
| 1331 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 1332 | if ((data & _MASKED_BIT_ENABLE(GFX_RUN_LIST_ENABLE)) | ||
| 1333 | || (data & _MASKED_BIT_DISABLE(GFX_RUN_LIST_ENABLE))) { | ||
| 1334 | enable_execlist = !!(data & GFX_RUN_LIST_ENABLE); | ||
| 1335 | |||
| 1336 | gvt_dbg_core("EXECLIST %s on ring %d\n", | ||
| 1337 | (enable_execlist ? "enabling" : "disabling"), | ||
| 1338 | ring_id); | ||
| 1339 | |||
| 1340 | if (enable_execlist) | ||
| 1341 | intel_vgpu_start_schedule(vgpu); | ||
| 1342 | } | ||
| 1343 | return 0; | ||
| 1344 | } | ||
| 1345 | |||
| 1346 | static int gvt_reg_tlb_control_handler(struct intel_vgpu *vgpu, | ||
| 1347 | unsigned int offset, void *p_data, unsigned int bytes) | ||
| 1348 | { | ||
| 1349 | int rc = 0; | ||
| 1350 | unsigned int id = 0; | ||
| 1351 | |||
| 1352 | switch (offset) { | ||
| 1353 | case 0x4260: | ||
| 1354 | id = RCS; | ||
| 1355 | break; | ||
| 1356 | case 0x4264: | ||
| 1357 | id = VCS; | ||
| 1358 | break; | ||
| 1359 | case 0x4268: | ||
| 1360 | id = VCS2; | ||
| 1361 | break; | ||
| 1362 | case 0x426c: | ||
| 1363 | id = BCS; | ||
| 1364 | break; | ||
| 1365 | case 0x4270: | ||
| 1366 | id = VECS; | ||
| 1367 | break; | ||
| 1368 | default: | ||
| 1369 | rc = -EINVAL; | ||
| 1370 | break; | ||
| 1371 | } | ||
| 1372 | set_bit(id, (void *)vgpu->tlb_handle_pending); | ||
| 1373 | |||
| 1374 | return rc; | ||
| 1375 | } | ||
| 1376 | |||
| 1377 | #define MMIO_F(reg, s, f, am, rm, d, r, w) do { \ | ||
| 1378 | ret = new_mmio_info(gvt, INTEL_GVT_MMIO_OFFSET(reg), \ | ||
| 1379 | f, s, am, rm, d, r, w); \ | ||
| 1380 | if (ret) \ | ||
| 1381 | return ret; \ | ||
| 1382 | } while (0) | ||
| 1383 | |||
| 1384 | #define MMIO_D(reg, d) \ | ||
| 1385 | MMIO_F(reg, 4, 0, 0, 0, d, NULL, NULL) | ||
| 1386 | |||
| 1387 | #define MMIO_DH(reg, d, r, w) \ | ||
| 1388 | MMIO_F(reg, 4, 0, 0, 0, d, r, w) | ||
| 1389 | |||
| 1390 | #define MMIO_DFH(reg, d, f, r, w) \ | ||
| 1391 | MMIO_F(reg, 4, f, 0, 0, d, r, w) | ||
| 1392 | |||
| 1393 | #define MMIO_GM(reg, d, r, w) \ | ||
| 1394 | MMIO_F(reg, 4, F_GMADR, 0xFFFFF000, 0, d, r, w) | ||
| 1395 | |||
| 1396 | #define MMIO_RO(reg, d, f, rm, r, w) \ | ||
| 1397 | MMIO_F(reg, 4, F_RO | f, 0, rm, d, r, w) | ||
| 1398 | |||
| 1399 | #define MMIO_RING_F(prefix, s, f, am, rm, d, r, w) do { \ | ||
| 1400 | MMIO_F(prefix(RENDER_RING_BASE), s, f, am, rm, d, r, w); \ | ||
| 1401 | MMIO_F(prefix(BLT_RING_BASE), s, f, am, rm, d, r, w); \ | ||
| 1402 | MMIO_F(prefix(GEN6_BSD_RING_BASE), s, f, am, rm, d, r, w); \ | ||
| 1403 | MMIO_F(prefix(VEBOX_RING_BASE), s, f, am, rm, d, r, w); \ | ||
| 1404 | } while (0) | ||
| 1405 | |||
| 1406 | #define MMIO_RING_D(prefix, d) \ | ||
| 1407 | MMIO_RING_F(prefix, 4, 0, 0, 0, d, NULL, NULL) | ||
| 1408 | |||
| 1409 | #define MMIO_RING_DFH(prefix, d, f, r, w) \ | ||
| 1410 | MMIO_RING_F(prefix, 4, f, 0, 0, d, r, w) | ||
| 1411 | |||
| 1412 | #define MMIO_RING_GM(prefix, d, r, w) \ | ||
| 1413 | MMIO_RING_F(prefix, 4, F_GMADR, 0xFFFF0000, 0, d, r, w) | ||
| 1414 | |||
| 1415 | #define MMIO_RING_RO(prefix, d, f, rm, r, w) \ | ||
| 1416 | MMIO_RING_F(prefix, 4, F_RO | f, 0, rm, d, r, w) | ||
| 1417 | |||
| 1418 | static int init_generic_mmio_info(struct intel_gvt *gvt) | ||
| 1419 | { | ||
| 1420 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
| 1421 | int ret; | ||
| 1422 | |||
| 1423 | MMIO_RING_DFH(RING_IMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler); | ||
| 1424 | |||
| 1425 | MMIO_DFH(SDEIMR, D_ALL, 0, NULL, intel_vgpu_reg_imr_handler); | ||
| 1426 | MMIO_DFH(SDEIER, D_ALL, 0, NULL, intel_vgpu_reg_ier_handler); | ||
| 1427 | MMIO_DFH(SDEIIR, D_ALL, 0, NULL, intel_vgpu_reg_iir_handler); | ||
| 1428 | MMIO_D(SDEISR, D_ALL); | ||
| 1429 | |||
| 1430 | MMIO_RING_D(RING_HWSTAM, D_ALL); | ||
| 1431 | |||
| 1432 | MMIO_GM(RENDER_HWS_PGA_GEN7, D_ALL, NULL, NULL); | ||
| 1433 | MMIO_GM(BSD_HWS_PGA_GEN7, D_ALL, NULL, NULL); | ||
| 1434 | MMIO_GM(BLT_HWS_PGA_GEN7, D_ALL, NULL, NULL); | ||
| 1435 | MMIO_GM(VEBOX_HWS_PGA_GEN7, D_ALL, NULL, NULL); | ||
| 1436 | |||
| 1437 | #define RING_REG(base) (base + 0x28) | ||
| 1438 | MMIO_RING_D(RING_REG, D_ALL); | ||
| 1439 | #undef RING_REG | ||
| 1440 | |||
| 1441 | #define RING_REG(base) (base + 0x134) | ||
| 1442 | MMIO_RING_D(RING_REG, D_ALL); | ||
| 1443 | #undef RING_REG | ||
| 1444 | |||
| 1445 | MMIO_GM(0x2148, D_ALL, NULL, NULL); | ||
| 1446 | MMIO_GM(CCID, D_ALL, NULL, NULL); | ||
| 1447 | MMIO_GM(0x12198, D_ALL, NULL, NULL); | ||
| 1448 | MMIO_D(GEN7_CXT_SIZE, D_ALL); | ||
| 1449 | |||
| 1450 | MMIO_RING_D(RING_TAIL, D_ALL); | ||
| 1451 | MMIO_RING_D(RING_HEAD, D_ALL); | ||
| 1452 | MMIO_RING_D(RING_CTL, D_ALL); | ||
| 1453 | MMIO_RING_D(RING_ACTHD, D_ALL); | ||
| 1454 | MMIO_RING_GM(RING_START, D_ALL, NULL, NULL); | ||
| 1455 | |||
| 1456 | /* RING MODE */ | ||
| 1457 | #define RING_REG(base) (base + 0x29c) | ||
| 1458 | MMIO_RING_DFH(RING_REG, D_ALL, F_MODE_MASK, NULL, ring_mode_mmio_write); | ||
| 1459 | #undef RING_REG | ||
| 1460 | |||
| 1461 | MMIO_RING_DFH(RING_MI_MODE, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1462 | MMIO_RING_DFH(RING_INSTPM, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1463 | MMIO_RING_DFH(RING_TIMESTAMP, D_ALL, F_CMD_ACCESS, | ||
| 1464 | ring_timestamp_mmio_read, NULL); | ||
| 1465 | MMIO_RING_DFH(RING_TIMESTAMP_UDW, D_ALL, F_CMD_ACCESS, | ||
| 1466 | ring_timestamp_mmio_read, NULL); | ||
| 1467 | |||
| 1468 | MMIO_DFH(GEN7_GT_MODE, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1469 | MMIO_DFH(CACHE_MODE_0_GEN7, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1470 | MMIO_DFH(CACHE_MODE_1, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1471 | |||
| 1472 | MMIO_DFH(0x20dc, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1473 | MMIO_DFH(_3D_CHICKEN3, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1474 | MMIO_DFH(0x2088, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1475 | MMIO_DFH(0x20e4, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1476 | MMIO_DFH(0x2470, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1477 | MMIO_D(GAM_ECOCHK, D_ALL); | ||
| 1478 | MMIO_DFH(GEN7_COMMON_SLICE_CHICKEN1, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1479 | MMIO_DFH(COMMON_SLICE_CHICKEN2, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1480 | MMIO_D(0x9030, D_ALL); | ||
| 1481 | MMIO_D(0x20a0, D_ALL); | ||
| 1482 | MMIO_D(0x2420, D_ALL); | ||
| 1483 | MMIO_D(0x2430, D_ALL); | ||
| 1484 | MMIO_D(0x2434, D_ALL); | ||
| 1485 | MMIO_D(0x2438, D_ALL); | ||
| 1486 | MMIO_D(0x243c, D_ALL); | ||
| 1487 | MMIO_DFH(0x7018, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1488 | MMIO_DFH(0xe184, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1489 | MMIO_DFH(0xe100, D_ALL, F_MODE_MASK, NULL, NULL); | ||
| 1490 | |||
| 1491 | /* display */ | ||
| 1492 | MMIO_F(0x60220, 0x20, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1493 | MMIO_D(0x602a0, D_ALL); | ||
| 1494 | |||
| 1495 | MMIO_D(0x65050, D_ALL); | ||
| 1496 | MMIO_D(0x650b4, D_ALL); | ||
| 1497 | |||
| 1498 | MMIO_D(0xc4040, D_ALL); | ||
| 1499 | MMIO_D(DERRMR, D_ALL); | ||
| 1500 | |||
| 1501 | MMIO_D(PIPEDSL(PIPE_A), D_ALL); | ||
| 1502 | MMIO_D(PIPEDSL(PIPE_B), D_ALL); | ||
| 1503 | MMIO_D(PIPEDSL(PIPE_C), D_ALL); | ||
| 1504 | MMIO_D(PIPEDSL(_PIPE_EDP), D_ALL); | ||
| 1505 | |||
| 1506 | MMIO_DH(PIPECONF(PIPE_A), D_ALL, NULL, pipeconf_mmio_write); | ||
| 1507 | MMIO_DH(PIPECONF(PIPE_B), D_ALL, NULL, pipeconf_mmio_write); | ||
| 1508 | MMIO_DH(PIPECONF(PIPE_C), D_ALL, NULL, pipeconf_mmio_write); | ||
| 1509 | MMIO_DH(PIPECONF(_PIPE_EDP), D_ALL, NULL, pipeconf_mmio_write); | ||
| 1510 | |||
| 1511 | MMIO_D(PIPESTAT(PIPE_A), D_ALL); | ||
| 1512 | MMIO_D(PIPESTAT(PIPE_B), D_ALL); | ||
| 1513 | MMIO_D(PIPESTAT(PIPE_C), D_ALL); | ||
| 1514 | MMIO_D(PIPESTAT(_PIPE_EDP), D_ALL); | ||
| 1515 | |||
| 1516 | MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_A), D_ALL); | ||
| 1517 | MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_B), D_ALL); | ||
| 1518 | MMIO_D(PIPE_FLIPCOUNT_G4X(PIPE_C), D_ALL); | ||
| 1519 | MMIO_D(PIPE_FLIPCOUNT_G4X(_PIPE_EDP), D_ALL); | ||
| 1520 | |||
| 1521 | MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_A), D_ALL); | ||
| 1522 | MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_B), D_ALL); | ||
| 1523 | MMIO_D(PIPE_FRMCOUNT_G4X(PIPE_C), D_ALL); | ||
| 1524 | MMIO_D(PIPE_FRMCOUNT_G4X(_PIPE_EDP), D_ALL); | ||
| 1525 | |||
| 1526 | MMIO_D(CURCNTR(PIPE_A), D_ALL); | ||
| 1527 | MMIO_D(CURCNTR(PIPE_B), D_ALL); | ||
| 1528 | MMIO_D(CURCNTR(PIPE_C), D_ALL); | ||
| 1529 | |||
| 1530 | MMIO_D(CURPOS(PIPE_A), D_ALL); | ||
| 1531 | MMIO_D(CURPOS(PIPE_B), D_ALL); | ||
| 1532 | MMIO_D(CURPOS(PIPE_C), D_ALL); | ||
| 1533 | |||
| 1534 | MMIO_D(CURBASE(PIPE_A), D_ALL); | ||
| 1535 | MMIO_D(CURBASE(PIPE_B), D_ALL); | ||
| 1536 | MMIO_D(CURBASE(PIPE_C), D_ALL); | ||
| 1537 | |||
| 1538 | MMIO_D(0x700ac, D_ALL); | ||
| 1539 | MMIO_D(0x710ac, D_ALL); | ||
| 1540 | MMIO_D(0x720ac, D_ALL); | ||
| 1541 | |||
| 1542 | MMIO_D(0x70090, D_ALL); | ||
| 1543 | MMIO_D(0x70094, D_ALL); | ||
| 1544 | MMIO_D(0x70098, D_ALL); | ||
| 1545 | MMIO_D(0x7009c, D_ALL); | ||
| 1546 | |||
| 1547 | MMIO_D(DSPCNTR(PIPE_A), D_ALL); | ||
| 1548 | MMIO_D(DSPADDR(PIPE_A), D_ALL); | ||
| 1549 | MMIO_D(DSPSTRIDE(PIPE_A), D_ALL); | ||
| 1550 | MMIO_D(DSPPOS(PIPE_A), D_ALL); | ||
| 1551 | MMIO_D(DSPSIZE(PIPE_A), D_ALL); | ||
| 1552 | MMIO_DH(DSPSURF(PIPE_A), D_ALL, NULL, pri_surf_mmio_write); | ||
| 1553 | MMIO_D(DSPOFFSET(PIPE_A), D_ALL); | ||
| 1554 | MMIO_D(DSPSURFLIVE(PIPE_A), D_ALL); | ||
| 1555 | |||
| 1556 | MMIO_D(DSPCNTR(PIPE_B), D_ALL); | ||
| 1557 | MMIO_D(DSPADDR(PIPE_B), D_ALL); | ||
| 1558 | MMIO_D(DSPSTRIDE(PIPE_B), D_ALL); | ||
| 1559 | MMIO_D(DSPPOS(PIPE_B), D_ALL); | ||
| 1560 | MMIO_D(DSPSIZE(PIPE_B), D_ALL); | ||
| 1561 | MMIO_DH(DSPSURF(PIPE_B), D_ALL, NULL, pri_surf_mmio_write); | ||
| 1562 | MMIO_D(DSPOFFSET(PIPE_B), D_ALL); | ||
| 1563 | MMIO_D(DSPSURFLIVE(PIPE_B), D_ALL); | ||
| 1564 | |||
| 1565 | MMIO_D(DSPCNTR(PIPE_C), D_ALL); | ||
| 1566 | MMIO_D(DSPADDR(PIPE_C), D_ALL); | ||
| 1567 | MMIO_D(DSPSTRIDE(PIPE_C), D_ALL); | ||
| 1568 | MMIO_D(DSPPOS(PIPE_C), D_ALL); | ||
| 1569 | MMIO_D(DSPSIZE(PIPE_C), D_ALL); | ||
| 1570 | MMIO_DH(DSPSURF(PIPE_C), D_ALL, NULL, pri_surf_mmio_write); | ||
| 1571 | MMIO_D(DSPOFFSET(PIPE_C), D_ALL); | ||
| 1572 | MMIO_D(DSPSURFLIVE(PIPE_C), D_ALL); | ||
| 1573 | |||
| 1574 | MMIO_D(SPRCTL(PIPE_A), D_ALL); | ||
| 1575 | MMIO_D(SPRLINOFF(PIPE_A), D_ALL); | ||
| 1576 | MMIO_D(SPRSTRIDE(PIPE_A), D_ALL); | ||
| 1577 | MMIO_D(SPRPOS(PIPE_A), D_ALL); | ||
| 1578 | MMIO_D(SPRSIZE(PIPE_A), D_ALL); | ||
| 1579 | MMIO_D(SPRKEYVAL(PIPE_A), D_ALL); | ||
| 1580 | MMIO_D(SPRKEYMSK(PIPE_A), D_ALL); | ||
| 1581 | MMIO_DH(SPRSURF(PIPE_A), D_ALL, NULL, spr_surf_mmio_write); | ||
| 1582 | MMIO_D(SPRKEYMAX(PIPE_A), D_ALL); | ||
| 1583 | MMIO_D(SPROFFSET(PIPE_A), D_ALL); | ||
| 1584 | MMIO_D(SPRSCALE(PIPE_A), D_ALL); | ||
| 1585 | MMIO_D(SPRSURFLIVE(PIPE_A), D_ALL); | ||
| 1586 | |||
| 1587 | MMIO_D(SPRCTL(PIPE_B), D_ALL); | ||
| 1588 | MMIO_D(SPRLINOFF(PIPE_B), D_ALL); | ||
| 1589 | MMIO_D(SPRSTRIDE(PIPE_B), D_ALL); | ||
| 1590 | MMIO_D(SPRPOS(PIPE_B), D_ALL); | ||
| 1591 | MMIO_D(SPRSIZE(PIPE_B), D_ALL); | ||
| 1592 | MMIO_D(SPRKEYVAL(PIPE_B), D_ALL); | ||
| 1593 | MMIO_D(SPRKEYMSK(PIPE_B), D_ALL); | ||
| 1594 | MMIO_DH(SPRSURF(PIPE_B), D_ALL, NULL, spr_surf_mmio_write); | ||
| 1595 | MMIO_D(SPRKEYMAX(PIPE_B), D_ALL); | ||
| 1596 | MMIO_D(SPROFFSET(PIPE_B), D_ALL); | ||
| 1597 | MMIO_D(SPRSCALE(PIPE_B), D_ALL); | ||
| 1598 | MMIO_D(SPRSURFLIVE(PIPE_B), D_ALL); | ||
| 1599 | |||
| 1600 | MMIO_D(SPRCTL(PIPE_C), D_ALL); | ||
| 1601 | MMIO_D(SPRLINOFF(PIPE_C), D_ALL); | ||
| 1602 | MMIO_D(SPRSTRIDE(PIPE_C), D_ALL); | ||
| 1603 | MMIO_D(SPRPOS(PIPE_C), D_ALL); | ||
| 1604 | MMIO_D(SPRSIZE(PIPE_C), D_ALL); | ||
| 1605 | MMIO_D(SPRKEYVAL(PIPE_C), D_ALL); | ||
| 1606 | MMIO_D(SPRKEYMSK(PIPE_C), D_ALL); | ||
| 1607 | MMIO_DH(SPRSURF(PIPE_C), D_ALL, NULL, spr_surf_mmio_write); | ||
| 1608 | MMIO_D(SPRKEYMAX(PIPE_C), D_ALL); | ||
| 1609 | MMIO_D(SPROFFSET(PIPE_C), D_ALL); | ||
| 1610 | MMIO_D(SPRSCALE(PIPE_C), D_ALL); | ||
| 1611 | MMIO_D(SPRSURFLIVE(PIPE_C), D_ALL); | ||
| 1612 | |||
| 1613 | MMIO_F(LGC_PALETTE(PIPE_A, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1614 | MMIO_F(LGC_PALETTE(PIPE_B, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1615 | MMIO_F(LGC_PALETTE(PIPE_C, 0), 4 * 256, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1616 | |||
| 1617 | MMIO_D(HTOTAL(TRANSCODER_A), D_ALL); | ||
| 1618 | MMIO_D(HBLANK(TRANSCODER_A), D_ALL); | ||
| 1619 | MMIO_D(HSYNC(TRANSCODER_A), D_ALL); | ||
| 1620 | MMIO_D(VTOTAL(TRANSCODER_A), D_ALL); | ||
| 1621 | MMIO_D(VBLANK(TRANSCODER_A), D_ALL); | ||
| 1622 | MMIO_D(VSYNC(TRANSCODER_A), D_ALL); | ||
| 1623 | MMIO_D(BCLRPAT(TRANSCODER_A), D_ALL); | ||
| 1624 | MMIO_D(VSYNCSHIFT(TRANSCODER_A), D_ALL); | ||
| 1625 | MMIO_D(PIPESRC(TRANSCODER_A), D_ALL); | ||
| 1626 | |||
| 1627 | MMIO_D(HTOTAL(TRANSCODER_B), D_ALL); | ||
| 1628 | MMIO_D(HBLANK(TRANSCODER_B), D_ALL); | ||
| 1629 | MMIO_D(HSYNC(TRANSCODER_B), D_ALL); | ||
| 1630 | MMIO_D(VTOTAL(TRANSCODER_B), D_ALL); | ||
| 1631 | MMIO_D(VBLANK(TRANSCODER_B), D_ALL); | ||
| 1632 | MMIO_D(VSYNC(TRANSCODER_B), D_ALL); | ||
| 1633 | MMIO_D(BCLRPAT(TRANSCODER_B), D_ALL); | ||
| 1634 | MMIO_D(VSYNCSHIFT(TRANSCODER_B), D_ALL); | ||
| 1635 | MMIO_D(PIPESRC(TRANSCODER_B), D_ALL); | ||
| 1636 | |||
| 1637 | MMIO_D(HTOTAL(TRANSCODER_C), D_ALL); | ||
| 1638 | MMIO_D(HBLANK(TRANSCODER_C), D_ALL); | ||
| 1639 | MMIO_D(HSYNC(TRANSCODER_C), D_ALL); | ||
| 1640 | MMIO_D(VTOTAL(TRANSCODER_C), D_ALL); | ||
| 1641 | MMIO_D(VBLANK(TRANSCODER_C), D_ALL); | ||
| 1642 | MMIO_D(VSYNC(TRANSCODER_C), D_ALL); | ||
| 1643 | MMIO_D(BCLRPAT(TRANSCODER_C), D_ALL); | ||
| 1644 | MMIO_D(VSYNCSHIFT(TRANSCODER_C), D_ALL); | ||
| 1645 | MMIO_D(PIPESRC(TRANSCODER_C), D_ALL); | ||
| 1646 | |||
| 1647 | MMIO_D(HTOTAL(TRANSCODER_EDP), D_ALL); | ||
| 1648 | MMIO_D(HBLANK(TRANSCODER_EDP), D_ALL); | ||
| 1649 | MMIO_D(HSYNC(TRANSCODER_EDP), D_ALL); | ||
| 1650 | MMIO_D(VTOTAL(TRANSCODER_EDP), D_ALL); | ||
| 1651 | MMIO_D(VBLANK(TRANSCODER_EDP), D_ALL); | ||
| 1652 | MMIO_D(VSYNC(TRANSCODER_EDP), D_ALL); | ||
| 1653 | MMIO_D(BCLRPAT(TRANSCODER_EDP), D_ALL); | ||
| 1654 | MMIO_D(VSYNCSHIFT(TRANSCODER_EDP), D_ALL); | ||
| 1655 | |||
| 1656 | MMIO_D(PIPE_DATA_M1(TRANSCODER_A), D_ALL); | ||
| 1657 | MMIO_D(PIPE_DATA_N1(TRANSCODER_A), D_ALL); | ||
| 1658 | MMIO_D(PIPE_DATA_M2(TRANSCODER_A), D_ALL); | ||
| 1659 | MMIO_D(PIPE_DATA_N2(TRANSCODER_A), D_ALL); | ||
| 1660 | MMIO_D(PIPE_LINK_M1(TRANSCODER_A), D_ALL); | ||
| 1661 | MMIO_D(PIPE_LINK_N1(TRANSCODER_A), D_ALL); | ||
| 1662 | MMIO_D(PIPE_LINK_M2(TRANSCODER_A), D_ALL); | ||
| 1663 | MMIO_D(PIPE_LINK_N2(TRANSCODER_A), D_ALL); | ||
| 1664 | |||
| 1665 | MMIO_D(PIPE_DATA_M1(TRANSCODER_B), D_ALL); | ||
| 1666 | MMIO_D(PIPE_DATA_N1(TRANSCODER_B), D_ALL); | ||
| 1667 | MMIO_D(PIPE_DATA_M2(TRANSCODER_B), D_ALL); | ||
| 1668 | MMIO_D(PIPE_DATA_N2(TRANSCODER_B), D_ALL); | ||
| 1669 | MMIO_D(PIPE_LINK_M1(TRANSCODER_B), D_ALL); | ||
| 1670 | MMIO_D(PIPE_LINK_N1(TRANSCODER_B), D_ALL); | ||
| 1671 | MMIO_D(PIPE_LINK_M2(TRANSCODER_B), D_ALL); | ||
| 1672 | MMIO_D(PIPE_LINK_N2(TRANSCODER_B), D_ALL); | ||
| 1673 | |||
| 1674 | MMIO_D(PIPE_DATA_M1(TRANSCODER_C), D_ALL); | ||
| 1675 | MMIO_D(PIPE_DATA_N1(TRANSCODER_C), D_ALL); | ||
| 1676 | MMIO_D(PIPE_DATA_M2(TRANSCODER_C), D_ALL); | ||
| 1677 | MMIO_D(PIPE_DATA_N2(TRANSCODER_C), D_ALL); | ||
| 1678 | MMIO_D(PIPE_LINK_M1(TRANSCODER_C), D_ALL); | ||
| 1679 | MMIO_D(PIPE_LINK_N1(TRANSCODER_C), D_ALL); | ||
| 1680 | MMIO_D(PIPE_LINK_M2(TRANSCODER_C), D_ALL); | ||
| 1681 | MMIO_D(PIPE_LINK_N2(TRANSCODER_C), D_ALL); | ||
| 1682 | |||
| 1683 | MMIO_D(PIPE_DATA_M1(TRANSCODER_EDP), D_ALL); | ||
| 1684 | MMIO_D(PIPE_DATA_N1(TRANSCODER_EDP), D_ALL); | ||
| 1685 | MMIO_D(PIPE_DATA_M2(TRANSCODER_EDP), D_ALL); | ||
| 1686 | MMIO_D(PIPE_DATA_N2(TRANSCODER_EDP), D_ALL); | ||
| 1687 | MMIO_D(PIPE_LINK_M1(TRANSCODER_EDP), D_ALL); | ||
| 1688 | MMIO_D(PIPE_LINK_N1(TRANSCODER_EDP), D_ALL); | ||
| 1689 | MMIO_D(PIPE_LINK_M2(TRANSCODER_EDP), D_ALL); | ||
| 1690 | MMIO_D(PIPE_LINK_N2(TRANSCODER_EDP), D_ALL); | ||
| 1691 | |||
| 1692 | MMIO_D(PF_CTL(PIPE_A), D_ALL); | ||
| 1693 | MMIO_D(PF_WIN_SZ(PIPE_A), D_ALL); | ||
| 1694 | MMIO_D(PF_WIN_POS(PIPE_A), D_ALL); | ||
| 1695 | MMIO_D(PF_VSCALE(PIPE_A), D_ALL); | ||
| 1696 | MMIO_D(PF_HSCALE(PIPE_A), D_ALL); | ||
| 1697 | |||
| 1698 | MMIO_D(PF_CTL(PIPE_B), D_ALL); | ||
| 1699 | MMIO_D(PF_WIN_SZ(PIPE_B), D_ALL); | ||
| 1700 | MMIO_D(PF_WIN_POS(PIPE_B), D_ALL); | ||
| 1701 | MMIO_D(PF_VSCALE(PIPE_B), D_ALL); | ||
| 1702 | MMIO_D(PF_HSCALE(PIPE_B), D_ALL); | ||
| 1703 | |||
| 1704 | MMIO_D(PF_CTL(PIPE_C), D_ALL); | ||
| 1705 | MMIO_D(PF_WIN_SZ(PIPE_C), D_ALL); | ||
| 1706 | MMIO_D(PF_WIN_POS(PIPE_C), D_ALL); | ||
| 1707 | MMIO_D(PF_VSCALE(PIPE_C), D_ALL); | ||
| 1708 | MMIO_D(PF_HSCALE(PIPE_C), D_ALL); | ||
| 1709 | |||
| 1710 | MMIO_D(WM0_PIPEA_ILK, D_ALL); | ||
| 1711 | MMIO_D(WM0_PIPEB_ILK, D_ALL); | ||
| 1712 | MMIO_D(WM0_PIPEC_IVB, D_ALL); | ||
| 1713 | MMIO_D(WM1_LP_ILK, D_ALL); | ||
| 1714 | MMIO_D(WM2_LP_ILK, D_ALL); | ||
| 1715 | MMIO_D(WM3_LP_ILK, D_ALL); | ||
| 1716 | MMIO_D(WM1S_LP_ILK, D_ALL); | ||
| 1717 | MMIO_D(WM2S_LP_IVB, D_ALL); | ||
| 1718 | MMIO_D(WM3S_LP_IVB, D_ALL); | ||
| 1719 | |||
| 1720 | MMIO_D(BLC_PWM_CPU_CTL2, D_ALL); | ||
| 1721 | MMIO_D(BLC_PWM_CPU_CTL, D_ALL); | ||
| 1722 | MMIO_D(BLC_PWM_PCH_CTL1, D_ALL); | ||
| 1723 | MMIO_D(BLC_PWM_PCH_CTL2, D_ALL); | ||
| 1724 | |||
| 1725 | MMIO_D(0x48268, D_ALL); | ||
| 1726 | |||
| 1727 | MMIO_F(PCH_GMBUS0, 4 * 4, 0, 0, 0, D_ALL, gmbus_mmio_read, | ||
| 1728 | gmbus_mmio_write); | ||
| 1729 | MMIO_F(PCH_GPIOA, 6 * 4, F_UNALIGN, 0, 0, D_ALL, NULL, NULL); | ||
| 1730 | MMIO_F(0xe4f00, 0x28, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1731 | |||
| 1732 | MMIO_F(_PCH_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, | ||
| 1733 | dp_aux_ch_ctl_mmio_write); | ||
| 1734 | MMIO_F(_PCH_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, | ||
| 1735 | dp_aux_ch_ctl_mmio_write); | ||
| 1736 | MMIO_F(_PCH_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_PRE_SKL, NULL, | ||
| 1737 | dp_aux_ch_ctl_mmio_write); | ||
| 1738 | |||
| 1739 | MMIO_RO(PCH_ADPA, D_ALL, 0, ADPA_CRT_HOTPLUG_MONITOR_MASK, NULL, pch_adpa_mmio_write); | ||
| 1740 | |||
| 1741 | MMIO_DH(_PCH_TRANSACONF, D_ALL, NULL, transconf_mmio_write); | ||
| 1742 | MMIO_DH(_PCH_TRANSBCONF, D_ALL, NULL, transconf_mmio_write); | ||
| 1743 | |||
| 1744 | MMIO_DH(FDI_RX_IIR(PIPE_A), D_ALL, NULL, fdi_rx_iir_mmio_write); | ||
| 1745 | MMIO_DH(FDI_RX_IIR(PIPE_B), D_ALL, NULL, fdi_rx_iir_mmio_write); | ||
| 1746 | MMIO_DH(FDI_RX_IIR(PIPE_C), D_ALL, NULL, fdi_rx_iir_mmio_write); | ||
| 1747 | MMIO_DH(FDI_RX_IMR(PIPE_A), D_ALL, NULL, update_fdi_rx_iir_status); | ||
| 1748 | MMIO_DH(FDI_RX_IMR(PIPE_B), D_ALL, NULL, update_fdi_rx_iir_status); | ||
| 1749 | MMIO_DH(FDI_RX_IMR(PIPE_C), D_ALL, NULL, update_fdi_rx_iir_status); | ||
| 1750 | MMIO_DH(FDI_RX_CTL(PIPE_A), D_ALL, NULL, update_fdi_rx_iir_status); | ||
| 1751 | MMIO_DH(FDI_RX_CTL(PIPE_B), D_ALL, NULL, update_fdi_rx_iir_status); | ||
| 1752 | MMIO_DH(FDI_RX_CTL(PIPE_C), D_ALL, NULL, update_fdi_rx_iir_status); | ||
| 1753 | |||
| 1754 | MMIO_D(_PCH_TRANS_HTOTAL_A, D_ALL); | ||
| 1755 | MMIO_D(_PCH_TRANS_HBLANK_A, D_ALL); | ||
| 1756 | MMIO_D(_PCH_TRANS_HSYNC_A, D_ALL); | ||
| 1757 | MMIO_D(_PCH_TRANS_VTOTAL_A, D_ALL); | ||
| 1758 | MMIO_D(_PCH_TRANS_VBLANK_A, D_ALL); | ||
| 1759 | MMIO_D(_PCH_TRANS_VSYNC_A, D_ALL); | ||
| 1760 | MMIO_D(_PCH_TRANS_VSYNCSHIFT_A, D_ALL); | ||
| 1761 | |||
| 1762 | MMIO_D(_PCH_TRANS_HTOTAL_B, D_ALL); | ||
| 1763 | MMIO_D(_PCH_TRANS_HBLANK_B, D_ALL); | ||
| 1764 | MMIO_D(_PCH_TRANS_HSYNC_B, D_ALL); | ||
| 1765 | MMIO_D(_PCH_TRANS_VTOTAL_B, D_ALL); | ||
| 1766 | MMIO_D(_PCH_TRANS_VBLANK_B, D_ALL); | ||
| 1767 | MMIO_D(_PCH_TRANS_VSYNC_B, D_ALL); | ||
| 1768 | MMIO_D(_PCH_TRANS_VSYNCSHIFT_B, D_ALL); | ||
| 1769 | |||
| 1770 | MMIO_D(_PCH_TRANSA_DATA_M1, D_ALL); | ||
| 1771 | MMIO_D(_PCH_TRANSA_DATA_N1, D_ALL); | ||
| 1772 | MMIO_D(_PCH_TRANSA_DATA_M2, D_ALL); | ||
| 1773 | MMIO_D(_PCH_TRANSA_DATA_N2, D_ALL); | ||
| 1774 | MMIO_D(_PCH_TRANSA_LINK_M1, D_ALL); | ||
| 1775 | MMIO_D(_PCH_TRANSA_LINK_N1, D_ALL); | ||
| 1776 | MMIO_D(_PCH_TRANSA_LINK_M2, D_ALL); | ||
| 1777 | MMIO_D(_PCH_TRANSA_LINK_N2, D_ALL); | ||
| 1778 | |||
| 1779 | MMIO_D(TRANS_DP_CTL(PIPE_A), D_ALL); | ||
| 1780 | MMIO_D(TRANS_DP_CTL(PIPE_B), D_ALL); | ||
| 1781 | MMIO_D(TRANS_DP_CTL(PIPE_C), D_ALL); | ||
| 1782 | |||
| 1783 | MMIO_D(TVIDEO_DIP_CTL(PIPE_A), D_ALL); | ||
| 1784 | MMIO_D(TVIDEO_DIP_DATA(PIPE_A), D_ALL); | ||
| 1785 | MMIO_D(TVIDEO_DIP_GCP(PIPE_A), D_ALL); | ||
| 1786 | |||
| 1787 | MMIO_D(TVIDEO_DIP_CTL(PIPE_B), D_ALL); | ||
| 1788 | MMIO_D(TVIDEO_DIP_DATA(PIPE_B), D_ALL); | ||
| 1789 | MMIO_D(TVIDEO_DIP_GCP(PIPE_B), D_ALL); | ||
| 1790 | |||
| 1791 | MMIO_D(TVIDEO_DIP_CTL(PIPE_C), D_ALL); | ||
| 1792 | MMIO_D(TVIDEO_DIP_DATA(PIPE_C), D_ALL); | ||
| 1793 | MMIO_D(TVIDEO_DIP_GCP(PIPE_C), D_ALL); | ||
| 1794 | |||
| 1795 | MMIO_D(_FDI_RXA_MISC, D_ALL); | ||
| 1796 | MMIO_D(_FDI_RXB_MISC, D_ALL); | ||
| 1797 | MMIO_D(_FDI_RXA_TUSIZE1, D_ALL); | ||
| 1798 | MMIO_D(_FDI_RXA_TUSIZE2, D_ALL); | ||
| 1799 | MMIO_D(_FDI_RXB_TUSIZE1, D_ALL); | ||
| 1800 | MMIO_D(_FDI_RXB_TUSIZE2, D_ALL); | ||
| 1801 | |||
| 1802 | MMIO_DH(PCH_PP_CONTROL, D_ALL, NULL, pch_pp_control_mmio_write); | ||
| 1803 | MMIO_D(PCH_PP_DIVISOR, D_ALL); | ||
| 1804 | MMIO_D(PCH_PP_STATUS, D_ALL); | ||
| 1805 | MMIO_D(PCH_LVDS, D_ALL); | ||
| 1806 | MMIO_D(_PCH_DPLL_A, D_ALL); | ||
| 1807 | MMIO_D(_PCH_DPLL_B, D_ALL); | ||
| 1808 | MMIO_D(_PCH_FPA0, D_ALL); | ||
| 1809 | MMIO_D(_PCH_FPA1, D_ALL); | ||
| 1810 | MMIO_D(_PCH_FPB0, D_ALL); | ||
| 1811 | MMIO_D(_PCH_FPB1, D_ALL); | ||
| 1812 | MMIO_D(PCH_DREF_CONTROL, D_ALL); | ||
| 1813 | MMIO_D(PCH_RAWCLK_FREQ, D_ALL); | ||
| 1814 | MMIO_D(PCH_DPLL_SEL, D_ALL); | ||
| 1815 | |||
| 1816 | MMIO_D(0x61208, D_ALL); | ||
| 1817 | MMIO_D(0x6120c, D_ALL); | ||
| 1818 | MMIO_D(PCH_PP_ON_DELAYS, D_ALL); | ||
| 1819 | MMIO_D(PCH_PP_OFF_DELAYS, D_ALL); | ||
| 1820 | |||
| 1821 | MMIO_DH(0xe651c, D_ALL, dpy_reg_mmio_read, NULL); | ||
| 1822 | MMIO_DH(0xe661c, D_ALL, dpy_reg_mmio_read, NULL); | ||
| 1823 | MMIO_DH(0xe671c, D_ALL, dpy_reg_mmio_read, NULL); | ||
| 1824 | MMIO_DH(0xe681c, D_ALL, dpy_reg_mmio_read, NULL); | ||
| 1825 | MMIO_DH(0xe6c04, D_ALL, dpy_reg_mmio_read_2, NULL); | ||
| 1826 | MMIO_DH(0xe6e1c, D_ALL, dpy_reg_mmio_read_3, NULL); | ||
| 1827 | |||
| 1828 | MMIO_RO(PCH_PORT_HOTPLUG, D_ALL, 0, | ||
| 1829 | PORTA_HOTPLUG_STATUS_MASK | ||
| 1830 | | PORTB_HOTPLUG_STATUS_MASK | ||
| 1831 | | PORTC_HOTPLUG_STATUS_MASK | ||
| 1832 | | PORTD_HOTPLUG_STATUS_MASK, | ||
| 1833 | NULL, NULL); | ||
| 1834 | |||
| 1835 | MMIO_DH(LCPLL_CTL, D_ALL, NULL, lcpll_ctl_mmio_write); | ||
| 1836 | MMIO_D(FUSE_STRAP, D_ALL); | ||
| 1837 | MMIO_D(DIGITAL_PORT_HOTPLUG_CNTRL, D_ALL); | ||
| 1838 | |||
| 1839 | MMIO_D(DISP_ARB_CTL, D_ALL); | ||
| 1840 | MMIO_D(DISP_ARB_CTL2, D_ALL); | ||
| 1841 | |||
| 1842 | MMIO_D(ILK_DISPLAY_CHICKEN1, D_ALL); | ||
| 1843 | MMIO_D(ILK_DISPLAY_CHICKEN2, D_ALL); | ||
| 1844 | MMIO_D(ILK_DSPCLK_GATE_D, D_ALL); | ||
| 1845 | |||
| 1846 | MMIO_D(SOUTH_CHICKEN1, D_ALL); | ||
| 1847 | MMIO_DH(SOUTH_CHICKEN2, D_ALL, NULL, south_chicken2_mmio_write); | ||
| 1848 | MMIO_D(_TRANSA_CHICKEN1, D_ALL); | ||
| 1849 | MMIO_D(_TRANSB_CHICKEN1, D_ALL); | ||
| 1850 | MMIO_D(SOUTH_DSPCLK_GATE_D, D_ALL); | ||
| 1851 | MMIO_D(_TRANSA_CHICKEN2, D_ALL); | ||
| 1852 | MMIO_D(_TRANSB_CHICKEN2, D_ALL); | ||
| 1853 | |||
| 1854 | MMIO_D(ILK_DPFC_CB_BASE, D_ALL); | ||
| 1855 | MMIO_D(ILK_DPFC_CONTROL, D_ALL); | ||
| 1856 | MMIO_D(ILK_DPFC_RECOMP_CTL, D_ALL); | ||
| 1857 | MMIO_D(ILK_DPFC_STATUS, D_ALL); | ||
| 1858 | MMIO_D(ILK_DPFC_FENCE_YOFF, D_ALL); | ||
| 1859 | MMIO_D(ILK_DPFC_CHICKEN, D_ALL); | ||
| 1860 | MMIO_D(ILK_FBC_RT_BASE, D_ALL); | ||
| 1861 | |||
| 1862 | MMIO_D(IPS_CTL, D_ALL); | ||
| 1863 | |||
| 1864 | MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_A), D_ALL); | ||
| 1865 | MMIO_D(PIPE_CSC_COEFF_BY(PIPE_A), D_ALL); | ||
| 1866 | MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_A), D_ALL); | ||
| 1867 | MMIO_D(PIPE_CSC_COEFF_BU(PIPE_A), D_ALL); | ||
| 1868 | MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_A), D_ALL); | ||
| 1869 | MMIO_D(PIPE_CSC_COEFF_BV(PIPE_A), D_ALL); | ||
| 1870 | MMIO_D(PIPE_CSC_MODE(PIPE_A), D_ALL); | ||
| 1871 | MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_A), D_ALL); | ||
| 1872 | MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_A), D_ALL); | ||
| 1873 | MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_A), D_ALL); | ||
| 1874 | MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_A), D_ALL); | ||
| 1875 | MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_A), D_ALL); | ||
| 1876 | MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_A), D_ALL); | ||
| 1877 | |||
| 1878 | MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_B), D_ALL); | ||
| 1879 | MMIO_D(PIPE_CSC_COEFF_BY(PIPE_B), D_ALL); | ||
| 1880 | MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_B), D_ALL); | ||
| 1881 | MMIO_D(PIPE_CSC_COEFF_BU(PIPE_B), D_ALL); | ||
| 1882 | MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_B), D_ALL); | ||
| 1883 | MMIO_D(PIPE_CSC_COEFF_BV(PIPE_B), D_ALL); | ||
| 1884 | MMIO_D(PIPE_CSC_MODE(PIPE_B), D_ALL); | ||
| 1885 | MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_B), D_ALL); | ||
| 1886 | MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_B), D_ALL); | ||
| 1887 | MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_B), D_ALL); | ||
| 1888 | MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_B), D_ALL); | ||
| 1889 | MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_B), D_ALL); | ||
| 1890 | MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_B), D_ALL); | ||
| 1891 | |||
| 1892 | MMIO_D(PIPE_CSC_COEFF_RY_GY(PIPE_C), D_ALL); | ||
| 1893 | MMIO_D(PIPE_CSC_COEFF_BY(PIPE_C), D_ALL); | ||
| 1894 | MMIO_D(PIPE_CSC_COEFF_RU_GU(PIPE_C), D_ALL); | ||
| 1895 | MMIO_D(PIPE_CSC_COEFF_BU(PIPE_C), D_ALL); | ||
| 1896 | MMIO_D(PIPE_CSC_COEFF_RV_GV(PIPE_C), D_ALL); | ||
| 1897 | MMIO_D(PIPE_CSC_COEFF_BV(PIPE_C), D_ALL); | ||
| 1898 | MMIO_D(PIPE_CSC_MODE(PIPE_C), D_ALL); | ||
| 1899 | MMIO_D(PIPE_CSC_PREOFF_HI(PIPE_C), D_ALL); | ||
| 1900 | MMIO_D(PIPE_CSC_PREOFF_ME(PIPE_C), D_ALL); | ||
| 1901 | MMIO_D(PIPE_CSC_PREOFF_LO(PIPE_C), D_ALL); | ||
| 1902 | MMIO_D(PIPE_CSC_POSTOFF_HI(PIPE_C), D_ALL); | ||
| 1903 | MMIO_D(PIPE_CSC_POSTOFF_ME(PIPE_C), D_ALL); | ||
| 1904 | MMIO_D(PIPE_CSC_POSTOFF_LO(PIPE_C), D_ALL); | ||
| 1905 | |||
| 1906 | MMIO_D(PREC_PAL_INDEX(PIPE_A), D_ALL); | ||
| 1907 | MMIO_D(PREC_PAL_DATA(PIPE_A), D_ALL); | ||
| 1908 | MMIO_F(PREC_PAL_GC_MAX(PIPE_A, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1909 | |||
| 1910 | MMIO_D(PREC_PAL_INDEX(PIPE_B), D_ALL); | ||
| 1911 | MMIO_D(PREC_PAL_DATA(PIPE_B), D_ALL); | ||
| 1912 | MMIO_F(PREC_PAL_GC_MAX(PIPE_B, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1913 | |||
| 1914 | MMIO_D(PREC_PAL_INDEX(PIPE_C), D_ALL); | ||
| 1915 | MMIO_D(PREC_PAL_DATA(PIPE_C), D_ALL); | ||
| 1916 | MMIO_F(PREC_PAL_GC_MAX(PIPE_C, 0), 4 * 3, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1917 | |||
| 1918 | MMIO_D(0x60110, D_ALL); | ||
| 1919 | MMIO_D(0x61110, D_ALL); | ||
| 1920 | MMIO_F(0x70400, 0x40, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1921 | MMIO_F(0x71400, 0x40, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1922 | MMIO_F(0x72400, 0x40, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1923 | MMIO_F(0x70440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); | ||
| 1924 | MMIO_F(0x71440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); | ||
| 1925 | MMIO_F(0x72440, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); | ||
| 1926 | MMIO_F(0x7044c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); | ||
| 1927 | MMIO_F(0x7144c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); | ||
| 1928 | MMIO_F(0x7244c, 0xc, 0, 0, 0, D_PRE_SKL, NULL, NULL); | ||
| 1929 | |||
| 1930 | MMIO_D(PIPE_WM_LINETIME(PIPE_A), D_ALL); | ||
| 1931 | MMIO_D(PIPE_WM_LINETIME(PIPE_B), D_ALL); | ||
| 1932 | MMIO_D(PIPE_WM_LINETIME(PIPE_C), D_ALL); | ||
| 1933 | MMIO_D(SPLL_CTL, D_ALL); | ||
| 1934 | MMIO_D(_WRPLL_CTL1, D_ALL); | ||
| 1935 | MMIO_D(_WRPLL_CTL2, D_ALL); | ||
| 1936 | MMIO_D(PORT_CLK_SEL(PORT_A), D_ALL); | ||
| 1937 | MMIO_D(PORT_CLK_SEL(PORT_B), D_ALL); | ||
| 1938 | MMIO_D(PORT_CLK_SEL(PORT_C), D_ALL); | ||
| 1939 | MMIO_D(PORT_CLK_SEL(PORT_D), D_ALL); | ||
| 1940 | MMIO_D(PORT_CLK_SEL(PORT_E), D_ALL); | ||
| 1941 | MMIO_D(TRANS_CLK_SEL(TRANSCODER_A), D_ALL); | ||
| 1942 | MMIO_D(TRANS_CLK_SEL(TRANSCODER_B), D_ALL); | ||
| 1943 | MMIO_D(TRANS_CLK_SEL(TRANSCODER_C), D_ALL); | ||
| 1944 | |||
| 1945 | MMIO_D(HSW_NDE_RSTWRN_OPT, D_ALL); | ||
| 1946 | MMIO_D(0x46508, D_ALL); | ||
| 1947 | |||
| 1948 | MMIO_D(0x49080, D_ALL); | ||
| 1949 | MMIO_D(0x49180, D_ALL); | ||
| 1950 | MMIO_D(0x49280, D_ALL); | ||
| 1951 | |||
| 1952 | MMIO_F(0x49090, 0x14, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1953 | MMIO_F(0x49190, 0x14, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1954 | MMIO_F(0x49290, 0x14, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1955 | |||
| 1956 | MMIO_D(GAMMA_MODE(PIPE_A), D_ALL); | ||
| 1957 | MMIO_D(GAMMA_MODE(PIPE_B), D_ALL); | ||
| 1958 | MMIO_D(GAMMA_MODE(PIPE_C), D_ALL); | ||
| 1959 | |||
| 1960 | MMIO_D(PIPE_MULT(PIPE_A), D_ALL); | ||
| 1961 | MMIO_D(PIPE_MULT(PIPE_B), D_ALL); | ||
| 1962 | MMIO_D(PIPE_MULT(PIPE_C), D_ALL); | ||
| 1963 | |||
| 1964 | MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_A), D_ALL); | ||
| 1965 | MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_B), D_ALL); | ||
| 1966 | MMIO_D(HSW_TVIDEO_DIP_CTL(TRANSCODER_C), D_ALL); | ||
| 1967 | |||
| 1968 | MMIO_DH(SFUSE_STRAP, D_ALL, NULL, NULL); | ||
| 1969 | MMIO_D(SBI_ADDR, D_ALL); | ||
| 1970 | MMIO_DH(SBI_DATA, D_ALL, sbi_data_mmio_read, NULL); | ||
| 1971 | MMIO_DH(SBI_CTL_STAT, D_ALL, NULL, sbi_ctl_mmio_write); | ||
| 1972 | MMIO_D(PIXCLK_GATE, D_ALL); | ||
| 1973 | |||
| 1974 | MMIO_F(_DPA_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_ALL, NULL, | ||
| 1975 | dp_aux_ch_ctl_mmio_write); | ||
| 1976 | |||
| 1977 | MMIO_DH(DDI_BUF_CTL(PORT_A), D_ALL, NULL, ddi_buf_ctl_mmio_write); | ||
| 1978 | MMIO_DH(DDI_BUF_CTL(PORT_B), D_ALL, NULL, ddi_buf_ctl_mmio_write); | ||
| 1979 | MMIO_DH(DDI_BUF_CTL(PORT_C), D_ALL, NULL, ddi_buf_ctl_mmio_write); | ||
| 1980 | MMIO_DH(DDI_BUF_CTL(PORT_D), D_ALL, NULL, ddi_buf_ctl_mmio_write); | ||
| 1981 | MMIO_DH(DDI_BUF_CTL(PORT_E), D_ALL, NULL, ddi_buf_ctl_mmio_write); | ||
| 1982 | |||
| 1983 | MMIO_DH(DP_TP_CTL(PORT_A), D_ALL, NULL, dp_tp_ctl_mmio_write); | ||
| 1984 | MMIO_DH(DP_TP_CTL(PORT_B), D_ALL, NULL, dp_tp_ctl_mmio_write); | ||
| 1985 | MMIO_DH(DP_TP_CTL(PORT_C), D_ALL, NULL, dp_tp_ctl_mmio_write); | ||
| 1986 | MMIO_DH(DP_TP_CTL(PORT_D), D_ALL, NULL, dp_tp_ctl_mmio_write); | ||
| 1987 | MMIO_DH(DP_TP_CTL(PORT_E), D_ALL, NULL, dp_tp_ctl_mmio_write); | ||
| 1988 | |||
| 1989 | MMIO_DH(DP_TP_STATUS(PORT_A), D_ALL, NULL, dp_tp_status_mmio_write); | ||
| 1990 | MMIO_DH(DP_TP_STATUS(PORT_B), D_ALL, NULL, dp_tp_status_mmio_write); | ||
| 1991 | MMIO_DH(DP_TP_STATUS(PORT_C), D_ALL, NULL, dp_tp_status_mmio_write); | ||
| 1992 | MMIO_DH(DP_TP_STATUS(PORT_D), D_ALL, NULL, dp_tp_status_mmio_write); | ||
| 1993 | MMIO_DH(DP_TP_STATUS(PORT_E), D_ALL, NULL, NULL); | ||
| 1994 | |||
| 1995 | MMIO_F(_DDI_BUF_TRANS_A, 0x50, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1996 | MMIO_F(0x64e60, 0x50, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1997 | MMIO_F(0x64eC0, 0x50, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1998 | MMIO_F(0x64f20, 0x50, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 1999 | MMIO_F(0x64f80, 0x50, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2000 | |||
| 2001 | MMIO_D(HSW_AUD_CFG(PIPE_A), D_ALL); | ||
| 2002 | MMIO_D(HSW_AUD_PIN_ELD_CP_VLD, D_ALL); | ||
| 2003 | |||
| 2004 | MMIO_DH(_TRANS_DDI_FUNC_CTL_A, D_ALL, NULL, NULL); | ||
| 2005 | MMIO_DH(_TRANS_DDI_FUNC_CTL_B, D_ALL, NULL, NULL); | ||
| 2006 | MMIO_DH(_TRANS_DDI_FUNC_CTL_C, D_ALL, NULL, NULL); | ||
| 2007 | MMIO_DH(_TRANS_DDI_FUNC_CTL_EDP, D_ALL, NULL, NULL); | ||
| 2008 | |||
| 2009 | MMIO_D(_TRANSA_MSA_MISC, D_ALL); | ||
| 2010 | MMIO_D(_TRANSB_MSA_MISC, D_ALL); | ||
| 2011 | MMIO_D(_TRANSC_MSA_MISC, D_ALL); | ||
| 2012 | MMIO_D(_TRANS_EDP_MSA_MISC, D_ALL); | ||
| 2013 | |||
| 2014 | MMIO_DH(FORCEWAKE, D_ALL, NULL, NULL); | ||
| 2015 | MMIO_D(FORCEWAKE_ACK, D_ALL); | ||
| 2016 | MMIO_D(GEN6_GT_CORE_STATUS, D_ALL); | ||
| 2017 | MMIO_D(GEN6_GT_THREAD_STATUS_REG, D_ALL); | ||
| 2018 | MMIO_D(GTFIFODBG, D_ALL); | ||
| 2019 | MMIO_D(GTFIFOCTL, D_ALL); | ||
| 2020 | MMIO_DH(FORCEWAKE_MT, D_PRE_SKL, NULL, mul_force_wake_write); | ||
| 2021 | MMIO_DH(FORCEWAKE_ACK_HSW, D_HSW | D_BDW, NULL, NULL); | ||
| 2022 | MMIO_D(ECOBUS, D_ALL); | ||
| 2023 | MMIO_DH(GEN6_RC_CONTROL, D_ALL, NULL, NULL); | ||
| 2024 | MMIO_DH(GEN6_RC_STATE, D_ALL, NULL, NULL); | ||
| 2025 | MMIO_D(GEN6_RPNSWREQ, D_ALL); | ||
| 2026 | MMIO_D(GEN6_RC_VIDEO_FREQ, D_ALL); | ||
| 2027 | MMIO_D(GEN6_RP_DOWN_TIMEOUT, D_ALL); | ||
| 2028 | MMIO_D(GEN6_RP_INTERRUPT_LIMITS, D_ALL); | ||
| 2029 | MMIO_D(GEN6_RPSTAT1, D_ALL); | ||
| 2030 | MMIO_D(GEN6_RP_CONTROL, D_ALL); | ||
| 2031 | MMIO_D(GEN6_RP_UP_THRESHOLD, D_ALL); | ||
| 2032 | MMIO_D(GEN6_RP_DOWN_THRESHOLD, D_ALL); | ||
| 2033 | MMIO_D(GEN6_RP_CUR_UP_EI, D_ALL); | ||
| 2034 | MMIO_D(GEN6_RP_CUR_UP, D_ALL); | ||
| 2035 | MMIO_D(GEN6_RP_PREV_UP, D_ALL); | ||
| 2036 | MMIO_D(GEN6_RP_CUR_DOWN_EI, D_ALL); | ||
| 2037 | MMIO_D(GEN6_RP_CUR_DOWN, D_ALL); | ||
| 2038 | MMIO_D(GEN6_RP_PREV_DOWN, D_ALL); | ||
| 2039 | MMIO_D(GEN6_RP_UP_EI, D_ALL); | ||
| 2040 | MMIO_D(GEN6_RP_DOWN_EI, D_ALL); | ||
| 2041 | MMIO_D(GEN6_RP_IDLE_HYSTERSIS, D_ALL); | ||
| 2042 | MMIO_D(GEN6_RC1_WAKE_RATE_LIMIT, D_ALL); | ||
| 2043 | MMIO_D(GEN6_RC6_WAKE_RATE_LIMIT, D_ALL); | ||
| 2044 | MMIO_D(GEN6_RC6pp_WAKE_RATE_LIMIT, D_ALL); | ||
| 2045 | MMIO_D(GEN6_RC_EVALUATION_INTERVAL, D_ALL); | ||
| 2046 | MMIO_D(GEN6_RC_IDLE_HYSTERSIS, D_ALL); | ||
| 2047 | MMIO_D(GEN6_RC_SLEEP, D_ALL); | ||
| 2048 | MMIO_D(GEN6_RC1e_THRESHOLD, D_ALL); | ||
| 2049 | MMIO_D(GEN6_RC6_THRESHOLD, D_ALL); | ||
| 2050 | MMIO_D(GEN6_RC6p_THRESHOLD, D_ALL); | ||
| 2051 | MMIO_D(GEN6_RC6pp_THRESHOLD, D_ALL); | ||
| 2052 | MMIO_D(GEN6_PMINTRMSK, D_ALL); | ||
| 2053 | MMIO_DH(HSW_PWR_WELL_BIOS, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); | ||
| 2054 | MMIO_DH(HSW_PWR_WELL_DRIVER, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); | ||
| 2055 | MMIO_DH(HSW_PWR_WELL_KVMR, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); | ||
| 2056 | MMIO_DH(HSW_PWR_WELL_DEBUG, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); | ||
| 2057 | MMIO_DH(HSW_PWR_WELL_CTL5, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); | ||
| 2058 | MMIO_DH(HSW_PWR_WELL_CTL6, D_HSW | D_BDW, NULL, power_well_ctl_mmio_write); | ||
| 2059 | |||
| 2060 | MMIO_D(RSTDBYCTL, D_ALL); | ||
| 2061 | |||
| 2062 | MMIO_DH(GEN6_GDRST, D_ALL, NULL, gdrst_mmio_write); | ||
| 2063 | MMIO_F(FENCE_REG_GEN6_LO(0), 0x80, 0, 0, 0, D_ALL, fence_mmio_read, fence_mmio_write); | ||
| 2064 | MMIO_F(VGT_PVINFO_PAGE, VGT_PVINFO_SIZE, F_UNALIGN, 0, 0, D_ALL, pvinfo_mmio_read, pvinfo_mmio_write); | ||
| 2065 | MMIO_DH(CPU_VGACNTRL, D_ALL, NULL, vga_control_mmio_write); | ||
| 2066 | |||
| 2067 | MMIO_F(MCHBAR_MIRROR_BASE_SNB, 0x40000, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2068 | |||
| 2069 | MMIO_D(TILECTL, D_ALL); | ||
| 2070 | |||
| 2071 | MMIO_D(GEN6_UCGCTL1, D_ALL); | ||
| 2072 | MMIO_D(GEN6_UCGCTL2, D_ALL); | ||
| 2073 | |||
| 2074 | MMIO_F(0x4f000, 0x90, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2075 | |||
| 2076 | MMIO_D(GEN6_PCODE_MAILBOX, D_PRE_SKL); | ||
| 2077 | MMIO_D(GEN6_PCODE_DATA, D_ALL); | ||
| 2078 | MMIO_D(0x13812c, D_ALL); | ||
| 2079 | MMIO_DH(GEN7_ERR_INT, D_ALL, NULL, NULL); | ||
| 2080 | MMIO_D(HSW_EDRAM_CAP, D_ALL); | ||
| 2081 | MMIO_D(HSW_IDICR, D_ALL); | ||
| 2082 | MMIO_DH(GFX_FLSH_CNTL_GEN6, D_ALL, NULL, NULL); | ||
| 2083 | |||
| 2084 | MMIO_D(0x3c, D_ALL); | ||
| 2085 | MMIO_D(0x860, D_ALL); | ||
| 2086 | MMIO_D(ECOSKPD, D_ALL); | ||
| 2087 | MMIO_D(0x121d0, D_ALL); | ||
| 2088 | MMIO_D(GEN6_BLITTER_ECOSKPD, D_ALL); | ||
| 2089 | MMIO_D(0x41d0, D_ALL); | ||
| 2090 | MMIO_D(GAC_ECO_BITS, D_ALL); | ||
| 2091 | MMIO_D(0x6200, D_ALL); | ||
| 2092 | MMIO_D(0x6204, D_ALL); | ||
| 2093 | MMIO_D(0x6208, D_ALL); | ||
| 2094 | MMIO_D(0x7118, D_ALL); | ||
| 2095 | MMIO_D(0x7180, D_ALL); | ||
| 2096 | MMIO_D(0x7408, D_ALL); | ||
| 2097 | MMIO_D(0x7c00, D_ALL); | ||
| 2098 | MMIO_D(GEN6_MBCTL, D_ALL); | ||
| 2099 | MMIO_D(0x911c, D_ALL); | ||
| 2100 | MMIO_D(0x9120, D_ALL); | ||
| 2101 | |||
| 2102 | MMIO_D(GAB_CTL, D_ALL); | ||
| 2103 | MMIO_D(0x48800, D_ALL); | ||
| 2104 | MMIO_D(0xce044, D_ALL); | ||
| 2105 | MMIO_D(0xe6500, D_ALL); | ||
| 2106 | MMIO_D(0xe6504, D_ALL); | ||
| 2107 | MMIO_D(0xe6600, D_ALL); | ||
| 2108 | MMIO_D(0xe6604, D_ALL); | ||
| 2109 | MMIO_D(0xe6700, D_ALL); | ||
| 2110 | MMIO_D(0xe6704, D_ALL); | ||
| 2111 | MMIO_D(0xe6800, D_ALL); | ||
| 2112 | MMIO_D(0xe6804, D_ALL); | ||
| 2113 | MMIO_D(PCH_GMBUS4, D_ALL); | ||
| 2114 | MMIO_D(PCH_GMBUS5, D_ALL); | ||
| 2115 | |||
| 2116 | MMIO_D(0x902c, D_ALL); | ||
| 2117 | MMIO_D(0xec008, D_ALL); | ||
| 2118 | MMIO_D(0xec00c, D_ALL); | ||
| 2119 | MMIO_D(0xec008 + 0x18, D_ALL); | ||
| 2120 | MMIO_D(0xec00c + 0x18, D_ALL); | ||
| 2121 | MMIO_D(0xec008 + 0x18 * 2, D_ALL); | ||
| 2122 | MMIO_D(0xec00c + 0x18 * 2, D_ALL); | ||
| 2123 | MMIO_D(0xec008 + 0x18 * 3, D_ALL); | ||
| 2124 | MMIO_D(0xec00c + 0x18 * 3, D_ALL); | ||
| 2125 | MMIO_D(0xec408, D_ALL); | ||
| 2126 | MMIO_D(0xec40c, D_ALL); | ||
| 2127 | MMIO_D(0xec408 + 0x18, D_ALL); | ||
| 2128 | MMIO_D(0xec40c + 0x18, D_ALL); | ||
| 2129 | MMIO_D(0xec408 + 0x18 * 2, D_ALL); | ||
| 2130 | MMIO_D(0xec40c + 0x18 * 2, D_ALL); | ||
| 2131 | MMIO_D(0xec408 + 0x18 * 3, D_ALL); | ||
| 2132 | MMIO_D(0xec40c + 0x18 * 3, D_ALL); | ||
| 2133 | MMIO_D(0xfc810, D_ALL); | ||
| 2134 | MMIO_D(0xfc81c, D_ALL); | ||
| 2135 | MMIO_D(0xfc828, D_ALL); | ||
| 2136 | MMIO_D(0xfc834, D_ALL); | ||
| 2137 | MMIO_D(0xfcc00, D_ALL); | ||
| 2138 | MMIO_D(0xfcc0c, D_ALL); | ||
| 2139 | MMIO_D(0xfcc18, D_ALL); | ||
| 2140 | MMIO_D(0xfcc24, D_ALL); | ||
| 2141 | MMIO_D(0xfd000, D_ALL); | ||
| 2142 | MMIO_D(0xfd00c, D_ALL); | ||
| 2143 | MMIO_D(0xfd018, D_ALL); | ||
| 2144 | MMIO_D(0xfd024, D_ALL); | ||
| 2145 | MMIO_D(0xfd034, D_ALL); | ||
| 2146 | |||
| 2147 | MMIO_DH(FPGA_DBG, D_ALL, NULL, fpga_dbg_mmio_write); | ||
| 2148 | MMIO_D(0x2054, D_ALL); | ||
| 2149 | MMIO_D(0x12054, D_ALL); | ||
| 2150 | MMIO_D(0x22054, D_ALL); | ||
| 2151 | MMIO_D(0x1a054, D_ALL); | ||
| 2152 | |||
| 2153 | MMIO_D(0x44070, D_ALL); | ||
| 2154 | |||
| 2155 | MMIO_D(0x215c, D_HSW_PLUS); | ||
| 2156 | MMIO_DFH(0x2178, D_ALL, F_CMD_ACCESS, NULL, NULL); | ||
| 2157 | MMIO_DFH(0x217c, D_ALL, F_CMD_ACCESS, NULL, NULL); | ||
| 2158 | MMIO_DFH(0x12178, D_ALL, F_CMD_ACCESS, NULL, NULL); | ||
| 2159 | MMIO_DFH(0x1217c, D_ALL, F_CMD_ACCESS, NULL, NULL); | ||
| 2160 | |||
| 2161 | MMIO_F(0x2290, 8, 0, 0, 0, D_HSW_PLUS, NULL, NULL); | ||
| 2162 | MMIO_D(OACONTROL, D_HSW); | ||
| 2163 | MMIO_D(0x2b00, D_BDW_PLUS); | ||
| 2164 | MMIO_D(0x2360, D_BDW_PLUS); | ||
| 2165 | MMIO_F(0x5200, 32, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2166 | MMIO_F(0x5240, 32, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2167 | MMIO_F(0x5280, 16, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2168 | |||
| 2169 | MMIO_DFH(0x1c17c, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); | ||
| 2170 | MMIO_DFH(0x1c178, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); | ||
| 2171 | MMIO_D(BCS_SWCTRL, D_ALL); | ||
| 2172 | |||
| 2173 | MMIO_F(HS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2174 | MMIO_F(DS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2175 | MMIO_F(IA_VERTICES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2176 | MMIO_F(IA_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2177 | MMIO_F(VS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2178 | MMIO_F(GS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2179 | MMIO_F(GS_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2180 | MMIO_F(CL_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2181 | MMIO_F(CL_PRIMITIVES_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2182 | MMIO_F(PS_INVOCATION_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2183 | MMIO_F(PS_DEPTH_COUNT, 8, 0, 0, 0, D_ALL, NULL, NULL); | ||
| 2184 | MMIO_DH(0x4260, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler); | ||
| 2185 | MMIO_DH(0x4264, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler); | ||
| 2186 | MMIO_DH(0x4268, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler); | ||
| 2187 | MMIO_DH(0x426c, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler); | ||
| 2188 | MMIO_DH(0x4270, D_BDW_PLUS, NULL, gvt_reg_tlb_control_handler); | ||
| 2189 | MMIO_DFH(0x4094, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); | ||
| 2190 | |||
| 2191 | return 0; | ||
| 2192 | } | ||
| 2193 | |||
| 2194 | static int init_broadwell_mmio_info(struct intel_gvt *gvt) | ||
| 2195 | { | ||
| 2196 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
| 2197 | int ret; | ||
| 2198 | |||
| 2199 | MMIO_DH(RING_IMR(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, | ||
| 2200 | intel_vgpu_reg_imr_handler); | ||
| 2201 | |||
| 2202 | MMIO_DH(GEN8_GT_IMR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); | ||
| 2203 | MMIO_DH(GEN8_GT_IER(0), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); | ||
| 2204 | MMIO_DH(GEN8_GT_IIR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); | ||
| 2205 | MMIO_D(GEN8_GT_ISR(0), D_BDW_PLUS); | ||
| 2206 | |||
| 2207 | MMIO_DH(GEN8_GT_IMR(1), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); | ||
| 2208 | MMIO_DH(GEN8_GT_IER(1), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); | ||
| 2209 | MMIO_DH(GEN8_GT_IIR(1), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); | ||
| 2210 | MMIO_D(GEN8_GT_ISR(1), D_BDW_PLUS); | ||
| 2211 | |||
| 2212 | MMIO_DH(GEN8_GT_IMR(2), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); | ||
| 2213 | MMIO_DH(GEN8_GT_IER(2), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); | ||
| 2214 | MMIO_DH(GEN8_GT_IIR(2), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); | ||
| 2215 | MMIO_D(GEN8_GT_ISR(2), D_BDW_PLUS); | ||
| 2216 | |||
| 2217 | MMIO_DH(GEN8_GT_IMR(3), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); | ||
| 2218 | MMIO_DH(GEN8_GT_IER(3), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); | ||
| 2219 | MMIO_DH(GEN8_GT_IIR(3), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); | ||
| 2220 | MMIO_D(GEN8_GT_ISR(3), D_BDW_PLUS); | ||
| 2221 | |||
| 2222 | MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_A), D_BDW_PLUS, NULL, | ||
| 2223 | intel_vgpu_reg_imr_handler); | ||
| 2224 | MMIO_DH(GEN8_DE_PIPE_IER(PIPE_A), D_BDW_PLUS, NULL, | ||
| 2225 | intel_vgpu_reg_ier_handler); | ||
| 2226 | MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_A), D_BDW_PLUS, NULL, | ||
| 2227 | intel_vgpu_reg_iir_handler); | ||
| 2228 | MMIO_D(GEN8_DE_PIPE_ISR(PIPE_A), D_BDW_PLUS); | ||
| 2229 | |||
| 2230 | MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_B), D_BDW_PLUS, NULL, | ||
| 2231 | intel_vgpu_reg_imr_handler); | ||
| 2232 | MMIO_DH(GEN8_DE_PIPE_IER(PIPE_B), D_BDW_PLUS, NULL, | ||
| 2233 | intel_vgpu_reg_ier_handler); | ||
| 2234 | MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_B), D_BDW_PLUS, NULL, | ||
| 2235 | intel_vgpu_reg_iir_handler); | ||
| 2236 | MMIO_D(GEN8_DE_PIPE_ISR(PIPE_B), D_BDW_PLUS); | ||
| 2237 | |||
| 2238 | MMIO_DH(GEN8_DE_PIPE_IMR(PIPE_C), D_BDW_PLUS, NULL, | ||
| 2239 | intel_vgpu_reg_imr_handler); | ||
| 2240 | MMIO_DH(GEN8_DE_PIPE_IER(PIPE_C), D_BDW_PLUS, NULL, | ||
| 2241 | intel_vgpu_reg_ier_handler); | ||
| 2242 | MMIO_DH(GEN8_DE_PIPE_IIR(PIPE_C), D_BDW_PLUS, NULL, | ||
| 2243 | intel_vgpu_reg_iir_handler); | ||
| 2244 | MMIO_D(GEN8_DE_PIPE_ISR(PIPE_C), D_BDW_PLUS); | ||
| 2245 | |||
| 2246 | MMIO_DH(GEN8_DE_PORT_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); | ||
| 2247 | MMIO_DH(GEN8_DE_PORT_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); | ||
| 2248 | MMIO_DH(GEN8_DE_PORT_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); | ||
| 2249 | MMIO_D(GEN8_DE_PORT_ISR, D_BDW_PLUS); | ||
| 2250 | |||
| 2251 | MMIO_DH(GEN8_DE_MISC_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); | ||
| 2252 | MMIO_DH(GEN8_DE_MISC_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); | ||
| 2253 | MMIO_DH(GEN8_DE_MISC_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); | ||
| 2254 | MMIO_D(GEN8_DE_MISC_ISR, D_BDW_PLUS); | ||
| 2255 | |||
| 2256 | MMIO_DH(GEN8_PCU_IMR, D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); | ||
| 2257 | MMIO_DH(GEN8_PCU_IER, D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); | ||
| 2258 | MMIO_DH(GEN8_PCU_IIR, D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); | ||
| 2259 | MMIO_D(GEN8_PCU_ISR, D_BDW_PLUS); | ||
| 2260 | |||
| 2261 | MMIO_DH(GEN8_MASTER_IRQ, D_BDW_PLUS, NULL, | ||
| 2262 | intel_vgpu_reg_master_irq_handler); | ||
| 2263 | |||
| 2264 | MMIO_D(RING_HWSTAM(GEN8_BSD2_RING_BASE), D_BDW_PLUS); | ||
| 2265 | MMIO_D(0x1c134, D_BDW_PLUS); | ||
| 2266 | |||
| 2267 | MMIO_D(RING_TAIL(GEN8_BSD2_RING_BASE), D_BDW_PLUS); | ||
| 2268 | MMIO_D(RING_HEAD(GEN8_BSD2_RING_BASE), D_BDW_PLUS); | ||
| 2269 | MMIO_GM(RING_START(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL); | ||
| 2270 | MMIO_D(RING_CTL(GEN8_BSD2_RING_BASE), D_BDW_PLUS); | ||
| 2271 | MMIO_D(RING_ACTHD(GEN8_BSD2_RING_BASE), D_BDW_PLUS); | ||
| 2272 | MMIO_D(RING_ACTHD_UDW(GEN8_BSD2_RING_BASE), D_BDW_PLUS); | ||
| 2273 | MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK, NULL, ring_mode_mmio_write); | ||
| 2274 | MMIO_DFH(RING_MI_MODE(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, | ||
| 2275 | NULL, NULL); | ||
| 2276 | MMIO_DFH(RING_INSTPM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, | ||
| 2277 | NULL, NULL); | ||
| 2278 | MMIO_DFH(RING_TIMESTAMP(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, | ||
| 2279 | ring_timestamp_mmio_read, NULL); | ||
| 2280 | |||
| 2281 | MMIO_RING_D(RING_ACTHD_UDW, D_BDW_PLUS); | ||
| 2282 | |||
| 2283 | #define RING_REG(base) (base + 0x230) | ||
| 2284 | MMIO_RING_DFH(RING_REG, D_BDW_PLUS, 0, NULL, elsp_mmio_write); | ||
| 2285 | MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, elsp_mmio_write); | ||
| 2286 | #undef RING_REG | ||
| 2287 | |||
| 2288 | #define RING_REG(base) (base + 0x234) | ||
| 2289 | MMIO_RING_F(RING_REG, 8, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL); | ||
| 2290 | MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO, 0, ~0LL, D_BDW_PLUS, NULL, NULL); | ||
| 2291 | #undef RING_REG | ||
| 2292 | |||
| 2293 | #define RING_REG(base) (base + 0x244) | ||
| 2294 | MMIO_RING_D(RING_REG, D_BDW_PLUS); | ||
| 2295 | MMIO_D(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS); | ||
| 2296 | #undef RING_REG | ||
| 2297 | |||
| 2298 | #define RING_REG(base) (base + 0x370) | ||
| 2299 | MMIO_RING_F(RING_REG, 48, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL); | ||
| 2300 | MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 48, F_RO, 0, ~0, D_BDW_PLUS, | ||
| 2301 | NULL, NULL); | ||
| 2302 | #undef RING_REG | ||
| 2303 | |||
| 2304 | #define RING_REG(base) (base + 0x3a0) | ||
| 2305 | MMIO_RING_DFH(RING_REG, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); | ||
| 2306 | MMIO_DFH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, NULL, NULL); | ||
| 2307 | #undef RING_REG | ||
| 2308 | |||
| 2309 | MMIO_D(PIPEMISC(PIPE_A), D_BDW_PLUS); | ||
| 2310 | MMIO_D(PIPEMISC(PIPE_B), D_BDW_PLUS); | ||
| 2311 | MMIO_D(PIPEMISC(PIPE_C), D_BDW_PLUS); | ||
| 2312 | MMIO_D(0x1c1d0, D_BDW_PLUS); | ||
| 2313 | MMIO_D(GEN6_MBCUNIT_SNPCR, D_BDW_PLUS); | ||
| 2314 | MMIO_D(GEN7_MISCCPCTL, D_BDW_PLUS); | ||
| 2315 | MMIO_D(0x1c054, D_BDW_PLUS); | ||
| 2316 | |||
| 2317 | MMIO_D(GEN8_PRIVATE_PAT_LO, D_BDW_PLUS); | ||
| 2318 | MMIO_D(GEN8_PRIVATE_PAT_HI, D_BDW_PLUS); | ||
| 2319 | |||
| 2320 | MMIO_D(GAMTARBMODE, D_BDW_PLUS); | ||
| 2321 | |||
| 2322 | #define RING_REG(base) (base + 0x270) | ||
| 2323 | MMIO_RING_F(RING_REG, 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL); | ||
| 2324 | MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL); | ||
| 2325 | #undef RING_REG | ||
| 2326 | |||
| 2327 | MMIO_RING_GM(RING_HWS_PGA, D_BDW_PLUS, NULL, NULL); | ||
| 2328 | MMIO_GM(0x1c080, D_BDW_PLUS, NULL, NULL); | ||
| 2329 | |||
| 2330 | MMIO_DFH(HDC_CHICKEN0, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); | ||
| 2331 | |||
| 2332 | MMIO_D(CHICKEN_PIPESL_1(PIPE_A), D_BDW); | ||
| 2333 | MMIO_D(CHICKEN_PIPESL_1(PIPE_B), D_BDW); | ||
| 2334 | MMIO_D(CHICKEN_PIPESL_1(PIPE_C), D_BDW); | ||
| 2335 | |||
| 2336 | MMIO_D(WM_MISC, D_BDW); | ||
| 2337 | MMIO_D(BDW_EDP_PSR_BASE, D_BDW); | ||
| 2338 | |||
| 2339 | MMIO_D(0x66c00, D_BDW_PLUS); | ||
| 2340 | MMIO_D(0x66c04, D_BDW_PLUS); | ||
| 2341 | |||
| 2342 | MMIO_D(HSW_GTT_CACHE_EN, D_BDW_PLUS); | ||
| 2343 | |||
| 2344 | MMIO_D(GEN8_EU_DISABLE0, D_BDW_PLUS); | ||
| 2345 | MMIO_D(GEN8_EU_DISABLE1, D_BDW_PLUS); | ||
| 2346 | MMIO_D(GEN8_EU_DISABLE2, D_BDW_PLUS); | ||
| 2347 | |||
| 2348 | MMIO_D(0xfdc, D_BDW); | ||
| 2349 | MMIO_D(GEN8_ROW_CHICKEN, D_BDW_PLUS); | ||
| 2350 | MMIO_D(GEN7_ROW_CHICKEN2, D_BDW_PLUS); | ||
| 2351 | MMIO_D(GEN8_UCGCTL6, D_BDW_PLUS); | ||
| 2352 | |||
| 2353 | MMIO_D(0xb1f0, D_BDW); | ||
| 2354 | MMIO_D(0xb1c0, D_BDW); | ||
| 2355 | MMIO_DFH(GEN8_L3SQCREG4, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); | ||
| 2356 | MMIO_D(0xb100, D_BDW); | ||
| 2357 | MMIO_D(0xb10c, D_BDW); | ||
| 2358 | MMIO_D(0xb110, D_BDW); | ||
| 2359 | |||
| 2360 | MMIO_DH(0x24d0, D_BDW_PLUS, NULL, NULL); | ||
| 2361 | MMIO_DH(0x24d4, D_BDW_PLUS, NULL, NULL); | ||
| 2362 | MMIO_DH(0x24d8, D_BDW_PLUS, NULL, NULL); | ||
| 2363 | MMIO_DH(0x24dc, D_BDW_PLUS, NULL, NULL); | ||
| 2364 | |||
| 2365 | MMIO_D(0x83a4, D_BDW); | ||
| 2366 | MMIO_D(GEN8_L3_LRA_1_GPGPU, D_BDW_PLUS); | ||
| 2367 | |||
| 2368 | MMIO_D(0x8430, D_BDW); | ||
| 2369 | |||
| 2370 | MMIO_D(0x110000, D_BDW_PLUS); | ||
| 2371 | |||
| 2372 | MMIO_D(0x48400, D_BDW_PLUS); | ||
| 2373 | |||
| 2374 | MMIO_D(0x6e570, D_BDW_PLUS); | ||
| 2375 | MMIO_D(0x65f10, D_BDW_PLUS); | ||
| 2376 | |||
| 2377 | MMIO_DFH(0xe194, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); | ||
| 2378 | MMIO_DFH(0xe188, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); | ||
| 2379 | MMIO_DFH(0xe180, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); | ||
| 2380 | MMIO_DFH(0x2580, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); | ||
| 2381 | |||
| 2382 | MMIO_D(0x2248, D_BDW); | ||
| 2383 | |||
| 2384 | return 0; | ||
| 2385 | } | ||
| 2386 | |||
| 2387 | static int init_skl_mmio_info(struct intel_gvt *gvt) | ||
| 2388 | { | ||
| 2389 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
| 2390 | int ret; | ||
| 2391 | |||
| 2392 | MMIO_DH(FORCEWAKE_RENDER_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write); | ||
| 2393 | MMIO_DH(FORCEWAKE_ACK_RENDER_GEN9, D_SKL_PLUS, NULL, NULL); | ||
| 2394 | MMIO_DH(FORCEWAKE_BLITTER_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write); | ||
| 2395 | MMIO_DH(FORCEWAKE_ACK_BLITTER_GEN9, D_SKL_PLUS, NULL, NULL); | ||
| 2396 | MMIO_DH(FORCEWAKE_MEDIA_GEN9, D_SKL_PLUS, NULL, mul_force_wake_write); | ||
| 2397 | MMIO_DH(FORCEWAKE_ACK_MEDIA_GEN9, D_SKL_PLUS, NULL, NULL); | ||
| 2398 | |||
| 2399 | MMIO_F(_DPB_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write); | ||
| 2400 | MMIO_F(_DPC_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write); | ||
| 2401 | MMIO_F(_DPD_AUX_CH_CTL, 6 * 4, 0, 0, 0, D_SKL, NULL, dp_aux_ch_ctl_mmio_write); | ||
| 2402 | |||
| 2403 | MMIO_D(HSW_PWR_WELL_BIOS, D_SKL); | ||
| 2404 | MMIO_DH(HSW_PWR_WELL_DRIVER, D_SKL, NULL, skl_power_well_ctl_write); | ||
| 2405 | |||
| 2406 | MMIO_DH(GEN6_PCODE_MAILBOX, D_SKL, NULL, mailbox_write); | ||
| 2407 | MMIO_D(0xa210, D_SKL_PLUS); | ||
| 2408 | MMIO_D(GEN9_MEDIA_PG_IDLE_HYSTERESIS, D_SKL_PLUS); | ||
| 2409 | MMIO_D(GEN9_RENDER_PG_IDLE_HYSTERESIS, D_SKL_PLUS); | ||
| 2410 | MMIO_DH(0x4ddc, D_SKL, NULL, skl_misc_ctl_write); | ||
| 2411 | MMIO_DH(0x42080, D_SKL, NULL, skl_misc_ctl_write); | ||
| 2412 | MMIO_D(0x45504, D_SKL); | ||
| 2413 | MMIO_D(0x45520, D_SKL); | ||
| 2414 | MMIO_D(0x46000, D_SKL); | ||
| 2415 | MMIO_DH(0x46010, D_SKL, NULL, skl_lcpll_write); | ||
| 2416 | MMIO_DH(0x46014, D_SKL, NULL, skl_lcpll_write); | ||
| 2417 | MMIO_D(0x6C040, D_SKL); | ||
| 2418 | MMIO_D(0x6C048, D_SKL); | ||
| 2419 | MMIO_D(0x6C050, D_SKL); | ||
| 2420 | MMIO_D(0x6C044, D_SKL); | ||
| 2421 | MMIO_D(0x6C04C, D_SKL); | ||
| 2422 | MMIO_D(0x6C054, D_SKL); | ||
| 2423 | MMIO_D(0x6c058, D_SKL); | ||
| 2424 | MMIO_D(0x6c05c, D_SKL); | ||
| 2425 | MMIO_DH(0X6c060, D_SKL, dpll_status_read, NULL); | ||
| 2426 | |||
| 2427 | MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 0), D_SKL, NULL, pf_write); | ||
| 2428 | MMIO_DH(SKL_PS_WIN_POS(PIPE_A, 1), D_SKL, NULL, pf_write); | ||
| 2429 | MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 0), D_SKL, NULL, pf_write); | ||
| 2430 | MMIO_DH(SKL_PS_WIN_POS(PIPE_B, 1), D_SKL, NULL, pf_write); | ||
| 2431 | MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 0), D_SKL, NULL, pf_write); | ||
| 2432 | MMIO_DH(SKL_PS_WIN_POS(PIPE_C, 1), D_SKL, NULL, pf_write); | ||
| 2433 | |||
| 2434 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 0), D_SKL, NULL, pf_write); | ||
| 2435 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_A, 1), D_SKL, NULL, pf_write); | ||
| 2436 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 0), D_SKL, NULL, pf_write); | ||
| 2437 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_B, 1), D_SKL, NULL, pf_write); | ||
| 2438 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 0), D_SKL, NULL, pf_write); | ||
| 2439 | MMIO_DH(SKL_PS_WIN_SZ(PIPE_C, 1), D_SKL, NULL, pf_write); | ||
| 2440 | |||
| 2441 | MMIO_DH(SKL_PS_CTRL(PIPE_A, 0), D_SKL, NULL, pf_write); | ||
| 2442 | MMIO_DH(SKL_PS_CTRL(PIPE_A, 1), D_SKL, NULL, pf_write); | ||
| 2443 | MMIO_DH(SKL_PS_CTRL(PIPE_B, 0), D_SKL, NULL, pf_write); | ||
| 2444 | MMIO_DH(SKL_PS_CTRL(PIPE_B, 1), D_SKL, NULL, pf_write); | ||
| 2445 | MMIO_DH(SKL_PS_CTRL(PIPE_C, 0), D_SKL, NULL, pf_write); | ||
| 2446 | MMIO_DH(SKL_PS_CTRL(PIPE_C, 1), D_SKL, NULL, pf_write); | ||
| 2447 | |||
| 2448 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL); | ||
| 2449 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL); | ||
| 2450 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL); | ||
| 2451 | MMIO_DH(PLANE_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL); | ||
| 2452 | |||
| 2453 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL); | ||
| 2454 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL); | ||
| 2455 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL); | ||
| 2456 | MMIO_DH(PLANE_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL); | ||
| 2457 | |||
| 2458 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL); | ||
| 2459 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL); | ||
| 2460 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL); | ||
| 2461 | MMIO_DH(PLANE_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL); | ||
| 2462 | |||
| 2463 | MMIO_DH(CUR_BUF_CFG(PIPE_A), D_SKL, NULL, NULL); | ||
| 2464 | MMIO_DH(CUR_BUF_CFG(PIPE_B), D_SKL, NULL, NULL); | ||
| 2465 | MMIO_DH(CUR_BUF_CFG(PIPE_C), D_SKL, NULL, NULL); | ||
| 2466 | |||
| 2467 | MMIO_F(PLANE_WM(PIPE_A, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2468 | MMIO_F(PLANE_WM(PIPE_A, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2469 | MMIO_F(PLANE_WM(PIPE_A, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2470 | |||
| 2471 | MMIO_F(PLANE_WM(PIPE_B, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2472 | MMIO_F(PLANE_WM(PIPE_B, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2473 | MMIO_F(PLANE_WM(PIPE_B, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2474 | |||
| 2475 | MMIO_F(PLANE_WM(PIPE_C, 0, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2476 | MMIO_F(PLANE_WM(PIPE_C, 1, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2477 | MMIO_F(PLANE_WM(PIPE_C, 2, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2478 | |||
| 2479 | MMIO_F(CUR_WM(PIPE_A, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2480 | MMIO_F(CUR_WM(PIPE_B, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2481 | MMIO_F(CUR_WM(PIPE_C, 0), 4 * 8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2482 | |||
| 2483 | MMIO_DH(PLANE_WM_TRANS(PIPE_A, 0), D_SKL, NULL, NULL); | ||
| 2484 | MMIO_DH(PLANE_WM_TRANS(PIPE_A, 1), D_SKL, NULL, NULL); | ||
| 2485 | MMIO_DH(PLANE_WM_TRANS(PIPE_A, 2), D_SKL, NULL, NULL); | ||
| 2486 | |||
| 2487 | MMIO_DH(PLANE_WM_TRANS(PIPE_B, 0), D_SKL, NULL, NULL); | ||
| 2488 | MMIO_DH(PLANE_WM_TRANS(PIPE_B, 1), D_SKL, NULL, NULL); | ||
| 2489 | MMIO_DH(PLANE_WM_TRANS(PIPE_B, 2), D_SKL, NULL, NULL); | ||
| 2490 | |||
| 2491 | MMIO_DH(PLANE_WM_TRANS(PIPE_C, 0), D_SKL, NULL, NULL); | ||
| 2492 | MMIO_DH(PLANE_WM_TRANS(PIPE_C, 1), D_SKL, NULL, NULL); | ||
| 2493 | MMIO_DH(PLANE_WM_TRANS(PIPE_C, 2), D_SKL, NULL, NULL); | ||
| 2494 | |||
| 2495 | MMIO_DH(CUR_WM_TRANS(PIPE_A), D_SKL, NULL, NULL); | ||
| 2496 | MMIO_DH(CUR_WM_TRANS(PIPE_B), D_SKL, NULL, NULL); | ||
| 2497 | MMIO_DH(CUR_WM_TRANS(PIPE_C), D_SKL, NULL, NULL); | ||
| 2498 | |||
| 2499 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 0), D_SKL, NULL, NULL); | ||
| 2500 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 1), D_SKL, NULL, NULL); | ||
| 2501 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 2), D_SKL, NULL, NULL); | ||
| 2502 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_A, 3), D_SKL, NULL, NULL); | ||
| 2503 | |||
| 2504 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 0), D_SKL, NULL, NULL); | ||
| 2505 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 1), D_SKL, NULL, NULL); | ||
| 2506 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 2), D_SKL, NULL, NULL); | ||
| 2507 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_B, 3), D_SKL, NULL, NULL); | ||
| 2508 | |||
| 2509 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 0), D_SKL, NULL, NULL); | ||
| 2510 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 1), D_SKL, NULL, NULL); | ||
| 2511 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 2), D_SKL, NULL, NULL); | ||
| 2512 | MMIO_DH(PLANE_NV12_BUF_CFG(PIPE_C, 3), D_SKL, NULL, NULL); | ||
| 2513 | |||
| 2514 | MMIO_DH(_REG_701C0(PIPE_A, 1), D_SKL, NULL, NULL); | ||
| 2515 | MMIO_DH(_REG_701C0(PIPE_A, 2), D_SKL, NULL, NULL); | ||
| 2516 | MMIO_DH(_REG_701C0(PIPE_A, 3), D_SKL, NULL, NULL); | ||
| 2517 | MMIO_DH(_REG_701C0(PIPE_A, 4), D_SKL, NULL, NULL); | ||
| 2518 | |||
| 2519 | MMIO_DH(_REG_701C0(PIPE_B, 1), D_SKL, NULL, NULL); | ||
| 2520 | MMIO_DH(_REG_701C0(PIPE_B, 2), D_SKL, NULL, NULL); | ||
| 2521 | MMIO_DH(_REG_701C0(PIPE_B, 3), D_SKL, NULL, NULL); | ||
| 2522 | MMIO_DH(_REG_701C0(PIPE_B, 4), D_SKL, NULL, NULL); | ||
| 2523 | |||
| 2524 | MMIO_DH(_REG_701C0(PIPE_C, 1), D_SKL, NULL, NULL); | ||
| 2525 | MMIO_DH(_REG_701C0(PIPE_C, 2), D_SKL, NULL, NULL); | ||
| 2526 | MMIO_DH(_REG_701C0(PIPE_C, 3), D_SKL, NULL, NULL); | ||
| 2527 | MMIO_DH(_REG_701C0(PIPE_C, 4), D_SKL, NULL, NULL); | ||
| 2528 | |||
| 2529 | MMIO_DH(_REG_701C4(PIPE_A, 1), D_SKL, NULL, NULL); | ||
| 2530 | MMIO_DH(_REG_701C4(PIPE_A, 2), D_SKL, NULL, NULL); | ||
| 2531 | MMIO_DH(_REG_701C4(PIPE_A, 3), D_SKL, NULL, NULL); | ||
| 2532 | MMIO_DH(_REG_701C4(PIPE_A, 4), D_SKL, NULL, NULL); | ||
| 2533 | |||
| 2534 | MMIO_DH(_REG_701C4(PIPE_B, 1), D_SKL, NULL, NULL); | ||
| 2535 | MMIO_DH(_REG_701C4(PIPE_B, 2), D_SKL, NULL, NULL); | ||
| 2536 | MMIO_DH(_REG_701C4(PIPE_B, 3), D_SKL, NULL, NULL); | ||
| 2537 | MMIO_DH(_REG_701C4(PIPE_B, 4), D_SKL, NULL, NULL); | ||
| 2538 | |||
| 2539 | MMIO_DH(_REG_701C4(PIPE_C, 1), D_SKL, NULL, NULL); | ||
| 2540 | MMIO_DH(_REG_701C4(PIPE_C, 2), D_SKL, NULL, NULL); | ||
| 2541 | MMIO_DH(_REG_701C4(PIPE_C, 3), D_SKL, NULL, NULL); | ||
| 2542 | MMIO_DH(_REG_701C4(PIPE_C, 4), D_SKL, NULL, NULL); | ||
| 2543 | |||
| 2544 | MMIO_D(0x70380, D_SKL); | ||
| 2545 | MMIO_D(0x71380, D_SKL); | ||
| 2546 | MMIO_D(0x72380, D_SKL); | ||
| 2547 | MMIO_D(0x7039c, D_SKL); | ||
| 2548 | |||
| 2549 | MMIO_F(0x80000, 0x3000, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2550 | MMIO_D(0x8f074, D_SKL); | ||
| 2551 | MMIO_D(0x8f004, D_SKL); | ||
| 2552 | MMIO_D(0x8f034, D_SKL); | ||
| 2553 | |||
| 2554 | MMIO_D(0xb11c, D_SKL); | ||
| 2555 | |||
| 2556 | MMIO_D(0x51000, D_SKL); | ||
| 2557 | MMIO_D(0x6c00c, D_SKL); | ||
| 2558 | |||
| 2559 | MMIO_F(0xc800, 0x7f8, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2560 | MMIO_F(0xb020, 0x80, 0, 0, 0, D_SKL, NULL, NULL); | ||
| 2561 | |||
| 2562 | MMIO_D(0xd08, D_SKL); | ||
| 2563 | MMIO_D(0x20e0, D_SKL); | ||
| 2564 | MMIO_D(0x20ec, D_SKL); | ||
| 2565 | |||
| 2566 | /* TRTT */ | ||
| 2567 | MMIO_D(0x4de0, D_SKL); | ||
| 2568 | MMIO_D(0x4de4, D_SKL); | ||
| 2569 | MMIO_D(0x4de8, D_SKL); | ||
| 2570 | MMIO_D(0x4dec, D_SKL); | ||
| 2571 | MMIO_D(0x4df0, D_SKL); | ||
| 2572 | MMIO_DH(0x4df4, D_SKL, NULL, gen9_trtte_write); | ||
| 2573 | MMIO_DH(0x4dfc, D_SKL, NULL, gen9_trtt_chicken_write); | ||
| 2574 | |||
| 2575 | MMIO_D(0x45008, D_SKL); | ||
| 2576 | |||
| 2577 | MMIO_D(0x46430, D_SKL); | ||
| 2578 | |||
| 2579 | MMIO_D(0x46520, D_SKL); | ||
| 2580 | |||
| 2581 | MMIO_D(0xc403c, D_SKL); | ||
| 2582 | MMIO_D(0xb004, D_SKL); | ||
| 2583 | MMIO_DH(DMA_CTRL, D_SKL_PLUS, NULL, dma_ctrl_write); | ||
| 2584 | |||
| 2585 | MMIO_D(0x65900, D_SKL); | ||
| 2586 | MMIO_D(0x1082c0, D_SKL); | ||
| 2587 | MMIO_D(0x4068, D_SKL); | ||
| 2588 | MMIO_D(0x67054, D_SKL); | ||
| 2589 | MMIO_D(0x6e560, D_SKL); | ||
| 2590 | MMIO_D(0x6e554, D_SKL); | ||
| 2591 | MMIO_D(0x2b20, D_SKL); | ||
| 2592 | MMIO_D(0x65f00, D_SKL); | ||
| 2593 | MMIO_D(0x65f08, D_SKL); | ||
| 2594 | MMIO_D(0x320f0, D_SKL); | ||
| 2595 | |||
| 2596 | MMIO_D(_REG_VCS2_EXCC, D_SKL); | ||
| 2597 | MMIO_D(0x70034, D_SKL); | ||
| 2598 | MMIO_D(0x71034, D_SKL); | ||
| 2599 | MMIO_D(0x72034, D_SKL); | ||
| 2600 | |||
| 2601 | MMIO_D(_PLANE_KEYVAL_1(PIPE_A), D_SKL); | ||
| 2602 | MMIO_D(_PLANE_KEYVAL_1(PIPE_B), D_SKL); | ||
| 2603 | MMIO_D(_PLANE_KEYVAL_1(PIPE_C), D_SKL); | ||
| 2604 | MMIO_D(_PLANE_KEYMSK_1(PIPE_A), D_SKL); | ||
| 2605 | MMIO_D(_PLANE_KEYMSK_1(PIPE_B), D_SKL); | ||
| 2606 | MMIO_D(_PLANE_KEYMSK_1(PIPE_C), D_SKL); | ||
| 2607 | |||
| 2608 | MMIO_D(0x44500, D_SKL); | ||
| 2609 | return 0; | ||
| 2610 | } | ||
| 2611 | |||
| 2612 | /** | ||
| 2613 | * intel_gvt_find_mmio_info - find MMIO information entry by aligned offset | ||
| 2614 | * @gvt: GVT device | ||
| 2615 | * @offset: register offset | ||
| 2616 | * | ||
| 2617 | * This function is used to find the MMIO information entry from hash table | ||
| 2618 | * | ||
| 2619 | * Returns: | ||
| 2620 | * pointer to MMIO information entry, NULL if not exists | ||
| 2621 | */ | ||
| 2622 | struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt, | ||
| 2623 | unsigned int offset) | ||
| 2624 | { | ||
| 2625 | struct intel_gvt_mmio_info *e; | ||
| 2626 | |||
| 2627 | WARN_ON(!IS_ALIGNED(offset, 4)); | ||
| 2628 | |||
| 2629 | hash_for_each_possible(gvt->mmio.mmio_info_table, e, node, offset) { | ||
| 2630 | if (e->offset == offset) | ||
| 2631 | return e; | ||
| 2632 | } | ||
| 2633 | return NULL; | ||
| 2634 | } | ||
| 2635 | |||
| 2636 | /** | ||
| 2637 | * intel_gvt_clean_mmio_info - clean up MMIO information table for GVT device | ||
| 2638 | * @gvt: GVT device | ||
| 2639 | * | ||
| 2640 | * This function is called at the driver unloading stage, to clean up the MMIO | ||
| 2641 | * information table of GVT device | ||
| 2642 | * | ||
| 2643 | */ | ||
| 2644 | void intel_gvt_clean_mmio_info(struct intel_gvt *gvt) | ||
| 2645 | { | ||
| 2646 | struct hlist_node *tmp; | ||
| 2647 | struct intel_gvt_mmio_info *e; | ||
| 2648 | int i; | ||
| 2649 | |||
| 2650 | hash_for_each_safe(gvt->mmio.mmio_info_table, i, tmp, e, node) | ||
| 2651 | kfree(e); | ||
| 2652 | |||
| 2653 | vfree(gvt->mmio.mmio_attribute); | ||
| 2654 | gvt->mmio.mmio_attribute = NULL; | ||
| 2655 | } | ||
| 2656 | |||
| 2657 | /** | ||
| 2658 | * intel_gvt_setup_mmio_info - setup MMIO information table for GVT device | ||
| 2659 | * @gvt: GVT device | ||
| 2660 | * | ||
| 2661 | * This function is called at the initialization stage, to setup the MMIO | ||
| 2662 | * information table for GVT device | ||
| 2663 | * | ||
| 2664 | * Returns: | ||
| 2665 | * zero on success, negative if failed. | ||
| 2666 | */ | ||
| 2667 | int intel_gvt_setup_mmio_info(struct intel_gvt *gvt) | ||
| 2668 | { | ||
| 2669 | struct intel_gvt_device_info *info = &gvt->device_info; | ||
| 2670 | struct drm_i915_private *dev_priv = gvt->dev_priv; | ||
| 2671 | int ret; | ||
| 2672 | |||
| 2673 | gvt->mmio.mmio_attribute = vzalloc(info->mmio_size); | ||
| 2674 | if (!gvt->mmio.mmio_attribute) | ||
| 2675 | return -ENOMEM; | ||
| 2676 | |||
| 2677 | ret = init_generic_mmio_info(gvt); | ||
| 2678 | if (ret) | ||
| 2679 | goto err; | ||
| 2680 | |||
| 2681 | if (IS_BROADWELL(dev_priv)) { | ||
| 2682 | ret = init_broadwell_mmio_info(gvt); | ||
| 2683 | if (ret) | ||
| 2684 | goto err; | ||
| 2685 | } else if (IS_SKYLAKE(dev_priv)) { | ||
| 2686 | ret = init_broadwell_mmio_info(gvt); | ||
| 2687 | if (ret) | ||
| 2688 | goto err; | ||
| 2689 | ret = init_skl_mmio_info(gvt); | ||
| 2690 | if (ret) | ||
| 2691 | goto err; | ||
| 2692 | } | ||
| 2693 | return 0; | ||
| 2694 | err: | ||
| 2695 | intel_gvt_clean_mmio_info(gvt); | ||
| 2696 | return ret; | ||
| 2697 | } | ||
| 2698 | |||
| 2699 | /** | ||
| 2700 | * intel_gvt_mmio_set_accessed - mark a MMIO has been accessed | ||
| 2701 | * @gvt: a GVT device | ||
| 2702 | * @offset: register offset | ||
| 2703 | * | ||
| 2704 | */ | ||
| 2705 | void intel_gvt_mmio_set_accessed(struct intel_gvt *gvt, unsigned int offset) | ||
| 2706 | { | ||
| 2707 | gvt->mmio.mmio_attribute[offset >> 2] |= | ||
| 2708 | F_ACCESSED; | ||
| 2709 | } | ||
| 2710 | |||
| 2711 | /** | ||
| 2712 | * intel_gvt_mmio_is_cmd_accessed - mark a MMIO could be accessed by command | ||
| 2713 | * @gvt: a GVT device | ||
| 2714 | * @offset: register offset | ||
| 2715 | * | ||
| 2716 | */ | ||
| 2717 | bool intel_gvt_mmio_is_cmd_access(struct intel_gvt *gvt, | ||
| 2718 | unsigned int offset) | ||
| 2719 | { | ||
| 2720 | return gvt->mmio.mmio_attribute[offset >> 2] & | ||
| 2721 | F_CMD_ACCESS; | ||
| 2722 | } | ||
| 2723 | |||
| 2724 | /** | ||
| 2725 | * intel_gvt_mmio_is_unalign - mark a MMIO could be accessed unaligned | ||
| 2726 | * @gvt: a GVT device | ||
| 2727 | * @offset: register offset | ||
| 2728 | * | ||
| 2729 | */ | ||
| 2730 | bool intel_gvt_mmio_is_unalign(struct intel_gvt *gvt, | ||
| 2731 | unsigned int offset) | ||
| 2732 | { | ||
| 2733 | return gvt->mmio.mmio_attribute[offset >> 2] & | ||
| 2734 | F_UNALIGN; | ||
| 2735 | } | ||
| 2736 | |||
| 2737 | /** | ||
| 2738 | * intel_gvt_mmio_set_cmd_accessed - mark a MMIO has been accessed by command | ||
| 2739 | * @gvt: a GVT device | ||
| 2740 | * @offset: register offset | ||
| 2741 | * | ||
| 2742 | */ | ||
| 2743 | void intel_gvt_mmio_set_cmd_accessed(struct intel_gvt *gvt, | ||
| 2744 | unsigned int offset) | ||
| 2745 | { | ||
| 2746 | gvt->mmio.mmio_attribute[offset >> 2] |= | ||
| 2747 | F_CMD_ACCESSED; | ||
| 2748 | } | ||
| 2749 | |||
| 2750 | /** | ||
| 2751 | * intel_gvt_mmio_has_mode_mask - if a MMIO has a mode mask | ||
| 2752 | * @gvt: a GVT device | ||
| 2753 | * @offset: register offset | ||
| 2754 | * | ||
| 2755 | * Returns: | ||
| 2756 | * True if a MMIO has a mode mask in its higher 16 bits, false if it isn't. | ||
| 2757 | * | ||
| 2758 | */ | ||
| 2759 | bool intel_gvt_mmio_has_mode_mask(struct intel_gvt *gvt, unsigned int offset) | ||
| 2760 | { | ||
| 2761 | return gvt->mmio.mmio_attribute[offset >> 2] & | ||
| 2762 | F_MODE_MASK; | ||
| 2763 | } | ||
| 2764 | |||
| 2765 | /** | ||
| 2766 | * intel_vgpu_default_mmio_read - default MMIO read handler | ||
| 2767 | * @vgpu: a vGPU | ||
| 2768 | * @offset: access offset | ||
| 2769 | * @p_data: data return buffer | ||
| 2770 | * @bytes: access data length | ||
| 2771 | * | ||
| 2772 | * Returns: | ||
| 2773 | * Zero on success, negative error code if failed. | ||
| 2774 | */ | ||
| 2775 | int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 2776 | void *p_data, unsigned int bytes) | ||
| 2777 | { | ||
| 2778 | read_vreg(vgpu, offset, p_data, bytes); | ||
| 2779 | return 0; | ||
| 2780 | } | ||
| 2781 | |||
| 2782 | /** | ||
| 2783 | * intel_t_default_mmio_write - default MMIO write handler | ||
| 2784 | * @vgpu: a vGPU | ||
| 2785 | * @offset: access offset | ||
| 2786 | * @p_data: write data buffer | ||
| 2787 | * @bytes: access data length | ||
| 2788 | * | ||
| 2789 | * Returns: | ||
| 2790 | * Zero on success, negative error code if failed. | ||
| 2791 | */ | ||
| 2792 | int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 2793 | void *p_data, unsigned int bytes) | ||
| 2794 | { | ||
| 2795 | write_vreg(vgpu, offset, p_data, bytes); | ||
| 2796 | return 0; | ||
| 2797 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h index 254df8bf1f35..027ef558d91c 100644 --- a/drivers/gpu/drm/i915/gvt/hypercall.h +++ b/drivers/gpu/drm/i915/gvt/hypercall.h | |||
| @@ -19,17 +19,51 @@ | |||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 21 | * SOFTWARE. | 21 | * SOFTWARE. |
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Eddie Dong <eddie.dong@intel.com> | ||
| 25 | * Dexuan Cui | ||
| 26 | * Jike Song <jike.song@intel.com> | ||
| 27 | * | ||
| 28 | * Contributors: | ||
| 29 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 30 | * | ||
| 22 | */ | 31 | */ |
| 23 | 32 | ||
| 24 | #ifndef _GVT_HYPERCALL_H_ | 33 | #ifndef _GVT_HYPERCALL_H_ |
| 25 | #define _GVT_HYPERCALL_H_ | 34 | #define _GVT_HYPERCALL_H_ |
| 26 | 35 | ||
| 36 | struct intel_gvt_io_emulation_ops { | ||
| 37 | int (*emulate_cfg_read)(void *, unsigned int, void *, unsigned int); | ||
| 38 | int (*emulate_cfg_write)(void *, unsigned int, void *, unsigned int); | ||
| 39 | int (*emulate_mmio_read)(void *, u64, void *, unsigned int); | ||
| 40 | int (*emulate_mmio_write)(void *, u64, void *, unsigned int); | ||
| 41 | }; | ||
| 42 | |||
| 43 | extern struct intel_gvt_io_emulation_ops intel_gvt_io_emulation_ops; | ||
| 44 | |||
| 27 | /* | 45 | /* |
| 28 | * Specific GVT-g MPT modules function collections. Currently GVT-g supports | 46 | * Specific GVT-g MPT modules function collections. Currently GVT-g supports |
| 29 | * both Xen and KVM by providing dedicated hypervisor-related MPT modules. | 47 | * both Xen and KVM by providing dedicated hypervisor-related MPT modules. |
| 30 | */ | 48 | */ |
| 31 | struct intel_gvt_mpt { | 49 | struct intel_gvt_mpt { |
| 32 | int (*detect_host)(void); | 50 | int (*detect_host)(void); |
| 51 | int (*attach_vgpu)(void *vgpu, unsigned long *handle); | ||
| 52 | void (*detach_vgpu)(unsigned long handle); | ||
| 53 | int (*inject_msi)(unsigned long handle, u32 addr, u16 data); | ||
| 54 | unsigned long (*from_virt_to_mfn)(void *p); | ||
| 55 | int (*set_wp_page)(unsigned long handle, u64 gfn); | ||
| 56 | int (*unset_wp_page)(unsigned long handle, u64 gfn); | ||
| 57 | int (*read_gpa)(unsigned long handle, unsigned long gpa, void *buf, | ||
| 58 | unsigned long len); | ||
| 59 | int (*write_gpa)(unsigned long handle, unsigned long gpa, void *buf, | ||
| 60 | unsigned long len); | ||
| 61 | unsigned long (*gfn_to_mfn)(unsigned long handle, unsigned long gfn); | ||
| 62 | int (*map_gfn_to_mfn)(unsigned long handle, unsigned long gfn, | ||
| 63 | unsigned long mfn, unsigned int nr, bool map, | ||
| 64 | int type); | ||
| 65 | int (*set_trap_area)(unsigned long handle, u64 start, u64 end, | ||
| 66 | bool map); | ||
| 33 | }; | 67 | }; |
| 34 | 68 | ||
| 35 | extern struct intel_gvt_mpt xengt_mpt; | 69 | extern struct intel_gvt_mpt xengt_mpt; |
diff --git a/drivers/gpu/drm/i915/gvt/interrupt.c b/drivers/gpu/drm/i915/gvt/interrupt.c new file mode 100644 index 000000000000..f7be02ac4be1 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/interrupt.c | |||
| @@ -0,0 +1,741 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Kevin Tian <kevin.tian@intel.com> | ||
| 25 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Min he <min.he@intel.com> | ||
| 29 | * | ||
| 30 | */ | ||
| 31 | |||
| 32 | #include "i915_drv.h" | ||
| 33 | #include "gvt.h" | ||
| 34 | |||
| 35 | /* common offset among interrupt control registers */ | ||
| 36 | #define regbase_to_isr(base) (base) | ||
| 37 | #define regbase_to_imr(base) (base + 0x4) | ||
| 38 | #define regbase_to_iir(base) (base + 0x8) | ||
| 39 | #define regbase_to_ier(base) (base + 0xC) | ||
| 40 | |||
| 41 | #define iir_to_regbase(iir) (iir - 0x8) | ||
| 42 | #define ier_to_regbase(ier) (ier - 0xC) | ||
| 43 | |||
| 44 | #define get_event_virt_handler(irq, e) (irq->events[e].v_handler) | ||
| 45 | #define get_irq_info(irq, e) (irq->events[e].info) | ||
| 46 | |||
| 47 | #define irq_to_gvt(irq) \ | ||
| 48 | container_of(irq, struct intel_gvt, irq) | ||
| 49 | |||
| 50 | static void update_upstream_irq(struct intel_vgpu *vgpu, | ||
| 51 | struct intel_gvt_irq_info *info); | ||
| 52 | |||
| 53 | static const char * const irq_name[INTEL_GVT_EVENT_MAX] = { | ||
| 54 | [RCS_MI_USER_INTERRUPT] = "Render CS MI USER INTERRUPT", | ||
| 55 | [RCS_DEBUG] = "Render EU debug from SVG", | ||
| 56 | [RCS_MMIO_SYNC_FLUSH] = "Render MMIO sync flush status", | ||
| 57 | [RCS_CMD_STREAMER_ERR] = "Render CS error interrupt", | ||
| 58 | [RCS_PIPE_CONTROL] = "Render PIPE CONTROL notify", | ||
| 59 | [RCS_WATCHDOG_EXCEEDED] = "Render CS Watchdog counter exceeded", | ||
| 60 | [RCS_PAGE_DIRECTORY_FAULT] = "Render page directory faults", | ||
| 61 | [RCS_AS_CONTEXT_SWITCH] = "Render AS Context Switch Interrupt", | ||
| 62 | |||
| 63 | [VCS_MI_USER_INTERRUPT] = "Video CS MI USER INTERRUPT", | ||
| 64 | [VCS_MMIO_SYNC_FLUSH] = "Video MMIO sync flush status", | ||
| 65 | [VCS_CMD_STREAMER_ERR] = "Video CS error interrupt", | ||
| 66 | [VCS_MI_FLUSH_DW] = "Video MI FLUSH DW notify", | ||
| 67 | [VCS_WATCHDOG_EXCEEDED] = "Video CS Watchdog counter exceeded", | ||
| 68 | [VCS_PAGE_DIRECTORY_FAULT] = "Video page directory faults", | ||
| 69 | [VCS_AS_CONTEXT_SWITCH] = "Video AS Context Switch Interrupt", | ||
| 70 | [VCS2_MI_USER_INTERRUPT] = "VCS2 Video CS MI USER INTERRUPT", | ||
| 71 | [VCS2_MI_FLUSH_DW] = "VCS2 Video MI FLUSH DW notify", | ||
| 72 | [VCS2_AS_CONTEXT_SWITCH] = "VCS2 Context Switch Interrupt", | ||
| 73 | |||
| 74 | [BCS_MI_USER_INTERRUPT] = "Blitter CS MI USER INTERRUPT", | ||
| 75 | [BCS_MMIO_SYNC_FLUSH] = "Billter MMIO sync flush status", | ||
| 76 | [BCS_CMD_STREAMER_ERR] = "Blitter CS error interrupt", | ||
| 77 | [BCS_MI_FLUSH_DW] = "Blitter MI FLUSH DW notify", | ||
| 78 | [BCS_PAGE_DIRECTORY_FAULT] = "Blitter page directory faults", | ||
| 79 | [BCS_AS_CONTEXT_SWITCH] = "Blitter AS Context Switch Interrupt", | ||
| 80 | |||
| 81 | [VECS_MI_FLUSH_DW] = "Video Enhanced Streamer MI FLUSH DW notify", | ||
| 82 | [VECS_AS_CONTEXT_SWITCH] = "VECS Context Switch Interrupt", | ||
| 83 | |||
| 84 | [PIPE_A_FIFO_UNDERRUN] = "Pipe A FIFO underrun", | ||
| 85 | [PIPE_A_CRC_ERR] = "Pipe A CRC error", | ||
| 86 | [PIPE_A_CRC_DONE] = "Pipe A CRC done", | ||
| 87 | [PIPE_A_VSYNC] = "Pipe A vsync", | ||
| 88 | [PIPE_A_LINE_COMPARE] = "Pipe A line compare", | ||
| 89 | [PIPE_A_ODD_FIELD] = "Pipe A odd field", | ||
| 90 | [PIPE_A_EVEN_FIELD] = "Pipe A even field", | ||
| 91 | [PIPE_A_VBLANK] = "Pipe A vblank", | ||
| 92 | [PIPE_B_FIFO_UNDERRUN] = "Pipe B FIFO underrun", | ||
| 93 | [PIPE_B_CRC_ERR] = "Pipe B CRC error", | ||
| 94 | [PIPE_B_CRC_DONE] = "Pipe B CRC done", | ||
| 95 | [PIPE_B_VSYNC] = "Pipe B vsync", | ||
| 96 | [PIPE_B_LINE_COMPARE] = "Pipe B line compare", | ||
| 97 | [PIPE_B_ODD_FIELD] = "Pipe B odd field", | ||
| 98 | [PIPE_B_EVEN_FIELD] = "Pipe B even field", | ||
| 99 | [PIPE_B_VBLANK] = "Pipe B vblank", | ||
| 100 | [PIPE_C_VBLANK] = "Pipe C vblank", | ||
| 101 | [DPST_PHASE_IN] = "DPST phase in event", | ||
| 102 | [DPST_HISTOGRAM] = "DPST histogram event", | ||
| 103 | [GSE] = "GSE", | ||
| 104 | [DP_A_HOTPLUG] = "DP A Hotplug", | ||
| 105 | [AUX_CHANNEL_A] = "AUX Channel A", | ||
| 106 | [PERF_COUNTER] = "Performance counter", | ||
| 107 | [POISON] = "Poison", | ||
| 108 | [GTT_FAULT] = "GTT fault", | ||
| 109 | [PRIMARY_A_FLIP_DONE] = "Primary Plane A flip done", | ||
| 110 | [PRIMARY_B_FLIP_DONE] = "Primary Plane B flip done", | ||
| 111 | [PRIMARY_C_FLIP_DONE] = "Primary Plane C flip done", | ||
| 112 | [SPRITE_A_FLIP_DONE] = "Sprite Plane A flip done", | ||
| 113 | [SPRITE_B_FLIP_DONE] = "Sprite Plane B flip done", | ||
| 114 | [SPRITE_C_FLIP_DONE] = "Sprite Plane C flip done", | ||
| 115 | |||
| 116 | [PCU_THERMAL] = "PCU Thermal Event", | ||
| 117 | [PCU_PCODE2DRIVER_MAILBOX] = "PCU pcode2driver mailbox event", | ||
| 118 | |||
| 119 | [FDI_RX_INTERRUPTS_TRANSCODER_A] = "FDI RX Interrupts Combined A", | ||
| 120 | [AUDIO_CP_CHANGE_TRANSCODER_A] = "Audio CP Change Transcoder A", | ||
| 121 | [AUDIO_CP_REQUEST_TRANSCODER_A] = "Audio CP Request Transcoder A", | ||
| 122 | [FDI_RX_INTERRUPTS_TRANSCODER_B] = "FDI RX Interrupts Combined B", | ||
| 123 | [AUDIO_CP_CHANGE_TRANSCODER_B] = "Audio CP Change Transcoder B", | ||
| 124 | [AUDIO_CP_REQUEST_TRANSCODER_B] = "Audio CP Request Transcoder B", | ||
| 125 | [FDI_RX_INTERRUPTS_TRANSCODER_C] = "FDI RX Interrupts Combined C", | ||
| 126 | [AUDIO_CP_CHANGE_TRANSCODER_C] = "Audio CP Change Transcoder C", | ||
| 127 | [AUDIO_CP_REQUEST_TRANSCODER_C] = "Audio CP Request Transcoder C", | ||
| 128 | [ERR_AND_DBG] = "South Error and Debug Interupts Combined", | ||
| 129 | [GMBUS] = "Gmbus", | ||
| 130 | [SDVO_B_HOTPLUG] = "SDVO B hotplug", | ||
| 131 | [CRT_HOTPLUG] = "CRT Hotplug", | ||
| 132 | [DP_B_HOTPLUG] = "DisplayPort/HDMI/DVI B Hotplug", | ||
| 133 | [DP_C_HOTPLUG] = "DisplayPort/HDMI/DVI C Hotplug", | ||
| 134 | [DP_D_HOTPLUG] = "DisplayPort/HDMI/DVI D Hotplug", | ||
| 135 | [AUX_CHANNEL_B] = "AUX Channel B", | ||
| 136 | [AUX_CHANNEL_C] = "AUX Channel C", | ||
| 137 | [AUX_CHANNEL_D] = "AUX Channel D", | ||
| 138 | [AUDIO_POWER_STATE_CHANGE_B] = "Audio Power State change Port B", | ||
| 139 | [AUDIO_POWER_STATE_CHANGE_C] = "Audio Power State change Port C", | ||
| 140 | [AUDIO_POWER_STATE_CHANGE_D] = "Audio Power State change Port D", | ||
| 141 | |||
| 142 | [INTEL_GVT_EVENT_RESERVED] = "RESERVED EVENTS!!!", | ||
| 143 | }; | ||
| 144 | |||
| 145 | static inline struct intel_gvt_irq_info *regbase_to_irq_info( | ||
| 146 | struct intel_gvt *gvt, | ||
| 147 | unsigned int reg) | ||
| 148 | { | ||
| 149 | struct intel_gvt_irq *irq = &gvt->irq; | ||
| 150 | int i; | ||
| 151 | |||
| 152 | for_each_set_bit(i, irq->irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX) { | ||
| 153 | if (i915_mmio_reg_offset(irq->info[i]->reg_base) == reg) | ||
| 154 | return irq->info[i]; | ||
| 155 | } | ||
| 156 | |||
| 157 | return NULL; | ||
| 158 | } | ||
| 159 | |||
| 160 | /** | ||
| 161 | * intel_vgpu_reg_imr_handler - Generic IMR register emulation write handler | ||
| 162 | * @vgpu: a vGPU | ||
| 163 | * @reg: register offset written by guest | ||
| 164 | * @p_data: register data written by guest | ||
| 165 | * @bytes: register data length | ||
| 166 | * | ||
| 167 | * This function is used to emulate the generic IMR register bit change | ||
| 168 | * behavior. | ||
| 169 | * | ||
| 170 | * Returns: | ||
| 171 | * Zero on success, negative error code if failed. | ||
| 172 | * | ||
| 173 | */ | ||
| 174 | int intel_vgpu_reg_imr_handler(struct intel_vgpu *vgpu, | ||
| 175 | unsigned int reg, void *p_data, unsigned int bytes) | ||
| 176 | { | ||
| 177 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 178 | struct intel_gvt_irq_ops *ops = gvt->irq.ops; | ||
| 179 | u32 changed, masked, unmasked; | ||
| 180 | u32 imr = *(u32 *)p_data; | ||
| 181 | |||
| 182 | gvt_dbg_irq("write IMR %x with val %x\n", | ||
| 183 | reg, imr); | ||
| 184 | |||
| 185 | gvt_dbg_irq("old vIMR %x\n", vgpu_vreg(vgpu, reg)); | ||
| 186 | |||
| 187 | /* figure out newly masked/unmasked bits */ | ||
| 188 | changed = vgpu_vreg(vgpu, reg) ^ imr; | ||
| 189 | masked = (vgpu_vreg(vgpu, reg) & changed) ^ changed; | ||
| 190 | unmasked = masked ^ changed; | ||
| 191 | |||
| 192 | gvt_dbg_irq("changed %x, masked %x, unmasked %x\n", | ||
| 193 | changed, masked, unmasked); | ||
| 194 | |||
| 195 | vgpu_vreg(vgpu, reg) = imr; | ||
| 196 | |||
| 197 | ops->check_pending_irq(vgpu); | ||
| 198 | gvt_dbg_irq("IRQ: new vIMR %x\n", vgpu_vreg(vgpu, reg)); | ||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | |||
| 202 | /** | ||
| 203 | * intel_vgpu_reg_master_irq_handler - master IRQ write emulation handler | ||
| 204 | * @vgpu: a vGPU | ||
| 205 | * @reg: register offset written by guest | ||
| 206 | * @p_data: register data written by guest | ||
| 207 | * @bytes: register data length | ||
| 208 | * | ||
| 209 | * This function is used to emulate the master IRQ register on gen8+. | ||
| 210 | * | ||
| 211 | * Returns: | ||
| 212 | * Zero on success, negative error code if failed. | ||
| 213 | * | ||
| 214 | */ | ||
| 215 | int intel_vgpu_reg_master_irq_handler(struct intel_vgpu *vgpu, | ||
| 216 | unsigned int reg, void *p_data, unsigned int bytes) | ||
| 217 | { | ||
| 218 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 219 | struct intel_gvt_irq_ops *ops = gvt->irq.ops; | ||
| 220 | u32 changed, enabled, disabled; | ||
| 221 | u32 ier = *(u32 *)p_data; | ||
| 222 | u32 virtual_ier = vgpu_vreg(vgpu, reg); | ||
| 223 | |||
| 224 | gvt_dbg_irq("write master irq reg %x with val %x\n", | ||
| 225 | reg, ier); | ||
| 226 | |||
| 227 | gvt_dbg_irq("old vreg %x\n", vgpu_vreg(vgpu, reg)); | ||
| 228 | |||
| 229 | /* | ||
| 230 | * GEN8_MASTER_IRQ is a special irq register, | ||
| 231 | * only bit 31 is allowed to be modified | ||
| 232 | * and treated as an IER bit. | ||
| 233 | */ | ||
| 234 | ier &= GEN8_MASTER_IRQ_CONTROL; | ||
| 235 | virtual_ier &= GEN8_MASTER_IRQ_CONTROL; | ||
| 236 | vgpu_vreg(vgpu, reg) &= ~GEN8_MASTER_IRQ_CONTROL; | ||
| 237 | vgpu_vreg(vgpu, reg) |= ier; | ||
| 238 | |||
| 239 | /* figure out newly enabled/disable bits */ | ||
| 240 | changed = virtual_ier ^ ier; | ||
| 241 | enabled = (virtual_ier & changed) ^ changed; | ||
| 242 | disabled = enabled ^ changed; | ||
| 243 | |||
| 244 | gvt_dbg_irq("changed %x, enabled %x, disabled %x\n", | ||
| 245 | changed, enabled, disabled); | ||
| 246 | |||
| 247 | ops->check_pending_irq(vgpu); | ||
| 248 | gvt_dbg_irq("new vreg %x\n", vgpu_vreg(vgpu, reg)); | ||
| 249 | return 0; | ||
| 250 | } | ||
| 251 | |||
| 252 | /** | ||
| 253 | * intel_vgpu_reg_ier_handler - Generic IER write emulation handler | ||
| 254 | * @vgpu: a vGPU | ||
| 255 | * @reg: register offset written by guest | ||
| 256 | * @p_data: register data written by guest | ||
| 257 | * @bytes: register data length | ||
| 258 | * | ||
| 259 | * This function is used to emulate the generic IER register behavior. | ||
| 260 | * | ||
| 261 | * Returns: | ||
| 262 | * Zero on success, negative error code if failed. | ||
| 263 | * | ||
| 264 | */ | ||
| 265 | int intel_vgpu_reg_ier_handler(struct intel_vgpu *vgpu, | ||
| 266 | unsigned int reg, void *p_data, unsigned int bytes) | ||
| 267 | { | ||
| 268 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 269 | struct intel_gvt_irq_ops *ops = gvt->irq.ops; | ||
| 270 | struct intel_gvt_irq_info *info; | ||
| 271 | u32 changed, enabled, disabled; | ||
| 272 | u32 ier = *(u32 *)p_data; | ||
| 273 | |||
| 274 | gvt_dbg_irq("write IER %x with val %x\n", | ||
| 275 | reg, ier); | ||
| 276 | |||
| 277 | gvt_dbg_irq("old vIER %x\n", vgpu_vreg(vgpu, reg)); | ||
| 278 | |||
| 279 | /* figure out newly enabled/disable bits */ | ||
| 280 | changed = vgpu_vreg(vgpu, reg) ^ ier; | ||
| 281 | enabled = (vgpu_vreg(vgpu, reg) & changed) ^ changed; | ||
| 282 | disabled = enabled ^ changed; | ||
| 283 | |||
| 284 | gvt_dbg_irq("changed %x, enabled %x, disabled %x\n", | ||
| 285 | changed, enabled, disabled); | ||
| 286 | vgpu_vreg(vgpu, reg) = ier; | ||
| 287 | |||
| 288 | info = regbase_to_irq_info(gvt, ier_to_regbase(reg)); | ||
| 289 | if (WARN_ON(!info)) | ||
| 290 | return -EINVAL; | ||
| 291 | |||
| 292 | if (info->has_upstream_irq) | ||
| 293 | update_upstream_irq(vgpu, info); | ||
| 294 | |||
| 295 | ops->check_pending_irq(vgpu); | ||
| 296 | gvt_dbg_irq("new vIER %x\n", vgpu_vreg(vgpu, reg)); | ||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | |||
| 300 | /** | ||
| 301 | * intel_vgpu_reg_iir_handler - Generic IIR write emulation handler | ||
| 302 | * @vgpu: a vGPU | ||
| 303 | * @reg: register offset written by guest | ||
| 304 | * @p_data: register data written by guest | ||
| 305 | * @bytes: register data length | ||
| 306 | * | ||
| 307 | * This function is used to emulate the generic IIR register behavior. | ||
| 308 | * | ||
| 309 | * Returns: | ||
| 310 | * Zero on success, negative error code if failed. | ||
| 311 | * | ||
| 312 | */ | ||
| 313 | int intel_vgpu_reg_iir_handler(struct intel_vgpu *vgpu, unsigned int reg, | ||
| 314 | void *p_data, unsigned int bytes) | ||
| 315 | { | ||
| 316 | struct intel_gvt_irq_info *info = regbase_to_irq_info(vgpu->gvt, | ||
| 317 | iir_to_regbase(reg)); | ||
| 318 | u32 iir = *(u32 *)p_data; | ||
| 319 | |||
| 320 | gvt_dbg_irq("write IIR %x with val %x\n", reg, iir); | ||
| 321 | |||
| 322 | if (WARN_ON(!info)) | ||
| 323 | return -EINVAL; | ||
| 324 | |||
| 325 | vgpu_vreg(vgpu, reg) &= ~iir; | ||
| 326 | |||
| 327 | if (info->has_upstream_irq) | ||
| 328 | update_upstream_irq(vgpu, info); | ||
| 329 | return 0; | ||
| 330 | } | ||
| 331 | |||
| 332 | static struct intel_gvt_irq_map gen8_irq_map[] = { | ||
| 333 | { INTEL_GVT_IRQ_INFO_MASTER, 0, INTEL_GVT_IRQ_INFO_GT0, 0xffff }, | ||
| 334 | { INTEL_GVT_IRQ_INFO_MASTER, 1, INTEL_GVT_IRQ_INFO_GT0, 0xffff0000 }, | ||
| 335 | { INTEL_GVT_IRQ_INFO_MASTER, 2, INTEL_GVT_IRQ_INFO_GT1, 0xffff }, | ||
| 336 | { INTEL_GVT_IRQ_INFO_MASTER, 3, INTEL_GVT_IRQ_INFO_GT1, 0xffff0000 }, | ||
| 337 | { INTEL_GVT_IRQ_INFO_MASTER, 4, INTEL_GVT_IRQ_INFO_GT2, 0xffff }, | ||
| 338 | { INTEL_GVT_IRQ_INFO_MASTER, 6, INTEL_GVT_IRQ_INFO_GT3, 0xffff }, | ||
| 339 | { INTEL_GVT_IRQ_INFO_MASTER, 16, INTEL_GVT_IRQ_INFO_DE_PIPE_A, ~0 }, | ||
| 340 | { INTEL_GVT_IRQ_INFO_MASTER, 17, INTEL_GVT_IRQ_INFO_DE_PIPE_B, ~0 }, | ||
| 341 | { INTEL_GVT_IRQ_INFO_MASTER, 18, INTEL_GVT_IRQ_INFO_DE_PIPE_C, ~0 }, | ||
| 342 | { INTEL_GVT_IRQ_INFO_MASTER, 20, INTEL_GVT_IRQ_INFO_DE_PORT, ~0 }, | ||
| 343 | { INTEL_GVT_IRQ_INFO_MASTER, 22, INTEL_GVT_IRQ_INFO_DE_MISC, ~0 }, | ||
| 344 | { INTEL_GVT_IRQ_INFO_MASTER, 23, INTEL_GVT_IRQ_INFO_PCH, ~0 }, | ||
| 345 | { INTEL_GVT_IRQ_INFO_MASTER, 30, INTEL_GVT_IRQ_INFO_PCU, ~0 }, | ||
| 346 | { -1, -1, ~0 }, | ||
| 347 | }; | ||
| 348 | |||
| 349 | static void update_upstream_irq(struct intel_vgpu *vgpu, | ||
| 350 | struct intel_gvt_irq_info *info) | ||
| 351 | { | ||
| 352 | struct intel_gvt_irq *irq = &vgpu->gvt->irq; | ||
| 353 | struct intel_gvt_irq_map *map = irq->irq_map; | ||
| 354 | struct intel_gvt_irq_info *up_irq_info = NULL; | ||
| 355 | u32 set_bits = 0; | ||
| 356 | u32 clear_bits = 0; | ||
| 357 | int bit; | ||
| 358 | u32 val = vgpu_vreg(vgpu, | ||
| 359 | regbase_to_iir(i915_mmio_reg_offset(info->reg_base))) | ||
| 360 | & vgpu_vreg(vgpu, | ||
| 361 | regbase_to_ier(i915_mmio_reg_offset(info->reg_base))); | ||
| 362 | |||
| 363 | if (!info->has_upstream_irq) | ||
| 364 | return; | ||
| 365 | |||
| 366 | for (map = irq->irq_map; map->up_irq_bit != -1; map++) { | ||
| 367 | if (info->group != map->down_irq_group) | ||
| 368 | continue; | ||
| 369 | |||
| 370 | if (!up_irq_info) | ||
| 371 | up_irq_info = irq->info[map->up_irq_group]; | ||
| 372 | else | ||
| 373 | WARN_ON(up_irq_info != irq->info[map->up_irq_group]); | ||
| 374 | |||
| 375 | bit = map->up_irq_bit; | ||
| 376 | |||
| 377 | if (val & map->down_irq_bitmask) | ||
| 378 | set_bits |= (1 << bit); | ||
| 379 | else | ||
| 380 | clear_bits |= (1 << bit); | ||
| 381 | } | ||
| 382 | |||
| 383 | WARN_ON(!up_irq_info); | ||
| 384 | |||
| 385 | if (up_irq_info->group == INTEL_GVT_IRQ_INFO_MASTER) { | ||
| 386 | u32 isr = i915_mmio_reg_offset(up_irq_info->reg_base); | ||
| 387 | |||
| 388 | vgpu_vreg(vgpu, isr) &= ~clear_bits; | ||
| 389 | vgpu_vreg(vgpu, isr) |= set_bits; | ||
| 390 | } else { | ||
| 391 | u32 iir = regbase_to_iir( | ||
| 392 | i915_mmio_reg_offset(up_irq_info->reg_base)); | ||
| 393 | u32 imr = regbase_to_imr( | ||
| 394 | i915_mmio_reg_offset(up_irq_info->reg_base)); | ||
| 395 | |||
| 396 | vgpu_vreg(vgpu, iir) |= (set_bits & ~vgpu_vreg(vgpu, imr)); | ||
| 397 | } | ||
| 398 | |||
| 399 | if (up_irq_info->has_upstream_irq) | ||
| 400 | update_upstream_irq(vgpu, up_irq_info); | ||
| 401 | } | ||
| 402 | |||
| 403 | static void init_irq_map(struct intel_gvt_irq *irq) | ||
| 404 | { | ||
| 405 | struct intel_gvt_irq_map *map; | ||
| 406 | struct intel_gvt_irq_info *up_info, *down_info; | ||
| 407 | int up_bit; | ||
| 408 | |||
| 409 | for (map = irq->irq_map; map->up_irq_bit != -1; map++) { | ||
| 410 | up_info = irq->info[map->up_irq_group]; | ||
| 411 | up_bit = map->up_irq_bit; | ||
| 412 | down_info = irq->info[map->down_irq_group]; | ||
| 413 | |||
| 414 | set_bit(up_bit, up_info->downstream_irq_bitmap); | ||
| 415 | down_info->has_upstream_irq = true; | ||
| 416 | |||
| 417 | gvt_dbg_irq("[up] grp %d bit %d -> [down] grp %d bitmask %x\n", | ||
| 418 | up_info->group, up_bit, | ||
| 419 | down_info->group, map->down_irq_bitmask); | ||
| 420 | } | ||
| 421 | } | ||
| 422 | |||
| 423 | /* =======================vEvent injection===================== */ | ||
| 424 | static int inject_virtual_interrupt(struct intel_vgpu *vgpu) | ||
| 425 | { | ||
| 426 | return intel_gvt_hypervisor_inject_msi(vgpu); | ||
| 427 | } | ||
| 428 | |||
| 429 | static void propagate_event(struct intel_gvt_irq *irq, | ||
| 430 | enum intel_gvt_event_type event, struct intel_vgpu *vgpu) | ||
| 431 | { | ||
| 432 | struct intel_gvt_irq_info *info; | ||
| 433 | unsigned int reg_base; | ||
| 434 | int bit; | ||
| 435 | |||
| 436 | info = get_irq_info(irq, event); | ||
| 437 | if (WARN_ON(!info)) | ||
| 438 | return; | ||
| 439 | |||
| 440 | reg_base = i915_mmio_reg_offset(info->reg_base); | ||
| 441 | bit = irq->events[event].bit; | ||
| 442 | |||
| 443 | if (!test_bit(bit, (void *)&vgpu_vreg(vgpu, | ||
| 444 | regbase_to_imr(reg_base)))) { | ||
| 445 | gvt_dbg_irq("set bit (%d) for (%s) for vgpu (%d)\n", | ||
| 446 | bit, irq_name[event], vgpu->id); | ||
| 447 | set_bit(bit, (void *)&vgpu_vreg(vgpu, | ||
| 448 | regbase_to_iir(reg_base))); | ||
| 449 | } | ||
| 450 | } | ||
| 451 | |||
| 452 | /* =======================vEvent Handlers===================== */ | ||
| 453 | static void handle_default_event_virt(struct intel_gvt_irq *irq, | ||
| 454 | enum intel_gvt_event_type event, struct intel_vgpu *vgpu) | ||
| 455 | { | ||
| 456 | if (!vgpu->irq.irq_warn_once[event]) { | ||
| 457 | gvt_dbg_core("vgpu%d: IRQ receive event %d (%s)\n", | ||
| 458 | vgpu->id, event, irq_name[event]); | ||
| 459 | vgpu->irq.irq_warn_once[event] = true; | ||
| 460 | } | ||
| 461 | propagate_event(irq, event, vgpu); | ||
| 462 | } | ||
| 463 | |||
| 464 | /* =====================GEN specific logic======================= */ | ||
| 465 | /* GEN8 interrupt routines. */ | ||
| 466 | |||
| 467 | #define DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(regname, regbase) \ | ||
| 468 | static struct intel_gvt_irq_info gen8_##regname##_info = { \ | ||
| 469 | .name = #regname"-IRQ", \ | ||
| 470 | .reg_base = (regbase), \ | ||
| 471 | .bit_to_event = {[0 ... INTEL_GVT_IRQ_BITWIDTH-1] = \ | ||
| 472 | INTEL_GVT_EVENT_RESERVED}, \ | ||
| 473 | } | ||
| 474 | |||
| 475 | DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt0, GEN8_GT_ISR(0)); | ||
| 476 | DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt1, GEN8_GT_ISR(1)); | ||
| 477 | DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt2, GEN8_GT_ISR(2)); | ||
| 478 | DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(gt3, GEN8_GT_ISR(3)); | ||
| 479 | DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_a, GEN8_DE_PIPE_ISR(PIPE_A)); | ||
| 480 | DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_b, GEN8_DE_PIPE_ISR(PIPE_B)); | ||
| 481 | DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_pipe_c, GEN8_DE_PIPE_ISR(PIPE_C)); | ||
| 482 | DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_port, GEN8_DE_PORT_ISR); | ||
| 483 | DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(de_misc, GEN8_DE_MISC_ISR); | ||
| 484 | DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(pcu, GEN8_PCU_ISR); | ||
| 485 | DEFINE_GVT_GEN8_INTEL_GVT_IRQ_INFO(master, GEN8_MASTER_IRQ); | ||
| 486 | |||
| 487 | static struct intel_gvt_irq_info gvt_base_pch_info = { | ||
| 488 | .name = "PCH-IRQ", | ||
| 489 | .reg_base = SDEISR, | ||
| 490 | .bit_to_event = {[0 ... INTEL_GVT_IRQ_BITWIDTH-1] = | ||
| 491 | INTEL_GVT_EVENT_RESERVED}, | ||
| 492 | }; | ||
| 493 | |||
| 494 | static void gen8_check_pending_irq(struct intel_vgpu *vgpu) | ||
| 495 | { | ||
| 496 | struct intel_gvt_irq *irq = &vgpu->gvt->irq; | ||
| 497 | int i; | ||
| 498 | |||
| 499 | if (!(vgpu_vreg(vgpu, i915_mmio_reg_offset(GEN8_MASTER_IRQ)) & | ||
| 500 | GEN8_MASTER_IRQ_CONTROL)) | ||
| 501 | return; | ||
| 502 | |||
| 503 | for_each_set_bit(i, irq->irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX) { | ||
| 504 | struct intel_gvt_irq_info *info = irq->info[i]; | ||
| 505 | u32 reg_base; | ||
| 506 | |||
| 507 | if (!info->has_upstream_irq) | ||
| 508 | continue; | ||
| 509 | |||
| 510 | reg_base = i915_mmio_reg_offset(info->reg_base); | ||
| 511 | if ((vgpu_vreg(vgpu, regbase_to_iir(reg_base)) | ||
| 512 | & vgpu_vreg(vgpu, regbase_to_ier(reg_base)))) | ||
| 513 | update_upstream_irq(vgpu, info); | ||
| 514 | } | ||
| 515 | |||
| 516 | if (vgpu_vreg(vgpu, i915_mmio_reg_offset(GEN8_MASTER_IRQ)) | ||
| 517 | & ~GEN8_MASTER_IRQ_CONTROL) | ||
| 518 | inject_virtual_interrupt(vgpu); | ||
| 519 | } | ||
| 520 | |||
| 521 | static void gen8_init_irq( | ||
| 522 | struct intel_gvt_irq *irq) | ||
| 523 | { | ||
| 524 | struct intel_gvt *gvt = irq_to_gvt(irq); | ||
| 525 | |||
| 526 | #define SET_BIT_INFO(s, b, e, i) \ | ||
| 527 | do { \ | ||
| 528 | s->events[e].bit = b; \ | ||
| 529 | s->events[e].info = s->info[i]; \ | ||
| 530 | s->info[i]->bit_to_event[b] = e;\ | ||
| 531 | } while (0) | ||
| 532 | |||
| 533 | #define SET_IRQ_GROUP(s, g, i) \ | ||
| 534 | do { \ | ||
| 535 | s->info[g] = i; \ | ||
| 536 | (i)->group = g; \ | ||
| 537 | set_bit(g, s->irq_info_bitmap); \ | ||
| 538 | } while (0) | ||
| 539 | |||
| 540 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_MASTER, &gen8_master_info); | ||
| 541 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT0, &gen8_gt0_info); | ||
| 542 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT1, &gen8_gt1_info); | ||
| 543 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT2, &gen8_gt2_info); | ||
| 544 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_GT3, &gen8_gt3_info); | ||
| 545 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_A, &gen8_de_pipe_a_info); | ||
| 546 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_B, &gen8_de_pipe_b_info); | ||
| 547 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PIPE_C, &gen8_de_pipe_c_info); | ||
| 548 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_PORT, &gen8_de_port_info); | ||
| 549 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_DE_MISC, &gen8_de_misc_info); | ||
| 550 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_PCU, &gen8_pcu_info); | ||
| 551 | SET_IRQ_GROUP(irq, INTEL_GVT_IRQ_INFO_PCH, &gvt_base_pch_info); | ||
| 552 | |||
| 553 | /* GEN8 level 2 interrupts. */ | ||
| 554 | |||
| 555 | /* GEN8 interrupt GT0 events */ | ||
| 556 | SET_BIT_INFO(irq, 0, RCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT0); | ||
| 557 | SET_BIT_INFO(irq, 4, RCS_PIPE_CONTROL, INTEL_GVT_IRQ_INFO_GT0); | ||
| 558 | SET_BIT_INFO(irq, 8, RCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT0); | ||
| 559 | |||
| 560 | SET_BIT_INFO(irq, 16, BCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT0); | ||
| 561 | SET_BIT_INFO(irq, 20, BCS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT0); | ||
| 562 | SET_BIT_INFO(irq, 24, BCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT0); | ||
| 563 | |||
| 564 | /* GEN8 interrupt GT1 events */ | ||
| 565 | SET_BIT_INFO(irq, 0, VCS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT1); | ||
| 566 | SET_BIT_INFO(irq, 4, VCS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT1); | ||
| 567 | SET_BIT_INFO(irq, 8, VCS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT1); | ||
| 568 | |||
| 569 | if (HAS_BSD2(gvt->dev_priv)) { | ||
| 570 | SET_BIT_INFO(irq, 16, VCS2_MI_USER_INTERRUPT, | ||
| 571 | INTEL_GVT_IRQ_INFO_GT1); | ||
| 572 | SET_BIT_INFO(irq, 20, VCS2_MI_FLUSH_DW, | ||
| 573 | INTEL_GVT_IRQ_INFO_GT1); | ||
| 574 | SET_BIT_INFO(irq, 24, VCS2_AS_CONTEXT_SWITCH, | ||
| 575 | INTEL_GVT_IRQ_INFO_GT1); | ||
| 576 | } | ||
| 577 | |||
| 578 | /* GEN8 interrupt GT3 events */ | ||
| 579 | SET_BIT_INFO(irq, 0, VECS_MI_USER_INTERRUPT, INTEL_GVT_IRQ_INFO_GT3); | ||
| 580 | SET_BIT_INFO(irq, 4, VECS_MI_FLUSH_DW, INTEL_GVT_IRQ_INFO_GT3); | ||
| 581 | SET_BIT_INFO(irq, 8, VECS_AS_CONTEXT_SWITCH, INTEL_GVT_IRQ_INFO_GT3); | ||
| 582 | |||
| 583 | SET_BIT_INFO(irq, 0, PIPE_A_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_A); | ||
| 584 | SET_BIT_INFO(irq, 0, PIPE_B_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_B); | ||
| 585 | SET_BIT_INFO(irq, 0, PIPE_C_VBLANK, INTEL_GVT_IRQ_INFO_DE_PIPE_C); | ||
| 586 | |||
| 587 | /* GEN8 interrupt DE PORT events */ | ||
| 588 | SET_BIT_INFO(irq, 0, AUX_CHANNEL_A, INTEL_GVT_IRQ_INFO_DE_PORT); | ||
| 589 | SET_BIT_INFO(irq, 3, DP_A_HOTPLUG, INTEL_GVT_IRQ_INFO_DE_PORT); | ||
| 590 | |||
| 591 | /* GEN8 interrupt DE MISC events */ | ||
| 592 | SET_BIT_INFO(irq, 0, GSE, INTEL_GVT_IRQ_INFO_DE_MISC); | ||
| 593 | |||
| 594 | /* PCH events */ | ||
| 595 | SET_BIT_INFO(irq, 17, GMBUS, INTEL_GVT_IRQ_INFO_PCH); | ||
| 596 | SET_BIT_INFO(irq, 19, CRT_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH); | ||
| 597 | SET_BIT_INFO(irq, 21, DP_B_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH); | ||
| 598 | SET_BIT_INFO(irq, 22, DP_C_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH); | ||
| 599 | SET_BIT_INFO(irq, 23, DP_D_HOTPLUG, INTEL_GVT_IRQ_INFO_PCH); | ||
| 600 | |||
| 601 | if (IS_BROADWELL(gvt->dev_priv)) { | ||
| 602 | SET_BIT_INFO(irq, 25, AUX_CHANNEL_B, INTEL_GVT_IRQ_INFO_PCH); | ||
| 603 | SET_BIT_INFO(irq, 26, AUX_CHANNEL_C, INTEL_GVT_IRQ_INFO_PCH); | ||
| 604 | SET_BIT_INFO(irq, 27, AUX_CHANNEL_D, INTEL_GVT_IRQ_INFO_PCH); | ||
| 605 | |||
| 606 | SET_BIT_INFO(irq, 4, PRIMARY_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A); | ||
| 607 | SET_BIT_INFO(irq, 5, SPRITE_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A); | ||
| 608 | |||
| 609 | SET_BIT_INFO(irq, 4, PRIMARY_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B); | ||
| 610 | SET_BIT_INFO(irq, 5, SPRITE_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B); | ||
| 611 | |||
| 612 | SET_BIT_INFO(irq, 4, PRIMARY_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C); | ||
| 613 | SET_BIT_INFO(irq, 5, SPRITE_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C); | ||
| 614 | } else if (IS_SKYLAKE(gvt->dev_priv)) { | ||
| 615 | SET_BIT_INFO(irq, 25, AUX_CHANNEL_B, INTEL_GVT_IRQ_INFO_DE_PORT); | ||
| 616 | SET_BIT_INFO(irq, 26, AUX_CHANNEL_C, INTEL_GVT_IRQ_INFO_DE_PORT); | ||
| 617 | SET_BIT_INFO(irq, 27, AUX_CHANNEL_D, INTEL_GVT_IRQ_INFO_DE_PORT); | ||
| 618 | |||
| 619 | SET_BIT_INFO(irq, 3, PRIMARY_A_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_A); | ||
| 620 | SET_BIT_INFO(irq, 3, PRIMARY_B_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_B); | ||
| 621 | SET_BIT_INFO(irq, 3, PRIMARY_C_FLIP_DONE, INTEL_GVT_IRQ_INFO_DE_PIPE_C); | ||
| 622 | } | ||
| 623 | |||
| 624 | /* GEN8 interrupt PCU events */ | ||
| 625 | SET_BIT_INFO(irq, 24, PCU_THERMAL, INTEL_GVT_IRQ_INFO_PCU); | ||
| 626 | SET_BIT_INFO(irq, 25, PCU_PCODE2DRIVER_MAILBOX, INTEL_GVT_IRQ_INFO_PCU); | ||
| 627 | } | ||
| 628 | |||
| 629 | static struct intel_gvt_irq_ops gen8_irq_ops = { | ||
| 630 | .init_irq = gen8_init_irq, | ||
| 631 | .check_pending_irq = gen8_check_pending_irq, | ||
| 632 | }; | ||
| 633 | |||
| 634 | /** | ||
| 635 | * intel_vgpu_trigger_virtual_event - Trigger a virtual event for a vGPU | ||
| 636 | * @vgpu: a vGPU | ||
| 637 | * @event: interrupt event | ||
| 638 | * | ||
| 639 | * This function is used to trigger a virtual interrupt event for vGPU. | ||
| 640 | * The caller provides the event to be triggered, the framework itself | ||
| 641 | * will emulate the IRQ register bit change. | ||
| 642 | * | ||
| 643 | */ | ||
| 644 | void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu, | ||
| 645 | enum intel_gvt_event_type event) | ||
| 646 | { | ||
| 647 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 648 | struct intel_gvt_irq *irq = &gvt->irq; | ||
| 649 | gvt_event_virt_handler_t handler; | ||
| 650 | struct intel_gvt_irq_ops *ops = gvt->irq.ops; | ||
| 651 | |||
| 652 | handler = get_event_virt_handler(irq, event); | ||
| 653 | WARN_ON(!handler); | ||
| 654 | |||
| 655 | handler(irq, event, vgpu); | ||
| 656 | |||
| 657 | ops->check_pending_irq(vgpu); | ||
| 658 | } | ||
| 659 | |||
| 660 | static void init_events( | ||
| 661 | struct intel_gvt_irq *irq) | ||
| 662 | { | ||
| 663 | int i; | ||
| 664 | |||
| 665 | for (i = 0; i < INTEL_GVT_EVENT_MAX; i++) { | ||
| 666 | irq->events[i].info = NULL; | ||
| 667 | irq->events[i].v_handler = handle_default_event_virt; | ||
| 668 | } | ||
| 669 | } | ||
| 670 | |||
| 671 | static enum hrtimer_restart vblank_timer_fn(struct hrtimer *data) | ||
| 672 | { | ||
| 673 | struct intel_gvt_vblank_timer *vblank_timer; | ||
| 674 | struct intel_gvt_irq *irq; | ||
| 675 | struct intel_gvt *gvt; | ||
| 676 | |||
| 677 | vblank_timer = container_of(data, struct intel_gvt_vblank_timer, timer); | ||
| 678 | irq = container_of(vblank_timer, struct intel_gvt_irq, vblank_timer); | ||
| 679 | gvt = container_of(irq, struct intel_gvt, irq); | ||
| 680 | |||
| 681 | intel_gvt_request_service(gvt, INTEL_GVT_REQUEST_EMULATE_VBLANK); | ||
| 682 | hrtimer_add_expires_ns(&vblank_timer->timer, vblank_timer->period); | ||
| 683 | return HRTIMER_RESTART; | ||
| 684 | } | ||
| 685 | |||
| 686 | /** | ||
| 687 | * intel_gvt_clean_irq - clean up GVT-g IRQ emulation subsystem | ||
| 688 | * @gvt: a GVT device | ||
| 689 | * | ||
| 690 | * This function is called at driver unloading stage, to clean up GVT-g IRQ | ||
| 691 | * emulation subsystem. | ||
| 692 | * | ||
| 693 | */ | ||
| 694 | void intel_gvt_clean_irq(struct intel_gvt *gvt) | ||
| 695 | { | ||
| 696 | struct intel_gvt_irq *irq = &gvt->irq; | ||
| 697 | |||
| 698 | hrtimer_cancel(&irq->vblank_timer.timer); | ||
| 699 | } | ||
| 700 | |||
| 701 | #define VBLNAK_TIMER_PERIOD 16000000 | ||
| 702 | |||
| 703 | /** | ||
| 704 | * intel_gvt_init_irq - initialize GVT-g IRQ emulation subsystem | ||
| 705 | * @gvt: a GVT device | ||
| 706 | * | ||
| 707 | * This function is called at driver loading stage, to initialize the GVT-g IRQ | ||
| 708 | * emulation subsystem. | ||
| 709 | * | ||
| 710 | * Returns: | ||
| 711 | * Zero on success, negative error code if failed. | ||
| 712 | */ | ||
| 713 | int intel_gvt_init_irq(struct intel_gvt *gvt) | ||
| 714 | { | ||
| 715 | struct intel_gvt_irq *irq = &gvt->irq; | ||
| 716 | struct intel_gvt_vblank_timer *vblank_timer = &irq->vblank_timer; | ||
| 717 | |||
| 718 | gvt_dbg_core("init irq framework\n"); | ||
| 719 | |||
| 720 | if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv)) { | ||
| 721 | irq->ops = &gen8_irq_ops; | ||
| 722 | irq->irq_map = gen8_irq_map; | ||
| 723 | } else { | ||
| 724 | WARN_ON(1); | ||
| 725 | return -ENODEV; | ||
| 726 | } | ||
| 727 | |||
| 728 | /* common event initialization */ | ||
| 729 | init_events(irq); | ||
| 730 | |||
| 731 | /* gen specific initialization */ | ||
| 732 | irq->ops->init_irq(irq); | ||
| 733 | |||
| 734 | init_irq_map(irq); | ||
| 735 | |||
| 736 | hrtimer_init(&vblank_timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | ||
| 737 | vblank_timer->timer.function = vblank_timer_fn; | ||
| 738 | vblank_timer->period = VBLNAK_TIMER_PERIOD; | ||
| 739 | |||
| 740 | return 0; | ||
| 741 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/interrupt.h b/drivers/gpu/drm/i915/gvt/interrupt.h new file mode 100644 index 000000000000..5313fb1b33e1 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/interrupt.h | |||
| @@ -0,0 +1,233 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Kevin Tian <kevin.tian@intel.com> | ||
| 25 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Min he <min.he@intel.com> | ||
| 29 | * | ||
| 30 | */ | ||
| 31 | |||
| 32 | #ifndef _GVT_INTERRUPT_H_ | ||
| 33 | #define _GVT_INTERRUPT_H_ | ||
| 34 | |||
| 35 | enum intel_gvt_event_type { | ||
| 36 | RCS_MI_USER_INTERRUPT = 0, | ||
| 37 | RCS_DEBUG, | ||
| 38 | RCS_MMIO_SYNC_FLUSH, | ||
| 39 | RCS_CMD_STREAMER_ERR, | ||
| 40 | RCS_PIPE_CONTROL, | ||
| 41 | RCS_L3_PARITY_ERR, | ||
| 42 | RCS_WATCHDOG_EXCEEDED, | ||
| 43 | RCS_PAGE_DIRECTORY_FAULT, | ||
| 44 | RCS_AS_CONTEXT_SWITCH, | ||
| 45 | RCS_MONITOR_BUFF_HALF_FULL, | ||
| 46 | |||
| 47 | VCS_MI_USER_INTERRUPT, | ||
| 48 | VCS_MMIO_SYNC_FLUSH, | ||
| 49 | VCS_CMD_STREAMER_ERR, | ||
| 50 | VCS_MI_FLUSH_DW, | ||
| 51 | VCS_WATCHDOG_EXCEEDED, | ||
| 52 | VCS_PAGE_DIRECTORY_FAULT, | ||
| 53 | VCS_AS_CONTEXT_SWITCH, | ||
| 54 | |||
| 55 | VCS2_MI_USER_INTERRUPT, | ||
| 56 | VCS2_MI_FLUSH_DW, | ||
| 57 | VCS2_AS_CONTEXT_SWITCH, | ||
| 58 | |||
| 59 | BCS_MI_USER_INTERRUPT, | ||
| 60 | BCS_MMIO_SYNC_FLUSH, | ||
| 61 | BCS_CMD_STREAMER_ERR, | ||
| 62 | BCS_MI_FLUSH_DW, | ||
| 63 | BCS_PAGE_DIRECTORY_FAULT, | ||
| 64 | BCS_AS_CONTEXT_SWITCH, | ||
| 65 | |||
| 66 | VECS_MI_USER_INTERRUPT, | ||
| 67 | VECS_MI_FLUSH_DW, | ||
| 68 | VECS_AS_CONTEXT_SWITCH, | ||
| 69 | |||
| 70 | PIPE_A_FIFO_UNDERRUN, | ||
| 71 | PIPE_B_FIFO_UNDERRUN, | ||
| 72 | PIPE_A_CRC_ERR, | ||
| 73 | PIPE_B_CRC_ERR, | ||
| 74 | PIPE_A_CRC_DONE, | ||
| 75 | PIPE_B_CRC_DONE, | ||
| 76 | PIPE_A_ODD_FIELD, | ||
| 77 | PIPE_B_ODD_FIELD, | ||
| 78 | PIPE_A_EVEN_FIELD, | ||
| 79 | PIPE_B_EVEN_FIELD, | ||
| 80 | PIPE_A_LINE_COMPARE, | ||
| 81 | PIPE_B_LINE_COMPARE, | ||
| 82 | PIPE_C_LINE_COMPARE, | ||
| 83 | PIPE_A_VBLANK, | ||
| 84 | PIPE_B_VBLANK, | ||
| 85 | PIPE_C_VBLANK, | ||
| 86 | PIPE_A_VSYNC, | ||
| 87 | PIPE_B_VSYNC, | ||
| 88 | PIPE_C_VSYNC, | ||
| 89 | PRIMARY_A_FLIP_DONE, | ||
| 90 | PRIMARY_B_FLIP_DONE, | ||
| 91 | PRIMARY_C_FLIP_DONE, | ||
| 92 | SPRITE_A_FLIP_DONE, | ||
| 93 | SPRITE_B_FLIP_DONE, | ||
| 94 | SPRITE_C_FLIP_DONE, | ||
| 95 | |||
| 96 | PCU_THERMAL, | ||
| 97 | PCU_PCODE2DRIVER_MAILBOX, | ||
| 98 | |||
| 99 | DPST_PHASE_IN, | ||
| 100 | DPST_HISTOGRAM, | ||
| 101 | GSE, | ||
| 102 | DP_A_HOTPLUG, | ||
| 103 | AUX_CHANNEL_A, | ||
| 104 | PERF_COUNTER, | ||
| 105 | POISON, | ||
| 106 | GTT_FAULT, | ||
| 107 | ERROR_INTERRUPT_COMBINED, | ||
| 108 | |||
| 109 | FDI_RX_INTERRUPTS_TRANSCODER_A, | ||
| 110 | AUDIO_CP_CHANGE_TRANSCODER_A, | ||
| 111 | AUDIO_CP_REQUEST_TRANSCODER_A, | ||
| 112 | FDI_RX_INTERRUPTS_TRANSCODER_B, | ||
| 113 | AUDIO_CP_CHANGE_TRANSCODER_B, | ||
| 114 | AUDIO_CP_REQUEST_TRANSCODER_B, | ||
| 115 | FDI_RX_INTERRUPTS_TRANSCODER_C, | ||
| 116 | AUDIO_CP_CHANGE_TRANSCODER_C, | ||
| 117 | AUDIO_CP_REQUEST_TRANSCODER_C, | ||
| 118 | ERR_AND_DBG, | ||
| 119 | GMBUS, | ||
| 120 | SDVO_B_HOTPLUG, | ||
| 121 | CRT_HOTPLUG, | ||
| 122 | DP_B_HOTPLUG, | ||
| 123 | DP_C_HOTPLUG, | ||
| 124 | DP_D_HOTPLUG, | ||
| 125 | AUX_CHANNEL_B, | ||
| 126 | AUX_CHANNEL_C, | ||
| 127 | AUX_CHANNEL_D, | ||
| 128 | AUDIO_POWER_STATE_CHANGE_B, | ||
| 129 | AUDIO_POWER_STATE_CHANGE_C, | ||
| 130 | AUDIO_POWER_STATE_CHANGE_D, | ||
| 131 | |||
| 132 | INTEL_GVT_EVENT_RESERVED, | ||
| 133 | INTEL_GVT_EVENT_MAX, | ||
| 134 | }; | ||
| 135 | |||
| 136 | struct intel_gvt_irq; | ||
| 137 | struct intel_gvt; | ||
| 138 | |||
| 139 | typedef void (*gvt_event_virt_handler_t)(struct intel_gvt_irq *irq, | ||
| 140 | enum intel_gvt_event_type event, struct intel_vgpu *vgpu); | ||
| 141 | |||
| 142 | struct intel_gvt_irq_ops { | ||
| 143 | void (*init_irq)(struct intel_gvt_irq *irq); | ||
| 144 | void (*check_pending_irq)(struct intel_vgpu *vgpu); | ||
| 145 | }; | ||
| 146 | |||
| 147 | /* the list of physical interrupt control register groups */ | ||
| 148 | enum intel_gvt_irq_type { | ||
| 149 | INTEL_GVT_IRQ_INFO_GT, | ||
| 150 | INTEL_GVT_IRQ_INFO_DPY, | ||
| 151 | INTEL_GVT_IRQ_INFO_PCH, | ||
| 152 | INTEL_GVT_IRQ_INFO_PM, | ||
| 153 | |||
| 154 | INTEL_GVT_IRQ_INFO_MASTER, | ||
| 155 | INTEL_GVT_IRQ_INFO_GT0, | ||
| 156 | INTEL_GVT_IRQ_INFO_GT1, | ||
| 157 | INTEL_GVT_IRQ_INFO_GT2, | ||
| 158 | INTEL_GVT_IRQ_INFO_GT3, | ||
| 159 | INTEL_GVT_IRQ_INFO_DE_PIPE_A, | ||
| 160 | INTEL_GVT_IRQ_INFO_DE_PIPE_B, | ||
| 161 | INTEL_GVT_IRQ_INFO_DE_PIPE_C, | ||
| 162 | INTEL_GVT_IRQ_INFO_DE_PORT, | ||
| 163 | INTEL_GVT_IRQ_INFO_DE_MISC, | ||
| 164 | INTEL_GVT_IRQ_INFO_AUD, | ||
| 165 | INTEL_GVT_IRQ_INFO_PCU, | ||
| 166 | |||
| 167 | INTEL_GVT_IRQ_INFO_MAX, | ||
| 168 | }; | ||
| 169 | |||
| 170 | #define INTEL_GVT_IRQ_BITWIDTH 32 | ||
| 171 | |||
| 172 | /* device specific interrupt bit definitions */ | ||
| 173 | struct intel_gvt_irq_info { | ||
| 174 | char *name; | ||
| 175 | i915_reg_t reg_base; | ||
| 176 | enum intel_gvt_event_type bit_to_event[INTEL_GVT_IRQ_BITWIDTH]; | ||
| 177 | unsigned long warned; | ||
| 178 | int group; | ||
| 179 | DECLARE_BITMAP(downstream_irq_bitmap, INTEL_GVT_IRQ_BITWIDTH); | ||
| 180 | bool has_upstream_irq; | ||
| 181 | }; | ||
| 182 | |||
| 183 | /* per-event information */ | ||
| 184 | struct intel_gvt_event_info { | ||
| 185 | int bit; /* map to register bit */ | ||
| 186 | int policy; /* forwarding policy */ | ||
| 187 | struct intel_gvt_irq_info *info; /* register info */ | ||
| 188 | gvt_event_virt_handler_t v_handler; /* for v_event */ | ||
| 189 | }; | ||
| 190 | |||
| 191 | struct intel_gvt_irq_map { | ||
| 192 | int up_irq_group; | ||
| 193 | int up_irq_bit; | ||
| 194 | int down_irq_group; | ||
| 195 | u32 down_irq_bitmask; | ||
| 196 | }; | ||
| 197 | |||
| 198 | struct intel_gvt_vblank_timer { | ||
| 199 | struct hrtimer timer; | ||
| 200 | u64 period; | ||
| 201 | }; | ||
| 202 | |||
| 203 | /* structure containing device specific IRQ state */ | ||
| 204 | struct intel_gvt_irq { | ||
| 205 | struct intel_gvt_irq_ops *ops; | ||
| 206 | struct intel_gvt_irq_info *info[INTEL_GVT_IRQ_INFO_MAX]; | ||
| 207 | DECLARE_BITMAP(irq_info_bitmap, INTEL_GVT_IRQ_INFO_MAX); | ||
| 208 | struct intel_gvt_event_info events[INTEL_GVT_EVENT_MAX]; | ||
| 209 | DECLARE_BITMAP(pending_events, INTEL_GVT_EVENT_MAX); | ||
| 210 | struct intel_gvt_irq_map *irq_map; | ||
| 211 | struct intel_gvt_vblank_timer vblank_timer; | ||
| 212 | }; | ||
| 213 | |||
| 214 | int intel_gvt_init_irq(struct intel_gvt *gvt); | ||
| 215 | void intel_gvt_clean_irq(struct intel_gvt *gvt); | ||
| 216 | |||
| 217 | void intel_vgpu_trigger_virtual_event(struct intel_vgpu *vgpu, | ||
| 218 | enum intel_gvt_event_type event); | ||
| 219 | |||
| 220 | int intel_vgpu_reg_iir_handler(struct intel_vgpu *vgpu, unsigned int reg, | ||
| 221 | void *p_data, unsigned int bytes); | ||
| 222 | int intel_vgpu_reg_ier_handler(struct intel_vgpu *vgpu, | ||
| 223 | unsigned int reg, void *p_data, unsigned int bytes); | ||
| 224 | int intel_vgpu_reg_master_irq_handler(struct intel_vgpu *vgpu, | ||
| 225 | unsigned int reg, void *p_data, unsigned int bytes); | ||
| 226 | int intel_vgpu_reg_imr_handler(struct intel_vgpu *vgpu, | ||
| 227 | unsigned int reg, void *p_data, unsigned int bytes); | ||
| 228 | |||
| 229 | int gvt_ring_id_to_pipe_control_notify_event(int ring_id); | ||
| 230 | int gvt_ring_id_to_mi_flush_dw_event(int ring_id); | ||
| 231 | int gvt_ring_id_to_mi_user_interrupt_event(int ring_id); | ||
| 232 | |||
| 233 | #endif /* _GVT_INTERRUPT_H_ */ | ||
diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c new file mode 100644 index 000000000000..585b01f63254 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/mmio.c | |||
| @@ -0,0 +1,306 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Ke Yu | ||
| 25 | * Kevin Tian <kevin.tian@intel.com> | ||
| 26 | * Dexuan Cui | ||
| 27 | * | ||
| 28 | * Contributors: | ||
| 29 | * Tina Zhang <tina.zhang@intel.com> | ||
| 30 | * Min He <min.he@intel.com> | ||
| 31 | * Niu Bing <bing.niu@intel.com> | ||
| 32 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | #include "i915_drv.h" | ||
| 37 | #include "gvt.h" | ||
| 38 | |||
| 39 | /** | ||
| 40 | * intel_vgpu_gpa_to_mmio_offset - translate a GPA to MMIO offset | ||
| 41 | * @vgpu: a vGPU | ||
| 42 | * | ||
| 43 | * Returns: | ||
| 44 | * Zero on success, negative error code if failed | ||
| 45 | */ | ||
| 46 | int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa) | ||
| 47 | { | ||
| 48 | u64 gttmmio_gpa = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0) & | ||
| 49 | ~GENMASK(3, 0); | ||
| 50 | return gpa - gttmmio_gpa; | ||
| 51 | } | ||
| 52 | |||
| 53 | #define reg_is_mmio(gvt, reg) \ | ||
| 54 | (reg >= 0 && reg < gvt->device_info.mmio_size) | ||
| 55 | |||
| 56 | #define reg_is_gtt(gvt, reg) \ | ||
| 57 | (reg >= gvt->device_info.gtt_start_offset \ | ||
| 58 | && reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt)) | ||
| 59 | |||
| 60 | /** | ||
| 61 | * intel_vgpu_emulate_mmio_read - emulate MMIO read | ||
| 62 | * @vgpu: a vGPU | ||
| 63 | * @pa: guest physical address | ||
| 64 | * @p_data: data return buffer | ||
| 65 | * @bytes: access data length | ||
| 66 | * | ||
| 67 | * Returns: | ||
| 68 | * Zero on success, negative error code if failed | ||
| 69 | */ | ||
| 70 | int intel_vgpu_emulate_mmio_read(void *__vgpu, uint64_t pa, | ||
| 71 | void *p_data, unsigned int bytes) | ||
| 72 | { | ||
| 73 | struct intel_vgpu *vgpu = __vgpu; | ||
| 74 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 75 | struct intel_gvt_mmio_info *mmio; | ||
| 76 | unsigned int offset = 0; | ||
| 77 | int ret = -EINVAL; | ||
| 78 | |||
| 79 | mutex_lock(&gvt->lock); | ||
| 80 | |||
| 81 | if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { | ||
| 82 | struct intel_vgpu_guest_page *gp; | ||
| 83 | |||
| 84 | gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT); | ||
| 85 | if (gp) { | ||
| 86 | ret = intel_gvt_hypervisor_read_gpa(vgpu, pa, | ||
| 87 | p_data, bytes); | ||
| 88 | if (ret) { | ||
| 89 | gvt_err("vgpu%d: guest page read error %d, " | ||
| 90 | "gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n", | ||
| 91 | vgpu->id, ret, | ||
| 92 | gp->gfn, pa, *(u32 *)p_data, bytes); | ||
| 93 | } | ||
| 94 | mutex_unlock(&gvt->lock); | ||
| 95 | return ret; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa); | ||
| 100 | |||
| 101 | if (WARN_ON(bytes > 8)) | ||
| 102 | goto err; | ||
| 103 | |||
| 104 | if (reg_is_gtt(gvt, offset)) { | ||
| 105 | if (WARN_ON(!IS_ALIGNED(offset, 4) && !IS_ALIGNED(offset, 8))) | ||
| 106 | goto err; | ||
| 107 | if (WARN_ON(bytes != 4 && bytes != 8)) | ||
| 108 | goto err; | ||
| 109 | if (WARN_ON(!reg_is_gtt(gvt, offset + bytes - 1))) | ||
| 110 | goto err; | ||
| 111 | |||
| 112 | ret = intel_vgpu_emulate_gtt_mmio_read(vgpu, offset, | ||
| 113 | p_data, bytes); | ||
| 114 | if (ret) | ||
| 115 | goto err; | ||
| 116 | mutex_unlock(&gvt->lock); | ||
| 117 | return ret; | ||
| 118 | } | ||
| 119 | |||
| 120 | if (WARN_ON_ONCE(!reg_is_mmio(gvt, offset))) { | ||
| 121 | ret = intel_gvt_hypervisor_read_gpa(vgpu, pa, p_data, bytes); | ||
| 122 | mutex_unlock(&gvt->lock); | ||
| 123 | return ret; | ||
| 124 | } | ||
| 125 | |||
| 126 | if (WARN_ON(!reg_is_mmio(gvt, offset + bytes - 1))) | ||
| 127 | goto err; | ||
| 128 | |||
| 129 | mmio = intel_gvt_find_mmio_info(gvt, rounddown(offset, 4)); | ||
| 130 | if (!mmio && !vgpu->mmio.disable_warn_untrack) { | ||
| 131 | gvt_err("vgpu%d: read untracked MMIO %x len %d val %x\n", | ||
| 132 | vgpu->id, offset, bytes, *(u32 *)p_data); | ||
| 133 | |||
| 134 | if (offset == 0x206c) { | ||
| 135 | gvt_err("------------------------------------------\n"); | ||
| 136 | gvt_err("vgpu%d: likely triggers a gfx reset\n", | ||
| 137 | vgpu->id); | ||
| 138 | gvt_err("------------------------------------------\n"); | ||
| 139 | vgpu->mmio.disable_warn_untrack = true; | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | if (!intel_gvt_mmio_is_unalign(gvt, offset)) { | ||
| 144 | if (WARN_ON(!IS_ALIGNED(offset, bytes))) | ||
| 145 | goto err; | ||
| 146 | } | ||
| 147 | |||
| 148 | if (mmio) { | ||
| 149 | if (!intel_gvt_mmio_is_unalign(gvt, mmio->offset)) { | ||
| 150 | if (WARN_ON(offset + bytes > mmio->offset + mmio->size)) | ||
| 151 | goto err; | ||
| 152 | if (WARN_ON(mmio->offset != offset)) | ||
| 153 | goto err; | ||
| 154 | } | ||
| 155 | ret = mmio->read(vgpu, offset, p_data, bytes); | ||
| 156 | } else | ||
| 157 | ret = intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes); | ||
| 158 | |||
| 159 | if (ret) | ||
| 160 | goto err; | ||
| 161 | |||
| 162 | intel_gvt_mmio_set_accessed(gvt, offset); | ||
| 163 | mutex_unlock(&gvt->lock); | ||
| 164 | return 0; | ||
| 165 | err: | ||
| 166 | gvt_err("vgpu%d: fail to emulate MMIO read %08x len %d\n", | ||
| 167 | vgpu->id, offset, bytes); | ||
| 168 | mutex_unlock(&gvt->lock); | ||
| 169 | return ret; | ||
| 170 | } | ||
| 171 | |||
| 172 | /** | ||
| 173 | * intel_vgpu_emulate_mmio_write - emulate MMIO write | ||
| 174 | * @vgpu: a vGPU | ||
| 175 | * @pa: guest physical address | ||
| 176 | * @p_data: write data buffer | ||
| 177 | * @bytes: access data length | ||
| 178 | * | ||
| 179 | * Returns: | ||
| 180 | * Zero on success, negative error code if failed | ||
| 181 | */ | ||
| 182 | int intel_vgpu_emulate_mmio_write(void *__vgpu, uint64_t pa, | ||
| 183 | void *p_data, unsigned int bytes) | ||
| 184 | { | ||
| 185 | struct intel_vgpu *vgpu = __vgpu; | ||
| 186 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 187 | struct intel_gvt_mmio_info *mmio; | ||
| 188 | unsigned int offset = 0; | ||
| 189 | u32 old_vreg = 0, old_sreg = 0; | ||
| 190 | int ret = -EINVAL; | ||
| 191 | |||
| 192 | mutex_lock(&gvt->lock); | ||
| 193 | |||
| 194 | if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { | ||
| 195 | struct intel_vgpu_guest_page *gp; | ||
| 196 | |||
| 197 | gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT); | ||
| 198 | if (gp) { | ||
| 199 | ret = gp->handler(gp, pa, p_data, bytes); | ||
| 200 | if (ret) { | ||
| 201 | gvt_err("vgpu%d: guest page write error %d, " | ||
| 202 | "gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n", | ||
| 203 | vgpu->id, ret, | ||
| 204 | gp->gfn, pa, *(u32 *)p_data, bytes); | ||
| 205 | } | ||
| 206 | mutex_unlock(&gvt->lock); | ||
| 207 | return ret; | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa); | ||
| 212 | |||
| 213 | if (WARN_ON(bytes > 8)) | ||
| 214 | goto err; | ||
| 215 | |||
| 216 | if (reg_is_gtt(gvt, offset)) { | ||
| 217 | if (WARN_ON(!IS_ALIGNED(offset, 4) && !IS_ALIGNED(offset, 8))) | ||
| 218 | goto err; | ||
| 219 | if (WARN_ON(bytes != 4 && bytes != 8)) | ||
| 220 | goto err; | ||
| 221 | if (WARN_ON(!reg_is_gtt(gvt, offset + bytes - 1))) | ||
| 222 | goto err; | ||
| 223 | |||
| 224 | ret = intel_vgpu_emulate_gtt_mmio_write(vgpu, offset, | ||
| 225 | p_data, bytes); | ||
| 226 | if (ret) | ||
| 227 | goto err; | ||
| 228 | mutex_unlock(&gvt->lock); | ||
| 229 | return ret; | ||
| 230 | } | ||
| 231 | |||
| 232 | if (WARN_ON_ONCE(!reg_is_mmio(gvt, offset))) { | ||
| 233 | ret = intel_gvt_hypervisor_write_gpa(vgpu, pa, p_data, bytes); | ||
| 234 | mutex_unlock(&gvt->lock); | ||
| 235 | return ret; | ||
| 236 | } | ||
| 237 | |||
| 238 | mmio = intel_gvt_find_mmio_info(gvt, rounddown(offset, 4)); | ||
| 239 | if (!mmio && !vgpu->mmio.disable_warn_untrack) | ||
| 240 | gvt_err("vgpu%d: write untracked MMIO %x len %d val %x\n", | ||
| 241 | vgpu->id, offset, bytes, *(u32 *)p_data); | ||
| 242 | |||
| 243 | if (!intel_gvt_mmio_is_unalign(gvt, offset)) { | ||
| 244 | if (WARN_ON(!IS_ALIGNED(offset, bytes))) | ||
| 245 | goto err; | ||
| 246 | } | ||
| 247 | |||
| 248 | if (mmio) { | ||
| 249 | u64 ro_mask = mmio->ro_mask; | ||
| 250 | |||
| 251 | if (!intel_gvt_mmio_is_unalign(gvt, mmio->offset)) { | ||
| 252 | if (WARN_ON(offset + bytes > mmio->offset + mmio->size)) | ||
| 253 | goto err; | ||
| 254 | if (WARN_ON(mmio->offset != offset)) | ||
| 255 | goto err; | ||
| 256 | } | ||
| 257 | |||
| 258 | if (intel_gvt_mmio_has_mode_mask(gvt, mmio->offset)) { | ||
| 259 | old_vreg = vgpu_vreg(vgpu, offset); | ||
| 260 | old_sreg = vgpu_sreg(vgpu, offset); | ||
| 261 | } | ||
| 262 | |||
| 263 | if (!ro_mask) { | ||
| 264 | ret = mmio->write(vgpu, offset, p_data, bytes); | ||
| 265 | } else { | ||
| 266 | /* Protect RO bits like HW */ | ||
| 267 | u64 data = 0; | ||
| 268 | |||
| 269 | /* all register bits are RO. */ | ||
| 270 | if (ro_mask == ~(u64)0) { | ||
| 271 | gvt_err("vgpu%d: try to write RO reg %x\n", | ||
| 272 | vgpu->id, offset); | ||
| 273 | ret = 0; | ||
| 274 | goto out; | ||
| 275 | } | ||
| 276 | /* keep the RO bits in the virtual register */ | ||
| 277 | memcpy(&data, p_data, bytes); | ||
| 278 | data &= ~mmio->ro_mask; | ||
| 279 | data |= vgpu_vreg(vgpu, offset) & mmio->ro_mask; | ||
| 280 | ret = mmio->write(vgpu, offset, &data, bytes); | ||
| 281 | } | ||
| 282 | |||
| 283 | /* higher 16bits of mode ctl regs are mask bits for change */ | ||
| 284 | if (intel_gvt_mmio_has_mode_mask(gvt, mmio->offset)) { | ||
| 285 | u32 mask = vgpu_vreg(vgpu, offset) >> 16; | ||
| 286 | |||
| 287 | vgpu_vreg(vgpu, offset) = (old_vreg & ~mask) | ||
| 288 | | (vgpu_vreg(vgpu, offset) & mask); | ||
| 289 | vgpu_sreg(vgpu, offset) = (old_sreg & ~mask) | ||
| 290 | | (vgpu_sreg(vgpu, offset) & mask); | ||
| 291 | } | ||
| 292 | } else | ||
| 293 | ret = intel_vgpu_default_mmio_write(vgpu, offset, p_data, | ||
| 294 | bytes); | ||
| 295 | if (ret) | ||
| 296 | goto err; | ||
| 297 | out: | ||
| 298 | intel_gvt_mmio_set_accessed(gvt, offset); | ||
| 299 | mutex_unlock(&gvt->lock); | ||
| 300 | return 0; | ||
| 301 | err: | ||
| 302 | gvt_err("vgpu%d: fail to emulate MMIO write %08x len %d\n", | ||
| 303 | vgpu->id, offset, bytes); | ||
| 304 | mutex_unlock(&gvt->lock); | ||
| 305 | return ret; | ||
| 306 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/mmio.h b/drivers/gpu/drm/i915/gvt/mmio.h new file mode 100644 index 000000000000..9dc739a01892 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/mmio.h | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Ke Yu | ||
| 25 | * Kevin Tian <kevin.tian@intel.com> | ||
| 26 | * Dexuan Cui | ||
| 27 | * | ||
| 28 | * Contributors: | ||
| 29 | * Tina Zhang <tina.zhang@intel.com> | ||
| 30 | * Min He <min.he@intel.com> | ||
| 31 | * Niu Bing <bing.niu@intel.com> | ||
| 32 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | #ifndef _GVT_MMIO_H_ | ||
| 37 | #define _GVT_MMIO_H_ | ||
| 38 | |||
| 39 | struct intel_gvt; | ||
| 40 | struct intel_vgpu; | ||
| 41 | |||
| 42 | #define D_SNB (1 << 0) | ||
| 43 | #define D_IVB (1 << 1) | ||
| 44 | #define D_HSW (1 << 2) | ||
| 45 | #define D_BDW (1 << 3) | ||
| 46 | #define D_SKL (1 << 4) | ||
| 47 | |||
| 48 | #define D_GEN9PLUS (D_SKL) | ||
| 49 | #define D_GEN8PLUS (D_BDW | D_SKL) | ||
| 50 | #define D_GEN75PLUS (D_HSW | D_BDW | D_SKL) | ||
| 51 | #define D_GEN7PLUS (D_IVB | D_HSW | D_BDW | D_SKL) | ||
| 52 | |||
| 53 | #define D_SKL_PLUS (D_SKL) | ||
| 54 | #define D_BDW_PLUS (D_BDW | D_SKL) | ||
| 55 | #define D_HSW_PLUS (D_HSW | D_BDW | D_SKL) | ||
| 56 | #define D_IVB_PLUS (D_IVB | D_HSW | D_BDW | D_SKL) | ||
| 57 | |||
| 58 | #define D_PRE_BDW (D_SNB | D_IVB | D_HSW) | ||
| 59 | #define D_PRE_SKL (D_SNB | D_IVB | D_HSW | D_BDW) | ||
| 60 | #define D_ALL (D_SNB | D_IVB | D_HSW | D_BDW | D_SKL) | ||
| 61 | |||
| 62 | struct intel_gvt_mmio_info { | ||
| 63 | u32 offset; | ||
| 64 | u32 size; | ||
| 65 | u32 length; | ||
| 66 | u32 addr_mask; | ||
| 67 | u64 ro_mask; | ||
| 68 | u32 device; | ||
| 69 | int (*read)(struct intel_vgpu *, unsigned int, void *, unsigned int); | ||
| 70 | int (*write)(struct intel_vgpu *, unsigned int, void *, unsigned int); | ||
| 71 | u32 addr_range; | ||
| 72 | struct hlist_node node; | ||
| 73 | }; | ||
| 74 | |||
| 75 | unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt); | ||
| 76 | bool intel_gvt_match_device(struct intel_gvt *gvt, unsigned long device); | ||
| 77 | |||
| 78 | int intel_gvt_setup_mmio_info(struct intel_gvt *gvt); | ||
| 79 | void intel_gvt_clean_mmio_info(struct intel_gvt *gvt); | ||
| 80 | |||
| 81 | struct intel_gvt_mmio_info *intel_gvt_find_mmio_info(struct intel_gvt *gvt, | ||
| 82 | unsigned int offset); | ||
| 83 | #define INTEL_GVT_MMIO_OFFSET(reg) ({ \ | ||
| 84 | typeof(reg) __reg = reg; \ | ||
| 85 | u32 *offset = (u32 *)&__reg; \ | ||
| 86 | *offset; \ | ||
| 87 | }) | ||
| 88 | |||
| 89 | int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa); | ||
| 90 | int intel_vgpu_emulate_mmio_read(void *__vgpu, u64 pa, void *p_data, | ||
| 91 | unsigned int bytes); | ||
| 92 | int intel_vgpu_emulate_mmio_write(void *__vgpu, u64 pa, void *p_data, | ||
| 93 | unsigned int bytes); | ||
| 94 | bool intel_gvt_mmio_is_cmd_access(struct intel_gvt *gvt, | ||
| 95 | unsigned int offset); | ||
| 96 | bool intel_gvt_mmio_is_unalign(struct intel_gvt *gvt, unsigned int offset); | ||
| 97 | void intel_gvt_mmio_set_accessed(struct intel_gvt *gvt, unsigned int offset); | ||
| 98 | void intel_gvt_mmio_set_cmd_accessed(struct intel_gvt *gvt, | ||
| 99 | unsigned int offset); | ||
| 100 | bool intel_gvt_mmio_has_mode_mask(struct intel_gvt *gvt, unsigned int offset); | ||
| 101 | int intel_vgpu_default_mmio_read(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 102 | void *p_data, unsigned int bytes); | ||
| 103 | int intel_vgpu_default_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, | ||
| 104 | void *p_data, unsigned int bytes); | ||
| 105 | #endif | ||
diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h index 03601e3ffa7c..67858782d327 100644 --- a/drivers/gpu/drm/i915/gvt/mpt.h +++ b/drivers/gpu/drm/i915/gvt/mpt.h | |||
| @@ -19,6 +19,15 @@ | |||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 21 | * SOFTWARE. | 21 | * SOFTWARE. |
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Eddie Dong <eddie.dong@intel.com> | ||
| 25 | * Dexuan Cui | ||
| 26 | * Jike Song <jike.song@intel.com> | ||
| 27 | * | ||
| 28 | * Contributors: | ||
| 29 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 30 | * | ||
| 22 | */ | 31 | */ |
| 23 | 32 | ||
| 24 | #ifndef _GVT_MPT_H_ | 33 | #ifndef _GVT_MPT_H_ |
| @@ -46,4 +55,215 @@ static inline int intel_gvt_hypervisor_detect_host(void) | |||
| 46 | return intel_gvt_host.mpt->detect_host(); | 55 | return intel_gvt_host.mpt->detect_host(); |
| 47 | } | 56 | } |
| 48 | 57 | ||
| 58 | /** | ||
| 59 | * intel_gvt_hypervisor_attach_vgpu - call hypervisor to initialize vGPU | ||
| 60 | * related stuffs inside hypervisor. | ||
| 61 | * | ||
| 62 | * Returns: | ||
| 63 | * Zero on success, negative error code if failed. | ||
| 64 | */ | ||
| 65 | static inline int intel_gvt_hypervisor_attach_vgpu(struct intel_vgpu *vgpu) | ||
| 66 | { | ||
| 67 | return intel_gvt_host.mpt->attach_vgpu(vgpu, &vgpu->handle); | ||
| 68 | } | ||
| 69 | |||
| 70 | /** | ||
| 71 | * intel_gvt_hypervisor_detach_vgpu - call hypervisor to release vGPU | ||
| 72 | * related stuffs inside hypervisor. | ||
| 73 | * | ||
| 74 | * Returns: | ||
| 75 | * Zero on success, negative error code if failed. | ||
| 76 | */ | ||
| 77 | static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu) | ||
| 78 | { | ||
| 79 | intel_gvt_host.mpt->detach_vgpu(vgpu->handle); | ||
| 80 | } | ||
| 81 | |||
| 82 | #define MSI_CAP_CONTROL(offset) (offset + 2) | ||
| 83 | #define MSI_CAP_ADDRESS(offset) (offset + 4) | ||
| 84 | #define MSI_CAP_DATA(offset) (offset + 8) | ||
| 85 | #define MSI_CAP_EN 0x1 | ||
| 86 | |||
| 87 | /** | ||
| 88 | * intel_gvt_hypervisor_inject_msi - inject a MSI interrupt into vGPU | ||
| 89 | * | ||
| 90 | * Returns: | ||
| 91 | * Zero on success, negative error code if failed. | ||
| 92 | */ | ||
| 93 | static inline int intel_gvt_hypervisor_inject_msi(struct intel_vgpu *vgpu) | ||
| 94 | { | ||
| 95 | unsigned long offset = vgpu->gvt->device_info.msi_cap_offset; | ||
| 96 | u16 control, data; | ||
| 97 | u32 addr; | ||
| 98 | int ret; | ||
| 99 | |||
| 100 | control = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_CONTROL(offset)); | ||
| 101 | addr = *(u32 *)(vgpu_cfg_space(vgpu) + MSI_CAP_ADDRESS(offset)); | ||
| 102 | data = *(u16 *)(vgpu_cfg_space(vgpu) + MSI_CAP_DATA(offset)); | ||
| 103 | |||
| 104 | /* Do not generate MSI if MSIEN is disable */ | ||
| 105 | if (!(control & MSI_CAP_EN)) | ||
| 106 | return 0; | ||
| 107 | |||
| 108 | if (WARN(control & GENMASK(15, 1), "only support one MSI format\n")) | ||
| 109 | return -EINVAL; | ||
| 110 | |||
| 111 | gvt_dbg_irq("vgpu%d: inject msi address %x data%x\n", vgpu->id, addr, | ||
| 112 | data); | ||
| 113 | |||
| 114 | ret = intel_gvt_host.mpt->inject_msi(vgpu->handle, addr, data); | ||
| 115 | if (ret) | ||
| 116 | return ret; | ||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | /** | ||
| 121 | * intel_gvt_hypervisor_set_wp_page - translate a host VA into MFN | ||
| 122 | * @p: host kernel virtual address | ||
| 123 | * | ||
| 124 | * Returns: | ||
| 125 | * MFN on success, INTEL_GVT_INVALID_ADDR if failed. | ||
| 126 | */ | ||
| 127 | static inline unsigned long intel_gvt_hypervisor_virt_to_mfn(void *p) | ||
| 128 | { | ||
| 129 | return intel_gvt_host.mpt->from_virt_to_mfn(p); | ||
| 130 | } | ||
| 131 | |||
| 132 | /** | ||
| 133 | * intel_gvt_hypervisor_set_wp_page - set a guest page to write-protected | ||
| 134 | * @vgpu: a vGPU | ||
| 135 | * @p: intel_vgpu_guest_page | ||
| 136 | * | ||
| 137 | * Returns: | ||
| 138 | * Zero on success, negative error code if failed. | ||
| 139 | */ | ||
| 140 | static inline int intel_gvt_hypervisor_set_wp_page(struct intel_vgpu *vgpu, | ||
| 141 | struct intel_vgpu_guest_page *p) | ||
| 142 | { | ||
| 143 | int ret; | ||
| 144 | |||
| 145 | if (p->writeprotection) | ||
| 146 | return 0; | ||
| 147 | |||
| 148 | ret = intel_gvt_host.mpt->set_wp_page(vgpu->handle, p->gfn); | ||
| 149 | if (ret) | ||
| 150 | return ret; | ||
| 151 | p->writeprotection = true; | ||
| 152 | atomic_inc(&vgpu->gtt.n_write_protected_guest_page); | ||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | /** | ||
| 157 | * intel_gvt_hypervisor_unset_wp_page - remove the write-protection of a | ||
| 158 | * guest page | ||
| 159 | * @vgpu: a vGPU | ||
| 160 | * @p: intel_vgpu_guest_page | ||
| 161 | * | ||
| 162 | * Returns: | ||
| 163 | * Zero on success, negative error code if failed. | ||
| 164 | */ | ||
| 165 | static inline int intel_gvt_hypervisor_unset_wp_page(struct intel_vgpu *vgpu, | ||
| 166 | struct intel_vgpu_guest_page *p) | ||
| 167 | { | ||
| 168 | int ret; | ||
| 169 | |||
| 170 | if (!p->writeprotection) | ||
| 171 | return 0; | ||
| 172 | |||
| 173 | ret = intel_gvt_host.mpt->unset_wp_page(vgpu->handle, p->gfn); | ||
| 174 | if (ret) | ||
| 175 | return ret; | ||
| 176 | p->writeprotection = false; | ||
| 177 | atomic_dec(&vgpu->gtt.n_write_protected_guest_page); | ||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | |||
| 181 | /** | ||
| 182 | * intel_gvt_hypervisor_read_gpa - copy data from GPA to host data buffer | ||
| 183 | * @vgpu: a vGPU | ||
| 184 | * @gpa: guest physical address | ||
| 185 | * @buf: host data buffer | ||
| 186 | * @len: data length | ||
| 187 | * | ||
| 188 | * Returns: | ||
| 189 | * Zero on success, negative error code if failed. | ||
| 190 | */ | ||
| 191 | static inline int intel_gvt_hypervisor_read_gpa(struct intel_vgpu *vgpu, | ||
| 192 | unsigned long gpa, void *buf, unsigned long len) | ||
| 193 | { | ||
| 194 | return intel_gvt_host.mpt->read_gpa(vgpu->handle, gpa, buf, len); | ||
| 195 | } | ||
| 196 | |||
| 197 | /** | ||
| 198 | * intel_gvt_hypervisor_write_gpa - copy data from host data buffer to GPA | ||
| 199 | * @vgpu: a vGPU | ||
| 200 | * @gpa: guest physical address | ||
| 201 | * @buf: host data buffer | ||
| 202 | * @len: data length | ||
| 203 | * | ||
| 204 | * Returns: | ||
| 205 | * Zero on success, negative error code if failed. | ||
| 206 | */ | ||
| 207 | static inline int intel_gvt_hypervisor_write_gpa(struct intel_vgpu *vgpu, | ||
| 208 | unsigned long gpa, void *buf, unsigned long len) | ||
| 209 | { | ||
| 210 | return intel_gvt_host.mpt->write_gpa(vgpu->handle, gpa, buf, len); | ||
| 211 | } | ||
| 212 | |||
| 213 | /** | ||
| 214 | * intel_gvt_hypervisor_gfn_to_mfn - translate a GFN to MFN | ||
| 215 | * @vgpu: a vGPU | ||
| 216 | * @gpfn: guest pfn | ||
| 217 | * | ||
| 218 | * Returns: | ||
| 219 | * MFN on success, INTEL_GVT_INVALID_ADDR if failed. | ||
| 220 | */ | ||
| 221 | static inline unsigned long intel_gvt_hypervisor_gfn_to_mfn( | ||
| 222 | struct intel_vgpu *vgpu, unsigned long gfn) | ||
| 223 | { | ||
| 224 | return intel_gvt_host.mpt->gfn_to_mfn(vgpu->handle, gfn); | ||
| 225 | } | ||
| 226 | |||
| 227 | enum { | ||
| 228 | GVT_MAP_APERTURE = 0, | ||
| 229 | GVT_MAP_OPREGION, | ||
| 230 | }; | ||
| 231 | |||
| 232 | /** | ||
| 233 | * intel_gvt_hypervisor_map_gfn_to_mfn - map a GFN region to MFN | ||
| 234 | * @vgpu: a vGPU | ||
| 235 | * @gfn: guest PFN | ||
| 236 | * @mfn: host PFN | ||
| 237 | * @nr: amount of PFNs | ||
| 238 | * @map: map or unmap | ||
| 239 | * @type: map type | ||
| 240 | * | ||
| 241 | * Returns: | ||
| 242 | * Zero on success, negative error code if failed. | ||
| 243 | */ | ||
| 244 | static inline int intel_gvt_hypervisor_map_gfn_to_mfn( | ||
| 245 | struct intel_vgpu *vgpu, unsigned long gfn, | ||
| 246 | unsigned long mfn, unsigned int nr, | ||
| 247 | bool map, int type) | ||
| 248 | { | ||
| 249 | return intel_gvt_host.mpt->map_gfn_to_mfn(vgpu->handle, gfn, mfn, nr, | ||
| 250 | map, type); | ||
| 251 | } | ||
| 252 | |||
| 253 | /** | ||
| 254 | * intel_gvt_hypervisor_set_trap_area - Trap a guest PA region | ||
| 255 | * @vgpu: a vGPU | ||
| 256 | * @start: the beginning of the guest physical address region | ||
| 257 | * @end: the end of the guest physical address region | ||
| 258 | * @map: map or unmap | ||
| 259 | * | ||
| 260 | * Returns: | ||
| 261 | * Zero on success, negative error code if failed. | ||
| 262 | */ | ||
| 263 | static inline int intel_gvt_hypervisor_set_trap_area( | ||
| 264 | struct intel_vgpu *vgpu, u64 start, u64 end, bool map) | ||
| 265 | { | ||
| 266 | return intel_gvt_host.mpt->set_trap_area(vgpu->handle, start, end, map); | ||
| 267 | } | ||
| 268 | |||
| 49 | #endif /* _GVT_MPT_H_ */ | 269 | #endif /* _GVT_MPT_H_ */ |
diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c new file mode 100644 index 000000000000..973c8a9d0b15 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/opregion.c | |||
| @@ -0,0 +1,344 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/acpi.h> | ||
| 25 | #include "i915_drv.h" | ||
| 26 | #include "gvt.h" | ||
| 27 | |||
| 28 | static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa) | ||
| 29 | { | ||
| 30 | void __iomem *host_va = vgpu->gvt->opregion.opregion_va; | ||
| 31 | u8 *buf; | ||
| 32 | int i; | ||
| 33 | |||
| 34 | if (WARN((vgpu_opregion(vgpu)->va), | ||
| 35 | "vgpu%d: opregion has been initialized already.\n", | ||
| 36 | vgpu->id)) | ||
| 37 | return -EINVAL; | ||
| 38 | |||
| 39 | vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_ATOMIC | | ||
| 40 | GFP_DMA32 | __GFP_ZERO, | ||
| 41 | INTEL_GVT_OPREGION_PORDER); | ||
| 42 | |||
| 43 | if (!vgpu_opregion(vgpu)->va) | ||
| 44 | return -ENOMEM; | ||
| 45 | |||
| 46 | memcpy_fromio(vgpu_opregion(vgpu)->va, host_va, | ||
| 47 | INTEL_GVT_OPREGION_SIZE); | ||
| 48 | |||
| 49 | for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) | ||
| 50 | vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i; | ||
| 51 | |||
| 52 | /* for unknown reason, the value in LID field is incorrect | ||
| 53 | * which block the windows guest, so workaround it by force | ||
| 54 | * setting it to "OPEN" | ||
| 55 | */ | ||
| 56 | buf = (u8 *)vgpu_opregion(vgpu)->va; | ||
| 57 | buf[INTEL_GVT_OPREGION_CLID] = 0x3; | ||
| 58 | |||
| 59 | return 0; | ||
| 60 | } | ||
| 61 | |||
| 62 | static int map_vgpu_opregion(struct intel_vgpu *vgpu, bool map) | ||
| 63 | { | ||
| 64 | u64 mfn; | ||
| 65 | int i, ret; | ||
| 66 | |||
| 67 | for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) { | ||
| 68 | mfn = intel_gvt_hypervisor_virt_to_mfn(vgpu_opregion(vgpu) | ||
| 69 | + i * PAGE_SIZE); | ||
| 70 | if (mfn == INTEL_GVT_INVALID_ADDR) { | ||
| 71 | gvt_err("fail to get MFN from VA\n"); | ||
| 72 | return -EINVAL; | ||
| 73 | } | ||
| 74 | ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, | ||
| 75 | vgpu_opregion(vgpu)->gfn[i], | ||
| 76 | mfn, 1, map, GVT_MAP_OPREGION); | ||
| 77 | if (ret) { | ||
| 78 | gvt_err("fail to map GFN to MFN, errno: %d\n", ret); | ||
| 79 | return ret; | ||
| 80 | } | ||
| 81 | } | ||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 85 | /** | ||
| 86 | * intel_vgpu_clean_opregion - clean the stuff used to emulate opregion | ||
| 87 | * @vgpu: a vGPU | ||
| 88 | * | ||
| 89 | */ | ||
| 90 | void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu) | ||
| 91 | { | ||
| 92 | int i; | ||
| 93 | |||
| 94 | gvt_dbg_core("vgpu%d: clean vgpu opregion\n", vgpu->id); | ||
| 95 | |||
| 96 | if (!vgpu_opregion(vgpu)->va) | ||
| 97 | return; | ||
| 98 | |||
| 99 | if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_KVM) { | ||
| 100 | vunmap(vgpu_opregion(vgpu)->va); | ||
| 101 | for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) { | ||
| 102 | if (vgpu_opregion(vgpu)->pages[i]) { | ||
| 103 | put_page(vgpu_opregion(vgpu)->pages[i]); | ||
| 104 | vgpu_opregion(vgpu)->pages[i] = NULL; | ||
| 105 | } | ||
| 106 | } | ||
| 107 | } else { | ||
| 108 | map_vgpu_opregion(vgpu, false); | ||
| 109 | free_pages((unsigned long)vgpu_opregion(vgpu)->va, | ||
| 110 | INTEL_GVT_OPREGION_PORDER); | ||
| 111 | } | ||
| 112 | |||
| 113 | vgpu_opregion(vgpu)->va = NULL; | ||
| 114 | } | ||
| 115 | |||
| 116 | /** | ||
| 117 | * intel_vgpu_init_opregion - initialize the stuff used to emulate opregion | ||
| 118 | * @vgpu: a vGPU | ||
| 119 | * @gpa: guest physical address of opregion | ||
| 120 | * | ||
| 121 | * Returns: | ||
| 122 | * Zero on success, negative error code if failed. | ||
| 123 | */ | ||
| 124 | int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa) | ||
| 125 | { | ||
| 126 | int ret; | ||
| 127 | |||
| 128 | gvt_dbg_core("vgpu%d: init vgpu opregion\n", vgpu->id); | ||
| 129 | |||
| 130 | if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_XEN) { | ||
| 131 | gvt_dbg_core("emulate opregion from kernel\n"); | ||
| 132 | |||
| 133 | ret = init_vgpu_opregion(vgpu, gpa); | ||
| 134 | if (ret) | ||
| 135 | return ret; | ||
| 136 | |||
| 137 | ret = map_vgpu_opregion(vgpu, true); | ||
| 138 | if (ret) | ||
| 139 | return ret; | ||
| 140 | } else { | ||
| 141 | gvt_dbg_core("emulate opregion from userspace\n"); | ||
| 142 | |||
| 143 | /* | ||
| 144 | * If opregion pages are not allocated from host kenrel, | ||
| 145 | * most of the params are meaningless | ||
| 146 | */ | ||
| 147 | ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, | ||
| 148 | 0, /* not used */ | ||
| 149 | 0, /* not used */ | ||
| 150 | 2, /* not used */ | ||
| 151 | 1, | ||
| 152 | GVT_MAP_OPREGION); | ||
| 153 | if (ret) | ||
| 154 | return ret; | ||
| 155 | } | ||
| 156 | return 0; | ||
| 157 | } | ||
| 158 | |||
| 159 | /** | ||
| 160 | * intel_gvt_clean_opregion - clean host opergion related stuffs | ||
| 161 | * @gvt: a GVT device | ||
| 162 | * | ||
| 163 | */ | ||
| 164 | void intel_gvt_clean_opregion(struct intel_gvt *gvt) | ||
| 165 | { | ||
| 166 | iounmap(gvt->opregion.opregion_va); | ||
| 167 | gvt->opregion.opregion_va = NULL; | ||
| 168 | } | ||
| 169 | |||
| 170 | /** | ||
| 171 | * intel_gvt_init_opregion - initialize host opergion related stuffs | ||
| 172 | * @gvt: a GVT device | ||
| 173 | * | ||
| 174 | * Returns: | ||
| 175 | * Zero on success, negative error code if failed. | ||
| 176 | */ | ||
| 177 | int intel_gvt_init_opregion(struct intel_gvt *gvt) | ||
| 178 | { | ||
| 179 | gvt_dbg_core("init host opregion\n"); | ||
| 180 | |||
| 181 | pci_read_config_dword(gvt->dev_priv->drm.pdev, INTEL_GVT_PCI_OPREGION, | ||
| 182 | &gvt->opregion.opregion_pa); | ||
| 183 | |||
| 184 | gvt->opregion.opregion_va = acpi_os_ioremap(gvt->opregion.opregion_pa, | ||
| 185 | INTEL_GVT_OPREGION_SIZE); | ||
| 186 | if (!gvt->opregion.opregion_va) { | ||
| 187 | gvt_err("fail to map host opregion\n"); | ||
| 188 | return -EFAULT; | ||
| 189 | } | ||
| 190 | return 0; | ||
| 191 | } | ||
| 192 | |||
| 193 | #define GVT_OPREGION_FUNC(scic) \ | ||
| 194 | ({ \ | ||
| 195 | u32 __ret; \ | ||
| 196 | __ret = (scic & OPREGION_SCIC_FUNC_MASK) >> \ | ||
| 197 | OPREGION_SCIC_FUNC_SHIFT; \ | ||
| 198 | __ret; \ | ||
| 199 | }) | ||
| 200 | |||
| 201 | #define GVT_OPREGION_SUBFUNC(scic) \ | ||
| 202 | ({ \ | ||
| 203 | u32 __ret; \ | ||
| 204 | __ret = (scic & OPREGION_SCIC_SUBFUNC_MASK) >> \ | ||
| 205 | OPREGION_SCIC_SUBFUNC_SHIFT; \ | ||
| 206 | __ret; \ | ||
| 207 | }) | ||
| 208 | |||
| 209 | static const char *opregion_func_name(u32 func) | ||
| 210 | { | ||
| 211 | const char *name = NULL; | ||
| 212 | |||
| 213 | switch (func) { | ||
| 214 | case 0 ... 3: | ||
| 215 | case 5: | ||
| 216 | case 7 ... 15: | ||
| 217 | name = "Reserved"; | ||
| 218 | break; | ||
| 219 | |||
| 220 | case 4: | ||
| 221 | name = "Get BIOS Data"; | ||
| 222 | break; | ||
| 223 | |||
| 224 | case 6: | ||
| 225 | name = "System BIOS Callbacks"; | ||
| 226 | break; | ||
| 227 | |||
| 228 | default: | ||
| 229 | name = "Unknown"; | ||
| 230 | break; | ||
| 231 | } | ||
| 232 | return name; | ||
| 233 | } | ||
| 234 | |||
| 235 | static const char *opregion_subfunc_name(u32 subfunc) | ||
| 236 | { | ||
| 237 | const char *name = NULL; | ||
| 238 | |||
| 239 | switch (subfunc) { | ||
| 240 | case 0: | ||
| 241 | name = "Supported Calls"; | ||
| 242 | break; | ||
| 243 | |||
| 244 | case 1: | ||
| 245 | name = "Requested Callbacks"; | ||
| 246 | break; | ||
| 247 | |||
| 248 | case 2 ... 3: | ||
| 249 | case 8 ... 9: | ||
| 250 | name = "Reserved"; | ||
| 251 | break; | ||
| 252 | |||
| 253 | case 5: | ||
| 254 | name = "Boot Display"; | ||
| 255 | break; | ||
| 256 | |||
| 257 | case 6: | ||
| 258 | name = "TV-Standard/Video-Connector"; | ||
| 259 | break; | ||
| 260 | |||
| 261 | case 7: | ||
| 262 | name = "Internal Graphics"; | ||
| 263 | break; | ||
| 264 | |||
| 265 | case 10: | ||
| 266 | name = "Spread Spectrum Clocks"; | ||
| 267 | break; | ||
| 268 | |||
| 269 | case 11: | ||
| 270 | name = "Get AKSV"; | ||
| 271 | break; | ||
| 272 | |||
| 273 | default: | ||
| 274 | name = "Unknown"; | ||
| 275 | break; | ||
| 276 | } | ||
| 277 | return name; | ||
| 278 | }; | ||
| 279 | |||
| 280 | static bool querying_capabilities(u32 scic) | ||
| 281 | { | ||
| 282 | u32 func, subfunc; | ||
| 283 | |||
| 284 | func = GVT_OPREGION_FUNC(scic); | ||
| 285 | subfunc = GVT_OPREGION_SUBFUNC(scic); | ||
| 286 | |||
| 287 | if ((func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA && | ||
| 288 | subfunc == INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS) | ||
| 289 | || (func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA && | ||
| 290 | subfunc == INTEL_GVT_OPREGION_SCIC_SF_REQEUSTEDCALLBACKS) | ||
| 291 | || (func == INTEL_GVT_OPREGION_SCIC_F_GETBIOSCALLBACKS && | ||
| 292 | subfunc == INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS)) { | ||
| 293 | return true; | ||
| 294 | } | ||
| 295 | return false; | ||
| 296 | } | ||
| 297 | |||
| 298 | /** | ||
| 299 | * intel_vgpu_emulate_opregion_request - emulating OpRegion request | ||
| 300 | * @vgpu: a vGPU | ||
| 301 | * @swsci: SWSCI request | ||
| 302 | * | ||
| 303 | * Returns: | ||
| 304 | * Zero on success, negative error code if failed | ||
| 305 | */ | ||
| 306 | int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci) | ||
| 307 | { | ||
| 308 | u32 *scic, *parm; | ||
| 309 | u32 func, subfunc; | ||
| 310 | |||
| 311 | scic = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_SCIC; | ||
| 312 | parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM; | ||
| 313 | |||
| 314 | if (!(swsci & SWSCI_SCI_SELECT)) { | ||
| 315 | gvt_err("vgpu%d: requesting SMI service\n", vgpu->id); | ||
| 316 | return 0; | ||
| 317 | } | ||
| 318 | /* ignore non 0->1 trasitions */ | ||
| 319 | if ((vgpu_cfg_space(vgpu)[INTEL_GVT_PCI_SWSCI] | ||
| 320 | & SWSCI_SCI_TRIGGER) || | ||
| 321 | !(swsci & SWSCI_SCI_TRIGGER)) { | ||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | func = GVT_OPREGION_FUNC(*scic); | ||
| 326 | subfunc = GVT_OPREGION_SUBFUNC(*scic); | ||
| 327 | if (!querying_capabilities(*scic)) { | ||
| 328 | gvt_err("vgpu%d: requesting runtime service: func \"%s\"," | ||
| 329 | " subfunc \"%s\"\n", | ||
| 330 | vgpu->id, | ||
| 331 | opregion_func_name(func), | ||
| 332 | opregion_subfunc_name(subfunc)); | ||
| 333 | /* | ||
| 334 | * emulate exit status of function call, '0' means | ||
| 335 | * "failure, generic, unsupported or unknown cause" | ||
| 336 | */ | ||
| 337 | *scic &= ~OPREGION_SCIC_EXIT_MASK; | ||
| 338 | return 0; | ||
| 339 | } | ||
| 340 | |||
| 341 | *scic = 0; | ||
| 342 | *parm = 0; | ||
| 343 | return 0; | ||
| 344 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/reg.h b/drivers/gpu/drm/i915/gvt/reg.h new file mode 100644 index 000000000000..0dfe789d8f02 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/reg.h | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #ifndef _GVT_REG_H | ||
| 25 | #define _GVT_REG_H | ||
| 26 | |||
| 27 | #define INTEL_GVT_PCI_CLASS_VGA_OTHER 0x80 | ||
| 28 | |||
| 29 | #define INTEL_GVT_PCI_GMCH_CONTROL 0x50 | ||
| 30 | #define BDW_GMCH_GMS_SHIFT 8 | ||
| 31 | #define BDW_GMCH_GMS_MASK 0xff | ||
| 32 | |||
| 33 | #define INTEL_GVT_PCI_SWSCI 0xe8 | ||
| 34 | #define SWSCI_SCI_SELECT (1 << 15) | ||
| 35 | #define SWSCI_SCI_TRIGGER 1 | ||
| 36 | |||
| 37 | #define INTEL_GVT_PCI_OPREGION 0xfc | ||
| 38 | |||
| 39 | #define INTEL_GVT_OPREGION_CLID 0x1AC | ||
| 40 | #define INTEL_GVT_OPREGION_SCIC 0x200 | ||
| 41 | #define OPREGION_SCIC_FUNC_MASK 0x1E | ||
| 42 | #define OPREGION_SCIC_FUNC_SHIFT 1 | ||
| 43 | #define OPREGION_SCIC_SUBFUNC_MASK 0xFF00 | ||
| 44 | #define OPREGION_SCIC_SUBFUNC_SHIFT 8 | ||
| 45 | #define OPREGION_SCIC_EXIT_MASK 0xE0 | ||
| 46 | #define INTEL_GVT_OPREGION_SCIC_F_GETBIOSDATA 4 | ||
| 47 | #define INTEL_GVT_OPREGION_SCIC_F_GETBIOSCALLBACKS 6 | ||
| 48 | #define INTEL_GVT_OPREGION_SCIC_SF_SUPPRTEDCALLS 0 | ||
| 49 | #define INTEL_GVT_OPREGION_SCIC_SF_REQEUSTEDCALLBACKS 1 | ||
| 50 | #define INTEL_GVT_OPREGION_PARM 0x204 | ||
| 51 | |||
| 52 | #define INTEL_GVT_OPREGION_PAGES 2 | ||
| 53 | #define INTEL_GVT_OPREGION_PORDER 1 | ||
| 54 | #define INTEL_GVT_OPREGION_SIZE (2 * 4096) | ||
| 55 | |||
| 56 | #define VGT_SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _PLANE_STRIDE_2_B) | ||
| 57 | |||
| 58 | #define _REG_VECS_EXCC 0x1A028 | ||
| 59 | #define _REG_VCS2_EXCC 0x1c028 | ||
| 60 | |||
| 61 | #define _REG_701C0(pipe, plane) (0x701c0 + pipe * 0x1000 + (plane - 1) * 0x100) | ||
| 62 | #define _REG_701C4(pipe, plane) (0x701c4 + pipe * 0x1000 + (plane - 1) * 0x100) | ||
| 63 | |||
| 64 | #define GFX_MODE_BIT_SET_IN_MASK(val, bit) \ | ||
| 65 | ((((bit) & 0xffff0000) == 0) && !!((val) & (((bit) << 16)))) | ||
| 66 | |||
| 67 | #define FORCEWAKE_RENDER_GEN9_REG 0xa278 | ||
| 68 | #define FORCEWAKE_ACK_RENDER_GEN9_REG 0x0D84 | ||
| 69 | #define FORCEWAKE_BLITTER_GEN9_REG 0xa188 | ||
| 70 | #define FORCEWAKE_ACK_BLITTER_GEN9_REG 0x130044 | ||
| 71 | #define FORCEWAKE_MEDIA_GEN9_REG 0xa270 | ||
| 72 | #define FORCEWAKE_ACK_MEDIA_GEN9_REG 0x0D88 | ||
| 73 | #define FORCEWAKE_ACK_HSW_REG 0x130044 | ||
| 74 | |||
| 75 | #define RB_HEAD_OFF_MASK ((1U << 21) - (1U << 2)) | ||
| 76 | #define RB_TAIL_OFF_MASK ((1U << 21) - (1U << 3)) | ||
| 77 | #define RB_TAIL_SIZE_MASK ((1U << 21) - (1U << 12)) | ||
| 78 | #define _RING_CTL_BUF_SIZE(ctl) (((ctl) & RB_TAIL_SIZE_MASK) + GTT_PAGE_SIZE) | ||
| 79 | |||
| 80 | #endif | ||
diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c new file mode 100644 index 000000000000..feebb65ba641 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/render.c | |||
| @@ -0,0 +1,291 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Eddie Dong <eddie.dong@intel.com> | ||
| 25 | * Kevin Tian <kevin.tian@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 29 | * Changbin Du <changbin.du@intel.com> | ||
| 30 | * Zhenyu Wang <zhenyuw@linux.intel.com> | ||
| 31 | * Tina Zhang <tina.zhang@intel.com> | ||
| 32 | * Bing Niu <bing.niu@intel.com> | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | #include "i915_drv.h" | ||
| 37 | #include "gvt.h" | ||
| 38 | |||
| 39 | struct render_mmio { | ||
| 40 | int ring_id; | ||
| 41 | i915_reg_t reg; | ||
| 42 | u32 mask; | ||
| 43 | bool in_context; | ||
| 44 | u32 value; | ||
| 45 | }; | ||
| 46 | |||
| 47 | static struct render_mmio gen8_render_mmio_list[] = { | ||
| 48 | {RCS, _MMIO(0x229c), 0xffff, false}, | ||
| 49 | {RCS, _MMIO(0x2248), 0x0, false}, | ||
| 50 | {RCS, _MMIO(0x2098), 0x0, false}, | ||
| 51 | {RCS, _MMIO(0x20c0), 0xffff, true}, | ||
| 52 | {RCS, _MMIO(0x24d0), 0, false}, | ||
| 53 | {RCS, _MMIO(0x24d4), 0, false}, | ||
| 54 | {RCS, _MMIO(0x24d8), 0, false}, | ||
| 55 | {RCS, _MMIO(0x24dc), 0, false}, | ||
| 56 | {RCS, _MMIO(0x7004), 0xffff, true}, | ||
| 57 | {RCS, _MMIO(0x7008), 0xffff, true}, | ||
| 58 | {RCS, _MMIO(0x7000), 0xffff, true}, | ||
| 59 | {RCS, _MMIO(0x7010), 0xffff, true}, | ||
| 60 | {RCS, _MMIO(0x7300), 0xffff, true}, | ||
| 61 | {RCS, _MMIO(0x83a4), 0xffff, true}, | ||
| 62 | |||
| 63 | {BCS, _MMIO(0x2229c), 0xffff, false}, | ||
| 64 | {BCS, _MMIO(0x2209c), 0xffff, false}, | ||
| 65 | {BCS, _MMIO(0x220c0), 0xffff, false}, | ||
| 66 | {BCS, _MMIO(0x22098), 0x0, false}, | ||
| 67 | {BCS, _MMIO(0x22028), 0x0, false}, | ||
| 68 | }; | ||
| 69 | |||
| 70 | static struct render_mmio gen9_render_mmio_list[] = { | ||
| 71 | {RCS, _MMIO(0x229c), 0xffff, false}, | ||
| 72 | {RCS, _MMIO(0x2248), 0x0, false}, | ||
| 73 | {RCS, _MMIO(0x2098), 0x0, false}, | ||
| 74 | {RCS, _MMIO(0x20c0), 0xffff, true}, | ||
| 75 | {RCS, _MMIO(0x24d0), 0, false}, | ||
| 76 | {RCS, _MMIO(0x24d4), 0, false}, | ||
| 77 | {RCS, _MMIO(0x24d8), 0, false}, | ||
| 78 | {RCS, _MMIO(0x24dc), 0, false}, | ||
| 79 | {RCS, _MMIO(0x7004), 0xffff, true}, | ||
| 80 | {RCS, _MMIO(0x7008), 0xffff, true}, | ||
| 81 | {RCS, _MMIO(0x7000), 0xffff, true}, | ||
| 82 | {RCS, _MMIO(0x7010), 0xffff, true}, | ||
| 83 | {RCS, _MMIO(0x7300), 0xffff, true}, | ||
| 84 | {RCS, _MMIO(0x83a4), 0xffff, true}, | ||
| 85 | |||
| 86 | {RCS, _MMIO(0x40e0), 0, false}, | ||
| 87 | {RCS, _MMIO(0x40e4), 0, false}, | ||
| 88 | {RCS, _MMIO(0x2580), 0xffff, true}, | ||
| 89 | {RCS, _MMIO(0x7014), 0xffff, true}, | ||
| 90 | {RCS, _MMIO(0x20ec), 0xffff, false}, | ||
| 91 | {RCS, _MMIO(0xb118), 0, false}, | ||
| 92 | {RCS, _MMIO(0xe100), 0xffff, true}, | ||
| 93 | {RCS, _MMIO(0xe180), 0xffff, true}, | ||
| 94 | {RCS, _MMIO(0xe184), 0xffff, true}, | ||
| 95 | {RCS, _MMIO(0xe188), 0xffff, true}, | ||
| 96 | {RCS, _MMIO(0xe194), 0xffff, true}, | ||
| 97 | {RCS, _MMIO(0x4de0), 0, false}, | ||
| 98 | {RCS, _MMIO(0x4de4), 0, false}, | ||
| 99 | {RCS, _MMIO(0x4de8), 0, false}, | ||
| 100 | {RCS, _MMIO(0x4dec), 0, false}, | ||
| 101 | {RCS, _MMIO(0x4df0), 0, false}, | ||
| 102 | {RCS, _MMIO(0x4df4), 0, false}, | ||
| 103 | |||
| 104 | {BCS, _MMIO(0x2229c), 0xffff, false}, | ||
| 105 | {BCS, _MMIO(0x2209c), 0xffff, false}, | ||
| 106 | {BCS, _MMIO(0x220c0), 0xffff, false}, | ||
| 107 | {BCS, _MMIO(0x22098), 0x0, false}, | ||
| 108 | {BCS, _MMIO(0x22028), 0x0, false}, | ||
| 109 | |||
| 110 | {VCS2, _MMIO(0x1c028), 0xffff, false}, | ||
| 111 | |||
| 112 | {VECS, _MMIO(0x1a028), 0xffff, false}, | ||
| 113 | }; | ||
| 114 | |||
| 115 | static u32 gen9_render_mocs[I915_NUM_ENGINES][64]; | ||
| 116 | static u32 gen9_render_mocs_L3[32]; | ||
| 117 | |||
| 118 | static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id) | ||
| 119 | { | ||
| 120 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 121 | i915_reg_t reg; | ||
| 122 | u32 regs[] = { | ||
| 123 | [RCS] = 0x4260, | ||
| 124 | [VCS] = 0x4264, | ||
| 125 | [VCS2] = 0x4268, | ||
| 126 | [BCS] = 0x426c, | ||
| 127 | [VECS] = 0x4270, | ||
| 128 | }; | ||
| 129 | |||
| 130 | if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) | ||
| 131 | return; | ||
| 132 | |||
| 133 | if (!test_and_clear_bit(ring_id, (void *)vgpu->tlb_handle_pending)) | ||
| 134 | return; | ||
| 135 | |||
| 136 | reg = _MMIO(regs[ring_id]); | ||
| 137 | |||
| 138 | I915_WRITE(reg, 0x1); | ||
| 139 | |||
| 140 | if (wait_for_atomic((I915_READ(reg) == 0), 50)) | ||
| 141 | gvt_err("timeout in invalidate ring (%d) tlb\n", ring_id); | ||
| 142 | |||
| 143 | gvt_dbg_core("invalidate TLB for ring %d\n", ring_id); | ||
| 144 | } | ||
| 145 | |||
| 146 | static void load_mocs(struct intel_vgpu *vgpu, int ring_id) | ||
| 147 | { | ||
| 148 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 149 | i915_reg_t offset, l3_offset; | ||
| 150 | u32 regs[] = { | ||
| 151 | [RCS] = 0xc800, | ||
| 152 | [VCS] = 0xc900, | ||
| 153 | [VCS2] = 0xca00, | ||
| 154 | [BCS] = 0xcc00, | ||
| 155 | [VECS] = 0xcb00, | ||
| 156 | }; | ||
| 157 | int i; | ||
| 158 | |||
| 159 | if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) | ||
| 160 | return; | ||
| 161 | |||
| 162 | if (!IS_SKYLAKE(dev_priv)) | ||
| 163 | return; | ||
| 164 | |||
| 165 | for (i = 0; i < 64; i++) { | ||
| 166 | gen9_render_mocs[ring_id][i] = I915_READ(offset); | ||
| 167 | I915_WRITE(offset, vgpu_vreg(vgpu, offset)); | ||
| 168 | POSTING_READ(offset); | ||
| 169 | offset.reg += 4; | ||
| 170 | } | ||
| 171 | |||
| 172 | if (ring_id == RCS) { | ||
| 173 | l3_offset.reg = 0xb020; | ||
| 174 | for (i = 0; i < 32; i++) { | ||
| 175 | gen9_render_mocs_L3[i] = I915_READ(l3_offset); | ||
| 176 | I915_WRITE(l3_offset, vgpu_vreg(vgpu, offset)); | ||
| 177 | POSTING_READ(l3_offset); | ||
| 178 | l3_offset.reg += 4; | ||
| 179 | } | ||
| 180 | } | ||
| 181 | } | ||
| 182 | |||
| 183 | static void restore_mocs(struct intel_vgpu *vgpu, int ring_id) | ||
| 184 | { | ||
| 185 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 186 | i915_reg_t offset, l3_offset; | ||
| 187 | u32 regs[] = { | ||
| 188 | [RCS] = 0xc800, | ||
| 189 | [VCS] = 0xc900, | ||
| 190 | [VCS2] = 0xca00, | ||
| 191 | [BCS] = 0xcc00, | ||
| 192 | [VECS] = 0xcb00, | ||
| 193 | }; | ||
| 194 | int i; | ||
| 195 | |||
| 196 | if (WARN_ON(ring_id >= ARRAY_SIZE(regs))) | ||
| 197 | return; | ||
| 198 | |||
| 199 | if (!IS_SKYLAKE(dev_priv)) | ||
| 200 | return; | ||
| 201 | |||
| 202 | for (i = 0; i < 64; i++) { | ||
| 203 | vgpu_vreg(vgpu, offset) = I915_READ(offset); | ||
| 204 | I915_WRITE(offset, gen9_render_mocs[ring_id][i]); | ||
| 205 | POSTING_READ(offset); | ||
| 206 | offset.reg += 4; | ||
| 207 | } | ||
| 208 | |||
| 209 | if (ring_id == RCS) { | ||
| 210 | l3_offset.reg = 0xb020; | ||
| 211 | for (i = 0; i < 32; i++) { | ||
| 212 | vgpu_vreg(vgpu, l3_offset) = I915_READ(l3_offset); | ||
| 213 | I915_WRITE(l3_offset, gen9_render_mocs_L3[i]); | ||
| 214 | POSTING_READ(l3_offset); | ||
| 215 | l3_offset.reg += 4; | ||
| 216 | } | ||
| 217 | } | ||
| 218 | } | ||
| 219 | |||
| 220 | void intel_gvt_load_render_mmio(struct intel_vgpu *vgpu, int ring_id) | ||
| 221 | { | ||
| 222 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 223 | struct render_mmio *mmio; | ||
| 224 | u32 v; | ||
| 225 | int i, array_size; | ||
| 226 | |||
| 227 | if (IS_SKYLAKE(vgpu->gvt->dev_priv)) { | ||
| 228 | mmio = gen9_render_mmio_list; | ||
| 229 | array_size = ARRAY_SIZE(gen9_render_mmio_list); | ||
| 230 | load_mocs(vgpu, ring_id); | ||
| 231 | } else { | ||
| 232 | mmio = gen8_render_mmio_list; | ||
| 233 | array_size = ARRAY_SIZE(gen8_render_mmio_list); | ||
| 234 | } | ||
| 235 | |||
| 236 | for (i = 0; i < array_size; i++, mmio++) { | ||
| 237 | if (mmio->ring_id != ring_id) | ||
| 238 | continue; | ||
| 239 | |||
| 240 | mmio->value = I915_READ(mmio->reg); | ||
| 241 | if (mmio->mask) | ||
| 242 | v = vgpu_vreg(vgpu, mmio->reg) | (mmio->mask << 16); | ||
| 243 | else | ||
| 244 | v = vgpu_vreg(vgpu, mmio->reg); | ||
| 245 | |||
| 246 | I915_WRITE(mmio->reg, v); | ||
| 247 | POSTING_READ(mmio->reg); | ||
| 248 | |||
| 249 | gvt_dbg_render("load reg %x old %x new %x\n", | ||
| 250 | i915_mmio_reg_offset(mmio->reg), | ||
| 251 | mmio->value, v); | ||
| 252 | } | ||
| 253 | handle_tlb_pending_event(vgpu, ring_id); | ||
| 254 | } | ||
| 255 | |||
| 256 | void intel_gvt_restore_render_mmio(struct intel_vgpu *vgpu, int ring_id) | ||
| 257 | { | ||
| 258 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 259 | struct render_mmio *mmio; | ||
| 260 | u32 v; | ||
| 261 | int i, array_size; | ||
| 262 | |||
| 263 | if (IS_SKYLAKE(dev_priv)) { | ||
| 264 | mmio = gen9_render_mmio_list; | ||
| 265 | array_size = ARRAY_SIZE(gen9_render_mmio_list); | ||
| 266 | restore_mocs(vgpu, ring_id); | ||
| 267 | } else { | ||
| 268 | mmio = gen8_render_mmio_list; | ||
| 269 | array_size = ARRAY_SIZE(gen8_render_mmio_list); | ||
| 270 | } | ||
| 271 | |||
| 272 | for (i = 0; i < array_size; i++, mmio++) { | ||
| 273 | if (mmio->ring_id != ring_id) | ||
| 274 | continue; | ||
| 275 | |||
| 276 | vgpu_vreg(vgpu, mmio->reg) = I915_READ(mmio->reg); | ||
| 277 | |||
| 278 | if (mmio->mask) { | ||
| 279 | vgpu_vreg(vgpu, mmio->reg) &= ~(mmio->mask << 16); | ||
| 280 | v = mmio->value | (mmio->mask << 16); | ||
| 281 | } else | ||
| 282 | v = mmio->value; | ||
| 283 | |||
| 284 | I915_WRITE(mmio->reg, v); | ||
| 285 | POSTING_READ(mmio->reg); | ||
| 286 | |||
| 287 | gvt_dbg_render("restore reg %x old %x new %x\n", | ||
| 288 | i915_mmio_reg_offset(mmio->reg), | ||
| 289 | mmio->value, v); | ||
| 290 | } | ||
| 291 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/render.h b/drivers/gpu/drm/i915/gvt/render.h new file mode 100644 index 000000000000..dac1a3cc458b --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/render.h | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Eddie Dong <eddie.dong@intel.com> | ||
| 25 | * Kevin Tian <kevin.tian@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 29 | * Changbin Du <changbin.du@intel.com> | ||
| 30 | * Zhenyu Wang <zhenyuw@linux.intel.com> | ||
| 31 | * Tina Zhang <tina.zhang@intel.com> | ||
| 32 | * Bing Niu <bing.niu@intel.com> | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | #ifndef __GVT_RENDER_H__ | ||
| 37 | #define __GVT_RENDER_H__ | ||
| 38 | |||
| 39 | void intel_gvt_load_render_mmio(struct intel_vgpu *vgpu, int ring_id); | ||
| 40 | |||
| 41 | void intel_gvt_restore_render_mmio(struct intel_vgpu *vgpu, int ring_id); | ||
| 42 | |||
| 43 | #endif | ||
diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c new file mode 100644 index 000000000000..1df6a5460f3e --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c | |||
| @@ -0,0 +1,294 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Anhua Xu | ||
| 25 | * Kevin Tian <kevin.tian@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Min He <min.he@intel.com> | ||
| 29 | * Bing Niu <bing.niu@intel.com> | ||
| 30 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 31 | * | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include "i915_drv.h" | ||
| 35 | #include "gvt.h" | ||
| 36 | |||
| 37 | static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu) | ||
| 38 | { | ||
| 39 | struct intel_vgpu_execlist *execlist; | ||
| 40 | enum intel_engine_id i; | ||
| 41 | struct intel_engine_cs *engine; | ||
| 42 | |||
| 43 | for_each_engine(engine, vgpu->gvt->dev_priv, i) { | ||
| 44 | execlist = &vgpu->execlist[i]; | ||
| 45 | if (!list_empty(workload_q_head(vgpu, i))) | ||
| 46 | return true; | ||
| 47 | } | ||
| 48 | |||
| 49 | return false; | ||
| 50 | } | ||
| 51 | |||
| 52 | static void try_to_schedule_next_vgpu(struct intel_gvt *gvt) | ||
| 53 | { | ||
| 54 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | ||
| 55 | enum intel_engine_id i; | ||
| 56 | struct intel_engine_cs *engine; | ||
| 57 | |||
| 58 | /* no target to schedule */ | ||
| 59 | if (!scheduler->next_vgpu) | ||
| 60 | return; | ||
| 61 | |||
| 62 | gvt_dbg_sched("try to schedule next vgpu %d\n", | ||
| 63 | scheduler->next_vgpu->id); | ||
| 64 | |||
| 65 | /* | ||
| 66 | * after the flag is set, workload dispatch thread will | ||
| 67 | * stop dispatching workload for current vgpu | ||
| 68 | */ | ||
| 69 | scheduler->need_reschedule = true; | ||
| 70 | |||
| 71 | /* still have uncompleted workload? */ | ||
| 72 | for_each_engine(engine, gvt->dev_priv, i) { | ||
| 73 | if (scheduler->current_workload[i]) { | ||
| 74 | gvt_dbg_sched("still have running workload\n"); | ||
| 75 | return; | ||
| 76 | } | ||
| 77 | } | ||
| 78 | |||
| 79 | gvt_dbg_sched("switch to next vgpu %d\n", | ||
| 80 | scheduler->next_vgpu->id); | ||
| 81 | |||
| 82 | /* switch current vgpu */ | ||
| 83 | scheduler->current_vgpu = scheduler->next_vgpu; | ||
| 84 | scheduler->next_vgpu = NULL; | ||
| 85 | |||
| 86 | scheduler->need_reschedule = false; | ||
| 87 | |||
| 88 | /* wake up workload dispatch thread */ | ||
| 89 | for_each_engine(engine, gvt->dev_priv, i) | ||
| 90 | wake_up(&scheduler->waitq[i]); | ||
| 91 | } | ||
| 92 | |||
| 93 | struct tbs_vgpu_data { | ||
| 94 | struct list_head list; | ||
| 95 | struct intel_vgpu *vgpu; | ||
| 96 | /* put some per-vgpu sched stats here */ | ||
| 97 | }; | ||
| 98 | |||
| 99 | struct tbs_sched_data { | ||
| 100 | struct intel_gvt *gvt; | ||
| 101 | struct delayed_work work; | ||
| 102 | unsigned long period; | ||
| 103 | struct list_head runq_head; | ||
| 104 | }; | ||
| 105 | |||
| 106 | #define GVT_DEFAULT_TIME_SLICE (1 * HZ / 1000) | ||
| 107 | |||
| 108 | static void tbs_sched_func(struct work_struct *work) | ||
| 109 | { | ||
| 110 | struct tbs_sched_data *sched_data = container_of(work, | ||
| 111 | struct tbs_sched_data, work.work); | ||
| 112 | struct tbs_vgpu_data *vgpu_data; | ||
| 113 | |||
| 114 | struct intel_gvt *gvt = sched_data->gvt; | ||
| 115 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | ||
| 116 | |||
| 117 | struct intel_vgpu *vgpu = NULL; | ||
| 118 | struct list_head *pos, *head; | ||
| 119 | |||
| 120 | mutex_lock(&gvt->lock); | ||
| 121 | |||
| 122 | /* no vgpu or has already had a target */ | ||
| 123 | if (list_empty(&sched_data->runq_head) || scheduler->next_vgpu) | ||
| 124 | goto out; | ||
| 125 | |||
| 126 | if (scheduler->current_vgpu) { | ||
| 127 | vgpu_data = scheduler->current_vgpu->sched_data; | ||
| 128 | head = &vgpu_data->list; | ||
| 129 | } else { | ||
| 130 | gvt_dbg_sched("no current vgpu search from q head\n"); | ||
| 131 | head = &sched_data->runq_head; | ||
| 132 | } | ||
| 133 | |||
| 134 | /* search a vgpu with pending workload */ | ||
| 135 | list_for_each(pos, head) { | ||
| 136 | if (pos == &sched_data->runq_head) | ||
| 137 | continue; | ||
| 138 | |||
| 139 | vgpu_data = container_of(pos, struct tbs_vgpu_data, list); | ||
| 140 | if (!vgpu_has_pending_workload(vgpu_data->vgpu)) | ||
| 141 | continue; | ||
| 142 | |||
| 143 | vgpu = vgpu_data->vgpu; | ||
| 144 | break; | ||
| 145 | } | ||
| 146 | |||
| 147 | if (vgpu) { | ||
| 148 | scheduler->next_vgpu = vgpu; | ||
| 149 | gvt_dbg_sched("pick next vgpu %d\n", vgpu->id); | ||
| 150 | } | ||
| 151 | out: | ||
| 152 | if (scheduler->next_vgpu) { | ||
| 153 | gvt_dbg_sched("try to schedule next vgpu %d\n", | ||
| 154 | scheduler->next_vgpu->id); | ||
| 155 | try_to_schedule_next_vgpu(gvt); | ||
| 156 | } | ||
| 157 | |||
| 158 | /* | ||
| 159 | * still have vgpu on runq | ||
| 160 | * or last schedule haven't finished due to running workload | ||
| 161 | */ | ||
| 162 | if (!list_empty(&sched_data->runq_head) || scheduler->next_vgpu) | ||
| 163 | schedule_delayed_work(&sched_data->work, sched_data->period); | ||
| 164 | |||
| 165 | mutex_unlock(&gvt->lock); | ||
| 166 | } | ||
| 167 | |||
| 168 | static int tbs_sched_init(struct intel_gvt *gvt) | ||
| 169 | { | ||
| 170 | struct intel_gvt_workload_scheduler *scheduler = | ||
| 171 | &gvt->scheduler; | ||
| 172 | |||
| 173 | struct tbs_sched_data *data; | ||
| 174 | |||
| 175 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
| 176 | if (!data) | ||
| 177 | return -ENOMEM; | ||
| 178 | |||
| 179 | INIT_LIST_HEAD(&data->runq_head); | ||
| 180 | INIT_DELAYED_WORK(&data->work, tbs_sched_func); | ||
| 181 | data->period = GVT_DEFAULT_TIME_SLICE; | ||
| 182 | data->gvt = gvt; | ||
| 183 | |||
| 184 | scheduler->sched_data = data; | ||
| 185 | return 0; | ||
| 186 | } | ||
| 187 | |||
| 188 | static void tbs_sched_clean(struct intel_gvt *gvt) | ||
| 189 | { | ||
| 190 | struct intel_gvt_workload_scheduler *scheduler = | ||
| 191 | &gvt->scheduler; | ||
| 192 | struct tbs_sched_data *data = scheduler->sched_data; | ||
| 193 | |||
| 194 | cancel_delayed_work(&data->work); | ||
| 195 | kfree(data); | ||
| 196 | scheduler->sched_data = NULL; | ||
| 197 | } | ||
| 198 | |||
| 199 | static int tbs_sched_init_vgpu(struct intel_vgpu *vgpu) | ||
| 200 | { | ||
| 201 | struct tbs_vgpu_data *data; | ||
| 202 | |||
| 203 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
| 204 | if (!data) | ||
| 205 | return -ENOMEM; | ||
| 206 | |||
| 207 | data->vgpu = vgpu; | ||
| 208 | INIT_LIST_HEAD(&data->list); | ||
| 209 | |||
| 210 | vgpu->sched_data = data; | ||
| 211 | return 0; | ||
| 212 | } | ||
| 213 | |||
| 214 | static void tbs_sched_clean_vgpu(struct intel_vgpu *vgpu) | ||
| 215 | { | ||
| 216 | kfree(vgpu->sched_data); | ||
| 217 | vgpu->sched_data = NULL; | ||
| 218 | } | ||
| 219 | |||
| 220 | static void tbs_sched_start_schedule(struct intel_vgpu *vgpu) | ||
| 221 | { | ||
| 222 | struct tbs_sched_data *sched_data = vgpu->gvt->scheduler.sched_data; | ||
| 223 | struct tbs_vgpu_data *vgpu_data = vgpu->sched_data; | ||
| 224 | |||
| 225 | if (!list_empty(&vgpu_data->list)) | ||
| 226 | return; | ||
| 227 | |||
| 228 | list_add_tail(&vgpu_data->list, &sched_data->runq_head); | ||
| 229 | schedule_delayed_work(&sched_data->work, sched_data->period); | ||
| 230 | } | ||
| 231 | |||
| 232 | static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu) | ||
| 233 | { | ||
| 234 | struct tbs_vgpu_data *vgpu_data = vgpu->sched_data; | ||
| 235 | |||
| 236 | list_del_init(&vgpu_data->list); | ||
| 237 | } | ||
| 238 | |||
| 239 | static struct intel_gvt_sched_policy_ops tbs_schedule_ops = { | ||
| 240 | .init = tbs_sched_init, | ||
| 241 | .clean = tbs_sched_clean, | ||
| 242 | .init_vgpu = tbs_sched_init_vgpu, | ||
| 243 | .clean_vgpu = tbs_sched_clean_vgpu, | ||
| 244 | .start_schedule = tbs_sched_start_schedule, | ||
| 245 | .stop_schedule = tbs_sched_stop_schedule, | ||
| 246 | }; | ||
| 247 | |||
| 248 | int intel_gvt_init_sched_policy(struct intel_gvt *gvt) | ||
| 249 | { | ||
| 250 | gvt->scheduler.sched_ops = &tbs_schedule_ops; | ||
| 251 | |||
| 252 | return gvt->scheduler.sched_ops->init(gvt); | ||
| 253 | } | ||
| 254 | |||
| 255 | void intel_gvt_clean_sched_policy(struct intel_gvt *gvt) | ||
| 256 | { | ||
| 257 | gvt->scheduler.sched_ops->clean(gvt); | ||
| 258 | } | ||
| 259 | |||
| 260 | int intel_vgpu_init_sched_policy(struct intel_vgpu *vgpu) | ||
| 261 | { | ||
| 262 | return vgpu->gvt->scheduler.sched_ops->init_vgpu(vgpu); | ||
| 263 | } | ||
| 264 | |||
| 265 | void intel_vgpu_clean_sched_policy(struct intel_vgpu *vgpu) | ||
| 266 | { | ||
| 267 | vgpu->gvt->scheduler.sched_ops->clean_vgpu(vgpu); | ||
| 268 | } | ||
| 269 | |||
| 270 | void intel_vgpu_start_schedule(struct intel_vgpu *vgpu) | ||
| 271 | { | ||
| 272 | gvt_dbg_core("vgpu%d: start schedule\n", vgpu->id); | ||
| 273 | |||
| 274 | vgpu->gvt->scheduler.sched_ops->start_schedule(vgpu); | ||
| 275 | } | ||
| 276 | |||
| 277 | void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu) | ||
| 278 | { | ||
| 279 | struct intel_gvt_workload_scheduler *scheduler = | ||
| 280 | &vgpu->gvt->scheduler; | ||
| 281 | |||
| 282 | gvt_dbg_core("vgpu%d: stop schedule\n", vgpu->id); | ||
| 283 | |||
| 284 | scheduler->sched_ops->stop_schedule(vgpu); | ||
| 285 | |||
| 286 | if (scheduler->next_vgpu == vgpu) | ||
| 287 | scheduler->next_vgpu = NULL; | ||
| 288 | |||
| 289 | if (scheduler->current_vgpu == vgpu) { | ||
| 290 | /* stop workload dispatching */ | ||
| 291 | scheduler->need_reschedule = true; | ||
| 292 | scheduler->current_vgpu = NULL; | ||
| 293 | } | ||
| 294 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.h b/drivers/gpu/drm/i915/gvt/sched_policy.h new file mode 100644 index 000000000000..bb8b9097e41a --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/sched_policy.h | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Anhua Xu | ||
| 25 | * Kevin Tian <kevin.tian@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Min He <min.he@intel.com> | ||
| 29 | * Bing Niu <bing.niu@intel.com> | ||
| 30 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 31 | * | ||
| 32 | */ | ||
| 33 | |||
| 34 | #ifndef __GVT_SCHED_POLICY__ | ||
| 35 | #define __GVT_SCHED_POLICY__ | ||
| 36 | |||
| 37 | struct intel_gvt_sched_policy_ops { | ||
| 38 | int (*init)(struct intel_gvt *gvt); | ||
| 39 | void (*clean)(struct intel_gvt *gvt); | ||
| 40 | int (*init_vgpu)(struct intel_vgpu *vgpu); | ||
| 41 | void (*clean_vgpu)(struct intel_vgpu *vgpu); | ||
| 42 | void (*start_schedule)(struct intel_vgpu *vgpu); | ||
| 43 | void (*stop_schedule)(struct intel_vgpu *vgpu); | ||
| 44 | }; | ||
| 45 | |||
| 46 | int intel_gvt_init_sched_policy(struct intel_gvt *gvt); | ||
| 47 | |||
| 48 | void intel_gvt_clean_sched_policy(struct intel_gvt *gvt); | ||
| 49 | |||
| 50 | int intel_vgpu_init_sched_policy(struct intel_vgpu *vgpu); | ||
| 51 | |||
| 52 | void intel_vgpu_clean_sched_policy(struct intel_vgpu *vgpu); | ||
| 53 | |||
| 54 | void intel_vgpu_start_schedule(struct intel_vgpu *vgpu); | ||
| 55 | |||
| 56 | void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu); | ||
| 57 | |||
| 58 | #endif | ||
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c new file mode 100644 index 000000000000..e96eaeebeb0a --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/scheduler.c | |||
| @@ -0,0 +1,578 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 25 | * | ||
| 26 | * Contributors: | ||
| 27 | * Ping Gao <ping.a.gao@intel.com> | ||
| 28 | * Tina Zhang <tina.zhang@intel.com> | ||
| 29 | * Chanbin Du <changbin.du@intel.com> | ||
| 30 | * Min He <min.he@intel.com> | ||
| 31 | * Bing Niu <bing.niu@intel.com> | ||
| 32 | * Zhenyu Wang <zhenyuw@linux.intel.com> | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | #include <linux/kthread.h> | ||
| 37 | |||
| 38 | #include "i915_drv.h" | ||
| 39 | #include "gvt.h" | ||
| 40 | |||
| 41 | #define RING_CTX_OFF(x) \ | ||
| 42 | offsetof(struct execlist_ring_context, x) | ||
| 43 | |||
| 44 | static void set_context_pdp_root_pointer( | ||
| 45 | struct execlist_ring_context *ring_context, | ||
| 46 | u32 pdp[8]) | ||
| 47 | { | ||
| 48 | struct execlist_mmio_pair *pdp_pair = &ring_context->pdp3_UDW; | ||
| 49 | int i; | ||
| 50 | |||
| 51 | for (i = 0; i < 8; i++) | ||
| 52 | pdp_pair[i].val = pdp[7 - i]; | ||
| 53 | } | ||
| 54 | |||
| 55 | static int populate_shadow_context(struct intel_vgpu_workload *workload) | ||
| 56 | { | ||
| 57 | struct intel_vgpu *vgpu = workload->vgpu; | ||
| 58 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 59 | int ring_id = workload->ring_id; | ||
| 60 | struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; | ||
| 61 | struct drm_i915_gem_object *ctx_obj = | ||
| 62 | shadow_ctx->engine[ring_id].state->obj; | ||
| 63 | struct execlist_ring_context *shadow_ring_context; | ||
| 64 | struct page *page; | ||
| 65 | void *dst; | ||
| 66 | unsigned long context_gpa, context_page_num; | ||
| 67 | int i; | ||
| 68 | |||
| 69 | gvt_dbg_sched("ring id %d workload lrca %x", ring_id, | ||
| 70 | workload->ctx_desc.lrca); | ||
| 71 | |||
| 72 | context_page_num = intel_lr_context_size( | ||
| 73 | gvt->dev_priv->engine[ring_id]); | ||
| 74 | |||
| 75 | context_page_num = context_page_num >> PAGE_SHIFT; | ||
| 76 | |||
| 77 | if (IS_BROADWELL(gvt->dev_priv) && ring_id == RCS) | ||
| 78 | context_page_num = 19; | ||
| 79 | |||
| 80 | i = 2; | ||
| 81 | |||
| 82 | while (i < context_page_num) { | ||
| 83 | context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, | ||
| 84 | (u32)((workload->ctx_desc.lrca + i) << | ||
| 85 | GTT_PAGE_SHIFT)); | ||
| 86 | if (context_gpa == INTEL_GVT_INVALID_ADDR) { | ||
| 87 | gvt_err("Invalid guest context descriptor\n"); | ||
| 88 | return -EINVAL; | ||
| 89 | } | ||
| 90 | |||
| 91 | page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i); | ||
| 92 | dst = kmap_atomic(page); | ||
| 93 | intel_gvt_hypervisor_read_gpa(vgpu, context_gpa, dst, | ||
| 94 | GTT_PAGE_SIZE); | ||
| 95 | kunmap_atomic(dst); | ||
| 96 | i++; | ||
| 97 | } | ||
| 98 | |||
| 99 | page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); | ||
| 100 | shadow_ring_context = kmap_atomic(page); | ||
| 101 | |||
| 102 | #define COPY_REG(name) \ | ||
| 103 | intel_gvt_hypervisor_read_gpa(vgpu, workload->ring_context_gpa \ | ||
| 104 | + RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4) | ||
| 105 | |||
| 106 | COPY_REG(ctx_ctrl); | ||
| 107 | COPY_REG(ctx_timestamp); | ||
| 108 | |||
| 109 | if (ring_id == RCS) { | ||
| 110 | COPY_REG(bb_per_ctx_ptr); | ||
| 111 | COPY_REG(rcs_indirect_ctx); | ||
| 112 | COPY_REG(rcs_indirect_ctx_offset); | ||
| 113 | } | ||
| 114 | #undef COPY_REG | ||
| 115 | |||
| 116 | set_context_pdp_root_pointer(shadow_ring_context, | ||
| 117 | workload->shadow_mm->shadow_page_table); | ||
| 118 | |||
| 119 | intel_gvt_hypervisor_read_gpa(vgpu, | ||
| 120 | workload->ring_context_gpa + | ||
| 121 | sizeof(*shadow_ring_context), | ||
| 122 | (void *)shadow_ring_context + | ||
| 123 | sizeof(*shadow_ring_context), | ||
| 124 | GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); | ||
| 125 | |||
| 126 | kunmap_atomic(shadow_ring_context); | ||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | static int shadow_context_status_change(struct notifier_block *nb, | ||
| 131 | unsigned long action, void *data) | ||
| 132 | { | ||
| 133 | struct intel_vgpu *vgpu = container_of(nb, | ||
| 134 | struct intel_vgpu, shadow_ctx_notifier_block); | ||
| 135 | struct drm_i915_gem_request *req = | ||
| 136 | (struct drm_i915_gem_request *)data; | ||
| 137 | struct intel_gvt_workload_scheduler *scheduler = | ||
| 138 | &vgpu->gvt->scheduler; | ||
| 139 | struct intel_vgpu_workload *workload = | ||
| 140 | scheduler->current_workload[req->engine->id]; | ||
| 141 | |||
| 142 | switch (action) { | ||
| 143 | case INTEL_CONTEXT_SCHEDULE_IN: | ||
| 144 | intel_gvt_load_render_mmio(workload->vgpu, | ||
| 145 | workload->ring_id); | ||
| 146 | atomic_set(&workload->shadow_ctx_active, 1); | ||
| 147 | break; | ||
| 148 | case INTEL_CONTEXT_SCHEDULE_OUT: | ||
| 149 | intel_gvt_restore_render_mmio(workload->vgpu, | ||
| 150 | workload->ring_id); | ||
| 151 | atomic_set(&workload->shadow_ctx_active, 0); | ||
| 152 | break; | ||
| 153 | default: | ||
| 154 | WARN_ON(1); | ||
| 155 | return NOTIFY_OK; | ||
| 156 | } | ||
| 157 | wake_up(&workload->shadow_ctx_status_wq); | ||
| 158 | return NOTIFY_OK; | ||
| 159 | } | ||
| 160 | |||
| 161 | static int dispatch_workload(struct intel_vgpu_workload *workload) | ||
| 162 | { | ||
| 163 | struct intel_vgpu *vgpu = workload->vgpu; | ||
| 164 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 165 | int ring_id = workload->ring_id; | ||
| 166 | struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; | ||
| 167 | struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; | ||
| 168 | struct drm_i915_gem_request *rq; | ||
| 169 | int ret; | ||
| 170 | |||
| 171 | gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n", | ||
| 172 | ring_id, workload); | ||
| 173 | |||
| 174 | shadow_ctx->desc_template = workload->ctx_desc.addressing_mode << | ||
| 175 | GEN8_CTX_ADDRESSING_MODE_SHIFT; | ||
| 176 | |||
| 177 | rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx); | ||
| 178 | if (IS_ERR(rq)) { | ||
| 179 | gvt_err("fail to allocate gem request\n"); | ||
| 180 | workload->status = PTR_ERR(rq); | ||
| 181 | return workload->status; | ||
| 182 | } | ||
| 183 | |||
| 184 | gvt_dbg_sched("ring id %d get i915 gem request %p\n", ring_id, rq); | ||
| 185 | |||
| 186 | workload->req = i915_gem_request_get(rq); | ||
| 187 | |||
| 188 | mutex_lock(&gvt->lock); | ||
| 189 | |||
| 190 | ret = intel_gvt_scan_and_shadow_workload(workload); | ||
| 191 | if (ret) | ||
| 192 | goto err; | ||
| 193 | |||
| 194 | ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx); | ||
| 195 | if (ret) | ||
| 196 | goto err; | ||
| 197 | |||
| 198 | ret = populate_shadow_context(workload); | ||
| 199 | if (ret) | ||
| 200 | goto err; | ||
| 201 | |||
| 202 | if (workload->prepare) { | ||
| 203 | ret = workload->prepare(workload); | ||
| 204 | if (ret) | ||
| 205 | goto err; | ||
| 206 | } | ||
| 207 | |||
| 208 | mutex_unlock(&gvt->lock); | ||
| 209 | |||
| 210 | gvt_dbg_sched("ring id %d submit workload to i915 %p\n", | ||
| 211 | ring_id, workload->req); | ||
| 212 | |||
| 213 | i915_add_request_no_flush(rq); | ||
| 214 | workload->dispatched = true; | ||
| 215 | return 0; | ||
| 216 | err: | ||
| 217 | workload->status = ret; | ||
| 218 | |||
| 219 | mutex_unlock(&gvt->lock); | ||
| 220 | |||
| 221 | i915_add_request_no_flush(rq); | ||
| 222 | return ret; | ||
| 223 | } | ||
| 224 | |||
| 225 | static struct intel_vgpu_workload *pick_next_workload( | ||
| 226 | struct intel_gvt *gvt, int ring_id) | ||
| 227 | { | ||
| 228 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | ||
| 229 | struct intel_vgpu_workload *workload = NULL; | ||
| 230 | |||
| 231 | mutex_lock(&gvt->lock); | ||
| 232 | |||
| 233 | /* | ||
| 234 | * no current vgpu / will be scheduled out / no workload | ||
| 235 | * bail out | ||
| 236 | */ | ||
| 237 | if (!scheduler->current_vgpu) { | ||
| 238 | gvt_dbg_sched("ring id %d stop - no current vgpu\n", ring_id); | ||
| 239 | goto out; | ||
| 240 | } | ||
| 241 | |||
| 242 | if (scheduler->need_reschedule) { | ||
| 243 | gvt_dbg_sched("ring id %d stop - will reschedule\n", ring_id); | ||
| 244 | goto out; | ||
| 245 | } | ||
| 246 | |||
| 247 | if (list_empty(workload_q_head(scheduler->current_vgpu, ring_id))) { | ||
| 248 | gvt_dbg_sched("ring id %d stop - no available workload\n", | ||
| 249 | ring_id); | ||
| 250 | goto out; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* | ||
| 254 | * still have current workload, maybe the workload disptacher | ||
| 255 | * fail to submit it for some reason, resubmit it. | ||
| 256 | */ | ||
| 257 | if (scheduler->current_workload[ring_id]) { | ||
| 258 | workload = scheduler->current_workload[ring_id]; | ||
| 259 | gvt_dbg_sched("ring id %d still have current workload %p\n", | ||
| 260 | ring_id, workload); | ||
| 261 | goto out; | ||
| 262 | } | ||
| 263 | |||
| 264 | /* | ||
| 265 | * pick a workload as current workload | ||
| 266 | * once current workload is set, schedule policy routines | ||
| 267 | * will wait the current workload is finished when trying to | ||
| 268 | * schedule out a vgpu. | ||
| 269 | */ | ||
| 270 | scheduler->current_workload[ring_id] = container_of( | ||
| 271 | workload_q_head(scheduler->current_vgpu, ring_id)->next, | ||
| 272 | struct intel_vgpu_workload, list); | ||
| 273 | |||
| 274 | workload = scheduler->current_workload[ring_id]; | ||
| 275 | |||
| 276 | gvt_dbg_sched("ring id %d pick new workload %p\n", ring_id, workload); | ||
| 277 | |||
| 278 | atomic_inc(&workload->vgpu->running_workload_num); | ||
| 279 | out: | ||
| 280 | mutex_unlock(&gvt->lock); | ||
| 281 | return workload; | ||
| 282 | } | ||
| 283 | |||
| 284 | static void update_guest_context(struct intel_vgpu_workload *workload) | ||
| 285 | { | ||
| 286 | struct intel_vgpu *vgpu = workload->vgpu; | ||
| 287 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 288 | int ring_id = workload->ring_id; | ||
| 289 | struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; | ||
| 290 | struct drm_i915_gem_object *ctx_obj = | ||
| 291 | shadow_ctx->engine[ring_id].state->obj; | ||
| 292 | struct execlist_ring_context *shadow_ring_context; | ||
| 293 | struct page *page; | ||
| 294 | void *src; | ||
| 295 | unsigned long context_gpa, context_page_num; | ||
| 296 | int i; | ||
| 297 | |||
| 298 | gvt_dbg_sched("ring id %d workload lrca %x\n", ring_id, | ||
| 299 | workload->ctx_desc.lrca); | ||
| 300 | |||
| 301 | context_page_num = intel_lr_context_size( | ||
| 302 | gvt->dev_priv->engine[ring_id]); | ||
| 303 | |||
| 304 | context_page_num = context_page_num >> PAGE_SHIFT; | ||
| 305 | |||
| 306 | if (IS_BROADWELL(gvt->dev_priv) && ring_id == RCS) | ||
| 307 | context_page_num = 19; | ||
| 308 | |||
| 309 | i = 2; | ||
| 310 | |||
| 311 | while (i < context_page_num) { | ||
| 312 | context_gpa = intel_vgpu_gma_to_gpa(vgpu->gtt.ggtt_mm, | ||
| 313 | (u32)((workload->ctx_desc.lrca + i) << | ||
| 314 | GTT_PAGE_SHIFT)); | ||
| 315 | if (context_gpa == INTEL_GVT_INVALID_ADDR) { | ||
| 316 | gvt_err("invalid guest context descriptor\n"); | ||
| 317 | return; | ||
| 318 | } | ||
| 319 | |||
| 320 | page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i); | ||
| 321 | src = kmap_atomic(page); | ||
| 322 | intel_gvt_hypervisor_write_gpa(vgpu, context_gpa, src, | ||
| 323 | GTT_PAGE_SIZE); | ||
| 324 | kunmap_atomic(src); | ||
| 325 | i++; | ||
| 326 | } | ||
| 327 | |||
| 328 | intel_gvt_hypervisor_write_gpa(vgpu, workload->ring_context_gpa + | ||
| 329 | RING_CTX_OFF(ring_header.val), &workload->rb_tail, 4); | ||
| 330 | |||
| 331 | page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN); | ||
| 332 | shadow_ring_context = kmap_atomic(page); | ||
| 333 | |||
| 334 | #define COPY_REG(name) \ | ||
| 335 | intel_gvt_hypervisor_write_gpa(vgpu, workload->ring_context_gpa + \ | ||
| 336 | RING_CTX_OFF(name.val), &shadow_ring_context->name.val, 4) | ||
| 337 | |||
| 338 | COPY_REG(ctx_ctrl); | ||
| 339 | COPY_REG(ctx_timestamp); | ||
| 340 | |||
| 341 | #undef COPY_REG | ||
| 342 | |||
| 343 | intel_gvt_hypervisor_write_gpa(vgpu, | ||
| 344 | workload->ring_context_gpa + | ||
| 345 | sizeof(*shadow_ring_context), | ||
| 346 | (void *)shadow_ring_context + | ||
| 347 | sizeof(*shadow_ring_context), | ||
| 348 | GTT_PAGE_SIZE - sizeof(*shadow_ring_context)); | ||
| 349 | |||
| 350 | kunmap_atomic(shadow_ring_context); | ||
| 351 | } | ||
| 352 | |||
| 353 | static void complete_current_workload(struct intel_gvt *gvt, int ring_id) | ||
| 354 | { | ||
| 355 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | ||
| 356 | struct intel_vgpu_workload *workload; | ||
| 357 | int event; | ||
| 358 | |||
| 359 | mutex_lock(&gvt->lock); | ||
| 360 | |||
| 361 | workload = scheduler->current_workload[ring_id]; | ||
| 362 | |||
| 363 | if (!workload->status && !workload->vgpu->resetting) { | ||
| 364 | wait_event(workload->shadow_ctx_status_wq, | ||
| 365 | !atomic_read(&workload->shadow_ctx_active)); | ||
| 366 | |||
| 367 | update_guest_context(workload); | ||
| 368 | |||
| 369 | for_each_set_bit(event, workload->pending_events, | ||
| 370 | INTEL_GVT_EVENT_MAX) | ||
| 371 | intel_vgpu_trigger_virtual_event(workload->vgpu, | ||
| 372 | event); | ||
| 373 | } | ||
| 374 | |||
| 375 | gvt_dbg_sched("ring id %d complete workload %p status %d\n", | ||
| 376 | ring_id, workload, workload->status); | ||
| 377 | |||
| 378 | scheduler->current_workload[ring_id] = NULL; | ||
| 379 | |||
| 380 | atomic_dec(&workload->vgpu->running_workload_num); | ||
| 381 | |||
| 382 | list_del_init(&workload->list); | ||
| 383 | workload->complete(workload); | ||
| 384 | |||
| 385 | wake_up(&scheduler->workload_complete_wq); | ||
| 386 | mutex_unlock(&gvt->lock); | ||
| 387 | } | ||
| 388 | |||
| 389 | struct workload_thread_param { | ||
| 390 | struct intel_gvt *gvt; | ||
| 391 | int ring_id; | ||
| 392 | }; | ||
| 393 | |||
| 394 | static DEFINE_MUTEX(scheduler_mutex); | ||
| 395 | |||
| 396 | static int workload_thread(void *priv) | ||
| 397 | { | ||
| 398 | struct workload_thread_param *p = (struct workload_thread_param *)priv; | ||
| 399 | struct intel_gvt *gvt = p->gvt; | ||
| 400 | int ring_id = p->ring_id; | ||
| 401 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | ||
| 402 | struct intel_vgpu_workload *workload = NULL; | ||
| 403 | int ret; | ||
| 404 | bool need_force_wake = IS_SKYLAKE(gvt->dev_priv); | ||
| 405 | |||
| 406 | kfree(p); | ||
| 407 | |||
| 408 | gvt_dbg_core("workload thread for ring %d started\n", ring_id); | ||
| 409 | |||
| 410 | while (!kthread_should_stop()) { | ||
| 411 | ret = wait_event_interruptible(scheduler->waitq[ring_id], | ||
| 412 | kthread_should_stop() || | ||
| 413 | (workload = pick_next_workload(gvt, ring_id))); | ||
| 414 | |||
| 415 | WARN_ON_ONCE(ret); | ||
| 416 | |||
| 417 | if (kthread_should_stop()) | ||
| 418 | break; | ||
| 419 | |||
| 420 | mutex_lock(&scheduler_mutex); | ||
| 421 | |||
| 422 | gvt_dbg_sched("ring id %d next workload %p vgpu %d\n", | ||
| 423 | workload->ring_id, workload, | ||
| 424 | workload->vgpu->id); | ||
| 425 | |||
| 426 | intel_runtime_pm_get(gvt->dev_priv); | ||
| 427 | |||
| 428 | gvt_dbg_sched("ring id %d will dispatch workload %p\n", | ||
| 429 | workload->ring_id, workload); | ||
| 430 | |||
| 431 | if (need_force_wake) | ||
| 432 | intel_uncore_forcewake_get(gvt->dev_priv, | ||
| 433 | FORCEWAKE_ALL); | ||
| 434 | |||
| 435 | mutex_lock(&gvt->dev_priv->drm.struct_mutex); | ||
| 436 | ret = dispatch_workload(workload); | ||
| 437 | mutex_unlock(&gvt->dev_priv->drm.struct_mutex); | ||
| 438 | |||
| 439 | if (ret) { | ||
| 440 | gvt_err("fail to dispatch workload, skip\n"); | ||
| 441 | goto complete; | ||
| 442 | } | ||
| 443 | |||
| 444 | gvt_dbg_sched("ring id %d wait workload %p\n", | ||
| 445 | workload->ring_id, workload); | ||
| 446 | |||
| 447 | workload->status = i915_wait_request(workload->req, | ||
| 448 | 0, NULL, NULL); | ||
| 449 | if (workload->status != 0) | ||
| 450 | gvt_err("fail to wait workload, skip\n"); | ||
| 451 | |||
| 452 | complete: | ||
| 453 | gvt_dbg_sched("will complete workload %p\n, status: %d\n", | ||
| 454 | workload, workload->status); | ||
| 455 | |||
| 456 | mutex_lock(&gvt->dev_priv->drm.struct_mutex); | ||
| 457 | complete_current_workload(gvt, ring_id); | ||
| 458 | mutex_unlock(&gvt->dev_priv->drm.struct_mutex); | ||
| 459 | |||
| 460 | i915_gem_request_put(fetch_and_zero(&workload->req)); | ||
| 461 | |||
| 462 | if (need_force_wake) | ||
| 463 | intel_uncore_forcewake_put(gvt->dev_priv, | ||
| 464 | FORCEWAKE_ALL); | ||
| 465 | |||
| 466 | intel_runtime_pm_put(gvt->dev_priv); | ||
| 467 | |||
| 468 | mutex_unlock(&scheduler_mutex); | ||
| 469 | |||
| 470 | } | ||
| 471 | return 0; | ||
| 472 | } | ||
| 473 | |||
| 474 | void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu) | ||
| 475 | { | ||
| 476 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 477 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | ||
| 478 | |||
| 479 | if (atomic_read(&vgpu->running_workload_num)) { | ||
| 480 | gvt_dbg_sched("wait vgpu idle\n"); | ||
| 481 | |||
| 482 | wait_event(scheduler->workload_complete_wq, | ||
| 483 | !atomic_read(&vgpu->running_workload_num)); | ||
| 484 | } | ||
| 485 | } | ||
| 486 | |||
| 487 | void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt) | ||
| 488 | { | ||
| 489 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | ||
| 490 | int i; | ||
| 491 | |||
| 492 | gvt_dbg_core("clean workload scheduler\n"); | ||
| 493 | |||
| 494 | for (i = 0; i < I915_NUM_ENGINES; i++) { | ||
| 495 | if (scheduler->thread[i]) { | ||
| 496 | kthread_stop(scheduler->thread[i]); | ||
| 497 | scheduler->thread[i] = NULL; | ||
| 498 | } | ||
| 499 | } | ||
| 500 | } | ||
| 501 | |||
| 502 | int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt) | ||
| 503 | { | ||
| 504 | struct intel_gvt_workload_scheduler *scheduler = &gvt->scheduler; | ||
| 505 | struct workload_thread_param *param = NULL; | ||
| 506 | int ret; | ||
| 507 | int i; | ||
| 508 | |||
| 509 | gvt_dbg_core("init workload scheduler\n"); | ||
| 510 | |||
| 511 | init_waitqueue_head(&scheduler->workload_complete_wq); | ||
| 512 | |||
| 513 | for (i = 0; i < I915_NUM_ENGINES; i++) { | ||
| 514 | /* check ring mask at init time */ | ||
| 515 | if (!HAS_ENGINE(gvt->dev_priv, i)) | ||
| 516 | continue; | ||
| 517 | |||
| 518 | init_waitqueue_head(&scheduler->waitq[i]); | ||
| 519 | |||
| 520 | param = kzalloc(sizeof(*param), GFP_KERNEL); | ||
| 521 | if (!param) { | ||
| 522 | ret = -ENOMEM; | ||
| 523 | goto err; | ||
| 524 | } | ||
| 525 | |||
| 526 | param->gvt = gvt; | ||
| 527 | param->ring_id = i; | ||
| 528 | |||
| 529 | scheduler->thread[i] = kthread_run(workload_thread, param, | ||
| 530 | "gvt workload %d", i); | ||
| 531 | if (IS_ERR(scheduler->thread[i])) { | ||
| 532 | gvt_err("fail to create workload thread\n"); | ||
| 533 | ret = PTR_ERR(scheduler->thread[i]); | ||
| 534 | goto err; | ||
| 535 | } | ||
| 536 | } | ||
| 537 | return 0; | ||
| 538 | err: | ||
| 539 | intel_gvt_clean_workload_scheduler(gvt); | ||
| 540 | kfree(param); | ||
| 541 | param = NULL; | ||
| 542 | return ret; | ||
| 543 | } | ||
| 544 | |||
| 545 | void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu) | ||
| 546 | { | ||
| 547 | struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; | ||
| 548 | |||
| 549 | atomic_notifier_chain_unregister(&vgpu->shadow_ctx->status_notifier, | ||
| 550 | &vgpu->shadow_ctx_notifier_block); | ||
| 551 | |||
| 552 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
| 553 | |||
| 554 | /* a little hacky to mark as ctx closed */ | ||
| 555 | vgpu->shadow_ctx->closed = true; | ||
| 556 | i915_gem_context_put(vgpu->shadow_ctx); | ||
| 557 | |||
| 558 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
| 559 | } | ||
| 560 | |||
| 561 | int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu) | ||
| 562 | { | ||
| 563 | atomic_set(&vgpu->running_workload_num, 0); | ||
| 564 | |||
| 565 | vgpu->shadow_ctx = i915_gem_context_create_gvt( | ||
| 566 | &vgpu->gvt->dev_priv->drm); | ||
| 567 | if (IS_ERR(vgpu->shadow_ctx)) | ||
| 568 | return PTR_ERR(vgpu->shadow_ctx); | ||
| 569 | |||
| 570 | vgpu->shadow_ctx->engine[RCS].initialised = true; | ||
| 571 | |||
| 572 | vgpu->shadow_ctx_notifier_block.notifier_call = | ||
| 573 | shadow_context_status_change; | ||
| 574 | |||
| 575 | atomic_notifier_chain_register(&vgpu->shadow_ctx->status_notifier, | ||
| 576 | &vgpu->shadow_ctx_notifier_block); | ||
| 577 | return 0; | ||
| 578 | } | ||
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h new file mode 100644 index 000000000000..3b30c28bff51 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/scheduler.h | |||
| @@ -0,0 +1,139 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 25 | * | ||
| 26 | * Contributors: | ||
| 27 | * Ping Gao <ping.a.gao@intel.com> | ||
| 28 | * Tina Zhang <tina.zhang@intel.com> | ||
| 29 | * Chanbin Du <changbin.du@intel.com> | ||
| 30 | * Min He <min.he@intel.com> | ||
| 31 | * Bing Niu <bing.niu@intel.com> | ||
| 32 | * Zhenyu Wang <zhenyuw@linux.intel.com> | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | #ifndef _GVT_SCHEDULER_H_ | ||
| 37 | #define _GVT_SCHEDULER_H_ | ||
| 38 | |||
| 39 | struct intel_gvt_workload_scheduler { | ||
| 40 | struct intel_vgpu *current_vgpu; | ||
| 41 | struct intel_vgpu *next_vgpu; | ||
| 42 | struct intel_vgpu_workload *current_workload[I915_NUM_ENGINES]; | ||
| 43 | bool need_reschedule; | ||
| 44 | |||
| 45 | wait_queue_head_t workload_complete_wq; | ||
| 46 | struct task_struct *thread[I915_NUM_ENGINES]; | ||
| 47 | wait_queue_head_t waitq[I915_NUM_ENGINES]; | ||
| 48 | |||
| 49 | void *sched_data; | ||
| 50 | struct intel_gvt_sched_policy_ops *sched_ops; | ||
| 51 | }; | ||
| 52 | |||
| 53 | #define INDIRECT_CTX_ADDR_MASK 0xffffffc0 | ||
| 54 | #define INDIRECT_CTX_SIZE_MASK 0x3f | ||
| 55 | struct shadow_indirect_ctx { | ||
| 56 | struct drm_i915_gem_object *obj; | ||
| 57 | unsigned long guest_gma; | ||
| 58 | unsigned long shadow_gma; | ||
| 59 | void *shadow_va; | ||
| 60 | uint32_t size; | ||
| 61 | }; | ||
| 62 | |||
| 63 | #define PER_CTX_ADDR_MASK 0xfffff000 | ||
| 64 | struct shadow_per_ctx { | ||
| 65 | unsigned long guest_gma; | ||
| 66 | unsigned long shadow_gma; | ||
| 67 | }; | ||
| 68 | |||
| 69 | struct intel_shadow_wa_ctx { | ||
| 70 | struct intel_vgpu_workload *workload; | ||
| 71 | struct shadow_indirect_ctx indirect_ctx; | ||
| 72 | struct shadow_per_ctx per_ctx; | ||
| 73 | |||
| 74 | }; | ||
| 75 | |||
| 76 | struct intel_vgpu_workload { | ||
| 77 | struct intel_vgpu *vgpu; | ||
| 78 | int ring_id; | ||
| 79 | struct drm_i915_gem_request *req; | ||
| 80 | /* if this workload has been dispatched to i915? */ | ||
| 81 | bool dispatched; | ||
| 82 | int status; | ||
| 83 | |||
| 84 | struct intel_vgpu_mm *shadow_mm; | ||
| 85 | |||
| 86 | /* different submission model may need different handler */ | ||
| 87 | int (*prepare)(struct intel_vgpu_workload *); | ||
| 88 | int (*complete)(struct intel_vgpu_workload *); | ||
| 89 | struct list_head list; | ||
| 90 | |||
| 91 | DECLARE_BITMAP(pending_events, INTEL_GVT_EVENT_MAX); | ||
| 92 | void *shadow_ring_buffer_va; | ||
| 93 | |||
| 94 | /* execlist context information */ | ||
| 95 | struct execlist_ctx_descriptor_format ctx_desc; | ||
| 96 | struct execlist_ring_context *ring_context; | ||
| 97 | unsigned long rb_head, rb_tail, rb_ctl, rb_start, rb_len; | ||
| 98 | bool restore_inhibit; | ||
| 99 | struct intel_vgpu_elsp_dwords elsp_dwords; | ||
| 100 | bool emulate_schedule_in; | ||
| 101 | atomic_t shadow_ctx_active; | ||
| 102 | wait_queue_head_t shadow_ctx_status_wq; | ||
| 103 | u64 ring_context_gpa; | ||
| 104 | |||
| 105 | /* shadow batch buffer */ | ||
| 106 | struct list_head shadow_bb; | ||
| 107 | struct intel_shadow_wa_ctx wa_ctx; | ||
| 108 | }; | ||
| 109 | |||
| 110 | /* Intel shadow batch buffer is a i915 gem object */ | ||
| 111 | struct intel_shadow_bb_entry { | ||
| 112 | struct list_head list; | ||
| 113 | struct drm_i915_gem_object *obj; | ||
| 114 | void *va; | ||
| 115 | unsigned long len; | ||
| 116 | void *bb_start_cmd_va; | ||
| 117 | }; | ||
| 118 | |||
| 119 | #define workload_q_head(vgpu, ring_id) \ | ||
| 120 | (&(vgpu->workload_q_head[ring_id])) | ||
| 121 | |||
| 122 | #define queue_workload(workload) do { \ | ||
| 123 | list_add_tail(&workload->list, \ | ||
| 124 | workload_q_head(workload->vgpu, workload->ring_id)); \ | ||
| 125 | wake_up(&workload->vgpu->gvt-> \ | ||
| 126 | scheduler.waitq[workload->ring_id]); \ | ||
| 127 | } while (0) | ||
| 128 | |||
| 129 | int intel_gvt_init_workload_scheduler(struct intel_gvt *gvt); | ||
| 130 | |||
| 131 | void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt); | ||
| 132 | |||
| 133 | void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu); | ||
| 134 | |||
| 135 | int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu); | ||
| 136 | |||
| 137 | void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu); | ||
| 138 | |||
| 139 | #endif | ||
diff --git a/drivers/gpu/drm/i915/gvt/trace.h b/drivers/gpu/drm/i915/gvt/trace.h new file mode 100644 index 000000000000..53a2d10cf3f1 --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/trace.h | |||
| @@ -0,0 +1,286 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2011-2016 Intel Corporation | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| 21 | * IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Jike Song <jike.song@intel.com> | ||
| 25 | * | ||
| 26 | * Contributors: | ||
| 27 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | |||
| 31 | #if !defined(_GVT_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) | ||
| 32 | #define _GVT_TRACE_H_ | ||
| 33 | |||
| 34 | #include <linux/types.h> | ||
| 35 | #include <linux/stringify.h> | ||
| 36 | #include <linux/tracepoint.h> | ||
| 37 | #include <asm/tsc.h> | ||
| 38 | |||
| 39 | #undef TRACE_SYSTEM | ||
| 40 | #define TRACE_SYSTEM gvt | ||
| 41 | |||
| 42 | TRACE_EVENT(spt_alloc, | ||
| 43 | TP_PROTO(int id, void *spt, int type, unsigned long mfn, | ||
| 44 | unsigned long gpt_gfn), | ||
| 45 | |||
| 46 | TP_ARGS(id, spt, type, mfn, gpt_gfn), | ||
| 47 | |||
| 48 | TP_STRUCT__entry( | ||
| 49 | __field(int, id) | ||
| 50 | __field(void *, spt) | ||
| 51 | __field(int, type) | ||
| 52 | __field(unsigned long, mfn) | ||
| 53 | __field(unsigned long, gpt_gfn) | ||
| 54 | ), | ||
| 55 | |||
| 56 | TP_fast_assign( | ||
| 57 | __entry->id = id; | ||
| 58 | __entry->spt = spt; | ||
| 59 | __entry->type = type; | ||
| 60 | __entry->mfn = mfn; | ||
| 61 | __entry->gpt_gfn = gpt_gfn; | ||
| 62 | ), | ||
| 63 | |||
| 64 | TP_printk("VM%d [alloc] spt %p type %d mfn 0x%lx gfn 0x%lx\n", | ||
| 65 | __entry->id, | ||
| 66 | __entry->spt, | ||
| 67 | __entry->type, | ||
| 68 | __entry->mfn, | ||
| 69 | __entry->gpt_gfn) | ||
| 70 | ); | ||
| 71 | |||
| 72 | TRACE_EVENT(spt_free, | ||
| 73 | TP_PROTO(int id, void *spt, int type), | ||
| 74 | |||
| 75 | TP_ARGS(id, spt, type), | ||
| 76 | |||
| 77 | TP_STRUCT__entry( | ||
| 78 | __field(int, id) | ||
| 79 | __field(void *, spt) | ||
| 80 | __field(int, type) | ||
| 81 | ), | ||
| 82 | |||
| 83 | TP_fast_assign( | ||
| 84 | __entry->id = id; | ||
| 85 | __entry->spt = spt; | ||
| 86 | __entry->type = type; | ||
| 87 | ), | ||
| 88 | |||
| 89 | TP_printk("VM%u [free] spt %p type %d\n", | ||
| 90 | __entry->id, | ||
| 91 | __entry->spt, | ||
| 92 | __entry->type) | ||
| 93 | ); | ||
| 94 | |||
| 95 | #define MAX_BUF_LEN 256 | ||
| 96 | |||
| 97 | TRACE_EVENT(gma_index, | ||
| 98 | TP_PROTO(const char *prefix, unsigned long gma, | ||
| 99 | unsigned long index), | ||
| 100 | |||
| 101 | TP_ARGS(prefix, gma, index), | ||
| 102 | |||
| 103 | TP_STRUCT__entry( | ||
| 104 | __array(char, buf, MAX_BUF_LEN) | ||
| 105 | ), | ||
| 106 | |||
| 107 | TP_fast_assign( | ||
| 108 | snprintf(__entry->buf, MAX_BUF_LEN, | ||
| 109 | "%s gma 0x%lx index 0x%lx\n", prefix, gma, index); | ||
| 110 | ), | ||
| 111 | |||
| 112 | TP_printk("%s", __entry->buf) | ||
| 113 | ); | ||
| 114 | |||
| 115 | TRACE_EVENT(gma_translate, | ||
| 116 | TP_PROTO(int id, char *type, int ring_id, int pt_level, | ||
| 117 | unsigned long gma, unsigned long gpa), | ||
| 118 | |||
| 119 | TP_ARGS(id, type, ring_id, pt_level, gma, gpa), | ||
| 120 | |||
| 121 | TP_STRUCT__entry( | ||
| 122 | __array(char, buf, MAX_BUF_LEN) | ||
| 123 | ), | ||
| 124 | |||
| 125 | TP_fast_assign( | ||
| 126 | snprintf(__entry->buf, MAX_BUF_LEN, | ||
| 127 | "VM%d %s ring %d pt_level %d gma 0x%lx -> gpa 0x%lx\n", | ||
| 128 | id, type, ring_id, pt_level, gma, gpa); | ||
| 129 | ), | ||
| 130 | |||
| 131 | TP_printk("%s", __entry->buf) | ||
| 132 | ); | ||
| 133 | |||
| 134 | TRACE_EVENT(spt_refcount, | ||
| 135 | TP_PROTO(int id, char *action, void *spt, int before, int after), | ||
| 136 | |||
| 137 | TP_ARGS(id, action, spt, before, after), | ||
| 138 | |||
| 139 | TP_STRUCT__entry( | ||
| 140 | __array(char, buf, MAX_BUF_LEN) | ||
| 141 | ), | ||
| 142 | |||
| 143 | TP_fast_assign( | ||
| 144 | snprintf(__entry->buf, MAX_BUF_LEN, | ||
| 145 | "VM%d [%s] spt %p before %d -> after %d\n", | ||
| 146 | id, action, spt, before, after); | ||
| 147 | ), | ||
| 148 | |||
| 149 | TP_printk("%s", __entry->buf) | ||
| 150 | ); | ||
| 151 | |||
| 152 | TRACE_EVENT(spt_change, | ||
| 153 | TP_PROTO(int id, char *action, void *spt, unsigned long gfn, | ||
| 154 | int type), | ||
| 155 | |||
| 156 | TP_ARGS(id, action, spt, gfn, type), | ||
| 157 | |||
| 158 | TP_STRUCT__entry( | ||
| 159 | __array(char, buf, MAX_BUF_LEN) | ||
| 160 | ), | ||
| 161 | |||
| 162 | TP_fast_assign( | ||
| 163 | snprintf(__entry->buf, MAX_BUF_LEN, | ||
| 164 | "VM%d [%s] spt %p gfn 0x%lx type %d\n", | ||
| 165 | id, action, spt, gfn, type); | ||
| 166 | ), | ||
| 167 | |||
| 168 | TP_printk("%s", __entry->buf) | ||
| 169 | ); | ||
| 170 | |||
| 171 | TRACE_EVENT(gpt_change, | ||
| 172 | TP_PROTO(int id, const char *tag, void *spt, int type, u64 v, | ||
| 173 | unsigned long index), | ||
| 174 | |||
| 175 | TP_ARGS(id, tag, spt, type, v, index), | ||
| 176 | |||
| 177 | TP_STRUCT__entry( | ||
| 178 | __array(char, buf, MAX_BUF_LEN) | ||
| 179 | ), | ||
| 180 | |||
| 181 | TP_fast_assign( | ||
| 182 | snprintf(__entry->buf, MAX_BUF_LEN, | ||
| 183 | "VM%d [%s] spt %p type %d entry 0x%llx index 0x%lx\n", | ||
| 184 | id, tag, spt, type, v, index); | ||
| 185 | ), | ||
| 186 | |||
| 187 | TP_printk("%s", __entry->buf) | ||
| 188 | ); | ||
| 189 | |||
| 190 | TRACE_EVENT(oos_change, | ||
| 191 | TP_PROTO(int id, const char *tag, int page_id, void *gpt, int type), | ||
| 192 | |||
| 193 | TP_ARGS(id, tag, page_id, gpt, type), | ||
| 194 | |||
| 195 | TP_STRUCT__entry( | ||
| 196 | __array(char, buf, MAX_BUF_LEN) | ||
| 197 | ), | ||
| 198 | |||
| 199 | TP_fast_assign( | ||
| 200 | snprintf(__entry->buf, MAX_BUF_LEN, | ||
| 201 | "VM%d [oos %s] page id %d gpt %p type %d\n", | ||
| 202 | id, tag, page_id, gpt, type); | ||
| 203 | ), | ||
| 204 | |||
| 205 | TP_printk("%s", __entry->buf) | ||
| 206 | ); | ||
| 207 | |||
| 208 | TRACE_EVENT(oos_sync, | ||
| 209 | TP_PROTO(int id, int page_id, void *gpt, int type, u64 v, | ||
| 210 | unsigned long index), | ||
| 211 | |||
| 212 | TP_ARGS(id, page_id, gpt, type, v, index), | ||
| 213 | |||
| 214 | TP_STRUCT__entry( | ||
| 215 | __array(char, buf, MAX_BUF_LEN) | ||
| 216 | ), | ||
| 217 | |||
| 218 | TP_fast_assign( | ||
| 219 | snprintf(__entry->buf, MAX_BUF_LEN, | ||
| 220 | "VM%d [oos sync] page id %d gpt %p type %d entry 0x%llx index 0x%lx\n", | ||
| 221 | id, page_id, gpt, type, v, index); | ||
| 222 | ), | ||
| 223 | |||
| 224 | TP_printk("%s", __entry->buf) | ||
| 225 | ); | ||
| 226 | |||
| 227 | #define MAX_CMD_STR_LEN 256 | ||
| 228 | TRACE_EVENT(gvt_command, | ||
| 229 | TP_PROTO(u8 vm_id, u8 ring_id, u32 ip_gma, u32 *cmd_va, u32 cmd_len, bool ring_buffer_cmd, cycles_t cost_pre_cmd_handler, cycles_t cost_cmd_handler), | ||
| 230 | |||
| 231 | TP_ARGS(vm_id, ring_id, ip_gma, cmd_va, cmd_len, ring_buffer_cmd, cost_pre_cmd_handler, cost_cmd_handler), | ||
| 232 | |||
| 233 | TP_STRUCT__entry( | ||
| 234 | __field(u8, vm_id) | ||
| 235 | __field(u8, ring_id) | ||
| 236 | __field(int, i) | ||
| 237 | __array(char, tmp_buf, MAX_CMD_STR_LEN) | ||
| 238 | __array(char, cmd_str, MAX_CMD_STR_LEN) | ||
| 239 | ), | ||
| 240 | |||
| 241 | TP_fast_assign( | ||
| 242 | __entry->vm_id = vm_id; | ||
| 243 | __entry->ring_id = ring_id; | ||
| 244 | __entry->cmd_str[0] = '\0'; | ||
| 245 | snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "VM(%d) Ring(%d): %s ip(%08x) pre handler cost (%llu), handler cost (%llu) ", vm_id, ring_id, ring_buffer_cmd ? "RB":"BB", ip_gma, cost_pre_cmd_handler, cost_cmd_handler); | ||
| 246 | strcat(__entry->cmd_str, __entry->tmp_buf); | ||
| 247 | entry->i = 0; | ||
| 248 | while (cmd_len > 0) { | ||
| 249 | if (cmd_len >= 8) { | ||
| 250 | snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x %08x %08x %08x %08x %08x %08x ", | ||
| 251 | cmd_va[__entry->i], cmd_va[__entry->i+1], cmd_va[__entry->i+2], cmd_va[__entry->i+3], | ||
| 252 | cmd_va[__entry->i+4], cmd_va[__entry->i+5], cmd_va[__entry->i+6], cmd_va[__entry->i+7]); | ||
| 253 | __entry->i += 8; | ||
| 254 | cmd_len -= 8; | ||
| 255 | strcat(__entry->cmd_str, __entry->tmp_buf); | ||
| 256 | } else if (cmd_len >= 4) { | ||
| 257 | snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x %08x %08x ", | ||
| 258 | cmd_va[__entry->i], cmd_va[__entry->i+1], cmd_va[__entry->i+2], cmd_va[__entry->i+3]); | ||
| 259 | __entry->i += 4; | ||
| 260 | cmd_len -= 4; | ||
| 261 | strcat(__entry->cmd_str, __entry->tmp_buf); | ||
| 262 | } else if (cmd_len >= 2) { | ||
| 263 | snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x %08x ", cmd_va[__entry->i], cmd_va[__entry->i+1]); | ||
| 264 | __entry->i += 2; | ||
| 265 | cmd_len -= 2; | ||
| 266 | strcat(__entry->cmd_str, __entry->tmp_buf); | ||
| 267 | } else if (cmd_len == 1) { | ||
| 268 | snprintf(__entry->tmp_buf, MAX_CMD_STR_LEN, "%08x ", cmd_va[__entry->i]); | ||
| 269 | __entry->i += 1; | ||
| 270 | cmd_len -= 1; | ||
| 271 | strcat(__entry->cmd_str, __entry->tmp_buf); | ||
| 272 | } | ||
| 273 | } | ||
| 274 | strcat(__entry->cmd_str, "\n"); | ||
| 275 | ), | ||
| 276 | |||
| 277 | TP_printk("%s", __entry->cmd_str) | ||
| 278 | ); | ||
| 279 | #endif /* _GVT_TRACE_H_ */ | ||
| 280 | |||
| 281 | /* This part must be out of protection */ | ||
| 282 | #undef TRACE_INCLUDE_PATH | ||
| 283 | #define TRACE_INCLUDE_PATH . | ||
| 284 | #undef TRACE_INCLUDE_FILE | ||
| 285 | #define TRACE_INCLUDE_FILE trace | ||
| 286 | #include <trace/define_trace.h> | ||
diff --git a/drivers/gpu/drm/i915/gvt/trace_points.c b/drivers/gpu/drm/i915/gvt/trace_points.c new file mode 100644 index 000000000000..a3deed692b9c --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/trace_points.c | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Jike Song <jike.song@intel.com> | ||
| 25 | * | ||
| 26 | * Contributors: | ||
| 27 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include "trace.h" | ||
| 32 | |||
| 33 | #ifndef __CHECKER__ | ||
| 34 | #define CREATE_TRACE_POINTS | ||
| 35 | #include "trace.h" | ||
| 36 | #endif | ||
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c new file mode 100644 index 000000000000..9401436d721f --- /dev/null +++ b/drivers/gpu/drm/i915/gvt/vgpu.c | |||
| @@ -0,0 +1,274 @@ | |||
| 1 | /* | ||
| 2 | * Copyright(c) 2011-2016 Intel Corporation. All rights reserved. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | * SOFTWARE. | ||
| 22 | * | ||
| 23 | * Authors: | ||
| 24 | * Eddie Dong <eddie.dong@intel.com> | ||
| 25 | * Kevin Tian <kevin.tian@intel.com> | ||
| 26 | * | ||
| 27 | * Contributors: | ||
| 28 | * Ping Gao <ping.a.gao@intel.com> | ||
| 29 | * Zhi Wang <zhi.a.wang@intel.com> | ||
| 30 | * Bing Niu <bing.niu@intel.com> | ||
| 31 | * | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include "i915_drv.h" | ||
| 35 | #include "gvt.h" | ||
| 36 | #include "i915_pvinfo.h" | ||
| 37 | |||
| 38 | static void clean_vgpu_mmio(struct intel_vgpu *vgpu) | ||
| 39 | { | ||
| 40 | vfree(vgpu->mmio.vreg); | ||
| 41 | vgpu->mmio.vreg = vgpu->mmio.sreg = NULL; | ||
| 42 | } | ||
| 43 | |||
| 44 | static int setup_vgpu_mmio(struct intel_vgpu *vgpu) | ||
| 45 | { | ||
| 46 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 47 | const struct intel_gvt_device_info *info = &gvt->device_info; | ||
| 48 | |||
| 49 | vgpu->mmio.vreg = vzalloc(info->mmio_size * 2); | ||
| 50 | if (!vgpu->mmio.vreg) | ||
| 51 | return -ENOMEM; | ||
| 52 | |||
| 53 | vgpu->mmio.sreg = vgpu->mmio.vreg + info->mmio_size; | ||
| 54 | |||
| 55 | memcpy(vgpu->mmio.vreg, gvt->firmware.mmio, info->mmio_size); | ||
| 56 | memcpy(vgpu->mmio.sreg, gvt->firmware.mmio, info->mmio_size); | ||
| 57 | |||
| 58 | vgpu_vreg(vgpu, GEN6_GT_THREAD_STATUS_REG) = 0; | ||
| 59 | |||
| 60 | /* set the bit 0:2(Core C-State ) to C0 */ | ||
| 61 | vgpu_vreg(vgpu, GEN6_GT_CORE_STATUS) = 0; | ||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static void setup_vgpu_cfg_space(struct intel_vgpu *vgpu, | ||
| 66 | struct intel_vgpu_creation_params *param) | ||
| 67 | { | ||
| 68 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 69 | const struct intel_gvt_device_info *info = &gvt->device_info; | ||
| 70 | u16 *gmch_ctl; | ||
| 71 | int i; | ||
| 72 | |||
| 73 | memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space, | ||
| 74 | info->cfg_space_size); | ||
| 75 | |||
| 76 | if (!param->primary) { | ||
| 77 | vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] = | ||
| 78 | INTEL_GVT_PCI_CLASS_VGA_OTHER; | ||
| 79 | vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] = | ||
| 80 | INTEL_GVT_PCI_CLASS_VGA_OTHER; | ||
| 81 | } | ||
| 82 | |||
| 83 | /* Show guest that there isn't any stolen memory.*/ | ||
| 84 | gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL); | ||
| 85 | *gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT); | ||
| 86 | |||
| 87 | intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2, | ||
| 88 | gvt_aperture_pa_base(gvt), true); | ||
| 89 | |||
| 90 | vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO | ||
| 91 | | PCI_COMMAND_MEMORY | ||
| 92 | | PCI_COMMAND_MASTER); | ||
| 93 | /* | ||
| 94 | * Clear the bar upper 32bit and let guest to assign the new value | ||
| 95 | */ | ||
| 96 | memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4); | ||
| 97 | memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4); | ||
| 98 | |||
| 99 | for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) { | ||
| 100 | vgpu->cfg_space.bar[i].size = pci_resource_len( | ||
| 101 | gvt->dev_priv->drm.pdev, i * 2); | ||
| 102 | vgpu->cfg_space.bar[i].tracked = false; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | static void populate_pvinfo_page(struct intel_vgpu *vgpu) | ||
| 107 | { | ||
| 108 | /* setup the ballooning information */ | ||
| 109 | vgpu_vreg64(vgpu, vgtif_reg(magic)) = VGT_MAGIC; | ||
| 110 | vgpu_vreg(vgpu, vgtif_reg(version_major)) = 1; | ||
| 111 | vgpu_vreg(vgpu, vgtif_reg(version_minor)) = 0; | ||
| 112 | vgpu_vreg(vgpu, vgtif_reg(display_ready)) = 0; | ||
| 113 | vgpu_vreg(vgpu, vgtif_reg(vgt_id)) = vgpu->id; | ||
| 114 | vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) = | ||
| 115 | vgpu_aperture_gmadr_base(vgpu); | ||
| 116 | vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.size)) = | ||
| 117 | vgpu_aperture_sz(vgpu); | ||
| 118 | vgpu_vreg(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.base)) = | ||
| 119 | vgpu_hidden_gmadr_base(vgpu); | ||
| 120 | vgpu_vreg(vgpu, vgtif_reg(avail_rs.nonmappable_gmadr.size)) = | ||
| 121 | vgpu_hidden_sz(vgpu); | ||
| 122 | |||
| 123 | vgpu_vreg(vgpu, vgtif_reg(avail_rs.fence_num)) = vgpu_fence_sz(vgpu); | ||
| 124 | |||
| 125 | gvt_dbg_core("Populate PVINFO PAGE for vGPU %d\n", vgpu->id); | ||
| 126 | gvt_dbg_core("aperture base [GMADR] 0x%llx size 0x%llx\n", | ||
| 127 | vgpu_aperture_gmadr_base(vgpu), vgpu_aperture_sz(vgpu)); | ||
| 128 | gvt_dbg_core("hidden base [GMADR] 0x%llx size=0x%llx\n", | ||
| 129 | vgpu_hidden_gmadr_base(vgpu), vgpu_hidden_sz(vgpu)); | ||
| 130 | gvt_dbg_core("fence size %d\n", vgpu_fence_sz(vgpu)); | ||
| 131 | |||
| 132 | WARN_ON(sizeof(struct vgt_if) != VGT_PVINFO_SIZE); | ||
| 133 | } | ||
| 134 | |||
| 135 | /** | ||
| 136 | * intel_gvt_destroy_vgpu - destroy a virtual GPU | ||
| 137 | * @vgpu: virtual GPU | ||
| 138 | * | ||
| 139 | * This function is called when user wants to destroy a virtual GPU. | ||
| 140 | * | ||
| 141 | */ | ||
| 142 | void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) | ||
| 143 | { | ||
| 144 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 145 | |||
| 146 | mutex_lock(&gvt->lock); | ||
| 147 | |||
| 148 | vgpu->active = false; | ||
| 149 | idr_remove(&gvt->vgpu_idr, vgpu->id); | ||
| 150 | |||
| 151 | if (atomic_read(&vgpu->running_workload_num)) { | ||
| 152 | mutex_unlock(&gvt->lock); | ||
| 153 | intel_gvt_wait_vgpu_idle(vgpu); | ||
| 154 | mutex_lock(&gvt->lock); | ||
| 155 | } | ||
| 156 | |||
| 157 | intel_vgpu_stop_schedule(vgpu); | ||
| 158 | intel_vgpu_clean_sched_policy(vgpu); | ||
| 159 | intel_vgpu_clean_gvt_context(vgpu); | ||
| 160 | intel_vgpu_clean_execlist(vgpu); | ||
| 161 | intel_vgpu_clean_display(vgpu); | ||
| 162 | intel_vgpu_clean_opregion(vgpu); | ||
| 163 | intel_vgpu_clean_gtt(vgpu); | ||
| 164 | intel_gvt_hypervisor_detach_vgpu(vgpu); | ||
| 165 | intel_vgpu_free_resource(vgpu); | ||
| 166 | clean_vgpu_mmio(vgpu); | ||
| 167 | vfree(vgpu); | ||
| 168 | |||
| 169 | mutex_unlock(&gvt->lock); | ||
| 170 | } | ||
| 171 | |||
| 172 | /** | ||
| 173 | * intel_gvt_create_vgpu - create a virtual GPU | ||
| 174 | * @gvt: GVT device | ||
| 175 | * @param: vGPU creation parameters | ||
| 176 | * | ||
| 177 | * This function is called when user wants to create a virtual GPU. | ||
| 178 | * | ||
| 179 | * Returns: | ||
| 180 | * pointer to intel_vgpu, error pointer if failed. | ||
| 181 | */ | ||
| 182 | struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt, | ||
| 183 | struct intel_vgpu_creation_params *param) | ||
| 184 | { | ||
| 185 | struct intel_vgpu *vgpu; | ||
| 186 | int ret; | ||
| 187 | |||
| 188 | gvt_dbg_core("handle %llu low %llu MB high %llu MB fence %llu\n", | ||
| 189 | param->handle, param->low_gm_sz, param->high_gm_sz, | ||
| 190 | param->fence_sz); | ||
| 191 | |||
| 192 | vgpu = vzalloc(sizeof(*vgpu)); | ||
| 193 | if (!vgpu) | ||
| 194 | return ERR_PTR(-ENOMEM); | ||
| 195 | |||
| 196 | mutex_lock(&gvt->lock); | ||
| 197 | |||
| 198 | ret = idr_alloc(&gvt->vgpu_idr, vgpu, 1, GVT_MAX_VGPU, GFP_KERNEL); | ||
| 199 | if (ret < 0) | ||
| 200 | goto out_free_vgpu; | ||
| 201 | |||
| 202 | vgpu->id = ret; | ||
| 203 | vgpu->handle = param->handle; | ||
| 204 | vgpu->gvt = gvt; | ||
| 205 | bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES); | ||
| 206 | |||
| 207 | setup_vgpu_cfg_space(vgpu, param); | ||
| 208 | |||
| 209 | ret = setup_vgpu_mmio(vgpu); | ||
| 210 | if (ret) | ||
| 211 | goto out_free_vgpu; | ||
| 212 | |||
| 213 | ret = intel_vgpu_alloc_resource(vgpu, param); | ||
| 214 | if (ret) | ||
| 215 | goto out_clean_vgpu_mmio; | ||
| 216 | |||
| 217 | populate_pvinfo_page(vgpu); | ||
| 218 | |||
| 219 | ret = intel_gvt_hypervisor_attach_vgpu(vgpu); | ||
| 220 | if (ret) | ||
| 221 | goto out_clean_vgpu_resource; | ||
| 222 | |||
| 223 | ret = intel_vgpu_init_gtt(vgpu); | ||
| 224 | if (ret) | ||
| 225 | goto out_detach_hypervisor_vgpu; | ||
| 226 | |||
| 227 | if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_KVM) { | ||
| 228 | ret = intel_vgpu_init_opregion(vgpu, 0); | ||
| 229 | if (ret) | ||
| 230 | goto out_clean_gtt; | ||
| 231 | } | ||
| 232 | |||
| 233 | ret = intel_vgpu_init_display(vgpu); | ||
| 234 | if (ret) | ||
| 235 | goto out_clean_opregion; | ||
| 236 | |||
| 237 | ret = intel_vgpu_init_execlist(vgpu); | ||
| 238 | if (ret) | ||
| 239 | goto out_clean_display; | ||
| 240 | |||
| 241 | ret = intel_vgpu_init_gvt_context(vgpu); | ||
| 242 | if (ret) | ||
| 243 | goto out_clean_execlist; | ||
| 244 | |||
| 245 | ret = intel_vgpu_init_sched_policy(vgpu); | ||
| 246 | if (ret) | ||
| 247 | goto out_clean_shadow_ctx; | ||
| 248 | |||
| 249 | vgpu->active = true; | ||
| 250 | mutex_unlock(&gvt->lock); | ||
| 251 | |||
| 252 | return vgpu; | ||
| 253 | |||
| 254 | out_clean_shadow_ctx: | ||
| 255 | intel_vgpu_clean_gvt_context(vgpu); | ||
| 256 | out_clean_execlist: | ||
| 257 | intel_vgpu_clean_execlist(vgpu); | ||
| 258 | out_clean_display: | ||
| 259 | intel_vgpu_clean_display(vgpu); | ||
| 260 | out_clean_opregion: | ||
| 261 | intel_vgpu_clean_opregion(vgpu); | ||
| 262 | out_clean_gtt: | ||
| 263 | intel_vgpu_clean_gtt(vgpu); | ||
| 264 | out_detach_hypervisor_vgpu: | ||
| 265 | intel_gvt_hypervisor_detach_vgpu(vgpu); | ||
| 266 | out_clean_vgpu_resource: | ||
| 267 | intel_vgpu_free_resource(vgpu); | ||
| 268 | out_clean_vgpu_mmio: | ||
| 269 | clean_vgpu_mmio(vgpu); | ||
| 270 | out_free_vgpu: | ||
| 271 | vfree(vgpu); | ||
| 272 | mutex_unlock(&gvt->lock); | ||
| 273 | return ERR_PTR(ret); | ||
| 274 | } | ||
diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 70980f82a15b..f191d7b66b1d 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c | |||
| @@ -1308,10 +1308,11 @@ int intel_engine_cmd_parser(struct intel_engine_cs *engine, | |||
| 1308 | int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv) | 1308 | int i915_cmd_parser_get_version(struct drm_i915_private *dev_priv) |
| 1309 | { | 1309 | { |
| 1310 | struct intel_engine_cs *engine; | 1310 | struct intel_engine_cs *engine; |
| 1311 | enum intel_engine_id id; | ||
| 1311 | bool active = false; | 1312 | bool active = false; |
| 1312 | 1313 | ||
| 1313 | /* If the command parser is not enabled, report 0 - unsupported */ | 1314 | /* If the command parser is not enabled, report 0 - unsupported */ |
| 1314 | for_each_engine(engine, dev_priv) { | 1315 | for_each_engine(engine, dev_priv, id) { |
| 1315 | if (intel_engine_needs_cmd_parser(engine)) { | 1316 | if (intel_engine_needs_cmd_parser(engine)) { |
| 1316 | active = true; | 1317 | active = true; |
| 1317 | break; | 1318 | break; |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 6c7bb87f764e..20638d22bbad 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
| @@ -79,10 +79,8 @@ static int i915_capabilities(struct seq_file *m, void *data) | |||
| 79 | seq_printf(m, "gen: %d\n", INTEL_GEN(dev_priv)); | 79 | seq_printf(m, "gen: %d\n", INTEL_GEN(dev_priv)); |
| 80 | seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev_priv)); | 80 | seq_printf(m, "pch: %d\n", INTEL_PCH_TYPE(dev_priv)); |
| 81 | #define PRINT_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x)) | 81 | #define PRINT_FLAG(x) seq_printf(m, #x ": %s\n", yesno(info->x)) |
| 82 | #define SEP_SEMICOLON ; | 82 | DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); |
| 83 | DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON); | ||
| 84 | #undef PRINT_FLAG | 83 | #undef PRINT_FLAG |
| 85 | #undef SEP_SEMICOLON | ||
| 86 | 84 | ||
| 87 | return 0; | 85 | return 0; |
| 88 | } | 86 | } |
| @@ -109,7 +107,7 @@ static char get_tiling_flag(struct drm_i915_gem_object *obj) | |||
| 109 | 107 | ||
| 110 | static char get_global_flag(struct drm_i915_gem_object *obj) | 108 | static char get_global_flag(struct drm_i915_gem_object *obj) |
| 111 | { | 109 | { |
| 112 | return i915_gem_object_to_ggtt(obj, NULL) ? 'g' : ' '; | 110 | return obj->fault_mappable ? 'g' : ' '; |
| 113 | } | 111 | } |
| 114 | 112 | ||
| 115 | static char get_pin_mapped_flag(struct drm_i915_gem_object *obj) | 113 | static char get_pin_mapped_flag(struct drm_i915_gem_object *obj) |
| @@ -152,7 +150,7 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) | |||
| 152 | obj->base.size / 1024, | 150 | obj->base.size / 1024, |
| 153 | obj->base.read_domains, | 151 | obj->base.read_domains, |
| 154 | obj->base.write_domain); | 152 | obj->base.write_domain); |
| 155 | for_each_engine_id(engine, dev_priv, id) | 153 | for_each_engine(engine, dev_priv, id) |
| 156 | seq_printf(m, "%x ", | 154 | seq_printf(m, "%x ", |
| 157 | i915_gem_active_get_seqno(&obj->last_read[id], | 155 | i915_gem_active_get_seqno(&obj->last_read[id], |
| 158 | &obj->base.dev->struct_mutex)); | 156 | &obj->base.dev->struct_mutex)); |
| @@ -188,15 +186,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) | |||
| 188 | } | 186 | } |
| 189 | if (obj->stolen) | 187 | if (obj->stolen) |
| 190 | seq_printf(m, " (stolen: %08llx)", obj->stolen->start); | 188 | seq_printf(m, " (stolen: %08llx)", obj->stolen->start); |
| 191 | if (obj->pin_display || obj->fault_mappable) { | ||
| 192 | char s[3], *t = s; | ||
| 193 | if (obj->pin_display) | ||
| 194 | *t++ = 'p'; | ||
| 195 | if (obj->fault_mappable) | ||
| 196 | *t++ = 'f'; | ||
| 197 | *t = '\0'; | ||
| 198 | seq_printf(m, " (%s mappable)", s); | ||
| 199 | } | ||
| 200 | 189 | ||
| 201 | engine = i915_gem_active_get_engine(&obj->last_write, | 190 | engine = i915_gem_active_get_engine(&obj->last_write, |
| 202 | &dev_priv->drm.struct_mutex); | 191 | &dev_priv->drm.struct_mutex); |
| @@ -334,11 +323,12 @@ static void print_batch_pool_stats(struct seq_file *m, | |||
| 334 | struct drm_i915_gem_object *obj; | 323 | struct drm_i915_gem_object *obj; |
| 335 | struct file_stats stats; | 324 | struct file_stats stats; |
| 336 | struct intel_engine_cs *engine; | 325 | struct intel_engine_cs *engine; |
| 326 | enum intel_engine_id id; | ||
| 337 | int j; | 327 | int j; |
| 338 | 328 | ||
| 339 | memset(&stats, 0, sizeof(stats)); | 329 | memset(&stats, 0, sizeof(stats)); |
| 340 | 330 | ||
| 341 | for_each_engine(engine, dev_priv) { | 331 | for_each_engine(engine, dev_priv, id) { |
| 342 | for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { | 332 | for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { |
| 343 | list_for_each_entry(obj, | 333 | list_for_each_entry(obj, |
| 344 | &engine->batch_pool.cache_list[j], | 334 | &engine->batch_pool.cache_list[j], |
| @@ -402,7 +392,7 @@ static int i915_gem_object_info(struct seq_file *m, void *data) | |||
| 402 | if (ret) | 392 | if (ret) |
| 403 | return ret; | 393 | return ret; |
| 404 | 394 | ||
| 405 | seq_printf(m, "%u objects, %zu bytes\n", | 395 | seq_printf(m, "%u objects, %llu bytes\n", |
| 406 | dev_priv->mm.object_count, | 396 | dev_priv->mm.object_count, |
| 407 | dev_priv->mm.object_memory); | 397 | dev_priv->mm.object_memory); |
| 408 | 398 | ||
| @@ -607,6 +597,7 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) | |||
| 607 | struct drm_device *dev = &dev_priv->drm; | 597 | struct drm_device *dev = &dev_priv->drm; |
| 608 | struct drm_i915_gem_object *obj; | 598 | struct drm_i915_gem_object *obj; |
| 609 | struct intel_engine_cs *engine; | 599 | struct intel_engine_cs *engine; |
| 600 | enum intel_engine_id id; | ||
| 610 | int total = 0; | 601 | int total = 0; |
| 611 | int ret, j; | 602 | int ret, j; |
| 612 | 603 | ||
| @@ -614,7 +605,7 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) | |||
| 614 | if (ret) | 605 | if (ret) |
| 615 | return ret; | 606 | return ret; |
| 616 | 607 | ||
| 617 | for_each_engine(engine, dev_priv) { | 608 | for_each_engine(engine, dev_priv, id) { |
| 618 | for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { | 609 | for (j = 0; j < ARRAY_SIZE(engine->batch_pool.cache_list); j++) { |
| 619 | int count; | 610 | int count; |
| 620 | 611 | ||
| @@ -645,12 +636,30 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) | |||
| 645 | return 0; | 636 | return 0; |
| 646 | } | 637 | } |
| 647 | 638 | ||
| 639 | static void print_request(struct seq_file *m, | ||
| 640 | struct drm_i915_gem_request *rq, | ||
| 641 | const char *prefix) | ||
| 642 | { | ||
| 643 | struct pid *pid = rq->ctx->pid; | ||
| 644 | struct task_struct *task; | ||
| 645 | |||
| 646 | rcu_read_lock(); | ||
| 647 | task = pid ? pid_task(pid, PIDTYPE_PID) : NULL; | ||
| 648 | seq_printf(m, "%s%x [%x:%x] @ %d: %s [%d]\n", prefix, | ||
| 649 | rq->fence.seqno, rq->ctx->hw_id, rq->fence.seqno, | ||
| 650 | jiffies_to_msecs(jiffies - rq->emitted_jiffies), | ||
| 651 | task ? task->comm : "<unknown>", | ||
| 652 | task ? task->pid : -1); | ||
| 653 | rcu_read_unlock(); | ||
| 654 | } | ||
| 655 | |||
| 648 | static int i915_gem_request_info(struct seq_file *m, void *data) | 656 | static int i915_gem_request_info(struct seq_file *m, void *data) |
| 649 | { | 657 | { |
| 650 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | 658 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
| 651 | struct drm_device *dev = &dev_priv->drm; | 659 | struct drm_device *dev = &dev_priv->drm; |
| 652 | struct intel_engine_cs *engine; | ||
| 653 | struct drm_i915_gem_request *req; | 660 | struct drm_i915_gem_request *req; |
| 661 | struct intel_engine_cs *engine; | ||
| 662 | enum intel_engine_id id; | ||
| 654 | int ret, any; | 663 | int ret, any; |
| 655 | 664 | ||
| 656 | ret = mutex_lock_interruptible(&dev->struct_mutex); | 665 | ret = mutex_lock_interruptible(&dev->struct_mutex); |
| @@ -658,7 +667,7 @@ static int i915_gem_request_info(struct seq_file *m, void *data) | |||
| 658 | return ret; | 667 | return ret; |
| 659 | 668 | ||
| 660 | any = 0; | 669 | any = 0; |
| 661 | for_each_engine(engine, dev_priv) { | 670 | for_each_engine(engine, dev_priv, id) { |
| 662 | int count; | 671 | int count; |
| 663 | 672 | ||
| 664 | count = 0; | 673 | count = 0; |
| @@ -668,19 +677,8 @@ static int i915_gem_request_info(struct seq_file *m, void *data) | |||
| 668 | continue; | 677 | continue; |
| 669 | 678 | ||
| 670 | seq_printf(m, "%s requests: %d\n", engine->name, count); | 679 | seq_printf(m, "%s requests: %d\n", engine->name, count); |
| 671 | list_for_each_entry(req, &engine->request_list, link) { | 680 | list_for_each_entry(req, &engine->request_list, link) |
| 672 | struct pid *pid = req->ctx->pid; | 681 | print_request(m, req, " "); |
| 673 | struct task_struct *task; | ||
| 674 | |||
| 675 | rcu_read_lock(); | ||
| 676 | task = pid ? pid_task(pid, PIDTYPE_PID) : NULL; | ||
| 677 | seq_printf(m, " %x @ %d: %s [%d]\n", | ||
| 678 | req->fence.seqno, | ||
| 679 | (int) (jiffies - req->emitted_jiffies), | ||
| 680 | task ? task->comm : "<unknown>", | ||
| 681 | task ? task->pid : -1); | ||
| 682 | rcu_read_unlock(); | ||
| 683 | } | ||
| 684 | 682 | ||
| 685 | any++; | 683 | any++; |
| 686 | } | 684 | } |
| @@ -715,8 +713,9 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data) | |||
| 715 | { | 713 | { |
| 716 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | 714 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
| 717 | struct intel_engine_cs *engine; | 715 | struct intel_engine_cs *engine; |
| 716 | enum intel_engine_id id; | ||
| 718 | 717 | ||
| 719 | for_each_engine(engine, dev_priv) | 718 | for_each_engine(engine, dev_priv, id) |
| 720 | i915_ring_seqno_info(m, engine); | 719 | i915_ring_seqno_info(m, engine); |
| 721 | 720 | ||
| 722 | return 0; | 721 | return 0; |
| @@ -727,6 +726,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) | |||
| 727 | { | 726 | { |
| 728 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | 727 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
| 729 | struct intel_engine_cs *engine; | 728 | struct intel_engine_cs *engine; |
| 729 | enum intel_engine_id id; | ||
| 730 | int i, pipe; | 730 | int i, pipe; |
| 731 | 731 | ||
| 732 | intel_runtime_pm_get(dev_priv); | 732 | intel_runtime_pm_get(dev_priv); |
| @@ -895,7 +895,7 @@ static int i915_interrupt_info(struct seq_file *m, void *data) | |||
| 895 | seq_printf(m, "Graphics Interrupt mask: %08x\n", | 895 | seq_printf(m, "Graphics Interrupt mask: %08x\n", |
| 896 | I915_READ(GTIMR)); | 896 | I915_READ(GTIMR)); |
| 897 | } | 897 | } |
| 898 | for_each_engine(engine, dev_priv) { | 898 | for_each_engine(engine, dev_priv, id) { |
| 899 | if (INTEL_GEN(dev_priv) >= 6) { | 899 | if (INTEL_GEN(dev_priv) >= 6) { |
| 900 | seq_printf(m, | 900 | seq_printf(m, |
| 901 | "Graphics Interrupt mask (%s): %08x\n", | 901 | "Graphics Interrupt mask (%s): %08x\n", |
| @@ -943,7 +943,7 @@ static int i915_hws_info(struct seq_file *m, void *data) | |||
| 943 | const u32 *hws; | 943 | const u32 *hws; |
| 944 | int i; | 944 | int i; |
| 945 | 945 | ||
| 946 | engine = &dev_priv->engine[(uintptr_t)node->info_ent->data]; | 946 | engine = dev_priv->engine[(uintptr_t)node->info_ent->data]; |
| 947 | hws = engine->status_page.page_addr; | 947 | hws = engine->status_page.page_addr; |
| 948 | if (hws == NULL) | 948 | if (hws == NULL) |
| 949 | return 0; | 949 | return 0; |
| @@ -956,6 +956,8 @@ static int i915_hws_info(struct seq_file *m, void *data) | |||
| 956 | return 0; | 956 | return 0; |
| 957 | } | 957 | } |
| 958 | 958 | ||
| 959 | #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) | ||
| 960 | |||
| 959 | static ssize_t | 961 | static ssize_t |
| 960 | i915_error_state_write(struct file *filp, | 962 | i915_error_state_write(struct file *filp, |
| 961 | const char __user *ubuf, | 963 | const char __user *ubuf, |
| @@ -1038,6 +1040,8 @@ static const struct file_operations i915_error_state_fops = { | |||
| 1038 | .release = i915_error_state_release, | 1040 | .release = i915_error_state_release, |
| 1039 | }; | 1041 | }; |
| 1040 | 1042 | ||
| 1043 | #endif | ||
| 1044 | |||
| 1041 | static int | 1045 | static int |
| 1042 | i915_next_seqno_get(void *data, u64 *val) | 1046 | i915_next_seqno_get(void *data, u64 *val) |
| 1043 | { | 1047 | { |
| @@ -1277,15 +1281,42 @@ out: | |||
| 1277 | return ret; | 1281 | return ret; |
| 1278 | } | 1282 | } |
| 1279 | 1283 | ||
| 1284 | static void i915_instdone_info(struct drm_i915_private *dev_priv, | ||
| 1285 | struct seq_file *m, | ||
| 1286 | struct intel_instdone *instdone) | ||
| 1287 | { | ||
| 1288 | int slice; | ||
| 1289 | int subslice; | ||
| 1290 | |||
| 1291 | seq_printf(m, "\t\tINSTDONE: 0x%08x\n", | ||
| 1292 | instdone->instdone); | ||
| 1293 | |||
| 1294 | if (INTEL_GEN(dev_priv) <= 3) | ||
| 1295 | return; | ||
| 1296 | |||
| 1297 | seq_printf(m, "\t\tSC_INSTDONE: 0x%08x\n", | ||
| 1298 | instdone->slice_common); | ||
| 1299 | |||
| 1300 | if (INTEL_GEN(dev_priv) <= 6) | ||
| 1301 | return; | ||
| 1302 | |||
| 1303 | for_each_instdone_slice_subslice(dev_priv, slice, subslice) | ||
| 1304 | seq_printf(m, "\t\tSAMPLER_INSTDONE[%d][%d]: 0x%08x\n", | ||
| 1305 | slice, subslice, instdone->sampler[slice][subslice]); | ||
| 1306 | |||
| 1307 | for_each_instdone_slice_subslice(dev_priv, slice, subslice) | ||
| 1308 | seq_printf(m, "\t\tROW_INSTDONE[%d][%d]: 0x%08x\n", | ||
| 1309 | slice, subslice, instdone->row[slice][subslice]); | ||
| 1310 | } | ||
| 1311 | |||
| 1280 | static int i915_hangcheck_info(struct seq_file *m, void *unused) | 1312 | static int i915_hangcheck_info(struct seq_file *m, void *unused) |
| 1281 | { | 1313 | { |
| 1282 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | 1314 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
| 1283 | struct intel_engine_cs *engine; | 1315 | struct intel_engine_cs *engine; |
| 1284 | u64 acthd[I915_NUM_ENGINES]; | 1316 | u64 acthd[I915_NUM_ENGINES]; |
| 1285 | u32 seqno[I915_NUM_ENGINES]; | 1317 | u32 seqno[I915_NUM_ENGINES]; |
| 1286 | u32 instdone[I915_NUM_INSTDONE_REG]; | 1318 | struct intel_instdone instdone; |
| 1287 | enum intel_engine_id id; | 1319 | enum intel_engine_id id; |
| 1288 | int j; | ||
| 1289 | 1320 | ||
| 1290 | if (test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) | 1321 | if (test_bit(I915_WEDGED, &dev_priv->gpu_error.flags)) |
| 1291 | seq_printf(m, "Wedged\n"); | 1322 | seq_printf(m, "Wedged\n"); |
| @@ -1303,12 +1334,12 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) | |||
| 1303 | 1334 | ||
| 1304 | intel_runtime_pm_get(dev_priv); | 1335 | intel_runtime_pm_get(dev_priv); |
| 1305 | 1336 | ||
| 1306 | for_each_engine_id(engine, dev_priv, id) { | 1337 | for_each_engine(engine, dev_priv, id) { |
| 1307 | acthd[id] = intel_engine_get_active_head(engine); | 1338 | acthd[id] = intel_engine_get_active_head(engine); |
| 1308 | seqno[id] = intel_engine_get_seqno(engine); | 1339 | seqno[id] = intel_engine_get_seqno(engine); |
| 1309 | } | 1340 | } |
| 1310 | 1341 | ||
| 1311 | i915_get_extra_instdone(dev_priv, instdone); | 1342 | intel_engine_get_instdone(dev_priv->engine[RCS], &instdone); |
| 1312 | 1343 | ||
| 1313 | intel_runtime_pm_put(dev_priv); | 1344 | intel_runtime_pm_put(dev_priv); |
| 1314 | 1345 | ||
| @@ -1319,7 +1350,10 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) | |||
| 1319 | } else | 1350 | } else |
| 1320 | seq_printf(m, "Hangcheck inactive\n"); | 1351 | seq_printf(m, "Hangcheck inactive\n"); |
| 1321 | 1352 | ||
| 1322 | for_each_engine_id(engine, dev_priv, id) { | 1353 | for_each_engine(engine, dev_priv, id) { |
| 1354 | struct intel_breadcrumbs *b = &engine->breadcrumbs; | ||
| 1355 | struct rb_node *rb; | ||
| 1356 | |||
| 1323 | seq_printf(m, "%s:\n", engine->name); | 1357 | seq_printf(m, "%s:\n", engine->name); |
| 1324 | seq_printf(m, "\tseqno = %x [current %x, last %x]\n", | 1358 | seq_printf(m, "\tseqno = %x [current %x, last %x]\n", |
| 1325 | engine->hangcheck.seqno, | 1359 | engine->hangcheck.seqno, |
| @@ -1329,6 +1363,15 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) | |||
| 1329 | yesno(intel_engine_has_waiter(engine)), | 1363 | yesno(intel_engine_has_waiter(engine)), |
| 1330 | yesno(test_bit(engine->id, | 1364 | yesno(test_bit(engine->id, |
| 1331 | &dev_priv->gpu_error.missed_irq_rings))); | 1365 | &dev_priv->gpu_error.missed_irq_rings))); |
| 1366 | spin_lock(&b->lock); | ||
| 1367 | for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { | ||
| 1368 | struct intel_wait *w = container_of(rb, typeof(*w), node); | ||
| 1369 | |||
| 1370 | seq_printf(m, "\t%s [%d] waiting for %x\n", | ||
| 1371 | w->tsk->comm, w->tsk->pid, w->seqno); | ||
| 1372 | } | ||
| 1373 | spin_unlock(&b->lock); | ||
| 1374 | |||
| 1332 | seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n", | 1375 | seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n", |
| 1333 | (long long)engine->hangcheck.acthd, | 1376 | (long long)engine->hangcheck.acthd, |
| 1334 | (long long)acthd[id]); | 1377 | (long long)acthd[id]); |
| @@ -1336,18 +1379,14 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) | |||
| 1336 | seq_printf(m, "\taction = %d\n", engine->hangcheck.action); | 1379 | seq_printf(m, "\taction = %d\n", engine->hangcheck.action); |
| 1337 | 1380 | ||
| 1338 | if (engine->id == RCS) { | 1381 | if (engine->id == RCS) { |
| 1339 | seq_puts(m, "\tinstdone read ="); | 1382 | seq_puts(m, "\tinstdone read =\n"); |
| 1340 | |||
| 1341 | for (j = 0; j < I915_NUM_INSTDONE_REG; j++) | ||
| 1342 | seq_printf(m, " 0x%08x", instdone[j]); | ||
| 1343 | 1383 | ||
| 1344 | seq_puts(m, "\n\tinstdone accu ="); | 1384 | i915_instdone_info(dev_priv, m, &instdone); |
| 1345 | 1385 | ||
| 1346 | for (j = 0; j < I915_NUM_INSTDONE_REG; j++) | 1386 | seq_puts(m, "\tinstdone accu =\n"); |
| 1347 | seq_printf(m, " 0x%08x", | ||
| 1348 | engine->hangcheck.instdone[j]); | ||
| 1349 | 1387 | ||
| 1350 | seq_puts(m, "\n"); | 1388 | i915_instdone_info(dev_priv, m, |
| 1389 | &engine->hangcheck.instdone); | ||
| 1351 | } | 1390 | } |
| 1352 | } | 1391 | } |
| 1353 | 1392 | ||
| @@ -1635,7 +1674,8 @@ static int i915_fbc_status(struct seq_file *m, void *unused) | |||
| 1635 | seq_printf(m, "FBC disabled: %s\n", | 1674 | seq_printf(m, "FBC disabled: %s\n", |
| 1636 | dev_priv->fbc.no_fbc_reason); | 1675 | dev_priv->fbc.no_fbc_reason); |
| 1637 | 1676 | ||
| 1638 | if (INTEL_GEN(dev_priv) >= 7) | 1677 | if (intel_fbc_is_active(dev_priv) && |
| 1678 | INTEL_GEN(dev_priv) >= 7) | ||
| 1639 | seq_printf(m, "Compressing: %s\n", | 1679 | seq_printf(m, "Compressing: %s\n", |
| 1640 | yesno(I915_READ(FBC_STATUS2) & | 1680 | yesno(I915_READ(FBC_STATUS2) & |
| 1641 | FBC_COMPRESSION_MASK)); | 1681 | FBC_COMPRESSION_MASK)); |
| @@ -1909,6 +1949,7 @@ static int i915_context_status(struct seq_file *m, void *unused) | |||
| 1909 | struct drm_device *dev = &dev_priv->drm; | 1949 | struct drm_device *dev = &dev_priv->drm; |
| 1910 | struct intel_engine_cs *engine; | 1950 | struct intel_engine_cs *engine; |
| 1911 | struct i915_gem_context *ctx; | 1951 | struct i915_gem_context *ctx; |
| 1952 | enum intel_engine_id id; | ||
| 1912 | int ret; | 1953 | int ret; |
| 1913 | 1954 | ||
| 1914 | ret = mutex_lock_interruptible(&dev->struct_mutex); | 1955 | ret = mutex_lock_interruptible(&dev->struct_mutex); |
| @@ -1935,7 +1976,7 @@ static int i915_context_status(struct seq_file *m, void *unused) | |||
| 1935 | seq_putc(m, ctx->remap_slice ? 'R' : 'r'); | 1976 | seq_putc(m, ctx->remap_slice ? 'R' : 'r'); |
| 1936 | seq_putc(m, '\n'); | 1977 | seq_putc(m, '\n'); |
| 1937 | 1978 | ||
| 1938 | for_each_engine(engine, dev_priv) { | 1979 | for_each_engine(engine, dev_priv, id) { |
| 1939 | struct intel_context *ce = &ctx->engine[engine->id]; | 1980 | struct intel_context *ce = &ctx->engine[engine->id]; |
| 1940 | 1981 | ||
| 1941 | seq_printf(m, "%s: ", engine->name); | 1982 | seq_printf(m, "%s: ", engine->name); |
| @@ -2002,6 +2043,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) | |||
| 2002 | struct drm_device *dev = &dev_priv->drm; | 2043 | struct drm_device *dev = &dev_priv->drm; |
| 2003 | struct intel_engine_cs *engine; | 2044 | struct intel_engine_cs *engine; |
| 2004 | struct i915_gem_context *ctx; | 2045 | struct i915_gem_context *ctx; |
| 2046 | enum intel_engine_id id; | ||
| 2005 | int ret; | 2047 | int ret; |
| 2006 | 2048 | ||
| 2007 | if (!i915.enable_execlists) { | 2049 | if (!i915.enable_execlists) { |
| @@ -2014,7 +2056,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) | |||
| 2014 | return ret; | 2056 | return ret; |
| 2015 | 2057 | ||
| 2016 | list_for_each_entry(ctx, &dev_priv->context_list, link) | 2058 | list_for_each_entry(ctx, &dev_priv->context_list, link) |
| 2017 | for_each_engine(engine, dev_priv) | 2059 | for_each_engine(engine, dev_priv, id) |
| 2018 | i915_dump_lrc_obj(m, ctx, engine); | 2060 | i915_dump_lrc_obj(m, ctx, engine); |
| 2019 | 2061 | ||
| 2020 | mutex_unlock(&dev->struct_mutex); | 2062 | mutex_unlock(&dev->struct_mutex); |
| @@ -2022,84 +2064,6 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) | |||
| 2022 | return 0; | 2064 | return 0; |
| 2023 | } | 2065 | } |
| 2024 | 2066 | ||
| 2025 | static int i915_execlists(struct seq_file *m, void *data) | ||
| 2026 | { | ||
| 2027 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | ||
| 2028 | struct drm_device *dev = &dev_priv->drm; | ||
| 2029 | struct intel_engine_cs *engine; | ||
| 2030 | u32 status_pointer; | ||
| 2031 | u8 read_pointer; | ||
| 2032 | u8 write_pointer; | ||
| 2033 | u32 status; | ||
| 2034 | u32 ctx_id; | ||
| 2035 | struct list_head *cursor; | ||
| 2036 | int i, ret; | ||
| 2037 | |||
| 2038 | if (!i915.enable_execlists) { | ||
| 2039 | seq_puts(m, "Logical Ring Contexts are disabled\n"); | ||
| 2040 | return 0; | ||
| 2041 | } | ||
| 2042 | |||
| 2043 | ret = mutex_lock_interruptible(&dev->struct_mutex); | ||
| 2044 | if (ret) | ||
| 2045 | return ret; | ||
| 2046 | |||
| 2047 | intel_runtime_pm_get(dev_priv); | ||
| 2048 | |||
| 2049 | for_each_engine(engine, dev_priv) { | ||
| 2050 | struct drm_i915_gem_request *head_req = NULL; | ||
| 2051 | int count = 0; | ||
| 2052 | |||
| 2053 | seq_printf(m, "%s\n", engine->name); | ||
| 2054 | |||
| 2055 | status = I915_READ(RING_EXECLIST_STATUS_LO(engine)); | ||
| 2056 | ctx_id = I915_READ(RING_EXECLIST_STATUS_HI(engine)); | ||
| 2057 | seq_printf(m, "\tExeclist status: 0x%08X, context: %u\n", | ||
| 2058 | status, ctx_id); | ||
| 2059 | |||
| 2060 | status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); | ||
| 2061 | seq_printf(m, "\tStatus pointer: 0x%08X\n", status_pointer); | ||
| 2062 | |||
| 2063 | read_pointer = GEN8_CSB_READ_PTR(status_pointer); | ||
| 2064 | write_pointer = GEN8_CSB_WRITE_PTR(status_pointer); | ||
| 2065 | if (read_pointer > write_pointer) | ||
| 2066 | write_pointer += GEN8_CSB_ENTRIES; | ||
| 2067 | seq_printf(m, "\tRead pointer: 0x%08X, write pointer 0x%08X\n", | ||
| 2068 | read_pointer, write_pointer); | ||
| 2069 | |||
| 2070 | for (i = 0; i < GEN8_CSB_ENTRIES; i++) { | ||
| 2071 | status = I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, i)); | ||
| 2072 | ctx_id = I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, i)); | ||
| 2073 | |||
| 2074 | seq_printf(m, "\tStatus buffer %d: 0x%08X, context: %u\n", | ||
| 2075 | i, status, ctx_id); | ||
| 2076 | } | ||
| 2077 | |||
| 2078 | spin_lock_bh(&engine->execlist_lock); | ||
| 2079 | list_for_each(cursor, &engine->execlist_queue) | ||
| 2080 | count++; | ||
| 2081 | head_req = list_first_entry_or_null(&engine->execlist_queue, | ||
| 2082 | struct drm_i915_gem_request, | ||
| 2083 | execlist_link); | ||
| 2084 | spin_unlock_bh(&engine->execlist_lock); | ||
| 2085 | |||
| 2086 | seq_printf(m, "\t%d requests in queue\n", count); | ||
| 2087 | if (head_req) { | ||
| 2088 | seq_printf(m, "\tHead request context: %u\n", | ||
| 2089 | head_req->ctx->hw_id); | ||
| 2090 | seq_printf(m, "\tHead request tail: %u\n", | ||
| 2091 | head_req->tail); | ||
| 2092 | } | ||
| 2093 | |||
| 2094 | seq_putc(m, '\n'); | ||
| 2095 | } | ||
| 2096 | |||
| 2097 | intel_runtime_pm_put(dev_priv); | ||
| 2098 | mutex_unlock(&dev->struct_mutex); | ||
| 2099 | |||
| 2100 | return 0; | ||
| 2101 | } | ||
| 2102 | |||
| 2103 | static const char *swizzle_string(unsigned swizzle) | 2067 | static const char *swizzle_string(unsigned swizzle) |
| 2104 | { | 2068 | { |
| 2105 | switch (swizzle) { | 2069 | switch (swizzle) { |
| @@ -2201,14 +2165,15 @@ static int per_file_ctx(int id, void *ptr, void *data) | |||
| 2201 | static void gen8_ppgtt_info(struct seq_file *m, | 2165 | static void gen8_ppgtt_info(struct seq_file *m, |
| 2202 | struct drm_i915_private *dev_priv) | 2166 | struct drm_i915_private *dev_priv) |
| 2203 | { | 2167 | { |
| 2204 | struct intel_engine_cs *engine; | ||
| 2205 | struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; | 2168 | struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt; |
| 2169 | struct intel_engine_cs *engine; | ||
| 2170 | enum intel_engine_id id; | ||
| 2206 | int i; | 2171 | int i; |
| 2207 | 2172 | ||
| 2208 | if (!ppgtt) | 2173 | if (!ppgtt) |
| 2209 | return; | 2174 | return; |
| 2210 | 2175 | ||
| 2211 | for_each_engine(engine, dev_priv) { | 2176 | for_each_engine(engine, dev_priv, id) { |
| 2212 | seq_printf(m, "%s\n", engine->name); | 2177 | seq_printf(m, "%s\n", engine->name); |
| 2213 | for (i = 0; i < 4; i++) { | 2178 | for (i = 0; i < 4; i++) { |
| 2214 | u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i)); | 2179 | u64 pdp = I915_READ(GEN8_RING_PDP_UDW(engine, i)); |
| @@ -2223,11 +2188,12 @@ static void gen6_ppgtt_info(struct seq_file *m, | |||
| 2223 | struct drm_i915_private *dev_priv) | 2188 | struct drm_i915_private *dev_priv) |
| 2224 | { | 2189 | { |
| 2225 | struct intel_engine_cs *engine; | 2190 | struct intel_engine_cs *engine; |
| 2191 | enum intel_engine_id id; | ||
| 2226 | 2192 | ||
| 2227 | if (IS_GEN6(dev_priv)) | 2193 | if (IS_GEN6(dev_priv)) |
| 2228 | seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE)); | 2194 | seq_printf(m, "GFX_MODE: 0x%08x\n", I915_READ(GFX_MODE)); |
| 2229 | 2195 | ||
| 2230 | for_each_engine(engine, dev_priv) { | 2196 | for_each_engine(engine, dev_priv, id) { |
| 2231 | seq_printf(m, "%s\n", engine->name); | 2197 | seq_printf(m, "%s\n", engine->name); |
| 2232 | if (IS_GEN7(dev_priv)) | 2198 | if (IS_GEN7(dev_priv)) |
| 2233 | seq_printf(m, "GFX_MODE: 0x%08x\n", | 2199 | seq_printf(m, "GFX_MODE: 0x%08x\n", |
| @@ -2296,9 +2262,10 @@ out_unlock: | |||
| 2296 | static int count_irq_waiters(struct drm_i915_private *i915) | 2262 | static int count_irq_waiters(struct drm_i915_private *i915) |
| 2297 | { | 2263 | { |
| 2298 | struct intel_engine_cs *engine; | 2264 | struct intel_engine_cs *engine; |
| 2265 | enum intel_engine_id id; | ||
| 2299 | int count = 0; | 2266 | int count = 0; |
| 2300 | 2267 | ||
| 2301 | for_each_engine(engine, i915) | 2268 | for_each_engine(engine, i915, id) |
| 2302 | count += intel_engine_has_waiter(engine); | 2269 | count += intel_engine_has_waiter(engine); |
| 2303 | 2270 | ||
| 2304 | return count; | 2271 | return count; |
| @@ -2461,7 +2428,7 @@ static void i915_guc_client_info(struct seq_file *m, | |||
| 2461 | seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail); | 2428 | seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail); |
| 2462 | seq_printf(m, "\tLast submission result: %d\n", client->retcode); | 2429 | seq_printf(m, "\tLast submission result: %d\n", client->retcode); |
| 2463 | 2430 | ||
| 2464 | for_each_engine_id(engine, dev_priv, id) { | 2431 | for_each_engine(engine, dev_priv, id) { |
| 2465 | u64 submissions = client->submissions[id]; | 2432 | u64 submissions = client->submissions[id]; |
| 2466 | tot += submissions; | 2433 | tot += submissions; |
| 2467 | seq_printf(m, "\tSubmissions: %llu %s\n", | 2434 | seq_printf(m, "\tSubmissions: %llu %s\n", |
| @@ -2504,7 +2471,7 @@ static int i915_guc_info(struct seq_file *m, void *data) | |||
| 2504 | seq_printf(m, "GuC last action error code: %d\n", guc.action_err); | 2471 | seq_printf(m, "GuC last action error code: %d\n", guc.action_err); |
| 2505 | 2472 | ||
| 2506 | seq_printf(m, "\nGuC submissions:\n"); | 2473 | seq_printf(m, "\nGuC submissions:\n"); |
| 2507 | for_each_engine_id(engine, dev_priv, id) { | 2474 | for_each_engine(engine, dev_priv, id) { |
| 2508 | u64 submissions = guc.submissions[id]; | 2475 | u64 submissions = guc.submissions[id]; |
| 2509 | total += submissions; | 2476 | total += submissions; |
| 2510 | seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n", | 2477 | seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x\n", |
| @@ -3121,6 +3088,134 @@ static int i915_display_info(struct seq_file *m, void *unused) | |||
| 3121 | return 0; | 3088 | return 0; |
| 3122 | } | 3089 | } |
| 3123 | 3090 | ||
| 3091 | static int i915_engine_info(struct seq_file *m, void *unused) | ||
| 3092 | { | ||
| 3093 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | ||
| 3094 | struct intel_engine_cs *engine; | ||
| 3095 | enum intel_engine_id id; | ||
| 3096 | |||
| 3097 | for_each_engine(engine, dev_priv, id) { | ||
| 3098 | struct intel_breadcrumbs *b = &engine->breadcrumbs; | ||
| 3099 | struct drm_i915_gem_request *rq; | ||
| 3100 | struct rb_node *rb; | ||
| 3101 | u64 addr; | ||
| 3102 | |||
| 3103 | seq_printf(m, "%s\n", engine->name); | ||
| 3104 | seq_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [score %d]\n", | ||
| 3105 | intel_engine_get_seqno(engine), | ||
| 3106 | engine->last_submitted_seqno, | ||
| 3107 | engine->hangcheck.seqno, | ||
| 3108 | engine->hangcheck.score); | ||
| 3109 | |||
| 3110 | rcu_read_lock(); | ||
| 3111 | |||
| 3112 | seq_printf(m, "\tRequests:\n"); | ||
| 3113 | |||
| 3114 | rq = list_first_entry(&engine->request_list, | ||
| 3115 | struct drm_i915_gem_request, link); | ||
| 3116 | if (&rq->link != &engine->request_list) | ||
| 3117 | print_request(m, rq, "\t\tfirst "); | ||
| 3118 | |||
| 3119 | rq = list_last_entry(&engine->request_list, | ||
| 3120 | struct drm_i915_gem_request, link); | ||
| 3121 | if (&rq->link != &engine->request_list) | ||
| 3122 | print_request(m, rq, "\t\tlast "); | ||
| 3123 | |||
| 3124 | rq = i915_gem_find_active_request(engine); | ||
| 3125 | if (rq) { | ||
| 3126 | print_request(m, rq, "\t\tactive "); | ||
| 3127 | seq_printf(m, | ||
| 3128 | "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n", | ||
| 3129 | rq->head, rq->postfix, rq->tail, | ||
| 3130 | rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u, | ||
| 3131 | rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u); | ||
| 3132 | } | ||
| 3133 | |||
| 3134 | seq_printf(m, "\tRING_START: 0x%08x [0x%08x]\n", | ||
| 3135 | I915_READ(RING_START(engine->mmio_base)), | ||
| 3136 | rq ? i915_ggtt_offset(rq->ring->vma) : 0); | ||
| 3137 | seq_printf(m, "\tRING_HEAD: 0x%08x [0x%08x]\n", | ||
| 3138 | I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR, | ||
| 3139 | rq ? rq->ring->head : 0); | ||
| 3140 | seq_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n", | ||
| 3141 | I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR, | ||
| 3142 | rq ? rq->ring->tail : 0); | ||
| 3143 | seq_printf(m, "\tRING_CTL: 0x%08x [%s]\n", | ||
| 3144 | I915_READ(RING_CTL(engine->mmio_base)), | ||
| 3145 | I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : ""); | ||
| 3146 | |||
| 3147 | rcu_read_unlock(); | ||
| 3148 | |||
| 3149 | addr = intel_engine_get_active_head(engine); | ||
| 3150 | seq_printf(m, "\tACTHD: 0x%08x_%08x\n", | ||
| 3151 | upper_32_bits(addr), lower_32_bits(addr)); | ||
| 3152 | addr = intel_engine_get_last_batch_head(engine); | ||
| 3153 | seq_printf(m, "\tBBADDR: 0x%08x_%08x\n", | ||
| 3154 | upper_32_bits(addr), lower_32_bits(addr)); | ||
| 3155 | |||
| 3156 | if (i915.enable_execlists) { | ||
| 3157 | u32 ptr, read, write; | ||
| 3158 | |||
| 3159 | seq_printf(m, "\tExeclist status: 0x%08x %08x\n", | ||
| 3160 | I915_READ(RING_EXECLIST_STATUS_LO(engine)), | ||
| 3161 | I915_READ(RING_EXECLIST_STATUS_HI(engine))); | ||
| 3162 | |||
| 3163 | ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); | ||
| 3164 | read = GEN8_CSB_READ_PTR(ptr); | ||
| 3165 | write = GEN8_CSB_WRITE_PTR(ptr); | ||
| 3166 | seq_printf(m, "\tExeclist CSB read %d, write %d\n", | ||
| 3167 | read, write); | ||
| 3168 | if (read >= GEN8_CSB_ENTRIES) | ||
| 3169 | read = 0; | ||
| 3170 | if (write >= GEN8_CSB_ENTRIES) | ||
| 3171 | write = 0; | ||
| 3172 | if (read > write) | ||
| 3173 | write += GEN8_CSB_ENTRIES; | ||
| 3174 | while (read < write) { | ||
| 3175 | unsigned int idx = ++read % GEN8_CSB_ENTRIES; | ||
| 3176 | |||
| 3177 | seq_printf(m, "\tExeclist CSB[%d]: 0x%08x, context: %d\n", | ||
| 3178 | idx, | ||
| 3179 | I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)), | ||
| 3180 | I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx))); | ||
| 3181 | } | ||
| 3182 | |||
| 3183 | rcu_read_lock(); | ||
| 3184 | rq = READ_ONCE(engine->execlist_port[0].request); | ||
| 3185 | if (rq) | ||
| 3186 | print_request(m, rq, "\t\tELSP[0] "); | ||
| 3187 | else | ||
| 3188 | seq_printf(m, "\t\tELSP[0] idle\n"); | ||
| 3189 | rq = READ_ONCE(engine->execlist_port[1].request); | ||
| 3190 | if (rq) | ||
| 3191 | print_request(m, rq, "\t\tELSP[1] "); | ||
| 3192 | else | ||
| 3193 | seq_printf(m, "\t\tELSP[1] idle\n"); | ||
| 3194 | rcu_read_unlock(); | ||
| 3195 | } else if (INTEL_GEN(dev_priv) > 6) { | ||
| 3196 | seq_printf(m, "\tPP_DIR_BASE: 0x%08x\n", | ||
| 3197 | I915_READ(RING_PP_DIR_BASE(engine))); | ||
| 3198 | seq_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n", | ||
| 3199 | I915_READ(RING_PP_DIR_BASE_READ(engine))); | ||
| 3200 | seq_printf(m, "\tPP_DIR_DCLV: 0x%08x\n", | ||
| 3201 | I915_READ(RING_PP_DIR_DCLV(engine))); | ||
| 3202 | } | ||
| 3203 | |||
| 3204 | spin_lock(&b->lock); | ||
| 3205 | for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { | ||
| 3206 | struct intel_wait *w = container_of(rb, typeof(*w), node); | ||
| 3207 | |||
| 3208 | seq_printf(m, "\t%s [%d] waiting for %x\n", | ||
| 3209 | w->tsk->comm, w->tsk->pid, w->seqno); | ||
| 3210 | } | ||
| 3211 | spin_unlock(&b->lock); | ||
| 3212 | |||
| 3213 | seq_puts(m, "\n"); | ||
| 3214 | } | ||
| 3215 | |||
| 3216 | return 0; | ||
| 3217 | } | ||
| 3218 | |||
| 3124 | static int i915_semaphore_status(struct seq_file *m, void *unused) | 3219 | static int i915_semaphore_status(struct seq_file *m, void *unused) |
| 3125 | { | 3220 | { |
| 3126 | struct drm_i915_private *dev_priv = node_to_i915(m->private); | 3221 | struct drm_i915_private *dev_priv = node_to_i915(m->private); |
| @@ -3147,7 +3242,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) | |||
| 3147 | page = i915_gem_object_get_page(dev_priv->semaphore->obj, 0); | 3242 | page = i915_gem_object_get_page(dev_priv->semaphore->obj, 0); |
| 3148 | 3243 | ||
| 3149 | seqno = (uint64_t *)kmap_atomic(page); | 3244 | seqno = (uint64_t *)kmap_atomic(page); |
| 3150 | for_each_engine_id(engine, dev_priv, id) { | 3245 | for_each_engine(engine, dev_priv, id) { |
| 3151 | uint64_t offset; | 3246 | uint64_t offset; |
| 3152 | 3247 | ||
| 3153 | seq_printf(m, "%s\n", engine->name); | 3248 | seq_printf(m, "%s\n", engine->name); |
| @@ -3172,7 +3267,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) | |||
| 3172 | kunmap_atomic(seqno); | 3267 | kunmap_atomic(seqno); |
| 3173 | } else { | 3268 | } else { |
| 3174 | seq_puts(m, " Last signal:"); | 3269 | seq_puts(m, " Last signal:"); |
| 3175 | for_each_engine(engine, dev_priv) | 3270 | for_each_engine(engine, dev_priv, id) |
| 3176 | for (j = 0; j < num_rings; j++) | 3271 | for (j = 0; j < num_rings; j++) |
| 3177 | seq_printf(m, "0x%08x\n", | 3272 | seq_printf(m, "0x%08x\n", |
| 3178 | I915_READ(engine->semaphore.mbox.signal[j])); | 3273 | I915_READ(engine->semaphore.mbox.signal[j])); |
| @@ -3180,7 +3275,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) | |||
| 3180 | } | 3275 | } |
| 3181 | 3276 | ||
| 3182 | seq_puts(m, "\nSync seqno:\n"); | 3277 | seq_puts(m, "\nSync seqno:\n"); |
| 3183 | for_each_engine(engine, dev_priv) { | 3278 | for_each_engine(engine, dev_priv, id) { |
| 3184 | for (j = 0; j < num_rings; j++) | 3279 | for (j = 0; j < num_rings; j++) |
| 3185 | seq_printf(m, " 0x%08x ", | 3280 | seq_printf(m, " 0x%08x ", |
| 3186 | engine->semaphore.sync_seqno[j]); | 3281 | engine->semaphore.sync_seqno[j]); |
| @@ -3236,7 +3331,7 @@ static int i915_wa_registers(struct seq_file *m, void *unused) | |||
| 3236 | intel_runtime_pm_get(dev_priv); | 3331 | intel_runtime_pm_get(dev_priv); |
| 3237 | 3332 | ||
| 3238 | seq_printf(m, "Workarounds applied: %d\n", workarounds->count); | 3333 | seq_printf(m, "Workarounds applied: %d\n", workarounds->count); |
| 3239 | for_each_engine_id(engine, dev_priv, id) | 3334 | for_each_engine(engine, dev_priv, id) |
| 3240 | seq_printf(m, "HW whitelist count for %s: %d\n", | 3335 | seq_printf(m, "HW whitelist count for %s: %d\n", |
| 3241 | engine->name, workarounds->hw_whitelist_count[id]); | 3336 | engine->name, workarounds->hw_whitelist_count[id]); |
| 3242 | for (i = 0; i < workarounds->count; ++i) { | 3337 | for (i = 0; i < workarounds->count; ++i) { |
| @@ -4462,7 +4557,7 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8]) | |||
| 4462 | else if (IS_VALLEYVIEW(dev_priv)) | 4557 | else if (IS_VALLEYVIEW(dev_priv)) |
| 4463 | num_levels = 1; | 4558 | num_levels = 1; |
| 4464 | else | 4559 | else |
| 4465 | num_levels = ilk_wm_max_level(dev) + 1; | 4560 | num_levels = ilk_wm_max_level(dev_priv) + 1; |
| 4466 | 4561 | ||
| 4467 | drm_modeset_lock_all(dev); | 4562 | drm_modeset_lock_all(dev); |
| 4468 | 4563 | ||
| @@ -4578,7 +4673,7 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf, | |||
| 4578 | else if (IS_VALLEYVIEW(dev_priv)) | 4673 | else if (IS_VALLEYVIEW(dev_priv)) |
| 4579 | num_levels = 1; | 4674 | num_levels = 1; |
| 4580 | else | 4675 | else |
| 4581 | num_levels = ilk_wm_max_level(dev) + 1; | 4676 | num_levels = ilk_wm_max_level(dev_priv) + 1; |
| 4582 | 4677 | ||
| 4583 | if (len >= sizeof(tmp)) | 4678 | if (len >= sizeof(tmp)) |
| 4584 | return -EINVAL; | 4679 | return -EINVAL; |
| @@ -5274,7 +5369,6 @@ static const struct drm_info_list i915_debugfs_list[] = { | |||
| 5274 | {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, | 5369 | {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, |
| 5275 | {"i915_context_status", i915_context_status, 0}, | 5370 | {"i915_context_status", i915_context_status, 0}, |
| 5276 | {"i915_dump_lrc", i915_dump_lrc, 0}, | 5371 | {"i915_dump_lrc", i915_dump_lrc, 0}, |
| 5277 | {"i915_execlists", i915_execlists, 0}, | ||
| 5278 | {"i915_forcewake_domains", i915_forcewake_domains, 0}, | 5372 | {"i915_forcewake_domains", i915_forcewake_domains, 0}, |
| 5279 | {"i915_swizzle_info", i915_swizzle_info, 0}, | 5373 | {"i915_swizzle_info", i915_swizzle_info, 0}, |
| 5280 | {"i915_ppgtt_info", i915_ppgtt_info, 0}, | 5374 | {"i915_ppgtt_info", i915_ppgtt_info, 0}, |
| @@ -5286,6 +5380,7 @@ static const struct drm_info_list i915_debugfs_list[] = { | |||
| 5286 | {"i915_power_domain_info", i915_power_domain_info, 0}, | 5380 | {"i915_power_domain_info", i915_power_domain_info, 0}, |
| 5287 | {"i915_dmc_info", i915_dmc_info, 0}, | 5381 | {"i915_dmc_info", i915_dmc_info, 0}, |
| 5288 | {"i915_display_info", i915_display_info, 0}, | 5382 | {"i915_display_info", i915_display_info, 0}, |
| 5383 | {"i915_engine_info", i915_engine_info, 0}, | ||
| 5289 | {"i915_semaphore_status", i915_semaphore_status, 0}, | 5384 | {"i915_semaphore_status", i915_semaphore_status, 0}, |
| 5290 | {"i915_shared_dplls_info", i915_shared_dplls_info, 0}, | 5385 | {"i915_shared_dplls_info", i915_shared_dplls_info, 0}, |
| 5291 | {"i915_dp_mst_info", i915_dp_mst_info, 0}, | 5386 | {"i915_dp_mst_info", i915_dp_mst_info, 0}, |
| @@ -5308,7 +5403,9 @@ static const struct i915_debugfs_files { | |||
| 5308 | {"i915_ring_missed_irq", &i915_ring_missed_irq_fops}, | 5403 | {"i915_ring_missed_irq", &i915_ring_missed_irq_fops}, |
| 5309 | {"i915_ring_test_irq", &i915_ring_test_irq_fops}, | 5404 | {"i915_ring_test_irq", &i915_ring_test_irq_fops}, |
| 5310 | {"i915_gem_drop_caches", &i915_drop_caches_fops}, | 5405 | {"i915_gem_drop_caches", &i915_drop_caches_fops}, |
| 5406 | #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) | ||
| 5311 | {"i915_error_state", &i915_error_state_fops}, | 5407 | {"i915_error_state", &i915_error_state_fops}, |
| 5408 | #endif | ||
| 5312 | {"i915_next_seqno", &i915_next_seqno_fops}, | 5409 | {"i915_next_seqno", &i915_next_seqno_fops}, |
| 5313 | {"i915_display_crc_ctl", &i915_display_crc_ctl_fops}, | 5410 | {"i915_display_crc_ctl", &i915_display_crc_ctl_fops}, |
| 5314 | {"i915_pri_wm_latency", &i915_pri_wm_latency_fops}, | 5411 | {"i915_pri_wm_latency", &i915_pri_wm_latency_fops}, |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7f4e8adec8a8..912d5348e3e7 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -114,7 +114,7 @@ static bool i915_error_injected(struct drm_i915_private *dev_priv) | |||
| 114 | fmt, ##__VA_ARGS__) | 114 | fmt, ##__VA_ARGS__) |
| 115 | 115 | ||
| 116 | 116 | ||
| 117 | static enum intel_pch intel_virt_detect_pch(struct drm_device *dev) | 117 | static enum intel_pch intel_virt_detect_pch(struct drm_i915_private *dev_priv) |
| 118 | { | 118 | { |
| 119 | enum intel_pch ret = PCH_NOP; | 119 | enum intel_pch ret = PCH_NOP; |
| 120 | 120 | ||
| @@ -125,16 +125,16 @@ static enum intel_pch intel_virt_detect_pch(struct drm_device *dev) | |||
| 125 | * make an educated guess as to which PCH is really there. | 125 | * make an educated guess as to which PCH is really there. |
| 126 | */ | 126 | */ |
| 127 | 127 | ||
| 128 | if (IS_GEN5(dev)) { | 128 | if (IS_GEN5(dev_priv)) { |
| 129 | ret = PCH_IBX; | 129 | ret = PCH_IBX; |
| 130 | DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n"); | 130 | DRM_DEBUG_KMS("Assuming Ibex Peak PCH\n"); |
| 131 | } else if (IS_GEN6(dev) || IS_IVYBRIDGE(dev)) { | 131 | } else if (IS_GEN6(dev_priv) || IS_IVYBRIDGE(dev_priv)) { |
| 132 | ret = PCH_CPT; | 132 | ret = PCH_CPT; |
| 133 | DRM_DEBUG_KMS("Assuming CouarPoint PCH\n"); | 133 | DRM_DEBUG_KMS("Assuming CouarPoint PCH\n"); |
| 134 | } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { | 134 | } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { |
| 135 | ret = PCH_LPT; | 135 | ret = PCH_LPT; |
| 136 | DRM_DEBUG_KMS("Assuming LynxPoint PCH\n"); | 136 | DRM_DEBUG_KMS("Assuming LynxPoint PCH\n"); |
| 137 | } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { | 137 | } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { |
| 138 | ret = PCH_SPT; | 138 | ret = PCH_SPT; |
| 139 | DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n"); | 139 | DRM_DEBUG_KMS("Assuming SunrisePoint PCH\n"); |
| 140 | } | 140 | } |
| @@ -174,40 +174,46 @@ static void intel_detect_pch(struct drm_device *dev) | |||
| 174 | if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) { | 174 | if (id == INTEL_PCH_IBX_DEVICE_ID_TYPE) { |
| 175 | dev_priv->pch_type = PCH_IBX; | 175 | dev_priv->pch_type = PCH_IBX; |
| 176 | DRM_DEBUG_KMS("Found Ibex Peak PCH\n"); | 176 | DRM_DEBUG_KMS("Found Ibex Peak PCH\n"); |
| 177 | WARN_ON(!IS_GEN5(dev)); | 177 | WARN_ON(!IS_GEN5(dev_priv)); |
| 178 | } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) { | 178 | } else if (id == INTEL_PCH_CPT_DEVICE_ID_TYPE) { |
| 179 | dev_priv->pch_type = PCH_CPT; | 179 | dev_priv->pch_type = PCH_CPT; |
| 180 | DRM_DEBUG_KMS("Found CougarPoint PCH\n"); | 180 | DRM_DEBUG_KMS("Found CougarPoint PCH\n"); |
| 181 | WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev))); | 181 | WARN_ON(!(IS_GEN6(dev_priv) || |
| 182 | IS_IVYBRIDGE(dev_priv))); | ||
| 182 | } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) { | 183 | } else if (id == INTEL_PCH_PPT_DEVICE_ID_TYPE) { |
| 183 | /* PantherPoint is CPT compatible */ | 184 | /* PantherPoint is CPT compatible */ |
| 184 | dev_priv->pch_type = PCH_CPT; | 185 | dev_priv->pch_type = PCH_CPT; |
| 185 | DRM_DEBUG_KMS("Found PantherPoint PCH\n"); | 186 | DRM_DEBUG_KMS("Found PantherPoint PCH\n"); |
| 186 | WARN_ON(!(IS_GEN6(dev) || IS_IVYBRIDGE(dev))); | 187 | WARN_ON(!(IS_GEN6(dev_priv) || |
| 188 | IS_IVYBRIDGE(dev_priv))); | ||
| 187 | } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { | 189 | } else if (id == INTEL_PCH_LPT_DEVICE_ID_TYPE) { |
| 188 | dev_priv->pch_type = PCH_LPT; | 190 | dev_priv->pch_type = PCH_LPT; |
| 189 | DRM_DEBUG_KMS("Found LynxPoint PCH\n"); | 191 | DRM_DEBUG_KMS("Found LynxPoint PCH\n"); |
| 190 | WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev)); | 192 | WARN_ON(!IS_HASWELL(dev_priv) && |
| 191 | WARN_ON(IS_HSW_ULT(dev) || IS_BDW_ULT(dev)); | 193 | !IS_BROADWELL(dev_priv)); |
| 194 | WARN_ON(IS_HSW_ULT(dev_priv) || | ||
| 195 | IS_BDW_ULT(dev_priv)); | ||
| 192 | } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { | 196 | } else if (id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) { |
| 193 | dev_priv->pch_type = PCH_LPT; | 197 | dev_priv->pch_type = PCH_LPT; |
| 194 | DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); | 198 | DRM_DEBUG_KMS("Found LynxPoint LP PCH\n"); |
| 195 | WARN_ON(!IS_HASWELL(dev) && !IS_BROADWELL(dev)); | 199 | WARN_ON(!IS_HASWELL(dev_priv) && |
| 196 | WARN_ON(!IS_HSW_ULT(dev) && !IS_BDW_ULT(dev)); | 200 | !IS_BROADWELL(dev_priv)); |
| 201 | WARN_ON(!IS_HSW_ULT(dev_priv) && | ||
| 202 | !IS_BDW_ULT(dev_priv)); | ||
| 197 | } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) { | 203 | } else if (id == INTEL_PCH_SPT_DEVICE_ID_TYPE) { |
| 198 | dev_priv->pch_type = PCH_SPT; | 204 | dev_priv->pch_type = PCH_SPT; |
| 199 | DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); | 205 | DRM_DEBUG_KMS("Found SunrisePoint PCH\n"); |
| 200 | WARN_ON(!IS_SKYLAKE(dev) && | 206 | WARN_ON(!IS_SKYLAKE(dev_priv) && |
| 201 | !IS_KABYLAKE(dev)); | 207 | !IS_KABYLAKE(dev_priv)); |
| 202 | } else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) { | 208 | } else if (id == INTEL_PCH_SPT_LP_DEVICE_ID_TYPE) { |
| 203 | dev_priv->pch_type = PCH_SPT; | 209 | dev_priv->pch_type = PCH_SPT; |
| 204 | DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n"); | 210 | DRM_DEBUG_KMS("Found SunrisePoint LP PCH\n"); |
| 205 | WARN_ON(!IS_SKYLAKE(dev) && | 211 | WARN_ON(!IS_SKYLAKE(dev_priv) && |
| 206 | !IS_KABYLAKE(dev)); | 212 | !IS_KABYLAKE(dev_priv)); |
| 207 | } else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) { | 213 | } else if (id == INTEL_PCH_KBP_DEVICE_ID_TYPE) { |
| 208 | dev_priv->pch_type = PCH_KBP; | 214 | dev_priv->pch_type = PCH_KBP; |
| 209 | DRM_DEBUG_KMS("Found KabyPoint PCH\n"); | 215 | DRM_DEBUG_KMS("Found KabyPoint PCH\n"); |
| 210 | WARN_ON(!IS_KABYLAKE(dev)); | 216 | WARN_ON(!IS_KABYLAKE(dev_priv)); |
| 211 | } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) || | 217 | } else if ((id == INTEL_PCH_P2X_DEVICE_ID_TYPE) || |
| 212 | (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) || | 218 | (id == INTEL_PCH_P3X_DEVICE_ID_TYPE) || |
| 213 | ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) && | 219 | ((id == INTEL_PCH_QEMU_DEVICE_ID_TYPE) && |
| @@ -215,7 +221,8 @@ static void intel_detect_pch(struct drm_device *dev) | |||
| 215 | PCI_SUBVENDOR_ID_REDHAT_QUMRANET && | 221 | PCI_SUBVENDOR_ID_REDHAT_QUMRANET && |
| 216 | pch->subsystem_device == | 222 | pch->subsystem_device == |
| 217 | PCI_SUBDEVICE_ID_QEMU)) { | 223 | PCI_SUBDEVICE_ID_QEMU)) { |
| 218 | dev_priv->pch_type = intel_virt_detect_pch(dev); | 224 | dev_priv->pch_type = |
| 225 | intel_virt_detect_pch(dev_priv); | ||
| 219 | } else | 226 | } else |
| 220 | continue; | 227 | continue; |
| 221 | 228 | ||
| @@ -255,16 +262,16 @@ static int i915_getparam(struct drm_device *dev, void *data, | |||
| 255 | value = dev_priv->overlay ? 1 : 0; | 262 | value = dev_priv->overlay ? 1 : 0; |
| 256 | break; | 263 | break; |
| 257 | case I915_PARAM_HAS_BSD: | 264 | case I915_PARAM_HAS_BSD: |
| 258 | value = intel_engine_initialized(&dev_priv->engine[VCS]); | 265 | value = !!dev_priv->engine[VCS]; |
| 259 | break; | 266 | break; |
| 260 | case I915_PARAM_HAS_BLT: | 267 | case I915_PARAM_HAS_BLT: |
| 261 | value = intel_engine_initialized(&dev_priv->engine[BCS]); | 268 | value = !!dev_priv->engine[BCS]; |
| 262 | break; | 269 | break; |
| 263 | case I915_PARAM_HAS_VEBOX: | 270 | case I915_PARAM_HAS_VEBOX: |
| 264 | value = intel_engine_initialized(&dev_priv->engine[VECS]); | 271 | value = !!dev_priv->engine[VECS]; |
| 265 | break; | 272 | break; |
| 266 | case I915_PARAM_HAS_BSD2: | 273 | case I915_PARAM_HAS_BSD2: |
| 267 | value = intel_engine_initialized(&dev_priv->engine[VCS2]); | 274 | value = !!dev_priv->engine[VCS2]; |
| 268 | break; | 275 | break; |
| 269 | case I915_PARAM_HAS_EXEC_CONSTANTS: | 276 | case I915_PARAM_HAS_EXEC_CONSTANTS: |
| 270 | value = INTEL_GEN(dev_priv) >= 4; | 277 | value = INTEL_GEN(dev_priv) >= 4; |
| @@ -417,12 +424,12 @@ intel_setup_mchbar(struct drm_device *dev) | |||
| 417 | u32 temp; | 424 | u32 temp; |
| 418 | bool enabled; | 425 | bool enabled; |
| 419 | 426 | ||
| 420 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 427 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 421 | return; | 428 | return; |
| 422 | 429 | ||
| 423 | dev_priv->mchbar_need_disable = false; | 430 | dev_priv->mchbar_need_disable = false; |
| 424 | 431 | ||
| 425 | if (IS_I915G(dev) || IS_I915GM(dev)) { | 432 | if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { |
| 426 | pci_read_config_dword(dev_priv->bridge_dev, DEVEN, &temp); | 433 | pci_read_config_dword(dev_priv->bridge_dev, DEVEN, &temp); |
| 427 | enabled = !!(temp & DEVEN_MCHBAR_EN); | 434 | enabled = !!(temp & DEVEN_MCHBAR_EN); |
| 428 | } else { | 435 | } else { |
| @@ -440,7 +447,7 @@ intel_setup_mchbar(struct drm_device *dev) | |||
| 440 | dev_priv->mchbar_need_disable = true; | 447 | dev_priv->mchbar_need_disable = true; |
| 441 | 448 | ||
| 442 | /* Space is allocated or reserved, so enable it. */ | 449 | /* Space is allocated or reserved, so enable it. */ |
| 443 | if (IS_I915G(dev) || IS_I915GM(dev)) { | 450 | if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { |
| 444 | pci_write_config_dword(dev_priv->bridge_dev, DEVEN, | 451 | pci_write_config_dword(dev_priv->bridge_dev, DEVEN, |
| 445 | temp | DEVEN_MCHBAR_EN); | 452 | temp | DEVEN_MCHBAR_EN); |
| 446 | } else { | 453 | } else { |
| @@ -456,7 +463,7 @@ intel_teardown_mchbar(struct drm_device *dev) | |||
| 456 | int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915; | 463 | int mchbar_reg = INTEL_INFO(dev)->gen >= 4 ? MCHBAR_I965 : MCHBAR_I915; |
| 457 | 464 | ||
| 458 | if (dev_priv->mchbar_need_disable) { | 465 | if (dev_priv->mchbar_need_disable) { |
| 459 | if (IS_I915G(dev) || IS_I915GM(dev)) { | 466 | if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { |
| 460 | u32 deven_val; | 467 | u32 deven_val; |
| 461 | 468 | ||
| 462 | pci_read_config_dword(dev_priv->bridge_dev, DEVEN, | 469 | pci_read_config_dword(dev_priv->bridge_dev, DEVEN, |
| @@ -532,32 +539,6 @@ static const struct vga_switcheroo_client_ops i915_switcheroo_ops = { | |||
| 532 | 539 | ||
| 533 | static void i915_gem_fini(struct drm_device *dev) | 540 | static void i915_gem_fini(struct drm_device *dev) |
| 534 | { | 541 | { |
| 535 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 536 | |||
| 537 | /* | ||
| 538 | * Neither the BIOS, ourselves or any other kernel | ||
| 539 | * expects the system to be in execlists mode on startup, | ||
| 540 | * so we need to reset the GPU back to legacy mode. And the only | ||
| 541 | * known way to disable logical contexts is through a GPU reset. | ||
| 542 | * | ||
| 543 | * So in order to leave the system in a known default configuration, | ||
| 544 | * always reset the GPU upon unload. Afterwards we then clean up the | ||
| 545 | * GEM state tracking, flushing off the requests and leaving the | ||
| 546 | * system in a known idle state. | ||
| 547 | * | ||
| 548 | * Note that is of the upmost importance that the GPU is idle and | ||
| 549 | * all stray writes are flushed *before* we dismantle the backing | ||
| 550 | * storage for the pinned objects. | ||
| 551 | * | ||
| 552 | * However, since we are uncertain that reseting the GPU on older | ||
| 553 | * machines is a good idea, we don't - just in case it leaves the | ||
| 554 | * machine in an unusable condition. | ||
| 555 | */ | ||
| 556 | if (HAS_HW_CONTEXTS(dev)) { | ||
| 557 | int reset = intel_gpu_reset(dev_priv, ALL_ENGINES); | ||
| 558 | WARN_ON(reset && reset != -ENODEV); | ||
| 559 | } | ||
| 560 | |||
| 561 | mutex_lock(&dev->struct_mutex); | 542 | mutex_lock(&dev->struct_mutex); |
| 562 | i915_gem_cleanup_engines(dev); | 543 | i915_gem_cleanup_engines(dev); |
| 563 | i915_gem_context_fini(dev); | 544 | i915_gem_context_fini(dev); |
| @@ -636,6 +617,8 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
| 636 | return 0; | 617 | return 0; |
| 637 | 618 | ||
| 638 | cleanup_gem: | 619 | cleanup_gem: |
| 620 | if (i915_gem_suspend(dev)) | ||
| 621 | DRM_ERROR("failed to idle hardware; continuing to unload!\n"); | ||
| 639 | i915_gem_fini(dev); | 622 | i915_gem_fini(dev); |
| 640 | cleanup_irq: | 623 | cleanup_irq: |
| 641 | intel_guc_fini(dev); | 624 | intel_guc_fini(dev); |
| @@ -771,6 +754,19 @@ static void i915_workqueues_cleanup(struct drm_i915_private *dev_priv) | |||
| 771 | destroy_workqueue(dev_priv->wq); | 754 | destroy_workqueue(dev_priv->wq); |
| 772 | } | 755 | } |
| 773 | 756 | ||
| 757 | /* | ||
| 758 | * We don't keep the workarounds for pre-production hardware, so we expect our | ||
| 759 | * driver to fail on these machines in one way or another. A little warning on | ||
| 760 | * dmesg may help both the user and the bug triagers. | ||
| 761 | */ | ||
| 762 | static void intel_detect_preproduction_hw(struct drm_i915_private *dev_priv) | ||
| 763 | { | ||
| 764 | if (IS_HSW_EARLY_SDV(dev_priv) || | ||
| 765 | IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0)) | ||
| 766 | DRM_ERROR("This is a pre-production stepping. " | ||
| 767 | "It may not be fully functional.\n"); | ||
| 768 | } | ||
| 769 | |||
| 774 | /** | 770 | /** |
| 775 | * i915_driver_init_early - setup state not requiring device access | 771 | * i915_driver_init_early - setup state not requiring device access |
| 776 | * @dev_priv: device private | 772 | * @dev_priv: device private |
| @@ -838,13 +834,7 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, | |||
| 838 | 834 | ||
| 839 | intel_device_info_dump(dev_priv); | 835 | intel_device_info_dump(dev_priv); |
| 840 | 836 | ||
| 841 | /* Not all pre-production machines fall into this category, only the | 837 | intel_detect_preproduction_hw(dev_priv); |
| 842 | * very first ones. Almost everything should work, except for maybe | ||
| 843 | * suspend/resume. And we don't implement workarounds that affect only | ||
| 844 | * pre-production machines. */ | ||
| 845 | if (IS_HSW_EARLY_SDV(dev_priv)) | ||
| 846 | DRM_INFO("This is an early pre-production Haswell machine. " | ||
| 847 | "It may not be fully functional.\n"); | ||
| 848 | 838 | ||
| 849 | return 0; | 839 | return 0; |
| 850 | 840 | ||
| @@ -870,7 +860,7 @@ static int i915_mmio_setup(struct drm_device *dev) | |||
| 870 | int mmio_bar; | 860 | int mmio_bar; |
| 871 | int mmio_size; | 861 | int mmio_size; |
| 872 | 862 | ||
| 873 | mmio_bar = IS_GEN2(dev) ? 1 : 0; | 863 | mmio_bar = IS_GEN2(dev_priv) ? 1 : 0; |
| 874 | /* | 864 | /* |
| 875 | * Before gen4, the registers and the GTT are behind different BARs. | 865 | * Before gen4, the registers and the GTT are behind different BARs. |
| 876 | * However, from gen4 onwards, the registers and the GTT are shared | 866 | * However, from gen4 onwards, the registers and the GTT are shared |
| @@ -1023,7 +1013,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) | |||
| 1023 | pci_set_master(pdev); | 1013 | pci_set_master(pdev); |
| 1024 | 1014 | ||
| 1025 | /* overlay on gen2 is broken and can't address above 1G */ | 1015 | /* overlay on gen2 is broken and can't address above 1G */ |
| 1026 | if (IS_GEN2(dev)) { | 1016 | if (IS_GEN2(dev_priv)) { |
| 1027 | ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(30)); | 1017 | ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(30)); |
| 1028 | if (ret) { | 1018 | if (ret) { |
| 1029 | DRM_ERROR("failed to set DMA mask\n"); | 1019 | DRM_ERROR("failed to set DMA mask\n"); |
| @@ -1070,7 +1060,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv) | |||
| 1070 | * be lost or delayed, but we use them anyways to avoid | 1060 | * be lost or delayed, but we use them anyways to avoid |
| 1071 | * stuck interrupts on some machines. | 1061 | * stuck interrupts on some machines. |
| 1072 | */ | 1062 | */ |
| 1073 | if (!IS_I945G(dev) && !IS_I945GM(dev)) { | 1063 | if (!IS_I945G(dev_priv) && !IS_I945GM(dev_priv)) { |
| 1074 | if (pci_enable_msi(pdev) < 0) | 1064 | if (pci_enable_msi(pdev) < 0) |
| 1075 | DRM_DEBUG_DRIVER("can't enable MSI"); | 1065 | DRM_DEBUG_DRIVER("can't enable MSI"); |
| 1076 | } | 1066 | } |
| @@ -1242,6 +1232,10 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 1242 | DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", | 1232 | DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", |
| 1243 | driver.name, driver.major, driver.minor, driver.patchlevel, | 1233 | driver.name, driver.major, driver.minor, driver.patchlevel, |
| 1244 | driver.date, pci_name(pdev), dev_priv->drm.primary->index); | 1234 | driver.date, pci_name(pdev), dev_priv->drm.primary->index); |
| 1235 | if (IS_ENABLED(CONFIG_DRM_I915_DEBUG)) | ||
| 1236 | DRM_INFO("DRM_I915_DEBUG enabled\n"); | ||
| 1237 | if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) | ||
| 1238 | DRM_INFO("DRM_I915_DEBUG_GEM enabled\n"); | ||
| 1245 | 1239 | ||
| 1246 | intel_runtime_pm_put(dev_priv); | 1240 | intel_runtime_pm_put(dev_priv); |
| 1247 | 1241 | ||
| @@ -1447,8 +1441,6 @@ static int i915_drm_suspend(struct drm_device *dev) | |||
| 1447 | 1441 | ||
| 1448 | dev_priv->suspend_count++; | 1442 | dev_priv->suspend_count++; |
| 1449 | 1443 | ||
| 1450 | intel_display_set_init_power(dev_priv, false); | ||
| 1451 | |||
| 1452 | intel_csr_ucode_suspend(dev_priv); | 1444 | intel_csr_ucode_suspend(dev_priv); |
| 1453 | 1445 | ||
| 1454 | out: | 1446 | out: |
| @@ -1466,6 +1458,8 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) | |||
| 1466 | 1458 | ||
| 1467 | disable_rpm_wakeref_asserts(dev_priv); | 1459 | disable_rpm_wakeref_asserts(dev_priv); |
| 1468 | 1460 | ||
| 1461 | intel_display_set_init_power(dev_priv, false); | ||
| 1462 | |||
| 1469 | fw_csr = !IS_BROXTON(dev_priv) && | 1463 | fw_csr = !IS_BROXTON(dev_priv) && |
| 1470 | suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload; | 1464 | suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload; |
| 1471 | /* | 1465 | /* |
| @@ -1721,6 +1715,22 @@ int i915_resume_switcheroo(struct drm_device *dev) | |||
| 1721 | return i915_drm_resume(dev); | 1715 | return i915_drm_resume(dev); |
| 1722 | } | 1716 | } |
| 1723 | 1717 | ||
| 1718 | static void disable_engines_irq(struct drm_i915_private *dev_priv) | ||
| 1719 | { | ||
| 1720 | struct intel_engine_cs *engine; | ||
| 1721 | enum intel_engine_id id; | ||
| 1722 | |||
| 1723 | /* Ensure irq handler finishes, and not run again. */ | ||
| 1724 | disable_irq(dev_priv->drm.irq); | ||
| 1725 | for_each_engine(engine, dev_priv, id) | ||
| 1726 | tasklet_kill(&engine->irq_tasklet); | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | static void enable_engines_irq(struct drm_i915_private *dev_priv) | ||
| 1730 | { | ||
| 1731 | enable_irq(dev_priv->drm.irq); | ||
| 1732 | } | ||
| 1733 | |||
| 1724 | /** | 1734 | /** |
| 1725 | * i915_reset - reset chip after a hang | 1735 | * i915_reset - reset chip after a hang |
| 1726 | * @dev: drm device to reset | 1736 | * @dev: drm device to reset |
| @@ -1754,7 +1764,11 @@ void i915_reset(struct drm_i915_private *dev_priv) | |||
| 1754 | error->reset_count++; | 1764 | error->reset_count++; |
| 1755 | 1765 | ||
| 1756 | pr_notice("drm/i915: Resetting chip after gpu hang\n"); | 1766 | pr_notice("drm/i915: Resetting chip after gpu hang\n"); |
| 1767 | |||
| 1768 | disable_engines_irq(dev_priv); | ||
| 1757 | ret = intel_gpu_reset(dev_priv, ALL_ENGINES); | 1769 | ret = intel_gpu_reset(dev_priv, ALL_ENGINES); |
| 1770 | enable_engines_irq(dev_priv); | ||
| 1771 | |||
| 1758 | if (ret) { | 1772 | if (ret) { |
| 1759 | if (ret != -ENODEV) | 1773 | if (ret != -ENODEV) |
| 1760 | DRM_ERROR("Failed to reset chip: %i\n", ret); | 1774 | DRM_ERROR("Failed to reset chip: %i\n", ret); |
| @@ -1786,15 +1800,6 @@ void i915_reset(struct drm_i915_private *dev_priv) | |||
| 1786 | goto error; | 1800 | goto error; |
| 1787 | } | 1801 | } |
| 1788 | 1802 | ||
| 1789 | /* | ||
| 1790 | * rps/rc6 re-init is necessary to restore state lost after the | ||
| 1791 | * reset and the re-install of gt irqs. Skip for ironlake per | ||
| 1792 | * previous concerns that it doesn't respond well to some forms | ||
| 1793 | * of re-init after reset. | ||
| 1794 | */ | ||
| 1795 | intel_sanitize_gt_powersave(dev_priv); | ||
| 1796 | intel_autoenable_gt_powersave(dev_priv); | ||
| 1797 | |||
| 1798 | wakeup: | 1803 | wakeup: |
| 1799 | wake_up_bit(&error->flags, I915_RESET_IN_PROGRESS); | 1804 | wake_up_bit(&error->flags, I915_RESET_IN_PROGRESS); |
| 1800 | return; | 1805 | return; |
| @@ -1872,7 +1877,17 @@ static int i915_pm_resume(struct device *kdev) | |||
| 1872 | /* freeze: before creating the hibernation_image */ | 1877 | /* freeze: before creating the hibernation_image */ |
| 1873 | static int i915_pm_freeze(struct device *kdev) | 1878 | static int i915_pm_freeze(struct device *kdev) |
| 1874 | { | 1879 | { |
| 1875 | return i915_pm_suspend(kdev); | 1880 | int ret; |
| 1881 | |||
| 1882 | ret = i915_pm_suspend(kdev); | ||
| 1883 | if (ret) | ||
| 1884 | return ret; | ||
| 1885 | |||
| 1886 | ret = i915_gem_freeze(kdev_to_i915(kdev)); | ||
| 1887 | if (ret) | ||
| 1888 | return ret; | ||
| 1889 | |||
| 1890 | return 0; | ||
| 1876 | } | 1891 | } |
| 1877 | 1892 | ||
| 1878 | static int i915_pm_freeze_late(struct device *kdev) | 1893 | static int i915_pm_freeze_late(struct device *kdev) |
| @@ -2281,7 +2296,7 @@ static int intel_runtime_suspend(struct device *kdev) | |||
| 2281 | if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6()))) | 2296 | if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6()))) |
| 2282 | return -ENODEV; | 2297 | return -ENODEV; |
| 2283 | 2298 | ||
| 2284 | if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev))) | 2299 | if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev_priv))) |
| 2285 | return -ENODEV; | 2300 | return -ENODEV; |
| 2286 | 2301 | ||
| 2287 | DRM_DEBUG_KMS("Suspending device\n"); | 2302 | DRM_DEBUG_KMS("Suspending device\n"); |
| @@ -2385,7 +2400,7 @@ static int intel_runtime_resume(struct device *kdev) | |||
| 2385 | struct drm_i915_private *dev_priv = to_i915(dev); | 2400 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2386 | int ret = 0; | 2401 | int ret = 0; |
| 2387 | 2402 | ||
| 2388 | if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev))) | 2403 | if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev_priv))) |
| 2389 | return -ENODEV; | 2404 | return -ENODEV; |
| 2390 | 2405 | ||
| 2391 | DRM_DEBUG_KMS("Resuming device\n"); | 2406 | DRM_DEBUG_KMS("Resuming device\n"); |
| @@ -2403,7 +2418,7 @@ static int intel_runtime_resume(struct device *kdev) | |||
| 2403 | if (IS_GEN6(dev_priv)) | 2418 | if (IS_GEN6(dev_priv)) |
| 2404 | intel_init_pch_refclk(dev); | 2419 | intel_init_pch_refclk(dev); |
| 2405 | 2420 | ||
| 2406 | if (IS_BROXTON(dev)) { | 2421 | if (IS_BROXTON(dev_priv)) { |
| 2407 | bxt_disable_dc9(dev_priv); | 2422 | bxt_disable_dc9(dev_priv); |
| 2408 | bxt_display_core_init(dev_priv, true); | 2423 | bxt_display_core_init(dev_priv, true); |
| 2409 | if (dev_priv->csr.dmc_payload && | 2424 | if (dev_priv->csr.dmc_payload && |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 4dd307ed4336..f022f438e5b9 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -70,7 +70,8 @@ | |||
| 70 | 70 | ||
| 71 | #define DRIVER_NAME "i915" | 71 | #define DRIVER_NAME "i915" |
| 72 | #define DRIVER_DESC "Intel Graphics" | 72 | #define DRIVER_DESC "Intel Graphics" |
| 73 | #define DRIVER_DATE "20160919" | 73 | #define DRIVER_DATE "20161024" |
| 74 | #define DRIVER_TIMESTAMP 1477290335 | ||
| 74 | 75 | ||
| 75 | #undef WARN_ON | 76 | #undef WARN_ON |
| 76 | /* Many gcc seem to no see through this and fall over :( */ | 77 | /* Many gcc seem to no see through this and fall over :( */ |
| @@ -185,6 +186,7 @@ enum plane { | |||
| 185 | #define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites[(p)] + (s) + 'A') | 186 | #define sprite_name(p, s) ((p) * INTEL_INFO(dev)->num_sprites[(p)] + (s) + 'A') |
| 186 | 187 | ||
| 187 | enum port { | 188 | enum port { |
| 189 | PORT_NONE = -1, | ||
| 188 | PORT_A = 0, | 190 | PORT_A = 0, |
| 189 | PORT_B, | 191 | PORT_B, |
| 190 | PORT_C, | 192 | PORT_C, |
| @@ -581,13 +583,25 @@ struct intel_uncore_funcs { | |||
| 581 | uint32_t val, bool trace); | 583 | uint32_t val, bool trace); |
| 582 | }; | 584 | }; |
| 583 | 585 | ||
| 586 | struct intel_forcewake_range { | ||
| 587 | u32 start; | ||
| 588 | u32 end; | ||
| 589 | |||
| 590 | enum forcewake_domains domains; | ||
| 591 | }; | ||
| 592 | |||
| 584 | struct intel_uncore { | 593 | struct intel_uncore { |
| 585 | spinlock_t lock; /** lock is also taken in irq contexts. */ | 594 | spinlock_t lock; /** lock is also taken in irq contexts. */ |
| 586 | 595 | ||
| 596 | const struct intel_forcewake_range *fw_domains_table; | ||
| 597 | unsigned int fw_domains_table_entries; | ||
| 598 | |||
| 587 | struct intel_uncore_funcs funcs; | 599 | struct intel_uncore_funcs funcs; |
| 588 | 600 | ||
| 589 | unsigned fifo_count; | 601 | unsigned fifo_count; |
| 602 | |||
| 590 | enum forcewake_domains fw_domains; | 603 | enum forcewake_domains fw_domains; |
| 604 | enum forcewake_domains fw_domains_active; | ||
| 591 | 605 | ||
| 592 | struct intel_uncore_forcewake_domain { | 606 | struct intel_uncore_forcewake_domain { |
| 593 | struct drm_i915_private *i915; | 607 | struct drm_i915_private *i915; |
| @@ -633,54 +647,53 @@ struct intel_csr { | |||
| 633 | uint32_t allowed_dc_mask; | 647 | uint32_t allowed_dc_mask; |
| 634 | }; | 648 | }; |
| 635 | 649 | ||
| 636 | #define DEV_INFO_FOR_EACH_FLAG(func, sep) \ | 650 | #define DEV_INFO_FOR_EACH_FLAG(func) \ |
| 637 | func(is_mobile) sep \ | 651 | /* Keep is_* in chronological order */ \ |
| 638 | func(is_i85x) sep \ | 652 | func(is_mobile); \ |
| 639 | func(is_i915g) sep \ | 653 | func(is_i85x); \ |
| 640 | func(is_i945gm) sep \ | 654 | func(is_i915g); \ |
| 641 | func(is_g33) sep \ | 655 | func(is_i945gm); \ |
| 642 | func(hws_needs_physical) sep \ | 656 | func(is_g33); \ |
| 643 | func(is_g4x) sep \ | 657 | func(is_g4x); \ |
| 644 | func(is_pineview) sep \ | 658 | func(is_pineview); \ |
| 645 | func(is_broadwater) sep \ | 659 | func(is_broadwater); \ |
| 646 | func(is_crestline) sep \ | 660 | func(is_crestline); \ |
| 647 | func(is_ivybridge) sep \ | 661 | func(is_ivybridge); \ |
| 648 | func(is_valleyview) sep \ | 662 | func(is_valleyview); \ |
| 649 | func(is_cherryview) sep \ | 663 | func(is_cherryview); \ |
| 650 | func(is_haswell) sep \ | 664 | func(is_haswell); \ |
| 651 | func(is_broadwell) sep \ | 665 | func(is_broadwell); \ |
| 652 | func(is_skylake) sep \ | 666 | func(is_skylake); \ |
| 653 | func(is_broxton) sep \ | 667 | func(is_broxton); \ |
| 654 | func(is_kabylake) sep \ | 668 | func(is_kabylake); \ |
| 655 | func(is_preliminary) sep \ | 669 | func(is_preliminary); \ |
| 656 | func(has_fbc) sep \ | 670 | /* Keep has_* in alphabetical order */ \ |
| 657 | func(has_psr) sep \ | 671 | func(has_csr); \ |
| 658 | func(has_runtime_pm) sep \ | 672 | func(has_ddi); \ |
| 659 | func(has_csr) sep \ | 673 | func(has_dp_mst); \ |
| 660 | func(has_resource_streamer) sep \ | 674 | func(has_fbc); \ |
| 661 | func(has_rc6) sep \ | 675 | func(has_fpga_dbg); \ |
| 662 | func(has_rc6p) sep \ | 676 | func(has_gmbus_irq); \ |
| 663 | func(has_dp_mst) sep \ | 677 | func(has_gmch_display); \ |
| 664 | func(has_gmbus_irq) sep \ | 678 | func(has_guc); \ |
| 665 | func(has_hw_contexts) sep \ | 679 | func(has_hotplug); \ |
| 666 | func(has_logical_ring_contexts) sep \ | 680 | func(has_hw_contexts); \ |
| 667 | func(has_l3_dpf) sep \ | 681 | func(has_l3_dpf); \ |
| 668 | func(has_gmch_display) sep \ | 682 | func(has_llc); \ |
| 669 | func(has_guc) sep \ | 683 | func(has_logical_ring_contexts); \ |
| 670 | func(has_pipe_cxsr) sep \ | 684 | func(has_overlay); \ |
| 671 | func(has_hotplug) sep \ | 685 | func(has_pipe_cxsr); \ |
| 672 | func(cursor_needs_physical) sep \ | 686 | func(has_pooled_eu); \ |
| 673 | func(has_overlay) sep \ | 687 | func(has_psr); \ |
| 674 | func(overlay_needs_physical) sep \ | 688 | func(has_rc6); \ |
| 675 | func(supports_tv) sep \ | 689 | func(has_rc6p); \ |
| 676 | func(has_llc) sep \ | 690 | func(has_resource_streamer); \ |
| 677 | func(has_snoop) sep \ | 691 | func(has_runtime_pm); \ |
| 678 | func(has_ddi) sep \ | 692 | func(has_snoop); \ |
| 679 | func(has_fpga_dbg) sep \ | 693 | func(cursor_needs_physical); \ |
| 680 | func(has_pooled_eu) | 694 | func(hws_needs_physical); \ |
| 681 | 695 | func(overlay_needs_physical); \ | |
| 682 | #define DEFINE_FLAG(name) u8 name:1 | 696 | func(supports_tv) |
| 683 | #define SEP_SEMICOLON ; | ||
| 684 | 697 | ||
| 685 | struct sseu_dev_info { | 698 | struct sseu_dev_info { |
| 686 | u8 slice_mask; | 699 | u8 slice_mask; |
| @@ -709,7 +722,9 @@ struct intel_device_info { | |||
| 709 | u16 gen_mask; | 722 | u16 gen_mask; |
| 710 | u8 ring_mask; /* Rings supported by the HW */ | 723 | u8 ring_mask; /* Rings supported by the HW */ |
| 711 | u8 num_rings; | 724 | u8 num_rings; |
| 712 | DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON); | 725 | #define DEFINE_FLAG(name) u8 name:1 |
| 726 | DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG); | ||
| 727 | #undef DEFINE_FLAG | ||
| 713 | u16 ddb_size; /* in blocks */ | 728 | u16 ddb_size; /* in blocks */ |
| 714 | /* Register offsets for the various display pipes and transcoders */ | 729 | /* Register offsets for the various display pipes and transcoders */ |
| 715 | int pipe_offsets[I915_MAX_TRANSCODERS]; | 730 | int pipe_offsets[I915_MAX_TRANSCODERS]; |
| @@ -726,15 +741,14 @@ struct intel_device_info { | |||
| 726 | } color; | 741 | } color; |
| 727 | }; | 742 | }; |
| 728 | 743 | ||
| 729 | #undef DEFINE_FLAG | ||
| 730 | #undef SEP_SEMICOLON | ||
| 731 | |||
| 732 | struct intel_display_error_state; | 744 | struct intel_display_error_state; |
| 733 | 745 | ||
| 734 | struct drm_i915_error_state { | 746 | struct drm_i915_error_state { |
| 735 | struct kref ref; | 747 | struct kref ref; |
| 736 | struct timeval time; | 748 | struct timeval time; |
| 737 | 749 | ||
| 750 | struct drm_i915_private *i915; | ||
| 751 | |||
| 738 | char error_msg[128]; | 752 | char error_msg[128]; |
| 739 | bool simulated; | 753 | bool simulated; |
| 740 | int iommu; | 754 | int iommu; |
| @@ -759,7 +773,7 @@ struct drm_i915_error_state { | |||
| 759 | u32 gam_ecochk; | 773 | u32 gam_ecochk; |
| 760 | u32 gab_ctl; | 774 | u32 gab_ctl; |
| 761 | u32 gfx_mode; | 775 | u32 gfx_mode; |
| 762 | u32 extra_instdone[I915_NUM_INSTDONE_REG]; | 776 | |
| 763 | u64 fence[I915_MAX_NUM_FENCES]; | 777 | u64 fence[I915_MAX_NUM_FENCES]; |
| 764 | struct intel_overlay_error_state *overlay; | 778 | struct intel_overlay_error_state *overlay; |
| 765 | struct intel_display_error_state *display; | 779 | struct intel_display_error_state *display; |
| @@ -775,6 +789,9 @@ struct drm_i915_error_state { | |||
| 775 | struct i915_address_space *vm; | 789 | struct i915_address_space *vm; |
| 776 | int num_requests; | 790 | int num_requests; |
| 777 | 791 | ||
| 792 | /* position of active request inside the ring */ | ||
| 793 | u32 rq_head, rq_post, rq_tail; | ||
| 794 | |||
| 778 | /* our own tracking of ring head and tail */ | 795 | /* our own tracking of ring head and tail */ |
| 779 | u32 cpu_ring_head; | 796 | u32 cpu_ring_head; |
| 780 | u32 cpu_ring_tail; | 797 | u32 cpu_ring_tail; |
| @@ -791,7 +808,6 @@ struct drm_i915_error_state { | |||
| 791 | u32 hws; | 808 | u32 hws; |
| 792 | u32 ipeir; | 809 | u32 ipeir; |
| 793 | u32 ipehr; | 810 | u32 ipehr; |
| 794 | u32 instdone; | ||
| 795 | u32 bbstate; | 811 | u32 bbstate; |
| 796 | u32 instpm; | 812 | u32 instpm; |
| 797 | u32 instps; | 813 | u32 instps; |
| @@ -802,11 +818,13 @@ struct drm_i915_error_state { | |||
| 802 | u64 faddr; | 818 | u64 faddr; |
| 803 | u32 rc_psmi; /* sleep state */ | 819 | u32 rc_psmi; /* sleep state */ |
| 804 | u32 semaphore_mboxes[I915_NUM_ENGINES - 1]; | 820 | u32 semaphore_mboxes[I915_NUM_ENGINES - 1]; |
| 821 | struct intel_instdone instdone; | ||
| 805 | 822 | ||
| 806 | struct drm_i915_error_object { | 823 | struct drm_i915_error_object { |
| 807 | int page_count; | ||
| 808 | u64 gtt_offset; | 824 | u64 gtt_offset; |
| 809 | u64 gtt_size; | 825 | u64 gtt_size; |
| 826 | int page_count; | ||
| 827 | int unused; | ||
| 810 | u32 *pages[0]; | 828 | u32 *pages[0]; |
| 811 | } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page; | 829 | } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page; |
| 812 | 830 | ||
| @@ -815,10 +833,11 @@ struct drm_i915_error_state { | |||
| 815 | struct drm_i915_error_request { | 833 | struct drm_i915_error_request { |
| 816 | long jiffies; | 834 | long jiffies; |
| 817 | pid_t pid; | 835 | pid_t pid; |
| 836 | u32 context; | ||
| 818 | u32 seqno; | 837 | u32 seqno; |
| 819 | u32 head; | 838 | u32 head; |
| 820 | u32 tail; | 839 | u32 tail; |
| 821 | } *requests; | 840 | } *requests, execlist[2]; |
| 822 | 841 | ||
| 823 | struct drm_i915_error_waiter { | 842 | struct drm_i915_error_waiter { |
| 824 | char comm[TASK_COMM_LEN]; | 843 | char comm[TASK_COMM_LEN]; |
| @@ -972,6 +991,9 @@ struct intel_fbc { | |||
| 972 | bool enabled; | 991 | bool enabled; |
| 973 | bool active; | 992 | bool active; |
| 974 | 993 | ||
| 994 | bool underrun_detected; | ||
| 995 | struct work_struct underrun_work; | ||
| 996 | |||
| 975 | struct intel_fbc_state_cache { | 997 | struct intel_fbc_state_cache { |
| 976 | struct { | 998 | struct { |
| 977 | unsigned int mode_flags; | 999 | unsigned int mode_flags; |
| @@ -1368,7 +1390,7 @@ struct i915_gem_mm { | |||
| 1368 | 1390 | ||
| 1369 | /* accounting, useful for userland debugging */ | 1391 | /* accounting, useful for userland debugging */ |
| 1370 | spinlock_t object_stat_lock; | 1392 | spinlock_t object_stat_lock; |
| 1371 | size_t object_memory; | 1393 | u64 object_memory; |
| 1372 | u32 object_count; | 1394 | u32 object_count; |
| 1373 | }; | 1395 | }; |
| 1374 | 1396 | ||
| @@ -1620,7 +1642,6 @@ static inline bool skl_ddb_entry_equal(const struct skl_ddb_entry *e1, | |||
| 1620 | } | 1642 | } |
| 1621 | 1643 | ||
| 1622 | struct skl_ddb_allocation { | 1644 | struct skl_ddb_allocation { |
| 1623 | struct skl_ddb_entry pipe[I915_MAX_PIPES]; | ||
| 1624 | struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; /* packed/uv */ | 1645 | struct skl_ddb_entry plane[I915_MAX_PIPES][I915_MAX_PLANES]; /* packed/uv */ |
| 1625 | struct skl_ddb_entry y_plane[I915_MAX_PIPES][I915_MAX_PLANES]; | 1646 | struct skl_ddb_entry y_plane[I915_MAX_PIPES][I915_MAX_PLANES]; |
| 1626 | }; | 1647 | }; |
| @@ -1628,15 +1649,12 @@ struct skl_ddb_allocation { | |||
| 1628 | struct skl_wm_values { | 1649 | struct skl_wm_values { |
| 1629 | unsigned dirty_pipes; | 1650 | unsigned dirty_pipes; |
| 1630 | struct skl_ddb_allocation ddb; | 1651 | struct skl_ddb_allocation ddb; |
| 1631 | uint32_t wm_linetime[I915_MAX_PIPES]; | ||
| 1632 | uint32_t plane[I915_MAX_PIPES][I915_MAX_PLANES][8]; | ||
| 1633 | uint32_t plane_trans[I915_MAX_PIPES][I915_MAX_PLANES]; | ||
| 1634 | }; | 1652 | }; |
| 1635 | 1653 | ||
| 1636 | struct skl_wm_level { | 1654 | struct skl_wm_level { |
| 1637 | bool plane_en[I915_MAX_PLANES]; | 1655 | bool plane_en; |
| 1638 | uint16_t plane_res_b[I915_MAX_PLANES]; | 1656 | uint16_t plane_res_b; |
| 1639 | uint8_t plane_res_l[I915_MAX_PLANES]; | 1657 | uint8_t plane_res_l; |
| 1640 | }; | 1658 | }; |
| 1641 | 1659 | ||
| 1642 | /* | 1660 | /* |
| @@ -1759,7 +1777,7 @@ struct drm_i915_private { | |||
| 1759 | 1777 | ||
| 1760 | struct i915_virtual_gpu vgpu; | 1778 | struct i915_virtual_gpu vgpu; |
| 1761 | 1779 | ||
| 1762 | struct intel_gvt gvt; | 1780 | struct intel_gvt *gvt; |
| 1763 | 1781 | ||
| 1764 | struct intel_guc guc; | 1782 | struct intel_guc guc; |
| 1765 | 1783 | ||
| @@ -1787,7 +1805,7 @@ struct drm_i915_private { | |||
| 1787 | 1805 | ||
| 1788 | struct pci_dev *bridge_dev; | 1806 | struct pci_dev *bridge_dev; |
| 1789 | struct i915_gem_context *kernel_context; | 1807 | struct i915_gem_context *kernel_context; |
| 1790 | struct intel_engine_cs engine[I915_NUM_ENGINES]; | 1808 | struct intel_engine_cs *engine[I915_NUM_ENGINES]; |
| 1791 | struct i915_vma *semaphore; | 1809 | struct i915_vma *semaphore; |
| 1792 | u32 next_seqno; | 1810 | u32 next_seqno; |
| 1793 | 1811 | ||
| @@ -1984,11 +2002,11 @@ struct drm_i915_private { | |||
| 1984 | struct vlv_s0ix_state vlv_s0ix_state; | 2002 | struct vlv_s0ix_state vlv_s0ix_state; |
| 1985 | 2003 | ||
| 1986 | enum { | 2004 | enum { |
| 1987 | I915_SKL_SAGV_UNKNOWN = 0, | 2005 | I915_SAGV_UNKNOWN = 0, |
| 1988 | I915_SKL_SAGV_DISABLED, | 2006 | I915_SAGV_DISABLED, |
| 1989 | I915_SKL_SAGV_ENABLED, | 2007 | I915_SAGV_ENABLED, |
| 1990 | I915_SKL_SAGV_NOT_CONTROLLED | 2008 | I915_SAGV_NOT_CONTROLLED |
| 1991 | } skl_sagv_status; | 2009 | } sagv_status; |
| 1992 | 2010 | ||
| 1993 | struct { | 2011 | struct { |
| 1994 | /* | 2012 | /* |
| @@ -2079,7 +2097,8 @@ struct drm_i915_private { | |||
| 2079 | /* perform PHY state sanity checks? */ | 2097 | /* perform PHY state sanity checks? */ |
| 2080 | bool chv_phy_assert[2]; | 2098 | bool chv_phy_assert[2]; |
| 2081 | 2099 | ||
| 2082 | struct intel_encoder *dig_port_map[I915_MAX_PORTS]; | 2100 | /* Used to save the pipe-to-encoder mapping for audio */ |
| 2101 | struct intel_encoder *av_enc_map[I915_MAX_PIPES]; | ||
| 2083 | 2102 | ||
| 2084 | /* | 2103 | /* |
| 2085 | * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch | 2104 | * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch |
| @@ -2103,19 +2122,11 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) | |||
| 2103 | } | 2122 | } |
| 2104 | 2123 | ||
| 2105 | /* Simple iterator over all initialised engines */ | 2124 | /* Simple iterator over all initialised engines */ |
| 2106 | #define for_each_engine(engine__, dev_priv__) \ | 2125 | #define for_each_engine(engine__, dev_priv__, id__) \ |
| 2107 | for ((engine__) = &(dev_priv__)->engine[0]; \ | 2126 | for ((id__) = 0; \ |
| 2108 | (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \ | 2127 | (id__) < I915_NUM_ENGINES; \ |
| 2109 | (engine__)++) \ | 2128 | (id__)++) \ |
| 2110 | for_each_if (intel_engine_initialized(engine__)) | 2129 | for_each_if ((engine__) = (dev_priv__)->engine[(id__)]) |
| 2111 | |||
| 2112 | /* Iterator with engine_id */ | ||
| 2113 | #define for_each_engine_id(engine__, dev_priv__, id__) \ | ||
| 2114 | for ((engine__) = &(dev_priv__)->engine[0], (id__) = 0; \ | ||
| 2115 | (engine__) < &(dev_priv__)->engine[I915_NUM_ENGINES]; \ | ||
| 2116 | (engine__)++) \ | ||
| 2117 | for_each_if (((id__) = (engine__)->id, \ | ||
| 2118 | intel_engine_initialized(engine__))) | ||
| 2119 | 2130 | ||
| 2120 | #define __mask_next_bit(mask) ({ \ | 2131 | #define __mask_next_bit(mask) ({ \ |
| 2121 | int __idx = ffs(mask) - 1; \ | 2132 | int __idx = ffs(mask) - 1; \ |
| @@ -2126,7 +2137,7 @@ static inline struct drm_i915_private *guc_to_i915(struct intel_guc *guc) | |||
| 2126 | /* Iterator over subset of engines selected by mask */ | 2137 | /* Iterator over subset of engines selected by mask */ |
| 2127 | #define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \ | 2138 | #define for_each_engine_masked(engine__, dev_priv__, mask__, tmp__) \ |
| 2128 | for (tmp__ = mask__ & INTEL_INFO(dev_priv__)->ring_mask; \ | 2139 | for (tmp__ = mask__ & INTEL_INFO(dev_priv__)->ring_mask; \ |
| 2129 | tmp__ ? (engine__ = &(dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; ) | 2140 | tmp__ ? (engine__ = (dev_priv__)->engine[__mask_next_bit(tmp__)]), 1 : 0; ) |
| 2130 | 2141 | ||
| 2131 | enum hdmi_force_audio { | 2142 | enum hdmi_force_audio { |
| 2132 | HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ | 2143 | HDMI_AUDIO_OFF_DVI = -2, /* no aux data for HDMI-DVI converter */ |
| @@ -2276,21 +2287,19 @@ struct drm_i915_gem_object { | |||
| 2276 | /** Record of address bit 17 of each page at last unbind. */ | 2287 | /** Record of address bit 17 of each page at last unbind. */ |
| 2277 | unsigned long *bit_17; | 2288 | unsigned long *bit_17; |
| 2278 | 2289 | ||
| 2279 | union { | 2290 | struct i915_gem_userptr { |
| 2280 | /** for phy allocated objects */ | 2291 | uintptr_t ptr; |
| 2281 | struct drm_dma_handle *phys_handle; | 2292 | unsigned read_only :1; |
| 2282 | 2293 | unsigned workers :4; | |
| 2283 | struct i915_gem_userptr { | ||
| 2284 | uintptr_t ptr; | ||
| 2285 | unsigned read_only :1; | ||
| 2286 | unsigned workers :4; | ||
| 2287 | #define I915_GEM_USERPTR_MAX_WORKERS 15 | 2294 | #define I915_GEM_USERPTR_MAX_WORKERS 15 |
| 2288 | 2295 | ||
| 2289 | struct i915_mm_struct *mm; | 2296 | struct i915_mm_struct *mm; |
| 2290 | struct i915_mmu_object *mmu_object; | 2297 | struct i915_mmu_object *mmu_object; |
| 2291 | struct work_struct *work; | 2298 | struct work_struct *work; |
| 2292 | } userptr; | 2299 | } userptr; |
| 2293 | }; | 2300 | |
| 2301 | /** for phys allocated objects */ | ||
| 2302 | struct drm_dma_handle *phys_handle; | ||
| 2294 | }; | 2303 | }; |
| 2295 | 2304 | ||
| 2296 | static inline struct drm_i915_gem_object * | 2305 | static inline struct drm_i915_gem_object * |
| @@ -2588,8 +2597,9 @@ struct drm_i915_cmd_table { | |||
| 2588 | __p; \ | 2597 | __p; \ |
| 2589 | }) | 2598 | }) |
| 2590 | #define INTEL_INFO(p) (&__I915__(p)->info) | 2599 | #define INTEL_INFO(p) (&__I915__(p)->info) |
| 2591 | #define INTEL_GEN(p) (INTEL_INFO(p)->gen) | 2600 | |
| 2592 | #define INTEL_DEVID(p) (INTEL_INFO(p)->device_id) | 2601 | #define INTEL_GEN(dev_priv) ((dev_priv)->info.gen) |
| 2602 | #define INTEL_DEVID(dev_priv) ((dev_priv)->info.device_id) | ||
| 2593 | 2603 | ||
| 2594 | #define REVID_FOREVER 0xff | 2604 | #define REVID_FOREVER 0xff |
| 2595 | #define INTEL_REVID(p) (__I915__(p)->drm.pdev->revision) | 2605 | #define INTEL_REVID(p) (__I915__(p)->drm.pdev->revision) |
| @@ -2600,7 +2610,7 @@ struct drm_i915_cmd_table { | |||
| 2600 | * | 2610 | * |
| 2601 | * Use GEN_FOREVER for unbound start and or end. | 2611 | * Use GEN_FOREVER for unbound start and or end. |
| 2602 | */ | 2612 | */ |
| 2603 | #define IS_GEN(p, s, e) ({ \ | 2613 | #define IS_GEN(dev_priv, s, e) ({ \ |
| 2604 | unsigned int __s = (s), __e = (e); \ | 2614 | unsigned int __s = (s), __e = (e); \ |
| 2605 | BUILD_BUG_ON(!__builtin_constant_p(s)); \ | 2615 | BUILD_BUG_ON(!__builtin_constant_p(s)); \ |
| 2606 | BUILD_BUG_ON(!__builtin_constant_p(e)); \ | 2616 | BUILD_BUG_ON(!__builtin_constant_p(e)); \ |
| @@ -2610,7 +2620,7 @@ struct drm_i915_cmd_table { | |||
| 2610 | __e = BITS_PER_LONG - 1; \ | 2620 | __e = BITS_PER_LONG - 1; \ |
| 2611 | else \ | 2621 | else \ |
| 2612 | __e = (e) - 1; \ | 2622 | __e = (e) - 1; \ |
| 2613 | !!(INTEL_INFO(p)->gen_mask & GENMASK((__e), (__s))); \ | 2623 | !!((dev_priv)->info.gen_mask & GENMASK((__e), (__s))); \ |
| 2614 | }) | 2624 | }) |
| 2615 | 2625 | ||
| 2616 | /* | 2626 | /* |
| @@ -2621,73 +2631,73 @@ struct drm_i915_cmd_table { | |||
| 2621 | #define IS_REVID(p, since, until) \ | 2631 | #define IS_REVID(p, since, until) \ |
| 2622 | (INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until)) | 2632 | (INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until)) |
| 2623 | 2633 | ||
| 2624 | #define IS_I830(dev) (INTEL_DEVID(dev) == 0x3577) | 2634 | #define IS_I830(dev_priv) (INTEL_DEVID(dev_priv) == 0x3577) |
| 2625 | #define IS_845G(dev) (INTEL_DEVID(dev) == 0x2562) | 2635 | #define IS_845G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2562) |
| 2626 | #define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x) | 2636 | #define IS_I85X(dev) (INTEL_INFO(dev)->is_i85x) |
| 2627 | #define IS_I865G(dev) (INTEL_DEVID(dev) == 0x2572) | 2637 | #define IS_I865G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2572) |
| 2628 | #define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g) | 2638 | #define IS_I915G(dev) (INTEL_INFO(dev)->is_i915g) |
| 2629 | #define IS_I915GM(dev) (INTEL_DEVID(dev) == 0x2592) | 2639 | #define IS_I915GM(dev_priv) (INTEL_DEVID(dev_priv) == 0x2592) |
| 2630 | #define IS_I945G(dev) (INTEL_DEVID(dev) == 0x2772) | 2640 | #define IS_I945G(dev_priv) (INTEL_DEVID(dev_priv) == 0x2772) |
| 2631 | #define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) | 2641 | #define IS_I945GM(dev) (INTEL_INFO(dev)->is_i945gm) |
| 2632 | #define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater) | 2642 | #define IS_BROADWATER(dev) (INTEL_INFO(dev)->is_broadwater) |
| 2633 | #define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) | 2643 | #define IS_CRESTLINE(dev) (INTEL_INFO(dev)->is_crestline) |
| 2634 | #define IS_GM45(dev) (INTEL_DEVID(dev) == 0x2A42) | 2644 | #define IS_GM45(dev_priv) (INTEL_DEVID(dev_priv) == 0x2A42) |
| 2635 | #define IS_G4X(dev) (INTEL_INFO(dev)->is_g4x) | 2645 | #define IS_G4X(dev_priv) ((dev_priv)->info.is_g4x) |
| 2636 | #define IS_PINEVIEW_G(dev) (INTEL_DEVID(dev) == 0xa001) | 2646 | #define IS_PINEVIEW_G(dev_priv) (INTEL_DEVID(dev_priv) == 0xa001) |
| 2637 | #define IS_PINEVIEW_M(dev) (INTEL_DEVID(dev) == 0xa011) | 2647 | #define IS_PINEVIEW_M(dev_priv) (INTEL_DEVID(dev_priv) == 0xa011) |
| 2638 | #define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview) | 2648 | #define IS_PINEVIEW(dev) (INTEL_INFO(dev)->is_pineview) |
| 2639 | #define IS_G33(dev) (INTEL_INFO(dev)->is_g33) | 2649 | #define IS_G33(dev) (INTEL_INFO(dev)->is_g33) |
| 2640 | #define IS_IRONLAKE_M(dev) (INTEL_DEVID(dev) == 0x0046) | 2650 | #define IS_IRONLAKE_M(dev_priv) (INTEL_DEVID(dev_priv) == 0x0046) |
| 2641 | #define IS_IVYBRIDGE(dev) (INTEL_INFO(dev)->is_ivybridge) | 2651 | #define IS_IVYBRIDGE(dev_priv) ((dev_priv)->info.is_ivybridge) |
| 2642 | #define IS_IVB_GT1(dev) (INTEL_DEVID(dev) == 0x0156 || \ | 2652 | #define IS_IVB_GT1(dev_priv) (INTEL_DEVID(dev_priv) == 0x0156 || \ |
| 2643 | INTEL_DEVID(dev) == 0x0152 || \ | 2653 | INTEL_DEVID(dev_priv) == 0x0152 || \ |
| 2644 | INTEL_DEVID(dev) == 0x015a) | 2654 | INTEL_DEVID(dev_priv) == 0x015a) |
| 2645 | #define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview) | 2655 | #define IS_VALLEYVIEW(dev_priv) ((dev_priv)->info.is_valleyview) |
| 2646 | #define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_cherryview) | 2656 | #define IS_CHERRYVIEW(dev_priv) ((dev_priv)->info.is_cherryview) |
| 2647 | #define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell) | 2657 | #define IS_HASWELL(dev_priv) ((dev_priv)->info.is_haswell) |
| 2648 | #define IS_BROADWELL(dev) (INTEL_INFO(dev)->is_broadwell) | 2658 | #define IS_BROADWELL(dev_priv) ((dev_priv)->info.is_broadwell) |
| 2649 | #define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake) | 2659 | #define IS_SKYLAKE(dev_priv) ((dev_priv)->info.is_skylake) |
| 2650 | #define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton) | 2660 | #define IS_BROXTON(dev_priv) ((dev_priv)->info.is_broxton) |
| 2651 | #define IS_KABYLAKE(dev) (INTEL_INFO(dev)->is_kabylake) | 2661 | #define IS_KABYLAKE(dev_priv) ((dev_priv)->info.is_kabylake) |
| 2652 | #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) | 2662 | #define IS_MOBILE(dev) (INTEL_INFO(dev)->is_mobile) |
| 2653 | #define IS_HSW_EARLY_SDV(dev) (IS_HASWELL(dev) && \ | 2663 | #define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \ |
| 2654 | (INTEL_DEVID(dev) & 0xFF00) == 0x0C00) | 2664 | (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00) |
| 2655 | #define IS_BDW_ULT(dev) (IS_BROADWELL(dev) && \ | 2665 | #define IS_BDW_ULT(dev_priv) (IS_BROADWELL(dev_priv) && \ |
| 2656 | ((INTEL_DEVID(dev) & 0xf) == 0x6 || \ | 2666 | ((INTEL_DEVID(dev_priv) & 0xf) == 0x6 || \ |
| 2657 | (INTEL_DEVID(dev) & 0xf) == 0xb || \ | 2667 | (INTEL_DEVID(dev_priv) & 0xf) == 0xb || \ |
| 2658 | (INTEL_DEVID(dev) & 0xf) == 0xe)) | 2668 | (INTEL_DEVID(dev_priv) & 0xf) == 0xe)) |
| 2659 | /* ULX machines are also considered ULT. */ | 2669 | /* ULX machines are also considered ULT. */ |
| 2660 | #define IS_BDW_ULX(dev) (IS_BROADWELL(dev) && \ | 2670 | #define IS_BDW_ULX(dev_priv) (IS_BROADWELL(dev_priv) && \ |
| 2661 | (INTEL_DEVID(dev) & 0xf) == 0xe) | 2671 | (INTEL_DEVID(dev_priv) & 0xf) == 0xe) |
| 2662 | #define IS_BDW_GT3(dev) (IS_BROADWELL(dev) && \ | 2672 | #define IS_BDW_GT3(dev_priv) (IS_BROADWELL(dev_priv) && \ |
| 2663 | (INTEL_DEVID(dev) & 0x00F0) == 0x0020) | 2673 | (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020) |
| 2664 | #define IS_HSW_ULT(dev) (IS_HASWELL(dev) && \ | 2674 | #define IS_HSW_ULT(dev_priv) (IS_HASWELL(dev_priv) && \ |
| 2665 | (INTEL_DEVID(dev) & 0xFF00) == 0x0A00) | 2675 | (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0A00) |
| 2666 | #define IS_HSW_GT3(dev) (IS_HASWELL(dev) && \ | 2676 | #define IS_HSW_GT3(dev_priv) (IS_HASWELL(dev_priv) && \ |
| 2667 | (INTEL_DEVID(dev) & 0x00F0) == 0x0020) | 2677 | (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020) |
| 2668 | /* ULX machines are also considered ULT. */ | 2678 | /* ULX machines are also considered ULT. */ |
| 2669 | #define IS_HSW_ULX(dev) (INTEL_DEVID(dev) == 0x0A0E || \ | 2679 | #define IS_HSW_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x0A0E || \ |
| 2670 | INTEL_DEVID(dev) == 0x0A1E) | 2680 | INTEL_DEVID(dev_priv) == 0x0A1E) |
| 2671 | #define IS_SKL_ULT(dev) (INTEL_DEVID(dev) == 0x1906 || \ | 2681 | #define IS_SKL_ULT(dev_priv) (INTEL_DEVID(dev_priv) == 0x1906 || \ |
| 2672 | INTEL_DEVID(dev) == 0x1913 || \ | 2682 | INTEL_DEVID(dev_priv) == 0x1913 || \ |
| 2673 | INTEL_DEVID(dev) == 0x1916 || \ | 2683 | INTEL_DEVID(dev_priv) == 0x1916 || \ |
| 2674 | INTEL_DEVID(dev) == 0x1921 || \ | 2684 | INTEL_DEVID(dev_priv) == 0x1921 || \ |
| 2675 | INTEL_DEVID(dev) == 0x1926) | 2685 | INTEL_DEVID(dev_priv) == 0x1926) |
| 2676 | #define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \ | 2686 | #define IS_SKL_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x190E || \ |
| 2677 | INTEL_DEVID(dev) == 0x1915 || \ | 2687 | INTEL_DEVID(dev_priv) == 0x1915 || \ |
| 2678 | INTEL_DEVID(dev) == 0x191E) | 2688 | INTEL_DEVID(dev_priv) == 0x191E) |
| 2679 | #define IS_KBL_ULT(dev) (INTEL_DEVID(dev) == 0x5906 || \ | 2689 | #define IS_KBL_ULT(dev_priv) (INTEL_DEVID(dev_priv) == 0x5906 || \ |
| 2680 | INTEL_DEVID(dev) == 0x5913 || \ | 2690 | INTEL_DEVID(dev_priv) == 0x5913 || \ |
| 2681 | INTEL_DEVID(dev) == 0x5916 || \ | 2691 | INTEL_DEVID(dev_priv) == 0x5916 || \ |
| 2682 | INTEL_DEVID(dev) == 0x5921 || \ | 2692 | INTEL_DEVID(dev_priv) == 0x5921 || \ |
| 2683 | INTEL_DEVID(dev) == 0x5926) | 2693 | INTEL_DEVID(dev_priv) == 0x5926) |
| 2684 | #define IS_KBL_ULX(dev) (INTEL_DEVID(dev) == 0x590E || \ | 2694 | #define IS_KBL_ULX(dev_priv) (INTEL_DEVID(dev_priv) == 0x590E || \ |
| 2685 | INTEL_DEVID(dev) == 0x5915 || \ | 2695 | INTEL_DEVID(dev_priv) == 0x5915 || \ |
| 2686 | INTEL_DEVID(dev) == 0x591E) | 2696 | INTEL_DEVID(dev_priv) == 0x591E) |
| 2687 | #define IS_SKL_GT3(dev) (IS_SKYLAKE(dev) && \ | 2697 | #define IS_SKL_GT3(dev_priv) (IS_SKYLAKE(dev_priv) && \ |
| 2688 | (INTEL_DEVID(dev) & 0x00F0) == 0x0020) | 2698 | (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0020) |
| 2689 | #define IS_SKL_GT4(dev) (IS_SKYLAKE(dev) && \ | 2699 | #define IS_SKL_GT4(dev_priv) (IS_SKYLAKE(dev_priv) && \ |
| 2690 | (INTEL_DEVID(dev) & 0x00F0) == 0x0030) | 2700 | (INTEL_DEVID(dev_priv) & 0x00F0) == 0x0030) |
| 2691 | 2701 | ||
| 2692 | #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) | 2702 | #define IS_PRELIMINARY_HW(intel_info) ((intel_info)->is_preliminary) |
| 2693 | 2703 | ||
| @@ -2707,7 +2717,8 @@ struct drm_i915_cmd_table { | |||
| 2707 | #define BXT_REVID_B0 0x3 | 2717 | #define BXT_REVID_B0 0x3 |
| 2708 | #define BXT_REVID_C0 0x9 | 2718 | #define BXT_REVID_C0 0x9 |
| 2709 | 2719 | ||
| 2710 | #define IS_BXT_REVID(p, since, until) (IS_BROXTON(p) && IS_REVID(p, since, until)) | 2720 | #define IS_BXT_REVID(dev_priv, since, until) \ |
| 2721 | (IS_BROXTON(dev_priv) && IS_REVID(dev_priv, since, until)) | ||
| 2711 | 2722 | ||
| 2712 | #define KBL_REVID_A0 0x0 | 2723 | #define KBL_REVID_A0 0x0 |
| 2713 | #define KBL_REVID_B0 0x1 | 2724 | #define KBL_REVID_B0 0x1 |
| @@ -2715,8 +2726,8 @@ struct drm_i915_cmd_table { | |||
| 2715 | #define KBL_REVID_D0 0x3 | 2726 | #define KBL_REVID_D0 0x3 |
| 2716 | #define KBL_REVID_E0 0x4 | 2727 | #define KBL_REVID_E0 0x4 |
| 2717 | 2728 | ||
| 2718 | #define IS_KBL_REVID(p, since, until) \ | 2729 | #define IS_KBL_REVID(dev_priv, since, until) \ |
| 2719 | (IS_KABYLAKE(p) && IS_REVID(p, since, until)) | 2730 | (IS_KABYLAKE(dev_priv) && IS_REVID(dev_priv, since, until)) |
| 2720 | 2731 | ||
| 2721 | /* | 2732 | /* |
| 2722 | * The genX designation typically refers to the render engine, so render | 2733 | * The genX designation typically refers to the render engine, so render |
| @@ -2724,14 +2735,14 @@ struct drm_i915_cmd_table { | |||
| 2724 | * have their own (e.g. HAS_PCH_SPLIT for ILK+ display, IS_foo for particular | 2735 | * have their own (e.g. HAS_PCH_SPLIT for ILK+ display, IS_foo for particular |
| 2725 | * chips, etc.). | 2736 | * chips, etc.). |
| 2726 | */ | 2737 | */ |
| 2727 | #define IS_GEN2(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(1))) | 2738 | #define IS_GEN2(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(1))) |
| 2728 | #define IS_GEN3(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(2))) | 2739 | #define IS_GEN3(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(2))) |
| 2729 | #define IS_GEN4(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(3))) | 2740 | #define IS_GEN4(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(3))) |
| 2730 | #define IS_GEN5(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(4))) | 2741 | #define IS_GEN5(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(4))) |
| 2731 | #define IS_GEN6(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(5))) | 2742 | #define IS_GEN6(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(5))) |
| 2732 | #define IS_GEN7(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(6))) | 2743 | #define IS_GEN7(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(6))) |
| 2733 | #define IS_GEN8(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(7))) | 2744 | #define IS_GEN8(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(7))) |
| 2734 | #define IS_GEN9(dev) (!!(INTEL_INFO(dev)->gen_mask & BIT(8))) | 2745 | #define IS_GEN9(dev_priv) (!!((dev_priv)->info.gen_mask & BIT(8))) |
| 2735 | 2746 | ||
| 2736 | #define ENGINE_MASK(id) BIT(id) | 2747 | #define ENGINE_MASK(id) BIT(id) |
| 2737 | #define RENDER_RING ENGINE_MASK(RCS) | 2748 | #define RENDER_RING ENGINE_MASK(RCS) |
| @@ -2752,8 +2763,8 @@ struct drm_i915_cmd_table { | |||
| 2752 | #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) | 2763 | #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) |
| 2753 | #define HAS_SNOOP(dev) (INTEL_INFO(dev)->has_snoop) | 2764 | #define HAS_SNOOP(dev) (INTEL_INFO(dev)->has_snoop) |
| 2754 | #define HAS_EDRAM(dev) (!!(__I915__(dev)->edram_cap & EDRAM_ENABLED)) | 2765 | #define HAS_EDRAM(dev) (!!(__I915__(dev)->edram_cap & EDRAM_ENABLED)) |
| 2755 | #define HAS_WT(dev) ((IS_HASWELL(dev) || IS_BROADWELL(dev)) && \ | 2766 | #define HAS_WT(dev_priv) ((IS_HASWELL(dev_priv) || \ |
| 2756 | HAS_EDRAM(dev)) | 2767 | IS_BROADWELL(dev_priv)) && HAS_EDRAM(dev_priv)) |
| 2757 | #define HWS_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->hws_needs_physical) | 2768 | #define HWS_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->hws_needs_physical) |
| 2758 | 2769 | ||
| 2759 | #define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->has_hw_contexts) | 2770 | #define HAS_HW_CONTEXTS(dev) (INTEL_INFO(dev)->has_hw_contexts) |
| @@ -2766,7 +2777,7 @@ struct drm_i915_cmd_table { | |||
| 2766 | #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) | 2777 | #define OVERLAY_NEEDS_PHYSICAL(dev) (INTEL_INFO(dev)->overlay_needs_physical) |
| 2767 | 2778 | ||
| 2768 | /* Early gen2 have a totally busted CS tlb and require pinned batches. */ | 2779 | /* Early gen2 have a totally busted CS tlb and require pinned batches. */ |
| 2769 | #define HAS_BROKEN_CS_TLB(dev) (IS_I830(dev) || IS_845G(dev)) | 2780 | #define HAS_BROKEN_CS_TLB(dev_priv) (IS_I830(dev_priv) || IS_845G(dev_priv)) |
| 2770 | 2781 | ||
| 2771 | /* WaRsDisableCoarsePowerGating:skl,bxt */ | 2782 | /* WaRsDisableCoarsePowerGating:skl,bxt */ |
| 2772 | #define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \ | 2783 | #define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \ |
| @@ -2786,8 +2797,9 @@ struct drm_i915_cmd_table { | |||
| 2786 | /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte | 2797 | /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte |
| 2787 | * rows, which changed the alignment requirements and fence programming. | 2798 | * rows, which changed the alignment requirements and fence programming. |
| 2788 | */ | 2799 | */ |
| 2789 | #define HAS_128_BYTE_Y_TILING(dev) (!IS_GEN2(dev) && !(IS_I915G(dev) || \ | 2800 | #define HAS_128_BYTE_Y_TILING(dev_priv) (!IS_GEN2(dev_priv) && \ |
| 2790 | IS_I915GM(dev))) | 2801 | !(IS_I915G(dev_priv) || \ |
| 2802 | IS_I915GM(dev_priv))) | ||
| 2791 | #define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv) | 2803 | #define SUPPORTS_TV(dev) (INTEL_INFO(dev)->supports_tv) |
| 2792 | #define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) | 2804 | #define I915_HAS_HOTPLUG(dev) (INTEL_INFO(dev)->has_hotplug) |
| 2793 | 2805 | ||
| @@ -2795,19 +2807,19 @@ struct drm_i915_cmd_table { | |||
| 2795 | #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) | 2807 | #define HAS_PIPE_CXSR(dev) (INTEL_INFO(dev)->has_pipe_cxsr) |
| 2796 | #define HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) | 2808 | #define HAS_FBC(dev) (INTEL_INFO(dev)->has_fbc) |
| 2797 | 2809 | ||
| 2798 | #define HAS_IPS(dev) (IS_HSW_ULT(dev) || IS_BROADWELL(dev)) | 2810 | #define HAS_IPS(dev_priv) (IS_HSW_ULT(dev_priv) || IS_BROADWELL(dev_priv)) |
| 2799 | 2811 | ||
| 2800 | #define HAS_DP_MST(dev) (INTEL_INFO(dev)->has_dp_mst) | 2812 | #define HAS_DP_MST(dev) (INTEL_INFO(dev)->has_dp_mst) |
| 2801 | 2813 | ||
| 2802 | #define HAS_DDI(dev) (INTEL_INFO(dev)->has_ddi) | 2814 | #define HAS_DDI(dev_priv) ((dev_priv)->info.has_ddi) |
| 2803 | #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) | 2815 | #define HAS_FPGA_DBG_UNCLAIMED(dev) (INTEL_INFO(dev)->has_fpga_dbg) |
| 2804 | #define HAS_PSR(dev) (INTEL_INFO(dev)->has_psr) | 2816 | #define HAS_PSR(dev) (INTEL_INFO(dev)->has_psr) |
| 2805 | #define HAS_RUNTIME_PM(dev) (INTEL_INFO(dev)->has_runtime_pm) | ||
| 2806 | #define HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) | 2817 | #define HAS_RC6(dev) (INTEL_INFO(dev)->has_rc6) |
| 2807 | #define HAS_RC6p(dev) (INTEL_INFO(dev)->has_rc6p) | 2818 | #define HAS_RC6p(dev) (INTEL_INFO(dev)->has_rc6p) |
| 2808 | 2819 | ||
| 2809 | #define HAS_CSR(dev) (INTEL_INFO(dev)->has_csr) | 2820 | #define HAS_CSR(dev) (INTEL_INFO(dev)->has_csr) |
| 2810 | 2821 | ||
| 2822 | #define HAS_RUNTIME_PM(dev_priv) ((dev_priv)->info.has_runtime_pm) | ||
| 2811 | /* | 2823 | /* |
| 2812 | * For now, anything with a GuC requires uCode loading, and then supports | 2824 | * For now, anything with a GuC requires uCode loading, and then supports |
| 2813 | * command submission once loaded. But these are logically independent | 2825 | * command submission once loaded. But these are logically independent |
| @@ -2834,22 +2846,27 @@ struct drm_i915_cmd_table { | |||
| 2834 | #define INTEL_PCH_P3X_DEVICE_ID_TYPE 0x7000 | 2846 | #define INTEL_PCH_P3X_DEVICE_ID_TYPE 0x7000 |
| 2835 | #define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */ | 2847 | #define INTEL_PCH_QEMU_DEVICE_ID_TYPE 0x2900 /* qemu q35 has 2918 */ |
| 2836 | 2848 | ||
| 2837 | #define INTEL_PCH_TYPE(dev) (__I915__(dev)->pch_type) | 2849 | #define INTEL_PCH_TYPE(dev_priv) ((dev_priv)->pch_type) |
| 2838 | #define HAS_PCH_KBP(dev) (INTEL_PCH_TYPE(dev) == PCH_KBP) | 2850 | #define HAS_PCH_KBP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_KBP) |
| 2839 | #define HAS_PCH_SPT(dev) (INTEL_PCH_TYPE(dev) == PCH_SPT) | 2851 | #define HAS_PCH_SPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_SPT) |
| 2840 | #define HAS_PCH_LPT(dev) (INTEL_PCH_TYPE(dev) == PCH_LPT) | 2852 | #define HAS_PCH_LPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_LPT) |
| 2841 | #define HAS_PCH_LPT_LP(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) | 2853 | #define HAS_PCH_LPT_LP(dev_priv) \ |
| 2842 | #define HAS_PCH_LPT_H(dev) (__I915__(dev)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) | 2854 | ((dev_priv)->pch_id == INTEL_PCH_LPT_LP_DEVICE_ID_TYPE) |
| 2843 | #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) | 2855 | #define HAS_PCH_LPT_H(dev_priv) \ |
| 2844 | #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) | 2856 | ((dev_priv)->pch_id == INTEL_PCH_LPT_DEVICE_ID_TYPE) |
| 2845 | #define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP) | 2857 | #define HAS_PCH_CPT(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_CPT) |
| 2846 | #define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE) | 2858 | #define HAS_PCH_IBX(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_IBX) |
| 2859 | #define HAS_PCH_NOP(dev_priv) (INTEL_PCH_TYPE(dev_priv) == PCH_NOP) | ||
| 2860 | #define HAS_PCH_SPLIT(dev_priv) (INTEL_PCH_TYPE(dev_priv) != PCH_NONE) | ||
| 2861 | |||
| 2862 | #define HAS_GMCH_DISPLAY(dev_priv) ((dev_priv)->info.has_gmch_display) | ||
| 2847 | 2863 | ||
| 2848 | #define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->has_gmch_display) | 2864 | #define HAS_LSPCON(dev_priv) (IS_GEN9(dev_priv)) |
| 2849 | 2865 | ||
| 2850 | /* DPF == dynamic parity feature */ | 2866 | /* DPF == dynamic parity feature */ |
| 2851 | #define HAS_L3_DPF(dev) (INTEL_INFO(dev)->has_l3_dpf) | 2867 | #define HAS_L3_DPF(dev_priv) ((dev_priv)->info.has_l3_dpf) |
| 2852 | #define NUM_L3_SLICES(dev) (IS_HSW_GT3(dev) ? 2 : HAS_L3_DPF(dev)) | 2868 | #define NUM_L3_SLICES(dev_priv) (IS_HSW_GT3(dev_priv) ? \ |
| 2869 | 2 : HAS_L3_DPF(dev_priv)) | ||
| 2853 | 2870 | ||
| 2854 | #define GT_FREQUENCY_MULTIPLIER 50 | 2871 | #define GT_FREQUENCY_MULTIPLIER 50 |
| 2855 | #define GEN9_FREQ_SCALER 3 | 2872 | #define GEN9_FREQ_SCALER 3 |
| @@ -2885,6 +2902,11 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level, | |||
| 2885 | extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, | 2902 | extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, |
| 2886 | unsigned long arg); | 2903 | unsigned long arg); |
| 2887 | #endif | 2904 | #endif |
| 2905 | extern const struct dev_pm_ops i915_pm_ops; | ||
| 2906 | |||
| 2907 | extern int i915_driver_load(struct pci_dev *pdev, | ||
| 2908 | const struct pci_device_id *ent); | ||
| 2909 | extern void i915_driver_unload(struct drm_device *dev); | ||
| 2888 | extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask); | 2910 | extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask); |
| 2889 | extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv); | 2911 | extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv); |
| 2890 | extern void i915_reset(struct drm_i915_private *dev_priv); | 2912 | extern void i915_reset(struct drm_i915_private *dev_priv); |
| @@ -2971,7 +2993,7 @@ int intel_wait_for_register_fw(struct drm_i915_private *dev_priv, | |||
| 2971 | 2993 | ||
| 2972 | static inline bool intel_gvt_active(struct drm_i915_private *dev_priv) | 2994 | static inline bool intel_gvt_active(struct drm_i915_private *dev_priv) |
| 2973 | { | 2995 | { |
| 2974 | return dev_priv->gvt.initialized; | 2996 | return dev_priv->gvt; |
| 2975 | } | 2997 | } |
| 2976 | 2998 | ||
| 2977 | static inline bool intel_vgpu_active(struct drm_i915_private *dev_priv) | 2999 | static inline bool intel_vgpu_active(struct drm_i915_private *dev_priv) |
| @@ -3076,6 +3098,7 @@ int i915_gem_wait_ioctl(struct drm_device *dev, void *data, | |||
| 3076 | void i915_gem_load_init(struct drm_device *dev); | 3098 | void i915_gem_load_init(struct drm_device *dev); |
| 3077 | void i915_gem_load_cleanup(struct drm_device *dev); | 3099 | void i915_gem_load_cleanup(struct drm_device *dev); |
| 3078 | void i915_gem_load_init_fences(struct drm_i915_private *dev_priv); | 3100 | void i915_gem_load_init_fences(struct drm_i915_private *dev_priv); |
| 3101 | int i915_gem_freeze(struct drm_i915_private *dev_priv); | ||
| 3079 | int i915_gem_freeze_late(struct drm_i915_private *dev_priv); | 3102 | int i915_gem_freeze_late(struct drm_i915_private *dev_priv); |
| 3080 | 3103 | ||
| 3081 | void *i915_gem_object_alloc(struct drm_device *dev); | 3104 | void *i915_gem_object_alloc(struct drm_device *dev); |
| @@ -3083,7 +3106,7 @@ void i915_gem_object_free(struct drm_i915_gem_object *obj); | |||
| 3083 | void i915_gem_object_init(struct drm_i915_gem_object *obj, | 3106 | void i915_gem_object_init(struct drm_i915_gem_object *obj, |
| 3084 | const struct drm_i915_gem_object_ops *ops); | 3107 | const struct drm_i915_gem_object_ops *ops); |
| 3085 | struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev, | 3108 | struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev, |
| 3086 | size_t size); | 3109 | u64 size); |
| 3087 | struct drm_i915_gem_object *i915_gem_object_create_from_data( | 3110 | struct drm_i915_gem_object *i915_gem_object_create_from_data( |
| 3088 | struct drm_device *dev, const void *data, size_t size); | 3111 | struct drm_device *dev, const void *data, size_t size); |
| 3089 | void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file); | 3112 | void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file); |
| @@ -3157,14 +3180,15 @@ i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n) | |||
| 3157 | 3180 | ||
| 3158 | static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) | 3181 | static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) |
| 3159 | { | 3182 | { |
| 3160 | BUG_ON(obj->pages == NULL); | 3183 | GEM_BUG_ON(obj->pages == NULL); |
| 3161 | obj->pages_pin_count++; | 3184 | obj->pages_pin_count++; |
| 3162 | } | 3185 | } |
| 3163 | 3186 | ||
| 3164 | static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) | 3187 | static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) |
| 3165 | { | 3188 | { |
| 3166 | BUG_ON(obj->pages_pin_count == 0); | 3189 | GEM_BUG_ON(obj->pages_pin_count == 0); |
| 3167 | obj->pages_pin_count--; | 3190 | obj->pages_pin_count--; |
| 3191 | GEM_BUG_ON(obj->pages_pin_count < obj->bind_count); | ||
| 3168 | } | 3192 | } |
| 3169 | 3193 | ||
| 3170 | enum i915_map_type { | 3194 | enum i915_map_type { |
| @@ -3522,6 +3546,8 @@ static inline void intel_display_crc_init(struct drm_i915_private *dev_priv) {} | |||
| 3522 | #endif | 3546 | #endif |
| 3523 | 3547 | ||
| 3524 | /* i915_gpu_error.c */ | 3548 | /* i915_gpu_error.c */ |
| 3549 | #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) | ||
| 3550 | |||
| 3525 | __printf(2, 3) | 3551 | __printf(2, 3) |
| 3526 | void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...); | 3552 | void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...); |
| 3527 | int i915_error_state_to_str(struct drm_i915_error_state_buf *estr, | 3553 | int i915_error_state_to_str(struct drm_i915_error_state_buf *estr, |
| @@ -3542,7 +3568,20 @@ void i915_error_state_get(struct drm_device *dev, | |||
| 3542 | void i915_error_state_put(struct i915_error_state_file_priv *error_priv); | 3568 | void i915_error_state_put(struct i915_error_state_file_priv *error_priv); |
| 3543 | void i915_destroy_error_state(struct drm_device *dev); | 3569 | void i915_destroy_error_state(struct drm_device *dev); |
| 3544 | 3570 | ||
| 3545 | void i915_get_extra_instdone(struct drm_i915_private *dev_priv, uint32_t *instdone); | 3571 | #else |
| 3572 | |||
| 3573 | static inline void i915_capture_error_state(struct drm_i915_private *dev_priv, | ||
| 3574 | u32 engine_mask, | ||
| 3575 | const char *error_msg) | ||
| 3576 | { | ||
| 3577 | } | ||
| 3578 | |||
| 3579 | static inline void i915_destroy_error_state(struct drm_device *dev) | ||
| 3580 | { | ||
| 3581 | } | ||
| 3582 | |||
| 3583 | #endif | ||
| 3584 | |||
| 3546 | const char *i915_cache_level_str(struct drm_i915_private *i915, int type); | 3585 | const char *i915_cache_level_str(struct drm_i915_private *i915, int type); |
| 3547 | 3586 | ||
| 3548 | /* i915_cmd_parser.c */ | 3587 | /* i915_cmd_parser.c */ |
| @@ -3592,6 +3631,9 @@ bool intel_bios_is_port_dp_dual_mode(struct drm_i915_private *dev_priv, enum por | |||
| 3592 | bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port); | 3631 | bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port); |
| 3593 | bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv, | 3632 | bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv, |
| 3594 | enum port port); | 3633 | enum port port); |
| 3634 | bool intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv, | ||
| 3635 | enum port port); | ||
| 3636 | |||
| 3595 | 3637 | ||
| 3596 | /* intel_opregion.c */ | 3638 | /* intel_opregion.c */ |
| 3597 | #ifdef CONFIG_ACPI | 3639 | #ifdef CONFIG_ACPI |
| @@ -3808,11 +3850,11 @@ __raw_write(64, q) | |||
| 3808 | #define INTEL_BROADCAST_RGB_FULL 1 | 3850 | #define INTEL_BROADCAST_RGB_FULL 1 |
| 3809 | #define INTEL_BROADCAST_RGB_LIMITED 2 | 3851 | #define INTEL_BROADCAST_RGB_LIMITED 2 |
| 3810 | 3852 | ||
| 3811 | static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev) | 3853 | static inline i915_reg_t i915_vgacntrl_reg(struct drm_i915_private *dev_priv) |
| 3812 | { | 3854 | { |
| 3813 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 3855 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 3814 | return VLV_VGACNTRL; | 3856 | return VLV_VGACNTRL; |
| 3815 | else if (INTEL_INFO(dev)->gen >= 5) | 3857 | else if (INTEL_GEN(dev_priv) >= 5) |
| 3816 | return CPU_VGACNTRL; | 3858 | return CPU_VGACNTRL; |
| 3817 | else | 3859 | else |
| 3818 | return VGACNTRL; | 3860 | return VGACNTRL; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2c8106758922..8ed8e24025ac 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -82,7 +82,7 @@ remove_mappable_node(struct drm_mm_node *node) | |||
| 82 | 82 | ||
| 83 | /* some bookkeeping */ | 83 | /* some bookkeeping */ |
| 84 | static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv, | 84 | static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv, |
| 85 | size_t size) | 85 | u64 size) |
| 86 | { | 86 | { |
| 87 | spin_lock(&dev_priv->mm.object_stat_lock); | 87 | spin_lock(&dev_priv->mm.object_stat_lock); |
| 88 | dev_priv->mm.object_count++; | 88 | dev_priv->mm.object_count++; |
| @@ -91,7 +91,7 @@ static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv, | |||
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv, | 93 | static void i915_gem_info_remove_obj(struct drm_i915_private *dev_priv, |
| 94 | size_t size) | 94 | u64 size) |
| 95 | { | 95 | { |
| 96 | spin_lock(&dev_priv->mm.object_stat_lock); | 96 | spin_lock(&dev_priv->mm.object_stat_lock); |
| 97 | dev_priv->mm.object_count--; | 97 | dev_priv->mm.object_count--; |
| @@ -860,7 +860,7 @@ i915_gem_gtt_pread(struct drm_device *dev, | |||
| 860 | 860 | ||
| 861 | mutex_unlock(&dev->struct_mutex); | 861 | mutex_unlock(&dev->struct_mutex); |
| 862 | if (likely(!i915.prefault_disable)) { | 862 | if (likely(!i915.prefault_disable)) { |
| 863 | ret = fault_in_multipages_writeable(user_data, remain); | 863 | ret = fault_in_pages_writeable(user_data, remain); |
| 864 | if (ret) { | 864 | if (ret) { |
| 865 | mutex_lock(&dev->struct_mutex); | 865 | mutex_lock(&dev->struct_mutex); |
| 866 | goto out_unpin; | 866 | goto out_unpin; |
| @@ -919,8 +919,7 @@ out_unpin: | |||
| 919 | if (node.allocated) { | 919 | if (node.allocated) { |
| 920 | wmb(); | 920 | wmb(); |
| 921 | ggtt->base.clear_range(&ggtt->base, | 921 | ggtt->base.clear_range(&ggtt->base, |
| 922 | node.start, node.size, | 922 | node.start, node.size); |
| 923 | true); | ||
| 924 | i915_gem_object_unpin_pages(obj); | 923 | i915_gem_object_unpin_pages(obj); |
| 925 | remove_mappable_node(&node); | 924 | remove_mappable_node(&node); |
| 926 | } else { | 925 | } else { |
| @@ -983,7 +982,7 @@ i915_gem_shmem_pread(struct drm_device *dev, | |||
| 983 | mutex_unlock(&dev->struct_mutex); | 982 | mutex_unlock(&dev->struct_mutex); |
| 984 | 983 | ||
| 985 | if (likely(!i915.prefault_disable) && !prefaulted) { | 984 | if (likely(!i915.prefault_disable) && !prefaulted) { |
| 986 | ret = fault_in_multipages_writeable(user_data, remain); | 985 | ret = fault_in_pages_writeable(user_data, remain); |
| 987 | /* Userspace is tricking us, but we've already clobbered | 986 | /* Userspace is tricking us, but we've already clobbered |
| 988 | * its pages with the prefault and promised to write the | 987 | * its pages with the prefault and promised to write the |
| 989 | * data up to the first fault. Hence ignore any errors | 988 | * data up to the first fault. Hence ignore any errors |
| @@ -1228,8 +1227,7 @@ out_unpin: | |||
| 1228 | if (node.allocated) { | 1227 | if (node.allocated) { |
| 1229 | wmb(); | 1228 | wmb(); |
| 1230 | ggtt->base.clear_range(&ggtt->base, | 1229 | ggtt->base.clear_range(&ggtt->base, |
| 1231 | node.start, node.size, | 1230 | node.start, node.size); |
| 1232 | true); | ||
| 1233 | i915_gem_object_unpin_pages(obj); | 1231 | i915_gem_object_unpin_pages(obj); |
| 1234 | remove_mappable_node(&node); | 1232 | remove_mappable_node(&node); |
| 1235 | } else { | 1233 | } else { |
| @@ -1431,7 +1429,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, | |||
| 1431 | return -EFAULT; | 1429 | return -EFAULT; |
| 1432 | 1430 | ||
| 1433 | if (likely(!i915.prefault_disable)) { | 1431 | if (likely(!i915.prefault_disable)) { |
| 1434 | ret = fault_in_multipages_readable(u64_to_user_ptr(args->data_ptr), | 1432 | ret = fault_in_pages_readable(u64_to_user_ptr(args->data_ptr), |
| 1435 | args->size); | 1433 | args->size); |
| 1436 | if (ret) | 1434 | if (ret) |
| 1437 | return -EFAULT; | 1435 | return -EFAULT; |
| @@ -1813,8 +1811,7 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf) | |||
| 1813 | view.params.partial.offset = rounddown(page_offset, chunk_size); | 1811 | view.params.partial.offset = rounddown(page_offset, chunk_size); |
| 1814 | view.params.partial.size = | 1812 | view.params.partial.size = |
| 1815 | min_t(unsigned int, chunk_size, | 1813 | min_t(unsigned int, chunk_size, |
| 1816 | (area->vm_end - area->vm_start) / PAGE_SIZE - | 1814 | vma_pages(area) - view.params.partial.offset); |
| 1817 | view.params.partial.offset); | ||
| 1818 | 1815 | ||
| 1819 | /* If the partial covers the entire object, just create a | 1816 | /* If the partial covers the entire object, just create a |
| 1820 | * normal VMA. | 1817 | * normal VMA. |
| @@ -2208,6 +2205,15 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) | |||
| 2208 | return 0; | 2205 | return 0; |
| 2209 | } | 2206 | } |
| 2210 | 2207 | ||
| 2208 | static unsigned int swiotlb_max_size(void) | ||
| 2209 | { | ||
| 2210 | #if IS_ENABLED(CONFIG_SWIOTLB) | ||
| 2211 | return rounddown(swiotlb_nr_tbl() << IO_TLB_SHIFT, PAGE_SIZE); | ||
| 2212 | #else | ||
| 2213 | return 0; | ||
| 2214 | #endif | ||
| 2215 | } | ||
| 2216 | |||
| 2211 | static int | 2217 | static int |
| 2212 | i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) | 2218 | i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) |
| 2213 | { | 2219 | { |
| @@ -2219,6 +2225,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) | |||
| 2219 | struct sgt_iter sgt_iter; | 2225 | struct sgt_iter sgt_iter; |
| 2220 | struct page *page; | 2226 | struct page *page; |
| 2221 | unsigned long last_pfn = 0; /* suppress gcc warning */ | 2227 | unsigned long last_pfn = 0; /* suppress gcc warning */ |
| 2228 | unsigned int max_segment; | ||
| 2222 | int ret; | 2229 | int ret; |
| 2223 | gfp_t gfp; | 2230 | gfp_t gfp; |
| 2224 | 2231 | ||
| @@ -2229,6 +2236,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) | |||
| 2229 | BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); | 2236 | BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); |
| 2230 | BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); | 2237 | BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); |
| 2231 | 2238 | ||
| 2239 | max_segment = swiotlb_max_size(); | ||
| 2240 | if (!max_segment) | ||
| 2241 | max_segment = rounddown(UINT_MAX, PAGE_SIZE); | ||
| 2242 | |||
| 2232 | st = kmalloc(sizeof(*st), GFP_KERNEL); | 2243 | st = kmalloc(sizeof(*st), GFP_KERNEL); |
| 2233 | if (st == NULL) | 2244 | if (st == NULL) |
| 2234 | return -ENOMEM; | 2245 | return -ENOMEM; |
| @@ -2264,22 +2275,15 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) | |||
| 2264 | * our own buffer, now let the real VM do its job and | 2275 | * our own buffer, now let the real VM do its job and |
| 2265 | * go down in flames if truly OOM. | 2276 | * go down in flames if truly OOM. |
| 2266 | */ | 2277 | */ |
| 2267 | i915_gem_shrink_all(dev_priv); | ||
| 2268 | page = shmem_read_mapping_page(mapping, i); | 2278 | page = shmem_read_mapping_page(mapping, i); |
| 2269 | if (IS_ERR(page)) { | 2279 | if (IS_ERR(page)) { |
| 2270 | ret = PTR_ERR(page); | 2280 | ret = PTR_ERR(page); |
| 2271 | goto err_pages; | 2281 | goto err_pages; |
| 2272 | } | 2282 | } |
| 2273 | } | 2283 | } |
| 2274 | #ifdef CONFIG_SWIOTLB | 2284 | if (!i || |
| 2275 | if (swiotlb_nr_tbl()) { | 2285 | sg->length >= max_segment || |
| 2276 | st->nents++; | 2286 | page_to_pfn(page) != last_pfn + 1) { |
| 2277 | sg_set_page(sg, page, PAGE_SIZE, 0); | ||
| 2278 | sg = sg_next(sg); | ||
| 2279 | continue; | ||
| 2280 | } | ||
| 2281 | #endif | ||
| 2282 | if (!i || page_to_pfn(page) != last_pfn + 1) { | ||
| 2283 | if (i) | 2287 | if (i) |
| 2284 | sg = sg_next(sg); | 2288 | sg = sg_next(sg); |
| 2285 | st->nents++; | 2289 | st->nents++; |
| @@ -2292,9 +2296,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) | |||
| 2292 | /* Check that the i965g/gm workaround works. */ | 2296 | /* Check that the i965g/gm workaround works. */ |
| 2293 | WARN_ON((gfp & __GFP_DMA32) && (last_pfn >= 0x00100000UL)); | 2297 | WARN_ON((gfp & __GFP_DMA32) && (last_pfn >= 0x00100000UL)); |
| 2294 | } | 2298 | } |
| 2295 | #ifdef CONFIG_SWIOTLB | 2299 | if (sg) /* loop terminated early; short sg table */ |
| 2296 | if (!swiotlb_nr_tbl()) | ||
| 2297 | #endif | ||
| 2298 | sg_mark_end(sg); | 2300 | sg_mark_end(sg); |
| 2299 | obj->pages = st; | 2301 | obj->pages = st; |
| 2300 | 2302 | ||
| @@ -2581,8 +2583,6 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) | |||
| 2581 | struct i915_gem_context *incomplete_ctx; | 2583 | struct i915_gem_context *incomplete_ctx; |
| 2582 | bool ring_hung; | 2584 | bool ring_hung; |
| 2583 | 2585 | ||
| 2584 | /* Ensure irq handler finishes, and not run again. */ | ||
| 2585 | tasklet_kill(&engine->irq_tasklet); | ||
| 2586 | if (engine->irq_seqno_barrier) | 2586 | if (engine->irq_seqno_barrier) |
| 2587 | engine->irq_seqno_barrier(engine); | 2587 | engine->irq_seqno_barrier(engine); |
| 2588 | 2588 | ||
| @@ -2591,6 +2591,9 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) | |||
| 2591 | return; | 2591 | return; |
| 2592 | 2592 | ||
| 2593 | ring_hung = engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG; | 2593 | ring_hung = engine->hangcheck.score >= HANGCHECK_SCORE_RING_HUNG; |
| 2594 | if (engine->hangcheck.seqno != intel_engine_get_seqno(engine)) | ||
| 2595 | ring_hung = false; | ||
| 2596 | |||
| 2594 | i915_set_reset_status(request->ctx, ring_hung); | 2597 | i915_set_reset_status(request->ctx, ring_hung); |
| 2595 | if (!ring_hung) | 2598 | if (!ring_hung) |
| 2596 | return; | 2599 | return; |
| @@ -2616,21 +2619,26 @@ static void i915_gem_reset_engine(struct intel_engine_cs *engine) | |||
| 2616 | list_for_each_entry_continue(request, &engine->request_list, link) | 2619 | list_for_each_entry_continue(request, &engine->request_list, link) |
| 2617 | if (request->ctx == incomplete_ctx) | 2620 | if (request->ctx == incomplete_ctx) |
| 2618 | reset_request(request); | 2621 | reset_request(request); |
| 2619 | |||
| 2620 | engine->i915->gt.active_engines &= ~intel_engine_flag(engine); | ||
| 2621 | } | 2622 | } |
| 2622 | 2623 | ||
| 2623 | void i915_gem_reset(struct drm_i915_private *dev_priv) | 2624 | void i915_gem_reset(struct drm_i915_private *dev_priv) |
| 2624 | { | 2625 | { |
| 2625 | struct intel_engine_cs *engine; | 2626 | struct intel_engine_cs *engine; |
| 2627 | enum intel_engine_id id; | ||
| 2626 | 2628 | ||
| 2627 | i915_gem_retire_requests(dev_priv); | 2629 | i915_gem_retire_requests(dev_priv); |
| 2628 | 2630 | ||
| 2629 | for_each_engine(engine, dev_priv) | 2631 | for_each_engine(engine, dev_priv, id) |
| 2630 | i915_gem_reset_engine(engine); | 2632 | i915_gem_reset_engine(engine); |
| 2631 | mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0); | ||
| 2632 | 2633 | ||
| 2633 | i915_gem_restore_fences(&dev_priv->drm); | 2634 | i915_gem_restore_fences(&dev_priv->drm); |
| 2635 | |||
| 2636 | if (dev_priv->gt.awake) { | ||
| 2637 | intel_sanitize_gt_powersave(dev_priv); | ||
| 2638 | intel_enable_gt_powersave(dev_priv); | ||
| 2639 | if (INTEL_GEN(dev_priv) >= 6) | ||
| 2640 | gen6_rps_busy(dev_priv); | ||
| 2641 | } | ||
| 2634 | } | 2642 | } |
| 2635 | 2643 | ||
| 2636 | static void nop_submit_request(struct drm_i915_gem_request *request) | 2644 | static void nop_submit_request(struct drm_i915_gem_request *request) |
| @@ -2668,12 +2676,13 @@ static void i915_gem_cleanup_engine(struct intel_engine_cs *engine) | |||
| 2668 | void i915_gem_set_wedged(struct drm_i915_private *dev_priv) | 2676 | void i915_gem_set_wedged(struct drm_i915_private *dev_priv) |
| 2669 | { | 2677 | { |
| 2670 | struct intel_engine_cs *engine; | 2678 | struct intel_engine_cs *engine; |
| 2679 | enum intel_engine_id id; | ||
| 2671 | 2680 | ||
| 2672 | lockdep_assert_held(&dev_priv->drm.struct_mutex); | 2681 | lockdep_assert_held(&dev_priv->drm.struct_mutex); |
| 2673 | set_bit(I915_WEDGED, &dev_priv->gpu_error.flags); | 2682 | set_bit(I915_WEDGED, &dev_priv->gpu_error.flags); |
| 2674 | 2683 | ||
| 2675 | i915_gem_context_lost(dev_priv); | 2684 | i915_gem_context_lost(dev_priv); |
| 2676 | for_each_engine(engine, dev_priv) | 2685 | for_each_engine(engine, dev_priv, id) |
| 2677 | i915_gem_cleanup_engine(engine); | 2686 | i915_gem_cleanup_engine(engine); |
| 2678 | mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0); | 2687 | mod_delayed_work(dev_priv->wq, &dev_priv->gt.idle_work, 0); |
| 2679 | 2688 | ||
| @@ -2712,6 +2721,7 @@ i915_gem_idle_work_handler(struct work_struct *work) | |||
| 2712 | container_of(work, typeof(*dev_priv), gt.idle_work.work); | 2721 | container_of(work, typeof(*dev_priv), gt.idle_work.work); |
| 2713 | struct drm_device *dev = &dev_priv->drm; | 2722 | struct drm_device *dev = &dev_priv->drm; |
| 2714 | struct intel_engine_cs *engine; | 2723 | struct intel_engine_cs *engine; |
| 2724 | enum intel_engine_id id; | ||
| 2715 | bool rearm_hangcheck; | 2725 | bool rearm_hangcheck; |
| 2716 | 2726 | ||
| 2717 | if (!READ_ONCE(dev_priv->gt.awake)) | 2727 | if (!READ_ONCE(dev_priv->gt.awake)) |
| @@ -2734,7 +2744,7 @@ i915_gem_idle_work_handler(struct work_struct *work) | |||
| 2734 | if (dev_priv->gt.active_engines) | 2744 | if (dev_priv->gt.active_engines) |
| 2735 | goto out_unlock; | 2745 | goto out_unlock; |
| 2736 | 2746 | ||
| 2737 | for_each_engine(engine, dev_priv) | 2747 | for_each_engine(engine, dev_priv, id) |
| 2738 | i915_gem_batch_pool_fini(&engine->batch_pool); | 2748 | i915_gem_batch_pool_fini(&engine->batch_pool); |
| 2739 | 2749 | ||
| 2740 | GEM_BUG_ON(!dev_priv->gt.awake); | 2750 | GEM_BUG_ON(!dev_priv->gt.awake); |
| @@ -2927,9 +2937,10 @@ int i915_gem_wait_for_idle(struct drm_i915_private *dev_priv, | |||
| 2927 | unsigned int flags) | 2937 | unsigned int flags) |
| 2928 | { | 2938 | { |
| 2929 | struct intel_engine_cs *engine; | 2939 | struct intel_engine_cs *engine; |
| 2940 | enum intel_engine_id id; | ||
| 2930 | int ret; | 2941 | int ret; |
| 2931 | 2942 | ||
| 2932 | for_each_engine(engine, dev_priv) { | 2943 | for_each_engine(engine, dev_priv, id) { |
| 2933 | if (engine->last_context == NULL) | 2944 | if (engine->last_context == NULL) |
| 2934 | continue; | 2945 | continue; |
| 2935 | 2946 | ||
| @@ -3091,6 +3102,9 @@ search_free: | |||
| 3091 | 3102 | ||
| 3092 | goto err_unpin; | 3103 | goto err_unpin; |
| 3093 | } | 3104 | } |
| 3105 | |||
| 3106 | GEM_BUG_ON(vma->node.start < start); | ||
| 3107 | GEM_BUG_ON(vma->node.start + vma->node.size > end); | ||
| 3094 | } | 3108 | } |
| 3095 | GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level)); | 3109 | GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level)); |
| 3096 | 3110 | ||
| @@ -3169,7 +3183,7 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj) | |||
| 3169 | */ | 3183 | */ |
| 3170 | wmb(); | 3184 | wmb(); |
| 3171 | if (INTEL_GEN(dev_priv) >= 6 && !HAS_LLC(dev_priv)) | 3185 | if (INTEL_GEN(dev_priv) >= 6 && !HAS_LLC(dev_priv)) |
| 3172 | POSTING_READ(RING_ACTHD(dev_priv->engine[RCS].mmio_base)); | 3186 | POSTING_READ(RING_ACTHD(dev_priv->engine[RCS]->mmio_base)); |
| 3173 | 3187 | ||
| 3174 | intel_fb_obj_flush(obj, false, write_origin(obj, I915_GEM_DOMAIN_GTT)); | 3188 | intel_fb_obj_flush(obj, false, write_origin(obj, I915_GEM_DOMAIN_GTT)); |
| 3175 | 3189 | ||
| @@ -3464,7 +3478,7 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data, | |||
| 3464 | level = I915_CACHE_LLC; | 3478 | level = I915_CACHE_LLC; |
| 3465 | break; | 3479 | break; |
| 3466 | case I915_CACHING_DISPLAY: | 3480 | case I915_CACHING_DISPLAY: |
| 3467 | level = HAS_WT(dev) ? I915_CACHE_WT : I915_CACHE_NONE; | 3481 | level = HAS_WT(dev_priv) ? I915_CACHE_WT : I915_CACHE_NONE; |
| 3468 | break; | 3482 | break; |
| 3469 | default: | 3483 | default: |
| 3470 | return -EINVAL; | 3484 | return -EINVAL; |
| @@ -3522,7 +3536,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, | |||
| 3522 | * with that bit in the PTE to main memory with just one PIPE_CONTROL. | 3536 | * with that bit in the PTE to main memory with just one PIPE_CONTROL. |
| 3523 | */ | 3537 | */ |
| 3524 | ret = i915_gem_object_set_cache_level(obj, | 3538 | ret = i915_gem_object_set_cache_level(obj, |
| 3525 | HAS_WT(obj->base.dev) ? I915_CACHE_WT : I915_CACHE_NONE); | 3539 | HAS_WT(to_i915(obj->base.dev)) ? |
| 3540 | I915_CACHE_WT : I915_CACHE_NONE); | ||
| 3526 | if (ret) { | 3541 | if (ret) { |
| 3527 | vma = ERR_PTR(ret); | 3542 | vma = ERR_PTR(ret); |
| 3528 | goto err_unpin_display; | 3543 | goto err_unpin_display; |
| @@ -3789,7 +3804,8 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, | |||
| 3789 | u64 alignment, | 3804 | u64 alignment, |
| 3790 | u64 flags) | 3805 | u64 flags) |
| 3791 | { | 3806 | { |
| 3792 | struct i915_address_space *vm = &to_i915(obj->base.dev)->ggtt.base; | 3807 | struct drm_i915_private *dev_priv = to_i915(obj->base.dev); |
| 3808 | struct i915_address_space *vm = &dev_priv->ggtt.base; | ||
| 3793 | struct i915_vma *vma; | 3809 | struct i915_vma *vma; |
| 3794 | int ret; | 3810 | int ret; |
| 3795 | 3811 | ||
| @@ -3802,6 +3818,41 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, | |||
| 3802 | (i915_vma_is_pinned(vma) || i915_vma_is_active(vma))) | 3818 | (i915_vma_is_pinned(vma) || i915_vma_is_active(vma))) |
| 3803 | return ERR_PTR(-ENOSPC); | 3819 | return ERR_PTR(-ENOSPC); |
| 3804 | 3820 | ||
| 3821 | if (flags & PIN_MAPPABLE) { | ||
| 3822 | u32 fence_size; | ||
| 3823 | |||
| 3824 | fence_size = i915_gem_get_ggtt_size(dev_priv, vma->size, | ||
| 3825 | i915_gem_object_get_tiling(obj)); | ||
| 3826 | /* If the required space is larger than the available | ||
| 3827 | * aperture, we will not able to find a slot for the | ||
| 3828 | * object and unbinding the object now will be in | ||
| 3829 | * vain. Worse, doing so may cause us to ping-pong | ||
| 3830 | * the object in and out of the Global GTT and | ||
| 3831 | * waste a lot of cycles under the mutex. | ||
| 3832 | */ | ||
| 3833 | if (fence_size > dev_priv->ggtt.mappable_end) | ||
| 3834 | return ERR_PTR(-E2BIG); | ||
| 3835 | |||
| 3836 | /* If NONBLOCK is set the caller is optimistically | ||
| 3837 | * trying to cache the full object within the mappable | ||
| 3838 | * aperture, and *must* have a fallback in place for | ||
| 3839 | * situations where we cannot bind the object. We | ||
| 3840 | * can be a little more lax here and use the fallback | ||
| 3841 | * more often to avoid costly migrations of ourselves | ||
| 3842 | * and other objects within the aperture. | ||
| 3843 | * | ||
| 3844 | * Half-the-aperture is used as a simple heuristic. | ||
| 3845 | * More interesting would to do search for a free | ||
| 3846 | * block prior to making the commitment to unbind. | ||
| 3847 | * That caters for the self-harm case, and with a | ||
| 3848 | * little more heuristics (e.g. NOFAULT, NOEVICT) | ||
| 3849 | * we could try to minimise harm to others. | ||
| 3850 | */ | ||
| 3851 | if (flags & PIN_NONBLOCK && | ||
| 3852 | fence_size > dev_priv->ggtt.mappable_end / 2) | ||
| 3853 | return ERR_PTR(-ENOSPC); | ||
| 3854 | } | ||
| 3855 | |||
| 3805 | WARN(i915_vma_is_pinned(vma), | 3856 | WARN(i915_vma_is_pinned(vma), |
| 3806 | "bo is already pinned in ggtt with incorrect alignment:" | 3857 | "bo is already pinned in ggtt with incorrect alignment:" |
| 3807 | " offset=%08x, req.alignment=%llx," | 3858 | " offset=%08x, req.alignment=%llx," |
| @@ -4080,14 +4131,29 @@ static const struct drm_i915_gem_object_ops i915_gem_object_ops = { | |||
| 4080 | .put_pages = i915_gem_object_put_pages_gtt, | 4131 | .put_pages = i915_gem_object_put_pages_gtt, |
| 4081 | }; | 4132 | }; |
| 4082 | 4133 | ||
| 4083 | struct drm_i915_gem_object *i915_gem_object_create(struct drm_device *dev, | 4134 | /* Note we don't consider signbits :| */ |
| 4084 | size_t size) | 4135 | #define overflows_type(x, T) \ |
| 4136 | (sizeof(x) > sizeof(T) && (x) >> (sizeof(T) * BITS_PER_BYTE)) | ||
| 4137 | |||
| 4138 | struct drm_i915_gem_object * | ||
| 4139 | i915_gem_object_create(struct drm_device *dev, u64 size) | ||
| 4085 | { | 4140 | { |
| 4086 | struct drm_i915_gem_object *obj; | 4141 | struct drm_i915_gem_object *obj; |
| 4087 | struct address_space *mapping; | 4142 | struct address_space *mapping; |
| 4088 | gfp_t mask; | 4143 | gfp_t mask; |
| 4089 | int ret; | 4144 | int ret; |
| 4090 | 4145 | ||
| 4146 | /* There is a prevalence of the assumption that we fit the object's | ||
| 4147 | * page count inside a 32bit _signed_ variable. Let's document this and | ||
| 4148 | * catch if we ever need to fix it. In the meantime, if you do spot | ||
| 4149 | * such a local variable, please consider fixing! | ||
| 4150 | */ | ||
| 4151 | if (WARN_ON(size >> PAGE_SHIFT > INT_MAX)) | ||
| 4152 | return ERR_PTR(-E2BIG); | ||
| 4153 | |||
| 4154 | if (overflows_type(size, obj->base.size)) | ||
| 4155 | return ERR_PTR(-E2BIG); | ||
| 4156 | |||
| 4091 | obj = i915_gem_object_alloc(dev); | 4157 | obj = i915_gem_object_alloc(dev); |
| 4092 | if (obj == NULL) | 4158 | if (obj == NULL) |
| 4093 | return ERR_PTR(-ENOMEM); | 4159 | return ERR_PTR(-ENOMEM); |
| @@ -4264,6 +4330,30 @@ int i915_gem_suspend(struct drm_device *dev) | |||
| 4264 | */ | 4330 | */ |
| 4265 | WARN_ON(dev_priv->gt.awake); | 4331 | WARN_ON(dev_priv->gt.awake); |
| 4266 | 4332 | ||
| 4333 | /* | ||
| 4334 | * Neither the BIOS, ourselves or any other kernel | ||
| 4335 | * expects the system to be in execlists mode on startup, | ||
| 4336 | * so we need to reset the GPU back to legacy mode. And the only | ||
| 4337 | * known way to disable logical contexts is through a GPU reset. | ||
| 4338 | * | ||
| 4339 | * So in order to leave the system in a known default configuration, | ||
| 4340 | * always reset the GPU upon unload and suspend. Afterwards we then | ||
| 4341 | * clean up the GEM state tracking, flushing off the requests and | ||
| 4342 | * leaving the system in a known idle state. | ||
| 4343 | * | ||
| 4344 | * Note that is of the upmost importance that the GPU is idle and | ||
| 4345 | * all stray writes are flushed *before* we dismantle the backing | ||
| 4346 | * storage for the pinned objects. | ||
| 4347 | * | ||
| 4348 | * However, since we are uncertain that resetting the GPU on older | ||
| 4349 | * machines is a good idea, we don't - just in case it leaves the | ||
| 4350 | * machine in an unusable condition. | ||
| 4351 | */ | ||
| 4352 | if (HAS_HW_CONTEXTS(dev)) { | ||
| 4353 | int reset = intel_gpu_reset(dev_priv, ALL_ENGINES); | ||
| 4354 | WARN_ON(reset && reset != -ENODEV); | ||
| 4355 | } | ||
| 4356 | |||
| 4267 | return 0; | 4357 | return 0; |
| 4268 | 4358 | ||
| 4269 | err: | 4359 | err: |
| @@ -4298,44 +4388,42 @@ void i915_gem_init_swizzling(struct drm_device *dev) | |||
| 4298 | I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) | | 4388 | I915_WRITE(DISP_ARB_CTL, I915_READ(DISP_ARB_CTL) | |
| 4299 | DISP_TILE_SURFACE_SWIZZLING); | 4389 | DISP_TILE_SURFACE_SWIZZLING); |
| 4300 | 4390 | ||
| 4301 | if (IS_GEN5(dev)) | 4391 | if (IS_GEN5(dev_priv)) |
| 4302 | return; | 4392 | return; |
| 4303 | 4393 | ||
| 4304 | I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL); | 4394 | I915_WRITE(TILECTL, I915_READ(TILECTL) | TILECTL_SWZCTL); |
| 4305 | if (IS_GEN6(dev)) | 4395 | if (IS_GEN6(dev_priv)) |
| 4306 | I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB)); | 4396 | I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_SNB)); |
| 4307 | else if (IS_GEN7(dev)) | 4397 | else if (IS_GEN7(dev_priv)) |
| 4308 | I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB)); | 4398 | I915_WRITE(ARB_MODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_IVB)); |
| 4309 | else if (IS_GEN8(dev)) | 4399 | else if (IS_GEN8(dev_priv)) |
| 4310 | I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_BDW)); | 4400 | I915_WRITE(GAMTARBMODE, _MASKED_BIT_ENABLE(ARB_MODE_SWIZZLE_BDW)); |
| 4311 | else | 4401 | else |
| 4312 | BUG(); | 4402 | BUG(); |
| 4313 | } | 4403 | } |
| 4314 | 4404 | ||
| 4315 | static void init_unused_ring(struct drm_device *dev, u32 base) | 4405 | static void init_unused_ring(struct drm_i915_private *dev_priv, u32 base) |
| 4316 | { | 4406 | { |
| 4317 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 4318 | |||
| 4319 | I915_WRITE(RING_CTL(base), 0); | 4407 | I915_WRITE(RING_CTL(base), 0); |
| 4320 | I915_WRITE(RING_HEAD(base), 0); | 4408 | I915_WRITE(RING_HEAD(base), 0); |
| 4321 | I915_WRITE(RING_TAIL(base), 0); | 4409 | I915_WRITE(RING_TAIL(base), 0); |
| 4322 | I915_WRITE(RING_START(base), 0); | 4410 | I915_WRITE(RING_START(base), 0); |
| 4323 | } | 4411 | } |
| 4324 | 4412 | ||
| 4325 | static void init_unused_rings(struct drm_device *dev) | 4413 | static void init_unused_rings(struct drm_i915_private *dev_priv) |
| 4326 | { | 4414 | { |
| 4327 | if (IS_I830(dev)) { | 4415 | if (IS_I830(dev_priv)) { |
| 4328 | init_unused_ring(dev, PRB1_BASE); | 4416 | init_unused_ring(dev_priv, PRB1_BASE); |
| 4329 | init_unused_ring(dev, SRB0_BASE); | 4417 | init_unused_ring(dev_priv, SRB0_BASE); |
| 4330 | init_unused_ring(dev, SRB1_BASE); | 4418 | init_unused_ring(dev_priv, SRB1_BASE); |
| 4331 | init_unused_ring(dev, SRB2_BASE); | 4419 | init_unused_ring(dev_priv, SRB2_BASE); |
| 4332 | init_unused_ring(dev, SRB3_BASE); | 4420 | init_unused_ring(dev_priv, SRB3_BASE); |
| 4333 | } else if (IS_GEN2(dev)) { | 4421 | } else if (IS_GEN2(dev_priv)) { |
| 4334 | init_unused_ring(dev, SRB0_BASE); | 4422 | init_unused_ring(dev_priv, SRB0_BASE); |
| 4335 | init_unused_ring(dev, SRB1_BASE); | 4423 | init_unused_ring(dev_priv, SRB1_BASE); |
| 4336 | } else if (IS_GEN3(dev)) { | 4424 | } else if (IS_GEN3(dev_priv)) { |
| 4337 | init_unused_ring(dev, PRB1_BASE); | 4425 | init_unused_ring(dev_priv, PRB1_BASE); |
| 4338 | init_unused_ring(dev, PRB2_BASE); | 4426 | init_unused_ring(dev_priv, PRB2_BASE); |
| 4339 | } | 4427 | } |
| 4340 | } | 4428 | } |
| 4341 | 4429 | ||
| @@ -4344,6 +4432,7 @@ i915_gem_init_hw(struct drm_device *dev) | |||
| 4344 | { | 4432 | { |
| 4345 | struct drm_i915_private *dev_priv = to_i915(dev); | 4433 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 4346 | struct intel_engine_cs *engine; | 4434 | struct intel_engine_cs *engine; |
| 4435 | enum intel_engine_id id; | ||
| 4347 | int ret; | 4436 | int ret; |
| 4348 | 4437 | ||
| 4349 | /* Double layer security blanket, see i915_gem_init() */ | 4438 | /* Double layer security blanket, see i915_gem_init() */ |
| @@ -4352,12 +4441,12 @@ i915_gem_init_hw(struct drm_device *dev) | |||
| 4352 | if (HAS_EDRAM(dev) && INTEL_GEN(dev_priv) < 9) | 4441 | if (HAS_EDRAM(dev) && INTEL_GEN(dev_priv) < 9) |
| 4353 | I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf)); | 4442 | I915_WRITE(HSW_IDICR, I915_READ(HSW_IDICR) | IDIHASHMSK(0xf)); |
| 4354 | 4443 | ||
| 4355 | if (IS_HASWELL(dev)) | 4444 | if (IS_HASWELL(dev_priv)) |
| 4356 | I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev) ? | 4445 | I915_WRITE(MI_PREDICATE_RESULT_2, IS_HSW_GT3(dev_priv) ? |
| 4357 | LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED); | 4446 | LOWER_SLICE_ENABLED : LOWER_SLICE_DISABLED); |
| 4358 | 4447 | ||
| 4359 | if (HAS_PCH_NOP(dev)) { | 4448 | if (HAS_PCH_NOP(dev_priv)) { |
| 4360 | if (IS_IVYBRIDGE(dev)) { | 4449 | if (IS_IVYBRIDGE(dev_priv)) { |
| 4361 | u32 temp = I915_READ(GEN7_MSG_CTL); | 4450 | u32 temp = I915_READ(GEN7_MSG_CTL); |
| 4362 | temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK); | 4451 | temp &= ~(WAIT_FOR_PCH_FLR_ACK | WAIT_FOR_PCH_RESET_ACK); |
| 4363 | I915_WRITE(GEN7_MSG_CTL, temp); | 4452 | I915_WRITE(GEN7_MSG_CTL, temp); |
| @@ -4376,7 +4465,7 @@ i915_gem_init_hw(struct drm_device *dev) | |||
| 4376 | * will prevent c3 entry. Makes sure all unused rings | 4465 | * will prevent c3 entry. Makes sure all unused rings |
| 4377 | * are totally idle. | 4466 | * are totally idle. |
| 4378 | */ | 4467 | */ |
| 4379 | init_unused_rings(dev); | 4468 | init_unused_rings(dev_priv); |
| 4380 | 4469 | ||
| 4381 | BUG_ON(!dev_priv->kernel_context); | 4470 | BUG_ON(!dev_priv->kernel_context); |
| 4382 | 4471 | ||
| @@ -4387,7 +4476,7 @@ i915_gem_init_hw(struct drm_device *dev) | |||
| 4387 | } | 4476 | } |
| 4388 | 4477 | ||
| 4389 | /* Need to do basic initialisation of all rings first: */ | 4478 | /* Need to do basic initialisation of all rings first: */ |
| 4390 | for_each_engine(engine, dev_priv) { | 4479 | for_each_engine(engine, dev_priv, id) { |
| 4391 | ret = engine->init_hw(engine); | 4480 | ret = engine->init_hw(engine); |
| 4392 | if (ret) | 4481 | if (ret) |
| 4393 | goto out; | 4482 | goto out; |
| @@ -4486,17 +4575,12 @@ i915_gem_cleanup_engines(struct drm_device *dev) | |||
| 4486 | { | 4575 | { |
| 4487 | struct drm_i915_private *dev_priv = to_i915(dev); | 4576 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 4488 | struct intel_engine_cs *engine; | 4577 | struct intel_engine_cs *engine; |
| 4578 | enum intel_engine_id id; | ||
| 4489 | 4579 | ||
| 4490 | for_each_engine(engine, dev_priv) | 4580 | for_each_engine(engine, dev_priv, id) |
| 4491 | dev_priv->gt.cleanup_engine(engine); | 4581 | dev_priv->gt.cleanup_engine(engine); |
| 4492 | } | 4582 | } |
| 4493 | 4583 | ||
| 4494 | static void | ||
| 4495 | init_engine_lists(struct intel_engine_cs *engine) | ||
| 4496 | { | ||
| 4497 | INIT_LIST_HEAD(&engine->request_list); | ||
| 4498 | } | ||
| 4499 | |||
| 4500 | void | 4584 | void |
| 4501 | i915_gem_load_init_fences(struct drm_i915_private *dev_priv) | 4585 | i915_gem_load_init_fences(struct drm_i915_private *dev_priv) |
| 4502 | { | 4586 | { |
| @@ -4533,7 +4617,6 @@ void | |||
| 4533 | i915_gem_load_init(struct drm_device *dev) | 4617 | i915_gem_load_init(struct drm_device *dev) |
| 4534 | { | 4618 | { |
| 4535 | struct drm_i915_private *dev_priv = to_i915(dev); | 4619 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 4536 | int i; | ||
| 4537 | 4620 | ||
| 4538 | dev_priv->objects = | 4621 | dev_priv->objects = |
| 4539 | kmem_cache_create("i915_gem_object", | 4622 | kmem_cache_create("i915_gem_object", |
| @@ -4557,8 +4640,6 @@ i915_gem_load_init(struct drm_device *dev) | |||
| 4557 | INIT_LIST_HEAD(&dev_priv->mm.unbound_list); | 4640 | INIT_LIST_HEAD(&dev_priv->mm.unbound_list); |
| 4558 | INIT_LIST_HEAD(&dev_priv->mm.bound_list); | 4641 | INIT_LIST_HEAD(&dev_priv->mm.bound_list); |
| 4559 | INIT_LIST_HEAD(&dev_priv->mm.fence_list); | 4642 | INIT_LIST_HEAD(&dev_priv->mm.fence_list); |
| 4560 | for (i = 0; i < I915_NUM_ENGINES; i++) | ||
| 4561 | init_engine_lists(&dev_priv->engine[i]); | ||
| 4562 | INIT_DELAYED_WORK(&dev_priv->gt.retire_work, | 4643 | INIT_DELAYED_WORK(&dev_priv->gt.retire_work, |
| 4563 | i915_gem_retire_work_handler); | 4644 | i915_gem_retire_work_handler); |
| 4564 | INIT_DELAYED_WORK(&dev_priv->gt.idle_work, | 4645 | INIT_DELAYED_WORK(&dev_priv->gt.idle_work, |
| @@ -4589,6 +4670,19 @@ void i915_gem_load_cleanup(struct drm_device *dev) | |||
| 4589 | rcu_barrier(); | 4670 | rcu_barrier(); |
| 4590 | } | 4671 | } |
| 4591 | 4672 | ||
| 4673 | int i915_gem_freeze(struct drm_i915_private *dev_priv) | ||
| 4674 | { | ||
| 4675 | intel_runtime_pm_get(dev_priv); | ||
| 4676 | |||
| 4677 | mutex_lock(&dev_priv->drm.struct_mutex); | ||
| 4678 | i915_gem_shrink_all(dev_priv); | ||
| 4679 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
| 4680 | |||
| 4681 | intel_runtime_pm_put(dev_priv); | ||
| 4682 | |||
| 4683 | return 0; | ||
| 4684 | } | ||
| 4685 | |||
| 4592 | int i915_gem_freeze_late(struct drm_i915_private *dev_priv) | 4686 | int i915_gem_freeze_late(struct drm_i915_private *dev_priv) |
| 4593 | { | 4687 | { |
| 4594 | struct drm_i915_gem_object *obj; | 4688 | struct drm_i915_gem_object *obj; |
| @@ -4612,7 +4706,8 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv) | |||
| 4612 | * the objects as well. | 4706 | * the objects as well. |
| 4613 | */ | 4707 | */ |
| 4614 | 4708 | ||
| 4615 | i915_gem_shrink_all(dev_priv); | 4709 | mutex_lock(&dev_priv->drm.struct_mutex); |
| 4710 | i915_gem_shrink(dev_priv, -1UL, I915_SHRINK_UNBOUND); | ||
| 4616 | 4711 | ||
| 4617 | for (p = phases; *p; p++) { | 4712 | for (p = phases; *p; p++) { |
| 4618 | list_for_each_entry(obj, *p, global_list) { | 4713 | list_for_each_entry(obj, *p, global_list) { |
| @@ -4620,6 +4715,7 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv) | |||
| 4620 | obj->base.write_domain = I915_GEM_DOMAIN_CPU; | 4715 | obj->base.write_domain = I915_GEM_DOMAIN_CPU; |
| 4621 | } | 4716 | } |
| 4622 | } | 4717 | } |
| 4718 | mutex_unlock(&dev_priv->drm.struct_mutex); | ||
| 4623 | 4719 | ||
| 4624 | return 0; | 4720 | return 0; |
| 4625 | } | 4721 | } |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index df10f4e95736..5dca32ac1c67 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
| @@ -192,7 +192,7 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size) | |||
| 192 | * This is only applicable for Ivy Bridge devices since | 192 | * This is only applicable for Ivy Bridge devices since |
| 193 | * later platforms don't have L3 control bits in the PTE. | 193 | * later platforms don't have L3 control bits in the PTE. |
| 194 | */ | 194 | */ |
| 195 | if (IS_IVYBRIDGE(dev)) { | 195 | if (IS_IVYBRIDGE(to_i915(dev))) { |
| 196 | ret = i915_gem_object_set_cache_level(obj, I915_CACHE_L3_LLC); | 196 | ret = i915_gem_object_set_cache_level(obj, I915_CACHE_L3_LLC); |
| 197 | /* Failure shouldn't ever happen this early */ | 197 | /* Failure shouldn't ever happen this early */ |
| 198 | if (WARN_ON(ret)) { | 198 | if (WARN_ON(ret)) { |
| @@ -474,10 +474,11 @@ int i915_gem_context_init(struct drm_device *dev) | |||
| 474 | void i915_gem_context_lost(struct drm_i915_private *dev_priv) | 474 | void i915_gem_context_lost(struct drm_i915_private *dev_priv) |
| 475 | { | 475 | { |
| 476 | struct intel_engine_cs *engine; | 476 | struct intel_engine_cs *engine; |
| 477 | enum intel_engine_id id; | ||
| 477 | 478 | ||
| 478 | lockdep_assert_held(&dev_priv->drm.struct_mutex); | 479 | lockdep_assert_held(&dev_priv->drm.struct_mutex); |
| 479 | 480 | ||
| 480 | for_each_engine(engine, dev_priv) { | 481 | for_each_engine(engine, dev_priv, id) { |
| 481 | if (engine->last_context) { | 482 | if (engine->last_context) { |
| 482 | i915_gem_context_unpin(engine->last_context, engine); | 483 | i915_gem_context_unpin(engine->last_context, engine); |
| 483 | engine->last_context = NULL; | 484 | engine->last_context = NULL; |
| @@ -492,13 +493,13 @@ void i915_gem_context_lost(struct drm_i915_private *dev_priv) | |||
| 492 | if (!i915_gem_context_is_default(ctx)) | 493 | if (!i915_gem_context_is_default(ctx)) |
| 493 | continue; | 494 | continue; |
| 494 | 495 | ||
| 495 | for_each_engine(engine, dev_priv) | 496 | for_each_engine(engine, dev_priv, id) |
| 496 | ctx->engine[engine->id].initialised = false; | 497 | ctx->engine[engine->id].initialised = false; |
| 497 | 498 | ||
| 498 | ctx->remap_slice = ALL_L3_SLICES(dev_priv); | 499 | ctx->remap_slice = ALL_L3_SLICES(dev_priv); |
| 499 | } | 500 | } |
| 500 | 501 | ||
| 501 | for_each_engine(engine, dev_priv) { | 502 | for_each_engine(engine, dev_priv, id) { |
| 502 | struct intel_context *kce = | 503 | struct intel_context *kce = |
| 503 | &dev_priv->kernel_context->engine[engine->id]; | 504 | &dev_priv->kernel_context->engine[engine->id]; |
| 504 | 505 | ||
| @@ -563,6 +564,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) | |||
| 563 | struct drm_i915_private *dev_priv = req->i915; | 564 | struct drm_i915_private *dev_priv = req->i915; |
| 564 | struct intel_ring *ring = req->ring; | 565 | struct intel_ring *ring = req->ring; |
| 565 | struct intel_engine_cs *engine = req->engine; | 566 | struct intel_engine_cs *engine = req->engine; |
| 567 | enum intel_engine_id id; | ||
| 566 | u32 flags = hw_flags | MI_MM_SPACE_GTT; | 568 | u32 flags = hw_flags | MI_MM_SPACE_GTT; |
| 567 | const int num_rings = | 569 | const int num_rings = |
| 568 | /* Use an extended w/a on ivb+ if signalling from other rings */ | 570 | /* Use an extended w/a on ivb+ if signalling from other rings */ |
| @@ -605,7 +607,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) | |||
| 605 | 607 | ||
| 606 | intel_ring_emit(ring, | 608 | intel_ring_emit(ring, |
| 607 | MI_LOAD_REGISTER_IMM(num_rings)); | 609 | MI_LOAD_REGISTER_IMM(num_rings)); |
| 608 | for_each_engine(signaller, dev_priv) { | 610 | for_each_engine(signaller, dev_priv, id) { |
| 609 | if (signaller == engine) | 611 | if (signaller == engine) |
| 610 | continue; | 612 | continue; |
| 611 | 613 | ||
| @@ -634,7 +636,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags) | |||
| 634 | 636 | ||
| 635 | intel_ring_emit(ring, | 637 | intel_ring_emit(ring, |
| 636 | MI_LOAD_REGISTER_IMM(num_rings)); | 638 | MI_LOAD_REGISTER_IMM(num_rings)); |
| 637 | for_each_engine(signaller, dev_priv) { | 639 | for_each_engine(signaller, dev_priv, id) { |
| 638 | if (signaller == engine) | 640 | if (signaller == engine) |
| 639 | continue; | 641 | continue; |
| 640 | 642 | ||
| @@ -929,8 +931,9 @@ int i915_switch_context(struct drm_i915_gem_request *req) | |||
| 929 | int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) | 931 | int i915_gem_switch_to_kernel_context(struct drm_i915_private *dev_priv) |
| 930 | { | 932 | { |
| 931 | struct intel_engine_cs *engine; | 933 | struct intel_engine_cs *engine; |
| 934 | enum intel_engine_id id; | ||
| 932 | 935 | ||
| 933 | for_each_engine(engine, dev_priv) { | 936 | for_each_engine(engine, dev_priv, id) { |
| 934 | struct drm_i915_gem_request *req; | 937 | struct drm_i915_gem_request *req; |
| 935 | int ret; | 938 | int ret; |
| 936 | 939 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 5b6f81c1dbca..b5e9e669f50f 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c | |||
| @@ -37,8 +37,9 @@ static bool | |||
| 37 | gpu_is_idle(struct drm_i915_private *dev_priv) | 37 | gpu_is_idle(struct drm_i915_private *dev_priv) |
| 38 | { | 38 | { |
| 39 | struct intel_engine_cs *engine; | 39 | struct intel_engine_cs *engine; |
| 40 | enum intel_engine_id id; | ||
| 40 | 41 | ||
| 41 | for_each_engine(engine, dev_priv) { | 42 | for_each_engine(engine, dev_priv, id) { |
| 42 | if (intel_engine_is_active(engine)) | 43 | if (intel_engine_is_active(engine)) |
| 43 | return false; | 44 | return false; |
| 44 | } | 45 | } |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 33c85227643d..e52affdcc125 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
| @@ -370,8 +370,7 @@ static void reloc_cache_fini(struct reloc_cache *cache) | |||
| 370 | 370 | ||
| 371 | ggtt->base.clear_range(&ggtt->base, | 371 | ggtt->base.clear_range(&ggtt->base, |
| 372 | cache->node.start, | 372 | cache->node.start, |
| 373 | cache->node.size, | 373 | cache->node.size); |
| 374 | true); | ||
| 375 | drm_mm_remove_node(&cache->node); | 374 | drm_mm_remove_node(&cache->node); |
| 376 | } else { | 375 | } else { |
| 377 | i915_vma_unpin((struct i915_vma *)cache->node.mm); | 376 | i915_vma_unpin((struct i915_vma *)cache->node.mm); |
| @@ -429,7 +428,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, | |||
| 429 | } | 428 | } |
| 430 | 429 | ||
| 431 | if (cache->vaddr) { | 430 | if (cache->vaddr) { |
| 432 | io_mapping_unmap_atomic(unmask_page(cache->vaddr)); | 431 | io_mapping_unmap_atomic((void __force __iomem *) unmask_page(cache->vaddr)); |
| 433 | } else { | 432 | } else { |
| 434 | struct i915_vma *vma; | 433 | struct i915_vma *vma; |
| 435 | int ret; | 434 | int ret; |
| @@ -451,8 +450,8 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, | |||
| 451 | 0, ggtt->mappable_end, | 450 | 0, ggtt->mappable_end, |
| 452 | DRM_MM_SEARCH_DEFAULT, | 451 | DRM_MM_SEARCH_DEFAULT, |
| 453 | DRM_MM_CREATE_DEFAULT); | 452 | DRM_MM_CREATE_DEFAULT); |
| 454 | if (ret) | 453 | if (ret) /* no inactive aperture space, use cpu reloc */ |
| 455 | return ERR_PTR(ret); | 454 | return NULL; |
| 456 | } else { | 455 | } else { |
| 457 | ret = i915_vma_put_fence(vma); | 456 | ret = i915_vma_put_fence(vma); |
| 458 | if (ret) { | 457 | if (ret) { |
| @@ -474,7 +473,7 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, | |||
| 474 | offset += page << PAGE_SHIFT; | 473 | offset += page << PAGE_SHIFT; |
| 475 | } | 474 | } |
| 476 | 475 | ||
| 477 | vaddr = io_mapping_map_atomic_wc(&cache->i915->ggtt.mappable, offset); | 476 | vaddr = (void __force *) io_mapping_map_atomic_wc(&cache->i915->ggtt.mappable, offset); |
| 478 | cache->page = page; | 477 | cache->page = page; |
| 479 | cache->vaddr = (unsigned long)vaddr; | 478 | cache->vaddr = (unsigned long)vaddr; |
| 480 | 479 | ||
| @@ -552,27 +551,13 @@ repeat: | |||
| 552 | return 0; | 551 | return 0; |
| 553 | } | 552 | } |
| 554 | 553 | ||
| 555 | static bool object_is_idle(struct drm_i915_gem_object *obj) | ||
| 556 | { | ||
| 557 | unsigned long active = i915_gem_object_get_active(obj); | ||
| 558 | int idx; | ||
| 559 | |||
| 560 | for_each_active(active, idx) { | ||
| 561 | if (!i915_gem_active_is_idle(&obj->last_read[idx], | ||
| 562 | &obj->base.dev->struct_mutex)) | ||
| 563 | return false; | ||
| 564 | } | ||
| 565 | |||
| 566 | return true; | ||
| 567 | } | ||
| 568 | |||
| 569 | static int | 554 | static int |
| 570 | i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, | 555 | i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, |
| 571 | struct eb_vmas *eb, | 556 | struct eb_vmas *eb, |
| 572 | struct drm_i915_gem_relocation_entry *reloc, | 557 | struct drm_i915_gem_relocation_entry *reloc, |
| 573 | struct reloc_cache *cache) | 558 | struct reloc_cache *cache) |
| 574 | { | 559 | { |
| 575 | struct drm_device *dev = obj->base.dev; | 560 | struct drm_i915_private *dev_priv = to_i915(obj->base.dev); |
| 576 | struct drm_gem_object *target_obj; | 561 | struct drm_gem_object *target_obj; |
| 577 | struct drm_i915_gem_object *target_i915_obj; | 562 | struct drm_i915_gem_object *target_i915_obj; |
| 578 | struct i915_vma *target_vma; | 563 | struct i915_vma *target_vma; |
| @@ -591,7 +576,7 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, | |||
| 591 | /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and | 576 | /* Sandybridge PPGTT errata: We need a global gtt mapping for MI and |
| 592 | * pipe_control writes because the gpu doesn't properly redirect them | 577 | * pipe_control writes because the gpu doesn't properly redirect them |
| 593 | * through the ppgtt for non_secure batchbuffers. */ | 578 | * through the ppgtt for non_secure batchbuffers. */ |
| 594 | if (unlikely(IS_GEN6(dev) && | 579 | if (unlikely(IS_GEN6(dev_priv) && |
| 595 | reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION)) { | 580 | reloc->write_domain == I915_GEM_DOMAIN_INSTRUCTION)) { |
| 596 | ret = i915_vma_bind(target_vma, target_i915_obj->cache_level, | 581 | ret = i915_vma_bind(target_vma, target_i915_obj->cache_level, |
| 597 | PIN_GLOBAL); | 582 | PIN_GLOBAL); |
| @@ -649,10 +634,6 @@ i915_gem_execbuffer_relocate_entry(struct drm_i915_gem_object *obj, | |||
| 649 | return -EINVAL; | 634 | return -EINVAL; |
| 650 | } | 635 | } |
| 651 | 636 | ||
| 652 | /* We can't wait for rendering with pagefaults disabled */ | ||
| 653 | if (pagefault_disabled() && !object_is_idle(obj)) | ||
| 654 | return -EFAULT; | ||
| 655 | |||
| 656 | ret = relocate_entry(obj, reloc, cache, target_offset); | 637 | ret = relocate_entry(obj, reloc, cache, target_offset); |
| 657 | if (ret) | 638 | if (ret) |
| 658 | return ret; | 639 | return ret; |
| @@ -679,12 +660,23 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma, | |||
| 679 | remain = entry->relocation_count; | 660 | remain = entry->relocation_count; |
| 680 | while (remain) { | 661 | while (remain) { |
| 681 | struct drm_i915_gem_relocation_entry *r = stack_reloc; | 662 | struct drm_i915_gem_relocation_entry *r = stack_reloc; |
| 682 | int count = remain; | 663 | unsigned long unwritten; |
| 683 | if (count > ARRAY_SIZE(stack_reloc)) | 664 | unsigned int count; |
| 684 | count = ARRAY_SIZE(stack_reloc); | 665 | |
| 666 | count = min_t(unsigned int, remain, ARRAY_SIZE(stack_reloc)); | ||
| 685 | remain -= count; | 667 | remain -= count; |
| 686 | 668 | ||
| 687 | if (__copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0]))) { | 669 | /* This is the fast path and we cannot handle a pagefault |
| 670 | * whilst holding the struct mutex lest the user pass in the | ||
| 671 | * relocations contained within a mmaped bo. For in such a case | ||
| 672 | * we, the page fault handler would call i915_gem_fault() and | ||
| 673 | * we would try to acquire the struct mutex again. Obviously | ||
| 674 | * this is bad and so lockdep complains vehemently. | ||
| 675 | */ | ||
| 676 | pagefault_disable(); | ||
| 677 | unwritten = __copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0])); | ||
| 678 | pagefault_enable(); | ||
| 679 | if (unlikely(unwritten)) { | ||
| 688 | ret = -EFAULT; | 680 | ret = -EFAULT; |
| 689 | goto out; | 681 | goto out; |
| 690 | } | 682 | } |
| @@ -696,11 +688,26 @@ i915_gem_execbuffer_relocate_vma(struct i915_vma *vma, | |||
| 696 | if (ret) | 688 | if (ret) |
| 697 | goto out; | 689 | goto out; |
| 698 | 690 | ||
| 699 | if (r->presumed_offset != offset && | 691 | if (r->presumed_offset != offset) { |
| 700 | __put_user(r->presumed_offset, | 692 | pagefault_disable(); |
| 701 | &user_relocs->presumed_offset)) { | 693 | unwritten = __put_user(r->presumed_offset, |
| 702 | ret = -EFAULT; | 694 | &user_relocs->presumed_offset); |
| 703 | goto out; | 695 | pagefault_enable(); |
| 696 | if (unlikely(unwritten)) { | ||
| 697 | /* Note that reporting an error now | ||
| 698 | * leaves everything in an inconsistent | ||
| 699 | * state as we have *already* changed | ||
| 700 | * the relocation value inside the | ||
| 701 | * object. As we have not changed the | ||
| 702 | * reloc.presumed_offset or will not | ||
| 703 | * change the execobject.offset, on the | ||
| 704 | * call we may not rewrite the value | ||
| 705 | * inside the object, leaving it | ||
| 706 | * dangling and causing a GPU hang. | ||
| 707 | */ | ||
| 708 | ret = -EFAULT; | ||
| 709 | goto out; | ||
| 710 | } | ||
| 704 | } | 711 | } |
| 705 | 712 | ||
| 706 | user_relocs++; | 713 | user_relocs++; |
| @@ -740,20 +747,11 @@ i915_gem_execbuffer_relocate(struct eb_vmas *eb) | |||
| 740 | struct i915_vma *vma; | 747 | struct i915_vma *vma; |
| 741 | int ret = 0; | 748 | int ret = 0; |
| 742 | 749 | ||
| 743 | /* This is the fast path and we cannot handle a pagefault whilst | ||
| 744 | * holding the struct mutex lest the user pass in the relocations | ||
| 745 | * contained within a mmaped bo. For in such a case we, the page | ||
| 746 | * fault handler would call i915_gem_fault() and we would try to | ||
| 747 | * acquire the struct mutex again. Obviously this is bad and so | ||
| 748 | * lockdep complains vehemently. | ||
| 749 | */ | ||
| 750 | pagefault_disable(); | ||
| 751 | list_for_each_entry(vma, &eb->vmas, exec_list) { | 750 | list_for_each_entry(vma, &eb->vmas, exec_list) { |
| 752 | ret = i915_gem_execbuffer_relocate_vma(vma, eb); | 751 | ret = i915_gem_execbuffer_relocate_vma(vma, eb); |
| 753 | if (ret) | 752 | if (ret) |
| 754 | break; | 753 | break; |
| 755 | } | 754 | } |
| 756 | pagefault_enable(); | ||
| 757 | 755 | ||
| 758 | return ret; | 756 | return ret; |
| 759 | } | 757 | } |
| @@ -1253,7 +1251,7 @@ validate_exec_list(struct drm_device *dev, | |||
| 1253 | return -EFAULT; | 1251 | return -EFAULT; |
| 1254 | 1252 | ||
| 1255 | if (likely(!i915.prefault_disable)) { | 1253 | if (likely(!i915.prefault_disable)) { |
| 1256 | if (fault_in_multipages_readable(ptr, length)) | 1254 | if (fault_in_pages_readable(ptr, length)) |
| 1257 | return -EFAULT; | 1255 | return -EFAULT; |
| 1258 | } | 1256 | } |
| 1259 | } | 1257 | } |
| @@ -1599,12 +1597,12 @@ eb_select_engine(struct drm_i915_private *dev_priv, | |||
| 1599 | return NULL; | 1597 | return NULL; |
| 1600 | } | 1598 | } |
| 1601 | 1599 | ||
| 1602 | engine = &dev_priv->engine[_VCS(bsd_idx)]; | 1600 | engine = dev_priv->engine[_VCS(bsd_idx)]; |
| 1603 | } else { | 1601 | } else { |
| 1604 | engine = &dev_priv->engine[user_ring_map[user_ring_id]]; | 1602 | engine = dev_priv->engine[user_ring_map[user_ring_id]]; |
| 1605 | } | 1603 | } |
| 1606 | 1604 | ||
| 1607 | if (!intel_engine_initialized(engine)) { | 1605 | if (!engine) { |
| 1608 | DRM_DEBUG("execbuf with invalid ring: %u\n", user_ring_id); | 1606 | DRM_DEBUG("execbuf with invalid ring: %u\n", user_ring_id); |
| 1609 | return NULL; | 1607 | return NULL; |
| 1610 | } | 1608 | } |
diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index 8df1fa7234e8..a6daf2deab74 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c | |||
| @@ -290,6 +290,8 @@ i915_vma_put_fence(struct i915_vma *vma) | |||
| 290 | { | 290 | { |
| 291 | struct drm_i915_fence_reg *fence = vma->fence; | 291 | struct drm_i915_fence_reg *fence = vma->fence; |
| 292 | 292 | ||
| 293 | assert_rpm_wakelock_held(to_i915(vma->vm->dev)); | ||
| 294 | |||
| 293 | if (!fence) | 295 | if (!fence) |
| 294 | return 0; | 296 | return 0; |
| 295 | 297 | ||
| @@ -341,6 +343,8 @@ i915_vma_get_fence(struct i915_vma *vma) | |||
| 341 | struct drm_i915_fence_reg *fence; | 343 | struct drm_i915_fence_reg *fence; |
| 342 | struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL; | 344 | struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL; |
| 343 | 345 | ||
| 346 | assert_rpm_wakelock_held(to_i915(vma->vm->dev)); | ||
| 347 | |||
| 344 | /* Just update our place in the LRU if our fence is getting reused. */ | 348 | /* Just update our place in the LRU if our fence is getting reused. */ |
| 345 | if (vma->fence) { | 349 | if (vma->fence) { |
| 346 | fence = vma->fence; | 350 | fence = vma->fence; |
| @@ -371,6 +375,12 @@ void i915_gem_restore_fences(struct drm_device *dev) | |||
| 371 | struct drm_i915_private *dev_priv = to_i915(dev); | 375 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 372 | int i; | 376 | int i; |
| 373 | 377 | ||
| 378 | /* Note that this may be called outside of struct_mutex, by | ||
| 379 | * runtime suspend/resume. The barrier we require is enforced by | ||
| 380 | * rpm itself - all access to fences/GTT are only within an rpm | ||
| 381 | * wakeref, and to acquire that wakeref you must pass through here. | ||
| 382 | */ | ||
| 383 | |||
| 374 | for (i = 0; i < dev_priv->num_fence_regs; i++) { | 384 | for (i = 0; i < dev_priv->num_fence_regs; i++) { |
| 375 | struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; | 385 | struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; |
| 376 | struct i915_vma *vma = reg->vma; | 386 | struct i915_vma *vma = reg->vma; |
| @@ -379,10 +389,17 @@ void i915_gem_restore_fences(struct drm_device *dev) | |||
| 379 | * Commit delayed tiling changes if we have an object still | 389 | * Commit delayed tiling changes if we have an object still |
| 380 | * attached to the fence, otherwise just clear the fence. | 390 | * attached to the fence, otherwise just clear the fence. |
| 381 | */ | 391 | */ |
| 382 | if (vma && !i915_gem_object_is_tiled(vma->obj)) | 392 | if (vma && !i915_gem_object_is_tiled(vma->obj)) { |
| 393 | GEM_BUG_ON(!reg->dirty); | ||
| 394 | GEM_BUG_ON(vma->obj->fault_mappable); | ||
| 395 | |||
| 396 | list_move(®->link, &dev_priv->mm.fence_list); | ||
| 397 | vma->fence = NULL; | ||
| 383 | vma = NULL; | 398 | vma = NULL; |
| 399 | } | ||
| 384 | 400 | ||
| 385 | fence_update(reg, vma); | 401 | fence_write(reg, vma); |
| 402 | reg->vma = vma; | ||
| 386 | } | 403 | } |
| 387 | } | 404 | } |
| 388 | 405 | ||
| @@ -448,7 +465,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) | |||
| 448 | uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; | 465 | uint32_t swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; |
| 449 | uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; | 466 | uint32_t swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; |
| 450 | 467 | ||
| 451 | if (INTEL_INFO(dev)->gen >= 8 || IS_VALLEYVIEW(dev)) { | 468 | if (INTEL_GEN(dev_priv) >= 8 || IS_VALLEYVIEW(dev_priv)) { |
| 452 | /* | 469 | /* |
| 453 | * On BDW+, swizzling is not used. We leave the CPU memory | 470 | * On BDW+, swizzling is not used. We leave the CPU memory |
| 454 | * controller in charge of optimizing memory accesses without | 471 | * controller in charge of optimizing memory accesses without |
| @@ -487,19 +504,20 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) | |||
| 487 | swizzle_y = I915_BIT_6_SWIZZLE_NONE; | 504 | swizzle_y = I915_BIT_6_SWIZZLE_NONE; |
| 488 | } | 505 | } |
| 489 | } | 506 | } |
| 490 | } else if (IS_GEN5(dev)) { | 507 | } else if (IS_GEN5(dev_priv)) { |
| 491 | /* On Ironlake whatever DRAM config, GPU always do | 508 | /* On Ironlake whatever DRAM config, GPU always do |
| 492 | * same swizzling setup. | 509 | * same swizzling setup. |
| 493 | */ | 510 | */ |
| 494 | swizzle_x = I915_BIT_6_SWIZZLE_9_10; | 511 | swizzle_x = I915_BIT_6_SWIZZLE_9_10; |
| 495 | swizzle_y = I915_BIT_6_SWIZZLE_9; | 512 | swizzle_y = I915_BIT_6_SWIZZLE_9; |
| 496 | } else if (IS_GEN2(dev)) { | 513 | } else if (IS_GEN2(dev_priv)) { |
| 497 | /* As far as we know, the 865 doesn't have these bit 6 | 514 | /* As far as we know, the 865 doesn't have these bit 6 |
| 498 | * swizzling issues. | 515 | * swizzling issues. |
| 499 | */ | 516 | */ |
| 500 | swizzle_x = I915_BIT_6_SWIZZLE_NONE; | 517 | swizzle_x = I915_BIT_6_SWIZZLE_NONE; |
| 501 | swizzle_y = I915_BIT_6_SWIZZLE_NONE; | 518 | swizzle_y = I915_BIT_6_SWIZZLE_NONE; |
| 502 | } else if (IS_MOBILE(dev) || (IS_GEN3(dev) && !IS_G33(dev))) { | 519 | } else if (IS_MOBILE(dev_priv) || (IS_GEN3(dev_priv) && |
| 520 | !IS_G33(dev_priv))) { | ||
| 503 | uint32_t dcc; | 521 | uint32_t dcc; |
| 504 | 522 | ||
| 505 | /* On 9xx chipsets, channel interleave by the CPU is | 523 | /* On 9xx chipsets, channel interleave by the CPU is |
| @@ -537,7 +555,7 @@ i915_gem_detect_bit_6_swizzle(struct drm_device *dev) | |||
| 537 | } | 555 | } |
| 538 | 556 | ||
| 539 | /* check for L-shaped memory aka modified enhanced addressing */ | 557 | /* check for L-shaped memory aka modified enhanced addressing */ |
| 540 | if (IS_GEN4(dev) && | 558 | if (IS_GEN4(dev_priv) && |
| 541 | !(I915_READ(DCC2) & DCC2_MODIFIED_ENHANCED_DISABLE)) { | 559 | !(I915_READ(DCC2) & DCC2_MODIFIED_ENHANCED_DISABLE)) { |
| 542 | swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; | 560 | swizzle_x = I915_BIT_6_SWIZZLE_UNKNOWN; |
| 543 | swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; | 561 | swizzle_y = I915_BIT_6_SWIZZLE_UNKNOWN; |
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 0bb4232f66bc..062fb0ad75da 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c | |||
| @@ -191,15 +191,13 @@ static void ppgtt_unbind_vma(struct i915_vma *vma) | |||
| 191 | { | 191 | { |
| 192 | vma->vm->clear_range(vma->vm, | 192 | vma->vm->clear_range(vma->vm, |
| 193 | vma->node.start, | 193 | vma->node.start, |
| 194 | vma->size, | 194 | vma->size); |
| 195 | true); | ||
| 196 | } | 195 | } |
| 197 | 196 | ||
| 198 | static gen8_pte_t gen8_pte_encode(dma_addr_t addr, | 197 | static gen8_pte_t gen8_pte_encode(dma_addr_t addr, |
| 199 | enum i915_cache_level level, | 198 | enum i915_cache_level level) |
| 200 | bool valid) | ||
| 201 | { | 199 | { |
| 202 | gen8_pte_t pte = valid ? _PAGE_PRESENT | _PAGE_RW : 0; | 200 | gen8_pte_t pte = _PAGE_PRESENT | _PAGE_RW; |
| 203 | pte |= addr; | 201 | pte |= addr; |
| 204 | 202 | ||
| 205 | switch (level) { | 203 | switch (level) { |
| @@ -234,9 +232,9 @@ static gen8_pde_t gen8_pde_encode(const dma_addr_t addr, | |||
| 234 | 232 | ||
| 235 | static gen6_pte_t snb_pte_encode(dma_addr_t addr, | 233 | static gen6_pte_t snb_pte_encode(dma_addr_t addr, |
| 236 | enum i915_cache_level level, | 234 | enum i915_cache_level level, |
| 237 | bool valid, u32 unused) | 235 | u32 unused) |
| 238 | { | 236 | { |
| 239 | gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; | 237 | gen6_pte_t pte = GEN6_PTE_VALID; |
| 240 | pte |= GEN6_PTE_ADDR_ENCODE(addr); | 238 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
| 241 | 239 | ||
| 242 | switch (level) { | 240 | switch (level) { |
| @@ -256,9 +254,9 @@ static gen6_pte_t snb_pte_encode(dma_addr_t addr, | |||
| 256 | 254 | ||
| 257 | static gen6_pte_t ivb_pte_encode(dma_addr_t addr, | 255 | static gen6_pte_t ivb_pte_encode(dma_addr_t addr, |
| 258 | enum i915_cache_level level, | 256 | enum i915_cache_level level, |
| 259 | bool valid, u32 unused) | 257 | u32 unused) |
| 260 | { | 258 | { |
| 261 | gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; | 259 | gen6_pte_t pte = GEN6_PTE_VALID; |
| 262 | pte |= GEN6_PTE_ADDR_ENCODE(addr); | 260 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
| 263 | 261 | ||
| 264 | switch (level) { | 262 | switch (level) { |
| @@ -280,9 +278,9 @@ static gen6_pte_t ivb_pte_encode(dma_addr_t addr, | |||
| 280 | 278 | ||
| 281 | static gen6_pte_t byt_pte_encode(dma_addr_t addr, | 279 | static gen6_pte_t byt_pte_encode(dma_addr_t addr, |
| 282 | enum i915_cache_level level, | 280 | enum i915_cache_level level, |
| 283 | bool valid, u32 flags) | 281 | u32 flags) |
| 284 | { | 282 | { |
| 285 | gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; | 283 | gen6_pte_t pte = GEN6_PTE_VALID; |
| 286 | pte |= GEN6_PTE_ADDR_ENCODE(addr); | 284 | pte |= GEN6_PTE_ADDR_ENCODE(addr); |
| 287 | 285 | ||
| 288 | if (!(flags & PTE_READ_ONLY)) | 286 | if (!(flags & PTE_READ_ONLY)) |
| @@ -296,9 +294,9 @@ static gen6_pte_t byt_pte_encode(dma_addr_t addr, | |||
| 296 | 294 | ||
| 297 | static gen6_pte_t hsw_pte_encode(dma_addr_t addr, | 295 | static gen6_pte_t hsw_pte_encode(dma_addr_t addr, |
| 298 | enum i915_cache_level level, | 296 | enum i915_cache_level level, |
| 299 | bool valid, u32 unused) | 297 | u32 unused) |
| 300 | { | 298 | { |
| 301 | gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; | 299 | gen6_pte_t pte = GEN6_PTE_VALID; |
| 302 | pte |= HSW_PTE_ADDR_ENCODE(addr); | 300 | pte |= HSW_PTE_ADDR_ENCODE(addr); |
| 303 | 301 | ||
| 304 | if (level != I915_CACHE_NONE) | 302 | if (level != I915_CACHE_NONE) |
| @@ -309,9 +307,9 @@ static gen6_pte_t hsw_pte_encode(dma_addr_t addr, | |||
| 309 | 307 | ||
| 310 | static gen6_pte_t iris_pte_encode(dma_addr_t addr, | 308 | static gen6_pte_t iris_pte_encode(dma_addr_t addr, |
| 311 | enum i915_cache_level level, | 309 | enum i915_cache_level level, |
| 312 | bool valid, u32 unused) | 310 | u32 unused) |
| 313 | { | 311 | { |
| 314 | gen6_pte_t pte = valid ? GEN6_PTE_VALID : 0; | 312 | gen6_pte_t pte = GEN6_PTE_VALID; |
| 315 | pte |= HSW_PTE_ADDR_ENCODE(addr); | 313 | pte |= HSW_PTE_ADDR_ENCODE(addr); |
| 316 | 314 | ||
| 317 | switch (level) { | 315 | switch (level) { |
| @@ -373,27 +371,29 @@ static void *kmap_page_dma(struct i915_page_dma *p) | |||
| 373 | /* We use the flushing unmap only with ppgtt structures: | 371 | /* We use the flushing unmap only with ppgtt structures: |
| 374 | * page directories, page tables and scratch pages. | 372 | * page directories, page tables and scratch pages. |
| 375 | */ | 373 | */ |
| 376 | static void kunmap_page_dma(struct drm_device *dev, void *vaddr) | 374 | static void kunmap_page_dma(struct drm_i915_private *dev_priv, void *vaddr) |
| 377 | { | 375 | { |
| 378 | /* There are only few exceptions for gen >=6. chv and bxt. | 376 | /* There are only few exceptions for gen >=6. chv and bxt. |
| 379 | * And we are not sure about the latter so play safe for now. | 377 | * And we are not sure about the latter so play safe for now. |
| 380 | */ | 378 | */ |
| 381 | if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) | 379 | if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv)) |
| 382 | drm_clflush_virt_range(vaddr, PAGE_SIZE); | 380 | drm_clflush_virt_range(vaddr, PAGE_SIZE); |
| 383 | 381 | ||
| 384 | kunmap_atomic(vaddr); | 382 | kunmap_atomic(vaddr); |
| 385 | } | 383 | } |
| 386 | 384 | ||
| 387 | #define kmap_px(px) kmap_page_dma(px_base(px)) | 385 | #define kmap_px(px) kmap_page_dma(px_base(px)) |
| 388 | #define kunmap_px(ppgtt, vaddr) kunmap_page_dma((ppgtt)->base.dev, (vaddr)) | 386 | #define kunmap_px(ppgtt, vaddr) \ |
| 387 | kunmap_page_dma(to_i915((ppgtt)->base.dev), (vaddr)) | ||
| 389 | 388 | ||
| 390 | #define setup_px(dev, px) setup_page_dma((dev), px_base(px)) | 389 | #define setup_px(dev, px) setup_page_dma((dev), px_base(px)) |
| 391 | #define cleanup_px(dev, px) cleanup_page_dma((dev), px_base(px)) | 390 | #define cleanup_px(dev, px) cleanup_page_dma((dev), px_base(px)) |
| 392 | #define fill_px(dev, px, v) fill_page_dma((dev), px_base(px), (v)) | 391 | #define fill_px(dev_priv, px, v) fill_page_dma((dev_priv), px_base(px), (v)) |
| 393 | #define fill32_px(dev, px, v) fill_page_dma_32((dev), px_base(px), (v)) | 392 | #define fill32_px(dev_priv, px, v) \ |
| 393 | fill_page_dma_32((dev_priv), px_base(px), (v)) | ||
| 394 | 394 | ||
| 395 | static void fill_page_dma(struct drm_device *dev, struct i915_page_dma *p, | 395 | static void fill_page_dma(struct drm_i915_private *dev_priv, |
| 396 | const uint64_t val) | 396 | struct i915_page_dma *p, const uint64_t val) |
| 397 | { | 397 | { |
| 398 | int i; | 398 | int i; |
| 399 | uint64_t * const vaddr = kmap_page_dma(p); | 399 | uint64_t * const vaddr = kmap_page_dma(p); |
| @@ -401,17 +401,17 @@ static void fill_page_dma(struct drm_device *dev, struct i915_page_dma *p, | |||
| 401 | for (i = 0; i < 512; i++) | 401 | for (i = 0; i < 512; i++) |
| 402 | vaddr[i] = val; | 402 | vaddr[i] = val; |
| 403 | 403 | ||
| 404 | kunmap_page_dma(dev, vaddr); | 404 | kunmap_page_dma(dev_priv, vaddr); |
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | static void fill_page_dma_32(struct drm_device *dev, struct i915_page_dma *p, | 407 | static void fill_page_dma_32(struct drm_i915_private *dev_priv, |
| 408 | const uint32_t val32) | 408 | struct i915_page_dma *p, const uint32_t val32) |
| 409 | { | 409 | { |
| 410 | uint64_t v = val32; | 410 | uint64_t v = val32; |
| 411 | 411 | ||
| 412 | v = v << 32 | val32; | 412 | v = v << 32 | val32; |
| 413 | 413 | ||
| 414 | fill_page_dma(dev, p, v); | 414 | fill_page_dma(dev_priv, p, v); |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | static int | 417 | static int |
| @@ -472,9 +472,9 @@ static void gen8_initialize_pt(struct i915_address_space *vm, | |||
| 472 | gen8_pte_t scratch_pte; | 472 | gen8_pte_t scratch_pte; |
| 473 | 473 | ||
| 474 | scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, | 474 | scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, |
| 475 | I915_CACHE_LLC, true); | 475 | I915_CACHE_LLC); |
| 476 | 476 | ||
| 477 | fill_px(vm->dev, pt, scratch_pte); | 477 | fill_px(to_i915(vm->dev), pt, scratch_pte); |
| 478 | } | 478 | } |
| 479 | 479 | ||
| 480 | static void gen6_initialize_pt(struct i915_address_space *vm, | 480 | static void gen6_initialize_pt(struct i915_address_space *vm, |
| @@ -485,9 +485,9 @@ static void gen6_initialize_pt(struct i915_address_space *vm, | |||
| 485 | WARN_ON(vm->scratch_page.daddr == 0); | 485 | WARN_ON(vm->scratch_page.daddr == 0); |
| 486 | 486 | ||
| 487 | scratch_pte = vm->pte_encode(vm->scratch_page.daddr, | 487 | scratch_pte = vm->pte_encode(vm->scratch_page.daddr, |
| 488 | I915_CACHE_LLC, true, 0); | 488 | I915_CACHE_LLC, 0); |
| 489 | 489 | ||
| 490 | fill32_px(vm->dev, pt, scratch_pte); | 490 | fill32_px(to_i915(vm->dev), pt, scratch_pte); |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | static struct i915_page_directory *alloc_pd(struct drm_device *dev) | 493 | static struct i915_page_directory *alloc_pd(struct drm_device *dev) |
| @@ -534,7 +534,7 @@ static void gen8_initialize_pd(struct i915_address_space *vm, | |||
| 534 | 534 | ||
| 535 | scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC); | 535 | scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt), I915_CACHE_LLC); |
| 536 | 536 | ||
| 537 | fill_px(vm->dev, pd, scratch_pde); | 537 | fill_px(to_i915(vm->dev), pd, scratch_pde); |
| 538 | } | 538 | } |
| 539 | 539 | ||
| 540 | static int __pdp_init(struct drm_device *dev, | 540 | static int __pdp_init(struct drm_device *dev, |
| @@ -615,7 +615,7 @@ static void gen8_initialize_pdp(struct i915_address_space *vm, | |||
| 615 | 615 | ||
| 616 | scratch_pdpe = gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC); | 616 | scratch_pdpe = gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC); |
| 617 | 617 | ||
| 618 | fill_px(vm->dev, pdp, scratch_pdpe); | 618 | fill_px(to_i915(vm->dev), pdp, scratch_pdpe); |
| 619 | } | 619 | } |
| 620 | 620 | ||
| 621 | static void gen8_initialize_pml4(struct i915_address_space *vm, | 621 | static void gen8_initialize_pml4(struct i915_address_space *vm, |
| @@ -626,7 +626,7 @@ static void gen8_initialize_pml4(struct i915_address_space *vm, | |||
| 626 | scratch_pml4e = gen8_pml4e_encode(px_dma(vm->scratch_pdp), | 626 | scratch_pml4e = gen8_pml4e_encode(px_dma(vm->scratch_pdp), |
| 627 | I915_CACHE_LLC); | 627 | I915_CACHE_LLC); |
| 628 | 628 | ||
| 629 | fill_px(vm->dev, pml4, scratch_pml4e); | 629 | fill_px(to_i915(vm->dev), pml4, scratch_pml4e); |
| 630 | } | 630 | } |
| 631 | 631 | ||
| 632 | static void | 632 | static void |
| @@ -706,85 +706,157 @@ static int gen8_48b_mm_switch(struct i915_hw_ppgtt *ppgtt, | |||
| 706 | return gen8_write_pdp(req, 0, px_dma(&ppgtt->pml4)); | 706 | return gen8_write_pdp(req, 0, px_dma(&ppgtt->pml4)); |
| 707 | } | 707 | } |
| 708 | 708 | ||
| 709 | static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm, | 709 | /* Removes entries from a single page table, releasing it if it's empty. |
| 710 | struct i915_page_directory_pointer *pdp, | 710 | * Caller can use the return value to update higher-level entries. |
| 711 | uint64_t start, | 711 | */ |
| 712 | uint64_t length, | 712 | static bool gen8_ppgtt_clear_pt(struct i915_address_space *vm, |
| 713 | gen8_pte_t scratch_pte) | 713 | struct i915_page_table *pt, |
| 714 | uint64_t start, | ||
| 715 | uint64_t length) | ||
| 714 | { | 716 | { |
| 715 | struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); | 717 | struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); |
| 718 | unsigned int pte_start = gen8_pte_index(start); | ||
| 719 | unsigned int num_entries = gen8_pte_count(start, length); | ||
| 720 | uint64_t pte; | ||
| 716 | gen8_pte_t *pt_vaddr; | 721 | gen8_pte_t *pt_vaddr; |
| 717 | unsigned pdpe = gen8_pdpe_index(start); | 722 | gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, |
| 718 | unsigned pde = gen8_pde_index(start); | 723 | I915_CACHE_LLC); |
| 719 | unsigned pte = gen8_pte_index(start); | ||
| 720 | unsigned num_entries = length >> PAGE_SHIFT; | ||
| 721 | unsigned last_pte, i; | ||
| 722 | 724 | ||
| 723 | if (WARN_ON(!pdp)) | 725 | if (WARN_ON(!px_page(pt))) |
| 724 | return; | 726 | return false; |
| 725 | 727 | ||
| 726 | while (num_entries) { | 728 | bitmap_clear(pt->used_ptes, pte_start, num_entries); |
| 727 | struct i915_page_directory *pd; | ||
| 728 | struct i915_page_table *pt; | ||
| 729 | 729 | ||
| 730 | if (WARN_ON(!pdp->page_directory[pdpe])) | 730 | if (bitmap_empty(pt->used_ptes, GEN8_PTES)) { |
| 731 | break; | 731 | free_pt(vm->dev, pt); |
| 732 | return true; | ||
| 733 | } | ||
| 732 | 734 | ||
| 733 | pd = pdp->page_directory[pdpe]; | 735 | pt_vaddr = kmap_px(pt); |
| 734 | 736 | ||
| 735 | if (WARN_ON(!pd->page_table[pde])) | 737 | for (pte = pte_start; pte < num_entries; pte++) |
| 736 | break; | 738 | pt_vaddr[pte] = scratch_pte; |
| 737 | 739 | ||
| 738 | pt = pd->page_table[pde]; | 740 | kunmap_px(ppgtt, pt_vaddr); |
| 739 | 741 | ||
| 740 | if (WARN_ON(!px_page(pt))) | 742 | return false; |
| 741 | break; | 743 | } |
| 742 | 744 | ||
| 743 | last_pte = pte + num_entries; | 745 | /* Removes entries from a single page dir, releasing it if it's empty. |
| 744 | if (last_pte > GEN8_PTES) | 746 | * Caller can use the return value to update higher-level entries |
| 745 | last_pte = GEN8_PTES; | 747 | */ |
| 748 | static bool gen8_ppgtt_clear_pd(struct i915_address_space *vm, | ||
| 749 | struct i915_page_directory *pd, | ||
| 750 | uint64_t start, | ||
| 751 | uint64_t length) | ||
| 752 | { | ||
| 753 | struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); | ||
| 754 | struct i915_page_table *pt; | ||
| 755 | uint64_t pde; | ||
| 756 | gen8_pde_t *pde_vaddr; | ||
| 757 | gen8_pde_t scratch_pde = gen8_pde_encode(px_dma(vm->scratch_pt), | ||
| 758 | I915_CACHE_LLC); | ||
| 746 | 759 | ||
| 747 | pt_vaddr = kmap_px(pt); | 760 | gen8_for_each_pde(pt, pd, start, length, pde) { |
| 761 | if (WARN_ON(!pd->page_table[pde])) | ||
| 762 | break; | ||
| 748 | 763 | ||
| 749 | for (i = pte; i < last_pte; i++) { | 764 | if (gen8_ppgtt_clear_pt(vm, pt, start, length)) { |
| 750 | pt_vaddr[i] = scratch_pte; | 765 | __clear_bit(pde, pd->used_pdes); |
| 751 | num_entries--; | 766 | pde_vaddr = kmap_px(pd); |
| 767 | pde_vaddr[pde] = scratch_pde; | ||
| 768 | kunmap_px(ppgtt, pde_vaddr); | ||
| 752 | } | 769 | } |
| 770 | } | ||
| 753 | 771 | ||
| 754 | kunmap_px(ppgtt, pt_vaddr); | 772 | if (bitmap_empty(pd->used_pdes, I915_PDES)) { |
| 773 | free_pd(vm->dev, pd); | ||
| 774 | return true; | ||
| 775 | } | ||
| 776 | |||
| 777 | return false; | ||
| 778 | } | ||
| 755 | 779 | ||
| 756 | pte = 0; | 780 | /* Removes entries from a single page dir pointer, releasing it if it's empty. |
| 757 | if (++pde == I915_PDES) { | 781 | * Caller can use the return value to update higher-level entries |
| 758 | if (++pdpe == I915_PDPES_PER_PDP(vm->dev)) | 782 | */ |
| 759 | break; | 783 | static bool gen8_ppgtt_clear_pdp(struct i915_address_space *vm, |
| 760 | pde = 0; | 784 | struct i915_page_directory_pointer *pdp, |
| 785 | uint64_t start, | ||
| 786 | uint64_t length) | ||
| 787 | { | ||
| 788 | struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); | ||
| 789 | struct i915_page_directory *pd; | ||
| 790 | uint64_t pdpe; | ||
| 791 | gen8_ppgtt_pdpe_t *pdpe_vaddr; | ||
| 792 | gen8_ppgtt_pdpe_t scratch_pdpe = | ||
| 793 | gen8_pdpe_encode(px_dma(vm->scratch_pd), I915_CACHE_LLC); | ||
| 794 | |||
| 795 | gen8_for_each_pdpe(pd, pdp, start, length, pdpe) { | ||
| 796 | if (WARN_ON(!pdp->page_directory[pdpe])) | ||
| 797 | break; | ||
| 798 | |||
| 799 | if (gen8_ppgtt_clear_pd(vm, pd, start, length)) { | ||
| 800 | __clear_bit(pdpe, pdp->used_pdpes); | ||
| 801 | if (USES_FULL_48BIT_PPGTT(vm->dev)) { | ||
| 802 | pdpe_vaddr = kmap_px(pdp); | ||
| 803 | pdpe_vaddr[pdpe] = scratch_pdpe; | ||
| 804 | kunmap_px(ppgtt, pdpe_vaddr); | ||
| 805 | } | ||
| 761 | } | 806 | } |
| 762 | } | 807 | } |
| 808 | |||
| 809 | if (USES_FULL_48BIT_PPGTT(vm->dev) && | ||
| 810 | bitmap_empty(pdp->used_pdpes, I915_PDPES_PER_PDP(vm->dev))) { | ||
| 811 | free_pdp(vm->dev, pdp); | ||
| 812 | return true; | ||
| 813 | } | ||
| 814 | |||
| 815 | return false; | ||
| 763 | } | 816 | } |
| 764 | 817 | ||
| 765 | static void gen8_ppgtt_clear_range(struct i915_address_space *vm, | 818 | /* Removes entries from a single pml4. |
| 766 | uint64_t start, | 819 | * This is the top-level structure in 4-level page tables used on gen8+. |
| 767 | uint64_t length, | 820 | * Empty entries are always scratch pml4e. |
| 768 | bool use_scratch) | 821 | */ |
| 822 | static void gen8_ppgtt_clear_pml4(struct i915_address_space *vm, | ||
| 823 | struct i915_pml4 *pml4, | ||
| 824 | uint64_t start, | ||
| 825 | uint64_t length) | ||
| 769 | { | 826 | { |
| 770 | struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); | 827 | struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); |
| 771 | gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, | 828 | struct i915_page_directory_pointer *pdp; |
| 772 | I915_CACHE_LLC, use_scratch); | 829 | uint64_t pml4e; |
| 830 | gen8_ppgtt_pml4e_t *pml4e_vaddr; | ||
| 831 | gen8_ppgtt_pml4e_t scratch_pml4e = | ||
| 832 | gen8_pml4e_encode(px_dma(vm->scratch_pdp), I915_CACHE_LLC); | ||
| 773 | 833 | ||
| 774 | if (!USES_FULL_48BIT_PPGTT(vm->dev)) { | 834 | GEM_BUG_ON(!USES_FULL_48BIT_PPGTT(vm->dev)); |
| 775 | gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length, | ||
| 776 | scratch_pte); | ||
| 777 | } else { | ||
| 778 | uint64_t pml4e; | ||
| 779 | struct i915_page_directory_pointer *pdp; | ||
| 780 | 835 | ||
| 781 | gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) { | 836 | gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) { |
| 782 | gen8_ppgtt_clear_pte_range(vm, pdp, start, length, | 837 | if (WARN_ON(!pml4->pdps[pml4e])) |
| 783 | scratch_pte); | 838 | break; |
| 839 | |||
| 840 | if (gen8_ppgtt_clear_pdp(vm, pdp, start, length)) { | ||
| 841 | __clear_bit(pml4e, pml4->used_pml4es); | ||
| 842 | pml4e_vaddr = kmap_px(pml4); | ||
| 843 | pml4e_vaddr[pml4e] = scratch_pml4e; | ||
| 844 | kunmap_px(ppgtt, pml4e_vaddr); | ||
| 784 | } | 845 | } |
| 785 | } | 846 | } |
| 786 | } | 847 | } |
| 787 | 848 | ||
| 849 | static void gen8_ppgtt_clear_range(struct i915_address_space *vm, | ||
| 850 | uint64_t start, uint64_t length) | ||
| 851 | { | ||
| 852 | struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); | ||
| 853 | |||
| 854 | if (USES_FULL_48BIT_PPGTT(vm->dev)) | ||
| 855 | gen8_ppgtt_clear_pml4(vm, &ppgtt->pml4, start, length); | ||
| 856 | else | ||
| 857 | gen8_ppgtt_clear_pdp(vm, &ppgtt->pdp, start, length); | ||
| 858 | } | ||
| 859 | |||
| 788 | static void | 860 | static void |
| 789 | gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, | 861 | gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, |
| 790 | struct i915_page_directory_pointer *pdp, | 862 | struct i915_page_directory_pointer *pdp, |
| @@ -809,7 +881,7 @@ gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm, | |||
| 809 | 881 | ||
| 810 | pt_vaddr[pte] = | 882 | pt_vaddr[pte] = |
| 811 | gen8_pte_encode(sg_page_iter_dma_address(sg_iter), | 883 | gen8_pte_encode(sg_page_iter_dma_address(sg_iter), |
| 812 | cache_level, true); | 884 | cache_level); |
| 813 | if (++pte == GEN8_PTES) { | 885 | if (++pte == GEN8_PTES) { |
| 814 | kunmap_px(ppgtt, pt_vaddr); | 886 | kunmap_px(ppgtt, pt_vaddr); |
| 815 | pt_vaddr = NULL; | 887 | pt_vaddr = NULL; |
| @@ -1452,7 +1524,7 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) | |||
| 1452 | uint64_t start = ppgtt->base.start; | 1524 | uint64_t start = ppgtt->base.start; |
| 1453 | uint64_t length = ppgtt->base.total; | 1525 | uint64_t length = ppgtt->base.total; |
| 1454 | gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, | 1526 | gen8_pte_t scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, |
| 1455 | I915_CACHE_LLC, true); | 1527 | I915_CACHE_LLC); |
| 1456 | 1528 | ||
| 1457 | if (!USES_FULL_48BIT_PPGTT(vm->dev)) { | 1529 | if (!USES_FULL_48BIT_PPGTT(vm->dev)) { |
| 1458 | gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m); | 1530 | gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m); |
| @@ -1569,7 +1641,7 @@ static void gen6_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m) | |||
| 1569 | uint32_t start = ppgtt->base.start, length = ppgtt->base.total; | 1641 | uint32_t start = ppgtt->base.start, length = ppgtt->base.total; |
| 1570 | 1642 | ||
| 1571 | scratch_pte = vm->pte_encode(vm->scratch_page.daddr, | 1643 | scratch_pte = vm->pte_encode(vm->scratch_page.daddr, |
| 1572 | I915_CACHE_LLC, true, 0); | 1644 | I915_CACHE_LLC, 0); |
| 1573 | 1645 | ||
| 1574 | gen6_for_each_pde(unused, &ppgtt->pd, start, length, pde) { | 1646 | gen6_for_each_pde(unused, &ppgtt->pd, start, length, pde) { |
| 1575 | u32 expected; | 1647 | u32 expected; |
| @@ -1728,8 +1800,9 @@ static void gen8_ppgtt_enable(struct drm_device *dev) | |||
| 1728 | { | 1800 | { |
| 1729 | struct drm_i915_private *dev_priv = to_i915(dev); | 1801 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 1730 | struct intel_engine_cs *engine; | 1802 | struct intel_engine_cs *engine; |
| 1803 | enum intel_engine_id id; | ||
| 1731 | 1804 | ||
| 1732 | for_each_engine(engine, dev_priv) { | 1805 | for_each_engine(engine, dev_priv, id) { |
| 1733 | u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0; | 1806 | u32 four_level = USES_FULL_48BIT_PPGTT(dev) ? GEN8_GFX_PPGTT_48B : 0; |
| 1734 | I915_WRITE(RING_MODE_GEN7(engine), | 1807 | I915_WRITE(RING_MODE_GEN7(engine), |
| 1735 | _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level)); | 1808 | _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE | four_level)); |
| @@ -1741,12 +1814,13 @@ static void gen7_ppgtt_enable(struct drm_device *dev) | |||
| 1741 | struct drm_i915_private *dev_priv = to_i915(dev); | 1814 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 1742 | struct intel_engine_cs *engine; | 1815 | struct intel_engine_cs *engine; |
| 1743 | uint32_t ecochk, ecobits; | 1816 | uint32_t ecochk, ecobits; |
| 1817 | enum intel_engine_id id; | ||
| 1744 | 1818 | ||
| 1745 | ecobits = I915_READ(GAC_ECO_BITS); | 1819 | ecobits = I915_READ(GAC_ECO_BITS); |
| 1746 | I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B); | 1820 | I915_WRITE(GAC_ECO_BITS, ecobits | ECOBITS_PPGTT_CACHE64B); |
| 1747 | 1821 | ||
| 1748 | ecochk = I915_READ(GAM_ECOCHK); | 1822 | ecochk = I915_READ(GAM_ECOCHK); |
| 1749 | if (IS_HASWELL(dev)) { | 1823 | if (IS_HASWELL(dev_priv)) { |
| 1750 | ecochk |= ECOCHK_PPGTT_WB_HSW; | 1824 | ecochk |= ECOCHK_PPGTT_WB_HSW; |
| 1751 | } else { | 1825 | } else { |
| 1752 | ecochk |= ECOCHK_PPGTT_LLC_IVB; | 1826 | ecochk |= ECOCHK_PPGTT_LLC_IVB; |
| @@ -1754,7 +1828,7 @@ static void gen7_ppgtt_enable(struct drm_device *dev) | |||
| 1754 | } | 1828 | } |
| 1755 | I915_WRITE(GAM_ECOCHK, ecochk); | 1829 | I915_WRITE(GAM_ECOCHK, ecochk); |
| 1756 | 1830 | ||
| 1757 | for_each_engine(engine, dev_priv) { | 1831 | for_each_engine(engine, dev_priv, id) { |
| 1758 | /* GFX_MODE is per-ring on gen7+ */ | 1832 | /* GFX_MODE is per-ring on gen7+ */ |
| 1759 | I915_WRITE(RING_MODE_GEN7(engine), | 1833 | I915_WRITE(RING_MODE_GEN7(engine), |
| 1760 | _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); | 1834 | _MASKED_BIT_ENABLE(GFX_PPGTT_ENABLE)); |
| @@ -1782,8 +1856,7 @@ static void gen6_ppgtt_enable(struct drm_device *dev) | |||
| 1782 | /* PPGTT support for Sandybdrige/Gen6 and later */ | 1856 | /* PPGTT support for Sandybdrige/Gen6 and later */ |
| 1783 | static void gen6_ppgtt_clear_range(struct i915_address_space *vm, | 1857 | static void gen6_ppgtt_clear_range(struct i915_address_space *vm, |
| 1784 | uint64_t start, | 1858 | uint64_t start, |
| 1785 | uint64_t length, | 1859 | uint64_t length) |
| 1786 | bool use_scratch) | ||
| 1787 | { | 1860 | { |
| 1788 | struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); | 1861 | struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm); |
| 1789 | gen6_pte_t *pt_vaddr, scratch_pte; | 1862 | gen6_pte_t *pt_vaddr, scratch_pte; |
| @@ -1794,7 +1867,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, | |||
| 1794 | unsigned last_pte, i; | 1867 | unsigned last_pte, i; |
| 1795 | 1868 | ||
| 1796 | scratch_pte = vm->pte_encode(vm->scratch_page.daddr, | 1869 | scratch_pte = vm->pte_encode(vm->scratch_page.daddr, |
| 1797 | I915_CACHE_LLC, true, 0); | 1870 | I915_CACHE_LLC, 0); |
| 1798 | 1871 | ||
| 1799 | while (num_entries) { | 1872 | while (num_entries) { |
| 1800 | last_pte = first_pte + num_entries; | 1873 | last_pte = first_pte + num_entries; |
| @@ -1832,7 +1905,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, | |||
| 1832 | pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]); | 1905 | pt_vaddr = kmap_px(ppgtt->pd.page_table[act_pt]); |
| 1833 | 1906 | ||
| 1834 | pt_vaddr[act_pte] = | 1907 | pt_vaddr[act_pte] = |
| 1835 | vm->pte_encode(addr, cache_level, true, flags); | 1908 | vm->pte_encode(addr, cache_level, flags); |
| 1836 | 1909 | ||
| 1837 | if (++act_pte == GEN6_PTES) { | 1910 | if (++act_pte == GEN6_PTES) { |
| 1838 | kunmap_px(ppgtt, pt_vaddr); | 1911 | kunmap_px(ppgtt, pt_vaddr); |
| @@ -2056,11 +2129,11 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) | |||
| 2056 | int ret; | 2129 | int ret; |
| 2057 | 2130 | ||
| 2058 | ppgtt->base.pte_encode = ggtt->base.pte_encode; | 2131 | ppgtt->base.pte_encode = ggtt->base.pte_encode; |
| 2059 | if (intel_vgpu_active(dev_priv) || IS_GEN6(dev)) | 2132 | if (intel_vgpu_active(dev_priv) || IS_GEN6(dev_priv)) |
| 2060 | ppgtt->switch_mm = gen6_mm_switch; | 2133 | ppgtt->switch_mm = gen6_mm_switch; |
| 2061 | else if (IS_HASWELL(dev)) | 2134 | else if (IS_HASWELL(dev_priv)) |
| 2062 | ppgtt->switch_mm = hsw_mm_switch; | 2135 | ppgtt->switch_mm = hsw_mm_switch; |
| 2063 | else if (IS_GEN7(dev)) | 2136 | else if (IS_GEN7(dev_priv)) |
| 2064 | ppgtt->switch_mm = gen7_mm_switch; | 2137 | ppgtt->switch_mm = gen7_mm_switch; |
| 2065 | else | 2138 | else |
| 2066 | BUG(); | 2139 | BUG(); |
| @@ -2129,13 +2202,13 @@ static void gtt_write_workarounds(struct drm_device *dev) | |||
| 2129 | * workarounds here even if they get overwritten by GPU reset. | 2202 | * workarounds here even if they get overwritten by GPU reset. |
| 2130 | */ | 2203 | */ |
| 2131 | /* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt */ | 2204 | /* WaIncreaseDefaultTLBEntries:chv,bdw,skl,bxt */ |
| 2132 | if (IS_BROADWELL(dev)) | 2205 | if (IS_BROADWELL(dev_priv)) |
| 2133 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW); | 2206 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_BDW); |
| 2134 | else if (IS_CHERRYVIEW(dev)) | 2207 | else if (IS_CHERRYVIEW(dev_priv)) |
| 2135 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV); | 2208 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN8_L3_LRA_1_GPGPU_DEFAULT_VALUE_CHV); |
| 2136 | else if (IS_SKYLAKE(dev)) | 2209 | else if (IS_SKYLAKE(dev_priv)) |
| 2137 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL); | 2210 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL); |
| 2138 | else if (IS_BROXTON(dev)) | 2211 | else if (IS_BROXTON(dev_priv)) |
| 2139 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT); | 2212 | I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT); |
| 2140 | } | 2213 | } |
| 2141 | 2214 | ||
| @@ -2157,6 +2230,8 @@ static int i915_ppgtt_init(struct i915_hw_ppgtt *ppgtt, | |||
| 2157 | 2230 | ||
| 2158 | int i915_ppgtt_init_hw(struct drm_device *dev) | 2231 | int i915_ppgtt_init_hw(struct drm_device *dev) |
| 2159 | { | 2232 | { |
| 2233 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 2234 | |||
| 2160 | gtt_write_workarounds(dev); | 2235 | gtt_write_workarounds(dev); |
| 2161 | 2236 | ||
| 2162 | /* In the case of execlists, PPGTT is enabled by the context descriptor | 2237 | /* In the case of execlists, PPGTT is enabled by the context descriptor |
| @@ -2168,9 +2243,9 @@ int i915_ppgtt_init_hw(struct drm_device *dev) | |||
| 2168 | if (!USES_PPGTT(dev)) | 2243 | if (!USES_PPGTT(dev)) |
| 2169 | return 0; | 2244 | return 0; |
| 2170 | 2245 | ||
| 2171 | if (IS_GEN6(dev)) | 2246 | if (IS_GEN6(dev_priv)) |
| 2172 | gen6_ppgtt_enable(dev); | 2247 | gen6_ppgtt_enable(dev); |
| 2173 | else if (IS_GEN7(dev)) | 2248 | else if (IS_GEN7(dev_priv)) |
| 2174 | gen7_ppgtt_enable(dev); | 2249 | gen7_ppgtt_enable(dev); |
| 2175 | else if (INTEL_INFO(dev)->gen >= 8) | 2250 | else if (INTEL_INFO(dev)->gen >= 8) |
| 2176 | gen8_ppgtt_enable(dev); | 2251 | gen8_ppgtt_enable(dev); |
| @@ -2239,11 +2314,12 @@ static bool needs_idle_maps(struct drm_i915_private *dev_priv) | |||
| 2239 | void i915_check_and_clear_faults(struct drm_i915_private *dev_priv) | 2314 | void i915_check_and_clear_faults(struct drm_i915_private *dev_priv) |
| 2240 | { | 2315 | { |
| 2241 | struct intel_engine_cs *engine; | 2316 | struct intel_engine_cs *engine; |
| 2317 | enum intel_engine_id id; | ||
| 2242 | 2318 | ||
| 2243 | if (INTEL_INFO(dev_priv)->gen < 6) | 2319 | if (INTEL_INFO(dev_priv)->gen < 6) |
| 2244 | return; | 2320 | return; |
| 2245 | 2321 | ||
| 2246 | for_each_engine(engine, dev_priv) { | 2322 | for_each_engine(engine, dev_priv, id) { |
| 2247 | u32 fault_reg; | 2323 | u32 fault_reg; |
| 2248 | fault_reg = I915_READ(RING_FAULT_REG(engine)); | 2324 | fault_reg = I915_READ(RING_FAULT_REG(engine)); |
| 2249 | if (fault_reg & RING_FAULT_VALID) { | 2325 | if (fault_reg & RING_FAULT_VALID) { |
| @@ -2260,7 +2336,10 @@ void i915_check_and_clear_faults(struct drm_i915_private *dev_priv) | |||
| 2260 | fault_reg & ~RING_FAULT_VALID); | 2336 | fault_reg & ~RING_FAULT_VALID); |
| 2261 | } | 2337 | } |
| 2262 | } | 2338 | } |
| 2263 | POSTING_READ(RING_FAULT_REG(&dev_priv->engine[RCS])); | 2339 | |
| 2340 | /* Engine specific init may not have been done till this point. */ | ||
| 2341 | if (dev_priv->engine[RCS]) | ||
| 2342 | POSTING_READ(RING_FAULT_REG(dev_priv->engine[RCS])); | ||
| 2264 | } | 2343 | } |
| 2265 | 2344 | ||
| 2266 | static void i915_ggtt_flush(struct drm_i915_private *dev_priv) | 2345 | static void i915_ggtt_flush(struct drm_i915_private *dev_priv) |
| @@ -2286,8 +2365,7 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev) | |||
| 2286 | 2365 | ||
| 2287 | i915_check_and_clear_faults(dev_priv); | 2366 | i915_check_and_clear_faults(dev_priv); |
| 2288 | 2367 | ||
| 2289 | ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total, | 2368 | ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total); |
| 2290 | true); | ||
| 2291 | 2369 | ||
| 2292 | i915_ggtt_flush(dev_priv); | 2370 | i915_ggtt_flush(dev_priv); |
| 2293 | } | 2371 | } |
| @@ -2321,7 +2399,7 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm, | |||
| 2321 | 2399 | ||
| 2322 | rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); | 2400 | rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); |
| 2323 | 2401 | ||
| 2324 | gen8_set_pte(pte, gen8_pte_encode(addr, level, true)); | 2402 | gen8_set_pte(pte, gen8_pte_encode(addr, level)); |
| 2325 | 2403 | ||
| 2326 | I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); | 2404 | I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); |
| 2327 | POSTING_READ(GFX_FLSH_CNTL_GEN6); | 2405 | POSTING_READ(GFX_FLSH_CNTL_GEN6); |
| @@ -2348,7 +2426,7 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm, | |||
| 2348 | gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT); | 2426 | gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT); |
| 2349 | 2427 | ||
| 2350 | for_each_sgt_dma(addr, sgt_iter, st) { | 2428 | for_each_sgt_dma(addr, sgt_iter, st) { |
| 2351 | gtt_entry = gen8_pte_encode(addr, level, true); | 2429 | gtt_entry = gen8_pte_encode(addr, level); |
| 2352 | gen8_set_pte(>t_entries[i++], gtt_entry); | 2430 | gen8_set_pte(>t_entries[i++], gtt_entry); |
| 2353 | } | 2431 | } |
| 2354 | 2432 | ||
| @@ -2412,7 +2490,7 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm, | |||
| 2412 | 2490 | ||
| 2413 | rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); | 2491 | rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv); |
| 2414 | 2492 | ||
| 2415 | iowrite32(vm->pte_encode(addr, level, true, flags), pte); | 2493 | iowrite32(vm->pte_encode(addr, level, flags), pte); |
| 2416 | 2494 | ||
| 2417 | I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); | 2495 | I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN); |
| 2418 | POSTING_READ(GFX_FLSH_CNTL_GEN6); | 2496 | POSTING_READ(GFX_FLSH_CNTL_GEN6); |
| @@ -2445,7 +2523,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, | |||
| 2445 | gtt_entries = (gen6_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT); | 2523 | gtt_entries = (gen6_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT); |
| 2446 | 2524 | ||
| 2447 | for_each_sgt_dma(addr, sgt_iter, st) { | 2525 | for_each_sgt_dma(addr, sgt_iter, st) { |
| 2448 | gtt_entry = vm->pte_encode(addr, level, true, flags); | 2526 | gtt_entry = vm->pte_encode(addr, level, flags); |
| 2449 | iowrite32(gtt_entry, >t_entries[i++]); | 2527 | iowrite32(gtt_entry, >t_entries[i++]); |
| 2450 | } | 2528 | } |
| 2451 | 2529 | ||
| @@ -2469,16 +2547,12 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, | |||
| 2469 | } | 2547 | } |
| 2470 | 2548 | ||
| 2471 | static void nop_clear_range(struct i915_address_space *vm, | 2549 | static void nop_clear_range(struct i915_address_space *vm, |
| 2472 | uint64_t start, | 2550 | uint64_t start, uint64_t length) |
| 2473 | uint64_t length, | ||
| 2474 | bool use_scratch) | ||
| 2475 | { | 2551 | { |
| 2476 | } | 2552 | } |
| 2477 | 2553 | ||
| 2478 | static void gen8_ggtt_clear_range(struct i915_address_space *vm, | 2554 | static void gen8_ggtt_clear_range(struct i915_address_space *vm, |
| 2479 | uint64_t start, | 2555 | uint64_t start, uint64_t length) |
| 2480 | uint64_t length, | ||
| 2481 | bool use_scratch) | ||
| 2482 | { | 2556 | { |
| 2483 | struct drm_i915_private *dev_priv = to_i915(vm->dev); | 2557 | struct drm_i915_private *dev_priv = to_i915(vm->dev); |
| 2484 | struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); | 2558 | struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); |
| @@ -2498,8 +2572,7 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, | |||
| 2498 | num_entries = max_entries; | 2572 | num_entries = max_entries; |
| 2499 | 2573 | ||
| 2500 | scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, | 2574 | scratch_pte = gen8_pte_encode(vm->scratch_page.daddr, |
| 2501 | I915_CACHE_LLC, | 2575 | I915_CACHE_LLC); |
| 2502 | use_scratch); | ||
| 2503 | for (i = 0; i < num_entries; i++) | 2576 | for (i = 0; i < num_entries; i++) |
| 2504 | gen8_set_pte(>t_base[i], scratch_pte); | 2577 | gen8_set_pte(>t_base[i], scratch_pte); |
| 2505 | readl(gtt_base); | 2578 | readl(gtt_base); |
| @@ -2509,8 +2582,7 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm, | |||
| 2509 | 2582 | ||
| 2510 | static void gen6_ggtt_clear_range(struct i915_address_space *vm, | 2583 | static void gen6_ggtt_clear_range(struct i915_address_space *vm, |
| 2511 | uint64_t start, | 2584 | uint64_t start, |
| 2512 | uint64_t length, | 2585 | uint64_t length) |
| 2513 | bool use_scratch) | ||
| 2514 | { | 2586 | { |
| 2515 | struct drm_i915_private *dev_priv = to_i915(vm->dev); | 2587 | struct drm_i915_private *dev_priv = to_i915(vm->dev); |
| 2516 | struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); | 2588 | struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm); |
| @@ -2530,7 +2602,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, | |||
| 2530 | num_entries = max_entries; | 2602 | num_entries = max_entries; |
| 2531 | 2603 | ||
| 2532 | scratch_pte = vm->pte_encode(vm->scratch_page.daddr, | 2604 | scratch_pte = vm->pte_encode(vm->scratch_page.daddr, |
| 2533 | I915_CACHE_LLC, use_scratch, 0); | 2605 | I915_CACHE_LLC, 0); |
| 2534 | 2606 | ||
| 2535 | for (i = 0; i < num_entries; i++) | 2607 | for (i = 0; i < num_entries; i++) |
| 2536 | iowrite32(scratch_pte, >t_base[i]); | 2608 | iowrite32(scratch_pte, >t_base[i]); |
| @@ -2577,8 +2649,7 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm, | |||
| 2577 | 2649 | ||
| 2578 | static void i915_ggtt_clear_range(struct i915_address_space *vm, | 2650 | static void i915_ggtt_clear_range(struct i915_address_space *vm, |
| 2579 | uint64_t start, | 2651 | uint64_t start, |
| 2580 | uint64_t length, | 2652 | uint64_t length) |
| 2581 | bool unused) | ||
| 2582 | { | 2653 | { |
| 2583 | struct drm_i915_private *dev_priv = to_i915(vm->dev); | 2654 | struct drm_i915_private *dev_priv = to_i915(vm->dev); |
| 2584 | unsigned first_entry = start >> PAGE_SHIFT; | 2655 | unsigned first_entry = start >> PAGE_SHIFT; |
| @@ -2662,13 +2733,11 @@ static void ggtt_unbind_vma(struct i915_vma *vma) | |||
| 2662 | 2733 | ||
| 2663 | if (vma->flags & I915_VMA_GLOBAL_BIND) | 2734 | if (vma->flags & I915_VMA_GLOBAL_BIND) |
| 2664 | vma->vm->clear_range(vma->vm, | 2735 | vma->vm->clear_range(vma->vm, |
| 2665 | vma->node.start, size, | 2736 | vma->node.start, size); |
| 2666 | true); | ||
| 2667 | 2737 | ||
| 2668 | if (vma->flags & I915_VMA_LOCAL_BIND && appgtt) | 2738 | if (vma->flags & I915_VMA_LOCAL_BIND && appgtt) |
| 2669 | appgtt->base.clear_range(&appgtt->base, | 2739 | appgtt->base.clear_range(&appgtt->base, |
| 2670 | vma->node.start, size, | 2740 | vma->node.start, size); |
| 2671 | true); | ||
| 2672 | } | 2741 | } |
| 2673 | 2742 | ||
| 2674 | void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) | 2743 | void i915_gem_gtt_finish_object(struct drm_i915_gem_object *obj) |
| @@ -2717,6 +2786,7 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) | |||
| 2717 | */ | 2786 | */ |
| 2718 | struct i915_ggtt *ggtt = &dev_priv->ggtt; | 2787 | struct i915_ggtt *ggtt = &dev_priv->ggtt; |
| 2719 | unsigned long hole_start, hole_end; | 2788 | unsigned long hole_start, hole_end; |
| 2789 | struct i915_hw_ppgtt *ppgtt; | ||
| 2720 | struct drm_mm_node *entry; | 2790 | struct drm_mm_node *entry; |
| 2721 | int ret; | 2791 | int ret; |
| 2722 | 2792 | ||
| @@ -2724,45 +2794,48 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) | |||
| 2724 | if (ret) | 2794 | if (ret) |
| 2725 | return ret; | 2795 | return ret; |
| 2726 | 2796 | ||
| 2797 | /* Reserve a mappable slot for our lockless error capture */ | ||
| 2798 | ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm, | ||
| 2799 | &ggtt->error_capture, | ||
| 2800 | 4096, 0, -1, | ||
| 2801 | 0, ggtt->mappable_end, | ||
| 2802 | 0, 0); | ||
| 2803 | if (ret) | ||
| 2804 | return ret; | ||
| 2805 | |||
| 2727 | /* Clear any non-preallocated blocks */ | 2806 | /* Clear any non-preallocated blocks */ |
| 2728 | drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) { | 2807 | drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) { |
| 2729 | DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", | 2808 | DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", |
| 2730 | hole_start, hole_end); | 2809 | hole_start, hole_end); |
| 2731 | ggtt->base.clear_range(&ggtt->base, hole_start, | 2810 | ggtt->base.clear_range(&ggtt->base, hole_start, |
| 2732 | hole_end - hole_start, true); | 2811 | hole_end - hole_start); |
| 2733 | } | 2812 | } |
| 2734 | 2813 | ||
| 2735 | /* And finally clear the reserved guard page */ | 2814 | /* And finally clear the reserved guard page */ |
| 2736 | ggtt->base.clear_range(&ggtt->base, | 2815 | ggtt->base.clear_range(&ggtt->base, |
| 2737 | ggtt->base.total - PAGE_SIZE, PAGE_SIZE, | 2816 | ggtt->base.total - PAGE_SIZE, PAGE_SIZE); |
| 2738 | true); | ||
| 2739 | 2817 | ||
| 2740 | if (USES_PPGTT(dev_priv) && !USES_FULL_PPGTT(dev_priv)) { | 2818 | if (USES_PPGTT(dev_priv) && !USES_FULL_PPGTT(dev_priv)) { |
| 2741 | struct i915_hw_ppgtt *ppgtt; | ||
| 2742 | |||
| 2743 | ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); | 2819 | ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); |
| 2744 | if (!ppgtt) | 2820 | if (!ppgtt) { |
| 2745 | return -ENOMEM; | 2821 | ret = -ENOMEM; |
| 2822 | goto err; | ||
| 2823 | } | ||
| 2746 | 2824 | ||
| 2747 | ret = __hw_ppgtt_init(ppgtt, dev_priv); | 2825 | ret = __hw_ppgtt_init(ppgtt, dev_priv); |
| 2748 | if (ret) { | 2826 | if (ret) |
| 2749 | kfree(ppgtt); | 2827 | goto err_ppgtt; |
| 2750 | return ret; | ||
| 2751 | } | ||
| 2752 | 2828 | ||
| 2753 | if (ppgtt->base.allocate_va_range) | 2829 | if (ppgtt->base.allocate_va_range) { |
| 2754 | ret = ppgtt->base.allocate_va_range(&ppgtt->base, 0, | 2830 | ret = ppgtt->base.allocate_va_range(&ppgtt->base, 0, |
| 2755 | ppgtt->base.total); | 2831 | ppgtt->base.total); |
| 2756 | if (ret) { | 2832 | if (ret) |
| 2757 | ppgtt->base.cleanup(&ppgtt->base); | 2833 | goto err_ppgtt_cleanup; |
| 2758 | kfree(ppgtt); | ||
| 2759 | return ret; | ||
| 2760 | } | 2834 | } |
| 2761 | 2835 | ||
| 2762 | ppgtt->base.clear_range(&ppgtt->base, | 2836 | ppgtt->base.clear_range(&ppgtt->base, |
| 2763 | ppgtt->base.start, | 2837 | ppgtt->base.start, |
| 2764 | ppgtt->base.total, | 2838 | ppgtt->base.total); |
| 2765 | true); | ||
| 2766 | 2839 | ||
| 2767 | dev_priv->mm.aliasing_ppgtt = ppgtt; | 2840 | dev_priv->mm.aliasing_ppgtt = ppgtt; |
| 2768 | WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma); | 2841 | WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma); |
| @@ -2770,6 +2843,14 @@ int i915_gem_init_ggtt(struct drm_i915_private *dev_priv) | |||
| 2770 | } | 2843 | } |
| 2771 | 2844 | ||
| 2772 | return 0; | 2845 | return 0; |
| 2846 | |||
| 2847 | err_ppgtt_cleanup: | ||
| 2848 | ppgtt->base.cleanup(&ppgtt->base); | ||
| 2849 | err_ppgtt: | ||
| 2850 | kfree(ppgtt); | ||
| 2851 | err: | ||
| 2852 | drm_mm_remove_node(&ggtt->error_capture); | ||
| 2853 | return ret; | ||
| 2773 | } | 2854 | } |
| 2774 | 2855 | ||
| 2775 | /** | 2856 | /** |
| @@ -2788,6 +2869,9 @@ void i915_ggtt_cleanup_hw(struct drm_i915_private *dev_priv) | |||
| 2788 | 2869 | ||
| 2789 | i915_gem_cleanup_stolen(&dev_priv->drm); | 2870 | i915_gem_cleanup_stolen(&dev_priv->drm); |
| 2790 | 2871 | ||
| 2872 | if (drm_mm_node_allocated(&ggtt->error_capture)) | ||
| 2873 | drm_mm_remove_node(&ggtt->error_capture); | ||
| 2874 | |||
| 2791 | if (drm_mm_initialized(&ggtt->base.mm)) { | 2875 | if (drm_mm_initialized(&ggtt->base.mm)) { |
| 2792 | intel_vgt_deballoon(dev_priv); | 2876 | intel_vgt_deballoon(dev_priv); |
| 2793 | 2877 | ||
| @@ -2895,7 +2979,7 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) | |||
| 2895 | * resort to an uncached mapping. The WC issue is easily caught by the | 2979 | * resort to an uncached mapping. The WC issue is easily caught by the |
| 2896 | * readback check when writing GTT PTE entries. | 2980 | * readback check when writing GTT PTE entries. |
| 2897 | */ | 2981 | */ |
| 2898 | if (IS_BROXTON(ggtt->base.dev)) | 2982 | if (IS_BROXTON(to_i915(ggtt->base.dev))) |
| 2899 | ggtt->gsm = ioremap_nocache(phys_addr, size); | 2983 | ggtt->gsm = ioremap_nocache(phys_addr, size); |
| 2900 | else | 2984 | else |
| 2901 | ggtt->gsm = ioremap_wc(phys_addr, size); | 2985 | ggtt->gsm = ioremap_wc(phys_addr, size); |
| @@ -3237,8 +3321,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) | |||
| 3237 | i915_check_and_clear_faults(dev_priv); | 3321 | i915_check_and_clear_faults(dev_priv); |
| 3238 | 3322 | ||
| 3239 | /* First fill our portion of the GTT with scratch pages */ | 3323 | /* First fill our portion of the GTT with scratch pages */ |
| 3240 | ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total, | 3324 | ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total); |
| 3241 | true); | ||
| 3242 | 3325 | ||
| 3243 | ggtt->base.closed = true; /* skip rewriting PTE on VMA unbind */ | 3326 | ggtt->base.closed = true; /* skip rewriting PTE on VMA unbind */ |
| 3244 | 3327 | ||
| @@ -3267,7 +3350,7 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev) | |||
| 3267 | ggtt->base.closed = false; | 3350 | ggtt->base.closed = false; |
| 3268 | 3351 | ||
| 3269 | if (INTEL_INFO(dev)->gen >= 8) { | 3352 | if (INTEL_INFO(dev)->gen >= 8) { |
| 3270 | if (IS_CHERRYVIEW(dev) || IS_BROXTON(dev)) | 3353 | if (IS_CHERRYVIEW(dev_priv) || IS_BROXTON(dev_priv)) |
| 3271 | chv_setup_private_ppat(dev_priv); | 3354 | chv_setup_private_ppat(dev_priv); |
| 3272 | else | 3355 | else |
| 3273 | bdw_setup_private_ppat(dev_priv); | 3356 | bdw_setup_private_ppat(dev_priv); |
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index ec78be2f8c77..c241d8143255 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h | |||
| @@ -395,7 +395,7 @@ struct i915_address_space { | |||
| 395 | /* FIXME: Need a more generic return type */ | 395 | /* FIXME: Need a more generic return type */ |
| 396 | gen6_pte_t (*pte_encode)(dma_addr_t addr, | 396 | gen6_pte_t (*pte_encode)(dma_addr_t addr, |
| 397 | enum i915_cache_level level, | 397 | enum i915_cache_level level, |
| 398 | bool valid, u32 flags); /* Create a valid PTE */ | 398 | u32 flags); /* Create a valid PTE */ |
| 399 | /* flags for pte_encode */ | 399 | /* flags for pte_encode */ |
| 400 | #define PTE_READ_ONLY (1<<0) | 400 | #define PTE_READ_ONLY (1<<0) |
| 401 | int (*allocate_va_range)(struct i915_address_space *vm, | 401 | int (*allocate_va_range)(struct i915_address_space *vm, |
| @@ -403,8 +403,7 @@ struct i915_address_space { | |||
| 403 | uint64_t length); | 403 | uint64_t length); |
| 404 | void (*clear_range)(struct i915_address_space *vm, | 404 | void (*clear_range)(struct i915_address_space *vm, |
| 405 | uint64_t start, | 405 | uint64_t start, |
| 406 | uint64_t length, | 406 | uint64_t length); |
| 407 | bool use_scratch); | ||
| 408 | void (*insert_page)(struct i915_address_space *vm, | 407 | void (*insert_page)(struct i915_address_space *vm, |
| 409 | dma_addr_t addr, | 408 | dma_addr_t addr, |
| 410 | uint64_t offset, | 409 | uint64_t offset, |
| @@ -450,6 +449,8 @@ struct i915_ggtt { | |||
| 450 | bool do_idle_maps; | 449 | bool do_idle_maps; |
| 451 | 450 | ||
| 452 | int mtrr; | 451 | int mtrr; |
| 452 | |||
| 453 | struct drm_mm_node error_capture; | ||
| 453 | }; | 454 | }; |
| 454 | 455 | ||
| 455 | struct i915_hw_ppgtt { | 456 | struct i915_hw_ppgtt { |
diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 95b7e9afd5f8..a98c0f42badd 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c | |||
| @@ -72,9 +72,9 @@ render_state_get_rodata(const struct drm_i915_gem_request *req) | |||
| 72 | 72 | ||
| 73 | static int render_state_setup(struct render_state *so) | 73 | static int render_state_setup(struct render_state *so) |
| 74 | { | 74 | { |
| 75 | struct drm_device *dev = so->vma->vm->dev; | 75 | struct drm_i915_private *dev_priv = to_i915(so->vma->vm->dev); |
| 76 | const struct intel_renderstate_rodata *rodata = so->rodata; | 76 | const struct intel_renderstate_rodata *rodata = so->rodata; |
| 77 | const bool has_64bit_reloc = INTEL_GEN(dev) >= 8; | 77 | const bool has_64bit_reloc = INTEL_GEN(dev_priv) >= 8; |
| 78 | unsigned int i = 0, reloc_index = 0; | 78 | unsigned int i = 0, reloc_index = 0; |
| 79 | struct page *page; | 79 | struct page *page; |
| 80 | u32 *d; | 80 | u32 *d; |
| @@ -115,7 +115,7 @@ static int render_state_setup(struct render_state *so) | |||
| 115 | 115 | ||
| 116 | so->aux_batch_offset = i * sizeof(u32); | 116 | so->aux_batch_offset = i * sizeof(u32); |
| 117 | 117 | ||
| 118 | if (HAS_POOLED_EU(dev)) { | 118 | if (HAS_POOLED_EU(dev_priv)) { |
| 119 | /* | 119 | /* |
| 120 | * We always program 3x6 pool config but depending upon which | 120 | * We always program 3x6 pool config but depending upon which |
| 121 | * subslice is disabled HW drops down to appropriate config | 121 | * subslice is disabled HW drops down to appropriate config |
diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 40978bc12ceb..74ede1f53372 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c | |||
| @@ -256,10 +256,11 @@ static int i915_gem_check_wedge(struct drm_i915_private *dev_priv) | |||
| 256 | static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno) | 256 | static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno) |
| 257 | { | 257 | { |
| 258 | struct intel_engine_cs *engine; | 258 | struct intel_engine_cs *engine; |
| 259 | enum intel_engine_id id; | ||
| 259 | int ret; | 260 | int ret; |
| 260 | 261 | ||
| 261 | /* Carefully retire all requests without writing to the rings */ | 262 | /* Carefully retire all requests without writing to the rings */ |
| 262 | for_each_engine(engine, dev_priv) { | 263 | for_each_engine(engine, dev_priv, id) { |
| 263 | ret = intel_engine_idle(engine, | 264 | ret = intel_engine_idle(engine, |
| 264 | I915_WAIT_INTERRUPTIBLE | | 265 | I915_WAIT_INTERRUPTIBLE | |
| 265 | I915_WAIT_LOCKED); | 266 | I915_WAIT_LOCKED); |
| @@ -276,7 +277,7 @@ static int i915_gem_init_seqno(struct drm_i915_private *dev_priv, u32 seqno) | |||
| 276 | } | 277 | } |
| 277 | 278 | ||
| 278 | /* Finally reset hw state */ | 279 | /* Finally reset hw state */ |
| 279 | for_each_engine(engine, dev_priv) | 280 | for_each_engine(engine, dev_priv, id) |
| 280 | intel_engine_init_seqno(engine, seqno); | 281 | intel_engine_init_seqno(engine, seqno); |
| 281 | 282 | ||
| 282 | return 0; | 283 | return 0; |
| @@ -328,6 +329,7 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) | |||
| 328 | 329 | ||
| 329 | switch (state) { | 330 | switch (state) { |
| 330 | case FENCE_COMPLETE: | 331 | case FENCE_COMPLETE: |
| 332 | request->engine->last_submitted_seqno = request->fence.seqno; | ||
| 331 | request->engine->submit_request(request); | 333 | request->engine->submit_request(request); |
| 332 | break; | 334 | break; |
| 333 | 335 | ||
| @@ -641,8 +643,8 @@ void __i915_add_request(struct drm_i915_gem_request *request, bool flush_caches) | |||
| 641 | &request->submitq); | 643 | &request->submitq); |
| 642 | 644 | ||
| 643 | request->emitted_jiffies = jiffies; | 645 | request->emitted_jiffies = jiffies; |
| 644 | request->previous_seqno = engine->last_submitted_seqno; | 646 | request->previous_seqno = engine->last_pending_seqno; |
| 645 | engine->last_submitted_seqno = request->fence.seqno; | 647 | engine->last_pending_seqno = request->fence.seqno; |
| 646 | i915_gem_active_set(&engine->last_request, request); | 648 | i915_gem_active_set(&engine->last_request, request); |
| 647 | list_add_tail(&request->link, &engine->request_list); | 649 | list_add_tail(&request->link, &engine->request_list); |
| 648 | list_add_tail(&request->ring_link, &ring->request_list); | 650 | list_add_tail(&request->ring_link, &ring->request_list); |
diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 1c237d02f30b..de25b6e0a101 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c | |||
| @@ -182,8 +182,9 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, | |||
| 182 | !is_vmalloc_addr(obj->mapping)) | 182 | !is_vmalloc_addr(obj->mapping)) |
| 183 | continue; | 183 | continue; |
| 184 | 184 | ||
| 185 | if ((flags & I915_SHRINK_ACTIVE) == 0 && | 185 | if (!(flags & I915_SHRINK_ACTIVE) && |
| 186 | i915_gem_object_is_active(obj)) | 186 | (i915_gem_object_is_active(obj) || |
| 187 | obj->framebuffer_references)) | ||
| 187 | continue; | 188 | continue; |
| 188 | 189 | ||
| 189 | if (!can_release_pages(obj)) | 190 | if (!can_release_pages(obj)) |
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 59989e8ee5dc..f4f6d3a48b05 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c | |||
| @@ -115,7 +115,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) | |||
| 115 | pci_read_config_dword(pdev, INTEL_BSM, &bsm); | 115 | pci_read_config_dword(pdev, INTEL_BSM, &bsm); |
| 116 | 116 | ||
| 117 | base = bsm & INTEL_BSM_MASK; | 117 | base = bsm & INTEL_BSM_MASK; |
| 118 | } else if (IS_I865G(dev)) { | 118 | } else if (IS_I865G(dev_priv)) { |
| 119 | u32 tseg_size = 0; | 119 | u32 tseg_size = 0; |
| 120 | u16 toud = 0; | 120 | u16 toud = 0; |
| 121 | u8 tmp; | 121 | u8 tmp; |
| @@ -154,7 +154,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) | |||
| 154 | tom = tmp * MB(32); | 154 | tom = tmp * MB(32); |
| 155 | 155 | ||
| 156 | base = tom - tseg_size - ggtt->stolen_size; | 156 | base = tom - tseg_size - ggtt->stolen_size; |
| 157 | } else if (IS_845G(dev)) { | 157 | } else if (IS_845G(dev_priv)) { |
| 158 | u32 tseg_size = 0; | 158 | u32 tseg_size = 0; |
| 159 | u32 tom; | 159 | u32 tom; |
| 160 | u8 tmp; | 160 | u8 tmp; |
| @@ -178,7 +178,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) | |||
| 178 | tom = tmp * MB(32); | 178 | tom = tmp * MB(32); |
| 179 | 179 | ||
| 180 | base = tom - tseg_size - ggtt->stolen_size; | 180 | base = tom - tseg_size - ggtt->stolen_size; |
| 181 | } else if (IS_I830(dev)) { | 181 | } else if (IS_I830(dev_priv)) { |
| 182 | u32 tseg_size = 0; | 182 | u32 tseg_size = 0; |
| 183 | u32 tom; | 183 | u32 tom; |
| 184 | u8 tmp; | 184 | u8 tmp; |
| @@ -204,7 +204,8 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) | |||
| 204 | return 0; | 204 | return 0; |
| 205 | 205 | ||
| 206 | /* make sure we don't clobber the GTT if it's within stolen memory */ | 206 | /* make sure we don't clobber the GTT if it's within stolen memory */ |
| 207 | if (INTEL_INFO(dev)->gen <= 4 && !IS_G33(dev) && !IS_G4X(dev)) { | 207 | if (INTEL_GEN(dev_priv) <= 4 && !IS_G33(dev_priv) && |
| 208 | !IS_G4X(dev_priv)) { | ||
| 208 | struct { | 209 | struct { |
| 209 | u32 start, end; | 210 | u32 start, end; |
| 210 | } stolen[2] = { | 211 | } stolen[2] = { |
| @@ -214,7 +215,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) | |||
| 214 | u64 ggtt_start, ggtt_end; | 215 | u64 ggtt_start, ggtt_end; |
| 215 | 216 | ||
| 216 | ggtt_start = I915_READ(PGTBL_CTL); | 217 | ggtt_start = I915_READ(PGTBL_CTL); |
| 217 | if (IS_GEN4(dev)) | 218 | if (IS_GEN4(dev_priv)) |
| 218 | ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) | | 219 | ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) | |
| 219 | (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28; | 220 | (ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28; |
| 220 | else | 221 | else |
| @@ -270,7 +271,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev) | |||
| 270 | * GEN3 firmware likes to smash pci bridges into the stolen | 271 | * GEN3 firmware likes to smash pci bridges into the stolen |
| 271 | * range. Apparently this works. | 272 | * range. Apparently this works. |
| 272 | */ | 273 | */ |
| 273 | if (r == NULL && !IS_GEN3(dev)) { | 274 | if (r == NULL && !IS_GEN3(dev_priv)) { |
| 274 | DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n", | 275 | DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n", |
| 275 | base, base + (uint32_t)ggtt->stolen_size); | 276 | base, base + (uint32_t)ggtt->stolen_size); |
| 276 | base = 0; | 277 | base = 0; |
| @@ -437,7 +438,7 @@ int i915_gem_init_stolen(struct drm_device *dev) | |||
| 437 | case 3: | 438 | case 3: |
| 438 | break; | 439 | break; |
| 439 | case 4: | 440 | case 4: |
| 440 | if (IS_G4X(dev)) | 441 | if (IS_G4X(dev_priv)) |
| 441 | g4x_get_stolen_reserved(dev_priv, &reserved_base, | 442 | g4x_get_stolen_reserved(dev_priv, &reserved_base, |
| 442 | &reserved_size); | 443 | &reserved_size); |
| 443 | break; | 444 | break; |
| @@ -456,7 +457,7 @@ int i915_gem_init_stolen(struct drm_device *dev) | |||
| 456 | break; | 457 | break; |
| 457 | default: | 458 | default: |
| 458 | if (IS_BROADWELL(dev_priv) || | 459 | if (IS_BROADWELL(dev_priv) || |
| 459 | IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev)) | 460 | IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
| 460 | bdw_get_stolen_reserved(dev_priv, &reserved_base, | 461 | bdw_get_stolen_reserved(dev_priv, &reserved_base, |
| 461 | &reserved_size); | 462 | &reserved_size); |
| 462 | else | 463 | else |
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index a14b1e3d4c78..c21bc0068d20 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
| @@ -62,6 +62,7 @@ | |||
| 62 | static bool | 62 | static bool |
| 63 | i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) | 63 | i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) |
| 64 | { | 64 | { |
| 65 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 65 | int tile_width; | 66 | int tile_width; |
| 66 | 67 | ||
| 67 | /* Linear is always fine */ | 68 | /* Linear is always fine */ |
| @@ -71,8 +72,8 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) | |||
| 71 | if (tiling_mode > I915_TILING_LAST) | 72 | if (tiling_mode > I915_TILING_LAST) |
| 72 | return false; | 73 | return false; |
| 73 | 74 | ||
| 74 | if (IS_GEN2(dev) || | 75 | if (IS_GEN2(dev_priv) || |
| 75 | (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) | 76 | (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev_priv))) |
| 76 | tile_width = 128; | 77 | tile_width = 128; |
| 77 | else | 78 | else |
| 78 | tile_width = 512; | 79 | tile_width = 512; |
| @@ -90,7 +91,7 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) | |||
| 90 | if (stride > 8192) | 91 | if (stride > 8192) |
| 91 | return false; | 92 | return false; |
| 92 | 93 | ||
| 93 | if (IS_GEN3(dev)) { | 94 | if (IS_GEN3(dev_priv)) { |
| 94 | if (size > I830_FENCE_MAX_SIZE_VAL << 20) | 95 | if (size > I830_FENCE_MAX_SIZE_VAL << 20) |
| 95 | return false; | 96 | return false; |
| 96 | } else { | 97 | } else { |
diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index e537930c64b5..c6f780f5abc9 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c | |||
| @@ -508,6 +508,10 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) | |||
| 508 | pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY); | 508 | pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY); |
| 509 | if (pvec != NULL) { | 509 | if (pvec != NULL) { |
| 510 | struct mm_struct *mm = obj->userptr.mm->mm; | 510 | struct mm_struct *mm = obj->userptr.mm->mm; |
| 511 | unsigned int flags = 0; | ||
| 512 | |||
| 513 | if (!obj->userptr.read_only) | ||
| 514 | flags |= FOLL_WRITE; | ||
| 511 | 515 | ||
| 512 | ret = -EFAULT; | 516 | ret = -EFAULT; |
| 513 | if (atomic_inc_not_zero(&mm->mm_users)) { | 517 | if (atomic_inc_not_zero(&mm->mm_users)) { |
| @@ -517,7 +521,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) | |||
| 517 | (work->task, mm, | 521 | (work->task, mm, |
| 518 | obj->userptr.ptr + pinned * PAGE_SIZE, | 522 | obj->userptr.ptr + pinned * PAGE_SIZE, |
| 519 | npages - pinned, | 523 | npages - pinned, |
| 520 | !obj->userptr.read_only, 0, | 524 | flags, |
| 521 | pvec + pinned, NULL); | 525 | pvec + pinned, NULL); |
| 522 | if (ret < 0) | 526 | if (ret < 0) |
| 523 | break; | 527 | break; |
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 334f15df7c8d..242b9a927899 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c | |||
| @@ -28,6 +28,8 @@ | |||
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #include <generated/utsrelease.h> | 30 | #include <generated/utsrelease.h> |
| 31 | #include <linux/stop_machine.h> | ||
| 32 | #include <linux/zlib.h> | ||
| 31 | #include "i915_drv.h" | 33 | #include "i915_drv.h" |
| 32 | 34 | ||
| 33 | static const char *engine_str(int engine) | 35 | static const char *engine_str(int engine) |
| @@ -172,6 +174,110 @@ static void i915_error_puts(struct drm_i915_error_state_buf *e, | |||
| 172 | #define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__) | 174 | #define err_printf(e, ...) i915_error_printf(e, __VA_ARGS__) |
| 173 | #define err_puts(e, s) i915_error_puts(e, s) | 175 | #define err_puts(e, s) i915_error_puts(e, s) |
| 174 | 176 | ||
| 177 | #ifdef CONFIG_DRM_I915_COMPRESS_ERROR | ||
| 178 | |||
| 179 | static bool compress_init(struct z_stream_s *zstream) | ||
| 180 | { | ||
| 181 | memset(zstream, 0, sizeof(*zstream)); | ||
| 182 | |||
| 183 | zstream->workspace = | ||
| 184 | kmalloc(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL), | ||
| 185 | GFP_ATOMIC | __GFP_NOWARN); | ||
| 186 | if (!zstream->workspace) | ||
| 187 | return false; | ||
| 188 | |||
| 189 | if (zlib_deflateInit(zstream, Z_DEFAULT_COMPRESSION) != Z_OK) { | ||
| 190 | kfree(zstream->workspace); | ||
| 191 | return false; | ||
| 192 | } | ||
| 193 | |||
| 194 | return true; | ||
| 195 | } | ||
| 196 | |||
| 197 | static int compress_page(struct z_stream_s *zstream, | ||
| 198 | void *src, | ||
| 199 | struct drm_i915_error_object *dst) | ||
| 200 | { | ||
| 201 | zstream->next_in = src; | ||
| 202 | zstream->avail_in = PAGE_SIZE; | ||
| 203 | |||
| 204 | do { | ||
| 205 | if (zstream->avail_out == 0) { | ||
| 206 | unsigned long page; | ||
| 207 | |||
| 208 | page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN); | ||
| 209 | if (!page) | ||
| 210 | return -ENOMEM; | ||
| 211 | |||
| 212 | dst->pages[dst->page_count++] = (void *)page; | ||
| 213 | |||
| 214 | zstream->next_out = (void *)page; | ||
| 215 | zstream->avail_out = PAGE_SIZE; | ||
| 216 | } | ||
| 217 | |||
| 218 | if (zlib_deflate(zstream, Z_SYNC_FLUSH) != Z_OK) | ||
| 219 | return -EIO; | ||
| 220 | } while (zstream->avail_in); | ||
| 221 | |||
| 222 | /* Fallback to uncompressed if we increase size? */ | ||
| 223 | if (0 && zstream->total_out > zstream->total_in) | ||
| 224 | return -E2BIG; | ||
| 225 | |||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | static void compress_fini(struct z_stream_s *zstream, | ||
| 230 | struct drm_i915_error_object *dst) | ||
| 231 | { | ||
| 232 | if (dst) { | ||
| 233 | zlib_deflate(zstream, Z_FINISH); | ||
| 234 | dst->unused = zstream->avail_out; | ||
| 235 | } | ||
| 236 | |||
| 237 | zlib_deflateEnd(zstream); | ||
| 238 | kfree(zstream->workspace); | ||
| 239 | } | ||
| 240 | |||
| 241 | static void err_compression_marker(struct drm_i915_error_state_buf *m) | ||
| 242 | { | ||
| 243 | err_puts(m, ":"); | ||
| 244 | } | ||
| 245 | |||
| 246 | #else | ||
| 247 | |||
| 248 | static bool compress_init(struct z_stream_s *zstream) | ||
| 249 | { | ||
| 250 | return true; | ||
| 251 | } | ||
| 252 | |||
| 253 | static int compress_page(struct z_stream_s *zstream, | ||
| 254 | void *src, | ||
| 255 | struct drm_i915_error_object *dst) | ||
| 256 | { | ||
| 257 | unsigned long page; | ||
| 258 | |||
| 259 | page = __get_free_page(GFP_ATOMIC | __GFP_NOWARN); | ||
| 260 | if (!page) | ||
| 261 | return -ENOMEM; | ||
| 262 | |||
| 263 | dst->pages[dst->page_count++] = | ||
| 264 | memcpy((void *)page, src, PAGE_SIZE); | ||
| 265 | |||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | static void compress_fini(struct z_stream_s *zstream, | ||
| 270 | struct drm_i915_error_object *dst) | ||
| 271 | { | ||
| 272 | } | ||
| 273 | |||
| 274 | static void err_compression_marker(struct drm_i915_error_state_buf *m) | ||
| 275 | { | ||
| 276 | err_puts(m, "~"); | ||
| 277 | } | ||
| 278 | |||
| 279 | #endif | ||
| 280 | |||
| 175 | static void print_error_buffers(struct drm_i915_error_state_buf *m, | 281 | static void print_error_buffers(struct drm_i915_error_state_buf *m, |
| 176 | const char *name, | 282 | const char *name, |
| 177 | struct drm_i915_error_buffer *err, | 283 | struct drm_i915_error_buffer *err, |
| @@ -228,13 +334,57 @@ static const char *hangcheck_action_to_str(enum intel_engine_hangcheck_action a) | |||
| 228 | return "unknown"; | 334 | return "unknown"; |
| 229 | } | 335 | } |
| 230 | 336 | ||
| 337 | static void error_print_instdone(struct drm_i915_error_state_buf *m, | ||
| 338 | struct drm_i915_error_engine *ee) | ||
| 339 | { | ||
| 340 | int slice; | ||
| 341 | int subslice; | ||
| 342 | |||
| 343 | err_printf(m, " INSTDONE: 0x%08x\n", | ||
| 344 | ee->instdone.instdone); | ||
| 345 | |||
| 346 | if (ee->engine_id != RCS || INTEL_GEN(m->i915) <= 3) | ||
| 347 | return; | ||
| 348 | |||
| 349 | err_printf(m, " SC_INSTDONE: 0x%08x\n", | ||
| 350 | ee->instdone.slice_common); | ||
| 351 | |||
| 352 | if (INTEL_GEN(m->i915) <= 6) | ||
| 353 | return; | ||
| 354 | |||
| 355 | for_each_instdone_slice_subslice(m->i915, slice, subslice) | ||
| 356 | err_printf(m, " SAMPLER_INSTDONE[%d][%d]: 0x%08x\n", | ||
| 357 | slice, subslice, | ||
| 358 | ee->instdone.sampler[slice][subslice]); | ||
| 359 | |||
| 360 | for_each_instdone_slice_subslice(m->i915, slice, subslice) | ||
| 361 | err_printf(m, " ROW_INSTDONE[%d][%d]: 0x%08x\n", | ||
| 362 | slice, subslice, | ||
| 363 | ee->instdone.row[slice][subslice]); | ||
| 364 | } | ||
| 365 | |||
| 366 | static void error_print_request(struct drm_i915_error_state_buf *m, | ||
| 367 | const char *prefix, | ||
| 368 | struct drm_i915_error_request *erq) | ||
| 369 | { | ||
| 370 | if (!erq->seqno) | ||
| 371 | return; | ||
| 372 | |||
| 373 | err_printf(m, "%s pid %d, seqno %8x:%08x, emitted %dms ago, head %08x, tail %08x\n", | ||
| 374 | prefix, erq->pid, | ||
| 375 | erq->context, erq->seqno, | ||
| 376 | jiffies_to_msecs(jiffies - erq->jiffies), | ||
| 377 | erq->head, erq->tail); | ||
| 378 | } | ||
| 379 | |||
| 231 | static void error_print_engine(struct drm_i915_error_state_buf *m, | 380 | static void error_print_engine(struct drm_i915_error_state_buf *m, |
| 232 | struct drm_i915_error_engine *ee) | 381 | struct drm_i915_error_engine *ee) |
| 233 | { | 382 | { |
| 234 | err_printf(m, "%s command stream:\n", engine_str(ee->engine_id)); | 383 | err_printf(m, "%s command stream:\n", engine_str(ee->engine_id)); |
| 235 | err_printf(m, " START: 0x%08x\n", ee->start); | 384 | err_printf(m, " START: 0x%08x\n", ee->start); |
| 236 | err_printf(m, " HEAD: 0x%08x\n", ee->head); | 385 | err_printf(m, " HEAD: 0x%08x [0x%08x]\n", ee->head, ee->rq_head); |
| 237 | err_printf(m, " TAIL: 0x%08x\n", ee->tail); | 386 | err_printf(m, " TAIL: 0x%08x [0x%08x, 0x%08x]\n", |
| 387 | ee->tail, ee->rq_post, ee->rq_tail); | ||
| 238 | err_printf(m, " CTL: 0x%08x\n", ee->ctl); | 388 | err_printf(m, " CTL: 0x%08x\n", ee->ctl); |
| 239 | err_printf(m, " MODE: 0x%08x\n", ee->mode); | 389 | err_printf(m, " MODE: 0x%08x\n", ee->mode); |
| 240 | err_printf(m, " HWS: 0x%08x\n", ee->hws); | 390 | err_printf(m, " HWS: 0x%08x\n", ee->hws); |
| @@ -242,7 +392,9 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, | |||
| 242 | (u32)(ee->acthd>>32), (u32)ee->acthd); | 392 | (u32)(ee->acthd>>32), (u32)ee->acthd); |
| 243 | err_printf(m, " IPEIR: 0x%08x\n", ee->ipeir); | 393 | err_printf(m, " IPEIR: 0x%08x\n", ee->ipeir); |
| 244 | err_printf(m, " IPEHR: 0x%08x\n", ee->ipehr); | 394 | err_printf(m, " IPEHR: 0x%08x\n", ee->ipehr); |
| 245 | err_printf(m, " INSTDONE: 0x%08x\n", ee->instdone); | 395 | |
| 396 | error_print_instdone(m, ee); | ||
| 397 | |||
| 246 | if (ee->batchbuffer) { | 398 | if (ee->batchbuffer) { |
| 247 | u64 start = ee->batchbuffer->gtt_offset; | 399 | u64 start = ee->batchbuffer->gtt_offset; |
| 248 | u64 end = start + ee->batchbuffer->gtt_size; | 400 | u64 end = start + ee->batchbuffer->gtt_size; |
| @@ -296,6 +448,8 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, | |||
| 296 | err_printf(m, " hangcheck: %s [%d]\n", | 448 | err_printf(m, " hangcheck: %s [%d]\n", |
| 297 | hangcheck_action_to_str(ee->hangcheck_action), | 449 | hangcheck_action_to_str(ee->hangcheck_action), |
| 298 | ee->hangcheck_score); | 450 | ee->hangcheck_score); |
| 451 | error_print_request(m, " ELSP[0]: ", &ee->execlist[0]); | ||
| 452 | error_print_request(m, " ELSP[1]: ", &ee->execlist[1]); | ||
| 299 | } | 453 | } |
| 300 | 454 | ||
| 301 | void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) | 455 | void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) |
| @@ -307,28 +461,72 @@ void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) | |||
| 307 | va_end(args); | 461 | va_end(args); |
| 308 | } | 462 | } |
| 309 | 463 | ||
| 464 | static int | ||
| 465 | ascii85_encode_len(int len) | ||
| 466 | { | ||
| 467 | return DIV_ROUND_UP(len, 4); | ||
| 468 | } | ||
| 469 | |||
| 470 | static bool | ||
| 471 | ascii85_encode(u32 in, char *out) | ||
| 472 | { | ||
| 473 | int i; | ||
| 474 | |||
| 475 | if (in == 0) | ||
| 476 | return false; | ||
| 477 | |||
| 478 | out[5] = '\0'; | ||
| 479 | for (i = 5; i--; ) { | ||
| 480 | out[i] = '!' + in % 85; | ||
| 481 | in /= 85; | ||
| 482 | } | ||
| 483 | |||
| 484 | return true; | ||
| 485 | } | ||
| 486 | |||
| 310 | static void print_error_obj(struct drm_i915_error_state_buf *m, | 487 | static void print_error_obj(struct drm_i915_error_state_buf *m, |
| 488 | struct intel_engine_cs *engine, | ||
| 489 | const char *name, | ||
| 311 | struct drm_i915_error_object *obj) | 490 | struct drm_i915_error_object *obj) |
| 312 | { | 491 | { |
| 313 | int page, offset, elt; | 492 | char out[6]; |
| 493 | int page; | ||
| 494 | |||
| 495 | if (!obj) | ||
| 496 | return; | ||
| 497 | |||
| 498 | if (name) { | ||
| 499 | err_printf(m, "%s --- %s = 0x%08x %08x\n", | ||
| 500 | engine ? engine->name : "global", name, | ||
| 501 | upper_32_bits(obj->gtt_offset), | ||
| 502 | lower_32_bits(obj->gtt_offset)); | ||
| 503 | } | ||
| 504 | |||
| 505 | err_compression_marker(m); | ||
| 506 | for (page = 0; page < obj->page_count; page++) { | ||
| 507 | int i, len; | ||
| 508 | |||
| 509 | len = PAGE_SIZE; | ||
| 510 | if (page == obj->page_count - 1) | ||
| 511 | len -= obj->unused; | ||
| 512 | len = ascii85_encode_len(len); | ||
| 314 | 513 | ||
| 315 | for (page = offset = 0; page < obj->page_count; page++) { | 514 | for (i = 0; i < len; i++) { |
| 316 | for (elt = 0; elt < PAGE_SIZE/4; elt++) { | 515 | if (ascii85_encode(obj->pages[page][i], out)) |
| 317 | err_printf(m, "%08x : %08x\n", offset, | 516 | err_puts(m, out); |
| 318 | obj->pages[page][elt]); | 517 | else |
| 319 | offset += 4; | 518 | err_puts(m, "z"); |
| 320 | } | 519 | } |
| 321 | } | 520 | } |
| 521 | err_puts(m, "\n"); | ||
| 322 | } | 522 | } |
| 323 | 523 | ||
| 324 | static void err_print_capabilities(struct drm_i915_error_state_buf *m, | 524 | static void err_print_capabilities(struct drm_i915_error_state_buf *m, |
| 325 | const struct intel_device_info *info) | 525 | const struct intel_device_info *info) |
| 326 | { | 526 | { |
| 327 | #define PRINT_FLAG(x) err_printf(m, #x ": %s\n", yesno(info->x)) | 527 | #define PRINT_FLAG(x) err_printf(m, #x ": %s\n", yesno(info->x)) |
| 328 | #define SEP_SEMICOLON ; | 528 | DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); |
| 329 | DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_SEMICOLON); | ||
| 330 | #undef PRINT_FLAG | 529 | #undef PRINT_FLAG |
| 331 | #undef SEP_SEMICOLON | ||
| 332 | } | 530 | } |
| 333 | 531 | ||
| 334 | int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | 532 | int i915_error_state_to_str(struct drm_i915_error_state_buf *m, |
| @@ -339,8 +537,8 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
| 339 | struct pci_dev *pdev = dev_priv->drm.pdev; | 537 | struct pci_dev *pdev = dev_priv->drm.pdev; |
| 340 | struct drm_i915_error_state *error = error_priv->error; | 538 | struct drm_i915_error_state *error = error_priv->error; |
| 341 | struct drm_i915_error_object *obj; | 539 | struct drm_i915_error_object *obj; |
| 342 | int i, j, offset, elt; | ||
| 343 | int max_hangcheck_score; | 540 | int max_hangcheck_score; |
| 541 | int i, j; | ||
| 344 | 542 | ||
| 345 | if (!error) { | 543 | if (!error) { |
| 346 | err_printf(m, "no error state collected\n"); | 544 | err_printf(m, "no error state collected\n"); |
| @@ -391,7 +589,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
| 391 | for (i = 0; i < 4; i++) | 589 | for (i = 0; i < 4; i++) |
| 392 | err_printf(m, "GTIER gt %d: 0x%08x\n", i, | 590 | err_printf(m, "GTIER gt %d: 0x%08x\n", i, |
| 393 | error->gtier[i]); | 591 | error->gtier[i]); |
| 394 | } else if (HAS_PCH_SPLIT(dev) || IS_VALLEYVIEW(dev)) | 592 | } else if (HAS_PCH_SPLIT(dev_priv) || IS_VALLEYVIEW(dev_priv)) |
| 395 | err_printf(m, "GTIER: 0x%08x\n", error->gtier[0]); | 593 | err_printf(m, "GTIER: 0x%08x\n", error->gtier[0]); |
| 396 | err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); | 594 | err_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); |
| 397 | err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); | 595 | err_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); |
| @@ -402,10 +600,6 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
| 402 | for (i = 0; i < dev_priv->num_fence_regs; i++) | 600 | for (i = 0; i < dev_priv->num_fence_regs; i++) |
| 403 | err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); | 601 | err_printf(m, " fence[%d] = %08llx\n", i, error->fence[i]); |
| 404 | 602 | ||
| 405 | for (i = 0; i < ARRAY_SIZE(error->extra_instdone); i++) | ||
| 406 | err_printf(m, " INSTDONE_%d: 0x%08x\n", i, | ||
| 407 | error->extra_instdone[i]); | ||
| 408 | |||
| 409 | if (INTEL_INFO(dev)->gen >= 6) { | 603 | if (INTEL_INFO(dev)->gen >= 6) { |
| 410 | err_printf(m, "ERROR: 0x%08x\n", error->error); | 604 | err_printf(m, "ERROR: 0x%08x\n", error->error); |
| 411 | 605 | ||
| @@ -416,7 +610,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
| 416 | err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg); | 610 | err_printf(m, "DONE_REG: 0x%08x\n", error->done_reg); |
| 417 | } | 611 | } |
| 418 | 612 | ||
| 419 | if (IS_GEN7(dev)) | 613 | if (IS_GEN7(dev_priv)) |
| 420 | err_printf(m, "ERR_INT: 0x%08x\n", error->err_int); | 614 | err_printf(m, "ERR_INT: 0x%08x\n", error->err_int); |
| 421 | 615 | ||
| 422 | for (i = 0; i < ARRAY_SIZE(error->engine); i++) { | 616 | for (i = 0; i < ARRAY_SIZE(error->engine); i++) { |
| @@ -438,7 +632,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
| 438 | 632 | ||
| 439 | len += scnprintf(buf + len, sizeof(buf), "%s%s", | 633 | len += scnprintf(buf + len, sizeof(buf), "%s%s", |
| 440 | first ? "" : ", ", | 634 | first ? "" : ", ", |
| 441 | dev_priv->engine[j].name); | 635 | dev_priv->engine[j]->name); |
| 442 | first = 0; | 636 | first = 0; |
| 443 | } | 637 | } |
| 444 | scnprintf(buf + len, sizeof(buf), ")"); | 638 | scnprintf(buf + len, sizeof(buf), ")"); |
| @@ -456,7 +650,7 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
| 456 | 650 | ||
| 457 | obj = ee->batchbuffer; | 651 | obj = ee->batchbuffer; |
| 458 | if (obj) { | 652 | if (obj) { |
| 459 | err_puts(m, dev_priv->engine[i].name); | 653 | err_puts(m, dev_priv->engine[i]->name); |
| 460 | if (ee->pid != -1) | 654 | if (ee->pid != -1) |
| 461 | err_printf(m, " (submitted by %s [%d])", | 655 | err_printf(m, " (submitted by %s [%d])", |
| 462 | ee->comm, | 656 | ee->comm, |
| @@ -464,37 +658,23 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
| 464 | err_printf(m, " --- gtt_offset = 0x%08x %08x\n", | 658 | err_printf(m, " --- gtt_offset = 0x%08x %08x\n", |
| 465 | upper_32_bits(obj->gtt_offset), | 659 | upper_32_bits(obj->gtt_offset), |
| 466 | lower_32_bits(obj->gtt_offset)); | 660 | lower_32_bits(obj->gtt_offset)); |
| 467 | print_error_obj(m, obj); | 661 | print_error_obj(m, dev_priv->engine[i], NULL, obj); |
| 468 | } | ||
| 469 | |||
| 470 | obj = ee->wa_batchbuffer; | ||
| 471 | if (obj) { | ||
| 472 | err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n", | ||
| 473 | dev_priv->engine[i].name, | ||
| 474 | lower_32_bits(obj->gtt_offset)); | ||
| 475 | print_error_obj(m, obj); | ||
| 476 | } | 662 | } |
| 477 | 663 | ||
| 478 | if (ee->num_requests) { | 664 | if (ee->num_requests) { |
| 479 | err_printf(m, "%s --- %d requests\n", | 665 | err_printf(m, "%s --- %d requests\n", |
| 480 | dev_priv->engine[i].name, | 666 | dev_priv->engine[i]->name, |
| 481 | ee->num_requests); | 667 | ee->num_requests); |
| 482 | for (j = 0; j < ee->num_requests; j++) { | 668 | for (j = 0; j < ee->num_requests; j++) |
| 483 | err_printf(m, " pid %d, seqno 0x%08x, emitted %ld, head 0x%08x, tail 0x%08x\n", | 669 | error_print_request(m, " ", &ee->requests[j]); |
| 484 | ee->requests[j].pid, | ||
| 485 | ee->requests[j].seqno, | ||
| 486 | ee->requests[j].jiffies, | ||
| 487 | ee->requests[j].head, | ||
| 488 | ee->requests[j].tail); | ||
| 489 | } | ||
| 490 | } | 670 | } |
| 491 | 671 | ||
| 492 | if (IS_ERR(ee->waiters)) { | 672 | if (IS_ERR(ee->waiters)) { |
| 493 | err_printf(m, "%s --- ? waiters [unable to acquire spinlock]\n", | 673 | err_printf(m, "%s --- ? waiters [unable to acquire spinlock]\n", |
| 494 | dev_priv->engine[i].name); | 674 | dev_priv->engine[i]->name); |
| 495 | } else if (ee->num_waiters) { | 675 | } else if (ee->num_waiters) { |
| 496 | err_printf(m, "%s --- %d waiters\n", | 676 | err_printf(m, "%s --- %d waiters\n", |
| 497 | dev_priv->engine[i].name, | 677 | dev_priv->engine[i]->name, |
| 498 | ee->num_waiters); | 678 | ee->num_waiters); |
| 499 | for (j = 0; j < ee->num_waiters; j++) { | 679 | for (j = 0; j < ee->num_waiters; j++) { |
| 500 | err_printf(m, " seqno 0x%08x for %s [%d]\n", | 680 | err_printf(m, " seqno 0x%08x for %s [%d]\n", |
| @@ -504,77 +684,23 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, | |||
| 504 | } | 684 | } |
| 505 | } | 685 | } |
| 506 | 686 | ||
| 507 | if ((obj = ee->ringbuffer)) { | 687 | print_error_obj(m, dev_priv->engine[i], |
| 508 | err_printf(m, "%s --- ringbuffer = 0x%08x\n", | 688 | "ringbuffer", ee->ringbuffer); |
| 509 | dev_priv->engine[i].name, | ||
| 510 | lower_32_bits(obj->gtt_offset)); | ||
| 511 | print_error_obj(m, obj); | ||
| 512 | } | ||
| 513 | 689 | ||
| 514 | if ((obj = ee->hws_page)) { | 690 | print_error_obj(m, dev_priv->engine[i], |
| 515 | u64 hws_offset = obj->gtt_offset; | 691 | "HW Status", ee->hws_page); |
| 516 | u32 *hws_page = &obj->pages[0][0]; | ||
| 517 | 692 | ||
| 518 | if (i915.enable_execlists) { | 693 | print_error_obj(m, dev_priv->engine[i], |
| 519 | hws_offset += LRC_PPHWSP_PN * PAGE_SIZE; | 694 | "HW context", ee->ctx); |
| 520 | hws_page = &obj->pages[LRC_PPHWSP_PN][0]; | ||
| 521 | } | ||
| 522 | err_printf(m, "%s --- HW Status = 0x%08llx\n", | ||
| 523 | dev_priv->engine[i].name, hws_offset); | ||
| 524 | offset = 0; | ||
| 525 | for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { | ||
| 526 | err_printf(m, "[%04x] %08x %08x %08x %08x\n", | ||
| 527 | offset, | ||
| 528 | hws_page[elt], | ||
| 529 | hws_page[elt+1], | ||
| 530 | hws_page[elt+2], | ||
| 531 | hws_page[elt+3]); | ||
| 532 | offset += 16; | ||
| 533 | } | ||
| 534 | } | ||
| 535 | 695 | ||
| 536 | obj = ee->wa_ctx; | 696 | print_error_obj(m, dev_priv->engine[i], |
| 537 | if (obj) { | 697 | "WA context", ee->wa_ctx); |
| 538 | u64 wa_ctx_offset = obj->gtt_offset; | ||
| 539 | u32 *wa_ctx_page = &obj->pages[0][0]; | ||
| 540 | struct intel_engine_cs *engine = &dev_priv->engine[RCS]; | ||
| 541 | u32 wa_ctx_size = (engine->wa_ctx.indirect_ctx.size + | ||
| 542 | engine->wa_ctx.per_ctx.size); | ||
| 543 | |||
| 544 | err_printf(m, "%s --- WA ctx batch buffer = 0x%08llx\n", | ||
| 545 | dev_priv->engine[i].name, wa_ctx_offset); | ||
| 546 | offset = 0; | ||
| 547 | for (elt = 0; elt < wa_ctx_size; elt += 4) { | ||
| 548 | err_printf(m, "[%04x] %08x %08x %08x %08x\n", | ||
| 549 | offset, | ||
| 550 | wa_ctx_page[elt + 0], | ||
| 551 | wa_ctx_page[elt + 1], | ||
| 552 | wa_ctx_page[elt + 2], | ||
| 553 | wa_ctx_page[elt + 3]); | ||
| 554 | offset += 16; | ||
| 555 | } | ||
| 556 | } | ||
| 557 | 698 | ||
| 558 | if ((obj = ee->ctx)) { | 699 | print_error_obj(m, dev_priv->engine[i], |
| 559 | err_printf(m, "%s --- HW Context = 0x%08x\n", | 700 | "WA batchbuffer", ee->wa_batchbuffer); |
| 560 | dev_priv->engine[i].name, | ||
| 561 | lower_32_bits(obj->gtt_offset)); | ||
| 562 | print_error_obj(m, obj); | ||
| 563 | } | ||
| 564 | } | 701 | } |
| 565 | 702 | ||
| 566 | if ((obj = error->semaphore)) { | 703 | print_error_obj(m, NULL, "Semaphores", error->semaphore); |
| 567 | err_printf(m, "Semaphore page = 0x%08x\n", | ||
| 568 | lower_32_bits(obj->gtt_offset)); | ||
| 569 | for (elt = 0; elt < PAGE_SIZE/16; elt += 4) { | ||
| 570 | err_printf(m, "[%04x] %08x %08x %08x %08x\n", | ||
| 571 | elt * 4, | ||
| 572 | obj->pages[0][elt], | ||
| 573 | obj->pages[0][elt+1], | ||
| 574 | obj->pages[0][elt+2], | ||
| 575 | obj->pages[0][elt+3]); | ||
| 576 | } | ||
| 577 | } | ||
| 578 | 704 | ||
| 579 | if (error->overlay) | 705 | if (error->overlay) |
| 580 | intel_overlay_print_error_state(m, error->overlay); | 706 | intel_overlay_print_error_state(m, error->overlay); |
| @@ -629,7 +755,7 @@ static void i915_error_object_free(struct drm_i915_error_object *obj) | |||
| 629 | return; | 755 | return; |
| 630 | 756 | ||
| 631 | for (page = 0; page < obj->page_count; page++) | 757 | for (page = 0; page < obj->page_count; page++) |
| 632 | kfree(obj->pages[page]); | 758 | free_page((unsigned long)obj->pages[page]); |
| 633 | 759 | ||
| 634 | kfree(obj); | 760 | kfree(obj); |
| 635 | } | 761 | } |
| @@ -667,104 +793,63 @@ static void i915_error_state_free(struct kref *error_ref) | |||
| 667 | } | 793 | } |
| 668 | 794 | ||
| 669 | static struct drm_i915_error_object * | 795 | static struct drm_i915_error_object * |
| 670 | i915_error_object_create(struct drm_i915_private *dev_priv, | 796 | i915_error_object_create(struct drm_i915_private *i915, |
| 671 | struct i915_vma *vma) | 797 | struct i915_vma *vma) |
| 672 | { | 798 | { |
| 673 | struct i915_ggtt *ggtt = &dev_priv->ggtt; | 799 | struct i915_ggtt *ggtt = &i915->ggtt; |
| 674 | struct drm_i915_gem_object *src; | 800 | const u64 slot = ggtt->error_capture.start; |
| 675 | struct drm_i915_error_object *dst; | 801 | struct drm_i915_error_object *dst; |
| 676 | int num_pages; | 802 | struct z_stream_s zstream; |
| 677 | bool use_ggtt; | 803 | unsigned long num_pages; |
| 678 | int i = 0; | 804 | struct sgt_iter iter; |
| 679 | u64 reloc_offset; | 805 | dma_addr_t dma; |
| 680 | 806 | ||
| 681 | if (!vma) | 807 | if (!vma) |
| 682 | return NULL; | 808 | return NULL; |
| 683 | 809 | ||
| 684 | src = vma->obj; | 810 | num_pages = min_t(u64, vma->size, vma->obj->base.size) >> PAGE_SHIFT; |
| 685 | if (!src->pages) | 811 | num_pages = DIV_ROUND_UP(10 * num_pages, 8); /* worstcase zlib growth */ |
| 686 | return NULL; | 812 | dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), |
| 687 | 813 | GFP_ATOMIC | __GFP_NOWARN); | |
| 688 | num_pages = src->base.size >> PAGE_SHIFT; | ||
| 689 | |||
| 690 | dst = kmalloc(sizeof(*dst) + num_pages * sizeof(u32 *), GFP_ATOMIC); | ||
| 691 | if (!dst) | 814 | if (!dst) |
| 692 | return NULL; | 815 | return NULL; |
| 693 | 816 | ||
| 694 | dst->gtt_offset = vma->node.start; | 817 | dst->gtt_offset = vma->node.start; |
| 695 | dst->gtt_size = vma->node.size; | 818 | dst->gtt_size = vma->node.size; |
| 819 | dst->page_count = 0; | ||
| 820 | dst->unused = 0; | ||
| 696 | 821 | ||
| 697 | reloc_offset = dst->gtt_offset; | 822 | if (!compress_init(&zstream)) { |
| 698 | use_ggtt = (src->cache_level == I915_CACHE_NONE && | 823 | kfree(dst); |
| 699 | (vma->flags & I915_VMA_GLOBAL_BIND) && | 824 | return NULL; |
| 700 | reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end); | ||
| 701 | |||
| 702 | /* Cannot access stolen address directly, try to use the aperture */ | ||
| 703 | if (src->stolen) { | ||
| 704 | use_ggtt = true; | ||
| 705 | |||
| 706 | if (!(vma->flags & I915_VMA_GLOBAL_BIND)) | ||
| 707 | goto unwind; | ||
| 708 | |||
| 709 | reloc_offset = vma->node.start; | ||
| 710 | if (reloc_offset + num_pages * PAGE_SIZE > ggtt->mappable_end) | ||
| 711 | goto unwind; | ||
| 712 | } | 825 | } |
| 713 | 826 | ||
| 714 | /* Cannot access snooped pages through the aperture */ | 827 | for_each_sgt_dma(dma, iter, vma->pages) { |
| 715 | if (use_ggtt && src->cache_level != I915_CACHE_NONE && | 828 | void __iomem *s; |
| 716 | !HAS_LLC(dev_priv)) | 829 | int ret; |
| 717 | goto unwind; | ||
| 718 | 830 | ||
| 719 | dst->page_count = num_pages; | 831 | ggtt->base.insert_page(&ggtt->base, dma, slot, |
| 720 | while (num_pages--) { | 832 | I915_CACHE_NONE, 0); |
| 721 | unsigned long flags; | ||
| 722 | void *d; | ||
| 723 | 833 | ||
| 724 | d = kmalloc(PAGE_SIZE, GFP_ATOMIC); | 834 | s = io_mapping_map_atomic_wc(&ggtt->mappable, slot); |
| 725 | if (d == NULL) | 835 | ret = compress_page(&zstream, (void __force *)s, dst); |
| 726 | goto unwind; | 836 | io_mapping_unmap_atomic(s); |
| 727 | |||
| 728 | local_irq_save(flags); | ||
| 729 | if (use_ggtt) { | ||
| 730 | void __iomem *s; | ||
| 731 | |||
| 732 | /* Simply ignore tiling or any overlapping fence. | ||
| 733 | * It's part of the error state, and this hopefully | ||
| 734 | * captures what the GPU read. | ||
| 735 | */ | ||
| 736 | |||
| 737 | s = io_mapping_map_atomic_wc(&ggtt->mappable, | ||
| 738 | reloc_offset); | ||
| 739 | memcpy_fromio(d, s, PAGE_SIZE); | ||
| 740 | io_mapping_unmap_atomic(s); | ||
| 741 | } else { | ||
| 742 | struct page *page; | ||
| 743 | void *s; | ||
| 744 | |||
| 745 | page = i915_gem_object_get_page(src, i); | ||
| 746 | |||
| 747 | drm_clflush_pages(&page, 1); | ||
| 748 | |||
| 749 | s = kmap_atomic(page); | ||
| 750 | memcpy(d, s, PAGE_SIZE); | ||
| 751 | kunmap_atomic(s); | ||
| 752 | |||
| 753 | drm_clflush_pages(&page, 1); | ||
| 754 | } | ||
| 755 | local_irq_restore(flags); | ||
| 756 | 837 | ||
| 757 | dst->pages[i++] = d; | 838 | if (ret) |
| 758 | reloc_offset += PAGE_SIZE; | 839 | goto unwind; |
| 759 | } | 840 | } |
| 760 | 841 | goto out; | |
| 761 | return dst; | ||
| 762 | 842 | ||
| 763 | unwind: | 843 | unwind: |
| 764 | while (i--) | 844 | while (dst->page_count--) |
| 765 | kfree(dst->pages[i]); | 845 | free_page((unsigned long)dst->pages[dst->page_count]); |
| 766 | kfree(dst); | 846 | kfree(dst); |
| 767 | return NULL; | 847 | dst = NULL; |
| 848 | |||
| 849 | out: | ||
| 850 | compress_fini(&zstream, dst); | ||
| 851 | ggtt->base.clear_range(&ggtt->base, slot, PAGE_SIZE); | ||
| 852 | return dst; | ||
| 768 | } | 853 | } |
| 769 | 854 | ||
| 770 | /* The error capture is special as tries to run underneath the normal | 855 | /* The error capture is special as tries to run underneath the normal |
| @@ -855,7 +940,8 @@ static uint32_t i915_error_generate_code(struct drm_i915_private *dev_priv, | |||
| 855 | if (engine_id) | 940 | if (engine_id) |
| 856 | *engine_id = i; | 941 | *engine_id = i; |
| 857 | 942 | ||
| 858 | return error->engine[i].ipehr ^ error->engine[i].instdone; | 943 | return error->engine[i].ipehr ^ |
| 944 | error->engine[i].instdone.instdone; | ||
| 859 | } | 945 | } |
| 860 | } | 946 | } |
| 861 | 947 | ||
| @@ -891,7 +977,7 @@ static void gen8_record_semaphore_state(struct drm_i915_error_state *error, | |||
| 891 | if (!error->semaphore) | 977 | if (!error->semaphore) |
| 892 | return; | 978 | return; |
| 893 | 979 | ||
| 894 | for_each_engine_id(to, dev_priv, id) { | 980 | for_each_engine(to, dev_priv, id) { |
| 895 | int idx; | 981 | int idx; |
| 896 | u16 signal_offset; | 982 | u16 signal_offset; |
| 897 | u32 *tmp; | 983 | u32 *tmp; |
| @@ -998,7 +1084,6 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, | |||
| 998 | ee->faddr = I915_READ(RING_DMA_FADD(engine->mmio_base)); | 1084 | ee->faddr = I915_READ(RING_DMA_FADD(engine->mmio_base)); |
| 999 | ee->ipeir = I915_READ(RING_IPEIR(engine->mmio_base)); | 1085 | ee->ipeir = I915_READ(RING_IPEIR(engine->mmio_base)); |
| 1000 | ee->ipehr = I915_READ(RING_IPEHR(engine->mmio_base)); | 1086 | ee->ipehr = I915_READ(RING_IPEHR(engine->mmio_base)); |
| 1001 | ee->instdone = I915_READ(RING_INSTDONE(engine->mmio_base)); | ||
| 1002 | ee->instps = I915_READ(RING_INSTPS(engine->mmio_base)); | 1087 | ee->instps = I915_READ(RING_INSTPS(engine->mmio_base)); |
| 1003 | ee->bbaddr = I915_READ(RING_BBADDR(engine->mmio_base)); | 1088 | ee->bbaddr = I915_READ(RING_BBADDR(engine->mmio_base)); |
| 1004 | if (INTEL_GEN(dev_priv) >= 8) { | 1089 | if (INTEL_GEN(dev_priv) >= 8) { |
| @@ -1010,9 +1095,10 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, | |||
| 1010 | ee->faddr = I915_READ(DMA_FADD_I8XX); | 1095 | ee->faddr = I915_READ(DMA_FADD_I8XX); |
| 1011 | ee->ipeir = I915_READ(IPEIR); | 1096 | ee->ipeir = I915_READ(IPEIR); |
| 1012 | ee->ipehr = I915_READ(IPEHR); | 1097 | ee->ipehr = I915_READ(IPEHR); |
| 1013 | ee->instdone = I915_READ(GEN2_INSTDONE); | ||
| 1014 | } | 1098 | } |
| 1015 | 1099 | ||
| 1100 | intel_engine_get_instdone(engine, &ee->instdone); | ||
| 1101 | |||
| 1016 | ee->waiting = intel_engine_has_waiter(engine); | 1102 | ee->waiting = intel_engine_has_waiter(engine); |
| 1017 | ee->instpm = I915_READ(RING_INSTPM(engine->mmio_base)); | 1103 | ee->instpm = I915_READ(RING_INSTPM(engine->mmio_base)); |
| 1018 | ee->acthd = intel_engine_get_active_head(engine); | 1104 | ee->acthd = intel_engine_get_active_head(engine); |
| @@ -1079,6 +1165,20 @@ static void error_record_engine_registers(struct drm_i915_error_state *error, | |||
| 1079 | } | 1165 | } |
| 1080 | } | 1166 | } |
| 1081 | 1167 | ||
| 1168 | static void record_request(struct drm_i915_gem_request *request, | ||
| 1169 | struct drm_i915_error_request *erq) | ||
| 1170 | { | ||
| 1171 | erq->context = request->ctx->hw_id; | ||
| 1172 | erq->seqno = request->fence.seqno; | ||
| 1173 | erq->jiffies = request->emitted_jiffies; | ||
| 1174 | erq->head = request->head; | ||
| 1175 | erq->tail = request->tail; | ||
| 1176 | |||
| 1177 | rcu_read_lock(); | ||
| 1178 | erq->pid = request->ctx->pid ? pid_nr(request->ctx->pid) : 0; | ||
| 1179 | rcu_read_unlock(); | ||
| 1180 | } | ||
| 1181 | |||
| 1082 | static void engine_record_requests(struct intel_engine_cs *engine, | 1182 | static void engine_record_requests(struct intel_engine_cs *engine, |
| 1083 | struct drm_i915_gem_request *first, | 1183 | struct drm_i915_gem_request *first, |
| 1084 | struct drm_i915_error_engine *ee) | 1184 | struct drm_i915_error_engine *ee) |
| @@ -1102,8 +1202,6 @@ static void engine_record_requests(struct intel_engine_cs *engine, | |||
| 1102 | count = 0; | 1202 | count = 0; |
| 1103 | request = first; | 1203 | request = first; |
| 1104 | list_for_each_entry_from(request, &engine->request_list, link) { | 1204 | list_for_each_entry_from(request, &engine->request_list, link) { |
| 1105 | struct drm_i915_error_request *erq; | ||
| 1106 | |||
| 1107 | if (count >= ee->num_requests) { | 1205 | if (count >= ee->num_requests) { |
| 1108 | /* | 1206 | /* |
| 1109 | * If the ring request list was changed in | 1207 | * If the ring request list was changed in |
| @@ -1123,19 +1221,22 @@ static void engine_record_requests(struct intel_engine_cs *engine, | |||
| 1123 | break; | 1221 | break; |
| 1124 | } | 1222 | } |
| 1125 | 1223 | ||
| 1126 | erq = &ee->requests[count++]; | 1224 | record_request(request, &ee->requests[count++]); |
| 1127 | erq->seqno = request->fence.seqno; | ||
| 1128 | erq->jiffies = request->emitted_jiffies; | ||
| 1129 | erq->head = request->head; | ||
| 1130 | erq->tail = request->tail; | ||
| 1131 | |||
| 1132 | rcu_read_lock(); | ||
| 1133 | erq->pid = request->ctx->pid ? pid_nr(request->ctx->pid) : 0; | ||
| 1134 | rcu_read_unlock(); | ||
| 1135 | } | 1225 | } |
| 1136 | ee->num_requests = count; | 1226 | ee->num_requests = count; |
| 1137 | } | 1227 | } |
| 1138 | 1228 | ||
| 1229 | static void error_record_engine_execlists(struct intel_engine_cs *engine, | ||
| 1230 | struct drm_i915_error_engine *ee) | ||
| 1231 | { | ||
| 1232 | unsigned int n; | ||
| 1233 | |||
| 1234 | for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) | ||
| 1235 | if (engine->execlist_port[n].request) | ||
| 1236 | record_request(engine->execlist_port[n].request, | ||
| 1237 | &ee->execlist[n]); | ||
| 1238 | } | ||
| 1239 | |||
| 1139 | static void i915_gem_record_rings(struct drm_i915_private *dev_priv, | 1240 | static void i915_gem_record_rings(struct drm_i915_private *dev_priv, |
| 1140 | struct drm_i915_error_state *error) | 1241 | struct drm_i915_error_state *error) |
| 1141 | { | 1242 | { |
| @@ -1146,20 +1247,21 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv, | |||
| 1146 | i915_error_object_create(dev_priv, dev_priv->semaphore); | 1247 | i915_error_object_create(dev_priv, dev_priv->semaphore); |
| 1147 | 1248 | ||
| 1148 | for (i = 0; i < I915_NUM_ENGINES; i++) { | 1249 | for (i = 0; i < I915_NUM_ENGINES; i++) { |
| 1149 | struct intel_engine_cs *engine = &dev_priv->engine[i]; | 1250 | struct intel_engine_cs *engine = dev_priv->engine[i]; |
| 1150 | struct drm_i915_error_engine *ee = &error->engine[i]; | 1251 | struct drm_i915_error_engine *ee = &error->engine[i]; |
| 1151 | struct drm_i915_gem_request *request; | 1252 | struct drm_i915_gem_request *request; |
| 1152 | 1253 | ||
| 1153 | ee->pid = -1; | 1254 | ee->pid = -1; |
| 1154 | ee->engine_id = -1; | 1255 | ee->engine_id = -1; |
| 1155 | 1256 | ||
| 1156 | if (!intel_engine_initialized(engine)) | 1257 | if (!engine) |
| 1157 | continue; | 1258 | continue; |
| 1158 | 1259 | ||
| 1159 | ee->engine_id = i; | 1260 | ee->engine_id = i; |
| 1160 | 1261 | ||
| 1161 | error_record_engine_registers(error, engine, ee); | 1262 | error_record_engine_registers(error, engine, ee); |
| 1162 | error_record_engine_waiters(engine, ee); | 1263 | error_record_engine_waiters(engine, ee); |
| 1264 | error_record_engine_execlists(engine, ee); | ||
| 1163 | 1265 | ||
| 1164 | request = i915_gem_find_active_request(engine); | 1266 | request = i915_gem_find_active_request(engine); |
| 1165 | if (request) { | 1267 | if (request) { |
| @@ -1202,6 +1304,10 @@ static void i915_gem_record_rings(struct drm_i915_private *dev_priv, | |||
| 1202 | error->simulated |= | 1304 | error->simulated |= |
| 1203 | request->ctx->flags & CONTEXT_NO_ERROR_CAPTURE; | 1305 | request->ctx->flags & CONTEXT_NO_ERROR_CAPTURE; |
| 1204 | 1306 | ||
| 1307 | ee->rq_head = request->head; | ||
| 1308 | ee->rq_post = request->postfix; | ||
| 1309 | ee->rq_tail = request->tail; | ||
| 1310 | |||
| 1205 | ring = request->ring; | 1311 | ring = request->ring; |
| 1206 | ee->cpu_ring_head = ring->head; | 1312 | ee->cpu_ring_head = ring->head; |
| 1207 | ee->cpu_ring_tail = ring->tail; | 1313 | ee->cpu_ring_tail = ring->tail; |
| @@ -1318,13 +1424,13 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, | |||
| 1318 | */ | 1424 | */ |
| 1319 | 1425 | ||
| 1320 | /* 1: Registers specific to a single generation */ | 1426 | /* 1: Registers specific to a single generation */ |
| 1321 | if (IS_VALLEYVIEW(dev)) { | 1427 | if (IS_VALLEYVIEW(dev_priv)) { |
| 1322 | error->gtier[0] = I915_READ(GTIER); | 1428 | error->gtier[0] = I915_READ(GTIER); |
| 1323 | error->ier = I915_READ(VLV_IER); | 1429 | error->ier = I915_READ(VLV_IER); |
| 1324 | error->forcewake = I915_READ_FW(FORCEWAKE_VLV); | 1430 | error->forcewake = I915_READ_FW(FORCEWAKE_VLV); |
| 1325 | } | 1431 | } |
| 1326 | 1432 | ||
| 1327 | if (IS_GEN7(dev)) | 1433 | if (IS_GEN7(dev_priv)) |
| 1328 | error->err_int = I915_READ(GEN7_ERR_INT); | 1434 | error->err_int = I915_READ(GEN7_ERR_INT); |
| 1329 | 1435 | ||
| 1330 | if (INTEL_INFO(dev)->gen >= 8) { | 1436 | if (INTEL_INFO(dev)->gen >= 8) { |
| @@ -1332,7 +1438,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, | |||
| 1332 | error->fault_data1 = I915_READ(GEN8_FAULT_TLB_DATA1); | 1438 | error->fault_data1 = I915_READ(GEN8_FAULT_TLB_DATA1); |
| 1333 | } | 1439 | } |
| 1334 | 1440 | ||
| 1335 | if (IS_GEN6(dev)) { | 1441 | if (IS_GEN6(dev_priv)) { |
| 1336 | error->forcewake = I915_READ_FW(FORCEWAKE); | 1442 | error->forcewake = I915_READ_FW(FORCEWAKE); |
| 1337 | error->gab_ctl = I915_READ(GAB_CTL); | 1443 | error->gab_ctl = I915_READ(GAB_CTL); |
| 1338 | error->gfx_mode = I915_READ(GFX_MODE); | 1444 | error->gfx_mode = I915_READ(GFX_MODE); |
| @@ -1349,7 +1455,7 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, | |||
| 1349 | } | 1455 | } |
| 1350 | 1456 | ||
| 1351 | /* 3: Feature specific registers */ | 1457 | /* 3: Feature specific registers */ |
| 1352 | if (IS_GEN6(dev) || IS_GEN7(dev)) { | 1458 | if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) { |
| 1353 | error->gam_ecochk = I915_READ(GAM_ECOCHK); | 1459 | error->gam_ecochk = I915_READ(GAM_ECOCHK); |
| 1354 | error->gac_eco = I915_READ(GAC_ECO_BITS); | 1460 | error->gac_eco = I915_READ(GAC_ECO_BITS); |
| 1355 | } | 1461 | } |
| @@ -1362,18 +1468,16 @@ static void i915_capture_reg_state(struct drm_i915_private *dev_priv, | |||
| 1362 | error->ier = I915_READ(GEN8_DE_MISC_IER); | 1468 | error->ier = I915_READ(GEN8_DE_MISC_IER); |
| 1363 | for (i = 0; i < 4; i++) | 1469 | for (i = 0; i < 4; i++) |
| 1364 | error->gtier[i] = I915_READ(GEN8_GT_IER(i)); | 1470 | error->gtier[i] = I915_READ(GEN8_GT_IER(i)); |
| 1365 | } else if (HAS_PCH_SPLIT(dev)) { | 1471 | } else if (HAS_PCH_SPLIT(dev_priv)) { |
| 1366 | error->ier = I915_READ(DEIER); | 1472 | error->ier = I915_READ(DEIER); |
| 1367 | error->gtier[0] = I915_READ(GTIER); | 1473 | error->gtier[0] = I915_READ(GTIER); |
| 1368 | } else if (IS_GEN2(dev)) { | 1474 | } else if (IS_GEN2(dev_priv)) { |
| 1369 | error->ier = I915_READ16(IER); | 1475 | error->ier = I915_READ16(IER); |
| 1370 | } else if (!IS_VALLEYVIEW(dev)) { | 1476 | } else if (!IS_VALLEYVIEW(dev_priv)) { |
| 1371 | error->ier = I915_READ(IER); | 1477 | error->ier = I915_READ(IER); |
| 1372 | } | 1478 | } |
| 1373 | error->eir = I915_READ(EIR); | 1479 | error->eir = I915_READ(EIR); |
| 1374 | error->pgtbl_er = I915_READ(PGTBL_ER); | 1480 | error->pgtbl_er = I915_READ(PGTBL_ER); |
| 1375 | |||
| 1376 | i915_get_extra_instdone(dev_priv, error->extra_instdone); | ||
| 1377 | } | 1481 | } |
| 1378 | 1482 | ||
| 1379 | static void i915_error_capture_msg(struct drm_i915_private *dev_priv, | 1483 | static void i915_error_capture_msg(struct drm_i915_private *dev_priv, |
| @@ -1418,6 +1522,27 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv, | |||
| 1418 | sizeof(error->device_info)); | 1522 | sizeof(error->device_info)); |
| 1419 | } | 1523 | } |
| 1420 | 1524 | ||
| 1525 | static int capture(void *data) | ||
| 1526 | { | ||
| 1527 | struct drm_i915_error_state *error = data; | ||
| 1528 | |||
| 1529 | i915_capture_gen_state(error->i915, error); | ||
| 1530 | i915_capture_reg_state(error->i915, error); | ||
| 1531 | i915_gem_record_fences(error->i915, error); | ||
| 1532 | i915_gem_record_rings(error->i915, error); | ||
| 1533 | i915_capture_active_buffers(error->i915, error); | ||
| 1534 | i915_capture_pinned_buffers(error->i915, error); | ||
| 1535 | |||
| 1536 | do_gettimeofday(&error->time); | ||
| 1537 | |||
| 1538 | error->overlay = intel_overlay_capture_error_state(error->i915); | ||
| 1539 | error->display = intel_display_capture_error_state(error->i915); | ||
| 1540 | |||
| 1541 | return 0; | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | #define DAY_AS_SECONDS(x) (24 * 60 * 60 * (x)) | ||
| 1545 | |||
| 1421 | /** | 1546 | /** |
| 1422 | * i915_capture_error_state - capture an error record for later analysis | 1547 | * i915_capture_error_state - capture an error record for later analysis |
| 1423 | * @dev: drm device | 1548 | * @dev: drm device |
| @@ -1435,6 +1560,9 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv, | |||
| 1435 | struct drm_i915_error_state *error; | 1560 | struct drm_i915_error_state *error; |
| 1436 | unsigned long flags; | 1561 | unsigned long flags; |
| 1437 | 1562 | ||
| 1563 | if (!i915.error_capture) | ||
| 1564 | return; | ||
| 1565 | |||
| 1438 | if (READ_ONCE(dev_priv->gpu_error.first_error)) | 1566 | if (READ_ONCE(dev_priv->gpu_error.first_error)) |
| 1439 | return; | 1567 | return; |
| 1440 | 1568 | ||
| @@ -1446,18 +1574,9 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv, | |||
| 1446 | } | 1574 | } |
| 1447 | 1575 | ||
| 1448 | kref_init(&error->ref); | 1576 | kref_init(&error->ref); |
| 1577 | error->i915 = dev_priv; | ||
| 1449 | 1578 | ||
| 1450 | i915_capture_gen_state(dev_priv, error); | 1579 | stop_machine(capture, error, NULL); |
| 1451 | i915_capture_reg_state(dev_priv, error); | ||
| 1452 | i915_gem_record_fences(dev_priv, error); | ||
| 1453 | i915_gem_record_rings(dev_priv, error); | ||
| 1454 | i915_capture_active_buffers(dev_priv, error); | ||
| 1455 | i915_capture_pinned_buffers(dev_priv, error); | ||
| 1456 | |||
| 1457 | do_gettimeofday(&error->time); | ||
| 1458 | |||
| 1459 | error->overlay = intel_overlay_capture_error_state(dev_priv); | ||
| 1460 | error->display = intel_display_capture_error_state(dev_priv); | ||
| 1461 | 1580 | ||
| 1462 | i915_error_capture_msg(dev_priv, error, engine_mask, error_msg); | 1581 | i915_error_capture_msg(dev_priv, error, engine_mask, error_msg); |
| 1463 | DRM_INFO("%s\n", error->error_msg); | 1582 | DRM_INFO("%s\n", error->error_msg); |
| @@ -1476,7 +1595,8 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv, | |||
| 1476 | return; | 1595 | return; |
| 1477 | } | 1596 | } |
| 1478 | 1597 | ||
| 1479 | if (!warned) { | 1598 | if (!warned && |
| 1599 | ktime_get_real_seconds() - DRIVER_TIMESTAMP < DAY_AS_SECONDS(180)) { | ||
| 1480 | DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n"); | 1600 | DRM_INFO("GPU hangs can indicate a bug anywhere in the entire gfx stack, including userspace.\n"); |
| 1481 | DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n"); | 1601 | DRM_INFO("Please file a _new_ bug report on bugs.freedesktop.org against DRI -> DRM/Intel\n"); |
| 1482 | DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n"); | 1602 | DRM_INFO("drm/i915 developers can then reassign to the right component if it's not a kernel issue.\n"); |
| @@ -1497,7 +1617,6 @@ void i915_error_state_get(struct drm_device *dev, | |||
| 1497 | if (error_priv->error) | 1617 | if (error_priv->error) |
| 1498 | kref_get(&error_priv->error->ref); | 1618 | kref_get(&error_priv->error->ref); |
| 1499 | spin_unlock_irq(&dev_priv->gpu_error.lock); | 1619 | spin_unlock_irq(&dev_priv->gpu_error.lock); |
| 1500 | |||
| 1501 | } | 1620 | } |
| 1502 | 1621 | ||
| 1503 | void i915_error_state_put(struct i915_error_state_file_priv *error_priv) | 1622 | void i915_error_state_put(struct i915_error_state_file_priv *error_priv) |
| @@ -1519,33 +1638,3 @@ void i915_destroy_error_state(struct drm_device *dev) | |||
| 1519 | if (error) | 1638 | if (error) |
| 1520 | kref_put(&error->ref, i915_error_state_free); | 1639 | kref_put(&error->ref, i915_error_state_free); |
| 1521 | } | 1640 | } |
| 1522 | |||
| 1523 | const char *i915_cache_level_str(struct drm_i915_private *i915, int type) | ||
| 1524 | { | ||
| 1525 | switch (type) { | ||
| 1526 | case I915_CACHE_NONE: return " uncached"; | ||
| 1527 | case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped"; | ||
| 1528 | case I915_CACHE_L3_LLC: return " L3+LLC"; | ||
| 1529 | case I915_CACHE_WT: return " WT"; | ||
| 1530 | default: return ""; | ||
| 1531 | } | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | /* NB: please notice the memset */ | ||
| 1535 | void i915_get_extra_instdone(struct drm_i915_private *dev_priv, | ||
| 1536 | uint32_t *instdone) | ||
| 1537 | { | ||
| 1538 | memset(instdone, 0, sizeof(*instdone) * I915_NUM_INSTDONE_REG); | ||
| 1539 | |||
| 1540 | if (IS_GEN2(dev_priv) || IS_GEN3(dev_priv)) | ||
| 1541 | instdone[0] = I915_READ(GEN2_INSTDONE); | ||
| 1542 | else if (IS_GEN4(dev_priv) || IS_GEN5(dev_priv) || IS_GEN6(dev_priv)) { | ||
| 1543 | instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE)); | ||
| 1544 | instdone[1] = I915_READ(GEN4_INSTDONE1); | ||
| 1545 | } else if (INTEL_GEN(dev_priv) >= 7) { | ||
| 1546 | instdone[0] = I915_READ(RING_INSTDONE(RENDER_RING_BASE)); | ||
| 1547 | instdone[1] = I915_READ(GEN7_SC_INSTDONE); | ||
| 1548 | instdone[2] = I915_READ(GEN7_SAMPLER_INSTDONE); | ||
| 1549 | instdone[3] = I915_READ(GEN7_ROW_INSTDONE); | ||
| 1550 | } | ||
| 1551 | } | ||
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 43358e18d34c..a1f76c8f8cde 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c | |||
| @@ -451,6 +451,18 @@ int i915_guc_wq_reserve(struct drm_i915_gem_request *request) | |||
| 451 | return ret; | 451 | return ret; |
| 452 | } | 452 | } |
| 453 | 453 | ||
| 454 | void i915_guc_wq_unreserve(struct drm_i915_gem_request *request) | ||
| 455 | { | ||
| 456 | const size_t wqi_size = sizeof(struct guc_wq_item); | ||
| 457 | struct i915_guc_client *gc = request->i915->guc.execbuf_client; | ||
| 458 | |||
| 459 | GEM_BUG_ON(READ_ONCE(gc->wq_rsvd) < wqi_size); | ||
| 460 | |||
| 461 | spin_lock(&gc->wq_lock); | ||
| 462 | gc->wq_rsvd -= wqi_size; | ||
| 463 | spin_unlock(&gc->wq_lock); | ||
| 464 | } | ||
| 465 | |||
| 454 | /* Construct a Work Item and append it to the GuC's Work Queue */ | 466 | /* Construct a Work Item and append it to the GuC's Work Queue */ |
| 455 | static void guc_wq_item_append(struct i915_guc_client *gc, | 467 | static void guc_wq_item_append(struct i915_guc_client *gc, |
| 456 | struct drm_i915_gem_request *rq) | 468 | struct drm_i915_gem_request *rq) |
| @@ -905,6 +917,7 @@ static void guc_addon_create(struct intel_guc *guc) | |||
| 905 | struct guc_policies *policies; | 917 | struct guc_policies *policies; |
| 906 | struct guc_mmio_reg_state *reg_state; | 918 | struct guc_mmio_reg_state *reg_state; |
| 907 | struct intel_engine_cs *engine; | 919 | struct intel_engine_cs *engine; |
| 920 | enum intel_engine_id id; | ||
| 908 | struct page *page; | 921 | struct page *page; |
| 909 | u32 size; | 922 | u32 size; |
| 910 | 923 | ||
| @@ -932,10 +945,10 @@ static void guc_addon_create(struct intel_guc *guc) | |||
| 932 | * so its address won't change after we've told the GuC where | 945 | * so its address won't change after we've told the GuC where |
| 933 | * to find it. | 946 | * to find it. |
| 934 | */ | 947 | */ |
| 935 | engine = &dev_priv->engine[RCS]; | 948 | engine = dev_priv->engine[RCS]; |
| 936 | ads->golden_context_lrca = engine->status_page.ggtt_offset; | 949 | ads->golden_context_lrca = engine->status_page.ggtt_offset; |
| 937 | 950 | ||
| 938 | for_each_engine(engine, dev_priv) | 951 | for_each_engine(engine, dev_priv, id) |
| 939 | ads->eng_state_size[engine->guc_id] = intel_lr_context_size(engine); | 952 | ads->eng_state_size[engine->guc_id] = intel_lr_context_size(engine); |
| 940 | 953 | ||
| 941 | /* GuC scheduling policies */ | 954 | /* GuC scheduling policies */ |
| @@ -948,7 +961,7 @@ static void guc_addon_create(struct intel_guc *guc) | |||
| 948 | /* MMIO reg state */ | 961 | /* MMIO reg state */ |
| 949 | reg_state = (void *)policies + sizeof(struct guc_policies); | 962 | reg_state = (void *)policies + sizeof(struct guc_policies); |
| 950 | 963 | ||
| 951 | for_each_engine(engine, dev_priv) { | 964 | for_each_engine(engine, dev_priv, id) { |
| 952 | reg_state->mmio_white_list[engine->guc_id].mmio_start = | 965 | reg_state->mmio_white_list[engine->guc_id].mmio_start = |
| 953 | engine->mmio_base + GUC_MMIO_WHITE_LIST_START; | 966 | engine->mmio_base + GUC_MMIO_WHITE_LIST_START; |
| 954 | 967 | ||
| @@ -1002,9 +1015,10 @@ int i915_guc_submission_init(struct drm_i915_private *dev_priv) | |||
| 1002 | int i915_guc_submission_enable(struct drm_i915_private *dev_priv) | 1015 | int i915_guc_submission_enable(struct drm_i915_private *dev_priv) |
| 1003 | { | 1016 | { |
| 1004 | struct intel_guc *guc = &dev_priv->guc; | 1017 | struct intel_guc *guc = &dev_priv->guc; |
| 1018 | struct drm_i915_gem_request *request; | ||
| 1005 | struct i915_guc_client *client; | 1019 | struct i915_guc_client *client; |
| 1006 | struct intel_engine_cs *engine; | 1020 | struct intel_engine_cs *engine; |
| 1007 | struct drm_i915_gem_request *request; | 1021 | enum intel_engine_id id; |
| 1008 | 1022 | ||
| 1009 | /* client for execbuf submission */ | 1023 | /* client for execbuf submission */ |
| 1010 | client = guc_client_alloc(dev_priv, | 1024 | client = guc_client_alloc(dev_priv, |
| @@ -1021,7 +1035,7 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) | |||
| 1021 | guc_init_doorbell_hw(guc); | 1035 | guc_init_doorbell_hw(guc); |
| 1022 | 1036 | ||
| 1023 | /* Take over from manual control of ELSP (execlists) */ | 1037 | /* Take over from manual control of ELSP (execlists) */ |
| 1024 | for_each_engine(engine, dev_priv) { | 1038 | for_each_engine(engine, dev_priv, id) { |
| 1025 | engine->submit_request = i915_guc_submit; | 1039 | engine->submit_request = i915_guc_submit; |
| 1026 | 1040 | ||
| 1027 | /* Replay the current set of previously submitted requests */ | 1041 | /* Replay the current set of previously submitted requests */ |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index c128fdbd24e4..23315e5461bf 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -350,6 +350,9 @@ void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv) | |||
| 350 | 350 | ||
| 351 | void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv) | 351 | void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv) |
| 352 | { | 352 | { |
| 353 | if (READ_ONCE(dev_priv->rps.interrupts_enabled)) | ||
| 354 | return; | ||
| 355 | |||
| 353 | spin_lock_irq(&dev_priv->irq_lock); | 356 | spin_lock_irq(&dev_priv->irq_lock); |
| 354 | WARN_ON_ONCE(dev_priv->rps.pm_iir); | 357 | WARN_ON_ONCE(dev_priv->rps.pm_iir); |
| 355 | WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); | 358 | WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); |
| @@ -368,6 +371,9 @@ u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask) | |||
| 368 | 371 | ||
| 369 | void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) | 372 | void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) |
| 370 | { | 373 | { |
| 374 | if (!READ_ONCE(dev_priv->rps.interrupts_enabled)) | ||
| 375 | return; | ||
| 376 | |||
| 371 | spin_lock_irq(&dev_priv->irq_lock); | 377 | spin_lock_irq(&dev_priv->irq_lock); |
| 372 | dev_priv->rps.interrupts_enabled = false; | 378 | dev_priv->rps.interrupts_enabled = false; |
| 373 | 379 | ||
| @@ -1052,8 +1058,9 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) | |||
| 1052 | static bool any_waiters(struct drm_i915_private *dev_priv) | 1058 | static bool any_waiters(struct drm_i915_private *dev_priv) |
| 1053 | { | 1059 | { |
| 1054 | struct intel_engine_cs *engine; | 1060 | struct intel_engine_cs *engine; |
| 1061 | enum intel_engine_id id; | ||
| 1055 | 1062 | ||
| 1056 | for_each_engine(engine, dev_priv) | 1063 | for_each_engine(engine, dev_priv, id) |
| 1057 | if (intel_engine_has_waiter(engine)) | 1064 | if (intel_engine_has_waiter(engine)) |
| 1058 | return true; | 1065 | return true; |
| 1059 | 1066 | ||
| @@ -1251,20 +1258,20 @@ static void ilk_gt_irq_handler(struct drm_i915_private *dev_priv, | |||
| 1251 | u32 gt_iir) | 1258 | u32 gt_iir) |
| 1252 | { | 1259 | { |
| 1253 | if (gt_iir & GT_RENDER_USER_INTERRUPT) | 1260 | if (gt_iir & GT_RENDER_USER_INTERRUPT) |
| 1254 | notify_ring(&dev_priv->engine[RCS]); | 1261 | notify_ring(dev_priv->engine[RCS]); |
| 1255 | if (gt_iir & ILK_BSD_USER_INTERRUPT) | 1262 | if (gt_iir & ILK_BSD_USER_INTERRUPT) |
| 1256 | notify_ring(&dev_priv->engine[VCS]); | 1263 | notify_ring(dev_priv->engine[VCS]); |
| 1257 | } | 1264 | } |
| 1258 | 1265 | ||
| 1259 | static void snb_gt_irq_handler(struct drm_i915_private *dev_priv, | 1266 | static void snb_gt_irq_handler(struct drm_i915_private *dev_priv, |
| 1260 | u32 gt_iir) | 1267 | u32 gt_iir) |
| 1261 | { | 1268 | { |
| 1262 | if (gt_iir & GT_RENDER_USER_INTERRUPT) | 1269 | if (gt_iir & GT_RENDER_USER_INTERRUPT) |
| 1263 | notify_ring(&dev_priv->engine[RCS]); | 1270 | notify_ring(dev_priv->engine[RCS]); |
| 1264 | if (gt_iir & GT_BSD_USER_INTERRUPT) | 1271 | if (gt_iir & GT_BSD_USER_INTERRUPT) |
| 1265 | notify_ring(&dev_priv->engine[VCS]); | 1272 | notify_ring(dev_priv->engine[VCS]); |
| 1266 | if (gt_iir & GT_BLT_USER_INTERRUPT) | 1273 | if (gt_iir & GT_BLT_USER_INTERRUPT) |
| 1267 | notify_ring(&dev_priv->engine[BCS]); | 1274 | notify_ring(dev_priv->engine[BCS]); |
| 1268 | 1275 | ||
| 1269 | if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT | | 1276 | if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT | |
| 1270 | GT_BSD_CS_ERROR_INTERRUPT | | 1277 | GT_BSD_CS_ERROR_INTERRUPT | |
| @@ -1334,21 +1341,21 @@ static void gen8_gt_irq_handler(struct drm_i915_private *dev_priv, | |||
| 1334 | u32 gt_iir[4]) | 1341 | u32 gt_iir[4]) |
| 1335 | { | 1342 | { |
| 1336 | if (gt_iir[0]) { | 1343 | if (gt_iir[0]) { |
| 1337 | gen8_cs_irq_handler(&dev_priv->engine[RCS], | 1344 | gen8_cs_irq_handler(dev_priv->engine[RCS], |
| 1338 | gt_iir[0], GEN8_RCS_IRQ_SHIFT); | 1345 | gt_iir[0], GEN8_RCS_IRQ_SHIFT); |
| 1339 | gen8_cs_irq_handler(&dev_priv->engine[BCS], | 1346 | gen8_cs_irq_handler(dev_priv->engine[BCS], |
| 1340 | gt_iir[0], GEN8_BCS_IRQ_SHIFT); | 1347 | gt_iir[0], GEN8_BCS_IRQ_SHIFT); |
| 1341 | } | 1348 | } |
| 1342 | 1349 | ||
| 1343 | if (gt_iir[1]) { | 1350 | if (gt_iir[1]) { |
| 1344 | gen8_cs_irq_handler(&dev_priv->engine[VCS], | 1351 | gen8_cs_irq_handler(dev_priv->engine[VCS], |
| 1345 | gt_iir[1], GEN8_VCS1_IRQ_SHIFT); | 1352 | gt_iir[1], GEN8_VCS1_IRQ_SHIFT); |
| 1346 | gen8_cs_irq_handler(&dev_priv->engine[VCS2], | 1353 | gen8_cs_irq_handler(dev_priv->engine[VCS2], |
| 1347 | gt_iir[1], GEN8_VCS2_IRQ_SHIFT); | 1354 | gt_iir[1], GEN8_VCS2_IRQ_SHIFT); |
| 1348 | } | 1355 | } |
| 1349 | 1356 | ||
| 1350 | if (gt_iir[3]) | 1357 | if (gt_iir[3]) |
| 1351 | gen8_cs_irq_handler(&dev_priv->engine[VECS], | 1358 | gen8_cs_irq_handler(dev_priv->engine[VECS], |
| 1352 | gt_iir[3], GEN8_VECS_IRQ_SHIFT); | 1359 | gt_iir[3], GEN8_VECS_IRQ_SHIFT); |
| 1353 | 1360 | ||
| 1354 | if (gt_iir[2] & dev_priv->pm_rps_events) | 1361 | if (gt_iir[2] & dev_priv->pm_rps_events) |
| @@ -1592,7 +1599,7 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) | |||
| 1592 | 1599 | ||
| 1593 | if (HAS_VEBOX(dev_priv)) { | 1600 | if (HAS_VEBOX(dev_priv)) { |
| 1594 | if (pm_iir & PM_VEBOX_USER_INTERRUPT) | 1601 | if (pm_iir & PM_VEBOX_USER_INTERRUPT) |
| 1595 | notify_ring(&dev_priv->engine[VECS]); | 1602 | notify_ring(dev_priv->engine[VECS]); |
| 1596 | 1603 | ||
| 1597 | if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) | 1604 | if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) |
| 1598 | DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir); | 1605 | DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir); |
| @@ -2545,92 +2552,52 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv) | |||
| 2545 | wake_up_all(&dev_priv->gpu_error.reset_queue); | 2552 | wake_up_all(&dev_priv->gpu_error.reset_queue); |
| 2546 | } | 2553 | } |
| 2547 | 2554 | ||
| 2548 | static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv) | 2555 | static inline void |
| 2556 | i915_err_print_instdone(struct drm_i915_private *dev_priv, | ||
| 2557 | struct intel_instdone *instdone) | ||
| 2549 | { | 2558 | { |
| 2550 | uint32_t instdone[I915_NUM_INSTDONE_REG]; | 2559 | int slice; |
| 2551 | u32 eir = I915_READ(EIR); | 2560 | int subslice; |
| 2552 | int pipe, i; | 2561 | |
| 2562 | pr_err(" INSTDONE: 0x%08x\n", instdone->instdone); | ||
| 2553 | 2563 | ||
| 2554 | if (!eir) | 2564 | if (INTEL_GEN(dev_priv) <= 3) |
| 2555 | return; | 2565 | return; |
| 2556 | 2566 | ||
| 2557 | pr_err("render error detected, EIR: 0x%08x\n", eir); | 2567 | pr_err(" SC_INSTDONE: 0x%08x\n", instdone->slice_common); |
| 2558 | 2568 | ||
| 2559 | i915_get_extra_instdone(dev_priv, instdone); | 2569 | if (INTEL_GEN(dev_priv) <= 6) |
| 2570 | return; | ||
| 2560 | 2571 | ||
| 2561 | if (IS_G4X(dev_priv)) { | 2572 | for_each_instdone_slice_subslice(dev_priv, slice, subslice) |
| 2562 | if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) { | 2573 | pr_err(" SAMPLER_INSTDONE[%d][%d]: 0x%08x\n", |
| 2563 | u32 ipeir = I915_READ(IPEIR_I965); | 2574 | slice, subslice, instdone->sampler[slice][subslice]); |
| 2564 | |||
| 2565 | pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR_I965)); | ||
| 2566 | pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR_I965)); | ||
| 2567 | for (i = 0; i < ARRAY_SIZE(instdone); i++) | ||
| 2568 | pr_err(" INSTDONE_%d: 0x%08x\n", i, instdone[i]); | ||
| 2569 | pr_err(" INSTPS: 0x%08x\n", I915_READ(INSTPS)); | ||
| 2570 | pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD_I965)); | ||
| 2571 | I915_WRITE(IPEIR_I965, ipeir); | ||
| 2572 | POSTING_READ(IPEIR_I965); | ||
| 2573 | } | ||
| 2574 | if (eir & GM45_ERROR_PAGE_TABLE) { | ||
| 2575 | u32 pgtbl_err = I915_READ(PGTBL_ER); | ||
| 2576 | pr_err("page table error\n"); | ||
| 2577 | pr_err(" PGTBL_ER: 0x%08x\n", pgtbl_err); | ||
| 2578 | I915_WRITE(PGTBL_ER, pgtbl_err); | ||
| 2579 | POSTING_READ(PGTBL_ER); | ||
| 2580 | } | ||
| 2581 | } | ||
| 2582 | 2575 | ||
| 2583 | if (!IS_GEN2(dev_priv)) { | 2576 | for_each_instdone_slice_subslice(dev_priv, slice, subslice) |
| 2584 | if (eir & I915_ERROR_PAGE_TABLE) { | 2577 | pr_err(" ROW_INSTDONE[%d][%d]: 0x%08x\n", |
| 2585 | u32 pgtbl_err = I915_READ(PGTBL_ER); | 2578 | slice, subslice, instdone->row[slice][subslice]); |
| 2586 | pr_err("page table error\n"); | 2579 | } |
| 2587 | pr_err(" PGTBL_ER: 0x%08x\n", pgtbl_err); | ||
| 2588 | I915_WRITE(PGTBL_ER, pgtbl_err); | ||
| 2589 | POSTING_READ(PGTBL_ER); | ||
| 2590 | } | ||
| 2591 | } | ||
| 2592 | 2580 | ||
| 2593 | if (eir & I915_ERROR_MEMORY_REFRESH) { | 2581 | static void i915_clear_error_registers(struct drm_i915_private *dev_priv) |
| 2594 | pr_err("memory refresh error:\n"); | 2582 | { |
| 2595 | for_each_pipe(dev_priv, pipe) | 2583 | u32 eir; |
| 2596 | pr_err("pipe %c stat: 0x%08x\n", | ||
| 2597 | pipe_name(pipe), I915_READ(PIPESTAT(pipe))); | ||
| 2598 | /* pipestat has already been acked */ | ||
| 2599 | } | ||
| 2600 | if (eir & I915_ERROR_INSTRUCTION) { | ||
| 2601 | pr_err("instruction error\n"); | ||
| 2602 | pr_err(" INSTPM: 0x%08x\n", I915_READ(INSTPM)); | ||
| 2603 | for (i = 0; i < ARRAY_SIZE(instdone); i++) | ||
| 2604 | pr_err(" INSTDONE_%d: 0x%08x\n", i, instdone[i]); | ||
| 2605 | if (INTEL_GEN(dev_priv) < 4) { | ||
| 2606 | u32 ipeir = I915_READ(IPEIR); | ||
| 2607 | |||
| 2608 | pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR)); | ||
| 2609 | pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR)); | ||
| 2610 | pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD)); | ||
| 2611 | I915_WRITE(IPEIR, ipeir); | ||
| 2612 | POSTING_READ(IPEIR); | ||
| 2613 | } else { | ||
| 2614 | u32 ipeir = I915_READ(IPEIR_I965); | ||
| 2615 | |||
| 2616 | pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR_I965)); | ||
| 2617 | pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR_I965)); | ||
| 2618 | pr_err(" INSTPS: 0x%08x\n", I915_READ(INSTPS)); | ||
| 2619 | pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD_I965)); | ||
| 2620 | I915_WRITE(IPEIR_I965, ipeir); | ||
| 2621 | POSTING_READ(IPEIR_I965); | ||
| 2622 | } | ||
| 2623 | } | ||
| 2624 | 2584 | ||
| 2625 | I915_WRITE(EIR, eir); | 2585 | if (!IS_GEN2(dev_priv)) |
| 2626 | POSTING_READ(EIR); | 2586 | I915_WRITE(PGTBL_ER, I915_READ(PGTBL_ER)); |
| 2587 | |||
| 2588 | if (INTEL_GEN(dev_priv) < 4) | ||
| 2589 | I915_WRITE(IPEIR, I915_READ(IPEIR)); | ||
| 2590 | else | ||
| 2591 | I915_WRITE(IPEIR_I965, I915_READ(IPEIR_I965)); | ||
| 2592 | |||
| 2593 | I915_WRITE(EIR, I915_READ(EIR)); | ||
| 2627 | eir = I915_READ(EIR); | 2594 | eir = I915_READ(EIR); |
| 2628 | if (eir) { | 2595 | if (eir) { |
| 2629 | /* | 2596 | /* |
| 2630 | * some errors might have become stuck, | 2597 | * some errors might have become stuck, |
| 2631 | * mask them. | 2598 | * mask them. |
| 2632 | */ | 2599 | */ |
| 2633 | DRM_ERROR("EIR stuck: 0x%08x, masking\n", eir); | 2600 | DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masking\n", eir); |
| 2634 | I915_WRITE(EMR, I915_READ(EMR) | eir); | 2601 | I915_WRITE(EMR, I915_READ(EMR) | eir); |
| 2635 | I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); | 2602 | I915_WRITE(IIR, I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); |
| 2636 | } | 2603 | } |
| @@ -2659,7 +2626,7 @@ void i915_handle_error(struct drm_i915_private *dev_priv, | |||
| 2659 | va_end(args); | 2626 | va_end(args); |
| 2660 | 2627 | ||
| 2661 | i915_capture_error_state(dev_priv, engine_mask, error_msg); | 2628 | i915_capture_error_state(dev_priv, engine_mask, error_msg); |
| 2662 | i915_report_and_clear_eir(dev_priv); | 2629 | i915_clear_error_registers(dev_priv); |
| 2663 | 2630 | ||
| 2664 | if (!engine_mask) | 2631 | if (!engine_mask) |
| 2665 | return; | 2632 | return; |
| @@ -2688,45 +2655,40 @@ void i915_handle_error(struct drm_i915_private *dev_priv, | |||
| 2688 | /* Called from drm generic code, passed 'crtc' which | 2655 | /* Called from drm generic code, passed 'crtc' which |
| 2689 | * we use as a pipe index | 2656 | * we use as a pipe index |
| 2690 | */ | 2657 | */ |
| 2691 | static int i915_enable_vblank(struct drm_device *dev, unsigned int pipe) | 2658 | static int i8xx_enable_vblank(struct drm_device *dev, unsigned int pipe) |
| 2692 | { | 2659 | { |
| 2693 | struct drm_i915_private *dev_priv = to_i915(dev); | 2660 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2694 | unsigned long irqflags; | 2661 | unsigned long irqflags; |
| 2695 | 2662 | ||
| 2696 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 2663 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
| 2697 | if (INTEL_INFO(dev)->gen >= 4) | 2664 | i915_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); |
| 2698 | i915_enable_pipestat(dev_priv, pipe, | ||
| 2699 | PIPE_START_VBLANK_INTERRUPT_STATUS); | ||
| 2700 | else | ||
| 2701 | i915_enable_pipestat(dev_priv, pipe, | ||
| 2702 | PIPE_VBLANK_INTERRUPT_STATUS); | ||
| 2703 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 2665 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 2704 | 2666 | ||
| 2705 | return 0; | 2667 | return 0; |
| 2706 | } | 2668 | } |
| 2707 | 2669 | ||
| 2708 | static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) | 2670 | static int i965_enable_vblank(struct drm_device *dev, unsigned int pipe) |
| 2709 | { | 2671 | { |
| 2710 | struct drm_i915_private *dev_priv = to_i915(dev); | 2672 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2711 | unsigned long irqflags; | 2673 | unsigned long irqflags; |
| 2712 | uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) : | ||
| 2713 | DE_PIPE_VBLANK(pipe); | ||
| 2714 | 2674 | ||
| 2715 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 2675 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
| 2716 | ilk_enable_display_irq(dev_priv, bit); | 2676 | i915_enable_pipestat(dev_priv, pipe, |
| 2677 | PIPE_START_VBLANK_INTERRUPT_STATUS); | ||
| 2717 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 2678 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 2718 | 2679 | ||
| 2719 | return 0; | 2680 | return 0; |
| 2720 | } | 2681 | } |
| 2721 | 2682 | ||
| 2722 | static int valleyview_enable_vblank(struct drm_device *dev, unsigned int pipe) | 2683 | static int ironlake_enable_vblank(struct drm_device *dev, unsigned int pipe) |
| 2723 | { | 2684 | { |
| 2724 | struct drm_i915_private *dev_priv = to_i915(dev); | 2685 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2725 | unsigned long irqflags; | 2686 | unsigned long irqflags; |
| 2687 | uint32_t bit = INTEL_GEN(dev_priv) >= 7 ? | ||
| 2688 | DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); | ||
| 2726 | 2689 | ||
| 2727 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 2690 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
| 2728 | i915_enable_pipestat(dev_priv, pipe, | 2691 | ilk_enable_display_irq(dev_priv, bit); |
| 2729 | PIPE_START_VBLANK_INTERRUPT_STATUS); | ||
| 2730 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 2692 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 2731 | 2693 | ||
| 2732 | return 0; | 2694 | return 0; |
| @@ -2747,38 +2709,36 @@ static int gen8_enable_vblank(struct drm_device *dev, unsigned int pipe) | |||
| 2747 | /* Called from drm generic code, passed 'crtc' which | 2709 | /* Called from drm generic code, passed 'crtc' which |
| 2748 | * we use as a pipe index | 2710 | * we use as a pipe index |
| 2749 | */ | 2711 | */ |
| 2750 | static void i915_disable_vblank(struct drm_device *dev, unsigned int pipe) | 2712 | static void i8xx_disable_vblank(struct drm_device *dev, unsigned int pipe) |
| 2751 | { | 2713 | { |
| 2752 | struct drm_i915_private *dev_priv = to_i915(dev); | 2714 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2753 | unsigned long irqflags; | 2715 | unsigned long irqflags; |
| 2754 | 2716 | ||
| 2755 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 2717 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
| 2756 | i915_disable_pipestat(dev_priv, pipe, | 2718 | i915_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_STATUS); |
| 2757 | PIPE_VBLANK_INTERRUPT_STATUS | | ||
| 2758 | PIPE_START_VBLANK_INTERRUPT_STATUS); | ||
| 2759 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 2719 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 2760 | } | 2720 | } |
| 2761 | 2721 | ||
| 2762 | static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe) | 2722 | static void i965_disable_vblank(struct drm_device *dev, unsigned int pipe) |
| 2763 | { | 2723 | { |
| 2764 | struct drm_i915_private *dev_priv = to_i915(dev); | 2724 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2765 | unsigned long irqflags; | 2725 | unsigned long irqflags; |
| 2766 | uint32_t bit = (INTEL_INFO(dev)->gen >= 7) ? DE_PIPE_VBLANK_IVB(pipe) : | ||
| 2767 | DE_PIPE_VBLANK(pipe); | ||
| 2768 | 2726 | ||
| 2769 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 2727 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
| 2770 | ilk_disable_display_irq(dev_priv, bit); | 2728 | i915_disable_pipestat(dev_priv, pipe, |
| 2729 | PIPE_START_VBLANK_INTERRUPT_STATUS); | ||
| 2771 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 2730 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 2772 | } | 2731 | } |
| 2773 | 2732 | ||
| 2774 | static void valleyview_disable_vblank(struct drm_device *dev, unsigned int pipe) | 2733 | static void ironlake_disable_vblank(struct drm_device *dev, unsigned int pipe) |
| 2775 | { | 2734 | { |
| 2776 | struct drm_i915_private *dev_priv = to_i915(dev); | 2735 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2777 | unsigned long irqflags; | 2736 | unsigned long irqflags; |
| 2737 | uint32_t bit = INTEL_GEN(dev_priv) >= 7 ? | ||
| 2738 | DE_PIPE_VBLANK_IVB(pipe) : DE_PIPE_VBLANK(pipe); | ||
| 2778 | 2739 | ||
| 2779 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); | 2740 | spin_lock_irqsave(&dev_priv->irq_lock, irqflags); |
| 2780 | i915_disable_pipestat(dev_priv, pipe, | 2741 | ilk_disable_display_irq(dev_priv, bit); |
| 2781 | PIPE_START_VBLANK_INTERRUPT_STATUS); | ||
| 2782 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); | 2742 | spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags); |
| 2783 | } | 2743 | } |
| 2784 | 2744 | ||
| @@ -2810,29 +2770,30 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr, | |||
| 2810 | { | 2770 | { |
| 2811 | struct drm_i915_private *dev_priv = engine->i915; | 2771 | struct drm_i915_private *dev_priv = engine->i915; |
| 2812 | struct intel_engine_cs *signaller; | 2772 | struct intel_engine_cs *signaller; |
| 2773 | enum intel_engine_id id; | ||
| 2813 | 2774 | ||
| 2814 | if (INTEL_GEN(dev_priv) >= 8) { | 2775 | if (INTEL_GEN(dev_priv) >= 8) { |
| 2815 | for_each_engine(signaller, dev_priv) { | 2776 | for_each_engine(signaller, dev_priv, id) { |
| 2816 | if (engine == signaller) | 2777 | if (engine == signaller) |
| 2817 | continue; | 2778 | continue; |
| 2818 | 2779 | ||
| 2819 | if (offset == signaller->semaphore.signal_ggtt[engine->id]) | 2780 | if (offset == signaller->semaphore.signal_ggtt[engine->hw_id]) |
| 2820 | return signaller; | 2781 | return signaller; |
| 2821 | } | 2782 | } |
| 2822 | } else { | 2783 | } else { |
| 2823 | u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK; | 2784 | u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK; |
| 2824 | 2785 | ||
| 2825 | for_each_engine(signaller, dev_priv) { | 2786 | for_each_engine(signaller, dev_priv, id) { |
| 2826 | if(engine == signaller) | 2787 | if(engine == signaller) |
| 2827 | continue; | 2788 | continue; |
| 2828 | 2789 | ||
| 2829 | if (sync_bits == signaller->semaphore.mbox.wait[engine->id]) | 2790 | if (sync_bits == signaller->semaphore.mbox.wait[engine->hw_id]) |
| 2830 | return signaller; | 2791 | return signaller; |
| 2831 | } | 2792 | } |
| 2832 | } | 2793 | } |
| 2833 | 2794 | ||
| 2834 | DRM_DEBUG_DRIVER("No signaller ring found for ring %i, ipehr 0x%08x, offset 0x%016llx\n", | 2795 | DRM_DEBUG_DRIVER("No signaller ring found for %s, ipehr 0x%08x, offset 0x%016llx\n", |
| 2835 | engine->id, ipehr, offset); | 2796 | engine->name, ipehr, offset); |
| 2836 | 2797 | ||
| 2837 | return ERR_PTR(-ENODEV); | 2798 | return ERR_PTR(-ENODEV); |
| 2838 | } | 2799 | } |
| @@ -2943,35 +2904,52 @@ static int semaphore_passed(struct intel_engine_cs *engine) | |||
| 2943 | static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) | 2904 | static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv) |
| 2944 | { | 2905 | { |
| 2945 | struct intel_engine_cs *engine; | 2906 | struct intel_engine_cs *engine; |
| 2907 | enum intel_engine_id id; | ||
| 2946 | 2908 | ||
| 2947 | for_each_engine(engine, dev_priv) | 2909 | for_each_engine(engine, dev_priv, id) |
| 2948 | engine->hangcheck.deadlock = 0; | 2910 | engine->hangcheck.deadlock = 0; |
| 2949 | } | 2911 | } |
| 2950 | 2912 | ||
| 2913 | static bool instdone_unchanged(u32 current_instdone, u32 *old_instdone) | ||
| 2914 | { | ||
| 2915 | u32 tmp = current_instdone | *old_instdone; | ||
| 2916 | bool unchanged; | ||
| 2917 | |||
| 2918 | unchanged = tmp == *old_instdone; | ||
| 2919 | *old_instdone |= tmp; | ||
| 2920 | |||
| 2921 | return unchanged; | ||
| 2922 | } | ||
| 2923 | |||
| 2951 | static bool subunits_stuck(struct intel_engine_cs *engine) | 2924 | static bool subunits_stuck(struct intel_engine_cs *engine) |
| 2952 | { | 2925 | { |
| 2953 | u32 instdone[I915_NUM_INSTDONE_REG]; | 2926 | struct drm_i915_private *dev_priv = engine->i915; |
| 2927 | struct intel_instdone instdone; | ||
| 2928 | struct intel_instdone *accu_instdone = &engine->hangcheck.instdone; | ||
| 2954 | bool stuck; | 2929 | bool stuck; |
| 2955 | int i; | 2930 | int slice; |
| 2931 | int subslice; | ||
| 2956 | 2932 | ||
| 2957 | if (engine->id != RCS) | 2933 | if (engine->id != RCS) |
| 2958 | return true; | 2934 | return true; |
| 2959 | 2935 | ||
| 2960 | i915_get_extra_instdone(engine->i915, instdone); | 2936 | intel_engine_get_instdone(engine, &instdone); |
| 2961 | 2937 | ||
| 2962 | /* There might be unstable subunit states even when | 2938 | /* There might be unstable subunit states even when |
| 2963 | * actual head is not moving. Filter out the unstable ones by | 2939 | * actual head is not moving. Filter out the unstable ones by |
| 2964 | * accumulating the undone -> done transitions and only | 2940 | * accumulating the undone -> done transitions and only |
| 2965 | * consider those as progress. | 2941 | * consider those as progress. |
| 2966 | */ | 2942 | */ |
| 2967 | stuck = true; | 2943 | stuck = instdone_unchanged(instdone.instdone, |
| 2968 | for (i = 0; i < I915_NUM_INSTDONE_REG; i++) { | 2944 | &accu_instdone->instdone); |
| 2969 | const u32 tmp = instdone[i] | engine->hangcheck.instdone[i]; | 2945 | stuck &= instdone_unchanged(instdone.slice_common, |
| 2970 | 2946 | &accu_instdone->slice_common); | |
| 2971 | if (tmp != engine->hangcheck.instdone[i]) | 2947 | |
| 2972 | stuck = false; | 2948 | for_each_instdone_slice_subslice(dev_priv, slice, subslice) { |
| 2973 | 2949 | stuck &= instdone_unchanged(instdone.sampler[slice][subslice], | |
| 2974 | engine->hangcheck.instdone[i] |= tmp; | 2950 | &accu_instdone->sampler[slice][subslice]); |
| 2951 | stuck &= instdone_unchanged(instdone.row[slice][subslice], | ||
| 2952 | &accu_instdone->row[slice][subslice]); | ||
| 2975 | } | 2953 | } |
| 2976 | 2954 | ||
| 2977 | return stuck; | 2955 | return stuck; |
| @@ -2983,7 +2961,7 @@ head_stuck(struct intel_engine_cs *engine, u64 acthd) | |||
| 2983 | if (acthd != engine->hangcheck.acthd) { | 2961 | if (acthd != engine->hangcheck.acthd) { |
| 2984 | 2962 | ||
| 2985 | /* Clear subunit states on head movement */ | 2963 | /* Clear subunit states on head movement */ |
| 2986 | memset(engine->hangcheck.instdone, 0, | 2964 | memset(&engine->hangcheck.instdone, 0, |
| 2987 | sizeof(engine->hangcheck.instdone)); | 2965 | sizeof(engine->hangcheck.instdone)); |
| 2988 | 2966 | ||
| 2989 | return HANGCHECK_ACTIVE; | 2967 | return HANGCHECK_ACTIVE; |
| @@ -3055,6 +3033,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) | |||
| 3055 | container_of(work, typeof(*dev_priv), | 3033 | container_of(work, typeof(*dev_priv), |
| 3056 | gpu_error.hangcheck_work.work); | 3034 | gpu_error.hangcheck_work.work); |
| 3057 | struct intel_engine_cs *engine; | 3035 | struct intel_engine_cs *engine; |
| 3036 | enum intel_engine_id id; | ||
| 3058 | unsigned int hung = 0, stuck = 0; | 3037 | unsigned int hung = 0, stuck = 0; |
| 3059 | int busy_count = 0; | 3038 | int busy_count = 0; |
| 3060 | #define BUSY 1 | 3039 | #define BUSY 1 |
| @@ -3074,7 +3053,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) | |||
| 3074 | */ | 3053 | */ |
| 3075 | intel_uncore_arm_unclaimed_mmio_detection(dev_priv); | 3054 | intel_uncore_arm_unclaimed_mmio_detection(dev_priv); |
| 3076 | 3055 | ||
| 3077 | for_each_engine(engine, dev_priv) { | 3056 | for_each_engine(engine, dev_priv, id) { |
| 3078 | bool busy = intel_engine_has_waiter(engine); | 3057 | bool busy = intel_engine_has_waiter(engine); |
| 3079 | u64 acthd; | 3058 | u64 acthd; |
| 3080 | u32 seqno; | 3059 | u32 seqno; |
| @@ -3153,7 +3132,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) | |||
| 3153 | /* Clear head and subunit states on seqno movement */ | 3132 | /* Clear head and subunit states on seqno movement */ |
| 3154 | acthd = 0; | 3133 | acthd = 0; |
| 3155 | 3134 | ||
| 3156 | memset(engine->hangcheck.instdone, 0, | 3135 | memset(&engine->hangcheck.instdone, 0, |
| 3157 | sizeof(engine->hangcheck.instdone)); | 3136 | sizeof(engine->hangcheck.instdone)); |
| 3158 | } | 3137 | } |
| 3159 | 3138 | ||
| @@ -3191,12 +3170,12 @@ static void ibx_irq_reset(struct drm_device *dev) | |||
| 3191 | { | 3170 | { |
| 3192 | struct drm_i915_private *dev_priv = to_i915(dev); | 3171 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 3193 | 3172 | ||
| 3194 | if (HAS_PCH_NOP(dev)) | 3173 | if (HAS_PCH_NOP(dev_priv)) |
| 3195 | return; | 3174 | return; |
| 3196 | 3175 | ||
| 3197 | GEN5_IRQ_RESET(SDE); | 3176 | GEN5_IRQ_RESET(SDE); |
| 3198 | 3177 | ||
| 3199 | if (HAS_PCH_CPT(dev) || HAS_PCH_LPT(dev)) | 3178 | if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) |
| 3200 | I915_WRITE(SERR_INT, 0xffffffff); | 3179 | I915_WRITE(SERR_INT, 0xffffffff); |
| 3201 | } | 3180 | } |
| 3202 | 3181 | ||
| @@ -3212,7 +3191,7 @@ static void ibx_irq_pre_postinstall(struct drm_device *dev) | |||
| 3212 | { | 3191 | { |
| 3213 | struct drm_i915_private *dev_priv = to_i915(dev); | 3192 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 3214 | 3193 | ||
| 3215 | if (HAS_PCH_NOP(dev)) | 3194 | if (HAS_PCH_NOP(dev_priv)) |
| 3216 | return; | 3195 | return; |
| 3217 | 3196 | ||
| 3218 | WARN_ON(I915_READ(SDEIER) != 0); | 3197 | WARN_ON(I915_READ(SDEIER) != 0); |
| @@ -3287,7 +3266,7 @@ static void ironlake_irq_reset(struct drm_device *dev) | |||
| 3287 | I915_WRITE(HWSTAM, 0xffffffff); | 3266 | I915_WRITE(HWSTAM, 0xffffffff); |
| 3288 | 3267 | ||
| 3289 | GEN5_IRQ_RESET(DE); | 3268 | GEN5_IRQ_RESET(DE); |
| 3290 | if (IS_GEN7(dev)) | 3269 | if (IS_GEN7(dev_priv)) |
| 3291 | I915_WRITE(GEN7_ERR_INT, 0xffffffff); | 3270 | I915_WRITE(GEN7_ERR_INT, 0xffffffff); |
| 3292 | 3271 | ||
| 3293 | gen5_gt_irq_reset(dev); | 3272 | gen5_gt_irq_reset(dev); |
| @@ -3337,7 +3316,7 @@ static void gen8_irq_reset(struct drm_device *dev) | |||
| 3337 | GEN5_IRQ_RESET(GEN8_DE_MISC_); | 3316 | GEN5_IRQ_RESET(GEN8_DE_MISC_); |
| 3338 | GEN5_IRQ_RESET(GEN8_PCU_); | 3317 | GEN5_IRQ_RESET(GEN8_PCU_); |
| 3339 | 3318 | ||
| 3340 | if (HAS_PCH_SPLIT(dev)) | 3319 | if (HAS_PCH_SPLIT(dev_priv)) |
| 3341 | ibx_irq_reset(dev); | 3320 | ibx_irq_reset(dev); |
| 3342 | } | 3321 | } |
| 3343 | 3322 | ||
| @@ -3526,10 +3505,10 @@ static void ibx_irq_postinstall(struct drm_device *dev) | |||
| 3526 | struct drm_i915_private *dev_priv = to_i915(dev); | 3505 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 3527 | u32 mask; | 3506 | u32 mask; |
| 3528 | 3507 | ||
| 3529 | if (HAS_PCH_NOP(dev)) | 3508 | if (HAS_PCH_NOP(dev_priv)) |
| 3530 | return; | 3509 | return; |
| 3531 | 3510 | ||
| 3532 | if (HAS_PCH_IBX(dev)) | 3511 | if (HAS_PCH_IBX(dev_priv)) |
| 3533 | mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; | 3512 | mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; |
| 3534 | else | 3513 | else |
| 3535 | mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; | 3514 | mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; |
| @@ -3546,14 +3525,14 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) | |||
| 3546 | pm_irqs = gt_irqs = 0; | 3525 | pm_irqs = gt_irqs = 0; |
| 3547 | 3526 | ||
| 3548 | dev_priv->gt_irq_mask = ~0; | 3527 | dev_priv->gt_irq_mask = ~0; |
| 3549 | if (HAS_L3_DPF(dev)) { | 3528 | if (HAS_L3_DPF(dev_priv)) { |
| 3550 | /* L3 parity interrupt is always unmasked. */ | 3529 | /* L3 parity interrupt is always unmasked. */ |
| 3551 | dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev); | 3530 | dev_priv->gt_irq_mask = ~GT_PARITY_ERROR(dev_priv); |
| 3552 | gt_irqs |= GT_PARITY_ERROR(dev); | 3531 | gt_irqs |= GT_PARITY_ERROR(dev_priv); |
| 3553 | } | 3532 | } |
| 3554 | 3533 | ||
| 3555 | gt_irqs |= GT_RENDER_USER_INTERRUPT; | 3534 | gt_irqs |= GT_RENDER_USER_INTERRUPT; |
| 3556 | if (IS_GEN5(dev)) { | 3535 | if (IS_GEN5(dev_priv)) { |
| 3557 | gt_irqs |= ILK_BSD_USER_INTERRUPT; | 3536 | gt_irqs |= ILK_BSD_USER_INTERRUPT; |
| 3558 | } else { | 3537 | } else { |
| 3559 | gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT; | 3538 | gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT; |
| @@ -3610,7 +3589,7 @@ static int ironlake_irq_postinstall(struct drm_device *dev) | |||
| 3610 | 3589 | ||
| 3611 | ibx_irq_postinstall(dev); | 3590 | ibx_irq_postinstall(dev); |
| 3612 | 3591 | ||
| 3613 | if (IS_IRONLAKE_M(dev)) { | 3592 | if (IS_IRONLAKE_M(dev_priv)) { |
| 3614 | /* Enable PCU event interrupts | 3593 | /* Enable PCU event interrupts |
| 3615 | * | 3594 | * |
| 3616 | * spinlocking not required here for correctness since interrupt | 3595 | * spinlocking not required here for correctness since interrupt |
| @@ -3750,13 +3729,13 @@ static int gen8_irq_postinstall(struct drm_device *dev) | |||
| 3750 | { | 3729 | { |
| 3751 | struct drm_i915_private *dev_priv = to_i915(dev); | 3730 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 3752 | 3731 | ||
| 3753 | if (HAS_PCH_SPLIT(dev)) | 3732 | if (HAS_PCH_SPLIT(dev_priv)) |
| 3754 | ibx_irq_pre_postinstall(dev); | 3733 | ibx_irq_pre_postinstall(dev); |
| 3755 | 3734 | ||
| 3756 | gen8_gt_irq_postinstall(dev_priv); | 3735 | gen8_gt_irq_postinstall(dev_priv); |
| 3757 | gen8_de_irq_postinstall(dev_priv); | 3736 | gen8_de_irq_postinstall(dev_priv); |
| 3758 | 3737 | ||
| 3759 | if (HAS_PCH_SPLIT(dev)) | 3738 | if (HAS_PCH_SPLIT(dev_priv)) |
| 3760 | ibx_irq_postinstall(dev); | 3739 | ibx_irq_postinstall(dev); |
| 3761 | 3740 | ||
| 3762 | I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); | 3741 | I915_WRITE(GEN8_MASTER_IRQ, GEN8_MASTER_IRQ_CONTROL); |
| @@ -3965,7 +3944,7 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) | |||
| 3965 | new_iir = I915_READ16(IIR); /* Flush posted writes */ | 3944 | new_iir = I915_READ16(IIR); /* Flush posted writes */ |
| 3966 | 3945 | ||
| 3967 | if (iir & I915_USER_INTERRUPT) | 3946 | if (iir & I915_USER_INTERRUPT) |
| 3968 | notify_ring(&dev_priv->engine[RCS]); | 3947 | notify_ring(dev_priv->engine[RCS]); |
| 3969 | 3948 | ||
| 3970 | for_each_pipe(dev_priv, pipe) { | 3949 | for_each_pipe(dev_priv, pipe) { |
| 3971 | int plane = pipe; | 3950 | int plane = pipe; |
| @@ -4162,7 +4141,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) | |||
| 4162 | new_iir = I915_READ(IIR); /* Flush posted writes */ | 4141 | new_iir = I915_READ(IIR); /* Flush posted writes */ |
| 4163 | 4142 | ||
| 4164 | if (iir & I915_USER_INTERRUPT) | 4143 | if (iir & I915_USER_INTERRUPT) |
| 4165 | notify_ring(&dev_priv->engine[RCS]); | 4144 | notify_ring(dev_priv->engine[RCS]); |
| 4166 | 4145 | ||
| 4167 | for_each_pipe(dev_priv, pipe) { | 4146 | for_each_pipe(dev_priv, pipe) { |
| 4168 | int plane = pipe; | 4147 | int plane = pipe; |
| @@ -4394,9 +4373,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) | |||
| 4394 | new_iir = I915_READ(IIR); /* Flush posted writes */ | 4373 | new_iir = I915_READ(IIR); /* Flush posted writes */ |
| 4395 | 4374 | ||
| 4396 | if (iir & I915_USER_INTERRUPT) | 4375 | if (iir & I915_USER_INTERRUPT) |
| 4397 | notify_ring(&dev_priv->engine[RCS]); | 4376 | notify_ring(dev_priv->engine[RCS]); |
| 4398 | if (iir & I915_BSD_USER_INTERRUPT) | 4377 | if (iir & I915_BSD_USER_INTERRUPT) |
| 4399 | notify_ring(&dev_priv->engine[VCS]); | 4378 | notify_ring(dev_priv->engine[VCS]); |
| 4400 | 4379 | ||
| 4401 | for_each_pipe(dev_priv, pipe) { | 4380 | for_each_pipe(dev_priv, pipe) { |
| 4402 | if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS && | 4381 | if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS && |
| @@ -4533,16 +4512,16 @@ void intel_irq_init(struct drm_i915_private *dev_priv) | |||
| 4533 | dev->driver->irq_preinstall = cherryview_irq_preinstall; | 4512 | dev->driver->irq_preinstall = cherryview_irq_preinstall; |
| 4534 | dev->driver->irq_postinstall = cherryview_irq_postinstall; | 4513 | dev->driver->irq_postinstall = cherryview_irq_postinstall; |
| 4535 | dev->driver->irq_uninstall = cherryview_irq_uninstall; | 4514 | dev->driver->irq_uninstall = cherryview_irq_uninstall; |
| 4536 | dev->driver->enable_vblank = valleyview_enable_vblank; | 4515 | dev->driver->enable_vblank = i965_enable_vblank; |
| 4537 | dev->driver->disable_vblank = valleyview_disable_vblank; | 4516 | dev->driver->disable_vblank = i965_disable_vblank; |
| 4538 | dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; | 4517 | dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; |
| 4539 | } else if (IS_VALLEYVIEW(dev_priv)) { | 4518 | } else if (IS_VALLEYVIEW(dev_priv)) { |
| 4540 | dev->driver->irq_handler = valleyview_irq_handler; | 4519 | dev->driver->irq_handler = valleyview_irq_handler; |
| 4541 | dev->driver->irq_preinstall = valleyview_irq_preinstall; | 4520 | dev->driver->irq_preinstall = valleyview_irq_preinstall; |
| 4542 | dev->driver->irq_postinstall = valleyview_irq_postinstall; | 4521 | dev->driver->irq_postinstall = valleyview_irq_postinstall; |
| 4543 | dev->driver->irq_uninstall = valleyview_irq_uninstall; | 4522 | dev->driver->irq_uninstall = valleyview_irq_uninstall; |
| 4544 | dev->driver->enable_vblank = valleyview_enable_vblank; | 4523 | dev->driver->enable_vblank = i965_enable_vblank; |
| 4545 | dev->driver->disable_vblank = valleyview_disable_vblank; | 4524 | dev->driver->disable_vblank = i965_disable_vblank; |
| 4546 | dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; | 4525 | dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; |
| 4547 | } else if (INTEL_INFO(dev_priv)->gen >= 8) { | 4526 | } else if (INTEL_INFO(dev_priv)->gen >= 8) { |
| 4548 | dev->driver->irq_handler = gen8_irq_handler; | 4527 | dev->driver->irq_handler = gen8_irq_handler; |
| @@ -4551,13 +4530,13 @@ void intel_irq_init(struct drm_i915_private *dev_priv) | |||
| 4551 | dev->driver->irq_uninstall = gen8_irq_uninstall; | 4530 | dev->driver->irq_uninstall = gen8_irq_uninstall; |
| 4552 | dev->driver->enable_vblank = gen8_enable_vblank; | 4531 | dev->driver->enable_vblank = gen8_enable_vblank; |
| 4553 | dev->driver->disable_vblank = gen8_disable_vblank; | 4532 | dev->driver->disable_vblank = gen8_disable_vblank; |
| 4554 | if (IS_BROXTON(dev)) | 4533 | if (IS_BROXTON(dev_priv)) |
| 4555 | dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; | 4534 | dev_priv->display.hpd_irq_setup = bxt_hpd_irq_setup; |
| 4556 | else if (HAS_PCH_SPT(dev) || HAS_PCH_KBP(dev)) | 4535 | else if (HAS_PCH_SPT(dev_priv) || HAS_PCH_KBP(dev_priv)) |
| 4557 | dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; | 4536 | dev_priv->display.hpd_irq_setup = spt_hpd_irq_setup; |
| 4558 | else | 4537 | else |
| 4559 | dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; | 4538 | dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; |
| 4560 | } else if (HAS_PCH_SPLIT(dev)) { | 4539 | } else if (HAS_PCH_SPLIT(dev_priv)) { |
| 4561 | dev->driver->irq_handler = ironlake_irq_handler; | 4540 | dev->driver->irq_handler = ironlake_irq_handler; |
| 4562 | dev->driver->irq_preinstall = ironlake_irq_reset; | 4541 | dev->driver->irq_preinstall = ironlake_irq_reset; |
| 4563 | dev->driver->irq_postinstall = ironlake_irq_postinstall; | 4542 | dev->driver->irq_postinstall = ironlake_irq_postinstall; |
| @@ -4571,21 +4550,25 @@ void intel_irq_init(struct drm_i915_private *dev_priv) | |||
| 4571 | dev->driver->irq_postinstall = i8xx_irq_postinstall; | 4550 | dev->driver->irq_postinstall = i8xx_irq_postinstall; |
| 4572 | dev->driver->irq_handler = i8xx_irq_handler; | 4551 | dev->driver->irq_handler = i8xx_irq_handler; |
| 4573 | dev->driver->irq_uninstall = i8xx_irq_uninstall; | 4552 | dev->driver->irq_uninstall = i8xx_irq_uninstall; |
| 4553 | dev->driver->enable_vblank = i8xx_enable_vblank; | ||
| 4554 | dev->driver->disable_vblank = i8xx_disable_vblank; | ||
| 4574 | } else if (IS_GEN3(dev_priv)) { | 4555 | } else if (IS_GEN3(dev_priv)) { |
| 4575 | dev->driver->irq_preinstall = i915_irq_preinstall; | 4556 | dev->driver->irq_preinstall = i915_irq_preinstall; |
| 4576 | dev->driver->irq_postinstall = i915_irq_postinstall; | 4557 | dev->driver->irq_postinstall = i915_irq_postinstall; |
| 4577 | dev->driver->irq_uninstall = i915_irq_uninstall; | 4558 | dev->driver->irq_uninstall = i915_irq_uninstall; |
| 4578 | dev->driver->irq_handler = i915_irq_handler; | 4559 | dev->driver->irq_handler = i915_irq_handler; |
| 4560 | dev->driver->enable_vblank = i8xx_enable_vblank; | ||
| 4561 | dev->driver->disable_vblank = i8xx_disable_vblank; | ||
| 4579 | } else { | 4562 | } else { |
| 4580 | dev->driver->irq_preinstall = i965_irq_preinstall; | 4563 | dev->driver->irq_preinstall = i965_irq_preinstall; |
| 4581 | dev->driver->irq_postinstall = i965_irq_postinstall; | 4564 | dev->driver->irq_postinstall = i965_irq_postinstall; |
| 4582 | dev->driver->irq_uninstall = i965_irq_uninstall; | 4565 | dev->driver->irq_uninstall = i965_irq_uninstall; |
| 4583 | dev->driver->irq_handler = i965_irq_handler; | 4566 | dev->driver->irq_handler = i965_irq_handler; |
| 4567 | dev->driver->enable_vblank = i965_enable_vblank; | ||
| 4568 | dev->driver->disable_vblank = i965_disable_vblank; | ||
| 4584 | } | 4569 | } |
| 4585 | if (I915_HAS_HOTPLUG(dev_priv)) | 4570 | if (I915_HAS_HOTPLUG(dev_priv)) |
| 4586 | dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; | 4571 | dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; |
| 4587 | dev->driver->enable_vblank = i915_enable_vblank; | ||
| 4588 | dev->driver->disable_vblank = i915_disable_vblank; | ||
| 4589 | } | 4572 | } |
| 4590 | } | 4573 | } |
| 4591 | 4574 | ||
diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 768ad89d9cd4..629e4334719c 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c | |||
| @@ -47,6 +47,7 @@ struct i915_params i915 __read_mostly = { | |||
| 47 | .load_detect_test = 0, | 47 | .load_detect_test = 0, |
| 48 | .force_reset_modeset_test = 0, | 48 | .force_reset_modeset_test = 0, |
| 49 | .reset = true, | 49 | .reset = true, |
| 50 | .error_capture = true, | ||
| 50 | .invert_brightness = 0, | 51 | .invert_brightness = 0, |
| 51 | .disable_display = 0, | 52 | .disable_display = 0, |
| 52 | .enable_cmd_parser = 1, | 53 | .enable_cmd_parser = 1, |
| @@ -115,6 +116,14 @@ MODULE_PARM_DESC(vbt_sdvo_panel_type, | |||
| 115 | module_param_named_unsafe(reset, i915.reset, bool, 0600); | 116 | module_param_named_unsafe(reset, i915.reset, bool, 0600); |
| 116 | MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)"); | 117 | MODULE_PARM_DESC(reset, "Attempt GPU resets (default: true)"); |
| 117 | 118 | ||
| 119 | #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) | ||
| 120 | module_param_named(error_capture, i915.error_capture, bool, 0600); | ||
| 121 | MODULE_PARM_DESC(error_capture, | ||
| 122 | "Record the GPU state following a hang. " | ||
| 123 | "This information in /sys/class/drm/card<N>/error is vital for " | ||
| 124 | "triaging and debugging hangs."); | ||
| 125 | #endif | ||
| 126 | |||
| 118 | module_param_named_unsafe(enable_hangcheck, i915.enable_hangcheck, bool, 0644); | 127 | module_param_named_unsafe(enable_hangcheck, i915.enable_hangcheck, bool, 0644); |
| 119 | MODULE_PARM_DESC(enable_hangcheck, | 128 | MODULE_PARM_DESC(enable_hangcheck, |
| 120 | "Periodically check GPU activity for detecting hangs. " | 129 | "Periodically check GPU activity for detecting hangs. " |
diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index 3a0dd78ddb38..94efc899c1ef 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h | |||
| @@ -59,6 +59,7 @@ struct i915_params { | |||
| 59 | bool load_detect_test; | 59 | bool load_detect_test; |
| 60 | bool force_reset_modeset_test; | 60 | bool force_reset_modeset_test; |
| 61 | bool reset; | 61 | bool reset; |
| 62 | bool error_capture; | ||
| 62 | bool disable_display; | 63 | bool disable_display; |
| 63 | bool verbose_state_checks; | 64 | bool verbose_state_checks; |
| 64 | bool nuclear_pageflip; | 65 | bool nuclear_pageflip; |
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 687c768833b3..31e6edd08dd0 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c | |||
| @@ -431,9 +431,6 @@ static const struct pci_device_id pciidlist[] = { | |||
| 431 | }; | 431 | }; |
| 432 | MODULE_DEVICE_TABLE(pci, pciidlist); | 432 | MODULE_DEVICE_TABLE(pci, pciidlist); |
| 433 | 433 | ||
| 434 | extern int i915_driver_load(struct pci_dev *pdev, | ||
| 435 | const struct pci_device_id *ent); | ||
| 436 | |||
| 437 | static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 434 | static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 438 | { | 435 | { |
| 439 | struct intel_device_info *intel_info = | 436 | struct intel_device_info *intel_info = |
| @@ -463,8 +460,6 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 463 | return i915_driver_load(pdev, ent); | 460 | return i915_driver_load(pdev, ent); |
| 464 | } | 461 | } |
| 465 | 462 | ||
| 466 | extern void i915_driver_unload(struct drm_device *dev); | ||
| 467 | |||
| 468 | static void i915_pci_remove(struct pci_dev *pdev) | 463 | static void i915_pci_remove(struct pci_dev *pdev) |
| 469 | { | 464 | { |
| 470 | struct drm_device *dev = pci_get_drvdata(pdev); | 465 | struct drm_device *dev = pci_get_drvdata(pdev); |
| @@ -473,8 +468,6 @@ static void i915_pci_remove(struct pci_dev *pdev) | |||
| 473 | drm_dev_unref(dev); | 468 | drm_dev_unref(dev); |
| 474 | } | 469 | } |
| 475 | 470 | ||
| 476 | extern const struct dev_pm_ops i915_pm_ops; | ||
| 477 | |||
| 478 | static struct pci_driver i915_pci_driver = { | 471 | static struct pci_driver i915_pci_driver = { |
| 479 | .name = DRIVER_NAME, | 472 | .name = DRIVER_NAME, |
| 480 | .id_table = pciidlist, | 473 | .id_table = pciidlist, |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 70d96162def6..00efaa13974d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -86,8 +86,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) | |||
| 86 | #define DEVEN 0x54 | 86 | #define DEVEN 0x54 |
| 87 | #define DEVEN_MCHBAR_EN (1 << 28) | 87 | #define DEVEN_MCHBAR_EN (1 << 28) |
| 88 | 88 | ||
| 89 | #define BSM 0x5c | 89 | /* BSM in include/drm/i915_drm.h */ |
| 90 | #define BSM_MASK (0xFFFF << 20) | ||
| 91 | 90 | ||
| 92 | #define HPLLCC 0xc0 /* 85x only */ | 91 | #define HPLLCC 0xc0 /* 85x only */ |
| 93 | #define GC_CLOCK_CONTROL_MASK (0x7 << 0) | 92 | #define GC_CLOCK_CONTROL_MASK (0x7 << 0) |
| @@ -1605,6 +1604,7 @@ enum skl_disp_power_wells { | |||
| 1605 | #define RING_HEAD(base) _MMIO((base)+0x34) | 1604 | #define RING_HEAD(base) _MMIO((base)+0x34) |
| 1606 | #define RING_START(base) _MMIO((base)+0x38) | 1605 | #define RING_START(base) _MMIO((base)+0x38) |
| 1607 | #define RING_CTL(base) _MMIO((base)+0x3c) | 1606 | #define RING_CTL(base) _MMIO((base)+0x3c) |
| 1607 | #define RING_CTL_SIZE(size) ((size) - PAGE_SIZE) /* in bytes -> pages */ | ||
| 1608 | #define RING_SYNC_0(base) _MMIO((base)+0x40) | 1608 | #define RING_SYNC_0(base) _MMIO((base)+0x40) |
| 1609 | #define RING_SYNC_1(base) _MMIO((base)+0x44) | 1609 | #define RING_SYNC_1(base) _MMIO((base)+0x44) |
| 1610 | #define RING_SYNC_2(base) _MMIO((base)+0x48) | 1610 | #define RING_SYNC_2(base) _MMIO((base)+0x48) |
| @@ -1708,7 +1708,11 @@ enum skl_disp_power_wells { | |||
| 1708 | #define GEN7_SC_INSTDONE _MMIO(0x7100) | 1708 | #define GEN7_SC_INSTDONE _MMIO(0x7100) |
| 1709 | #define GEN7_SAMPLER_INSTDONE _MMIO(0xe160) | 1709 | #define GEN7_SAMPLER_INSTDONE _MMIO(0xe160) |
| 1710 | #define GEN7_ROW_INSTDONE _MMIO(0xe164) | 1710 | #define GEN7_ROW_INSTDONE _MMIO(0xe164) |
| 1711 | #define I915_NUM_INSTDONE_REG 4 | 1711 | #define GEN8_MCR_SELECTOR _MMIO(0xfdc) |
| 1712 | #define GEN8_MCR_SLICE(slice) (((slice) & 3) << 26) | ||
| 1713 | #define GEN8_MCR_SLICE_MASK GEN8_MCR_SLICE(3) | ||
| 1714 | #define GEN8_MCR_SUBSLICE(subslice) (((subslice) & 3) << 24) | ||
| 1715 | #define GEN8_MCR_SUBSLICE_MASK GEN8_MCR_SUBSLICE(3) | ||
| 1712 | #define RING_IPEIR(base) _MMIO((base)+0x64) | 1716 | #define RING_IPEIR(base) _MMIO((base)+0x64) |
| 1713 | #define RING_IPEHR(base) _MMIO((base)+0x68) | 1717 | #define RING_IPEHR(base) _MMIO((base)+0x68) |
| 1714 | /* | 1718 | /* |
| @@ -2089,9 +2093,9 @@ enum skl_disp_power_wells { | |||
| 2089 | #define PM_VEBOX_CS_ERROR_INTERRUPT (1 << 12) /* hsw+ */ | 2093 | #define PM_VEBOX_CS_ERROR_INTERRUPT (1 << 12) /* hsw+ */ |
| 2090 | #define PM_VEBOX_USER_INTERRUPT (1 << 10) /* hsw+ */ | 2094 | #define PM_VEBOX_USER_INTERRUPT (1 << 10) /* hsw+ */ |
| 2091 | 2095 | ||
| 2092 | #define GT_PARITY_ERROR(dev) \ | 2096 | #define GT_PARITY_ERROR(dev_priv) \ |
| 2093 | (GT_RENDER_L3_PARITY_ERROR_INTERRUPT | \ | 2097 | (GT_RENDER_L3_PARITY_ERROR_INTERRUPT | \ |
| 2094 | (IS_HASWELL(dev) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0)) | 2098 | (IS_HASWELL(dev_priv) ? GT_RENDER_L3_PARITY_ERROR_INTERRUPT_S1 : 0)) |
| 2095 | 2099 | ||
| 2096 | /* These are all the "old" interrupts */ | 2100 | /* These are all the "old" interrupts */ |
| 2097 | #define ILK_BSD_USER_INTERRUPT (1<<5) | 2101 | #define ILK_BSD_USER_INTERRUPT (1<<5) |
| @@ -7327,6 +7331,10 @@ enum { | |||
| 7327 | #define AUD_CONFIG_UPPER_N_MASK (0xff << 20) | 7331 | #define AUD_CONFIG_UPPER_N_MASK (0xff << 20) |
| 7328 | #define AUD_CONFIG_LOWER_N_SHIFT 4 | 7332 | #define AUD_CONFIG_LOWER_N_SHIFT 4 |
| 7329 | #define AUD_CONFIG_LOWER_N_MASK (0xfff << 4) | 7333 | #define AUD_CONFIG_LOWER_N_MASK (0xfff << 4) |
| 7334 | #define AUD_CONFIG_N_MASK (AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK) | ||
| 7335 | #define AUD_CONFIG_N(n) \ | ||
| 7336 | (((((n) >> 12) & 0xff) << AUD_CONFIG_UPPER_N_SHIFT) | \ | ||
| 7337 | (((n) & 0xfff) << AUD_CONFIG_LOWER_N_SHIFT)) | ||
| 7330 | #define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16 | 7338 | #define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16 |
| 7331 | #define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK (0xf << 16) | 7339 | #define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK (0xf << 16) |
| 7332 | #define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 (0 << 16) | 7340 | #define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 (0 << 16) |
diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index a0af170062b1..344cbf39cfa9 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c | |||
| @@ -38,7 +38,7 @@ static void i915_save_display(struct drm_device *dev) | |||
| 38 | dev_priv->regfile.saveDSPARB = I915_READ(DSPARB); | 38 | dev_priv->regfile.saveDSPARB = I915_READ(DSPARB); |
| 39 | 39 | ||
| 40 | /* save FBC interval */ | 40 | /* save FBC interval */ |
| 41 | if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev)) | 41 | if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv)) |
| 42 | dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL); | 42 | dev_priv->regfile.saveFBC_CONTROL = I915_READ(FBC_CONTROL); |
| 43 | } | 43 | } |
| 44 | 44 | ||
| @@ -54,7 +54,7 @@ static void i915_restore_display(struct drm_device *dev) | |||
| 54 | intel_fbc_global_disable(dev_priv); | 54 | intel_fbc_global_disable(dev_priv); |
| 55 | 55 | ||
| 56 | /* restore FBC interval */ | 56 | /* restore FBC interval */ |
| 57 | if (HAS_FBC(dev) && INTEL_INFO(dev)->gen <= 4 && !IS_G4X(dev)) | 57 | if (HAS_FBC(dev_priv) && INTEL_GEN(dev_priv) <= 4 && !IS_G4X(dev_priv)) |
| 58 | I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL); | 58 | I915_WRITE(FBC_CONTROL, dev_priv->regfile.saveFBC_CONTROL); |
| 59 | 59 | ||
| 60 | i915_redisable_vga(dev); | 60 | i915_redisable_vga(dev); |
| @@ -70,7 +70,7 @@ int i915_save_state(struct drm_device *dev) | |||
| 70 | 70 | ||
| 71 | i915_save_display(dev); | 71 | i915_save_display(dev); |
| 72 | 72 | ||
| 73 | if (IS_GEN4(dev)) | 73 | if (IS_GEN4(dev_priv)) |
| 74 | pci_read_config_word(pdev, GCDGMBUS, | 74 | pci_read_config_word(pdev, GCDGMBUS, |
| 75 | &dev_priv->regfile.saveGCDGMBUS); | 75 | &dev_priv->regfile.saveGCDGMBUS); |
| 76 | 76 | ||
| @@ -116,7 +116,7 @@ int i915_restore_state(struct drm_device *dev) | |||
| 116 | 116 | ||
| 117 | i915_gem_restore_fences(dev); | 117 | i915_gem_restore_fences(dev); |
| 118 | 118 | ||
| 119 | if (IS_GEN4(dev)) | 119 | if (IS_GEN4(dev_priv)) |
| 120 | pci_write_config_word(pdev, GCDGMBUS, | 120 | pci_write_config_word(pdev, GCDGMBUS, |
| 121 | dev_priv->regfile.saveGCDGMBUS); | 121 | dev_priv->regfile.saveGCDGMBUS); |
| 122 | i915_restore_display(dev); | 122 | i915_restore_display(dev); |
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 1012eeea1324..47590ab08d7e 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c | |||
| @@ -514,6 +514,8 @@ static const struct attribute *vlv_attrs[] = { | |||
| 514 | NULL, | 514 | NULL, |
| 515 | }; | 515 | }; |
| 516 | 516 | ||
| 517 | #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) | ||
| 518 | |||
| 517 | static ssize_t error_state_read(struct file *filp, struct kobject *kobj, | 519 | static ssize_t error_state_read(struct file *filp, struct kobject *kobj, |
| 518 | struct bin_attribute *attr, char *buf, | 520 | struct bin_attribute *attr, char *buf, |
| 519 | loff_t off, size_t count) | 521 | loff_t off, size_t count) |
| @@ -571,6 +573,21 @@ static struct bin_attribute error_state_attr = { | |||
| 571 | .write = error_state_write, | 573 | .write = error_state_write, |
| 572 | }; | 574 | }; |
| 573 | 575 | ||
| 576 | static void i915_setup_error_capture(struct device *kdev) | ||
| 577 | { | ||
| 578 | if (sysfs_create_bin_file(&kdev->kobj, &error_state_attr)) | ||
| 579 | DRM_ERROR("error_state sysfs setup failed\n"); | ||
| 580 | } | ||
| 581 | |||
| 582 | static void i915_teardown_error_capture(struct device *kdev) | ||
| 583 | { | ||
| 584 | sysfs_remove_bin_file(&kdev->kobj, &error_state_attr); | ||
| 585 | } | ||
| 586 | #else | ||
| 587 | static void i915_setup_error_capture(struct device *kdev) {} | ||
| 588 | static void i915_teardown_error_capture(struct device *kdev) {} | ||
| 589 | #endif | ||
| 590 | |||
| 574 | void i915_setup_sysfs(struct drm_i915_private *dev_priv) | 591 | void i915_setup_sysfs(struct drm_i915_private *dev_priv) |
| 575 | { | 592 | { |
| 576 | struct device *kdev = dev_priv->drm.primary->kdev; | 593 | struct device *kdev = dev_priv->drm.primary->kdev; |
| @@ -617,17 +634,15 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv) | |||
| 617 | if (ret) | 634 | if (ret) |
| 618 | DRM_ERROR("RPS sysfs setup failed\n"); | 635 | DRM_ERROR("RPS sysfs setup failed\n"); |
| 619 | 636 | ||
| 620 | ret = sysfs_create_bin_file(&kdev->kobj, | 637 | i915_setup_error_capture(kdev); |
| 621 | &error_state_attr); | ||
| 622 | if (ret) | ||
| 623 | DRM_ERROR("error_state sysfs setup failed\n"); | ||
| 624 | } | 638 | } |
| 625 | 639 | ||
| 626 | void i915_teardown_sysfs(struct drm_i915_private *dev_priv) | 640 | void i915_teardown_sysfs(struct drm_i915_private *dev_priv) |
| 627 | { | 641 | { |
| 628 | struct device *kdev = dev_priv->drm.primary->kdev; | 642 | struct device *kdev = dev_priv->drm.primary->kdev; |
| 629 | 643 | ||
| 630 | sysfs_remove_bin_file(&kdev->kobj, &error_state_attr); | 644 | i915_teardown_error_capture(kdev); |
| 645 | |||
| 631 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) | 646 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 632 | sysfs_remove_files(&kdev->kobj, vlv_attrs); | 647 | sysfs_remove_files(&kdev->kobj, vlv_attrs); |
| 633 | else | 648 | else |
diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 6c70a5bfd7d8..7093cfbb62b1 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c | |||
| @@ -81,7 +81,7 @@ static const struct { | |||
| 81 | int clock; | 81 | int clock; |
| 82 | int n; | 82 | int n; |
| 83 | int cts; | 83 | int cts; |
| 84 | } aud_ncts[] = { | 84 | } hdmi_aud_ncts[] = { |
| 85 | { 44100, TMDS_296M, 4459, 234375 }, | 85 | { 44100, TMDS_296M, 4459, 234375 }, |
| 86 | { 44100, TMDS_297M, 4704, 247500 }, | 86 | { 44100, TMDS_297M, 4704, 247500 }, |
| 87 | { 48000, TMDS_296M, 5824, 281250 }, | 87 | { 48000, TMDS_296M, 5824, 281250 }, |
| @@ -121,45 +121,20 @@ static u32 audio_config_hdmi_pixel_clock(const struct drm_display_mode *adjusted | |||
| 121 | return hdmi_audio_clock[i].config; | 121 | return hdmi_audio_clock[i].config; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | static int audio_config_get_n(const struct drm_display_mode *mode, int rate) | 124 | static int audio_config_hdmi_get_n(const struct drm_display_mode *adjusted_mode, |
| 125 | int rate) | ||
| 125 | { | 126 | { |
| 126 | int i; | 127 | int i; |
| 127 | 128 | ||
| 128 | for (i = 0; i < ARRAY_SIZE(aud_ncts); i++) { | 129 | for (i = 0; i < ARRAY_SIZE(hdmi_aud_ncts); i++) { |
| 129 | if ((rate == aud_ncts[i].sample_rate) && | 130 | if (rate == hdmi_aud_ncts[i].sample_rate && |
| 130 | (mode->clock == aud_ncts[i].clock)) { | 131 | adjusted_mode->crtc_clock == hdmi_aud_ncts[i].clock) { |
| 131 | return aud_ncts[i].n; | 132 | return hdmi_aud_ncts[i].n; |
| 132 | } | 133 | } |
| 133 | } | 134 | } |
| 134 | return 0; | 135 | return 0; |
| 135 | } | 136 | } |
| 136 | 137 | ||
| 137 | static uint32_t audio_config_setup_n_reg(int n, uint32_t val) | ||
| 138 | { | ||
| 139 | int n_low, n_up; | ||
| 140 | uint32_t tmp = val; | ||
| 141 | |||
| 142 | n_low = n & 0xfff; | ||
| 143 | n_up = (n >> 12) & 0xff; | ||
| 144 | tmp &= ~(AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK); | ||
| 145 | tmp |= ((n_up << AUD_CONFIG_UPPER_N_SHIFT) | | ||
| 146 | (n_low << AUD_CONFIG_LOWER_N_SHIFT) | | ||
| 147 | AUD_CONFIG_N_PROG_ENABLE); | ||
| 148 | return tmp; | ||
| 149 | } | ||
| 150 | |||
| 151 | /* check whether N/CTS/M need be set manually */ | ||
| 152 | static bool audio_rate_need_prog(struct intel_crtc *crtc, | ||
| 153 | const struct drm_display_mode *mode) | ||
| 154 | { | ||
| 155 | if (((mode->clock == TMDS_297M) || | ||
| 156 | (mode->clock == TMDS_296M)) && | ||
| 157 | intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) | ||
| 158 | return true; | ||
| 159 | else | ||
| 160 | return false; | ||
| 161 | } | ||
| 162 | |||
| 163 | static bool intel_eld_uptodate(struct drm_connector *connector, | 138 | static bool intel_eld_uptodate(struct drm_connector *connector, |
| 164 | i915_reg_t reg_eldv, uint32_t bits_eldv, | 139 | i915_reg_t reg_eldv, uint32_t bits_eldv, |
| 165 | i915_reg_t reg_elda, uint32_t bits_elda, | 140 | i915_reg_t reg_elda, uint32_t bits_elda, |
| @@ -245,6 +220,65 @@ static void g4x_audio_codec_enable(struct drm_connector *connector, | |||
| 245 | I915_WRITE(G4X_AUD_CNTL_ST, tmp); | 220 | I915_WRITE(G4X_AUD_CNTL_ST, tmp); |
| 246 | } | 221 | } |
| 247 | 222 | ||
| 223 | static void | ||
| 224 | hsw_dp_audio_config_update(struct intel_crtc *intel_crtc, enum port port, | ||
| 225 | const struct drm_display_mode *adjusted_mode) | ||
| 226 | { | ||
| 227 | struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); | ||
| 228 | enum pipe pipe = intel_crtc->pipe; | ||
| 229 | u32 tmp; | ||
| 230 | |||
| 231 | tmp = I915_READ(HSW_AUD_CFG(pipe)); | ||
| 232 | tmp &= ~AUD_CONFIG_N_VALUE_INDEX; | ||
| 233 | tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; | ||
| 234 | tmp &= ~AUD_CONFIG_N_PROG_ENABLE; | ||
| 235 | tmp |= AUD_CONFIG_N_VALUE_INDEX; | ||
| 236 | |||
| 237 | I915_WRITE(HSW_AUD_CFG(pipe), tmp); | ||
| 238 | } | ||
| 239 | |||
| 240 | static void | ||
| 241 | hsw_hdmi_audio_config_update(struct intel_crtc *intel_crtc, enum port port, | ||
| 242 | const struct drm_display_mode *adjusted_mode) | ||
| 243 | { | ||
| 244 | struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); | ||
| 245 | struct i915_audio_component *acomp = dev_priv->audio_component; | ||
| 246 | int rate = acomp ? acomp->aud_sample_rate[port] : 0; | ||
| 247 | enum pipe pipe = intel_crtc->pipe; | ||
| 248 | int n; | ||
| 249 | u32 tmp; | ||
| 250 | |||
| 251 | tmp = I915_READ(HSW_AUD_CFG(pipe)); | ||
| 252 | tmp &= ~AUD_CONFIG_N_VALUE_INDEX; | ||
| 253 | tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; | ||
| 254 | tmp &= ~AUD_CONFIG_N_PROG_ENABLE; | ||
| 255 | tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); | ||
| 256 | |||
| 257 | if (adjusted_mode->crtc_clock == TMDS_296M || | ||
| 258 | adjusted_mode->crtc_clock == TMDS_297M) { | ||
| 259 | n = audio_config_hdmi_get_n(adjusted_mode, rate); | ||
| 260 | if (n != 0) { | ||
| 261 | tmp &= ~AUD_CONFIG_N_MASK; | ||
| 262 | tmp |= AUD_CONFIG_N(n); | ||
| 263 | tmp |= AUD_CONFIG_N_PROG_ENABLE; | ||
| 264 | } else { | ||
| 265 | DRM_DEBUG_KMS("no suitable N value is found\n"); | ||
| 266 | } | ||
| 267 | } | ||
| 268 | |||
| 269 | I915_WRITE(HSW_AUD_CFG(pipe), tmp); | ||
| 270 | } | ||
| 271 | |||
| 272 | static void | ||
| 273 | hsw_audio_config_update(struct intel_crtc *intel_crtc, enum port port, | ||
| 274 | const struct drm_display_mode *adjusted_mode) | ||
| 275 | { | ||
| 276 | if (intel_crtc_has_dp_encoder(intel_crtc->config)) | ||
| 277 | hsw_dp_audio_config_update(intel_crtc, port, adjusted_mode); | ||
| 278 | else | ||
| 279 | hsw_hdmi_audio_config_update(intel_crtc, port, adjusted_mode); | ||
| 280 | } | ||
| 281 | |||
| 248 | static void hsw_audio_codec_disable(struct intel_encoder *encoder) | 282 | static void hsw_audio_codec_disable(struct intel_encoder *encoder) |
| 249 | { | 283 | { |
| 250 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 284 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| @@ -276,20 +310,16 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder) | |||
| 276 | } | 310 | } |
| 277 | 311 | ||
| 278 | static void hsw_audio_codec_enable(struct drm_connector *connector, | 312 | static void hsw_audio_codec_enable(struct drm_connector *connector, |
| 279 | struct intel_encoder *encoder, | 313 | struct intel_encoder *intel_encoder, |
| 280 | const struct drm_display_mode *adjusted_mode) | 314 | const struct drm_display_mode *adjusted_mode) |
| 281 | { | 315 | { |
| 282 | struct drm_i915_private *dev_priv = to_i915(connector->dev); | 316 | struct drm_i915_private *dev_priv = to_i915(connector->dev); |
| 283 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | 317 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc); |
| 284 | enum pipe pipe = intel_crtc->pipe; | 318 | enum pipe pipe = intel_crtc->pipe; |
| 285 | struct i915_audio_component *acomp = dev_priv->audio_component; | 319 | enum port port = intel_encoder->port; |
| 286 | const uint8_t *eld = connector->eld; | 320 | const uint8_t *eld = connector->eld; |
| 287 | struct intel_digital_port *intel_dig_port = | ||
| 288 | enc_to_dig_port(&encoder->base); | ||
| 289 | enum port port = intel_dig_port->port; | ||
| 290 | uint32_t tmp; | 321 | uint32_t tmp; |
| 291 | int len, i; | 322 | int len, i; |
| 292 | int n, rate; | ||
| 293 | 323 | ||
| 294 | DRM_DEBUG_KMS("Enable audio codec on pipe %c, %u bytes ELD\n", | 324 | DRM_DEBUG_KMS("Enable audio codec on pipe %c, %u bytes ELD\n", |
| 295 | pipe_name(pipe), drm_eld_size(eld)); | 325 | pipe_name(pipe), drm_eld_size(eld)); |
| @@ -325,42 +355,17 @@ static void hsw_audio_codec_enable(struct drm_connector *connector, | |||
| 325 | I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); | 355 | I915_WRITE(HSW_AUD_PIN_ELD_CP_VLD, tmp); |
| 326 | 356 | ||
| 327 | /* Enable timestamps */ | 357 | /* Enable timestamps */ |
| 328 | tmp = I915_READ(HSW_AUD_CFG(pipe)); | 358 | hsw_audio_config_update(intel_crtc, port, adjusted_mode); |
| 329 | tmp &= ~AUD_CONFIG_N_VALUE_INDEX; | ||
| 330 | tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK; | ||
| 331 | if (intel_crtc_has_dp_encoder(intel_crtc->config)) | ||
| 332 | tmp |= AUD_CONFIG_N_VALUE_INDEX; | ||
| 333 | else | ||
| 334 | tmp |= audio_config_hdmi_pixel_clock(adjusted_mode); | ||
| 335 | |||
| 336 | tmp &= ~AUD_CONFIG_N_PROG_ENABLE; | ||
| 337 | if (audio_rate_need_prog(intel_crtc, adjusted_mode)) { | ||
| 338 | if (!acomp) | ||
| 339 | rate = 0; | ||
| 340 | else if (port >= PORT_A && port <= PORT_E) | ||
| 341 | rate = acomp->aud_sample_rate[port]; | ||
| 342 | else { | ||
| 343 | DRM_ERROR("invalid port: %d\n", port); | ||
| 344 | rate = 0; | ||
| 345 | } | ||
| 346 | n = audio_config_get_n(adjusted_mode, rate); | ||
| 347 | if (n != 0) | ||
| 348 | tmp = audio_config_setup_n_reg(n, tmp); | ||
| 349 | else | ||
| 350 | DRM_DEBUG_KMS("no suitable N value is found\n"); | ||
| 351 | } | ||
| 352 | |||
| 353 | I915_WRITE(HSW_AUD_CFG(pipe), tmp); | ||
| 354 | 359 | ||
| 355 | mutex_unlock(&dev_priv->av_mutex); | 360 | mutex_unlock(&dev_priv->av_mutex); |
| 356 | } | 361 | } |
| 357 | 362 | ||
| 358 | static void ilk_audio_codec_disable(struct intel_encoder *encoder) | 363 | static void ilk_audio_codec_disable(struct intel_encoder *intel_encoder) |
| 359 | { | 364 | { |
| 360 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 365 | struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); |
| 361 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | 366 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc); |
| 362 | enum port port = enc_to_dig_port(&encoder->base)->port; | ||
| 363 | enum pipe pipe = intel_crtc->pipe; | 367 | enum pipe pipe = intel_crtc->pipe; |
| 368 | enum port port = intel_encoder->port; | ||
| 364 | uint32_t tmp, eldv; | 369 | uint32_t tmp, eldv; |
| 365 | i915_reg_t aud_config, aud_cntrl_st2; | 370 | i915_reg_t aud_config, aud_cntrl_st2; |
| 366 | 371 | ||
| @@ -400,13 +405,13 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder) | |||
| 400 | } | 405 | } |
| 401 | 406 | ||
| 402 | static void ilk_audio_codec_enable(struct drm_connector *connector, | 407 | static void ilk_audio_codec_enable(struct drm_connector *connector, |
| 403 | struct intel_encoder *encoder, | 408 | struct intel_encoder *intel_encoder, |
| 404 | const struct drm_display_mode *adjusted_mode) | 409 | const struct drm_display_mode *adjusted_mode) |
| 405 | { | 410 | { |
| 406 | struct drm_i915_private *dev_priv = to_i915(connector->dev); | 411 | struct drm_i915_private *dev_priv = to_i915(connector->dev); |
| 407 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc); | 412 | struct intel_crtc *intel_crtc = to_intel_crtc(intel_encoder->base.crtc); |
| 408 | enum port port = enc_to_dig_port(&encoder->base)->port; | ||
| 409 | enum pipe pipe = intel_crtc->pipe; | 413 | enum pipe pipe = intel_crtc->pipe; |
| 414 | enum port port = intel_encoder->port; | ||
| 410 | uint8_t *eld = connector->eld; | 415 | uint8_t *eld = connector->eld; |
| 411 | uint32_t tmp, eldv; | 416 | uint32_t tmp, eldv; |
| 412 | int len, i; | 417 | int len, i; |
| @@ -425,13 +430,13 @@ static void ilk_audio_codec_enable(struct drm_connector *connector, | |||
| 425 | * infrastructure is not there yet. | 430 | * infrastructure is not there yet. |
| 426 | */ | 431 | */ |
| 427 | 432 | ||
| 428 | if (HAS_PCH_IBX(connector->dev)) { | 433 | if (HAS_PCH_IBX(dev_priv)) { |
| 429 | hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); | 434 | hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe); |
| 430 | aud_config = IBX_AUD_CFG(pipe); | 435 | aud_config = IBX_AUD_CFG(pipe); |
| 431 | aud_cntl_st = IBX_AUD_CNTL_ST(pipe); | 436 | aud_cntl_st = IBX_AUD_CNTL_ST(pipe); |
| 432 | aud_cntrl_st2 = IBX_AUD_CNTL_ST2; | 437 | aud_cntrl_st2 = IBX_AUD_CNTL_ST2; |
| 433 | } else if (IS_VALLEYVIEW(connector->dev) || | 438 | } else if (IS_VALLEYVIEW(dev_priv) || |
| 434 | IS_CHERRYVIEW(connector->dev)) { | 439 | IS_CHERRYVIEW(dev_priv)) { |
| 435 | hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); | 440 | hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe); |
| 436 | aud_config = VLV_AUD_CFG(pipe); | 441 | aud_config = VLV_AUD_CFG(pipe); |
| 437 | aud_cntl_st = VLV_AUD_CNTL_ST(pipe); | 442 | aud_cntl_st = VLV_AUD_CNTL_ST(pipe); |
| @@ -490,11 +495,10 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) | |||
| 490 | struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); | 495 | struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); |
| 491 | const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; | 496 | const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; |
| 492 | struct drm_connector *connector; | 497 | struct drm_connector *connector; |
| 493 | struct drm_device *dev = encoder->dev; | 498 | struct drm_i915_private *dev_priv = to_i915(encoder->dev); |
| 494 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 495 | struct i915_audio_component *acomp = dev_priv->audio_component; | 499 | struct i915_audio_component *acomp = dev_priv->audio_component; |
| 496 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); | 500 | enum port port = intel_encoder->port; |
| 497 | enum port port = intel_dig_port->port; | 501 | enum pipe pipe = crtc->pipe; |
| 498 | 502 | ||
| 499 | connector = drm_select_eld(encoder); | 503 | connector = drm_select_eld(encoder); |
| 500 | if (!connector) | 504 | if (!connector) |
| @@ -518,13 +522,19 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) | |||
| 518 | adjusted_mode); | 522 | adjusted_mode); |
| 519 | 523 | ||
| 520 | mutex_lock(&dev_priv->av_mutex); | 524 | mutex_lock(&dev_priv->av_mutex); |
| 521 | intel_dig_port->audio_connector = connector; | 525 | intel_encoder->audio_connector = connector; |
| 526 | |||
| 522 | /* referred in audio callbacks */ | 527 | /* referred in audio callbacks */ |
| 523 | dev_priv->dig_port_map[port] = intel_encoder; | 528 | dev_priv->av_enc_map[pipe] = intel_encoder; |
| 524 | mutex_unlock(&dev_priv->av_mutex); | 529 | mutex_unlock(&dev_priv->av_mutex); |
| 525 | 530 | ||
| 531 | /* audio drivers expect pipe = -1 to indicate Non-MST cases */ | ||
| 532 | if (intel_encoder->type != INTEL_OUTPUT_DP_MST) | ||
| 533 | pipe = -1; | ||
| 534 | |||
| 526 | if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) | 535 | if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) |
| 527 | acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port); | 536 | acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, |
| 537 | (int) port, (int) pipe); | ||
| 528 | } | 538 | } |
| 529 | 539 | ||
| 530 | /** | 540 | /** |
| @@ -537,22 +547,27 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder) | |||
| 537 | void intel_audio_codec_disable(struct intel_encoder *intel_encoder) | 547 | void intel_audio_codec_disable(struct intel_encoder *intel_encoder) |
| 538 | { | 548 | { |
| 539 | struct drm_encoder *encoder = &intel_encoder->base; | 549 | struct drm_encoder *encoder = &intel_encoder->base; |
| 540 | struct drm_device *dev = encoder->dev; | 550 | struct drm_i915_private *dev_priv = to_i915(encoder->dev); |
| 541 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 542 | struct i915_audio_component *acomp = dev_priv->audio_component; | 551 | struct i915_audio_component *acomp = dev_priv->audio_component; |
| 543 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); | 552 | enum port port = intel_encoder->port; |
| 544 | enum port port = intel_dig_port->port; | 553 | struct intel_crtc *crtc = to_intel_crtc(encoder->crtc); |
| 554 | enum pipe pipe = crtc->pipe; | ||
| 545 | 555 | ||
| 546 | if (dev_priv->display.audio_codec_disable) | 556 | if (dev_priv->display.audio_codec_disable) |
| 547 | dev_priv->display.audio_codec_disable(intel_encoder); | 557 | dev_priv->display.audio_codec_disable(intel_encoder); |
| 548 | 558 | ||
| 549 | mutex_lock(&dev_priv->av_mutex); | 559 | mutex_lock(&dev_priv->av_mutex); |
| 550 | intel_dig_port->audio_connector = NULL; | 560 | intel_encoder->audio_connector = NULL; |
| 551 | dev_priv->dig_port_map[port] = NULL; | 561 | dev_priv->av_enc_map[pipe] = NULL; |
| 552 | mutex_unlock(&dev_priv->av_mutex); | 562 | mutex_unlock(&dev_priv->av_mutex); |
| 553 | 563 | ||
| 564 | /* audio drivers expect pipe = -1 to indicate Non-MST cases */ | ||
| 565 | if (intel_encoder->type != INTEL_OUTPUT_DP_MST) | ||
| 566 | pipe = -1; | ||
| 567 | |||
| 554 | if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) | 568 | if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify) |
| 555 | acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, (int) port); | 569 | acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr, |
| 570 | (int) port, (int) pipe); | ||
| 556 | } | 571 | } |
| 557 | 572 | ||
| 558 | /** | 573 | /** |
| @@ -627,74 +642,67 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev) | |||
| 627 | return dev_priv->cdclk_freq; | 642 | return dev_priv->cdclk_freq; |
| 628 | } | 643 | } |
| 629 | 644 | ||
| 630 | static int i915_audio_component_sync_audio_rate(struct device *kdev, | 645 | static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, |
| 631 | int port, int rate) | 646 | int port, int pipe) |
| 647 | { | ||
| 648 | |||
| 649 | if (WARN_ON(pipe >= I915_MAX_PIPES)) | ||
| 650 | return NULL; | ||
| 651 | |||
| 652 | /* MST */ | ||
| 653 | if (pipe >= 0) | ||
| 654 | return dev_priv->av_enc_map[pipe]; | ||
| 655 | |||
| 656 | /* Non-MST */ | ||
| 657 | for_each_pipe(dev_priv, pipe) { | ||
| 658 | struct intel_encoder *encoder; | ||
| 659 | |||
| 660 | encoder = dev_priv->av_enc_map[pipe]; | ||
| 661 | if (encoder == NULL) | ||
| 662 | continue; | ||
| 663 | |||
| 664 | if (port == encoder->port) | ||
| 665 | return encoder; | ||
| 666 | } | ||
| 667 | |||
| 668 | return NULL; | ||
| 669 | } | ||
| 670 | |||
| 671 | static int i915_audio_component_sync_audio_rate(struct device *kdev, int port, | ||
| 672 | int pipe, int rate) | ||
| 632 | { | 673 | { |
| 633 | struct drm_i915_private *dev_priv = kdev_to_i915(kdev); | 674 | struct drm_i915_private *dev_priv = kdev_to_i915(kdev); |
| 634 | struct intel_encoder *intel_encoder; | 675 | struct intel_encoder *intel_encoder; |
| 635 | struct intel_crtc *crtc; | 676 | struct intel_crtc *crtc; |
| 636 | struct drm_display_mode *mode; | 677 | struct drm_display_mode *adjusted_mode; |
| 637 | struct i915_audio_component *acomp = dev_priv->audio_component; | 678 | struct i915_audio_component *acomp = dev_priv->audio_component; |
| 638 | enum pipe pipe = INVALID_PIPE; | ||
| 639 | u32 tmp; | ||
| 640 | int n; | ||
| 641 | int err = 0; | 679 | int err = 0; |
| 642 | 680 | ||
| 643 | /* HSW, BDW, SKL, KBL need this fix */ | 681 | if (!HAS_DDI(dev_priv)) |
| 644 | if (!IS_SKYLAKE(dev_priv) && | ||
| 645 | !IS_KABYLAKE(dev_priv) && | ||
| 646 | !IS_BROADWELL(dev_priv) && | ||
| 647 | !IS_HASWELL(dev_priv)) | ||
| 648 | return 0; | 682 | return 0; |
| 649 | 683 | ||
| 650 | i915_audio_component_get_power(kdev); | 684 | i915_audio_component_get_power(kdev); |
| 651 | mutex_lock(&dev_priv->av_mutex); | 685 | mutex_lock(&dev_priv->av_mutex); |
| 686 | |||
| 652 | /* 1. get the pipe */ | 687 | /* 1. get the pipe */ |
| 653 | intel_encoder = dev_priv->dig_port_map[port]; | 688 | intel_encoder = get_saved_enc(dev_priv, port, pipe); |
| 654 | /* intel_encoder might be NULL for DP MST */ | ||
| 655 | if (!intel_encoder || !intel_encoder->base.crtc || | 689 | if (!intel_encoder || !intel_encoder->base.crtc || |
| 656 | intel_encoder->type != INTEL_OUTPUT_HDMI) { | 690 | intel_encoder->type != INTEL_OUTPUT_HDMI) { |
| 657 | DRM_DEBUG_KMS("no valid port %c\n", port_name(port)); | 691 | DRM_DEBUG_KMS("Not valid for port %c\n", port_name(port)); |
| 658 | err = -ENODEV; | 692 | err = -ENODEV; |
| 659 | goto unlock; | 693 | goto unlock; |
| 660 | } | 694 | } |
| 695 | |||
| 696 | /* pipe passed from the audio driver will be -1 for Non-MST case */ | ||
| 661 | crtc = to_intel_crtc(intel_encoder->base.crtc); | 697 | crtc = to_intel_crtc(intel_encoder->base.crtc); |
| 662 | pipe = crtc->pipe; | 698 | pipe = crtc->pipe; |
| 663 | if (pipe == INVALID_PIPE) { | ||
| 664 | DRM_DEBUG_KMS("no pipe for the port %c\n", port_name(port)); | ||
| 665 | err = -ENODEV; | ||
| 666 | goto unlock; | ||
| 667 | } | ||
| 668 | 699 | ||
| 669 | DRM_DEBUG_KMS("pipe %c connects port %c\n", | 700 | adjusted_mode = &crtc->config->base.adjusted_mode; |
| 670 | pipe_name(pipe), port_name(port)); | ||
| 671 | mode = &crtc->config->base.adjusted_mode; | ||
| 672 | 701 | ||
| 673 | /* port must be valid now, otherwise the pipe will be invalid */ | 702 | /* port must be valid now, otherwise the pipe will be invalid */ |
| 674 | acomp->aud_sample_rate[port] = rate; | 703 | acomp->aud_sample_rate[port] = rate; |
| 675 | 704 | ||
| 676 | /* 2. check whether to set the N/CTS/M manually or not */ | 705 | hsw_audio_config_update(crtc, port, adjusted_mode); |
| 677 | if (!audio_rate_need_prog(crtc, mode)) { | ||
| 678 | tmp = I915_READ(HSW_AUD_CFG(pipe)); | ||
| 679 | tmp &= ~AUD_CONFIG_N_PROG_ENABLE; | ||
| 680 | I915_WRITE(HSW_AUD_CFG(pipe), tmp); | ||
| 681 | goto unlock; | ||
| 682 | } | ||
| 683 | |||
| 684 | n = audio_config_get_n(mode, rate); | ||
| 685 | if (n == 0) { | ||
| 686 | DRM_DEBUG_KMS("Using automatic mode for N value on port %c\n", | ||
| 687 | port_name(port)); | ||
| 688 | tmp = I915_READ(HSW_AUD_CFG(pipe)); | ||
| 689 | tmp &= ~AUD_CONFIG_N_PROG_ENABLE; | ||
| 690 | I915_WRITE(HSW_AUD_CFG(pipe), tmp); | ||
| 691 | goto unlock; | ||
| 692 | } | ||
| 693 | |||
| 694 | /* 3. set the N/CTS/M */ | ||
| 695 | tmp = I915_READ(HSW_AUD_CFG(pipe)); | ||
| 696 | tmp = audio_config_setup_n_reg(n, tmp); | ||
| 697 | I915_WRITE(HSW_AUD_CFG(pipe), tmp); | ||
| 698 | 706 | ||
| 699 | unlock: | 707 | unlock: |
| 700 | mutex_unlock(&dev_priv->av_mutex); | 708 | mutex_unlock(&dev_priv->av_mutex); |
| @@ -703,27 +711,29 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, | |||
| 703 | } | 711 | } |
| 704 | 712 | ||
| 705 | static int i915_audio_component_get_eld(struct device *kdev, int port, | 713 | static int i915_audio_component_get_eld(struct device *kdev, int port, |
| 706 | bool *enabled, | 714 | int pipe, bool *enabled, |
| 707 | unsigned char *buf, int max_bytes) | 715 | unsigned char *buf, int max_bytes) |
| 708 | { | 716 | { |
| 709 | struct drm_i915_private *dev_priv = kdev_to_i915(kdev); | 717 | struct drm_i915_private *dev_priv = kdev_to_i915(kdev); |
| 710 | struct intel_encoder *intel_encoder; | 718 | struct intel_encoder *intel_encoder; |
| 711 | struct intel_digital_port *intel_dig_port; | ||
| 712 | const u8 *eld; | 719 | const u8 *eld; |
| 713 | int ret = -EINVAL; | 720 | int ret = -EINVAL; |
| 714 | 721 | ||
| 715 | mutex_lock(&dev_priv->av_mutex); | 722 | mutex_lock(&dev_priv->av_mutex); |
| 716 | intel_encoder = dev_priv->dig_port_map[port]; | 723 | |
| 717 | /* intel_encoder might be NULL for DP MST */ | 724 | intel_encoder = get_saved_enc(dev_priv, port, pipe); |
| 718 | if (intel_encoder) { | 725 | if (!intel_encoder) { |
| 719 | ret = 0; | 726 | DRM_DEBUG_KMS("Not valid for port %c\n", port_name(port)); |
| 720 | intel_dig_port = enc_to_dig_port(&intel_encoder->base); | 727 | mutex_unlock(&dev_priv->av_mutex); |
| 721 | *enabled = intel_dig_port->audio_connector != NULL; | 728 | return ret; |
| 722 | if (*enabled) { | 729 | } |
| 723 | eld = intel_dig_port->audio_connector->eld; | 730 | |
| 724 | ret = drm_eld_size(eld); | 731 | ret = 0; |
| 725 | memcpy(buf, eld, min(max_bytes, ret)); | 732 | *enabled = intel_encoder->audio_connector != NULL; |
| 726 | } | 733 | if (*enabled) { |
| 734 | eld = intel_encoder->audio_connector->eld; | ||
| 735 | ret = drm_eld_size(eld); | ||
| 736 | memcpy(buf, eld, min(max_bytes, ret)); | ||
| 727 | } | 737 | } |
| 728 | 738 | ||
| 729 | mutex_unlock(&dev_priv->av_mutex); | 739 | mutex_unlock(&dev_priv->av_mutex); |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index c6e69e4cfa83..5ab646ef8c9f 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
| @@ -996,6 +996,10 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv, | |||
| 996 | goto err; | 996 | goto err; |
| 997 | } | 997 | } |
| 998 | 998 | ||
| 999 | /* Log about presence of sequences we won't run. */ | ||
| 1000 | if (seq_id == MIPI_SEQ_TEAR_ON || seq_id == MIPI_SEQ_TEAR_OFF) | ||
| 1001 | DRM_DEBUG_KMS("Unsupported sequence %u\n", seq_id); | ||
| 1002 | |||
| 999 | dev_priv->vbt.dsi.sequence[seq_id] = data + index; | 1003 | dev_priv->vbt.dsi.sequence[seq_id] = data + index; |
| 1000 | 1004 | ||
| 1001 | if (sequence->version >= 3) | 1005 | if (sequence->version >= 3) |
| @@ -1031,6 +1035,77 @@ static u8 translate_iboost(u8 val) | |||
| 1031 | return mapping[val]; | 1035 | return mapping[val]; |
| 1032 | } | 1036 | } |
| 1033 | 1037 | ||
| 1038 | static void sanitize_ddc_pin(struct drm_i915_private *dev_priv, | ||
| 1039 | enum port port) | ||
| 1040 | { | ||
| 1041 | const struct ddi_vbt_port_info *info = | ||
| 1042 | &dev_priv->vbt.ddi_port_info[port]; | ||
| 1043 | enum port p; | ||
| 1044 | |||
| 1045 | if (!info->alternate_ddc_pin) | ||
| 1046 | return; | ||
| 1047 | |||
| 1048 | for_each_port_masked(p, (1 << port) - 1) { | ||
| 1049 | struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p]; | ||
| 1050 | |||
| 1051 | if (info->alternate_ddc_pin != i->alternate_ddc_pin) | ||
| 1052 | continue; | ||
| 1053 | |||
| 1054 | DRM_DEBUG_KMS("port %c trying to use the same DDC pin (0x%x) as port %c, " | ||
| 1055 | "disabling port %c DVI/HDMI support\n", | ||
| 1056 | port_name(p), i->alternate_ddc_pin, | ||
| 1057 | port_name(port), port_name(p)); | ||
| 1058 | |||
| 1059 | /* | ||
| 1060 | * If we have multiple ports supposedly sharing the | ||
| 1061 | * pin, then dvi/hdmi couldn't exist on the shared | ||
| 1062 | * port. Otherwise they share the same ddc bin and | ||
| 1063 | * system couldn't communicate with them separately. | ||
| 1064 | * | ||
| 1065 | * Due to parsing the ports in alphabetical order, | ||
| 1066 | * a higher port will always clobber a lower one. | ||
| 1067 | */ | ||
| 1068 | i->supports_dvi = false; | ||
| 1069 | i->supports_hdmi = false; | ||
| 1070 | i->alternate_ddc_pin = 0; | ||
| 1071 | } | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | static void sanitize_aux_ch(struct drm_i915_private *dev_priv, | ||
| 1075 | enum port port) | ||
| 1076 | { | ||
| 1077 | const struct ddi_vbt_port_info *info = | ||
| 1078 | &dev_priv->vbt.ddi_port_info[port]; | ||
| 1079 | enum port p; | ||
| 1080 | |||
| 1081 | if (!info->alternate_aux_channel) | ||
| 1082 | return; | ||
| 1083 | |||
| 1084 | for_each_port_masked(p, (1 << port) - 1) { | ||
| 1085 | struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p]; | ||
| 1086 | |||
| 1087 | if (info->alternate_aux_channel != i->alternate_aux_channel) | ||
| 1088 | continue; | ||
| 1089 | |||
| 1090 | DRM_DEBUG_KMS("port %c trying to use the same AUX CH (0x%x) as port %c, " | ||
| 1091 | "disabling port %c DP support\n", | ||
| 1092 | port_name(p), i->alternate_aux_channel, | ||
| 1093 | port_name(port), port_name(p)); | ||
| 1094 | |||
| 1095 | /* | ||
| 1096 | * If we have multiple ports supposedlt sharing the | ||
| 1097 | * aux channel, then DP couldn't exist on the shared | ||
| 1098 | * port. Otherwise they share the same aux channel | ||
| 1099 | * and system couldn't communicate with them separately. | ||
| 1100 | * | ||
| 1101 | * Due to parsing the ports in alphabetical order, | ||
| 1102 | * a higher port will always clobber a lower one. | ||
| 1103 | */ | ||
| 1104 | i->supports_dp = false; | ||
| 1105 | i->alternate_aux_channel = 0; | ||
| 1106 | } | ||
| 1107 | } | ||
| 1108 | |||
| 1034 | static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, | 1109 | static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, |
| 1035 | const struct bdb_header *bdb) | 1110 | const struct bdb_header *bdb) |
| 1036 | { | 1111 | { |
| @@ -1105,54 +1180,15 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, | |||
| 1105 | DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); | 1180 | DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); |
| 1106 | 1181 | ||
| 1107 | if (is_dvi) { | 1182 | if (is_dvi) { |
| 1108 | if (port == PORT_E) { | 1183 | info->alternate_ddc_pin = ddc_pin; |
| 1109 | info->alternate_ddc_pin = ddc_pin; | 1184 | |
| 1110 | /* if DDIE share ddc pin with other port, then | 1185 | sanitize_ddc_pin(dev_priv, port); |
| 1111 | * dvi/hdmi couldn't exist on the shared port. | ||
| 1112 | * Otherwise they share the same ddc bin and system | ||
| 1113 | * couldn't communicate with them seperately. */ | ||
| 1114 | if (ddc_pin == DDC_PIN_B) { | ||
| 1115 | dev_priv->vbt.ddi_port_info[PORT_B].supports_dvi = 0; | ||
| 1116 | dev_priv->vbt.ddi_port_info[PORT_B].supports_hdmi = 0; | ||
| 1117 | } else if (ddc_pin == DDC_PIN_C) { | ||
| 1118 | dev_priv->vbt.ddi_port_info[PORT_C].supports_dvi = 0; | ||
| 1119 | dev_priv->vbt.ddi_port_info[PORT_C].supports_hdmi = 0; | ||
| 1120 | } else if (ddc_pin == DDC_PIN_D) { | ||
| 1121 | dev_priv->vbt.ddi_port_info[PORT_D].supports_dvi = 0; | ||
| 1122 | dev_priv->vbt.ddi_port_info[PORT_D].supports_hdmi = 0; | ||
| 1123 | } | ||
| 1124 | } else if (ddc_pin == DDC_PIN_B && port != PORT_B) | ||
| 1125 | DRM_DEBUG_KMS("Unexpected DDC pin for port B\n"); | ||
| 1126 | else if (ddc_pin == DDC_PIN_C && port != PORT_C) | ||
| 1127 | DRM_DEBUG_KMS("Unexpected DDC pin for port C\n"); | ||
| 1128 | else if (ddc_pin == DDC_PIN_D && port != PORT_D) | ||
| 1129 | DRM_DEBUG_KMS("Unexpected DDC pin for port D\n"); | ||
| 1130 | } | 1186 | } |
| 1131 | 1187 | ||
| 1132 | if (is_dp) { | 1188 | if (is_dp) { |
| 1133 | if (port == PORT_E) { | 1189 | info->alternate_aux_channel = aux_channel; |
| 1134 | info->alternate_aux_channel = aux_channel; | 1190 | |
| 1135 | /* if DDIE share aux channel with other port, then | 1191 | sanitize_aux_ch(dev_priv, port); |
| 1136 | * DP couldn't exist on the shared port. Otherwise | ||
| 1137 | * they share the same aux channel and system | ||
| 1138 | * couldn't communicate with them seperately. */ | ||
| 1139 | if (aux_channel == DP_AUX_A) | ||
| 1140 | dev_priv->vbt.ddi_port_info[PORT_A].supports_dp = 0; | ||
| 1141 | else if (aux_channel == DP_AUX_B) | ||
| 1142 | dev_priv->vbt.ddi_port_info[PORT_B].supports_dp = 0; | ||
| 1143 | else if (aux_channel == DP_AUX_C) | ||
| 1144 | dev_priv->vbt.ddi_port_info[PORT_C].supports_dp = 0; | ||
| 1145 | else if (aux_channel == DP_AUX_D) | ||
| 1146 | dev_priv->vbt.ddi_port_info[PORT_D].supports_dp = 0; | ||
| 1147 | } | ||
| 1148 | else if (aux_channel == DP_AUX_A && port != PORT_A) | ||
| 1149 | DRM_DEBUG_KMS("Unexpected AUX channel for port A\n"); | ||
| 1150 | else if (aux_channel == DP_AUX_B && port != PORT_B) | ||
| 1151 | DRM_DEBUG_KMS("Unexpected AUX channel for port B\n"); | ||
| 1152 | else if (aux_channel == DP_AUX_C && port != PORT_C) | ||
| 1153 | DRM_DEBUG_KMS("Unexpected AUX channel for port C\n"); | ||
| 1154 | else if (aux_channel == DP_AUX_D && port != PORT_D) | ||
| 1155 | DRM_DEBUG_KMS("Unexpected AUX channel for port D\n"); | ||
| 1156 | } | 1192 | } |
| 1157 | 1193 | ||
| 1158 | if (bdb->version >= 158) { | 1194 | if (bdb->version >= 158) { |
| @@ -1759,3 +1795,52 @@ intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv, | |||
| 1759 | 1795 | ||
| 1760 | return false; | 1796 | return false; |
| 1761 | } | 1797 | } |
| 1798 | |||
| 1799 | /** | ||
| 1800 | * intel_bios_is_lspcon_present - if LSPCON is attached on %port | ||
| 1801 | * @dev_priv: i915 device instance | ||
| 1802 | * @port: port to check | ||
| 1803 | * | ||
| 1804 | * Return true if LSPCON is present on this port | ||
| 1805 | */ | ||
| 1806 | bool | ||
| 1807 | intel_bios_is_lspcon_present(struct drm_i915_private *dev_priv, | ||
| 1808 | enum port port) | ||
| 1809 | { | ||
| 1810 | int i; | ||
| 1811 | |||
| 1812 | if (!HAS_LSPCON(dev_priv)) | ||
| 1813 | return false; | ||
| 1814 | |||
| 1815 | for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { | ||
| 1816 | if (!dev_priv->vbt.child_dev[i].common.lspcon) | ||
| 1817 | continue; | ||
| 1818 | |||
| 1819 | switch (dev_priv->vbt.child_dev[i].common.dvo_port) { | ||
| 1820 | case DVO_PORT_DPA: | ||
| 1821 | case DVO_PORT_HDMIA: | ||
| 1822 | if (port == PORT_A) | ||
| 1823 | return true; | ||
| 1824 | break; | ||
| 1825 | case DVO_PORT_DPB: | ||
| 1826 | case DVO_PORT_HDMIB: | ||
| 1827 | if (port == PORT_B) | ||
| 1828 | return true; | ||
| 1829 | break; | ||
| 1830 | case DVO_PORT_DPC: | ||
| 1831 | case DVO_PORT_HDMIC: | ||
| 1832 | if (port == PORT_C) | ||
| 1833 | return true; | ||
| 1834 | break; | ||
| 1835 | case DVO_PORT_DPD: | ||
| 1836 | case DVO_PORT_HDMID: | ||
| 1837 | if (port == PORT_D) | ||
| 1838 | return true; | ||
| 1839 | break; | ||
| 1840 | default: | ||
| 1841 | break; | ||
| 1842 | } | ||
| 1843 | } | ||
| 1844 | |||
| 1845 | return false; | ||
| 1846 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 9bad14d22c95..23fc1042fed4 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c | |||
| @@ -578,6 +578,36 @@ int intel_engine_init_breadcrumbs(struct intel_engine_cs *engine) | |||
| 578 | return 0; | 578 | return 0; |
| 579 | } | 579 | } |
| 580 | 580 | ||
| 581 | static void cancel_fake_irq(struct intel_engine_cs *engine) | ||
| 582 | { | ||
| 583 | struct intel_breadcrumbs *b = &engine->breadcrumbs; | ||
| 584 | |||
| 585 | del_timer_sync(&b->hangcheck); | ||
| 586 | del_timer_sync(&b->fake_irq); | ||
| 587 | clear_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings); | ||
| 588 | } | ||
| 589 | |||
| 590 | void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine) | ||
| 591 | { | ||
| 592 | struct intel_breadcrumbs *b = &engine->breadcrumbs; | ||
| 593 | |||
| 594 | cancel_fake_irq(engine); | ||
| 595 | spin_lock(&b->lock); | ||
| 596 | |||
| 597 | __intel_breadcrumbs_disable_irq(b); | ||
| 598 | if (intel_engine_has_waiter(engine)) { | ||
| 599 | b->timeout = wait_timeout(); | ||
| 600 | __intel_breadcrumbs_enable_irq(b); | ||
| 601 | if (READ_ONCE(b->irq_posted)) | ||
| 602 | wake_up_process(b->first_wait->tsk); | ||
| 603 | } else { | ||
| 604 | /* sanitize the IMR and unmask any auxiliary interrupts */ | ||
| 605 | irq_disable(engine); | ||
| 606 | } | ||
| 607 | |||
| 608 | spin_unlock(&b->lock); | ||
| 609 | } | ||
| 610 | |||
| 581 | void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) | 611 | void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) |
| 582 | { | 612 | { |
| 583 | struct intel_breadcrumbs *b = &engine->breadcrumbs; | 613 | struct intel_breadcrumbs *b = &engine->breadcrumbs; |
| @@ -585,13 +615,13 @@ void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine) | |||
| 585 | if (!IS_ERR_OR_NULL(b->signaler)) | 615 | if (!IS_ERR_OR_NULL(b->signaler)) |
| 586 | kthread_stop(b->signaler); | 616 | kthread_stop(b->signaler); |
| 587 | 617 | ||
| 588 | del_timer_sync(&b->hangcheck); | 618 | cancel_fake_irq(engine); |
| 589 | del_timer_sync(&b->fake_irq); | ||
| 590 | } | 619 | } |
| 591 | 620 | ||
| 592 | unsigned int intel_kick_waiters(struct drm_i915_private *i915) | 621 | unsigned int intel_kick_waiters(struct drm_i915_private *i915) |
| 593 | { | 622 | { |
| 594 | struct intel_engine_cs *engine; | 623 | struct intel_engine_cs *engine; |
| 624 | enum intel_engine_id id; | ||
| 595 | unsigned int mask = 0; | 625 | unsigned int mask = 0; |
| 596 | 626 | ||
| 597 | /* To avoid the task_struct disappearing beneath us as we wake up | 627 | /* To avoid the task_struct disappearing beneath us as we wake up |
| @@ -599,7 +629,7 @@ unsigned int intel_kick_waiters(struct drm_i915_private *i915) | |||
| 599 | * RCU lock, i.e. as we call wake_up_process() we must be holding the | 629 | * RCU lock, i.e. as we call wake_up_process() we must be holding the |
| 600 | * rcu_read_lock(). | 630 | * rcu_read_lock(). |
| 601 | */ | 631 | */ |
| 602 | for_each_engine(engine, i915) | 632 | for_each_engine(engine, i915, id) |
| 603 | if (unlikely(intel_engine_wakeup(engine))) | 633 | if (unlikely(intel_engine_wakeup(engine))) |
| 604 | mask |= intel_engine_flag(engine); | 634 | mask |= intel_engine_flag(engine); |
| 605 | 635 | ||
| @@ -609,9 +639,10 @@ unsigned int intel_kick_waiters(struct drm_i915_private *i915) | |||
| 609 | unsigned int intel_kick_signalers(struct drm_i915_private *i915) | 639 | unsigned int intel_kick_signalers(struct drm_i915_private *i915) |
| 610 | { | 640 | { |
| 611 | struct intel_engine_cs *engine; | 641 | struct intel_engine_cs *engine; |
| 642 | enum intel_engine_id id; | ||
| 612 | unsigned int mask = 0; | 643 | unsigned int mask = 0; |
| 613 | 644 | ||
| 614 | for_each_engine(engine, i915) { | 645 | for_each_engine(engine, i915, id) { |
| 615 | if (unlikely(READ_ONCE(engine->breadcrumbs.first_signal))) { | 646 | if (unlikely(READ_ONCE(engine->breadcrumbs.first_signal))) { |
| 616 | wake_up_process(engine->breadcrumbs.signaler); | 647 | wake_up_process(engine->breadcrumbs.signaler); |
| 617 | mask |= intel_engine_flag(engine); | 648 | mask |= intel_engine_flag(engine); |
diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index 95a72771eea6..445108855275 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c | |||
| @@ -273,7 +273,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc, | |||
| 273 | enum pipe pipe = intel_crtc->pipe; | 273 | enum pipe pipe = intel_crtc->pipe; |
| 274 | int i; | 274 | int i; |
| 275 | 275 | ||
| 276 | if (HAS_GMCH_DISPLAY(dev)) { | 276 | if (HAS_GMCH_DISPLAY(dev_priv)) { |
| 277 | if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) | 277 | if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI)) |
| 278 | assert_dsi_pll_enabled(dev_priv); | 278 | assert_dsi_pll_enabled(dev_priv); |
| 279 | else | 279 | else |
| @@ -288,7 +288,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc, | |||
| 288 | (drm_color_lut_extract(lut[i].green, 8) << 8) | | 288 | (drm_color_lut_extract(lut[i].green, 8) << 8) | |
| 289 | drm_color_lut_extract(lut[i].blue, 8); | 289 | drm_color_lut_extract(lut[i].blue, 8); |
| 290 | 290 | ||
| 291 | if (HAS_GMCH_DISPLAY(dev)) | 291 | if (HAS_GMCH_DISPLAY(dev_priv)) |
| 292 | I915_WRITE(PALETTE(pipe, i), word); | 292 | I915_WRITE(PALETTE(pipe, i), word); |
| 293 | else | 293 | else |
| 294 | I915_WRITE(LGC_PALETTE(pipe, i), word); | 294 | I915_WRITE(LGC_PALETTE(pipe, i), word); |
| @@ -297,7 +297,7 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc, | |||
| 297 | for (i = 0; i < 256; i++) { | 297 | for (i = 0; i < 256; i++) { |
| 298 | uint32_t word = (i << 16) | (i << 8) | i; | 298 | uint32_t word = (i << 16) | (i << 8) | i; |
| 299 | 299 | ||
| 300 | if (HAS_GMCH_DISPLAY(dev)) | 300 | if (HAS_GMCH_DISPLAY(dev_priv)) |
| 301 | I915_WRITE(PALETTE(pipe, i), word); | 301 | I915_WRITE(PALETTE(pipe, i), word); |
| 302 | else | 302 | else |
| 303 | I915_WRITE(LGC_PALETTE(pipe, i), word); | 303 | I915_WRITE(LGC_PALETTE(pipe, i), word); |
| @@ -326,7 +326,7 @@ static void haswell_load_luts(struct drm_crtc_state *crtc_state) | |||
| 326 | * Workaround : Do not read or write the pipe palette/gamma data while | 326 | * Workaround : Do not read or write the pipe palette/gamma data while |
| 327 | * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. | 327 | * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. |
| 328 | */ | 328 | */ |
| 329 | if (IS_HASWELL(dev) && intel_crtc_state->ips_enabled && | 329 | if (IS_HASWELL(dev_priv) && intel_crtc_state->ips_enabled && |
| 330 | (intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) { | 330 | (intel_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)) { |
| 331 | hsw_disable_ips(intel_crtc); | 331 | hsw_disable_ips(intel_crtc); |
| 332 | reenable_ips = true; | 332 | reenable_ips = true; |
| @@ -534,14 +534,14 @@ void intel_color_init(struct drm_crtc *crtc) | |||
| 534 | 534 | ||
| 535 | drm_mode_crtc_set_gamma_size(crtc, 256); | 535 | drm_mode_crtc_set_gamma_size(crtc, 256); |
| 536 | 536 | ||
| 537 | if (IS_CHERRYVIEW(dev)) { | 537 | if (IS_CHERRYVIEW(dev_priv)) { |
| 538 | dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix; | 538 | dev_priv->display.load_csc_matrix = cherryview_load_csc_matrix; |
| 539 | dev_priv->display.load_luts = cherryview_load_luts; | 539 | dev_priv->display.load_luts = cherryview_load_luts; |
| 540 | } else if (IS_HASWELL(dev)) { | 540 | } else if (IS_HASWELL(dev_priv)) { |
| 541 | dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; | 541 | dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; |
| 542 | dev_priv->display.load_luts = haswell_load_luts; | 542 | dev_priv->display.load_luts = haswell_load_luts; |
| 543 | } else if (IS_BROADWELL(dev) || IS_SKYLAKE(dev) || | 543 | } else if (IS_BROADWELL(dev_priv) || IS_SKYLAKE(dev_priv) || |
| 544 | IS_BROXTON(dev) || IS_KABYLAKE(dev)) { | 544 | IS_BROXTON(dev_priv) || IS_KABYLAKE(dev_priv)) { |
| 545 | dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; | 545 | dev_priv->display.load_csc_matrix = i9xx_load_csc_matrix; |
| 546 | dev_priv->display.load_luts = broadwell_load_luts; | 546 | dev_priv->display.load_luts = broadwell_load_luts; |
| 547 | } else { | 547 | } else { |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index dfbcf16b41df..a97151fcb9f4 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
| @@ -84,7 +84,7 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder, | |||
| 84 | if (!(tmp & ADPA_DAC_ENABLE)) | 84 | if (!(tmp & ADPA_DAC_ENABLE)) |
| 85 | goto out; | 85 | goto out; |
| 86 | 86 | ||
| 87 | if (HAS_PCH_CPT(dev)) | 87 | if (HAS_PCH_CPT(dev_priv)) |
| 88 | *pipe = PORT_TO_PIPE_CPT(tmp); | 88 | *pipe = PORT_TO_PIPE_CPT(tmp); |
| 89 | else | 89 | else |
| 90 | *pipe = PORT_TO_PIPE(tmp); | 90 | *pipe = PORT_TO_PIPE(tmp); |
| @@ -165,16 +165,16 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, | |||
| 165 | adpa |= ADPA_VSYNC_ACTIVE_HIGH; | 165 | adpa |= ADPA_VSYNC_ACTIVE_HIGH; |
| 166 | 166 | ||
| 167 | /* For CPT allow 3 pipe config, for others just use A or B */ | 167 | /* For CPT allow 3 pipe config, for others just use A or B */ |
| 168 | if (HAS_PCH_LPT(dev)) | 168 | if (HAS_PCH_LPT(dev_priv)) |
| 169 | ; /* Those bits don't exist here */ | 169 | ; /* Those bits don't exist here */ |
| 170 | else if (HAS_PCH_CPT(dev)) | 170 | else if (HAS_PCH_CPT(dev_priv)) |
| 171 | adpa |= PORT_TRANS_SEL_CPT(crtc->pipe); | 171 | adpa |= PORT_TRANS_SEL_CPT(crtc->pipe); |
| 172 | else if (crtc->pipe == 0) | 172 | else if (crtc->pipe == 0) |
| 173 | adpa |= ADPA_PIPE_A_SELECT; | 173 | adpa |= ADPA_PIPE_A_SELECT; |
| 174 | else | 174 | else |
| 175 | adpa |= ADPA_PIPE_B_SELECT; | 175 | adpa |= ADPA_PIPE_B_SELECT; |
| 176 | 176 | ||
| 177 | if (!HAS_PCH_SPLIT(dev)) | 177 | if (!HAS_PCH_SPLIT(dev_priv)) |
| 178 | I915_WRITE(BCLRPAT(crtc->pipe), 0); | 178 | I915_WRITE(BCLRPAT(crtc->pipe), 0); |
| 179 | 179 | ||
| 180 | switch (mode) { | 180 | switch (mode) { |
| @@ -241,7 +241,8 @@ intel_crt_mode_valid(struct drm_connector *connector, | |||
| 241 | struct drm_display_mode *mode) | 241 | struct drm_display_mode *mode) |
| 242 | { | 242 | { |
| 243 | struct drm_device *dev = connector->dev; | 243 | struct drm_device *dev = connector->dev; |
| 244 | int max_dotclk = to_i915(dev)->max_dotclk_freq; | 244 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 245 | int max_dotclk = dev_priv->max_dotclk_freq; | ||
| 245 | int max_clock; | 246 | int max_clock; |
| 246 | 247 | ||
| 247 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | 248 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
| @@ -250,15 +251,15 @@ intel_crt_mode_valid(struct drm_connector *connector, | |||
| 250 | if (mode->clock < 25000) | 251 | if (mode->clock < 25000) |
| 251 | return MODE_CLOCK_LOW; | 252 | return MODE_CLOCK_LOW; |
| 252 | 253 | ||
| 253 | if (HAS_PCH_LPT(dev)) | 254 | if (HAS_PCH_LPT(dev_priv)) |
| 254 | max_clock = 180000; | 255 | max_clock = 180000; |
| 255 | else if (IS_VALLEYVIEW(dev)) | 256 | else if (IS_VALLEYVIEW(dev_priv)) |
| 256 | /* | 257 | /* |
| 257 | * 270 MHz due to current DPLL limits, | 258 | * 270 MHz due to current DPLL limits, |
| 258 | * DAC limit supposedly 355 MHz. | 259 | * DAC limit supposedly 355 MHz. |
| 259 | */ | 260 | */ |
| 260 | max_clock = 270000; | 261 | max_clock = 270000; |
| 261 | else if (IS_GEN3(dev) || IS_GEN4(dev)) | 262 | else if (IS_GEN3(dev_priv) || IS_GEN4(dev_priv)) |
| 262 | max_clock = 400000; | 263 | max_clock = 400000; |
| 263 | else | 264 | else |
| 264 | max_clock = 350000; | 265 | max_clock = 350000; |
| @@ -269,7 +270,7 @@ intel_crt_mode_valid(struct drm_connector *connector, | |||
| 269 | return MODE_CLOCK_HIGH; | 270 | return MODE_CLOCK_HIGH; |
| 270 | 271 | ||
| 271 | /* The FDI receiver on LPT only supports 8bpc and only has 2 lanes. */ | 272 | /* The FDI receiver on LPT only supports 8bpc and only has 2 lanes. */ |
| 272 | if (HAS_PCH_LPT(dev) && | 273 | if (HAS_PCH_LPT(dev_priv) && |
| 273 | (ironlake_get_lanes_required(mode->clock, 270000, 24) > 2)) | 274 | (ironlake_get_lanes_required(mode->clock, 270000, 24) > 2)) |
| 274 | return MODE_CLOCK_HIGH; | 275 | return MODE_CLOCK_HIGH; |
| 275 | 276 | ||
| @@ -280,13 +281,13 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder, | |||
| 280 | struct intel_crtc_state *pipe_config, | 281 | struct intel_crtc_state *pipe_config, |
| 281 | struct drm_connector_state *conn_state) | 282 | struct drm_connector_state *conn_state) |
| 282 | { | 283 | { |
| 283 | struct drm_device *dev = encoder->base.dev; | 284 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 284 | 285 | ||
| 285 | if (HAS_PCH_SPLIT(dev)) | 286 | if (HAS_PCH_SPLIT(dev_priv)) |
| 286 | pipe_config->has_pch_encoder = true; | 287 | pipe_config->has_pch_encoder = true; |
| 287 | 288 | ||
| 288 | /* LPT FDI RX only supports 8bpc. */ | 289 | /* LPT FDI RX only supports 8bpc. */ |
| 289 | if (HAS_PCH_LPT(dev)) { | 290 | if (HAS_PCH_LPT(dev_priv)) { |
| 290 | if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) { | 291 | if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) { |
| 291 | DRM_DEBUG_KMS("LPT only supports 24bpp\n"); | 292 | DRM_DEBUG_KMS("LPT only supports 24bpp\n"); |
| 292 | return false; | 293 | return false; |
| @@ -296,7 +297,7 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder, | |||
| 296 | } | 297 | } |
| 297 | 298 | ||
| 298 | /* FDI must always be 2.7 GHz */ | 299 | /* FDI must always be 2.7 GHz */ |
| 299 | if (HAS_DDI(dev)) | 300 | if (HAS_DDI(dev_priv)) |
| 300 | pipe_config->port_clock = 135000 * 2; | 301 | pipe_config->port_clock = 135000 * 2; |
| 301 | 302 | ||
| 302 | return true; | 303 | return true; |
| @@ -312,7 +313,7 @@ static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) | |||
| 312 | 313 | ||
| 313 | /* The first time through, trigger an explicit detection cycle */ | 314 | /* The first time through, trigger an explicit detection cycle */ |
| 314 | if (crt->force_hotplug_required) { | 315 | if (crt->force_hotplug_required) { |
| 315 | bool turn_off_dac = HAS_PCH_SPLIT(dev); | 316 | bool turn_off_dac = HAS_PCH_SPLIT(dev_priv); |
| 316 | u32 save_adpa; | 317 | u32 save_adpa; |
| 317 | 318 | ||
| 318 | crt->force_hotplug_required = 0; | 319 | crt->force_hotplug_required = 0; |
| @@ -419,10 +420,10 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
| 419 | bool ret = false; | 420 | bool ret = false; |
| 420 | int i, tries = 0; | 421 | int i, tries = 0; |
| 421 | 422 | ||
| 422 | if (HAS_PCH_SPLIT(dev)) | 423 | if (HAS_PCH_SPLIT(dev_priv)) |
| 423 | return intel_ironlake_crt_detect_hotplug(connector); | 424 | return intel_ironlake_crt_detect_hotplug(connector); |
| 424 | 425 | ||
| 425 | if (IS_VALLEYVIEW(dev)) | 426 | if (IS_VALLEYVIEW(dev_priv)) |
| 426 | return valleyview_crt_detect_hotplug(connector); | 427 | return valleyview_crt_detect_hotplug(connector); |
| 427 | 428 | ||
| 428 | /* | 429 | /* |
| @@ -430,7 +431,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
| 430 | * to get a reliable result. | 431 | * to get a reliable result. |
| 431 | */ | 432 | */ |
| 432 | 433 | ||
| 433 | if (IS_G4X(dev) && !IS_GM45(dev)) | 434 | if (IS_G4X(dev_priv) && !IS_GM45(dev_priv)) |
| 434 | tries = 2; | 435 | tries = 2; |
| 435 | else | 436 | else |
| 436 | tries = 1; | 437 | tries = 1; |
| @@ -566,7 +567,7 @@ intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe) | |||
| 566 | /* Set the border color to purple. */ | 567 | /* Set the border color to purple. */ |
| 567 | I915_WRITE(bclrpat_reg, 0x500050); | 568 | I915_WRITE(bclrpat_reg, 0x500050); |
| 568 | 569 | ||
| 569 | if (!IS_GEN2(dev)) { | 570 | if (!IS_GEN2(dev_priv)) { |
| 570 | uint32_t pipeconf = I915_READ(pipeconf_reg); | 571 | uint32_t pipeconf = I915_READ(pipeconf_reg); |
| 571 | I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); | 572 | I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); |
| 572 | POSTING_READ(pipeconf_reg); | 573 | POSTING_READ(pipeconf_reg); |
| @@ -643,6 +644,32 @@ intel_crt_load_detect(struct intel_crt *crt, uint32_t pipe) | |||
| 643 | return status; | 644 | return status; |
| 644 | } | 645 | } |
| 645 | 646 | ||
| 647 | static int intel_spurious_crt_detect_dmi_callback(const struct dmi_system_id *id) | ||
| 648 | { | ||
| 649 | DRM_DEBUG_DRIVER("Skipping CRT detection for %s\n", id->ident); | ||
| 650 | return 1; | ||
| 651 | } | ||
| 652 | |||
| 653 | static const struct dmi_system_id intel_spurious_crt_detect[] = { | ||
| 654 | { | ||
| 655 | .callback = intel_spurious_crt_detect_dmi_callback, | ||
| 656 | .ident = "ACER ZGB", | ||
| 657 | .matches = { | ||
| 658 | DMI_MATCH(DMI_SYS_VENDOR, "ACER"), | ||
| 659 | DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), | ||
| 660 | }, | ||
| 661 | }, | ||
| 662 | { | ||
| 663 | .callback = intel_spurious_crt_detect_dmi_callback, | ||
| 664 | .ident = "Intel DZ77BH-55K", | ||
| 665 | .matches = { | ||
| 666 | DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), | ||
| 667 | DMI_MATCH(DMI_BOARD_NAME, "DZ77BH-55K"), | ||
| 668 | }, | ||
| 669 | }, | ||
| 670 | { } | ||
| 671 | }; | ||
| 672 | |||
| 646 | static enum drm_connector_status | 673 | static enum drm_connector_status |
| 647 | intel_crt_detect(struct drm_connector *connector, bool force) | 674 | intel_crt_detect(struct drm_connector *connector, bool force) |
| 648 | { | 675 | { |
| @@ -659,6 +686,10 @@ intel_crt_detect(struct drm_connector *connector, bool force) | |||
| 659 | connector->base.id, connector->name, | 686 | connector->base.id, connector->name, |
| 660 | force); | 687 | force); |
| 661 | 688 | ||
| 689 | /* Skip machines without VGA that falsely report hotplug events */ | ||
| 690 | if (dmi_check_system(intel_spurious_crt_detect)) | ||
| 691 | return connector_status_disconnected; | ||
| 692 | |||
| 662 | power_domain = intel_display_port_power_domain(intel_encoder); | 693 | power_domain = intel_display_port_power_domain(intel_encoder); |
| 663 | intel_display_power_get(dev_priv, power_domain); | 694 | intel_display_power_get(dev_priv, power_domain); |
| 664 | 695 | ||
| @@ -740,7 +771,7 @@ static int intel_crt_get_modes(struct drm_connector *connector) | |||
| 740 | 771 | ||
| 741 | i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin); | 772 | i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin); |
| 742 | ret = intel_crt_ddc_get_modes(connector, i2c); | 773 | ret = intel_crt_ddc_get_modes(connector, i2c); |
| 743 | if (ret || !IS_G4X(dev)) | 774 | if (ret || !IS_G4X(dev_priv)) |
| 744 | goto out; | 775 | goto out; |
| 745 | 776 | ||
| 746 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ | 777 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ |
| @@ -808,32 +839,6 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = { | |||
| 808 | .destroy = intel_encoder_destroy, | 839 | .destroy = intel_encoder_destroy, |
| 809 | }; | 840 | }; |
| 810 | 841 | ||
| 811 | static int intel_no_crt_dmi_callback(const struct dmi_system_id *id) | ||
| 812 | { | ||
| 813 | DRM_INFO("Skipping CRT initialization for %s\n", id->ident); | ||
| 814 | return 1; | ||
| 815 | } | ||
| 816 | |||
| 817 | static const struct dmi_system_id intel_no_crt[] = { | ||
| 818 | { | ||
| 819 | .callback = intel_no_crt_dmi_callback, | ||
| 820 | .ident = "ACER ZGB", | ||
| 821 | .matches = { | ||
| 822 | DMI_MATCH(DMI_SYS_VENDOR, "ACER"), | ||
| 823 | DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"), | ||
| 824 | }, | ||
| 825 | }, | ||
| 826 | { | ||
| 827 | .callback = intel_no_crt_dmi_callback, | ||
| 828 | .ident = "DELL XPS 8700", | ||
| 829 | .matches = { | ||
| 830 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 831 | DMI_MATCH(DMI_PRODUCT_NAME, "XPS 8700"), | ||
| 832 | }, | ||
| 833 | }, | ||
| 834 | { } | ||
| 835 | }; | ||
| 836 | |||
| 837 | void intel_crt_init(struct drm_device *dev) | 842 | void intel_crt_init(struct drm_device *dev) |
| 838 | { | 843 | { |
| 839 | struct drm_connector *connector; | 844 | struct drm_connector *connector; |
| @@ -843,13 +848,9 @@ void intel_crt_init(struct drm_device *dev) | |||
| 843 | i915_reg_t adpa_reg; | 848 | i915_reg_t adpa_reg; |
| 844 | u32 adpa; | 849 | u32 adpa; |
| 845 | 850 | ||
| 846 | /* Skip machines without VGA that falsely report hotplug events */ | 851 | if (HAS_PCH_SPLIT(dev_priv)) |
| 847 | if (dmi_check_system(intel_no_crt)) | ||
| 848 | return; | ||
| 849 | |||
| 850 | if (HAS_PCH_SPLIT(dev)) | ||
| 851 | adpa_reg = PCH_ADPA; | 852 | adpa_reg = PCH_ADPA; |
| 852 | else if (IS_VALLEYVIEW(dev)) | 853 | else if (IS_VALLEYVIEW(dev_priv)) |
| 853 | adpa_reg = VLV_ADPA; | 854 | adpa_reg = VLV_ADPA; |
| 854 | else | 855 | else |
| 855 | adpa_reg = ADPA; | 856 | adpa_reg = ADPA; |
| @@ -893,12 +894,12 @@ void intel_crt_init(struct drm_device *dev) | |||
| 893 | 894 | ||
| 894 | crt->base.type = INTEL_OUTPUT_ANALOG; | 895 | crt->base.type = INTEL_OUTPUT_ANALOG; |
| 895 | crt->base.cloneable = (1 << INTEL_OUTPUT_DVO) | (1 << INTEL_OUTPUT_HDMI); | 896 | crt->base.cloneable = (1 << INTEL_OUTPUT_DVO) | (1 << INTEL_OUTPUT_HDMI); |
| 896 | if (IS_I830(dev)) | 897 | if (IS_I830(dev_priv)) |
| 897 | crt->base.crtc_mask = (1 << 0); | 898 | crt->base.crtc_mask = (1 << 0); |
| 898 | else | 899 | else |
| 899 | crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); | 900 | crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
| 900 | 901 | ||
| 901 | if (IS_GEN2(dev)) | 902 | if (IS_GEN2(dev_priv)) |
| 902 | connector->interlace_allowed = 0; | 903 | connector->interlace_allowed = 0; |
| 903 | else | 904 | else |
| 904 | connector->interlace_allowed = 1; | 905 | connector->interlace_allowed = 1; |
| @@ -907,20 +908,23 @@ void intel_crt_init(struct drm_device *dev) | |||
| 907 | crt->adpa_reg = adpa_reg; | 908 | crt->adpa_reg = adpa_reg; |
| 908 | 909 | ||
| 909 | crt->base.compute_config = intel_crt_compute_config; | 910 | crt->base.compute_config = intel_crt_compute_config; |
| 910 | if (HAS_PCH_SPLIT(dev)) { | 911 | if (HAS_PCH_SPLIT(dev_priv)) { |
| 911 | crt->base.disable = pch_disable_crt; | 912 | crt->base.disable = pch_disable_crt; |
| 912 | crt->base.post_disable = pch_post_disable_crt; | 913 | crt->base.post_disable = pch_post_disable_crt; |
| 913 | } else { | 914 | } else { |
| 914 | crt->base.disable = intel_disable_crt; | 915 | crt->base.disable = intel_disable_crt; |
| 915 | } | 916 | } |
| 916 | crt->base.enable = intel_enable_crt; | 917 | crt->base.enable = intel_enable_crt; |
| 917 | if (I915_HAS_HOTPLUG(dev)) | 918 | if (I915_HAS_HOTPLUG(dev) && |
| 919 | !dmi_check_system(intel_spurious_crt_detect)) | ||
| 918 | crt->base.hpd_pin = HPD_CRT; | 920 | crt->base.hpd_pin = HPD_CRT; |
| 919 | if (HAS_DDI(dev)) { | 921 | if (HAS_DDI(dev_priv)) { |
| 922 | crt->base.port = PORT_E; | ||
| 920 | crt->base.get_config = hsw_crt_get_config; | 923 | crt->base.get_config = hsw_crt_get_config; |
| 921 | crt->base.get_hw_state = intel_ddi_get_hw_state; | 924 | crt->base.get_hw_state = intel_ddi_get_hw_state; |
| 922 | crt->base.post_disable = hsw_post_disable_crt; | 925 | crt->base.post_disable = hsw_post_disable_crt; |
| 923 | } else { | 926 | } else { |
| 927 | crt->base.port = PORT_NONE; | ||
| 924 | crt->base.get_config = intel_crt_get_config; | 928 | crt->base.get_config = intel_crt_get_config; |
| 925 | crt->base.get_hw_state = intel_crt_get_hw_state; | 929 | crt->base.get_hw_state = intel_crt_get_hw_state; |
| 926 | } | 930 | } |
| @@ -941,7 +945,7 @@ void intel_crt_init(struct drm_device *dev) | |||
| 941 | * polarity and link reversal bits or not, instead of relying on the | 945 | * polarity and link reversal bits or not, instead of relying on the |
| 942 | * BIOS. | 946 | * BIOS. |
| 943 | */ | 947 | */ |
| 944 | if (HAS_PCH_LPT(dev)) { | 948 | if (HAS_PCH_LPT(dev_priv)) { |
| 945 | u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT | | 949 | u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT | |
| 946 | FDI_RX_LINK_REVERSAL_OVERRIDE; | 950 | FDI_RX_LINK_REVERSAL_OVERRIDE; |
| 947 | 951 | ||
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 15d47c87def6..fb18d699ce10 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
| @@ -167,8 +167,47 @@ static const struct ddi_buf_trans skl_y_ddi_translations_dp[] = { | |||
| 167 | { 0x80005012, 0x000000C0, 0x3 }, | 167 | { 0x80005012, 0x000000C0, 0x3 }, |
| 168 | }; | 168 | }; |
| 169 | 169 | ||
| 170 | /* Kabylake H and S */ | ||
| 171 | static const struct ddi_buf_trans kbl_ddi_translations_dp[] = { | ||
| 172 | { 0x00002016, 0x000000A0, 0x0 }, | ||
| 173 | { 0x00005012, 0x0000009B, 0x0 }, | ||
| 174 | { 0x00007011, 0x00000088, 0x0 }, | ||
| 175 | { 0x80009010, 0x000000C0, 0x1 }, | ||
| 176 | { 0x00002016, 0x0000009B, 0x0 }, | ||
| 177 | { 0x00005012, 0x00000088, 0x0 }, | ||
| 178 | { 0x80007011, 0x000000C0, 0x1 }, | ||
| 179 | { 0x00002016, 0x00000097, 0x0 }, | ||
| 180 | { 0x80005012, 0x000000C0, 0x1 }, | ||
| 181 | }; | ||
| 182 | |||
| 183 | /* Kabylake U */ | ||
| 184 | static const struct ddi_buf_trans kbl_u_ddi_translations_dp[] = { | ||
| 185 | { 0x0000201B, 0x000000A1, 0x0 }, | ||
| 186 | { 0x00005012, 0x00000088, 0x0 }, | ||
| 187 | { 0x80007011, 0x000000CD, 0x3 }, | ||
| 188 | { 0x80009010, 0x000000C0, 0x3 }, | ||
| 189 | { 0x0000201B, 0x0000009D, 0x0 }, | ||
| 190 | { 0x80005012, 0x000000C0, 0x3 }, | ||
| 191 | { 0x80007011, 0x000000C0, 0x3 }, | ||
| 192 | { 0x00002016, 0x0000004F, 0x0 }, | ||
| 193 | { 0x80005012, 0x000000C0, 0x3 }, | ||
| 194 | }; | ||
| 195 | |||
| 196 | /* Kabylake Y */ | ||
| 197 | static const struct ddi_buf_trans kbl_y_ddi_translations_dp[] = { | ||
| 198 | { 0x00001017, 0x000000A1, 0x0 }, | ||
| 199 | { 0x00005012, 0x00000088, 0x0 }, | ||
| 200 | { 0x80007011, 0x000000CD, 0x3 }, | ||
| 201 | { 0x8000800F, 0x000000C0, 0x3 }, | ||
| 202 | { 0x00001017, 0x0000009D, 0x0 }, | ||
| 203 | { 0x80005012, 0x000000C0, 0x3 }, | ||
| 204 | { 0x80007011, 0x000000C0, 0x3 }, | ||
| 205 | { 0x00001017, 0x0000004C, 0x0 }, | ||
| 206 | { 0x80005012, 0x000000C0, 0x3 }, | ||
| 207 | }; | ||
| 208 | |||
| 170 | /* | 209 | /* |
| 171 | * Skylake H and S | 210 | * Skylake/Kabylake H and S |
| 172 | * eDP 1.4 low vswing translation parameters | 211 | * eDP 1.4 low vswing translation parameters |
| 173 | */ | 212 | */ |
| 174 | static const struct ddi_buf_trans skl_ddi_translations_edp[] = { | 213 | static const struct ddi_buf_trans skl_ddi_translations_edp[] = { |
| @@ -185,7 +224,7 @@ static const struct ddi_buf_trans skl_ddi_translations_edp[] = { | |||
| 185 | }; | 224 | }; |
| 186 | 225 | ||
| 187 | /* | 226 | /* |
| 188 | * Skylake U | 227 | * Skylake/Kabylake U |
| 189 | * eDP 1.4 low vswing translation parameters | 228 | * eDP 1.4 low vswing translation parameters |
| 190 | */ | 229 | */ |
| 191 | static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = { | 230 | static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = { |
| @@ -202,7 +241,7 @@ static const struct ddi_buf_trans skl_u_ddi_translations_edp[] = { | |||
| 202 | }; | 241 | }; |
| 203 | 242 | ||
| 204 | /* | 243 | /* |
| 205 | * Skylake Y | 244 | * Skylake/Kabylake Y |
| 206 | * eDP 1.4 low vswing translation parameters | 245 | * eDP 1.4 low vswing translation parameters |
| 207 | */ | 246 | */ |
| 208 | static const struct ddi_buf_trans skl_y_ddi_translations_edp[] = { | 247 | static const struct ddi_buf_trans skl_y_ddi_translations_edp[] = { |
| @@ -218,7 +257,7 @@ static const struct ddi_buf_trans skl_y_ddi_translations_edp[] = { | |||
| 218 | { 0x00000018, 0x0000008A, 0x0 }, | 257 | { 0x00000018, 0x0000008A, 0x0 }, |
| 219 | }; | 258 | }; |
| 220 | 259 | ||
| 221 | /* Skylake U, H and S */ | 260 | /* Skylake/Kabylake U, H and S */ |
| 222 | static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { | 261 | static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { |
| 223 | { 0x00000018, 0x000000AC, 0x0 }, | 262 | { 0x00000018, 0x000000AC, 0x0 }, |
| 224 | { 0x00005012, 0x0000009D, 0x0 }, | 263 | { 0x00005012, 0x0000009D, 0x0 }, |
| @@ -233,7 +272,7 @@ static const struct ddi_buf_trans skl_ddi_translations_hdmi[] = { | |||
| 233 | { 0x80000018, 0x000000C0, 0x1 }, | 272 | { 0x80000018, 0x000000C0, 0x1 }, |
| 234 | }; | 273 | }; |
| 235 | 274 | ||
| 236 | /* Skylake Y */ | 275 | /* Skylake/Kabylake Y */ |
| 237 | static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = { | 276 | static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = { |
| 238 | { 0x00000018, 0x000000A1, 0x0 }, | 277 | { 0x00000018, 0x000000A1, 0x0 }, |
| 239 | { 0x00005012, 0x000000DF, 0x0 }, | 278 | { 0x00005012, 0x000000DF, 0x0 }, |
| @@ -334,10 +373,10 @@ bdw_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) | |||
| 334 | static const struct ddi_buf_trans * | 373 | static const struct ddi_buf_trans * |
| 335 | skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) | 374 | skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) |
| 336 | { | 375 | { |
| 337 | if (IS_SKL_ULX(dev_priv) || IS_KBL_ULX(dev_priv)) { | 376 | if (IS_SKL_ULX(dev_priv)) { |
| 338 | *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); | 377 | *n_entries = ARRAY_SIZE(skl_y_ddi_translations_dp); |
| 339 | return skl_y_ddi_translations_dp; | 378 | return skl_y_ddi_translations_dp; |
| 340 | } else if (IS_SKL_ULT(dev_priv) || IS_KBL_ULT(dev_priv)) { | 379 | } else if (IS_SKL_ULT(dev_priv)) { |
| 341 | *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); | 380 | *n_entries = ARRAY_SIZE(skl_u_ddi_translations_dp); |
| 342 | return skl_u_ddi_translations_dp; | 381 | return skl_u_ddi_translations_dp; |
| 343 | } else { | 382 | } else { |
| @@ -347,6 +386,21 @@ skl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) | |||
| 347 | } | 386 | } |
| 348 | 387 | ||
| 349 | static const struct ddi_buf_trans * | 388 | static const struct ddi_buf_trans * |
| 389 | kbl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) | ||
| 390 | { | ||
| 391 | if (IS_KBL_ULX(dev_priv)) { | ||
| 392 | *n_entries = ARRAY_SIZE(kbl_y_ddi_translations_dp); | ||
| 393 | return kbl_y_ddi_translations_dp; | ||
| 394 | } else if (IS_KBL_ULT(dev_priv)) { | ||
| 395 | *n_entries = ARRAY_SIZE(kbl_u_ddi_translations_dp); | ||
| 396 | return kbl_u_ddi_translations_dp; | ||
| 397 | } else { | ||
| 398 | *n_entries = ARRAY_SIZE(kbl_ddi_translations_dp); | ||
| 399 | return kbl_ddi_translations_dp; | ||
| 400 | } | ||
| 401 | } | ||
| 402 | |||
| 403 | static const struct ddi_buf_trans * | ||
| 350 | skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) | 404 | skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) |
| 351 | { | 405 | { |
| 352 | if (dev_priv->vbt.edp.low_vswing) { | 406 | if (dev_priv->vbt.edp.low_vswing) { |
| @@ -362,7 +416,10 @@ skl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) | |||
| 362 | } | 416 | } |
| 363 | } | 417 | } |
| 364 | 418 | ||
| 365 | return skl_get_buf_trans_dp(dev_priv, n_entries); | 419 | if (IS_KABYLAKE(dev_priv)) |
| 420 | return kbl_get_buf_trans_dp(dev_priv, n_entries); | ||
| 421 | else | ||
| 422 | return skl_get_buf_trans_dp(dev_priv, n_entries); | ||
| 366 | } | 423 | } |
| 367 | 424 | ||
| 368 | static const struct ddi_buf_trans * | 425 | static const struct ddi_buf_trans * |
| @@ -430,21 +487,18 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) | |||
| 430 | if (IS_BROXTON(dev_priv)) | 487 | if (IS_BROXTON(dev_priv)) |
| 431 | return; | 488 | return; |
| 432 | 489 | ||
| 433 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { | 490 | if (IS_KABYLAKE(dev_priv)) { |
| 491 | ddi_translations_fdi = NULL; | ||
| 492 | ddi_translations_dp = | ||
| 493 | kbl_get_buf_trans_dp(dev_priv, &n_dp_entries); | ||
| 494 | ddi_translations_edp = | ||
| 495 | skl_get_buf_trans_edp(dev_priv, &n_edp_entries); | ||
| 496 | } else if (IS_SKYLAKE(dev_priv)) { | ||
| 434 | ddi_translations_fdi = NULL; | 497 | ddi_translations_fdi = NULL; |
| 435 | ddi_translations_dp = | 498 | ddi_translations_dp = |
| 436 | skl_get_buf_trans_dp(dev_priv, &n_dp_entries); | 499 | skl_get_buf_trans_dp(dev_priv, &n_dp_entries); |
| 437 | ddi_translations_edp = | 500 | ddi_translations_edp = |
| 438 | skl_get_buf_trans_edp(dev_priv, &n_edp_entries); | 501 | skl_get_buf_trans_edp(dev_priv, &n_edp_entries); |
| 439 | |||
| 440 | /* If we're boosting the current, set bit 31 of trans1 */ | ||
| 441 | if (dev_priv->vbt.ddi_port_info[port].dp_boost_level) | ||
| 442 | iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE; | ||
| 443 | |||
| 444 | if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP && | ||
| 445 | port != PORT_A && port != PORT_E && | ||
| 446 | n_edp_entries > 9)) | ||
| 447 | n_edp_entries = 9; | ||
| 448 | } else if (IS_BROADWELL(dev_priv)) { | 502 | } else if (IS_BROADWELL(dev_priv)) { |
| 449 | ddi_translations_fdi = bdw_ddi_translations_fdi; | 503 | ddi_translations_fdi = bdw_ddi_translations_fdi; |
| 450 | ddi_translations_dp = bdw_ddi_translations_dp; | 504 | ddi_translations_dp = bdw_ddi_translations_dp; |
| @@ -464,6 +518,17 @@ void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) | |||
| 464 | n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); | 518 | n_dp_entries = ARRAY_SIZE(bdw_ddi_translations_dp); |
| 465 | } | 519 | } |
| 466 | 520 | ||
| 521 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { | ||
| 522 | /* If we're boosting the current, set bit 31 of trans1 */ | ||
| 523 | if (dev_priv->vbt.ddi_port_info[port].dp_boost_level) | ||
| 524 | iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE; | ||
| 525 | |||
| 526 | if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP && | ||
| 527 | port != PORT_A && port != PORT_E && | ||
| 528 | n_edp_entries > 9)) | ||
| 529 | n_edp_entries = 9; | ||
| 530 | } | ||
| 531 | |||
| 467 | switch (encoder->type) { | 532 | switch (encoder->type) { |
| 468 | case INTEL_OUTPUT_EDP: | 533 | case INTEL_OUTPUT_EDP: |
| 469 | ddi_translations = ddi_translations_edp; | 534 | ddi_translations = ddi_translations_edp; |
| @@ -1020,13 +1085,13 @@ static void bxt_ddi_clock_get(struct intel_encoder *encoder, | |||
| 1020 | void intel_ddi_clock_get(struct intel_encoder *encoder, | 1085 | void intel_ddi_clock_get(struct intel_encoder *encoder, |
| 1021 | struct intel_crtc_state *pipe_config) | 1086 | struct intel_crtc_state *pipe_config) |
| 1022 | { | 1087 | { |
| 1023 | struct drm_device *dev = encoder->base.dev; | 1088 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 1024 | 1089 | ||
| 1025 | if (INTEL_INFO(dev)->gen <= 8) | 1090 | if (INTEL_GEN(dev_priv) <= 8) |
| 1026 | hsw_ddi_clock_get(encoder, pipe_config); | 1091 | hsw_ddi_clock_get(encoder, pipe_config); |
| 1027 | else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) | 1092 | else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
| 1028 | skl_ddi_clock_get(encoder, pipe_config); | 1093 | skl_ddi_clock_get(encoder, pipe_config); |
| 1029 | else if (IS_BROXTON(dev)) | 1094 | else if (IS_BROXTON(dev_priv)) |
| 1030 | bxt_ddi_clock_get(encoder, pipe_config); | 1095 | bxt_ddi_clock_get(encoder, pipe_config); |
| 1031 | } | 1096 | } |
| 1032 | 1097 | ||
| @@ -1081,14 +1146,14 @@ bxt_ddi_pll_select(struct intel_crtc *intel_crtc, | |||
| 1081 | bool intel_ddi_pll_select(struct intel_crtc *intel_crtc, | 1146 | bool intel_ddi_pll_select(struct intel_crtc *intel_crtc, |
| 1082 | struct intel_crtc_state *crtc_state) | 1147 | struct intel_crtc_state *crtc_state) |
| 1083 | { | 1148 | { |
| 1084 | struct drm_device *dev = intel_crtc->base.dev; | 1149 | struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev); |
| 1085 | struct intel_encoder *intel_encoder = | 1150 | struct intel_encoder *intel_encoder = |
| 1086 | intel_ddi_get_crtc_new_encoder(crtc_state); | 1151 | intel_ddi_get_crtc_new_encoder(crtc_state); |
| 1087 | 1152 | ||
| 1088 | if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) | 1153 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
| 1089 | return skl_ddi_pll_select(intel_crtc, crtc_state, | 1154 | return skl_ddi_pll_select(intel_crtc, crtc_state, |
| 1090 | intel_encoder); | 1155 | intel_encoder); |
| 1091 | else if (IS_BROXTON(dev)) | 1156 | else if (IS_BROXTON(dev_priv)) |
| 1092 | return bxt_ddi_pll_select(intel_crtc, crtc_state, | 1157 | return bxt_ddi_pll_select(intel_crtc, crtc_state, |
| 1093 | intel_encoder); | 1158 | intel_encoder); |
| 1094 | else | 1159 | else |
| @@ -1189,7 +1254,7 @@ void intel_ddi_enable_transcoder_func(struct drm_crtc *crtc) | |||
| 1189 | * eDP when not using the panel fitter, and when not | 1254 | * eDP when not using the panel fitter, and when not |
| 1190 | * using motion blur mitigation (which we don't | 1255 | * using motion blur mitigation (which we don't |
| 1191 | * support). */ | 1256 | * support). */ |
| 1192 | if (IS_HASWELL(dev) && | 1257 | if (IS_HASWELL(dev_priv) && |
| 1193 | (intel_crtc->config->pch_pfit.enabled || | 1258 | (intel_crtc->config->pch_pfit.enabled || |
| 1194 | intel_crtc->config->pch_pfit.force_thru)) | 1259 | intel_crtc->config->pch_pfit.force_thru)) |
| 1195 | temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; | 1260 | temp |= TRANS_DDI_EDP_INPUT_A_ONOFF; |
| @@ -1434,7 +1499,12 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder, u32 level) | |||
| 1434 | if (dp_iboost) { | 1499 | if (dp_iboost) { |
| 1435 | iboost = dp_iboost; | 1500 | iboost = dp_iboost; |
| 1436 | } else { | 1501 | } else { |
| 1437 | ddi_translations = skl_get_buf_trans_dp(dev_priv, &n_entries); | 1502 | if (IS_KABYLAKE(dev_priv)) |
| 1503 | ddi_translations = kbl_get_buf_trans_dp(dev_priv, | ||
| 1504 | &n_entries); | ||
| 1505 | else | ||
| 1506 | ddi_translations = skl_get_buf_trans_dp(dev_priv, | ||
| 1507 | &n_entries); | ||
| 1438 | iboost = ddi_translations[level].i_boost; | 1508 | iboost = ddi_translations[level].i_boost; |
| 1439 | } | 1509 | } |
| 1440 | } else if (type == INTEL_OUTPUT_EDP) { | 1510 | } else if (type == INTEL_OUTPUT_EDP) { |
| @@ -1742,7 +1812,7 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder, | |||
| 1742 | intel_edp_panel_off(intel_dp); | 1812 | intel_edp_panel_off(intel_dp); |
| 1743 | } | 1813 | } |
| 1744 | 1814 | ||
| 1745 | if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) | 1815 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
| 1746 | I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) | | 1816 | I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) | |
| 1747 | DPLL_CTRL2_DDI_CLK_OFF(port))); | 1817 | DPLL_CTRL2_DDI_CLK_OFF(port))); |
| 1748 | else if (INTEL_INFO(dev)->gen < 9) | 1818 | else if (INTEL_INFO(dev)->gen < 9) |
| @@ -2438,7 +2508,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) | |||
| 2438 | struct intel_digital_port *intel_dig_port; | 2508 | struct intel_digital_port *intel_dig_port; |
| 2439 | struct intel_encoder *intel_encoder; | 2509 | struct intel_encoder *intel_encoder; |
| 2440 | struct drm_encoder *encoder; | 2510 | struct drm_encoder *encoder; |
| 2441 | bool init_hdmi, init_dp; | 2511 | bool init_hdmi, init_dp, init_lspcon = false; |
| 2442 | int max_lanes; | 2512 | int max_lanes; |
| 2443 | 2513 | ||
| 2444 | if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) { | 2514 | if (I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) { |
| @@ -2470,6 +2540,19 @@ void intel_ddi_init(struct drm_device *dev, enum port port) | |||
| 2470 | init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || | 2540 | init_hdmi = (dev_priv->vbt.ddi_port_info[port].supports_dvi || |
| 2471 | dev_priv->vbt.ddi_port_info[port].supports_hdmi); | 2541 | dev_priv->vbt.ddi_port_info[port].supports_hdmi); |
| 2472 | init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp; | 2542 | init_dp = dev_priv->vbt.ddi_port_info[port].supports_dp; |
| 2543 | |||
| 2544 | if (intel_bios_is_lspcon_present(dev_priv, port)) { | ||
| 2545 | /* | ||
| 2546 | * Lspcon device needs to be driven with DP connector | ||
| 2547 | * with special detection sequence. So make sure DP | ||
| 2548 | * is initialized before lspcon. | ||
| 2549 | */ | ||
| 2550 | init_dp = true; | ||
| 2551 | init_lspcon = true; | ||
| 2552 | init_hdmi = false; | ||
| 2553 | DRM_DEBUG_KMS("VBT says port %c has lspcon\n", port_name(port)); | ||
| 2554 | } | ||
| 2555 | |||
| 2473 | if (!init_dp && !init_hdmi) { | 2556 | if (!init_dp && !init_hdmi) { |
| 2474 | DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, respect it\n", | 2557 | DRM_DEBUG_KMS("VBT says port %c is not DVI/HDMI/DP compatible, respect it\n", |
| 2475 | port_name(port)); | 2558 | port_name(port)); |
| @@ -2509,7 +2592,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) | |||
| 2509 | * configuration so that we use the proper lane count for our | 2592 | * configuration so that we use the proper lane count for our |
| 2510 | * calculations. | 2593 | * calculations. |
| 2511 | */ | 2594 | */ |
| 2512 | if (IS_BROXTON(dev) && port == PORT_A) { | 2595 | if (IS_BROXTON(dev_priv) && port == PORT_A) { |
| 2513 | if (!(intel_dig_port->saved_port_bits & DDI_A_4_LANES)) { | 2596 | if (!(intel_dig_port->saved_port_bits & DDI_A_4_LANES)) { |
| 2514 | DRM_DEBUG_KMS("BXT BIOS forgot to set DDI_A_4_LANES for port A; fixing\n"); | 2597 | DRM_DEBUG_KMS("BXT BIOS forgot to set DDI_A_4_LANES for port A; fixing\n"); |
| 2515 | intel_dig_port->saved_port_bits |= DDI_A_4_LANES; | 2598 | intel_dig_port->saved_port_bits |= DDI_A_4_LANES; |
| @@ -2520,6 +2603,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) | |||
| 2520 | intel_dig_port->max_lanes = max_lanes; | 2603 | intel_dig_port->max_lanes = max_lanes; |
| 2521 | 2604 | ||
| 2522 | intel_encoder->type = INTEL_OUTPUT_UNKNOWN; | 2605 | intel_encoder->type = INTEL_OUTPUT_UNKNOWN; |
| 2606 | intel_encoder->port = port; | ||
| 2523 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); | 2607 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
| 2524 | intel_encoder->cloneable = 0; | 2608 | intel_encoder->cloneable = 0; |
| 2525 | 2609 | ||
| @@ -2532,7 +2616,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port) | |||
| 2532 | * On BXT A0/A1, sw needs to activate DDIA HPD logic and | 2616 | * On BXT A0/A1, sw needs to activate DDIA HPD logic and |
| 2533 | * interrupts to check the external panel connection. | 2617 | * interrupts to check the external panel connection. |
| 2534 | */ | 2618 | */ |
| 2535 | if (IS_BXT_REVID(dev, 0, BXT_REVID_A1) && port == PORT_B) | 2619 | if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) && port == PORT_B) |
| 2536 | dev_priv->hotplug.irq_port[PORT_A] = intel_dig_port; | 2620 | dev_priv->hotplug.irq_port[PORT_A] = intel_dig_port; |
| 2537 | else | 2621 | else |
| 2538 | dev_priv->hotplug.irq_port[port] = intel_dig_port; | 2622 | dev_priv->hotplug.irq_port[port] = intel_dig_port; |
| @@ -2545,6 +2629,20 @@ void intel_ddi_init(struct drm_device *dev, enum port port) | |||
| 2545 | goto err; | 2629 | goto err; |
| 2546 | } | 2630 | } |
| 2547 | 2631 | ||
| 2632 | if (init_lspcon) { | ||
| 2633 | if (lspcon_init(intel_dig_port)) | ||
| 2634 | /* TODO: handle hdmi info frame part */ | ||
| 2635 | DRM_DEBUG_KMS("LSPCON init success on port %c\n", | ||
| 2636 | port_name(port)); | ||
| 2637 | else | ||
| 2638 | /* | ||
| 2639 | * LSPCON init faied, but DP init was success, so | ||
| 2640 | * lets try to drive as DP++ port. | ||
| 2641 | */ | ||
| 2642 | DRM_ERROR("LSPCON init failed on port %c\n", | ||
| 2643 | port_name(port)); | ||
| 2644 | } | ||
| 2645 | |||
| 2548 | return; | 2646 | return; |
| 2549 | 2647 | ||
| 2550 | err: | 2648 | err: |
diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 73b6858600ac..d6a8f11813d5 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c | |||
| @@ -28,20 +28,14 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv) | |||
| 28 | { | 28 | { |
| 29 | const struct intel_device_info *info = &dev_priv->info; | 29 | const struct intel_device_info *info = &dev_priv->info; |
| 30 | 30 | ||
| 31 | #define PRINT_S(name) "%s" | 31 | DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x", |
| 32 | #define SEP_EMPTY | ||
| 33 | #define PRINT_FLAG(name) info->name ? #name "," : "" | ||
| 34 | #define SEP_COMMA , | ||
| 35 | DRM_DEBUG_DRIVER("i915 device info: gen=%i, pciid=0x%04x rev=0x%02x flags=" | ||
| 36 | DEV_INFO_FOR_EACH_FLAG(PRINT_S, SEP_EMPTY), | ||
| 37 | info->gen, | 32 | info->gen, |
| 38 | dev_priv->drm.pdev->device, | 33 | dev_priv->drm.pdev->device, |
| 39 | dev_priv->drm.pdev->revision, | 34 | dev_priv->drm.pdev->revision); |
| 40 | DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG, SEP_COMMA)); | 35 | #define PRINT_FLAG(name) \ |
| 41 | #undef PRINT_S | 36 | DRM_DEBUG_DRIVER("i915 device info: " #name ": %s", yesno(info->name)) |
| 42 | #undef SEP_EMPTY | 37 | DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); |
| 43 | #undef PRINT_FLAG | 38 | #undef PRINT_FLAG |
| 44 | #undef SEP_COMMA | ||
| 45 | } | 39 | } |
| 46 | 40 | ||
| 47 | static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) | 41 | static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) |
| @@ -192,7 +186,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv) | |||
| 192 | struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; | 186 | struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; |
| 193 | const int s_max = 3, ss_max = 3, eu_max = 8; | 187 | const int s_max = 3, ss_max = 3, eu_max = 8; |
| 194 | int s, ss; | 188 | int s, ss; |
| 195 | u32 fuse2, eu_disable[s_max]; | 189 | u32 fuse2, eu_disable[3]; /* s_max */ |
| 196 | 190 | ||
| 197 | fuse2 = I915_READ(GEN8_FUSE2); | 191 | fuse2 = I915_READ(GEN8_FUSE2); |
| 198 | sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; | 192 | sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6c5c36eba6cb..6f8f6ec5b27a 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
| @@ -600,7 +600,7 @@ int chv_calc_dpll_params(int refclk, struct dpll *clock) | |||
| 600 | * the given connectors. | 600 | * the given connectors. |
| 601 | */ | 601 | */ |
| 602 | 602 | ||
| 603 | static bool intel_PLL_is_valid(struct drm_device *dev, | 603 | static bool intel_PLL_is_valid(struct drm_i915_private *dev_priv, |
| 604 | const struct intel_limit *limit, | 604 | const struct intel_limit *limit, |
| 605 | const struct dpll *clock) | 605 | const struct dpll *clock) |
| 606 | { | 606 | { |
| @@ -613,12 +613,13 @@ static bool intel_PLL_is_valid(struct drm_device *dev, | |||
| 613 | if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) | 613 | if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) |
| 614 | INTELPllInvalid("m1 out of range\n"); | 614 | INTELPllInvalid("m1 out of range\n"); |
| 615 | 615 | ||
| 616 | if (!IS_PINEVIEW(dev) && !IS_VALLEYVIEW(dev) && | 616 | if (!IS_PINEVIEW(dev_priv) && !IS_VALLEYVIEW(dev_priv) && |
| 617 | !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) | 617 | !IS_CHERRYVIEW(dev_priv) && !IS_BROXTON(dev_priv)) |
| 618 | if (clock->m1 <= clock->m2) | 618 | if (clock->m1 <= clock->m2) |
| 619 | INTELPllInvalid("m1 <= m2\n"); | 619 | INTELPllInvalid("m1 <= m2\n"); |
| 620 | 620 | ||
| 621 | if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && !IS_BROXTON(dev)) { | 621 | if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) && |
| 622 | !IS_BROXTON(dev_priv)) { | ||
| 622 | if (clock->p < limit->p.min || limit->p.max < clock->p) | 623 | if (clock->p < limit->p.min || limit->p.max < clock->p) |
| 623 | INTELPllInvalid("p out of range\n"); | 624 | INTELPllInvalid("p out of range\n"); |
| 624 | if (clock->m < limit->m.min || limit->m.max < clock->m) | 625 | if (clock->m < limit->m.min || limit->m.max < clock->m) |
| @@ -698,7 +699,8 @@ i9xx_find_best_dpll(const struct intel_limit *limit, | |||
| 698 | int this_err; | 699 | int this_err; |
| 699 | 700 | ||
| 700 | i9xx_calc_dpll_params(refclk, &clock); | 701 | i9xx_calc_dpll_params(refclk, &clock); |
| 701 | if (!intel_PLL_is_valid(dev, limit, | 702 | if (!intel_PLL_is_valid(to_i915(dev), |
| 703 | limit, | ||
| 702 | &clock)) | 704 | &clock)) |
| 703 | continue; | 705 | continue; |
| 704 | if (match_clock && | 706 | if (match_clock && |
| @@ -753,7 +755,8 @@ pnv_find_best_dpll(const struct intel_limit *limit, | |||
| 753 | int this_err; | 755 | int this_err; |
| 754 | 756 | ||
| 755 | pnv_calc_dpll_params(refclk, &clock); | 757 | pnv_calc_dpll_params(refclk, &clock); |
| 756 | if (!intel_PLL_is_valid(dev, limit, | 758 | if (!intel_PLL_is_valid(to_i915(dev), |
| 759 | limit, | ||
| 757 | &clock)) | 760 | &clock)) |
| 758 | continue; | 761 | continue; |
| 759 | if (match_clock && | 762 | if (match_clock && |
| @@ -813,7 +816,8 @@ g4x_find_best_dpll(const struct intel_limit *limit, | |||
| 813 | int this_err; | 816 | int this_err; |
| 814 | 817 | ||
| 815 | i9xx_calc_dpll_params(refclk, &clock); | 818 | i9xx_calc_dpll_params(refclk, &clock); |
| 816 | if (!intel_PLL_is_valid(dev, limit, | 819 | if (!intel_PLL_is_valid(to_i915(dev), |
| 820 | limit, | ||
| 817 | &clock)) | 821 | &clock)) |
| 818 | continue; | 822 | continue; |
| 819 | 823 | ||
| @@ -845,7 +849,7 @@ static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq, | |||
| 845 | * For CHV ignore the error and consider only the P value. | 849 | * For CHV ignore the error and consider only the P value. |
| 846 | * Prefer a bigger P value based on HW requirements. | 850 | * Prefer a bigger P value based on HW requirements. |
| 847 | */ | 851 | */ |
| 848 | if (IS_CHERRYVIEW(dev)) { | 852 | if (IS_CHERRYVIEW(to_i915(dev))) { |
| 849 | *error_ppm = 0; | 853 | *error_ppm = 0; |
| 850 | 854 | ||
| 851 | return calculated_clock->p > best_clock->p; | 855 | return calculated_clock->p > best_clock->p; |
| @@ -909,7 +913,8 @@ vlv_find_best_dpll(const struct intel_limit *limit, | |||
| 909 | 913 | ||
| 910 | vlv_calc_dpll_params(refclk, &clock); | 914 | vlv_calc_dpll_params(refclk, &clock); |
| 911 | 915 | ||
| 912 | if (!intel_PLL_is_valid(dev, limit, | 916 | if (!intel_PLL_is_valid(to_i915(dev), |
| 917 | limit, | ||
| 913 | &clock)) | 918 | &clock)) |
| 914 | continue; | 919 | continue; |
| 915 | 920 | ||
| @@ -977,7 +982,7 @@ chv_find_best_dpll(const struct intel_limit *limit, | |||
| 977 | 982 | ||
| 978 | chv_calc_dpll_params(refclk, &clock); | 983 | chv_calc_dpll_params(refclk, &clock); |
| 979 | 984 | ||
| 980 | if (!intel_PLL_is_valid(dev, limit, &clock)) | 985 | if (!intel_PLL_is_valid(to_i915(dev), limit, &clock)) |
| 981 | continue; | 986 | continue; |
| 982 | 987 | ||
| 983 | if (!vlv_PLL_is_optimal(dev, target, &clock, best_clock, | 988 | if (!vlv_PLL_is_optimal(dev, target, &clock, best_clock, |
| @@ -1040,7 +1045,7 @@ static bool pipe_dsl_stopped(struct drm_device *dev, enum pipe pipe) | |||
| 1040 | u32 line1, line2; | 1045 | u32 line1, line2; |
| 1041 | u32 line_mask; | 1046 | u32 line_mask; |
| 1042 | 1047 | ||
| 1043 | if (IS_GEN2(dev)) | 1048 | if (IS_GEN2(dev_priv)) |
| 1044 | line_mask = DSL_LINEMASK_GEN2; | 1049 | line_mask = DSL_LINEMASK_GEN2; |
| 1045 | else | 1050 | else |
| 1046 | line_mask = DSL_LINEMASK_GEN3; | 1051 | line_mask = DSL_LINEMASK_GEN3; |
| @@ -1187,19 +1192,17 @@ void assert_fdi_rx_pll(struct drm_i915_private *dev_priv, | |||
| 1187 | onoff(state), onoff(cur_state)); | 1192 | onoff(state), onoff(cur_state)); |
| 1188 | } | 1193 | } |
| 1189 | 1194 | ||
| 1190 | void assert_panel_unlocked(struct drm_i915_private *dev_priv, | 1195 | void assert_panel_unlocked(struct drm_i915_private *dev_priv, enum pipe pipe) |
| 1191 | enum pipe pipe) | ||
| 1192 | { | 1196 | { |
| 1193 | struct drm_device *dev = &dev_priv->drm; | ||
| 1194 | i915_reg_t pp_reg; | 1197 | i915_reg_t pp_reg; |
| 1195 | u32 val; | 1198 | u32 val; |
| 1196 | enum pipe panel_pipe = PIPE_A; | 1199 | enum pipe panel_pipe = PIPE_A; |
| 1197 | bool locked = true; | 1200 | bool locked = true; |
| 1198 | 1201 | ||
| 1199 | if (WARN_ON(HAS_DDI(dev))) | 1202 | if (WARN_ON(HAS_DDI(dev_priv))) |
| 1200 | return; | 1203 | return; |
| 1201 | 1204 | ||
| 1202 | if (HAS_PCH_SPLIT(dev)) { | 1205 | if (HAS_PCH_SPLIT(dev_priv)) { |
| 1203 | u32 port_sel; | 1206 | u32 port_sel; |
| 1204 | 1207 | ||
| 1205 | pp_reg = PP_CONTROL(0); | 1208 | pp_reg = PP_CONTROL(0); |
| @@ -1209,7 +1212,7 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, | |||
| 1209 | I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) | 1212 | I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) |
| 1210 | panel_pipe = PIPE_B; | 1213 | panel_pipe = PIPE_B; |
| 1211 | /* XXX: else fix for eDP */ | 1214 | /* XXX: else fix for eDP */ |
| 1212 | } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 1215 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 1213 | /* presumably write lock depends on pipe, not port select */ | 1216 | /* presumably write lock depends on pipe, not port select */ |
| 1214 | pp_reg = PP_CONTROL(pipe); | 1217 | pp_reg = PP_CONTROL(pipe); |
| 1215 | panel_pipe = pipe; | 1218 | panel_pipe = pipe; |
| @@ -1232,10 +1235,9 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv, | |||
| 1232 | static void assert_cursor(struct drm_i915_private *dev_priv, | 1235 | static void assert_cursor(struct drm_i915_private *dev_priv, |
| 1233 | enum pipe pipe, bool state) | 1236 | enum pipe pipe, bool state) |
| 1234 | { | 1237 | { |
| 1235 | struct drm_device *dev = &dev_priv->drm; | ||
| 1236 | bool cur_state; | 1238 | bool cur_state; |
| 1237 | 1239 | ||
| 1238 | if (IS_845G(dev) || IS_I865G(dev)) | 1240 | if (IS_845G(dev_priv) || IS_I865G(dev_priv)) |
| 1239 | cur_state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE; | 1241 | cur_state = I915_READ(CURCNTR(PIPE_A)) & CURSOR_ENABLE; |
| 1240 | else | 1242 | else |
| 1241 | cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; | 1243 | cur_state = I915_READ(CURCNTR(pipe)) & CURSOR_MODE; |
| @@ -1330,7 +1332,7 @@ static void assert_sprites_disabled(struct drm_i915_private *dev_priv, | |||
| 1330 | "plane %d assertion failure, should be off on pipe %c but is still active\n", | 1332 | "plane %d assertion failure, should be off on pipe %c but is still active\n", |
| 1331 | sprite, pipe_name(pipe)); | 1333 | sprite, pipe_name(pipe)); |
| 1332 | } | 1334 | } |
| 1333 | } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 1335 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 1334 | for_each_sprite(dev_priv, pipe, sprite) { | 1336 | for_each_sprite(dev_priv, pipe, sprite) { |
| 1335 | u32 val = I915_READ(SPCNTR(pipe, sprite)); | 1337 | u32 val = I915_READ(SPCNTR(pipe, sprite)); |
| 1336 | I915_STATE_WARN(val & SP_ENABLE, | 1338 | I915_STATE_WARN(val & SP_ENABLE, |
| @@ -1619,11 +1621,11 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) | |||
| 1619 | assert_pipe_disabled(dev_priv, crtc->pipe); | 1621 | assert_pipe_disabled(dev_priv, crtc->pipe); |
| 1620 | 1622 | ||
| 1621 | /* PLL is protected by panel, make sure we can write it */ | 1623 | /* PLL is protected by panel, make sure we can write it */ |
| 1622 | if (IS_MOBILE(dev) && !IS_I830(dev)) | 1624 | if (IS_MOBILE(dev_priv) && !IS_I830(dev_priv)) |
| 1623 | assert_panel_unlocked(dev_priv, crtc->pipe); | 1625 | assert_panel_unlocked(dev_priv, crtc->pipe); |
| 1624 | 1626 | ||
| 1625 | /* Enable DVO 2x clock on both PLLs if necessary */ | 1627 | /* Enable DVO 2x clock on both PLLs if necessary */ |
| 1626 | if (IS_I830(dev) && intel_num_dvo_pipes(dev) > 0) { | 1628 | if (IS_I830(dev_priv) && intel_num_dvo_pipes(dev) > 0) { |
| 1627 | /* | 1629 | /* |
| 1628 | * It appears to be important that we don't enable this | 1630 | * It appears to be important that we don't enable this |
| 1629 | * for the current pipe before otherwise configuring the | 1631 | * for the current pipe before otherwise configuring the |
| @@ -1688,7 +1690,7 @@ static void i9xx_disable_pll(struct intel_crtc *crtc) | |||
| 1688 | enum pipe pipe = crtc->pipe; | 1690 | enum pipe pipe = crtc->pipe; |
| 1689 | 1691 | ||
| 1690 | /* Disable DVO 2x clock on both PLLs if necessary */ | 1692 | /* Disable DVO 2x clock on both PLLs if necessary */ |
| 1691 | if (IS_I830(dev) && | 1693 | if (IS_I830(dev_priv) && |
| 1692 | intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DVO) && | 1694 | intel_crtc_has_type(crtc->config, INTEL_OUTPUT_DVO) && |
| 1693 | !intel_num_dvo_pipes(dev)) { | 1695 | !intel_num_dvo_pipes(dev)) { |
| 1694 | I915_WRITE(DPLL(PIPE_B), | 1696 | I915_WRITE(DPLL(PIPE_B), |
| @@ -1786,7 +1788,6 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, | |||
| 1786 | static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, | 1788 | static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, |
| 1787 | enum pipe pipe) | 1789 | enum pipe pipe) |
| 1788 | { | 1790 | { |
| 1789 | struct drm_device *dev = &dev_priv->drm; | ||
| 1790 | struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; | 1791 | struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; |
| 1791 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 1792 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 1792 | i915_reg_t reg; | 1793 | i915_reg_t reg; |
| @@ -1799,7 +1800,7 @@ static void ironlake_enable_pch_transcoder(struct drm_i915_private *dev_priv, | |||
| 1799 | assert_fdi_tx_enabled(dev_priv, pipe); | 1800 | assert_fdi_tx_enabled(dev_priv, pipe); |
| 1800 | assert_fdi_rx_enabled(dev_priv, pipe); | 1801 | assert_fdi_rx_enabled(dev_priv, pipe); |
| 1801 | 1802 | ||
| 1802 | if (HAS_PCH_CPT(dev)) { | 1803 | if (HAS_PCH_CPT(dev_priv)) { |
| 1803 | /* Workaround: Set the timing override bit before enabling the | 1804 | /* Workaround: Set the timing override bit before enabling the |
| 1804 | * pch transcoder. */ | 1805 | * pch transcoder. */ |
| 1805 | reg = TRANS_CHICKEN2(pipe); | 1806 | reg = TRANS_CHICKEN2(pipe); |
| @@ -1877,7 +1878,6 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, | |||
| 1877 | static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, | 1878 | static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, |
| 1878 | enum pipe pipe) | 1879 | enum pipe pipe) |
| 1879 | { | 1880 | { |
| 1880 | struct drm_device *dev = &dev_priv->drm; | ||
| 1881 | i915_reg_t reg; | 1881 | i915_reg_t reg; |
| 1882 | uint32_t val; | 1882 | uint32_t val; |
| 1883 | 1883 | ||
| @@ -1898,7 +1898,7 @@ static void ironlake_disable_pch_transcoder(struct drm_i915_private *dev_priv, | |||
| 1898 | 50)) | 1898 | 50)) |
| 1899 | DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe)); | 1899 | DRM_ERROR("failed to disable transcoder %c\n", pipe_name(pipe)); |
| 1900 | 1900 | ||
| 1901 | if (HAS_PCH_CPT(dev)) { | 1901 | if (HAS_PCH_CPT(dev_priv)) { |
| 1902 | /* Workaround: Clear the timing override chicken bit again. */ | 1902 | /* Workaround: Clear the timing override chicken bit again. */ |
| 1903 | reg = TRANS_CHICKEN2(pipe); | 1903 | reg = TRANS_CHICKEN2(pipe); |
| 1904 | val = I915_READ(reg); | 1904 | val = I915_READ(reg); |
| @@ -1926,6 +1926,18 @@ void lpt_disable_pch_transcoder(struct drm_i915_private *dev_priv) | |||
| 1926 | I915_WRITE(TRANS_CHICKEN2(PIPE_A), val); | 1926 | I915_WRITE(TRANS_CHICKEN2(PIPE_A), val); |
| 1927 | } | 1927 | } |
| 1928 | 1928 | ||
| 1929 | enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc) | ||
| 1930 | { | ||
| 1931 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); | ||
| 1932 | |||
| 1933 | WARN_ON(!crtc->config->has_pch_encoder); | ||
| 1934 | |||
| 1935 | if (HAS_PCH_LPT(dev_priv)) | ||
| 1936 | return TRANSCODER_A; | ||
| 1937 | else | ||
| 1938 | return (enum transcoder) crtc->pipe; | ||
| 1939 | } | ||
| 1940 | |||
| 1929 | /** | 1941 | /** |
| 1930 | * intel_enable_pipe - enable a pipe, asserting requirements | 1942 | * intel_enable_pipe - enable a pipe, asserting requirements |
| 1931 | * @crtc: crtc responsible for the pipe | 1943 | * @crtc: crtc responsible for the pipe |
| @@ -1939,7 +1951,6 @@ static void intel_enable_pipe(struct intel_crtc *crtc) | |||
| 1939 | struct drm_i915_private *dev_priv = to_i915(dev); | 1951 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 1940 | enum pipe pipe = crtc->pipe; | 1952 | enum pipe pipe = crtc->pipe; |
| 1941 | enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; | 1953 | enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; |
| 1942 | enum pipe pch_transcoder; | ||
| 1943 | i915_reg_t reg; | 1954 | i915_reg_t reg; |
| 1944 | u32 val; | 1955 | u32 val; |
| 1945 | 1956 | ||
| @@ -1949,11 +1960,6 @@ static void intel_enable_pipe(struct intel_crtc *crtc) | |||
| 1949 | assert_cursor_disabled(dev_priv, pipe); | 1960 | assert_cursor_disabled(dev_priv, pipe); |
| 1950 | assert_sprites_disabled(dev_priv, pipe); | 1961 | assert_sprites_disabled(dev_priv, pipe); |
| 1951 | 1962 | ||
| 1952 | if (HAS_PCH_LPT(dev_priv)) | ||
| 1953 | pch_transcoder = TRANSCODER_A; | ||
| 1954 | else | ||
| 1955 | pch_transcoder = pipe; | ||
| 1956 | |||
| 1957 | /* | 1963 | /* |
| 1958 | * A pipe without a PLL won't actually be able to drive bits from | 1964 | * A pipe without a PLL won't actually be able to drive bits from |
| 1959 | * a plane. On ILK+ the pipe PLLs are integrated, so we don't | 1965 | * a plane. On ILK+ the pipe PLLs are integrated, so we don't |
| @@ -1967,7 +1973,8 @@ static void intel_enable_pipe(struct intel_crtc *crtc) | |||
| 1967 | } else { | 1973 | } else { |
| 1968 | if (crtc->config->has_pch_encoder) { | 1974 | if (crtc->config->has_pch_encoder) { |
| 1969 | /* if driving the PCH, we need FDI enabled */ | 1975 | /* if driving the PCH, we need FDI enabled */ |
| 1970 | assert_fdi_rx_pll_enabled(dev_priv, pch_transcoder); | 1976 | assert_fdi_rx_pll_enabled(dev_priv, |
| 1977 | (enum pipe) intel_crtc_pch_transcoder(crtc)); | ||
| 1971 | assert_fdi_tx_pll_enabled(dev_priv, | 1978 | assert_fdi_tx_pll_enabled(dev_priv, |
| 1972 | (enum pipe) cpu_transcoder); | 1979 | (enum pipe) cpu_transcoder); |
| 1973 | } | 1980 | } |
| @@ -3033,7 +3040,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, | |||
| 3033 | ((crtc_state->pipe_src_h - 1) << 16) | | 3040 | ((crtc_state->pipe_src_h - 1) << 16) | |
| 3034 | (crtc_state->pipe_src_w - 1)); | 3041 | (crtc_state->pipe_src_w - 1)); |
| 3035 | I915_WRITE(DSPPOS(plane), 0); | 3042 | I915_WRITE(DSPPOS(plane), 0); |
| 3036 | } else if (IS_CHERRYVIEW(dev) && plane == PLANE_B) { | 3043 | } else if (IS_CHERRYVIEW(dev_priv) && plane == PLANE_B) { |
| 3037 | I915_WRITE(PRIMSIZE(plane), | 3044 | I915_WRITE(PRIMSIZE(plane), |
| 3038 | ((crtc_state->pipe_src_h - 1) << 16) | | 3045 | ((crtc_state->pipe_src_h - 1) << 16) | |
| 3039 | (crtc_state->pipe_src_w - 1)); | 3046 | (crtc_state->pipe_src_w - 1)); |
| @@ -3071,7 +3078,7 @@ static void i9xx_update_primary_plane(struct drm_plane *primary, | |||
| 3071 | fb->modifier[0] == I915_FORMAT_MOD_X_TILED) | 3078 | fb->modifier[0] == I915_FORMAT_MOD_X_TILED) |
| 3072 | dspcntr |= DISPPLANE_TILED; | 3079 | dspcntr |= DISPPLANE_TILED; |
| 3073 | 3080 | ||
| 3074 | if (IS_G4X(dev)) | 3081 | if (IS_G4X(dev_priv)) |
| 3075 | dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; | 3082 | dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; |
| 3076 | 3083 | ||
| 3077 | intel_add_fb_offsets(&x, &y, plane_state, 0); | 3084 | intel_add_fb_offsets(&x, &y, plane_state, 0); |
| @@ -3144,7 +3151,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, | |||
| 3144 | dspcntr = DISPPLANE_GAMMA_ENABLE; | 3151 | dspcntr = DISPPLANE_GAMMA_ENABLE; |
| 3145 | dspcntr |= DISPLAY_PLANE_ENABLE; | 3152 | dspcntr |= DISPLAY_PLANE_ENABLE; |
| 3146 | 3153 | ||
| 3147 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 3154 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 3148 | dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; | 3155 | dspcntr |= DISPPLANE_PIPE_CSC_ENABLE; |
| 3149 | 3156 | ||
| 3150 | switch (fb->pixel_format) { | 3157 | switch (fb->pixel_format) { |
| @@ -3173,7 +3180,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, | |||
| 3173 | if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) | 3180 | if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) |
| 3174 | dspcntr |= DISPPLANE_TILED; | 3181 | dspcntr |= DISPPLANE_TILED; |
| 3175 | 3182 | ||
| 3176 | if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) | 3183 | if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) |
| 3177 | dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; | 3184 | dspcntr |= DISPPLANE_TRICKLE_FEED_DISABLE; |
| 3178 | 3185 | ||
| 3179 | intel_add_fb_offsets(&x, &y, plane_state, 0); | 3186 | intel_add_fb_offsets(&x, &y, plane_state, 0); |
| @@ -3184,7 +3191,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, | |||
| 3184 | if (rotation == DRM_ROTATE_180) { | 3191 | if (rotation == DRM_ROTATE_180) { |
| 3185 | dspcntr |= DISPPLANE_ROTATE_180; | 3192 | dspcntr |= DISPPLANE_ROTATE_180; |
| 3186 | 3193 | ||
| 3187 | if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { | 3194 | if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) { |
| 3188 | x += (crtc_state->pipe_src_w - 1); | 3195 | x += (crtc_state->pipe_src_w - 1); |
| 3189 | y += (crtc_state->pipe_src_h - 1); | 3196 | y += (crtc_state->pipe_src_h - 1); |
| 3190 | } | 3197 | } |
| @@ -3201,7 +3208,7 @@ static void ironlake_update_primary_plane(struct drm_plane *primary, | |||
| 3201 | I915_WRITE(DSPSURF(plane), | 3208 | I915_WRITE(DSPSURF(plane), |
| 3202 | intel_fb_gtt_offset(fb, rotation) + | 3209 | intel_fb_gtt_offset(fb, rotation) + |
| 3203 | intel_crtc->dspaddr_offset); | 3210 | intel_crtc->dspaddr_offset); |
| 3204 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { | 3211 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { |
| 3205 | I915_WRITE(DSPOFFSET(plane), (y << 16) | x); | 3212 | I915_WRITE(DSPOFFSET(plane), (y << 16) | x); |
| 3206 | } else { | 3213 | } else { |
| 3207 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); | 3214 | I915_WRITE(DSPTILEOFF(plane), (y << 16) | x); |
| @@ -3378,6 +3385,8 @@ static void skylake_update_primary_plane(struct drm_plane *plane, | |||
| 3378 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); | 3385 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc_state->base.crtc); |
| 3379 | struct drm_framebuffer *fb = plane_state->base.fb; | 3386 | struct drm_framebuffer *fb = plane_state->base.fb; |
| 3380 | const struct skl_wm_values *wm = &dev_priv->wm.skl_results; | 3387 | const struct skl_wm_values *wm = &dev_priv->wm.skl_results; |
| 3388 | const struct skl_plane_wm *p_wm = | ||
| 3389 | &crtc_state->wm.skl.optimal.planes[0]; | ||
| 3381 | int pipe = intel_crtc->pipe; | 3390 | int pipe = intel_crtc->pipe; |
| 3382 | u32 plane_ctl; | 3391 | u32 plane_ctl; |
| 3383 | unsigned int rotation = plane_state->base.rotation; | 3392 | unsigned int rotation = plane_state->base.rotation; |
| @@ -3408,11 +3417,13 @@ static void skylake_update_primary_plane(struct drm_plane *plane, | |||
| 3408 | dst_w--; | 3417 | dst_w--; |
| 3409 | dst_h--; | 3418 | dst_h--; |
| 3410 | 3419 | ||
| 3420 | intel_crtc->dspaddr_offset = surf_addr; | ||
| 3421 | |||
| 3411 | intel_crtc->adjusted_x = src_x; | 3422 | intel_crtc->adjusted_x = src_x; |
| 3412 | intel_crtc->adjusted_y = src_y; | 3423 | intel_crtc->adjusted_y = src_y; |
| 3413 | 3424 | ||
| 3414 | if (wm->dirty_pipes & drm_crtc_mask(&intel_crtc->base)) | 3425 | if (wm->dirty_pipes & drm_crtc_mask(&intel_crtc->base)) |
| 3415 | skl_write_plane_wm(intel_crtc, wm, 0); | 3426 | skl_write_plane_wm(intel_crtc, p_wm, &wm->ddb, 0); |
| 3416 | 3427 | ||
| 3417 | I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); | 3428 | I915_WRITE(PLANE_CTL(pipe, 0), plane_ctl); |
| 3418 | I915_WRITE(PLANE_OFFSET(pipe, 0), (src_y << 16) | src_x); | 3429 | I915_WRITE(PLANE_OFFSET(pipe, 0), (src_y << 16) | src_x); |
| @@ -3446,6 +3457,8 @@ static void skylake_disable_primary_plane(struct drm_plane *primary, | |||
| 3446 | struct drm_device *dev = crtc->dev; | 3457 | struct drm_device *dev = crtc->dev; |
| 3447 | struct drm_i915_private *dev_priv = to_i915(dev); | 3458 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 3448 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 3459 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 3460 | struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); | ||
| 3461 | const struct skl_plane_wm *p_wm = &cstate->wm.skl.optimal.planes[0]; | ||
| 3449 | int pipe = intel_crtc->pipe; | 3462 | int pipe = intel_crtc->pipe; |
| 3450 | 3463 | ||
| 3451 | /* | 3464 | /* |
| @@ -3453,7 +3466,8 @@ static void skylake_disable_primary_plane(struct drm_plane *primary, | |||
| 3453 | * plane's visiblity isn't actually changing neither is its watermarks. | 3466 | * plane's visiblity isn't actually changing neither is its watermarks. |
| 3454 | */ | 3467 | */ |
| 3455 | if (!crtc->primary->state->visible) | 3468 | if (!crtc->primary->state->visible) |
| 3456 | skl_write_plane_wm(intel_crtc, &dev_priv->wm.skl_results, 0); | 3469 | skl_write_plane_wm(intel_crtc, p_wm, |
| 3470 | &dev_priv->wm.skl_results.ddb, 0); | ||
| 3457 | 3471 | ||
| 3458 | I915_WRITE(PLANE_CTL(pipe, 0), 0); | 3472 | I915_WRITE(PLANE_CTL(pipe, 0), 0); |
| 3459 | I915_WRITE(PLANE_SURF(pipe, 0), 0); | 3473 | I915_WRITE(PLANE_SURF(pipe, 0), 0); |
| @@ -3601,8 +3615,6 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) | |||
| 3601 | 3615 | ||
| 3602 | dev_priv->modeset_restore_state = NULL; | 3616 | dev_priv->modeset_restore_state = NULL; |
| 3603 | 3617 | ||
| 3604 | dev_priv->modeset_restore_state = NULL; | ||
| 3605 | |||
| 3606 | /* reset doesn't touch the display */ | 3618 | /* reset doesn't touch the display */ |
| 3607 | if (!gpu_reset_clobbers_display(dev_priv)) { | 3619 | if (!gpu_reset_clobbers_display(dev_priv)) { |
| 3608 | if (!state) { | 3620 | if (!state) { |
| @@ -3629,6 +3641,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) | |||
| 3629 | intel_runtime_pm_disable_interrupts(dev_priv); | 3641 | intel_runtime_pm_disable_interrupts(dev_priv); |
| 3630 | intel_runtime_pm_enable_interrupts(dev_priv); | 3642 | intel_runtime_pm_enable_interrupts(dev_priv); |
| 3631 | 3643 | ||
| 3644 | intel_pps_unlock_regs_wa(dev_priv); | ||
| 3632 | intel_modeset_init_hw(dev); | 3645 | intel_modeset_init_hw(dev); |
| 3633 | 3646 | ||
| 3634 | spin_lock_irq(&dev_priv->irq_lock); | 3647 | spin_lock_irq(&dev_priv->irq_lock); |
| @@ -3713,7 +3726,7 @@ static void intel_update_pipe_config(struct intel_crtc *crtc, | |||
| 3713 | 3726 | ||
| 3714 | if (pipe_config->pch_pfit.enabled) | 3727 | if (pipe_config->pch_pfit.enabled) |
| 3715 | skylake_pfit_enable(crtc); | 3728 | skylake_pfit_enable(crtc); |
| 3716 | } else if (HAS_PCH_SPLIT(dev)) { | 3729 | } else if (HAS_PCH_SPLIT(dev_priv)) { |
| 3717 | if (pipe_config->pch_pfit.enabled) | 3730 | if (pipe_config->pch_pfit.enabled) |
| 3718 | ironlake_pfit_enable(crtc); | 3731 | ironlake_pfit_enable(crtc); |
| 3719 | else if (old_crtc_state->pch_pfit.enabled) | 3732 | else if (old_crtc_state->pch_pfit.enabled) |
| @@ -3733,7 +3746,7 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) | |||
| 3733 | /* enable normal train */ | 3746 | /* enable normal train */ |
| 3734 | reg = FDI_TX_CTL(pipe); | 3747 | reg = FDI_TX_CTL(pipe); |
| 3735 | temp = I915_READ(reg); | 3748 | temp = I915_READ(reg); |
| 3736 | if (IS_IVYBRIDGE(dev)) { | 3749 | if (IS_IVYBRIDGE(dev_priv)) { |
| 3737 | temp &= ~FDI_LINK_TRAIN_NONE_IVB; | 3750 | temp &= ~FDI_LINK_TRAIN_NONE_IVB; |
| 3738 | temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE; | 3751 | temp |= FDI_LINK_TRAIN_NONE_IVB | FDI_TX_ENHANCE_FRAME_ENABLE; |
| 3739 | } else { | 3752 | } else { |
| @@ -3744,7 +3757,7 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) | |||
| 3744 | 3757 | ||
| 3745 | reg = FDI_RX_CTL(pipe); | 3758 | reg = FDI_RX_CTL(pipe); |
| 3746 | temp = I915_READ(reg); | 3759 | temp = I915_READ(reg); |
| 3747 | if (HAS_PCH_CPT(dev)) { | 3760 | if (HAS_PCH_CPT(dev_priv)) { |
| 3748 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | 3761 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; |
| 3749 | temp |= FDI_LINK_TRAIN_NORMAL_CPT; | 3762 | temp |= FDI_LINK_TRAIN_NORMAL_CPT; |
| 3750 | } else { | 3763 | } else { |
| @@ -3758,7 +3771,7 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) | |||
| 3758 | udelay(1000); | 3771 | udelay(1000); |
| 3759 | 3772 | ||
| 3760 | /* IVB wants error correction enabled */ | 3773 | /* IVB wants error correction enabled */ |
| 3761 | if (IS_IVYBRIDGE(dev)) | 3774 | if (IS_IVYBRIDGE(dev_priv)) |
| 3762 | I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE | | 3775 | I915_WRITE(reg, I915_READ(reg) | FDI_FS_ERRC_ENABLE | |
| 3763 | FDI_FE_ERRC_ENABLE); | 3776 | FDI_FE_ERRC_ENABLE); |
| 3764 | } | 3777 | } |
| @@ -3902,7 +3915,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) | |||
| 3902 | 3915 | ||
| 3903 | reg = FDI_RX_CTL(pipe); | 3916 | reg = FDI_RX_CTL(pipe); |
| 3904 | temp = I915_READ(reg); | 3917 | temp = I915_READ(reg); |
| 3905 | if (HAS_PCH_CPT(dev)) { | 3918 | if (HAS_PCH_CPT(dev_priv)) { |
| 3906 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | 3919 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; |
| 3907 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; | 3920 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; |
| 3908 | } else { | 3921 | } else { |
| @@ -3946,7 +3959,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) | |||
| 3946 | temp = I915_READ(reg); | 3959 | temp = I915_READ(reg); |
| 3947 | temp &= ~FDI_LINK_TRAIN_NONE; | 3960 | temp &= ~FDI_LINK_TRAIN_NONE; |
| 3948 | temp |= FDI_LINK_TRAIN_PATTERN_2; | 3961 | temp |= FDI_LINK_TRAIN_PATTERN_2; |
| 3949 | if (IS_GEN6(dev)) { | 3962 | if (IS_GEN6(dev_priv)) { |
| 3950 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; | 3963 | temp &= ~FDI_LINK_TRAIN_VOL_EMP_MASK; |
| 3951 | /* SNB-B */ | 3964 | /* SNB-B */ |
| 3952 | temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; | 3965 | temp |= FDI_LINK_TRAIN_400MV_0DB_SNB_B; |
| @@ -3955,7 +3968,7 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) | |||
| 3955 | 3968 | ||
| 3956 | reg = FDI_RX_CTL(pipe); | 3969 | reg = FDI_RX_CTL(pipe); |
| 3957 | temp = I915_READ(reg); | 3970 | temp = I915_READ(reg); |
| 3958 | if (HAS_PCH_CPT(dev)) { | 3971 | if (HAS_PCH_CPT(dev_priv)) { |
| 3959 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | 3972 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; |
| 3960 | temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; | 3973 | temp |= FDI_LINK_TRAIN_PATTERN_2_CPT; |
| 3961 | } else { | 3974 | } else { |
| @@ -4209,7 +4222,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) | |||
| 4209 | udelay(100); | 4222 | udelay(100); |
| 4210 | 4223 | ||
| 4211 | /* Ironlake workaround, disable clock pointer after downing FDI */ | 4224 | /* Ironlake workaround, disable clock pointer after downing FDI */ |
| 4212 | if (HAS_PCH_IBX(dev)) | 4225 | if (HAS_PCH_IBX(dev_priv)) |
| 4213 | I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR); | 4226 | I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR); |
| 4214 | 4227 | ||
| 4215 | /* still set train pattern 1 */ | 4228 | /* still set train pattern 1 */ |
| @@ -4221,7 +4234,7 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) | |||
| 4221 | 4234 | ||
| 4222 | reg = FDI_RX_CTL(pipe); | 4235 | reg = FDI_RX_CTL(pipe); |
| 4223 | temp = I915_READ(reg); | 4236 | temp = I915_READ(reg); |
| 4224 | if (HAS_PCH_CPT(dev)) { | 4237 | if (HAS_PCH_CPT(dev_priv)) { |
| 4225 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; | 4238 | temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT; |
| 4226 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; | 4239 | temp |= FDI_LINK_TRAIN_PATTERN_1_CPT; |
| 4227 | } else { | 4240 | } else { |
| @@ -4544,7 +4557,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) | |||
| 4544 | 4557 | ||
| 4545 | assert_pch_transcoder_disabled(dev_priv, pipe); | 4558 | assert_pch_transcoder_disabled(dev_priv, pipe); |
| 4546 | 4559 | ||
| 4547 | if (IS_IVYBRIDGE(dev)) | 4560 | if (IS_IVYBRIDGE(dev_priv)) |
| 4548 | ivybridge_update_fdi_bc_bifurcation(intel_crtc); | 4561 | ivybridge_update_fdi_bc_bifurcation(intel_crtc); |
| 4549 | 4562 | ||
| 4550 | /* Write the TU size bits before fdi link training, so that error | 4563 | /* Write the TU size bits before fdi link training, so that error |
| @@ -4557,7 +4570,7 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) | |||
| 4557 | 4570 | ||
| 4558 | /* We need to program the right clock selection before writing the pixel | 4571 | /* We need to program the right clock selection before writing the pixel |
| 4559 | * mutliplier into the DPLL. */ | 4572 | * mutliplier into the DPLL. */ |
| 4560 | if (HAS_PCH_CPT(dev)) { | 4573 | if (HAS_PCH_CPT(dev_priv)) { |
| 4561 | u32 sel; | 4574 | u32 sel; |
| 4562 | 4575 | ||
| 4563 | temp = I915_READ(PCH_DPLL_SEL); | 4576 | temp = I915_READ(PCH_DPLL_SEL); |
| @@ -4587,7 +4600,8 @@ static void ironlake_pch_enable(struct drm_crtc *crtc) | |||
| 4587 | intel_fdi_normal_train(crtc); | 4600 | intel_fdi_normal_train(crtc); |
| 4588 | 4601 | ||
| 4589 | /* For PCH DP, enable TRANS_DP_CTL */ | 4602 | /* For PCH DP, enable TRANS_DP_CTL */ |
| 4590 | if (HAS_PCH_CPT(dev) && intel_crtc_has_dp_encoder(intel_crtc->config)) { | 4603 | if (HAS_PCH_CPT(dev_priv) && |
| 4604 | intel_crtc_has_dp_encoder(intel_crtc->config)) { | ||
| 4591 | const struct drm_display_mode *adjusted_mode = | 4605 | const struct drm_display_mode *adjusted_mode = |
| 4592 | &intel_crtc->config->base.adjusted_mode; | 4606 | &intel_crtc->config->base.adjusted_mode; |
| 4593 | u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5; | 4607 | u32 bpc = (I915_READ(PIPECONF(pipe)) & PIPECONF_BPC_MASK) >> 5; |
| @@ -4857,7 +4871,7 @@ static void ironlake_pfit_enable(struct intel_crtc *crtc) | |||
| 4857 | * as some pre-programmed values are broken, | 4871 | * as some pre-programmed values are broken, |
| 4858 | * e.g. x201. | 4872 | * e.g. x201. |
| 4859 | */ | 4873 | */ |
| 4860 | if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) | 4874 | if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) |
| 4861 | I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 | | 4875 | I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 | |
| 4862 | PF_PIPE_SEL_IVB(pipe)); | 4876 | PF_PIPE_SEL_IVB(pipe)); |
| 4863 | else | 4877 | else |
| @@ -4882,7 +4896,7 @@ void hsw_enable_ips(struct intel_crtc *crtc) | |||
| 4882 | */ | 4896 | */ |
| 4883 | 4897 | ||
| 4884 | assert_plane_enabled(dev_priv, crtc->plane); | 4898 | assert_plane_enabled(dev_priv, crtc->plane); |
| 4885 | if (IS_BROADWELL(dev)) { | 4899 | if (IS_BROADWELL(dev_priv)) { |
| 4886 | mutex_lock(&dev_priv->rps.hw_lock); | 4900 | mutex_lock(&dev_priv->rps.hw_lock); |
| 4887 | WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0xc0000000)); | 4901 | WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0xc0000000)); |
| 4888 | mutex_unlock(&dev_priv->rps.hw_lock); | 4902 | mutex_unlock(&dev_priv->rps.hw_lock); |
| @@ -4914,7 +4928,7 @@ void hsw_disable_ips(struct intel_crtc *crtc) | |||
| 4914 | return; | 4928 | return; |
| 4915 | 4929 | ||
| 4916 | assert_plane_enabled(dev_priv, crtc->plane); | 4930 | assert_plane_enabled(dev_priv, crtc->plane); |
| 4917 | if (IS_BROADWELL(dev)) { | 4931 | if (IS_BROADWELL(dev_priv)) { |
| 4918 | mutex_lock(&dev_priv->rps.hw_lock); | 4932 | mutex_lock(&dev_priv->rps.hw_lock); |
| 4919 | WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); | 4933 | WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); |
| 4920 | mutex_unlock(&dev_priv->rps.hw_lock); | 4934 | mutex_unlock(&dev_priv->rps.hw_lock); |
| @@ -4983,7 +4997,7 @@ intel_post_enable_primary(struct drm_crtc *crtc) | |||
| 4983 | * FIXME: Need to fix the logic to work when we turn off all planes | 4997 | * FIXME: Need to fix the logic to work when we turn off all planes |
| 4984 | * but leave the pipe running. | 4998 | * but leave the pipe running. |
| 4985 | */ | 4999 | */ |
| 4986 | if (IS_GEN2(dev)) | 5000 | if (IS_GEN2(dev_priv)) |
| 4987 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); | 5001 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); |
| 4988 | 5002 | ||
| 4989 | /* Underruns don't always raise interrupts, so check manually. */ | 5003 | /* Underruns don't always raise interrupts, so check manually. */ |
| @@ -5006,7 +5020,7 @@ intel_pre_disable_primary(struct drm_crtc *crtc) | |||
| 5006 | * FIXME: Need to fix the logic to work when we turn off all planes | 5020 | * FIXME: Need to fix the logic to work when we turn off all planes |
| 5007 | * but leave the pipe running. | 5021 | * but leave the pipe running. |
| 5008 | */ | 5022 | */ |
| 5009 | if (IS_GEN2(dev)) | 5023 | if (IS_GEN2(dev_priv)) |
| 5010 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); | 5024 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); |
| 5011 | 5025 | ||
| 5012 | /* | 5026 | /* |
| @@ -5038,7 +5052,7 @@ intel_pre_disable_primary_noatomic(struct drm_crtc *crtc) | |||
| 5038 | * event which is after the vblank start event, so we need to have a | 5052 | * event which is after the vblank start event, so we need to have a |
| 5039 | * wait-for-vblank between disabling the plane and the pipe. | 5053 | * wait-for-vblank between disabling the plane and the pipe. |
| 5040 | */ | 5054 | */ |
| 5041 | if (HAS_GMCH_DISPLAY(dev)) { | 5055 | if (HAS_GMCH_DISPLAY(dev_priv)) { |
| 5042 | intel_set_memory_cxsr(dev_priv, false); | 5056 | intel_set_memory_cxsr(dev_priv, false); |
| 5043 | dev_priv->wm.vlv.cxsr = false; | 5057 | dev_priv->wm.vlv.cxsr = false; |
| 5044 | intel_wait_for_vblank(dev, pipe); | 5058 | intel_wait_for_vblank(dev, pipe); |
| @@ -5103,7 +5117,7 @@ static void intel_pre_plane_update(struct intel_crtc_state *old_crtc_state) | |||
| 5103 | intel_pre_disable_primary(&crtc->base); | 5117 | intel_pre_disable_primary(&crtc->base); |
| 5104 | } | 5118 | } |
| 5105 | 5119 | ||
| 5106 | if (pipe_config->disable_cxsr && HAS_GMCH_DISPLAY(dev)) { | 5120 | if (pipe_config->disable_cxsr && HAS_GMCH_DISPLAY(dev_priv)) { |
| 5107 | crtc->wm.cxsr_allowed = false; | 5121 | crtc->wm.cxsr_allowed = false; |
| 5108 | 5122 | ||
| 5109 | /* | 5123 | /* |
| @@ -5381,7 +5395,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, | |||
| 5381 | 5395 | ||
| 5382 | intel_encoders_enable(crtc, pipe_config, old_state); | 5396 | intel_encoders_enable(crtc, pipe_config, old_state); |
| 5383 | 5397 | ||
| 5384 | if (HAS_PCH_CPT(dev)) | 5398 | if (HAS_PCH_CPT(dev_priv)) |
| 5385 | cpt_verify_modeset(dev, intel_crtc->pipe); | 5399 | cpt_verify_modeset(dev, intel_crtc->pipe); |
| 5386 | 5400 | ||
| 5387 | /* Must wait for vblank to avoid spurious PCH FIFO underruns */ | 5401 | /* Must wait for vblank to avoid spurious PCH FIFO underruns */ |
| @@ -5394,7 +5408,7 @@ static void ironlake_crtc_enable(struct intel_crtc_state *pipe_config, | |||
| 5394 | /* IPS only exists on ULT machines and is tied to pipe A. */ | 5408 | /* IPS only exists on ULT machines and is tied to pipe A. */ |
| 5395 | static bool hsw_crtc_supports_ips(struct intel_crtc *crtc) | 5409 | static bool hsw_crtc_supports_ips(struct intel_crtc *crtc) |
| 5396 | { | 5410 | { |
| 5397 | return HAS_IPS(crtc->base.dev) && crtc->pipe == PIPE_A; | 5411 | return HAS_IPS(to_i915(crtc->base.dev)) && crtc->pipe == PIPE_A; |
| 5398 | } | 5412 | } |
| 5399 | 5413 | ||
| 5400 | static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, | 5414 | static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, |
| @@ -5506,7 +5520,7 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, | |||
| 5506 | /* If we change the relative order between pipe/planes enabling, we need | 5520 | /* If we change the relative order between pipe/planes enabling, we need |
| 5507 | * to change the workaround. */ | 5521 | * to change the workaround. */ |
| 5508 | hsw_workaround_pipe = pipe_config->hsw_workaround_pipe; | 5522 | hsw_workaround_pipe = pipe_config->hsw_workaround_pipe; |
| 5509 | if (IS_HASWELL(dev) && hsw_workaround_pipe != INVALID_PIPE) { | 5523 | if (IS_HASWELL(dev_priv) && hsw_workaround_pipe != INVALID_PIPE) { |
| 5510 | intel_wait_for_vblank(dev, hsw_workaround_pipe); | 5524 | intel_wait_for_vblank(dev, hsw_workaround_pipe); |
| 5511 | intel_wait_for_vblank(dev, hsw_workaround_pipe); | 5525 | intel_wait_for_vblank(dev, hsw_workaround_pipe); |
| 5512 | } | 5526 | } |
| @@ -5563,7 +5577,7 @@ static void ironlake_crtc_disable(struct intel_crtc_state *old_crtc_state, | |||
| 5563 | if (intel_crtc->config->has_pch_encoder) { | 5577 | if (intel_crtc->config->has_pch_encoder) { |
| 5564 | ironlake_disable_pch_transcoder(dev_priv, pipe); | 5578 | ironlake_disable_pch_transcoder(dev_priv, pipe); |
| 5565 | 5579 | ||
| 5566 | if (HAS_PCH_CPT(dev)) { | 5580 | if (HAS_PCH_CPT(dev_priv)) { |
| 5567 | i915_reg_t reg; | 5581 | i915_reg_t reg; |
| 5568 | u32 temp; | 5582 | u32 temp; |
| 5569 | 5583 | ||
| @@ -5697,13 +5711,13 @@ static enum intel_display_power_domain port_to_aux_power_domain(enum port port) | |||
| 5697 | enum intel_display_power_domain | 5711 | enum intel_display_power_domain |
| 5698 | intel_display_port_power_domain(struct intel_encoder *intel_encoder) | 5712 | intel_display_port_power_domain(struct intel_encoder *intel_encoder) |
| 5699 | { | 5713 | { |
| 5700 | struct drm_device *dev = intel_encoder->base.dev; | 5714 | struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); |
| 5701 | struct intel_digital_port *intel_dig_port; | 5715 | struct intel_digital_port *intel_dig_port; |
| 5702 | 5716 | ||
| 5703 | switch (intel_encoder->type) { | 5717 | switch (intel_encoder->type) { |
| 5704 | case INTEL_OUTPUT_UNKNOWN: | 5718 | case INTEL_OUTPUT_UNKNOWN: |
| 5705 | /* Only DDI platforms should ever use this output type */ | 5719 | /* Only DDI platforms should ever use this output type */ |
| 5706 | WARN_ON_ONCE(!HAS_DDI(dev)); | 5720 | WARN_ON_ONCE(!HAS_DDI(dev_priv)); |
| 5707 | case INTEL_OUTPUT_DP: | 5721 | case INTEL_OUTPUT_DP: |
| 5708 | case INTEL_OUTPUT_HDMI: | 5722 | case INTEL_OUTPUT_HDMI: |
| 5709 | case INTEL_OUTPUT_EDP: | 5723 | case INTEL_OUTPUT_EDP: |
| @@ -5724,7 +5738,7 @@ intel_display_port_power_domain(struct intel_encoder *intel_encoder) | |||
| 5724 | enum intel_display_power_domain | 5738 | enum intel_display_power_domain |
| 5725 | intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder) | 5739 | intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder) |
| 5726 | { | 5740 | { |
| 5727 | struct drm_device *dev = intel_encoder->base.dev; | 5741 | struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); |
| 5728 | struct intel_digital_port *intel_dig_port; | 5742 | struct intel_digital_port *intel_dig_port; |
| 5729 | 5743 | ||
| 5730 | switch (intel_encoder->type) { | 5744 | switch (intel_encoder->type) { |
| @@ -5737,7 +5751,7 @@ intel_display_port_aux_power_domain(struct intel_encoder *intel_encoder) | |||
| 5737 | * what's the status of the given connectors, play safe and | 5751 | * what's the status of the given connectors, play safe and |
| 5738 | * run the DP detection too. | 5752 | * run the DP detection too. |
| 5739 | */ | 5753 | */ |
| 5740 | WARN_ON_ONCE(!HAS_DDI(dev)); | 5754 | WARN_ON_ONCE(!HAS_DDI(dev_priv)); |
| 5741 | case INTEL_OUTPUT_DP: | 5755 | case INTEL_OUTPUT_DP: |
| 5742 | case INTEL_OUTPUT_EDP: | 5756 | case INTEL_OUTPUT_EDP: |
| 5743 | intel_dig_port = enc_to_dig_port(&intel_encoder->base); | 5757 | intel_dig_port = enc_to_dig_port(&intel_encoder->base); |
| @@ -5833,7 +5847,7 @@ static void intel_update_max_cdclk(struct drm_device *dev) | |||
| 5833 | { | 5847 | { |
| 5834 | struct drm_i915_private *dev_priv = to_i915(dev); | 5848 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 5835 | 5849 | ||
| 5836 | if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { | 5850 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { |
| 5837 | u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK; | 5851 | u32 limit = I915_READ(SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK; |
| 5838 | int max_cdclk, vco; | 5852 | int max_cdclk, vco; |
| 5839 | 5853 | ||
| @@ -5855,9 +5869,9 @@ static void intel_update_max_cdclk(struct drm_device *dev) | |||
| 5855 | max_cdclk = 308571; | 5869 | max_cdclk = 308571; |
| 5856 | 5870 | ||
| 5857 | dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco); | 5871 | dev_priv->max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco); |
| 5858 | } else if (IS_BROXTON(dev)) { | 5872 | } else if (IS_BROXTON(dev_priv)) { |
| 5859 | dev_priv->max_cdclk_freq = 624000; | 5873 | dev_priv->max_cdclk_freq = 624000; |
| 5860 | } else if (IS_BROADWELL(dev)) { | 5874 | } else if (IS_BROADWELL(dev_priv)) { |
| 5861 | /* | 5875 | /* |
| 5862 | * FIXME with extra cooling we can allow | 5876 | * FIXME with extra cooling we can allow |
| 5863 | * 540 MHz for ULX and 675 Mhz for ULT. | 5877 | * 540 MHz for ULX and 675 Mhz for ULT. |
| @@ -5866,15 +5880,15 @@ static void intel_update_max_cdclk(struct drm_device *dev) | |||
| 5866 | */ | 5880 | */ |
| 5867 | if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) | 5881 | if (I915_READ(FUSE_STRAP) & HSW_CDCLK_LIMIT) |
| 5868 | dev_priv->max_cdclk_freq = 450000; | 5882 | dev_priv->max_cdclk_freq = 450000; |
| 5869 | else if (IS_BDW_ULX(dev)) | 5883 | else if (IS_BDW_ULX(dev_priv)) |
| 5870 | dev_priv->max_cdclk_freq = 450000; | 5884 | dev_priv->max_cdclk_freq = 450000; |
| 5871 | else if (IS_BDW_ULT(dev)) | 5885 | else if (IS_BDW_ULT(dev_priv)) |
| 5872 | dev_priv->max_cdclk_freq = 540000; | 5886 | dev_priv->max_cdclk_freq = 540000; |
| 5873 | else | 5887 | else |
| 5874 | dev_priv->max_cdclk_freq = 675000; | 5888 | dev_priv->max_cdclk_freq = 675000; |
| 5875 | } else if (IS_CHERRYVIEW(dev)) { | 5889 | } else if (IS_CHERRYVIEW(dev_priv)) { |
| 5876 | dev_priv->max_cdclk_freq = 320000; | 5890 | dev_priv->max_cdclk_freq = 320000; |
| 5877 | } else if (IS_VALLEYVIEW(dev)) { | 5891 | } else if (IS_VALLEYVIEW(dev_priv)) { |
| 5878 | dev_priv->max_cdclk_freq = 400000; | 5892 | dev_priv->max_cdclk_freq = 400000; |
| 5879 | } else { | 5893 | } else { |
| 5880 | /* otherwise assume cdclk is fixed */ | 5894 | /* otherwise assume cdclk is fixed */ |
| @@ -6674,7 +6688,7 @@ static void valleyview_modeset_commit_cdclk(struct drm_atomic_state *old_state) | |||
| 6674 | */ | 6688 | */ |
| 6675 | intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A); | 6689 | intel_display_power_get(dev_priv, POWER_DOMAIN_PIPE_A); |
| 6676 | 6690 | ||
| 6677 | if (IS_CHERRYVIEW(dev)) | 6691 | if (IS_CHERRYVIEW(dev_priv)) |
| 6678 | cherryview_set_cdclk(dev, req_cdclk); | 6692 | cherryview_set_cdclk(dev, req_cdclk); |
| 6679 | else | 6693 | else |
| 6680 | valleyview_set_cdclk(dev, req_cdclk); | 6694 | valleyview_set_cdclk(dev, req_cdclk); |
| @@ -6702,7 +6716,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, | |||
| 6702 | intel_set_pipe_timings(intel_crtc); | 6716 | intel_set_pipe_timings(intel_crtc); |
| 6703 | intel_set_pipe_src_size(intel_crtc); | 6717 | intel_set_pipe_src_size(intel_crtc); |
| 6704 | 6718 | ||
| 6705 | if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) { | 6719 | if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) { |
| 6706 | struct drm_i915_private *dev_priv = to_i915(dev); | 6720 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 6707 | 6721 | ||
| 6708 | I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY); | 6722 | I915_WRITE(CHV_BLEND(pipe), CHV_BLEND_LEGACY); |
| @@ -6717,7 +6731,7 @@ static void valleyview_crtc_enable(struct intel_crtc_state *pipe_config, | |||
| 6717 | 6731 | ||
| 6718 | intel_encoders_pre_pll_enable(crtc, pipe_config, old_state); | 6732 | intel_encoders_pre_pll_enable(crtc, pipe_config, old_state); |
| 6719 | 6733 | ||
| 6720 | if (IS_CHERRYVIEW(dev)) { | 6734 | if (IS_CHERRYVIEW(dev_priv)) { |
| 6721 | chv_prepare_pll(intel_crtc, intel_crtc->config); | 6735 | chv_prepare_pll(intel_crtc, intel_crtc->config); |
| 6722 | chv_enable_pll(intel_crtc, intel_crtc->config); | 6736 | chv_enable_pll(intel_crtc, intel_crtc->config); |
| 6723 | } else { | 6737 | } else { |
| @@ -6773,7 +6787,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, | |||
| 6773 | 6787 | ||
| 6774 | intel_crtc->active = true; | 6788 | intel_crtc->active = true; |
| 6775 | 6789 | ||
| 6776 | if (!IS_GEN2(dev)) | 6790 | if (!IS_GEN2(dev_priv)) |
| 6777 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); | 6791 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); |
| 6778 | 6792 | ||
| 6779 | intel_encoders_pre_enable(crtc, pipe_config, old_state); | 6793 | intel_encoders_pre_enable(crtc, pipe_config, old_state); |
| @@ -6821,7 +6835,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, | |||
| 6821 | * On gen2 planes are double buffered but the pipe isn't, so we must | 6835 | * On gen2 planes are double buffered but the pipe isn't, so we must |
| 6822 | * wait for planes to fully turn off before disabling the pipe. | 6836 | * wait for planes to fully turn off before disabling the pipe. |
| 6823 | */ | 6837 | */ |
| 6824 | if (IS_GEN2(dev)) | 6838 | if (IS_GEN2(dev_priv)) |
| 6825 | intel_wait_for_vblank(dev, pipe); | 6839 | intel_wait_for_vblank(dev, pipe); |
| 6826 | 6840 | ||
| 6827 | intel_encoders_disable(crtc, old_crtc_state, old_state); | 6841 | intel_encoders_disable(crtc, old_crtc_state, old_state); |
| @@ -6836,9 +6850,9 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, | |||
| 6836 | intel_encoders_post_disable(crtc, old_crtc_state, old_state); | 6850 | intel_encoders_post_disable(crtc, old_crtc_state, old_state); |
| 6837 | 6851 | ||
| 6838 | if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) { | 6852 | if (!intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_DSI)) { |
| 6839 | if (IS_CHERRYVIEW(dev)) | 6853 | if (IS_CHERRYVIEW(dev_priv)) |
| 6840 | chv_disable_pll(dev_priv, pipe); | 6854 | chv_disable_pll(dev_priv, pipe); |
| 6841 | else if (IS_VALLEYVIEW(dev)) | 6855 | else if (IS_VALLEYVIEW(dev_priv)) |
| 6842 | vlv_disable_pll(dev_priv, pipe); | 6856 | vlv_disable_pll(dev_priv, pipe); |
| 6843 | else | 6857 | else |
| 6844 | i9xx_disable_pll(intel_crtc); | 6858 | i9xx_disable_pll(intel_crtc); |
| @@ -6846,7 +6860,7 @@ static void i9xx_crtc_disable(struct intel_crtc_state *old_crtc_state, | |||
| 6846 | 6860 | ||
| 6847 | intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state); | 6861 | intel_encoders_post_pll_disable(crtc, old_crtc_state, old_state); |
| 6848 | 6862 | ||
| 6849 | if (!IS_GEN2(dev)) | 6863 | if (!IS_GEN2(dev_priv)) |
| 6850 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); | 6864 | intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); |
| 6851 | } | 6865 | } |
| 6852 | 6866 | ||
| @@ -7026,6 +7040,7 @@ static int pipe_required_fdi_lanes(struct intel_crtc_state *crtc_state) | |||
| 7026 | static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, | 7040 | static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, |
| 7027 | struct intel_crtc_state *pipe_config) | 7041 | struct intel_crtc_state *pipe_config) |
| 7028 | { | 7042 | { |
| 7043 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 7029 | struct drm_atomic_state *state = pipe_config->base.state; | 7044 | struct drm_atomic_state *state = pipe_config->base.state; |
| 7030 | struct intel_crtc *other_crtc; | 7045 | struct intel_crtc *other_crtc; |
| 7031 | struct intel_crtc_state *other_crtc_state; | 7046 | struct intel_crtc_state *other_crtc_state; |
| @@ -7038,7 +7053,7 @@ static int ironlake_check_fdi_lanes(struct drm_device *dev, enum pipe pipe, | |||
| 7038 | return -EINVAL; | 7053 | return -EINVAL; |
| 7039 | } | 7054 | } |
| 7040 | 7055 | ||
| 7041 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { | 7056 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { |
| 7042 | if (pipe_config->fdi_lanes > 2) { | 7057 | if (pipe_config->fdi_lanes > 2) { |
| 7043 | DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n", | 7058 | DRM_DEBUG_KMS("only 2 lanes on haswell, required: %i lanes\n", |
| 7044 | pipe_config->fdi_lanes); | 7059 | pipe_config->fdi_lanes); |
| @@ -7223,11 +7238,11 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, | |||
| 7223 | /* Cantiga+ cannot handle modes with a hsync front porch of 0. | 7238 | /* Cantiga+ cannot handle modes with a hsync front porch of 0. |
| 7224 | * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw. | 7239 | * WaPruneModeWithIncorrectHsyncOffset:ctg,elk,ilk,snb,ivb,vlv,hsw. |
| 7225 | */ | 7240 | */ |
| 7226 | if ((INTEL_INFO(dev)->gen > 4 || IS_G4X(dev)) && | 7241 | if ((INTEL_GEN(dev_priv) > 4 || IS_G4X(dev_priv)) && |
| 7227 | adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay) | 7242 | adjusted_mode->crtc_hsync_start == adjusted_mode->crtc_hdisplay) |
| 7228 | return -EINVAL; | 7243 | return -EINVAL; |
| 7229 | 7244 | ||
| 7230 | if (HAS_IPS(dev)) | 7245 | if (HAS_IPS(dev_priv)) |
| 7231 | hsw_compute_ips_config(crtc, pipe_config); | 7246 | hsw_compute_ips_config(crtc, pipe_config); |
| 7232 | 7247 | ||
| 7233 | if (pipe_config->has_pch_encoder) | 7248 | if (pipe_config->has_pch_encoder) |
| @@ -7365,7 +7380,7 @@ static int haswell_get_display_clock_speed(struct drm_device *dev) | |||
| 7365 | return 450000; | 7380 | return 450000; |
| 7366 | else if (freq == LCPLL_CLK_FREQ_450) | 7381 | else if (freq == LCPLL_CLK_FREQ_450) |
| 7367 | return 450000; | 7382 | return 450000; |
| 7368 | else if (IS_HSW_ULT(dev)) | 7383 | else if (IS_HSW_ULT(dev_priv)) |
| 7369 | return 337500; | 7384 | return 337500; |
| 7370 | else | 7385 | else |
| 7371 | return 540000; | 7386 | return 540000; |
| @@ -7535,9 +7550,9 @@ static unsigned int intel_hpll_vco(struct drm_device *dev) | |||
| 7535 | uint8_t tmp = 0; | 7550 | uint8_t tmp = 0; |
| 7536 | 7551 | ||
| 7537 | /* FIXME other chipsets? */ | 7552 | /* FIXME other chipsets? */ |
| 7538 | if (IS_GM45(dev)) | 7553 | if (IS_GM45(dev_priv)) |
| 7539 | vco_table = ctg_vco; | 7554 | vco_table = ctg_vco; |
| 7540 | else if (IS_G4X(dev)) | 7555 | else if (IS_G4X(dev_priv)) |
| 7541 | vco_table = elk_vco; | 7556 | vco_table = elk_vco; |
| 7542 | else if (IS_CRESTLINE(dev)) | 7557 | else if (IS_CRESTLINE(dev)) |
| 7543 | vco_table = cl_vco; | 7558 | vco_table = cl_vco; |
| @@ -7802,8 +7817,8 @@ static void intel_cpu_transcoder_set_m_n(struct intel_crtc *crtc, | |||
| 7802 | * for gen < 8) and if DRRS is supported (to make sure the | 7817 | * for gen < 8) and if DRRS is supported (to make sure the |
| 7803 | * registers are not unnecessarily accessed). | 7818 | * registers are not unnecessarily accessed). |
| 7804 | */ | 7819 | */ |
| 7805 | if (m2_n2 && (IS_CHERRYVIEW(dev) || INTEL_INFO(dev)->gen < 8) && | 7820 | if (m2_n2 && (IS_CHERRYVIEW(dev_priv) || |
| 7806 | crtc->config->has_drrs) { | 7821 | INTEL_GEN(dev_priv) < 8) && crtc->config->has_drrs) { |
| 7807 | I915_WRITE(PIPE_DATA_M2(transcoder), | 7822 | I915_WRITE(PIPE_DATA_M2(transcoder), |
| 7808 | TU_SIZE(m2_n2->tu) | m2_n2->gmch_m); | 7823 | TU_SIZE(m2_n2->tu) | m2_n2->gmch_m); |
| 7809 | I915_WRITE(PIPE_DATA_N2(transcoder), m2_n2->gmch_n); | 7824 | I915_WRITE(PIPE_DATA_N2(transcoder), m2_n2->gmch_n); |
| @@ -8105,7 +8120,7 @@ int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, | |||
| 8105 | pipe_config->pixel_multiplier = 1; | 8120 | pipe_config->pixel_multiplier = 1; |
| 8106 | pipe_config->dpll = *dpll; | 8121 | pipe_config->dpll = *dpll; |
| 8107 | 8122 | ||
| 8108 | if (IS_CHERRYVIEW(dev)) { | 8123 | if (IS_CHERRYVIEW(to_i915(dev))) { |
| 8109 | chv_compute_dpll(crtc, pipe_config); | 8124 | chv_compute_dpll(crtc, pipe_config); |
| 8110 | chv_prepare_pll(crtc, pipe_config); | 8125 | chv_prepare_pll(crtc, pipe_config); |
| 8111 | chv_enable_pll(crtc, pipe_config); | 8126 | chv_enable_pll(crtc, pipe_config); |
| @@ -8130,7 +8145,7 @@ int vlv_force_pll_on(struct drm_device *dev, enum pipe pipe, | |||
| 8130 | */ | 8145 | */ |
| 8131 | void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe) | 8146 | void vlv_force_pll_off(struct drm_device *dev, enum pipe pipe) |
| 8132 | { | 8147 | { |
| 8133 | if (IS_CHERRYVIEW(dev)) | 8148 | if (IS_CHERRYVIEW(to_i915(dev))) |
| 8134 | chv_disable_pll(to_i915(dev), pipe); | 8149 | chv_disable_pll(to_i915(dev), pipe); |
| 8135 | else | 8150 | else |
| 8136 | vlv_disable_pll(to_i915(dev), pipe); | 8151 | vlv_disable_pll(to_i915(dev), pipe); |
| @@ -8154,7 +8169,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc, | |||
| 8154 | else | 8169 | else |
| 8155 | dpll |= DPLLB_MODE_DAC_SERIAL; | 8170 | dpll |= DPLLB_MODE_DAC_SERIAL; |
| 8156 | 8171 | ||
| 8157 | if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { | 8172 | if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) || IS_G33(dev_priv)) { |
| 8158 | dpll |= (crtc_state->pixel_multiplier - 1) | 8173 | dpll |= (crtc_state->pixel_multiplier - 1) |
| 8159 | << SDVO_MULTIPLIER_SHIFT_HIRES; | 8174 | << SDVO_MULTIPLIER_SHIFT_HIRES; |
| 8160 | } | 8175 | } |
| @@ -8171,7 +8186,7 @@ static void i9xx_compute_dpll(struct intel_crtc *crtc, | |||
| 8171 | dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; | 8186 | dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW; |
| 8172 | else { | 8187 | else { |
| 8173 | dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; | 8188 | dpll |= (1 << (clock->p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; |
| 8174 | if (IS_G4X(dev) && reduced_clock) | 8189 | if (IS_G4X(dev_priv) && reduced_clock) |
| 8175 | dpll |= (1 << (reduced_clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; | 8190 | dpll |= (1 << (reduced_clock->p1 - 1)) << DPLL_FPA1_P1_POST_DIV_SHIFT; |
| 8176 | } | 8191 | } |
| 8177 | switch (clock->p2) { | 8192 | switch (clock->p2) { |
| @@ -8233,7 +8248,8 @@ static void i8xx_compute_dpll(struct intel_crtc *crtc, | |||
| 8233 | dpll |= PLL_P2_DIVIDE_BY_4; | 8248 | dpll |= PLL_P2_DIVIDE_BY_4; |
| 8234 | } | 8249 | } |
| 8235 | 8250 | ||
| 8236 | if (!IS_I830(dev) && intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO)) | 8251 | if (!IS_I830(dev_priv) && |
| 8252 | intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DVO)) | ||
| 8237 | dpll |= DPLL_DVO_2X_MODE; | 8253 | dpll |= DPLL_DVO_2X_MODE; |
| 8238 | 8254 | ||
| 8239 | if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && | 8255 | if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && |
| @@ -8302,7 +8318,7 @@ static void intel_set_pipe_timings(struct intel_crtc *intel_crtc) | |||
| 8302 | * programmed with the VTOTAL_EDP value. Same for VTOTAL_C. This is | 8318 | * programmed with the VTOTAL_EDP value. Same for VTOTAL_C. This is |
| 8303 | * documented on the DDI_FUNC_CTL register description, EDP Input Select | 8319 | * documented on the DDI_FUNC_CTL register description, EDP Input Select |
| 8304 | * bits. */ | 8320 | * bits. */ |
| 8305 | if (IS_HASWELL(dev) && cpu_transcoder == TRANSCODER_EDP && | 8321 | if (IS_HASWELL(dev_priv) && cpu_transcoder == TRANSCODER_EDP && |
| 8306 | (pipe == PIPE_B || pipe == PIPE_C)) | 8322 | (pipe == PIPE_B || pipe == PIPE_C)) |
| 8307 | I915_WRITE(VTOTAL(pipe), I915_READ(VTOTAL(cpu_transcoder))); | 8323 | I915_WRITE(VTOTAL(pipe), I915_READ(VTOTAL(cpu_transcoder))); |
| 8308 | 8324 | ||
| @@ -8412,7 +8428,8 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) | |||
| 8412 | pipeconf |= PIPECONF_DOUBLE_WIDE; | 8428 | pipeconf |= PIPECONF_DOUBLE_WIDE; |
| 8413 | 8429 | ||
| 8414 | /* only g4x and later have fancy bpc/dither controls */ | 8430 | /* only g4x and later have fancy bpc/dither controls */ |
| 8415 | if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 8431 | if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || |
| 8432 | IS_CHERRYVIEW(dev_priv)) { | ||
| 8416 | /* Bspec claims that we can't use dithering for 30bpp pipes. */ | 8433 | /* Bspec claims that we can't use dithering for 30bpp pipes. */ |
| 8417 | if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30) | 8434 | if (intel_crtc->config->dither && intel_crtc->config->pipe_bpp != 30) |
| 8418 | pipeconf |= PIPECONF_DITHER_EN | | 8435 | pipeconf |= PIPECONF_DITHER_EN | |
| @@ -8452,7 +8469,7 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) | |||
| 8452 | } else | 8469 | } else |
| 8453 | pipeconf |= PIPECONF_PROGRESSIVE; | 8470 | pipeconf |= PIPECONF_PROGRESSIVE; |
| 8454 | 8471 | ||
| 8455 | if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && | 8472 | if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && |
| 8456 | intel_crtc->config->limited_color_range) | 8473 | intel_crtc->config->limited_color_range) |
| 8457 | pipeconf |= PIPECONF_COLOR_RANGE_SELECT; | 8474 | pipeconf |= PIPECONF_COLOR_RANGE_SELECT; |
| 8458 | 8475 | ||
| @@ -8656,7 +8673,8 @@ static void i9xx_get_pfit_config(struct intel_crtc *crtc, | |||
| 8656 | struct drm_i915_private *dev_priv = to_i915(dev); | 8673 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 8657 | uint32_t tmp; | 8674 | uint32_t tmp; |
| 8658 | 8675 | ||
| 8659 | if (INTEL_INFO(dev)->gen <= 3 && (IS_I830(dev) || !IS_MOBILE(dev))) | 8676 | if (INTEL_GEN(dev_priv) <= 3 && |
| 8677 | (IS_I830(dev_priv) || !IS_MOBILE(dev_priv))) | ||
| 8660 | return; | 8678 | return; |
| 8661 | 8679 | ||
| 8662 | tmp = I915_READ(PFIT_CONTROL); | 8680 | tmp = I915_READ(PFIT_CONTROL); |
| @@ -8828,7 +8846,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, | |||
| 8828 | if (!(tmp & PIPECONF_ENABLE)) | 8846 | if (!(tmp & PIPECONF_ENABLE)) |
| 8829 | goto out; | 8847 | goto out; |
| 8830 | 8848 | ||
| 8831 | if (IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 8849 | if (IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || |
| 8850 | IS_CHERRYVIEW(dev_priv)) { | ||
| 8832 | switch (tmp & PIPECONF_BPC_MASK) { | 8851 | switch (tmp & PIPECONF_BPC_MASK) { |
| 8833 | case PIPECONF_6BPC: | 8852 | case PIPECONF_6BPC: |
| 8834 | pipe_config->pipe_bpp = 18; | 8853 | pipe_config->pipe_bpp = 18; |
| @@ -8844,7 +8863,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, | |||
| 8844 | } | 8863 | } |
| 8845 | } | 8864 | } |
| 8846 | 8865 | ||
| 8847 | if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && | 8866 | if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && |
| 8848 | (tmp & PIPECONF_COLOR_RANGE_SELECT)) | 8867 | (tmp & PIPECONF_COLOR_RANGE_SELECT)) |
| 8849 | pipe_config->limited_color_range = true; | 8868 | pipe_config->limited_color_range = true; |
| 8850 | 8869 | ||
| @@ -8858,7 +8877,7 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, | |||
| 8858 | 8877 | ||
| 8859 | if (INTEL_INFO(dev)->gen >= 4) { | 8878 | if (INTEL_INFO(dev)->gen >= 4) { |
| 8860 | /* No way to read it out on pipes B and C */ | 8879 | /* No way to read it out on pipes B and C */ |
| 8861 | if (IS_CHERRYVIEW(dev) && crtc->pipe != PIPE_A) | 8880 | if (IS_CHERRYVIEW(dev_priv) && crtc->pipe != PIPE_A) |
| 8862 | tmp = dev_priv->chv_dpll_md[crtc->pipe]; | 8881 | tmp = dev_priv->chv_dpll_md[crtc->pipe]; |
| 8863 | else | 8882 | else |
| 8864 | tmp = I915_READ(DPLL_MD(crtc->pipe)); | 8883 | tmp = I915_READ(DPLL_MD(crtc->pipe)); |
| @@ -8866,7 +8885,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, | |||
| 8866 | ((tmp & DPLL_MD_UDI_MULTIPLIER_MASK) | 8885 | ((tmp & DPLL_MD_UDI_MULTIPLIER_MASK) |
| 8867 | >> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1; | 8886 | >> DPLL_MD_UDI_MULTIPLIER_SHIFT) + 1; |
| 8868 | pipe_config->dpll_hw_state.dpll_md = tmp; | 8887 | pipe_config->dpll_hw_state.dpll_md = tmp; |
| 8869 | } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { | 8888 | } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) || |
| 8889 | IS_G33(dev_priv)) { | ||
| 8870 | tmp = I915_READ(DPLL(crtc->pipe)); | 8890 | tmp = I915_READ(DPLL(crtc->pipe)); |
| 8871 | pipe_config->pixel_multiplier = | 8891 | pipe_config->pixel_multiplier = |
| 8872 | ((tmp & SDVO_MULTIPLIER_MASK) | 8892 | ((tmp & SDVO_MULTIPLIER_MASK) |
| @@ -8878,13 +8898,13 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, | |||
| 8878 | pipe_config->pixel_multiplier = 1; | 8898 | pipe_config->pixel_multiplier = 1; |
| 8879 | } | 8899 | } |
| 8880 | pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe)); | 8900 | pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(crtc->pipe)); |
| 8881 | if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { | 8901 | if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) { |
| 8882 | /* | 8902 | /* |
| 8883 | * DPLL_DVO_2X_MODE must be enabled for both DPLLs | 8903 | * DPLL_DVO_2X_MODE must be enabled for both DPLLs |
| 8884 | * on 830. Filter it out here so that we don't | 8904 | * on 830. Filter it out here so that we don't |
| 8885 | * report errors due to that. | 8905 | * report errors due to that. |
| 8886 | */ | 8906 | */ |
| 8887 | if (IS_I830(dev)) | 8907 | if (IS_I830(dev_priv)) |
| 8888 | pipe_config->dpll_hw_state.dpll &= ~DPLL_DVO_2X_MODE; | 8908 | pipe_config->dpll_hw_state.dpll &= ~DPLL_DVO_2X_MODE; |
| 8889 | 8909 | ||
| 8890 | pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe)); | 8910 | pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(crtc->pipe)); |
| @@ -8896,9 +8916,9 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, | |||
| 8896 | DPLL_PORTB_READY_MASK); | 8916 | DPLL_PORTB_READY_MASK); |
| 8897 | } | 8917 | } |
| 8898 | 8918 | ||
| 8899 | if (IS_CHERRYVIEW(dev)) | 8919 | if (IS_CHERRYVIEW(dev_priv)) |
| 8900 | chv_crtc_clock_get(crtc, pipe_config); | 8920 | chv_crtc_clock_get(crtc, pipe_config); |
| 8901 | else if (IS_VALLEYVIEW(dev)) | 8921 | else if (IS_VALLEYVIEW(dev_priv)) |
| 8902 | vlv_crtc_clock_get(crtc, pipe_config); | 8922 | vlv_crtc_clock_get(crtc, pipe_config); |
| 8903 | else | 8923 | else |
| 8904 | i9xx_crtc_clock_get(crtc, pipe_config); | 8924 | i9xx_crtc_clock_get(crtc, pipe_config); |
| @@ -8949,7 +8969,7 @@ static void ironlake_init_pch_refclk(struct drm_device *dev) | |||
| 8949 | } | 8969 | } |
| 8950 | } | 8970 | } |
| 8951 | 8971 | ||
| 8952 | if (HAS_PCH_IBX(dev)) { | 8972 | if (HAS_PCH_IBX(dev_priv)) { |
| 8953 | has_ck505 = dev_priv->vbt.display_clock_mode; | 8973 | has_ck505 = dev_priv->vbt.display_clock_mode; |
| 8954 | can_ssc = has_ck505; | 8974 | can_ssc = has_ck505; |
| 8955 | } else { | 8975 | } else { |
| @@ -9197,7 +9217,8 @@ static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread, | |||
| 9197 | 9217 | ||
| 9198 | if (WARN(with_fdi && !with_spread, "FDI requires downspread\n")) | 9218 | if (WARN(with_fdi && !with_spread, "FDI requires downspread\n")) |
| 9199 | with_spread = true; | 9219 | with_spread = true; |
| 9200 | if (WARN(HAS_PCH_LPT_LP(dev) && with_fdi, "LP PCH doesn't have FDI\n")) | 9220 | if (WARN(HAS_PCH_LPT_LP(dev_priv) && |
| 9221 | with_fdi, "LP PCH doesn't have FDI\n")) | ||
| 9201 | with_fdi = false; | 9222 | with_fdi = false; |
| 9202 | 9223 | ||
| 9203 | mutex_lock(&dev_priv->sb_lock); | 9224 | mutex_lock(&dev_priv->sb_lock); |
| @@ -9220,7 +9241,7 @@ static void lpt_enable_clkout_dp(struct drm_device *dev, bool with_spread, | |||
| 9220 | } | 9241 | } |
| 9221 | } | 9242 | } |
| 9222 | 9243 | ||
| 9223 | reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0; | 9244 | reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0; |
| 9224 | tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); | 9245 | tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); |
| 9225 | tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE; | 9246 | tmp |= SBI_GEN0_CFG_BUFFENABLE_DISABLE; |
| 9226 | intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); | 9247 | intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); |
| @@ -9236,7 +9257,7 @@ static void lpt_disable_clkout_dp(struct drm_device *dev) | |||
| 9236 | 9257 | ||
| 9237 | mutex_lock(&dev_priv->sb_lock); | 9258 | mutex_lock(&dev_priv->sb_lock); |
| 9238 | 9259 | ||
| 9239 | reg = HAS_PCH_LPT_LP(dev) ? SBI_GEN0 : SBI_DBUFF0; | 9260 | reg = HAS_PCH_LPT_LP(dev_priv) ? SBI_GEN0 : SBI_DBUFF0; |
| 9240 | tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); | 9261 | tmp = intel_sbi_read(dev_priv, reg, SBI_ICLK); |
| 9241 | tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE; | 9262 | tmp &= ~SBI_GEN0_CFG_BUFFENABLE_DISABLE; |
| 9242 | intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); | 9263 | intel_sbi_write(dev_priv, reg, tmp, SBI_ICLK); |
| @@ -9344,9 +9365,11 @@ static void lpt_init_pch_refclk(struct drm_device *dev) | |||
| 9344 | */ | 9365 | */ |
| 9345 | void intel_init_pch_refclk(struct drm_device *dev) | 9366 | void intel_init_pch_refclk(struct drm_device *dev) |
| 9346 | { | 9367 | { |
| 9347 | if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) | 9368 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 9369 | |||
| 9370 | if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) | ||
| 9348 | ironlake_init_pch_refclk(dev); | 9371 | ironlake_init_pch_refclk(dev); |
| 9349 | else if (HAS_PCH_LPT(dev)) | 9372 | else if (HAS_PCH_LPT(dev_priv)) |
| 9350 | lpt_init_pch_refclk(dev); | 9373 | lpt_init_pch_refclk(dev); |
| 9351 | } | 9374 | } |
| 9352 | 9375 | ||
| @@ -9475,7 +9498,7 @@ static void ironlake_compute_dpll(struct intel_crtc *intel_crtc, | |||
| 9475 | if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) { | 9498 | if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS)) { |
| 9476 | if ((intel_panel_use_ssc(dev_priv) && | 9499 | if ((intel_panel_use_ssc(dev_priv) && |
| 9477 | dev_priv->vbt.lvds_ssc_freq == 100000) || | 9500 | dev_priv->vbt.lvds_ssc_freq == 100000) || |
| 9478 | (HAS_PCH_IBX(dev) && intel_is_dual_link_lvds(dev))) | 9501 | (HAS_PCH_IBX(dev_priv) && intel_is_dual_link_lvds(dev))) |
| 9479 | factor = 25; | 9502 | factor = 25; |
| 9480 | } else if (crtc_state->sdvo_tv_clock) | 9503 | } else if (crtc_state->sdvo_tv_clock) |
| 9481 | factor = 20; | 9504 | factor = 20; |
| @@ -9511,6 +9534,24 @@ static void ironlake_compute_dpll(struct intel_crtc *intel_crtc, | |||
| 9511 | if (intel_crtc_has_dp_encoder(crtc_state)) | 9534 | if (intel_crtc_has_dp_encoder(crtc_state)) |
| 9512 | dpll |= DPLL_SDVO_HIGH_SPEED; | 9535 | dpll |= DPLL_SDVO_HIGH_SPEED; |
| 9513 | 9536 | ||
| 9537 | /* | ||
| 9538 | * The high speed IO clock is only really required for | ||
| 9539 | * SDVO/HDMI/DP, but we also enable it for CRT to make it | ||
| 9540 | * possible to share the DPLL between CRT and HDMI. Enabling | ||
| 9541 | * the clock needlessly does no real harm, except use up a | ||
| 9542 | * bit of power potentially. | ||
| 9543 | * | ||
| 9544 | * We'll limit this to IVB with 3 pipes, since it has only two | ||
| 9545 | * DPLLs and so DPLL sharing is the only way to get three pipes | ||
| 9546 | * driving PCH ports at the same time. On SNB we could do this, | ||
| 9547 | * and potentially avoid enabling the second DPLL, but it's not | ||
| 9548 | * clear if it''s a win or loss power wise. No point in doing | ||
| 9549 | * this on ILK at all since it has a fixed DPLL<->pipe mapping. | ||
| 9550 | */ | ||
| 9551 | if (INTEL_INFO(dev_priv)->num_pipes == 3 && | ||
| 9552 | intel_crtc_has_type(crtc_state, INTEL_OUTPUT_ANALOG)) | ||
| 9553 | dpll |= DPLL_SDVO_HIGH_SPEED; | ||
| 9554 | |||
| 9514 | /* compute bitmask from p1 value */ | 9555 | /* compute bitmask from p1 value */ |
| 9515 | dpll |= (1 << (crtc_state->dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; | 9556 | dpll |= (1 << (crtc_state->dpll.p1 - 1)) << DPLL_FPA01_P1_POST_DIV_SHIFT; |
| 9516 | /* also FPA1 */ | 9557 | /* also FPA1 */ |
| @@ -9817,7 +9858,7 @@ static void ironlake_get_pfit_config(struct intel_crtc *crtc, | |||
| 9817 | /* We currently do not free assignements of panel fitters on | 9858 | /* We currently do not free assignements of panel fitters on |
| 9818 | * ivb/hsw (since we don't use the higher upscaling modes which | 9859 | * ivb/hsw (since we don't use the higher upscaling modes which |
| 9819 | * differentiates them) so just WARN about this case for now. */ | 9860 | * differentiates them) so just WARN about this case for now. */ |
| 9820 | if (IS_GEN7(dev)) { | 9861 | if (IS_GEN7(dev_priv)) { |
| 9821 | WARN_ON((tmp & PF_PIPE_SEL_MASK_IVB) != | 9862 | WARN_ON((tmp & PF_PIPE_SEL_MASK_IVB) != |
| 9822 | PF_PIPE_SEL_IVB(crtc->pipe)); | 9863 | PF_PIPE_SEL_IVB(crtc->pipe)); |
| 9823 | } | 9864 | } |
| @@ -9862,7 +9903,7 @@ ironlake_get_initial_plane_config(struct intel_crtc *crtc, | |||
| 9862 | fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8; | 9903 | fb->bits_per_pixel = drm_format_plane_cpp(fourcc, 0) * 8; |
| 9863 | 9904 | ||
| 9864 | base = I915_READ(DSPSURF(pipe)) & 0xfffff000; | 9905 | base = I915_READ(DSPSURF(pipe)) & 0xfffff000; |
| 9865 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { | 9906 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { |
| 9866 | offset = I915_READ(DSPOFFSET(pipe)); | 9907 | offset = I915_READ(DSPOFFSET(pipe)); |
| 9867 | } else { | 9908 | } else { |
| 9868 | if (plane_config->tiling) | 9909 | if (plane_config->tiling) |
| @@ -10006,7 +10047,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) | |||
| 10006 | I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n"); | 10047 | I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n"); |
| 10007 | I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE, | 10048 | I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE, |
| 10008 | "CPU PWM1 enabled\n"); | 10049 | "CPU PWM1 enabled\n"); |
| 10009 | if (IS_HASWELL(dev)) | 10050 | if (IS_HASWELL(dev_priv)) |
| 10010 | I915_STATE_WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE, | 10051 | I915_STATE_WARN(I915_READ(HSW_BLC_PWM2_CTL) & BLM_PWM_ENABLE, |
| 10011 | "CPU PWM2 enabled\n"); | 10052 | "CPU PWM2 enabled\n"); |
| 10012 | I915_STATE_WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE, | 10053 | I915_STATE_WARN(I915_READ(BLC_PWM_PCH_CTL1) & BLM_PCH_PWM_ENABLE, |
| @@ -10026,9 +10067,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv) | |||
| 10026 | 10067 | ||
| 10027 | static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv) | 10068 | static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv) |
| 10028 | { | 10069 | { |
| 10029 | struct drm_device *dev = &dev_priv->drm; | 10070 | if (IS_HASWELL(dev_priv)) |
| 10030 | |||
| 10031 | if (IS_HASWELL(dev)) | ||
| 10032 | return I915_READ(D_COMP_HSW); | 10071 | return I915_READ(D_COMP_HSW); |
| 10033 | else | 10072 | else |
| 10034 | return I915_READ(D_COMP_BDW); | 10073 | return I915_READ(D_COMP_BDW); |
| @@ -10036,9 +10075,7 @@ static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv) | |||
| 10036 | 10075 | ||
| 10037 | static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val) | 10076 | static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val) |
| 10038 | { | 10077 | { |
| 10039 | struct drm_device *dev = &dev_priv->drm; | 10078 | if (IS_HASWELL(dev_priv)) { |
| 10040 | |||
| 10041 | if (IS_HASWELL(dev)) { | ||
| 10042 | mutex_lock(&dev_priv->rps.hw_lock); | 10079 | mutex_lock(&dev_priv->rps.hw_lock); |
| 10043 | if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, | 10080 | if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, |
| 10044 | val)) | 10081 | val)) |
| @@ -10186,7 +10223,7 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv) | |||
| 10186 | 10223 | ||
| 10187 | DRM_DEBUG_KMS("Enabling package C8+\n"); | 10224 | DRM_DEBUG_KMS("Enabling package C8+\n"); |
| 10188 | 10225 | ||
| 10189 | if (HAS_PCH_LPT_LP(dev)) { | 10226 | if (HAS_PCH_LPT_LP(dev_priv)) { |
| 10190 | val = I915_READ(SOUTH_DSPCLK_GATE_D); | 10227 | val = I915_READ(SOUTH_DSPCLK_GATE_D); |
| 10191 | val &= ~PCH_LP_PARTITION_LEVEL_DISABLE; | 10228 | val &= ~PCH_LP_PARTITION_LEVEL_DISABLE; |
| 10192 | I915_WRITE(SOUTH_DSPCLK_GATE_D, val); | 10229 | I915_WRITE(SOUTH_DSPCLK_GATE_D, val); |
| @@ -10206,7 +10243,7 @@ void hsw_disable_pc8(struct drm_i915_private *dev_priv) | |||
| 10206 | hsw_restore_lcpll(dev_priv); | 10243 | hsw_restore_lcpll(dev_priv); |
| 10207 | lpt_init_pch_refclk(dev); | 10244 | lpt_init_pch_refclk(dev); |
| 10208 | 10245 | ||
| 10209 | if (HAS_PCH_LPT_LP(dev)) { | 10246 | if (HAS_PCH_LPT_LP(dev_priv)) { |
| 10210 | val = I915_READ(SOUTH_DSPCLK_GATE_D); | 10247 | val = I915_READ(SOUTH_DSPCLK_GATE_D); |
| 10211 | val |= PCH_LP_PARTITION_LEVEL_DISABLE; | 10248 | val |= PCH_LP_PARTITION_LEVEL_DISABLE; |
| 10212 | I915_WRITE(SOUTH_DSPCLK_GATE_D, val); | 10249 | I915_WRITE(SOUTH_DSPCLK_GATE_D, val); |
| @@ -10630,9 +10667,9 @@ static void haswell_get_ddi_port_state(struct intel_crtc *crtc, | |||
| 10630 | 10667 | ||
| 10631 | port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT; | 10668 | port = (tmp & TRANS_DDI_PORT_MASK) >> TRANS_DDI_PORT_SHIFT; |
| 10632 | 10669 | ||
| 10633 | if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) | 10670 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
| 10634 | skylake_get_ddi_pll(dev_priv, port, pipe_config); | 10671 | skylake_get_ddi_pll(dev_priv, port, pipe_config); |
| 10635 | else if (IS_BROXTON(dev)) | 10672 | else if (IS_BROXTON(dev_priv)) |
| 10636 | bxt_get_ddi_pll(dev_priv, port, pipe_config); | 10673 | bxt_get_ddi_pll(dev_priv, port, pipe_config); |
| 10637 | else | 10674 | else |
| 10638 | haswell_get_ddi_pll(dev_priv, port, pipe_config); | 10675 | haswell_get_ddi_pll(dev_priv, port, pipe_config); |
| @@ -10715,7 +10752,7 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, | |||
| 10715 | ironlake_get_pfit_config(crtc, pipe_config); | 10752 | ironlake_get_pfit_config(crtc, pipe_config); |
| 10716 | } | 10753 | } |
| 10717 | 10754 | ||
| 10718 | if (IS_HASWELL(dev)) | 10755 | if (IS_HASWELL(dev_priv)) |
| 10719 | pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) && | 10756 | pipe_config->ips_enabled = hsw_crtc_supports_ips(crtc) && |
| 10720 | (I915_READ(IPS_CTL) & IPS_ENABLE); | 10757 | (I915_READ(IPS_CTL) & IPS_ENABLE); |
| 10721 | 10758 | ||
| @@ -10803,12 +10840,15 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, | |||
| 10803 | struct drm_device *dev = crtc->dev; | 10840 | struct drm_device *dev = crtc->dev; |
| 10804 | struct drm_i915_private *dev_priv = to_i915(dev); | 10841 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 10805 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 10842 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 10843 | struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); | ||
| 10806 | const struct skl_wm_values *wm = &dev_priv->wm.skl_results; | 10844 | const struct skl_wm_values *wm = &dev_priv->wm.skl_results; |
| 10845 | const struct skl_plane_wm *p_wm = | ||
| 10846 | &cstate->wm.skl.optimal.planes[PLANE_CURSOR]; | ||
| 10807 | int pipe = intel_crtc->pipe; | 10847 | int pipe = intel_crtc->pipe; |
| 10808 | uint32_t cntl = 0; | 10848 | uint32_t cntl = 0; |
| 10809 | 10849 | ||
| 10810 | if (INTEL_GEN(dev_priv) >= 9 && wm->dirty_pipes & drm_crtc_mask(crtc)) | 10850 | if (INTEL_GEN(dev_priv) >= 9 && wm->dirty_pipes & drm_crtc_mask(crtc)) |
| 10811 | skl_write_cursor_wm(intel_crtc, wm); | 10851 | skl_write_cursor_wm(intel_crtc, p_wm, &wm->ddb); |
| 10812 | 10852 | ||
| 10813 | if (plane_state && plane_state->base.visible) { | 10853 | if (plane_state && plane_state->base.visible) { |
| 10814 | cntl = MCURSOR_GAMMA_ENABLE; | 10854 | cntl = MCURSOR_GAMMA_ENABLE; |
| @@ -10828,7 +10868,7 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base, | |||
| 10828 | } | 10868 | } |
| 10829 | cntl |= pipe << 28; /* Connect to correct pipe */ | 10869 | cntl |= pipe << 28; /* Connect to correct pipe */ |
| 10830 | 10870 | ||
| 10831 | if (HAS_DDI(dev)) | 10871 | if (HAS_DDI(dev_priv)) |
| 10832 | cntl |= CURSOR_PIPE_CSC_ENABLE; | 10872 | cntl |= CURSOR_PIPE_CSC_ENABLE; |
| 10833 | 10873 | ||
| 10834 | if (plane_state->base.rotation == DRM_ROTATE_180) | 10874 | if (plane_state->base.rotation == DRM_ROTATE_180) |
| @@ -10876,7 +10916,7 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, | |||
| 10876 | pos |= y << CURSOR_Y_SHIFT; | 10916 | pos |= y << CURSOR_Y_SHIFT; |
| 10877 | 10917 | ||
| 10878 | /* ILK+ do this automagically */ | 10918 | /* ILK+ do this automagically */ |
| 10879 | if (HAS_GMCH_DISPLAY(dev) && | 10919 | if (HAS_GMCH_DISPLAY(dev_priv) && |
| 10880 | plane_state->base.rotation == DRM_ROTATE_180) { | 10920 | plane_state->base.rotation == DRM_ROTATE_180) { |
| 10881 | base += (plane_state->base.crtc_h * | 10921 | base += (plane_state->base.crtc_h * |
| 10882 | plane_state->base.crtc_w - 1) * 4; | 10922 | plane_state->base.crtc_w - 1) * 4; |
| @@ -10885,13 +10925,13 @@ static void intel_crtc_update_cursor(struct drm_crtc *crtc, | |||
| 10885 | 10925 | ||
| 10886 | I915_WRITE(CURPOS(pipe), pos); | 10926 | I915_WRITE(CURPOS(pipe), pos); |
| 10887 | 10927 | ||
| 10888 | if (IS_845G(dev) || IS_I865G(dev)) | 10928 | if (IS_845G(dev_priv) || IS_I865G(dev_priv)) |
| 10889 | i845_update_cursor(crtc, base, plane_state); | 10929 | i845_update_cursor(crtc, base, plane_state); |
| 10890 | else | 10930 | else |
| 10891 | i9xx_update_cursor(crtc, base, plane_state); | 10931 | i9xx_update_cursor(crtc, base, plane_state); |
| 10892 | } | 10932 | } |
| 10893 | 10933 | ||
| 10894 | static bool cursor_size_ok(struct drm_device *dev, | 10934 | static bool cursor_size_ok(struct drm_i915_private *dev_priv, |
| 10895 | uint32_t width, uint32_t height) | 10935 | uint32_t width, uint32_t height) |
| 10896 | { | 10936 | { |
| 10897 | if (width == 0 || height == 0) | 10937 | if (width == 0 || height == 0) |
| @@ -10903,11 +10943,11 @@ static bool cursor_size_ok(struct drm_device *dev, | |||
| 10903 | * the precision of the register. Everything else requires | 10943 | * the precision of the register. Everything else requires |
| 10904 | * square cursors, limited to a few power-of-two sizes. | 10944 | * square cursors, limited to a few power-of-two sizes. |
| 10905 | */ | 10945 | */ |
| 10906 | if (IS_845G(dev) || IS_I865G(dev)) { | 10946 | if (IS_845G(dev_priv) || IS_I865G(dev_priv)) { |
| 10907 | if ((width & 63) != 0) | 10947 | if ((width & 63) != 0) |
| 10908 | return false; | 10948 | return false; |
| 10909 | 10949 | ||
| 10910 | if (width > (IS_845G(dev) ? 64 : 512)) | 10950 | if (width > (IS_845G(dev_priv) ? 64 : 512)) |
| 10911 | return false; | 10951 | return false; |
| 10912 | 10952 | ||
| 10913 | if (height > 1023) | 10953 | if (height > 1023) |
| @@ -10916,7 +10956,7 @@ static bool cursor_size_ok(struct drm_device *dev, | |||
| 10916 | switch (width | height) { | 10956 | switch (width | height) { |
| 10917 | case 256: | 10957 | case 256: |
| 10918 | case 128: | 10958 | case 128: |
| 10919 | if (IS_GEN2(dev)) | 10959 | if (IS_GEN2(dev_priv)) |
| 10920 | return false; | 10960 | return false; |
| 10921 | case 64: | 10961 | case 64: |
| 10922 | break; | 10962 | break; |
| @@ -11299,9 +11339,9 @@ static int i9xx_pll_refclk(struct drm_device *dev, | |||
| 11299 | 11339 | ||
| 11300 | if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN) | 11340 | if ((dpll & PLL_REF_INPUT_MASK) == PLLB_REF_INPUT_SPREADSPECTRUMIN) |
| 11301 | return dev_priv->vbt.lvds_ssc_freq; | 11341 | return dev_priv->vbt.lvds_ssc_freq; |
| 11302 | else if (HAS_PCH_SPLIT(dev)) | 11342 | else if (HAS_PCH_SPLIT(dev_priv)) |
| 11303 | return 120000; | 11343 | return 120000; |
| 11304 | else if (!IS_GEN2(dev)) | 11344 | else if (!IS_GEN2(dev_priv)) |
| 11305 | return 96000; | 11345 | return 96000; |
| 11306 | else | 11346 | else |
| 11307 | return 48000; | 11347 | return 48000; |
| @@ -11334,7 +11374,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, | |||
| 11334 | clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; | 11374 | clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; |
| 11335 | } | 11375 | } |
| 11336 | 11376 | ||
| 11337 | if (!IS_GEN2(dev)) { | 11377 | if (!IS_GEN2(dev_priv)) { |
| 11338 | if (IS_PINEVIEW(dev)) | 11378 | if (IS_PINEVIEW(dev)) |
| 11339 | clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >> | 11379 | clock.p1 = ffs((dpll & DPLL_FPA01_P1_POST_DIV_MASK_PINEVIEW) >> |
| 11340 | DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW); | 11380 | DPLL_FPA01_P1_POST_DIV_SHIFT_PINEVIEW); |
| @@ -11362,7 +11402,7 @@ static void i9xx_crtc_clock_get(struct intel_crtc *crtc, | |||
| 11362 | else | 11402 | else |
| 11363 | port_clock = i9xx_calc_dpll_params(refclk, &clock); | 11403 | port_clock = i9xx_calc_dpll_params(refclk, &clock); |
| 11364 | } else { | 11404 | } else { |
| 11365 | u32 lvds = IS_I830(dev) ? 0 : I915_READ(LVDS); | 11405 | u32 lvds = IS_I830(dev_priv) ? 0 : I915_READ(LVDS); |
| 11366 | bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN); | 11406 | bool is_lvds = (pipe == 1) && (lvds & LVDS_PORT_EN); |
| 11367 | 11407 | ||
| 11368 | if (is_lvds) { | 11408 | if (is_lvds) { |
| @@ -11563,7 +11603,7 @@ static bool __pageflip_finished_cs(struct intel_crtc *crtc, | |||
| 11563 | * really needed there. But since ctg has the registers, | 11603 | * really needed there. But since ctg has the registers, |
| 11564 | * include it in the check anyway. | 11604 | * include it in the check anyway. |
| 11565 | */ | 11605 | */ |
| 11566 | if (INTEL_INFO(dev)->gen < 5 && !IS_G4X(dev)) | 11606 | if (INTEL_GEN(dev_priv) < 5 && !IS_G4X(dev_priv)) |
| 11567 | return true; | 11607 | return true; |
| 11568 | 11608 | ||
| 11569 | /* | 11609 | /* |
| @@ -11833,6 +11873,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, | |||
| 11833 | struct drm_i915_gem_request *req, | 11873 | struct drm_i915_gem_request *req, |
| 11834 | uint32_t flags) | 11874 | uint32_t flags) |
| 11835 | { | 11875 | { |
| 11876 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 11836 | struct intel_ring *ring = req->ring; | 11877 | struct intel_ring *ring = req->ring; |
| 11837 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 11878 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 11838 | uint32_t plane_bit = 0; | 11879 | uint32_t plane_bit = 0; |
| @@ -11861,7 +11902,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, | |||
| 11861 | * 48bits addresses, and we need a NOOP for the batch size to | 11902 | * 48bits addresses, and we need a NOOP for the batch size to |
| 11862 | * stay even. | 11903 | * stay even. |
| 11863 | */ | 11904 | */ |
| 11864 | if (IS_GEN8(dev)) | 11905 | if (IS_GEN8(dev_priv)) |
| 11865 | len += 2; | 11906 | len += 2; |
| 11866 | } | 11907 | } |
| 11867 | 11908 | ||
| @@ -11898,7 +11939,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, | |||
| 11898 | intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE | | 11939 | intel_ring_emit(ring, ~(DERRMR_PIPEA_PRI_FLIP_DONE | |
| 11899 | DERRMR_PIPEB_PRI_FLIP_DONE | | 11940 | DERRMR_PIPEB_PRI_FLIP_DONE | |
| 11900 | DERRMR_PIPEC_PRI_FLIP_DONE)); | 11941 | DERRMR_PIPEC_PRI_FLIP_DONE)); |
| 11901 | if (IS_GEN8(dev)) | 11942 | if (IS_GEN8(dev_priv)) |
| 11902 | intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 | | 11943 | intel_ring_emit(ring, MI_STORE_REGISTER_MEM_GEN8 | |
| 11903 | MI_SRM_LRM_GLOBAL_GTT); | 11944 | MI_SRM_LRM_GLOBAL_GTT); |
| 11904 | else | 11945 | else |
| @@ -11907,7 +11948,7 @@ static int intel_gen7_queue_flip(struct drm_device *dev, | |||
| 11907 | intel_ring_emit_reg(ring, DERRMR); | 11948 | intel_ring_emit_reg(ring, DERRMR); |
| 11908 | intel_ring_emit(ring, | 11949 | intel_ring_emit(ring, |
| 11909 | i915_ggtt_offset(req->engine->scratch) + 256); | 11950 | i915_ggtt_offset(req->engine->scratch) + 256); |
| 11910 | if (IS_GEN8(dev)) { | 11951 | if (IS_GEN8(dev_priv)) { |
| 11911 | intel_ring_emit(ring, 0); | 11952 | intel_ring_emit(ring, 0); |
| 11912 | intel_ring_emit(ring, MI_NOOP); | 11953 | intel_ring_emit(ring, MI_NOOP); |
| 11913 | } | 11954 | } |
| @@ -12226,23 +12267,23 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
| 12226 | 12267 | ||
| 12227 | atomic_inc(&intel_crtc->unpin_work_count); | 12268 | atomic_inc(&intel_crtc->unpin_work_count); |
| 12228 | 12269 | ||
| 12229 | if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) | 12270 | if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) |
| 12230 | work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1; | 12271 | work->flip_count = I915_READ(PIPE_FLIPCOUNT_G4X(pipe)) + 1; |
| 12231 | 12272 | ||
| 12232 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 12273 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 12233 | engine = &dev_priv->engine[BCS]; | 12274 | engine = dev_priv->engine[BCS]; |
| 12234 | if (fb->modifier[0] != old_fb->modifier[0]) | 12275 | if (fb->modifier[0] != old_fb->modifier[0]) |
| 12235 | /* vlv: DISPLAY_FLIP fails to change tiling */ | 12276 | /* vlv: DISPLAY_FLIP fails to change tiling */ |
| 12236 | engine = NULL; | 12277 | engine = NULL; |
| 12237 | } else if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev)) { | 12278 | } else if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) { |
| 12238 | engine = &dev_priv->engine[BCS]; | 12279 | engine = dev_priv->engine[BCS]; |
| 12239 | } else if (INTEL_INFO(dev)->gen >= 7) { | 12280 | } else if (INTEL_INFO(dev)->gen >= 7) { |
| 12240 | engine = i915_gem_active_get_engine(&obj->last_write, | 12281 | engine = i915_gem_active_get_engine(&obj->last_write, |
| 12241 | &obj->base.dev->struct_mutex); | 12282 | &obj->base.dev->struct_mutex); |
| 12242 | if (engine == NULL || engine->id != RCS) | 12283 | if (engine == NULL || engine->id != RCS) |
| 12243 | engine = &dev_priv->engine[BCS]; | 12284 | engine = dev_priv->engine[BCS]; |
| 12244 | } else { | 12285 | } else { |
| 12245 | engine = &dev_priv->engine[RCS]; | 12286 | engine = dev_priv->engine[RCS]; |
| 12246 | } | 12287 | } |
| 12247 | 12288 | ||
| 12248 | mmio_flip = use_mmio_flip(engine, obj); | 12289 | mmio_flip = use_mmio_flip(engine, obj); |
| @@ -12273,7 +12314,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
| 12273 | 12314 | ||
| 12274 | work->flip_queued_req = i915_gem_active_get(&obj->last_write, | 12315 | work->flip_queued_req = i915_gem_active_get(&obj->last_write, |
| 12275 | &obj->base.dev->struct_mutex); | 12316 | &obj->base.dev->struct_mutex); |
| 12276 | schedule_work(&work->mmio_work); | 12317 | queue_work(system_unbound_wq, &work->mmio_work); |
| 12277 | } else { | 12318 | } else { |
| 12278 | request = i915_gem_request_alloc(engine, engine->last_context); | 12319 | request = i915_gem_request_alloc(engine, engine->last_context); |
| 12279 | if (IS_ERR(request)) { | 12320 | if (IS_ERR(request)) { |
| @@ -12430,7 +12471,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, | |||
| 12430 | struct drm_framebuffer *fb = plane_state->fb; | 12471 | struct drm_framebuffer *fb = plane_state->fb; |
| 12431 | int ret; | 12472 | int ret; |
| 12432 | 12473 | ||
| 12433 | if (INTEL_GEN(dev) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) { | 12474 | if (INTEL_GEN(dev_priv) >= 9 && plane->type != DRM_PLANE_TYPE_CURSOR) { |
| 12434 | ret = skl_update_scaler_plane( | 12475 | ret = skl_update_scaler_plane( |
| 12435 | to_intel_crtc_state(crtc_state), | 12476 | to_intel_crtc_state(crtc_state), |
| 12436 | to_intel_plane_state(plane_state)); | 12477 | to_intel_plane_state(plane_state)); |
| @@ -12509,7 +12550,7 @@ int intel_plane_atomic_calc_changes(struct drm_crtc_state *crtc_state, | |||
| 12509 | * cstate->update_wm was already set above, so this flag will | 12550 | * cstate->update_wm was already set above, so this flag will |
| 12510 | * take effect when we commit and program watermarks. | 12551 | * take effect when we commit and program watermarks. |
| 12511 | */ | 12552 | */ |
| 12512 | if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev) && | 12553 | if (plane->type == DRM_PLANE_TYPE_OVERLAY && IS_IVYBRIDGE(dev_priv) && |
| 12513 | needs_scaling(to_intel_plane_state(plane_state)) && | 12554 | needs_scaling(to_intel_plane_state(plane_state)) && |
| 12514 | !needs_scaling(old_plane_state)) | 12555 | !needs_scaling(old_plane_state)) |
| 12515 | pipe_config->disable_lp_wm = true; | 12556 | pipe_config->disable_lp_wm = true; |
| @@ -12685,15 +12726,16 @@ static int | |||
| 12685 | compute_baseline_pipe_bpp(struct intel_crtc *crtc, | 12726 | compute_baseline_pipe_bpp(struct intel_crtc *crtc, |
| 12686 | struct intel_crtc_state *pipe_config) | 12727 | struct intel_crtc_state *pipe_config) |
| 12687 | { | 12728 | { |
| 12688 | struct drm_device *dev = crtc->base.dev; | 12729 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); |
| 12689 | struct drm_atomic_state *state; | 12730 | struct drm_atomic_state *state; |
| 12690 | struct drm_connector *connector; | 12731 | struct drm_connector *connector; |
| 12691 | struct drm_connector_state *connector_state; | 12732 | struct drm_connector_state *connector_state; |
| 12692 | int bpp, i; | 12733 | int bpp, i; |
| 12693 | 12734 | ||
| 12694 | if ((IS_G4X(dev) || IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))) | 12735 | if ((IS_G4X(dev_priv) || IS_VALLEYVIEW(dev_priv) || |
| 12736 | IS_CHERRYVIEW(dev_priv))) | ||
| 12695 | bpp = 10*3; | 12737 | bpp = 10*3; |
| 12696 | else if (INTEL_INFO(dev)->gen >= 5) | 12738 | else if (INTEL_GEN(dev_priv) >= 5) |
| 12697 | bpp = 12*3; | 12739 | bpp = 12*3; |
| 12698 | else | 12740 | else |
| 12699 | bpp = 8*3; | 12741 | bpp = 8*3; |
| @@ -12731,6 +12773,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, | |||
| 12731 | const char *context) | 12773 | const char *context) |
| 12732 | { | 12774 | { |
| 12733 | struct drm_device *dev = crtc->base.dev; | 12775 | struct drm_device *dev = crtc->base.dev; |
| 12776 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 12734 | struct drm_plane *plane; | 12777 | struct drm_plane *plane; |
| 12735 | struct intel_plane *intel_plane; | 12778 | struct intel_plane *intel_plane; |
| 12736 | struct intel_plane_state *state; | 12779 | struct intel_plane_state *state; |
| @@ -12792,7 +12835,7 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, | |||
| 12792 | DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled); | 12835 | DRM_DEBUG_KMS("ips: %i\n", pipe_config->ips_enabled); |
| 12793 | DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide); | 12836 | DRM_DEBUG_KMS("double wide: %i\n", pipe_config->double_wide); |
| 12794 | 12837 | ||
| 12795 | if (IS_BROXTON(dev)) { | 12838 | if (IS_BROXTON(dev_priv)) { |
| 12796 | DRM_DEBUG_KMS("dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x," | 12839 | DRM_DEBUG_KMS("dpll_hw_state: ebb0: 0x%x, ebb4: 0x%x," |
| 12797 | "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, " | 12840 | "pll0: 0x%x, pll1: 0x%x, pll2: 0x%x, pll3: 0x%x, " |
| 12798 | "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n", | 12841 | "pll6: 0x%x, pll8: 0x%x, pll9: 0x%x, pll10: 0x%x, pcsdw12: 0x%x\n", |
| @@ -12807,13 +12850,13 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, | |||
| 12807 | pipe_config->dpll_hw_state.pll9, | 12850 | pipe_config->dpll_hw_state.pll9, |
| 12808 | pipe_config->dpll_hw_state.pll10, | 12851 | pipe_config->dpll_hw_state.pll10, |
| 12809 | pipe_config->dpll_hw_state.pcsdw12); | 12852 | pipe_config->dpll_hw_state.pcsdw12); |
| 12810 | } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { | 12853 | } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { |
| 12811 | DRM_DEBUG_KMS("dpll_hw_state: " | 12854 | DRM_DEBUG_KMS("dpll_hw_state: " |
| 12812 | "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n", | 12855 | "ctrl1: 0x%x, cfgcr1: 0x%x, cfgcr2: 0x%x\n", |
| 12813 | pipe_config->dpll_hw_state.ctrl1, | 12856 | pipe_config->dpll_hw_state.ctrl1, |
| 12814 | pipe_config->dpll_hw_state.cfgcr1, | 12857 | pipe_config->dpll_hw_state.cfgcr1, |
| 12815 | pipe_config->dpll_hw_state.cfgcr2); | 12858 | pipe_config->dpll_hw_state.cfgcr2); |
| 12816 | } else if (HAS_DDI(dev)) { | 12859 | } else if (HAS_DDI(dev_priv)) { |
| 12817 | DRM_DEBUG_KMS("dpll_hw_state: wrpll: 0x%x spll: 0x%x\n", | 12860 | DRM_DEBUG_KMS("dpll_hw_state: wrpll: 0x%x spll: 0x%x\n", |
| 12818 | pipe_config->dpll_hw_state.wrpll, | 12861 | pipe_config->dpll_hw_state.wrpll, |
| 12819 | pipe_config->dpll_hw_state.spll); | 12862 | pipe_config->dpll_hw_state.spll); |
| @@ -12891,7 +12934,7 @@ static bool check_digital_port_conflicts(struct drm_atomic_state *state) | |||
| 12891 | switch (encoder->type) { | 12934 | switch (encoder->type) { |
| 12892 | unsigned int port_mask; | 12935 | unsigned int port_mask; |
| 12893 | case INTEL_OUTPUT_UNKNOWN: | 12936 | case INTEL_OUTPUT_UNKNOWN: |
| 12894 | if (WARN_ON(!HAS_DDI(dev))) | 12937 | if (WARN_ON(!HAS_DDI(to_i915(dev)))) |
| 12895 | break; | 12938 | break; |
| 12896 | case INTEL_OUTPUT_DP: | 12939 | case INTEL_OUTPUT_DP: |
| 12897 | case INTEL_OUTPUT_HDMI: | 12940 | case INTEL_OUTPUT_HDMI: |
| @@ -13177,6 +13220,7 @@ intel_pipe_config_compare(struct drm_device *dev, | |||
| 13177 | struct intel_crtc_state *pipe_config, | 13220 | struct intel_crtc_state *pipe_config, |
| 13178 | bool adjust) | 13221 | bool adjust) |
| 13179 | { | 13222 | { |
| 13223 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 13180 | bool ret = true; | 13224 | bool ret = true; |
| 13181 | 13225 | ||
| 13182 | #define INTEL_ERR_OR_DBG_KMS(fmt, ...) \ | 13226 | #define INTEL_ERR_OR_DBG_KMS(fmt, ...) \ |
| @@ -13322,8 +13366,8 @@ intel_pipe_config_compare(struct drm_device *dev, | |||
| 13322 | 13366 | ||
| 13323 | PIPE_CONF_CHECK_I(pixel_multiplier); | 13367 | PIPE_CONF_CHECK_I(pixel_multiplier); |
| 13324 | PIPE_CONF_CHECK_I(has_hdmi_sink); | 13368 | PIPE_CONF_CHECK_I(has_hdmi_sink); |
| 13325 | if ((INTEL_INFO(dev)->gen < 8 && !IS_HASWELL(dev)) || | 13369 | if ((INTEL_GEN(dev_priv) < 8 && !IS_HASWELL(dev_priv)) || |
| 13326 | IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 13370 | IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 13327 | PIPE_CONF_CHECK_I(limited_color_range); | 13371 | PIPE_CONF_CHECK_I(limited_color_range); |
| 13328 | PIPE_CONF_CHECK_I(has_infoframe); | 13372 | PIPE_CONF_CHECK_I(has_infoframe); |
| 13329 | 13373 | ||
| @@ -13363,7 +13407,7 @@ intel_pipe_config_compare(struct drm_device *dev, | |||
| 13363 | } | 13407 | } |
| 13364 | 13408 | ||
| 13365 | /* BDW+ don't expose a synchronous way to read the state */ | 13409 | /* BDW+ don't expose a synchronous way to read the state */ |
| 13366 | if (IS_HASWELL(dev)) | 13410 | if (IS_HASWELL(dev_priv)) |
| 13367 | PIPE_CONF_CHECK_I(ips_enabled); | 13411 | PIPE_CONF_CHECK_I(ips_enabled); |
| 13368 | 13412 | ||
| 13369 | PIPE_CONF_CHECK_I(double_wide); | 13413 | PIPE_CONF_CHECK_I(double_wide); |
| @@ -13382,7 +13426,7 @@ intel_pipe_config_compare(struct drm_device *dev, | |||
| 13382 | PIPE_CONF_CHECK_X(dsi_pll.ctrl); | 13426 | PIPE_CONF_CHECK_X(dsi_pll.ctrl); |
| 13383 | PIPE_CONF_CHECK_X(dsi_pll.div); | 13427 | PIPE_CONF_CHECK_X(dsi_pll.div); |
| 13384 | 13428 | ||
| 13385 | if (IS_G4X(dev) || INTEL_INFO(dev)->gen >= 5) | 13429 | if (IS_G4X(dev_priv) || INTEL_GEN(dev_priv) >= 5) |
| 13386 | PIPE_CONF_CHECK_I(pipe_bpp); | 13430 | PIPE_CONF_CHECK_I(pipe_bpp); |
| 13387 | 13431 | ||
| 13388 | PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock); | 13432 | PIPE_CONF_CHECK_CLOCK_FUZZY(base.adjusted_mode.crtc_clock); |
| @@ -13423,30 +13467,65 @@ static void verify_wm_state(struct drm_crtc *crtc, | |||
| 13423 | struct drm_device *dev = crtc->dev; | 13467 | struct drm_device *dev = crtc->dev; |
| 13424 | struct drm_i915_private *dev_priv = to_i915(dev); | 13468 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 13425 | struct skl_ddb_allocation hw_ddb, *sw_ddb; | 13469 | struct skl_ddb_allocation hw_ddb, *sw_ddb; |
| 13426 | struct skl_ddb_entry *hw_entry, *sw_entry; | 13470 | struct skl_pipe_wm hw_wm, *sw_wm; |
| 13471 | struct skl_plane_wm *hw_plane_wm, *sw_plane_wm; | ||
| 13472 | struct skl_ddb_entry *hw_ddb_entry, *sw_ddb_entry; | ||
| 13427 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 13473 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 13428 | const enum pipe pipe = intel_crtc->pipe; | 13474 | const enum pipe pipe = intel_crtc->pipe; |
| 13429 | int plane; | 13475 | int plane, level, max_level = ilk_wm_max_level(dev_priv); |
| 13430 | 13476 | ||
| 13431 | if (INTEL_INFO(dev)->gen < 9 || !new_state->active) | 13477 | if (INTEL_INFO(dev)->gen < 9 || !new_state->active) |
| 13432 | return; | 13478 | return; |
| 13433 | 13479 | ||
| 13480 | skl_pipe_wm_get_hw_state(crtc, &hw_wm); | ||
| 13481 | sw_wm = &intel_crtc->wm.active.skl; | ||
| 13482 | |||
| 13434 | skl_ddb_get_hw_state(dev_priv, &hw_ddb); | 13483 | skl_ddb_get_hw_state(dev_priv, &hw_ddb); |
| 13435 | sw_ddb = &dev_priv->wm.skl_hw.ddb; | 13484 | sw_ddb = &dev_priv->wm.skl_hw.ddb; |
| 13436 | 13485 | ||
| 13437 | /* planes */ | 13486 | /* planes */ |
| 13438 | for_each_plane(dev_priv, pipe, plane) { | 13487 | for_each_plane(dev_priv, pipe, plane) { |
| 13439 | hw_entry = &hw_ddb.plane[pipe][plane]; | 13488 | hw_plane_wm = &hw_wm.planes[plane]; |
| 13440 | sw_entry = &sw_ddb->plane[pipe][plane]; | 13489 | sw_plane_wm = &sw_wm->planes[plane]; |
| 13441 | 13490 | ||
| 13442 | if (skl_ddb_entry_equal(hw_entry, sw_entry)) | 13491 | /* Watermarks */ |
| 13443 | continue; | 13492 | for (level = 0; level <= max_level; level++) { |
| 13493 | if (skl_wm_level_equals(&hw_plane_wm->wm[level], | ||
| 13494 | &sw_plane_wm->wm[level])) | ||
| 13495 | continue; | ||
| 13444 | 13496 | ||
| 13445 | DRM_ERROR("mismatch in DDB state pipe %c plane %d " | 13497 | DRM_ERROR("mismatch in WM pipe %c plane %d level %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", |
| 13446 | "(expected (%u,%u), found (%u,%u))\n", | 13498 | pipe_name(pipe), plane + 1, level, |
| 13447 | pipe_name(pipe), plane + 1, | 13499 | sw_plane_wm->wm[level].plane_en, |
| 13448 | sw_entry->start, sw_entry->end, | 13500 | sw_plane_wm->wm[level].plane_res_b, |
| 13449 | hw_entry->start, hw_entry->end); | 13501 | sw_plane_wm->wm[level].plane_res_l, |
| 13502 | hw_plane_wm->wm[level].plane_en, | ||
| 13503 | hw_plane_wm->wm[level].plane_res_b, | ||
| 13504 | hw_plane_wm->wm[level].plane_res_l); | ||
| 13505 | } | ||
| 13506 | |||
| 13507 | if (!skl_wm_level_equals(&hw_plane_wm->trans_wm, | ||
| 13508 | &sw_plane_wm->trans_wm)) { | ||
| 13509 | DRM_ERROR("mismatch in trans WM pipe %c plane %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", | ||
| 13510 | pipe_name(pipe), plane + 1, | ||
| 13511 | sw_plane_wm->trans_wm.plane_en, | ||
| 13512 | sw_plane_wm->trans_wm.plane_res_b, | ||
| 13513 | sw_plane_wm->trans_wm.plane_res_l, | ||
| 13514 | hw_plane_wm->trans_wm.plane_en, | ||
| 13515 | hw_plane_wm->trans_wm.plane_res_b, | ||
| 13516 | hw_plane_wm->trans_wm.plane_res_l); | ||
| 13517 | } | ||
| 13518 | |||
| 13519 | /* DDB */ | ||
| 13520 | hw_ddb_entry = &hw_ddb.plane[pipe][plane]; | ||
| 13521 | sw_ddb_entry = &sw_ddb->plane[pipe][plane]; | ||
| 13522 | |||
| 13523 | if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { | ||
| 13524 | DRM_ERROR("mismatch in DDB state pipe %c plane %d (expected (%u,%u), found (%u,%u))\n", | ||
| 13525 | pipe_name(pipe), plane + 1, | ||
| 13526 | sw_ddb_entry->start, sw_ddb_entry->end, | ||
| 13527 | hw_ddb_entry->start, hw_ddb_entry->end); | ||
| 13528 | } | ||
| 13450 | } | 13529 | } |
| 13451 | 13530 | ||
| 13452 | /* | 13531 | /* |
| @@ -13456,15 +13535,46 @@ static void verify_wm_state(struct drm_crtc *crtc, | |||
| 13456 | * once the plane becomes visible, we can skip this check | 13535 | * once the plane becomes visible, we can skip this check |
| 13457 | */ | 13536 | */ |
| 13458 | if (intel_crtc->cursor_addr) { | 13537 | if (intel_crtc->cursor_addr) { |
| 13459 | hw_entry = &hw_ddb.plane[pipe][PLANE_CURSOR]; | 13538 | hw_plane_wm = &hw_wm.planes[PLANE_CURSOR]; |
| 13460 | sw_entry = &sw_ddb->plane[pipe][PLANE_CURSOR]; | 13539 | sw_plane_wm = &sw_wm->planes[PLANE_CURSOR]; |
| 13540 | |||
| 13541 | /* Watermarks */ | ||
| 13542 | for (level = 0; level <= max_level; level++) { | ||
| 13543 | if (skl_wm_level_equals(&hw_plane_wm->wm[level], | ||
| 13544 | &sw_plane_wm->wm[level])) | ||
| 13545 | continue; | ||
| 13546 | |||
| 13547 | DRM_ERROR("mismatch in WM pipe %c cursor level %d (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", | ||
| 13548 | pipe_name(pipe), level, | ||
| 13549 | sw_plane_wm->wm[level].plane_en, | ||
| 13550 | sw_plane_wm->wm[level].plane_res_b, | ||
| 13551 | sw_plane_wm->wm[level].plane_res_l, | ||
| 13552 | hw_plane_wm->wm[level].plane_en, | ||
| 13553 | hw_plane_wm->wm[level].plane_res_b, | ||
| 13554 | hw_plane_wm->wm[level].plane_res_l); | ||
| 13555 | } | ||
| 13556 | |||
| 13557 | if (!skl_wm_level_equals(&hw_plane_wm->trans_wm, | ||
| 13558 | &sw_plane_wm->trans_wm)) { | ||
| 13559 | DRM_ERROR("mismatch in trans WM pipe %c cursor (expected e=%d b=%u l=%u, got e=%d b=%u l=%u)\n", | ||
| 13560 | pipe_name(pipe), | ||
| 13561 | sw_plane_wm->trans_wm.plane_en, | ||
| 13562 | sw_plane_wm->trans_wm.plane_res_b, | ||
| 13563 | sw_plane_wm->trans_wm.plane_res_l, | ||
| 13564 | hw_plane_wm->trans_wm.plane_en, | ||
| 13565 | hw_plane_wm->trans_wm.plane_res_b, | ||
| 13566 | hw_plane_wm->trans_wm.plane_res_l); | ||
| 13567 | } | ||
| 13461 | 13568 | ||
| 13462 | if (!skl_ddb_entry_equal(hw_entry, sw_entry)) { | 13569 | /* DDB */ |
| 13463 | DRM_ERROR("mismatch in DDB state pipe %c cursor " | 13570 | hw_ddb_entry = &hw_ddb.plane[pipe][PLANE_CURSOR]; |
| 13464 | "(expected (%u,%u), found (%u,%u))\n", | 13571 | sw_ddb_entry = &sw_ddb->plane[pipe][PLANE_CURSOR]; |
| 13572 | |||
| 13573 | if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { | ||
| 13574 | DRM_ERROR("mismatch in DDB state pipe %c cursor (expected (%u,%u), found (%u,%u))\n", | ||
| 13465 | pipe_name(pipe), | 13575 | pipe_name(pipe), |
| 13466 | sw_entry->start, sw_entry->end, | 13576 | sw_ddb_entry->start, sw_ddb_entry->end, |
| 13467 | hw_entry->start, hw_entry->end); | 13577 | hw_ddb_entry->start, hw_ddb_entry->end); |
| 13468 | } | 13578 | } |
| 13469 | } | 13579 | } |
| 13470 | } | 13580 | } |
| @@ -13715,7 +13825,7 @@ intel_modeset_verify_disabled(struct drm_device *dev) | |||
| 13715 | 13825 | ||
| 13716 | static void update_scanline_offset(struct intel_crtc *crtc) | 13826 | static void update_scanline_offset(struct intel_crtc *crtc) |
| 13717 | { | 13827 | { |
| 13718 | struct drm_device *dev = crtc->base.dev; | 13828 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); |
| 13719 | 13829 | ||
| 13720 | /* | 13830 | /* |
| 13721 | * The scanline counter increments at the leading edge of hsync. | 13831 | * The scanline counter increments at the leading edge of hsync. |
| @@ -13735,7 +13845,7 @@ static void update_scanline_offset(struct intel_crtc *crtc) | |||
| 13735 | * there's an extra 1 line difference. So we need to add two instead of | 13845 | * there's an extra 1 line difference. So we need to add two instead of |
| 13736 | * one to the value. | 13846 | * one to the value. |
| 13737 | */ | 13847 | */ |
| 13738 | if (IS_GEN2(dev)) { | 13848 | if (IS_GEN2(dev_priv)) { |
| 13739 | const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; | 13849 | const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode; |
| 13740 | int vtotal; | 13850 | int vtotal; |
| 13741 | 13851 | ||
| @@ -13744,7 +13854,7 @@ static void update_scanline_offset(struct intel_crtc *crtc) | |||
| 13744 | vtotal /= 2; | 13854 | vtotal /= 2; |
| 13745 | 13855 | ||
| 13746 | crtc->scanline_offset = vtotal - 1; | 13856 | crtc->scanline_offset = vtotal - 1; |
| 13747 | } else if (HAS_DDI(dev) && | 13857 | } else if (HAS_DDI(dev_priv) && |
| 13748 | intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) { | 13858 | intel_crtc_has_type(crtc->config, INTEL_OUTPUT_HDMI)) { |
| 13749 | crtc->scanline_offset = 2; | 13859 | crtc->scanline_offset = 2; |
| 13750 | } else | 13860 | } else |
| @@ -14222,12 +14332,11 @@ static void skl_update_crtcs(struct drm_atomic_state *state, | |||
| 14222 | unsigned int *crtc_vblank_mask) | 14332 | unsigned int *crtc_vblank_mask) |
| 14223 | { | 14333 | { |
| 14224 | struct drm_device *dev = state->dev; | 14334 | struct drm_device *dev = state->dev; |
| 14225 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 14226 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); | 14335 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); |
| 14227 | struct drm_crtc *crtc; | 14336 | struct drm_crtc *crtc; |
| 14337 | struct intel_crtc *intel_crtc; | ||
| 14228 | struct drm_crtc_state *old_crtc_state; | 14338 | struct drm_crtc_state *old_crtc_state; |
| 14229 | struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb; | 14339 | struct intel_crtc_state *cstate; |
| 14230 | struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb; | ||
| 14231 | unsigned int updated = 0; | 14340 | unsigned int updated = 0; |
| 14232 | bool progress; | 14341 | bool progress; |
| 14233 | enum pipe pipe; | 14342 | enum pipe pipe; |
| @@ -14245,12 +14354,14 @@ static void skl_update_crtcs(struct drm_atomic_state *state, | |||
| 14245 | for_each_crtc_in_state(state, crtc, old_crtc_state, i) { | 14354 | for_each_crtc_in_state(state, crtc, old_crtc_state, i) { |
| 14246 | bool vbl_wait = false; | 14355 | bool vbl_wait = false; |
| 14247 | unsigned int cmask = drm_crtc_mask(crtc); | 14356 | unsigned int cmask = drm_crtc_mask(crtc); |
| 14248 | pipe = to_intel_crtc(crtc)->pipe; | 14357 | |
| 14358 | intel_crtc = to_intel_crtc(crtc); | ||
| 14359 | cstate = to_intel_crtc_state(crtc->state); | ||
| 14360 | pipe = intel_crtc->pipe; | ||
| 14249 | 14361 | ||
| 14250 | if (updated & cmask || !crtc->state->active) | 14362 | if (updated & cmask || !crtc->state->active) |
| 14251 | continue; | 14363 | continue; |
| 14252 | if (skl_ddb_allocation_overlaps(state, cur_ddb, new_ddb, | 14364 | if (skl_ddb_allocation_overlaps(state, intel_crtc)) |
| 14253 | pipe)) | ||
| 14254 | continue; | 14365 | continue; |
| 14255 | 14366 | ||
| 14256 | updated |= cmask; | 14367 | updated |= cmask; |
| @@ -14261,7 +14372,8 @@ static void skl_update_crtcs(struct drm_atomic_state *state, | |||
| 14261 | * then we need to wait for a vblank to pass for the | 14372 | * then we need to wait for a vblank to pass for the |
| 14262 | * new ddb allocation to take effect. | 14373 | * new ddb allocation to take effect. |
| 14263 | */ | 14374 | */ |
| 14264 | if (!skl_ddb_allocation_equals(cur_ddb, new_ddb, pipe) && | 14375 | if (!skl_ddb_entry_equal(&cstate->wm.skl.ddb, |
| 14376 | &intel_crtc->hw_ddb) && | ||
| 14265 | !crtc->state->active_changed && | 14377 | !crtc->state->active_changed && |
| 14266 | intel_state->wm_results.dirty_pipes != updated) | 14378 | intel_state->wm_results.dirty_pipes != updated) |
| 14267 | vbl_wait = true; | 14379 | vbl_wait = true; |
| @@ -14369,8 +14481,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) | |||
| 14369 | * SKL workaround: bspec recommends we disable the SAGV when we | 14481 | * SKL workaround: bspec recommends we disable the SAGV when we |
| 14370 | * have more then one pipe enabled | 14482 | * have more then one pipe enabled |
| 14371 | */ | 14483 | */ |
| 14372 | if (IS_SKYLAKE(dev_priv) && !skl_can_enable_sagv(state)) | 14484 | if (!intel_can_enable_sagv(state)) |
| 14373 | skl_disable_sagv(dev_priv); | 14485 | intel_disable_sagv(dev_priv); |
| 14374 | 14486 | ||
| 14375 | intel_modeset_verify_disabled(dev); | 14487 | intel_modeset_verify_disabled(dev); |
| 14376 | } | 14488 | } |
| @@ -14427,9 +14539,8 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) | |||
| 14427 | intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state); | 14539 | intel_modeset_verify_crtc(crtc, old_crtc_state, crtc->state); |
| 14428 | } | 14540 | } |
| 14429 | 14541 | ||
| 14430 | if (IS_SKYLAKE(dev_priv) && intel_state->modeset && | 14542 | if (intel_state->modeset && intel_can_enable_sagv(state)) |
| 14431 | skl_can_enable_sagv(state)) | 14543 | intel_enable_sagv(dev_priv); |
| 14432 | skl_enable_sagv(dev_priv); | ||
| 14433 | 14544 | ||
| 14434 | drm_atomic_helper_commit_hw_done(state); | 14545 | drm_atomic_helper_commit_hw_done(state); |
| 14435 | 14546 | ||
| @@ -14642,6 +14753,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, | |||
| 14642 | struct drm_plane_state *new_state) | 14753 | struct drm_plane_state *new_state) |
| 14643 | { | 14754 | { |
| 14644 | struct drm_device *dev = plane->dev; | 14755 | struct drm_device *dev = plane->dev; |
| 14756 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 14645 | struct drm_framebuffer *fb = new_state->fb; | 14757 | struct drm_framebuffer *fb = new_state->fb; |
| 14646 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); | 14758 | struct drm_i915_gem_object *obj = intel_fb_obj(fb); |
| 14647 | struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb); | 14759 | struct drm_i915_gem_object *old_obj = intel_fb_obj(plane->state->fb); |
| @@ -14693,7 +14805,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, | |||
| 14693 | 14805 | ||
| 14694 | if (plane->type == DRM_PLANE_TYPE_CURSOR && | 14806 | if (plane->type == DRM_PLANE_TYPE_CURSOR && |
| 14695 | INTEL_INFO(dev)->cursor_needs_physical) { | 14807 | INTEL_INFO(dev)->cursor_needs_physical) { |
| 14696 | int align = IS_I830(dev) ? 16 * 1024 : 256; | 14808 | int align = IS_I830(dev_priv) ? 16 * 1024 : 256; |
| 14697 | ret = i915_gem_object_attach_phys(obj, align); | 14809 | ret = i915_gem_object_attach_phys(obj, align); |
| 14698 | if (ret) | 14810 | if (ret) |
| 14699 | DRM_DEBUG_KMS("failed to attach phys object\n"); | 14811 | DRM_DEBUG_KMS("failed to attach phys object\n"); |
| @@ -14818,6 +14930,8 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, | |||
| 14818 | struct drm_device *dev = crtc->dev; | 14930 | struct drm_device *dev = crtc->dev; |
| 14819 | struct drm_i915_private *dev_priv = to_i915(dev); | 14931 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 14820 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 14932 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 14933 | struct intel_crtc_state *intel_cstate = | ||
| 14934 | to_intel_crtc_state(crtc->state); | ||
| 14821 | struct intel_crtc_state *old_intel_state = | 14935 | struct intel_crtc_state *old_intel_state = |
| 14822 | to_intel_crtc_state(old_crtc_state); | 14936 | to_intel_crtc_state(old_crtc_state); |
| 14823 | bool modeset = needs_modeset(crtc->state); | 14937 | bool modeset = needs_modeset(crtc->state); |
| @@ -14834,13 +14948,13 @@ static void intel_begin_crtc_commit(struct drm_crtc *crtc, | |||
| 14834 | intel_color_load_luts(crtc->state); | 14948 | intel_color_load_luts(crtc->state); |
| 14835 | } | 14949 | } |
| 14836 | 14950 | ||
| 14837 | if (to_intel_crtc_state(crtc->state)->update_pipe) | 14951 | if (intel_cstate->update_pipe) { |
| 14838 | intel_update_pipe_config(intel_crtc, old_intel_state); | 14952 | intel_update_pipe_config(intel_crtc, old_intel_state); |
| 14839 | else if (INTEL_GEN(dev_priv) >= 9) { | 14953 | } else if (INTEL_GEN(dev_priv) >= 9) { |
| 14840 | skl_detach_scalers(intel_crtc); | 14954 | skl_detach_scalers(intel_crtc); |
| 14841 | 14955 | ||
| 14842 | I915_WRITE(PIPE_WM_LINETIME(pipe), | 14956 | I915_WRITE(PIPE_WM_LINETIME(pipe), |
| 14843 | dev_priv->wm.skl_hw.wm_linetime[pipe]); | 14957 | intel_cstate->wm.skl.optimal.linetime); |
| 14844 | } | 14958 | } |
| 14845 | } | 14959 | } |
| 14846 | 14960 | ||
| @@ -14883,6 +14997,7 @@ const struct drm_plane_funcs intel_plane_funcs = { | |||
| 14883 | static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, | 14997 | static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, |
| 14884 | int pipe) | 14998 | int pipe) |
| 14885 | { | 14999 | { |
| 15000 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 14886 | struct intel_plane *primary = NULL; | 15001 | struct intel_plane *primary = NULL; |
| 14887 | struct intel_plane_state *state = NULL; | 15002 | struct intel_plane_state *state = NULL; |
| 14888 | const uint32_t *intel_primary_formats; | 15003 | const uint32_t *intel_primary_formats; |
| @@ -14918,7 +15033,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, | |||
| 14918 | 15033 | ||
| 14919 | primary->update_plane = skylake_update_primary_plane; | 15034 | primary->update_plane = skylake_update_primary_plane; |
| 14920 | primary->disable_plane = skylake_disable_primary_plane; | 15035 | primary->disable_plane = skylake_disable_primary_plane; |
| 14921 | } else if (HAS_PCH_SPLIT(dev)) { | 15036 | } else if (HAS_PCH_SPLIT(dev_priv)) { |
| 14922 | intel_primary_formats = i965_primary_formats; | 15037 | intel_primary_formats = i965_primary_formats; |
| 14923 | num_formats = ARRAY_SIZE(i965_primary_formats); | 15038 | num_formats = ARRAY_SIZE(i965_primary_formats); |
| 14924 | 15039 | ||
| @@ -14944,7 +15059,7 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, | |||
| 14944 | intel_primary_formats, num_formats, | 15059 | intel_primary_formats, num_formats, |
| 14945 | DRM_PLANE_TYPE_PRIMARY, | 15060 | DRM_PLANE_TYPE_PRIMARY, |
| 14946 | "plane 1%c", pipe_name(pipe)); | 15061 | "plane 1%c", pipe_name(pipe)); |
| 14947 | else if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) | 15062 | else if (INTEL_GEN(dev_priv) >= 5 || IS_G4X(dev_priv)) |
| 14948 | ret = drm_universal_plane_init(dev, &primary->base, 0, | 15063 | ret = drm_universal_plane_init(dev, &primary->base, 0, |
| 14949 | &intel_plane_funcs, | 15064 | &intel_plane_funcs, |
| 14950 | intel_primary_formats, num_formats, | 15065 | intel_primary_formats, num_formats, |
| @@ -14959,18 +15074,18 @@ static struct drm_plane *intel_primary_plane_create(struct drm_device *dev, | |||
| 14959 | if (ret) | 15074 | if (ret) |
| 14960 | goto fail; | 15075 | goto fail; |
| 14961 | 15076 | ||
| 14962 | if (INTEL_GEN(dev) >= 9) { | 15077 | if (INTEL_GEN(dev_priv) >= 9) { |
| 14963 | supported_rotations = | 15078 | supported_rotations = |
| 14964 | DRM_ROTATE_0 | DRM_ROTATE_90 | | 15079 | DRM_ROTATE_0 | DRM_ROTATE_90 | |
| 14965 | DRM_ROTATE_180 | DRM_ROTATE_270; | 15080 | DRM_ROTATE_180 | DRM_ROTATE_270; |
| 14966 | } else if (INTEL_GEN(dev) >= 4) { | 15081 | } else if (INTEL_GEN(dev_priv) >= 4) { |
| 14967 | supported_rotations = | 15082 | supported_rotations = |
| 14968 | DRM_ROTATE_0 | DRM_ROTATE_180; | 15083 | DRM_ROTATE_0 | DRM_ROTATE_180; |
| 14969 | } else { | 15084 | } else { |
| 14970 | supported_rotations = DRM_ROTATE_0; | 15085 | supported_rotations = DRM_ROTATE_0; |
| 14971 | } | 15086 | } |
| 14972 | 15087 | ||
| 14973 | if (INTEL_GEN(dev) >= 4) | 15088 | if (INTEL_GEN(dev_priv) >= 4) |
| 14974 | drm_plane_create_rotation_property(&primary->base, | 15089 | drm_plane_create_rotation_property(&primary->base, |
| 14975 | DRM_ROTATE_0, | 15090 | DRM_ROTATE_0, |
| 14976 | supported_rotations); | 15091 | supported_rotations); |
| @@ -15010,7 +15125,8 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
| 15010 | return 0; | 15125 | return 0; |
| 15011 | 15126 | ||
| 15012 | /* Check for which cursor types we support */ | 15127 | /* Check for which cursor types we support */ |
| 15013 | if (!cursor_size_ok(plane->dev, state->base.crtc_w, state->base.crtc_h)) { | 15128 | if (!cursor_size_ok(to_i915(plane->dev), state->base.crtc_w, |
| 15129 | state->base.crtc_h)) { | ||
| 15014 | DRM_DEBUG("Cursor dimension %dx%d not supported\n", | 15130 | DRM_DEBUG("Cursor dimension %dx%d not supported\n", |
| 15015 | state->base.crtc_w, state->base.crtc_h); | 15131 | state->base.crtc_w, state->base.crtc_h); |
| 15016 | return -EINVAL; | 15132 | return -EINVAL; |
| @@ -15037,7 +15153,7 @@ intel_check_cursor_plane(struct drm_plane *plane, | |||
| 15037 | * display power well must be turned off and on again. | 15153 | * display power well must be turned off and on again. |
| 15038 | * Refuse the put the cursor into that compromised position. | 15154 | * Refuse the put the cursor into that compromised position. |
| 15039 | */ | 15155 | */ |
| 15040 | if (IS_CHERRYVIEW(plane->dev) && pipe == PIPE_C && | 15156 | if (IS_CHERRYVIEW(to_i915(plane->dev)) && pipe == PIPE_C && |
| 15041 | state->base.visible && state->base.crtc_x < 0) { | 15157 | state->base.visible && state->base.crtc_x < 0) { |
| 15042 | DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n"); | 15158 | DRM_DEBUG_KMS("CHV cursor C not allowed to straddle the left screen edge\n"); |
| 15043 | return -EINVAL; | 15159 | return -EINVAL; |
| @@ -15081,6 +15197,7 @@ intel_update_cursor_plane(struct drm_plane *plane, | |||
| 15081 | static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, | 15197 | static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, |
| 15082 | int pipe) | 15198 | int pipe) |
| 15083 | { | 15199 | { |
| 15200 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 15084 | struct intel_plane *cursor = NULL; | 15201 | struct intel_plane *cursor = NULL; |
| 15085 | struct intel_plane_state *state = NULL; | 15202 | struct intel_plane_state *state = NULL; |
| 15086 | int ret; | 15203 | int ret; |
| @@ -15112,7 +15229,7 @@ static struct drm_plane *intel_cursor_plane_create(struct drm_device *dev, | |||
| 15112 | if (ret) | 15229 | if (ret) |
| 15113 | goto fail; | 15230 | goto fail; |
| 15114 | 15231 | ||
| 15115 | if (INTEL_GEN(dev) >= 4) | 15232 | if (INTEL_GEN(dev_priv) >= 4) |
| 15116 | drm_plane_create_rotation_property(&cursor->base, | 15233 | drm_plane_create_rotation_property(&cursor->base, |
| 15117 | DRM_ROTATE_0, | 15234 | DRM_ROTATE_0, |
| 15118 | DRM_ROTATE_0 | | 15235 | DRM_ROTATE_0 | |
| @@ -15285,7 +15402,7 @@ static bool has_edp_a(struct drm_device *dev) | |||
| 15285 | if ((I915_READ(DP_A) & DP_DETECTED) == 0) | 15402 | if ((I915_READ(DP_A) & DP_DETECTED) == 0) |
| 15286 | return false; | 15403 | return false; |
| 15287 | 15404 | ||
| 15288 | if (IS_GEN5(dev) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE)) | 15405 | if (IS_GEN5(dev_priv) && (I915_READ(FUSE_STRAP) & ILK_eDP_A_DISABLE)) |
| 15289 | return false; | 15406 | return false; |
| 15290 | 15407 | ||
| 15291 | return true; | 15408 | return true; |
| @@ -15298,17 +15415,18 @@ static bool intel_crt_present(struct drm_device *dev) | |||
| 15298 | if (INTEL_INFO(dev)->gen >= 9) | 15415 | if (INTEL_INFO(dev)->gen >= 9) |
| 15299 | return false; | 15416 | return false; |
| 15300 | 15417 | ||
| 15301 | if (IS_HSW_ULT(dev) || IS_BDW_ULT(dev)) | 15418 | if (IS_HSW_ULT(dev_priv) || IS_BDW_ULT(dev_priv)) |
| 15302 | return false; | 15419 | return false; |
| 15303 | 15420 | ||
| 15304 | if (IS_CHERRYVIEW(dev)) | 15421 | if (IS_CHERRYVIEW(dev_priv)) |
| 15305 | return false; | 15422 | return false; |
| 15306 | 15423 | ||
| 15307 | if (HAS_PCH_LPT_H(dev) && I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED) | 15424 | if (HAS_PCH_LPT_H(dev_priv) && |
| 15425 | I915_READ(SFUSE_STRAP) & SFUSE_STRAP_CRT_DISABLED) | ||
| 15308 | return false; | 15426 | return false; |
| 15309 | 15427 | ||
| 15310 | /* DDI E can't be used if DDI A requires 4 lanes */ | 15428 | /* DDI E can't be used if DDI A requires 4 lanes */ |
| 15311 | if (HAS_DDI(dev) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) | 15429 | if (HAS_DDI(dev_priv) && I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_A_4_LANES) |
| 15312 | return false; | 15430 | return false; |
| 15313 | 15431 | ||
| 15314 | if (!dev_priv->vbt.int_crt_support) | 15432 | if (!dev_priv->vbt.int_crt_support) |
| @@ -15371,7 +15489,7 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 15371 | if (intel_crt_present(dev)) | 15489 | if (intel_crt_present(dev)) |
| 15372 | intel_crt_init(dev); | 15490 | intel_crt_init(dev); |
| 15373 | 15491 | ||
| 15374 | if (IS_BROXTON(dev)) { | 15492 | if (IS_BROXTON(dev_priv)) { |
| 15375 | /* | 15493 | /* |
| 15376 | * FIXME: Broxton doesn't support port detection via the | 15494 | * FIXME: Broxton doesn't support port detection via the |
| 15377 | * DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to | 15495 | * DDI_BUF_CTL_A or SFUSE_STRAP registers, find another way to |
| @@ -15382,7 +15500,7 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 15382 | intel_ddi_init(dev, PORT_C); | 15500 | intel_ddi_init(dev, PORT_C); |
| 15383 | 15501 | ||
| 15384 | intel_dsi_init(dev); | 15502 | intel_dsi_init(dev); |
| 15385 | } else if (HAS_DDI(dev)) { | 15503 | } else if (HAS_DDI(dev_priv)) { |
| 15386 | int found; | 15504 | int found; |
| 15387 | 15505 | ||
| 15388 | /* | 15506 | /* |
| @@ -15392,7 +15510,7 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 15392 | */ | 15510 | */ |
| 15393 | found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED; | 15511 | found = I915_READ(DDI_BUF_CTL(PORT_A)) & DDI_INIT_DISPLAY_DETECTED; |
| 15394 | /* WaIgnoreDDIAStrap: skl */ | 15512 | /* WaIgnoreDDIAStrap: skl */ |
| 15395 | if (found || IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) | 15513 | if (found || IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
| 15396 | intel_ddi_init(dev, PORT_A); | 15514 | intel_ddi_init(dev, PORT_A); |
| 15397 | 15515 | ||
| 15398 | /* DDI B, C and D detection is indicated by the SFUSE_STRAP | 15516 | /* DDI B, C and D detection is indicated by the SFUSE_STRAP |
| @@ -15408,13 +15526,13 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 15408 | /* | 15526 | /* |
| 15409 | * On SKL we don't have a way to detect DDI-E so we rely on VBT. | 15527 | * On SKL we don't have a way to detect DDI-E so we rely on VBT. |
| 15410 | */ | 15528 | */ |
| 15411 | if ((IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) && | 15529 | if ((IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) && |
| 15412 | (dev_priv->vbt.ddi_port_info[PORT_E].supports_dp || | 15530 | (dev_priv->vbt.ddi_port_info[PORT_E].supports_dp || |
| 15413 | dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi || | 15531 | dev_priv->vbt.ddi_port_info[PORT_E].supports_dvi || |
| 15414 | dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi)) | 15532 | dev_priv->vbt.ddi_port_info[PORT_E].supports_hdmi)) |
| 15415 | intel_ddi_init(dev, PORT_E); | 15533 | intel_ddi_init(dev, PORT_E); |
| 15416 | 15534 | ||
| 15417 | } else if (HAS_PCH_SPLIT(dev)) { | 15535 | } else if (HAS_PCH_SPLIT(dev_priv)) { |
| 15418 | int found; | 15536 | int found; |
| 15419 | dpd_is_edp = intel_dp_is_edp(dev, PORT_D); | 15537 | dpd_is_edp = intel_dp_is_edp(dev, PORT_D); |
| 15420 | 15538 | ||
| @@ -15441,7 +15559,7 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 15441 | 15559 | ||
| 15442 | if (I915_READ(PCH_DP_D) & DP_DETECTED) | 15560 | if (I915_READ(PCH_DP_D) & DP_DETECTED) |
| 15443 | intel_dp_init(dev, PCH_DP_D, PORT_D); | 15561 | intel_dp_init(dev, PCH_DP_D, PORT_D); |
| 15444 | } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 15562 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 15445 | bool has_edp, has_port; | 15563 | bool has_edp, has_port; |
| 15446 | 15564 | ||
| 15447 | /* | 15565 | /* |
| @@ -15473,7 +15591,7 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 15473 | if ((I915_READ(VLV_HDMIC) & SDVO_DETECTED || has_port) && !has_edp) | 15591 | if ((I915_READ(VLV_HDMIC) & SDVO_DETECTED || has_port) && !has_edp) |
| 15474 | intel_hdmi_init(dev, VLV_HDMIC, PORT_C); | 15592 | intel_hdmi_init(dev, VLV_HDMIC, PORT_C); |
| 15475 | 15593 | ||
| 15476 | if (IS_CHERRYVIEW(dev)) { | 15594 | if (IS_CHERRYVIEW(dev_priv)) { |
| 15477 | /* | 15595 | /* |
| 15478 | * eDP not supported on port D, | 15596 | * eDP not supported on port D, |
| 15479 | * so no need to worry about it | 15597 | * so no need to worry about it |
| @@ -15486,18 +15604,18 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 15486 | } | 15604 | } |
| 15487 | 15605 | ||
| 15488 | intel_dsi_init(dev); | 15606 | intel_dsi_init(dev); |
| 15489 | } else if (!IS_GEN2(dev) && !IS_PINEVIEW(dev)) { | 15607 | } else if (!IS_GEN2(dev_priv) && !IS_PINEVIEW(dev_priv)) { |
| 15490 | bool found = false; | 15608 | bool found = false; |
| 15491 | 15609 | ||
| 15492 | if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) { | 15610 | if (I915_READ(GEN3_SDVOB) & SDVO_DETECTED) { |
| 15493 | DRM_DEBUG_KMS("probing SDVOB\n"); | 15611 | DRM_DEBUG_KMS("probing SDVOB\n"); |
| 15494 | found = intel_sdvo_init(dev, GEN3_SDVOB, PORT_B); | 15612 | found = intel_sdvo_init(dev, GEN3_SDVOB, PORT_B); |
| 15495 | if (!found && IS_G4X(dev)) { | 15613 | if (!found && IS_G4X(dev_priv)) { |
| 15496 | DRM_DEBUG_KMS("probing HDMI on SDVOB\n"); | 15614 | DRM_DEBUG_KMS("probing HDMI on SDVOB\n"); |
| 15497 | intel_hdmi_init(dev, GEN4_HDMIB, PORT_B); | 15615 | intel_hdmi_init(dev, GEN4_HDMIB, PORT_B); |
| 15498 | } | 15616 | } |
| 15499 | 15617 | ||
| 15500 | if (!found && IS_G4X(dev)) | 15618 | if (!found && IS_G4X(dev_priv)) |
| 15501 | intel_dp_init(dev, DP_B, PORT_B); | 15619 | intel_dp_init(dev, DP_B, PORT_B); |
| 15502 | } | 15620 | } |
| 15503 | 15621 | ||
| @@ -15510,18 +15628,17 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
| 15510 | 15628 | ||
| 15511 | if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) { | 15629 | if (!found && (I915_READ(GEN3_SDVOC) & SDVO_DETECTED)) { |
| 15512 | 15630 | ||
| 15513 | if (IS_G4X(dev)) { | 15631 | if (IS_G4X(dev_priv)) { |
| 15514 | DRM_DEBUG_KMS("probing HDMI on SDVOC\n"); | 15632 | DRM_DEBUG_KMS("probing HDMI on SDVOC\n"); |
| 15515 | intel_hdmi_init(dev, GEN4_HDMIC, PORT_C); | 15633 | intel_hdmi_init(dev, GEN4_HDMIC, PORT_C); |
| 15516 | } | 15634 | } |
| 15517 | if (IS_G4X(dev)) | 15635 | if (IS_G4X(dev_priv)) |
| 15518 | intel_dp_init(dev, DP_C, PORT_C); | 15636 | intel_dp_init(dev, DP_C, PORT_C); |
| 15519 | } | 15637 | } |
| 15520 | 15638 | ||
| 15521 | if (IS_G4X(dev) && | 15639 | if (IS_G4X(dev_priv) && (I915_READ(DP_D) & DP_DETECTED)) |
| 15522 | (I915_READ(DP_D) & DP_DETECTED)) | ||
| 15523 | intel_dp_init(dev, DP_D, PORT_D); | 15640 | intel_dp_init(dev, DP_D, PORT_D); |
| 15524 | } else if (IS_GEN2(dev)) | 15641 | } else if (IS_GEN2(dev_priv)) |
| 15525 | intel_dvo_init(dev); | 15642 | intel_dvo_init(dev); |
| 15526 | 15643 | ||
| 15527 | if (SUPPORTS_TV(dev)) | 15644 | if (SUPPORTS_TV(dev)) |
| @@ -15592,10 +15709,10 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = { | |||
| 15592 | }; | 15709 | }; |
| 15593 | 15710 | ||
| 15594 | static | 15711 | static |
| 15595 | u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier, | 15712 | u32 intel_fb_pitch_limit(struct drm_i915_private *dev_priv, |
| 15596 | uint32_t pixel_format) | 15713 | uint64_t fb_modifier, uint32_t pixel_format) |
| 15597 | { | 15714 | { |
| 15598 | u32 gen = INTEL_INFO(dev)->gen; | 15715 | u32 gen = INTEL_INFO(dev_priv)->gen; |
| 15599 | 15716 | ||
| 15600 | if (gen >= 9) { | 15717 | if (gen >= 9) { |
| 15601 | int cpp = drm_format_plane_cpp(pixel_format, 0); | 15718 | int cpp = drm_format_plane_cpp(pixel_format, 0); |
| @@ -15604,7 +15721,8 @@ u32 intel_fb_pitch_limit(struct drm_device *dev, uint64_t fb_modifier, | |||
| 15604 | * pixels and 32K bytes." | 15721 | * pixels and 32K bytes." |
| 15605 | */ | 15722 | */ |
| 15606 | return min(8192 * cpp, 32768); | 15723 | return min(8192 * cpp, 32768); |
| 15607 | } else if (gen >= 5 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { | 15724 | } else if (gen >= 5 && !IS_VALLEYVIEW(dev_priv) && |
| 15725 | !IS_CHERRYVIEW(dev_priv)) { | ||
| 15608 | return 32*1024; | 15726 | return 32*1024; |
| 15609 | } else if (gen >= 4) { | 15727 | } else if (gen >= 4) { |
| 15610 | if (fb_modifier == I915_FORMAT_MOD_X_TILED) | 15728 | if (fb_modifier == I915_FORMAT_MOD_X_TILED) |
| @@ -15691,7 +15809,7 @@ static int intel_framebuffer_init(struct drm_device *dev, | |||
| 15691 | return -EINVAL; | 15809 | return -EINVAL; |
| 15692 | } | 15810 | } |
| 15693 | 15811 | ||
| 15694 | pitch_limit = intel_fb_pitch_limit(dev, mode_cmd->modifier[0], | 15812 | pitch_limit = intel_fb_pitch_limit(dev_priv, mode_cmd->modifier[0], |
| 15695 | mode_cmd->pixel_format); | 15813 | mode_cmd->pixel_format); |
| 15696 | if (mode_cmd->pitches[0] > pitch_limit) { | 15814 | if (mode_cmd->pitches[0] > pitch_limit) { |
| 15697 | DRM_DEBUG("%s pitch (%u) must be at less than %d\n", | 15815 | DRM_DEBUG("%s pitch (%u) must be at less than %d\n", |
| @@ -15729,7 +15847,7 @@ static int intel_framebuffer_init(struct drm_device *dev, | |||
| 15729 | } | 15847 | } |
| 15730 | break; | 15848 | break; |
| 15731 | case DRM_FORMAT_ABGR8888: | 15849 | case DRM_FORMAT_ABGR8888: |
| 15732 | if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && | 15850 | if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) && |
| 15733 | INTEL_INFO(dev)->gen < 9) { | 15851 | INTEL_INFO(dev)->gen < 9) { |
| 15734 | format_name = drm_get_format_name(mode_cmd->pixel_format); | 15852 | format_name = drm_get_format_name(mode_cmd->pixel_format); |
| 15735 | DRM_DEBUG("unsupported pixel format: %s\n", format_name); | 15853 | DRM_DEBUG("unsupported pixel format: %s\n", format_name); |
| @@ -15748,7 +15866,7 @@ static int intel_framebuffer_init(struct drm_device *dev, | |||
| 15748 | } | 15866 | } |
| 15749 | break; | 15867 | break; |
| 15750 | case DRM_FORMAT_ABGR2101010: | 15868 | case DRM_FORMAT_ABGR2101010: |
| 15751 | if (!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev)) { | 15869 | if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) { |
| 15752 | format_name = drm_get_format_name(mode_cmd->pixel_format); | 15870 | format_name = drm_get_format_name(mode_cmd->pixel_format); |
| 15753 | DRM_DEBUG("unsupported pixel format: %s\n", format_name); | 15871 | DRM_DEBUG("unsupported pixel format: %s\n", format_name); |
| 15754 | kfree(format_name); | 15872 | kfree(format_name); |
| @@ -15815,12 +15933,6 @@ intel_user_framebuffer_create(struct drm_device *dev, | |||
| 15815 | return fb; | 15933 | return fb; |
| 15816 | } | 15934 | } |
| 15817 | 15935 | ||
| 15818 | #ifndef CONFIG_DRM_FBDEV_EMULATION | ||
| 15819 | static inline void intel_fbdev_output_poll_changed(struct drm_device *dev) | ||
| 15820 | { | ||
| 15821 | } | ||
| 15822 | #endif | ||
| 15823 | |||
| 15824 | static const struct drm_mode_config_funcs intel_mode_funcs = { | 15936 | static const struct drm_mode_config_funcs intel_mode_funcs = { |
| 15825 | .fb_create = intel_user_framebuffer_create, | 15937 | .fb_create = intel_user_framebuffer_create, |
| 15826 | .output_poll_changed = intel_fbdev_output_poll_changed, | 15938 | .output_poll_changed = intel_fbdev_output_poll_changed, |
| @@ -16201,7 +16313,7 @@ static void i915_disable_vga(struct drm_device *dev) | |||
| 16201 | struct drm_i915_private *dev_priv = to_i915(dev); | 16313 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 16202 | struct pci_dev *pdev = dev_priv->drm.pdev; | 16314 | struct pci_dev *pdev = dev_priv->drm.pdev; |
| 16203 | u8 sr1; | 16315 | u8 sr1; |
| 16204 | i915_reg_t vga_reg = i915_vgacntrl_reg(dev); | 16316 | i915_reg_t vga_reg = i915_vgacntrl_reg(dev_priv); |
| 16205 | 16317 | ||
| 16206 | /* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */ | 16318 | /* WaEnableVGAAccessThroughIOPort:ctg,elk,ilk,snb,ivb,vlv,hsw */ |
| 16207 | vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); | 16319 | vga_get_uninterruptible(pdev, VGA_RSRC_LEGACY_IO); |
| @@ -16340,7 +16452,7 @@ void intel_modeset_init(struct drm_device *dev) | |||
| 16340 | * BIOS isn't using it, don't assume it will work even if the VBT | 16452 | * BIOS isn't using it, don't assume it will work even if the VBT |
| 16341 | * indicates as much. | 16453 | * indicates as much. |
| 16342 | */ | 16454 | */ |
| 16343 | if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { | 16455 | if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) { |
| 16344 | bool bios_lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) & | 16456 | bool bios_lvds_use_ssc = !!(I915_READ(PCH_DREF_CONTROL) & |
| 16345 | DREF_SSC1_ENABLE); | 16457 | DREF_SSC1_ENABLE); |
| 16346 | 16458 | ||
| @@ -16352,10 +16464,10 @@ void intel_modeset_init(struct drm_device *dev) | |||
| 16352 | } | 16464 | } |
| 16353 | } | 16465 | } |
| 16354 | 16466 | ||
| 16355 | if (IS_GEN2(dev)) { | 16467 | if (IS_GEN2(dev_priv)) { |
| 16356 | dev->mode_config.max_width = 2048; | 16468 | dev->mode_config.max_width = 2048; |
| 16357 | dev->mode_config.max_height = 2048; | 16469 | dev->mode_config.max_height = 2048; |
| 16358 | } else if (IS_GEN3(dev)) { | 16470 | } else if (IS_GEN3(dev_priv)) { |
| 16359 | dev->mode_config.max_width = 4096; | 16471 | dev->mode_config.max_width = 4096; |
| 16360 | dev->mode_config.max_height = 4096; | 16472 | dev->mode_config.max_height = 4096; |
| 16361 | } else { | 16473 | } else { |
| @@ -16363,10 +16475,10 @@ void intel_modeset_init(struct drm_device *dev) | |||
| 16363 | dev->mode_config.max_height = 8192; | 16475 | dev->mode_config.max_height = 8192; |
| 16364 | } | 16476 | } |
| 16365 | 16477 | ||
| 16366 | if (IS_845G(dev) || IS_I865G(dev)) { | 16478 | if (IS_845G(dev_priv) || IS_I865G(dev_priv)) { |
| 16367 | dev->mode_config.cursor_width = IS_845G(dev) ? 64 : 512; | 16479 | dev->mode_config.cursor_width = IS_845G(dev_priv) ? 64 : 512; |
| 16368 | dev->mode_config.cursor_height = 1023; | 16480 | dev->mode_config.cursor_height = 1023; |
| 16369 | } else if (IS_GEN2(dev)) { | 16481 | } else if (IS_GEN2(dev_priv)) { |
| 16370 | dev->mode_config.cursor_width = GEN2_CURSOR_WIDTH; | 16482 | dev->mode_config.cursor_width = GEN2_CURSOR_WIDTH; |
| 16371 | dev->mode_config.cursor_height = GEN2_CURSOR_HEIGHT; | 16483 | dev->mode_config.cursor_height = GEN2_CURSOR_HEIGHT; |
| 16372 | } else { | 16484 | } else { |
| @@ -16572,7 +16684,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) | |||
| 16572 | if (crtc->active && !intel_crtc_has_encoders(crtc)) | 16684 | if (crtc->active && !intel_crtc_has_encoders(crtc)) |
| 16573 | intel_crtc_disable_noatomic(&crtc->base); | 16685 | intel_crtc_disable_noatomic(&crtc->base); |
| 16574 | 16686 | ||
| 16575 | if (crtc->active || HAS_GMCH_DISPLAY(dev)) { | 16687 | if (crtc->active || HAS_GMCH_DISPLAY(dev_priv)) { |
| 16576 | /* | 16688 | /* |
| 16577 | * We start out with underrun reporting disabled to avoid races. | 16689 | * We start out with underrun reporting disabled to avoid races. |
| 16578 | * For correct bookkeeping mark this on active crtcs. | 16690 | * For correct bookkeeping mark this on active crtcs. |
| @@ -16647,7 +16759,7 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder) | |||
| 16647 | void i915_redisable_vga_power_on(struct drm_device *dev) | 16759 | void i915_redisable_vga_power_on(struct drm_device *dev) |
| 16648 | { | 16760 | { |
| 16649 | struct drm_i915_private *dev_priv = to_i915(dev); | 16761 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 16650 | i915_reg_t vga_reg = i915_vgacntrl_reg(dev); | 16762 | i915_reg_t vga_reg = i915_vgacntrl_reg(dev_priv); |
| 16651 | 16763 | ||
| 16652 | if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) { | 16764 | if (!(I915_READ(vga_reg) & VGA_DISP_DISABLE)) { |
| 16653 | DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); | 16765 | DRM_DEBUG_KMS("Something enabled VGA plane, disabling it\n"); |
| @@ -16885,11 +16997,11 @@ intel_modeset_setup_hw_state(struct drm_device *dev) | |||
| 16885 | pll->on = false; | 16997 | pll->on = false; |
| 16886 | } | 16998 | } |
| 16887 | 16999 | ||
| 16888 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 17000 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 16889 | vlv_wm_get_hw_state(dev); | 17001 | vlv_wm_get_hw_state(dev); |
| 16890 | else if (IS_GEN9(dev)) | 17002 | else if (IS_GEN9(dev_priv)) |
| 16891 | skl_wm_get_hw_state(dev); | 17003 | skl_wm_get_hw_state(dev); |
| 16892 | else if (HAS_PCH_SPLIT(dev)) | 17004 | else if (HAS_PCH_SPLIT(dev_priv)) |
| 16893 | ilk_wm_get_hw_state(dev); | 17005 | ilk_wm_get_hw_state(dev); |
| 16894 | 17006 | ||
| 16895 | for_each_intel_crtc(dev, crtc) { | 17007 | for_each_intel_crtc(dev, crtc) { |
| @@ -17080,6 +17192,8 @@ int intel_modeset_vga_set_state(struct drm_device *dev, bool state) | |||
| 17080 | return 0; | 17192 | return 0; |
| 17081 | } | 17193 | } |
| 17082 | 17194 | ||
| 17195 | #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) | ||
| 17196 | |||
| 17083 | struct intel_display_error_state { | 17197 | struct intel_display_error_state { |
| 17084 | 17198 | ||
| 17085 | u32 power_well_driver; | 17199 | u32 power_well_driver; |
| @@ -17218,7 +17332,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, | |||
| 17218 | return; | 17332 | return; |
| 17219 | 17333 | ||
| 17220 | err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes); | 17334 | err_printf(m, "Num Pipes: %d\n", INTEL_INFO(dev)->num_pipes); |
| 17221 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 17335 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 17222 | err_printf(m, "PWR_WELL_CTL2: %08x\n", | 17336 | err_printf(m, "PWR_WELL_CTL2: %08x\n", |
| 17223 | error->power_well_driver); | 17337 | error->power_well_driver); |
| 17224 | for_each_pipe(dev_priv, i) { | 17338 | for_each_pipe(dev_priv, i) { |
| @@ -17235,7 +17349,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, | |||
| 17235 | err_printf(m, " SIZE: %08x\n", error->plane[i].size); | 17349 | err_printf(m, " SIZE: %08x\n", error->plane[i].size); |
| 17236 | err_printf(m, " POS: %08x\n", error->plane[i].pos); | 17350 | err_printf(m, " POS: %08x\n", error->plane[i].pos); |
| 17237 | } | 17351 | } |
| 17238 | if (INTEL_INFO(dev)->gen <= 7 && !IS_HASWELL(dev)) | 17352 | if (INTEL_GEN(dev_priv) <= 7 && !IS_HASWELL(dev_priv)) |
| 17239 | err_printf(m, " ADDR: %08x\n", error->plane[i].addr); | 17353 | err_printf(m, " ADDR: %08x\n", error->plane[i].addr); |
| 17240 | if (INTEL_INFO(dev)->gen >= 4) { | 17354 | if (INTEL_INFO(dev)->gen >= 4) { |
| 17241 | err_printf(m, " SURF: %08x\n", error->plane[i].surface); | 17355 | err_printf(m, " SURF: %08x\n", error->plane[i].surface); |
| @@ -17262,3 +17376,5 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, | |||
| 17262 | err_printf(m, " VSYNC: %08x\n", error->transcoder[i].vsync); | 17376 | err_printf(m, " VSYNC: %08x\n", error->transcoder[i].vsync); |
| 17263 | } | 17377 | } |
| 17264 | } | 17378 | } |
| 17379 | |||
| 17380 | #endif | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 01bc67194dba..3c2293bd24bf 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -344,7 +344,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) | |||
| 344 | DP |= DP_PORT_WIDTH(1); | 344 | DP |= DP_PORT_WIDTH(1); |
| 345 | DP |= DP_LINK_TRAIN_PAT_1; | 345 | DP |= DP_LINK_TRAIN_PAT_1; |
| 346 | 346 | ||
| 347 | if (IS_CHERRYVIEW(dev)) | 347 | if (IS_CHERRYVIEW(dev_priv)) |
| 348 | DP |= DP_PIPE_SELECT_CHV(pipe); | 348 | DP |= DP_PIPE_SELECT_CHV(pipe); |
| 349 | else if (pipe == PIPE_B) | 349 | else if (pipe == PIPE_B) |
| 350 | DP |= DP_PIPEB_SELECT; | 350 | DP |= DP_PIPEB_SELECT; |
| @@ -356,10 +356,10 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp) | |||
| 356 | * So enable temporarily it if it's not already enabled. | 356 | * So enable temporarily it if it's not already enabled. |
| 357 | */ | 357 | */ |
| 358 | if (!pll_enabled) { | 358 | if (!pll_enabled) { |
| 359 | release_cl_override = IS_CHERRYVIEW(dev) && | 359 | release_cl_override = IS_CHERRYVIEW(dev_priv) && |
| 360 | !chv_phy_powergate_ch(dev_priv, phy, ch, true); | 360 | !chv_phy_powergate_ch(dev_priv, phy, ch, true); |
| 361 | 361 | ||
| 362 | if (vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev) ? | 362 | if (vlv_force_pll_on(dev, pipe, IS_CHERRYVIEW(dev_priv) ? |
| 363 | &chv_dpll[0].dpll : &vlv_dpll[0].dpll)) { | 363 | &chv_dpll[0].dpll : &vlv_dpll[0].dpll)) { |
| 364 | DRM_ERROR("Failed to force on pll for pipe %c!\n", | 364 | DRM_ERROR("Failed to force on pll for pipe %c!\n", |
| 365 | pipe_name(pipe)); | 365 | pipe_name(pipe)); |
| @@ -570,8 +570,8 @@ void intel_power_sequencer_reset(struct drm_i915_private *dev_priv) | |||
| 570 | struct drm_device *dev = &dev_priv->drm; | 570 | struct drm_device *dev = &dev_priv->drm; |
| 571 | struct intel_encoder *encoder; | 571 | struct intel_encoder *encoder; |
| 572 | 572 | ||
| 573 | if (WARN_ON(!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && | 573 | if (WARN_ON(!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) && |
| 574 | !IS_BROXTON(dev))) | 574 | !IS_BROXTON(dev_priv))) |
| 575 | return; | 575 | return; |
| 576 | 576 | ||
| 577 | /* | 577 | /* |
| @@ -591,7 +591,7 @@ void intel_power_sequencer_reset(struct drm_i915_private *dev_priv) | |||
| 591 | continue; | 591 | continue; |
| 592 | 592 | ||
| 593 | intel_dp = enc_to_intel_dp(&encoder->base); | 593 | intel_dp = enc_to_intel_dp(&encoder->base); |
| 594 | if (IS_BROXTON(dev)) | 594 | if (IS_BROXTON(dev_priv)) |
| 595 | intel_dp->pps_reset = true; | 595 | intel_dp->pps_reset = true; |
| 596 | else | 596 | else |
| 597 | intel_dp->pps_pipe = INVALID_PIPE; | 597 | intel_dp->pps_pipe = INVALID_PIPE; |
| @@ -664,7 +664,7 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code, | |||
| 664 | 664 | ||
| 665 | pps_lock(intel_dp); | 665 | pps_lock(intel_dp); |
| 666 | 666 | ||
| 667 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 667 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 668 | enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); | 668 | enum pipe pipe = vlv_power_sequencer_pipe(intel_dp); |
| 669 | i915_reg_t pp_ctrl_reg, pp_div_reg; | 669 | i915_reg_t pp_ctrl_reg, pp_div_reg; |
| 670 | u32 pp_div; | 670 | u32 pp_div; |
| @@ -692,7 +692,7 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp) | |||
| 692 | 692 | ||
| 693 | lockdep_assert_held(&dev_priv->pps_mutex); | 693 | lockdep_assert_held(&dev_priv->pps_mutex); |
| 694 | 694 | ||
| 695 | if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && | 695 | if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && |
| 696 | intel_dp->pps_pipe == INVALID_PIPE) | 696 | intel_dp->pps_pipe == INVALID_PIPE) |
| 697 | return false; | 697 | return false; |
| 698 | 698 | ||
| @@ -706,7 +706,7 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp) | |||
| 706 | 706 | ||
| 707 | lockdep_assert_held(&dev_priv->pps_mutex); | 707 | lockdep_assert_held(&dev_priv->pps_mutex); |
| 708 | 708 | ||
| 709 | if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && | 709 | if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && |
| 710 | intel_dp->pps_pipe == INVALID_PIPE) | 710 | intel_dp->pps_pipe == INVALID_PIPE) |
| 711 | return false; | 711 | return false; |
| 712 | 712 | ||
| @@ -821,15 +821,16 @@ static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp, | |||
| 821 | uint32_t aux_clock_divider) | 821 | uint32_t aux_clock_divider) |
| 822 | { | 822 | { |
| 823 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | 823 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 824 | struct drm_device *dev = intel_dig_port->base.base.dev; | 824 | struct drm_i915_private *dev_priv = |
| 825 | to_i915(intel_dig_port->base.base.dev); | ||
| 825 | uint32_t precharge, timeout; | 826 | uint32_t precharge, timeout; |
| 826 | 827 | ||
| 827 | if (IS_GEN6(dev)) | 828 | if (IS_GEN6(dev_priv)) |
| 828 | precharge = 3; | 829 | precharge = 3; |
| 829 | else | 830 | else |
| 830 | precharge = 5; | 831 | precharge = 5; |
| 831 | 832 | ||
| 832 | if (IS_BROADWELL(dev) && intel_dig_port->port == PORT_A) | 833 | if (IS_BROADWELL(dev_priv) && intel_dig_port->port == PORT_A) |
| 833 | timeout = DP_AUX_CH_CTL_TIME_OUT_600us; | 834 | timeout = DP_AUX_CH_CTL_TIME_OUT_600us; |
| 834 | else | 835 | else |
| 835 | timeout = DP_AUX_CH_CTL_TIME_OUT_400us; | 836 | timeout = DP_AUX_CH_CTL_TIME_OUT_400us; |
| @@ -1108,8 +1109,46 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) | |||
| 1108 | return ret; | 1109 | return ret; |
| 1109 | } | 1110 | } |
| 1110 | 1111 | ||
| 1112 | static enum port intel_aux_port(struct drm_i915_private *dev_priv, | ||
| 1113 | enum port port) | ||
| 1114 | { | ||
| 1115 | const struct ddi_vbt_port_info *info = | ||
| 1116 | &dev_priv->vbt.ddi_port_info[port]; | ||
| 1117 | enum port aux_port; | ||
| 1118 | |||
| 1119 | if (!info->alternate_aux_channel) { | ||
| 1120 | DRM_DEBUG_KMS("using AUX %c for port %c (platform default)\n", | ||
| 1121 | port_name(port), port_name(port)); | ||
| 1122 | return port; | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | switch (info->alternate_aux_channel) { | ||
| 1126 | case DP_AUX_A: | ||
| 1127 | aux_port = PORT_A; | ||
| 1128 | break; | ||
| 1129 | case DP_AUX_B: | ||
| 1130 | aux_port = PORT_B; | ||
| 1131 | break; | ||
| 1132 | case DP_AUX_C: | ||
| 1133 | aux_port = PORT_C; | ||
| 1134 | break; | ||
| 1135 | case DP_AUX_D: | ||
| 1136 | aux_port = PORT_D; | ||
| 1137 | break; | ||
| 1138 | default: | ||
| 1139 | MISSING_CASE(info->alternate_aux_channel); | ||
| 1140 | aux_port = PORT_A; | ||
| 1141 | break; | ||
| 1142 | } | ||
| 1143 | |||
| 1144 | DRM_DEBUG_KMS("using AUX %c for port %c (VBT)\n", | ||
| 1145 | port_name(aux_port), port_name(port)); | ||
| 1146 | |||
| 1147 | return aux_port; | ||
| 1148 | } | ||
| 1149 | |||
| 1111 | static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv, | 1150 | static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv, |
| 1112 | enum port port) | 1151 | enum port port) |
| 1113 | { | 1152 | { |
| 1114 | switch (port) { | 1153 | switch (port) { |
| 1115 | case PORT_B: | 1154 | case PORT_B: |
| @@ -1123,7 +1162,7 @@ static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv, | |||
| 1123 | } | 1162 | } |
| 1124 | 1163 | ||
| 1125 | static i915_reg_t g4x_aux_data_reg(struct drm_i915_private *dev_priv, | 1164 | static i915_reg_t g4x_aux_data_reg(struct drm_i915_private *dev_priv, |
| 1126 | enum port port, int index) | 1165 | enum port port, int index) |
| 1127 | { | 1166 | { |
| 1128 | switch (port) { | 1167 | switch (port) { |
| 1129 | case PORT_B: | 1168 | case PORT_B: |
| @@ -1137,7 +1176,7 @@ static i915_reg_t g4x_aux_data_reg(struct drm_i915_private *dev_priv, | |||
| 1137 | } | 1176 | } |
| 1138 | 1177 | ||
| 1139 | static i915_reg_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv, | 1178 | static i915_reg_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv, |
| 1140 | enum port port) | 1179 | enum port port) |
| 1141 | { | 1180 | { |
| 1142 | switch (port) { | 1181 | switch (port) { |
| 1143 | case PORT_A: | 1182 | case PORT_A: |
| @@ -1153,7 +1192,7 @@ static i915_reg_t ilk_aux_ctl_reg(struct drm_i915_private *dev_priv, | |||
| 1153 | } | 1192 | } |
| 1154 | 1193 | ||
| 1155 | static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv, | 1194 | static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv, |
| 1156 | enum port port, int index) | 1195 | enum port port, int index) |
| 1157 | { | 1196 | { |
| 1158 | switch (port) { | 1197 | switch (port) { |
| 1159 | case PORT_A: | 1198 | case PORT_A: |
| @@ -1168,36 +1207,9 @@ static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv, | |||
| 1168 | } | 1207 | } |
| 1169 | } | 1208 | } |
| 1170 | 1209 | ||
| 1171 | /* | ||
| 1172 | * On SKL we don't have Aux for port E so we rely | ||
| 1173 | * on VBT to set a proper alternate aux channel. | ||
| 1174 | */ | ||
| 1175 | static enum port skl_porte_aux_port(struct drm_i915_private *dev_priv) | ||
| 1176 | { | ||
| 1177 | const struct ddi_vbt_port_info *info = | ||
| 1178 | &dev_priv->vbt.ddi_port_info[PORT_E]; | ||
| 1179 | |||
| 1180 | switch (info->alternate_aux_channel) { | ||
| 1181 | case DP_AUX_A: | ||
| 1182 | return PORT_A; | ||
| 1183 | case DP_AUX_B: | ||
| 1184 | return PORT_B; | ||
| 1185 | case DP_AUX_C: | ||
| 1186 | return PORT_C; | ||
| 1187 | case DP_AUX_D: | ||
| 1188 | return PORT_D; | ||
| 1189 | default: | ||
| 1190 | MISSING_CASE(info->alternate_aux_channel); | ||
| 1191 | return PORT_A; | ||
| 1192 | } | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv, | 1210 | static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv, |
| 1196 | enum port port) | 1211 | enum port port) |
| 1197 | { | 1212 | { |
| 1198 | if (port == PORT_E) | ||
| 1199 | port = skl_porte_aux_port(dev_priv); | ||
| 1200 | |||
| 1201 | switch (port) { | 1213 | switch (port) { |
| 1202 | case PORT_A: | 1214 | case PORT_A: |
| 1203 | case PORT_B: | 1215 | case PORT_B: |
| @@ -1211,11 +1223,8 @@ static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv, | |||
| 1211 | } | 1223 | } |
| 1212 | 1224 | ||
| 1213 | static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv, | 1225 | static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv, |
| 1214 | enum port port, int index) | 1226 | enum port port, int index) |
| 1215 | { | 1227 | { |
| 1216 | if (port == PORT_E) | ||
| 1217 | port = skl_porte_aux_port(dev_priv); | ||
| 1218 | |||
| 1219 | switch (port) { | 1228 | switch (port) { |
| 1220 | case PORT_A: | 1229 | case PORT_A: |
| 1221 | case PORT_B: | 1230 | case PORT_B: |
| @@ -1229,7 +1238,7 @@ static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv, | |||
| 1229 | } | 1238 | } |
| 1230 | 1239 | ||
| 1231 | static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv, | 1240 | static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv, |
| 1232 | enum port port) | 1241 | enum port port) |
| 1233 | { | 1242 | { |
| 1234 | if (INTEL_INFO(dev_priv)->gen >= 9) | 1243 | if (INTEL_INFO(dev_priv)->gen >= 9) |
| 1235 | return skl_aux_ctl_reg(dev_priv, port); | 1244 | return skl_aux_ctl_reg(dev_priv, port); |
| @@ -1240,7 +1249,7 @@ static i915_reg_t intel_aux_ctl_reg(struct drm_i915_private *dev_priv, | |||
| 1240 | } | 1249 | } |
| 1241 | 1250 | ||
| 1242 | static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv, | 1251 | static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv, |
| 1243 | enum port port, int index) | 1252 | enum port port, int index) |
| 1244 | { | 1253 | { |
| 1245 | if (INTEL_INFO(dev_priv)->gen >= 9) | 1254 | if (INTEL_INFO(dev_priv)->gen >= 9) |
| 1246 | return skl_aux_data_reg(dev_priv, port, index); | 1255 | return skl_aux_data_reg(dev_priv, port, index); |
| @@ -1253,7 +1262,8 @@ static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv, | |||
| 1253 | static void intel_aux_reg_init(struct intel_dp *intel_dp) | 1262 | static void intel_aux_reg_init(struct intel_dp *intel_dp) |
| 1254 | { | 1263 | { |
| 1255 | struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); | 1264 | struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); |
| 1256 | enum port port = dp_to_dig_port(intel_dp)->port; | 1265 | enum port port = intel_aux_port(dev_priv, |
| 1266 | dp_to_dig_port(intel_dp)->port); | ||
| 1257 | int i; | 1267 | int i; |
| 1258 | 1268 | ||
| 1259 | intel_dp->aux_ch_ctl_reg = intel_aux_ctl_reg(dev_priv, port); | 1269 | intel_dp->aux_ch_ctl_reg = intel_aux_ctl_reg(dev_priv, port); |
| @@ -1297,14 +1307,10 @@ intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates) | |||
| 1297 | bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp) | 1307 | bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp) |
| 1298 | { | 1308 | { |
| 1299 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); | 1309 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
| 1300 | struct drm_device *dev = dig_port->base.base.dev; | 1310 | struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); |
| 1301 | |||
| 1302 | /* WaDisableHBR2:skl */ | ||
| 1303 | if (IS_SKL_REVID(dev, 0, SKL_REVID_B0)) | ||
| 1304 | return false; | ||
| 1305 | 1311 | ||
| 1306 | if ((IS_HASWELL(dev) && !IS_HSW_ULX(dev)) || IS_BROADWELL(dev) || | 1312 | if ((IS_HASWELL(dev_priv) && !IS_HSW_ULX(dev_priv)) || |
| 1307 | (INTEL_INFO(dev)->gen >= 9)) | 1313 | IS_BROADWELL(dev_priv) || (INTEL_GEN(dev_priv) >= 9)) |
| 1308 | return true; | 1314 | return true; |
| 1309 | else | 1315 | else |
| 1310 | return false; | 1316 | return false; |
| @@ -1314,13 +1320,13 @@ static int | |||
| 1314 | intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates) | 1320 | intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates) |
| 1315 | { | 1321 | { |
| 1316 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); | 1322 | struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); |
| 1317 | struct drm_device *dev = dig_port->base.base.dev; | 1323 | struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); |
| 1318 | int size; | 1324 | int size; |
| 1319 | 1325 | ||
| 1320 | if (IS_BROXTON(dev)) { | 1326 | if (IS_BROXTON(dev_priv)) { |
| 1321 | *source_rates = bxt_rates; | 1327 | *source_rates = bxt_rates; |
| 1322 | size = ARRAY_SIZE(bxt_rates); | 1328 | size = ARRAY_SIZE(bxt_rates); |
| 1323 | } else if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { | 1329 | } else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { |
| 1324 | *source_rates = skl_rates; | 1330 | *source_rates = skl_rates; |
| 1325 | size = ARRAY_SIZE(skl_rates); | 1331 | size = ARRAY_SIZE(skl_rates); |
| 1326 | } else { | 1332 | } else { |
| @@ -1340,19 +1346,20 @@ intel_dp_set_clock(struct intel_encoder *encoder, | |||
| 1340 | struct intel_crtc_state *pipe_config) | 1346 | struct intel_crtc_state *pipe_config) |
| 1341 | { | 1347 | { |
| 1342 | struct drm_device *dev = encoder->base.dev; | 1348 | struct drm_device *dev = encoder->base.dev; |
| 1349 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 1343 | const struct dp_link_dpll *divisor = NULL; | 1350 | const struct dp_link_dpll *divisor = NULL; |
| 1344 | int i, count = 0; | 1351 | int i, count = 0; |
| 1345 | 1352 | ||
| 1346 | if (IS_G4X(dev)) { | 1353 | if (IS_G4X(dev_priv)) { |
| 1347 | divisor = gen4_dpll; | 1354 | divisor = gen4_dpll; |
| 1348 | count = ARRAY_SIZE(gen4_dpll); | 1355 | count = ARRAY_SIZE(gen4_dpll); |
| 1349 | } else if (HAS_PCH_SPLIT(dev)) { | 1356 | } else if (HAS_PCH_SPLIT(dev_priv)) { |
| 1350 | divisor = pch_dpll; | 1357 | divisor = pch_dpll; |
| 1351 | count = ARRAY_SIZE(pch_dpll); | 1358 | count = ARRAY_SIZE(pch_dpll); |
| 1352 | } else if (IS_CHERRYVIEW(dev)) { | 1359 | } else if (IS_CHERRYVIEW(dev_priv)) { |
| 1353 | divisor = chv_dpll; | 1360 | divisor = chv_dpll; |
| 1354 | count = ARRAY_SIZE(chv_dpll); | 1361 | count = ARRAY_SIZE(chv_dpll); |
| 1355 | } else if (IS_VALLEYVIEW(dev)) { | 1362 | } else if (IS_VALLEYVIEW(dev_priv)) { |
| 1356 | divisor = vlv_dpll; | 1363 | divisor = vlv_dpll; |
| 1357 | count = ARRAY_SIZE(vlv_dpll); | 1364 | count = ARRAY_SIZE(vlv_dpll); |
| 1358 | } | 1365 | } |
| @@ -1567,7 +1574,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, | |||
| 1567 | 1574 | ||
| 1568 | max_clock = common_len - 1; | 1575 | max_clock = common_len - 1; |
| 1569 | 1576 | ||
| 1570 | if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev) && port != PORT_A) | 1577 | if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv) && port != PORT_A) |
| 1571 | pipe_config->has_pch_encoder = true; | 1578 | pipe_config->has_pch_encoder = true; |
| 1572 | 1579 | ||
| 1573 | pipe_config->has_drrs = false; | 1580 | pipe_config->has_drrs = false; |
| @@ -1584,7 +1591,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, | |||
| 1584 | return ret; | 1591 | return ret; |
| 1585 | } | 1592 | } |
| 1586 | 1593 | ||
| 1587 | if (HAS_GMCH_DISPLAY(dev)) | 1594 | if (HAS_GMCH_DISPLAY(dev_priv)) |
| 1588 | intel_gmch_panel_fitting(intel_crtc, pipe_config, | 1595 | intel_gmch_panel_fitting(intel_crtc, pipe_config, |
| 1589 | intel_connector->panel.fitting_mode); | 1596 | intel_connector->panel.fitting_mode); |
| 1590 | else | 1597 | else |
| @@ -1709,7 +1716,7 @@ found: | |||
| 1709 | to_intel_atomic_state(pipe_config->base.state)->cdclk_pll_vco = vco; | 1716 | to_intel_atomic_state(pipe_config->base.state)->cdclk_pll_vco = vco; |
| 1710 | } | 1717 | } |
| 1711 | 1718 | ||
| 1712 | if (!HAS_DDI(dev)) | 1719 | if (!HAS_DDI(dev_priv)) |
| 1713 | intel_dp_set_clock(encoder, pipe_config); | 1720 | intel_dp_set_clock(encoder, pipe_config); |
| 1714 | 1721 | ||
| 1715 | return true; | 1722 | return true; |
| @@ -1767,7 +1774,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder, | |||
| 1767 | 1774 | ||
| 1768 | /* Split out the IBX/CPU vs CPT settings */ | 1775 | /* Split out the IBX/CPU vs CPT settings */ |
| 1769 | 1776 | ||
| 1770 | if (IS_GEN7(dev) && port == PORT_A) { | 1777 | if (IS_GEN7(dev_priv) && port == PORT_A) { |
| 1771 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) | 1778 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
| 1772 | intel_dp->DP |= DP_SYNC_HS_HIGH; | 1779 | intel_dp->DP |= DP_SYNC_HS_HIGH; |
| 1773 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) | 1780 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
| @@ -1778,7 +1785,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder, | |||
| 1778 | intel_dp->DP |= DP_ENHANCED_FRAMING; | 1785 | intel_dp->DP |= DP_ENHANCED_FRAMING; |
| 1779 | 1786 | ||
| 1780 | intel_dp->DP |= crtc->pipe << 29; | 1787 | intel_dp->DP |= crtc->pipe << 29; |
| 1781 | } else if (HAS_PCH_CPT(dev) && port != PORT_A) { | 1788 | } else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) { |
| 1782 | u32 trans_dp; | 1789 | u32 trans_dp; |
| 1783 | 1790 | ||
| 1784 | intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; | 1791 | intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT; |
| @@ -1790,8 +1797,9 @@ static void intel_dp_prepare(struct intel_encoder *encoder, | |||
| 1790 | trans_dp &= ~TRANS_DP_ENH_FRAMING; | 1797 | trans_dp &= ~TRANS_DP_ENH_FRAMING; |
| 1791 | I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp); | 1798 | I915_WRITE(TRANS_DP_CTL(crtc->pipe), trans_dp); |
| 1792 | } else { | 1799 | } else { |
| 1793 | if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) && | 1800 | if (!HAS_PCH_SPLIT(dev_priv) && !IS_VALLEYVIEW(dev_priv) && |
| 1794 | !IS_CHERRYVIEW(dev) && pipe_config->limited_color_range) | 1801 | !IS_CHERRYVIEW(dev_priv) && |
| 1802 | pipe_config->limited_color_range) | ||
| 1795 | intel_dp->DP |= DP_COLOR_RANGE_16_235; | 1803 | intel_dp->DP |= DP_COLOR_RANGE_16_235; |
| 1796 | 1804 | ||
| 1797 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) | 1805 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
| @@ -1803,7 +1811,7 @@ static void intel_dp_prepare(struct intel_encoder *encoder, | |||
| 1803 | if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) | 1811 | if (drm_dp_enhanced_frame_cap(intel_dp->dpcd)) |
| 1804 | intel_dp->DP |= DP_ENHANCED_FRAMING; | 1812 | intel_dp->DP |= DP_ENHANCED_FRAMING; |
| 1805 | 1813 | ||
| 1806 | if (IS_CHERRYVIEW(dev)) | 1814 | if (IS_CHERRYVIEW(dev_priv)) |
| 1807 | intel_dp->DP |= DP_PIPE_SELECT_CHV(crtc->pipe); | 1815 | intel_dp->DP |= DP_PIPE_SELECT_CHV(crtc->pipe); |
| 1808 | else if (crtc->pipe == PIPE_B) | 1816 | else if (crtc->pipe == PIPE_B) |
| 1809 | intel_dp->DP |= DP_PIPEB_SELECT; | 1817 | intel_dp->DP |= DP_PIPEB_SELECT; |
| @@ -2112,7 +2120,7 @@ static void edp_panel_on(struct intel_dp *intel_dp) | |||
| 2112 | 2120 | ||
| 2113 | pp_ctrl_reg = _pp_ctrl_reg(intel_dp); | 2121 | pp_ctrl_reg = _pp_ctrl_reg(intel_dp); |
| 2114 | pp = ironlake_get_pp_control(intel_dp); | 2122 | pp = ironlake_get_pp_control(intel_dp); |
| 2115 | if (IS_GEN5(dev)) { | 2123 | if (IS_GEN5(dev_priv)) { |
| 2116 | /* ILK workaround: disable reset around power sequence */ | 2124 | /* ILK workaround: disable reset around power sequence */ |
| 2117 | pp &= ~PANEL_POWER_RESET; | 2125 | pp &= ~PANEL_POWER_RESET; |
| 2118 | I915_WRITE(pp_ctrl_reg, pp); | 2126 | I915_WRITE(pp_ctrl_reg, pp); |
| @@ -2120,7 +2128,7 @@ static void edp_panel_on(struct intel_dp *intel_dp) | |||
| 2120 | } | 2128 | } |
| 2121 | 2129 | ||
| 2122 | pp |= PANEL_POWER_ON; | 2130 | pp |= PANEL_POWER_ON; |
| 2123 | if (!IS_GEN5(dev)) | 2131 | if (!IS_GEN5(dev_priv)) |
| 2124 | pp |= PANEL_POWER_RESET; | 2132 | pp |= PANEL_POWER_RESET; |
| 2125 | 2133 | ||
| 2126 | I915_WRITE(pp_ctrl_reg, pp); | 2134 | I915_WRITE(pp_ctrl_reg, pp); |
| @@ -2129,7 +2137,7 @@ static void edp_panel_on(struct intel_dp *intel_dp) | |||
| 2129 | wait_panel_on(intel_dp); | 2137 | wait_panel_on(intel_dp); |
| 2130 | intel_dp->last_power_on = jiffies; | 2138 | intel_dp->last_power_on = jiffies; |
| 2131 | 2139 | ||
| 2132 | if (IS_GEN5(dev)) { | 2140 | if (IS_GEN5(dev_priv)) { |
| 2133 | pp |= PANEL_POWER_RESET; /* restore panel reset bit */ | 2141 | pp |= PANEL_POWER_RESET; /* restore panel reset bit */ |
| 2134 | I915_WRITE(pp_ctrl_reg, pp); | 2142 | I915_WRITE(pp_ctrl_reg, pp); |
| 2135 | POSTING_READ(pp_ctrl_reg); | 2143 | POSTING_READ(pp_ctrl_reg); |
| @@ -2442,9 +2450,9 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, | |||
| 2442 | if (!(tmp & DP_PORT_EN)) | 2450 | if (!(tmp & DP_PORT_EN)) |
| 2443 | goto out; | 2451 | goto out; |
| 2444 | 2452 | ||
| 2445 | if (IS_GEN7(dev) && port == PORT_A) { | 2453 | if (IS_GEN7(dev_priv) && port == PORT_A) { |
| 2446 | *pipe = PORT_TO_PIPE_CPT(tmp); | 2454 | *pipe = PORT_TO_PIPE_CPT(tmp); |
| 2447 | } else if (HAS_PCH_CPT(dev) && port != PORT_A) { | 2455 | } else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) { |
| 2448 | enum pipe p; | 2456 | enum pipe p; |
| 2449 | 2457 | ||
| 2450 | for_each_pipe(dev_priv, p) { | 2458 | for_each_pipe(dev_priv, p) { |
| @@ -2459,7 +2467,7 @@ static bool intel_dp_get_hw_state(struct intel_encoder *encoder, | |||
| 2459 | 2467 | ||
| 2460 | DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n", | 2468 | DRM_DEBUG_KMS("No pipe for dp port 0x%x found\n", |
| 2461 | i915_mmio_reg_offset(intel_dp->output_reg)); | 2469 | i915_mmio_reg_offset(intel_dp->output_reg)); |
| 2462 | } else if (IS_CHERRYVIEW(dev)) { | 2470 | } else if (IS_CHERRYVIEW(dev_priv)) { |
| 2463 | *pipe = DP_PORT_TO_PIPE_CHV(tmp); | 2471 | *pipe = DP_PORT_TO_PIPE_CHV(tmp); |
| 2464 | } else { | 2472 | } else { |
| 2465 | *pipe = PORT_TO_PIPE(tmp); | 2473 | *pipe = PORT_TO_PIPE(tmp); |
| @@ -2487,7 +2495,7 @@ static void intel_dp_get_config(struct intel_encoder *encoder, | |||
| 2487 | 2495 | ||
| 2488 | pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A; | 2496 | pipe_config->has_audio = tmp & DP_AUDIO_OUTPUT_ENABLE && port != PORT_A; |
| 2489 | 2497 | ||
| 2490 | if (HAS_PCH_CPT(dev) && port != PORT_A) { | 2498 | if (HAS_PCH_CPT(dev_priv) && port != PORT_A) { |
| 2491 | u32 trans_dp = I915_READ(TRANS_DP_CTL(crtc->pipe)); | 2499 | u32 trans_dp = I915_READ(TRANS_DP_CTL(crtc->pipe)); |
| 2492 | 2500 | ||
| 2493 | if (trans_dp & TRANS_DP_HSYNC_ACTIVE_HIGH) | 2501 | if (trans_dp & TRANS_DP_HSYNC_ACTIVE_HIGH) |
| @@ -2513,8 +2521,8 @@ static void intel_dp_get_config(struct intel_encoder *encoder, | |||
| 2513 | 2521 | ||
| 2514 | pipe_config->base.adjusted_mode.flags |= flags; | 2522 | pipe_config->base.adjusted_mode.flags |= flags; |
| 2515 | 2523 | ||
| 2516 | if (!HAS_PCH_SPLIT(dev) && !IS_VALLEYVIEW(dev) && | 2524 | if (!HAS_PCH_SPLIT(dev_priv) && !IS_VALLEYVIEW(dev_priv) && |
| 2517 | !IS_CHERRYVIEW(dev) && tmp & DP_COLOR_RANGE_16_235) | 2525 | !IS_CHERRYVIEW(dev_priv) && tmp & DP_COLOR_RANGE_16_235) |
| 2518 | pipe_config->limited_color_range = true; | 2526 | pipe_config->limited_color_range = true; |
| 2519 | 2527 | ||
| 2520 | pipe_config->lane_count = | 2528 | pipe_config->lane_count = |
| @@ -2634,7 +2642,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
| 2634 | DRM_DEBUG_KMS("Using DP training pattern TPS%d\n", | 2642 | DRM_DEBUG_KMS("Using DP training pattern TPS%d\n", |
| 2635 | dp_train_pat & DP_TRAINING_PATTERN_MASK); | 2643 | dp_train_pat & DP_TRAINING_PATTERN_MASK); |
| 2636 | 2644 | ||
| 2637 | if (HAS_DDI(dev)) { | 2645 | if (HAS_DDI(dev_priv)) { |
| 2638 | uint32_t temp = I915_READ(DP_TP_CTL(port)); | 2646 | uint32_t temp = I915_READ(DP_TP_CTL(port)); |
| 2639 | 2647 | ||
| 2640 | if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) | 2648 | if (dp_train_pat & DP_LINK_SCRAMBLING_DISABLE) |
| @@ -2660,8 +2668,8 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
| 2660 | } | 2668 | } |
| 2661 | I915_WRITE(DP_TP_CTL(port), temp); | 2669 | I915_WRITE(DP_TP_CTL(port), temp); |
| 2662 | 2670 | ||
| 2663 | } else if ((IS_GEN7(dev) && port == PORT_A) || | 2671 | } else if ((IS_GEN7(dev_priv) && port == PORT_A) || |
| 2664 | (HAS_PCH_CPT(dev) && port != PORT_A)) { | 2672 | (HAS_PCH_CPT(dev_priv) && port != PORT_A)) { |
| 2665 | *DP &= ~DP_LINK_TRAIN_MASK_CPT; | 2673 | *DP &= ~DP_LINK_TRAIN_MASK_CPT; |
| 2666 | 2674 | ||
| 2667 | switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { | 2675 | switch (dp_train_pat & DP_TRAINING_PATTERN_MASK) { |
| @@ -2681,7 +2689,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
| 2681 | } | 2689 | } |
| 2682 | 2690 | ||
| 2683 | } else { | 2691 | } else { |
| 2684 | if (IS_CHERRYVIEW(dev)) | 2692 | if (IS_CHERRYVIEW(dev_priv)) |
| 2685 | *DP &= ~DP_LINK_TRAIN_MASK_CHV; | 2693 | *DP &= ~DP_LINK_TRAIN_MASK_CHV; |
| 2686 | else | 2694 | else |
| 2687 | *DP &= ~DP_LINK_TRAIN_MASK; | 2695 | *DP &= ~DP_LINK_TRAIN_MASK; |
| @@ -2697,7 +2705,7 @@ _intel_dp_set_link_train(struct intel_dp *intel_dp, | |||
| 2697 | *DP |= DP_LINK_TRAIN_PAT_2; | 2705 | *DP |= DP_LINK_TRAIN_PAT_2; |
| 2698 | break; | 2706 | break; |
| 2699 | case DP_TRAINING_PATTERN_3: | 2707 | case DP_TRAINING_PATTERN_3: |
| 2700 | if (IS_CHERRYVIEW(dev)) { | 2708 | if (IS_CHERRYVIEW(dev_priv)) { |
| 2701 | *DP |= DP_LINK_TRAIN_PAT_3_CHV; | 2709 | *DP |= DP_LINK_TRAIN_PAT_3_CHV; |
| 2702 | } else { | 2710 | } else { |
| 2703 | DRM_DEBUG_KMS("TPS3 not supported, using TPS2 instead\n"); | 2711 | DRM_DEBUG_KMS("TPS3 not supported, using TPS2 instead\n"); |
| @@ -2747,7 +2755,7 @@ static void intel_enable_dp(struct intel_encoder *encoder, | |||
| 2747 | 2755 | ||
| 2748 | pps_lock(intel_dp); | 2756 | pps_lock(intel_dp); |
| 2749 | 2757 | ||
| 2750 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 2758 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 2751 | vlv_init_panel_power_sequencer(intel_dp); | 2759 | vlv_init_panel_power_sequencer(intel_dp); |
| 2752 | 2760 | ||
| 2753 | intel_dp_enable_port(intel_dp, pipe_config); | 2761 | intel_dp_enable_port(intel_dp, pipe_config); |
| @@ -2758,10 +2766,10 @@ static void intel_enable_dp(struct intel_encoder *encoder, | |||
| 2758 | 2766 | ||
| 2759 | pps_unlock(intel_dp); | 2767 | pps_unlock(intel_dp); |
| 2760 | 2768 | ||
| 2761 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 2769 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 2762 | unsigned int lane_mask = 0x0; | 2770 | unsigned int lane_mask = 0x0; |
| 2763 | 2771 | ||
| 2764 | if (IS_CHERRYVIEW(dev)) | 2772 | if (IS_CHERRYVIEW(dev_priv)) |
| 2765 | lane_mask = intel_dp_unused_lane_mask(pipe_config->lane_count); | 2773 | lane_mask = intel_dp_unused_lane_mask(pipe_config->lane_count); |
| 2766 | 2774 | ||
| 2767 | vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp), | 2775 | vlv_wait_port_ready(dev_priv, dp_to_dig_port(intel_dp), |
| @@ -2981,17 +2989,17 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) | |||
| 2981 | struct drm_i915_private *dev_priv = to_i915(dev); | 2989 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2982 | enum port port = dp_to_dig_port(intel_dp)->port; | 2990 | enum port port = dp_to_dig_port(intel_dp)->port; |
| 2983 | 2991 | ||
| 2984 | if (IS_BROXTON(dev)) | 2992 | if (IS_BROXTON(dev_priv)) |
| 2985 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; | 2993 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; |
| 2986 | else if (INTEL_INFO(dev)->gen >= 9) { | 2994 | else if (INTEL_INFO(dev)->gen >= 9) { |
| 2987 | if (dev_priv->vbt.edp.low_vswing && port == PORT_A) | 2995 | if (dev_priv->vbt.edp.low_vswing && port == PORT_A) |
| 2988 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; | 2996 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; |
| 2989 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; | 2997 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; |
| 2990 | } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 2998 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 2991 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; | 2999 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; |
| 2992 | else if (IS_GEN7(dev) && port == PORT_A) | 3000 | else if (IS_GEN7(dev_priv) && port == PORT_A) |
| 2993 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; | 3001 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; |
| 2994 | else if (HAS_PCH_CPT(dev) && port != PORT_A) | 3002 | else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) |
| 2995 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; | 3003 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; |
| 2996 | else | 3004 | else |
| 2997 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; | 3005 | return DP_TRAIN_VOLTAGE_SWING_LEVEL_2; |
| @@ -3000,10 +3008,10 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) | |||
| 3000 | uint8_t | 3008 | uint8_t |
| 3001 | intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) | 3009 | intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) |
| 3002 | { | 3010 | { |
| 3003 | struct drm_device *dev = intel_dp_to_dev(intel_dp); | 3011 | struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); |
| 3004 | enum port port = dp_to_dig_port(intel_dp)->port; | 3012 | enum port port = dp_to_dig_port(intel_dp)->port; |
| 3005 | 3013 | ||
| 3006 | if (INTEL_INFO(dev)->gen >= 9) { | 3014 | if (INTEL_GEN(dev_priv) >= 9) { |
| 3007 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { | 3015 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
| 3008 | case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: | 3016 | case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
| 3009 | return DP_TRAIN_PRE_EMPH_LEVEL_3; | 3017 | return DP_TRAIN_PRE_EMPH_LEVEL_3; |
| @@ -3016,7 +3024,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) | |||
| 3016 | default: | 3024 | default: |
| 3017 | return DP_TRAIN_PRE_EMPH_LEVEL_0; | 3025 | return DP_TRAIN_PRE_EMPH_LEVEL_0; |
| 3018 | } | 3026 | } |
| 3019 | } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { | 3027 | } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { |
| 3020 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { | 3028 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
| 3021 | case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: | 3029 | case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
| 3022 | return DP_TRAIN_PRE_EMPH_LEVEL_3; | 3030 | return DP_TRAIN_PRE_EMPH_LEVEL_3; |
| @@ -3028,7 +3036,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) | |||
| 3028 | default: | 3036 | default: |
| 3029 | return DP_TRAIN_PRE_EMPH_LEVEL_0; | 3037 | return DP_TRAIN_PRE_EMPH_LEVEL_0; |
| 3030 | } | 3038 | } |
| 3031 | } else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 3039 | } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 3032 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { | 3040 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
| 3033 | case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: | 3041 | case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
| 3034 | return DP_TRAIN_PRE_EMPH_LEVEL_3; | 3042 | return DP_TRAIN_PRE_EMPH_LEVEL_3; |
| @@ -3040,7 +3048,7 @@ intel_dp_pre_emphasis_max(struct intel_dp *intel_dp, uint8_t voltage_swing) | |||
| 3040 | default: | 3048 | default: |
| 3041 | return DP_TRAIN_PRE_EMPH_LEVEL_0; | 3049 | return DP_TRAIN_PRE_EMPH_LEVEL_0; |
| 3042 | } | 3050 | } |
| 3043 | } else if (IS_GEN7(dev) && port == PORT_A) { | 3051 | } else if (IS_GEN7(dev_priv) && port == PORT_A) { |
| 3044 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { | 3052 | switch (voltage_swing & DP_TRAIN_VOLTAGE_SWING_MASK) { |
| 3045 | case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: | 3053 | case DP_TRAIN_VOLTAGE_SWING_LEVEL_0: |
| 3046 | return DP_TRAIN_PRE_EMPH_LEVEL_2; | 3054 | return DP_TRAIN_PRE_EMPH_LEVEL_2; |
| @@ -3341,21 +3349,21 @@ intel_dp_set_signal_levels(struct intel_dp *intel_dp) | |||
| 3341 | uint32_t signal_levels, mask = 0; | 3349 | uint32_t signal_levels, mask = 0; |
| 3342 | uint8_t train_set = intel_dp->train_set[0]; | 3350 | uint8_t train_set = intel_dp->train_set[0]; |
| 3343 | 3351 | ||
| 3344 | if (HAS_DDI(dev)) { | 3352 | if (HAS_DDI(dev_priv)) { |
| 3345 | signal_levels = ddi_signal_levels(intel_dp); | 3353 | signal_levels = ddi_signal_levels(intel_dp); |
| 3346 | 3354 | ||
| 3347 | if (IS_BROXTON(dev)) | 3355 | if (IS_BROXTON(dev_priv)) |
| 3348 | signal_levels = 0; | 3356 | signal_levels = 0; |
| 3349 | else | 3357 | else |
| 3350 | mask = DDI_BUF_EMP_MASK; | 3358 | mask = DDI_BUF_EMP_MASK; |
| 3351 | } else if (IS_CHERRYVIEW(dev)) { | 3359 | } else if (IS_CHERRYVIEW(dev_priv)) { |
| 3352 | signal_levels = chv_signal_levels(intel_dp); | 3360 | signal_levels = chv_signal_levels(intel_dp); |
| 3353 | } else if (IS_VALLEYVIEW(dev)) { | 3361 | } else if (IS_VALLEYVIEW(dev_priv)) { |
| 3354 | signal_levels = vlv_signal_levels(intel_dp); | 3362 | signal_levels = vlv_signal_levels(intel_dp); |
| 3355 | } else if (IS_GEN7(dev) && port == PORT_A) { | 3363 | } else if (IS_GEN7(dev_priv) && port == PORT_A) { |
| 3356 | signal_levels = gen7_edp_signal_levels(train_set); | 3364 | signal_levels = gen7_edp_signal_levels(train_set); |
| 3357 | mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; | 3365 | mask = EDP_LINK_TRAIN_VOL_EMP_MASK_IVB; |
| 3358 | } else if (IS_GEN6(dev) && port == PORT_A) { | 3366 | } else if (IS_GEN6(dev_priv) && port == PORT_A) { |
| 3359 | signal_levels = gen6_edp_signal_levels(train_set); | 3367 | signal_levels = gen6_edp_signal_levels(train_set); |
| 3360 | mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB; | 3368 | mask = EDP_LINK_TRAIN_VOL_EMP_MASK_SNB; |
| 3361 | } else { | 3369 | } else { |
| @@ -3400,7 +3408,7 @@ void intel_dp_set_idle_link_train(struct intel_dp *intel_dp) | |||
| 3400 | enum port port = intel_dig_port->port; | 3408 | enum port port = intel_dig_port->port; |
| 3401 | uint32_t val; | 3409 | uint32_t val; |
| 3402 | 3410 | ||
| 3403 | if (!HAS_DDI(dev)) | 3411 | if (!HAS_DDI(dev_priv)) |
| 3404 | return; | 3412 | return; |
| 3405 | 3413 | ||
| 3406 | val = I915_READ(DP_TP_CTL(port)); | 3414 | val = I915_READ(DP_TP_CTL(port)); |
| @@ -3435,7 +3443,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) | |||
| 3435 | struct drm_i915_private *dev_priv = to_i915(dev); | 3443 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 3436 | uint32_t DP = intel_dp->DP; | 3444 | uint32_t DP = intel_dp->DP; |
| 3437 | 3445 | ||
| 3438 | if (WARN_ON(HAS_DDI(dev))) | 3446 | if (WARN_ON(HAS_DDI(dev_priv))) |
| 3439 | return; | 3447 | return; |
| 3440 | 3448 | ||
| 3441 | if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)) | 3449 | if (WARN_ON((I915_READ(intel_dp->output_reg) & DP_PORT_EN) == 0)) |
| @@ -3443,12 +3451,12 @@ intel_dp_link_down(struct intel_dp *intel_dp) | |||
| 3443 | 3451 | ||
| 3444 | DRM_DEBUG_KMS("\n"); | 3452 | DRM_DEBUG_KMS("\n"); |
| 3445 | 3453 | ||
| 3446 | if ((IS_GEN7(dev) && port == PORT_A) || | 3454 | if ((IS_GEN7(dev_priv) && port == PORT_A) || |
| 3447 | (HAS_PCH_CPT(dev) && port != PORT_A)) { | 3455 | (HAS_PCH_CPT(dev_priv) && port != PORT_A)) { |
| 3448 | DP &= ~DP_LINK_TRAIN_MASK_CPT; | 3456 | DP &= ~DP_LINK_TRAIN_MASK_CPT; |
| 3449 | DP |= DP_LINK_TRAIN_PAT_IDLE_CPT; | 3457 | DP |= DP_LINK_TRAIN_PAT_IDLE_CPT; |
| 3450 | } else { | 3458 | } else { |
| 3451 | if (IS_CHERRYVIEW(dev)) | 3459 | if (IS_CHERRYVIEW(dev_priv)) |
| 3452 | DP &= ~DP_LINK_TRAIN_MASK_CHV; | 3460 | DP &= ~DP_LINK_TRAIN_MASK_CHV; |
| 3453 | else | 3461 | else |
| 3454 | DP &= ~DP_LINK_TRAIN_MASK; | 3462 | DP &= ~DP_LINK_TRAIN_MASK; |
| @@ -3466,7 +3474,7 @@ intel_dp_link_down(struct intel_dp *intel_dp) | |||
| 3466 | * to transcoder A after disabling it to allow the | 3474 | * to transcoder A after disabling it to allow the |
| 3467 | * matching HDMI port to be enabled on transcoder A. | 3475 | * matching HDMI port to be enabled on transcoder A. |
| 3468 | */ | 3476 | */ |
| 3469 | if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B && port != PORT_A) { | 3477 | if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B && port != PORT_A) { |
| 3470 | /* | 3478 | /* |
| 3471 | * We get CPU/PCH FIFO underruns on the other pipe when | 3479 | * We get CPU/PCH FIFO underruns on the other pipe when |
| 3472 | * doing the workaround. Sweep them under the rug. | 3480 | * doing the workaround. Sweep them under the rug. |
| @@ -3549,8 +3557,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp) | |||
| 3549 | /* Read the eDP Display control capabilities registers */ | 3557 | /* Read the eDP Display control capabilities registers */ |
| 3550 | if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) && | 3558 | if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) && |
| 3551 | drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, | 3559 | drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, |
| 3552 | intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd) == | 3560 | intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) == |
| 3553 | sizeof(intel_dp->edp_dpcd))) | 3561 | sizeof(intel_dp->edp_dpcd)) |
| 3554 | DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd), | 3562 | DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd), |
| 3555 | intel_dp->edp_dpcd); | 3563 | intel_dp->edp_dpcd); |
| 3556 | 3564 | ||
| @@ -3986,6 +3994,31 @@ go_again: | |||
| 3986 | } | 3994 | } |
| 3987 | 3995 | ||
| 3988 | static void | 3996 | static void |
| 3997 | intel_dp_retrain_link(struct intel_dp *intel_dp) | ||
| 3998 | { | ||
| 3999 | struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; | ||
| 4000 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | ||
| 4001 | struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | ||
| 4002 | |||
| 4003 | /* Suppress underruns caused by re-training */ | ||
| 4004 | intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, false); | ||
| 4005 | if (crtc->config->has_pch_encoder) | ||
| 4006 | intel_set_pch_fifo_underrun_reporting(dev_priv, | ||
| 4007 | intel_crtc_pch_transcoder(crtc), false); | ||
| 4008 | |||
| 4009 | intel_dp_start_link_train(intel_dp); | ||
| 4010 | intel_dp_stop_link_train(intel_dp); | ||
| 4011 | |||
| 4012 | /* Keep underrun reporting disabled until things are stable */ | ||
| 4013 | intel_wait_for_vblank(&dev_priv->drm, crtc->pipe); | ||
| 4014 | |||
| 4015 | intel_set_cpu_fifo_underrun_reporting(dev_priv, crtc->pipe, true); | ||
| 4016 | if (crtc->config->has_pch_encoder) | ||
| 4017 | intel_set_pch_fifo_underrun_reporting(dev_priv, | ||
| 4018 | intel_crtc_pch_transcoder(crtc), true); | ||
| 4019 | } | ||
| 4020 | |||
| 4021 | static void | ||
| 3989 | intel_dp_check_link_status(struct intel_dp *intel_dp) | 4022 | intel_dp_check_link_status(struct intel_dp *intel_dp) |
| 3990 | { | 4023 | { |
| 3991 | struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; | 4024 | struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base; |
| @@ -4005,13 +4038,18 @@ intel_dp_check_link_status(struct intel_dp *intel_dp) | |||
| 4005 | if (!to_intel_crtc(intel_encoder->base.crtc)->active) | 4038 | if (!to_intel_crtc(intel_encoder->base.crtc)->active) |
| 4006 | return; | 4039 | return; |
| 4007 | 4040 | ||
| 4041 | /* FIXME: we need to synchronize this sort of stuff with hardware | ||
| 4042 | * readout */ | ||
| 4043 | if (WARN_ON_ONCE(!intel_dp->lane_count)) | ||
| 4044 | return; | ||
| 4045 | |||
| 4008 | /* if link training is requested we should perform it always */ | 4046 | /* if link training is requested we should perform it always */ |
| 4009 | if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) || | 4047 | if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) || |
| 4010 | (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) { | 4048 | (!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) { |
| 4011 | DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", | 4049 | DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n", |
| 4012 | intel_encoder->base.name); | 4050 | intel_encoder->base.name); |
| 4013 | intel_dp_start_link_train(intel_dp); | 4051 | |
| 4014 | intel_dp_stop_link_train(intel_dp); | 4052 | intel_dp_retrain_link(intel_dp); |
| 4015 | } | 4053 | } |
| 4016 | } | 4054 | } |
| 4017 | 4055 | ||
| @@ -4334,7 +4372,7 @@ intel_dp_unset_edid(struct intel_dp *intel_dp) | |||
| 4334 | intel_dp->has_audio = false; | 4372 | intel_dp->has_audio = false; |
| 4335 | } | 4373 | } |
| 4336 | 4374 | ||
| 4337 | static void | 4375 | static enum drm_connector_status |
| 4338 | intel_dp_long_pulse(struct intel_connector *intel_connector) | 4376 | intel_dp_long_pulse(struct intel_connector *intel_connector) |
| 4339 | { | 4377 | { |
| 4340 | struct drm_connector *connector = &intel_connector->base; | 4378 | struct drm_connector *connector = &intel_connector->base; |
| @@ -4358,7 +4396,7 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) | |||
| 4358 | else | 4396 | else |
| 4359 | status = connector_status_disconnected; | 4397 | status = connector_status_disconnected; |
| 4360 | 4398 | ||
| 4361 | if (status != connector_status_connected) { | 4399 | if (status == connector_status_disconnected) { |
| 4362 | intel_dp->compliance_test_active = 0; | 4400 | intel_dp->compliance_test_active = 0; |
| 4363 | intel_dp->compliance_test_type = 0; | 4401 | intel_dp->compliance_test_type = 0; |
| 4364 | intel_dp->compliance_test_data = 0; | 4402 | intel_dp->compliance_test_data = 0; |
| @@ -4420,8 +4458,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) | |||
| 4420 | intel_dp->aux.i2c_defer_count = 0; | 4458 | intel_dp->aux.i2c_defer_count = 0; |
| 4421 | 4459 | ||
| 4422 | intel_dp_set_edid(intel_dp); | 4460 | intel_dp_set_edid(intel_dp); |
| 4423 | 4461 | if (is_edp(intel_dp) || intel_connector->detect_edid) | |
| 4424 | status = connector_status_connected; | 4462 | status = connector_status_connected; |
| 4425 | intel_dp->detect_done = true; | 4463 | intel_dp->detect_done = true; |
| 4426 | 4464 | ||
| 4427 | /* Try to read the source of the interrupt */ | 4465 | /* Try to read the source of the interrupt */ |
| @@ -4440,12 +4478,11 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) | |||
| 4440 | } | 4478 | } |
| 4441 | 4479 | ||
| 4442 | out: | 4480 | out: |
| 4443 | if ((status != connector_status_connected) && | 4481 | if (status != connector_status_connected && !intel_dp->is_mst) |
| 4444 | (intel_dp->is_mst == false)) | ||
| 4445 | intel_dp_unset_edid(intel_dp); | 4482 | intel_dp_unset_edid(intel_dp); |
| 4446 | 4483 | ||
| 4447 | intel_display_power_put(to_i915(dev), power_domain); | 4484 | intel_display_power_put(to_i915(dev), power_domain); |
| 4448 | return; | 4485 | return status; |
| 4449 | } | 4486 | } |
| 4450 | 4487 | ||
| 4451 | static enum drm_connector_status | 4488 | static enum drm_connector_status |
| @@ -4454,7 +4491,7 @@ intel_dp_detect(struct drm_connector *connector, bool force) | |||
| 4454 | struct intel_dp *intel_dp = intel_attached_dp(connector); | 4491 | struct intel_dp *intel_dp = intel_attached_dp(connector); |
| 4455 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); | 4492 | struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); |
| 4456 | struct intel_encoder *intel_encoder = &intel_dig_port->base; | 4493 | struct intel_encoder *intel_encoder = &intel_dig_port->base; |
| 4457 | struct intel_connector *intel_connector = to_intel_connector(connector); | 4494 | enum drm_connector_status status = connector->status; |
| 4458 | 4495 | ||
| 4459 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", | 4496 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", |
| 4460 | connector->base.id, connector->name); | 4497 | connector->base.id, connector->name); |
| @@ -4469,14 +4506,11 @@ intel_dp_detect(struct drm_connector *connector, bool force) | |||
| 4469 | 4506 | ||
| 4470 | /* If full detect is not performed yet, do a full detect */ | 4507 | /* If full detect is not performed yet, do a full detect */ |
| 4471 | if (!intel_dp->detect_done) | 4508 | if (!intel_dp->detect_done) |
| 4472 | intel_dp_long_pulse(intel_dp->attached_connector); | 4509 | status = intel_dp_long_pulse(intel_dp->attached_connector); |
| 4473 | 4510 | ||
| 4474 | intel_dp->detect_done = false; | 4511 | intel_dp->detect_done = false; |
| 4475 | 4512 | ||
| 4476 | if (is_edp(intel_dp) || intel_connector->detect_edid) | 4513 | return status; |
| 4477 | return connector_status_connected; | ||
| 4478 | else | ||
| 4479 | return connector_status_disconnected; | ||
| 4480 | } | 4514 | } |
| 4481 | 4515 | ||
| 4482 | static void | 4516 | static void |
| @@ -4757,11 +4791,16 @@ static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp) | |||
| 4757 | void intel_dp_encoder_reset(struct drm_encoder *encoder) | 4791 | void intel_dp_encoder_reset(struct drm_encoder *encoder) |
| 4758 | { | 4792 | { |
| 4759 | struct drm_i915_private *dev_priv = to_i915(encoder->dev); | 4793 | struct drm_i915_private *dev_priv = to_i915(encoder->dev); |
| 4760 | struct intel_dp *intel_dp = enc_to_intel_dp(encoder); | 4794 | struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder); |
| 4795 | struct intel_lspcon *lspcon = &intel_dig_port->lspcon; | ||
| 4796 | struct intel_dp *intel_dp = &intel_dig_port->dp; | ||
| 4761 | 4797 | ||
| 4762 | if (!HAS_DDI(dev_priv)) | 4798 | if (!HAS_DDI(dev_priv)) |
| 4763 | intel_dp->DP = I915_READ(intel_dp->output_reg); | 4799 | intel_dp->DP = I915_READ(intel_dp->output_reg); |
| 4764 | 4800 | ||
| 4801 | if (IS_GEN9(dev_priv) && lspcon->active) | ||
| 4802 | lspcon_resume(lspcon); | ||
| 4803 | |||
| 4765 | if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP) | 4804 | if (to_intel_encoder(encoder)->type != INTEL_OUTPUT_EDP) |
| 4766 | return; | 4805 | return; |
| 4767 | 4806 | ||
| @@ -4828,36 +4867,34 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd) | |||
| 4828 | port_name(intel_dig_port->port), | 4867 | port_name(intel_dig_port->port), |
| 4829 | long_hpd ? "long" : "short"); | 4868 | long_hpd ? "long" : "short"); |
| 4830 | 4869 | ||
| 4870 | if (long_hpd) { | ||
| 4871 | intel_dp->detect_done = false; | ||
| 4872 | return IRQ_NONE; | ||
| 4873 | } | ||
| 4874 | |||
| 4831 | power_domain = intel_display_port_aux_power_domain(intel_encoder); | 4875 | power_domain = intel_display_port_aux_power_domain(intel_encoder); |
| 4832 | intel_display_power_get(dev_priv, power_domain); | 4876 | intel_display_power_get(dev_priv, power_domain); |
| 4833 | 4877 | ||
| 4834 | if (long_hpd) { | 4878 | if (intel_dp->is_mst) { |
| 4835 | intel_dp_long_pulse(intel_dp->attached_connector); | 4879 | if (intel_dp_check_mst_status(intel_dp) == -EINVAL) { |
| 4836 | if (intel_dp->is_mst) | 4880 | /* |
| 4837 | ret = IRQ_HANDLED; | 4881 | * If we were in MST mode, and device is not |
| 4838 | goto put_power; | 4882 | * there, get out of MST mode |
| 4839 | 4883 | */ | |
| 4840 | } else { | 4884 | DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", |
| 4841 | if (intel_dp->is_mst) { | 4885 | intel_dp->is_mst, intel_dp->mst_mgr.mst_state); |
| 4842 | if (intel_dp_check_mst_status(intel_dp) == -EINVAL) { | 4886 | intel_dp->is_mst = false; |
| 4843 | /* | 4887 | drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, |
| 4844 | * If we were in MST mode, and device is not | 4888 | intel_dp->is_mst); |
| 4845 | * there, get out of MST mode | 4889 | intel_dp->detect_done = false; |
| 4846 | */ | 4890 | goto put_power; |
| 4847 | DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", | ||
| 4848 | intel_dp->is_mst, intel_dp->mst_mgr.mst_state); | ||
| 4849 | intel_dp->is_mst = false; | ||
| 4850 | drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, | ||
| 4851 | intel_dp->is_mst); | ||
| 4852 | goto put_power; | ||
| 4853 | } | ||
| 4854 | } | 4891 | } |
| 4892 | } | ||
| 4855 | 4893 | ||
| 4856 | if (!intel_dp->is_mst) { | 4894 | if (!intel_dp->is_mst) { |
| 4857 | if (!intel_dp_short_pulse(intel_dp)) { | 4895 | if (!intel_dp_short_pulse(intel_dp)) { |
| 4858 | intel_dp_long_pulse(intel_dp->attached_connector); | 4896 | intel_dp->detect_done = false; |
| 4859 | goto put_power; | 4897 | goto put_power; |
| 4860 | } | ||
| 4861 | } | 4898 | } |
| 4862 | } | 4899 | } |
| 4863 | 4900 | ||
| @@ -5077,7 +5114,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | |||
| 5077 | (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT); | 5114 | (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT); |
| 5078 | /* Compute the divisor for the pp clock, simply match the Bspec | 5115 | /* Compute the divisor for the pp clock, simply match the Bspec |
| 5079 | * formula. */ | 5116 | * formula. */ |
| 5080 | if (IS_BROXTON(dev)) { | 5117 | if (IS_BROXTON(dev_priv)) { |
| 5081 | pp_div = I915_READ(regs.pp_ctrl); | 5118 | pp_div = I915_READ(regs.pp_ctrl); |
| 5082 | pp_div &= ~BXT_POWER_CYCLE_DELAY_MASK; | 5119 | pp_div &= ~BXT_POWER_CYCLE_DELAY_MASK; |
| 5083 | pp_div |= (DIV_ROUND_UP((seq->t11_t12 + 1), 1000) | 5120 | pp_div |= (DIV_ROUND_UP((seq->t11_t12 + 1), 1000) |
| @@ -5090,9 +5127,9 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | |||
| 5090 | 5127 | ||
| 5091 | /* Haswell doesn't have any port selection bits for the panel | 5128 | /* Haswell doesn't have any port selection bits for the panel |
| 5092 | * power sequencer any more. */ | 5129 | * power sequencer any more. */ |
| 5093 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 5130 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 5094 | port_sel = PANEL_PORT_SELECT_VLV(port); | 5131 | port_sel = PANEL_PORT_SELECT_VLV(port); |
| 5095 | } else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) { | 5132 | } else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) { |
| 5096 | if (port == PORT_A) | 5133 | if (port == PORT_A) |
| 5097 | port_sel = PANEL_PORT_SELECT_DPA; | 5134 | port_sel = PANEL_PORT_SELECT_DPA; |
| 5098 | else | 5135 | else |
| @@ -5103,7 +5140,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | |||
| 5103 | 5140 | ||
| 5104 | I915_WRITE(regs.pp_on, pp_on); | 5141 | I915_WRITE(regs.pp_on, pp_on); |
| 5105 | I915_WRITE(regs.pp_off, pp_off); | 5142 | I915_WRITE(regs.pp_off, pp_off); |
| 5106 | if (IS_BROXTON(dev)) | 5143 | if (IS_BROXTON(dev_priv)) |
| 5107 | I915_WRITE(regs.pp_ctrl, pp_div); | 5144 | I915_WRITE(regs.pp_ctrl, pp_div); |
| 5108 | else | 5145 | else |
| 5109 | I915_WRITE(regs.pp_div, pp_div); | 5146 | I915_WRITE(regs.pp_div, pp_div); |
| @@ -5111,7 +5148,7 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | |||
| 5111 | DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", | 5148 | DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", |
| 5112 | I915_READ(regs.pp_on), | 5149 | I915_READ(regs.pp_on), |
| 5113 | I915_READ(regs.pp_off), | 5150 | I915_READ(regs.pp_off), |
| 5114 | IS_BROXTON(dev) ? | 5151 | IS_BROXTON(dev_priv) ? |
| 5115 | (I915_READ(regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK) : | 5152 | (I915_READ(regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK) : |
| 5116 | I915_READ(regs.pp_div)); | 5153 | I915_READ(regs.pp_div)); |
| 5117 | } | 5154 | } |
| @@ -5119,7 +5156,9 @@ intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | |||
| 5119 | static void intel_dp_pps_init(struct drm_device *dev, | 5156 | static void intel_dp_pps_init(struct drm_device *dev, |
| 5120 | struct intel_dp *intel_dp) | 5157 | struct intel_dp *intel_dp) |
| 5121 | { | 5158 | { |
| 5122 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 5159 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 5160 | |||
| 5161 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { | ||
| 5123 | vlv_initial_power_sequencer_setup(intel_dp); | 5162 | vlv_initial_power_sequencer_setup(intel_dp); |
| 5124 | } else { | 5163 | } else { |
| 5125 | intel_dp_init_panel_power_sequencer(dev, intel_dp); | 5164 | intel_dp_init_panel_power_sequencer(dev, intel_dp); |
| @@ -5589,7 +5628,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, | |||
| 5589 | } | 5628 | } |
| 5590 | mutex_unlock(&dev->mode_config.mutex); | 5629 | mutex_unlock(&dev->mode_config.mutex); |
| 5591 | 5630 | ||
| 5592 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 5631 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 5593 | intel_dp->edp_notifier.notifier_call = edp_notify_handler; | 5632 | intel_dp->edp_notifier.notifier_call = edp_notify_handler; |
| 5594 | register_reboot_notifier(&intel_dp->edp_notifier); | 5633 | register_reboot_notifier(&intel_dp->edp_notifier); |
| 5595 | 5634 | ||
| @@ -5598,7 +5637,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, | |||
| 5598 | * If the current pipe isn't valid, try the PPS pipe, and if that | 5637 | * If the current pipe isn't valid, try the PPS pipe, and if that |
| 5599 | * fails just assume pipe A. | 5638 | * fails just assume pipe A. |
| 5600 | */ | 5639 | */ |
| 5601 | if (IS_CHERRYVIEW(dev)) | 5640 | if (IS_CHERRYVIEW(dev_priv)) |
| 5602 | pipe = DP_PORT_TO_PIPE_CHV(intel_dp->DP); | 5641 | pipe = DP_PORT_TO_PIPE_CHV(intel_dp->DP); |
| 5603 | else | 5642 | else |
| 5604 | pipe = PORT_TO_PIPE(intel_dp->DP); | 5643 | pipe = PORT_TO_PIPE(intel_dp->DP); |
| @@ -5654,9 +5693,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 5654 | /* intel_dp vfuncs */ | 5693 | /* intel_dp vfuncs */ |
| 5655 | if (INTEL_INFO(dev)->gen >= 9) | 5694 | if (INTEL_INFO(dev)->gen >= 9) |
| 5656 | intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider; | 5695 | intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider; |
| 5657 | else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 5696 | else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 5658 | intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider; | 5697 | intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider; |
| 5659 | else if (HAS_PCH_SPLIT(dev)) | 5698 | else if (HAS_PCH_SPLIT(dev_priv)) |
| 5660 | intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider; | 5699 | intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider; |
| 5661 | else | 5700 | else |
| 5662 | intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider; | 5701 | intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider; |
| @@ -5666,7 +5705,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 5666 | else | 5705 | else |
| 5667 | intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl; | 5706 | intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl; |
| 5668 | 5707 | ||
| 5669 | if (HAS_DDI(dev)) | 5708 | if (HAS_DDI(dev_priv)) |
| 5670 | intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain; | 5709 | intel_dp->prepare_link_retrain = intel_ddi_prepare_link_retrain; |
| 5671 | 5710 | ||
| 5672 | /* Preserve the current hw state. */ | 5711 | /* Preserve the current hw state. */ |
| @@ -5687,7 +5726,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 5687 | intel_encoder->type = INTEL_OUTPUT_EDP; | 5726 | intel_encoder->type = INTEL_OUTPUT_EDP; |
| 5688 | 5727 | ||
| 5689 | /* eDP only on port B and/or C on vlv/chv */ | 5728 | /* eDP only on port B and/or C on vlv/chv */ |
| 5690 | if (WARN_ON((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && | 5729 | if (WARN_ON((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && |
| 5691 | is_edp(intel_dp) && port != PORT_B && port != PORT_C)) | 5730 | is_edp(intel_dp) && port != PORT_B && port != PORT_C)) |
| 5692 | return false; | 5731 | return false; |
| 5693 | 5732 | ||
| @@ -5708,7 +5747,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 5708 | 5747 | ||
| 5709 | intel_connector_attach_encoder(intel_connector, intel_encoder); | 5748 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
| 5710 | 5749 | ||
| 5711 | if (HAS_DDI(dev)) | 5750 | if (HAS_DDI(dev_priv)) |
| 5712 | intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; | 5751 | intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; |
| 5713 | else | 5752 | else |
| 5714 | intel_connector->get_hw_state = intel_connector_get_hw_state; | 5753 | intel_connector->get_hw_state = intel_connector_get_hw_state; |
| @@ -5720,7 +5759,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 5720 | break; | 5759 | break; |
| 5721 | case PORT_B: | 5760 | case PORT_B: |
| 5722 | intel_encoder->hpd_pin = HPD_PORT_B; | 5761 | intel_encoder->hpd_pin = HPD_PORT_B; |
| 5723 | if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) | 5762 | if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) |
| 5724 | intel_encoder->hpd_pin = HPD_PORT_A; | 5763 | intel_encoder->hpd_pin = HPD_PORT_A; |
| 5725 | break; | 5764 | break; |
| 5726 | case PORT_C: | 5765 | case PORT_C: |
| @@ -5754,7 +5793,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 5754 | * 0xd. Failure to do so will result in spurious interrupts being | 5793 | * 0xd. Failure to do so will result in spurious interrupts being |
| 5755 | * generated on the port when a cable is not attached. | 5794 | * generated on the port when a cable is not attached. |
| 5756 | */ | 5795 | */ |
| 5757 | if (IS_G4X(dev) && !IS_GM45(dev)) { | 5796 | if (IS_G4X(dev_priv) && !IS_GM45(dev_priv)) { |
| 5758 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); | 5797 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); |
| 5759 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); | 5798 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); |
| 5760 | } | 5799 | } |
| @@ -5797,13 +5836,13 @@ bool intel_dp_init(struct drm_device *dev, | |||
| 5797 | intel_encoder->get_hw_state = intel_dp_get_hw_state; | 5836 | intel_encoder->get_hw_state = intel_dp_get_hw_state; |
| 5798 | intel_encoder->get_config = intel_dp_get_config; | 5837 | intel_encoder->get_config = intel_dp_get_config; |
| 5799 | intel_encoder->suspend = intel_dp_encoder_suspend; | 5838 | intel_encoder->suspend = intel_dp_encoder_suspend; |
| 5800 | if (IS_CHERRYVIEW(dev)) { | 5839 | if (IS_CHERRYVIEW(dev_priv)) { |
| 5801 | intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; | 5840 | intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; |
| 5802 | intel_encoder->pre_enable = chv_pre_enable_dp; | 5841 | intel_encoder->pre_enable = chv_pre_enable_dp; |
| 5803 | intel_encoder->enable = vlv_enable_dp; | 5842 | intel_encoder->enable = vlv_enable_dp; |
| 5804 | intel_encoder->post_disable = chv_post_disable_dp; | 5843 | intel_encoder->post_disable = chv_post_disable_dp; |
| 5805 | intel_encoder->post_pll_disable = chv_dp_post_pll_disable; | 5844 | intel_encoder->post_pll_disable = chv_dp_post_pll_disable; |
| 5806 | } else if (IS_VALLEYVIEW(dev)) { | 5845 | } else if (IS_VALLEYVIEW(dev_priv)) { |
| 5807 | intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable; | 5846 | intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable; |
| 5808 | intel_encoder->pre_enable = vlv_pre_enable_dp; | 5847 | intel_encoder->pre_enable = vlv_pre_enable_dp; |
| 5809 | intel_encoder->enable = vlv_enable_dp; | 5848 | intel_encoder->enable = vlv_enable_dp; |
| @@ -5820,7 +5859,7 @@ bool intel_dp_init(struct drm_device *dev, | |||
| 5820 | intel_dig_port->max_lanes = 4; | 5859 | intel_dig_port->max_lanes = 4; |
| 5821 | 5860 | ||
| 5822 | intel_encoder->type = INTEL_OUTPUT_DP; | 5861 | intel_encoder->type = INTEL_OUTPUT_DP; |
| 5823 | if (IS_CHERRYVIEW(dev)) { | 5862 | if (IS_CHERRYVIEW(dev_priv)) { |
| 5824 | if (port == PORT_D) | 5863 | if (port == PORT_D) |
| 5825 | intel_encoder->crtc_mask = 1 << 2; | 5864 | intel_encoder->crtc_mask = 1 << 2; |
| 5826 | else | 5865 | else |
| @@ -5829,6 +5868,7 @@ bool intel_dp_init(struct drm_device *dev, | |||
| 5829 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); | 5868 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
| 5830 | } | 5869 | } |
| 5831 | intel_encoder->cloneable = 0; | 5870 | intel_encoder->cloneable = 0; |
| 5871 | intel_encoder->port = port; | ||
| 5832 | 5872 | ||
| 5833 | intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; | 5873 | intel_dig_port->hpd_pulse = intel_dp_hpd_pulse; |
| 5834 | dev_priv->hotplug.irq_port[port] = intel_dig_port; | 5874 | dev_priv->hotplug.irq_port[port] = intel_dig_port; |
diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index c438b02184cb..0048b520baf7 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c | |||
| @@ -225,9 +225,6 @@ static u32 intel_dp_training_pattern(struct intel_dp *intel_dp) | |||
| 225 | * Intel platforms that support HBR2 also support TPS3. TPS3 support is | 225 | * Intel platforms that support HBR2 also support TPS3. TPS3 support is |
| 226 | * also mandatory for downstream devices that support HBR2. However, not | 226 | * also mandatory for downstream devices that support HBR2. However, not |
| 227 | * all sinks follow the spec. | 227 | * all sinks follow the spec. |
| 228 | * | ||
| 229 | * Due to WaDisableHBR2 SKL < B0 is the only exception where TPS3 is | ||
| 230 | * supported in source but still not enabled. | ||
| 231 | */ | 228 | */ |
| 232 | source_tps3 = intel_dp_source_supports_hbr2(intel_dp); | 229 | source_tps3 = intel_dp_source_supports_hbr2(intel_dp); |
| 233 | sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd); | 230 | sink_tps3 = drm_dp_tps3_supported(intel_dp->dpcd); |
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 54a9d7610d8f..3ffbd69e4551 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c | |||
| @@ -523,6 +523,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum | |||
| 523 | DRM_MODE_ENCODER_DPMST, "DP-MST %c", pipe_name(pipe)); | 523 | DRM_MODE_ENCODER_DPMST, "DP-MST %c", pipe_name(pipe)); |
| 524 | 524 | ||
| 525 | intel_encoder->type = INTEL_OUTPUT_DP_MST; | 525 | intel_encoder->type = INTEL_OUTPUT_DP_MST; |
| 526 | intel_encoder->port = intel_dig_port->port; | ||
| 526 | intel_encoder->crtc_mask = 0x7; | 527 | intel_encoder->crtc_mask = 0x7; |
| 527 | intel_encoder->cloneable = 0; | 528 | intel_encoder->cloneable = 0; |
| 528 | 529 | ||
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index c26d18a574b6..605d0b509f24 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c | |||
| @@ -1694,21 +1694,32 @@ bool bxt_ddi_dp_set_dpll_hw_state(int clock, | |||
| 1694 | return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state); | 1694 | return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state); |
| 1695 | } | 1695 | } |
| 1696 | 1696 | ||
| 1697 | static bool | ||
| 1698 | bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc *intel_crtc, | ||
| 1699 | struct intel_crtc_state *crtc_state, int clock, | ||
| 1700 | struct intel_dpll_hw_state *dpll_hw_state) | ||
| 1701 | { | ||
| 1702 | struct bxt_clk_div clk_div = { }; | ||
| 1703 | |||
| 1704 | bxt_ddi_hdmi_pll_dividers(intel_crtc, crtc_state, clock, &clk_div); | ||
| 1705 | |||
| 1706 | return bxt_ddi_set_dpll_hw_state(clock, &clk_div, dpll_hw_state); | ||
| 1707 | } | ||
| 1708 | |||
| 1697 | static struct intel_shared_dpll * | 1709 | static struct intel_shared_dpll * |
| 1698 | bxt_get_dpll(struct intel_crtc *crtc, | 1710 | bxt_get_dpll(struct intel_crtc *crtc, |
| 1699 | struct intel_crtc_state *crtc_state, | 1711 | struct intel_crtc_state *crtc_state, |
| 1700 | struct intel_encoder *encoder) | 1712 | struct intel_encoder *encoder) |
| 1701 | { | 1713 | { |
| 1702 | struct bxt_clk_div clk_div = {0}; | 1714 | struct intel_dpll_hw_state dpll_hw_state = { }; |
| 1703 | struct intel_dpll_hw_state dpll_hw_state = {0}; | ||
| 1704 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); | 1715 | struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); |
| 1705 | struct intel_digital_port *intel_dig_port; | 1716 | struct intel_digital_port *intel_dig_port; |
| 1706 | struct intel_shared_dpll *pll; | 1717 | struct intel_shared_dpll *pll; |
| 1707 | int i, clock = crtc_state->port_clock; | 1718 | int i, clock = crtc_state->port_clock; |
| 1708 | 1719 | ||
| 1709 | if (encoder->type == INTEL_OUTPUT_HDMI | 1720 | if (encoder->type == INTEL_OUTPUT_HDMI && |
| 1710 | && !bxt_ddi_hdmi_pll_dividers(crtc, crtc_state, | 1721 | !bxt_ddi_hdmi_set_dpll_hw_state(crtc, crtc_state, clock, |
| 1711 | clock, &clk_div)) | 1722 | &dpll_hw_state)) |
| 1712 | return NULL; | 1723 | return NULL; |
| 1713 | 1724 | ||
| 1714 | if ((encoder->type == INTEL_OUTPUT_DP || | 1725 | if ((encoder->type == INTEL_OUTPUT_DP || |
| @@ -1840,13 +1851,13 @@ void intel_shared_dpll_init(struct drm_device *dev) | |||
| 1840 | const struct dpll_info *dpll_info; | 1851 | const struct dpll_info *dpll_info; |
| 1841 | int i; | 1852 | int i; |
| 1842 | 1853 | ||
| 1843 | if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) | 1854 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) |
| 1844 | dpll_mgr = &skl_pll_mgr; | 1855 | dpll_mgr = &skl_pll_mgr; |
| 1845 | else if (IS_BROXTON(dev)) | 1856 | else if (IS_BROXTON(dev_priv)) |
| 1846 | dpll_mgr = &bxt_pll_mgr; | 1857 | dpll_mgr = &bxt_pll_mgr; |
| 1847 | else if (HAS_DDI(dev)) | 1858 | else if (HAS_DDI(dev_priv)) |
| 1848 | dpll_mgr = &hsw_pll_mgr; | 1859 | dpll_mgr = &hsw_pll_mgr; |
| 1849 | else if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) | 1860 | else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) |
| 1850 | dpll_mgr = &pch_pll_mgr; | 1861 | dpll_mgr = &pch_pll_mgr; |
| 1851 | 1862 | ||
| 1852 | if (!dpll_mgr) { | 1863 | if (!dpll_mgr) { |
| @@ -1872,7 +1883,7 @@ void intel_shared_dpll_init(struct drm_device *dev) | |||
| 1872 | BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); | 1883 | BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS); |
| 1873 | 1884 | ||
| 1874 | /* FIXME: Move this to a more suitable place */ | 1885 | /* FIXME: Move this to a more suitable place */ |
| 1875 | if (HAS_DDI(dev)) | 1886 | if (HAS_DDI(dev_priv)) |
| 1876 | intel_ddi_pll_init(dev); | 1887 | intel_ddi_pll_init(dev); |
| 1877 | } | 1888 | } |
| 1878 | 1889 | ||
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5145ff264c8e..4e90b0760f3f 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
| @@ -206,6 +206,7 @@ struct intel_encoder { | |||
| 206 | struct drm_encoder base; | 206 | struct drm_encoder base; |
| 207 | 207 | ||
| 208 | enum intel_output_type type; | 208 | enum intel_output_type type; |
| 209 | enum port port; | ||
| 209 | unsigned int cloneable; | 210 | unsigned int cloneable; |
| 210 | void (*hot_plug)(struct intel_encoder *); | 211 | void (*hot_plug)(struct intel_encoder *); |
| 211 | bool (*compute_config)(struct intel_encoder *, | 212 | bool (*compute_config)(struct intel_encoder *, |
| @@ -247,6 +248,8 @@ struct intel_encoder { | |||
| 247 | void (*suspend)(struct intel_encoder *); | 248 | void (*suspend)(struct intel_encoder *); |
| 248 | int crtc_mask; | 249 | int crtc_mask; |
| 249 | enum hpd_pin hpd_pin; | 250 | enum hpd_pin hpd_pin; |
| 251 | /* for communication with audio component; protected by av_mutex */ | ||
| 252 | const struct drm_connector *audio_connector; | ||
| 250 | }; | 253 | }; |
| 251 | 254 | ||
| 252 | struct intel_panel { | 255 | struct intel_panel { |
| @@ -263,6 +266,7 @@ struct intel_panel { | |||
| 263 | bool enabled; | 266 | bool enabled; |
| 264 | bool combination_mode; /* gen 2/4 only */ | 267 | bool combination_mode; /* gen 2/4 only */ |
| 265 | bool active_low_pwm; | 268 | bool active_low_pwm; |
| 269 | bool alternate_pwm_increment; /* lpt+ */ | ||
| 266 | 270 | ||
| 267 | /* PWM chip */ | 271 | /* PWM chip */ |
| 268 | bool util_pin_active_low; /* bxt+ */ | 272 | bool util_pin_active_low; /* bxt+ */ |
| @@ -464,9 +468,13 @@ struct intel_pipe_wm { | |||
| 464 | bool sprites_scaled; | 468 | bool sprites_scaled; |
| 465 | }; | 469 | }; |
| 466 | 470 | ||
| 467 | struct skl_pipe_wm { | 471 | struct skl_plane_wm { |
| 468 | struct skl_wm_level wm[8]; | 472 | struct skl_wm_level wm[8]; |
| 469 | struct skl_wm_level trans_wm; | 473 | struct skl_wm_level trans_wm; |
| 474 | }; | ||
| 475 | |||
| 476 | struct skl_pipe_wm { | ||
| 477 | struct skl_plane_wm planes[I915_MAX_PLANES]; | ||
| 470 | uint32_t linetime; | 478 | uint32_t linetime; |
| 471 | }; | 479 | }; |
| 472 | 480 | ||
| @@ -492,6 +500,7 @@ struct intel_crtc_wm_state { | |||
| 492 | struct { | 500 | struct { |
| 493 | /* gen9+ only needs 1-step wm programming */ | 501 | /* gen9+ only needs 1-step wm programming */ |
| 494 | struct skl_pipe_wm optimal; | 502 | struct skl_pipe_wm optimal; |
| 503 | struct skl_ddb_entry ddb; | ||
| 495 | 504 | ||
| 496 | /* cached plane data rate */ | 505 | /* cached plane data rate */ |
| 497 | unsigned plane_data_rate[I915_MAX_PLANES]; | 506 | unsigned plane_data_rate[I915_MAX_PLANES]; |
| @@ -729,6 +738,9 @@ struct intel_crtc { | |||
| 729 | bool cxsr_allowed; | 738 | bool cxsr_allowed; |
| 730 | } wm; | 739 | } wm; |
| 731 | 740 | ||
| 741 | /* gen9+: ddb allocation currently being used */ | ||
| 742 | struct skl_ddb_entry hw_ddb; | ||
| 743 | |||
| 732 | int scanline_offset; | 744 | int scanline_offset; |
| 733 | 745 | ||
| 734 | struct { | 746 | struct { |
| @@ -795,22 +807,22 @@ struct intel_plane { | |||
| 795 | }; | 807 | }; |
| 796 | 808 | ||
| 797 | struct intel_watermark_params { | 809 | struct intel_watermark_params { |
| 798 | unsigned long fifo_size; | 810 | u16 fifo_size; |
| 799 | unsigned long max_wm; | 811 | u16 max_wm; |
| 800 | unsigned long default_wm; | 812 | u8 default_wm; |
| 801 | unsigned long guard_size; | 813 | u8 guard_size; |
| 802 | unsigned long cacheline_size; | 814 | u8 cacheline_size; |
| 803 | }; | 815 | }; |
| 804 | 816 | ||
| 805 | struct cxsr_latency { | 817 | struct cxsr_latency { |
| 806 | int is_desktop; | 818 | bool is_desktop : 1; |
| 807 | int is_ddr3; | 819 | bool is_ddr3 : 1; |
| 808 | unsigned long fsb_freq; | 820 | u16 fsb_freq; |
| 809 | unsigned long mem_freq; | 821 | u16 mem_freq; |
| 810 | unsigned long display_sr; | 822 | u16 display_sr; |
| 811 | unsigned long display_hpll_disable; | 823 | u16 display_hpll_disable; |
| 812 | unsigned long cursor_sr; | 824 | u16 cursor_sr; |
| 813 | unsigned long cursor_hpll_disable; | 825 | u16 cursor_hpll_disable; |
| 814 | }; | 826 | }; |
| 815 | 827 | ||
| 816 | #define to_intel_atomic_state(x) container_of(x, struct intel_atomic_state, base) | 828 | #define to_intel_atomic_state(x) container_of(x, struct intel_atomic_state, base) |
| @@ -949,17 +961,22 @@ struct intel_dp { | |||
| 949 | bool compliance_test_active; | 961 | bool compliance_test_active; |
| 950 | }; | 962 | }; |
| 951 | 963 | ||
| 964 | struct intel_lspcon { | ||
| 965 | bool active; | ||
| 966 | enum drm_lspcon_mode mode; | ||
| 967 | struct drm_dp_aux *aux; | ||
| 968 | }; | ||
| 969 | |||
| 952 | struct intel_digital_port { | 970 | struct intel_digital_port { |
| 953 | struct intel_encoder base; | 971 | struct intel_encoder base; |
| 954 | enum port port; | 972 | enum port port; |
| 955 | u32 saved_port_bits; | 973 | u32 saved_port_bits; |
| 956 | struct intel_dp dp; | 974 | struct intel_dp dp; |
| 957 | struct intel_hdmi hdmi; | 975 | struct intel_hdmi hdmi; |
| 976 | struct intel_lspcon lspcon; | ||
| 958 | enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool); | 977 | enum irqreturn (*hpd_pulse)(struct intel_digital_port *, bool); |
| 959 | bool release_cl2_override; | 978 | bool release_cl2_override; |
| 960 | uint8_t max_lanes; | 979 | uint8_t max_lanes; |
| 961 | /* for communication with audio component; protected by av_mutex */ | ||
| 962 | const struct drm_connector *audio_connector; | ||
| 963 | }; | 980 | }; |
| 964 | 981 | ||
| 965 | struct intel_dp_mst_encoder { | 982 | struct intel_dp_mst_encoder { |
| @@ -1181,6 +1198,7 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv); | |||
| 1181 | void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); | 1198 | void i915_audio_component_cleanup(struct drm_i915_private *dev_priv); |
| 1182 | 1199 | ||
| 1183 | /* intel_display.c */ | 1200 | /* intel_display.c */ |
| 1201 | enum transcoder intel_crtc_pch_transcoder(struct intel_crtc *crtc); | ||
| 1184 | void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco); | 1202 | void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco); |
| 1185 | void intel_update_rawclk(struct drm_i915_private *dev_priv); | 1203 | void intel_update_rawclk(struct drm_i915_private *dev_priv); |
| 1186 | int vlv_get_cck_clock(struct drm_i915_private *dev_priv, | 1204 | int vlv_get_cck_clock(struct drm_i915_private *dev_priv, |
| @@ -1477,6 +1495,10 @@ static inline void intel_fbdev_set_suspend(struct drm_device *dev, int state, bo | |||
| 1477 | { | 1495 | { |
| 1478 | } | 1496 | } |
| 1479 | 1497 | ||
| 1498 | static inline void intel_fbdev_output_poll_changed(struct drm_device *dev) | ||
| 1499 | { | ||
| 1500 | } | ||
| 1501 | |||
| 1480 | static inline void intel_fbdev_restore_mode(struct drm_device *dev) | 1502 | static inline void intel_fbdev_restore_mode(struct drm_device *dev) |
| 1481 | { | 1503 | { |
| 1482 | } | 1504 | } |
| @@ -1503,6 +1525,7 @@ void intel_fbc_invalidate(struct drm_i915_private *dev_priv, | |||
| 1503 | void intel_fbc_flush(struct drm_i915_private *dev_priv, | 1525 | void intel_fbc_flush(struct drm_i915_private *dev_priv, |
| 1504 | unsigned int frontbuffer_bits, enum fb_op_origin origin); | 1526 | unsigned int frontbuffer_bits, enum fb_op_origin origin); |
| 1505 | void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); | 1527 | void intel_fbc_cleanup_cfb(struct drm_i915_private *dev_priv); |
| 1528 | void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv); | ||
| 1506 | 1529 | ||
| 1507 | /* intel_hdmi.c */ | 1530 | /* intel_hdmi.c */ |
| 1508 | void intel_hdmi_init(struct drm_device *dev, i915_reg_t hdmi_reg, enum port port); | 1531 | void intel_hdmi_init(struct drm_device *dev, i915_reg_t hdmi_reg, enum port port); |
| @@ -1706,7 +1729,7 @@ bool chv_phy_powergate_ch(struct drm_i915_private *dev_priv, enum dpio_phy phy, | |||
| 1706 | /* intel_pm.c */ | 1729 | /* intel_pm.c */ |
| 1707 | void intel_init_clock_gating(struct drm_device *dev); | 1730 | void intel_init_clock_gating(struct drm_device *dev); |
| 1708 | void intel_suspend_hw(struct drm_device *dev); | 1731 | void intel_suspend_hw(struct drm_device *dev); |
| 1709 | int ilk_wm_max_level(const struct drm_device *dev); | 1732 | int ilk_wm_max_level(const struct drm_i915_private *dev_priv); |
| 1710 | void intel_update_watermarks(struct drm_crtc *crtc); | 1733 | void intel_update_watermarks(struct drm_crtc *crtc); |
| 1711 | void intel_init_pm(struct drm_device *dev); | 1734 | void intel_init_pm(struct drm_device *dev); |
| 1712 | void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv); | 1735 | void intel_init_clock_gating_hooks(struct drm_i915_private *dev_priv); |
| @@ -1732,20 +1755,24 @@ void ilk_wm_get_hw_state(struct drm_device *dev); | |||
| 1732 | void skl_wm_get_hw_state(struct drm_device *dev); | 1755 | void skl_wm_get_hw_state(struct drm_device *dev); |
| 1733 | void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, | 1756 | void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, |
| 1734 | struct skl_ddb_allocation *ddb /* out */); | 1757 | struct skl_ddb_allocation *ddb /* out */); |
| 1735 | bool skl_can_enable_sagv(struct drm_atomic_state *state); | 1758 | void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc, |
| 1736 | int skl_enable_sagv(struct drm_i915_private *dev_priv); | 1759 | struct skl_pipe_wm *out); |
| 1737 | int skl_disable_sagv(struct drm_i915_private *dev_priv); | 1760 | bool intel_can_enable_sagv(struct drm_atomic_state *state); |
| 1761 | int intel_enable_sagv(struct drm_i915_private *dev_priv); | ||
| 1762 | int intel_disable_sagv(struct drm_i915_private *dev_priv); | ||
| 1763 | bool skl_wm_level_equals(const struct skl_wm_level *l1, | ||
| 1764 | const struct skl_wm_level *l2); | ||
| 1738 | bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old, | 1765 | bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old, |
| 1739 | const struct skl_ddb_allocation *new, | 1766 | const struct skl_ddb_allocation *new, |
| 1740 | enum pipe pipe); | 1767 | enum pipe pipe); |
| 1741 | bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state, | 1768 | bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state, |
| 1742 | const struct skl_ddb_allocation *old, | 1769 | struct intel_crtc *intel_crtc); |
| 1743 | const struct skl_ddb_allocation *new, | ||
| 1744 | enum pipe pipe); | ||
| 1745 | void skl_write_cursor_wm(struct intel_crtc *intel_crtc, | 1770 | void skl_write_cursor_wm(struct intel_crtc *intel_crtc, |
| 1746 | const struct skl_wm_values *wm); | 1771 | const struct skl_plane_wm *wm, |
| 1772 | const struct skl_ddb_allocation *ddb); | ||
| 1747 | void skl_write_plane_wm(struct intel_crtc *intel_crtc, | 1773 | void skl_write_plane_wm(struct intel_crtc *intel_crtc, |
| 1748 | const struct skl_wm_values *wm, | 1774 | const struct skl_plane_wm *wm, |
| 1775 | const struct skl_ddb_allocation *ddb, | ||
| 1749 | int plane); | 1776 | int plane); |
| 1750 | uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); | 1777 | uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); |
| 1751 | bool ilk_disable_lp_wm(struct drm_device *dev); | 1778 | bool ilk_disable_lp_wm(struct drm_device *dev); |
| @@ -1825,4 +1852,7 @@ int intel_color_check(struct drm_crtc *crtc, struct drm_crtc_state *state); | |||
| 1825 | void intel_color_set_csc(struct drm_crtc_state *crtc_state); | 1852 | void intel_color_set_csc(struct drm_crtc_state *crtc_state); |
| 1826 | void intel_color_load_luts(struct drm_crtc_state *crtc_state); | 1853 | void intel_color_load_luts(struct drm_crtc_state *crtc_state); |
| 1827 | 1854 | ||
| 1855 | /* intel_lspcon.c */ | ||
| 1856 | bool lspcon_init(struct intel_digital_port *intel_dig_port); | ||
| 1857 | void lspcon_resume(struct intel_lspcon *lspcon); | ||
| 1828 | #endif /* __INTEL_DRV_H__ */ | 1858 | #endif /* __INTEL_DRV_H__ */ |
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index b2e3d3a334f7..4e0d025490a3 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c | |||
| @@ -437,11 +437,11 @@ static void vlv_dsi_device_ready(struct intel_encoder *encoder) | |||
| 437 | 437 | ||
| 438 | static void intel_dsi_device_ready(struct intel_encoder *encoder) | 438 | static void intel_dsi_device_ready(struct intel_encoder *encoder) |
| 439 | { | 439 | { |
| 440 | struct drm_device *dev = encoder->base.dev; | 440 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 441 | 441 | ||
| 442 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 442 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 443 | vlv_dsi_device_ready(encoder); | 443 | vlv_dsi_device_ready(encoder); |
| 444 | else if (IS_BROXTON(dev)) | 444 | else if (IS_BROXTON(dev_priv)) |
| 445 | bxt_dsi_device_ready(encoder); | 445 | bxt_dsi_device_ready(encoder); |
| 446 | } | 446 | } |
| 447 | 447 | ||
| @@ -464,7 +464,7 @@ static void intel_dsi_port_enable(struct intel_encoder *encoder) | |||
| 464 | } | 464 | } |
| 465 | 465 | ||
| 466 | for_each_dsi_port(port, intel_dsi->ports) { | 466 | for_each_dsi_port(port, intel_dsi->ports) { |
| 467 | i915_reg_t port_ctrl = IS_BROXTON(dev) ? | 467 | i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ? |
| 468 | BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); | 468 | BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); |
| 469 | u32 temp; | 469 | u32 temp; |
| 470 | 470 | ||
| @@ -494,7 +494,7 @@ static void intel_dsi_port_disable(struct intel_encoder *encoder) | |||
| 494 | enum port port; | 494 | enum port port; |
| 495 | 495 | ||
| 496 | for_each_dsi_port(port, intel_dsi->ports) { | 496 | for_each_dsi_port(port, intel_dsi->ports) { |
| 497 | i915_reg_t port_ctrl = IS_BROXTON(dev) ? | 497 | i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ? |
| 498 | BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); | 498 | BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); |
| 499 | u32 temp; | 499 | u32 temp; |
| 500 | 500 | ||
| @@ -656,7 +656,6 @@ static void intel_dsi_disable(struct intel_encoder *encoder) | |||
| 656 | 656 | ||
| 657 | static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) | 657 | static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) |
| 658 | { | 658 | { |
| 659 | struct drm_device *dev = encoder->base.dev; | ||
| 660 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 659 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 661 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | 660 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
| 662 | enum port port; | 661 | enum port port; |
| @@ -664,7 +663,7 @@ static void intel_dsi_clear_device_ready(struct intel_encoder *encoder) | |||
| 664 | DRM_DEBUG_KMS("\n"); | 663 | DRM_DEBUG_KMS("\n"); |
| 665 | for_each_dsi_port(port, intel_dsi->ports) { | 664 | for_each_dsi_port(port, intel_dsi->ports) { |
| 666 | /* Common bit for both MIPI Port A & MIPI Port C on VLV/CHV */ | 665 | /* Common bit for both MIPI Port A & MIPI Port C on VLV/CHV */ |
| 667 | i915_reg_t port_ctrl = IS_BROXTON(dev) ? | 666 | i915_reg_t port_ctrl = IS_BROXTON(dev_priv) ? |
| 668 | BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(PORT_A); | 667 | BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(PORT_A); |
| 669 | u32 val; | 668 | u32 val; |
| 670 | 669 | ||
| @@ -741,7 +740,6 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, | |||
| 741 | { | 740 | { |
| 742 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); | 741 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 743 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); | 742 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); |
| 744 | struct drm_device *dev = encoder->base.dev; | ||
| 745 | enum intel_display_power_domain power_domain; | 743 | enum intel_display_power_domain power_domain; |
| 746 | enum port port; | 744 | enum port port; |
| 747 | bool active = false; | 745 | bool active = false; |
| @@ -762,7 +760,7 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, | |||
| 762 | 760 | ||
| 763 | /* XXX: this only works for one DSI output */ | 761 | /* XXX: this only works for one DSI output */ |
| 764 | for_each_dsi_port(port, intel_dsi->ports) { | 762 | for_each_dsi_port(port, intel_dsi->ports) { |
| 765 | i915_reg_t ctrl_reg = IS_BROXTON(dev) ? | 763 | i915_reg_t ctrl_reg = IS_BROXTON(dev_priv) ? |
| 766 | BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); | 764 | BXT_MIPI_PORT_CTRL(port) : MIPI_PORT_CTRL(port); |
| 767 | bool enabled = I915_READ(ctrl_reg) & DPI_ENABLE; | 765 | bool enabled = I915_READ(ctrl_reg) & DPI_ENABLE; |
| 768 | 766 | ||
| @@ -771,7 +769,8 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, | |||
| 771 | * bit in port C control register does not get set. As a | 769 | * bit in port C control register does not get set. As a |
| 772 | * workaround, check pipe B conf instead. | 770 | * workaround, check pipe B conf instead. |
| 773 | */ | 771 | */ |
| 774 | if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && port == PORT_C) | 772 | if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && |
| 773 | port == PORT_C) | ||
| 775 | enabled = I915_READ(PIPECONF(PIPE_B)) & PIPECONF_ENABLE; | 774 | enabled = I915_READ(PIPECONF(PIPE_B)) & PIPECONF_ENABLE; |
| 776 | 775 | ||
| 777 | /* Try command mode if video mode not enabled */ | 776 | /* Try command mode if video mode not enabled */ |
| @@ -970,11 +969,11 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, | |||
| 970 | static void intel_dsi_get_config(struct intel_encoder *encoder, | 969 | static void intel_dsi_get_config(struct intel_encoder *encoder, |
| 971 | struct intel_crtc_state *pipe_config) | 970 | struct intel_crtc_state *pipe_config) |
| 972 | { | 971 | { |
| 973 | struct drm_device *dev = encoder->base.dev; | 972 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 974 | u32 pclk; | 973 | u32 pclk; |
| 975 | DRM_DEBUG_KMS("\n"); | 974 | DRM_DEBUG_KMS("\n"); |
| 976 | 975 | ||
| 977 | if (IS_BROXTON(dev)) | 976 | if (IS_BROXTON(dev_priv)) |
| 978 | bxt_dsi_get_pipe_config(encoder, pipe_config); | 977 | bxt_dsi_get_pipe_config(encoder, pipe_config); |
| 979 | 978 | ||
| 980 | pclk = intel_dsi_get_pclk(encoder, pipe_config->pipe_bpp, | 979 | pclk = intel_dsi_get_pclk(encoder, pipe_config->pipe_bpp, |
| @@ -1066,7 +1065,7 @@ static void set_dsi_timings(struct drm_encoder *encoder, | |||
| 1066 | hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio); | 1065 | hbp = txbyteclkhs(hbp, bpp, lane_count, intel_dsi->burst_mode_ratio); |
| 1067 | 1066 | ||
| 1068 | for_each_dsi_port(port, intel_dsi->ports) { | 1067 | for_each_dsi_port(port, intel_dsi->ports) { |
| 1069 | if (IS_BROXTON(dev)) { | 1068 | if (IS_BROXTON(dev_priv)) { |
| 1070 | /* | 1069 | /* |
| 1071 | * Program hdisplay and vdisplay on MIPI transcoder. | 1070 | * Program hdisplay and vdisplay on MIPI transcoder. |
| 1072 | * This is different from calculated hactive and | 1071 | * This is different from calculated hactive and |
| @@ -1138,7 +1137,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, | |||
| 1138 | } | 1137 | } |
| 1139 | 1138 | ||
| 1140 | for_each_dsi_port(port, intel_dsi->ports) { | 1139 | for_each_dsi_port(port, intel_dsi->ports) { |
| 1141 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 1140 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 1142 | /* | 1141 | /* |
| 1143 | * escape clock divider, 20MHz, shared for A and C. | 1142 | * escape clock divider, 20MHz, shared for A and C. |
| 1144 | * device ready must be off when doing this! txclkesc? | 1143 | * device ready must be off when doing this! txclkesc? |
| @@ -1153,7 +1152,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, | |||
| 1153 | tmp &= ~READ_REQUEST_PRIORITY_MASK; | 1152 | tmp &= ~READ_REQUEST_PRIORITY_MASK; |
| 1154 | I915_WRITE(MIPI_CTRL(port), tmp | | 1153 | I915_WRITE(MIPI_CTRL(port), tmp | |
| 1155 | READ_REQUEST_PRIORITY_HIGH); | 1154 | READ_REQUEST_PRIORITY_HIGH); |
| 1156 | } else if (IS_BROXTON(dev)) { | 1155 | } else if (IS_BROXTON(dev_priv)) { |
| 1157 | enum pipe pipe = intel_crtc->pipe; | 1156 | enum pipe pipe = intel_crtc->pipe; |
| 1158 | 1157 | ||
| 1159 | tmp = I915_READ(MIPI_CTRL(port)); | 1158 | tmp = I915_READ(MIPI_CTRL(port)); |
| @@ -1242,7 +1241,7 @@ static void intel_dsi_prepare(struct intel_encoder *intel_encoder, | |||
| 1242 | I915_WRITE(MIPI_INIT_COUNT(port), | 1241 | I915_WRITE(MIPI_INIT_COUNT(port), |
| 1243 | txclkesc(intel_dsi->escape_clk_div, 100)); | 1242 | txclkesc(intel_dsi->escape_clk_div, 100)); |
| 1244 | 1243 | ||
| 1245 | if (IS_BROXTON(dev) && (!intel_dsi->dual_link)) { | 1244 | if (IS_BROXTON(dev_priv) && (!intel_dsi->dual_link)) { |
| 1246 | /* | 1245 | /* |
| 1247 | * BXT spec says write MIPI_INIT_COUNT for | 1246 | * BXT spec says write MIPI_INIT_COUNT for |
| 1248 | * both the ports, even if only one is | 1247 | * both the ports, even if only one is |
| @@ -1346,7 +1345,7 @@ static int intel_dsi_set_property(struct drm_connector *connector, | |||
| 1346 | DRM_DEBUG_KMS("no scaling not supported\n"); | 1345 | DRM_DEBUG_KMS("no scaling not supported\n"); |
| 1347 | return -EINVAL; | 1346 | return -EINVAL; |
| 1348 | } | 1347 | } |
| 1349 | if (HAS_GMCH_DISPLAY(dev) && | 1348 | if (HAS_GMCH_DISPLAY(to_i915(dev)) && |
| 1350 | val == DRM_MODE_SCALE_CENTER) { | 1349 | val == DRM_MODE_SCALE_CENTER) { |
| 1351 | DRM_DEBUG_KMS("centering not supported\n"); | 1350 | DRM_DEBUG_KMS("centering not supported\n"); |
| 1352 | return -EINVAL; | 1351 | return -EINVAL; |
| @@ -1450,9 +1449,9 @@ void intel_dsi_init(struct drm_device *dev) | |||
| 1450 | if (!intel_bios_is_dsi_present(dev_priv, &port)) | 1449 | if (!intel_bios_is_dsi_present(dev_priv, &port)) |
| 1451 | return; | 1450 | return; |
| 1452 | 1451 | ||
| 1453 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 1452 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 1454 | dev_priv->mipi_mmio_base = VLV_MIPI_BASE; | 1453 | dev_priv->mipi_mmio_base = VLV_MIPI_BASE; |
| 1455 | } else if (IS_BROXTON(dev)) { | 1454 | } else if (IS_BROXTON(dev_priv)) { |
| 1456 | dev_priv->mipi_mmio_base = BXT_MIPI_BASE; | 1455 | dev_priv->mipi_mmio_base = BXT_MIPI_BASE; |
| 1457 | } else { | 1456 | } else { |
| 1458 | DRM_ERROR("Unsupported Mipi device to reg base"); | 1457 | DRM_ERROR("Unsupported Mipi device to reg base"); |
| @@ -1488,6 +1487,7 @@ void intel_dsi_init(struct drm_device *dev) | |||
| 1488 | 1487 | ||
| 1489 | intel_connector->get_hw_state = intel_connector_get_hw_state; | 1488 | intel_connector->get_hw_state = intel_connector_get_hw_state; |
| 1490 | 1489 | ||
| 1490 | intel_encoder->port = port; | ||
| 1491 | /* | 1491 | /* |
| 1492 | * On BYT/CHV, pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI | 1492 | * On BYT/CHV, pipe A maps to MIPI DSI port A, pipe B maps to MIPI DSI |
| 1493 | * port C. BXT isn't limited like this. | 1493 | * port C. BXT isn't limited like this. |
diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index cd154ce6b6c1..9f279a3d0f74 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | |||
| @@ -126,6 +126,8 @@ static const u8 *mipi_exec_send_packet(struct intel_dsi *intel_dsi, | |||
| 126 | u16 len; | 126 | u16 len; |
| 127 | enum port port; | 127 | enum port port; |
| 128 | 128 | ||
| 129 | DRM_DEBUG_KMS("\n"); | ||
| 130 | |||
| 129 | flags = *data++; | 131 | flags = *data++; |
| 130 | type = *data++; | 132 | type = *data++; |
| 131 | 133 | ||
| @@ -199,6 +201,8 @@ static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data) | |||
| 199 | { | 201 | { |
| 200 | u32 delay = *((const u32 *) data); | 202 | u32 delay = *((const u32 *) data); |
| 201 | 203 | ||
| 204 | DRM_DEBUG_KMS("\n"); | ||
| 205 | |||
| 202 | usleep_range(delay, delay + 10); | 206 | usleep_range(delay, delay + 10); |
| 203 | data += 4; | 207 | data += 4; |
| 204 | 208 | ||
| @@ -307,6 +311,8 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) | |||
| 307 | u8 gpio_source, gpio_index; | 311 | u8 gpio_source, gpio_index; |
| 308 | bool value; | 312 | bool value; |
| 309 | 313 | ||
| 314 | DRM_DEBUG_KMS("\n"); | ||
| 315 | |||
| 310 | if (dev_priv->vbt.dsi.seq_version >= 3) | 316 | if (dev_priv->vbt.dsi.seq_version >= 3) |
| 311 | data++; | 317 | data++; |
| 312 | 318 | ||
| @@ -331,18 +337,36 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) | |||
| 331 | return data; | 337 | return data; |
| 332 | } | 338 | } |
| 333 | 339 | ||
| 334 | static const u8 *mipi_exec_i2c_skip(struct intel_dsi *intel_dsi, const u8 *data) | 340 | static const u8 *mipi_exec_i2c(struct intel_dsi *intel_dsi, const u8 *data) |
| 335 | { | 341 | { |
| 342 | DRM_DEBUG_KMS("Skipping I2C element execution\n"); | ||
| 343 | |||
| 336 | return data + *(data + 6) + 7; | 344 | return data + *(data + 6) + 7; |
| 337 | } | 345 | } |
| 338 | 346 | ||
| 347 | static const u8 *mipi_exec_spi(struct intel_dsi *intel_dsi, const u8 *data) | ||
| 348 | { | ||
| 349 | DRM_DEBUG_KMS("Skipping SPI element execution\n"); | ||
| 350 | |||
| 351 | return data + *(data + 5) + 6; | ||
| 352 | } | ||
| 353 | |||
| 354 | static const u8 *mipi_exec_pmic(struct intel_dsi *intel_dsi, const u8 *data) | ||
| 355 | { | ||
| 356 | DRM_DEBUG_KMS("Skipping PMIC element execution\n"); | ||
| 357 | |||
| 358 | return data + 15; | ||
| 359 | } | ||
| 360 | |||
| 339 | typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi, | 361 | typedef const u8 * (*fn_mipi_elem_exec)(struct intel_dsi *intel_dsi, |
| 340 | const u8 *data); | 362 | const u8 *data); |
| 341 | static const fn_mipi_elem_exec exec_elem[] = { | 363 | static const fn_mipi_elem_exec exec_elem[] = { |
| 342 | [MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet, | 364 | [MIPI_SEQ_ELEM_SEND_PKT] = mipi_exec_send_packet, |
| 343 | [MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay, | 365 | [MIPI_SEQ_ELEM_DELAY] = mipi_exec_delay, |
| 344 | [MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio, | 366 | [MIPI_SEQ_ELEM_GPIO] = mipi_exec_gpio, |
| 345 | [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c_skip, | 367 | [MIPI_SEQ_ELEM_I2C] = mipi_exec_i2c, |
| 368 | [MIPI_SEQ_ELEM_SPI] = mipi_exec_spi, | ||
| 369 | [MIPI_SEQ_ELEM_PMIC] = mipi_exec_pmic, | ||
| 346 | }; | 370 | }; |
| 347 | 371 | ||
| 348 | /* | 372 | /* |
| @@ -385,11 +409,8 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id) | |||
| 385 | return; | 409 | return; |
| 386 | 410 | ||
| 387 | data = dev_priv->vbt.dsi.sequence[seq_id]; | 411 | data = dev_priv->vbt.dsi.sequence[seq_id]; |
| 388 | if (!data) { | 412 | if (!data) |
| 389 | DRM_DEBUG_KMS("MIPI sequence %d - %s not available\n", | ||
| 390 | seq_id, sequence_name(seq_id)); | ||
| 391 | return; | 413 | return; |
| 392 | } | ||
| 393 | 414 | ||
| 394 | WARN_ON(*data != seq_id); | 415 | WARN_ON(*data != seq_id); |
| 395 | 416 | ||
| @@ -420,7 +441,15 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id) | |||
| 420 | operation_size = *data++; | 441 | operation_size = *data++; |
| 421 | 442 | ||
| 422 | if (mipi_elem_exec) { | 443 | if (mipi_elem_exec) { |
| 444 | const u8 *next = data + operation_size; | ||
| 445 | |||
| 423 | data = mipi_elem_exec(intel_dsi, data); | 446 | data = mipi_elem_exec(intel_dsi, data); |
| 447 | |||
| 448 | /* Consistency check if we have size. */ | ||
| 449 | if (operation_size && data != next) { | ||
| 450 | DRM_ERROR("Inconsistent operation size\n"); | ||
| 451 | return; | ||
| 452 | } | ||
| 424 | } else if (operation_size) { | 453 | } else if (operation_size) { |
| 425 | /* We have size, skip. */ | 454 | /* We have size, skip. */ |
| 426 | DRM_DEBUG_KMS("Unsupported MIPI operation byte %u\n", | 455 | DRM_DEBUG_KMS("Unsupported MIPI operation byte %u\n", |
| @@ -438,6 +467,8 @@ static void generic_exec_sequence(struct drm_panel *panel, enum mipi_seq seq_id) | |||
| 438 | static int vbt_panel_prepare(struct drm_panel *panel) | 467 | static int vbt_panel_prepare(struct drm_panel *panel) |
| 439 | { | 468 | { |
| 440 | generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET); | 469 | generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET); |
| 470 | generic_exec_sequence(panel, MIPI_SEQ_POWER_ON); | ||
| 471 | generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET); | ||
| 441 | generic_exec_sequence(panel, MIPI_SEQ_INIT_OTP); | 472 | generic_exec_sequence(panel, MIPI_SEQ_INIT_OTP); |
| 442 | 473 | ||
| 443 | return 0; | 474 | return 0; |
| @@ -445,7 +476,8 @@ static int vbt_panel_prepare(struct drm_panel *panel) | |||
| 445 | 476 | ||
| 446 | static int vbt_panel_unprepare(struct drm_panel *panel) | 477 | static int vbt_panel_unprepare(struct drm_panel *panel) |
| 447 | { | 478 | { |
| 448 | generic_exec_sequence(panel, MIPI_SEQ_DEASSERT_RESET); | 479 | generic_exec_sequence(panel, MIPI_SEQ_ASSERT_RESET); |
| 480 | generic_exec_sequence(panel, MIPI_SEQ_POWER_OFF); | ||
| 449 | 481 | ||
| 450 | return 0; | 482 | return 0; |
| 451 | } | 483 | } |
| @@ -453,12 +485,14 @@ static int vbt_panel_unprepare(struct drm_panel *panel) | |||
| 453 | static int vbt_panel_enable(struct drm_panel *panel) | 485 | static int vbt_panel_enable(struct drm_panel *panel) |
| 454 | { | 486 | { |
| 455 | generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_ON); | 487 | generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_ON); |
| 488 | generic_exec_sequence(panel, MIPI_SEQ_BACKLIGHT_ON); | ||
| 456 | 489 | ||
| 457 | return 0; | 490 | return 0; |
| 458 | } | 491 | } |
| 459 | 492 | ||
| 460 | static int vbt_panel_disable(struct drm_panel *panel) | 493 | static int vbt_panel_disable(struct drm_panel *panel) |
| 461 | { | 494 | { |
| 495 | generic_exec_sequence(panel, MIPI_SEQ_BACKLIGHT_OFF); | ||
| 462 | generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_OFF); | 496 | generic_exec_sequence(panel, MIPI_SEQ_DISPLAY_OFF); |
| 463 | 497 | ||
| 464 | return 0; | 498 | return 0; |
diff --git a/drivers/gpu/drm/i915/intel_dsi_pll.c b/drivers/gpu/drm/i915/intel_dsi_pll.c index 6ab58a01b18e..56eff6004bc0 100644 --- a/drivers/gpu/drm/i915/intel_dsi_pll.c +++ b/drivers/gpu/drm/i915/intel_dsi_pll.c | |||
| @@ -351,7 +351,7 @@ static u32 bxt_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp, | |||
| 351 | u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp, | 351 | u32 intel_dsi_get_pclk(struct intel_encoder *encoder, int pipe_bpp, |
| 352 | struct intel_crtc_state *config) | 352 | struct intel_crtc_state *config) |
| 353 | { | 353 | { |
| 354 | if (IS_BROXTON(encoder->base.dev)) | 354 | if (IS_BROXTON(to_i915(encoder->base.dev))) |
| 355 | return bxt_dsi_get_pclk(encoder, pipe_bpp, config); | 355 | return bxt_dsi_get_pclk(encoder, pipe_bpp, config); |
| 356 | else | 356 | else |
| 357 | return vlv_dsi_get_pclk(encoder, pipe_bpp, config); | 357 | return vlv_dsi_get_pclk(encoder, pipe_bpp, config); |
| @@ -515,11 +515,11 @@ bool intel_dsi_pll_is_enabled(struct drm_i915_private *dev_priv) | |||
| 515 | int intel_compute_dsi_pll(struct intel_encoder *encoder, | 515 | int intel_compute_dsi_pll(struct intel_encoder *encoder, |
| 516 | struct intel_crtc_state *config) | 516 | struct intel_crtc_state *config) |
| 517 | { | 517 | { |
| 518 | struct drm_device *dev = encoder->base.dev; | 518 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 519 | 519 | ||
| 520 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 520 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 521 | return vlv_compute_dsi_pll(encoder, config); | 521 | return vlv_compute_dsi_pll(encoder, config); |
| 522 | else if (IS_BROXTON(dev)) | 522 | else if (IS_BROXTON(dev_priv)) |
| 523 | return bxt_compute_dsi_pll(encoder, config); | 523 | return bxt_compute_dsi_pll(encoder, config); |
| 524 | 524 | ||
| 525 | return -ENODEV; | 525 | return -ENODEV; |
| @@ -528,21 +528,21 @@ int intel_compute_dsi_pll(struct intel_encoder *encoder, | |||
| 528 | void intel_enable_dsi_pll(struct intel_encoder *encoder, | 528 | void intel_enable_dsi_pll(struct intel_encoder *encoder, |
| 529 | const struct intel_crtc_state *config) | 529 | const struct intel_crtc_state *config) |
| 530 | { | 530 | { |
| 531 | struct drm_device *dev = encoder->base.dev; | 531 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 532 | 532 | ||
| 533 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 533 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 534 | vlv_enable_dsi_pll(encoder, config); | 534 | vlv_enable_dsi_pll(encoder, config); |
| 535 | else if (IS_BROXTON(dev)) | 535 | else if (IS_BROXTON(dev_priv)) |
| 536 | bxt_enable_dsi_pll(encoder, config); | 536 | bxt_enable_dsi_pll(encoder, config); |
| 537 | } | 537 | } |
| 538 | 538 | ||
| 539 | void intel_disable_dsi_pll(struct intel_encoder *encoder) | 539 | void intel_disable_dsi_pll(struct intel_encoder *encoder) |
| 540 | { | 540 | { |
| 541 | struct drm_device *dev = encoder->base.dev; | 541 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 542 | 542 | ||
| 543 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 543 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 544 | vlv_disable_dsi_pll(encoder); | 544 | vlv_disable_dsi_pll(encoder); |
| 545 | else if (IS_BROXTON(dev)) | 545 | else if (IS_BROXTON(dev_priv)) |
| 546 | bxt_disable_dsi_pll(encoder); | 546 | bxt_disable_dsi_pll(encoder); |
| 547 | } | 547 | } |
| 548 | 548 | ||
| @@ -564,10 +564,10 @@ static void bxt_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) | |||
| 564 | 564 | ||
| 565 | void intel_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) | 565 | void intel_dsi_reset_clocks(struct intel_encoder *encoder, enum port port) |
| 566 | { | 566 | { |
| 567 | struct drm_device *dev = encoder->base.dev; | 567 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 568 | 568 | ||
| 569 | if (IS_BROXTON(dev)) | 569 | if (IS_BROXTON(dev_priv)) |
| 570 | bxt_dsi_reset_clocks(encoder, port); | 570 | bxt_dsi_reset_clocks(encoder, port); |
| 571 | else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 571 | else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 572 | vlv_dsi_reset_clocks(encoder, port); | 572 | vlv_dsi_reset_clocks(encoder, port); |
| 573 | } | 573 | } |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 2e452c505e7e..cd574900cd8d 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
| @@ -412,16 +412,14 @@ intel_dvo_get_current_mode(struct drm_connector *connector) | |||
| 412 | return mode; | 412 | return mode; |
| 413 | } | 413 | } |
| 414 | 414 | ||
| 415 | static char intel_dvo_port_name(i915_reg_t dvo_reg) | 415 | static enum port intel_dvo_port(i915_reg_t dvo_reg) |
| 416 | { | 416 | { |
| 417 | if (i915_mmio_reg_equal(dvo_reg, DVOA)) | 417 | if (i915_mmio_reg_equal(dvo_reg, DVOA)) |
| 418 | return 'A'; | 418 | return PORT_A; |
| 419 | else if (i915_mmio_reg_equal(dvo_reg, DVOB)) | 419 | else if (i915_mmio_reg_equal(dvo_reg, DVOB)) |
| 420 | return 'B'; | 420 | return PORT_B; |
| 421 | else if (i915_mmio_reg_equal(dvo_reg, DVOC)) | ||
| 422 | return 'C'; | ||
| 423 | else | 421 | else |
| 424 | return '?'; | 422 | return PORT_C; |
| 425 | } | 423 | } |
| 426 | 424 | ||
| 427 | void intel_dvo_init(struct drm_device *dev) | 425 | void intel_dvo_init(struct drm_device *dev) |
| @@ -464,6 +462,7 @@ void intel_dvo_init(struct drm_device *dev) | |||
| 464 | bool dvoinit; | 462 | bool dvoinit; |
| 465 | enum pipe pipe; | 463 | enum pipe pipe; |
| 466 | uint32_t dpll[I915_MAX_PIPES]; | 464 | uint32_t dpll[I915_MAX_PIPES]; |
| 465 | enum port port; | ||
| 467 | 466 | ||
| 468 | /* Allow the I2C driver info to specify the GPIO to be used in | 467 | /* Allow the I2C driver info to specify the GPIO to be used in |
| 469 | * special cases, but otherwise default to what's defined | 468 | * special cases, but otherwise default to what's defined |
| @@ -511,12 +510,15 @@ void intel_dvo_init(struct drm_device *dev) | |||
| 511 | if (!dvoinit) | 510 | if (!dvoinit) |
| 512 | continue; | 511 | continue; |
| 513 | 512 | ||
| 513 | port = intel_dvo_port(dvo->dvo_reg); | ||
| 514 | drm_encoder_init(dev, &intel_encoder->base, | 514 | drm_encoder_init(dev, &intel_encoder->base, |
| 515 | &intel_dvo_enc_funcs, encoder_type, | 515 | &intel_dvo_enc_funcs, encoder_type, |
| 516 | "DVO %c", intel_dvo_port_name(dvo->dvo_reg)); | 516 | "DVO %c", port_name(port)); |
| 517 | 517 | ||
| 518 | intel_encoder->type = INTEL_OUTPUT_DVO; | 518 | intel_encoder->type = INTEL_OUTPUT_DVO; |
| 519 | intel_encoder->port = port; | ||
| 519 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); | 520 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); |
| 521 | |||
| 520 | switch (dvo->type) { | 522 | switch (dvo->type) { |
| 521 | case INTEL_DVO_CHIP_TMDS: | 523 | case INTEL_DVO_CHIP_TMDS: |
| 522 | intel_encoder->cloneable = (1 << INTEL_OUTPUT_ANALOG) | | 524 | intel_encoder->cloneable = (1 << INTEL_OUTPUT_ANALOG) | |
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index e405f1080296..2dc94812bea5 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c | |||
| @@ -82,12 +82,17 @@ static const struct engine_info { | |||
| 82 | }, | 82 | }, |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | static struct intel_engine_cs * | 85 | static int |
| 86 | intel_engine_setup(struct drm_i915_private *dev_priv, | 86 | intel_engine_setup(struct drm_i915_private *dev_priv, |
| 87 | enum intel_engine_id id) | 87 | enum intel_engine_id id) |
| 88 | { | 88 | { |
| 89 | const struct engine_info *info = &intel_engines[id]; | 89 | const struct engine_info *info = &intel_engines[id]; |
| 90 | struct intel_engine_cs *engine = &dev_priv->engine[id]; | 90 | struct intel_engine_cs *engine; |
| 91 | |||
| 92 | GEM_BUG_ON(dev_priv->engine[id]); | ||
| 93 | engine = kzalloc(sizeof(*engine), GFP_KERNEL); | ||
| 94 | if (!engine) | ||
| 95 | return -ENOMEM; | ||
| 91 | 96 | ||
| 92 | engine->id = id; | 97 | engine->id = id; |
| 93 | engine->i915 = dev_priv; | 98 | engine->i915 = dev_priv; |
| @@ -97,7 +102,8 @@ intel_engine_setup(struct drm_i915_private *dev_priv, | |||
| 97 | engine->mmio_base = info->mmio_base; | 102 | engine->mmio_base = info->mmio_base; |
| 98 | engine->irq_shift = info->irq_shift; | 103 | engine->irq_shift = info->irq_shift; |
| 99 | 104 | ||
| 100 | return engine; | 105 | dev_priv->engine[id] = engine; |
| 106 | return 0; | ||
| 101 | } | 107 | } |
| 102 | 108 | ||
| 103 | /** | 109 | /** |
| @@ -110,13 +116,16 @@ int intel_engines_init(struct drm_device *dev) | |||
| 110 | { | 116 | { |
| 111 | struct drm_i915_private *dev_priv = to_i915(dev); | 117 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 112 | struct intel_device_info *device_info = mkwrite_device_info(dev_priv); | 118 | struct intel_device_info *device_info = mkwrite_device_info(dev_priv); |
| 119 | unsigned int ring_mask = INTEL_INFO(dev_priv)->ring_mask; | ||
| 113 | unsigned int mask = 0; | 120 | unsigned int mask = 0; |
| 114 | int (*init)(struct intel_engine_cs *engine); | 121 | int (*init)(struct intel_engine_cs *engine); |
| 122 | struct intel_engine_cs *engine; | ||
| 123 | enum intel_engine_id id; | ||
| 115 | unsigned int i; | 124 | unsigned int i; |
| 116 | int ret; | 125 | int ret; |
| 117 | 126 | ||
| 118 | WARN_ON(INTEL_INFO(dev_priv)->ring_mask == 0); | 127 | WARN_ON(ring_mask == 0); |
| 119 | WARN_ON(INTEL_INFO(dev_priv)->ring_mask & | 128 | WARN_ON(ring_mask & |
| 120 | GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES)); | 129 | GENMASK(sizeof(mask) * BITS_PER_BYTE - 1, I915_NUM_ENGINES)); |
| 121 | 130 | ||
| 122 | for (i = 0; i < ARRAY_SIZE(intel_engines); i++) { | 131 | for (i = 0; i < ARRAY_SIZE(intel_engines); i++) { |
| @@ -131,7 +140,11 @@ int intel_engines_init(struct drm_device *dev) | |||
| 131 | if (!init) | 140 | if (!init) |
| 132 | continue; | 141 | continue; |
| 133 | 142 | ||
| 134 | ret = init(intel_engine_setup(dev_priv, i)); | 143 | ret = intel_engine_setup(dev_priv, i); |
| 144 | if (ret) | ||
| 145 | goto cleanup; | ||
| 146 | |||
| 147 | ret = init(dev_priv->engine[i]); | ||
| 135 | if (ret) | 148 | if (ret) |
| 136 | goto cleanup; | 149 | goto cleanup; |
| 137 | 150 | ||
| @@ -143,7 +156,7 @@ int intel_engines_init(struct drm_device *dev) | |||
| 143 | * are added to the driver by a warning and disabling the forgotten | 156 | * are added to the driver by a warning and disabling the forgotten |
| 144 | * engines. | 157 | * engines. |
| 145 | */ | 158 | */ |
| 146 | if (WARN_ON(mask != INTEL_INFO(dev_priv)->ring_mask)) | 159 | if (WARN_ON(mask != ring_mask)) |
| 147 | device_info->ring_mask = mask; | 160 | device_info->ring_mask = mask; |
| 148 | 161 | ||
| 149 | device_info->num_rings = hweight32(mask); | 162 | device_info->num_rings = hweight32(mask); |
| @@ -151,11 +164,11 @@ int intel_engines_init(struct drm_device *dev) | |||
| 151 | return 0; | 164 | return 0; |
| 152 | 165 | ||
| 153 | cleanup: | 166 | cleanup: |
| 154 | for (i = 0; i < I915_NUM_ENGINES; i++) { | 167 | for_each_engine(engine, dev_priv, id) { |
| 155 | if (i915.enable_execlists) | 168 | if (i915.enable_execlists) |
| 156 | intel_logical_ring_cleanup(&dev_priv->engine[i]); | 169 | intel_logical_ring_cleanup(engine); |
| 157 | else | 170 | else |
| 158 | intel_engine_cleanup(&dev_priv->engine[i]); | 171 | intel_engine_cleanup(engine); |
| 159 | } | 172 | } |
| 160 | 173 | ||
| 161 | return ret; | 174 | return ret; |
| @@ -210,9 +223,6 @@ void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno) | |||
| 210 | void intel_engine_init_hangcheck(struct intel_engine_cs *engine) | 223 | void intel_engine_init_hangcheck(struct intel_engine_cs *engine) |
| 211 | { | 224 | { |
| 212 | memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); | 225 | memset(&engine->hangcheck, 0, sizeof(engine->hangcheck)); |
| 213 | clear_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings); | ||
| 214 | if (intel_engine_has_waiter(engine)) | ||
| 215 | i915_queue_hangcheck(engine->i915); | ||
| 216 | } | 226 | } |
| 217 | 227 | ||
| 218 | static void intel_engine_init_requests(struct intel_engine_cs *engine) | 228 | static void intel_engine_init_requests(struct intel_engine_cs *engine) |
| @@ -307,18 +317,6 @@ int intel_engine_init_common(struct intel_engine_cs *engine) | |||
| 307 | return 0; | 317 | return 0; |
| 308 | } | 318 | } |
| 309 | 319 | ||
| 310 | void intel_engine_reset_irq(struct intel_engine_cs *engine) | ||
| 311 | { | ||
| 312 | struct drm_i915_private *dev_priv = engine->i915; | ||
| 313 | |||
| 314 | spin_lock_irq(&dev_priv->irq_lock); | ||
| 315 | if (intel_engine_has_waiter(engine)) | ||
| 316 | engine->irq_enable(engine); | ||
| 317 | else | ||
| 318 | engine->irq_disable(engine); | ||
| 319 | spin_unlock_irq(&dev_priv->irq_lock); | ||
| 320 | } | ||
| 321 | |||
| 322 | /** | 320 | /** |
| 323 | * intel_engines_cleanup_common - cleans up the engine state created by | 321 | * intel_engines_cleanup_common - cleans up the engine state created by |
| 324 | * the common initiailizers. | 322 | * the common initiailizers. |
| @@ -334,3 +332,137 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) | |||
| 334 | intel_engine_cleanup_cmd_parser(engine); | 332 | intel_engine_cleanup_cmd_parser(engine); |
| 335 | i915_gem_batch_pool_fini(&engine->batch_pool); | 333 | i915_gem_batch_pool_fini(&engine->batch_pool); |
| 336 | } | 334 | } |
| 335 | |||
| 336 | u64 intel_engine_get_active_head(struct intel_engine_cs *engine) | ||
| 337 | { | ||
| 338 | struct drm_i915_private *dev_priv = engine->i915; | ||
| 339 | u64 acthd; | ||
| 340 | |||
| 341 | if (INTEL_GEN(dev_priv) >= 8) | ||
| 342 | acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), | ||
| 343 | RING_ACTHD_UDW(engine->mmio_base)); | ||
| 344 | else if (INTEL_GEN(dev_priv) >= 4) | ||
| 345 | acthd = I915_READ(RING_ACTHD(engine->mmio_base)); | ||
| 346 | else | ||
| 347 | acthd = I915_READ(ACTHD); | ||
| 348 | |||
| 349 | return acthd; | ||
| 350 | } | ||
| 351 | |||
| 352 | u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine) | ||
| 353 | { | ||
| 354 | struct drm_i915_private *dev_priv = engine->i915; | ||
| 355 | u64 bbaddr; | ||
| 356 | |||
| 357 | if (INTEL_GEN(dev_priv) >= 8) | ||
| 358 | bbaddr = I915_READ64_2x32(RING_BBADDR(engine->mmio_base), | ||
| 359 | RING_BBADDR_UDW(engine->mmio_base)); | ||
| 360 | else | ||
| 361 | bbaddr = I915_READ(RING_BBADDR(engine->mmio_base)); | ||
| 362 | |||
| 363 | return bbaddr; | ||
| 364 | } | ||
| 365 | |||
| 366 | const char *i915_cache_level_str(struct drm_i915_private *i915, int type) | ||
| 367 | { | ||
| 368 | switch (type) { | ||
| 369 | case I915_CACHE_NONE: return " uncached"; | ||
| 370 | case I915_CACHE_LLC: return HAS_LLC(i915) ? " LLC" : " snooped"; | ||
| 371 | case I915_CACHE_L3_LLC: return " L3+LLC"; | ||
| 372 | case I915_CACHE_WT: return " WT"; | ||
| 373 | default: return ""; | ||
| 374 | } | ||
| 375 | } | ||
| 376 | |||
| 377 | static inline uint32_t | ||
| 378 | read_subslice_reg(struct drm_i915_private *dev_priv, int slice, | ||
| 379 | int subslice, i915_reg_t reg) | ||
| 380 | { | ||
| 381 | uint32_t mcr; | ||
| 382 | uint32_t ret; | ||
| 383 | enum forcewake_domains fw_domains; | ||
| 384 | |||
| 385 | fw_domains = intel_uncore_forcewake_for_reg(dev_priv, reg, | ||
| 386 | FW_REG_READ); | ||
| 387 | fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, | ||
| 388 | GEN8_MCR_SELECTOR, | ||
| 389 | FW_REG_READ | FW_REG_WRITE); | ||
| 390 | |||
| 391 | spin_lock_irq(&dev_priv->uncore.lock); | ||
| 392 | intel_uncore_forcewake_get__locked(dev_priv, fw_domains); | ||
| 393 | |||
| 394 | mcr = I915_READ_FW(GEN8_MCR_SELECTOR); | ||
| 395 | /* | ||
| 396 | * The HW expects the slice and sublice selectors to be reset to 0 | ||
| 397 | * after reading out the registers. | ||
| 398 | */ | ||
| 399 | WARN_ON_ONCE(mcr & (GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK)); | ||
| 400 | mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); | ||
| 401 | mcr |= GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); | ||
| 402 | I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); | ||
| 403 | |||
| 404 | ret = I915_READ_FW(reg); | ||
| 405 | |||
| 406 | mcr &= ~(GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK); | ||
| 407 | I915_WRITE_FW(GEN8_MCR_SELECTOR, mcr); | ||
| 408 | |||
| 409 | intel_uncore_forcewake_put__locked(dev_priv, fw_domains); | ||
| 410 | spin_unlock_irq(&dev_priv->uncore.lock); | ||
| 411 | |||
| 412 | return ret; | ||
| 413 | } | ||
| 414 | |||
| 415 | /* NB: please notice the memset */ | ||
| 416 | void intel_engine_get_instdone(struct intel_engine_cs *engine, | ||
| 417 | struct intel_instdone *instdone) | ||
| 418 | { | ||
| 419 | struct drm_i915_private *dev_priv = engine->i915; | ||
| 420 | u32 mmio_base = engine->mmio_base; | ||
| 421 | int slice; | ||
| 422 | int subslice; | ||
| 423 | |||
| 424 | memset(instdone, 0, sizeof(*instdone)); | ||
| 425 | |||
| 426 | switch (INTEL_GEN(dev_priv)) { | ||
| 427 | default: | ||
| 428 | instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); | ||
| 429 | |||
| 430 | if (engine->id != RCS) | ||
| 431 | break; | ||
| 432 | |||
| 433 | instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); | ||
| 434 | for_each_instdone_slice_subslice(dev_priv, slice, subslice) { | ||
| 435 | instdone->sampler[slice][subslice] = | ||
| 436 | read_subslice_reg(dev_priv, slice, subslice, | ||
| 437 | GEN7_SAMPLER_INSTDONE); | ||
| 438 | instdone->row[slice][subslice] = | ||
| 439 | read_subslice_reg(dev_priv, slice, subslice, | ||
| 440 | GEN7_ROW_INSTDONE); | ||
| 441 | } | ||
| 442 | break; | ||
| 443 | case 7: | ||
| 444 | instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); | ||
| 445 | |||
| 446 | if (engine->id != RCS) | ||
| 447 | break; | ||
| 448 | |||
| 449 | instdone->slice_common = I915_READ(GEN7_SC_INSTDONE); | ||
| 450 | instdone->sampler[0][0] = I915_READ(GEN7_SAMPLER_INSTDONE); | ||
| 451 | instdone->row[0][0] = I915_READ(GEN7_ROW_INSTDONE); | ||
| 452 | |||
| 453 | break; | ||
| 454 | case 6: | ||
| 455 | case 5: | ||
| 456 | case 4: | ||
| 457 | instdone->instdone = I915_READ(RING_INSTDONE(mmio_base)); | ||
| 458 | |||
| 459 | if (engine->id == RCS) | ||
| 460 | /* HACK: Using the wrong struct member */ | ||
| 461 | instdone->slice_common = I915_READ(GEN4_INSTDONE1); | ||
| 462 | break; | ||
| 463 | case 3: | ||
| 464 | case 2: | ||
| 465 | instdone->instdone = I915_READ(GEN2_INSTDONE); | ||
| 466 | break; | ||
| 467 | } | ||
| 468 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index afc040be1172..49048d9d7895 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c | |||
| @@ -774,6 +774,14 @@ static bool intel_fbc_can_activate(struct intel_crtc *crtc) | |||
| 774 | struct intel_fbc *fbc = &dev_priv->fbc; | 774 | struct intel_fbc *fbc = &dev_priv->fbc; |
| 775 | struct intel_fbc_state_cache *cache = &fbc->state_cache; | 775 | struct intel_fbc_state_cache *cache = &fbc->state_cache; |
| 776 | 776 | ||
| 777 | /* We don't need to use a state cache here since this information is | ||
| 778 | * global for all CRTC. | ||
| 779 | */ | ||
| 780 | if (fbc->underrun_detected) { | ||
| 781 | fbc->no_fbc_reason = "underrun detected"; | ||
| 782 | return false; | ||
| 783 | } | ||
| 784 | |||
| 777 | if (!cache->plane.visible) { | 785 | if (!cache->plane.visible) { |
| 778 | fbc->no_fbc_reason = "primary plane not visible"; | 786 | fbc->no_fbc_reason = "primary plane not visible"; |
| 779 | return false; | 787 | return false; |
| @@ -859,6 +867,11 @@ static bool intel_fbc_can_choose(struct intel_crtc *crtc) | |||
| 859 | return false; | 867 | return false; |
| 860 | } | 868 | } |
| 861 | 869 | ||
| 870 | if (fbc->underrun_detected) { | ||
| 871 | fbc->no_fbc_reason = "underrun detected"; | ||
| 872 | return false; | ||
| 873 | } | ||
| 874 | |||
| 862 | if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) { | 875 | if (fbc_on_pipe_a_only(dev_priv) && crtc->pipe != PIPE_A) { |
| 863 | fbc->no_fbc_reason = "no enabled pipes can have FBC"; | 876 | fbc->no_fbc_reason = "no enabled pipes can have FBC"; |
| 864 | return false; | 877 | return false; |
| @@ -1221,6 +1234,59 @@ void intel_fbc_global_disable(struct drm_i915_private *dev_priv) | |||
| 1221 | cancel_work_sync(&fbc->work.work); | 1234 | cancel_work_sync(&fbc->work.work); |
| 1222 | } | 1235 | } |
| 1223 | 1236 | ||
| 1237 | static void intel_fbc_underrun_work_fn(struct work_struct *work) | ||
| 1238 | { | ||
| 1239 | struct drm_i915_private *dev_priv = | ||
| 1240 | container_of(work, struct drm_i915_private, fbc.underrun_work); | ||
| 1241 | struct intel_fbc *fbc = &dev_priv->fbc; | ||
| 1242 | |||
| 1243 | mutex_lock(&fbc->lock); | ||
| 1244 | |||
| 1245 | /* Maybe we were scheduled twice. */ | ||
| 1246 | if (fbc->underrun_detected) | ||
| 1247 | goto out; | ||
| 1248 | |||
| 1249 | DRM_DEBUG_KMS("Disabling FBC due to FIFO underrun.\n"); | ||
| 1250 | fbc->underrun_detected = true; | ||
| 1251 | |||
| 1252 | intel_fbc_deactivate(dev_priv); | ||
| 1253 | out: | ||
| 1254 | mutex_unlock(&fbc->lock); | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | /** | ||
| 1258 | * intel_fbc_handle_fifo_underrun_irq - disable FBC when we get a FIFO underrun | ||
| 1259 | * @dev_priv: i915 device instance | ||
| 1260 | * | ||
| 1261 | * Without FBC, most underruns are harmless and don't really cause too many | ||
| 1262 | * problems, except for an annoying message on dmesg. With FBC, underruns can | ||
| 1263 | * become black screens or even worse, especially when paired with bad | ||
| 1264 | * watermarks. So in order for us to be on the safe side, completely disable FBC | ||
| 1265 | * in case we ever detect a FIFO underrun on any pipe. An underrun on any pipe | ||
| 1266 | * already suggests that watermarks may be bad, so try to be as safe as | ||
| 1267 | * possible. | ||
| 1268 | * | ||
| 1269 | * This function is called from the IRQ handler. | ||
| 1270 | */ | ||
| 1271 | void intel_fbc_handle_fifo_underrun_irq(struct drm_i915_private *dev_priv) | ||
| 1272 | { | ||
| 1273 | struct intel_fbc *fbc = &dev_priv->fbc; | ||
| 1274 | |||
| 1275 | if (!fbc_supported(dev_priv)) | ||
| 1276 | return; | ||
| 1277 | |||
| 1278 | /* There's no guarantee that underrun_detected won't be set to true | ||
| 1279 | * right after this check and before the work is scheduled, but that's | ||
| 1280 | * not a problem since we'll check it again under the work function | ||
| 1281 | * while FBC is locked. This check here is just to prevent us from | ||
| 1282 | * unnecessarily scheduling the work, and it relies on the fact that we | ||
| 1283 | * never switch underrun_detect back to false after it's true. */ | ||
| 1284 | if (READ_ONCE(fbc->underrun_detected)) | ||
| 1285 | return; | ||
| 1286 | |||
| 1287 | schedule_work(&fbc->underrun_work); | ||
| 1288 | } | ||
| 1289 | |||
| 1224 | /** | 1290 | /** |
| 1225 | * intel_fbc_init_pipe_state - initialize FBC's CRTC visibility tracking | 1291 | * intel_fbc_init_pipe_state - initialize FBC's CRTC visibility tracking |
| 1226 | * @dev_priv: i915 device instance | 1292 | * @dev_priv: i915 device instance |
| @@ -1292,6 +1358,7 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) | |||
| 1292 | enum pipe pipe; | 1358 | enum pipe pipe; |
| 1293 | 1359 | ||
| 1294 | INIT_WORK(&fbc->work.work, intel_fbc_work_fn); | 1360 | INIT_WORK(&fbc->work.work, intel_fbc_work_fn); |
| 1361 | INIT_WORK(&fbc->underrun_work, intel_fbc_underrun_work_fn); | ||
| 1295 | mutex_init(&fbc->lock); | 1362 | mutex_init(&fbc->lock); |
| 1296 | fbc->enabled = false; | 1363 | fbc->enabled = false; |
| 1297 | fbc->active = false; | 1364 | fbc->active = false; |
diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index 2aa744081f09..3018f4f589c8 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c | |||
| @@ -254,13 +254,13 @@ static bool __intel_set_cpu_fifo_underrun_reporting(struct drm_device *dev, | |||
| 254 | old = !intel_crtc->cpu_fifo_underrun_disabled; | 254 | old = !intel_crtc->cpu_fifo_underrun_disabled; |
| 255 | intel_crtc->cpu_fifo_underrun_disabled = !enable; | 255 | intel_crtc->cpu_fifo_underrun_disabled = !enable; |
| 256 | 256 | ||
| 257 | if (HAS_GMCH_DISPLAY(dev)) | 257 | if (HAS_GMCH_DISPLAY(dev_priv)) |
| 258 | i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old); | 258 | i9xx_set_fifo_underrun_reporting(dev, pipe, enable, old); |
| 259 | else if (IS_GEN5(dev) || IS_GEN6(dev)) | 259 | else if (IS_GEN5(dev_priv) || IS_GEN6(dev_priv)) |
| 260 | ironlake_set_fifo_underrun_reporting(dev, pipe, enable); | 260 | ironlake_set_fifo_underrun_reporting(dev, pipe, enable); |
| 261 | else if (IS_GEN7(dev)) | 261 | else if (IS_GEN7(dev_priv)) |
| 262 | ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old); | 262 | ivybridge_set_fifo_underrun_reporting(dev, pipe, enable, old); |
| 263 | else if (IS_GEN8(dev) || IS_GEN9(dev)) | 263 | else if (IS_GEN8(dev_priv) || IS_GEN9(dev_priv)) |
| 264 | broadwell_set_fifo_underrun_reporting(dev, pipe, enable); | 264 | broadwell_set_fifo_underrun_reporting(dev, pipe, enable); |
| 265 | 265 | ||
| 266 | return old; | 266 | return old; |
| @@ -372,6 +372,8 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv, | |||
| 372 | if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) | 372 | if (intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false)) |
| 373 | DRM_ERROR("CPU pipe %c FIFO underrun\n", | 373 | DRM_ERROR("CPU pipe %c FIFO underrun\n", |
| 374 | pipe_name(pipe)); | 374 | pipe_name(pipe)); |
| 375 | |||
| 376 | intel_fbc_handle_fifo_underrun_irq(dev_priv); | ||
| 375 | } | 377 | } |
| 376 | 378 | ||
| 377 | /** | 379 | /** |
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h index b1ba86958811..5cdf7aa75be5 100644 --- a/drivers/gpu/drm/i915/intel_guc.h +++ b/drivers/gpu/drm/i915/intel_guc.h | |||
| @@ -160,6 +160,7 @@ extern int intel_guc_resume(struct drm_device *dev); | |||
| 160 | int i915_guc_submission_init(struct drm_i915_private *dev_priv); | 160 | int i915_guc_submission_init(struct drm_i915_private *dev_priv); |
| 161 | int i915_guc_submission_enable(struct drm_i915_private *dev_priv); | 161 | int i915_guc_submission_enable(struct drm_i915_private *dev_priv); |
| 162 | int i915_guc_wq_reserve(struct drm_i915_gem_request *rq); | 162 | int i915_guc_wq_reserve(struct drm_i915_gem_request *rq); |
| 163 | void i915_guc_wq_unreserve(struct drm_i915_gem_request *request); | ||
| 163 | void i915_guc_submission_disable(struct drm_i915_private *dev_priv); | 164 | void i915_guc_submission_disable(struct drm_i915_private *dev_priv); |
| 164 | void i915_guc_submission_fini(struct drm_i915_private *dev_priv); | 165 | void i915_guc_submission_fini(struct drm_i915_private *dev_priv); |
| 165 | 166 | ||
diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_loader.c index 6fd39efb7894..3c8eaae13732 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_loader.c | |||
| @@ -100,12 +100,13 @@ const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status) | |||
| 100 | static void guc_interrupts_release(struct drm_i915_private *dev_priv) | 100 | static void guc_interrupts_release(struct drm_i915_private *dev_priv) |
| 101 | { | 101 | { |
| 102 | struct intel_engine_cs *engine; | 102 | struct intel_engine_cs *engine; |
| 103 | enum intel_engine_id id; | ||
| 103 | int irqs; | 104 | int irqs; |
| 104 | 105 | ||
| 105 | /* tell all command streamers NOT to forward interrupts or vblank to GuC */ | 106 | /* tell all command streamers NOT to forward interrupts or vblank to GuC */ |
| 106 | irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER); | 107 | irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_NEVER); |
| 107 | irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING); | 108 | irqs |= _MASKED_BIT_DISABLE(GFX_INTERRUPT_STEERING); |
| 108 | for_each_engine(engine, dev_priv) | 109 | for_each_engine(engine, dev_priv, id) |
| 109 | I915_WRITE(RING_MODE_GEN7(engine), irqs); | 110 | I915_WRITE(RING_MODE_GEN7(engine), irqs); |
| 110 | 111 | ||
| 111 | /* route all GT interrupts to the host */ | 112 | /* route all GT interrupts to the host */ |
| @@ -117,12 +118,13 @@ static void guc_interrupts_release(struct drm_i915_private *dev_priv) | |||
| 117 | static void guc_interrupts_capture(struct drm_i915_private *dev_priv) | 118 | static void guc_interrupts_capture(struct drm_i915_private *dev_priv) |
| 118 | { | 119 | { |
| 119 | struct intel_engine_cs *engine; | 120 | struct intel_engine_cs *engine; |
| 121 | enum intel_engine_id id; | ||
| 120 | int irqs; | 122 | int irqs; |
| 121 | u32 tmp; | 123 | u32 tmp; |
| 122 | 124 | ||
| 123 | /* tell all command streamers to forward interrupts (but not vblank) to GuC */ | 125 | /* tell all command streamers to forward interrupts (but not vblank) to GuC */ |
| 124 | irqs = _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING); | 126 | irqs = _MASKED_BIT_ENABLE(GFX_INTERRUPT_STEERING); |
| 125 | for_each_engine(engine, dev_priv) | 127 | for_each_engine(engine, dev_priv, id) |
| 126 | I915_WRITE(RING_MODE_GEN7(engine), irqs); | 128 | I915_WRITE(RING_MODE_GEN7(engine), irqs); |
| 127 | 129 | ||
| 128 | /* route USER_INTERRUPT to Host, all others are sent to GuC. */ | 130 | /* route USER_INTERRUPT to Host, all others are sent to GuC. */ |
| @@ -347,7 +349,6 @@ static u32 guc_wopcm_size(struct drm_i915_private *dev_priv) | |||
| 347 | static int guc_ucode_xfer(struct drm_i915_private *dev_priv) | 349 | static int guc_ucode_xfer(struct drm_i915_private *dev_priv) |
| 348 | { | 350 | { |
| 349 | struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; | 351 | struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; |
| 350 | struct drm_device *dev = &dev_priv->drm; | ||
| 351 | struct i915_vma *vma; | 352 | struct i915_vma *vma; |
| 352 | int ret; | 353 | int ret; |
| 353 | 354 | ||
| @@ -375,24 +376,22 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) | |||
| 375 | /* Enable MIA caching. GuC clock gating is disabled. */ | 376 | /* Enable MIA caching. GuC clock gating is disabled. */ |
| 376 | I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE); | 377 | I915_WRITE(GUC_SHIM_CONTROL, GUC_SHIM_CONTROL_VALUE); |
| 377 | 378 | ||
| 378 | /* WaDisableMinuteIaClockGating:skl,bxt */ | 379 | /* WaDisableMinuteIaClockGating:bxt */ |
| 379 | if (IS_SKL_REVID(dev, 0, SKL_REVID_B0) || | 380 | if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { |
| 380 | IS_BXT_REVID(dev, 0, BXT_REVID_A1)) { | ||
| 381 | I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) & | 381 | I915_WRITE(GUC_SHIM_CONTROL, (I915_READ(GUC_SHIM_CONTROL) & |
| 382 | ~GUC_ENABLE_MIA_CLOCK_GATING)); | 382 | ~GUC_ENABLE_MIA_CLOCK_GATING)); |
| 383 | } | 383 | } |
| 384 | 384 | ||
| 385 | /* WaC6DisallowByGfxPause*/ | 385 | /* WaC6DisallowByGfxPause:bxt */ |
| 386 | if (IS_SKL_REVID(dev, 0, SKL_REVID_C0) || | 386 | if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_B0)) |
| 387 | IS_BXT_REVID(dev, 0, BXT_REVID_B0)) | ||
| 388 | I915_WRITE(GEN6_GFXPAUSE, 0x30FFF); | 387 | I915_WRITE(GEN6_GFXPAUSE, 0x30FFF); |
| 389 | 388 | ||
| 390 | if (IS_BROXTON(dev)) | 389 | if (IS_BROXTON(dev_priv)) |
| 391 | I915_WRITE(GEN9LP_GT_PM_CONFIG, GT_DOORBELL_ENABLE); | 390 | I915_WRITE(GEN9LP_GT_PM_CONFIG, GT_DOORBELL_ENABLE); |
| 392 | else | 391 | else |
| 393 | I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE); | 392 | I915_WRITE(GEN9_GT_PM_CONFIG, GT_DOORBELL_ENABLE); |
| 394 | 393 | ||
| 395 | if (IS_GEN9(dev)) { | 394 | if (IS_GEN9(dev_priv)) { |
| 396 | /* DOP Clock Gating Enable for GuC clocks */ | 395 | /* DOP Clock Gating Enable for GuC clocks */ |
| 397 | I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE | | 396 | I915_WRITE(GEN7_MISCCPCTL, (GEN8_DOP_CLOCK_GATE_GUC_ENABLE | |
| 398 | I915_READ(GEN7_MISCCPCTL))); | 397 | I915_READ(GEN7_MISCCPCTL))); |
| @@ -720,23 +719,28 @@ void intel_guc_init(struct drm_device *dev) | |||
| 720 | struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; | 719 | struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw; |
| 721 | const char *fw_path; | 720 | const char *fw_path; |
| 722 | 721 | ||
| 723 | /* A negative value means "use platform default" */ | 722 | if (!HAS_GUC(dev)) { |
| 724 | if (i915.enable_guc_loading < 0) | 723 | i915.enable_guc_loading = 0; |
| 725 | i915.enable_guc_loading = HAS_GUC_UCODE(dev); | 724 | i915.enable_guc_submission = 0; |
| 726 | if (i915.enable_guc_submission < 0) | 725 | } else { |
| 727 | i915.enable_guc_submission = HAS_GUC_SCHED(dev); | 726 | /* A negative value means "use platform default" */ |
| 727 | if (i915.enable_guc_loading < 0) | ||
| 728 | i915.enable_guc_loading = HAS_GUC_UCODE(dev); | ||
| 729 | if (i915.enable_guc_submission < 0) | ||
| 730 | i915.enable_guc_submission = HAS_GUC_SCHED(dev); | ||
| 731 | } | ||
| 728 | 732 | ||
| 729 | if (!HAS_GUC_UCODE(dev)) { | 733 | if (!HAS_GUC_UCODE(dev)) { |
| 730 | fw_path = NULL; | 734 | fw_path = NULL; |
| 731 | } else if (IS_SKYLAKE(dev)) { | 735 | } else if (IS_SKYLAKE(dev_priv)) { |
| 732 | fw_path = I915_SKL_GUC_UCODE; | 736 | fw_path = I915_SKL_GUC_UCODE; |
| 733 | guc_fw->guc_fw_major_wanted = SKL_FW_MAJOR; | 737 | guc_fw->guc_fw_major_wanted = SKL_FW_MAJOR; |
| 734 | guc_fw->guc_fw_minor_wanted = SKL_FW_MINOR; | 738 | guc_fw->guc_fw_minor_wanted = SKL_FW_MINOR; |
| 735 | } else if (IS_BROXTON(dev)) { | 739 | } else if (IS_BROXTON(dev_priv)) { |
| 736 | fw_path = I915_BXT_GUC_UCODE; | 740 | fw_path = I915_BXT_GUC_UCODE; |
| 737 | guc_fw->guc_fw_major_wanted = BXT_FW_MAJOR; | 741 | guc_fw->guc_fw_major_wanted = BXT_FW_MAJOR; |
| 738 | guc_fw->guc_fw_minor_wanted = BXT_FW_MINOR; | 742 | guc_fw->guc_fw_minor_wanted = BXT_FW_MINOR; |
| 739 | } else if (IS_KABYLAKE(dev)) { | 743 | } else if (IS_KABYLAKE(dev_priv)) { |
| 740 | fw_path = I915_KBL_GUC_UCODE; | 744 | fw_path = I915_KBL_GUC_UCODE; |
| 741 | guc_fw->guc_fw_major_wanted = KBL_FW_MAJOR; | 745 | guc_fw->guc_fw_major_wanted = KBL_FW_MAJOR; |
| 742 | guc_fw->guc_fw_minor_wanted = KBL_FW_MINOR; | 746 | guc_fw->guc_fw_minor_wanted = KBL_FW_MINOR; |
diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c index 434f4d5c553d..290384e86c63 100644 --- a/drivers/gpu/drm/i915/intel_gvt.c +++ b/drivers/gpu/drm/i915/intel_gvt.c | |||
| @@ -31,14 +31,20 @@ | |||
| 31 | * GPU among multiple virtual machines on a time-sharing basis. Each | 31 | * GPU among multiple virtual machines on a time-sharing basis. Each |
| 32 | * virtual machine is presented a virtual GPU (vGPU), which has equivalent | 32 | * virtual machine is presented a virtual GPU (vGPU), which has equivalent |
| 33 | * features as the underlying physical GPU (pGPU), so i915 driver can run | 33 | * features as the underlying physical GPU (pGPU), so i915 driver can run |
| 34 | * seamlessly in a virtual machine. This file provides the englightments | 34 | * seamlessly in a virtual machine. |
| 35 | * of GVT and the necessary components used by GVT in i915 driver. | 35 | * |
| 36 | * To virtualize GPU resources GVT-g driver depends on hypervisor technology | ||
| 37 | * e.g KVM/VFIO/mdev, Xen, etc. to provide resource access trapping capability | ||
| 38 | * and be virtualized within GVT-g device module. More architectural design | ||
| 39 | * doc is available on https://01.org/group/2230/documentation-list. | ||
| 36 | */ | 40 | */ |
| 37 | 41 | ||
| 38 | static bool is_supported_device(struct drm_i915_private *dev_priv) | 42 | static bool is_supported_device(struct drm_i915_private *dev_priv) |
| 39 | { | 43 | { |
| 40 | if (IS_BROADWELL(dev_priv)) | 44 | if (IS_BROADWELL(dev_priv)) |
| 41 | return true; | 45 | return true; |
| 46 | if (IS_SKYLAKE(dev_priv)) | ||
| 47 | return true; | ||
| 42 | return false; | 48 | return false; |
| 43 | } | 49 | } |
| 44 | 50 | ||
diff --git a/drivers/gpu/drm/i915/intel_gvt.h b/drivers/gpu/drm/i915/intel_gvt.h index 960211df74db..25df2d65b985 100644 --- a/drivers/gpu/drm/i915/intel_gvt.h +++ b/drivers/gpu/drm/i915/intel_gvt.h | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | #ifndef _INTEL_GVT_H_ | 24 | #ifndef _INTEL_GVT_H_ |
| 25 | #define _INTEL_GVT_H_ | 25 | #define _INTEL_GVT_H_ |
| 26 | 26 | ||
| 27 | #include "gvt/gvt.h" | 27 | struct intel_gvt; |
| 28 | 28 | ||
| 29 | #ifdef CONFIG_DRM_I915_GVT | 29 | #ifdef CONFIG_DRM_I915_GVT |
| 30 | int intel_gvt_init(struct drm_i915_private *dev_priv); | 30 | int intel_gvt_init(struct drm_i915_private *dev_priv); |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index f40a35f2913a..af8715f31807 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
| @@ -50,7 +50,7 @@ assert_hdmi_port_disabled(struct intel_hdmi *intel_hdmi) | |||
| 50 | struct drm_i915_private *dev_priv = to_i915(dev); | 50 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 51 | uint32_t enabled_bits; | 51 | uint32_t enabled_bits; |
| 52 | 52 | ||
| 53 | enabled_bits = HAS_DDI(dev) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; | 53 | enabled_bits = HAS_DDI(dev_priv) ? DDI_BUF_CTL_ENABLE : SDVO_ENABLE; |
| 54 | 54 | ||
| 55 | WARN(I915_READ(intel_hdmi->hdmi_reg) & enabled_bits, | 55 | WARN(I915_READ(intel_hdmi->hdmi_reg) & enabled_bits, |
| 56 | "HDMI port enabled, expecting disabled\n"); | 56 | "HDMI port enabled, expecting disabled\n"); |
| @@ -864,7 +864,7 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder) | |||
| 864 | intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); | 864 | intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); |
| 865 | 865 | ||
| 866 | hdmi_val = SDVO_ENCODING_HDMI; | 866 | hdmi_val = SDVO_ENCODING_HDMI; |
| 867 | if (!HAS_PCH_SPLIT(dev) && crtc->config->limited_color_range) | 867 | if (!HAS_PCH_SPLIT(dev_priv) && crtc->config->limited_color_range) |
| 868 | hdmi_val |= HDMI_COLOR_RANGE_16_235; | 868 | hdmi_val |= HDMI_COLOR_RANGE_16_235; |
| 869 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) | 869 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
| 870 | hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH; | 870 | hdmi_val |= SDVO_VSYNC_ACTIVE_HIGH; |
| @@ -879,9 +879,9 @@ static void intel_hdmi_prepare(struct intel_encoder *encoder) | |||
| 879 | if (crtc->config->has_hdmi_sink) | 879 | if (crtc->config->has_hdmi_sink) |
| 880 | hdmi_val |= HDMI_MODE_SELECT_HDMI; | 880 | hdmi_val |= HDMI_MODE_SELECT_HDMI; |
| 881 | 881 | ||
| 882 | if (HAS_PCH_CPT(dev)) | 882 | if (HAS_PCH_CPT(dev_priv)) |
| 883 | hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe); | 883 | hdmi_val |= SDVO_PIPE_SEL_CPT(crtc->pipe); |
| 884 | else if (IS_CHERRYVIEW(dev)) | 884 | else if (IS_CHERRYVIEW(dev_priv)) |
| 885 | hdmi_val |= SDVO_PIPE_SEL_CHV(crtc->pipe); | 885 | hdmi_val |= SDVO_PIPE_SEL_CHV(crtc->pipe); |
| 886 | else | 886 | else |
| 887 | hdmi_val |= SDVO_PIPE_SEL(crtc->pipe); | 887 | hdmi_val |= SDVO_PIPE_SEL(crtc->pipe); |
| @@ -911,9 +911,9 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder, | |||
| 911 | if (!(tmp & SDVO_ENABLE)) | 911 | if (!(tmp & SDVO_ENABLE)) |
| 912 | goto out; | 912 | goto out; |
| 913 | 913 | ||
| 914 | if (HAS_PCH_CPT(dev)) | 914 | if (HAS_PCH_CPT(dev_priv)) |
| 915 | *pipe = PORT_TO_PIPE_CPT(tmp); | 915 | *pipe = PORT_TO_PIPE_CPT(tmp); |
| 916 | else if (IS_CHERRYVIEW(dev)) | 916 | else if (IS_CHERRYVIEW(dev_priv)) |
| 917 | *pipe = SDVO_PORT_TO_PIPE_CHV(tmp); | 917 | *pipe = SDVO_PORT_TO_PIPE_CHV(tmp); |
| 918 | else | 918 | else |
| 919 | *pipe = PORT_TO_PIPE(tmp); | 919 | *pipe = PORT_TO_PIPE(tmp); |
| @@ -956,7 +956,7 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, | |||
| 956 | if (tmp & SDVO_AUDIO_ENABLE) | 956 | if (tmp & SDVO_AUDIO_ENABLE) |
| 957 | pipe_config->has_audio = true; | 957 | pipe_config->has_audio = true; |
| 958 | 958 | ||
| 959 | if (!HAS_PCH_SPLIT(dev) && | 959 | if (!HAS_PCH_SPLIT(dev_priv) && |
| 960 | tmp & HDMI_COLOR_RANGE_16_235) | 960 | tmp & HDMI_COLOR_RANGE_16_235) |
| 961 | pipe_config->limited_color_range = true; | 961 | pipe_config->limited_color_range = true; |
| 962 | 962 | ||
| @@ -1141,7 +1141,7 @@ static void intel_disable_hdmi(struct intel_encoder *encoder, | |||
| 1141 | * to transcoder A after disabling it to allow the | 1141 | * to transcoder A after disabling it to allow the |
| 1142 | * matching DP port to be enabled on transcoder A. | 1142 | * matching DP port to be enabled on transcoder A. |
| 1143 | */ | 1143 | */ |
| 1144 | if (HAS_PCH_IBX(dev) && crtc->pipe == PIPE_B) { | 1144 | if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) { |
| 1145 | /* | 1145 | /* |
| 1146 | * We get CPU/PCH FIFO underruns on the other pipe when | 1146 | * We get CPU/PCH FIFO underruns on the other pipe when |
| 1147 | * doing the workaround. Sweep them under the rug. | 1147 | * doing the workaround. Sweep them under the rug. |
| @@ -1241,7 +1241,7 @@ static enum drm_mode_status | |||
| 1241 | hdmi_port_clock_valid(struct intel_hdmi *hdmi, | 1241 | hdmi_port_clock_valid(struct intel_hdmi *hdmi, |
| 1242 | int clock, bool respect_downstream_limits) | 1242 | int clock, bool respect_downstream_limits) |
| 1243 | { | 1243 | { |
| 1244 | struct drm_device *dev = intel_hdmi_to_dev(hdmi); | 1244 | struct drm_i915_private *dev_priv = to_i915(intel_hdmi_to_dev(hdmi)); |
| 1245 | 1245 | ||
| 1246 | if (clock < 25000) | 1246 | if (clock < 25000) |
| 1247 | return MODE_CLOCK_LOW; | 1247 | return MODE_CLOCK_LOW; |
| @@ -1249,11 +1249,11 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, | |||
| 1249 | return MODE_CLOCK_HIGH; | 1249 | return MODE_CLOCK_HIGH; |
| 1250 | 1250 | ||
| 1251 | /* BXT DPLL can't generate 223-240 MHz */ | 1251 | /* BXT DPLL can't generate 223-240 MHz */ |
| 1252 | if (IS_BROXTON(dev) && clock > 223333 && clock < 240000) | 1252 | if (IS_BROXTON(dev_priv) && clock > 223333 && clock < 240000) |
| 1253 | return MODE_CLOCK_RANGE; | 1253 | return MODE_CLOCK_RANGE; |
| 1254 | 1254 | ||
| 1255 | /* CHV DPLL can't generate 216-240 MHz */ | 1255 | /* CHV DPLL can't generate 216-240 MHz */ |
| 1256 | if (IS_CHERRYVIEW(dev) && clock > 216000 && clock < 240000) | 1256 | if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000) |
| 1257 | return MODE_CLOCK_RANGE; | 1257 | return MODE_CLOCK_RANGE; |
| 1258 | 1258 | ||
| 1259 | return MODE_OK; | 1259 | return MODE_OK; |
| @@ -1265,6 +1265,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, | |||
| 1265 | { | 1265 | { |
| 1266 | struct intel_hdmi *hdmi = intel_attached_hdmi(connector); | 1266 | struct intel_hdmi *hdmi = intel_attached_hdmi(connector); |
| 1267 | struct drm_device *dev = intel_hdmi_to_dev(hdmi); | 1267 | struct drm_device *dev = intel_hdmi_to_dev(hdmi); |
| 1268 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 1268 | enum drm_mode_status status; | 1269 | enum drm_mode_status status; |
| 1269 | int clock; | 1270 | int clock; |
| 1270 | int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; | 1271 | int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; |
| @@ -1287,7 +1288,7 @@ intel_hdmi_mode_valid(struct drm_connector *connector, | |||
| 1287 | status = hdmi_port_clock_valid(hdmi, clock, true); | 1288 | status = hdmi_port_clock_valid(hdmi, clock, true); |
| 1288 | 1289 | ||
| 1289 | /* if we can't do 8bpc we may still be able to do 12bpc */ | 1290 | /* if we can't do 8bpc we may still be able to do 12bpc */ |
| 1290 | if (!HAS_GMCH_DISPLAY(dev) && status != MODE_OK) | 1291 | if (!HAS_GMCH_DISPLAY(dev_priv) && status != MODE_OK) |
| 1291 | status = hdmi_port_clock_valid(hdmi, clock * 3 / 2, true); | 1292 | status = hdmi_port_clock_valid(hdmi, clock * 3 / 2, true); |
| 1292 | 1293 | ||
| 1293 | return status; | 1294 | return status; |
| @@ -1297,7 +1298,7 @@ static bool hdmi_12bpc_possible(struct intel_crtc_state *crtc_state) | |||
| 1297 | { | 1298 | { |
| 1298 | struct drm_device *dev = crtc_state->base.crtc->dev; | 1299 | struct drm_device *dev = crtc_state->base.crtc->dev; |
| 1299 | 1300 | ||
| 1300 | if (HAS_GMCH_DISPLAY(dev)) | 1301 | if (HAS_GMCH_DISPLAY(to_i915(dev))) |
| 1301 | return false; | 1302 | return false; |
| 1302 | 1303 | ||
| 1303 | /* | 1304 | /* |
| @@ -1312,7 +1313,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, | |||
| 1312 | struct drm_connector_state *conn_state) | 1313 | struct drm_connector_state *conn_state) |
| 1313 | { | 1314 | { |
| 1314 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); | 1315 | struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(&encoder->base); |
| 1315 | struct drm_device *dev = encoder->base.dev; | 1316 | struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); |
| 1316 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; | 1317 | struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode; |
| 1317 | int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock; | 1318 | int clock_8bpc = pipe_config->base.adjusted_mode.crtc_clock; |
| 1318 | int clock_12bpc = clock_8bpc * 3 / 2; | 1319 | int clock_12bpc = clock_8bpc * 3 / 2; |
| @@ -1339,7 +1340,7 @@ bool intel_hdmi_compute_config(struct intel_encoder *encoder, | |||
| 1339 | clock_12bpc *= 2; | 1340 | clock_12bpc *= 2; |
| 1340 | } | 1341 | } |
| 1341 | 1342 | ||
| 1342 | if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) | 1343 | if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv)) |
| 1343 | pipe_config->has_pch_encoder = true; | 1344 | pipe_config->has_pch_encoder = true; |
| 1344 | 1345 | ||
| 1345 | if (pipe_config->has_hdmi_sink && intel_hdmi->has_audio) | 1346 | if (pipe_config->has_hdmi_sink && intel_hdmi->has_audio) |
| @@ -1799,6 +1800,50 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c | |||
| 1799 | intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; | 1800 | intel_hdmi->aspect_ratio = HDMI_PICTURE_ASPECT_NONE; |
| 1800 | } | 1801 | } |
| 1801 | 1802 | ||
| 1803 | static u8 intel_hdmi_ddc_pin(struct drm_i915_private *dev_priv, | ||
| 1804 | enum port port) | ||
| 1805 | { | ||
| 1806 | const struct ddi_vbt_port_info *info = | ||
| 1807 | &dev_priv->vbt.ddi_port_info[port]; | ||
| 1808 | u8 ddc_pin; | ||
| 1809 | |||
| 1810 | if (info->alternate_ddc_pin) { | ||
| 1811 | DRM_DEBUG_KMS("Using DDC pin 0x%x for port %c (VBT)\n", | ||
| 1812 | info->alternate_ddc_pin, port_name(port)); | ||
| 1813 | return info->alternate_ddc_pin; | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | switch (port) { | ||
| 1817 | case PORT_B: | ||
| 1818 | if (IS_BROXTON(dev_priv)) | ||
| 1819 | ddc_pin = GMBUS_PIN_1_BXT; | ||
| 1820 | else | ||
| 1821 | ddc_pin = GMBUS_PIN_DPB; | ||
| 1822 | break; | ||
| 1823 | case PORT_C: | ||
| 1824 | if (IS_BROXTON(dev_priv)) | ||
| 1825 | ddc_pin = GMBUS_PIN_2_BXT; | ||
| 1826 | else | ||
| 1827 | ddc_pin = GMBUS_PIN_DPC; | ||
| 1828 | break; | ||
| 1829 | case PORT_D: | ||
| 1830 | if (IS_CHERRYVIEW(dev_priv)) | ||
| 1831 | ddc_pin = GMBUS_PIN_DPD_CHV; | ||
| 1832 | else | ||
| 1833 | ddc_pin = GMBUS_PIN_DPD; | ||
| 1834 | break; | ||
| 1835 | default: | ||
| 1836 | MISSING_CASE(port); | ||
| 1837 | ddc_pin = GMBUS_PIN_DPB; | ||
| 1838 | break; | ||
| 1839 | } | ||
| 1840 | |||
| 1841 | DRM_DEBUG_KMS("Using DDC pin 0x%x for port %c (platform default)\n", | ||
| 1842 | ddc_pin, port_name(port)); | ||
| 1843 | |||
| 1844 | return ddc_pin; | ||
| 1845 | } | ||
| 1846 | |||
| 1802 | void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | 1847 | void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, |
| 1803 | struct intel_connector *intel_connector) | 1848 | struct intel_connector *intel_connector) |
| 1804 | { | 1849 | { |
| @@ -1808,7 +1853,6 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 1808 | struct drm_device *dev = intel_encoder->base.dev; | 1853 | struct drm_device *dev = intel_encoder->base.dev; |
| 1809 | struct drm_i915_private *dev_priv = to_i915(dev); | 1854 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 1810 | enum port port = intel_dig_port->port; | 1855 | enum port port = intel_dig_port->port; |
| 1811 | uint8_t alternate_ddc_pin; | ||
| 1812 | 1856 | ||
| 1813 | DRM_DEBUG_KMS("Adding HDMI connector on port %c\n", | 1857 | DRM_DEBUG_KMS("Adding HDMI connector on port %c\n", |
| 1814 | port_name(port)); | 1858 | port_name(port)); |
| @@ -1826,12 +1870,10 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 1826 | connector->doublescan_allowed = 0; | 1870 | connector->doublescan_allowed = 0; |
| 1827 | connector->stereo_allowed = 1; | 1871 | connector->stereo_allowed = 1; |
| 1828 | 1872 | ||
| 1873 | intel_hdmi->ddc_bus = intel_hdmi_ddc_pin(dev_priv, port); | ||
| 1874 | |||
| 1829 | switch (port) { | 1875 | switch (port) { |
| 1830 | case PORT_B: | 1876 | case PORT_B: |
| 1831 | if (IS_BROXTON(dev_priv)) | ||
| 1832 | intel_hdmi->ddc_bus = GMBUS_PIN_1_BXT; | ||
| 1833 | else | ||
| 1834 | intel_hdmi->ddc_bus = GMBUS_PIN_DPB; | ||
| 1835 | /* | 1877 | /* |
| 1836 | * On BXT A0/A1, sw needs to activate DDIA HPD logic and | 1878 | * On BXT A0/A1, sw needs to activate DDIA HPD logic and |
| 1837 | * interrupts to check the external panel connection. | 1879 | * interrupts to check the external panel connection. |
| @@ -1842,61 +1884,32 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 1842 | intel_encoder->hpd_pin = HPD_PORT_B; | 1884 | intel_encoder->hpd_pin = HPD_PORT_B; |
| 1843 | break; | 1885 | break; |
| 1844 | case PORT_C: | 1886 | case PORT_C: |
| 1845 | if (IS_BROXTON(dev_priv)) | ||
| 1846 | intel_hdmi->ddc_bus = GMBUS_PIN_2_BXT; | ||
| 1847 | else | ||
| 1848 | intel_hdmi->ddc_bus = GMBUS_PIN_DPC; | ||
| 1849 | intel_encoder->hpd_pin = HPD_PORT_C; | 1887 | intel_encoder->hpd_pin = HPD_PORT_C; |
| 1850 | break; | 1888 | break; |
| 1851 | case PORT_D: | 1889 | case PORT_D: |
| 1852 | if (WARN_ON(IS_BROXTON(dev_priv))) | ||
| 1853 | intel_hdmi->ddc_bus = GMBUS_PIN_DISABLED; | ||
| 1854 | else if (IS_CHERRYVIEW(dev_priv)) | ||
| 1855 | intel_hdmi->ddc_bus = GMBUS_PIN_DPD_CHV; | ||
| 1856 | else | ||
| 1857 | intel_hdmi->ddc_bus = GMBUS_PIN_DPD; | ||
| 1858 | intel_encoder->hpd_pin = HPD_PORT_D; | 1890 | intel_encoder->hpd_pin = HPD_PORT_D; |
| 1859 | break; | 1891 | break; |
| 1860 | case PORT_E: | 1892 | case PORT_E: |
| 1861 | /* On SKL PORT E doesn't have seperate GMBUS pin | ||
| 1862 | * We rely on VBT to set a proper alternate GMBUS pin. */ | ||
| 1863 | alternate_ddc_pin = | ||
| 1864 | dev_priv->vbt.ddi_port_info[PORT_E].alternate_ddc_pin; | ||
| 1865 | switch (alternate_ddc_pin) { | ||
| 1866 | case DDC_PIN_B: | ||
| 1867 | intel_hdmi->ddc_bus = GMBUS_PIN_DPB; | ||
| 1868 | break; | ||
| 1869 | case DDC_PIN_C: | ||
| 1870 | intel_hdmi->ddc_bus = GMBUS_PIN_DPC; | ||
| 1871 | break; | ||
| 1872 | case DDC_PIN_D: | ||
| 1873 | intel_hdmi->ddc_bus = GMBUS_PIN_DPD; | ||
| 1874 | break; | ||
| 1875 | default: | ||
| 1876 | MISSING_CASE(alternate_ddc_pin); | ||
| 1877 | } | ||
| 1878 | intel_encoder->hpd_pin = HPD_PORT_E; | 1893 | intel_encoder->hpd_pin = HPD_PORT_E; |
| 1879 | break; | 1894 | break; |
| 1880 | case PORT_A: | ||
| 1881 | intel_encoder->hpd_pin = HPD_PORT_A; | ||
| 1882 | /* Internal port only for eDP. */ | ||
| 1883 | default: | 1895 | default: |
| 1884 | BUG(); | 1896 | MISSING_CASE(port); |
| 1897 | return; | ||
| 1885 | } | 1898 | } |
| 1886 | 1899 | ||
| 1887 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 1900 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 1888 | intel_hdmi->write_infoframe = vlv_write_infoframe; | 1901 | intel_hdmi->write_infoframe = vlv_write_infoframe; |
| 1889 | intel_hdmi->set_infoframes = vlv_set_infoframes; | 1902 | intel_hdmi->set_infoframes = vlv_set_infoframes; |
| 1890 | intel_hdmi->infoframe_enabled = vlv_infoframe_enabled; | 1903 | intel_hdmi->infoframe_enabled = vlv_infoframe_enabled; |
| 1891 | } else if (IS_G4X(dev)) { | 1904 | } else if (IS_G4X(dev_priv)) { |
| 1892 | intel_hdmi->write_infoframe = g4x_write_infoframe; | 1905 | intel_hdmi->write_infoframe = g4x_write_infoframe; |
| 1893 | intel_hdmi->set_infoframes = g4x_set_infoframes; | 1906 | intel_hdmi->set_infoframes = g4x_set_infoframes; |
| 1894 | intel_hdmi->infoframe_enabled = g4x_infoframe_enabled; | 1907 | intel_hdmi->infoframe_enabled = g4x_infoframe_enabled; |
| 1895 | } else if (HAS_DDI(dev)) { | 1908 | } else if (HAS_DDI(dev_priv)) { |
| 1896 | intel_hdmi->write_infoframe = hsw_write_infoframe; | 1909 | intel_hdmi->write_infoframe = hsw_write_infoframe; |
| 1897 | intel_hdmi->set_infoframes = hsw_set_infoframes; | 1910 | intel_hdmi->set_infoframes = hsw_set_infoframes; |
| 1898 | intel_hdmi->infoframe_enabled = hsw_infoframe_enabled; | 1911 | intel_hdmi->infoframe_enabled = hsw_infoframe_enabled; |
| 1899 | } else if (HAS_PCH_IBX(dev)) { | 1912 | } else if (HAS_PCH_IBX(dev_priv)) { |
| 1900 | intel_hdmi->write_infoframe = ibx_write_infoframe; | 1913 | intel_hdmi->write_infoframe = ibx_write_infoframe; |
| 1901 | intel_hdmi->set_infoframes = ibx_set_infoframes; | 1914 | intel_hdmi->set_infoframes = ibx_set_infoframes; |
| 1902 | intel_hdmi->infoframe_enabled = ibx_infoframe_enabled; | 1915 | intel_hdmi->infoframe_enabled = ibx_infoframe_enabled; |
| @@ -1906,7 +1919,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 1906 | intel_hdmi->infoframe_enabled = cpt_infoframe_enabled; | 1919 | intel_hdmi->infoframe_enabled = cpt_infoframe_enabled; |
| 1907 | } | 1920 | } |
| 1908 | 1921 | ||
| 1909 | if (HAS_DDI(dev)) | 1922 | if (HAS_DDI(dev_priv)) |
| 1910 | intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; | 1923 | intel_connector->get_hw_state = intel_ddi_connector_get_hw_state; |
| 1911 | else | 1924 | else |
| 1912 | intel_connector->get_hw_state = intel_connector_get_hw_state; | 1925 | intel_connector->get_hw_state = intel_connector_get_hw_state; |
| @@ -1920,7 +1933,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 1920 | * 0xd. Failure to do so will result in spurious interrupts being | 1933 | * 0xd. Failure to do so will result in spurious interrupts being |
| 1921 | * generated on the port when a cable is not attached. | 1934 | * generated on the port when a cable is not attached. |
| 1922 | */ | 1935 | */ |
| 1923 | if (IS_G4X(dev) && !IS_GM45(dev)) { | 1936 | if (IS_G4X(dev_priv) && !IS_GM45(dev_priv)) { |
| 1924 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); | 1937 | u32 temp = I915_READ(PEG_BAND_GAP_DATA); |
| 1925 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); | 1938 | I915_WRITE(PEG_BAND_GAP_DATA, (temp & ~0xf) | 0xd); |
| 1926 | } | 1939 | } |
| @@ -1929,6 +1942,7 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port, | |||
| 1929 | void intel_hdmi_init(struct drm_device *dev, | 1942 | void intel_hdmi_init(struct drm_device *dev, |
| 1930 | i915_reg_t hdmi_reg, enum port port) | 1943 | i915_reg_t hdmi_reg, enum port port) |
| 1931 | { | 1944 | { |
| 1945 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 1932 | struct intel_digital_port *intel_dig_port; | 1946 | struct intel_digital_port *intel_dig_port; |
| 1933 | struct intel_encoder *intel_encoder; | 1947 | struct intel_encoder *intel_encoder; |
| 1934 | struct intel_connector *intel_connector; | 1948 | struct intel_connector *intel_connector; |
| @@ -1949,7 +1963,7 @@ void intel_hdmi_init(struct drm_device *dev, | |||
| 1949 | DRM_MODE_ENCODER_TMDS, "HDMI %c", port_name(port)); | 1963 | DRM_MODE_ENCODER_TMDS, "HDMI %c", port_name(port)); |
| 1950 | 1964 | ||
| 1951 | intel_encoder->compute_config = intel_hdmi_compute_config; | 1965 | intel_encoder->compute_config = intel_hdmi_compute_config; |
| 1952 | if (HAS_PCH_SPLIT(dev)) { | 1966 | if (HAS_PCH_SPLIT(dev_priv)) { |
| 1953 | intel_encoder->disable = pch_disable_hdmi; | 1967 | intel_encoder->disable = pch_disable_hdmi; |
| 1954 | intel_encoder->post_disable = pch_post_disable_hdmi; | 1968 | intel_encoder->post_disable = pch_post_disable_hdmi; |
| 1955 | } else { | 1969 | } else { |
| @@ -1957,29 +1971,30 @@ void intel_hdmi_init(struct drm_device *dev, | |||
| 1957 | } | 1971 | } |
| 1958 | intel_encoder->get_hw_state = intel_hdmi_get_hw_state; | 1972 | intel_encoder->get_hw_state = intel_hdmi_get_hw_state; |
| 1959 | intel_encoder->get_config = intel_hdmi_get_config; | 1973 | intel_encoder->get_config = intel_hdmi_get_config; |
| 1960 | if (IS_CHERRYVIEW(dev)) { | 1974 | if (IS_CHERRYVIEW(dev_priv)) { |
| 1961 | intel_encoder->pre_pll_enable = chv_hdmi_pre_pll_enable; | 1975 | intel_encoder->pre_pll_enable = chv_hdmi_pre_pll_enable; |
| 1962 | intel_encoder->pre_enable = chv_hdmi_pre_enable; | 1976 | intel_encoder->pre_enable = chv_hdmi_pre_enable; |
| 1963 | intel_encoder->enable = vlv_enable_hdmi; | 1977 | intel_encoder->enable = vlv_enable_hdmi; |
| 1964 | intel_encoder->post_disable = chv_hdmi_post_disable; | 1978 | intel_encoder->post_disable = chv_hdmi_post_disable; |
| 1965 | intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable; | 1979 | intel_encoder->post_pll_disable = chv_hdmi_post_pll_disable; |
| 1966 | } else if (IS_VALLEYVIEW(dev)) { | 1980 | } else if (IS_VALLEYVIEW(dev_priv)) { |
| 1967 | intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable; | 1981 | intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable; |
| 1968 | intel_encoder->pre_enable = vlv_hdmi_pre_enable; | 1982 | intel_encoder->pre_enable = vlv_hdmi_pre_enable; |
| 1969 | intel_encoder->enable = vlv_enable_hdmi; | 1983 | intel_encoder->enable = vlv_enable_hdmi; |
| 1970 | intel_encoder->post_disable = vlv_hdmi_post_disable; | 1984 | intel_encoder->post_disable = vlv_hdmi_post_disable; |
| 1971 | } else { | 1985 | } else { |
| 1972 | intel_encoder->pre_enable = intel_hdmi_pre_enable; | 1986 | intel_encoder->pre_enable = intel_hdmi_pre_enable; |
| 1973 | if (HAS_PCH_CPT(dev)) | 1987 | if (HAS_PCH_CPT(dev_priv)) |
| 1974 | intel_encoder->enable = cpt_enable_hdmi; | 1988 | intel_encoder->enable = cpt_enable_hdmi; |
| 1975 | else if (HAS_PCH_IBX(dev)) | 1989 | else if (HAS_PCH_IBX(dev_priv)) |
| 1976 | intel_encoder->enable = ibx_enable_hdmi; | 1990 | intel_encoder->enable = ibx_enable_hdmi; |
| 1977 | else | 1991 | else |
| 1978 | intel_encoder->enable = g4x_enable_hdmi; | 1992 | intel_encoder->enable = g4x_enable_hdmi; |
| 1979 | } | 1993 | } |
| 1980 | 1994 | ||
| 1981 | intel_encoder->type = INTEL_OUTPUT_HDMI; | 1995 | intel_encoder->type = INTEL_OUTPUT_HDMI; |
| 1982 | if (IS_CHERRYVIEW(dev)) { | 1996 | intel_encoder->port = port; |
| 1997 | if (IS_CHERRYVIEW(dev_priv)) { | ||
| 1983 | if (port == PORT_D) | 1998 | if (port == PORT_D) |
| 1984 | intel_encoder->crtc_mask = 1 << 2; | 1999 | intel_encoder->crtc_mask = 1 << 2; |
| 1985 | else | 2000 | else |
| @@ -1993,7 +2008,7 @@ void intel_hdmi_init(struct drm_device *dev, | |||
| 1993 | * to work on real hardware. And since g4x can send infoframes to | 2008 | * to work on real hardware. And since g4x can send infoframes to |
| 1994 | * only one port anyway, nothing is lost by allowing it. | 2009 | * only one port anyway, nothing is lost by allowing it. |
| 1995 | */ | 2010 | */ |
| 1996 | if (IS_G4X(dev)) | 2011 | if (IS_G4X(dev_priv)) |
| 1997 | intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI; | 2012 | intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI; |
| 1998 | 2013 | ||
| 1999 | intel_dig_port->port = port; | 2014 | intel_dig_port->port = port; |
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 79aab9ad6faa..83f260bb4eef 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
| @@ -138,11 +138,10 @@ static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable) | |||
| 138 | static u32 get_reserved(struct intel_gmbus *bus) | 138 | static u32 get_reserved(struct intel_gmbus *bus) |
| 139 | { | 139 | { |
| 140 | struct drm_i915_private *dev_priv = bus->dev_priv; | 140 | struct drm_i915_private *dev_priv = bus->dev_priv; |
| 141 | struct drm_device *dev = &dev_priv->drm; | ||
| 142 | u32 reserved = 0; | 141 | u32 reserved = 0; |
| 143 | 142 | ||
| 144 | /* On most chips, these bits must be preserved in software. */ | 143 | /* On most chips, these bits must be preserved in software. */ |
| 145 | if (!IS_I830(dev) && !IS_845G(dev)) | 144 | if (!IS_I830(dev_priv) && !IS_845G(dev_priv)) |
| 146 | reserved = I915_READ_NOTRACE(bus->gpio_reg) & | 145 | reserved = I915_READ_NOTRACE(bus->gpio_reg) & |
| 147 | (GPIO_DATA_PULLUP_DISABLE | | 146 | (GPIO_DATA_PULLUP_DISABLE | |
| 148 | GPIO_CLOCK_PULLUP_DISABLE); | 147 | GPIO_CLOCK_PULLUP_DISABLE); |
| @@ -468,13 +467,9 @@ do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) | |||
| 468 | struct intel_gmbus, | 467 | struct intel_gmbus, |
| 469 | adapter); | 468 | adapter); |
| 470 | struct drm_i915_private *dev_priv = bus->dev_priv; | 469 | struct drm_i915_private *dev_priv = bus->dev_priv; |
| 471 | const unsigned int fw = | ||
| 472 | intel_uncore_forcewake_for_reg(dev_priv, GMBUS0, | ||
| 473 | FW_REG_READ | FW_REG_WRITE); | ||
| 474 | int i = 0, inc, try = 0; | 470 | int i = 0, inc, try = 0; |
| 475 | int ret = 0; | 471 | int ret = 0; |
| 476 | 472 | ||
| 477 | intel_uncore_forcewake_get(dev_priv, fw); | ||
| 478 | retry: | 473 | retry: |
| 479 | I915_WRITE_FW(GMBUS0, bus->reg0); | 474 | I915_WRITE_FW(GMBUS0, bus->reg0); |
| 480 | 475 | ||
| @@ -576,7 +571,6 @@ timeout: | |||
| 576 | ret = -EAGAIN; | 571 | ret = -EAGAIN; |
| 577 | 572 | ||
| 578 | out: | 573 | out: |
| 579 | intel_uncore_forcewake_put(dev_priv, fw); | ||
| 580 | return ret; | 574 | return ret; |
| 581 | } | 575 | } |
| 582 | 576 | ||
| @@ -633,10 +627,10 @@ int intel_setup_gmbus(struct drm_device *dev) | |||
| 633 | unsigned int pin; | 627 | unsigned int pin; |
| 634 | int ret; | 628 | int ret; |
| 635 | 629 | ||
| 636 | if (HAS_PCH_NOP(dev)) | 630 | if (HAS_PCH_NOP(dev_priv)) |
| 637 | return 0; | 631 | return 0; |
| 638 | 632 | ||
| 639 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 633 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 640 | dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE; | 634 | dev_priv->gpio_mmio_base = VLV_DISPLAY_BASE; |
| 641 | else if (!HAS_GMCH_DISPLAY(dev_priv)) | 635 | else if (!HAS_GMCH_DISPLAY(dev_priv)) |
| 642 | dev_priv->gpio_mmio_base = | 636 | dev_priv->gpio_mmio_base = |
| @@ -674,7 +668,7 @@ int intel_setup_gmbus(struct drm_device *dev) | |||
| 674 | bus->reg0 = pin | GMBUS_RATE_100KHZ; | 668 | bus->reg0 = pin | GMBUS_RATE_100KHZ; |
| 675 | 669 | ||
| 676 | /* gmbus seems to be broken on i830 */ | 670 | /* gmbus seems to be broken on i830 */ |
| 677 | if (IS_I830(dev)) | 671 | if (IS_I830(dev_priv)) |
| 678 | bus->force_bit = 1; | 672 | bus->force_bit = 1; |
| 679 | 673 | ||
| 680 | intel_gpio_setup(bus, pin); | 674 | intel_gpio_setup(bus, pin); |
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 251143361f31..bc86585b9fbb 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
| @@ -226,10 +226,16 @@ enum { | |||
| 226 | /* Typical size of the average request (2 pipecontrols and a MI_BB) */ | 226 | /* Typical size of the average request (2 pipecontrols and a MI_BB) */ |
| 227 | #define EXECLISTS_REQUEST_SIZE 64 /* bytes */ | 227 | #define EXECLISTS_REQUEST_SIZE 64 /* bytes */ |
| 228 | 228 | ||
| 229 | #define WA_TAIL_DWORDS 2 | ||
| 230 | |||
| 229 | static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, | 231 | static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, |
| 230 | struct intel_engine_cs *engine); | 232 | struct intel_engine_cs *engine); |
| 231 | static int intel_lr_context_pin(struct i915_gem_context *ctx, | 233 | static int intel_lr_context_pin(struct i915_gem_context *ctx, |
| 232 | struct intel_engine_cs *engine); | 234 | struct intel_engine_cs *engine); |
| 235 | static void execlists_init_reg_state(u32 *reg_state, | ||
| 236 | struct i915_gem_context *ctx, | ||
| 237 | struct intel_engine_cs *engine, | ||
| 238 | struct intel_ring *ring); | ||
| 233 | 239 | ||
| 234 | /** | 240 | /** |
| 235 | * intel_sanitize_enable_execlists() - sanitize i915.enable_execlists | 241 | * intel_sanitize_enable_execlists() - sanitize i915.enable_execlists |
| @@ -269,8 +275,7 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *engine) | |||
| 269 | struct drm_i915_private *dev_priv = engine->i915; | 275 | struct drm_i915_private *dev_priv = engine->i915; |
| 270 | 276 | ||
| 271 | engine->disable_lite_restore_wa = | 277 | engine->disable_lite_restore_wa = |
| 272 | (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || | 278 | IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1) && |
| 273 | IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) && | ||
| 274 | (engine->id == VCS || engine->id == VCS2); | 279 | (engine->id == VCS || engine->id == VCS2); |
| 275 | 280 | ||
| 276 | engine->ctx_desc_template = GEN8_CTX_VALID; | 281 | engine->ctx_desc_template = GEN8_CTX_VALID; |
| @@ -621,6 +626,10 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request | |||
| 621 | 626 | ||
| 622 | request->ring = ce->ring; | 627 | request->ring = ce->ring; |
| 623 | 628 | ||
| 629 | ret = intel_lr_context_pin(request->ctx, engine); | ||
| 630 | if (ret) | ||
| 631 | return ret; | ||
| 632 | |||
| 624 | if (i915.enable_guc_submission) { | 633 | if (i915.enable_guc_submission) { |
| 625 | /* | 634 | /* |
| 626 | * Check that the GuC has space for the request before | 635 | * Check that the GuC has space for the request before |
| @@ -629,21 +638,17 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request | |||
| 629 | */ | 638 | */ |
| 630 | ret = i915_guc_wq_reserve(request); | 639 | ret = i915_guc_wq_reserve(request); |
| 631 | if (ret) | 640 | if (ret) |
| 632 | return ret; | 641 | goto err_unpin; |
| 633 | } | 642 | } |
| 634 | 643 | ||
| 635 | ret = intel_lr_context_pin(request->ctx, engine); | ||
| 636 | if (ret) | ||
| 637 | return ret; | ||
| 638 | |||
| 639 | ret = intel_ring_begin(request, 0); | 644 | ret = intel_ring_begin(request, 0); |
| 640 | if (ret) | 645 | if (ret) |
| 641 | goto err_unpin; | 646 | goto err_unreserve; |
| 642 | 647 | ||
| 643 | if (!ce->initialised) { | 648 | if (!ce->initialised) { |
| 644 | ret = engine->init_context(request); | 649 | ret = engine->init_context(request); |
| 645 | if (ret) | 650 | if (ret) |
| 646 | goto err_unpin; | 651 | goto err_unreserve; |
| 647 | 652 | ||
| 648 | ce->initialised = true; | 653 | ce->initialised = true; |
| 649 | } | 654 | } |
| @@ -658,6 +663,9 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request | |||
| 658 | request->reserved_space -= EXECLISTS_REQUEST_SIZE; | 663 | request->reserved_space -= EXECLISTS_REQUEST_SIZE; |
| 659 | return 0; | 664 | return 0; |
| 660 | 665 | ||
| 666 | err_unreserve: | ||
| 667 | if (i915.enable_guc_submission) | ||
| 668 | i915_guc_wq_unreserve(request); | ||
| 661 | err_unpin: | 669 | err_unpin: |
| 662 | intel_lr_context_unpin(request->ctx, engine); | 670 | intel_lr_context_unpin(request->ctx, engine); |
| 663 | return ret; | 671 | return ret; |
| @@ -708,7 +716,6 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx, | |||
| 708 | { | 716 | { |
| 709 | struct intel_context *ce = &ctx->engine[engine->id]; | 717 | struct intel_context *ce = &ctx->engine[engine->id]; |
| 710 | void *vaddr; | 718 | void *vaddr; |
| 711 | u32 *lrc_reg_state; | ||
| 712 | int ret; | 719 | int ret; |
| 713 | 720 | ||
| 714 | lockdep_assert_held(&ctx->i915->drm.struct_mutex); | 721 | lockdep_assert_held(&ctx->i915->drm.struct_mutex); |
| @@ -727,17 +734,16 @@ static int intel_lr_context_pin(struct i915_gem_context *ctx, | |||
| 727 | goto unpin_vma; | 734 | goto unpin_vma; |
| 728 | } | 735 | } |
| 729 | 736 | ||
| 730 | lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; | ||
| 731 | |||
| 732 | ret = intel_ring_pin(ce->ring); | 737 | ret = intel_ring_pin(ce->ring); |
| 733 | if (ret) | 738 | if (ret) |
| 734 | goto unpin_map; | 739 | goto unpin_map; |
| 735 | 740 | ||
| 736 | intel_lr_context_descriptor_update(ctx, engine); | 741 | intel_lr_context_descriptor_update(ctx, engine); |
| 737 | 742 | ||
| 738 | lrc_reg_state[CTX_RING_BUFFER_START+1] = | 743 | ce->lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; |
| 744 | ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = | ||
| 739 | i915_ggtt_offset(ce->ring->vma); | 745 | i915_ggtt_offset(ce->ring->vma); |
| 740 | ce->lrc_reg_state = lrc_reg_state; | 746 | |
| 741 | ce->state->obj->dirty = true; | 747 | ce->state->obj->dirty = true; |
| 742 | 748 | ||
| 743 | /* Invalidate GuC TLB. */ | 749 | /* Invalidate GuC TLB. */ |
| @@ -846,13 +852,12 @@ static inline int gen8_emit_flush_coherentl3_wa(struct intel_engine_cs *engine, | |||
| 846 | uint32_t l3sqc4_flush = (0x40400000 | GEN8_LQSC_FLUSH_COHERENT_LINES); | 852 | uint32_t l3sqc4_flush = (0x40400000 | GEN8_LQSC_FLUSH_COHERENT_LINES); |
| 847 | 853 | ||
| 848 | /* | 854 | /* |
| 849 | * WaDisableLSQCROPERFforOCL:skl,kbl | 855 | * WaDisableLSQCROPERFforOCL:kbl |
| 850 | * This WA is implemented in skl_init_clock_gating() but since | 856 | * This WA is implemented in skl_init_clock_gating() but since |
| 851 | * this batch updates GEN8_L3SQCREG4 with default value we need to | 857 | * this batch updates GEN8_L3SQCREG4 with default value we need to |
| 852 | * set this bit here to retain the WA during flush. | 858 | * set this bit here to retain the WA during flush. |
| 853 | */ | 859 | */ |
| 854 | if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0) || | 860 | if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0)) |
| 855 | IS_KBL_REVID(dev_priv, 0, KBL_REVID_E0)) | ||
| 856 | l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS; | 861 | l3sqc4_flush |= GEN8_LQSC_RO_PERF_DIS; |
| 857 | 862 | ||
| 858 | wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 | | 863 | wa_ctx_emit(batch, index, (MI_STORE_REGISTER_MEM_GEN8 | |
| @@ -995,9 +1000,8 @@ static int gen9_init_indirectctx_bb(struct intel_engine_cs *engine, | |||
| 995 | struct drm_i915_private *dev_priv = engine->i915; | 1000 | struct drm_i915_private *dev_priv = engine->i915; |
| 996 | uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS); | 1001 | uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS); |
| 997 | 1002 | ||
| 998 | /* WaDisableCtxRestoreArbitration:skl,bxt */ | 1003 | /* WaDisableCtxRestoreArbitration:bxt */ |
| 999 | if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_D0) || | 1004 | if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) |
| 1000 | IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) | ||
| 1001 | wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE); | 1005 | wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_DISABLE); |
| 1002 | 1006 | ||
| 1003 | /* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt */ | 1007 | /* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt */ |
| @@ -1068,9 +1072,8 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *engine, | |||
| 1068 | { | 1072 | { |
| 1069 | uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS); | 1073 | uint32_t index = wa_ctx_start(wa_ctx, *offset, CACHELINE_DWORDS); |
| 1070 | 1074 | ||
| 1071 | /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ | 1075 | /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */ |
| 1072 | if (IS_SKL_REVID(engine->i915, 0, SKL_REVID_B0) || | 1076 | if (IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) { |
| 1073 | IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) { | ||
| 1074 | wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1)); | 1077 | wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(1)); |
| 1075 | wa_ctx_emit_reg(batch, index, GEN9_SLICE_COMMON_ECO_CHICKEN0); | 1078 | wa_ctx_emit_reg(batch, index, GEN9_SLICE_COMMON_ECO_CHICKEN0); |
| 1076 | wa_ctx_emit(batch, index, | 1079 | wa_ctx_emit(batch, index, |
| @@ -1097,9 +1100,8 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *engine, | |||
| 1097 | wa_ctx_emit(batch, index, MI_NOOP); | 1100 | wa_ctx_emit(batch, index, MI_NOOP); |
| 1098 | } | 1101 | } |
| 1099 | 1102 | ||
| 1100 | /* WaDisableCtxRestoreArbitration:skl,bxt */ | 1103 | /* WaDisableCtxRestoreArbitration:bxt */ |
| 1101 | if (IS_SKL_REVID(engine->i915, 0, SKL_REVID_D0) || | 1104 | if (IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) |
| 1102 | IS_BXT_REVID(engine->i915, 0, BXT_REVID_A1)) | ||
| 1103 | wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_ENABLE); | 1105 | wa_ctx_emit(batch, index, MI_ARB_ON_OFF | MI_ARB_ENABLE); |
| 1104 | 1106 | ||
| 1105 | wa_ctx_emit(batch, index, MI_BATCH_BUFFER_END); | 1107 | wa_ctx_emit(batch, index, MI_BATCH_BUFFER_END); |
| @@ -1231,7 +1233,7 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) | |||
| 1231 | 1233 | ||
| 1232 | lrc_init_hws(engine); | 1234 | lrc_init_hws(engine); |
| 1233 | 1235 | ||
| 1234 | intel_engine_reset_irq(engine); | 1236 | intel_engine_reset_breadcrumbs(engine); |
| 1235 | 1237 | ||
| 1236 | I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff); | 1238 | I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff); |
| 1237 | 1239 | ||
| @@ -1243,8 +1245,12 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) | |||
| 1243 | 1245 | ||
| 1244 | intel_engine_init_hangcheck(engine); | 1246 | intel_engine_init_hangcheck(engine); |
| 1245 | 1247 | ||
| 1246 | if (!execlists_elsp_idle(engine)) | 1248 | /* After a GPU reset, we may have requests to replay */ |
| 1249 | if (!execlists_elsp_idle(engine)) { | ||
| 1250 | engine->execlist_port[0].count = 0; | ||
| 1251 | engine->execlist_port[1].count = 0; | ||
| 1247 | execlists_submit_ports(engine); | 1252 | execlists_submit_ports(engine); |
| 1253 | } | ||
| 1248 | 1254 | ||
| 1249 | return 0; | 1255 | return 0; |
| 1250 | } | 1256 | } |
| @@ -1289,8 +1295,21 @@ static void reset_common_ring(struct intel_engine_cs *engine, | |||
| 1289 | struct execlist_port *port = engine->execlist_port; | 1295 | struct execlist_port *port = engine->execlist_port; |
| 1290 | struct intel_context *ce = &request->ctx->engine[engine->id]; | 1296 | struct intel_context *ce = &request->ctx->engine[engine->id]; |
| 1291 | 1297 | ||
| 1298 | /* We want a simple context + ring to execute the breadcrumb update. | ||
| 1299 | * We cannot rely on the context being intact across the GPU hang, | ||
| 1300 | * so clear it and rebuild just what we need for the breadcrumb. | ||
| 1301 | * All pending requests for this context will be zapped, and any | ||
| 1302 | * future request will be after userspace has had the opportunity | ||
| 1303 | * to recreate its own state. | ||
| 1304 | */ | ||
| 1305 | execlists_init_reg_state(ce->lrc_reg_state, | ||
| 1306 | request->ctx, engine, ce->ring); | ||
| 1307 | |||
| 1292 | /* Move the RING_HEAD onto the breadcrumb, past the hanging batch */ | 1308 | /* Move the RING_HEAD onto the breadcrumb, past the hanging batch */ |
| 1309 | ce->lrc_reg_state[CTX_RING_BUFFER_START+1] = | ||
| 1310 | i915_ggtt_offset(ce->ring->vma); | ||
| 1293 | ce->lrc_reg_state[CTX_RING_HEAD+1] = request->postfix; | 1311 | ce->lrc_reg_state[CTX_RING_HEAD+1] = request->postfix; |
| 1312 | |||
| 1294 | request->ring->head = request->postfix; | 1313 | request->ring->head = request->postfix; |
| 1295 | request->ring->last_retired_head = -1; | 1314 | request->ring->last_retired_head = -1; |
| 1296 | intel_ring_update_space(request->ring); | 1315 | intel_ring_update_space(request->ring); |
| @@ -1306,10 +1325,10 @@ static void reset_common_ring(struct intel_engine_cs *engine, | |||
| 1306 | memset(&port[1], 0, sizeof(port[1])); | 1325 | memset(&port[1], 0, sizeof(port[1])); |
| 1307 | } | 1326 | } |
| 1308 | 1327 | ||
| 1309 | /* CS is stopped, and we will resubmit both ports on resume */ | ||
| 1310 | GEM_BUG_ON(request->ctx != port[0].request->ctx); | 1328 | GEM_BUG_ON(request->ctx != port[0].request->ctx); |
| 1311 | port[0].count = 0; | 1329 | |
| 1312 | port[1].count = 0; | 1330 | /* Reset WaIdleLiteRestore:bdw,skl as well */ |
| 1331 | request->tail = request->wa_tail - WA_TAIL_DWORDS * sizeof(u32); | ||
| 1313 | } | 1332 | } |
| 1314 | 1333 | ||
| 1315 | static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) | 1334 | static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) |
| @@ -1547,7 +1566,6 @@ static void bxt_a_seqno_barrier(struct intel_engine_cs *engine) | |||
| 1547 | * used as a workaround for not being allowed to do lite | 1566 | * used as a workaround for not being allowed to do lite |
| 1548 | * restore with HEAD==TAIL (WaIdleLiteRestore). | 1567 | * restore with HEAD==TAIL (WaIdleLiteRestore). |
| 1549 | */ | 1568 | */ |
| 1550 | #define WA_TAIL_DWORDS 2 | ||
| 1551 | 1569 | ||
| 1552 | static int gen8_emit_request(struct drm_i915_gem_request *request) | 1570 | static int gen8_emit_request(struct drm_i915_gem_request *request) |
| 1553 | { | 1571 | { |
| @@ -1630,9 +1648,6 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) | |||
| 1630 | { | 1648 | { |
| 1631 | struct drm_i915_private *dev_priv; | 1649 | struct drm_i915_private *dev_priv; |
| 1632 | 1650 | ||
| 1633 | if (!intel_engine_initialized(engine)) | ||
| 1634 | return; | ||
| 1635 | |||
| 1636 | /* | 1651 | /* |
| 1637 | * Tasklet cannot be active at this point due intel_mark_active/idle | 1652 | * Tasklet cannot be active at this point due intel_mark_active/idle |
| 1638 | * so this is just for documentation. | 1653 | * so this is just for documentation. |
| @@ -1659,13 +1674,16 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) | |||
| 1659 | 1674 | ||
| 1660 | lrc_destroy_wa_ctx_obj(engine); | 1675 | lrc_destroy_wa_ctx_obj(engine); |
| 1661 | engine->i915 = NULL; | 1676 | engine->i915 = NULL; |
| 1677 | dev_priv->engine[engine->id] = NULL; | ||
| 1678 | kfree(engine); | ||
| 1662 | } | 1679 | } |
| 1663 | 1680 | ||
| 1664 | void intel_execlists_enable_submission(struct drm_i915_private *dev_priv) | 1681 | void intel_execlists_enable_submission(struct drm_i915_private *dev_priv) |
| 1665 | { | 1682 | { |
| 1666 | struct intel_engine_cs *engine; | 1683 | struct intel_engine_cs *engine; |
| 1684 | enum intel_engine_id id; | ||
| 1667 | 1685 | ||
| 1668 | for_each_engine(engine, dev_priv) | 1686 | for_each_engine(engine, dev_priv, id) |
| 1669 | engine->submit_request = execlists_submit_request; | 1687 | engine->submit_request = execlists_submit_request; |
| 1670 | } | 1688 | } |
| 1671 | 1689 | ||
| @@ -1894,38 +1912,13 @@ static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *engine) | |||
| 1894 | return indirect_ctx_offset; | 1912 | return indirect_ctx_offset; |
| 1895 | } | 1913 | } |
| 1896 | 1914 | ||
| 1897 | static int | 1915 | static void execlists_init_reg_state(u32 *reg_state, |
| 1898 | populate_lr_context(struct i915_gem_context *ctx, | 1916 | struct i915_gem_context *ctx, |
| 1899 | struct drm_i915_gem_object *ctx_obj, | 1917 | struct intel_engine_cs *engine, |
| 1900 | struct intel_engine_cs *engine, | 1918 | struct intel_ring *ring) |
| 1901 | struct intel_ring *ring) | ||
| 1902 | { | 1919 | { |
| 1903 | struct drm_i915_private *dev_priv = ctx->i915; | 1920 | struct drm_i915_private *dev_priv = engine->i915; |
| 1904 | struct i915_hw_ppgtt *ppgtt = ctx->ppgtt; | 1921 | struct i915_hw_ppgtt *ppgtt = ctx->ppgtt ?: dev_priv->mm.aliasing_ppgtt; |
| 1905 | void *vaddr; | ||
| 1906 | u32 *reg_state; | ||
| 1907 | int ret; | ||
| 1908 | |||
| 1909 | if (!ppgtt) | ||
| 1910 | ppgtt = dev_priv->mm.aliasing_ppgtt; | ||
| 1911 | |||
| 1912 | ret = i915_gem_object_set_to_cpu_domain(ctx_obj, true); | ||
| 1913 | if (ret) { | ||
| 1914 | DRM_DEBUG_DRIVER("Could not set to CPU domain\n"); | ||
| 1915 | return ret; | ||
| 1916 | } | ||
| 1917 | |||
| 1918 | vaddr = i915_gem_object_pin_map(ctx_obj, I915_MAP_WB); | ||
| 1919 | if (IS_ERR(vaddr)) { | ||
| 1920 | ret = PTR_ERR(vaddr); | ||
| 1921 | DRM_DEBUG_DRIVER("Could not map object pages! (%d)\n", ret); | ||
| 1922 | return ret; | ||
| 1923 | } | ||
| 1924 | ctx_obj->dirty = true; | ||
| 1925 | |||
| 1926 | /* The second page of the context object contains some fields which must | ||
| 1927 | * be set up prior to the first execution. */ | ||
| 1928 | reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; | ||
| 1929 | 1922 | ||
| 1930 | /* A context is actually a big batch buffer with several MI_LOAD_REGISTER_IMM | 1923 | /* A context is actually a big batch buffer with several MI_LOAD_REGISTER_IMM |
| 1931 | * commands followed by (reg, value) pairs. The values we are setting here are | 1924 | * commands followed by (reg, value) pairs. The values we are setting here are |
| @@ -1939,19 +1932,16 @@ populate_lr_context(struct i915_gem_context *ctx, | |||
| 1939 | _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH | | 1932 | _MASKED_BIT_ENABLE(CTX_CTRL_INHIBIT_SYN_CTX_SWITCH | |
| 1940 | CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | | 1933 | CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT | |
| 1941 | (HAS_RESOURCE_STREAMER(dev_priv) ? | 1934 | (HAS_RESOURCE_STREAMER(dev_priv) ? |
| 1942 | CTX_CTRL_RS_CTX_ENABLE : 0))); | 1935 | CTX_CTRL_RS_CTX_ENABLE : 0))); |
| 1943 | ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(engine->mmio_base), | 1936 | ASSIGN_CTX_REG(reg_state, CTX_RING_HEAD, RING_HEAD(engine->mmio_base), |
| 1944 | 0); | 1937 | 0); |
| 1945 | ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(engine->mmio_base), | 1938 | ASSIGN_CTX_REG(reg_state, CTX_RING_TAIL, RING_TAIL(engine->mmio_base), |
| 1946 | 0); | 1939 | 0); |
| 1947 | /* Ring buffer start address is not known until the buffer is pinned. | ||
| 1948 | * It is written to the context image in execlists_update_context() | ||
| 1949 | */ | ||
| 1950 | ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START, | 1940 | ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_START, |
| 1951 | RING_START(engine->mmio_base), 0); | 1941 | RING_START(engine->mmio_base), 0); |
| 1952 | ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL, | 1942 | ASSIGN_CTX_REG(reg_state, CTX_RING_BUFFER_CONTROL, |
| 1953 | RING_CTL(engine->mmio_base), | 1943 | RING_CTL(engine->mmio_base), |
| 1954 | ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | RING_VALID); | 1944 | RING_CTL_SIZE(ring->size) | RING_VALID); |
| 1955 | ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U, | 1945 | ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_U, |
| 1956 | RING_BBADDR_UDW(engine->mmio_base), 0); | 1946 | RING_BBADDR_UDW(engine->mmio_base), 0); |
| 1957 | ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L, | 1947 | ASSIGN_CTX_REG(reg_state, CTX_BB_HEAD_L, |
| @@ -2029,6 +2019,36 @@ populate_lr_context(struct i915_gem_context *ctx, | |||
| 2029 | ASSIGN_CTX_REG(reg_state, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE, | 2019 | ASSIGN_CTX_REG(reg_state, CTX_R_PWR_CLK_STATE, GEN8_R_PWR_CLK_STATE, |
| 2030 | make_rpcs(dev_priv)); | 2020 | make_rpcs(dev_priv)); |
| 2031 | } | 2021 | } |
| 2022 | } | ||
| 2023 | |||
| 2024 | static int | ||
| 2025 | populate_lr_context(struct i915_gem_context *ctx, | ||
| 2026 | struct drm_i915_gem_object *ctx_obj, | ||
| 2027 | struct intel_engine_cs *engine, | ||
| 2028 | struct intel_ring *ring) | ||
| 2029 | { | ||
| 2030 | void *vaddr; | ||
| 2031 | int ret; | ||
| 2032 | |||
| 2033 | ret = i915_gem_object_set_to_cpu_domain(ctx_obj, true); | ||
| 2034 | if (ret) { | ||
| 2035 | DRM_DEBUG_DRIVER("Could not set to CPU domain\n"); | ||
| 2036 | return ret; | ||
| 2037 | } | ||
| 2038 | |||
| 2039 | vaddr = i915_gem_object_pin_map(ctx_obj, I915_MAP_WB); | ||
| 2040 | if (IS_ERR(vaddr)) { | ||
| 2041 | ret = PTR_ERR(vaddr); | ||
| 2042 | DRM_DEBUG_DRIVER("Could not map object pages! (%d)\n", ret); | ||
| 2043 | return ret; | ||
| 2044 | } | ||
| 2045 | ctx_obj->dirty = true; | ||
| 2046 | |||
| 2047 | /* The second page of the context object contains some fields which must | ||
| 2048 | * be set up prior to the first execution. */ | ||
| 2049 | |||
| 2050 | execlists_init_reg_state(vaddr + LRC_STATE_PN * PAGE_SIZE, | ||
| 2051 | ctx, engine, ring); | ||
| 2032 | 2052 | ||
| 2033 | i915_gem_object_unpin_map(ctx_obj); | 2053 | i915_gem_object_unpin_map(ctx_obj); |
| 2034 | 2054 | ||
| @@ -2129,30 +2149,43 @@ error_deref_obj: | |||
| 2129 | 2149 | ||
| 2130 | void intel_lr_context_resume(struct drm_i915_private *dev_priv) | 2150 | void intel_lr_context_resume(struct drm_i915_private *dev_priv) |
| 2131 | { | 2151 | { |
| 2132 | struct i915_gem_context *ctx = dev_priv->kernel_context; | ||
| 2133 | struct intel_engine_cs *engine; | 2152 | struct intel_engine_cs *engine; |
| 2153 | struct i915_gem_context *ctx; | ||
| 2154 | enum intel_engine_id id; | ||
| 2155 | |||
| 2156 | /* Because we emit WA_TAIL_DWORDS there may be a disparity | ||
| 2157 | * between our bookkeeping in ce->ring->head and ce->ring->tail and | ||
| 2158 | * that stored in context. As we only write new commands from | ||
| 2159 | * ce->ring->tail onwards, everything before that is junk. If the GPU | ||
| 2160 | * starts reading from its RING_HEAD from the context, it may try to | ||
| 2161 | * execute that junk and die. | ||
| 2162 | * | ||
| 2163 | * So to avoid that we reset the context images upon resume. For | ||
| 2164 | * simplicity, we just zero everything out. | ||
| 2165 | */ | ||
| 2166 | list_for_each_entry(ctx, &dev_priv->context_list, link) { | ||
| 2167 | for_each_engine(engine, dev_priv, id) { | ||
| 2168 | struct intel_context *ce = &ctx->engine[engine->id]; | ||
| 2169 | u32 *reg; | ||
| 2134 | 2170 | ||
| 2135 | for_each_engine(engine, dev_priv) { | 2171 | if (!ce->state) |
| 2136 | struct intel_context *ce = &ctx->engine[engine->id]; | 2172 | continue; |
| 2137 | void *vaddr; | ||
| 2138 | uint32_t *reg_state; | ||
| 2139 | |||
| 2140 | if (!ce->state) | ||
| 2141 | continue; | ||
| 2142 | |||
| 2143 | vaddr = i915_gem_object_pin_map(ce->state->obj, I915_MAP_WB); | ||
| 2144 | if (WARN_ON(IS_ERR(vaddr))) | ||
| 2145 | continue; | ||
| 2146 | 2173 | ||
| 2147 | reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE; | 2174 | reg = i915_gem_object_pin_map(ce->state->obj, |
| 2175 | I915_MAP_WB); | ||
| 2176 | if (WARN_ON(IS_ERR(reg))) | ||
| 2177 | continue; | ||
| 2148 | 2178 | ||
| 2149 | reg_state[CTX_RING_HEAD+1] = 0; | 2179 | reg += LRC_STATE_PN * PAGE_SIZE / sizeof(*reg); |
| 2150 | reg_state[CTX_RING_TAIL+1] = 0; | 2180 | reg[CTX_RING_HEAD+1] = 0; |
| 2181 | reg[CTX_RING_TAIL+1] = 0; | ||
| 2151 | 2182 | ||
| 2152 | ce->state->obj->dirty = true; | 2183 | ce->state->obj->dirty = true; |
| 2153 | i915_gem_object_unpin_map(ce->state->obj); | 2184 | i915_gem_object_unpin_map(ce->state->obj); |
| 2154 | 2185 | ||
| 2155 | ce->ring->head = 0; | 2186 | ce->ring->head = ce->ring->tail = 0; |
| 2156 | ce->ring->tail = 0; | 2187 | ce->ring->last_retired_head = -1; |
| 2188 | intel_ring_update_space(ce->ring); | ||
| 2189 | } | ||
| 2157 | } | 2190 | } |
| 2158 | } | 2191 | } |
diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c new file mode 100644 index 000000000000..632149c6b3ad --- /dev/null +++ b/drivers/gpu/drm/i915/intel_lspcon.c | |||
| @@ -0,0 +1,136 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2016 Intel Corporation | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice (including the next | ||
| 12 | * paragraph) shall be included in all copies or substantial portions of the | ||
| 13 | * Software. | ||
| 14 | * | ||
| 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 21 | * DEALINGS IN THE SOFTWARE. | ||
| 22 | * | ||
| 23 | * | ||
| 24 | */ | ||
| 25 | #include <drm/drm_edid.h> | ||
| 26 | #include <drm/drm_atomic_helper.h> | ||
| 27 | #include <drm/drm_dp_dual_mode_helper.h> | ||
| 28 | #include "intel_drv.h" | ||
| 29 | |||
| 30 | static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon) | ||
| 31 | { | ||
| 32 | enum drm_lspcon_mode current_mode = DRM_LSPCON_MODE_INVALID; | ||
| 33 | struct i2c_adapter *adapter = &lspcon->aux->ddc; | ||
| 34 | |||
| 35 | if (drm_lspcon_get_mode(adapter, ¤t_mode)) | ||
| 36 | DRM_ERROR("Error reading LSPCON mode\n"); | ||
| 37 | else | ||
| 38 | DRM_DEBUG_KMS("Current LSPCON mode %s\n", | ||
| 39 | current_mode == DRM_LSPCON_MODE_PCON ? "PCON" : "LS"); | ||
| 40 | return current_mode; | ||
| 41 | } | ||
| 42 | |||
| 43 | static int lspcon_change_mode(struct intel_lspcon *lspcon, | ||
| 44 | enum drm_lspcon_mode mode, bool force) | ||
| 45 | { | ||
| 46 | int err; | ||
| 47 | enum drm_lspcon_mode current_mode; | ||
| 48 | struct i2c_adapter *adapter = &lspcon->aux->ddc; | ||
| 49 | |||
| 50 | err = drm_lspcon_get_mode(adapter, ¤t_mode); | ||
| 51 | if (err) { | ||
| 52 | DRM_ERROR("Error reading LSPCON mode\n"); | ||
| 53 | return err; | ||
| 54 | } | ||
| 55 | |||
| 56 | if (current_mode == mode) { | ||
| 57 | DRM_DEBUG_KMS("Current mode = desired LSPCON mode\n"); | ||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | err = drm_lspcon_set_mode(adapter, mode); | ||
| 62 | if (err < 0) { | ||
| 63 | DRM_ERROR("LSPCON mode change failed\n"); | ||
| 64 | return err; | ||
| 65 | } | ||
| 66 | |||
| 67 | lspcon->mode = mode; | ||
| 68 | DRM_DEBUG_KMS("LSPCON mode changed done\n"); | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | static bool lspcon_probe(struct intel_lspcon *lspcon) | ||
| 73 | { | ||
| 74 | enum drm_dp_dual_mode_type adaptor_type; | ||
| 75 | struct i2c_adapter *adapter = &lspcon->aux->ddc; | ||
| 76 | |||
| 77 | /* Lets probe the adaptor and check its type */ | ||
| 78 | adaptor_type = drm_dp_dual_mode_detect(adapter); | ||
| 79 | if (adaptor_type != DRM_DP_DUAL_MODE_LSPCON) { | ||
| 80 | DRM_DEBUG_KMS("No LSPCON detected, found %s\n", | ||
| 81 | drm_dp_get_dual_mode_type_name(adaptor_type)); | ||
| 82 | return false; | ||
| 83 | } | ||
| 84 | |||
| 85 | /* Yay ... got a LSPCON device */ | ||
| 86 | DRM_DEBUG_KMS("LSPCON detected\n"); | ||
| 87 | lspcon->mode = lspcon_get_current_mode(lspcon); | ||
| 88 | lspcon->active = true; | ||
| 89 | return true; | ||
| 90 | } | ||
| 91 | |||
| 92 | void lspcon_resume(struct intel_lspcon *lspcon) | ||
| 93 | { | ||
| 94 | if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON, true)) | ||
| 95 | DRM_ERROR("LSPCON resume failed\n"); | ||
| 96 | else | ||
| 97 | DRM_DEBUG_KMS("LSPCON resume success\n"); | ||
| 98 | } | ||
| 99 | |||
| 100 | bool lspcon_init(struct intel_digital_port *intel_dig_port) | ||
| 101 | { | ||
| 102 | struct intel_dp *dp = &intel_dig_port->dp; | ||
| 103 | struct intel_lspcon *lspcon = &intel_dig_port->lspcon; | ||
| 104 | struct drm_device *dev = intel_dig_port->base.base.dev; | ||
| 105 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 106 | |||
| 107 | if (!IS_GEN9(dev_priv)) { | ||
| 108 | DRM_ERROR("LSPCON is supported on GEN9 only\n"); | ||
| 109 | return false; | ||
| 110 | } | ||
| 111 | |||
| 112 | lspcon->active = false; | ||
| 113 | lspcon->mode = DRM_LSPCON_MODE_INVALID; | ||
| 114 | lspcon->aux = &dp->aux; | ||
| 115 | |||
| 116 | if (!lspcon_probe(lspcon)) { | ||
| 117 | DRM_ERROR("Failed to probe lspcon\n"); | ||
| 118 | return false; | ||
| 119 | } | ||
| 120 | |||
| 121 | /* | ||
| 122 | * In the SW state machine, lets Put LSPCON in PCON mode only. | ||
| 123 | * In this way, it will work with both HDMI 1.4 sinks as well as HDMI | ||
| 124 | * 2.0 sinks. | ||
| 125 | */ | ||
| 126 | if (lspcon->active && lspcon->mode != DRM_LSPCON_MODE_PCON) { | ||
| 127 | if (lspcon_change_mode(lspcon, DRM_LSPCON_MODE_PCON, | ||
| 128 | true) < 0) { | ||
| 129 | DRM_ERROR("LSPCON mode change to PCON failed\n"); | ||
| 130 | return false; | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | DRM_DEBUG_KMS("Success: LSPCON init\n"); | ||
| 135 | return true; | ||
| 136 | } | ||
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index e1d47d51ea47..199b90c7907a 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -106,7 +106,7 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder, | |||
| 106 | if (!(tmp & LVDS_PORT_EN)) | 106 | if (!(tmp & LVDS_PORT_EN)) |
| 107 | goto out; | 107 | goto out; |
| 108 | 108 | ||
| 109 | if (HAS_PCH_CPT(dev)) | 109 | if (HAS_PCH_CPT(dev_priv)) |
| 110 | *pipe = PORT_TO_PIPE_CPT(tmp); | 110 | *pipe = PORT_TO_PIPE_CPT(tmp); |
| 111 | else | 111 | else |
| 112 | *pipe = PORT_TO_PIPE(tmp); | 112 | *pipe = PORT_TO_PIPE(tmp); |
| @@ -396,7 +396,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, | |||
| 396 | struct intel_crtc_state *pipe_config, | 396 | struct intel_crtc_state *pipe_config, |
| 397 | struct drm_connector_state *conn_state) | 397 | struct drm_connector_state *conn_state) |
| 398 | { | 398 | { |
| 399 | struct drm_device *dev = intel_encoder->base.dev; | 399 | struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev); |
| 400 | struct intel_lvds_encoder *lvds_encoder = | 400 | struct intel_lvds_encoder *lvds_encoder = |
| 401 | to_lvds_encoder(&intel_encoder->base); | 401 | to_lvds_encoder(&intel_encoder->base); |
| 402 | struct intel_connector *intel_connector = | 402 | struct intel_connector *intel_connector = |
| @@ -406,7 +406,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, | |||
| 406 | unsigned int lvds_bpp; | 406 | unsigned int lvds_bpp; |
| 407 | 407 | ||
| 408 | /* Should never happen!! */ | 408 | /* Should never happen!! */ |
| 409 | if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) { | 409 | if (INTEL_GEN(dev_priv) < 4 && intel_crtc->pipe == 0) { |
| 410 | DRM_ERROR("Can't support LVDS on pipe A\n"); | 410 | DRM_ERROR("Can't support LVDS on pipe A\n"); |
| 411 | return false; | 411 | return false; |
| 412 | } | 412 | } |
| @@ -431,7 +431,7 @@ static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder, | |||
| 431 | intel_fixed_panel_mode(intel_connector->panel.fixed_mode, | 431 | intel_fixed_panel_mode(intel_connector->panel.fixed_mode, |
| 432 | adjusted_mode); | 432 | adjusted_mode); |
| 433 | 433 | ||
| 434 | if (HAS_PCH_SPLIT(dev)) { | 434 | if (HAS_PCH_SPLIT(dev_priv)) { |
| 435 | pipe_config->has_pch_encoder = true; | 435 | pipe_config->has_pch_encoder = true; |
| 436 | 436 | ||
| 437 | intel_pch_panel_fitting(intel_crtc, pipe_config, | 437 | intel_pch_panel_fitting(intel_crtc, pipe_config, |
| @@ -566,7 +566,7 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, | |||
| 566 | * and as part of the cleanup in the hw state restore we also redisable | 566 | * and as part of the cleanup in the hw state restore we also redisable |
| 567 | * the vga plane. | 567 | * the vga plane. |
| 568 | */ | 568 | */ |
| 569 | if (!HAS_PCH_SPLIT(dev)) | 569 | if (!HAS_PCH_SPLIT(dev_priv)) |
| 570 | intel_display_resume(dev); | 570 | intel_display_resume(dev); |
| 571 | 571 | ||
| 572 | dev_priv->modeset_restore = MODESET_DONE; | 572 | dev_priv->modeset_restore = MODESET_DONE; |
| @@ -949,16 +949,17 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) | |||
| 949 | return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP; | 949 | return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP; |
| 950 | } | 950 | } |
| 951 | 951 | ||
| 952 | static bool intel_lvds_supported(struct drm_device *dev) | 952 | static bool intel_lvds_supported(struct drm_i915_private *dev_priv) |
| 953 | { | 953 | { |
| 954 | /* With the introduction of the PCH we gained a dedicated | 954 | /* With the introduction of the PCH we gained a dedicated |
| 955 | * LVDS presence pin, use it. */ | 955 | * LVDS presence pin, use it. */ |
| 956 | if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) | 956 | if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) |
| 957 | return true; | 957 | return true; |
| 958 | 958 | ||
| 959 | /* Otherwise LVDS was only attached to mobile products, | 959 | /* Otherwise LVDS was only attached to mobile products, |
| 960 | * except for the inglorious 830gm */ | 960 | * except for the inglorious 830gm */ |
| 961 | if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev)) | 961 | if (INTEL_GEN(dev_priv) <= 4 && |
| 962 | IS_MOBILE(dev_priv) && !IS_I830(dev_priv)) | ||
| 962 | return true; | 963 | return true; |
| 963 | 964 | ||
| 964 | return false; | 965 | return false; |
| @@ -990,21 +991,21 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 990 | int pipe; | 991 | int pipe; |
| 991 | u8 pin; | 992 | u8 pin; |
| 992 | 993 | ||
| 993 | if (!intel_lvds_supported(dev)) | 994 | if (!intel_lvds_supported(dev_priv)) |
| 994 | return; | 995 | return; |
| 995 | 996 | ||
| 996 | /* Skip init on machines we know falsely report LVDS */ | 997 | /* Skip init on machines we know falsely report LVDS */ |
| 997 | if (dmi_check_system(intel_no_lvds)) | 998 | if (dmi_check_system(intel_no_lvds)) |
| 998 | return; | 999 | return; |
| 999 | 1000 | ||
| 1000 | if (HAS_PCH_SPLIT(dev)) | 1001 | if (HAS_PCH_SPLIT(dev_priv)) |
| 1001 | lvds_reg = PCH_LVDS; | 1002 | lvds_reg = PCH_LVDS; |
| 1002 | else | 1003 | else |
| 1003 | lvds_reg = LVDS; | 1004 | lvds_reg = LVDS; |
| 1004 | 1005 | ||
| 1005 | lvds = I915_READ(lvds_reg); | 1006 | lvds = I915_READ(lvds_reg); |
| 1006 | 1007 | ||
| 1007 | if (HAS_PCH_SPLIT(dev)) { | 1008 | if (HAS_PCH_SPLIT(dev_priv)) { |
| 1008 | if ((lvds & LVDS_DETECTED) == 0) | 1009 | if ((lvds & LVDS_DETECTED) == 0) |
| 1009 | return; | 1010 | return; |
| 1010 | if (dev_priv->vbt.edp.support) { | 1011 | if (dev_priv->vbt.edp.support) { |
| @@ -1064,12 +1065,13 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 1064 | intel_connector->get_hw_state = intel_connector_get_hw_state; | 1065 | intel_connector->get_hw_state = intel_connector_get_hw_state; |
| 1065 | 1066 | ||
| 1066 | intel_connector_attach_encoder(intel_connector, intel_encoder); | 1067 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
| 1067 | intel_encoder->type = INTEL_OUTPUT_LVDS; | ||
| 1068 | 1068 | ||
| 1069 | intel_encoder->type = INTEL_OUTPUT_LVDS; | ||
| 1070 | intel_encoder->port = PORT_NONE; | ||
| 1069 | intel_encoder->cloneable = 0; | 1071 | intel_encoder->cloneable = 0; |
| 1070 | if (HAS_PCH_SPLIT(dev)) | 1072 | if (HAS_PCH_SPLIT(dev_priv)) |
| 1071 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); | 1073 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); |
| 1072 | else if (IS_GEN4(dev)) | 1074 | else if (IS_GEN4(dev_priv)) |
| 1073 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); | 1075 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); |
| 1074 | else | 1076 | else |
| 1075 | intel_encoder->crtc_mask = (1 << 1); | 1077 | intel_encoder->crtc_mask = (1 << 1); |
| @@ -1157,7 +1159,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 1157 | */ | 1159 | */ |
| 1158 | 1160 | ||
| 1159 | /* Ironlake: FIXME if still fail, not try pipe mode now */ | 1161 | /* Ironlake: FIXME if still fail, not try pipe mode now */ |
| 1160 | if (HAS_PCH_SPLIT(dev)) | 1162 | if (HAS_PCH_SPLIT(dev_priv)) |
| 1161 | goto failed; | 1163 | goto failed; |
| 1162 | 1164 | ||
| 1163 | pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; | 1165 | pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; |
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index a24bc8c7889f..25bcd4a178d3 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c | |||
| @@ -233,7 +233,7 @@ static int intel_overlay_do_wait_request(struct intel_overlay *overlay, | |||
| 233 | static struct drm_i915_gem_request *alloc_request(struct intel_overlay *overlay) | 233 | static struct drm_i915_gem_request *alloc_request(struct intel_overlay *overlay) |
| 234 | { | 234 | { |
| 235 | struct drm_i915_private *dev_priv = overlay->i915; | 235 | struct drm_i915_private *dev_priv = overlay->i915; |
| 236 | struct intel_engine_cs *engine = &dev_priv->engine[RCS]; | 236 | struct intel_engine_cs *engine = dev_priv->engine[RCS]; |
| 237 | 237 | ||
| 238 | return i915_gem_request_alloc(engine, dev_priv->kernel_context); | 238 | return i915_gem_request_alloc(engine, dev_priv->kernel_context); |
| 239 | } | 239 | } |
| @@ -1470,6 +1470,8 @@ void intel_cleanup_overlay(struct drm_i915_private *dev_priv) | |||
| 1470 | kfree(dev_priv->overlay); | 1470 | kfree(dev_priv->overlay); |
| 1471 | } | 1471 | } |
| 1472 | 1472 | ||
| 1473 | #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) | ||
| 1474 | |||
| 1473 | struct intel_overlay_error_state { | 1475 | struct intel_overlay_error_state { |
| 1474 | struct overlay_registers regs; | 1476 | struct overlay_registers regs; |
| 1475 | unsigned long base; | 1477 | unsigned long base; |
| @@ -1587,3 +1589,5 @@ intel_overlay_print_error_state(struct drm_i915_error_state_buf *m, | |||
| 1587 | P(UVSCALEV); | 1589 | P(UVSCALEV); |
| 1588 | #undef P | 1590 | #undef P |
| 1589 | } | 1591 | } |
| 1592 | |||
| 1593 | #endif | ||
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index c10e9b0405e8..be4b4d546fd9 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
| @@ -841,7 +841,7 @@ static void lpt_enable_backlight(struct intel_connector *connector) | |||
| 841 | { | 841 | { |
| 842 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); | 842 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
| 843 | struct intel_panel *panel = &connector->panel; | 843 | struct intel_panel *panel = &connector->panel; |
| 844 | u32 pch_ctl1, pch_ctl2; | 844 | u32 pch_ctl1, pch_ctl2, schicken; |
| 845 | 845 | ||
| 846 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); | 846 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
| 847 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { | 847 | if (pch_ctl1 & BLM_PCH_PWM_ENABLE) { |
| @@ -850,6 +850,22 @@ static void lpt_enable_backlight(struct intel_connector *connector) | |||
| 850 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); | 850 | I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1); |
| 851 | } | 851 | } |
| 852 | 852 | ||
| 853 | if (HAS_PCH_LPT(dev_priv)) { | ||
| 854 | schicken = I915_READ(SOUTH_CHICKEN2); | ||
| 855 | if (panel->backlight.alternate_pwm_increment) | ||
| 856 | schicken |= LPT_PWM_GRANULARITY; | ||
| 857 | else | ||
| 858 | schicken &= ~LPT_PWM_GRANULARITY; | ||
| 859 | I915_WRITE(SOUTH_CHICKEN2, schicken); | ||
| 860 | } else { | ||
| 861 | schicken = I915_READ(SOUTH_CHICKEN1); | ||
| 862 | if (panel->backlight.alternate_pwm_increment) | ||
| 863 | schicken |= SPT_PWM_GRANULARITY; | ||
| 864 | else | ||
| 865 | schicken &= ~SPT_PWM_GRANULARITY; | ||
| 866 | I915_WRITE(SOUTH_CHICKEN1, schicken); | ||
| 867 | } | ||
| 868 | |||
| 853 | pch_ctl2 = panel->backlight.max << 16; | 869 | pch_ctl2 = panel->backlight.max << 16; |
| 854 | I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); | 870 | I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2); |
| 855 | 871 | ||
| @@ -1242,10 +1258,10 @@ static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | |||
| 1242 | */ | 1258 | */ |
| 1243 | static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | 1259 | static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
| 1244 | { | 1260 | { |
| 1245 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); | 1261 | struct intel_panel *panel = &connector->panel; |
| 1246 | u32 mul; | 1262 | u32 mul; |
| 1247 | 1263 | ||
| 1248 | if (I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY) | 1264 | if (panel->backlight.alternate_pwm_increment) |
| 1249 | mul = 128; | 1265 | mul = 128; |
| 1250 | else | 1266 | else |
| 1251 | mul = 16; | 1267 | mul = 16; |
| @@ -1261,9 +1277,10 @@ static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | |||
| 1261 | static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) | 1277 | static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz) |
| 1262 | { | 1278 | { |
| 1263 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); | 1279 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
| 1280 | struct intel_panel *panel = &connector->panel; | ||
| 1264 | u32 mul, clock; | 1281 | u32 mul, clock; |
| 1265 | 1282 | ||
| 1266 | if (I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY) | 1283 | if (panel->backlight.alternate_pwm_increment) |
| 1267 | mul = 16; | 1284 | mul = 16; |
| 1268 | else | 1285 | else |
| 1269 | mul = 128; | 1286 | mul = 128; |
| @@ -1414,6 +1431,13 @@ static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unus | |||
| 1414 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); | 1431 | struct drm_i915_private *dev_priv = to_i915(connector->base.dev); |
| 1415 | struct intel_panel *panel = &connector->panel; | 1432 | struct intel_panel *panel = &connector->panel; |
| 1416 | u32 pch_ctl1, pch_ctl2, val; | 1433 | u32 pch_ctl1, pch_ctl2, val; |
| 1434 | bool alt; | ||
| 1435 | |||
| 1436 | if (HAS_PCH_LPT(dev_priv)) | ||
| 1437 | alt = I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY; | ||
| 1438 | else | ||
| 1439 | alt = I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY; | ||
| 1440 | panel->backlight.alternate_pwm_increment = alt; | ||
| 1417 | 1441 | ||
| 1418 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); | 1442 | pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1); |
| 1419 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; | 1443 | panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY; |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1472400ddce3..560fc7af8267 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -252,8 +252,8 @@ static const struct cxsr_latency cxsr_latency_table[] = { | |||
| 252 | {0, 1, 400, 800, 6042, 36042, 6584, 36584}, /* DDR3-800 SC */ | 252 | {0, 1, 400, 800, 6042, 36042, 6584, 36584}, /* DDR3-800 SC */ |
| 253 | }; | 253 | }; |
| 254 | 254 | ||
| 255 | static const struct cxsr_latency *intel_get_cxsr_latency(int is_desktop, | 255 | static const struct cxsr_latency *intel_get_cxsr_latency(bool is_desktop, |
| 256 | int is_ddr3, | 256 | bool is_ddr3, |
| 257 | int fsb, | 257 | int fsb, |
| 258 | int mem) | 258 | int mem) |
| 259 | { | 259 | { |
| @@ -322,11 +322,11 @@ void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) | |||
| 322 | struct drm_device *dev = &dev_priv->drm; | 322 | struct drm_device *dev = &dev_priv->drm; |
| 323 | u32 val; | 323 | u32 val; |
| 324 | 324 | ||
| 325 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 325 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 326 | I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0); | 326 | I915_WRITE(FW_BLC_SELF_VLV, enable ? FW_CSPWRDWNEN : 0); |
| 327 | POSTING_READ(FW_BLC_SELF_VLV); | 327 | POSTING_READ(FW_BLC_SELF_VLV); |
| 328 | dev_priv->wm.vlv.cxsr = enable; | 328 | dev_priv->wm.vlv.cxsr = enable; |
| 329 | } else if (IS_G4X(dev) || IS_CRESTLINE(dev)) { | 329 | } else if (IS_G4X(dev_priv) || IS_CRESTLINE(dev_priv)) { |
| 330 | I915_WRITE(FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0); | 330 | I915_WRITE(FW_BLC_SELF, enable ? FW_BLC_SELF_EN : 0); |
| 331 | POSTING_READ(FW_BLC_SELF); | 331 | POSTING_READ(FW_BLC_SELF); |
| 332 | } else if (IS_PINEVIEW(dev)) { | 332 | } else if (IS_PINEVIEW(dev)) { |
| @@ -334,12 +334,12 @@ void intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enable) | |||
| 334 | val |= enable ? PINEVIEW_SELF_REFRESH_EN : 0; | 334 | val |= enable ? PINEVIEW_SELF_REFRESH_EN : 0; |
| 335 | I915_WRITE(DSPFW3, val); | 335 | I915_WRITE(DSPFW3, val); |
| 336 | POSTING_READ(DSPFW3); | 336 | POSTING_READ(DSPFW3); |
| 337 | } else if (IS_I945G(dev) || IS_I945GM(dev)) { | 337 | } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) { |
| 338 | val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) : | 338 | val = enable ? _MASKED_BIT_ENABLE(FW_BLC_SELF_EN) : |
| 339 | _MASKED_BIT_DISABLE(FW_BLC_SELF_EN); | 339 | _MASKED_BIT_DISABLE(FW_BLC_SELF_EN); |
| 340 | I915_WRITE(FW_BLC_SELF, val); | 340 | I915_WRITE(FW_BLC_SELF, val); |
| 341 | POSTING_READ(FW_BLC_SELF); | 341 | POSTING_READ(FW_BLC_SELF); |
| 342 | } else if (IS_I915GM(dev)) { | 342 | } else if (IS_I915GM(dev_priv)) { |
| 343 | /* | 343 | /* |
| 344 | * FIXME can't find a bit like this for 915G, and | 344 | * FIXME can't find a bit like this for 915G, and |
| 345 | * and yet it does have the related watermark in | 345 | * and yet it does have the related watermark in |
| @@ -648,8 +648,10 @@ static void pineview_update_wm(struct drm_crtc *unused_crtc) | |||
| 648 | u32 reg; | 648 | u32 reg; |
| 649 | unsigned long wm; | 649 | unsigned long wm; |
| 650 | 650 | ||
| 651 | latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3, | 651 | latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv), |
| 652 | dev_priv->fsb_freq, dev_priv->mem_freq); | 652 | dev_priv->is_ddr3, |
| 653 | dev_priv->fsb_freq, | ||
| 654 | dev_priv->mem_freq); | ||
| 653 | if (!latency) { | 655 | if (!latency) { |
| 654 | DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); | 656 | DRM_DEBUG_KMS("Unknown FSB/MEM found, disable CxSR\n"); |
| 655 | intel_set_memory_cxsr(dev_priv, false); | 657 | intel_set_memory_cxsr(dev_priv, false); |
| @@ -775,13 +777,13 @@ static bool g4x_check_srwm(struct drm_device *dev, | |||
| 775 | display_wm, cursor_wm); | 777 | display_wm, cursor_wm); |
| 776 | 778 | ||
| 777 | if (display_wm > display->max_wm) { | 779 | if (display_wm > display->max_wm) { |
| 778 | DRM_DEBUG_KMS("display watermark is too large(%d/%ld), disabling\n", | 780 | DRM_DEBUG_KMS("display watermark is too large(%d/%u), disabling\n", |
| 779 | display_wm, display->max_wm); | 781 | display_wm, display->max_wm); |
| 780 | return false; | 782 | return false; |
| 781 | } | 783 | } |
| 782 | 784 | ||
| 783 | if (cursor_wm > cursor->max_wm) { | 785 | if (cursor_wm > cursor->max_wm) { |
| 784 | DRM_DEBUG_KMS("cursor watermark is too large(%d/%ld), disabling\n", | 786 | DRM_DEBUG_KMS("cursor watermark is too large(%d/%u), disabling\n", |
| 785 | cursor_wm, cursor->max_wm); | 787 | cursor_wm, cursor->max_wm); |
| 786 | return false; | 788 | return false; |
| 787 | } | 789 | } |
| @@ -1528,7 +1530,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) | |||
| 1528 | 1530 | ||
| 1529 | if (IS_I945GM(dev)) | 1531 | if (IS_I945GM(dev)) |
| 1530 | wm_info = &i945_wm_info; | 1532 | wm_info = &i945_wm_info; |
| 1531 | else if (!IS_GEN2(dev)) | 1533 | else if (!IS_GEN2(dev_priv)) |
| 1532 | wm_info = &i915_wm_info; | 1534 | wm_info = &i915_wm_info; |
| 1533 | else | 1535 | else |
| 1534 | wm_info = &i830_a_wm_info; | 1536 | wm_info = &i830_a_wm_info; |
| @@ -1538,7 +1540,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) | |||
| 1538 | if (intel_crtc_active(crtc)) { | 1540 | if (intel_crtc_active(crtc)) { |
| 1539 | const struct drm_display_mode *adjusted_mode; | 1541 | const struct drm_display_mode *adjusted_mode; |
| 1540 | int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); | 1542 | int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); |
| 1541 | if (IS_GEN2(dev)) | 1543 | if (IS_GEN2(dev_priv)) |
| 1542 | cpp = 4; | 1544 | cpp = 4; |
| 1543 | 1545 | ||
| 1544 | adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; | 1546 | adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; |
| @@ -1552,7 +1554,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) | |||
| 1552 | planea_wm = wm_info->max_wm; | 1554 | planea_wm = wm_info->max_wm; |
| 1553 | } | 1555 | } |
| 1554 | 1556 | ||
| 1555 | if (IS_GEN2(dev)) | 1557 | if (IS_GEN2(dev_priv)) |
| 1556 | wm_info = &i830_bc_wm_info; | 1558 | wm_info = &i830_bc_wm_info; |
| 1557 | 1559 | ||
| 1558 | fifo_size = dev_priv->display.get_fifo_size(dev, 1); | 1560 | fifo_size = dev_priv->display.get_fifo_size(dev, 1); |
| @@ -1560,7 +1562,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) | |||
| 1560 | if (intel_crtc_active(crtc)) { | 1562 | if (intel_crtc_active(crtc)) { |
| 1561 | const struct drm_display_mode *adjusted_mode; | 1563 | const struct drm_display_mode *adjusted_mode; |
| 1562 | int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); | 1564 | int cpp = drm_format_plane_cpp(crtc->primary->state->fb->pixel_format, 0); |
| 1563 | if (IS_GEN2(dev)) | 1565 | if (IS_GEN2(dev_priv)) |
| 1564 | cpp = 4; | 1566 | cpp = 4; |
| 1565 | 1567 | ||
| 1566 | adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; | 1568 | adjusted_mode = &to_intel_crtc(crtc)->config->base.adjusted_mode; |
| @@ -1579,7 +1581,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) | |||
| 1579 | 1581 | ||
| 1580 | DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); | 1582 | DRM_DEBUG_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm); |
| 1581 | 1583 | ||
| 1582 | if (IS_I915GM(dev) && enabled) { | 1584 | if (IS_I915GM(dev_priv) && enabled) { |
| 1583 | struct drm_i915_gem_object *obj; | 1585 | struct drm_i915_gem_object *obj; |
| 1584 | 1586 | ||
| 1585 | obj = intel_fb_obj(enabled->primary->state->fb); | 1587 | obj = intel_fb_obj(enabled->primary->state->fb); |
| @@ -1609,7 +1611,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) | |||
| 1609 | unsigned long line_time_us; | 1611 | unsigned long line_time_us; |
| 1610 | int entries; | 1612 | int entries; |
| 1611 | 1613 | ||
| 1612 | if (IS_I915GM(dev) || IS_I945GM(dev)) | 1614 | if (IS_I915GM(dev_priv) || IS_I945GM(dev_priv)) |
| 1613 | cpp = 4; | 1615 | cpp = 4; |
| 1614 | 1616 | ||
| 1615 | line_time_us = max(htotal * 1000 / clock, 1); | 1617 | line_time_us = max(htotal * 1000 / clock, 1); |
| @@ -1623,7 +1625,7 @@ static void i9xx_update_wm(struct drm_crtc *unused_crtc) | |||
| 1623 | if (srwm < 0) | 1625 | if (srwm < 0) |
| 1624 | srwm = 1; | 1626 | srwm = 1; |
| 1625 | 1627 | ||
| 1626 | if (IS_I945G(dev) || IS_I945GM(dev)) | 1628 | if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) |
| 1627 | I915_WRITE(FW_BLC_SELF, | 1629 | I915_WRITE(FW_BLC_SELF, |
| 1628 | FW_BLC_SELF_FIFO_MASK | (srwm & 0xff)); | 1630 | FW_BLC_SELF_FIFO_MASK | (srwm & 0xff)); |
| 1629 | else | 1631 | else |
| @@ -2080,10 +2082,10 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8]) | |||
| 2080 | { | 2082 | { |
| 2081 | struct drm_i915_private *dev_priv = to_i915(dev); | 2083 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2082 | 2084 | ||
| 2083 | if (IS_GEN9(dev)) { | 2085 | if (IS_GEN9(dev_priv)) { |
| 2084 | uint32_t val; | 2086 | uint32_t val; |
| 2085 | int ret, i; | 2087 | int ret, i; |
| 2086 | int level, max_level = ilk_wm_max_level(dev); | 2088 | int level, max_level = ilk_wm_max_level(dev_priv); |
| 2087 | 2089 | ||
| 2088 | /* read the first set of memory latencies[0:3] */ | 2090 | /* read the first set of memory latencies[0:3] */ |
| 2089 | val = 0; /* data0 to be programmed to 0 for first set */ | 2091 | val = 0; /* data0 to be programmed to 0 for first set */ |
| @@ -2127,33 +2129,35 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8]) | |||
| 2127 | GEN9_MEM_LATENCY_LEVEL_MASK; | 2129 | GEN9_MEM_LATENCY_LEVEL_MASK; |
| 2128 | 2130 | ||
| 2129 | /* | 2131 | /* |
| 2132 | * If a level n (n > 1) has a 0us latency, all levels m (m >= n) | ||
| 2133 | * need to be disabled. We make sure to sanitize the values out | ||
| 2134 | * of the punit to satisfy this requirement. | ||
| 2135 | */ | ||
| 2136 | for (level = 1; level <= max_level; level++) { | ||
| 2137 | if (wm[level] == 0) { | ||
| 2138 | for (i = level + 1; i <= max_level; i++) | ||
| 2139 | wm[i] = 0; | ||
| 2140 | break; | ||
| 2141 | } | ||
| 2142 | } | ||
| 2143 | |||
| 2144 | /* | ||
| 2130 | * WaWmMemoryReadLatency:skl | 2145 | * WaWmMemoryReadLatency:skl |
| 2131 | * | 2146 | * |
| 2132 | * punit doesn't take into account the read latency so we need | 2147 | * punit doesn't take into account the read latency so we need |
| 2133 | * to add 2us to the various latency levels we retrieve from | 2148 | * to add 2us to the various latency levels we retrieve from the |
| 2134 | * the punit. | 2149 | * punit when level 0 response data us 0us. |
| 2135 | * - W0 is a bit special in that it's the only level that | ||
| 2136 | * can't be disabled if we want to have display working, so | ||
| 2137 | * we always add 2us there. | ||
| 2138 | * - For levels >=1, punit returns 0us latency when they are | ||
| 2139 | * disabled, so we respect that and don't add 2us then | ||
| 2140 | * | ||
| 2141 | * Additionally, if a level n (n > 1) has a 0us latency, all | ||
| 2142 | * levels m (m >= n) need to be disabled. We make sure to | ||
| 2143 | * sanitize the values out of the punit to satisfy this | ||
| 2144 | * requirement. | ||
| 2145 | */ | 2150 | */ |
| 2146 | wm[0] += 2; | 2151 | if (wm[0] == 0) { |
| 2147 | for (level = 1; level <= max_level; level++) | 2152 | wm[0] += 2; |
| 2148 | if (wm[level] != 0) | 2153 | for (level = 1; level <= max_level; level++) { |
| 2154 | if (wm[level] == 0) | ||
| 2155 | break; | ||
| 2149 | wm[level] += 2; | 2156 | wm[level] += 2; |
| 2150 | else { | ||
| 2151 | for (i = level + 1; i <= max_level; i++) | ||
| 2152 | wm[i] = 0; | ||
| 2153 | |||
| 2154 | break; | ||
| 2155 | } | 2157 | } |
| 2156 | } else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { | 2158 | } |
| 2159 | |||
| 2160 | } else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { | ||
| 2157 | uint64_t sskpd = I915_READ64(MCH_SSKPD); | 2161 | uint64_t sskpd = I915_READ64(MCH_SSKPD); |
| 2158 | 2162 | ||
| 2159 | wm[0] = (sskpd >> 56) & 0xFF; | 2163 | wm[0] = (sskpd >> 56) & 0xFF; |
| @@ -2180,42 +2184,44 @@ static void intel_read_wm_latency(struct drm_device *dev, uint16_t wm[8]) | |||
| 2180 | } | 2184 | } |
| 2181 | } | 2185 | } |
| 2182 | 2186 | ||
| 2183 | static void intel_fixup_spr_wm_latency(struct drm_device *dev, uint16_t wm[5]) | 2187 | static void intel_fixup_spr_wm_latency(struct drm_i915_private *dev_priv, |
| 2188 | uint16_t wm[5]) | ||
| 2184 | { | 2189 | { |
| 2185 | /* ILK sprite LP0 latency is 1300 ns */ | 2190 | /* ILK sprite LP0 latency is 1300 ns */ |
| 2186 | if (IS_GEN5(dev)) | 2191 | if (IS_GEN5(dev_priv)) |
| 2187 | wm[0] = 13; | 2192 | wm[0] = 13; |
| 2188 | } | 2193 | } |
| 2189 | 2194 | ||
| 2190 | static void intel_fixup_cur_wm_latency(struct drm_device *dev, uint16_t wm[5]) | 2195 | static void intel_fixup_cur_wm_latency(struct drm_i915_private *dev_priv, |
| 2196 | uint16_t wm[5]) | ||
| 2191 | { | 2197 | { |
| 2192 | /* ILK cursor LP0 latency is 1300 ns */ | 2198 | /* ILK cursor LP0 latency is 1300 ns */ |
| 2193 | if (IS_GEN5(dev)) | 2199 | if (IS_GEN5(dev_priv)) |
| 2194 | wm[0] = 13; | 2200 | wm[0] = 13; |
| 2195 | 2201 | ||
| 2196 | /* WaDoubleCursorLP3Latency:ivb */ | 2202 | /* WaDoubleCursorLP3Latency:ivb */ |
| 2197 | if (IS_IVYBRIDGE(dev)) | 2203 | if (IS_IVYBRIDGE(dev_priv)) |
| 2198 | wm[3] *= 2; | 2204 | wm[3] *= 2; |
| 2199 | } | 2205 | } |
| 2200 | 2206 | ||
| 2201 | int ilk_wm_max_level(const struct drm_device *dev) | 2207 | int ilk_wm_max_level(const struct drm_i915_private *dev_priv) |
| 2202 | { | 2208 | { |
| 2203 | /* how many WM levels are we expecting */ | 2209 | /* how many WM levels are we expecting */ |
| 2204 | if (INTEL_INFO(dev)->gen >= 9) | 2210 | if (INTEL_GEN(dev_priv) >= 9) |
| 2205 | return 7; | 2211 | return 7; |
| 2206 | else if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 2212 | else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 2207 | return 4; | 2213 | return 4; |
| 2208 | else if (INTEL_INFO(dev)->gen >= 6) | 2214 | else if (INTEL_GEN(dev_priv) >= 6) |
| 2209 | return 3; | 2215 | return 3; |
| 2210 | else | 2216 | else |
| 2211 | return 2; | 2217 | return 2; |
| 2212 | } | 2218 | } |
| 2213 | 2219 | ||
| 2214 | static void intel_print_wm_latency(struct drm_device *dev, | 2220 | static void intel_print_wm_latency(struct drm_i915_private *dev_priv, |
| 2215 | const char *name, | 2221 | const char *name, |
| 2216 | const uint16_t wm[8]) | 2222 | const uint16_t wm[8]) |
| 2217 | { | 2223 | { |
| 2218 | int level, max_level = ilk_wm_max_level(dev); | 2224 | int level, max_level = ilk_wm_max_level(dev_priv); |
| 2219 | 2225 | ||
| 2220 | for (level = 0; level <= max_level; level++) { | 2226 | for (level = 0; level <= max_level; level++) { |
| 2221 | unsigned int latency = wm[level]; | 2227 | unsigned int latency = wm[level]; |
| @@ -2230,7 +2236,7 @@ static void intel_print_wm_latency(struct drm_device *dev, | |||
| 2230 | * - latencies are in us on gen9. | 2236 | * - latencies are in us on gen9. |
| 2231 | * - before then, WM1+ latency values are in 0.5us units | 2237 | * - before then, WM1+ latency values are in 0.5us units |
| 2232 | */ | 2238 | */ |
| 2233 | if (IS_GEN9(dev)) | 2239 | if (IS_GEN9(dev_priv)) |
| 2234 | latency *= 10; | 2240 | latency *= 10; |
| 2235 | else if (level > 0) | 2241 | else if (level > 0) |
| 2236 | latency *= 5; | 2242 | latency *= 5; |
| @@ -2244,7 +2250,7 @@ static void intel_print_wm_latency(struct drm_device *dev, | |||
| 2244 | static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv, | 2250 | static bool ilk_increase_wm_latency(struct drm_i915_private *dev_priv, |
| 2245 | uint16_t wm[5], uint16_t min) | 2251 | uint16_t wm[5], uint16_t min) |
| 2246 | { | 2252 | { |
| 2247 | int level, max_level = ilk_wm_max_level(&dev_priv->drm); | 2253 | int level, max_level = ilk_wm_max_level(dev_priv); |
| 2248 | 2254 | ||
| 2249 | if (wm[0] >= min) | 2255 | if (wm[0] >= min) |
| 2250 | return false; | 2256 | return false; |
| @@ -2273,9 +2279,9 @@ static void snb_wm_latency_quirk(struct drm_device *dev) | |||
| 2273 | return; | 2279 | return; |
| 2274 | 2280 | ||
| 2275 | DRM_DEBUG_KMS("WM latency values increased to avoid potential underruns\n"); | 2281 | DRM_DEBUG_KMS("WM latency values increased to avoid potential underruns\n"); |
| 2276 | intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency); | 2282 | intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency); |
| 2277 | intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency); | 2283 | intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); |
| 2278 | intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency); | 2284 | intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); |
| 2279 | } | 2285 | } |
| 2280 | 2286 | ||
| 2281 | static void ilk_setup_wm_latency(struct drm_device *dev) | 2287 | static void ilk_setup_wm_latency(struct drm_device *dev) |
| @@ -2289,14 +2295,14 @@ static void ilk_setup_wm_latency(struct drm_device *dev) | |||
| 2289 | memcpy(dev_priv->wm.cur_latency, dev_priv->wm.pri_latency, | 2295 | memcpy(dev_priv->wm.cur_latency, dev_priv->wm.pri_latency, |
| 2290 | sizeof(dev_priv->wm.pri_latency)); | 2296 | sizeof(dev_priv->wm.pri_latency)); |
| 2291 | 2297 | ||
| 2292 | intel_fixup_spr_wm_latency(dev, dev_priv->wm.spr_latency); | 2298 | intel_fixup_spr_wm_latency(dev_priv, dev_priv->wm.spr_latency); |
| 2293 | intel_fixup_cur_wm_latency(dev, dev_priv->wm.cur_latency); | 2299 | intel_fixup_cur_wm_latency(dev_priv, dev_priv->wm.cur_latency); |
| 2294 | 2300 | ||
| 2295 | intel_print_wm_latency(dev, "Primary", dev_priv->wm.pri_latency); | 2301 | intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency); |
| 2296 | intel_print_wm_latency(dev, "Sprite", dev_priv->wm.spr_latency); | 2302 | intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); |
| 2297 | intel_print_wm_latency(dev, "Cursor", dev_priv->wm.cur_latency); | 2303 | intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); |
| 2298 | 2304 | ||
| 2299 | if (IS_GEN6(dev)) | 2305 | if (IS_GEN6(dev_priv)) |
| 2300 | snb_wm_latency_quirk(dev); | 2306 | snb_wm_latency_quirk(dev); |
| 2301 | } | 2307 | } |
| 2302 | 2308 | ||
| @@ -2305,7 +2311,7 @@ static void skl_setup_wm_latency(struct drm_device *dev) | |||
| 2305 | struct drm_i915_private *dev_priv = to_i915(dev); | 2311 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2306 | 2312 | ||
| 2307 | intel_read_wm_latency(dev, dev_priv->wm.skl_latency); | 2313 | intel_read_wm_latency(dev, dev_priv->wm.skl_latency); |
| 2308 | intel_print_wm_latency(dev, "Gen9 Plane", dev_priv->wm.skl_latency); | 2314 | intel_print_wm_latency(dev_priv, "Gen9 Plane", dev_priv->wm.skl_latency); |
| 2309 | } | 2315 | } |
| 2310 | 2316 | ||
| 2311 | static bool ilk_validate_pipe_wm(struct drm_device *dev, | 2317 | static bool ilk_validate_pipe_wm(struct drm_device *dev, |
| @@ -2343,7 +2349,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate) | |||
| 2343 | struct intel_plane_state *pristate = NULL; | 2349 | struct intel_plane_state *pristate = NULL; |
| 2344 | struct intel_plane_state *sprstate = NULL; | 2350 | struct intel_plane_state *sprstate = NULL; |
| 2345 | struct intel_plane_state *curstate = NULL; | 2351 | struct intel_plane_state *curstate = NULL; |
| 2346 | int level, max_level = ilk_wm_max_level(dev), usable_level; | 2352 | int level, max_level = ilk_wm_max_level(dev_priv), usable_level; |
| 2347 | struct ilk_wm_maximums max; | 2353 | struct ilk_wm_maximums max; |
| 2348 | 2354 | ||
| 2349 | pipe_wm = &cstate->wm.ilk.optimal; | 2355 | pipe_wm = &cstate->wm.ilk.optimal; |
| @@ -2388,7 +2394,7 @@ static int ilk_compute_pipe_wm(struct intel_crtc_state *cstate) | |||
| 2388 | memset(&pipe_wm->wm, 0, sizeof(pipe_wm->wm)); | 2394 | memset(&pipe_wm->wm, 0, sizeof(pipe_wm->wm)); |
| 2389 | pipe_wm->wm[0] = pipe_wm->raw_wm[0]; | 2395 | pipe_wm->wm[0] = pipe_wm->raw_wm[0]; |
| 2390 | 2396 | ||
| 2391 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 2397 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 2392 | pipe_wm->linetime = hsw_compute_linetime_wm(cstate); | 2398 | pipe_wm->linetime = hsw_compute_linetime_wm(cstate); |
| 2393 | 2399 | ||
| 2394 | if (!ilk_validate_pipe_wm(dev, pipe_wm)) | 2400 | if (!ilk_validate_pipe_wm(dev, pipe_wm)) |
| @@ -2430,7 +2436,7 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev, | |||
| 2430 | { | 2436 | { |
| 2431 | struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate; | 2437 | struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate; |
| 2432 | struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk; | 2438 | struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk; |
| 2433 | int level, max_level = ilk_wm_max_level(dev); | 2439 | int level, max_level = ilk_wm_max_level(to_i915(dev)); |
| 2434 | 2440 | ||
| 2435 | /* | 2441 | /* |
| 2436 | * Start with the final, target watermarks, then combine with the | 2442 | * Start with the final, target watermarks, then combine with the |
| @@ -2514,11 +2520,11 @@ static void ilk_wm_merge(struct drm_device *dev, | |||
| 2514 | struct intel_pipe_wm *merged) | 2520 | struct intel_pipe_wm *merged) |
| 2515 | { | 2521 | { |
| 2516 | struct drm_i915_private *dev_priv = to_i915(dev); | 2522 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2517 | int level, max_level = ilk_wm_max_level(dev); | 2523 | int level, max_level = ilk_wm_max_level(dev_priv); |
| 2518 | int last_enabled_level = max_level; | 2524 | int last_enabled_level = max_level; |
| 2519 | 2525 | ||
| 2520 | /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */ | 2526 | /* ILK/SNB/IVB: LP1+ watermarks only w/ single pipe */ |
| 2521 | if ((INTEL_INFO(dev)->gen <= 6 || IS_IVYBRIDGE(dev)) && | 2527 | if ((INTEL_GEN(dev_priv) <= 6 || IS_IVYBRIDGE(dev_priv)) && |
| 2522 | config->num_pipes_active > 1) | 2528 | config->num_pipes_active > 1) |
| 2523 | last_enabled_level = 0; | 2529 | last_enabled_level = 0; |
| 2524 | 2530 | ||
| @@ -2554,7 +2560,7 @@ static void ilk_wm_merge(struct drm_device *dev, | |||
| 2554 | * What we should check here is whether FBC can be | 2560 | * What we should check here is whether FBC can be |
| 2555 | * enabled sometime later. | 2561 | * enabled sometime later. |
| 2556 | */ | 2562 | */ |
| 2557 | if (IS_GEN5(dev) && !merged->fbc_wm_enabled && | 2563 | if (IS_GEN5(dev_priv) && !merged->fbc_wm_enabled && |
| 2558 | intel_fbc_is_active(dev_priv)) { | 2564 | intel_fbc_is_active(dev_priv)) { |
| 2559 | for (level = 2; level <= max_level; level++) { | 2565 | for (level = 2; level <= max_level; level++) { |
| 2560 | struct intel_wm_level *wm = &merged->wm[level]; | 2566 | struct intel_wm_level *wm = &merged->wm[level]; |
| @@ -2575,7 +2581,7 @@ static unsigned int ilk_wm_lp_latency(struct drm_device *dev, int level) | |||
| 2575 | { | 2581 | { |
| 2576 | struct drm_i915_private *dev_priv = to_i915(dev); | 2582 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2577 | 2583 | ||
| 2578 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 2584 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 2579 | return 2 * level; | 2585 | return 2 * level; |
| 2580 | else | 2586 | else |
| 2581 | return dev_priv->wm.pri_latency[level]; | 2587 | return dev_priv->wm.pri_latency[level]; |
| @@ -2654,7 +2660,7 @@ static struct intel_pipe_wm *ilk_find_best_result(struct drm_device *dev, | |||
| 2654 | struct intel_pipe_wm *r1, | 2660 | struct intel_pipe_wm *r1, |
| 2655 | struct intel_pipe_wm *r2) | 2661 | struct intel_pipe_wm *r2) |
| 2656 | { | 2662 | { |
| 2657 | int level, max_level = ilk_wm_max_level(dev); | 2663 | int level, max_level = ilk_wm_max_level(to_i915(dev)); |
| 2658 | int level1 = 0, level2 = 0; | 2664 | int level1 = 0, level2 = 0; |
| 2659 | 2665 | ||
| 2660 | for (level = 1; level <= max_level; level++) { | 2666 | for (level = 1; level <= max_level; level++) { |
| @@ -2799,7 +2805,7 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv, | |||
| 2799 | I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]); | 2805 | I915_WRITE(PIPE_WM_LINETIME(PIPE_C), results->wm_linetime[2]); |
| 2800 | 2806 | ||
| 2801 | if (dirty & WM_DIRTY_DDB) { | 2807 | if (dirty & WM_DIRTY_DDB) { |
| 2802 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) { | 2808 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { |
| 2803 | val = I915_READ(WM_MISC); | 2809 | val = I915_READ(WM_MISC); |
| 2804 | if (results->partitioning == INTEL_DDB_PART_1_2) | 2810 | if (results->partitioning == INTEL_DDB_PART_1_2) |
| 2805 | val &= ~WM_MISC_DATA_PARTITION_5_6; | 2811 | val &= ~WM_MISC_DATA_PARTITION_5_6; |
| @@ -2878,6 +2884,34 @@ skl_wm_plane_id(const struct intel_plane *plane) | |||
| 2878 | } | 2884 | } |
| 2879 | 2885 | ||
| 2880 | /* | 2886 | /* |
| 2887 | * FIXME: We still don't have the proper code detect if we need to apply the WA, | ||
| 2888 | * so assume we'll always need it in order to avoid underruns. | ||
| 2889 | */ | ||
| 2890 | static bool skl_needs_memory_bw_wa(struct intel_atomic_state *state) | ||
| 2891 | { | ||
| 2892 | struct drm_i915_private *dev_priv = to_i915(state->base.dev); | ||
| 2893 | |||
| 2894 | if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv) || | ||
| 2895 | IS_KABYLAKE(dev_priv)) | ||
| 2896 | return true; | ||
| 2897 | |||
| 2898 | return false; | ||
| 2899 | } | ||
| 2900 | |||
| 2901 | static bool | ||
| 2902 | intel_has_sagv(struct drm_i915_private *dev_priv) | ||
| 2903 | { | ||
| 2904 | if (IS_KABYLAKE(dev_priv)) | ||
| 2905 | return true; | ||
| 2906 | |||
| 2907 | if (IS_SKYLAKE(dev_priv) && | ||
| 2908 | dev_priv->sagv_status != I915_SAGV_NOT_CONTROLLED) | ||
| 2909 | return true; | ||
| 2910 | |||
| 2911 | return false; | ||
| 2912 | } | ||
| 2913 | |||
| 2914 | /* | ||
| 2881 | * SAGV dynamically adjusts the system agent voltage and clock frequencies | 2915 | * SAGV dynamically adjusts the system agent voltage and clock frequencies |
| 2882 | * depending on power and performance requirements. The display engine access | 2916 | * depending on power and performance requirements. The display engine access |
| 2883 | * to system memory is blocked during the adjustment time. Because of the | 2917 | * to system memory is blocked during the adjustment time. Because of the |
| @@ -2889,12 +2923,14 @@ skl_wm_plane_id(const struct intel_plane *plane) | |||
| 2889 | * - We're not using an interlaced display configuration | 2923 | * - We're not using an interlaced display configuration |
| 2890 | */ | 2924 | */ |
| 2891 | int | 2925 | int |
| 2892 | skl_enable_sagv(struct drm_i915_private *dev_priv) | 2926 | intel_enable_sagv(struct drm_i915_private *dev_priv) |
| 2893 | { | 2927 | { |
| 2894 | int ret; | 2928 | int ret; |
| 2895 | 2929 | ||
| 2896 | if (dev_priv->skl_sagv_status == I915_SKL_SAGV_NOT_CONTROLLED || | 2930 | if (!intel_has_sagv(dev_priv)) |
| 2897 | dev_priv->skl_sagv_status == I915_SKL_SAGV_ENABLED) | 2931 | return 0; |
| 2932 | |||
| 2933 | if (dev_priv->sagv_status == I915_SAGV_ENABLED) | ||
| 2898 | return 0; | 2934 | return 0; |
| 2899 | 2935 | ||
| 2900 | DRM_DEBUG_KMS("Enabling the SAGV\n"); | 2936 | DRM_DEBUG_KMS("Enabling the SAGV\n"); |
| @@ -2910,21 +2946,21 @@ skl_enable_sagv(struct drm_i915_private *dev_priv) | |||
| 2910 | * Some skl systems, pre-release machines in particular, | 2946 | * Some skl systems, pre-release machines in particular, |
| 2911 | * don't actually have an SAGV. | 2947 | * don't actually have an SAGV. |
| 2912 | */ | 2948 | */ |
| 2913 | if (ret == -ENXIO) { | 2949 | if (IS_SKYLAKE(dev_priv) && ret == -ENXIO) { |
| 2914 | DRM_DEBUG_DRIVER("No SAGV found on system, ignoring\n"); | 2950 | DRM_DEBUG_DRIVER("No SAGV found on system, ignoring\n"); |
| 2915 | dev_priv->skl_sagv_status = I915_SKL_SAGV_NOT_CONTROLLED; | 2951 | dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; |
| 2916 | return 0; | 2952 | return 0; |
| 2917 | } else if (ret < 0) { | 2953 | } else if (ret < 0) { |
| 2918 | DRM_ERROR("Failed to enable the SAGV\n"); | 2954 | DRM_ERROR("Failed to enable the SAGV\n"); |
| 2919 | return ret; | 2955 | return ret; |
| 2920 | } | 2956 | } |
| 2921 | 2957 | ||
| 2922 | dev_priv->skl_sagv_status = I915_SKL_SAGV_ENABLED; | 2958 | dev_priv->sagv_status = I915_SAGV_ENABLED; |
| 2923 | return 0; | 2959 | return 0; |
| 2924 | } | 2960 | } |
| 2925 | 2961 | ||
| 2926 | static int | 2962 | static int |
| 2927 | skl_do_sagv_disable(struct drm_i915_private *dev_priv) | 2963 | intel_do_sagv_disable(struct drm_i915_private *dev_priv) |
| 2928 | { | 2964 | { |
| 2929 | int ret; | 2965 | int ret; |
| 2930 | uint32_t temp = GEN9_SAGV_DISABLE; | 2966 | uint32_t temp = GEN9_SAGV_DISABLE; |
| @@ -2938,19 +2974,21 @@ skl_do_sagv_disable(struct drm_i915_private *dev_priv) | |||
| 2938 | } | 2974 | } |
| 2939 | 2975 | ||
| 2940 | int | 2976 | int |
| 2941 | skl_disable_sagv(struct drm_i915_private *dev_priv) | 2977 | intel_disable_sagv(struct drm_i915_private *dev_priv) |
| 2942 | { | 2978 | { |
| 2943 | int ret, result; | 2979 | int ret, result; |
| 2944 | 2980 | ||
| 2945 | if (dev_priv->skl_sagv_status == I915_SKL_SAGV_NOT_CONTROLLED || | 2981 | if (!intel_has_sagv(dev_priv)) |
| 2946 | dev_priv->skl_sagv_status == I915_SKL_SAGV_DISABLED) | 2982 | return 0; |
| 2983 | |||
| 2984 | if (dev_priv->sagv_status == I915_SAGV_DISABLED) | ||
| 2947 | return 0; | 2985 | return 0; |
| 2948 | 2986 | ||
| 2949 | DRM_DEBUG_KMS("Disabling the SAGV\n"); | 2987 | DRM_DEBUG_KMS("Disabling the SAGV\n"); |
| 2950 | mutex_lock(&dev_priv->rps.hw_lock); | 2988 | mutex_lock(&dev_priv->rps.hw_lock); |
| 2951 | 2989 | ||
| 2952 | /* bspec says to keep retrying for at least 1 ms */ | 2990 | /* bspec says to keep retrying for at least 1 ms */ |
| 2953 | ret = wait_for(result = skl_do_sagv_disable(dev_priv), 1); | 2991 | ret = wait_for(result = intel_do_sagv_disable(dev_priv), 1); |
| 2954 | mutex_unlock(&dev_priv->rps.hw_lock); | 2992 | mutex_unlock(&dev_priv->rps.hw_lock); |
| 2955 | 2993 | ||
| 2956 | if (ret == -ETIMEDOUT) { | 2994 | if (ret == -ETIMEDOUT) { |
| @@ -2962,27 +3000,33 @@ skl_disable_sagv(struct drm_i915_private *dev_priv) | |||
| 2962 | * Some skl systems, pre-release machines in particular, | 3000 | * Some skl systems, pre-release machines in particular, |
| 2963 | * don't actually have an SAGV. | 3001 | * don't actually have an SAGV. |
| 2964 | */ | 3002 | */ |
| 2965 | if (result == -ENXIO) { | 3003 | if (IS_SKYLAKE(dev_priv) && result == -ENXIO) { |
| 2966 | DRM_DEBUG_DRIVER("No SAGV found on system, ignoring\n"); | 3004 | DRM_DEBUG_DRIVER("No SAGV found on system, ignoring\n"); |
| 2967 | dev_priv->skl_sagv_status = I915_SKL_SAGV_NOT_CONTROLLED; | 3005 | dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; |
| 2968 | return 0; | 3006 | return 0; |
| 2969 | } else if (result < 0) { | 3007 | } else if (result < 0) { |
| 2970 | DRM_ERROR("Failed to disable the SAGV\n"); | 3008 | DRM_ERROR("Failed to disable the SAGV\n"); |
| 2971 | return result; | 3009 | return result; |
| 2972 | } | 3010 | } |
| 2973 | 3011 | ||
| 2974 | dev_priv->skl_sagv_status = I915_SKL_SAGV_DISABLED; | 3012 | dev_priv->sagv_status = I915_SAGV_DISABLED; |
| 2975 | return 0; | 3013 | return 0; |
| 2976 | } | 3014 | } |
| 2977 | 3015 | ||
| 2978 | bool skl_can_enable_sagv(struct drm_atomic_state *state) | 3016 | bool intel_can_enable_sagv(struct drm_atomic_state *state) |
| 2979 | { | 3017 | { |
| 2980 | struct drm_device *dev = state->dev; | 3018 | struct drm_device *dev = state->dev; |
| 2981 | struct drm_i915_private *dev_priv = to_i915(dev); | 3019 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 2982 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); | 3020 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); |
| 2983 | struct drm_crtc *crtc; | 3021 | struct intel_crtc *crtc; |
| 3022 | struct intel_plane *plane; | ||
| 3023 | struct intel_crtc_state *cstate; | ||
| 3024 | struct skl_plane_wm *wm; | ||
| 2984 | enum pipe pipe; | 3025 | enum pipe pipe; |
| 2985 | int level, plane; | 3026 | int level, latency; |
| 3027 | |||
| 3028 | if (!intel_has_sagv(dev_priv)) | ||
| 3029 | return false; | ||
| 2986 | 3030 | ||
| 2987 | /* | 3031 | /* |
| 2988 | * SKL workaround: bspec recommends we disable the SAGV when we have | 3032 | * SKL workaround: bspec recommends we disable the SAGV when we have |
| @@ -2997,27 +3041,37 @@ bool skl_can_enable_sagv(struct drm_atomic_state *state) | |||
| 2997 | 3041 | ||
| 2998 | /* Since we're now guaranteed to only have one active CRTC... */ | 3042 | /* Since we're now guaranteed to only have one active CRTC... */ |
| 2999 | pipe = ffs(intel_state->active_crtcs) - 1; | 3043 | pipe = ffs(intel_state->active_crtcs) - 1; |
| 3000 | crtc = dev_priv->pipe_to_crtc_mapping[pipe]; | 3044 | crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]); |
| 3045 | cstate = to_intel_crtc_state(crtc->base.state); | ||
| 3001 | 3046 | ||
| 3002 | if (crtc->state->mode.flags & DRM_MODE_FLAG_INTERLACE) | 3047 | if (crtc->base.state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) |
| 3003 | return false; | 3048 | return false; |
| 3004 | 3049 | ||
| 3005 | for_each_plane(dev_priv, pipe, plane) { | 3050 | for_each_intel_plane_on_crtc(dev, crtc, plane) { |
| 3051 | wm = &cstate->wm.skl.optimal.planes[skl_wm_plane_id(plane)]; | ||
| 3052 | |||
| 3006 | /* Skip this plane if it's not enabled */ | 3053 | /* Skip this plane if it's not enabled */ |
| 3007 | if (intel_state->wm_results.plane[pipe][plane][0] == 0) | 3054 | if (!wm->wm[0].plane_en) |
| 3008 | continue; | 3055 | continue; |
| 3009 | 3056 | ||
| 3010 | /* Find the highest enabled wm level for this plane */ | 3057 | /* Find the highest enabled wm level for this plane */ |
| 3011 | for (level = ilk_wm_max_level(dev); | 3058 | for (level = ilk_wm_max_level(dev_priv); |
| 3012 | intel_state->wm_results.plane[pipe][plane][level] == 0; --level) | 3059 | !wm->wm[level].plane_en; --level) |
| 3013 | { } | 3060 | { } |
| 3014 | 3061 | ||
| 3062 | latency = dev_priv->wm.skl_latency[level]; | ||
| 3063 | |||
| 3064 | if (skl_needs_memory_bw_wa(intel_state) && | ||
| 3065 | plane->base.state->fb->modifier[0] == | ||
| 3066 | I915_FORMAT_MOD_X_TILED) | ||
| 3067 | latency += 15; | ||
| 3068 | |||
| 3015 | /* | 3069 | /* |
| 3016 | * If any of the planes on this pipe don't enable wm levels | 3070 | * If any of the planes on this pipe don't enable wm levels |
| 3017 | * that incur memory latencies higher then 30µs we can't enable | 3071 | * that incur memory latencies higher then 30µs we can't enable |
| 3018 | * the SAGV | 3072 | * the SAGV |
| 3019 | */ | 3073 | */ |
| 3020 | if (dev_priv->wm.skl_latency[level] < SKL_SAGV_BLOCK_TIME) | 3074 | if (latency < SKL_SAGV_BLOCK_TIME) |
| 3021 | return false; | 3075 | return false; |
| 3022 | } | 3076 | } |
| 3023 | 3077 | ||
| @@ -3036,7 +3090,6 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, | |||
| 3036 | struct drm_crtc *for_crtc = cstate->base.crtc; | 3090 | struct drm_crtc *for_crtc = cstate->base.crtc; |
| 3037 | unsigned int pipe_size, ddb_size; | 3091 | unsigned int pipe_size, ddb_size; |
| 3038 | int nth_active_pipe; | 3092 | int nth_active_pipe; |
| 3039 | int pipe = to_intel_crtc(for_crtc)->pipe; | ||
| 3040 | 3093 | ||
| 3041 | if (WARN_ON(!state) || !cstate->base.active) { | 3094 | if (WARN_ON(!state) || !cstate->base.active) { |
| 3042 | alloc->start = 0; | 3095 | alloc->start = 0; |
| @@ -3064,7 +3117,7 @@ skl_ddb_get_pipe_allocation_limits(struct drm_device *dev, | |||
| 3064 | * we currently hold. | 3117 | * we currently hold. |
| 3065 | */ | 3118 | */ |
| 3066 | if (!intel_state->active_pipe_changes) { | 3119 | if (!intel_state->active_pipe_changes) { |
| 3067 | *alloc = dev_priv->wm.skl_hw.ddb.pipe[pipe]; | 3120 | *alloc = to_intel_crtc(for_crtc)->hw_ddb; |
| 3068 | return; | 3121 | return; |
| 3069 | } | 3122 | } |
| 3070 | 3123 | ||
| @@ -3332,7 +3385,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, | |||
| 3332 | struct drm_plane *plane; | 3385 | struct drm_plane *plane; |
| 3333 | struct drm_plane_state *pstate; | 3386 | struct drm_plane_state *pstate; |
| 3334 | enum pipe pipe = intel_crtc->pipe; | 3387 | enum pipe pipe = intel_crtc->pipe; |
| 3335 | struct skl_ddb_entry *alloc = &ddb->pipe[pipe]; | 3388 | struct skl_ddb_entry *alloc = &cstate->wm.skl.ddb; |
| 3336 | uint16_t alloc_size, start, cursor_blocks; | 3389 | uint16_t alloc_size, start, cursor_blocks; |
| 3337 | uint16_t *minimum = cstate->wm.skl.minimum_blocks; | 3390 | uint16_t *minimum = cstate->wm.skl.minimum_blocks; |
| 3338 | uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks; | 3391 | uint16_t *y_minimum = cstate->wm.skl.minimum_y_blocks; |
| @@ -3340,13 +3393,15 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, | |||
| 3340 | int num_active; | 3393 | int num_active; |
| 3341 | int id, i; | 3394 | int id, i; |
| 3342 | 3395 | ||
| 3396 | /* Clear the partitioning for disabled planes. */ | ||
| 3397 | memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); | ||
| 3398 | memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); | ||
| 3399 | |||
| 3343 | if (WARN_ON(!state)) | 3400 | if (WARN_ON(!state)) |
| 3344 | return 0; | 3401 | return 0; |
| 3345 | 3402 | ||
| 3346 | if (!cstate->base.active) { | 3403 | if (!cstate->base.active) { |
| 3347 | ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0; | 3404 | alloc->start = alloc->end = 0; |
| 3348 | memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); | ||
| 3349 | memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); | ||
| 3350 | return 0; | 3405 | return 0; |
| 3351 | } | 3406 | } |
| 3352 | 3407 | ||
| @@ -3446,12 +3501,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate, | |||
| 3446 | return 0; | 3501 | return 0; |
| 3447 | } | 3502 | } |
| 3448 | 3503 | ||
| 3449 | static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_state *config) | ||
| 3450 | { | ||
| 3451 | /* TODO: Take into account the scalers once we support them */ | ||
| 3452 | return config->base.adjusted_mode.crtc_clock; | ||
| 3453 | } | ||
| 3454 | |||
| 3455 | /* | 3504 | /* |
| 3456 | * The max latency should be 257 (max the punit can code is 255 and we add 2us | 3505 | * The max latency should be 257 (max the punit can code is 255 and we add 2us |
| 3457 | * for the read latency) and cpp should always be <= 8, so that | 3506 | * for the read latency) and cpp should always be <= 8, so that |
| @@ -3472,29 +3521,14 @@ static uint32_t skl_wm_method1(uint32_t pixel_rate, uint8_t cpp, uint32_t latenc | |||
| 3472 | } | 3521 | } |
| 3473 | 3522 | ||
| 3474 | static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, | 3523 | static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal, |
| 3475 | uint32_t horiz_pixels, uint8_t cpp, | 3524 | uint32_t latency, uint32_t plane_blocks_per_line) |
| 3476 | uint64_t tiling, uint32_t latency) | ||
| 3477 | { | 3525 | { |
| 3478 | uint32_t ret; | 3526 | uint32_t ret; |
| 3479 | uint32_t plane_bytes_per_line, plane_blocks_per_line; | ||
| 3480 | uint32_t wm_intermediate_val; | 3527 | uint32_t wm_intermediate_val; |
| 3481 | 3528 | ||
| 3482 | if (latency == 0) | 3529 | if (latency == 0) |
| 3483 | return UINT_MAX; | 3530 | return UINT_MAX; |
| 3484 | 3531 | ||
| 3485 | plane_bytes_per_line = horiz_pixels * cpp; | ||
| 3486 | |||
| 3487 | if (tiling == I915_FORMAT_MOD_Y_TILED || | ||
| 3488 | tiling == I915_FORMAT_MOD_Yf_TILED) { | ||
| 3489 | plane_bytes_per_line *= 4; | ||
| 3490 | plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); | ||
| 3491 | plane_blocks_per_line /= 4; | ||
| 3492 | } else if (tiling == DRM_FORMAT_MOD_NONE) { | ||
| 3493 | plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512) + 1; | ||
| 3494 | } else { | ||
| 3495 | plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); | ||
| 3496 | } | ||
| 3497 | |||
| 3498 | wm_intermediate_val = latency * pixel_rate; | 3532 | wm_intermediate_val = latency * pixel_rate; |
| 3499 | ret = DIV_ROUND_UP(wm_intermediate_val, pipe_htotal * 1000) * | 3533 | ret = DIV_ROUND_UP(wm_intermediate_val, pipe_htotal * 1000) * |
| 3500 | plane_blocks_per_line; | 3534 | plane_blocks_per_line; |
| @@ -3517,7 +3551,7 @@ static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cst | |||
| 3517 | * Adjusted plane pixel rate is just the pipe's adjusted pixel rate | 3551 | * Adjusted plane pixel rate is just the pipe's adjusted pixel rate |
| 3518 | * with additional adjustments for plane-specific scaling. | 3552 | * with additional adjustments for plane-specific scaling. |
| 3519 | */ | 3553 | */ |
| 3520 | adjusted_pixel_rate = skl_pipe_pixel_rate(cstate); | 3554 | adjusted_pixel_rate = ilk_pipe_pixel_rate(cstate); |
| 3521 | downscale_amount = skl_plane_downscale_amount(pstate); | 3555 | downscale_amount = skl_plane_downscale_amount(pstate); |
| 3522 | 3556 | ||
| 3523 | pixel_rate = adjusted_pixel_rate * downscale_amount >> 16; | 3557 | pixel_rate = adjusted_pixel_rate * downscale_amount >> 16; |
| @@ -3545,12 +3579,19 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
| 3545 | uint8_t cpp; | 3579 | uint8_t cpp; |
| 3546 | uint32_t width = 0, height = 0; | 3580 | uint32_t width = 0, height = 0; |
| 3547 | uint32_t plane_pixel_rate; | 3581 | uint32_t plane_pixel_rate; |
| 3582 | uint32_t y_tile_minimum, y_min_scanlines; | ||
| 3583 | struct intel_atomic_state *state = | ||
| 3584 | to_intel_atomic_state(cstate->base.state); | ||
| 3585 | bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state); | ||
| 3548 | 3586 | ||
| 3549 | if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) { | 3587 | if (latency == 0 || !cstate->base.active || !intel_pstate->base.visible) { |
| 3550 | *enabled = false; | 3588 | *enabled = false; |
| 3551 | return 0; | 3589 | return 0; |
| 3552 | } | 3590 | } |
| 3553 | 3591 | ||
| 3592 | if (apply_memory_bw_wa && fb->modifier[0] == I915_FORMAT_MOD_X_TILED) | ||
| 3593 | latency += 15; | ||
| 3594 | |||
| 3554 | width = drm_rect_width(&intel_pstate->base.src) >> 16; | 3595 | width = drm_rect_width(&intel_pstate->base.src) >> 16; |
| 3555 | height = drm_rect_height(&intel_pstate->base.src) >> 16; | 3596 | height = drm_rect_height(&intel_pstate->base.src) >> 16; |
| 3556 | 3597 | ||
| @@ -3560,41 +3601,60 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
| 3560 | cpp = drm_format_plane_cpp(fb->pixel_format, 0); | 3601 | cpp = drm_format_plane_cpp(fb->pixel_format, 0); |
| 3561 | plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); | 3602 | plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); |
| 3562 | 3603 | ||
| 3604 | if (drm_rotation_90_or_270(pstate->rotation)) { | ||
| 3605 | int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? | ||
| 3606 | drm_format_plane_cpp(fb->pixel_format, 1) : | ||
| 3607 | drm_format_plane_cpp(fb->pixel_format, 0); | ||
| 3608 | |||
| 3609 | switch (cpp) { | ||
| 3610 | case 1: | ||
| 3611 | y_min_scanlines = 16; | ||
| 3612 | break; | ||
| 3613 | case 2: | ||
| 3614 | y_min_scanlines = 8; | ||
| 3615 | break; | ||
| 3616 | case 4: | ||
| 3617 | y_min_scanlines = 4; | ||
| 3618 | break; | ||
| 3619 | default: | ||
| 3620 | MISSING_CASE(cpp); | ||
| 3621 | return -EINVAL; | ||
| 3622 | } | ||
| 3623 | } else { | ||
| 3624 | y_min_scanlines = 4; | ||
| 3625 | } | ||
| 3626 | |||
| 3627 | plane_bytes_per_line = width * cpp; | ||
| 3628 | if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || | ||
| 3629 | fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { | ||
| 3630 | plane_blocks_per_line = | ||
| 3631 | DIV_ROUND_UP(plane_bytes_per_line * y_min_scanlines, 512); | ||
| 3632 | plane_blocks_per_line /= y_min_scanlines; | ||
| 3633 | } else if (fb->modifier[0] == DRM_FORMAT_MOD_NONE) { | ||
| 3634 | plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512) | ||
| 3635 | + 1; | ||
| 3636 | } else { | ||
| 3637 | plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); | ||
| 3638 | } | ||
| 3639 | |||
| 3563 | method1 = skl_wm_method1(plane_pixel_rate, cpp, latency); | 3640 | method1 = skl_wm_method1(plane_pixel_rate, cpp, latency); |
| 3564 | method2 = skl_wm_method2(plane_pixel_rate, | 3641 | method2 = skl_wm_method2(plane_pixel_rate, |
| 3565 | cstate->base.adjusted_mode.crtc_htotal, | 3642 | cstate->base.adjusted_mode.crtc_htotal, |
| 3566 | width, | 3643 | latency, |
| 3567 | cpp, | 3644 | plane_blocks_per_line); |
| 3568 | fb->modifier[0], | ||
| 3569 | latency); | ||
| 3570 | 3645 | ||
| 3571 | plane_bytes_per_line = width * cpp; | 3646 | y_tile_minimum = plane_blocks_per_line * y_min_scanlines; |
| 3572 | plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512); | 3647 | if (apply_memory_bw_wa) |
| 3648 | y_tile_minimum *= 2; | ||
| 3573 | 3649 | ||
| 3574 | if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || | 3650 | if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || |
| 3575 | fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { | 3651 | fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { |
| 3576 | uint32_t min_scanlines = 4; | ||
| 3577 | uint32_t y_tile_minimum; | ||
| 3578 | if (drm_rotation_90_or_270(pstate->rotation)) { | ||
| 3579 | int cpp = (fb->pixel_format == DRM_FORMAT_NV12) ? | ||
| 3580 | drm_format_plane_cpp(fb->pixel_format, 1) : | ||
| 3581 | drm_format_plane_cpp(fb->pixel_format, 0); | ||
| 3582 | |||
| 3583 | switch (cpp) { | ||
| 3584 | case 1: | ||
| 3585 | min_scanlines = 16; | ||
| 3586 | break; | ||
| 3587 | case 2: | ||
| 3588 | min_scanlines = 8; | ||
| 3589 | break; | ||
| 3590 | case 8: | ||
| 3591 | WARN(1, "Unsupported pixel depth for rotation"); | ||
| 3592 | } | ||
| 3593 | } | ||
| 3594 | y_tile_minimum = plane_blocks_per_line * min_scanlines; | ||
| 3595 | selected_result = max(method2, y_tile_minimum); | 3652 | selected_result = max(method2, y_tile_minimum); |
| 3596 | } else { | 3653 | } else { |
| 3597 | if ((ddb_allocation / plane_blocks_per_line) >= 1) | 3654 | if ((cpp * cstate->base.adjusted_mode.crtc_htotal / 512 < 1) && |
| 3655 | (plane_bytes_per_line / 512 < 1)) | ||
| 3656 | selected_result = method2; | ||
| 3657 | else if ((ddb_allocation / plane_blocks_per_line) >= 1) | ||
| 3598 | selected_result = min(method1, method2); | 3658 | selected_result = min(method1, method2); |
| 3599 | else | 3659 | else |
| 3600 | selected_result = method1; | 3660 | selected_result = method1; |
| @@ -3605,10 +3665,12 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, | |||
| 3605 | 3665 | ||
| 3606 | if (level >= 1 && level <= 7) { | 3666 | if (level >= 1 && level <= 7) { |
| 3607 | if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || | 3667 | if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED || |
| 3608 | fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) | 3668 | fb->modifier[0] == I915_FORMAT_MOD_Yf_TILED) { |
| 3609 | res_lines += 4; | 3669 | res_blocks += y_tile_minimum; |
| 3610 | else | 3670 | res_lines += y_min_scanlines; |
| 3671 | } else { | ||
| 3611 | res_blocks++; | 3672 | res_blocks++; |
| 3673 | } | ||
| 3612 | } | 3674 | } |
| 3613 | 3675 | ||
| 3614 | if (res_blocks >= ddb_allocation || res_lines > 31) { | 3676 | if (res_blocks >= ddb_allocation || res_lines > 31) { |
| @@ -3642,67 +3704,52 @@ static int | |||
| 3642 | skl_compute_wm_level(const struct drm_i915_private *dev_priv, | 3704 | skl_compute_wm_level(const struct drm_i915_private *dev_priv, |
| 3643 | struct skl_ddb_allocation *ddb, | 3705 | struct skl_ddb_allocation *ddb, |
| 3644 | struct intel_crtc_state *cstate, | 3706 | struct intel_crtc_state *cstate, |
| 3707 | struct intel_plane *intel_plane, | ||
| 3645 | int level, | 3708 | int level, |
| 3646 | struct skl_wm_level *result) | 3709 | struct skl_wm_level *result) |
| 3647 | { | 3710 | { |
| 3648 | struct drm_atomic_state *state = cstate->base.state; | 3711 | struct drm_atomic_state *state = cstate->base.state; |
| 3649 | struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); | 3712 | struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); |
| 3650 | struct drm_plane *plane; | 3713 | struct drm_plane *plane = &intel_plane->base; |
| 3651 | struct intel_plane *intel_plane; | 3714 | struct intel_plane_state *intel_pstate = NULL; |
| 3652 | struct intel_plane_state *intel_pstate; | ||
| 3653 | uint16_t ddb_blocks; | 3715 | uint16_t ddb_blocks; |
| 3654 | enum pipe pipe = intel_crtc->pipe; | 3716 | enum pipe pipe = intel_crtc->pipe; |
| 3655 | int ret; | 3717 | int ret; |
| 3718 | int i = skl_wm_plane_id(intel_plane); | ||
| 3719 | |||
| 3720 | if (state) | ||
| 3721 | intel_pstate = | ||
| 3722 | intel_atomic_get_existing_plane_state(state, | ||
| 3723 | intel_plane); | ||
| 3656 | 3724 | ||
| 3657 | /* | 3725 | /* |
| 3658 | * We'll only calculate watermarks for planes that are actually | 3726 | * Note: If we start supporting multiple pending atomic commits against |
| 3659 | * enabled, so make sure all other planes are set as disabled. | 3727 | * the same planes/CRTC's in the future, plane->state will no longer be |
| 3728 | * the correct pre-state to use for the calculations here and we'll | ||
| 3729 | * need to change where we get the 'unchanged' plane data from. | ||
| 3730 | * | ||
| 3731 | * For now this is fine because we only allow one queued commit against | ||
| 3732 | * a CRTC. Even if the plane isn't modified by this transaction and we | ||
| 3733 | * don't have a plane lock, we still have the CRTC's lock, so we know | ||
| 3734 | * that no other transactions are racing with us to update it. | ||
| 3660 | */ | 3735 | */ |
| 3661 | memset(result, 0, sizeof(*result)); | 3736 | if (!intel_pstate) |
| 3737 | intel_pstate = to_intel_plane_state(plane->state); | ||
| 3662 | 3738 | ||
| 3663 | for_each_intel_plane_mask(&dev_priv->drm, | 3739 | WARN_ON(!intel_pstate->base.fb); |
| 3664 | intel_plane, | ||
| 3665 | cstate->base.plane_mask) { | ||
| 3666 | int i = skl_wm_plane_id(intel_plane); | ||
| 3667 | 3740 | ||
| 3668 | plane = &intel_plane->base; | 3741 | ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]); |
| 3669 | intel_pstate = NULL; | ||
| 3670 | if (state) | ||
| 3671 | intel_pstate = | ||
| 3672 | intel_atomic_get_existing_plane_state(state, | ||
| 3673 | intel_plane); | ||
| 3674 | 3742 | ||
| 3675 | /* | 3743 | ret = skl_compute_plane_wm(dev_priv, |
| 3676 | * Note: If we start supporting multiple pending atomic commits | 3744 | cstate, |
| 3677 | * against the same planes/CRTC's in the future, plane->state | 3745 | intel_pstate, |
| 3678 | * will no longer be the correct pre-state to use for the | 3746 | ddb_blocks, |
| 3679 | * calculations here and we'll need to change where we get the | 3747 | level, |
| 3680 | * 'unchanged' plane data from. | 3748 | &result->plane_res_b, |
| 3681 | * | 3749 | &result->plane_res_l, |
| 3682 | * For now this is fine because we only allow one queued commit | 3750 | &result->plane_en); |
| 3683 | * against a CRTC. Even if the plane isn't modified by this | 3751 | if (ret) |
| 3684 | * transaction and we don't have a plane lock, we still have | 3752 | return ret; |
| 3685 | * the CRTC's lock, so we know that no other transactions are | ||
| 3686 | * racing with us to update it. | ||
| 3687 | */ | ||
| 3688 | if (!intel_pstate) | ||
| 3689 | intel_pstate = to_intel_plane_state(plane->state); | ||
| 3690 | |||
| 3691 | WARN_ON(!intel_pstate->base.fb); | ||
| 3692 | |||
| 3693 | ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][i]); | ||
| 3694 | |||
| 3695 | ret = skl_compute_plane_wm(dev_priv, | ||
| 3696 | cstate, | ||
| 3697 | intel_pstate, | ||
| 3698 | ddb_blocks, | ||
| 3699 | level, | ||
| 3700 | &result->plane_res_b[i], | ||
| 3701 | &result->plane_res_l[i], | ||
| 3702 | &result->plane_en[i]); | ||
| 3703 | if (ret) | ||
| 3704 | return ret; | ||
| 3705 | } | ||
| 3706 | 3753 | ||
| 3707 | return 0; | 3754 | return 0; |
| 3708 | } | 3755 | } |
| @@ -3710,32 +3757,28 @@ skl_compute_wm_level(const struct drm_i915_private *dev_priv, | |||
| 3710 | static uint32_t | 3757 | static uint32_t |
| 3711 | skl_compute_linetime_wm(struct intel_crtc_state *cstate) | 3758 | skl_compute_linetime_wm(struct intel_crtc_state *cstate) |
| 3712 | { | 3759 | { |
| 3760 | uint32_t pixel_rate; | ||
| 3761 | |||
| 3713 | if (!cstate->base.active) | 3762 | if (!cstate->base.active) |
| 3714 | return 0; | 3763 | return 0; |
| 3715 | 3764 | ||
| 3716 | if (WARN_ON(skl_pipe_pixel_rate(cstate) == 0)) | 3765 | pixel_rate = ilk_pipe_pixel_rate(cstate); |
| 3766 | |||
| 3767 | if (WARN_ON(pixel_rate == 0)) | ||
| 3717 | return 0; | 3768 | return 0; |
| 3718 | 3769 | ||
| 3719 | return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000, | 3770 | return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000, |
| 3720 | skl_pipe_pixel_rate(cstate)); | 3771 | pixel_rate); |
| 3721 | } | 3772 | } |
| 3722 | 3773 | ||
| 3723 | static void skl_compute_transition_wm(struct intel_crtc_state *cstate, | 3774 | static void skl_compute_transition_wm(struct intel_crtc_state *cstate, |
| 3724 | struct skl_wm_level *trans_wm /* out */) | 3775 | struct skl_wm_level *trans_wm /* out */) |
| 3725 | { | 3776 | { |
| 3726 | struct drm_crtc *crtc = cstate->base.crtc; | ||
| 3727 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 3728 | struct intel_plane *intel_plane; | ||
| 3729 | |||
| 3730 | if (!cstate->base.active) | 3777 | if (!cstate->base.active) |
| 3731 | return; | 3778 | return; |
| 3732 | 3779 | ||
| 3733 | /* Until we know more, just disable transition WMs */ | 3780 | /* Until we know more, just disable transition WMs */ |
| 3734 | for_each_intel_plane_on_crtc(crtc->dev, intel_crtc, intel_plane) { | 3781 | trans_wm->plane_en = false; |
| 3735 | int i = skl_wm_plane_id(intel_plane); | ||
| 3736 | |||
| 3737 | trans_wm->plane_en[i] = false; | ||
| 3738 | } | ||
| 3739 | } | 3782 | } |
| 3740 | 3783 | ||
| 3741 | static int skl_build_pipe_wm(struct intel_crtc_state *cstate, | 3784 | static int skl_build_pipe_wm(struct intel_crtc_state *cstate, |
| @@ -3744,77 +3787,34 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, | |||
| 3744 | { | 3787 | { |
| 3745 | struct drm_device *dev = cstate->base.crtc->dev; | 3788 | struct drm_device *dev = cstate->base.crtc->dev; |
| 3746 | const struct drm_i915_private *dev_priv = to_i915(dev); | 3789 | const struct drm_i915_private *dev_priv = to_i915(dev); |
| 3747 | int level, max_level = ilk_wm_max_level(dev); | 3790 | struct intel_plane *intel_plane; |
| 3791 | struct skl_plane_wm *wm; | ||
| 3792 | int level, max_level = ilk_wm_max_level(dev_priv); | ||
| 3748 | int ret; | 3793 | int ret; |
| 3749 | 3794 | ||
| 3750 | for (level = 0; level <= max_level; level++) { | 3795 | /* |
| 3751 | ret = skl_compute_wm_level(dev_priv, ddb, cstate, | 3796 | * We'll only calculate watermarks for planes that are actually |
| 3752 | level, &pipe_wm->wm[level]); | 3797 | * enabled, so make sure all other planes are set as disabled. |
| 3753 | if (ret) | 3798 | */ |
| 3754 | return ret; | 3799 | memset(pipe_wm->planes, 0, sizeof(pipe_wm->planes)); |
| 3755 | } | ||
| 3756 | pipe_wm->linetime = skl_compute_linetime_wm(cstate); | ||
| 3757 | |||
| 3758 | skl_compute_transition_wm(cstate, &pipe_wm->trans_wm); | ||
| 3759 | |||
| 3760 | return 0; | ||
| 3761 | } | ||
| 3762 | |||
| 3763 | static void skl_compute_wm_results(struct drm_device *dev, | ||
| 3764 | struct skl_pipe_wm *p_wm, | ||
| 3765 | struct skl_wm_values *r, | ||
| 3766 | struct intel_crtc *intel_crtc) | ||
| 3767 | { | ||
| 3768 | int level, max_level = ilk_wm_max_level(dev); | ||
| 3769 | enum pipe pipe = intel_crtc->pipe; | ||
| 3770 | uint32_t temp; | ||
| 3771 | int i; | ||
| 3772 | |||
| 3773 | for (level = 0; level <= max_level; level++) { | ||
| 3774 | for (i = 0; i < intel_num_planes(intel_crtc); i++) { | ||
| 3775 | temp = 0; | ||
| 3776 | |||
| 3777 | temp |= p_wm->wm[level].plane_res_l[i] << | ||
| 3778 | PLANE_WM_LINES_SHIFT; | ||
| 3779 | temp |= p_wm->wm[level].plane_res_b[i]; | ||
| 3780 | if (p_wm->wm[level].plane_en[i]) | ||
| 3781 | temp |= PLANE_WM_EN; | ||
| 3782 | 3800 | ||
| 3783 | r->plane[pipe][i][level] = temp; | 3801 | for_each_intel_plane_mask(&dev_priv->drm, |
| 3802 | intel_plane, | ||
| 3803 | cstate->base.plane_mask) { | ||
| 3804 | wm = &pipe_wm->planes[skl_wm_plane_id(intel_plane)]; | ||
| 3805 | |||
| 3806 | for (level = 0; level <= max_level; level++) { | ||
| 3807 | ret = skl_compute_wm_level(dev_priv, ddb, cstate, | ||
| 3808 | intel_plane, level, | ||
| 3809 | &wm->wm[level]); | ||
| 3810 | if (ret) | ||
| 3811 | return ret; | ||
| 3784 | } | 3812 | } |
| 3785 | 3813 | skl_compute_transition_wm(cstate, &wm->trans_wm); | |
| 3786 | temp = 0; | ||
| 3787 | |||
| 3788 | temp |= p_wm->wm[level].plane_res_l[PLANE_CURSOR] << PLANE_WM_LINES_SHIFT; | ||
| 3789 | temp |= p_wm->wm[level].plane_res_b[PLANE_CURSOR]; | ||
| 3790 | |||
| 3791 | if (p_wm->wm[level].plane_en[PLANE_CURSOR]) | ||
| 3792 | temp |= PLANE_WM_EN; | ||
| 3793 | |||
| 3794 | r->plane[pipe][PLANE_CURSOR][level] = temp; | ||
| 3795 | |||
| 3796 | } | ||
| 3797 | |||
| 3798 | /* transition WMs */ | ||
| 3799 | for (i = 0; i < intel_num_planes(intel_crtc); i++) { | ||
| 3800 | temp = 0; | ||
| 3801 | temp |= p_wm->trans_wm.plane_res_l[i] << PLANE_WM_LINES_SHIFT; | ||
| 3802 | temp |= p_wm->trans_wm.plane_res_b[i]; | ||
| 3803 | if (p_wm->trans_wm.plane_en[i]) | ||
| 3804 | temp |= PLANE_WM_EN; | ||
| 3805 | |||
| 3806 | r->plane_trans[pipe][i] = temp; | ||
| 3807 | } | 3814 | } |
| 3815 | pipe_wm->linetime = skl_compute_linetime_wm(cstate); | ||
| 3808 | 3816 | ||
| 3809 | temp = 0; | 3817 | return 0; |
| 3810 | temp |= p_wm->trans_wm.plane_res_l[PLANE_CURSOR] << PLANE_WM_LINES_SHIFT; | ||
| 3811 | temp |= p_wm->trans_wm.plane_res_b[PLANE_CURSOR]; | ||
| 3812 | if (p_wm->trans_wm.plane_en[PLANE_CURSOR]) | ||
| 3813 | temp |= PLANE_WM_EN; | ||
| 3814 | |||
| 3815 | r->plane_trans[pipe][PLANE_CURSOR] = temp; | ||
| 3816 | |||
| 3817 | r->wm_linetime[pipe] = p_wm->linetime; | ||
| 3818 | } | 3818 | } |
| 3819 | 3819 | ||
| 3820 | static void skl_ddb_entry_write(struct drm_i915_private *dev_priv, | 3820 | static void skl_ddb_entry_write(struct drm_i915_private *dev_priv, |
| @@ -3827,53 +3827,77 @@ static void skl_ddb_entry_write(struct drm_i915_private *dev_priv, | |||
| 3827 | I915_WRITE(reg, 0); | 3827 | I915_WRITE(reg, 0); |
| 3828 | } | 3828 | } |
| 3829 | 3829 | ||
| 3830 | static void skl_write_wm_level(struct drm_i915_private *dev_priv, | ||
| 3831 | i915_reg_t reg, | ||
| 3832 | const struct skl_wm_level *level) | ||
| 3833 | { | ||
| 3834 | uint32_t val = 0; | ||
| 3835 | |||
| 3836 | if (level->plane_en) { | ||
| 3837 | val |= PLANE_WM_EN; | ||
| 3838 | val |= level->plane_res_b; | ||
| 3839 | val |= level->plane_res_l << PLANE_WM_LINES_SHIFT; | ||
| 3840 | } | ||
| 3841 | |||
| 3842 | I915_WRITE(reg, val); | ||
| 3843 | } | ||
| 3844 | |||
| 3830 | void skl_write_plane_wm(struct intel_crtc *intel_crtc, | 3845 | void skl_write_plane_wm(struct intel_crtc *intel_crtc, |
| 3831 | const struct skl_wm_values *wm, | 3846 | const struct skl_plane_wm *wm, |
| 3847 | const struct skl_ddb_allocation *ddb, | ||
| 3832 | int plane) | 3848 | int plane) |
| 3833 | { | 3849 | { |
| 3834 | struct drm_crtc *crtc = &intel_crtc->base; | 3850 | struct drm_crtc *crtc = &intel_crtc->base; |
| 3835 | struct drm_device *dev = crtc->dev; | 3851 | struct drm_device *dev = crtc->dev; |
| 3836 | struct drm_i915_private *dev_priv = to_i915(dev); | 3852 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 3837 | int level, max_level = ilk_wm_max_level(dev); | 3853 | int level, max_level = ilk_wm_max_level(dev_priv); |
| 3838 | enum pipe pipe = intel_crtc->pipe; | 3854 | enum pipe pipe = intel_crtc->pipe; |
| 3839 | 3855 | ||
| 3840 | for (level = 0; level <= max_level; level++) { | 3856 | for (level = 0; level <= max_level; level++) { |
| 3841 | I915_WRITE(PLANE_WM(pipe, plane, level), | 3857 | skl_write_wm_level(dev_priv, PLANE_WM(pipe, plane, level), |
| 3842 | wm->plane[pipe][plane][level]); | 3858 | &wm->wm[level]); |
| 3843 | } | 3859 | } |
| 3844 | I915_WRITE(PLANE_WM_TRANS(pipe, plane), wm->plane_trans[pipe][plane]); | 3860 | skl_write_wm_level(dev_priv, PLANE_WM_TRANS(pipe, plane), |
| 3861 | &wm->trans_wm); | ||
| 3845 | 3862 | ||
| 3846 | skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane), | 3863 | skl_ddb_entry_write(dev_priv, PLANE_BUF_CFG(pipe, plane), |
| 3847 | &wm->ddb.plane[pipe][plane]); | 3864 | &ddb->plane[pipe][plane]); |
| 3848 | skl_ddb_entry_write(dev_priv, PLANE_NV12_BUF_CFG(pipe, plane), | 3865 | skl_ddb_entry_write(dev_priv, PLANE_NV12_BUF_CFG(pipe, plane), |
| 3849 | &wm->ddb.y_plane[pipe][plane]); | 3866 | &ddb->y_plane[pipe][plane]); |
| 3850 | } | 3867 | } |
| 3851 | 3868 | ||
| 3852 | void skl_write_cursor_wm(struct intel_crtc *intel_crtc, | 3869 | void skl_write_cursor_wm(struct intel_crtc *intel_crtc, |
| 3853 | const struct skl_wm_values *wm) | 3870 | const struct skl_plane_wm *wm, |
| 3871 | const struct skl_ddb_allocation *ddb) | ||
| 3854 | { | 3872 | { |
| 3855 | struct drm_crtc *crtc = &intel_crtc->base; | 3873 | struct drm_crtc *crtc = &intel_crtc->base; |
| 3856 | struct drm_device *dev = crtc->dev; | 3874 | struct drm_device *dev = crtc->dev; |
| 3857 | struct drm_i915_private *dev_priv = to_i915(dev); | 3875 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 3858 | int level, max_level = ilk_wm_max_level(dev); | 3876 | int level, max_level = ilk_wm_max_level(dev_priv); |
| 3859 | enum pipe pipe = intel_crtc->pipe; | 3877 | enum pipe pipe = intel_crtc->pipe; |
| 3860 | 3878 | ||
| 3861 | for (level = 0; level <= max_level; level++) { | 3879 | for (level = 0; level <= max_level; level++) { |
| 3862 | I915_WRITE(CUR_WM(pipe, level), | 3880 | skl_write_wm_level(dev_priv, CUR_WM(pipe, level), |
| 3863 | wm->plane[pipe][PLANE_CURSOR][level]); | 3881 | &wm->wm[level]); |
| 3864 | } | 3882 | } |
| 3865 | I915_WRITE(CUR_WM_TRANS(pipe), wm->plane_trans[pipe][PLANE_CURSOR]); | 3883 | skl_write_wm_level(dev_priv, CUR_WM_TRANS(pipe), &wm->trans_wm); |
| 3866 | 3884 | ||
| 3867 | skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe), | 3885 | skl_ddb_entry_write(dev_priv, CUR_BUF_CFG(pipe), |
| 3868 | &wm->ddb.plane[pipe][PLANE_CURSOR]); | 3886 | &ddb->plane[pipe][PLANE_CURSOR]); |
| 3869 | } | 3887 | } |
| 3870 | 3888 | ||
| 3871 | bool skl_ddb_allocation_equals(const struct skl_ddb_allocation *old, | 3889 | bool skl_wm_level_equals(const struct skl_wm_level *l1, |
| 3872 | const struct skl_ddb_allocation *new, | 3890 | const struct skl_wm_level *l2) |
| 3873 | enum pipe pipe) | ||
| 3874 | { | 3891 | { |
| 3875 | return new->pipe[pipe].start == old->pipe[pipe].start && | 3892 | if (l1->plane_en != l2->plane_en) |
| 3876 | new->pipe[pipe].end == old->pipe[pipe].end; | 3893 | return false; |
| 3894 | |||
| 3895 | /* If both planes aren't enabled, the rest shouldn't matter */ | ||
| 3896 | if (!l1->plane_en) | ||
| 3897 | return true; | ||
| 3898 | |||
| 3899 | return (l1->plane_res_l == l2->plane_res_l && | ||
| 3900 | l1->plane_res_b == l2->plane_res_b); | ||
| 3877 | } | 3901 | } |
| 3878 | 3902 | ||
| 3879 | static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, | 3903 | static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, |
| @@ -3883,22 +3907,22 @@ static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, | |||
| 3883 | } | 3907 | } |
| 3884 | 3908 | ||
| 3885 | bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state, | 3909 | bool skl_ddb_allocation_overlaps(struct drm_atomic_state *state, |
| 3886 | const struct skl_ddb_allocation *old, | 3910 | struct intel_crtc *intel_crtc) |
| 3887 | const struct skl_ddb_allocation *new, | ||
| 3888 | enum pipe pipe) | ||
| 3889 | { | 3911 | { |
| 3890 | struct drm_device *dev = state->dev; | 3912 | struct drm_crtc *other_crtc; |
| 3891 | struct intel_crtc *intel_crtc; | 3913 | struct drm_crtc_state *other_cstate; |
| 3892 | enum pipe otherp; | 3914 | struct intel_crtc *other_intel_crtc; |
| 3915 | const struct skl_ddb_entry *ddb = | ||
| 3916 | &to_intel_crtc_state(intel_crtc->base.state)->wm.skl.ddb; | ||
| 3917 | int i; | ||
| 3893 | 3918 | ||
| 3894 | for_each_intel_crtc(dev, intel_crtc) { | 3919 | for_each_crtc_in_state(state, other_crtc, other_cstate, i) { |
| 3895 | otherp = intel_crtc->pipe; | 3920 | other_intel_crtc = to_intel_crtc(other_crtc); |
| 3896 | 3921 | ||
| 3897 | if (otherp == pipe) | 3922 | if (other_intel_crtc == intel_crtc) |
| 3898 | continue; | 3923 | continue; |
| 3899 | 3924 | ||
| 3900 | if (skl_ddb_entries_overlap(&new->pipe[pipe], | 3925 | if (skl_ddb_entries_overlap(ddb, &other_intel_crtc->hw_ddb)) |
| 3901 | &old->pipe[otherp])) | ||
| 3902 | return true; | 3926 | return true; |
| 3903 | } | 3927 | } |
| 3904 | 3928 | ||
| @@ -3940,6 +3964,41 @@ pipes_modified(struct drm_atomic_state *state) | |||
| 3940 | } | 3964 | } |
| 3941 | 3965 | ||
| 3942 | static int | 3966 | static int |
| 3967 | skl_ddb_add_affected_planes(struct intel_crtc_state *cstate) | ||
| 3968 | { | ||
| 3969 | struct drm_atomic_state *state = cstate->base.state; | ||
| 3970 | struct drm_device *dev = state->dev; | ||
| 3971 | struct drm_crtc *crtc = cstate->base.crtc; | ||
| 3972 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 3973 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 3974 | struct intel_atomic_state *intel_state = to_intel_atomic_state(state); | ||
| 3975 | struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb; | ||
| 3976 | struct skl_ddb_allocation *cur_ddb = &dev_priv->wm.skl_hw.ddb; | ||
| 3977 | struct drm_plane_state *plane_state; | ||
| 3978 | struct drm_plane *plane; | ||
| 3979 | enum pipe pipe = intel_crtc->pipe; | ||
| 3980 | int id; | ||
| 3981 | |||
| 3982 | WARN_ON(!drm_atomic_get_existing_crtc_state(state, crtc)); | ||
| 3983 | |||
| 3984 | drm_for_each_plane_mask(plane, dev, crtc->state->plane_mask) { | ||
| 3985 | id = skl_wm_plane_id(to_intel_plane(plane)); | ||
| 3986 | |||
| 3987 | if (skl_ddb_entry_equal(&cur_ddb->plane[pipe][id], | ||
| 3988 | &new_ddb->plane[pipe][id]) && | ||
| 3989 | skl_ddb_entry_equal(&cur_ddb->y_plane[pipe][id], | ||
| 3990 | &new_ddb->y_plane[pipe][id])) | ||
| 3991 | continue; | ||
| 3992 | |||
| 3993 | plane_state = drm_atomic_get_plane_state(state, plane); | ||
| 3994 | if (IS_ERR(plane_state)) | ||
| 3995 | return PTR_ERR(plane_state); | ||
| 3996 | } | ||
| 3997 | |||
| 3998 | return 0; | ||
| 3999 | } | ||
| 4000 | |||
| 4001 | static int | ||
| 3943 | skl_compute_ddb(struct drm_atomic_state *state) | 4002 | skl_compute_ddb(struct drm_atomic_state *state) |
| 3944 | { | 4003 | { |
| 3945 | struct drm_device *dev = state->dev; | 4004 | struct drm_device *dev = state->dev; |
| @@ -3992,6 +4051,12 @@ skl_compute_ddb(struct drm_atomic_state *state) | |||
| 3992 | intel_state->wm_results.dirty_pipes = ~0; | 4051 | intel_state->wm_results.dirty_pipes = ~0; |
| 3993 | } | 4052 | } |
| 3994 | 4053 | ||
| 4054 | /* | ||
| 4055 | * We're not recomputing for the pipes not included in the commit, so | ||
| 4056 | * make sure we start with the current state. | ||
| 4057 | */ | ||
| 4058 | memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb)); | ||
| 4059 | |||
| 3995 | for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { | 4060 | for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) { |
| 3996 | struct intel_crtc_state *cstate; | 4061 | struct intel_crtc_state *cstate; |
| 3997 | 4062 | ||
| @@ -4003,7 +4068,7 @@ skl_compute_ddb(struct drm_atomic_state *state) | |||
| 4003 | if (ret) | 4068 | if (ret) |
| 4004 | return ret; | 4069 | return ret; |
| 4005 | 4070 | ||
| 4006 | ret = drm_atomic_add_affected_planes(state, &intel_crtc->base); | 4071 | ret = skl_ddb_add_affected_planes(cstate); |
| 4007 | if (ret) | 4072 | if (ret) |
| 4008 | return ret; | 4073 | return ret; |
| 4009 | } | 4074 | } |
| @@ -4016,19 +4081,64 @@ skl_copy_wm_for_pipe(struct skl_wm_values *dst, | |||
| 4016 | struct skl_wm_values *src, | 4081 | struct skl_wm_values *src, |
| 4017 | enum pipe pipe) | 4082 | enum pipe pipe) |
| 4018 | { | 4083 | { |
| 4019 | dst->wm_linetime[pipe] = src->wm_linetime[pipe]; | ||
| 4020 | memcpy(dst->plane[pipe], src->plane[pipe], | ||
| 4021 | sizeof(dst->plane[pipe])); | ||
| 4022 | memcpy(dst->plane_trans[pipe], src->plane_trans[pipe], | ||
| 4023 | sizeof(dst->plane_trans[pipe])); | ||
| 4024 | |||
| 4025 | dst->ddb.pipe[pipe] = src->ddb.pipe[pipe]; | ||
| 4026 | memcpy(dst->ddb.y_plane[pipe], src->ddb.y_plane[pipe], | 4084 | memcpy(dst->ddb.y_plane[pipe], src->ddb.y_plane[pipe], |
| 4027 | sizeof(dst->ddb.y_plane[pipe])); | 4085 | sizeof(dst->ddb.y_plane[pipe])); |
| 4028 | memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], | 4086 | memcpy(dst->ddb.plane[pipe], src->ddb.plane[pipe], |
| 4029 | sizeof(dst->ddb.plane[pipe])); | 4087 | sizeof(dst->ddb.plane[pipe])); |
| 4030 | } | 4088 | } |
| 4031 | 4089 | ||
| 4090 | static void | ||
| 4091 | skl_print_wm_changes(const struct drm_atomic_state *state) | ||
| 4092 | { | ||
| 4093 | const struct drm_device *dev = state->dev; | ||
| 4094 | const struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 4095 | const struct intel_atomic_state *intel_state = | ||
| 4096 | to_intel_atomic_state(state); | ||
| 4097 | const struct drm_crtc *crtc; | ||
| 4098 | const struct drm_crtc_state *cstate; | ||
| 4099 | const struct drm_plane *plane; | ||
| 4100 | const struct intel_plane *intel_plane; | ||
| 4101 | const struct drm_plane_state *pstate; | ||
| 4102 | const struct skl_ddb_allocation *old_ddb = &dev_priv->wm.skl_hw.ddb; | ||
| 4103 | const struct skl_ddb_allocation *new_ddb = &intel_state->wm_results.ddb; | ||
| 4104 | enum pipe pipe; | ||
| 4105 | int id; | ||
| 4106 | int i, j; | ||
| 4107 | |||
| 4108 | for_each_crtc_in_state(state, crtc, cstate, i) { | ||
| 4109 | pipe = to_intel_crtc(crtc)->pipe; | ||
| 4110 | |||
| 4111 | for_each_plane_in_state(state, plane, pstate, j) { | ||
| 4112 | const struct skl_ddb_entry *old, *new; | ||
| 4113 | |||
| 4114 | intel_plane = to_intel_plane(plane); | ||
| 4115 | id = skl_wm_plane_id(intel_plane); | ||
| 4116 | old = &old_ddb->plane[pipe][id]; | ||
| 4117 | new = &new_ddb->plane[pipe][id]; | ||
| 4118 | |||
| 4119 | if (intel_plane->pipe != pipe) | ||
| 4120 | continue; | ||
| 4121 | |||
| 4122 | if (skl_ddb_entry_equal(old, new)) | ||
| 4123 | continue; | ||
| 4124 | |||
| 4125 | if (id != PLANE_CURSOR) { | ||
| 4126 | DRM_DEBUG_ATOMIC("[PLANE:%d:plane %d%c] ddb (%d - %d) -> (%d - %d)\n", | ||
| 4127 | plane->base.id, id + 1, | ||
| 4128 | pipe_name(pipe), | ||
| 4129 | old->start, old->end, | ||
| 4130 | new->start, new->end); | ||
| 4131 | } else { | ||
| 4132 | DRM_DEBUG_ATOMIC("[PLANE:%d:cursor %c] ddb (%d - %d) -> (%d - %d)\n", | ||
| 4133 | plane->base.id, | ||
| 4134 | pipe_name(pipe), | ||
| 4135 | old->start, old->end, | ||
| 4136 | new->start, new->end); | ||
| 4137 | } | ||
| 4138 | } | ||
| 4139 | } | ||
| 4140 | } | ||
| 4141 | |||
| 4032 | static int | 4142 | static int |
| 4033 | skl_compute_wm(struct drm_atomic_state *state) | 4143 | skl_compute_wm(struct drm_atomic_state *state) |
| 4034 | { | 4144 | { |
| @@ -4071,7 +4181,6 @@ skl_compute_wm(struct drm_atomic_state *state) | |||
| 4071 | * no suitable watermark values can be found. | 4181 | * no suitable watermark values can be found. |
| 4072 | */ | 4182 | */ |
| 4073 | for_each_crtc_in_state(state, crtc, cstate, i) { | 4183 | for_each_crtc_in_state(state, crtc, cstate, i) { |
| 4074 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | ||
| 4075 | struct intel_crtc_state *intel_cstate = | 4184 | struct intel_crtc_state *intel_cstate = |
| 4076 | to_intel_crtc_state(cstate); | 4185 | to_intel_crtc_state(cstate); |
| 4077 | 4186 | ||
| @@ -4089,9 +4198,10 @@ skl_compute_wm(struct drm_atomic_state *state) | |||
| 4089 | continue; | 4198 | continue; |
| 4090 | 4199 | ||
| 4091 | intel_cstate->update_wm_pre = true; | 4200 | intel_cstate->update_wm_pre = true; |
| 4092 | skl_compute_wm_results(crtc->dev, pipe_wm, results, intel_crtc); | ||
| 4093 | } | 4201 | } |
| 4094 | 4202 | ||
| 4203 | skl_print_wm_changes(state); | ||
| 4204 | |||
| 4095 | return 0; | 4205 | return 0; |
| 4096 | } | 4206 | } |
| 4097 | 4207 | ||
| @@ -4123,13 +4233,17 @@ static void skl_update_wm(struct drm_crtc *crtc) | |||
| 4123 | int plane; | 4233 | int plane; |
| 4124 | 4234 | ||
| 4125 | for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) | 4235 | for (plane = 0; plane < intel_num_planes(intel_crtc); plane++) |
| 4126 | skl_write_plane_wm(intel_crtc, results, plane); | 4236 | skl_write_plane_wm(intel_crtc, &pipe_wm->planes[plane], |
| 4237 | &results->ddb, plane); | ||
| 4127 | 4238 | ||
| 4128 | skl_write_cursor_wm(intel_crtc, results); | 4239 | skl_write_cursor_wm(intel_crtc, &pipe_wm->planes[PLANE_CURSOR], |
| 4240 | &results->ddb); | ||
| 4129 | } | 4241 | } |
| 4130 | 4242 | ||
| 4131 | skl_copy_wm_for_pipe(hw_vals, results, pipe); | 4243 | skl_copy_wm_for_pipe(hw_vals, results, pipe); |
| 4132 | 4244 | ||
| 4245 | intel_crtc->hw_ddb = cstate->wm.skl.ddb; | ||
| 4246 | |||
| 4133 | mutex_unlock(&dev_priv->wm.wm_mutex); | 4247 | mutex_unlock(&dev_priv->wm.wm_mutex); |
| 4134 | } | 4248 | } |
| 4135 | 4249 | ||
| @@ -4208,114 +4322,77 @@ static void ilk_optimize_watermarks(struct intel_crtc_state *cstate) | |||
| 4208 | mutex_unlock(&dev_priv->wm.wm_mutex); | 4322 | mutex_unlock(&dev_priv->wm.wm_mutex); |
| 4209 | } | 4323 | } |
| 4210 | 4324 | ||
| 4211 | static void skl_pipe_wm_active_state(uint32_t val, | 4325 | static inline void skl_wm_level_from_reg_val(uint32_t val, |
| 4212 | struct skl_pipe_wm *active, | 4326 | struct skl_wm_level *level) |
| 4213 | bool is_transwm, | ||
| 4214 | bool is_cursor, | ||
| 4215 | int i, | ||
| 4216 | int level) | ||
| 4217 | { | 4327 | { |
| 4218 | bool is_enabled = (val & PLANE_WM_EN) != 0; | 4328 | level->plane_en = val & PLANE_WM_EN; |
| 4219 | 4329 | level->plane_res_b = val & PLANE_WM_BLOCKS_MASK; | |
| 4220 | if (!is_transwm) { | 4330 | level->plane_res_l = (val >> PLANE_WM_LINES_SHIFT) & |
| 4221 | if (!is_cursor) { | 4331 | PLANE_WM_LINES_MASK; |
| 4222 | active->wm[level].plane_en[i] = is_enabled; | ||
| 4223 | active->wm[level].plane_res_b[i] = | ||
| 4224 | val & PLANE_WM_BLOCKS_MASK; | ||
| 4225 | active->wm[level].plane_res_l[i] = | ||
| 4226 | (val >> PLANE_WM_LINES_SHIFT) & | ||
| 4227 | PLANE_WM_LINES_MASK; | ||
| 4228 | } else { | ||
| 4229 | active->wm[level].plane_en[PLANE_CURSOR] = is_enabled; | ||
| 4230 | active->wm[level].plane_res_b[PLANE_CURSOR] = | ||
| 4231 | val & PLANE_WM_BLOCKS_MASK; | ||
| 4232 | active->wm[level].plane_res_l[PLANE_CURSOR] = | ||
| 4233 | (val >> PLANE_WM_LINES_SHIFT) & | ||
| 4234 | PLANE_WM_LINES_MASK; | ||
| 4235 | } | ||
| 4236 | } else { | ||
| 4237 | if (!is_cursor) { | ||
| 4238 | active->trans_wm.plane_en[i] = is_enabled; | ||
| 4239 | active->trans_wm.plane_res_b[i] = | ||
| 4240 | val & PLANE_WM_BLOCKS_MASK; | ||
| 4241 | active->trans_wm.plane_res_l[i] = | ||
| 4242 | (val >> PLANE_WM_LINES_SHIFT) & | ||
| 4243 | PLANE_WM_LINES_MASK; | ||
| 4244 | } else { | ||
| 4245 | active->trans_wm.plane_en[PLANE_CURSOR] = is_enabled; | ||
| 4246 | active->trans_wm.plane_res_b[PLANE_CURSOR] = | ||
| 4247 | val & PLANE_WM_BLOCKS_MASK; | ||
| 4248 | active->trans_wm.plane_res_l[PLANE_CURSOR] = | ||
| 4249 | (val >> PLANE_WM_LINES_SHIFT) & | ||
| 4250 | PLANE_WM_LINES_MASK; | ||
| 4251 | } | ||
| 4252 | } | ||
| 4253 | } | 4332 | } |
| 4254 | 4333 | ||
| 4255 | static void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc) | 4334 | void skl_pipe_wm_get_hw_state(struct drm_crtc *crtc, |
| 4335 | struct skl_pipe_wm *out) | ||
| 4256 | { | 4336 | { |
| 4257 | struct drm_device *dev = crtc->dev; | 4337 | struct drm_device *dev = crtc->dev; |
| 4258 | struct drm_i915_private *dev_priv = to_i915(dev); | 4338 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 4259 | struct skl_wm_values *hw = &dev_priv->wm.skl_hw; | ||
| 4260 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 4339 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 4261 | struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); | 4340 | struct intel_plane *intel_plane; |
| 4262 | struct skl_pipe_wm *active = &cstate->wm.skl.optimal; | 4341 | struct skl_plane_wm *wm; |
| 4263 | enum pipe pipe = intel_crtc->pipe; | 4342 | enum pipe pipe = intel_crtc->pipe; |
| 4264 | int level, i, max_level; | 4343 | int level, id, max_level; |
| 4265 | uint32_t temp; | 4344 | uint32_t val; |
| 4266 | |||
| 4267 | max_level = ilk_wm_max_level(dev); | ||
| 4268 | |||
| 4269 | hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); | ||
| 4270 | |||
| 4271 | for (level = 0; level <= max_level; level++) { | ||
| 4272 | for (i = 0; i < intel_num_planes(intel_crtc); i++) | ||
| 4273 | hw->plane[pipe][i][level] = | ||
| 4274 | I915_READ(PLANE_WM(pipe, i, level)); | ||
| 4275 | hw->plane[pipe][PLANE_CURSOR][level] = I915_READ(CUR_WM(pipe, level)); | ||
| 4276 | } | ||
| 4277 | |||
| 4278 | for (i = 0; i < intel_num_planes(intel_crtc); i++) | ||
| 4279 | hw->plane_trans[pipe][i] = I915_READ(PLANE_WM_TRANS(pipe, i)); | ||
| 4280 | hw->plane_trans[pipe][PLANE_CURSOR] = I915_READ(CUR_WM_TRANS(pipe)); | ||
| 4281 | 4345 | ||
| 4282 | if (!intel_crtc->active) | 4346 | max_level = ilk_wm_max_level(dev_priv); |
| 4283 | return; | ||
| 4284 | 4347 | ||
| 4285 | hw->dirty_pipes |= drm_crtc_mask(crtc); | 4348 | for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) { |
| 4349 | id = skl_wm_plane_id(intel_plane); | ||
| 4350 | wm = &out->planes[id]; | ||
| 4286 | 4351 | ||
| 4287 | active->linetime = hw->wm_linetime[pipe]; | 4352 | for (level = 0; level <= max_level; level++) { |
| 4353 | if (id != PLANE_CURSOR) | ||
| 4354 | val = I915_READ(PLANE_WM(pipe, id, level)); | ||
| 4355 | else | ||
| 4356 | val = I915_READ(CUR_WM(pipe, level)); | ||
| 4288 | 4357 | ||
| 4289 | for (level = 0; level <= max_level; level++) { | 4358 | skl_wm_level_from_reg_val(val, &wm->wm[level]); |
| 4290 | for (i = 0; i < intel_num_planes(intel_crtc); i++) { | ||
| 4291 | temp = hw->plane[pipe][i][level]; | ||
| 4292 | skl_pipe_wm_active_state(temp, active, false, | ||
| 4293 | false, i, level); | ||
| 4294 | } | 4359 | } |
| 4295 | temp = hw->plane[pipe][PLANE_CURSOR][level]; | ||
| 4296 | skl_pipe_wm_active_state(temp, active, false, true, i, level); | ||
| 4297 | } | ||
| 4298 | 4360 | ||
| 4299 | for (i = 0; i < intel_num_planes(intel_crtc); i++) { | 4361 | if (id != PLANE_CURSOR) |
| 4300 | temp = hw->plane_trans[pipe][i]; | 4362 | val = I915_READ(PLANE_WM_TRANS(pipe, id)); |
| 4301 | skl_pipe_wm_active_state(temp, active, true, false, i, 0); | 4363 | else |
| 4364 | val = I915_READ(CUR_WM_TRANS(pipe)); | ||
| 4365 | |||
| 4366 | skl_wm_level_from_reg_val(val, &wm->trans_wm); | ||
| 4302 | } | 4367 | } |
| 4303 | 4368 | ||
| 4304 | temp = hw->plane_trans[pipe][PLANE_CURSOR]; | 4369 | if (!intel_crtc->active) |
| 4305 | skl_pipe_wm_active_state(temp, active, true, true, i, 0); | 4370 | return; |
| 4306 | 4371 | ||
| 4307 | intel_crtc->wm.active.skl = *active; | 4372 | out->linetime = I915_READ(PIPE_WM_LINETIME(pipe)); |
| 4308 | } | 4373 | } |
| 4309 | 4374 | ||
| 4310 | void skl_wm_get_hw_state(struct drm_device *dev) | 4375 | void skl_wm_get_hw_state(struct drm_device *dev) |
| 4311 | { | 4376 | { |
| 4312 | struct drm_i915_private *dev_priv = to_i915(dev); | 4377 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 4378 | struct skl_wm_values *hw = &dev_priv->wm.skl_hw; | ||
| 4313 | struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb; | 4379 | struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb; |
| 4314 | struct drm_crtc *crtc; | 4380 | struct drm_crtc *crtc; |
| 4381 | struct intel_crtc *intel_crtc; | ||
| 4382 | struct intel_crtc_state *cstate; | ||
| 4315 | 4383 | ||
| 4316 | skl_ddb_get_hw_state(dev_priv, ddb); | 4384 | skl_ddb_get_hw_state(dev_priv, ddb); |
| 4317 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | 4385 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
| 4318 | skl_pipe_wm_get_hw_state(crtc); | 4386 | intel_crtc = to_intel_crtc(crtc); |
| 4387 | cstate = to_intel_crtc_state(crtc->state); | ||
| 4388 | |||
| 4389 | skl_pipe_wm_get_hw_state(crtc, &cstate->wm.skl.optimal); | ||
| 4390 | |||
| 4391 | if (intel_crtc->active) { | ||
| 4392 | hw->dirty_pipes |= drm_crtc_mask(crtc); | ||
| 4393 | intel_crtc->wm.active.skl = cstate->wm.skl.optimal; | ||
| 4394 | } | ||
| 4395 | } | ||
| 4319 | 4396 | ||
| 4320 | if (dev_priv->active_crtcs) { | 4397 | if (dev_priv->active_crtcs) { |
| 4321 | /* Fully recompute DDB on first atomic commit */ | 4398 | /* Fully recompute DDB on first atomic commit */ |
| @@ -4342,7 +4419,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) | |||
| 4342 | }; | 4419 | }; |
| 4343 | 4420 | ||
| 4344 | hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]); | 4421 | hw->wm_pipe[pipe] = I915_READ(wm0_pipe_reg[pipe]); |
| 4345 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 4422 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 4346 | hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); | 4423 | hw->wm_linetime[pipe] = I915_READ(PIPE_WM_LINETIME(pipe)); |
| 4347 | 4424 | ||
| 4348 | memset(active, 0, sizeof(*active)); | 4425 | memset(active, 0, sizeof(*active)); |
| @@ -4364,7 +4441,7 @@ static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc) | |||
| 4364 | active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK; | 4441 | active->wm[0].cur_val = tmp & WM0_PIPE_CURSOR_MASK; |
| 4365 | active->linetime = hw->wm_linetime[pipe]; | 4442 | active->linetime = hw->wm_linetime[pipe]; |
| 4366 | } else { | 4443 | } else { |
| 4367 | int level, max_level = ilk_wm_max_level(dev); | 4444 | int level, max_level = ilk_wm_max_level(dev_priv); |
| 4368 | 4445 | ||
| 4369 | /* | 4446 | /* |
| 4370 | * For inactive pipes, all watermark levels | 4447 | * For inactive pipes, all watermark levels |
| @@ -4550,10 +4627,10 @@ void ilk_wm_get_hw_state(struct drm_device *dev) | |||
| 4550 | hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB); | 4627 | hw->wm_lp_spr[2] = I915_READ(WM3S_LP_IVB); |
| 4551 | } | 4628 | } |
| 4552 | 4629 | ||
| 4553 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 4630 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 4554 | hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? | 4631 | hw->partitioning = (I915_READ(WM_MISC) & WM_MISC_DATA_PARTITION_5_6) ? |
| 4555 | INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; | 4632 | INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; |
| 4556 | else if (IS_IVYBRIDGE(dev)) | 4633 | else if (IS_IVYBRIDGE(dev_priv)) |
| 4557 | hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ? | 4634 | hw->partitioning = (I915_READ(DISP_ARB_CTL2) & DISP_DATA_PARTITION_5_6) ? |
| 4558 | INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; | 4635 | INTEL_DDB_PART_5_6 : INTEL_DDB_PART_1_2; |
| 4559 | 4636 | ||
| @@ -5297,6 +5374,7 @@ static void gen9_enable_rps(struct drm_i915_private *dev_priv) | |||
| 5297 | static void gen9_enable_rc6(struct drm_i915_private *dev_priv) | 5374 | static void gen9_enable_rc6(struct drm_i915_private *dev_priv) |
| 5298 | { | 5375 | { |
| 5299 | struct intel_engine_cs *engine; | 5376 | struct intel_engine_cs *engine; |
| 5377 | enum intel_engine_id id; | ||
| 5300 | uint32_t rc6_mask = 0; | 5378 | uint32_t rc6_mask = 0; |
| 5301 | 5379 | ||
| 5302 | /* 1a: Software RC state - RC0 */ | 5380 | /* 1a: Software RC state - RC0 */ |
| @@ -5318,7 +5396,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) | |||
| 5318 | I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16); | 5396 | I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 54 << 16); |
| 5319 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ | 5397 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ |
| 5320 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ | 5398 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ |
| 5321 | for_each_engine(engine, dev_priv) | 5399 | for_each_engine(engine, dev_priv, id) |
| 5322 | I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); | 5400 | I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); |
| 5323 | 5401 | ||
| 5324 | if (HAS_GUC(dev_priv)) | 5402 | if (HAS_GUC(dev_priv)) |
| @@ -5334,9 +5412,8 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) | |||
| 5334 | if (intel_enable_rc6() & INTEL_RC6_ENABLE) | 5412 | if (intel_enable_rc6() & INTEL_RC6_ENABLE) |
| 5335 | rc6_mask = GEN6_RC_CTL_RC6_ENABLE; | 5413 | rc6_mask = GEN6_RC_CTL_RC6_ENABLE; |
| 5336 | DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE)); | 5414 | DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE)); |
| 5337 | /* WaRsUseTimeoutMode */ | 5415 | /* WaRsUseTimeoutMode:bxt */ |
| 5338 | if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_D0) || | 5416 | if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { |
| 5339 | IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { | ||
| 5340 | I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us */ | 5417 | I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us */ |
| 5341 | I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | | 5418 | I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | |
| 5342 | GEN7_RC_CTL_TO_MODE | | 5419 | GEN7_RC_CTL_TO_MODE | |
| @@ -5364,6 +5441,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) | |||
| 5364 | static void gen8_enable_rps(struct drm_i915_private *dev_priv) | 5441 | static void gen8_enable_rps(struct drm_i915_private *dev_priv) |
| 5365 | { | 5442 | { |
| 5366 | struct intel_engine_cs *engine; | 5443 | struct intel_engine_cs *engine; |
| 5444 | enum intel_engine_id id; | ||
| 5367 | uint32_t rc6_mask = 0; | 5445 | uint32_t rc6_mask = 0; |
| 5368 | 5446 | ||
| 5369 | /* 1a: Software RC state - RC0 */ | 5447 | /* 1a: Software RC state - RC0 */ |
| @@ -5380,7 +5458,7 @@ static void gen8_enable_rps(struct drm_i915_private *dev_priv) | |||
| 5380 | I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16); | 5458 | I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16); |
| 5381 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ | 5459 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ |
| 5382 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ | 5460 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ |
| 5383 | for_each_engine(engine, dev_priv) | 5461 | for_each_engine(engine, dev_priv, id) |
| 5384 | I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); | 5462 | I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); |
| 5385 | I915_WRITE(GEN6_RC_SLEEP, 0); | 5463 | I915_WRITE(GEN6_RC_SLEEP, 0); |
| 5386 | if (IS_BROADWELL(dev_priv)) | 5464 | if (IS_BROADWELL(dev_priv)) |
| @@ -5440,6 +5518,7 @@ static void gen8_enable_rps(struct drm_i915_private *dev_priv) | |||
| 5440 | static void gen6_enable_rps(struct drm_i915_private *dev_priv) | 5518 | static void gen6_enable_rps(struct drm_i915_private *dev_priv) |
| 5441 | { | 5519 | { |
| 5442 | struct intel_engine_cs *engine; | 5520 | struct intel_engine_cs *engine; |
| 5521 | enum intel_engine_id id; | ||
| 5443 | u32 rc6vids, rc6_mask = 0; | 5522 | u32 rc6vids, rc6_mask = 0; |
| 5444 | u32 gtfifodbg; | 5523 | u32 gtfifodbg; |
| 5445 | int rc6_mode; | 5524 | int rc6_mode; |
| @@ -5473,7 +5552,7 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 5473 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); | 5552 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); |
| 5474 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); | 5553 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); |
| 5475 | 5554 | ||
| 5476 | for_each_engine(engine, dev_priv) | 5555 | for_each_engine(engine, dev_priv, id) |
| 5477 | I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); | 5556 | I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); |
| 5478 | 5557 | ||
| 5479 | I915_WRITE(GEN6_RC_SLEEP, 0); | 5558 | I915_WRITE(GEN6_RC_SLEEP, 0); |
| @@ -5510,10 +5589,6 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
| 5510 | I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 50000); | 5589 | I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 50000); |
| 5511 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); | 5590 | I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); |
| 5512 | 5591 | ||
| 5513 | ret = sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_MIN_FREQ_TABLE, 0); | ||
| 5514 | if (ret) | ||
| 5515 | DRM_DEBUG_DRIVER("Failed to set the min frequency\n"); | ||
| 5516 | |||
| 5517 | reset_rps(dev_priv, gen6_set_rps); | 5592 | reset_rps(dev_priv, gen6_set_rps); |
| 5518 | 5593 | ||
| 5519 | rc6vids = 0; | 5594 | rc6vids = 0; |
| @@ -5922,6 +5997,7 @@ static void valleyview_cleanup_gt_powersave(struct drm_i915_private *dev_priv) | |||
| 5922 | static void cherryview_enable_rps(struct drm_i915_private *dev_priv) | 5997 | static void cherryview_enable_rps(struct drm_i915_private *dev_priv) |
| 5923 | { | 5998 | { |
| 5924 | struct intel_engine_cs *engine; | 5999 | struct intel_engine_cs *engine; |
| 6000 | enum intel_engine_id id; | ||
| 5925 | u32 gtfifodbg, val, rc6_mode = 0, pcbr; | 6001 | u32 gtfifodbg, val, rc6_mode = 0, pcbr; |
| 5926 | 6002 | ||
| 5927 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); | 6003 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); |
| @@ -5948,7 +6024,7 @@ static void cherryview_enable_rps(struct drm_i915_private *dev_priv) | |||
| 5948 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ | 6024 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); /* 12500 * 1280ns */ |
| 5949 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ | 6025 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); /* 25 * 1280ns */ |
| 5950 | 6026 | ||
| 5951 | for_each_engine(engine, dev_priv) | 6027 | for_each_engine(engine, dev_priv, id) |
| 5952 | I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); | 6028 | I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); |
| 5953 | I915_WRITE(GEN6_RC_SLEEP, 0); | 6029 | I915_WRITE(GEN6_RC_SLEEP, 0); |
| 5954 | 6030 | ||
| @@ -6010,6 +6086,7 @@ static void cherryview_enable_rps(struct drm_i915_private *dev_priv) | |||
| 6010 | static void valleyview_enable_rps(struct drm_i915_private *dev_priv) | 6086 | static void valleyview_enable_rps(struct drm_i915_private *dev_priv) |
| 6011 | { | 6087 | { |
| 6012 | struct intel_engine_cs *engine; | 6088 | struct intel_engine_cs *engine; |
| 6089 | enum intel_engine_id id; | ||
| 6013 | u32 gtfifodbg, val, rc6_mode = 0; | 6090 | u32 gtfifodbg, val, rc6_mode = 0; |
| 6014 | 6091 | ||
| 6015 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); | 6092 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); |
| @@ -6049,7 +6126,7 @@ static void valleyview_enable_rps(struct drm_i915_private *dev_priv) | |||
| 6049 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); | 6126 | I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); |
| 6050 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); | 6127 | I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); |
| 6051 | 6128 | ||
| 6052 | for_each_engine(engine, dev_priv) | 6129 | for_each_engine(engine, dev_priv, id) |
| 6053 | I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); | 6130 | I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); |
| 6054 | 6131 | ||
| 6055 | I915_WRITE(GEN6_RC6_THRESHOLD, 0x557); | 6132 | I915_WRITE(GEN6_RC6_THRESHOLD, 0x557); |
| @@ -6732,7 +6809,7 @@ static void __intel_autoenable_gt_powersave(struct work_struct *work) | |||
| 6732 | if (READ_ONCE(dev_priv->rps.enabled)) | 6809 | if (READ_ONCE(dev_priv->rps.enabled)) |
| 6733 | goto out; | 6810 | goto out; |
| 6734 | 6811 | ||
| 6735 | rcs = &dev_priv->engine[RCS]; | 6812 | rcs = dev_priv->engine[RCS]; |
| 6736 | if (rcs->last_context) | 6813 | if (rcs->last_context) |
| 6737 | goto out; | 6814 | goto out; |
| 6738 | 6815 | ||
| @@ -6869,7 +6946,7 @@ static void ironlake_init_clock_gating(struct drm_device *dev) | |||
| 6869 | * The bit 22 of 0x42004 | 6946 | * The bit 22 of 0x42004 |
| 6870 | * The bit 7,8,9 of 0x42020. | 6947 | * The bit 7,8,9 of 0x42020. |
| 6871 | */ | 6948 | */ |
| 6872 | if (IS_IRONLAKE_M(dev)) { | 6949 | if (IS_IRONLAKE_M(dev_priv)) { |
| 6873 | /* WaFbcAsynchFlipDisableFbcQueue:ilk */ | 6950 | /* WaFbcAsynchFlipDisableFbcQueue:ilk */ |
| 6874 | I915_WRITE(ILK_DISPLAY_CHICKEN1, | 6951 | I915_WRITE(ILK_DISPLAY_CHICKEN1, |
| 6875 | I915_READ(ILK_DISPLAY_CHICKEN1) | | 6952 | I915_READ(ILK_DISPLAY_CHICKEN1) | |
| @@ -7071,7 +7148,7 @@ static void lpt_init_clock_gating(struct drm_device *dev) | |||
| 7071 | * TODO: this bit should only be enabled when really needed, then | 7148 | * TODO: this bit should only be enabled when really needed, then |
| 7072 | * disabled when not needed anymore in order to save power. | 7149 | * disabled when not needed anymore in order to save power. |
| 7073 | */ | 7150 | */ |
| 7074 | if (HAS_PCH_LPT_LP(dev)) | 7151 | if (HAS_PCH_LPT_LP(dev_priv)) |
| 7075 | I915_WRITE(SOUTH_DSPCLK_GATE_D, | 7152 | I915_WRITE(SOUTH_DSPCLK_GATE_D, |
| 7076 | I915_READ(SOUTH_DSPCLK_GATE_D) | | 7153 | I915_READ(SOUTH_DSPCLK_GATE_D) | |
| 7077 | PCH_LP_PARTITION_LEVEL_DISABLE); | 7154 | PCH_LP_PARTITION_LEVEL_DISABLE); |
| @@ -7086,7 +7163,7 @@ static void lpt_suspend_hw(struct drm_device *dev) | |||
| 7086 | { | 7163 | { |
| 7087 | struct drm_i915_private *dev_priv = to_i915(dev); | 7164 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 7088 | 7165 | ||
| 7089 | if (HAS_PCH_LPT_LP(dev)) { | 7166 | if (HAS_PCH_LPT_LP(dev_priv)) { |
| 7090 | uint32_t val = I915_READ(SOUTH_DSPCLK_GATE_D); | 7167 | uint32_t val = I915_READ(SOUTH_DSPCLK_GATE_D); |
| 7091 | 7168 | ||
| 7092 | val &= ~PCH_LP_PARTITION_LEVEL_DISABLE; | 7169 | val &= ~PCH_LP_PARTITION_LEVEL_DISABLE; |
| @@ -7279,7 +7356,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) | |||
| 7279 | CHICKEN3_DGMG_DONE_FIX_DISABLE); | 7356 | CHICKEN3_DGMG_DONE_FIX_DISABLE); |
| 7280 | 7357 | ||
| 7281 | /* WaDisablePSDDualDispatchEnable:ivb */ | 7358 | /* WaDisablePSDDualDispatchEnable:ivb */ |
| 7282 | if (IS_IVB_GT1(dev)) | 7359 | if (IS_IVB_GT1(dev_priv)) |
| 7283 | I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, | 7360 | I915_WRITE(GEN7_HALF_SLICE_CHICKEN1, |
| 7284 | _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); | 7361 | _MASKED_BIT_ENABLE(GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE)); |
| 7285 | 7362 | ||
| @@ -7295,7 +7372,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) | |||
| 7295 | GEN7_WA_FOR_GEN7_L3_CONTROL); | 7372 | GEN7_WA_FOR_GEN7_L3_CONTROL); |
| 7296 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, | 7373 | I915_WRITE(GEN7_L3_CHICKEN_MODE_REGISTER, |
| 7297 | GEN7_WA_L3_CHICKEN_MODE); | 7374 | GEN7_WA_L3_CHICKEN_MODE); |
| 7298 | if (IS_IVB_GT1(dev)) | 7375 | if (IS_IVB_GT1(dev_priv)) |
| 7299 | I915_WRITE(GEN7_ROW_CHICKEN2, | 7376 | I915_WRITE(GEN7_ROW_CHICKEN2, |
| 7300 | _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); | 7377 | _MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE)); |
| 7301 | else { | 7378 | else { |
| @@ -7352,7 +7429,7 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) | |||
| 7352 | snpcr |= GEN6_MBC_SNPCR_MED; | 7429 | snpcr |= GEN6_MBC_SNPCR_MED; |
| 7353 | I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); | 7430 | I915_WRITE(GEN6_MBCUNIT_SNPCR, snpcr); |
| 7354 | 7431 | ||
| 7355 | if (!HAS_PCH_NOP(dev)) | 7432 | if (!HAS_PCH_NOP(dev_priv)) |
| 7356 | cpt_init_clock_gating(dev); | 7433 | cpt_init_clock_gating(dev); |
| 7357 | 7434 | ||
| 7358 | gen6_check_mch_setup(dev); | 7435 | gen6_check_mch_setup(dev); |
| @@ -7489,7 +7566,7 @@ static void g4x_init_clock_gating(struct drm_device *dev) | |||
| 7489 | dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | | 7566 | dspclk_gate = VRHUNIT_CLOCK_GATE_DISABLE | |
| 7490 | OVRUNIT_CLOCK_GATE_DISABLE | | 7567 | OVRUNIT_CLOCK_GATE_DISABLE | |
| 7491 | OVCUNIT_CLOCK_GATE_DISABLE; | 7568 | OVCUNIT_CLOCK_GATE_DISABLE; |
| 7492 | if (IS_GM45(dev)) | 7569 | if (IS_GM45(dev_priv)) |
| 7493 | dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; | 7570 | dspclk_gate |= DSSUNIT_CLOCK_GATE_DISABLE; |
| 7494 | I915_WRITE(DSPCLK_GATE_D, dspclk_gate); | 7571 | I915_WRITE(DSPCLK_GATE_D, dspclk_gate); |
| 7495 | 7572 | ||
| @@ -7595,7 +7672,7 @@ void intel_init_clock_gating(struct drm_device *dev) | |||
| 7595 | 7672 | ||
| 7596 | void intel_suspend_hw(struct drm_device *dev) | 7673 | void intel_suspend_hw(struct drm_device *dev) |
| 7597 | { | 7674 | { |
| 7598 | if (HAS_PCH_LPT(dev)) | 7675 | if (HAS_PCH_LPT(to_i915(dev))) |
| 7599 | lpt_suspend_hw(dev); | 7676 | lpt_suspend_hw(dev); |
| 7600 | } | 7677 | } |
| 7601 | 7678 | ||
| @@ -7663,7 +7740,7 @@ void intel_init_pm(struct drm_device *dev) | |||
| 7663 | /* For cxsr */ | 7740 | /* For cxsr */ |
| 7664 | if (IS_PINEVIEW(dev)) | 7741 | if (IS_PINEVIEW(dev)) |
| 7665 | i915_pineview_get_mem_freq(dev); | 7742 | i915_pineview_get_mem_freq(dev); |
| 7666 | else if (IS_GEN5(dev)) | 7743 | else if (IS_GEN5(dev_priv)) |
| 7667 | i915_ironlake_get_mem_freq(dev); | 7744 | i915_ironlake_get_mem_freq(dev); |
| 7668 | 7745 | ||
| 7669 | /* For FIFO watermark updates */ | 7746 | /* For FIFO watermark updates */ |
| @@ -7671,12 +7748,12 @@ void intel_init_pm(struct drm_device *dev) | |||
| 7671 | skl_setup_wm_latency(dev); | 7748 | skl_setup_wm_latency(dev); |
| 7672 | dev_priv->display.update_wm = skl_update_wm; | 7749 | dev_priv->display.update_wm = skl_update_wm; |
| 7673 | dev_priv->display.compute_global_watermarks = skl_compute_wm; | 7750 | dev_priv->display.compute_global_watermarks = skl_compute_wm; |
| 7674 | } else if (HAS_PCH_SPLIT(dev)) { | 7751 | } else if (HAS_PCH_SPLIT(dev_priv)) { |
| 7675 | ilk_setup_wm_latency(dev); | 7752 | ilk_setup_wm_latency(dev); |
| 7676 | 7753 | ||
| 7677 | if ((IS_GEN5(dev) && dev_priv->wm.pri_latency[1] && | 7754 | if ((IS_GEN5(dev_priv) && dev_priv->wm.pri_latency[1] && |
| 7678 | dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) || | 7755 | dev_priv->wm.spr_latency[1] && dev_priv->wm.cur_latency[1]) || |
| 7679 | (!IS_GEN5(dev) && dev_priv->wm.pri_latency[0] && | 7756 | (!IS_GEN5(dev_priv) && dev_priv->wm.pri_latency[0] && |
| 7680 | dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) { | 7757 | dev_priv->wm.spr_latency[0] && dev_priv->wm.cur_latency[0])) { |
| 7681 | dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm; | 7758 | dev_priv->display.compute_pipe_wm = ilk_compute_pipe_wm; |
| 7682 | dev_priv->display.compute_intermediate_wm = | 7759 | dev_priv->display.compute_intermediate_wm = |
| @@ -7689,14 +7766,14 @@ void intel_init_pm(struct drm_device *dev) | |||
| 7689 | DRM_DEBUG_KMS("Failed to read display plane latency. " | 7766 | DRM_DEBUG_KMS("Failed to read display plane latency. " |
| 7690 | "Disable CxSR\n"); | 7767 | "Disable CxSR\n"); |
| 7691 | } | 7768 | } |
| 7692 | } else if (IS_CHERRYVIEW(dev)) { | 7769 | } else if (IS_CHERRYVIEW(dev_priv)) { |
| 7693 | vlv_setup_wm_latency(dev); | 7770 | vlv_setup_wm_latency(dev); |
| 7694 | dev_priv->display.update_wm = vlv_update_wm; | 7771 | dev_priv->display.update_wm = vlv_update_wm; |
| 7695 | } else if (IS_VALLEYVIEW(dev)) { | 7772 | } else if (IS_VALLEYVIEW(dev_priv)) { |
| 7696 | vlv_setup_wm_latency(dev); | 7773 | vlv_setup_wm_latency(dev); |
| 7697 | dev_priv->display.update_wm = vlv_update_wm; | 7774 | dev_priv->display.update_wm = vlv_update_wm; |
| 7698 | } else if (IS_PINEVIEW(dev)) { | 7775 | } else if (IS_PINEVIEW(dev)) { |
| 7699 | if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev), | 7776 | if (!intel_get_cxsr_latency(IS_PINEVIEW_G(dev_priv), |
| 7700 | dev_priv->is_ddr3, | 7777 | dev_priv->is_ddr3, |
| 7701 | dev_priv->fsb_freq, | 7778 | dev_priv->fsb_freq, |
| 7702 | dev_priv->mem_freq)) { | 7779 | dev_priv->mem_freq)) { |
| @@ -7710,14 +7787,14 @@ void intel_init_pm(struct drm_device *dev) | |||
| 7710 | dev_priv->display.update_wm = NULL; | 7787 | dev_priv->display.update_wm = NULL; |
| 7711 | } else | 7788 | } else |
| 7712 | dev_priv->display.update_wm = pineview_update_wm; | 7789 | dev_priv->display.update_wm = pineview_update_wm; |
| 7713 | } else if (IS_G4X(dev)) { | 7790 | } else if (IS_G4X(dev_priv)) { |
| 7714 | dev_priv->display.update_wm = g4x_update_wm; | 7791 | dev_priv->display.update_wm = g4x_update_wm; |
| 7715 | } else if (IS_GEN4(dev)) { | 7792 | } else if (IS_GEN4(dev_priv)) { |
| 7716 | dev_priv->display.update_wm = i965_update_wm; | 7793 | dev_priv->display.update_wm = i965_update_wm; |
| 7717 | } else if (IS_GEN3(dev)) { | 7794 | } else if (IS_GEN3(dev_priv)) { |
| 7718 | dev_priv->display.update_wm = i9xx_update_wm; | 7795 | dev_priv->display.update_wm = i9xx_update_wm; |
| 7719 | dev_priv->display.get_fifo_size = i9xx_get_fifo_size; | 7796 | dev_priv->display.get_fifo_size = i9xx_get_fifo_size; |
| 7720 | } else if (IS_GEN2(dev)) { | 7797 | } else if (IS_GEN2(dev_priv)) { |
| 7721 | if (INTEL_INFO(dev)->num_pipes == 1) { | 7798 | if (INTEL_INFO(dev)->num_pipes == 1) { |
| 7722 | dev_priv->display.update_wm = i845_update_wm; | 7799 | dev_priv->display.update_wm = i845_update_wm; |
| 7723 | dev_priv->display.get_fifo_size = i845_get_fifo_size; | 7800 | dev_priv->display.get_fifo_size = i845_get_fifo_size; |
diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index 108ba1e5d658..271a3e29ff23 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c | |||
| @@ -268,7 +268,7 @@ static void hsw_psr_enable_source(struct intel_dp *intel_dp) | |||
| 268 | val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT; | 268 | val |= max_sleep_time << EDP_PSR_MAX_SLEEP_TIME_SHIFT; |
| 269 | val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; | 269 | val |= idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; |
| 270 | 270 | ||
| 271 | if (IS_HASWELL(dev)) | 271 | if (IS_HASWELL(dev_priv)) |
| 272 | val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; | 272 | val |= EDP_PSR_MIN_LINK_ENTRY_TIME_8_LINES; |
| 273 | 273 | ||
| 274 | if (dev_priv->psr.link_standby) | 274 | if (dev_priv->psr.link_standby) |
| @@ -344,7 +344,7 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) | |||
| 344 | * ones. Since by Display design transcoder EDP is tied to port A | 344 | * ones. Since by Display design transcoder EDP is tied to port A |
| 345 | * we can safely escape based on the port A. | 345 | * we can safely escape based on the port A. |
| 346 | */ | 346 | */ |
| 347 | if (HAS_DDI(dev) && dig_port->port != PORT_A) { | 347 | if (HAS_DDI(dev_priv) && dig_port->port != PORT_A) { |
| 348 | DRM_DEBUG_KMS("PSR condition failed: Port not supported\n"); | 348 | DRM_DEBUG_KMS("PSR condition failed: Port not supported\n"); |
| 349 | return false; | 349 | return false; |
| 350 | } | 350 | } |
| @@ -354,20 +354,20 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) | |||
| 354 | return false; | 354 | return false; |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && | 357 | if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && |
| 358 | !dev_priv->psr.link_standby) { | 358 | !dev_priv->psr.link_standby) { |
| 359 | DRM_ERROR("PSR condition failed: Link off requested but not supported on this platform\n"); | 359 | DRM_ERROR("PSR condition failed: Link off requested but not supported on this platform\n"); |
| 360 | return false; | 360 | return false; |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | if (IS_HASWELL(dev) && | 363 | if (IS_HASWELL(dev_priv) && |
| 364 | I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config->cpu_transcoder)) & | 364 | I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config->cpu_transcoder)) & |
| 365 | S3D_ENABLE) { | 365 | S3D_ENABLE) { |
| 366 | DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n"); | 366 | DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n"); |
| 367 | return false; | 367 | return false; |
| 368 | } | 368 | } |
| 369 | 369 | ||
| 370 | if (IS_HASWELL(dev) && | 370 | if (IS_HASWELL(dev_priv) && |
| 371 | adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { | 371 | adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { |
| 372 | DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); | 372 | DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); |
| 373 | return false; | 373 | return false; |
| @@ -402,7 +402,7 @@ static void intel_psr_activate(struct intel_dp *intel_dp) | |||
| 402 | lockdep_assert_held(&dev_priv->psr.lock); | 402 | lockdep_assert_held(&dev_priv->psr.lock); |
| 403 | 403 | ||
| 404 | /* Enable/Re-enable PSR on the host */ | 404 | /* Enable/Re-enable PSR on the host */ |
| 405 | if (HAS_DDI(dev)) | 405 | if (HAS_DDI(dev_priv)) |
| 406 | /* On HSW+ after we enable PSR on source it will activate it | 406 | /* On HSW+ after we enable PSR on source it will activate it |
| 407 | * as soon as it match configure idle_frame count. So | 407 | * as soon as it match configure idle_frame count. So |
| 408 | * we just actually enable it here on activation time. | 408 | * we just actually enable it here on activation time. |
| @@ -448,7 +448,7 @@ void intel_psr_enable(struct intel_dp *intel_dp) | |||
| 448 | 448 | ||
| 449 | dev_priv->psr.busy_frontbuffer_bits = 0; | 449 | dev_priv->psr.busy_frontbuffer_bits = 0; |
| 450 | 450 | ||
| 451 | if (HAS_DDI(dev)) { | 451 | if (HAS_DDI(dev_priv)) { |
| 452 | hsw_psr_setup_vsc(intel_dp); | 452 | hsw_psr_setup_vsc(intel_dp); |
| 453 | 453 | ||
| 454 | if (dev_priv->psr.psr2_support) { | 454 | if (dev_priv->psr.psr2_support) { |
| @@ -580,7 +580,7 @@ void intel_psr_disable(struct intel_dp *intel_dp) | |||
| 580 | } | 580 | } |
| 581 | 581 | ||
| 582 | /* Disable PSR on Source */ | 582 | /* Disable PSR on Source */ |
| 583 | if (HAS_DDI(dev)) | 583 | if (HAS_DDI(dev_priv)) |
| 584 | hsw_psr_disable(intel_dp); | 584 | hsw_psr_disable(intel_dp); |
| 585 | else | 585 | else |
| 586 | vlv_psr_disable(intel_dp); | 586 | vlv_psr_disable(intel_dp); |
| @@ -827,17 +827,17 @@ void intel_psr_init(struct drm_device *dev) | |||
| 827 | 827 | ||
| 828 | /* Per platform default */ | 828 | /* Per platform default */ |
| 829 | if (i915.enable_psr == -1) { | 829 | if (i915.enable_psr == -1) { |
| 830 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 830 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 831 | i915.enable_psr = 1; | 831 | i915.enable_psr = 1; |
| 832 | else | 832 | else |
| 833 | i915.enable_psr = 0; | 833 | i915.enable_psr = 0; |
| 834 | } | 834 | } |
| 835 | 835 | ||
| 836 | /* Set link_standby x link_off defaults */ | 836 | /* Set link_standby x link_off defaults */ |
| 837 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 837 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 838 | /* HSW and BDW require workarounds that we don't implement. */ | 838 | /* HSW and BDW require workarounds that we don't implement. */ |
| 839 | dev_priv->psr.link_standby = false; | 839 | dev_priv->psr.link_standby = false; |
| 840 | else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) | 840 | else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) |
| 841 | /* On VLV and CHV only standby mode is supported. */ | 841 | /* On VLV and CHV only standby mode is supported. */ |
| 842 | dev_priv->psr.link_standby = true; | 842 | dev_priv->psr.link_standby = true; |
| 843 | else | 843 | else |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 7a74750076c5..32786ba199b9 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
| @@ -405,22 +405,6 @@ gen8_render_ring_flush(struct drm_i915_gem_request *req, u32 mode) | |||
| 405 | return gen8_emit_pipe_control(req, flags, scratch_addr); | 405 | return gen8_emit_pipe_control(req, flags, scratch_addr); |
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | u64 intel_engine_get_active_head(struct intel_engine_cs *engine) | ||
| 409 | { | ||
| 410 | struct drm_i915_private *dev_priv = engine->i915; | ||
| 411 | u64 acthd; | ||
| 412 | |||
| 413 | if (INTEL_GEN(dev_priv) >= 8) | ||
| 414 | acthd = I915_READ64_2x32(RING_ACTHD(engine->mmio_base), | ||
| 415 | RING_ACTHD_UDW(engine->mmio_base)); | ||
| 416 | else if (INTEL_GEN(dev_priv) >= 4) | ||
| 417 | acthd = I915_READ(RING_ACTHD(engine->mmio_base)); | ||
| 418 | else | ||
| 419 | acthd = I915_READ(ACTHD); | ||
| 420 | |||
| 421 | return acthd; | ||
| 422 | } | ||
| 423 | |||
| 424 | static void ring_setup_phys_status_page(struct intel_engine_cs *engine) | 408 | static void ring_setup_phys_status_page(struct intel_engine_cs *engine) |
| 425 | { | 409 | { |
| 426 | struct drm_i915_private *dev_priv = engine->i915; | 410 | struct drm_i915_private *dev_priv = engine->i915; |
| @@ -564,7 +548,7 @@ static int init_ring_common(struct intel_engine_cs *engine) | |||
| 564 | else | 548 | else |
| 565 | intel_ring_setup_status_page(engine); | 549 | intel_ring_setup_status_page(engine); |
| 566 | 550 | ||
| 567 | intel_engine_reset_irq(engine); | 551 | intel_engine_reset_breadcrumbs(engine); |
| 568 | 552 | ||
| 569 | /* Enforce ordering by reading HEAD register back */ | 553 | /* Enforce ordering by reading HEAD register back */ |
| 570 | I915_READ_HEAD(engine); | 554 | I915_READ_HEAD(engine); |
| @@ -585,9 +569,7 @@ static int init_ring_common(struct intel_engine_cs *engine) | |||
| 585 | I915_WRITE_TAIL(engine, ring->tail); | 569 | I915_WRITE_TAIL(engine, ring->tail); |
| 586 | (void)I915_READ_TAIL(engine); | 570 | (void)I915_READ_TAIL(engine); |
| 587 | 571 | ||
| 588 | I915_WRITE_CTL(engine, | 572 | I915_WRITE_CTL(engine, RING_CTL_SIZE(ring->size) | RING_VALID); |
| 589 | ((ring->size - PAGE_SIZE) & RING_NR_PAGES) | ||
| 590 | | RING_VALID); | ||
| 591 | 573 | ||
| 592 | /* If the head is still not zero, the ring is dead */ | 574 | /* If the head is still not zero, the ring is dead */ |
| 593 | if (intel_wait_for_register_fw(dev_priv, RING_CTL(engine->mmio_base), | 575 | if (intel_wait_for_register_fw(dev_priv, RING_CTL(engine->mmio_base), |
| @@ -851,15 +833,13 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) | |||
| 851 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, | 833 | WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, |
| 852 | GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); | 834 | GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC); |
| 853 | 835 | ||
| 854 | /* WaDisableDgMirrorFixInHalfSliceChicken5:skl,bxt */ | 836 | /* WaDisableDgMirrorFixInHalfSliceChicken5:bxt */ |
| 855 | if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || | 837 | if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) |
| 856 | IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) | ||
| 857 | WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, | 838 | WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, |
| 858 | GEN9_DG_MIRROR_FIX_ENABLE); | 839 | GEN9_DG_MIRROR_FIX_ENABLE); |
| 859 | 840 | ||
| 860 | /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:skl,bxt */ | 841 | /* WaSetDisablePixMaskCammingAndRhwoInCommonSliceChicken:bxt */ |
| 861 | if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_B0) || | 842 | if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { |
| 862 | IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) { | ||
| 863 | WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, | 843 | WA_SET_BIT_MASKED(GEN7_COMMON_SLICE_CHICKEN1, |
| 864 | GEN9_RHWO_OPTIMIZATION_DISABLE); | 844 | GEN9_RHWO_OPTIMIZATION_DISABLE); |
| 865 | /* | 845 | /* |
| @@ -869,10 +849,8 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) | |||
| 869 | */ | 849 | */ |
| 870 | } | 850 | } |
| 871 | 851 | ||
| 872 | /* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl */ | ||
| 873 | /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */ | 852 | /* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl */ |
| 874 | WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, | 853 | WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, |
| 875 | GEN9_ENABLE_YV12_BUGFIX | | ||
| 876 | GEN9_ENABLE_GPGPU_PREEMPTION); | 854 | GEN9_ENABLE_GPGPU_PREEMPTION); |
| 877 | 855 | ||
| 878 | /* Wa4x4STCOptimizationDisable:skl,bxt,kbl */ | 856 | /* Wa4x4STCOptimizationDisable:skl,bxt,kbl */ |
| @@ -884,9 +862,8 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) | |||
| 884 | WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, | 862 | WA_CLR_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN5, |
| 885 | GEN9_CCS_TLB_PREFETCH_ENABLE); | 863 | GEN9_CCS_TLB_PREFETCH_ENABLE); |
| 886 | 864 | ||
| 887 | /* WaDisableMaskBasedCammingInRCC:skl,bxt */ | 865 | /* WaDisableMaskBasedCammingInRCC:bxt */ |
| 888 | if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_C0) || | 866 | if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) |
| 889 | IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1)) | ||
| 890 | WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, | 867 | WA_SET_BIT_MASKED(SLICE_ECO_CHICKEN0, |
| 891 | PIXEL_MASK_CAMMING_DISABLE); | 868 | PIXEL_MASK_CAMMING_DISABLE); |
| 892 | 869 | ||
| @@ -1003,47 +980,12 @@ static int skl_init_workarounds(struct intel_engine_cs *engine) | |||
| 1003 | * until D0 which is the default case so this is equivalent to | 980 | * until D0 which is the default case so this is equivalent to |
| 1004 | * !WaDisablePerCtxtPreemptionGranularityControl:skl | 981 | * !WaDisablePerCtxtPreemptionGranularityControl:skl |
| 1005 | */ | 982 | */ |
| 1006 | if (IS_SKL_REVID(dev_priv, SKL_REVID_E0, REVID_FOREVER)) { | 983 | I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, |
| 1007 | I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, | 984 | _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); |
| 1008 | _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) { | ||
| 1012 | /* WaDisableChickenBitTSGBarrierAckForFFSliceCS:skl */ | ||
| 1013 | I915_WRITE(FF_SLICE_CS_CHICKEN2, | ||
| 1014 | _MASKED_BIT_ENABLE(GEN9_TSG_BARRIER_ACK_DISABLE)); | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | /* GEN8_L3SQCREG4 has a dependency with WA batch so any new changes | ||
| 1018 | * involving this register should also be added to WA batch as required. | ||
| 1019 | */ | ||
| 1020 | if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_E0)) | ||
| 1021 | /* WaDisableLSQCROPERFforOCL:skl */ | ||
| 1022 | I915_WRITE(GEN8_L3SQCREG4, I915_READ(GEN8_L3SQCREG4) | | ||
| 1023 | GEN8_LQSC_RO_PERF_DIS); | ||
| 1024 | 985 | ||
| 1025 | /* WaEnableGapsTsvCreditFix:skl */ | 986 | /* WaEnableGapsTsvCreditFix:skl */ |
| 1026 | if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, REVID_FOREVER)) { | 987 | I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | |
| 1027 | I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | | 988 | GEN9_GAPS_TSV_CREDIT_DISABLE)); |
| 1028 | GEN9_GAPS_TSV_CREDIT_DISABLE)); | ||
| 1029 | } | ||
| 1030 | |||
| 1031 | /* WaDisablePowerCompilerClockGating:skl */ | ||
| 1032 | if (IS_SKL_REVID(dev_priv, SKL_REVID_B0, SKL_REVID_B0)) | ||
| 1033 | WA_SET_BIT_MASKED(HIZ_CHICKEN, | ||
| 1034 | BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE); | ||
| 1035 | |||
| 1036 | /* WaBarrierPerformanceFixDisable:skl */ | ||
| 1037 | if (IS_SKL_REVID(dev_priv, SKL_REVID_C0, SKL_REVID_D0)) | ||
| 1038 | WA_SET_BIT_MASKED(HDC_CHICKEN0, | ||
| 1039 | HDC_FENCE_DEST_SLM_DISABLE | | ||
| 1040 | HDC_BARRIER_PERFORMANCE_DISABLE); | ||
| 1041 | |||
| 1042 | /* WaDisableSbeCacheDispatchPortSharing:skl */ | ||
| 1043 | if (IS_SKL_REVID(dev_priv, 0, SKL_REVID_F0)) | ||
| 1044 | WA_SET_BIT_MASKED( | ||
| 1045 | GEN7_HALF_SLICE_CHICKEN1, | ||
| 1046 | GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); | ||
| 1047 | 989 | ||
| 1048 | /* WaDisableGafsUnitClkGating:skl */ | 990 | /* WaDisableGafsUnitClkGating:skl */ |
| 1049 | WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); | 991 | WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); |
| @@ -1284,7 +1226,7 @@ static int gen8_rcs_signal(struct drm_i915_gem_request *req) | |||
| 1284 | if (ret) | 1226 | if (ret) |
| 1285 | return ret; | 1227 | return ret; |
| 1286 | 1228 | ||
| 1287 | for_each_engine_id(waiter, dev_priv, id) { | 1229 | for_each_engine(waiter, dev_priv, id) { |
| 1288 | u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; | 1230 | u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; |
| 1289 | if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) | 1231 | if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) |
| 1290 | continue; | 1232 | continue; |
| @@ -1321,7 +1263,7 @@ static int gen8_xcs_signal(struct drm_i915_gem_request *req) | |||
| 1321 | if (ret) | 1263 | if (ret) |
| 1322 | return ret; | 1264 | return ret; |
| 1323 | 1265 | ||
| 1324 | for_each_engine_id(waiter, dev_priv, id) { | 1266 | for_each_engine(waiter, dev_priv, id) { |
| 1325 | u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; | 1267 | u64 gtt_offset = req->engine->semaphore.signal_ggtt[id]; |
| 1326 | if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) | 1268 | if (gtt_offset == MI_SEMAPHORE_SYNC_INVALID) |
| 1327 | continue; | 1269 | continue; |
| @@ -1348,6 +1290,7 @@ static int gen6_signal(struct drm_i915_gem_request *req) | |||
| 1348 | struct intel_ring *ring = req->ring; | 1290 | struct intel_ring *ring = req->ring; |
| 1349 | struct drm_i915_private *dev_priv = req->i915; | 1291 | struct drm_i915_private *dev_priv = req->i915; |
| 1350 | struct intel_engine_cs *engine; | 1292 | struct intel_engine_cs *engine; |
| 1293 | enum intel_engine_id id; | ||
| 1351 | int ret, num_rings; | 1294 | int ret, num_rings; |
| 1352 | 1295 | ||
| 1353 | num_rings = INTEL_INFO(dev_priv)->num_rings; | 1296 | num_rings = INTEL_INFO(dev_priv)->num_rings; |
| @@ -1355,7 +1298,7 @@ static int gen6_signal(struct drm_i915_gem_request *req) | |||
| 1355 | if (ret) | 1298 | if (ret) |
| 1356 | return ret; | 1299 | return ret; |
| 1357 | 1300 | ||
| 1358 | for_each_engine(engine, dev_priv) { | 1301 | for_each_engine(engine, dev_priv, id) { |
| 1359 | i915_reg_t mbox_reg; | 1302 | i915_reg_t mbox_reg; |
| 1360 | 1303 | ||
| 1361 | if (!(BIT(engine->hw_id) & GEN6_SEMAPHORES_MASK)) | 1304 | if (!(BIT(engine->hw_id) & GEN6_SEMAPHORES_MASK)) |
| @@ -1989,6 +1932,7 @@ intel_engine_create_ring(struct intel_engine_cs *engine, int size) | |||
| 1989 | struct i915_vma *vma; | 1932 | struct i915_vma *vma; |
| 1990 | 1933 | ||
| 1991 | GEM_BUG_ON(!is_power_of_2(size)); | 1934 | GEM_BUG_ON(!is_power_of_2(size)); |
| 1935 | GEM_BUG_ON(RING_CTL_SIZE(size) & ~RING_NR_PAGES); | ||
| 1992 | 1936 | ||
| 1993 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); | 1937 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); |
| 1994 | if (!ring) | 1938 | if (!ring) |
| @@ -2146,9 +2090,6 @@ void intel_engine_cleanup(struct intel_engine_cs *engine) | |||
| 2146 | { | 2090 | { |
| 2147 | struct drm_i915_private *dev_priv; | 2091 | struct drm_i915_private *dev_priv; |
| 2148 | 2092 | ||
| 2149 | if (!intel_engine_initialized(engine)) | ||
| 2150 | return; | ||
| 2151 | |||
| 2152 | dev_priv = engine->i915; | 2093 | dev_priv = engine->i915; |
| 2153 | 2094 | ||
| 2154 | if (engine->buffer) { | 2095 | if (engine->buffer) { |
| @@ -2175,13 +2116,16 @@ void intel_engine_cleanup(struct intel_engine_cs *engine) | |||
| 2175 | intel_ring_context_unpin(dev_priv->kernel_context, engine); | 2116 | intel_ring_context_unpin(dev_priv->kernel_context, engine); |
| 2176 | 2117 | ||
| 2177 | engine->i915 = NULL; | 2118 | engine->i915 = NULL; |
| 2119 | dev_priv->engine[engine->id] = NULL; | ||
| 2120 | kfree(engine); | ||
| 2178 | } | 2121 | } |
| 2179 | 2122 | ||
| 2180 | void intel_legacy_submission_resume(struct drm_i915_private *dev_priv) | 2123 | void intel_legacy_submission_resume(struct drm_i915_private *dev_priv) |
| 2181 | { | 2124 | { |
| 2182 | struct intel_engine_cs *engine; | 2125 | struct intel_engine_cs *engine; |
| 2126 | enum intel_engine_id id; | ||
| 2183 | 2127 | ||
| 2184 | for_each_engine(engine, dev_priv) { | 2128 | for_each_engine(engine, dev_priv, id) { |
| 2185 | engine->buffer->head = engine->buffer->tail; | 2129 | engine->buffer->head = engine->buffer->tail; |
| 2186 | engine->buffer->last_retired_head = -1; | 2130 | engine->buffer->last_retired_head = -1; |
| 2187 | } | 2131 | } |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 7f64d611159b..32b2e6332ccf 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
| @@ -73,13 +73,40 @@ enum intel_engine_hangcheck_action { | |||
| 73 | 73 | ||
| 74 | #define HANGCHECK_SCORE_RING_HUNG 31 | 74 | #define HANGCHECK_SCORE_RING_HUNG 31 |
| 75 | 75 | ||
| 76 | #define I915_MAX_SLICES 3 | ||
| 77 | #define I915_MAX_SUBSLICES 3 | ||
| 78 | |||
| 79 | #define instdone_slice_mask(dev_priv__) \ | ||
| 80 | (INTEL_GEN(dev_priv__) == 7 ? \ | ||
| 81 | 1 : INTEL_INFO(dev_priv__)->sseu.slice_mask) | ||
| 82 | |||
| 83 | #define instdone_subslice_mask(dev_priv__) \ | ||
| 84 | (INTEL_GEN(dev_priv__) == 7 ? \ | ||
| 85 | 1 : INTEL_INFO(dev_priv__)->sseu.subslice_mask) | ||
| 86 | |||
| 87 | #define for_each_instdone_slice_subslice(dev_priv__, slice__, subslice__) \ | ||
| 88 | for ((slice__) = 0, (subslice__) = 0; \ | ||
| 89 | (slice__) < I915_MAX_SLICES; \ | ||
| 90 | (subslice__) = ((subslice__) + 1) < I915_MAX_SUBSLICES ? (subslice__) + 1 : 0, \ | ||
| 91 | (slice__) += ((subslice__) == 0)) \ | ||
| 92 | for_each_if((BIT(slice__) & instdone_slice_mask(dev_priv__)) && \ | ||
| 93 | (BIT(subslice__) & instdone_subslice_mask(dev_priv__))) | ||
| 94 | |||
| 95 | struct intel_instdone { | ||
| 96 | u32 instdone; | ||
| 97 | /* The following exist only in the RCS engine */ | ||
| 98 | u32 slice_common; | ||
| 99 | u32 sampler[I915_MAX_SLICES][I915_MAX_SUBSLICES]; | ||
| 100 | u32 row[I915_MAX_SLICES][I915_MAX_SUBSLICES]; | ||
| 101 | }; | ||
| 102 | |||
| 76 | struct intel_engine_hangcheck { | 103 | struct intel_engine_hangcheck { |
| 77 | u64 acthd; | 104 | u64 acthd; |
| 78 | u32 seqno; | 105 | u32 seqno; |
| 79 | int score; | 106 | int score; |
| 80 | enum intel_engine_hangcheck_action action; | 107 | enum intel_engine_hangcheck_action action; |
| 81 | int deadlock; | 108 | int deadlock; |
| 82 | u32 instdone[I915_NUM_INSTDONE_REG]; | 109 | struct intel_instdone instdone; |
| 83 | }; | 110 | }; |
| 84 | 111 | ||
| 85 | struct intel_ring { | 112 | struct intel_ring { |
| @@ -328,6 +355,7 @@ struct intel_engine_cs { | |||
| 328 | * inspecting request list. | 355 | * inspecting request list. |
| 329 | */ | 356 | */ |
| 330 | u32 last_submitted_seqno; | 357 | u32 last_submitted_seqno; |
| 358 | u32 last_pending_seqno; | ||
| 331 | 359 | ||
| 332 | /* An RCU guarded pointer to the last request. No reference is | 360 | /* An RCU guarded pointer to the last request. No reference is |
| 333 | * held to the request, users must carefully acquire a reference to | 361 | * held to the request, users must carefully acquire a reference to |
| @@ -367,12 +395,6 @@ struct intel_engine_cs { | |||
| 367 | u32 (*get_cmd_length_mask)(u32 cmd_header); | 395 | u32 (*get_cmd_length_mask)(u32 cmd_header); |
| 368 | }; | 396 | }; |
| 369 | 397 | ||
| 370 | static inline bool | ||
| 371 | intel_engine_initialized(const struct intel_engine_cs *engine) | ||
| 372 | { | ||
| 373 | return engine->i915 != NULL; | ||
| 374 | } | ||
| 375 | |||
| 376 | static inline unsigned | 398 | static inline unsigned |
| 377 | intel_engine_flag(const struct intel_engine_cs *engine) | 399 | intel_engine_flag(const struct intel_engine_cs *engine) |
| 378 | { | 400 | { |
| @@ -393,7 +415,7 @@ intel_engine_sync_index(struct intel_engine_cs *engine, | |||
| 393 | * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs; | 415 | * vcs2 -> 0 = rcs, 1 = vcs, 2 = bcs, 3 = vecs; |
| 394 | */ | 416 | */ |
| 395 | 417 | ||
| 396 | idx = (other - engine) - 1; | 418 | idx = (other->id - engine->id) - 1; |
| 397 | if (idx < 0) | 419 | if (idx < 0) |
| 398 | idx += I915_NUM_ENGINES; | 420 | idx += I915_NUM_ENGINES; |
| 399 | 421 | ||
| @@ -492,7 +514,6 @@ int __intel_ring_space(int head, int tail, int size); | |||
| 492 | void intel_ring_update_space(struct intel_ring *ring); | 514 | void intel_ring_update_space(struct intel_ring *ring); |
| 493 | 515 | ||
| 494 | void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno); | 516 | void intel_engine_init_seqno(struct intel_engine_cs *engine, u32 seqno); |
| 495 | void intel_engine_reset_irq(struct intel_engine_cs *engine); | ||
| 496 | 517 | ||
| 497 | void intel_engine_setup_common(struct intel_engine_cs *engine); | 518 | void intel_engine_setup_common(struct intel_engine_cs *engine); |
| 498 | int intel_engine_init_common(struct intel_engine_cs *engine); | 519 | int intel_engine_init_common(struct intel_engine_cs *engine); |
| @@ -514,6 +535,8 @@ int intel_init_blt_ring_buffer(struct intel_engine_cs *engine); | |||
| 514 | int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine); | 535 | int intel_init_vebox_ring_buffer(struct intel_engine_cs *engine); |
| 515 | 536 | ||
| 516 | u64 intel_engine_get_active_head(struct intel_engine_cs *engine); | 537 | u64 intel_engine_get_active_head(struct intel_engine_cs *engine); |
| 538 | u64 intel_engine_get_last_batch_head(struct intel_engine_cs *engine); | ||
| 539 | |||
| 517 | static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine) | 540 | static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine) |
| 518 | { | 541 | { |
| 519 | return intel_read_status_page(engine, I915_GEM_HWS_INDEX); | 542 | return intel_read_status_page(engine, I915_GEM_HWS_INDEX); |
| @@ -521,6 +544,9 @@ static inline u32 intel_engine_get_seqno(struct intel_engine_cs *engine) | |||
| 521 | 544 | ||
| 522 | int init_workarounds_ring(struct intel_engine_cs *engine); | 545 | int init_workarounds_ring(struct intel_engine_cs *engine); |
| 523 | 546 | ||
| 547 | void intel_engine_get_instdone(struct intel_engine_cs *engine, | ||
| 548 | struct intel_instdone *instdone); | ||
| 549 | |||
| 524 | /* | 550 | /* |
| 525 | * Arbitrary size for largest possible 'add request' sequence. The code paths | 551 | * Arbitrary size for largest possible 'add request' sequence. The code paths |
| 526 | * are complex and variable. Empirical measurement shows that the worst case | 552 | * are complex and variable. Empirical measurement shows that the worst case |
| @@ -584,6 +610,7 @@ static inline bool intel_engine_wakeup(const struct intel_engine_cs *engine) | |||
| 584 | return wakeup; | 610 | return wakeup; |
| 585 | } | 611 | } |
| 586 | 612 | ||
| 613 | void intel_engine_reset_breadcrumbs(struct intel_engine_cs *engine); | ||
| 587 | void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); | 614 | void intel_engine_fini_breadcrumbs(struct intel_engine_cs *engine); |
| 588 | unsigned int intel_kick_waiters(struct drm_i915_private *i915); | 615 | unsigned int intel_kick_waiters(struct drm_i915_private *i915); |
| 589 | unsigned int intel_kick_signalers(struct drm_i915_private *i915); | 616 | unsigned int intel_kick_signalers(struct drm_i915_private *i915); |
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 6c11168facd6..ee56a8756c07 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c | |||
| @@ -288,7 +288,6 @@ void intel_display_set_init_power(struct drm_i915_private *dev_priv, | |||
| 288 | static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) | 288 | static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) |
| 289 | { | 289 | { |
| 290 | struct pci_dev *pdev = dev_priv->drm.pdev; | 290 | struct pci_dev *pdev = dev_priv->drm.pdev; |
| 291 | struct drm_device *dev = &dev_priv->drm; | ||
| 292 | 291 | ||
| 293 | /* | 292 | /* |
| 294 | * After we re-enable the power well, if we touch VGA register 0x3d5 | 293 | * After we re-enable the power well, if we touch VGA register 0x3d5 |
| @@ -304,7 +303,7 @@ static void hsw_power_well_post_enable(struct drm_i915_private *dev_priv) | |||
| 304 | outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); | 303 | outb(inb(VGA_MSR_READ), VGA_MSR_WRITE); |
| 305 | vga_put(pdev, VGA_RSRC_LEGACY_IO); | 304 | vga_put(pdev, VGA_RSRC_LEGACY_IO); |
| 306 | 305 | ||
| 307 | if (IS_BROADWELL(dev)) | 306 | if (IS_BROADWELL(dev_priv)) |
| 308 | gen8_irq_power_well_post_enable(dev_priv, | 307 | gen8_irq_power_well_post_enable(dev_priv, |
| 309 | 1 << PIPE_C | 1 << PIPE_B); | 308 | 1 << PIPE_C | 1 << PIPE_B); |
| 310 | } | 309 | } |
| @@ -2590,20 +2589,19 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) | |||
| 2590 | */ | 2589 | */ |
| 2591 | void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) | 2590 | void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) |
| 2592 | { | 2591 | { |
| 2593 | struct drm_device *dev = &dev_priv->drm; | ||
| 2594 | struct i915_power_domains *power_domains = &dev_priv->power_domains; | 2592 | struct i915_power_domains *power_domains = &dev_priv->power_domains; |
| 2595 | 2593 | ||
| 2596 | power_domains->initializing = true; | 2594 | power_domains->initializing = true; |
| 2597 | 2595 | ||
| 2598 | if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) { | 2596 | if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) { |
| 2599 | skl_display_core_init(dev_priv, resume); | 2597 | skl_display_core_init(dev_priv, resume); |
| 2600 | } else if (IS_BROXTON(dev)) { | 2598 | } else if (IS_BROXTON(dev_priv)) { |
| 2601 | bxt_display_core_init(dev_priv, resume); | 2599 | bxt_display_core_init(dev_priv, resume); |
| 2602 | } else if (IS_CHERRYVIEW(dev)) { | 2600 | } else if (IS_CHERRYVIEW(dev_priv)) { |
| 2603 | mutex_lock(&power_domains->lock); | 2601 | mutex_lock(&power_domains->lock); |
| 2604 | chv_phy_control_init(dev_priv); | 2602 | chv_phy_control_init(dev_priv); |
| 2605 | mutex_unlock(&power_domains->lock); | 2603 | mutex_unlock(&power_domains->lock); |
| 2606 | } else if (IS_VALLEYVIEW(dev)) { | 2604 | } else if (IS_VALLEYVIEW(dev_priv)) { |
| 2607 | mutex_lock(&power_domains->lock); | 2605 | mutex_lock(&power_domains->lock); |
| 2608 | vlv_cmnlane_wa(dev_priv); | 2606 | vlv_cmnlane_wa(dev_priv); |
| 2609 | mutex_unlock(&power_domains->lock); | 2607 | mutex_unlock(&power_domains->lock); |
| @@ -2758,7 +2756,6 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv) | |||
| 2758 | void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) | 2756 | void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) |
| 2759 | { | 2757 | { |
| 2760 | struct pci_dev *pdev = dev_priv->drm.pdev; | 2758 | struct pci_dev *pdev = dev_priv->drm.pdev; |
| 2761 | struct drm_device *dev = &dev_priv->drm; | ||
| 2762 | struct device *kdev = &pdev->dev; | 2759 | struct device *kdev = &pdev->dev; |
| 2763 | 2760 | ||
| 2764 | pm_runtime_set_autosuspend_delay(kdev, 10000); /* 10s */ | 2761 | pm_runtime_set_autosuspend_delay(kdev, 10000); /* 10s */ |
| @@ -2770,7 +2767,7 @@ void intel_runtime_pm_enable(struct drm_i915_private *dev_priv) | |||
| 2770 | * so the driver's own RPM reference tracking asserts also work on | 2767 | * so the driver's own RPM reference tracking asserts also work on |
| 2771 | * platforms without RPM support. | 2768 | * platforms without RPM support. |
| 2772 | */ | 2769 | */ |
| 2773 | if (!HAS_RUNTIME_PM(dev)) { | 2770 | if (!HAS_RUNTIME_PM(dev_priv)) { |
| 2774 | pm_runtime_dont_use_autosuspend(kdev); | 2771 | pm_runtime_dont_use_autosuspend(kdev); |
| 2775 | pm_runtime_get_sync(kdev); | 2772 | pm_runtime_get_sync(kdev); |
| 2776 | } else { | 2773 | } else { |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index c551024d4871..49fb95d03d74 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -251,7 +251,7 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val) | |||
| 251 | * HW workaround, need to write this twice for issue | 251 | * HW workaround, need to write this twice for issue |
| 252 | * that may result in first write getting masked. | 252 | * that may result in first write getting masked. |
| 253 | */ | 253 | */ |
| 254 | if (HAS_PCH_IBX(dev)) { | 254 | if (HAS_PCH_IBX(dev_priv)) { |
| 255 | I915_WRITE(intel_sdvo->sdvo_reg, val); | 255 | I915_WRITE(intel_sdvo->sdvo_reg, val); |
| 256 | POSTING_READ(intel_sdvo->sdvo_reg); | 256 | POSTING_READ(intel_sdvo->sdvo_reg); |
| 257 | } | 257 | } |
| @@ -307,7 +307,7 @@ static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch) | |||
| 307 | static const struct _sdvo_cmd_name { | 307 | static const struct _sdvo_cmd_name { |
| 308 | u8 cmd; | 308 | u8 cmd; |
| 309 | const char *name; | 309 | const char *name; |
| 310 | } sdvo_cmd_names[] = { | 310 | } __attribute__ ((packed)) sdvo_cmd_names[] = { |
| 311 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), | 311 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), |
| 312 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), | 312 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), |
| 313 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), | 313 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), |
| @@ -1133,7 +1133,7 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder, | |||
| 1133 | DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n"); | 1133 | DRM_DEBUG_KMS("forcing bpc to 8 for SDVO\n"); |
| 1134 | pipe_config->pipe_bpp = 8*3; | 1134 | pipe_config->pipe_bpp = 8*3; |
| 1135 | 1135 | ||
| 1136 | if (HAS_PCH_SPLIT(encoder->base.dev)) | 1136 | if (HAS_PCH_SPLIT(to_i915(encoder->base.dev))) |
| 1137 | pipe_config->has_pch_encoder = true; | 1137 | pipe_config->has_pch_encoder = true; |
| 1138 | 1138 | ||
| 1139 | /* We need to construct preferred input timings based on our | 1139 | /* We need to construct preferred input timings based on our |
| @@ -1273,7 +1273,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, | |||
| 1273 | /* The real mode polarity is set by the SDVO commands, using | 1273 | /* The real mode polarity is set by the SDVO commands, using |
| 1274 | * struct intel_sdvo_dtd. */ | 1274 | * struct intel_sdvo_dtd. */ |
| 1275 | sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH; | 1275 | sdvox = SDVO_VSYNC_ACTIVE_HIGH | SDVO_HSYNC_ACTIVE_HIGH; |
| 1276 | if (!HAS_PCH_SPLIT(dev) && crtc_state->limited_color_range) | 1276 | if (!HAS_PCH_SPLIT(dev_priv) && crtc_state->limited_color_range) |
| 1277 | sdvox |= HDMI_COLOR_RANGE_16_235; | 1277 | sdvox |= HDMI_COLOR_RANGE_16_235; |
| 1278 | if (INTEL_INFO(dev)->gen < 5) | 1278 | if (INTEL_INFO(dev)->gen < 5) |
| 1279 | sdvox |= SDVO_BORDER_ENABLE; | 1279 | sdvox |= SDVO_BORDER_ENABLE; |
| @@ -1286,7 +1286,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, | |||
| 1286 | sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; | 1286 | sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; |
| 1287 | } | 1287 | } |
| 1288 | 1288 | ||
| 1289 | if (INTEL_PCH_TYPE(dev) >= PCH_CPT) | 1289 | if (INTEL_PCH_TYPE(dev_priv) >= PCH_CPT) |
| 1290 | sdvox |= SDVO_PIPE_SEL_CPT(crtc->pipe); | 1290 | sdvox |= SDVO_PIPE_SEL_CPT(crtc->pipe); |
| 1291 | else | 1291 | else |
| 1292 | sdvox |= SDVO_PIPE_SEL(crtc->pipe); | 1292 | sdvox |= SDVO_PIPE_SEL(crtc->pipe); |
| @@ -1296,7 +1296,8 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder, | |||
| 1296 | 1296 | ||
| 1297 | if (INTEL_INFO(dev)->gen >= 4) { | 1297 | if (INTEL_INFO(dev)->gen >= 4) { |
| 1298 | /* done in crtc_mode_set as the dpll_md reg must be written early */ | 1298 | /* done in crtc_mode_set as the dpll_md reg must be written early */ |
| 1299 | } else if (IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev)) { | 1299 | } else if (IS_I945G(dev_priv) || IS_I945GM(dev_priv) || |
| 1300 | IS_G33(dev_priv)) { | ||
| 1300 | /* done in crtc_mode_set as it lives inside the dpll register */ | 1301 | /* done in crtc_mode_set as it lives inside the dpll register */ |
| 1301 | } else { | 1302 | } else { |
| 1302 | sdvox |= (crtc_state->pixel_multiplier - 1) | 1303 | sdvox |= (crtc_state->pixel_multiplier - 1) |
| @@ -1339,7 +1340,7 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder, | |||
| 1339 | if (!(tmp & SDVO_ENABLE) && (active_outputs == 0)) | 1340 | if (!(tmp & SDVO_ENABLE) && (active_outputs == 0)) |
| 1340 | return false; | 1341 | return false; |
| 1341 | 1342 | ||
| 1342 | if (HAS_PCH_CPT(dev)) | 1343 | if (HAS_PCH_CPT(dev_priv)) |
| 1343 | *pipe = PORT_TO_PIPE_CPT(tmp); | 1344 | *pipe = PORT_TO_PIPE_CPT(tmp); |
| 1344 | else | 1345 | else |
| 1345 | *pipe = PORT_TO_PIPE(tmp); | 1346 | *pipe = PORT_TO_PIPE(tmp); |
| @@ -1389,7 +1390,7 @@ static void intel_sdvo_get_config(struct intel_encoder *encoder, | |||
| 1389 | * encoder->get_config we so already have a valid pixel multplier on all | 1390 | * encoder->get_config we so already have a valid pixel multplier on all |
| 1390 | * other platfroms. | 1391 | * other platfroms. |
| 1391 | */ | 1392 | */ |
| 1392 | if (IS_I915G(dev) || IS_I915GM(dev)) { | 1393 | if (IS_I915G(dev_priv) || IS_I915GM(dev_priv)) { |
| 1393 | pipe_config->pixel_multiplier = | 1394 | pipe_config->pixel_multiplier = |
| 1394 | ((sdvox & SDVO_PORT_MULTIPLY_MASK) | 1395 | ((sdvox & SDVO_PORT_MULTIPLY_MASK) |
| 1395 | >> SDVO_PORT_MULTIPLY_SHIFT) + 1; | 1396 | >> SDVO_PORT_MULTIPLY_SHIFT) + 1; |
| @@ -1595,15 +1596,15 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in | |||
| 1595 | 1596 | ||
| 1596 | static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo) | 1597 | static uint16_t intel_sdvo_get_hotplug_support(struct intel_sdvo *intel_sdvo) |
| 1597 | { | 1598 | { |
| 1598 | struct drm_device *dev = intel_sdvo->base.base.dev; | 1599 | struct drm_i915_private *dev_priv = to_i915(intel_sdvo->base.base.dev); |
| 1599 | uint16_t hotplug; | 1600 | uint16_t hotplug; |
| 1600 | 1601 | ||
| 1601 | if (!I915_HAS_HOTPLUG(dev)) | 1602 | if (!I915_HAS_HOTPLUG(dev_priv)) |
| 1602 | return 0; | 1603 | return 0; |
| 1603 | 1604 | ||
| 1604 | /* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise | 1605 | /* HW Erratum: SDVO Hotplug is broken on all i945G chips, there's noise |
| 1605 | * on the line. */ | 1606 | * on the line. */ |
| 1606 | if (IS_I945G(dev) || IS_I945GM(dev)) | 1607 | if (IS_I945G(dev_priv) || IS_I945GM(dev_priv)) |
| 1607 | return 0; | 1608 | return 0; |
| 1608 | 1609 | ||
| 1609 | if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, | 1610 | if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, |
| @@ -2981,6 +2982,7 @@ bool intel_sdvo_init(struct drm_device *dev, | |||
| 2981 | /* encoder type will be decided later */ | 2982 | /* encoder type will be decided later */ |
| 2982 | intel_encoder = &intel_sdvo->base; | 2983 | intel_encoder = &intel_sdvo->base; |
| 2983 | intel_encoder->type = INTEL_OUTPUT_SDVO; | 2984 | intel_encoder->type = INTEL_OUTPUT_SDVO; |
| 2985 | intel_encoder->port = port; | ||
| 2984 | drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0, | 2986 | drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0, |
| 2985 | "SDVO %c", port_name(port)); | 2987 | "SDVO %c", port_name(port)); |
| 2986 | 2988 | ||
| @@ -2996,7 +2998,7 @@ bool intel_sdvo_init(struct drm_device *dev, | |||
| 2996 | } | 2998 | } |
| 2997 | 2999 | ||
| 2998 | intel_encoder->compute_config = intel_sdvo_compute_config; | 3000 | intel_encoder->compute_config = intel_sdvo_compute_config; |
| 2999 | if (HAS_PCH_SPLIT(dev)) { | 3001 | if (HAS_PCH_SPLIT(dev_priv)) { |
| 3000 | intel_encoder->disable = pch_disable_sdvo; | 3002 | intel_encoder->disable = pch_disable_sdvo; |
| 3001 | intel_encoder->post_disable = pch_post_disable_sdvo; | 3003 | intel_encoder->post_disable = pch_post_disable_sdvo; |
| 3002 | } else { | 3004 | } else { |
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 3ea6419e18b9..43d0350856e7 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
| @@ -208,6 +208,8 @@ skl_update_plane(struct drm_plane *drm_plane, | |||
| 208 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 208 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 209 | const int pipe = intel_plane->pipe; | 209 | const int pipe = intel_plane->pipe; |
| 210 | const int plane = intel_plane->plane + 1; | 210 | const int plane = intel_plane->plane + 1; |
| 211 | const struct skl_plane_wm *p_wm = | ||
| 212 | &crtc_state->wm.skl.optimal.planes[plane]; | ||
| 211 | u32 plane_ctl; | 213 | u32 plane_ctl; |
| 212 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; | 214 | const struct drm_intel_sprite_colorkey *key = &plane_state->ckey; |
| 213 | u32 surf_addr = plane_state->main.offset; | 215 | u32 surf_addr = plane_state->main.offset; |
| @@ -232,7 +234,7 @@ skl_update_plane(struct drm_plane *drm_plane, | |||
| 232 | plane_ctl |= skl_plane_ctl_rotation(rotation); | 234 | plane_ctl |= skl_plane_ctl_rotation(rotation); |
| 233 | 235 | ||
| 234 | if (wm->dirty_pipes & drm_crtc_mask(crtc)) | 236 | if (wm->dirty_pipes & drm_crtc_mask(crtc)) |
| 235 | skl_write_plane_wm(intel_crtc, wm, plane); | 237 | skl_write_plane_wm(intel_crtc, p_wm, &wm->ddb, plane); |
| 236 | 238 | ||
| 237 | if (key->flags) { | 239 | if (key->flags) { |
| 238 | I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value); | 240 | I915_WRITE(PLANE_KEYVAL(pipe, plane), key->min_value); |
| @@ -289,6 +291,7 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) | |||
| 289 | struct drm_device *dev = dplane->dev; | 291 | struct drm_device *dev = dplane->dev; |
| 290 | struct drm_i915_private *dev_priv = to_i915(dev); | 292 | struct drm_i915_private *dev_priv = to_i915(dev); |
| 291 | struct intel_plane *intel_plane = to_intel_plane(dplane); | 293 | struct intel_plane *intel_plane = to_intel_plane(dplane); |
| 294 | struct intel_crtc_state *cstate = to_intel_crtc_state(crtc->state); | ||
| 292 | const int pipe = intel_plane->pipe; | 295 | const int pipe = intel_plane->pipe; |
| 293 | const int plane = intel_plane->plane + 1; | 296 | const int plane = intel_plane->plane + 1; |
| 294 | 297 | ||
| @@ -298,7 +301,8 @@ skl_disable_plane(struct drm_plane *dplane, struct drm_crtc *crtc) | |||
| 298 | */ | 301 | */ |
| 299 | if (!dplane->state->visible) | 302 | if (!dplane->state->visible) |
| 300 | skl_write_plane_wm(to_intel_crtc(crtc), | 303 | skl_write_plane_wm(to_intel_crtc(crtc), |
| 301 | &dev_priv->wm.skl_results, plane); | 304 | &cstate->wm.skl.optimal.planes[plane], |
| 305 | &dev_priv->wm.skl_results.ddb, plane); | ||
| 302 | 306 | ||
| 303 | I915_WRITE(PLANE_CTL(pipe, plane), 0); | 307 | I915_WRITE(PLANE_CTL(pipe, plane), 0); |
| 304 | 308 | ||
| @@ -450,7 +454,7 @@ vlv_update_plane(struct drm_plane *dplane, | |||
| 450 | if (key->flags & I915_SET_COLORKEY_SOURCE) | 454 | if (key->flags & I915_SET_COLORKEY_SOURCE) |
| 451 | sprctl |= SP_SOURCE_KEY; | 455 | sprctl |= SP_SOURCE_KEY; |
| 452 | 456 | ||
| 453 | if (IS_CHERRYVIEW(dev) && pipe == PIPE_B) | 457 | if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) |
| 454 | chv_update_csc(intel_plane, fb->pixel_format); | 458 | chv_update_csc(intel_plane, fb->pixel_format); |
| 455 | 459 | ||
| 456 | I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); | 460 | I915_WRITE(SPSTRIDE(pipe, plane), fb->pitches[0]); |
| @@ -542,12 +546,12 @@ ivb_update_plane(struct drm_plane *plane, | |||
| 542 | if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) | 546 | if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) |
| 543 | sprctl |= SPRITE_TILED; | 547 | sprctl |= SPRITE_TILED; |
| 544 | 548 | ||
| 545 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 549 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 546 | sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; | 550 | sprctl &= ~SPRITE_TRICKLE_FEED_DISABLE; |
| 547 | else | 551 | else |
| 548 | sprctl |= SPRITE_TRICKLE_FEED_DISABLE; | 552 | sprctl |= SPRITE_TRICKLE_FEED_DISABLE; |
| 549 | 553 | ||
| 550 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 554 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 551 | sprctl |= SPRITE_PIPE_CSC_ENABLE; | 555 | sprctl |= SPRITE_PIPE_CSC_ENABLE; |
| 552 | 556 | ||
| 553 | /* Sizes are 0 based */ | 557 | /* Sizes are 0 based */ |
| @@ -566,7 +570,7 @@ ivb_update_plane(struct drm_plane *plane, | |||
| 566 | sprctl |= SPRITE_ROTATE_180; | 570 | sprctl |= SPRITE_ROTATE_180; |
| 567 | 571 | ||
| 568 | /* HSW and BDW does this automagically in hardware */ | 572 | /* HSW and BDW does this automagically in hardware */ |
| 569 | if (!IS_HASWELL(dev) && !IS_BROADWELL(dev)) { | 573 | if (!IS_HASWELL(dev_priv) && !IS_BROADWELL(dev_priv)) { |
| 570 | x += src_w; | 574 | x += src_w; |
| 571 | y += src_h; | 575 | y += src_h; |
| 572 | } | 576 | } |
| @@ -590,7 +594,7 @@ ivb_update_plane(struct drm_plane *plane, | |||
| 590 | 594 | ||
| 591 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET | 595 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET |
| 592 | * register */ | 596 | * register */ |
| 593 | if (IS_HASWELL(dev) || IS_BROADWELL(dev)) | 597 | if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) |
| 594 | I915_WRITE(SPROFFSET(pipe), (y << 16) | x); | 598 | I915_WRITE(SPROFFSET(pipe), (y << 16) | x); |
| 595 | else if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) | 599 | else if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) |
| 596 | I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); | 600 | I915_WRITE(SPRTILEOFF(pipe), (y << 16) | x); |
| @@ -680,7 +684,7 @@ ilk_update_plane(struct drm_plane *plane, | |||
| 680 | if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) | 684 | if (fb->modifier[0] == I915_FORMAT_MOD_X_TILED) |
| 681 | dvscntr |= DVS_TILED; | 685 | dvscntr |= DVS_TILED; |
| 682 | 686 | ||
| 683 | if (IS_GEN6(dev)) | 687 | if (IS_GEN6(dev_priv)) |
| 684 | dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */ | 688 | dvscntr |= DVS_TRICKLE_FEED_DISABLE; /* must disable */ |
| 685 | 689 | ||
| 686 | /* Sizes are 0 based */ | 690 | /* Sizes are 0 based */ |
| @@ -753,7 +757,7 @@ intel_check_sprite_plane(struct drm_plane *plane, | |||
| 753 | struct intel_crtc_state *crtc_state, | 757 | struct intel_crtc_state *crtc_state, |
| 754 | struct intel_plane_state *state) | 758 | struct intel_plane_state *state) |
| 755 | { | 759 | { |
| 756 | struct drm_device *dev = plane->dev; | 760 | struct drm_i915_private *dev_priv = to_i915(plane->dev); |
| 757 | struct drm_crtc *crtc = state->base.crtc; | 761 | struct drm_crtc *crtc = state->base.crtc; |
| 758 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 762 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
| 759 | struct intel_plane *intel_plane = to_intel_plane(plane); | 763 | struct intel_plane *intel_plane = to_intel_plane(plane); |
| @@ -797,7 +801,7 @@ intel_check_sprite_plane(struct drm_plane *plane, | |||
| 797 | } | 801 | } |
| 798 | 802 | ||
| 799 | /* setup can_scale, min_scale, max_scale */ | 803 | /* setup can_scale, min_scale, max_scale */ |
| 800 | if (INTEL_INFO(dev)->gen >= 9) { | 804 | if (INTEL_GEN(dev_priv) >= 9) { |
| 801 | /* use scaler when colorkey is not required */ | 805 | /* use scaler when colorkey is not required */ |
| 802 | if (state->ckey.flags == I915_SET_COLORKEY_NONE) { | 806 | if (state->ckey.flags == I915_SET_COLORKEY_NONE) { |
| 803 | can_scale = 1; | 807 | can_scale = 1; |
| @@ -913,7 +917,7 @@ intel_check_sprite_plane(struct drm_plane *plane, | |||
| 913 | 917 | ||
| 914 | width_bytes = ((src_x * cpp) & 63) + src_w * cpp; | 918 | width_bytes = ((src_x * cpp) & 63) + src_w * cpp; |
| 915 | 919 | ||
| 916 | if (INTEL_INFO(dev)->gen < 9 && (src_w > 2048 || src_h > 2048 || | 920 | if (INTEL_GEN(dev_priv) < 9 && (src_w > 2048 || src_h > 2048 || |
| 917 | width_bytes > 4096 || fb->pitches[0] > 4096)) { | 921 | width_bytes > 4096 || fb->pitches[0] > 4096)) { |
| 918 | DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); | 922 | DRM_DEBUG_KMS("Source dimensions exceed hardware limits\n"); |
| 919 | return -EINVAL; | 923 | return -EINVAL; |
| @@ -932,7 +936,7 @@ intel_check_sprite_plane(struct drm_plane *plane, | |||
| 932 | dst->y1 = crtc_y; | 936 | dst->y1 = crtc_y; |
| 933 | dst->y2 = crtc_y + crtc_h; | 937 | dst->y2 = crtc_y + crtc_h; |
| 934 | 938 | ||
| 935 | if (INTEL_GEN(dev) >= 9) { | 939 | if (INTEL_GEN(dev_priv) >= 9) { |
| 936 | ret = skl_check_plane_surface(state); | 940 | ret = skl_check_plane_surface(state); |
| 937 | if (ret) | 941 | if (ret) |
| 938 | return ret; | 942 | return ret; |
| @@ -944,6 +948,7 @@ intel_check_sprite_plane(struct drm_plane *plane, | |||
| 944 | int intel_sprite_set_colorkey(struct drm_device *dev, void *data, | 948 | int intel_sprite_set_colorkey(struct drm_device *dev, void *data, |
| 945 | struct drm_file *file_priv) | 949 | struct drm_file *file_priv) |
| 946 | { | 950 | { |
| 951 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 947 | struct drm_intel_sprite_colorkey *set = data; | 952 | struct drm_intel_sprite_colorkey *set = data; |
| 948 | struct drm_plane *plane; | 953 | struct drm_plane *plane; |
| 949 | struct drm_plane_state *plane_state; | 954 | struct drm_plane_state *plane_state; |
| @@ -955,7 +960,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, | |||
| 955 | if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) | 960 | if ((set->flags & (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) == (I915_SET_COLORKEY_DESTINATION | I915_SET_COLORKEY_SOURCE)) |
| 956 | return -EINVAL; | 961 | return -EINVAL; |
| 957 | 962 | ||
| 958 | if ((IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) && | 963 | if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && |
| 959 | set->flags & I915_SET_COLORKEY_DESTINATION) | 964 | set->flags & I915_SET_COLORKEY_DESTINATION) |
| 960 | return -EINVAL; | 965 | return -EINVAL; |
| 961 | 966 | ||
| @@ -1040,6 +1045,7 @@ static uint32_t skl_plane_formats[] = { | |||
| 1040 | int | 1045 | int |
| 1041 | intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) | 1046 | intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) |
| 1042 | { | 1047 | { |
| 1048 | struct drm_i915_private *dev_priv = to_i915(dev); | ||
| 1043 | struct intel_plane *intel_plane = NULL; | 1049 | struct intel_plane *intel_plane = NULL; |
| 1044 | struct intel_plane_state *state = NULL; | 1050 | struct intel_plane_state *state = NULL; |
| 1045 | unsigned long possible_crtcs; | 1051 | unsigned long possible_crtcs; |
| @@ -1072,7 +1078,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) | |||
| 1072 | intel_plane->update_plane = ilk_update_plane; | 1078 | intel_plane->update_plane = ilk_update_plane; |
| 1073 | intel_plane->disable_plane = ilk_disable_plane; | 1079 | intel_plane->disable_plane = ilk_disable_plane; |
| 1074 | 1080 | ||
| 1075 | if (IS_GEN6(dev)) { | 1081 | if (IS_GEN6(dev_priv)) { |
| 1076 | plane_formats = snb_plane_formats; | 1082 | plane_formats = snb_plane_formats; |
| 1077 | num_plane_formats = ARRAY_SIZE(snb_plane_formats); | 1083 | num_plane_formats = ARRAY_SIZE(snb_plane_formats); |
| 1078 | } else { | 1084 | } else { |
| @@ -1083,7 +1089,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) | |||
| 1083 | 1089 | ||
| 1084 | case 7: | 1090 | case 7: |
| 1085 | case 8: | 1091 | case 8: |
| 1086 | if (IS_IVYBRIDGE(dev)) { | 1092 | if (IS_IVYBRIDGE(dev_priv)) { |
| 1087 | intel_plane->can_scale = true; | 1093 | intel_plane->can_scale = true; |
| 1088 | intel_plane->max_downscale = 2; | 1094 | intel_plane->max_downscale = 2; |
| 1089 | } else { | 1095 | } else { |
| @@ -1091,7 +1097,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) | |||
| 1091 | intel_plane->max_downscale = 1; | 1097 | intel_plane->max_downscale = 1; |
| 1092 | } | 1098 | } |
| 1093 | 1099 | ||
| 1094 | if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) { | 1100 | if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { |
| 1095 | intel_plane->update_plane = vlv_update_plane; | 1101 | intel_plane->update_plane = vlv_update_plane; |
| 1096 | intel_plane->disable_plane = vlv_disable_plane; | 1102 | intel_plane->disable_plane = vlv_disable_plane; |
| 1097 | 1103 | ||
| @@ -1120,7 +1126,7 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane) | |||
| 1120 | goto fail; | 1126 | goto fail; |
| 1121 | } | 1127 | } |
| 1122 | 1128 | ||
| 1123 | if (INTEL_GEN(dev) >= 9) { | 1129 | if (INTEL_GEN(dev_priv) >= 9) { |
| 1124 | supported_rotations = | 1130 | supported_rotations = |
| 1125 | DRM_ROTATE_0 | DRM_ROTATE_90 | | 1131 | DRM_ROTATE_0 | DRM_ROTATE_90 | |
| 1126 | DRM_ROTATE_180 | DRM_ROTATE_270; | 1132 | DRM_ROTATE_180 | DRM_ROTATE_270; |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index d960e4866595..7118fb55f57f 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
| @@ -86,7 +86,8 @@ struct intel_tv { | |||
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | struct video_levels { | 88 | struct video_levels { |
| 89 | int blank, black, burst; | 89 | u16 blank, black; |
| 90 | u8 burst; | ||
| 90 | }; | 91 | }; |
| 91 | 92 | ||
| 92 | struct color_conversion { | 93 | struct color_conversion { |
| @@ -339,34 +340,43 @@ static const struct video_levels component_levels = { | |||
| 339 | 340 | ||
| 340 | struct tv_mode { | 341 | struct tv_mode { |
| 341 | const char *name; | 342 | const char *name; |
| 342 | int clock; | 343 | |
| 343 | int refresh; /* in millihertz (for precision) */ | 344 | u32 clock; |
| 345 | u16 refresh; /* in millihertz (for precision) */ | ||
| 344 | u32 oversample; | 346 | u32 oversample; |
| 345 | int hsync_end, hblank_start, hblank_end, htotal; | 347 | u8 hsync_end; |
| 346 | bool progressive, trilevel_sync, component_only; | 348 | u16 hblank_start, hblank_end, htotal; |
| 347 | int vsync_start_f1, vsync_start_f2, vsync_len; | 349 | bool progressive : 1, trilevel_sync : 1, component_only : 1; |
| 348 | bool veq_ena; | 350 | u8 vsync_start_f1, vsync_start_f2, vsync_len; |
| 349 | int veq_start_f1, veq_start_f2, veq_len; | 351 | bool veq_ena : 1; |
| 350 | int vi_end_f1, vi_end_f2, nbr_end; | 352 | u8 veq_start_f1, veq_start_f2, veq_len; |
| 351 | bool burst_ena; | 353 | u8 vi_end_f1, vi_end_f2; |
| 352 | int hburst_start, hburst_len; | 354 | u16 nbr_end; |
| 353 | int vburst_start_f1, vburst_end_f1; | 355 | bool burst_ena : 1; |
| 354 | int vburst_start_f2, vburst_end_f2; | 356 | u8 hburst_start, hburst_len; |
| 355 | int vburst_start_f3, vburst_end_f3; | 357 | u8 vburst_start_f1; |
| 356 | int vburst_start_f4, vburst_end_f4; | 358 | u16 vburst_end_f1; |
| 359 | u8 vburst_start_f2; | ||
| 360 | u16 vburst_end_f2; | ||
| 361 | u8 vburst_start_f3; | ||
| 362 | u16 vburst_end_f3; | ||
| 363 | u8 vburst_start_f4; | ||
| 364 | u16 vburst_end_f4; | ||
| 357 | /* | 365 | /* |
| 358 | * subcarrier programming | 366 | * subcarrier programming |
| 359 | */ | 367 | */ |
| 360 | int dda2_size, dda3_size, dda1_inc, dda2_inc, dda3_inc; | 368 | u16 dda2_size, dda3_size; |
| 369 | u8 dda1_inc; | ||
| 370 | u16 dda2_inc, dda3_inc; | ||
| 361 | u32 sc_reset; | 371 | u32 sc_reset; |
| 362 | bool pal_burst; | 372 | bool pal_burst : 1; |
| 363 | /* | 373 | /* |
| 364 | * blank/black levels | 374 | * blank/black levels |
| 365 | */ | 375 | */ |
| 366 | const struct video_levels *composite_levels, *svideo_levels; | 376 | const struct video_levels *composite_levels, *svideo_levels; |
| 367 | const struct color_conversion *composite_color, *svideo_color; | 377 | const struct color_conversion *composite_color, *svideo_color; |
| 368 | const u32 *filter_table; | 378 | const u32 *filter_table; |
| 369 | int max_srcw; | 379 | u16 max_srcw; |
| 370 | }; | 380 | }; |
| 371 | 381 | ||
| 372 | 382 | ||
| @@ -1095,7 +1105,7 @@ static void intel_tv_pre_enable(struct intel_encoder *encoder, | |||
| 1095 | tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT; | 1105 | tv_mode->dda3_inc << TV_SCDDA3_INC_SHIFT; |
| 1096 | 1106 | ||
| 1097 | /* Enable two fixes for the chips that need them. */ | 1107 | /* Enable two fixes for the chips that need them. */ |
| 1098 | if (IS_I915GM(dev)) | 1108 | if (IS_I915GM(dev_priv)) |
| 1099 | tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX; | 1109 | tv_ctl |= TV_ENC_C0_FIX | TV_ENC_SDP_FIX; |
| 1100 | 1110 | ||
| 1101 | set_tv_mode_timings(dev_priv, tv_mode, burst_ena); | 1111 | set_tv_mode_timings(dev_priv, tv_mode, burst_ena); |
| @@ -1220,7 +1230,7 @@ intel_tv_detect_type(struct intel_tv *intel_tv, | |||
| 1220 | * The TV sense state should be cleared to zero on cantiga platform. Otherwise | 1230 | * The TV sense state should be cleared to zero on cantiga platform. Otherwise |
| 1221 | * the TV is misdetected. This is hardware requirement. | 1231 | * the TV is misdetected. This is hardware requirement. |
| 1222 | */ | 1232 | */ |
| 1223 | if (IS_GM45(dev)) | 1233 | if (IS_GM45(dev_priv)) |
| 1224 | tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL | | 1234 | tv_dac &= ~(TVDAC_STATE_CHG_EN | TVDAC_A_SENSE_CTL | |
| 1225 | TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL); | 1235 | TVDAC_B_SENSE_CTL | TVDAC_C_SENSE_CTL); |
| 1226 | 1236 | ||
| @@ -1610,7 +1620,9 @@ intel_tv_init(struct drm_device *dev) | |||
| 1610 | intel_connector->get_hw_state = intel_connector_get_hw_state; | 1620 | intel_connector->get_hw_state = intel_connector_get_hw_state; |
| 1611 | 1621 | ||
| 1612 | intel_connector_attach_encoder(intel_connector, intel_encoder); | 1622 | intel_connector_attach_encoder(intel_connector, intel_encoder); |
| 1623 | |||
| 1613 | intel_encoder->type = INTEL_OUTPUT_TVOUT; | 1624 | intel_encoder->type = INTEL_OUTPUT_TVOUT; |
| 1625 | intel_encoder->port = PORT_NONE; | ||
| 1614 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); | 1626 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); |
| 1615 | intel_encoder->cloneable = 0; | 1627 | intel_encoder->cloneable = 0; |
| 1616 | intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1)); | 1628 | intel_encoder->base.possible_crtcs = ((1 << 0) | (1 << 1)); |
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index a9b6c936aadd..e2b188dcf908 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c | |||
| @@ -231,19 +231,21 @@ intel_uncore_fw_release_timer(struct hrtimer *timer) | |||
| 231 | { | 231 | { |
| 232 | struct intel_uncore_forcewake_domain *domain = | 232 | struct intel_uncore_forcewake_domain *domain = |
| 233 | container_of(timer, struct intel_uncore_forcewake_domain, timer); | 233 | container_of(timer, struct intel_uncore_forcewake_domain, timer); |
| 234 | struct drm_i915_private *dev_priv = domain->i915; | ||
| 234 | unsigned long irqflags; | 235 | unsigned long irqflags; |
| 235 | 236 | ||
| 236 | assert_rpm_device_not_suspended(domain->i915); | 237 | assert_rpm_device_not_suspended(dev_priv); |
| 237 | 238 | ||
| 238 | spin_lock_irqsave(&domain->i915->uncore.lock, irqflags); | 239 | spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); |
| 239 | if (WARN_ON(domain->wake_count == 0)) | 240 | if (WARN_ON(domain->wake_count == 0)) |
| 240 | domain->wake_count++; | 241 | domain->wake_count++; |
| 241 | 242 | ||
| 242 | if (--domain->wake_count == 0) | 243 | if (--domain->wake_count == 0) { |
| 243 | domain->i915->uncore.funcs.force_wake_put(domain->i915, | 244 | dev_priv->uncore.funcs.force_wake_put(dev_priv, domain->mask); |
| 244 | 1 << domain->id); | 245 | dev_priv->uncore.fw_domains_active &= ~domain->mask; |
| 246 | } | ||
| 245 | 247 | ||
| 246 | spin_unlock_irqrestore(&domain->i915->uncore.lock, irqflags); | 248 | spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); |
| 247 | 249 | ||
| 248 | return HRTIMER_NORESTART; | 250 | return HRTIMER_NORESTART; |
| 249 | } | 251 | } |
| @@ -254,7 +256,7 @@ void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv, | |||
| 254 | unsigned long irqflags; | 256 | unsigned long irqflags; |
| 255 | struct intel_uncore_forcewake_domain *domain; | 257 | struct intel_uncore_forcewake_domain *domain; |
| 256 | int retry_count = 100; | 258 | int retry_count = 100; |
| 257 | enum forcewake_domains fw = 0, active_domains; | 259 | enum forcewake_domains fw, active_domains; |
| 258 | 260 | ||
| 259 | /* Hold uncore.lock across reset to prevent any register access | 261 | /* Hold uncore.lock across reset to prevent any register access |
| 260 | * with forcewake not set correctly. Wait until all pending | 262 | * with forcewake not set correctly. Wait until all pending |
| @@ -291,10 +293,7 @@ void intel_uncore_forcewake_reset(struct drm_i915_private *dev_priv, | |||
| 291 | 293 | ||
| 292 | WARN_ON(active_domains); | 294 | WARN_ON(active_domains); |
| 293 | 295 | ||
| 294 | for_each_fw_domain(domain, dev_priv) | 296 | fw = dev_priv->uncore.fw_domains_active; |
| 295 | if (domain->wake_count) | ||
| 296 | fw |= domain->mask; | ||
| 297 | |||
| 298 | if (fw) | 297 | if (fw) |
| 299 | dev_priv->uncore.funcs.force_wake_put(dev_priv, fw); | 298 | dev_priv->uncore.funcs.force_wake_put(dev_priv, fw); |
| 300 | 299 | ||
| @@ -443,9 +442,6 @@ static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, | |||
| 443 | { | 442 | { |
| 444 | struct intel_uncore_forcewake_domain *domain; | 443 | struct intel_uncore_forcewake_domain *domain; |
| 445 | 444 | ||
| 446 | if (!dev_priv->uncore.funcs.force_wake_get) | ||
| 447 | return; | ||
| 448 | |||
| 449 | fw_domains &= dev_priv->uncore.fw_domains; | 445 | fw_domains &= dev_priv->uncore.fw_domains; |
| 450 | 446 | ||
| 451 | for_each_fw_domain_masked(domain, fw_domains, dev_priv) { | 447 | for_each_fw_domain_masked(domain, fw_domains, dev_priv) { |
| @@ -453,8 +449,10 @@ static void __intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, | |||
| 453 | fw_domains &= ~domain->mask; | 449 | fw_domains &= ~domain->mask; |
| 454 | } | 450 | } |
| 455 | 451 | ||
| 456 | if (fw_domains) | 452 | if (fw_domains) { |
| 457 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); | 453 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); |
| 454 | dev_priv->uncore.fw_domains_active |= fw_domains; | ||
| 455 | } | ||
| 458 | } | 456 | } |
| 459 | 457 | ||
| 460 | /** | 458 | /** |
| @@ -509,9 +507,6 @@ static void __intel_uncore_forcewake_put(struct drm_i915_private *dev_priv, | |||
| 509 | { | 507 | { |
| 510 | struct intel_uncore_forcewake_domain *domain; | 508 | struct intel_uncore_forcewake_domain *domain; |
| 511 | 509 | ||
| 512 | if (!dev_priv->uncore.funcs.force_wake_put) | ||
| 513 | return; | ||
| 514 | |||
| 515 | fw_domains &= dev_priv->uncore.fw_domains; | 510 | fw_domains &= dev_priv->uncore.fw_domains; |
| 516 | 511 | ||
| 517 | for_each_fw_domain_masked(domain, fw_domains, dev_priv) { | 512 | for_each_fw_domain_masked(domain, fw_domains, dev_priv) { |
| @@ -567,13 +562,10 @@ void intel_uncore_forcewake_put__locked(struct drm_i915_private *dev_priv, | |||
| 567 | 562 | ||
| 568 | void assert_forcewakes_inactive(struct drm_i915_private *dev_priv) | 563 | void assert_forcewakes_inactive(struct drm_i915_private *dev_priv) |
| 569 | { | 564 | { |
| 570 | struct intel_uncore_forcewake_domain *domain; | ||
| 571 | |||
| 572 | if (!dev_priv->uncore.funcs.force_wake_get) | 565 | if (!dev_priv->uncore.funcs.force_wake_get) |
| 573 | return; | 566 | return; |
| 574 | 567 | ||
| 575 | for_each_fw_domain(domain, dev_priv) | 568 | WARN_ON(dev_priv->uncore.fw_domains_active); |
| 576 | WARN_ON(domain->wake_count); | ||
| 577 | } | 569 | } |
| 578 | 570 | ||
| 579 | /* We give fast paths for the really cool registers */ | 571 | /* We give fast paths for the really cool registers */ |
| @@ -589,49 +581,146 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv) | |||
| 589 | __fwd; \ | 581 | __fwd; \ |
| 590 | }) | 582 | }) |
| 591 | 583 | ||
| 592 | #define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end)) | 584 | static int fw_range_cmp(u32 offset, const struct intel_forcewake_range *entry) |
| 585 | { | ||
| 586 | if (offset < entry->start) | ||
| 587 | return -1; | ||
| 588 | else if (offset > entry->end) | ||
| 589 | return 1; | ||
| 590 | else | ||
| 591 | return 0; | ||
| 592 | } | ||
| 593 | |||
| 594 | /* Copied and "macroized" from lib/bsearch.c */ | ||
| 595 | #define BSEARCH(key, base, num, cmp) ({ \ | ||
| 596 | unsigned int start__ = 0, end__ = (num); \ | ||
| 597 | typeof(base) result__ = NULL; \ | ||
| 598 | while (start__ < end__) { \ | ||
| 599 | unsigned int mid__ = start__ + (end__ - start__) / 2; \ | ||
| 600 | int ret__ = (cmp)((key), (base) + mid__); \ | ||
| 601 | if (ret__ < 0) { \ | ||
| 602 | end__ = mid__; \ | ||
| 603 | } else if (ret__ > 0) { \ | ||
| 604 | start__ = mid__ + 1; \ | ||
| 605 | } else { \ | ||
| 606 | result__ = (base) + mid__; \ | ||
| 607 | break; \ | ||
| 608 | } \ | ||
| 609 | } \ | ||
| 610 | result__; \ | ||
| 611 | }) | ||
| 612 | |||
| 613 | static enum forcewake_domains | ||
| 614 | find_fw_domain(struct drm_i915_private *dev_priv, u32 offset) | ||
| 615 | { | ||
| 616 | const struct intel_forcewake_range *entry; | ||
| 617 | |||
| 618 | entry = BSEARCH(offset, | ||
| 619 | dev_priv->uncore.fw_domains_table, | ||
| 620 | dev_priv->uncore.fw_domains_table_entries, | ||
| 621 | fw_range_cmp); | ||
| 593 | 622 | ||
| 594 | #define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \ | 623 | return entry ? entry->domains : 0; |
| 595 | (REG_RANGE((reg), 0x2000, 0x4000) || \ | 624 | } |
| 596 | REG_RANGE((reg), 0x5000, 0x8000) || \ | 625 | |
| 597 | REG_RANGE((reg), 0xB000, 0x12000) || \ | 626 | static void |
| 598 | REG_RANGE((reg), 0x2E000, 0x30000)) | 627 | intel_fw_table_check(struct drm_i915_private *dev_priv) |
| 628 | { | ||
| 629 | const struct intel_forcewake_range *ranges; | ||
| 630 | unsigned int num_ranges; | ||
| 631 | s32 prev; | ||
| 632 | unsigned int i; | ||
| 633 | |||
| 634 | if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG)) | ||
| 635 | return; | ||
| 636 | |||
| 637 | ranges = dev_priv->uncore.fw_domains_table; | ||
| 638 | if (!ranges) | ||
| 639 | return; | ||
| 640 | |||
| 641 | num_ranges = dev_priv->uncore.fw_domains_table_entries; | ||
| 642 | |||
| 643 | for (i = 0, prev = -1; i < num_ranges; i++, ranges++) { | ||
| 644 | WARN_ON_ONCE(prev >= (s32)ranges->start); | ||
| 645 | prev = ranges->start; | ||
| 646 | WARN_ON_ONCE(prev >= (s32)ranges->end); | ||
| 647 | prev = ranges->end; | ||
| 648 | } | ||
| 649 | } | ||
| 599 | 650 | ||
| 600 | #define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg) \ | 651 | #define GEN_FW_RANGE(s, e, d) \ |
| 601 | (REG_RANGE((reg), 0x12000, 0x14000) || \ | 652 | { .start = (s), .end = (e), .domains = (d) } |
| 602 | REG_RANGE((reg), 0x22000, 0x24000) || \ | ||
| 603 | REG_RANGE((reg), 0x30000, 0x40000)) | ||
| 604 | 653 | ||
| 605 | #define __vlv_reg_read_fw_domains(offset) \ | 654 | #define HAS_FWTABLE(dev_priv) \ |
| 655 | (IS_GEN9(dev_priv) || \ | ||
| 656 | IS_CHERRYVIEW(dev_priv) || \ | ||
| 657 | IS_VALLEYVIEW(dev_priv)) | ||
| 658 | |||
| 659 | /* *Must* be sorted by offset ranges! See intel_fw_table_check(). */ | ||
| 660 | static const struct intel_forcewake_range __vlv_fw_ranges[] = { | ||
| 661 | GEN_FW_RANGE(0x2000, 0x3fff, FORCEWAKE_RENDER), | ||
| 662 | GEN_FW_RANGE(0x5000, 0x7fff, FORCEWAKE_RENDER), | ||
| 663 | GEN_FW_RANGE(0xb000, 0x11fff, FORCEWAKE_RENDER), | ||
| 664 | GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA), | ||
| 665 | GEN_FW_RANGE(0x22000, 0x23fff, FORCEWAKE_MEDIA), | ||
| 666 | GEN_FW_RANGE(0x2e000, 0x2ffff, FORCEWAKE_RENDER), | ||
| 667 | GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA), | ||
| 668 | }; | ||
| 669 | |||
| 670 | #define __fwtable_reg_read_fw_domains(offset) \ | ||
| 606 | ({ \ | 671 | ({ \ |
| 607 | enum forcewake_domains __fwd = 0; \ | 672 | enum forcewake_domains __fwd = 0; \ |
| 608 | if (!NEEDS_FORCE_WAKE(offset)) \ | 673 | if (NEEDS_FORCE_WAKE((offset))) \ |
| 609 | __fwd = 0; \ | 674 | __fwd = find_fw_domain(dev_priv, offset); \ |
| 610 | else if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(offset)) \ | ||
| 611 | __fwd = FORCEWAKE_RENDER; \ | ||
| 612 | else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(offset)) \ | ||
| 613 | __fwd = FORCEWAKE_MEDIA; \ | ||
| 614 | __fwd; \ | 675 | __fwd; \ |
| 615 | }) | 676 | }) |
| 616 | 677 | ||
| 678 | /* *Must* be sorted by offset! See intel_shadow_table_check(). */ | ||
| 617 | static const i915_reg_t gen8_shadowed_regs[] = { | 679 | static const i915_reg_t gen8_shadowed_regs[] = { |
| 618 | GEN6_RPNSWREQ, | 680 | RING_TAIL(RENDER_RING_BASE), /* 0x2000 (base) */ |
| 619 | GEN6_RC_VIDEO_FREQ, | 681 | GEN6_RPNSWREQ, /* 0xA008 */ |
| 620 | RING_TAIL(RENDER_RING_BASE), | 682 | GEN6_RC_VIDEO_FREQ, /* 0xA00C */ |
| 621 | RING_TAIL(GEN6_BSD_RING_BASE), | 683 | RING_TAIL(GEN6_BSD_RING_BASE), /* 0x12000 (base) */ |
| 622 | RING_TAIL(VEBOX_RING_BASE), | 684 | RING_TAIL(VEBOX_RING_BASE), /* 0x1a000 (base) */ |
| 623 | RING_TAIL(BLT_RING_BASE), | 685 | RING_TAIL(BLT_RING_BASE), /* 0x22000 (base) */ |
| 624 | /* TODO: Other registers are not yet used */ | 686 | /* TODO: Other registers are not yet used */ |
| 625 | }; | 687 | }; |
| 626 | 688 | ||
| 689 | static void intel_shadow_table_check(void) | ||
| 690 | { | ||
| 691 | const i915_reg_t *reg = gen8_shadowed_regs; | ||
| 692 | s32 prev; | ||
| 693 | u32 offset; | ||
| 694 | unsigned int i; | ||
| 695 | |||
| 696 | if (!IS_ENABLED(CONFIG_DRM_I915_DEBUG)) | ||
| 697 | return; | ||
| 698 | |||
| 699 | for (i = 0, prev = -1; i < ARRAY_SIZE(gen8_shadowed_regs); i++, reg++) { | ||
| 700 | offset = i915_mmio_reg_offset(*reg); | ||
| 701 | WARN_ON_ONCE(prev >= (s32)offset); | ||
| 702 | prev = offset; | ||
| 703 | } | ||
| 704 | } | ||
| 705 | |||
| 706 | static int mmio_reg_cmp(u32 key, const i915_reg_t *reg) | ||
| 707 | { | ||
| 708 | u32 offset = i915_mmio_reg_offset(*reg); | ||
| 709 | |||
| 710 | if (key < offset) | ||
| 711 | return -1; | ||
| 712 | else if (key > offset) | ||
| 713 | return 1; | ||
| 714 | else | ||
| 715 | return 0; | ||
| 716 | } | ||
| 717 | |||
| 627 | static bool is_gen8_shadowed(u32 offset) | 718 | static bool is_gen8_shadowed(u32 offset) |
| 628 | { | 719 | { |
| 629 | int i; | 720 | const i915_reg_t *regs = gen8_shadowed_regs; |
| 630 | for (i = 0; i < ARRAY_SIZE(gen8_shadowed_regs); i++) | ||
| 631 | if (offset == gen8_shadowed_regs[i].reg) | ||
| 632 | return true; | ||
| 633 | 721 | ||
| 634 | return false; | 722 | return BSEARCH(offset, regs, ARRAY_SIZE(gen8_shadowed_regs), |
| 723 | mmio_reg_cmp); | ||
| 635 | } | 724 | } |
| 636 | 725 | ||
| 637 | #define __gen8_reg_write_fw_domains(offset) \ | 726 | #define __gen8_reg_write_fw_domains(offset) \ |
| @@ -644,143 +733,70 @@ static bool is_gen8_shadowed(u32 offset) | |||
| 644 | __fwd; \ | 733 | __fwd; \ |
| 645 | }) | 734 | }) |
| 646 | 735 | ||
| 647 | #define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \ | 736 | /* *Must* be sorted by offset ranges! See intel_fw_table_check(). */ |
| 648 | (REG_RANGE((reg), 0x2000, 0x4000) || \ | 737 | static const struct intel_forcewake_range __chv_fw_ranges[] = { |
| 649 | REG_RANGE((reg), 0x5200, 0x8000) || \ | 738 | GEN_FW_RANGE(0x2000, 0x3fff, FORCEWAKE_RENDER), |
| 650 | REG_RANGE((reg), 0x8300, 0x8500) || \ | 739 | GEN_FW_RANGE(0x4000, 0x4fff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), |
| 651 | REG_RANGE((reg), 0xB000, 0xB480) || \ | 740 | GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), |
| 652 | REG_RANGE((reg), 0xE000, 0xE800)) | 741 | GEN_FW_RANGE(0x8000, 0x82ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), |
| 653 | 742 | GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER), | |
| 654 | #define FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg) \ | 743 | GEN_FW_RANGE(0x8500, 0x85ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), |
| 655 | (REG_RANGE((reg), 0x8800, 0x8900) || \ | 744 | GEN_FW_RANGE(0x8800, 0x88ff, FORCEWAKE_MEDIA), |
| 656 | REG_RANGE((reg), 0xD000, 0xD800) || \ | 745 | GEN_FW_RANGE(0x9000, 0xafff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), |
| 657 | REG_RANGE((reg), 0x12000, 0x14000) || \ | 746 | GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER), |
| 658 | REG_RANGE((reg), 0x1A000, 0x1C000) || \ | 747 | GEN_FW_RANGE(0xd000, 0xd7ff, FORCEWAKE_MEDIA), |
| 659 | REG_RANGE((reg), 0x1E800, 0x1EA00) || \ | 748 | GEN_FW_RANGE(0xe000, 0xe7ff, FORCEWAKE_RENDER), |
| 660 | REG_RANGE((reg), 0x30000, 0x38000)) | 749 | GEN_FW_RANGE(0xf000, 0xffff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), |
| 661 | 750 | GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA), | |
| 662 | #define FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg) \ | 751 | GEN_FW_RANGE(0x1a000, 0x1bfff, FORCEWAKE_MEDIA), |
| 663 | (REG_RANGE((reg), 0x4000, 0x5000) || \ | 752 | GEN_FW_RANGE(0x1e800, 0x1e9ff, FORCEWAKE_MEDIA), |
| 664 | REG_RANGE((reg), 0x8000, 0x8300) || \ | 753 | GEN_FW_RANGE(0x30000, 0x37fff, FORCEWAKE_MEDIA), |
| 665 | REG_RANGE((reg), 0x8500, 0x8600) || \ | 754 | }; |
| 666 | REG_RANGE((reg), 0x9000, 0xB000) || \ | ||
| 667 | REG_RANGE((reg), 0xF000, 0x10000)) | ||
| 668 | |||
| 669 | #define __chv_reg_read_fw_domains(offset) \ | ||
| 670 | ({ \ | ||
| 671 | enum forcewake_domains __fwd = 0; \ | ||
| 672 | if (!NEEDS_FORCE_WAKE(offset)) \ | ||
| 673 | __fwd = 0; \ | ||
| 674 | else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \ | ||
| 675 | __fwd = FORCEWAKE_RENDER; \ | ||
| 676 | else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \ | ||
| 677 | __fwd = FORCEWAKE_MEDIA; \ | ||
| 678 | else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \ | ||
| 679 | __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ | ||
| 680 | __fwd; \ | ||
| 681 | }) | ||
| 682 | 755 | ||
| 683 | #define __chv_reg_write_fw_domains(offset) \ | 756 | #define __fwtable_reg_write_fw_domains(offset) \ |
| 684 | ({ \ | 757 | ({ \ |
| 685 | enum forcewake_domains __fwd = 0; \ | 758 | enum forcewake_domains __fwd = 0; \ |
| 686 | if (!NEEDS_FORCE_WAKE(offset) || is_gen8_shadowed(offset)) \ | 759 | if (NEEDS_FORCE_WAKE((offset)) && !is_gen8_shadowed(offset)) \ |
| 687 | __fwd = 0; \ | 760 | __fwd = find_fw_domain(dev_priv, offset); \ |
| 688 | else if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(offset)) \ | ||
| 689 | __fwd = FORCEWAKE_RENDER; \ | ||
| 690 | else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(offset)) \ | ||
| 691 | __fwd = FORCEWAKE_MEDIA; \ | ||
| 692 | else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \ | ||
| 693 | __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ | ||
| 694 | __fwd; \ | ||
| 695 | }) | ||
| 696 | |||
| 697 | #define FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) \ | ||
| 698 | REG_RANGE((reg), 0xB00, 0x2000) | ||
| 699 | |||
| 700 | #define FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) \ | ||
| 701 | (REG_RANGE((reg), 0x2000, 0x2700) || \ | ||
| 702 | REG_RANGE((reg), 0x3000, 0x4000) || \ | ||
| 703 | REG_RANGE((reg), 0x5200, 0x8000) || \ | ||
| 704 | REG_RANGE((reg), 0x8140, 0x8160) || \ | ||
| 705 | REG_RANGE((reg), 0x8300, 0x8500) || \ | ||
| 706 | REG_RANGE((reg), 0x8C00, 0x8D00) || \ | ||
| 707 | REG_RANGE((reg), 0xB000, 0xB480) || \ | ||
| 708 | REG_RANGE((reg), 0xE000, 0xE900) || \ | ||
| 709 | REG_RANGE((reg), 0x24400, 0x24800)) | ||
| 710 | |||
| 711 | #define FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) \ | ||
| 712 | (REG_RANGE((reg), 0x8130, 0x8140) || \ | ||
| 713 | REG_RANGE((reg), 0x8800, 0x8A00) || \ | ||
| 714 | REG_RANGE((reg), 0xD000, 0xD800) || \ | ||
| 715 | REG_RANGE((reg), 0x12000, 0x14000) || \ | ||
| 716 | REG_RANGE((reg), 0x1A000, 0x1EA00) || \ | ||
| 717 | REG_RANGE((reg), 0x30000, 0x40000)) | ||
| 718 | |||
| 719 | #define FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg) \ | ||
| 720 | REG_RANGE((reg), 0x9400, 0x9800) | ||
| 721 | |||
| 722 | #define FORCEWAKE_GEN9_BLITTER_RANGE_OFFSET(reg) \ | ||
| 723 | ((reg) < 0x40000 && \ | ||
| 724 | !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg) && \ | ||
| 725 | !FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(reg) && \ | ||
| 726 | !FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(reg) && \ | ||
| 727 | !FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(reg)) | ||
| 728 | |||
| 729 | #define SKL_NEEDS_FORCE_WAKE(reg) \ | ||
| 730 | ((reg) < 0x40000 && !FORCEWAKE_GEN9_UNCORE_RANGE_OFFSET(reg)) | ||
| 731 | |||
| 732 | #define __gen9_reg_read_fw_domains(offset) \ | ||
| 733 | ({ \ | ||
| 734 | enum forcewake_domains __fwd; \ | ||
| 735 | if (!SKL_NEEDS_FORCE_WAKE(offset)) \ | ||
| 736 | __fwd = 0; \ | ||
| 737 | else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \ | ||
| 738 | __fwd = FORCEWAKE_RENDER; \ | ||
| 739 | else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \ | ||
| 740 | __fwd = FORCEWAKE_MEDIA; \ | ||
| 741 | else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \ | ||
| 742 | __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ | ||
| 743 | else \ | ||
| 744 | __fwd = FORCEWAKE_BLITTER; \ | ||
| 745 | __fwd; \ | 761 | __fwd; \ |
| 746 | }) | 762 | }) |
| 747 | 763 | ||
| 748 | static const i915_reg_t gen9_shadowed_regs[] = { | 764 | /* *Must* be sorted by offset ranges! See intel_fw_table_check(). */ |
| 749 | RING_TAIL(RENDER_RING_BASE), | 765 | static const struct intel_forcewake_range __gen9_fw_ranges[] = { |
| 750 | RING_TAIL(GEN6_BSD_RING_BASE), | 766 | GEN_FW_RANGE(0x0, 0xaff, FORCEWAKE_BLITTER), |
| 751 | RING_TAIL(VEBOX_RING_BASE), | 767 | GEN_FW_RANGE(0xb00, 0x1fff, 0), /* uncore range */ |
| 752 | RING_TAIL(BLT_RING_BASE), | 768 | GEN_FW_RANGE(0x2000, 0x26ff, FORCEWAKE_RENDER), |
| 753 | GEN6_RPNSWREQ, | 769 | GEN_FW_RANGE(0x2700, 0x2fff, FORCEWAKE_BLITTER), |
| 754 | GEN6_RC_VIDEO_FREQ, | 770 | GEN_FW_RANGE(0x3000, 0x3fff, FORCEWAKE_RENDER), |
| 755 | /* TODO: Other registers are not yet used */ | 771 | GEN_FW_RANGE(0x4000, 0x51ff, FORCEWAKE_BLITTER), |
| 772 | GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), | ||
| 773 | GEN_FW_RANGE(0x8000, 0x812f, FORCEWAKE_BLITTER), | ||
| 774 | GEN_FW_RANGE(0x8130, 0x813f, FORCEWAKE_MEDIA), | ||
| 775 | GEN_FW_RANGE(0x8140, 0x815f, FORCEWAKE_RENDER), | ||
| 776 | GEN_FW_RANGE(0x8160, 0x82ff, FORCEWAKE_BLITTER), | ||
| 777 | GEN_FW_RANGE(0x8300, 0x84ff, FORCEWAKE_RENDER), | ||
| 778 | GEN_FW_RANGE(0x8500, 0x87ff, FORCEWAKE_BLITTER), | ||
| 779 | GEN_FW_RANGE(0x8800, 0x89ff, FORCEWAKE_MEDIA), | ||
| 780 | GEN_FW_RANGE(0x8a00, 0x8bff, FORCEWAKE_BLITTER), | ||
| 781 | GEN_FW_RANGE(0x8c00, 0x8cff, FORCEWAKE_RENDER), | ||
| 782 | GEN_FW_RANGE(0x8d00, 0x93ff, FORCEWAKE_BLITTER), | ||
| 783 | GEN_FW_RANGE(0x9400, 0x97ff, FORCEWAKE_RENDER | FORCEWAKE_MEDIA), | ||
| 784 | GEN_FW_RANGE(0x9800, 0xafff, FORCEWAKE_BLITTER), | ||
| 785 | GEN_FW_RANGE(0xb000, 0xb47f, FORCEWAKE_RENDER), | ||
| 786 | GEN_FW_RANGE(0xb480, 0xbfff, FORCEWAKE_BLITTER), | ||
| 787 | GEN_FW_RANGE(0xd000, 0xd7ff, FORCEWAKE_MEDIA), | ||
| 788 | GEN_FW_RANGE(0xd800, 0xdfff, FORCEWAKE_BLITTER), | ||
| 789 | GEN_FW_RANGE(0xe000, 0xe8ff, FORCEWAKE_RENDER), | ||
| 790 | GEN_FW_RANGE(0xe900, 0x11fff, FORCEWAKE_BLITTER), | ||
| 791 | GEN_FW_RANGE(0x12000, 0x13fff, FORCEWAKE_MEDIA), | ||
| 792 | GEN_FW_RANGE(0x14000, 0x19fff, FORCEWAKE_BLITTER), | ||
| 793 | GEN_FW_RANGE(0x1a000, 0x1e9ff, FORCEWAKE_MEDIA), | ||
| 794 | GEN_FW_RANGE(0x1ea00, 0x243ff, FORCEWAKE_BLITTER), | ||
| 795 | GEN_FW_RANGE(0x24400, 0x247ff, FORCEWAKE_RENDER), | ||
| 796 | GEN_FW_RANGE(0x24800, 0x2ffff, FORCEWAKE_BLITTER), | ||
| 797 | GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_MEDIA), | ||
| 756 | }; | 798 | }; |
| 757 | 799 | ||
| 758 | static bool is_gen9_shadowed(u32 offset) | ||
| 759 | { | ||
| 760 | int i; | ||
| 761 | for (i = 0; i < ARRAY_SIZE(gen9_shadowed_regs); i++) | ||
| 762 | if (offset == gen9_shadowed_regs[i].reg) | ||
| 763 | return true; | ||
| 764 | |||
| 765 | return false; | ||
| 766 | } | ||
| 767 | |||
| 768 | #define __gen9_reg_write_fw_domains(offset) \ | ||
| 769 | ({ \ | ||
| 770 | enum forcewake_domains __fwd; \ | ||
| 771 | if (!SKL_NEEDS_FORCE_WAKE(offset) || is_gen9_shadowed(offset)) \ | ||
| 772 | __fwd = 0; \ | ||
| 773 | else if (FORCEWAKE_GEN9_RENDER_RANGE_OFFSET(offset)) \ | ||
| 774 | __fwd = FORCEWAKE_RENDER; \ | ||
| 775 | else if (FORCEWAKE_GEN9_MEDIA_RANGE_OFFSET(offset)) \ | ||
| 776 | __fwd = FORCEWAKE_MEDIA; \ | ||
| 777 | else if (FORCEWAKE_GEN9_COMMON_RANGE_OFFSET(offset)) \ | ||
| 778 | __fwd = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \ | ||
| 779 | else \ | ||
| 780 | __fwd = FORCEWAKE_BLITTER; \ | ||
| 781 | __fwd; \ | ||
| 782 | }) | ||
| 783 | |||
| 784 | static void | 800 | static void |
| 785 | ilk_dummy_write(struct drm_i915_private *dev_priv) | 801 | ilk_dummy_write(struct drm_i915_private *dev_priv) |
| 786 | { | 802 | { |
| @@ -796,10 +812,9 @@ __unclaimed_reg_debug(struct drm_i915_private *dev_priv, | |||
| 796 | const bool read, | 812 | const bool read, |
| 797 | const bool before) | 813 | const bool before) |
| 798 | { | 814 | { |
| 799 | if (WARN(check_for_unclaimed_mmio(dev_priv), | 815 | if (WARN(check_for_unclaimed_mmio(dev_priv) && !before, |
| 800 | "Unclaimed register detected %s %s register 0x%x\n", | 816 | "Unclaimed %s register 0x%x\n", |
| 801 | before ? "before" : "after", | 817 | read ? "read from" : "write to", |
| 802 | read ? "reading" : "writing to", | ||
| 803 | i915_mmio_reg_offset(reg))) | 818 | i915_mmio_reg_offset(reg))) |
| 804 | i915.mmio_debug--; /* Only report the first N failures */ | 819 | i915.mmio_debug--; /* Only report the first N failures */ |
| 805 | } | 820 | } |
| @@ -870,26 +885,30 @@ __gen2_read(64) | |||
| 870 | trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ | 885 | trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \ |
| 871 | return val | 886 | return val |
| 872 | 887 | ||
| 873 | static inline void __force_wake_auto(struct drm_i915_private *dev_priv, | 888 | static noinline void ___force_wake_auto(struct drm_i915_private *dev_priv, |
| 874 | enum forcewake_domains fw_domains) | 889 | enum forcewake_domains fw_domains) |
| 875 | { | 890 | { |
| 876 | struct intel_uncore_forcewake_domain *domain; | 891 | struct intel_uncore_forcewake_domain *domain; |
| 877 | 892 | ||
| 893 | for_each_fw_domain_masked(domain, fw_domains, dev_priv) | ||
| 894 | fw_domain_arm_timer(domain); | ||
| 895 | |||
| 896 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); | ||
| 897 | dev_priv->uncore.fw_domains_active |= fw_domains; | ||
| 898 | } | ||
| 899 | |||
| 900 | static inline void __force_wake_auto(struct drm_i915_private *dev_priv, | ||
| 901 | enum forcewake_domains fw_domains) | ||
| 902 | { | ||
| 878 | if (WARN_ON(!fw_domains)) | 903 | if (WARN_ON(!fw_domains)) |
| 879 | return; | 904 | return; |
| 880 | 905 | ||
| 881 | /* Ideally GCC would be constant-fold and eliminate this loop */ | 906 | /* Turn on all requested but inactive supported forcewake domains. */ |
| 882 | for_each_fw_domain_masked(domain, fw_domains, dev_priv) { | 907 | fw_domains &= dev_priv->uncore.fw_domains; |
| 883 | if (domain->wake_count) { | 908 | fw_domains &= ~dev_priv->uncore.fw_domains_active; |
| 884 | fw_domains &= ~domain->mask; | ||
| 885 | continue; | ||
| 886 | } | ||
| 887 | |||
| 888 | fw_domain_arm_timer(domain); | ||
| 889 | } | ||
| 890 | 909 | ||
| 891 | if (fw_domains) | 910 | if (fw_domains) |
| 892 | dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_domains); | 911 | ___force_wake_auto(dev_priv, fw_domains); |
| 893 | } | 912 | } |
| 894 | 913 | ||
| 895 | #define __gen6_read(x) \ | 914 | #define __gen6_read(x) \ |
| @@ -904,62 +923,28 @@ gen6_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ | |||
| 904 | GEN6_READ_FOOTER; \ | 923 | GEN6_READ_FOOTER; \ |
| 905 | } | 924 | } |
| 906 | 925 | ||
| 907 | #define __vlv_read(x) \ | 926 | #define __fwtable_read(x) \ |
| 908 | static u##x \ | ||
| 909 | vlv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ | ||
| 910 | enum forcewake_domains fw_engine; \ | ||
| 911 | GEN6_READ_HEADER(x); \ | ||
| 912 | fw_engine = __vlv_reg_read_fw_domains(offset); \ | ||
| 913 | if (fw_engine) \ | ||
| 914 | __force_wake_auto(dev_priv, fw_engine); \ | ||
| 915 | val = __raw_i915_read##x(dev_priv, reg); \ | ||
| 916 | GEN6_READ_FOOTER; \ | ||
| 917 | } | ||
| 918 | |||
| 919 | #define __chv_read(x) \ | ||
| 920 | static u##x \ | 927 | static u##x \ |
| 921 | chv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ | 928 | fwtable_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ |
| 922 | enum forcewake_domains fw_engine; \ | 929 | enum forcewake_domains fw_engine; \ |
| 923 | GEN6_READ_HEADER(x); \ | 930 | GEN6_READ_HEADER(x); \ |
| 924 | fw_engine = __chv_reg_read_fw_domains(offset); \ | 931 | fw_engine = __fwtable_reg_read_fw_domains(offset); \ |
| 925 | if (fw_engine) \ | 932 | if (fw_engine) \ |
| 926 | __force_wake_auto(dev_priv, fw_engine); \ | 933 | __force_wake_auto(dev_priv, fw_engine); \ |
| 927 | val = __raw_i915_read##x(dev_priv, reg); \ | 934 | val = __raw_i915_read##x(dev_priv, reg); \ |
| 928 | GEN6_READ_FOOTER; \ | 935 | GEN6_READ_FOOTER; \ |
| 929 | } | 936 | } |
| 930 | 937 | ||
| 931 | #define __gen9_read(x) \ | 938 | __fwtable_read(8) |
| 932 | static u##x \ | 939 | __fwtable_read(16) |
| 933 | gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \ | 940 | __fwtable_read(32) |
| 934 | enum forcewake_domains fw_engine; \ | 941 | __fwtable_read(64) |
| 935 | GEN6_READ_HEADER(x); \ | ||
| 936 | fw_engine = __gen9_reg_read_fw_domains(offset); \ | ||
| 937 | if (fw_engine) \ | ||
| 938 | __force_wake_auto(dev_priv, fw_engine); \ | ||
| 939 | val = __raw_i915_read##x(dev_priv, reg); \ | ||
| 940 | GEN6_READ_FOOTER; \ | ||
| 941 | } | ||
| 942 | |||
| 943 | __gen9_read(8) | ||
| 944 | __gen9_read(16) | ||
| 945 | __gen9_read(32) | ||
| 946 | __gen9_read(64) | ||
| 947 | __chv_read(8) | ||
| 948 | __chv_read(16) | ||
| 949 | __chv_read(32) | ||
| 950 | __chv_read(64) | ||
| 951 | __vlv_read(8) | ||
| 952 | __vlv_read(16) | ||
| 953 | __vlv_read(32) | ||
| 954 | __vlv_read(64) | ||
| 955 | __gen6_read(8) | 942 | __gen6_read(8) |
| 956 | __gen6_read(16) | 943 | __gen6_read(16) |
| 957 | __gen6_read(32) | 944 | __gen6_read(32) |
| 958 | __gen6_read(64) | 945 | __gen6_read(64) |
| 959 | 946 | ||
| 960 | #undef __gen9_read | 947 | #undef __fwtable_read |
| 961 | #undef __chv_read | ||
| 962 | #undef __vlv_read | ||
| 963 | #undef __gen6_read | 948 | #undef __gen6_read |
| 964 | #undef GEN6_READ_FOOTER | 949 | #undef GEN6_READ_FOOTER |
| 965 | #undef GEN6_READ_HEADER | 950 | #undef GEN6_READ_HEADER |
| @@ -1055,21 +1040,6 @@ gen6_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool | |||
| 1055 | GEN6_WRITE_FOOTER; \ | 1040 | GEN6_WRITE_FOOTER; \ |
| 1056 | } | 1041 | } |
| 1057 | 1042 | ||
| 1058 | #define __hsw_write(x) \ | ||
| 1059 | static void \ | ||
| 1060 | hsw_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ | ||
| 1061 | u32 __fifo_ret = 0; \ | ||
| 1062 | GEN6_WRITE_HEADER; \ | ||
| 1063 | if (NEEDS_FORCE_WAKE(offset)) { \ | ||
| 1064 | __fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \ | ||
| 1065 | } \ | ||
| 1066 | __raw_i915_write##x(dev_priv, reg, val); \ | ||
| 1067 | if (unlikely(__fifo_ret)) { \ | ||
| 1068 | gen6_gt_check_fifodbg(dev_priv); \ | ||
| 1069 | } \ | ||
| 1070 | GEN6_WRITE_FOOTER; \ | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | #define __gen8_write(x) \ | 1043 | #define __gen8_write(x) \ |
| 1074 | static void \ | 1044 | static void \ |
| 1075 | gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ | 1045 | gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ |
| @@ -1082,51 +1052,30 @@ gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool | |||
| 1082 | GEN6_WRITE_FOOTER; \ | 1052 | GEN6_WRITE_FOOTER; \ |
| 1083 | } | 1053 | } |
| 1084 | 1054 | ||
| 1085 | #define __chv_write(x) \ | 1055 | #define __fwtable_write(x) \ |
| 1086 | static void \ | ||
| 1087 | chv_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ | ||
| 1088 | enum forcewake_domains fw_engine; \ | ||
| 1089 | GEN6_WRITE_HEADER; \ | ||
| 1090 | fw_engine = __chv_reg_write_fw_domains(offset); \ | ||
| 1091 | if (fw_engine) \ | ||
| 1092 | __force_wake_auto(dev_priv, fw_engine); \ | ||
| 1093 | __raw_i915_write##x(dev_priv, reg, val); \ | ||
| 1094 | GEN6_WRITE_FOOTER; \ | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | #define __gen9_write(x) \ | ||
| 1098 | static void \ | 1056 | static void \ |
| 1099 | gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \ | 1057 | fwtable_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \ |
| 1100 | bool trace) { \ | ||
| 1101 | enum forcewake_domains fw_engine; \ | 1058 | enum forcewake_domains fw_engine; \ |
| 1102 | GEN6_WRITE_HEADER; \ | 1059 | GEN6_WRITE_HEADER; \ |
| 1103 | fw_engine = __gen9_reg_write_fw_domains(offset); \ | 1060 | fw_engine = __fwtable_reg_write_fw_domains(offset); \ |
| 1104 | if (fw_engine) \ | 1061 | if (fw_engine) \ |
| 1105 | __force_wake_auto(dev_priv, fw_engine); \ | 1062 | __force_wake_auto(dev_priv, fw_engine); \ |
| 1106 | __raw_i915_write##x(dev_priv, reg, val); \ | 1063 | __raw_i915_write##x(dev_priv, reg, val); \ |
| 1107 | GEN6_WRITE_FOOTER; \ | 1064 | GEN6_WRITE_FOOTER; \ |
| 1108 | } | 1065 | } |
| 1109 | 1066 | ||
| 1110 | __gen9_write(8) | 1067 | __fwtable_write(8) |
| 1111 | __gen9_write(16) | 1068 | __fwtable_write(16) |
| 1112 | __gen9_write(32) | 1069 | __fwtable_write(32) |
| 1113 | __chv_write(8) | ||
| 1114 | __chv_write(16) | ||
| 1115 | __chv_write(32) | ||
| 1116 | __gen8_write(8) | 1070 | __gen8_write(8) |
| 1117 | __gen8_write(16) | 1071 | __gen8_write(16) |
| 1118 | __gen8_write(32) | 1072 | __gen8_write(32) |
| 1119 | __hsw_write(8) | ||
| 1120 | __hsw_write(16) | ||
| 1121 | __hsw_write(32) | ||
| 1122 | __gen6_write(8) | 1073 | __gen6_write(8) |
| 1123 | __gen6_write(16) | 1074 | __gen6_write(16) |
| 1124 | __gen6_write(32) | 1075 | __gen6_write(32) |
| 1125 | 1076 | ||
| 1126 | #undef __gen9_write | 1077 | #undef __fwtable_write |
| 1127 | #undef __chv_write | ||
| 1128 | #undef __gen8_write | 1078 | #undef __gen8_write |
| 1129 | #undef __hsw_write | ||
| 1130 | #undef __gen6_write | 1079 | #undef __gen6_write |
| 1131 | #undef GEN6_WRITE_FOOTER | 1080 | #undef GEN6_WRITE_FOOTER |
| 1132 | #undef GEN6_WRITE_HEADER | 1081 | #undef GEN6_WRITE_HEADER |
| @@ -1315,6 +1264,13 @@ static void intel_uncore_fw_domains_init(struct drm_i915_private *dev_priv) | |||
| 1315 | WARN_ON(dev_priv->uncore.fw_domains == 0); | 1264 | WARN_ON(dev_priv->uncore.fw_domains == 0); |
| 1316 | } | 1265 | } |
| 1317 | 1266 | ||
| 1267 | #define ASSIGN_FW_DOMAINS_TABLE(d) \ | ||
| 1268 | { \ | ||
| 1269 | dev_priv->uncore.fw_domains_table = \ | ||
| 1270 | (struct intel_forcewake_range *)(d); \ | ||
| 1271 | dev_priv->uncore.fw_domains_table_entries = ARRAY_SIZE((d)); \ | ||
| 1272 | } | ||
| 1273 | |||
| 1318 | void intel_uncore_init(struct drm_i915_private *dev_priv) | 1274 | void intel_uncore_init(struct drm_i915_private *dev_priv) |
| 1319 | { | 1275 | { |
| 1320 | i915_check_vgpu(dev_priv); | 1276 | i915_check_vgpu(dev_priv); |
| @@ -1328,13 +1284,15 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) | |||
| 1328 | switch (INTEL_INFO(dev_priv)->gen) { | 1284 | switch (INTEL_INFO(dev_priv)->gen) { |
| 1329 | default: | 1285 | default: |
| 1330 | case 9: | 1286 | case 9: |
| 1331 | ASSIGN_WRITE_MMIO_VFUNCS(gen9); | 1287 | ASSIGN_FW_DOMAINS_TABLE(__gen9_fw_ranges); |
| 1332 | ASSIGN_READ_MMIO_VFUNCS(gen9); | 1288 | ASSIGN_WRITE_MMIO_VFUNCS(fwtable); |
| 1289 | ASSIGN_READ_MMIO_VFUNCS(fwtable); | ||
| 1333 | break; | 1290 | break; |
| 1334 | case 8: | 1291 | case 8: |
| 1335 | if (IS_CHERRYVIEW(dev_priv)) { | 1292 | if (IS_CHERRYVIEW(dev_priv)) { |
| 1336 | ASSIGN_WRITE_MMIO_VFUNCS(chv); | 1293 | ASSIGN_FW_DOMAINS_TABLE(__chv_fw_ranges); |
| 1337 | ASSIGN_READ_MMIO_VFUNCS(chv); | 1294 | ASSIGN_WRITE_MMIO_VFUNCS(fwtable); |
| 1295 | ASSIGN_READ_MMIO_VFUNCS(fwtable); | ||
| 1338 | 1296 | ||
| 1339 | } else { | 1297 | } else { |
| 1340 | ASSIGN_WRITE_MMIO_VFUNCS(gen8); | 1298 | ASSIGN_WRITE_MMIO_VFUNCS(gen8); |
| @@ -1343,14 +1301,11 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) | |||
| 1343 | break; | 1301 | break; |
| 1344 | case 7: | 1302 | case 7: |
| 1345 | case 6: | 1303 | case 6: |
| 1346 | if (IS_HASWELL(dev_priv)) { | 1304 | ASSIGN_WRITE_MMIO_VFUNCS(gen6); |
| 1347 | ASSIGN_WRITE_MMIO_VFUNCS(hsw); | ||
| 1348 | } else { | ||
| 1349 | ASSIGN_WRITE_MMIO_VFUNCS(gen6); | ||
| 1350 | } | ||
| 1351 | 1305 | ||
| 1352 | if (IS_VALLEYVIEW(dev_priv)) { | 1306 | if (IS_VALLEYVIEW(dev_priv)) { |
| 1353 | ASSIGN_READ_MMIO_VFUNCS(vlv); | 1307 | ASSIGN_FW_DOMAINS_TABLE(__vlv_fw_ranges); |
| 1308 | ASSIGN_READ_MMIO_VFUNCS(fwtable); | ||
| 1354 | } else { | 1309 | } else { |
| 1355 | ASSIGN_READ_MMIO_VFUNCS(gen6); | 1310 | ASSIGN_READ_MMIO_VFUNCS(gen6); |
| 1356 | } | 1311 | } |
| @@ -1367,6 +1322,10 @@ void intel_uncore_init(struct drm_i915_private *dev_priv) | |||
| 1367 | break; | 1322 | break; |
| 1368 | } | 1323 | } |
| 1369 | 1324 | ||
| 1325 | intel_fw_table_check(dev_priv); | ||
| 1326 | if (INTEL_GEN(dev_priv) >= 8) | ||
| 1327 | intel_shadow_table_check(); | ||
| 1328 | |||
| 1370 | if (intel_vgpu_active(dev_priv)) { | 1329 | if (intel_vgpu_active(dev_priv)) { |
| 1371 | ASSIGN_WRITE_MMIO_VFUNCS(vgpu); | 1330 | ASSIGN_WRITE_MMIO_VFUNCS(vgpu); |
| 1372 | ASSIGN_READ_MMIO_VFUNCS(vgpu); | 1331 | ASSIGN_READ_MMIO_VFUNCS(vgpu); |
| @@ -1816,35 +1775,16 @@ static enum forcewake_domains | |||
| 1816 | intel_uncore_forcewake_for_read(struct drm_i915_private *dev_priv, | 1775 | intel_uncore_forcewake_for_read(struct drm_i915_private *dev_priv, |
| 1817 | i915_reg_t reg) | 1776 | i915_reg_t reg) |
| 1818 | { | 1777 | { |
| 1778 | u32 offset = i915_mmio_reg_offset(reg); | ||
| 1819 | enum forcewake_domains fw_domains; | 1779 | enum forcewake_domains fw_domains; |
| 1820 | 1780 | ||
| 1821 | if (intel_vgpu_active(dev_priv)) | 1781 | if (HAS_FWTABLE(dev_priv)) { |
| 1822 | return 0; | 1782 | fw_domains = __fwtable_reg_read_fw_domains(offset); |
| 1823 | 1783 | } else if (INTEL_GEN(dev_priv) >= 6) { | |
| 1824 | switch (INTEL_GEN(dev_priv)) { | 1784 | fw_domains = __gen6_reg_read_fw_domains(offset); |
| 1825 | case 9: | 1785 | } else { |
| 1826 | fw_domains = __gen9_reg_read_fw_domains(i915_mmio_reg_offset(reg)); | 1786 | WARN_ON(!IS_GEN(dev_priv, 2, 5)); |
| 1827 | break; | 1787 | fw_domains = 0; |
| 1828 | case 8: | ||
| 1829 | if (IS_CHERRYVIEW(dev_priv)) | ||
| 1830 | fw_domains = __chv_reg_read_fw_domains(i915_mmio_reg_offset(reg)); | ||
| 1831 | else | ||
| 1832 | fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg)); | ||
| 1833 | break; | ||
| 1834 | case 7: | ||
| 1835 | case 6: | ||
| 1836 | if (IS_VALLEYVIEW(dev_priv)) | ||
| 1837 | fw_domains = __vlv_reg_read_fw_domains(i915_mmio_reg_offset(reg)); | ||
| 1838 | else | ||
| 1839 | fw_domains = __gen6_reg_read_fw_domains(i915_mmio_reg_offset(reg)); | ||
| 1840 | break; | ||
| 1841 | default: | ||
| 1842 | MISSING_CASE(INTEL_INFO(dev_priv)->gen); | ||
| 1843 | case 5: /* forcewake was introduced with gen6 */ | ||
| 1844 | case 4: | ||
| 1845 | case 3: | ||
| 1846 | case 2: | ||
| 1847 | return 0; | ||
| 1848 | } | 1788 | } |
| 1849 | 1789 | ||
| 1850 | WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains); | 1790 | WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains); |
| @@ -1856,32 +1796,18 @@ static enum forcewake_domains | |||
| 1856 | intel_uncore_forcewake_for_write(struct drm_i915_private *dev_priv, | 1796 | intel_uncore_forcewake_for_write(struct drm_i915_private *dev_priv, |
| 1857 | i915_reg_t reg) | 1797 | i915_reg_t reg) |
| 1858 | { | 1798 | { |
| 1799 | u32 offset = i915_mmio_reg_offset(reg); | ||
| 1859 | enum forcewake_domains fw_domains; | 1800 | enum forcewake_domains fw_domains; |
| 1860 | 1801 | ||
| 1861 | if (intel_vgpu_active(dev_priv)) | 1802 | if (HAS_FWTABLE(dev_priv) && !IS_VALLEYVIEW(dev_priv)) { |
| 1862 | return 0; | 1803 | fw_domains = __fwtable_reg_write_fw_domains(offset); |
| 1863 | 1804 | } else if (IS_GEN8(dev_priv)) { | |
| 1864 | switch (INTEL_GEN(dev_priv)) { | 1805 | fw_domains = __gen8_reg_write_fw_domains(offset); |
| 1865 | case 9: | 1806 | } else if (IS_GEN(dev_priv, 6, 7)) { |
| 1866 | fw_domains = __gen9_reg_write_fw_domains(i915_mmio_reg_offset(reg)); | ||
| 1867 | break; | ||
| 1868 | case 8: | ||
| 1869 | if (IS_CHERRYVIEW(dev_priv)) | ||
| 1870 | fw_domains = __chv_reg_write_fw_domains(i915_mmio_reg_offset(reg)); | ||
| 1871 | else | ||
| 1872 | fw_domains = __gen8_reg_write_fw_domains(i915_mmio_reg_offset(reg)); | ||
| 1873 | break; | ||
| 1874 | case 7: | ||
| 1875 | case 6: | ||
| 1876 | fw_domains = FORCEWAKE_RENDER; | 1807 | fw_domains = FORCEWAKE_RENDER; |
| 1877 | break; | 1808 | } else { |
| 1878 | default: | 1809 | WARN_ON(!IS_GEN(dev_priv, 2, 5)); |
| 1879 | MISSING_CASE(INTEL_INFO(dev_priv)->gen); | 1810 | fw_domains = 0; |
| 1880 | case 5: | ||
| 1881 | case 4: | ||
| 1882 | case 3: | ||
| 1883 | case 2: | ||
| 1884 | return 0; | ||
| 1885 | } | 1811 | } |
| 1886 | 1812 | ||
| 1887 | WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains); | 1813 | WARN_ON(fw_domains & ~dev_priv->uncore.fw_domains); |
| @@ -1911,6 +1837,9 @@ intel_uncore_forcewake_for_reg(struct drm_i915_private *dev_priv, | |||
| 1911 | 1837 | ||
| 1912 | WARN_ON(!op); | 1838 | WARN_ON(!op); |
| 1913 | 1839 | ||
| 1840 | if (intel_vgpu_active(dev_priv)) | ||
| 1841 | return 0; | ||
| 1842 | |||
| 1914 | if (op & FW_REG_READ) | 1843 | if (op & FW_REG_READ) |
| 1915 | fw_domains = intel_uncore_forcewake_for_read(dev_priv, reg); | 1844 | fw_domains = intel_uncore_forcewake_for_read(dev_priv, reg); |
| 1916 | 1845 | ||
diff --git a/drivers/gpu/drm/msm/msm_perf.c b/drivers/gpu/drm/msm/msm_perf.c index 17fe4e53e0d1..1627294575cb 100644 --- a/drivers/gpu/drm/msm/msm_perf.c +++ b/drivers/gpu/drm/msm/msm_perf.c | |||
| @@ -229,8 +229,8 @@ int msm_perf_debugfs_init(struct drm_minor *minor) | |||
| 229 | perf->ent = debugfs_create_file("perf", S_IFREG | S_IRUGO, | 229 | perf->ent = debugfs_create_file("perf", S_IFREG | S_IRUGO, |
| 230 | minor->debugfs_root, perf, &perf_debugfs_fops); | 230 | minor->debugfs_root, perf, &perf_debugfs_fops); |
| 231 | if (!perf->ent) { | 231 | if (!perf->ent) { |
| 232 | DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/perf\n", | 232 | DRM_ERROR("Cannot create /sys/kernel/debug/dri/%pd/perf\n", |
| 233 | minor->debugfs_root->d_name.name); | 233 | minor->debugfs_root); |
| 234 | goto fail; | 234 | goto fail; |
| 235 | } | 235 | } |
| 236 | 236 | ||
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c index 3a5fdfcd67ae..8487f461f05f 100644 --- a/drivers/gpu/drm/msm/msm_rd.c +++ b/drivers/gpu/drm/msm/msm_rd.c | |||
| @@ -243,8 +243,8 @@ int msm_rd_debugfs_init(struct drm_minor *minor) | |||
| 243 | rd->ent = debugfs_create_file("rd", S_IFREG | S_IRUGO, | 243 | rd->ent = debugfs_create_file("rd", S_IFREG | S_IRUGO, |
| 244 | minor->debugfs_root, rd, &rd_debugfs_fops); | 244 | minor->debugfs_root, rd, &rd_debugfs_fops); |
| 245 | if (!rd->ent) { | 245 | if (!rd->ent) { |
| 246 | DRM_ERROR("Cannot create /sys/kernel/debug/dri/%s/rd\n", | 246 | DRM_ERROR("Cannot create /sys/kernel/debug/dri/%pd/rd\n", |
| 247 | minor->debugfs_root->d_name.name); | 247 | minor->debugfs_root); |
| 248 | goto fail; | 248 | goto fail; |
| 249 | } | 249 | } |
| 250 | 250 | ||
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index 7ea8aa7ca408..6bc712f32c8b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h | |||
| @@ -175,6 +175,7 @@ struct nvkm_device_func { | |||
| 175 | void (*fini)(struct nvkm_device *, bool suspend); | 175 | void (*fini)(struct nvkm_device *, bool suspend); |
| 176 | resource_size_t (*resource_addr)(struct nvkm_device *, unsigned bar); | 176 | resource_size_t (*resource_addr)(struct nvkm_device *, unsigned bar); |
| 177 | resource_size_t (*resource_size)(struct nvkm_device *, unsigned bar); | 177 | resource_size_t (*resource_size)(struct nvkm_device *, unsigned bar); |
| 178 | bool cpu_coherent; | ||
| 178 | }; | 179 | }; |
| 179 | 180 | ||
| 180 | struct nvkm_device_quirk { | 181 | struct nvkm_device_quirk { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 66f31c3eb8ba..343b8659472c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
| @@ -209,7 +209,8 @@ nouveau_bo_new(struct drm_device *dev, int size, int align, | |||
| 209 | nvbo->tile_flags = tile_flags; | 209 | nvbo->tile_flags = tile_flags; |
| 210 | nvbo->bo.bdev = &drm->ttm.bdev; | 210 | nvbo->bo.bdev = &drm->ttm.bdev; |
| 211 | 211 | ||
| 212 | nvbo->force_coherent = flags & TTM_PL_FLAG_UNCACHED; | 212 | if (!nvxx_device(&drm->device)->func->cpu_coherent) |
| 213 | nvbo->force_coherent = flags & TTM_PL_FLAG_UNCACHED; | ||
| 213 | 214 | ||
| 214 | nvbo->page_shift = 12; | 215 | nvbo->page_shift = 12; |
| 215 | if (drm->client.vm) { | 216 | if (drm->client.vm) { |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c index b1b693219db3..62ad0300cfa5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c | |||
| @@ -1614,6 +1614,7 @@ nvkm_device_pci_func = { | |||
| 1614 | .fini = nvkm_device_pci_fini, | 1614 | .fini = nvkm_device_pci_fini, |
| 1615 | .resource_addr = nvkm_device_pci_resource_addr, | 1615 | .resource_addr = nvkm_device_pci_resource_addr, |
| 1616 | .resource_size = nvkm_device_pci_resource_size, | 1616 | .resource_size = nvkm_device_pci_resource_size, |
| 1617 | .cpu_coherent = !IS_ENABLED(CONFIG_ARM), | ||
| 1617 | }; | 1618 | }; |
| 1618 | 1619 | ||
| 1619 | int | 1620 | int |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index 939682f18788..9b638bd905ff 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | |||
| @@ -245,6 +245,7 @@ nvkm_device_tegra_func = { | |||
| 245 | .fini = nvkm_device_tegra_fini, | 245 | .fini = nvkm_device_tegra_fini, |
| 246 | .resource_addr = nvkm_device_tegra_resource_addr, | 246 | .resource_addr = nvkm_device_tegra_resource_addr, |
| 247 | .resource_size = nvkm_device_tegra_resource_size, | 247 | .resource_size = nvkm_device_tegra_resource_size, |
| 248 | .cpu_coherent = false, | ||
| 248 | }; | 249 | }; |
| 249 | 250 | ||
| 250 | int | 251 | int |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c index edec30fd3ecd..0a7b6ed5ed28 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c | |||
| @@ -37,7 +37,10 @@ nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *base, int cookie) | |||
| 37 | { | 37 | { |
| 38 | struct nv04_fifo_chan *chan = nv04_fifo_chan(base); | 38 | struct nv04_fifo_chan *chan = nv04_fifo_chan(base); |
| 39 | struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem; | 39 | struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem; |
| 40 | |||
| 41 | mutex_lock(&chan->fifo->base.engine.subdev.mutex); | ||
| 40 | nvkm_ramht_remove(imem->ramht, cookie); | 42 | nvkm_ramht_remove(imem->ramht, cookie); |
| 43 | mutex_unlock(&chan->fifo->base.engine.subdev.mutex); | ||
| 41 | } | 44 | } |
| 42 | 45 | ||
| 43 | static int | 46 | static int |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index a4e9f35da3a2..74f99bac08b1 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
| @@ -1638,8 +1638,8 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, | |||
| 1638 | WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, | 1638 | WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, |
| 1639 | (viewport_w << 16) | viewport_h); | 1639 | (viewport_w << 16) | viewport_h); |
| 1640 | 1640 | ||
| 1641 | /* set pageflip to happen anywhere in vblank interval */ | 1641 | /* set pageflip to happen only at start of vblank interval (front porch) */ |
| 1642 | WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); | 1642 | WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3); |
| 1643 | 1643 | ||
| 1644 | if (!atomic && fb && fb != crtc->primary->fb) { | 1644 | if (!atomic && fb && fb != crtc->primary->fb) { |
| 1645 | radeon_fb = to_radeon_framebuffer(fb); | 1645 | radeon_fb = to_radeon_framebuffer(fb); |
diff --git a/drivers/gpu/drm/radeon/r600_dpm.c b/drivers/gpu/drm/radeon/r600_dpm.c index 6a4b020dd0b4..5a26eb4545aa 100644 --- a/drivers/gpu/drm/radeon/r600_dpm.c +++ b/drivers/gpu/drm/radeon/r600_dpm.c | |||
| @@ -156,19 +156,20 @@ u32 r600_dpm_get_vblank_time(struct radeon_device *rdev) | |||
| 156 | struct drm_device *dev = rdev->ddev; | 156 | struct drm_device *dev = rdev->ddev; |
| 157 | struct drm_crtc *crtc; | 157 | struct drm_crtc *crtc; |
| 158 | struct radeon_crtc *radeon_crtc; | 158 | struct radeon_crtc *radeon_crtc; |
| 159 | u32 line_time_us, vblank_lines; | 159 | u32 vblank_in_pixels; |
| 160 | u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */ | 160 | u32 vblank_time_us = 0xffffffff; /* if the displays are off, vblank time is max */ |
| 161 | 161 | ||
| 162 | if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { | 162 | if (rdev->num_crtc && rdev->mode_info.mode_config_initialized) { |
| 163 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 163 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
| 164 | radeon_crtc = to_radeon_crtc(crtc); | 164 | radeon_crtc = to_radeon_crtc(crtc); |
| 165 | if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { | 165 | if (crtc->enabled && radeon_crtc->enabled && radeon_crtc->hw_mode.clock) { |
| 166 | line_time_us = (radeon_crtc->hw_mode.crtc_htotal * 1000) / | 166 | vblank_in_pixels = |
| 167 | radeon_crtc->hw_mode.clock; | 167 | radeon_crtc->hw_mode.crtc_htotal * |
| 168 | vblank_lines = radeon_crtc->hw_mode.crtc_vblank_end - | 168 | (radeon_crtc->hw_mode.crtc_vblank_end - |
| 169 | radeon_crtc->hw_mode.crtc_vdisplay + | 169 | radeon_crtc->hw_mode.crtc_vdisplay + |
| 170 | (radeon_crtc->v_border * 2); | 170 | (radeon_crtc->v_border * 2)); |
| 171 | vblank_time_us = vblank_lines * line_time_us; | 171 | |
| 172 | vblank_time_us = vblank_in_pixels * 1000 / radeon_crtc->hw_mode.clock; | ||
| 172 | break; | 173 | break; |
| 173 | } | 174 | } |
| 174 | } | 175 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 50e96d2c593d..e18839d52e3e 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -927,6 +927,16 @@ radeon_lvds_detect(struct drm_connector *connector, bool force) | |||
| 927 | return ret; | 927 | return ret; |
| 928 | } | 928 | } |
| 929 | 929 | ||
| 930 | static void radeon_connector_unregister(struct drm_connector *connector) | ||
| 931 | { | ||
| 932 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | ||
| 933 | |||
| 934 | if (radeon_connector->ddc_bus->has_aux) { | ||
| 935 | drm_dp_aux_unregister(&radeon_connector->ddc_bus->aux); | ||
| 936 | radeon_connector->ddc_bus->has_aux = false; | ||
| 937 | } | ||
| 938 | } | ||
| 939 | |||
| 930 | static void radeon_connector_destroy(struct drm_connector *connector) | 940 | static void radeon_connector_destroy(struct drm_connector *connector) |
| 931 | { | 941 | { |
| 932 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); | 942 | struct radeon_connector *radeon_connector = to_radeon_connector(connector); |
| @@ -984,6 +994,7 @@ static const struct drm_connector_funcs radeon_lvds_connector_funcs = { | |||
| 984 | .dpms = drm_helper_connector_dpms, | 994 | .dpms = drm_helper_connector_dpms, |
| 985 | .detect = radeon_lvds_detect, | 995 | .detect = radeon_lvds_detect, |
| 986 | .fill_modes = drm_helper_probe_single_connector_modes, | 996 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 997 | .early_unregister = radeon_connector_unregister, | ||
| 987 | .destroy = radeon_connector_destroy, | 998 | .destroy = radeon_connector_destroy, |
| 988 | .set_property = radeon_lvds_set_property, | 999 | .set_property = radeon_lvds_set_property, |
| 989 | }; | 1000 | }; |
| @@ -1111,6 +1122,7 @@ static const struct drm_connector_funcs radeon_vga_connector_funcs = { | |||
| 1111 | .dpms = drm_helper_connector_dpms, | 1122 | .dpms = drm_helper_connector_dpms, |
| 1112 | .detect = radeon_vga_detect, | 1123 | .detect = radeon_vga_detect, |
| 1113 | .fill_modes = drm_helper_probe_single_connector_modes, | 1124 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1125 | .early_unregister = radeon_connector_unregister, | ||
| 1114 | .destroy = radeon_connector_destroy, | 1126 | .destroy = radeon_connector_destroy, |
| 1115 | .set_property = radeon_connector_set_property, | 1127 | .set_property = radeon_connector_set_property, |
| 1116 | }; | 1128 | }; |
| @@ -1188,6 +1200,7 @@ static const struct drm_connector_funcs radeon_tv_connector_funcs = { | |||
| 1188 | .dpms = drm_helper_connector_dpms, | 1200 | .dpms = drm_helper_connector_dpms, |
| 1189 | .detect = radeon_tv_detect, | 1201 | .detect = radeon_tv_detect, |
| 1190 | .fill_modes = drm_helper_probe_single_connector_modes, | 1202 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1203 | .early_unregister = radeon_connector_unregister, | ||
| 1191 | .destroy = radeon_connector_destroy, | 1204 | .destroy = radeon_connector_destroy, |
| 1192 | .set_property = radeon_connector_set_property, | 1205 | .set_property = radeon_connector_set_property, |
| 1193 | }; | 1206 | }; |
| @@ -1519,6 +1532,7 @@ static const struct drm_connector_funcs radeon_dvi_connector_funcs = { | |||
| 1519 | .detect = radeon_dvi_detect, | 1532 | .detect = radeon_dvi_detect, |
| 1520 | .fill_modes = drm_helper_probe_single_connector_modes, | 1533 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1521 | .set_property = radeon_connector_set_property, | 1534 | .set_property = radeon_connector_set_property, |
| 1535 | .early_unregister = radeon_connector_unregister, | ||
| 1522 | .destroy = radeon_connector_destroy, | 1536 | .destroy = radeon_connector_destroy, |
| 1523 | .force = radeon_dvi_force, | 1537 | .force = radeon_dvi_force, |
| 1524 | }; | 1538 | }; |
| @@ -1832,6 +1846,7 @@ static const struct drm_connector_funcs radeon_dp_connector_funcs = { | |||
| 1832 | .detect = radeon_dp_detect, | 1846 | .detect = radeon_dp_detect, |
| 1833 | .fill_modes = drm_helper_probe_single_connector_modes, | 1847 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1834 | .set_property = radeon_connector_set_property, | 1848 | .set_property = radeon_connector_set_property, |
| 1849 | .early_unregister = radeon_connector_unregister, | ||
| 1835 | .destroy = radeon_connector_destroy, | 1850 | .destroy = radeon_connector_destroy, |
| 1836 | .force = radeon_dvi_force, | 1851 | .force = radeon_dvi_force, |
| 1837 | }; | 1852 | }; |
| @@ -1841,6 +1856,7 @@ static const struct drm_connector_funcs radeon_edp_connector_funcs = { | |||
| 1841 | .detect = radeon_dp_detect, | 1856 | .detect = radeon_dp_detect, |
| 1842 | .fill_modes = drm_helper_probe_single_connector_modes, | 1857 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1843 | .set_property = radeon_lvds_set_property, | 1858 | .set_property = radeon_lvds_set_property, |
| 1859 | .early_unregister = radeon_connector_unregister, | ||
| 1844 | .destroy = radeon_connector_destroy, | 1860 | .destroy = radeon_connector_destroy, |
| 1845 | .force = radeon_dvi_force, | 1861 | .force = radeon_dvi_force, |
| 1846 | }; | 1862 | }; |
| @@ -1850,6 +1866,7 @@ static const struct drm_connector_funcs radeon_lvds_bridge_connector_funcs = { | |||
| 1850 | .detect = radeon_dp_detect, | 1866 | .detect = radeon_dp_detect, |
| 1851 | .fill_modes = drm_helper_probe_single_connector_modes, | 1867 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 1852 | .set_property = radeon_lvds_set_property, | 1868 | .set_property = radeon_lvds_set_property, |
| 1869 | .early_unregister = radeon_connector_unregister, | ||
| 1853 | .destroy = radeon_connector_destroy, | 1870 | .destroy = radeon_connector_destroy, |
| 1854 | .force = radeon_dvi_force, | 1871 | .force = radeon_dvi_force, |
| 1855 | }; | 1872 | }; |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 890171f08987..cdb8cb568c15 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
| @@ -321,16 +321,30 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) | |||
| 321 | update_pending = radeon_page_flip_pending(rdev, crtc_id); | 321 | update_pending = radeon_page_flip_pending(rdev, crtc_id); |
| 322 | 322 | ||
| 323 | /* Has the pageflip already completed in crtc, or is it certain | 323 | /* Has the pageflip already completed in crtc, or is it certain |
| 324 | * to complete in this vblank? | 324 | * to complete in this vblank? GET_DISTANCE_TO_VBLANKSTART provides |
| 325 | * distance to start of "fudged earlier" vblank in vpos, distance to | ||
| 326 | * start of real vblank in hpos. vpos >= 0 && hpos < 0 means we are in | ||
| 327 | * the last few scanlines before start of real vblank, where the vblank | ||
| 328 | * irq can fire, so we have sampled update_pending a bit too early and | ||
| 329 | * know the flip will complete at leading edge of the upcoming real | ||
| 330 | * vblank. On pre-AVIVO hardware, flips also complete inside the real | ||
| 331 | * vblank, not only at leading edge, so if update_pending for hpos >= 0 | ||
| 332 | * == inside real vblank, the flip will complete almost immediately. | ||
| 333 | * Note that this method of completion handling is still not 100% race | ||
| 334 | * free, as we could execute before the radeon_flip_work_func managed | ||
| 335 | * to run and set the RADEON_FLIP_SUBMITTED status, thereby we no-op, | ||
| 336 | * but the flip still gets programmed into hw and completed during | ||
| 337 | * vblank, leading to a delayed emission of the flip completion event. | ||
| 338 | * This applies at least to pre-AVIVO hardware, where flips are always | ||
| 339 | * completing inside vblank, not only at leading edge of vblank. | ||
| 325 | */ | 340 | */ |
| 326 | if (update_pending && | 341 | if (update_pending && |
| 327 | (DRM_SCANOUTPOS_VALID & radeon_get_crtc_scanoutpos(rdev->ddev, | 342 | (DRM_SCANOUTPOS_VALID & |
| 328 | crtc_id, | 343 | radeon_get_crtc_scanoutpos(rdev->ddev, crtc_id, |
| 329 | USE_REAL_VBLANKSTART, | 344 | GET_DISTANCE_TO_VBLANKSTART, |
| 330 | &vpos, &hpos, NULL, NULL, | 345 | &vpos, &hpos, NULL, NULL, |
| 331 | &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) && | 346 | &rdev->mode_info.crtcs[crtc_id]->base.hwmode)) && |
| 332 | ((vpos >= (99 * rdev->mode_info.crtcs[crtc_id]->base.hwmode.crtc_vdisplay)/100) || | 347 | ((vpos >= 0 && hpos < 0) || (hpos >= 0 && !ASIC_IS_AVIVO(rdev)))) { |
| 333 | (vpos < 0 && !ASIC_IS_AVIVO(rdev)))) { | ||
| 334 | /* crtc didn't flip in this target vblank interval, | 348 | /* crtc didn't flip in this target vblank interval, |
| 335 | * but flip is pending in crtc. Based on the current | 349 | * but flip is pending in crtc. Based on the current |
| 336 | * scanout position we know that the current frame is | 350 | * scanout position we know that the current frame is |
| @@ -438,16 +452,19 @@ static void radeon_flip_work_func(struct work_struct *__work) | |||
| 438 | } | 452 | } |
| 439 | 453 | ||
| 440 | /* Wait until we're out of the vertical blank period before the one | 454 | /* Wait until we're out of the vertical blank period before the one |
| 441 | * targeted by the flip | 455 | * targeted by the flip. Always wait on pre DCE4 to avoid races with |
| 456 | * flip completion handling from vblank irq, as these old asics don't | ||
| 457 | * have reliable pageflip completion interrupts. | ||
| 442 | */ | 458 | */ |
| 443 | while (radeon_crtc->enabled && | 459 | while (radeon_crtc->enabled && |
| 444 | (radeon_get_crtc_scanoutpos(dev, work->crtc_id, 0, | 460 | (radeon_get_crtc_scanoutpos(dev, work->crtc_id, 0, |
| 445 | &vpos, &hpos, NULL, NULL, | 461 | &vpos, &hpos, NULL, NULL, |
| 446 | &crtc->hwmode) | 462 | &crtc->hwmode) |
| 447 | & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == | 463 | & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) == |
| 448 | (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && | 464 | (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) && |
| 449 | (int)(work->target_vblank - | 465 | (!ASIC_IS_AVIVO(rdev) || |
| 450 | dev->driver->get_vblank_counter(dev, work->crtc_id)) > 0) | 466 | ((int) (work->target_vblank - |
| 467 | dev->driver->get_vblank_counter(dev, work->crtc_id)) > 0))) | ||
| 451 | usleep_range(1000, 2000); | 468 | usleep_range(1000, 2000); |
| 452 | 469 | ||
| 453 | /* We borrow the event spin lock for protecting flip_status */ | 470 | /* We borrow the event spin lock for protecting flip_status */ |
| @@ -1658,20 +1675,20 @@ int radeon_modeset_init(struct radeon_device *rdev) | |||
| 1658 | 1675 | ||
| 1659 | void radeon_modeset_fini(struct radeon_device *rdev) | 1676 | void radeon_modeset_fini(struct radeon_device *rdev) |
| 1660 | { | 1677 | { |
| 1661 | radeon_fbdev_fini(rdev); | ||
| 1662 | kfree(rdev->mode_info.bios_hardcoded_edid); | ||
| 1663 | |||
| 1664 | /* free i2c buses */ | ||
| 1665 | radeon_i2c_fini(rdev); | ||
| 1666 | |||
| 1667 | if (rdev->mode_info.mode_config_initialized) { | 1678 | if (rdev->mode_info.mode_config_initialized) { |
| 1668 | radeon_afmt_fini(rdev); | ||
| 1669 | drm_kms_helper_poll_fini(rdev->ddev); | 1679 | drm_kms_helper_poll_fini(rdev->ddev); |
| 1670 | radeon_hpd_fini(rdev); | 1680 | radeon_hpd_fini(rdev); |
| 1671 | drm_crtc_force_disable_all(rdev->ddev); | 1681 | drm_crtc_force_disable_all(rdev->ddev); |
| 1682 | radeon_fbdev_fini(rdev); | ||
| 1683 | radeon_afmt_fini(rdev); | ||
| 1672 | drm_mode_config_cleanup(rdev->ddev); | 1684 | drm_mode_config_cleanup(rdev->ddev); |
| 1673 | rdev->mode_info.mode_config_initialized = false; | 1685 | rdev->mode_info.mode_config_initialized = false; |
| 1674 | } | 1686 | } |
| 1687 | |||
| 1688 | kfree(rdev->mode_info.bios_hardcoded_edid); | ||
| 1689 | |||
| 1690 | /* free i2c buses */ | ||
| 1691 | radeon_i2c_fini(rdev); | ||
| 1675 | } | 1692 | } |
| 1676 | 1693 | ||
| 1677 | static bool is_hdtv_mode(const struct drm_display_mode *mode) | 1694 | static bool is_hdtv_mode(const struct drm_display_mode *mode) |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 91c8f4339566..00ea0002b539 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -96,9 +96,10 @@ | |||
| 96 | * 2.45.0 - Allow setting shader registers using DMA/COPY packet3 on SI | 96 | * 2.45.0 - Allow setting shader registers using DMA/COPY packet3 on SI |
| 97 | * 2.46.0 - Add PFP_SYNC_ME support on evergreen | 97 | * 2.46.0 - Add PFP_SYNC_ME support on evergreen |
| 98 | * 2.47.0 - Add UVD_NO_OP register support | 98 | * 2.47.0 - Add UVD_NO_OP register support |
| 99 | * 2.48.0 - TA_CS_BC_BASE_ADDR allowed on SI | ||
| 99 | */ | 100 | */ |
| 100 | #define KMS_DRIVER_MAJOR 2 | 101 | #define KMS_DRIVER_MAJOR 2 |
| 101 | #define KMS_DRIVER_MINOR 47 | 102 | #define KMS_DRIVER_MINOR 48 |
| 102 | #define KMS_DRIVER_PATCHLEVEL 0 | 103 | #define KMS_DRIVER_PATCHLEVEL 0 |
| 103 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); | 104 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); |
| 104 | int radeon_driver_unload_kms(struct drm_device *dev); | 105 | int radeon_driver_unload_kms(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 021aa005623f..29f7817af821 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c | |||
| @@ -982,9 +982,8 @@ void radeon_i2c_destroy(struct radeon_i2c_chan *i2c) | |||
| 982 | { | 982 | { |
| 983 | if (!i2c) | 983 | if (!i2c) |
| 984 | return; | 984 | return; |
| 985 | WARN_ON(i2c->has_aux); | ||
| 985 | i2c_del_adapter(&i2c->adapter); | 986 | i2c_del_adapter(&i2c->adapter); |
| 986 | if (i2c->has_aux) | ||
| 987 | drm_dp_aux_unregister(&i2c->aux); | ||
| 988 | kfree(i2c); | 987 | kfree(i2c); |
| 989 | } | 988 | } |
| 990 | 989 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 455268214b89..3de5e6e21662 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c | |||
| @@ -566,7 +566,8 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_tt *ttm) | |||
| 566 | uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE; | 566 | uint64_t userptr = gtt->userptr + pinned * PAGE_SIZE; |
| 567 | struct page **pages = ttm->pages + pinned; | 567 | struct page **pages = ttm->pages + pinned; |
| 568 | 568 | ||
| 569 | r = get_user_pages(userptr, num_pages, write, 0, pages, NULL); | 569 | r = get_user_pages(userptr, num_pages, write ? FOLL_WRITE : 0, |
| 570 | pages, NULL); | ||
| 570 | if (r < 0) | 571 | if (r < 0) |
| 571 | goto release_pages; | 572 | goto release_pages; |
| 572 | 573 | ||
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 76c55c5d11ec..c55d653aaf5f 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c | |||
| @@ -406,8 +406,9 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) | |||
| 406 | for (i = 0; i < rdev->num_crtc; i++) { | 406 | for (i = 0; i < rdev->num_crtc; i++) { |
| 407 | if (save->crtc_enabled[i]) { | 407 | if (save->crtc_enabled[i]) { |
| 408 | tmp = RREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + crtc_offsets[i]); | 408 | tmp = RREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + crtc_offsets[i]); |
| 409 | if ((tmp & 0x7) != 0) { | 409 | if ((tmp & 0x7) != 3) { |
| 410 | tmp &= ~0x7; | 410 | tmp &= ~0x7; |
| 411 | tmp |= 0x3; | ||
| 411 | WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + crtc_offsets[i], tmp); | 412 | WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + crtc_offsets[i], tmp); |
| 412 | } | 413 | } |
| 413 | tmp = RREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i]); | 414 | tmp = RREG32(AVIVO_D1GRPH_UPDATE + crtc_offsets[i]); |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 7ee9aafbdf74..e402be8821c4 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -4431,6 +4431,7 @@ static bool si_vm_reg_valid(u32 reg) | |||
| 4431 | case SPI_CONFIG_CNTL: | 4431 | case SPI_CONFIG_CNTL: |
| 4432 | case SPI_CONFIG_CNTL_1: | 4432 | case SPI_CONFIG_CNTL_1: |
| 4433 | case TA_CNTL_AUX: | 4433 | case TA_CNTL_AUX: |
| 4434 | case TA_CS_BC_BASE_ADDR: | ||
| 4434 | return true; | 4435 | return true; |
| 4435 | default: | 4436 | default: |
| 4436 | DRM_ERROR("Invalid register 0x%x in CS\n", reg); | 4437 | DRM_ERROR("Invalid register 0x%x in CS\n", reg); |
diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index ba7e3d19b38d..89bdf20344ae 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c | |||
| @@ -3015,6 +3015,12 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, | |||
| 3015 | if (rdev->pdev->device == 0x6811 && | 3015 | if (rdev->pdev->device == 0x6811 && |
| 3016 | rdev->pdev->revision == 0x81) | 3016 | rdev->pdev->revision == 0x81) |
| 3017 | max_mclk = 120000; | 3017 | max_mclk = 120000; |
| 3018 | /* limit sclk/mclk on Jet parts for stability */ | ||
| 3019 | if (rdev->pdev->device == 0x6665 && | ||
| 3020 | rdev->pdev->revision == 0xc3) { | ||
| 3021 | max_sclk = 75000; | ||
| 3022 | max_mclk = 80000; | ||
| 3023 | } | ||
| 3018 | 3024 | ||
| 3019 | if (rps->vce_active) { | 3025 | if (rps->vce_active) { |
| 3020 | rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk; | 3026 | rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk; |
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index eb220eecba78..65a911ddd509 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
| @@ -1145,6 +1145,7 @@ | |||
| 1145 | #define SPI_LB_CU_MASK 0x9354 | 1145 | #define SPI_LB_CU_MASK 0x9354 |
| 1146 | 1146 | ||
| 1147 | #define TA_CNTL_AUX 0x9508 | 1147 | #define TA_CNTL_AUX 0x9508 |
| 1148 | #define TA_CS_BC_BASE_ADDR 0x950C | ||
| 1148 | 1149 | ||
| 1149 | #define CC_RB_BACKEND_DISABLE 0x98F4 | 1150 | #define CC_RB_BACKEND_DISABLE 0x98F4 |
| 1150 | #define BACKEND_DISABLE(x) ((x) << 16) | 1151 | #define BACKEND_DISABLE(x) ((x) << 16) |
diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 9688bfa92ccd..611b6b9bb3cb 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c | |||
| @@ -122,7 +122,7 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, | |||
| 122 | return 0; | 122 | return 0; |
| 123 | cmd = urb->transfer_buffer; | 123 | cmd = urb->transfer_buffer; |
| 124 | 124 | ||
| 125 | for (i = y; i < height ; i++) { | 125 | for (i = y; i < y + height ; i++) { |
| 126 | const int line_offset = fb->base.pitches[0] * i; | 126 | const int line_offset = fb->base.pitches[0] * i; |
| 127 | const int byte_offset = line_offset + (x * bpp); | 127 | const int byte_offset = line_offset + (x * bpp); |
| 128 | const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); | 128 | const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); |
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 2682f07d8f1e..7f08d681a74b 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c | |||
| @@ -229,7 +229,7 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, | |||
| 229 | * and need to make things up in a approximative but consistent way. | 229 | * and need to make things up in a approximative but consistent way. |
| 230 | */ | 230 | */ |
| 231 | ret |= DRM_SCANOUTPOS_IN_VBLANK; | 231 | ret |= DRM_SCANOUTPOS_IN_VBLANK; |
| 232 | vblank_lines = mode->crtc_vtotal - mode->crtc_vdisplay; | 232 | vblank_lines = mode->vtotal - mode->vdisplay; |
| 233 | 233 | ||
| 234 | if (flags & DRM_CALLED_FROM_VBLIRQ) { | 234 | if (flags & DRM_CALLED_FROM_VBLIRQ) { |
| 235 | /* | 235 | /* |
| @@ -378,7 +378,7 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) | |||
| 378 | struct drm_crtc_state *state = crtc->state; | 378 | struct drm_crtc_state *state = crtc->state; |
| 379 | struct drm_display_mode *mode = &state->adjusted_mode; | 379 | struct drm_display_mode *mode = &state->adjusted_mode; |
| 380 | bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; | 380 | bool interlace = mode->flags & DRM_MODE_FLAG_INTERLACE; |
| 381 | u32 vactive = (mode->vdisplay >> (interlace ? 1 : 0)); | 381 | u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; |
| 382 | u32 format = PV_CONTROL_FORMAT_24; | 382 | u32 format = PV_CONTROL_FORMAT_24; |
| 383 | bool debug_dump_regs = false; | 383 | bool debug_dump_regs = false; |
| 384 | int clock_select = vc4_get_clock_select(crtc); | 384 | int clock_select = vc4_get_clock_select(crtc); |
| @@ -394,47 +394,65 @@ static void vc4_crtc_mode_set_nofb(struct drm_crtc *crtc) | |||
| 394 | CRTC_WRITE(PV_CONTROL, 0); | 394 | CRTC_WRITE(PV_CONTROL, 0); |
| 395 | 395 | ||
| 396 | CRTC_WRITE(PV_HORZA, | 396 | CRTC_WRITE(PV_HORZA, |
| 397 | VC4_SET_FIELD(mode->htotal - mode->hsync_end, | 397 | VC4_SET_FIELD((mode->htotal - |
| 398 | mode->hsync_end) * pixel_rep, | ||
| 398 | PV_HORZA_HBP) | | 399 | PV_HORZA_HBP) | |
| 399 | VC4_SET_FIELD(mode->hsync_end - mode->hsync_start, | 400 | VC4_SET_FIELD((mode->hsync_end - |
| 401 | mode->hsync_start) * pixel_rep, | ||
| 400 | PV_HORZA_HSYNC)); | 402 | PV_HORZA_HSYNC)); |
| 401 | CRTC_WRITE(PV_HORZB, | 403 | CRTC_WRITE(PV_HORZB, |
| 402 | VC4_SET_FIELD(mode->hsync_start - mode->hdisplay, | 404 | VC4_SET_FIELD((mode->hsync_start - |
| 405 | mode->hdisplay) * pixel_rep, | ||
| 403 | PV_HORZB_HFP) | | 406 | PV_HORZB_HFP) | |
| 404 | VC4_SET_FIELD(mode->hdisplay, PV_HORZB_HACTIVE)); | 407 | VC4_SET_FIELD(mode->hdisplay * pixel_rep, PV_HORZB_HACTIVE)); |
| 405 | 408 | ||
| 406 | CRTC_WRITE(PV_VERTA, | 409 | CRTC_WRITE(PV_VERTA, |
| 407 | VC4_SET_FIELD(mode->vtotal - mode->vsync_end, | 410 | VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, |
| 408 | PV_VERTA_VBP) | | 411 | PV_VERTA_VBP) | |
| 409 | VC4_SET_FIELD(mode->vsync_end - mode->vsync_start, | 412 | VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, |
| 410 | PV_VERTA_VSYNC)); | 413 | PV_VERTA_VSYNC)); |
| 411 | CRTC_WRITE(PV_VERTB, | 414 | CRTC_WRITE(PV_VERTB, |
| 412 | VC4_SET_FIELD(mode->vsync_start - mode->vdisplay, | 415 | VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, |
| 413 | PV_VERTB_VFP) | | 416 | PV_VERTB_VFP) | |
| 414 | VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE)); | 417 | VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); |
| 415 | 418 | ||
| 416 | if (interlace) { | 419 | if (interlace) { |
| 417 | CRTC_WRITE(PV_VERTA_EVEN, | 420 | CRTC_WRITE(PV_VERTA_EVEN, |
| 418 | VC4_SET_FIELD(mode->vtotal - mode->vsync_end - 1, | 421 | VC4_SET_FIELD(mode->crtc_vtotal - |
| 422 | mode->crtc_vsync_end - 1, | ||
| 419 | PV_VERTA_VBP) | | 423 | PV_VERTA_VBP) | |
| 420 | VC4_SET_FIELD(mode->vsync_end - mode->vsync_start, | 424 | VC4_SET_FIELD(mode->crtc_vsync_end - |
| 425 | mode->crtc_vsync_start, | ||
| 421 | PV_VERTA_VSYNC)); | 426 | PV_VERTA_VSYNC)); |
| 422 | CRTC_WRITE(PV_VERTB_EVEN, | 427 | CRTC_WRITE(PV_VERTB_EVEN, |
| 423 | VC4_SET_FIELD(mode->vsync_start - mode->vdisplay, | 428 | VC4_SET_FIELD(mode->crtc_vsync_start - |
| 429 | mode->crtc_vdisplay, | ||
| 424 | PV_VERTB_VFP) | | 430 | PV_VERTB_VFP) | |
| 425 | VC4_SET_FIELD(vactive, PV_VERTB_VACTIVE)); | 431 | VC4_SET_FIELD(mode->crtc_vdisplay, PV_VERTB_VACTIVE)); |
| 432 | |||
| 433 | /* We set up first field even mode for HDMI. VEC's | ||
| 434 | * NTSC mode would want first field odd instead, once | ||
| 435 | * we support it (to do so, set ODD_FIRST and put the | ||
| 436 | * delay in VSYNCD_EVEN instead). | ||
| 437 | */ | ||
| 438 | CRTC_WRITE(PV_V_CONTROL, | ||
| 439 | PV_VCONTROL_CONTINUOUS | | ||
| 440 | PV_VCONTROL_INTERLACE | | ||
| 441 | VC4_SET_FIELD(mode->htotal * pixel_rep / 2, | ||
| 442 | PV_VCONTROL_ODD_DELAY)); | ||
| 443 | CRTC_WRITE(PV_VSYNCD_EVEN, 0); | ||
| 444 | } else { | ||
| 445 | CRTC_WRITE(PV_V_CONTROL, PV_VCONTROL_CONTINUOUS); | ||
| 426 | } | 446 | } |
| 427 | 447 | ||
| 428 | CRTC_WRITE(PV_HACT_ACT, mode->hdisplay); | 448 | CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); |
| 429 | 449 | ||
| 430 | CRTC_WRITE(PV_V_CONTROL, | ||
| 431 | PV_VCONTROL_CONTINUOUS | | ||
| 432 | (interlace ? PV_VCONTROL_INTERLACE : 0)); | ||
| 433 | 450 | ||
| 434 | CRTC_WRITE(PV_CONTROL, | 451 | CRTC_WRITE(PV_CONTROL, |
| 435 | VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | | 452 | VC4_SET_FIELD(format, PV_CONTROL_FORMAT) | |
| 436 | VC4_SET_FIELD(vc4_get_fifo_full_level(format), | 453 | VC4_SET_FIELD(vc4_get_fifo_full_level(format), |
| 437 | PV_CONTROL_FIFO_LEVEL) | | 454 | PV_CONTROL_FIFO_LEVEL) | |
| 455 | VC4_SET_FIELD(pixel_rep - 1, PV_CONTROL_PIXEL_REP) | | ||
| 438 | PV_CONTROL_CLR_AT_START | | 456 | PV_CONTROL_CLR_AT_START | |
| 439 | PV_CONTROL_TRIGGER_UNDERFLOW | | 457 | PV_CONTROL_TRIGGER_UNDERFLOW | |
| 440 | PV_CONTROL_WAIT_HSTART | | 458 | PV_CONTROL_WAIT_HSTART | |
| @@ -544,16 +562,6 @@ static bool vc4_crtc_mode_fixup(struct drm_crtc *crtc, | |||
| 544 | return false; | 562 | return false; |
| 545 | } | 563 | } |
| 546 | 564 | ||
| 547 | /* | ||
| 548 | * Interlaced video modes got CRTC_INTERLACE_HALVE_V applied when | ||
| 549 | * coming from user space. We don't want this, as it screws up | ||
| 550 | * vblank timestamping, so fix it up. | ||
| 551 | */ | ||
| 552 | drm_mode_set_crtcinfo(adjusted_mode, 0); | ||
| 553 | |||
| 554 | DRM_DEBUG_KMS("[CRTC:%d] adjusted_mode :\n", crtc->base.id); | ||
| 555 | drm_mode_debug_printmodeline(adjusted_mode); | ||
| 556 | |||
| 557 | return true; | 565 | return true; |
| 558 | } | 566 | } |
| 559 | 567 | ||
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 428e24919ef1..7c1e4d97486f 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h | |||
| @@ -122,9 +122,16 @@ to_vc4_dev(struct drm_device *dev) | |||
| 122 | struct vc4_bo { | 122 | struct vc4_bo { |
| 123 | struct drm_gem_cma_object base; | 123 | struct drm_gem_cma_object base; |
| 124 | 124 | ||
| 125 | /* seqno of the last job to render to this BO. */ | 125 | /* seqno of the last job to render using this BO. */ |
| 126 | uint64_t seqno; | 126 | uint64_t seqno; |
| 127 | 127 | ||
| 128 | /* seqno of the last job to use the RCL to write to this BO. | ||
| 129 | * | ||
| 130 | * Note that this doesn't include binner overflow memory | ||
| 131 | * writes. | ||
| 132 | */ | ||
| 133 | uint64_t write_seqno; | ||
| 134 | |||
| 128 | /* List entry for the BO's position in either | 135 | /* List entry for the BO's position in either |
| 129 | * vc4_exec_info->unref_list or vc4_dev->bo_cache.time_list | 136 | * vc4_exec_info->unref_list or vc4_dev->bo_cache.time_list |
| 130 | */ | 137 | */ |
| @@ -216,6 +223,9 @@ struct vc4_exec_info { | |||
| 216 | /* Sequence number for this bin/render job. */ | 223 | /* Sequence number for this bin/render job. */ |
| 217 | uint64_t seqno; | 224 | uint64_t seqno; |
| 218 | 225 | ||
| 226 | /* Latest write_seqno of any BO that binning depends on. */ | ||
| 227 | uint64_t bin_dep_seqno; | ||
| 228 | |||
| 219 | /* Last current addresses the hardware was processing when the | 229 | /* Last current addresses the hardware was processing when the |
| 220 | * hangcheck timer checked on us. | 230 | * hangcheck timer checked on us. |
| 221 | */ | 231 | */ |
| @@ -230,6 +240,13 @@ struct vc4_exec_info { | |||
| 230 | struct drm_gem_cma_object **bo; | 240 | struct drm_gem_cma_object **bo; |
| 231 | uint32_t bo_count; | 241 | uint32_t bo_count; |
| 232 | 242 | ||
| 243 | /* List of BOs that are being written by the RCL. Other than | ||
| 244 | * the binner temporary storage, this is all the BOs written | ||
| 245 | * by the job. | ||
| 246 | */ | ||
| 247 | struct drm_gem_cma_object *rcl_write_bo[4]; | ||
| 248 | uint32_t rcl_write_bo_count; | ||
| 249 | |||
| 233 | /* Pointers for our position in vc4->job_list */ | 250 | /* Pointers for our position in vc4->job_list */ |
| 234 | struct list_head head; | 251 | struct list_head head; |
| 235 | 252 | ||
| @@ -307,18 +324,15 @@ struct vc4_exec_info { | |||
| 307 | static inline struct vc4_exec_info * | 324 | static inline struct vc4_exec_info * |
| 308 | vc4_first_bin_job(struct vc4_dev *vc4) | 325 | vc4_first_bin_job(struct vc4_dev *vc4) |
| 309 | { | 326 | { |
| 310 | if (list_empty(&vc4->bin_job_list)) | 327 | return list_first_entry_or_null(&vc4->bin_job_list, |
| 311 | return NULL; | 328 | struct vc4_exec_info, head); |
| 312 | return list_first_entry(&vc4->bin_job_list, struct vc4_exec_info, head); | ||
| 313 | } | 329 | } |
| 314 | 330 | ||
| 315 | static inline struct vc4_exec_info * | 331 | static inline struct vc4_exec_info * |
| 316 | vc4_first_render_job(struct vc4_dev *vc4) | 332 | vc4_first_render_job(struct vc4_dev *vc4) |
| 317 | { | 333 | { |
| 318 | if (list_empty(&vc4->render_job_list)) | 334 | return list_first_entry_or_null(&vc4->render_job_list, |
| 319 | return NULL; | 335 | struct vc4_exec_info, head); |
| 320 | return list_first_entry(&vc4->render_job_list, | ||
| 321 | struct vc4_exec_info, head); | ||
| 322 | } | 336 | } |
| 323 | 337 | ||
| 324 | static inline struct vc4_exec_info * | 338 | static inline struct vc4_exec_info * |
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 77daea6cb866..47a095f392f8 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c | |||
| @@ -467,6 +467,11 @@ vc4_update_bo_seqnos(struct vc4_exec_info *exec, uint64_t seqno) | |||
| 467 | list_for_each_entry(bo, &exec->unref_list, unref_head) { | 467 | list_for_each_entry(bo, &exec->unref_list, unref_head) { |
| 468 | bo->seqno = seqno; | 468 | bo->seqno = seqno; |
| 469 | } | 469 | } |
| 470 | |||
| 471 | for (i = 0; i < exec->rcl_write_bo_count; i++) { | ||
| 472 | bo = to_vc4_bo(&exec->rcl_write_bo[i]->base); | ||
| 473 | bo->write_seqno = seqno; | ||
| 474 | } | ||
| 470 | } | 475 | } |
| 471 | 476 | ||
| 472 | /* Queues a struct vc4_exec_info for execution. If no job is | 477 | /* Queues a struct vc4_exec_info for execution. If no job is |
| @@ -669,6 +674,14 @@ vc4_get_bcl(struct drm_device *dev, struct vc4_exec_info *exec) | |||
| 669 | goto fail; | 674 | goto fail; |
| 670 | 675 | ||
| 671 | ret = vc4_validate_shader_recs(dev, exec); | 676 | ret = vc4_validate_shader_recs(dev, exec); |
| 677 | if (ret) | ||
| 678 | goto fail; | ||
| 679 | |||
| 680 | /* Block waiting on any previous rendering into the CS's VBO, | ||
| 681 | * IB, or textures, so that pixels are actually written by the | ||
| 682 | * time we try to read them. | ||
| 683 | */ | ||
| 684 | ret = vc4_wait_for_seqno(dev, exec->bin_dep_seqno, ~0ull, true); | ||
| 672 | 685 | ||
| 673 | fail: | 686 | fail: |
| 674 | drm_free_large(temp); | 687 | drm_free_large(temp); |
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 68ad10634b29..c4cb2e26de32 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c | |||
| @@ -62,6 +62,8 @@ struct vc4_hdmi { | |||
| 62 | struct vc4_hdmi_encoder { | 62 | struct vc4_hdmi_encoder { |
| 63 | struct vc4_encoder base; | 63 | struct vc4_encoder base; |
| 64 | bool hdmi_monitor; | 64 | bool hdmi_monitor; |
| 65 | bool limited_rgb_range; | ||
| 66 | bool rgb_range_selectable; | ||
| 65 | }; | 67 | }; |
| 66 | 68 | ||
| 67 | static inline struct vc4_hdmi_encoder * | 69 | static inline struct vc4_hdmi_encoder * |
| @@ -174,6 +176,9 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) | |||
| 174 | return connector_status_disconnected; | 176 | return connector_status_disconnected; |
| 175 | } | 177 | } |
| 176 | 178 | ||
| 179 | if (drm_probe_ddc(vc4->hdmi->ddc)) | ||
| 180 | return connector_status_connected; | ||
| 181 | |||
| 177 | if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) | 182 | if (HDMI_READ(VC4_HDMI_HOTPLUG) & VC4_HDMI_HOTPLUG_CONNECTED) |
| 178 | return connector_status_connected; | 183 | return connector_status_connected; |
| 179 | else | 184 | else |
| @@ -202,41 +207,22 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) | |||
| 202 | return -ENODEV; | 207 | return -ENODEV; |
| 203 | 208 | ||
| 204 | vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid); | 209 | vc4_encoder->hdmi_monitor = drm_detect_hdmi_monitor(edid); |
| 210 | |||
| 211 | if (edid && edid->input & DRM_EDID_INPUT_DIGITAL) { | ||
| 212 | vc4_encoder->rgb_range_selectable = | ||
| 213 | drm_rgb_quant_range_selectable(edid); | ||
| 214 | } | ||
| 215 | |||
| 205 | drm_mode_connector_update_edid_property(connector, edid); | 216 | drm_mode_connector_update_edid_property(connector, edid); |
| 206 | ret = drm_add_edid_modes(connector, edid); | 217 | ret = drm_add_edid_modes(connector, edid); |
| 207 | 218 | ||
| 208 | return ret; | 219 | return ret; |
| 209 | } | 220 | } |
| 210 | 221 | ||
| 211 | /* | ||
| 212 | * drm_helper_probe_single_connector_modes() applies drm_mode_set_crtcinfo to | ||
| 213 | * all modes with flag CRTC_INTERLACE_HALVE_V. We don't want this, as it | ||
| 214 | * screws up vblank timestamping for interlaced modes, so fix it up. | ||
| 215 | */ | ||
| 216 | static int vc4_hdmi_connector_probe_modes(struct drm_connector *connector, | ||
| 217 | uint32_t maxX, uint32_t maxY) | ||
| 218 | { | ||
| 219 | struct drm_display_mode *mode; | ||
| 220 | int count; | ||
| 221 | |||
| 222 | count = drm_helper_probe_single_connector_modes(connector, maxX, maxY); | ||
| 223 | if (count == 0) | ||
| 224 | return 0; | ||
| 225 | |||
| 226 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed adapted modes :\n", | ||
| 227 | connector->base.id, connector->name); | ||
| 228 | list_for_each_entry(mode, &connector->modes, head) { | ||
| 229 | drm_mode_set_crtcinfo(mode, 0); | ||
| 230 | drm_mode_debug_printmodeline(mode); | ||
| 231 | } | ||
| 232 | |||
| 233 | return count; | ||
| 234 | } | ||
| 235 | |||
| 236 | static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { | 222 | static const struct drm_connector_funcs vc4_hdmi_connector_funcs = { |
| 237 | .dpms = drm_atomic_helper_connector_dpms, | 223 | .dpms = drm_atomic_helper_connector_dpms, |
| 238 | .detect = vc4_hdmi_connector_detect, | 224 | .detect = vc4_hdmi_connector_detect, |
| 239 | .fill_modes = vc4_hdmi_connector_probe_modes, | 225 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 240 | .destroy = vc4_hdmi_connector_destroy, | 226 | .destroy = vc4_hdmi_connector_destroy, |
| 241 | .reset = drm_atomic_helper_connector_reset, | 227 | .reset = drm_atomic_helper_connector_reset, |
| 242 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, | 228 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
| @@ -294,25 +280,143 @@ static const struct drm_encoder_funcs vc4_hdmi_encoder_funcs = { | |||
| 294 | .destroy = vc4_hdmi_encoder_destroy, | 280 | .destroy = vc4_hdmi_encoder_destroy, |
| 295 | }; | 281 | }; |
| 296 | 282 | ||
| 283 | static int vc4_hdmi_stop_packet(struct drm_encoder *encoder, | ||
| 284 | enum hdmi_infoframe_type type) | ||
| 285 | { | ||
| 286 | struct drm_device *dev = encoder->dev; | ||
| 287 | struct vc4_dev *vc4 = to_vc4_dev(dev); | ||
| 288 | u32 packet_id = type - 0x80; | ||
| 289 | |||
| 290 | HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, | ||
| 291 | HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & ~BIT(packet_id)); | ||
| 292 | |||
| 293 | return wait_for(!(HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) & | ||
| 294 | BIT(packet_id)), 100); | ||
| 295 | } | ||
| 296 | |||
| 297 | static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, | ||
| 298 | union hdmi_infoframe *frame) | ||
| 299 | { | ||
| 300 | struct drm_device *dev = encoder->dev; | ||
| 301 | struct vc4_dev *vc4 = to_vc4_dev(dev); | ||
| 302 | u32 packet_id = frame->any.type - 0x80; | ||
| 303 | u32 packet_reg = VC4_HDMI_GCP_0 + VC4_HDMI_PACKET_STRIDE * packet_id; | ||
| 304 | uint8_t buffer[VC4_HDMI_PACKET_STRIDE]; | ||
| 305 | ssize_t len, i; | ||
| 306 | int ret; | ||
| 307 | |||
| 308 | WARN_ONCE(!(HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) & | ||
| 309 | VC4_HDMI_RAM_PACKET_ENABLE), | ||
| 310 | "Packet RAM has to be on to store the packet."); | ||
| 311 | |||
| 312 | len = hdmi_infoframe_pack(frame, buffer, sizeof(buffer)); | ||
| 313 | if (len < 0) | ||
| 314 | return; | ||
| 315 | |||
| 316 | ret = vc4_hdmi_stop_packet(encoder, frame->any.type); | ||
| 317 | if (ret) { | ||
| 318 | DRM_ERROR("Failed to wait for infoframe to go idle: %d\n", ret); | ||
| 319 | return; | ||
| 320 | } | ||
| 321 | |||
| 322 | for (i = 0; i < len; i += 7) { | ||
| 323 | HDMI_WRITE(packet_reg, | ||
| 324 | buffer[i + 0] << 0 | | ||
| 325 | buffer[i + 1] << 8 | | ||
| 326 | buffer[i + 2] << 16); | ||
| 327 | packet_reg += 4; | ||
| 328 | |||
| 329 | HDMI_WRITE(packet_reg, | ||
| 330 | buffer[i + 3] << 0 | | ||
| 331 | buffer[i + 4] << 8 | | ||
| 332 | buffer[i + 5] << 16 | | ||
| 333 | buffer[i + 6] << 24); | ||
| 334 | packet_reg += 4; | ||
| 335 | } | ||
| 336 | |||
| 337 | HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, | ||
| 338 | HDMI_READ(VC4_HDMI_RAM_PACKET_CONFIG) | BIT(packet_id)); | ||
| 339 | ret = wait_for((HDMI_READ(VC4_HDMI_RAM_PACKET_STATUS) & | ||
| 340 | BIT(packet_id)), 100); | ||
| 341 | if (ret) | ||
| 342 | DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret); | ||
| 343 | } | ||
| 344 | |||
| 345 | static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) | ||
| 346 | { | ||
| 347 | struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); | ||
| 348 | struct drm_crtc *crtc = encoder->crtc; | ||
| 349 | const struct drm_display_mode *mode = &crtc->state->adjusted_mode; | ||
| 350 | union hdmi_infoframe frame; | ||
| 351 | int ret; | ||
| 352 | |||
| 353 | ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode); | ||
| 354 | if (ret < 0) { | ||
| 355 | DRM_ERROR("couldn't fill AVI infoframe\n"); | ||
| 356 | return; | ||
| 357 | } | ||
| 358 | |||
| 359 | if (vc4_encoder->rgb_range_selectable) { | ||
| 360 | if (vc4_encoder->limited_rgb_range) { | ||
| 361 | frame.avi.quantization_range = | ||
| 362 | HDMI_QUANTIZATION_RANGE_LIMITED; | ||
| 363 | } else { | ||
| 364 | frame.avi.quantization_range = | ||
| 365 | HDMI_QUANTIZATION_RANGE_FULL; | ||
| 366 | } | ||
| 367 | } | ||
| 368 | |||
| 369 | vc4_hdmi_write_infoframe(encoder, &frame); | ||
| 370 | } | ||
| 371 | |||
| 372 | static void vc4_hdmi_set_spd_infoframe(struct drm_encoder *encoder) | ||
| 373 | { | ||
| 374 | union hdmi_infoframe frame; | ||
| 375 | int ret; | ||
| 376 | |||
| 377 | ret = hdmi_spd_infoframe_init(&frame.spd, "Broadcom", "Videocore"); | ||
| 378 | if (ret < 0) { | ||
| 379 | DRM_ERROR("couldn't fill SPD infoframe\n"); | ||
| 380 | return; | ||
| 381 | } | ||
| 382 | |||
| 383 | frame.spd.sdi = HDMI_SPD_SDI_PC; | ||
| 384 | |||
| 385 | vc4_hdmi_write_infoframe(encoder, &frame); | ||
| 386 | } | ||
| 387 | |||
| 388 | static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) | ||
| 389 | { | ||
| 390 | vc4_hdmi_set_avi_infoframe(encoder); | ||
| 391 | vc4_hdmi_set_spd_infoframe(encoder); | ||
| 392 | } | ||
| 393 | |||
| 297 | static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, | 394 | static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, |
| 298 | struct drm_display_mode *unadjusted_mode, | 395 | struct drm_display_mode *unadjusted_mode, |
| 299 | struct drm_display_mode *mode) | 396 | struct drm_display_mode *mode) |
| 300 | { | 397 | { |
| 398 | struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); | ||
| 301 | struct drm_device *dev = encoder->dev; | 399 | struct drm_device *dev = encoder->dev; |
| 302 | struct vc4_dev *vc4 = to_vc4_dev(dev); | 400 | struct vc4_dev *vc4 = to_vc4_dev(dev); |
| 303 | bool debug_dump_regs = false; | 401 | bool debug_dump_regs = false; |
| 304 | bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; | 402 | bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; |
| 305 | bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; | 403 | bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; |
| 306 | u32 vactive = (mode->vdisplay >> | 404 | bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; |
| 307 | ((mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0)); | 405 | u32 pixel_rep = (mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1; |
| 308 | u32 verta = (VC4_SET_FIELD(mode->vsync_end - mode->vsync_start, | 406 | u32 verta = (VC4_SET_FIELD(mode->crtc_vsync_end - mode->crtc_vsync_start, |
| 309 | VC4_HDMI_VERTA_VSP) | | 407 | VC4_HDMI_VERTA_VSP) | |
| 310 | VC4_SET_FIELD(mode->vsync_start - mode->vdisplay, | 408 | VC4_SET_FIELD(mode->crtc_vsync_start - mode->crtc_vdisplay, |
| 311 | VC4_HDMI_VERTA_VFP) | | 409 | VC4_HDMI_VERTA_VFP) | |
| 312 | VC4_SET_FIELD(vactive, VC4_HDMI_VERTA_VAL)); | 410 | VC4_SET_FIELD(mode->crtc_vdisplay, VC4_HDMI_VERTA_VAL)); |
| 313 | u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | | 411 | u32 vertb = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | |
| 314 | VC4_SET_FIELD(mode->vtotal - mode->vsync_end, | 412 | VC4_SET_FIELD(mode->crtc_vtotal - mode->crtc_vsync_end, |
| 315 | VC4_HDMI_VERTB_VBP)); | 413 | VC4_HDMI_VERTB_VBP)); |
| 414 | u32 vertb_even = (VC4_SET_FIELD(0, VC4_HDMI_VERTB_VSPO) | | ||
| 415 | VC4_SET_FIELD(mode->crtc_vtotal - | ||
| 416 | mode->crtc_vsync_end - | ||
| 417 | interlaced, | ||
| 418 | VC4_HDMI_VERTB_VBP)); | ||
| 419 | u32 csc_ctl; | ||
| 316 | 420 | ||
| 317 | if (debug_dump_regs) { | 421 | if (debug_dump_regs) { |
| 318 | DRM_INFO("HDMI regs before:\n"); | 422 | DRM_INFO("HDMI regs before:\n"); |
| @@ -321,7 +425,8 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, | |||
| 321 | 425 | ||
| 322 | HD_WRITE(VC4_HD_VID_CTL, 0); | 426 | HD_WRITE(VC4_HD_VID_CTL, 0); |
| 323 | 427 | ||
| 324 | clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000); | 428 | clk_set_rate(vc4->hdmi->pixel_clock, mode->clock * 1000 * |
| 429 | ((mode->flags & DRM_MODE_FLAG_DBLCLK) ? 2 : 1)); | ||
| 325 | 430 | ||
| 326 | HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL, | 431 | HDMI_WRITE(VC4_HDMI_SCHEDULER_CONTROL, |
| 327 | HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | | 432 | HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | |
| @@ -331,29 +436,62 @@ static void vc4_hdmi_encoder_mode_set(struct drm_encoder *encoder, | |||
| 331 | HDMI_WRITE(VC4_HDMI_HORZA, | 436 | HDMI_WRITE(VC4_HDMI_HORZA, |
| 332 | (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) | | 437 | (vsync_pos ? VC4_HDMI_HORZA_VPOS : 0) | |
| 333 | (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) | | 438 | (hsync_pos ? VC4_HDMI_HORZA_HPOS : 0) | |
| 334 | VC4_SET_FIELD(mode->hdisplay, VC4_HDMI_HORZA_HAP)); | 439 | VC4_SET_FIELD(mode->hdisplay * pixel_rep, |
| 440 | VC4_HDMI_HORZA_HAP)); | ||
| 335 | 441 | ||
| 336 | HDMI_WRITE(VC4_HDMI_HORZB, | 442 | HDMI_WRITE(VC4_HDMI_HORZB, |
| 337 | VC4_SET_FIELD(mode->htotal - mode->hsync_end, | 443 | VC4_SET_FIELD((mode->htotal - |
| 444 | mode->hsync_end) * pixel_rep, | ||
| 338 | VC4_HDMI_HORZB_HBP) | | 445 | VC4_HDMI_HORZB_HBP) | |
| 339 | VC4_SET_FIELD(mode->hsync_end - mode->hsync_start, | 446 | VC4_SET_FIELD((mode->hsync_end - |
| 447 | mode->hsync_start) * pixel_rep, | ||
| 340 | VC4_HDMI_HORZB_HSP) | | 448 | VC4_HDMI_HORZB_HSP) | |
| 341 | VC4_SET_FIELD(mode->hsync_start - mode->hdisplay, | 449 | VC4_SET_FIELD((mode->hsync_start - |
| 450 | mode->hdisplay) * pixel_rep, | ||
| 342 | VC4_HDMI_HORZB_HFP)); | 451 | VC4_HDMI_HORZB_HFP)); |
| 343 | 452 | ||
| 344 | HDMI_WRITE(VC4_HDMI_VERTA0, verta); | 453 | HDMI_WRITE(VC4_HDMI_VERTA0, verta); |
| 345 | HDMI_WRITE(VC4_HDMI_VERTA1, verta); | 454 | HDMI_WRITE(VC4_HDMI_VERTA1, verta); |
| 346 | 455 | ||
| 347 | HDMI_WRITE(VC4_HDMI_VERTB0, vertb); | 456 | HDMI_WRITE(VC4_HDMI_VERTB0, vertb_even); |
| 348 | HDMI_WRITE(VC4_HDMI_VERTB1, vertb); | 457 | HDMI_WRITE(VC4_HDMI_VERTB1, vertb); |
| 349 | 458 | ||
| 350 | HD_WRITE(VC4_HD_VID_CTL, | 459 | HD_WRITE(VC4_HD_VID_CTL, |
| 351 | (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | | 460 | (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | |
| 352 | (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); | 461 | (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); |
| 353 | 462 | ||
| 463 | csc_ctl = VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, | ||
| 464 | VC4_HD_CSC_CTL_ORDER); | ||
| 465 | |||
| 466 | if (vc4_encoder->hdmi_monitor && drm_match_cea_mode(mode) > 1) { | ||
| 467 | /* CEA VICs other than #1 requre limited range RGB | ||
| 468 | * output unless overridden by an AVI infoframe. | ||
| 469 | * Apply a colorspace conversion to squash 0-255 down | ||
| 470 | * to 16-235. The matrix here is: | ||
| 471 | * | ||
| 472 | * [ 0 0 0.8594 16] | ||
| 473 | * [ 0 0.8594 0 16] | ||
| 474 | * [ 0.8594 0 0 16] | ||
| 475 | * [ 0 0 0 1] | ||
| 476 | */ | ||
| 477 | csc_ctl |= VC4_HD_CSC_CTL_ENABLE; | ||
| 478 | csc_ctl |= VC4_HD_CSC_CTL_RGB2YCC; | ||
| 479 | csc_ctl |= VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM, | ||
| 480 | VC4_HD_CSC_CTL_MODE); | ||
| 481 | |||
| 482 | HD_WRITE(VC4_HD_CSC_12_11, (0x000 << 16) | 0x000); | ||
| 483 | HD_WRITE(VC4_HD_CSC_14_13, (0x100 << 16) | 0x6e0); | ||
| 484 | HD_WRITE(VC4_HD_CSC_22_21, (0x6e0 << 16) | 0x000); | ||
| 485 | HD_WRITE(VC4_HD_CSC_24_23, (0x100 << 16) | 0x000); | ||
| 486 | HD_WRITE(VC4_HD_CSC_32_31, (0x000 << 16) | 0x6e0); | ||
| 487 | HD_WRITE(VC4_HD_CSC_34_33, (0x100 << 16) | 0x000); | ||
| 488 | vc4_encoder->limited_rgb_range = true; | ||
| 489 | } else { | ||
| 490 | vc4_encoder->limited_rgb_range = false; | ||
| 491 | } | ||
| 492 | |||
| 354 | /* The RGB order applies even when CSC is disabled. */ | 493 | /* The RGB order applies even when CSC is disabled. */ |
| 355 | HD_WRITE(VC4_HD_CSC_CTL, VC4_SET_FIELD(VC4_HD_CSC_CTL_ORDER_BGR, | 494 | HD_WRITE(VC4_HD_CSC_CTL, csc_ctl); |
| 356 | VC4_HD_CSC_CTL_ORDER)); | ||
| 357 | 495 | ||
| 358 | HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); | 496 | HDMI_WRITE(VC4_HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); |
| 359 | 497 | ||
| @@ -368,6 +506,8 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) | |||
| 368 | struct drm_device *dev = encoder->dev; | 506 | struct drm_device *dev = encoder->dev; |
| 369 | struct vc4_dev *vc4 = to_vc4_dev(dev); | 507 | struct vc4_dev *vc4 = to_vc4_dev(dev); |
| 370 | 508 | ||
| 509 | HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, 0); | ||
| 510 | |||
| 371 | HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16); | 511 | HDMI_WRITE(VC4_HDMI_TX_PHY_RESET_CTL, 0xf << 16); |
| 372 | HD_WRITE(VC4_HD_VID_CTL, | 512 | HD_WRITE(VC4_HD_VID_CTL, |
| 373 | HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); | 513 | HD_READ(VC4_HD_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); |
| @@ -394,7 +534,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) | |||
| 394 | VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); | 534 | VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); |
| 395 | 535 | ||
| 396 | ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & | 536 | ret = wait_for(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & |
| 397 | VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1); | 537 | VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE, 1000); |
| 398 | WARN_ONCE(ret, "Timeout waiting for " | 538 | WARN_ONCE(ret, "Timeout waiting for " |
| 399 | "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n"); | 539 | "VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n"); |
| 400 | } else { | 540 | } else { |
| @@ -406,7 +546,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) | |||
| 406 | ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); | 546 | ~VC4_HDMI_SCHEDULER_CONTROL_MODE_HDMI); |
| 407 | 547 | ||
| 408 | ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & | 548 | ret = wait_for(!(HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) & |
| 409 | VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1); | 549 | VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE), 1000); |
| 410 | WARN_ONCE(ret, "Timeout waiting for " | 550 | WARN_ONCE(ret, "Timeout waiting for " |
| 411 | "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n"); | 551 | "!VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE\n"); |
| 412 | } | 552 | } |
| @@ -420,9 +560,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) | |||
| 420 | HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | | 560 | HDMI_READ(VC4_HDMI_SCHEDULER_CONTROL) | |
| 421 | VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT); | 561 | VC4_HDMI_SCHEDULER_CONTROL_VERT_ALWAYS_KEEPOUT); |
| 422 | 562 | ||
| 423 | /* XXX: Set HDMI_RAM_PACKET_CONFIG (1 << 16) and set | 563 | HDMI_WRITE(VC4_HDMI_RAM_PACKET_CONFIG, |
| 424 | * up the infoframe. | 564 | VC4_HDMI_RAM_PACKET_ENABLE); |
| 425 | */ | 565 | |
| 566 | vc4_hdmi_set_infoframes(encoder); | ||
| 426 | 567 | ||
| 427 | drift = HDMI_READ(VC4_HDMI_FIFO_CTL); | 568 | drift = HDMI_READ(VC4_HDMI_FIFO_CTL); |
| 428 | drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; | 569 | drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; |
diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 160942a9180e..1aa44c2db556 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h | |||
| @@ -175,6 +175,8 @@ | |||
| 175 | # define PV_CONTROL_CLR_AT_START BIT(14) | 175 | # define PV_CONTROL_CLR_AT_START BIT(14) |
| 176 | # define PV_CONTROL_TRIGGER_UNDERFLOW BIT(13) | 176 | # define PV_CONTROL_TRIGGER_UNDERFLOW BIT(13) |
| 177 | # define PV_CONTROL_WAIT_HSTART BIT(12) | 177 | # define PV_CONTROL_WAIT_HSTART BIT(12) |
| 178 | # define PV_CONTROL_PIXEL_REP_MASK VC4_MASK(5, 4) | ||
| 179 | # define PV_CONTROL_PIXEL_REP_SHIFT 4 | ||
| 178 | # define PV_CONTROL_CLK_SELECT_DSI_VEC 0 | 180 | # define PV_CONTROL_CLK_SELECT_DSI_VEC 0 |
| 179 | # define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1 | 181 | # define PV_CONTROL_CLK_SELECT_DPI_SMI_HDMI 1 |
| 180 | # define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2) | 182 | # define PV_CONTROL_CLK_SELECT_MASK VC4_MASK(3, 2) |
| @@ -183,6 +185,9 @@ | |||
| 183 | # define PV_CONTROL_EN BIT(0) | 185 | # define PV_CONTROL_EN BIT(0) |
| 184 | 186 | ||
| 185 | #define PV_V_CONTROL 0x04 | 187 | #define PV_V_CONTROL 0x04 |
| 188 | # define PV_VCONTROL_ODD_DELAY_MASK VC4_MASK(22, 6) | ||
| 189 | # define PV_VCONTROL_ODD_DELAY_SHIFT 6 | ||
| 190 | # define PV_VCONTROL_ODD_FIRST BIT(5) | ||
| 186 | # define PV_VCONTROL_INTERLACE BIT(4) | 191 | # define PV_VCONTROL_INTERLACE BIT(4) |
| 187 | # define PV_VCONTROL_CONTINUOUS BIT(1) | 192 | # define PV_VCONTROL_CONTINUOUS BIT(1) |
| 188 | # define PV_VCONTROL_VIDEN BIT(0) | 193 | # define PV_VCONTROL_VIDEN BIT(0) |
| @@ -438,6 +443,8 @@ | |||
| 438 | #define VC4_HDMI_RAM_PACKET_CONFIG 0x0a0 | 443 | #define VC4_HDMI_RAM_PACKET_CONFIG 0x0a0 |
| 439 | # define VC4_HDMI_RAM_PACKET_ENABLE BIT(16) | 444 | # define VC4_HDMI_RAM_PACKET_ENABLE BIT(16) |
| 440 | 445 | ||
| 446 | #define VC4_HDMI_RAM_PACKET_STATUS 0x0a4 | ||
| 447 | |||
| 441 | #define VC4_HDMI_HORZA 0x0c4 | 448 | #define VC4_HDMI_HORZA 0x0c4 |
| 442 | # define VC4_HDMI_HORZA_VPOS BIT(14) | 449 | # define VC4_HDMI_HORZA_VPOS BIT(14) |
| 443 | # define VC4_HDMI_HORZA_HPOS BIT(13) | 450 | # define VC4_HDMI_HORZA_HPOS BIT(13) |
| @@ -499,6 +506,9 @@ | |||
| 499 | 506 | ||
| 500 | #define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0 | 507 | #define VC4_HDMI_TX_PHY_RESET_CTL 0x2c0 |
| 501 | 508 | ||
| 509 | #define VC4_HDMI_GCP_0 0x400 | ||
| 510 | #define VC4_HDMI_PACKET_STRIDE 0x24 | ||
| 511 | |||
| 502 | #define VC4_HD_M_CTL 0x00c | 512 | #define VC4_HD_M_CTL 0x00c |
| 503 | # define VC4_HD_M_REGISTER_FILE_STANDBY (3 << 6) | 513 | # define VC4_HD_M_REGISTER_FILE_STANDBY (3 << 6) |
| 504 | # define VC4_HD_M_RAM_STANDBY (3 << 4) | 514 | # define VC4_HD_M_RAM_STANDBY (3 << 4) |
| @@ -528,10 +538,17 @@ | |||
| 528 | # define VC4_HD_CSC_CTL_MODE_SHIFT 2 | 538 | # define VC4_HD_CSC_CTL_MODE_SHIFT 2 |
| 529 | # define VC4_HD_CSC_CTL_MODE_RGB_TO_SD_YPRPB 0 | 539 | # define VC4_HD_CSC_CTL_MODE_RGB_TO_SD_YPRPB 0 |
| 530 | # define VC4_HD_CSC_CTL_MODE_RGB_TO_HD_YPRPB 1 | 540 | # define VC4_HD_CSC_CTL_MODE_RGB_TO_HD_YPRPB 1 |
| 531 | # define VC4_HD_CSC_CTL_MODE_CUSTOM 2 | 541 | # define VC4_HD_CSC_CTL_MODE_CUSTOM 3 |
| 532 | # define VC4_HD_CSC_CTL_RGB2YCC BIT(1) | 542 | # define VC4_HD_CSC_CTL_RGB2YCC BIT(1) |
| 533 | # define VC4_HD_CSC_CTL_ENABLE BIT(0) | 543 | # define VC4_HD_CSC_CTL_ENABLE BIT(0) |
| 534 | 544 | ||
| 545 | #define VC4_HD_CSC_12_11 0x044 | ||
| 546 | #define VC4_HD_CSC_14_13 0x048 | ||
| 547 | #define VC4_HD_CSC_22_21 0x04c | ||
| 548 | #define VC4_HD_CSC_24_23 0x050 | ||
| 549 | #define VC4_HD_CSC_32_31 0x054 | ||
| 550 | #define VC4_HD_CSC_34_33 0x058 | ||
| 551 | |||
| 535 | #define VC4_HD_FRAME_COUNT 0x068 | 552 | #define VC4_HD_FRAME_COUNT 0x068 |
| 536 | 553 | ||
| 537 | /* HVS display list information. */ | 554 | /* HVS display list information. */ |
diff --git a/drivers/gpu/drm/vc4/vc4_render_cl.c b/drivers/gpu/drm/vc4/vc4_render_cl.c index 0f12418725e5..08886a309757 100644 --- a/drivers/gpu/drm/vc4/vc4_render_cl.c +++ b/drivers/gpu/drm/vc4/vc4_render_cl.c | |||
| @@ -45,6 +45,8 @@ struct vc4_rcl_setup { | |||
| 45 | 45 | ||
| 46 | struct drm_gem_cma_object *rcl; | 46 | struct drm_gem_cma_object *rcl; |
| 47 | u32 next_offset; | 47 | u32 next_offset; |
| 48 | |||
| 49 | u32 next_write_bo_index; | ||
| 48 | }; | 50 | }; |
| 49 | 51 | ||
| 50 | static inline void rcl_u8(struct vc4_rcl_setup *setup, u8 val) | 52 | static inline void rcl_u8(struct vc4_rcl_setup *setup, u8 val) |
| @@ -407,6 +409,8 @@ static int vc4_rcl_msaa_surface_setup(struct vc4_exec_info *exec, | |||
| 407 | if (!*obj) | 409 | if (!*obj) |
| 408 | return -EINVAL; | 410 | return -EINVAL; |
| 409 | 411 | ||
| 412 | exec->rcl_write_bo[exec->rcl_write_bo_count++] = *obj; | ||
| 413 | |||
| 410 | if (surf->offset & 0xf) { | 414 | if (surf->offset & 0xf) { |
| 411 | DRM_ERROR("MSAA write must be 16b aligned.\n"); | 415 | DRM_ERROR("MSAA write must be 16b aligned.\n"); |
| 412 | return -EINVAL; | 416 | return -EINVAL; |
| @@ -417,7 +421,8 @@ static int vc4_rcl_msaa_surface_setup(struct vc4_exec_info *exec, | |||
| 417 | 421 | ||
| 418 | static int vc4_rcl_surface_setup(struct vc4_exec_info *exec, | 422 | static int vc4_rcl_surface_setup(struct vc4_exec_info *exec, |
| 419 | struct drm_gem_cma_object **obj, | 423 | struct drm_gem_cma_object **obj, |
| 420 | struct drm_vc4_submit_rcl_surface *surf) | 424 | struct drm_vc4_submit_rcl_surface *surf, |
| 425 | bool is_write) | ||
| 421 | { | 426 | { |
| 422 | uint8_t tiling = VC4_GET_FIELD(surf->bits, | 427 | uint8_t tiling = VC4_GET_FIELD(surf->bits, |
| 423 | VC4_LOADSTORE_TILE_BUFFER_TILING); | 428 | VC4_LOADSTORE_TILE_BUFFER_TILING); |
| @@ -440,6 +445,9 @@ static int vc4_rcl_surface_setup(struct vc4_exec_info *exec, | |||
| 440 | if (!*obj) | 445 | if (!*obj) |
| 441 | return -EINVAL; | 446 | return -EINVAL; |
| 442 | 447 | ||
| 448 | if (is_write) | ||
| 449 | exec->rcl_write_bo[exec->rcl_write_bo_count++] = *obj; | ||
| 450 | |||
| 443 | if (surf->flags & VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) { | 451 | if (surf->flags & VC4_SUBMIT_RCL_SURFACE_READ_IS_FULL_RES) { |
| 444 | if (surf == &exec->args->zs_write) { | 452 | if (surf == &exec->args->zs_write) { |
| 445 | DRM_ERROR("general zs write may not be a full-res.\n"); | 453 | DRM_ERROR("general zs write may not be a full-res.\n"); |
| @@ -542,6 +550,8 @@ vc4_rcl_render_config_surface_setup(struct vc4_exec_info *exec, | |||
| 542 | if (!*obj) | 550 | if (!*obj) |
| 543 | return -EINVAL; | 551 | return -EINVAL; |
| 544 | 552 | ||
| 553 | exec->rcl_write_bo[exec->rcl_write_bo_count++] = *obj; | ||
| 554 | |||
| 545 | if (tiling > VC4_TILING_FORMAT_LT) { | 555 | if (tiling > VC4_TILING_FORMAT_LT) { |
| 546 | DRM_ERROR("Bad tiling format\n"); | 556 | DRM_ERROR("Bad tiling format\n"); |
| 547 | return -EINVAL; | 557 | return -EINVAL; |
| @@ -599,15 +609,18 @@ int vc4_get_rcl(struct drm_device *dev, struct vc4_exec_info *exec) | |||
| 599 | if (ret) | 609 | if (ret) |
| 600 | return ret; | 610 | return ret; |
| 601 | 611 | ||
| 602 | ret = vc4_rcl_surface_setup(exec, &setup.color_read, &args->color_read); | 612 | ret = vc4_rcl_surface_setup(exec, &setup.color_read, &args->color_read, |
| 613 | false); | ||
| 603 | if (ret) | 614 | if (ret) |
| 604 | return ret; | 615 | return ret; |
| 605 | 616 | ||
| 606 | ret = vc4_rcl_surface_setup(exec, &setup.zs_read, &args->zs_read); | 617 | ret = vc4_rcl_surface_setup(exec, &setup.zs_read, &args->zs_read, |
| 618 | false); | ||
| 607 | if (ret) | 619 | if (ret) |
| 608 | return ret; | 620 | return ret; |
| 609 | 621 | ||
| 610 | ret = vc4_rcl_surface_setup(exec, &setup.zs_write, &args->zs_write); | 622 | ret = vc4_rcl_surface_setup(exec, &setup.zs_write, &args->zs_write, |
| 623 | true); | ||
| 611 | if (ret) | 624 | if (ret) |
| 612 | return ret; | 625 | return ret; |
| 613 | 626 | ||
diff --git a/drivers/gpu/drm/vc4/vc4_validate.c b/drivers/gpu/drm/vc4/vc4_validate.c index 9ce1d0adf882..26503e307438 100644 --- a/drivers/gpu/drm/vc4/vc4_validate.c +++ b/drivers/gpu/drm/vc4/vc4_validate.c | |||
| @@ -267,6 +267,9 @@ validate_indexed_prim_list(VALIDATE_ARGS) | |||
| 267 | if (!ib) | 267 | if (!ib) |
| 268 | return -EINVAL; | 268 | return -EINVAL; |
| 269 | 269 | ||
| 270 | exec->bin_dep_seqno = max(exec->bin_dep_seqno, | ||
| 271 | to_vc4_bo(&ib->base)->write_seqno); | ||
| 272 | |||
| 270 | if (offset > ib->base.size || | 273 | if (offset > ib->base.size || |
| 271 | (ib->base.size - offset) / index_size < length) { | 274 | (ib->base.size - offset) / index_size < length) { |
| 272 | DRM_ERROR("IB access overflow (%d + %d*%d > %zd)\n", | 275 | DRM_ERROR("IB access overflow (%d + %d*%d > %zd)\n", |
| @@ -555,8 +558,7 @@ static bool | |||
| 555 | reloc_tex(struct vc4_exec_info *exec, | 558 | reloc_tex(struct vc4_exec_info *exec, |
| 556 | void *uniform_data_u, | 559 | void *uniform_data_u, |
| 557 | struct vc4_texture_sample_info *sample, | 560 | struct vc4_texture_sample_info *sample, |
| 558 | uint32_t texture_handle_index) | 561 | uint32_t texture_handle_index, bool is_cs) |
| 559 | |||
| 560 | { | 562 | { |
| 561 | struct drm_gem_cma_object *tex; | 563 | struct drm_gem_cma_object *tex; |
| 562 | uint32_t p0 = *(uint32_t *)(uniform_data_u + sample->p_offset[0]); | 564 | uint32_t p0 = *(uint32_t *)(uniform_data_u + sample->p_offset[0]); |
| @@ -714,6 +716,11 @@ reloc_tex(struct vc4_exec_info *exec, | |||
| 714 | 716 | ||
| 715 | *validated_p0 = tex->paddr + p0; | 717 | *validated_p0 = tex->paddr + p0; |
| 716 | 718 | ||
| 719 | if (is_cs) { | ||
| 720 | exec->bin_dep_seqno = max(exec->bin_dep_seqno, | ||
| 721 | to_vc4_bo(&tex->base)->write_seqno); | ||
| 722 | } | ||
| 723 | |||
| 717 | return true; | 724 | return true; |
| 718 | fail: | 725 | fail: |
| 719 | DRM_INFO("Texture p0 at %d: 0x%08x\n", sample->p_offset[0], p0); | 726 | DRM_INFO("Texture p0 at %d: 0x%08x\n", sample->p_offset[0], p0); |
| @@ -835,7 +842,8 @@ validate_gl_shader_rec(struct drm_device *dev, | |||
| 835 | if (!reloc_tex(exec, | 842 | if (!reloc_tex(exec, |
| 836 | uniform_data_u, | 843 | uniform_data_u, |
| 837 | &validated_shader->texture_samples[tex], | 844 | &validated_shader->texture_samples[tex], |
| 838 | texture_handles_u[tex])) { | 845 | texture_handles_u[tex], |
| 846 | i == 2)) { | ||
| 839 | return -EINVAL; | 847 | return -EINVAL; |
| 840 | } | 848 | } |
| 841 | } | 849 | } |
| @@ -867,6 +875,9 @@ validate_gl_shader_rec(struct drm_device *dev, | |||
| 867 | uint32_t stride = *(uint8_t *)(pkt_u + o + 5); | 875 | uint32_t stride = *(uint8_t *)(pkt_u + o + 5); |
| 868 | uint32_t max_index; | 876 | uint32_t max_index; |
| 869 | 877 | ||
| 878 | exec->bin_dep_seqno = max(exec->bin_dep_seqno, | ||
| 879 | to_vc4_bo(&vbo->base)->write_seqno); | ||
| 880 | |||
| 870 | if (state->addr & 0x8) | 881 | if (state->addr & 0x8) |
| 871 | stride |= (*(uint32_t *)(pkt_u + 100 + i * 4)) & ~0xff; | 882 | stride |= (*(uint32_t *)(pkt_u + 100 + i * 4)) & ~0xff; |
| 872 | 883 | ||
diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c index 7e2a12c4fed2..1a3ad769f8c8 100644 --- a/drivers/gpu/drm/via/via_dmablit.c +++ b/drivers/gpu/drm/via/via_dmablit.c | |||
| @@ -241,8 +241,8 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) | |||
| 241 | down_read(¤t->mm->mmap_sem); | 241 | down_read(¤t->mm->mmap_sem); |
| 242 | ret = get_user_pages((unsigned long)xfer->mem_addr, | 242 | ret = get_user_pages((unsigned long)xfer->mem_addr, |
| 243 | vsg->num_pages, | 243 | vsg->num_pages, |
| 244 | (vsg->direction == DMA_FROM_DEVICE), | 244 | (vsg->direction == DMA_FROM_DEVICE) ? FOLL_WRITE : 0, |
| 245 | 0, vsg->pages, NULL); | 245 | vsg->pages, NULL); |
| 246 | 246 | ||
| 247 | up_read(¤t->mm->mmap_sem); | 247 | up_read(¤t->mm->mmap_sem); |
| 248 | if (ret != vsg->num_pages) { | 248 | if (ret != vsg->num_pages) { |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index e8ae3dc476d1..18061a4bc2f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
| @@ -241,15 +241,15 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, | |||
| 241 | void *ptr); | 241 | void *ptr); |
| 242 | 242 | ||
| 243 | MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev"); | 243 | MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev"); |
| 244 | module_param_named(enable_fbdev, enable_fbdev, int, 0600); | 244 | module_param_named(enable_fbdev, enable_fbdev, int, S_IRUSR | S_IWUSR); |
| 245 | MODULE_PARM_DESC(force_dma_api, "Force using the DMA API for TTM pages"); | 245 | MODULE_PARM_DESC(force_dma_api, "Force using the DMA API for TTM pages"); |
| 246 | module_param_named(force_dma_api, vmw_force_iommu, int, 0600); | 246 | module_param_named(force_dma_api, vmw_force_iommu, int, S_IRUSR | S_IWUSR); |
| 247 | MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages"); | 247 | MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages"); |
| 248 | module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600); | 248 | module_param_named(restrict_iommu, vmw_restrict_iommu, int, S_IRUSR | S_IWUSR); |
| 249 | MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages"); | 249 | MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages"); |
| 250 | module_param_named(force_coherent, vmw_force_coherent, int, 0600); | 250 | module_param_named(force_coherent, vmw_force_coherent, int, S_IRUSR | S_IWUSR); |
| 251 | MODULE_PARM_DESC(restrict_dma_mask, "Restrict DMA mask to 44 bits with IOMMU"); | 251 | MODULE_PARM_DESC(restrict_dma_mask, "Restrict DMA mask to 44 bits with IOMMU"); |
| 252 | module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, 0600); | 252 | module_param_named(restrict_dma_mask, vmw_restrict_dma_mask, int, S_IRUSR | S_IWUSR); |
| 253 | MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes"); | 253 | MODULE_PARM_DESC(assume_16bpp, "Assume 16-bpp when filtering modes"); |
| 254 | module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600); | 254 | module_param_named(assume_16bpp, vmw_assume_16bpp, int, 0600); |
| 255 | 255 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 070d750af16d..1e59a486bba8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
| @@ -43,7 +43,7 @@ | |||
| 43 | 43 | ||
| 44 | #define VMWGFX_DRIVER_DATE "20160210" | 44 | #define VMWGFX_DRIVER_DATE "20160210" |
| 45 | #define VMWGFX_DRIVER_MAJOR 2 | 45 | #define VMWGFX_DRIVER_MAJOR 2 |
| 46 | #define VMWGFX_DRIVER_MINOR 10 | 46 | #define VMWGFX_DRIVER_MINOR 11 |
| 47 | #define VMWGFX_DRIVER_PATCHLEVEL 0 | 47 | #define VMWGFX_DRIVER_PATCHLEVEL 0 |
| 48 | #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 | 48 | #define VMWGFX_FILE_PAGE_OFFSET 0x00100000 |
| 49 | #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) | 49 | #define VMWGFX_FIFO_STATIC_SIZE (1024*1024) |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index dc5beff2b4aa..c7b53d987f06 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | |||
| @@ -35,17 +35,37 @@ | |||
| 35 | #define VMW_RES_HT_ORDER 12 | 35 | #define VMW_RES_HT_ORDER 12 |
| 36 | 36 | ||
| 37 | /** | 37 | /** |
| 38 | * enum vmw_resource_relocation_type - Relocation type for resources | ||
| 39 | * | ||
| 40 | * @vmw_res_rel_normal: Traditional relocation. The resource id in the | ||
| 41 | * command stream is replaced with the actual id after validation. | ||
| 42 | * @vmw_res_rel_nop: NOP relocation. The command is unconditionally replaced | ||
| 43 | * with a NOP. | ||
| 44 | * @vmw_res_rel_cond_nop: Conditional NOP relocation. If the resource id | ||
| 45 | * after validation is -1, the command is replaced with a NOP. Otherwise no | ||
| 46 | * action. | ||
| 47 | */ | ||
| 48 | enum vmw_resource_relocation_type { | ||
| 49 | vmw_res_rel_normal, | ||
| 50 | vmw_res_rel_nop, | ||
| 51 | vmw_res_rel_cond_nop, | ||
| 52 | vmw_res_rel_max | ||
| 53 | }; | ||
| 54 | |||
| 55 | /** | ||
| 38 | * struct vmw_resource_relocation - Relocation info for resources | 56 | * struct vmw_resource_relocation - Relocation info for resources |
| 39 | * | 57 | * |
| 40 | * @head: List head for the software context's relocation list. | 58 | * @head: List head for the software context's relocation list. |
| 41 | * @res: Non-ref-counted pointer to the resource. | 59 | * @res: Non-ref-counted pointer to the resource. |
| 42 | * @offset: Offset of 4 byte entries into the command buffer where the | 60 | * @offset: Offset of single byte entries into the command buffer where the |
| 43 | * id that needs fixup is located. | 61 | * id that needs fixup is located. |
| 62 | * @rel_type: Type of relocation. | ||
| 44 | */ | 63 | */ |
| 45 | struct vmw_resource_relocation { | 64 | struct vmw_resource_relocation { |
| 46 | struct list_head head; | 65 | struct list_head head; |
| 47 | const struct vmw_resource *res; | 66 | const struct vmw_resource *res; |
| 48 | unsigned long offset; | 67 | u32 offset:29; |
| 68 | enum vmw_resource_relocation_type rel_type:3; | ||
| 49 | }; | 69 | }; |
| 50 | 70 | ||
| 51 | /** | 71 | /** |
| @@ -109,7 +129,18 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, | |||
| 109 | struct vmw_dma_buffer *vbo, | 129 | struct vmw_dma_buffer *vbo, |
| 110 | bool validate_as_mob, | 130 | bool validate_as_mob, |
| 111 | uint32_t *p_val_node); | 131 | uint32_t *p_val_node); |
| 112 | 132 | /** | |
| 133 | * vmw_ptr_diff - Compute the offset from a to b in bytes | ||
| 134 | * | ||
| 135 | * @a: A starting pointer. | ||
| 136 | * @b: A pointer offset in the same address space. | ||
| 137 | * | ||
| 138 | * Returns: The offset in bytes between the two pointers. | ||
| 139 | */ | ||
| 140 | static size_t vmw_ptr_diff(void *a, void *b) | ||
| 141 | { | ||
| 142 | return (unsigned long) b - (unsigned long) a; | ||
| 143 | } | ||
| 113 | 144 | ||
| 114 | /** | 145 | /** |
| 115 | * vmw_resources_unreserve - unreserve resources previously reserved for | 146 | * vmw_resources_unreserve - unreserve resources previously reserved for |
| @@ -409,11 +440,14 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, | |||
| 409 | * @list: Pointer to head of relocation list. | 440 | * @list: Pointer to head of relocation list. |
| 410 | * @res: The resource. | 441 | * @res: The resource. |
| 411 | * @offset: Offset into the command buffer currently being parsed where the | 442 | * @offset: Offset into the command buffer currently being parsed where the |
| 412 | * id that needs fixup is located. Granularity is 4 bytes. | 443 | * id that needs fixup is located. Granularity is one byte. |
| 444 | * @rel_type: Relocation type. | ||
| 413 | */ | 445 | */ |
| 414 | static int vmw_resource_relocation_add(struct list_head *list, | 446 | static int vmw_resource_relocation_add(struct list_head *list, |
| 415 | const struct vmw_resource *res, | 447 | const struct vmw_resource *res, |
| 416 | unsigned long offset) | 448 | unsigned long offset, |
| 449 | enum vmw_resource_relocation_type | ||
| 450 | rel_type) | ||
| 417 | { | 451 | { |
| 418 | struct vmw_resource_relocation *rel; | 452 | struct vmw_resource_relocation *rel; |
| 419 | 453 | ||
| @@ -425,6 +459,7 @@ static int vmw_resource_relocation_add(struct list_head *list, | |||
| 425 | 459 | ||
| 426 | rel->res = res; | 460 | rel->res = res; |
| 427 | rel->offset = offset; | 461 | rel->offset = offset; |
| 462 | rel->rel_type = rel_type; | ||
| 428 | list_add_tail(&rel->head, list); | 463 | list_add_tail(&rel->head, list); |
| 429 | 464 | ||
| 430 | return 0; | 465 | return 0; |
| @@ -459,11 +494,24 @@ static void vmw_resource_relocations_apply(uint32_t *cb, | |||
| 459 | { | 494 | { |
| 460 | struct vmw_resource_relocation *rel; | 495 | struct vmw_resource_relocation *rel; |
| 461 | 496 | ||
| 497 | /* Validate the struct vmw_resource_relocation member size */ | ||
| 498 | BUILD_BUG_ON(SVGA_CB_MAX_SIZE >= (1 << 29)); | ||
| 499 | BUILD_BUG_ON(vmw_res_rel_max >= (1 << 3)); | ||
| 500 | |||
| 462 | list_for_each_entry(rel, list, head) { | 501 | list_for_each_entry(rel, list, head) { |
| 463 | if (likely(rel->res != NULL)) | 502 | u32 *addr = (u32 *)((unsigned long) cb + rel->offset); |
| 464 | cb[rel->offset] = rel->res->id; | 503 | switch (rel->rel_type) { |
| 465 | else | 504 | case vmw_res_rel_normal: |
| 466 | cb[rel->offset] = SVGA_3D_CMD_NOP; | 505 | *addr = rel->res->id; |
| 506 | break; | ||
| 507 | case vmw_res_rel_nop: | ||
| 508 | *addr = SVGA_3D_CMD_NOP; | ||
| 509 | break; | ||
| 510 | default: | ||
| 511 | if (rel->res->id == -1) | ||
| 512 | *addr = SVGA_3D_CMD_NOP; | ||
| 513 | break; | ||
| 514 | } | ||
| 467 | } | 515 | } |
| 468 | } | 516 | } |
| 469 | 517 | ||
| @@ -655,7 +703,9 @@ static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv, | |||
| 655 | *p_val = NULL; | 703 | *p_val = NULL; |
| 656 | ret = vmw_resource_relocation_add(&sw_context->res_relocations, | 704 | ret = vmw_resource_relocation_add(&sw_context->res_relocations, |
| 657 | res, | 705 | res, |
| 658 | id_loc - sw_context->buf_start); | 706 | vmw_ptr_diff(sw_context->buf_start, |
| 707 | id_loc), | ||
| 708 | vmw_res_rel_normal); | ||
| 659 | if (unlikely(ret != 0)) | 709 | if (unlikely(ret != 0)) |
| 660 | return ret; | 710 | return ret; |
| 661 | 711 | ||
| @@ -721,7 +771,8 @@ vmw_cmd_res_check(struct vmw_private *dev_priv, | |||
| 721 | 771 | ||
| 722 | return vmw_resource_relocation_add | 772 | return vmw_resource_relocation_add |
| 723 | (&sw_context->res_relocations, res, | 773 | (&sw_context->res_relocations, res, |
| 724 | id_loc - sw_context->buf_start); | 774 | vmw_ptr_diff(sw_context->buf_start, id_loc), |
| 775 | vmw_res_rel_normal); | ||
| 725 | } | 776 | } |
| 726 | 777 | ||
| 727 | ret = vmw_user_resource_lookup_handle(dev_priv, | 778 | ret = vmw_user_resource_lookup_handle(dev_priv, |
| @@ -2143,10 +2194,10 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv, | |||
| 2143 | return ret; | 2194 | return ret; |
| 2144 | 2195 | ||
| 2145 | return vmw_resource_relocation_add(&sw_context->res_relocations, | 2196 | return vmw_resource_relocation_add(&sw_context->res_relocations, |
| 2146 | NULL, &cmd->header.id - | 2197 | NULL, |
| 2147 | sw_context->buf_start); | 2198 | vmw_ptr_diff(sw_context->buf_start, |
| 2148 | 2199 | &cmd->header.id), | |
| 2149 | return 0; | 2200 | vmw_res_rel_nop); |
| 2150 | } | 2201 | } |
| 2151 | 2202 | ||
| 2152 | /** | 2203 | /** |
| @@ -2188,10 +2239,10 @@ static int vmw_cmd_shader_destroy(struct vmw_private *dev_priv, | |||
| 2188 | return ret; | 2239 | return ret; |
| 2189 | 2240 | ||
| 2190 | return vmw_resource_relocation_add(&sw_context->res_relocations, | 2241 | return vmw_resource_relocation_add(&sw_context->res_relocations, |
| 2191 | NULL, &cmd->header.id - | 2242 | NULL, |
| 2192 | sw_context->buf_start); | 2243 | vmw_ptr_diff(sw_context->buf_start, |
| 2193 | 2244 | &cmd->header.id), | |
| 2194 | return 0; | 2245 | vmw_res_rel_nop); |
| 2195 | } | 2246 | } |
| 2196 | 2247 | ||
| 2197 | /** | 2248 | /** |
| @@ -2848,8 +2899,7 @@ static int vmw_cmd_dx_cid_check(struct vmw_private *dev_priv, | |||
| 2848 | * @header: Pointer to the command header in the command stream. | 2899 | * @header: Pointer to the command header in the command stream. |
| 2849 | * | 2900 | * |
| 2850 | * Check that the view exists, and if it was not created using this | 2901 | * Check that the view exists, and if it was not created using this |
| 2851 | * command batch, make sure it's validated (present in the device) so that | 2902 | * command batch, conditionally make this command a NOP. |
| 2852 | * the remove command will not confuse the device. | ||
| 2853 | */ | 2903 | */ |
| 2854 | static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv, | 2904 | static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv, |
| 2855 | struct vmw_sw_context *sw_context, | 2905 | struct vmw_sw_context *sw_context, |
| @@ -2877,10 +2927,16 @@ static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv, | |||
| 2877 | return ret; | 2927 | return ret; |
| 2878 | 2928 | ||
| 2879 | /* | 2929 | /* |
| 2880 | * Add view to the validate list iff it was not created using this | 2930 | * If the view wasn't created during this command batch, it might |
| 2881 | * command batch. | 2931 | * have been removed due to a context swapout, so add a |
| 2932 | * relocation to conditionally make this command a NOP to avoid | ||
| 2933 | * device errors. | ||
| 2882 | */ | 2934 | */ |
| 2883 | return vmw_view_res_val_add(sw_context, view); | 2935 | return vmw_resource_relocation_add(&sw_context->res_relocations, |
| 2936 | view, | ||
| 2937 | vmw_ptr_diff(sw_context->buf_start, | ||
| 2938 | &cmd->header.id), | ||
| 2939 | vmw_res_rel_cond_nop); | ||
| 2884 | } | 2940 | } |
| 2885 | 2941 | ||
| 2886 | /** | 2942 | /** |
| @@ -3029,6 +3085,35 @@ static int vmw_cmd_dx_genmips(struct vmw_private *dev_priv, | |||
| 3029 | cmd->body.shaderResourceViewId); | 3085 | cmd->body.shaderResourceViewId); |
| 3030 | } | 3086 | } |
| 3031 | 3087 | ||
| 3088 | /** | ||
| 3089 | * vmw_cmd_dx_transfer_from_buffer - | ||
| 3090 | * Validate an SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER command | ||
| 3091 | * | ||
| 3092 | * @dev_priv: Pointer to a device private struct. | ||
| 3093 | * @sw_context: The software context being used for this batch. | ||
| 3094 | * @header: Pointer to the command header in the command stream. | ||
| 3095 | */ | ||
| 3096 | static int vmw_cmd_dx_transfer_from_buffer(struct vmw_private *dev_priv, | ||
| 3097 | struct vmw_sw_context *sw_context, | ||
| 3098 | SVGA3dCmdHeader *header) | ||
| 3099 | { | ||
| 3100 | struct { | ||
| 3101 | SVGA3dCmdHeader header; | ||
| 3102 | SVGA3dCmdDXTransferFromBuffer body; | ||
| 3103 | } *cmd = container_of(header, typeof(*cmd), header); | ||
| 3104 | int ret; | ||
| 3105 | |||
| 3106 | ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | ||
| 3107 | user_surface_converter, | ||
| 3108 | &cmd->body.srcSid, NULL); | ||
| 3109 | if (ret != 0) | ||
| 3110 | return ret; | ||
| 3111 | |||
| 3112 | return vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, | ||
| 3113 | user_surface_converter, | ||
| 3114 | &cmd->body.destSid, NULL); | ||
| 3115 | } | ||
| 3116 | |||
| 3032 | static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, | 3117 | static int vmw_cmd_check_not_3d(struct vmw_private *dev_priv, |
| 3033 | struct vmw_sw_context *sw_context, | 3118 | struct vmw_sw_context *sw_context, |
| 3034 | void *buf, uint32_t *size) | 3119 | void *buf, uint32_t *size) |
| @@ -3379,6 +3464,9 @@ static const struct vmw_cmd_entry vmw_cmd_entries[SVGA_3D_CMD_MAX] = { | |||
| 3379 | &vmw_cmd_buffer_copy_check, true, false, true), | 3464 | &vmw_cmd_buffer_copy_check, true, false, true), |
| 3380 | VMW_CMD_DEF(SVGA_3D_CMD_DX_PRED_COPY_REGION, | 3465 | VMW_CMD_DEF(SVGA_3D_CMD_DX_PRED_COPY_REGION, |
| 3381 | &vmw_cmd_pred_copy_check, true, false, true), | 3466 | &vmw_cmd_pred_copy_check, true, false, true), |
| 3467 | VMW_CMD_DEF(SVGA_3D_CMD_DX_TRANSFER_FROM_BUFFER, | ||
| 3468 | &vmw_cmd_dx_transfer_from_buffer, | ||
| 3469 | true, false, true), | ||
| 3382 | }; | 3470 | }; |
| 3383 | 3471 | ||
| 3384 | static int vmw_cmd_check(struct vmw_private *dev_priv, | 3472 | static int vmw_cmd_check(struct vmw_private *dev_priv, |
| @@ -3848,14 +3936,14 @@ static void *vmw_execbuf_cmdbuf(struct vmw_private *dev_priv, | |||
| 3848 | int ret; | 3936 | int ret; |
| 3849 | 3937 | ||
| 3850 | *header = NULL; | 3938 | *header = NULL; |
| 3851 | if (!dev_priv->cman || kernel_commands) | ||
| 3852 | return kernel_commands; | ||
| 3853 | |||
| 3854 | if (command_size > SVGA_CB_MAX_SIZE) { | 3939 | if (command_size > SVGA_CB_MAX_SIZE) { |
| 3855 | DRM_ERROR("Command buffer is too large.\n"); | 3940 | DRM_ERROR("Command buffer is too large.\n"); |
| 3856 | return ERR_PTR(-EINVAL); | 3941 | return ERR_PTR(-EINVAL); |
| 3857 | } | 3942 | } |
| 3858 | 3943 | ||
| 3944 | if (!dev_priv->cman || kernel_commands) | ||
| 3945 | return kernel_commands; | ||
| 3946 | |||
| 3859 | /* If possible, add a little space for fencing. */ | 3947 | /* If possible, add a little space for fencing. */ |
| 3860 | cmdbuf_size = command_size + 512; | 3948 | cmdbuf_size = command_size + 512; |
| 3861 | cmdbuf_size = min_t(size_t, cmdbuf_size, SVGA_CB_MAX_SIZE); | 3949 | cmdbuf_size = min_t(size_t, cmdbuf_size, SVGA_CB_MAX_SIZE); |
| @@ -4232,9 +4320,6 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, | |||
| 4232 | ttm_bo_unref(&query_val.bo); | 4320 | ttm_bo_unref(&query_val.bo); |
| 4233 | ttm_bo_unref(&pinned_val.bo); | 4321 | ttm_bo_unref(&pinned_val.bo); |
| 4234 | vmw_dmabuf_unreference(&dev_priv->pinned_bo); | 4322 | vmw_dmabuf_unreference(&dev_priv->pinned_bo); |
| 4235 | DRM_INFO("Dummy query bo pin count: %d\n", | ||
| 4236 | dev_priv->dummy_query_bo->pin_count); | ||
| 4237 | |||
| 4238 | out_unlock: | 4323 | out_unlock: |
| 4239 | return; | 4324 | return; |
| 4240 | 4325 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index c2a721a8cef9..b445ce9b9757 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | |||
| @@ -324,7 +324,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res) | |||
| 324 | if (res->id != -1) { | 324 | if (res->id != -1) { |
| 325 | 325 | ||
| 326 | cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size()); | 326 | cmd = vmw_fifo_reserve(dev_priv, vmw_surface_destroy_size()); |
| 327 | if (unlikely(cmd == NULL)) { | 327 | if (unlikely(!cmd)) { |
| 328 | DRM_ERROR("Failed reserving FIFO space for surface " | 328 | DRM_ERROR("Failed reserving FIFO space for surface " |
| 329 | "destruction.\n"); | 329 | "destruction.\n"); |
| 330 | return; | 330 | return; |
| @@ -397,7 +397,7 @@ static int vmw_legacy_srf_create(struct vmw_resource *res) | |||
| 397 | 397 | ||
| 398 | submit_size = vmw_surface_define_size(srf); | 398 | submit_size = vmw_surface_define_size(srf); |
| 399 | cmd = vmw_fifo_reserve(dev_priv, submit_size); | 399 | cmd = vmw_fifo_reserve(dev_priv, submit_size); |
| 400 | if (unlikely(cmd == NULL)) { | 400 | if (unlikely(!cmd)) { |
| 401 | DRM_ERROR("Failed reserving FIFO space for surface " | 401 | DRM_ERROR("Failed reserving FIFO space for surface " |
| 402 | "creation.\n"); | 402 | "creation.\n"); |
| 403 | ret = -ENOMEM; | 403 | ret = -ENOMEM; |
| @@ -446,11 +446,10 @@ static int vmw_legacy_srf_dma(struct vmw_resource *res, | |||
| 446 | uint8_t *cmd; | 446 | uint8_t *cmd; |
| 447 | struct vmw_private *dev_priv = res->dev_priv; | 447 | struct vmw_private *dev_priv = res->dev_priv; |
| 448 | 448 | ||
| 449 | BUG_ON(val_buf->bo == NULL); | 449 | BUG_ON(!val_buf->bo); |
| 450 | |||
| 451 | submit_size = vmw_surface_dma_size(srf); | 450 | submit_size = vmw_surface_dma_size(srf); |
| 452 | cmd = vmw_fifo_reserve(dev_priv, submit_size); | 451 | cmd = vmw_fifo_reserve(dev_priv, submit_size); |
| 453 | if (unlikely(cmd == NULL)) { | 452 | if (unlikely(!cmd)) { |
| 454 | DRM_ERROR("Failed reserving FIFO space for surface " | 453 | DRM_ERROR("Failed reserving FIFO space for surface " |
| 455 | "DMA.\n"); | 454 | "DMA.\n"); |
| 456 | return -ENOMEM; | 455 | return -ENOMEM; |
| @@ -538,7 +537,7 @@ static int vmw_legacy_srf_destroy(struct vmw_resource *res) | |||
| 538 | 537 | ||
| 539 | submit_size = vmw_surface_destroy_size(); | 538 | submit_size = vmw_surface_destroy_size(); |
| 540 | cmd = vmw_fifo_reserve(dev_priv, submit_size); | 539 | cmd = vmw_fifo_reserve(dev_priv, submit_size); |
| 541 | if (unlikely(cmd == NULL)) { | 540 | if (unlikely(!cmd)) { |
| 542 | DRM_ERROR("Failed reserving FIFO space for surface " | 541 | DRM_ERROR("Failed reserving FIFO space for surface " |
| 543 | "eviction.\n"); | 542 | "eviction.\n"); |
| 544 | return -ENOMEM; | 543 | return -ENOMEM; |
| @@ -578,7 +577,7 @@ static int vmw_surface_init(struct vmw_private *dev_priv, | |||
| 578 | int ret; | 577 | int ret; |
| 579 | struct vmw_resource *res = &srf->res; | 578 | struct vmw_resource *res = &srf->res; |
| 580 | 579 | ||
| 581 | BUG_ON(res_free == NULL); | 580 | BUG_ON(!res_free); |
| 582 | if (!dev_priv->has_mob) | 581 | if (!dev_priv->has_mob) |
| 583 | vmw_fifo_resource_inc(dev_priv); | 582 | vmw_fifo_resource_inc(dev_priv); |
| 584 | ret = vmw_resource_init(dev_priv, res, true, res_free, | 583 | ret = vmw_resource_init(dev_priv, res, true, res_free, |
| @@ -700,7 +699,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, | |||
| 700 | struct drm_vmw_surface_create_req *req = &arg->req; | 699 | struct drm_vmw_surface_create_req *req = &arg->req; |
| 701 | struct drm_vmw_surface_arg *rep = &arg->rep; | 700 | struct drm_vmw_surface_arg *rep = &arg->rep; |
| 702 | struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; | 701 | struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; |
| 703 | struct drm_vmw_size __user *user_sizes; | ||
| 704 | int ret; | 702 | int ret; |
| 705 | int i, j; | 703 | int i, j; |
| 706 | uint32_t cur_bo_offset; | 704 | uint32_t cur_bo_offset; |
| @@ -748,7 +746,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, | |||
| 748 | } | 746 | } |
| 749 | 747 | ||
| 750 | user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL); | 748 | user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL); |
| 751 | if (unlikely(user_srf == NULL)) { | 749 | if (unlikely(!user_srf)) { |
| 752 | ret = -ENOMEM; | 750 | ret = -ENOMEM; |
| 753 | goto out_no_user_srf; | 751 | goto out_no_user_srf; |
| 754 | } | 752 | } |
| @@ -763,29 +761,21 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, | |||
| 763 | memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels)); | 761 | memcpy(srf->mip_levels, req->mip_levels, sizeof(srf->mip_levels)); |
| 764 | srf->num_sizes = num_sizes; | 762 | srf->num_sizes = num_sizes; |
| 765 | user_srf->size = size; | 763 | user_srf->size = size; |
| 766 | 764 | srf->sizes = memdup_user((struct drm_vmw_size __user *)(unsigned long) | |
| 767 | srf->sizes = kmalloc(srf->num_sizes * sizeof(*srf->sizes), GFP_KERNEL); | 765 | req->size_addr, |
| 768 | if (unlikely(srf->sizes == NULL)) { | 766 | sizeof(*srf->sizes) * srf->num_sizes); |
| 769 | ret = -ENOMEM; | 767 | if (IS_ERR(srf->sizes)) { |
| 768 | ret = PTR_ERR(srf->sizes); | ||
| 770 | goto out_no_sizes; | 769 | goto out_no_sizes; |
| 771 | } | 770 | } |
| 772 | srf->offsets = kmalloc(srf->num_sizes * sizeof(*srf->offsets), | 771 | srf->offsets = kmalloc_array(srf->num_sizes, |
| 773 | GFP_KERNEL); | 772 | sizeof(*srf->offsets), |
| 774 | if (unlikely(srf->offsets == NULL)) { | 773 | GFP_KERNEL); |
| 774 | if (unlikely(!srf->offsets)) { | ||
| 775 | ret = -ENOMEM; | 775 | ret = -ENOMEM; |
| 776 | goto out_no_offsets; | 776 | goto out_no_offsets; |
| 777 | } | 777 | } |
| 778 | 778 | ||
| 779 | user_sizes = (struct drm_vmw_size __user *)(unsigned long) | ||
| 780 | req->size_addr; | ||
| 781 | |||
| 782 | ret = copy_from_user(srf->sizes, user_sizes, | ||
| 783 | srf->num_sizes * sizeof(*srf->sizes)); | ||
| 784 | if (unlikely(ret != 0)) { | ||
| 785 | ret = -EFAULT; | ||
| 786 | goto out_no_copy; | ||
| 787 | } | ||
| 788 | |||
| 789 | srf->base_size = *srf->sizes; | 779 | srf->base_size = *srf->sizes; |
| 790 | srf->autogen_filter = SVGA3D_TEX_FILTER_NONE; | 780 | srf->autogen_filter = SVGA3D_TEX_FILTER_NONE; |
| 791 | srf->multisample_count = 0; | 781 | srf->multisample_count = 0; |
| @@ -923,7 +913,7 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv, | |||
| 923 | 913 | ||
| 924 | ret = -EINVAL; | 914 | ret = -EINVAL; |
| 925 | base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle); | 915 | base = ttm_base_object_lookup_for_ref(dev_priv->tdev, handle); |
| 926 | if (unlikely(base == NULL)) { | 916 | if (unlikely(!base)) { |
| 927 | DRM_ERROR("Could not find surface to reference.\n"); | 917 | DRM_ERROR("Could not find surface to reference.\n"); |
| 928 | goto out_no_lookup; | 918 | goto out_no_lookup; |
| 929 | } | 919 | } |
| @@ -1069,7 +1059,7 @@ static int vmw_gb_surface_create(struct vmw_resource *res) | |||
| 1069 | 1059 | ||
| 1070 | cmd = vmw_fifo_reserve(dev_priv, submit_len); | 1060 | cmd = vmw_fifo_reserve(dev_priv, submit_len); |
| 1071 | cmd2 = (typeof(cmd2))cmd; | 1061 | cmd2 = (typeof(cmd2))cmd; |
| 1072 | if (unlikely(cmd == NULL)) { | 1062 | if (unlikely(!cmd)) { |
| 1073 | DRM_ERROR("Failed reserving FIFO space for surface " | 1063 | DRM_ERROR("Failed reserving FIFO space for surface " |
| 1074 | "creation.\n"); | 1064 | "creation.\n"); |
| 1075 | ret = -ENOMEM; | 1065 | ret = -ENOMEM; |
| @@ -1135,7 +1125,7 @@ static int vmw_gb_surface_bind(struct vmw_resource *res, | |||
| 1135 | submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0); | 1125 | submit_size = sizeof(*cmd1) + (res->backup_dirty ? sizeof(*cmd2) : 0); |
| 1136 | 1126 | ||
| 1137 | cmd1 = vmw_fifo_reserve(dev_priv, submit_size); | 1127 | cmd1 = vmw_fifo_reserve(dev_priv, submit_size); |
| 1138 | if (unlikely(cmd1 == NULL)) { | 1128 | if (unlikely(!cmd1)) { |
| 1139 | DRM_ERROR("Failed reserving FIFO space for surface " | 1129 | DRM_ERROR("Failed reserving FIFO space for surface " |
| 1140 | "binding.\n"); | 1130 | "binding.\n"); |
| 1141 | return -ENOMEM; | 1131 | return -ENOMEM; |
| @@ -1185,7 +1175,7 @@ static int vmw_gb_surface_unbind(struct vmw_resource *res, | |||
| 1185 | 1175 | ||
| 1186 | submit_size = sizeof(*cmd3) + (readback ? sizeof(*cmd1) : sizeof(*cmd2)); | 1176 | submit_size = sizeof(*cmd3) + (readback ? sizeof(*cmd1) : sizeof(*cmd2)); |
| 1187 | cmd = vmw_fifo_reserve(dev_priv, submit_size); | 1177 | cmd = vmw_fifo_reserve(dev_priv, submit_size); |
| 1188 | if (unlikely(cmd == NULL)) { | 1178 | if (unlikely(!cmd)) { |
| 1189 | DRM_ERROR("Failed reserving FIFO space for surface " | 1179 | DRM_ERROR("Failed reserving FIFO space for surface " |
| 1190 | "unbinding.\n"); | 1180 | "unbinding.\n"); |
| 1191 | return -ENOMEM; | 1181 | return -ENOMEM; |
| @@ -1244,7 +1234,7 @@ static int vmw_gb_surface_destroy(struct vmw_resource *res) | |||
| 1244 | vmw_binding_res_list_scrub(&res->binding_head); | 1234 | vmw_binding_res_list_scrub(&res->binding_head); |
| 1245 | 1235 | ||
| 1246 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); | 1236 | cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd)); |
| 1247 | if (unlikely(cmd == NULL)) { | 1237 | if (unlikely(!cmd)) { |
| 1248 | DRM_ERROR("Failed reserving FIFO space for surface " | 1238 | DRM_ERROR("Failed reserving FIFO space for surface " |
| 1249 | "destruction.\n"); | 1239 | "destruction.\n"); |
| 1250 | mutex_unlock(&dev_priv->binding_mutex); | 1240 | mutex_unlock(&dev_priv->binding_mutex); |
| @@ -1410,7 +1400,7 @@ int vmw_gb_surface_reference_ioctl(struct drm_device *dev, void *data, | |||
| 1410 | 1400 | ||
| 1411 | user_srf = container_of(base, struct vmw_user_surface, prime.base); | 1401 | user_srf = container_of(base, struct vmw_user_surface, prime.base); |
| 1412 | srf = &user_srf->srf; | 1402 | srf = &user_srf->srf; |
| 1413 | if (srf->res.backup == NULL) { | 1403 | if (!srf->res.backup) { |
| 1414 | DRM_ERROR("Shared GB surface is missing a backup buffer.\n"); | 1404 | DRM_ERROR("Shared GB surface is missing a backup buffer.\n"); |
| 1415 | goto out_bad_resource; | 1405 | goto out_bad_resource; |
| 1416 | } | 1406 | } |
| @@ -1524,7 +1514,7 @@ int vmw_surface_gb_priv_define(struct drm_device *dev, | |||
| 1524 | } | 1514 | } |
| 1525 | 1515 | ||
| 1526 | user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL); | 1516 | user_srf = kzalloc(sizeof(*user_srf), GFP_KERNEL); |
| 1527 | if (unlikely(user_srf == NULL)) { | 1517 | if (unlikely(!user_srf)) { |
| 1528 | ret = -ENOMEM; | 1518 | ret = -ENOMEM; |
| 1529 | goto out_no_user_srf; | 1519 | goto out_no_user_srf; |
| 1530 | } | 1520 | } |
