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

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

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