Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'drm-misc-fixes-2018-02-21' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes

Fixes for 4.16. I contains fixes for deadlock on runtime suspend on few
drivers, a memory leak on non-blocking commits, a crash on color-eviction.
The is also meson and edid fixes, plus a fix for a doc warning.

* tag 'drm-misc-fixes-2018-02-21' of git://anongit.freedesktop.org/drm/drm-misc:
drm/tve200: fix kernel-doc documentation comment include
drm/meson: fix vsync buffer update
drm: Handle unexpected holes in color-eviction
drm/edid: Add 6 bpc quirk for CPT panel in Asus UX303LA
drm/amdgpu: Fix deadlock on runtime suspend
drm/radeon: Fix deadlock on runtime suspend
drm/nouveau: Fix deadlock on runtime suspend
drm: Allow determining if current task is output poll worker
workqueue: Allow retrieval of current task's work struct
drm/atomic: Fix memleak on ERESTARTSYS during non-blocking commits

+196 -58
+1 -1
Documentation/gpu/tve200.rst
··· 3 3 ================================== 4 4 5 5 .. kernel-doc:: drivers/gpu/drm/tve200/tve200_drv.c 6 - :doc: Faraday TV Encoder 200 6 + :doc: Faraday TV Encoder TVE200 DRM Driver
+38 -20
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
··· 736 736 enum drm_connector_status ret = connector_status_disconnected; 737 737 int r; 738 738 739 - r = pm_runtime_get_sync(connector->dev->dev); 740 - if (r < 0) 741 - return connector_status_disconnected; 739 + if (!drm_kms_helper_is_poll_worker()) { 740 + r = pm_runtime_get_sync(connector->dev->dev); 741 + if (r < 0) 742 + return connector_status_disconnected; 743 + } 742 744 743 745 if (encoder) { 744 746 struct amdgpu_encoder *amdgpu_encoder = to_amdgpu_encoder(encoder); ··· 759 757 /* check acpi lid status ??? */ 760 758 761 759 amdgpu_connector_update_scratch_regs(connector, ret); 762 - pm_runtime_mark_last_busy(connector->dev->dev); 763 - pm_runtime_put_autosuspend(connector->dev->dev); 760 + 761 + if (!drm_kms_helper_is_poll_worker()) { 762 + pm_runtime_mark_last_busy(connector->dev->dev); 763 + pm_runtime_put_autosuspend(connector->dev->dev); 764 + } 765 + 764 766 return ret; 765 767 } 766 768 ··· 874 868 enum drm_connector_status ret = connector_status_disconnected; 875 869 int r; 876 870 877 - r = pm_runtime_get_sync(connector->dev->dev); 878 - if (r < 0) 879 - return connector_status_disconnected; 871 + if (!drm_kms_helper_is_poll_worker()) { 872 + r = pm_runtime_get_sync(connector->dev->dev); 873 + if (r < 0) 874 + return connector_status_disconnected; 875 + } 880 876 881 877 encoder = amdgpu_connector_best_single_encoder(connector); 882 878 if (!encoder) ··· 932 924 amdgpu_connector_update_scratch_regs(connector, ret); 933 925 934 926 out: 935 - pm_runtime_mark_last_busy(connector->dev->dev); 936 - pm_runtime_put_autosuspend(connector->dev->dev); 927 + if (!drm_kms_helper_is_poll_worker()) { 928 + pm_runtime_mark_last_busy(connector->dev->dev); 929 + pm_runtime_put_autosuspend(connector->dev->dev); 930 + } 937 931 938 932 return ret; 939 933 } ··· 998 988 enum drm_connector_status ret = connector_status_disconnected; 999 989 bool dret = false, broken_edid = false; 1000 990 1001 - r = pm_runtime_get_sync(connector->dev->dev); 1002 - if (r < 0) 1003 - return connector_status_disconnected; 991 + if (!drm_kms_helper_is_poll_worker()) { 992 + r = pm_runtime_get_sync(connector->dev->dev); 993 + if (r < 0) 994 + return connector_status_disconnected; 995 + } 1004 996 1005 997 if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) { 1006 998 ret = connector->status; ··· 1127 1115 amdgpu_connector_update_scratch_regs(connector, ret); 1128 1116 1129 1117 exit: 1130 - pm_runtime_mark_last_busy(connector->dev->dev); 1131 - pm_runtime_put_autosuspend(connector->dev->dev); 1118 + if (!drm_kms_helper_is_poll_worker()) { 1119 + pm_runtime_mark_last_busy(connector->dev->dev); 1120 + pm_runtime_put_autosuspend(connector->dev->dev); 1121 + } 1132 1122 1133 1123 return ret; 1134 1124 } ··· 1373 1359 struct drm_encoder *encoder = amdgpu_connector_best_single_encoder(connector); 1374 1360 int r; 1375 1361 1376 - r = pm_runtime_get_sync(connector->dev->dev); 1377 - if (r < 0) 1378 - return connector_status_disconnected; 1362 + if (!drm_kms_helper_is_poll_worker()) { 1363 + r = pm_runtime_get_sync(connector->dev->dev); 1364 + if (r < 0) 1365 + return connector_status_disconnected; 1366 + } 1379 1367 1380 1368 if (!force && amdgpu_connector_check_hpd_status_unchanged(connector)) { 1381 1369 ret = connector->status; ··· 1445 1429 1446 1430 amdgpu_connector_update_scratch_regs(connector, ret); 1447 1431 out: 1448 - pm_runtime_mark_last_busy(connector->dev->dev); 1449 - pm_runtime_put_autosuspend(connector->dev->dev); 1432 + if (!drm_kms_helper_is_poll_worker()) { 1433 + pm_runtime_mark_last_busy(connector->dev->dev); 1434 + pm_runtime_put_autosuspend(connector->dev->dev); 1435 + } 1450 1436 1451 1437 return ret; 1452 1438 }
+15
drivers/gpu/drm/drm_atomic_helper.c
··· 1878 1878 new_crtc_state->event->base.completion = &commit->flip_done; 1879 1879 new_crtc_state->event->base.completion_release = release_crtc_commit; 1880 1880 drm_crtc_commit_get(commit); 1881 + 1882 + commit->abort_completion = true; 1881 1883 } 1882 1884 1883 1885 for_each_oldnew_connector_in_state(state, conn, old_conn_state, new_conn_state, i) { ··· 3423 3421 void __drm_atomic_helper_crtc_destroy_state(struct drm_crtc_state *state) 3424 3422 { 3425 3423 if (state->commit) { 3424 + /* 3425 + * In the event that a non-blocking commit returns 3426 + * -ERESTARTSYS before the commit_tail work is queued, we will 3427 + * have an extra reference to the commit object. Release it, if 3428 + * the event has not been consumed by the worker. 3429 + * 3430 + * state->event may be freed, so we can't directly look at 3431 + * state->event->base.completion. 3432 + */ 3433 + if (state->event && state->commit->abort_completion) 3434 + drm_crtc_commit_put(state->commit); 3435 + 3426 3436 kfree(state->commit->event); 3427 3437 state->commit->event = NULL; 3438 + 3428 3439 drm_crtc_commit_put(state->commit); 3429 3440 } 3430 3441
+3
drivers/gpu/drm/drm_edid.c
··· 113 113 /* AEO model 0 reports 8 bpc, but is a 6 bpc panel */ 114 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 119 /* Belinea 10 15 55 */ 117 120 { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, 118 121 { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 },
+18 -3
drivers/gpu/drm/drm_mm.c
··· 836 836 if (!mm->color_adjust) 837 837 return NULL; 838 838 839 - hole = list_first_entry(&mm->hole_stack, typeof(*hole), hole_stack); 840 - hole_start = __drm_mm_hole_node_start(hole); 841 - hole_end = hole_start + hole->hole_size; 839 + /* 840 + * The hole found during scanning should ideally be the first element 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 858 DRM_MM_BUG_ON(hole_start > scan->hit_start); 844 859 DRM_MM_BUG_ON(hole_end < scan->hit_end);
+20
drivers/gpu/drm/drm_probe_helper.c
··· 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 677 * drm_kms_helper_poll_disable - disable output polling 658 678 * @dev: drm_device 659 679 *
+6
drivers/gpu/drm/meson/meson_crtc.c
··· 36 36 #include "meson_venc.h" 37 37 #include "meson_vpp.h" 38 38 #include "meson_viu.h" 39 + #include "meson_canvas.h" 39 40 #include "meson_registers.h" 40 41 41 42 /* CRTC definition */ ··· 192 191 meson_vpp_setup_interlace_vscaler_osd1(priv, &dest); 193 192 } else 194 193 meson_vpp_disable_interlace_vscaler_osd1(priv); 194 + 195 + meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1, 196 + priv->viu.osd1_addr, priv->viu.osd1_stride, 197 + priv->viu.osd1_height, MESON_CANVAS_WRAP_NONE, 198 + MESON_CANVAS_BLKMODE_LINEAR); 195 199 196 200 /* Enable OSD1 */ 197 201 writel_bits_relaxed(VPP_OSD1_POSTBLEND, VPP_OSD1_POSTBLEND,
+3
drivers/gpu/drm/meson/meson_drv.h
··· 43 43 bool osd1_commit; 44 44 uint32_t osd1_ctrl_stat; 45 45 uint32_t osd1_blk0_cfg[5]; 46 + uint32_t osd1_addr; 47 + uint32_t osd1_stride; 48 + uint32_t osd1_height; 46 49 } viu; 47 50 48 51 struct {
+3 -4
drivers/gpu/drm/meson/meson_plane.c
··· 164 164 /* Update Canvas with buffer address */ 165 165 gem = drm_fb_cma_get_gem_obj(fb, 0); 166 166 167 - meson_canvas_setup(priv, MESON_CANVAS_ID_OSD1, 168 - gem->paddr, fb->pitches[0], 169 - fb->height, MESON_CANVAS_WRAP_NONE, 170 - MESON_CANVAS_BLKMODE_LINEAR); 167 + priv->viu.osd1_addr = gem->paddr; 168 + priv->viu.osd1_stride = fb->pitches[0]; 169 + priv->viu.osd1_height = fb->height; 171 170 172 171 spin_unlock_irqrestore(&priv->drm->event_lock, flags); 173 172 }
+13 -5
drivers/gpu/drm/nouveau/nouveau_connector.c
··· 570 570 nv_connector->edid = NULL; 571 571 } 572 572 573 - ret = pm_runtime_get_sync(connector->dev->dev); 574 - if (ret < 0 && ret != -EACCES) 575 - return conn_status; 573 + /* Outputs are only polled while runtime active, so acquiring a 574 + * runtime PM ref here is unnecessary (and would deadlock upon 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 583 nv_encoder = nouveau_connector_ddc_detect(connector); 578 584 if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { ··· 653 647 654 648 out: 655 649 656 - pm_runtime_mark_last_busy(connector->dev->dev); 657 - pm_runtime_put_autosuspend(connector->dev->dev); 650 + if (!drm_kms_helper_is_poll_worker()) { 651 + pm_runtime_mark_last_busy(connector->dev->dev); 652 + pm_runtime_put_autosuspend(connector->dev->dev); 653 + } 658 654 659 655 return conn_status; 660 656 }
+49 -25
drivers/gpu/drm/radeon/radeon_connectors.c
··· 899 899 enum drm_connector_status ret = connector_status_disconnected; 900 900 int r; 901 901 902 - r = pm_runtime_get_sync(connector->dev->dev); 903 - if (r < 0) 904 - return connector_status_disconnected; 902 + if (!drm_kms_helper_is_poll_worker()) { 903 + r = pm_runtime_get_sync(connector->dev->dev); 904 + if (r < 0) 905 + return connector_status_disconnected; 906 + } 905 907 906 908 if (encoder) { 907 909 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); ··· 926 924 /* check acpi lid status ??? */ 927 925 928 926 radeon_connector_update_scratch_regs(connector, ret); 929 - pm_runtime_mark_last_busy(connector->dev->dev); 930 - pm_runtime_put_autosuspend(connector->dev->dev); 927 + 928 + if (!drm_kms_helper_is_poll_worker()) { 929 + pm_runtime_mark_last_busy(connector->dev->dev); 930 + pm_runtime_put_autosuspend(connector->dev->dev); 931 + } 932 + 931 933 return ret; 932 934 } 933 935 ··· 1045 1039 enum drm_connector_status ret = connector_status_disconnected; 1046 1040 int r; 1047 1041 1048 - r = pm_runtime_get_sync(connector->dev->dev); 1049 - if (r < 0) 1050 - return connector_status_disconnected; 1042 + if (!drm_kms_helper_is_poll_worker()) { 1043 + r = pm_runtime_get_sync(connector->dev->dev); 1044 + if (r < 0) 1045 + return connector_status_disconnected; 1046 + } 1051 1047 1052 1048 encoder = radeon_best_single_encoder(connector); 1053 1049 if (!encoder) ··· 1116 1108 radeon_connector_update_scratch_regs(connector, ret); 1117 1109 1118 1110 out: 1119 - pm_runtime_mark_last_busy(connector->dev->dev); 1120 - pm_runtime_put_autosuspend(connector->dev->dev); 1111 + if (!drm_kms_helper_is_poll_worker()) { 1112 + pm_runtime_mark_last_busy(connector->dev->dev); 1113 + pm_runtime_put_autosuspend(connector->dev->dev); 1114 + } 1121 1115 1122 1116 return ret; 1123 1117 } ··· 1183 1173 if (!radeon_connector->dac_load_detect) 1184 1174 return ret; 1185 1175 1186 - r = pm_runtime_get_sync(connector->dev->dev); 1187 - if (r < 0) 1188 - return connector_status_disconnected; 1176 + if (!drm_kms_helper_is_poll_worker()) { 1177 + r = pm_runtime_get_sync(connector->dev->dev); 1178 + if (r < 0) 1179 + return connector_status_disconnected; 1180 + } 1189 1181 1190 1182 encoder = radeon_best_single_encoder(connector); 1191 1183 if (!encoder) ··· 1199 1187 if (ret == connector_status_connected) 1200 1188 ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, false); 1201 1189 radeon_connector_update_scratch_regs(connector, ret); 1202 - pm_runtime_mark_last_busy(connector->dev->dev); 1203 - pm_runtime_put_autosuspend(connector->dev->dev); 1190 + 1191 + if (!drm_kms_helper_is_poll_worker()) { 1192 + pm_runtime_mark_last_busy(connector->dev->dev); 1193 + pm_runtime_put_autosuspend(connector->dev->dev); 1194 + } 1195 + 1204 1196 return ret; 1205 1197 } 1206 1198 ··· 1267 1251 enum drm_connector_status ret = connector_status_disconnected; 1268 1252 bool dret = false, broken_edid = false; 1269 1253 1270 - r = pm_runtime_get_sync(connector->dev->dev); 1271 - if (r < 0) 1272 - return connector_status_disconnected; 1254 + if (!drm_kms_helper_is_poll_worker()) { 1255 + r = pm_runtime_get_sync(connector->dev->dev); 1256 + if (r < 0) 1257 + return connector_status_disconnected; 1258 + } 1273 1259 1274 1260 if (radeon_connector->detected_hpd_without_ddc) { 1275 1261 force = true; ··· 1454 1436 } 1455 1437 1456 1438 exit: 1457 - pm_runtime_mark_last_busy(connector->dev->dev); 1458 - pm_runtime_put_autosuspend(connector->dev->dev); 1439 + if (!drm_kms_helper_is_poll_worker()) { 1440 + pm_runtime_mark_last_busy(connector->dev->dev); 1441 + pm_runtime_put_autosuspend(connector->dev->dev); 1442 + } 1459 1443 1460 1444 return ret; 1461 1445 } ··· 1708 1688 if (radeon_dig_connector->is_mst) 1709 1689 return connector_status_disconnected; 1710 1690 1711 - r = pm_runtime_get_sync(connector->dev->dev); 1712 - if (r < 0) 1713 - return connector_status_disconnected; 1691 + if (!drm_kms_helper_is_poll_worker()) { 1692 + r = pm_runtime_get_sync(connector->dev->dev); 1693 + if (r < 0) 1694 + return connector_status_disconnected; 1695 + } 1714 1696 1715 1697 if (!force && radeon_check_hpd_status_unchanged(connector)) { 1716 1698 ret = connector->status; ··· 1799 1777 } 1800 1778 1801 1779 out: 1802 - pm_runtime_mark_last_busy(connector->dev->dev); 1803 - pm_runtime_put_autosuspend(connector->dev->dev); 1780 + if (!drm_kms_helper_is_poll_worker()) { 1781 + pm_runtime_mark_last_busy(connector->dev->dev); 1782 + pm_runtime_put_autosuspend(connector->dev->dev); 1783 + } 1804 1784 1805 1785 return ret; 1806 1786 }
+9
include/drm/drm_atomic.h
··· 134 134 * &drm_pending_vblank_event pointer to clean up private events. 135 135 */ 136 136 struct drm_pending_vblank_event *event; 137 + 138 + /** 139 + * @abort_completion: 140 + * 141 + * A flag that's set after drm_atomic_helper_setup_commit takes a second 142 + * reference for the completion of $drm_crtc_state.event. It's used by 143 + * the free code to remove the second reference if commit fails. 144 + */ 145 + bool abort_completion; 137 146 }; 138 147 139 148 struct __drm_planes_state {
+1
include/drm/drm_crtc_helper.h
··· 77 77 78 78 void drm_kms_helper_poll_disable(struct drm_device *dev); 79 79 void drm_kms_helper_poll_enable(struct drm_device *dev); 80 + bool drm_kms_helper_is_poll_worker(void); 80 81 81 82 #endif
+1
include/linux/workqueue.h
··· 465 465 466 466 extern void workqueue_set_max_active(struct workqueue_struct *wq, 467 467 int max_active); 468 + extern struct work_struct *current_work(void); 468 469 extern bool current_is_workqueue_rescuer(void); 469 470 extern bool workqueue_congested(int cpu, struct workqueue_struct *wq); 470 471 extern unsigned int work_busy(struct work_struct *work);
+16
kernel/workqueue.c
··· 4180 4180 EXPORT_SYMBOL_GPL(workqueue_set_max_active); 4181 4181 4182 4182 /** 4183 + * current_work - retrieve %current task's work struct 4184 + * 4185 + * Determine if %current task is a workqueue worker and what it's working on. 4186 + * Useful to find out the context that the %current task is running in. 4187 + * 4188 + * Return: work struct if %current task is a workqueue worker, %NULL otherwise. 4189 + */ 4190 + struct work_struct *current_work(void) 4191 + { 4192 + struct worker *worker = current_wq_worker(); 4193 + 4194 + return worker ? worker->current_work : NULL; 4195 + } 4196 + EXPORT_SYMBOL(current_work); 4197 + 4198 + /** 4183 4199 * current_is_workqueue_rescuer - is %current workqueue rescuer? 4184 4200 * 4185 4201 * Determine whether %current is a workqueue rescuer. Can be used from