History

Merge tag 'drm-misc-next-2025-12-12' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next

drm-misc-next for 6.19: UAPI Changes: - panfrost: Add PANFROST_BO_SYNC ioctl - panthor: Add PANTHOR_BO_SYNC ioctl Core Changes: - atomic: Add drm_device pointer to drm_private_obj - bridge: Introduce drm_bridge_unplug, drm_bridge_enter, and drm_bridge_exit - dma-buf: Improve sg_table debugging - dma-fence: Add new helpers, and use them when needed - dp_mst: Avoid out-of-bounds access with VCPI==0 - gem: Reduce page table overhead with transparent huge pages - panic: Report invalid panic modes - sched: Add TODO entries - ttm: Various cleanups - vblank: Various refactoring and cleanups - Kconfig cleanups - Removed support for kdb Driver Changes: - amdxdna: Fix race conditions at suspend, Improve handling of zero tail pointers, Fix cu_idx being overwritten during command setup - ast: Support imported cursor buffers - - panthor: Enable timestamp propagation, Multiple improvements and fixes to improve the overall robustness, notably of the scheduler. - panels: - panel-edp: Support for CSW MNE007QB3-1, AUO B140HAN06.4, AUO B140QAX01.H Signed-off-by: Dave Airlie <airlied@redhat.com> [airlied: fix mm conflict] From: Maxime Ripard <mripard@redhat.com> Link: https://patch.msgid.link/20251212-spectacular-agama-of-abracadabra-aaef32@penduick

Dave Airlie committed 10 months ago

Commit 6c8e4042 parents 9448598 470cb09103 files · +2537 −1482Browse files

Unified · Split

103 files
  1. Documentation/gpu/drm-mm.rst +23 −6
  2. Documentation/gpu/todo.rst +45 −0
  3. Documentation/process/debugging/kgdb.rst +0 −28
  4. drivers/accel/amdxdna/aie2_message.c +12 −6
  5. drivers/accel/amdxdna/aie2_pci.c +1 −1
  6. drivers/accel/amdxdna/aie2_pci.h +3 −0
  7. drivers/accel/amdxdna/aie2_pm.c +16 −1
  8. drivers/accel/amdxdna/aie2_psp.c +15 −0
  9. drivers/accel/amdxdna/aie2_smu.c +4 −23
  10. drivers/accel/amdxdna/amdxdna_mailbox.c +1 −18
  11. drivers/accel/amdxdna/amdxdna_pci_drv.h +0 −1
  12. drivers/accel/amdxdna/amdxdna_pm.c +2 −20
  13. drivers/accel/amdxdna/npu1_regs.c +2 −0
  14. drivers/accel/amdxdna/npu2_regs.c +2 −0
  15. drivers/accel/amdxdna/npu4_regs.c +2 −0
  16. drivers/accel/amdxdna/npu5_regs.c +2 −0
  17. drivers/accel/amdxdna/npu6_regs.c +2 −0
  18. drivers/dma-buf/Kconfig +1 −1
  19. drivers/dma-buf/dma-buf.c +62 −17
  20. drivers/dma-buf/dma-fence.c +62 −38
  21. drivers/dma-buf/st-dma-fence.c +2 −2
  22. drivers/gpu/drm/Kconfig +59 −140
  23. drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +11 −24
  24. drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +11 −24
  25. drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +11 −24
  26. drivers/gpu/drm/amd/amdkfd/kfd_process.c +3 −3
  27. drivers/gpu/drm/ast/ast_cursor.c +62 −21
  28. drivers/gpu/drm/bridge/ti-sn65dsi83.c +66 −20
  29. drivers/gpu/drm/display/drm_dp_mst_topology.c +2 −1
  30. drivers/gpu/drm/drm_atomic.c +1 −0
  31. drivers/gpu/drm/drm_bridge.c +62 −0
  32. drivers/gpu/drm/drm_fb_helper.c +0 −108
  33. drivers/gpu/drm/drm_gem.c +155 −49
  34. drivers/gpu/drm/drm_gem_shmem_helper.c +41 −36
  35. drivers/gpu/drm/drm_panic.c +62 −13
  36. drivers/gpu/drm/drm_plane.c +2 −2
  37. drivers/gpu/drm/drm_vblank.c +21 −31
  38. drivers/gpu/drm/hyperv/Kconfig +14 −0
  39. drivers/gpu/drm/i915/Makefile +1 −2
  40. drivers/gpu/drm/i915/gem/i915_gem_object_types.h +6 −4
  41. drivers/gpu/drm/i915/gem/i915_gem_shmem.c +41 −17
  42. drivers/gpu/drm/i915/gem/i915_gemfs.c +0 −71
  43. drivers/gpu/drm/i915/gem/i915_gemfs.h +0 −14
  44. drivers/gpu/drm/i915/gem/selftests/huge_pages.c +3 −12
  45. drivers/gpu/drm/i915/i915_drv.h +0 −5
  46. drivers/gpu/drm/nouveau/dispnv04/crtc.c +4 −20
  47. drivers/gpu/drm/panel/panel-edp.c +3 −0
  48. drivers/gpu/drm/panfrost/panfrost_device.c +3 −0
  49. drivers/gpu/drm/panfrost/panfrost_device.h +1 −0
  50. drivers/gpu/drm/panfrost/panfrost_drv.c +104 −3
  51. drivers/gpu/drm/panfrost/panfrost_drv.h +9 −0
  52. drivers/gpu/drm/panfrost/panfrost_gem.c +257 −0
  53. drivers/gpu/drm/panfrost/panfrost_gem.h +12 −0
  54. drivers/gpu/drm/panfrost/panfrost_gpu.c +23 −3
  55. drivers/gpu/drm/panfrost/panfrost_regs.h +8 −2
  56. drivers/gpu/drm/panthor/panthor_device.c +12 −1
  57. drivers/gpu/drm/panthor/panthor_drv.c +84 −3
  58. drivers/gpu/drm/panthor/panthor_drv.h +9 −0
  59. drivers/gpu/drm/panthor/panthor_fw.c +2 −2
  60. drivers/gpu/drm/panthor/panthor_gem.c +255 −3
  61. drivers/gpu/drm/panthor/panthor_gem.h +8 −0
  62. drivers/gpu/drm/panthor/panthor_gpu.c +13 −8
  63. drivers/gpu/drm/panthor/panthor_mmu.c +183 −131
  64. drivers/gpu/drm/panthor/panthor_sched.c +129 −121
  65. drivers/gpu/drm/pl111/pl111_display.c +2 −2
  66. drivers/gpu/drm/pl111/pl111_drv.c +15 −14
  67. drivers/gpu/drm/pl111/pl111_nomadik.c +2 −2
  68. drivers/gpu/drm/pl111/pl111_nomadik.h +2 −2
  69. drivers/gpu/drm/pl111/pl111_versatile.c +27 −26
  70. drivers/gpu/drm/pl111/pl111_versatile.h +1 −1
  71. drivers/gpu/drm/radeon/atombios_crtc.c +19 −55
  72. drivers/gpu/drm/radeon/radeon_legacy_crtc.c +6 −17
  73. drivers/gpu/drm/radeon/radeon_mode.h +1 −9
  74. drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c +1 −1
  75. drivers/gpu/drm/ttm/ttm_bo.c +33 −31
  76. drivers/gpu/drm/ttm/ttm_bo_util.c +25 −32
  77. drivers/gpu/drm/ttm/ttm_bo_vm.c +5 −7
  78. drivers/gpu/drm/ttm/ttm_device.c +1 −4
  79. drivers/gpu/drm/ttm/ttm_pool.c +14 −12
  80. drivers/gpu/drm/ttm/ttm_resource.c +4 −10
  81. drivers/gpu/drm/ttm/ttm_tt.c +1 −1
  82. drivers/gpu/drm/v3d/Makefile +1 −2
  83. drivers/gpu/drm/v3d/v3d_bo.c +2 −4
  84. drivers/gpu/drm/v3d/v3d_drv.c +1 −1
  85. drivers/gpu/drm/v3d/v3d_drv.h +1 −10
  86. drivers/gpu/drm/v3d/v3d_gem.c +19 −2
  87. drivers/gpu/drm/v3d/v3d_gemfs.c +0 −62
  88. drivers/gpu/drm/vgem/Kconfig +9 −0
  89. drivers/gpu/drm/xe/xe_hw_fence.c +1 −3
  90. drivers/video/fbdev/core/fbcon.c +0 −24
  91. drivers/video/fbdev/core/fbcon.h +0 −1
  92. include/drm/drm_atomic.h +5 −0
  93. include/drm/drm_bridge.h +12 −0
  94. include/drm/drm_device.h +15 −0
  95. include/drm/drm_fb_helper.h +0 −21
  96. include/drm/drm_gem.h +42 −3
  97. include/drm/drm_gem_shmem_helper.h +0 −3
  98. include/drm/drm_modeset_helper_vtables.h +0 −23
  99. include/drm/drm_vblank.h +1 −2
  100. include/linux/dma-fence.h +28 −7
  101. include/linux/fb.h +0 −4
  102. include/uapi/drm/panfrost_drm.h +75 −1
  103. include/uapi/drm/panthor_drm.h +154 −3
Documentation/gpu/drm-mm.rst+23−6
@@ -155,7 +155,12 @@ drm_gem_object_init() will create an shmfs file of the · 154 unmodified lines
155requested size and store it into the struct :c:type:`struct155requested size and store it into the struct :c:type:`struct
156drm_gem_object <drm_gem_object>` filp field. The memory is156drm_gem_object <drm_gem_object>` filp field. The memory is
157used as either main storage for the object when the graphics hardware157used as either main storage for the object when the graphics hardware
158uses system memory directly or as a backing store otherwise.158uses system memory directly or as a backing store otherwise. Drivers
159can call drm_gem_huge_mnt_create() to create, mount and use a huge
160shmem mountpoint instead of the default one ('shm_mnt'). For builds
161with CONFIG_TRANSPARENT_HUGEPAGE enabled, further calls to
162drm_gem_object_init() will let shmem allocate huge pages when
163possible.
159 164
160Drivers are responsible for the actual physical pages allocation by165Drivers are responsible for the actual physical pages allocation by
161calling shmem_read_mapping_page_gfp() for each page.166calling shmem_read_mapping_page_gfp() for each page.
@@ -290,15 +295,27 @@ The open and close operations must update the GEM object reference · 128 unmodified lines
290count. Drivers can use the drm_gem_vm_open() and drm_gem_vm_close() helper295count. Drivers can use the drm_gem_vm_open() and drm_gem_vm_close() helper
291functions directly as open and close handlers.296functions directly as open and close handlers.
292 297
293The fault operation handler is responsible for mapping individual pages298The fault operation handler is responsible for mapping pages to
294to userspace when a page fault occurs. Depending on the memory299userspace when a page fault occurs. Depending on the memory allocation
295allocation scheme, drivers can allocate pages at fault time, or can300scheme, drivers can allocate pages at fault time, or can decide to
296decide to allocate memory for the GEM object at the time the object is301allocate memory for the GEM object at the time the object is created.
297created.
298 302
299Drivers that want to map the GEM object upfront instead of handling page303Drivers that want to map the GEM object upfront instead of handling page
300faults can implement their own mmap file operation handler.304faults can implement their own mmap file operation handler.
301 305
306In order to reduce page table overhead, if the internal shmem mountpoint
307"shm_mnt" is configured to use transparent huge pages (for builds with
308CONFIG_TRANSPARENT_HUGEPAGE enabled) and if the shmem backing store
309managed to allocate a huge page for a faulty address, the fault handler
310will first attempt to insert that huge page into the VMA before falling
311back to individual page insertion. mmap() user address alignment for GEM
312objects is handled by providing a custom get_unmapped_area file
313operation which forwards to the shmem backing store. For most drivers,
314which don't create a huge mountpoint by default or through a module
315parameter, transparent huge pages can be enabled by either setting the
316"transparent_hugepage_shmem" kernel parameter or the
317"/sys/kernel/mm/transparent_hugepage/shmem_enabled" sysfs knob.
318
302For platforms without MMU the GEM core provides a helper method319For platforms without MMU the GEM core provides a helper method
303drm_gem_dma_get_unmapped_area(). The mmap() routines will call this to get a320drm_gem_dma_get_unmapped_area(). The mmap() routines will call this to get a
304proposed address for the mapping.321proposed address for the mapping.
Documentation/gpu/todo.rst+45−0
@@ -878,6 +878,51 @@ Contact: Christian König · 877 unmodified lines
878 878
879Level: Starter879Level: Starter
880 880
881DRM GPU Scheduler
882=================
883
884Provide a universal successor for drm_sched_resubmit_jobs()
885-----------------------------------------------------------
886
887drm_sched_resubmit_jobs() is deprecated. Main reason being that it leads to
888reinitializing dma_fences. See that function's docu for details. The better
889approach for valid resubmissions by amdgpu and Xe is (apparently) to figure out
890which job (and, through association: which entity) caused the hang. Then, the
891job's buffer data, together with all other jobs' buffer data currently in the
892same hardware ring, must be invalidated. This can for example be done by
893overwriting it. amdgpu currently determines which jobs are in the ring and need
894to be overwritten by keeping copies of the job. Xe obtains that information by
895directly accessing drm_sched's pending_list.
896
897Tasks:
898
8991. implement scheduler functionality through which the driver can obtain the
900 information which *broken* jobs are currently in the hardware ring.
9012. Such infrastructure would then typically be used in
902 drm_sched_backend_ops.timedout_job(). Document that.
9033. Port a driver as first user.
9044. Document the new alternative in the docu of deprecated
905 drm_sched_resubmit_jobs().
906
907Contact: Christian König <christian.koenig@amd.com>
908 Philipp Stanner <phasta@kernel.org>
909
910Level: Advanced
911
912Add locking for runqueues
913-------------------------
914
915There is an old FIXME by Sima in include/drm/gpu_scheduler.h. It details that
916struct drm_sched_rq is read at many places without any locks, not even with a
917READ_ONCE. At XDC 2025 no one could really tell why that is the case, whether
918locks are needed and whether they could be added. (But for real, that should
919probably be locked!). Check whether it's possible to add locks everywhere, and
920do so if yes.
921
922Contact: Philipp Stanner <phasta@kernel.org>
923
924Level: Intermediate
925
881Outside DRM926Outside DRM
882===========927===========
883 928
Documentation/process/debugging/kgdb.rst+0−28
@@ -889,34 +889,6 @@ in the virtual console layer. On resuming kernel execution, the kernel · 888 unmodified lines
889debugger calls kgdboc_post_exp_handler() which in turn calls889debugger calls kgdboc_post_exp_handler() which in turn calls
890con_debug_leave().890con_debug_leave().
891 891
892Any video driver that wants to be compatible with the kernel debugger
893and the atomic kms callbacks must implement the ``mode_set_base_atomic``,
894``fb_debug_enter`` and ``fb_debug_leave operations``. For the
895``fb_debug_enter`` and ``fb_debug_leave`` the option exists to use the
896generic drm fb helper functions or implement something custom for the
897hardware. The following example shows the initialization of the
898.mode_set_base_atomic operation in
899drivers/gpu/drm/i915/intel_display.c::
900
901
902 static const struct drm_crtc_helper_funcs intel_helper_funcs = {
903 [...]
904 .mode_set_base_atomic = intel_pipe_set_base_atomic,
905 [...]
906 };
907
908
909Here is an example of how the i915 driver initializes the
910fb_debug_enter and fb_debug_leave functions to use the generic drm
911helpers in ``drivers/gpu/drm/i915/intel_fb.c``::
912
913
914 static struct fb_ops intelfb_ops = {
915 [...]
916 .fb_debug_enter = drm_fb_helper_debug_enter,
917 .fb_debug_leave = drm_fb_helper_debug_leave,
918 [...]
919 };
920 892
921 893
922Credits894Credits
drivers/accel/amdxdna/aie2_message.c+12−6
@@ -39,7 +39,6 @@ static int aie2_send_mgmt_msg_wait(struct amdxdna_dev_hdl *ndev, · 38 unmodified lines
39 if (!ndev->mgmt_chann)39 if (!ndev->mgmt_chann)
40 return -ENODEV;40 return -ENODEV;
41 41
42 drm_WARN_ON(&xdna->ddev, xdna->rpm_on && !mutex_is_locked(&xdna->dev_lock));
43 ret = xdna_send_msg_wait(xdna, ndev->mgmt_chann, msg);42 ret = xdna_send_msg_wait(xdna, ndev->mgmt_chann, msg);
44 if (ret == -ETIME) {43 if (ret == -ETIME) {
45 xdna_mailbox_stop_channel(ndev->mgmt_chann);44 xdna_mailbox_stop_channel(ndev->mgmt_chann);
@@ -59,8 +58,15 @@ static int aie2_send_mgmt_msg_wait(struct amdxdna_dev_hdl *ndev, · 13 unmodified lines
59int aie2_suspend_fw(struct amdxdna_dev_hdl *ndev)58int aie2_suspend_fw(struct amdxdna_dev_hdl *ndev)
60{59{
61 DECLARE_AIE2_MSG(suspend, MSG_OP_SUSPEND);60 DECLARE_AIE2_MSG(suspend, MSG_OP_SUSPEND);
61 int ret;
62 62
63 return aie2_send_mgmt_msg_wait(ndev, &msg);63 ret = aie2_send_mgmt_msg_wait(ndev, &msg);
64 if (ret) {
65 XDNA_ERR(ndev->xdna, "Failed to suspend fw, ret %d", ret);
66 return ret;
67 }
68
69 return aie2_psp_waitmode_poll(ndev->psp_hdl);
64}70}
65 71
66int aie2_resume_fw(struct amdxdna_dev_hdl *ndev)72int aie2_resume_fw(struct amdxdna_dev_hdl *ndev)
@@ -646,6 +652,7 @@ aie2_cmdlist_fill_npu_cf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *siz · 579 unmodified lines
646 u32 cmd_len;652 u32 cmd_len;
647 void *cmd;653 void *cmd;
648 654
655 memset(npu_slot, 0, sizeof(*npu_slot));
649 cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);656 cmd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
650 if (*size < sizeof(*npu_slot) + cmd_len)657 if (*size < sizeof(*npu_slot) + cmd_len)
651 return -EINVAL;658 return -EINVAL;
@@ -654,7 +661,6 @@ aie2_cmdlist_fill_npu_cf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *siz · 2 unmodified lines
654 if (npu_slot->cu_idx == INVALID_CU_IDX)661 if (npu_slot->cu_idx == INVALID_CU_IDX)
655 return -EINVAL;662 return -EINVAL;
656 663
657 memset(npu_slot, 0, sizeof(*npu_slot));
658 npu_slot->type = EXEC_NPU_TYPE_NON_ELF;664 npu_slot->type = EXEC_NPU_TYPE_NON_ELF;
659 npu_slot->arg_cnt = cmd_len / sizeof(u32);665 npu_slot->arg_cnt = cmd_len / sizeof(u32);
660 memcpy(npu_slot->args, cmd, cmd_len);666 memcpy(npu_slot->args, cmd, cmd_len);
@@ -671,6 +677,7 @@ aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si · 10 unmodified lines
671 u32 cmd_len;677 u32 cmd_len;
672 u32 arg_sz;678 u32 arg_sz;
673 679
680 memset(npu_slot, 0, sizeof(*npu_slot));
674 sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);681 sn = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
675 arg_sz = cmd_len - sizeof(*sn);682 arg_sz = cmd_len - sizeof(*sn);
676 if (cmd_len < sizeof(*sn) || arg_sz > MAX_NPU_ARGS_SIZE)683 if (cmd_len < sizeof(*sn) || arg_sz > MAX_NPU_ARGS_SIZE)
@@ -683,7 +690,6 @@ aie2_cmdlist_fill_npu_dpu(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si · 6 unmodified lines
683 if (npu_slot->cu_idx == INVALID_CU_IDX)690 if (npu_slot->cu_idx == INVALID_CU_IDX)
684 return -EINVAL;691 return -EINVAL;
685 692
686 memset(npu_slot, 0, sizeof(*npu_slot));
687 npu_slot->type = EXEC_NPU_TYPE_PARTIAL_ELF;693 npu_slot->type = EXEC_NPU_TYPE_PARTIAL_ELF;
688 npu_slot->inst_buf_addr = sn->buffer;694 npu_slot->inst_buf_addr = sn->buffer;
689 npu_slot->inst_size = sn->buffer_size;695 npu_slot->inst_size = sn->buffer_size;
@@ -703,6 +709,7 @@ aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t · 13 unmodified lines
703 u32 cmd_len;709 u32 cmd_len;
704 u32 arg_sz;710 u32 arg_sz;
705 711
712 memset(npu_slot, 0, sizeof(*npu_slot));
706 pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);713 pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
707 arg_sz = cmd_len - sizeof(*pd);714 arg_sz = cmd_len - sizeof(*pd);
708 if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)715 if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
@@ -715,7 +722,6 @@ aie2_cmdlist_fill_npu_preempt(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t · 6 unmodified lines
715 if (npu_slot->cu_idx == INVALID_CU_IDX)722 if (npu_slot->cu_idx == INVALID_CU_IDX)
716 return -EINVAL;723 return -EINVAL;
717 724
718 memset(npu_slot, 0, sizeof(*npu_slot));
719 npu_slot->type = EXEC_NPU_TYPE_PREEMPT;725 npu_slot->type = EXEC_NPU_TYPE_PREEMPT;
720 npu_slot->inst_buf_addr = pd->inst_buf;726 npu_slot->inst_buf_addr = pd->inst_buf;
721 npu_slot->save_buf_addr = pd->save_buf;727 npu_slot->save_buf_addr = pd->save_buf;
@@ -739,6 +745,7 @@ aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si · 17 unmodified lines
739 u32 cmd_len;745 u32 cmd_len;
740 u32 arg_sz;746 u32 arg_sz;
741 747
748 memset(npu_slot, 0, sizeof(*npu_slot));
742 pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);749 pd = amdxdna_cmd_get_payload(cmd_bo, &cmd_len);
743 arg_sz = cmd_len - sizeof(*pd);750 arg_sz = cmd_len - sizeof(*pd);
744 if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)751 if (cmd_len < sizeof(*pd) || arg_sz > MAX_NPU_ARGS_SIZE)
@@ -747,7 +754,6 @@ aie2_cmdlist_fill_npu_elf(struct amdxdna_gem_obj *cmd_bo, void *slot, size_t *si · 2 unmodified lines
747 if (*size < sizeof(*npu_slot) + arg_sz)754 if (*size < sizeof(*npu_slot) + arg_sz)
748 return -EINVAL;755 return -EINVAL;
749 756
750 memset(npu_slot, 0, sizeof(*npu_slot));
751 npu_slot->type = EXEC_NPU_TYPE_ELF;757 npu_slot->type = EXEC_NPU_TYPE_ELF;
752 npu_slot->inst_buf_addr = pd->inst_buf;758 npu_slot->inst_buf_addr = pd->inst_buf;
753 npu_slot->save_buf_addr = pd->save_buf;759 npu_slot->save_buf_addr = pd->save_buf;
drivers/accel/amdxdna/aie2_pci.c+1−1
@@ -322,7 +322,7 @@ static int aie2_xrs_set_dft_dpm_level(struct drm_device *ddev, u32 dpm_level) · 321 unmodified lines
322 if (ndev->pw_mode != POWER_MODE_DEFAULT || ndev->dpm_level == dpm_level)322 if (ndev->pw_mode != POWER_MODE_DEFAULT || ndev->dpm_level == dpm_level)
323 return 0;323 return 0;
324 324
325 return ndev->priv->hw_ops.set_dpm(ndev, dpm_level);325 return aie2_pm_set_dpm(ndev, dpm_level);
326}326}
327 327
328static struct xrs_action_ops aie2_xrs_actions = {328static struct xrs_action_ops aie2_xrs_actions = {
drivers/accel/amdxdna/aie2_pci.h+3−0
@@ -70,6 +70,7 @@ enum psp_reg_idx { · 69 unmodified lines
70 PSP_INTR_REG = PSP_NUM_IN_REGS,70 PSP_INTR_REG = PSP_NUM_IN_REGS,
71 PSP_STATUS_REG,71 PSP_STATUS_REG,
72 PSP_RESP_REG,72 PSP_RESP_REG,
73 PSP_PWAITMODE_REG,
73 PSP_MAX_REGS /* Keep this at the end */74 PSP_MAX_REGS /* Keep this at the end */
74};75};
75 76
@@ -285,11 +286,13 @@ int npu4_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level); · 209 unmodified lines
285/* aie2_pm.c */286/* aie2_pm.c */
286int aie2_pm_init(struct amdxdna_dev_hdl *ndev);287int aie2_pm_init(struct amdxdna_dev_hdl *ndev);
287int aie2_pm_set_mode(struct amdxdna_dev_hdl *ndev, enum amdxdna_power_mode_type target);288int aie2_pm_set_mode(struct amdxdna_dev_hdl *ndev, enum amdxdna_power_mode_type target);
289int aie2_pm_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level);
288 290
289/* aie2_psp.c */291/* aie2_psp.c */
290struct psp_device *aie2m_psp_create(struct drm_device *ddev, struct psp_config *conf);292struct psp_device *aie2m_psp_create(struct drm_device *ddev, struct psp_config *conf);
291int aie2_psp_start(struct psp_device *psp);293int aie2_psp_start(struct psp_device *psp);
292void aie2_psp_stop(struct psp_device *psp);294void aie2_psp_stop(struct psp_device *psp);
295int aie2_psp_waitmode_poll(struct psp_device *psp);
293 296
294/* aie2_error.c */297/* aie2_error.c */
295int aie2_error_async_events_alloc(struct amdxdna_dev_hdl *ndev);298int aie2_error_async_events_alloc(struct amdxdna_dev_hdl *ndev);
drivers/accel/amdxdna/aie2_pm.c+16−1
@@ -10,6 +10,7 @@ · 9 unmodified lines
10 10
11#include "aie2_pci.h"11#include "aie2_pci.h"
12#include "amdxdna_pci_drv.h"12#include "amdxdna_pci_drv.h"
13#include "amdxdna_pm.h"
13 14
14#define AIE2_CLK_GATING_ENABLE 115#define AIE2_CLK_GATING_ENABLE 1
15#define AIE2_CLK_GATING_DISABLE 016#define AIE2_CLK_GATING_DISABLE 0
@@ -26,6 +27,20 @@ static int aie2_pm_set_clk_gating(struct amdxdna_dev_hdl *ndev, u32 val) · 10 unmodified lines
26 return 0;27 return 0;
27}28}
28 29
30int aie2_pm_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
31{
32 int ret;
33
34 ret = amdxdna_pm_resume_get(ndev->xdna);
35 if (ret)
36 return ret;
37
38 ret = ndev->priv->hw_ops.set_dpm(ndev, dpm_level);
39 amdxdna_pm_suspend_put(ndev->xdna);
40
41 return ret;
42}
43
29int aie2_pm_init(struct amdxdna_dev_hdl *ndev)44int aie2_pm_init(struct amdxdna_dev_hdl *ndev)
30{45{
31 int ret;46 int ret;
@@ -94,7 +109,7 @@ int aie2_pm_set_mode(struct amdxdna_dev_hdl *ndev, enum amdxdna_power_mode_type · 62 unmodified lines
94 return -EOPNOTSUPP;109 return -EOPNOTSUPP;
95 }110 }
96 111
97 ret = ndev->priv->hw_ops.set_dpm(ndev, dpm_level);112 ret = aie2_pm_set_dpm(ndev, dpm_level);
98 if (ret)113 if (ret)
99 return ret;114 return ret;
100 115
drivers/accel/amdxdna/aie2_psp.c+15−0
@@ -76,6 +76,21 @@ static int psp_exec(struct psp_device *psp, u32 *reg_vals) · 75 unmodified lines
76 return 0;76 return 0;
77}77}
78 78
79int aie2_psp_waitmode_poll(struct psp_device *psp)
80{
81 struct amdxdna_dev *xdna = to_xdna_dev(psp->ddev);
82 u32 mode_reg;
83 int ret;
84
85 ret = readx_poll_timeout(readl, PSP_REG(psp, PSP_PWAITMODE_REG), mode_reg,
86 (mode_reg & 0x1) == 1,
87 PSP_POLL_INTERVAL, PSP_POLL_TIMEOUT);
88 if (ret)
89 XDNA_ERR(xdna, "fw waitmode reg error, ret %d", ret);
90
91 return ret;
92}
93
79void aie2_psp_stop(struct psp_device *psp)94void aie2_psp_stop(struct psp_device *psp)
80{95{
81 u32 reg_vals[PSP_NUM_IN_REGS] = { PSP_RELEASE_TMR, };96 u32 reg_vals[PSP_NUM_IN_REGS] = { PSP_RELEASE_TMR, };
drivers/accel/amdxdna/aie2_smu.c+4−23
@@ -11,7 +11,6 @@ · 10 unmodified lines
11 11
12#include "aie2_pci.h"12#include "aie2_pci.h"
13#include "amdxdna_pci_drv.h"13#include "amdxdna_pci_drv.h"
14#include "amdxdna_pm.h"
15 14
16#define SMU_RESULT_OK 115#define SMU_RESULT_OK 1
17 16
@@ -67,16 +66,12 @@ int npu1_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level) · 49 unmodified lines
67 u32 freq;66 u32 freq;
68 int ret;67 int ret;
69 68
70 ret = amdxdna_pm_resume_get(ndev->xdna);
71 if (ret)
72 return ret;
73
74 ret = aie2_smu_exec(ndev, AIE2_SMU_SET_MPNPUCLK_FREQ,69 ret = aie2_smu_exec(ndev, AIE2_SMU_SET_MPNPUCLK_FREQ,
75 ndev->priv->dpm_clk_tbl[dpm_level].npuclk, &freq);70 ndev->priv->dpm_clk_tbl[dpm_level].npuclk, &freq);
76 if (ret) {71 if (ret) {
77 XDNA_ERR(ndev->xdna, "Set npu clock to %d failed, ret %d\n",72 XDNA_ERR(ndev->xdna, "Set npu clock to %d failed, ret %d\n",
78 ndev->priv->dpm_clk_tbl[dpm_level].npuclk, ret);73 ndev->priv->dpm_clk_tbl[dpm_level].npuclk, ret);
79 goto suspend_put;74 return ret;
80 }75 }
81 ndev->npuclk_freq = freq;76 ndev->npuclk_freq = freq;
82 77
@@ -85,10 +80,9 @@ int npu1_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level) · 2 unmodified lines
85 if (ret) {80 if (ret) {
86 XDNA_ERR(ndev->xdna, "Set h clock to %d failed, ret %d\n",81 XDNA_ERR(ndev->xdna, "Set h clock to %d failed, ret %d\n",
87 ndev->priv->dpm_clk_tbl[dpm_level].hclk, ret);82 ndev->priv->dpm_clk_tbl[dpm_level].hclk, ret);
88 goto suspend_put;83 return ret;
89 }84 }
90 85
91 amdxdna_pm_suspend_put(ndev->xdna);
92 ndev->hclk_freq = freq;86 ndev->hclk_freq = freq;
93 ndev->dpm_level = dpm_level;87 ndev->dpm_level = dpm_level;
94 ndev->max_tops = 2 * ndev->total_col;88 ndev->max_tops = 2 * ndev->total_col;
@@ -98,35 +92,26 @@ int npu1_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level) · 3 unmodified lines
98 ndev->npuclk_freq, ndev->hclk_freq);92 ndev->npuclk_freq, ndev->hclk_freq);
99 93
100 return 0;94 return 0;
101
102suspend_put:
103 amdxdna_pm_suspend_put(ndev->xdna);
104 return ret;
105}95}
106 96
107int npu4_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)97int npu4_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level)
108{98{
109 int ret;99 int ret;
110 100
111 ret = amdxdna_pm_resume_get(ndev->xdna);
112 if (ret)
113 return ret;
114
115 ret = aie2_smu_exec(ndev, AIE2_SMU_SET_HARD_DPMLEVEL, dpm_level, NULL);101 ret = aie2_smu_exec(ndev, AIE2_SMU_SET_HARD_DPMLEVEL, dpm_level, NULL);
116 if (ret) {102 if (ret) {
117 XDNA_ERR(ndev->xdna, "Set hard dpm level %d failed, ret %d ",103 XDNA_ERR(ndev->xdna, "Set hard dpm level %d failed, ret %d ",
118 dpm_level, ret);104 dpm_level, ret);
119 goto suspend_put;105 return ret;
120 }106 }
121 107
122 ret = aie2_smu_exec(ndev, AIE2_SMU_SET_SOFT_DPMLEVEL, dpm_level, NULL);108 ret = aie2_smu_exec(ndev, AIE2_SMU_SET_SOFT_DPMLEVEL, dpm_level, NULL);
123 if (ret) {109 if (ret) {
124 XDNA_ERR(ndev->xdna, "Set soft dpm level %d failed, ret %d",110 XDNA_ERR(ndev->xdna, "Set soft dpm level %d failed, ret %d",
125 dpm_level, ret);111 dpm_level, ret);
126 goto suspend_put;112 return ret;
127 }113 }
128 114
129 amdxdna_pm_suspend_put(ndev->xdna);
130 ndev->npuclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].npuclk;115 ndev->npuclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].npuclk;
131 ndev->hclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].hclk;116 ndev->hclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].hclk;
132 ndev->dpm_level = dpm_level;117 ndev->dpm_level = dpm_level;
@@ -137,10 +122,6 @@ int npu4_set_dpm(struct amdxdna_dev_hdl *ndev, u32 dpm_level) · 4 unmodified lines
137 ndev->npuclk_freq, ndev->hclk_freq);122 ndev->npuclk_freq, ndev->hclk_freq);
138 123
139 return 0;124 return 0;
140
141suspend_put:
142 amdxdna_pm_suspend_put(ndev->xdna);
143 return ret;
144}125}
145 126
146int aie2_smu_init(struct amdxdna_dev_hdl *ndev)127int aie2_smu_init(struct amdxdna_dev_hdl *ndev)
drivers/accel/amdxdna/amdxdna_mailbox.c+1−18
@@ -112,22 +112,6 @@ static u32 mailbox_reg_read(struct mailbox_channel *mb_chann, u32 mbox_reg) · 111 unmodified lines
112 return readl(ringbuf_addr);112 return readl(ringbuf_addr);
113}113}
114 114
115static int mailbox_reg_read_non_zero(struct mailbox_channel *mb_chann, u32 mbox_reg, u32 *val)
116{
117 struct xdna_mailbox_res *mb_res = &mb_chann->mb->res;
118 void __iomem *ringbuf_addr = mb_res->mbox_base + mbox_reg;
119 int ret, value;
120
121 /* Poll till value is not zero */
122 ret = readx_poll_timeout(readl, ringbuf_addr, value,
123 value, 1 /* us */, 100);
124 if (ret < 0)
125 return ret;
126
127 *val = value;
128 return 0;
129}
130
131static inline void115static inline void
132mailbox_set_headptr(struct mailbox_channel *mb_chann, u32 headptr_val)116mailbox_set_headptr(struct mailbox_channel *mb_chann, u32 headptr_val)
133{117{
@@ -286,8 +270,7 @@ static int mailbox_get_msg(struct mailbox_channel *mb_chann) · 152 unmodified lines
286 u32 start_addr;270 u32 start_addr;
287 int ret;271 int ret;
288 272
289 if (mailbox_reg_read_non_zero(mb_chann, mb_chann->res[CHAN_RES_I2X].mb_tail_ptr_reg, &tail))273 tail = mailbox_get_tailptr(mb_chann, CHAN_RES_I2X);
290 return -EINVAL;
291 head = mb_chann->i2x_head;274 head = mb_chann->i2x_head;
292 ringbuf_size = mailbox_get_ringbuf_size(mb_chann, CHAN_RES_I2X);275 ringbuf_size = mailbox_get_ringbuf_size(mb_chann, CHAN_RES_I2X);
293 start_addr = mb_chann->res[CHAN_RES_I2X].rb_start_addr;276 start_addr = mb_chann->res[CHAN_RES_I2X].rb_start_addr;
drivers/accel/amdxdna/amdxdna_pci_drv.h+0−1
@@ -101,7 +101,6 @@ struct amdxdna_dev { · 100 unmodified lines
101 struct amdxdna_fw_ver fw_ver;101 struct amdxdna_fw_ver fw_ver;
102 struct rw_semaphore notifier_lock; /* for mmu notifier*/102 struct rw_semaphore notifier_lock; /* for mmu notifier*/
103 struct workqueue_struct *notifier_wq;103 struct workqueue_struct *notifier_wq;
104 bool rpm_on;
105};104};
106 105
107/*106/*
drivers/accel/amdxdna/amdxdna_pm.c+2−20
@@ -15,14 +15,9 @@ int amdxdna_pm_suspend(struct device *dev) · 14 unmodified lines
15{15{
16 struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));16 struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
17 int ret = -EOPNOTSUPP;17 int ret = -EOPNOTSUPP;
18 bool rpm;
19 18
20 if (xdna->dev_info->ops->suspend) {19 if (xdna->dev_info->ops->suspend)
21 rpm = xdna->rpm_on;
22 xdna->rpm_on = false;
23 ret = xdna->dev_info->ops->suspend(xdna);20 ret = xdna->dev_info->ops->suspend(xdna);
24 xdna->rpm_on = rpm;
25 }
26 21
27 XDNA_DBG(xdna, "Suspend done ret %d", ret);22 XDNA_DBG(xdna, "Suspend done ret %d", ret);
28 return ret;23 return ret;
@@ -32,14 +27,9 @@ int amdxdna_pm_resume(struct device *dev) · 3 unmodified lines
32{27{
33 struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));28 struct amdxdna_dev *xdna = to_xdna_dev(dev_get_drvdata(dev));
34 int ret = -EOPNOTSUPP;29 int ret = -EOPNOTSUPP;
35 bool rpm;
36 30
37 if (xdna->dev_info->ops->resume) {31 if (xdna->dev_info->ops->resume)
38 rpm = xdna->rpm_on;
39 xdna->rpm_on = false;
40 ret = xdna->dev_info->ops->resume(xdna);32 ret = xdna->dev_info->ops->resume(xdna);
41 xdna->rpm_on = rpm;
42 }
43 33
44 XDNA_DBG(xdna, "Resume done ret %d", ret);34 XDNA_DBG(xdna, "Resume done ret %d", ret);
45 return ret;35 return ret;
@@ -50,9 +40,6 @@ int amdxdna_pm_resume_get(struct amdxdna_dev *xdna) · 4 unmodified lines
50 struct device *dev = xdna->ddev.dev;40 struct device *dev = xdna->ddev.dev;
51 int ret;41 int ret;
52 42
53 if (!xdna->rpm_on)
54 return 0;
55
56 ret = pm_runtime_resume_and_get(dev);43 ret = pm_runtime_resume_and_get(dev);
57 if (ret) {44 if (ret) {
58 XDNA_ERR(xdna, "Resume failed: %d", ret);45 XDNA_ERR(xdna, "Resume failed: %d", ret);
@@ -66,9 +53,6 @@ void amdxdna_pm_suspend_put(struct amdxdna_dev *xdna) · 7 unmodified lines
66{53{
67 struct device *dev = xdna->ddev.dev;54 struct device *dev = xdna->ddev.dev;
68 55
69 if (!xdna->rpm_on)
70 return;
71
72 pm_runtime_put_autosuspend(dev);56 pm_runtime_put_autosuspend(dev);
73}57}
74 58
@@ -81,14 +65,12 @@ void amdxdna_pm_init(struct amdxdna_dev *xdna) · 6 unmodified lines
81 pm_runtime_use_autosuspend(dev);65 pm_runtime_use_autosuspend(dev);
82 pm_runtime_allow(dev);66 pm_runtime_allow(dev);
83 pm_runtime_put_autosuspend(dev);67 pm_runtime_put_autosuspend(dev);
84 xdna->rpm_on = true;
85}68}
86 69
87void amdxdna_pm_fini(struct amdxdna_dev *xdna)70void amdxdna_pm_fini(struct amdxdna_dev *xdna)
88{71{
89 struct device *dev = xdna->ddev.dev;72 struct device *dev = xdna->ddev.dev;
90 73
91 xdna->rpm_on = false;
92 pm_runtime_get_noresume(dev);74 pm_runtime_get_noresume(dev);
93 pm_runtime_forbid(dev);75 pm_runtime_forbid(dev);
94}76}
drivers/accel/amdxdna/npu1_regs.c+2−0
@@ -13,6 +13,7 @@ · 12 unmodified lines
13#include "amdxdna_pci_drv.h"13#include "amdxdna_pci_drv.h"
14 14
15/* Address definition from NPU1 docs */15/* Address definition from NPU1 docs */
16#define MPNPU_PWAITMODE 0x3010034
16#define MPNPU_PUB_SEC_INTR 0x301009017#define MPNPU_PUB_SEC_INTR 0x3010090
17#define MPNPU_PUB_PWRMGMT_INTR 0x301009418#define MPNPU_PUB_PWRMGMT_INTR 0x3010094
18#define MPNPU_PUB_SCRATCH2 0x30100A019#define MPNPU_PUB_SCRATCH2 0x30100A0
@@ -92,6 +93,7 @@ static const struct amdxdna_dev_priv npu1_dev_priv = { · 73 unmodified lines
92 DEFINE_BAR_OFFSET(PSP_INTR_REG, NPU1_PSP, MPNPU_PUB_SEC_INTR),93 DEFINE_BAR_OFFSET(PSP_INTR_REG, NPU1_PSP, MPNPU_PUB_SEC_INTR),
93 DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU1_PSP, MPNPU_PUB_SCRATCH2),94 DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU1_PSP, MPNPU_PUB_SCRATCH2),
94 DEFINE_BAR_OFFSET(PSP_RESP_REG, NPU1_PSP, MPNPU_PUB_SCRATCH3),95 DEFINE_BAR_OFFSET(PSP_RESP_REG, NPU1_PSP, MPNPU_PUB_SCRATCH3),
96 DEFINE_BAR_OFFSET(PSP_PWAITMODE_REG, NPU1_PSP, MPNPU_PWAITMODE),
95 },97 },
96 .smu_regs_off = {98 .smu_regs_off = {
97 DEFINE_BAR_OFFSET(SMU_CMD_REG, NPU1_SMU, MPNPU_PUB_SCRATCH5),99 DEFINE_BAR_OFFSET(SMU_CMD_REG, NPU1_SMU, MPNPU_PUB_SCRATCH5),
drivers/accel/amdxdna/npu2_regs.c+2−0
@@ -13,6 +13,7 @@ · 12 unmodified lines
13#include "amdxdna_pci_drv.h"13#include "amdxdna_pci_drv.h"
14 14
15/* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */15/* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */
16#define MPNPU_PWAITMODE 0x301003C
16#define MPNPU_PUB_SEC_INTR 0x301006017#define MPNPU_PUB_SEC_INTR 0x3010060
17#define MPNPU_PUB_PWRMGMT_INTR 0x301006418#define MPNPU_PUB_PWRMGMT_INTR 0x3010064
18#define MPNPU_PUB_SCRATCH0 0x301006C19#define MPNPU_PUB_SCRATCH0 0x301006C
@@ -85,6 +86,7 @@ static const struct amdxdna_dev_priv npu2_dev_priv = { · 66 unmodified lines
85 DEFINE_BAR_OFFSET(PSP_INTR_REG, NPU2_PSP, MP0_C2PMSG_73),86 DEFINE_BAR_OFFSET(PSP_INTR_REG, NPU2_PSP, MP0_C2PMSG_73),
86 DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU2_PSP, MP0_C2PMSG_123),87 DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU2_PSP, MP0_C2PMSG_123),
87 DEFINE_BAR_OFFSET(PSP_RESP_REG, NPU2_REG, MPNPU_PUB_SCRATCH3),88 DEFINE_BAR_OFFSET(PSP_RESP_REG, NPU2_REG, MPNPU_PUB_SCRATCH3),
89 DEFINE_BAR_OFFSET(PSP_PWAITMODE_REG, NPU2_REG, MPNPU_PWAITMODE),
88 },90 },
89 .smu_regs_off = {91 .smu_regs_off = {
90 DEFINE_BAR_OFFSET(SMU_CMD_REG, NPU2_SMU, MP1_C2PMSG_0),92 DEFINE_BAR_OFFSET(SMU_CMD_REG, NPU2_SMU, MP1_C2PMSG_0),
drivers/accel/amdxdna/npu4_regs.c+2−0
@@ -13,6 +13,7 @@ · 12 unmodified lines
13#include "amdxdna_pci_drv.h"13#include "amdxdna_pci_drv.h"
14 14
15/* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */15/* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */
16#define MPNPU_PWAITMODE 0x301003C
16#define MPNPU_PUB_SEC_INTR 0x301006017#define MPNPU_PUB_SEC_INTR 0x3010060
17#define MPNPU_PUB_PWRMGMT_INTR 0x301006418#define MPNPU_PUB_PWRMGMT_INTR 0x3010064
18#define MPNPU_PUB_SCRATCH0 0x301006C19#define MPNPU_PUB_SCRATCH0 0x301006C
@@ -116,6 +117,7 @@ static const struct amdxdna_dev_priv npu4_dev_priv = { · 97 unmodified lines
116 DEFINE_BAR_OFFSET(PSP_INTR_REG, NPU4_PSP, MP0_C2PMSG_73),117 DEFINE_BAR_OFFSET(PSP_INTR_REG, NPU4_PSP, MP0_C2PMSG_73),
117 DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU4_PSP, MP0_C2PMSG_123),118 DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU4_PSP, MP0_C2PMSG_123),
118 DEFINE_BAR_OFFSET(PSP_RESP_REG, NPU4_REG, MPNPU_PUB_SCRATCH3),119 DEFINE_BAR_OFFSET(PSP_RESP_REG, NPU4_REG, MPNPU_PUB_SCRATCH3),
120 DEFINE_BAR_OFFSET(PSP_PWAITMODE_REG, NPU4_REG, MPNPU_PWAITMODE),
119 },121 },
120 .smu_regs_off = {122 .smu_regs_off = {
121 DEFINE_BAR_OFFSET(SMU_CMD_REG, NPU4_SMU, MP1_C2PMSG_0),123 DEFINE_BAR_OFFSET(SMU_CMD_REG, NPU4_SMU, MP1_C2PMSG_0),
drivers/accel/amdxdna/npu5_regs.c+2−0
@@ -13,6 +13,7 @@ · 12 unmodified lines
13#include "amdxdna_pci_drv.h"13#include "amdxdna_pci_drv.h"
14 14
15/* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */15/* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */
16#define MPNPU_PWAITMODE 0x301003C
16#define MPNPU_PUB_SEC_INTR 0x301006017#define MPNPU_PUB_SEC_INTR 0x3010060
17#define MPNPU_PUB_PWRMGMT_INTR 0x301006418#define MPNPU_PUB_PWRMGMT_INTR 0x3010064
18#define MPNPU_PUB_SCRATCH0 0x301006C19#define MPNPU_PUB_SCRATCH0 0x301006C
@@ -85,6 +86,7 @@ static const struct amdxdna_dev_priv npu5_dev_priv = { · 66 unmodified lines
85 DEFINE_BAR_OFFSET(PSP_INTR_REG, NPU5_PSP, MP0_C2PMSG_73),86 DEFINE_BAR_OFFSET(PSP_INTR_REG, NPU5_PSP, MP0_C2PMSG_73),
86 DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU5_PSP, MP0_C2PMSG_123),87 DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU5_PSP, MP0_C2PMSG_123),
87 DEFINE_BAR_OFFSET(PSP_RESP_REG, NPU5_REG, MPNPU_PUB_SCRATCH3),88 DEFINE_BAR_OFFSET(PSP_RESP_REG, NPU5_REG, MPNPU_PUB_SCRATCH3),
89 DEFINE_BAR_OFFSET(PSP_PWAITMODE_REG, NPU5_REG, MPNPU_PWAITMODE),
88 },90 },
89 .smu_regs_off = {91 .smu_regs_off = {
90 DEFINE_BAR_OFFSET(SMU_CMD_REG, NPU5_SMU, MP1_C2PMSG_0),92 DEFINE_BAR_OFFSET(SMU_CMD_REG, NPU5_SMU, MP1_C2PMSG_0),
drivers/accel/amdxdna/npu6_regs.c+2−0
@@ -13,6 +13,7 @@ · 12 unmodified lines
13#include "amdxdna_pci_drv.h"13#include "amdxdna_pci_drv.h"
14 14
15/* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */15/* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */
16#define MPNPU_PWAITMODE 0x301003C
16#define MPNPU_PUB_SEC_INTR 0x301006017#define MPNPU_PUB_SEC_INTR 0x3010060
17#define MPNPU_PUB_PWRMGMT_INTR 0x301006418#define MPNPU_PUB_PWRMGMT_INTR 0x3010064
18#define MPNPU_PUB_SCRATCH0 0x301006C19#define MPNPU_PUB_SCRATCH0 0x301006C
@@ -85,6 +86,7 @@ static const struct amdxdna_dev_priv npu6_dev_priv = { · 66 unmodified lines
85 DEFINE_BAR_OFFSET(PSP_INTR_REG, NPU6_PSP, MP0_C2PMSG_73),86 DEFINE_BAR_OFFSET(PSP_INTR_REG, NPU6_PSP, MP0_C2PMSG_73),
86 DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU6_PSP, MP0_C2PMSG_123),87 DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU6_PSP, MP0_C2PMSG_123),
87 DEFINE_BAR_OFFSET(PSP_RESP_REG, NPU6_REG, MPNPU_PUB_SCRATCH3),88 DEFINE_BAR_OFFSET(PSP_RESP_REG, NPU6_REG, MPNPU_PUB_SCRATCH3),
89 DEFINE_BAR_OFFSET(PSP_PWAITMODE_REG, NPU6_REG, MPNPU_PWAITMODE),
88 },90 },
89 .smu_regs_off = {91 .smu_regs_off = {
90 DEFINE_BAR_OFFSET(SMU_CMD_REG, NPU6_SMU, MP1_C2PMSG_0),92 DEFINE_BAR_OFFSET(SMU_CMD_REG, NPU6_SMU, MP1_C2PMSG_0),
drivers/dma-buf/Kconfig+1−1
@@ -55,7 +55,7 @@ config DMABUF_MOVE_NOTIFY · 54 unmodified lines
55config DMABUF_DEBUG55config DMABUF_DEBUG
56 bool "DMA-BUF debug checks"56 bool "DMA-BUF debug checks"
57 depends on DMA_SHARED_BUFFER57 depends on DMA_SHARED_BUFFER
58 default y if DMA_API_DEBUG58 default y if DEBUG
59 help59 help
60 This option enables additional checks for DMA-BUF importers and60 This option enables additional checks for DMA-BUF importers and
61 exporters. Specifically it validates that importers do not peek at the61 exporters. Specifically it validates that importers do not peek at the
drivers/dma-buf/dma-buf.c+62−17
@@ -35,6 +35,12 @@ · 34 unmodified lines
35 35
36#include "dma-buf-sysfs-stats.h"36#include "dma-buf-sysfs-stats.h"
37 37
38/* Wrapper to hide the sg_table page link from the importer */
39struct dma_buf_sg_table_wrapper {
40 struct sg_table *original;
41 struct sg_table wrapper;
42};
43
38static inline int is_dma_buf_file(struct file *);44static inline int is_dma_buf_file(struct file *);
39 45
40static DEFINE_MUTEX(dmabuf_list_mutex);46static DEFINE_MUTEX(dmabuf_list_mutex);
@@ -820,21 +826,59 @@ void dma_buf_put(struct dma_buf *dmabuf) · 779 unmodified lines
820}826}
821EXPORT_SYMBOL_NS_GPL(dma_buf_put, "DMA_BUF");827EXPORT_SYMBOL_NS_GPL(dma_buf_put, "DMA_BUF");
822 828
823static void mangle_sg_table(struct sg_table *sg_table)829static int dma_buf_wrap_sg_table(struct sg_table **sg_table)
824{830{
825#ifdef CONFIG_DMABUF_DEBUG831 struct scatterlist *to_sg, *from_sg;
826 int i;832 struct sg_table *from = *sg_table;
827 struct scatterlist *sg;833 struct dma_buf_sg_table_wrapper *to;
828 834 int i, ret;
829 /* To catch abuse of the underlying struct page by importers mix835
830 * up the bits, but take care to preserve the low SG_ bits to836 if (!IS_ENABLED(CONFIG_DMABUF_DEBUG))
831 * not corrupt the sgt. The mixing is undone on unmap837 return 0;
832 * before passing the sgt back to the exporter.838
839 /*
840 * To catch abuse of the underlying struct page by importers copy the
841 * sg_table without copying the page_link and give only the copy back to
842 * the importer.
833 */843 */
834 for_each_sgtable_sg(sg_table, sg, i)844 to = kzalloc(sizeof(*to), GFP_KERNEL);
835 sg->page_link ^= ~0xffUL;845 if (!to)
836#endif846 return -ENOMEM;
847
848 ret = sg_alloc_table(&to->wrapper, from->nents, GFP_KERNEL);
849 if (ret)
850 goto free_to;
851
852 to_sg = to->wrapper.sgl;
853 for_each_sgtable_dma_sg(from, from_sg, i) {
854 to_sg->offset = 0;
855 to_sg->length = 0;
856 sg_assign_page(to_sg, NULL);
857 sg_dma_address(to_sg) = sg_dma_address(from_sg);
858 sg_dma_len(to_sg) = sg_dma_len(from_sg);
859 to_sg = sg_next(to_sg);
860 }
837 861
862 to->original = from;
863 *sg_table = &to->wrapper;
864 return 0;
865
866free_to:
867 kfree(to);
868 return ret;
869}
870
871static void dma_buf_unwrap_sg_table(struct sg_table **sg_table)
872{
873 struct dma_buf_sg_table_wrapper *copy;
874
875 if (!IS_ENABLED(CONFIG_DMABUF_DEBUG))
876 return;
877
878 copy = container_of(*sg_table, typeof(*copy), wrapper);
879 *sg_table = copy->original;
880 sg_free_table(&copy->wrapper);
881 kfree(copy);
838}882}
839 883
840static inline bool884static inline bool
@@ -1131,10 +1175,11 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, · 290 unmodified lines
1131 if (ret < 0)1175 if (ret < 0)
1132 goto error_unmap;1176 goto error_unmap;
1133 }1177 }
1134 mangle_sg_table(sg_table);1178 ret = dma_buf_wrap_sg_table(&sg_table);
1179 if (ret)
1180 goto error_unmap;
1135 1181
1136#ifdef CONFIG_DMA_API_DEBUG1182 if (IS_ENABLED(CONFIG_DMA_API_DEBUG)) {
1137 {
1138 struct scatterlist *sg;1183 struct scatterlist *sg;
1139 u64 addr;1184 u64 addr;
1140 int len;1185 int len;
@@ -1146,10 +1191,10 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, · 5 unmodified lines
1146 if (!PAGE_ALIGNED(addr) || !PAGE_ALIGNED(len)) {1191 if (!PAGE_ALIGNED(addr) || !PAGE_ALIGNED(len)) {
1147 pr_debug("%s: addr %llx or len %x is not page aligned!\n",1192 pr_debug("%s: addr %llx or len %x is not page aligned!\n",
1148 __func__, addr, len);1193 __func__, addr, len);
1194 break;
1149 }1195 }
1150 }1196 }
1151 }1197 }
1152#endif /* CONFIG_DMA_API_DEBUG */
1153 return sg_table;1198 return sg_table;
1154 1199
1155error_unmap:1200error_unmap:
@@ -1213,7 +1258,7 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, · 57 unmodified lines
1213 1258
1214 dma_resv_assert_held(attach->dmabuf->resv);1259 dma_resv_assert_held(attach->dmabuf->resv);
1215 1260
1216 mangle_sg_table(sg_table);1261 dma_buf_unwrap_sg_table(&sg_table);
1217 attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);1262 attach->dmabuf->ops->unmap_dma_buf(attach, sg_table, direction);
1218 1263
1219 if (dma_buf_pin_on_map(attach))1264 if (dma_buf_pin_on_map(attach))
drivers/dma-buf/dma-fence.c+62−38
@@ -358,11 +358,8 @@ void __dma_fence_might_wait(void) · 357 unmodified lines
358 *358 *
359 * Unlike dma_fence_signal_timestamp(), this function must be called with359 * Unlike dma_fence_signal_timestamp(), this function must be called with
360 * &dma_fence.lock held.360 * &dma_fence.lock held.
361 *
362 * Returns 0 on success and a negative error value when @fence has been
363 * signalled already.
364 */361 */
365int dma_fence_signal_timestamp_locked(struct dma_fence *fence,362void dma_fence_signal_timestamp_locked(struct dma_fence *fence,
366 ktime_t timestamp)363 ktime_t timestamp)
367{364{
368 struct dma_fence_cb *cur, *tmp;365 struct dma_fence_cb *cur, *tmp;
@@ -372,7 +369,7 @@ int dma_fence_signal_timestamp_locked(struct dma_fence *fence, · 3 unmodified lines
372 369
373 if (unlikely(test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT,370 if (unlikely(test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT,
374 &fence->flags)))371 &fence->flags)))
375 return -EINVAL;372 return;
376 373
377 /* Stash the cb_list before replacing it with the timestamp */374 /* Stash the cb_list before replacing it with the timestamp */
378 list_replace(&fence->cb_list, &cb_list);375 list_replace(&fence->cb_list, &cb_list);
@@ -385,8 +382,6 @@ int dma_fence_signal_timestamp_locked(struct dma_fence *fence, · 6 unmodified lines
385 INIT_LIST_HEAD(&cur->node);382 INIT_LIST_HEAD(&cur->node);
386 cur->func(fence, cur);383 cur->func(fence, cur);
387 }384 }
388
389 return 0;
390}385}
391EXPORT_SYMBOL(dma_fence_signal_timestamp_locked);386EXPORT_SYMBOL(dma_fence_signal_timestamp_locked);
392 387
@@ -401,23 +396,17 @@ EXPORT_SYMBOL(dma_fence_signal_timestamp_locked); · 8 unmodified lines
401 * can only go from the unsignaled to the signaled state and not back, it will396 * can only go from the unsignaled to the signaled state and not back, it will
402 * only be effective the first time. Set the timestamp provided as the fence397 * only be effective the first time. Set the timestamp provided as the fence
403 * signal timestamp.398 * signal timestamp.
404 *
405 * Returns 0 on success and a negative error value when @fence has been
406 * signalled already.
407 */399 */
408int dma_fence_signal_timestamp(struct dma_fence *fence, ktime_t timestamp)400void dma_fence_signal_timestamp(struct dma_fence *fence, ktime_t timestamp)
409{401{
410 unsigned long flags;402 unsigned long flags;
411 int ret;
412 403
413 if (WARN_ON(!fence))404 if (WARN_ON(!fence))
414 return -EINVAL;405 return;
415 406
416 spin_lock_irqsave(fence->lock, flags);407 spin_lock_irqsave(fence->lock, flags);
417 ret = dma_fence_signal_timestamp_locked(fence, timestamp);408 dma_fence_signal_timestamp_locked(fence, timestamp);
418 spin_unlock_irqrestore(fence->lock, flags);409 spin_unlock_irqrestore(fence->lock, flags);
419
420 return ret;
421}410}
422EXPORT_SYMBOL(dma_fence_signal_timestamp);411EXPORT_SYMBOL(dma_fence_signal_timestamp);
423 412
@@ -433,16 +422,57 @@ EXPORT_SYMBOL(dma_fence_signal_timestamp); · 9 unmodified lines
433 *422 *
434 * Unlike dma_fence_signal(), this function must be called with &dma_fence.lock423 * Unlike dma_fence_signal(), this function must be called with &dma_fence.lock
435 * held.424 * held.
436 *
437 * Returns 0 on success and a negative error value when @fence has been
438 * signalled already.
439 */425 */
440int dma_fence_signal_locked(struct dma_fence *fence)426void dma_fence_signal_locked(struct dma_fence *fence)
441{427{
442 return dma_fence_signal_timestamp_locked(fence, ktime_get());428 dma_fence_signal_timestamp_locked(fence, ktime_get());
443}429}
444EXPORT_SYMBOL(dma_fence_signal_locked);430EXPORT_SYMBOL(dma_fence_signal_locked);
445 431
432/**
433 * dma_fence_check_and_signal_locked - signal the fence if it's not yet signaled
434 * @fence: the fence to check and signal
435 *
436 * Checks whether a fence was signaled and signals it if it was not yet signaled.
437 *
438 * Unlike dma_fence_check_and_signal(), this function must be called with
439 * &struct dma_fence.lock being held.
440 *
441 * Return: true if fence has been signaled already, false otherwise.
442 */
443bool dma_fence_check_and_signal_locked(struct dma_fence *fence)
444{
445 bool ret;
446
447 ret = dma_fence_test_signaled_flag(fence);
448 dma_fence_signal_locked(fence);
449
450 return ret;
451}
452EXPORT_SYMBOL(dma_fence_check_and_signal_locked);
453
454/**
455 * dma_fence_check_and_signal - signal the fence if it's not yet signaled
456 * @fence: the fence to check and signal
457 *
458 * Checks whether a fence was signaled and signals it if it was not yet signaled.
459 * All this is done in a race-free manner.
460 *
461 * Return: true if fence has been signaled already, false otherwise.
462 */
463bool dma_fence_check_and_signal(struct dma_fence *fence)
464{
465 unsigned long flags;
466 bool ret;
467
468 spin_lock_irqsave(fence->lock, flags);
469 ret = dma_fence_check_and_signal_locked(fence);
470 spin_unlock_irqrestore(fence->lock, flags);
471
472 return ret;
473}
474EXPORT_SYMBOL(dma_fence_check_and_signal);
475
446/**476/**
447 * dma_fence_signal - signal completion of a fence477 * dma_fence_signal - signal completion of a fence
448 * @fence: the fence to signal478 * @fence: the fence to signal
@@ -452,28 +482,22 @@ EXPORT_SYMBOL(dma_fence_signal_locked); · 3 unmodified lines
452 * dma_fence_add_callback(). Can be called multiple times, but since a fence482 * dma_fence_add_callback(). Can be called multiple times, but since a fence
453 * can only go from the unsignaled to the signaled state and not back, it will483 * can only go from the unsignaled to the signaled state and not back, it will
454 * only be effective the first time.484 * only be effective the first time.
455 *
456 * Returns 0 on success and a negative error value when @fence has been
457 * signalled already.
458 */485 */
459int dma_fence_signal(struct dma_fence *fence)486void dma_fence_signal(struct dma_fence *fence)
460{487{
461 unsigned long flags;488 unsigned long flags;
462 int ret;
463 bool tmp;489 bool tmp;
464 490
465 if (WARN_ON(!fence))491 if (WARN_ON(!fence))
466 return -EINVAL;492 return;
467 493
468 tmp = dma_fence_begin_signalling();494 tmp = dma_fence_begin_signalling();
469 495
470 spin_lock_irqsave(fence->lock, flags);496 spin_lock_irqsave(fence->lock, flags);
471 ret = dma_fence_signal_timestamp_locked(fence, ktime_get());497 dma_fence_signal_timestamp_locked(fence, ktime_get());
472 spin_unlock_irqrestore(fence->lock, flags);498 spin_unlock_irqrestore(fence->lock, flags);
473 499
474 dma_fence_end_signalling(tmp);500 dma_fence_end_signalling(tmp);
475
476 return ret;
477}501}
478EXPORT_SYMBOL(dma_fence_signal);502EXPORT_SYMBOL(dma_fence_signal);
479 503
@@ -543,7 +567,7 @@ void dma_fence_release(struct kref *kref) · 63 unmodified lines
543 trace_dma_fence_destroy(fence);567 trace_dma_fence_destroy(fence);
544 568
545 if (!list_empty(&fence->cb_list) &&569 if (!list_empty(&fence->cb_list) &&
546 !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {570 !dma_fence_test_signaled_flag(fence)) {
547 const char __rcu *timeline;571 const char __rcu *timeline;
548 const char __rcu *driver;572 const char __rcu *driver;
549 unsigned long flags;573 unsigned long flags;
@@ -600,7 +624,7 @@ static bool __dma_fence_enable_signaling(struct dma_fence *fence) · 50 unmodified lines
600 was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,624 was_set = test_and_set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
601 &fence->flags);625 &fence->flags);
602 626
603 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))627 if (dma_fence_test_signaled_flag(fence))
604 return false;628 return false;
605 629
606 if (!was_set && fence->ops->enable_signaling) {630 if (!was_set && fence->ops->enable_signaling) {
@@ -664,7 +688,7 @@ int dma_fence_add_callback(struct dma_fence *fence, struct dma_fence_cb *cb, · 57 unmodified lines
664 if (WARN_ON(!fence || !func))688 if (WARN_ON(!fence || !func))
665 return -EINVAL;689 return -EINVAL;
666 690
667 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {691 if (dma_fence_test_signaled_flag(fence)) {
668 INIT_LIST_HEAD(&cb->node);692 INIT_LIST_HEAD(&cb->node);
669 return -ENOENT;693 return -ENOENT;
670 }694 }
@@ -781,7 +805,7 @@ dma_fence_default_wait(struct dma_fence *fence, bool intr, signed long timeout) · 110 unmodified lines
781 805
782 spin_lock_irqsave(fence->lock, flags);806 spin_lock_irqsave(fence->lock, flags);
783 807
784 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))808 if (dma_fence_test_signaled_flag(fence))
785 goto out;809 goto out;
786 810
787 if (intr && signal_pending(current)) {811 if (intr && signal_pending(current)) {
@@ -798,7 +822,7 @@ dma_fence_default_wait(struct dma_fence *fence, bool intr, signed long timeout) · 10 unmodified lines
798 cb.task = current;822 cb.task = current;
799 list_add(&cb.base.node, &fence->cb_list);823 list_add(&cb.base.node, &fence->cb_list);
800 824
801 while (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags) && ret > 0) {825 while (!dma_fence_test_signaled_flag(fence) && ret > 0) {
802 if (intr)826 if (intr)
803 __set_current_state(TASK_INTERRUPTIBLE);827 __set_current_state(TASK_INTERRUPTIBLE);
804 else828 else
@@ -830,7 +854,7 @@ dma_fence_test_signaled_any(struct dma_fence **fences, uint32_t count, · 25 unmodified lines
830 854
831 for (i = 0; i < count; ++i) {855 for (i = 0; i < count; ++i) {
832 struct dma_fence *fence = fences[i];856 struct dma_fence *fence = fences[i];
833 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) {857 if (dma_fence_test_signaled_flag(fence)) {
834 if (idx)858 if (idx)
835 *idx = i;859 *idx = i;
836 return true;860 return true;
@@ -1108,7 +1132,7 @@ const char __rcu *dma_fence_driver_name(struct dma_fence *fence) · 271 unmodified lines
1108 RCU_LOCKDEP_WARN(!rcu_read_lock_held(),1132 RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
1109 "RCU protection is required for safe access to returned string");1133 "RCU protection is required for safe access to returned string");
1110 1134
1111 if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))1135 if (!dma_fence_test_signaled_flag(fence))
1112 return fence->ops->get_driver_name(fence);1136 return fence->ops->get_driver_name(fence);
1113 else1137 else
1114 return "detached-driver";1138 return "detached-driver";
@@ -1140,7 +1164,7 @@ const char __rcu *dma_fence_timeline_name(struct dma_fence *fence) · 25 unmodified lines
1140 RCU_LOCKDEP_WARN(!rcu_read_lock_held(),1164 RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
1141 "RCU protection is required for safe access to returned string");1165 "RCU protection is required for safe access to returned string");
1142 1166
1143 if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))1167 if (!dma_fence_test_signaled_flag(fence))
1144 return fence->ops->get_timeline_name(fence);1168 return fence->ops->get_timeline_name(fence);
1145 else1169 else
1146 return "signaled-timeline";1170 return "signaled-timeline";
drivers/dma-buf/st-dma-fence.c+2−2
@@ -126,7 +126,7 @@ static int test_signaling(void *arg) · 125 unmodified lines
126 goto err_free;126 goto err_free;
127 }127 }
128 128
129 if (dma_fence_signal(f)) {129 if (dma_fence_check_and_signal(f)) {
130 pr_err("Fence reported being already signaled\n");130 pr_err("Fence reported being already signaled\n");
131 goto err_free;131 goto err_free;
132 }132 }
@@ -136,7 +136,7 @@ static int test_signaling(void *arg) · 3 unmodified lines
136 goto err_free;136 goto err_free;
137 }137 }
138 138
139 if (!dma_fence_signal(f)) {139 if (!dma_fence_test_signaled_flag(f)) {
140 pr_err("Fence reported not being already signaled\n");140 pr_err("Fence reported not being already signaled\n");
141 goto err_free;141 goto err_free;
142 }142 }
drivers/gpu/drm/Kconfig+59−140
@@ -265,164 +265,83 @@ config DRM_SCHED · 264 unmodified lines
265 tristate265 tristate
266 depends on DRM266 depends on DRM
267 267
268source "drivers/gpu/drm/sysfb/Kconfig"268# Separate option as not all DRM drivers use it
269config DRM_PANEL_BACKLIGHT_QUIRKS
270 tristate
269 271
270source "drivers/gpu/drm/arm/Kconfig"272config DRM_LIB_RANDOM
273 bool
274 default n
271 275
272source "drivers/gpu/drm/radeon/Kconfig"276config DRM_PRIVACY_SCREEN
277 bool
278 default n
273 279
280# DRM driver Kconfig files, sorted
281source "drivers/gpu/drm/adp/Kconfig"
274source "drivers/gpu/drm/amd/amdgpu/Kconfig"282source "drivers/gpu/drm/amd/amdgpu/Kconfig"
275 283source "drivers/gpu/drm/arm/Kconfig"
276source "drivers/gpu/drm/nouveau/Kconfig"
277
278source "drivers/gpu/drm/nova/Kconfig"
279
280source "drivers/gpu/drm/i915/Kconfig"
281
282source "drivers/gpu/drm/xe/Kconfig"
283
284source "drivers/gpu/drm/kmb/Kconfig"
285
286config DRM_VGEM
287 tristate "Virtual GEM provider"
288 depends on DRM && MMU
289 select DRM_GEM_SHMEM_HELPER
290 help
291 Choose this option to get a virtual graphics memory manager,
292 as used by Mesa's software renderer for enhanced performance.
293 If M is selected the module will be called vgem.
294
295source "drivers/gpu/drm/vkms/Kconfig"
296
297source "drivers/gpu/drm/exynos/Kconfig"
298
299source "drivers/gpu/drm/rockchip/Kconfig"
300
301source "drivers/gpu/drm/vmwgfx/Kconfig"
302
303source "drivers/gpu/drm/gma500/Kconfig"
304
305source "drivers/gpu/drm/udl/Kconfig"
306
307source "drivers/gpu/drm/ast/Kconfig"
308
309source "drivers/gpu/drm/mgag200/Kconfig"
310
311source "drivers/gpu/drm/armada/Kconfig"284source "drivers/gpu/drm/armada/Kconfig"
312 285source "drivers/gpu/drm/aspeed/Kconfig"
286source "drivers/gpu/drm/ast/Kconfig"
313source "drivers/gpu/drm/atmel-hlcdc/Kconfig"287source "drivers/gpu/drm/atmel-hlcdc/Kconfig"
314
315source "drivers/gpu/drm/renesas/Kconfig"
316
317source "drivers/gpu/drm/sun4i/Kconfig"
318
319source "drivers/gpu/drm/omapdrm/Kconfig"
320
321source "drivers/gpu/drm/tilcdc/Kconfig"
322
323source "drivers/gpu/drm/qxl/Kconfig"
324
325source "drivers/gpu/drm/virtio/Kconfig"
326
327source "drivers/gpu/drm/msm/Kconfig"
328
329source "drivers/gpu/drm/fsl-dcu/Kconfig"
330
331source "drivers/gpu/drm/tegra/Kconfig"
332
333source "drivers/gpu/drm/stm/Kconfig"
334
335source "drivers/gpu/drm/panel/Kconfig"
336
337source "drivers/gpu/drm/bridge/Kconfig"288source "drivers/gpu/drm/bridge/Kconfig"
338
339source "drivers/gpu/drm/sti/Kconfig"
340
341source "drivers/gpu/drm/imx/Kconfig"
342
343source "drivers/gpu/drm/ingenic/Kconfig"
344
345source "drivers/gpu/drm/v3d/Kconfig"
346
347source "drivers/gpu/drm/vc4/Kconfig"
348
349source "drivers/gpu/drm/loongson/Kconfig"
350
351source "drivers/gpu/drm/etnaviv/Kconfig"289source "drivers/gpu/drm/etnaviv/Kconfig"
352 290source "drivers/gpu/drm/exynos/Kconfig"
291source "drivers/gpu/drm/fsl-dcu/Kconfig"
292source "drivers/gpu/drm/gma500/Kconfig"
293source "drivers/gpu/drm/gud/Kconfig"
353source "drivers/gpu/drm/hisilicon/Kconfig"294source "drivers/gpu/drm/hisilicon/Kconfig"
354 295source "drivers/gpu/drm/hyperv/Kconfig"
296source "drivers/gpu/drm/i915/Kconfig"
297source "drivers/gpu/drm/imagination/Kconfig"
298source "drivers/gpu/drm/imx/Kconfig"
299source "drivers/gpu/drm/ingenic/Kconfig"
300source "drivers/gpu/drm/kmb/Kconfig"
301source "drivers/gpu/drm/lima/Kconfig"
355source "drivers/gpu/drm/logicvc/Kconfig"302source "drivers/gpu/drm/logicvc/Kconfig"
356 303source "drivers/gpu/drm/loongson/Kconfig"
304source "drivers/gpu/drm/mcde/Kconfig"
357source "drivers/gpu/drm/mediatek/Kconfig"305source "drivers/gpu/drm/mediatek/Kconfig"
358
359source "drivers/gpu/drm/mxsfb/Kconfig"
360
361source "drivers/gpu/drm/meson/Kconfig"306source "drivers/gpu/drm/meson/Kconfig"
362 307source "drivers/gpu/drm/mgag200/Kconfig"
363source "drivers/gpu/drm/tiny/Kconfig"308source "drivers/gpu/drm/msm/Kconfig"
364 309source "drivers/gpu/drm/mxsfb/Kconfig"
365source "drivers/gpu/drm/pl111/Kconfig"310source "drivers/gpu/drm/nouveau/Kconfig"
366 311source "drivers/gpu/drm/nova/Kconfig"
367source "drivers/gpu/drm/tve200/Kconfig"312source "drivers/gpu/drm/omapdrm/Kconfig"
368 313source "drivers/gpu/drm/panel/Kconfig"
369source "drivers/gpu/drm/xen/Kconfig"
370
371source "drivers/gpu/drm/vboxvideo/Kconfig"
372
373source "drivers/gpu/drm/lima/Kconfig"
374
375source "drivers/gpu/drm/panfrost/Kconfig"314source "drivers/gpu/drm/panfrost/Kconfig"
376
377source "drivers/gpu/drm/panthor/Kconfig"315source "drivers/gpu/drm/panthor/Kconfig"
378 316source "drivers/gpu/drm/pl111/Kconfig"
379source "drivers/gpu/drm/aspeed/Kconfig"317source "drivers/gpu/drm/qxl/Kconfig"
380 318source "drivers/gpu/drm/radeon/Kconfig"
381source "drivers/gpu/drm/mcde/Kconfig"319source "drivers/gpu/drm/renesas/Kconfig"
382 320source "drivers/gpu/drm/rockchip/Kconfig"
383source "drivers/gpu/drm/tidss/Kconfig"
384
385source "drivers/gpu/drm/adp/Kconfig"
386
387source "drivers/gpu/drm/xlnx/Kconfig"
388
389source "drivers/gpu/drm/gud/Kconfig"
390
391source "drivers/gpu/drm/sitronix/Kconfig"321source "drivers/gpu/drm/sitronix/Kconfig"
392
393source "drivers/gpu/drm/solomon/Kconfig"322source "drivers/gpu/drm/solomon/Kconfig"
394
395source "drivers/gpu/drm/sprd/Kconfig"323source "drivers/gpu/drm/sprd/Kconfig"
396 324source "drivers/gpu/drm/sti/Kconfig"
397source "drivers/gpu/drm/imagination/Kconfig"325source "drivers/gpu/drm/stm/Kconfig"
398 326source "drivers/gpu/drm/sun4i/Kconfig"
327source "drivers/gpu/drm/sysfb/Kconfig"
328source "drivers/gpu/drm/tegra/Kconfig"
329source "drivers/gpu/drm/tidss/Kconfig"
330source "drivers/gpu/drm/tilcdc/Kconfig"
331source "drivers/gpu/drm/tiny/Kconfig"
332source "drivers/gpu/drm/tve200/Kconfig"
399source "drivers/gpu/drm/tyr/Kconfig"333source "drivers/gpu/drm/tyr/Kconfig"
400 334source "drivers/gpu/drm/udl/Kconfig"
401config DRM_HYPERV335source "drivers/gpu/drm/v3d/Kconfig"
402 tristate "DRM Support for Hyper-V synthetic video device"336source "drivers/gpu/drm/vboxvideo/Kconfig"
403 depends on DRM && PCI && HYPERV_VMBUS337source "drivers/gpu/drm/vc4/Kconfig"
404 select DRM_CLIENT_SELECTION338source "drivers/gpu/drm/vgem/Kconfig"
405 select DRM_KMS_HELPER339source "drivers/gpu/drm/virtio/Kconfig"
406 select DRM_GEM_SHMEM_HELPER340source "drivers/gpu/drm/vkms/Kconfig"
407 help341source "drivers/gpu/drm/vmwgfx/Kconfig"
408 This is a KMS driver for Hyper-V synthetic video device. Choose this342source "drivers/gpu/drm/xe/Kconfig"
409 option if you would like to enable drm driver for Hyper-V virtual343source "drivers/gpu/drm/xen/Kconfig"
410 machine. Unselect Hyper-V framebuffer driver (CONFIG_FB_HYPERV) so344source "drivers/gpu/drm/xlnx/Kconfig"
411 that DRM driver is used by default.
412
413 If M is selected the module will be called hyperv_drm.
414
415# Separate option as not all DRM drivers use it
416config DRM_PANEL_BACKLIGHT_QUIRKS
417 tristate
418
419config DRM_LIB_RANDOM
420 bool
421 default n
422
423config DRM_PRIVACY_SCREEN
424 bool
425 default n
426 345
427endif346endif
428 347
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c+11−24
@@ -1838,7 +1838,7 @@ static void dce_v10_0_grph_enable(struct drm_crtc *crtc, bool enable) · 1837 unmodified lines
1838 1838
1839static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,1839static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
1840 struct drm_framebuffer *fb,1840 struct drm_framebuffer *fb,
1841 int x, int y, int atomic)1841 int x, int y)
1842{1842{
1843 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);1843 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
1844 struct drm_device *dev = crtc->dev;1844 struct drm_device *dev = crtc->dev;
@@ -1855,15 +1855,12 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, · 10 unmodified lines
1855 bool bypass_lut = false;1855 bool bypass_lut = false;
1856 1856
1857 /* no fb bound */1857 /* no fb bound */
1858 if (!atomic && !crtc->primary->fb) {1858 if (!crtc->primary->fb) {
1859 DRM_DEBUG_KMS("No FB bound\n");1859 DRM_DEBUG_KMS("No FB bound\n");
1860 return 0;1860 return 0;
1861 }1861 }
1862 1862
1863 if (atomic)1863 target_fb = crtc->primary->fb;
1864 target_fb = fb;
1865 else
1866 target_fb = crtc->primary->fb;
1867 1864
1868 /* If atomic, assume fb object is pinned & idle & fenced and1865 /* If atomic, assume fb object is pinned & idle & fenced and
1869 * just update base pointers1866 * just update base pointers
@@ -1874,13 +1871,11 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, · 4 unmodified lines
1874 if (unlikely(r != 0))1871 if (unlikely(r != 0))
1875 return r;1872 return r;
1876 1873
1877 if (!atomic) {1874 abo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
1878 abo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;1875 r = amdgpu_bo_pin(abo, AMDGPU_GEM_DOMAIN_VRAM);
1879 r = amdgpu_bo_pin(abo, AMDGPU_GEM_DOMAIN_VRAM);1876 if (unlikely(r != 0)) {
1880 if (unlikely(r != 0)) {1877 amdgpu_bo_unreserve(abo);
1881 amdgpu_bo_unreserve(abo);1878 return -EINVAL;
1882 return -EINVAL;
1883 }
1884 }1879 }
1885 fb_location = amdgpu_bo_gpu_offset(abo);1880 fb_location = amdgpu_bo_gpu_offset(abo);
1886 1881
@@ -2068,7 +2063,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc, · 181 unmodified lines
2068 /* set pageflip to happen anywhere in vblank interval */2063 /* set pageflip to happen anywhere in vblank interval */
2069 WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);2064 WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
2070 2065
2071 if (!atomic && fb && fb != crtc->primary->fb) {2066 if (fb && fb != crtc->primary->fb) {
2072 abo = gem_to_amdgpu_bo(fb->obj[0]);2067 abo = gem_to_amdgpu_bo(fb->obj[0]);
2073 r = amdgpu_bo_reserve(abo, true);2068 r = amdgpu_bo_reserve(abo, true);
2074 if (unlikely(r != 0))2069 if (unlikely(r != 0))
@@ -2611,7 +2606,7 @@ static int dce_v10_0_crtc_mode_set(struct drm_crtc *crtc, · 536 unmodified lines
2611 2606
2612 amdgpu_atombios_crtc_set_pll(crtc, adjusted_mode);2607 amdgpu_atombios_crtc_set_pll(crtc, adjusted_mode);
2613 amdgpu_atombios_crtc_set_dtd_timing(crtc, adjusted_mode);2608 amdgpu_atombios_crtc_set_dtd_timing(crtc, adjusted_mode);
2614 dce_v10_0_crtc_do_set_base(crtc, old_fb, x, y, 0);2609 dce_v10_0_crtc_do_set_base(crtc, old_fb, x, y);
2615 amdgpu_atombios_crtc_overscan_setup(crtc, mode, adjusted_mode);2610 amdgpu_atombios_crtc_overscan_setup(crtc, mode, adjusted_mode);
2616 amdgpu_atombios_crtc_scaler_setup(crtc);2611 amdgpu_atombios_crtc_scaler_setup(crtc);
2617 dce_v10_0_cursor_reset(crtc);2612 dce_v10_0_cursor_reset(crtc);
@@ -2659,14 +2654,7 @@ static bool dce_v10_0_crtc_mode_fixup(struct drm_crtc *crtc, · 41 unmodified lines
2659static int dce_v10_0_crtc_set_base(struct drm_crtc *crtc, int x, int y,2654static int dce_v10_0_crtc_set_base(struct drm_crtc *crtc, int x, int y,
2660 struct drm_framebuffer *old_fb)2655 struct drm_framebuffer *old_fb)
2661{2656{
2662 return dce_v10_0_crtc_do_set_base(crtc, old_fb, x, y, 0);2657 return dce_v10_0_crtc_do_set_base(crtc, old_fb, x, y);
2663}
2664
2665static int dce_v10_0_crtc_set_base_atomic(struct drm_crtc *crtc,
2666 struct drm_framebuffer *fb,
2667 int x, int y, enum mode_set_atomic state)
2668{
2669 return dce_v10_0_crtc_do_set_base(crtc, fb, x, y, 1);
2670}2658}
2671 2659
2672static const struct drm_crtc_helper_funcs dce_v10_0_crtc_helper_funcs = {2660static const struct drm_crtc_helper_funcs dce_v10_0_crtc_helper_funcs = {
@@ -2674,7 +2662,6 @@ static const struct drm_crtc_helper_funcs dce_v10_0_crtc_helper_funcs = { · 1 unmodified line
2674 .mode_fixup = dce_v10_0_crtc_mode_fixup,2662 .mode_fixup = dce_v10_0_crtc_mode_fixup,
2675 .mode_set = dce_v10_0_crtc_mode_set,2663 .mode_set = dce_v10_0_crtc_mode_set,
2676 .mode_set_base = dce_v10_0_crtc_set_base,2664 .mode_set_base = dce_v10_0_crtc_set_base,
2677 .mode_set_base_atomic = dce_v10_0_crtc_set_base_atomic,
2678 .prepare = dce_v10_0_crtc_prepare,2665 .prepare = dce_v10_0_crtc_prepare,
2679 .commit = dce_v10_0_crtc_commit,2666 .commit = dce_v10_0_crtc_commit,
2680 .disable = dce_v10_0_crtc_disable,2667 .disable = dce_v10_0_crtc_disable,
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c+11−24
@@ -1876,7 +1876,7 @@ static void dce_v6_0_grph_enable(struct drm_crtc *crtc, bool enable) · 1875 unmodified lines
1876 1876
1877static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc,1877static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc,
1878 struct drm_framebuffer *fb,1878 struct drm_framebuffer *fb,
1879 int x, int y, int atomic)1879 int x, int y)
1880{1880{
1881 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);1881 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
1882 struct drm_device *dev = crtc->dev;1882 struct drm_device *dev = crtc->dev;
@@ -1892,15 +1892,12 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc, · 9 unmodified lines
1892 bool bypass_lut = false;1892 bool bypass_lut = false;
1893 1893
1894 /* no fb bound */1894 /* no fb bound */
1895 if (!atomic && !crtc->primary->fb) {1895 if (!crtc->primary->fb) {
1896 DRM_DEBUG_KMS("No FB bound\n");1896 DRM_DEBUG_KMS("No FB bound\n");
1897 return 0;1897 return 0;
1898 }1898 }
1899 1899
1900 if (atomic)1900 target_fb = crtc->primary->fb;
1901 target_fb = fb;
1902 else
1903 target_fb = crtc->primary->fb;
1904 1901
1905 /* If atomic, assume fb object is pinned & idle & fenced and1902 /* If atomic, assume fb object is pinned & idle & fenced and
1906 * just update base pointers1903 * just update base pointers
@@ -1911,13 +1908,11 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc, · 4 unmodified lines
1911 if (unlikely(r != 0))1908 if (unlikely(r != 0))
1912 return r;1909 return r;
1913 1910
1914 if (!atomic) {1911 abo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
1915 abo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;1912 r = amdgpu_bo_pin(abo, AMDGPU_GEM_DOMAIN_VRAM);
1916 r = amdgpu_bo_pin(abo, AMDGPU_GEM_DOMAIN_VRAM);1913 if (unlikely(r != 0)) {
1917 if (unlikely(r != 0)) {1914 amdgpu_bo_unreserve(abo);
1918 amdgpu_bo_unreserve(abo);1915 return -EINVAL;
1919 return -EINVAL;
1920 }
1921 }1916 }
1922 fb_location = amdgpu_bo_gpu_offset(abo);1917 fb_location = amdgpu_bo_gpu_offset(abo);
1923 1918
@@ -2083,7 +2078,7 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc, · 159 unmodified lines
2083 /* set pageflip to happen anywhere in vblank interval */2078 /* set pageflip to happen anywhere in vblank interval */
2084 WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);2079 WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
2085 2080
2086 if (!atomic && fb && fb != crtc->primary->fb) {2081 if (fb && fb != crtc->primary->fb) {
2087 abo = gem_to_amdgpu_bo(fb->obj[0]);2082 abo = gem_to_amdgpu_bo(fb->obj[0]);
2088 r = amdgpu_bo_reserve(abo, true);2083 r = amdgpu_bo_reserve(abo, true);
2089 if (unlikely(r != 0))2084 if (unlikely(r != 0))
@@ -2578,7 +2573,7 @@ static int dce_v6_0_crtc_mode_set(struct drm_crtc *crtc, · 488 unmodified lines
2578 2573
2579 amdgpu_atombios_crtc_set_pll(crtc, adjusted_mode);2574 amdgpu_atombios_crtc_set_pll(crtc, adjusted_mode);
2580 amdgpu_atombios_crtc_set_dtd_timing(crtc, adjusted_mode);2575 amdgpu_atombios_crtc_set_dtd_timing(crtc, adjusted_mode);
2581 dce_v6_0_crtc_do_set_base(crtc, old_fb, x, y, 0);2576 dce_v6_0_crtc_do_set_base(crtc, old_fb, x, y);
2582 amdgpu_atombios_crtc_overscan_setup(crtc, mode, adjusted_mode);2577 amdgpu_atombios_crtc_overscan_setup(crtc, mode, adjusted_mode);
2583 amdgpu_atombios_crtc_scaler_setup(crtc);2578 amdgpu_atombios_crtc_scaler_setup(crtc);
2584 dce_v6_0_cursor_reset(crtc);2579 dce_v6_0_cursor_reset(crtc);
@@ -2626,14 +2621,7 @@ static bool dce_v6_0_crtc_mode_fixup(struct drm_crtc *crtc, · 41 unmodified lines
2626static int dce_v6_0_crtc_set_base(struct drm_crtc *crtc, int x, int y,2621static int dce_v6_0_crtc_set_base(struct drm_crtc *crtc, int x, int y,
2627 struct drm_framebuffer *old_fb)2622 struct drm_framebuffer *old_fb)
2628{2623{
2629 return dce_v6_0_crtc_do_set_base(crtc, old_fb, x, y, 0);2624 return dce_v6_0_crtc_do_set_base(crtc, old_fb, x, y);
2630}
2631
2632static int dce_v6_0_crtc_set_base_atomic(struct drm_crtc *crtc,
2633 struct drm_framebuffer *fb,
2634 int x, int y, enum mode_set_atomic state)
2635{
2636 return dce_v6_0_crtc_do_set_base(crtc, fb, x, y, 1);
2637}2625}
2638 2626
2639static const struct drm_crtc_helper_funcs dce_v6_0_crtc_helper_funcs = {2627static const struct drm_crtc_helper_funcs dce_v6_0_crtc_helper_funcs = {
@@ -2641,7 +2629,6 @@ static const struct drm_crtc_helper_funcs dce_v6_0_crtc_helper_funcs = { · 1 unmodified line
2641 .mode_fixup = dce_v6_0_crtc_mode_fixup,2629 .mode_fixup = dce_v6_0_crtc_mode_fixup,
2642 .mode_set = dce_v6_0_crtc_mode_set,2630 .mode_set = dce_v6_0_crtc_mode_set,
2643 .mode_set_base = dce_v6_0_crtc_set_base,2631 .mode_set_base = dce_v6_0_crtc_set_base,
2644 .mode_set_base_atomic = dce_v6_0_crtc_set_base_atomic,
2645 .prepare = dce_v6_0_crtc_prepare,2632 .prepare = dce_v6_0_crtc_prepare,
2646 .commit = dce_v6_0_crtc_commit,2633 .commit = dce_v6_0_crtc_commit,
2647 .disable = dce_v6_0_crtc_disable,2634 .disable = dce_v6_0_crtc_disable,
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c+11−24
@@ -1785,7 +1785,7 @@ static void dce_v8_0_grph_enable(struct drm_crtc *crtc, bool enable) · 1784 unmodified lines
1785 1785
1786static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,1786static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
1787 struct drm_framebuffer *fb,1787 struct drm_framebuffer *fb,
1788 int x, int y, int atomic)1788 int x, int y)
1789{1789{
1790 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);1790 struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
1791 struct drm_device *dev = crtc->dev;1791 struct drm_device *dev = crtc->dev;
@@ -1802,15 +1802,12 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, · 10 unmodified lines
1802 bool bypass_lut = false;1802 bool bypass_lut = false;
1803 1803
1804 /* no fb bound */1804 /* no fb bound */
1805 if (!atomic && !crtc->primary->fb) {1805 if (!crtc->primary->fb) {
1806 DRM_DEBUG_KMS("No FB bound\n");1806 DRM_DEBUG_KMS("No FB bound\n");
1807 return 0;1807 return 0;
1808 }1808 }
1809 1809
1810 if (atomic)1810 target_fb = crtc->primary->fb;
1811 target_fb = fb;
1812 else
1813 target_fb = crtc->primary->fb;
1814 1811
1815 /* If atomic, assume fb object is pinned & idle & fenced and1812 /* If atomic, assume fb object is pinned & idle & fenced and
1816 * just update base pointers1813 * just update base pointers
@@ -1821,13 +1818,11 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, · 4 unmodified lines
1821 if (unlikely(r != 0))1818 if (unlikely(r != 0))
1822 return r;1819 return r;
1823 1820
1824 if (!atomic) {1821 abo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
1825 abo->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;1822 r = amdgpu_bo_pin(abo, AMDGPU_GEM_DOMAIN_VRAM);
1826 r = amdgpu_bo_pin(abo, AMDGPU_GEM_DOMAIN_VRAM);1823 if (unlikely(r != 0)) {
1827 if (unlikely(r != 0)) {1824 amdgpu_bo_unreserve(abo);
1828 amdgpu_bo_unreserve(abo);1825 return -EINVAL;
1829 return -EINVAL;
1830 }
1831 }1826 }
1832 fb_location = amdgpu_bo_gpu_offset(abo);1827 fb_location = amdgpu_bo_gpu_offset(abo);
1833 1828
@@ -1995,7 +1990,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc, · 161 unmodified lines
1995 /* set pageflip to happen anywhere in vblank interval */1990 /* set pageflip to happen anywhere in vblank interval */
1996 WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);1991 WREG32(mmMASTER_UPDATE_MODE + amdgpu_crtc->crtc_offset, 0);
1997 1992
1998 if (!atomic && fb && fb != crtc->primary->fb) {1993 if (fb && fb != crtc->primary->fb) {
1999 abo = gem_to_amdgpu_bo(fb->obj[0]);1994 abo = gem_to_amdgpu_bo(fb->obj[0]);
2000 r = amdgpu_bo_reserve(abo, true);1995 r = amdgpu_bo_reserve(abo, true);
2001 if (unlikely(r != 0))1996 if (unlikely(r != 0))
@@ -2537,7 +2532,7 @@ static int dce_v8_0_crtc_mode_set(struct drm_crtc *crtc, · 535 unmodified lines
2537 2532
2538 amdgpu_atombios_crtc_set_pll(crtc, adjusted_mode);2533 amdgpu_atombios_crtc_set_pll(crtc, adjusted_mode);
2539 amdgpu_atombios_crtc_set_dtd_timing(crtc, adjusted_mode);2534 amdgpu_atombios_crtc_set_dtd_timing(crtc, adjusted_mode);
2540 dce_v8_0_crtc_do_set_base(crtc, old_fb, x, y, 0);2535 dce_v8_0_crtc_do_set_base(crtc, old_fb, x, y);
2541 amdgpu_atombios_crtc_overscan_setup(crtc, mode, adjusted_mode);2536 amdgpu_atombios_crtc_overscan_setup(crtc, mode, adjusted_mode);
2542 amdgpu_atombios_crtc_scaler_setup(crtc);2537 amdgpu_atombios_crtc_scaler_setup(crtc);
2543 dce_v8_0_cursor_reset(crtc);2538 dce_v8_0_cursor_reset(crtc);
@@ -2585,14 +2580,7 @@ static bool dce_v8_0_crtc_mode_fixup(struct drm_crtc *crtc, · 41 unmodified lines
2585static int dce_v8_0_crtc_set_base(struct drm_crtc *crtc, int x, int y,2580static int dce_v8_0_crtc_set_base(struct drm_crtc *crtc, int x, int y,
2586 struct drm_framebuffer *old_fb)2581 struct drm_framebuffer *old_fb)
2587{2582{
2588 return dce_v8_0_crtc_do_set_base(crtc, old_fb, x, y, 0);2583 return dce_v8_0_crtc_do_set_base(crtc, old_fb, x, y);
2589}
2590
2591static int dce_v8_0_crtc_set_base_atomic(struct drm_crtc *crtc,
2592 struct drm_framebuffer *fb,
2593 int x, int y, enum mode_set_atomic state)
2594{
2595 return dce_v8_0_crtc_do_set_base(crtc, fb, x, y, 1);
2596}2584}
2597 2585
2598static const struct drm_crtc_helper_funcs dce_v8_0_crtc_helper_funcs = {2586static const struct drm_crtc_helper_funcs dce_v8_0_crtc_helper_funcs = {
@@ -2600,7 +2588,6 @@ static const struct drm_crtc_helper_funcs dce_v8_0_crtc_helper_funcs = { · 1 unmodified line
2600 .mode_fixup = dce_v8_0_crtc_mode_fixup,2588 .mode_fixup = dce_v8_0_crtc_mode_fixup,
2601 .mode_set = dce_v8_0_crtc_mode_set,2589 .mode_set = dce_v8_0_crtc_mode_set,
2602 .mode_set_base = dce_v8_0_crtc_set_base,2590 .mode_set_base = dce_v8_0_crtc_set_base,
2603 .mode_set_base_atomic = dce_v8_0_crtc_set_base_atomic,
2604 .prepare = dce_v8_0_crtc_prepare,2591 .prepare = dce_v8_0_crtc_prepare,
2605 .commit = dce_v8_0_crtc_commit,2592 .commit = dce_v8_0_crtc_commit,
2606 .disable = dce_v8_0_crtc_disable,2593 .disable = dce_v8_0_crtc_disable,
drivers/gpu/drm/amd/amdkfd/kfd_process.c+3−3
@@ -1987,10 +1987,10 @@ kfd_process_gpuid_from_node(struct kfd_process *p, struct kfd_node *node, · 1986 unmodified lines
1987 return -EINVAL;1987 return -EINVAL;
1988}1988}
1989 1989
1990static int signal_eviction_fence(struct kfd_process *p)1990static bool signal_eviction_fence(struct kfd_process *p)
1991{1991{
1992 struct dma_fence *ef;1992 struct dma_fence *ef;
1993 int ret;1993 bool ret;
1994 1994
1995 rcu_read_lock();1995 rcu_read_lock();
1996 ef = dma_fence_get_rcu_safe(&p->ef);1996 ef = dma_fence_get_rcu_safe(&p->ef);
@@ -1998,7 +1998,7 @@ static int signal_eviction_fence(struct kfd_process *p) · 1 unmodified line
1998 if (!ef)1998 if (!ef)
1999 return -EINVAL;1999 return -EINVAL;
2000 2000
2001 ret = dma_fence_signal(ef);2001 ret = dma_fence_check_and_signal(ef);
2002 dma_fence_put(ef);2002 dma_fence_put(ef);
2003 2003
2004 return ret;2004 return ret;
drivers/gpu/drm/ast/ast_cursor.c+62−21
@@ -28,6 +28,7 @@ · 27 unmodified lines
28#include <drm/drm_damage_helper.h>28#include <drm/drm_damage_helper.h>
29#include <drm/drm_format_helper.h>29#include <drm/drm_format_helper.h>
30#include <drm/drm_gem_atomic_helper.h>30#include <drm/drm_gem_atomic_helper.h>
31#include <drm/drm_gem_framebuffer_helper.h>
31#include <drm/drm_print.h>32#include <drm/drm_print.h>
32 33
33#include "ast_drv.h"34#include "ast_drv.h"
@@ -181,6 +182,62 @@ static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane, · 147 unmodified lines
181 return 0;182 return 0;
182}183}
183 184
185static const u8 *ast_cursor_plane_get_argb4444(struct ast_cursor_plane *ast_cursor_plane,
186 struct drm_shadow_plane_state *shadow_plane_state,
187 const struct drm_rect *clip)
188{
189 struct drm_plane_state *plane_state = &shadow_plane_state->base;
190 struct drm_framebuffer *fb = plane_state->fb;
191 u8 *argb4444 = NULL;
192
193 if (drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE) == 0) {
194 switch (fb->format->format) {
195 case DRM_FORMAT_ARGB4444:
196 if (shadow_plane_state->data[0].is_iomem) {
197 struct iosys_map argb4444_dst[DRM_FORMAT_MAX_PLANES] = {
198 IOSYS_MAP_INIT_VADDR(ast_cursor_plane->argb4444),
199 };
200 unsigned int argb4444_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
201 AST_HWC_PITCH,
202 };
203
204 drm_fb_memcpy(argb4444_dst, argb4444_dst_pitch,
205 shadow_plane_state->data, fb, clip);
206 argb4444 = argb4444_dst[0].vaddr;
207 } else {
208 argb4444 = shadow_plane_state->data[0].vaddr;
209 }
210 break;
211 case DRM_FORMAT_ARGB8888:
212 {
213 struct iosys_map argb4444_dst[DRM_FORMAT_MAX_PLANES] = {
214 IOSYS_MAP_INIT_VADDR(ast_cursor_plane->argb4444),
215 };
216 unsigned int argb4444_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
217 AST_HWC_PITCH,
218 };
219
220 drm_fb_argb8888_to_argb4444(argb4444_dst, argb4444_dst_pitch,
221 shadow_plane_state->data, fb, clip,
222 &shadow_plane_state->fmtcnv_state);
223 argb4444 = argb4444_dst[0].vaddr;
224 }
225 break;
226 }
227
228 drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
229 } else {
230 /*
231 * Fall back to white square if GEM object is not ready. Gives
232 * the user an indication where the cursor is located.
233 */
234 memset(ast_cursor_plane->argb4444, 0xff, sizeof(ast_cursor_plane->argb4444));
235 argb4444 = ast_cursor_plane->argb4444;
236 }
237
238 return argb4444;
239}
240
184static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,241static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
185 struct drm_atomic_state *state)242 struct drm_atomic_state *state)
186{243{
@@ -205,29 +262,13 @@ static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane, · 18 unmodified lines
205 */262 */
206 263
207 if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) {264 if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) {
208 u8 *argb4444;265 const u8 *argb4444 = ast_cursor_plane_get_argb4444(ast_cursor_plane,
266 shadow_plane_state,
267 &damage);
209 268
210 switch (fb->format->format) {269 if (argb4444)
211 case DRM_FORMAT_ARGB4444:270 ast_set_cursor_image(ast, argb4444, fb->width, fb->height);
212 argb4444 = shadow_plane_state->data[0].vaddr;
213 break;
214 default:
215 argb4444 = ast_cursor_plane->argb4444;
216 {
217 struct iosys_map argb4444_dst[DRM_FORMAT_MAX_PLANES] = {
218 IOSYS_MAP_INIT_VADDR(argb4444),
219 };
220 unsigned int argb4444_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
221 AST_HWC_PITCH,
222 };
223 271
224 drm_fb_argb8888_to_argb4444(argb4444_dst, argb4444_dst_pitch,
225 shadow_plane_state->data, fb, &damage,
226 &shadow_plane_state->fmtcnv_state);
227 }
228 break;
229 }
230 ast_set_cursor_image(ast, argb4444, fb->width, fb->height);
231 ast_set_cursor_base(ast, dst_off);272 ast_set_cursor_base(ast, dst_off);
232 }273 }
233 274
drivers/gpu/drm/bridge/ti-sn65dsi83.c+66−20
@@ -406,6 +406,10 @@ static void sn65dsi83_reset_work(struct work_struct *ws) · 405 unmodified lines
406{406{
407 struct sn65dsi83 *ctx = container_of(ws, struct sn65dsi83, reset_work);407 struct sn65dsi83 *ctx = container_of(ws, struct sn65dsi83, reset_work);
408 int ret;408 int ret;
409 int idx;
410
411 if (!drm_bridge_enter(&ctx->bridge, &idx))
412 return;
409 413
410 /* Reset the pipe */414 /* Reset the pipe */
411 ret = sn65dsi83_reset_pipe(ctx);415 ret = sn65dsi83_reset_pipe(ctx);
@@ -415,12 +419,18 @@ static void sn65dsi83_reset_work(struct work_struct *ws) · 3 unmodified lines
415 }419 }
416 if (ctx->irq)420 if (ctx->irq)
417 enable_irq(ctx->irq);421 enable_irq(ctx->irq);
422
423 drm_bridge_exit(idx);
418}424}
419 425
420static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx)426static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx)
421{427{
422 unsigned int irq_stat;428 unsigned int irq_stat;
423 int ret;429 int ret;
430 int idx;
431
432 if (!drm_bridge_enter(&ctx->bridge, &idx))
433 return;
424 434
425 /*435 /*
426 * Schedule a reset in case of:436 * Schedule a reset in case of:
@@ -448,6 +458,8 @@ static void sn65dsi83_handle_errors(struct sn65dsi83 *ctx) · 21 unmodified lines
448 458
449 schedule_work(&ctx->reset_work);459 schedule_work(&ctx->reset_work);
450 }460 }
461
462 drm_bridge_exit(idx);
451}463}
452 464
453static void sn65dsi83_monitor_work(struct work_struct *work)465static void sn65dsi83_monitor_work(struct work_struct *work)
@@ -470,6 +482,37 @@ static void sn65dsi83_monitor_stop(struct sn65dsi83 *ctx) · 16 unmodified lines
470 cancel_delayed_work_sync(&ctx->monitor_work);482 cancel_delayed_work_sync(&ctx->monitor_work);
471}483}
472 484
485/*
486 * Release resources taken by sn65dsi83_atomic_pre_enable().
487 *
488 * Invoked by sn65dsi83_atomic_disable() normally, or by devres after
489 * sn65dsi83_remove() in case this happens befora atomic_disable.
490 */
491static void sn65dsi83_release_resources(void *data)
492{
493 struct sn65dsi83 *ctx = (struct sn65dsi83 *)data;
494 int ret;
495
496 if (ctx->irq) {
497 /* Disable irq */
498 regmap_write(ctx->regmap, REG_IRQ_EN, 0x0);
499 regmap_write(ctx->regmap, REG_IRQ_GLOBAL, 0x0);
500 } else {
501 /* Stop the polling task */
502 sn65dsi83_monitor_stop(ctx);
503 }
504
505 /* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */
506 gpiod_set_value_cansleep(ctx->enable_gpio, 0);
507 usleep_range(10000, 11000);
508
509 ret = regulator_disable(ctx->vcc);
510 if (ret)
511 dev_err(ctx->dev, "Failed to disable vcc: %d\n", ret);
512
513 regcache_mark_dirty(ctx->regmap);
514}
515
473static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,516static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge,
474 struct drm_atomic_state *state)517 struct drm_atomic_state *state)
475{518{
@@ -485,11 +528,15 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, · 9 unmodified lines
485 __le16 le16val;528 __le16 le16val;
486 u16 val;529 u16 val;
487 int ret;530 int ret;
531 int idx;
532
533 if (!drm_bridge_enter(bridge, &idx))
534 return;
488 535
489 ret = regulator_enable(ctx->vcc);536 ret = regulator_enable(ctx->vcc);
490 if (ret) {537 if (ret) {
491 dev_err(ctx->dev, "Failed to enable vcc: %d\n", ret);538 dev_err(ctx->dev, "Failed to enable vcc: %d\n", ret);
492 return;539 goto err_exit;
493 }540 }
494 541
495 /* Deassert reset */542 /* Deassert reset */
@@ -632,7 +679,7 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, · 136 unmodified lines
632 dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret);679 dev_err(ctx->dev, "failed to lock PLL, ret=%i\n", ret);
633 /* On failure, disable PLL again and exit. */680 /* On failure, disable PLL again and exit. */
634 regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);681 regmap_write(ctx->regmap, REG_RC_PLL_EN, 0x00);
635 return;682 goto err_add_action;
636 }683 }
637 684
638 /* Trigger reset after CSR register update. */685 /* Trigger reset after CSR register update. */
@@ -640,6 +687,11 @@ static void sn65dsi83_atomic_pre_enable(struct drm_bridge *bridge, · 1 unmodified line
640 687
641 /* Wait for 10ms after soft reset as specified in datasheet */688 /* Wait for 10ms after soft reset as specified in datasheet */
642 usleep_range(10000, 12000);689 usleep_range(10000, 12000);
690
691err_add_action:
692 devm_add_action(ctx->dev, sn65dsi83_release_resources, ctx);
693err_exit:
694 drm_bridge_exit(idx);
643}695}
644 696
645static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,697static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
@@ -647,6 +699,10 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge, · 1 unmodified line
647{699{
648 struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);700 struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
649 unsigned int pval;701 unsigned int pval;
702 int idx;
703
704 if (!drm_bridge_enter(bridge, &idx))
705 return;
650 706
651 /* Clear all errors that got asserted during initialization. */707 /* Clear all errors that got asserted during initialization. */
652 regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);708 regmap_read(ctx->regmap, REG_IRQ_STAT, &pval);
@@ -666,32 +722,22 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge, · 13 unmodified lines
666 /* Use the polling task */722 /* Use the polling task */
667 sn65dsi83_monitor_start(ctx);723 sn65dsi83_monitor_start(ctx);
668 }724 }
725
726 drm_bridge_exit(idx);
669}727}
670 728
671static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,729static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,
672 struct drm_atomic_state *state)730 struct drm_atomic_state *state)
673{731{
674 struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);732 struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
675 int ret;733 int idx;
676 734
677 if (ctx->irq) {735 if (!drm_bridge_enter(bridge, &idx))
678 /* Disable irq */736 return;
679 regmap_write(ctx->regmap, REG_IRQ_EN, 0x0);
680 regmap_write(ctx->regmap, REG_IRQ_GLOBAL, 0x0);
681 } else {
682 /* Stop the polling task */
683 sn65dsi83_monitor_stop(ctx);
684 }
685
686 /* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */
687 gpiod_set_value_cansleep(ctx->enable_gpio, 0);
688 usleep_range(10000, 11000);
689 737
690 ret = regulator_disable(ctx->vcc);738 devm_release_action(ctx->dev, sn65dsi83_release_resources, ctx);
691 if (ret)
692 dev_err(ctx->dev, "Failed to disable vcc: %d\n", ret);
693 739
694 regcache_mark_dirty(ctx->regmap);740 drm_bridge_exit(idx);
695}741}
696 742
697static enum drm_mode_status743static enum drm_mode_status
@@ -1012,7 +1058,7 @@ static void sn65dsi83_remove(struct i2c_client *client) · 314 unmodified lines
1012{1058{
1013 struct sn65dsi83 *ctx = i2c_get_clientdata(client);1059 struct sn65dsi83 *ctx = i2c_get_clientdata(client);
1014 1060
1015 drm_bridge_remove(&ctx->bridge);1061 drm_bridge_unplug(&ctx->bridge);
1016}1062}
1017 1063
1018static const struct i2c_device_id sn65dsi83_id[] = {1064static const struct i2c_device_id sn65dsi83_id[] = {
drivers/gpu/drm/display/drm_dp_mst_topology.c+2−1
@@ -4572,7 +4572,8 @@ int drm_dp_atomic_release_time_slots(struct drm_atomic_state *state, · 4571 unmodified lines
4572 if (!payload->delete) {4572 if (!payload->delete) {
4573 payload->pbn = 0;4573 payload->pbn = 0;
4574 payload->delete = true;4574 payload->delete = true;
4575 topology_state->payload_mask &= ~BIT(payload->vcpi - 1);4575 if (payload->vcpi > 0)
4576 topology_state->payload_mask &= ~BIT(payload->vcpi - 1);
4576 }4577 }
4577 4578
4578 return 0;4579 return 0;
drivers/gpu/drm/drm_atomic.c+1−0
@@ -906,6 +906,7 @@ drm_atomic_private_obj_init(struct drm_device *dev, · 905 unmodified lines
906 906
907 drm_modeset_lock_init(&obj->lock);907 drm_modeset_lock_init(&obj->lock);
908 908
909 obj->dev = dev;
909 obj->state = state;910 obj->state = state;
910 obj->funcs = funcs;911 obj->funcs = funcs;
911 list_add_tail(&obj->head, &dev->mode_config.privobj_list);912 list_add_tail(&obj->head, &dev->mode_config.privobj_list);
drivers/gpu/drm/drm_bridge.c+62−0
@@ -27,6 +27,7 @@ · 26 unmodified lines
27#include <linux/media-bus-format.h>27#include <linux/media-bus-format.h>
28#include <linux/module.h>28#include <linux/module.h>
29#include <linux/mutex.h>29#include <linux/mutex.h>
30#include <linux/srcu.h>
30 31
31#include <drm/drm_atomic_state_helper.h>32#include <drm/drm_atomic_state_helper.h>
32#include <drm/drm_bridge.h>33#include <drm/drm_bridge.h>
@@ -202,6 +203,67 @@ static DEFINE_MUTEX(bridge_lock); · 169 unmodified lines
202static LIST_HEAD(bridge_list);203static LIST_HEAD(bridge_list);
203static LIST_HEAD(bridge_lingering_list);204static LIST_HEAD(bridge_lingering_list);
204 205
206DEFINE_STATIC_SRCU(drm_bridge_unplug_srcu);
207
208/**
209 * drm_bridge_enter - Enter DRM bridge critical section
210 * @bridge: DRM bridge
211 * @idx: Pointer to index that will be passed to the matching drm_bridge_exit()
212 *
213 * This function marks and protects the beginning of a section that should not
214 * be entered after the bridge has been unplugged. The section end is marked
215 * with drm_bridge_exit(). Calls to this function can be nested.
216 *
217 * Returns:
218 * True if it is OK to enter the section, false otherwise.
219 */
220bool drm_bridge_enter(struct drm_bridge *bridge, int *idx)
221{
222 *idx = srcu_read_lock(&drm_bridge_unplug_srcu);
223
224 if (bridge->unplugged) {
225 srcu_read_unlock(&drm_bridge_unplug_srcu, *idx);
226 return false;
227 }
228
229 return true;
230}
231EXPORT_SYMBOL(drm_bridge_enter);
232
233/**
234 * drm_bridge_exit - Exit DRM bridge critical section
235 * @idx: index returned by drm_bridge_enter()
236 *
237 * This function marks the end of a section that should not be entered after
238 * the bridge has been unplugged.
239 */
240void drm_bridge_exit(int idx)
241{
242 srcu_read_unlock(&drm_bridge_unplug_srcu, idx);
243}
244EXPORT_SYMBOL(drm_bridge_exit);
245
246/**
247 * drm_bridge_unplug - declare a DRM bridge was unplugged and remove it
248 * @bridge: DRM bridge
249 *
250 * This tells the bridge has been physically unplugged and no operations on
251 * device resources must be done anymore. Entry-points can use
252 * drm_bridge_enter() and drm_bridge_exit() to protect device resources in
253 * a race free manner.
254 *
255 * Also unregisters the bridge.
256 */
257void drm_bridge_unplug(struct drm_bridge *bridge)
258{
259 bridge->unplugged = true;
260
261 synchronize_srcu(&drm_bridge_unplug_srcu);
262
263 drm_bridge_remove(bridge);
264}
265EXPORT_SYMBOL(drm_bridge_unplug);
266
205static void __drm_bridge_free(struct kref *kref)267static void __drm_bridge_free(struct kref *kref)
206{268{
207 struct drm_bridge *bridge = container_of(kref, struct drm_bridge, refcount);269 struct drm_bridge *bridge = container_of(kref, struct drm_bridge, refcount);
drivers/gpu/drm/drm_fb_helper.c+0−108
@@ -75,9 +75,6 @@ MODULE_PARM_DESC(drm_leak_fbdev_smem, · 74 unmodified lines
75 "Allow unsafe leaking fbdev physical smem address [default=false]");75 "Allow unsafe leaking fbdev physical smem address [default=false]");
76#endif76#endif
77 77
78static LIST_HEAD(kernel_fb_helper_list);
79static DEFINE_MUTEX(kernel_fb_helper_lock);
80
81/**78/**
82 * DOC: fbdev helpers79 * DOC: fbdev helpers
83 *80 *
@@ -115,101 +112,6 @@ static DEFINE_MUTEX(kernel_fb_helper_lock); · 31 unmodified lines
115 * mmap page writes.112 * mmap page writes.
116 */113 */
117 114
118static void drm_fb_helper_restore_lut_atomic(struct drm_crtc *crtc)
119{
120 uint16_t *r_base, *g_base, *b_base;
121
122 if (crtc->funcs->gamma_set == NULL)
123 return;
124
125 r_base = crtc->gamma_store;
126 g_base = r_base + crtc->gamma_size;
127 b_base = g_base + crtc->gamma_size;
128
129 crtc->funcs->gamma_set(crtc, r_base, g_base, b_base,
130 crtc->gamma_size, NULL);
131}
132
133/**
134 * drm_fb_helper_debug_enter - implementation for &fb_ops.fb_debug_enter
135 * @info: fbdev registered by the helper
136 */
137int drm_fb_helper_debug_enter(struct fb_info *info)
138{
139 struct drm_fb_helper *helper = info->par;
140 const struct drm_crtc_helper_funcs *funcs;
141 struct drm_mode_set *mode_set;
142
143 list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
144 mutex_lock(&helper->client.modeset_mutex);
145 drm_client_for_each_modeset(mode_set, &helper->client) {
146 if (!mode_set->crtc->enabled)
147 continue;
148
149 funcs = mode_set->crtc->helper_private;
150 if (funcs->mode_set_base_atomic == NULL)
151 continue;
152
153 if (drm_drv_uses_atomic_modeset(mode_set->crtc->dev))
154 continue;
155
156 funcs->mode_set_base_atomic(mode_set->crtc,
157 mode_set->fb,
158 mode_set->x,
159 mode_set->y,
160 ENTER_ATOMIC_MODE_SET);
161 }
162 mutex_unlock(&helper->client.modeset_mutex);
163 }
164
165 return 0;
166}
167EXPORT_SYMBOL(drm_fb_helper_debug_enter);
168
169/**
170 * drm_fb_helper_debug_leave - implementation for &fb_ops.fb_debug_leave
171 * @info: fbdev registered by the helper
172 */
173int drm_fb_helper_debug_leave(struct fb_info *info)
174{
175 struct drm_fb_helper *helper = info->par;
176 struct drm_client_dev *client = &helper->client;
177 struct drm_device *dev = helper->dev;
178 struct drm_crtc *crtc;
179 const struct drm_crtc_helper_funcs *funcs;
180 struct drm_mode_set *mode_set;
181 struct drm_framebuffer *fb;
182
183 mutex_lock(&client->modeset_mutex);
184 drm_client_for_each_modeset(mode_set, client) {
185 crtc = mode_set->crtc;
186 if (drm_drv_uses_atomic_modeset(crtc->dev))
187 continue;
188
189 funcs = crtc->helper_private;
190 fb = crtc->primary->fb;
191
192 if (!crtc->enabled)
193 continue;
194
195 if (!fb) {
196 drm_err(dev, "no fb to restore?\n");
197 continue;
198 }
199
200 if (funcs->mode_set_base_atomic == NULL)
201 continue;
202
203 drm_fb_helper_restore_lut_atomic(mode_set->crtc);
204 funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
205 crtc->y, LEAVE_ATOMIC_MODE_SET);
206 }
207 mutex_unlock(&client->modeset_mutex);
208
209 return 0;
210}
211EXPORT_SYMBOL(drm_fb_helper_debug_leave);
212
213static int115static int
214__drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper,116__drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper,
215 bool force)117 bool force)
@@ -397,7 +299,6 @@ void drm_fb_helper_prepare(struct drm_device *dev, struct drm_fb_helper *helper, · 181 unmodified lines
397 if (!preferred_bpp)299 if (!preferred_bpp)
398 preferred_bpp = 32;300 preferred_bpp = 32;
399 301
400 INIT_LIST_HEAD(&helper->kernel_fb_list);
401 spin_lock_init(&helper->damage_lock);302 spin_lock_init(&helper->damage_lock);
402 INIT_WORK(&helper->resume_work, drm_fb_helper_resume_worker);303 INIT_WORK(&helper->resume_work, drm_fb_helper_resume_worker);
403 INIT_WORK(&helper->damage_work, drm_fb_helper_damage_work);304 INIT_WORK(&helper->damage_work, drm_fb_helper_damage_work);
@@ -534,11 +435,6 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) · 130 unmodified lines
534 435
535 drm_fb_helper_release_info(fb_helper);436 drm_fb_helper_release_info(fb_helper);
536 437
537 mutex_lock(&kernel_fb_helper_lock);
538 if (!list_empty(&fb_helper->kernel_fb_list))
539 list_del(&fb_helper->kernel_fb_list);
540 mutex_unlock(&kernel_fb_helper_lock);
541
542 if (!fb_helper->client.funcs)438 if (!fb_helper->client.funcs)
543 drm_client_release(&fb_helper->client);439 drm_client_release(&fb_helper->client);
544}440}
@@ -1766,10 +1662,6 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper) · 1221 unmodified lines
1766 drm_info(dev, "fb%d: %s frame buffer device\n",1662 drm_info(dev, "fb%d: %s frame buffer device\n",
1767 info->node, info->fix.id);1663 info->node, info->fix.id);
1768 1664
1769 mutex_lock(&kernel_fb_helper_lock);
1770 list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
1771 mutex_unlock(&kernel_fb_helper_lock);
1772
1773 return 0;1665 return 0;
1774 1666
1775err_drm_fb_helper_release_info:1667err_drm_fb_helper_release_info:
drivers/gpu/drm/drm_gem.c+155−49
@@ -29,6 +29,9 @@ · 28 unmodified lines
29#include <linux/export.h>29#include <linux/export.h>
30#include <linux/file.h>30#include <linux/file.h>
31#include <linux/fs.h>31#include <linux/fs.h>
32#ifdef CONFIG_TRANSPARENT_HUGEPAGE
33#include <linux/fs_context.h>
34#endif
32#include <linux/iosys-map.h>35#include <linux/iosys-map.h>
33#include <linux/mem_encrypt.h>36#include <linux/mem_encrypt.h>
34#include <linux/mm.h>37#include <linux/mm.h>
@@ -36,6 +39,7 @@ · 1 unmodified line
36#include <linux/module.h>39#include <linux/module.h>
37#include <linux/pagemap.h>40#include <linux/pagemap.h>
38#include <linux/pagevec.h>41#include <linux/pagevec.h>
42#include <linux/sched/mm.h>
39#include <linux/shmem_fs.h>43#include <linux/shmem_fs.h>
40#include <linux/slab.h>44#include <linux/slab.h>
41#include <linux/string_helpers.h>45#include <linux/string_helpers.h>
@@ -81,6 +85,60 @@ · 39 unmodified lines
81 * up at a later date, and as our interface with shmfs for memory allocation.85 * up at a later date, and as our interface with shmfs for memory allocation.
82 */86 */
83 87
88#ifdef CONFIG_TRANSPARENT_HUGEPAGE
89static void drm_gem_huge_mnt_free(struct drm_device *dev, void *data)
90{
91 kern_unmount(dev->huge_mnt);
92}
93
94/**
95 * drm_gem_huge_mnt_create - Create, mount and use a huge tmpfs mountpoint
96 * @dev: DRM device that will use the huge tmpfs mountpoint
97 * @value: huge tmpfs mount option value
98 *
99 * This function creates and mounts a dedicated huge tmpfs mountpoint for the
100 * lifetime of the DRM device @dev which is used at GEM object initialization
101 * with drm_gem_object_init().
102 *
103 * The most common option for @value is "within_size" which only allocates huge
104 * pages if the page will be fully within the GEM object size. "always",
105 * "advise" and "never" are supported too but the latter would just create a
106 * mountpoint similar to the default one (`shm_mnt`). See shmemfs and
107 * Transparent Hugepage for more information.
108 *
109 * Returns:
110 * 0 on success or a negative error code on failure.
111 */
112int drm_gem_huge_mnt_create(struct drm_device *dev, const char *value)
113{
114 struct file_system_type *type;
115 struct fs_context *fc;
116 int ret;
117
118 if (unlikely(drm_gem_get_huge_mnt(dev)))
119 return 0;
120
121 type = get_fs_type("tmpfs");
122 if (unlikely(!type))
123 return -EOPNOTSUPP;
124 fc = fs_context_for_mount(type, SB_KERNMOUNT);
125 if (IS_ERR(fc))
126 return PTR_ERR(fc);
127 ret = vfs_parse_fs_string(fc, "source", "tmpfs");
128 if (unlikely(ret))
129 return -ENOPARAM;
130 ret = vfs_parse_fs_string(fc, "huge", value);
131 if (unlikely(ret))
132 return -ENOPARAM;
133
134 dev->huge_mnt = fc_mount_longterm(fc);
135 put_fs_context(fc);
136
137 return drmm_add_action_or_reset(dev, drm_gem_huge_mnt_free, NULL);
138}
139EXPORT_SYMBOL_GPL(drm_gem_huge_mnt_create);
140#endif
141
84static void142static void
85drm_gem_init_release(struct drm_device *dev, void *ptr)143drm_gem_init_release(struct drm_device *dev, void *ptr)
86{144{
@@ -113,29 +171,28 @@ drm_gem_init(struct drm_device *dev) · 26 unmodified lines
113}171}
114 172
115/**173/**
116 * drm_gem_object_init_with_mnt - initialize an allocated shmem-backed GEM174 * drm_gem_object_init - initialize an allocated shmem-backed GEM object
117 * object in a given shmfs mountpoint
118 *175 *
119 * @dev: drm_device the object should be initialized for176 * @dev: drm_device the object should be initialized for
120 * @obj: drm_gem_object to initialize177 * @obj: drm_gem_object to initialize
121 * @size: object size178 * @size: object size
122 * @gemfs: tmpfs mount where the GEM object will be created. If NULL, use
123 * the usual tmpfs mountpoint (`shm_mnt`).
124 *179 *
125 * Initialize an already allocated GEM object of the specified size with180 * Initialize an already allocated GEM object of the specified size with
126 * shmfs backing store.181 * shmfs backing store. A huge mountpoint can be used by calling
182 * drm_gem_huge_mnt_create() beforehand.
127 */183 */
128int drm_gem_object_init_with_mnt(struct drm_device *dev,184int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj,
129 struct drm_gem_object *obj, size_t size,185 size_t size)
130 struct vfsmount *gemfs)
131{186{
187 struct vfsmount *huge_mnt;
132 struct file *filp;188 struct file *filp;
133 189
134 drm_gem_private_object_init(dev, obj, size);190 drm_gem_private_object_init(dev, obj, size);
135 191
136 if (gemfs)192 huge_mnt = drm_gem_get_huge_mnt(dev);
137 filp = shmem_file_setup_with_mnt(gemfs, "drm mm object", size,193 if (huge_mnt)
138 VM_NORESERVE);194 filp = shmem_file_setup_with_mnt(huge_mnt, "drm mm object",
195 size, VM_NORESERVE);
139 else196 else
140 filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);197 filp = shmem_file_setup("drm mm object", size, VM_NORESERVE);
141 198
@@ -146,22 +203,6 @@ int drm_gem_object_init_with_mnt(struct drm_device *dev, · 4 unmodified lines
146 203
147 return 0;204 return 0;
148}205}
149EXPORT_SYMBOL(drm_gem_object_init_with_mnt);
150
151/**
152 * drm_gem_object_init - initialize an allocated shmem-backed GEM object
153 * @dev: drm_device the object should be initialized for
154 * @obj: drm_gem_object to initialize
155 * @size: object size
156 *
157 * Initialize an already allocated GEM object of the specified size with
158 * shmfs backing store.
159 */
160int drm_gem_object_init(struct drm_device *dev, struct drm_gem_object *obj,
161 size_t size)
162{
163 return drm_gem_object_init_with_mnt(dev, obj, size, NULL);
164}
165EXPORT_SYMBOL(drm_gem_object_init);206EXPORT_SYMBOL(drm_gem_object_init);
166 207
167/**208/**
@@ -1181,36 +1222,27 @@ err_drm_gem_object_put: · 1013 unmodified lines
1181}1222}
1182EXPORT_SYMBOL(drm_gem_mmap_obj);1223EXPORT_SYMBOL(drm_gem_mmap_obj);
1183 1224
1184/**1225/*
1185 * drm_gem_mmap - memory map routine for GEM objects1226 * Look up a GEM object in offset space based on the exact start address. The
1186 * @filp: DRM file pointer1227 * caller must be granted access to the object. Returns a GEM object on success
1187 * @vma: VMA for the area to be mapped1228 * or a negative error code on failure. The returned GEM object needs to be
1188 *1229 * released with drm_gem_object_put().
1189 * If a driver supports GEM object mapping, mmap calls on the DRM file
1190 * descriptor will end up here.
1191 *
1192 * Look up the GEM object based on the offset passed in (vma->vm_pgoff will
1193 * contain the fake offset we created when the GTT map ioctl was called on
1194 * the object) and map it with a call to drm_gem_mmap_obj().
1195 *
1196 * If the caller is not granted access to the buffer object, the mmap will fail
1197 * with EACCES. Please see the vma manager for more information.
1198 */1230 */
1199int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)1231static struct drm_gem_object *
1232drm_gem_object_lookup_at_offset(struct file *filp, unsigned long start,
1233 unsigned long pages)
1200{1234{
1201 struct drm_file *priv = filp->private_data;1235 struct drm_file *priv = filp->private_data;
1202 struct drm_device *dev = priv->minor->dev;1236 struct drm_device *dev = priv->minor->dev;
1203 struct drm_gem_object *obj = NULL;1237 struct drm_gem_object *obj = NULL;
1204 struct drm_vma_offset_node *node;1238 struct drm_vma_offset_node *node;
1205 int ret;
1206 1239
1207 if (drm_dev_is_unplugged(dev))1240 if (drm_dev_is_unplugged(dev))
1208 return -ENODEV;1241 return ERR_PTR(-ENODEV);
1209 1242
1210 drm_vma_offset_lock_lookup(dev->vma_offset_manager);1243 drm_vma_offset_lock_lookup(dev->vma_offset_manager);
1211 node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,1244 node = drm_vma_offset_exact_lookup_locked(dev->vma_offset_manager,
1212 vma->vm_pgoff,1245 start, pages);
1213 vma_pages(vma));
1214 if (likely(node)) {1246 if (likely(node)) {
1215 obj = container_of(node, struct drm_gem_object, vma_node);1247 obj = container_of(node, struct drm_gem_object, vma_node);
1216 /*1248 /*
@@ -1229,14 +1261,88 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) · 12 unmodified lines
1229 drm_vma_offset_unlock_lookup(dev->vma_offset_manager);1261 drm_vma_offset_unlock_lookup(dev->vma_offset_manager);
1230 1262
1231 if (!obj)1263 if (!obj)
1232 return -EINVAL;1264 return ERR_PTR(-EINVAL);
1233 1265
1234 if (!drm_vma_node_is_allowed(node, priv)) {1266 if (!drm_vma_node_is_allowed(node, priv)) {
1235 drm_gem_object_put(obj);1267 drm_gem_object_put(obj);
1236 return -EACCES;1268 return ERR_PTR(-EACCES);
1237 }1269 }
1238 1270
1239 ret = drm_gem_mmap_obj(obj, drm_vma_node_size(node) << PAGE_SHIFT,1271 return obj;
1272}
1273
1274#ifdef CONFIG_MMU
1275/**
1276 * drm_gem_get_unmapped_area - get memory mapping region routine for GEM objects
1277 * @filp: DRM file pointer
1278 * @uaddr: User address hint
1279 * @len: Mapping length
1280 * @pgoff: Offset (in pages)
1281 * @flags: Mapping flags
1282 *
1283 * If a driver supports GEM object mapping, before ending up in drm_gem_mmap(),
1284 * mmap calls on the DRM file descriptor will first try to find a free linear
1285 * address space large enough for a mapping. Since GEM objects are backed by
1286 * shmem buffers, this should preferably be handled by the shmem virtual memory
1287 * filesystem which can appropriately align addresses to huge page sizes when
1288 * needed.
1289 *
1290 * Look up the GEM object based on the offset passed in (vma->vm_pgoff will
1291 * contain the fake offset we created) and call shmem_get_unmapped_area() with
1292 * the right file pointer.
1293 *
1294 * If a GEM object is not available at the given offset or if the caller is not
1295 * granted access to it, fall back to mm_get_unmapped_area().
1296 */
1297unsigned long drm_gem_get_unmapped_area(struct file *filp, unsigned long uaddr,
1298 unsigned long len, unsigned long pgoff,
1299 unsigned long flags)
1300{
1301 struct drm_gem_object *obj;
1302 unsigned long ret;
1303
1304 obj = drm_gem_object_lookup_at_offset(filp, pgoff, len >> PAGE_SHIFT);
1305 if (IS_ERR(obj) || !obj->filp || !obj->filp->f_op->get_unmapped_area)
1306 return mm_get_unmapped_area(filp, uaddr, len, 0,
1307 flags);
1308
1309 ret = obj->filp->f_op->get_unmapped_area(obj->filp, uaddr, len, 0,
1310 flags);
1311
1312 drm_gem_object_put(obj);
1313
1314 return ret;
1315}
1316EXPORT_SYMBOL_GPL(drm_gem_get_unmapped_area);
1317#endif
1318
1319/**
1320 * drm_gem_mmap - memory map routine for GEM objects
1321 * @filp: DRM file pointer
1322 * @vma: VMA for the area to be mapped
1323 *
1324 * If a driver supports GEM object mapping, mmap calls on the DRM file
1325 * descriptor will end up here.
1326 *
1327 * Look up the GEM object based on the offset passed in (vma->vm_pgoff will
1328 * contain the fake offset we created) and map it with a call to
1329 * drm_gem_mmap_obj().
1330 *
1331 * If the caller is not granted access to the buffer object, the mmap will fail
1332 * with EACCES. Please see the vma manager for more information.
1333 */
1334int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma)
1335{
1336 struct drm_gem_object *obj;
1337 int ret;
1338
1339 obj = drm_gem_object_lookup_at_offset(filp, vma->vm_pgoff,
1340 vma_pages(vma));
1341 if (IS_ERR(obj))
1342 return PTR_ERR(obj);
1343
1344 ret = drm_gem_mmap_obj(obj,
1345 drm_vma_node_size(&obj->vma_node) << PAGE_SHIFT,
1240 vma);1346 vma);
1241 1347
1242 drm_gem_object_put(obj);1348 drm_gem_object_put(obj);
drivers/gpu/drm/drm_gem_shmem_helper.c+41−36
@@ -50,7 +50,7 @@ static const struct drm_gem_object_funcs drm_gem_shmem_funcs = { · 49 unmodified lines
50};50};
51 51
52static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem,52static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem,
53 size_t size, bool private, struct vfsmount *gemfs)53 size_t size, bool private)
54{54{
55 struct drm_gem_object *obj = &shmem->base;55 struct drm_gem_object *obj = &shmem->base;
56 int ret = 0;56 int ret = 0;
@@ -62,7 +62,7 @@ static int __drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_obj · 5 unmodified lines
62 drm_gem_private_object_init(dev, obj, size);62 drm_gem_private_object_init(dev, obj, size);
63 shmem->map_wc = false; /* dma-buf mappings use always writecombine */63 shmem->map_wc = false; /* dma-buf mappings use always writecombine */
64 } else {64 } else {
65 ret = drm_gem_object_init_with_mnt(dev, obj, size, gemfs);65 ret = drm_gem_object_init(dev, obj, size);
66 }66 }
67 if (ret) {67 if (ret) {
68 drm_gem_private_object_fini(obj);68 drm_gem_private_object_fini(obj);
@@ -103,13 +103,12 @@ err_release: · 34 unmodified lines
103 */103 */
104int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem, size_t size)104int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem, size_t size)
105{105{
106 return __drm_gem_shmem_init(dev, shmem, size, false, NULL);106 return __drm_gem_shmem_init(dev, shmem, size, false);
107}107}
108EXPORT_SYMBOL_GPL(drm_gem_shmem_init);108EXPORT_SYMBOL_GPL(drm_gem_shmem_init);
109 109
110static struct drm_gem_shmem_object *110static struct drm_gem_shmem_object *
111__drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private,111__drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private)
112 struct vfsmount *gemfs)
113{112{
114 struct drm_gem_shmem_object *shmem;113 struct drm_gem_shmem_object *shmem;
115 struct drm_gem_object *obj;114 struct drm_gem_object *obj;
@@ -129,7 +128,7 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private, · 13 unmodified lines
129 obj = &shmem->base;128 obj = &shmem->base;
130 }129 }
131 130
132 ret = __drm_gem_shmem_init(dev, shmem, size, private, gemfs);131 ret = __drm_gem_shmem_init(dev, shmem, size, private);
133 if (ret) {132 if (ret) {
134 kfree(obj);133 kfree(obj);
135 return ERR_PTR(ret);134 return ERR_PTR(ret);
@@ -150,31 +149,10 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private, · 14 unmodified lines
150 */149 */
151struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size)150struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size)
152{151{
153 return __drm_gem_shmem_create(dev, size, false, NULL);152 return __drm_gem_shmem_create(dev, size, false);
154}153}
155EXPORT_SYMBOL_GPL(drm_gem_shmem_create);154EXPORT_SYMBOL_GPL(drm_gem_shmem_create);
156 155
157/**
158 * drm_gem_shmem_create_with_mnt - Allocate an object with the given size in a
159 * given mountpoint
160 * @dev: DRM device
161 * @size: Size of the object to allocate
162 * @gemfs: tmpfs mount where the GEM object will be created
163 *
164 * This function creates a shmem GEM object in a given tmpfs mountpoint.
165 *
166 * Returns:
167 * A struct drm_gem_shmem_object * on success or an ERR_PTR()-encoded negative
168 * error code on failure.
169 */
170struct drm_gem_shmem_object *drm_gem_shmem_create_with_mnt(struct drm_device *dev,
171 size_t size,
172 struct vfsmount *gemfs)
173{
174 return __drm_gem_shmem_create(dev, size, false, gemfs);
175}
176EXPORT_SYMBOL_GPL(drm_gem_shmem_create_with_mnt);
177
178/**156/**
179 * drm_gem_shmem_release - Release resources associated with a shmem GEM object.157 * drm_gem_shmem_release - Release resources associated with a shmem GEM object.
180 * @shmem: shmem GEM object158 * @shmem: shmem GEM object
@@ -567,6 +545,26 @@ int drm_gem_shmem_dumb_create(struct drm_file *file, struct drm_device *dev, · 386 unmodified lines
567}545}
568EXPORT_SYMBOL_GPL(drm_gem_shmem_dumb_create);546EXPORT_SYMBOL_GPL(drm_gem_shmem_dumb_create);
569 547
548static bool drm_gem_shmem_try_map_pmd(struct vm_fault *vmf, unsigned long addr,
549 struct page *page)
550{
551#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
552 unsigned long pfn = page_to_pfn(page);
553 unsigned long paddr = pfn << PAGE_SHIFT;
554 bool aligned = (addr & ~PMD_MASK) == (paddr & ~PMD_MASK);
555
556 if (aligned &&
557 pmd_none(*vmf->pmd) &&
558 folio_test_pmd_mappable(page_folio(page))) {
559 pfn &= PMD_MASK >> PAGE_SHIFT;
560 if (vmf_insert_pfn_pmd(vmf, pfn, false) == VM_FAULT_NOPAGE)
561 return true;
562 }
563#endif
564
565 return false;
566}
567
570static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)568static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
571{569{
572 struct vm_area_struct *vma = vmf->vma;570 struct vm_area_struct *vma = vmf->vma;
@@ -574,11 +572,12 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf) · 1 unmodified line
574 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);572 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
575 loff_t num_pages = obj->size >> PAGE_SHIFT;573 loff_t num_pages = obj->size >> PAGE_SHIFT;
576 vm_fault_t ret;574 vm_fault_t ret;
577 struct page *page;575 struct page **pages = shmem->pages;
578 pgoff_t page_offset;576 pgoff_t page_offset;
577 unsigned long pfn;
579 578
580 /* We don't use vmf->pgoff since that has the fake offset */579 /* Offset to faulty address in the VMA. */
581 page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;580 page_offset = vmf->pgoff - vma->vm_pgoff;
582 581
583 dma_resv_lock(shmem->base.resv, NULL);582 dma_resv_lock(shmem->base.resv, NULL);
584 583
@@ -586,12 +585,18 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf) · 1 unmodified line
586 drm_WARN_ON_ONCE(obj->dev, !shmem->pages) ||585 drm_WARN_ON_ONCE(obj->dev, !shmem->pages) ||
587 shmem->madv < 0) {586 shmem->madv < 0) {
588 ret = VM_FAULT_SIGBUS;587 ret = VM_FAULT_SIGBUS;
589 } else {588 goto out;
590 page = shmem->pages[page_offset];589 }
591 590
592 ret = vmf_insert_pfn(vma, vmf->address, page_to_pfn(page));591 if (drm_gem_shmem_try_map_pmd(vmf, vmf->address, pages[page_offset])) {
592 ret = VM_FAULT_NOPAGE;
593 goto out;
593 }594 }
594 595
596 pfn = page_to_pfn(pages[page_offset]);
597 ret = vmf_insert_pfn(vma, vmf->address, pfn);
598
599 out:
595 dma_resv_unlock(shmem->base.resv);600 dma_resv_unlock(shmem->base.resv);
596 601
597 return ret;602 return ret;
@@ -824,7 +829,7 @@ drm_gem_shmem_prime_import_sg_table(struct drm_device *dev, · 226 unmodified lines
824 size_t size = PAGE_ALIGN(attach->dmabuf->size);829 size_t size = PAGE_ALIGN(attach->dmabuf->size);
825 struct drm_gem_shmem_object *shmem;830 struct drm_gem_shmem_object *shmem;
826 831
827 shmem = __drm_gem_shmem_create(dev, size, true, NULL);832 shmem = __drm_gem_shmem_create(dev, size, true);
828 if (IS_ERR(shmem))833 if (IS_ERR(shmem))
829 return ERR_CAST(shmem);834 return ERR_CAST(shmem);
830 835
@@ -872,7 +877,7 @@ struct drm_gem_object *drm_gem_shmem_prime_import_no_map(struct drm_device *dev, · 41 unmodified lines
872 877
873 size = PAGE_ALIGN(attach->dmabuf->size);878 size = PAGE_ALIGN(attach->dmabuf->size);
874 879
875 shmem = __drm_gem_shmem_create(dev, size, true, NULL);880 shmem = __drm_gem_shmem_create(dev, size, true);
876 if (IS_ERR(shmem)) {881 if (IS_ERR(shmem)) {
877 ret = PTR_ERR(shmem);882 ret = PTR_ERR(shmem);
878 goto fail_detach;883 goto fail_detach;
drivers/gpu/drm/drm_panic.c+62−13
@@ -39,12 +39,6 @@ MODULE_AUTHOR("Jocelyn Falempe"); · 38 unmodified lines
39MODULE_DESCRIPTION("DRM panic handler");39MODULE_DESCRIPTION("DRM panic handler");
40MODULE_LICENSE("GPL");40MODULE_LICENSE("GPL");
41 41
42static char drm_panic_screen[16] = CONFIG_DRM_PANIC_SCREEN;
43module_param_string(panic_screen, drm_panic_screen, sizeof(drm_panic_screen), 0644);
44MODULE_PARM_DESC(panic_screen,
45 "Choose what will be displayed by drm_panic, 'user' or 'kmsg' [default="
46 CONFIG_DRM_PANIC_SCREEN "]");
47
48/**42/**
49 * DOC: overview43 * DOC: overview
50 *44 *
@@ -813,14 +807,59 @@ static void draw_panic_static_qr_code(struct drm_scanout_buffer *sb) · 762 unmodified lines
813 draw_panic_static_user(sb);807 draw_panic_static_user(sb);
814}808}
815#else809#else
816static void draw_panic_static_qr_code(struct drm_scanout_buffer *sb)810static void drm_panic_qr_init(void) {};
811static void drm_panic_qr_exit(void) {};
812#endif
813
814enum drm_panic_type {
815 DRM_PANIC_TYPE_KMSG,
816 DRM_PANIC_TYPE_USER,
817 DRM_PANIC_TYPE_QR,
818};
819
820static enum drm_panic_type drm_panic_type = -1;
821
822static const char *drm_panic_type_map[] = {
823 [DRM_PANIC_TYPE_KMSG] = "kmsg",
824 [DRM_PANIC_TYPE_USER] = "user",
825#if IS_ENABLED(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
826 [DRM_PANIC_TYPE_QR] = "qr",
827#endif
828};
829
830static int drm_panic_type_set(const char *val, const struct kernel_param *kp)
817{831{
818 draw_panic_static_user(sb);832 unsigned int i;
833
834 for (i = 0; i < ARRAY_SIZE(drm_panic_type_map); i++) {
835 if (!strcmp(val, drm_panic_type_map[i])) {
836 drm_panic_type = i;
837 return 0;
838 }
839 }
840
841 return -EINVAL;
819}842}
820 843
821static void drm_panic_qr_init(void) {};844static int drm_panic_type_get(char *buffer, const struct kernel_param *kp)
822static void drm_panic_qr_exit(void) {};845{
846 return scnprintf(buffer, PAGE_SIZE, "%s\n",
847 drm_panic_type_map[drm_panic_type]);
848}
849
850static const struct kernel_param_ops drm_panic_ops = {
851 .set = drm_panic_type_set,
852 .get = drm_panic_type_get,
853};
854
855module_param_cb(panic_screen, &drm_panic_ops, NULL, 0644);
856MODULE_PARM_DESC(panic_screen,
857#if IS_ENABLED(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
858 "Choose what will be displayed by drm_panic, 'user', 'kmsg' or 'qr' [default="
859#else
860 "Choose what will be displayed by drm_panic, 'user' or 'kmsg' [default="
823#endif861#endif
862 CONFIG_DRM_PANIC_SCREEN "]");
824 863
825/*864/*
826 * drm_panic_is_format_supported()865 * drm_panic_is_format_supported()
@@ -838,11 +877,19 @@ static bool drm_panic_is_format_supported(const struct drm_format_info *format) · 11 unmodified lines
838 877
839static void draw_panic_dispatch(struct drm_scanout_buffer *sb)878static void draw_panic_dispatch(struct drm_scanout_buffer *sb)
840{879{
841 if (!strcmp(drm_panic_screen, "kmsg")) {880 switch (drm_panic_type) {
881 case DRM_PANIC_TYPE_KMSG:
842 draw_panic_static_kmsg(sb);882 draw_panic_static_kmsg(sb);
843 } else if (!strcmp(drm_panic_screen, "qr_code")) {883 break;
884
885#if IS_ENABLED(CONFIG_DRM_PANIC_SCREEN_QR_CODE)
886 case DRM_PANIC_TYPE_QR:
844 draw_panic_static_qr_code(sb);887 draw_panic_static_qr_code(sb);
845 } else {888 break;
889#endif
890
891 case DRM_PANIC_TYPE_USER:
892 default:
846 draw_panic_static_user(sb);893 draw_panic_static_user(sb);
847 }894 }
848}895}
@@ -1025,6 +1072,8 @@ void drm_panic_unregister(struct drm_device *dev) · 176 unmodified lines
1025 */1072 */
1026void __init drm_panic_init(void)1073void __init drm_panic_init(void)
1027{1074{
1075 if (drm_panic_type == -1)
1076 drm_panic_type_set(CONFIG_DRM_PANIC_SCREEN, NULL);
1028 drm_panic_qr_init();1077 drm_panic_qr_init();
1029}1078}
1030 1079
drivers/gpu/drm/drm_plane.c+2−2
@@ -1867,9 +1867,9 @@ int drm_plane_create_color_pipeline_property(struct drm_plane *plane, · 1866 unmodified lines
1867 prop = drm_property_create_enum(plane->dev, DRM_MODE_PROP_ATOMIC,1867 prop = drm_property_create_enum(plane->dev, DRM_MODE_PROP_ATOMIC,
1868 "COLOR_PIPELINE",1868 "COLOR_PIPELINE",
1869 all_pipelines, len);1869 all_pipelines, len);
1870 if (IS_ERR(prop)) {1870 if (!prop) {
1871 kfree(all_pipelines);1871 kfree(all_pipelines);
1872 return PTR_ERR(prop);1872 return -ENOMEM;
1873 }1873 }
1874 1874
1875 drm_object_attach_property(&plane->base, prop, 0);1875 drm_object_attach_property(&plane->base, prop, 0);
drivers/gpu/drm/drm_vblank.c+21−31
@@ -551,7 +551,7 @@ int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs) · 550 unmodified lines
551 dev->num_crtcs = num_crtcs;551 dev->num_crtcs = num_crtcs;
552 552
553 for (i = 0; i < num_crtcs; i++) {553 for (i = 0; i < num_crtcs; i++) {
554 struct drm_vblank_crtc *vblank = &dev->vblank[i];554 struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, i);
555 555
556 vblank->dev = dev;556 vblank->dev = dev;
557 vblank->pipe = i;557 vblank->pipe = i;
@@ -605,7 +605,9 @@ EXPORT_SYMBOL(drm_dev_has_vblank); · 47 unmodified lines
605 */605 */
606wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc)606wait_queue_head_t *drm_crtc_vblank_waitqueue(struct drm_crtc *crtc)
607{607{
608 return &crtc->dev->vblank[drm_crtc_index(crtc)].queue;608 struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
609
610 return &vblank->queue;
609}611}
610EXPORT_SYMBOL(drm_crtc_vblank_waitqueue);612EXPORT_SYMBOL(drm_crtc_vblank_waitqueue);
611 613
@@ -710,7 +712,6 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal( · 98 unmodified lines
710{712{
711 struct drm_device *dev = crtc->dev;713 struct drm_device *dev = crtc->dev;
712 unsigned int pipe = crtc->index;714 unsigned int pipe = crtc->index;
713 struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
714 struct timespec64 ts_etime, ts_vblank_time;715 struct timespec64 ts_etime, ts_vblank_time;
715 ktime_t stime, etime;716 ktime_t stime, etime;
716 bool vbl_status;717 bool vbl_status;
@@ -729,10 +730,13 @@ drm_crtc_vblank_helper_get_vblank_timestamp_internal( · 12 unmodified lines
729 return false;730 return false;
730 }731 }
731 732
732 if (drm_drv_uses_atomic_modeset(dev))733 if (drm_drv_uses_atomic_modeset(dev)) {
734 struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
735
733 mode = &vblank->hwmode;736 mode = &vblank->hwmode;
734 else737 } else {
735 mode = &crtc->hwmode;738 mode = &crtc->hwmode;
739 }
736 740
737 /* If mode timing undefined, just return as no-op:741 /* If mode timing undefined, just return as no-op:
738 * Happens during initial modesetting of a crtc.742 * Happens during initial modesetting of a crtc.
@@ -1285,29 +1289,27 @@ void drm_crtc_vblank_put(struct drm_crtc *crtc) · 546 unmodified lines
1285EXPORT_SYMBOL(drm_crtc_vblank_put);1289EXPORT_SYMBOL(drm_crtc_vblank_put);
1286 1290
1287/**1291/**
1288 * drm_wait_one_vblank - wait for one vblank1292 * drm_crtc_wait_one_vblank - wait for one vblank
1289 * @dev: DRM device1293 * @crtc: DRM crtc
1290 * @pipe: CRTC index
1291 *1294 *
1292 * This waits for one vblank to pass on @pipe, using the irq driver interfaces.1295 * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
1293 * It is a failure to call this when the vblank irq for @pipe is disabled, e.g.1296 * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
1294 * due to lack of driver support or because the crtc is off.1297 * due to lack of driver support or because the crtc is off.
1295 *1298 *
1296 * This is the legacy version of drm_crtc_wait_one_vblank().1299 * Returns: 0 on success, negative error on failures.
1297 */1300 */
1298void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)1301int drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
1299{1302{
1300 struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);1303 struct drm_device *dev = crtc->dev;
1304 int pipe = drm_crtc_index(crtc);
1305 struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
1301 int ret;1306 int ret;
1302 u64 last;1307 u64 last;
1303 1308
1304 if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
1305 return;
1306
1307 ret = drm_vblank_get(dev, pipe);1309 ret = drm_vblank_get(dev, pipe);
1308 if (drm_WARN(dev, ret, "vblank not available on crtc %i, ret=%i\n",1310 if (drm_WARN(dev, ret, "vblank not available on crtc %i, ret=%i\n",
1309 pipe, ret))1311 pipe, ret))
1310 return;1312 return ret;
1311 1313
1312 last = drm_vblank_count(dev, pipe);1314 last = drm_vblank_count(dev, pipe);
1313 1315
@@ -1318,20 +1320,8 @@ void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) · 4 unmodified lines
1318 drm_WARN(dev, ret == 0, "vblank wait timed out on crtc %i\n", pipe);1320 drm_WARN(dev, ret == 0, "vblank wait timed out on crtc %i\n", pipe);
1319 1321
1320 drm_vblank_put(dev, pipe);1322 drm_vblank_put(dev, pipe);
1321}
1322EXPORT_SYMBOL(drm_wait_one_vblank);
1323 1323
1324/**1324 return ret ? 0 : -ETIMEDOUT;
1325 * drm_crtc_wait_one_vblank - wait for one vblank
1326 * @crtc: DRM crtc
1327 *
1328 * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
1329 * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
1330 * due to lack of driver support or because the crtc is off.
1331 */
1332void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
1333{
1334 drm_wait_one_vblank(crtc->dev, drm_crtc_index(crtc));
1335}1325}
1336EXPORT_SYMBOL(drm_crtc_wait_one_vblank);1326EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
1337 1327
@@ -1794,7 +1784,7 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, · 456 unmodified lines
1794 if (pipe >= dev->num_crtcs)1784 if (pipe >= dev->num_crtcs)
1795 return -EINVAL;1785 return -EINVAL;
1796 1786
1797 vblank = &dev->vblank[pipe];1787 vblank = drm_vblank_crtc(dev, pipe);
1798 1788
1799 /* If the counter is currently enabled and accurate, short-circuit1789 /* If the counter is currently enabled and accurate, short-circuit
1800 * queries to return the cached timestamp of the last vblank.1790 * queries to return the cached timestamp of the last vblank.
drivers/gpu/drm/hyperv/Kconfig+14−0
@@ -0,0 +1,14 @@
1# SPDX-License-Identifier: GPL-2.0-only
2config DRM_HYPERV
3 tristate "DRM Support for Hyper-V synthetic video device"
4 depends on DRM && PCI && HYPERV_VMBUS
5 select DRM_CLIENT_SELECTION
6 select DRM_KMS_HELPER
7 select DRM_GEM_SHMEM_HELPER
8 help
9 This is a KMS driver for Hyper-V synthetic video device. Choose this
10 option if you would like to enable drm driver for Hyper-V virtual
11 machine. Unselect Hyper-V framebuffer driver (CONFIG_FB_HYPERV) so
12 that DRM driver is used by default.
13
14 If M is selected the module will be called hyperv_drm.
drivers/gpu/drm/i915/Makefile+1−2
@@ -170,8 +170,7 @@ gem-y += \ · 169 unmodified lines
170 gem/i915_gem_ttm_move.o \170 gem/i915_gem_ttm_move.o \
171 gem/i915_gem_ttm_pm.o \171 gem/i915_gem_ttm_pm.o \
172 gem/i915_gem_userptr.o \172 gem/i915_gem_userptr.o \
173 gem/i915_gem_wait.o \173 gem/i915_gem_wait.o
174 gem/i915_gemfs.o
175i915-y += \174i915-y += \
176 $(gem-y) \175 $(gem-y) \
177 i915_active.o \176 i915_active.o \
drivers/gpu/drm/i915/gem/i915_gem_object_types.h+6−4
@@ -348,12 +348,13 @@ struct drm_i915_gem_object { · 347 unmodified lines
348 */348 */
349#define I915_BO_ALLOC_GPU_ONLY BIT(6)349#define I915_BO_ALLOC_GPU_ONLY BIT(6)
350#define I915_BO_ALLOC_CCS_AUX BIT(7)350#define I915_BO_ALLOC_CCS_AUX BIT(7)
351#define I915_BO_ALLOC_NOTHP BIT(8)
351/*352/*
352 * Object is allowed to retain its initial data and will not be cleared on first353 * Object is allowed to retain its initial data and will not be cleared on first
353 * access if used along with I915_BO_ALLOC_USER. This is mainly to keep354 * access if used along with I915_BO_ALLOC_USER. This is mainly to keep
354 * preallocated framebuffer data intact while transitioning it to i915drmfb.355 * preallocated framebuffer data intact while transitioning it to i915drmfb.
355 */356 */
356#define I915_BO_PREALLOC BIT(8)357#define I915_BO_PREALLOC BIT(9)
357#define I915_BO_ALLOC_FLAGS (I915_BO_ALLOC_CONTIGUOUS | \358#define I915_BO_ALLOC_FLAGS (I915_BO_ALLOC_CONTIGUOUS | \
358 I915_BO_ALLOC_VOLATILE | \359 I915_BO_ALLOC_VOLATILE | \
359 I915_BO_ALLOC_CPU_CLEAR | \360 I915_BO_ALLOC_CPU_CLEAR | \
@@ -362,10 +363,11 @@ struct drm_i915_gem_object { · 2 unmodified lines
362 I915_BO_ALLOC_PM_EARLY | \363 I915_BO_ALLOC_PM_EARLY | \
363 I915_BO_ALLOC_GPU_ONLY | \364 I915_BO_ALLOC_GPU_ONLY | \
364 I915_BO_ALLOC_CCS_AUX | \365 I915_BO_ALLOC_CCS_AUX | \
366 I915_BO_ALLOC_NOTHP | \
365 I915_BO_PREALLOC)367 I915_BO_PREALLOC)
366#define I915_BO_READONLY BIT(9)368#define I915_BO_READONLY BIT(10)
367#define I915_TILING_QUIRK_BIT 10 /* unknown swizzling; do not release! */369#define I915_TILING_QUIRK_BIT 11 /* unknown swizzling; do not release! */
368#define I915_BO_PROTECTED BIT(11)370#define I915_BO_PROTECTED BIT(12)
369 /**371 /**
370 * @mem_flags - Mutable placement-related flags372 * @mem_flags - Mutable placement-related flags
371 *373 *
drivers/gpu/drm/i915/gem/i915_gem_shmem.c+41−17
@@ -9,14 +9,16 @@ · 8 unmodified lines
9#include <linux/uio.h>9#include <linux/uio.h>
10 10
11#include <drm/drm_cache.h>11#include <drm/drm_cache.h>
12#include <drm/drm_gem.h>
13#include <drm/drm_print.h>
12 14
13#include "gem/i915_gem_region.h"15#include "gem/i915_gem_region.h"
14#include "i915_drv.h"16#include "i915_drv.h"
15#include "i915_gem_object.h"17#include "i915_gem_object.h"
16#include "i915_gem_tiling.h"18#include "i915_gem_tiling.h"
17#include "i915_gemfs.h"
18#include "i915_scatterlist.h"19#include "i915_scatterlist.h"
19#include "i915_trace.h"20#include "i915_trace.h"
21#include "i915_utils.h"
20 22
21/*23/*
22 * Move folios to appropriate lru and release the batch, decrementing the24 * Move folios to appropriate lru and release the batch, decrementing the
@@ -494,9 +496,11 @@ const struct drm_i915_gem_object_ops i915_gem_shmem_ops = { · 471 unmodified lines
494 496
495static int __create_shmem(struct drm_i915_private *i915,497static int __create_shmem(struct drm_i915_private *i915,
496 struct drm_gem_object *obj,498 struct drm_gem_object *obj,
497 resource_size_t size)499 resource_size_t size,
500 unsigned int flags)
498{501{
499 unsigned long flags = VM_NORESERVE;502 unsigned long shmem_flags = VM_NORESERVE;
503 struct vfsmount *huge_mnt;
500 struct file *filp;504 struct file *filp;
501 505
502 drm_gem_private_object_init(&i915->drm, obj, size);506 drm_gem_private_object_init(&i915->drm, obj, size);
@@ -515,11 +519,12 @@ static int __create_shmem(struct drm_i915_private *i915, · 12 unmodified lines
515 if (BITS_PER_LONG == 64 && size > MAX_LFS_FILESIZE)519 if (BITS_PER_LONG == 64 && size > MAX_LFS_FILESIZE)
516 return -E2BIG;520 return -E2BIG;
517 521
518 if (i915->mm.gemfs)522 huge_mnt = drm_gem_get_huge_mnt(&i915->drm);
519 filp = shmem_file_setup_with_mnt(i915->mm.gemfs, "i915", size,523 if (!(flags & I915_BO_ALLOC_NOTHP) && huge_mnt)
520 flags);524 filp = shmem_file_setup_with_mnt(huge_mnt, "i915", size,
525 shmem_flags);
521 else526 else
522 filp = shmem_file_setup("i915", size, flags);527 filp = shmem_file_setup("i915", size, shmem_flags);
523 if (IS_ERR(filp))528 if (IS_ERR(filp))
524 return PTR_ERR(filp);529 return PTR_ERR(filp);
525 530
@@ -548,7 +553,7 @@ static int shmem_object_init(struct intel_memory_region *mem, · 22 unmodified lines
548 gfp_t mask;553 gfp_t mask;
549 int ret;554 int ret;
550 555
551 ret = __create_shmem(i915, &obj->base, size);556 ret = __create_shmem(i915, &obj->base, size, flags);
552 if (ret)557 if (ret)
553 return ret;558 return ret;
554 559
@@ -644,21 +649,40 @@ fail: · 89 unmodified lines
644 649
645static int init_shmem(struct intel_memory_region *mem)650static int init_shmem(struct intel_memory_region *mem)
646{651{
647 i915_gemfs_init(mem->i915);652 struct drm_i915_private *i915 = mem->i915;
648 intel_memory_region_set_name(mem, "system");
649 653
650 return 0; /* We have fallback to the kernel mnt if gemfs init failed. */654 /*
651}655 * By creating our own shmemfs mountpoint, we can pass in
656 * mount flags that better match our usecase.
657 *
658 * One example, although it is probably better with a per-file
659 * control, is selecting huge page allocations ("huge=within_size").
660 * However, we only do so on platforms which benefit from it, or to
661 * offset the overhead of iommu lookups, where with latter it is a net
662 * win even on platforms which would otherwise see some performance
663 * regressions such a slow reads issue on Broadwell and Skylake.
664 */
652 665
653static int release_shmem(struct intel_memory_region *mem)666 if (GRAPHICS_VER(i915) < 11 && !i915_vtd_active(i915))
654{667 goto no_thp;
655 i915_gemfs_fini(mem->i915);668
656 return 0;669 drm_gem_huge_mnt_create(&i915->drm, "within_size");
670 if (drm_gem_get_huge_mnt(&i915->drm))
671 drm_info(&i915->drm, "Using Transparent Hugepages\n");
672 else
673 drm_notice(&i915->drm,
674 "Transparent Hugepage support is recommended for optimal performance%s\n",
675 GRAPHICS_VER(i915) >= 11 ? " on this platform!" :
676 " when IOMMU is enabled!");
677
678 no_thp:
679 intel_memory_region_set_name(mem, "system");
680
681 return 0; /* We have fallback to the kernel mnt if huge mnt failed. */
657}682}
658 683
659static const struct intel_memory_region_ops shmem_region_ops = {684static const struct intel_memory_region_ops shmem_region_ops = {
660 .init = init_shmem,685 .init = init_shmem,
661 .release = release_shmem,
662 .init_object = shmem_object_init,686 .init_object = shmem_object_init,
663};687};
664 688
drivers/gpu/drm/i915/gem/i915_gemfs.c+0−71
@@ -1,71 +0,0 @@
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2017 Intel Corporation
4 */
5
6#include <linux/fs.h>
7#include <linux/mount.h>
8#include <linux/fs_context.h>
9
10#include <drm/drm_print.h>
11
12#include "i915_drv.h"
13#include "i915_gemfs.h"
14#include "i915_utils.h"
15
16void i915_gemfs_init(struct drm_i915_private *i915)
17{
18 struct file_system_type *type;
19 struct fs_context *fc;
20 struct vfsmount *gemfs;
21 int ret;
22
23 /*
24 * By creating our own shmemfs mountpoint, we can pass in
25 * mount flags that better match our usecase.
26 *
27 * One example, although it is probably better with a per-file
28 * control, is selecting huge page allocations ("huge=within_size").
29 * However, we only do so on platforms which benefit from it, or to
30 * offset the overhead of iommu lookups, where with latter it is a net
31 * win even on platforms which would otherwise see some performance
32 * regressions such a slow reads issue on Broadwell and Skylake.
33 */
34
35 if (GRAPHICS_VER(i915) < 11 && !i915_vtd_active(i915))
36 return;
37
38 if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
39 goto err;
40
41 type = get_fs_type("tmpfs");
42 if (!type)
43 goto err;
44
45 fc = fs_context_for_mount(type, SB_KERNMOUNT);
46 if (IS_ERR(fc))
47 goto err;
48 ret = vfs_parse_fs_string(fc, "source", "tmpfs");
49 if (!ret)
50 ret = vfs_parse_fs_string(fc, "huge", "within_size");
51 if (!ret)
52 gemfs = fc_mount_longterm(fc);
53 put_fs_context(fc);
54 if (ret)
55 goto err;
56
57 i915->mm.gemfs = gemfs;
58 drm_info(&i915->drm, "Using Transparent Hugepages\n");
59 return;
60
61err:
62 drm_notice(&i915->drm,
63 "Transparent Hugepage support is recommended for optimal performance%s\n",
64 GRAPHICS_VER(i915) >= 11 ? " on this platform!" :
65 " when IOMMU is enabled!");
66}
67
68void i915_gemfs_fini(struct drm_i915_private *i915)
69{
70 kern_unmount(i915->mm.gemfs);
71}
drivers/gpu/drm/i915/gem/i915_gemfs.h+0−14
@@ -1,14 +0,0 @@
1/* SPDX-License-Identifier: MIT */
2/*
3 * Copyright © 2017 Intel Corporation
4 */
5
6#ifndef __I915_GEMFS_H__
7#define __I915_GEMFS_H__
8
9struct drm_i915_private;
10
11void i915_gemfs_init(struct drm_i915_private *i915);
12void i915_gemfs_fini(struct drm_i915_private *i915);
13
14#endif
drivers/gpu/drm/i915/gem/selftests/huge_pages.c+3−12
@@ -1316,7 +1316,7 @@ typedef struct drm_i915_gem_object * · 1315 unmodified lines
1316 1316
1317static inline bool igt_can_allocate_thp(struct drm_i915_private *i915)1317static inline bool igt_can_allocate_thp(struct drm_i915_private *i915)
1318{1318{
1319 return i915->mm.gemfs && has_transparent_hugepage();1319 return !!drm_gem_get_huge_mnt(&i915->drm);
1320}1320}
1321 1321
1322static struct drm_i915_gem_object *1322static struct drm_i915_gem_object *
@@ -1761,7 +1761,6 @@ static int igt_tmpfs_fallback(void *arg) · 438 unmodified lines
1761 struct drm_i915_private *i915 = arg;1761 struct drm_i915_private *i915 = arg;
1762 struct i915_address_space *vm;1762 struct i915_address_space *vm;
1763 struct i915_gem_context *ctx;1763 struct i915_gem_context *ctx;
1764 struct vfsmount *gemfs = i915->mm.gemfs;
1765 struct drm_i915_gem_object *obj;1764 struct drm_i915_gem_object *obj;
1766 struct i915_vma *vma;1765 struct i915_vma *vma;
1767 struct file *file;1766 struct file *file;
@@ -1779,15 +1778,8 @@ static int igt_tmpfs_fallback(void *arg) · 11 unmodified lines
1779 }1778 }
1780 vm = i915_gem_context_get_eb_vm(ctx);1779 vm = i915_gem_context_get_eb_vm(ctx);
1781 1780
1782 /*1781 obj = i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_SMEM],
1783 * Make sure that we don't burst into a ball of flames upon falling back1782 PAGE_SIZE, 0, I915_BO_ALLOC_NOTHP);
1784 * to tmpfs, which we rely on if on the off-chance we encounter a failure
1785 * when setting up gemfs.
1786 */
1787
1788 i915->mm.gemfs = NULL;
1789
1790 obj = i915_gem_object_create_shmem(i915, PAGE_SIZE);
1791 if (IS_ERR(obj)) {1783 if (IS_ERR(obj)) {
1792 err = PTR_ERR(obj);1784 err = PTR_ERR(obj);
1793 goto out_restore;1785 goto out_restore;
@@ -1819,7 +1811,6 @@ static int igt_tmpfs_fallback(void *arg) · 25 unmodified lines
1819out_put:1811out_put:
1820 i915_gem_object_put(obj);1812 i915_gem_object_put(obj);
1821out_restore:1813out_restore:
1822 i915->mm.gemfs = gemfs;
1823 1814
1824 i915_vm_put(vm);1815 i915_vm_put(vm);
1825out:1816out:
drivers/gpu/drm/i915/i915_drv.h+0−5
@@ -141,11 +141,6 @@ struct i915_gem_mm { · 140 unmodified lines
141 */141 */
142 atomic_t free_count;142 atomic_t free_count;
143 143
144 /**
145 * tmpfs instance used for shmem backed objects
146 */
147 struct vfsmount *gemfs;
148
149 struct intel_memory_region *regions[INTEL_REGION_UNKNOWN];144 struct intel_memory_region *regions[INTEL_REGION_UNKNOWN];
150 145
151 struct notifier_block oom_notifier;146 struct notifier_block oom_notifier;
drivers/gpu/drm/nouveau/dispnv04/crtc.c+4−20
@@ -837,7 +837,7 @@ nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, · 836 unmodified lines
837static int837static int
838nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,838nv04_crtc_do_mode_set_base(struct drm_crtc *crtc,
839 struct drm_framebuffer *passed_fb,839 struct drm_framebuffer *passed_fb,
840 int x, int y, bool atomic)840 int x, int y)
841{841{
842 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);842 struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
843 struct drm_device *dev = crtc->dev;843 struct drm_device *dev = crtc->dev;
@@ -850,19 +850,12 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, · 6 unmodified lines
850 NV_DEBUG(drm, "index %d\n", nv_crtc->index);850 NV_DEBUG(drm, "index %d\n", nv_crtc->index);
851 851
852 /* no fb bound */852 /* no fb bound */
853 if (!atomic && !crtc->primary->fb) {853 if (!crtc->primary->fb) {
854 NV_DEBUG(drm, "No FB bound\n");854 NV_DEBUG(drm, "No FB bound\n");
855 return 0;855 return 0;
856 }856 }
857 857
858 /* If atomic, we want to switch to the fb we were passed, so858 drm_fb = crtc->primary->fb;
859 * now we update pointers to do that.
860 */
861 if (atomic) {
862 drm_fb = passed_fb;
863 } else {
864 drm_fb = crtc->primary->fb;
865 }
866 859
867 nvbo = nouveau_gem_object(drm_fb->obj[0]);860 nvbo = nouveau_gem_object(drm_fb->obj[0]);
868 nv_crtc->fb.offset = nvbo->offset;861 nv_crtc->fb.offset = nvbo->offset;
@@ -920,15 +913,7 @@ nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, · 51 unmodified lines
920 int ret = nv_crtc_swap_fbs(crtc, old_fb);913 int ret = nv_crtc_swap_fbs(crtc, old_fb);
921 if (ret)914 if (ret)
922 return ret;915 return ret;
923 return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y, false);916 return nv04_crtc_do_mode_set_base(crtc, old_fb, x, y);
924}
925
926static int
927nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
928 struct drm_framebuffer *fb,
929 int x, int y, enum mode_set_atomic state)
930{
931 return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true);
932}917}
933 918
934static void nv04_cursor_upload(struct drm_device *dev, struct nouveau_bo *src,919static void nv04_cursor_upload(struct drm_device *dev, struct nouveau_bo *src,
@@ -1274,7 +1259,6 @@ static const struct drm_crtc_helper_funcs nv04_crtc_helper_funcs = { · 339 unmodified lines
1274 .commit = nv_crtc_commit,1259 .commit = nv_crtc_commit,
1275 .mode_set = nv_crtc_mode_set,1260 .mode_set = nv_crtc_mode_set,
1276 .mode_set_base = nv04_crtc_mode_set_base,1261 .mode_set_base = nv04_crtc_mode_set_base,
1277 .mode_set_base_atomic = nv04_crtc_mode_set_base_atomic,
1278 .disable = nv_crtc_disable,1262 .disable = nv_crtc_disable,
1279 .get_scanout_position = nouveau_display_scanoutpos,1263 .get_scanout_position = nouveau_display_scanoutpos,
1280};1264};
drivers/gpu/drm/panel/panel-edp.c+3−0
@@ -1880,6 +1880,7 @@ static const struct panel_delay delay_80_500_e50_d50 = { · 1879 unmodified lines
1880 */1880 */
1881static const struct edp_panel_entry edp_panels[] = {1881static const struct edp_panel_entry edp_panels[] = {
1882 EDP_PANEL_ENTRY('A', 'U', 'O', 0x04a4, &delay_200_500_e50, "B122UAN01.0"),1882 EDP_PANEL_ENTRY('A', 'U', 'O', 0x04a4, &delay_200_500_e50, "B122UAN01.0"),
1883 EDP_PANEL_ENTRY('A', 'U', 'O', 0x0ba4, &delay_200_500_e50, "B140QAX01.H"),
1883 EDP_PANEL_ENTRY('A', 'U', 'O', 0x105c, &delay_200_500_e50, "B116XTN01.0"),1884 EDP_PANEL_ENTRY('A', 'U', 'O', 0x105c, &delay_200_500_e50, "B116XTN01.0"),
1884 EDP_PANEL_ENTRY('A', 'U', 'O', 0x1062, &delay_200_500_e50, "B120XAN01.0"),1885 EDP_PANEL_ENTRY('A', 'U', 'O', 0x1062, &delay_200_500_e50, "B120XAN01.0"),
1885 EDP_PANEL_ENTRY('A', 'U', 'O', 0x125c, &delay_200_500_e50, "Unknown"),1886 EDP_PANEL_ENTRY('A', 'U', 'O', 0x125c, &delay_200_500_e50, "Unknown"),
@@ -1904,6 +1905,7 @@ static const struct edp_panel_entry edp_panels[] = { · 18 unmodified lines
1904 EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"),1905 EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"),
1905 EDP_PANEL_ENTRY('A', 'U', 'O', 0x635c, &delay_200_500_e50, "B116XAN06.3"),1906 EDP_PANEL_ENTRY('A', 'U', 'O', 0x635c, &delay_200_500_e50, "B116XAN06.3"),
1906 EDP_PANEL_ENTRY('A', 'U', 'O', 0x639c, &delay_200_500_e50, "B140HAK02.7"),1907 EDP_PANEL_ENTRY('A', 'U', 'O', 0x639c, &delay_200_500_e50, "B140HAK02.7"),
1908 EDP_PANEL_ENTRY('A', 'U', 'O', 0x643d, &delay_200_500_e50, "B140HAN06.4"),
1907 EDP_PANEL_ENTRY('A', 'U', 'O', 0x723c, &delay_200_500_e50, "B140XTN07.2"),1909 EDP_PANEL_ENTRY('A', 'U', 'O', 0x723c, &delay_200_500_e50, "B140XTN07.2"),
1908 EDP_PANEL_ENTRY('A', 'U', 'O', 0x73aa, &delay_200_500_e50, "B116XTN02.3"),1910 EDP_PANEL_ENTRY('A', 'U', 'O', 0x73aa, &delay_200_500_e50, "B116XTN02.3"),
1909 EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"),1911 EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"),
@@ -2033,6 +2035,7 @@ static const struct edp_panel_entry edp_panels[] = { · 123 unmodified lines
2033 EDP_PANEL_ENTRY('C', 'S', 'W', 0x1462, &delay_200_500_e50, "MNE007QS5-2"),2035 EDP_PANEL_ENTRY('C', 'S', 'W', 0x1462, &delay_200_500_e50, "MNE007QS5-2"),
2034 EDP_PANEL_ENTRY('C', 'S', 'W', 0x1468, &delay_200_500_e50, "MNE007QB2-2"),2036 EDP_PANEL_ENTRY('C', 'S', 'W', 0x1468, &delay_200_500_e50, "MNE007QB2-2"),
2035 EDP_PANEL_ENTRY('C', 'S', 'W', 0x146e, &delay_80_500_e50_d50, "MNE007QB3-1"),2037 EDP_PANEL_ENTRY('C', 'S', 'W', 0x146e, &delay_80_500_e50_d50, "MNE007QB3-1"),
2038 EDP_PANEL_ENTRY('C', 'S', 'W', 0x147c, &delay_200_500_e50_d100, "MNE007QB3-1"),
2036 EDP_PANEL_ENTRY('C', 'S', 'W', 0x1519, &delay_200_500_e80_d50, "MNF601BS1-3"),2039 EDP_PANEL_ENTRY('C', 'S', 'W', 0x1519, &delay_200_500_e80_d50, "MNF601BS1-3"),
2037 2040
2038 EDP_PANEL_ENTRY('E', 'T', 'C', 0x0000, &delay_50_500_e200_d200_po2e335, "LP079QX1-SP0V"),2041 EDP_PANEL_ENTRY('E', 'T', 'C', 0x0000, &delay_50_500_e200_d200_po2e335, "LP079QX1-SP0V"),
drivers/gpu/drm/panfrost/panfrost_device.c+3−0
@@ -12,6 +12,7 @@ · 11 unmodified lines
12#include "panfrost_device.h"12#include "panfrost_device.h"
13#include "panfrost_devfreq.h"13#include "panfrost_devfreq.h"
14#include "panfrost_features.h"14#include "panfrost_features.h"
15#include "panfrost_gem.h"
15#include "panfrost_issues.h"16#include "panfrost_issues.h"
16#include "panfrost_gpu.h"17#include "panfrost_gpu.h"
17#include "panfrost_job.h"18#include "panfrost_job.h"
@@ -267,6 +268,8 @@ int panfrost_device_init(struct panfrost_device *pfdev) · 249 unmodified lines
267 if (err)268 if (err)
268 goto out_job;269 goto out_job;
269 270
271 panfrost_gem_init(pfdev);
272
270 return 0;273 return 0;
271out_job:274out_job:
272 panfrost_jm_fini(pfdev);275 panfrost_jm_fini(pfdev);
drivers/gpu/drm/panfrost/panfrost_device.h+1−0
@@ -79,6 +79,7 @@ struct panfrost_features { · 78 unmodified lines
79 u32 thread_max_workgroup_sz;79 u32 thread_max_workgroup_sz;
80 u32 thread_max_barrier_sz;80 u32 thread_max_barrier_sz;
81 u32 coherency_features;81 u32 coherency_features;
82 u32 selected_coherency;
82 u32 afbc_features;83 u32 afbc_features;
83 u32 texture_features[4];84 u32 texture_features[4];
84 u32 js_features[16];85 u32 js_features[16];
drivers/gpu/drm/panfrost/panfrost_drv.c+104−3
@@ -95,6 +95,7 @@ static int panfrost_ioctl_get_param(struct drm_device *ddev, void *data, struct · 94 unmodified lines
95 PANFROST_FEATURE_ARRAY(JS_FEATURES, js_features, 15);95 PANFROST_FEATURE_ARRAY(JS_FEATURES, js_features, 15);
96 PANFROST_FEATURE(NR_CORE_GROUPS, nr_core_groups);96 PANFROST_FEATURE(NR_CORE_GROUPS, nr_core_groups);
97 PANFROST_FEATURE(THREAD_TLS_ALLOC, thread_tls_alloc);97 PANFROST_FEATURE(THREAD_TLS_ALLOC, thread_tls_alloc);
98 PANFROST_FEATURE(SELECTED_COHERENCY, selected_coherency);
98 99
99 case DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP:100 case DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP:
100 ret = panfrost_ioctl_query_timestamp(pfdev, &param->value);101 ret = panfrost_ioctl_query_timestamp(pfdev, &param->value);
@@ -125,6 +126,10 @@ static int panfrost_ioctl_get_param(struct drm_device *ddev, void *data, struct · 24 unmodified lines
125 return 0;126 return 0;
126}127}
127 128
129#define PANFROST_BO_FLAGS (PANFROST_BO_NOEXEC | \
130 PANFROST_BO_HEAP | \
131 PANFROST_BO_WB_MMAP)
132
128static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data,133static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data,
129 struct drm_file *file)134 struct drm_file *file)
130{135{
@@ -134,8 +139,7 @@ static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, · 3 unmodified lines
134 struct panfrost_gem_mapping *mapping;139 struct panfrost_gem_mapping *mapping;
135 int ret;140 int ret;
136 141
137 if (!args->size || args->pad ||142 if (!args->size || args->pad || (args->flags & ~PANFROST_BO_FLAGS))
138 (args->flags & ~(PANFROST_BO_NOEXEC | PANFROST_BO_HEAP)))
139 return -EINVAL;143 return -EINVAL;
140 144
141 /* Heaps should never be executable */145 /* Heaps should never be executable */
@@ -579,6 +583,91 @@ static int panfrost_ioctl_jm_ctx_destroy(struct drm_device *dev, void *data, · 437 unmodified lines
579 return panfrost_jm_ctx_destroy(file, args->handle);583 return panfrost_jm_ctx_destroy(file, args->handle);
580}584}
581 585
586static int panfrost_ioctl_sync_bo(struct drm_device *ddev, void *data,
587 struct drm_file *file)
588{
589 struct drm_panfrost_sync_bo *args = data;
590 struct drm_panfrost_bo_sync_op *ops;
591 struct drm_gem_object *obj;
592 int ret;
593 u32 i;
594
595 if (args->pad)
596 return -EINVAL;
597
598 if (!args->op_count)
599 return 0;
600
601 ops = kvmalloc_array(args->op_count, sizeof(*ops), GFP_KERNEL);
602 if (!ops) {
603 DRM_DEBUG("Failed to allocate incoming BO sync ops array\n");
604 return -ENOMEM;
605 }
606
607 if (copy_from_user(ops, (void __user *)(uintptr_t)args->ops,
608 args->op_count * sizeof(*ops))) {
609 DRM_DEBUG("Failed to copy in BO sync ops\n");
610 ret = -EFAULT;
611 goto err_ops;
612 }
613
614 for (i = 0; i < args->op_count; i++) {
615 obj = drm_gem_object_lookup(file, ops[i].handle);
616 if (!obj) {
617 ret = -ENOENT;
618 goto err_ops;
619 }
620
621 ret = panfrost_gem_sync(obj, ops[i].type,
622 ops[i].offset, ops[i].size);
623
624 drm_gem_object_put(obj);
625
626 if (ret)
627 goto err_ops;
628 }
629
630err_ops:
631 kvfree(ops);
632
633 return ret;
634}
635
636static int panfrost_ioctl_query_bo_info(struct drm_device *dev, void *data,
637 struct drm_file *file_priv)
638{
639 struct drm_panfrost_query_bo_info *args = data;
640 struct drm_gem_object *gem_obj;
641 struct panfrost_gem_object *bo;
642
643 gem_obj = drm_gem_object_lookup(file_priv, args->handle);
644 if (!gem_obj) {
645 DRM_DEBUG("Failed to look up GEM BO %d\n", args->handle);
646 return -ENOENT;
647 }
648
649 bo = to_panfrost_bo(gem_obj);
650 args->pad = 0;
651 args->create_flags = 0;
652 args->extra_flags = 0;
653
654 if (drm_gem_is_imported(gem_obj)) {
655 args->extra_flags |= DRM_PANFROST_BO_IS_IMPORTED;
656 } else {
657 if (bo->noexec)
658 args->create_flags |= PANFROST_BO_NOEXEC;
659
660 if (bo->is_heap)
661 args->create_flags |= PANFROST_BO_HEAP;
662
663 if (!bo->base.map_wc)
664 args->create_flags |= PANFROST_BO_WB_MMAP;
665 }
666
667 drm_gem_object_put(gem_obj);
668 return 0;
669}
670
582int panfrost_unstable_ioctl_check(void)671int panfrost_unstable_ioctl_check(void)
583{672{
584 if (!unstable_ioctls)673 if (!unstable_ioctls)
@@ -648,6 +737,8 @@ static const struct drm_ioctl_desc panfrost_drm_driver_ioctls[] = { · 63 unmodified lines
648 PANFROST_IOCTL(SET_LABEL_BO, set_label_bo, DRM_RENDER_ALLOW),737 PANFROST_IOCTL(SET_LABEL_BO, set_label_bo, DRM_RENDER_ALLOW),
649 PANFROST_IOCTL(JM_CTX_CREATE, jm_ctx_create, DRM_RENDER_ALLOW),738 PANFROST_IOCTL(JM_CTX_CREATE, jm_ctx_create, DRM_RENDER_ALLOW),
650 PANFROST_IOCTL(JM_CTX_DESTROY, jm_ctx_destroy, DRM_RENDER_ALLOW),739 PANFROST_IOCTL(JM_CTX_DESTROY, jm_ctx_destroy, DRM_RENDER_ALLOW),
740 PANFROST_IOCTL(SYNC_BO, sync_bo, DRM_RENDER_ALLOW),
741 PANFROST_IOCTL(QUERY_BO_INFO, query_bo_info, DRM_RENDER_ALLOW),
651};742};
652 743
653static void panfrost_gpu_show_fdinfo(struct panfrost_device *pfdev,744static void panfrost_gpu_show_fdinfo(struct panfrost_device *pfdev,
@@ -837,6 +928,9 @@ static void panfrost_debugfs_init(struct drm_minor *minor) · 183 unmodified lines
837 * - 1.4 - adds SET_LABEL_BO928 * - 1.4 - adds SET_LABEL_BO
838 * - 1.5 - adds JM_CTX_{CREATE,DESTROY} ioctls and extend SUBMIT to allow929 * - 1.5 - adds JM_CTX_{CREATE,DESTROY} ioctls and extend SUBMIT to allow
839 * context creation with configurable priorities/affinity930 * context creation with configurable priorities/affinity
931 * - 1.6 - adds PANFROST_BO_MAP_WB, PANFROST_IOCTL_SYNC_BO,
932 * PANFROST_IOCTL_QUERY_BO_INFO and
933 * DRM_PANFROST_PARAM_SELECTED_COHERENCY
840 */934 */
841static const struct drm_driver panfrost_drm_driver = {935static const struct drm_driver panfrost_drm_driver = {
842 .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ,936 .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ,
@@ -849,15 +943,22 @@ static const struct drm_driver panfrost_drm_driver = { · 6 unmodified lines
849 .name = "panfrost",943 .name = "panfrost",
850 .desc = "panfrost DRM",944 .desc = "panfrost DRM",
851 .major = 1,945 .major = 1,
852 .minor = 5,946 .minor = 6,
853 947
854 .gem_create_object = panfrost_gem_create_object,948 .gem_create_object = panfrost_gem_create_object,
949 .gem_prime_import = panfrost_gem_prime_import,
855 .gem_prime_import_sg_table = panfrost_gem_prime_import_sg_table,950 .gem_prime_import_sg_table = panfrost_gem_prime_import_sg_table,
856#ifdef CONFIG_DEBUG_FS951#ifdef CONFIG_DEBUG_FS
857 .debugfs_init = panfrost_debugfs_init,952 .debugfs_init = panfrost_debugfs_init,
858#endif953#endif
859};954};
860 955
956#ifdef CONFIG_TRANSPARENT_HUGEPAGE
957bool panfrost_transparent_hugepage = true;
958module_param_named(transparent_hugepage, panfrost_transparent_hugepage, bool, 0400);
959MODULE_PARM_DESC(transparent_hugepage, "Use a dedicated tmpfs mount point with Transparent Hugepage enabled (true = default)");
960#endif
961
861static int panfrost_probe(struct platform_device *pdev)962static int panfrost_probe(struct platform_device *pdev)
862{963{
863 struct panfrost_device *pfdev;964 struct panfrost_device *pfdev;
drivers/gpu/drm/panfrost/panfrost_drv.h+9−0
@@ -0,0 +1,9 @@
1/* SPDX-License-Identifier: GPL-2.0 or MIT */
2/* Copyright 2025 Amazon.com, Inc. or its affiliates */
3
4#ifndef __PANFROST_DRV_H__
5#define __PANFROST_DRV_H__
6
7extern bool panfrost_transparent_hugepage;
8
9#endif
drivers/gpu/drm/panfrost/panfrost_gem.c+257−0
@@ -1,5 +1,6 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2/* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */2/* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
3/* Copyright 2025 Amazon.com, Inc. or its affiliates */
3 4
4#include <linux/cleanup.h>5#include <linux/cleanup.h>
5#include <linux/err.h>6#include <linux/err.h>
@@ -10,9 +11,26 @@ · 4 unmodified lines
10#include <drm/panfrost_drm.h>11#include <drm/panfrost_drm.h>
11#include <drm/drm_print.h>12#include <drm/drm_print.h>
12#include "panfrost_device.h"13#include "panfrost_device.h"
14#include "panfrost_drv.h"
13#include "panfrost_gem.h"15#include "panfrost_gem.h"
14#include "panfrost_mmu.h"16#include "panfrost_mmu.h"
15 17
18void panfrost_gem_init(struct panfrost_device *pfdev)
19{
20 int err;
21
22 if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
23 !panfrost_transparent_hugepage)
24 return;
25
26 err = drm_gem_huge_mnt_create(&pfdev->base, "within_size");
27 if (drm_gem_get_huge_mnt(&pfdev->base))
28 drm_info(&pfdev->base, "Using Transparent Hugepage\n");
29 else if (err)
30 drm_warn(&pfdev->base, "Can't use Transparent Hugepage (%d)\n",
31 err);
32}
33
16#ifdef CONFIG_DEBUG_FS34#ifdef CONFIG_DEBUG_FS
17static void panfrost_gem_debugfs_bo_add(struct panfrost_device *pfdev,35static void panfrost_gem_debugfs_bo_add(struct panfrost_device *pfdev,
18 struct panfrost_gem_object *bo)36 struct panfrost_gem_object *bo)
@@ -259,6 +277,128 @@ static size_t panfrost_gem_rss(struct drm_gem_object *obj) · 240 unmodified lines
259 return 0;277 return 0;
260}278}
261 279
280static struct sg_table *
281panfrost_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
282 enum dma_data_direction dir)
283{
284 struct sg_table *sgt = drm_gem_map_dma_buf(attach, dir);
285
286 if (!IS_ERR(sgt))
287 attach->priv = sgt;
288
289 return sgt;
290}
291
292static void
293panfrost_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
294 struct sg_table *sgt,
295 enum dma_data_direction dir)
296{
297 attach->priv = NULL;
298 drm_gem_unmap_dma_buf(attach, sgt, dir);
299}
300
301static int
302panfrost_gem_prime_begin_cpu_access(struct dma_buf *dma_buf,
303 enum dma_data_direction dir)
304{
305 struct drm_gem_object *obj = dma_buf->priv;
306 struct drm_device *dev = obj->dev;
307 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
308 struct dma_buf_attachment *attach;
309
310 dma_resv_lock(obj->resv, NULL);
311 if (shmem->sgt)
312 dma_sync_sgtable_for_cpu(dev->dev, shmem->sgt, dir);
313
314 if (shmem->vaddr)
315 invalidate_kernel_vmap_range(shmem->vaddr, shmem->base.size);
316
317 list_for_each_entry(attach, &dma_buf->attachments, node) {
318 struct sg_table *sgt = attach->priv;
319
320 if (sgt)
321 dma_sync_sgtable_for_cpu(attach->dev, sgt, dir);
322 }
323 dma_resv_unlock(obj->resv);
324
325 return 0;
326}
327
328static int
329panfrost_gem_prime_end_cpu_access(struct dma_buf *dma_buf,
330 enum dma_data_direction dir)
331{
332 struct drm_gem_object *obj = dma_buf->priv;
333 struct drm_device *dev = obj->dev;
334 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
335 struct dma_buf_attachment *attach;
336
337 dma_resv_lock(obj->resv, NULL);
338 list_for_each_entry(attach, &dma_buf->attachments, node) {
339 struct sg_table *sgt = attach->priv;
340
341 if (sgt)
342 dma_sync_sgtable_for_device(attach->dev, sgt, dir);
343 }
344
345 if (shmem->vaddr)
346 flush_kernel_vmap_range(shmem->vaddr, shmem->base.size);
347
348 if (shmem->sgt)
349 dma_sync_sgtable_for_device(dev->dev, shmem->sgt, dir);
350
351 dma_resv_unlock(obj->resv);
352 return 0;
353}
354
355static const struct dma_buf_ops panfrost_dma_buf_ops = {
356 .attach = drm_gem_map_attach,
357 .detach = drm_gem_map_detach,
358 .map_dma_buf = panfrost_gem_prime_map_dma_buf,
359 .unmap_dma_buf = panfrost_gem_prime_unmap_dma_buf,
360 .release = drm_gem_dmabuf_release,
361 .mmap = drm_gem_dmabuf_mmap,
362 .vmap = drm_gem_dmabuf_vmap,
363 .vunmap = drm_gem_dmabuf_vunmap,
364 .begin_cpu_access = panfrost_gem_prime_begin_cpu_access,
365 .end_cpu_access = panfrost_gem_prime_end_cpu_access,
366};
367
368static struct dma_buf *
369panfrost_gem_prime_export(struct drm_gem_object *obj, int flags)
370{
371 struct drm_device *dev = obj->dev;
372 struct dma_buf_export_info exp_info = {
373 .exp_name = KBUILD_MODNAME,
374 .owner = THIS_MODULE,
375 .ops = &panfrost_dma_buf_ops,
376 .size = obj->size,
377 .flags = flags,
378 .priv = obj,
379 .resv = obj->resv,
380 };
381
382 return drm_gem_dmabuf_export(dev, &exp_info);
383}
384
385struct drm_gem_object *
386panfrost_gem_prime_import(struct drm_device *dev,
387 struct dma_buf *dma_buf)
388{
389 struct drm_gem_object *obj = dma_buf->priv;
390
391 if (dma_buf->ops == &panfrost_dma_buf_ops && obj->dev == dev) {
392 /* Importing dmabuf exported from our own gem increases
393 * refcount on gem itself instead of f_count of dmabuf.
394 */
395 drm_gem_object_get(obj);
396 return obj;
397 }
398
399 return drm_gem_prime_import(dev, dma_buf);
400}
401
262static const struct drm_gem_object_funcs panfrost_gem_funcs = {402static const struct drm_gem_object_funcs panfrost_gem_funcs = {
263 .free = panfrost_gem_free_object,403 .free = panfrost_gem_free_object,
264 .open = panfrost_gem_open,404 .open = panfrost_gem_open,
@@ -267,6 +407,7 @@ static const struct drm_gem_object_funcs panfrost_gem_funcs = { · 2 unmodified lines
267 .pin = panfrost_gem_pin,407 .pin = panfrost_gem_pin,
268 .unpin = drm_gem_shmem_object_unpin,408 .unpin = drm_gem_shmem_object_unpin,
269 .get_sg_table = drm_gem_shmem_object_get_sg_table,409 .get_sg_table = drm_gem_shmem_object_get_sg_table,
410 .export = panfrost_gem_prime_export,
270 .vmap = drm_gem_shmem_object_vmap,411 .vmap = drm_gem_shmem_object_vmap,
271 .vunmap = drm_gem_shmem_object_vunmap,412 .vunmap = drm_gem_shmem_object_vunmap,
272 .mmap = drm_gem_shmem_object_mmap,413 .mmap = drm_gem_shmem_object_mmap,
@@ -303,12 +444,42 @@ struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t · 30 unmodified lines
303 return &obj->base.base;444 return &obj->base.base;
304}445}
305 446
447static bool
448should_map_wc(struct panfrost_gem_object *bo)
449{
450 struct panfrost_device *pfdev = to_panfrost_device(bo->base.base.dev);
451
452 /* We can't do uncached mappings if the device is coherent,
453 * because the zeroing done by the shmem layer at page allocation
454 * time happens on a cached mapping which isn't CPU-flushed (at least
455 * not on Arm64 where the flush is deferred to PTE setup time, and
456 * only done conditionally based on the mapping permissions). We can't
457 * rely on dma_map_sgtable()/dma_sync_sgtable_for_xxx() either to flush
458 * those, because they are NOPed if dma_dev_coherent() returns true.
459 */
460 if (pfdev->coherent)
461 return false;
462
463 /* Cached mappings are explicitly requested, so no write-combine. */
464 if (bo->wb_mmap)
465 return false;
466
467 /* The default is write-combine. */
468 return true;
469}
470
306struct panfrost_gem_object *471struct panfrost_gem_object *
307panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags)472panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags)
308{473{
309 struct drm_gem_shmem_object *shmem;474 struct drm_gem_shmem_object *shmem;
310 struct panfrost_gem_object *bo;475 struct panfrost_gem_object *bo;
311 476
477 /* The heap buffer is not supposed to be CPU-visible, so don't allow
478 * WB_MMAP on those.
479 */
480 if ((flags & PANFROST_BO_HEAP) && (flags & PANFROST_BO_WB_MMAP))
481 return ERR_PTR(-EINVAL);
482
312 /* Round up heap allocations to 2MB to keep fault handling simple */483 /* Round up heap allocations to 2MB to keep fault handling simple */
313 if (flags & PANFROST_BO_HEAP)484 if (flags & PANFROST_BO_HEAP)
314 size = roundup(size, SZ_2M);485 size = roundup(size, SZ_2M);
@@ -320,6 +491,8 @@ panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags) · 5 unmodified lines
320 bo = to_panfrost_bo(&shmem->base);491 bo = to_panfrost_bo(&shmem->base);
321 bo->noexec = !!(flags & PANFROST_BO_NOEXEC);492 bo->noexec = !!(flags & PANFROST_BO_NOEXEC);
322 bo->is_heap = !!(flags & PANFROST_BO_HEAP);493 bo->is_heap = !!(flags & PANFROST_BO_HEAP);
494 bo->wb_mmap = !!(flags & PANFROST_BO_WB_MMAP);
495 bo->base.map_wc = should_map_wc(bo);
323 496
324 return bo;497 return bo;
325}498}
@@ -366,6 +539,90 @@ panfrost_gem_set_label(struct drm_gem_object *obj, const char *label) · 40 unmodified lines
366 kfree_const(old_label);539 kfree_const(old_label);
367}540}
368 541
542int
543panfrost_gem_sync(struct drm_gem_object *obj, u32 type, u32 offset, u32 size)
544{
545 struct panfrost_gem_object *bo = to_panfrost_bo(obj);
546 struct drm_gem_shmem_object *shmem = &bo->base;
547 const struct drm_device *dev = shmem->base.dev;
548 struct sg_table *sgt;
549 struct scatterlist *sgl;
550 unsigned int count;
551
552 /* Make sure the range is in bounds. */
553 if (offset + size < offset || offset + size > shmem->base.size)
554 return -EINVAL;
555
556 /* Disallow CPU-cache maintenance on imported buffers. */
557 if (drm_gem_is_imported(&shmem->base))
558 return -EINVAL;
559
560 switch (type) {
561 case PANFROST_BO_SYNC_CPU_CACHE_FLUSH:
562 case PANFROST_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE:
563 break;
564
565 default:
566 return -EINVAL;
567 }
568
569 /* Don't bother if it's WC-mapped */
570 if (shmem->map_wc)
571 return 0;
572
573 /* Nothing to do if the size is zero. */
574 if (size == 0)
575 return 0;
576
577 sgt = drm_gem_shmem_get_pages_sgt(shmem);
578 if (IS_ERR(sgt))
579 return PTR_ERR(sgt);
580
581 for_each_sgtable_dma_sg(sgt, sgl, count) {
582 if (size == 0)
583 break;
584
585 dma_addr_t paddr = sg_dma_address(sgl);
586 size_t len = sg_dma_len(sgl);
587
588 if (len <= offset) {
589 offset -= len;
590 continue;
591 }
592
593 paddr += offset;
594 len -= offset;
595 len = min_t(size_t, len, size);
596 size -= len;
597 offset = 0;
598
599 /* It's unclear whether dma_sync_xxx() is the right API to do CPU
600 * cache maintenance given an IOMMU can register their own
601 * implementation doing more than just CPU cache flushes/invalidation,
602 * and what we really care about here is CPU caches only, but that's
603 * the best we have that is both arch-agnostic and does at least the
604 * CPU cache maintenance on a <page,offset,size> tuple.
605 *
606 * Also, I wish we could do a single
607 *
608 * dma_sync_single_for_device(BIDIR)
609 *
610 * and get a flush+invalidate, but that's not how it's implemented
611 * in practice (at least on arm64), so we have to make it
612 *
613 * dma_sync_single_for_device(TO_DEVICE)
614 * dma_sync_single_for_cpu(FROM_DEVICE)
615 *
616 * for the flush+invalidate case.
617 */
618 dma_sync_single_for_device(dev->dev, paddr, len, DMA_TO_DEVICE);
619 if (type == PANFROST_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE)
620 dma_sync_single_for_cpu(dev->dev, paddr, len, DMA_FROM_DEVICE);
621 }
622
623 return 0;
624}
625
369void626void
370panfrost_gem_internal_set_label(struct drm_gem_object *obj, const char *label)627panfrost_gem_internal_set_label(struct drm_gem_object *obj, const char *label)
371{628{
drivers/gpu/drm/panfrost/panfrost_gem.h+12−0
@@ -98,6 +98,11 @@ struct panfrost_gem_object { · 97 unmodified lines
98 bool noexec :1;98 bool noexec :1;
99 bool is_heap :1;99 bool is_heap :1;
100 100
101 /* On coherent devices, this reflects the creation flags, not the true
102 * cacheability attribute of the mapping.
103 */
104 bool wb_mmap :1;
105
101#ifdef CONFIG_DEBUG_FS106#ifdef CONFIG_DEBUG_FS
102 struct panfrost_gem_debugfs debugfs;107 struct panfrost_gem_debugfs debugfs;
103#endif108#endif
@@ -124,12 +129,17 @@ drm_mm_node_to_panfrost_mapping(struct drm_mm_node *node) · 20 unmodified lines
124 return container_of(node, struct panfrost_gem_mapping, mmnode);129 return container_of(node, struct panfrost_gem_mapping, mmnode);
125}130}
126 131
132void panfrost_gem_init(struct panfrost_device *pfdev);
133
127struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t size);134struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t size);
128 135
129struct drm_gem_object *136struct drm_gem_object *
130panfrost_gem_prime_import_sg_table(struct drm_device *dev,137panfrost_gem_prime_import_sg_table(struct drm_device *dev,
131 struct dma_buf_attachment *attach,138 struct dma_buf_attachment *attach,
132 struct sg_table *sgt);139 struct sg_table *sgt);
140struct drm_gem_object *
141panfrost_gem_prime_import(struct drm_device *dev,
142 struct dma_buf *dma_buf);
133 143
134struct panfrost_gem_object *144struct panfrost_gem_object *
135panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags);145panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags);
@@ -148,6 +158,8 @@ int panfrost_gem_shrinker_init(struct drm_device *dev); · 12 unmodified lines
148void panfrost_gem_shrinker_cleanup(struct drm_device *dev);158void panfrost_gem_shrinker_cleanup(struct drm_device *dev);
149 159
150void panfrost_gem_set_label(struct drm_gem_object *obj, const char *label);160void panfrost_gem_set_label(struct drm_gem_object *obj, const char *label);
161int panfrost_gem_sync(struct drm_gem_object *obj, u32 type,
162 u32 offset, u32 size);
151void panfrost_gem_internal_set_label(struct drm_gem_object *obj, const char *label);163void panfrost_gem_internal_set_label(struct drm_gem_object *obj, const char *label);
152 164
153#ifdef CONFIG_DEBUG_FS165#ifdef CONFIG_DEBUG_FS
drivers/gpu/drm/panfrost/panfrost_gpu.c+23−3
@@ -159,8 +159,8 @@ static void panfrost_gpu_init_quirks(struct panfrost_device *pfdev) · 158 unmodified lines
159 pfdev->features.revision >= 0x2000)159 pfdev->features.revision >= 0x2000)
160 quirks |= JM_MAX_JOB_THROTTLE_LIMIT << JM_JOB_THROTTLE_LIMIT_SHIFT;160 quirks |= JM_MAX_JOB_THROTTLE_LIMIT << JM_JOB_THROTTLE_LIMIT_SHIFT;
161 else if (panfrost_model_eq(pfdev, 0x6000) &&161 else if (panfrost_model_eq(pfdev, 0x6000) &&
162 pfdev->features.coherency_features == COHERENCY_ACE)162 pfdev->features.coherency_features == BIT(COHERENCY_ACE))
163 quirks |= (COHERENCY_ACE_LITE | COHERENCY_ACE) <<163 quirks |= (BIT(COHERENCY_ACE_LITE) | BIT(COHERENCY_ACE)) <<
164 JM_FORCE_COHERENCY_FEATURES_SHIFT;164 JM_FORCE_COHERENCY_FEATURES_SHIFT;
165 165
166 if (panfrost_has_hw_feature(pfdev, HW_FEATURE_IDVS_GROUP_SIZE))166 if (panfrost_has_hw_feature(pfdev, HW_FEATURE_IDVS_GROUP_SIZE))
@@ -263,7 +263,27 @@ static int panfrost_gpu_init_features(struct panfrost_device *pfdev) · 96 unmodified lines
263 pfdev->features.max_threads = gpu_read(pfdev, GPU_THREAD_MAX_THREADS);263 pfdev->features.max_threads = gpu_read(pfdev, GPU_THREAD_MAX_THREADS);
264 pfdev->features.thread_max_workgroup_sz = gpu_read(pfdev, GPU_THREAD_MAX_WORKGROUP_SIZE);264 pfdev->features.thread_max_workgroup_sz = gpu_read(pfdev, GPU_THREAD_MAX_WORKGROUP_SIZE);
265 pfdev->features.thread_max_barrier_sz = gpu_read(pfdev, GPU_THREAD_MAX_BARRIER_SIZE);265 pfdev->features.thread_max_barrier_sz = gpu_read(pfdev, GPU_THREAD_MAX_BARRIER_SIZE);
266 pfdev->features.coherency_features = gpu_read(pfdev, GPU_COHERENCY_FEATURES);266
267 if (panfrost_has_hw_feature(pfdev, HW_FEATURE_COHERENCY_REG))
268 pfdev->features.coherency_features = gpu_read(pfdev, GPU_COHERENCY_FEATURES);
269 else
270 pfdev->features.coherency_features = BIT(COHERENCY_ACE_LITE);
271
272 BUILD_BUG_ON(COHERENCY_ACE_LITE != DRM_PANFROST_GPU_COHERENCY_ACE_LITE);
273 BUILD_BUG_ON(COHERENCY_ACE != DRM_PANFROST_GPU_COHERENCY_ACE);
274 BUILD_BUG_ON(COHERENCY_NONE != DRM_PANFROST_GPU_COHERENCY_NONE);
275
276 if (!pfdev->coherent) {
277 pfdev->features.selected_coherency = COHERENCY_NONE;
278 } else if (pfdev->features.coherency_features & BIT(COHERENCY_ACE)) {
279 pfdev->features.selected_coherency = COHERENCY_ACE;
280 } else if (pfdev->features.coherency_features & BIT(COHERENCY_ACE_LITE)) {
281 pfdev->features.selected_coherency = COHERENCY_ACE_LITE;
282 } else {
283 drm_WARN(&pfdev->base, true, "No known coherency protocol supported");
284 pfdev->features.selected_coherency = COHERENCY_NONE;
285 }
286
267 pfdev->features.afbc_features = gpu_read(pfdev, GPU_AFBC_FEATURES);287 pfdev->features.afbc_features = gpu_read(pfdev, GPU_AFBC_FEATURES);
268 for (i = 0; i < 4; i++)288 for (i = 0; i < 4; i++)
269 pfdev->features.texture_features[i] = gpu_read(pfdev, GPU_TEXTURE_FEATURES(i));289 pfdev->features.texture_features[i] = gpu_read(pfdev, GPU_TEXTURE_FEATURES(i));
drivers/gpu/drm/panfrost/panfrost_regs.h+8−2
@@ -102,9 +102,15 @@ · 101 unmodified lines
102#define GPU_L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */102#define GPU_L2_PRESENT_LO 0x120 /* (RO) Level 2 cache present bitmap, low word */
103#define GPU_L2_PRESENT_HI 0x124 /* (RO) Level 2 cache present bitmap, high word */103#define GPU_L2_PRESENT_HI 0x124 /* (RO) Level 2 cache present bitmap, high word */
104 104
105/* GPU_COHERENCY_FEATURES is a bitmask of BIT(COHERENCY_xxx) values encoding the
106 * set of supported coherency protocols. GPU_COHERENCY_ENABLE is passed a
107 * COHERENCY_xxx value.
108 */
105#define GPU_COHERENCY_FEATURES 0x300 /* (RO) Coherency features present */109#define GPU_COHERENCY_FEATURES 0x300 /* (RO) Coherency features present */
106#define COHERENCY_ACE_LITE BIT(0)110#define GPU_COHERENCY_ENABLE 0x304 /* (RW) Coherency protocol selection */
107#define COHERENCY_ACE BIT(1)111#define COHERENCY_ACE_LITE 0
112#define COHERENCY_ACE 1
113#define COHERENCY_NONE 31
108 114
109#define GPU_STACK_PRESENT_LO 0xE00 /* (RO) Core stack present bitmap, low word */115#define GPU_STACK_PRESENT_LO 0xE00 /* (RO) Core stack present bitmap, low word */
110#define GPU_STACK_PRESENT_HI 0xE04 /* (RO) Core stack present bitmap, high word */116#define GPU_STACK_PRESENT_HI 0xE04 /* (RO) Core stack present bitmap, high word */
drivers/gpu/drm/panthor/panthor_device.c+12−1
@@ -18,6 +18,7 @@ · 17 unmodified lines
18#include "panthor_devfreq.h"18#include "panthor_devfreq.h"
19#include "panthor_device.h"19#include "panthor_device.h"
20#include "panthor_fw.h"20#include "panthor_fw.h"
21#include "panthor_gem.h"
21#include "panthor_gpu.h"22#include "panthor_gpu.h"
22#include "panthor_hw.h"23#include "panthor_hw.h"
23#include "panthor_mmu.h"24#include "panthor_mmu.h"
@@ -27,6 +28,12 @@ · 3 unmodified lines
27 28
28static int panthor_gpu_coherency_init(struct panthor_device *ptdev)29static int panthor_gpu_coherency_init(struct panthor_device *ptdev)
29{30{
31 BUILD_BUG_ON(GPU_COHERENCY_NONE != DRM_PANTHOR_GPU_COHERENCY_NONE);
32 BUILD_BUG_ON(GPU_COHERENCY_ACE_LITE != DRM_PANTHOR_GPU_COHERENCY_ACE_LITE);
33 BUILD_BUG_ON(GPU_COHERENCY_ACE != DRM_PANTHOR_GPU_COHERENCY_ACE);
34
35 /* Start with no coherency, and update it if the device is flagged coherent. */
36 ptdev->gpu_info.selected_coherency = GPU_COHERENCY_NONE;
30 ptdev->coherent = device_get_dma_attr(ptdev->base.dev) == DEV_DMA_COHERENT;37 ptdev->coherent = device_get_dma_attr(ptdev->base.dev) == DEV_DMA_COHERENT;
31 38
32 if (!ptdev->coherent)39 if (!ptdev->coherent)
@@ -36,8 +43,10 @@ static int panthor_gpu_coherency_init(struct panthor_device *ptdev) · 3 unmodified lines
36 * ACE protocol has never been supported for command stream frontend GPUs.43 * ACE protocol has never been supported for command stream frontend GPUs.
37 */44 */
38 if ((gpu_read(ptdev, GPU_COHERENCY_FEATURES) &45 if ((gpu_read(ptdev, GPU_COHERENCY_FEATURES) &
39 GPU_COHERENCY_PROT_BIT(ACE_LITE)))46 GPU_COHERENCY_PROT_BIT(ACE_LITE))) {
47 ptdev->gpu_info.selected_coherency = GPU_COHERENCY_ACE_LITE;
40 return 0;48 return 0;
49 }
41 50
42 drm_err(&ptdev->base, "Coherency not supported by the device");51 drm_err(&ptdev->base, "Coherency not supported by the device");
43 return -ENOTSUPP;52 return -ENOTSUPP;
@@ -294,6 +303,8 @@ int panthor_device_init(struct panthor_device *ptdev) · 250 unmodified lines
294 if (ret)303 if (ret)
295 goto err_unplug_fw;304 goto err_unplug_fw;
296 305
306 panthor_gem_init(ptdev);
307
297 /* ~3 frames */308 /* ~3 frames */
298 pm_runtime_set_autosuspend_delay(ptdev->base.dev, 50);309 pm_runtime_set_autosuspend_delay(ptdev->base.dev, 50);
299 pm_runtime_use_autosuspend(ptdev->base.dev);310 pm_runtime_use_autosuspend(ptdev->base.dev);
drivers/gpu/drm/panthor/panthor_drv.c+84−3
@@ -177,7 +177,8 @@ panthor_get_uobj_array(const struct drm_panthor_obj_array *in, u32 min_stride, · 176 unmodified lines
177 PANTHOR_UOBJ_DECL(struct drm_panthor_sync_op, timeline_value), \177 PANTHOR_UOBJ_DECL(struct drm_panthor_sync_op, timeline_value), \
178 PANTHOR_UOBJ_DECL(struct drm_panthor_queue_submit, syncs), \178 PANTHOR_UOBJ_DECL(struct drm_panthor_queue_submit, syncs), \
179 PANTHOR_UOBJ_DECL(struct drm_panthor_queue_create, ringbuf_size), \179 PANTHOR_UOBJ_DECL(struct drm_panthor_queue_create, ringbuf_size), \
180 PANTHOR_UOBJ_DECL(struct drm_panthor_vm_bind_op, syncs))180 PANTHOR_UOBJ_DECL(struct drm_panthor_vm_bind_op, syncs), \
181 PANTHOR_UOBJ_DECL(struct drm_panthor_bo_sync_op, size))
181 182
182/**183/**
183 * PANTHOR_UOBJ_SET() - Copy a kernel object to a user object.184 * PANTHOR_UOBJ_SET() - Copy a kernel object to a user object.
@@ -901,7 +902,8 @@ static int panthor_ioctl_vm_destroy(struct drm_device *ddev, void *data, · 717 unmodified lines
901 return panthor_vm_pool_destroy_vm(pfile->vms, args->id);902 return panthor_vm_pool_destroy_vm(pfile->vms, args->id);
902}903}
903 904
904#define PANTHOR_BO_FLAGS DRM_PANTHOR_BO_NO_MMAP905#define PANTHOR_BO_FLAGS (DRM_PANTHOR_BO_NO_MMAP | \
906 DRM_PANTHOR_BO_WB_MMAP)
905 907
906static int panthor_ioctl_bo_create(struct drm_device *ddev, void *data,908static int panthor_ioctl_bo_create(struct drm_device *ddev, void *data,
907 struct drm_file *file)909 struct drm_file *file)
@@ -920,6 +922,10 @@ static int panthor_ioctl_bo_create(struct drm_device *ddev, void *data, · 12 unmodified lines
920 goto out_dev_exit;922 goto out_dev_exit;
921 }923 }
922 924
925 if ((args->flags & DRM_PANTHOR_BO_NO_MMAP) &&
926 (args->flags & DRM_PANTHOR_BO_WB_MMAP))
927 return -EINVAL;
928
923 if (args->exclusive_vm_id) {929 if (args->exclusive_vm_id) {
924 vm = panthor_vm_pool_get_vm(pfile->vms, args->exclusive_vm_id);930 vm = panthor_vm_pool_get_vm(pfile->vms, args->exclusive_vm_id);
925 if (!vm) {931 if (!vm) {
@@ -1396,6 +1402,66 @@ static int panthor_ioctl_set_user_mmio_offset(struct drm_device *ddev, · 470 unmodified lines
1396 return 0;1402 return 0;
1397}1403}
1398 1404
1405static int panthor_ioctl_bo_sync(struct drm_device *ddev, void *data,
1406 struct drm_file *file)
1407{
1408 struct drm_panthor_bo_sync *args = data;
1409 struct drm_panthor_bo_sync_op *ops;
1410 struct drm_gem_object *obj;
1411 int ret;
1412
1413 if (!args->ops.count)
1414 return 0;
1415
1416 ret = PANTHOR_UOBJ_GET_ARRAY(ops, &args->ops);
1417 if (ret)
1418 return ret;
1419
1420 for (u32 i = 0; i < args->ops.count; i++) {
1421 obj = drm_gem_object_lookup(file, ops[i].handle);
1422 if (!obj) {
1423 ret = -ENOENT;
1424 goto err_ops;
1425 }
1426
1427 ret = panthor_gem_sync(obj, ops[i].type, ops[i].offset,
1428 ops[i].size);
1429
1430 drm_gem_object_put(obj);
1431
1432 if (ret)
1433 goto err_ops;
1434 }
1435
1436err_ops:
1437 kvfree(ops);
1438
1439 return ret;
1440}
1441
1442static int panthor_ioctl_bo_query_info(struct drm_device *ddev, void *data,
1443 struct drm_file *file)
1444{
1445 struct drm_panthor_bo_query_info *args = data;
1446 struct panthor_gem_object *bo;
1447 struct drm_gem_object *obj;
1448
1449 obj = drm_gem_object_lookup(file, args->handle);
1450 if (!obj)
1451 return -ENOENT;
1452
1453 bo = to_panthor_bo(obj);
1454 args->pad = 0;
1455 args->create_flags = bo->flags;
1456
1457 args->extra_flags = 0;
1458 if (drm_gem_is_imported(&bo->base.base))
1459 args->extra_flags |= DRM_PANTHOR_BO_IS_IMPORTED;
1460
1461 drm_gem_object_put(obj);
1462 return 0;
1463}
1464
1399static int1465static int
1400panthor_open(struct drm_device *ddev, struct drm_file *file)1466panthor_open(struct drm_device *ddev, struct drm_file *file)
1401{1467{
@@ -1470,6 +1536,8 @@ static const struct drm_ioctl_desc panthor_drm_driver_ioctls[] = { · 68 unmodified lines
1470 PANTHOR_IOCTL(GROUP_SUBMIT, group_submit, DRM_RENDER_ALLOW),1536 PANTHOR_IOCTL(GROUP_SUBMIT, group_submit, DRM_RENDER_ALLOW),
1471 PANTHOR_IOCTL(BO_SET_LABEL, bo_set_label, DRM_RENDER_ALLOW),1537 PANTHOR_IOCTL(BO_SET_LABEL, bo_set_label, DRM_RENDER_ALLOW),
1472 PANTHOR_IOCTL(SET_USER_MMIO_OFFSET, set_user_mmio_offset, DRM_RENDER_ALLOW),1538 PANTHOR_IOCTL(SET_USER_MMIO_OFFSET, set_user_mmio_offset, DRM_RENDER_ALLOW),
1539 PANTHOR_IOCTL(BO_SYNC, bo_sync, DRM_RENDER_ALLOW),
1540 PANTHOR_IOCTL(BO_QUERY_INFO, bo_query_info, DRM_RENDER_ALLOW),
1473};1541};
1474 1542
1475static int panthor_mmap(struct file *filp, struct vm_area_struct *vma)1543static int panthor_mmap(struct file *filp, struct vm_area_struct *vma)
@@ -1559,6 +1627,7 @@ static const struct file_operations panthor_drm_driver_fops = { · 83 unmodified lines
1559 .read = drm_read,1627 .read = drm_read,
1560 .llseek = noop_llseek,1628 .llseek = noop_llseek,
1561 .mmap = panthor_mmap,1629 .mmap = panthor_mmap,
1630 .get_unmapped_area = drm_gem_get_unmapped_area,
1562 .show_fdinfo = drm_show_fdinfo,1631 .show_fdinfo = drm_show_fdinfo,
1563 .fop_flags = FOP_UNSIGNED_OFFSET,1632 .fop_flags = FOP_UNSIGNED_OFFSET,
1564};1633};
@@ -1604,6 +1673,11 @@ static void panthor_debugfs_init(struct drm_minor *minor) · 39 unmodified lines
1604 * - 1.3 - adds DRM_PANTHOR_GROUP_STATE_INNOCENT flag1673 * - 1.3 - adds DRM_PANTHOR_GROUP_STATE_INNOCENT flag
1605 * - 1.4 - adds DRM_IOCTL_PANTHOR_BO_SET_LABEL ioctl1674 * - 1.4 - adds DRM_IOCTL_PANTHOR_BO_SET_LABEL ioctl
1606 * - 1.5 - adds DRM_PANTHOR_SET_USER_MMIO_OFFSET ioctl1675 * - 1.5 - adds DRM_PANTHOR_SET_USER_MMIO_OFFSET ioctl
1676 * - 1.6 - enables GLB_COUNTER_EN
1677 * - 1.7 - adds DRM_PANTHOR_BO_WB_MMAP flag
1678 * - adds DRM_IOCTL_PANTHOR_BO_SYNC ioctl
1679 * - adds DRM_IOCTL_PANTHOR_BO_QUERY_INFO ioctl
1680 * - adds drm_panthor_gpu_info::selected_coherency
1607 */1681 */
1608static const struct drm_driver panthor_drm_driver = {1682static const struct drm_driver panthor_drm_driver = {
1609 .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ |1683 .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ |
@@ -1617,15 +1691,22 @@ static const struct drm_driver panthor_drm_driver = { · 7 unmodified lines
1617 .name = "panthor",1691 .name = "panthor",
1618 .desc = "Panthor DRM driver",1692 .desc = "Panthor DRM driver",
1619 .major = 1,1693 .major = 1,
1620 .minor = 5,1694 .minor = 7,
1621 1695
1622 .gem_create_object = panthor_gem_create_object,1696 .gem_create_object = panthor_gem_create_object,
1623 .gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table,1697 .gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table,
1698 .gem_prime_import = panthor_gem_prime_import,
1624#ifdef CONFIG_DEBUG_FS1699#ifdef CONFIG_DEBUG_FS
1625 .debugfs_init = panthor_debugfs_init,1700 .debugfs_init = panthor_debugfs_init,
1626#endif1701#endif
1627};1702};
1628 1703
1704#ifdef CONFIG_TRANSPARENT_HUGEPAGE
1705bool panthor_transparent_hugepage = true;
1706module_param_named(transparent_hugepage, panthor_transparent_hugepage, bool, 0400);
1707MODULE_PARM_DESC(transparent_hugepage, "Use a dedicated tmpfs mount point with Transparent Hugepage enabled (true = default)");
1708#endif
1709
1629static int panthor_probe(struct platform_device *pdev)1710static int panthor_probe(struct platform_device *pdev)
1630{1711{
1631 struct panthor_device *ptdev;1712 struct panthor_device *ptdev;
drivers/gpu/drm/panthor/panthor_drv.h+9−0
@@ -0,0 +1,9 @@
1/* SPDX-License-Identifier: GPL-2.0 or MIT */
2/* Copyright 2025 Amazon.com, Inc. or its affiliates */
3
4#ifndef __PANTHOR_DRV_H__
5#define __PANTHOR_DRV_H__
6
7extern bool panthor_transparent_hugepage;
8
9#endif
drivers/gpu/drm/panthor/panthor_fw.c+2−2
@@ -1044,7 +1044,8 @@ static void panthor_fw_init_global_iface(struct panthor_device *ptdev) · 1043 unmodified lines
1044 if (panthor_fw_has_glb_state(ptdev))1044 if (panthor_fw_has_glb_state(ptdev))
1045 glb_iface->input->ack_irq_mask |= GLB_STATE_MASK;1045 glb_iface->input->ack_irq_mask |= GLB_STATE_MASK;
1046 1046
1047 panthor_fw_update_reqs(glb_iface, req, GLB_IDLE_EN, GLB_IDLE_EN);1047 panthor_fw_update_reqs(glb_iface, req, GLB_IDLE_EN | GLB_COUNTER_EN,
1048 GLB_IDLE_EN | GLB_COUNTER_EN);
1048 panthor_fw_toggle_reqs(glb_iface, req, ack,1049 panthor_fw_toggle_reqs(glb_iface, req, ack,
1049 GLB_CFG_ALLOC_EN |1050 GLB_CFG_ALLOC_EN |
1050 GLB_CFG_POWEROFF_TIMER |1051 GLB_CFG_POWEROFF_TIMER |
@@ -1187,7 +1188,6 @@ void panthor_fw_pre_reset(struct panthor_device *ptdev, bool on_hang) · 136 unmodified lines
1187 else1188 else
1188 ptdev->reset.fast = true;1189 ptdev->reset.fast = true;
1189 }1190 }
1190 panthor_fw_stop(ptdev);
1191 1191
1192 panthor_job_irq_suspend(&ptdev->fw->irq);1192 panthor_job_irq_suspend(&ptdev->fw->irq);
1193 panthor_fw_stop(ptdev);1193 panthor_fw_stop(ptdev);
drivers/gpu/drm/panthor/panthor_gem.c+255−3
@@ -1,6 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0 or MIT1// SPDX-License-Identifier: GPL-2.0 or MIT
2/* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */2/* Copyright 2019 Linaro, Ltd, Rob Herring <robh@kernel.org> */
3/* Copyright 2023 Collabora ltd. */3/* Copyright 2023 Collabora ltd. */
4/* Copyright 2025 Amazon.com, Inc. or its affiliates */
4 5
5#include <linux/cleanup.h>6#include <linux/cleanup.h>
6#include <linux/dma-buf.h>7#include <linux/dma-buf.h>
@@ -12,10 +13,27 @@ · 5 unmodified lines
12#include <drm/panthor_drm.h>13#include <drm/panthor_drm.h>
13 14
14#include "panthor_device.h"15#include "panthor_device.h"
16#include "panthor_drv.h"
15#include "panthor_fw.h"17#include "panthor_fw.h"
16#include "panthor_gem.h"18#include "panthor_gem.h"
17#include "panthor_mmu.h"19#include "panthor_mmu.h"
18 20
21void panthor_gem_init(struct panthor_device *ptdev)
22{
23 int err;
24
25 if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
26 !panthor_transparent_hugepage)
27 return;
28
29 err = drm_gem_huge_mnt_create(&ptdev->base, "within_size");
30 if (drm_gem_get_huge_mnt(&ptdev->base))
31 drm_info(&ptdev->base, "Using Transparent Hugepage\n");
32 else if (err)
33 drm_warn(&ptdev->base, "Can't use Transparent Hugepage (%d)\n",
34 err);
35}
36
19#ifdef CONFIG_DEBUG_FS37#ifdef CONFIG_DEBUG_FS
20static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo)38static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo)
21{39{
@@ -59,6 +77,39 @@ static void panthor_gem_debugfs_set_usage_flags(struct panthor_gem_object *bo, u · 37 unmodified lines
59static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo) {}77static void panthor_gem_debugfs_bo_init(struct panthor_gem_object *bo) {}
60#endif78#endif
61 79
80static bool
81should_map_wc(struct panthor_gem_object *bo, struct panthor_vm *exclusive_vm)
82{
83 struct panthor_device *ptdev = container_of(bo->base.base.dev, struct panthor_device, base);
84
85 /* We can't do uncached mappings if the device is coherent,
86 * because the zeroing done by the shmem layer at page allocation
87 * time happens on a cached mapping which isn't CPU-flushed (at least
88 * not on Arm64 where the flush is deferred to PTE setup time, and
89 * only done conditionally based on the mapping permissions). We can't
90 * rely on dma_map_sgtable()/dma_sync_sgtable_for_xxx() either to flush
91 * those, because they are NOPed if dma_dev_coherent() returns true.
92 *
93 * FIXME: Note that this problem is going to pop up again when we
94 * decide to support mapping buffers with the NO_MMAP flag as
95 * non-shareable (AKA buffers accessed only by the GPU), because we
96 * need the same CPU flush to happen after page allocation, otherwise
97 * there's a risk of data leak or late corruption caused by a dirty
98 * cacheline being evicted. At this point we'll need a way to force
99 * CPU cache maintenance regardless of whether the device is coherent
100 * or not.
101 */
102 if (ptdev->coherent)
103 return false;
104
105 /* Cached mappings are explicitly requested, so no write-combine. */
106 if (bo->flags & DRM_PANTHOR_BO_WB_MMAP)
107 return false;
108
109 /* The default is write-combine. */
110 return true;
111}
112
62static void panthor_gem_free_object(struct drm_gem_object *obj)113static void panthor_gem_free_object(struct drm_gem_object *obj)
63{114{
64 struct panthor_gem_object *bo = to_panthor_bo(obj);115 struct panthor_gem_object *bo = to_panthor_bo(obj);
@@ -145,6 +196,7 @@ panthor_kernel_bo_create(struct panthor_device *ptdev, struct panthor_vm *vm, · 80 unmodified lines
145 bo = to_panthor_bo(&obj->base);196 bo = to_panthor_bo(&obj->base);
146 kbo->obj = &obj->base;197 kbo->obj = &obj->base;
147 bo->flags = bo_flags;198 bo->flags = bo_flags;
199 bo->base.map_wc = should_map_wc(bo, vm);
148 bo->exclusive_vm_root_gem = panthor_vm_root_gem(vm);200 bo->exclusive_vm_root_gem = panthor_vm_root_gem(vm);
149 drm_gem_object_get(bo->exclusive_vm_root_gem);201 drm_gem_object_get(bo->exclusive_vm_root_gem);
150 bo->base.base.resv = bo->exclusive_vm_root_gem->resv;202 bo->base.base.resv = bo->exclusive_vm_root_gem->resv;
@@ -184,14 +236,130 @@ err_free_bo: · 33 unmodified lines
184 return ERR_PTR(ret);236 return ERR_PTR(ret);
185}237}
186 238
239static struct sg_table *
240panthor_gem_prime_map_dma_buf(struct dma_buf_attachment *attach,
241 enum dma_data_direction dir)
242{
243 struct sg_table *sgt = drm_gem_map_dma_buf(attach, dir);
244
245 if (!IS_ERR(sgt))
246 attach->priv = sgt;
247
248 return sgt;
249}
250
251static void
252panthor_gem_prime_unmap_dma_buf(struct dma_buf_attachment *attach,
253 struct sg_table *sgt,
254 enum dma_data_direction dir)
255{
256 attach->priv = NULL;
257 drm_gem_unmap_dma_buf(attach, sgt, dir);
258}
259
260static int
261panthor_gem_prime_begin_cpu_access(struct dma_buf *dma_buf,
262 enum dma_data_direction dir)
263{
264 struct drm_gem_object *obj = dma_buf->priv;
265 struct drm_device *dev = obj->dev;
266 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
267 struct dma_buf_attachment *attach;
268
269 dma_resv_lock(obj->resv, NULL);
270 if (shmem->sgt)
271 dma_sync_sgtable_for_cpu(dev->dev, shmem->sgt, dir);
272
273 if (shmem->vaddr)
274 invalidate_kernel_vmap_range(shmem->vaddr, shmem->base.size);
275
276 list_for_each_entry(attach, &dma_buf->attachments, node) {
277 struct sg_table *sgt = attach->priv;
278
279 if (sgt)
280 dma_sync_sgtable_for_cpu(attach->dev, sgt, dir);
281 }
282 dma_resv_unlock(obj->resv);
283
284 return 0;
285}
286
287static int
288panthor_gem_prime_end_cpu_access(struct dma_buf *dma_buf,
289 enum dma_data_direction dir)
290{
291 struct drm_gem_object *obj = dma_buf->priv;
292 struct drm_device *dev = obj->dev;
293 struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
294 struct dma_buf_attachment *attach;
295
296 dma_resv_lock(obj->resv, NULL);
297 list_for_each_entry(attach, &dma_buf->attachments, node) {
298 struct sg_table *sgt = attach->priv;
299
300 if (sgt)
301 dma_sync_sgtable_for_device(attach->dev, sgt, dir);
302 }
303
304 if (shmem->vaddr)
305 flush_kernel_vmap_range(shmem->vaddr, shmem->base.size);
306
307 if (shmem->sgt)
308 dma_sync_sgtable_for_device(dev->dev, shmem->sgt, dir);
309
310 dma_resv_unlock(obj->resv);
311 return 0;
312}
313
314static const struct dma_buf_ops panthor_dma_buf_ops = {
315 .attach = drm_gem_map_attach,
316 .detach = drm_gem_map_detach,
317 .map_dma_buf = panthor_gem_prime_map_dma_buf,
318 .unmap_dma_buf = panthor_gem_prime_unmap_dma_buf,
319 .release = drm_gem_dmabuf_release,
320 .mmap = drm_gem_dmabuf_mmap,
321 .vmap = drm_gem_dmabuf_vmap,
322 .vunmap = drm_gem_dmabuf_vunmap,
323 .begin_cpu_access = panthor_gem_prime_begin_cpu_access,
324 .end_cpu_access = panthor_gem_prime_end_cpu_access,
325};
326
187static struct dma_buf *327static struct dma_buf *
188panthor_gem_prime_export(struct drm_gem_object *obj, int flags)328panthor_gem_prime_export(struct drm_gem_object *obj, int flags)
189{329{
330 struct drm_device *dev = obj->dev;
331 struct dma_buf_export_info exp_info = {
332 .exp_name = KBUILD_MODNAME,
333 .owner = THIS_MODULE,
334 .ops = &panthor_dma_buf_ops,
335 .size = obj->size,
336 .flags = flags,
337 .priv = obj,
338 .resv = obj->resv,
339 };
340
190 /* We can't export GEMs that have an exclusive VM. */341 /* We can't export GEMs that have an exclusive VM. */
191 if (to_panthor_bo(obj)->exclusive_vm_root_gem)342 if (to_panthor_bo(obj)->exclusive_vm_root_gem)
192 return ERR_PTR(-EINVAL);343 return ERR_PTR(-EINVAL);
193 344
194 return drm_gem_prime_export(obj, flags);345 return drm_gem_dmabuf_export(dev, &exp_info);
346}
347
348struct drm_gem_object *
349panthor_gem_prime_import(struct drm_device *dev,
350 struct dma_buf *dma_buf)
351{
352 struct drm_gem_object *obj = dma_buf->priv;
353
354 if (dma_buf->ops == &panthor_dma_buf_ops && obj->dev == dev) {
355 /* Importing dmabuf exported from our own gem increases
356 * refcount on gem itself instead of f_count of dmabuf.
357 */
358 drm_gem_object_get(obj);
359 return obj;
360 }
361
362 return drm_gem_prime_import(dev, dma_buf);
195}363}
196 364
197static enum drm_gem_object_status panthor_gem_status(struct drm_gem_object *obj)365static enum drm_gem_object_status panthor_gem_status(struct drm_gem_object *obj)
@@ -229,7 +397,6 @@ static const struct drm_gem_object_funcs panthor_gem_funcs = { · 31 unmodified lines
229 */397 */
230struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size)398struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size)
231{399{
232 struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base);
233 struct panthor_gem_object *obj;400 struct panthor_gem_object *obj;
234 401
235 obj = kzalloc(sizeof(*obj), GFP_KERNEL);402 obj = kzalloc(sizeof(*obj), GFP_KERNEL);
@@ -237,7 +404,6 @@ struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t · 1 unmodified line
237 return ERR_PTR(-ENOMEM);404 return ERR_PTR(-ENOMEM);
238 405
239 obj->base.base.funcs = &panthor_gem_funcs;406 obj->base.base.funcs = &panthor_gem_funcs;
240 obj->base.map_wc = !ptdev->coherent;
241 mutex_init(&obj->label.lock);407 mutex_init(&obj->label.lock);
242 408
243 panthor_gem_debugfs_bo_init(obj);409 panthor_gem_debugfs_bo_init(obj);
@@ -272,6 +438,7 @@ panthor_gem_create_with_handle(struct drm_file *file, · 28 unmodified lines
272 438
273 bo = to_panthor_bo(&shmem->base);439 bo = to_panthor_bo(&shmem->base);
274 bo->flags = flags;440 bo->flags = flags;
441 bo->base.map_wc = should_map_wc(bo, exclusive_vm);
275 442
276 if (exclusive_vm) {443 if (exclusive_vm) {
277 bo->exclusive_vm_root_gem = panthor_vm_root_gem(exclusive_vm);444 bo->exclusive_vm_root_gem = panthor_vm_root_gem(exclusive_vm);
@@ -349,6 +516,91 @@ panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label) · 71 unmodified lines
349 panthor_gem_bo_set_label(bo->obj, str);516 panthor_gem_bo_set_label(bo->obj, str);
350}517}
351 518
519int
520panthor_gem_sync(struct drm_gem_object *obj, u32 type,
521 u64 offset, u64 size)
522{
523 struct panthor_gem_object *bo = to_panthor_bo(obj);
524 struct drm_gem_shmem_object *shmem = &bo->base;
525 const struct drm_device *dev = shmem->base.dev;
526 struct sg_table *sgt;
527 struct scatterlist *sgl;
528 unsigned int count;
529
530 /* Make sure the range is in bounds. */
531 if (offset + size < offset || offset + size > shmem->base.size)
532 return -EINVAL;
533
534 /* Disallow CPU-cache maintenance on imported buffers. */
535 if (drm_gem_is_imported(&shmem->base))
536 return -EINVAL;
537
538 switch (type) {
539 case DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH:
540 case DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE:
541 break;
542
543 default:
544 return -EINVAL;
545 }
546
547 /* Don't bother if it's WC-mapped */
548 if (shmem->map_wc)
549 return 0;
550
551 /* Nothing to do if the size is zero. */
552 if (size == 0)
553 return 0;
554
555 sgt = drm_gem_shmem_get_pages_sgt(shmem);
556 if (IS_ERR(sgt))
557 return PTR_ERR(sgt);
558
559 for_each_sgtable_dma_sg(sgt, sgl, count) {
560 if (size == 0)
561 break;
562
563 dma_addr_t paddr = sg_dma_address(sgl);
564 size_t len = sg_dma_len(sgl);
565
566 if (len <= offset) {
567 offset -= len;
568 continue;
569 }
570
571 paddr += offset;
572 len -= offset;
573 len = min_t(size_t, len, size);
574 size -= len;
575 offset = 0;
576
577 /* It's unclear whether dma_sync_xxx() is the right API to do CPU
578 * cache maintenance given an IOMMU can register their own
579 * implementation doing more than just CPU cache flushes/invalidation,
580 * and what we really care about here is CPU caches only, but that's
581 * the best we have that is both arch-agnostic and does at least the
582 * CPU cache maintenance on a <page,offset,size> tuple.
583 *
584 * Also, I wish we could do a single
585 *
586 * dma_sync_single_for_device(BIDIR)
587 *
588 * and get a flush+invalidate, but that's not how it's implemented
589 * in practice (at least on arm64), so we have to make it
590 *
591 * dma_sync_single_for_device(TO_DEVICE)
592 * dma_sync_single_for_cpu(FROM_DEVICE)
593 *
594 * for the flush+invalidate case.
595 */
596 dma_sync_single_for_device(dev->dev, paddr, len, DMA_TO_DEVICE);
597 if (type == DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE)
598 dma_sync_single_for_cpu(dev->dev, paddr, len, DMA_FROM_DEVICE);
599 }
600
601 return 0;
602}
603
352#ifdef CONFIG_DEBUG_FS604#ifdef CONFIG_DEBUG_FS
353struct gem_size_totals {605struct gem_size_totals {
354 size_t size;606 size_t size;
drivers/gpu/drm/panthor/panthor_gem.h+8−0
@@ -136,6 +136,8 @@ struct panthor_gem_object *to_panthor_bo(struct drm_gem_object *obj) · 135 unmodified lines
136 return container_of(to_drm_gem_shmem_obj(obj), struct panthor_gem_object, base);136 return container_of(to_drm_gem_shmem_obj(obj), struct panthor_gem_object, base);
137}137}
138 138
139void panthor_gem_init(struct panthor_device *ptdev);
140
139struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size);141struct drm_gem_object *panthor_gem_create_object(struct drm_device *ddev, size_t size);
140 142
141int143int
@@ -146,6 +148,12 @@ panthor_gem_create_with_handle(struct drm_file *file, · 4 unmodified lines
146 148
147void panthor_gem_bo_set_label(struct drm_gem_object *obj, const char *label);149void panthor_gem_bo_set_label(struct drm_gem_object *obj, const char *label);
148void panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label);150void panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label);
151int panthor_gem_sync(struct drm_gem_object *obj,
152 u32 type, u64 offset, u64 size);
153
154struct drm_gem_object *
155panthor_gem_prime_import(struct drm_device *dev,
156 struct dma_buf *dma_buf);
149 157
150static inline u64158static inline u64
151panthor_kernel_bo_gpuva(struct panthor_kernel_bo *bo)159panthor_kernel_bo_gpuva(struct panthor_kernel_bo *bo)
drivers/gpu/drm/panthor/panthor_gpu.c+13−8
@@ -51,7 +51,7 @@ struct panthor_gpu { · 50 unmodified lines
51static void panthor_gpu_coherency_set(struct panthor_device *ptdev)51static void panthor_gpu_coherency_set(struct panthor_device *ptdev)
52{52{
53 gpu_write(ptdev, GPU_COHERENCY_PROTOCOL,53 gpu_write(ptdev, GPU_COHERENCY_PROTOCOL,
54 ptdev->coherent ? GPU_COHERENCY_PROT_BIT(ACE_LITE) : GPU_COHERENCY_NONE);54 ptdev->gpu_info.selected_coherency);
55}55}
56 56
57static void panthor_gpu_l2_config_set(struct panthor_device *ptdev)57static void panthor_gpu_l2_config_set(struct panthor_device *ptdev)
@@ -289,38 +289,42 @@ int panthor_gpu_l2_power_on(struct panthor_device *ptdev) · 231 unmodified lines
289int panthor_gpu_flush_caches(struct panthor_device *ptdev,289int panthor_gpu_flush_caches(struct panthor_device *ptdev,
290 u32 l2, u32 lsc, u32 other)290 u32 l2, u32 lsc, u32 other)
291{291{
292 bool timedout = false;
293 unsigned long flags;292 unsigned long flags;
293 int ret = 0;
294 294
295 /* Serialize cache flush operations. */295 /* Serialize cache flush operations. */
296 guard(mutex)(&ptdev->gpu->cache_flush_lock);296 guard(mutex)(&ptdev->gpu->cache_flush_lock);
297 297
298 spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags);298 spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags);
299 if (!drm_WARN_ON(&ptdev->base,299 if (!(ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED)) {
300 ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED)) {
301 ptdev->gpu->pending_reqs |= GPU_IRQ_CLEAN_CACHES_COMPLETED;300 ptdev->gpu->pending_reqs |= GPU_IRQ_CLEAN_CACHES_COMPLETED;
302 gpu_write(ptdev, GPU_CMD, GPU_FLUSH_CACHES(l2, lsc, other));301 gpu_write(ptdev, GPU_CMD, GPU_FLUSH_CACHES(l2, lsc, other));
302 } else {
303 ret = -EIO;
303 }304 }
304 spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags);305 spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags);
305 306
307 if (ret)
308 return ret;
309
306 if (!wait_event_timeout(ptdev->gpu->reqs_acked,310 if (!wait_event_timeout(ptdev->gpu->reqs_acked,
307 !(ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED),311 !(ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED),
308 msecs_to_jiffies(100))) {312 msecs_to_jiffies(100))) {
309 spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags);313 spin_lock_irqsave(&ptdev->gpu->reqs_lock, flags);
310 if ((ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED) != 0 &&314 if ((ptdev->gpu->pending_reqs & GPU_IRQ_CLEAN_CACHES_COMPLETED) != 0 &&
311 !(gpu_read(ptdev, GPU_INT_RAWSTAT) & GPU_IRQ_CLEAN_CACHES_COMPLETED))315 !(gpu_read(ptdev, GPU_INT_RAWSTAT) & GPU_IRQ_CLEAN_CACHES_COMPLETED))
312 timedout = true;316 ret = -ETIMEDOUT;
313 else317 else
314 ptdev->gpu->pending_reqs &= ~GPU_IRQ_CLEAN_CACHES_COMPLETED;318 ptdev->gpu->pending_reqs &= ~GPU_IRQ_CLEAN_CACHES_COMPLETED;
315 spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags);319 spin_unlock_irqrestore(&ptdev->gpu->reqs_lock, flags);
316 }320 }
317 321
318 if (timedout) {322 if (ret) {
323 panthor_device_schedule_reset(ptdev);
319 drm_err(&ptdev->base, "Flush caches timeout");324 drm_err(&ptdev->base, "Flush caches timeout");
320 return -ETIMEDOUT;
321 }325 }
322 326
323 return 0;327 return ret;
324}328}
325 329
326/**330/**
@@ -360,6 +364,7 @@ int panthor_gpu_soft_reset(struct panthor_device *ptdev) · 33 unmodified lines
360 return -ETIMEDOUT;364 return -ETIMEDOUT;
361 }365 }
362 366
367 ptdev->gpu->pending_reqs = 0;
363 return 0;368 return 0;
364}369}
365 370
drivers/gpu/drm/panthor/panthor_mmu.c+183−131
@@ -375,6 +375,15 @@ struct panthor_vm { · 374 unmodified lines
375 * flagged as faulty as a result.375 * flagged as faulty as a result.
376 */376 */
377 bool unhandled_fault;377 bool unhandled_fault;
378
379 /** @locked_region: Information about the currently locked region currently. */
380 struct {
381 /** @locked_region.start: Start of the locked region. */
382 u64 start;
383
384 /** @locked_region.size: Size of the locked region. */
385 u64 size;
386 } locked_region;
378};387};
379 388
380/**389/**
@@ -510,27 +519,27 @@ static int wait_ready(struct panthor_device *ptdev, u32 as_nr) · 129 unmodified lines
510 return ret;519 return ret;
511}520}
512 521
513static int write_cmd(struct panthor_device *ptdev, u32 as_nr, u32 cmd)522static int as_send_cmd_and_wait(struct panthor_device *ptdev, u32 as_nr, u32 cmd)
514{523{
515 int status;524 int status;
516 525
517 /* write AS_COMMAND when MMU is ready to accept another command */526 /* write AS_COMMAND when MMU is ready to accept another command */
518 status = wait_ready(ptdev, as_nr);527 status = wait_ready(ptdev, as_nr);
519 if (!status)528 if (!status) {
520 gpu_write(ptdev, AS_COMMAND(as_nr), cmd);529 gpu_write(ptdev, AS_COMMAND(as_nr), cmd);
530 status = wait_ready(ptdev, as_nr);
531 }
521 532
522 return status;533 return status;
523}534}
524 535
525static void lock_region(struct panthor_device *ptdev, u32 as_nr,536static u64 pack_region_range(struct panthor_device *ptdev, u64 region_start, u64 size)
526 u64 region_start, u64 size)
527{537{
528 u8 region_width;538 u8 region_width;
529 u64 region;
530 u64 region_end = region_start + size;539 u64 region_end = region_start + size;
531 540
532 if (!size)541 if (drm_WARN_ON_ONCE(&ptdev->base, !size))
533 return;542 return 0;
534 543
535 /*544 /*
536 * The locked region is a naturally aligned power of 2 block encoded as545 * The locked region is a naturally aligned power of 2 block encoded as
@@ -549,106 +558,51 @@ static void lock_region(struct panthor_device *ptdev, u32 as_nr, · 12 unmodified lines
549 */558 */
550 region_start &= GENMASK_ULL(63, region_width);559 region_start &= GENMASK_ULL(63, region_width);
551 560
552 region = region_width | region_start;561 return region_width | region_start;
553
554 /* Lock the region that needs to be updated */
555 gpu_write64(ptdev, AS_LOCKADDR(as_nr), region);
556 write_cmd(ptdev, as_nr, AS_COMMAND_LOCK);
557}
558
559static int mmu_hw_do_operation_locked(struct panthor_device *ptdev, int as_nr,
560 u64 iova, u64 size, u32 op)
561{
562 const u32 l2_flush_op = CACHE_CLEAN | CACHE_INV;
563 u32 lsc_flush_op;
564 int ret;
565
566 lockdep_assert_held(&ptdev->mmu->as.slots_lock);
567
568 switch (op) {
569 case AS_COMMAND_FLUSH_MEM:
570 lsc_flush_op = CACHE_CLEAN | CACHE_INV;
571 break;
572 case AS_COMMAND_FLUSH_PT:
573 lsc_flush_op = 0;
574 break;
575 default:
576 drm_WARN(&ptdev->base, 1, "Unexpected AS_COMMAND: %d", op);
577 return -EINVAL;
578 }
579
580 if (as_nr < 0)
581 return 0;
582
583 /*
584 * If the AS number is greater than zero, then we can be sure
585 * the device is up and running, so we don't need to explicitly
586 * power it up
587 */
588
589 lock_region(ptdev, as_nr, iova, size);
590
591 ret = wait_ready(ptdev, as_nr);
592 if (ret)
593 return ret;
594
595 ret = panthor_gpu_flush_caches(ptdev, l2_flush_op, lsc_flush_op, 0);
596 if (ret)
597 return ret;
598
599 /*
600 * Explicitly unlock the region as the AS is not unlocked automatically
601 * at the end of the GPU_CONTROL cache flush command, unlike
602 * AS_COMMAND_FLUSH_MEM or AS_COMMAND_FLUSH_PT.
603 */
604 write_cmd(ptdev, as_nr, AS_COMMAND_UNLOCK);
605
606 /* Wait for the unlock command to complete */
607 return wait_ready(ptdev, as_nr);
608}
609
610static int mmu_hw_do_operation(struct panthor_vm *vm,
611 u64 iova, u64 size, u32 op)
612{
613 struct panthor_device *ptdev = vm->ptdev;
614 int ret;
615
616 mutex_lock(&ptdev->mmu->as.slots_lock);
617 ret = mmu_hw_do_operation_locked(ptdev, vm->as.id, iova, size, op);
618 mutex_unlock(&ptdev->mmu->as.slots_lock);
619
620 return ret;
621}562}
622 563
623static int panthor_mmu_as_enable(struct panthor_device *ptdev, u32 as_nr,564static int panthor_mmu_as_enable(struct panthor_device *ptdev, u32 as_nr,
624 u64 transtab, u64 transcfg, u64 memattr)565 u64 transtab, u64 transcfg, u64 memattr)
625{566{
626 int ret;
627
628 ret = mmu_hw_do_operation_locked(ptdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);
629 if (ret)
630 return ret;
631
632 gpu_write64(ptdev, AS_TRANSTAB(as_nr), transtab);567 gpu_write64(ptdev, AS_TRANSTAB(as_nr), transtab);
633 gpu_write64(ptdev, AS_MEMATTR(as_nr), memattr);568 gpu_write64(ptdev, AS_MEMATTR(as_nr), memattr);
634 gpu_write64(ptdev, AS_TRANSCFG(as_nr), transcfg);569 gpu_write64(ptdev, AS_TRANSCFG(as_nr), transcfg);
635 570
636 return write_cmd(ptdev, as_nr, AS_COMMAND_UPDATE);571 return as_send_cmd_and_wait(ptdev, as_nr, AS_COMMAND_UPDATE);
637}572}
638 573
639static int panthor_mmu_as_disable(struct panthor_device *ptdev, u32 as_nr)574static int panthor_mmu_as_disable(struct panthor_device *ptdev, u32 as_nr,
575 bool recycle_slot)
640{576{
577 struct panthor_vm *vm = ptdev->mmu->as.slots[as_nr].vm;
641 int ret;578 int ret;
642 579
643 ret = mmu_hw_do_operation_locked(ptdev, as_nr, 0, ~0ULL, AS_COMMAND_FLUSH_MEM);580 lockdep_assert_held(&ptdev->mmu->as.slots_lock);
581
582 /* Flush+invalidate RW caches, invalidate RO ones. */
583 ret = panthor_gpu_flush_caches(ptdev, CACHE_CLEAN | CACHE_INV,
584 CACHE_CLEAN | CACHE_INV, CACHE_INV);
644 if (ret)585 if (ret)
645 return ret;586 return ret;
646 587
588 if (vm && vm->locked_region.size) {
589 /* Unlock the region if there's a lock pending. */
590 ret = as_send_cmd_and_wait(ptdev, vm->as.id, AS_COMMAND_UNLOCK);
591 if (ret)
592 return ret;
593 }
594
595 /* If the slot is going to be used immediately, don't bother changing
596 * the config.
597 */
598 if (recycle_slot)
599 return 0;
600
647 gpu_write64(ptdev, AS_TRANSTAB(as_nr), 0);601 gpu_write64(ptdev, AS_TRANSTAB(as_nr), 0);
648 gpu_write64(ptdev, AS_MEMATTR(as_nr), 0);602 gpu_write64(ptdev, AS_MEMATTR(as_nr), 0);
649 gpu_write64(ptdev, AS_TRANSCFG(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED);603 gpu_write64(ptdev, AS_TRANSCFG(as_nr), AS_TRANSCFG_ADRMODE_UNMAPPED);
650 604
651 return write_cmd(ptdev, as_nr, AS_COMMAND_UPDATE);605 return as_send_cmd_and_wait(ptdev, as_nr, AS_COMMAND_UPDATE);
652}606}
653 607
654static u32 panthor_mmu_fault_mask(struct panthor_device *ptdev, u32 value)608static u32 panthor_mmu_fault_mask(struct panthor_device *ptdev, u32 value)
@@ -722,6 +676,10 @@ int panthor_vm_active(struct panthor_vm *vm) · 67 unmodified lines
722 if (refcount_inc_not_zero(&vm->as.active_cnt))676 if (refcount_inc_not_zero(&vm->as.active_cnt))
723 goto out_dev_exit;677 goto out_dev_exit;
724 678
679 /* Make sure we don't race with lock/unlock_region() calls
680 * happening around VM bind operations.
681 */
682 mutex_lock(&vm->op_lock);
725 mutex_lock(&ptdev->mmu->as.slots_lock);683 mutex_lock(&ptdev->mmu->as.slots_lock);
726 684
727 if (refcount_inc_not_zero(&vm->as.active_cnt))685 if (refcount_inc_not_zero(&vm->as.active_cnt))
@@ -759,6 +717,11 @@ int panthor_vm_active(struct panthor_vm *vm) · 31 unmodified lines
759 717
760 drm_WARN_ON(&ptdev->base, refcount_read(&lru_vm->as.active_cnt));718 drm_WARN_ON(&ptdev->base, refcount_read(&lru_vm->as.active_cnt));
761 as = lru_vm->as.id;719 as = lru_vm->as.id;
720
721 ret = panthor_mmu_as_disable(ptdev, as, true);
722 if (ret)
723 goto out_unlock;
724
762 panthor_vm_release_as_locked(lru_vm);725 panthor_vm_release_as_locked(lru_vm);
763 }726 }
764 727
@@ -789,6 +752,10 @@ out_enable_as: · 24 unmodified lines
789 gpu_write(ptdev, MMU_INT_MASK, ~ptdev->mmu->as.faulty_mask);752 gpu_write(ptdev, MMU_INT_MASK, ~ptdev->mmu->as.faulty_mask);
790 }753 }
791 754
755 /* The VM update is guarded by ::op_lock, which we take at the beginning
756 * of this function, so we don't expect any locked region here.
757 */
758 drm_WARN_ON(&vm->ptdev->base, vm->locked_region.size > 0);
792 ret = panthor_mmu_as_enable(vm->ptdev, vm->as.id, transtab, transcfg, vm->memattr);759 ret = panthor_mmu_as_enable(vm->ptdev, vm->as.id, transtab, transcfg, vm->memattr);
793 760
794out_make_active:761out_make_active:
@@ -799,6 +766,7 @@ out_make_active: · 4 unmodified lines
799 766
800out_unlock:767out_unlock:
801 mutex_unlock(&ptdev->mmu->as.slots_lock);768 mutex_unlock(&ptdev->mmu->as.slots_lock);
769 mutex_unlock(&vm->op_lock);
802 770
803out_dev_exit:771out_dev_exit:
804 drm_dev_exit(cookie);772 drm_dev_exit(cookie);
@@ -882,44 +850,64 @@ static size_t get_pgsize(u64 addr, size_t size, size_t *count) · 77 unmodified lines
882 return SZ_2M;850 return SZ_2M;
883}851}
884 852
885static int panthor_vm_flush_range(struct panthor_vm *vm, u64 iova, u64 size)853static void panthor_vm_declare_unusable(struct panthor_vm *vm)
886{854{
887 struct panthor_device *ptdev = vm->ptdev;855 struct panthor_device *ptdev = vm->ptdev;
888 int ret = 0, cookie;856 int cookie;
889
890 if (vm->as.id < 0)
891 return 0;
892 857
893 /* If the device is unplugged, we just silently skip the flush. */858 if (vm->unusable)
894 if (!drm_dev_enter(&ptdev->base, &cookie))859 return;
895 return 0;
896
897 ret = mmu_hw_do_operation(vm, iova, size, AS_COMMAND_FLUSH_PT);
898 860
899 drm_dev_exit(cookie);861 vm->unusable = true;
900 return ret;862 mutex_lock(&ptdev->mmu->as.slots_lock);
863 if (vm->as.id >= 0 && drm_dev_enter(&ptdev->base, &cookie)) {
864 panthor_mmu_as_disable(ptdev, vm->as.id, false);
865 drm_dev_exit(cookie);
866 }
867 mutex_unlock(&ptdev->mmu->as.slots_lock);
901}868}
902 869
903static int panthor_vm_unmap_pages(struct panthor_vm *vm, u64 iova, u64 size)870static void panthor_vm_unmap_pages(struct panthor_vm *vm, u64 iova, u64 size)
904{871{
905 struct panthor_device *ptdev = vm->ptdev;872 struct panthor_device *ptdev = vm->ptdev;
906 struct io_pgtable_ops *ops = vm->pgtbl_ops;873 struct io_pgtable_ops *ops = vm->pgtbl_ops;
907 u64 start_iova = iova;874 u64 start_iova = iova;
908 u64 offset = 0;875 u64 offset = 0;
909 876
877 if (!size)
878 return;
879
880 drm_WARN_ON(&ptdev->base,
881 (iova < vm->locked_region.start) ||
882 (iova + size > vm->locked_region.start + vm->locked_region.size));
883
910 while (offset < size) {884 while (offset < size) {
911 size_t unmapped_sz = 0, pgcount;885 size_t unmapped_sz = 0, pgcount;
912 size_t pgsize = get_pgsize(iova + offset, size - offset, &pgcount);886 size_t pgsize = get_pgsize(iova + offset, size - offset, &pgcount);
913 887
914 unmapped_sz = ops->unmap_pages(ops, iova + offset, pgsize, pgcount, NULL);888 unmapped_sz = ops->unmap_pages(ops, iova + offset, pgsize, pgcount, NULL);
889 if (drm_WARN_ON_ONCE(&ptdev->base, unmapped_sz != pgsize * pgcount)) {
890 /* Gracefully handle sparsely unmapped regions to avoid leaving
891 * page table pages behind when the drm_gpuvm and VM page table
892 * are out-of-sync. This is not supposed to happen, hence the
893 * above WARN_ON().
894 */
895 while (!ops->iova_to_phys(ops, iova + unmapped_sz) &&
896 unmapped_sz < pgsize * pgcount)
897 unmapped_sz += SZ_4K;
898
899 /* We're passed the point where we can try to fix things,
900 * so flag the VM unusable to make sure it's not going
901 * to be used anymore.
902 */
903 panthor_vm_declare_unusable(vm);
915 904
916 if (drm_WARN_ON(&ptdev->base, unmapped_sz != pgsize * pgcount)) {905 /* If we don't make progress, we're screwed. That also means
917 drm_err(&ptdev->base, "failed to unmap range %llx-%llx (requested range %llx-%llx)\n",906 * something else prevents us from unmapping the region, but
918 iova + offset + unmapped_sz,907 * there's not much we can do here: time for debugging.
919 iova + offset + pgsize * pgcount,908 */
920 iova, iova + size);909 if (drm_WARN_ON_ONCE(&ptdev->base, !unmapped_sz))
921 panthor_vm_flush_range(vm, iova, offset + unmapped_sz);910 return;
922 return -EINVAL;
923 }911 }
924 912
925 drm_dbg(&ptdev->base,913 drm_dbg(&ptdev->base,
@@ -929,8 +917,6 @@ static int panthor_vm_unmap_pages(struct panthor_vm *vm, u64 iova, u64 size) · 3 unmodified lines
929 917
930 offset += unmapped_sz;918 offset += unmapped_sz;
931 }919 }
932
933 return panthor_vm_flush_range(vm, iova, size);
934}920}
935 921
936static int922static int
@@ -948,6 +934,10 @@ panthor_vm_map_pages(struct panthor_vm *vm, u64 iova, int prot, · 11 unmodified lines
948 if (!size)934 if (!size)
949 return 0;935 return 0;
950 936
937 drm_WARN_ON(&ptdev->base,
938 (iova < vm->locked_region.start) ||
939 (iova + size > vm->locked_region.start + vm->locked_region.size));
940
951 for_each_sgtable_dma_sg(sgt, sgl, count) {941 for_each_sgtable_dma_sg(sgt, sgl, count) {
952 dma_addr_t paddr = sg_dma_address(sgl);942 dma_addr_t paddr = sg_dma_address(sgl);
953 size_t len = sg_dma_len(sgl);943 size_t len = sg_dma_len(sgl);
@@ -978,16 +968,17 @@ panthor_vm_map_pages(struct panthor_vm *vm, u64 iova, int prot, · 24 unmodified lines
978 paddr += mapped;968 paddr += mapped;
979 len -= mapped;969 len -= mapped;
980 970
981 if (drm_WARN_ON(&ptdev->base, !ret && !mapped))971 /* If nothing was mapped, consider it an ENOMEM. */
972 if (!ret && !mapped)
982 ret = -ENOMEM;973 ret = -ENOMEM;
983 974
984 if (ret) {975 /* If something fails, we stop there, and flag the VM unusable. */
985 /* If something failed, unmap what we've already mapped before976 if (drm_WARN_ON_ONCE(&ptdev->base, ret)) {
986 * returning. The unmap call is not supposed to fail.977 /* Unmap what we've already mapped to avoid leaving page
978 * table pages behind.
987 */979 */
988 drm_WARN_ON(&ptdev->base,980 panthor_vm_unmap_pages(vm, start_iova, iova - start_iova);
989 panthor_vm_unmap_pages(vm, start_iova,981 panthor_vm_declare_unusable(vm);
990 iova - start_iova));
991 return ret;982 return ret;
992 }983 }
993 }984 }
@@ -998,7 +989,7 @@ panthor_vm_map_pages(struct panthor_vm *vm, u64 iova, int prot, · 4 unmodified lines
998 offset = 0;989 offset = 0;
999 }990 }
1000 991
1001 return panthor_vm_flush_range(vm, start_iova, iova - start_iova);992 return 0;
1002}993}
1003 994
1004static int flags_to_prot(u32 flags)995static int flags_to_prot(u32 flags)
@@ -1641,6 +1632,62 @@ static const char *access_type_name(struct panthor_device *ptdev, · 636 unmodified lines
1641 }1632 }
1642}1633}
1643 1634
1635static int panthor_vm_lock_region(struct panthor_vm *vm, u64 start, u64 size)
1636{
1637 struct panthor_device *ptdev = vm->ptdev;
1638 int ret = 0;
1639
1640 mutex_lock(&ptdev->mmu->as.slots_lock);
1641 drm_WARN_ON(&ptdev->base, vm->locked_region.start || vm->locked_region.size);
1642 if (vm->as.id >= 0 && size) {
1643 /* Lock the region that needs to be updated */
1644 gpu_write64(ptdev, AS_LOCKADDR(vm->as.id),
1645 pack_region_range(ptdev, start, size));
1646
1647 /* If the lock succeeded, update the locked_region info. */
1648 ret = as_send_cmd_and_wait(ptdev, vm->as.id, AS_COMMAND_LOCK);
1649 }
1650
1651 if (!ret) {
1652 vm->locked_region.start = start;
1653 vm->locked_region.size = size;
1654 }
1655 mutex_unlock(&ptdev->mmu->as.slots_lock);
1656
1657 return ret;
1658}
1659
1660static void panthor_vm_unlock_region(struct panthor_vm *vm)
1661{
1662 struct panthor_device *ptdev = vm->ptdev;
1663
1664 mutex_lock(&ptdev->mmu->as.slots_lock);
1665 if (vm->as.id >= 0) {
1666 int ret;
1667
1668 /* flush+invalidate RW caches and invalidate RO ones.
1669 * TODO: See if we can use FLUSH_PA_RANGE when the physical
1670 * range is narrow enough and the HW supports it.
1671 */
1672 ret = panthor_gpu_flush_caches(ptdev, CACHE_CLEAN | CACHE_INV,
1673 CACHE_CLEAN | CACHE_INV,
1674 CACHE_INV);
1675
1676 /* Unlock the region if the flush is effective. */
1677 if (!ret)
1678 ret = as_send_cmd_and_wait(ptdev, vm->as.id, AS_COMMAND_UNLOCK);
1679
1680 /* If we fail to flush or unlock the region, schedule a GPU reset
1681 * to unblock the situation.
1682 */
1683 if (ret)
1684 panthor_device_schedule_reset(ptdev);
1685 }
1686 vm->locked_region.start = 0;
1687 vm->locked_region.size = 0;
1688 mutex_unlock(&ptdev->mmu->as.slots_lock);
1689}
1690
1644static void panthor_mmu_irq_handler(struct panthor_device *ptdev, u32 status)1691static void panthor_mmu_irq_handler(struct panthor_device *ptdev, u32 status)
1645{1692{
1646 bool has_unhandled_faults = false;1693 bool has_unhandled_faults = false;
@@ -1701,7 +1748,7 @@ static void panthor_mmu_irq_handler(struct panthor_device *ptdev, u32 status) · 54 unmodified lines
1701 ptdev->mmu->as.slots[as].vm->unhandled_fault = true;1748 ptdev->mmu->as.slots[as].vm->unhandled_fault = true;
1702 1749
1703 /* Disable the MMU to kill jobs on this AS. */1750 /* Disable the MMU to kill jobs on this AS. */
1704 panthor_mmu_as_disable(ptdev, as);1751 panthor_mmu_as_disable(ptdev, as, false);
1705 mutex_unlock(&ptdev->mmu->as.slots_lock);1752 mutex_unlock(&ptdev->mmu->as.slots_lock);
1706 1753
1707 status &= ~mask;1754 status &= ~mask;
@@ -1730,7 +1777,8 @@ void panthor_mmu_suspend(struct panthor_device *ptdev) · 22 unmodified lines
1730 struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm;1777 struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm;
1731 1778
1732 if (vm) {1779 if (vm) {
1733 drm_WARN_ON(&ptdev->base, panthor_mmu_as_disable(ptdev, i));1780 drm_WARN_ON(&ptdev->base,
1781 panthor_mmu_as_disable(ptdev, i, false));
1734 panthor_vm_release_as_locked(vm);1782 panthor_vm_release_as_locked(vm);
1735 }1783 }
1736 }1784 }
@@ -1845,12 +1893,13 @@ static void panthor_vm_free(struct drm_gpuvm *gpuvm) · 108 unmodified lines
1845 drm_sched_entity_destroy(&vm->entity);1893 drm_sched_entity_destroy(&vm->entity);
1846 drm_sched_fini(&vm->sched);1894 drm_sched_fini(&vm->sched);
1847 1895
1896 mutex_lock(&vm->op_lock);
1848 mutex_lock(&ptdev->mmu->as.slots_lock);1897 mutex_lock(&ptdev->mmu->as.slots_lock);
1849 if (vm->as.id >= 0) {1898 if (vm->as.id >= 0) {
1850 int cookie;1899 int cookie;
1851 1900
1852 if (drm_dev_enter(&ptdev->base, &cookie)) {1901 if (drm_dev_enter(&ptdev->base, &cookie)) {
1853 panthor_mmu_as_disable(ptdev, vm->as.id);1902 panthor_mmu_as_disable(ptdev, vm->as.id, false);
1854 drm_dev_exit(cookie);1903 drm_dev_exit(cookie);
1855 }1904 }
1856 1905
@@ -1859,6 +1908,7 @@ static void panthor_vm_free(struct drm_gpuvm *gpuvm) · 2 unmodified lines
1859 list_del(&vm->as.lru_node);1908 list_del(&vm->as.lru_node);
1860 }1909 }
1861 mutex_unlock(&ptdev->mmu->as.slots_lock);1910 mutex_unlock(&ptdev->mmu->as.slots_lock);
1911 mutex_unlock(&vm->op_lock);
1862 1912
1863 free_io_pgtable_ops(vm->pgtbl_ops);1913 free_io_pgtable_ops(vm->pgtbl_ops);
1864 1914
@@ -2060,12 +2110,9 @@ static int panthor_gpuva_sm_step_remap(struct drm_gpuva_op *op, · 195 unmodified lines
2060 struct panthor_vm_op_ctx *op_ctx = vm->op_ctx;2110 struct panthor_vm_op_ctx *op_ctx = vm->op_ctx;
2061 struct panthor_vma *prev_vma = NULL, *next_vma = NULL;2111 struct panthor_vma *prev_vma = NULL, *next_vma = NULL;
2062 u64 unmap_start, unmap_range;2112 u64 unmap_start, unmap_range;
2063 int ret;
2064 2113
2065 drm_gpuva_op_remap_to_unmap_range(&op->remap, &unmap_start, &unmap_range);2114 drm_gpuva_op_remap_to_unmap_range(&op->remap, &unmap_start, &unmap_range);
2066 ret = panthor_vm_unmap_pages(vm, unmap_start, unmap_range);2115 panthor_vm_unmap_pages(vm, unmap_start, unmap_range);
2067 if (ret)
2068 return ret;
2069 2116
2070 if (op->remap.prev) {2117 if (op->remap.prev) {
2071 prev_vma = panthor_vm_op_ctx_get_vma(op_ctx);2118 prev_vma = panthor_vm_op_ctx_get_vma(op_ctx);
@@ -2103,13 +2150,9 @@ static int panthor_gpuva_sm_step_unmap(struct drm_gpuva_op *op, · 31 unmodified lines
2103{2150{
2104 struct panthor_vma *unmap_vma = container_of(op->unmap.va, struct panthor_vma, base);2151 struct panthor_vma *unmap_vma = container_of(op->unmap.va, struct panthor_vma, base);
2105 struct panthor_vm *vm = priv;2152 struct panthor_vm *vm = priv;
2106 int ret;
2107
2108 ret = panthor_vm_unmap_pages(vm, unmap_vma->base.va.addr,
2109 unmap_vma->base.va.range);
2110 if (drm_WARN_ON(&vm->ptdev->base, ret))
2111 return ret;
2112 2153
2154 panthor_vm_unmap_pages(vm, unmap_vma->base.va.addr,
2155 unmap_vma->base.va.range);
2113 drm_gpuva_unmap(&op->unmap);2156 drm_gpuva_unmap(&op->unmap);
2114 panthor_vma_unlink(unmap_vma);2157 panthor_vma_unlink(unmap_vma);
2115 return 0;2158 return 0;
@@ -2154,6 +2197,11 @@ panthor_vm_exec_op(struct panthor_vm *vm, struct panthor_vm_op_ctx *op, · 38 unmodified lines
2154 2197
2155 mutex_lock(&vm->op_lock);2198 mutex_lock(&vm->op_lock);
2156 vm->op_ctx = op;2199 vm->op_ctx = op;
2200
2201 ret = panthor_vm_lock_region(vm, op->va.addr, op->va.range);
2202 if (ret)
2203 goto out;
2204
2157 switch (op_type) {2205 switch (op_type) {
2158 case DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: {2206 case DRM_PANTHOR_VM_BIND_OP_TYPE_MAP: {
2159 const struct drm_gpuvm_map_req map_req = {2207 const struct drm_gpuvm_map_req map_req = {
@@ -2181,8 +2229,11 @@ panthor_vm_exec_op(struct panthor_vm *vm, struct panthor_vm_op_ctx *op, · 21 unmodified lines
2181 break;2229 break;
2182 }2230 }
2183 2231
2232 panthor_vm_unlock_region(vm);
2233
2234out:
2184 if (ret && flag_vm_unusable_on_failure)2235 if (ret && flag_vm_unusable_on_failure)
2185 vm->unusable = true;2236 panthor_vm_declare_unusable(vm);
2186 2237
2187 vm->op_ctx = NULL;2238 vm->op_ctx = NULL;
2188 mutex_unlock(&vm->op_lock);2239 mutex_unlock(&vm->op_lock);
@@ -2694,7 +2745,8 @@ void panthor_mmu_unplug(struct panthor_device *ptdev) · 505 unmodified lines
2694 struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm;2745 struct panthor_vm *vm = ptdev->mmu->as.slots[i].vm;
2695 2746
2696 if (vm) {2747 if (vm) {
2697 drm_WARN_ON(&ptdev->base, panthor_mmu_as_disable(ptdev, i));2748 drm_WARN_ON(&ptdev->base,
2749 panthor_mmu_as_disable(ptdev, i, false));
2698 panthor_vm_release_as_locked(vm);2750 panthor_vm_release_as_locked(vm);
2699 }2751 }
2700 }2752 }
drivers/gpu/drm/panthor/panthor_sched.c+129−121
@@ -108,15 +108,6 @@ struct panthor_csg_slot { · 107 unmodified lines
108 108
109 /** @priority: Group priority. */109 /** @priority: Group priority. */
110 u8 priority;110 u8 priority;
111
112 /**
113 * @idle: True if the group bound to this slot is idle.
114 *
115 * A group is idle when it has nothing waiting for execution on
116 * all its queues, or when queues are blocked waiting for something
117 * to happen (synchronization object).
118 */
119 bool idle;
120};111};
121 112
122/**113/**
@@ -878,8 +869,11 @@ panthor_queue_get_syncwait_obj(struct panthor_group *group, struct panthor_queue · 755 unmodified lines
878 struct iosys_map map;869 struct iosys_map map;
879 int ret;870 int ret;
880 871
881 if (queue->syncwait.kmap)872 if (queue->syncwait.kmap) {
882 return queue->syncwait.kmap + queue->syncwait.offset;873 bo = container_of(queue->syncwait.obj,
874 struct panthor_gem_object, base.base);
875 goto out_sync;
876 }
883 877
884 bo = panthor_vm_get_bo_for_va(group->vm,878 bo = panthor_vm_get_bo_for_va(group->vm,
885 queue->syncwait.gpu_va,879 queue->syncwait.gpu_va,
@@ -896,6 +890,17 @@ panthor_queue_get_syncwait_obj(struct panthor_group *group, struct panthor_queue · 10 unmodified lines
896 if (drm_WARN_ON(&ptdev->base, !queue->syncwait.kmap))890 if (drm_WARN_ON(&ptdev->base, !queue->syncwait.kmap))
897 goto err_put_syncwait_obj;891 goto err_put_syncwait_obj;
898 892
893out_sync:
894 /* Make sure the CPU caches are invalidated before the seqno is read.
895 * drm_gem_shmem_sync() is a NOP if map_wc=true, so no need to check
896 * it here.
897 */
898 panthor_gem_sync(&bo->base.base, queue->syncwait.offset,
899 queue->syncwait.sync64 ?
900 sizeof(struct panthor_syncobj_64b) :
901 sizeof(struct panthor_syncobj_32b),
902 DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE);
903
899 return queue->syncwait.kmap + queue->syncwait.offset;904 return queue->syncwait.kmap + queue->syncwait.offset;
900 905
901err_put_syncwait_obj:906err_put_syncwait_obj:
@@ -908,9 +913,8 @@ static void group_free_queue(struct panthor_group *group, struct panthor_queue * · 6 unmodified lines
908 if (IS_ERR_OR_NULL(queue))913 if (IS_ERR_OR_NULL(queue))
909 return;914 return;
910 915
911 /* This should have been disabled before that point. */916 /* Disable the timeout before tearing down drm_sched components. */
912 drm_WARN_ON(&group->ptdev->base,917 disable_delayed_work_sync(&queue->timeout.work);
913 disable_delayed_work_sync(&queue->timeout.work));
914 918
915 if (queue->entity.fence_context)919 if (queue->entity.fence_context)
916 drm_sched_entity_destroy(&queue->entity);920 drm_sched_entity_destroy(&queue->entity);
@@ -1062,28 +1066,11 @@ group_unbind_locked(struct panthor_group *group) · 145 unmodified lines
1062static bool1066static bool
1063group_is_idle(struct panthor_group *group)1067group_is_idle(struct panthor_group *group)
1064{1068{
1065 struct panthor_device *ptdev = group->ptdev;1069 u32 inactive_queues = group->idle_queues | group->blocked_queues;
1066 u32 inactive_queues;
1067
1068 if (group->csg_id >= 0)
1069 return ptdev->scheduler->csg_slots[group->csg_id].idle;
1070 1070
1071 inactive_queues = group->idle_queues | group->blocked_queues;
1072 return hweight32(inactive_queues) == group->queue_count;1071 return hweight32(inactive_queues) == group->queue_count;
1073}1072}
1074 1073
1075static void
1076queue_reset_timeout_locked(struct panthor_queue *queue)
1077{
1078 lockdep_assert_held(&queue->fence_ctx.lock);
1079
1080 if (queue->timeout.remaining != MAX_SCHEDULE_TIMEOUT) {
1081 mod_delayed_work(queue->scheduler.timeout_wq,
1082 &queue->timeout.work,
1083 msecs_to_jiffies(JOB_TIMEOUT_MS));
1084 }
1085}
1086
1087static bool1074static bool
1088group_can_run(struct panthor_group *group)1075group_can_run(struct panthor_group *group)
1089{1076{
@@ -1100,6 +1087,18 @@ queue_timeout_is_suspended(struct panthor_queue *queue) · 10 unmodified lines
1100 return queue->timeout.remaining != MAX_SCHEDULE_TIMEOUT;1087 return queue->timeout.remaining != MAX_SCHEDULE_TIMEOUT;
1101}1088}
1102 1089
1090static void
1091queue_reset_timeout_locked(struct panthor_queue *queue)
1092{
1093 lockdep_assert_held(&queue->fence_ctx.lock);
1094
1095 if (!queue_timeout_is_suspended(queue)) {
1096 mod_delayed_work(queue->scheduler.timeout_wq,
1097 &queue->timeout.work,
1098 msecs_to_jiffies(JOB_TIMEOUT_MS));
1099 }
1100}
1101
1103static void1102static void
1104queue_suspend_timeout_locked(struct panthor_queue *queue)1103queue_suspend_timeout_locked(struct panthor_queue *queue)
1105{1104{
@@ -1200,12 +1199,10 @@ cs_slot_prog_locked(struct panthor_device *ptdev, u32 csg_id, u32 cs_id) · 94 unmodified lines
1200 panthor_fw_update_reqs(cs_iface, req,1199 panthor_fw_update_reqs(cs_iface, req,
1201 CS_IDLE_SYNC_WAIT |1200 CS_IDLE_SYNC_WAIT |
1202 CS_IDLE_EMPTY |1201 CS_IDLE_EMPTY |
1203 CS_STATE_START |1202 CS_STATE_START,
1204 CS_EXTRACT_EVENT,
1205 CS_IDLE_SYNC_WAIT |1203 CS_IDLE_SYNC_WAIT |
1206 CS_IDLE_EMPTY |1204 CS_IDLE_EMPTY |
1207 CS_STATE_MASK |1205 CS_STATE_MASK);
1208 CS_EXTRACT_EVENT);
1209 if (queue->iface.input->insert != queue->iface.input->extract)1206 if (queue->iface.input->insert != queue->iface.input->extract)
1210 queue_resume_timeout(queue);1207 queue_resume_timeout(queue);
1211}1208}
@@ -1725,17 +1722,6 @@ static bool cs_slot_process_irq_locked(struct panthor_device *ptdev, · 513 unmodified lines
1725 return (events & (CS_FAULT | CS_TILER_OOM)) != 0;1722 return (events & (CS_FAULT | CS_TILER_OOM)) != 0;
1726}1723}
1727 1724
1728static void csg_slot_sync_idle_state_locked(struct panthor_device *ptdev, u32 csg_id)
1729{
1730 struct panthor_csg_slot *csg_slot = &ptdev->scheduler->csg_slots[csg_id];
1731 struct panthor_fw_csg_iface *csg_iface;
1732
1733 lockdep_assert_held(&ptdev->scheduler->lock);
1734
1735 csg_iface = panthor_fw_get_csg_iface(ptdev, csg_id);
1736 csg_slot->idle = csg_iface->output->status_state & CSG_STATUS_STATE_IS_IDLE;
1737}
1738
1739static void csg_slot_process_idle_event_locked(struct panthor_device *ptdev, u32 csg_id)1725static void csg_slot_process_idle_event_locked(struct panthor_device *ptdev, u32 csg_id)
1740{1726{
1741 struct panthor_scheduler *sched = ptdev->scheduler;1727 struct panthor_scheduler *sched = ptdev->scheduler;
@@ -1997,10 +1983,8 @@ static int csgs_upd_ctx_apply_locked(struct panthor_device *ptdev, · 255 unmodified lines
1997 if (acked & CSG_STATE_MASK)1983 if (acked & CSG_STATE_MASK)
1998 csg_slot_sync_state_locked(ptdev, csg_id);1984 csg_slot_sync_state_locked(ptdev, csg_id);
1999 1985
2000 if (acked & CSG_STATUS_UPDATE) {1986 if (acked & CSG_STATUS_UPDATE)
2001 csg_slot_sync_queues_state_locked(ptdev, csg_id);1987 csg_slot_sync_queues_state_locked(ptdev, csg_id);
2002 csg_slot_sync_idle_state_locked(ptdev, csg_id);
2003 }
2004 1988
2005 if (ret && acked != req_mask &&1989 if (ret && acked != req_mask &&
2006 ((csg_iface->input->req ^ csg_iface->output->ack) & req_mask) != 0) {1990 ((csg_iface->input->req ^ csg_iface->output->ack) & req_mask) != 0) {
@@ -2020,10 +2004,10 @@ struct panthor_sched_tick_ctx { · 13 unmodified lines
2020 struct list_head groups[PANTHOR_CSG_PRIORITY_COUNT];2004 struct list_head groups[PANTHOR_CSG_PRIORITY_COUNT];
2021 u32 idle_group_count;2005 u32 idle_group_count;
2022 u32 group_count;2006 u32 group_count;
2023 enum panthor_csg_priority min_priority;
2024 struct panthor_vm *vms[MAX_CS_PER_CSG];2007 struct panthor_vm *vms[MAX_CS_PER_CSG];
2025 u32 as_count;2008 u32 as_count;
2026 bool immediate_tick;2009 bool immediate_tick;
2010 bool stop_tick;
2027 u32 csg_upd_failed_mask;2011 u32 csg_upd_failed_mask;
2028};2012};
2029 2013
@@ -2066,17 +2050,21 @@ tick_ctx_pick_groups_from_list(const struct panthor_scheduler *sched, · 36 unmodified lines
2066 if (!owned_by_tick_ctx)2050 if (!owned_by_tick_ctx)
2067 group_get(group);2051 group_get(group);
2068 2052
2069 list_move_tail(&group->run_node, &ctx->groups[group->priority]);
2070 ctx->group_count++;2053 ctx->group_count++;
2054
2055 /* If we have more than one active group with the same priority,
2056 * we need to keep ticking to rotate the CSG priority.
2057 */
2071 if (group_is_idle(group))2058 if (group_is_idle(group))
2072 ctx->idle_group_count++;2059 ctx->idle_group_count++;
2060 else if (!list_empty(&ctx->groups[group->priority]))
2061 ctx->stop_tick = false;
2062
2063 list_move_tail(&group->run_node, &ctx->groups[group->priority]);
2073 2064
2074 if (i == ctx->as_count)2065 if (i == ctx->as_count)
2075 ctx->vms[ctx->as_count++] = group->vm;2066 ctx->vms[ctx->as_count++] = group->vm;
2076 2067
2077 if (ctx->min_priority > group->priority)
2078 ctx->min_priority = group->priority;
2079
2080 if (tick_ctx_is_full(sched, ctx))2068 if (tick_ctx_is_full(sched, ctx))
2081 return;2069 return;
2082 }2070 }
@@ -2085,31 +2073,22 @@ tick_ctx_pick_groups_from_list(const struct panthor_scheduler *sched, · 2 unmodified lines
2085static void2073static void
2086tick_ctx_insert_old_group(struct panthor_scheduler *sched,2074tick_ctx_insert_old_group(struct panthor_scheduler *sched,
2087 struct panthor_sched_tick_ctx *ctx,2075 struct panthor_sched_tick_ctx *ctx,
2088 struct panthor_group *group,2076 struct panthor_group *group)
2089 bool full_tick)
2090{2077{
2091 struct panthor_csg_slot *csg_slot = &sched->csg_slots[group->csg_id];2078 struct panthor_csg_slot *csg_slot = &sched->csg_slots[group->csg_id];
2092 struct panthor_group *other_group;2079 struct panthor_group *other_group;
2093 2080
2094 if (!full_tick) {2081 /* Class groups in descending priority order so we can easily rotate. */
2095 list_add_tail(&group->run_node, &ctx->old_groups[group->priority]);
2096 return;
2097 }
2098
2099 /* Rotate to make sure groups with lower CSG slot
2100 * priorities have a chance to get a higher CSG slot
2101 * priority next time they get picked. This priority
2102 * has an impact on resource request ordering, so it's
2103 * important to make sure we don't let one group starve
2104 * all other groups with the same group priority.
2105 */
2106 list_for_each_entry(other_group,2082 list_for_each_entry(other_group,
2107 &ctx->old_groups[csg_slot->group->priority],2083 &ctx->old_groups[csg_slot->group->priority],
2108 run_node) {2084 run_node) {
2109 struct panthor_csg_slot *other_csg_slot = &sched->csg_slots[other_group->csg_id];2085 struct panthor_csg_slot *other_csg_slot = &sched->csg_slots[other_group->csg_id];
2110 2086
2111 if (other_csg_slot->priority > csg_slot->priority) {2087 /* Our group has a higher prio than the one we're testing against,
2112 list_add_tail(&csg_slot->group->run_node, &other_group->run_node);2088 * place it just before.
2089 */
2090 if (csg_slot->priority > other_csg_slot->priority) {
2091 list_add_tail(&group->run_node, &other_group->run_node);
2113 return;2092 return;
2114 }2093 }
2115 }2094 }
@@ -2119,8 +2098,7 @@ tick_ctx_insert_old_group(struct panthor_scheduler *sched, · 3 unmodified lines
2119 2098
2120static void2099static void
2121tick_ctx_init(struct panthor_scheduler *sched,2100tick_ctx_init(struct panthor_scheduler *sched,
2122 struct panthor_sched_tick_ctx *ctx,2101 struct panthor_sched_tick_ctx *ctx)
2123 bool full_tick)
2124{2102{
2125 struct panthor_device *ptdev = sched->ptdev;2103 struct panthor_device *ptdev = sched->ptdev;
2126 struct panthor_csg_slots_upd_ctx upd_ctx;2104 struct panthor_csg_slots_upd_ctx upd_ctx;
@@ -2130,7 +2108,7 @@ tick_ctx_init(struct panthor_scheduler *sched, · 3 unmodified lines
2130 memset(ctx, 0, sizeof(*ctx));2108 memset(ctx, 0, sizeof(*ctx));
2131 csgs_upd_ctx_init(&upd_ctx);2109 csgs_upd_ctx_init(&upd_ctx);
2132 2110
2133 ctx->min_priority = PANTHOR_CSG_PRIORITY_COUNT;2111 ctx->stop_tick = true;
2134 for (i = 0; i < ARRAY_SIZE(ctx->groups); i++) {2112 for (i = 0; i < ARRAY_SIZE(ctx->groups); i++) {
2135 INIT_LIST_HEAD(&ctx->groups[i]);2113 INIT_LIST_HEAD(&ctx->groups[i]);
2136 INIT_LIST_HEAD(&ctx->old_groups[i]);2114 INIT_LIST_HEAD(&ctx->old_groups[i]);
@@ -2158,7 +2136,7 @@ tick_ctx_init(struct panthor_scheduler *sched, · 21 unmodified lines
2158 group->fatal_queues |= GENMASK(group->queue_count - 1, 0);2136 group->fatal_queues |= GENMASK(group->queue_count - 1, 0);
2159 }2137 }
2160 2138
2161 tick_ctx_insert_old_group(sched, ctx, group, full_tick);2139 tick_ctx_insert_old_group(sched, ctx, group);
2162 csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, i,2140 csgs_upd_ctx_queue_reqs(ptdev, &upd_ctx, i,
2163 csg_iface->output->ack ^ CSG_STATUS_UPDATE,2141 csg_iface->output->ack ^ CSG_STATUS_UPDATE,
2164 CSG_STATUS_UPDATE);2142 CSG_STATUS_UPDATE);
@@ -2442,32 +2420,18 @@ static u64 · 277 unmodified lines
2442tick_ctx_update_resched_target(struct panthor_scheduler *sched,2420tick_ctx_update_resched_target(struct panthor_scheduler *sched,
2443 const struct panthor_sched_tick_ctx *ctx)2421 const struct panthor_sched_tick_ctx *ctx)
2444{2422{
2445 /* We had space left, no need to reschedule until some external event happens. */2423 u64 resched_target;
2446 if (!tick_ctx_is_full(sched, ctx))
2447 goto no_tick;
2448
2449 /* If idle groups were scheduled, no need to wake up until some external
2450 * event happens (group unblocked, new job submitted, ...).
2451 */
2452 if (ctx->idle_group_count)
2453 goto no_tick;
2454 2424
2455 if (drm_WARN_ON(&sched->ptdev->base, ctx->min_priority >= PANTHOR_CSG_PRIORITY_COUNT))2425 if (ctx->stop_tick)
2456 goto no_tick;2426 goto no_tick;
2457 2427
2458 /* If there are groups of the same priority waiting, we need to2428 resched_target = sched->last_tick + sched->tick_period;
2459 * keep the scheduler ticking, otherwise, we'll just wait for
2460 * new groups with higher priority to be queued.
2461 */
2462 if (!list_empty(&sched->groups.runnable[ctx->min_priority])) {
2463 u64 resched_target = sched->last_tick + sched->tick_period;
2464 2429
2465 if (time_before64(sched->resched_target, sched->last_tick) ||2430 if (time_before64(sched->resched_target, sched->last_tick) ||
2466 time_before64(resched_target, sched->resched_target))2431 time_before64(resched_target, sched->resched_target))
2467 sched->resched_target = resched_target;2432 sched->resched_target = resched_target;
2468 2433
2469 return sched->resched_target - sched->last_tick;2434 return sched->resched_target - sched->last_tick;
2470 }
2471 2435
2472no_tick:2436no_tick:
2473 sched->resched_target = U64_MAX;2437 sched->resched_target = U64_MAX;
@@ -2480,9 +2444,11 @@ static void tick_work(struct work_struct *work) · 6 unmodified lines
2480 tick_work.work);2444 tick_work.work);
2481 struct panthor_device *ptdev = sched->ptdev;2445 struct panthor_device *ptdev = sched->ptdev;
2482 struct panthor_sched_tick_ctx ctx;2446 struct panthor_sched_tick_ctx ctx;
2447 u64 resched_target = sched->resched_target;
2483 u64 remaining_jiffies = 0, resched_delay;2448 u64 remaining_jiffies = 0, resched_delay;
2484 u64 now = get_jiffies_64();2449 u64 now = get_jiffies_64();
2485 int prio, ret, cookie;2450 int prio, ret, cookie;
2451 bool full_tick;
2486 2452
2487 if (!drm_dev_enter(&ptdev->base, &cookie))2453 if (!drm_dev_enter(&ptdev->base, &cookie))
2488 return;2454 return;
@@ -2491,18 +2457,24 @@ static void tick_work(struct work_struct *work) · 2 unmodified lines
2491 if (drm_WARN_ON(&ptdev->base, ret))2457 if (drm_WARN_ON(&ptdev->base, ret))
2492 goto out_dev_exit;2458 goto out_dev_exit;
2493 2459
2494 if (time_before64(now, sched->resched_target))2460 /* If the tick is stopped, calculate when the next tick would be */
2495 remaining_jiffies = sched->resched_target - now;2461 if (resched_target == U64_MAX)
2462 resched_target = sched->last_tick + sched->tick_period;
2463
2464 if (time_before64(now, resched_target))
2465 remaining_jiffies = resched_target - now;
2466
2467 full_tick = remaining_jiffies == 0;
2496 2468
2497 mutex_lock(&sched->lock);2469 mutex_lock(&sched->lock);
2498 if (panthor_device_reset_is_pending(sched->ptdev))2470 if (panthor_device_reset_is_pending(sched->ptdev))
2499 goto out_unlock;2471 goto out_unlock;
2500 2472
2501 tick_ctx_init(sched, &ctx, remaining_jiffies != 0);2473 tick_ctx_init(sched, &ctx);
2502 if (ctx.csg_upd_failed_mask)2474 if (ctx.csg_upd_failed_mask)
2503 goto out_cleanup_ctx;2475 goto out_cleanup_ctx;
2504 2476
2505 if (remaining_jiffies) {2477 if (!full_tick) {
2506 /* Scheduling forced in the middle of a tick. Only RT groups2478 /* Scheduling forced in the middle of a tick. Only RT groups
2507 * can preempt non-RT ones. Currently running RT groups can't be2479 * can preempt non-RT ones. Currently running RT groups can't be
2508 * preempted.2480 * preempted.
@@ -2524,9 +2496,29 @@ static void tick_work(struct work_struct *work) · 15 unmodified lines
2524 for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1;2496 for (prio = PANTHOR_CSG_PRIORITY_COUNT - 1;
2525 prio >= 0 && !tick_ctx_is_full(sched, &ctx);2497 prio >= 0 && !tick_ctx_is_full(sched, &ctx);
2526 prio--) {2498 prio--) {
2499 struct panthor_group *old_highest_prio_group =
2500 list_first_entry_or_null(&ctx.old_groups[prio],
2501 struct panthor_group, run_node);
2502
2503 /* Pull out the group with the highest prio for rotation. */
2504 if (old_highest_prio_group)
2505 list_del(&old_highest_prio_group->run_node);
2506
2507 /* Re-insert old active groups so they get a chance to run with higher prio. */
2508 tick_ctx_pick_groups_from_list(sched, &ctx, &ctx.old_groups[prio], true, true);
2509
2510 /* Fill the remaining slots with runnable groups. */
2527 tick_ctx_pick_groups_from_list(sched, &ctx, &sched->groups.runnable[prio],2511 tick_ctx_pick_groups_from_list(sched, &ctx, &sched->groups.runnable[prio],
2528 true, false);2512 true, false);
2529 tick_ctx_pick_groups_from_list(sched, &ctx, &ctx.old_groups[prio], true, true);2513
2514 /* Re-insert the old group with the highest prio, and give it a chance to be
2515 * scheduled again (but with a lower prio) if there's room left.
2516 */
2517 if (old_highest_prio_group) {
2518 list_add_tail(&old_highest_prio_group->run_node, &ctx.old_groups[prio]);
2519 tick_ctx_pick_groups_from_list(sched, &ctx, &ctx.old_groups[prio],
2520 true, true);
2521 }
2530 }2522 }
2531 2523
2532 /* If we have free CSG slots left, pick idle groups */2524 /* If we have free CSG slots left, pick idle groups */
@@ -2651,14 +2643,33 @@ static void sync_upd_work(struct work_struct *work) · 118 unmodified lines
2651 sched_queue_delayed_work(sched, tick, 0);2643 sched_queue_delayed_work(sched, tick, 0);
2652}2644}
2653 2645
2646static void sched_resume_tick(struct panthor_device *ptdev)
2647{
2648 struct panthor_scheduler *sched = ptdev->scheduler;
2649 u64 delay_jiffies, now;
2650
2651 drm_WARN_ON(&ptdev->base, sched->resched_target != U64_MAX);
2652
2653 /* Scheduler tick was off, recalculate the resched_target based on the
2654 * last tick event, and queue the scheduler work.
2655 */
2656 now = get_jiffies_64();
2657 sched->resched_target = sched->last_tick + sched->tick_period;
2658 if (sched->used_csg_slot_count == sched->csg_slot_count &&
2659 time_before64(now, sched->resched_target))
2660 delay_jiffies = min_t(unsigned long, sched->resched_target - now, ULONG_MAX);
2661 else
2662 delay_jiffies = 0;
2663
2664 sched_queue_delayed_work(sched, tick, delay_jiffies);
2665}
2666
2654static void group_schedule_locked(struct panthor_group *group, u32 queue_mask)2667static void group_schedule_locked(struct panthor_group *group, u32 queue_mask)
2655{2668{
2656 struct panthor_device *ptdev = group->ptdev;2669 struct panthor_device *ptdev = group->ptdev;
2657 struct panthor_scheduler *sched = ptdev->scheduler;2670 struct panthor_scheduler *sched = ptdev->scheduler;
2658 struct list_head *queue = &sched->groups.runnable[group->priority];2671 struct list_head *queue = &sched->groups.runnable[group->priority];
2659 u64 delay_jiffies = 0;
2660 bool was_idle;2672 bool was_idle;
2661 u64 now;
2662 2673
2663 if (!group_can_run(group))2674 if (!group_can_run(group))
2664 return;2675 return;
@@ -2703,13 +2714,7 @@ static void group_schedule_locked(struct panthor_group *group, u32 queue_mask) · 38 unmodified lines
2703 /* Scheduler tick was off, recalculate the resched_target based on the2714 /* Scheduler tick was off, recalculate the resched_target based on the
2704 * last tick event, and queue the scheduler work.2715 * last tick event, and queue the scheduler work.
2705 */2716 */
2706 now = get_jiffies_64();2717 sched_resume_tick(ptdev);
2707 sched->resched_target = sched->last_tick + sched->tick_period;
2708 if (sched->used_csg_slot_count == sched->csg_slot_count &&
2709 time_before64(now, sched->resched_target))
2710 delay_jiffies = min_t(unsigned long, sched->resched_target - now, ULONG_MAX);
2711
2712 sched_queue_delayed_work(sched, tick, delay_jiffies);
2713}2718}
2714 2719
2715static void queue_stop(struct panthor_queue *queue,2720static void queue_stop(struct panthor_queue *queue,
@@ -2767,13 +2772,6 @@ static void panthor_group_start(struct panthor_group *group) · 51 unmodified lines
2767 group_put(group);2772 group_put(group);
2768}2773}
2769 2774
2770static void panthor_sched_immediate_tick(struct panthor_device *ptdev)
2771{
2772 struct panthor_scheduler *sched = ptdev->scheduler;
2773
2774 sched_queue_delayed_work(sched, tick, 0);
2775}
2776
2777/**2775/**
2778 * panthor_sched_report_mmu_fault() - Report MMU faults to the scheduler.2776 * panthor_sched_report_mmu_fault() - Report MMU faults to the scheduler.
2779 */2777 */
@@ -2781,13 +2779,13 @@ void panthor_sched_report_mmu_fault(struct panthor_device *ptdev) · 1 unmodified line
2781{2779{
2782 /* Force a tick to immediately kill faulty groups. */2780 /* Force a tick to immediately kill faulty groups. */
2783 if (ptdev->scheduler)2781 if (ptdev->scheduler)
2784 panthor_sched_immediate_tick(ptdev);2782 sched_queue_delayed_work(ptdev->scheduler, tick, 0);
2785}2783}
2786 2784
2787void panthor_sched_resume(struct panthor_device *ptdev)2785void panthor_sched_resume(struct panthor_device *ptdev)
2788{2786{
2789 /* Force a tick to re-evaluate after a resume. */2787 /* Force a tick to re-evaluate after a resume. */
2790 panthor_sched_immediate_tick(ptdev);2788 sched_queue_delayed_work(ptdev->scheduler, tick, 0);
2791}2789}
2792 2790
2793void panthor_sched_suspend(struct panthor_device *ptdev)2791void panthor_sched_suspend(struct panthor_device *ptdev)
@@ -2943,8 +2941,6 @@ void panthor_sched_pre_reset(struct panthor_device *ptdev) · 149 unmodified lines
2943 * new jobs while we're resetting.2941 * new jobs while we're resetting.
2944 */2942 */
2945 for (i = 0; i < ARRAY_SIZE(sched->groups.runnable); i++) {2943 for (i = 0; i < ARRAY_SIZE(sched->groups.runnable); i++) {
2946 /* All groups should be in the idle lists. */
2947 drm_WARN_ON(&ptdev->base, !list_empty(&sched->groups.runnable[i]));
2948 list_for_each_entry_safe(group, group_tmp, &sched->groups.runnable[i], run_node)2944 list_for_each_entry_safe(group, group_tmp, &sched->groups.runnable[i], run_node)
2949 panthor_group_stop(group);2945 panthor_group_stop(group);
2950 }2946 }
@@ -3343,6 +3339,18 @@ queue_run_job(struct drm_sched_job *sched_job) · 392 unmodified lines
3343 if (group->csg_id < 0) {3339 if (group->csg_id < 0) {
3344 group_schedule_locked(group, BIT(job->queue_idx));3340 group_schedule_locked(group, BIT(job->queue_idx));
3345 } else {3341 } else {
3342 u32 queue_mask = BIT(job->queue_idx);
3343 bool resume_tick = group_is_idle(group) &&
3344 (group->idle_queues & queue_mask) &&
3345 !(group->blocked_queues & queue_mask) &&
3346 sched->resched_target == U64_MAX;
3347
3348 /* We just added something to the queue, so it's no longer idle. */
3349 group->idle_queues &= ~queue_mask;
3350
3351 if (resume_tick)
3352 sched_resume_tick(ptdev);
3353
3346 gpu_write(ptdev, CSF_DOORBELL(queue->doorbell_id), 1);3354 gpu_write(ptdev, CSF_DOORBELL(queue->doorbell_id), 1);
3347 if (!sched->pm.has_ref &&3355 if (!sched->pm.has_ref &&
3348 !(group->blocked_queues & BIT(job->queue_idx))) {3356 !(group->blocked_queues & BIT(job->queue_idx))) {
drivers/gpu/drm/pl111/pl111_display.c+2−2
@@ -138,7 +138,7 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, · 137 unmodified lines
138 138
139 ret = clk_set_rate(priv->clk, mode->clock * 1000);139 ret = clk_set_rate(priv->clk, mode->clock * 1000);
140 if (ret) {140 if (ret) {
141 dev_err(drm->dev,141 drm_err(drm,
142 "Failed to set pixel clock rate to %d: %d\n",142 "Failed to set pixel clock rate to %d: %d\n",
143 mode->clock * 1000, ret);143 mode->clock * 1000, ret);
144 }144 }
@@ -553,7 +553,7 @@ pl111_init_clock_divider(struct drm_device *drm) · 408 unmodified lines
553 int ret;553 int ret;
554 554
555 if (IS_ERR(parent)) {555 if (IS_ERR(parent)) {
556 dev_err(drm->dev, "CLCD: unable to get clcdclk.\n");556 drm_err(drm, "CLCD: unable to get clcdclk.\n");
557 return PTR_ERR(parent);557 return PTR_ERR(parent);
558 }558 }
559 559
drivers/gpu/drm/pl111/pl111_drv.c+15−14
@@ -55,6 +55,7 @@ · 54 unmodified lines
55#include <drm/drm_gem_framebuffer_helper.h>55#include <drm/drm_gem_framebuffer_helper.h>
56#include <drm/drm_of.h>56#include <drm/drm_of.h>
57#include <drm/drm_panel.h>57#include <drm/drm_panel.h>
58#include <drm/drm_print.h>
58#include <drm/drm_probe_helper.h>59#include <drm/drm_probe_helper.h>
59#include <drm/drm_vblank.h>60#include <drm/drm_vblank.h>
60 61
@@ -98,7 +99,7 @@ static int pl111_modeset_init(struct drm_device *dev) · 37 unmodified lines
98 struct drm_panel *tmp_panel;99 struct drm_panel *tmp_panel;
99 struct drm_bridge *tmp_bridge;100 struct drm_bridge *tmp_bridge;
100 101
101 dev_dbg(dev->dev, "checking endpoint %d\n", i);102 drm_dbg(dev, "checking endpoint %d\n", i);
102 103
103 ret = drm_of_find_panel_or_bridge(dev->dev->of_node,104 ret = drm_of_find_panel_or_bridge(dev->dev->of_node,
104 0, i,105 0, i,
@@ -114,18 +115,18 @@ static int pl111_modeset_init(struct drm_device *dev) · 9 unmodified lines
114 defer = true;115 defer = true;
115 } else if (ret != -ENODEV) {116 } else if (ret != -ENODEV) {
116 /* Continue, maybe something else is working */117 /* Continue, maybe something else is working */
117 dev_err(dev->dev,118 drm_err(dev,
118 "endpoint %d returns %d\n", i, ret);119 "endpoint %d returns %d\n", i, ret);
119 }120 }
120 }121 }
121 122
122 if (tmp_panel) {123 if (tmp_panel) {
123 dev_info(dev->dev,124 drm_info(dev,
124 "found panel on endpoint %d\n", i);125 "found panel on endpoint %d\n", i);
125 panel = tmp_panel;126 panel = tmp_panel;
126 }127 }
127 if (tmp_bridge) {128 if (tmp_bridge) {
128 dev_info(dev->dev,129 drm_info(dev,
129 "found bridge on endpoint %d\n", i);130 "found bridge on endpoint %d\n", i);
130 bridge = tmp_bridge;131 bridge = tmp_bridge;
131 }132 }
@@ -149,9 +150,9 @@ static int pl111_modeset_init(struct drm_device *dev) · 17 unmodified lines
149 goto finish;150 goto finish;
150 }151 }
151 } else if (bridge) {152 } else if (bridge) {
152 dev_info(dev->dev, "Using non-panel bridge\n");153 drm_info(dev, "Using non-panel bridge\n");
153 } else {154 } else {
154 dev_err(dev->dev, "No bridge, exiting\n");155 drm_err(dev, "No bridge, exiting\n");
155 return -ENODEV;156 return -ENODEV;
156 }157 }
157 158
@@ -163,7 +164,7 @@ static int pl111_modeset_init(struct drm_device *dev) · 5 unmodified lines
163 164
164 ret = pl111_display_init(dev);165 ret = pl111_display_init(dev);
165 if (ret != 0) {166 if (ret != 0) {
166 dev_err(dev->dev, "Failed to init display\n");167 drm_err(dev, "Failed to init display\n");
167 goto out_bridge;168 goto out_bridge;
168 }169 }
169 170
@@ -175,7 +176,7 @@ static int pl111_modeset_init(struct drm_device *dev) · 5 unmodified lines
175 if (!priv->variant->broken_vblank) {176 if (!priv->variant->broken_vblank) {
176 ret = drm_vblank_init(dev, 1);177 ret = drm_vblank_init(dev, 1);
177 if (ret != 0) {178 if (ret != 0) {
178 dev_err(dev->dev, "Failed to init vblank\n");179 drm_err(dev, "Failed to init vblank\n");
179 goto out_bridge;180 goto out_bridge;
180 }181 }
181 }182 }
@@ -255,13 +256,13 @@ static int pl111_amba_probe(struct amba_device *amba_dev, · 73 unmodified lines
255 256
256 ret = of_reserved_mem_device_init(dev);257 ret = of_reserved_mem_device_init(dev);
257 if (!ret) {258 if (!ret) {
258 dev_info(dev, "using device-specific reserved memory\n");259 drm_info(drm, "using device-specific reserved memory\n");
259 priv->use_device_memory = true;260 priv->use_device_memory = true;
260 }261 }
261 262
262 if (of_property_read_u32(dev->of_node, "max-memory-bandwidth",263 if (of_property_read_u32(dev->of_node, "max-memory-bandwidth",
263 &priv->memory_bw)) {264 &priv->memory_bw)) {
264 dev_info(dev, "no max memory bandwidth specified, assume unlimited\n");265 drm_info(drm, "no max memory bandwidth specified, assume unlimited\n");
265 priv->memory_bw = 0;266 priv->memory_bw = 0;
266 }267 }
267 268
@@ -276,17 +277,17 @@ static int pl111_amba_probe(struct amba_device *amba_dev, · 8 unmodified lines
276 277
277 priv->regs = devm_ioremap_resource(dev, &amba_dev->res);278 priv->regs = devm_ioremap_resource(dev, &amba_dev->res);
278 if (IS_ERR(priv->regs)) {279 if (IS_ERR(priv->regs)) {
279 dev_err(dev, "%s failed mmio\n", __func__);280 drm_err(drm, "%s failed mmio\n", __func__);
280 ret = PTR_ERR(priv->regs);281 ret = PTR_ERR(priv->regs);
281 goto dev_put;282 goto dev_put;
282 }283 }
283 284
284 /* This may override some variant settings */285 /* This may override some variant settings */
285 ret = pl111_versatile_init(dev, priv);286 ret = pl111_versatile_init(drm, priv);
286 if (ret)287 if (ret)
287 goto dev_put;288 goto dev_put;
288 289
289 pl111_nomadik_init(dev);290 pl111_nomadik_init(drm);
290 291
291 /* turn off interrupts before requesting the irq */292 /* turn off interrupts before requesting the irq */
292 writel(0, priv->regs + priv->ienb);293 writel(0, priv->regs + priv->ienb);
@@ -294,7 +295,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev, · 1 unmodified line
294 ret = devm_request_irq(dev, amba_dev->irq[0], pl111_irq, 0,295 ret = devm_request_irq(dev, amba_dev->irq[0], pl111_irq, 0,
295 variant->name, priv);296 variant->name, priv);
296 if (ret != 0) {297 if (ret != 0) {
297 dev_err(dev, "%s failed irq %d\n", __func__, ret);298 drm_err(drm, "%s failed irq %d\n", __func__, ret);
298 return ret;299 return ret;
299 }300 }
300 301
drivers/gpu/drm/pl111/pl111_nomadik.c+2−2
@@ -9,7 +9,7 @@ · 8 unmodified lines
9#define PMU_CTRL_OFFSET 0x00009#define PMU_CTRL_OFFSET 0x0000
10#define PMU_CTRL_LCDNDIF BIT(26)10#define PMU_CTRL_LCDNDIF BIT(26)
11 11
12void pl111_nomadik_init(struct device *dev)12void pl111_nomadik_init(struct drm_device *dev)
13{13{
14 struct regmap *pmu_regmap;14 struct regmap *pmu_regmap;
15 15
@@ -31,6 +31,6 @@ void pl111_nomadik_init(struct device *dev) · 15 unmodified lines
31 PMU_CTRL_OFFSET,31 PMU_CTRL_OFFSET,
32 PMU_CTRL_LCDNDIF,32 PMU_CTRL_LCDNDIF,
33 0);33 0);
34 dev_info(dev, "set Nomadik PMU mux to CLCD mode\n");34 drm_info(dev, "set Nomadik PMU mux to CLCD mode\n");
35}35}
36EXPORT_SYMBOL_GPL(pl111_nomadik_init);36EXPORT_SYMBOL_GPL(pl111_nomadik_init);
drivers/gpu/drm/pl111/pl111_nomadik.h+2−2
@@ -8,11 +8,11 @@ struct device; · 7 unmodified lines
8 8
9#ifdef CONFIG_ARCH_NOMADIK9#ifdef CONFIG_ARCH_NOMADIK
10 10
11void pl111_nomadik_init(struct device *dev);11void pl111_nomadik_init(struct drm_device *dev);
12 12
13#else13#else
14 14
15static inline void pl111_nomadik_init(struct device *dev)15static inline void pl111_nomadik_init(struct drm_device *dev)
16{16{
17}17}
18 18
drivers/gpu/drm/pl111/pl111_versatile.c+27−26
@@ -20,6 +20,7 @@ · 19 unmodified lines
20#include <linux/vexpress.h>20#include <linux/vexpress.h>
21 21
22#include <drm/drm_fourcc.h>22#include <drm/drm_fourcc.h>
23#include <drm/drm_print.h>
23 24
24#include "pl111_versatile.h"25#include "pl111_versatile.h"
25#include "pl111_drm.h"26#include "pl111_drm.h"
@@ -116,7 +117,7 @@ static void pl111_integrator_enable(struct drm_device *drm, u32 format) · 90 unmodified lines
116{117{
117 u32 val;118 u32 val;
118 119
119 dev_info(drm->dev, "enable Integrator CLCD connectors\n");120 drm_info(drm, "enable Integrator CLCD connectors\n");
120 121
121 /* FIXME: really needed? */122 /* FIXME: really needed? */
122 val = INTEGRATOR_CLCD_LCD_STATIC1 | INTEGRATOR_CLCD_LCD_STATIC2 |123 val = INTEGRATOR_CLCD_LCD_STATIC1 | INTEGRATOR_CLCD_LCD_STATIC2 |
@@ -134,7 +135,7 @@ static void pl111_integrator_enable(struct drm_device *drm, u32 format) · 11 unmodified lines
134 val |= INTEGRATOR_CLCD_LCDMUX_VGA555;135 val |= INTEGRATOR_CLCD_LCDMUX_VGA555;
135 break;136 break;
136 default:137 default:
137 dev_err(drm->dev, "unhandled format on Integrator 0x%08x\n",138 drm_err(drm, "unhandled format on Integrator 0x%08x\n",
138 format);139 format);
139 break;140 break;
140 }141 }
@@ -156,7 +157,7 @@ static void pl111_impd1_enable(struct drm_device *drm, u32 format) · 15 unmodified lines
156{157{
157 u32 val;158 u32 val;
158 159
159 dev_info(drm->dev, "enable IM-PD1 CLCD connectors\n");160 drm_info(drm, "enable IM-PD1 CLCD connectors\n");
160 val = IMPD1_CTRL_DISP_VGA | IMPD1_CTRL_DISP_ENABLE;161 val = IMPD1_CTRL_DISP_VGA | IMPD1_CTRL_DISP_ENABLE;
161 162
162 regmap_update_bits(versatile_syscon_map,163 regmap_update_bits(versatile_syscon_map,
@@ -167,7 +168,7 @@ static void pl111_impd1_enable(struct drm_device *drm, u32 format) · 4 unmodified lines
167 168
168static void pl111_impd1_disable(struct drm_device *drm)169static void pl111_impd1_disable(struct drm_device *drm)
169{170{
170 dev_info(drm->dev, "disable IM-PD1 CLCD connectors\n");171 drm_info(drm, "disable IM-PD1 CLCD connectors\n");
171 172
172 regmap_update_bits(versatile_syscon_map,173 regmap_update_bits(versatile_syscon_map,
173 IMPD1_CTRL_OFFSET,174 IMPD1_CTRL_OFFSET,
@@ -194,7 +195,7 @@ static void pl111_impd1_disable(struct drm_device *drm) · 20 unmodified lines
194 195
195static void pl111_versatile_disable(struct drm_device *drm)196static void pl111_versatile_disable(struct drm_device *drm)
196{197{
197 dev_info(drm->dev, "disable Versatile CLCD connectors\n");198 drm_info(drm, "disable Versatile CLCD connectors\n");
198 regmap_update_bits(versatile_syscon_map,199 regmap_update_bits(versatile_syscon_map,
199 SYS_CLCD,200 SYS_CLCD,
200 SYS_CLCD_CONNECTOR_MASK,201 SYS_CLCD_CONNECTOR_MASK,
@@ -205,7 +206,7 @@ static void pl111_versatile_enable(struct drm_device *drm, u32 format) · 4 unmodified lines
205{206{
206 u32 val = 0;207 u32 val = 0;
207 208
208 dev_info(drm->dev, "enable Versatile CLCD connectors\n");209 drm_info(drm, "enable Versatile CLCD connectors\n");
209 210
210 switch (format) {211 switch (format) {
211 case DRM_FORMAT_ABGR8888:212 case DRM_FORMAT_ABGR8888:
@@ -227,7 +228,7 @@ static void pl111_versatile_enable(struct drm_device *drm, u32 format) · 15 unmodified lines
227 val |= SYS_CLCD_MODE_5551;228 val |= SYS_CLCD_MODE_5551;
228 break;229 break;
229 default:230 default:
230 dev_err(drm->dev, "unhandled format on Versatile 0x%08x\n",231 drm_err(drm, "unhandled format on Versatile 0x%08x\n",
231 format);232 format);
232 break;233 break;
233 }234 }
@@ -247,7 +248,7 @@ static void pl111_versatile_enable(struct drm_device *drm, u32 format) · 13 unmodified lines
247 248
248static void pl111_realview_clcd_disable(struct drm_device *drm)249static void pl111_realview_clcd_disable(struct drm_device *drm)
249{250{
250 dev_info(drm->dev, "disable RealView CLCD connectors\n");251 drm_info(drm, "disable RealView CLCD connectors\n");
251 regmap_update_bits(versatile_syscon_map,252 regmap_update_bits(versatile_syscon_map,
252 SYS_CLCD,253 SYS_CLCD,
253 SYS_CLCD_CONNECTOR_MASK,254 SYS_CLCD_CONNECTOR_MASK,
@@ -256,7 +257,7 @@ static void pl111_realview_clcd_disable(struct drm_device *drm) · 2 unmodified lines
256 257
257static void pl111_realview_clcd_enable(struct drm_device *drm, u32 format)258static void pl111_realview_clcd_enable(struct drm_device *drm, u32 format)
258{259{
259 dev_info(drm->dev, "enable RealView CLCD connectors\n");260 drm_info(drm, "enable RealView CLCD connectors\n");
260 regmap_update_bits(versatile_syscon_map,261 regmap_update_bits(versatile_syscon_map,
261 SYS_CLCD,262 SYS_CLCD,
262 SYS_CLCD_CONNECTOR_MASK,263 SYS_CLCD_CONNECTOR_MASK,
@@ -376,7 +377,7 @@ static const struct pl111_variant_data pl111_vexpress = { · 113 unmodified lines
376#define VEXPRESS_FPGAMUX_DAUGHTERBOARD_1 0x01377#define VEXPRESS_FPGAMUX_DAUGHTERBOARD_1 0x01
377#define VEXPRESS_FPGAMUX_DAUGHTERBOARD_2 0x02378#define VEXPRESS_FPGAMUX_DAUGHTERBOARD_2 0x02
378 379
379static int pl111_vexpress_clcd_init(struct device *dev, struct device_node *np,380static int pl111_vexpress_clcd_init(struct drm_device *dev, struct device_node *np,
380 struct pl111_drm_dev_private *priv)381 struct pl111_drm_dev_private *priv)
381{382{
382 struct platform_device *pdev;383 struct platform_device *pdev;
@@ -433,22 +434,22 @@ static int pl111_vexpress_clcd_init(struct device *dev, struct device_node *np, · 50 unmodified lines
433 mux_motherboard = false;434 mux_motherboard = false;
434 435
435 if (mux_motherboard) {436 if (mux_motherboard) {
436 dev_info(dev, "DVI muxed to motherboard CLCD\n");437 drm_info(dev, "DVI muxed to motherboard CLCD\n");
437 val = VEXPRESS_FPGAMUX_MOTHERBOARD;438 val = VEXPRESS_FPGAMUX_MOTHERBOARD;
438 } else if (ct_clcd == dev->of_node) {439 } else if (ct_clcd == dev->dev->of_node) {
439 dev_info(dev,440 drm_info(dev,
440 "DVI muxed to daughterboard 1 (core tile) CLCD\n");441 "DVI muxed to daughterboard 1 (core tile) CLCD\n");
441 val = VEXPRESS_FPGAMUX_DAUGHTERBOARD_1;442 val = VEXPRESS_FPGAMUX_DAUGHTERBOARD_1;
442 } else {443 } else {
443 dev_info(dev, "core tile graphics present\n");444 drm_info(dev, "core tile graphics present\n");
444 dev_info(dev, "this device will be deactivated\n");445 drm_info(dev, "this device will be deactivated\n");
445 return -ENODEV;446 return -ENODEV;
446 }447 }
447 448
448 /* Call into deep Vexpress configuration API */449 /* Call into deep Vexpress configuration API */
449 pdev = of_find_device_by_node(np);450 pdev = of_find_device_by_node(np);
450 if (!pdev) {451 if (!pdev) {
451 dev_err(dev, "can't find the sysreg device, deferring\n");452 drm_err(dev, "can't find the sysreg device, deferring\n");
452 return -EPROBE_DEFER;453 return -EPROBE_DEFER;
453 }454 }
454 455
@@ -461,17 +462,17 @@ static int pl111_vexpress_clcd_init(struct device *dev, struct device_node *np, · 6 unmodified lines
461 ret = regmap_write(map, 0, val);462 ret = regmap_write(map, 0, val);
462 platform_device_put(pdev);463 platform_device_put(pdev);
463 if (ret) {464 if (ret) {
464 dev_err(dev, "error setting DVI muxmode\n");465 drm_err(dev, "error setting DVI muxmode\n");
465 return -ENODEV;466 return -ENODEV;
466 }467 }
467 468
468 priv->variant = &pl111_vexpress;469 priv->variant = &pl111_vexpress;
469 dev_info(dev, "initializing Versatile Express PL111\n");470 drm_info(dev, "initializing Versatile Express PL111\n");
470 471
471 return 0;472 return 0;
472}473}
473 474
474int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv)475int pl111_versatile_init(struct drm_device *dev, struct pl111_drm_dev_private *priv)
475{476{
476 const struct of_device_id *clcd_id;477 const struct of_device_id *clcd_id;
477 enum versatile_clcd versatile_clcd_type;478 enum versatile_clcd versatile_clcd_type;
@@ -492,7 +493,7 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv) · 14 unmodified lines
492 int ret = pl111_vexpress_clcd_init(dev, np, priv);493 int ret = pl111_vexpress_clcd_init(dev, np, priv);
493 of_node_put(np);494 of_node_put(np);
494 if (ret)495 if (ret)
495 dev_err(dev, "Versatile Express init failed - %d", ret);496 drm_err(dev, "Versatile Express init failed - %d", ret);
496 return ret;497 return ret;
497 }498 }
498 499
@@ -511,7 +512,7 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv) · 12 unmodified lines
511 map = syscon_node_to_regmap(np);512 map = syscon_node_to_regmap(np);
512 of_node_put(np);513 of_node_put(np);
513 if (IS_ERR(map)) {514 if (IS_ERR(map)) {
514 dev_err(dev, "no Versatile syscon regmap\n");515 drm_err(dev, "no Versatile syscon regmap\n");
515 return PTR_ERR(map);516 return PTR_ERR(map);
516 }517 }
517 518
@@ -520,14 +521,14 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv) · 2 unmodified lines
520 versatile_syscon_map = map;521 versatile_syscon_map = map;
521 priv->variant = &pl110_integrator;522 priv->variant = &pl110_integrator;
522 priv->variant_display_enable = pl111_integrator_enable;523 priv->variant_display_enable = pl111_integrator_enable;
523 dev_info(dev, "set up callbacks for Integrator PL110\n");524 drm_info(dev, "set up callbacks for Integrator PL110\n");
524 break;525 break;
525 case INTEGRATOR_IMPD1:526 case INTEGRATOR_IMPD1:
526 versatile_syscon_map = map;527 versatile_syscon_map = map;
527 priv->variant = &pl110_impd1;528 priv->variant = &pl110_impd1;
528 priv->variant_display_enable = pl111_impd1_enable;529 priv->variant_display_enable = pl111_impd1_enable;
529 priv->variant_display_disable = pl111_impd1_disable;530 priv->variant_display_disable = pl111_impd1_disable;
530 dev_info(dev, "set up callbacks for IM-PD1 PL110\n");531 drm_info(dev, "set up callbacks for IM-PD1 PL110\n");
531 break;532 break;
532 case VERSATILE_CLCD:533 case VERSATILE_CLCD:
533 versatile_syscon_map = map;534 versatile_syscon_map = map;
@@ -542,7 +543,7 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv) · 8 unmodified lines
542 */543 */
543 priv->ienb = CLCD_PL111_IENB;544 priv->ienb = CLCD_PL111_IENB;
544 priv->ctrl = CLCD_PL111_CNTL;545 priv->ctrl = CLCD_PL111_CNTL;
545 dev_info(dev, "set up callbacks for Versatile PL110\n");546 drm_info(dev, "set up callbacks for Versatile PL110\n");
546 break;547 break;
547 case REALVIEW_CLCD_EB:548 case REALVIEW_CLCD_EB:
548 case REALVIEW_CLCD_PB1176:549 case REALVIEW_CLCD_PB1176:
@@ -553,10 +554,10 @@ int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv) · 4 unmodified lines
553 priv->variant = &pl111_realview;554 priv->variant = &pl111_realview;
554 priv->variant_display_enable = pl111_realview_clcd_enable;555 priv->variant_display_enable = pl111_realview_clcd_enable;
555 priv->variant_display_disable = pl111_realview_clcd_disable;556 priv->variant_display_disable = pl111_realview_clcd_disable;
556 dev_info(dev, "set up callbacks for RealView PL111\n");557 drm_info(dev, "set up callbacks for RealView PL111\n");
557 break;558 break;
558 default:559 default:
559 dev_info(dev, "unknown Versatile system controller\n");560 drm_info(dev, "unknown Versatile system controller\n");
560 break;561 break;
561 }562 }
562 563
drivers/gpu/drm/pl111/pl111_versatile.h+1−1
@@ -7,6 +7,6 @@ · 6 unmodified lines
7struct device;7struct device;
8struct pl111_drm_dev_private;8struct pl111_drm_dev_private;
9 9
10int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv);10int pl111_versatile_init(struct drm_device *dev, struct pl111_drm_dev_private *priv);
11 11
12#endif12#endif
drivers/gpu/drm/radeon/atombios_crtc.c+19−55
@@ -1133,7 +1133,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode · 1132 unmodified lines
1133 1133
1134static int dce4_crtc_do_set_base(struct drm_crtc *crtc,1134static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
1135 struct drm_framebuffer *fb,1135 struct drm_framebuffer *fb,
1136 int x, int y, int atomic)1136 int x, int y)
1137{1137{
1138 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);1138 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1139 struct drm_device *dev = crtc->dev;1139 struct drm_device *dev = crtc->dev;
@@ -1150,33 +1150,23 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, · 10 unmodified lines
1150 bool bypass_lut = false;1150 bool bypass_lut = false;
1151 1151
1152 /* no fb bound */1152 /* no fb bound */
1153 if (!atomic && !crtc->primary->fb) {1153 if (!crtc->primary->fb) {
1154 DRM_DEBUG_KMS("No FB bound\n");1154 DRM_DEBUG_KMS("No FB bound\n");
1155 return 0;1155 return 0;
1156 }1156 }
1157 1157
1158 if (atomic)1158 target_fb = crtc->primary->fb;
1159 target_fb = fb;
1160 else
1161 target_fb = crtc->primary->fb;
1162 1159
1163 /* If atomic, assume fb object is pinned & idle & fenced and
1164 * just update base pointers
1165 */
1166 obj = target_fb->obj[0];1160 obj = target_fb->obj[0];
1167 rbo = gem_to_radeon_bo(obj);1161 rbo = gem_to_radeon_bo(obj);
1168 r = radeon_bo_reserve(rbo, false);1162 r = radeon_bo_reserve(rbo, false);
1169 if (unlikely(r != 0))1163 if (unlikely(r != 0))
1170 return r;1164 return r;
1171 1165
1172 if (atomic)1166 r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
1173 fb_location = radeon_bo_gpu_offset(rbo);1167 if (unlikely(r != 0)) {
1174 else {1168 radeon_bo_unreserve(rbo);
1175 r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);1169 return -EINVAL;
1176 if (unlikely(r != 0)) {
1177 radeon_bo_unreserve(rbo);
1178 return -EINVAL;
1179 }
1180 }1170 }
1181 1171
1182 radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);1172 radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
@@ -1437,7 +1427,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, · 254 unmodified lines
1437 /* set pageflip to happen anywhere in vblank interval */1427 /* set pageflip to happen anywhere in vblank interval */
1438 WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);1428 WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
1439 1429
1440 if (!atomic && fb && fb != crtc->primary->fb) {1430 if (fb && fb != crtc->primary->fb) {
1441 rbo = gem_to_radeon_bo(fb->obj[0]);1431 rbo = gem_to_radeon_bo(fb->obj[0]);
1442 r = radeon_bo_reserve(rbo, false);1432 r = radeon_bo_reserve(rbo, false);
1443 if (unlikely(r != 0))1433 if (unlikely(r != 0))
@@ -1454,7 +1444,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, · 10 unmodified lines
1454 1444
1455static int avivo_crtc_do_set_base(struct drm_crtc *crtc,1445static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
1456 struct drm_framebuffer *fb,1446 struct drm_framebuffer *fb,
1457 int x, int y, int atomic)1447 int x, int y)
1458{1448{
1459 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);1449 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
1460 struct drm_device *dev = crtc->dev;1450 struct drm_device *dev = crtc->dev;
@@ -1470,15 +1460,12 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, · 9 unmodified lines
1470 bool bypass_lut = false;1460 bool bypass_lut = false;
1471 1461
1472 /* no fb bound */1462 /* no fb bound */
1473 if (!atomic && !crtc->primary->fb) {1463 if (!crtc->primary->fb) {
1474 DRM_DEBUG_KMS("No FB bound\n");1464 DRM_DEBUG_KMS("No FB bound\n");
1475 return 0;1465 return 0;
1476 }1466 }
1477 1467
1478 if (atomic)1468 target_fb = crtc->primary->fb;
1479 target_fb = fb;
1480 else
1481 target_fb = crtc->primary->fb;
1482 1469
1483 obj = target_fb->obj[0];1470 obj = target_fb->obj[0];
1484 rbo = gem_to_radeon_bo(obj);1471 rbo = gem_to_radeon_bo(obj);
@@ -1486,17 +1473,10 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, · 1 unmodified line
1486 if (unlikely(r != 0))1473 if (unlikely(r != 0))
1487 return r;1474 return r;
1488 1475
1489 /* If atomic, assume fb object is pinned & idle & fenced and1476 r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
1490 * just update base pointers1477 if (unlikely(r != 0)) {
1491 */1478 radeon_bo_unreserve(rbo);
1492 if (atomic)1479 return -EINVAL;
1493 fb_location = radeon_bo_gpu_offset(rbo);
1494 else {
1495 r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
1496 if (unlikely(r != 0)) {
1497 radeon_bo_unreserve(rbo);
1498 return -EINVAL;
1499 }
1500 }1480 }
1501 radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);1481 radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
1502 radeon_bo_unreserve(rbo);1482 radeon_bo_unreserve(rbo);
@@ -1645,7 +1625,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, · 142 unmodified lines
1645 /* set pageflip to happen only at start of vblank interval (front porch) */1625 /* set pageflip to happen only at start of vblank interval (front porch) */
1646 WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);1626 WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 3);
1647 1627
1648 if (!atomic && fb && fb != crtc->primary->fb) {1628 if (fb && fb != crtc->primary->fb) {
1649 rbo = gem_to_radeon_bo(fb->obj[0]);1629 rbo = gem_to_radeon_bo(fb->obj[0]);
1650 r = radeon_bo_reserve(rbo, false);1630 r = radeon_bo_reserve(rbo, false);
1651 if (unlikely(r != 0))1631 if (unlikely(r != 0))
@@ -1667,26 +1647,11 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, · 15 unmodified lines
1667 struct radeon_device *rdev = dev->dev_private;1647 struct radeon_device *rdev = dev->dev_private;
1668 1648
1669 if (ASIC_IS_DCE4(rdev))1649 if (ASIC_IS_DCE4(rdev))
1670 return dce4_crtc_do_set_base(crtc, old_fb, x, y, 0);1650 return dce4_crtc_do_set_base(crtc, old_fb, x, y);
1671 else if (ASIC_IS_AVIVO(rdev))
1672 return avivo_crtc_do_set_base(crtc, old_fb, x, y, 0);
1673 else
1674 return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0);
1675}
1676
1677int atombios_crtc_set_base_atomic(struct drm_crtc *crtc,
1678 struct drm_framebuffer *fb,
1679 int x, int y, enum mode_set_atomic state)
1680{
1681 struct drm_device *dev = crtc->dev;
1682 struct radeon_device *rdev = dev->dev_private;
1683
1684 if (ASIC_IS_DCE4(rdev))
1685 return dce4_crtc_do_set_base(crtc, fb, x, y, 1);
1686 else if (ASIC_IS_AVIVO(rdev))1651 else if (ASIC_IS_AVIVO(rdev))
1687 return avivo_crtc_do_set_base(crtc, fb, x, y, 1);1652 return avivo_crtc_do_set_base(crtc, old_fb, x, y);
1688 else1653 else
1689 return radeon_crtc_do_set_base(crtc, fb, x, y, 1);1654 return radeon_crtc_do_set_base(crtc, old_fb, x, y);
1690}1655}
1691 1656
1692/* properly set additional regs when using atombios */1657/* properly set additional regs when using atombios */
@@ -2215,7 +2180,6 @@ static const struct drm_crtc_helper_funcs atombios_helper_funcs = { · 522 unmodified lines
2215 .mode_fixup = atombios_crtc_mode_fixup,2180 .mode_fixup = atombios_crtc_mode_fixup,
2216 .mode_set = atombios_crtc_mode_set,2181 .mode_set = atombios_crtc_mode_set,
2217 .mode_set_base = atombios_crtc_set_base,2182 .mode_set_base = atombios_crtc_set_base,
2218 .mode_set_base_atomic = atombios_crtc_set_base_atomic,
2219 .prepare = atombios_crtc_prepare,2183 .prepare = atombios_crtc_prepare,
2220 .commit = atombios_crtc_commit,2184 .commit = atombios_crtc_commit,
2221 .disable = atombios_crtc_disable,2185 .disable = atombios_crtc_disable,
drivers/gpu/drm/radeon/radeon_legacy_crtc.c+6−17
@@ -360,19 +360,12 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) · 359 unmodified lines
360int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,360int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
361 struct drm_framebuffer *old_fb)361 struct drm_framebuffer *old_fb)
362{362{
363 return radeon_crtc_do_set_base(crtc, old_fb, x, y, 0);363 return radeon_crtc_do_set_base(crtc, old_fb, x, y);
364}
365
366int radeon_crtc_set_base_atomic(struct drm_crtc *crtc,
367 struct drm_framebuffer *fb,
368 int x, int y, enum mode_set_atomic state)
369{
370 return radeon_crtc_do_set_base(crtc, fb, x, y, 1);
371}364}
372 365
373int radeon_crtc_do_set_base(struct drm_crtc *crtc,366int radeon_crtc_do_set_base(struct drm_crtc *crtc,
374 struct drm_framebuffer *fb,367 struct drm_framebuffer *fb,
375 int x, int y, int atomic)368 int x, int y)
376{369{
377 struct drm_device *dev = crtc->dev;370 struct drm_device *dev = crtc->dev;
378 struct radeon_device *rdev = dev->dev_private;371 struct radeon_device *rdev = dev->dev_private;
@@ -390,15 +383,12 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, · 11 unmodified lines
390 383
391 DRM_DEBUG_KMS("\n");384 DRM_DEBUG_KMS("\n");
392 /* no fb bound */385 /* no fb bound */
393 if (!atomic && !crtc->primary->fb) {386 if (!crtc->primary->fb) {
394 DRM_DEBUG_KMS("No FB bound\n");387 DRM_DEBUG_KMS("No FB bound\n");
395 return 0;388 return 0;
396 }389 }
397 390
398 if (atomic)391 target_fb = crtc->primary->fb;
399 target_fb = fb;
400 else
401 target_fb = crtc->primary->fb;
402 392
403 switch (target_fb->format->cpp[0] * 8) {393 switch (target_fb->format->cpp[0] * 8) {
404 case 8:394 case 8:
@@ -445,7 +435,7 @@ retry: · 40 unmodified lines
445 * We don't shutdown the display controller because new buffer435 * We don't shutdown the display controller because new buffer
446 * will end up in same spot.436 * will end up in same spot.
447 */437 */
448 if (!atomic && fb && fb != crtc->primary->fb) {438 if (fb && fb != crtc->primary->fb) {
449 struct radeon_bo *old_rbo;439 struct radeon_bo *old_rbo;
450 unsigned long nsize, osize;440 unsigned long nsize, osize;
451 441
@@ -555,7 +545,7 @@ retry: · 103 unmodified lines
555 WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);545 WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, crtc_offset);
556 WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);546 WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);
557 547
558 if (!atomic && fb && fb != crtc->primary->fb) {548 if (fb && fb != crtc->primary->fb) {
559 rbo = gem_to_radeon_bo(fb->obj[0]);549 rbo = gem_to_radeon_bo(fb->obj[0]);
560 r = radeon_bo_reserve(rbo, false);550 r = radeon_bo_reserve(rbo, false);
561 if (unlikely(r != 0))551 if (unlikely(r != 0))
@@ -1108,7 +1098,6 @@ static const struct drm_crtc_helper_funcs legacy_helper_funcs = { · 546 unmodified lines
1108 .mode_fixup = radeon_crtc_mode_fixup,1098 .mode_fixup = radeon_crtc_mode_fixup,
1109 .mode_set = radeon_crtc_mode_set,1099 .mode_set = radeon_crtc_mode_set,
1110 .mode_set_base = radeon_crtc_set_base,1100 .mode_set_base = radeon_crtc_set_base,
1111 .mode_set_base_atomic = radeon_crtc_set_base_atomic,
1112 .prepare = radeon_crtc_prepare,1101 .prepare = radeon_crtc_prepare,
1113 .commit = radeon_crtc_commit,1102 .commit = radeon_crtc_commit,
1114 .disable = radeon_crtc_disable,1103 .disable = radeon_crtc_disable,
drivers/gpu/drm/radeon/radeon_mode.h+1−9
@@ -804,10 +804,6 @@ extern bool radeon_encoder_is_digital(struct drm_encoder *encoder); · 803 unmodified lines
804extern void radeon_crtc_load_lut(struct drm_crtc *crtc);804extern void radeon_crtc_load_lut(struct drm_crtc *crtc);
805extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,805extern int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
806 struct drm_framebuffer *old_fb);806 struct drm_framebuffer *old_fb);
807extern int atombios_crtc_set_base_atomic(struct drm_crtc *crtc,
808 struct drm_framebuffer *fb,
809 int x, int y,
810 enum mode_set_atomic state);
811extern int atombios_crtc_mode_set(struct drm_crtc *crtc,807extern int atombios_crtc_mode_set(struct drm_crtc *crtc,
812 struct drm_display_mode *mode,808 struct drm_display_mode *mode,
813 struct drm_display_mode *adjusted_mode,809 struct drm_display_mode *adjusted_mode,
@@ -817,13 +813,9 @@ extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode); · 3 unmodified lines
817 813
818extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,814extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
819 struct drm_framebuffer *old_fb);815 struct drm_framebuffer *old_fb);
820extern int radeon_crtc_set_base_atomic(struct drm_crtc *crtc,
821 struct drm_framebuffer *fb,
822 int x, int y,
823 enum mode_set_atomic state);
824extern int radeon_crtc_do_set_base(struct drm_crtc *crtc,816extern int radeon_crtc_do_set_base(struct drm_crtc *crtc,
825 struct drm_framebuffer *fb,817 struct drm_framebuffer *fb,
826 int x, int y, int atomic);818 int x, int y);
827extern int radeon_crtc_cursor_set2(struct drm_crtc *crtc,819extern int radeon_crtc_cursor_set2(struct drm_crtc *crtc,
828 struct drm_file *file_priv,820 struct drm_file *file_priv,
829 uint32_t handle,821 uint32_t handle,
drivers/gpu/drm/ttm/tests/ttm_bo_validate_test.c+1−1
@@ -692,7 +692,7 @@ static int threaded_fence_signal(void *arg) · 691 unmodified lines
692 692
693 msleep(20);693 msleep(20);
694 694
695 return dma_fence_signal(fence);695 return dma_fence_check_and_signal(fence) ? -EINVAL : 0;
696}696}
697 697
698static void ttm_bo_validate_move_fence_not_signaled(struct kunit *test)698static void ttm_bo_validate_move_fence_not_signaled(struct kunit *test)
drivers/gpu/drm/ttm/ttm_bo.c+33−31
@@ -268,8 +268,8 @@ static void ttm_bo_release(struct kref *kref) · 267 unmodified lines
268 30 * HZ);268 30 * HZ);
269 }269 }
270 270
271 if (bo->bdev->funcs->release_notify)271 if (bdev->funcs->release_notify)
272 bo->bdev->funcs->release_notify(bo);272 bdev->funcs->release_notify(bo);
273 273
274 drm_vma_offset_remove(bdev->vma_manager, &bo->base.vma_node);274 drm_vma_offset_remove(bdev->vma_manager, &bo->base.vma_node);
275 ttm_mem_io_free(bdev, bo->resource);275 ttm_mem_io_free(bdev, bo->resource);
@@ -283,7 +283,7 @@ static void ttm_bo_release(struct kref *kref) · 7 unmodified lines
283 ttm_bo_flush_all_fences(bo);283 ttm_bo_flush_all_fences(bo);
284 bo->deleted = true;284 bo->deleted = true;
285 285
286 spin_lock(&bo->bdev->lru_lock);286 spin_lock(&bdev->lru_lock);
287 287
288 /*288 /*
289 * Make pinned bos immediately available to289 * Make pinned bos immediately available to
@@ -299,7 +299,7 @@ static void ttm_bo_release(struct kref *kref) · 9 unmodified lines
299 }299 }
300 300
301 kref_init(&bo->kref);301 kref_init(&bo->kref);
302 spin_unlock(&bo->bdev->lru_lock);302 spin_unlock(&bdev->lru_lock);
303 303
304 INIT_WORK(&bo->delayed_delete, ttm_bo_delayed_delete);304 INIT_WORK(&bo->delayed_delete, ttm_bo_delayed_delete);
305 305
@@ -359,7 +359,6 @@ static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo, · 53 unmodified lines
359static int ttm_bo_evict(struct ttm_buffer_object *bo,359static int ttm_bo_evict(struct ttm_buffer_object *bo,
360 struct ttm_operation_ctx *ctx)360 struct ttm_operation_ctx *ctx)
361{361{
362 struct ttm_device *bdev = bo->bdev;
363 struct ttm_resource *evict_mem;362 struct ttm_resource *evict_mem;
364 struct ttm_placement placement;363 struct ttm_placement placement;
365 struct ttm_place hop;364 struct ttm_place hop;
@@ -370,7 +369,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, · 4 unmodified lines
370 dma_resv_assert_held(bo->base.resv);369 dma_resv_assert_held(bo->base.resv);
371 370
372 placement.num_placement = 0;371 placement.num_placement = 0;
373 bdev->funcs->evict_flags(bo, &placement);372 bo->bdev->funcs->evict_flags(bo, &placement);
374 373
375 if (!placement.num_placement) {374 if (!placement.num_placement) {
376 ret = ttm_bo_wait_ctx(bo, ctx);375 ret = ttm_bo_wait_ctx(bo, ctx);
@@ -423,16 +422,16 @@ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, · 46 unmodified lines
423 const struct ttm_place *place)422 const struct ttm_place *place)
424{423{
425 struct ttm_resource *res = bo->resource;424 struct ttm_resource *res = bo->resource;
426 struct ttm_device *bdev = bo->bdev;
427 425
428 dma_resv_assert_held(bo->base.resv);426 dma_resv_assert_held(bo->base.resv);
429 if (bo->resource->mem_type == TTM_PL_SYSTEM)427
428 if (res->mem_type == TTM_PL_SYSTEM)
430 return true;429 return true;
431 430
432 /* Don't evict this BO if it's outside of the431 /* Don't evict this BO if it's outside of the
433 * requested placement range432 * requested placement range
434 */433 */
435 return ttm_resource_intersects(bdev, res, place, bo->base.size);434 return ttm_resource_intersects(bo->bdev, res, place, bo->base.size);
436}435}
437EXPORT_SYMBOL(ttm_bo_eviction_valuable);436EXPORT_SYMBOL(ttm_bo_eviction_valuable);
438 437
@@ -1027,7 +1026,7 @@ int ttm_bo_init_validate(struct ttm_device *bdev, struct ttm_buffer_object *bo, · 588 unmodified lines
1027 struct sg_table *sg, struct dma_resv *resv,1026 struct sg_table *sg, struct dma_resv *resv,
1028 void (*destroy) (struct ttm_buffer_object *))1027 void (*destroy) (struct ttm_buffer_object *))
1029{1028{
1030 struct ttm_operation_ctx ctx = { interruptible, false };1029 struct ttm_operation_ctx ctx = { .interruptible = interruptible };
1031 int ret;1030 int ret;
1032 1031
1033 ret = ttm_bo_init_reserved(bdev, bo, type, placement, alignment, &ctx,1032 ret = ttm_bo_init_reserved(bdev, bo, type, placement, alignment, &ctx,
@@ -1108,10 +1107,13 @@ struct ttm_bo_swapout_walk { · 74 unmodified lines
1108static s641107static s64
1109ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)1108ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
1110{1109{
1111 struct ttm_place place = {.mem_type = bo->resource->mem_type};1110 struct ttm_resource *res = bo->resource;
1111 struct ttm_place place = { .mem_type = res->mem_type };
1112 struct ttm_bo_swapout_walk *swapout_walk =1112 struct ttm_bo_swapout_walk *swapout_walk =
1113 container_of(walk, typeof(*swapout_walk), walk);1113 container_of(walk, typeof(*swapout_walk), walk);
1114 struct ttm_operation_ctx *ctx = walk->arg.ctx;1114 struct ttm_operation_ctx *ctx = walk->arg.ctx;
1115 struct ttm_device *bdev = bo->bdev;
1116 struct ttm_tt *tt = bo->ttm;
1115 s64 ret;1117 s64 ret;
1116 1118
1117 /*1119 /*
@@ -1120,20 +1122,19 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo) · 2 unmodified lines
1120 * The driver may use the fact that we're moving from SYSTEM1122 * The driver may use the fact that we're moving from SYSTEM
1121 * as an indication that we're about to swap out.1123 * as an indication that we're about to swap out.
1122 */1124 */
1123 if (bo->pin_count || !bo->bdev->funcs->eviction_valuable(bo, &place)) {1125 if (bo->pin_count || !bdev->funcs->eviction_valuable(bo, &place)) {
1124 ret = -EBUSY;1126 ret = -EBUSY;
1125 goto out;1127 goto out;
1126 }1128 }
1127 1129
1128 if (!bo->ttm || !ttm_tt_is_populated(bo->ttm) ||1130 if (!tt || !ttm_tt_is_populated(tt) ||
1129 bo->ttm->page_flags & TTM_TT_FLAG_EXTERNAL ||1131 tt->page_flags & (TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_SWAPPED)) {
1130 bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED) {
1131 ret = -EBUSY;1132 ret = -EBUSY;
1132 goto out;1133 goto out;
1133 }1134 }
1134 1135
1135 if (bo->deleted) {1136 if (bo->deleted) {
1136 pgoff_t num_pages = bo->ttm->num_pages;1137 pgoff_t num_pages = tt->num_pages;
1137 1138
1138 ret = ttm_bo_wait_ctx(bo, ctx);1139 ret = ttm_bo_wait_ctx(bo, ctx);
1139 if (ret)1140 if (ret)
@@ -1147,7 +1148,7 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo) · 7 unmodified lines
1147 /*1148 /*
1148 * Move to system cached1149 * Move to system cached
1149 */1150 */
1150 if (bo->resource->mem_type != TTM_PL_SYSTEM) {1151 if (res->mem_type != TTM_PL_SYSTEM) {
1151 struct ttm_resource *evict_mem;1152 struct ttm_resource *evict_mem;
1152 struct ttm_place hop;1153 struct ttm_place hop;
1153 1154
@@ -1174,21 +1175,21 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo) · 20 unmodified lines
1174 goto out;1175 goto out;
1175 1176
1176 ttm_bo_unmap_virtual(bo);1177 ttm_bo_unmap_virtual(bo);
1177 if (bo->bdev->funcs->swap_notify)1178 if (bdev->funcs->swap_notify)
1178 bo->bdev->funcs->swap_notify(bo);1179 bdev->funcs->swap_notify(bo);
1179 1180
1180 if (ttm_tt_is_populated(bo->ttm)) {1181 if (ttm_tt_is_populated(tt)) {
1181 spin_lock(&bo->bdev->lru_lock);1182 spin_lock(&bdev->lru_lock);
1182 ttm_resource_del_bulk_move(bo->resource, bo);1183 ttm_resource_del_bulk_move(res, bo);
1183 spin_unlock(&bo->bdev->lru_lock);1184 spin_unlock(&bdev->lru_lock);
1184 1185
1185 ret = ttm_tt_swapout(bo->bdev, bo->ttm, swapout_walk->gfp_flags);1186 ret = ttm_tt_swapout(bdev, tt, swapout_walk->gfp_flags);
1186 1187
1187 spin_lock(&bo->bdev->lru_lock);1188 spin_lock(&bdev->lru_lock);
1188 if (ret)1189 if (ret)
1189 ttm_resource_add_bulk_move(bo->resource, bo);1190 ttm_resource_add_bulk_move(res, bo);
1190 ttm_resource_move_to_lru_tail(bo->resource);1191 ttm_resource_move_to_lru_tail(res);
1191 spin_unlock(&bo->bdev->lru_lock);1192 spin_unlock(&bdev->lru_lock);
1192 }1193 }
1193 1194
1194out:1195out:
@@ -1261,6 +1262,7 @@ void ttm_bo_tt_destroy(struct ttm_buffer_object *bo) · 66 unmodified lines
1261int ttm_bo_populate(struct ttm_buffer_object *bo,1262int ttm_bo_populate(struct ttm_buffer_object *bo,
1262 struct ttm_operation_ctx *ctx)1263 struct ttm_operation_ctx *ctx)
1263{1264{
1265 struct ttm_device *bdev = bo->bdev;
1264 struct ttm_tt *tt = bo->ttm;1266 struct ttm_tt *tt = bo->ttm;
1265 bool swapped;1267 bool swapped;
1266 int ret;1268 int ret;
@@ -1271,16 +1273,16 @@ int ttm_bo_populate(struct ttm_buffer_object *bo, · 4 unmodified lines
1271 return 0;1273 return 0;
1272 1274
1273 swapped = ttm_tt_is_swapped(tt);1275 swapped = ttm_tt_is_swapped(tt);
1274 ret = ttm_tt_populate(bo->bdev, tt, ctx);1276 ret = ttm_tt_populate(bdev, tt, ctx);
1275 if (ret)1277 if (ret)
1276 return ret;1278 return ret;
1277 1279
1278 if (swapped && !ttm_tt_is_swapped(tt) && !bo->pin_count &&1280 if (swapped && !ttm_tt_is_swapped(tt) && !bo->pin_count &&
1279 bo->resource) {1281 bo->resource) {
1280 spin_lock(&bo->bdev->lru_lock);1282 spin_lock(&bdev->lru_lock);
1281 ttm_resource_add_bulk_move(bo->resource, bo);1283 ttm_resource_add_bulk_move(bo->resource, bo);
1282 ttm_resource_move_to_lru_tail(bo->resource);1284 ttm_resource_move_to_lru_tail(bo->resource);
1283 spin_unlock(&bo->bdev->lru_lock);1285 spin_unlock(&bdev->lru_lock);
1284 }1286 }
1285 1287
1286 return 0;1288 return 0;
drivers/gpu/drm/ttm/ttm_bo_util.c+25−32
@@ -174,13 +174,13 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, · 173 unmodified lines
174 174
175 dst_iter = ttm_kmap_iter_linear_io_init(&_dst_iter.io, bdev, dst_mem);175 dst_iter = ttm_kmap_iter_linear_io_init(&_dst_iter.io, bdev, dst_mem);
176 if (PTR_ERR(dst_iter) == -EINVAL && dst_man->use_tt)176 if (PTR_ERR(dst_iter) == -EINVAL && dst_man->use_tt)
177 dst_iter = ttm_kmap_iter_tt_init(&_dst_iter.tt, bo->ttm);177 dst_iter = ttm_kmap_iter_tt_init(&_dst_iter.tt, ttm);
178 if (IS_ERR(dst_iter))178 if (IS_ERR(dst_iter))
179 return PTR_ERR(dst_iter);179 return PTR_ERR(dst_iter);
180 180
181 src_iter = ttm_kmap_iter_linear_io_init(&_src_iter.io, bdev, src_mem);181 src_iter = ttm_kmap_iter_linear_io_init(&_src_iter.io, bdev, src_mem);
182 if (PTR_ERR(src_iter) == -EINVAL && src_man->use_tt)182 if (PTR_ERR(src_iter) == -EINVAL && src_man->use_tt)
183 src_iter = ttm_kmap_iter_tt_init(&_src_iter.tt, bo->ttm);183 src_iter = ttm_kmap_iter_tt_init(&_src_iter.tt, ttm);
184 if (IS_ERR(src_iter)) {184 if (IS_ERR(src_iter)) {
185 ret = PTR_ERR(src_iter);185 ret = PTR_ERR(src_iter);
186 goto out_src_iter;186 goto out_src_iter;
@@ -318,11 +318,11 @@ static int ttm_bo_ioremap(struct ttm_buffer_object *bo, · 131 unmodified lines
318{318{
319 struct ttm_resource *mem = bo->resource;319 struct ttm_resource *mem = bo->resource;
320 320
321 if (bo->resource->bus.addr) {321 if (mem->bus.addr) {
322 map->bo_kmap_type = ttm_bo_map_premapped;322 map->bo_kmap_type = ttm_bo_map_premapped;
323 map->virtual = ((u8 *)bo->resource->bus.addr) + offset;323 map->virtual = ((u8 *)mem->bus.addr) + offset;
324 } else {324 } else {
325 resource_size_t res = bo->resource->bus.offset + offset;325 resource_size_t res = mem->bus.offset + offset;
326 326
327 map->bo_kmap_type = ttm_bo_map_iomap;327 map->bo_kmap_type = ttm_bo_map_iomap;
328 if (mem->bus.caching == ttm_write_combined)328 if (mem->bus.caching == ttm_write_combined)
@@ -343,13 +343,10 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, · 14 unmodified lines
343 struct ttm_bo_kmap_obj *map)343 struct ttm_bo_kmap_obj *map)
344{344{
345 struct ttm_resource *mem = bo->resource;345 struct ttm_resource *mem = bo->resource;
346 struct ttm_operation_ctx ctx = {346 struct ttm_operation_ctx ctx = { };
347 .interruptible = false,
348 .no_wait_gpu = false
349 };
350 struct ttm_tt *ttm = bo->ttm;347 struct ttm_tt *ttm = bo->ttm;
351 struct ttm_resource_manager *man =348 struct ttm_resource_manager *man =
352 ttm_manager_type(bo->bdev, bo->resource->mem_type);349 ttm_manager_type(bo->bdev, mem->mem_type);
353 pgprot_t prot;350 pgprot_t prot;
354 int ret;351 int ret;
355 352
@@ -428,20 +425,21 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo, · 72 unmodified lines
428 unsigned long start_page, unsigned long num_pages,425 unsigned long start_page, unsigned long num_pages,
429 struct ttm_bo_kmap_obj *map)426 struct ttm_bo_kmap_obj *map)
430{427{
428 struct ttm_resource *res = bo->resource;
431 unsigned long offset, size;429 unsigned long offset, size;
432 int ret;430 int ret;
433 431
434 map->virtual = NULL;432 map->virtual = NULL;
435 map->bo = bo;433 map->bo = bo;
436 if (num_pages > PFN_UP(bo->resource->size))434 if (num_pages > PFN_UP(res->size))
437 return -EINVAL;435 return -EINVAL;
438 if ((start_page + num_pages) > PFN_UP(bo->resource->size))436 if ((start_page + num_pages) > PFN_UP(res->size))
439 return -EINVAL;437 return -EINVAL;
440 438
441 ret = ttm_mem_io_reserve(bo->bdev, bo->resource);439 ret = ttm_mem_io_reserve(bo->bdev, res);
442 if (ret)440 if (ret)
443 return ret;441 return ret;
444 if (!bo->resource->bus.is_iomem) {442 if (!res->bus.is_iomem) {
445 return ttm_bo_kmap_ttm(bo, start_page, num_pages, map);443 return ttm_bo_kmap_ttm(bo, start_page, num_pages, map);
446 } else {444 } else {
447 offset = start_page << PAGE_SHIFT;445 offset = start_page << PAGE_SHIFT;
@@ -530,10 +528,7 @@ int ttm_bo_vmap(struct ttm_buffer_object *bo, struct iosys_map *map) · 82 unmodified lines
530 iosys_map_set_vaddr_iomem(map, vaddr_iomem);528 iosys_map_set_vaddr_iomem(map, vaddr_iomem);
531 529
532 } else {530 } else {
533 struct ttm_operation_ctx ctx = {531 struct ttm_operation_ctx ctx = { };
534 .interruptible = false,
535 .no_wait_gpu = false
536 };
537 struct ttm_tt *ttm = bo->ttm;532 struct ttm_tt *ttm = bo->ttm;
538 pgprot_t prot;533 pgprot_t prot;
539 void *vaddr;534 void *vaddr;
@@ -581,7 +576,7 @@ void ttm_bo_vunmap(struct ttm_buffer_object *bo, struct iosys_map *map) · 41 unmodified lines
581 iounmap(map->vaddr_iomem);576 iounmap(map->vaddr_iomem);
582 iosys_map_clear(map);577 iosys_map_clear(map);
583 578
584 ttm_mem_io_free(bo->bdev, bo->resource);579 ttm_mem_io_free(bo->bdev, mem);
585}580}
586EXPORT_SYMBOL(ttm_bo_vunmap);581EXPORT_SYMBOL(ttm_bo_vunmap);
587 582
@@ -644,12 +639,11 @@ static int ttm_bo_move_to_ghost(struct ttm_buffer_object *bo, · 56 unmodified lines
644static void ttm_bo_move_pipeline_evict(struct ttm_buffer_object *bo,639static void ttm_bo_move_pipeline_evict(struct ttm_buffer_object *bo,
645 struct dma_fence *fence)640 struct dma_fence *fence)
646{641{
647 struct ttm_device *bdev = bo->bdev;
648 struct ttm_resource_manager *from;642 struct ttm_resource_manager *from;
649 struct dma_fence *tmp;643 struct dma_fence *tmp;
650 int i;644 int i;
651 645
652 from = ttm_manager_type(bdev, bo->resource->mem_type);646 from = ttm_manager_type(bo->bdev, bo->resource->mem_type);
653 647
654 /**648 /**
655 * BO doesn't have a TTM we need to bind/unbind. Just remember649 * BO doesn't have a TTM we need to bind/unbind. Just remember
@@ -743,8 +737,8 @@ EXPORT_SYMBOL(ttm_bo_move_accel_cleanup); · 87 unmodified lines
743void ttm_bo_move_sync_cleanup(struct ttm_buffer_object *bo,737void ttm_bo_move_sync_cleanup(struct ttm_buffer_object *bo,
744 struct ttm_resource *new_mem)738 struct ttm_resource *new_mem)
745{739{
746 struct ttm_device *bdev = bo->bdev;740 struct ttm_resource_manager *man =
747 struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type);741 ttm_manager_type(bo->bdev, new_mem->mem_type);
748 int ret;742 int ret;
749 743
750 ret = ttm_bo_wait_free_node(bo, man->use_tt);744 ret = ttm_bo_wait_free_node(bo, man->use_tt);
@@ -848,13 +842,12 @@ static int ttm_lru_walk_ticketlock(struct ttm_bo_lru_cursor *curs, · 97 unmodified lines
848 struct ttm_buffer_object *bo)842 struct ttm_buffer_object *bo)
849{843{
850 struct ttm_lru_walk_arg *arg = curs->arg;844 struct ttm_lru_walk_arg *arg = curs->arg;
851 struct dma_resv *resv = bo->base.resv;
852 int ret;845 int ret;
853 846
854 if (arg->ctx->interruptible)847 if (arg->ctx->interruptible)
855 ret = dma_resv_lock_interruptible(resv, arg->ticket);848 ret = dma_resv_lock_interruptible(bo->base.resv, arg->ticket);
856 else849 else
857 ret = dma_resv_lock(resv, arg->ticket);850 ret = dma_resv_lock(bo->base.resv, arg->ticket);
858 851
859 if (!ret) {852 if (!ret) {
860 curs->needs_unlock = true;853 curs->needs_unlock = true;
@@ -1098,7 +1091,7 @@ long ttm_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo, · 237 unmodified lines
1098 .num_placement = 1,1091 .num_placement = 1,
1099 .placement = &sys_placement_flags,1092 .placement = &sys_placement_flags,
1100 };1093 };
1101 struct ttm_tt *tt = bo->ttm;1094 struct ttm_device *bdev = bo->bdev;
1102 long lret;1095 long lret;
1103 1096
1104 dma_resv_assert_held(bo->base.resv);1097 dma_resv_assert_held(bo->base.resv);
@@ -1120,19 +1113,19 @@ long ttm_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo, · 15 unmodified lines
1120 return lret;1113 return lret;
1121 1114
1122 if (bo->bulk_move) {1115 if (bo->bulk_move) {
1123 spin_lock(&bo->bdev->lru_lock);1116 spin_lock(&bdev->lru_lock);
1124 ttm_resource_del_bulk_move(bo->resource, bo);1117 ttm_resource_del_bulk_move(bo->resource, bo);
1125 spin_unlock(&bo->bdev->lru_lock);1118 spin_unlock(&bdev->lru_lock);
1126 }1119 }
1127 1120
1128 lret = ttm_tt_backup(bo->bdev, tt, (struct ttm_backup_flags)1121 lret = ttm_tt_backup(bdev, bo->ttm, (struct ttm_backup_flags)
1129 {.purge = flags.purge,1122 {.purge = flags.purge,
1130 .writeback = flags.writeback});1123 .writeback = flags.writeback});
1131 1124
1132 if (lret <= 0 && bo->bulk_move) {1125 if (lret <= 0 && bo->bulk_move) {
1133 spin_lock(&bo->bdev->lru_lock);1126 spin_lock(&bdev->lru_lock);
1134 ttm_resource_add_bulk_move(bo->resource, bo);1127 ttm_resource_add_bulk_move(bo->resource, bo);
1135 spin_unlock(&bo->bdev->lru_lock);1128 spin_unlock(&bdev->lru_lock);
1136 }1129 }
1137 1130
1138 if (lret < 0 && lret != -EINTR)1131 if (lret < 0 && lret != -EINTR)
drivers/gpu/drm/ttm/ttm_bo_vm.c+5−7
@@ -186,7 +186,6 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, · 185 unmodified lines
186{186{
187 struct vm_area_struct *vma = vmf->vma;187 struct vm_area_struct *vma = vmf->vma;
188 struct ttm_buffer_object *bo = vma->vm_private_data;188 struct ttm_buffer_object *bo = vma->vm_private_data;
189 struct ttm_device *bdev = bo->bdev;
190 unsigned long page_offset;189 unsigned long page_offset;
191 unsigned long page_last;190 unsigned long page_last;
192 unsigned long pfn;191 unsigned long pfn;
@@ -205,7 +204,7 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf, · 12 unmodified lines
205 if (unlikely(ret != 0))204 if (unlikely(ret != 0))
206 return ret;205 return ret;
207 206
208 err = ttm_mem_io_reserve(bdev, bo->resource);207 err = ttm_mem_io_reserve(bo->bdev, bo->resource);
209 if (unlikely(err != 0))208 if (unlikely(err != 0))
210 return VM_FAULT_SIGBUS;209 return VM_FAULT_SIGBUS;
211 210
@@ -293,7 +292,6 @@ vm_fault_t ttm_bo_vm_dummy_page(struct vm_fault *vmf, pgprot_t prot) · 81 unmodified lines
293{292{
294 struct vm_area_struct *vma = vmf->vma;293 struct vm_area_struct *vma = vmf->vma;
295 struct ttm_buffer_object *bo = vma->vm_private_data;294 struct ttm_buffer_object *bo = vma->vm_private_data;
296 struct drm_device *ddev = bo->base.dev;
297 vm_fault_t ret = VM_FAULT_NOPAGE;295 vm_fault_t ret = VM_FAULT_NOPAGE;
298 unsigned long address;296 unsigned long address;
299 unsigned long pfn;297 unsigned long pfn;
@@ -305,7 +303,8 @@ vm_fault_t ttm_bo_vm_dummy_page(struct vm_fault *vmf, pgprot_t prot) · 5 unmodified lines
305 return VM_FAULT_OOM;303 return VM_FAULT_OOM;
306 304
307 /* Set the page to be freed using drmm release action */305 /* Set the page to be freed using drmm release action */
308 if (drmm_add_action_or_reset(ddev, ttm_bo_release_dummy_page, page))306 if (drmm_add_action_or_reset(bo->base.dev, ttm_bo_release_dummy_page,
307 page))
309 return VM_FAULT_OOM;308 return VM_FAULT_OOM;
310 309
311 pfn = page_to_pfn(page);310 pfn = page_to_pfn(page);
@@ -322,10 +321,9 @@ EXPORT_SYMBOL(ttm_bo_vm_dummy_page); · 10 unmodified lines
322vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)321vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
323{322{
324 struct vm_area_struct *vma = vmf->vma;323 struct vm_area_struct *vma = vmf->vma;
325 pgprot_t prot;
326 struct ttm_buffer_object *bo = vma->vm_private_data;324 struct ttm_buffer_object *bo = vma->vm_private_data;
327 struct drm_device *ddev = bo->base.dev;
328 vm_fault_t ret;325 vm_fault_t ret;
326 pgprot_t prot;
329 int idx;327 int idx;
330 328
331 ret = ttm_bo_vm_reserve(bo, vmf);329 ret = ttm_bo_vm_reserve(bo, vmf);
@@ -333,7 +331,7 @@ vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf) · 1 unmodified line
333 return ret;331 return ret;
334 332
335 prot = vma->vm_page_prot;333 prot = vma->vm_page_prot;
336 if (drm_dev_enter(ddev, &idx)) {334 if (drm_dev_enter(bo->base.dev, &idx)) {
337 ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT);335 ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT);
338 drm_dev_exit(idx);336 drm_dev_exit(idx);
339 } else {337 } else {
drivers/gpu/drm/ttm/ttm_device.c+1−4
@@ -135,10 +135,7 @@ out: · 134 unmodified lines
135 */135 */
136int ttm_device_prepare_hibernation(struct ttm_device *bdev)136int ttm_device_prepare_hibernation(struct ttm_device *bdev)
137{137{
138 struct ttm_operation_ctx ctx = {138 struct ttm_operation_ctx ctx = { };
139 .interruptible = false,
140 .no_wait_gpu = false,
141 };
142 int ret;139 int ret;
143 140
144 do {141 do {
drivers/gpu/drm/ttm/ttm_pool.c+14−12
@@ -845,32 +845,34 @@ EXPORT_SYMBOL(ttm_pool_alloc); · 844 unmodified lines
845int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt,845int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
846 const struct ttm_operation_ctx *ctx)846 const struct ttm_operation_ctx *ctx)
847{847{
848 struct ttm_pool_tt_restore *restore = tt->restore;
848 struct ttm_pool_alloc_state alloc;849 struct ttm_pool_alloc_state alloc;
849 850
850 if (WARN_ON(!ttm_tt_is_backed_up(tt)))851 if (WARN_ON(!ttm_tt_is_backed_up(tt)))
851 return -EINVAL;852 return -EINVAL;
852 853
853 if (!tt->restore) {854 if (!restore) {
854 gfp_t gfp = GFP_KERNEL | __GFP_NOWARN;855 gfp_t gfp = GFP_KERNEL | __GFP_NOWARN;
855 856
856 ttm_pool_alloc_state_init(tt, &alloc);857 ttm_pool_alloc_state_init(tt, &alloc);
857 if (ctx->gfp_retry_mayfail)858 if (ctx->gfp_retry_mayfail)
858 gfp |= __GFP_RETRY_MAYFAIL;859 gfp |= __GFP_RETRY_MAYFAIL;
859 860
860 tt->restore = kzalloc(sizeof(*tt->restore), gfp);861 restore = kzalloc(sizeof(*restore), gfp);
861 if (!tt->restore)862 if (!restore)
862 return -ENOMEM;863 return -ENOMEM;
863 864
864 tt->restore->snapshot_alloc = alloc;865 restore->snapshot_alloc = alloc;
865 tt->restore->pool = pool;866 restore->pool = pool;
866 tt->restore->restored_pages = 1;867 restore->restored_pages = 1;
867 } else {
868 struct ttm_pool_tt_restore *restore = tt->restore;
869 int ret;
870 868
869 tt->restore = restore;
870 } else {
871 alloc = restore->snapshot_alloc;871 alloc = restore->snapshot_alloc;
872 if (ttm_pool_restore_valid(tt->restore)) {872 if (ttm_pool_restore_valid(restore)) {
873 ret = ttm_pool_restore_commit(restore, tt->backup, ctx, &alloc);873 int ret = ttm_pool_restore_commit(restore, tt->backup,
874 ctx, &alloc);
875
874 if (ret)876 if (ret)
875 return ret;877 return ret;
876 }878 }
@@ -878,7 +880,7 @@ int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt, · 1 unmodified line
878 return 0;880 return 0;
879 }881 }
880 882
881 return __ttm_pool_alloc(pool, tt, ctx, &alloc, tt->restore);883 return __ttm_pool_alloc(pool, tt, ctx, &alloc, restore);
882}884}
883 885
884/**886/**
drivers/gpu/drm/ttm/ttm_resource.c+4−10
@@ -446,9 +446,6 @@ bool ttm_resource_intersects(struct ttm_device *bdev, · 445 unmodified lines
446{446{
447 struct ttm_resource_manager *man;447 struct ttm_resource_manager *man;
448 448
449 if (!res)
450 return false;
451
452 man = ttm_manager_type(bdev, res->mem_type);449 man = ttm_manager_type(bdev, res->mem_type);
453 if (!place || !man->func->intersects)450 if (!place || !man->func->intersects)
454 return true;451 return true;
@@ -548,10 +545,7 @@ EXPORT_SYMBOL(ttm_resource_manager_init); · 93 unmodified lines
548int ttm_resource_manager_evict_all(struct ttm_device *bdev,545int ttm_resource_manager_evict_all(struct ttm_device *bdev,
549 struct ttm_resource_manager *man)546 struct ttm_resource_manager *man)
550{547{
551 struct ttm_operation_ctx ctx = {548 struct ttm_operation_ctx ctx = { };
552 .interruptible = false,
553 .no_wait_gpu = false,
554 };
555 struct dma_fence *fence;549 struct dma_fence *fence;
556 int ret, i;550 int ret, i;
557 551
@@ -628,11 +622,11 @@ ttm_resource_cursor_check_bulk(struct ttm_resource_cursor *cursor, · 70 unmodified lines
628 struct ttm_lru_item *next_lru)622 struct ttm_lru_item *next_lru)
629{623{
630 struct ttm_resource *next = ttm_lru_item_to_res(next_lru);624 struct ttm_resource *next = ttm_lru_item_to_res(next_lru);
631 struct ttm_lru_bulk_move *bulk = NULL;625 struct ttm_lru_bulk_move *bulk;
632 struct ttm_buffer_object *bo = next->bo;
633 626
634 lockdep_assert_held(&cursor->man->bdev->lru_lock);627 lockdep_assert_held(&cursor->man->bdev->lru_lock);
635 bulk = bo->bulk_move;628
629 bulk = next->bo->bulk_move;
636 630
637 if (cursor->bulk != bulk) {631 if (cursor->bulk != bulk) {
638 if (bulk) {632 if (bulk) {
drivers/gpu/drm/ttm/ttm_tt.c+1−1
@@ -456,7 +456,7 @@ EXPORT_SYMBOL_FOR_TESTS_ONLY(ttm_tt_unpopulate); · 455 unmodified lines
456/* Test the shrinker functions and dump the result */456/* Test the shrinker functions and dump the result */
457static int ttm_tt_debugfs_shrink_show(struct seq_file *m, void *data)457static int ttm_tt_debugfs_shrink_show(struct seq_file *m, void *data)
458{458{
459 struct ttm_operation_ctx ctx = { false, false };459 struct ttm_operation_ctx ctx = { };
460 460
461 seq_printf(m, "%d\n", ttm_global_swapout(&ctx, GFP_KERNEL));461 seq_printf(m, "%d\n", ttm_global_swapout(&ctx, GFP_KERNEL));
462 return 0;462 return 0;
drivers/gpu/drm/v3d/Makefile+1−2
@@ -13,8 +13,7 @@ v3d-y := \ · 12 unmodified lines
13 v3d_trace_points.o \13 v3d_trace_points.o \
14 v3d_sched.o \14 v3d_sched.o \
15 v3d_sysfs.o \15 v3d_sysfs.o \
16 v3d_submit.o \16 v3d_submit.o
17 v3d_gemfs.o
18 17
19v3d-$(CONFIG_DEBUG_FS) += v3d_debugfs.o18v3d-$(CONFIG_DEBUG_FS) += v3d_debugfs.o
20 19
drivers/gpu/drm/v3d/v3d_bo.c+2−4
@@ -114,7 +114,7 @@ v3d_bo_create_finish(struct drm_gem_object *obj) · 113 unmodified lines
114 if (IS_ERR(sgt))114 if (IS_ERR(sgt))
115 return PTR_ERR(sgt);115 return PTR_ERR(sgt);
116 116
117 if (!v3d->gemfs)117 if (!drm_gem_get_huge_mnt(obj->dev))
118 align = SZ_4K;118 align = SZ_4K;
119 else if (obj->size >= SZ_1M)119 else if (obj->size >= SZ_1M)
120 align = SZ_1M;120 align = SZ_1M;
@@ -150,12 +150,10 @@ struct v3d_bo *v3d_bo_create(struct drm_device *dev, struct drm_file *file_priv, · 29 unmodified lines
150 size_t unaligned_size)150 size_t unaligned_size)
151{151{
152 struct drm_gem_shmem_object *shmem_obj;152 struct drm_gem_shmem_object *shmem_obj;
153 struct v3d_dev *v3d = to_v3d_dev(dev);
154 struct v3d_bo *bo;153 struct v3d_bo *bo;
155 int ret;154 int ret;
156 155
157 shmem_obj = drm_gem_shmem_create_with_mnt(dev, unaligned_size,156 shmem_obj = drm_gem_shmem_create(dev, unaligned_size);
158 v3d->gemfs);
159 if (IS_ERR(shmem_obj))157 if (IS_ERR(shmem_obj))
160 return ERR_CAST(shmem_obj);158 return ERR_CAST(shmem_obj);
161 bo = to_v3d_bo(&shmem_obj->base);159 bo = to_v3d_bo(&shmem_obj->base);
drivers/gpu/drm/v3d/v3d_drv.c+1−1
@@ -107,7 +107,7 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data, · 106 unmodified lines
107 args->value = v3d->perfmon_info.max_counters;107 args->value = v3d->perfmon_info.max_counters;
108 return 0;108 return 0;
109 case DRM_V3D_PARAM_SUPPORTS_SUPER_PAGES:109 case DRM_V3D_PARAM_SUPPORTS_SUPER_PAGES:
110 args->value = !!v3d->gemfs;110 args->value = !!drm_gem_get_huge_mnt(dev);
111 return 0;111 return 0;
112 case DRM_V3D_PARAM_GLOBAL_RESET_COUNTER:112 case DRM_V3D_PARAM_GLOBAL_RESET_COUNTER:
113 mutex_lock(&v3d->reset_lock);113 mutex_lock(&v3d->reset_lock);
drivers/gpu/drm/v3d/v3d_drv.h+1−10
@@ -158,11 +158,6 @@ struct v3d_dev { · 157 unmodified lines
158 struct drm_mm mm;158 struct drm_mm mm;
159 spinlock_t mm_lock;159 spinlock_t mm_lock;
160 160
161 /*
162 * tmpfs instance used for shmem backed objects
163 */
164 struct vfsmount *gemfs;
165
166 struct work_struct overflow_mem_work;161 struct work_struct overflow_mem_work;
167 162
168 struct v3d_queue_state queue[V3D_MAX_QUEUES];163 struct v3d_queue_state queue[V3D_MAX_QUEUES];
@@ -569,6 +564,7 @@ extern const struct dma_fence_ops v3d_fence_ops; · 400 unmodified lines
569struct dma_fence *v3d_fence_create(struct v3d_dev *v3d, enum v3d_queue q);564struct dma_fence *v3d_fence_create(struct v3d_dev *v3d, enum v3d_queue q);
570 565
571/* v3d_gem.c */566/* v3d_gem.c */
567extern bool super_pages;
572int v3d_gem_init(struct drm_device *dev);568int v3d_gem_init(struct drm_device *dev);
573void v3d_gem_destroy(struct drm_device *dev);569void v3d_gem_destroy(struct drm_device *dev);
574void v3d_reset_sms(struct v3d_dev *v3d);570void v3d_reset_sms(struct v3d_dev *v3d);
@@ -576,11 +572,6 @@ void v3d_reset(struct v3d_dev *v3d); · 1 unmodified line
576void v3d_invalidate_caches(struct v3d_dev *v3d);572void v3d_invalidate_caches(struct v3d_dev *v3d);
577void v3d_clean_caches(struct v3d_dev *v3d);573void v3d_clean_caches(struct v3d_dev *v3d);
578 574
579/* v3d_gemfs.c */
580extern bool super_pages;
581void v3d_gemfs_init(struct v3d_dev *v3d);
582void v3d_gemfs_fini(struct v3d_dev *v3d);
583
584/* v3d_submit.c */575/* v3d_submit.c */
585void v3d_job_cleanup(struct v3d_job *job);576void v3d_job_cleanup(struct v3d_job *job);
586void v3d_job_put(struct v3d_job *job);577void v3d_job_put(struct v3d_job *job);
drivers/gpu/drm/v3d/v3d_gem.c+19−2
@@ -259,6 +259,24 @@ v3d_invalidate_caches(struct v3d_dev *v3d) · 258 unmodified lines
259 v3d_invalidate_slices(v3d, 0);259 v3d_invalidate_slices(v3d, 0);
260}260}
261 261
262static void
263v3d_huge_mnt_init(struct v3d_dev *v3d)
264{
265 int err = 0;
266
267 if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && super_pages)
268 err = drm_gem_huge_mnt_create(&v3d->drm, "within_size");
269
270 if (drm_gem_get_huge_mnt(&v3d->drm))
271 drm_info(&v3d->drm, "Using Transparent Hugepages\n");
272 else if (err)
273 drm_warn(&v3d->drm, "Can't use Transparent Hugepages (%d)\n",
274 err);
275 else
276 drm_notice(&v3d->drm,
277 "Transparent Hugepage support is recommended for optimal performance on this platform!\n");
278}
279
262int280int
263v3d_gem_init(struct drm_device *dev)281v3d_gem_init(struct drm_device *dev)
264{282{
@@ -310,7 +328,7 @@ v3d_gem_init(struct drm_device *dev) · 45 unmodified lines
310 v3d_init_hw_state(v3d);328 v3d_init_hw_state(v3d);
311 v3d_mmu_set_page_table(v3d);329 v3d_mmu_set_page_table(v3d);
312 330
313 v3d_gemfs_init(v3d);331 v3d_huge_mnt_init(v3d);
314 332
315 ret = v3d_sched_init(v3d);333 ret = v3d_sched_init(v3d);
316 if (ret) {334 if (ret) {
@@ -330,7 +348,6 @@ v3d_gem_destroy(struct drm_device *dev) · 13 unmodified lines
330 enum v3d_queue q;348 enum v3d_queue q;
331 349
332 v3d_sched_fini(v3d);350 v3d_sched_fini(v3d);
333 v3d_gemfs_fini(v3d);
334 351
335 /* Waiting for jobs to finish would need to be done before352 /* Waiting for jobs to finish would need to be done before
336 * unregistering V3D.353 * unregistering V3D.
drivers/gpu/drm/v3d/v3d_gemfs.c+0−62
@@ -1,62 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0+
2/* Copyright (C) 2024 Raspberry Pi */
3
4#include <linux/fs.h>
5#include <linux/mount.h>
6#include <linux/fs_context.h>
7
8#include <drm/drm_print.h>
9
10#include "v3d_drv.h"
11
12void v3d_gemfs_init(struct v3d_dev *v3d)
13{
14 struct file_system_type *type;
15 struct fs_context *fc;
16 struct vfsmount *gemfs;
17 int ret;
18
19 /*
20 * By creating our own shmemfs mountpoint, we can pass in
21 * mount flags that better match our usecase. However, we
22 * only do so on platforms which benefit from it.
23 */
24 if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE))
25 goto err;
26
27 /* The user doesn't want to enable Super Pages */
28 if (!super_pages)
29 goto err;
30
31 type = get_fs_type("tmpfs");
32 if (!type)
33 goto err;
34
35 fc = fs_context_for_mount(type, SB_KERNMOUNT);
36 if (IS_ERR(fc))
37 goto err;
38 ret = vfs_parse_fs_string(fc, "source", "tmpfs");
39 if (!ret)
40 ret = vfs_parse_fs_string(fc, "huge", "within_size");
41 if (!ret)
42 gemfs = fc_mount_longterm(fc);
43 put_fs_context(fc);
44 if (ret)
45 goto err;
46
47 v3d->gemfs = gemfs;
48 drm_info(&v3d->drm, "Using Transparent Hugepages\n");
49
50 return;
51
52err:
53 v3d->gemfs = NULL;
54 drm_notice(&v3d->drm,
55 "Transparent Hugepage support is recommended for optimal performance on this platform!\n");
56}
57
58void v3d_gemfs_fini(struct v3d_dev *v3d)
59{
60 if (v3d->gemfs)
61 kern_unmount(v3d->gemfs);
62}
drivers/gpu/drm/vgem/Kconfig+9−0
@@ -0,0 +1,9 @@
1# SPDX-License-Identifier: GPL-2.0-only
2config DRM_VGEM
3 tristate "Virtual GEM provider"
4 depends on DRM && MMU
5 select DRM_GEM_SHMEM_HELPER
6 help
7 Choose this option to get a virtual graphics memory manager,
8 as used by Mesa's software renderer for enhanced performance.
9 If M is selected the module will be called vgem.
drivers/gpu/drm/xe/xe_hw_fence.c+1−3
@@ -85,7 +85,6 @@ void xe_hw_fence_irq_finish(struct xe_hw_fence_irq *irq) · 84 unmodified lines
85{85{
86 struct xe_hw_fence *fence, *next;86 struct xe_hw_fence *fence, *next;
87 unsigned long flags;87 unsigned long flags;
88 int err;
89 bool tmp;88 bool tmp;
90 89
91 if (XE_WARN_ON(!list_empty(&irq->pending))) {90 if (XE_WARN_ON(!list_empty(&irq->pending))) {
@@ -93,9 +92,8 @@ void xe_hw_fence_irq_finish(struct xe_hw_fence_irq *irq) · 1 unmodified line
93 spin_lock_irqsave(&irq->lock, flags);92 spin_lock_irqsave(&irq->lock, flags);
94 list_for_each_entry_safe(fence, next, &irq->pending, irq_link) {93 list_for_each_entry_safe(fence, next, &irq->pending, irq_link) {
95 list_del_init(&fence->irq_link);94 list_del_init(&fence->irq_link);
96 err = dma_fence_signal_locked(&fence->dma);95 XE_WARN_ON(dma_fence_check_and_signal_locked(&fence->dma));
97 dma_fence_put(&fence->dma);96 dma_fence_put(&fence->dma);
98 XE_WARN_ON(err);
99 }97 }
100 spin_unlock_irqrestore(&irq->lock, flags);98 spin_unlock_irqrestore(&irq->lock, flags);
101 dma_fence_end_signalling(tmp);99 dma_fence_end_signalling(tmp);
drivers/video/fbdev/core/fbcon.c+0−24
@@ -2289,28 +2289,6 @@ static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank, · 2288 unmodified lines
2289 return false;2289 return false;
2290}2290}
2291 2291
2292static void fbcon_debug_enter(struct vc_data *vc)
2293{
2294 struct fb_info *info = fbcon_info_from_console(vc->vc_num);
2295 struct fbcon_par *par = info->fbcon_par;
2296
2297 par->save_graphics = par->graphics;
2298 par->graphics = 0;
2299 if (info->fbops->fb_debug_enter)
2300 info->fbops->fb_debug_enter(info);
2301 fbcon_set_palette(vc, color_table);
2302}
2303
2304static void fbcon_debug_leave(struct vc_data *vc)
2305{
2306 struct fb_info *info = fbcon_info_from_console(vc->vc_num);
2307 struct fbcon_par *par = info->fbcon_par;
2308
2309 par->graphics = par->save_graphics;
2310 if (info->fbops->fb_debug_leave)
2311 info->fbops->fb_debug_leave(info);
2312}
2313
2314static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch)2292static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch)
2315{2293{
2316 u8 *fontdata = vc->vc_font.data;2294 u8 *fontdata = vc->vc_font.data;
@@ -3214,8 +3192,6 @@ static const struct consw fb_con = { · 897 unmodified lines
3214 .con_set_palette = fbcon_set_palette,3192 .con_set_palette = fbcon_set_palette,
3215 .con_invert_region = fbcon_invert_region,3193 .con_invert_region = fbcon_invert_region,
3216 .con_resize = fbcon_resize,3194 .con_resize = fbcon_resize,
3217 .con_debug_enter = fbcon_debug_enter,
3218 .con_debug_leave = fbcon_debug_leave,
3219};3195};
3220 3196
3221static ssize_t rotate_store(struct device *device,3197static ssize_t rotate_store(struct device *device,
drivers/video/fbdev/core/fbcon.h+0−1
@@ -79,7 +79,6 @@ struct fbcon_par { · 78 unmodified lines
79 int cursor_reset;79 int cursor_reset;
80 int blank_state;80 int blank_state;
81 int graphics;81 int graphics;
82 int save_graphics; /* for debug enter/leave */
83 bool initialized;82 bool initialized;
84 int rotate;83 int rotate;
85 int cur_rotate;84 int cur_rotate;
include/drm/drm_atomic.h+5−0
@@ -339,6 +339,11 @@ struct drm_private_state_funcs { · 338 unmodified lines
339 * drm_atomic_helper_wait_for_dependencies().339 * drm_atomic_helper_wait_for_dependencies().
340 */340 */
341struct drm_private_obj {341struct drm_private_obj {
342 /**
343 * @dev: parent DRM device
344 */
345 struct drm_device *dev;
346
342 /**347 /**
343 * @head: List entry used to attach a private object to a &drm_device348 * @head: List entry used to attach a private object to a &drm_device
344 * (queued to &drm_mode_config.privobj_list).349 * (queued to &drm_mode_config.privobj_list).
include/drm/drm_bridge.h+12−0
@@ -1143,6 +1143,14 @@ struct drm_bridge { · 1142 unmodified lines
1143 */1143 */
1144 struct kref refcount;1144 struct kref refcount;
1145 1145
1146 /**
1147 * @unplugged:
1148 *
1149 * Flag to tell if the bridge has been unplugged.
1150 * See drm_bridge_enter() and drm_bridge_unplug().
1151 */
1152 bool unplugged;
1153
1146 /** @driver_private: pointer to the bridge driver's internal context */1154 /** @driver_private: pointer to the bridge driver's internal context */
1147 void *driver_private;1155 void *driver_private;
1148 /** @ops: bitmask of operations supported by the bridge */1156 /** @ops: bitmask of operations supported by the bridge */
@@ -1278,6 +1286,10 @@ drm_priv_to_bridge(struct drm_private_obj *priv) · 129 unmodified lines
1278 return container_of(priv, struct drm_bridge, base);1286 return container_of(priv, struct drm_bridge, base);
1279}1287}
1280 1288
1289bool drm_bridge_enter(struct drm_bridge *bridge, int *idx);
1290void drm_bridge_exit(int idx);
1291void drm_bridge_unplug(struct drm_bridge *bridge);
1292
1281struct drm_bridge *drm_bridge_get(struct drm_bridge *bridge);1293struct drm_bridge *drm_bridge_get(struct drm_bridge *bridge);
1282void drm_bridge_put(struct drm_bridge *bridge);1294void drm_bridge_put(struct drm_bridge *bridge);
1283 1295
include/drm/drm_device.h+15−0
@@ -3,6 +3,9 @@ · 2 unmodified lines
3 3
4#include <linux/list.h>4#include <linux/list.h>
5#include <linux/kref.h>5#include <linux/kref.h>
6#ifdef CONFIG_TRANSPARENT_HUGEPAGE
7#include <linux/mount.h>
8#endif
6#include <linux/mutex.h>9#include <linux/mutex.h>
7#include <linux/idr.h>10#include <linux/idr.h>
8#include <linux/sched.h>11#include <linux/sched.h>
@@ -168,6 +171,18 @@ struct drm_device { · 159 unmodified lines
168 */171 */
169 struct drm_master *master;172 struct drm_master *master;
170 173
174#ifdef CONFIG_TRANSPARENT_HUGEPAGE
175 /**
176 * @huge_mnt:
177 *
178 * Huge tmpfs mountpoint used at GEM object initialization
179 * drm_gem_object_init(). Drivers can call drm_gem_huge_mnt_create() to
180 * create, mount and use it. The default tmpfs mountpoint (`shm_mnt`) is
181 * used if NULL.
182 */
183 struct vfsmount *huge_mnt;
184#endif
185
171 /**186 /**
172 * @driver_features: per-device driver features187 * @driver_features: per-device driver features
173 *188 *
include/drm/drm_fb_helper.h+0−21
@@ -166,13 +166,6 @@ struct drm_fb_helper { · 165 unmodified lines
166 */166 */
167 struct mutex lock;167 struct mutex lock;
168 168
169 /**
170 * @kernel_fb_list:
171 *
172 * Entry on the global kernel_fb_helper_list, used for kgdb entry/exit.
173 */
174 struct list_head kernel_fb_list;
175
176 /**169 /**
177 * @delayed_hotplug:170 * @delayed_hotplug:
178 *171 *
@@ -236,8 +229,6 @@ drm_fb_helper_from_client(struct drm_client_dev *client) · 57 unmodified lines
236 .fb_setcmap = drm_fb_helper_setcmap, \229 .fb_setcmap = drm_fb_helper_setcmap, \
237 .fb_blank = drm_fb_helper_blank, \230 .fb_blank = drm_fb_helper_blank, \
238 .fb_pan_display = drm_fb_helper_pan_display, \231 .fb_pan_display = drm_fb_helper_pan_display, \
239 .fb_debug_enter = drm_fb_helper_debug_enter, \
240 .fb_debug_leave = drm_fb_helper_debug_leave, \
241 .fb_ioctl = drm_fb_helper_ioctl232 .fb_ioctl = drm_fb_helper_ioctl
242 233
243#ifdef CONFIG_DRM_FBDEV_EMULATION234#ifdef CONFIG_DRM_FBDEV_EMULATION
@@ -280,8 +271,6 @@ int drm_fb_helper_ioctl(struct fb_info *info, unsigned int cmd, · 36 unmodified lines
280 271
281int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);272int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper);
282int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper);273int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper);
283int drm_fb_helper_debug_enter(struct fb_info *info);
284int drm_fb_helper_debug_leave(struct fb_info *info);
285#else274#else
286static inline void drm_fb_helper_prepare(struct drm_device *dev,275static inline void drm_fb_helper_prepare(struct drm_device *dev,
287 struct drm_fb_helper *helper,276 struct drm_fb_helper *helper,
@@ -387,16 +376,6 @@ static inline int drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper) · 99 unmodified lines
387{376{
388 return 0;377 return 0;
389}378}
390
391static inline int drm_fb_helper_debug_enter(struct fb_info *info)
392{
393 return 0;
394}
395
396static inline int drm_fb_helper_debug_leave(struct fb_info *info)
397{
398 return 0;
399}
400#endif379#endif
401 380
402#endif381#endif
include/drm/drm_gem.h+42−3
@@ -40,6 +40,9 @@ · 39 unmodified lines
40#include <linux/list.h>40#include <linux/list.h>
41#include <linux/mutex.h>41#include <linux/mutex.h>
42 42
43#ifdef CONFIG_TRANSPARENT_HUGEPAGE
44#include <drm/drm_device.h>
45#endif
43#include <drm/drm_vma_manager.h>46#include <drm/drm_vma_manager.h>
44 47
45struct iosys_map;48struct iosys_map;
@@ -469,6 +472,7 @@ struct drm_gem_object { · 423 unmodified lines
469 .poll = drm_poll,\472 .poll = drm_poll,\
470 .read = drm_read,\473 .read = drm_read,\
471 .llseek = noop_llseek,\474 .llseek = noop_llseek,\
475 .get_unmapped_area = drm_gem_get_unmapped_area,\
472 .mmap = drm_gem_mmap, \476 .mmap = drm_gem_mmap, \
473 .fop_flags = FOP_UNSIGNED_OFFSET477 .fop_flags = FOP_UNSIGNED_OFFSET
474 478
@@ -491,13 +495,40 @@ struct drm_gem_object { · 16 unmodified lines
491 DRM_GEM_FOPS,\495 DRM_GEM_FOPS,\
492 }496 }
493 497
498#ifdef CONFIG_TRANSPARENT_HUGEPAGE
499int drm_gem_huge_mnt_create(struct drm_device *dev, const char *value);
500#else
501static inline int drm_gem_huge_mnt_create(struct drm_device *dev,
502 const char *value)
503{
504 return 0;
505}
506#endif
507
508/**
509 * drm_gem_get_huge_mnt - Get the huge tmpfs mountpoint used by a DRM device
510 * @dev: DRM device
511
512 * This function gets the huge tmpfs mountpoint used by DRM device @dev. A huge
513 * tmpfs mountpoint is used instead of `shm_mnt` after a successful call to
514 * drm_gem_huge_mnt_create() when CONFIG_TRANSPARENT_HUGEPAGE is enabled.
515
516 * Returns:
517 * The huge tmpfs mountpoint in use, NULL otherwise.
518 */
519static inline struct vfsmount *drm_gem_get_huge_mnt(struct drm_device *dev)
520{
521#ifdef CONFIG_TRANSPARENT_HUGEPAGE
522 return dev->huge_mnt;
523#else
524 return NULL;
525#endif
526}
527
494void drm_gem_object_release(struct drm_gem_object *obj);528void drm_gem_object_release(struct drm_gem_object *obj);
495void drm_gem_object_free(struct kref *kref);529void drm_gem_object_free(struct kref *kref);
496int drm_gem_object_init(struct drm_device *dev,530int drm_gem_object_init(struct drm_device *dev,
497 struct drm_gem_object *obj, size_t size);531 struct drm_gem_object *obj, size_t size);
498int drm_gem_object_init_with_mnt(struct drm_device *dev,
499 struct drm_gem_object *obj, size_t size,
500 struct vfsmount *gemfs);
501void drm_gem_private_object_init(struct drm_device *dev,532void drm_gem_private_object_init(struct drm_device *dev,
502 struct drm_gem_object *obj, size_t size);533 struct drm_gem_object *obj, size_t size);
503void drm_gem_private_object_fini(struct drm_gem_object *obj);534void drm_gem_private_object_fini(struct drm_gem_object *obj);
@@ -507,6 +538,14 @@ int drm_gem_mmap_obj(struct drm_gem_object *obj, unsigned long obj_size, · 3 unmodified lines
507 struct vm_area_struct *vma);538 struct vm_area_struct *vma);
508int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);539int drm_gem_mmap(struct file *filp, struct vm_area_struct *vma);
509 540
541#ifdef CONFIG_MMU
542unsigned long drm_gem_get_unmapped_area(struct file *filp, unsigned long uaddr,
543 unsigned long len, unsigned long pgoff,
544 unsigned long flags);
545#else
546#define drm_gem_get_unmapped_area NULL
547#endif
548
510/**549/**
511 * drm_gem_object_get - acquire a GEM buffer object reference550 * drm_gem_object_get - acquire a GEM buffer object reference
512 * @obj: GEM buffer object551 * @obj: GEM buffer object
include/drm/drm_gem_shmem_helper.h+0−3
@@ -109,9 +109,6 @@ struct drm_gem_shmem_object { · 108 unmodified lines
109 109
110int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem, size_t size);110int drm_gem_shmem_init(struct drm_device *dev, struct drm_gem_shmem_object *shmem, size_t size);
111struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size);111struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size);
112struct drm_gem_shmem_object *drm_gem_shmem_create_with_mnt(struct drm_device *dev,
113 size_t size,
114 struct vfsmount *gemfs);
115void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem);112void drm_gem_shmem_release(struct drm_gem_shmem_object *shmem);
116void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem);113void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem);
117 114
include/drm/drm_modeset_helper_vtables.h+0−23
@@ -52,11 +52,6 @@ struct drm_scanout_buffer; · 51 unmodified lines
52struct drm_writeback_connector;52struct drm_writeback_connector;
53struct drm_writeback_job;53struct drm_writeback_job;
54 54
55enum mode_set_atomic {
56 LEAVE_ATOMIC_MODE_SET,
57 ENTER_ATOMIC_MODE_SET,
58};
59
60/**55/**
61 * struct drm_crtc_helper_funcs - helper operations for CRTCs56 * struct drm_crtc_helper_funcs - helper operations for CRTCs
62 *57 *
@@ -253,24 +248,6 @@ struct drm_crtc_helper_funcs { · 190 unmodified lines
253 int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,248 int (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
254 struct drm_framebuffer *old_fb);249 struct drm_framebuffer *old_fb);
255 250
256 /**
257 * @mode_set_base_atomic:
258 *
259 * This callback is used by the fbdev helpers to set a new framebuffer
260 * and scanout without sleeping, i.e. from an atomic calling context. It
261 * is only used to implement kgdb support.
262 *
263 * This callback is optional and only needed for kgdb support in the fbdev
264 * helpers.
265 *
266 * RETURNS:
267 *
268 * 0 on success or a negative error code on failure.
269 */
270 int (*mode_set_base_atomic)(struct drm_crtc *crtc,
271 struct drm_framebuffer *fb, int x, int y,
272 enum mode_set_atomic);
273
274 /**251 /**
275 * @disable:252 * @disable:
276 *253 *
include/drm/drm_vblank.h+1−2
@@ -302,8 +302,7 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe); · 301 unmodified lines
302bool drm_crtc_handle_vblank(struct drm_crtc *crtc);302bool drm_crtc_handle_vblank(struct drm_crtc *crtc);
303int drm_crtc_vblank_get(struct drm_crtc *crtc);303int drm_crtc_vblank_get(struct drm_crtc *crtc);
304void drm_crtc_vblank_put(struct drm_crtc *crtc);304void drm_crtc_vblank_put(struct drm_crtc *crtc);
305void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe);305int drm_crtc_wait_one_vblank(struct drm_crtc *crtc);
306void drm_crtc_wait_one_vblank(struct drm_crtc *crtc);
307void drm_crtc_vblank_off(struct drm_crtc *crtc);306void drm_crtc_vblank_off(struct drm_crtc *crtc);
308void drm_crtc_vblank_reset(struct drm_crtc *crtc);307void drm_crtc_vblank_reset(struct drm_crtc *crtc);
309void drm_crtc_vblank_on_config(struct drm_crtc *crtc,308void drm_crtc_vblank_on_config(struct drm_crtc *crtc,
include/linux/dma-fence.h+28−7
@@ -364,11 +364,12 @@ static inline void dma_fence_end_signalling(bool cookie) {} · 363 unmodified lines
364static inline void __dma_fence_might_wait(void) {}364static inline void __dma_fence_might_wait(void) {}
365#endif365#endif
366 366
367int dma_fence_signal(struct dma_fence *fence);367void dma_fence_signal(struct dma_fence *fence);
368int dma_fence_signal_locked(struct dma_fence *fence);368bool dma_fence_check_and_signal(struct dma_fence *fence);
369int dma_fence_signal_timestamp(struct dma_fence *fence, ktime_t timestamp);369bool dma_fence_check_and_signal_locked(struct dma_fence *fence);
370int dma_fence_signal_timestamp_locked(struct dma_fence *fence,370void dma_fence_signal_locked(struct dma_fence *fence);
371 ktime_t timestamp);371void dma_fence_signal_timestamp(struct dma_fence *fence, ktime_t timestamp);
372void dma_fence_signal_timestamp_locked(struct dma_fence *fence, ktime_t timestamp);
372signed long dma_fence_default_wait(struct dma_fence *fence,373signed long dma_fence_default_wait(struct dma_fence *fence,
373 bool intr, signed long timeout);374 bool intr, signed long timeout);
374int dma_fence_add_callback(struct dma_fence *fence,375int dma_fence_add_callback(struct dma_fence *fence,
@@ -401,6 +402,26 @@ void dma_fence_enable_sw_signaling(struct dma_fence *fence); · 26 unmodified lines
401const char __rcu *dma_fence_driver_name(struct dma_fence *fence);402const char __rcu *dma_fence_driver_name(struct dma_fence *fence);
402const char __rcu *dma_fence_timeline_name(struct dma_fence *fence);403const char __rcu *dma_fence_timeline_name(struct dma_fence *fence);
403 404
405/*
406 * dma_fence_test_signaled_flag - Only check whether a fence is signaled yet.
407 * @fence: the fence to check
408 *
409 * This function just checks whether @fence is signaled, without interacting
410 * with the fence in any way. The user must, therefore, ensure through other
411 * means that fences get signaled eventually.
412 *
413 * This function uses test_bit(), which is thread-safe. Naturally, this function
414 * should be used opportunistically; a fence could get signaled at any moment
415 * after the check is done.
416 *
417 * Return: true if signaled, false otherwise.
418 */
419static inline bool
420dma_fence_test_signaled_flag(struct dma_fence *fence)
421{
422 return test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags);
423}
424
404/**425/**
405 * dma_fence_is_signaled_locked - Return an indication if the fence426 * dma_fence_is_signaled_locked - Return an indication if the fence
406 * is signaled yet.427 * is signaled yet.
@@ -418,7 +439,7 @@ const char __rcu *dma_fence_timeline_name(struct dma_fence *fence); · 11 unmodified lines
418static inline bool439static inline bool
419dma_fence_is_signaled_locked(struct dma_fence *fence)440dma_fence_is_signaled_locked(struct dma_fence *fence)
420{441{
421 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))442 if (dma_fence_test_signaled_flag(fence))
422 return true;443 return true;
423 444
424 if (fence->ops->signaled && fence->ops->signaled(fence)) {445 if (fence->ops->signaled && fence->ops->signaled(fence)) {
@@ -448,7 +469,7 @@ dma_fence_is_signaled_locked(struct dma_fence *fence) · 23 unmodified lines
448static inline bool469static inline bool
449dma_fence_is_signaled(struct dma_fence *fence)470dma_fence_is_signaled(struct dma_fence *fence)
450{471{
451 if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags))472 if (dma_fence_test_signaled_flag(fence))
452 return true;473 return true;
453 474
454 if (fence->ops->signaled && fence->ops->signaled(fence)) {475 if (fence->ops->signaled && fence->ops->signaled(fence)) {
include/linux/fb.h+0−4
@@ -304,10 +304,6 @@ struct fb_ops { · 303 unmodified lines
304 304
305 /* teardown any resources to do with this framebuffer */305 /* teardown any resources to do with this framebuffer */
306 void (*fb_destroy)(struct fb_info *info);306 void (*fb_destroy)(struct fb_info *info);
307
308 /* called at KDB enter and leave time to prepare the console */
309 int (*fb_debug_enter)(struct fb_info *info);
310 int (*fb_debug_leave)(struct fb_info *info);
311};307};
312 308
313#ifdef CONFIG_FB_TILEBLITTING309#ifdef CONFIG_FB_TILEBLITTING
include/uapi/drm/panfrost_drm.h+75−1
@@ -24,6 +24,8 @@ extern "C" { · 23 unmodified lines
24#define DRM_PANFROST_SET_LABEL_BO 0x0924#define DRM_PANFROST_SET_LABEL_BO 0x09
25#define DRM_PANFROST_JM_CTX_CREATE 0x0a25#define DRM_PANFROST_JM_CTX_CREATE 0x0a
26#define DRM_PANFROST_JM_CTX_DESTROY 0x0b26#define DRM_PANFROST_JM_CTX_DESTROY 0x0b
27#define DRM_PANFROST_SYNC_BO 0x0c
28#define DRM_PANFROST_QUERY_BO_INFO 0x0d
27 29
28#define DRM_IOCTL_PANFROST_SUBMIT DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_SUBMIT, struct drm_panfrost_submit)30#define DRM_IOCTL_PANFROST_SUBMIT DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_SUBMIT, struct drm_panfrost_submit)
29#define DRM_IOCTL_PANFROST_WAIT_BO DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_WAIT_BO, struct drm_panfrost_wait_bo)31#define DRM_IOCTL_PANFROST_WAIT_BO DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_WAIT_BO, struct drm_panfrost_wait_bo)
@@ -35,6 +37,8 @@ extern "C" { · 5 unmodified lines
35#define DRM_IOCTL_PANFROST_SET_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_SET_LABEL_BO, struct drm_panfrost_set_label_bo)37#define DRM_IOCTL_PANFROST_SET_LABEL_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_SET_LABEL_BO, struct drm_panfrost_set_label_bo)
36#define DRM_IOCTL_PANFROST_JM_CTX_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_JM_CTX_CREATE, struct drm_panfrost_jm_ctx_create)38#define DRM_IOCTL_PANFROST_JM_CTX_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_JM_CTX_CREATE, struct drm_panfrost_jm_ctx_create)
37#define DRM_IOCTL_PANFROST_JM_CTX_DESTROY DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_JM_CTX_DESTROY, struct drm_panfrost_jm_ctx_destroy)39#define DRM_IOCTL_PANFROST_JM_CTX_DESTROY DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_JM_CTX_DESTROY, struct drm_panfrost_jm_ctx_destroy)
40#define DRM_IOCTL_PANFROST_SYNC_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_SYNC_BO, struct drm_panfrost_sync_bo)
41#define DRM_IOCTL_PANFROST_QUERY_BO_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_QUERY_BO_INFO, struct drm_panfrost_query_bo_info)
38 42
39/*43/*
40 * Unstable ioctl(s): only exposed when the unsafe unstable_ioctls module44 * Unstable ioctl(s): only exposed when the unsafe unstable_ioctls module
@@ -120,9 +124,12 @@ struct drm_panfrost_wait_bo { · 79 unmodified lines
120 __s64 timeout_ns;124 __s64 timeout_ns;
121};125};
122 126
123/* Valid flags to pass to drm_panfrost_create_bo */127/* Valid flags to pass to drm_panfrost_create_bo.
128 * PANFROST_BO_WB_MMAP can't be set if PANFROST_BO_HEAP is.
129 */
124#define PANFROST_BO_NOEXEC 1130#define PANFROST_BO_NOEXEC 1
125#define PANFROST_BO_HEAP 2131#define PANFROST_BO_HEAP 2
132#define PANFROST_BO_WB_MMAP 4
126 133
127/**134/**
128 * struct drm_panfrost_create_bo - ioctl argument for creating Panfrost BOs.135 * struct drm_panfrost_create_bo - ioctl argument for creating Panfrost BOs.
@@ -228,6 +235,13 @@ enum drm_panfrost_param { · 99 unmodified lines
228 DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP,235 DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP,
229 DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP_FREQUENCY,236 DRM_PANFROST_PARAM_SYSTEM_TIMESTAMP_FREQUENCY,
230 DRM_PANFROST_PARAM_ALLOWED_JM_CTX_PRIORITIES,237 DRM_PANFROST_PARAM_ALLOWED_JM_CTX_PRIORITIES,
238 DRM_PANFROST_PARAM_SELECTED_COHERENCY,
239};
240
241enum drm_panfrost_gpu_coherency {
242 DRM_PANFROST_GPU_COHERENCY_ACE_LITE = 0,
243 DRM_PANFROST_GPU_COHERENCY_ACE = 1,
244 DRM_PANFROST_GPU_COHERENCY_NONE = 31,
231};245};
232 246
233struct drm_panfrost_get_param {247struct drm_panfrost_get_param {
@@ -301,6 +315,66 @@ struct drm_panfrost_set_label_bo { · 67 unmodified lines
301 __u64 label;315 __u64 label;
302};316};
303 317
318/* Valid flags to pass to drm_panfrost_bo_sync_op */
319#define PANFROST_BO_SYNC_CPU_CACHE_FLUSH 0
320#define PANFROST_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE 1
321
322/**
323 * struct drm_panthor_bo_flush_map_op - BO map sync op
324 */
325struct drm_panfrost_bo_sync_op {
326 /** @handle: Handle of the buffer object to sync. */
327 __u32 handle;
328
329 /** @type: Type of sync operation. */
330 __u32 type;
331
332 /**
333 * @offset: Offset into the BO at which the sync range starts.
334 *
335 * This will be rounded down to the nearest cache line as needed.
336 */
337 __u32 offset;
338
339 /**
340 * @size: Size of the range to sync
341 *
342 * @size + @offset will be rounded up to the nearest cache line as
343 * needed.
344 */
345 __u32 size;
346};
347
348/**
349 * struct drm_panfrost_sync_bo - ioctl argument for syncing BO maps
350 */
351struct drm_panfrost_sync_bo {
352 /** Array of struct drm_panfrost_bo_sync_op */
353 __u64 ops;
354
355 /** Number of BO sync ops */
356 __u32 op_count;
357
358 __u32 pad;
359};
360
361/** BO comes from a different subsystem. */
362#define DRM_PANFROST_BO_IS_IMPORTED (1 << 0)
363
364struct drm_panfrost_query_bo_info {
365 /** Handle of the object being queried. */
366 __u32 handle;
367
368 /** Extra flags that are not coming from the BO_CREATE ioctl(). */
369 __u32 extra_flags;
370
371 /** Flags passed at creation time. */
372 __u32 create_flags;
373
374 /** Will be zero on return. */
375 __u32 pad;
376};
377
304/* Definitions for coredump decoding in user space */378/* Definitions for coredump decoding in user space */
305#define PANFROSTDUMP_MAJOR 1379#define PANFROSTDUMP_MAJOR 1
306#define PANFROSTDUMP_MINOR 0380#define PANFROSTDUMP_MINOR 0
include/uapi/drm/panthor_drm.h+154−3
@@ -144,6 +144,16 @@ enum drm_panthor_ioctl_id { · 143 unmodified lines
144 * pgoff_t size.144 * pgoff_t size.
145 */145 */
146 DRM_PANTHOR_SET_USER_MMIO_OFFSET,146 DRM_PANTHOR_SET_USER_MMIO_OFFSET,
147
148 /** @DRM_PANTHOR_BO_SYNC: Sync BO data to/from the device */
149 DRM_PANTHOR_BO_SYNC,
150
151 /**
152 * @DRM_PANTHOR_BO_QUERY_INFO: Query information about a BO.
153 *
154 * This is useful for imported BOs.
155 */
156 DRM_PANTHOR_BO_QUERY_INFO,
147};157};
148 158
149/**159/**
@@ -245,6 +255,26 @@ enum drm_panthor_dev_query_type { · 95 unmodified lines
245 DRM_PANTHOR_DEV_QUERY_GROUP_PRIORITIES_INFO,255 DRM_PANTHOR_DEV_QUERY_GROUP_PRIORITIES_INFO,
246};256};
247 257
258/**
259 * enum drm_panthor_gpu_coherency: Type of GPU coherency
260 */
261enum drm_panthor_gpu_coherency {
262 /**
263 * @DRM_PANTHOR_GPU_COHERENCY_ACE_LITE: ACE Lite coherency.
264 */
265 DRM_PANTHOR_GPU_COHERENCY_ACE_LITE = 0,
266
267 /**
268 * @DRM_PANTHOR_GPU_COHERENCY_ACE: ACE coherency.
269 */
270 DRM_PANTHOR_GPU_COHERENCY_ACE = 1,
271
272 /**
273 * @DRM_PANTHOR_GPU_COHERENCY_NONE: No coherency.
274 */
275 DRM_PANTHOR_GPU_COHERENCY_NONE = 31,
276};
277
248/**278/**
249 * struct drm_panthor_gpu_info - GPU information279 * struct drm_panthor_gpu_info - GPU information
250 *280 *
@@ -301,7 +331,16 @@ struct drm_panthor_gpu_info { · 50 unmodified lines
301 */331 */
302 __u32 thread_max_barrier_size;332 __u32 thread_max_barrier_size;
303 333
304 /** @coherency_features: Coherency features. */334 /**
335 * @coherency_features: Coherency features.
336 *
337 * Combination of drm_panthor_gpu_coherency flags.
338 *
339 * Note that this is just what the coherency protocols supported by the
340 * GPU, but the actual coherency in place depends on the SoC
341 * integration and is reflected by
342 * drm_panthor_gpu_info::selected_coherency.
343 */
305 __u32 coherency_features;344 __u32 coherency_features;
306 345
307 /** @texture_features: Texture features. */346 /** @texture_features: Texture features. */
@@ -310,8 +349,12 @@ struct drm_panthor_gpu_info { · 2 unmodified lines
310 /** @as_present: Bitmask encoding the number of address-space exposed by the MMU. */349 /** @as_present: Bitmask encoding the number of address-space exposed by the MMU. */
311 __u32 as_present;350 __u32 as_present;
312 351
313 /** @pad0: MBZ. */352 /**
314 __u32 pad0;353 * @select_coherency: Coherency selected for this device.
354 *
355 * One of drm_panthor_gpu_coherency.
356 */
357 __u32 selected_coherency;
315 358
316 /** @shader_present: Bitmask encoding the shader cores exposed by the GPU. */359 /** @shader_present: Bitmask encoding the shader cores exposed by the GPU. */
317 __u64 shader_present;360 __u64 shader_present;
@@ -638,6 +681,15 @@ struct drm_panthor_vm_get_state { · 320 unmodified lines
638enum drm_panthor_bo_flags {681enum drm_panthor_bo_flags {
639 /** @DRM_PANTHOR_BO_NO_MMAP: The buffer object will never be CPU-mapped in userspace. */682 /** @DRM_PANTHOR_BO_NO_MMAP: The buffer object will never be CPU-mapped in userspace. */
640 DRM_PANTHOR_BO_NO_MMAP = (1 << 0),683 DRM_PANTHOR_BO_NO_MMAP = (1 << 0),
684
685 /**
686 * @DRM_PANTHOR_BO_WB_MMAP: Force "Write-Back Cacheable" CPU mapping.
687 *
688 * CPU map the buffer object in userspace by forcing the "Write-Back
689 * Cacheable" cacheability attribute. The mapping otherwise uses the
690 * "Non-Cacheable" attribute if the GPU is not IO coherent.
691 */
692 DRM_PANTHOR_BO_WB_MMAP = (1 << 1),
641};693};
642 694
643/**695/**
@@ -1040,6 +1092,101 @@ struct drm_panthor_set_user_mmio_offset { · 396 unmodified lines
1040 __u64 offset;1092 __u64 offset;
1041};1093};
1042 1094
1095/**
1096 * enum drm_panthor_bo_sync_op_type - BO sync type
1097 */
1098enum drm_panthor_bo_sync_op_type {
1099 /** @DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH: Flush CPU caches. */
1100 DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH = 0,
1101
1102 /** @DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE: Flush and invalidate CPU caches. */
1103 DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE = 1,
1104};
1105
1106/**
1107 * struct drm_panthor_bo_sync_op - BO map sync op
1108 */
1109struct drm_panthor_bo_sync_op {
1110 /** @handle: Handle of the buffer object to sync. */
1111 __u32 handle;
1112
1113 /** @type: Type of operation. */
1114 __u32 type;
1115
1116 /**
1117 * @offset: Offset into the BO at which the sync range starts.
1118 *
1119 * This will be rounded down to the nearest cache line as needed.
1120 */
1121 __u64 offset;
1122
1123 /**
1124 * @size: Size of the range to sync
1125 *
1126 * @size + @offset will be rounded up to the nearest cache line as
1127 * needed.
1128 */
1129 __u64 size;
1130};
1131
1132/**
1133 * struct drm_panthor_bo_sync - BO map sync request
1134 */
1135struct drm_panthor_bo_sync {
1136 /**
1137 * @ops: Array of struct drm_panthor_bo_sync_op sync operations.
1138 */
1139 struct drm_panthor_obj_array ops;
1140};
1141
1142/**
1143 * enum drm_panthor_bo_extra_flags - Set of flags returned on a BO_QUERY_INFO request
1144 *
1145 * Those are flags reflecting BO properties that are not directly coming from the flags
1146 * passed are creation time, or information on BOs that were imported from other drivers.
1147 */
1148enum drm_panthor_bo_extra_flags {
1149 /**
1150 * @DRM_PANTHOR_BO_IS_IMPORTED: BO has been imported from an external driver.
1151 *
1152 * Note that imported dma-buf handles are not flagged as imported if they
1153 * where exported by panthor. Only buffers that are coming from other drivers
1154 * (dma heaps, other GPUs, display controllers, V4L, ...).
1155 *
1156 * It's also important to note that all imported BOs are mapped cached and can't
1157 * be considered IO-coherent even if the GPU is. This means they require explicit
1158 * syncs that must go through the DRM_PANTHOR_BO_SYNC ioctl (userland cache
1159 * maintenance is not allowed in that case, because extra operations might be
1160 * needed to make changes visible to the CPU/device, like buffer migration when the
1161 * exporter is a GPU with its own VRAM).
1162 */
1163 DRM_PANTHOR_BO_IS_IMPORTED = (1 << 0),
1164};
1165
1166/**
1167 * struct drm_panthor_bo_query_info - Query BO info
1168 */
1169struct drm_panthor_bo_query_info {
1170 /** @handle: Handle of the buffer object to query flags on. */
1171 __u32 handle;
1172
1173 /**
1174 * @extra_flags: Combination of enum drm_panthor_bo_extra_flags flags.
1175 */
1176 __u32 extra_flags;
1177
1178 /**
1179 * @create_flags: Flags passed at creation time.
1180 *
1181 * Combination of enum drm_panthor_bo_flags flags.
1182 * Will be zero if the buffer comes from a different driver.
1183 */
1184 __u32 create_flags;
1185
1186 /** @pad: Will be zero on return. */
1187 __u32 pad;
1188};
1189
1043/**1190/**
1044 * DRM_IOCTL_PANTHOR() - Build a Panthor IOCTL number1191 * DRM_IOCTL_PANTHOR() - Build a Panthor IOCTL number
1045 * @__access: Access type. Must be R, W or RW.1192 * @__access: Access type. Must be R, W or RW.
@@ -1086,6 +1233,10 @@ enum { · 40 unmodified lines
1086 DRM_IOCTL_PANTHOR(WR, BO_SET_LABEL, bo_set_label),1233 DRM_IOCTL_PANTHOR(WR, BO_SET_LABEL, bo_set_label),
1087 DRM_IOCTL_PANTHOR_SET_USER_MMIO_OFFSET =1234 DRM_IOCTL_PANTHOR_SET_USER_MMIO_OFFSET =
1088 DRM_IOCTL_PANTHOR(WR, SET_USER_MMIO_OFFSET, set_user_mmio_offset),1235 DRM_IOCTL_PANTHOR(WR, SET_USER_MMIO_OFFSET, set_user_mmio_offset),
1236 DRM_IOCTL_PANTHOR_BO_SYNC =
1237 DRM_IOCTL_PANTHOR(WR, BO_SYNC, bo_sync),
1238 DRM_IOCTL_PANTHOR_BO_QUERY_INFO =
1239 DRM_IOCTL_PANTHOR(WR, BO_QUERY_INFO, bo_query_info),
1089};1240};
1090 1241
1091#if defined(__cplusplus)1242#if defined(__cplusplus)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t