diff options
| author | Rob Herring <robh@kernel.org> | 2018-03-08 10:21:07 -0500 |
|---|---|---|
| committer | Rob Herring <robh@kernel.org> | 2018-03-08 10:21:07 -0500 |
| commit | c679fa6e3aaa5c58fc514b5b88cfa82774b8d390 (patch) | |
| tree | 0c10b339368bd1795152a66a4e245e6f654fb3ec /drivers/gpu | |
| parent | bdb7013df910681f84eff27b07791d4c160cb76f (diff) | |
| parent | 4fd98e374fd377ae0458a9dc44aa779cf9631ddd (diff) | |
Merge branch 'dtc-update' into dt/next
Diffstat (limited to 'drivers/gpu')
42 files changed, 587 insertions, 264 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c index e2c3c5ec42d1..c53095b3b0fb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c | |||
| @@ -568,6 +568,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = { | |||
| 568 | /* HG _PR3 doesn't seem to work on this A+A weston board */ | 568 | /* HG _PR3 doesn't seem to work on this A+A weston board */ |
| 569 | { 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX }, | 569 | { 0x1002, 0x6900, 0x1002, 0x0124, AMDGPU_PX_QUIRK_FORCE_ATPX }, |
| 570 | { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX }, | 570 | { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX }, |
| 571 | { 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX }, | ||
| 571 | { 0, 0, 0, 0, 0 }, | 572 | { 0, 0, 0, 0, 0 }, |
| 572 | }; | 573 | }; |
| 573 | 574 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 8ca3783f2deb..74d2efaec52f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | |||
| @@ -736,9 +736,11 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force) | |||
| 736 | enum drm_connector_status ret = connector_status_disconnected; | 736 | enum drm_connector_status ret = connector_status_disconnected; |
| 737 | int r; | 737 | int r; |
| 738 | 738 | ||
| 739 | r = pm_runtime_get_sync(connector->dev->dev); | 739 | if (!drm_kms_helper_is_poll_worker()) { |
| 740 | if (r < 0) | 740 | r = pm_runtime_get_sync(connector->dev->dev); |
| 741 | return connector_status_disconnected; | 741 | if (r < 0) |
| 742 | return connector_status_disconnected; | ||
| 743 | } | ||
| 742 | 744 | ||
| 743 | if (encoder) { | 745 | if (encoder) { |
| 744 | struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); | 746 | struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); |
| @@ -757,8 +759,12 @@ amdgpu_connector_lvds_detect(struct drm_connector *connector, bool force) | |||
| 757 | /* check acpi lid status ??? */ | 759 | /* check acpi lid status ??? */ |
| 758 | 760 | ||
| 759 | amdgpu_connector_update_scratch_regs(connector, ret); | 761 | amdgpu_connector_update_scratch_regs(connector, ret); |
| 760 | pm_runtime_mark_last_busy(connector->dev->dev); | 762 | |
| 761 | pm_runtime_put_autosuspend(connector->dev->dev); | 763 | if (!drm_kms_helper_is_poll_worker()) { |
| 764 | pm_runtime_mark_last_busy(connector->dev->dev); | ||
| 765 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
| 766 | } | ||
| 767 | |||
| 762 | return ret; | 768 | return ret; |
| 763 | } | 769 | } |
| 764 | 770 | ||
| @@ -868,9 +874,11 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force) | |||
| 868 | enum drm_connector_status ret = connector_status_disconnected; | 874 | enum drm_connector_status ret = connector_status_disconnected; |
| 869 | int r; | 875 | int r; |
| 870 | 876 | ||
| 871 | r = pm_runtime_get_sync(connector->dev->dev); | 877 | if (!drm_kms_helper_is_poll_worker()) { |
| 872 | if (r < 0) | 878 | r = pm_runtime_get_sync(connector->dev->dev); |
| 873 | return connector_status_disconnected; | 879 | if (r < 0) |
| 880 | return connector_status_disconnected; | ||
| 881 | } | ||
| 874 | 882 | ||
| 875 | encoder = amdgpu_connector_best_single_encoder(connector); | 883 | encoder = amdgpu_connector_best_single_encoder(connector); |
| 876 | if (!encoder) | 884 | if (!encoder) |
| @@ -924,8 +932,10 @@ amdgpu_connector_vga_detect(struct drm_connector *connector, bool force) | |||
| 924 | amdgpu_connector_update_scratch_regs(connector, ret); | 932 | amdgpu_connector_update_scratch_regs(connector, ret); |
| 925 | 933 | ||
| 926 | out: | 934 | out: |
| 927 | pm_runtime_mark_last_busy(connector->dev->dev); | 935 | if (!drm_kms_helper_is_poll_worker()) { |
| 928 | pm_runtime_put_autosuspend(connector->dev->dev); | 936 | pm_runtime_mark_last_busy(connector->dev->dev); |
| 937 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
| 938 | } | ||
| 929 | 939 | ||
| 930 | return ret; | 940 | return ret; |
| 931 | } | 941 | } |
| @@ -988,9 +998,11 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) | |||
| 988 | enum drm_connector_status ret = connector_status_disconnected; | 998 | enum drm_connector_status ret = connector_status_disconnected; |
| 989 | bool dret = false, broken_edid = false; | 999 | bool dret = false, broken_edid = false; |
| 990 | 1000 | ||
| 991 | r = pm_runtime_get_sync(connector->dev->dev); | 1001 | if (!drm_kms_helper_is_poll_worker()) { |
| 992 | if (r < 0) | 1002 | r = pm_runtime_get_sync(connector->dev->dev); |
| 993 | return connector_status_disconnected; | 1003 | if (r < 0) |
| 1004 | return connector_status_disconnected; | ||
| 1005 | } | ||
| 994 | 1006 | ||
| 995 | if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) { | 1007 | if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) { |
| 996 | ret = connector->status; | 1008 | ret = connector->status; |
| @@ -1115,8 +1127,10 @@ out: | |||
| 1115 | amdgpu_connector_update_scratch_regs(connector, ret); | 1127 | amdgpu_connector_update_scratch_regs(connector, ret); |
| 1116 | 1128 | ||
| 1117 | exit: | 1129 | exit: |
| 1118 | pm_runtime_mark_last_busy(connector->dev->dev); | 1130 | if (!drm_kms_helper_is_poll_worker()) { |
| 1119 | pm_runtime_put_autosuspend(connector->dev->dev); | 1131 | pm_runtime_mark_last_busy(connector->dev->dev); |
| 1132 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
| 1133 | } | ||
| 1120 | 1134 | ||
| 1121 | return ret; | 1135 | return ret; |
| 1122 | } | 1136 | } |
| @@ -1359,9 +1373,11 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force) | |||
| 1359 | struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector); | 1373 | struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector); |
| 1360 | int r; | 1374 | int r; |
| 1361 | 1375 | ||
| 1362 | r = pm_runtime_get_sync(connector->dev->dev); | 1376 | if (!drm_kms_helper_is_poll_worker()) { |
| 1363 | if (r < 0) | 1377 | r = pm_runtime_get_sync(connector->dev->dev); |
| 1364 | return connector_status_disconnected; | 1378 | if (r < 0) |
| 1379 | return connector_status_disconnected; | ||
| 1380 | } | ||
| 1365 | 1381 | ||
| 1366 | if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) { | 1382 | if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) { |
| 1367 | ret = connector->status; | 1383 | ret = connector->status; |
| @@ -1429,8 +1445,10 @@ amdgpu_connector_dp_detect(struct drm_connector *connector, bool force) | |||
| 1429 | 1445 | ||
| 1430 | amdgpu_connector_update_scratch_regs(connector, ret); | 1446 | amdgpu_connector_update_scratch_regs(connector, ret); |
| 1431 | out: | 1447 | out: |
| 1432 | pm_runtime_mark_last_busy(connector->dev->dev); | 1448 | if (!drm_kms_helper_is_poll_worker()) { |
| 1433 | pm_runtime_put_autosuspend(connector->dev->dev); | 1449 | pm_runtime_mark_last_busy(connector->dev->dev); |
| 1450 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
| 1451 | } | ||
| 1434 | 1452 | ||
| 1435 | return ret; | 1453 | return ret; |
| 1436 | } | 1454 | } |
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 61e8c3e02d16..33d91e4474ea 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | |||
| @@ -718,7 +718,7 @@ static enum link_training_result perform_channel_equalization_sequence( | |||
| 718 | uint32_t retries_ch_eq; | 718 | uint32_t retries_ch_eq; |
| 719 | enum dc_lane_count lane_count = lt_settings->link_settings.lane_count; | 719 | enum dc_lane_count lane_count = lt_settings->link_settings.lane_count; |
| 720 | union lane_align_status_updated dpcd_lane_status_updated = {{0}}; | 720 | union lane_align_status_updated dpcd_lane_status_updated = {{0}}; |
| 721 | union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}};; | 721 | union lane_status dpcd_lane_status[LANE_COUNT_DP_MAX] = {{{0}}}; |
| 722 | 722 | ||
| 723 | hw_tr_pattern = get_supported_tp(link); | 723 | hw_tr_pattern = get_supported_tp(link); |
| 724 | 724 | ||
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 4c3223a4d62b..adb6e7b9280c 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c | |||
| @@ -162,7 +162,7 @@ static int pp_hw_init(void *handle) | |||
| 162 | if(hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) { | 162 | if(hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) { |
| 163 | pr_err("smc start failed\n"); | 163 | pr_err("smc start failed\n"); |
| 164 | hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr); | 164 | hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr); |
| 165 | return -EINVAL;; | 165 | return -EINVAL; |
| 166 | } | 166 | } |
| 167 | if (ret == PP_DPM_DISABLED) | 167 | if (ret == PP_DPM_DISABLED) |
| 168 | goto exit; | 168 | goto exit; |
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index cd23b1b28259..c91b9b054e3f 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c | |||
| @@ -294,22 +294,7 @@ static void cirrus_crtc_prepare(struct drm_crtc *crtc) | |||
| 294 | { | 294 | { |
| 295 | } | 295 | } |
| 296 | 296 | ||
| 297 | /* | 297 | static void cirrus_crtc_load_lut(struct drm_crtc *crtc) |
| 298 | * This is called after a mode is programmed. It should reverse anything done | ||
| 299 | * by the prepare function | ||
| 300 | */ | ||
| 301 | static void cirrus_crtc_commit(struct drm_crtc *crtc) | ||
| 302 | { | ||
| 303 | } | ||
| 304 | |||
| 305 | /* | ||
| 306 | * The core can pass us a set of gamma values to program. We actually only | ||
| 307 | * use this for 8-bit mode so can't perform smooth fades on deeper modes, | ||
| 308 | * but it's a requirement that we provide the function | ||
| 309 | */ | ||
| 310 | static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | ||
| 311 | u16 *blue, uint32_t size, | ||
| 312 | struct drm_modeset_acquire_ctx *ctx) | ||
| 313 | { | 298 | { |
| 314 | struct drm_device *dev = crtc->dev; | 299 | struct drm_device *dev = crtc->dev; |
| 315 | struct cirrus_device *cdev = dev->dev_private; | 300 | struct cirrus_device *cdev = dev->dev_private; |
| @@ -317,7 +302,7 @@ static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
| 317 | int i; | 302 | int i; |
| 318 | 303 | ||
| 319 | if (!crtc->enabled) | 304 | if (!crtc->enabled) |
| 320 | return 0; | 305 | return; |
| 321 | 306 | ||
| 322 | r = crtc->gamma_store; | 307 | r = crtc->gamma_store; |
| 323 | g = r + crtc->gamma_size; | 308 | g = r + crtc->gamma_size; |
| @@ -330,6 +315,27 @@ static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | |||
| 330 | WREG8(PALETTE_DATA, *g++ >> 8); | 315 | WREG8(PALETTE_DATA, *g++ >> 8); |
| 331 | WREG8(PALETTE_DATA, *b++ >> 8); | 316 | WREG8(PALETTE_DATA, *b++ >> 8); |
| 332 | } | 317 | } |
| 318 | } | ||
| 319 | |||
| 320 | /* | ||
| 321 | * This is called after a mode is programmed. It should reverse anything done | ||
| 322 | * by the prepare function | ||
| 323 | */ | ||
| 324 | static void cirrus_crtc_commit(struct drm_crtc *crtc) | ||
| 325 | { | ||
| 326 | cirrus_crtc_load_lut(crtc); | ||
| 327 | } | ||
| 328 | |||
| 329 | /* | ||
| 330 | * The core can pass us a set of gamma values to program. We actually only | ||
| 331 | * use this for 8-bit mode so can't perform smooth fades on deeper modes, | ||
| 332 | * but it's a requirement that we provide the function | ||
| 333 | */ | ||
| 334 | static int cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, | ||
| 335 | u16 *blue, uint32_t size, | ||
| 336 | struct drm_modeset_acquire_ctx *ctx) | ||
| 337 | { | ||
| 338 | cirrus_crtc_load_lut(crtc); | ||
| 333 | 339 | ||
| 334 | return 0; | 340 | return 0; |
| 335 | } | 341 | } |
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ab4032167094..ae3cbfe9e01c 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
| @@ -1878,6 +1878,8 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, | |||
| 1878 | new_crtc_state->event->base.completion = &commit->flip_done; | 1878 | new_crtc_state->event->base.completion = &commit->flip_done; |
| 1879 | new_crtc_state->event->base.completion_release = release_crtc_commit; | 1879 | new_crtc_state->event->base.completion_release = release_crtc_commit; |
| 1880 | drm_crtc_commit_get(commit); | 1880 | drm_crtc_commit_get(commit); |
| 1881 | |||
| 1882 | commit->abort_completion = true; | ||
| 1881 | } | 1883 | } |
| 1882 | 1884 | ||
| 1883 | for_each_oldnew_connector_in_state(state, conn, old_conn_state, new_conn_state, i) { | 1885 | for_each_oldnew_connector_in_state(state, conn, old_conn_state, new_conn_state, i) { |
| @@ -3421,8 +3423,21 @@ EXPORT_SYMBOL(drm_atomic_helper_crtc_duplicate_state); | |||
| 3421 | void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) | 3423 | void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) |
| 3422 | { | 3424 | { |
| 3423 | if (state->commit) { | 3425 | if (state->commit) { |
| 3426 | /* | ||
| 3427 | * In the event that a non-blocking commit returns | ||
| 3428 | * -ERESTARTSYS before the commit_tail work is queued, we will | ||
| 3429 | * have an extra reference to the commit object. Release it, if | ||
| 3430 | * the event has not been consumed by the worker. | ||
| 3431 | * | ||
| 3432 | * state->event may be freed, so we can't directly look at | ||
| 3433 | * state->event->base.completion. | ||
| 3434 | */ | ||
| 3435 | if (state->event && state->commit->abort_completion) | ||
| 3436 | drm_crtc_commit_put(state->commit); | ||
| 3437 | |||
| 3424 | kfree(state->commit->event); | 3438 | kfree(state->commit->event); |
| 3425 | state->commit->event = NULL; | 3439 | state->commit->event = NULL; |
| 3440 | |||
| 3426 | drm_crtc_commit_put(state->commit); | 3441 | drm_crtc_commit_put(state->commit); |
| 3427 | } | 3442 | } |
| 3428 | 3443 | ||
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ddd537914575..4f751a9d71a3 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -113,6 +113,9 @@ static const struct edid_quirk { | |||
| 113 | /* AEO model 0 reports 8 bpc, but is a 6 bpc panel */ | 113 | /* AEO model 0 reports 8 bpc, but is a 6 bpc panel */ |
| 114 | { "AEO", 0, EDID_QUIRK_FORCE_6BPC }, | 114 | { "AEO", 0, EDID_QUIRK_FORCE_6BPC }, |
| 115 | 115 | ||
| 116 | /* CPT panel of Asus UX303LA reports 8 bpc, but is a 6 bpc panel */ | ||
| 117 | { "CPT", 0x17df, EDID_QUIRK_FORCE_6BPC }, | ||
| 118 | |||
| 116 | /* Belinea 10 15 55 */ | 119 | /* Belinea 10 15 55 */ |
| 117 | { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, | 120 | { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, |
| 118 | { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, | 121 | { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, |
| @@ -162,6 +165,24 @@ static const struct edid_quirk { | |||
| 162 | 165 | ||
| 163 | /* HTC Vive VR Headset */ | 166 | /* HTC Vive VR Headset */ |
| 164 | { "HVR", 0xaa01, EDID_QUIRK_NON_DESKTOP }, | 167 | { "HVR", 0xaa01, EDID_QUIRK_NON_DESKTOP }, |
| 168 | |||
| 169 | /* Oculus Rift DK1, DK2, and CV1 VR Headsets */ | ||
| 170 | { "OVR", 0x0001, EDID_QUIRK_NON_DESKTOP }, | ||
| 171 | { "OVR", 0x0003, EDID_QUIRK_NON_DESKTOP }, | ||
| 172 | { "OVR", 0x0004, EDID_QUIRK_NON_DESKTOP }, | ||
| 173 | |||
| 174 | /* Windows Mixed Reality Headsets */ | ||
| 175 | { "ACR", 0x7fce, EDID_QUIRK_NON_DESKTOP }, | ||
| 176 | { "HPN", 0x3515, EDID_QUIRK_NON_DESKTOP }, | ||
| 177 | { "LEN", 0x0408, EDID_QUIRK_NON_DESKTOP }, | ||
| 178 | { "LEN", 0xb800, EDID_QUIRK_NON_DESKTOP }, | ||
| 179 | { "FUJ", 0x1970, EDID_QUIRK_NON_DESKTOP }, | ||
| 180 | { "DEL", 0x7fce, EDID_QUIRK_NON_DESKTOP }, | ||
| 181 | { "SEC", 0x144a, EDID_QUIRK_NON_DESKTOP }, | ||
| 182 | { "AUS", 0xc102, EDID_QUIRK_NON_DESKTOP }, | ||
| 183 | |||
| 184 | /* Sony PlayStation VR Headset */ | ||
| 185 | { "SNY", 0x0704, EDID_QUIRK_NON_DESKTOP }, | ||
| 165 | }; | 186 | }; |
| 166 | 187 | ||
| 167 | /* | 188 | /* |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 186c4e90cc1c..89eef1bb4ddc 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
| @@ -836,9 +836,24 @@ struct drm_mm_node *drm_mm_scan_color_evict(struct drm_mm_scan *scan) | |||
| 836 | if (!mm->color_adjust) | 836 | if (!mm->color_adjust) |
| 837 | return NULL; | 837 | return NULL; |
| 838 | 838 | ||
| 839 | hole = list_first_entry(&mm->hole_stack, typeof(*hole), hole_stack); | 839 | /* |
| 840 | hole_start = __drm_mm_hole_node_start(hole); | 840 | * The hole found during scanning should ideally be the first element |
| 841 | hole_end = hole_start + hole->hole_size; | 841 | * in the hole_stack list, but due to side-effects in the driver it |
| 842 | * may not be. | ||
| 843 | */ | ||
| 844 | list_for_each_entry(hole, &mm->hole_stack, hole_stack) { | ||
| 845 | hole_start = __drm_mm_hole_node_start(hole); | ||
| 846 | hole_end = hole_start + hole->hole_size; | ||
| 847 | |||
| 848 | if (hole_start <= scan->hit_start && | ||
| 849 | hole_end >= scan->hit_end) | ||
| 850 | break; | ||
| 851 | } | ||
| 852 | |||
| 853 | /* We should only be called after we found the hole previously */ | ||
| 854 | DRM_MM_BUG_ON(&hole->hole_stack == &mm->hole_stack); | ||
| 855 | if (unlikely(&hole->hole_stack == &mm->hole_stack)) | ||
| 856 | return NULL; | ||
| 842 | 857 | ||
| 843 | DRM_MM_BUG_ON(hole_start > scan->hit_start); | 858 | DRM_MM_BUG_ON(hole_start > scan->hit_start); |
| 844 | DRM_MM_BUG_ON(hole_end < scan->hit_end); | 859 | DRM_MM_BUG_ON(hole_end < scan->hit_end); |
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 555fbe54d6e2..00b8445ba819 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c | |||
| @@ -654,6 +654,26 @@ out: | |||
| 654 | } | 654 | } |
| 655 | 655 | ||
| 656 | /** | 656 | /** |
| 657 | * drm_kms_helper_is_poll_worker - is %current task an output poll worker? | ||
| 658 | * | ||
| 659 | * Determine if %current task is an output poll worker. This can be used | ||
| 660 | * to select distinct code paths for output polling versus other contexts. | ||
| 661 | * | ||
| 662 | * One use case is to avoid a deadlock between the output poll worker and | ||
| 663 | * the autosuspend worker wherein the latter waits for polling to finish | ||
| 664 | * upon calling drm_kms_helper_poll_disable(), while the former waits for | ||
| 665 | * runtime suspend to finish upon calling pm_runtime_get_sync() in a | ||
| 666 | * connector ->detect hook. | ||
| 667 | */ | ||
| 668 | bool drm_kms_helper_is_poll_worker(void) | ||
| 669 | { | ||
| 670 | struct work_struct *work = current_work(); | ||
| 671 | |||
| 672 | return work && work->func == output_poll_execute; | ||
| 673 | } | ||
| 674 | EXPORT_SYMBOL(drm_kms_helper_is_poll_worker); | ||
| 675 | |||
| 676 | /** | ||
| 657 | * drm_kms_helper_poll_disable - disable output polling | 677 | * drm_kms_helper_poll_disable - disable output polling |
| 658 | * @dev: drm_device | 678 | * @dev: drm_device |
| 659 | * | 679 | * |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 2b8bf2dd6387..f68ef1b3a28c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c | |||
| @@ -286,7 +286,6 @@ static int g2d_init_cmdlist(struct g2d_data *g2d) | |||
| 286 | 286 | ||
| 287 | node = kcalloc(G2D_CMDLIST_NUM, sizeof(*node), GFP_KERNEL); | 287 | node = kcalloc(G2D_CMDLIST_NUM, sizeof(*node), GFP_KERNEL); |
| 288 | if (!node) { | 288 | if (!node) { |
| 289 | dev_err(dev, "failed to allocate memory\n"); | ||
| 290 | ret = -ENOMEM; | 289 | ret = -ENOMEM; |
| 291 | goto err; | 290 | goto err; |
| 292 | } | 291 | } |
| @@ -926,7 +925,7 @@ static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no) | |||
| 926 | struct drm_device *drm_dev = g2d->subdrv.drm_dev; | 925 | struct drm_device *drm_dev = g2d->subdrv.drm_dev; |
| 927 | struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node; | 926 | struct g2d_runqueue_node *runqueue_node = g2d->runqueue_node; |
| 928 | struct drm_exynos_pending_g2d_event *e; | 927 | struct drm_exynos_pending_g2d_event *e; |
| 929 | struct timeval now; | 928 | struct timespec64 now; |
| 930 | 929 | ||
| 931 | if (list_empty(&runqueue_node->event_list)) | 930 | if (list_empty(&runqueue_node->event_list)) |
| 932 | return; | 931 | return; |
| @@ -934,9 +933,9 @@ static void g2d_finish_event(struct g2d_data *g2d, u32 cmdlist_no) | |||
| 934 | e = list_first_entry(&runqueue_node->event_list, | 933 | e = list_first_entry(&runqueue_node->event_list, |
| 935 | struct drm_exynos_pending_g2d_event, base.link); | 934 | struct drm_exynos_pending_g2d_event, base.link); |
| 936 | 935 | ||
| 937 | do_gettimeofday(&now); | 936 | ktime_get_ts64(&now); |
| 938 | e->event.tv_sec = now.tv_sec; | 937 | e->event.tv_sec = now.tv_sec; |
| 939 | e->event.tv_usec = now.tv_usec; | 938 | e->event.tv_usec = now.tv_nsec / NSEC_PER_USEC; |
| 940 | e->event.cmdlist_no = cmdlist_no; | 939 | e->event.cmdlist_no = cmdlist_no; |
| 941 | 940 | ||
| 942 | drm_send_event(drm_dev, &e->base); | 941 | drm_send_event(drm_dev, &e->base); |
| @@ -1358,10 +1357,9 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data, | |||
| 1358 | return -EFAULT; | 1357 | return -EFAULT; |
| 1359 | 1358 | ||
| 1360 | runqueue_node = kmem_cache_alloc(g2d->runqueue_slab, GFP_KERNEL); | 1359 | runqueue_node = kmem_cache_alloc(g2d->runqueue_slab, GFP_KERNEL); |
| 1361 | if (!runqueue_node) { | 1360 | if (!runqueue_node) |
| 1362 | dev_err(dev, "failed to allocate memory\n"); | ||
| 1363 | return -ENOMEM; | 1361 | return -ENOMEM; |
| 1364 | } | 1362 | |
| 1365 | run_cmdlist = &runqueue_node->run_cmdlist; | 1363 | run_cmdlist = &runqueue_node->run_cmdlist; |
| 1366 | event_list = &runqueue_node->event_list; | 1364 | event_list = &runqueue_node->event_list; |
| 1367 | INIT_LIST_HEAD(run_cmdlist); | 1365 | INIT_LIST_HEAD(run_cmdlist); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.h b/drivers/gpu/drm/exynos/exynos_drm_rotator.h deleted file mode 100644 index 71a0b4c0c1e8..000000000000 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.h +++ /dev/null | |||
| @@ -1,19 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||
| 3 | * | ||
| 4 | * Authors: | ||
| 5 | * YoungJun Cho <yj44.cho@samsung.com> | ||
| 6 | * Eunchul Kim <chulspro.kim@samsung.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #ifndef _EXYNOS_DRM_ROTATOR_H_ | ||
| 15 | #define _EXYNOS_DRM_ROTATOR_H_ | ||
| 16 | |||
| 17 | /* TODO */ | ||
| 18 | |||
| 19 | #endif | ||
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index a4b75a46f946..abd84cbcf1c2 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
| @@ -1068,10 +1068,13 @@ static void hdmi_audio_config(struct hdmi_context *hdata) | |||
| 1068 | /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */ | 1068 | /* Configuration I2S input ports. Configure I2S_PIN_SEL_0~4 */ |
| 1069 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5) | 1069 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_0, HDMI_I2S_SEL_SCLK(5) |
| 1070 | | HDMI_I2S_SEL_LRCK(6)); | 1070 | | HDMI_I2S_SEL_LRCK(6)); |
| 1071 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(1) | 1071 | |
| 1072 | | HDMI_I2S_SEL_SDATA2(4)); | 1072 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_1, HDMI_I2S_SEL_SDATA1(3) |
| 1073 | | HDMI_I2S_SEL_SDATA0(4)); | ||
| 1074 | |||
| 1073 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1) | 1075 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_2, HDMI_I2S_SEL_SDATA3(1) |
| 1074 | | HDMI_I2S_SEL_SDATA2(2)); | 1076 | | HDMI_I2S_SEL_SDATA2(2)); |
| 1077 | |||
| 1075 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0)); | 1078 | hdmi_reg_writeb(hdata, HDMI_I2S_PIN_SEL_3, HDMI_I2S_SEL_DSD(0)); |
| 1076 | 1079 | ||
| 1077 | /* I2S_CON_1 & 2 */ | 1080 | /* I2S_CON_1 & 2 */ |
diff --git a/drivers/gpu/drm/exynos/regs-fimc.h b/drivers/gpu/drm/exynos/regs-fimc.h index 30496134a3d0..d7cbe53c4c01 100644 --- a/drivers/gpu/drm/exynos/regs-fimc.h +++ b/drivers/gpu/drm/exynos/regs-fimc.h | |||
| @@ -569,7 +569,7 @@ | |||
| 569 | #define EXYNOS_CIIMGEFF_FIN_EMBOSSING (4 << 26) | 569 | #define EXYNOS_CIIMGEFF_FIN_EMBOSSING (4 << 26) |
| 570 | #define EXYNOS_CIIMGEFF_FIN_SILHOUETTE (5 << 26) | 570 | #define EXYNOS_CIIMGEFF_FIN_SILHOUETTE (5 << 26) |
| 571 | #define EXYNOS_CIIMGEFF_FIN_MASK (7 << 26) | 571 | #define EXYNOS_CIIMGEFF_FIN_MASK (7 << 26) |
| 572 | #define EXYNOS_CIIMGEFF_PAT_CBCR_MASK ((0xff < 13) | (0xff < 0)) | 572 | #define EXYNOS_CIIMGEFF_PAT_CBCR_MASK ((0xff << 13) | (0xff << 0)) |
| 573 | 573 | ||
| 574 | /* Real input DMA size register */ | 574 | /* Real input DMA size register */ |
| 575 | #define EXYNOS_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31) | 575 | #define EXYNOS_CIREAL_ISIZE_AUTOLOAD_ENABLE (1 << 31) |
diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h index 04be0f7e8193..4420c203ac85 100644 --- a/drivers/gpu/drm/exynos/regs-hdmi.h +++ b/drivers/gpu/drm/exynos/regs-hdmi.h | |||
| @@ -464,7 +464,7 @@ | |||
| 464 | 464 | ||
| 465 | /* I2S_PIN_SEL_1 */ | 465 | /* I2S_PIN_SEL_1 */ |
| 466 | #define HDMI_I2S_SEL_SDATA1(x) (((x) & 0x7) << 4) | 466 | #define HDMI_I2S_SEL_SDATA1(x) (((x) & 0x7) << 4) |
| 467 | #define HDMI_I2S_SEL_SDATA2(x) ((x) & 0x7) | 467 | #define HDMI_I2S_SEL_SDATA0(x) ((x) & 0x7) |
| 468 | 468 | ||
| 469 | /* I2S_PIN_SEL_2 */ | 469 | /* I2S_PIN_SEL_2 */ |
| 470 | #define HDMI_I2S_SEL_SDATA3(x) (((x) & 0x7) << 4) | 470 | #define HDMI_I2S_SEL_SDATA3(x) (((x) & 0x7) << 4) |
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 909499b73d03..021f722e2481 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c | |||
| @@ -733,6 +733,25 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf, | |||
| 733 | return ret == 0 ? count : ret; | 733 | return ret == 0 ? count : ret; |
| 734 | } | 734 | } |
| 735 | 735 | ||
| 736 | static bool gtt_entry(struct mdev_device *mdev, loff_t *ppos) | ||
| 737 | { | ||
| 738 | struct intel_vgpu *vgpu = mdev_get_drvdata(mdev); | ||
| 739 | unsigned int index = VFIO_PCI_OFFSET_TO_INDEX(*ppos); | ||
| 740 | struct intel_gvt *gvt = vgpu->gvt; | ||
| 741 | int offset; | ||
| 742 | |||
| 743 | /* Only allow MMIO GGTT entry access */ | ||
| 744 | if (index != PCI_BASE_ADDRESS_0) | ||
| 745 | return false; | ||
| 746 | |||
| 747 | offset = (u64)(*ppos & VFIO_PCI_OFFSET_MASK) - | ||
| 748 | intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_0); | ||
| 749 | |||
| 750 | return (offset >= gvt->device_info.gtt_start_offset && | ||
| 751 | offset < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt)) ? | ||
| 752 | true : false; | ||
| 753 | } | ||
| 754 | |||
| 736 | static ssize_t intel_vgpu_read(struct mdev_device *mdev, char __user *buf, | 755 | static ssize_t intel_vgpu_read(struct mdev_device *mdev, char __user *buf, |
| 737 | size_t count, loff_t *ppos) | 756 | size_t count, loff_t *ppos) |
| 738 | { | 757 | { |
| @@ -742,7 +761,21 @@ static ssize_t intel_vgpu_read(struct mdev_device *mdev, char __user *buf, | |||
| 742 | while (count) { | 761 | while (count) { |
| 743 | size_t filled; | 762 | size_t filled; |
| 744 | 763 | ||
| 745 | if (count >= 4 && !(*ppos % 4)) { | 764 | /* Only support GGTT entry 8 bytes read */ |
| 765 | if (count >= 8 && !(*ppos % 8) && | ||
| 766 | gtt_entry(mdev, ppos)) { | ||
| 767 | u64 val; | ||
| 768 | |||
| 769 | ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val), | ||
| 770 | ppos, false); | ||
| 771 | if (ret <= 0) | ||
| 772 | goto read_err; | ||
| 773 | |||
| 774 | if (copy_to_user(buf, &val, sizeof(val))) | ||
| 775 | goto read_err; | ||
| 776 | |||
| 777 | filled = 8; | ||
| 778 | } else if (count >= 4 && !(*ppos % 4)) { | ||
| 746 | u32 val; | 779 | u32 val; |
| 747 | 780 | ||
| 748 | ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val), | 781 | ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val), |
| @@ -802,7 +835,21 @@ static ssize_t intel_vgpu_write(struct mdev_device *mdev, | |||
| 802 | while (count) { | 835 | while (count) { |
| 803 | size_t filled; | 836 | size_t filled; |
| 804 | 837 | ||
| 805 | if (count >= 4 && !(*ppos % 4)) { | 838 | /* Only support GGTT entry 8 bytes write */ |
| 839 | if (count >= 8 && !(*ppos % 8) && | ||
| 840 | gtt_entry(mdev, ppos)) { | ||
| 841 | u64 val; | ||
| 842 | |||
| 843 | if (copy_from_user(&val, buf, sizeof(val))) | ||
| 844 | goto write_err; | ||
| 845 | |||
| 846 | ret = intel_vgpu_rw(mdev, (char *)&val, sizeof(val), | ||
| 847 | ppos, true); | ||
| 848 | if (ret <= 0) | ||
| 849 | goto write_err; | ||
| 850 | |||
| 851 | filled = 8; | ||
| 852 | } else if (count >= 4 && !(*ppos % 4)) { | ||
| 806 | u32 val; | 853 | u32 val; |
| 807 | 854 | ||
| 808 | if (copy_from_user(&val, buf, sizeof(val))) | 855 | if (copy_from_user(&val, buf, sizeof(val))) |
diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index 73ad6e90e49d..256f1bb522b7 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c | |||
| @@ -118,6 +118,7 @@ static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = { | |||
| 118 | {RCS, HALF_SLICE_CHICKEN3, 0xffff, true}, /* 0xe184 */ | 118 | {RCS, HALF_SLICE_CHICKEN3, 0xffff, true}, /* 0xe184 */ |
| 119 | {RCS, GEN9_HALF_SLICE_CHICKEN5, 0xffff, true}, /* 0xe188 */ | 119 | {RCS, GEN9_HALF_SLICE_CHICKEN5, 0xffff, true}, /* 0xe188 */ |
| 120 | {RCS, GEN9_HALF_SLICE_CHICKEN7, 0xffff, true}, /* 0xe194 */ | 120 | {RCS, GEN9_HALF_SLICE_CHICKEN7, 0xffff, true}, /* 0xe194 */ |
| 121 | {RCS, GEN8_ROW_CHICKEN, 0xffff, true}, /* 0xe4f0 */ | ||
| 121 | {RCS, TRVATTL3PTRDW(0), 0, false}, /* 0x4de0 */ | 122 | {RCS, TRVATTL3PTRDW(0), 0, false}, /* 0x4de0 */ |
| 122 | {RCS, TRVATTL3PTRDW(1), 0, false}, /* 0x4de4 */ | 123 | {RCS, TRVATTL3PTRDW(1), 0, false}, /* 0x4de4 */ |
| 123 | {RCS, TRNULLDETCT, 0, false}, /* 0x4de8 */ | 124 | {RCS, TRNULLDETCT, 0, false}, /* 0x4de8 */ |
diff --git a/drivers/gpu/drm/i915/gvt/trace.h b/drivers/gpu/drm/i915/gvt/trace.h index 7a2511538f34..736bd2bc5127 100644 --- a/drivers/gpu/drm/i915/gvt/trace.h +++ b/drivers/gpu/drm/i915/gvt/trace.h | |||
| @@ -333,7 +333,7 @@ TRACE_EVENT(render_mmio, | |||
| 333 | TP_PROTO(int old_id, int new_id, char *action, unsigned int reg, | 333 | TP_PROTO(int old_id, int new_id, char *action, unsigned int reg, |
| 334 | unsigned int old_val, unsigned int new_val), | 334 | unsigned int old_val, unsigned int new_val), |
| 335 | 335 | ||
| 336 | TP_ARGS(old_id, new_id, action, reg, new_val, old_val), | 336 | TP_ARGS(old_id, new_id, action, reg, old_val, new_val), |
| 337 | 337 | ||
| 338 | TP_STRUCT__entry( | 338 | TP_STRUCT__entry( |
| 339 | __field(int, old_id) | 339 | __field(int, old_id) |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 173d0095e3b2..2f5209de0391 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -1433,19 +1433,7 @@ void i915_driver_unload(struct drm_device *dev) | |||
| 1433 | 1433 | ||
| 1434 | intel_modeset_cleanup(dev); | 1434 | intel_modeset_cleanup(dev); |
| 1435 | 1435 | ||
| 1436 | /* | 1436 | intel_bios_cleanup(dev_priv); |
| 1437 | * free the memory space allocated for the child device | ||
| 1438 | * config parsed from VBT | ||
| 1439 | */ | ||
| 1440 | if (dev_priv->vbt.child_dev && dev_priv->vbt.child_dev_num) { | ||
| 1441 | kfree(dev_priv->vbt.child_dev); | ||
| 1442 | dev_priv->vbt.child_dev = NULL; | ||
| 1443 | dev_priv->vbt.child_dev_num = 0; | ||
| 1444 | } | ||
| 1445 | kfree(dev_priv->vbt.sdvo_lvds_vbt_mode); | ||
| 1446 | dev_priv->vbt.sdvo_lvds_vbt_mode = NULL; | ||
| 1447 | kfree(dev_priv->vbt.lfp_lvds_vbt_mode); | ||
| 1448 | dev_priv->vbt.lfp_lvds_vbt_mode = NULL; | ||
| 1449 | 1437 | ||
| 1450 | vga_switcheroo_unregister_client(pdev); | 1438 | vga_switcheroo_unregister_client(pdev); |
| 1451 | vga_client_register(pdev, NULL, NULL, NULL); | 1439 | vga_client_register(pdev, NULL, NULL, NULL); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a42deebedb0f..d307429a5ae0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
| @@ -1349,6 +1349,7 @@ struct intel_vbt_data { | |||
| 1349 | u32 size; | 1349 | u32 size; |
| 1350 | u8 *data; | 1350 | u8 *data; |
| 1351 | const u8 *sequence[MIPI_SEQ_MAX]; | 1351 | const u8 *sequence[MIPI_SEQ_MAX]; |
| 1352 | u8 *deassert_seq; /* Used by fixup_mipi_sequences() */ | ||
| 1352 | } dsi; | 1353 | } dsi; |
| 1353 | 1354 | ||
| 1354 | int crt_ddc_pin; | 1355 | int crt_ddc_pin; |
| @@ -3657,6 +3658,7 @@ extern void intel_i2c_reset(struct drm_i915_private *dev_priv); | |||
| 3657 | 3658 | ||
| 3658 | /* intel_bios.c */ | 3659 | /* intel_bios.c */ |
| 3659 | void intel_bios_init(struct drm_i915_private *dev_priv); | 3660 | void intel_bios_init(struct drm_i915_private *dev_priv); |
| 3661 | void intel_bios_cleanup(struct drm_i915_private *dev_priv); | ||
| 3660 | bool intel_bios_is_valid_vbt(const void *buf, size_t size); | 3662 | bool intel_bios_is_valid_vbt(const void *buf, size_t size); |
| 3661 | bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); | 3663 | bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); |
| 3662 | bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin); | 3664 | bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin); |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 648e7536ff51..0c963fcf31ff 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
| @@ -803,7 +803,7 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, | |||
| 803 | 803 | ||
| 804 | case I915_CONTEXT_PARAM_PRIORITY: | 804 | case I915_CONTEXT_PARAM_PRIORITY: |
| 805 | { | 805 | { |
| 806 | int priority = args->value; | 806 | s64 priority = args->value; |
| 807 | 807 | ||
| 808 | if (args->size) | 808 | if (args->size) |
| 809 | ret = -EINVAL; | 809 | ret = -EINVAL; |
diff --git a/drivers/gpu/drm/i915/i915_oa_cflgt3.c b/drivers/gpu/drm/i915/i915_oa_cflgt3.c index 42ff06fe54a3..792facdb6702 100644 --- a/drivers/gpu/drm/i915/i915_oa_cflgt3.c +++ b/drivers/gpu/drm/i915/i915_oa_cflgt3.c | |||
| @@ -84,9 +84,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) | |||
| 84 | void | 84 | void |
| 85 | i915_perf_load_test_config_cflgt3(struct drm_i915_private *dev_priv) | 85 | i915_perf_load_test_config_cflgt3(struct drm_i915_private *dev_priv) |
| 86 | { | 86 | { |
| 87 | strncpy(dev_priv->perf.oa.test_config.uuid, | 87 | strlcpy(dev_priv->perf.oa.test_config.uuid, |
| 88 | "577e8e2c-3fa0-4875-8743-3538d585e3b0", | 88 | "577e8e2c-3fa0-4875-8743-3538d585e3b0", |
| 89 | UUID_STRING_LEN); | 89 | sizeof(dev_priv->perf.oa.test_config.uuid)); |
| 90 | dev_priv->perf.oa.test_config.id = 1; | 90 | dev_priv->perf.oa.test_config.id = 1; |
| 91 | 91 | ||
| 92 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; | 92 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
diff --git a/drivers/gpu/drm/i915/i915_oa_cnl.c b/drivers/gpu/drm/i915/i915_oa_cnl.c index ff0ac3627cc4..ba9140c87cc0 100644 --- a/drivers/gpu/drm/i915/i915_oa_cnl.c +++ b/drivers/gpu/drm/i915/i915_oa_cnl.c | |||
| @@ -96,9 +96,9 @@ show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) | |||
| 96 | void | 96 | void |
| 97 | i915_perf_load_test_config_cnl(struct drm_i915_private *dev_priv) | 97 | i915_perf_load_test_config_cnl(struct drm_i915_private *dev_priv) |
| 98 | { | 98 | { |
| 99 | strncpy(dev_priv->perf.oa.test_config.uuid, | 99 | strlcpy(dev_priv->perf.oa.test_config.uuid, |
| 100 | "db41edd4-d8e7-4730-ad11-b9a2d6833503", | 100 | "db41edd4-d8e7-4730-ad11-b9a2d6833503", |
| 101 | UUID_STRING_LEN); | 101 | sizeof(dev_priv->perf.oa.test_config.uuid)); |
| 102 | dev_priv->perf.oa.test_config.id = 1; | 102 | dev_priv->perf.oa.test_config.id = 1; |
| 103 | 103 | ||
| 104 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; | 104 | dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; |
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c index 55a8a1e29424..0e9b98c32b62 100644 --- a/drivers/gpu/drm/i915/i915_pmu.c +++ b/drivers/gpu/drm/i915/i915_pmu.c | |||
| @@ -285,26 +285,41 @@ static u64 count_interrupts(struct drm_i915_private *i915) | |||
| 285 | return sum; | 285 | return sum; |
| 286 | } | 286 | } |
| 287 | 287 | ||
| 288 | static void i915_pmu_event_destroy(struct perf_event *event) | 288 | static void engine_event_destroy(struct perf_event *event) |
| 289 | { | 289 | { |
| 290 | WARN_ON(event->parent); | 290 | struct drm_i915_private *i915 = |
| 291 | container_of(event->pmu, typeof(*i915), pmu.base); | ||
| 292 | struct intel_engine_cs *engine; | ||
| 293 | |||
| 294 | engine = intel_engine_lookup_user(i915, | ||
| 295 | engine_event_class(event), | ||
| 296 | engine_event_instance(event)); | ||
| 297 | if (WARN_ON_ONCE(!engine)) | ||
| 298 | return; | ||
| 299 | |||
| 300 | if (engine_event_sample(event) == I915_SAMPLE_BUSY && | ||
| 301 | intel_engine_supports_stats(engine)) | ||
| 302 | intel_disable_engine_stats(engine); | ||
| 291 | } | 303 | } |
| 292 | 304 | ||
| 293 | static int engine_event_init(struct perf_event *event) | 305 | static void i915_pmu_event_destroy(struct perf_event *event) |
| 294 | { | 306 | { |
| 295 | struct drm_i915_private *i915 = | 307 | WARN_ON(event->parent); |
| 296 | container_of(event->pmu, typeof(*i915), pmu.base); | ||
| 297 | 308 | ||
| 298 | if (!intel_engine_lookup_user(i915, engine_event_class(event), | 309 | if (is_engine_event(event)) |
| 299 | engine_event_instance(event))) | 310 | engine_event_destroy(event); |
| 300 | return -ENODEV; | 311 | } |
| 301 | 312 | ||
| 302 | switch (engine_event_sample(event)) { | 313 | static int |
| 314 | engine_event_status(struct intel_engine_cs *engine, | ||
| 315 | enum drm_i915_pmu_engine_sample sample) | ||
| 316 | { | ||
| 317 | switch (sample) { | ||
| 303 | case I915_SAMPLE_BUSY: | 318 | case I915_SAMPLE_BUSY: |
| 304 | case I915_SAMPLE_WAIT: | 319 | case I915_SAMPLE_WAIT: |
| 305 | break; | 320 | break; |
| 306 | case I915_SAMPLE_SEMA: | 321 | case I915_SAMPLE_SEMA: |
| 307 | if (INTEL_GEN(i915) < 6) | 322 | if (INTEL_GEN(engine->i915) < 6) |
| 308 | return -ENODEV; | 323 | return -ENODEV; |
| 309 | break; | 324 | break; |
| 310 | default: | 325 | default: |
| @@ -314,6 +329,30 @@ static int engine_event_init(struct perf_event *event) | |||
| 314 | return 0; | 329 | return 0; |
| 315 | } | 330 | } |
| 316 | 331 | ||
| 332 | static int engine_event_init(struct perf_event *event) | ||
| 333 | { | ||
| 334 | struct drm_i915_private *i915 = | ||
| 335 | container_of(event->pmu, typeof(*i915), pmu.base); | ||
| 336 | struct intel_engine_cs *engine; | ||
| 337 | u8 sample; | ||
| 338 | int ret; | ||
| 339 | |||
| 340 | engine = intel_engine_lookup_user(i915, engine_event_class(event), | ||
| 341 | engine_event_instance(event)); | ||
| 342 | if (!engine) | ||
| 343 | return -ENODEV; | ||
| 344 | |||
| 345 | sample = engine_event_sample(event); | ||
| 346 | ret = engine_event_status(engine, sample); | ||
| 347 | if (ret) | ||
| 348 | return ret; | ||
| 349 | |||
| 350 | if (sample == I915_SAMPLE_BUSY && intel_engine_supports_stats(engine)) | ||
| 351 | ret = intel_enable_engine_stats(engine); | ||
| 352 | |||
| 353 | return ret; | ||
| 354 | } | ||
| 355 | |||
| 317 | static int i915_pmu_event_init(struct perf_event *event) | 356 | static int i915_pmu_event_init(struct perf_event *event) |
| 318 | { | 357 | { |
| 319 | struct drm_i915_private *i915 = | 358 | struct drm_i915_private *i915 = |
| @@ -370,7 +409,94 @@ static int i915_pmu_event_init(struct perf_event *event) | |||
| 370 | return 0; | 409 | return 0; |
| 371 | } | 410 | } |
| 372 | 411 | ||
| 373 | static u64 __i915_pmu_event_read(struct perf_event *event) | 412 | static u64 __get_rc6(struct drm_i915_private *i915) |
| 413 | { | ||
| 414 | u64 val; | ||
| 415 | |||
| 416 | val = intel_rc6_residency_ns(i915, | ||
| 417 | IS_VALLEYVIEW(i915) ? | ||
| 418 | VLV_GT_RENDER_RC6 : | ||
| 419 | GEN6_GT_GFX_RC6); | ||
| 420 | |||
| 421 | if (HAS_RC6p(i915)) | ||
| 422 | val += intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6p); | ||
| 423 | |||
| 424 | if (HAS_RC6pp(i915)) | ||
| 425 | val += intel_rc6_residency_ns(i915, GEN6_GT_GFX_RC6pp); | ||
| 426 | |||
| 427 | return val; | ||
| 428 | } | ||
| 429 | |||
| 430 | static u64 get_rc6(struct drm_i915_private *i915, bool locked) | ||
| 431 | { | ||
| 432 | #if IS_ENABLED(CONFIG_PM) | ||
| 433 | unsigned long flags; | ||
| 434 | u64 val; | ||
| 435 | |||
| 436 | if (intel_runtime_pm_get_if_in_use(i915)) { | ||
| 437 | val = __get_rc6(i915); | ||
| 438 | intel_runtime_pm_put(i915); | ||
| 439 | |||
| 440 | /* | ||
| 441 | * If we are coming back from being runtime suspended we must | ||
| 442 | * be careful not to report a larger value than returned | ||
| 443 | * previously. | ||
| 444 | */ | ||
| 445 | |||
| 446 | if (!locked) | ||
| 447 | spin_lock_irqsave(&i915->pmu.lock, flags); | ||
| 448 | |||
| 449 | if (val >= i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) { | ||
| 450 | i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = 0; | ||
| 451 | i915->pmu.sample[__I915_SAMPLE_RC6].cur = val; | ||
| 452 | } else { | ||
| 453 | val = i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur; | ||
| 454 | } | ||
| 455 | |||
| 456 | if (!locked) | ||
| 457 | spin_unlock_irqrestore(&i915->pmu.lock, flags); | ||
| 458 | } else { | ||
| 459 | struct pci_dev *pdev = i915->drm.pdev; | ||
| 460 | struct device *kdev = &pdev->dev; | ||
| 461 | unsigned long flags2; | ||
| 462 | |||
| 463 | /* | ||
| 464 | * We are runtime suspended. | ||
| 465 | * | ||
| 466 | * Report the delta from when the device was suspended to now, | ||
| 467 | * on top of the last known real value, as the approximated RC6 | ||
| 468 | * counter value. | ||
| 469 | */ | ||
| 470 | if (!locked) | ||
| 471 | spin_lock_irqsave(&i915->pmu.lock, flags); | ||
| 472 | |||
| 473 | spin_lock_irqsave(&kdev->power.lock, flags2); | ||
| 474 | |||
| 475 | if (!i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur) | ||
| 476 | i915->pmu.suspended_jiffies_last = | ||
| 477 | kdev->power.suspended_jiffies; | ||
| 478 | |||
| 479 | val = kdev->power.suspended_jiffies - | ||
| 480 | i915->pmu.suspended_jiffies_last; | ||
| 481 | val += jiffies - kdev->power.accounting_timestamp; | ||
| 482 | |||
| 483 | spin_unlock_irqrestore(&kdev->power.lock, flags2); | ||
| 484 | |||
| 485 | val = jiffies_to_nsecs(val); | ||
| 486 | val += i915->pmu.sample[__I915_SAMPLE_RC6].cur; | ||
| 487 | i915->pmu.sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val; | ||
| 488 | |||
| 489 | if (!locked) | ||
| 490 | spin_unlock_irqrestore(&i915->pmu.lock, flags); | ||
| 491 | } | ||
| 492 | |||
| 493 | return val; | ||
| 494 | #else | ||
| 495 | return __get_rc6(i915); | ||
| 496 | #endif | ||
| 497 | } | ||
| 498 | |||
| 499 | static u64 __i915_pmu_event_read(struct perf_event *event, bool locked) | ||
| 374 | { | 500 | { |
| 375 | struct drm_i915_private *i915 = | 501 | struct drm_i915_private *i915 = |
| 376 | container_of(event->pmu, typeof(*i915), pmu.base); | 502 | container_of(event->pmu, typeof(*i915), pmu.base); |
| @@ -387,7 +513,7 @@ static u64 __i915_pmu_event_read(struct perf_event *event) | |||
| 387 | if (WARN_ON_ONCE(!engine)) { | 513 | if (WARN_ON_ONCE(!engine)) { |
| 388 | /* Do nothing */ | 514 | /* Do nothing */ |
| 389 | } else if (sample == I915_SAMPLE_BUSY && | 515 | } else if (sample == I915_SAMPLE_BUSY && |
| 390 | engine->pmu.busy_stats) { | 516 | intel_engine_supports_stats(engine)) { |
| 391 | val = ktime_to_ns(intel_engine_get_busy_time(engine)); | 517 | val = ktime_to_ns(intel_engine_get_busy_time(engine)); |
| 392 | } else { | 518 | } else { |
| 393 | val = engine->pmu.sample[sample].cur; | 519 | val = engine->pmu.sample[sample].cur; |
| @@ -408,18 +534,7 @@ static u64 __i915_pmu_event_read(struct perf_event *event) | |||
| 408 | val = count_interrupts(i915); | 534 | val = count_interrupts(i915); |
| 409 | break; | 535 | break; |
| 410 | case I915_PMU_RC6_RESIDENCY: | 536 | case I915_PMU_RC6_RESIDENCY: |
| 411 | intel_runtime_pm_get(i915); | 537 | val = get_rc6(i915, locked); |
| 412 | val = intel_rc6_residency_ns(i915, | ||
| 413 | IS_VALLEYVIEW(i915) ? | ||
| 414 | VLV_GT_RENDER_RC6 : | ||
| 415 | GEN6_GT_GFX_RC6); | ||
| 416 | if (HAS_RC6p(i915)) | ||
| 417 | val += intel_rc6_residency_ns(i915, | ||
| 418 | GEN6_GT_GFX_RC6p); | ||
| 419 | if (HAS_RC6pp(i915)) | ||
| 420 | val += intel_rc6_residency_ns(i915, | ||
| 421 | GEN6_GT_GFX_RC6pp); | ||
| 422 | intel_runtime_pm_put(i915); | ||
| 423 | break; | 538 | break; |
| 424 | } | 539 | } |
| 425 | } | 540 | } |
| @@ -434,7 +549,7 @@ static void i915_pmu_event_read(struct perf_event *event) | |||
| 434 | 549 | ||
| 435 | again: | 550 | again: |
| 436 | prev = local64_read(&hwc->prev_count); | 551 | prev = local64_read(&hwc->prev_count); |
| 437 | new = __i915_pmu_event_read(event); | 552 | new = __i915_pmu_event_read(event, false); |
| 438 | 553 | ||
| 439 | if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev) | 554 | if (local64_cmpxchg(&hwc->prev_count, prev, new) != prev) |
| 440 | goto again; | 555 | goto again; |
| @@ -442,12 +557,6 @@ again: | |||
| 442 | local64_add(new - prev, &event->count); | 557 | local64_add(new - prev, &event->count); |
| 443 | } | 558 | } |
| 444 | 559 | ||
| 445 | static bool engine_needs_busy_stats(struct intel_engine_cs *engine) | ||
| 446 | { | ||
| 447 | return intel_engine_supports_stats(engine) && | ||
| 448 | (engine->pmu.enable & BIT(I915_SAMPLE_BUSY)); | ||
| 449 | } | ||
| 450 | |||
| 451 | static void i915_pmu_enable(struct perf_event *event) | 560 | static void i915_pmu_enable(struct perf_event *event) |
| 452 | { | 561 | { |
| 453 | struct drm_i915_private *i915 = | 562 | struct drm_i915_private *i915 = |
| @@ -487,21 +596,7 @@ static void i915_pmu_enable(struct perf_event *event) | |||
| 487 | 596 | ||
| 488 | GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS); | 597 | GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS); |
| 489 | GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0); | 598 | GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0); |
| 490 | if (engine->pmu.enable_count[sample]++ == 0) { | 599 | engine->pmu.enable_count[sample]++; |
| 491 | /* | ||
| 492 | * Enable engine busy stats tracking if needed or | ||
| 493 | * alternatively cancel the scheduled disable. | ||
| 494 | * | ||
| 495 | * If the delayed disable was pending, cancel it and | ||
| 496 | * in this case do not enable since it already is. | ||
| 497 | */ | ||
| 498 | if (engine_needs_busy_stats(engine) && | ||
| 499 | !engine->pmu.busy_stats) { | ||
| 500 | engine->pmu.busy_stats = true; | ||
| 501 | if (!cancel_delayed_work(&engine->pmu.disable_busy_stats)) | ||
| 502 | intel_enable_engine_stats(engine); | ||
| 503 | } | ||
| 504 | } | ||
| 505 | } | 600 | } |
| 506 | 601 | ||
| 507 | /* | 602 | /* |
| @@ -509,19 +604,11 @@ static void i915_pmu_enable(struct perf_event *event) | |||
| 509 | * for all listeners. Even when the event was already enabled and has | 604 | * for all listeners. Even when the event was already enabled and has |
| 510 | * an existing non-zero value. | 605 | * an existing non-zero value. |
| 511 | */ | 606 | */ |
| 512 | local64_set(&event->hw.prev_count, __i915_pmu_event_read(event)); | 607 | local64_set(&event->hw.prev_count, __i915_pmu_event_read(event, true)); |
| 513 | 608 | ||
| 514 | spin_unlock_irqrestore(&i915->pmu.lock, flags); | 609 | spin_unlock_irqrestore(&i915->pmu.lock, flags); |
| 515 | } | 610 | } |
| 516 | 611 | ||
| 517 | static void __disable_busy_stats(struct work_struct *work) | ||
| 518 | { | ||
| 519 | struct intel_engine_cs *engine = | ||
| 520 | container_of(work, typeof(*engine), pmu.disable_busy_stats.work); | ||
| 521 | |||
| 522 | intel_disable_engine_stats(engine); | ||
| 523 | } | ||
| 524 | |||
| 525 | static void i915_pmu_disable(struct perf_event *event) | 612 | static void i915_pmu_disable(struct perf_event *event) |
| 526 | { | 613 | { |
| 527 | struct drm_i915_private *i915 = | 614 | struct drm_i915_private *i915 = |
| @@ -545,26 +632,8 @@ static void i915_pmu_disable(struct perf_event *event) | |||
| 545 | * Decrement the reference count and clear the enabled | 632 | * Decrement the reference count and clear the enabled |
| 546 | * bitmask when the last listener on an event goes away. | 633 | * bitmask when the last listener on an event goes away. |
| 547 | */ | 634 | */ |
| 548 | if (--engine->pmu.enable_count[sample] == 0) { | 635 | if (--engine->pmu.enable_count[sample] == 0) |
| 549 | engine->pmu.enable &= ~BIT(sample); | 636 | engine->pmu.enable &= ~BIT(sample); |
| 550 | if (!engine_needs_busy_stats(engine) && | ||
| 551 | engine->pmu.busy_stats) { | ||
| 552 | engine->pmu.busy_stats = false; | ||
| 553 | /* | ||
| 554 | * We request a delayed disable to handle the | ||
| 555 | * rapid on/off cycles on events, which can | ||
| 556 | * happen when tools like perf stat start, in a | ||
| 557 | * nicer way. | ||
| 558 | * | ||
| 559 | * In addition, this also helps with busy stats | ||
| 560 | * accuracy with background CPU offline/online | ||
| 561 | * migration events. | ||
| 562 | */ | ||
| 563 | queue_delayed_work(system_wq, | ||
| 564 | &engine->pmu.disable_busy_stats, | ||
| 565 | round_jiffies_up_relative(HZ)); | ||
| 566 | } | ||
| 567 | } | ||
| 568 | } | 637 | } |
| 569 | 638 | ||
| 570 | GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); | 639 | GEM_BUG_ON(bit >= I915_PMU_MASK_BITS); |
| @@ -797,8 +866,6 @@ static void i915_pmu_unregister_cpuhp_state(struct drm_i915_private *i915) | |||
| 797 | 866 | ||
| 798 | void i915_pmu_register(struct drm_i915_private *i915) | 867 | void i915_pmu_register(struct drm_i915_private *i915) |
| 799 | { | 868 | { |
| 800 | struct intel_engine_cs *engine; | ||
| 801 | enum intel_engine_id id; | ||
| 802 | int ret; | 869 | int ret; |
| 803 | 870 | ||
| 804 | if (INTEL_GEN(i915) <= 2) { | 871 | if (INTEL_GEN(i915) <= 2) { |
| @@ -820,10 +887,6 @@ void i915_pmu_register(struct drm_i915_private *i915) | |||
| 820 | hrtimer_init(&i915->pmu.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 887 | hrtimer_init(&i915->pmu.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
| 821 | i915->pmu.timer.function = i915_sample; | 888 | i915->pmu.timer.function = i915_sample; |
| 822 | 889 | ||
| 823 | for_each_engine(engine, i915, id) | ||
| 824 | INIT_DELAYED_WORK(&engine->pmu.disable_busy_stats, | ||
| 825 | __disable_busy_stats); | ||
| 826 | |||
| 827 | ret = perf_pmu_register(&i915->pmu.base, "i915", -1); | 890 | ret = perf_pmu_register(&i915->pmu.base, "i915", -1); |
| 828 | if (ret) | 891 | if (ret) |
| 829 | goto err; | 892 | goto err; |
| @@ -843,9 +906,6 @@ err: | |||
| 843 | 906 | ||
| 844 | void i915_pmu_unregister(struct drm_i915_private *i915) | 907 | void i915_pmu_unregister(struct drm_i915_private *i915) |
| 845 | { | 908 | { |
| 846 | struct intel_engine_cs *engine; | ||
| 847 | enum intel_engine_id id; | ||
| 848 | |||
| 849 | if (!i915->pmu.base.event_init) | 909 | if (!i915->pmu.base.event_init) |
| 850 | return; | 910 | return; |
| 851 | 911 | ||
| @@ -853,11 +913,6 @@ void i915_pmu_unregister(struct drm_i915_private *i915) | |||
| 853 | 913 | ||
| 854 | hrtimer_cancel(&i915->pmu.timer); | 914 | hrtimer_cancel(&i915->pmu.timer); |
| 855 | 915 | ||
| 856 | for_each_engine(engine, i915, id) { | ||
| 857 | GEM_BUG_ON(engine->pmu.busy_stats); | ||
| 858 | flush_delayed_work(&engine->pmu.disable_busy_stats); | ||
| 859 | } | ||
| 860 | |||
| 861 | i915_pmu_unregister_cpuhp_state(i915); | 916 | i915_pmu_unregister_cpuhp_state(i915); |
| 862 | 917 | ||
| 863 | perf_pmu_unregister(&i915->pmu.base); | 918 | perf_pmu_unregister(&i915->pmu.base); |
diff --git a/drivers/gpu/drm/i915/i915_pmu.h b/drivers/gpu/drm/i915/i915_pmu.h index 40c154d13565..bb62df15afa4 100644 --- a/drivers/gpu/drm/i915/i915_pmu.h +++ b/drivers/gpu/drm/i915/i915_pmu.h | |||
| @@ -27,6 +27,8 @@ | |||
| 27 | enum { | 27 | enum { |
| 28 | __I915_SAMPLE_FREQ_ACT = 0, | 28 | __I915_SAMPLE_FREQ_ACT = 0, |
| 29 | __I915_SAMPLE_FREQ_REQ, | 29 | __I915_SAMPLE_FREQ_REQ, |
| 30 | __I915_SAMPLE_RC6, | ||
| 31 | __I915_SAMPLE_RC6_ESTIMATED, | ||
| 30 | __I915_NUM_PMU_SAMPLERS | 32 | __I915_NUM_PMU_SAMPLERS |
| 31 | }; | 33 | }; |
| 32 | 34 | ||
| @@ -94,6 +96,10 @@ struct i915_pmu { | |||
| 94 | * struct intel_engine_cs. | 96 | * struct intel_engine_cs. |
| 95 | */ | 97 | */ |
| 96 | struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS]; | 98 | struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS]; |
| 99 | /** | ||
| 100 | * @suspended_jiffies_last: Cached suspend time from PM core. | ||
| 101 | */ | ||
| 102 | unsigned long suspended_jiffies_last; | ||
| 97 | }; | 103 | }; |
| 98 | 104 | ||
| 99 | #ifdef CONFIG_PERF_EVENTS | 105 | #ifdef CONFIG_PERF_EVENTS |
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index f7f771749e48..b49a2df44430 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c | |||
| @@ -947,6 +947,86 @@ static int goto_next_sequence_v3(const u8 *data, int index, int total) | |||
| 947 | return 0; | 947 | return 0; |
| 948 | } | 948 | } |
| 949 | 949 | ||
| 950 | /* | ||
| 951 | * Get len of pre-fixed deassert fragment from a v1 init OTP sequence, | ||
| 952 | * skip all delay + gpio operands and stop at the first DSI packet op. | ||
| 953 | */ | ||
| 954 | static int get_init_otp_deassert_fragment_len(struct drm_i915_private *dev_priv) | ||
| 955 | { | ||
| 956 | const u8 *data = dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; | ||
| 957 | int index, len; | ||
| 958 | |||
| 959 | if (WARN_ON(!data || dev_priv->vbt.dsi.seq_version != 1)) | ||
| 960 | return 0; | ||
| 961 | |||
| 962 | /* index = 1 to skip sequence byte */ | ||
| 963 | for (index = 1; data[index] != MIPI_SEQ_ELEM_END; index += len) { | ||
| 964 | switch (data[index]) { | ||
| 965 | case MIPI_SEQ_ELEM_SEND_PKT: | ||
| 966 | return index == 1 ? 0 : index; | ||
| 967 | case MIPI_SEQ_ELEM_DELAY: | ||
| 968 | len = 5; /* 1 byte for operand + uint32 */ | ||
| 969 | break; | ||
| 970 | case MIPI_SEQ_ELEM_GPIO: | ||
| 971 | len = 3; /* 1 byte for op, 1 for gpio_nr, 1 for value */ | ||
| 972 | break; | ||
| 973 | default: | ||
| 974 | return 0; | ||
| 975 | } | ||
| 976 | } | ||
| 977 | |||
| 978 | return 0; | ||
| 979 | } | ||
| 980 | |||
| 981 | /* | ||
| 982 | * Some v1 VBT MIPI sequences do the deassert in the init OTP sequence. | ||
| 983 | * The deassert must be done before calling intel_dsi_device_ready, so for | ||
| 984 | * these devices we split the init OTP sequence into a deassert sequence and | ||
| 985 | * the actual init OTP part. | ||
| 986 | */ | ||
| 987 | static void fixup_mipi_sequences(struct drm_i915_private *dev_priv) | ||
| 988 | { | ||
| 989 | u8 *init_otp; | ||
| 990 | int len; | ||
| 991 | |||
| 992 | /* Limit this to VLV for now. */ | ||
| 993 | if (!IS_VALLEYVIEW(dev_priv)) | ||
| 994 | return; | ||
| 995 | |||
| 996 | /* Limit this to v1 vid-mode sequences */ | ||
| 997 | if (dev_priv->vbt.dsi.config->is_cmd_mode || | ||
| 998 | dev_priv->vbt.dsi.seq_version != 1) | ||
| 999 | return; | ||
| 1000 | |||
| 1001 | /* Only do this if there are otp and assert seqs and no deassert seq */ | ||
| 1002 | if (!dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] || | ||
| 1003 | !dev_priv->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET] || | ||
| 1004 | dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]) | ||
| 1005 | return; | ||
| 1006 | |||
| 1007 | /* The deassert-sequence ends at the first DSI packet */ | ||
| 1008 | len = get_init_otp_deassert_fragment_len(dev_priv); | ||
| 1009 | if (!len) | ||
| 1010 | return; | ||
| 1011 | |||
| 1012 | DRM_DEBUG_KMS("Using init OTP fragment to deassert reset\n"); | ||
| 1013 | |||
| 1014 | /* Copy the fragment, update seq byte and terminate it */ | ||
| 1015 | init_otp = (u8 *)dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; | ||
| 1016 | dev_priv->vbt.dsi.deassert_seq = kmemdup(init_otp, len + 1, GFP_KERNEL); | ||
| 1017 | if (!dev_priv->vbt.dsi.deassert_seq) | ||
| 1018 | return; | ||
| 1019 | dev_priv->vbt.dsi.deassert_seq[0] = MIPI_SEQ_DEASSERT_RESET; | ||
| 1020 | dev_priv->vbt.dsi.deassert_seq[len] = MIPI_SEQ_ELEM_END; | ||
| 1021 | /* Use the copy for deassert */ | ||
| 1022 | dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET] = | ||
| 1023 | dev_priv->vbt.dsi.deassert_seq; | ||
| 1024 | /* Replace the last byte of the fragment with init OTP seq byte */ | ||
| 1025 | init_otp[len - 1] = MIPI_SEQ_INIT_OTP; | ||
| 1026 | /* And make MIPI_MIPI_SEQ_INIT_OTP point to it */ | ||
| 1027 | dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP] = init_otp + len - 1; | ||
| 1028 | } | ||
| 1029 | |||
| 950 | static void | 1030 | static void |
| 951 | parse_mipi_sequence(struct drm_i915_private *dev_priv, | 1031 | parse_mipi_sequence(struct drm_i915_private *dev_priv, |
| 952 | const struct bdb_header *bdb) | 1032 | const struct bdb_header *bdb) |
| @@ -1016,6 +1096,8 @@ parse_mipi_sequence(struct drm_i915_private *dev_priv, | |||
| 1016 | dev_priv->vbt.dsi.size = seq_size; | 1096 | dev_priv->vbt.dsi.size = seq_size; |
| 1017 | dev_priv->vbt.dsi.seq_version = sequence->version; | 1097 | dev_priv->vbt.dsi.seq_version = sequence->version; |
| 1018 | 1098 | ||
| 1099 | fixup_mipi_sequences(dev_priv); | ||
| 1100 | |||
| 1019 | DRM_DEBUG_DRIVER("MIPI related VBT parsing complete\n"); | 1101 | DRM_DEBUG_DRIVER("MIPI related VBT parsing complete\n"); |
| 1020 | return; | 1102 | return; |
| 1021 | 1103 | ||
| @@ -1589,6 +1671,29 @@ out: | |||
| 1589 | } | 1671 | } |
| 1590 | 1672 | ||
| 1591 | /** | 1673 | /** |
| 1674 | * intel_bios_cleanup - Free any resources allocated by intel_bios_init() | ||
| 1675 | * @dev_priv: i915 device instance | ||
| 1676 | */ | ||
| 1677 | void intel_bios_cleanup(struct drm_i915_private *dev_priv) | ||
| 1678 | { | ||
| 1679 | kfree(dev_priv->vbt.child_dev); | ||
| 1680 | dev_priv->vbt.child_dev = NULL; | ||
| 1681 | dev_priv->vbt.child_dev_num = 0; | ||
| 1682 | kfree(dev_priv->vbt.sdvo_lvds_vbt_mode); | ||
| 1683 | dev_priv->vbt.sdvo_lvds_vbt_mode = NULL; | ||
| 1684 | kfree(dev_priv->vbt.lfp_lvds_vbt_mode); | ||
| 1685 | dev_priv->vbt.lfp_lvds_vbt_mode = NULL; | ||
| 1686 | kfree(dev_priv->vbt.dsi.data); | ||
| 1687 | dev_priv->vbt.dsi.data = NULL; | ||
| 1688 | kfree(dev_priv->vbt.dsi.pps); | ||
| 1689 | dev_priv->vbt.dsi.pps = NULL; | ||
| 1690 | kfree(dev_priv->vbt.dsi.config); | ||
| 1691 | dev_priv->vbt.dsi.config = NULL; | ||
| 1692 | kfree(dev_priv->vbt.dsi.deassert_seq); | ||
| 1693 | dev_priv->vbt.dsi.deassert_seq = NULL; | ||
| 1694 | } | ||
| 1695 | |||
| 1696 | /** | ||
| 1592 | * intel_bios_is_tv_present - is integrated TV present in VBT | 1697 | * intel_bios_is_tv_present - is integrated TV present in VBT |
| 1593 | * @dev_priv: i915 device instance | 1698 | * @dev_priv: i915 device instance |
| 1594 | * | 1699 | * |
diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index bd40fea16b4f..f54ddda9fdad 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c | |||
| @@ -594,29 +594,16 @@ void intel_engine_remove_wait(struct intel_engine_cs *engine, | |||
| 594 | spin_unlock_irq(&b->rb_lock); | 594 | spin_unlock_irq(&b->rb_lock); |
| 595 | } | 595 | } |
| 596 | 596 | ||
| 597 | static bool signal_valid(const struct drm_i915_gem_request *request) | ||
| 598 | { | ||
| 599 | return intel_wait_check_request(&request->signaling.wait, request); | ||
| 600 | } | ||
| 601 | |||
| 602 | static bool signal_complete(const struct drm_i915_gem_request *request) | 597 | static bool signal_complete(const struct drm_i915_gem_request *request) |
| 603 | { | 598 | { |
| 604 | if (!request) | 599 | if (!request) |
| 605 | return false; | 600 | return false; |
| 606 | 601 | ||
| 607 | /* If another process served as the bottom-half it may have already | 602 | /* |
| 608 | * signalled that this wait is already completed. | 603 | * Carefully check if the request is complete, giving time for the |
| 609 | */ | ||
| 610 | if (intel_wait_complete(&request->signaling.wait)) | ||
| 611 | return signal_valid(request); | ||
| 612 | |||
| 613 | /* Carefully check if the request is complete, giving time for the | ||
| 614 | * seqno to be visible or if the GPU hung. | 604 | * seqno to be visible or if the GPU hung. |
| 615 | */ | 605 | */ |
| 616 | if (__i915_request_irq_complete(request)) | 606 | return __i915_request_irq_complete(request); |
| 617 | return true; | ||
| 618 | |||
| 619 | return false; | ||
| 620 | } | 607 | } |
| 621 | 608 | ||
| 622 | static struct drm_i915_gem_request *to_signaler(struct rb_node *rb) | 609 | static struct drm_i915_gem_request *to_signaler(struct rb_node *rb) |
| @@ -659,9 +646,13 @@ static int intel_breadcrumbs_signaler(void *arg) | |||
| 659 | request = i915_gem_request_get_rcu(request); | 646 | request = i915_gem_request_get_rcu(request); |
| 660 | rcu_read_unlock(); | 647 | rcu_read_unlock(); |
| 661 | if (signal_complete(request)) { | 648 | if (signal_complete(request)) { |
| 662 | local_bh_disable(); | 649 | if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, |
| 663 | dma_fence_signal(&request->fence); | 650 | &request->fence.flags)) { |
| 664 | local_bh_enable(); /* kick start the tasklets */ | 651 | local_bh_disable(); |
| 652 | dma_fence_signal(&request->fence); | ||
| 653 | GEM_BUG_ON(!i915_gem_request_completed(request)); | ||
| 654 | local_bh_enable(); /* kick start the tasklets */ | ||
| 655 | } | ||
| 665 | 656 | ||
| 666 | spin_lock_irq(&b->rb_lock); | 657 | spin_lock_irq(&b->rb_lock); |
| 667 | 658 | ||
diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index 5dc118f26b51..1704c8897afd 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c | |||
| @@ -1952,6 +1952,14 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) | |||
| 1952 | if (crtc_state->has_audio && INTEL_GEN(dev_priv) >= 9) | 1952 | if (crtc_state->has_audio && INTEL_GEN(dev_priv) >= 9) |
| 1953 | min_cdclk = max(2 * 96000, min_cdclk); | 1953 | min_cdclk = max(2 * 96000, min_cdclk); |
| 1954 | 1954 | ||
| 1955 | /* | ||
| 1956 | * On Valleyview some DSI panels lose (v|h)sync when the clock is lower | ||
| 1957 | * than 320000KHz. | ||
| 1958 | */ | ||
| 1959 | if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI) && | ||
| 1960 | IS_VALLEYVIEW(dev_priv)) | ||
| 1961 | min_cdclk = max(320000, min_cdclk); | ||
| 1962 | |||
| 1955 | if (min_cdclk > dev_priv->max_cdclk_freq) { | 1963 | if (min_cdclk > dev_priv->max_cdclk_freq) { |
| 1956 | DRM_DEBUG_KMS("required cdclk (%d kHz) exceeds max (%d kHz)\n", | 1964 | DRM_DEBUG_KMS("required cdclk (%d kHz) exceeds max (%d kHz)\n", |
| 1957 | min_cdclk, dev_priv->max_cdclk_freq); | 1965 | min_cdclk, dev_priv->max_cdclk_freq); |
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index d790bdc227ff..fa960cfd2764 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c | |||
| @@ -1458,7 +1458,9 @@ static bool ring_is_idle(struct intel_engine_cs *engine) | |||
| 1458 | struct drm_i915_private *dev_priv = engine->i915; | 1458 | struct drm_i915_private *dev_priv = engine->i915; |
| 1459 | bool idle = true; | 1459 | bool idle = true; |
| 1460 | 1460 | ||
| 1461 | intel_runtime_pm_get(dev_priv); | 1461 | /* If the whole device is asleep, the engine must be idle */ |
| 1462 | if (!intel_runtime_pm_get_if_in_use(dev_priv)) | ||
| 1463 | return true; | ||
| 1462 | 1464 | ||
| 1463 | /* First check that no commands are left in the ring */ | 1465 | /* First check that no commands are left in the ring */ |
| 1464 | if ((I915_READ_HEAD(engine) & HEAD_ADDR) != | 1466 | if ((I915_READ_HEAD(engine) & HEAD_ADDR) != |
| @@ -1943,16 +1945,22 @@ intel_engine_lookup_user(struct drm_i915_private *i915, u8 class, u8 instance) | |||
| 1943 | */ | 1945 | */ |
| 1944 | int intel_enable_engine_stats(struct intel_engine_cs *engine) | 1946 | int intel_enable_engine_stats(struct intel_engine_cs *engine) |
| 1945 | { | 1947 | { |
| 1948 | struct intel_engine_execlists *execlists = &engine->execlists; | ||
| 1946 | unsigned long flags; | 1949 | unsigned long flags; |
| 1950 | int err = 0; | ||
| 1947 | 1951 | ||
| 1948 | if (!intel_engine_supports_stats(engine)) | 1952 | if (!intel_engine_supports_stats(engine)) |
| 1949 | return -ENODEV; | 1953 | return -ENODEV; |
| 1950 | 1954 | ||
| 1955 | tasklet_disable(&execlists->tasklet); | ||
| 1951 | spin_lock_irqsave(&engine->stats.lock, flags); | 1956 | spin_lock_irqsave(&engine->stats.lock, flags); |
| 1952 | if (engine->stats.enabled == ~0) | 1957 | |
| 1953 | goto busy; | 1958 | if (unlikely(engine->stats.enabled == ~0)) { |
| 1959 | err = -EBUSY; | ||
| 1960 | goto unlock; | ||
| 1961 | } | ||
| 1962 | |||
| 1954 | if (engine->stats.enabled++ == 0) { | 1963 | if (engine->stats.enabled++ == 0) { |
| 1955 | struct intel_engine_execlists *execlists = &engine->execlists; | ||
| 1956 | const struct execlist_port *port = execlists->port; | 1964 | const struct execlist_port *port = execlists->port; |
| 1957 | unsigned int num_ports = execlists_num_ports(execlists); | 1965 | unsigned int num_ports = execlists_num_ports(execlists); |
| 1958 | 1966 | ||
| @@ -1967,14 +1975,12 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine) | |||
| 1967 | if (engine->stats.active) | 1975 | if (engine->stats.active) |
| 1968 | engine->stats.start = engine->stats.enabled_at; | 1976 | engine->stats.start = engine->stats.enabled_at; |
| 1969 | } | 1977 | } |
| 1970 | spin_unlock_irqrestore(&engine->stats.lock, flags); | ||
| 1971 | |||
| 1972 | return 0; | ||
| 1973 | 1978 | ||
| 1974 | busy: | 1979 | unlock: |
| 1975 | spin_unlock_irqrestore(&engine->stats.lock, flags); | 1980 | spin_unlock_irqrestore(&engine->stats.lock, flags); |
| 1981 | tasklet_enable(&execlists->tasklet); | ||
| 1976 | 1982 | ||
| 1977 | return -EBUSY; | 1983 | return err; |
| 1978 | } | 1984 | } |
| 1979 | 1985 | ||
| 1980 | static ktime_t __intel_engine_get_busy_time(struct intel_engine_cs *engine) | 1986 | static ktime_t __intel_engine_get_busy_time(struct intel_engine_cs *engine) |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index c5ff203e42d6..a0e7a6c2a57c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h | |||
| @@ -366,20 +366,6 @@ struct intel_engine_cs { | |||
| 366 | */ | 366 | */ |
| 367 | #define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_SEMA + 1) | 367 | #define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_SEMA + 1) |
| 368 | struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX]; | 368 | struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX]; |
| 369 | /** | ||
| 370 | * @busy_stats: Has enablement of engine stats tracking been | ||
| 371 | * requested. | ||
| 372 | */ | ||
| 373 | bool busy_stats; | ||
| 374 | /** | ||
| 375 | * @disable_busy_stats: Work item for busy stats disabling. | ||
| 376 | * | ||
| 377 | * Same as with @enable_busy_stats action, with the difference | ||
| 378 | * that we delay it in case there are rapid enable-disable | ||
| 379 | * actions, which can happen during tool startup (like perf | ||
| 380 | * stat). | ||
| 381 | */ | ||
| 382 | struct delayed_work disable_busy_stats; | ||
| 383 | } pmu; | 369 | } pmu; |
| 384 | 370 | ||
| 385 | /* | 371 | /* |
diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c index 5155f0179b61..05520202c967 100644 --- a/drivers/gpu/drm/meson/meson_crtc.c +++ b/drivers/gpu/drm/meson/meson_crtc.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include "meson_venc.h" | 36 | #include "meson_venc.h" |
| 37 | #include "meson_vpp.h" | 37 | #include "meson_vpp.h" |
| 38 | #include "meson_viu.h" | 38 | #include "meson_viu.h" |
| 39 | #include "meson_canvas.h" | ||
| 39 | #include "meson_registers.h" | 40 | #include "meson_registers.h" |
| 40 | 41 | ||
| 41 | /* CRTC definition */ | 42 | /* CRTC definition */ |
| @@ -192,6 +193,11 @@ void meson_crtc_irq(struct meson_drm *priv) | |||
| 192 | } else | 193 | } else |
| 193 | meson_vpp_disable_interlace_vscaler_osd1(priv); | 194 | meson_vpp_disable_interlace_vscaler_osd1(priv); |
| 194 | 195 | ||
| 196 | meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1, | ||
| 197 | priv->viu.osd1_addr, priv->viu.osd1_stride, | ||
| 198 | priv->viu.osd1_height, MESON_CANVAS_WRAP_NONE, | ||
| 199 | MESON_CANVAS_BLKMODE_LINEAR); | ||
| 200 | |||
| 195 | /* Enable OSD1 */ | 201 | /* Enable OSD1 */ |
| 196 | writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND, | 202 | writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND, |
| 197 | priv->io_base + _REG(VPP_MISC)); | 203 | priv->io_base + _REG(VPP_MISC)); |
diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h index 5e8b392b9d1f..8450d6ac8c9b 100644 --- a/drivers/gpu/drm/meson/meson_drv.h +++ b/drivers/gpu/drm/meson/meson_drv.h | |||
| @@ -43,6 +43,9 @@ struct meson_drm { | |||
| 43 | bool osd1_commit; | 43 | bool osd1_commit; |
| 44 | uint32_t osd1_ctrl_stat; | 44 | uint32_t osd1_ctrl_stat; |
| 45 | uint32_t osd1_blk0_cfg[5]; | 45 | uint32_t osd1_blk0_cfg[5]; |
| 46 | uint32_t osd1_addr; | ||
| 47 | uint32_t osd1_stride; | ||
| 48 | uint32_t osd1_height; | ||
| 46 | } viu; | 49 | } viu; |
| 47 | 50 | ||
| 48 | struct { | 51 | struct { |
diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index d0a6ac8390f3..27bd3503e1e4 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c | |||
| @@ -164,10 +164,9 @@ static void meson_plane_atomic_update(struct drm_plane *plane, | |||
| 164 | /* Update Canvas with buffer address */ | 164 | /* Update Canvas with buffer address */ |
| 165 | gem = drm_fb_cma_get_gem_obj(fb, 0); | 165 | gem = drm_fb_cma_get_gem_obj(fb, 0); |
| 166 | 166 | ||
| 167 | meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1, | 167 | priv->viu.osd1_addr = gem->paddr; |
| 168 | gem->paddr, fb->pitches[0], | 168 | priv->viu.osd1_stride = fb->pitches[0]; |
| 169 | fb->height, MESON_CANVAS_WRAP_NONE, | 169 | priv->viu.osd1_height = fb->height; |
| 170 | MESON_CANVAS_BLKMODE_LINEAR); | ||
| 171 | 170 | ||
| 172 | spin_unlock_irqrestore(&priv->drm->event_lock, flags); | 171 | spin_unlock_irqrestore(&priv->drm->event_lock, flags); |
| 173 | } | 172 | } |
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index 3e9bba4d6624..6d8e3a9a6fc0 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c | |||
| @@ -680,7 +680,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) | |||
| 680 | } else { | 680 | } else { |
| 681 | dev_info(&pdev->dev, | 681 | dev_info(&pdev->dev, |
| 682 | "no iommu, fallback to phys contig buffers for scanout\n"); | 682 | "no iommu, fallback to phys contig buffers for scanout\n"); |
| 683 | aspace = NULL;; | 683 | aspace = NULL; |
| 684 | } | 684 | } |
| 685 | 685 | ||
| 686 | pm_runtime_put_sync(&pdev->dev); | 686 | pm_runtime_put_sync(&pdev->dev); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 69d6e61a01ec..6ed9cb053dfa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
| @@ -570,9 +570,15 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
| 570 | nv_connector->edid = NULL; | 570 | nv_connector->edid = NULL; |
| 571 | } | 571 | } |
| 572 | 572 | ||
| 573 | ret = pm_runtime_get_sync(connector->dev->dev); | 573 | /* Outputs are only polled while runtime active, so acquiring a |
| 574 | if (ret < 0 && ret != -EACCES) | 574 | * runtime PM ref here is unnecessary (and would deadlock upon |
| 575 | return conn_status; | 575 | * runtime suspend because it waits for polling to finish). |
| 576 | */ | ||
| 577 | if (!drm_kms_helper_is_poll_worker()) { | ||
| 578 | ret = pm_runtime_get_sync(connector->dev->dev); | ||
| 579 | if (ret < 0 && ret != -EACCES) | ||
| 580 | return conn_status; | ||
| 581 | } | ||
| 576 | 582 | ||
| 577 | nv_encoder = nouveau_connector_ddc_detect(connector); | 583 | nv_encoder = nouveau_connector_ddc_detect(connector); |
| 578 | if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { | 584 | if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { |
| @@ -647,8 +653,10 @@ detect_analog: | |||
| 647 | 653 | ||
| 648 | out: | 654 | out: |
| 649 | 655 | ||
| 650 | pm_runtime_mark_last_busy(connector->dev->dev); | 656 | if (!drm_kms_helper_is_poll_worker()) { |
| 651 | pm_runtime_put_autosuspend(connector->dev->dev); | 657 | pm_runtime_mark_last_busy(connector->dev->dev); |
| 658 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
| 659 | } | ||
| 652 | 660 | ||
| 653 | return conn_status; | 661 | return conn_status; |
| 654 | } | 662 | } |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index bf62303571b3..3695cde669f8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c | |||
| @@ -301,7 +301,7 @@ nvkm_therm_attr_set(struct nvkm_therm *therm, | |||
| 301 | void | 301 | void |
| 302 | nvkm_therm_clkgate_enable(struct nvkm_therm *therm) | 302 | nvkm_therm_clkgate_enable(struct nvkm_therm *therm) |
| 303 | { | 303 | { |
| 304 | if (!therm->func->clkgate_enable || !therm->clkgating_enabled) | 304 | if (!therm || !therm->func->clkgate_enable || !therm->clkgating_enabled) |
| 305 | return; | 305 | return; |
| 306 | 306 | ||
| 307 | nvkm_debug(&therm->subdev, | 307 | nvkm_debug(&therm->subdev, |
| @@ -312,7 +312,7 @@ nvkm_therm_clkgate_enable(struct nvkm_therm *therm) | |||
| 312 | void | 312 | void |
| 313 | nvkm_therm_clkgate_fini(struct nvkm_therm *therm, bool suspend) | 313 | nvkm_therm_clkgate_fini(struct nvkm_therm *therm, bool suspend) |
| 314 | { | 314 | { |
| 315 | if (!therm->func->clkgate_fini || !therm->clkgating_enabled) | 315 | if (!therm || !therm->func->clkgate_fini || !therm->clkgating_enabled) |
| 316 | return; | 316 | return; |
| 317 | 317 | ||
| 318 | nvkm_debug(&therm->subdev, | 318 | nvkm_debug(&therm->subdev, |
| @@ -395,7 +395,7 @@ void | |||
| 395 | nvkm_therm_clkgate_init(struct nvkm_therm *therm, | 395 | nvkm_therm_clkgate_init(struct nvkm_therm *therm, |
| 396 | const struct nvkm_therm_clkgate_pack *p) | 396 | const struct nvkm_therm_clkgate_pack *p) |
| 397 | { | 397 | { |
| 398 | if (!therm->func->clkgate_init || !therm->clkgating_enabled) | 398 | if (!therm || !therm->func->clkgate_init || !therm->clkgating_enabled) |
| 399 | return; | 399 | return; |
| 400 | 400 | ||
| 401 | therm->func->clkgate_init(therm, p); | 401 | therm->func->clkgate_init(therm, p); |
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 5012f5e47a1e..2e2ca3c6b47d 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c | |||
| @@ -899,9 +899,11 @@ radeon_lvds_detect(struct drm_connector *connector, bool force) | |||
| 899 | enum drm_connector_status ret = connector_status_disconnected; | 899 | enum drm_connector_status ret = connector_status_disconnected; |
| 900 | int r; | 900 | int r; |
| 901 | 901 | ||
| 902 | r = pm_runtime_get_sync(connector->dev->dev); | 902 | if (!drm_kms_helper_is_poll_worker()) { |
| 903 | if (r < 0) | 903 | r = pm_runtime_get_sync(connector->dev->dev); |
| 904 | return connector_status_disconnected; | 904 | if (r < 0) |
| 905 | return connector_status_disconnected; | ||
| 906 | } | ||
| 905 | 907 | ||
| 906 | if (encoder) { | 908 | if (encoder) { |
| 907 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 909 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
| @@ -924,8 +926,12 @@ radeon_lvds_detect(struct drm_connector *connector, bool force) | |||
| 924 | /* check acpi lid status ??? */ | 926 | /* check acpi lid status ??? */ |
| 925 | 927 | ||
| 926 | radeon_connector_update_scratch_regs(connector, ret); | 928 | radeon_connector_update_scratch_regs(connector, ret); |
| 927 | pm_runtime_mark_last_busy(connector->dev->dev); | 929 | |
| 928 | pm_runtime_put_autosuspend(connector->dev->dev); | 930 | if (!drm_kms_helper_is_poll_worker()) { |
| 931 | pm_runtime_mark_last_busy(connector->dev->dev); | ||
| 932 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
| 933 | } | ||
| 934 | |||
| 929 | return ret; | 935 | return ret; |
| 930 | } | 936 | } |
| 931 | 937 | ||
| @@ -1039,9 +1045,11 @@ radeon_vga_detect(struct drm_connector *connector, bool force) | |||
| 1039 | enum drm_connector_status ret = connector_status_disconnected; | 1045 | enum drm_connector_status ret = connector_status_disconnected; |
| 1040 | int r; | 1046 | int r; |
| 1041 | 1047 | ||
| 1042 | r = pm_runtime_get_sync(connector->dev->dev); | 1048 | if (!drm_kms_helper_is_poll_worker()) { |
| 1043 | if (r < 0) | 1049 | r = pm_runtime_get_sync(connector->dev->dev); |
| 1044 | return connector_status_disconnected; | 1050 | if (r < 0) |
| 1051 | return connector_status_disconnected; | ||
| 1052 | } | ||
| 1045 | 1053 | ||
| 1046 | encoder = radeon_best_single_encoder(connector); | 1054 | encoder = radeon_best_single_encoder(connector); |
| 1047 | if (!encoder) | 1055 | if (!encoder) |
| @@ -1108,8 +1116,10 @@ radeon_vga_detect(struct drm_connector *connector, bool force) | |||
| 1108 | radeon_connector_update_scratch_regs(connector, ret); | 1116 | radeon_connector_update_scratch_regs(connector, ret); |
| 1109 | 1117 | ||
| 1110 | out: | 1118 | out: |
| 1111 | pm_runtime_mark_last_busy(connector->dev->dev); | 1119 | if (!drm_kms_helper_is_poll_worker()) { |
| 1112 | pm_runtime_put_autosuspend(connector->dev->dev); | 1120 | pm_runtime_mark_last_busy(connector->dev->dev); |
| 1121 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
| 1122 | } | ||
| 1113 | 1123 | ||
| 1114 | return ret; | 1124 | return ret; |
| 1115 | } | 1125 | } |
| @@ -1173,9 +1183,11 @@ radeon_tv_detect(struct drm_connector *connector, bool force) | |||
| 1173 | if (!radeon_connector->dac_load_detect) | 1183 | if (!radeon_connector->dac_load_detect) |
| 1174 | return ret; | 1184 | return ret; |
| 1175 | 1185 | ||
| 1176 | r = pm_runtime_get_sync(connector->dev->dev); | 1186 | if (!drm_kms_helper_is_poll_worker()) { |
| 1177 | if (r < 0) | 1187 | r = pm_runtime_get_sync(connector->dev->dev); |
| 1178 | return connector_status_disconnected; | 1188 | if (r < 0) |
| 1189 | return connector_status_disconnected; | ||
| 1190 | } | ||
| 1179 | 1191 | ||
| 1180 | encoder = radeon_best_single_encoder(connector); | 1192 | encoder = radeon_best_single_encoder(connector); |
| 1181 | if (!encoder) | 1193 | if (!encoder) |
| @@ -1187,8 +1199,12 @@ radeon_tv_detect(struct drm_connector *connector, bool force) | |||
| 1187 | if (ret == connector_status_connected) | 1199 | if (ret == connector_status_connected) |
| 1188 | ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false); | 1200 | ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false); |
| 1189 | radeon_connector_update_scratch_regs(connector, ret); | 1201 | radeon_connector_update_scratch_regs(connector, ret); |
| 1190 | pm_runtime_mark_last_busy(connector->dev->dev); | 1202 | |
| 1191 | pm_runtime_put_autosuspend(connector->dev->dev); | 1203 | if (!drm_kms_helper_is_poll_worker()) { |
| 1204 | pm_runtime_mark_last_busy(connector->dev->dev); | ||
| 1205 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
| 1206 | } | ||
| 1207 | |||
| 1192 | return ret; | 1208 | return ret; |
| 1193 | } | 1209 | } |
| 1194 | 1210 | ||
| @@ -1251,9 +1267,11 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) | |||
| 1251 | enum drm_connector_status ret = connector_status_disconnected; | 1267 | enum drm_connector_status ret = connector_status_disconnected; |
| 1252 | bool dret = false, broken_edid = false; | 1268 | bool dret = false, broken_edid = false; |
| 1253 | 1269 | ||
| 1254 | r = pm_runtime_get_sync(connector->dev->dev); | 1270 | if (!drm_kms_helper_is_poll_worker()) { |
| 1255 | if (r < 0) | 1271 | r = pm_runtime_get_sync(connector->dev->dev); |
| 1256 | return connector_status_disconnected; | 1272 | if (r < 0) |
| 1273 | return connector_status_disconnected; | ||
| 1274 | } | ||
| 1257 | 1275 | ||
| 1258 | if (radeon_connector->detected_hpd_without_ddc) { | 1276 | if (radeon_connector->detected_hpd_without_ddc) { |
| 1259 | force = true; | 1277 | force = true; |
| @@ -1436,8 +1454,10 @@ out: | |||
| 1436 | } | 1454 | } |
| 1437 | 1455 | ||
| 1438 | exit: | 1456 | exit: |
| 1439 | pm_runtime_mark_last_busy(connector->dev->dev); | 1457 | if (!drm_kms_helper_is_poll_worker()) { |
| 1440 | pm_runtime_put_autosuspend(connector->dev->dev); | 1458 | pm_runtime_mark_last_busy(connector->dev->dev); |
| 1459 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
| 1460 | } | ||
| 1441 | 1461 | ||
| 1442 | return ret; | 1462 | return ret; |
| 1443 | } | 1463 | } |
| @@ -1688,9 +1708,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force) | |||
| 1688 | if (radeon_dig_connector->is_mst) | 1708 | if (radeon_dig_connector->is_mst) |
| 1689 | return connector_status_disconnected; | 1709 | return connector_status_disconnected; |
| 1690 | 1710 | ||
| 1691 | r = pm_runtime_get_sync(connector->dev->dev); | 1711 | if (!drm_kms_helper_is_poll_worker()) { |
| 1692 | if (r < 0) | 1712 | r = pm_runtime_get_sync(connector->dev->dev); |
| 1693 | return connector_status_disconnected; | 1713 | if (r < 0) |
| 1714 | return connector_status_disconnected; | ||
| 1715 | } | ||
| 1694 | 1716 | ||
| 1695 | if (!force && radeon_check_hpd_status_unchanged(connector)) { | 1717 | if (!force && radeon_check_hpd_status_unchanged(connector)) { |
| 1696 | ret = connector->status; | 1718 | ret = connector->status; |
| @@ -1777,8 +1799,10 @@ radeon_dp_detect(struct drm_connector *connector, bool force) | |||
| 1777 | } | 1799 | } |
| 1778 | 1800 | ||
| 1779 | out: | 1801 | out: |
| 1780 | pm_runtime_mark_last_busy(connector->dev->dev); | 1802 | if (!drm_kms_helper_is_poll_worker()) { |
| 1781 | pm_runtime_put_autosuspend(connector->dev->dev); | 1803 | pm_runtime_mark_last_busy(connector->dev->dev); |
| 1804 | pm_runtime_put_autosuspend(connector->dev->dev); | ||
| 1805 | } | ||
| 1782 | 1806 | ||
| 1783 | return ret; | 1807 | return ret; |
| 1784 | } | 1808 | } |
diff --git a/drivers/gpu/drm/scheduler/gpu_scheduler.c b/drivers/gpu/drm/scheduler/gpu_scheduler.c index 2c18996d59c5..0d95888ccc3e 100644 --- a/drivers/gpu/drm/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/scheduler/gpu_scheduler.c | |||
| @@ -461,7 +461,7 @@ void drm_sched_hw_job_reset(struct drm_gpu_scheduler *sched, struct drm_sched_jo | |||
| 461 | { | 461 | { |
| 462 | struct drm_sched_job *s_job; | 462 | struct drm_sched_job *s_job; |
| 463 | struct drm_sched_entity *entity, *tmp; | 463 | struct drm_sched_entity *entity, *tmp; |
| 464 | int i;; | 464 | int i; |
| 465 | 465 | ||
| 466 | spin_lock(&sched->job_list_lock); | 466 | spin_lock(&sched->job_list_lock); |
| 467 | list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) { | 467 | list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) { |
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 658fa2d3e40c..48685cddbad1 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c | |||
| @@ -1089,7 +1089,7 @@ static void ipu_irq_handler(struct irq_desc *desc) | |||
| 1089 | { | 1089 | { |
| 1090 | struct ipu_soc *ipu = irq_desc_get_handler_data(desc); | 1090 | struct ipu_soc *ipu = irq_desc_get_handler_data(desc); |
| 1091 | struct irq_chip *chip = irq_desc_get_chip(desc); | 1091 | struct irq_chip *chip = irq_desc_get_chip(desc); |
| 1092 | const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14}; | 1092 | static const int int_reg[] = { 0, 1, 2, 3, 10, 11, 12, 13, 14}; |
| 1093 | 1093 | ||
| 1094 | chained_irq_enter(chip, desc); | 1094 | chained_irq_enter(chip, desc); |
| 1095 | 1095 | ||
| @@ -1102,7 +1102,7 @@ static void ipu_err_irq_handler(struct irq_desc *desc) | |||
| 1102 | { | 1102 | { |
| 1103 | struct ipu_soc *ipu = irq_desc_get_handler_data(desc); | 1103 | struct ipu_soc *ipu = irq_desc_get_handler_data(desc); |
| 1104 | struct irq_chip *chip = irq_desc_get_chip(desc); | 1104 | struct irq_chip *chip = irq_desc_get_chip(desc); |
| 1105 | const int int_reg[] = { 4, 5, 8, 9}; | 1105 | static const int int_reg[] = { 4, 5, 8, 9}; |
| 1106 | 1106 | ||
| 1107 | chained_irq_enter(chip, desc); | 1107 | chained_irq_enter(chip, desc); |
| 1108 | 1108 | ||
diff --git a/drivers/gpu/ipu-v3/ipu-cpmem.c b/drivers/gpu/ipu-v3/ipu-cpmem.c index bb9c087e6c0d..9f2d9ec42add 100644 --- a/drivers/gpu/ipu-v3/ipu-cpmem.c +++ b/drivers/gpu/ipu-v3/ipu-cpmem.c | |||
| @@ -788,12 +788,14 @@ int ipu_cpmem_set_image(struct ipuv3_channel *ch, struct ipu_image *image) | |||
| 788 | case V4L2_PIX_FMT_SGBRG8: | 788 | case V4L2_PIX_FMT_SGBRG8: |
| 789 | case V4L2_PIX_FMT_SGRBG8: | 789 | case V4L2_PIX_FMT_SGRBG8: |
| 790 | case V4L2_PIX_FMT_SRGGB8: | 790 | case V4L2_PIX_FMT_SRGGB8: |
| 791 | case V4L2_PIX_FMT_GREY: | ||
| 791 | offset = image->rect.left + image->rect.top * pix->bytesperline; | 792 | offset = image->rect.left + image->rect.top * pix->bytesperline; |
| 792 | break; | 793 | break; |
| 793 | case V4L2_PIX_FMT_SBGGR16: | 794 | case V4L2_PIX_FMT_SBGGR16: |
| 794 | case V4L2_PIX_FMT_SGBRG16: | 795 | case V4L2_PIX_FMT_SGBRG16: |
| 795 | case V4L2_PIX_FMT_SGRBG16: | 796 | case V4L2_PIX_FMT_SGRBG16: |
| 796 | case V4L2_PIX_FMT_SRGGB16: | 797 | case V4L2_PIX_FMT_SRGGB16: |
| 798 | case V4L2_PIX_FMT_Y16: | ||
| 797 | offset = image->rect.left * 2 + | 799 | offset = image->rect.left * 2 + |
| 798 | image->rect.top * pix->bytesperline; | 800 | image->rect.top * pix->bytesperline; |
| 799 | break; | 801 | break; |
diff --git a/drivers/gpu/ipu-v3/ipu-csi.c b/drivers/gpu/ipu-v3/ipu-csi.c index 24e12b87a0cb..caa05b0702e1 100644 --- a/drivers/gpu/ipu-v3/ipu-csi.c +++ b/drivers/gpu/ipu-v3/ipu-csi.c | |||
| @@ -288,6 +288,7 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code) | |||
| 288 | case MEDIA_BUS_FMT_SGBRG10_1X10: | 288 | case MEDIA_BUS_FMT_SGBRG10_1X10: |
| 289 | case MEDIA_BUS_FMT_SGRBG10_1X10: | 289 | case MEDIA_BUS_FMT_SGRBG10_1X10: |
| 290 | case MEDIA_BUS_FMT_SRGGB10_1X10: | 290 | case MEDIA_BUS_FMT_SRGGB10_1X10: |
| 291 | case MEDIA_BUS_FMT_Y10_1X10: | ||
| 291 | cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; | 292 | cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; |
| 292 | cfg->mipi_dt = MIPI_DT_RAW10; | 293 | cfg->mipi_dt = MIPI_DT_RAW10; |
| 293 | cfg->data_width = IPU_CSI_DATA_WIDTH_10; | 294 | cfg->data_width = IPU_CSI_DATA_WIDTH_10; |
| @@ -296,6 +297,7 @@ static int mbus_code_to_bus_cfg(struct ipu_csi_bus_config *cfg, u32 mbus_code) | |||
| 296 | case MEDIA_BUS_FMT_SGBRG12_1X12: | 297 | case MEDIA_BUS_FMT_SGBRG12_1X12: |
| 297 | case MEDIA_BUS_FMT_SGRBG12_1X12: | 298 | case MEDIA_BUS_FMT_SGRBG12_1X12: |
| 298 | case MEDIA_BUS_FMT_SRGGB12_1X12: | 299 | case MEDIA_BUS_FMT_SRGGB12_1X12: |
| 300 | case MEDIA_BUS_FMT_Y12_1X12: | ||
| 299 | cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; | 301 | cfg->data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER; |
| 300 | cfg->mipi_dt = MIPI_DT_RAW12; | 302 | cfg->mipi_dt = MIPI_DT_RAW12; |
| 301 | cfg->data_width = IPU_CSI_DATA_WIDTH_12; | 303 | cfg->data_width = IPU_CSI_DATA_WIDTH_12; |
diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c index f1cec3d70498..0f70e8847540 100644 --- a/drivers/gpu/ipu-v3/ipu-pre.c +++ b/drivers/gpu/ipu-v3/ipu-pre.c | |||
| @@ -129,11 +129,14 @@ ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index) | |||
| 129 | if (pre_node == pre->dev->of_node) { | 129 | if (pre_node == pre->dev->of_node) { |
| 130 | mutex_unlock(&ipu_pre_list_mutex); | 130 | mutex_unlock(&ipu_pre_list_mutex); |
| 131 | device_link_add(dev, pre->dev, DL_FLAG_AUTOREMOVE); | 131 | device_link_add(dev, pre->dev, DL_FLAG_AUTOREMOVE); |
| 132 | of_node_put(pre_node); | ||
| 132 | return pre; | 133 | return pre; |
| 133 | } | 134 | } |
| 134 | } | 135 | } |
| 135 | mutex_unlock(&ipu_pre_list_mutex); | 136 | mutex_unlock(&ipu_pre_list_mutex); |
| 136 | 137 | ||
| 138 | of_node_put(pre_node); | ||
| 139 | |||
| 137 | return NULL; | 140 | return NULL; |
| 138 | } | 141 | } |
| 139 | 142 | ||
diff --git a/drivers/gpu/ipu-v3/ipu-prg.c b/drivers/gpu/ipu-v3/ipu-prg.c index 067365c733c6..97b99500153d 100644 --- a/drivers/gpu/ipu-v3/ipu-prg.c +++ b/drivers/gpu/ipu-v3/ipu-prg.c | |||
| @@ -102,11 +102,14 @@ ipu_prg_lookup_by_phandle(struct device *dev, const char *name, int ipu_id) | |||
| 102 | mutex_unlock(&ipu_prg_list_mutex); | 102 | mutex_unlock(&ipu_prg_list_mutex); |
| 103 | device_link_add(dev, prg->dev, DL_FLAG_AUTOREMOVE); | 103 | device_link_add(dev, prg->dev, DL_FLAG_AUTOREMOVE); |
| 104 | prg->id = ipu_id; | 104 | prg->id = ipu_id; |
| 105 | of_node_put(prg_node); | ||
| 105 | return prg; | 106 | return prg; |
| 106 | } | 107 | } |
| 107 | } | 108 | } |
| 108 | mutex_unlock(&ipu_prg_list_mutex); | 109 | mutex_unlock(&ipu_prg_list_mutex); |
| 109 | 110 | ||
| 111 | of_node_put(prg_node); | ||
| 112 | |||
| 110 | return NULL; | 113 | return NULL; |
| 111 | } | 114 | } |
| 112 | 115 | ||
