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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'drm-misc-next-2023-12-07' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for 6.8:

UAPI Changes:
- Remove Userspace Mode-Setting ioctls
- v3d: New uapi to handle jobs involving the CPU

Cross-subsystem Changes:

Core Changes:
- atomic: Add support for FB-less planes which got reverted a bit
later for lack of IGT tests and userspace code, Dump private objects
state in drm_state_dump.
- dma-buf: Add fence deadline support
- encoder: Create per-encoder debugfs directory, move the bridge chain
file to that directory

Driver Changes:
- Include drm_auth.h in driver that use it but don't include it, Drop
drm_plane_helper.h from drivers that include it but don't use it
- imagination: Plenty of small fixes
- panfrost: Improve interrupt handling at poweroff
- qaic: Convert to persistent DRM devices
- tidss: Support for the AM62A7, a few probe improvements, some cleanups
- v3d: Support for jobs involving the CPU

- bridge:
- Create transparent aux-bridge for DP/USB-C
- lt8912b: Add suspend/resume support and power regulator support

- panel:
- himax-hx8394: Drop prepare, unprepare and shutdown logic, Support
panel rotation
- New panels: BOE BP101WX1-100, Powkiddy X55, Ampire AM8001280G,
Evervision VGG644804, SDC ATNA45AF01

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Maxime Ripard <mripard@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/yu5heqaufyeo4nlowzieu4s5unwqrqyx4jixbfjmzdon677rpk@t53vceua2dao

+6456 -10514
+8 -1
Documentation/accel/qaic/qaic.rst
··· 93 93 uAPI 94 94 ==== 95 95 96 + QAIC creates an accel device per phsyical PCIe device. This accel device exists 97 + for as long as the PCIe device is known to Linux. 98 + 99 + The PCIe device may not be in the state to accept requests from userspace at 100 + all times. QAIC will trigger KOBJ_ONLINE/OFFLINE uevents to advertise when the 101 + device can accept requests (ONLINE) and when the device is no longer accepting 102 + requests (OFFLINE) because of a reset or other state transition. 103 + 96 104 QAIC defines a number of driver specific IOCTLs as part of the userspace API. 97 - This section describes those APIs. 98 105 99 106 DRM_IOCTL_QAIC_MANAGE 100 107 This IOCTL allows userspace to send a NNC request to the QSM. The call will
+2
Documentation/core-api/pin_user_pages.rst
··· 153 153 because DAX pages do not have a separate page cache, and so "pinning" implies 154 154 locking down file system blocks, which is not (yet) supported in that way. 155 155 156 + .. _mmu-notifier-registration-case: 157 + 156 158 CASE 3: MMU notifier registration, with or without page faulting hardware 157 159 ------------------------------------------------------------------------- 158 160 Device drivers can pin pages via get_user_pages*(), and register for mmu
+21
Documentation/devicetree/bindings/display/bridge/lontium,lt8912b.yaml
··· 55 55 - port@0 56 56 - port@1 57 57 58 + vcchdmipll-supply: 59 + description: A 1.8V supply that powers the HDMI PLL. 60 + 61 + vcchdmitx-supply: 62 + description: A 1.8V supply that powers the HDMI TX part. 63 + 64 + vcclvdspll-supply: 65 + description: A 1.8V supply that powers the LVDS PLL. 66 + 67 + vcclvdstx-supply: 68 + description: A 1.8V supply that powers the LVDS TX part. 69 + 70 + vccmipirx-supply: 71 + description: A 1.8V supply that powers the MIPI RX part. 72 + 73 + vccsysclk-supply: 74 + description: A 1.8V supply that powers the SYSCLK. 75 + 76 + vdd-supply: 77 + description: A 1.8V supply that powers the digital part. 78 + 58 79 required: 59 80 - compatible 60 81 - reg
+3
Documentation/devicetree/bindings/display/panel/himax,hx8394.yaml
··· 23 23 items: 24 24 - enum: 25 25 - hannstar,hsd060bhw4 26 + - powkiddy,x55-panel 26 27 - const: himax,hx8394 27 28 28 29 reg: true ··· 31 30 reset-gpios: true 32 31 33 32 backlight: true 33 + 34 + rotation: true 34 35 35 36 port: true 36 37
+1
Documentation/devicetree/bindings/display/panel/ilitek,ili9881c.yaml
··· 16 16 compatible: 17 17 items: 18 18 - enum: 19 + - ampire,am8001280g 19 20 - bananapi,lhr050h41 20 21 - feixin,k101-im2byl02 21 22 - tdo,tl050hdv35
+4
Documentation/devicetree/bindings/display/panel/panel-simple.yaml
··· 73 73 - auo,t215hvn01 74 74 # Shanghai AVIC Optoelectronics 7" 1024x600 color TFT-LCD panel 75 75 - avic,tm070ddh03 76 + # BOE BP101WX1-100 10.1" WXGA (1280x800) LVDS panel 77 + - boe,bp101wx1-100 76 78 # BOE EV121WXM-N10-1850 12.1" WXGA (1280x800) TFT LCD panel 77 79 - boe,ev121wxm-n10-1850 78 80 # BOE HV070WSA-100 7.01" WSVGA TFT LCD panel ··· 146 144 - edt,etmv570g2dhu 147 145 # E Ink VB3300-KCA 148 146 - eink,vb3300-kca 147 + # Evervision Electronics Co. Ltd. VGG644804 5.7" VGA TFT LCD Panel 148 + - evervision,vgg644804 149 149 # Evervision Electronics Co. Ltd. VGG804821 5.0" WVGA TFT LCD Panel 150 150 - evervision,vgg804821 151 151 # Foxlink Group 5" WVGA TFT LCD panel
+14
Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml
··· 23 23 compatible: 24 24 enum: 25 25 - ti,am625-dss 26 + - ti,am62a7,dss 26 27 - ti,am65x-dss 27 28 28 29 reg: ··· 88 87 For AM65x DSS, the OLDI output port node from video port 1. 89 88 For AM625 DSS, the internal DPI output port node from video 90 89 port 1. 90 + For AM62A7 DSS, the port is tied off inside the SoC. 91 91 92 92 port@1: 93 93 $ref: /schemas/graph.yaml#/properties/port ··· 109 107 description: 110 108 Input memory (from main memory to dispc) bandwidth limit in 111 109 bytes per second 110 + 111 + allOf: 112 + - if: 113 + properties: 114 + compatible: 115 + contains: 116 + const: ti,am62a7-dss 117 + then: 118 + properties: 119 + ports: 120 + properties: 121 + port@0: false 112 122 113 123 required: 114 124 - compatible
+1
Documentation/devicetree/bindings/gpu/arm,mali-utgard.yaml
··· 29 29 - allwinner,sun50i-a64-mali 30 30 - rockchip,rk3036-mali 31 31 - rockchip,rk3066-mali 32 + - rockchip,rk3128-mali 32 33 - rockchip,rk3188-mali 33 34 - rockchip,rk3228-mali 34 35 - samsung,exynos4210-mali
+8
Documentation/gpu/drm-kms.rst
··· 548 548 .. kernel-doc:: drivers/gpu/drm/drm_blend.c 549 549 :doc: overview 550 550 551 + .. _damage_tracking_properties: 552 + 551 553 Damage Tracking Properties 552 554 -------------------------- 553 555 ··· 580 578 581 579 .. kernel-doc:: drivers/gpu/drm/drm_connector.c 582 580 :doc: Variable refresh properties 581 + 582 + Cursor Hotspot Properties 583 + --------------------------- 584 + 585 + .. kernel-doc:: drivers/gpu/drm/drm_plane.c 586 + :doc: hotspot properties 583 587 584 588 Existing KMS Properties 585 589 -----------------------
+4
Documentation/gpu/drm-mm.rst
··· 466 466 .. kernel-doc:: drivers/gpu/drm/drm_mm.c 467 467 :export: 468 468 469 + .. _drm_gpuvm: 470 + 469 471 DRM GPUVM 470 472 ========= 471 473 ··· 482 480 483 481 .. kernel-doc:: drivers/gpu/drm/drm_gpuvm.c 484 482 :doc: Split and Merge 483 + 484 + .. _drm_gpuvm_locking: 485 485 486 486 Locking 487 487 -------
+582
Documentation/gpu/drm-vm-bind-locking.rst
··· 1 + .. SPDX-License-Identifier: (GPL-2.0+ OR MIT) 2 + 3 + =============== 4 + VM_BIND locking 5 + =============== 6 + 7 + This document attempts to describe what's needed to get VM_BIND locking right, 8 + including the userptr mmu_notifier locking. It also discusses some 9 + optimizations to get rid of the looping through of all userptr mappings and 10 + external / shared object mappings that is needed in the simplest 11 + implementation. In addition, there is a section describing the VM_BIND locking 12 + required for implementing recoverable pagefaults. 13 + 14 + The DRM GPUVM set of helpers 15 + ============================ 16 + 17 + There is a set of helpers for drivers implementing VM_BIND, and this 18 + set of helpers implements much, but not all of the locking described 19 + in this document. In particular, it is currently lacking a userptr 20 + implementation. This document does not intend to describe the DRM GPUVM 21 + implementation in detail, but it is covered in :ref:`its own 22 + documentation <drm_gpuvm>`. It is highly recommended for any driver 23 + implementing VM_BIND to use the DRM GPUVM helpers and to extend it if 24 + common functionality is missing. 25 + 26 + Nomenclature 27 + ============ 28 + 29 + * ``gpu_vm``: Abstraction of a virtual GPU address space with 30 + meta-data. Typically one per client (DRM file-private), or one per 31 + execution context. 32 + * ``gpu_vma``: Abstraction of a GPU address range within a gpu_vm with 33 + associated meta-data. The backing storage of a gpu_vma can either be 34 + a GEM object or anonymous or page-cache pages mapped also into the CPU 35 + address space for the process. 36 + * ``gpu_vm_bo``: Abstracts the association of a GEM object and 37 + a VM. The GEM object maintains a list of gpu_vm_bos, where each gpu_vm_bo 38 + maintains a list of gpu_vmas. 39 + * ``userptr gpu_vma or just userptr``: A gpu_vma, whose backing store 40 + is anonymous or page-cache pages as described above. 41 + * ``revalidating``: Revalidating a gpu_vma means making the latest version 42 + of the backing store resident and making sure the gpu_vma's 43 + page-table entries point to that backing store. 44 + * ``dma_fence``: A struct dma_fence that is similar to a struct completion 45 + and which tracks GPU activity. When the GPU activity is finished, 46 + the dma_fence signals. Please refer to the ``DMA Fences`` section of 47 + the :doc:`dma-buf doc </driver-api/dma-buf>`. 48 + * ``dma_resv``: A struct dma_resv (a.k.a reservation object) that is used 49 + to track GPU activity in the form of multiple dma_fences on a 50 + gpu_vm or a GEM object. The dma_resv contains an array / list 51 + of dma_fences and a lock that needs to be held when adding 52 + additional dma_fences to the dma_resv. The lock is of a type that 53 + allows deadlock-safe locking of multiple dma_resvs in arbitrary 54 + order. Please refer to the ``Reservation Objects`` section of the 55 + :doc:`dma-buf doc </driver-api/dma-buf>`. 56 + * ``exec function``: An exec function is a function that revalidates all 57 + affected gpu_vmas, submits a GPU command batch and registers the 58 + dma_fence representing the GPU command's activity with all affected 59 + dma_resvs. For completeness, although not covered by this document, 60 + it's worth mentioning that an exec function may also be the 61 + revalidation worker that is used by some drivers in compute / 62 + long-running mode. 63 + * ``local object``: A GEM object which is only mapped within a 64 + single VM. Local GEM objects share the gpu_vm's dma_resv. 65 + * ``external object``: a.k.a shared object: A GEM object which may be shared 66 + by multiple gpu_vms and whose backing storage may be shared with 67 + other drivers. 68 + 69 + Locks and locking order 70 + ======================= 71 + 72 + One of the benefits of VM_BIND is that local GEM objects share the gpu_vm's 73 + dma_resv object and hence the dma_resv lock. So, even with a huge 74 + number of local GEM objects, only one lock is needed to make the exec 75 + sequence atomic. 76 + 77 + The following locks and locking orders are used: 78 + 79 + * The ``gpu_vm->lock`` (optionally an rwsem). Protects the gpu_vm's 80 + data structure keeping track of gpu_vmas. It can also protect the 81 + gpu_vm's list of userptr gpu_vmas. With a CPU mm analogy this would 82 + correspond to the mmap_lock. An rwsem allows several readers to walk 83 + the VM tree concurrently, but the benefit of that concurrency most 84 + likely varies from driver to driver. 85 + * The ``userptr_seqlock``. This lock is taken in read mode for each 86 + userptr gpu_vma on the gpu_vm's userptr list, and in write mode during mmu 87 + notifier invalidation. This is not a real seqlock but described in 88 + ``mm/mmu_notifier.c`` as a "Collision-retry read-side/write-side 89 + 'lock' a lot like a seqcount. However this allows multiple 90 + write-sides to hold it at once...". The read side critical section 91 + is enclosed by ``mmu_interval_read_begin() / 92 + mmu_interval_read_retry()`` with ``mmu_interval_read_begin()`` 93 + sleeping if the write side is held. 94 + The write side is held by the core mm while calling mmu interval 95 + invalidation notifiers. 96 + * The ``gpu_vm->resv`` lock. Protects the gpu_vm's list of gpu_vmas needing 97 + rebinding, as well as the residency state of all the gpu_vm's local 98 + GEM objects. 99 + Furthermore, it typically protects the gpu_vm's list of evicted and 100 + external GEM objects. 101 + * The ``gpu_vm->userptr_notifier_lock``. This is an rwsem that is 102 + taken in read mode during exec and write mode during a mmu notifier 103 + invalidation. The userptr notifier lock is per gpu_vm. 104 + * The ``gem_object->gpuva_lock`` This lock protects the GEM object's 105 + list of gpu_vm_bos. This is usually the same lock as the GEM 106 + object's dma_resv, but some drivers protects this list differently, 107 + see below. 108 + * The ``gpu_vm list spinlocks``. With some implementations they are needed 109 + to be able to update the gpu_vm evicted- and external object 110 + list. For those implementations, the spinlocks are grabbed when the 111 + lists are manipulated. However, to avoid locking order violations 112 + with the dma_resv locks, a special scheme is needed when iterating 113 + over the lists. 114 + 115 + .. _gpu_vma lifetime: 116 + 117 + Protection and lifetime of gpu_vm_bos and gpu_vmas 118 + ================================================== 119 + 120 + The GEM object's list of gpu_vm_bos, and the gpu_vm_bo's list of gpu_vmas 121 + is protected by the ``gem_object->gpuva_lock``, which is typically the 122 + same as the GEM object's dma_resv, but if the driver 123 + needs to access these lists from within a dma_fence signalling 124 + critical section, it can instead choose to protect it with a 125 + separate lock, which can be locked from within the dma_fence signalling 126 + critical section. Such drivers then need to pay additional attention 127 + to what locks need to be taken from within the loop when iterating 128 + over the gpu_vm_bo and gpu_vma lists to avoid locking-order violations. 129 + 130 + The DRM GPUVM set of helpers provide lockdep asserts that this lock is 131 + held in relevant situations and also provides a means of making itself 132 + aware of which lock is actually used: :c:func:`drm_gem_gpuva_set_lock`. 133 + 134 + Each gpu_vm_bo holds a reference counted pointer to the underlying GEM 135 + object, and each gpu_vma holds a reference counted pointer to the 136 + gpu_vm_bo. When iterating over the GEM object's list of gpu_vm_bos and 137 + over the gpu_vm_bo's list of gpu_vmas, the ``gem_object->gpuva_lock`` must 138 + not be dropped, otherwise, gpu_vmas attached to a gpu_vm_bo may 139 + disappear without notice since those are not reference-counted. A 140 + driver may implement its own scheme to allow this at the expense of 141 + additional complexity, but this is outside the scope of this document. 142 + 143 + In the DRM GPUVM implementation, each gpu_vm_bo and each gpu_vma 144 + holds a reference count on the gpu_vm itself. Due to this, and to avoid circular 145 + reference counting, cleanup of the gpu_vm's gpu_vmas must not be done from the 146 + gpu_vm's destructor. Drivers typically implements a gpu_vm close 147 + function for this cleanup. The gpu_vm close function will abort gpu 148 + execution using this VM, unmap all gpu_vmas and release page-table memory. 149 + 150 + Revalidation and eviction of local objects 151 + ========================================== 152 + 153 + Note that in all the code examples given below we use simplified 154 + pseudo-code. In particular, the dma_resv deadlock avoidance algorithm 155 + as well as reserving memory for dma_resv fences is left out. 156 + 157 + Revalidation 158 + ____________ 159 + With VM_BIND, all local objects need to be resident when the gpu is 160 + executing using the gpu_vm, and the objects need to have valid 161 + gpu_vmas set up pointing to them. Typically, each gpu command buffer 162 + submission is therefore preceded with a re-validation section: 163 + 164 + .. code-block:: C 165 + 166 + dma_resv_lock(gpu_vm->resv); 167 + 168 + // Validation section starts here. 169 + for_each_gpu_vm_bo_on_evict_list(&gpu_vm->evict_list, &gpu_vm_bo) { 170 + validate_gem_bo(&gpu_vm_bo->gem_bo); 171 + 172 + // The following list iteration needs the Gem object's 173 + // dma_resv to be held (it protects the gpu_vm_bo's list of 174 + // gpu_vmas, but since local gem objects share the gpu_vm's 175 + // dma_resv, it is already held at this point. 176 + for_each_gpu_vma_of_gpu_vm_bo(&gpu_vm_bo, &gpu_vma) 177 + move_gpu_vma_to_rebind_list(&gpu_vma, &gpu_vm->rebind_list); 178 + } 179 + 180 + for_each_gpu_vma_on_rebind_list(&gpu vm->rebind_list, &gpu_vma) { 181 + rebind_gpu_vma(&gpu_vma); 182 + remove_gpu_vma_from_rebind_list(&gpu_vma); 183 + } 184 + // Validation section ends here, and job submission starts. 185 + 186 + add_dependencies(&gpu_job, &gpu_vm->resv); 187 + job_dma_fence = gpu_submit(&gpu_job)); 188 + 189 + add_dma_fence(job_dma_fence, &gpu_vm->resv); 190 + dma_resv_unlock(gpu_vm->resv); 191 + 192 + The reason for having a separate gpu_vm rebind list is that there 193 + might be userptr gpu_vmas that are not mapping a buffer object that 194 + also need rebinding. 195 + 196 + Eviction 197 + ________ 198 + 199 + Eviction of one of these local objects will then look similar to the 200 + following: 201 + 202 + .. code-block:: C 203 + 204 + obj = get_object_from_lru(); 205 + 206 + dma_resv_lock(obj->resv); 207 + for_each_gpu_vm_bo_of_obj(obj, &gpu_vm_bo); 208 + add_gpu_vm_bo_to_evict_list(&gpu_vm_bo, &gpu_vm->evict_list); 209 + 210 + add_dependencies(&eviction_job, &obj->resv); 211 + job_dma_fence = gpu_submit(&eviction_job); 212 + add_dma_fence(&obj->resv, job_dma_fence); 213 + 214 + dma_resv_unlock(&obj->resv); 215 + put_object(obj); 216 + 217 + Note that since the object is local to the gpu_vm, it will share the gpu_vm's 218 + dma_resv lock such that ``obj->resv == gpu_vm->resv``. 219 + The gpu_vm_bos marked for eviction are put on the gpu_vm's evict list, 220 + which is protected by ``gpu_vm->resv``. During eviction all local 221 + objects have their dma_resv locked and, due to the above equality, also 222 + the gpu_vm's dma_resv protecting the gpu_vm's evict list is locked. 223 + 224 + With VM_BIND, gpu_vmas don't need to be unbound before eviction, 225 + since the driver must ensure that the eviction blit or copy will wait 226 + for GPU idle or depend on all previous GPU activity. Furthermore, any 227 + subsequent attempt by the GPU to access freed memory through the 228 + gpu_vma will be preceded by a new exec function, with a revalidation 229 + section which will make sure all gpu_vmas are rebound. The eviction 230 + code holding the object's dma_resv while revalidating will ensure a 231 + new exec function may not race with the eviction. 232 + 233 + A driver can be implemented in such a way that, on each exec function, 234 + only a subset of vmas are selected for rebind. In this case, all vmas that are 235 + *not* selected for rebind must be unbound before the exec 236 + function workload is submitted. 237 + 238 + Locking with external buffer objects 239 + ==================================== 240 + 241 + Since external buffer objects may be shared by multiple gpu_vm's they 242 + can't share their reservation object with a single gpu_vm. Instead 243 + they need to have a reservation object of their own. The external 244 + objects bound to a gpu_vm using one or many gpu_vmas are therefore put on a 245 + per-gpu_vm list which is protected by the gpu_vm's dma_resv lock or 246 + one of the :ref:`gpu_vm list spinlocks <Spinlock iteration>`. Once 247 + the gpu_vm's reservation object is locked, it is safe to traverse the 248 + external object list and lock the dma_resvs of all external 249 + objects. However, if instead a list spinlock is used, a more elaborate 250 + iteration scheme needs to be used. 251 + 252 + At eviction time, the gpu_vm_bos of *all* the gpu_vms an external 253 + object is bound to need to be put on their gpu_vm's evict list. 254 + However, when evicting an external object, the dma_resvs of the 255 + gpu_vms the object is bound to are typically not held. Only 256 + the object's private dma_resv can be guaranteed to be held. If there 257 + is a ww_acquire context at hand at eviction time we could grab those 258 + dma_resvs but that could cause expensive ww_mutex rollbacks. A simple 259 + option is to just mark the gpu_vm_bos of the evicted gem object with 260 + an ``evicted`` bool that is inspected before the next time the 261 + corresponding gpu_vm evicted list needs to be traversed. For example, when 262 + traversing the list of external objects and locking them. At that time, 263 + both the gpu_vm's dma_resv and the object's dma_resv is held, and the 264 + gpu_vm_bo marked evicted, can then be added to the gpu_vm's list of 265 + evicted gpu_vm_bos. The ``evicted`` bool is formally protected by the 266 + object's dma_resv. 267 + 268 + The exec function becomes 269 + 270 + .. code-block:: C 271 + 272 + dma_resv_lock(gpu_vm->resv); 273 + 274 + // External object list is protected by the gpu_vm->resv lock. 275 + for_each_gpu_vm_bo_on_extobj_list(gpu_vm, &gpu_vm_bo) { 276 + dma_resv_lock(gpu_vm_bo.gem_obj->resv); 277 + if (gpu_vm_bo_marked_evicted(&gpu_vm_bo)) 278 + add_gpu_vm_bo_to_evict_list(&gpu_vm_bo, &gpu_vm->evict_list); 279 + } 280 + 281 + for_each_gpu_vm_bo_on_evict_list(&gpu_vm->evict_list, &gpu_vm_bo) { 282 + validate_gem_bo(&gpu_vm_bo->gem_bo); 283 + 284 + for_each_gpu_vma_of_gpu_vm_bo(&gpu_vm_bo, &gpu_vma) 285 + move_gpu_vma_to_rebind_list(&gpu_vma, &gpu_vm->rebind_list); 286 + } 287 + 288 + for_each_gpu_vma_on_rebind_list(&gpu vm->rebind_list, &gpu_vma) { 289 + rebind_gpu_vma(&gpu_vma); 290 + remove_gpu_vma_from_rebind_list(&gpu_vma); 291 + } 292 + 293 + add_dependencies(&gpu_job, &gpu_vm->resv); 294 + job_dma_fence = gpu_submit(&gpu_job)); 295 + 296 + add_dma_fence(job_dma_fence, &gpu_vm->resv); 297 + for_each_external_obj(gpu_vm, &obj) 298 + add_dma_fence(job_dma_fence, &obj->resv); 299 + dma_resv_unlock_all_resv_locks(); 300 + 301 + And the corresponding shared-object aware eviction would look like: 302 + 303 + .. code-block:: C 304 + 305 + obj = get_object_from_lru(); 306 + 307 + dma_resv_lock(obj->resv); 308 + for_each_gpu_vm_bo_of_obj(obj, &gpu_vm_bo) 309 + if (object_is_vm_local(obj)) 310 + add_gpu_vm_bo_to_evict_list(&gpu_vm_bo, &gpu_vm->evict_list); 311 + else 312 + mark_gpu_vm_bo_evicted(&gpu_vm_bo); 313 + 314 + add_dependencies(&eviction_job, &obj->resv); 315 + job_dma_fence = gpu_submit(&eviction_job); 316 + add_dma_fence(&obj->resv, job_dma_fence); 317 + 318 + dma_resv_unlock(&obj->resv); 319 + put_object(obj); 320 + 321 + .. _Spinlock iteration: 322 + 323 + Accessing the gpu_vm's lists without the dma_resv lock held 324 + =========================================================== 325 + 326 + Some drivers will hold the gpu_vm's dma_resv lock when accessing the 327 + gpu_vm's evict list and external objects lists. However, there are 328 + drivers that need to access these lists without the dma_resv lock 329 + held, for example due to asynchronous state updates from within the 330 + dma_fence signalling critical path. In such cases, a spinlock can be 331 + used to protect manipulation of the lists. However, since higher level 332 + sleeping locks need to be taken for each list item while iterating 333 + over the lists, the items already iterated over need to be 334 + temporarily moved to a private list and the spinlock released 335 + while processing each item: 336 + 337 + .. code block:: C 338 + 339 + struct list_head still_in_list; 340 + 341 + INIT_LIST_HEAD(&still_in_list); 342 + 343 + spin_lock(&gpu_vm->list_lock); 344 + do { 345 + struct list_head *entry = list_first_entry_or_null(&gpu_vm->list, head); 346 + 347 + if (!entry) 348 + break; 349 + 350 + list_move_tail(&entry->head, &still_in_list); 351 + list_entry_get_unless_zero(entry); 352 + spin_unlock(&gpu_vm->list_lock); 353 + 354 + process(entry); 355 + 356 + spin_lock(&gpu_vm->list_lock); 357 + list_entry_put(entry); 358 + } while (true); 359 + 360 + list_splice_tail(&still_in_list, &gpu_vm->list); 361 + spin_unlock(&gpu_vm->list_lock); 362 + 363 + Due to the additional locking and atomic operations, drivers that *can* 364 + avoid accessing the gpu_vm's list outside of the dma_resv lock 365 + might want to avoid also this iteration scheme. Particularly, if the 366 + driver anticipates a large number of list items. For lists where the 367 + anticipated number of list items is small, where list iteration doesn't 368 + happen very often or if there is a significant additional cost 369 + associated with each iteration, the atomic operation overhead 370 + associated with this type of iteration is, most likely, negligible. Note that 371 + if this scheme is used, it is necessary to make sure this list 372 + iteration is protected by an outer level lock or semaphore, since list 373 + items are temporarily pulled off the list while iterating, and it is 374 + also worth mentioning that the local list ``still_in_list`` should 375 + also be considered protected by the ``gpu_vm->list_lock``, and it is 376 + thus possible that items can be removed also from the local list 377 + concurrently with list iteration. 378 + 379 + Please refer to the :ref:`DRM GPUVM locking section 380 + <drm_gpuvm_locking>` and its internal 381 + :c:func:`get_next_vm_bo_from_list` function. 382 + 383 + 384 + userptr gpu_vmas 385 + ================ 386 + 387 + A userptr gpu_vma is a gpu_vma that, instead of mapping a buffer object to a 388 + GPU virtual address range, directly maps a CPU mm range of anonymous- 389 + or file page-cache pages. 390 + A very simple approach would be to just pin the pages using 391 + pin_user_pages() at bind time and unpin them at unbind time, but this 392 + creates a Denial-Of-Service vector since a single user-space process 393 + would be able to pin down all of system memory, which is not 394 + desirable. (For special use-cases and assuming proper accounting pinning might 395 + still be a desirable feature, though). What we need to do in the 396 + general case is to obtain a reference to the desired pages, make sure 397 + we are notified using a MMU notifier just before the CPU mm unmaps the 398 + pages, dirty them if they are not mapped read-only to the GPU, and 399 + then drop the reference. 400 + When we are notified by the MMU notifier that CPU mm is about to drop the 401 + pages, we need to stop GPU access to the pages by waiting for VM idle 402 + in the MMU notifier and make sure that before the next time the GPU 403 + tries to access whatever is now present in the CPU mm range, we unmap 404 + the old pages from the GPU page tables and repeat the process of 405 + obtaining new page references. (See the :ref:`notifier example 406 + <Invalidation example>` below). Note that when the core mm decides to 407 + laundry pages, we get such an unmap MMU notification and can mark the 408 + pages dirty again before the next GPU access. We also get similar MMU 409 + notifications for NUMA accounting which the GPU driver doesn't really 410 + need to care about, but so far it has proven difficult to exclude 411 + certain notifications. 412 + 413 + Using a MMU notifier for device DMA (and other methods) is described in 414 + :ref:`the pin_user_pages() documentation <mmu-notifier-registration-case>`. 415 + 416 + Now, the method of obtaining struct page references using 417 + get_user_pages() unfortunately can't be used under a dma_resv lock 418 + since that would violate the locking order of the dma_resv lock vs the 419 + mmap_lock that is grabbed when resolving a CPU pagefault. This means 420 + the gpu_vm's list of userptr gpu_vmas needs to be protected by an 421 + outer lock, which in our example below is the ``gpu_vm->lock``. 422 + 423 + The MMU interval seqlock for a userptr gpu_vma is used in the following 424 + way: 425 + 426 + .. code-block:: C 427 + 428 + // Exclusive locking mode here is strictly needed only if there are 429 + // invalidated userptr gpu_vmas present, to avoid concurrent userptr 430 + // revalidations of the same userptr gpu_vma. 431 + down_write(&gpu_vm->lock); 432 + retry: 433 + 434 + // Note: mmu_interval_read_begin() blocks until there is no 435 + // invalidation notifier running anymore. 436 + seq = mmu_interval_read_begin(&gpu_vma->userptr_interval); 437 + if (seq != gpu_vma->saved_seq) { 438 + obtain_new_page_pointers(&gpu_vma); 439 + dma_resv_lock(&gpu_vm->resv); 440 + add_gpu_vma_to_revalidate_list(&gpu_vma, &gpu_vm); 441 + dma_resv_unlock(&gpu_vm->resv); 442 + gpu_vma->saved_seq = seq; 443 + } 444 + 445 + // The usual revalidation goes here. 446 + 447 + // Final userptr sequence validation may not happen before the 448 + // submission dma_fence is added to the gpu_vm's resv, from the POW 449 + // of the MMU invalidation notifier. Hence the 450 + // userptr_notifier_lock that will make them appear atomic. 451 + 452 + add_dependencies(&gpu_job, &gpu_vm->resv); 453 + down_read(&gpu_vm->userptr_notifier_lock); 454 + if (mmu_interval_read_retry(&gpu_vma->userptr_interval, gpu_vma->saved_seq)) { 455 + up_read(&gpu_vm->userptr_notifier_lock); 456 + goto retry; 457 + } 458 + 459 + job_dma_fence = gpu_submit(&gpu_job)); 460 + 461 + add_dma_fence(job_dma_fence, &gpu_vm->resv); 462 + 463 + for_each_external_obj(gpu_vm, &obj) 464 + add_dma_fence(job_dma_fence, &obj->resv); 465 + 466 + dma_resv_unlock_all_resv_locks(); 467 + up_read(&gpu_vm->userptr_notifier_lock); 468 + up_write(&gpu_vm->lock); 469 + 470 + The code between ``mmu_interval_read_begin()`` and the 471 + ``mmu_interval_read_retry()`` marks the read side critical section of 472 + what we call the ``userptr_seqlock``. In reality, the gpu_vm's userptr 473 + gpu_vma list is looped through, and the check is done for *all* of its 474 + userptr gpu_vmas, although we only show a single one here. 475 + 476 + The userptr gpu_vma MMU invalidation notifier might be called from 477 + reclaim context and, again, to avoid locking order violations, we can't 478 + take any dma_resv lock nor the gpu_vm->lock from within it. 479 + 480 + .. _Invalidation example: 481 + .. code-block:: C 482 + 483 + bool gpu_vma_userptr_invalidate(userptr_interval, cur_seq) 484 + { 485 + // Make sure the exec function either sees the new sequence 486 + // and backs off or we wait for the dma-fence: 487 + 488 + down_write(&gpu_vm->userptr_notifier_lock); 489 + mmu_interval_set_seq(userptr_interval, cur_seq); 490 + up_write(&gpu_vm->userptr_notifier_lock); 491 + 492 + // At this point, the exec function can't succeed in 493 + // submitting a new job, because cur_seq is an invalid 494 + // sequence number and will always cause a retry. When all 495 + // invalidation callbacks, the mmu notifier core will flip 496 + // the sequence number to a valid one. However we need to 497 + // stop gpu access to the old pages here. 498 + 499 + dma_resv_wait_timeout(&gpu_vm->resv, DMA_RESV_USAGE_BOOKKEEP, 500 + false, MAX_SCHEDULE_TIMEOUT); 501 + return true; 502 + } 503 + 504 + When this invalidation notifier returns, the GPU can no longer be 505 + accessing the old pages of the userptr gpu_vma and needs to redo the 506 + page-binding before a new GPU submission can succeed. 507 + 508 + Efficient userptr gpu_vma exec_function iteration 509 + _________________________________________________ 510 + 511 + If the gpu_vm's list of userptr gpu_vmas becomes large, it's 512 + inefficient to iterate through the complete lists of userptrs on each 513 + exec function to check whether each userptr gpu_vma's saved 514 + sequence number is stale. A solution to this is to put all 515 + *invalidated* userptr gpu_vmas on a separate gpu_vm list and 516 + only check the gpu_vmas present on this list on each exec 517 + function. This list will then lend itself very-well to the spinlock 518 + locking scheme that is 519 + :ref:`described in the spinlock iteration section <Spinlock iteration>`, since 520 + in the mmu notifier, where we add the invalidated gpu_vmas to the 521 + list, it's not possible to take any outer locks like the 522 + ``gpu_vm->lock`` or the ``gpu_vm->resv`` lock. Note that the 523 + ``gpu_vm->lock`` still needs to be taken while iterating to ensure the list is 524 + complete, as also mentioned in that section. 525 + 526 + If using an invalidated userptr list like this, the retry check in the 527 + exec function trivially becomes a check for invalidated list empty. 528 + 529 + Locking at bind and unbind time 530 + =============================== 531 + 532 + At bind time, assuming a GEM object backed gpu_vma, each 533 + gpu_vma needs to be associated with a gpu_vm_bo and that 534 + gpu_vm_bo in turn needs to be added to the GEM object's 535 + gpu_vm_bo list, and possibly to the gpu_vm's external object 536 + list. This is referred to as *linking* the gpu_vma, and typically 537 + requires that the ``gpu_vm->lock`` and the ``gem_object->gpuva_lock`` 538 + are held. When unlinking a gpu_vma the same locks should be held, 539 + and that ensures that when iterating over ``gpu_vmas`, either under 540 + the ``gpu_vm->resv`` or the GEM object's dma_resv, that the gpu_vmas 541 + stay alive as long as the lock under which we iterate is not released. For 542 + userptr gpu_vmas it's similarly required that during vma destroy, the 543 + outer ``gpu_vm->lock`` is held, since otherwise when iterating over 544 + the invalidated userptr list as described in the previous section, 545 + there is nothing keeping those userptr gpu_vmas alive. 546 + 547 + Locking for recoverable page-fault page-table updates 548 + ===================================================== 549 + 550 + There are two important things we need to ensure with locking for 551 + recoverable page-faults: 552 + 553 + * At the time we return pages back to the system / allocator for 554 + reuse, there should be no remaining GPU mappings and any GPU TLB 555 + must have been flushed. 556 + * The unmapping and mapping of a gpu_vma must not race. 557 + 558 + Since the unmapping (or zapping) of GPU ptes is typically taking place 559 + where it is hard or even impossible to take any outer level locks we 560 + must either introduce a new lock that is held at both mapping and 561 + unmapping time, or look at the locks we do hold at unmapping time and 562 + make sure that they are held also at mapping time. For userptr 563 + gpu_vmas, the ``userptr_seqlock`` is held in write mode in the mmu 564 + invalidation notifier where zapping happens. Hence, if the 565 + ``userptr_seqlock`` as well as the ``gpu_vm->userptr_notifier_lock`` 566 + is held in read mode during mapping, it will not race with the 567 + zapping. For GEM object backed gpu_vmas, zapping will take place under 568 + the GEM object's dma_resv and ensuring that the dma_resv is held also 569 + when populating the page-tables for any gpu_vma pointing to the GEM 570 + object, will similarly ensure we are race-free. 571 + 572 + If any part of the mapping is performed asynchronously 573 + under a dma-fence with these locks released, the zapping will need to 574 + wait for that dma-fence to signal under the relevant lock before 575 + starting to modify the page-table. 576 + 577 + Since modifying the 578 + page-table structure in a way that frees up page-table memory 579 + might also require outer level locks, the zapping of GPU ptes 580 + typically focuses only on zeroing page-table or page-directory entries 581 + and flushing TLB, whereas freeing of page-table memory is deferred to 582 + unbind or rebind time.
+1 -1
Documentation/gpu/imagination/index.rst
··· 3 3 ======================================= 4 4 5 5 .. kernel-doc:: drivers/gpu/drm/imagination/pvr_drv.c 6 - :doc: PowerVR Graphics Driver 6 + :doc: PowerVR (Series 6 and later) and IMG Graphics Driver 7 7 8 8 Contents 9 9 ========
+1 -4
Documentation/gpu/imagination/uapi.rst
··· 46 46 drm_pvr_dev_query_heap_info 47 47 48 48 .. kernel-doc:: include/uapi/drm/pvr_drm.h 49 - :doc: Flags for DRM_PVR_DEV_QUERY_HEAP_INFO_GET. 50 - 51 - .. kernel-doc:: include/uapi/drm/pvr_drm.h 52 49 :identifiers: drm_pvr_static_data_area_usage 53 50 drm_pvr_static_data_area 54 51 drm_pvr_dev_query_static_data_areas ··· 118 121 :identifiers: drm_pvr_ioctl_destroy_free_list_args 119 122 120 123 CREATE_HWRT_DATASET and DESTROY_HWRT_DATASET 121 - -------------------------------------- 124 + -------------------------------------------- 122 125 .. kernel-doc:: include/uapi/drm/pvr_drm.h 123 126 :doc: PowerVR IOCTL CREATE_HWRT_DATASET and DESTROY_HWRT_DATASET interfaces 124 127
+1
Documentation/gpu/implementation_guidelines.rst
··· 7 7 .. toctree:: 8 8 9 9 drm-vm-bind-async 10 + drm-vm-bind-locking
+5
Documentation/gpu/rfc/xe.rst
··· 123 123 124 124 * O(1) complexity under VM_BIND. 125 125 126 + The document is now included in the drm documentation :doc:`here </gpu/drm-vm-bind-async>`. 127 + 126 128 Some parts of userptr like mmu_notifiers should become GPUVA or DRM helpers when 127 129 the second driver supporting VM_BIND+userptr appears. Details to be defined when 128 130 the time comes. 131 + 132 + The DRM GPUVM helpers do not yet include the userptr parts, but discussions 133 + about implementing them are ongoing. 129 134 130 135 Long running compute: minimal data structure/scaffolding 131 136 --------------------------------------------------------
+26 -4
Documentation/gpu/todo.rst
··· 337 337 338 338 Level: Intermediate 339 339 340 - Remove load/unload callbacks from all non-DRIVER_LEGACY drivers 341 - --------------------------------------------------------------- 340 + Remove load/unload callbacks 341 + ---------------------------- 342 342 343 343 The load/unload callbacks in struct &drm_driver are very much midlayers, plus 344 344 for historical reasons they get the ordering wrong (and we can't fix that) ··· 347 347 - Rework drivers to no longer use the load/unload callbacks, directly coding the 348 348 load/unload sequence into the driver's probe function. 349 349 350 - - Once all non-DRIVER_LEGACY drivers are converted, disallow the load/unload 351 - callbacks for all modern drivers. 350 + - Once all drivers are converted, remove the load/unload callbacks. 352 351 353 352 Contact: Daniel Vetter 354 353 ··· 778 779 multiple panels really should build on top of this new KMS property. 779 780 780 781 Contact: Hans de Goede 782 + 783 + Level: Advanced 784 + 785 + Buffer age or other damage accumulation algorithm for buffer damage 786 + =================================================================== 787 + 788 + Drivers that do per-buffer uploads, need a buffer damage handling (rather than 789 + frame damage like drivers that do per-plane or per-CRTC uploads), but there is 790 + no support to get the buffer age or any other damage accumulation algorithm. 791 + 792 + For this reason, the damage helpers just fallback to a full plane update if the 793 + framebuffer attached to a plane has changed since the last page-flip. Drivers 794 + set &drm_plane_state.ignore_damage_clips to true as indication to 795 + drm_atomic_helper_damage_iter_init() and drm_atomic_helper_damage_iter_next() 796 + helpers that the damage clips should be ignored. 797 + 798 + This should be improved to get damage tracking properly working on drivers that 799 + do per-buffer uploads. 800 + 801 + More information about damage tracking and references to learning materials can 802 + be found in :ref:`damage_tracking_properties`. 803 + 804 + Contact: Javier Martinez Canillas <javierm@redhat.com> 781 805 782 806 Level: Advanced 783 807
+1
MAINTAINERS
··· 10397 10397 M: Donald Robson <donald.robson@imgtec.com> 10398 10398 M: Matt Coster <matt.coster@imgtec.com> 10399 10399 S: Supported 10400 + T: git git://anongit.freedesktop.org/drm/drm-misc 10400 10401 F: Documentation/devicetree/bindings/gpu/img,powervr.yaml 10401 10402 F: Documentation/gpu/imagination/ 10402 10403 F: drivers/gpu/drm/imagination/
+1
drivers/accel/drm_accel.c
··· 11 11 #include <linux/idr.h> 12 12 13 13 #include <drm/drm_accel.h> 14 + #include <drm/drm_auth.h> 14 15 #include <drm/drm_debugfs.h> 15 16 #include <drm/drm_drv.h> 16 17 #include <drm/drm_file.h>
+1 -1
drivers/accel/qaic/mhi_controller.c
··· 469 469 pci_err(qdev->pdev, "Fatal error received from device. Attempting to recover\n"); 470 470 /* this event occurs in non-atomic context */ 471 471 if (reason == MHI_CB_SYS_ERROR) 472 - qaic_dev_reset_clean_local_state(qdev, true); 472 + qaic_dev_reset_clean_local_state(qdev); 473 473 } 474 474 475 475 static int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntrl)
+12 -3
drivers/accel/qaic/qaic.h
··· 31 31 #define to_drm(qddev) (&(qddev)->drm) 32 32 #define to_accel_kdev(qddev) (to_drm(qddev)->accel->kdev) /* Return Linux device of accel node */ 33 33 34 + enum __packed dev_states { 35 + /* Device is offline or will be very soon */ 36 + QAIC_OFFLINE, 37 + /* Device is booting, not clear if it's in a usable state */ 38 + QAIC_BOOT, 39 + /* Device is fully operational */ 40 + QAIC_ONLINE, 41 + }; 42 + 34 43 extern bool datapath_polling; 35 44 36 45 struct qaic_user { ··· 130 121 struct workqueue_struct *cntl_wq; 131 122 /* Synchronizes all the users of device during cleanup */ 132 123 struct srcu_struct dev_lock; 133 - /* true: Device under reset; false: Device not under reset */ 134 - bool in_reset; 124 + /* Track the state of the device during resets */ 125 + enum dev_states dev_state; 135 126 /* true: single MSI is used to operate device */ 136 127 bool single_msi; 137 128 /* ··· 283 274 void release_dbc(struct qaic_device *qdev, u32 dbc_id); 284 275 285 276 void wake_all_cntl(struct qaic_device *qdev); 286 - void qaic_dev_reset_clean_local_state(struct qaic_device *qdev, bool exit_reset); 277 + void qaic_dev_reset_clean_local_state(struct qaic_device *qdev); 287 278 288 279 struct drm_gem_object *qaic_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); 289 280
+3 -2
drivers/accel/qaic/qaic_control.c
··· 1022 1022 int xfer_count = 0; 1023 1023 int retry_count; 1024 1024 1025 - if (qdev->in_reset) { 1025 + /* Allow QAIC_BOOT state since we need to check control protocol version */ 1026 + if (qdev->dev_state == QAIC_OFFLINE) { 1026 1027 mutex_unlock(&qdev->cntl_mutex); 1027 1028 return ERR_PTR(-ENODEV); 1028 1029 } ··· 1307 1306 qdev = usr->qddev->qdev; 1308 1307 1309 1308 qdev_rcu_id = srcu_read_lock(&qdev->dev_lock); 1310 - if (qdev->in_reset) { 1309 + if (qdev->dev_state != QAIC_ONLINE) { 1311 1310 srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id); 1312 1311 srcu_read_unlock(&usr->qddev_lock, usr_rcu_id); 1313 1312 return -ENODEV;
+8 -8
drivers/accel/qaic/qaic_data.c
··· 690 690 691 691 qdev = usr->qddev->qdev; 692 692 qdev_rcu_id = srcu_read_lock(&qdev->dev_lock); 693 - if (qdev->in_reset) { 693 + if (qdev->dev_state != QAIC_ONLINE) { 694 694 ret = -ENODEV; 695 695 goto unlock_dev_srcu; 696 696 } ··· 749 749 750 750 qdev = usr->qddev->qdev; 751 751 qdev_rcu_id = srcu_read_lock(&qdev->dev_lock); 752 - if (qdev->in_reset) { 752 + if (qdev->dev_state != QAIC_ONLINE) { 753 753 ret = -ENODEV; 754 754 goto unlock_dev_srcu; 755 755 } ··· 970 970 971 971 qdev = usr->qddev->qdev; 972 972 qdev_rcu_id = srcu_read_lock(&qdev->dev_lock); 973 - if (qdev->in_reset) { 973 + if (qdev->dev_state != QAIC_ONLINE) { 974 974 ret = -ENODEV; 975 975 goto unlock_dev_srcu; 976 976 } ··· 1341 1341 1342 1342 qdev = usr->qddev->qdev; 1343 1343 qdev_rcu_id = srcu_read_lock(&qdev->dev_lock); 1344 - if (qdev->in_reset) { 1344 + if (qdev->dev_state != QAIC_ONLINE) { 1345 1345 ret = -ENODEV; 1346 1346 goto unlock_dev_srcu; 1347 1347 } ··· 1497 1497 rcu_id = srcu_read_lock(&dbc->ch_lock); 1498 1498 1499 1499 while (1) { 1500 - if (dbc->qdev->in_reset) { 1500 + if (dbc->qdev->dev_state != QAIC_ONLINE) { 1501 1501 srcu_read_unlock(&dbc->ch_lock, rcu_id); 1502 1502 return; 1503 1503 } ··· 1687 1687 1688 1688 qdev = usr->qddev->qdev; 1689 1689 qdev_rcu_id = srcu_read_lock(&qdev->dev_lock); 1690 - if (qdev->in_reset) { 1690 + if (qdev->dev_state != QAIC_ONLINE) { 1691 1691 ret = -ENODEV; 1692 1692 goto unlock_dev_srcu; 1693 1693 } ··· 1756 1756 1757 1757 qdev = usr->qddev->qdev; 1758 1758 qdev_rcu_id = srcu_read_lock(&qdev->dev_lock); 1759 - if (qdev->in_reset) { 1759 + if (qdev->dev_state != QAIC_ONLINE) { 1760 1760 ret = -ENODEV; 1761 1761 goto unlock_dev_srcu; 1762 1762 } ··· 1847 1847 1848 1848 qdev = usr->qddev->qdev; 1849 1849 qdev_rcu_id = srcu_read_lock(&qdev->dev_lock); 1850 - if (qdev->in_reset) { 1850 + if (qdev->dev_state != QAIC_ONLINE) { 1851 1851 ret = -ENODEV; 1852 1852 goto unlock_dev_srcu; 1853 1853 }
+20 -30
drivers/accel/qaic/qaic_drv.c
··· 8 8 #include <linux/idr.h> 9 9 #include <linux/interrupt.h> 10 10 #include <linux/list.h> 11 + #include <linux/kobject.h> 11 12 #include <linux/kref.h> 12 13 #include <linux/mhi.h> 13 14 #include <linux/module.h> ··· 44 43 static bool link_up; 45 44 static DEFINE_IDA(qaic_usrs); 46 45 47 - static int qaic_create_drm_device(struct qaic_device *qdev, s32 partition_id); 48 - static void qaic_destroy_drm_device(struct qaic_device *qdev, s32 partition_id); 49 - 50 46 static void free_usr(struct kref *kref) 51 47 { 52 48 struct qaic_user *usr = container_of(kref, struct qaic_user, ref_count); ··· 62 64 int ret; 63 65 64 66 rcu_id = srcu_read_lock(&qdev->dev_lock); 65 - if (qdev->in_reset) { 67 + if (qdev->dev_state != QAIC_ONLINE) { 66 68 ret = -ENODEV; 67 69 goto dev_unlock; 68 70 } ··· 119 121 if (qddev) { 120 122 qdev = qddev->qdev; 121 123 qdev_rcu_id = srcu_read_lock(&qdev->dev_lock); 122 - if (!qdev->in_reset) { 124 + if (qdev->dev_state == QAIC_ONLINE) { 123 125 qaic_release_usr(qdev, usr); 124 126 for (i = 0; i < qdev->num_dbc; ++i) 125 127 if (qdev->dbc[i].usr && qdev->dbc[i].usr->handle == usr->handle) ··· 181 183 182 184 qddev->partition_id = partition_id; 183 185 184 - /* 185 - * drm_dev_unregister() sets the driver data to NULL and 186 - * drm_dev_register() does not update the driver data. During a SOC 187 - * reset drm dev is unregistered and registered again leaving the 188 - * driver data to NULL. 189 - */ 190 - dev_set_drvdata(to_accel_kdev(qddev), drm->accel); 191 186 ret = drm_dev_register(drm, 0); 192 187 if (ret) 193 188 pci_dbg(qdev->pdev, "drm_dev_register failed %d\n", ret); ··· 194 203 struct drm_device *drm = to_drm(qddev); 195 204 struct qaic_user *usr; 196 205 197 - drm_dev_get(drm); 198 206 drm_dev_unregister(drm); 199 207 qddev->partition_id = 0; 200 208 /* ··· 222 232 mutex_lock(&qddev->users_mutex); 223 233 } 224 234 mutex_unlock(&qddev->users_mutex); 225 - drm_dev_put(drm); 226 235 } 227 236 228 237 static int qaic_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id) ··· 243 254 244 255 qdev = pci_get_drvdata(to_pci_dev(mhi_dev->mhi_cntrl->cntrl_dev)); 245 256 246 - qdev->in_reset = false; 247 - 248 257 dev_set_drvdata(&mhi_dev->dev, qdev); 249 258 qdev->cntl_ch = mhi_dev; 250 259 ··· 252 265 return ret; 253 266 } 254 267 268 + qdev->dev_state = QAIC_BOOT; 255 269 ret = get_cntl_version(qdev, NULL, &major, &minor); 256 270 if (ret || major != CNTL_MAJOR || minor > CNTL_MINOR) { 257 271 pci_err(qdev->pdev, "%s: Control protocol version (%d.%d) not supported. Supported version is (%d.%d). Ret: %d\n", ··· 260 272 ret = -EINVAL; 261 273 goto close_control; 262 274 } 263 - 264 - ret = qaic_create_drm_device(qdev, QAIC_NO_PARTITION); 275 + qdev->dev_state = QAIC_ONLINE; 276 + kobject_uevent(&(to_accel_kdev(qdev->qddev))->kobj, KOBJ_ONLINE); 265 277 266 278 return ret; 267 279 ··· 279 291 { 280 292 int i; 281 293 282 - qdev->in_reset = true; 294 + kobject_uevent(&(to_accel_kdev(qdev->qddev))->kobj, KOBJ_OFFLINE); 295 + qdev->dev_state = QAIC_OFFLINE; 283 296 /* wake up any waiters to avoid waiting for timeouts at sync */ 284 297 wake_all_cntl(qdev); 285 298 for (i = 0; i < qdev->num_dbc; ++i) ··· 288 299 synchronize_srcu(&qdev->dev_lock); 289 300 } 290 301 291 - void qaic_dev_reset_clean_local_state(struct qaic_device *qdev, bool exit_reset) 302 + void qaic_dev_reset_clean_local_state(struct qaic_device *qdev) 292 303 { 293 304 int i; 294 305 295 306 qaic_notify_reset(qdev); 296 307 297 - /* remove drmdevs to prevent new users from coming in */ 298 - qaic_destroy_drm_device(qdev, QAIC_NO_PARTITION); 299 - 300 308 /* start tearing things down */ 301 309 for (i = 0; i < qdev->num_dbc; ++i) 302 310 release_dbc(qdev, i); 303 - 304 - if (exit_reset) 305 - qdev->in_reset = false; 306 311 } 307 312 308 313 static void cleanup_qdev(struct qaic_device *qdev) ··· 321 338 if (!qdev) 322 339 return NULL; 323 340 341 + qdev->dev_state = QAIC_OFFLINE; 324 342 if (id->device == PCI_DEV_AIC100) { 325 343 qdev->num_dbc = 16; 326 344 qdev->dbc = devm_kcalloc(&pdev->dev, qdev->num_dbc, sizeof(*qdev->dbc), GFP_KERNEL); ··· 483 499 goto cleanup_qdev; 484 500 } 485 501 502 + ret = qaic_create_drm_device(qdev, QAIC_NO_PARTITION); 503 + if (ret) 504 + goto cleanup_qdev; 505 + 486 506 qdev->mhi_cntrl = qaic_mhi_register_controller(pdev, qdev->bar_0, mhi_irq, 487 507 qdev->single_msi); 488 508 if (IS_ERR(qdev->mhi_cntrl)) { 489 509 ret = PTR_ERR(qdev->mhi_cntrl); 490 - goto cleanup_qdev; 510 + goto cleanup_drm_dev; 491 511 } 492 512 493 513 return 0; 494 514 515 + cleanup_drm_dev: 516 + qaic_destroy_drm_device(qdev, QAIC_NO_PARTITION); 495 517 cleanup_qdev: 496 518 cleanup_qdev(qdev); 497 519 return ret; ··· 510 520 if (!qdev) 511 521 return; 512 522 513 - qaic_dev_reset_clean_local_state(qdev, false); 523 + qaic_dev_reset_clean_local_state(qdev); 524 + qaic_destroy_drm_device(qdev, QAIC_NO_PARTITION); 514 525 qaic_mhi_free_controller(qdev->mhi_cntrl, link_up); 515 526 cleanup_qdev(qdev); 516 527 } ··· 534 543 535 544 qaic_notify_reset(qdev); 536 545 qaic_mhi_start_reset(qdev->mhi_cntrl); 537 - qaic_dev_reset_clean_local_state(qdev, false); 546 + qaic_dev_reset_clean_local_state(qdev); 538 547 } 539 548 540 549 static void qaic_pci_reset_done(struct pci_dev *pdev) 541 550 { 542 551 struct qaic_device *qdev = pci_get_drvdata(pdev); 543 552 544 - qdev->in_reset = false; 545 553 qaic_mhi_reset_done(qdev->mhi_cntrl); 546 554 } 547 555
+2 -8
drivers/auxdisplay/Kconfig
··· 112 112 depends on X86 113 113 depends on FB 114 114 depends on KS0108 115 - select FB_SYS_FILLRECT 116 - select FB_SYS_COPYAREA 117 - select FB_SYS_IMAGEBLIT 118 - select FB_SYS_FOPS 115 + select FB_SYSMEM_HELPERS 119 116 default n 120 117 help 121 118 If you have a Crystalfontz 128x64 2-color LCD, cfag12864b Series, ··· 167 170 config HT16K33 168 171 tristate "Holtek Ht16K33 LED controller with keyscan" 169 172 depends on FB && I2C && INPUT 170 - select FB_SYS_FOPS 171 - select FB_SYS_FILLRECT 172 - select FB_SYS_COPYAREA 173 - select FB_SYS_IMAGEBLIT 173 + select FB_SYSMEM_HELPERS 174 174 select INPUT_MATRIXKMAP 175 175 select FB_BACKLIGHT 176 176 select NEW_LEDS
+5 -5
drivers/auxdisplay/cfag12864bfb.c
··· 51 51 { 52 52 struct page *pages = virt_to_page(cfag12864b_buffer); 53 53 54 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 55 + 54 56 return vm_map_pages_zero(vma, &pages, 1); 55 57 } 56 58 57 59 static const struct fb_ops cfag12864bfb_ops = { 58 60 .owner = THIS_MODULE, 59 - .fb_read = fb_sys_read, 60 - .fb_write = fb_sys_write, 61 - .fb_fillrect = sys_fillrect, 62 - .fb_copyarea = sys_copyarea, 63 - .fb_imageblit = sys_imageblit, 61 + __FB_DEFAULT_SYSMEM_OPS_RDWR, 62 + __FB_DEFAULT_SYSMEM_OPS_DRAW, 64 63 .fb_mmap = cfag12864bfb_mmap, 65 64 }; 66 65 ··· 71 72 if (!info) 72 73 goto none; 73 74 75 + info->flags = FBINFO_VIRTFB; 74 76 info->screen_buffer = cfag12864b_buffer; 75 77 info->screen_size = CFAG12864B_SIZE; 76 78 info->fbops = &cfag12864bfb_ops;
+5 -5
drivers/auxdisplay/ht16k33.c
··· 351 351 struct ht16k33_priv *priv = info->par; 352 352 struct page *pages = virt_to_page(priv->fbdev.buffer); 353 353 354 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 355 + 354 356 return vm_map_pages_zero(vma, &pages, 1); 355 357 } 356 358 357 359 static const struct fb_ops ht16k33_fb_ops = { 358 360 .owner = THIS_MODULE, 359 - .fb_read = fb_sys_read, 360 - .fb_write = fb_sys_write, 361 + __FB_DEFAULT_SYSMEM_OPS_RDWR, 361 362 .fb_blank = ht16k33_blank, 362 - .fb_fillrect = sys_fillrect, 363 - .fb_copyarea = sys_copyarea, 364 - .fb_imageblit = sys_imageblit, 363 + __FB_DEFAULT_SYSMEM_OPS_DRAW, 365 364 .fb_mmap = ht16k33_mmap, 366 365 }; 367 366 ··· 639 640 640 641 INIT_DELAYED_WORK(&priv->work, ht16k33_fb_update); 641 642 fbdev->info->fbops = &ht16k33_fb_ops; 643 + fbdev->info->flags |= FBINFO_VIRTFB; 642 644 fbdev->info->screen_buffer = fbdev->buffer; 643 645 fbdev->info->screen_size = HT16K33_FB_SIZE; 644 646 fbdev->info->fix = ht16k33_fb_fix;
-6
drivers/char/agp/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 2 agpgart-y := backend.o generic.o isoch.o 3 3 4 - ifeq ($(CONFIG_DRM_LEGACY),y) 5 - agpgart-$(CONFIG_COMPAT) += compat_ioctl.o 6 - agpgart-y += frontend.o 7 - endif 8 - 9 - 10 4 obj-$(CONFIG_AGP) += agpgart.o 11 5 obj-$(CONFIG_AGP_ALI) += ali-agp.o 12 6 obj-$(CONFIG_AGP_ATI) += ati-agp.o
-9
drivers/char/agp/agp.h
··· 185 185 int agp_add_bridge(struct agp_bridge_data *bridge); 186 186 void agp_remove_bridge(struct agp_bridge_data *bridge); 187 187 188 - /* Frontend routines. */ 189 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 190 - int agp_frontend_initialize(void); 191 - void agp_frontend_cleanup(void); 192 - #else 193 - static inline int agp_frontend_initialize(void) { return 0; } 194 - static inline void agp_frontend_cleanup(void) {} 195 - #endif 196 - 197 188 /* Generic routines. */ 198 189 void agp_generic_enable(struct agp_bridge_data *bridge, u32 mode); 199 190 int agp_generic_create_gatt_table(struct agp_bridge_data *bridge);
-11
drivers/char/agp/backend.c
··· 293 293 } 294 294 295 295 if (list_empty(&agp_bridges)) { 296 - error = agp_frontend_initialize(); 297 - if (error) { 298 - dev_info(&bridge->dev->dev, 299 - "agp_frontend_initialize() failed\n"); 300 - goto frontend_err; 301 - } 302 - 303 296 dev_info(&bridge->dev->dev, "AGP aperture is %dM @ 0x%lx\n", 304 297 bridge->driver->fetch_size(), bridge->gart_bus_addr); 305 298 ··· 301 308 list_add(&bridge->list, &agp_bridges); 302 309 return 0; 303 310 304 - frontend_err: 305 - agp_backend_cleanup(bridge); 306 311 err_out: 307 312 module_put(bridge->driver->owner); 308 313 err_put_bridge: ··· 314 323 { 315 324 agp_backend_cleanup(bridge); 316 325 list_del(&bridge->list); 317 - if (list_empty(&agp_bridges)) 318 - agp_frontend_cleanup(); 319 326 module_put(bridge->driver->owner); 320 327 } 321 328 EXPORT_SYMBOL_GPL(agp_remove_bridge);
-291
drivers/char/agp/compat_ioctl.c
··· 1 - /* 2 - * AGPGART driver frontend compatibility ioctls 3 - * Copyright (C) 2004 Silicon Graphics, Inc. 4 - * Copyright (C) 2002-2003 Dave Jones 5 - * Copyright (C) 1999 Jeff Hartmann 6 - * Copyright (C) 1999 Precision Insight, Inc. 7 - * Copyright (C) 1999 Xi Graphics, Inc. 8 - * 9 - * Permission is hereby granted, free of charge, to any person obtaining a 10 - * copy of this software and associated documentation files (the "Software"), 11 - * to deal in the Software without restriction, including without limitation 12 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 - * and/or sell copies of the Software, and to permit persons to whom the 14 - * Software is furnished to do so, subject to the following conditions: 15 - * 16 - * The above copyright notice and this permission notice shall be included 17 - * in all copies or substantial portions of the Software. 18 - * 19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 - * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 23 - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24 - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 25 - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 - * 27 - */ 28 - 29 - #include <linux/kernel.h> 30 - #include <linux/pci.h> 31 - #include <linux/fs.h> 32 - #include <linux/agpgart.h> 33 - #include <linux/slab.h> 34 - #include <linux/uaccess.h> 35 - #include "agp.h" 36 - #include "compat_ioctl.h" 37 - 38 - static int compat_agpioc_info_wrap(struct agp_file_private *priv, void __user *arg) 39 - { 40 - struct agp_info32 userinfo; 41 - struct agp_kern_info kerninfo; 42 - 43 - agp_copy_info(agp_bridge, &kerninfo); 44 - 45 - userinfo.version.major = kerninfo.version.major; 46 - userinfo.version.minor = kerninfo.version.minor; 47 - userinfo.bridge_id = kerninfo.device->vendor | 48 - (kerninfo.device->device << 16); 49 - userinfo.agp_mode = kerninfo.mode; 50 - userinfo.aper_base = (compat_long_t)kerninfo.aper_base; 51 - userinfo.aper_size = kerninfo.aper_size; 52 - userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory; 53 - userinfo.pg_used = kerninfo.current_memory; 54 - 55 - if (copy_to_user(arg, &userinfo, sizeof(userinfo))) 56 - return -EFAULT; 57 - 58 - return 0; 59 - } 60 - 61 - static int compat_agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg) 62 - { 63 - struct agp_region32 ureserve; 64 - struct agp_region kreserve; 65 - struct agp_client *client; 66 - struct agp_file_private *client_priv; 67 - 68 - DBG(""); 69 - if (copy_from_user(&ureserve, arg, sizeof(ureserve))) 70 - return -EFAULT; 71 - 72 - if ((unsigned) ureserve.seg_count >= ~0U/sizeof(struct agp_segment32)) 73 - return -EFAULT; 74 - 75 - kreserve.pid = ureserve.pid; 76 - kreserve.seg_count = ureserve.seg_count; 77 - 78 - client = agp_find_client_by_pid(kreserve.pid); 79 - 80 - if (kreserve.seg_count == 0) { 81 - /* remove a client */ 82 - client_priv = agp_find_private(kreserve.pid); 83 - 84 - if (client_priv != NULL) { 85 - set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); 86 - set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); 87 - } 88 - if (client == NULL) { 89 - /* client is already removed */ 90 - return 0; 91 - } 92 - return agp_remove_client(kreserve.pid); 93 - } else { 94 - struct agp_segment32 *usegment; 95 - struct agp_segment *ksegment; 96 - int seg; 97 - 98 - if (ureserve.seg_count >= 16384) 99 - return -EINVAL; 100 - 101 - usegment = kmalloc_array(ureserve.seg_count, 102 - sizeof(*usegment), 103 - GFP_KERNEL); 104 - if (!usegment) 105 - return -ENOMEM; 106 - 107 - ksegment = kmalloc_array(kreserve.seg_count, 108 - sizeof(*ksegment), 109 - GFP_KERNEL); 110 - if (!ksegment) { 111 - kfree(usegment); 112 - return -ENOMEM; 113 - } 114 - 115 - if (copy_from_user(usegment, (void __user *) ureserve.seg_list, 116 - sizeof(*usegment) * ureserve.seg_count)) { 117 - kfree(usegment); 118 - kfree(ksegment); 119 - return -EFAULT; 120 - } 121 - 122 - for (seg = 0; seg < ureserve.seg_count; seg++) { 123 - ksegment[seg].pg_start = usegment[seg].pg_start; 124 - ksegment[seg].pg_count = usegment[seg].pg_count; 125 - ksegment[seg].prot = usegment[seg].prot; 126 - } 127 - 128 - kfree(usegment); 129 - kreserve.seg_list = ksegment; 130 - 131 - if (client == NULL) { 132 - /* Create the client and add the segment */ 133 - client = agp_create_client(kreserve.pid); 134 - 135 - if (client == NULL) { 136 - kfree(ksegment); 137 - return -ENOMEM; 138 - } 139 - client_priv = agp_find_private(kreserve.pid); 140 - 141 - if (client_priv != NULL) { 142 - set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); 143 - set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); 144 - } 145 - } 146 - return agp_create_segment(client, &kreserve); 147 - } 148 - /* Will never really happen */ 149 - return -EINVAL; 150 - } 151 - 152 - static int compat_agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg) 153 - { 154 - struct agp_memory *memory; 155 - struct agp_allocate32 alloc; 156 - 157 - DBG(""); 158 - if (copy_from_user(&alloc, arg, sizeof(alloc))) 159 - return -EFAULT; 160 - 161 - memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type); 162 - 163 - if (memory == NULL) 164 - return -ENOMEM; 165 - 166 - alloc.key = memory->key; 167 - alloc.physical = memory->physical; 168 - 169 - if (copy_to_user(arg, &alloc, sizeof(alloc))) { 170 - agp_free_memory_wrap(memory); 171 - return -EFAULT; 172 - } 173 - return 0; 174 - } 175 - 176 - static int compat_agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg) 177 - { 178 - struct agp_bind32 bind_info; 179 - struct agp_memory *memory; 180 - 181 - DBG(""); 182 - if (copy_from_user(&bind_info, arg, sizeof(bind_info))) 183 - return -EFAULT; 184 - 185 - memory = agp_find_mem_by_key(bind_info.key); 186 - 187 - if (memory == NULL) 188 - return -EINVAL; 189 - 190 - return agp_bind_memory(memory, bind_info.pg_start); 191 - } 192 - 193 - static int compat_agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg) 194 - { 195 - struct agp_memory *memory; 196 - struct agp_unbind32 unbind; 197 - 198 - DBG(""); 199 - if (copy_from_user(&unbind, arg, sizeof(unbind))) 200 - return -EFAULT; 201 - 202 - memory = agp_find_mem_by_key(unbind.key); 203 - 204 - if (memory == NULL) 205 - return -EINVAL; 206 - 207 - return agp_unbind_memory(memory); 208 - } 209 - 210 - long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 211 - { 212 - struct agp_file_private *curr_priv = file->private_data; 213 - int ret_val = -ENOTTY; 214 - 215 - mutex_lock(&(agp_fe.agp_mutex)); 216 - 217 - if ((agp_fe.current_controller == NULL) && 218 - (cmd != AGPIOC_ACQUIRE32)) { 219 - ret_val = -EINVAL; 220 - goto ioctl_out; 221 - } 222 - if ((agp_fe.backend_acquired != true) && 223 - (cmd != AGPIOC_ACQUIRE32)) { 224 - ret_val = -EBUSY; 225 - goto ioctl_out; 226 - } 227 - if (cmd != AGPIOC_ACQUIRE32) { 228 - if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) { 229 - ret_val = -EPERM; 230 - goto ioctl_out; 231 - } 232 - /* Use the original pid of the controller, 233 - * in case it's threaded */ 234 - 235 - if (agp_fe.current_controller->pid != curr_priv->my_pid) { 236 - ret_val = -EBUSY; 237 - goto ioctl_out; 238 - } 239 - } 240 - 241 - switch (cmd) { 242 - case AGPIOC_INFO32: 243 - ret_val = compat_agpioc_info_wrap(curr_priv, (void __user *) arg); 244 - break; 245 - 246 - case AGPIOC_ACQUIRE32: 247 - ret_val = agpioc_acquire_wrap(curr_priv); 248 - break; 249 - 250 - case AGPIOC_RELEASE32: 251 - ret_val = agpioc_release_wrap(curr_priv); 252 - break; 253 - 254 - case AGPIOC_SETUP32: 255 - ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg); 256 - break; 257 - 258 - case AGPIOC_RESERVE32: 259 - ret_val = compat_agpioc_reserve_wrap(curr_priv, (void __user *) arg); 260 - break; 261 - 262 - case AGPIOC_PROTECT32: 263 - ret_val = agpioc_protect_wrap(curr_priv); 264 - break; 265 - 266 - case AGPIOC_ALLOCATE32: 267 - ret_val = compat_agpioc_allocate_wrap(curr_priv, (void __user *) arg); 268 - break; 269 - 270 - case AGPIOC_DEALLOCATE32: 271 - ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg); 272 - break; 273 - 274 - case AGPIOC_BIND32: 275 - ret_val = compat_agpioc_bind_wrap(curr_priv, (void __user *) arg); 276 - break; 277 - 278 - case AGPIOC_UNBIND32: 279 - ret_val = compat_agpioc_unbind_wrap(curr_priv, (void __user *) arg); 280 - break; 281 - 282 - case AGPIOC_CHIPSET_FLUSH32: 283 - break; 284 - } 285 - 286 - ioctl_out: 287 - DBG("ioctl returns %d\n", ret_val); 288 - mutex_unlock(&(agp_fe.agp_mutex)); 289 - return ret_val; 290 - } 291 -
-106
drivers/char/agp/compat_ioctl.h
··· 1 - /* 2 - * Copyright (C) 1999 Jeff Hartmann 3 - * Copyright (C) 1999 Precision Insight, Inc. 4 - * Copyright (C) 1999 Xi Graphics, Inc. 5 - * 6 - * Permission is hereby granted, free of charge, to any person obtaining a 7 - * copy of this software and associated documentation files (the "Software"), 8 - * to deal in the Software without restriction, including without limitation 9 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 - * and/or sell copies of the Software, and to permit persons to whom the 11 - * Software is furnished to do so, subject to the following conditions: 12 - * 13 - * The above copyright notice and this permission notice shall be included 14 - * in all copies or substantial portions of the Software. 15 - * 16 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 - * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 20 - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 22 - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 - * 24 - */ 25 - 26 - #ifndef _AGP_COMPAT_IOCTL_H 27 - #define _AGP_COMPAT_IOCTL_H 28 - 29 - #include <linux/compat.h> 30 - #include <linux/agpgart.h> 31 - 32 - #define AGPIOC_INFO32 _IOR (AGPIOC_BASE, 0, compat_uptr_t) 33 - #define AGPIOC_ACQUIRE32 _IO (AGPIOC_BASE, 1) 34 - #define AGPIOC_RELEASE32 _IO (AGPIOC_BASE, 2) 35 - #define AGPIOC_SETUP32 _IOW (AGPIOC_BASE, 3, compat_uptr_t) 36 - #define AGPIOC_RESERVE32 _IOW (AGPIOC_BASE, 4, compat_uptr_t) 37 - #define AGPIOC_PROTECT32 _IOW (AGPIOC_BASE, 5, compat_uptr_t) 38 - #define AGPIOC_ALLOCATE32 _IOWR(AGPIOC_BASE, 6, compat_uptr_t) 39 - #define AGPIOC_DEALLOCATE32 _IOW (AGPIOC_BASE, 7, compat_int_t) 40 - #define AGPIOC_BIND32 _IOW (AGPIOC_BASE, 8, compat_uptr_t) 41 - #define AGPIOC_UNBIND32 _IOW (AGPIOC_BASE, 9, compat_uptr_t) 42 - #define AGPIOC_CHIPSET_FLUSH32 _IO (AGPIOC_BASE, 10) 43 - 44 - struct agp_info32 { 45 - struct agp_version version; /* version of the driver */ 46 - u32 bridge_id; /* bridge vendor/device */ 47 - u32 agp_mode; /* mode info of bridge */ 48 - compat_long_t aper_base; /* base of aperture */ 49 - compat_size_t aper_size; /* size of aperture */ 50 - compat_size_t pg_total; /* max pages (swap + system) */ 51 - compat_size_t pg_system; /* max pages (system) */ 52 - compat_size_t pg_used; /* current pages used */ 53 - }; 54 - 55 - /* 56 - * The "prot" down below needs still a "sleep" flag somehow ... 57 - */ 58 - struct agp_segment32 { 59 - compat_off_t pg_start; /* starting page to populate */ 60 - compat_size_t pg_count; /* number of pages */ 61 - compat_int_t prot; /* prot flags for mmap */ 62 - }; 63 - 64 - struct agp_region32 { 65 - compat_pid_t pid; /* pid of process */ 66 - compat_size_t seg_count; /* number of segments */ 67 - struct agp_segment32 *seg_list; 68 - }; 69 - 70 - struct agp_allocate32 { 71 - compat_int_t key; /* tag of allocation */ 72 - compat_size_t pg_count; /* number of pages */ 73 - u32 type; /* 0 == normal, other devspec */ 74 - u32 physical; /* device specific (some devices 75 - * need a phys address of the 76 - * actual page behind the gatt 77 - * table) */ 78 - }; 79 - 80 - struct agp_bind32 { 81 - compat_int_t key; /* tag of allocation */ 82 - compat_off_t pg_start; /* starting page to populate */ 83 - }; 84 - 85 - struct agp_unbind32 { 86 - compat_int_t key; /* tag of allocation */ 87 - u32 priority; /* priority for paging out */ 88 - }; 89 - 90 - extern struct agp_front_data agp_fe; 91 - 92 - int agpioc_acquire_wrap(struct agp_file_private *priv); 93 - int agpioc_release_wrap(struct agp_file_private *priv); 94 - int agpioc_protect_wrap(struct agp_file_private *priv); 95 - int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg); 96 - int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg); 97 - struct agp_file_private *agp_find_private(pid_t pid); 98 - struct agp_client *agp_create_client(pid_t id); 99 - int agp_remove_client(pid_t id); 100 - int agp_create_segment(struct agp_client *client, struct agp_region *region); 101 - void agp_free_memory_wrap(struct agp_memory *memory); 102 - struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type); 103 - struct agp_memory *agp_find_mem_by_key(int key); 104 - struct agp_client *agp_find_client_by_pid(pid_t id); 105 - 106 - #endif /* _AGP_COMPAT_H */
-1068
drivers/char/agp/frontend.c
··· 1 - /* 2 - * AGPGART driver frontend 3 - * Copyright (C) 2004 Silicon Graphics, Inc. 4 - * Copyright (C) 2002-2003 Dave Jones 5 - * Copyright (C) 1999 Jeff Hartmann 6 - * Copyright (C) 1999 Precision Insight, Inc. 7 - * Copyright (C) 1999 Xi Graphics, Inc. 8 - * 9 - * Permission is hereby granted, free of charge, to any person obtaining a 10 - * copy of this software and associated documentation files (the "Software"), 11 - * to deal in the Software without restriction, including without limitation 12 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 - * and/or sell copies of the Software, and to permit persons to whom the 14 - * Software is furnished to do so, subject to the following conditions: 15 - * 16 - * The above copyright notice and this permission notice shall be included 17 - * in all copies or substantial portions of the Software. 18 - * 19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 - * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 23 - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 24 - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 25 - * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 - * 27 - */ 28 - 29 - #include <linux/types.h> 30 - #include <linux/kernel.h> 31 - #include <linux/module.h> 32 - #include <linux/mman.h> 33 - #include <linux/pci.h> 34 - #include <linux/miscdevice.h> 35 - #include <linux/agp_backend.h> 36 - #include <linux/agpgart.h> 37 - #include <linux/slab.h> 38 - #include <linux/mm.h> 39 - #include <linux/fs.h> 40 - #include <linux/sched.h> 41 - #include <linux/uaccess.h> 42 - 43 - #include "agp.h" 44 - #include "compat_ioctl.h" 45 - 46 - struct agp_front_data agp_fe; 47 - 48 - struct agp_memory *agp_find_mem_by_key(int key) 49 - { 50 - struct agp_memory *curr; 51 - 52 - if (agp_fe.current_controller == NULL) 53 - return NULL; 54 - 55 - curr = agp_fe.current_controller->pool; 56 - 57 - while (curr != NULL) { 58 - if (curr->key == key) 59 - break; 60 - curr = curr->next; 61 - } 62 - 63 - DBG("key=%d -> mem=%p", key, curr); 64 - return curr; 65 - } 66 - 67 - static void agp_remove_from_pool(struct agp_memory *temp) 68 - { 69 - struct agp_memory *prev; 70 - struct agp_memory *next; 71 - 72 - /* Check to see if this is even in the memory pool */ 73 - 74 - DBG("mem=%p", temp); 75 - if (agp_find_mem_by_key(temp->key) != NULL) { 76 - next = temp->next; 77 - prev = temp->prev; 78 - 79 - if (prev != NULL) { 80 - prev->next = next; 81 - if (next != NULL) 82 - next->prev = prev; 83 - 84 - } else { 85 - /* This is the first item on the list */ 86 - if (next != NULL) 87 - next->prev = NULL; 88 - 89 - agp_fe.current_controller->pool = next; 90 - } 91 - } 92 - } 93 - 94 - /* 95 - * Routines for managing each client's segment list - 96 - * These routines handle adding and removing segments 97 - * to each auth'ed client. 98 - */ 99 - 100 - static struct 101 - agp_segment_priv *agp_find_seg_in_client(const struct agp_client *client, 102 - unsigned long offset, 103 - int size, pgprot_t page_prot) 104 - { 105 - struct agp_segment_priv *seg; 106 - int i; 107 - off_t pg_start; 108 - size_t pg_count; 109 - 110 - pg_start = offset / 4096; 111 - pg_count = size / 4096; 112 - seg = *(client->segments); 113 - 114 - for (i = 0; i < client->num_segments; i++) { 115 - if ((seg[i].pg_start == pg_start) && 116 - (seg[i].pg_count == pg_count) && 117 - (pgprot_val(seg[i].prot) == pgprot_val(page_prot))) { 118 - return seg + i; 119 - } 120 - } 121 - 122 - return NULL; 123 - } 124 - 125 - static void agp_remove_seg_from_client(struct agp_client *client) 126 - { 127 - DBG("client=%p", client); 128 - 129 - if (client->segments != NULL) { 130 - if (*(client->segments) != NULL) { 131 - DBG("Freeing %p from client %p", *(client->segments), client); 132 - kfree(*(client->segments)); 133 - } 134 - DBG("Freeing %p from client %p", client->segments, client); 135 - kfree(client->segments); 136 - client->segments = NULL; 137 - } 138 - } 139 - 140 - static void agp_add_seg_to_client(struct agp_client *client, 141 - struct agp_segment_priv ** seg, int num_segments) 142 - { 143 - struct agp_segment_priv **prev_seg; 144 - 145 - prev_seg = client->segments; 146 - 147 - if (prev_seg != NULL) 148 - agp_remove_seg_from_client(client); 149 - 150 - DBG("Adding seg %p (%d segments) to client %p", seg, num_segments, client); 151 - client->num_segments = num_segments; 152 - client->segments = seg; 153 - } 154 - 155 - static pgprot_t agp_convert_mmap_flags(int prot) 156 - { 157 - unsigned long prot_bits; 158 - 159 - prot_bits = calc_vm_prot_bits(prot, 0) | VM_SHARED; 160 - return vm_get_page_prot(prot_bits); 161 - } 162 - 163 - int agp_create_segment(struct agp_client *client, struct agp_region *region) 164 - { 165 - struct agp_segment_priv **ret_seg; 166 - struct agp_segment_priv *seg; 167 - struct agp_segment *user_seg; 168 - size_t i; 169 - 170 - seg = kzalloc((sizeof(struct agp_segment_priv) * region->seg_count), GFP_KERNEL); 171 - if (seg == NULL) { 172 - kfree(region->seg_list); 173 - region->seg_list = NULL; 174 - return -ENOMEM; 175 - } 176 - user_seg = region->seg_list; 177 - 178 - for (i = 0; i < region->seg_count; i++) { 179 - seg[i].pg_start = user_seg[i].pg_start; 180 - seg[i].pg_count = user_seg[i].pg_count; 181 - seg[i].prot = agp_convert_mmap_flags(user_seg[i].prot); 182 - } 183 - kfree(region->seg_list); 184 - region->seg_list = NULL; 185 - 186 - ret_seg = kmalloc(sizeof(void *), GFP_KERNEL); 187 - if (ret_seg == NULL) { 188 - kfree(seg); 189 - return -ENOMEM; 190 - } 191 - *ret_seg = seg; 192 - agp_add_seg_to_client(client, ret_seg, region->seg_count); 193 - return 0; 194 - } 195 - 196 - /* End - Routines for managing each client's segment list */ 197 - 198 - /* This function must only be called when current_controller != NULL */ 199 - static void agp_insert_into_pool(struct agp_memory * temp) 200 - { 201 - struct agp_memory *prev; 202 - 203 - prev = agp_fe.current_controller->pool; 204 - 205 - if (prev != NULL) { 206 - prev->prev = temp; 207 - temp->next = prev; 208 - } 209 - agp_fe.current_controller->pool = temp; 210 - } 211 - 212 - 213 - /* File private list routines */ 214 - 215 - struct agp_file_private *agp_find_private(pid_t pid) 216 - { 217 - struct agp_file_private *curr; 218 - 219 - curr = agp_fe.file_priv_list; 220 - 221 - while (curr != NULL) { 222 - if (curr->my_pid == pid) 223 - return curr; 224 - curr = curr->next; 225 - } 226 - 227 - return NULL; 228 - } 229 - 230 - static void agp_insert_file_private(struct agp_file_private * priv) 231 - { 232 - struct agp_file_private *prev; 233 - 234 - prev = agp_fe.file_priv_list; 235 - 236 - if (prev != NULL) 237 - prev->prev = priv; 238 - priv->next = prev; 239 - agp_fe.file_priv_list = priv; 240 - } 241 - 242 - static void agp_remove_file_private(struct agp_file_private * priv) 243 - { 244 - struct agp_file_private *next; 245 - struct agp_file_private *prev; 246 - 247 - next = priv->next; 248 - prev = priv->prev; 249 - 250 - if (prev != NULL) { 251 - prev->next = next; 252 - 253 - if (next != NULL) 254 - next->prev = prev; 255 - 256 - } else { 257 - if (next != NULL) 258 - next->prev = NULL; 259 - 260 - agp_fe.file_priv_list = next; 261 - } 262 - } 263 - 264 - /* End - File flag list routines */ 265 - 266 - /* 267 - * Wrappers for agp_free_memory & agp_allocate_memory 268 - * These make sure that internal lists are kept updated. 269 - */ 270 - void agp_free_memory_wrap(struct agp_memory *memory) 271 - { 272 - agp_remove_from_pool(memory); 273 - agp_free_memory(memory); 274 - } 275 - 276 - struct agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type) 277 - { 278 - struct agp_memory *memory; 279 - 280 - memory = agp_allocate_memory(agp_bridge, pg_count, type); 281 - if (memory == NULL) 282 - return NULL; 283 - 284 - agp_insert_into_pool(memory); 285 - return memory; 286 - } 287 - 288 - /* Routines for managing the list of controllers - 289 - * These routines manage the current controller, and the list of 290 - * controllers 291 - */ 292 - 293 - static struct agp_controller *agp_find_controller_by_pid(pid_t id) 294 - { 295 - struct agp_controller *controller; 296 - 297 - controller = agp_fe.controllers; 298 - 299 - while (controller != NULL) { 300 - if (controller->pid == id) 301 - return controller; 302 - controller = controller->next; 303 - } 304 - 305 - return NULL; 306 - } 307 - 308 - static struct agp_controller *agp_create_controller(pid_t id) 309 - { 310 - struct agp_controller *controller; 311 - 312 - controller = kzalloc(sizeof(struct agp_controller), GFP_KERNEL); 313 - if (controller == NULL) 314 - return NULL; 315 - 316 - controller->pid = id; 317 - return controller; 318 - } 319 - 320 - static int agp_insert_controller(struct agp_controller *controller) 321 - { 322 - struct agp_controller *prev_controller; 323 - 324 - prev_controller = agp_fe.controllers; 325 - controller->next = prev_controller; 326 - 327 - if (prev_controller != NULL) 328 - prev_controller->prev = controller; 329 - 330 - agp_fe.controllers = controller; 331 - 332 - return 0; 333 - } 334 - 335 - static void agp_remove_all_clients(struct agp_controller *controller) 336 - { 337 - struct agp_client *client; 338 - struct agp_client *temp; 339 - 340 - client = controller->clients; 341 - 342 - while (client) { 343 - struct agp_file_private *priv; 344 - 345 - temp = client; 346 - agp_remove_seg_from_client(temp); 347 - priv = agp_find_private(temp->pid); 348 - 349 - if (priv != NULL) { 350 - clear_bit(AGP_FF_IS_VALID, &priv->access_flags); 351 - clear_bit(AGP_FF_IS_CLIENT, &priv->access_flags); 352 - } 353 - client = client->next; 354 - kfree(temp); 355 - } 356 - } 357 - 358 - static void agp_remove_all_memory(struct agp_controller *controller) 359 - { 360 - struct agp_memory *memory; 361 - struct agp_memory *temp; 362 - 363 - memory = controller->pool; 364 - 365 - while (memory) { 366 - temp = memory; 367 - memory = memory->next; 368 - agp_free_memory_wrap(temp); 369 - } 370 - } 371 - 372 - static int agp_remove_controller(struct agp_controller *controller) 373 - { 374 - struct agp_controller *prev_controller; 375 - struct agp_controller *next_controller; 376 - 377 - prev_controller = controller->prev; 378 - next_controller = controller->next; 379 - 380 - if (prev_controller != NULL) { 381 - prev_controller->next = next_controller; 382 - if (next_controller != NULL) 383 - next_controller->prev = prev_controller; 384 - 385 - } else { 386 - if (next_controller != NULL) 387 - next_controller->prev = NULL; 388 - 389 - agp_fe.controllers = next_controller; 390 - } 391 - 392 - agp_remove_all_memory(controller); 393 - agp_remove_all_clients(controller); 394 - 395 - if (agp_fe.current_controller == controller) { 396 - agp_fe.current_controller = NULL; 397 - agp_fe.backend_acquired = false; 398 - agp_backend_release(agp_bridge); 399 - } 400 - kfree(controller); 401 - return 0; 402 - } 403 - 404 - static void agp_controller_make_current(struct agp_controller *controller) 405 - { 406 - struct agp_client *clients; 407 - 408 - clients = controller->clients; 409 - 410 - while (clients != NULL) { 411 - struct agp_file_private *priv; 412 - 413 - priv = agp_find_private(clients->pid); 414 - 415 - if (priv != NULL) { 416 - set_bit(AGP_FF_IS_VALID, &priv->access_flags); 417 - set_bit(AGP_FF_IS_CLIENT, &priv->access_flags); 418 - } 419 - clients = clients->next; 420 - } 421 - 422 - agp_fe.current_controller = controller; 423 - } 424 - 425 - static void agp_controller_release_current(struct agp_controller *controller, 426 - struct agp_file_private *controller_priv) 427 - { 428 - struct agp_client *clients; 429 - 430 - clear_bit(AGP_FF_IS_VALID, &controller_priv->access_flags); 431 - clients = controller->clients; 432 - 433 - while (clients != NULL) { 434 - struct agp_file_private *priv; 435 - 436 - priv = agp_find_private(clients->pid); 437 - 438 - if (priv != NULL) 439 - clear_bit(AGP_FF_IS_VALID, &priv->access_flags); 440 - 441 - clients = clients->next; 442 - } 443 - 444 - agp_fe.current_controller = NULL; 445 - agp_fe.used_by_controller = false; 446 - agp_backend_release(agp_bridge); 447 - } 448 - 449 - /* 450 - * Routines for managing client lists - 451 - * These routines are for managing the list of auth'ed clients. 452 - */ 453 - 454 - static struct agp_client 455 - *agp_find_client_in_controller(struct agp_controller *controller, pid_t id) 456 - { 457 - struct agp_client *client; 458 - 459 - if (controller == NULL) 460 - return NULL; 461 - 462 - client = controller->clients; 463 - 464 - while (client != NULL) { 465 - if (client->pid == id) 466 - return client; 467 - client = client->next; 468 - } 469 - 470 - return NULL; 471 - } 472 - 473 - static struct agp_controller *agp_find_controller_for_client(pid_t id) 474 - { 475 - struct agp_controller *controller; 476 - 477 - controller = agp_fe.controllers; 478 - 479 - while (controller != NULL) { 480 - if ((agp_find_client_in_controller(controller, id)) != NULL) 481 - return controller; 482 - controller = controller->next; 483 - } 484 - 485 - return NULL; 486 - } 487 - 488 - struct agp_client *agp_find_client_by_pid(pid_t id) 489 - { 490 - struct agp_client *temp; 491 - 492 - if (agp_fe.current_controller == NULL) 493 - return NULL; 494 - 495 - temp = agp_find_client_in_controller(agp_fe.current_controller, id); 496 - return temp; 497 - } 498 - 499 - static void agp_insert_client(struct agp_client *client) 500 - { 501 - struct agp_client *prev_client; 502 - 503 - prev_client = agp_fe.current_controller->clients; 504 - client->next = prev_client; 505 - 506 - if (prev_client != NULL) 507 - prev_client->prev = client; 508 - 509 - agp_fe.current_controller->clients = client; 510 - agp_fe.current_controller->num_clients++; 511 - } 512 - 513 - struct agp_client *agp_create_client(pid_t id) 514 - { 515 - struct agp_client *new_client; 516 - 517 - new_client = kzalloc(sizeof(struct agp_client), GFP_KERNEL); 518 - if (new_client == NULL) 519 - return NULL; 520 - 521 - new_client->pid = id; 522 - agp_insert_client(new_client); 523 - return new_client; 524 - } 525 - 526 - int agp_remove_client(pid_t id) 527 - { 528 - struct agp_client *client; 529 - struct agp_client *prev_client; 530 - struct agp_client *next_client; 531 - struct agp_controller *controller; 532 - 533 - controller = agp_find_controller_for_client(id); 534 - if (controller == NULL) 535 - return -EINVAL; 536 - 537 - client = agp_find_client_in_controller(controller, id); 538 - if (client == NULL) 539 - return -EINVAL; 540 - 541 - prev_client = client->prev; 542 - next_client = client->next; 543 - 544 - if (prev_client != NULL) { 545 - prev_client->next = next_client; 546 - if (next_client != NULL) 547 - next_client->prev = prev_client; 548 - 549 - } else { 550 - if (next_client != NULL) 551 - next_client->prev = NULL; 552 - controller->clients = next_client; 553 - } 554 - 555 - controller->num_clients--; 556 - agp_remove_seg_from_client(client); 557 - kfree(client); 558 - return 0; 559 - } 560 - 561 - /* End - Routines for managing client lists */ 562 - 563 - /* File Operations */ 564 - 565 - static int agp_mmap(struct file *file, struct vm_area_struct *vma) 566 - { 567 - unsigned int size, current_size; 568 - unsigned long offset; 569 - struct agp_client *client; 570 - struct agp_file_private *priv = file->private_data; 571 - struct agp_kern_info kerninfo; 572 - 573 - mutex_lock(&(agp_fe.agp_mutex)); 574 - 575 - if (agp_fe.backend_acquired != true) 576 - goto out_eperm; 577 - 578 - if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags))) 579 - goto out_eperm; 580 - 581 - agp_copy_info(agp_bridge, &kerninfo); 582 - size = vma->vm_end - vma->vm_start; 583 - current_size = kerninfo.aper_size; 584 - current_size = current_size * 0x100000; 585 - offset = vma->vm_pgoff << PAGE_SHIFT; 586 - DBG("%lx:%lx", offset, offset+size); 587 - 588 - if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) { 589 - if ((size + offset) > current_size) 590 - goto out_inval; 591 - 592 - client = agp_find_client_by_pid(current->pid); 593 - 594 - if (client == NULL) 595 - goto out_eperm; 596 - 597 - if (!agp_find_seg_in_client(client, offset, size, vma->vm_page_prot)) 598 - goto out_inval; 599 - 600 - DBG("client vm_ops=%p", kerninfo.vm_ops); 601 - if (kerninfo.vm_ops) { 602 - vma->vm_ops = kerninfo.vm_ops; 603 - } else if (io_remap_pfn_range(vma, vma->vm_start, 604 - (kerninfo.aper_base + offset) >> PAGE_SHIFT, 605 - size, 606 - pgprot_writecombine(vma->vm_page_prot))) { 607 - goto out_again; 608 - } 609 - mutex_unlock(&(agp_fe.agp_mutex)); 610 - return 0; 611 - } 612 - 613 - if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) { 614 - if (size != current_size) 615 - goto out_inval; 616 - 617 - DBG("controller vm_ops=%p", kerninfo.vm_ops); 618 - if (kerninfo.vm_ops) { 619 - vma->vm_ops = kerninfo.vm_ops; 620 - } else if (io_remap_pfn_range(vma, vma->vm_start, 621 - kerninfo.aper_base >> PAGE_SHIFT, 622 - size, 623 - pgprot_writecombine(vma->vm_page_prot))) { 624 - goto out_again; 625 - } 626 - mutex_unlock(&(agp_fe.agp_mutex)); 627 - return 0; 628 - } 629 - 630 - out_eperm: 631 - mutex_unlock(&(agp_fe.agp_mutex)); 632 - return -EPERM; 633 - 634 - out_inval: 635 - mutex_unlock(&(agp_fe.agp_mutex)); 636 - return -EINVAL; 637 - 638 - out_again: 639 - mutex_unlock(&(agp_fe.agp_mutex)); 640 - return -EAGAIN; 641 - } 642 - 643 - static int agp_release(struct inode *inode, struct file *file) 644 - { 645 - struct agp_file_private *priv = file->private_data; 646 - 647 - mutex_lock(&(agp_fe.agp_mutex)); 648 - 649 - DBG("priv=%p", priv); 650 - 651 - if (test_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags)) { 652 - struct agp_controller *controller; 653 - 654 - controller = agp_find_controller_by_pid(priv->my_pid); 655 - 656 - if (controller != NULL) { 657 - if (controller == agp_fe.current_controller) 658 - agp_controller_release_current(controller, priv); 659 - agp_remove_controller(controller); 660 - controller = NULL; 661 - } 662 - } 663 - 664 - if (test_bit(AGP_FF_IS_CLIENT, &priv->access_flags)) 665 - agp_remove_client(priv->my_pid); 666 - 667 - agp_remove_file_private(priv); 668 - kfree(priv); 669 - file->private_data = NULL; 670 - mutex_unlock(&(agp_fe.agp_mutex)); 671 - return 0; 672 - } 673 - 674 - static int agp_open(struct inode *inode, struct file *file) 675 - { 676 - int minor = iminor(inode); 677 - struct agp_file_private *priv; 678 - struct agp_client *client; 679 - 680 - if (minor != AGPGART_MINOR) 681 - return -ENXIO; 682 - 683 - mutex_lock(&(agp_fe.agp_mutex)); 684 - 685 - priv = kzalloc(sizeof(struct agp_file_private), GFP_KERNEL); 686 - if (priv == NULL) { 687 - mutex_unlock(&(agp_fe.agp_mutex)); 688 - return -ENOMEM; 689 - } 690 - 691 - set_bit(AGP_FF_ALLOW_CLIENT, &priv->access_flags); 692 - priv->my_pid = current->pid; 693 - 694 - if (capable(CAP_SYS_RAWIO)) 695 - /* Root priv, can be controller */ 696 - set_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags); 697 - 698 - client = agp_find_client_by_pid(current->pid); 699 - 700 - if (client != NULL) { 701 - set_bit(AGP_FF_IS_CLIENT, &priv->access_flags); 702 - set_bit(AGP_FF_IS_VALID, &priv->access_flags); 703 - } 704 - file->private_data = (void *) priv; 705 - agp_insert_file_private(priv); 706 - DBG("private=%p, client=%p", priv, client); 707 - 708 - mutex_unlock(&(agp_fe.agp_mutex)); 709 - 710 - return 0; 711 - } 712 - 713 - static int agpioc_info_wrap(struct agp_file_private *priv, void __user *arg) 714 - { 715 - struct agp_info userinfo; 716 - struct agp_kern_info kerninfo; 717 - 718 - agp_copy_info(agp_bridge, &kerninfo); 719 - 720 - memset(&userinfo, 0, sizeof(userinfo)); 721 - userinfo.version.major = kerninfo.version.major; 722 - userinfo.version.minor = kerninfo.version.minor; 723 - userinfo.bridge_id = kerninfo.device->vendor | 724 - (kerninfo.device->device << 16); 725 - userinfo.agp_mode = kerninfo.mode; 726 - userinfo.aper_base = kerninfo.aper_base; 727 - userinfo.aper_size = kerninfo.aper_size; 728 - userinfo.pg_total = userinfo.pg_system = kerninfo.max_memory; 729 - userinfo.pg_used = kerninfo.current_memory; 730 - 731 - if (copy_to_user(arg, &userinfo, sizeof(struct agp_info))) 732 - return -EFAULT; 733 - 734 - return 0; 735 - } 736 - 737 - int agpioc_acquire_wrap(struct agp_file_private *priv) 738 - { 739 - struct agp_controller *controller; 740 - 741 - DBG(""); 742 - 743 - if (!(test_bit(AGP_FF_ALLOW_CONTROLLER, &priv->access_flags))) 744 - return -EPERM; 745 - 746 - if (agp_fe.current_controller != NULL) 747 - return -EBUSY; 748 - 749 - if (!agp_bridge) 750 - return -ENODEV; 751 - 752 - if (atomic_read(&agp_bridge->agp_in_use)) 753 - return -EBUSY; 754 - 755 - atomic_inc(&agp_bridge->agp_in_use); 756 - 757 - agp_fe.backend_acquired = true; 758 - 759 - controller = agp_find_controller_by_pid(priv->my_pid); 760 - 761 - if (controller != NULL) { 762 - agp_controller_make_current(controller); 763 - } else { 764 - controller = agp_create_controller(priv->my_pid); 765 - 766 - if (controller == NULL) { 767 - agp_fe.backend_acquired = false; 768 - agp_backend_release(agp_bridge); 769 - return -ENOMEM; 770 - } 771 - agp_insert_controller(controller); 772 - agp_controller_make_current(controller); 773 - } 774 - 775 - set_bit(AGP_FF_IS_CONTROLLER, &priv->access_flags); 776 - set_bit(AGP_FF_IS_VALID, &priv->access_flags); 777 - return 0; 778 - } 779 - 780 - int agpioc_release_wrap(struct agp_file_private *priv) 781 - { 782 - DBG(""); 783 - agp_controller_release_current(agp_fe.current_controller, priv); 784 - return 0; 785 - } 786 - 787 - int agpioc_setup_wrap(struct agp_file_private *priv, void __user *arg) 788 - { 789 - struct agp_setup mode; 790 - 791 - DBG(""); 792 - if (copy_from_user(&mode, arg, sizeof(struct agp_setup))) 793 - return -EFAULT; 794 - 795 - agp_enable(agp_bridge, mode.agp_mode); 796 - return 0; 797 - } 798 - 799 - static int agpioc_reserve_wrap(struct agp_file_private *priv, void __user *arg) 800 - { 801 - struct agp_region reserve; 802 - struct agp_client *client; 803 - struct agp_file_private *client_priv; 804 - 805 - DBG(""); 806 - if (copy_from_user(&reserve, arg, sizeof(struct agp_region))) 807 - return -EFAULT; 808 - 809 - if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment)) 810 - return -EFAULT; 811 - 812 - client = agp_find_client_by_pid(reserve.pid); 813 - 814 - if (reserve.seg_count == 0) { 815 - /* remove a client */ 816 - client_priv = agp_find_private(reserve.pid); 817 - 818 - if (client_priv != NULL) { 819 - set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); 820 - set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); 821 - } 822 - if (client == NULL) { 823 - /* client is already removed */ 824 - return 0; 825 - } 826 - return agp_remove_client(reserve.pid); 827 - } else { 828 - struct agp_segment *segment; 829 - 830 - if (reserve.seg_count >= 16384) 831 - return -EINVAL; 832 - 833 - segment = kmalloc((sizeof(struct agp_segment) * reserve.seg_count), 834 - GFP_KERNEL); 835 - 836 - if (segment == NULL) 837 - return -ENOMEM; 838 - 839 - if (copy_from_user(segment, (void __user *) reserve.seg_list, 840 - sizeof(struct agp_segment) * reserve.seg_count)) { 841 - kfree(segment); 842 - return -EFAULT; 843 - } 844 - reserve.seg_list = segment; 845 - 846 - if (client == NULL) { 847 - /* Create the client and add the segment */ 848 - client = agp_create_client(reserve.pid); 849 - 850 - if (client == NULL) { 851 - kfree(segment); 852 - return -ENOMEM; 853 - } 854 - client_priv = agp_find_private(reserve.pid); 855 - 856 - if (client_priv != NULL) { 857 - set_bit(AGP_FF_IS_CLIENT, &client_priv->access_flags); 858 - set_bit(AGP_FF_IS_VALID, &client_priv->access_flags); 859 - } 860 - } 861 - return agp_create_segment(client, &reserve); 862 - } 863 - /* Will never really happen */ 864 - return -EINVAL; 865 - } 866 - 867 - int agpioc_protect_wrap(struct agp_file_private *priv) 868 - { 869 - DBG(""); 870 - /* This function is not currently implemented */ 871 - return -EINVAL; 872 - } 873 - 874 - static int agpioc_allocate_wrap(struct agp_file_private *priv, void __user *arg) 875 - { 876 - struct agp_memory *memory; 877 - struct agp_allocate alloc; 878 - 879 - DBG(""); 880 - if (copy_from_user(&alloc, arg, sizeof(struct agp_allocate))) 881 - return -EFAULT; 882 - 883 - if (alloc.type >= AGP_USER_TYPES) 884 - return -EINVAL; 885 - 886 - memory = agp_allocate_memory_wrap(alloc.pg_count, alloc.type); 887 - 888 - if (memory == NULL) 889 - return -ENOMEM; 890 - 891 - alloc.key = memory->key; 892 - alloc.physical = memory->physical; 893 - 894 - if (copy_to_user(arg, &alloc, sizeof(struct agp_allocate))) { 895 - agp_free_memory_wrap(memory); 896 - return -EFAULT; 897 - } 898 - return 0; 899 - } 900 - 901 - int agpioc_deallocate_wrap(struct agp_file_private *priv, int arg) 902 - { 903 - struct agp_memory *memory; 904 - 905 - DBG(""); 906 - memory = agp_find_mem_by_key(arg); 907 - 908 - if (memory == NULL) 909 - return -EINVAL; 910 - 911 - agp_free_memory_wrap(memory); 912 - return 0; 913 - } 914 - 915 - static int agpioc_bind_wrap(struct agp_file_private *priv, void __user *arg) 916 - { 917 - struct agp_bind bind_info; 918 - struct agp_memory *memory; 919 - 920 - DBG(""); 921 - if (copy_from_user(&bind_info, arg, sizeof(struct agp_bind))) 922 - return -EFAULT; 923 - 924 - memory = agp_find_mem_by_key(bind_info.key); 925 - 926 - if (memory == NULL) 927 - return -EINVAL; 928 - 929 - return agp_bind_memory(memory, bind_info.pg_start); 930 - } 931 - 932 - static int agpioc_unbind_wrap(struct agp_file_private *priv, void __user *arg) 933 - { 934 - struct agp_memory *memory; 935 - struct agp_unbind unbind; 936 - 937 - DBG(""); 938 - if (copy_from_user(&unbind, arg, sizeof(struct agp_unbind))) 939 - return -EFAULT; 940 - 941 - memory = agp_find_mem_by_key(unbind.key); 942 - 943 - if (memory == NULL) 944 - return -EINVAL; 945 - 946 - return agp_unbind_memory(memory); 947 - } 948 - 949 - static long agp_ioctl(struct file *file, 950 - unsigned int cmd, unsigned long arg) 951 - { 952 - struct agp_file_private *curr_priv = file->private_data; 953 - int ret_val = -ENOTTY; 954 - 955 - DBG("priv=%p, cmd=%x", curr_priv, cmd); 956 - mutex_lock(&(agp_fe.agp_mutex)); 957 - 958 - if ((agp_fe.current_controller == NULL) && 959 - (cmd != AGPIOC_ACQUIRE)) { 960 - ret_val = -EINVAL; 961 - goto ioctl_out; 962 - } 963 - if ((agp_fe.backend_acquired != true) && 964 - (cmd != AGPIOC_ACQUIRE)) { 965 - ret_val = -EBUSY; 966 - goto ioctl_out; 967 - } 968 - if (cmd != AGPIOC_ACQUIRE) { 969 - if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) { 970 - ret_val = -EPERM; 971 - goto ioctl_out; 972 - } 973 - /* Use the original pid of the controller, 974 - * in case it's threaded */ 975 - 976 - if (agp_fe.current_controller->pid != curr_priv->my_pid) { 977 - ret_val = -EBUSY; 978 - goto ioctl_out; 979 - } 980 - } 981 - 982 - switch (cmd) { 983 - case AGPIOC_INFO: 984 - ret_val = agpioc_info_wrap(curr_priv, (void __user *) arg); 985 - break; 986 - 987 - case AGPIOC_ACQUIRE: 988 - ret_val = agpioc_acquire_wrap(curr_priv); 989 - break; 990 - 991 - case AGPIOC_RELEASE: 992 - ret_val = agpioc_release_wrap(curr_priv); 993 - break; 994 - 995 - case AGPIOC_SETUP: 996 - ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg); 997 - break; 998 - 999 - case AGPIOC_RESERVE: 1000 - ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg); 1001 - break; 1002 - 1003 - case AGPIOC_PROTECT: 1004 - ret_val = agpioc_protect_wrap(curr_priv); 1005 - break; 1006 - 1007 - case AGPIOC_ALLOCATE: 1008 - ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg); 1009 - break; 1010 - 1011 - case AGPIOC_DEALLOCATE: 1012 - ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg); 1013 - break; 1014 - 1015 - case AGPIOC_BIND: 1016 - ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg); 1017 - break; 1018 - 1019 - case AGPIOC_UNBIND: 1020 - ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg); 1021 - break; 1022 - 1023 - case AGPIOC_CHIPSET_FLUSH: 1024 - break; 1025 - } 1026 - 1027 - ioctl_out: 1028 - DBG("ioctl returns %d\n", ret_val); 1029 - mutex_unlock(&(agp_fe.agp_mutex)); 1030 - return ret_val; 1031 - } 1032 - 1033 - static const struct file_operations agp_fops = 1034 - { 1035 - .owner = THIS_MODULE, 1036 - .llseek = no_llseek, 1037 - .unlocked_ioctl = agp_ioctl, 1038 - #ifdef CONFIG_COMPAT 1039 - .compat_ioctl = compat_agp_ioctl, 1040 - #endif 1041 - .mmap = agp_mmap, 1042 - .open = agp_open, 1043 - .release = agp_release, 1044 - }; 1045 - 1046 - static struct miscdevice agp_miscdev = 1047 - { 1048 - .minor = AGPGART_MINOR, 1049 - .name = "agpgart", 1050 - .fops = &agp_fops 1051 - }; 1052 - 1053 - int agp_frontend_initialize(void) 1054 - { 1055 - memset(&agp_fe, 0, sizeof(struct agp_front_data)); 1056 - mutex_init(&(agp_fe.agp_mutex)); 1057 - 1058 - if (misc_register(&agp_miscdev)) { 1059 - printk(KERN_ERR PFX "unable to get minor: %d\n", AGPGART_MINOR); 1060 - return -EIO; 1061 - } 1062 - return 0; 1063 - } 1064 - 1065 - void agp_frontend_cleanup(void) 1066 - { 1067 - misc_deregister(&agp_miscdev); 1068 - }
+2 -1
drivers/dma-buf/dma-fence.c
··· 934 934 * the GPU's devfreq to reduce frequency, when in fact the opposite is what is 935 935 * needed. 936 936 * 937 - * To this end, deadline hint(s) can be set on a &dma_fence via &dma_fence_set_deadline. 937 + * To this end, deadline hint(s) can be set on a &dma_fence via &dma_fence_set_deadline 938 + * (or indirectly via userspace facing ioctls like &sync_set_deadline). 938 939 * The deadline hint provides a way for the waiting driver, or userspace, to 939 940 * convey an appropriate sense of urgency to the signaling driver. 940 941 *
+82
drivers/dma-buf/sw_sync.c
··· 52 52 __s32 fence; /* fd of new fence */ 53 53 }; 54 54 55 + /** 56 + * struct sw_sync_get_deadline - get the deadline hint of a sw_sync fence 57 + * @deadline_ns: absolute time of the deadline 58 + * @pad: must be zero 59 + * @fence_fd: the sw_sync fence fd (in) 60 + * 61 + * Return the earliest deadline set on the fence. The timebase for the 62 + * deadline is CLOCK_MONOTONIC (same as vblank). If there is no deadline 63 + * set on the fence, this ioctl will return -ENOENT. 64 + */ 65 + struct sw_sync_get_deadline { 66 + __u64 deadline_ns; 67 + __u32 pad; 68 + __s32 fence_fd; 69 + }; 70 + 55 71 #define SW_SYNC_IOC_MAGIC 'W' 56 72 57 73 #define SW_SYNC_IOC_CREATE_FENCE _IOWR(SW_SYNC_IOC_MAGIC, 0,\ 58 74 struct sw_sync_create_fence_data) 59 75 60 76 #define SW_SYNC_IOC_INC _IOW(SW_SYNC_IOC_MAGIC, 1, __u32) 77 + #define SW_SYNC_GET_DEADLINE _IOWR(SW_SYNC_IOC_MAGIC, 2, \ 78 + struct sw_sync_get_deadline) 79 + 80 + 81 + #define SW_SYNC_HAS_DEADLINE_BIT DMA_FENCE_FLAG_USER_BITS 61 82 62 83 static const struct dma_fence_ops timeline_fence_ops; 63 84 ··· 192 171 snprintf(str, size, "%d", parent->value); 193 172 } 194 173 174 + static void timeline_fence_set_deadline(struct dma_fence *fence, ktime_t deadline) 175 + { 176 + struct sync_pt *pt = dma_fence_to_sync_pt(fence); 177 + unsigned long flags; 178 + 179 + spin_lock_irqsave(fence->lock, flags); 180 + if (test_bit(SW_SYNC_HAS_DEADLINE_BIT, &fence->flags)) { 181 + if (ktime_before(deadline, pt->deadline)) 182 + pt->deadline = deadline; 183 + } else { 184 + pt->deadline = deadline; 185 + __set_bit(SW_SYNC_HAS_DEADLINE_BIT, &fence->flags); 186 + } 187 + spin_unlock_irqrestore(fence->lock, flags); 188 + } 189 + 195 190 static const struct dma_fence_ops timeline_fence_ops = { 196 191 .get_driver_name = timeline_fence_get_driver_name, 197 192 .get_timeline_name = timeline_fence_get_timeline_name, ··· 216 179 .release = timeline_fence_release, 217 180 .fence_value_str = timeline_fence_value_str, 218 181 .timeline_value_str = timeline_fence_timeline_value_str, 182 + .set_deadline = timeline_fence_set_deadline, 219 183 }; 220 184 221 185 /** ··· 425 387 return 0; 426 388 } 427 389 390 + static int sw_sync_ioctl_get_deadline(struct sync_timeline *obj, unsigned long arg) 391 + { 392 + struct sw_sync_get_deadline data; 393 + struct dma_fence *fence; 394 + unsigned long flags; 395 + struct sync_pt *pt; 396 + int ret = 0; 397 + 398 + if (copy_from_user(&data, (void __user *)arg, sizeof(data))) 399 + return -EFAULT; 400 + 401 + if (data.deadline_ns || data.pad) 402 + return -EINVAL; 403 + 404 + fence = sync_file_get_fence(data.fence_fd); 405 + if (!fence) 406 + return -EINVAL; 407 + 408 + pt = dma_fence_to_sync_pt(fence); 409 + if (!pt) 410 + return -EINVAL; 411 + 412 + spin_lock_irqsave(fence->lock, flags); 413 + if (test_bit(SW_SYNC_HAS_DEADLINE_BIT, &fence->flags)) { 414 + data.deadline_ns = ktime_to_ns(pt->deadline); 415 + } else { 416 + ret = -ENOENT; 417 + } 418 + spin_unlock_irqrestore(fence->lock, flags); 419 + 420 + dma_fence_put(fence); 421 + 422 + if (ret) 423 + return ret; 424 + 425 + if (copy_to_user((void __user *)arg, &data, sizeof(data))) 426 + return -EFAULT; 427 + 428 + return 0; 429 + } 430 + 428 431 static long sw_sync_ioctl(struct file *file, unsigned int cmd, 429 432 unsigned long arg) 430 433 { ··· 477 398 478 399 case SW_SYNC_IOC_INC: 479 400 return sw_sync_ioctl_inc(obj, arg); 401 + 402 + case SW_SYNC_GET_DEADLINE: 403 + return sw_sync_ioctl_get_deadline(obj, arg); 480 404 481 405 default: 482 406 return -ENOTTY;
+2
drivers/dma-buf/sync_debug.h
··· 55 55 * @base: base fence object 56 56 * @link: link on the sync timeline's list 57 57 * @node: node in the sync timeline's tree 58 + * @deadline: the earliest fence deadline hint 58 59 */ 59 60 struct sync_pt { 60 61 struct dma_fence base; 61 62 struct list_head link; 62 63 struct rb_node node; 64 + ktime_t deadline; 63 65 }; 64 66 65 67 extern const struct file_operations sw_sync_debugfs_fops;
+19
drivers/dma-buf/sync_file.c
··· 347 347 return ret; 348 348 } 349 349 350 + static int sync_file_ioctl_set_deadline(struct sync_file *sync_file, 351 + unsigned long arg) 352 + { 353 + struct sync_set_deadline ts; 354 + 355 + if (copy_from_user(&ts, (void __user *)arg, sizeof(ts))) 356 + return -EFAULT; 357 + 358 + if (ts.pad) 359 + return -EINVAL; 360 + 361 + dma_fence_set_deadline(sync_file->fence, ns_to_ktime(ts.deadline_ns)); 362 + 363 + return 0; 364 + } 365 + 350 366 static long sync_file_ioctl(struct file *file, unsigned int cmd, 351 367 unsigned long arg) 352 368 { ··· 374 358 375 359 case SYNC_IOC_FILE_INFO: 376 360 return sync_file_ioctl_fence_info(sync_file, arg); 361 + 362 + case SYNC_IOC_SET_DEADLINE: 363 + return sync_file_ioctl_set_deadline(sync_file, arg); 377 364 378 365 default: 379 366 return -ENOTTY;
+2 -22
drivers/gpu/drm/Kconfig
··· 74 74 75 75 config DRM_KUNIT_TEST 76 76 tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS 77 - depends on DRM && KUNIT 77 + depends on DRM && KUNIT && MMU 78 78 select DRM_BUDDY 79 79 select DRM_DISPLAY_DP_HELPER 80 80 select DRM_DISPLAY_HELPER 81 81 select DRM_EXEC 82 82 select DRM_EXPORT_FOR_TESTS if m 83 + select DRM_GEM_SHMEM_HELPER 83 84 select DRM_KMS_HELPER 84 85 select DRM_KUNIT_TEST_HELPERS 85 86 select DRM_LIB_RANDOM ··· 409 408 that DRM driver is used by default. 410 409 411 410 If M is selected the module will be called hyperv_drm. 412 - 413 - # Keep legacy drivers last 414 - 415 - menuconfig DRM_LEGACY 416 - bool "Enable legacy drivers (DANGEROUS)" 417 - depends on DRM && MMU 418 - help 419 - Enable legacy DRI1 drivers. Those drivers expose unsafe and dangerous 420 - APIs to user-space, which can be used to circumvent access 421 - restrictions and other security measures. For backwards compatibility 422 - those drivers are still available, but their use is highly 423 - inadvisable and might harm your system. 424 - 425 - You are recommended to use the safe modeset-only drivers instead, and 426 - perform 3D emulation in user-space. 427 - 428 - Unless you have strong reasons to go rogue, say "N". 429 - 430 - if DRM_LEGACY 431 - # leave here to list legacy drivers 432 - endif # DRM_LEGACY 433 411 434 412 config DRM_EXPORT_FOR_TESTS 435 413 bool
-12
drivers/gpu/drm/Makefile
··· 47 47 drm_vblank_work.o \ 48 48 drm_vma_manager.o \ 49 49 drm_writeback.o 50 - drm-$(CONFIG_DRM_LEGACY) += \ 51 - drm_agpsupport.o \ 52 - drm_bufs.o \ 53 - drm_context.o \ 54 - drm_dma.o \ 55 - drm_hashtab.o \ 56 - drm_irq.o \ 57 - drm_legacy_misc.o \ 58 - drm_lock.o \ 59 - drm_memory.o \ 60 - drm_scatter.o \ 61 - drm_vm.o 62 50 drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o 63 51 drm-$(CONFIG_COMPAT) += drm_ioc32.o 64 52 drm-$(CONFIG_DRM_PANEL) += drm_panel.o
+2 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
··· 73 73 return DRM_SCHED_PRIORITY_NORMAL; 74 74 75 75 case AMDGPU_CTX_PRIORITY_VERY_LOW: 76 - return DRM_SCHED_PRIORITY_MIN; 76 + return DRM_SCHED_PRIORITY_LOW; 77 77 78 78 case AMDGPU_CTX_PRIORITY_LOW: 79 - return DRM_SCHED_PRIORITY_MIN; 79 + return DRM_SCHED_PRIORITY_LOW; 80 80 81 81 case AMDGPU_CTX_PRIORITY_NORMAL: 82 82 return DRM_SCHED_PRIORITY_NORMAL;
+1 -1
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
··· 325 325 int i; 326 326 327 327 /* Signal all jobs not yet scheduled */ 328 - for (i = sched->num_rqs - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { 328 + for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) { 329 329 struct drm_sched_rq *rq = sched->sched_rq[i]; 330 330 spin_lock(&rq->lock); 331 331 list_for_each_entry(s_entity, &rq->entities, list) {
-1
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
··· 92 92 #include <drm/drm_vblank.h> 93 93 #include <drm/drm_audio_component.h> 94 94 #include <drm/drm_gem_atomic_helper.h> 95 - #include <drm/drm_plane_helper.h> 96 95 97 96 #include <acpi/video.h> 98 97
+7 -17
drivers/gpu/drm/armada/armada_crtc.c
··· 7 7 #include <linux/clk.h> 8 8 #include <linux/component.h> 9 9 #include <linux/module.h> 10 - #include <linux/of_device.h> 10 + #include <linux/of.h> 11 11 #include <linux/platform_device.h> 12 + #include <linux/property.h> 12 13 13 14 #include <drm/drm_atomic.h> 14 15 #include <drm/drm_atomic_helper.h> ··· 1013 1012 int irq = platform_get_irq(pdev, 0); 1014 1013 const struct armada_variant *variant; 1015 1014 struct device_node *port = NULL; 1015 + struct device_node *np, *parent = dev->of_node; 1016 1016 1017 1017 if (irq < 0) 1018 1018 return irq; 1019 1019 1020 - if (!dev->of_node) { 1021 - const struct platform_device_id *id; 1022 1020 1023 - id = platform_get_device_id(pdev); 1024 - if (!id) 1025 - return -ENXIO; 1021 + variant = device_get_match_data(dev); 1022 + if (!variant) 1023 + return -ENXIO; 1026 1024 1027 - variant = (const struct armada_variant *)id->driver_data; 1028 - } else { 1029 - const struct of_device_id *match; 1030 - struct device_node *np, *parent = dev->of_node; 1031 - 1032 - match = of_match_device(dev->driver->of_match_table, dev); 1033 - if (!match) 1034 - return -ENXIO; 1035 - 1025 + if (parent) { 1036 1026 np = of_get_child_by_name(parent, "ports"); 1037 1027 if (np) 1038 1028 parent = np; ··· 1033 1041 dev_err(dev, "no port node found in %pOF\n", parent); 1034 1042 return -ENXIO; 1035 1043 } 1036 - 1037 - variant = match->data; 1038 1044 } 1039 1045 1040 1046 return armada_drm_crtc_create(drm, dev, res, irq, variant, port);
+4 -6
drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
··· 6 6 #include <linux/irq.h> 7 7 #include <linux/mfd/syscon.h> 8 8 #include <linux/module.h> 9 - #include <linux/of.h> 10 - #include <linux/of_device.h> 9 + #include <linux/mod_devicetable.h> 11 10 #include <linux/of_reserved_mem.h> 12 11 #include <linux/platform_device.h> 12 + #include <linux/property.h> 13 13 #include <linux/regmap.h> 14 14 #include <linux/reset.h> 15 15 ··· 143 143 struct aspeed_gfx *priv = to_aspeed_gfx(drm); 144 144 struct device_node *np = pdev->dev.of_node; 145 145 const struct aspeed_gfx_config *config; 146 - const struct of_device_id *match; 147 146 struct resource *res; 148 147 int ret; 149 148 ··· 151 152 if (IS_ERR(priv->base)) 152 153 return PTR_ERR(priv->base); 153 154 154 - match = of_match_device(aspeed_gfx_match, &pdev->dev); 155 - if (!match) 155 + config = device_get_match_data(&pdev->dev); 156 + if (!config) 156 157 return -EINVAL; 157 - config = match->data; 158 158 159 159 priv->dac_reg = config->dac_reg; 160 160 priv->int_clr_reg = config->int_clear_reg;
+255 -8
drivers/gpu/drm/ast/ast_drv.c
··· 89 89 90 90 MODULE_DEVICE_TABLE(pci, ast_pciidlist); 91 91 92 + static bool ast_is_vga_enabled(void __iomem *ioregs) 93 + { 94 + u8 vgaer = __ast_read8(ioregs, AST_IO_VGAER); 95 + 96 + return vgaer & AST_IO_VGAER_VGA_ENABLE; 97 + } 98 + 99 + static void ast_enable_vga(void __iomem *ioregs) 100 + { 101 + __ast_write8(ioregs, AST_IO_VGAER, AST_IO_VGAER_VGA_ENABLE); 102 + __ast_write8(ioregs, AST_IO_VGAMR_W, AST_IO_VGAMR_IOSEL); 103 + } 104 + 105 + /* 106 + * Run this function as part of the HW device cleanup; not 107 + * when the DRM device gets released. 108 + */ 109 + static void ast_enable_mmio_release(void *data) 110 + { 111 + void __iomem *ioregs = (void __force __iomem *)data; 112 + 113 + /* enable standard VGA decode */ 114 + __ast_write8_i(ioregs, AST_IO_VGACRI, 0xa1, AST_IO_VGACRA1_MMIO_ENABLED); 115 + } 116 + 117 + static int ast_enable_mmio(struct device *dev, void __iomem *ioregs) 118 + { 119 + void *data = (void __force *)ioregs; 120 + 121 + __ast_write8_i(ioregs, AST_IO_VGACRI, 0xa1, 122 + AST_IO_VGACRA1_MMIO_ENABLED | 123 + AST_IO_VGACRA1_VGAIO_DISABLED); 124 + 125 + return devm_add_action_or_reset(dev, ast_enable_mmio_release, data); 126 + } 127 + 128 + static void ast_open_key(void __iomem *ioregs) 129 + { 130 + __ast_write8_i(ioregs, AST_IO_VGACRI, 0x80, AST_IO_VGACR80_PASSWORD); 131 + } 132 + 133 + static int ast_detect_chip(struct pci_dev *pdev, 134 + void __iomem *regs, void __iomem *ioregs, 135 + enum ast_chip *chip_out, 136 + enum ast_config_mode *config_mode_out) 137 + { 138 + struct device *dev = &pdev->dev; 139 + struct device_node *np = dev->of_node; 140 + enum ast_config_mode config_mode = ast_use_defaults; 141 + uint32_t scu_rev = 0xffffffff; 142 + enum ast_chip chip; 143 + u32 data; 144 + u8 vgacrd0, vgacrd1; 145 + 146 + /* 147 + * Find configuration mode and read SCU revision 148 + */ 149 + 150 + /* Check if we have device-tree properties */ 151 + if (np && !of_property_read_u32(np, "aspeed,scu-revision-id", &data)) { 152 + /* We do, disable P2A access */ 153 + config_mode = ast_use_dt; 154 + scu_rev = data; 155 + } else if (pdev->device == PCI_CHIP_AST2000) { // Not all families have a P2A bridge 156 + /* 157 + * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge 158 + * is disabled. We force using P2A if VGA only mode bit 159 + * is set D[7] 160 + */ 161 + vgacrd0 = __ast_read8_i(ioregs, AST_IO_VGACRI, 0xd0); 162 + vgacrd1 = __ast_read8_i(ioregs, AST_IO_VGACRI, 0xd1); 163 + if (!(vgacrd0 & 0x80) || !(vgacrd1 & 0x10)) { 164 + 165 + /* 166 + * We have a P2A bridge and it is enabled. 167 + */ 168 + 169 + /* Patch AST2500/AST2510 */ 170 + if ((pdev->revision & 0xf0) == 0x40) { 171 + if (!(vgacrd0 & AST_VRAM_INIT_STATUS_MASK)) 172 + ast_patch_ahb_2500(regs); 173 + } 174 + 175 + /* Double check that it's actually working */ 176 + data = __ast_read32(regs, 0xf004); 177 + if ((data != 0xffffffff) && (data != 0x00)) { 178 + config_mode = ast_use_p2a; 179 + 180 + /* Read SCU7c (silicon revision register) */ 181 + __ast_write32(regs, 0xf004, 0x1e6e0000); 182 + __ast_write32(regs, 0xf000, 0x1); 183 + scu_rev = __ast_read32(regs, 0x1207c); 184 + } 185 + } 186 + } 187 + 188 + switch (config_mode) { 189 + case ast_use_defaults: 190 + dev_info(dev, "Using default configuration\n"); 191 + break; 192 + case ast_use_dt: 193 + dev_info(dev, "Using device-tree for configuration\n"); 194 + break; 195 + case ast_use_p2a: 196 + dev_info(dev, "Using P2A bridge for configuration\n"); 197 + break; 198 + } 199 + 200 + /* 201 + * Identify chipset 202 + */ 203 + 204 + if (pdev->revision >= 0x50) { 205 + chip = AST2600; 206 + dev_info(dev, "AST 2600 detected\n"); 207 + } else if (pdev->revision >= 0x40) { 208 + switch (scu_rev & 0x300) { 209 + case 0x0100: 210 + chip = AST2510; 211 + dev_info(dev, "AST 2510 detected\n"); 212 + break; 213 + default: 214 + chip = AST2500; 215 + dev_info(dev, "AST 2500 detected\n"); 216 + break; 217 + } 218 + } else if (pdev->revision >= 0x30) { 219 + switch (scu_rev & 0x300) { 220 + case 0x0100: 221 + chip = AST1400; 222 + dev_info(dev, "AST 1400 detected\n"); 223 + break; 224 + default: 225 + chip = AST2400; 226 + dev_info(dev, "AST 2400 detected\n"); 227 + break; 228 + } 229 + } else if (pdev->revision >= 0x20) { 230 + switch (scu_rev & 0x300) { 231 + case 0x0000: 232 + chip = AST1300; 233 + dev_info(dev, "AST 1300 detected\n"); 234 + break; 235 + default: 236 + chip = AST2300; 237 + dev_info(dev, "AST 2300 detected\n"); 238 + break; 239 + } 240 + } else if (pdev->revision >= 0x10) { 241 + switch (scu_rev & 0x0300) { 242 + case 0x0200: 243 + chip = AST1100; 244 + dev_info(dev, "AST 1100 detected\n"); 245 + break; 246 + case 0x0100: 247 + chip = AST2200; 248 + dev_info(dev, "AST 2200 detected\n"); 249 + break; 250 + case 0x0000: 251 + chip = AST2150; 252 + dev_info(dev, "AST 2150 detected\n"); 253 + break; 254 + default: 255 + chip = AST2100; 256 + dev_info(dev, "AST 2100 detected\n"); 257 + break; 258 + } 259 + } else { 260 + chip = AST2000; 261 + dev_info(dev, "AST 2000 detected\n"); 262 + } 263 + 264 + *chip_out = chip; 265 + *config_mode_out = config_mode; 266 + 267 + return 0; 268 + } 269 + 92 270 static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 93 271 { 94 - struct ast_device *ast; 95 - struct drm_device *dev; 272 + struct device *dev = &pdev->dev; 96 273 int ret; 274 + void __iomem *regs; 275 + void __iomem *ioregs; 276 + enum ast_config_mode config_mode; 277 + enum ast_chip chip; 278 + struct drm_device *drm; 279 + bool need_post = false; 97 280 98 281 ret = drm_aperture_remove_conflicting_pci_framebuffers(pdev, &ast_driver); 99 282 if (ret) ··· 286 103 if (ret) 287 104 return ret; 288 105 289 - ast = ast_device_create(&ast_driver, pdev, ent->driver_data); 290 - if (IS_ERR(ast)) 291 - return PTR_ERR(ast); 292 - dev = &ast->base; 106 + regs = pcim_iomap(pdev, 1, 0); 107 + if (!regs) 108 + return -EIO; 293 109 294 - ret = drm_dev_register(dev, ent->driver_data); 110 + if (pdev->revision >= 0x40) { 111 + /* 112 + * On AST2500 and later models, MMIO is enabled by 113 + * default. Adopt it to be compatible with ARM. 114 + */ 115 + resource_size_t len = pci_resource_len(pdev, 1); 116 + 117 + if (len < AST_IO_MM_OFFSET) 118 + return -EIO; 119 + if ((len - AST_IO_MM_OFFSET) < AST_IO_MM_LENGTH) 120 + return -EIO; 121 + ioregs = regs + AST_IO_MM_OFFSET; 122 + } else if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { 123 + /* 124 + * Map I/O registers if we have a PCI BAR for I/O. 125 + */ 126 + resource_size_t len = pci_resource_len(pdev, 2); 127 + 128 + if (len < AST_IO_MM_LENGTH) 129 + return -EIO; 130 + ioregs = pcim_iomap(pdev, 2, 0); 131 + if (!ioregs) 132 + return -EIO; 133 + } else { 134 + /* 135 + * Anything else is best effort. 136 + */ 137 + resource_size_t len = pci_resource_len(pdev, 1); 138 + 139 + if (len < AST_IO_MM_OFFSET) 140 + return -EIO; 141 + if ((len - AST_IO_MM_OFFSET) < AST_IO_MM_LENGTH) 142 + return -EIO; 143 + ioregs = regs + AST_IO_MM_OFFSET; 144 + 145 + dev_info(dev, "Platform has no I/O space, using MMIO\n"); 146 + } 147 + 148 + if (!ast_is_vga_enabled(ioregs)) { 149 + dev_info(dev, "VGA not enabled on entry, requesting chip POST\n"); 150 + need_post = true; 151 + } 152 + 153 + /* 154 + * If VGA isn't enabled, we need to enable now or subsequent 155 + * access to the scratch registers will fail. 156 + */ 157 + if (need_post) 158 + ast_enable_vga(ioregs); 159 + /* Enable extended register access */ 160 + ast_open_key(ioregs); 161 + 162 + ret = ast_enable_mmio(dev, ioregs); 295 163 if (ret) 296 164 return ret; 297 165 298 - drm_fbdev_generic_setup(dev, 32); 166 + ret = ast_detect_chip(pdev, regs, ioregs, &chip, &config_mode); 167 + if (ret) 168 + return ret; 169 + 170 + drm = ast_device_create(pdev, &ast_driver, chip, config_mode, regs, ioregs, need_post); 171 + if (IS_ERR(drm)) 172 + return PTR_ERR(drm); 173 + pci_set_drvdata(pdev, drm); 174 + 175 + ret = drm_dev_register(drm, ent->driver_data); 176 + if (ret) 177 + return ret; 178 + 179 + drm_fbdev_generic_setup(drm, 32); 299 180 300 181 return 0; 301 182 }
+74 -27
drivers/gpu/drm/ast/ast_drv.h
··· 98 98 #define AST_TX_DP501_BIT BIT(AST_TX_DP501) 99 99 #define AST_TX_ASTDP_BIT BIT(AST_TX_ASTDP) 100 100 101 + enum ast_config_mode { 102 + ast_use_p2a, 103 + ast_use_dt, 104 + ast_use_defaults 105 + }; 106 + 101 107 #define AST_DRAM_512Mx16 0 102 108 #define AST_DRAM_1Gx16 1 103 109 #define AST_DRAM_512Mx32 2 ··· 198 192 struct ast_device { 199 193 struct drm_device base; 200 194 201 - struct mutex ioregs_lock; /* Protects access to I/O registers in ioregs */ 202 195 void __iomem *regs; 203 196 void __iomem *ioregs; 204 197 void __iomem *dp501_fw_buf; 205 198 199 + enum ast_config_mode config_mode; 206 200 enum ast_chip chip; 201 + 207 202 uint32_t dram_bus_width; 208 203 uint32_t dram_type; 209 204 uint32_t mclk; ··· 213 206 unsigned long vram_base; 214 207 unsigned long vram_size; 215 208 unsigned long vram_fb_available; 209 + 210 + struct mutex modeset_lock; /* Protects access to modeset I/O registers in ioregs */ 216 211 217 212 struct ast_plane primary_plane; 218 213 struct ast_plane cursor_plane; ··· 243 234 } output; 244 235 245 236 bool support_wide_screen; 246 - enum { 247 - ast_use_p2a, 248 - ast_use_dt, 249 - ast_use_defaults 250 - } config_mode; 251 237 252 238 unsigned long tx_chip_types; /* bitfield of enum ast_chip_type */ 253 239 u8 *dp501_fw_addr; ··· 254 250 return container_of(dev, struct ast_device, base); 255 251 } 256 252 257 - struct ast_device *ast_device_create(const struct drm_driver *drv, 258 - struct pci_dev *pdev, 259 - unsigned long flags); 253 + struct drm_device *ast_device_create(struct pci_dev *pdev, 254 + const struct drm_driver *drv, 255 + enum ast_chip chip, 256 + enum ast_config_mode config_mode, 257 + void __iomem *regs, 258 + void __iomem *ioregs, 259 + bool need_post); 260 260 261 261 static inline unsigned long __ast_gen(struct ast_device *ast) 262 262 { ··· 280 272 #define IS_AST_GEN6(__ast) __ast_gen_is_eq(__ast, 6) 281 273 #define IS_AST_GEN7(__ast) __ast_gen_is_eq(__ast, 7) 282 274 275 + static inline u8 __ast_read8(const void __iomem *addr, u32 reg) 276 + { 277 + return ioread8(addr + reg); 278 + } 279 + 280 + static inline u32 __ast_read32(const void __iomem *addr, u32 reg) 281 + { 282 + return ioread32(addr + reg); 283 + } 284 + 285 + static inline void __ast_write8(void __iomem *addr, u32 reg, u8 val) 286 + { 287 + iowrite8(val, addr + reg); 288 + } 289 + 290 + static inline void __ast_write32(void __iomem *addr, u32 reg, u32 val) 291 + { 292 + iowrite32(val, addr + reg); 293 + } 294 + 295 + static inline u8 __ast_read8_i(void __iomem *addr, u32 reg, u8 index) 296 + { 297 + __ast_write8(addr, reg, index); 298 + return __ast_read8(addr, reg + 1); 299 + } 300 + 301 + static inline u8 __ast_read8_i_masked(void __iomem *addr, u32 reg, u8 index, u8 read_mask) 302 + { 303 + u8 val = __ast_read8_i(addr, reg, index); 304 + 305 + return val & read_mask; 306 + } 307 + 308 + static inline void __ast_write8_i(void __iomem *addr, u32 reg, u8 index, u8 val) 309 + { 310 + __ast_write8(addr, reg, index); 311 + __ast_write8(addr, reg + 1, val); 312 + } 313 + 314 + static inline void __ast_write8_i_masked(void __iomem *addr, u32 reg, u8 index, u8 read_mask, 315 + u8 val) 316 + { 317 + u8 tmp = __ast_read8_i_masked(addr, reg, index, read_mask); 318 + 319 + tmp |= val; 320 + __ast_write8_i(addr, reg, index, tmp); 321 + } 322 + 283 323 static inline u32 ast_read32(struct ast_device *ast, u32 reg) 284 324 { 285 - return ioread32(ast->regs + reg); 325 + return __ast_read32(ast->regs, reg); 286 326 } 287 327 288 328 static inline void ast_write32(struct ast_device *ast, u32 reg, u32 val) 289 329 { 290 - iowrite32(val, ast->regs + reg); 330 + __ast_write32(ast->regs, reg, val); 291 331 } 292 332 293 333 static inline u8 ast_io_read8(struct ast_device *ast, u32 reg) 294 334 { 295 - return ioread8(ast->ioregs + reg); 335 + return __ast_read8(ast->ioregs, reg); 296 336 } 297 337 298 338 static inline void ast_io_write8(struct ast_device *ast, u32 reg, u8 val) 299 339 { 300 - iowrite8(val, ast->ioregs + reg); 340 + __ast_write8(ast->ioregs, reg, val); 301 341 } 302 342 303 343 static inline u8 ast_get_index_reg(struct ast_device *ast, u32 base, u8 index) 304 344 { 305 - ast_io_write8(ast, base, index); 306 - ++base; 307 - return ast_io_read8(ast, base); 345 + return __ast_read8_i(ast->ioregs, base, index); 308 346 } 309 347 310 348 static inline u8 ast_get_index_reg_mask(struct ast_device *ast, u32 base, u8 index, 311 349 u8 preserve_mask) 312 350 { 313 - u8 val = ast_get_index_reg(ast, base, index); 314 - 315 - return val & preserve_mask; 351 + return __ast_read8_i_masked(ast->ioregs, base, index, preserve_mask); 316 352 } 317 353 318 354 static inline void ast_set_index_reg(struct ast_device *ast, u32 base, u8 index, u8 val) 319 355 { 320 - ast_io_write8(ast, base, index); 321 - ++base; 322 - ast_io_write8(ast, base, val); 356 + __ast_write8_i(ast->ioregs, base, index, val); 323 357 } 324 358 325 359 static inline void ast_set_index_reg_mask(struct ast_device *ast, u32 base, u8 index, 326 360 u8 preserve_mask, u8 val) 327 361 { 328 - u8 tmp = ast_get_index_reg_mask(ast, base, index, preserve_mask); 329 - 330 - tmp |= val; 331 - ast_set_index_reg(ast, base, index, tmp); 362 + __ast_write8_i_masked(ast->ioregs, base, index, preserve_mask, val); 332 363 } 333 364 334 365 #define AST_VIDMEM_SIZE_8M 0x00800000 ··· 489 442 void ast_post_gpu(struct drm_device *dev); 490 443 u32 ast_mindwm(struct ast_device *ast, u32 r); 491 444 void ast_moutdwm(struct ast_device *ast, u32 r, u32 v); 492 - void ast_patch_ahb_2500(struct ast_device *ast); 445 + void ast_patch_ahb_2500(void __iomem *regs); 493 446 /* ast dp501 */ 494 447 void ast_set_dp501_video_output(struct drm_device *dev, u8 mode); 495 448 bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size);
+14 -230
drivers/gpu/drm/ast/ast_main.c
··· 35 35 36 36 #include "ast_drv.h" 37 37 38 - static bool ast_is_vga_enabled(struct drm_device *dev) 39 - { 40 - struct ast_device *ast = to_ast_device(dev); 41 - u8 ch; 42 - 43 - ch = ast_io_read8(ast, AST_IO_VGAER); 44 - 45 - return !!(ch & 0x01); 46 - } 47 - 48 - static void ast_enable_vga(struct drm_device *dev) 49 - { 50 - struct ast_device *ast = to_ast_device(dev); 51 - 52 - ast_io_write8(ast, AST_IO_VGAER, 0x01); 53 - ast_io_write8(ast, AST_IO_VGAMR_W, 0x01); 54 - } 55 - 56 - /* 57 - * Run this function as part of the HW device cleanup; not 58 - * when the DRM device gets released. 59 - */ 60 - static void ast_enable_mmio_release(void *data) 61 - { 62 - struct ast_device *ast = data; 63 - 64 - /* enable standard VGA decode */ 65 - ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x04); 66 - } 67 - 68 - static int ast_enable_mmio(struct ast_device *ast) 69 - { 70 - struct drm_device *dev = &ast->base; 71 - 72 - ast_set_index_reg(ast, AST_IO_VGACRI, 0xa1, 0x06); 73 - 74 - return devm_add_action_or_reset(dev->dev, ast_enable_mmio_release, ast); 75 - } 76 - 77 - static void ast_open_key(struct ast_device *ast) 78 - { 79 - ast_set_index_reg(ast, AST_IO_VGACRI, 0x80, 0xA8); 80 - } 81 - 82 - static int ast_device_config_init(struct ast_device *ast) 83 - { 84 - struct drm_device *dev = &ast->base; 85 - struct pci_dev *pdev = to_pci_dev(dev->dev); 86 - struct device_node *np = dev->dev->of_node; 87 - uint32_t scu_rev = 0xffffffff; 88 - u32 data; 89 - u8 jregd0, jregd1; 90 - 91 - /* 92 - * Find configuration mode and read SCU revision 93 - */ 94 - 95 - ast->config_mode = ast_use_defaults; 96 - 97 - /* Check if we have device-tree properties */ 98 - if (np && !of_property_read_u32(np, "aspeed,scu-revision-id", &data)) { 99 - /* We do, disable P2A access */ 100 - ast->config_mode = ast_use_dt; 101 - scu_rev = data; 102 - } else if (pdev->device == PCI_CHIP_AST2000) { // Not all families have a P2A bridge 103 - /* 104 - * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge 105 - * is disabled. We force using P2A if VGA only mode bit 106 - * is set D[7] 107 - */ 108 - jregd0 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); 109 - jregd1 = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd1, 0xff); 110 - if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) { 111 - 112 - /* 113 - * We have a P2A bridge and it is enabled. 114 - */ 115 - 116 - /* Patch AST2500/AST2510 */ 117 - if ((pdev->revision & 0xf0) == 0x40) { 118 - if (!(jregd0 & AST_VRAM_INIT_STATUS_MASK)) 119 - ast_patch_ahb_2500(ast); 120 - } 121 - 122 - /* Double check that it's actually working */ 123 - data = ast_read32(ast, 0xf004); 124 - if ((data != 0xffffffff) && (data != 0x00)) { 125 - ast->config_mode = ast_use_p2a; 126 - 127 - /* Read SCU7c (silicon revision register) */ 128 - ast_write32(ast, 0xf004, 0x1e6e0000); 129 - ast_write32(ast, 0xf000, 0x1); 130 - scu_rev = ast_read32(ast, 0x1207c); 131 - } 132 - } 133 - } 134 - 135 - switch (ast->config_mode) { 136 - case ast_use_defaults: 137 - drm_info(dev, "Using default configuration\n"); 138 - break; 139 - case ast_use_dt: 140 - drm_info(dev, "Using device-tree for configuration\n"); 141 - break; 142 - case ast_use_p2a: 143 - drm_info(dev, "Using P2A bridge for configuration\n"); 144 - break; 145 - } 146 - 147 - /* 148 - * Identify chipset 149 - */ 150 - 151 - if (pdev->revision >= 0x50) { 152 - ast->chip = AST2600; 153 - drm_info(dev, "AST 2600 detected\n"); 154 - } else if (pdev->revision >= 0x40) { 155 - switch (scu_rev & 0x300) { 156 - case 0x0100: 157 - ast->chip = AST2510; 158 - drm_info(dev, "AST 2510 detected\n"); 159 - break; 160 - default: 161 - ast->chip = AST2500; 162 - drm_info(dev, "AST 2500 detected\n"); 163 - } 164 - } else if (pdev->revision >= 0x30) { 165 - switch (scu_rev & 0x300) { 166 - case 0x0100: 167 - ast->chip = AST1400; 168 - drm_info(dev, "AST 1400 detected\n"); 169 - break; 170 - default: 171 - ast->chip = AST2400; 172 - drm_info(dev, "AST 2400 detected\n"); 173 - } 174 - } else if (pdev->revision >= 0x20) { 175 - switch (scu_rev & 0x300) { 176 - case 0x0000: 177 - ast->chip = AST1300; 178 - drm_info(dev, "AST 1300 detected\n"); 179 - break; 180 - default: 181 - ast->chip = AST2300; 182 - drm_info(dev, "AST 2300 detected\n"); 183 - break; 184 - } 185 - } else if (pdev->revision >= 0x10) { 186 - switch (scu_rev & 0x0300) { 187 - case 0x0200: 188 - ast->chip = AST1100; 189 - drm_info(dev, "AST 1100 detected\n"); 190 - break; 191 - case 0x0100: 192 - ast->chip = AST2200; 193 - drm_info(dev, "AST 2200 detected\n"); 194 - break; 195 - case 0x0000: 196 - ast->chip = AST2150; 197 - drm_info(dev, "AST 2150 detected\n"); 198 - break; 199 - default: 200 - ast->chip = AST2100; 201 - drm_info(dev, "AST 2100 detected\n"); 202 - break; 203 - } 204 - } else { 205 - ast->chip = AST2000; 206 - drm_info(dev, "AST 2000 detected\n"); 207 - } 208 - 209 - return 0; 210 - } 211 - 212 38 static void ast_detect_widescreen(struct ast_device *ast) 213 39 { 214 40 u8 jreg; ··· 250 424 return 0; 251 425 } 252 426 253 - struct ast_device *ast_device_create(const struct drm_driver *drv, 254 - struct pci_dev *pdev, 255 - unsigned long flags) 427 + struct drm_device *ast_device_create(struct pci_dev *pdev, 428 + const struct drm_driver *drv, 429 + enum ast_chip chip, 430 + enum ast_config_mode config_mode, 431 + void __iomem *regs, 432 + void __iomem *ioregs, 433 + bool need_post) 256 434 { 257 435 struct drm_device *dev; 258 436 struct ast_device *ast; 259 - bool need_post = false; 260 - int ret = 0; 437 + int ret; 261 438 262 439 ast = devm_drm_dev_alloc(&pdev->dev, drv, struct ast_device, base); 263 440 if (IS_ERR(ast)) 264 - return ast; 441 + return ERR_CAST(ast); 265 442 dev = &ast->base; 266 443 267 - pci_set_drvdata(pdev, dev); 268 - 269 - ret = drmm_mutex_init(dev, &ast->ioregs_lock); 270 - if (ret) 271 - return ERR_PTR(ret); 272 - 273 - ast->regs = pcim_iomap(pdev, 1, 0); 274 - if (!ast->regs) 275 - return ERR_PTR(-EIO); 276 - 277 - /* 278 - * After AST2500, MMIO is enabled by default, and it should be adopted 279 - * to be compatible with Arm. 280 - */ 281 - if (pdev->revision >= 0x40) { 282 - ast->ioregs = ast->regs + AST_IO_MM_OFFSET; 283 - } else if (!(pci_resource_flags(pdev, 2) & IORESOURCE_IO)) { 284 - drm_info(dev, "platform has no IO space, trying MMIO\n"); 285 - ast->ioregs = ast->regs + AST_IO_MM_OFFSET; 286 - } 287 - 288 - /* "map" IO regs if the above hasn't done so already */ 289 - if (!ast->ioregs) { 290 - ast->ioregs = pcim_iomap(pdev, 2, 0); 291 - if (!ast->ioregs) 292 - return ERR_PTR(-EIO); 293 - } 294 - 295 - if (!ast_is_vga_enabled(dev)) { 296 - drm_info(dev, "VGA not enabled on entry, requesting chip POST\n"); 297 - need_post = true; 298 - } 299 - 300 - /* 301 - * If VGA isn't enabled, we need to enable now or subsequent 302 - * access to the scratch registers will fail. 303 - */ 304 - if (need_post) 305 - ast_enable_vga(dev); 306 - 307 - /* Enable extended register access */ 308 - ast_open_key(ast); 309 - ret = ast_enable_mmio(ast); 310 - if (ret) 311 - return ERR_PTR(ret); 312 - 313 - ret = ast_device_config_init(ast); 314 - if (ret) 315 - return ERR_PTR(ret); 444 + ast->chip = chip; 445 + ast->config_mode = config_mode; 446 + ast->regs = regs; 447 + ast->ioregs = ioregs; 316 448 317 449 ast_detect_widescreen(ast); 318 450 ast_detect_tx_chip(ast, need_post); ··· 301 517 if (ret) 302 518 return ERR_PTR(ret); 303 519 304 - return ast; 520 + return dev; 305 521 }
+15 -11
drivers/gpu/drm/ast/ast_mode.c
··· 1358 1358 * Protect access to I/O registers from concurrent modesetting 1359 1359 * by acquiring the I/O-register lock. 1360 1360 */ 1361 - mutex_lock(&ast->ioregs_lock); 1361 + mutex_lock(&ast->modeset_lock); 1362 1362 1363 1363 edid = drm_get_edid(connector, &ast_vga_connector->i2c->adapter); 1364 1364 if (!edid) 1365 1365 goto err_mutex_unlock; 1366 1366 1367 - mutex_unlock(&ast->ioregs_lock); 1367 + mutex_unlock(&ast->modeset_lock); 1368 1368 1369 1369 count = drm_add_edid_modes(connector, edid); 1370 1370 kfree(edid); ··· 1372 1372 return count; 1373 1373 1374 1374 err_mutex_unlock: 1375 - mutex_unlock(&ast->ioregs_lock); 1375 + mutex_unlock(&ast->modeset_lock); 1376 1376 err_drm_connector_update_edid_property: 1377 1377 drm_connector_update_edid_property(connector, NULL); 1378 1378 return 0; ··· 1464 1464 * Protect access to I/O registers from concurrent modesetting 1465 1465 * by acquiring the I/O-register lock. 1466 1466 */ 1467 - mutex_lock(&ast->ioregs_lock); 1467 + mutex_lock(&ast->modeset_lock); 1468 1468 1469 1469 edid = drm_get_edid(connector, &ast_sil164_connector->i2c->adapter); 1470 1470 if (!edid) 1471 1471 goto err_mutex_unlock; 1472 1472 1473 - mutex_unlock(&ast->ioregs_lock); 1473 + mutex_unlock(&ast->modeset_lock); 1474 1474 1475 1475 count = drm_add_edid_modes(connector, edid); 1476 1476 kfree(edid); ··· 1478 1478 return count; 1479 1479 1480 1480 err_mutex_unlock: 1481 - mutex_unlock(&ast->ioregs_lock); 1481 + mutex_unlock(&ast->modeset_lock); 1482 1482 err_drm_connector_update_edid_property: 1483 1483 drm_connector_update_edid_property(connector, NULL); 1484 1484 return 0; ··· 1670 1670 * Protect access to I/O registers from concurrent modesetting 1671 1671 * by acquiring the I/O-register lock. 1672 1672 */ 1673 - mutex_lock(&ast->ioregs_lock); 1673 + mutex_lock(&ast->modeset_lock); 1674 1674 1675 1675 succ = ast_astdp_read_edid(connector->dev, edid); 1676 1676 if (succ < 0) 1677 1677 goto err_mutex_unlock; 1678 1678 1679 - mutex_unlock(&ast->ioregs_lock); 1679 + mutex_unlock(&ast->modeset_lock); 1680 1680 1681 1681 drm_connector_update_edid_property(connector, edid); 1682 1682 count = drm_add_edid_modes(connector, edid); ··· 1685 1685 return count; 1686 1686 1687 1687 err_mutex_unlock: 1688 - mutex_unlock(&ast->ioregs_lock); 1688 + mutex_unlock(&ast->modeset_lock); 1689 1689 kfree(edid); 1690 1690 err_drm_connector_update_edid_property: 1691 1691 drm_connector_update_edid_property(connector, NULL); ··· 1870 1870 * display modes. Protect access to I/O registers by acquiring 1871 1871 * the I/O-register lock. Released in atomic_flush(). 1872 1872 */ 1873 - mutex_lock(&ast->ioregs_lock); 1873 + mutex_lock(&ast->modeset_lock); 1874 1874 drm_atomic_helper_commit_tail_rpm(state); 1875 - mutex_unlock(&ast->ioregs_lock); 1875 + mutex_unlock(&ast->modeset_lock); 1876 1876 } 1877 1877 1878 1878 static const struct drm_mode_config_helper_funcs ast_mode_config_helper_funcs = { ··· 1909 1909 struct drm_device *dev = &ast->base; 1910 1910 struct drm_connector *physical_connector = NULL; 1911 1911 int ret; 1912 + 1913 + ret = drmm_mutex_init(dev, &ast->modeset_lock); 1914 + if (ret) 1915 + return ret; 1912 1916 1913 1917 ret = drmm_mode_config_init(dev); 1914 1918 if (ret)
+46 -29
drivers/gpu/drm/ast/ast_post.c
··· 77 77 ast_set_index_reg_mask(ast, AST_IO_VGACRI, 0xb6, 0xff, reg); 78 78 } 79 79 80 - u32 ast_mindwm(struct ast_device *ast, u32 r) 80 + static u32 __ast_mindwm(void __iomem *regs, u32 r) 81 81 { 82 - uint32_t data; 82 + u32 data; 83 83 84 - ast_write32(ast, 0xf004, r & 0xffff0000); 85 - ast_write32(ast, 0xf000, 0x1); 84 + __ast_write32(regs, 0xf004, r & 0xffff0000); 85 + __ast_write32(regs, 0xf000, 0x1); 86 86 87 87 do { 88 - data = ast_read32(ast, 0xf004) & 0xffff0000; 88 + data = __ast_read32(regs, 0xf004) & 0xffff0000; 89 89 } while (data != (r & 0xffff0000)); 90 - return ast_read32(ast, 0x10000 + (r & 0x0000ffff)); 90 + 91 + return __ast_read32(regs, 0x10000 + (r & 0x0000ffff)); 92 + } 93 + 94 + static void __ast_moutdwm(void __iomem *regs, u32 r, u32 v) 95 + { 96 + u32 data; 97 + 98 + __ast_write32(regs, 0xf004, r & 0xffff0000); 99 + __ast_write32(regs, 0xf000, 0x1); 100 + 101 + do { 102 + data = __ast_read32(regs, 0xf004) & 0xffff0000; 103 + } while (data != (r & 0xffff0000)); 104 + 105 + __ast_write32(regs, 0x10000 + (r & 0x0000ffff), v); 106 + } 107 + 108 + u32 ast_mindwm(struct ast_device *ast, u32 r) 109 + { 110 + return __ast_mindwm(ast->regs, r); 91 111 } 92 112 93 113 void ast_moutdwm(struct ast_device *ast, u32 r, u32 v) 94 114 { 95 - uint32_t data; 96 - ast_write32(ast, 0xf004, r & 0xffff0000); 97 - ast_write32(ast, 0xf000, 0x1); 98 - do { 99 - data = ast_read32(ast, 0xf004) & 0xffff0000; 100 - } while (data != (r & 0xffff0000)); 101 - ast_write32(ast, 0x10000 + (r & 0x0000ffff), v); 115 + __ast_moutdwm(ast->regs, r, v); 102 116 } 103 117 104 118 /* ··· 2001 1987 return true; 2002 1988 } 2003 1989 2004 - void ast_patch_ahb_2500(struct ast_device *ast) 1990 + void ast_patch_ahb_2500(void __iomem *regs) 2005 1991 { 2006 - u32 data; 1992 + u32 data; 2007 1993 2008 1994 /* Clear bus lock condition */ 2009 - ast_moutdwm(ast, 0x1e600000, 0xAEED1A03); 2010 - ast_moutdwm(ast, 0x1e600084, 0x00010000); 2011 - ast_moutdwm(ast, 0x1e600088, 0x00000000); 2012 - ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8); 2013 - data = ast_mindwm(ast, 0x1e6e2070); 2014 - if (data & 0x08000000) { /* check fast reset */ 1995 + __ast_moutdwm(regs, 0x1e600000, 0xAEED1A03); 1996 + __ast_moutdwm(regs, 0x1e600084, 0x00010000); 1997 + __ast_moutdwm(regs, 0x1e600088, 0x00000000); 1998 + __ast_moutdwm(regs, 0x1e6e2000, 0x1688A8A8); 1999 + 2000 + data = __ast_mindwm(regs, 0x1e6e2070); 2001 + if (data & 0x08000000) { /* check fast reset */ 2015 2002 /* 2016 2003 * If "Fast restet" is enabled for ARM-ICE debugger, 2017 2004 * then WDT needs to enable, that ··· 2024 2009 * [1]:= 1:WDT will be cleeared and disabled after timeout occurs 2025 2010 * [0]:= 1:WDT enable 2026 2011 */ 2027 - ast_moutdwm(ast, 0x1E785004, 0x00000010); 2028 - ast_moutdwm(ast, 0x1E785008, 0x00004755); 2029 - ast_moutdwm(ast, 0x1E78500c, 0x00000033); 2012 + __ast_moutdwm(regs, 0x1E785004, 0x00000010); 2013 + __ast_moutdwm(regs, 0x1E785008, 0x00004755); 2014 + __ast_moutdwm(regs, 0x1E78500c, 0x00000033); 2030 2015 udelay(1000); 2031 2016 } 2017 + 2032 2018 do { 2033 - ast_moutdwm(ast, 0x1e6e2000, 0x1688A8A8); 2034 - data = ast_mindwm(ast, 0x1e6e2000); 2035 - } while (data != 1); 2036 - ast_moutdwm(ast, 0x1e6e207c, 0x08000000); /* clear fast reset */ 2019 + __ast_moutdwm(regs, 0x1e6e2000, 0x1688A8A8); 2020 + data = __ast_mindwm(regs, 0x1e6e2000); 2021 + } while (data != 1); 2022 + 2023 + __ast_moutdwm(regs, 0x1e6e207c, 0x08000000); /* clear fast reset */ 2037 2024 } 2038 2025 2039 2026 void ast_post_chip_2500(struct drm_device *dev) ··· 2047 2030 reg = ast_get_index_reg_mask(ast, AST_IO_VGACRI, 0xd0, 0xff); 2048 2031 if ((reg & AST_VRAM_INIT_STATUS_MASK) == 0) {/* vga only */ 2049 2032 /* Clear bus lock condition */ 2050 - ast_patch_ahb_2500(ast); 2033 + ast_patch_ahb_2500(ast->regs); 2051 2034 2052 2035 /* Disable watchdog */ 2053 2036 ast_moutdwm(ast, 0x1E78502C, 0x00000000);
+10 -2
drivers/gpu/drm/ast/ast_reg.h
··· 10 10 */ 11 11 12 12 #define AST_IO_MM_OFFSET (0x380) 13 + #define AST_IO_MM_LENGTH (128) 13 14 14 15 #define AST_IO_VGAARI_W (0x40) 16 + 15 17 #define AST_IO_VGAMR_W (0x42) 18 + #define AST_IO_VGAMR_R (0x4c) 19 + #define AST_IO_VGAMR_IOSEL BIT(0) 20 + 16 21 #define AST_IO_VGAER (0x43) 22 + #define AST_IO_VGAER_VGA_ENABLE BIT(0) 23 + 17 24 #define AST_IO_VGASRI (0x44) 18 25 #define AST_IO_VGADRR (0x47) 19 26 #define AST_IO_VGADWR (0x48) ··· 28 21 #define AST_IO_VGAGRI (0x4E) 29 22 30 23 #define AST_IO_VGACRI (0x54) 24 + #define AST_IO_VGACR80_PASSWORD (0xa8) 25 + #define AST_IO_VGACRA1_VGAIO_DISABLED BIT(1) 26 + #define AST_IO_VGACRA1_MMIO_ENABLED BIT(2) 31 27 #define AST_IO_VGACRCB_HWC_16BPP BIT(0) /* set: ARGB4444, cleared: 2bpp palette */ 32 28 #define AST_IO_VGACRCB_HWC_ENABLED BIT(1) 33 29 34 30 #define AST_IO_VGAIR1_R (0x5A) 35 31 #define AST_IO_VGAIR1_VREFRESH BIT(3) 36 - 37 - #define AST_IO_VGAMR_R (0x4C) 38 32 39 33 /* 40 34 * Display Transmitter Type
+17
drivers/gpu/drm/bridge/Kconfig
··· 12 12 help 13 13 DRM bridge wrapper of DRM panels 14 14 15 + config DRM_AUX_BRIDGE 16 + tristate 17 + depends on DRM_BRIDGE && OF 18 + select AUXILIARY_BUS 19 + select DRM_PANEL_BRIDGE 20 + help 21 + Simple transparent bridge that is used by several non-DRM drivers to 22 + build bridges chain. 23 + 24 + config DRM_AUX_HPD_BRIDGE 25 + tristate 26 + depends on DRM_BRIDGE && OF 27 + select AUXILIARY_BUS 28 + help 29 + Simple bridge that terminates the bridge chain and provides HPD 30 + support. 31 + 15 32 menu "Display Interface Bridges" 16 33 depends on DRM && DRM_BRIDGE 17 34
+2
drivers/gpu/drm/bridge/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 + obj-$(CONFIG_DRM_AUX_BRIDGE) += aux-bridge.o 3 + obj-$(CONFIG_DRM_AUX_HPD_BRIDGE) += aux-hpd-bridge.o 2 4 obj-$(CONFIG_DRM_CHIPONE_ICN6211) += chipone-icn6211.o 3 5 obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o 4 6 obj-$(CONFIG_DRM_CROS_EC_ANX7688) += cros-ec-anx7688.o
+36 -18
drivers/gpu/drm/bridge/analogix/anx7625.c
··· 1298 1298 XTAL_FRQ_SEL, XTAL_FRQ_27M); 1299 1299 } 1300 1300 1301 + static int anx7625_hpd_timer_config(struct anx7625_data *ctx) 1302 + { 1303 + int ret; 1304 + 1305 + /* Set irq detect window to 2ms */ 1306 + ret = anx7625_reg_write(ctx, ctx->i2c.tx_p2_client, 1307 + HPD_DET_TIMER_BIT0_7, HPD_TIME & 0xFF); 1308 + ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client, 1309 + HPD_DET_TIMER_BIT8_15, 1310 + (HPD_TIME >> 8) & 0xFF); 1311 + ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client, 1312 + HPD_DET_TIMER_BIT16_23, 1313 + (HPD_TIME >> 16) & 0xFF); 1314 + 1315 + return ret; 1316 + } 1317 + 1318 + static int anx7625_read_hpd_gpio_config_status(struct anx7625_data *ctx) 1319 + { 1320 + return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, GPIO_CTRL_2); 1321 + } 1322 + 1301 1323 static void anx7625_disable_pd_protocol(struct anx7625_data *ctx) 1302 1324 { 1303 1325 struct device *dev = ctx->dev; 1304 - int ret; 1326 + int ret, val; 1305 1327 1306 1328 /* Reset main ocm */ 1307 1329 ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client, 0x88, 0x40); ··· 1337 1315 DRM_DEV_DEBUG_DRIVER(dev, "disable PD feature fail.\n"); 1338 1316 else 1339 1317 DRM_DEV_DEBUG_DRIVER(dev, "disable PD feature succeeded.\n"); 1318 + 1319 + /* 1320 + * Make sure the HPD GPIO already be configured after OCM release before 1321 + * setting HPD detect window register. Here we poll the status register 1322 + * at maximum 40ms, then config HPD irq detect window register 1323 + */ 1324 + readx_poll_timeout(anx7625_read_hpd_gpio_config_status, 1325 + ctx, val, 1326 + ((val & HPD_SOURCE) || (val < 0)), 1327 + 2000, 2000 * 20); 1328 + 1329 + /* Set HPD irq detect window to 2ms */ 1330 + anx7625_hpd_timer_config(ctx); 1340 1331 } 1341 1332 1342 1333 static int anx7625_ocm_loading_check(struct anx7625_data *ctx) ··· 1472 1437 1473 1438 static int anx7625_read_hpd_status_p0(struct anx7625_data *ctx) 1474 1439 { 1475 - int ret; 1476 - 1477 - /* Set irq detect window to 2ms */ 1478 - ret = anx7625_reg_write(ctx, ctx->i2c.tx_p2_client, 1479 - HPD_DET_TIMER_BIT0_7, HPD_TIME & 0xFF); 1480 - ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client, 1481 - HPD_DET_TIMER_BIT8_15, 1482 - (HPD_TIME >> 8) & 0xFF); 1483 - ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p2_client, 1484 - HPD_DET_TIMER_BIT16_23, 1485 - (HPD_TIME >> 16) & 0xFF); 1486 - if (ret < 0) 1487 - return ret; 1488 - 1489 1440 return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, SYSTEM_STSTUS); 1490 1441 } 1491 1442 ··· 1484 1463 /* Interrupt mode, no need poll HPD status, just return */ 1485 1464 if (ctx->pdata.intp_irq) 1486 1465 return 0; 1487 - 1488 - /* Delay 200ms for FW HPD de-bounce */ 1489 - msleep(200); 1490 1466 1491 1467 ret = readx_poll_timeout(anx7625_read_hpd_status_p0, 1492 1468 ctx, val,
+4
drivers/gpu/drm/bridge/analogix/anx7625.h
··· 259 259 #define AP_MIPI_RX_EN BIT(5) /* 1: MIPI RX input in 0: no RX in */ 260 260 #define AP_DISABLE_PD BIT(6) 261 261 #define AP_DISABLE_DISPLAY BIT(7) 262 + 263 + #define GPIO_CTRL_2 0x49 264 + #define HPD_SOURCE BIT(6) 265 + 262 266 /***************************************************************/ 263 267 /* Register definition of device address 0x84 */ 264 268 #define MIPI_PHY_CONTROL_3 0x03
+140
drivers/gpu/drm/bridge/aux-bridge.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (C) 2023 Linaro Ltd. 4 + * 5 + * Author: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 6 + */ 7 + #include <linux/auxiliary_bus.h> 8 + #include <linux/module.h> 9 + 10 + #include <drm/drm_bridge.h> 11 + #include <drm/bridge/aux-bridge.h> 12 + 13 + static DEFINE_IDA(drm_aux_bridge_ida); 14 + 15 + static void drm_aux_bridge_release(struct device *dev) 16 + { 17 + struct auxiliary_device *adev = to_auxiliary_dev(dev); 18 + 19 + ida_free(&drm_aux_bridge_ida, adev->id); 20 + 21 + kfree(adev); 22 + } 23 + 24 + static void drm_aux_bridge_unregister_adev(void *_adev) 25 + { 26 + struct auxiliary_device *adev = _adev; 27 + 28 + auxiliary_device_delete(adev); 29 + auxiliary_device_uninit(adev); 30 + } 31 + 32 + /** 33 + * drm_aux_bridge_register - Create a simple bridge device to link the chain 34 + * @parent: device instance providing this bridge 35 + * 36 + * Creates a simple DRM bridge that doesn't implement any drm_bridge 37 + * operations. Such bridges merely fill a place in the bridge chain linking 38 + * surrounding DRM bridges. 39 + * 40 + * Return: zero on success, negative error code on failure 41 + */ 42 + int drm_aux_bridge_register(struct device *parent) 43 + { 44 + struct auxiliary_device *adev; 45 + int ret; 46 + 47 + adev = kzalloc(sizeof(*adev), GFP_KERNEL); 48 + if (!adev) 49 + return -ENOMEM; 50 + 51 + ret = ida_alloc(&drm_aux_bridge_ida, GFP_KERNEL); 52 + if (ret < 0) { 53 + kfree(adev); 54 + return ret; 55 + } 56 + 57 + adev->id = ret; 58 + adev->name = "aux_bridge"; 59 + adev->dev.parent = parent; 60 + adev->dev.of_node = parent->of_node; 61 + adev->dev.release = drm_aux_bridge_release; 62 + 63 + ret = auxiliary_device_init(adev); 64 + if (ret) { 65 + ida_free(&drm_aux_bridge_ida, adev->id); 66 + kfree(adev); 67 + return ret; 68 + } 69 + 70 + ret = auxiliary_device_add(adev); 71 + if (ret) { 72 + auxiliary_device_uninit(adev); 73 + return ret; 74 + } 75 + 76 + return devm_add_action_or_reset(parent, drm_aux_bridge_unregister_adev, adev); 77 + } 78 + EXPORT_SYMBOL_GPL(drm_aux_bridge_register); 79 + 80 + struct drm_aux_bridge_data { 81 + struct drm_bridge bridge; 82 + struct drm_bridge *next_bridge; 83 + struct device *dev; 84 + }; 85 + 86 + static int drm_aux_bridge_attach(struct drm_bridge *bridge, 87 + enum drm_bridge_attach_flags flags) 88 + { 89 + struct drm_aux_bridge_data *data; 90 + 91 + if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) 92 + return -EINVAL; 93 + 94 + data = container_of(bridge, struct drm_aux_bridge_data, bridge); 95 + 96 + return drm_bridge_attach(bridge->encoder, data->next_bridge, bridge, 97 + DRM_BRIDGE_ATTACH_NO_CONNECTOR); 98 + } 99 + 100 + static const struct drm_bridge_funcs drm_aux_bridge_funcs = { 101 + .attach = drm_aux_bridge_attach, 102 + }; 103 + 104 + static int drm_aux_bridge_probe(struct auxiliary_device *auxdev, 105 + const struct auxiliary_device_id *id) 106 + { 107 + struct drm_aux_bridge_data *data; 108 + 109 + data = devm_kzalloc(&auxdev->dev, sizeof(*data), GFP_KERNEL); 110 + if (!data) 111 + return -ENOMEM; 112 + 113 + data->dev = &auxdev->dev; 114 + data->next_bridge = devm_drm_of_get_bridge(&auxdev->dev, auxdev->dev.of_node, 0, 0); 115 + if (IS_ERR(data->next_bridge)) 116 + return dev_err_probe(&auxdev->dev, PTR_ERR(data->next_bridge), 117 + "failed to acquire drm_bridge\n"); 118 + 119 + data->bridge.funcs = &drm_aux_bridge_funcs; 120 + data->bridge.of_node = data->dev->of_node; 121 + 122 + return devm_drm_bridge_add(data->dev, &data->bridge); 123 + } 124 + 125 + static const struct auxiliary_device_id drm_aux_bridge_table[] = { 126 + { .name = KBUILD_MODNAME ".aux_bridge" }, 127 + {}, 128 + }; 129 + MODULE_DEVICE_TABLE(auxiliary, drm_aux_bridge_table); 130 + 131 + static struct auxiliary_driver drm_aux_bridge_drv = { 132 + .name = "aux_bridge", 133 + .id_table = drm_aux_bridge_table, 134 + .probe = drm_aux_bridge_probe, 135 + }; 136 + module_auxiliary_driver(drm_aux_bridge_drv); 137 + 138 + MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>"); 139 + MODULE_DESCRIPTION("DRM transparent bridge"); 140 + MODULE_LICENSE("GPL");
+163
drivers/gpu/drm/bridge/aux-hpd-bridge.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (C) 2023 Linaro Ltd. 4 + * 5 + * Author: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 6 + */ 7 + #include <linux/auxiliary_bus.h> 8 + #include <linux/module.h> 9 + #include <linux/of_device.h> 10 + 11 + #include <drm/drm_bridge.h> 12 + #include <drm/bridge/aux-bridge.h> 13 + 14 + static DEFINE_IDA(drm_aux_hpd_bridge_ida); 15 + 16 + struct drm_aux_hpd_bridge_data { 17 + struct drm_bridge bridge; 18 + struct device *dev; 19 + }; 20 + 21 + static void drm_aux_hpd_bridge_release(struct device *dev) 22 + { 23 + struct auxiliary_device *adev = to_auxiliary_dev(dev); 24 + 25 + ida_free(&drm_aux_hpd_bridge_ida, adev->id); 26 + 27 + of_node_put(adev->dev.platform_data); 28 + 29 + kfree(adev); 30 + } 31 + 32 + static void drm_aux_hpd_bridge_unregister_adev(void *_adev) 33 + { 34 + struct auxiliary_device *adev = _adev; 35 + 36 + auxiliary_device_delete(adev); 37 + auxiliary_device_uninit(adev); 38 + } 39 + 40 + /** 41 + * drm_dp_hpd_bridge_register - Create a simple HPD DisplayPort bridge 42 + * @parent: device instance providing this bridge 43 + * @np: device node pointer corresponding to this bridge instance 44 + * 45 + * Creates a simple DRM bridge with the type set to 46 + * DRM_MODE_CONNECTOR_DisplayPort, which terminates the bridge chain and is 47 + * able to send the HPD events. 48 + * 49 + * Return: device instance that will handle created bridge or an error code 50 + * encoded into the pointer. 51 + */ 52 + struct device *drm_dp_hpd_bridge_register(struct device *parent, 53 + struct device_node *np) 54 + { 55 + struct auxiliary_device *adev; 56 + int ret; 57 + 58 + adev = kzalloc(sizeof(*adev), GFP_KERNEL); 59 + if (!adev) 60 + return ERR_PTR(-ENOMEM); 61 + 62 + ret = ida_alloc(&drm_aux_hpd_bridge_ida, GFP_KERNEL); 63 + if (ret < 0) { 64 + kfree(adev); 65 + return ERR_PTR(ret); 66 + } 67 + 68 + adev->id = ret; 69 + adev->name = "dp_hpd_bridge"; 70 + adev->dev.parent = parent; 71 + adev->dev.of_node = parent->of_node; 72 + adev->dev.release = drm_aux_hpd_bridge_release; 73 + adev->dev.platform_data = np; 74 + 75 + ret = auxiliary_device_init(adev); 76 + if (ret) { 77 + ida_free(&drm_aux_hpd_bridge_ida, adev->id); 78 + kfree(adev); 79 + return ERR_PTR(ret); 80 + } 81 + 82 + ret = auxiliary_device_add(adev); 83 + if (ret) { 84 + auxiliary_device_uninit(adev); 85 + return ERR_PTR(ret); 86 + } 87 + 88 + ret = devm_add_action_or_reset(parent, drm_aux_hpd_bridge_unregister_adev, adev); 89 + if (ret) 90 + return ERR_PTR(ret); 91 + 92 + return &adev->dev; 93 + } 94 + EXPORT_SYMBOL_GPL(drm_dp_hpd_bridge_register); 95 + 96 + /** 97 + * drm_aux_hpd_bridge_notify - notify hot plug detection events 98 + * @dev: device created for the HPD bridge 99 + * @status: output connection status 100 + * 101 + * A wrapper around drm_bridge_hpd_notify() that is used to report hot plug 102 + * detection events for bridges created via drm_dp_hpd_bridge_register(). 103 + * 104 + * This function shall be called in a context that can sleep. 105 + */ 106 + void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) 107 + { 108 + struct auxiliary_device *adev = to_auxiliary_dev(dev); 109 + struct drm_aux_hpd_bridge_data *data = auxiliary_get_drvdata(adev); 110 + 111 + if (!data) 112 + return; 113 + 114 + drm_bridge_hpd_notify(&data->bridge, status); 115 + } 116 + EXPORT_SYMBOL_GPL(drm_aux_hpd_bridge_notify); 117 + 118 + static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge, 119 + enum drm_bridge_attach_flags flags) 120 + { 121 + return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL; 122 + } 123 + 124 + static const struct drm_bridge_funcs drm_aux_hpd_bridge_funcs = { 125 + .attach = drm_aux_hpd_bridge_attach, 126 + }; 127 + 128 + static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev, 129 + const struct auxiliary_device_id *id) 130 + { 131 + struct drm_aux_hpd_bridge_data *data; 132 + 133 + data = devm_kzalloc(&auxdev->dev, sizeof(*data), GFP_KERNEL); 134 + if (!data) 135 + return -ENOMEM; 136 + 137 + data->dev = &auxdev->dev; 138 + data->bridge.funcs = &drm_aux_hpd_bridge_funcs; 139 + data->bridge.of_node = dev_get_platdata(data->dev); 140 + data->bridge.ops = DRM_BRIDGE_OP_HPD; 141 + data->bridge.type = id->driver_data; 142 + 143 + auxiliary_set_drvdata(auxdev, data); 144 + 145 + return devm_drm_bridge_add(data->dev, &data->bridge); 146 + } 147 + 148 + static const struct auxiliary_device_id drm_aux_hpd_bridge_table[] = { 149 + { .name = KBUILD_MODNAME ".dp_hpd_bridge", .driver_data = DRM_MODE_CONNECTOR_DisplayPort, }, 150 + {}, 151 + }; 152 + MODULE_DEVICE_TABLE(auxiliary, drm_aux_hpd_bridge_table); 153 + 154 + static struct auxiliary_driver drm_aux_hpd_bridge_drv = { 155 + .name = "aux_hpd_bridge", 156 + .id_table = drm_aux_hpd_bridge_table, 157 + .probe = drm_aux_hpd_bridge_probe, 158 + }; 159 + module_auxiliary_driver(drm_aux_hpd_bridge_drv); 160 + 161 + MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>"); 162 + MODULE_DESCRIPTION("DRM HPD bridge"); 163 + MODULE_LICENSE("GPL");
+2 -1
drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-hdcp.c
··· 403 403 404 404 static int _cdns_mhdp_hdcp_enable(struct cdns_mhdp_device *mhdp, u8 content_type) 405 405 { 406 - int ret, tries = 3; 406 + int ret = -EINVAL; 407 + int tries = 3; 407 408 u32 i; 408 409 409 410 for (i = 0; i < tries; i++) {
+2 -2
drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
··· 226 226 unsigned long fout; 227 227 unsigned long best_fout = 0; 228 228 unsigned int fvco_div; 229 - unsigned int min_n, max_n, n, best_n; 230 - unsigned long m, best_m; 229 + unsigned int min_n, max_n, n, best_n = UINT_MAX; 230 + unsigned long m, best_m = 0; 231 231 unsigned long min_delta = ULONG_MAX; 232 232 unsigned long delta; 233 233 u64 tmp;
+58
drivers/gpu/drm/bridge/lontium-lt8912b.c
··· 43 43 44 44 struct videomode mode; 45 45 46 + struct regulator_bulk_data supplies[7]; 47 + 46 48 u8 data_lanes; 47 49 bool is_power_on; 48 50 }; ··· 259 257 260 258 static int lt8912_hard_power_on(struct lt8912 *lt) 261 259 { 260 + int ret; 261 + 262 + ret = regulator_bulk_enable(ARRAY_SIZE(lt->supplies), lt->supplies); 263 + if (ret) 264 + return ret; 265 + 262 266 gpiod_set_value_cansleep(lt->gp_reset, 0); 263 267 msleep(20); 264 268 ··· 275 267 { 276 268 gpiod_set_value_cansleep(lt->gp_reset, 1); 277 269 msleep(20); 270 + 271 + regulator_bulk_disable(ARRAY_SIZE(lt->supplies), lt->supplies); 272 + 278 273 lt->is_power_on = false; 279 274 } 280 275 ··· 645 634 .get_edid = lt8912_bridge_get_edid, 646 635 }; 647 636 637 + static int lt8912_bridge_resume(struct device *dev) 638 + { 639 + struct lt8912 *lt = dev_get_drvdata(dev); 640 + int ret; 641 + 642 + ret = lt8912_hard_power_on(lt); 643 + if (ret) 644 + return ret; 645 + 646 + ret = lt8912_soft_power_on(lt); 647 + if (ret) 648 + return ret; 649 + 650 + return lt8912_video_on(lt); 651 + } 652 + 653 + static int lt8912_bridge_suspend(struct device *dev) 654 + { 655 + struct lt8912 *lt = dev_get_drvdata(dev); 656 + 657 + lt8912_hard_power_off(lt); 658 + 659 + return 0; 660 + } 661 + 662 + static DEFINE_SIMPLE_DEV_PM_OPS(lt8912_bridge_pm_ops, lt8912_bridge_suspend, lt8912_bridge_resume); 663 + 664 + static int lt8912_get_regulators(struct lt8912 *lt) 665 + { 666 + unsigned int i; 667 + const char * const supply_names[] = { 668 + "vdd", "vccmipirx", "vccsysclk", "vcclvdstx", 669 + "vcchdmitx", "vcclvdspll", "vcchdmipll" 670 + }; 671 + 672 + for (i = 0; i < ARRAY_SIZE(lt->supplies); i++) 673 + lt->supplies[i].supply = supply_names[i]; 674 + 675 + return devm_regulator_bulk_get(lt->dev, ARRAY_SIZE(lt->supplies), 676 + lt->supplies); 677 + } 678 + 648 679 static int lt8912_parse_dt(struct lt8912 *lt) 649 680 { 650 681 struct gpio_desc *gp_reset; ··· 737 684 ret = -EINVAL; 738 685 goto err_free_host_node; 739 686 } 687 + 688 + ret = lt8912_get_regulators(lt); 689 + if (ret) 690 + goto err_free_host_node; 740 691 741 692 of_node_put(port_node); 742 693 return 0; ··· 827 770 .driver = { 828 771 .name = "lt8912", 829 772 .of_match_table = lt8912_dt_match, 773 + .pm = pm_sleep_ptr(&lt8912_bridge_pm_ops), 830 774 }, 831 775 .probe = lt8912_probe, 832 776 .remove = lt8912_remove,
+3 -3
drivers/gpu/drm/bridge/nxp-ptn3460.c
··· 54 54 int ret; 55 55 56 56 ret = i2c_master_send(ptn_bridge->client, &addr, 1); 57 - if (ret <= 0) { 57 + if (ret < 0) { 58 58 DRM_ERROR("Failed to send i2c command, ret=%d\n", ret); 59 59 return ret; 60 60 } 61 61 62 62 ret = i2c_master_recv(ptn_bridge->client, buf, len); 63 - if (ret <= 0) { 63 + if (ret < 0) { 64 64 DRM_ERROR("Failed to recv i2c data, ret=%d\n", ret); 65 65 return ret; 66 66 } ··· 78 78 buf[1] = val; 79 79 80 80 ret = i2c_master_send(ptn_bridge->client, buf, ARRAY_SIZE(buf)); 81 - if (ret <= 0) { 81 + if (ret < 0) { 82 82 DRM_ERROR("Failed to send i2c command, ret=%d\n", ret); 83 83 return ret; 84 84 }
+1 -1
drivers/gpu/drm/bridge/tc358767.c
··· 2273 2273 } else { 2274 2274 if (tc->hpd_pin < 0 || tc->hpd_pin > 1) { 2275 2275 dev_err(dev, "failed to parse HPD number\n"); 2276 - return ret; 2276 + return -EINVAL; 2277 2277 } 2278 2278 } 2279 2279
+2 -4
drivers/gpu/drm/bridge/ti-sn65dsi86.c
··· 1413 1413 int ret; 1414 1414 1415 1415 if (!pdata->pwm_enabled) { 1416 - ret = pm_runtime_get_sync(pdata->dev); 1417 - if (ret < 0) { 1418 - pm_runtime_put_sync(pdata->dev); 1416 + ret = pm_runtime_resume_and_get(pdata->dev); 1417 + if (ret < 0) 1419 1418 return ret; 1420 - } 1421 1419 } 1422 1420 1423 1421 if (state->enabled) {
-451
drivers/gpu/drm/drm_agpsupport.c
··· 1 - /* 2 - * \file drm_agpsupport.c 3 - * DRM support for AGP/GART backend 4 - * 5 - * \author Rickard E. (Rik) Faith <faith@valinux.com> 6 - * \author Gareth Hughes <gareth@valinux.com> 7 - */ 8 - 9 - /* 10 - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 11 - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 12 - * All Rights Reserved. 13 - * 14 - * Permission is hereby granted, free of charge, to any person obtaining a 15 - * copy of this software and associated documentation files (the "Software"), 16 - * to deal in the Software without restriction, including without limitation 17 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 - * and/or sell copies of the Software, and to permit persons to whom the 19 - * Software is furnished to do so, subject to the following conditions: 20 - * 21 - * The above copyright notice and this permission notice (including the next 22 - * paragraph) shall be included in all copies or substantial portions of the 23 - * Software. 24 - * 25 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 29 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 30 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 31 - * OTHER DEALINGS IN THE SOFTWARE. 32 - */ 33 - 34 - #include <linux/module.h> 35 - #include <linux/pci.h> 36 - #include <linux/slab.h> 37 - 38 - #if IS_ENABLED(CONFIG_AGP) 39 - #include <asm/agp.h> 40 - #endif 41 - 42 - #include <drm/drm_device.h> 43 - #include <drm/drm_drv.h> 44 - #include <drm/drm_file.h> 45 - #include <drm/drm_print.h> 46 - 47 - #include "drm_legacy.h" 48 - 49 - #if IS_ENABLED(CONFIG_AGP) 50 - 51 - /* 52 - * Get AGP information. 53 - * 54 - * \return zero on success or a negative number on failure. 55 - * 56 - * Verifies the AGP device has been initialized and acquired and fills in the 57 - * drm_agp_info structure with the information in drm_agp_head::agp_info. 58 - */ 59 - int drm_legacy_agp_info(struct drm_device *dev, struct drm_agp_info *info) 60 - { 61 - struct agp_kern_info *kern; 62 - 63 - if (!dev->agp || !dev->agp->acquired) 64 - return -EINVAL; 65 - 66 - kern = &dev->agp->agp_info; 67 - info->agp_version_major = kern->version.major; 68 - info->agp_version_minor = kern->version.minor; 69 - info->mode = kern->mode; 70 - info->aperture_base = kern->aper_base; 71 - info->aperture_size = kern->aper_size * 1024 * 1024; 72 - info->memory_allowed = kern->max_memory << PAGE_SHIFT; 73 - info->memory_used = kern->current_memory << PAGE_SHIFT; 74 - info->id_vendor = kern->device->vendor; 75 - info->id_device = kern->device->device; 76 - 77 - return 0; 78 - } 79 - EXPORT_SYMBOL(drm_legacy_agp_info); 80 - 81 - int drm_legacy_agp_info_ioctl(struct drm_device *dev, void *data, 82 - struct drm_file *file_priv) 83 - { 84 - struct drm_agp_info *info = data; 85 - int err; 86 - 87 - err = drm_legacy_agp_info(dev, info); 88 - if (err) 89 - return err; 90 - 91 - return 0; 92 - } 93 - 94 - /* 95 - * Acquire the AGP device. 96 - * 97 - * \param dev DRM device that is to acquire AGP. 98 - * \return zero on success or a negative number on failure. 99 - * 100 - * Verifies the AGP device hasn't been acquired before and calls 101 - * \c agp_backend_acquire. 102 - */ 103 - int drm_legacy_agp_acquire(struct drm_device *dev) 104 - { 105 - struct pci_dev *pdev = to_pci_dev(dev->dev); 106 - 107 - if (!dev->agp) 108 - return -ENODEV; 109 - if (dev->agp->acquired) 110 - return -EBUSY; 111 - dev->agp->bridge = agp_backend_acquire(pdev); 112 - if (!dev->agp->bridge) 113 - return -ENODEV; 114 - dev->agp->acquired = 1; 115 - return 0; 116 - } 117 - EXPORT_SYMBOL(drm_legacy_agp_acquire); 118 - 119 - /* 120 - * Acquire the AGP device (ioctl). 121 - * 122 - * \return zero on success or a negative number on failure. 123 - * 124 - * Verifies the AGP device hasn't been acquired before and calls 125 - * \c agp_backend_acquire. 126 - */ 127 - int drm_legacy_agp_acquire_ioctl(struct drm_device *dev, void *data, 128 - struct drm_file *file_priv) 129 - { 130 - return drm_legacy_agp_acquire((struct drm_device *)file_priv->minor->dev); 131 - } 132 - 133 - /* 134 - * Release the AGP device. 135 - * 136 - * \param dev DRM device that is to release AGP. 137 - * \return zero on success or a negative number on failure. 138 - * 139 - * Verifies the AGP device has been acquired and calls \c agp_backend_release. 140 - */ 141 - int drm_legacy_agp_release(struct drm_device *dev) 142 - { 143 - if (!dev->agp || !dev->agp->acquired) 144 - return -EINVAL; 145 - agp_backend_release(dev->agp->bridge); 146 - dev->agp->acquired = 0; 147 - return 0; 148 - } 149 - EXPORT_SYMBOL(drm_legacy_agp_release); 150 - 151 - int drm_legacy_agp_release_ioctl(struct drm_device *dev, void *data, 152 - struct drm_file *file_priv) 153 - { 154 - return drm_legacy_agp_release(dev); 155 - } 156 - 157 - /* 158 - * Enable the AGP bus. 159 - * 160 - * \param dev DRM device that has previously acquired AGP. 161 - * \param mode Requested AGP mode. 162 - * \return zero on success or a negative number on failure. 163 - * 164 - * Verifies the AGP device has been acquired but not enabled, and calls 165 - * \c agp_enable. 166 - */ 167 - int drm_legacy_agp_enable(struct drm_device *dev, struct drm_agp_mode mode) 168 - { 169 - if (!dev->agp || !dev->agp->acquired) 170 - return -EINVAL; 171 - 172 - dev->agp->mode = mode.mode; 173 - agp_enable(dev->agp->bridge, mode.mode); 174 - dev->agp->enabled = 1; 175 - return 0; 176 - } 177 - EXPORT_SYMBOL(drm_legacy_agp_enable); 178 - 179 - int drm_legacy_agp_enable_ioctl(struct drm_device *dev, void *data, 180 - struct drm_file *file_priv) 181 - { 182 - struct drm_agp_mode *mode = data; 183 - 184 - return drm_legacy_agp_enable(dev, *mode); 185 - } 186 - 187 - /* 188 - * Allocate AGP memory. 189 - * 190 - * \return zero on success or a negative number on failure. 191 - * 192 - * Verifies the AGP device is present and has been acquired, allocates the 193 - * memory via agp_allocate_memory() and creates a drm_agp_mem entry for it. 194 - */ 195 - int drm_legacy_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request) 196 - { 197 - struct drm_agp_mem *entry; 198 - struct agp_memory *memory; 199 - unsigned long pages; 200 - u32 type; 201 - 202 - if (!dev->agp || !dev->agp->acquired) 203 - return -EINVAL; 204 - entry = kzalloc(sizeof(*entry), GFP_KERNEL); 205 - if (!entry) 206 - return -ENOMEM; 207 - 208 - pages = DIV_ROUND_UP(request->size, PAGE_SIZE); 209 - type = (u32) request->type; 210 - memory = agp_allocate_memory(dev->agp->bridge, pages, type); 211 - if (!memory) { 212 - kfree(entry); 213 - return -ENOMEM; 214 - } 215 - 216 - entry->handle = (unsigned long)memory->key + 1; 217 - entry->memory = memory; 218 - entry->bound = 0; 219 - entry->pages = pages; 220 - list_add(&entry->head, &dev->agp->memory); 221 - 222 - request->handle = entry->handle; 223 - request->physical = memory->physical; 224 - 225 - return 0; 226 - } 227 - EXPORT_SYMBOL(drm_legacy_agp_alloc); 228 - 229 - 230 - int drm_legacy_agp_alloc_ioctl(struct drm_device *dev, void *data, 231 - struct drm_file *file_priv) 232 - { 233 - struct drm_agp_buffer *request = data; 234 - 235 - return drm_legacy_agp_alloc(dev, request); 236 - } 237 - 238 - /* 239 - * Search for the AGP memory entry associated with a handle. 240 - * 241 - * \param dev DRM device structure. 242 - * \param handle AGP memory handle. 243 - * \return pointer to the drm_agp_mem structure associated with \p handle. 244 - * 245 - * Walks through drm_agp_head::memory until finding a matching handle. 246 - */ 247 - static struct drm_agp_mem *drm_legacy_agp_lookup_entry(struct drm_device *dev, 248 - unsigned long handle) 249 - { 250 - struct drm_agp_mem *entry; 251 - 252 - list_for_each_entry(entry, &dev->agp->memory, head) { 253 - if (entry->handle == handle) 254 - return entry; 255 - } 256 - return NULL; 257 - } 258 - 259 - /* 260 - * Unbind AGP memory from the GATT (ioctl). 261 - * 262 - * \return zero on success or a negative number on failure. 263 - * 264 - * Verifies the AGP device is present and acquired, looks-up the AGP memory 265 - * entry and passes it to the unbind_agp() function. 266 - */ 267 - int drm_legacy_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request) 268 - { 269 - struct drm_agp_mem *entry; 270 - int ret; 271 - 272 - if (!dev->agp || !dev->agp->acquired) 273 - return -EINVAL; 274 - entry = drm_legacy_agp_lookup_entry(dev, request->handle); 275 - if (!entry || !entry->bound) 276 - return -EINVAL; 277 - ret = agp_unbind_memory(entry->memory); 278 - if (ret == 0) 279 - entry->bound = 0; 280 - return ret; 281 - } 282 - EXPORT_SYMBOL(drm_legacy_agp_unbind); 283 - 284 - 285 - int drm_legacy_agp_unbind_ioctl(struct drm_device *dev, void *data, 286 - struct drm_file *file_priv) 287 - { 288 - struct drm_agp_binding *request = data; 289 - 290 - return drm_legacy_agp_unbind(dev, request); 291 - } 292 - 293 - /* 294 - * Bind AGP memory into the GATT (ioctl) 295 - * 296 - * \return zero on success or a negative number on failure. 297 - * 298 - * Verifies the AGP device is present and has been acquired and that no memory 299 - * is currently bound into the GATT. Looks-up the AGP memory entry and passes 300 - * it to bind_agp() function. 301 - */ 302 - int drm_legacy_agp_bind(struct drm_device *dev, struct drm_agp_binding *request) 303 - { 304 - struct drm_agp_mem *entry; 305 - int retcode; 306 - int page; 307 - 308 - if (!dev->agp || !dev->agp->acquired) 309 - return -EINVAL; 310 - entry = drm_legacy_agp_lookup_entry(dev, request->handle); 311 - if (!entry || entry->bound) 312 - return -EINVAL; 313 - page = DIV_ROUND_UP(request->offset, PAGE_SIZE); 314 - retcode = agp_bind_memory(entry->memory, page); 315 - if (retcode) 316 - return retcode; 317 - entry->bound = dev->agp->base + (page << PAGE_SHIFT); 318 - DRM_DEBUG("base = 0x%lx entry->bound = 0x%lx\n", 319 - dev->agp->base, entry->bound); 320 - return 0; 321 - } 322 - EXPORT_SYMBOL(drm_legacy_agp_bind); 323 - 324 - 325 - int drm_legacy_agp_bind_ioctl(struct drm_device *dev, void *data, 326 - struct drm_file *file_priv) 327 - { 328 - struct drm_agp_binding *request = data; 329 - 330 - return drm_legacy_agp_bind(dev, request); 331 - } 332 - 333 - /* 334 - * Free AGP memory (ioctl). 335 - * 336 - * \return zero on success or a negative number on failure. 337 - * 338 - * Verifies the AGP device is present and has been acquired and looks up the 339 - * AGP memory entry. If the memory is currently bound, unbind it via 340 - * unbind_agp(). Frees it via free_agp() as well as the entry itself 341 - * and unlinks from the doubly linked list it's inserted in. 342 - */ 343 - int drm_legacy_agp_free(struct drm_device *dev, struct drm_agp_buffer *request) 344 - { 345 - struct drm_agp_mem *entry; 346 - 347 - if (!dev->agp || !dev->agp->acquired) 348 - return -EINVAL; 349 - entry = drm_legacy_agp_lookup_entry(dev, request->handle); 350 - if (!entry) 351 - return -EINVAL; 352 - if (entry->bound) 353 - agp_unbind_memory(entry->memory); 354 - 355 - list_del(&entry->head); 356 - 357 - agp_free_memory(entry->memory); 358 - kfree(entry); 359 - return 0; 360 - } 361 - EXPORT_SYMBOL(drm_legacy_agp_free); 362 - 363 - 364 - int drm_legacy_agp_free_ioctl(struct drm_device *dev, void *data, 365 - struct drm_file *file_priv) 366 - { 367 - struct drm_agp_buffer *request = data; 368 - 369 - return drm_legacy_agp_free(dev, request); 370 - } 371 - 372 - /* 373 - * Initialize the AGP resources. 374 - * 375 - * \return pointer to a drm_agp_head structure. 376 - * 377 - * Gets the drm_agp_t structure which is made available by the agpgart module 378 - * via the inter_module_* functions. Creates and initializes a drm_agp_head 379 - * structure. 380 - * 381 - * Note that final cleanup of the kmalloced structure is directly done in 382 - * drm_pci_agp_destroy. 383 - */ 384 - struct drm_agp_head *drm_legacy_agp_init(struct drm_device *dev) 385 - { 386 - struct pci_dev *pdev = to_pci_dev(dev->dev); 387 - struct drm_agp_head *head = NULL; 388 - 389 - head = kzalloc(sizeof(*head), GFP_KERNEL); 390 - if (!head) 391 - return NULL; 392 - head->bridge = agp_find_bridge(pdev); 393 - if (!head->bridge) { 394 - head->bridge = agp_backend_acquire(pdev); 395 - if (!head->bridge) { 396 - kfree(head); 397 - return NULL; 398 - } 399 - agp_copy_info(head->bridge, &head->agp_info); 400 - agp_backend_release(head->bridge); 401 - } else { 402 - agp_copy_info(head->bridge, &head->agp_info); 403 - } 404 - if (head->agp_info.chipset == NOT_SUPPORTED) { 405 - kfree(head); 406 - return NULL; 407 - } 408 - INIT_LIST_HEAD(&head->memory); 409 - head->cant_use_aperture = head->agp_info.cant_use_aperture; 410 - head->page_mask = head->agp_info.page_mask; 411 - head->base = head->agp_info.aper_base; 412 - return head; 413 - } 414 - /* Only exported for i810.ko */ 415 - EXPORT_SYMBOL(drm_legacy_agp_init); 416 - 417 - /** 418 - * drm_legacy_agp_clear - Clear AGP resource list 419 - * @dev: DRM device 420 - * 421 - * Iterate over all AGP resources and remove them. But keep the AGP head 422 - * intact so it can still be used. It is safe to call this if AGP is disabled or 423 - * was already removed. 424 - * 425 - * Cleanup is only done for drivers who have DRIVER_LEGACY set. 426 - */ 427 - void drm_legacy_agp_clear(struct drm_device *dev) 428 - { 429 - struct drm_agp_mem *entry, *tempe; 430 - 431 - if (!dev->agp) 432 - return; 433 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 434 - return; 435 - 436 - list_for_each_entry_safe(entry, tempe, &dev->agp->memory, head) { 437 - if (entry->bound) 438 - agp_unbind_memory(entry->memory); 439 - agp_free_memory(entry->memory); 440 - kfree(entry); 441 - } 442 - INIT_LIST_HEAD(&dev->agp->memory); 443 - 444 - if (dev->agp->acquired) 445 - drm_legacy_agp_release(dev); 446 - 447 - dev->agp->acquired = 0; 448 - dev->agp->enabled = 0; 449 - } 450 - 451 - #endif
+9
drivers/gpu/drm/drm_atomic.c
··· 1773 1773 struct drm_crtc *crtc; 1774 1774 struct drm_connector *connector; 1775 1775 struct drm_connector_list_iter conn_iter; 1776 + struct drm_private_obj *obj; 1776 1777 1777 1778 if (!drm_drv_uses_atomic_modeset(dev)) 1778 1779 return; ··· 1802 1801 if (take_locks) 1803 1802 drm_modeset_unlock(&dev->mode_config.connection_mutex); 1804 1803 drm_connector_list_iter_end(&conn_iter); 1804 + 1805 + list_for_each_entry(obj, &config->privobj_list, head) { 1806 + if (take_locks) 1807 + drm_modeset_lock(&obj->lock, NULL); 1808 + drm_atomic_private_obj_print_state(p, obj->state); 1809 + if (take_locks) 1810 + drm_modeset_unlock(&obj->lock); 1811 + } 1805 1812 } 1806 1813 1807 1814 /**
+14
drivers/gpu/drm/drm_atomic_state_helper.c
··· 275 275 plane_state->normalized_zpos = val; 276 276 } 277 277 } 278 + 279 + if (plane->hotspot_x_property) { 280 + if (!drm_object_property_get_default_value(&plane->base, 281 + plane->hotspot_x_property, 282 + &val)) 283 + plane_state->hotspot_x = val; 284 + } 285 + 286 + if (plane->hotspot_y_property) { 287 + if (!drm_object_property_get_default_value(&plane->base, 288 + plane->hotspot_y_property, 289 + &val)) 290 + plane_state->hotspot_y = val; 291 + } 278 292 } 279 293 EXPORT_SYMBOL(__drm_atomic_helper_plane_state_reset); 280 294
+91 -6
drivers/gpu/drm/drm_atomic_uapi.c
··· 593 593 } else if (plane->funcs->atomic_set_property) { 594 594 return plane->funcs->atomic_set_property(plane, state, 595 595 property, val); 596 + } else if (property == plane->hotspot_x_property) { 597 + if (plane->type != DRM_PLANE_TYPE_CURSOR) { 598 + drm_dbg_atomic(plane->dev, 599 + "[PLANE:%d:%s] is not a cursor plane: 0x%llx\n", 600 + plane->base.id, plane->name, val); 601 + return -EINVAL; 602 + } 603 + state->hotspot_x = val; 604 + } else if (property == plane->hotspot_y_property) { 605 + if (plane->type != DRM_PLANE_TYPE_CURSOR) { 606 + drm_dbg_atomic(plane->dev, 607 + "[PLANE:%d:%s] is not a cursor plane: 0x%llx\n", 608 + plane->base.id, plane->name, val); 609 + return -EINVAL; 610 + } 611 + state->hotspot_y = val; 596 612 } else { 597 613 drm_dbg_atomic(plane->dev, 598 614 "[PLANE:%d:%s] unknown property [PROP:%d:%s]\n", ··· 669 653 *val = state->scaling_filter; 670 654 } else if (plane->funcs->atomic_get_property) { 671 655 return plane->funcs->atomic_get_property(plane, state, property, val); 656 + } else if (property == plane->hotspot_x_property) { 657 + *val = state->hotspot_x; 658 + } else if (property == plane->hotspot_y_property) { 659 + *val = state->hotspot_y; 672 660 } else { 673 661 drm_dbg_atomic(dev, 674 662 "[PLANE:%d:%s] unknown property [PROP:%d:%s]\n", ··· 1026 1006 return ret; 1027 1007 } 1028 1008 1009 + static int drm_atomic_check_prop_changes(int ret, uint64_t old_val, uint64_t prop_value, 1010 + struct drm_property *prop) 1011 + { 1012 + if (ret != 0 || old_val != prop_value) { 1013 + drm_dbg_atomic(prop->dev, 1014 + "[PROP:%d:%s] No prop can be changed during async flip\n", 1015 + prop->base.id, prop->name); 1016 + return -EINVAL; 1017 + } 1018 + 1019 + return 0; 1020 + } 1021 + 1029 1022 int drm_atomic_set_property(struct drm_atomic_state *state, 1030 1023 struct drm_file *file_priv, 1031 1024 struct drm_mode_object *obj, 1032 1025 struct drm_property *prop, 1033 - uint64_t prop_value) 1026 + u64 prop_value, 1027 + bool async_flip) 1034 1028 { 1035 1029 struct drm_mode_object *ref; 1030 + u64 old_val; 1036 1031 int ret; 1037 1032 1038 1033 if (!drm_property_change_valid_get(prop, prop_value, &ref)) ··· 1061 1026 connector_state = drm_atomic_get_connector_state(state, connector); 1062 1027 if (IS_ERR(connector_state)) { 1063 1028 ret = PTR_ERR(connector_state); 1029 + break; 1030 + } 1031 + 1032 + if (async_flip) { 1033 + ret = drm_atomic_connector_get_property(connector, connector_state, 1034 + prop, &old_val); 1035 + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); 1064 1036 break; 1065 1037 } 1066 1038 ··· 1086 1044 break; 1087 1045 } 1088 1046 1047 + if (async_flip) { 1048 + ret = drm_atomic_crtc_get_property(crtc, crtc_state, 1049 + prop, &old_val); 1050 + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); 1051 + break; 1052 + } 1053 + 1089 1054 ret = drm_atomic_crtc_set_property(crtc, 1090 1055 crtc_state, prop, prop_value); 1091 1056 break; ··· 1100 1051 case DRM_MODE_OBJECT_PLANE: { 1101 1052 struct drm_plane *plane = obj_to_plane(obj); 1102 1053 struct drm_plane_state *plane_state; 1054 + struct drm_mode_config *config = &plane->dev->mode_config; 1103 1055 1104 1056 plane_state = drm_atomic_get_plane_state(state, plane); 1105 1057 if (IS_ERR(plane_state)) { 1106 1058 ret = PTR_ERR(plane_state); 1059 + break; 1060 + } 1061 + 1062 + if (async_flip && prop != config->prop_fb_id) { 1063 + ret = drm_atomic_plane_get_property(plane, plane_state, 1064 + prop, &old_val); 1065 + ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop); 1066 + break; 1067 + } 1068 + 1069 + if (async_flip && plane_state->plane->type != DRM_PLANE_TYPE_PRIMARY) { 1070 + drm_dbg_atomic(prop->dev, 1071 + "[OBJECT:%d] Only primary planes can be changed during async flip\n", 1072 + obj->id); 1073 + ret = -EINVAL; 1107 1074 break; 1108 1075 } 1109 1076 ··· 1388 1323 kfree(fence_state); 1389 1324 } 1390 1325 1326 + static void 1327 + set_async_flip(struct drm_atomic_state *state) 1328 + { 1329 + struct drm_crtc *crtc; 1330 + struct drm_crtc_state *crtc_state; 1331 + int i; 1332 + 1333 + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { 1334 + crtc_state->async_flip = true; 1335 + } 1336 + } 1337 + 1391 1338 int drm_mode_atomic_ioctl(struct drm_device *dev, 1392 1339 void *data, struct drm_file *file_priv) 1393 1340 { ··· 1414 1337 struct drm_out_fence_state *fence_state; 1415 1338 int ret = 0; 1416 1339 unsigned int i, j, num_fences; 1340 + bool async_flip = false; 1417 1341 1418 1342 /* disallow for drivers not supporting atomic: */ 1419 1343 if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) ··· 1441 1363 } 1442 1364 1443 1365 if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) { 1444 - drm_dbg_atomic(dev, 1445 - "commit failed: invalid flag DRM_MODE_PAGE_FLIP_ASYNC\n"); 1446 - return -EINVAL; 1366 + if (!dev->mode_config.async_page_flip) { 1367 + drm_dbg_atomic(dev, 1368 + "commit failed: DRM_MODE_PAGE_FLIP_ASYNC not supported\n"); 1369 + return -EINVAL; 1370 + } 1371 + 1372 + async_flip = true; 1447 1373 } 1448 1374 1449 1375 /* can't test and expect an event at the same time. */ ··· 1532 1450 goto out; 1533 1451 } 1534 1452 1535 - ret = drm_atomic_set_property(state, file_priv, 1536 - obj, prop, prop_value); 1453 + ret = drm_atomic_set_property(state, file_priv, obj, 1454 + prop, prop_value, async_flip); 1537 1455 if (ret) { 1538 1456 drm_mode_object_put(obj); 1539 1457 goto out; ··· 1549 1467 &num_fences); 1550 1468 if (ret) 1551 1469 goto out; 1470 + 1471 + if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) 1472 + set_async_flip(state); 1552 1473 1553 1474 if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { 1554 1475 ret = drm_atomic_check_only(state);
+1 -7
drivers/gpu/drm/drm_auth.c
··· 37 37 #include <drm/drm_print.h> 38 38 39 39 #include "drm_internal.h" 40 - #include "drm_legacy.h" 41 40 42 41 /** 43 42 * DOC: master and authentication 44 43 * 45 44 * &struct drm_master is used to track groups of clients with open 46 - * primary/legacy device nodes. For every &struct drm_file which has had at 45 + * primary device nodes. For every &struct drm_file which has had at 47 46 * least once successfully became the device master (either through the 48 47 * SET_MASTER IOCTL, or implicitly through opening the primary device node when 49 48 * no one else is the current master that time) there exists one &drm_master. ··· 138 139 return NULL; 139 140 140 141 kref_init(&master->refcount); 141 - drm_master_legacy_init(master); 142 142 idr_init_base(&master->magic_map, 1); 143 143 master->dev = dev; 144 144 ··· 363 365 if (!drm_is_current_master_locked(file_priv)) 364 366 goto out; 365 367 366 - drm_legacy_lock_master_cleanup(dev, master); 367 - 368 368 if (dev->master == file_priv->master) 369 369 drm_drop_master(dev, file_priv); 370 370 out: ··· 424 428 425 429 if (drm_core_check_feature(dev, DRIVER_MODESET)) 426 430 drm_lease_destroy(master); 427 - 428 - drm_legacy_master_rmmaps(dev, master); 429 431 430 432 idr_destroy(&master->magic_map); 431 433 idr_destroy(&master->leases);
-44
drivers/gpu/drm/drm_bridge.c
··· 1347 1347 EXPORT_SYMBOL(of_drm_find_bridge); 1348 1348 #endif 1349 1349 1350 - #ifdef CONFIG_DEBUG_FS 1351 - static int drm_bridge_chains_info(struct seq_file *m, void *data) 1352 - { 1353 - struct drm_debugfs_entry *entry = m->private; 1354 - struct drm_device *dev = entry->dev; 1355 - struct drm_printer p = drm_seq_file_printer(m); 1356 - struct drm_mode_config *config = &dev->mode_config; 1357 - struct drm_encoder *encoder; 1358 - unsigned int bridge_idx = 0; 1359 - 1360 - list_for_each_entry(encoder, &config->encoder_list, head) { 1361 - struct drm_bridge *bridge; 1362 - 1363 - drm_printf(&p, "encoder[%u]\n", encoder->base.id); 1364 - 1365 - drm_for_each_bridge_in_chain(encoder, bridge) { 1366 - drm_printf(&p, "\tbridge[%u] type: %u, ops: %#x", 1367 - bridge_idx, bridge->type, bridge->ops); 1368 - 1369 - #ifdef CONFIG_OF 1370 - if (bridge->of_node) 1371 - drm_printf(&p, ", OF: %pOFfc", bridge->of_node); 1372 - #endif 1373 - 1374 - drm_printf(&p, "\n"); 1375 - 1376 - bridge_idx++; 1377 - } 1378 - } 1379 - 1380 - return 0; 1381 - } 1382 - 1383 - static const struct drm_debugfs_info drm_bridge_debugfs_list[] = { 1384 - { "bridge_chains", drm_bridge_chains_info, 0 }, 1385 - }; 1386 - 1387 - void drm_bridge_debugfs_init(struct drm_device *dev) 1388 - { 1389 - drm_debugfs_add_files(dev, drm_bridge_debugfs_list, 1390 - ARRAY_SIZE(drm_bridge_debugfs_list)); 1391 - } 1392 - #endif 1393 - 1394 1350 MODULE_AUTHOR("Ajay Kumar <ajaykumar.rs@samsung.com>"); 1395 1351 MODULE_DESCRIPTION("DRM bridge infrastructure"); 1396 1352 MODULE_LICENSE("GPL and additional rights");
-6
drivers/gpu/drm/drm_bridge_connector.c
··· 198 198 struct drm_bridge_connector *bridge_connector = 199 199 to_drm_bridge_connector(connector); 200 200 201 - if (bridge_connector->bridge_hpd) { 202 - struct drm_bridge *hpd = bridge_connector->bridge_hpd; 203 - 204 - drm_bridge_hpd_disable(hpd); 205 - } 206 - 207 201 drm_connector_unregister(connector); 208 202 drm_connector_cleanup(connector); 209 203
-1627
drivers/gpu/drm/drm_bufs.c
··· 1 - /* 2 - * Legacy: Generic DRM Buffer Management 3 - * 4 - * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. 5 - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 6 - * All Rights Reserved. 7 - * 8 - * Author: Rickard E. (Rik) Faith <faith@valinux.com> 9 - * Author: Gareth Hughes <gareth@valinux.com> 10 - * 11 - * Permission is hereby granted, free of charge, to any person obtaining a 12 - * copy of this software and associated documentation files (the "Software"), 13 - * to deal in the Software without restriction, including without limitation 14 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15 - * and/or sell copies of the Software, and to permit persons to whom the 16 - * Software is furnished to do so, subject to the following conditions: 17 - * 18 - * The above copyright notice and this permission notice (including the next 19 - * paragraph) shall be included in all copies or substantial portions of the 20 - * Software. 21 - * 22 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 26 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 27 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 - * OTHER DEALINGS IN THE SOFTWARE. 29 - */ 30 - 31 - #include <linux/export.h> 32 - #include <linux/log2.h> 33 - #include <linux/mm.h> 34 - #include <linux/mman.h> 35 - #include <linux/nospec.h> 36 - #include <linux/pci.h> 37 - #include <linux/slab.h> 38 - #include <linux/uaccess.h> 39 - #include <linux/vmalloc.h> 40 - 41 - #include <asm/shmparam.h> 42 - 43 - #include <drm/drm_device.h> 44 - #include <drm/drm_drv.h> 45 - #include <drm/drm_file.h> 46 - #include <drm/drm_print.h> 47 - 48 - #include "drm_legacy.h" 49 - 50 - 51 - static struct drm_map_list *drm_find_matching_map(struct drm_device *dev, 52 - struct drm_local_map *map) 53 - { 54 - struct drm_map_list *entry; 55 - 56 - list_for_each_entry(entry, &dev->maplist, head) { 57 - /* 58 - * Because the kernel-userspace ABI is fixed at a 32-bit offset 59 - * while PCI resources may live above that, we only compare the 60 - * lower 32 bits of the map offset for maps of type 61 - * _DRM_FRAMEBUFFER or _DRM_REGISTERS. 62 - * It is assumed that if a driver have more than one resource 63 - * of each type, the lower 32 bits are different. 64 - */ 65 - if (!entry->map || 66 - map->type != entry->map->type || 67 - entry->master != dev->master) 68 - continue; 69 - switch (map->type) { 70 - case _DRM_SHM: 71 - if (map->flags != _DRM_CONTAINS_LOCK) 72 - break; 73 - return entry; 74 - case _DRM_REGISTERS: 75 - case _DRM_FRAME_BUFFER: 76 - if ((entry->map->offset & 0xffffffff) == 77 - (map->offset & 0xffffffff)) 78 - return entry; 79 - break; 80 - default: /* Make gcc happy */ 81 - break; 82 - } 83 - if (entry->map->offset == map->offset) 84 - return entry; 85 - } 86 - 87 - return NULL; 88 - } 89 - 90 - static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash, 91 - unsigned long user_token, int hashed_handle, int shm) 92 - { 93 - int use_hashed_handle, shift; 94 - unsigned long add; 95 - 96 - #if (BITS_PER_LONG == 64) 97 - use_hashed_handle = ((user_token & 0xFFFFFFFF00000000UL) || hashed_handle); 98 - #elif (BITS_PER_LONG == 32) 99 - use_hashed_handle = hashed_handle; 100 - #else 101 - #error Unsupported long size. Neither 64 nor 32 bits. 102 - #endif 103 - 104 - if (!use_hashed_handle) { 105 - int ret; 106 - 107 - hash->key = user_token >> PAGE_SHIFT; 108 - ret = drm_ht_insert_item(&dev->map_hash, hash); 109 - if (ret != -EINVAL) 110 - return ret; 111 - } 112 - 113 - shift = 0; 114 - add = DRM_MAP_HASH_OFFSET >> PAGE_SHIFT; 115 - if (shm && (SHMLBA > PAGE_SIZE)) { 116 - int bits = ilog2(SHMLBA >> PAGE_SHIFT) + 1; 117 - 118 - /* For shared memory, we have to preserve the SHMLBA 119 - * bits of the eventual vma->vm_pgoff value during 120 - * mmap(). Otherwise we run into cache aliasing problems 121 - * on some platforms. On these platforms, the pgoff of 122 - * a mmap() request is used to pick a suitable virtual 123 - * address for the mmap() region such that it will not 124 - * cause cache aliasing problems. 125 - * 126 - * Therefore, make sure the SHMLBA relevant bits of the 127 - * hash value we use are equal to those in the original 128 - * kernel virtual address. 129 - */ 130 - shift = bits; 131 - add |= ((user_token >> PAGE_SHIFT) & ((1UL << bits) - 1UL)); 132 - } 133 - 134 - return drm_ht_just_insert_please(&dev->map_hash, hash, 135 - user_token, 32 - PAGE_SHIFT - 3, 136 - shift, add); 137 - } 138 - 139 - /* 140 - * Core function to create a range of memory available for mapping by a 141 - * non-root process. 142 - * 143 - * Adjusts the memory offset to its absolute value according to the mapping 144 - * type. Adds the map to the map list drm_device::maplist. Adds MTRR's where 145 - * applicable and if supported by the kernel. 146 - */ 147 - static int drm_addmap_core(struct drm_device *dev, resource_size_t offset, 148 - unsigned int size, enum drm_map_type type, 149 - enum drm_map_flags flags, 150 - struct drm_map_list **maplist) 151 - { 152 - struct drm_local_map *map; 153 - struct drm_map_list *list; 154 - unsigned long user_token; 155 - int ret; 156 - 157 - map = kmalloc(sizeof(*map), GFP_KERNEL); 158 - if (!map) 159 - return -ENOMEM; 160 - 161 - map->offset = offset; 162 - map->size = size; 163 - map->flags = flags; 164 - map->type = type; 165 - 166 - /* Only allow shared memory to be removable since we only keep enough 167 - * book keeping information about shared memory to allow for removal 168 - * when processes fork. 169 - */ 170 - if ((map->flags & _DRM_REMOVABLE) && map->type != _DRM_SHM) { 171 - kfree(map); 172 - return -EINVAL; 173 - } 174 - DRM_DEBUG("offset = 0x%08llx, size = 0x%08lx, type = %d\n", 175 - (unsigned long long)map->offset, map->size, map->type); 176 - 177 - /* page-align _DRM_SHM maps. They are allocated here so there is no security 178 - * hole created by that and it works around various broken drivers that use 179 - * a non-aligned quantity to map the SAREA. --BenH 180 - */ 181 - if (map->type == _DRM_SHM) 182 - map->size = PAGE_ALIGN(map->size); 183 - 184 - if ((map->offset & (~(resource_size_t)PAGE_MASK)) || (map->size & (~PAGE_MASK))) { 185 - kfree(map); 186 - return -EINVAL; 187 - } 188 - map->mtrr = -1; 189 - map->handle = NULL; 190 - 191 - switch (map->type) { 192 - case _DRM_REGISTERS: 193 - case _DRM_FRAME_BUFFER: 194 - #if !defined(__sparc__) && !defined(__alpha__) && !defined(__ia64__) && !defined(__powerpc64__) && !defined(__x86_64__) && !defined(__arm__) 195 - if (map->offset + (map->size-1) < map->offset || 196 - map->offset < virt_to_phys(high_memory)) { 197 - kfree(map); 198 - return -EINVAL; 199 - } 200 - #endif 201 - /* Some drivers preinitialize some maps, without the X Server 202 - * needing to be aware of it. Therefore, we just return success 203 - * when the server tries to create a duplicate map. 204 - */ 205 - list = drm_find_matching_map(dev, map); 206 - if (list != NULL) { 207 - if (list->map->size != map->size) { 208 - DRM_DEBUG("Matching maps of type %d with " 209 - "mismatched sizes, (%ld vs %ld)\n", 210 - map->type, map->size, 211 - list->map->size); 212 - list->map->size = map->size; 213 - } 214 - 215 - kfree(map); 216 - *maplist = list; 217 - return 0; 218 - } 219 - 220 - if (map->type == _DRM_FRAME_BUFFER || 221 - (map->flags & _DRM_WRITE_COMBINING)) { 222 - map->mtrr = 223 - arch_phys_wc_add(map->offset, map->size); 224 - } 225 - if (map->type == _DRM_REGISTERS) { 226 - if (map->flags & _DRM_WRITE_COMBINING) 227 - map->handle = ioremap_wc(map->offset, 228 - map->size); 229 - else 230 - map->handle = ioremap(map->offset, map->size); 231 - if (!map->handle) { 232 - kfree(map); 233 - return -ENOMEM; 234 - } 235 - } 236 - 237 - break; 238 - case _DRM_SHM: 239 - list = drm_find_matching_map(dev, map); 240 - if (list != NULL) { 241 - if (list->map->size != map->size) { 242 - DRM_DEBUG("Matching maps of type %d with " 243 - "mismatched sizes, (%ld vs %ld)\n", 244 - map->type, map->size, list->map->size); 245 - list->map->size = map->size; 246 - } 247 - 248 - kfree(map); 249 - *maplist = list; 250 - return 0; 251 - } 252 - map->handle = vmalloc_user(map->size); 253 - DRM_DEBUG("%lu %d %p\n", 254 - map->size, order_base_2(map->size), map->handle); 255 - if (!map->handle) { 256 - kfree(map); 257 - return -ENOMEM; 258 - } 259 - map->offset = (unsigned long)map->handle; 260 - if (map->flags & _DRM_CONTAINS_LOCK) { 261 - /* Prevent a 2nd X Server from creating a 2nd lock */ 262 - if (dev->master->lock.hw_lock != NULL) { 263 - vfree(map->handle); 264 - kfree(map); 265 - return -EBUSY; 266 - } 267 - dev->sigdata.lock = dev->master->lock.hw_lock = map->handle; /* Pointer to lock */ 268 - } 269 - break; 270 - case _DRM_AGP: { 271 - struct drm_agp_mem *entry; 272 - int valid = 0; 273 - 274 - if (!dev->agp) { 275 - kfree(map); 276 - return -EINVAL; 277 - } 278 - #ifdef __alpha__ 279 - map->offset += dev->hose->mem_space->start; 280 - #endif 281 - /* In some cases (i810 driver), user space may have already 282 - * added the AGP base itself, because dev->agp->base previously 283 - * only got set during AGP enable. So, only add the base 284 - * address if the map's offset isn't already within the 285 - * aperture. 286 - */ 287 - if (map->offset < dev->agp->base || 288 - map->offset > dev->agp->base + 289 - dev->agp->agp_info.aper_size * 1024 * 1024 - 1) { 290 - map->offset += dev->agp->base; 291 - } 292 - map->mtrr = dev->agp->agp_mtrr; /* for getmap */ 293 - 294 - /* This assumes the DRM is in total control of AGP space. 295 - * It's not always the case as AGP can be in the control 296 - * of user space (i.e. i810 driver). So this loop will get 297 - * skipped and we double check that dev->agp->memory is 298 - * actually set as well as being invalid before EPERM'ing 299 - */ 300 - list_for_each_entry(entry, &dev->agp->memory, head) { 301 - if ((map->offset >= entry->bound) && 302 - (map->offset + map->size <= entry->bound + entry->pages * PAGE_SIZE)) { 303 - valid = 1; 304 - break; 305 - } 306 - } 307 - if (!list_empty(&dev->agp->memory) && !valid) { 308 - kfree(map); 309 - return -EPERM; 310 - } 311 - DRM_DEBUG("AGP offset = 0x%08llx, size = 0x%08lx\n", 312 - (unsigned long long)map->offset, map->size); 313 - 314 - break; 315 - } 316 - case _DRM_SCATTER_GATHER: 317 - if (!dev->sg) { 318 - kfree(map); 319 - return -EINVAL; 320 - } 321 - map->offset += (unsigned long)dev->sg->virtual; 322 - break; 323 - case _DRM_CONSISTENT: 324 - /* dma_addr_t is 64bit on i386 with CONFIG_HIGHMEM64G, 325 - * As we're limiting the address to 2^32-1 (or less), 326 - * casting it down to 32 bits is no problem, but we 327 - * need to point to a 64bit variable first. 328 - */ 329 - map->handle = dma_alloc_coherent(dev->dev, 330 - map->size, 331 - &map->offset, 332 - GFP_KERNEL); 333 - if (!map->handle) { 334 - kfree(map); 335 - return -ENOMEM; 336 - } 337 - break; 338 - default: 339 - kfree(map); 340 - return -EINVAL; 341 - } 342 - 343 - list = kzalloc(sizeof(*list), GFP_KERNEL); 344 - if (!list) { 345 - if (map->type == _DRM_REGISTERS) 346 - iounmap(map->handle); 347 - kfree(map); 348 - return -EINVAL; 349 - } 350 - list->map = map; 351 - 352 - mutex_lock(&dev->struct_mutex); 353 - list_add(&list->head, &dev->maplist); 354 - 355 - /* Assign a 32-bit handle */ 356 - /* We do it here so that dev->struct_mutex protects the increment */ 357 - user_token = (map->type == _DRM_SHM) ? (unsigned long)map->handle : 358 - map->offset; 359 - ret = drm_map_handle(dev, &list->hash, user_token, 0, 360 - (map->type == _DRM_SHM)); 361 - if (ret) { 362 - if (map->type == _DRM_REGISTERS) 363 - iounmap(map->handle); 364 - kfree(map); 365 - kfree(list); 366 - mutex_unlock(&dev->struct_mutex); 367 - return ret; 368 - } 369 - 370 - list->user_token = list->hash.key << PAGE_SHIFT; 371 - mutex_unlock(&dev->struct_mutex); 372 - 373 - if (!(map->flags & _DRM_DRIVER)) 374 - list->master = dev->master; 375 - *maplist = list; 376 - return 0; 377 - } 378 - 379 - int drm_legacy_addmap(struct drm_device *dev, resource_size_t offset, 380 - unsigned int size, enum drm_map_type type, 381 - enum drm_map_flags flags, struct drm_local_map **map_ptr) 382 - { 383 - struct drm_map_list *list; 384 - int rc; 385 - 386 - rc = drm_addmap_core(dev, offset, size, type, flags, &list); 387 - if (!rc) 388 - *map_ptr = list->map; 389 - return rc; 390 - } 391 - EXPORT_SYMBOL(drm_legacy_addmap); 392 - 393 - struct drm_local_map *drm_legacy_findmap(struct drm_device *dev, 394 - unsigned int token) 395 - { 396 - struct drm_map_list *_entry; 397 - 398 - list_for_each_entry(_entry, &dev->maplist, head) 399 - if (_entry->user_token == token) 400 - return _entry->map; 401 - return NULL; 402 - } 403 - EXPORT_SYMBOL(drm_legacy_findmap); 404 - 405 - /* 406 - * Ioctl to specify a range of memory that is available for mapping by a 407 - * non-root process. 408 - * 409 - * \param inode device inode. 410 - * \param file_priv DRM file private. 411 - * \param cmd command. 412 - * \param arg pointer to a drm_map structure. 413 - * \return zero on success or a negative value on error. 414 - * 415 - */ 416 - int drm_legacy_addmap_ioctl(struct drm_device *dev, void *data, 417 - struct drm_file *file_priv) 418 - { 419 - struct drm_map *map = data; 420 - struct drm_map_list *maplist; 421 - int err; 422 - 423 - if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP || map->type == _DRM_SHM)) 424 - return -EPERM; 425 - 426 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 427 - return -EOPNOTSUPP; 428 - 429 - err = drm_addmap_core(dev, map->offset, map->size, map->type, 430 - map->flags, &maplist); 431 - 432 - if (err) 433 - return err; 434 - 435 - /* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */ 436 - map->handle = (void *)(unsigned long)maplist->user_token; 437 - 438 - /* 439 - * It appears that there are no users of this value whatsoever -- 440 - * drmAddMap just discards it. Let's not encourage its use. 441 - * (Keeping drm_addmap_core's returned mtrr value would be wrong -- 442 - * it's not a real mtrr index anymore.) 443 - */ 444 - map->mtrr = -1; 445 - 446 - return 0; 447 - } 448 - 449 - /* 450 - * Get a mapping information. 451 - * 452 - * \param inode device inode. 453 - * \param file_priv DRM file private. 454 - * \param cmd command. 455 - * \param arg user argument, pointing to a drm_map structure. 456 - * 457 - * \return zero on success or a negative number on failure. 458 - * 459 - * Searches for the mapping with the specified offset and copies its information 460 - * into userspace 461 - */ 462 - int drm_legacy_getmap_ioctl(struct drm_device *dev, void *data, 463 - struct drm_file *file_priv) 464 - { 465 - struct drm_map *map = data; 466 - struct drm_map_list *r_list = NULL; 467 - struct list_head *list; 468 - int idx; 469 - int i; 470 - 471 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 472 - return -EOPNOTSUPP; 473 - 474 - idx = map->offset; 475 - if (idx < 0) 476 - return -EINVAL; 477 - 478 - i = 0; 479 - mutex_lock(&dev->struct_mutex); 480 - list_for_each(list, &dev->maplist) { 481 - if (i == idx) { 482 - r_list = list_entry(list, struct drm_map_list, head); 483 - break; 484 - } 485 - i++; 486 - } 487 - if (!r_list || !r_list->map) { 488 - mutex_unlock(&dev->struct_mutex); 489 - return -EINVAL; 490 - } 491 - 492 - map->offset = r_list->map->offset; 493 - map->size = r_list->map->size; 494 - map->type = r_list->map->type; 495 - map->flags = r_list->map->flags; 496 - map->handle = (void *)(unsigned long) r_list->user_token; 497 - map->mtrr = arch_phys_wc_index(r_list->map->mtrr); 498 - 499 - mutex_unlock(&dev->struct_mutex); 500 - 501 - return 0; 502 - } 503 - 504 - /* 505 - * Remove a map private from list and deallocate resources if the mapping 506 - * isn't in use. 507 - * 508 - * Searches the map on drm_device::maplist, removes it from the list, see if 509 - * it's being used, and free any associated resource (such as MTRR's) if it's not 510 - * being on use. 511 - * 512 - * \sa drm_legacy_addmap 513 - */ 514 - int drm_legacy_rmmap_locked(struct drm_device *dev, struct drm_local_map *map) 515 - { 516 - struct drm_map_list *r_list = NULL, *list_t; 517 - int found = 0; 518 - struct drm_master *master; 519 - 520 - /* Find the list entry for the map and remove it */ 521 - list_for_each_entry_safe(r_list, list_t, &dev->maplist, head) { 522 - if (r_list->map == map) { 523 - master = r_list->master; 524 - list_del(&r_list->head); 525 - drm_ht_remove_key(&dev->map_hash, 526 - r_list->user_token >> PAGE_SHIFT); 527 - kfree(r_list); 528 - found = 1; 529 - break; 530 - } 531 - } 532 - 533 - if (!found) 534 - return -EINVAL; 535 - 536 - switch (map->type) { 537 - case _DRM_REGISTERS: 538 - iounmap(map->handle); 539 - fallthrough; 540 - case _DRM_FRAME_BUFFER: 541 - arch_phys_wc_del(map->mtrr); 542 - break; 543 - case _DRM_SHM: 544 - vfree(map->handle); 545 - if (master) { 546 - if (dev->sigdata.lock == master->lock.hw_lock) 547 - dev->sigdata.lock = NULL; 548 - master->lock.hw_lock = NULL; /* SHM removed */ 549 - master->lock.file_priv = NULL; 550 - wake_up_interruptible_all(&master->lock.lock_queue); 551 - } 552 - break; 553 - case _DRM_AGP: 554 - case _DRM_SCATTER_GATHER: 555 - break; 556 - case _DRM_CONSISTENT: 557 - dma_free_coherent(dev->dev, 558 - map->size, 559 - map->handle, 560 - map->offset); 561 - break; 562 - } 563 - kfree(map); 564 - 565 - return 0; 566 - } 567 - EXPORT_SYMBOL(drm_legacy_rmmap_locked); 568 - 569 - void drm_legacy_rmmap(struct drm_device *dev, struct drm_local_map *map) 570 - { 571 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 572 - return; 573 - 574 - mutex_lock(&dev->struct_mutex); 575 - drm_legacy_rmmap_locked(dev, map); 576 - mutex_unlock(&dev->struct_mutex); 577 - } 578 - EXPORT_SYMBOL(drm_legacy_rmmap); 579 - 580 - void drm_legacy_master_rmmaps(struct drm_device *dev, struct drm_master *master) 581 - { 582 - struct drm_map_list *r_list, *list_temp; 583 - 584 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 585 - return; 586 - 587 - mutex_lock(&dev->struct_mutex); 588 - list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) { 589 - if (r_list->master == master) { 590 - drm_legacy_rmmap_locked(dev, r_list->map); 591 - r_list = NULL; 592 - } 593 - } 594 - mutex_unlock(&dev->struct_mutex); 595 - } 596 - 597 - void drm_legacy_rmmaps(struct drm_device *dev) 598 - { 599 - struct drm_map_list *r_list, *list_temp; 600 - 601 - list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head) 602 - drm_legacy_rmmap(dev, r_list->map); 603 - } 604 - 605 - /* The rmmap ioctl appears to be unnecessary. All mappings are torn down on 606 - * the last close of the device, and this is necessary for cleanup when things 607 - * exit uncleanly. Therefore, having userland manually remove mappings seems 608 - * like a pointless exercise since they're going away anyway. 609 - * 610 - * One use case might be after addmap is allowed for normal users for SHM and 611 - * gets used by drivers that the server doesn't need to care about. This seems 612 - * unlikely. 613 - * 614 - * \param inode device inode. 615 - * \param file_priv DRM file private. 616 - * \param cmd command. 617 - * \param arg pointer to a struct drm_map structure. 618 - * \return zero on success or a negative value on error. 619 - */ 620 - int drm_legacy_rmmap_ioctl(struct drm_device *dev, void *data, 621 - struct drm_file *file_priv) 622 - { 623 - struct drm_map *request = data; 624 - struct drm_local_map *map = NULL; 625 - struct drm_map_list *r_list; 626 - int ret; 627 - 628 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 629 - return -EOPNOTSUPP; 630 - 631 - mutex_lock(&dev->struct_mutex); 632 - list_for_each_entry(r_list, &dev->maplist, head) { 633 - if (r_list->map && 634 - r_list->user_token == (unsigned long)request->handle && 635 - r_list->map->flags & _DRM_REMOVABLE) { 636 - map = r_list->map; 637 - break; 638 - } 639 - } 640 - 641 - /* List has wrapped around to the head pointer, or it's empty we didn't 642 - * find anything. 643 - */ 644 - if (list_empty(&dev->maplist) || !map) { 645 - mutex_unlock(&dev->struct_mutex); 646 - return -EINVAL; 647 - } 648 - 649 - /* Register and framebuffer maps are permanent */ 650 - if ((map->type == _DRM_REGISTERS) || (map->type == _DRM_FRAME_BUFFER)) { 651 - mutex_unlock(&dev->struct_mutex); 652 - return 0; 653 - } 654 - 655 - ret = drm_legacy_rmmap_locked(dev, map); 656 - 657 - mutex_unlock(&dev->struct_mutex); 658 - 659 - return ret; 660 - } 661 - 662 - /* 663 - * Cleanup after an error on one of the addbufs() functions. 664 - * 665 - * \param dev DRM device. 666 - * \param entry buffer entry where the error occurred. 667 - * 668 - * Frees any pages and buffers associated with the given entry. 669 - */ 670 - static void drm_cleanup_buf_error(struct drm_device *dev, 671 - struct drm_buf_entry *entry) 672 - { 673 - drm_dma_handle_t *dmah; 674 - int i; 675 - 676 - if (entry->seg_count) { 677 - for (i = 0; i < entry->seg_count; i++) { 678 - if (entry->seglist[i]) { 679 - dmah = entry->seglist[i]; 680 - dma_free_coherent(dev->dev, 681 - dmah->size, 682 - dmah->vaddr, 683 - dmah->busaddr); 684 - kfree(dmah); 685 - } 686 - } 687 - kfree(entry->seglist); 688 - 689 - entry->seg_count = 0; 690 - } 691 - 692 - if (entry->buf_count) { 693 - for (i = 0; i < entry->buf_count; i++) { 694 - kfree(entry->buflist[i].dev_private); 695 - } 696 - kfree(entry->buflist); 697 - 698 - entry->buf_count = 0; 699 - } 700 - } 701 - 702 - #if IS_ENABLED(CONFIG_AGP) 703 - /* 704 - * Add AGP buffers for DMA transfers. 705 - * 706 - * \param dev struct drm_device to which the buffers are to be added. 707 - * \param request pointer to a struct drm_buf_desc describing the request. 708 - * \return zero on success or a negative number on failure. 709 - * 710 - * After some sanity checks creates a drm_buf structure for each buffer and 711 - * reallocates the buffer list of the same size order to accommodate the new 712 - * buffers. 713 - */ 714 - int drm_legacy_addbufs_agp(struct drm_device *dev, 715 - struct drm_buf_desc *request) 716 - { 717 - struct drm_device_dma *dma = dev->dma; 718 - struct drm_buf_entry *entry; 719 - struct drm_agp_mem *agp_entry; 720 - struct drm_buf *buf; 721 - unsigned long offset; 722 - unsigned long agp_offset; 723 - int count; 724 - int order; 725 - int size; 726 - int alignment; 727 - int page_order; 728 - int total; 729 - int byte_count; 730 - int i, valid; 731 - struct drm_buf **temp_buflist; 732 - 733 - if (!dma) 734 - return -EINVAL; 735 - 736 - count = request->count; 737 - order = order_base_2(request->size); 738 - size = 1 << order; 739 - 740 - alignment = (request->flags & _DRM_PAGE_ALIGN) 741 - ? PAGE_ALIGN(size) : size; 742 - page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; 743 - total = PAGE_SIZE << page_order; 744 - 745 - byte_count = 0; 746 - agp_offset = dev->agp->base + request->agp_start; 747 - 748 - DRM_DEBUG("count: %d\n", count); 749 - DRM_DEBUG("order: %d\n", order); 750 - DRM_DEBUG("size: %d\n", size); 751 - DRM_DEBUG("agp_offset: %lx\n", agp_offset); 752 - DRM_DEBUG("alignment: %d\n", alignment); 753 - DRM_DEBUG("page_order: %d\n", page_order); 754 - DRM_DEBUG("total: %d\n", total); 755 - 756 - if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) 757 - return -EINVAL; 758 - 759 - /* Make sure buffers are located in AGP memory that we own */ 760 - valid = 0; 761 - list_for_each_entry(agp_entry, &dev->agp->memory, head) { 762 - if ((agp_offset >= agp_entry->bound) && 763 - (agp_offset + total * count <= agp_entry->bound + agp_entry->pages * PAGE_SIZE)) { 764 - valid = 1; 765 - break; 766 - } 767 - } 768 - if (!list_empty(&dev->agp->memory) && !valid) { 769 - DRM_DEBUG("zone invalid\n"); 770 - return -EINVAL; 771 - } 772 - spin_lock(&dev->buf_lock); 773 - if (dev->buf_use) { 774 - spin_unlock(&dev->buf_lock); 775 - return -EBUSY; 776 - } 777 - atomic_inc(&dev->buf_alloc); 778 - spin_unlock(&dev->buf_lock); 779 - 780 - mutex_lock(&dev->struct_mutex); 781 - entry = &dma->bufs[order]; 782 - if (entry->buf_count) { 783 - mutex_unlock(&dev->struct_mutex); 784 - atomic_dec(&dev->buf_alloc); 785 - return -ENOMEM; /* May only call once for each order */ 786 - } 787 - 788 - if (count < 0 || count > 4096) { 789 - mutex_unlock(&dev->struct_mutex); 790 - atomic_dec(&dev->buf_alloc); 791 - return -EINVAL; 792 - } 793 - 794 - entry->buflist = kcalloc(count, sizeof(*entry->buflist), GFP_KERNEL); 795 - if (!entry->buflist) { 796 - mutex_unlock(&dev->struct_mutex); 797 - atomic_dec(&dev->buf_alloc); 798 - return -ENOMEM; 799 - } 800 - 801 - entry->buf_size = size; 802 - entry->page_order = page_order; 803 - 804 - offset = 0; 805 - 806 - while (entry->buf_count < count) { 807 - buf = &entry->buflist[entry->buf_count]; 808 - buf->idx = dma->buf_count + entry->buf_count; 809 - buf->total = alignment; 810 - buf->order = order; 811 - buf->used = 0; 812 - 813 - buf->offset = (dma->byte_count + offset); 814 - buf->bus_address = agp_offset + offset; 815 - buf->address = (void *)(agp_offset + offset); 816 - buf->next = NULL; 817 - buf->waiting = 0; 818 - buf->pending = 0; 819 - buf->file_priv = NULL; 820 - 821 - buf->dev_priv_size = dev->driver->dev_priv_size; 822 - buf->dev_private = kzalloc(buf->dev_priv_size, GFP_KERNEL); 823 - if (!buf->dev_private) { 824 - /* Set count correctly so we free the proper amount. */ 825 - entry->buf_count = count; 826 - drm_cleanup_buf_error(dev, entry); 827 - mutex_unlock(&dev->struct_mutex); 828 - atomic_dec(&dev->buf_alloc); 829 - return -ENOMEM; 830 - } 831 - 832 - DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); 833 - 834 - offset += alignment; 835 - entry->buf_count++; 836 - byte_count += PAGE_SIZE << page_order; 837 - } 838 - 839 - DRM_DEBUG("byte_count: %d\n", byte_count); 840 - 841 - temp_buflist = krealloc(dma->buflist, 842 - (dma->buf_count + entry->buf_count) * 843 - sizeof(*dma->buflist), GFP_KERNEL); 844 - if (!temp_buflist) { 845 - /* Free the entry because it isn't valid */ 846 - drm_cleanup_buf_error(dev, entry); 847 - mutex_unlock(&dev->struct_mutex); 848 - atomic_dec(&dev->buf_alloc); 849 - return -ENOMEM; 850 - } 851 - dma->buflist = temp_buflist; 852 - 853 - for (i = 0; i < entry->buf_count; i++) { 854 - dma->buflist[i + dma->buf_count] = &entry->buflist[i]; 855 - } 856 - 857 - dma->buf_count += entry->buf_count; 858 - dma->seg_count += entry->seg_count; 859 - dma->page_count += byte_count >> PAGE_SHIFT; 860 - dma->byte_count += byte_count; 861 - 862 - DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); 863 - DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); 864 - 865 - mutex_unlock(&dev->struct_mutex); 866 - 867 - request->count = entry->buf_count; 868 - request->size = size; 869 - 870 - dma->flags = _DRM_DMA_USE_AGP; 871 - 872 - atomic_dec(&dev->buf_alloc); 873 - return 0; 874 - } 875 - EXPORT_SYMBOL(drm_legacy_addbufs_agp); 876 - #endif /* CONFIG_AGP */ 877 - 878 - int drm_legacy_addbufs_pci(struct drm_device *dev, 879 - struct drm_buf_desc *request) 880 - { 881 - struct drm_device_dma *dma = dev->dma; 882 - int count; 883 - int order; 884 - int size; 885 - int total; 886 - int page_order; 887 - struct drm_buf_entry *entry; 888 - drm_dma_handle_t *dmah; 889 - struct drm_buf *buf; 890 - int alignment; 891 - unsigned long offset; 892 - int i; 893 - int byte_count; 894 - int page_count; 895 - unsigned long *temp_pagelist; 896 - struct drm_buf **temp_buflist; 897 - 898 - if (!drm_core_check_feature(dev, DRIVER_PCI_DMA)) 899 - return -EOPNOTSUPP; 900 - 901 - if (!dma) 902 - return -EINVAL; 903 - 904 - if (!capable(CAP_SYS_ADMIN)) 905 - return -EPERM; 906 - 907 - count = request->count; 908 - order = order_base_2(request->size); 909 - size = 1 << order; 910 - 911 - DRM_DEBUG("count=%d, size=%d (%d), order=%d\n", 912 - request->count, request->size, size, order); 913 - 914 - if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) 915 - return -EINVAL; 916 - 917 - alignment = (request->flags & _DRM_PAGE_ALIGN) 918 - ? PAGE_ALIGN(size) : size; 919 - page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; 920 - total = PAGE_SIZE << page_order; 921 - 922 - spin_lock(&dev->buf_lock); 923 - if (dev->buf_use) { 924 - spin_unlock(&dev->buf_lock); 925 - return -EBUSY; 926 - } 927 - atomic_inc(&dev->buf_alloc); 928 - spin_unlock(&dev->buf_lock); 929 - 930 - mutex_lock(&dev->struct_mutex); 931 - entry = &dma->bufs[order]; 932 - if (entry->buf_count) { 933 - mutex_unlock(&dev->struct_mutex); 934 - atomic_dec(&dev->buf_alloc); 935 - return -ENOMEM; /* May only call once for each order */ 936 - } 937 - 938 - if (count < 0 || count > 4096) { 939 - mutex_unlock(&dev->struct_mutex); 940 - atomic_dec(&dev->buf_alloc); 941 - return -EINVAL; 942 - } 943 - 944 - entry->buflist = kcalloc(count, sizeof(*entry->buflist), GFP_KERNEL); 945 - if (!entry->buflist) { 946 - mutex_unlock(&dev->struct_mutex); 947 - atomic_dec(&dev->buf_alloc); 948 - return -ENOMEM; 949 - } 950 - 951 - entry->seglist = kcalloc(count, sizeof(*entry->seglist), GFP_KERNEL); 952 - if (!entry->seglist) { 953 - kfree(entry->buflist); 954 - mutex_unlock(&dev->struct_mutex); 955 - atomic_dec(&dev->buf_alloc); 956 - return -ENOMEM; 957 - } 958 - 959 - /* Keep the original pagelist until we know all the allocations 960 - * have succeeded 961 - */ 962 - temp_pagelist = kmalloc_array(dma->page_count + (count << page_order), 963 - sizeof(*dma->pagelist), 964 - GFP_KERNEL); 965 - if (!temp_pagelist) { 966 - kfree(entry->buflist); 967 - kfree(entry->seglist); 968 - mutex_unlock(&dev->struct_mutex); 969 - atomic_dec(&dev->buf_alloc); 970 - return -ENOMEM; 971 - } 972 - memcpy(temp_pagelist, 973 - dma->pagelist, dma->page_count * sizeof(*dma->pagelist)); 974 - DRM_DEBUG("pagelist: %d entries\n", 975 - dma->page_count + (count << page_order)); 976 - 977 - entry->buf_size = size; 978 - entry->page_order = page_order; 979 - byte_count = 0; 980 - page_count = 0; 981 - 982 - while (entry->buf_count < count) { 983 - dmah = kmalloc(sizeof(drm_dma_handle_t), GFP_KERNEL); 984 - if (!dmah) { 985 - /* Set count correctly so we free the proper amount. */ 986 - entry->buf_count = count; 987 - entry->seg_count = count; 988 - drm_cleanup_buf_error(dev, entry); 989 - kfree(temp_pagelist); 990 - mutex_unlock(&dev->struct_mutex); 991 - atomic_dec(&dev->buf_alloc); 992 - return -ENOMEM; 993 - } 994 - 995 - dmah->size = total; 996 - dmah->vaddr = dma_alloc_coherent(dev->dev, 997 - dmah->size, 998 - &dmah->busaddr, 999 - GFP_KERNEL); 1000 - if (!dmah->vaddr) { 1001 - kfree(dmah); 1002 - 1003 - /* Set count correctly so we free the proper amount. */ 1004 - entry->buf_count = count; 1005 - entry->seg_count = count; 1006 - drm_cleanup_buf_error(dev, entry); 1007 - kfree(temp_pagelist); 1008 - mutex_unlock(&dev->struct_mutex); 1009 - atomic_dec(&dev->buf_alloc); 1010 - return -ENOMEM; 1011 - } 1012 - entry->seglist[entry->seg_count++] = dmah; 1013 - for (i = 0; i < (1 << page_order); i++) { 1014 - DRM_DEBUG("page %d @ 0x%08lx\n", 1015 - dma->page_count + page_count, 1016 - (unsigned long)dmah->vaddr + PAGE_SIZE * i); 1017 - temp_pagelist[dma->page_count + page_count++] 1018 - = (unsigned long)dmah->vaddr + PAGE_SIZE * i; 1019 - } 1020 - for (offset = 0; 1021 - offset + size <= total && entry->buf_count < count; 1022 - offset += alignment, ++entry->buf_count) { 1023 - buf = &entry->buflist[entry->buf_count]; 1024 - buf->idx = dma->buf_count + entry->buf_count; 1025 - buf->total = alignment; 1026 - buf->order = order; 1027 - buf->used = 0; 1028 - buf->offset = (dma->byte_count + byte_count + offset); 1029 - buf->address = (void *)(dmah->vaddr + offset); 1030 - buf->bus_address = dmah->busaddr + offset; 1031 - buf->next = NULL; 1032 - buf->waiting = 0; 1033 - buf->pending = 0; 1034 - buf->file_priv = NULL; 1035 - 1036 - buf->dev_priv_size = dev->driver->dev_priv_size; 1037 - buf->dev_private = kzalloc(buf->dev_priv_size, 1038 - GFP_KERNEL); 1039 - if (!buf->dev_private) { 1040 - /* Set count correctly so we free the proper amount. */ 1041 - entry->buf_count = count; 1042 - entry->seg_count = count; 1043 - drm_cleanup_buf_error(dev, entry); 1044 - kfree(temp_pagelist); 1045 - mutex_unlock(&dev->struct_mutex); 1046 - atomic_dec(&dev->buf_alloc); 1047 - return -ENOMEM; 1048 - } 1049 - 1050 - DRM_DEBUG("buffer %d @ %p\n", 1051 - entry->buf_count, buf->address); 1052 - } 1053 - byte_count += PAGE_SIZE << page_order; 1054 - } 1055 - 1056 - temp_buflist = krealloc(dma->buflist, 1057 - (dma->buf_count + entry->buf_count) * 1058 - sizeof(*dma->buflist), GFP_KERNEL); 1059 - if (!temp_buflist) { 1060 - /* Free the entry because it isn't valid */ 1061 - drm_cleanup_buf_error(dev, entry); 1062 - kfree(temp_pagelist); 1063 - mutex_unlock(&dev->struct_mutex); 1064 - atomic_dec(&dev->buf_alloc); 1065 - return -ENOMEM; 1066 - } 1067 - dma->buflist = temp_buflist; 1068 - 1069 - for (i = 0; i < entry->buf_count; i++) { 1070 - dma->buflist[i + dma->buf_count] = &entry->buflist[i]; 1071 - } 1072 - 1073 - /* No allocations failed, so now we can replace the original pagelist 1074 - * with the new one. 1075 - */ 1076 - if (dma->page_count) { 1077 - kfree(dma->pagelist); 1078 - } 1079 - dma->pagelist = temp_pagelist; 1080 - 1081 - dma->buf_count += entry->buf_count; 1082 - dma->seg_count += entry->seg_count; 1083 - dma->page_count += entry->seg_count << page_order; 1084 - dma->byte_count += PAGE_SIZE * (entry->seg_count << page_order); 1085 - 1086 - mutex_unlock(&dev->struct_mutex); 1087 - 1088 - request->count = entry->buf_count; 1089 - request->size = size; 1090 - 1091 - if (request->flags & _DRM_PCI_BUFFER_RO) 1092 - dma->flags = _DRM_DMA_USE_PCI_RO; 1093 - 1094 - atomic_dec(&dev->buf_alloc); 1095 - return 0; 1096 - 1097 - } 1098 - EXPORT_SYMBOL(drm_legacy_addbufs_pci); 1099 - 1100 - static int drm_legacy_addbufs_sg(struct drm_device *dev, 1101 - struct drm_buf_desc *request) 1102 - { 1103 - struct drm_device_dma *dma = dev->dma; 1104 - struct drm_buf_entry *entry; 1105 - struct drm_buf *buf; 1106 - unsigned long offset; 1107 - unsigned long agp_offset; 1108 - int count; 1109 - int order; 1110 - int size; 1111 - int alignment; 1112 - int page_order; 1113 - int total; 1114 - int byte_count; 1115 - int i; 1116 - struct drm_buf **temp_buflist; 1117 - 1118 - if (!drm_core_check_feature(dev, DRIVER_SG)) 1119 - return -EOPNOTSUPP; 1120 - 1121 - if (!dma) 1122 - return -EINVAL; 1123 - 1124 - if (!capable(CAP_SYS_ADMIN)) 1125 - return -EPERM; 1126 - 1127 - count = request->count; 1128 - order = order_base_2(request->size); 1129 - size = 1 << order; 1130 - 1131 - alignment = (request->flags & _DRM_PAGE_ALIGN) 1132 - ? PAGE_ALIGN(size) : size; 1133 - page_order = order - PAGE_SHIFT > 0 ? order - PAGE_SHIFT : 0; 1134 - total = PAGE_SIZE << page_order; 1135 - 1136 - byte_count = 0; 1137 - agp_offset = request->agp_start; 1138 - 1139 - DRM_DEBUG("count: %d\n", count); 1140 - DRM_DEBUG("order: %d\n", order); 1141 - DRM_DEBUG("size: %d\n", size); 1142 - DRM_DEBUG("agp_offset: %lu\n", agp_offset); 1143 - DRM_DEBUG("alignment: %d\n", alignment); 1144 - DRM_DEBUG("page_order: %d\n", page_order); 1145 - DRM_DEBUG("total: %d\n", total); 1146 - 1147 - if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) 1148 - return -EINVAL; 1149 - 1150 - spin_lock(&dev->buf_lock); 1151 - if (dev->buf_use) { 1152 - spin_unlock(&dev->buf_lock); 1153 - return -EBUSY; 1154 - } 1155 - atomic_inc(&dev->buf_alloc); 1156 - spin_unlock(&dev->buf_lock); 1157 - 1158 - mutex_lock(&dev->struct_mutex); 1159 - entry = &dma->bufs[order]; 1160 - if (entry->buf_count) { 1161 - mutex_unlock(&dev->struct_mutex); 1162 - atomic_dec(&dev->buf_alloc); 1163 - return -ENOMEM; /* May only call once for each order */ 1164 - } 1165 - 1166 - if (count < 0 || count > 4096) { 1167 - mutex_unlock(&dev->struct_mutex); 1168 - atomic_dec(&dev->buf_alloc); 1169 - return -EINVAL; 1170 - } 1171 - 1172 - entry->buflist = kcalloc(count, sizeof(*entry->buflist), GFP_KERNEL); 1173 - if (!entry->buflist) { 1174 - mutex_unlock(&dev->struct_mutex); 1175 - atomic_dec(&dev->buf_alloc); 1176 - return -ENOMEM; 1177 - } 1178 - 1179 - entry->buf_size = size; 1180 - entry->page_order = page_order; 1181 - 1182 - offset = 0; 1183 - 1184 - while (entry->buf_count < count) { 1185 - buf = &entry->buflist[entry->buf_count]; 1186 - buf->idx = dma->buf_count + entry->buf_count; 1187 - buf->total = alignment; 1188 - buf->order = order; 1189 - buf->used = 0; 1190 - 1191 - buf->offset = (dma->byte_count + offset); 1192 - buf->bus_address = agp_offset + offset; 1193 - buf->address = (void *)(agp_offset + offset 1194 - + (unsigned long)dev->sg->virtual); 1195 - buf->next = NULL; 1196 - buf->waiting = 0; 1197 - buf->pending = 0; 1198 - buf->file_priv = NULL; 1199 - 1200 - buf->dev_priv_size = dev->driver->dev_priv_size; 1201 - buf->dev_private = kzalloc(buf->dev_priv_size, GFP_KERNEL); 1202 - if (!buf->dev_private) { 1203 - /* Set count correctly so we free the proper amount. */ 1204 - entry->buf_count = count; 1205 - drm_cleanup_buf_error(dev, entry); 1206 - mutex_unlock(&dev->struct_mutex); 1207 - atomic_dec(&dev->buf_alloc); 1208 - return -ENOMEM; 1209 - } 1210 - 1211 - DRM_DEBUG("buffer %d @ %p\n", entry->buf_count, buf->address); 1212 - 1213 - offset += alignment; 1214 - entry->buf_count++; 1215 - byte_count += PAGE_SIZE << page_order; 1216 - } 1217 - 1218 - DRM_DEBUG("byte_count: %d\n", byte_count); 1219 - 1220 - temp_buflist = krealloc(dma->buflist, 1221 - (dma->buf_count + entry->buf_count) * 1222 - sizeof(*dma->buflist), GFP_KERNEL); 1223 - if (!temp_buflist) { 1224 - /* Free the entry because it isn't valid */ 1225 - drm_cleanup_buf_error(dev, entry); 1226 - mutex_unlock(&dev->struct_mutex); 1227 - atomic_dec(&dev->buf_alloc); 1228 - return -ENOMEM; 1229 - } 1230 - dma->buflist = temp_buflist; 1231 - 1232 - for (i = 0; i < entry->buf_count; i++) { 1233 - dma->buflist[i + dma->buf_count] = &entry->buflist[i]; 1234 - } 1235 - 1236 - dma->buf_count += entry->buf_count; 1237 - dma->seg_count += entry->seg_count; 1238 - dma->page_count += byte_count >> PAGE_SHIFT; 1239 - dma->byte_count += byte_count; 1240 - 1241 - DRM_DEBUG("dma->buf_count : %d\n", dma->buf_count); 1242 - DRM_DEBUG("entry->buf_count : %d\n", entry->buf_count); 1243 - 1244 - mutex_unlock(&dev->struct_mutex); 1245 - 1246 - request->count = entry->buf_count; 1247 - request->size = size; 1248 - 1249 - dma->flags = _DRM_DMA_USE_SG; 1250 - 1251 - atomic_dec(&dev->buf_alloc); 1252 - return 0; 1253 - } 1254 - 1255 - /* 1256 - * Add buffers for DMA transfers (ioctl). 1257 - * 1258 - * \param inode device inode. 1259 - * \param file_priv DRM file private. 1260 - * \param cmd command. 1261 - * \param arg pointer to a struct drm_buf_desc request. 1262 - * \return zero on success or a negative number on failure. 1263 - * 1264 - * According with the memory type specified in drm_buf_desc::flags and the 1265 - * build options, it dispatches the call either to addbufs_agp(), 1266 - * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent 1267 - * PCI memory respectively. 1268 - */ 1269 - int drm_legacy_addbufs(struct drm_device *dev, void *data, 1270 - struct drm_file *file_priv) 1271 - { 1272 - struct drm_buf_desc *request = data; 1273 - int ret; 1274 - 1275 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 1276 - return -EOPNOTSUPP; 1277 - 1278 - if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) 1279 - return -EOPNOTSUPP; 1280 - 1281 - #if IS_ENABLED(CONFIG_AGP) 1282 - if (request->flags & _DRM_AGP_BUFFER) 1283 - ret = drm_legacy_addbufs_agp(dev, request); 1284 - else 1285 - #endif 1286 - if (request->flags & _DRM_SG_BUFFER) 1287 - ret = drm_legacy_addbufs_sg(dev, request); 1288 - else if (request->flags & _DRM_FB_BUFFER) 1289 - ret = -EINVAL; 1290 - else 1291 - ret = drm_legacy_addbufs_pci(dev, request); 1292 - 1293 - return ret; 1294 - } 1295 - 1296 - /* 1297 - * Get information about the buffer mappings. 1298 - * 1299 - * This was originally mean for debugging purposes, or by a sophisticated 1300 - * client library to determine how best to use the available buffers (e.g., 1301 - * large buffers can be used for image transfer). 1302 - * 1303 - * \param inode device inode. 1304 - * \param file_priv DRM file private. 1305 - * \param cmd command. 1306 - * \param arg pointer to a drm_buf_info structure. 1307 - * \return zero on success or a negative number on failure. 1308 - * 1309 - * Increments drm_device::buf_use while holding the drm_device::buf_lock 1310 - * lock, preventing of allocating more buffers after this call. Information 1311 - * about each requested buffer is then copied into user space. 1312 - */ 1313 - int __drm_legacy_infobufs(struct drm_device *dev, 1314 - void *data, int *p, 1315 - int (*f)(void *, int, struct drm_buf_entry *)) 1316 - { 1317 - struct drm_device_dma *dma = dev->dma; 1318 - int i; 1319 - int count; 1320 - 1321 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 1322 - return -EOPNOTSUPP; 1323 - 1324 - if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) 1325 - return -EOPNOTSUPP; 1326 - 1327 - if (!dma) 1328 - return -EINVAL; 1329 - 1330 - spin_lock(&dev->buf_lock); 1331 - if (atomic_read(&dev->buf_alloc)) { 1332 - spin_unlock(&dev->buf_lock); 1333 - return -EBUSY; 1334 - } 1335 - ++dev->buf_use; /* Can't allocate more after this call */ 1336 - spin_unlock(&dev->buf_lock); 1337 - 1338 - for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) { 1339 - if (dma->bufs[i].buf_count) 1340 - ++count; 1341 - } 1342 - 1343 - DRM_DEBUG("count = %d\n", count); 1344 - 1345 - if (*p >= count) { 1346 - for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) { 1347 - struct drm_buf_entry *from = &dma->bufs[i]; 1348 - 1349 - if (from->buf_count) { 1350 - if (f(data, count, from) < 0) 1351 - return -EFAULT; 1352 - DRM_DEBUG("%d %d %d %d %d\n", 1353 - i, 1354 - dma->bufs[i].buf_count, 1355 - dma->bufs[i].buf_size, 1356 - dma->bufs[i].low_mark, 1357 - dma->bufs[i].high_mark); 1358 - ++count; 1359 - } 1360 - } 1361 - } 1362 - *p = count; 1363 - 1364 - return 0; 1365 - } 1366 - 1367 - static int copy_one_buf(void *data, int count, struct drm_buf_entry *from) 1368 - { 1369 - struct drm_buf_info *request = data; 1370 - struct drm_buf_desc __user *to = &request->list[count]; 1371 - struct drm_buf_desc v = {.count = from->buf_count, 1372 - .size = from->buf_size, 1373 - .low_mark = from->low_mark, 1374 - .high_mark = from->high_mark}; 1375 - 1376 - if (copy_to_user(to, &v, offsetof(struct drm_buf_desc, flags))) 1377 - return -EFAULT; 1378 - return 0; 1379 - } 1380 - 1381 - int drm_legacy_infobufs(struct drm_device *dev, void *data, 1382 - struct drm_file *file_priv) 1383 - { 1384 - struct drm_buf_info *request = data; 1385 - 1386 - return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf); 1387 - } 1388 - 1389 - /* 1390 - * Specifies a low and high water mark for buffer allocation 1391 - * 1392 - * \param inode device inode. 1393 - * \param file_priv DRM file private. 1394 - * \param cmd command. 1395 - * \param arg a pointer to a drm_buf_desc structure. 1396 - * \return zero on success or a negative number on failure. 1397 - * 1398 - * Verifies that the size order is bounded between the admissible orders and 1399 - * updates the respective drm_device_dma::bufs entry low and high water mark. 1400 - * 1401 - * \note This ioctl is deprecated and mostly never used. 1402 - */ 1403 - int drm_legacy_markbufs(struct drm_device *dev, void *data, 1404 - struct drm_file *file_priv) 1405 - { 1406 - struct drm_device_dma *dma = dev->dma; 1407 - struct drm_buf_desc *request = data; 1408 - int order; 1409 - struct drm_buf_entry *entry; 1410 - 1411 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 1412 - return -EOPNOTSUPP; 1413 - 1414 - if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) 1415 - return -EOPNOTSUPP; 1416 - 1417 - if (!dma) 1418 - return -EINVAL; 1419 - 1420 - DRM_DEBUG("%d, %d, %d\n", 1421 - request->size, request->low_mark, request->high_mark); 1422 - order = order_base_2(request->size); 1423 - if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) 1424 - return -EINVAL; 1425 - entry = &dma->bufs[order]; 1426 - 1427 - if (request->low_mark < 0 || request->low_mark > entry->buf_count) 1428 - return -EINVAL; 1429 - if (request->high_mark < 0 || request->high_mark > entry->buf_count) 1430 - return -EINVAL; 1431 - 1432 - entry->low_mark = request->low_mark; 1433 - entry->high_mark = request->high_mark; 1434 - 1435 - return 0; 1436 - } 1437 - 1438 - /* 1439 - * Unreserve the buffers in list, previously reserved using drmDMA. 1440 - * 1441 - * \param inode device inode. 1442 - * \param file_priv DRM file private. 1443 - * \param cmd command. 1444 - * \param arg pointer to a drm_buf_free structure. 1445 - * \return zero on success or a negative number on failure. 1446 - * 1447 - * Calls free_buffer() for each used buffer. 1448 - * This function is primarily used for debugging. 1449 - */ 1450 - int drm_legacy_freebufs(struct drm_device *dev, void *data, 1451 - struct drm_file *file_priv) 1452 - { 1453 - struct drm_device_dma *dma = dev->dma; 1454 - struct drm_buf_free *request = data; 1455 - int i; 1456 - int idx; 1457 - struct drm_buf *buf; 1458 - 1459 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 1460 - return -EOPNOTSUPP; 1461 - 1462 - if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) 1463 - return -EOPNOTSUPP; 1464 - 1465 - if (!dma) 1466 - return -EINVAL; 1467 - 1468 - DRM_DEBUG("%d\n", request->count); 1469 - for (i = 0; i < request->count; i++) { 1470 - if (copy_from_user(&idx, &request->list[i], sizeof(idx))) 1471 - return -EFAULT; 1472 - if (idx < 0 || idx >= dma->buf_count) { 1473 - DRM_ERROR("Index %d (of %d max)\n", 1474 - idx, dma->buf_count - 1); 1475 - return -EINVAL; 1476 - } 1477 - idx = array_index_nospec(idx, dma->buf_count); 1478 - buf = dma->buflist[idx]; 1479 - if (buf->file_priv != file_priv) { 1480 - DRM_ERROR("Process %d freeing buffer not owned\n", 1481 - task_pid_nr(current)); 1482 - return -EINVAL; 1483 - } 1484 - drm_legacy_free_buffer(dev, buf); 1485 - } 1486 - 1487 - return 0; 1488 - } 1489 - 1490 - /* 1491 - * Maps all of the DMA buffers into client-virtual space (ioctl). 1492 - * 1493 - * \param inode device inode. 1494 - * \param file_priv DRM file private. 1495 - * \param cmd command. 1496 - * \param arg pointer to a drm_buf_map structure. 1497 - * \return zero on success or a negative number on failure. 1498 - * 1499 - * Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information 1500 - * about each buffer into user space. For PCI buffers, it calls vm_mmap() with 1501 - * offset equal to 0, which drm_mmap() interprets as PCI buffers and calls 1502 - * drm_mmap_dma(). 1503 - */ 1504 - int __drm_legacy_mapbufs(struct drm_device *dev, void *data, int *p, 1505 - void __user **v, 1506 - int (*f)(void *, int, unsigned long, 1507 - struct drm_buf *), 1508 - struct drm_file *file_priv) 1509 - { 1510 - struct drm_device_dma *dma = dev->dma; 1511 - int retcode = 0; 1512 - unsigned long virtual; 1513 - int i; 1514 - 1515 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 1516 - return -EOPNOTSUPP; 1517 - 1518 - if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) 1519 - return -EOPNOTSUPP; 1520 - 1521 - if (!dma) 1522 - return -EINVAL; 1523 - 1524 - spin_lock(&dev->buf_lock); 1525 - if (atomic_read(&dev->buf_alloc)) { 1526 - spin_unlock(&dev->buf_lock); 1527 - return -EBUSY; 1528 - } 1529 - dev->buf_use++; /* Can't allocate more after this call */ 1530 - spin_unlock(&dev->buf_lock); 1531 - 1532 - if (*p >= dma->buf_count) { 1533 - if ((dev->agp && (dma->flags & _DRM_DMA_USE_AGP)) 1534 - || (drm_core_check_feature(dev, DRIVER_SG) 1535 - && (dma->flags & _DRM_DMA_USE_SG))) { 1536 - struct drm_local_map *map = dev->agp_buffer_map; 1537 - unsigned long token = dev->agp_buffer_token; 1538 - 1539 - if (!map) { 1540 - retcode = -EINVAL; 1541 - goto done; 1542 - } 1543 - virtual = vm_mmap(file_priv->filp, 0, map->size, 1544 - PROT_READ | PROT_WRITE, 1545 - MAP_SHARED, 1546 - token); 1547 - } else { 1548 - virtual = vm_mmap(file_priv->filp, 0, dma->byte_count, 1549 - PROT_READ | PROT_WRITE, 1550 - MAP_SHARED, 0); 1551 - } 1552 - if (virtual > -1024UL) { 1553 - /* Real error */ 1554 - retcode = (signed long)virtual; 1555 - goto done; 1556 - } 1557 - *v = (void __user *)virtual; 1558 - 1559 - for (i = 0; i < dma->buf_count; i++) { 1560 - if (f(data, i, virtual, dma->buflist[i]) < 0) { 1561 - retcode = -EFAULT; 1562 - goto done; 1563 - } 1564 - } 1565 - } 1566 - done: 1567 - *p = dma->buf_count; 1568 - DRM_DEBUG("%d buffers, retcode = %d\n", *p, retcode); 1569 - 1570 - return retcode; 1571 - } 1572 - 1573 - static int map_one_buf(void *data, int idx, unsigned long virtual, 1574 - struct drm_buf *buf) 1575 - { 1576 - struct drm_buf_map *request = data; 1577 - unsigned long address = virtual + buf->offset; /* *** */ 1578 - 1579 - if (copy_to_user(&request->list[idx].idx, &buf->idx, 1580 - sizeof(request->list[0].idx))) 1581 - return -EFAULT; 1582 - if (copy_to_user(&request->list[idx].total, &buf->total, 1583 - sizeof(request->list[0].total))) 1584 - return -EFAULT; 1585 - if (clear_user(&request->list[idx].used, sizeof(int))) 1586 - return -EFAULT; 1587 - if (copy_to_user(&request->list[idx].address, &address, 1588 - sizeof(address))) 1589 - return -EFAULT; 1590 - return 0; 1591 - } 1592 - 1593 - int drm_legacy_mapbufs(struct drm_device *dev, void *data, 1594 - struct drm_file *file_priv) 1595 - { 1596 - struct drm_buf_map *request = data; 1597 - 1598 - return __drm_legacy_mapbufs(dev, data, &request->count, 1599 - &request->virtual, map_one_buf, 1600 - file_priv); 1601 - } 1602 - 1603 - int drm_legacy_dma_ioctl(struct drm_device *dev, void *data, 1604 - struct drm_file *file_priv) 1605 - { 1606 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 1607 - return -EOPNOTSUPP; 1608 - 1609 - if (dev->driver->dma_ioctl) 1610 - return dev->driver->dma_ioctl(dev, data, file_priv); 1611 - else 1612 - return -EINVAL; 1613 - } 1614 - 1615 - struct drm_local_map *drm_legacy_getsarea(struct drm_device *dev) 1616 - { 1617 - struct drm_map_list *entry; 1618 - 1619 - list_for_each_entry(entry, &dev->maplist, head) { 1620 - if (entry->map && entry->map->type == _DRM_SHM && 1621 - (entry->map->flags & _DRM_CONTAINS_LOCK)) { 1622 - return entry->map; 1623 - } 1624 - } 1625 - return NULL; 1626 - } 1627 - EXPORT_SYMBOL(drm_legacy_getsarea);
-513
drivers/gpu/drm/drm_context.c
··· 1 - /* 2 - * Legacy: Generic DRM Contexts 3 - * 4 - * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. 5 - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 6 - * All Rights Reserved. 7 - * 8 - * Author: Rickard E. (Rik) Faith <faith@valinux.com> 9 - * Author: Gareth Hughes <gareth@valinux.com> 10 - * 11 - * Permission is hereby granted, free of charge, to any person obtaining a 12 - * copy of this software and associated documentation files (the "Software"), 13 - * to deal in the Software without restriction, including without limitation 14 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15 - * and/or sell copies of the Software, and to permit persons to whom the 16 - * Software is furnished to do so, subject to the following conditions: 17 - * 18 - * The above copyright notice and this permission notice (including the next 19 - * paragraph) shall be included in all copies or substantial portions of the 20 - * Software. 21 - * 22 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 26 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 27 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 - * OTHER DEALINGS IN THE SOFTWARE. 29 - */ 30 - 31 - #include <linux/slab.h> 32 - #include <linux/uaccess.h> 33 - 34 - #include <drm/drm_drv.h> 35 - #include <drm/drm_file.h> 36 - #include <drm/drm_print.h> 37 - 38 - #include "drm_legacy.h" 39 - 40 - struct drm_ctx_list { 41 - struct list_head head; 42 - drm_context_t handle; 43 - struct drm_file *tag; 44 - }; 45 - 46 - /******************************************************************/ 47 - /** \name Context bitmap support */ 48 - /*@{*/ 49 - 50 - /* 51 - * Free a handle from the context bitmap. 52 - * 53 - * \param dev DRM device. 54 - * \param ctx_handle context handle. 55 - * 56 - * Clears the bit specified by \p ctx_handle in drm_device::ctx_bitmap and the entry 57 - * in drm_device::ctx_idr, while holding the drm_device::struct_mutex 58 - * lock. 59 - */ 60 - void drm_legacy_ctxbitmap_free(struct drm_device * dev, int ctx_handle) 61 - { 62 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 63 - return; 64 - 65 - mutex_lock(&dev->struct_mutex); 66 - idr_remove(&dev->ctx_idr, ctx_handle); 67 - mutex_unlock(&dev->struct_mutex); 68 - } 69 - 70 - /* 71 - * Context bitmap allocation. 72 - * 73 - * \param dev DRM device. 74 - * \return (non-negative) context handle on success or a negative number on failure. 75 - * 76 - * Allocate a new idr from drm_device::ctx_idr while holding the 77 - * drm_device::struct_mutex lock. 78 - */ 79 - static int drm_legacy_ctxbitmap_next(struct drm_device * dev) 80 - { 81 - int ret; 82 - 83 - mutex_lock(&dev->struct_mutex); 84 - ret = idr_alloc(&dev->ctx_idr, NULL, DRM_RESERVED_CONTEXTS, 0, 85 - GFP_KERNEL); 86 - mutex_unlock(&dev->struct_mutex); 87 - return ret; 88 - } 89 - 90 - /* 91 - * Context bitmap initialization. 92 - * 93 - * \param dev DRM device. 94 - * 95 - * Initialise the drm_device::ctx_idr 96 - */ 97 - void drm_legacy_ctxbitmap_init(struct drm_device * dev) 98 - { 99 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 100 - return; 101 - 102 - idr_init(&dev->ctx_idr); 103 - } 104 - 105 - /* 106 - * Context bitmap cleanup. 107 - * 108 - * \param dev DRM device. 109 - * 110 - * Free all idr members using drm_ctx_sarea_free helper function 111 - * while holding the drm_device::struct_mutex lock. 112 - */ 113 - void drm_legacy_ctxbitmap_cleanup(struct drm_device * dev) 114 - { 115 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 116 - return; 117 - 118 - mutex_lock(&dev->struct_mutex); 119 - idr_destroy(&dev->ctx_idr); 120 - mutex_unlock(&dev->struct_mutex); 121 - } 122 - 123 - /** 124 - * drm_legacy_ctxbitmap_flush() - Flush all contexts owned by a file 125 - * @dev: DRM device to operate on 126 - * @file: Open file to flush contexts for 127 - * 128 - * This iterates over all contexts on @dev and drops them if they're owned by 129 - * @file. Note that after this call returns, new contexts might be added if 130 - * the file is still alive. 131 - */ 132 - void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file) 133 - { 134 - struct drm_ctx_list *pos, *tmp; 135 - 136 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 137 - return; 138 - 139 - mutex_lock(&dev->ctxlist_mutex); 140 - 141 - list_for_each_entry_safe(pos, tmp, &dev->ctxlist, head) { 142 - if (pos->tag == file && 143 - pos->handle != DRM_KERNEL_CONTEXT) { 144 - if (dev->driver->context_dtor) 145 - dev->driver->context_dtor(dev, pos->handle); 146 - 147 - drm_legacy_ctxbitmap_free(dev, pos->handle); 148 - list_del(&pos->head); 149 - kfree(pos); 150 - } 151 - } 152 - 153 - mutex_unlock(&dev->ctxlist_mutex); 154 - } 155 - 156 - /*@}*/ 157 - 158 - /******************************************************************/ 159 - /** \name Per Context SAREA Support */ 160 - /*@{*/ 161 - 162 - /* 163 - * Get per-context SAREA. 164 - * 165 - * \param inode device inode. 166 - * \param file_priv DRM file private. 167 - * \param cmd command. 168 - * \param arg user argument pointing to a drm_ctx_priv_map structure. 169 - * \return zero on success or a negative number on failure. 170 - * 171 - * Gets the map from drm_device::ctx_idr with the handle specified and 172 - * returns its handle. 173 - */ 174 - int drm_legacy_getsareactx(struct drm_device *dev, void *data, 175 - struct drm_file *file_priv) 176 - { 177 - struct drm_ctx_priv_map *request = data; 178 - struct drm_local_map *map; 179 - struct drm_map_list *_entry; 180 - 181 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 182 - return -EOPNOTSUPP; 183 - 184 - mutex_lock(&dev->struct_mutex); 185 - 186 - map = idr_find(&dev->ctx_idr, request->ctx_id); 187 - if (!map) { 188 - mutex_unlock(&dev->struct_mutex); 189 - return -EINVAL; 190 - } 191 - 192 - request->handle = NULL; 193 - list_for_each_entry(_entry, &dev->maplist, head) { 194 - if (_entry->map == map) { 195 - request->handle = 196 - (void *)(unsigned long)_entry->user_token; 197 - break; 198 - } 199 - } 200 - 201 - mutex_unlock(&dev->struct_mutex); 202 - 203 - if (request->handle == NULL) 204 - return -EINVAL; 205 - 206 - return 0; 207 - } 208 - 209 - /* 210 - * Set per-context SAREA. 211 - * 212 - * \param inode device inode. 213 - * \param file_priv DRM file private. 214 - * \param cmd command. 215 - * \param arg user argument pointing to a drm_ctx_priv_map structure. 216 - * \return zero on success or a negative number on failure. 217 - * 218 - * Searches the mapping specified in \p arg and update the entry in 219 - * drm_device::ctx_idr with it. 220 - */ 221 - int drm_legacy_setsareactx(struct drm_device *dev, void *data, 222 - struct drm_file *file_priv) 223 - { 224 - struct drm_ctx_priv_map *request = data; 225 - struct drm_local_map *map = NULL; 226 - struct drm_map_list *r_list = NULL; 227 - 228 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 229 - return -EOPNOTSUPP; 230 - 231 - mutex_lock(&dev->struct_mutex); 232 - list_for_each_entry(r_list, &dev->maplist, head) { 233 - if (r_list->map 234 - && r_list->user_token == (unsigned long) request->handle) 235 - goto found; 236 - } 237 - bad: 238 - mutex_unlock(&dev->struct_mutex); 239 - return -EINVAL; 240 - 241 - found: 242 - map = r_list->map; 243 - if (!map) 244 - goto bad; 245 - 246 - if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id))) 247 - goto bad; 248 - 249 - mutex_unlock(&dev->struct_mutex); 250 - 251 - return 0; 252 - } 253 - 254 - /*@}*/ 255 - 256 - /******************************************************************/ 257 - /** \name The actual DRM context handling routines */ 258 - /*@{*/ 259 - 260 - /* 261 - * Switch context. 262 - * 263 - * \param dev DRM device. 264 - * \param old old context handle. 265 - * \param new new context handle. 266 - * \return zero on success or a negative number on failure. 267 - * 268 - * Attempt to set drm_device::context_flag. 269 - */ 270 - static int drm_context_switch(struct drm_device * dev, int old, int new) 271 - { 272 - if (test_and_set_bit(0, &dev->context_flag)) { 273 - DRM_ERROR("Reentering -- FIXME\n"); 274 - return -EBUSY; 275 - } 276 - 277 - DRM_DEBUG("Context switch from %d to %d\n", old, new); 278 - 279 - if (new == dev->last_context) { 280 - clear_bit(0, &dev->context_flag); 281 - return 0; 282 - } 283 - 284 - return 0; 285 - } 286 - 287 - /* 288 - * Complete context switch. 289 - * 290 - * \param dev DRM device. 291 - * \param new new context handle. 292 - * \return zero on success or a negative number on failure. 293 - * 294 - * Updates drm_device::last_context and drm_device::last_switch. Verifies the 295 - * hardware lock is held, clears the drm_device::context_flag and wakes up 296 - * drm_device::context_wait. 297 - */ 298 - static int drm_context_switch_complete(struct drm_device *dev, 299 - struct drm_file *file_priv, int new) 300 - { 301 - dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ 302 - 303 - if (!_DRM_LOCK_IS_HELD(file_priv->master->lock.hw_lock->lock)) { 304 - DRM_ERROR("Lock isn't held after context switch\n"); 305 - } 306 - 307 - /* If a context switch is ever initiated 308 - when the kernel holds the lock, release 309 - that lock here. 310 - */ 311 - clear_bit(0, &dev->context_flag); 312 - 313 - return 0; 314 - } 315 - 316 - /* 317 - * Reserve contexts. 318 - * 319 - * \param inode device inode. 320 - * \param file_priv DRM file private. 321 - * \param cmd command. 322 - * \param arg user argument pointing to a drm_ctx_res structure. 323 - * \return zero on success or a negative number on failure. 324 - */ 325 - int drm_legacy_resctx(struct drm_device *dev, void *data, 326 - struct drm_file *file_priv) 327 - { 328 - struct drm_ctx_res *res = data; 329 - struct drm_ctx ctx; 330 - int i; 331 - 332 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 333 - return -EOPNOTSUPP; 334 - 335 - if (res->count >= DRM_RESERVED_CONTEXTS) { 336 - memset(&ctx, 0, sizeof(ctx)); 337 - for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { 338 - ctx.handle = i; 339 - if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx))) 340 - return -EFAULT; 341 - } 342 - } 343 - res->count = DRM_RESERVED_CONTEXTS; 344 - 345 - return 0; 346 - } 347 - 348 - /* 349 - * Add context. 350 - * 351 - * \param inode device inode. 352 - * \param file_priv DRM file private. 353 - * \param cmd command. 354 - * \param arg user argument pointing to a drm_ctx structure. 355 - * \return zero on success or a negative number on failure. 356 - * 357 - * Get a new handle for the context and copy to userspace. 358 - */ 359 - int drm_legacy_addctx(struct drm_device *dev, void *data, 360 - struct drm_file *file_priv) 361 - { 362 - struct drm_ctx_list *ctx_entry; 363 - struct drm_ctx *ctx = data; 364 - int tmp_handle; 365 - 366 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 367 - return -EOPNOTSUPP; 368 - 369 - tmp_handle = drm_legacy_ctxbitmap_next(dev); 370 - if (tmp_handle == DRM_KERNEL_CONTEXT) { 371 - /* Skip kernel's context and get a new one. */ 372 - tmp_handle = drm_legacy_ctxbitmap_next(dev); 373 - } 374 - DRM_DEBUG("%d\n", tmp_handle); 375 - if (tmp_handle < 0) { 376 - DRM_DEBUG("Not enough free contexts.\n"); 377 - /* Should this return -EBUSY instead? */ 378 - return tmp_handle; 379 - } 380 - 381 - ctx->handle = tmp_handle; 382 - 383 - ctx_entry = kmalloc(sizeof(*ctx_entry), GFP_KERNEL); 384 - if (!ctx_entry) { 385 - DRM_DEBUG("out of memory\n"); 386 - return -ENOMEM; 387 - } 388 - 389 - INIT_LIST_HEAD(&ctx_entry->head); 390 - ctx_entry->handle = ctx->handle; 391 - ctx_entry->tag = file_priv; 392 - 393 - mutex_lock(&dev->ctxlist_mutex); 394 - list_add(&ctx_entry->head, &dev->ctxlist); 395 - mutex_unlock(&dev->ctxlist_mutex); 396 - 397 - return 0; 398 - } 399 - 400 - /* 401 - * Get context. 402 - * 403 - * \param inode device inode. 404 - * \param file_priv DRM file private. 405 - * \param cmd command. 406 - * \param arg user argument pointing to a drm_ctx structure. 407 - * \return zero on success or a negative number on failure. 408 - */ 409 - int drm_legacy_getctx(struct drm_device *dev, void *data, 410 - struct drm_file *file_priv) 411 - { 412 - struct drm_ctx *ctx = data; 413 - 414 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 415 - return -EOPNOTSUPP; 416 - 417 - /* This is 0, because we don't handle any context flags */ 418 - ctx->flags = 0; 419 - 420 - return 0; 421 - } 422 - 423 - /* 424 - * Switch context. 425 - * 426 - * \param inode device inode. 427 - * \param file_priv DRM file private. 428 - * \param cmd command. 429 - * \param arg user argument pointing to a drm_ctx structure. 430 - * \return zero on success or a negative number on failure. 431 - * 432 - * Calls context_switch(). 433 - */ 434 - int drm_legacy_switchctx(struct drm_device *dev, void *data, 435 - struct drm_file *file_priv) 436 - { 437 - struct drm_ctx *ctx = data; 438 - 439 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 440 - return -EOPNOTSUPP; 441 - 442 - DRM_DEBUG("%d\n", ctx->handle); 443 - return drm_context_switch(dev, dev->last_context, ctx->handle); 444 - } 445 - 446 - /* 447 - * New context. 448 - * 449 - * \param inode device inode. 450 - * \param file_priv DRM file private. 451 - * \param cmd command. 452 - * \param arg user argument pointing to a drm_ctx structure. 453 - * \return zero on success or a negative number on failure. 454 - * 455 - * Calls context_switch_complete(). 456 - */ 457 - int drm_legacy_newctx(struct drm_device *dev, void *data, 458 - struct drm_file *file_priv) 459 - { 460 - struct drm_ctx *ctx = data; 461 - 462 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 463 - return -EOPNOTSUPP; 464 - 465 - DRM_DEBUG("%d\n", ctx->handle); 466 - drm_context_switch_complete(dev, file_priv, ctx->handle); 467 - 468 - return 0; 469 - } 470 - 471 - /* 472 - * Remove context. 473 - * 474 - * \param inode device inode. 475 - * \param file_priv DRM file private. 476 - * \param cmd command. 477 - * \param arg user argument pointing to a drm_ctx structure. 478 - * \return zero on success or a negative number on failure. 479 - * 480 - * If not the special kernel context, calls ctxbitmap_free() to free the specified context. 481 - */ 482 - int drm_legacy_rmctx(struct drm_device *dev, void *data, 483 - struct drm_file *file_priv) 484 - { 485 - struct drm_ctx *ctx = data; 486 - 487 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 488 - return -EOPNOTSUPP; 489 - 490 - DRM_DEBUG("%d\n", ctx->handle); 491 - if (ctx->handle != DRM_KERNEL_CONTEXT) { 492 - if (dev->driver->context_dtor) 493 - dev->driver->context_dtor(dev, ctx->handle); 494 - drm_legacy_ctxbitmap_free(dev, ctx->handle); 495 - } 496 - 497 - mutex_lock(&dev->ctxlist_mutex); 498 - if (!list_empty(&dev->ctxlist)) { 499 - struct drm_ctx_list *pos, *n; 500 - 501 - list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { 502 - if (pos->handle == ctx->handle) { 503 - list_del(&pos->head); 504 - kfree(pos); 505 - } 506 - } 507 - } 508 - mutex_unlock(&dev->ctxlist_mutex); 509 - 510 - return 0; 511 - } 512 - 513 - /*@}*/
+2 -5
drivers/gpu/drm/drm_crtc_helper.c
··· 439 439 * @state: atomic state object 440 440 * 441 441 * Provides a default CRTC-state check handler for CRTCs that only have 442 - * one primary plane attached to it. 443 - * 444 - * This is often the case for the CRTC of simple framebuffers. See also 445 - * drm_plane_helper_atomic_check() for the respective plane-state check 446 - * helper function. 442 + * one primary plane attached to it. This is often the case for the CRTC 443 + * of simple framebuffers. 447 444 * 448 445 * RETURNS: 449 446 * Zero on success, or an errno code otherwise.
+1 -1
drivers/gpu/drm/drm_crtc_internal.h
··· 253 253 struct drm_file *file_priv, 254 254 struct drm_mode_object *obj, 255 255 struct drm_property *prop, 256 - uint64_t prop_value); 256 + u64 prop_value, bool async_flip); 257 257 int drm_atomic_get_property(struct drm_mode_object *obj, 258 258 struct drm_property *property, uint64_t *val); 259 259
+2 -1
drivers/gpu/drm/drm_damage_helper.c
··· 241 241 iter->plane_src.x2 = (src.x2 >> 16) + !!(src.x2 & 0xFFFF); 242 242 iter->plane_src.y2 = (src.y2 >> 16) + !!(src.y2 & 0xFFFF); 243 243 244 - if (!iter->clips || !drm_rect_equals(&state->src, &old_state->src)) { 244 + if (!iter->clips || state->ignore_damage_clips || 245 + !drm_rect_equals(&state->src, &old_state->src)) { 245 246 iter->clips = NULL; 246 247 iter->num_clips = 0; 247 248 iter->full_update = true;
+62 -3
drivers/gpu/drm/drm_debugfs.c
··· 314 314 drm_framebuffer_debugfs_init(dev); 315 315 drm_client_debugfs_init(dev); 316 316 } 317 - if (drm_drv_uses_atomic_modeset(dev)) { 317 + if (drm_drv_uses_atomic_modeset(dev)) 318 318 drm_atomic_debugfs_init(dev); 319 - drm_bridge_debugfs_init(dev); 320 - } 321 319 } 322 320 323 321 int drm_debugfs_register(struct drm_minor *minor, int minor_id, ··· 585 587 { 586 588 debugfs_remove_recursive(crtc->debugfs_entry); 587 589 crtc->debugfs_entry = NULL; 590 + } 591 + 592 + static int bridges_show(struct seq_file *m, void *data) 593 + { 594 + struct drm_encoder *encoder = m->private; 595 + struct drm_printer p = drm_seq_file_printer(m); 596 + struct drm_bridge *bridge; 597 + unsigned int idx = 0; 598 + 599 + drm_for_each_bridge_in_chain(encoder, bridge) { 600 + drm_printf(&p, "bridge[%d]: %ps\n", idx++, bridge->funcs); 601 + drm_printf(&p, "\ttype: [%d] %s\n", 602 + bridge->type, 603 + drm_get_connector_type_name(bridge->type)); 604 + #ifdef CONFIG_OF 605 + if (bridge->of_node) 606 + drm_printf(&p, "\tOF: %pOFfc\n", bridge->of_node); 607 + #endif 608 + drm_printf(&p, "\tops: [0x%x]", bridge->ops); 609 + if (bridge->ops & DRM_BRIDGE_OP_DETECT) 610 + drm_puts(&p, " detect"); 611 + if (bridge->ops & DRM_BRIDGE_OP_EDID) 612 + drm_puts(&p, " edid"); 613 + if (bridge->ops & DRM_BRIDGE_OP_HPD) 614 + drm_puts(&p, " hpd"); 615 + if (bridge->ops & DRM_BRIDGE_OP_MODES) 616 + drm_puts(&p, " modes"); 617 + drm_puts(&p, "\n"); 618 + } 619 + 620 + return 0; 621 + } 622 + DEFINE_SHOW_ATTRIBUTE(bridges); 623 + 624 + void drm_debugfs_encoder_add(struct drm_encoder *encoder) 625 + { 626 + struct drm_minor *minor = encoder->dev->primary; 627 + struct dentry *root; 628 + char *name; 629 + 630 + name = kasprintf(GFP_KERNEL, "encoder-%d", encoder->index); 631 + if (!name) 632 + return; 633 + 634 + root = debugfs_create_dir(name, minor->debugfs_root); 635 + kfree(name); 636 + 637 + encoder->debugfs_entry = root; 638 + 639 + /* bridges list */ 640 + debugfs_create_file("bridges", 0444, root, encoder, 641 + &bridges_fops); 642 + 643 + if (encoder->funcs->debugfs_init) 644 + encoder->funcs->debugfs_init(encoder, root); 645 + } 646 + 647 + void drm_debugfs_encoder_remove(struct drm_encoder *encoder) 648 + { 649 + debugfs_remove_recursive(encoder->debugfs_entry); 650 + encoder->debugfs_entry = NULL; 588 651 } 589 652 590 653 #endif /* CONFIG_DEBUG_FS */
-178
drivers/gpu/drm/drm_dma.c
··· 1 - /* 2 - * \file drm_dma.c 3 - * DMA IOCTL and function support 4 - * 5 - * \author Rickard E. (Rik) Faith <faith@valinux.com> 6 - * \author Gareth Hughes <gareth@valinux.com> 7 - */ 8 - 9 - /* 10 - * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com 11 - * 12 - * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. 13 - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 14 - * All Rights Reserved. 15 - * 16 - * Permission is hereby granted, free of charge, to any person obtaining a 17 - * copy of this software and associated documentation files (the "Software"), 18 - * to deal in the Software without restriction, including without limitation 19 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 - * and/or sell copies of the Software, and to permit persons to whom the 21 - * Software is furnished to do so, subject to the following conditions: 22 - * 23 - * The above copyright notice and this permission notice (including the next 24 - * paragraph) shall be included in all copies or substantial portions of the 25 - * Software. 26 - * 27 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 31 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 32 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33 - * OTHER DEALINGS IN THE SOFTWARE. 34 - */ 35 - 36 - #include <linux/export.h> 37 - #include <linux/pci.h> 38 - 39 - #include <drm/drm_drv.h> 40 - #include <drm/drm_print.h> 41 - 42 - #include "drm_legacy.h" 43 - 44 - /** 45 - * drm_legacy_dma_setup() - Initialize the DMA data. 46 - * 47 - * @dev: DRM device. 48 - * Return: zero on success or a negative value on failure. 49 - * 50 - * Allocate and initialize a drm_device_dma structure. 51 - */ 52 - int drm_legacy_dma_setup(struct drm_device *dev) 53 - { 54 - int i; 55 - 56 - if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA) || 57 - !drm_core_check_feature(dev, DRIVER_LEGACY)) 58 - return 0; 59 - 60 - dev->buf_use = 0; 61 - atomic_set(&dev->buf_alloc, 0); 62 - 63 - dev->dma = kzalloc(sizeof(*dev->dma), GFP_KERNEL); 64 - if (!dev->dma) 65 - return -ENOMEM; 66 - 67 - for (i = 0; i <= DRM_MAX_ORDER; i++) 68 - memset(&dev->dma->bufs[i], 0, sizeof(dev->dma->bufs[0])); 69 - 70 - return 0; 71 - } 72 - 73 - /** 74 - * drm_legacy_dma_takedown() - Cleanup the DMA resources. 75 - * 76 - * @dev: DRM device. 77 - * 78 - * Free all pages associated with DMA buffers, the buffers and pages lists, and 79 - * finally the drm_device::dma structure itself. 80 - */ 81 - void drm_legacy_dma_takedown(struct drm_device *dev) 82 - { 83 - struct drm_device_dma *dma = dev->dma; 84 - drm_dma_handle_t *dmah; 85 - int i, j; 86 - 87 - if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA) || 88 - !drm_core_check_feature(dev, DRIVER_LEGACY)) 89 - return; 90 - 91 - if (!dma) 92 - return; 93 - 94 - /* Clear dma buffers */ 95 - for (i = 0; i <= DRM_MAX_ORDER; i++) { 96 - if (dma->bufs[i].seg_count) { 97 - DRM_DEBUG("order %d: buf_count = %d," 98 - " seg_count = %d\n", 99 - i, 100 - dma->bufs[i].buf_count, 101 - dma->bufs[i].seg_count); 102 - for (j = 0; j < dma->bufs[i].seg_count; j++) { 103 - if (dma->bufs[i].seglist[j]) { 104 - dmah = dma->bufs[i].seglist[j]; 105 - dma_free_coherent(dev->dev, 106 - dmah->size, 107 - dmah->vaddr, 108 - dmah->busaddr); 109 - kfree(dmah); 110 - } 111 - } 112 - kfree(dma->bufs[i].seglist); 113 - } 114 - if (dma->bufs[i].buf_count) { 115 - for (j = 0; j < dma->bufs[i].buf_count; j++) { 116 - kfree(dma->bufs[i].buflist[j].dev_private); 117 - } 118 - kfree(dma->bufs[i].buflist); 119 - } 120 - } 121 - 122 - kfree(dma->buflist); 123 - kfree(dma->pagelist); 124 - kfree(dev->dma); 125 - dev->dma = NULL; 126 - } 127 - 128 - /** 129 - * drm_legacy_free_buffer() - Free a buffer. 130 - * 131 - * @dev: DRM device. 132 - * @buf: buffer to free. 133 - * 134 - * Resets the fields of \p buf. 135 - */ 136 - void drm_legacy_free_buffer(struct drm_device *dev, struct drm_buf * buf) 137 - { 138 - if (!buf) 139 - return; 140 - 141 - buf->waiting = 0; 142 - buf->pending = 0; 143 - buf->file_priv = NULL; 144 - buf->used = 0; 145 - } 146 - 147 - /** 148 - * drm_legacy_reclaim_buffers() - Reclaim the buffers. 149 - * 150 - * @dev: DRM device. 151 - * @file_priv: DRM file private. 152 - * 153 - * Frees each buffer associated with \p file_priv not already on the hardware. 154 - */ 155 - void drm_legacy_reclaim_buffers(struct drm_device *dev, 156 - struct drm_file *file_priv) 157 - { 158 - struct drm_device_dma *dma = dev->dma; 159 - int i; 160 - 161 - if (!dma) 162 - return; 163 - for (i = 0; i < dma->buf_count; i++) { 164 - if (dma->buflist[i]->file_priv == file_priv) { 165 - switch (dma->buflist[i]->list) { 166 - case DRM_LIST_NONE: 167 - drm_legacy_free_buffer(dev, dma->buflist[i]); 168 - break; 169 - case DRM_LIST_WAIT: 170 - dma->buflist[i]->list = DRM_LIST_RECLAIM; 171 - break; 172 - default: 173 - /* Buffer already on hardware. */ 174 - break; 175 - } 176 - } 177 - } 178 - }
+8 -19
drivers/gpu/drm/drm_drv.c
··· 48 48 49 49 #include "drm_crtc_internal.h" 50 50 #include "drm_internal.h" 51 - #include "drm_legacy.h" 52 51 53 52 MODULE_AUTHOR("Gareth Hughes, Leif Delgass, José Fonseca, Jon Smirl"); 54 53 MODULE_DESCRIPTION("DRM shared core routines"); ··· 584 585 585 586 static void drm_dev_init_release(struct drm_device *dev, void *res) 586 587 { 587 - drm_legacy_ctxbitmap_cleanup(dev); 588 - drm_legacy_remove_map_hash(dev); 589 588 drm_fs_inode_free(dev->anon_inode); 590 589 591 590 put_device(dev->dev); ··· 594 597 mutex_destroy(&dev->clientlist_mutex); 595 598 mutex_destroy(&dev->filelist_mutex); 596 599 mutex_destroy(&dev->struct_mutex); 597 - drm_legacy_destroy_members(dev); 598 600 } 599 601 600 602 static int drm_dev_init(struct drm_device *dev, ··· 628 632 return -EINVAL; 629 633 } 630 634 631 - drm_legacy_init_members(dev); 632 635 INIT_LIST_HEAD(&dev->filelist); 633 636 INIT_LIST_HEAD(&dev->filelist_internal); 634 637 INIT_LIST_HEAD(&dev->clientlist); ··· 667 672 if (ret) 668 673 goto err; 669 674 } 670 - 671 - ret = drm_legacy_create_map_hash(dev); 672 - if (ret) 673 - goto err; 674 - 675 - drm_legacy_ctxbitmap_init(dev); 676 675 677 676 if (drm_core_check_feature(dev, DRIVER_GEM)) { 678 677 ret = drm_gem_init(dev); ··· 938 949 goto err_minors; 939 950 } 940 951 941 - if (drm_core_check_feature(dev, DRIVER_MODESET)) 942 - drm_modeset_register_all(dev); 952 + if (drm_core_check_feature(dev, DRIVER_MODESET)) { 953 + ret = drm_modeset_register_all(dev); 954 + if (ret) 955 + goto err_unload; 956 + } 943 957 944 958 DRM_INFO("Initialized %s %d.%d.%d %s for %s on minor %d\n", 945 959 driver->name, driver->major, driver->minor, ··· 952 960 953 961 goto out_unlock; 954 962 963 + err_unload: 964 + if (dev->driver->unload) 965 + dev->driver->unload(dev); 955 966 err_minors: 956 967 remove_compat_control_link(dev); 957 968 drm_minor_unregister(dev, DRM_MINOR_ACCEL); ··· 985 990 */ 986 991 void drm_dev_unregister(struct drm_device *dev) 987 992 { 988 - if (drm_core_check_feature(dev, DRIVER_LEGACY)) 989 - drm_lastclose(dev); 990 - 991 993 dev->registered = false; 992 994 993 995 drm_client_dev_unregister(dev); ··· 994 1002 995 1003 if (dev->driver->unload) 996 1004 dev->driver->unload(dev); 997 - 998 - drm_legacy_pci_agp_destroy(dev); 999 - drm_legacy_rmmaps(dev); 1000 1005 1001 1006 remove_compat_control_link(dev); 1002 1007 drm_minor_unregister(dev, DRM_MINOR_ACCEL);
+4
drivers/gpu/drm/drm_encoder.c
··· 30 30 #include <drm/drm_print.h> 31 31 32 32 #include "drm_crtc_internal.h" 33 + #include "drm_internal.h" 33 34 34 35 /** 35 36 * DOC: overview ··· 75 74 int ret = 0; 76 75 77 76 drm_for_each_encoder(encoder, dev) { 77 + drm_debugfs_encoder_add(encoder); 78 + 78 79 if (encoder->funcs && encoder->funcs->late_register) 79 80 ret = encoder->funcs->late_register(encoder); 80 81 if (ret) ··· 93 90 drm_for_each_encoder(encoder, dev) { 94 91 if (encoder->funcs && encoder->funcs->early_unregister) 95 92 encoder->funcs->early_unregister(encoder); 93 + drm_debugfs_encoder_remove(encoder); 96 94 } 97 95 } 98 96
+3 -63
drivers/gpu/drm/drm_file.c
··· 47 47 48 48 #include "drm_crtc_internal.h" 49 49 #include "drm_internal.h" 50 - #include "drm_legacy.h" 51 50 52 51 /* from BKL pushdown */ 53 52 DEFINE_MUTEX(drm_global_mutex); 54 53 55 54 bool drm_dev_needs_global_mutex(struct drm_device *dev) 56 55 { 57 - /* 58 - * Legacy drivers rely on all kinds of BKL locking semantics, don't 59 - * bother. They also still need BKL locking for their ioctls, so better 60 - * safe than sorry. 61 - */ 62 - if (drm_core_check_feature(dev, DRIVER_LEGACY)) 63 - return true; 64 - 65 56 /* 66 57 * The deprecated ->load callback must be called after the driver is 67 58 * already registered. This means such drivers rely on the BKL to make ··· 98 107 * drm_send_event() as the main starting points. 99 108 * 100 109 * The memory mapping implementation will vary depending on how the driver 101 - * manages memory. Legacy drivers will use the deprecated drm_legacy_mmap() 102 - * function, modern drivers should use one of the provided memory-manager 103 - * specific implementations. For GEM-based drivers this is drm_gem_mmap(). 110 + * manages memory. For GEM-based drivers this is drm_gem_mmap(). 104 111 * 105 112 * No other file operations are supported by the DRM userspace API. Overall the 106 113 * following is an example &file_operations structure:: ··· 243 254 (long)old_encode_dev(file->minor->kdev->devt), 244 255 atomic_read(&dev->open_count)); 245 256 246 - #ifdef CONFIG_DRM_LEGACY 247 - if (drm_core_check_feature(dev, DRIVER_LEGACY) && 248 - dev->driver->preclose) 249 - dev->driver->preclose(dev, file); 250 - #endif 251 - 252 - if (drm_core_check_feature(dev, DRIVER_LEGACY)) 253 - drm_legacy_lock_release(dev, file->filp); 254 - 255 - if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) 256 - drm_legacy_reclaim_buffers(dev, file); 257 - 258 257 drm_events_release(file); 259 258 260 259 if (drm_core_check_feature(dev, DRIVER_MODESET)) { ··· 255 278 256 279 if (drm_core_check_feature(dev, DRIVER_GEM)) 257 280 drm_gem_release(dev, file); 258 - 259 - drm_legacy_ctxbitmap_flush(dev, file); 260 281 261 282 if (drm_is_primary_client(file)) 262 283 drm_master_release(file); ··· 342 367 list_add(&priv->lhead, &dev->filelist); 343 368 mutex_unlock(&dev->filelist_mutex); 344 369 345 - #ifdef CONFIG_DRM_LEGACY 346 - #ifdef __alpha__ 347 - /* 348 - * Default the hose 349 - */ 350 - if (!dev->hose) { 351 - struct pci_dev *pci_dev; 352 - 353 - pci_dev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, NULL); 354 - if (pci_dev) { 355 - dev->hose = pci_dev->sysdata; 356 - pci_dev_put(pci_dev); 357 - } 358 - if (!dev->hose) { 359 - struct pci_bus *b = list_entry(pci_root_buses.next, 360 - struct pci_bus, node); 361 - if (b) 362 - dev->hose = b->sysdata; 363 - } 364 - } 365 - #endif 366 - #endif 367 - 368 370 return 0; 369 371 } 370 372 ··· 363 411 struct drm_device *dev; 364 412 struct drm_minor *minor; 365 413 int retcode; 366 - int need_setup = 0; 367 414 368 415 minor = drm_minor_acquire(iminor(inode)); 369 416 if (IS_ERR(minor)) ··· 372 421 if (drm_dev_needs_global_mutex(dev)) 373 422 mutex_lock(&drm_global_mutex); 374 423 375 - if (!atomic_fetch_inc(&dev->open_count)) 376 - need_setup = 1; 424 + atomic_fetch_inc(&dev->open_count); 377 425 378 426 /* share address_space across all char-devs of a single device */ 379 427 filp->f_mapping = dev->anon_inode->i_mapping; ··· 380 430 retcode = drm_open_helper(filp, minor); 381 431 if (retcode) 382 432 goto err_undo; 383 - if (need_setup) { 384 - retcode = drm_legacy_setup(dev); 385 - if (retcode) { 386 - drm_close_helper(filp); 387 - goto err_undo; 388 - } 389 - } 390 433 391 434 if (drm_dev_needs_global_mutex(dev)) 392 435 mutex_unlock(&drm_global_mutex); ··· 402 459 if (dev->driver->lastclose) 403 460 dev->driver->lastclose(dev); 404 461 drm_dbg_core(dev, "driver lastclose completed\n"); 405 - 406 - if (drm_core_check_feature(dev, DRIVER_LEGACY)) 407 - drm_legacy_dev_reinit(dev); 408 462 409 463 drm_client_dev_restore(dev); 410 464 } ··· 898 958 { 899 959 struct drm_gem_object *obj; 900 960 struct drm_memory_stats status = {}; 901 - enum drm_gem_object_status supported_status; 961 + enum drm_gem_object_status supported_status = 0; 902 962 int id; 903 963 904 964 spin_lock(&file->table_lock);
+1 -1
drivers/gpu/drm/drm_framebuffer.c
··· 583 583 struct drm_mode_fb_cmd2 *r = data; 584 584 struct drm_framebuffer *fb; 585 585 unsigned int i; 586 - int ret; 586 + int ret = 0; 587 587 588 588 if (!drm_core_check_feature(dev, DRIVER_MODESET)) 589 589 return -EINVAL;
+44 -7
drivers/gpu/drm/drm_gpuvm.c
··· 1086 1086 EXPORT_SYMBOL_GPL(drm_gpuvm_put); 1087 1087 1088 1088 static int 1089 + exec_prepare_obj(struct drm_exec *exec, struct drm_gem_object *obj, 1090 + unsigned int num_fences) 1091 + { 1092 + return num_fences ? drm_exec_prepare_obj(exec, obj, num_fences) : 1093 + drm_exec_lock_obj(exec, obj); 1094 + } 1095 + 1096 + /** 1097 + * drm_gpuvm_prepare_vm() - prepare the GPUVMs common dma-resv 1098 + * @gpuvm: the &drm_gpuvm 1099 + * @exec: the &drm_exec context 1100 + * @num_fences: the amount of &dma_fences to reserve 1101 + * 1102 + * Calls drm_exec_prepare_obj() for the GPUVMs dummy &drm_gem_object; if 1103 + * @num_fences is zero drm_exec_lock_obj() is called instead. 1104 + * 1105 + * Using this function directly, it is the drivers responsibility to call 1106 + * drm_exec_init() and drm_exec_fini() accordingly. 1107 + * 1108 + * Returns: 0 on success, negative error code on failure. 1109 + */ 1110 + int 1111 + drm_gpuvm_prepare_vm(struct drm_gpuvm *gpuvm, 1112 + struct drm_exec *exec, 1113 + unsigned int num_fences) 1114 + { 1115 + return exec_prepare_obj(exec, gpuvm->r_obj, num_fences); 1116 + } 1117 + EXPORT_SYMBOL_GPL(drm_gpuvm_prepare_vm); 1118 + 1119 + static int 1089 1120 __drm_gpuvm_prepare_objects(struct drm_gpuvm *gpuvm, 1090 1121 struct drm_exec *exec, 1091 1122 unsigned int num_fences) ··· 1126 1095 int ret = 0; 1127 1096 1128 1097 for_each_vm_bo_in_list(gpuvm, extobj, &extobjs, vm_bo) { 1129 - ret = drm_exec_prepare_obj(exec, vm_bo->obj, num_fences); 1098 + ret = exec_prepare_obj(exec, vm_bo->obj, num_fences); 1130 1099 if (ret) 1131 1100 break; 1132 1101 } ··· 1147 1116 1148 1117 drm_gpuvm_resv_assert_held(gpuvm); 1149 1118 list_for_each_entry(vm_bo, &gpuvm->extobj.list, list.entry.extobj) { 1150 - ret = drm_exec_prepare_obj(exec, vm_bo->obj, num_fences); 1119 + ret = exec_prepare_obj(exec, vm_bo->obj, num_fences); 1151 1120 if (ret) 1152 1121 break; 1153 1122 ··· 1165 1134 * @num_fences: the amount of &dma_fences to reserve 1166 1135 * 1167 1136 * Calls drm_exec_prepare_obj() for all &drm_gem_objects the given 1168 - * &drm_gpuvm contains mappings of. 1137 + * &drm_gpuvm contains mappings of; if @num_fences is zero drm_exec_lock_obj() 1138 + * is called instead. 1169 1139 * 1170 1140 * Using this function directly, it is the drivers responsibility to call 1171 1141 * drm_exec_init() and drm_exec_fini() accordingly. ··· 1203 1171 * @num_fences: the amount of &dma_fences to reserve 1204 1172 * 1205 1173 * Calls drm_exec_prepare_obj() for all &drm_gem_objects mapped between @addr 1206 - * and @addr + @range. 1174 + * and @addr + @range; if @num_fences is zero drm_exec_lock_obj() is called 1175 + * instead. 1207 1176 * 1208 1177 * Returns: 0 on success, negative error code on failure. 1209 1178 */ ··· 1219 1186 drm_gpuvm_for_each_va_range(va, gpuvm, addr, end) { 1220 1187 struct drm_gem_object *obj = va->gem.obj; 1221 1188 1222 - ret = drm_exec_prepare_obj(exec, obj, num_fences); 1189 + ret = exec_prepare_obj(exec, obj, num_fences); 1223 1190 if (ret) 1224 1191 return ret; 1225 1192 } ··· 1535 1502 * hold the dma-resv or driver specific GEM gpuva lock. 1536 1503 * 1537 1504 * This function may only be called from non-atomic context. 1505 + * 1506 + * Returns: true if vm_bo was destroyed, false otherwise. 1538 1507 */ 1539 - void 1508 + bool 1540 1509 drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo) 1541 1510 { 1542 1511 might_sleep(); 1543 1512 1544 1513 if (vm_bo) 1545 - kref_put(&vm_bo->kref, drm_gpuvm_bo_destroy); 1514 + return !!kref_put(&vm_bo->kref, drm_gpuvm_bo_destroy); 1515 + 1516 + return false; 1546 1517 } 1547 1518 EXPORT_SYMBOL_GPL(drm_gpuvm_bo_put); 1548 1519
-203
drivers/gpu/drm/drm_hashtab.c
··· 1 - /************************************************************************** 2 - * 3 - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA. 4 - * All Rights Reserved. 5 - * 6 - * Permission is hereby granted, free of charge, to any person obtaining a 7 - * copy of this software and associated documentation files (the 8 - * "Software"), to deal in the Software without restriction, including 9 - * without limitation the rights to use, copy, modify, merge, publish, 10 - * distribute, sub license, and/or sell copies of the Software, and to 11 - * permit persons to whom the Software is furnished to do so, subject to 12 - * the following conditions: 13 - * 14 - * The above copyright notice and this permission notice (including the 15 - * next paragraph) shall be included in all copies or substantial portions 16 - * of the Software. 17 - * 18 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21 - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22 - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23 - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24 - * USE OR OTHER DEALINGS IN THE SOFTWARE. 25 - * 26 - * 27 - **************************************************************************/ 28 - /* 29 - * Simple open hash tab implementation. 30 - * 31 - * Authors: 32 - * Thomas Hellström <thomas-at-tungstengraphics-dot-com> 33 - */ 34 - 35 - #include <linux/hash.h> 36 - #include <linux/mm.h> 37 - #include <linux/rculist.h> 38 - #include <linux/slab.h> 39 - #include <linux/vmalloc.h> 40 - 41 - #include <drm/drm_print.h> 42 - 43 - #include "drm_legacy.h" 44 - 45 - int drm_ht_create(struct drm_open_hash *ht, unsigned int order) 46 - { 47 - unsigned int size = 1 << order; 48 - 49 - ht->order = order; 50 - ht->table = NULL; 51 - if (size <= PAGE_SIZE / sizeof(*ht->table)) 52 - ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL); 53 - else 54 - ht->table = vzalloc(array_size(size, sizeof(*ht->table))); 55 - if (!ht->table) { 56 - DRM_ERROR("Out of memory for hash table\n"); 57 - return -ENOMEM; 58 - } 59 - return 0; 60 - } 61 - 62 - void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key) 63 - { 64 - struct drm_hash_item *entry; 65 - struct hlist_head *h_list; 66 - unsigned int hashed_key; 67 - int count = 0; 68 - 69 - hashed_key = hash_long(key, ht->order); 70 - DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key); 71 - h_list = &ht->table[hashed_key]; 72 - hlist_for_each_entry(entry, h_list, head) 73 - DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key); 74 - } 75 - 76 - static struct hlist_node *drm_ht_find_key(struct drm_open_hash *ht, 77 - unsigned long key) 78 - { 79 - struct drm_hash_item *entry; 80 - struct hlist_head *h_list; 81 - unsigned int hashed_key; 82 - 83 - hashed_key = hash_long(key, ht->order); 84 - h_list = &ht->table[hashed_key]; 85 - hlist_for_each_entry(entry, h_list, head) { 86 - if (entry->key == key) 87 - return &entry->head; 88 - if (entry->key > key) 89 - break; 90 - } 91 - return NULL; 92 - } 93 - 94 - static struct hlist_node *drm_ht_find_key_rcu(struct drm_open_hash *ht, 95 - unsigned long key) 96 - { 97 - struct drm_hash_item *entry; 98 - struct hlist_head *h_list; 99 - unsigned int hashed_key; 100 - 101 - hashed_key = hash_long(key, ht->order); 102 - h_list = &ht->table[hashed_key]; 103 - hlist_for_each_entry_rcu(entry, h_list, head) { 104 - if (entry->key == key) 105 - return &entry->head; 106 - if (entry->key > key) 107 - break; 108 - } 109 - return NULL; 110 - } 111 - 112 - int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item) 113 - { 114 - struct drm_hash_item *entry; 115 - struct hlist_head *h_list; 116 - struct hlist_node *parent; 117 - unsigned int hashed_key; 118 - unsigned long key = item->key; 119 - 120 - hashed_key = hash_long(key, ht->order); 121 - h_list = &ht->table[hashed_key]; 122 - parent = NULL; 123 - hlist_for_each_entry(entry, h_list, head) { 124 - if (entry->key == key) 125 - return -EINVAL; 126 - if (entry->key > key) 127 - break; 128 - parent = &entry->head; 129 - } 130 - if (parent) { 131 - hlist_add_behind_rcu(&item->head, parent); 132 - } else { 133 - hlist_add_head_rcu(&item->head, h_list); 134 - } 135 - return 0; 136 - } 137 - 138 - /* 139 - * Just insert an item and return any "bits" bit key that hasn't been 140 - * used before. 141 - */ 142 - int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item, 143 - unsigned long seed, int bits, int shift, 144 - unsigned long add) 145 - { 146 - int ret; 147 - unsigned long mask = (1UL << bits) - 1; 148 - unsigned long first, unshifted_key; 149 - 150 - unshifted_key = hash_long(seed, bits); 151 - first = unshifted_key; 152 - do { 153 - item->key = (unshifted_key << shift) + add; 154 - ret = drm_ht_insert_item(ht, item); 155 - if (ret) 156 - unshifted_key = (unshifted_key + 1) & mask; 157 - } while(ret && (unshifted_key != first)); 158 - 159 - if (ret) { 160 - DRM_ERROR("Available key bit space exhausted\n"); 161 - return -EINVAL; 162 - } 163 - return 0; 164 - } 165 - 166 - int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, 167 - struct drm_hash_item **item) 168 - { 169 - struct hlist_node *list; 170 - 171 - list = drm_ht_find_key_rcu(ht, key); 172 - if (!list) 173 - return -EINVAL; 174 - 175 - *item = hlist_entry(list, struct drm_hash_item, head); 176 - return 0; 177 - } 178 - 179 - int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key) 180 - { 181 - struct hlist_node *list; 182 - 183 - list = drm_ht_find_key(ht, key); 184 - if (list) { 185 - hlist_del_init_rcu(list); 186 - return 0; 187 - } 188 - return -EINVAL; 189 - } 190 - 191 - int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item) 192 - { 193 - hlist_del_init_rcu(&item->head); 194 - return 0; 195 - } 196 - 197 - void drm_ht_remove(struct drm_open_hash *ht) 198 - { 199 - if (ht->table) { 200 - kvfree(ht->table); 201 - ht->table = NULL; 202 - } 203 - }
+10 -7
drivers/gpu/drm/drm_internal.h
··· 117 117 /* IOCTLS */ 118 118 int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, 119 119 struct drm_file *filp); 120 - int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data, 121 - struct drm_file *file_priv); 122 120 123 121 /* drm_irq.c */ 124 122 125 123 /* IOCTLS */ 126 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 127 - int drm_legacy_irq_control(struct drm_device *dev, void *data, 128 - struct drm_file *file_priv); 129 - #endif 130 - 131 124 int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data, 132 125 struct drm_file *filp); 133 126 ··· 187 194 void drm_debugfs_crtc_add(struct drm_crtc *crtc); 188 195 void drm_debugfs_crtc_remove(struct drm_crtc *crtc); 189 196 void drm_debugfs_crtc_crc_add(struct drm_crtc *crtc); 197 + void drm_debugfs_encoder_add(struct drm_encoder *encoder); 198 + void drm_debugfs_encoder_remove(struct drm_encoder *encoder); 190 199 #else 191 200 static inline void drm_debugfs_dev_fini(struct drm_device *dev) 192 201 { ··· 223 228 } 224 229 225 230 static inline void drm_debugfs_crtc_crc_add(struct drm_crtc *crtc) 231 + { 232 + } 233 + 234 + static inline void drm_debugfs_encoder_add(struct drm_encoder *encoder) 235 + { 236 + } 237 + 238 + static inline void drm_debugfs_encoder_remove(struct drm_encoder *encoder) 226 239 { 227 240 } 228 241
+2 -611
drivers/gpu/drm/drm_ioc32.c
··· 31 31 #include <linux/ratelimit.h> 32 32 #include <linux/export.h> 33 33 34 + #include <drm/drm_device.h> 34 35 #include <drm/drm_file.h> 35 36 #include <drm/drm_print.h> 36 37 37 38 #include "drm_crtc_internal.h" 38 39 #include "drm_internal.h" 39 - #include "drm_legacy.h" 40 40 41 41 #define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t) 42 42 #define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t) ··· 163 163 return -EINVAL; 164 164 } 165 165 166 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 167 - typedef struct drm_map32 { 168 - u32 offset; /* Requested physical address (0 for SAREA) */ 169 - u32 size; /* Requested physical size (bytes) */ 170 - enum drm_map_type type; /* Type of memory to map */ 171 - enum drm_map_flags flags; /* Flags */ 172 - u32 handle; /* User-space: "Handle" to pass to mmap() */ 173 - int mtrr; /* MTRR slot used */ 174 - } drm_map32_t; 175 - 176 - static int compat_drm_getmap(struct file *file, unsigned int cmd, 177 - unsigned long arg) 178 - { 179 - drm_map32_t __user *argp = (void __user *)arg; 180 - drm_map32_t m32; 181 - struct drm_map map; 182 - int err; 183 - 184 - if (copy_from_user(&m32, argp, sizeof(m32))) 185 - return -EFAULT; 186 - 187 - map.offset = m32.offset; 188 - err = drm_ioctl_kernel(file, drm_legacy_getmap_ioctl, &map, 0); 189 - if (err) 190 - return err; 191 - 192 - m32.offset = map.offset; 193 - m32.size = map.size; 194 - m32.type = map.type; 195 - m32.flags = map.flags; 196 - m32.handle = ptr_to_compat((void __user *)map.handle); 197 - m32.mtrr = map.mtrr; 198 - if (copy_to_user(argp, &m32, sizeof(m32))) 199 - return -EFAULT; 200 - return 0; 201 - 202 - } 203 - 204 - static int compat_drm_addmap(struct file *file, unsigned int cmd, 205 - unsigned long arg) 206 - { 207 - drm_map32_t __user *argp = (void __user *)arg; 208 - drm_map32_t m32; 209 - struct drm_map map; 210 - int err; 211 - 212 - if (copy_from_user(&m32, argp, sizeof(m32))) 213 - return -EFAULT; 214 - 215 - map.offset = m32.offset; 216 - map.size = m32.size; 217 - map.type = m32.type; 218 - map.flags = m32.flags; 219 - 220 - err = drm_ioctl_kernel(file, drm_legacy_addmap_ioctl, &map, 221 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 222 - if (err) 223 - return err; 224 - 225 - m32.offset = map.offset; 226 - m32.mtrr = map.mtrr; 227 - m32.handle = ptr_to_compat((void __user *)map.handle); 228 - if (map.handle != compat_ptr(m32.handle)) 229 - pr_err_ratelimited("compat_drm_addmap truncated handle %p for type %d offset %x\n", 230 - map.handle, m32.type, m32.offset); 231 - 232 - if (copy_to_user(argp, &m32, sizeof(m32))) 233 - return -EFAULT; 234 - 235 - return 0; 236 - } 237 - 238 - static int compat_drm_rmmap(struct file *file, unsigned int cmd, 239 - unsigned long arg) 240 - { 241 - drm_map32_t __user *argp = (void __user *)arg; 242 - struct drm_map map; 243 - u32 handle; 244 - 245 - if (get_user(handle, &argp->handle)) 246 - return -EFAULT; 247 - map.handle = compat_ptr(handle); 248 - return drm_ioctl_kernel(file, drm_legacy_rmmap_ioctl, &map, DRM_AUTH); 249 - } 250 - #endif 251 - 252 166 typedef struct drm_client32 { 253 167 int idx; /* Which client desired? */ 254 168 int auth; /* Is client authenticated? */ ··· 222 308 return 0; 223 309 } 224 310 225 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 226 - typedef struct drm_buf_desc32 { 227 - int count; /* Number of buffers of this size */ 228 - int size; /* Size in bytes */ 229 - int low_mark; /* Low water mark */ 230 - int high_mark; /* High water mark */ 231 - int flags; 232 - u32 agp_start; /* Start address in the AGP aperture */ 233 - } drm_buf_desc32_t; 234 - 235 - static int compat_drm_addbufs(struct file *file, unsigned int cmd, 236 - unsigned long arg) 237 - { 238 - drm_buf_desc32_t __user *argp = (void __user *)arg; 239 - drm_buf_desc32_t desc32; 240 - struct drm_buf_desc desc; 241 - int err; 242 - 243 - if (copy_from_user(&desc32, argp, sizeof(drm_buf_desc32_t))) 244 - return -EFAULT; 245 - 246 - desc = (struct drm_buf_desc){ 247 - desc32.count, desc32.size, desc32.low_mark, desc32.high_mark, 248 - desc32.flags, desc32.agp_start 249 - }; 250 - 251 - err = drm_ioctl_kernel(file, drm_legacy_addbufs, &desc, 252 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 253 - if (err) 254 - return err; 255 - 256 - desc32 = (drm_buf_desc32_t){ 257 - desc.count, desc.size, desc.low_mark, desc.high_mark, 258 - desc.flags, desc.agp_start 259 - }; 260 - if (copy_to_user(argp, &desc32, sizeof(drm_buf_desc32_t))) 261 - return -EFAULT; 262 - 263 - return 0; 264 - } 265 - 266 - static int compat_drm_markbufs(struct file *file, unsigned int cmd, 267 - unsigned long arg) 268 - { 269 - drm_buf_desc32_t b32; 270 - drm_buf_desc32_t __user *argp = (void __user *)arg; 271 - struct drm_buf_desc buf; 272 - 273 - if (copy_from_user(&b32, argp, sizeof(b32))) 274 - return -EFAULT; 275 - 276 - buf.size = b32.size; 277 - buf.low_mark = b32.low_mark; 278 - buf.high_mark = b32.high_mark; 279 - 280 - return drm_ioctl_kernel(file, drm_legacy_markbufs, &buf, 281 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 282 - } 283 - 284 - typedef struct drm_buf_info32 { 285 - int count; /**< Entries in list */ 286 - u32 list; 287 - } drm_buf_info32_t; 288 - 289 - static int copy_one_buf32(void *data, int count, struct drm_buf_entry *from) 290 - { 291 - drm_buf_info32_t *request = data; 292 - drm_buf_desc32_t __user *to = compat_ptr(request->list); 293 - drm_buf_desc32_t v = {.count = from->buf_count, 294 - .size = from->buf_size, 295 - .low_mark = from->low_mark, 296 - .high_mark = from->high_mark}; 297 - 298 - if (copy_to_user(to + count, &v, offsetof(drm_buf_desc32_t, flags))) 299 - return -EFAULT; 300 - return 0; 301 - } 302 - 303 - static int drm_legacy_infobufs32(struct drm_device *dev, void *data, 304 - struct drm_file *file_priv) 305 - { 306 - drm_buf_info32_t *request = data; 307 - 308 - return __drm_legacy_infobufs(dev, data, &request->count, copy_one_buf32); 309 - } 310 - 311 - static int compat_drm_infobufs(struct file *file, unsigned int cmd, 312 - unsigned long arg) 313 - { 314 - drm_buf_info32_t req32; 315 - drm_buf_info32_t __user *argp = (void __user *)arg; 316 - int err; 317 - 318 - if (copy_from_user(&req32, argp, sizeof(req32))) 319 - return -EFAULT; 320 - 321 - if (req32.count < 0) 322 - req32.count = 0; 323 - 324 - err = drm_ioctl_kernel(file, drm_legacy_infobufs32, &req32, DRM_AUTH); 325 - if (err) 326 - return err; 327 - 328 - if (put_user(req32.count, &argp->count)) 329 - return -EFAULT; 330 - 331 - return 0; 332 - } 333 - 334 - typedef struct drm_buf_pub32 { 335 - int idx; /**< Index into the master buffer list */ 336 - int total; /**< Buffer size */ 337 - int used; /**< Amount of buffer in use (for DMA) */ 338 - u32 address; /**< Address of buffer */ 339 - } drm_buf_pub32_t; 340 - 341 - typedef struct drm_buf_map32 { 342 - int count; /**< Length of the buffer list */ 343 - u32 virtual; /**< Mmap'd area in user-virtual */ 344 - u32 list; /**< Buffer information */ 345 - } drm_buf_map32_t; 346 - 347 - static int map_one_buf32(void *data, int idx, unsigned long virtual, 348 - struct drm_buf *buf) 349 - { 350 - drm_buf_map32_t *request = data; 351 - drm_buf_pub32_t __user *to = compat_ptr(request->list) + idx; 352 - drm_buf_pub32_t v; 353 - 354 - v.idx = buf->idx; 355 - v.total = buf->total; 356 - v.used = 0; 357 - v.address = virtual + buf->offset; 358 - if (copy_to_user(to, &v, sizeof(v))) 359 - return -EFAULT; 360 - return 0; 361 - } 362 - 363 - static int drm_legacy_mapbufs32(struct drm_device *dev, void *data, 364 - struct drm_file *file_priv) 365 - { 366 - drm_buf_map32_t *request = data; 367 - void __user *v; 368 - int err = __drm_legacy_mapbufs(dev, data, &request->count, 369 - &v, map_one_buf32, 370 - file_priv); 371 - request->virtual = ptr_to_compat(v); 372 - return err; 373 - } 374 - 375 - static int compat_drm_mapbufs(struct file *file, unsigned int cmd, 376 - unsigned long arg) 377 - { 378 - drm_buf_map32_t __user *argp = (void __user *)arg; 379 - drm_buf_map32_t req32; 380 - int err; 381 - 382 - if (copy_from_user(&req32, argp, sizeof(req32))) 383 - return -EFAULT; 384 - if (req32.count < 0) 385 - return -EINVAL; 386 - 387 - err = drm_ioctl_kernel(file, drm_legacy_mapbufs32, &req32, DRM_AUTH); 388 - if (err) 389 - return err; 390 - 391 - if (put_user(req32.count, &argp->count) 392 - || put_user(req32.virtual, &argp->virtual)) 393 - return -EFAULT; 394 - 395 - return 0; 396 - } 397 - 398 - typedef struct drm_buf_free32 { 399 - int count; 400 - u32 list; 401 - } drm_buf_free32_t; 402 - 403 - static int compat_drm_freebufs(struct file *file, unsigned int cmd, 404 - unsigned long arg) 405 - { 406 - drm_buf_free32_t req32; 407 - struct drm_buf_free request; 408 - drm_buf_free32_t __user *argp = (void __user *)arg; 409 - 410 - if (copy_from_user(&req32, argp, sizeof(req32))) 411 - return -EFAULT; 412 - 413 - request.count = req32.count; 414 - request.list = compat_ptr(req32.list); 415 - return drm_ioctl_kernel(file, drm_legacy_freebufs, &request, DRM_AUTH); 416 - } 417 - 418 - typedef struct drm_ctx_priv_map32 { 419 - unsigned int ctx_id; /**< Context requesting private mapping */ 420 - u32 handle; /**< Handle of map */ 421 - } drm_ctx_priv_map32_t; 422 - 423 - static int compat_drm_setsareactx(struct file *file, unsigned int cmd, 424 - unsigned long arg) 425 - { 426 - drm_ctx_priv_map32_t req32; 427 - struct drm_ctx_priv_map request; 428 - drm_ctx_priv_map32_t __user *argp = (void __user *)arg; 429 - 430 - if (copy_from_user(&req32, argp, sizeof(req32))) 431 - return -EFAULT; 432 - 433 - request.ctx_id = req32.ctx_id; 434 - request.handle = compat_ptr(req32.handle); 435 - return drm_ioctl_kernel(file, drm_legacy_setsareactx, &request, 436 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 437 - } 438 - 439 - static int compat_drm_getsareactx(struct file *file, unsigned int cmd, 440 - unsigned long arg) 441 - { 442 - struct drm_ctx_priv_map req; 443 - drm_ctx_priv_map32_t req32; 444 - drm_ctx_priv_map32_t __user *argp = (void __user *)arg; 445 - int err; 446 - 447 - if (copy_from_user(&req32, argp, sizeof(req32))) 448 - return -EFAULT; 449 - 450 - req.ctx_id = req32.ctx_id; 451 - err = drm_ioctl_kernel(file, drm_legacy_getsareactx, &req, DRM_AUTH); 452 - if (err) 453 - return err; 454 - 455 - req32.handle = ptr_to_compat((void __user *)req.handle); 456 - if (copy_to_user(argp, &req32, sizeof(req32))) 457 - return -EFAULT; 458 - 459 - return 0; 460 - } 461 - 462 - typedef struct drm_ctx_res32 { 463 - int count; 464 - u32 contexts; 465 - } drm_ctx_res32_t; 466 - 467 - static int compat_drm_resctx(struct file *file, unsigned int cmd, 468 - unsigned long arg) 469 - { 470 - drm_ctx_res32_t __user *argp = (void __user *)arg; 471 - drm_ctx_res32_t res32; 472 - struct drm_ctx_res res; 473 - int err; 474 - 475 - if (copy_from_user(&res32, argp, sizeof(res32))) 476 - return -EFAULT; 477 - 478 - res.count = res32.count; 479 - res.contexts = compat_ptr(res32.contexts); 480 - err = drm_ioctl_kernel(file, drm_legacy_resctx, &res, DRM_AUTH); 481 - if (err) 482 - return err; 483 - 484 - res32.count = res.count; 485 - if (copy_to_user(argp, &res32, sizeof(res32))) 486 - return -EFAULT; 487 - 488 - return 0; 489 - } 490 - 491 - typedef struct drm_dma32 { 492 - int context; /**< Context handle */ 493 - int send_count; /**< Number of buffers to send */ 494 - u32 send_indices; /**< List of handles to buffers */ 495 - u32 send_sizes; /**< Lengths of data to send */ 496 - enum drm_dma_flags flags; /**< Flags */ 497 - int request_count; /**< Number of buffers requested */ 498 - int request_size; /**< Desired size for buffers */ 499 - u32 request_indices; /**< Buffer information */ 500 - u32 request_sizes; 501 - int granted_count; /**< Number of buffers granted */ 502 - } drm_dma32_t; 503 - 504 - static int compat_drm_dma(struct file *file, unsigned int cmd, 505 - unsigned long arg) 506 - { 507 - drm_dma32_t d32; 508 - drm_dma32_t __user *argp = (void __user *)arg; 509 - struct drm_dma d; 510 - int err; 511 - 512 - if (copy_from_user(&d32, argp, sizeof(d32))) 513 - return -EFAULT; 514 - 515 - d.context = d32.context; 516 - d.send_count = d32.send_count; 517 - d.send_indices = compat_ptr(d32.send_indices); 518 - d.send_sizes = compat_ptr(d32.send_sizes); 519 - d.flags = d32.flags; 520 - d.request_count = d32.request_count; 521 - d.request_indices = compat_ptr(d32.request_indices); 522 - d.request_sizes = compat_ptr(d32.request_sizes); 523 - err = drm_ioctl_kernel(file, drm_legacy_dma_ioctl, &d, DRM_AUTH); 524 - if (err) 525 - return err; 526 - 527 - if (put_user(d.request_size, &argp->request_size) 528 - || put_user(d.granted_count, &argp->granted_count)) 529 - return -EFAULT; 530 - 531 - return 0; 532 - } 533 - #endif 534 - 535 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 536 - #if IS_ENABLED(CONFIG_AGP) 537 - typedef struct drm_agp_mode32 { 538 - u32 mode; /**< AGP mode */ 539 - } drm_agp_mode32_t; 540 - 541 - static int compat_drm_agp_enable(struct file *file, unsigned int cmd, 542 - unsigned long arg) 543 - { 544 - drm_agp_mode32_t __user *argp = (void __user *)arg; 545 - struct drm_agp_mode mode; 546 - 547 - if (get_user(mode.mode, &argp->mode)) 548 - return -EFAULT; 549 - 550 - return drm_ioctl_kernel(file, drm_legacy_agp_enable_ioctl, &mode, 551 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 552 - } 553 - 554 - typedef struct drm_agp_info32 { 555 - int agp_version_major; 556 - int agp_version_minor; 557 - u32 mode; 558 - u32 aperture_base; /* physical address */ 559 - u32 aperture_size; /* bytes */ 560 - u32 memory_allowed; /* bytes */ 561 - u32 memory_used; 562 - 563 - /* PCI information */ 564 - unsigned short id_vendor; 565 - unsigned short id_device; 566 - } drm_agp_info32_t; 567 - 568 - static int compat_drm_agp_info(struct file *file, unsigned int cmd, 569 - unsigned long arg) 570 - { 571 - drm_agp_info32_t __user *argp = (void __user *)arg; 572 - drm_agp_info32_t i32; 573 - struct drm_agp_info info; 574 - int err; 575 - 576 - err = drm_ioctl_kernel(file, drm_legacy_agp_info_ioctl, &info, DRM_AUTH); 577 - if (err) 578 - return err; 579 - 580 - i32.agp_version_major = info.agp_version_major; 581 - i32.agp_version_minor = info.agp_version_minor; 582 - i32.mode = info.mode; 583 - i32.aperture_base = info.aperture_base; 584 - i32.aperture_size = info.aperture_size; 585 - i32.memory_allowed = info.memory_allowed; 586 - i32.memory_used = info.memory_used; 587 - i32.id_vendor = info.id_vendor; 588 - i32.id_device = info.id_device; 589 - if (copy_to_user(argp, &i32, sizeof(i32))) 590 - return -EFAULT; 591 - 592 - return 0; 593 - } 594 - 595 - typedef struct drm_agp_buffer32 { 596 - u32 size; /**< In bytes -- will round to page boundary */ 597 - u32 handle; /**< Used for binding / unbinding */ 598 - u32 type; /**< Type of memory to allocate */ 599 - u32 physical; /**< Physical used by i810 */ 600 - } drm_agp_buffer32_t; 601 - 602 - static int compat_drm_agp_alloc(struct file *file, unsigned int cmd, 603 - unsigned long arg) 604 - { 605 - drm_agp_buffer32_t __user *argp = (void __user *)arg; 606 - drm_agp_buffer32_t req32; 607 - struct drm_agp_buffer request; 608 - int err; 609 - 610 - if (copy_from_user(&req32, argp, sizeof(req32))) 611 - return -EFAULT; 612 - 613 - request.size = req32.size; 614 - request.type = req32.type; 615 - err = drm_ioctl_kernel(file, drm_legacy_agp_alloc_ioctl, &request, 616 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 617 - if (err) 618 - return err; 619 - 620 - req32.handle = request.handle; 621 - req32.physical = request.physical; 622 - if (copy_to_user(argp, &req32, sizeof(req32))) { 623 - drm_ioctl_kernel(file, drm_legacy_agp_free_ioctl, &request, 624 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 625 - return -EFAULT; 626 - } 627 - 628 - return 0; 629 - } 630 - 631 - static int compat_drm_agp_free(struct file *file, unsigned int cmd, 632 - unsigned long arg) 633 - { 634 - drm_agp_buffer32_t __user *argp = (void __user *)arg; 635 - struct drm_agp_buffer request; 636 - 637 - if (get_user(request.handle, &argp->handle)) 638 - return -EFAULT; 639 - 640 - return drm_ioctl_kernel(file, drm_legacy_agp_free_ioctl, &request, 641 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 642 - } 643 - 644 - typedef struct drm_agp_binding32 { 645 - u32 handle; /**< From drm_agp_buffer */ 646 - u32 offset; /**< In bytes -- will round to page boundary */ 647 - } drm_agp_binding32_t; 648 - 649 - static int compat_drm_agp_bind(struct file *file, unsigned int cmd, 650 - unsigned long arg) 651 - { 652 - drm_agp_binding32_t __user *argp = (void __user *)arg; 653 - drm_agp_binding32_t req32; 654 - struct drm_agp_binding request; 655 - 656 - if (copy_from_user(&req32, argp, sizeof(req32))) 657 - return -EFAULT; 658 - 659 - request.handle = req32.handle; 660 - request.offset = req32.offset; 661 - return drm_ioctl_kernel(file, drm_legacy_agp_bind_ioctl, &request, 662 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 663 - } 664 - 665 - static int compat_drm_agp_unbind(struct file *file, unsigned int cmd, 666 - unsigned long arg) 667 - { 668 - drm_agp_binding32_t __user *argp = (void __user *)arg; 669 - struct drm_agp_binding request; 670 - 671 - if (get_user(request.handle, &argp->handle)) 672 - return -EFAULT; 673 - 674 - return drm_ioctl_kernel(file, drm_legacy_agp_unbind_ioctl, &request, 675 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 676 - } 677 - #endif /* CONFIG_AGP */ 678 - 679 - typedef struct drm_scatter_gather32 { 680 - u32 size; /**< In bytes -- will round to page boundary */ 681 - u32 handle; /**< Used for mapping / unmapping */ 682 - } drm_scatter_gather32_t; 683 - 684 - static int compat_drm_sg_alloc(struct file *file, unsigned int cmd, 685 - unsigned long arg) 686 - { 687 - drm_scatter_gather32_t __user *argp = (void __user *)arg; 688 - struct drm_scatter_gather request; 689 - int err; 690 - 691 - if (get_user(request.size, &argp->size)) 692 - return -EFAULT; 693 - 694 - err = drm_ioctl_kernel(file, drm_legacy_sg_alloc, &request, 695 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 696 - if (err) 697 - return err; 698 - 699 - /* XXX not sure about the handle conversion here... */ 700 - if (put_user(request.handle >> PAGE_SHIFT, &argp->handle)) 701 - return -EFAULT; 702 - 703 - return 0; 704 - } 705 - 706 - static int compat_drm_sg_free(struct file *file, unsigned int cmd, 707 - unsigned long arg) 708 - { 709 - drm_scatter_gather32_t __user *argp = (void __user *)arg; 710 - struct drm_scatter_gather request; 711 - unsigned long x; 712 - 713 - if (get_user(x, &argp->handle)) 714 - return -EFAULT; 715 - request.handle = x << PAGE_SHIFT; 716 - return drm_ioctl_kernel(file, drm_legacy_sg_free, &request, 717 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); 718 - } 719 - #endif 720 311 #if defined(CONFIG_X86) 721 312 typedef struct drm_update_draw32 { 722 313 drm_drawable_t handle; ··· 273 854 req.request.type = req32.request.type; 274 855 req.request.sequence = req32.request.sequence; 275 856 req.request.signal = req32.request.signal; 276 - err = drm_ioctl_kernel(file, drm_wait_vblank_ioctl, &req, DRM_UNLOCKED); 857 + err = drm_ioctl_kernel(file, drm_wait_vblank_ioctl, &req, 0); 277 858 278 859 req32.reply.type = req.reply.type; 279 860 req32.reply.sequence = req.reply.sequence; ··· 333 914 #define DRM_IOCTL32_DEF(n, f) [DRM_IOCTL_NR(n##32)] = {.fn = f, .name = #n} 334 915 DRM_IOCTL32_DEF(DRM_IOCTL_VERSION, compat_drm_version), 335 916 DRM_IOCTL32_DEF(DRM_IOCTL_GET_UNIQUE, compat_drm_getunique), 336 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 337 - DRM_IOCTL32_DEF(DRM_IOCTL_GET_MAP, compat_drm_getmap), 338 - #endif 339 917 DRM_IOCTL32_DEF(DRM_IOCTL_GET_CLIENT, compat_drm_getclient), 340 918 DRM_IOCTL32_DEF(DRM_IOCTL_GET_STATS, compat_drm_getstats), 341 919 DRM_IOCTL32_DEF(DRM_IOCTL_SET_UNIQUE, compat_drm_setunique), 342 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 343 - DRM_IOCTL32_DEF(DRM_IOCTL_ADD_MAP, compat_drm_addmap), 344 - DRM_IOCTL32_DEF(DRM_IOCTL_ADD_BUFS, compat_drm_addbufs), 345 - DRM_IOCTL32_DEF(DRM_IOCTL_MARK_BUFS, compat_drm_markbufs), 346 - DRM_IOCTL32_DEF(DRM_IOCTL_INFO_BUFS, compat_drm_infobufs), 347 - DRM_IOCTL32_DEF(DRM_IOCTL_MAP_BUFS, compat_drm_mapbufs), 348 - DRM_IOCTL32_DEF(DRM_IOCTL_FREE_BUFS, compat_drm_freebufs), 349 - DRM_IOCTL32_DEF(DRM_IOCTL_RM_MAP, compat_drm_rmmap), 350 - DRM_IOCTL32_DEF(DRM_IOCTL_SET_SAREA_CTX, compat_drm_setsareactx), 351 - DRM_IOCTL32_DEF(DRM_IOCTL_GET_SAREA_CTX, compat_drm_getsareactx), 352 - DRM_IOCTL32_DEF(DRM_IOCTL_RES_CTX, compat_drm_resctx), 353 - DRM_IOCTL32_DEF(DRM_IOCTL_DMA, compat_drm_dma), 354 - #if IS_ENABLED(CONFIG_AGP) 355 - DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ENABLE, compat_drm_agp_enable), 356 - DRM_IOCTL32_DEF(DRM_IOCTL_AGP_INFO, compat_drm_agp_info), 357 - DRM_IOCTL32_DEF(DRM_IOCTL_AGP_ALLOC, compat_drm_agp_alloc), 358 - DRM_IOCTL32_DEF(DRM_IOCTL_AGP_FREE, compat_drm_agp_free), 359 - DRM_IOCTL32_DEF(DRM_IOCTL_AGP_BIND, compat_drm_agp_bind), 360 - DRM_IOCTL32_DEF(DRM_IOCTL_AGP_UNBIND, compat_drm_agp_unbind), 361 - #endif 362 - #endif 363 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 364 - DRM_IOCTL32_DEF(DRM_IOCTL_SG_ALLOC, compat_drm_sg_alloc), 365 - DRM_IOCTL32_DEF(DRM_IOCTL_SG_FREE, compat_drm_sg_free), 366 - #endif 367 920 #if defined(CONFIG_X86) 368 921 DRM_IOCTL32_DEF(DRM_IOCTL_UPDATE_DRAW, compat_drm_update_draw), 369 922 #endif
+19 -74
drivers/gpu/drm/drm_ioctl.c
··· 42 42 43 43 #include "drm_crtc_internal.h" 44 44 #include "drm_internal.h" 45 - #include "drm_legacy.h" 46 45 47 46 /** 48 47 * DOC: getunique and setversion story ··· 300 301 case DRM_CAP_CRTC_IN_VBLANK_EVENT: 301 302 req->value = 1; 302 303 break; 304 + case DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP: 305 + req->value = drm_core_check_feature(dev, DRIVER_ATOMIC) && 306 + dev->mode_config.async_page_flip; 307 + break; 303 308 default: 304 309 return -EINVAL; 305 310 } ··· 363 360 if (req->value > 1) 364 361 return -EINVAL; 365 362 file_priv->writeback_connectors = req->value; 363 + break; 364 + case DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT: 365 + if (!drm_core_check_feature(dev, DRIVER_CURSOR_HOTSPOT)) 366 + return -EOPNOTSUPP; 367 + if (!file_priv->atomic) 368 + return -EINVAL; 369 + if (req->value > 1) 370 + return -EINVAL; 371 + file_priv->supports_virtualized_cursor_plane = req->value; 366 372 break; 367 373 default: 368 374 return -EINVAL; ··· 571 559 .name = #ioctl \ 572 560 } 573 561 574 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 575 - #define DRM_LEGACY_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(ioctl, _func, _flags) 576 - #else 577 - #define DRM_LEGACY_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(ioctl, drm_invalid_op, _flags) 578 - #endif 579 - 580 562 /* Ioctl table */ 581 563 static const struct drm_ioctl_desc drm_ioctls[] = { 582 564 DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_RENDER_ALLOW), 583 565 DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), 584 566 DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), 585 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_legacy_irq_by_busid, 586 - DRM_MASTER|DRM_ROOT_ONLY), 587 - 588 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, 0), 589 567 590 568 DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0), 591 569 DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0), ··· 588 586 DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 589 587 DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_MASTER), 590 588 591 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_legacy_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 592 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_legacy_rmmap_ioctl, DRM_AUTH), 593 - 594 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_legacy_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 595 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_legacy_getsareactx, DRM_AUTH), 596 - 597 589 DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, 0), 598 590 DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, 0), 599 - 600 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_legacy_addctx, DRM_AUTH|DRM_ROOT_ONLY), 601 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_legacy_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 602 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 603 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_legacy_getctx, DRM_AUTH), 604 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_legacy_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 605 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_legacy_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 606 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_legacy_resctx, DRM_AUTH), 607 591 608 592 DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 609 593 DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 610 594 611 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_LOCK, drm_legacy_lock, DRM_AUTH), 612 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_legacy_unlock, DRM_AUTH), 613 - 614 595 DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH), 615 596 616 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_legacy_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 617 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_legacy_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 618 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_legacy_infobufs, DRM_AUTH), 619 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_legacy_mapbufs, DRM_AUTH), 620 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_legacy_freebufs, DRM_AUTH), 621 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_DMA, drm_legacy_dma_ioctl, DRM_AUTH), 622 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_legacy_irq_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 623 - 624 - #if IS_ENABLED(CONFIG_AGP) 625 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_legacy_agp_acquire_ioctl, 626 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 627 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_legacy_agp_release_ioctl, 628 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 629 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_legacy_agp_enable_ioctl, 630 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 631 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_legacy_agp_info_ioctl, DRM_AUTH), 632 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_legacy_agp_alloc_ioctl, 633 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 634 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_legacy_agp_free_ioctl, 635 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 636 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_legacy_agp_bind_ioctl, 637 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 638 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_legacy_agp_unbind_ioctl, 639 - DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 640 - #endif 641 - 642 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_legacy_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 643 - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_legacy_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 644 - 645 - DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank_ioctl, DRM_UNLOCKED), 646 - 647 - DRM_IOCTL_DEF(DRM_IOCTL_MODESET_CTL, drm_legacy_modeset_ctl_ioctl, 0), 597 + DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank_ioctl, 0), 648 598 649 599 DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 650 600 ··· 729 775 { 730 776 struct drm_file *file_priv = file->private_data; 731 777 struct drm_device *dev = file_priv->minor->dev; 732 - int retcode; 778 + int ret; 733 779 734 780 /* Update drm_file owner if fd was passed along. */ 735 781 drm_file_update_pid(file_priv); ··· 737 783 if (drm_dev_is_unplugged(dev)) 738 784 return -ENODEV; 739 785 740 - retcode = drm_ioctl_permit(flags, file_priv); 741 - if (unlikely(retcode)) 742 - return retcode; 786 + ret = drm_ioctl_permit(flags, file_priv); 787 + if (unlikely(ret)) 788 + return ret; 743 789 744 - /* Enforce sane locking for modern driver ioctls. */ 745 - if (likely(!drm_core_check_feature(dev, DRIVER_LEGACY)) || 746 - (flags & DRM_UNLOCKED)) 747 - retcode = func(dev, kdata, file_priv); 748 - else { 749 - mutex_lock(&drm_global_mutex); 750 - retcode = func(dev, kdata, file_priv); 751 - mutex_unlock(&drm_global_mutex); 752 - } 753 - return retcode; 790 + return func(dev, kdata, file_priv); 754 791 } 755 792 EXPORT_SYMBOL(drm_ioctl_kernel); 756 793
-204
drivers/gpu/drm/drm_irq.c
··· 1 - /* 2 - * drm_irq.c IRQ and vblank support 3 - * 4 - * \author Rickard E. (Rik) Faith <faith@valinux.com> 5 - * \author Gareth Hughes <gareth@valinux.com> 6 - * 7 - * Permission is hereby granted, free of charge, to any person obtaining a 8 - * copy of this software and associated documentation files (the "Software"), 9 - * to deal in the Software without restriction, including without limitation 10 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 - * and/or sell copies of the Software, and to permit persons to whom the 12 - * Software is furnished to do so, subject to the following conditions: 13 - * 14 - * The above copyright notice and this permission notice (including the next 15 - * paragraph) shall be included in all copies or substantial portions of the 16 - * Software. 17 - * 18 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 - * OTHER DEALINGS IN THE SOFTWARE. 25 - */ 26 - 27 - /* 28 - * Created: Fri Mar 19 14:30:16 1999 by faith@valinux.com 29 - * 30 - * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas. 31 - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 32 - * All Rights Reserved. 33 - * 34 - * Permission is hereby granted, free of charge, to any person obtaining a 35 - * copy of this software and associated documentation files (the "Software"), 36 - * to deal in the Software without restriction, including without limitation 37 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 38 - * and/or sell copies of the Software, and to permit persons to whom the 39 - * Software is furnished to do so, subject to the following conditions: 40 - * 41 - * The above copyright notice and this permission notice (including the next 42 - * paragraph) shall be included in all copies or substantial portions of the 43 - * Software. 44 - * 45 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 47 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 48 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 49 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 50 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 51 - * OTHER DEALINGS IN THE SOFTWARE. 52 - */ 53 - 54 - 55 - #include <linux/export.h> 56 - #include <linux/interrupt.h> /* For task queue support */ 57 - #include <linux/pci.h> 58 - #include <linux/vgaarb.h> 59 - 60 - #include <drm/drm.h> 61 - #include <drm/drm_device.h> 62 - #include <drm/drm_drv.h> 63 - #include <drm/drm_legacy.h> 64 - #include <drm/drm_print.h> 65 - #include <drm/drm_vblank.h> 66 - 67 - #include "drm_internal.h" 68 - 69 - static int drm_legacy_irq_install(struct drm_device *dev, int irq) 70 - { 71 - int ret; 72 - unsigned long sh_flags = 0; 73 - 74 - if (irq == 0) 75 - return -EINVAL; 76 - 77 - if (dev->irq_enabled) 78 - return -EBUSY; 79 - dev->irq_enabled = true; 80 - 81 - DRM_DEBUG("irq=%d\n", irq); 82 - 83 - /* Before installing handler */ 84 - if (dev->driver->irq_preinstall) 85 - dev->driver->irq_preinstall(dev); 86 - 87 - /* PCI devices require shared interrupts. */ 88 - if (dev_is_pci(dev->dev)) 89 - sh_flags = IRQF_SHARED; 90 - 91 - ret = request_irq(irq, dev->driver->irq_handler, 92 - sh_flags, dev->driver->name, dev); 93 - 94 - if (ret < 0) { 95 - dev->irq_enabled = false; 96 - return ret; 97 - } 98 - 99 - /* After installing handler */ 100 - if (dev->driver->irq_postinstall) 101 - ret = dev->driver->irq_postinstall(dev); 102 - 103 - if (ret < 0) { 104 - dev->irq_enabled = false; 105 - if (drm_core_check_feature(dev, DRIVER_LEGACY)) 106 - vga_client_unregister(to_pci_dev(dev->dev)); 107 - free_irq(irq, dev); 108 - } else { 109 - dev->irq = irq; 110 - } 111 - 112 - return ret; 113 - } 114 - 115 - int drm_legacy_irq_uninstall(struct drm_device *dev) 116 - { 117 - unsigned long irqflags; 118 - bool irq_enabled; 119 - int i; 120 - 121 - irq_enabled = dev->irq_enabled; 122 - dev->irq_enabled = false; 123 - 124 - /* 125 - * Wake up any waiters so they don't hang. This is just to paper over 126 - * issues for UMS drivers which aren't in full control of their 127 - * vblank/irq handling. KMS drivers must ensure that vblanks are all 128 - * disabled when uninstalling the irq handler. 129 - */ 130 - if (drm_dev_has_vblank(dev)) { 131 - spin_lock_irqsave(&dev->vbl_lock, irqflags); 132 - for (i = 0; i < dev->num_crtcs; i++) { 133 - struct drm_vblank_crtc *vblank = &dev->vblank[i]; 134 - 135 - if (!vblank->enabled) 136 - continue; 137 - 138 - WARN_ON(drm_core_check_feature(dev, DRIVER_MODESET)); 139 - 140 - drm_vblank_disable_and_save(dev, i); 141 - wake_up(&vblank->queue); 142 - } 143 - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); 144 - } 145 - 146 - if (!irq_enabled) 147 - return -EINVAL; 148 - 149 - DRM_DEBUG("irq=%d\n", dev->irq); 150 - 151 - if (drm_core_check_feature(dev, DRIVER_LEGACY)) 152 - vga_client_unregister(to_pci_dev(dev->dev)); 153 - 154 - if (dev->driver->irq_uninstall) 155 - dev->driver->irq_uninstall(dev); 156 - 157 - free_irq(dev->irq, dev); 158 - 159 - return 0; 160 - } 161 - EXPORT_SYMBOL(drm_legacy_irq_uninstall); 162 - 163 - int drm_legacy_irq_control(struct drm_device *dev, void *data, 164 - struct drm_file *file_priv) 165 - { 166 - struct drm_control *ctl = data; 167 - int ret = 0, irq; 168 - struct pci_dev *pdev; 169 - 170 - /* if we haven't irq we fallback for compatibility reasons - 171 - * this used to be a separate function in drm_dma.h 172 - */ 173 - 174 - if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 175 - return 0; 176 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 177 - return 0; 178 - /* UMS was only ever supported on pci devices. */ 179 - if (WARN_ON(!dev_is_pci(dev->dev))) 180 - return -EINVAL; 181 - 182 - switch (ctl->func) { 183 - case DRM_INST_HANDLER: 184 - pdev = to_pci_dev(dev->dev); 185 - irq = pdev->irq; 186 - 187 - if (dev->if_version < DRM_IF_VERSION(1, 2) && 188 - ctl->irq != irq) 189 - return -EINVAL; 190 - mutex_lock(&dev->struct_mutex); 191 - ret = drm_legacy_irq_install(dev, irq); 192 - mutex_unlock(&dev->struct_mutex); 193 - 194 - return ret; 195 - case DRM_UNINST_HANDLER: 196 - mutex_lock(&dev->struct_mutex); 197 - ret = drm_legacy_irq_uninstall(dev); 198 - mutex_unlock(&dev->struct_mutex); 199 - 200 - return ret; 201 - default: 202 - return -EINVAL; 203 - } 204 - }
-290
drivers/gpu/drm/drm_legacy.h
··· 1 - #ifndef __DRM_LEGACY_H__ 2 - #define __DRM_LEGACY_H__ 3 - 4 - /* 5 - * Copyright (c) 2014 David Herrmann <dh.herrmann@gmail.com> 6 - * 7 - * Permission is hereby granted, free of charge, to any person obtaining a 8 - * copy of this software and associated documentation files (the "Software"), 9 - * to deal in the Software without restriction, including without limitation 10 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 - * and/or sell copies of the Software, and to permit persons to whom the 12 - * Software is furnished to do so, subject to the following conditions: 13 - * 14 - * The above copyright notice and this permission notice shall be included in 15 - * all copies or substantial portions of the Software. 16 - * 17 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 - * OTHER DEALINGS IN THE SOFTWARE. 24 - */ 25 - 26 - /* 27 - * This file contains legacy interfaces that modern drm drivers 28 - * should no longer be using. They cannot be removed as legacy 29 - * drivers use them, and removing them are API breaks. 30 - */ 31 - #include <linux/list.h> 32 - 33 - #include <drm/drm.h> 34 - #include <drm/drm_device.h> 35 - #include <drm/drm_legacy.h> 36 - 37 - struct agp_memory; 38 - struct drm_buf_desc; 39 - struct drm_device; 40 - struct drm_file; 41 - struct drm_hash_item; 42 - struct drm_open_hash; 43 - 44 - /* 45 - * Hash-table Support 46 - */ 47 - 48 - #define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member) 49 - 50 - /* drm_hashtab.c */ 51 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 52 - int drm_ht_create(struct drm_open_hash *ht, unsigned int order); 53 - int drm_ht_insert_item(struct drm_open_hash *ht, struct drm_hash_item *item); 54 - int drm_ht_just_insert_please(struct drm_open_hash *ht, struct drm_hash_item *item, 55 - unsigned long seed, int bits, int shift, 56 - unsigned long add); 57 - int drm_ht_find_item(struct drm_open_hash *ht, unsigned long key, struct drm_hash_item **item); 58 - 59 - void drm_ht_verbose_list(struct drm_open_hash *ht, unsigned long key); 60 - int drm_ht_remove_key(struct drm_open_hash *ht, unsigned long key); 61 - int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item); 62 - void drm_ht_remove(struct drm_open_hash *ht); 63 - #endif 64 - 65 - /* 66 - * RCU-safe interface 67 - * 68 - * The user of this API needs to make sure that two or more instances of the 69 - * hash table manipulation functions are never run simultaneously. 70 - * The lookup function drm_ht_find_item_rcu may, however, run simultaneously 71 - * with any of the manipulation functions as long as it's called from within 72 - * an RCU read-locked section. 73 - */ 74 - #define drm_ht_insert_item_rcu drm_ht_insert_item 75 - #define drm_ht_just_insert_please_rcu drm_ht_just_insert_please 76 - #define drm_ht_remove_key_rcu drm_ht_remove_key 77 - #define drm_ht_remove_item_rcu drm_ht_remove_item 78 - #define drm_ht_find_item_rcu drm_ht_find_item 79 - 80 - /* 81 - * Generic DRM Contexts 82 - */ 83 - 84 - #define DRM_KERNEL_CONTEXT 0 85 - #define DRM_RESERVED_CONTEXTS 1 86 - 87 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 88 - void drm_legacy_ctxbitmap_init(struct drm_device *dev); 89 - void drm_legacy_ctxbitmap_cleanup(struct drm_device *dev); 90 - void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file); 91 - #else 92 - static inline void drm_legacy_ctxbitmap_init(struct drm_device *dev) {} 93 - static inline void drm_legacy_ctxbitmap_cleanup(struct drm_device *dev) {} 94 - static inline void drm_legacy_ctxbitmap_flush(struct drm_device *dev, struct drm_file *file) {} 95 - #endif 96 - 97 - void drm_legacy_ctxbitmap_free(struct drm_device *dev, int ctx_handle); 98 - 99 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 100 - int drm_legacy_resctx(struct drm_device *d, void *v, struct drm_file *f); 101 - int drm_legacy_addctx(struct drm_device *d, void *v, struct drm_file *f); 102 - int drm_legacy_getctx(struct drm_device *d, void *v, struct drm_file *f); 103 - int drm_legacy_switchctx(struct drm_device *d, void *v, struct drm_file *f); 104 - int drm_legacy_newctx(struct drm_device *d, void *v, struct drm_file *f); 105 - int drm_legacy_rmctx(struct drm_device *d, void *v, struct drm_file *f); 106 - 107 - int drm_legacy_setsareactx(struct drm_device *d, void *v, struct drm_file *f); 108 - int drm_legacy_getsareactx(struct drm_device *d, void *v, struct drm_file *f); 109 - #endif 110 - 111 - /* 112 - * Generic Buffer Management 113 - */ 114 - 115 - #define DRM_MAP_HASH_OFFSET 0x10000000 116 - 117 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 118 - static inline int drm_legacy_create_map_hash(struct drm_device *dev) 119 - { 120 - return drm_ht_create(&dev->map_hash, 12); 121 - } 122 - 123 - static inline void drm_legacy_remove_map_hash(struct drm_device *dev) 124 - { 125 - drm_ht_remove(&dev->map_hash); 126 - } 127 - #else 128 - static inline int drm_legacy_create_map_hash(struct drm_device *dev) 129 - { 130 - return 0; 131 - } 132 - 133 - static inline void drm_legacy_remove_map_hash(struct drm_device *dev) {} 134 - #endif 135 - 136 - 137 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 138 - int drm_legacy_getmap_ioctl(struct drm_device *dev, void *data, 139 - struct drm_file *file_priv); 140 - int drm_legacy_addmap_ioctl(struct drm_device *d, void *v, struct drm_file *f); 141 - int drm_legacy_rmmap_ioctl(struct drm_device *d, void *v, struct drm_file *f); 142 - 143 - int drm_legacy_addbufs(struct drm_device *d, void *v, struct drm_file *f); 144 - int drm_legacy_infobufs(struct drm_device *d, void *v, struct drm_file *f); 145 - int drm_legacy_markbufs(struct drm_device *d, void *v, struct drm_file *f); 146 - int drm_legacy_freebufs(struct drm_device *d, void *v, struct drm_file *f); 147 - int drm_legacy_mapbufs(struct drm_device *d, void *v, struct drm_file *f); 148 - int drm_legacy_dma_ioctl(struct drm_device *d, void *v, struct drm_file *f); 149 - #endif 150 - 151 - int __drm_legacy_infobufs(struct drm_device *, void *, int *, 152 - int (*)(void *, int, struct drm_buf_entry *)); 153 - int __drm_legacy_mapbufs(struct drm_device *, void *, int *, 154 - void __user **, 155 - int (*)(void *, int, unsigned long, struct drm_buf *), 156 - struct drm_file *); 157 - 158 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 159 - void drm_legacy_master_rmmaps(struct drm_device *dev, 160 - struct drm_master *master); 161 - void drm_legacy_rmmaps(struct drm_device *dev); 162 - #else 163 - static inline void drm_legacy_master_rmmaps(struct drm_device *dev, 164 - struct drm_master *master) {} 165 - static inline void drm_legacy_rmmaps(struct drm_device *dev) {} 166 - #endif 167 - 168 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 169 - void drm_legacy_vma_flush(struct drm_device *d); 170 - #else 171 - static inline void drm_legacy_vma_flush(struct drm_device *d) 172 - { 173 - /* do nothing */ 174 - } 175 - #endif 176 - 177 - /* 178 - * AGP Support 179 - */ 180 - 181 - struct drm_agp_mem { 182 - unsigned long handle; 183 - struct agp_memory *memory; 184 - unsigned long bound; 185 - int pages; 186 - struct list_head head; 187 - }; 188 - 189 - /* drm_agpsupport.c */ 190 - #if IS_ENABLED(CONFIG_DRM_LEGACY) && IS_ENABLED(CONFIG_AGP) 191 - void drm_legacy_agp_clear(struct drm_device *dev); 192 - 193 - int drm_legacy_agp_acquire_ioctl(struct drm_device *dev, void *data, 194 - struct drm_file *file_priv); 195 - int drm_legacy_agp_release_ioctl(struct drm_device *dev, void *data, 196 - struct drm_file *file_priv); 197 - int drm_legacy_agp_enable_ioctl(struct drm_device *dev, void *data, 198 - struct drm_file *file_priv); 199 - int drm_legacy_agp_info_ioctl(struct drm_device *dev, void *data, 200 - struct drm_file *file_priv); 201 - int drm_legacy_agp_alloc_ioctl(struct drm_device *dev, void *data, 202 - struct drm_file *file_priv); 203 - int drm_legacy_agp_free_ioctl(struct drm_device *dev, void *data, 204 - struct drm_file *file_priv); 205 - int drm_legacy_agp_unbind_ioctl(struct drm_device *dev, void *data, 206 - struct drm_file *file_priv); 207 - int drm_legacy_agp_bind_ioctl(struct drm_device *dev, void *data, 208 - struct drm_file *file_priv); 209 - #else 210 - static inline void drm_legacy_agp_clear(struct drm_device *dev) {} 211 - #endif 212 - 213 - /* drm_lock.c */ 214 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 215 - int drm_legacy_lock(struct drm_device *d, void *v, struct drm_file *f); 216 - int drm_legacy_unlock(struct drm_device *d, void *v, struct drm_file *f); 217 - void drm_legacy_lock_release(struct drm_device *dev, struct file *filp); 218 - #else 219 - static inline void drm_legacy_lock_release(struct drm_device *dev, struct file *filp) {} 220 - #endif 221 - 222 - /* DMA support */ 223 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 224 - int drm_legacy_dma_setup(struct drm_device *dev); 225 - void drm_legacy_dma_takedown(struct drm_device *dev); 226 - #else 227 - static inline int drm_legacy_dma_setup(struct drm_device *dev) 228 - { 229 - return 0; 230 - } 231 - #endif 232 - 233 - void drm_legacy_free_buffer(struct drm_device *dev, 234 - struct drm_buf * buf); 235 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 236 - void drm_legacy_reclaim_buffers(struct drm_device *dev, 237 - struct drm_file *filp); 238 - #else 239 - static inline void drm_legacy_reclaim_buffers(struct drm_device *dev, 240 - struct drm_file *filp) {} 241 - #endif 242 - 243 - /* Scatter Gather Support */ 244 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 245 - void drm_legacy_sg_cleanup(struct drm_device *dev); 246 - int drm_legacy_sg_alloc(struct drm_device *dev, void *data, 247 - struct drm_file *file_priv); 248 - int drm_legacy_sg_free(struct drm_device *dev, void *data, 249 - struct drm_file *file_priv); 250 - #endif 251 - 252 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 253 - void drm_legacy_init_members(struct drm_device *dev); 254 - void drm_legacy_destroy_members(struct drm_device *dev); 255 - void drm_legacy_dev_reinit(struct drm_device *dev); 256 - int drm_legacy_setup(struct drm_device * dev); 257 - #else 258 - static inline void drm_legacy_init_members(struct drm_device *dev) {} 259 - static inline void drm_legacy_destroy_members(struct drm_device *dev) {} 260 - static inline void drm_legacy_dev_reinit(struct drm_device *dev) {} 261 - static inline int drm_legacy_setup(struct drm_device * dev) { return 0; } 262 - #endif 263 - 264 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 265 - void drm_legacy_lock_master_cleanup(struct drm_device *dev, struct drm_master *master); 266 - #else 267 - static inline void drm_legacy_lock_master_cleanup(struct drm_device *dev, struct drm_master *master) {} 268 - #endif 269 - 270 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 271 - void drm_master_legacy_init(struct drm_master *master); 272 - #else 273 - static inline void drm_master_legacy_init(struct drm_master *master) {} 274 - #endif 275 - 276 - /* drm_pci.c */ 277 - #if IS_ENABLED(CONFIG_DRM_LEGACY) && IS_ENABLED(CONFIG_PCI) 278 - int drm_legacy_irq_by_busid(struct drm_device *dev, void *data, struct drm_file *file_priv); 279 - void drm_legacy_pci_agp_destroy(struct drm_device *dev); 280 - #else 281 - static inline int drm_legacy_irq_by_busid(struct drm_device *dev, void *data, 282 - struct drm_file *file_priv) 283 - { 284 - return -EINVAL; 285 - } 286 - 287 - static inline void drm_legacy_pci_agp_destroy(struct drm_device *dev) {} 288 - #endif 289 - 290 - #endif /* __DRM_LEGACY_H__ */
-105
drivers/gpu/drm/drm_legacy_misc.c
··· 1 - /* 2 - * \file drm_legacy_misc.c 3 - * Misc legacy support functions. 4 - * 5 - * \author Rickard E. (Rik) Faith <faith@valinux.com> 6 - * \author Gareth Hughes <gareth@valinux.com> 7 - */ 8 - 9 - /* 10 - * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com 11 - * 12 - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 13 - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 14 - * All Rights Reserved. 15 - * 16 - * Permission is hereby granted, free of charge, to any person obtaining a 17 - * copy of this software and associated documentation files (the "Software"), 18 - * to deal in the Software without restriction, including without limitation 19 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 - * and/or sell copies of the Software, and to permit persons to whom the 21 - * Software is furnished to do so, subject to the following conditions: 22 - * 23 - * The above copyright notice and this permission notice (including the next 24 - * paragraph) shall be included in all copies or substantial portions of the 25 - * Software. 26 - * 27 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 31 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 32 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33 - * OTHER DEALINGS IN THE SOFTWARE. 34 - */ 35 - 36 - #include <drm/drm_device.h> 37 - #include <drm/drm_drv.h> 38 - #include <drm/drm_print.h> 39 - 40 - #include "drm_internal.h" 41 - #include "drm_legacy.h" 42 - 43 - void drm_legacy_init_members(struct drm_device *dev) 44 - { 45 - INIT_LIST_HEAD(&dev->ctxlist); 46 - INIT_LIST_HEAD(&dev->vmalist); 47 - INIT_LIST_HEAD(&dev->maplist); 48 - spin_lock_init(&dev->buf_lock); 49 - mutex_init(&dev->ctxlist_mutex); 50 - } 51 - 52 - void drm_legacy_destroy_members(struct drm_device *dev) 53 - { 54 - mutex_destroy(&dev->ctxlist_mutex); 55 - } 56 - 57 - int drm_legacy_setup(struct drm_device * dev) 58 - { 59 - int ret; 60 - 61 - if (dev->driver->firstopen && 62 - drm_core_check_feature(dev, DRIVER_LEGACY)) { 63 - ret = dev->driver->firstopen(dev); 64 - if (ret != 0) 65 - return ret; 66 - } 67 - 68 - ret = drm_legacy_dma_setup(dev); 69 - if (ret < 0) 70 - return ret; 71 - 72 - 73 - DRM_DEBUG("\n"); 74 - return 0; 75 - } 76 - 77 - void drm_legacy_dev_reinit(struct drm_device *dev) 78 - { 79 - if (dev->irq_enabled) 80 - drm_legacy_irq_uninstall(dev); 81 - 82 - mutex_lock(&dev->struct_mutex); 83 - 84 - drm_legacy_agp_clear(dev); 85 - 86 - drm_legacy_sg_cleanup(dev); 87 - drm_legacy_vma_flush(dev); 88 - drm_legacy_dma_takedown(dev); 89 - 90 - mutex_unlock(&dev->struct_mutex); 91 - 92 - dev->sigdata.lock = NULL; 93 - 94 - dev->context_flag = 0; 95 - dev->last_context = 0; 96 - dev->if_version = 0; 97 - 98 - DRM_DEBUG("lastclose completed\n"); 99 - } 100 - 101 - void drm_master_legacy_init(struct drm_master *master) 102 - { 103 - spin_lock_init(&master->lock.spinlock); 104 - init_waitqueue_head(&master->lock.lock_queue); 105 - }
-373
drivers/gpu/drm/drm_lock.c
··· 1 - /* 2 - * \file drm_lock.c 3 - * IOCTLs for locking 4 - * 5 - * \author Rickard E. (Rik) Faith <faith@valinux.com> 6 - * \author Gareth Hughes <gareth@valinux.com> 7 - */ 8 - 9 - /* 10 - * Created: Tue Feb 2 08:37:54 1999 by faith@valinux.com 11 - * 12 - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 13 - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 14 - * All Rights Reserved. 15 - * 16 - * Permission is hereby granted, free of charge, to any person obtaining a 17 - * copy of this software and associated documentation files (the "Software"), 18 - * to deal in the Software without restriction, including without limitation 19 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 - * and/or sell copies of the Software, and to permit persons to whom the 21 - * Software is furnished to do so, subject to the following conditions: 22 - * 23 - * The above copyright notice and this permission notice (including the next 24 - * paragraph) shall be included in all copies or substantial portions of the 25 - * Software. 26 - * 27 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 31 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 32 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33 - * OTHER DEALINGS IN THE SOFTWARE. 34 - */ 35 - 36 - #include <linux/export.h> 37 - #include <linux/sched/signal.h> 38 - 39 - #include <drm/drm.h> 40 - #include <drm/drm_drv.h> 41 - #include <drm/drm_file.h> 42 - #include <drm/drm_print.h> 43 - 44 - #include "drm_internal.h" 45 - #include "drm_legacy.h" 46 - 47 - static int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context); 48 - 49 - /* 50 - * Take the heavyweight lock. 51 - * 52 - * \param lock lock pointer. 53 - * \param context locking context. 54 - * \return one if the lock is held, or zero otherwise. 55 - * 56 - * Attempt to mark the lock as held by the given context, via the \p cmpxchg instruction. 57 - */ 58 - static 59 - int drm_lock_take(struct drm_lock_data *lock_data, 60 - unsigned int context) 61 - { 62 - unsigned int old, new, prev; 63 - volatile unsigned int *lock = &lock_data->hw_lock->lock; 64 - 65 - spin_lock_bh(&lock_data->spinlock); 66 - do { 67 - old = *lock; 68 - if (old & _DRM_LOCK_HELD) 69 - new = old | _DRM_LOCK_CONT; 70 - else { 71 - new = context | _DRM_LOCK_HELD | 72 - ((lock_data->user_waiters + lock_data->kernel_waiters > 1) ? 73 - _DRM_LOCK_CONT : 0); 74 - } 75 - prev = cmpxchg(lock, old, new); 76 - } while (prev != old); 77 - spin_unlock_bh(&lock_data->spinlock); 78 - 79 - if (_DRM_LOCKING_CONTEXT(old) == context) { 80 - if (old & _DRM_LOCK_HELD) { 81 - if (context != DRM_KERNEL_CONTEXT) { 82 - DRM_ERROR("%d holds heavyweight lock\n", 83 - context); 84 - } 85 - return 0; 86 - } 87 - } 88 - 89 - if ((_DRM_LOCKING_CONTEXT(new)) == context && (new & _DRM_LOCK_HELD)) { 90 - /* Have lock */ 91 - return 1; 92 - } 93 - return 0; 94 - } 95 - 96 - /* 97 - * This takes a lock forcibly and hands it to context. Should ONLY be used 98 - * inside *_unlock to give lock to kernel before calling *_dma_schedule. 99 - * 100 - * \param dev DRM device. 101 - * \param lock lock pointer. 102 - * \param context locking context. 103 - * \return always one. 104 - * 105 - * Resets the lock file pointer. 106 - * Marks the lock as held by the given context, via the \p cmpxchg instruction. 107 - */ 108 - static int drm_lock_transfer(struct drm_lock_data *lock_data, 109 - unsigned int context) 110 - { 111 - unsigned int old, new, prev; 112 - volatile unsigned int *lock = &lock_data->hw_lock->lock; 113 - 114 - lock_data->file_priv = NULL; 115 - do { 116 - old = *lock; 117 - new = context | _DRM_LOCK_HELD; 118 - prev = cmpxchg(lock, old, new); 119 - } while (prev != old); 120 - return 1; 121 - } 122 - 123 - static int drm_legacy_lock_free(struct drm_lock_data *lock_data, 124 - unsigned int context) 125 - { 126 - unsigned int old, new, prev; 127 - volatile unsigned int *lock = &lock_data->hw_lock->lock; 128 - 129 - spin_lock_bh(&lock_data->spinlock); 130 - if (lock_data->kernel_waiters != 0) { 131 - drm_lock_transfer(lock_data, 0); 132 - lock_data->idle_has_lock = 1; 133 - spin_unlock_bh(&lock_data->spinlock); 134 - return 1; 135 - } 136 - spin_unlock_bh(&lock_data->spinlock); 137 - 138 - do { 139 - old = *lock; 140 - new = _DRM_LOCKING_CONTEXT(old); 141 - prev = cmpxchg(lock, old, new); 142 - } while (prev != old); 143 - 144 - if (_DRM_LOCK_IS_HELD(old) && _DRM_LOCKING_CONTEXT(old) != context) { 145 - DRM_ERROR("%d freed heavyweight lock held by %d\n", 146 - context, _DRM_LOCKING_CONTEXT(old)); 147 - return 1; 148 - } 149 - wake_up_interruptible(&lock_data->lock_queue); 150 - return 0; 151 - } 152 - 153 - /* 154 - * Lock ioctl. 155 - * 156 - * \param inode device inode. 157 - * \param file_priv DRM file private. 158 - * \param cmd command. 159 - * \param arg user argument, pointing to a drm_lock structure. 160 - * \return zero on success or negative number on failure. 161 - * 162 - * Add the current task to the lock wait queue, and attempt to take to lock. 163 - */ 164 - int drm_legacy_lock(struct drm_device *dev, void *data, 165 - struct drm_file *file_priv) 166 - { 167 - DECLARE_WAITQUEUE(entry, current); 168 - struct drm_lock *lock = data; 169 - struct drm_master *master = file_priv->master; 170 - int ret = 0; 171 - 172 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 173 - return -EOPNOTSUPP; 174 - 175 - ++file_priv->lock_count; 176 - 177 - if (lock->context == DRM_KERNEL_CONTEXT) { 178 - DRM_ERROR("Process %d using kernel context %d\n", 179 - task_pid_nr(current), lock->context); 180 - return -EINVAL; 181 - } 182 - 183 - DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", 184 - lock->context, task_pid_nr(current), 185 - master->lock.hw_lock ? master->lock.hw_lock->lock : -1, 186 - lock->flags); 187 - 188 - add_wait_queue(&master->lock.lock_queue, &entry); 189 - spin_lock_bh(&master->lock.spinlock); 190 - master->lock.user_waiters++; 191 - spin_unlock_bh(&master->lock.spinlock); 192 - 193 - for (;;) { 194 - __set_current_state(TASK_INTERRUPTIBLE); 195 - if (!master->lock.hw_lock) { 196 - /* Device has been unregistered */ 197 - send_sig(SIGTERM, current, 0); 198 - ret = -EINTR; 199 - break; 200 - } 201 - if (drm_lock_take(&master->lock, lock->context)) { 202 - master->lock.file_priv = file_priv; 203 - master->lock.lock_time = jiffies; 204 - break; /* Got lock */ 205 - } 206 - 207 - /* Contention */ 208 - mutex_unlock(&drm_global_mutex); 209 - schedule(); 210 - mutex_lock(&drm_global_mutex); 211 - if (signal_pending(current)) { 212 - ret = -EINTR; 213 - break; 214 - } 215 - } 216 - spin_lock_bh(&master->lock.spinlock); 217 - master->lock.user_waiters--; 218 - spin_unlock_bh(&master->lock.spinlock); 219 - __set_current_state(TASK_RUNNING); 220 - remove_wait_queue(&master->lock.lock_queue, &entry); 221 - 222 - DRM_DEBUG("%d %s\n", lock->context, 223 - ret ? "interrupted" : "has lock"); 224 - if (ret) return ret; 225 - 226 - /* don't set the block all signals on the master process for now 227 - * really probably not the correct answer but lets us debug xkb 228 - * xserver for now */ 229 - if (!drm_is_current_master(file_priv)) { 230 - dev->sigdata.context = lock->context; 231 - dev->sigdata.lock = master->lock.hw_lock; 232 - } 233 - 234 - if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT)) 235 - { 236 - if (dev->driver->dma_quiescent(dev)) { 237 - DRM_DEBUG("%d waiting for DMA quiescent\n", 238 - lock->context); 239 - return -EBUSY; 240 - } 241 - } 242 - 243 - return 0; 244 - } 245 - 246 - /* 247 - * Unlock ioctl. 248 - * 249 - * \param inode device inode. 250 - * \param file_priv DRM file private. 251 - * \param cmd command. 252 - * \param arg user argument, pointing to a drm_lock structure. 253 - * \return zero on success or negative number on failure. 254 - * 255 - * Transfer and free the lock. 256 - */ 257 - int drm_legacy_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) 258 - { 259 - struct drm_lock *lock = data; 260 - struct drm_master *master = file_priv->master; 261 - 262 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 263 - return -EOPNOTSUPP; 264 - 265 - if (lock->context == DRM_KERNEL_CONTEXT) { 266 - DRM_ERROR("Process %d using kernel context %d\n", 267 - task_pid_nr(current), lock->context); 268 - return -EINVAL; 269 - } 270 - 271 - if (drm_legacy_lock_free(&master->lock, lock->context)) { 272 - /* FIXME: Should really bail out here. */ 273 - } 274 - 275 - return 0; 276 - } 277 - 278 - /* 279 - * This function returns immediately and takes the hw lock 280 - * with the kernel context if it is free, otherwise it gets the highest priority when and if 281 - * it is eventually released. 282 - * 283 - * This guarantees that the kernel will _eventually_ have the lock _unless_ it is held 284 - * by a blocked process. (In the latter case an explicit wait for the hardware lock would cause 285 - * a deadlock, which is why the "idlelock" was invented). 286 - * 287 - * This should be sufficient to wait for GPU idle without 288 - * having to worry about starvation. 289 - */ 290 - void drm_legacy_idlelock_take(struct drm_lock_data *lock_data) 291 - { 292 - int ret; 293 - 294 - spin_lock_bh(&lock_data->spinlock); 295 - lock_data->kernel_waiters++; 296 - if (!lock_data->idle_has_lock) { 297 - 298 - spin_unlock_bh(&lock_data->spinlock); 299 - ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT); 300 - spin_lock_bh(&lock_data->spinlock); 301 - 302 - if (ret == 1) 303 - lock_data->idle_has_lock = 1; 304 - } 305 - spin_unlock_bh(&lock_data->spinlock); 306 - } 307 - EXPORT_SYMBOL(drm_legacy_idlelock_take); 308 - 309 - void drm_legacy_idlelock_release(struct drm_lock_data *lock_data) 310 - { 311 - unsigned int old, prev; 312 - volatile unsigned int *lock = &lock_data->hw_lock->lock; 313 - 314 - spin_lock_bh(&lock_data->spinlock); 315 - if (--lock_data->kernel_waiters == 0) { 316 - if (lock_data->idle_has_lock) { 317 - do { 318 - old = *lock; 319 - prev = cmpxchg(lock, old, DRM_KERNEL_CONTEXT); 320 - } while (prev != old); 321 - wake_up_interruptible(&lock_data->lock_queue); 322 - lock_data->idle_has_lock = 0; 323 - } 324 - } 325 - spin_unlock_bh(&lock_data->spinlock); 326 - } 327 - EXPORT_SYMBOL(drm_legacy_idlelock_release); 328 - 329 - static int drm_legacy_i_have_hw_lock(struct drm_device *dev, 330 - struct drm_file *file_priv) 331 - { 332 - struct drm_master *master = file_priv->master; 333 - 334 - return (file_priv->lock_count && master->lock.hw_lock && 335 - _DRM_LOCK_IS_HELD(master->lock.hw_lock->lock) && 336 - master->lock.file_priv == file_priv); 337 - } 338 - 339 - void drm_legacy_lock_release(struct drm_device *dev, struct file *filp) 340 - { 341 - struct drm_file *file_priv = filp->private_data; 342 - 343 - /* if the master has gone away we can't do anything with the lock */ 344 - if (!dev->master) 345 - return; 346 - 347 - if (drm_legacy_i_have_hw_lock(dev, file_priv)) { 348 - DRM_DEBUG("File %p released, freeing lock for context %d\n", 349 - filp, _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); 350 - drm_legacy_lock_free(&file_priv->master->lock, 351 - _DRM_LOCKING_CONTEXT(file_priv->master->lock.hw_lock->lock)); 352 - } 353 - } 354 - 355 - void drm_legacy_lock_master_cleanup(struct drm_device *dev, struct drm_master *master) 356 - { 357 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 358 - return; 359 - 360 - /* 361 - * Since the master is disappearing, so is the 362 - * possibility to lock. 363 - */ 364 - mutex_lock(&dev->struct_mutex); 365 - if (master->lock.hw_lock) { 366 - if (dev->sigdata.lock == master->lock.hw_lock) 367 - dev->sigdata.lock = NULL; 368 - master->lock.hw_lock = NULL; 369 - master->lock.file_priv = NULL; 370 - wake_up_interruptible_all(&master->lock.lock_queue); 371 - } 372 - mutex_unlock(&dev->struct_mutex); 373 - }
-138
drivers/gpu/drm/drm_memory.c
··· 1 - /* 2 - * \file drm_memory.c 3 - * Memory management wrappers for DRM 4 - * 5 - * \author Rickard E. (Rik) Faith <faith@valinux.com> 6 - * \author Gareth Hughes <gareth@valinux.com> 7 - */ 8 - 9 - /* 10 - * Created: Thu Feb 4 14:00:34 1999 by faith@valinux.com 11 - * 12 - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 13 - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 14 - * All Rights Reserved. 15 - * 16 - * Permission is hereby granted, free of charge, to any person obtaining a 17 - * copy of this software and associated documentation files (the "Software"), 18 - * to deal in the Software without restriction, including without limitation 19 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 - * and/or sell copies of the Software, and to permit persons to whom the 21 - * Software is furnished to do so, subject to the following conditions: 22 - * 23 - * The above copyright notice and this permission notice (including the next 24 - * paragraph) shall be included in all copies or substantial portions of the 25 - * Software. 26 - * 27 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 31 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 32 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33 - * OTHER DEALINGS IN THE SOFTWARE. 34 - */ 35 - 36 - #include <linux/export.h> 37 - #include <linux/highmem.h> 38 - #include <linux/pci.h> 39 - #include <linux/vmalloc.h> 40 - 41 - #include <drm/drm_cache.h> 42 - #include <drm/drm_device.h> 43 - 44 - #include "drm_legacy.h" 45 - 46 - #if IS_ENABLED(CONFIG_AGP) 47 - 48 - #ifdef HAVE_PAGE_AGP 49 - # include <asm/agp.h> 50 - #else 51 - # ifdef __powerpc__ 52 - # define PAGE_AGP pgprot_noncached_wc(PAGE_KERNEL) 53 - # else 54 - # define PAGE_AGP PAGE_KERNEL 55 - # endif 56 - #endif 57 - 58 - static void *agp_remap(unsigned long offset, unsigned long size, 59 - struct drm_device *dev) 60 - { 61 - unsigned long i, num_pages = 62 - PAGE_ALIGN(size) / PAGE_SIZE; 63 - struct drm_agp_mem *agpmem; 64 - struct page **page_map; 65 - struct page **phys_page_map; 66 - void *addr; 67 - 68 - size = PAGE_ALIGN(size); 69 - 70 - #ifdef __alpha__ 71 - offset -= dev->hose->mem_space->start; 72 - #endif 73 - 74 - list_for_each_entry(agpmem, &dev->agp->memory, head) 75 - if (agpmem->bound <= offset 76 - && (agpmem->bound + (agpmem->pages << PAGE_SHIFT)) >= 77 - (offset + size)) 78 - break; 79 - if (&agpmem->head == &dev->agp->memory) 80 - return NULL; 81 - 82 - /* 83 - * OK, we're mapping AGP space on a chipset/platform on which memory accesses by 84 - * the CPU do not get remapped by the GART. We fix this by using the kernel's 85 - * page-table instead (that's probably faster anyhow...). 86 - */ 87 - /* note: use vmalloc() because num_pages could be large... */ 88 - page_map = vmalloc(array_size(num_pages, sizeof(struct page *))); 89 - if (!page_map) 90 - return NULL; 91 - 92 - phys_page_map = (agpmem->memory->pages + (offset - agpmem->bound) / PAGE_SIZE); 93 - for (i = 0; i < num_pages; ++i) 94 - page_map[i] = phys_page_map[i]; 95 - addr = vmap(page_map, num_pages, VM_IOREMAP, PAGE_AGP); 96 - vfree(page_map); 97 - 98 - return addr; 99 - } 100 - 101 - #else /* CONFIG_AGP */ 102 - static inline void *agp_remap(unsigned long offset, unsigned long size, 103 - struct drm_device *dev) 104 - { 105 - return NULL; 106 - } 107 - 108 - #endif /* CONFIG_AGP */ 109 - 110 - void drm_legacy_ioremap(struct drm_local_map *map, struct drm_device *dev) 111 - { 112 - if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) 113 - map->handle = agp_remap(map->offset, map->size, dev); 114 - else 115 - map->handle = ioremap(map->offset, map->size); 116 - } 117 - EXPORT_SYMBOL(drm_legacy_ioremap); 118 - 119 - void drm_legacy_ioremap_wc(struct drm_local_map *map, struct drm_device *dev) 120 - { 121 - if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) 122 - map->handle = agp_remap(map->offset, map->size, dev); 123 - else 124 - map->handle = ioremap_wc(map->offset, map->size); 125 - } 126 - EXPORT_SYMBOL(drm_legacy_ioremap_wc); 127 - 128 - void drm_legacy_ioremapfree(struct drm_local_map *map, struct drm_device *dev) 129 - { 130 - if (!map->handle || !map->size) 131 - return; 132 - 133 - if (dev->agp && dev->agp->cant_use_aperture && map->type == _DRM_AGP) 134 - vunmap(map->handle); 135 - else 136 - iounmap(map->handle); 137 - } 138 - EXPORT_SYMBOL(drm_legacy_ioremapfree);
+15 -2
drivers/gpu/drm/drm_mipi_dsi.c
··· 347 347 { 348 348 struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev); 349 349 350 - mipi_dsi_detach(dsi); 350 + if (dsi->attached) 351 + mipi_dsi_detach(dsi); 351 352 mipi_dsi_device_unregister(dsi); 352 353 353 354 return 0; ··· 371 370 int mipi_dsi_attach(struct mipi_dsi_device *dsi) 372 371 { 373 372 const struct mipi_dsi_host_ops *ops = dsi->host->ops; 373 + int ret; 374 374 375 375 if (!ops || !ops->attach) 376 376 return -ENOSYS; 377 377 378 - return ops->attach(dsi->host, dsi); 378 + ret = ops->attach(dsi->host, dsi); 379 + if (ret) 380 + return ret; 381 + 382 + dsi->attached = true; 383 + 384 + return 0; 379 385 } 380 386 EXPORT_SYMBOL(mipi_dsi_attach); 381 387 ··· 394 386 { 395 387 const struct mipi_dsi_host_ops *ops = dsi->host->ops; 396 388 389 + if (WARN_ON(!dsi->attached)) 390 + return -EINVAL; 391 + 397 392 if (!ops || !ops->detach) 398 393 return -ENOSYS; 394 + 395 + dsi->attached = false; 399 396 400 397 return ops->detach(dsi->host, dsi); 401 398 }
+1 -1
drivers/gpu/drm/drm_mode_object.c
··· 538 538 obj_to_connector(obj), 539 539 prop_value); 540 540 } else { 541 - ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value); 541 + ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value, false); 542 542 if (ret) 543 543 goto out; 544 544 ret = drm_atomic_commit(state);
+1 -203
drivers/gpu/drm/drm_pci.c
··· 29 29 #include <linux/pci.h> 30 30 #include <linux/slab.h> 31 31 32 + #include <drm/drm_auth.h> 32 33 #include <drm/drm.h> 33 34 #include <drm/drm_drv.h> 34 35 #include <drm/drm_print.h> 35 36 36 37 #include "drm_internal.h" 37 - #include "drm_legacy.h" 38 - 39 - #ifdef CONFIG_DRM_LEGACY 40 - /* List of devices hanging off drivers with stealth attach. */ 41 - static LIST_HEAD(legacy_dev_list); 42 - static DEFINE_MUTEX(legacy_dev_list_lock); 43 - #endif 44 38 45 39 static int drm_get_pci_domain(struct drm_device *dev) 46 40 { ··· 65 71 master->unique_len = strlen(master->unique); 66 72 return 0; 67 73 } 68 - 69 - #ifdef CONFIG_DRM_LEGACY 70 - 71 - static int drm_legacy_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p) 72 - { 73 - struct pci_dev *pdev = to_pci_dev(dev->dev); 74 - 75 - if ((p->busnum >> 8) != drm_get_pci_domain(dev) || 76 - (p->busnum & 0xff) != pdev->bus->number || 77 - p->devnum != PCI_SLOT(pdev->devfn) || p->funcnum != PCI_FUNC(pdev->devfn)) 78 - return -EINVAL; 79 - 80 - p->irq = pdev->irq; 81 - 82 - DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum, 83 - p->irq); 84 - return 0; 85 - } 86 - 87 - /** 88 - * drm_legacy_irq_by_busid - Get interrupt from bus ID 89 - * @dev: DRM device 90 - * @data: IOCTL parameter pointing to a drm_irq_busid structure 91 - * @file_priv: DRM file private. 92 - * 93 - * Finds the PCI device with the specified bus id and gets its IRQ number. 94 - * This IOCTL is deprecated, and will now return EINVAL for any busid not equal 95 - * to that of the device that this DRM instance attached to. 96 - * 97 - * Return: 0 on success or a negative error code on failure. 98 - */ 99 - int drm_legacy_irq_by_busid(struct drm_device *dev, void *data, 100 - struct drm_file *file_priv) 101 - { 102 - struct drm_irq_busid *p = data; 103 - 104 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 105 - return -EOPNOTSUPP; 106 - 107 - /* UMS was only ever support on PCI devices. */ 108 - if (WARN_ON(!dev_is_pci(dev->dev))) 109 - return -EINVAL; 110 - 111 - if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) 112 - return -EOPNOTSUPP; 113 - 114 - return drm_legacy_pci_irq_by_busid(dev, p); 115 - } 116 - 117 - void drm_legacy_pci_agp_destroy(struct drm_device *dev) 118 - { 119 - if (dev->agp) { 120 - arch_phys_wc_del(dev->agp->agp_mtrr); 121 - drm_legacy_agp_clear(dev); 122 - kfree(dev->agp); 123 - dev->agp = NULL; 124 - } 125 - } 126 - 127 - static void drm_legacy_pci_agp_init(struct drm_device *dev) 128 - { 129 - if (drm_core_check_feature(dev, DRIVER_USE_AGP)) { 130 - if (pci_find_capability(to_pci_dev(dev->dev), PCI_CAP_ID_AGP)) 131 - dev->agp = drm_legacy_agp_init(dev); 132 - if (dev->agp) { 133 - dev->agp->agp_mtrr = arch_phys_wc_add( 134 - dev->agp->agp_info.aper_base, 135 - dev->agp->agp_info.aper_size * 136 - 1024 * 1024); 137 - } 138 - } 139 - } 140 - 141 - static int drm_legacy_get_pci_dev(struct pci_dev *pdev, 142 - const struct pci_device_id *ent, 143 - const struct drm_driver *driver) 144 - { 145 - struct drm_device *dev; 146 - int ret; 147 - 148 - DRM_DEBUG("\n"); 149 - 150 - dev = drm_dev_alloc(driver, &pdev->dev); 151 - if (IS_ERR(dev)) 152 - return PTR_ERR(dev); 153 - 154 - ret = pci_enable_device(pdev); 155 - if (ret) 156 - goto err_free; 157 - 158 - #ifdef __alpha__ 159 - dev->hose = pdev->sysdata; 160 - #endif 161 - 162 - drm_legacy_pci_agp_init(dev); 163 - 164 - ret = drm_dev_register(dev, ent->driver_data); 165 - if (ret) 166 - goto err_agp; 167 - 168 - if (drm_core_check_feature(dev, DRIVER_LEGACY)) { 169 - mutex_lock(&legacy_dev_list_lock); 170 - list_add_tail(&dev->legacy_dev_list, &legacy_dev_list); 171 - mutex_unlock(&legacy_dev_list_lock); 172 - } 173 - 174 - return 0; 175 - 176 - err_agp: 177 - drm_legacy_pci_agp_destroy(dev); 178 - pci_disable_device(pdev); 179 - err_free: 180 - drm_dev_put(dev); 181 - return ret; 182 - } 183 - 184 - /** 185 - * drm_legacy_pci_init - shadow-attach a legacy DRM PCI driver 186 - * @driver: DRM device driver 187 - * @pdriver: PCI device driver 188 - * 189 - * This is only used by legacy dri1 drivers and deprecated. 190 - * 191 - * Return: 0 on success or a negative error code on failure. 192 - */ 193 - int drm_legacy_pci_init(const struct drm_driver *driver, 194 - struct pci_driver *pdriver) 195 - { 196 - struct pci_dev *pdev = NULL; 197 - const struct pci_device_id *pid; 198 - int i; 199 - 200 - DRM_DEBUG("\n"); 201 - 202 - if (WARN_ON(!(driver->driver_features & DRIVER_LEGACY))) 203 - return -EINVAL; 204 - 205 - /* If not using KMS, fall back to stealth mode manual scanning. */ 206 - for (i = 0; pdriver->id_table[i].vendor != 0; i++) { 207 - pid = &pdriver->id_table[i]; 208 - 209 - /* Loop around setting up a DRM device for each PCI device 210 - * matching our ID and device class. If we had the internal 211 - * function that pci_get_subsys and pci_get_class used, we'd 212 - * be able to just pass pid in instead of doing a two-stage 213 - * thing. 214 - */ 215 - pdev = NULL; 216 - while ((pdev = 217 - pci_get_subsys(pid->vendor, pid->device, pid->subvendor, 218 - pid->subdevice, pdev)) != NULL) { 219 - if ((pdev->class & pid->class_mask) != pid->class) 220 - continue; 221 - 222 - /* stealth mode requires a manual probe */ 223 - pci_dev_get(pdev); 224 - drm_legacy_get_pci_dev(pdev, pid, driver); 225 - } 226 - } 227 - return 0; 228 - } 229 - EXPORT_SYMBOL(drm_legacy_pci_init); 230 - 231 - /** 232 - * drm_legacy_pci_exit - unregister shadow-attach legacy DRM driver 233 - * @driver: DRM device driver 234 - * @pdriver: PCI device driver 235 - * 236 - * Unregister a DRM driver shadow-attached through drm_legacy_pci_init(). This 237 - * is deprecated and only used by dri1 drivers. 238 - */ 239 - void drm_legacy_pci_exit(const struct drm_driver *driver, 240 - struct pci_driver *pdriver) 241 - { 242 - struct drm_device *dev, *tmp; 243 - 244 - DRM_DEBUG("\n"); 245 - 246 - if (!(driver->driver_features & DRIVER_LEGACY)) { 247 - WARN_ON(1); 248 - } else { 249 - mutex_lock(&legacy_dev_list_lock); 250 - list_for_each_entry_safe(dev, tmp, &legacy_dev_list, 251 - legacy_dev_list) { 252 - if (dev->driver == driver) { 253 - list_del(&dev->legacy_dev_list); 254 - drm_put_dev(dev); 255 - } 256 - } 257 - mutex_unlock(&legacy_dev_list_lock); 258 - } 259 - DRM_INFO("Module unloaded\n"); 260 - } 261 - EXPORT_SYMBOL(drm_legacy_pci_exit); 262 - 263 - #endif
+148 -2
drivers/gpu/drm/drm_plane.c
··· 230 230 return 0; 231 231 } 232 232 233 + /** 234 + * DOC: hotspot properties 235 + * 236 + * HOTSPOT_X: property to set mouse hotspot x offset. 237 + * HOTSPOT_Y: property to set mouse hotspot y offset. 238 + * 239 + * When the plane is being used as a cursor image to display a mouse pointer, 240 + * the "hotspot" is the offset within the cursor image where mouse events 241 + * are expected to go. 242 + * 243 + * Positive values move the hotspot from the top-left corner of the cursor 244 + * plane towards the right and bottom. 245 + * 246 + * Most display drivers do not need this information because the 247 + * hotspot is not actually connected to anything visible on screen. 248 + * However, this is necessary for display drivers like the para-virtualized 249 + * drivers (eg qxl, vbox, virtio, vmwgfx), that are attached to a user console 250 + * with a mouse pointer. Since these consoles are often being remoted over a 251 + * network, they would otherwise have to wait to display the pointer movement to 252 + * the user until a full network round-trip has occurred. New mouse events have 253 + * to be sent from the user's console, over the network to the virtual input 254 + * devices, forwarded to the desktop for processing, and then the cursor plane's 255 + * position can be updated and sent back to the user's console over the network. 256 + * Instead, with the hotspot information, the console can anticipate the new 257 + * location, and draw the mouse cursor there before the confirmation comes in. 258 + * To do that correctly, the user's console must be able predict how the 259 + * desktop will process mouse events, which normally requires the desktop's 260 + * mouse topology information, ie where each CRTC sits in the mouse coordinate 261 + * space. This is typically sent to the para-virtualized drivers using some 262 + * driver-specific method, and the driver then forwards it to the console by 263 + * way of the virtual display device or hypervisor. 264 + * 265 + * The assumption is generally made that there is only one cursor plane being 266 + * used this way at a time, and that the desktop is feeding all mouse devices 267 + * into the same global pointer. Para-virtualized drivers that require this 268 + * should only be exposing a single cursor plane, or find some other way 269 + * to coordinate with a userspace desktop that supports multiple pointers. 270 + * If the hotspot properties are set, the cursor plane is therefore assumed to be 271 + * used only for displaying a mouse cursor image, and the position of the combined 272 + * cursor plane + offset can therefore be used for coordinating with input from a 273 + * mouse device. 274 + * 275 + * The cursor will then be drawn either at the location of the plane in the CRTC 276 + * console, or as a free-floating cursor plane on the user's console 277 + * corresponding to their desktop mouse position. 278 + * 279 + * DRM clients which would like to work correctly on drivers which expose 280 + * hotspot properties should advertise DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT. 281 + * Setting this property on drivers which do not special case 282 + * cursor planes will return EOPNOTSUPP, which can be used by userspace to 283 + * gauge requirements of the hardware/drivers they're running on. Advertising 284 + * DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT implies that the userspace client will be 285 + * correctly setting the hotspot properties. 286 + */ 287 + 288 + /** 289 + * drm_plane_create_hotspot_properties - creates the mouse hotspot 290 + * properties and attaches them to the given cursor plane 291 + * 292 + * @plane: drm cursor plane 293 + * 294 + * This function enables the mouse hotspot property on a given 295 + * cursor plane. Look at the documentation for hotspot properties 296 + * to get a better understanding for what they're used for. 297 + * 298 + * RETURNS: 299 + * Zero for success or -errno 300 + */ 301 + static int drm_plane_create_hotspot_properties(struct drm_plane *plane) 302 + { 303 + struct drm_property *prop_x; 304 + struct drm_property *prop_y; 305 + 306 + drm_WARN_ON(plane->dev, 307 + !drm_core_check_feature(plane->dev, 308 + DRIVER_CURSOR_HOTSPOT)); 309 + 310 + prop_x = drm_property_create_signed_range(plane->dev, 0, "HOTSPOT_X", 311 + INT_MIN, INT_MAX); 312 + if (IS_ERR(prop_x)) 313 + return PTR_ERR(prop_x); 314 + 315 + prop_y = drm_property_create_signed_range(plane->dev, 0, "HOTSPOT_Y", 316 + INT_MIN, INT_MAX); 317 + if (IS_ERR(prop_y)) { 318 + drm_property_destroy(plane->dev, prop_x); 319 + return PTR_ERR(prop_y); 320 + } 321 + 322 + drm_object_attach_property(&plane->base, prop_x, 0); 323 + drm_object_attach_property(&plane->base, prop_y, 0); 324 + plane->hotspot_x_property = prop_x; 325 + plane->hotspot_y_property = prop_y; 326 + 327 + return 0; 328 + } 329 + 233 330 __printf(9, 0) 234 331 static int __drm_universal_plane_init(struct drm_device *dev, 235 332 struct drm_plane *plane, ··· 444 347 drm_object_attach_property(&plane->base, config->prop_src_y, 0); 445 348 drm_object_attach_property(&plane->base, config->prop_src_w, 0); 446 349 drm_object_attach_property(&plane->base, config->prop_src_h, 0); 350 + } 351 + if (drm_core_check_feature(dev, DRIVER_CURSOR_HOTSPOT) && 352 + type == DRM_PLANE_TYPE_CURSOR) { 353 + drm_plane_create_hotspot_properties(plane); 447 354 } 448 355 449 356 if (format_modifier_count) ··· 777 676 */ 778 677 if (plane->type != DRM_PLANE_TYPE_OVERLAY && 779 678 !file_priv->universal_planes) 679 + continue; 680 + 681 + /* 682 + * If we're running on a virtualized driver then, 683 + * unless userspace advertizes support for the 684 + * virtualized cursor plane, disable cursor planes 685 + * because they'll be broken due to missing cursor 686 + * hotspot info. 687 + */ 688 + if (plane->type == DRM_PLANE_TYPE_CURSOR && 689 + drm_core_check_feature(dev, DRIVER_CURSOR_HOTSPOT) && 690 + file_priv->atomic && 691 + !file_priv->supports_virtualized_cursor_plane) 780 692 continue; 781 693 782 694 if (drm_lease_held(file_priv, plane->base.id)) { ··· 1166 1052 return PTR_ERR(fb); 1167 1053 } 1168 1054 1169 - fb->hot_x = req->hot_x; 1170 - fb->hot_y = req->hot_y; 1055 + if (plane->hotspot_x_property && plane->state) 1056 + plane->state->hotspot_x = req->hot_x; 1057 + if (plane->hotspot_y_property && plane->state) 1058 + plane->state->hotspot_y = req->hot_y; 1171 1059 } else { 1172 1060 fb = NULL; 1173 1061 } ··· 1558 1442 * Drivers implementing damage can use drm_atomic_helper_damage_iter_init() and 1559 1443 * drm_atomic_helper_damage_iter_next() helper iterator function to get damage 1560 1444 * rectangles clipped to &drm_plane_state.src. 1445 + * 1446 + * Note that there are two types of damage handling: frame damage and buffer 1447 + * damage, the type of damage handling implemented depends on a driver's upload 1448 + * target. Drivers implementing a per-plane or per-CRTC upload target need to 1449 + * handle frame damage, while drivers implementing a per-buffer upload target 1450 + * need to handle buffer damage. 1451 + * 1452 + * The existing damage helpers only support the frame damage type, there is no 1453 + * buffer age support or similar damage accumulation algorithm implemented yet. 1454 + * 1455 + * Only drivers handling frame damage can use the mentioned damage helpers to 1456 + * iterate over the damaged regions. Drivers that handle buffer damage, must set 1457 + * &drm_plane_state.ignore_damage_clips for drm_atomic_helper_damage_iter_init() 1458 + * to know that damage clips should be ignored and return &drm_plane_state.src 1459 + * as the damage rectangle, to force a full plane update. 1460 + * 1461 + * Drivers with a per-buffer upload target could compare the &drm_plane_state.fb 1462 + * of the old and new plane states to determine if the framebuffer attached to a 1463 + * plane has changed or not since the last plane update. If &drm_plane_state.fb 1464 + * has changed, then &drm_plane_state.ignore_damage_clips must be set to true. 1465 + * 1466 + * That is because drivers with a per-plane upload target, expect the backing 1467 + * storage buffer to not change for a given plane. If the upload buffer changes 1468 + * between page flips, the new upload buffer has to be updated as a whole. This 1469 + * can be improved in the future if support for frame damage is added to the DRM 1470 + * damage helpers, similarly to how user-space already handle this case as it is 1471 + * explained in the following documents: 1472 + * 1473 + * https://registry.khronos.org/EGL/extensions/KHR/EGL_KHR_swap_buffers_with_damage.txt 1474 + * https://emersion.fr/blog/2019/intro-to-damage-tracking/ 1561 1475 */ 1562 1476 1563 1477 /**
-32
drivers/gpu/drm/drm_plane_helper.c
··· 279 279 kfree(plane); 280 280 } 281 281 EXPORT_SYMBOL(drm_plane_helper_destroy); 282 - 283 - /** 284 - * drm_plane_helper_atomic_check() - Helper to check plane atomic-state 285 - * @plane: plane to check 286 - * @state: atomic state object 287 - * 288 - * Provides a default plane-state check handler for planes whose atomic-state 289 - * scale and positioning are not expected to change since the plane is always 290 - * a fullscreen scanout buffer. 291 - * 292 - * This is often the case for the primary plane of simple framebuffers. See 293 - * also drm_crtc_helper_atomic_check() for the respective CRTC-state check 294 - * helper function. 295 - * 296 - * RETURNS: 297 - * Zero on success, or an errno code otherwise. 298 - */ 299 - int drm_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state) 300 - { 301 - struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); 302 - struct drm_crtc *new_crtc = new_plane_state->crtc; 303 - struct drm_crtc_state *new_crtc_state = NULL; 304 - 305 - if (new_crtc) 306 - new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); 307 - 308 - return drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, 309 - DRM_PLANE_NO_SCALING, 310 - DRM_PLANE_NO_SCALING, 311 - false, false); 312 - } 313 - EXPORT_SYMBOL(drm_plane_helper_atomic_check);
-220
drivers/gpu/drm/drm_scatter.c
··· 1 - /* 2 - * \file drm_scatter.c 3 - * IOCTLs to manage scatter/gather memory 4 - * 5 - * \author Gareth Hughes <gareth@valinux.com> 6 - */ 7 - 8 - /* 9 - * Created: Mon Dec 18 23:20:54 2000 by gareth@valinux.com 10 - * 11 - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 12 - * All Rights Reserved. 13 - * 14 - * Permission is hereby granted, free of charge, to any person obtaining a 15 - * copy of this software and associated documentation files (the "Software"), 16 - * to deal in the Software without restriction, including without limitation 17 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 18 - * and/or sell copies of the Software, and to permit persons to whom the 19 - * Software is furnished to do so, subject to the following conditions: 20 - * 21 - * The above copyright notice and this permission notice (including the next 22 - * paragraph) shall be included in all copies or substantial portions of the 23 - * Software. 24 - * 25 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 28 - * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 29 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 30 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 31 - * DEALINGS IN THE SOFTWARE. 32 - */ 33 - 34 - #include <linux/mm.h> 35 - #include <linux/slab.h> 36 - #include <linux/vmalloc.h> 37 - 38 - #include <drm/drm.h> 39 - #include <drm/drm_drv.h> 40 - #include <drm/drm_print.h> 41 - 42 - #include "drm_legacy.h" 43 - 44 - #define DEBUG_SCATTER 0 45 - 46 - static void drm_sg_cleanup(struct drm_sg_mem * entry) 47 - { 48 - struct page *page; 49 - int i; 50 - 51 - for (i = 0; i < entry->pages; i++) { 52 - page = entry->pagelist[i]; 53 - if (page) 54 - ClearPageReserved(page); 55 - } 56 - 57 - vfree(entry->virtual); 58 - 59 - kfree(entry->busaddr); 60 - kfree(entry->pagelist); 61 - kfree(entry); 62 - } 63 - 64 - void drm_legacy_sg_cleanup(struct drm_device *dev) 65 - { 66 - if (drm_core_check_feature(dev, DRIVER_SG) && dev->sg && 67 - drm_core_check_feature(dev, DRIVER_LEGACY)) { 68 - drm_sg_cleanup(dev->sg); 69 - dev->sg = NULL; 70 - } 71 - } 72 - #ifdef _LP64 73 - # define ScatterHandle(x) (unsigned int)((x >> 32) + (x & ((1L << 32) - 1))) 74 - #else 75 - # define ScatterHandle(x) (unsigned int)(x) 76 - #endif 77 - 78 - int drm_legacy_sg_alloc(struct drm_device *dev, void *data, 79 - struct drm_file *file_priv) 80 - { 81 - struct drm_scatter_gather *request = data; 82 - struct drm_sg_mem *entry; 83 - unsigned long pages, i, j; 84 - 85 - DRM_DEBUG("\n"); 86 - 87 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 88 - return -EOPNOTSUPP; 89 - 90 - if (!drm_core_check_feature(dev, DRIVER_SG)) 91 - return -EOPNOTSUPP; 92 - 93 - if (request->size > SIZE_MAX - PAGE_SIZE) 94 - return -EINVAL; 95 - 96 - if (dev->sg) 97 - return -EINVAL; 98 - 99 - entry = kzalloc(sizeof(*entry), GFP_KERNEL); 100 - if (!entry) 101 - return -ENOMEM; 102 - 103 - pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE; 104 - DRM_DEBUG("size=%ld pages=%ld\n", request->size, pages); 105 - 106 - entry->pages = pages; 107 - entry->pagelist = kcalloc(pages, sizeof(*entry->pagelist), GFP_KERNEL); 108 - if (!entry->pagelist) { 109 - kfree(entry); 110 - return -ENOMEM; 111 - } 112 - 113 - entry->busaddr = kcalloc(pages, sizeof(*entry->busaddr), GFP_KERNEL); 114 - if (!entry->busaddr) { 115 - kfree(entry->pagelist); 116 - kfree(entry); 117 - return -ENOMEM; 118 - } 119 - 120 - entry->virtual = vmalloc_32(pages << PAGE_SHIFT); 121 - if (!entry->virtual) { 122 - kfree(entry->busaddr); 123 - kfree(entry->pagelist); 124 - kfree(entry); 125 - return -ENOMEM; 126 - } 127 - 128 - /* This also forces the mapping of COW pages, so our page list 129 - * will be valid. Please don't remove it... 130 - */ 131 - memset(entry->virtual, 0, pages << PAGE_SHIFT); 132 - 133 - entry->handle = ScatterHandle((unsigned long)entry->virtual); 134 - 135 - DRM_DEBUG("handle = %08lx\n", entry->handle); 136 - DRM_DEBUG("virtual = %p\n", entry->virtual); 137 - 138 - for (i = (unsigned long)entry->virtual, j = 0; j < pages; 139 - i += PAGE_SIZE, j++) { 140 - entry->pagelist[j] = vmalloc_to_page((void *)i); 141 - if (!entry->pagelist[j]) 142 - goto failed; 143 - SetPageReserved(entry->pagelist[j]); 144 - } 145 - 146 - request->handle = entry->handle; 147 - 148 - dev->sg = entry; 149 - 150 - #if DEBUG_SCATTER 151 - /* Verify that each page points to its virtual address, and vice 152 - * versa. 153 - */ 154 - { 155 - int error = 0; 156 - 157 - for (i = 0; i < pages; i++) { 158 - unsigned long *tmp; 159 - 160 - tmp = page_address(entry->pagelist[i]); 161 - for (j = 0; 162 - j < PAGE_SIZE / sizeof(unsigned long); 163 - j++, tmp++) { 164 - *tmp = 0xcafebabe; 165 - } 166 - tmp = (unsigned long *)((u8 *) entry->virtual + 167 - (PAGE_SIZE * i)); 168 - for (j = 0; 169 - j < PAGE_SIZE / sizeof(unsigned long); 170 - j++, tmp++) { 171 - if (*tmp != 0xcafebabe && error == 0) { 172 - error = 1; 173 - DRM_ERROR("Scatter allocation error, " 174 - "pagelist does not match " 175 - "virtual mapping\n"); 176 - } 177 - } 178 - tmp = page_address(entry->pagelist[i]); 179 - for (j = 0; 180 - j < PAGE_SIZE / sizeof(unsigned long); 181 - j++, tmp++) { 182 - *tmp = 0; 183 - } 184 - } 185 - if (error == 0) 186 - DRM_ERROR("Scatter allocation matches pagelist\n"); 187 - } 188 - #endif 189 - 190 - return 0; 191 - 192 - failed: 193 - drm_sg_cleanup(entry); 194 - return -ENOMEM; 195 - } 196 - 197 - int drm_legacy_sg_free(struct drm_device *dev, void *data, 198 - struct drm_file *file_priv) 199 - { 200 - struct drm_scatter_gather *request = data; 201 - struct drm_sg_mem *entry; 202 - 203 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 204 - return -EOPNOTSUPP; 205 - 206 - if (!drm_core_check_feature(dev, DRIVER_SG)) 207 - return -EOPNOTSUPP; 208 - 209 - entry = dev->sg; 210 - dev->sg = NULL; 211 - 212 - if (!entry || entry->handle != request->handle) 213 - return -EINVAL; 214 - 215 - DRM_DEBUG("virtual = %p\n", entry->virtual); 216 - 217 - drm_sg_cleanup(entry); 218 - 219 - return 0; 220 - }
+51 -13
drivers/gpu/drm/drm_syncobj.c
··· 126 126 * synchronize between the two. 127 127 * This requirement is inherited from the Vulkan fence API. 128 128 * 129 + * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE is set, the ioctl will also set 130 + * a fence deadline hint on the backing fences before waiting, to provide the 131 + * fence signaler with an appropriate sense of urgency. The deadline is 132 + * specified as an absolute &CLOCK_MONOTONIC value in units of ns. 133 + * 129 134 * Similarly, &DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT takes an array of syncobj 130 135 * handles as well as an array of u64 points and does a host-side wait on all 131 136 * of syncobj fences at the given points simultaneously. ··· 1032 1027 uint32_t count, 1033 1028 uint32_t flags, 1034 1029 signed long timeout, 1035 - uint32_t *idx) 1030 + uint32_t *idx, 1031 + ktime_t *deadline) 1036 1032 { 1037 1033 struct syncobj_wait_entry *entries; 1038 1034 struct dma_fence *fence; ··· 1112 1106 if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { 1113 1107 for (i = 0; i < count; ++i) 1114 1108 drm_syncobj_fence_add_wait(syncobjs[i], &entries[i]); 1109 + } 1110 + 1111 + if (deadline) { 1112 + for (i = 0; i < count; ++i) { 1113 + fence = entries[i].fence; 1114 + if (!fence) 1115 + continue; 1116 + dma_fence_set_deadline(fence, *deadline); 1117 + } 1115 1118 } 1116 1119 1117 1120 do { ··· 1221 1206 struct drm_file *file_private, 1222 1207 struct drm_syncobj_wait *wait, 1223 1208 struct drm_syncobj_timeline_wait *timeline_wait, 1224 - struct drm_syncobj **syncobjs, bool timeline) 1209 + struct drm_syncobj **syncobjs, bool timeline, 1210 + ktime_t *deadline) 1225 1211 { 1226 1212 signed long timeout = 0; 1227 1213 uint32_t first = ~0; ··· 1233 1217 NULL, 1234 1218 wait->count_handles, 1235 1219 wait->flags, 1236 - timeout, &first); 1220 + timeout, &first, 1221 + deadline); 1237 1222 if (timeout < 0) 1238 1223 return timeout; 1239 1224 wait->first_signaled = first; ··· 1244 1227 u64_to_user_ptr(timeline_wait->points), 1245 1228 timeline_wait->count_handles, 1246 1229 timeline_wait->flags, 1247 - timeout, &first); 1230 + timeout, &first, 1231 + deadline); 1248 1232 if (timeout < 0) 1249 1233 return timeout; 1250 1234 timeline_wait->first_signaled = first; ··· 1316 1298 { 1317 1299 struct drm_syncobj_wait *args = data; 1318 1300 struct drm_syncobj **syncobjs; 1301 + unsigned int possible_flags; 1302 + ktime_t t, *tp = NULL; 1319 1303 int ret = 0; 1320 1304 1321 1305 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) 1322 1306 return -EOPNOTSUPP; 1323 1307 1324 - if (args->flags & ~(DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL | 1325 - DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT)) 1308 + possible_flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL | 1309 + DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT | 1310 + DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE; 1311 + 1312 + if (args->flags & ~possible_flags) 1326 1313 return -EINVAL; 1327 1314 1328 1315 if (args->count_handles == 0) 1329 - return -EINVAL; 1316 + return 0; 1330 1317 1331 1318 ret = drm_syncobj_array_find(file_private, 1332 1319 u64_to_user_ptr(args->handles), ··· 1340 1317 if (ret < 0) 1341 1318 return ret; 1342 1319 1320 + if (args->flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE) { 1321 + t = ns_to_ktime(args->deadline_nsec); 1322 + tp = &t; 1323 + } 1324 + 1343 1325 ret = drm_syncobj_array_wait(dev, file_private, 1344 - args, NULL, syncobjs, false); 1326 + args, NULL, syncobjs, false, tp); 1345 1327 1346 1328 drm_syncobj_array_free(syncobjs, args->count_handles); 1347 1329 ··· 1359 1331 { 1360 1332 struct drm_syncobj_timeline_wait *args = data; 1361 1333 struct drm_syncobj **syncobjs; 1334 + unsigned int possible_flags; 1335 + ktime_t t, *tp = NULL; 1362 1336 int ret = 0; 1363 1337 1364 1338 if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) 1365 1339 return -EOPNOTSUPP; 1366 1340 1367 - if (args->flags & ~(DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL | 1368 - DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT | 1369 - DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) 1341 + possible_flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL | 1342 + DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT | 1343 + DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE | 1344 + DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE; 1345 + 1346 + if (args->flags & ~possible_flags) 1370 1347 return -EINVAL; 1371 1348 1372 1349 if (args->count_handles == 0) 1373 - return -EINVAL; 1350 + return 0; 1374 1351 1375 1352 ret = drm_syncobj_array_find(file_private, 1376 1353 u64_to_user_ptr(args->handles), ··· 1384 1351 if (ret < 0) 1385 1352 return ret; 1386 1353 1354 + if (args->flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE) { 1355 + t = ns_to_ktime(args->deadline_nsec); 1356 + tp = &t; 1357 + } 1358 + 1387 1359 ret = drm_syncobj_array_wait(dev, file_private, 1388 - NULL, args, syncobjs, true); 1360 + NULL, args, syncobjs, true, tp); 1389 1361 1390 1362 drm_syncobj_array_free(syncobjs, args->count_handles); 1391 1363
-101
drivers/gpu/drm/drm_vblank.c
··· 210 210 if (crtc->funcs->get_vblank_counter) 211 211 return crtc->funcs->get_vblank_counter(crtc); 212 212 } 213 - #ifdef CONFIG_DRM_LEGACY 214 - else if (dev->driver->get_vblank_counter) { 215 - return dev->driver->get_vblank_counter(dev, pipe); 216 - } 217 - #endif 218 213 219 214 return drm_vblank_no_hw_counter(dev, pipe); 220 215 } ··· 428 433 if (crtc->funcs->disable_vblank) 429 434 crtc->funcs->disable_vblank(crtc); 430 435 } 431 - #ifdef CONFIG_DRM_LEGACY 432 - else { 433 - dev->driver->disable_vblank(dev, pipe); 434 - } 435 - #endif 436 436 } 437 437 438 438 /* ··· 1141 1151 if (crtc->funcs->enable_vblank) 1142 1152 return crtc->funcs->enable_vblank(crtc); 1143 1153 } 1144 - #ifdef CONFIG_DRM_LEGACY 1145 - else if (dev->driver->enable_vblank) { 1146 - return dev->driver->enable_vblank(dev, pipe); 1147 - } 1148 - #endif 1149 1154 1150 1155 return -EINVAL; 1151 1156 } ··· 1559 1574 } 1560 1575 EXPORT_SYMBOL(drm_crtc_vblank_restore); 1561 1576 1562 - static void drm_legacy_vblank_pre_modeset(struct drm_device *dev, 1563 - unsigned int pipe) 1564 - { 1565 - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; 1566 - 1567 - /* vblank is not initialized (IRQ not installed ?), or has been freed */ 1568 - if (!drm_dev_has_vblank(dev)) 1569 - return; 1570 - 1571 - if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) 1572 - return; 1573 - 1574 - /* 1575 - * To avoid all the problems that might happen if interrupts 1576 - * were enabled/disabled around or between these calls, we just 1577 - * have the kernel take a reference on the CRTC (just once though 1578 - * to avoid corrupting the count if multiple, mismatch calls occur), 1579 - * so that interrupts remain enabled in the interim. 1580 - */ 1581 - if (!vblank->inmodeset) { 1582 - vblank->inmodeset = 0x1; 1583 - if (drm_vblank_get(dev, pipe) == 0) 1584 - vblank->inmodeset |= 0x2; 1585 - } 1586 - } 1587 - 1588 - static void drm_legacy_vblank_post_modeset(struct drm_device *dev, 1589 - unsigned int pipe) 1590 - { 1591 - struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; 1592 - 1593 - /* vblank is not initialized (IRQ not installed ?), or has been freed */ 1594 - if (!drm_dev_has_vblank(dev)) 1595 - return; 1596 - 1597 - if (drm_WARN_ON(dev, pipe >= dev->num_crtcs)) 1598 - return; 1599 - 1600 - if (vblank->inmodeset) { 1601 - spin_lock_irq(&dev->vbl_lock); 1602 - drm_reset_vblank_timestamp(dev, pipe); 1603 - spin_unlock_irq(&dev->vbl_lock); 1604 - 1605 - if (vblank->inmodeset & 0x2) 1606 - drm_vblank_put(dev, pipe); 1607 - 1608 - vblank->inmodeset = 0; 1609 - } 1610 - } 1611 - 1612 - int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data, 1613 - struct drm_file *file_priv) 1614 - { 1615 - struct drm_modeset_ctl *modeset = data; 1616 - unsigned int pipe; 1617 - 1618 - /* If drm_vblank_init() hasn't been called yet, just no-op */ 1619 - if (!drm_dev_has_vblank(dev)) 1620 - return 0; 1621 - 1622 - /* KMS drivers handle this internally */ 1623 - if (!drm_core_check_feature(dev, DRIVER_LEGACY)) 1624 - return 0; 1625 - 1626 - pipe = modeset->crtc; 1627 - if (pipe >= dev->num_crtcs) 1628 - return -EINVAL; 1629 - 1630 - switch (modeset->cmd) { 1631 - case _DRM_PRE_MODESET: 1632 - drm_legacy_vblank_pre_modeset(dev, pipe); 1633 - break; 1634 - case _DRM_POST_MODESET: 1635 - drm_legacy_vblank_post_modeset(dev, pipe); 1636 - break; 1637 - default: 1638 - return -EINVAL; 1639 - } 1640 - 1641 - return 0; 1642 - } 1643 - 1644 1577 static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, 1645 1578 u64 req_seq, 1646 1579 union drm_wait_vblank *vblwait, ··· 1683 1780 1684 1781 static bool drm_wait_vblank_supported(struct drm_device *dev) 1685 1782 { 1686 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 1687 - if (unlikely(drm_core_check_feature(dev, DRIVER_LEGACY))) 1688 - return dev->irq_enabled; 1689 - #endif 1690 1783 return drm_dev_has_vblank(dev); 1691 1784 } 1692 1785
-665
drivers/gpu/drm/drm_vm.c
··· 1 - /* 2 - * \file drm_vm.c 3 - * Memory mapping for DRM 4 - * 5 - * \author Rickard E. (Rik) Faith <faith@valinux.com> 6 - * \author Gareth Hughes <gareth@valinux.com> 7 - */ 8 - 9 - /* 10 - * Created: Mon Jan 4 08:58:31 1999 by faith@valinux.com 11 - * 12 - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 13 - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 14 - * All Rights Reserved. 15 - * 16 - * Permission is hereby granted, free of charge, to any person obtaining a 17 - * copy of this software and associated documentation files (the "Software"), 18 - * to deal in the Software without restriction, including without limitation 19 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 - * and/or sell copies of the Software, and to permit persons to whom the 21 - * Software is furnished to do so, subject to the following conditions: 22 - * 23 - * The above copyright notice and this permission notice (including the next 24 - * paragraph) shall be included in all copies or substantial portions of the 25 - * Software. 26 - * 27 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 31 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 32 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33 - * OTHER DEALINGS IN THE SOFTWARE. 34 - */ 35 - 36 - #include <linux/export.h> 37 - #include <linux/pci.h> 38 - #include <linux/seq_file.h> 39 - #include <linux/vmalloc.h> 40 - #include <linux/pgtable.h> 41 - 42 - #if defined(__ia64__) 43 - #include <linux/efi.h> 44 - #include <linux/slab.h> 45 - #endif 46 - #include <linux/mem_encrypt.h> 47 - 48 - #include <drm/drm_device.h> 49 - #include <drm/drm_drv.h> 50 - #include <drm/drm_file.h> 51 - #include <drm/drm_framebuffer.h> 52 - #include <drm/drm_print.h> 53 - 54 - #include "drm_internal.h" 55 - #include "drm_legacy.h" 56 - 57 - struct drm_vma_entry { 58 - struct list_head head; 59 - struct vm_area_struct *vma; 60 - pid_t pid; 61 - }; 62 - 63 - static void drm_vm_open(struct vm_area_struct *vma); 64 - static void drm_vm_close(struct vm_area_struct *vma); 65 - 66 - static pgprot_t drm_io_prot(struct drm_local_map *map, 67 - struct vm_area_struct *vma) 68 - { 69 - pgprot_t tmp = vm_get_page_prot(vma->vm_flags); 70 - 71 - #if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__) || \ 72 - defined(__mips__) || defined(__loongarch__) 73 - if (map->type == _DRM_REGISTERS && !(map->flags & _DRM_WRITE_COMBINING)) 74 - tmp = pgprot_noncached(tmp); 75 - else 76 - tmp = pgprot_writecombine(tmp); 77 - #elif defined(__ia64__) 78 - if (efi_range_is_wc(vma->vm_start, vma->vm_end - 79 - vma->vm_start)) 80 - tmp = pgprot_writecombine(tmp); 81 - else 82 - tmp = pgprot_noncached(tmp); 83 - #elif defined(__sparc__) || defined(__arm__) 84 - tmp = pgprot_noncached(tmp); 85 - #endif 86 - return tmp; 87 - } 88 - 89 - static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma) 90 - { 91 - pgprot_t tmp = vm_get_page_prot(vma->vm_flags); 92 - 93 - #if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE) 94 - tmp = pgprot_noncached_wc(tmp); 95 - #endif 96 - return tmp; 97 - } 98 - 99 - /* 100 - * \c fault method for AGP virtual memory. 101 - * 102 - * \param vma virtual memory area. 103 - * \param address access address. 104 - * \return pointer to the page structure. 105 - * 106 - * Find the right map and if it's AGP memory find the real physical page to 107 - * map, get the page, increment the use count and return it. 108 - */ 109 - #if IS_ENABLED(CONFIG_AGP) 110 - static vm_fault_t drm_vm_fault(struct vm_fault *vmf) 111 - { 112 - struct vm_area_struct *vma = vmf->vma; 113 - struct drm_file *priv = vma->vm_file->private_data; 114 - struct drm_device *dev = priv->minor->dev; 115 - struct drm_local_map *map = NULL; 116 - struct drm_map_list *r_list; 117 - struct drm_hash_item *hash; 118 - 119 - /* 120 - * Find the right map 121 - */ 122 - if (!dev->agp) 123 - goto vm_fault_error; 124 - 125 - if (!dev->agp || !dev->agp->cant_use_aperture) 126 - goto vm_fault_error; 127 - 128 - if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) 129 - goto vm_fault_error; 130 - 131 - r_list = drm_hash_entry(hash, struct drm_map_list, hash); 132 - map = r_list->map; 133 - 134 - if (map && map->type == _DRM_AGP) { 135 - /* 136 - * Using vm_pgoff as a selector forces us to use this unusual 137 - * addressing scheme. 138 - */ 139 - resource_size_t offset = vmf->address - vma->vm_start; 140 - resource_size_t baddr = map->offset + offset; 141 - struct drm_agp_mem *agpmem; 142 - struct page *page; 143 - 144 - #ifdef __alpha__ 145 - /* 146 - * Adjust to a bus-relative address 147 - */ 148 - baddr -= dev->hose->mem_space->start; 149 - #endif 150 - 151 - /* 152 - * It's AGP memory - find the real physical page to map 153 - */ 154 - list_for_each_entry(agpmem, &dev->agp->memory, head) { 155 - if (agpmem->bound <= baddr && 156 - agpmem->bound + agpmem->pages * PAGE_SIZE > baddr) 157 - break; 158 - } 159 - 160 - if (&agpmem->head == &dev->agp->memory) 161 - goto vm_fault_error; 162 - 163 - /* 164 - * Get the page, inc the use count, and return it 165 - */ 166 - offset = (baddr - agpmem->bound) >> PAGE_SHIFT; 167 - page = agpmem->memory->pages[offset]; 168 - get_page(page); 169 - vmf->page = page; 170 - 171 - DRM_DEBUG 172 - ("baddr = 0x%llx page = 0x%p, offset = 0x%llx, count=%d\n", 173 - (unsigned long long)baddr, 174 - agpmem->memory->pages[offset], 175 - (unsigned long long)offset, 176 - page_count(page)); 177 - return 0; 178 - } 179 - vm_fault_error: 180 - return VM_FAULT_SIGBUS; /* Disallow mremap */ 181 - } 182 - #else 183 - static vm_fault_t drm_vm_fault(struct vm_fault *vmf) 184 - { 185 - return VM_FAULT_SIGBUS; 186 - } 187 - #endif 188 - 189 - /* 190 - * \c nopage method for shared virtual memory. 191 - * 192 - * \param vma virtual memory area. 193 - * \param address access address. 194 - * \return pointer to the page structure. 195 - * 196 - * Get the mapping, find the real physical page to map, get the page, and 197 - * return it. 198 - */ 199 - static vm_fault_t drm_vm_shm_fault(struct vm_fault *vmf) 200 - { 201 - struct vm_area_struct *vma = vmf->vma; 202 - struct drm_local_map *map = vma->vm_private_data; 203 - unsigned long offset; 204 - unsigned long i; 205 - struct page *page; 206 - 207 - if (!map) 208 - return VM_FAULT_SIGBUS; /* Nothing allocated */ 209 - 210 - offset = vmf->address - vma->vm_start; 211 - i = (unsigned long)map->handle + offset; 212 - page = vmalloc_to_page((void *)i); 213 - if (!page) 214 - return VM_FAULT_SIGBUS; 215 - get_page(page); 216 - vmf->page = page; 217 - 218 - DRM_DEBUG("shm_fault 0x%lx\n", offset); 219 - return 0; 220 - } 221 - 222 - /* 223 - * \c close method for shared virtual memory. 224 - * 225 - * \param vma virtual memory area. 226 - * 227 - * Deletes map information if we are the last 228 - * person to close a mapping and it's not in the global maplist. 229 - */ 230 - static void drm_vm_shm_close(struct vm_area_struct *vma) 231 - { 232 - struct drm_file *priv = vma->vm_file->private_data; 233 - struct drm_device *dev = priv->minor->dev; 234 - struct drm_vma_entry *pt, *temp; 235 - struct drm_local_map *map; 236 - struct drm_map_list *r_list; 237 - int found_maps = 0; 238 - 239 - DRM_DEBUG("0x%08lx,0x%08lx\n", 240 - vma->vm_start, vma->vm_end - vma->vm_start); 241 - 242 - map = vma->vm_private_data; 243 - 244 - mutex_lock(&dev->struct_mutex); 245 - list_for_each_entry_safe(pt, temp, &dev->vmalist, head) { 246 - if (pt->vma->vm_private_data == map) 247 - found_maps++; 248 - if (pt->vma == vma) { 249 - list_del(&pt->head); 250 - kfree(pt); 251 - } 252 - } 253 - 254 - /* We were the only map that was found */ 255 - if (found_maps == 1 && map->flags & _DRM_REMOVABLE) { 256 - /* Check to see if we are in the maplist, if we are not, then 257 - * we delete this mappings information. 258 - */ 259 - found_maps = 0; 260 - list_for_each_entry(r_list, &dev->maplist, head) { 261 - if (r_list->map == map) 262 - found_maps++; 263 - } 264 - 265 - if (!found_maps) { 266 - switch (map->type) { 267 - case _DRM_REGISTERS: 268 - case _DRM_FRAME_BUFFER: 269 - arch_phys_wc_del(map->mtrr); 270 - iounmap(map->handle); 271 - break; 272 - case _DRM_SHM: 273 - vfree(map->handle); 274 - break; 275 - case _DRM_AGP: 276 - case _DRM_SCATTER_GATHER: 277 - break; 278 - case _DRM_CONSISTENT: 279 - dma_free_coherent(dev->dev, 280 - map->size, 281 - map->handle, 282 - map->offset); 283 - break; 284 - } 285 - kfree(map); 286 - } 287 - } 288 - mutex_unlock(&dev->struct_mutex); 289 - } 290 - 291 - /* 292 - * \c fault method for DMA virtual memory. 293 - * 294 - * \param address access address. 295 - * \return pointer to the page structure. 296 - * 297 - * Determine the page number from the page offset and get it from drm_device_dma::pagelist. 298 - */ 299 - static vm_fault_t drm_vm_dma_fault(struct vm_fault *vmf) 300 - { 301 - struct vm_area_struct *vma = vmf->vma; 302 - struct drm_file *priv = vma->vm_file->private_data; 303 - struct drm_device *dev = priv->minor->dev; 304 - struct drm_device_dma *dma = dev->dma; 305 - unsigned long offset; 306 - unsigned long page_nr; 307 - struct page *page; 308 - 309 - if (!dma) 310 - return VM_FAULT_SIGBUS; /* Error */ 311 - if (!dma->pagelist) 312 - return VM_FAULT_SIGBUS; /* Nothing allocated */ 313 - 314 - offset = vmf->address - vma->vm_start; 315 - /* vm_[pg]off[set] should be 0 */ 316 - page_nr = offset >> PAGE_SHIFT; /* page_nr could just be vmf->pgoff */ 317 - page = virt_to_page((void *)dma->pagelist[page_nr]); 318 - 319 - get_page(page); 320 - vmf->page = page; 321 - 322 - DRM_DEBUG("dma_fault 0x%lx (page %lu)\n", offset, page_nr); 323 - return 0; 324 - } 325 - 326 - /* 327 - * \c fault method for scatter-gather virtual memory. 328 - * 329 - * \param address access address. 330 - * \return pointer to the page structure. 331 - * 332 - * Determine the map offset from the page offset and get it from drm_sg_mem::pagelist. 333 - */ 334 - static vm_fault_t drm_vm_sg_fault(struct vm_fault *vmf) 335 - { 336 - struct vm_area_struct *vma = vmf->vma; 337 - struct drm_local_map *map = vma->vm_private_data; 338 - struct drm_file *priv = vma->vm_file->private_data; 339 - struct drm_device *dev = priv->minor->dev; 340 - struct drm_sg_mem *entry = dev->sg; 341 - unsigned long offset; 342 - unsigned long map_offset; 343 - unsigned long page_offset; 344 - struct page *page; 345 - 346 - if (!entry) 347 - return VM_FAULT_SIGBUS; /* Error */ 348 - if (!entry->pagelist) 349 - return VM_FAULT_SIGBUS; /* Nothing allocated */ 350 - 351 - offset = vmf->address - vma->vm_start; 352 - map_offset = map->offset - (unsigned long)dev->sg->virtual; 353 - page_offset = (offset >> PAGE_SHIFT) + (map_offset >> PAGE_SHIFT); 354 - page = entry->pagelist[page_offset]; 355 - get_page(page); 356 - vmf->page = page; 357 - 358 - return 0; 359 - } 360 - 361 - /** AGP virtual memory operations */ 362 - static const struct vm_operations_struct drm_vm_ops = { 363 - .fault = drm_vm_fault, 364 - .open = drm_vm_open, 365 - .close = drm_vm_close, 366 - }; 367 - 368 - /** Shared virtual memory operations */ 369 - static const struct vm_operations_struct drm_vm_shm_ops = { 370 - .fault = drm_vm_shm_fault, 371 - .open = drm_vm_open, 372 - .close = drm_vm_shm_close, 373 - }; 374 - 375 - /** DMA virtual memory operations */ 376 - static const struct vm_operations_struct drm_vm_dma_ops = { 377 - .fault = drm_vm_dma_fault, 378 - .open = drm_vm_open, 379 - .close = drm_vm_close, 380 - }; 381 - 382 - /** Scatter-gather virtual memory operations */ 383 - static const struct vm_operations_struct drm_vm_sg_ops = { 384 - .fault = drm_vm_sg_fault, 385 - .open = drm_vm_open, 386 - .close = drm_vm_close, 387 - }; 388 - 389 - static void drm_vm_open_locked(struct drm_device *dev, 390 - struct vm_area_struct *vma) 391 - { 392 - struct drm_vma_entry *vma_entry; 393 - 394 - DRM_DEBUG("0x%08lx,0x%08lx\n", 395 - vma->vm_start, vma->vm_end - vma->vm_start); 396 - 397 - vma_entry = kmalloc(sizeof(*vma_entry), GFP_KERNEL); 398 - if (vma_entry) { 399 - vma_entry->vma = vma; 400 - vma_entry->pid = current->pid; 401 - list_add(&vma_entry->head, &dev->vmalist); 402 - } 403 - } 404 - 405 - static void drm_vm_open(struct vm_area_struct *vma) 406 - { 407 - struct drm_file *priv = vma->vm_file->private_data; 408 - struct drm_device *dev = priv->minor->dev; 409 - 410 - mutex_lock(&dev->struct_mutex); 411 - drm_vm_open_locked(dev, vma); 412 - mutex_unlock(&dev->struct_mutex); 413 - } 414 - 415 - static void drm_vm_close_locked(struct drm_device *dev, 416 - struct vm_area_struct *vma) 417 - { 418 - struct drm_vma_entry *pt, *temp; 419 - 420 - DRM_DEBUG("0x%08lx,0x%08lx\n", 421 - vma->vm_start, vma->vm_end - vma->vm_start); 422 - 423 - list_for_each_entry_safe(pt, temp, &dev->vmalist, head) { 424 - if (pt->vma == vma) { 425 - list_del(&pt->head); 426 - kfree(pt); 427 - break; 428 - } 429 - } 430 - } 431 - 432 - /* 433 - * \c close method for all virtual memory types. 434 - * 435 - * \param vma virtual memory area. 436 - * 437 - * Search the \p vma private data entry in drm_device::vmalist, unlink it, and 438 - * free it. 439 - */ 440 - static void drm_vm_close(struct vm_area_struct *vma) 441 - { 442 - struct drm_file *priv = vma->vm_file->private_data; 443 - struct drm_device *dev = priv->minor->dev; 444 - 445 - mutex_lock(&dev->struct_mutex); 446 - drm_vm_close_locked(dev, vma); 447 - mutex_unlock(&dev->struct_mutex); 448 - } 449 - 450 - /* 451 - * mmap DMA memory. 452 - * 453 - * \param file_priv DRM file private. 454 - * \param vma virtual memory area. 455 - * \return zero on success or a negative number on failure. 456 - * 457 - * Sets the virtual memory area operations structure to vm_dma_ops, the file 458 - * pointer, and calls vm_open(). 459 - */ 460 - static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) 461 - { 462 - struct drm_file *priv = filp->private_data; 463 - struct drm_device *dev; 464 - struct drm_device_dma *dma; 465 - unsigned long length = vma->vm_end - vma->vm_start; 466 - 467 - dev = priv->minor->dev; 468 - dma = dev->dma; 469 - DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", 470 - vma->vm_start, vma->vm_end, vma->vm_pgoff); 471 - 472 - /* Length must match exact page count */ 473 - if (!dma || (length >> PAGE_SHIFT) != dma->page_count) { 474 - return -EINVAL; 475 - } 476 - 477 - if (!capable(CAP_SYS_ADMIN) && 478 - (dma->flags & _DRM_DMA_USE_PCI_RO)) { 479 - vm_flags_clear(vma, VM_WRITE | VM_MAYWRITE); 480 - #if defined(__i386__) || defined(__x86_64__) 481 - pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; 482 - #else 483 - /* Ye gads this is ugly. With more thought 484 - we could move this up higher and use 485 - `protection_map' instead. */ 486 - vma->vm_page_prot = 487 - __pgprot(pte_val 488 - (pte_wrprotect 489 - (__pte(pgprot_val(vma->vm_page_prot))))); 490 - #endif 491 - } 492 - 493 - vma->vm_ops = &drm_vm_dma_ops; 494 - 495 - vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP); 496 - 497 - drm_vm_open_locked(dev, vma); 498 - return 0; 499 - } 500 - 501 - static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev) 502 - { 503 - #ifdef __alpha__ 504 - return dev->hose->dense_mem_base; 505 - #else 506 - return 0; 507 - #endif 508 - } 509 - 510 - /* 511 - * mmap DMA memory. 512 - * 513 - * \param file_priv DRM file private. 514 - * \param vma virtual memory area. 515 - * \return zero on success or a negative number on failure. 516 - * 517 - * If the virtual memory area has no offset associated with it then it's a DMA 518 - * area, so calls mmap_dma(). Otherwise searches the map in drm_device::maplist, 519 - * checks that the restricted flag is not set, sets the virtual memory operations 520 - * according to the mapping type and remaps the pages. Finally sets the file 521 - * pointer and calls vm_open(). 522 - */ 523 - static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) 524 - { 525 - struct drm_file *priv = filp->private_data; 526 - struct drm_device *dev = priv->minor->dev; 527 - struct drm_local_map *map = NULL; 528 - resource_size_t offset = 0; 529 - struct drm_hash_item *hash; 530 - 531 - DRM_DEBUG("start = 0x%lx, end = 0x%lx, page offset = 0x%lx\n", 532 - vma->vm_start, vma->vm_end, vma->vm_pgoff); 533 - 534 - if (!priv->authenticated) 535 - return -EACCES; 536 - 537 - /* We check for "dma". On Apple's UniNorth, it's valid to have 538 - * the AGP mapped at physical address 0 539 - * --BenH. 540 - */ 541 - if (!vma->vm_pgoff 542 - #if IS_ENABLED(CONFIG_AGP) 543 - && (!dev->agp 544 - || dev->agp->agp_info.device->vendor != PCI_VENDOR_ID_APPLE) 545 - #endif 546 - ) 547 - return drm_mmap_dma(filp, vma); 548 - 549 - if (drm_ht_find_item(&dev->map_hash, vma->vm_pgoff, &hash)) { 550 - DRM_ERROR("Could not find map\n"); 551 - return -EINVAL; 552 - } 553 - 554 - map = drm_hash_entry(hash, struct drm_map_list, hash)->map; 555 - if (!map || ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) 556 - return -EPERM; 557 - 558 - /* Check for valid size. */ 559 - if (map->size < vma->vm_end - vma->vm_start) 560 - return -EINVAL; 561 - 562 - if (!capable(CAP_SYS_ADMIN) && (map->flags & _DRM_READ_ONLY)) { 563 - vm_flags_clear(vma, VM_WRITE | VM_MAYWRITE); 564 - #if defined(__i386__) || defined(__x86_64__) 565 - pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW; 566 - #else 567 - /* Ye gads this is ugly. With more thought 568 - we could move this up higher and use 569 - `protection_map' instead. */ 570 - vma->vm_page_prot = 571 - __pgprot(pte_val 572 - (pte_wrprotect 573 - (__pte(pgprot_val(vma->vm_page_prot))))); 574 - #endif 575 - } 576 - 577 - switch (map->type) { 578 - #if !defined(__arm__) 579 - case _DRM_AGP: 580 - if (dev->agp && dev->agp->cant_use_aperture) { 581 - /* 582 - * On some platforms we can't talk to bus dma address from the CPU, so for 583 - * memory of type DRM_AGP, we'll deal with sorting out the real physical 584 - * pages and mappings in fault() 585 - */ 586 - #if defined(__powerpc__) 587 - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 588 - #endif 589 - vma->vm_ops = &drm_vm_ops; 590 - break; 591 - } 592 - fallthrough; /* to _DRM_FRAME_BUFFER... */ 593 - #endif 594 - case _DRM_FRAME_BUFFER: 595 - case _DRM_REGISTERS: 596 - offset = drm_core_get_reg_ofs(dev); 597 - vma->vm_page_prot = drm_io_prot(map, vma); 598 - if (io_remap_pfn_range(vma, vma->vm_start, 599 - (map->offset + offset) >> PAGE_SHIFT, 600 - vma->vm_end - vma->vm_start, 601 - vma->vm_page_prot)) 602 - return -EAGAIN; 603 - DRM_DEBUG(" Type = %d; start = 0x%lx, end = 0x%lx," 604 - " offset = 0x%llx\n", 605 - map->type, 606 - vma->vm_start, vma->vm_end, (unsigned long long)(map->offset + offset)); 607 - 608 - vma->vm_ops = &drm_vm_ops; 609 - break; 610 - case _DRM_CONSISTENT: 611 - /* Consistent memory is really like shared memory. But 612 - * it's allocated in a different way, so avoid fault */ 613 - if (remap_pfn_range(vma, vma->vm_start, 614 - page_to_pfn(virt_to_page(map->handle)), 615 - vma->vm_end - vma->vm_start, vma->vm_page_prot)) 616 - return -EAGAIN; 617 - vma->vm_page_prot = drm_dma_prot(map->type, vma); 618 - fallthrough; /* to _DRM_SHM */ 619 - case _DRM_SHM: 620 - vma->vm_ops = &drm_vm_shm_ops; 621 - vma->vm_private_data = (void *)map; 622 - break; 623 - case _DRM_SCATTER_GATHER: 624 - vma->vm_ops = &drm_vm_sg_ops; 625 - vma->vm_private_data = (void *)map; 626 - vma->vm_page_prot = drm_dma_prot(map->type, vma); 627 - break; 628 - default: 629 - return -EINVAL; /* This should never happen. */ 630 - } 631 - vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP); 632 - 633 - drm_vm_open_locked(dev, vma); 634 - return 0; 635 - } 636 - 637 - int drm_legacy_mmap(struct file *filp, struct vm_area_struct *vma) 638 - { 639 - struct drm_file *priv = filp->private_data; 640 - struct drm_device *dev = priv->minor->dev; 641 - int ret; 642 - 643 - if (drm_dev_is_unplugged(dev)) 644 - return -ENODEV; 645 - 646 - mutex_lock(&dev->struct_mutex); 647 - ret = drm_mmap_locked(filp, vma); 648 - mutex_unlock(&dev->struct_mutex); 649 - 650 - return ret; 651 - } 652 - EXPORT_SYMBOL(drm_legacy_mmap); 653 - 654 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 655 - void drm_legacy_vma_flush(struct drm_device *dev) 656 - { 657 - struct drm_vma_entry *vma, *vma_temp; 658 - 659 - /* Clear vma list (only needed for legacy drivers) */ 660 - list_for_each_entry_safe(vma, vma_temp, &dev->vmalist, head) { 661 - list_del(&vma->head); 662 - kfree(vma); 663 - } 664 - } 665 - #endif
+5 -4
drivers/gpu/drm/exynos/exynos_drm_gsc.c
··· 11 11 #include <linux/component.h> 12 12 #include <linux/kernel.h> 13 13 #include <linux/mfd/syscon.h> 14 - #include <linux/of_device.h> 14 + #include <linux/mod_devicetable.h> 15 15 #include <linux/platform_device.h> 16 16 #include <linux/pm_runtime.h> 17 + #include <linux/property.h> 17 18 #include <linux/regmap.h> 18 19 19 20 #include <drm/drm_fourcc.h> ··· 104 103 unsigned int num_formats; 105 104 106 105 void __iomem *regs; 107 - const char **clk_names; 106 + const char *const *clk_names; 108 107 struct clk *clocks[GSC_MAX_CLOCKS]; 109 108 int num_clocks; 110 109 struct gsc_scaler sc; ··· 1218 1217 static int gsc_probe(struct platform_device *pdev) 1219 1218 { 1220 1219 struct device *dev = &pdev->dev; 1221 - struct gsc_driverdata *driver_data; 1220 + const struct gsc_driverdata *driver_data; 1222 1221 struct exynos_drm_ipp_formats *formats; 1223 1222 struct gsc_context *ctx; 1224 1223 int num_formats, ret, i, j; ··· 1227 1226 if (!ctx) 1228 1227 return -ENOMEM; 1229 1228 1230 - driver_data = (struct gsc_driverdata *)of_device_get_match_data(dev); 1229 + driver_data = device_get_match_data(dev); 1231 1230 ctx->dev = dev; 1232 1231 ctx->num_clocks = driver_data->num_clocks; 1233 1232 ctx->clk_names = driver_data->clk_names;
+1
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
··· 9 9 #include <linux/sync_file.h> 10 10 #include <linux/uaccess.h> 11 11 12 + #include <drm/drm_auth.h> 12 13 #include <drm/drm_syncobj.h> 13 14 14 15 #include "display/intel_frontbuffer.h"
+1
drivers/gpu/drm/imagination/pvr_cccb.h
··· 86 86 87 87 /** 88 88 * pvr_cccb_cmdseq_can_fit() - Check if a command sequence can fit in the CCCB. 89 + * @pvr_cccb: Target Client CCB. 89 90 * @size: Command sequence size. 90 91 * 91 92 * Returns:
+5 -5
drivers/gpu/drm/imagination/pvr_device.c
··· 105 105 106 106 sys_clk = devm_clk_get_optional(drm_dev->dev, "sys"); 107 107 if (IS_ERR(sys_clk)) 108 - return dev_err_probe(drm_dev->dev, PTR_ERR(core_clk), 108 + return dev_err_probe(drm_dev->dev, PTR_ERR(sys_clk), 109 109 "failed to get sys clock\n"); 110 110 111 111 mem_clk = devm_clk_get_optional(drm_dev->dev, "mem"); 112 112 if (IS_ERR(mem_clk)) 113 - return dev_err_probe(drm_dev->dev, PTR_ERR(core_clk), 113 + return dev_err_probe(drm_dev->dev, PTR_ERR(mem_clk), 114 114 "failed to get mem clock\n"); 115 115 116 116 pvr_dev->core_clk = core_clk; ··· 127 127 * This is called any time we receive a FW event. It iterates over all 128 128 * active queues and calls pvr_queue_process() on them. 129 129 */ 130 - void pvr_device_process_active_queues(struct pvr_device *pvr_dev) 130 + static void pvr_device_process_active_queues(struct pvr_device *pvr_dev) 131 131 { 132 132 struct pvr_queue *queue, *tmp_queue; 133 133 LIST_HEAD(active_queues); ··· 286 286 287 287 filename = pvr_build_firmware_filename(pvr_dev, "powervr/rogue", 288 288 PVR_FW_VERSION_MAJOR); 289 - if (IS_ERR(filename)) 290 - return PTR_ERR(filename); 289 + if (!filename) 290 + return -ENOMEM; 291 291 292 292 /* 293 293 * This function takes a copy of &filename, meaning we can free our
+18 -7
drivers/gpu/drm/imagination/pvr_device.h
··· 203 203 struct mutex lock; 204 204 } queues; 205 205 206 + /** 207 + * @watchdog: Watchdog for communications with firmware. 208 + */ 206 209 struct { 207 210 /** @work: Work item for watchdog callback. */ 208 211 struct delayed_work work; 209 212 210 - /** @old_kccb_cmds_executed: KCCB command execution count at last watchdog poll. */ 213 + /** 214 + * @old_kccb_cmds_executed: KCCB command execution count at last 215 + * watchdog poll. 216 + */ 211 217 u32 old_kccb_cmds_executed; 212 218 213 - /** @kccb_stall_count: Number of watchdog polls KCCB has been stalled for. */ 219 + /** 220 + * @kccb_stall_count: Number of watchdog polls KCCB has been 221 + * stalled for. 222 + */ 214 223 u32 kccb_stall_count; 215 224 } watchdog; 216 225 226 + /** 227 + * @kccb: Circular buffer for communications with firmware. 228 + */ 217 229 struct { 218 230 /** @ccb: Kernel CCB. */ 219 231 struct pvr_ccb ccb; ··· 237 225 struct pvr_fw_object *rtn_obj; 238 226 239 227 /** 240 - * @rtn: Pointer to CPU mapping of KCCB return slots. Must be accessed by 241 - * READ_ONCE()/WRITE_ONCE(). 228 + * @rtn: Pointer to CPU mapping of KCCB return slots. Must be 229 + * accessed by READ_ONCE()/WRITE_ONCE(). 242 230 */ 243 231 u32 *rtn; 244 232 ··· 305 293 306 294 /** 307 295 * @pvr_dev: A reference to the powervr-specific wrapper for the 308 - * associated device. Saves on repeated calls to 309 - * to_pvr_device(). 296 + * associated device. Saves on repeated calls to to_pvr_device(). 310 297 */ 311 298 struct pvr_device *pvr_dev; 312 299 313 300 /** 314 301 * @ctx_handles: Array of contexts belonging to this file. Array members 315 - * are of type "struct pvr_context *". 302 + * are of type "struct pvr_context *". 316 303 * 317 304 * This array is used to allocate handles returned to userspace. 318 305 */
+2 -1
drivers/gpu/drm/imagination/pvr_device_info.c
··· 227 227 /* Verify no unsupported values in the bitmask. */ 228 228 if (features_size > mapping_max_size) { 229 229 drm_warn(from_pvr_device(pvr_dev), "Unsupported features in firmware image"); 230 - } else if (features_size == mapping_max_size && (mapping_max & 63)) { 230 + } else if (features_size == mapping_max_size && 231 + ((mapping_max & 63) != 0)) { 231 232 u64 invalid_mask = ~0ull << (mapping_max & 63); 232 233 233 234 if (features[features_size - 1] & invalid_mask)
+1 -1
drivers/gpu/drm/imagination/pvr_free_list.c
··· 255 255 256 256 if (!num_pages) 257 257 break; 258 - }; 258 + } 259 259 /* clang-format on */ 260 260 261 261 /* Make sure our free_list update is flushed. */
+2 -1
drivers/gpu/drm/imagination/pvr_fw.h
··· 481 481 } 482 482 483 483 /** 484 - * pvr_fw_get_dma_addr() - Get DMA address for given offset in firmware object 484 + * pvr_fw_object_get_dma_addr() - Get DMA address for given offset in firmware 485 + * object. 485 486 * @fw_obj: Pointer to object to lookup address in. 486 487 * @offset: Offset within object to lookup address at. 487 488 * @dma_addr_out: Pointer to location to store DMA address.
+4 -4
drivers/gpu/drm/imagination/pvr_fw_info.h
··· 122 122 * struct pvr_fw_device_info_header - Device information header. 123 123 */ 124 124 struct pvr_fw_device_info_header { 125 - /* BRN Mask size (in u64s). */ 125 + /** @brn_mask_size: BRN mask size (in u64s). */ 126 126 u64 brn_mask_size; 127 - /* ERN Mask size (in u64s). */ 127 + /** @ern_mask_size: ERN mask size (in u64s). */ 128 128 u64 ern_mask_size; 129 - /* Feature Mask size (in u64s). */ 129 + /** @feature_mask_size: Feature mask size (in u64s). */ 130 130 u64 feature_mask_size; 131 - /* Feature Parameter size (in u64s). */ 131 + /** @feature_param_size: Feature parameter size (in u64s). */ 132 132 u64 feature_param_size; 133 133 }; 134 134
+1
drivers/gpu/drm/imagination/pvr_fw_meta.c
··· 4 4 #include "pvr_device.h" 5 5 #include "pvr_fw.h" 6 6 #include "pvr_fw_info.h" 7 + #include "pvr_fw_meta.h" 7 8 #include "pvr_gem.h" 8 9 #include "pvr_rogue_cr_defs.h" 9 10 #include "pvr_rogue_meta.h"
+2 -46
drivers/gpu/drm/imagination/pvr_fw_trace.c
··· 121 121 pvr_fw_object_unmap_and_destroy(fw_trace->tracebuf_ctrl_obj); 122 122 } 123 123 124 + #if defined(CONFIG_DEBUG_FS) 125 + 124 126 /** 125 127 * update_logtype() - Send KCCB command to trigger FW to update logtype 126 128 * @pvr_dev: Target PowerVR device ··· 166 164 167 165 return err; 168 166 } 169 - 170 - #if defined(CONFIG_DEBUG_FS) 171 - 172 - static int fw_trace_group_mask_show(struct seq_file *m, void *data) 173 - { 174 - struct pvr_device *pvr_dev = m->private; 175 - 176 - seq_printf(m, "%08x\n", pvr_dev->fw_dev.fw_trace.group_mask); 177 - 178 - return 0; 179 - } 180 - 181 - static int fw_trace_group_mask_open(struct inode *inode, struct file *file) 182 - { 183 - return single_open(file, fw_trace_group_mask_show, inode->i_private); 184 - } 185 - 186 - static ssize_t fw_trace_group_mask_write(struct file *file, const char __user *ubuf, size_t len, 187 - loff_t *offp) 188 - { 189 - struct seq_file *m = file->private_data; 190 - struct pvr_device *pvr_dev = m->private; 191 - u32 new_group_mask; 192 - int err; 193 - 194 - err = kstrtouint_from_user(ubuf, len, 0, &new_group_mask); 195 - if (err) 196 - return err; 197 - 198 - err = update_logtype(pvr_dev, new_group_mask); 199 - if (err) 200 - return err; 201 - 202 - pvr_dev->fw_dev.fw_trace.group_mask = new_group_mask; 203 - 204 - return (ssize_t)len; 205 - } 206 - 207 - static const struct file_operations pvr_fw_trace_group_mask_fops = { 208 - .owner = THIS_MODULE, 209 - .open = fw_trace_group_mask_open, 210 - .read = seq_read, 211 - .write = fw_trace_group_mask_write, 212 - .llseek = default_llseek, 213 - .release = single_release, 214 - }; 215 167 216 168 struct pvr_fw_trace_seq_data { 217 169 /** @buffer: Pointer to copy of trace data. */
+1
drivers/gpu/drm/imagination/pvr_hwrt.h
··· 64 64 /** @common_fw_obj: FW object representing common FW-side structure. */ 65 65 struct pvr_fw_object *common_fw_obj; 66 66 67 + /** @common: Common HWRT data. */ 67 68 struct rogue_fwif_hwrtdata_common common; 68 69 69 70 /** @data: HWRT data structures belonging to this set. */
+1 -3
drivers/gpu/drm/imagination/pvr_job.c
··· 378 378 379 379 /** 380 380 * prepare_job_syncs_for_each() - Prepare all sync objects for an array of jobs. 381 - * @file: PowerVR file. 381 + * @pvr_file: PowerVR file. 382 382 * @job_data: Array of precreated jobs and their sync_ops. 383 383 * @job_count: Number of jobs. 384 384 * @signal_array: xarray to receive signal sync objects. ··· 696 696 * @pvr_dev: Target PowerVR device. 697 697 * @pvr_file: Pointer to PowerVR file structure. 698 698 * @args: Ioctl args. 699 - * @job_count: Number of jobs in @jobs_args. On error this will be updated 700 - * with the index into @jobs_args where the error occurred. 701 699 * 702 700 * This initial implementation is entirely synchronous; on return the GPU will 703 701 * be idle. This will not be the case for future implementations.
+2 -1
drivers/gpu/drm/imagination/pvr_mmu.c
··· 335 335 336 336 /** 337 337 * pvr_mmu_backing_page_sync() - Flush a MMU backing page from the CPU to the 338 - * device. 338 + * device. 339 339 * @page: Target backing page. 340 + * @flags: MMU flush flags. Must be one of %PVR_MMU_SYNC_LEVEL_*_FLAGS. 340 341 * 341 342 * .. caution:: 342 343 *
+1 -1
drivers/gpu/drm/imagination/pvr_queue.c
··· 1292 1292 goto err_release_ufo; 1293 1293 1294 1294 err = drm_sched_entity_init(&queue->entity, 1295 - DRM_SCHED_PRIORITY_MIN, 1295 + DRM_SCHED_PRIORITY_KERNEL, 1296 1296 &sched, 1, &ctx->faulty); 1297 1297 if (err) 1298 1298 goto err_sched_fini;
+2 -2
drivers/gpu/drm/imagination/pvr_queue.h
··· 50 50 */ 51 51 struct pvr_job *job; 52 52 53 - /** @lock: Lock protecting access to the job object. */ 53 + /** @job_lock: Lock protecting access to the job object. */ 54 54 struct mutex job_lock; 55 55 }; 56 56 ··· 114 114 } timeline_ufo; 115 115 116 116 /** 117 - * last_queued_job_scheduled_fence: The scheduled fence of the last 117 + * @last_queued_job_scheduled_fence: The scheduled fence of the last 118 118 * job queued to this queue. 119 119 * 120 120 * We use it to insert frag -> geom dependencies when issuing combined
+2 -2
drivers/gpu/drm/imagination/pvr_rogue_fwif_sf.h
··· 497 497 { ROGUE_FW_LOG_CREATESFID(213, ROGUE_FW_GROUP_MAIN, 1), 498 498 "Safety Watchdog threshold period set to 0x%x clock cycles" }, 499 499 { ROGUE_FW_LOG_CREATESFID(214, ROGUE_FW_GROUP_MAIN, 0), 500 - "MTS Safety Event trigged by the safety watchdog." }, 500 + "MTS Safety Event triggered by the safety watchdog." }, 501 501 { ROGUE_FW_LOG_CREATESFID(215, ROGUE_FW_GROUP_MAIN, 3), 502 502 "DM%d USC tasks range limit 0 - %d, stride %d" }, 503 503 { ROGUE_FW_LOG_CREATESFID(216, ROGUE_FW_GROUP_MAIN, 1), ··· 1114 1114 { ROGUE_FW_LOG_CREATESFID(39, ROGUE_FW_GROUP_SPM, 2), 1115 1115 "3DMemFree matches freelist 0x%08x (FL type = %u)" }, 1116 1116 { ROGUE_FW_LOG_CREATESFID(40, ROGUE_FW_GROUP_SPM, 0), 1117 - "Raise the 3DMemFreeDedected flag" }, 1117 + "Raise the 3DMemFreeDetected flag" }, 1118 1118 { ROGUE_FW_LOG_CREATESFID(41, ROGUE_FW_GROUP_SPM, 1), 1119 1119 "Wait for pending grow on Freelist 0x%08x" }, 1120 1120 { ROGUE_FW_LOG_CREATESFID(42, ROGUE_FW_GROUP_SPM, 1),
+58 -73
drivers/gpu/drm/imagination/pvr_vm.c
··· 42 42 /** @mmu_ctx: The context for binding to physical memory. */ 43 43 struct pvr_mmu_context *mmu_ctx; 44 44 45 - /** @gpuva_mgr: GPUVA manager object associated with this context. */ 45 + /** @gpuvm_mgr: GPUVM object associated with this context. */ 46 46 struct drm_gpuvm gpuvm_mgr; 47 47 48 48 /** @lock: Global lock on this VM. */ ··· 63 63 */ 64 64 struct drm_gem_object dummy_gem; 65 65 }; 66 + 67 + static inline 68 + struct pvr_vm_context *to_pvr_vm_context(struct drm_gpuvm *gpuvm) 69 + { 70 + return container_of(gpuvm, struct pvr_vm_context, gpuvm_mgr); 71 + } 66 72 67 73 struct pvr_vm_context *pvr_vm_context_get(struct pvr_vm_context *vm_ctx) 68 74 { ··· 113 107 /** @base: The wrapped drm_gpuva object. */ 114 108 struct drm_gpuva base; 115 109 }; 116 - 117 - static __always_inline 118 - struct pvr_vm_gpuva *to_pvr_vm_gpuva(struct drm_gpuva *gpuva) 119 - { 120 - return container_of(gpuva, struct pvr_vm_gpuva, base); 121 - } 122 110 123 111 enum pvr_vm_bind_type { 124 112 PVR_VM_BIND_TYPE_MAP, ··· 224 224 struct pvr_gem_object *pvr_obj, u64 offset, 225 225 u64 device_addr, u64 size) 226 226 { 227 + struct drm_gem_object *obj = gem_from_pvr_gem(pvr_obj); 227 228 const bool is_user = vm_ctx == vm_ctx->pvr_dev->kernel_vm_ctx; 228 229 const u64 pvr_obj_size = pvr_gem_object_size(pvr_obj); 229 230 struct sg_table *sgt; ··· 239 238 return -EINVAL; 240 239 } 241 240 242 - if (!pvr_device_addr_and_size_are_valid(device_addr, size) || 241 + if (!pvr_device_addr_and_size_are_valid(vm_ctx, device_addr, size) || 243 242 offset & ~PAGE_MASK || size & ~PAGE_MASK || 244 243 offset >= pvr_obj_size || offset_plus_size > pvr_obj_size) 245 244 return -EINVAL; 246 245 247 246 bind_op->type = PVR_VM_BIND_TYPE_MAP; 248 247 249 - bind_op->gpuvm_bo = drm_gpuvm_bo_create(&vm_ctx->gpuvm_mgr, 250 - gem_from_pvr_gem(pvr_obj)); 251 - if (!bind_op->gpuvm_bo) 252 - return -ENOMEM; 248 + dma_resv_lock(obj->resv, NULL); 249 + bind_op->gpuvm_bo = drm_gpuvm_bo_obtain(&vm_ctx->gpuvm_mgr, obj); 250 + dma_resv_unlock(obj->resv); 251 + if (IS_ERR(bind_op->gpuvm_bo)) 252 + return PTR_ERR(bind_op->gpuvm_bo); 253 253 254 254 bind_op->new_va = kzalloc(sizeof(*bind_op->new_va), GFP_KERNEL); 255 255 bind_op->prev_va = kzalloc(sizeof(*bind_op->prev_va), GFP_KERNEL); ··· 295 293 { 296 294 int err; 297 295 298 - if (!pvr_device_addr_and_size_are_valid(device_addr, size)) 296 + if (!pvr_device_addr_and_size_are_valid(vm_ctx, device_addr, size)) 299 297 return -EINVAL; 300 298 301 299 bind_op->type = PVR_VM_BIND_TYPE_UNMAP; ··· 325 323 pvr_vm_bind_op_fini(bind_op); 326 324 327 325 return err; 328 - } 329 - 330 - static int 331 - pvr_vm_bind_op_lock_resvs(struct drm_exec *exec, struct pvr_vm_bind_op *bind_op) 332 - { 333 - drm_exec_until_all_locked(exec) { 334 - struct drm_gem_object *r_obj = &bind_op->vm_ctx->dummy_gem; 335 - struct drm_gpuvm *gpuvm = &bind_op->vm_ctx->gpuvm_mgr; 336 - struct pvr_gem_object *pvr_obj = bind_op->pvr_obj; 337 - struct drm_gpuvm_bo *gpuvm_bo; 338 - 339 - /* Acquire lock on the vm_context's reserve object. */ 340 - int err = drm_exec_lock_obj(exec, r_obj); 341 - 342 - drm_exec_retry_on_contention(exec); 343 - if (err) 344 - return err; 345 - 346 - /* Acquire lock on all BOs in the context. */ 347 - list_for_each_entry(gpuvm_bo, &gpuvm->extobj.list, 348 - list.entry.extobj) { 349 - err = drm_exec_lock_obj(exec, gpuvm_bo->obj); 350 - 351 - drm_exec_retry_on_contention(exec); 352 - if (err) 353 - return err; 354 - } 355 - 356 - /* Unmap operations don't have an object to lock. */ 357 - if (!pvr_obj) 358 - break; 359 - 360 - /* Acquire lock on the GEM being mapped. */ 361 - err = drm_exec_lock_obj(exec, 362 - gem_from_pvr_gem(bind_op->pvr_obj)); 363 - 364 - drm_exec_retry_on_contention(exec); 365 - if (err) 366 - return err; 367 - } 368 - 369 - return 0; 370 326 } 371 327 372 328 /** ··· 463 503 /** 464 504 * pvr_device_addr_and_size_are_valid() - Tests whether a device-virtual 465 505 * address and associated size are both valid. 506 + * @vm_ctx: Target VM context. 466 507 * @device_addr: Virtual device address to test. 467 508 * @size: Size of the range based at @device_addr to test. 468 509 * ··· 482 521 * * %false otherwise. 483 522 */ 484 523 bool 485 - pvr_device_addr_and_size_are_valid(u64 device_addr, u64 size) 524 + pvr_device_addr_and_size_are_valid(struct pvr_vm_context *vm_ctx, 525 + u64 device_addr, u64 size) 486 526 { 487 527 return pvr_device_addr_is_valid(device_addr) && 528 + drm_gpuvm_range_valid(&vm_ctx->gpuvm_mgr, device_addr, size) && 488 529 size != 0 && (size & ~PVR_DEVICE_PAGE_MASK) == 0 && 489 530 (device_addr + size <= PVR_PAGE_TABLE_ADDR_SPACE_SIZE); 490 531 } 491 532 492 - void pvr_gpuvm_free(struct drm_gpuvm *gpuvm) 533 + static void pvr_gpuvm_free(struct drm_gpuvm *gpuvm) 493 534 { 494 - 535 + kfree(to_pvr_vm_context(gpuvm)); 495 536 } 496 537 497 538 static const struct drm_gpuvm_ops pvr_vm_gpuva_ops = { ··· 613 650 WARN_ON(pvr_vm_unmap(vm_ctx, vm_ctx->gpuvm_mgr.mm_start, 614 651 vm_ctx->gpuvm_mgr.mm_range)); 615 652 616 - drm_gpuvm_put(&vm_ctx->gpuvm_mgr); 617 653 pvr_mmu_context_destroy(vm_ctx->mmu_ctx); 618 654 drm_gem_private_object_fini(&vm_ctx->dummy_gem); 619 655 mutex_destroy(&vm_ctx->lock); 620 656 621 - kfree(vm_ctx); 657 + drm_gpuvm_put(&vm_ctx->gpuvm_mgr); 622 658 } 623 659 624 660 /** ··· 683 721 } 684 722 } 685 723 724 + static int 725 + pvr_vm_lock_extra(struct drm_gpuvm_exec *vm_exec) 726 + { 727 + struct pvr_vm_bind_op *bind_op = vm_exec->extra.priv; 728 + struct pvr_gem_object *pvr_obj = bind_op->pvr_obj; 729 + 730 + /* Unmap operations don't have an object to lock. */ 731 + if (!pvr_obj) 732 + return 0; 733 + 734 + /* Acquire lock on the GEM being mapped. */ 735 + return drm_exec_lock_obj(&vm_exec->exec, gem_from_pvr_gem(pvr_obj)); 736 + } 737 + 686 738 /** 687 739 * pvr_vm_map() - Map a section of physical memory into a section of 688 740 * device-virtual memory. ··· 724 748 u64 pvr_obj_offset, u64 device_addr, u64 size) 725 749 { 726 750 struct pvr_vm_bind_op bind_op = {0}; 727 - struct drm_exec exec; 751 + struct drm_gpuvm_exec vm_exec = { 752 + .vm = &vm_ctx->gpuvm_mgr, 753 + .flags = DRM_EXEC_INTERRUPTIBLE_WAIT | 754 + DRM_EXEC_IGNORE_DUPLICATES, 755 + .extra = { 756 + .fn = pvr_vm_lock_extra, 757 + .priv = &bind_op, 758 + }, 759 + }; 728 760 729 761 int err = pvr_vm_bind_op_map_init(&bind_op, vm_ctx, pvr_obj, 730 762 pvr_obj_offset, device_addr, ··· 741 757 if (err) 742 758 return err; 743 759 744 - drm_exec_init(&exec, 745 - DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES); 746 - 747 760 pvr_gem_object_get(pvr_obj); 748 761 749 - err = pvr_vm_bind_op_lock_resvs(&exec, &bind_op); 762 + err = drm_gpuvm_exec_lock(&vm_exec); 750 763 if (err) 751 764 goto err_cleanup; 752 765 753 766 err = pvr_vm_bind_op_exec(&bind_op); 754 767 755 - drm_exec_fini(&exec); 768 + drm_gpuvm_exec_unlock(&vm_exec); 756 769 757 770 err_cleanup: 758 771 pvr_vm_bind_op_fini(&bind_op); ··· 775 794 pvr_vm_unmap(struct pvr_vm_context *vm_ctx, u64 device_addr, u64 size) 776 795 { 777 796 struct pvr_vm_bind_op bind_op = {0}; 778 - struct drm_exec exec; 797 + struct drm_gpuvm_exec vm_exec = { 798 + .vm = &vm_ctx->gpuvm_mgr, 799 + .flags = DRM_EXEC_INTERRUPTIBLE_WAIT | 800 + DRM_EXEC_IGNORE_DUPLICATES, 801 + .extra = { 802 + .fn = pvr_vm_lock_extra, 803 + .priv = &bind_op, 804 + }, 805 + }; 779 806 780 807 int err = pvr_vm_bind_op_unmap_init(&bind_op, vm_ctx, device_addr, 781 808 size); 782 - 783 809 if (err) 784 810 return err; 785 811 786 - drm_exec_init(&exec, 787 - DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES); 788 - 789 - err = pvr_vm_bind_op_lock_resvs(&exec, &bind_op); 812 + err = drm_gpuvm_exec_lock(&vm_exec); 790 813 if (err) 791 814 goto err_cleanup; 792 815 793 816 err = pvr_vm_bind_op_exec(&bind_op); 794 817 795 - drm_exec_fini(&exec); 818 + drm_gpuvm_exec_unlock(&vm_exec); 796 819 797 820 err_cleanup: 798 821 pvr_vm_bind_op_fini(&bind_op);
+2 -1
drivers/gpu/drm/imagination/pvr_vm.h
··· 29 29 /* Functions defined in pvr_vm.c */ 30 30 31 31 bool pvr_device_addr_is_valid(u64 device_addr); 32 - bool pvr_device_addr_and_size_are_valid(u64 device_addr, u64 size); 32 + bool pvr_device_addr_and_size_are_valid(struct pvr_vm_context *vm_ctx, 33 + u64 device_addr, u64 size); 33 34 34 35 struct pvr_vm_context *pvr_vm_create_context(struct pvr_device *pvr_dev, 35 36 bool is_userspace_context);
+5 -6
drivers/gpu/drm/imagination/pvr_vm_mips.c
··· 57 57 PAGE_SIZE, DMA_TO_DEVICE); 58 58 if (dma_mapping_error(dev, mips_data->pt_dma_addr[page_nr])) { 59 59 err = -ENOMEM; 60 + __free_page(mips_data->pt_pages[page_nr]); 60 61 goto err_free_pages; 61 62 } 62 63 } ··· 80 79 return 0; 81 80 82 81 err_free_pages: 83 - for (; page_nr >= 0; page_nr--) { 84 - if (mips_data->pt_dma_addr[page_nr]) 85 - dma_unmap_page(from_pvr_device(pvr_dev)->dev, 86 - mips_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE); 82 + while (--page_nr >= 0) { 83 + dma_unmap_page(from_pvr_device(pvr_dev)->dev, 84 + mips_data->pt_dma_addr[page_nr], PAGE_SIZE, DMA_TO_DEVICE); 87 85 88 - if (mips_data->pt_pages[page_nr]) 89 - __free_page(mips_data->pt_pages[page_nr]); 86 + __free_page(mips_data->pt_pages[page_nr]); 90 87 } 91 88 92 89 return err;
+4 -5
drivers/gpu/drm/imx/ipuv3/imx-ldb.c
··· 12 12 #include <linux/mfd/syscon.h> 13 13 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> 14 14 #include <linux/module.h> 15 - #include <linux/of_device.h> 15 + #include <linux/of.h> 16 16 #include <linux/of_graph.h> 17 + #include <linux/platform_device.h> 18 + #include <linux/property.h> 17 19 #include <linux/regmap.h> 18 20 #include <linux/videodev2.h> 19 21 ··· 619 617 { 620 618 struct device *dev = &pdev->dev; 621 619 struct device_node *np = dev->of_node; 622 - const struct of_device_id *of_id = of_match_device(imx_ldb_dt_ids, dev); 623 620 struct device_node *child; 624 621 struct imx_ldb *imx_ldb; 625 622 int dual; ··· 639 638 regmap_write(imx_ldb->regmap, IOMUXC_GPR2, 0); 640 639 641 640 imx_ldb->dev = dev; 642 - 643 - if (of_id) 644 - imx_ldb->lvds_mux = of_id->data; 641 + imx_ldb->lvds_mux = device_get_match_data(dev); 645 642 646 643 dual = of_property_read_bool(np, "fsl,dual-channel"); 647 644 if (dual)
-9
drivers/gpu/drm/imx/lcdc/imx-lcdc.c
··· 342 342 .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, 343 343 }; 344 344 345 - static void imx_lcdc_release(struct drm_device *drm) 346 - { 347 - struct imx_lcdc *lcdc = imx_lcdc_from_drmdev(drm); 348 - 349 - drm_kms_helper_poll_fini(drm); 350 - kfree(lcdc); 351 - } 352 - 353 345 DEFINE_DRM_GEM_DMA_FOPS(imx_lcdc_drm_fops); 354 346 355 347 static struct drm_driver imx_lcdc_drm_driver = { 356 348 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, 357 349 .fops = &imx_lcdc_drm_fops, 358 350 DRM_GEM_DMA_DRIVER_OPS_VMAP, 359 - .release = imx_lcdc_release, 360 351 .name = "imx-lcdc", 361 352 .desc = "i.MX LCDC driver", 362 353 .date = "20200716",
+1
drivers/gpu/drm/loongson/Kconfig
··· 3 3 config DRM_LOONGSON 4 4 tristate "DRM support for Loongson Graphics" 5 5 depends on DRM && PCI && MMU 6 + depends on LOONGARCH || MIPS || COMPILE_TEST 6 7 select DRM_KMS_HELPER 7 8 select DRM_TTM 8 9 select I2C
-1
drivers/gpu/drm/loongson/lsdc_plane.c
··· 9 9 #include <drm/drm_atomic_helper.h> 10 10 #include <drm/drm_framebuffer.h> 11 11 #include <drm/drm_gem_atomic_helper.h> 12 - #include <drm/drm_plane_helper.h> 13 12 14 13 #include "lsdc_drv.h" 15 14 #include "lsdc_regs.h"
+1 -1
drivers/gpu/drm/msm/msm_gpu.h
··· 347 347 * DRM_SCHED_PRIORITY_KERNEL priority level is treated specially in some 348 348 * cases, so we don't use it (no need for kernel generated jobs). 349 349 */ 350 - #define NR_SCHED_PRIORITIES (1 + DRM_SCHED_PRIORITY_HIGH - DRM_SCHED_PRIORITY_MIN) 350 + #define NR_SCHED_PRIORITIES (1 + DRM_SCHED_PRIORITY_LOW - DRM_SCHED_PRIORITY_HIGH) 351 351 352 352 /** 353 353 * struct msm_file_private - per-drm_file context
+3 -7
drivers/gpu/drm/mxsfb/mxsfb_drv.c
··· 11 11 #include <linux/clk.h> 12 12 #include <linux/dma-mapping.h> 13 13 #include <linux/io.h> 14 + #include <linux/mod_devicetable.h> 14 15 #include <linux/module.h> 15 - #include <linux/of_device.h> 16 16 #include <linux/platform_device.h> 17 + #include <linux/property.h> 17 18 #include <linux/pm_runtime.h> 18 19 19 20 #include <drm/drm_atomic_helper.h> ··· 347 346 static int mxsfb_probe(struct platform_device *pdev) 348 347 { 349 348 struct drm_device *drm; 350 - const struct of_device_id *of_id = 351 - of_match_device(mxsfb_dt_ids, &pdev->dev); 352 349 int ret; 353 - 354 - if (!pdev->dev.of_node) 355 - return -ENODEV; 356 350 357 351 drm = drm_dev_alloc(&mxsfb_driver, &pdev->dev); 358 352 if (IS_ERR(drm)) 359 353 return PTR_ERR(drm); 360 354 361 - ret = mxsfb_load(drm, of_id->data); 355 + ret = mxsfb_load(drm, device_get_match_data(&pdev->dev)); 362 356 if (ret) 363 357 goto err_free; 364 358
+6 -13
drivers/gpu/drm/nouveau/nouveau_abi16.c
··· 127 127 { 128 128 struct nouveau_abi16_ntfy *ntfy, *temp; 129 129 130 - /* When a client exits without waiting for it's queued up jobs to 131 - * finish it might happen that we fault the channel. This is due to 132 - * drm_file_free() calling drm_gem_release() before the postclose() 133 - * callback. Hence, we can't tear down this scheduler entity before 134 - * uvmm mappings are unmapped. Currently, we can't detect this case. 135 - * 136 - * However, this should be rare and harmless, since the channel isn't 137 - * needed anymore. 138 - */ 139 - nouveau_sched_entity_fini(&chan->sched_entity); 130 + /* Cancel all jobs from the entity's queue. */ 131 + drm_sched_entity_fini(&chan->sched.entity); 140 132 141 - /* wait for all activity to stop before cleaning up */ 142 133 if (chan->chan) 143 134 nouveau_channel_idle(chan->chan); 135 + 136 + nouveau_sched_fini(&chan->sched); 144 137 145 138 /* cleanup notifier state */ 146 139 list_for_each_entry_safe(ntfy, temp, &chan->notifiers, head) { ··· 337 344 if (ret) 338 345 goto done; 339 346 340 - ret = nouveau_sched_entity_init(&chan->sched_entity, &drm->sched, 341 - drm->sched_wq); 347 + ret = nouveau_sched_init(&chan->sched, drm, drm->sched_wq, 348 + chan->chan->dma.ib_max); 342 349 if (ret) 343 350 goto done; 344 351
+1 -1
drivers/gpu/drm/nouveau/nouveau_abi16.h
··· 26 26 struct nouveau_bo *ntfy; 27 27 struct nouveau_vma *ntfy_vma; 28 28 struct nvkm_mm heap; 29 - struct nouveau_sched_entity sched_entity; 29 + struct nouveau_sched sched; 30 30 }; 31 31 32 32 struct nouveau_abi16 {
+3 -1
drivers/gpu/drm/nouveau/nouveau_bo.c
··· 1061 1061 { 1062 1062 struct nouveau_drm *drm = nouveau_bdev(bo->bdev); 1063 1063 struct nouveau_bo *nvbo = nouveau_bo(bo); 1064 + struct drm_gem_object *obj = &bo->base; 1064 1065 struct ttm_resource *old_reg = bo->resource; 1065 1066 struct nouveau_drm_tile *new_tile = NULL; 1066 1067 int ret = 0; 1067 - 1068 1068 1069 1069 if (new_reg->mem_type == TTM_PL_TT) { 1070 1070 ret = nouveau_ttm_tt_bind(bo->bdev, bo->ttm, new_reg); ··· 1072 1072 return ret; 1073 1073 } 1074 1074 1075 + drm_gpuvm_bo_gem_evict(obj, evict); 1075 1076 nouveau_bo_move_ntfy(bo, new_reg); 1076 1077 ret = ttm_bo_wait_ctx(bo, ctx); 1077 1078 if (ret) ··· 1137 1136 out_ntfy: 1138 1137 if (ret) { 1139 1138 nouveau_bo_move_ntfy(bo, bo->resource); 1139 + drm_gpuvm_bo_gem_evict(obj, !evict); 1140 1140 } 1141 1141 return ret; 1142 1142 }
+21 -10
drivers/gpu/drm/nouveau/nouveau_drm.c
··· 201 201 WARN_ON(!list_empty(&cli->worker)); 202 202 203 203 usif_client_fini(cli); 204 + nouveau_sched_fini(&cli->sched); 204 205 if (uvmm) 205 206 nouveau_uvmm_fini(uvmm); 206 - nouveau_sched_entity_fini(&cli->sched_entity); 207 207 nouveau_vmm_fini(&cli->svm); 208 208 nouveau_vmm_fini(&cli->vmm); 209 209 nvif_mmu_dtor(&cli->mmu); ··· 310 310 311 311 cli->mem = &mems[ret]; 312 312 313 - ret = nouveau_sched_entity_init(&cli->sched_entity, &drm->sched, 314 - drm->sched_wq); 313 + /* Don't pass in the (shared) sched_wq in order to let 314 + * nouveau_sched_init() create a dedicated one for VM_BIND jobs. 315 + * 316 + * This is required to ensure that for VM_BIND jobs free_job() work and 317 + * run_job() work can always run concurrently and hence, free_job() work 318 + * can never stall run_job() work. For EXEC jobs we don't have this 319 + * requirement, since EXEC job's free_job() does not require to take any 320 + * locks which indirectly or directly are held for allocations 321 + * elsewhere. 322 + */ 323 + ret = nouveau_sched_init(&cli->sched, drm, NULL, 1); 315 324 if (ret) 316 325 goto done; 317 326 ··· 591 582 nvif_parent_ctor(&nouveau_parent, &drm->parent); 592 583 drm->master.base.object.parent = &drm->parent; 593 584 594 - ret = nouveau_sched_init(drm); 595 - if (ret) 585 + drm->sched_wq = alloc_workqueue("nouveau_sched_wq_shared", 0, 586 + WQ_MAX_ACTIVE); 587 + if (!drm->sched_wq) { 588 + ret = -ENOMEM; 596 589 goto fail_alloc; 590 + } 597 591 598 592 ret = nouveau_cli_init(drm, "DRM-master", &drm->master); 599 593 if (ret) 600 - goto fail_sched; 594 + goto fail_wq; 601 595 602 596 ret = nouveau_cli_init(drm, "DRM", &drm->client); 603 597 if (ret) ··· 670 658 nouveau_cli_fini(&drm->client); 671 659 fail_master: 672 660 nouveau_cli_fini(&drm->master); 673 - fail_sched: 674 - nouveau_sched_fini(drm); 661 + fail_wq: 662 + destroy_workqueue(drm->sched_wq); 675 663 fail_alloc: 676 664 nvif_parent_dtor(&drm->parent); 677 665 kfree(drm); ··· 723 711 } 724 712 mutex_unlock(&drm->clients_lock); 725 713 726 - nouveau_sched_fini(drm); 727 - 728 714 nouveau_cli_fini(&drm->client); 729 715 nouveau_cli_fini(&drm->master); 716 + destroy_workqueue(drm->sched_wq); 730 717 nvif_parent_dtor(&drm->parent); 731 718 mutex_destroy(&drm->clients_lock); 732 719 kfree(drm);
+4 -5
drivers/gpu/drm/nouveau/nouveau_drv.h
··· 98 98 bool disabled; 99 99 } uvmm; 100 100 101 - struct nouveau_sched_entity sched_entity; 101 + struct nouveau_sched sched; 102 102 103 103 const struct nvif_mclass *mem; 104 104 ··· 258 258 u64 context_base; 259 259 } *runl; 260 260 261 + /* Workqueue used for channel schedulers. */ 262 + struct workqueue_struct *sched_wq; 263 + 261 264 /* context for accelerated drm-internal operations */ 262 265 struct nouveau_channel *cechan; 263 266 struct nouveau_channel *channel; ··· 301 298 struct mutex lock; 302 299 bool component_registered; 303 300 } audio; 304 - 305 - struct drm_gpu_scheduler sched; 306 - struct workqueue_struct *sched_wq; 307 - 308 301 }; 309 302 310 303 static inline struct nouveau_drm *
+21 -47
drivers/gpu/drm/nouveau/nouveau_exec.c
··· 1 1 // SPDX-License-Identifier: MIT 2 2 3 - #include <drm/drm_exec.h> 4 - 5 3 #include "nouveau_drv.h" 6 4 #include "nouveau_gem.h" 7 5 #include "nouveau_mem.h" ··· 84 86 */ 85 87 86 88 static int 87 - nouveau_exec_job_submit(struct nouveau_job *job) 89 + nouveau_exec_job_submit(struct nouveau_job *job, 90 + struct drm_gpuvm_exec *vme) 88 91 { 89 92 struct nouveau_exec_job *exec_job = to_nouveau_exec_job(job); 90 93 struct nouveau_cli *cli = job->cli; 91 94 struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(cli); 92 - struct drm_exec *exec = &job->exec; 93 - struct drm_gem_object *obj; 94 - unsigned long index; 95 95 int ret; 96 96 97 97 /* Create a new fence, but do not emit yet. */ ··· 98 102 return ret; 99 103 100 104 nouveau_uvmm_lock(uvmm); 101 - drm_exec_init(exec, DRM_EXEC_INTERRUPTIBLE_WAIT | 102 - DRM_EXEC_IGNORE_DUPLICATES); 103 - drm_exec_until_all_locked(exec) { 104 - struct drm_gpuva *va; 105 - 106 - drm_gpuvm_for_each_va(va, &uvmm->base) { 107 - if (unlikely(va == &uvmm->base.kernel_alloc_node)) 108 - continue; 109 - 110 - ret = drm_exec_prepare_obj(exec, va->gem.obj, 1); 111 - drm_exec_retry_on_contention(exec); 112 - if (ret) 113 - goto err_uvmm_unlock; 114 - } 105 + ret = drm_gpuvm_exec_lock(vme); 106 + if (ret) { 107 + nouveau_uvmm_unlock(uvmm); 108 + return ret; 115 109 } 116 110 nouveau_uvmm_unlock(uvmm); 117 111 118 - drm_exec_for_each_locked_object(exec, index, obj) { 119 - struct nouveau_bo *nvbo = nouveau_gem_object(obj); 120 - 121 - ret = nouveau_bo_validate(nvbo, true, false); 122 - if (ret) 123 - goto err_exec_fini; 112 + ret = drm_gpuvm_exec_validate(vme); 113 + if (ret) { 114 + drm_gpuvm_exec_unlock(vme); 115 + return ret; 124 116 } 125 117 126 118 return 0; 127 - 128 - err_uvmm_unlock: 129 - nouveau_uvmm_unlock(uvmm); 130 - err_exec_fini: 131 - drm_exec_fini(exec); 132 - return ret; 133 - 134 119 } 135 120 136 121 static void 137 - nouveau_exec_job_armed_submit(struct nouveau_job *job) 122 + nouveau_exec_job_armed_submit(struct nouveau_job *job, 123 + struct drm_gpuvm_exec *vme) 138 124 { 139 - struct drm_exec *exec = &job->exec; 140 - struct drm_gem_object *obj; 141 - unsigned long index; 142 - 143 - drm_exec_for_each_locked_object(exec, index, obj) 144 - dma_resv_add_fence(obj->resv, job->done_fence, job->resv_usage); 145 - 146 - drm_exec_fini(exec); 125 + drm_gpuvm_exec_resv_add_fence(vme, job->done_fence, 126 + job->resv_usage, job->resv_usage); 127 + drm_gpuvm_exec_unlock(vme); 147 128 } 148 129 149 130 static struct dma_fence * ··· 165 192 { 166 193 struct nouveau_exec_job *exec_job = to_nouveau_exec_job(job); 167 194 195 + nouveau_job_done(job); 168 196 nouveau_job_free(job); 169 197 170 198 kfree(exec_job->fence); ··· 184 210 185 211 NV_PRINTK(warn, job->cli, "job timeout, channel %d killed!\n", 186 212 chan->chid); 187 - 188 - nouveau_sched_entity_fini(job->entity); 189 213 190 214 return DRM_GPU_SCHED_STAT_NOMINAL; 191 215 } ··· 231 259 } 232 260 } 233 261 262 + args.file_priv = __args->file_priv; 234 263 job->chan = __args->chan; 235 264 236 - args.sched_entity = __args->sched_entity; 237 - args.file_priv = __args->file_priv; 265 + args.sched = __args->sched; 266 + /* Plus one to account for the HW fence. */ 267 + args.credits = job->push.count + 1; 238 268 239 269 args.in_sync.count = __args->in_sync.count; 240 270 args.in_sync.s = __args->in_sync.s; ··· 389 415 if (ret) 390 416 goto out; 391 417 392 - args.sched_entity = &chan16->sched_entity; 418 + args.sched = &chan16->sched; 393 419 args.file_priv = file_priv; 394 420 args.chan = chan; 395 421
+1 -5
drivers/gpu/drm/nouveau/nouveau_exec.h
··· 3 3 #ifndef __NOUVEAU_EXEC_H__ 4 4 #define __NOUVEAU_EXEC_H__ 5 5 6 - #include <drm/drm_exec.h> 7 - 8 6 #include "nouveau_drv.h" 9 7 #include "nouveau_sched.h" 10 8 11 9 struct nouveau_exec_job_args { 12 10 struct drm_file *file_priv; 13 - struct nouveau_sched_entity *sched_entity; 14 - 15 - struct drm_exec exec; 11 + struct nouveau_sched *sched; 16 12 struct nouveau_channel *chan; 17 13 18 14 struct {
+116 -91
drivers/gpu/drm/nouveau/nouveau_sched.c
··· 12 12 #include "nouveau_abi16.h" 13 13 #include "nouveau_sched.h" 14 14 15 - /* FIXME 16 - * 17 - * We want to make sure that jobs currently executing can't be deferred by 18 - * other jobs competing for the hardware. Otherwise we might end up with job 19 - * timeouts just because of too many clients submitting too many jobs. We don't 20 - * want jobs to time out because of system load, but because of the job being 21 - * too bulky. 22 - * 23 - * For now allow for up to 16 concurrent jobs in flight until we know how many 24 - * rings the hardware can process in parallel. 25 - */ 26 - #define NOUVEAU_SCHED_HW_SUBMISSIONS 16 27 15 #define NOUVEAU_SCHED_JOB_TIMEOUT_MS 10000 16 + 17 + /* Starts at 0, since the DRM scheduler interprets those parameters as (initial) 18 + * index to the run-queue array. 19 + */ 20 + enum nouveau_sched_priority { 21 + NOUVEAU_SCHED_PRIORITY_SINGLE = DRM_SCHED_PRIORITY_KERNEL, 22 + NOUVEAU_SCHED_PRIORITY_COUNT, 23 + }; 28 24 29 25 int 30 26 nouveau_job_init(struct nouveau_job *job, 31 27 struct nouveau_job_args *args) 32 28 { 33 - struct nouveau_sched_entity *entity = args->sched_entity; 29 + struct nouveau_sched *sched = args->sched; 34 30 int ret; 31 + 32 + INIT_LIST_HEAD(&job->entry); 35 33 36 34 job->file_priv = args->file_priv; 37 35 job->cli = nouveau_cli(args->file_priv); 38 - job->entity = entity; 36 + job->sched = sched; 39 37 40 38 job->sync = args->sync; 41 39 job->resv_usage = args->resv_usage; ··· 84 86 ret = -ENOMEM; 85 87 goto err_free_objs; 86 88 } 87 - 88 89 } 89 90 90 - ret = drm_sched_job_init(&job->base, &entity->base, 1, NULL); 91 + ret = drm_sched_job_init(&job->base, &sched->entity, 92 + args->credits, NULL); 91 93 if (ret) 92 94 goto err_free_chains; 93 95 ··· 107 109 } 108 110 109 111 void 112 + nouveau_job_fini(struct nouveau_job *job) 113 + { 114 + dma_fence_put(job->done_fence); 115 + drm_sched_job_cleanup(&job->base); 116 + 117 + job->ops->free(job); 118 + } 119 + 120 + void 121 + nouveau_job_done(struct nouveau_job *job) 122 + { 123 + struct nouveau_sched *sched = job->sched; 124 + 125 + spin_lock(&sched->job.list.lock); 126 + list_del(&job->entry); 127 + spin_unlock(&sched->job.list.lock); 128 + 129 + wake_up(&sched->job.wq); 130 + } 131 + 132 + void 110 133 nouveau_job_free(struct nouveau_job *job) 111 134 { 112 135 kfree(job->in_sync.data); 113 136 kfree(job->out_sync.data); 114 137 kfree(job->out_sync.objs); 115 138 kfree(job->out_sync.chains); 116 - } 117 - 118 - void nouveau_job_fini(struct nouveau_job *job) 119 - { 120 - dma_fence_put(job->done_fence); 121 - drm_sched_job_cleanup(&job->base); 122 - job->ops->free(job); 123 139 } 124 140 125 141 static int ··· 273 261 int 274 262 nouveau_job_submit(struct nouveau_job *job) 275 263 { 276 - struct nouveau_sched_entity *entity = to_nouveau_sched_entity(job->base.entity); 264 + struct nouveau_sched *sched = job->sched; 277 265 struct dma_fence *done_fence = NULL; 266 + struct drm_gpuvm_exec vm_exec = { 267 + .vm = &nouveau_cli_uvmm(job->cli)->base, 268 + .flags = DRM_EXEC_IGNORE_DUPLICATES, 269 + .num_fences = 1, 270 + }; 278 271 int ret; 279 272 280 273 ret = nouveau_job_add_deps(job); ··· 293 276 /* Make sure the job appears on the sched_entity's queue in the same 294 277 * order as it was submitted. 295 278 */ 296 - mutex_lock(&entity->mutex); 279 + mutex_lock(&sched->mutex); 297 280 298 281 /* Guarantee we won't fail after the submit() callback returned 299 282 * successfully. 300 283 */ 301 284 if (job->ops->submit) { 302 - ret = job->ops->submit(job); 285 + ret = job->ops->submit(job, &vm_exec); 303 286 if (ret) 304 287 goto err_cleanup; 305 288 } 289 + 290 + /* Submit was successful; add the job to the schedulers job list. */ 291 + spin_lock(&sched->job.list.lock); 292 + list_add(&job->entry, &sched->job.list.head); 293 + spin_unlock(&sched->job.list.lock); 306 294 307 295 drm_sched_job_arm(&job->base); 308 296 job->done_fence = dma_fence_get(&job->base.s_fence->finished); 309 297 if (job->sync) 310 298 done_fence = dma_fence_get(job->done_fence); 311 299 312 - /* If a sched job depends on a dma-fence from a job from the same GPU 313 - * scheduler instance, but a different scheduler entity, the GPU 314 - * scheduler does only wait for the particular job to be scheduled, 315 - * rather than for the job to fully complete. This is due to the GPU 316 - * scheduler assuming that there is a scheduler instance per ring. 317 - * However, the current implementation, in order to avoid arbitrary 318 - * amounts of kthreads, has a single scheduler instance while scheduler 319 - * entities represent rings. 320 - * 321 - * As a workaround, set the DRM_SCHED_FENCE_DONT_PIPELINE for all 322 - * out-fences in order to force the scheduler to wait for full job 323 - * completion for dependent jobs from different entities and same 324 - * scheduler instance. 325 - * 326 - * There is some work in progress [1] to address the issues of firmware 327 - * schedulers; once it is in-tree the scheduler topology in Nouveau 328 - * should be re-worked accordingly. 329 - * 330 - * [1] https://lore.kernel.org/dri-devel/20230801205103.627779-1-matthew.brost@intel.com/ 331 - */ 332 - set_bit(DRM_SCHED_FENCE_DONT_PIPELINE, &job->done_fence->flags); 333 - 334 300 if (job->ops->armed_submit) 335 - job->ops->armed_submit(job); 301 + job->ops->armed_submit(job, &vm_exec); 336 302 337 303 nouveau_job_fence_attach(job); 338 304 ··· 326 326 327 327 drm_sched_entity_push_job(&job->base); 328 328 329 - mutex_unlock(&entity->mutex); 329 + mutex_unlock(&sched->mutex); 330 330 331 331 if (done_fence) { 332 332 dma_fence_wait(done_fence, true); ··· 336 336 return 0; 337 337 338 338 err_cleanup: 339 - mutex_unlock(&entity->mutex); 339 + mutex_unlock(&sched->mutex); 340 340 nouveau_job_fence_attach_cleanup(job); 341 341 err: 342 342 job->state = NOUVEAU_JOB_SUBMIT_FAILED; 343 343 return ret; 344 - } 345 - 346 - bool 347 - nouveau_sched_entity_qwork(struct nouveau_sched_entity *entity, 348 - struct work_struct *work) 349 - { 350 - return queue_work(entity->sched_wq, work); 351 344 } 352 345 353 346 static struct dma_fence * ··· 392 399 nouveau_job_fini(job); 393 400 } 394 401 395 - int nouveau_sched_entity_init(struct nouveau_sched_entity *entity, 396 - struct drm_gpu_scheduler *sched, 397 - struct workqueue_struct *sched_wq) 398 - { 399 - mutex_init(&entity->mutex); 400 - spin_lock_init(&entity->job.list.lock); 401 - INIT_LIST_HEAD(&entity->job.list.head); 402 - init_waitqueue_head(&entity->job.wq); 403 - 404 - entity->sched_wq = sched_wq; 405 - return drm_sched_entity_init(&entity->base, 406 - DRM_SCHED_PRIORITY_NORMAL, 407 - &sched, 1, NULL); 408 - } 409 - 410 - void 411 - nouveau_sched_entity_fini(struct nouveau_sched_entity *entity) 412 - { 413 - drm_sched_entity_destroy(&entity->base); 414 - } 415 - 416 402 static const struct drm_sched_backend_ops nouveau_sched_ops = { 417 403 .run_job = nouveau_sched_run_job, 418 404 .timedout_job = nouveau_sched_timedout_job, 419 405 .free_job = nouveau_sched_free_job, 420 406 }; 421 407 422 - int nouveau_sched_init(struct nouveau_drm *drm) 408 + int 409 + nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, 410 + struct workqueue_struct *wq, u32 credit_limit) 423 411 { 424 - struct drm_gpu_scheduler *sched = &drm->sched; 412 + struct drm_gpu_scheduler *drm_sched = &sched->base; 413 + struct drm_sched_entity *entity = &sched->entity; 425 414 long job_hang_limit = msecs_to_jiffies(NOUVEAU_SCHED_JOB_TIMEOUT_MS); 415 + int ret; 426 416 427 - drm->sched_wq = create_singlethread_workqueue("nouveau_sched_wq"); 428 - if (!drm->sched_wq) 429 - return -ENOMEM; 417 + if (!wq) { 418 + wq = alloc_workqueue("nouveau_sched_wq_%d", 0, WQ_MAX_ACTIVE, 419 + current->pid); 420 + if (!wq) 421 + return -ENOMEM; 430 422 431 - return drm_sched_init(sched, &nouveau_sched_ops, NULL, 432 - DRM_SCHED_PRIORITY_COUNT, 433 - NOUVEAU_SCHED_HW_SUBMISSIONS, 0, job_hang_limit, 434 - NULL, NULL, "nouveau_sched", drm->dev->dev); 423 + sched->wq = wq; 424 + } 425 + 426 + ret = drm_sched_init(drm_sched, &nouveau_sched_ops, wq, 427 + NOUVEAU_SCHED_PRIORITY_COUNT, 428 + credit_limit, 0, job_hang_limit, 429 + NULL, NULL, "nouveau_sched", drm->dev->dev); 430 + if (ret) 431 + goto fail_wq; 432 + 433 + /* Using DRM_SCHED_PRIORITY_KERNEL, since that's what we're required to use 434 + * when we want to have a single run-queue only. 435 + * 436 + * It's not documented, but one will find out when trying to use any 437 + * other priority running into faults, because the scheduler uses the 438 + * priority as array index. 439 + * 440 + * Can't use NOUVEAU_SCHED_PRIORITY_SINGLE either, because it's not 441 + * matching the enum type used in drm_sched_entity_init(). 442 + */ 443 + ret = drm_sched_entity_init(entity, DRM_SCHED_PRIORITY_KERNEL, 444 + &drm_sched, 1, NULL); 445 + if (ret) 446 + goto fail_sched; 447 + 448 + mutex_init(&sched->mutex); 449 + spin_lock_init(&sched->job.list.lock); 450 + INIT_LIST_HEAD(&sched->job.list.head); 451 + init_waitqueue_head(&sched->job.wq); 452 + 453 + return 0; 454 + 455 + fail_sched: 456 + drm_sched_fini(drm_sched); 457 + fail_wq: 458 + if (sched->wq) 459 + destroy_workqueue(sched->wq); 460 + return ret; 435 461 } 436 462 437 - void nouveau_sched_fini(struct nouveau_drm *drm) 463 + void 464 + nouveau_sched_fini(struct nouveau_sched *sched) 438 465 { 439 - destroy_workqueue(drm->sched_wq); 440 - drm_sched_fini(&drm->sched); 466 + struct drm_gpu_scheduler *drm_sched = &sched->base; 467 + struct drm_sched_entity *entity = &sched->entity; 468 + 469 + rmb(); /* for list_empty to work without lock */ 470 + wait_event(sched->job.wq, list_empty(&sched->job.list.head)); 471 + 472 + drm_sched_entity_fini(entity); 473 + drm_sched_fini(drm_sched); 474 + 475 + /* Destroy workqueue after scheduler tear down, otherwise it might still 476 + * be in use. 477 + */ 478 + if (sched->wq) 479 + destroy_workqueue(sched->wq); 441 480 }
+17 -26
drivers/gpu/drm/nouveau/nouveau_sched.h
··· 5 5 6 6 #include <linux/types.h> 7 7 8 - #include <drm/drm_exec.h> 8 + #include <drm/drm_gpuvm.h> 9 9 #include <drm/gpu_scheduler.h> 10 10 11 11 #include "nouveau_drv.h" ··· 26 26 27 27 struct nouveau_job_args { 28 28 struct drm_file *file_priv; 29 - struct nouveau_sched_entity *sched_entity; 29 + struct nouveau_sched *sched; 30 + u32 credits; 30 31 31 32 enum dma_resv_usage resv_usage; 32 33 bool sync; ··· 50 49 51 50 enum nouveau_job_state state; 52 51 53 - struct nouveau_sched_entity *entity; 52 + struct nouveau_sched *sched; 53 + struct list_head entry; 54 54 55 55 struct drm_file *file_priv; 56 56 struct nouveau_cli *cli; 57 57 58 - struct drm_exec exec; 59 58 enum dma_resv_usage resv_usage; 60 59 struct dma_fence *done_fence; 61 60 ··· 77 76 /* If .submit() returns without any error, it is guaranteed that 78 77 * armed_submit() is called. 79 78 */ 80 - int (*submit)(struct nouveau_job *); 81 - void (*armed_submit)(struct nouveau_job *); 79 + int (*submit)(struct nouveau_job *, struct drm_gpuvm_exec *); 80 + void (*armed_submit)(struct nouveau_job *, struct drm_gpuvm_exec *); 82 81 struct dma_fence *(*run)(struct nouveau_job *); 83 82 void (*free)(struct nouveau_job *); 84 83 enum drm_gpu_sched_stat (*timeout)(struct nouveau_job *); ··· 91 90 92 91 int nouveau_job_init(struct nouveau_job *job, 93 92 struct nouveau_job_args *args); 93 + void nouveau_job_fini(struct nouveau_job *job); 94 + int nouveau_job_submit(struct nouveau_job *job); 95 + void nouveau_job_done(struct nouveau_job *job); 94 96 void nouveau_job_free(struct nouveau_job *job); 95 97 96 - int nouveau_job_submit(struct nouveau_job *job); 97 - void nouveau_job_fini(struct nouveau_job *job); 98 - 99 - #define to_nouveau_sched_entity(entity) \ 100 - container_of((entity), struct nouveau_sched_entity, base) 101 - 102 - struct nouveau_sched_entity { 103 - struct drm_sched_entity base; 98 + struct nouveau_sched { 99 + struct drm_gpu_scheduler base; 100 + struct drm_sched_entity entity; 101 + struct workqueue_struct *wq; 104 102 struct mutex mutex; 105 - 106 - struct workqueue_struct *sched_wq; 107 103 108 104 struct { 109 105 struct { ··· 111 113 } job; 112 114 }; 113 115 114 - int nouveau_sched_entity_init(struct nouveau_sched_entity *entity, 115 - struct drm_gpu_scheduler *sched, 116 - struct workqueue_struct *sched_wq); 117 - void nouveau_sched_entity_fini(struct nouveau_sched_entity *entity); 118 - 119 - bool nouveau_sched_entity_qwork(struct nouveau_sched_entity *entity, 120 - struct work_struct *work); 121 - 122 - int nouveau_sched_init(struct nouveau_drm *drm); 123 - void nouveau_sched_fini(struct nouveau_drm *drm); 116 + int nouveau_sched_init(struct nouveau_sched *sched, struct nouveau_drm *drm, 117 + struct workqueue_struct *wq, u32 credit_limit); 118 + void nouveau_sched_fini(struct nouveau_sched *sched); 124 119 125 120 #endif
+99 -111
drivers/gpu/drm/nouveau/nouveau_uvmm.c
··· 438 438 static void 439 439 op_map_prepare_unwind(struct nouveau_uvma *uvma) 440 440 { 441 + struct drm_gpuva *va = &uvma->va; 441 442 nouveau_uvma_gem_put(uvma); 442 - drm_gpuva_remove(&uvma->va); 443 + drm_gpuva_remove(va); 443 444 nouveau_uvma_free(uvma); 444 445 } 445 446 ··· 469 468 break; 470 469 case DRM_GPUVA_OP_REMAP: { 471 470 struct drm_gpuva_op_remap *r = &op->remap; 471 + struct drm_gpuva *va = r->unmap->va; 472 472 473 473 if (r->next) 474 474 op_map_prepare_unwind(new->next); ··· 477 475 if (r->prev) 478 476 op_map_prepare_unwind(new->prev); 479 477 480 - op_unmap_prepare_unwind(r->unmap->va); 478 + op_unmap_prepare_unwind(va); 481 479 break; 482 480 } 483 481 case DRM_GPUVA_OP_UNMAP: ··· 608 606 drm_gpuva_unmap(u); 609 607 } 610 608 609 + /* 610 + * Note: @args should not be NULL when calling for a map operation. 611 + */ 611 612 static int 612 613 nouveau_uvmm_sm_prepare(struct nouveau_uvmm *uvmm, 613 614 struct nouveau_uvma_prealloc *new, ··· 631 626 if (ret) 632 627 goto unwind; 633 628 634 - if (args && vmm_get_range) { 629 + if (vmm_get_range) { 635 630 ret = nouveau_uvmm_vmm_get(uvmm, vmm_get_start, 636 631 vmm_get_range); 637 632 if (ret) { ··· 639 634 goto unwind; 640 635 } 641 636 } 637 + 642 638 break; 643 639 } 644 640 case DRM_GPUVA_OP_REMAP: { ··· 966 960 { 967 961 struct nouveau_uvmm_bind_job *job = 968 962 container_of(kref, struct nouveau_uvmm_bind_job, kref); 963 + struct bind_job_op *op, *next; 964 + 965 + list_for_each_op_safe(op, next, &job->ops) { 966 + list_del(&op->entry); 967 + kfree(op); 968 + } 969 969 970 970 nouveau_job_free(&job->base); 971 971 kfree(job); ··· 1013 1001 static void 1014 1002 bind_validate_map_sparse(struct nouveau_job *job, u64 addr, u64 range) 1015 1003 { 1016 - struct nouveau_uvmm_bind_job *bind_job; 1017 - struct nouveau_sched_entity *entity = job->entity; 1004 + struct nouveau_sched *sched = job->sched; 1005 + struct nouveau_job *__job; 1018 1006 struct bind_job_op *op; 1019 1007 u64 end = addr + range; 1020 1008 1021 1009 again: 1022 - spin_lock(&entity->job.list.lock); 1023 - list_for_each_entry(bind_job, &entity->job.list.head, entry) { 1010 + spin_lock(&sched->job.list.lock); 1011 + list_for_each_entry(__job, &sched->job.list.head, entry) { 1012 + struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(__job); 1013 + 1024 1014 list_for_each_op(op, &bind_job->ops) { 1025 1015 if (op->op == OP_UNMAP) { 1026 1016 u64 op_addr = op->va.addr; ··· 1030 1016 1031 1017 if (!(end <= op_addr || addr >= op_end)) { 1032 1018 nouveau_uvmm_bind_job_get(bind_job); 1033 - spin_unlock(&entity->job.list.lock); 1019 + spin_unlock(&sched->job.list.lock); 1034 1020 wait_for_completion(&bind_job->complete); 1035 1021 nouveau_uvmm_bind_job_put(bind_job); 1036 1022 goto again; ··· 1038 1024 } 1039 1025 } 1040 1026 } 1041 - spin_unlock(&entity->job.list.lock); 1027 + spin_unlock(&sched->job.list.lock); 1042 1028 } 1043 1029 1044 1030 static int ··· 1149 1135 } 1150 1136 1151 1137 static int 1152 - nouveau_uvmm_bind_job_submit(struct nouveau_job *job) 1138 + bind_lock_validate(struct nouveau_job *job, struct drm_exec *exec, 1139 + unsigned int num_fences) 1140 + { 1141 + struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(job); 1142 + struct bind_job_op *op; 1143 + int ret; 1144 + 1145 + list_for_each_op(op, &bind_job->ops) { 1146 + struct drm_gpuva_op *va_op; 1147 + 1148 + if (!op->ops) 1149 + continue; 1150 + 1151 + drm_gpuva_for_each_op(va_op, op->ops) { 1152 + struct drm_gem_object *obj = op_gem_obj(va_op); 1153 + 1154 + if (unlikely(!obj)) 1155 + continue; 1156 + 1157 + ret = drm_exec_prepare_obj(exec, obj, num_fences); 1158 + if (ret) 1159 + return ret; 1160 + 1161 + /* Don't validate GEMs backing mappings we're about to 1162 + * unmap, it's not worth the effort. 1163 + */ 1164 + if (va_op->op == DRM_GPUVA_OP_UNMAP) 1165 + continue; 1166 + 1167 + ret = nouveau_bo_validate(nouveau_gem_object(obj), 1168 + true, false); 1169 + if (ret) 1170 + return ret; 1171 + } 1172 + } 1173 + 1174 + return 0; 1175 + } 1176 + 1177 + static int 1178 + nouveau_uvmm_bind_job_submit(struct nouveau_job *job, 1179 + struct drm_gpuvm_exec *vme) 1153 1180 { 1154 1181 struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(job->cli); 1155 1182 struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(job); 1156 - struct nouveau_sched_entity *entity = job->entity; 1157 - struct drm_exec *exec = &job->exec; 1183 + struct drm_exec *exec = &vme->exec; 1158 1184 struct bind_job_op *op; 1159 1185 int ret; 1160 1186 ··· 1211 1157 dma_resv_unlock(obj->resv); 1212 1158 if (IS_ERR(op->vm_bo)) 1213 1159 return PTR_ERR(op->vm_bo); 1160 + 1161 + drm_gpuvm_bo_extobj_add(op->vm_bo); 1214 1162 } 1215 1163 1216 1164 ret = bind_validate_op(job, op); ··· 1235 1179 * unwind all GPU VA space changes on failure. 1236 1180 */ 1237 1181 nouveau_uvmm_lock(uvmm); 1182 + 1238 1183 list_for_each_op(op, &bind_job->ops) { 1239 1184 switch (op->op) { 1240 1185 case OP_MAP_SPARSE: ··· 1347 1290 } 1348 1291 } 1349 1292 1350 - drm_exec_init(exec, DRM_EXEC_INTERRUPTIBLE_WAIT | 1351 - DRM_EXEC_IGNORE_DUPLICATES); 1293 + drm_exec_init(exec, vme->flags); 1352 1294 drm_exec_until_all_locked(exec) { 1353 - list_for_each_op(op, &bind_job->ops) { 1354 - struct drm_gpuva_op *va_op; 1355 - 1356 - if (IS_ERR_OR_NULL(op->ops)) 1357 - continue; 1358 - 1359 - drm_gpuva_for_each_op(va_op, op->ops) { 1360 - struct drm_gem_object *obj = op_gem_obj(va_op); 1361 - 1362 - if (unlikely(!obj)) 1363 - continue; 1364 - 1365 - ret = drm_exec_prepare_obj(exec, obj, 1); 1366 - drm_exec_retry_on_contention(exec); 1367 - if (ret) { 1368 - op = list_last_op(&bind_job->ops); 1369 - goto unwind; 1370 - } 1371 - } 1372 - } 1373 - } 1374 - 1375 - list_for_each_op(op, &bind_job->ops) { 1376 - struct drm_gpuva_op *va_op; 1377 - 1378 - if (IS_ERR_OR_NULL(op->ops)) 1379 - continue; 1380 - 1381 - drm_gpuva_for_each_op(va_op, op->ops) { 1382 - struct drm_gem_object *obj = op_gem_obj(va_op); 1383 - 1384 - if (unlikely(!obj)) 1385 - continue; 1386 - 1387 - /* Don't validate GEMs backing mappings we're about to 1388 - * unmap, it's not worth the effort. 1389 - */ 1390 - if (unlikely(va_op->op == DRM_GPUVA_OP_UNMAP)) 1391 - continue; 1392 - 1393 - ret = nouveau_bo_validate(nouveau_gem_object(obj), 1394 - true, false); 1395 - if (ret) { 1396 - op = list_last_op(&bind_job->ops); 1397 - goto unwind; 1398 - } 1295 + ret = bind_lock_validate(job, exec, vme->num_fences); 1296 + drm_exec_retry_on_contention(exec); 1297 + if (ret) { 1298 + op = list_last_op(&bind_job->ops); 1299 + goto unwind; 1399 1300 } 1400 1301 } 1401 1302 ··· 1390 1375 } 1391 1376 nouveau_uvmm_unlock(uvmm); 1392 1377 1393 - spin_lock(&entity->job.list.lock); 1394 - list_add(&bind_job->entry, &entity->job.list.head); 1395 - spin_unlock(&entity->job.list.lock); 1396 - 1397 1378 return 0; 1398 1379 1399 1380 unwind_continue: ··· 1424 1413 } 1425 1414 1426 1415 nouveau_uvmm_unlock(uvmm); 1427 - drm_exec_fini(exec); 1416 + drm_gpuvm_exec_unlock(vme); 1428 1417 return ret; 1429 1418 } 1430 1419 1431 1420 static void 1432 - nouveau_uvmm_bind_job_armed_submit(struct nouveau_job *job) 1421 + nouveau_uvmm_bind_job_armed_submit(struct nouveau_job *job, 1422 + struct drm_gpuvm_exec *vme) 1433 1423 { 1434 - struct drm_exec *exec = &job->exec; 1435 - struct drm_gem_object *obj; 1436 - unsigned long index; 1437 - 1438 - drm_exec_for_each_locked_object(exec, index, obj) 1439 - dma_resv_add_fence(obj->resv, job->done_fence, job->resv_usage); 1440 - 1441 - drm_exec_fini(exec); 1424 + drm_gpuvm_exec_resv_add_fence(vme, job->done_fence, 1425 + job->resv_usage, job->resv_usage); 1426 + drm_gpuvm_exec_unlock(vme); 1442 1427 } 1443 1428 1444 1429 static struct dma_fence * ··· 1472 1465 } 1473 1466 1474 1467 static void 1475 - nouveau_uvmm_bind_job_free_work_fn(struct work_struct *work) 1468 + nouveau_uvmm_bind_job_cleanup(struct nouveau_job *job) 1476 1469 { 1477 - struct nouveau_uvmm_bind_job *bind_job = 1478 - container_of(work, struct nouveau_uvmm_bind_job, work); 1479 - struct nouveau_job *job = &bind_job->base; 1470 + struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(job); 1480 1471 struct nouveau_uvmm *uvmm = nouveau_cli_uvmm(job->cli); 1481 - struct nouveau_sched_entity *entity = job->entity; 1482 - struct bind_job_op *op, *next; 1472 + struct bind_job_op *op; 1483 1473 1484 1474 list_for_each_op(op, &bind_job->ops) { 1485 1475 struct drm_gem_object *obj = op->gem.obj; ··· 1528 1524 drm_gem_object_put(obj); 1529 1525 } 1530 1526 1531 - spin_lock(&entity->job.list.lock); 1532 - list_del(&bind_job->entry); 1533 - spin_unlock(&entity->job.list.lock); 1534 - 1527 + nouveau_job_done(job); 1535 1528 complete_all(&bind_job->complete); 1536 - wake_up(&entity->job.wq); 1537 - 1538 - /* Remove and free ops after removing the bind job from the job list to 1539 - * avoid races against bind_validate_map_sparse(). 1540 - */ 1541 - list_for_each_op_safe(op, next, &bind_job->ops) { 1542 - list_del(&op->entry); 1543 - kfree(op); 1544 - } 1545 1529 1546 1530 nouveau_uvmm_bind_job_put(bind_job); 1547 - } 1548 - 1549 - static void 1550 - nouveau_uvmm_bind_job_free_qwork(struct nouveau_job *job) 1551 - { 1552 - struct nouveau_uvmm_bind_job *bind_job = to_uvmm_bind_job(job); 1553 - struct nouveau_sched_entity *entity = job->entity; 1554 - 1555 - nouveau_sched_entity_qwork(entity, &bind_job->work); 1556 1531 } 1557 1532 1558 1533 static struct nouveau_job_ops nouveau_bind_job_ops = { 1559 1534 .submit = nouveau_uvmm_bind_job_submit, 1560 1535 .armed_submit = nouveau_uvmm_bind_job_armed_submit, 1561 1536 .run = nouveau_uvmm_bind_job_run, 1562 - .free = nouveau_uvmm_bind_job_free_qwork, 1537 + .free = nouveau_uvmm_bind_job_cleanup, 1563 1538 }; 1564 1539 1565 1540 static int ··· 1599 1616 return ret; 1600 1617 1601 1618 INIT_LIST_HEAD(&job->ops); 1602 - INIT_LIST_HEAD(&job->entry); 1603 1619 1604 1620 for (i = 0; i < __args->op.count; i++) { 1605 1621 ret = bind_job_op_from_uop(&op, &__args->op.s[i]); ··· 1609 1627 } 1610 1628 1611 1629 init_completion(&job->complete); 1612 - INIT_WORK(&job->work, nouveau_uvmm_bind_job_free_work_fn); 1613 1630 1614 - args.sched_entity = __args->sched_entity; 1615 1631 args.file_priv = __args->file_priv; 1632 + 1633 + args.sched = __args->sched; 1634 + args.credits = 1; 1616 1635 1617 1636 args.in_sync.count = __args->in_sync.count; 1618 1637 args.in_sync.s = __args->in_sync.s; ··· 1740 1757 if (ret) 1741 1758 return ret; 1742 1759 1743 - args.sched_entity = &cli->sched_entity; 1760 + args.sched = &cli->sched; 1744 1761 args.file_priv = file_priv; 1745 1762 1746 1763 ret = nouveau_uvmm_vm_bind(&args); ··· 1798 1815 kfree(uvmm); 1799 1816 } 1800 1817 1818 + static int 1819 + nouveau_uvmm_bo_validate(struct drm_gpuvm_bo *vm_bo, struct drm_exec *exec) 1820 + { 1821 + struct nouveau_bo *nvbo = nouveau_gem_object(vm_bo->obj); 1822 + 1823 + return nouveau_bo_validate(nvbo, true, false); 1824 + } 1825 + 1801 1826 static const struct drm_gpuvm_ops gpuvm_ops = { 1802 1827 .vm_free = nouveau_uvmm_free, 1828 + .vm_bo_validate = nouveau_uvmm_bo_validate, 1803 1829 }; 1804 1830 1805 1831 int ··· 1892 1900 MA_STATE(mas, &uvmm->region_mt, 0, 0); 1893 1901 struct nouveau_uvma_region *reg; 1894 1902 struct nouveau_cli *cli = uvmm->vmm.cli; 1895 - struct nouveau_sched_entity *entity = &cli->sched_entity; 1896 1903 struct drm_gpuva *va, *next; 1897 - 1898 - rmb(); /* for list_empty to work without lock */ 1899 - wait_event(entity->job.wq, list_empty(&entity->job.list.head)); 1900 1904 1901 1905 nouveau_uvmm_lock(uvmm); 1902 1906 drm_gpuvm_for_each_va_safe(va, next, &uvmm->base) {
+1 -3
drivers/gpu/drm/nouveau/nouveau_uvmm.h
··· 44 44 struct nouveau_job base; 45 45 46 46 struct kref kref; 47 - struct list_head entry; 48 - struct work_struct work; 49 47 struct completion complete; 50 48 51 49 /* struct bind_job_op */ ··· 52 54 53 55 struct nouveau_uvmm_bind_job_args { 54 56 struct drm_file *file_priv; 55 - struct nouveau_sched_entity *sched_entity; 57 + struct nouveau_sched *sched; 56 58 57 59 unsigned int flags; 58 60
+2 -2
drivers/gpu/drm/omapdrm/dss/dispc.c
··· 22 22 #include <linux/hardirq.h> 23 23 #include <linux/platform_device.h> 24 24 #include <linux/pm_runtime.h> 25 + #include <linux/property.h> 25 26 #include <linux/sizes.h> 26 27 #include <linux/mfd/syscon.h> 27 28 #include <linux/regmap.h> 28 29 #include <linux/of.h> 29 - #include <linux/of_device.h> 30 30 #include <linux/component.h> 31 31 #include <linux/sys_soc.h> 32 32 #include <drm/drm_fourcc.h> ··· 4765 4765 if (soc) 4766 4766 dispc->feat = soc->data; 4767 4767 else 4768 - dispc->feat = of_match_device(dispc_of_match, &pdev->dev)->data; 4768 + dispc->feat = device_get_match_data(&pdev->dev); 4769 4769 4770 4770 r = dispc_errata_i734_wa_init(dispc); 4771 4771 if (r)
+3 -2
drivers/gpu/drm/omapdrm/dss/dss.c
··· 22 22 #include <linux/pinctrl/consumer.h> 23 23 #include <linux/platform_device.h> 24 24 #include <linux/pm_runtime.h> 25 + #include <linux/property.h> 25 26 #include <linux/gfp.h> 26 27 #include <linux/sizes.h> 27 28 #include <linux/mfd/syscon.h> 28 29 #include <linux/regmap.h> 29 30 #include <linux/of.h> 30 - #include <linux/of_device.h> 31 + #include <linux/of_platform.h> 31 32 #include <linux/of_graph.h> 32 33 #include <linux/regulator/consumer.h> 33 34 #include <linux/suspend.h> ··· 1446 1445 if (soc) 1447 1446 dss->feat = soc->data; 1448 1447 else 1449 - dss->feat = of_match_device(dss_of_match, &pdev->dev)->data; 1448 + dss->feat = device_get_match_data(&pdev->dev); 1450 1449 1451 1450 /* Map I/O registers, get and setup clocks. */ 1452 1451 dss->base = devm_platform_ioremap_resource(pdev, 0);
+10 -4
drivers/gpu/drm/omapdrm/omap_gem.c
··· 48 48 * OMAP_BO_MEM_DMA_API flag set) 49 49 * 50 50 * - buffers imported from dmabuf (with the OMAP_BO_MEM_DMABUF flag set) 51 - * if they are physically contiguous (when sgt->orig_nents == 1) 51 + * if they are physically contiguous 52 52 * 53 53 * - buffers mapped through the TILER when pin_cnt is not zero, in which 54 54 * case the DMA address points to the TILER aperture ··· 148 148 return drm_vma_node_offset_addr(&obj->vma_node); 149 149 } 150 150 151 + static bool omap_gem_sgt_is_contiguous(struct sg_table *sgt, size_t size) 152 + { 153 + return !(drm_prime_get_contiguous_size(sgt) < size); 154 + } 155 + 151 156 static bool omap_gem_is_contiguous(struct omap_gem_object *omap_obj) 152 157 { 153 158 if (omap_obj->flags & OMAP_BO_MEM_DMA_API) 154 159 return true; 155 160 156 - if ((omap_obj->flags & OMAP_BO_MEM_DMABUF) && omap_obj->sgt->nents == 1) 161 + if ((omap_obj->flags & OMAP_BO_MEM_DMABUF) && 162 + omap_gem_sgt_is_contiguous(omap_obj->sgt, omap_obj->base.size)) 157 163 return true; 158 164 159 165 return false; ··· 1391 1385 union omap_gem_size gsize; 1392 1386 1393 1387 /* Without a DMM only physically contiguous buffers can be supported. */ 1394 - if (sgt->orig_nents != 1 && !priv->has_dmm) 1388 + if (!omap_gem_sgt_is_contiguous(sgt, size) && !priv->has_dmm) 1395 1389 return ERR_PTR(-EINVAL); 1396 1390 1397 1391 gsize.bytes = PAGE_ALIGN(size); ··· 1405 1399 1406 1400 omap_obj->sgt = sgt; 1407 1401 1408 - if (sgt->orig_nents == 1) { 1402 + if (omap_gem_sgt_is_contiguous(sgt, size)) { 1409 1403 omap_obj->dma_addr = sg_dma_address(sgt->sgl); 1410 1404 } else { 1411 1405 /* Create pages list from sgt */
+71 -12
drivers/gpu/drm/panel/panel-edp.c
··· 203 203 204 204 /** @name: Name of this panel (for printing to logs). */ 205 205 const char *name; 206 + 207 + /** @override_edid_mode: Override the mode obtained by edid. */ 208 + const struct drm_display_mode *override_edid_mode; 206 209 }; 207 210 208 211 struct panel_edp { ··· 302 299 } 303 300 304 301 return num; 302 + } 303 + 304 + static int panel_edp_override_edid_mode(struct panel_edp *panel, 305 + struct drm_connector *connector, 306 + const struct drm_display_mode *override_mode) 307 + { 308 + struct drm_display_mode *mode; 309 + 310 + mode = drm_mode_duplicate(connector->dev, override_mode); 311 + if (!mode) { 312 + dev_err(panel->base.dev, "failed to add additional mode\n"); 313 + return 0; 314 + } 315 + 316 + mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 317 + drm_mode_set_name(mode); 318 + drm_mode_probed_add(connector, mode); 319 + return 1; 305 320 } 306 321 307 322 static int panel_edp_get_non_edid_modes(struct panel_edp *panel, ··· 589 568 { 590 569 struct panel_edp *p = to_panel_edp(panel); 591 570 int num = 0; 571 + bool has_hard_coded_modes = p->desc->num_timings || p->desc->num_modes; 572 + bool has_override_edid_mode = p->detected_panel && 573 + p->detected_panel != ERR_PTR(-EINVAL) && 574 + p->detected_panel->override_edid_mode; 592 575 593 576 /* probe EDID if a DDC bus is available */ 594 577 if (p->ddc) { ··· 600 575 601 576 if (!p->edid) 602 577 p->edid = drm_get_edid(connector, p->ddc); 603 - 604 - if (p->edid) 605 - num += drm_add_edid_modes(connector, p->edid); 578 + /* 579 + * If both edid and hard-coded modes exists, skip edid modes to 580 + * avoid multiple preferred modes. 581 + */ 582 + if (p->edid && !has_hard_coded_modes) { 583 + if (has_override_edid_mode) { 584 + /* 585 + * override_edid_mode is specified. Use 586 + * override_edid_mode instead of from edid. 587 + */ 588 + num += panel_edp_override_edid_mode(p, connector, 589 + p->detected_panel->override_edid_mode); 590 + } else { 591 + num += drm_add_edid_modes(connector, p->edid); 592 + } 593 + } 606 594 607 595 pm_runtime_mark_last_busy(panel->dev); 608 596 pm_runtime_put_autosuspend(panel->dev); 609 597 } 610 598 611 - /* 612 - * Add hard-coded panel modes. Don't call this if there are no timings 613 - * and no modes (the generic edp-panel case) because it will clobber 614 - * the display_info that was already set by drm_add_edid_modes(). 615 - */ 616 - if (p->desc->num_timings || p->desc->num_modes) 599 + if (has_hard_coded_modes) 617 600 num += panel_edp_get_non_edid_modes(p, connector); 618 601 else if (!num) 619 602 dev_warn(p->base.dev, "No display modes\n"); ··· 981 948 .width = 217, 982 949 .height = 136, 983 950 }, 951 + }; 952 + 953 + static const struct drm_display_mode auo_b116xa3_mode = { 954 + .clock = 70589, 955 + .hdisplay = 1366, 956 + .hsync_start = 1366 + 40, 957 + .hsync_end = 1366 + 40 + 40, 958 + .htotal = 1366 + 40 + 40 + 32, 959 + .vdisplay = 768, 960 + .vsync_start = 768 + 10, 961 + .vsync_end = 768 + 10 + 12, 962 + .vtotal = 768 + 10 + 12 + 6, 963 + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, 984 964 }; 985 965 986 966 static const struct drm_display_mode auo_b116xak01_mode = { ··· 1895 1849 .delay = _delay \ 1896 1850 } 1897 1851 1852 + #define EDP_PANEL_ENTRY2(vend_chr_0, vend_chr_1, vend_chr_2, product_id, _delay, _name, _mode) \ 1853 + { \ 1854 + .name = _name, \ 1855 + .panel_id = drm_edid_encode_panel_id(vend_chr_0, vend_chr_1, vend_chr_2, \ 1856 + product_id), \ 1857 + .delay = _delay, \ 1858 + .override_edid_mode = _mode \ 1859 + } 1860 + 1898 1861 /* 1899 1862 * This table is used to figure out power sequencing delays for panels that 1900 1863 * are detected by EDID. Entries here may point to entries in the ··· 1921 1866 EDP_PANEL_ENTRY('A', 'U', 'O', 0x239b, &delay_200_500_e50, "B116XAN06.1"), 1922 1867 EDP_PANEL_ENTRY('A', 'U', 'O', 0x255c, &delay_200_500_e50, "B116XTN02.5"), 1923 1868 EDP_PANEL_ENTRY('A', 'U', 'O', 0x403d, &delay_200_500_e50, "B140HAN04.0"), 1924 - EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01.0"), 1869 + EDP_PANEL_ENTRY2('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01.0", 1870 + &auo_b116xa3_mode), 1925 1871 EDP_PANEL_ENTRY('A', 'U', 'O', 0x582d, &delay_200_500_e50, "B133UAN01.0"), 1926 - EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"), 1872 + EDP_PANEL_ENTRY2('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1", 1873 + &auo_b116xa3_mode), 1927 1874 EDP_PANEL_ENTRY('A', 'U', 'O', 0x635c, &delay_200_500_e50, "B116XAN06.3"), 1928 1875 EDP_PANEL_ENTRY('A', 'U', 'O', 0x639c, &delay_200_500_e50, "B140HAK02.7"), 1929 1876 EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"), ··· 1967 1910 EDP_PANEL_ENTRY('C', 'M', 'N', 0x142b, &delay_200_500_e80_d50, "N140HCA-EAC"), 1968 1911 EDP_PANEL_ENTRY('C', 'M', 'N', 0x144f, &delay_200_500_e80_d50, "N140HGA-EA1"), 1969 1912 EDP_PANEL_ENTRY('C', 'M', 'N', 0x1468, &delay_200_500_e80, "N140HGA-EA1"), 1970 - EDP_PANEL_ENTRY('C', 'M', 'N', 0x14e5, &delay_200_500_e80_d50, "N140HGA-EA1"), 1971 1913 EDP_PANEL_ENTRY('C', 'M', 'N', 0x14d4, &delay_200_500_e80_d50, "N140HCA-EAC"), 1972 1914 EDP_PANEL_ENTRY('C', 'M', 'N', 0x14d6, &delay_200_500_e80_d50, "N140BGA-EA4"), 1915 + EDP_PANEL_ENTRY('C', 'M', 'N', 0x14e5, &delay_200_500_e80_d50, "N140HGA-EA1"), 1973 1916 1974 1917 EDP_PANEL_ENTRY('H', 'K', 'C', 0x2d5c, &delay_200_500_e200, "MB116AN01-2"), 1975 1918 ··· 1982 1925 EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"), 1983 1926 EDP_PANEL_ENTRY('K', 'D', 'C', 0x0809, &delay_200_500_e50, "KD116N2930A15"), 1984 1927 EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"), 1928 + 1929 + EDP_PANEL_ENTRY('S', 'D', 'C', 0x416d, &delay_100_500_e200, "ATNA45AF01"), 1985 1930 1986 1931 EDP_PANEL_ENTRY('S', 'H', 'P', 0x1511, &delay_200_500_e50, "LQ140M1JW48"), 1987 1932 EDP_PANEL_ENTRY('S', 'H', 'P', 0x1523, &sharp_lq140m1jw46.delay, "LQ140M1JW46"),
+152 -28
drivers/gpu/drm/panel/panel-himax-hx8394.c
··· 38 38 #define HX8394_CMD_SETMIPI 0xba 39 39 #define HX8394_CMD_SETOTP 0xbb 40 40 #define HX8394_CMD_SETREGBANK 0xbd 41 + #define HX8394_CMD_UNKNOWN5 0xbf 41 42 #define HX8394_CMD_UNKNOWN1 0xc0 42 43 #define HX8394_CMD_SETDGCLUT 0xc1 43 44 #define HX8394_CMD_SETID 0xc3 ··· 53 52 #define HX8394_CMD_SETGIP1 0xd5 54 53 #define HX8394_CMD_SETGIP2 0xd6 55 54 #define HX8394_CMD_SETGPO 0xd6 55 + #define HX8394_CMD_UNKNOWN4 0xd8 56 56 #define HX8394_CMD_SETSCALING 0xdd 57 57 #define HX8394_CMD_SETIDLE 0xdf 58 58 #define HX8394_CMD_SETGAMMA 0xe0 ··· 70 68 struct gpio_desc *reset_gpio; 71 69 struct regulator *vcc; 72 70 struct regulator *iovcc; 73 - bool prepared; 71 + enum drm_panel_orientation orientation; 74 72 75 73 const struct hx8394_panel_desc *desc; 76 74 }; ··· 205 203 .init_sequence = hsd060bhw4_init_sequence, 206 204 }; 207 205 206 + static int powkiddy_x55_init_sequence(struct hx8394 *ctx) 207 + { 208 + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); 209 + 210 + /* 5.19.8 SETEXTC: Set extension command (B9h) */ 211 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETEXTC, 212 + 0xff, 0x83, 0x94); 213 + 214 + /* 5.19.9 SETMIPI: Set MIPI control (BAh) */ 215 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETMIPI, 216 + 0x63, 0x03, 0x68, 0x6b, 0xb2, 0xc0); 217 + 218 + /* 5.19.2 SETPOWER: Set power (B1h) */ 219 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, 220 + 0x48, 0x12, 0x72, 0x09, 0x32, 0x54, 0x71, 0x71, 0x57, 0x47); 221 + 222 + /* 5.19.3 SETDISP: Set display related register (B2h) */ 223 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETDISP, 224 + 0x00, 0x80, 0x64, 0x2c, 0x16, 0x2f); 225 + 226 + /* 5.19.4 SETCYC: Set display waveform cycles (B4h) */ 227 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETCYC, 228 + 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0c, 0x86, 0x75, 229 + 0x00, 0x3f, 0x73, 0x74, 0x73, 0x74, 0x73, 0x74, 0x01, 0x0c, 230 + 0x86); 231 + 232 + /* 5.19.5 SETVCOM: Set VCOM voltage (B6h) */ 233 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETVCOM, 234 + 0x6e, 0x6e); 235 + 236 + /* 5.19.19 SETGIP0: Set GIP Option0 (D3h) */ 237 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP0, 238 + 0x00, 0x00, 0x07, 0x07, 0x40, 0x07, 0x0c, 0x00, 0x08, 0x10, 239 + 0x08, 0x00, 0x08, 0x54, 0x15, 0x0a, 0x05, 0x0a, 0x02, 0x15, 240 + 0x06, 0x05, 0x06, 0x47, 0x44, 0x0a, 0x0a, 0x4b, 0x10, 0x07, 241 + 0x07, 0x0c, 0x40); 242 + 243 + /* 5.19.20 Set GIP Option1 (D5h) */ 244 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP1, 245 + 0x1c, 0x1c, 0x1d, 0x1d, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 246 + 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x24, 0x25, 0x18, 0x18, 247 + 0x26, 0x27, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 248 + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x20, 0x21, 249 + 0x18, 0x18, 0x18, 0x18); 250 + 251 + /* 5.19.21 Set GIP Option2 (D6h) */ 252 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGIP2, 253 + 0x1c, 0x1c, 0x1d, 0x1d, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 254 + 0x01, 0x00, 0x0b, 0x0a, 0x09, 0x08, 0x21, 0x20, 0x18, 0x18, 255 + 0x27, 0x26, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 256 + 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x25, 0x24, 257 + 0x18, 0x18, 0x18, 0x18); 258 + 259 + /* 5.19.25 SETGAMMA: Set gamma curve related setting (E0h) */ 260 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETGAMMA, 261 + 0x00, 0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24, 0x22, 0x47, 0x56, 262 + 0x65, 0x66, 0x6e, 0x82, 0x88, 0x8b, 0x9a, 0x9d, 0x98, 0xa8, 263 + 0xb9, 0x5d, 0x5c, 0x61, 0x66, 0x6a, 0x6f, 0x7f, 0x7f, 0x00, 264 + 0x0a, 0x15, 0x1b, 0x1e, 0x21, 0x24, 0x22, 0x47, 0x56, 0x65, 265 + 0x65, 0x6e, 0x81, 0x87, 0x8b, 0x98, 0x9d, 0x99, 0xa8, 0xba, 266 + 0x5d, 0x5d, 0x62, 0x67, 0x6b, 0x72, 0x7f, 0x7f); 267 + 268 + /* Unknown command, not listed in the HX8394-F datasheet */ 269 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN1, 270 + 0x1f, 0x31); 271 + 272 + /* 5.19.17 SETPANEL (CCh) */ 273 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPANEL, 274 + 0x0b); 275 + 276 + /* Unknown command, not listed in the HX8394-F datasheet */ 277 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN3, 278 + 0x02); 279 + 280 + /* 5.19.11 Set register bank (BDh) */ 281 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, 282 + 0x02); 283 + 284 + /* Unknown command, not listed in the HX8394-F datasheet */ 285 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN4, 286 + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 287 + 0xff, 0xff); 288 + 289 + /* 5.19.11 Set register bank (BDh) */ 290 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, 291 + 0x00); 292 + 293 + /* 5.19.11 Set register bank (BDh) */ 294 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, 295 + 0x01); 296 + 297 + /* 5.19.2 SETPOWER: Set power (B1h) */ 298 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETPOWER, 299 + 0x00); 300 + 301 + /* 5.19.11 Set register bank (BDh) */ 302 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_SETREGBANK, 303 + 0x00); 304 + 305 + /* Unknown command, not listed in the HX8394-F datasheet */ 306 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN5, 307 + 0x40, 0x81, 0x50, 0x00, 0x1a, 0xfc, 0x01); 308 + 309 + /* Unknown command, not listed in the HX8394-F datasheet */ 310 + mipi_dsi_dcs_write_seq(dsi, HX8394_CMD_UNKNOWN2, 311 + 0xed); 312 + 313 + return 0; 314 + } 315 + 316 + static const struct drm_display_mode powkiddy_x55_mode = { 317 + .hdisplay = 720, 318 + .hsync_start = 720 + 44, 319 + .hsync_end = 720 + 44 + 20, 320 + .htotal = 720 + 44 + 20 + 20, 321 + .vdisplay = 1280, 322 + .vsync_start = 1280 + 12, 323 + .vsync_end = 1280 + 12 + 10, 324 + .vtotal = 1280 + 12 + 10 + 10, 325 + .clock = 63290, 326 + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, 327 + .width_mm = 67, 328 + .height_mm = 121, 329 + }; 330 + 331 + static const struct hx8394_panel_desc powkiddy_x55_desc = { 332 + .mode = &powkiddy_x55_mode, 333 + .lanes = 4, 334 + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | 335 + MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET, 336 + .format = MIPI_DSI_FMT_RGB888, 337 + .init_sequence = powkiddy_x55_init_sequence, 338 + }; 339 + 208 340 static int hx8394_enable(struct drm_panel *panel) 209 341 { 210 342 struct hx8394 *ctx = panel_to_hx8394(panel); ··· 398 262 { 399 263 struct hx8394 *ctx = panel_to_hx8394(panel); 400 264 401 - if (!ctx->prepared) 402 - return 0; 403 - 404 265 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 405 266 406 267 regulator_disable(ctx->iovcc); 407 268 regulator_disable(ctx->vcc); 408 - 409 - ctx->prepared = false; 410 269 411 270 return 0; 412 271 } ··· 410 279 { 411 280 struct hx8394 *ctx = panel_to_hx8394(panel); 412 281 int ret; 413 - 414 - if (ctx->prepared) 415 - return 0; 416 282 417 283 gpiod_set_value_cansleep(ctx->reset_gpio, 1); 418 284 ··· 428 300 gpiod_set_value_cansleep(ctx->reset_gpio, 0); 429 301 430 302 msleep(180); 431 - 432 - ctx->prepared = true; 433 303 434 304 return 0; 435 305 ··· 461 335 return 1; 462 336 } 463 337 338 + static enum drm_panel_orientation hx8394_get_orientation(struct drm_panel *panel) 339 + { 340 + struct hx8394 *ctx = panel_to_hx8394(panel); 341 + 342 + return ctx->orientation; 343 + } 344 + 464 345 static const struct drm_panel_funcs hx8394_drm_funcs = { 465 346 .disable = hx8394_disable, 466 347 .unprepare = hx8394_unprepare, 467 348 .prepare = hx8394_prepare, 468 349 .enable = hx8394_enable, 469 350 .get_modes = hx8394_get_modes, 351 + .get_orientation = hx8394_get_orientation, 470 352 }; 471 353 472 354 static int hx8394_probe(struct mipi_dsi_device *dsi) ··· 491 357 if (IS_ERR(ctx->reset_gpio)) 492 358 return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio), 493 359 "Failed to get reset gpio\n"); 360 + 361 + ret = of_drm_get_panel_orientation(dev->of_node, &ctx->orientation); 362 + if (ret < 0) { 363 + dev_err(dev, "%pOF: failed to get orientation %d\n", dev->of_node, ret); 364 + return ret; 365 + } 494 366 495 367 mipi_dsi_set_drvdata(dsi, ctx); 496 368 ··· 541 401 return 0; 542 402 } 543 403 544 - static void hx8394_shutdown(struct mipi_dsi_device *dsi) 545 - { 546 - struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi); 547 - int ret; 548 - 549 - ret = drm_panel_disable(&ctx->panel); 550 - if (ret < 0) 551 - dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret); 552 - 553 - ret = drm_panel_unprepare(&ctx->panel); 554 - if (ret < 0) 555 - dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret); 556 - } 557 - 558 404 static void hx8394_remove(struct mipi_dsi_device *dsi) 559 405 { 560 406 struct hx8394 *ctx = mipi_dsi_get_drvdata(dsi); 561 407 int ret; 562 - 563 - hx8394_shutdown(dsi); 564 408 565 409 ret = mipi_dsi_detach(dsi); 566 410 if (ret < 0) ··· 555 431 556 432 static const struct of_device_id hx8394_of_match[] = { 557 433 { .compatible = "hannstar,hsd060bhw4", .data = &hsd060bhw4_desc }, 434 + { .compatible = "powkiddy,x55-panel", .data = &powkiddy_x55_desc }, 558 435 { /* sentinel */ } 559 436 }; 560 437 MODULE_DEVICE_TABLE(of, hx8394_of_match); ··· 563 438 static struct mipi_dsi_driver hx8394_driver = { 564 439 .probe = hx8394_probe, 565 440 .remove = hx8394_remove, 566 - .shutdown = hx8394_shutdown, 567 441 .driver = { 568 442 .name = DRV_NAME, 569 443 .of_match_table = hx8394_of_match,
+225
drivers/gpu/drm/panel/panel-ilitek-ili9881c.c
··· 830 830 ILI9881C_SWITCH_PAGE_INSTR(0), 831 831 }; 832 832 833 + static const struct ili9881c_instr am8001280g_init[] = { 834 + ILI9881C_SWITCH_PAGE_INSTR(3), 835 + ILI9881C_COMMAND_INSTR(0x01, 0x00), 836 + ILI9881C_COMMAND_INSTR(0x02, 0x00), 837 + ILI9881C_COMMAND_INSTR(0x03, 0x73), 838 + ILI9881C_COMMAND_INSTR(0x04, 0xD3), 839 + ILI9881C_COMMAND_INSTR(0x05, 0x00), 840 + ILI9881C_COMMAND_INSTR(0x06, 0x0A), 841 + ILI9881C_COMMAND_INSTR(0x07, 0x0E), 842 + ILI9881C_COMMAND_INSTR(0x08, 0x00), 843 + ILI9881C_COMMAND_INSTR(0x09, 0x01), 844 + ILI9881C_COMMAND_INSTR(0x0a, 0x01), 845 + ILI9881C_COMMAND_INSTR(0x0b, 0x01), 846 + ILI9881C_COMMAND_INSTR(0x0c, 0x01), 847 + ILI9881C_COMMAND_INSTR(0x0d, 0x01), 848 + ILI9881C_COMMAND_INSTR(0x0e, 0x01), 849 + ILI9881C_COMMAND_INSTR(0x0f, 0x01), 850 + ILI9881C_COMMAND_INSTR(0x10, 0x01), 851 + ILI9881C_COMMAND_INSTR(0x11, 0x00), 852 + ILI9881C_COMMAND_INSTR(0x12, 0x00), 853 + ILI9881C_COMMAND_INSTR(0x13, 0x00), 854 + ILI9881C_COMMAND_INSTR(0x14, 0x00), 855 + ILI9881C_COMMAND_INSTR(0x15, 0x00), 856 + ILI9881C_COMMAND_INSTR(0x16, 0x00), 857 + ILI9881C_COMMAND_INSTR(0x17, 0x00), 858 + ILI9881C_COMMAND_INSTR(0x18, 0x00), 859 + ILI9881C_COMMAND_INSTR(0x19, 0x00), 860 + ILI9881C_COMMAND_INSTR(0x1a, 0x00), 861 + ILI9881C_COMMAND_INSTR(0x1b, 0x00), 862 + ILI9881C_COMMAND_INSTR(0x1c, 0x00), 863 + ILI9881C_COMMAND_INSTR(0x1d, 0x00), 864 + ILI9881C_COMMAND_INSTR(0x1e, 0x40), 865 + ILI9881C_COMMAND_INSTR(0x1f, 0x80), 866 + ILI9881C_COMMAND_INSTR(0x20, 0x06), 867 + ILI9881C_COMMAND_INSTR(0x21, 0x01), 868 + ILI9881C_COMMAND_INSTR(0x22, 0x00), 869 + ILI9881C_COMMAND_INSTR(0x23, 0x00), 870 + ILI9881C_COMMAND_INSTR(0x24, 0x00), 871 + ILI9881C_COMMAND_INSTR(0x25, 0x00), 872 + ILI9881C_COMMAND_INSTR(0x26, 0x00), 873 + ILI9881C_COMMAND_INSTR(0x27, 0x00), 874 + ILI9881C_COMMAND_INSTR(0x28, 0x33), 875 + ILI9881C_COMMAND_INSTR(0x29, 0x03), 876 + ILI9881C_COMMAND_INSTR(0x2a, 0x00), 877 + ILI9881C_COMMAND_INSTR(0x2b, 0x00), 878 + ILI9881C_COMMAND_INSTR(0x2c, 0x00), 879 + ILI9881C_COMMAND_INSTR(0x2d, 0x00), 880 + ILI9881C_COMMAND_INSTR(0x2e, 0x00), 881 + ILI9881C_COMMAND_INSTR(0x2f, 0x00), 882 + ILI9881C_COMMAND_INSTR(0x30, 0x00), 883 + ILI9881C_COMMAND_INSTR(0x31, 0x00), 884 + ILI9881C_COMMAND_INSTR(0x32, 0x00), 885 + ILI9881C_COMMAND_INSTR(0x33, 0x00), 886 + ILI9881C_COMMAND_INSTR(0x34, 0x03), 887 + ILI9881C_COMMAND_INSTR(0x35, 0x00), 888 + ILI9881C_COMMAND_INSTR(0x36, 0x03), 889 + ILI9881C_COMMAND_INSTR(0x37, 0x00), 890 + ILI9881C_COMMAND_INSTR(0x38, 0x00), 891 + ILI9881C_COMMAND_INSTR(0x39, 0x00), 892 + ILI9881C_COMMAND_INSTR(0x3a, 0x40), 893 + ILI9881C_COMMAND_INSTR(0x3b, 0x40), 894 + ILI9881C_COMMAND_INSTR(0x3c, 0x00), 895 + ILI9881C_COMMAND_INSTR(0x3d, 0x00), 896 + ILI9881C_COMMAND_INSTR(0x3e, 0x00), 897 + ILI9881C_COMMAND_INSTR(0x3f, 0x00), 898 + ILI9881C_COMMAND_INSTR(0x40, 0x00), 899 + ILI9881C_COMMAND_INSTR(0x41, 0x00), 900 + ILI9881C_COMMAND_INSTR(0x42, 0x00), 901 + ILI9881C_COMMAND_INSTR(0x43, 0x00), 902 + ILI9881C_COMMAND_INSTR(0x44, 0x00), 903 + 904 + ILI9881C_COMMAND_INSTR(0x50, 0x01), 905 + ILI9881C_COMMAND_INSTR(0x51, 0x23), 906 + ILI9881C_COMMAND_INSTR(0x52, 0x45), 907 + ILI9881C_COMMAND_INSTR(0x53, 0x67), 908 + ILI9881C_COMMAND_INSTR(0x54, 0x89), 909 + ILI9881C_COMMAND_INSTR(0x55, 0xab), 910 + ILI9881C_COMMAND_INSTR(0x56, 0x01), 911 + ILI9881C_COMMAND_INSTR(0x57, 0x23), 912 + ILI9881C_COMMAND_INSTR(0x58, 0x45), 913 + ILI9881C_COMMAND_INSTR(0x59, 0x67), 914 + ILI9881C_COMMAND_INSTR(0x5a, 0x89), 915 + ILI9881C_COMMAND_INSTR(0x5b, 0xab), 916 + ILI9881C_COMMAND_INSTR(0x5c, 0xcd), 917 + ILI9881C_COMMAND_INSTR(0x5d, 0xef), 918 + 919 + ILI9881C_COMMAND_INSTR(0x5e, 0x11), 920 + ILI9881C_COMMAND_INSTR(0x5f, 0x02), 921 + ILI9881C_COMMAND_INSTR(0x60, 0x00), 922 + ILI9881C_COMMAND_INSTR(0x61, 0x01), 923 + ILI9881C_COMMAND_INSTR(0x62, 0x0D), 924 + ILI9881C_COMMAND_INSTR(0x63, 0x0C), 925 + ILI9881C_COMMAND_INSTR(0x64, 0x0F), 926 + ILI9881C_COMMAND_INSTR(0x65, 0x0E), 927 + ILI9881C_COMMAND_INSTR(0x66, 0x06), 928 + ILI9881C_COMMAND_INSTR(0x67, 0x07), 929 + ILI9881C_COMMAND_INSTR(0x68, 0x02), 930 + ILI9881C_COMMAND_INSTR(0x69, 0x02), 931 + ILI9881C_COMMAND_INSTR(0x6a, 0x08), 932 + ILI9881C_COMMAND_INSTR(0x6b, 0x02), 933 + ILI9881C_COMMAND_INSTR(0x6c, 0x02), 934 + ILI9881C_COMMAND_INSTR(0x6d, 0x02), 935 + ILI9881C_COMMAND_INSTR(0x6e, 0x02), 936 + ILI9881C_COMMAND_INSTR(0x6f, 0x02), 937 + ILI9881C_COMMAND_INSTR(0x70, 0x02), 938 + ILI9881C_COMMAND_INSTR(0x71, 0x02), 939 + ILI9881C_COMMAND_INSTR(0x72, 0x02), 940 + ILI9881C_COMMAND_INSTR(0x73, 0x02), 941 + ILI9881C_COMMAND_INSTR(0x74, 0x02), 942 + ILI9881C_COMMAND_INSTR(0x75, 0x02), 943 + ILI9881C_COMMAND_INSTR(0x76, 0x00), 944 + ILI9881C_COMMAND_INSTR(0x77, 0x01), 945 + ILI9881C_COMMAND_INSTR(0x78, 0x0D), 946 + ILI9881C_COMMAND_INSTR(0x79, 0x0C), 947 + ILI9881C_COMMAND_INSTR(0x7a, 0x0F), 948 + ILI9881C_COMMAND_INSTR(0x7b, 0x0E), 949 + ILI9881C_COMMAND_INSTR(0x7c, 0x06), 950 + ILI9881C_COMMAND_INSTR(0x7d, 0x07), 951 + ILI9881C_COMMAND_INSTR(0x7e, 0x02), 952 + ILI9881C_COMMAND_INSTR(0x7f, 0x02), 953 + ILI9881C_COMMAND_INSTR(0x80, 0x08), 954 + ILI9881C_COMMAND_INSTR(0x81, 0x02), 955 + ILI9881C_COMMAND_INSTR(0x82, 0x02), 956 + ILI9881C_COMMAND_INSTR(0x83, 0x02), 957 + ILI9881C_COMMAND_INSTR(0x84, 0x02), 958 + ILI9881C_COMMAND_INSTR(0x85, 0x02), 959 + ILI9881C_COMMAND_INSTR(0x86, 0x02), 960 + ILI9881C_COMMAND_INSTR(0x87, 0x02), 961 + ILI9881C_COMMAND_INSTR(0x88, 0x02), 962 + ILI9881C_COMMAND_INSTR(0x89, 0x02), 963 + ILI9881C_COMMAND_INSTR(0x8A, 0x02), 964 + 965 + ILI9881C_SWITCH_PAGE_INSTR(4), 966 + ILI9881C_COMMAND_INSTR(0x6c, 0x15), 967 + ILI9881C_COMMAND_INSTR(0x6e, 0x30), 968 + ILI9881C_COMMAND_INSTR(0x6f, 0x33), 969 + ILI9881C_COMMAND_INSTR(0x8d, 0x15), 970 + ILI9881C_COMMAND_INSTR(0x3a, 0xa4), 971 + ILI9881C_COMMAND_INSTR(0x87, 0xba), 972 + ILI9881C_COMMAND_INSTR(0x26, 0x76), 973 + ILI9881C_COMMAND_INSTR(0xb2, 0xd1), 974 + 975 + ILI9881C_SWITCH_PAGE_INSTR(1), 976 + ILI9881C_COMMAND_INSTR(0x22, 0x0A), 977 + ILI9881C_COMMAND_INSTR(0x31, 0x0B), 978 + ILI9881C_COMMAND_INSTR(0x50, 0xa5), 979 + ILI9881C_COMMAND_INSTR(0x51, 0xa0), 980 + ILI9881C_COMMAND_INSTR(0x53, 0x70), 981 + ILI9881C_COMMAND_INSTR(0x55, 0x7A), 982 + ILI9881C_COMMAND_INSTR(0x60, 0x14), 983 + 984 + ILI9881C_COMMAND_INSTR(0xA0, 0x00), 985 + ILI9881C_COMMAND_INSTR(0xA1, 0x53), 986 + ILI9881C_COMMAND_INSTR(0xA2, 0x50), 987 + ILI9881C_COMMAND_INSTR(0xA3, 0x20), 988 + ILI9881C_COMMAND_INSTR(0xA4, 0x27), 989 + ILI9881C_COMMAND_INSTR(0xA5, 0x33), 990 + ILI9881C_COMMAND_INSTR(0xA6, 0x25), 991 + ILI9881C_COMMAND_INSTR(0xA7, 0x25), 992 + ILI9881C_COMMAND_INSTR(0xA8, 0xD4), 993 + ILI9881C_COMMAND_INSTR(0xA9, 0x1A), 994 + ILI9881C_COMMAND_INSTR(0xAA, 0x2B), 995 + ILI9881C_COMMAND_INSTR(0xAB, 0xB5), 996 + ILI9881C_COMMAND_INSTR(0xAC, 0x19), 997 + ILI9881C_COMMAND_INSTR(0xAD, 0x18), 998 + ILI9881C_COMMAND_INSTR(0xAE, 0x53), 999 + ILI9881C_COMMAND_INSTR(0xAF, 0x1A), 1000 + ILI9881C_COMMAND_INSTR(0xB0, 0x25), 1001 + ILI9881C_COMMAND_INSTR(0xB1, 0x62), 1002 + ILI9881C_COMMAND_INSTR(0xB2, 0x6A), 1003 + ILI9881C_COMMAND_INSTR(0xB3, 0x31), 1004 + 1005 + ILI9881C_COMMAND_INSTR(0xC0, 0x00), 1006 + ILI9881C_COMMAND_INSTR(0xC1, 0x53), 1007 + ILI9881C_COMMAND_INSTR(0xC2, 0x50), 1008 + ILI9881C_COMMAND_INSTR(0xC3, 0x20), 1009 + ILI9881C_COMMAND_INSTR(0xC4, 0x27), 1010 + ILI9881C_COMMAND_INSTR(0xC5, 0x33), 1011 + ILI9881C_COMMAND_INSTR(0xC6, 0x25), 1012 + ILI9881C_COMMAND_INSTR(0xC7, 0x25), 1013 + ILI9881C_COMMAND_INSTR(0xC8, 0xD4), 1014 + ILI9881C_COMMAND_INSTR(0xC9, 0x1A), 1015 + ILI9881C_COMMAND_INSTR(0xCA, 0x2B), 1016 + ILI9881C_COMMAND_INSTR(0xCB, 0xB5), 1017 + ILI9881C_COMMAND_INSTR(0xCC, 0x19), 1018 + ILI9881C_COMMAND_INSTR(0xCD, 0x18), 1019 + ILI9881C_COMMAND_INSTR(0xCE, 0x53), 1020 + ILI9881C_COMMAND_INSTR(0xCF, 0x1A), 1021 + ILI9881C_COMMAND_INSTR(0xD0, 0x25), 1022 + ILI9881C_COMMAND_INSTR(0xD1, 0x62), 1023 + ILI9881C_COMMAND_INSTR(0xD2, 0x6A), 1024 + ILI9881C_COMMAND_INSTR(0xD3, 0x31), 1025 + ILI9881C_SWITCH_PAGE_INSTR(0), 1026 + ILI9881C_COMMAND_INSTR(MIPI_DCS_WRITE_CONTROL_DISPLAY, 0x2c), 1027 + ILI9881C_COMMAND_INSTR(MIPI_DCS_WRITE_POWER_SAVE, 0x00), 1028 + }; 1029 + 833 1030 static inline struct ili9881c *panel_to_ili9881c(struct drm_panel *panel) 834 1031 { 835 1032 return container_of(panel, struct ili9881c, panel); ··· 1211 1014 .height_mm = 121, 1212 1015 }; 1213 1016 1017 + static const struct drm_display_mode am8001280g_default_mode = { 1018 + .clock = 67911, 1019 + 1020 + .hdisplay = 800, 1021 + .hsync_start = 800 + 20, 1022 + .hsync_end = 800 + 20 + 32, 1023 + .htotal = 800 + 20 + 32 + 20, 1024 + 1025 + .vdisplay = 1280, 1026 + .vsync_start = 1280 + 6, 1027 + .vsync_end = 1280 + 6 + 8, 1028 + .vtotal = 1280 + 6 + 8 + 4, 1029 + 1030 + .width_mm = 94, 1031 + .height_mm = 151, 1032 + }; 1033 + 1214 1034 static int ili9881c_get_modes(struct drm_panel *panel, 1215 1035 struct drm_connector *connector) 1216 1036 { ··· 1308 1094 return ret; 1309 1095 } 1310 1096 1097 + ctx->panel.prepare_prev_first = true; 1098 + 1311 1099 ret = drm_panel_of_backlight(&ctx->panel); 1312 1100 if (ret) 1313 1101 return ret; ··· 1361 1145 MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET, 1362 1146 }; 1363 1147 1148 + static const struct ili9881c_desc am8001280g_desc = { 1149 + .init = am8001280g_init, 1150 + .init_length = ARRAY_SIZE(am8001280g_init), 1151 + .mode = &am8001280g_default_mode, 1152 + .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 1153 + MIPI_DSI_CLOCK_NON_CONTINUOUS | MIPI_DSI_MODE_LPM, 1154 + }; 1155 + 1364 1156 static const struct of_device_id ili9881c_of_match[] = { 1365 1157 { .compatible = "bananapi,lhr050h41", .data = &lhr050h41_desc }, 1366 1158 { .compatible = "feixin,k101-im2byl02", .data = &k101_im2byl02_desc }, 1367 1159 { .compatible = "tdo,tl050hdv35", .data = &tl050hdv35_desc }, 1368 1160 { .compatible = "wanchanglong,w552946aba", .data = &w552946aba_desc }, 1161 + { .compatible = "ampire,am8001280g", .data = &am8001280g_desc }, 1369 1162 { } 1370 1163 }; 1371 1164 MODULE_DEVICE_TABLE(of, ili9881c_of_match);
+62
drivers/gpu/drm/panel/panel-simple.c
··· 1324 1324 }, 1325 1325 }; 1326 1326 1327 + static const struct drm_display_mode boe_bp101wx1_100_mode = { 1328 + .clock = 78945, 1329 + .hdisplay = 1280, 1330 + .hsync_start = 1280 + 0, 1331 + .hsync_end = 1280 + 0 + 2, 1332 + .htotal = 1280 + 62 + 0 + 2, 1333 + .vdisplay = 800, 1334 + .vsync_start = 800 + 8, 1335 + .vsync_end = 800 + 8 + 2, 1336 + .vtotal = 800 + 6 + 8 + 2, 1337 + }; 1338 + 1339 + static const struct panel_desc boe_bp101wx1_100 = { 1340 + .modes = &boe_bp101wx1_100_mode, 1341 + .num_modes = 1, 1342 + .bpc = 8, 1343 + .size = { 1344 + .width = 217, 1345 + .height = 136, 1346 + }, 1347 + .delay = { 1348 + .enable = 50, 1349 + .disable = 50, 1350 + }, 1351 + .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA, 1352 + .bus_flags = DRM_BUS_FLAG_DE_HIGH, 1353 + .connector_type = DRM_MODE_CONNECTOR_LVDS, 1354 + }; 1355 + 1327 1356 static const struct display_timing boe_ev121wxm_n10_1850_timing = { 1328 1357 .pixelclock = { 69922000, 71000000, 72293000 }, 1329 1358 .hactive = { 1280, 1280, 1280 }, ··· 2000 1971 .bus_format = MEDIA_BUS_FMT_RGB888_1X24, 2001 1972 .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE, 2002 1973 .connector_type = DRM_MODE_CONNECTOR_DPI, 1974 + }; 1975 + 1976 + static const struct display_timing evervision_vgg644804_timing = { 1977 + .pixelclock = { 25175000, 25175000, 25175000 }, 1978 + .hactive = { 640, 640, 640 }, 1979 + .hfront_porch = { 16, 16, 16 }, 1980 + .hback_porch = { 82, 114, 170 }, 1981 + .hsync_len = { 5, 30, 30 }, 1982 + .vactive = { 480, 480, 480 }, 1983 + .vfront_porch = { 10, 10, 10 }, 1984 + .vback_porch = { 30, 32, 34 }, 1985 + .vsync_len = { 1, 3, 5 }, 1986 + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW | 1987 + DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE | 1988 + DISPLAY_FLAGS_SYNC_POSEDGE, 1989 + }; 1990 + 1991 + static const struct panel_desc evervision_vgg644804 = { 1992 + .timings = &evervision_vgg644804_timing, 1993 + .num_timings = 1, 1994 + .bpc = 8, 1995 + .size = { 1996 + .width = 115, 1997 + .height = 86, 1998 + }, 1999 + .bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG, 2000 + .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE, 2003 2001 }; 2004 2002 2005 2003 static const struct display_timing evervision_vgg804821_timing = { ··· 4310 4254 .compatible = "bananapi,s070wv20-ct16", 4311 4255 .data = &bananapi_s070wv20_ct16, 4312 4256 }, { 4257 + .compatible = "boe,bp101wx1-100", 4258 + .data = &boe_bp101wx1_100, 4259 + }, { 4313 4260 .compatible = "boe,ev121wxm-n10-1850", 4314 4261 .data = &boe_ev121wxm_n10_1850, 4315 4262 }, { ··· 4393 4334 }, { 4394 4335 .compatible = "eink,vb3300-kca", 4395 4336 .data = &eink_vb3300_kca, 4337 + }, { 4338 + .compatible = "evervision,vgg644804", 4339 + .data = &evervision_vgg644804, 4396 4340 }, { 4397 4341 .compatible = "evervision,vgg804821", 4398 4342 .data = &evervision_vgg804821,
+3
drivers/gpu/drm/panfrost/panfrost_device.c
··· 421 421 return -EBUSY; 422 422 423 423 panfrost_devfreq_suspend(pfdev); 424 + panfrost_job_suspend_irq(pfdev); 425 + panfrost_mmu_suspend_irq(pfdev); 426 + panfrost_gpu_suspend_irq(pfdev); 424 427 panfrost_gpu_power_off(pfdev); 425 428 426 429 return 0;
+10
drivers/gpu/drm/panfrost/panfrost_device.h
··· 25 25 #define NUM_JOB_SLOTS 3 26 26 #define MAX_PM_DOMAINS 5 27 27 28 + enum panfrost_drv_comp_bits { 29 + PANFROST_COMP_BIT_GPU, 30 + PANFROST_COMP_BIT_JOB, 31 + PANFROST_COMP_BIT_MMU, 32 + PANFROST_COMP_BIT_MAX 33 + }; 34 + 28 35 /** 29 36 * enum panfrost_gpu_pm - Supported kernel power management features 30 37 * @GPU_PM_CLK_DIS: Allow disabling clocks during system suspend ··· 101 94 struct device *dev; 102 95 struct drm_device *ddev; 103 96 struct platform_device *pdev; 97 + int gpu_irq; 98 + int mmu_irq; 104 99 105 100 void __iomem *iomem; 106 101 struct clk *clock; ··· 116 107 117 108 struct panfrost_features features; 118 109 const struct panfrost_compatible *comp; 110 + DECLARE_BITMAP(is_suspended, PANFROST_COMP_BIT_MAX); 119 111 120 112 spinlock_t as_lock; 121 113 unsigned long as_in_use_mask;
+29 -11
drivers/gpu/drm/panfrost/panfrost_gpu.c
··· 22 22 static irqreturn_t panfrost_gpu_irq_handler(int irq, void *data) 23 23 { 24 24 struct panfrost_device *pfdev = data; 25 - u32 state = gpu_read(pfdev, GPU_INT_STAT); 26 - u32 fault_status = gpu_read(pfdev, GPU_FAULT_STATUS); 25 + u32 fault_status, state; 27 26 27 + if (test_bit(PANFROST_COMP_BIT_GPU, pfdev->is_suspended)) 28 + return IRQ_NONE; 29 + 30 + fault_status = gpu_read(pfdev, GPU_FAULT_STATUS); 31 + state = gpu_read(pfdev, GPU_INT_STAT); 28 32 if (!state) 29 33 return IRQ_NONE; 30 34 ··· 65 61 gpu_write(pfdev, GPU_INT_MASK, 0); 66 62 gpu_write(pfdev, GPU_INT_CLEAR, GPU_IRQ_RESET_COMPLETED); 67 63 64 + clear_bit(PANFROST_COMP_BIT_GPU, pfdev->is_suspended); 65 + 68 66 gpu_write(pfdev, GPU_CMD, GPU_CMD_SOFT_RESET); 69 67 ret = readl_relaxed_poll_timeout(pfdev->iomem + GPU_INT_RAWSTAT, 70 68 val, val & GPU_IRQ_RESET_COMPLETED, 10, 10000); ··· 84 78 } 85 79 86 80 gpu_write(pfdev, GPU_INT_CLEAR, GPU_IRQ_MASK_ALL); 87 - gpu_write(pfdev, GPU_INT_MASK, GPU_IRQ_MASK_ALL); 81 + 82 + /* Only enable the interrupts we care about */ 83 + gpu_write(pfdev, GPU_INT_MASK, 84 + GPU_IRQ_MASK_ERROR | 85 + GPU_IRQ_PERFCNT_SAMPLE_COMPLETED | 86 + GPU_IRQ_CLEAN_CACHES_COMPLETED); 88 87 89 88 /* 90 89 * All in-flight jobs should have released their cycle ··· 436 425 437 426 void panfrost_gpu_power_off(struct panfrost_device *pfdev) 438 427 { 439 - u64 core_mask = panfrost_get_core_mask(pfdev); 440 428 int ret; 441 429 u32 val; 442 430 443 - gpu_write(pfdev, SHADER_PWROFF_LO, pfdev->features.shader_present & core_mask); 431 + gpu_write(pfdev, SHADER_PWROFF_LO, pfdev->features.shader_present); 444 432 ret = readl_relaxed_poll_timeout(pfdev->iomem + SHADER_PWRTRANS_LO, 445 433 val, !val, 1, 1000); 446 434 if (ret) ··· 451 441 if (ret) 452 442 dev_err(pfdev->dev, "tiler power transition timeout"); 453 443 454 - gpu_write(pfdev, L2_PWROFF_LO, pfdev->features.l2_present & core_mask); 444 + gpu_write(pfdev, L2_PWROFF_LO, pfdev->features.l2_present); 455 445 ret = readl_poll_timeout(pfdev->iomem + L2_PWRTRANS_LO, 456 446 val, !val, 0, 1000); 457 447 if (ret) 458 448 dev_err(pfdev->dev, "l2 power transition timeout"); 459 449 } 460 450 451 + void panfrost_gpu_suspend_irq(struct panfrost_device *pfdev) 452 + { 453 + set_bit(PANFROST_COMP_BIT_GPU, pfdev->is_suspended); 454 + 455 + gpu_write(pfdev, GPU_INT_MASK, 0); 456 + synchronize_irq(pfdev->gpu_irq); 457 + } 458 + 461 459 int panfrost_gpu_init(struct panfrost_device *pfdev) 462 460 { 463 - int err, irq; 461 + int err; 464 462 465 463 err = panfrost_gpu_soft_reset(pfdev); 466 464 if (err) ··· 483 465 484 466 dma_set_max_seg_size(pfdev->dev, UINT_MAX); 485 467 486 - irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "gpu"); 487 - if (irq < 0) 488 - return irq; 468 + pfdev->gpu_irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "gpu"); 469 + if (pfdev->gpu_irq < 0) 470 + return pfdev->gpu_irq; 489 471 490 - err = devm_request_irq(pfdev->dev, irq, panfrost_gpu_irq_handler, 472 + err = devm_request_irq(pfdev->dev, pfdev->gpu_irq, panfrost_gpu_irq_handler, 491 473 IRQF_SHARED, KBUILD_MODNAME "-gpu", pfdev); 492 474 if (err) { 493 475 dev_err(pfdev->dev, "failed to request gpu irq");
+1
drivers/gpu/drm/panfrost/panfrost_gpu.h
··· 15 15 int panfrost_gpu_soft_reset(struct panfrost_device *pfdev); 16 16 void panfrost_gpu_power_on(struct panfrost_device *pfdev); 17 17 void panfrost_gpu_power_off(struct panfrost_device *pfdev); 18 + void panfrost_gpu_suspend_irq(struct panfrost_device *pfdev); 18 19 19 20 void panfrost_cycle_counter_get(struct panfrost_device *pfdev); 20 21 void panfrost_cycle_counter_put(struct panfrost_device *pfdev);
+22 -4
drivers/gpu/drm/panfrost/panfrost_job.c
··· 405 405 int j; 406 406 u32 irq_mask = 0; 407 407 408 + clear_bit(PANFROST_COMP_BIT_JOB, pfdev->is_suspended); 409 + 408 410 for (j = 0; j < NUM_JOB_SLOTS; j++) { 409 411 irq_mask |= MK_JS_MASK(j); 410 412 } 411 413 412 414 job_write(pfdev, JOB_INT_CLEAR, irq_mask); 413 415 job_write(pfdev, JOB_INT_MASK, irq_mask); 416 + } 417 + 418 + void panfrost_job_suspend_irq(struct panfrost_device *pfdev) 419 + { 420 + set_bit(PANFROST_COMP_BIT_JOB, pfdev->is_suspended); 421 + 422 + job_write(pfdev, JOB_INT_MASK, 0); 423 + synchronize_irq(pfdev->js->irq); 414 424 } 415 425 416 426 static void panfrost_job_handle_err(struct panfrost_device *pfdev, ··· 802 792 struct panfrost_device *pfdev = data; 803 793 804 794 panfrost_job_handle_irqs(pfdev); 805 - job_write(pfdev, JOB_INT_MASK, 806 - GENMASK(16 + NUM_JOB_SLOTS - 1, 16) | 807 - GENMASK(NUM_JOB_SLOTS - 1, 0)); 795 + 796 + /* Enable interrupts only if we're not about to get suspended */ 797 + if (!test_bit(PANFROST_COMP_BIT_JOB, pfdev->is_suspended)) 798 + job_write(pfdev, JOB_INT_MASK, 799 + GENMASK(16 + NUM_JOB_SLOTS - 1, 16) | 800 + GENMASK(NUM_JOB_SLOTS - 1, 0)); 801 + 808 802 return IRQ_HANDLED; 809 803 } 810 804 811 805 static irqreturn_t panfrost_job_irq_handler(int irq, void *data) 812 806 { 813 807 struct panfrost_device *pfdev = data; 814 - u32 status = job_read(pfdev, JOB_INT_STAT); 808 + u32 status; 815 809 810 + if (test_bit(PANFROST_COMP_BIT_JOB, pfdev->is_suspended)) 811 + return IRQ_NONE; 812 + 813 + status = job_read(pfdev, JOB_INT_STAT); 816 814 if (!status) 817 815 return IRQ_NONE; 818 816
+1
drivers/gpu/drm/panfrost/panfrost_job.h
··· 47 47 int panfrost_job_push(struct panfrost_job *job); 48 48 void panfrost_job_put(struct panfrost_job *job); 49 49 void panfrost_job_enable_interrupts(struct panfrost_device *pfdev); 50 + void panfrost_job_suspend_irq(struct panfrost_device *pfdev); 50 51 int panfrost_job_is_idle(struct panfrost_device *pfdev); 51 52 52 53 #endif
+24 -8
drivers/gpu/drm/panfrost/panfrost_mmu.c
··· 231 231 { 232 232 struct panfrost_mmu *mmu, *mmu_tmp; 233 233 234 + clear_bit(PANFROST_COMP_BIT_MMU, pfdev->is_suspended); 235 + 234 236 spin_lock(&pfdev->as_lock); 235 237 236 238 pfdev->as_alloc_mask = 0; ··· 672 670 { 673 671 struct panfrost_device *pfdev = data; 674 672 673 + if (test_bit(PANFROST_COMP_BIT_MMU, pfdev->is_suspended)) 674 + return IRQ_NONE; 675 + 675 676 if (!mmu_read(pfdev, MMU_INT_STAT)) 676 677 return IRQ_NONE; 677 678 ··· 749 744 status = mmu_read(pfdev, MMU_INT_RAWSTAT) & ~pfdev->as_faulty_mask; 750 745 } 751 746 752 - spin_lock(&pfdev->as_lock); 753 - mmu_write(pfdev, MMU_INT_MASK, ~pfdev->as_faulty_mask); 754 - spin_unlock(&pfdev->as_lock); 747 + /* Enable interrupts only if we're not about to get suspended */ 748 + if (!test_bit(PANFROST_COMP_BIT_MMU, pfdev->is_suspended)) { 749 + spin_lock(&pfdev->as_lock); 750 + mmu_write(pfdev, MMU_INT_MASK, ~pfdev->as_faulty_mask); 751 + spin_unlock(&pfdev->as_lock); 752 + } 755 753 756 754 return IRQ_HANDLED; 757 755 }; 758 756 759 757 int panfrost_mmu_init(struct panfrost_device *pfdev) 760 758 { 761 - int err, irq; 759 + int err; 762 760 763 - irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "mmu"); 764 - if (irq < 0) 765 - return irq; 761 + pfdev->mmu_irq = platform_get_irq_byname(to_platform_device(pfdev->dev), "mmu"); 762 + if (pfdev->mmu_irq < 0) 763 + return pfdev->mmu_irq; 766 764 767 - err = devm_request_threaded_irq(pfdev->dev, irq, 765 + err = devm_request_threaded_irq(pfdev->dev, pfdev->mmu_irq, 768 766 panfrost_mmu_irq_handler, 769 767 panfrost_mmu_irq_handler_thread, 770 768 IRQF_SHARED, KBUILD_MODNAME "-mmu", ··· 784 776 void panfrost_mmu_fini(struct panfrost_device *pfdev) 785 777 { 786 778 mmu_write(pfdev, MMU_INT_MASK, 0); 779 + } 780 + 781 + void panfrost_mmu_suspend_irq(struct panfrost_device *pfdev) 782 + { 783 + set_bit(PANFROST_COMP_BIT_MMU, pfdev->is_suspended); 784 + 785 + mmu_write(pfdev, MMU_INT_MASK, 0); 786 + synchronize_irq(pfdev->mmu_irq); 787 787 }
+1
drivers/gpu/drm/panfrost/panfrost_mmu.h
··· 14 14 int panfrost_mmu_init(struct panfrost_device *pfdev); 15 15 void panfrost_mmu_fini(struct panfrost_device *pfdev); 16 16 void panfrost_mmu_reset(struct panfrost_device *pfdev); 17 + void panfrost_mmu_suspend_irq(struct panfrost_device *pfdev); 17 18 18 19 u32 panfrost_mmu_as_get(struct panfrost_device *pfdev, struct panfrost_mmu *mmu); 19 20 void panfrost_mmu_as_put(struct panfrost_device *pfdev, struct panfrost_mmu *mmu);
+6 -8
drivers/gpu/drm/qxl/qxl_display.c
··· 485 485 static int qxl_primary_apply_cursor(struct qxl_device *qdev, 486 486 struct drm_plane_state *plane_state) 487 487 { 488 - struct drm_framebuffer *fb = plane_state->fb; 489 488 struct qxl_crtc *qcrtc = to_qxl_crtc(plane_state->crtc); 490 489 struct qxl_cursor_cmd *cmd; 491 490 struct qxl_release *release; ··· 509 510 510 511 cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release); 511 512 cmd->type = QXL_CURSOR_SET; 512 - cmd->u.set.position.x = plane_state->crtc_x + fb->hot_x; 513 - cmd->u.set.position.y = plane_state->crtc_y + fb->hot_y; 513 + cmd->u.set.position.x = plane_state->crtc_x + plane_state->hotspot_x; 514 + cmd->u.set.position.y = plane_state->crtc_y + plane_state->hotspot_y; 514 515 515 516 cmd->u.set.shape = qxl_bo_physical_address(qdev, qcrtc->cursor_bo, 0); 516 517 ··· 530 531 static int qxl_primary_move_cursor(struct qxl_device *qdev, 531 532 struct drm_plane_state *plane_state) 532 533 { 533 - struct drm_framebuffer *fb = plane_state->fb; 534 534 struct qxl_crtc *qcrtc = to_qxl_crtc(plane_state->crtc); 535 535 struct qxl_cursor_cmd *cmd; 536 536 struct qxl_release *release; ··· 552 554 553 555 cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release); 554 556 cmd->type = QXL_CURSOR_MOVE; 555 - cmd->u.position.x = plane_state->crtc_x + fb->hot_x; 556 - cmd->u.position.y = plane_state->crtc_y + fb->hot_y; 557 + cmd->u.position.x = plane_state->crtc_x + plane_state->hotspot_x; 558 + cmd->u.position.y = plane_state->crtc_y + plane_state->hotspot_y; 557 559 qxl_release_unmap(qdev, release, &cmd->release_info); 558 560 559 561 qxl_release_fence_buffer_objects(release); ··· 849 851 struct qxl_bo *old_cursor_bo = qcrtc->cursor_bo; 850 852 851 853 qcrtc->cursor_bo = qxl_create_cursor(qdev, user_bo, 852 - new_state->fb->hot_x, 853 - new_state->fb->hot_y); 854 + new_state->hotspot_x, 855 + new_state->hotspot_y); 854 856 qxl_free_cursor(old_cursor_bo); 855 857 } 856 858
+1 -1
drivers/gpu/drm/qxl/qxl_drv.c
··· 285 285 }; 286 286 287 287 static struct drm_driver qxl_driver = { 288 - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, 288 + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_CURSOR_HOTSPOT, 289 289 290 290 .dumb_create = qxl_mode_dumb_create, 291 291 .dumb_map_offset = drm_gem_ttm_dumb_map_offset,
-7
drivers/gpu/drm/qxl/qxl_drv.h
··· 119 119 120 120 #define to_qxl_crtc(x) container_of(x, struct qxl_crtc, base) 121 121 #define drm_connector_to_qxl_output(x) container_of(x, struct qxl_output, base) 122 - #define drm_encoder_to_qxl_output(x) container_of(x, struct qxl_output, enc) 123 122 124 123 struct qxl_mman { 125 124 struct ttm_device bdev; ··· 255 256 256 257 #define to_qxl(dev) container_of(dev, struct qxl_device, ddev) 257 258 258 - int qxl_debugfs_fence_init(struct qxl_device *rdev); 259 - 260 259 int qxl_device_init(struct qxl_device *qdev, struct pci_dev *pdev); 261 260 void qxl_device_fini(struct qxl_device *qdev); 262 261 ··· 340 343 struct qxl_drm_image **image_ptr, 341 344 int height, int stride); 342 345 void qxl_image_free_objects(struct qxl_device *qdev, struct qxl_drm_image *dimage); 343 - 344 - void qxl_update_screen(struct qxl_device *qxl); 345 346 346 347 /* qxl io operations (qxl_cmd.c) */ 347 348 ··· 440 445 441 446 int qxl_bo_check_id(struct qxl_device *qdev, struct qxl_bo *bo); 442 447 443 - struct qxl_drv_surface * 444 - qxl_surface_lookup(struct drm_device *dev, int surface_id); 445 448 void qxl_surface_evict(struct qxl_device *qdev, struct qxl_bo *surf, bool freeing); 446 449 447 450 /* qxl_ioctl.c */
-1
drivers/gpu/drm/radeon/radeon_drv.h
··· 33 33 34 34 #include <linux/firmware.h> 35 35 #include <linux/platform_device.h> 36 - #include <drm/drm_legacy.h> 37 36 38 37 #include "radeon_family.h" 39 38
-1
drivers/gpu/drm/renesas/shmobile/shmob_drm_plane.c
··· 14 14 #include <drm/drm_fourcc.h> 15 15 #include <drm/drm_framebuffer.h> 16 16 #include <drm/drm_gem_dma_helper.h> 17 - #include <drm/drm_plane_helper.h> 18 17 19 18 #include "shmob_drm_drv.h" 20 19 #include "shmob_drm_kms.h"
+9 -5
drivers/gpu/drm/scheduler/sched_entity.c
··· 81 81 */ 82 82 pr_warn("%s: called with uninitialized scheduler\n", __func__); 83 83 } else if (num_sched_list) { 84 - /* The "priority" of an entity cannot exceed the number 85 - * of run-queues of a scheduler. 84 + /* The "priority" of an entity cannot exceed the number of run-queues of a 85 + * scheduler. Protect against num_rqs being 0, by converting to signed. Choose 86 + * the lowest priority available. 86 87 */ 87 - if (entity->priority >= sched_list[0]->num_rqs) 88 - entity->priority = max_t(u32, sched_list[0]->num_rqs, 89 - DRM_SCHED_PRIORITY_MIN); 88 + if (entity->priority >= sched_list[0]->num_rqs) { 89 + drm_err(sched_list[0], "entity with out-of-bounds priority:%u num_rqs:%u\n", 90 + entity->priority, sched_list[0]->num_rqs); 91 + entity->priority = max_t(s32, (s32) sched_list[0]->num_rqs - 1, 92 + (s32) DRM_SCHED_PRIORITY_KERNEL); 93 + } 90 94 entity->rq = sched_list[0]->sched_rq[entity->priority]; 91 95 } 92 96
+9 -11
drivers/gpu/drm/scheduler/sched_main.c
··· 1029 1029 void drm_sched_wakeup(struct drm_gpu_scheduler *sched, 1030 1030 struct drm_sched_entity *entity) 1031 1031 { 1032 - if (drm_sched_entity_is_ready(entity)) 1033 - if (drm_sched_can_queue(sched, entity)) 1034 - drm_sched_run_job_queue(sched); 1032 + if (drm_sched_can_queue(sched, entity)) 1033 + drm_sched_run_job_queue(sched); 1035 1034 } 1036 1035 1037 1036 /** ··· 1050 1051 struct drm_sched_entity *entity; 1051 1052 int i; 1052 1053 1053 - /* Kernel run queue has higher priority than normal run queue*/ 1054 - for (i = sched->num_rqs - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { 1054 + /* Start with the highest priority. 1055 + */ 1056 + for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) { 1055 1057 entity = drm_sched_policy == DRM_SCHED_POLICY_FIFO ? 1056 1058 drm_sched_rq_select_entity_fifo(sched, sched->sched_rq[i]) : 1057 1059 drm_sched_rq_select_entity_rr(sched, sched->sched_rq[i]); ··· 1291 1291 if (!sched->sched_rq) 1292 1292 goto Out_free; 1293 1293 sched->num_rqs = num_rqs; 1294 - for (i = DRM_SCHED_PRIORITY_MIN; i < sched->num_rqs; i++) { 1294 + for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) { 1295 1295 sched->sched_rq[i] = kzalloc(sizeof(*sched->sched_rq[i]), GFP_KERNEL); 1296 1296 if (!sched->sched_rq[i]) 1297 1297 goto Out_unroll; ··· 1312 1312 sched->ready = true; 1313 1313 return 0; 1314 1314 Out_unroll: 1315 - for (--i ; i >= DRM_SCHED_PRIORITY_MIN; i--) 1315 + for (--i ; i >= DRM_SCHED_PRIORITY_KERNEL; i--) 1316 1316 kfree(sched->sched_rq[i]); 1317 1317 Out_free: 1318 1318 kfree(sched->sched_rq); ··· 1338 1338 1339 1339 drm_sched_wqueue_stop(sched); 1340 1340 1341 - for (i = sched->num_rqs - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { 1341 + for (i = DRM_SCHED_PRIORITY_KERNEL; i < sched->num_rqs; i++) { 1342 1342 struct drm_sched_rq *rq = sched->sched_rq[i]; 1343 1343 1344 1344 spin_lock(&rq->lock); ··· 1390 1390 if (bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) { 1391 1391 atomic_inc(&bad->karma); 1392 1392 1393 - for (i = DRM_SCHED_PRIORITY_MIN; 1394 - i < min_t(typeof(sched->num_rqs), sched->num_rqs, DRM_SCHED_PRIORITY_KERNEL); 1395 - i++) { 1393 + for (i = DRM_SCHED_PRIORITY_HIGH; i < sched->num_rqs; i++) { 1396 1394 struct drm_sched_rq *rq = sched->sched_rq[i]; 1397 1395 1398 1396 spin_lock(&rq->lock);
-1
drivers/gpu/drm/solomon/ssd130x.h
··· 17 17 #include <drm/drm_crtc.h> 18 18 #include <drm/drm_drv.h> 19 19 #include <drm/drm_encoder.h> 20 - #include <drm/drm_plane_helper.h> 21 20 22 21 #include <linux/regmap.h> 23 22
+1
drivers/gpu/drm/tests/Makefile
··· 13 13 drm_format_helper_test.o \ 14 14 drm_format_test.o \ 15 15 drm_framebuffer_test.o \ 16 + drm_gem_shmem_test.o \ 16 17 drm_managed_test.o \ 17 18 drm_mm_test.o \ 18 19 drm_modes_test.o \
+383
drivers/gpu/drm/tests/drm_gem_shmem_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * KUnit test suite for GEM objects backed by shmem buffers 4 + * 5 + * Copyright (C) 2023 Red Hat, Inc. 6 + * 7 + * Author: Marco Pagani <marpagan@redhat.com> 8 + */ 9 + 10 + #include <linux/dma-buf.h> 11 + #include <linux/iosys-map.h> 12 + #include <linux/sizes.h> 13 + 14 + #include <kunit/test.h> 15 + 16 + #include <drm/drm_device.h> 17 + #include <drm/drm_drv.h> 18 + #include <drm/drm_gem.h> 19 + #include <drm/drm_gem_shmem_helper.h> 20 + #include <drm/drm_kunit_helpers.h> 21 + 22 + #define TEST_SIZE SZ_1M 23 + #define TEST_BYTE 0xae 24 + 25 + /* 26 + * Wrappers to avoid an explicit type casting when passing action 27 + * functions to kunit_add_action(). 28 + */ 29 + static void kfree_wrapper(void *ptr) 30 + { 31 + const void *obj = ptr; 32 + 33 + kfree(obj); 34 + } 35 + 36 + static void sg_free_table_wrapper(void *ptr) 37 + { 38 + struct sg_table *sgt = ptr; 39 + 40 + sg_free_table(sgt); 41 + } 42 + 43 + static void drm_gem_shmem_free_wrapper(void *ptr) 44 + { 45 + struct drm_gem_shmem_object *shmem = ptr; 46 + 47 + drm_gem_shmem_free(shmem); 48 + } 49 + 50 + /* 51 + * Test creating a shmem GEM object backed by shmem buffer. The test 52 + * case succeeds if the GEM object is successfully allocated with the 53 + * shmem file node and object functions attributes set, and the size 54 + * attribute is equal to the correct size. 55 + */ 56 + static void drm_gem_shmem_test_obj_create(struct kunit *test) 57 + { 58 + struct drm_device *drm_dev = test->priv; 59 + struct drm_gem_shmem_object *shmem; 60 + 61 + shmem = drm_gem_shmem_create(drm_dev, TEST_SIZE); 62 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, shmem); 63 + KUNIT_EXPECT_EQ(test, shmem->base.size, TEST_SIZE); 64 + KUNIT_EXPECT_NOT_NULL(test, shmem->base.filp); 65 + KUNIT_EXPECT_NOT_NULL(test, shmem->base.funcs); 66 + 67 + drm_gem_shmem_free(shmem); 68 + } 69 + 70 + /* 71 + * Test creating a shmem GEM object from a scatter/gather table exported 72 + * via a DMA-BUF. The test case succeed if the GEM object is successfully 73 + * created with the shmem file node attribute equal to NULL and the sgt 74 + * attribute pointing to the scatter/gather table that has been imported. 75 + */ 76 + static void drm_gem_shmem_test_obj_create_private(struct kunit *test) 77 + { 78 + struct drm_device *drm_dev = test->priv; 79 + struct drm_gem_shmem_object *shmem; 80 + struct drm_gem_object *gem_obj; 81 + struct dma_buf buf_mock; 82 + struct dma_buf_attachment attach_mock; 83 + struct sg_table *sgt; 84 + char *buf; 85 + int ret; 86 + 87 + /* Create a mock scatter/gather table */ 88 + buf = kunit_kzalloc(test, TEST_SIZE, GFP_KERNEL); 89 + KUNIT_ASSERT_NOT_NULL(test, buf); 90 + 91 + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); 92 + KUNIT_ASSERT_NOT_NULL(test, sgt); 93 + 94 + ret = kunit_add_action_or_reset(test, kfree_wrapper, sgt); 95 + KUNIT_ASSERT_EQ(test, ret, 0); 96 + 97 + ret = sg_alloc_table(sgt, 1, GFP_KERNEL); 98 + KUNIT_ASSERT_EQ(test, ret, 0); 99 + 100 + ret = kunit_add_action_or_reset(test, sg_free_table_wrapper, sgt); 101 + KUNIT_ASSERT_EQ(test, ret, 0); 102 + 103 + sg_init_one(sgt->sgl, buf, TEST_SIZE); 104 + 105 + /* Init a mock DMA-BUF */ 106 + buf_mock.size = TEST_SIZE; 107 + attach_mock.dmabuf = &buf_mock; 108 + 109 + gem_obj = drm_gem_shmem_prime_import_sg_table(drm_dev, &attach_mock, sgt); 110 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, gem_obj); 111 + KUNIT_EXPECT_EQ(test, gem_obj->size, TEST_SIZE); 112 + KUNIT_EXPECT_NULL(test, gem_obj->filp); 113 + KUNIT_EXPECT_NOT_NULL(test, gem_obj->funcs); 114 + 115 + /* The scatter/gather table will be freed by drm_gem_shmem_free */ 116 + kunit_remove_action(test, sg_free_table_wrapper, sgt); 117 + kunit_remove_action(test, kfree_wrapper, sgt); 118 + 119 + shmem = to_drm_gem_shmem_obj(gem_obj); 120 + KUNIT_EXPECT_PTR_EQ(test, shmem->sgt, sgt); 121 + 122 + drm_gem_shmem_free(shmem); 123 + } 124 + 125 + /* 126 + * Test pinning backing pages for a shmem GEM object. The test case 127 + * succeeds if a suitable number of backing pages are allocated, and 128 + * the pages table counter attribute is increased by one. 129 + */ 130 + static void drm_gem_shmem_test_pin_pages(struct kunit *test) 131 + { 132 + struct drm_device *drm_dev = test->priv; 133 + struct drm_gem_shmem_object *shmem; 134 + int i, ret; 135 + 136 + shmem = drm_gem_shmem_create(drm_dev, TEST_SIZE); 137 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, shmem); 138 + KUNIT_EXPECT_NULL(test, shmem->pages); 139 + KUNIT_EXPECT_EQ(test, shmem->pages_use_count, 0); 140 + 141 + ret = kunit_add_action_or_reset(test, drm_gem_shmem_free_wrapper, shmem); 142 + KUNIT_ASSERT_EQ(test, ret, 0); 143 + 144 + ret = drm_gem_shmem_pin(shmem); 145 + KUNIT_ASSERT_EQ(test, ret, 0); 146 + KUNIT_ASSERT_NOT_NULL(test, shmem->pages); 147 + KUNIT_EXPECT_EQ(test, shmem->pages_use_count, 1); 148 + 149 + for (i = 0; i < (shmem->base.size >> PAGE_SHIFT); i++) 150 + KUNIT_ASSERT_NOT_NULL(test, shmem->pages[i]); 151 + 152 + drm_gem_shmem_unpin(shmem); 153 + KUNIT_EXPECT_NULL(test, shmem->pages); 154 + KUNIT_EXPECT_EQ(test, shmem->pages_use_count, 0); 155 + } 156 + 157 + /* 158 + * Test creating a virtual mapping for a shmem GEM object. The test 159 + * case succeeds if the backing memory is mapped and the reference 160 + * counter for virtual mapping is increased by one. Moreover, the test 161 + * case writes and then reads a test pattern over the mapped memory. 162 + */ 163 + static void drm_gem_shmem_test_vmap(struct kunit *test) 164 + { 165 + struct drm_device *drm_dev = test->priv; 166 + struct drm_gem_shmem_object *shmem; 167 + struct iosys_map map; 168 + int ret, i; 169 + 170 + shmem = drm_gem_shmem_create(drm_dev, TEST_SIZE); 171 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, shmem); 172 + KUNIT_EXPECT_NULL(test, shmem->vaddr); 173 + KUNIT_EXPECT_EQ(test, shmem->vmap_use_count, 0); 174 + 175 + ret = kunit_add_action_or_reset(test, drm_gem_shmem_free_wrapper, shmem); 176 + KUNIT_ASSERT_EQ(test, ret, 0); 177 + 178 + ret = drm_gem_shmem_vmap(shmem, &map); 179 + KUNIT_ASSERT_EQ(test, ret, 0); 180 + KUNIT_ASSERT_NOT_NULL(test, shmem->vaddr); 181 + KUNIT_ASSERT_FALSE(test, iosys_map_is_null(&map)); 182 + KUNIT_EXPECT_EQ(test, shmem->vmap_use_count, 1); 183 + 184 + iosys_map_memset(&map, 0, TEST_BYTE, TEST_SIZE); 185 + for (i = 0; i < TEST_SIZE; i++) 186 + KUNIT_EXPECT_EQ(test, iosys_map_rd(&map, i, u8), TEST_BYTE); 187 + 188 + drm_gem_shmem_vunmap(shmem, &map); 189 + KUNIT_EXPECT_NULL(test, shmem->vaddr); 190 + KUNIT_EXPECT_EQ(test, shmem->vmap_use_count, 0); 191 + } 192 + 193 + /* 194 + * Test exporting a scatter/gather table of pinned pages suitable for 195 + * PRIME usage from a shmem GEM object. The test case succeeds if a 196 + * scatter/gather table large enough to accommodate the backing memory 197 + * is successfully exported. 198 + */ 199 + static void drm_gem_shmem_test_get_pages_sgt(struct kunit *test) 200 + { 201 + struct drm_device *drm_dev = test->priv; 202 + struct drm_gem_shmem_object *shmem; 203 + struct sg_table *sgt; 204 + struct scatterlist *sg; 205 + unsigned int si, len = 0; 206 + int ret; 207 + 208 + shmem = drm_gem_shmem_create(drm_dev, TEST_SIZE); 209 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, shmem); 210 + 211 + ret = kunit_add_action_or_reset(test, drm_gem_shmem_free_wrapper, shmem); 212 + KUNIT_ASSERT_EQ(test, ret, 0); 213 + 214 + ret = drm_gem_shmem_pin(shmem); 215 + KUNIT_ASSERT_EQ(test, ret, 0); 216 + 217 + sgt = drm_gem_shmem_get_sg_table(shmem); 218 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sgt); 219 + KUNIT_EXPECT_NULL(test, shmem->sgt); 220 + 221 + ret = kunit_add_action_or_reset(test, sg_free_table_wrapper, sgt); 222 + KUNIT_ASSERT_EQ(test, ret, 0); 223 + 224 + for_each_sgtable_sg(sgt, sg, si) { 225 + KUNIT_EXPECT_NOT_NULL(test, sg); 226 + len += sg->length; 227 + } 228 + 229 + KUNIT_EXPECT_GE(test, len, TEST_SIZE); 230 + } 231 + 232 + /* 233 + * Test pinning pages and exporting a scatter/gather table suitable for 234 + * driver usage from a shmem GEM object. The test case succeeds if the 235 + * backing pages are pinned and a scatter/gather table large enough to 236 + * accommodate the backing memory is successfully exported. 237 + */ 238 + static void drm_gem_shmem_test_get_sg_table(struct kunit *test) 239 + { 240 + struct drm_device *drm_dev = test->priv; 241 + struct drm_gem_shmem_object *shmem; 242 + struct sg_table *sgt; 243 + struct scatterlist *sg; 244 + unsigned int si, ret, len = 0; 245 + 246 + shmem = drm_gem_shmem_create(drm_dev, TEST_SIZE); 247 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, shmem); 248 + 249 + ret = kunit_add_action_or_reset(test, drm_gem_shmem_free_wrapper, shmem); 250 + KUNIT_ASSERT_EQ(test, ret, 0); 251 + 252 + /* The scatter/gather table will be freed by drm_gem_shmem_free */ 253 + sgt = drm_gem_shmem_get_pages_sgt(shmem); 254 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sgt); 255 + KUNIT_ASSERT_NOT_NULL(test, shmem->pages); 256 + KUNIT_EXPECT_EQ(test, shmem->pages_use_count, 1); 257 + KUNIT_EXPECT_PTR_EQ(test, sgt, shmem->sgt); 258 + 259 + for_each_sgtable_sg(sgt, sg, si) { 260 + KUNIT_EXPECT_NOT_NULL(test, sg); 261 + len += sg->length; 262 + } 263 + 264 + KUNIT_EXPECT_GE(test, len, TEST_SIZE); 265 + } 266 + 267 + /* 268 + * Test updating the madvise state of a shmem GEM object. The test 269 + * case checks that the function for setting madv updates it only if 270 + * its current value is greater or equal than zero and returns false 271 + * if it has a negative value. 272 + */ 273 + static void drm_gem_shmem_test_madvise(struct kunit *test) 274 + { 275 + struct drm_device *drm_dev = test->priv; 276 + struct drm_gem_shmem_object *shmem; 277 + int ret; 278 + 279 + shmem = drm_gem_shmem_create(drm_dev, TEST_SIZE); 280 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, shmem); 281 + KUNIT_ASSERT_EQ(test, shmem->madv, 0); 282 + 283 + ret = kunit_add_action_or_reset(test, drm_gem_shmem_free_wrapper, shmem); 284 + KUNIT_ASSERT_EQ(test, ret, 0); 285 + 286 + ret = drm_gem_shmem_madvise(shmem, 1); 287 + KUNIT_EXPECT_TRUE(test, ret); 288 + KUNIT_ASSERT_EQ(test, shmem->madv, 1); 289 + 290 + /* Set madv to a negative value */ 291 + ret = drm_gem_shmem_madvise(shmem, -1); 292 + KUNIT_EXPECT_FALSE(test, ret); 293 + KUNIT_ASSERT_EQ(test, shmem->madv, -1); 294 + 295 + /* Check that madv cannot be set back to a positive value */ 296 + ret = drm_gem_shmem_madvise(shmem, 0); 297 + KUNIT_EXPECT_FALSE(test, ret); 298 + KUNIT_ASSERT_EQ(test, shmem->madv, -1); 299 + } 300 + 301 + /* 302 + * Test purging a shmem GEM object. First, assert that a newly created 303 + * shmem GEM object is not purgeable. Then, set madvise to a positive 304 + * value and call drm_gem_shmem_get_pages_sgt() to pin and dma-map the 305 + * backing pages. Finally, assert that the shmem GEM object is now 306 + * purgeable and purge it. 307 + */ 308 + static void drm_gem_shmem_test_purge(struct kunit *test) 309 + { 310 + struct drm_device *drm_dev = test->priv; 311 + struct drm_gem_shmem_object *shmem; 312 + struct sg_table *sgt; 313 + int ret; 314 + 315 + shmem = drm_gem_shmem_create(drm_dev, TEST_SIZE); 316 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, shmem); 317 + 318 + ret = kunit_add_action_or_reset(test, drm_gem_shmem_free_wrapper, shmem); 319 + KUNIT_ASSERT_EQ(test, ret, 0); 320 + 321 + ret = drm_gem_shmem_is_purgeable(shmem); 322 + KUNIT_EXPECT_FALSE(test, ret); 323 + 324 + ret = drm_gem_shmem_madvise(shmem, 1); 325 + KUNIT_EXPECT_TRUE(test, ret); 326 + 327 + /* The scatter/gather table will be freed by drm_gem_shmem_free */ 328 + sgt = drm_gem_shmem_get_pages_sgt(shmem); 329 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, sgt); 330 + 331 + ret = drm_gem_shmem_is_purgeable(shmem); 332 + KUNIT_EXPECT_TRUE(test, ret); 333 + 334 + drm_gem_shmem_purge(shmem); 335 + KUNIT_EXPECT_NULL(test, shmem->pages); 336 + KUNIT_EXPECT_NULL(test, shmem->sgt); 337 + KUNIT_EXPECT_EQ(test, shmem->madv, -1); 338 + } 339 + 340 + static int drm_gem_shmem_test_init(struct kunit *test) 341 + { 342 + struct device *dev; 343 + struct drm_device *drm_dev; 344 + 345 + /* Allocate a parent device */ 346 + dev = drm_kunit_helper_alloc_device(test); 347 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); 348 + 349 + /* 350 + * The DRM core will automatically initialize the GEM core and create 351 + * a DRM Memory Manager object which provides an address space pool 352 + * for GEM objects allocation. 353 + */ 354 + drm_dev = __drm_kunit_helper_alloc_drm_device(test, dev, sizeof(*drm_dev), 355 + 0, DRIVER_GEM); 356 + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm_dev); 357 + 358 + test->priv = drm_dev; 359 + 360 + return 0; 361 + } 362 + 363 + static struct kunit_case drm_gem_shmem_test_cases[] = { 364 + KUNIT_CASE(drm_gem_shmem_test_obj_create), 365 + KUNIT_CASE(drm_gem_shmem_test_obj_create_private), 366 + KUNIT_CASE(drm_gem_shmem_test_pin_pages), 367 + KUNIT_CASE(drm_gem_shmem_test_vmap), 368 + KUNIT_CASE(drm_gem_shmem_test_get_pages_sgt), 369 + KUNIT_CASE(drm_gem_shmem_test_get_sg_table), 370 + KUNIT_CASE(drm_gem_shmem_test_madvise), 371 + KUNIT_CASE(drm_gem_shmem_test_purge), 372 + {} 373 + }; 374 + 375 + static struct kunit_suite drm_gem_shmem_suite = { 376 + .name = "drm_gem_shmem", 377 + .init = drm_gem_shmem_test_init, 378 + .test_cases = drm_gem_shmem_test_cases 379 + }; 380 + 381 + kunit_test_suite(drm_gem_shmem_suite); 382 + 383 + MODULE_LICENSE("GPL");
+4 -8
drivers/gpu/drm/tidss/tidss_crtc.c
··· 169 169 struct tidss_device *tidss = to_tidss(ddev); 170 170 unsigned long flags; 171 171 172 - dev_dbg(ddev->dev, 173 - "%s: %s enabled %d, needs modeset %d, event %p\n", __func__, 174 - crtc->name, drm_atomic_crtc_needs_modeset(crtc->state), 175 - crtc->state->enable, crtc->state->event); 176 - 177 - /* There is nothing to do if CRTC is not going to be enabled. */ 178 - if (!crtc->state->enable) 179 - return; 172 + dev_dbg(ddev->dev, "%s: %s is %sactive, %s modeset, event %p\n", 173 + __func__, crtc->name, crtc->state->active ? "" : "not ", 174 + drm_atomic_crtc_needs_modeset(crtc->state) ? "needs" : "doesn't need", 175 + crtc->state->event); 180 176 181 177 /* 182 178 * Flush CRTC changes with go bit only if new modeset is not
+131 -7
drivers/gpu/drm/tidss/tidss_dispc.c
··· 322 322 .vid_order = { 1, 0 }, 323 323 }; 324 324 325 + const struct dispc_features dispc_am62a7_feats = { 326 + /* 327 + * if the code reaches dispc_mode_valid with VP1, 328 + * it should return MODE_BAD. 329 + */ 330 + .max_pclk_khz = { 331 + [DISPC_VP_TIED_OFF] = 0, 332 + [DISPC_VP_DPI] = 165000, 333 + }, 334 + 335 + .scaling = { 336 + .in_width_max_5tap_rgb = 1280, 337 + .in_width_max_3tap_rgb = 2560, 338 + .in_width_max_5tap_yuv = 2560, 339 + .in_width_max_3tap_yuv = 4096, 340 + .upscale_limit = 16, 341 + .downscale_limit_5tap = 4, 342 + .downscale_limit_3tap = 2, 343 + /* 344 + * The max supported pixel inc value is 255. The value 345 + * of pixel inc is calculated like this: 1+(xinc-1)*bpp. 346 + * The maximum bpp of all formats supported by the HW 347 + * is 8. So the maximum supported xinc value is 32, 348 + * because 1+(32-1)*8 < 255 < 1+(33-1)*4. 349 + */ 350 + .xinc_max = 32, 351 + }, 352 + 353 + .subrev = DISPC_AM62A7, 354 + 355 + .common = "common", 356 + .common_regs = tidss_am65x_common_regs, 357 + 358 + .num_vps = 2, 359 + .vp_name = { "vp1", "vp2" }, 360 + .ovr_name = { "ovr1", "ovr2" }, 361 + .vpclk_name = { "vp1", "vp2" }, 362 + /* VP1 of the DSS in AM62A7 SoC is tied off internally */ 363 + .vp_bus_type = { DISPC_VP_TIED_OFF, DISPC_VP_DPI }, 364 + 365 + .vp_feat = { .color = { 366 + .has_ctm = true, 367 + .gamma_size = 256, 368 + .gamma_type = TIDSS_GAMMA_8BIT, 369 + }, 370 + }, 371 + 372 + .num_planes = 2, 373 + /* note: vid is plane_id 0 and vidl1 is plane_id 1 */ 374 + .vid_name = { "vid", "vidl1" }, 375 + .vid_lite = { false, true, }, 376 + .vid_order = { 1, 0 }, 377 + }; 378 + 325 379 static const u16 *dispc_common_regmap; 326 380 327 381 struct dss_vp_data { ··· 878 824 case DISPC_K2G: 879 825 return dispc_k2g_read_and_clear_irqstatus(dispc); 880 826 case DISPC_AM625: 827 + case DISPC_AM62A7: 881 828 case DISPC_AM65X: 882 829 case DISPC_J721E: 883 830 return dispc_k3_read_and_clear_irqstatus(dispc); ··· 895 840 dispc_k2g_set_irqenable(dispc, mask); 896 841 break; 897 842 case DISPC_AM625: 843 + case DISPC_AM62A7: 898 844 case DISPC_AM65X: 899 845 case DISPC_J721E: 900 846 dispc_k3_set_irqenable(dispc, mask); ··· 1387 1331 x, y, layer); 1388 1332 break; 1389 1333 case DISPC_AM625: 1334 + case DISPC_AM62A7: 1390 1335 case DISPC_AM65X: 1391 1336 dispc_am65x_ovr_set_plane(dispc, hw_plane, hw_videoport, 1392 1337 x, y, layer); ··· 2307 2250 dispc_k2g_plane_init(dispc); 2308 2251 break; 2309 2252 case DISPC_AM625: 2253 + case DISPC_AM62A7: 2310 2254 case DISPC_AM65X: 2311 2255 case DISPC_J721E: 2312 2256 dispc_k3_plane_init(dispc); ··· 2415 2357 dispc_k2g_vp_write_gamma_table(dispc, hw_videoport); 2416 2358 break; 2417 2359 case DISPC_AM625: 2360 + case DISPC_AM62A7: 2418 2361 case DISPC_AM65X: 2419 2362 dispc_am65x_vp_write_gamma_table(dispc, hw_videoport); 2420 2363 break; ··· 2761 2702 } 2762 2703 } 2763 2704 2764 - static void dispc_softreset(struct dispc_device *dispc) 2705 + /* 2706 + * K2G display controller does not support soft reset, so we do a basic manual 2707 + * reset here: make sure the IRQs are masked and VPs are disabled. 2708 + */ 2709 + static void dispc_softreset_k2g(struct dispc_device *dispc) 2710 + { 2711 + dispc_set_irqenable(dispc, 0); 2712 + dispc_read_and_clear_irqstatus(dispc); 2713 + 2714 + for (unsigned int vp_idx = 0; vp_idx < dispc->feat->num_vps; ++vp_idx) 2715 + VP_REG_FLD_MOD(dispc, vp_idx, DISPC_VP_CONTROL, 0, 0, 0); 2716 + } 2717 + 2718 + static int dispc_softreset(struct dispc_device *dispc) 2765 2719 { 2766 2720 u32 val; 2767 - int ret = 0; 2721 + int ret; 2722 + 2723 + if (dispc->feat->subrev == DISPC_K2G) { 2724 + dispc_softreset_k2g(dispc); 2725 + return 0; 2726 + } 2768 2727 2769 2728 /* Soft reset */ 2770 2729 REG_FLD_MOD(dispc, DSS_SYSCONFIG, 1, 1, 1); 2771 2730 /* Wait for reset to complete */ 2772 2731 ret = readl_poll_timeout(dispc->base_common + DSS_SYSSTATUS, 2773 2732 val, val & 1, 100, 5000); 2733 + if (ret) { 2734 + dev_err(dispc->dev, "failed to reset dispc\n"); 2735 + return ret; 2736 + } 2737 + 2738 + return 0; 2739 + } 2740 + 2741 + static int dispc_init_hw(struct dispc_device *dispc) 2742 + { 2743 + struct device *dev = dispc->dev; 2744 + int ret; 2745 + 2746 + ret = pm_runtime_set_active(dev); 2747 + if (ret) { 2748 + dev_err(dev, "Failed to set DSS PM to active\n"); 2749 + return ret; 2750 + } 2751 + 2752 + ret = clk_prepare_enable(dispc->fclk); 2753 + if (ret) { 2754 + dev_err(dev, "Failed to enable DSS fclk\n"); 2755 + goto err_runtime_suspend; 2756 + } 2757 + 2758 + ret = dispc_softreset(dispc); 2774 2759 if (ret) 2775 - dev_warn(dispc->dev, "failed to reset dispc\n"); 2760 + goto err_clk_disable; 2761 + 2762 + clk_disable_unprepare(dispc->fclk); 2763 + ret = pm_runtime_set_suspended(dev); 2764 + if (ret) { 2765 + dev_err(dev, "Failed to set DSS PM to suspended\n"); 2766 + return ret; 2767 + } 2768 + 2769 + return 0; 2770 + 2771 + err_clk_disable: 2772 + clk_disable_unprepare(dispc->fclk); 2773 + 2774 + err_runtime_suspend: 2775 + ret = pm_runtime_set_suspended(dev); 2776 + if (ret) { 2777 + dev_err(dev, "Failed to set DSS PM to suspended\n"); 2778 + return ret; 2779 + } 2780 + 2781 + return ret; 2776 2782 } 2777 2783 2778 2784 int dispc_init(struct tidss_device *tidss) ··· 2901 2777 return r; 2902 2778 } 2903 2779 2904 - /* K2G display controller does not support soft reset */ 2905 - if (feat->subrev != DISPC_K2G) 2906 - dispc_softreset(dispc); 2907 - 2908 2780 for (i = 0; i < dispc->feat->num_vps; i++) { 2909 2781 u32 gamma_size = dispc->feat->vp_feat.color.gamma_size; 2910 2782 u32 *gamma_table; ··· 2948 2828 2949 2829 of_property_read_u32(dispc->dev->of_node, "max-memory-bandwidth", 2950 2830 &dispc->memory_bandwidth_limit); 2831 + 2832 + r = dispc_init_hw(dispc); 2833 + if (r) 2834 + return r; 2951 2835 2952 2836 tidss->dispc = dispc; 2953 2837
+3
drivers/gpu/drm/tidss/tidss_dispc.h
··· 54 54 DISPC_VP_DPI, /* DPI output */ 55 55 DISPC_VP_OLDI, /* OLDI (LVDS) output */ 56 56 DISPC_VP_INTERNAL, /* SoC internal routing */ 57 + DISPC_VP_TIED_OFF, /* Tied off / Unavailable */ 57 58 DISPC_VP_MAX_BUS_TYPE, 58 59 }; 59 60 60 61 enum dispc_dss_subrevision { 61 62 DISPC_K2G, 62 63 DISPC_AM625, 64 + DISPC_AM62A7, 63 65 DISPC_AM65X, 64 66 DISPC_J721E, 65 67 }; ··· 90 88 91 89 extern const struct dispc_features dispc_k2g_feats; 92 90 extern const struct dispc_features dispc_am625_feats; 91 + extern const struct dispc_features dispc_am62a7_feats; 93 92 extern const struct dispc_features dispc_am65x_feats; 94 93 extern const struct dispc_features dispc_j721e_feats; 95 94
+13 -3
drivers/gpu/drm/tidss/tidss_drv.c
··· 32 32 33 33 dev_dbg(tidss->dev, "%s\n", __func__); 34 34 35 - r = pm_runtime_get_sync(tidss->dev); 35 + r = pm_runtime_resume_and_get(tidss->dev); 36 36 WARN_ON(r < 0); 37 - return r < 0 ? r : 0; 37 + return r; 38 38 } 39 39 40 40 void tidss_runtime_put(struct tidss_device *tidss) ··· 43 43 44 44 dev_dbg(tidss->dev, "%s\n", __func__); 45 45 46 - r = pm_runtime_put_sync(tidss->dev); 46 + pm_runtime_mark_last_busy(tidss->dev); 47 + 48 + r = pm_runtime_put_autosuspend(tidss->dev); 47 49 WARN_ON(r < 0); 48 50 } 49 51 ··· 138 136 139 137 platform_set_drvdata(pdev, tidss); 140 138 139 + spin_lock_init(&tidss->wait_lock); 140 + 141 141 ret = dispc_init(tidss); 142 142 if (ret) { 143 143 dev_err(dev, "failed to initialize dispc: %d\n", ret); ··· 147 143 } 148 144 149 145 pm_runtime_enable(dev); 146 + 147 + pm_runtime_set_autosuspend_delay(dev, 1000); 148 + pm_runtime_use_autosuspend(dev); 150 149 151 150 #ifndef CONFIG_PM 152 151 /* If we don't have PM, we need to call resume manually */ ··· 199 192 #ifndef CONFIG_PM 200 193 dispc_runtime_suspend(tidss->dispc); 201 194 #endif 195 + pm_runtime_dont_use_autosuspend(dev); 202 196 pm_runtime_disable(dev); 203 197 204 198 return ret; ··· 223 215 /* If we don't have PM, we need to call suspend manually */ 224 216 dispc_runtime_suspend(tidss->dispc); 225 217 #endif 218 + pm_runtime_dont_use_autosuspend(dev); 226 219 pm_runtime_disable(dev); 227 220 228 221 /* devm allocated dispc goes away with the dev so mark it NULL */ ··· 240 231 static const struct of_device_id tidss_of_table[] = { 241 232 { .compatible = "ti,k2g-dss", .data = &dispc_k2g_feats, }, 242 233 { .compatible = "ti,am625-dss", .data = &dispc_am625_feats, }, 234 + { .compatible = "ti,am62a7-dss", .data = &dispc_am62a7_feats, }, 243 235 { .compatible = "ti,am65x-dss", .data = &dispc_am65x_feats, }, 244 236 { .compatible = "ti,j721e-dss", .data = &dispc_j721e_feats, }, 245 237 { }
+8 -46
drivers/gpu/drm/tidss/tidss_irq.c
··· 93 93 spin_unlock_irqrestore(&tidss->wait_lock, flags); 94 94 } 95 95 96 - static void tidss_irq_preinstall(struct drm_device *ddev) 96 + int tidss_irq_install(struct drm_device *ddev, unsigned int irq) 97 97 { 98 98 struct tidss_device *tidss = to_tidss(ddev); 99 + int ret; 99 100 100 - spin_lock_init(&tidss->wait_lock); 101 + if (irq == IRQ_NOTCONNECTED) 102 + return -ENOTCONN; 101 103 102 - tidss_runtime_get(tidss); 103 - 104 - dispc_set_irqenable(tidss->dispc, 0); 105 - dispc_read_and_clear_irqstatus(tidss->dispc); 106 - 107 - tidss_runtime_put(tidss); 108 - } 109 - 110 - static void tidss_irq_postinstall(struct drm_device *ddev) 111 - { 112 - struct tidss_device *tidss = to_tidss(ddev); 113 - unsigned long flags; 114 - unsigned int i; 115 - 116 - tidss_runtime_get(tidss); 117 - 118 - spin_lock_irqsave(&tidss->wait_lock, flags); 104 + ret = request_irq(irq, tidss_irq_handler, 0, ddev->driver->name, ddev); 105 + if (ret) 106 + return ret; 119 107 120 108 tidss->irq_mask = DSS_IRQ_DEVICE_OCP_ERR; 121 109 122 - for (i = 0; i < tidss->num_crtcs; ++i) { 110 + for (unsigned int i = 0; i < tidss->num_crtcs; ++i) { 123 111 struct tidss_crtc *tcrtc = to_tidss_crtc(tidss->crtcs[i]); 124 112 125 113 tidss->irq_mask |= DSS_IRQ_VP_SYNC_LOST(tcrtc->hw_videoport); ··· 115 127 tidss->irq_mask |= DSS_IRQ_VP_FRAME_DONE(tcrtc->hw_videoport); 116 128 } 117 129 118 - tidss_irq_update(tidss); 119 - 120 - spin_unlock_irqrestore(&tidss->wait_lock, flags); 121 - 122 - tidss_runtime_put(tidss); 123 - } 124 - 125 - int tidss_irq_install(struct drm_device *ddev, unsigned int irq) 126 - { 127 - int ret; 128 - 129 - if (irq == IRQ_NOTCONNECTED) 130 - return -ENOTCONN; 131 - 132 - tidss_irq_preinstall(ddev); 133 - 134 - ret = request_irq(irq, tidss_irq_handler, 0, ddev->driver->name, ddev); 135 - if (ret) 136 - return ret; 137 - 138 - tidss_irq_postinstall(ddev); 139 - 140 130 return 0; 141 131 } 142 132 143 133 void tidss_irq_uninstall(struct drm_device *ddev) 144 134 { 145 135 struct tidss_device *tidss = to_tidss(ddev); 146 - 147 - tidss_runtime_get(tidss); 148 - dispc_set_irqenable(tidss->dispc, 0); 149 - tidss_runtime_put(tidss); 150 136 151 137 free_irq(tidss->irq, ddev); 152 138 }
+1 -1
drivers/gpu/drm/tidss/tidss_kms.c
··· 29 29 tidss_runtime_get(tidss); 30 30 31 31 drm_atomic_helper_commit_modeset_disables(ddev, old_state); 32 - drm_atomic_helper_commit_planes(ddev, old_state, 0); 32 + drm_atomic_helper_commit_planes(ddev, old_state, DRM_PLANE_COMMIT_ACTIVE_ONLY); 33 33 drm_atomic_helper_commit_modeset_enables(ddev, old_state); 34 34 35 35 drm_atomic_helper_commit_hw_done(old_state);
+4 -5
drivers/gpu/drm/tilcdc/tilcdc_drv.c
··· 570 570 match); 571 571 } 572 572 573 - static int tilcdc_pdev_remove(struct platform_device *pdev) 573 + static void tilcdc_pdev_remove(struct platform_device *pdev) 574 574 { 575 575 int ret; 576 576 577 577 ret = tilcdc_get_external_components(&pdev->dev, NULL); 578 578 if (ret < 0) 579 - return ret; 579 + dev_err(&pdev->dev, "tilcdc_get_external_components() failed (%pe)\n", 580 + ERR_PTR(ret)); 580 581 else if (ret == 0) 581 582 tilcdc_fini(platform_get_drvdata(pdev)); 582 583 else 583 584 component_master_del(&pdev->dev, &tilcdc_comp_ops); 584 - 585 - return 0; 586 585 } 587 586 588 587 static void tilcdc_pdev_shutdown(struct platform_device *pdev) ··· 598 599 599 600 static struct platform_driver tilcdc_platform_driver = { 600 601 .probe = tilcdc_pdev_probe, 601 - .remove = tilcdc_pdev_remove, 602 + .remove_new = tilcdc_pdev_remove, 602 603 .shutdown = tilcdc_pdev_shutdown, 603 604 .driver = { 604 605 .name = "tilcdc",
-1
drivers/gpu/drm/tiny/ofdrm.c
··· 19 19 #include <drm/drm_gem_shmem_helper.h> 20 20 #include <drm/drm_managed.h> 21 21 #include <drm/drm_modeset_helper_vtables.h> 22 - #include <drm/drm_plane_helper.h> 23 22 #include <drm/drm_probe_helper.h> 24 23 #include <drm/drm_simple_kms_helper.h> 25 24
-1
drivers/gpu/drm/tiny/simpledrm.c
··· 25 25 #include <drm/drm_gem_shmem_helper.h> 26 26 #include <drm/drm_managed.h> 27 27 #include <drm/drm_modeset_helper_vtables.h> 28 - #include <drm/drm_plane_helper.h> 29 28 #include <drm/drm_probe_helper.h> 30 29 31 30 #define DRIVER_NAME "simpledrm"
+7 -1
drivers/gpu/drm/ttm/ttm_bo.c
··· 370 370 spin_unlock(&bo->bdev->lru_lock); 371 371 372 372 INIT_WORK(&bo->delayed_delete, ttm_bo_delayed_delete); 373 - queue_work(bdev->wq, &bo->delayed_delete); 373 + 374 + /* Schedule the worker on the closest NUMA node. This 375 + * improves performance since system memory might be 376 + * cleared on free and that is best done on a CPU core 377 + * close to it. 378 + */ 379 + queue_work_node(bdev->pool.nid, bdev->wq, &bo->delayed_delete); 374 380 return; 375 381 } 376 382
+4 -2
drivers/gpu/drm/ttm/ttm_device.c
··· 204 204 if (ret) 205 205 return ret; 206 206 207 - bdev->wq = alloc_workqueue("ttm", WQ_MEM_RECLAIM | WQ_HIGHPRI, 16); 207 + bdev->wq = alloc_workqueue("ttm", 208 + WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 16); 208 209 if (!bdev->wq) { 209 210 ttm_global_release(); 210 211 return -ENOMEM; ··· 214 213 bdev->funcs = funcs; 215 214 216 215 ttm_sys_man_init(bdev); 217 - ttm_pool_init(&bdev->pool, dev, NUMA_NO_NODE, use_dma_alloc, use_dma32); 216 + 217 + ttm_pool_init(&bdev->pool, dev, dev_to_node(dev), use_dma_alloc, use_dma32); 218 218 219 219 bdev->vma_manager = vma_manager; 220 220 spin_lock_init(&bdev->lru_lock);
+17 -2
drivers/gpu/drm/udl/udl_modeset.c
··· 21 21 #include <drm/drm_gem_framebuffer_helper.h> 22 22 #include <drm/drm_gem_shmem_helper.h> 23 23 #include <drm/drm_modeset_helper_vtables.h> 24 - #include <drm/drm_plane_helper.h> 25 24 #include <drm/drm_probe_helper.h> 26 25 #include <drm/drm_vblank.h> 27 26 ··· 260 261 DRM_FORMAT_MOD_INVALID 261 262 }; 262 263 264 + static int udl_primary_plane_helper_atomic_check(struct drm_plane *plane, 265 + struct drm_atomic_state *state) 266 + { 267 + struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane); 268 + struct drm_crtc *new_crtc = new_plane_state->crtc; 269 + struct drm_crtc_state *new_crtc_state = NULL; 270 + 271 + if (new_crtc) 272 + new_crtc_state = drm_atomic_get_new_crtc_state(state, new_crtc); 273 + 274 + return drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state, 275 + DRM_PLANE_NO_SCALING, 276 + DRM_PLANE_NO_SCALING, 277 + false, false); 278 + } 279 + 263 280 static void udl_primary_plane_helper_atomic_update(struct drm_plane *plane, 264 281 struct drm_atomic_state *state) 265 282 { ··· 311 296 312 297 static const struct drm_plane_helper_funcs udl_primary_plane_helper_funcs = { 313 298 DRM_GEM_SHADOW_PLANE_HELPER_FUNCS, 314 - .atomic_check = drm_plane_helper_atomic_check, 299 + .atomic_check = udl_primary_plane_helper_atomic_check, 315 300 .atomic_update = udl_primary_plane_helper_atomic_update, 316 301 }; 317 302
+2 -1
drivers/gpu/drm/v3d/Makefile
··· 12 12 v3d_perfmon.o \ 13 13 v3d_trace_points.o \ 14 14 v3d_sched.o \ 15 - v3d_sysfs.o 15 + v3d_sysfs.o \ 16 + v3d_submit.o 16 17 17 18 v3d-$(CONFIG_DEBUG_FS) += v3d_debugfs.o 18 19
+51
drivers/gpu/drm/v3d/v3d_bo.c
··· 33 33 struct v3d_dev *v3d = to_v3d_dev(obj->dev); 34 34 struct v3d_bo *bo = to_v3d_bo(obj); 35 35 36 + if (bo->vaddr) 37 + v3d_put_bo_vaddr(bo); 38 + 36 39 v3d_mmu_remove_ptes(bo); 37 40 38 41 mutex_lock(&v3d->bo_lock); ··· 137 134 if (IS_ERR(shmem_obj)) 138 135 return ERR_CAST(shmem_obj); 139 136 bo = to_v3d_bo(&shmem_obj->base); 137 + bo->vaddr = NULL; 140 138 141 139 ret = v3d_bo_create_finish(&shmem_obj->base); 142 140 if (ret) ··· 169 165 } 170 166 171 167 return obj; 168 + } 169 + 170 + void v3d_get_bo_vaddr(struct v3d_bo *bo) 171 + { 172 + struct drm_gem_shmem_object *obj = &bo->base; 173 + 174 + bo->vaddr = vmap(obj->pages, obj->base.size >> PAGE_SHIFT, VM_MAP, 175 + pgprot_writecombine(PAGE_KERNEL)); 176 + } 177 + 178 + void v3d_put_bo_vaddr(struct v3d_bo *bo) 179 + { 180 + vunmap(bo->vaddr); 181 + bo->vaddr = NULL; 172 182 } 173 183 174 184 int v3d_create_bo_ioctl(struct drm_device *dev, void *data, ··· 250 232 251 233 drm_gem_object_put(gem_obj); 252 234 return 0; 235 + } 236 + 237 + int 238 + v3d_wait_bo_ioctl(struct drm_device *dev, void *data, 239 + struct drm_file *file_priv) 240 + { 241 + int ret; 242 + struct drm_v3d_wait_bo *args = data; 243 + ktime_t start = ktime_get(); 244 + u64 delta_ns; 245 + unsigned long timeout_jiffies = 246 + nsecs_to_jiffies_timeout(args->timeout_ns); 247 + 248 + if (args->pad != 0) 249 + return -EINVAL; 250 + 251 + ret = drm_gem_dma_resv_wait(file_priv, args->handle, 252 + true, timeout_jiffies); 253 + 254 + /* Decrement the user's timeout, in case we got interrupted 255 + * such that the ioctl will be restarted. 256 + */ 257 + delta_ns = ktime_to_ns(ktime_sub(ktime_get(), start)); 258 + if (delta_ns < args->timeout_ns) 259 + args->timeout_ns -= delta_ns; 260 + else 261 + args->timeout_ns = 0; 262 + 263 + /* Asked to wait beyond the jiffie/scheduler precision? */ 264 + if (ret == -ETIME && args->timeout_ns) 265 + ret = -EAGAIN; 266 + 267 + return ret; 253 268 }
+4
drivers/gpu/drm/v3d/v3d_drv.c
··· 91 91 case DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT: 92 92 args->value = 1; 93 93 return 0; 94 + case DRM_V3D_PARAM_SUPPORTS_CPU_QUEUE: 95 + args->value = 1; 96 + return 0; 94 97 default: 95 98 DRM_DEBUG("Unknown parameter %d\n", args->param); 96 99 return -EINVAL; ··· 192 189 DRM_IOCTL_DEF_DRV(V3D_PERFMON_CREATE, v3d_perfmon_create_ioctl, DRM_RENDER_ALLOW), 193 190 DRM_IOCTL_DEF_DRV(V3D_PERFMON_DESTROY, v3d_perfmon_destroy_ioctl, DRM_RENDER_ALLOW), 194 191 DRM_IOCTL_DEF_DRV(V3D_PERFMON_GET_VALUES, v3d_perfmon_get_values_ioctl, DRM_RENDER_ALLOW), 192 + DRM_IOCTL_DEF_DRV(V3D_SUBMIT_CPU, v3d_submit_cpu_ioctl, DRM_RENDER_ALLOW | DRM_AUTH), 195 193 }; 196 194 197 195 static const struct drm_driver v3d_drm_driver = {
+124 -10
drivers/gpu/drm/v3d/v3d_drv.h
··· 19 19 20 20 #define GMP_GRANULARITY (128 * 1024) 21 21 22 - #define V3D_MAX_QUEUES (V3D_CACHE_CLEAN + 1) 22 + #define V3D_MAX_QUEUES (V3D_CPU + 1) 23 23 24 24 static inline char *v3d_queue_to_string(enum v3d_queue queue) 25 25 { ··· 29 29 case V3D_TFU: return "tfu"; 30 30 case V3D_CSD: return "csd"; 31 31 case V3D_CACHE_CLEAN: return "cache_clean"; 32 + case V3D_CPU: return "cpu"; 32 33 } 33 34 return "UNKNOWN"; 34 35 } ··· 123 122 struct v3d_render_job *render_job; 124 123 struct v3d_tfu_job *tfu_job; 125 124 struct v3d_csd_job *csd_job; 125 + struct v3d_cpu_job *cpu_job; 126 126 127 127 struct v3d_queue_state queue[V3D_MAX_QUEUES]; 128 128 ··· 202 200 * v3d_render_job->unref_list 203 201 */ 204 202 struct list_head unref_head; 203 + 204 + void *vaddr; 205 205 }; 206 206 207 207 static inline struct v3d_bo * ··· 316 312 struct drm_v3d_submit_csd args; 317 313 }; 318 314 315 + enum v3d_cpu_job_type { 316 + V3D_CPU_JOB_TYPE_INDIRECT_CSD = 1, 317 + V3D_CPU_JOB_TYPE_TIMESTAMP_QUERY, 318 + V3D_CPU_JOB_TYPE_RESET_TIMESTAMP_QUERY, 319 + V3D_CPU_JOB_TYPE_COPY_TIMESTAMP_QUERY, 320 + V3D_CPU_JOB_TYPE_RESET_PERFORMANCE_QUERY, 321 + V3D_CPU_JOB_TYPE_COPY_PERFORMANCE_QUERY, 322 + }; 323 + 324 + struct v3d_timestamp_query { 325 + /* Offset of this query in the timestamp BO for its value. */ 326 + u32 offset; 327 + 328 + /* Syncobj that indicates the timestamp availability */ 329 + struct drm_syncobj *syncobj; 330 + }; 331 + 332 + /* Number of perfmons required to handle all supported performance counters */ 333 + #define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_PERFCNT_NUM, \ 334 + DRM_V3D_MAX_PERF_COUNTERS) 335 + 336 + struct v3d_performance_query { 337 + /* Performance monitor IDs for this query */ 338 + u32 kperfmon_ids[V3D_MAX_PERFMONS]; 339 + 340 + /* Syncobj that indicates the query availability */ 341 + struct drm_syncobj *syncobj; 342 + }; 343 + 344 + struct v3d_indirect_csd_info { 345 + /* Indirect CSD */ 346 + struct v3d_csd_job *job; 347 + 348 + /* Clean cache job associated to the Indirect CSD job */ 349 + struct v3d_job *clean_job; 350 + 351 + /* Offset within the BO where the workgroup counts are stored */ 352 + u32 offset; 353 + 354 + /* Workgroups size */ 355 + u32 wg_size; 356 + 357 + /* Indices of the uniforms with the workgroup dispatch counts 358 + * in the uniform stream. 359 + */ 360 + u32 wg_uniform_offsets[3]; 361 + 362 + /* Indirect BO */ 363 + struct drm_gem_object *indirect; 364 + 365 + /* Context of the Indirect CSD job */ 366 + struct ww_acquire_ctx acquire_ctx; 367 + }; 368 + 369 + struct v3d_timestamp_query_info { 370 + struct v3d_timestamp_query *queries; 371 + 372 + u32 count; 373 + }; 374 + 375 + struct v3d_performance_query_info { 376 + struct v3d_performance_query *queries; 377 + 378 + /* Number of performance queries */ 379 + u32 count; 380 + 381 + /* Number of performance monitors related to that query pool */ 382 + u32 nperfmons; 383 + 384 + /* Number of performance counters related to that query pool */ 385 + u32 ncounters; 386 + }; 387 + 388 + struct v3d_copy_query_results_info { 389 + /* Define if should write to buffer using 64 or 32 bits */ 390 + bool do_64bit; 391 + 392 + /* Define if it can write to buffer even if the query is not available */ 393 + bool do_partial; 394 + 395 + /* Define if it should write availability bit to buffer */ 396 + bool availability_bit; 397 + 398 + /* Offset of the copy buffer in the BO */ 399 + u32 offset; 400 + 401 + /* Stride of the copy buffer in the BO */ 402 + u32 stride; 403 + }; 404 + 405 + struct v3d_cpu_job { 406 + struct v3d_job base; 407 + 408 + enum v3d_cpu_job_type job_type; 409 + 410 + struct v3d_indirect_csd_info indirect_csd; 411 + 412 + struct v3d_timestamp_query_info timestamp_query; 413 + 414 + struct v3d_copy_query_results_info copy; 415 + 416 + struct v3d_performance_query_info performance_query; 417 + }; 418 + 419 + typedef void (*v3d_cpu_job_fn)(struct v3d_cpu_job *); 420 + 319 421 struct v3d_submit_outsync { 320 422 struct drm_syncobj *syncobj; 321 423 }; ··· 489 379 void v3d_free_object(struct drm_gem_object *gem_obj); 490 380 struct v3d_bo *v3d_bo_create(struct drm_device *dev, struct drm_file *file_priv, 491 381 size_t size); 382 + void v3d_get_bo_vaddr(struct v3d_bo *bo); 383 + void v3d_put_bo_vaddr(struct v3d_bo *bo); 492 384 int v3d_create_bo_ioctl(struct drm_device *dev, void *data, 493 385 struct drm_file *file_priv); 494 386 int v3d_mmap_bo_ioctl(struct drm_device *dev, void *data, 495 387 struct drm_file *file_priv); 496 388 int v3d_get_bo_offset_ioctl(struct drm_device *dev, void *data, 497 389 struct drm_file *file_priv); 390 + int v3d_wait_bo_ioctl(struct drm_device *dev, void *data, 391 + struct drm_file *file_priv); 498 392 struct drm_gem_object *v3d_prime_import_sg_table(struct drm_device *dev, 499 393 struct dma_buf_attachment *attach, 500 394 struct sg_table *sgt); ··· 513 399 /* v3d_gem.c */ 514 400 int v3d_gem_init(struct drm_device *dev); 515 401 void v3d_gem_destroy(struct drm_device *dev); 402 + void v3d_reset(struct v3d_dev *v3d); 403 + void v3d_invalidate_caches(struct v3d_dev *v3d); 404 + void v3d_clean_caches(struct v3d_dev *v3d); 405 + 406 + /* v3d_submit.c */ 407 + void v3d_job_cleanup(struct v3d_job *job); 408 + void v3d_job_put(struct v3d_job *job); 516 409 int v3d_submit_cl_ioctl(struct drm_device *dev, void *data, 517 410 struct drm_file *file_priv); 518 411 int v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, 519 412 struct drm_file *file_priv); 520 413 int v3d_submit_csd_ioctl(struct drm_device *dev, void *data, 521 414 struct drm_file *file_priv); 522 - int v3d_wait_bo_ioctl(struct drm_device *dev, void *data, 523 - struct drm_file *file_priv); 524 - void v3d_job_cleanup(struct v3d_job *job); 525 - void v3d_job_put(struct v3d_job *job); 526 - void v3d_reset(struct v3d_dev *v3d); 527 - void v3d_invalidate_caches(struct v3d_dev *v3d); 528 - void v3d_clean_caches(struct v3d_dev *v3d); 415 + int v3d_submit_cpu_ioctl(struct drm_device *dev, void *data, 416 + struct drm_file *file_priv); 529 417 530 418 /* v3d_irq.c */ 531 419 int v3d_irq_init(struct v3d_dev *v3d); ··· 536 420 void v3d_irq_reset(struct v3d_dev *v3d); 537 421 538 422 /* v3d_mmu.c */ 539 - int v3d_mmu_get_offset(struct drm_file *file_priv, struct v3d_bo *bo, 540 - u32 *offset); 541 423 int v3d_mmu_set_page_table(struct v3d_dev *v3d); 542 424 void v3d_mmu_insert_ptes(struct v3d_bo *bo); 543 425 void v3d_mmu_remove_ptes(struct v3d_bo *bo);
-768
drivers/gpu/drm/v3d/v3d_gem.c
··· 11 11 #include <linux/uaccess.h> 12 12 13 13 #include <drm/drm_managed.h> 14 - #include <drm/drm_syncobj.h> 15 - #include <uapi/drm/v3d_drm.h> 16 14 17 15 #include "v3d_drv.h" 18 16 #include "v3d_regs.h" ··· 237 239 v3d_invalidate_l2c(v3d, 0); 238 240 v3d_flush_l2t(v3d, 0); 239 241 v3d_invalidate_slices(v3d, 0); 240 - } 241 - 242 - /* Takes the reservation lock on all the BOs being referenced, so that 243 - * at queue submit time we can update the reservations. 244 - * 245 - * We don't lock the RCL the tile alloc/state BOs, or overflow memory 246 - * (all of which are on exec->unref_list). They're entirely private 247 - * to v3d, so we don't attach dma-buf fences to them. 248 - */ 249 - static int 250 - v3d_lock_bo_reservations(struct v3d_job *job, 251 - struct ww_acquire_ctx *acquire_ctx) 252 - { 253 - int i, ret; 254 - 255 - ret = drm_gem_lock_reservations(job->bo, job->bo_count, acquire_ctx); 256 - if (ret) 257 - return ret; 258 - 259 - for (i = 0; i < job->bo_count; i++) { 260 - ret = dma_resv_reserve_fences(job->bo[i]->resv, 1); 261 - if (ret) 262 - goto fail; 263 - 264 - ret = drm_sched_job_add_implicit_dependencies(&job->base, 265 - job->bo[i], true); 266 - if (ret) 267 - goto fail; 268 - } 269 - 270 - return 0; 271 - 272 - fail: 273 - drm_gem_unlock_reservations(job->bo, job->bo_count, acquire_ctx); 274 - return ret; 275 - } 276 - 277 - /** 278 - * v3d_lookup_bos() - Sets up job->bo[] with the GEM objects 279 - * referenced by the job. 280 - * @dev: DRM device 281 - * @file_priv: DRM file for this fd 282 - * @job: V3D job being set up 283 - * @bo_handles: GEM handles 284 - * @bo_count: Number of GEM handles passed in 285 - * 286 - * The command validator needs to reference BOs by their index within 287 - * the submitted job's BO list. This does the validation of the job's 288 - * BO list and reference counting for the lifetime of the job. 289 - * 290 - * Note that this function doesn't need to unreference the BOs on 291 - * failure, because that will happen at v3d_exec_cleanup() time. 292 - */ 293 - static int 294 - v3d_lookup_bos(struct drm_device *dev, 295 - struct drm_file *file_priv, 296 - struct v3d_job *job, 297 - u64 bo_handles, 298 - u32 bo_count) 299 - { 300 - job->bo_count = bo_count; 301 - 302 - if (!job->bo_count) { 303 - /* See comment on bo_index for why we have to check 304 - * this. 305 - */ 306 - DRM_DEBUG("Rendering requires BOs\n"); 307 - return -EINVAL; 308 - } 309 - 310 - return drm_gem_objects_lookup(file_priv, 311 - (void __user *)(uintptr_t)bo_handles, 312 - job->bo_count, &job->bo); 313 - } 314 - 315 - static void 316 - v3d_job_free(struct kref *ref) 317 - { 318 - struct v3d_job *job = container_of(ref, struct v3d_job, refcount); 319 - int i; 320 - 321 - if (job->bo) { 322 - for (i = 0; i < job->bo_count; i++) 323 - drm_gem_object_put(job->bo[i]); 324 - kvfree(job->bo); 325 - } 326 - 327 - dma_fence_put(job->irq_fence); 328 - dma_fence_put(job->done_fence); 329 - 330 - if (job->perfmon) 331 - v3d_perfmon_put(job->perfmon); 332 - 333 - kfree(job); 334 - } 335 - 336 - static void 337 - v3d_render_job_free(struct kref *ref) 338 - { 339 - struct v3d_render_job *job = container_of(ref, struct v3d_render_job, 340 - base.refcount); 341 - struct v3d_bo *bo, *save; 342 - 343 - list_for_each_entry_safe(bo, save, &job->unref_list, unref_head) { 344 - drm_gem_object_put(&bo->base.base); 345 - } 346 - 347 - v3d_job_free(ref); 348 - } 349 - 350 - void v3d_job_cleanup(struct v3d_job *job) 351 - { 352 - if (!job) 353 - return; 354 - 355 - drm_sched_job_cleanup(&job->base); 356 - v3d_job_put(job); 357 - } 358 - 359 - void v3d_job_put(struct v3d_job *job) 360 - { 361 - kref_put(&job->refcount, job->free); 362 - } 363 - 364 - int 365 - v3d_wait_bo_ioctl(struct drm_device *dev, void *data, 366 - struct drm_file *file_priv) 367 - { 368 - int ret; 369 - struct drm_v3d_wait_bo *args = data; 370 - ktime_t start = ktime_get(); 371 - u64 delta_ns; 372 - unsigned long timeout_jiffies = 373 - nsecs_to_jiffies_timeout(args->timeout_ns); 374 - 375 - if (args->pad != 0) 376 - return -EINVAL; 377 - 378 - ret = drm_gem_dma_resv_wait(file_priv, args->handle, 379 - true, timeout_jiffies); 380 - 381 - /* Decrement the user's timeout, in case we got interrupted 382 - * such that the ioctl will be restarted. 383 - */ 384 - delta_ns = ktime_to_ns(ktime_sub(ktime_get(), start)); 385 - if (delta_ns < args->timeout_ns) 386 - args->timeout_ns -= delta_ns; 387 - else 388 - args->timeout_ns = 0; 389 - 390 - /* Asked to wait beyond the jiffie/scheduler precision? */ 391 - if (ret == -ETIME && args->timeout_ns) 392 - ret = -EAGAIN; 393 - 394 - return ret; 395 - } 396 - 397 - static int 398 - v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, 399 - void **container, size_t size, void (*free)(struct kref *ref), 400 - u32 in_sync, struct v3d_submit_ext *se, enum v3d_queue queue) 401 - { 402 - struct v3d_file_priv *v3d_priv = file_priv->driver_priv; 403 - struct v3d_job *job; 404 - bool has_multisync = se && (se->flags & DRM_V3D_EXT_ID_MULTI_SYNC); 405 - int ret, i; 406 - 407 - *container = kcalloc(1, size, GFP_KERNEL); 408 - if (!*container) { 409 - DRM_ERROR("Cannot allocate memory for v3d job."); 410 - return -ENOMEM; 411 - } 412 - 413 - job = *container; 414 - job->v3d = v3d; 415 - job->free = free; 416 - job->file = file_priv; 417 - 418 - ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue], 419 - 1, v3d_priv); 420 - if (ret) 421 - goto fail; 422 - 423 - if (has_multisync) { 424 - if (se->in_sync_count && se->wait_stage == queue) { 425 - struct drm_v3d_sem __user *handle = u64_to_user_ptr(se->in_syncs); 426 - 427 - for (i = 0; i < se->in_sync_count; i++) { 428 - struct drm_v3d_sem in; 429 - 430 - if (copy_from_user(&in, handle++, sizeof(in))) { 431 - ret = -EFAULT; 432 - DRM_DEBUG("Failed to copy wait dep handle.\n"); 433 - goto fail_deps; 434 - } 435 - ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in.handle, 0); 436 - 437 - // TODO: Investigate why this was filtered out for the IOCTL. 438 - if (ret && ret != -ENOENT) 439 - goto fail_deps; 440 - } 441 - } 442 - } else { 443 - ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in_sync, 0); 444 - 445 - // TODO: Investigate why this was filtered out for the IOCTL. 446 - if (ret && ret != -ENOENT) 447 - goto fail_deps; 448 - } 449 - 450 - kref_init(&job->refcount); 451 - 452 - return 0; 453 - 454 - fail_deps: 455 - drm_sched_job_cleanup(&job->base); 456 - fail: 457 - kfree(*container); 458 - *container = NULL; 459 - 460 - return ret; 461 - } 462 - 463 - static void 464 - v3d_push_job(struct v3d_job *job) 465 - { 466 - drm_sched_job_arm(&job->base); 467 - 468 - job->done_fence = dma_fence_get(&job->base.s_fence->finished); 469 - 470 - /* put by scheduler job completion */ 471 - kref_get(&job->refcount); 472 - 473 - drm_sched_entity_push_job(&job->base); 474 - } 475 - 476 - static void 477 - v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv, 478 - struct v3d_job *job, 479 - struct ww_acquire_ctx *acquire_ctx, 480 - u32 out_sync, 481 - struct v3d_submit_ext *se, 482 - struct dma_fence *done_fence) 483 - { 484 - struct drm_syncobj *sync_out; 485 - bool has_multisync = se && (se->flags & DRM_V3D_EXT_ID_MULTI_SYNC); 486 - int i; 487 - 488 - for (i = 0; i < job->bo_count; i++) { 489 - /* XXX: Use shared fences for read-only objects. */ 490 - dma_resv_add_fence(job->bo[i]->resv, job->done_fence, 491 - DMA_RESV_USAGE_WRITE); 492 - } 493 - 494 - drm_gem_unlock_reservations(job->bo, job->bo_count, acquire_ctx); 495 - 496 - /* Update the return sync object for the job */ 497 - /* If it only supports a single signal semaphore*/ 498 - if (!has_multisync) { 499 - sync_out = drm_syncobj_find(file_priv, out_sync); 500 - if (sync_out) { 501 - drm_syncobj_replace_fence(sync_out, done_fence); 502 - drm_syncobj_put(sync_out); 503 - } 504 - return; 505 - } 506 - 507 - /* If multiple semaphores extension is supported */ 508 - if (se->out_sync_count) { 509 - for (i = 0; i < se->out_sync_count; i++) { 510 - drm_syncobj_replace_fence(se->out_syncs[i].syncobj, 511 - done_fence); 512 - drm_syncobj_put(se->out_syncs[i].syncobj); 513 - } 514 - kvfree(se->out_syncs); 515 - } 516 - } 517 - 518 - static void 519 - v3d_put_multisync_post_deps(struct v3d_submit_ext *se) 520 - { 521 - unsigned int i; 522 - 523 - if (!(se && se->out_sync_count)) 524 - return; 525 - 526 - for (i = 0; i < se->out_sync_count; i++) 527 - drm_syncobj_put(se->out_syncs[i].syncobj); 528 - kvfree(se->out_syncs); 529 - } 530 - 531 - static int 532 - v3d_get_multisync_post_deps(struct drm_file *file_priv, 533 - struct v3d_submit_ext *se, 534 - u32 count, u64 handles) 535 - { 536 - struct drm_v3d_sem __user *post_deps; 537 - int i, ret; 538 - 539 - if (!count) 540 - return 0; 541 - 542 - se->out_syncs = (struct v3d_submit_outsync *) 543 - kvmalloc_array(count, 544 - sizeof(struct v3d_submit_outsync), 545 - GFP_KERNEL); 546 - if (!se->out_syncs) 547 - return -ENOMEM; 548 - 549 - post_deps = u64_to_user_ptr(handles); 550 - 551 - for (i = 0; i < count; i++) { 552 - struct drm_v3d_sem out; 553 - 554 - if (copy_from_user(&out, post_deps++, sizeof(out))) { 555 - ret = -EFAULT; 556 - DRM_DEBUG("Failed to copy post dep handles\n"); 557 - goto fail; 558 - } 559 - 560 - se->out_syncs[i].syncobj = drm_syncobj_find(file_priv, 561 - out.handle); 562 - if (!se->out_syncs[i].syncobj) { 563 - ret = -EINVAL; 564 - goto fail; 565 - } 566 - } 567 - se->out_sync_count = count; 568 - 569 - return 0; 570 - 571 - fail: 572 - for (i--; i >= 0; i--) 573 - drm_syncobj_put(se->out_syncs[i].syncobj); 574 - kvfree(se->out_syncs); 575 - 576 - return ret; 577 - } 578 - 579 - /* Get data for multiple binary semaphores synchronization. Parse syncobj 580 - * to be signaled when job completes (out_sync). 581 - */ 582 - static int 583 - v3d_get_multisync_submit_deps(struct drm_file *file_priv, 584 - struct drm_v3d_extension __user *ext, 585 - void *data) 586 - { 587 - struct drm_v3d_multi_sync multisync; 588 - struct v3d_submit_ext *se = data; 589 - int ret; 590 - 591 - if (copy_from_user(&multisync, ext, sizeof(multisync))) 592 - return -EFAULT; 593 - 594 - if (multisync.pad) 595 - return -EINVAL; 596 - 597 - ret = v3d_get_multisync_post_deps(file_priv, data, multisync.out_sync_count, 598 - multisync.out_syncs); 599 - if (ret) 600 - return ret; 601 - 602 - se->in_sync_count = multisync.in_sync_count; 603 - se->in_syncs = multisync.in_syncs; 604 - se->flags |= DRM_V3D_EXT_ID_MULTI_SYNC; 605 - se->wait_stage = multisync.wait_stage; 606 - 607 - return 0; 608 - } 609 - 610 - /* Whenever userspace sets ioctl extensions, v3d_get_extensions parses data 611 - * according to the extension id (name). 612 - */ 613 - static int 614 - v3d_get_extensions(struct drm_file *file_priv, 615 - u64 ext_handles, 616 - void *data) 617 - { 618 - struct drm_v3d_extension __user *user_ext; 619 - int ret; 620 - 621 - user_ext = u64_to_user_ptr(ext_handles); 622 - while (user_ext) { 623 - struct drm_v3d_extension ext; 624 - 625 - if (copy_from_user(&ext, user_ext, sizeof(ext))) { 626 - DRM_DEBUG("Failed to copy submit extension\n"); 627 - return -EFAULT; 628 - } 629 - 630 - switch (ext.id) { 631 - case DRM_V3D_EXT_ID_MULTI_SYNC: 632 - ret = v3d_get_multisync_submit_deps(file_priv, user_ext, data); 633 - if (ret) 634 - return ret; 635 - break; 636 - default: 637 - DRM_DEBUG_DRIVER("Unknown extension id: %d\n", ext.id); 638 - return -EINVAL; 639 - } 640 - 641 - user_ext = u64_to_user_ptr(ext.next); 642 - } 643 - 644 - return 0; 645 - } 646 - 647 - /** 648 - * v3d_submit_cl_ioctl() - Submits a job (frame) to the V3D. 649 - * @dev: DRM device 650 - * @data: ioctl argument 651 - * @file_priv: DRM file for this fd 652 - * 653 - * This is the main entrypoint for userspace to submit a 3D frame to 654 - * the GPU. Userspace provides the binner command list (if 655 - * applicable), and the kernel sets up the render command list to draw 656 - * to the framebuffer described in the ioctl, using the command lists 657 - * that the 3D engine's binner will produce. 658 - */ 659 - int 660 - v3d_submit_cl_ioctl(struct drm_device *dev, void *data, 661 - struct drm_file *file_priv) 662 - { 663 - struct v3d_dev *v3d = to_v3d_dev(dev); 664 - struct v3d_file_priv *v3d_priv = file_priv->driver_priv; 665 - struct drm_v3d_submit_cl *args = data; 666 - struct v3d_submit_ext se = {0}; 667 - struct v3d_bin_job *bin = NULL; 668 - struct v3d_render_job *render = NULL; 669 - struct v3d_job *clean_job = NULL; 670 - struct v3d_job *last_job; 671 - struct ww_acquire_ctx acquire_ctx; 672 - int ret = 0; 673 - 674 - trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end); 675 - 676 - if (args->pad) 677 - return -EINVAL; 678 - 679 - if (args->flags && 680 - args->flags & ~(DRM_V3D_SUBMIT_CL_FLUSH_CACHE | 681 - DRM_V3D_SUBMIT_EXTENSION)) { 682 - DRM_INFO("invalid flags: %d\n", args->flags); 683 - return -EINVAL; 684 - } 685 - 686 - if (args->flags & DRM_V3D_SUBMIT_EXTENSION) { 687 - ret = v3d_get_extensions(file_priv, args->extensions, &se); 688 - if (ret) { 689 - DRM_DEBUG("Failed to get extensions.\n"); 690 - return ret; 691 - } 692 - } 693 - 694 - ret = v3d_job_init(v3d, file_priv, (void *)&render, sizeof(*render), 695 - v3d_render_job_free, args->in_sync_rcl, &se, V3D_RENDER); 696 - if (ret) 697 - goto fail; 698 - 699 - render->start = args->rcl_start; 700 - render->end = args->rcl_end; 701 - INIT_LIST_HEAD(&render->unref_list); 702 - 703 - if (args->bcl_start != args->bcl_end) { 704 - ret = v3d_job_init(v3d, file_priv, (void *)&bin, sizeof(*bin), 705 - v3d_job_free, args->in_sync_bcl, &se, V3D_BIN); 706 - if (ret) 707 - goto fail; 708 - 709 - bin->start = args->bcl_start; 710 - bin->end = args->bcl_end; 711 - bin->qma = args->qma; 712 - bin->qms = args->qms; 713 - bin->qts = args->qts; 714 - bin->render = render; 715 - } 716 - 717 - if (args->flags & DRM_V3D_SUBMIT_CL_FLUSH_CACHE) { 718 - ret = v3d_job_init(v3d, file_priv, (void *)&clean_job, sizeof(*clean_job), 719 - v3d_job_free, 0, NULL, V3D_CACHE_CLEAN); 720 - if (ret) 721 - goto fail; 722 - 723 - last_job = clean_job; 724 - } else { 725 - last_job = &render->base; 726 - } 727 - 728 - ret = v3d_lookup_bos(dev, file_priv, last_job, 729 - args->bo_handles, args->bo_handle_count); 730 - if (ret) 731 - goto fail; 732 - 733 - ret = v3d_lock_bo_reservations(last_job, &acquire_ctx); 734 - if (ret) 735 - goto fail; 736 - 737 - if (args->perfmon_id) { 738 - render->base.perfmon = v3d_perfmon_find(v3d_priv, 739 - args->perfmon_id); 740 - 741 - if (!render->base.perfmon) { 742 - ret = -ENOENT; 743 - goto fail_perfmon; 744 - } 745 - } 746 - 747 - mutex_lock(&v3d->sched_lock); 748 - if (bin) { 749 - bin->base.perfmon = render->base.perfmon; 750 - v3d_perfmon_get(bin->base.perfmon); 751 - v3d_push_job(&bin->base); 752 - 753 - ret = drm_sched_job_add_dependency(&render->base.base, 754 - dma_fence_get(bin->base.done_fence)); 755 - if (ret) 756 - goto fail_unreserve; 757 - } 758 - 759 - v3d_push_job(&render->base); 760 - 761 - if (clean_job) { 762 - struct dma_fence *render_fence = 763 - dma_fence_get(render->base.done_fence); 764 - ret = drm_sched_job_add_dependency(&clean_job->base, 765 - render_fence); 766 - if (ret) 767 - goto fail_unreserve; 768 - clean_job->perfmon = render->base.perfmon; 769 - v3d_perfmon_get(clean_job->perfmon); 770 - v3d_push_job(clean_job); 771 - } 772 - 773 - mutex_unlock(&v3d->sched_lock); 774 - 775 - v3d_attach_fences_and_unlock_reservation(file_priv, 776 - last_job, 777 - &acquire_ctx, 778 - args->out_sync, 779 - &se, 780 - last_job->done_fence); 781 - 782 - if (bin) 783 - v3d_job_put(&bin->base); 784 - v3d_job_put(&render->base); 785 - if (clean_job) 786 - v3d_job_put(clean_job); 787 - 788 - return 0; 789 - 790 - fail_unreserve: 791 - mutex_unlock(&v3d->sched_lock); 792 - fail_perfmon: 793 - drm_gem_unlock_reservations(last_job->bo, 794 - last_job->bo_count, &acquire_ctx); 795 - fail: 796 - v3d_job_cleanup((void *)bin); 797 - v3d_job_cleanup((void *)render); 798 - v3d_job_cleanup(clean_job); 799 - v3d_put_multisync_post_deps(&se); 800 - 801 - return ret; 802 - } 803 - 804 - /** 805 - * v3d_submit_tfu_ioctl() - Submits a TFU (texture formatting) job to the V3D. 806 - * @dev: DRM device 807 - * @data: ioctl argument 808 - * @file_priv: DRM file for this fd 809 - * 810 - * Userspace provides the register setup for the TFU, which we don't 811 - * need to validate since the TFU is behind the MMU. 812 - */ 813 - int 814 - v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, 815 - struct drm_file *file_priv) 816 - { 817 - struct v3d_dev *v3d = to_v3d_dev(dev); 818 - struct drm_v3d_submit_tfu *args = data; 819 - struct v3d_submit_ext se = {0}; 820 - struct v3d_tfu_job *job = NULL; 821 - struct ww_acquire_ctx acquire_ctx; 822 - int ret = 0; 823 - 824 - trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia); 825 - 826 - if (args->flags && !(args->flags & DRM_V3D_SUBMIT_EXTENSION)) { 827 - DRM_DEBUG("invalid flags: %d\n", args->flags); 828 - return -EINVAL; 829 - } 830 - 831 - if (args->flags & DRM_V3D_SUBMIT_EXTENSION) { 832 - ret = v3d_get_extensions(file_priv, args->extensions, &se); 833 - if (ret) { 834 - DRM_DEBUG("Failed to get extensions.\n"); 835 - return ret; 836 - } 837 - } 838 - 839 - ret = v3d_job_init(v3d, file_priv, (void *)&job, sizeof(*job), 840 - v3d_job_free, args->in_sync, &se, V3D_TFU); 841 - if (ret) 842 - goto fail; 843 - 844 - job->base.bo = kcalloc(ARRAY_SIZE(args->bo_handles), 845 - sizeof(*job->base.bo), GFP_KERNEL); 846 - if (!job->base.bo) { 847 - ret = -ENOMEM; 848 - goto fail; 849 - } 850 - 851 - job->args = *args; 852 - 853 - for (job->base.bo_count = 0; 854 - job->base.bo_count < ARRAY_SIZE(args->bo_handles); 855 - job->base.bo_count++) { 856 - struct drm_gem_object *bo; 857 - 858 - if (!args->bo_handles[job->base.bo_count]) 859 - break; 860 - 861 - bo = drm_gem_object_lookup(file_priv, args->bo_handles[job->base.bo_count]); 862 - if (!bo) { 863 - DRM_DEBUG("Failed to look up GEM BO %d: %d\n", 864 - job->base.bo_count, 865 - args->bo_handles[job->base.bo_count]); 866 - ret = -ENOENT; 867 - goto fail; 868 - } 869 - job->base.bo[job->base.bo_count] = bo; 870 - } 871 - 872 - ret = v3d_lock_bo_reservations(&job->base, &acquire_ctx); 873 - if (ret) 874 - goto fail; 875 - 876 - mutex_lock(&v3d->sched_lock); 877 - v3d_push_job(&job->base); 878 - mutex_unlock(&v3d->sched_lock); 879 - 880 - v3d_attach_fences_and_unlock_reservation(file_priv, 881 - &job->base, &acquire_ctx, 882 - args->out_sync, 883 - &se, 884 - job->base.done_fence); 885 - 886 - v3d_job_put(&job->base); 887 - 888 - return 0; 889 - 890 - fail: 891 - v3d_job_cleanup((void *)job); 892 - v3d_put_multisync_post_deps(&se); 893 - 894 - return ret; 895 - } 896 - 897 - /** 898 - * v3d_submit_csd_ioctl() - Submits a CSD (texture formatting) job to the V3D. 899 - * @dev: DRM device 900 - * @data: ioctl argument 901 - * @file_priv: DRM file for this fd 902 - * 903 - * Userspace provides the register setup for the CSD, which we don't 904 - * need to validate since the CSD is behind the MMU. 905 - */ 906 - int 907 - v3d_submit_csd_ioctl(struct drm_device *dev, void *data, 908 - struct drm_file *file_priv) 909 - { 910 - struct v3d_dev *v3d = to_v3d_dev(dev); 911 - struct v3d_file_priv *v3d_priv = file_priv->driver_priv; 912 - struct drm_v3d_submit_csd *args = data; 913 - struct v3d_submit_ext se = {0}; 914 - struct v3d_csd_job *job = NULL; 915 - struct v3d_job *clean_job = NULL; 916 - struct ww_acquire_ctx acquire_ctx; 917 - int ret; 918 - 919 - trace_v3d_submit_csd_ioctl(&v3d->drm, args->cfg[5], args->cfg[6]); 920 - 921 - if (args->pad) 922 - return -EINVAL; 923 - 924 - if (!v3d_has_csd(v3d)) { 925 - DRM_DEBUG("Attempting CSD submit on non-CSD hardware\n"); 926 - return -EINVAL; 927 - } 928 - 929 - if (args->flags && !(args->flags & DRM_V3D_SUBMIT_EXTENSION)) { 930 - DRM_INFO("invalid flags: %d\n", args->flags); 931 - return -EINVAL; 932 - } 933 - 934 - if (args->flags & DRM_V3D_SUBMIT_EXTENSION) { 935 - ret = v3d_get_extensions(file_priv, args->extensions, &se); 936 - if (ret) { 937 - DRM_DEBUG("Failed to get extensions.\n"); 938 - return ret; 939 - } 940 - } 941 - 942 - ret = v3d_job_init(v3d, file_priv, (void *)&job, sizeof(*job), 943 - v3d_job_free, args->in_sync, &se, V3D_CSD); 944 - if (ret) 945 - goto fail; 946 - 947 - ret = v3d_job_init(v3d, file_priv, (void *)&clean_job, sizeof(*clean_job), 948 - v3d_job_free, 0, NULL, V3D_CACHE_CLEAN); 949 - if (ret) 950 - goto fail; 951 - 952 - job->args = *args; 953 - 954 - ret = v3d_lookup_bos(dev, file_priv, clean_job, 955 - args->bo_handles, args->bo_handle_count); 956 - if (ret) 957 - goto fail; 958 - 959 - ret = v3d_lock_bo_reservations(clean_job, &acquire_ctx); 960 - if (ret) 961 - goto fail; 962 - 963 - if (args->perfmon_id) { 964 - job->base.perfmon = v3d_perfmon_find(v3d_priv, 965 - args->perfmon_id); 966 - if (!job->base.perfmon) { 967 - ret = -ENOENT; 968 - goto fail_perfmon; 969 - } 970 - } 971 - 972 - mutex_lock(&v3d->sched_lock); 973 - v3d_push_job(&job->base); 974 - 975 - ret = drm_sched_job_add_dependency(&clean_job->base, 976 - dma_fence_get(job->base.done_fence)); 977 - if (ret) 978 - goto fail_unreserve; 979 - 980 - v3d_push_job(clean_job); 981 - mutex_unlock(&v3d->sched_lock); 982 - 983 - v3d_attach_fences_and_unlock_reservation(file_priv, 984 - clean_job, 985 - &acquire_ctx, 986 - args->out_sync, 987 - &se, 988 - clean_job->done_fence); 989 - 990 - v3d_job_put(&job->base); 991 - v3d_job_put(clean_job); 992 - 993 - return 0; 994 - 995 - fail_unreserve: 996 - mutex_unlock(&v3d->sched_lock); 997 - fail_perfmon: 998 - drm_gem_unlock_reservations(clean_job->bo, clean_job->bo_count, 999 - &acquire_ctx); 1000 - fail: 1001 - v3d_job_cleanup((void *)job); 1002 - v3d_job_cleanup(clean_job); 1003 - v3d_put_multisync_post_deps(&se); 1004 - 1005 - return ret; 1006 242 } 1007 243 1008 244 int
+316
drivers/gpu/drm/v3d/v3d_sched.c
··· 21 21 #include <linux/sched/clock.h> 22 22 #include <linux/kthread.h> 23 23 24 + #include <drm/drm_syncobj.h> 25 + 24 26 #include "v3d_drv.h" 25 27 #include "v3d_regs.h" 26 28 #include "v3d_trace.h" 29 + 30 + #define V3D_CSD_CFG012_WG_COUNT_SHIFT 16 27 31 28 32 static struct v3d_job * 29 33 to_v3d_job(struct drm_sched_job *sched_job) ··· 59 55 return container_of(sched_job, struct v3d_csd_job, base.base); 60 56 } 61 57 58 + static struct v3d_cpu_job * 59 + to_cpu_job(struct drm_sched_job *sched_job) 60 + { 61 + return container_of(sched_job, struct v3d_cpu_job, base.base); 62 + } 63 + 62 64 static void 63 65 v3d_sched_job_free(struct drm_sched_job *sched_job) 64 66 { 65 67 struct v3d_job *job = to_v3d_job(sched_job); 66 68 67 69 v3d_job_cleanup(job); 70 + } 71 + 72 + static void 73 + v3d_cpu_job_free(struct drm_sched_job *sched_job) 74 + { 75 + struct v3d_cpu_job *job = to_cpu_job(sched_job); 76 + struct v3d_timestamp_query_info *timestamp_query = &job->timestamp_query; 77 + struct v3d_performance_query_info *performance_query = &job->performance_query; 78 + 79 + if (timestamp_query->queries) { 80 + for (int i = 0; i < timestamp_query->count; i++) 81 + drm_syncobj_put(timestamp_query->queries[i].syncobj); 82 + kvfree(timestamp_query->queries); 83 + } 84 + 85 + if (performance_query->queries) { 86 + for (int i = 0; i < performance_query->count; i++) 87 + drm_syncobj_put(performance_query->queries[i].syncobj); 88 + kvfree(performance_query->queries); 89 + } 90 + 91 + v3d_job_cleanup(&job->base); 68 92 } 69 93 70 94 static void ··· 294 262 return fence; 295 263 } 296 264 265 + static void 266 + v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job) 267 + { 268 + struct v3d_indirect_csd_info *indirect_csd = &job->indirect_csd; 269 + struct v3d_bo *bo = to_v3d_bo(job->base.bo[0]); 270 + struct v3d_bo *indirect = to_v3d_bo(indirect_csd->indirect); 271 + struct drm_v3d_submit_csd *args = &indirect_csd->job->args; 272 + u32 *wg_counts; 273 + 274 + v3d_get_bo_vaddr(bo); 275 + v3d_get_bo_vaddr(indirect); 276 + 277 + wg_counts = (uint32_t *)(bo->vaddr + indirect_csd->offset); 278 + 279 + if (wg_counts[0] == 0 || wg_counts[1] == 0 || wg_counts[2] == 0) 280 + return; 281 + 282 + args->cfg[0] = wg_counts[0] << V3D_CSD_CFG012_WG_COUNT_SHIFT; 283 + args->cfg[1] = wg_counts[1] << V3D_CSD_CFG012_WG_COUNT_SHIFT; 284 + args->cfg[2] = wg_counts[2] << V3D_CSD_CFG012_WG_COUNT_SHIFT; 285 + args->cfg[4] = DIV_ROUND_UP(indirect_csd->wg_size, 16) * 286 + (wg_counts[0] * wg_counts[1] * wg_counts[2]) - 1; 287 + 288 + for (int i = 0; i < 3; i++) { 289 + /* 0xffffffff indicates that the uniform rewrite is not needed */ 290 + if (indirect_csd->wg_uniform_offsets[i] != 0xffffffff) { 291 + u32 uniform_idx = indirect_csd->wg_uniform_offsets[i]; 292 + ((uint32_t *)indirect->vaddr)[uniform_idx] = wg_counts[i]; 293 + } 294 + } 295 + 296 + v3d_put_bo_vaddr(indirect); 297 + v3d_put_bo_vaddr(bo); 298 + } 299 + 300 + static void 301 + v3d_timestamp_query(struct v3d_cpu_job *job) 302 + { 303 + struct v3d_timestamp_query_info *timestamp_query = &job->timestamp_query; 304 + struct v3d_bo *bo = to_v3d_bo(job->base.bo[0]); 305 + u8 *value_addr; 306 + 307 + v3d_get_bo_vaddr(bo); 308 + 309 + for (int i = 0; i < timestamp_query->count; i++) { 310 + value_addr = ((u8 *)bo->vaddr) + timestamp_query->queries[i].offset; 311 + *((u64 *)value_addr) = i == 0 ? ktime_get_ns() : 0ull; 312 + 313 + drm_syncobj_replace_fence(timestamp_query->queries[i].syncobj, 314 + job->base.done_fence); 315 + } 316 + 317 + v3d_put_bo_vaddr(bo); 318 + } 319 + 320 + static void 321 + v3d_reset_timestamp_queries(struct v3d_cpu_job *job) 322 + { 323 + struct v3d_timestamp_query_info *timestamp_query = &job->timestamp_query; 324 + struct v3d_timestamp_query *queries = timestamp_query->queries; 325 + struct v3d_bo *bo = to_v3d_bo(job->base.bo[0]); 326 + u8 *value_addr; 327 + 328 + v3d_get_bo_vaddr(bo); 329 + 330 + for (int i = 0; i < timestamp_query->count; i++) { 331 + value_addr = ((u8 *)bo->vaddr) + queries[i].offset; 332 + *((u64 *)value_addr) = 0; 333 + 334 + drm_syncobj_replace_fence(queries[i].syncobj, NULL); 335 + } 336 + 337 + v3d_put_bo_vaddr(bo); 338 + } 339 + 340 + static void 341 + write_to_buffer(void *dst, u32 idx, bool do_64bit, u64 value) 342 + { 343 + if (do_64bit) { 344 + u64 *dst64 = (u64 *)dst; 345 + 346 + dst64[idx] = value; 347 + } else { 348 + u32 *dst32 = (u32 *)dst; 349 + 350 + dst32[idx] = (u32)value; 351 + } 352 + } 353 + 354 + static void 355 + v3d_copy_query_results(struct v3d_cpu_job *job) 356 + { 357 + struct v3d_timestamp_query_info *timestamp_query = &job->timestamp_query; 358 + struct v3d_timestamp_query *queries = timestamp_query->queries; 359 + struct v3d_bo *bo = to_v3d_bo(job->base.bo[0]); 360 + struct v3d_bo *timestamp = to_v3d_bo(job->base.bo[1]); 361 + struct v3d_copy_query_results_info *copy = &job->copy; 362 + struct dma_fence *fence; 363 + u8 *query_addr; 364 + bool available, write_result; 365 + u8 *data; 366 + int i; 367 + 368 + v3d_get_bo_vaddr(bo); 369 + v3d_get_bo_vaddr(timestamp); 370 + 371 + data = ((u8 *)bo->vaddr) + copy->offset; 372 + 373 + for (i = 0; i < timestamp_query->count; i++) { 374 + fence = drm_syncobj_fence_get(queries[i].syncobj); 375 + available = fence ? dma_fence_is_signaled(fence) : false; 376 + 377 + write_result = available || copy->do_partial; 378 + if (write_result) { 379 + query_addr = ((u8 *)timestamp->vaddr) + queries[i].offset; 380 + write_to_buffer(data, 0, copy->do_64bit, *((u64 *)query_addr)); 381 + } 382 + 383 + if (copy->availability_bit) 384 + write_to_buffer(data, 1, copy->do_64bit, available ? 1u : 0u); 385 + 386 + data += copy->stride; 387 + 388 + dma_fence_put(fence); 389 + } 390 + 391 + v3d_put_bo_vaddr(timestamp); 392 + v3d_put_bo_vaddr(bo); 393 + } 394 + 395 + static void 396 + v3d_reset_performance_queries(struct v3d_cpu_job *job) 397 + { 398 + struct v3d_performance_query_info *performance_query = &job->performance_query; 399 + struct v3d_file_priv *v3d_priv = job->base.file->driver_priv; 400 + struct v3d_dev *v3d = job->base.v3d; 401 + struct v3d_perfmon *perfmon; 402 + 403 + for (int i = 0; i < performance_query->count; i++) { 404 + for (int j = 0; j < performance_query->nperfmons; j++) { 405 + perfmon = v3d_perfmon_find(v3d_priv, 406 + performance_query->queries[i].kperfmon_ids[j]); 407 + if (!perfmon) { 408 + DRM_DEBUG("Failed to find perfmon."); 409 + continue; 410 + } 411 + 412 + v3d_perfmon_stop(v3d, perfmon, false); 413 + 414 + memset(perfmon->values, 0, perfmon->ncounters * sizeof(u64)); 415 + 416 + v3d_perfmon_put(perfmon); 417 + } 418 + 419 + drm_syncobj_replace_fence(performance_query->queries[i].syncobj, NULL); 420 + } 421 + } 422 + 423 + static void 424 + v3d_write_performance_query_result(struct v3d_cpu_job *job, void *data, u32 query) 425 + { 426 + struct v3d_performance_query_info *performance_query = &job->performance_query; 427 + struct v3d_copy_query_results_info *copy = &job->copy; 428 + struct v3d_file_priv *v3d_priv = job->base.file->driver_priv; 429 + struct v3d_dev *v3d = job->base.v3d; 430 + struct v3d_perfmon *perfmon; 431 + u64 counter_values[V3D_PERFCNT_NUM]; 432 + 433 + for (int i = 0; i < performance_query->nperfmons; i++) { 434 + perfmon = v3d_perfmon_find(v3d_priv, 435 + performance_query->queries[query].kperfmon_ids[i]); 436 + if (!perfmon) { 437 + DRM_DEBUG("Failed to find perfmon."); 438 + continue; 439 + } 440 + 441 + v3d_perfmon_stop(v3d, perfmon, true); 442 + 443 + memcpy(&counter_values[i * DRM_V3D_MAX_PERF_COUNTERS], perfmon->values, 444 + perfmon->ncounters * sizeof(u64)); 445 + 446 + v3d_perfmon_put(perfmon); 447 + } 448 + 449 + for (int i = 0; i < performance_query->ncounters; i++) 450 + write_to_buffer(data, i, copy->do_64bit, counter_values[i]); 451 + } 452 + 453 + static void 454 + v3d_copy_performance_query(struct v3d_cpu_job *job) 455 + { 456 + struct v3d_performance_query_info *performance_query = &job->performance_query; 457 + struct v3d_copy_query_results_info *copy = &job->copy; 458 + struct v3d_bo *bo = to_v3d_bo(job->base.bo[0]); 459 + struct dma_fence *fence; 460 + bool available, write_result; 461 + u8 *data; 462 + 463 + v3d_get_bo_vaddr(bo); 464 + 465 + data = ((u8 *)bo->vaddr) + copy->offset; 466 + 467 + for (int i = 0; i < performance_query->count; i++) { 468 + fence = drm_syncobj_fence_get(performance_query->queries[i].syncobj); 469 + available = fence ? dma_fence_is_signaled(fence) : false; 470 + 471 + write_result = available || copy->do_partial; 472 + if (write_result) 473 + v3d_write_performance_query_result(job, data, i); 474 + 475 + if (copy->availability_bit) 476 + write_to_buffer(data, performance_query->ncounters, 477 + copy->do_64bit, available ? 1u : 0u); 478 + 479 + data += copy->stride; 480 + 481 + dma_fence_put(fence); 482 + } 483 + 484 + v3d_put_bo_vaddr(bo); 485 + } 486 + 487 + static const v3d_cpu_job_fn cpu_job_function[] = { 488 + [V3D_CPU_JOB_TYPE_INDIRECT_CSD] = v3d_rewrite_csd_job_wg_counts_from_indirect, 489 + [V3D_CPU_JOB_TYPE_TIMESTAMP_QUERY] = v3d_timestamp_query, 490 + [V3D_CPU_JOB_TYPE_RESET_TIMESTAMP_QUERY] = v3d_reset_timestamp_queries, 491 + [V3D_CPU_JOB_TYPE_COPY_TIMESTAMP_QUERY] = v3d_copy_query_results, 492 + [V3D_CPU_JOB_TYPE_RESET_PERFORMANCE_QUERY] = v3d_reset_performance_queries, 493 + [V3D_CPU_JOB_TYPE_COPY_PERFORMANCE_QUERY] = v3d_copy_performance_query, 494 + }; 495 + 496 + static struct dma_fence * 497 + v3d_cpu_job_run(struct drm_sched_job *sched_job) 498 + { 499 + struct v3d_cpu_job *job = to_cpu_job(sched_job); 500 + struct v3d_dev *v3d = job->base.v3d; 501 + struct v3d_file_priv *file = job->base.file->driver_priv; 502 + u64 runtime; 503 + 504 + v3d->cpu_job = job; 505 + 506 + if (job->job_type >= ARRAY_SIZE(cpu_job_function)) { 507 + DRM_DEBUG_DRIVER("Unknown CPU job: %d\n", job->job_type); 508 + return NULL; 509 + } 510 + 511 + file->start_ns[V3D_CPU] = local_clock(); 512 + v3d->queue[V3D_CPU].start_ns = file->start_ns[V3D_CPU]; 513 + 514 + trace_v3d_cpu_job_begin(&v3d->drm, job->job_type); 515 + 516 + cpu_job_function[job->job_type](job); 517 + 518 + trace_v3d_cpu_job_end(&v3d->drm, job->job_type); 519 + 520 + runtime = local_clock() - file->start_ns[V3D_CPU]; 521 + 522 + file->enabled_ns[V3D_CPU] += runtime; 523 + v3d->queue[V3D_CPU].enabled_ns += runtime; 524 + 525 + file->jobs_sent[V3D_CPU]++; 526 + v3d->queue[V3D_CPU].jobs_sent++; 527 + 528 + file->start_ns[V3D_CPU] = 0; 529 + v3d->queue[V3D_CPU].start_ns = 0; 530 + 531 + return NULL; 532 + } 533 + 297 534 static struct dma_fence * 298 535 v3d_cache_clean_job_run(struct drm_sched_job *sched_job) 299 536 { ··· 717 416 .free_job = v3d_sched_job_free 718 417 }; 719 418 419 + static const struct drm_sched_backend_ops v3d_cpu_sched_ops = { 420 + .run_job = v3d_cpu_job_run, 421 + .timedout_job = v3d_generic_job_timedout, 422 + .free_job = v3d_cpu_job_free 423 + }; 424 + 720 425 int 721 426 v3d_sched_init(struct v3d_dev *v3d) 722 427 { ··· 777 470 if (ret) 778 471 goto fail; 779 472 } 473 + 474 + ret = drm_sched_init(&v3d->queue[V3D_CPU].sched, 475 + &v3d_cpu_sched_ops, NULL, 476 + DRM_SCHED_PRIORITY_COUNT, 477 + 1, job_hang_limit, 478 + msecs_to_jiffies(hang_limit_ms), NULL, 479 + NULL, "v3d_cpu", v3d->drm.dev); 480 + if (ret) 481 + goto fail; 780 482 781 483 return 0; 782 484
+1320
drivers/gpu/drm/v3d/v3d_submit.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Copyright (C) 2014-2018 Broadcom 4 + * Copyright (C) 2023 Raspberry Pi 5 + */ 6 + 7 + #include <drm/drm_syncobj.h> 8 + 9 + #include "v3d_drv.h" 10 + #include "v3d_regs.h" 11 + #include "v3d_trace.h" 12 + 13 + /* Takes the reservation lock on all the BOs being referenced, so that 14 + * at queue submit time we can update the reservations. 15 + * 16 + * We don't lock the RCL the tile alloc/state BOs, or overflow memory 17 + * (all of which are on exec->unref_list). They're entirely private 18 + * to v3d, so we don't attach dma-buf fences to them. 19 + */ 20 + static int 21 + v3d_lock_bo_reservations(struct v3d_job *job, 22 + struct ww_acquire_ctx *acquire_ctx) 23 + { 24 + int i, ret; 25 + 26 + ret = drm_gem_lock_reservations(job->bo, job->bo_count, acquire_ctx); 27 + if (ret) 28 + return ret; 29 + 30 + for (i = 0; i < job->bo_count; i++) { 31 + ret = dma_resv_reserve_fences(job->bo[i]->resv, 1); 32 + if (ret) 33 + goto fail; 34 + 35 + ret = drm_sched_job_add_implicit_dependencies(&job->base, 36 + job->bo[i], true); 37 + if (ret) 38 + goto fail; 39 + } 40 + 41 + return 0; 42 + 43 + fail: 44 + drm_gem_unlock_reservations(job->bo, job->bo_count, acquire_ctx); 45 + return ret; 46 + } 47 + 48 + /** 49 + * v3d_lookup_bos() - Sets up job->bo[] with the GEM objects 50 + * referenced by the job. 51 + * @dev: DRM device 52 + * @file_priv: DRM file for this fd 53 + * @job: V3D job being set up 54 + * @bo_handles: GEM handles 55 + * @bo_count: Number of GEM handles passed in 56 + * 57 + * The command validator needs to reference BOs by their index within 58 + * the submitted job's BO list. This does the validation of the job's 59 + * BO list and reference counting for the lifetime of the job. 60 + * 61 + * Note that this function doesn't need to unreference the BOs on 62 + * failure, because that will happen at v3d_exec_cleanup() time. 63 + */ 64 + static int 65 + v3d_lookup_bos(struct drm_device *dev, 66 + struct drm_file *file_priv, 67 + struct v3d_job *job, 68 + u64 bo_handles, 69 + u32 bo_count) 70 + { 71 + job->bo_count = bo_count; 72 + 73 + if (!job->bo_count) { 74 + /* See comment on bo_index for why we have to check 75 + * this. 76 + */ 77 + DRM_DEBUG("Rendering requires BOs\n"); 78 + return -EINVAL; 79 + } 80 + 81 + return drm_gem_objects_lookup(file_priv, 82 + (void __user *)(uintptr_t)bo_handles, 83 + job->bo_count, &job->bo); 84 + } 85 + 86 + static void 87 + v3d_job_free(struct kref *ref) 88 + { 89 + struct v3d_job *job = container_of(ref, struct v3d_job, refcount); 90 + int i; 91 + 92 + if (job->bo) { 93 + for (i = 0; i < job->bo_count; i++) 94 + drm_gem_object_put(job->bo[i]); 95 + kvfree(job->bo); 96 + } 97 + 98 + dma_fence_put(job->irq_fence); 99 + dma_fence_put(job->done_fence); 100 + 101 + if (job->perfmon) 102 + v3d_perfmon_put(job->perfmon); 103 + 104 + kfree(job); 105 + } 106 + 107 + static void 108 + v3d_render_job_free(struct kref *ref) 109 + { 110 + struct v3d_render_job *job = container_of(ref, struct v3d_render_job, 111 + base.refcount); 112 + struct v3d_bo *bo, *save; 113 + 114 + list_for_each_entry_safe(bo, save, &job->unref_list, unref_head) { 115 + drm_gem_object_put(&bo->base.base); 116 + } 117 + 118 + v3d_job_free(ref); 119 + } 120 + 121 + void v3d_job_cleanup(struct v3d_job *job) 122 + { 123 + if (!job) 124 + return; 125 + 126 + drm_sched_job_cleanup(&job->base); 127 + v3d_job_put(job); 128 + } 129 + 130 + void v3d_job_put(struct v3d_job *job) 131 + { 132 + if (!job) 133 + return; 134 + 135 + kref_put(&job->refcount, job->free); 136 + } 137 + 138 + static int 139 + v3d_job_allocate(void **container, size_t size) 140 + { 141 + *container = kcalloc(1, size, GFP_KERNEL); 142 + if (!*container) { 143 + DRM_ERROR("Cannot allocate memory for V3D job.\n"); 144 + return -ENOMEM; 145 + } 146 + 147 + return 0; 148 + } 149 + 150 + static int 151 + v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, 152 + struct v3d_job *job, void (*free)(struct kref *ref), 153 + u32 in_sync, struct v3d_submit_ext *se, enum v3d_queue queue) 154 + { 155 + struct v3d_file_priv *v3d_priv = file_priv->driver_priv; 156 + bool has_multisync = se && (se->flags & DRM_V3D_EXT_ID_MULTI_SYNC); 157 + int ret, i; 158 + 159 + job->v3d = v3d; 160 + job->free = free; 161 + job->file = file_priv; 162 + 163 + ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue], 164 + 1, v3d_priv); 165 + if (ret) 166 + return ret; 167 + 168 + if (has_multisync) { 169 + if (se->in_sync_count && se->wait_stage == queue) { 170 + struct drm_v3d_sem __user *handle = u64_to_user_ptr(se->in_syncs); 171 + 172 + for (i = 0; i < se->in_sync_count; i++) { 173 + struct drm_v3d_sem in; 174 + 175 + if (copy_from_user(&in, handle++, sizeof(in))) { 176 + ret = -EFAULT; 177 + DRM_DEBUG("Failed to copy wait dep handle.\n"); 178 + goto fail_deps; 179 + } 180 + ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in.handle, 0); 181 + 182 + // TODO: Investigate why this was filtered out for the IOCTL. 183 + if (ret && ret != -ENOENT) 184 + goto fail_deps; 185 + } 186 + } 187 + } else { 188 + ret = drm_sched_job_add_syncobj_dependency(&job->base, file_priv, in_sync, 0); 189 + 190 + // TODO: Investigate why this was filtered out for the IOCTL. 191 + if (ret && ret != -ENOENT) 192 + goto fail_deps; 193 + } 194 + 195 + kref_init(&job->refcount); 196 + 197 + return 0; 198 + 199 + fail_deps: 200 + drm_sched_job_cleanup(&job->base); 201 + return ret; 202 + } 203 + 204 + static void 205 + v3d_push_job(struct v3d_job *job) 206 + { 207 + drm_sched_job_arm(&job->base); 208 + 209 + job->done_fence = dma_fence_get(&job->base.s_fence->finished); 210 + 211 + /* put by scheduler job completion */ 212 + kref_get(&job->refcount); 213 + 214 + drm_sched_entity_push_job(&job->base); 215 + } 216 + 217 + static void 218 + v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv, 219 + struct v3d_job *job, 220 + struct ww_acquire_ctx *acquire_ctx, 221 + u32 out_sync, 222 + struct v3d_submit_ext *se, 223 + struct dma_fence *done_fence) 224 + { 225 + struct drm_syncobj *sync_out; 226 + bool has_multisync = se && (se->flags & DRM_V3D_EXT_ID_MULTI_SYNC); 227 + int i; 228 + 229 + for (i = 0; i < job->bo_count; i++) { 230 + /* XXX: Use shared fences for read-only objects. */ 231 + dma_resv_add_fence(job->bo[i]->resv, job->done_fence, 232 + DMA_RESV_USAGE_WRITE); 233 + } 234 + 235 + drm_gem_unlock_reservations(job->bo, job->bo_count, acquire_ctx); 236 + 237 + /* Update the return sync object for the job */ 238 + /* If it only supports a single signal semaphore*/ 239 + if (!has_multisync) { 240 + sync_out = drm_syncobj_find(file_priv, out_sync); 241 + if (sync_out) { 242 + drm_syncobj_replace_fence(sync_out, done_fence); 243 + drm_syncobj_put(sync_out); 244 + } 245 + return; 246 + } 247 + 248 + /* If multiple semaphores extension is supported */ 249 + if (se->out_sync_count) { 250 + for (i = 0; i < se->out_sync_count; i++) { 251 + drm_syncobj_replace_fence(se->out_syncs[i].syncobj, 252 + done_fence); 253 + drm_syncobj_put(se->out_syncs[i].syncobj); 254 + } 255 + kvfree(se->out_syncs); 256 + } 257 + } 258 + 259 + static int 260 + v3d_setup_csd_jobs_and_bos(struct drm_file *file_priv, 261 + struct v3d_dev *v3d, 262 + struct drm_v3d_submit_csd *args, 263 + struct v3d_csd_job **job, 264 + struct v3d_job **clean_job, 265 + struct v3d_submit_ext *se, 266 + struct ww_acquire_ctx *acquire_ctx) 267 + { 268 + int ret; 269 + 270 + ret = v3d_job_allocate((void *)job, sizeof(**job)); 271 + if (ret) 272 + return ret; 273 + 274 + ret = v3d_job_init(v3d, file_priv, &(*job)->base, 275 + v3d_job_free, args->in_sync, se, V3D_CSD); 276 + if (ret) 277 + return ret; 278 + 279 + ret = v3d_job_allocate((void *)clean_job, sizeof(**clean_job)); 280 + if (ret) 281 + return ret; 282 + 283 + ret = v3d_job_init(v3d, file_priv, *clean_job, 284 + v3d_job_free, 0, NULL, V3D_CACHE_CLEAN); 285 + if (ret) 286 + return ret; 287 + 288 + (*job)->args = *args; 289 + 290 + ret = v3d_lookup_bos(&v3d->drm, file_priv, *clean_job, 291 + args->bo_handles, args->bo_handle_count); 292 + if (ret) 293 + return ret; 294 + 295 + return v3d_lock_bo_reservations(*clean_job, acquire_ctx); 296 + } 297 + 298 + static void 299 + v3d_put_multisync_post_deps(struct v3d_submit_ext *se) 300 + { 301 + unsigned int i; 302 + 303 + if (!(se && se->out_sync_count)) 304 + return; 305 + 306 + for (i = 0; i < se->out_sync_count; i++) 307 + drm_syncobj_put(se->out_syncs[i].syncobj); 308 + kvfree(se->out_syncs); 309 + } 310 + 311 + static int 312 + v3d_get_multisync_post_deps(struct drm_file *file_priv, 313 + struct v3d_submit_ext *se, 314 + u32 count, u64 handles) 315 + { 316 + struct drm_v3d_sem __user *post_deps; 317 + int i, ret; 318 + 319 + if (!count) 320 + return 0; 321 + 322 + se->out_syncs = (struct v3d_submit_outsync *) 323 + kvmalloc_array(count, 324 + sizeof(struct v3d_submit_outsync), 325 + GFP_KERNEL); 326 + if (!se->out_syncs) 327 + return -ENOMEM; 328 + 329 + post_deps = u64_to_user_ptr(handles); 330 + 331 + for (i = 0; i < count; i++) { 332 + struct drm_v3d_sem out; 333 + 334 + if (copy_from_user(&out, post_deps++, sizeof(out))) { 335 + ret = -EFAULT; 336 + DRM_DEBUG("Failed to copy post dep handles\n"); 337 + goto fail; 338 + } 339 + 340 + se->out_syncs[i].syncobj = drm_syncobj_find(file_priv, 341 + out.handle); 342 + if (!se->out_syncs[i].syncobj) { 343 + ret = -EINVAL; 344 + goto fail; 345 + } 346 + } 347 + se->out_sync_count = count; 348 + 349 + return 0; 350 + 351 + fail: 352 + for (i--; i >= 0; i--) 353 + drm_syncobj_put(se->out_syncs[i].syncobj); 354 + kvfree(se->out_syncs); 355 + 356 + return ret; 357 + } 358 + 359 + /* Get data for multiple binary semaphores synchronization. Parse syncobj 360 + * to be signaled when job completes (out_sync). 361 + */ 362 + static int 363 + v3d_get_multisync_submit_deps(struct drm_file *file_priv, 364 + struct drm_v3d_extension __user *ext, 365 + struct v3d_submit_ext *se) 366 + { 367 + struct drm_v3d_multi_sync multisync; 368 + int ret; 369 + 370 + if (se->in_sync_count || se->out_sync_count) { 371 + DRM_DEBUG("Two multisync extensions were added to the same job."); 372 + return -EINVAL; 373 + } 374 + 375 + if (copy_from_user(&multisync, ext, sizeof(multisync))) 376 + return -EFAULT; 377 + 378 + if (multisync.pad) 379 + return -EINVAL; 380 + 381 + ret = v3d_get_multisync_post_deps(file_priv, se, multisync.out_sync_count, 382 + multisync.out_syncs); 383 + if (ret) 384 + return ret; 385 + 386 + se->in_sync_count = multisync.in_sync_count; 387 + se->in_syncs = multisync.in_syncs; 388 + se->flags |= DRM_V3D_EXT_ID_MULTI_SYNC; 389 + se->wait_stage = multisync.wait_stage; 390 + 391 + return 0; 392 + } 393 + 394 + /* Get data for the indirect CSD job submission. */ 395 + static int 396 + v3d_get_cpu_indirect_csd_params(struct drm_file *file_priv, 397 + struct drm_v3d_extension __user *ext, 398 + struct v3d_cpu_job *job) 399 + { 400 + struct v3d_file_priv *v3d_priv = file_priv->driver_priv; 401 + struct v3d_dev *v3d = v3d_priv->v3d; 402 + struct drm_v3d_indirect_csd indirect_csd; 403 + struct v3d_indirect_csd_info *info = &job->indirect_csd; 404 + 405 + if (!job) { 406 + DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); 407 + return -EINVAL; 408 + } 409 + 410 + if (job->job_type) { 411 + DRM_DEBUG("Two CPU job extensions were added to the same CPU job.\n"); 412 + return -EINVAL; 413 + } 414 + 415 + if (copy_from_user(&indirect_csd, ext, sizeof(indirect_csd))) 416 + return -EFAULT; 417 + 418 + if (!v3d_has_csd(v3d)) { 419 + DRM_DEBUG("Attempting CSD submit on non-CSD hardware.\n"); 420 + return -EINVAL; 421 + } 422 + 423 + job->job_type = V3D_CPU_JOB_TYPE_INDIRECT_CSD; 424 + info->offset = indirect_csd.offset; 425 + info->wg_size = indirect_csd.wg_size; 426 + memcpy(&info->wg_uniform_offsets, &indirect_csd.wg_uniform_offsets, 427 + sizeof(indirect_csd.wg_uniform_offsets)); 428 + 429 + info->indirect = drm_gem_object_lookup(file_priv, indirect_csd.indirect); 430 + 431 + return v3d_setup_csd_jobs_and_bos(file_priv, v3d, &indirect_csd.submit, 432 + &info->job, &info->clean_job, 433 + NULL, &info->acquire_ctx); 434 + } 435 + 436 + /* Get data for the query timestamp job submission. */ 437 + static int 438 + v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv, 439 + struct drm_v3d_extension __user *ext, 440 + struct v3d_cpu_job *job) 441 + { 442 + u32 __user *offsets, *syncs; 443 + struct drm_v3d_timestamp_query timestamp; 444 + 445 + if (!job) { 446 + DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); 447 + return -EINVAL; 448 + } 449 + 450 + if (job->job_type) { 451 + DRM_DEBUG("Two CPU job extensions were added to the same CPU job.\n"); 452 + return -EINVAL; 453 + } 454 + 455 + if (copy_from_user(&timestamp, ext, sizeof(timestamp))) 456 + return -EFAULT; 457 + 458 + if (timestamp.pad) 459 + return -EINVAL; 460 + 461 + job->job_type = V3D_CPU_JOB_TYPE_TIMESTAMP_QUERY; 462 + 463 + job->timestamp_query.queries = kvmalloc_array(timestamp.count, 464 + sizeof(struct v3d_timestamp_query), 465 + GFP_KERNEL); 466 + if (!job->timestamp_query.queries) 467 + return -ENOMEM; 468 + 469 + offsets = u64_to_user_ptr(timestamp.offsets); 470 + syncs = u64_to_user_ptr(timestamp.syncs); 471 + 472 + for (int i = 0; i < timestamp.count; i++) { 473 + u32 offset, sync; 474 + 475 + if (copy_from_user(&offset, offsets++, sizeof(offset))) { 476 + kvfree(job->timestamp_query.queries); 477 + return -EFAULT; 478 + } 479 + 480 + job->timestamp_query.queries[i].offset = offset; 481 + 482 + if (copy_from_user(&sync, syncs++, sizeof(sync))) { 483 + kvfree(job->timestamp_query.queries); 484 + return -EFAULT; 485 + } 486 + 487 + job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); 488 + } 489 + job->timestamp_query.count = timestamp.count; 490 + 491 + return 0; 492 + } 493 + 494 + static int 495 + v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv, 496 + struct drm_v3d_extension __user *ext, 497 + struct v3d_cpu_job *job) 498 + { 499 + u32 __user *syncs; 500 + struct drm_v3d_reset_timestamp_query reset; 501 + 502 + if (!job) { 503 + DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); 504 + return -EINVAL; 505 + } 506 + 507 + if (job->job_type) { 508 + DRM_DEBUG("Two CPU job extensions were added to the same CPU job.\n"); 509 + return -EINVAL; 510 + } 511 + 512 + if (copy_from_user(&reset, ext, sizeof(reset))) 513 + return -EFAULT; 514 + 515 + job->job_type = V3D_CPU_JOB_TYPE_RESET_TIMESTAMP_QUERY; 516 + 517 + job->timestamp_query.queries = kvmalloc_array(reset.count, 518 + sizeof(struct v3d_timestamp_query), 519 + GFP_KERNEL); 520 + if (!job->timestamp_query.queries) 521 + return -ENOMEM; 522 + 523 + syncs = u64_to_user_ptr(reset.syncs); 524 + 525 + for (int i = 0; i < reset.count; i++) { 526 + u32 sync; 527 + 528 + job->timestamp_query.queries[i].offset = reset.offset + 8 * i; 529 + 530 + if (copy_from_user(&sync, syncs++, sizeof(sync))) { 531 + kvfree(job->timestamp_query.queries); 532 + return -EFAULT; 533 + } 534 + 535 + job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); 536 + } 537 + job->timestamp_query.count = reset.count; 538 + 539 + return 0; 540 + } 541 + 542 + /* Get data for the copy timestamp query results job submission. */ 543 + static int 544 + v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv, 545 + struct drm_v3d_extension __user *ext, 546 + struct v3d_cpu_job *job) 547 + { 548 + u32 __user *offsets, *syncs; 549 + struct drm_v3d_copy_timestamp_query copy; 550 + int i; 551 + 552 + if (!job) { 553 + DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); 554 + return -EINVAL; 555 + } 556 + 557 + if (job->job_type) { 558 + DRM_DEBUG("Two CPU job extensions were added to the same CPU job.\n"); 559 + return -EINVAL; 560 + } 561 + 562 + if (copy_from_user(&copy, ext, sizeof(copy))) 563 + return -EFAULT; 564 + 565 + if (copy.pad) 566 + return -EINVAL; 567 + 568 + job->job_type = V3D_CPU_JOB_TYPE_COPY_TIMESTAMP_QUERY; 569 + 570 + job->timestamp_query.queries = kvmalloc_array(copy.count, 571 + sizeof(struct v3d_timestamp_query), 572 + GFP_KERNEL); 573 + if (!job->timestamp_query.queries) 574 + return -ENOMEM; 575 + 576 + offsets = u64_to_user_ptr(copy.offsets); 577 + syncs = u64_to_user_ptr(copy.syncs); 578 + 579 + for (i = 0; i < copy.count; i++) { 580 + u32 offset, sync; 581 + 582 + if (copy_from_user(&offset, offsets++, sizeof(offset))) { 583 + kvfree(job->timestamp_query.queries); 584 + return -EFAULT; 585 + } 586 + 587 + job->timestamp_query.queries[i].offset = offset; 588 + 589 + if (copy_from_user(&sync, syncs++, sizeof(sync))) { 590 + kvfree(job->timestamp_query.queries); 591 + return -EFAULT; 592 + } 593 + 594 + job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); 595 + } 596 + job->timestamp_query.count = copy.count; 597 + 598 + job->copy.do_64bit = copy.do_64bit; 599 + job->copy.do_partial = copy.do_partial; 600 + job->copy.availability_bit = copy.availability_bit; 601 + job->copy.offset = copy.offset; 602 + job->copy.stride = copy.stride; 603 + 604 + return 0; 605 + } 606 + 607 + static int 608 + v3d_get_cpu_reset_performance_params(struct drm_file *file_priv, 609 + struct drm_v3d_extension __user *ext, 610 + struct v3d_cpu_job *job) 611 + { 612 + u32 __user *syncs; 613 + u64 __user *kperfmon_ids; 614 + struct drm_v3d_reset_performance_query reset; 615 + 616 + if (!job) { 617 + DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); 618 + return -EINVAL; 619 + } 620 + 621 + if (job->job_type) { 622 + DRM_DEBUG("Two CPU job extensions were added to the same CPU job.\n"); 623 + return -EINVAL; 624 + } 625 + 626 + if (copy_from_user(&reset, ext, sizeof(reset))) 627 + return -EFAULT; 628 + 629 + job->job_type = V3D_CPU_JOB_TYPE_RESET_PERFORMANCE_QUERY; 630 + 631 + job->performance_query.queries = kvmalloc_array(reset.count, 632 + sizeof(struct v3d_performance_query), 633 + GFP_KERNEL); 634 + if (!job->performance_query.queries) 635 + return -ENOMEM; 636 + 637 + syncs = u64_to_user_ptr(reset.syncs); 638 + kperfmon_ids = u64_to_user_ptr(reset.kperfmon_ids); 639 + 640 + for (int i = 0; i < reset.count; i++) { 641 + u32 sync; 642 + u64 ids; 643 + u32 __user *ids_pointer; 644 + u32 id; 645 + 646 + if (copy_from_user(&sync, syncs++, sizeof(sync))) { 647 + kvfree(job->performance_query.queries); 648 + return -EFAULT; 649 + } 650 + 651 + job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); 652 + 653 + if (copy_from_user(&ids, kperfmon_ids++, sizeof(ids))) { 654 + kvfree(job->performance_query.queries); 655 + return -EFAULT; 656 + } 657 + 658 + ids_pointer = u64_to_user_ptr(ids); 659 + 660 + for (int j = 0; j < reset.nperfmons; j++) { 661 + if (copy_from_user(&id, ids_pointer++, sizeof(id))) { 662 + kvfree(job->performance_query.queries); 663 + return -EFAULT; 664 + } 665 + 666 + job->performance_query.queries[i].kperfmon_ids[j] = id; 667 + } 668 + } 669 + job->performance_query.count = reset.count; 670 + job->performance_query.nperfmons = reset.nperfmons; 671 + 672 + return 0; 673 + } 674 + 675 + static int 676 + v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv, 677 + struct drm_v3d_extension __user *ext, 678 + struct v3d_cpu_job *job) 679 + { 680 + u32 __user *syncs; 681 + u64 __user *kperfmon_ids; 682 + struct drm_v3d_copy_performance_query copy; 683 + 684 + if (!job) { 685 + DRM_DEBUG("CPU job extension was attached to a GPU job.\n"); 686 + return -EINVAL; 687 + } 688 + 689 + if (job->job_type) { 690 + DRM_DEBUG("Two CPU job extensions were added to the same CPU job.\n"); 691 + return -EINVAL; 692 + } 693 + 694 + if (copy_from_user(&copy, ext, sizeof(copy))) 695 + return -EFAULT; 696 + 697 + if (copy.pad) 698 + return -EINVAL; 699 + 700 + job->job_type = V3D_CPU_JOB_TYPE_COPY_PERFORMANCE_QUERY; 701 + 702 + job->performance_query.queries = kvmalloc_array(copy.count, 703 + sizeof(struct v3d_performance_query), 704 + GFP_KERNEL); 705 + if (!job->performance_query.queries) 706 + return -ENOMEM; 707 + 708 + syncs = u64_to_user_ptr(copy.syncs); 709 + kperfmon_ids = u64_to_user_ptr(copy.kperfmon_ids); 710 + 711 + for (int i = 0; i < copy.count; i++) { 712 + u32 sync; 713 + u64 ids; 714 + u32 __user *ids_pointer; 715 + u32 id; 716 + 717 + if (copy_from_user(&sync, syncs++, sizeof(sync))) { 718 + kvfree(job->performance_query.queries); 719 + return -EFAULT; 720 + } 721 + 722 + job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync); 723 + 724 + if (copy_from_user(&ids, kperfmon_ids++, sizeof(ids))) { 725 + kvfree(job->performance_query.queries); 726 + return -EFAULT; 727 + } 728 + 729 + ids_pointer = u64_to_user_ptr(ids); 730 + 731 + for (int j = 0; j < copy.nperfmons; j++) { 732 + if (copy_from_user(&id, ids_pointer++, sizeof(id))) { 733 + kvfree(job->performance_query.queries); 734 + return -EFAULT; 735 + } 736 + 737 + job->performance_query.queries[i].kperfmon_ids[j] = id; 738 + } 739 + } 740 + job->performance_query.count = copy.count; 741 + job->performance_query.nperfmons = copy.nperfmons; 742 + job->performance_query.ncounters = copy.ncounters; 743 + 744 + job->copy.do_64bit = copy.do_64bit; 745 + job->copy.do_partial = copy.do_partial; 746 + job->copy.availability_bit = copy.availability_bit; 747 + job->copy.offset = copy.offset; 748 + job->copy.stride = copy.stride; 749 + 750 + return 0; 751 + } 752 + 753 + /* Whenever userspace sets ioctl extensions, v3d_get_extensions parses data 754 + * according to the extension id (name). 755 + */ 756 + static int 757 + v3d_get_extensions(struct drm_file *file_priv, 758 + u64 ext_handles, 759 + struct v3d_submit_ext *se, 760 + struct v3d_cpu_job *job) 761 + { 762 + struct drm_v3d_extension __user *user_ext; 763 + int ret; 764 + 765 + user_ext = u64_to_user_ptr(ext_handles); 766 + while (user_ext) { 767 + struct drm_v3d_extension ext; 768 + 769 + if (copy_from_user(&ext, user_ext, sizeof(ext))) { 770 + DRM_DEBUG("Failed to copy submit extension\n"); 771 + return -EFAULT; 772 + } 773 + 774 + switch (ext.id) { 775 + case DRM_V3D_EXT_ID_MULTI_SYNC: 776 + ret = v3d_get_multisync_submit_deps(file_priv, user_ext, se); 777 + break; 778 + case DRM_V3D_EXT_ID_CPU_INDIRECT_CSD: 779 + ret = v3d_get_cpu_indirect_csd_params(file_priv, user_ext, job); 780 + break; 781 + case DRM_V3D_EXT_ID_CPU_TIMESTAMP_QUERY: 782 + ret = v3d_get_cpu_timestamp_query_params(file_priv, user_ext, job); 783 + break; 784 + case DRM_V3D_EXT_ID_CPU_RESET_TIMESTAMP_QUERY: 785 + ret = v3d_get_cpu_reset_timestamp_params(file_priv, user_ext, job); 786 + break; 787 + case DRM_V3D_EXT_ID_CPU_COPY_TIMESTAMP_QUERY: 788 + ret = v3d_get_cpu_copy_query_results_params(file_priv, user_ext, job); 789 + break; 790 + case DRM_V3D_EXT_ID_CPU_RESET_PERFORMANCE_QUERY: 791 + ret = v3d_get_cpu_reset_performance_params(file_priv, user_ext, job); 792 + break; 793 + case DRM_V3D_EXT_ID_CPU_COPY_PERFORMANCE_QUERY: 794 + ret = v3d_get_cpu_copy_performance_query_params(file_priv, user_ext, job); 795 + break; 796 + default: 797 + DRM_DEBUG_DRIVER("Unknown extension id: %d\n", ext.id); 798 + return -EINVAL; 799 + } 800 + 801 + if (ret) 802 + return ret; 803 + 804 + user_ext = u64_to_user_ptr(ext.next); 805 + } 806 + 807 + return 0; 808 + } 809 + 810 + /** 811 + * v3d_submit_cl_ioctl() - Submits a job (frame) to the V3D. 812 + * @dev: DRM device 813 + * @data: ioctl argument 814 + * @file_priv: DRM file for this fd 815 + * 816 + * This is the main entrypoint for userspace to submit a 3D frame to 817 + * the GPU. Userspace provides the binner command list (if 818 + * applicable), and the kernel sets up the render command list to draw 819 + * to the framebuffer described in the ioctl, using the command lists 820 + * that the 3D engine's binner will produce. 821 + */ 822 + int 823 + v3d_submit_cl_ioctl(struct drm_device *dev, void *data, 824 + struct drm_file *file_priv) 825 + { 826 + struct v3d_dev *v3d = to_v3d_dev(dev); 827 + struct v3d_file_priv *v3d_priv = file_priv->driver_priv; 828 + struct drm_v3d_submit_cl *args = data; 829 + struct v3d_submit_ext se = {0}; 830 + struct v3d_bin_job *bin = NULL; 831 + struct v3d_render_job *render = NULL; 832 + struct v3d_job *clean_job = NULL; 833 + struct v3d_job *last_job; 834 + struct ww_acquire_ctx acquire_ctx; 835 + int ret = 0; 836 + 837 + trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end); 838 + 839 + if (args->pad) 840 + return -EINVAL; 841 + 842 + if (args->flags && 843 + args->flags & ~(DRM_V3D_SUBMIT_CL_FLUSH_CACHE | 844 + DRM_V3D_SUBMIT_EXTENSION)) { 845 + DRM_INFO("invalid flags: %d\n", args->flags); 846 + return -EINVAL; 847 + } 848 + 849 + if (args->flags & DRM_V3D_SUBMIT_EXTENSION) { 850 + ret = v3d_get_extensions(file_priv, args->extensions, &se, NULL); 851 + if (ret) { 852 + DRM_DEBUG("Failed to get extensions.\n"); 853 + return ret; 854 + } 855 + } 856 + 857 + ret = v3d_job_allocate((void *)&render, sizeof(*render)); 858 + if (ret) 859 + return ret; 860 + 861 + ret = v3d_job_init(v3d, file_priv, &render->base, 862 + v3d_render_job_free, args->in_sync_rcl, &se, V3D_RENDER); 863 + if (ret) 864 + goto fail; 865 + 866 + render->start = args->rcl_start; 867 + render->end = args->rcl_end; 868 + INIT_LIST_HEAD(&render->unref_list); 869 + 870 + if (args->bcl_start != args->bcl_end) { 871 + ret = v3d_job_allocate((void *)&bin, sizeof(*bin)); 872 + if (ret) 873 + goto fail; 874 + 875 + ret = v3d_job_init(v3d, file_priv, &bin->base, 876 + v3d_job_free, args->in_sync_bcl, &se, V3D_BIN); 877 + if (ret) 878 + goto fail; 879 + 880 + bin->start = args->bcl_start; 881 + bin->end = args->bcl_end; 882 + bin->qma = args->qma; 883 + bin->qms = args->qms; 884 + bin->qts = args->qts; 885 + bin->render = render; 886 + } 887 + 888 + if (args->flags & DRM_V3D_SUBMIT_CL_FLUSH_CACHE) { 889 + ret = v3d_job_allocate((void *)&clean_job, sizeof(*clean_job)); 890 + if (ret) 891 + goto fail; 892 + 893 + ret = v3d_job_init(v3d, file_priv, clean_job, 894 + v3d_job_free, 0, NULL, V3D_CACHE_CLEAN); 895 + if (ret) 896 + goto fail; 897 + 898 + last_job = clean_job; 899 + } else { 900 + last_job = &render->base; 901 + } 902 + 903 + ret = v3d_lookup_bos(dev, file_priv, last_job, 904 + args->bo_handles, args->bo_handle_count); 905 + if (ret) 906 + goto fail; 907 + 908 + ret = v3d_lock_bo_reservations(last_job, &acquire_ctx); 909 + if (ret) 910 + goto fail; 911 + 912 + if (args->perfmon_id) { 913 + render->base.perfmon = v3d_perfmon_find(v3d_priv, 914 + args->perfmon_id); 915 + 916 + if (!render->base.perfmon) { 917 + ret = -ENOENT; 918 + goto fail_perfmon; 919 + } 920 + } 921 + 922 + mutex_lock(&v3d->sched_lock); 923 + if (bin) { 924 + bin->base.perfmon = render->base.perfmon; 925 + v3d_perfmon_get(bin->base.perfmon); 926 + v3d_push_job(&bin->base); 927 + 928 + ret = drm_sched_job_add_dependency(&render->base.base, 929 + dma_fence_get(bin->base.done_fence)); 930 + if (ret) 931 + goto fail_unreserve; 932 + } 933 + 934 + v3d_push_job(&render->base); 935 + 936 + if (clean_job) { 937 + struct dma_fence *render_fence = 938 + dma_fence_get(render->base.done_fence); 939 + ret = drm_sched_job_add_dependency(&clean_job->base, 940 + render_fence); 941 + if (ret) 942 + goto fail_unreserve; 943 + clean_job->perfmon = render->base.perfmon; 944 + v3d_perfmon_get(clean_job->perfmon); 945 + v3d_push_job(clean_job); 946 + } 947 + 948 + mutex_unlock(&v3d->sched_lock); 949 + 950 + v3d_attach_fences_and_unlock_reservation(file_priv, 951 + last_job, 952 + &acquire_ctx, 953 + args->out_sync, 954 + &se, 955 + last_job->done_fence); 956 + 957 + v3d_job_put(&bin->base); 958 + v3d_job_put(&render->base); 959 + v3d_job_put(clean_job); 960 + 961 + return 0; 962 + 963 + fail_unreserve: 964 + mutex_unlock(&v3d->sched_lock); 965 + fail_perfmon: 966 + drm_gem_unlock_reservations(last_job->bo, 967 + last_job->bo_count, &acquire_ctx); 968 + fail: 969 + v3d_job_cleanup((void *)bin); 970 + v3d_job_cleanup((void *)render); 971 + v3d_job_cleanup(clean_job); 972 + v3d_put_multisync_post_deps(&se); 973 + 974 + return ret; 975 + } 976 + 977 + /** 978 + * v3d_submit_tfu_ioctl() - Submits a TFU (texture formatting) job to the V3D. 979 + * @dev: DRM device 980 + * @data: ioctl argument 981 + * @file_priv: DRM file for this fd 982 + * 983 + * Userspace provides the register setup for the TFU, which we don't 984 + * need to validate since the TFU is behind the MMU. 985 + */ 986 + int 987 + v3d_submit_tfu_ioctl(struct drm_device *dev, void *data, 988 + struct drm_file *file_priv) 989 + { 990 + struct v3d_dev *v3d = to_v3d_dev(dev); 991 + struct drm_v3d_submit_tfu *args = data; 992 + struct v3d_submit_ext se = {0}; 993 + struct v3d_tfu_job *job = NULL; 994 + struct ww_acquire_ctx acquire_ctx; 995 + int ret = 0; 996 + 997 + trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia); 998 + 999 + if (args->flags && !(args->flags & DRM_V3D_SUBMIT_EXTENSION)) { 1000 + DRM_DEBUG("invalid flags: %d\n", args->flags); 1001 + return -EINVAL; 1002 + } 1003 + 1004 + if (args->flags & DRM_V3D_SUBMIT_EXTENSION) { 1005 + ret = v3d_get_extensions(file_priv, args->extensions, &se, NULL); 1006 + if (ret) { 1007 + DRM_DEBUG("Failed to get extensions.\n"); 1008 + return ret; 1009 + } 1010 + } 1011 + 1012 + ret = v3d_job_allocate((void *)&job, sizeof(*job)); 1013 + if (ret) 1014 + return ret; 1015 + 1016 + ret = v3d_job_init(v3d, file_priv, &job->base, 1017 + v3d_job_free, args->in_sync, &se, V3D_TFU); 1018 + if (ret) 1019 + goto fail; 1020 + 1021 + job->base.bo = kcalloc(ARRAY_SIZE(args->bo_handles), 1022 + sizeof(*job->base.bo), GFP_KERNEL); 1023 + if (!job->base.bo) { 1024 + ret = -ENOMEM; 1025 + goto fail; 1026 + } 1027 + 1028 + job->args = *args; 1029 + 1030 + for (job->base.bo_count = 0; 1031 + job->base.bo_count < ARRAY_SIZE(args->bo_handles); 1032 + job->base.bo_count++) { 1033 + struct drm_gem_object *bo; 1034 + 1035 + if (!args->bo_handles[job->base.bo_count]) 1036 + break; 1037 + 1038 + bo = drm_gem_object_lookup(file_priv, args->bo_handles[job->base.bo_count]); 1039 + if (!bo) { 1040 + DRM_DEBUG("Failed to look up GEM BO %d: %d\n", 1041 + job->base.bo_count, 1042 + args->bo_handles[job->base.bo_count]); 1043 + ret = -ENOENT; 1044 + goto fail; 1045 + } 1046 + job->base.bo[job->base.bo_count] = bo; 1047 + } 1048 + 1049 + ret = v3d_lock_bo_reservations(&job->base, &acquire_ctx); 1050 + if (ret) 1051 + goto fail; 1052 + 1053 + mutex_lock(&v3d->sched_lock); 1054 + v3d_push_job(&job->base); 1055 + mutex_unlock(&v3d->sched_lock); 1056 + 1057 + v3d_attach_fences_and_unlock_reservation(file_priv, 1058 + &job->base, &acquire_ctx, 1059 + args->out_sync, 1060 + &se, 1061 + job->base.done_fence); 1062 + 1063 + v3d_job_put(&job->base); 1064 + 1065 + return 0; 1066 + 1067 + fail: 1068 + v3d_job_cleanup((void *)job); 1069 + v3d_put_multisync_post_deps(&se); 1070 + 1071 + return ret; 1072 + } 1073 + 1074 + /** 1075 + * v3d_submit_csd_ioctl() - Submits a CSD (compute shader) job to the V3D. 1076 + * @dev: DRM device 1077 + * @data: ioctl argument 1078 + * @file_priv: DRM file for this fd 1079 + * 1080 + * Userspace provides the register setup for the CSD, which we don't 1081 + * need to validate since the CSD is behind the MMU. 1082 + */ 1083 + int 1084 + v3d_submit_csd_ioctl(struct drm_device *dev, void *data, 1085 + struct drm_file *file_priv) 1086 + { 1087 + struct v3d_dev *v3d = to_v3d_dev(dev); 1088 + struct v3d_file_priv *v3d_priv = file_priv->driver_priv; 1089 + struct drm_v3d_submit_csd *args = data; 1090 + struct v3d_submit_ext se = {0}; 1091 + struct v3d_csd_job *job = NULL; 1092 + struct v3d_job *clean_job = NULL; 1093 + struct ww_acquire_ctx acquire_ctx; 1094 + int ret; 1095 + 1096 + trace_v3d_submit_csd_ioctl(&v3d->drm, args->cfg[5], args->cfg[6]); 1097 + 1098 + if (args->pad) 1099 + return -EINVAL; 1100 + 1101 + if (!v3d_has_csd(v3d)) { 1102 + DRM_DEBUG("Attempting CSD submit on non-CSD hardware\n"); 1103 + return -EINVAL; 1104 + } 1105 + 1106 + if (args->flags && !(args->flags & DRM_V3D_SUBMIT_EXTENSION)) { 1107 + DRM_INFO("invalid flags: %d\n", args->flags); 1108 + return -EINVAL; 1109 + } 1110 + 1111 + if (args->flags & DRM_V3D_SUBMIT_EXTENSION) { 1112 + ret = v3d_get_extensions(file_priv, args->extensions, &se, NULL); 1113 + if (ret) { 1114 + DRM_DEBUG("Failed to get extensions.\n"); 1115 + return ret; 1116 + } 1117 + } 1118 + 1119 + ret = v3d_setup_csd_jobs_and_bos(file_priv, v3d, args, 1120 + &job, &clean_job, &se, 1121 + &acquire_ctx); 1122 + if (ret) 1123 + goto fail; 1124 + 1125 + if (args->perfmon_id) { 1126 + job->base.perfmon = v3d_perfmon_find(v3d_priv, 1127 + args->perfmon_id); 1128 + if (!job->base.perfmon) { 1129 + ret = -ENOENT; 1130 + goto fail_perfmon; 1131 + } 1132 + } 1133 + 1134 + mutex_lock(&v3d->sched_lock); 1135 + v3d_push_job(&job->base); 1136 + 1137 + ret = drm_sched_job_add_dependency(&clean_job->base, 1138 + dma_fence_get(job->base.done_fence)); 1139 + if (ret) 1140 + goto fail_unreserve; 1141 + 1142 + v3d_push_job(clean_job); 1143 + mutex_unlock(&v3d->sched_lock); 1144 + 1145 + v3d_attach_fences_and_unlock_reservation(file_priv, 1146 + clean_job, 1147 + &acquire_ctx, 1148 + args->out_sync, 1149 + &se, 1150 + clean_job->done_fence); 1151 + 1152 + v3d_job_put(&job->base); 1153 + v3d_job_put(clean_job); 1154 + 1155 + return 0; 1156 + 1157 + fail_unreserve: 1158 + mutex_unlock(&v3d->sched_lock); 1159 + fail_perfmon: 1160 + drm_gem_unlock_reservations(clean_job->bo, clean_job->bo_count, 1161 + &acquire_ctx); 1162 + fail: 1163 + v3d_job_cleanup((void *)job); 1164 + v3d_job_cleanup(clean_job); 1165 + v3d_put_multisync_post_deps(&se); 1166 + 1167 + return ret; 1168 + } 1169 + 1170 + static const unsigned int cpu_job_bo_handle_count[] = { 1171 + [V3D_CPU_JOB_TYPE_INDIRECT_CSD] = 1, 1172 + [V3D_CPU_JOB_TYPE_TIMESTAMP_QUERY] = 1, 1173 + [V3D_CPU_JOB_TYPE_RESET_TIMESTAMP_QUERY] = 1, 1174 + [V3D_CPU_JOB_TYPE_COPY_TIMESTAMP_QUERY] = 2, 1175 + [V3D_CPU_JOB_TYPE_RESET_PERFORMANCE_QUERY] = 0, 1176 + [V3D_CPU_JOB_TYPE_COPY_PERFORMANCE_QUERY] = 1, 1177 + }; 1178 + 1179 + /** 1180 + * v3d_submit_cpu_ioctl() - Submits a CPU job to the V3D. 1181 + * @dev: DRM device 1182 + * @data: ioctl argument 1183 + * @file_priv: DRM file for this fd 1184 + * 1185 + * Userspace specifies the CPU job type and data required to perform its 1186 + * operations through the drm_v3d_extension struct. 1187 + */ 1188 + int 1189 + v3d_submit_cpu_ioctl(struct drm_device *dev, void *data, 1190 + struct drm_file *file_priv) 1191 + { 1192 + struct v3d_dev *v3d = to_v3d_dev(dev); 1193 + struct drm_v3d_submit_cpu *args = data; 1194 + struct v3d_submit_ext se = {0}; 1195 + struct v3d_submit_ext *out_se = NULL; 1196 + struct v3d_cpu_job *cpu_job = NULL; 1197 + struct v3d_csd_job *csd_job = NULL; 1198 + struct v3d_job *clean_job = NULL; 1199 + struct ww_acquire_ctx acquire_ctx; 1200 + int ret; 1201 + 1202 + if (args->flags && !(args->flags & DRM_V3D_SUBMIT_EXTENSION)) { 1203 + DRM_INFO("Invalid flags: %d\n", args->flags); 1204 + return -EINVAL; 1205 + } 1206 + 1207 + ret = v3d_job_allocate((void *)&cpu_job, sizeof(*cpu_job)); 1208 + if (ret) 1209 + return ret; 1210 + 1211 + if (args->flags & DRM_V3D_SUBMIT_EXTENSION) { 1212 + ret = v3d_get_extensions(file_priv, args->extensions, &se, cpu_job); 1213 + if (ret) { 1214 + DRM_DEBUG("Failed to get extensions.\n"); 1215 + goto fail; 1216 + } 1217 + } 1218 + 1219 + /* Every CPU job must have a CPU job user extension */ 1220 + if (!cpu_job->job_type) { 1221 + DRM_DEBUG("CPU job must have a CPU job user extension.\n"); 1222 + ret = -EINVAL; 1223 + goto fail; 1224 + } 1225 + 1226 + if (args->bo_handle_count != cpu_job_bo_handle_count[cpu_job->job_type]) { 1227 + DRM_DEBUG("This CPU job was not submitted with the proper number of BOs.\n"); 1228 + ret = -EINVAL; 1229 + goto fail; 1230 + } 1231 + 1232 + trace_v3d_submit_cpu_ioctl(&v3d->drm, cpu_job->job_type); 1233 + 1234 + ret = v3d_job_init(v3d, file_priv, &cpu_job->base, 1235 + v3d_job_free, 0, &se, V3D_CPU); 1236 + if (ret) 1237 + goto fail; 1238 + 1239 + clean_job = cpu_job->indirect_csd.clean_job; 1240 + csd_job = cpu_job->indirect_csd.job; 1241 + 1242 + if (args->bo_handle_count) { 1243 + ret = v3d_lookup_bos(dev, file_priv, &cpu_job->base, 1244 + args->bo_handles, args->bo_handle_count); 1245 + if (ret) 1246 + goto fail; 1247 + 1248 + ret = v3d_lock_bo_reservations(&cpu_job->base, &acquire_ctx); 1249 + if (ret) 1250 + goto fail; 1251 + } 1252 + 1253 + mutex_lock(&v3d->sched_lock); 1254 + v3d_push_job(&cpu_job->base); 1255 + 1256 + switch (cpu_job->job_type) { 1257 + case V3D_CPU_JOB_TYPE_INDIRECT_CSD: 1258 + ret = drm_sched_job_add_dependency(&csd_job->base.base, 1259 + dma_fence_get(cpu_job->base.done_fence)); 1260 + if (ret) 1261 + goto fail_unreserve; 1262 + 1263 + v3d_push_job(&csd_job->base); 1264 + 1265 + ret = drm_sched_job_add_dependency(&clean_job->base, 1266 + dma_fence_get(csd_job->base.done_fence)); 1267 + if (ret) 1268 + goto fail_unreserve; 1269 + 1270 + v3d_push_job(clean_job); 1271 + 1272 + break; 1273 + default: 1274 + break; 1275 + } 1276 + mutex_unlock(&v3d->sched_lock); 1277 + 1278 + out_se = (cpu_job->job_type == V3D_CPU_JOB_TYPE_INDIRECT_CSD) ? NULL : &se; 1279 + 1280 + v3d_attach_fences_and_unlock_reservation(file_priv, 1281 + &cpu_job->base, 1282 + &acquire_ctx, 0, 1283 + out_se, cpu_job->base.done_fence); 1284 + 1285 + switch (cpu_job->job_type) { 1286 + case V3D_CPU_JOB_TYPE_INDIRECT_CSD: 1287 + v3d_attach_fences_and_unlock_reservation(file_priv, 1288 + clean_job, 1289 + &cpu_job->indirect_csd.acquire_ctx, 1290 + 0, &se, clean_job->done_fence); 1291 + break; 1292 + default: 1293 + break; 1294 + } 1295 + 1296 + v3d_job_put(&cpu_job->base); 1297 + v3d_job_put(&csd_job->base); 1298 + v3d_job_put(clean_job); 1299 + 1300 + return 0; 1301 + 1302 + fail_unreserve: 1303 + mutex_unlock(&v3d->sched_lock); 1304 + 1305 + drm_gem_unlock_reservations(cpu_job->base.bo, cpu_job->base.bo_count, 1306 + &acquire_ctx); 1307 + 1308 + drm_gem_unlock_reservations(clean_job->bo, clean_job->bo_count, 1309 + &cpu_job->indirect_csd.acquire_ctx); 1310 + 1311 + fail: 1312 + v3d_job_cleanup((void *)cpu_job); 1313 + v3d_job_cleanup((void *)csd_job); 1314 + v3d_job_cleanup(clean_job); 1315 + v3d_put_multisync_post_deps(&se); 1316 + kvfree(cpu_job->timestamp_query.queries); 1317 + kvfree(cpu_job->performance_query.queries); 1318 + 1319 + return ret; 1320 + }
+57
drivers/gpu/drm/v3d/v3d_trace.h
··· 225 225 __entry->seqno) 226 226 ); 227 227 228 + TRACE_EVENT(v3d_submit_cpu_ioctl, 229 + TP_PROTO(struct drm_device *dev, enum v3d_cpu_job_type job_type), 230 + TP_ARGS(dev, job_type), 231 + 232 + TP_STRUCT__entry( 233 + __field(u32, dev) 234 + __field(enum v3d_cpu_job_type, job_type) 235 + ), 236 + 237 + TP_fast_assign( 238 + __entry->dev = dev->primary->index; 239 + __entry->job_type = job_type; 240 + ), 241 + 242 + TP_printk("dev=%u, job_type=%d", 243 + __entry->dev, 244 + __entry->job_type) 245 + ); 246 + 247 + TRACE_EVENT(v3d_cpu_job_begin, 248 + TP_PROTO(struct drm_device *dev, enum v3d_cpu_job_type job_type), 249 + TP_ARGS(dev, job_type), 250 + 251 + TP_STRUCT__entry( 252 + __field(u32, dev) 253 + __field(enum v3d_cpu_job_type, job_type) 254 + ), 255 + 256 + TP_fast_assign( 257 + __entry->dev = dev->primary->index; 258 + __entry->job_type = job_type; 259 + ), 260 + 261 + TP_printk("dev=%u, job_type=%d", 262 + __entry->dev, 263 + __entry->job_type) 264 + ); 265 + 266 + TRACE_EVENT(v3d_cpu_job_end, 267 + TP_PROTO(struct drm_device *dev, enum v3d_cpu_job_type job_type), 268 + TP_ARGS(dev, job_type), 269 + 270 + TP_STRUCT__entry( 271 + __field(u32, dev) 272 + __field(enum v3d_cpu_job_type, job_type) 273 + ), 274 + 275 + TP_fast_assign( 276 + __entry->dev = dev->primary->index; 277 + __entry->job_type = job_type; 278 + ), 279 + 280 + TP_printk("dev=%u, job_type=%d", 281 + __entry->dev, 282 + __entry->job_type) 283 + ); 284 + 228 285 TRACE_EVENT(v3d_cache_clean_begin, 229 286 TP_PROTO(struct drm_device *dev), 230 287 TP_ARGS(dev),
+1 -1
drivers/gpu/drm/vboxvideo/vbox_drv.c
··· 182 182 183 183 static const struct drm_driver driver = { 184 184 .driver_features = 185 - DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, 185 + DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC | DRIVER_CURSOR_HOTSPOT, 186 186 187 187 .fops = &vbox_fops, 188 188 .name = DRIVER_NAME,
+2 -2
drivers/gpu/drm/vboxvideo/vbox_mode.c
··· 429 429 flags = VBOX_MOUSE_POINTER_VISIBLE | VBOX_MOUSE_POINTER_SHAPE | 430 430 VBOX_MOUSE_POINTER_ALPHA; 431 431 hgsmi_update_pointer_shape(vbox->guest_pool, flags, 432 - min_t(u32, max(fb->hot_x, 0), width), 433 - min_t(u32, max(fb->hot_y, 0), height), 432 + min_t(u32, max(new_state->hotspot_x, 0), width), 433 + min_t(u32, max(new_state->hotspot_y, 0), height), 434 434 width, height, vbox->cursor_data, data_size); 435 435 436 436 mutex_unlock(&vbox->hw_mutex);
+1 -1
drivers/gpu/drm/virtio/virtgpu_drv.c
··· 177 177 * out via drm_device::driver_features: 178 178 */ 179 179 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC | 180 - DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE, 180 + DRIVER_SYNCOBJ | DRIVER_SYNCOBJ_TIMELINE | DRIVER_CURSOR_HOTSPOT, 181 181 .open = virtio_gpu_driver_open, 182 182 .postclose = virtio_gpu_driver_postclose, 183 183
+14 -4
drivers/gpu/drm/virtio/virtgpu_plane.c
··· 79 79 { 80 80 struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, 81 81 plane); 82 + struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, 83 + plane); 82 84 bool is_cursor = plane->type == DRM_PLANE_TYPE_CURSOR; 83 85 struct drm_crtc_state *crtc_state; 84 86 int ret; 85 87 86 88 if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc)) 87 89 return 0; 90 + 91 + /* 92 + * Ignore damage clips if the framebuffer attached to the plane's state 93 + * has changed since the last plane update (page-flip). In this case, a 94 + * full plane update should happen because uploads are done per-buffer. 95 + */ 96 + if (old_plane_state->fb != new_plane_state->fb) 97 + new_plane_state->ignore_damage_clips = true; 88 98 89 99 crtc_state = drm_atomic_get_crtc_state(state, 90 100 new_plane_state->crtc); ··· 333 323 DRM_DEBUG("update, handle %d, pos +%d+%d, hot %d,%d\n", handle, 334 324 plane->state->crtc_x, 335 325 plane->state->crtc_y, 336 - plane->state->fb ? plane->state->fb->hot_x : 0, 337 - plane->state->fb ? plane->state->fb->hot_y : 0); 326 + plane->state->hotspot_x, 327 + plane->state->hotspot_y); 338 328 output->cursor.hdr.type = 339 329 cpu_to_le32(VIRTIO_GPU_CMD_UPDATE_CURSOR); 340 330 output->cursor.resource_id = cpu_to_le32(handle); 341 331 if (plane->state->fb) { 342 332 output->cursor.hot_x = 343 - cpu_to_le32(plane->state->fb->hot_x); 333 + cpu_to_le32(plane->state->hotspot_x); 344 334 output->cursor.hot_y = 345 - cpu_to_le32(plane->state->fb->hot_y); 335 + cpu_to_le32(plane->state->hotspot_y); 346 336 } else { 347 337 output->cursor.hot_x = cpu_to_le32(0); 348 338 output->cursor.hot_y = cpu_to_le32(0);
+1 -1
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
··· 1611 1611 1612 1612 static const struct drm_driver driver = { 1613 1613 .driver_features = 1614 - DRIVER_MODESET | DRIVER_RENDER | DRIVER_ATOMIC | DRIVER_GEM, 1614 + DRIVER_MODESET | DRIVER_RENDER | DRIVER_ATOMIC | DRIVER_GEM | DRIVER_CURSOR_HOTSPOT, 1615 1615 .ioctls = vmw_ioctls, 1616 1616 .num_ioctls = ARRAY_SIZE(vmw_ioctls), 1617 1617 .master_set = vmw_master_set,
+13 -7
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
··· 768 768 struct vmw_plane_state *old_vps = vmw_plane_state_to_vps(old_state); 769 769 s32 hotspot_x, hotspot_y; 770 770 771 - hotspot_x = du->hotspot_x; 772 - hotspot_y = du->hotspot_y; 773 - 774 - if (new_state->fb) { 775 - hotspot_x += new_state->fb->hot_x; 776 - hotspot_y += new_state->fb->hot_y; 777 - } 771 + hotspot_x = du->hotspot_x + new_state->hotspot_x; 772 + hotspot_y = du->hotspot_y + new_state->hotspot_y; 778 773 779 774 du->cursor_surface = vps->surf; 780 775 du->cursor_bo = vps->bo; ··· 832 837 { 833 838 struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, 834 839 plane); 840 + struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, 841 + plane); 835 842 struct drm_crtc_state *crtc_state = NULL; 836 843 struct drm_framebuffer *new_fb = new_state->fb; 844 + struct drm_framebuffer *old_fb = old_state->fb; 837 845 int ret; 846 + 847 + /* 848 + * Ignore damage clips if the framebuffer attached to the plane's state 849 + * has changed since the last plane update (page-flip). In this case, a 850 + * full plane update should happen because uploads are done per-buffer. 851 + */ 852 + if (old_fb != new_fb) 853 + new_state->ignore_damage_clips = true; 838 854 839 855 if (new_state->crtc) 840 856 crtc_state = drm_atomic_get_new_crtc_state(state,
-1
drivers/gpu/drm/xlnx/zynqmp_kms.c
··· 27 27 #include <drm/drm_managed.h> 28 28 #include <drm/drm_mode_config.h> 29 29 #include <drm/drm_plane.h> 30 - #include <drm/drm_plane_helper.h> 31 30 #include <drm/drm_probe_helper.h> 32 31 #include <drm/drm_simple_kms_helper.h> 33 32 #include <drm/drm_vblank.h>
+1
drivers/hid/hid-picolcd_fb.c
··· 505 505 dev_err(dev, "can't get a free page for framebuffer\n"); 506 506 goto err_nomem; 507 507 } 508 + info->flags |= FBINFO_VIRTFB; 508 509 info->screen_buffer = fbdata->bitmap; 509 510 info->fix.smem_start = (unsigned long)fbdata->bitmap; 510 511 memset(fbdata->vbitmap, 0xff, PICOLCDFB_SIZE);
+1 -3
drivers/media/pci/ivtv/Kconfig
··· 48 48 config VIDEO_FB_IVTV 49 49 tristate "Conexant cx23415 framebuffer support" 50 50 depends on VIDEO_IVTV && FB 51 - select FB_CFB_FILLRECT 52 - select FB_CFB_COPYAREA 53 - select FB_CFB_IMAGEBLIT 51 + select FB_IOMEM_HELPERS 54 52 help 55 53 This is a framebuffer driver for the Conexant cx23415 MPEG 56 54 encoder/decoder.
+3 -3
drivers/media/pci/ivtv/ivtvfb.c
··· 927 927 928 928 static const struct fb_ops ivtvfb_ops = { 929 929 .owner = THIS_MODULE, 930 + .fb_read = fb_io_read, 930 931 .fb_write = ivtvfb_write, 931 932 .fb_check_var = ivtvfb_check_var, 932 933 .fb_set_par = ivtvfb_set_par, 933 934 .fb_setcolreg = ivtvfb_setcolreg, 934 - .fb_fillrect = cfb_fillrect, 935 - .fb_copyarea = cfb_copyarea, 936 - .fb_imageblit = cfb_imageblit, 935 + __FB_DEFAULT_IOMEM_OPS_DRAW, 937 936 .fb_cursor = NULL, 938 937 .fb_ioctl = ivtvfb_ioctl, 939 938 .fb_pan_display = ivtvfb_pan_display, 940 939 .fb_blank = ivtvfb_blank, 940 + __FB_DEFAULT_IOMEM_OPS_MMAP, 941 941 }; 942 942 943 943 /* Restore hardware after firmware restart */
+1 -1
drivers/phy/qualcomm/Kconfig
··· 63 63 depends on DRM || DRM=n 64 64 select GENERIC_PHY 65 65 select MFD_SYSCON 66 - select DRM_PANEL_BRIDGE if DRM 66 + select DRM_AUX_BRIDGE if DRM_BRIDGE 67 67 help 68 68 Enable this to support the QMP Combo PHY transceiver that is used 69 69 with USB3 and DisplayPort controllers on Qualcomm chips.
+2 -42
drivers/phy/qualcomm/phy-qcom-qmp-combo.c
··· 21 21 #include <linux/usb/typec.h> 22 22 #include <linux/usb/typec_mux.h> 23 23 24 - #include <drm/drm_bridge.h> 24 + #include <drm/bridge/aux-bridge.h> 25 25 26 26 #include <dt-bindings/phy/phy-qcom-qmp.h> 27 27 ··· 1418 1418 struct clk_fixed_rate pipe_clk_fixed; 1419 1419 struct clk_hw dp_link_hw; 1420 1420 struct clk_hw dp_pixel_hw; 1421 - 1422 - struct drm_bridge bridge; 1423 1421 1424 1422 struct typec_switch_dev *sw; 1425 1423 enum typec_orientation orientation; ··· 3189 3191 } 3190 3192 #endif 3191 3193 3192 - #if IS_ENABLED(CONFIG_DRM) 3193 - static int qmp_combo_bridge_attach(struct drm_bridge *bridge, 3194 - enum drm_bridge_attach_flags flags) 3195 - { 3196 - struct qmp_combo *qmp = container_of(bridge, struct qmp_combo, bridge); 3197 - struct drm_bridge *next_bridge; 3198 - 3199 - if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) 3200 - return -EINVAL; 3201 - 3202 - next_bridge = devm_drm_of_get_bridge(qmp->dev, qmp->dev->of_node, 0, 0); 3203 - if (IS_ERR(next_bridge)) { 3204 - dev_err(qmp->dev, "failed to acquire drm_bridge: %pe\n", next_bridge); 3205 - return PTR_ERR(next_bridge); 3206 - } 3207 - 3208 - return drm_bridge_attach(bridge->encoder, next_bridge, bridge, 3209 - DRM_BRIDGE_ATTACH_NO_CONNECTOR); 3210 - } 3211 - 3212 - static const struct drm_bridge_funcs qmp_combo_bridge_funcs = { 3213 - .attach = qmp_combo_bridge_attach, 3214 - }; 3215 - 3216 - static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) 3217 - { 3218 - qmp->bridge.funcs = &qmp_combo_bridge_funcs; 3219 - qmp->bridge.of_node = qmp->dev->of_node; 3220 - 3221 - return devm_drm_bridge_add(qmp->dev, &qmp->bridge); 3222 - } 3223 - #else 3224 - static int qmp_combo_dp_register_bridge(struct qmp_combo *qmp) 3225 - { 3226 - return 0; 3227 - } 3228 - #endif 3229 - 3230 3194 static int qmp_combo_parse_dt_lecacy_dp(struct qmp_combo *qmp, struct device_node *np) 3231 3195 { 3232 3196 struct device *dev = qmp->dev; ··· 3400 3440 if (ret) 3401 3441 return ret; 3402 3442 3403 - ret = qmp_combo_dp_register_bridge(qmp); 3443 + ret = drm_aux_bridge_register(dev); 3404 3444 if (ret) 3405 3445 return ret; 3406 3446
+1
drivers/soc/qcom/Kconfig
··· 86 86 depends on OF 87 87 select AUXILIARY_BUS 88 88 select QCOM_PDR_HELPERS 89 + select DRM_AUX_HPD_BRIDGE 89 90 help 90 91 The Qualcomm PMIC GLINK driver provides access, over GLINK, to the 91 92 USB and battery firmware running on one of the coprocessors in
+52 -13
drivers/staging/sm750fb/sm750.c
··· 663 663 return ret; 664 664 } 665 665 666 - static struct fb_ops lynxfb_ops = { 666 + static const struct fb_ops lynxfb_ops = { 667 667 .owner = THIS_MODULE, 668 + FB_DEFAULT_IOMEM_OPS, 668 669 .fb_check_var = lynxfb_ops_check_var, 669 670 .fb_set_par = lynxfb_ops_set_par, 670 671 .fb_setcolreg = lynxfb_ops_setcolreg, 671 672 .fb_blank = lynxfb_ops_blank, 672 - .fb_fillrect = cfb_fillrect, 673 - .fb_imageblit = cfb_imageblit, 674 - .fb_copyarea = cfb_copyarea, 675 - /* cursor */ 673 + .fb_pan_display = lynxfb_ops_pan_display, 674 + }; 675 + 676 + static const struct fb_ops lynxfb_ops_with_cursor = { 677 + .owner = THIS_MODULE, 678 + FB_DEFAULT_IOMEM_OPS, 679 + .fb_check_var = lynxfb_ops_check_var, 680 + .fb_set_par = lynxfb_ops_set_par, 681 + .fb_setcolreg = lynxfb_ops_setcolreg, 682 + .fb_blank = lynxfb_ops_blank, 683 + .fb_pan_display = lynxfb_ops_pan_display, 676 684 .fb_cursor = lynxfb_ops_cursor, 685 + }; 686 + 687 + static const struct fb_ops lynxfb_ops_accel = { 688 + .owner = THIS_MODULE, 689 + __FB_DEFAULT_IOMEM_OPS_RDWR, 690 + .fb_check_var = lynxfb_ops_check_var, 691 + .fb_set_par = lynxfb_ops_set_par, 692 + .fb_setcolreg = lynxfb_ops_setcolreg, 693 + .fb_blank = lynxfb_ops_blank, 694 + .fb_pan_display = lynxfb_ops_pan_display, 695 + .fb_fillrect = lynxfb_ops_fillrect, 696 + .fb_copyarea = lynxfb_ops_copyarea, 697 + .fb_imageblit = lynxfb_ops_imageblit, 698 + __FB_DEFAULT_IOMEM_OPS_MMAP, 699 + }; 700 + 701 + static const struct fb_ops lynxfb_ops_accel_with_cursor = { 702 + .owner = THIS_MODULE, 703 + __FB_DEFAULT_IOMEM_OPS_RDWR, 704 + .fb_check_var = lynxfb_ops_check_var, 705 + .fb_set_par = lynxfb_ops_set_par, 706 + .fb_setcolreg = lynxfb_ops_setcolreg, 707 + .fb_blank = lynxfb_ops_blank, 708 + .fb_pan_display = lynxfb_ops_pan_display, 709 + .fb_fillrect = lynxfb_ops_fillrect, 710 + .fb_copyarea = lynxfb_ops_copyarea, 711 + .fb_imageblit = lynxfb_ops_imageblit, 712 + .fb_cursor = lynxfb_ops_cursor, 713 + __FB_DEFAULT_IOMEM_OPS_MMAP, 677 714 }; 678 715 679 716 static int lynxfb_set_fbinfo(struct fb_info *info, int index) ··· 751 714 par->index = index; 752 715 output->channel = &crtc->channel; 753 716 sm750fb_set_drv(par); 754 - lynxfb_ops.fb_pan_display = lynxfb_ops_pan_display; 755 717 756 718 /* 757 719 * set current cursor variable and proc pointer, ··· 767 731 crtc->cursor.vstart = sm750_dev->pvMem + crtc->cursor.offset; 768 732 769 733 memset_io(crtc->cursor.vstart, 0, crtc->cursor.size); 770 - if (!g_hwcursor) { 771 - lynxfb_ops.fb_cursor = NULL; 734 + if (!g_hwcursor) 772 735 sm750_hw_cursor_disable(&crtc->cursor); 773 - } 774 736 775 737 /* set info->fbops, must be set before fb_find_mode */ 776 738 if (!sm750_dev->accel_off) { 777 739 /* use 2d acceleration */ 778 - lynxfb_ops.fb_fillrect = lynxfb_ops_fillrect; 779 - lynxfb_ops.fb_copyarea = lynxfb_ops_copyarea; 780 - lynxfb_ops.fb_imageblit = lynxfb_ops_imageblit; 740 + if (!g_hwcursor) 741 + info->fbops = &lynxfb_ops_accel; 742 + else 743 + info->fbops = &lynxfb_ops_accel_with_cursor; 744 + } else { 745 + if (!g_hwcursor) 746 + info->fbops = &lynxfb_ops; 747 + else 748 + info->fbops = &lynxfb_ops_with_cursor; 781 749 } 782 - info->fbops = &lynxfb_ops; 783 750 784 751 if (!g_fbmode[index]) { 785 752 g_fbmode[index] = g_def_fbmode;
+1 -1
drivers/usb/typec/mux/Kconfig
··· 40 40 tristate "On Semiconductor NB7VPQ904M Type-C redriver driver" 41 41 depends on I2C 42 42 depends on DRM || DRM=n 43 - select DRM_PANEL_BRIDGE if DRM 43 + select DRM_AUX_BRIDGE if DRM_BRIDGE 44 44 select REGMAP_I2C 45 45 help 46 46 Say Y or M if your system has a On Semiconductor NB7VPQ904M Type-C
+2 -42
drivers/usb/typec/mux/nb7vpq904m.c
··· 11 11 #include <linux/regmap.h> 12 12 #include <linux/bitfield.h> 13 13 #include <linux/of_graph.h> 14 - #include <drm/drm_bridge.h> 14 + #include <drm/bridge/aux-bridge.h> 15 15 #include <linux/usb/typec_dp.h> 16 16 #include <linux/usb/typec_mux.h> 17 17 #include <linux/usb/typec_retimer.h> ··· 69 69 70 70 bool swap_data_lanes; 71 71 struct typec_switch *typec_switch; 72 - 73 - struct drm_bridge bridge; 74 72 75 73 struct mutex lock; /* protect non-concurrent retimer & switch */ 76 74 ··· 295 297 return ret; 296 298 } 297 299 298 - #if IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_DRM_PANEL_BRIDGE) 299 - static int nb7vpq904m_bridge_attach(struct drm_bridge *bridge, 300 - enum drm_bridge_attach_flags flags) 301 - { 302 - struct nb7vpq904m *nb7 = container_of(bridge, struct nb7vpq904m, bridge); 303 - struct drm_bridge *next_bridge; 304 - 305 - if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)) 306 - return -EINVAL; 307 - 308 - next_bridge = devm_drm_of_get_bridge(&nb7->client->dev, nb7->client->dev.of_node, 0, 0); 309 - if (IS_ERR(next_bridge)) { 310 - dev_err(&nb7->client->dev, "failed to acquire drm_bridge: %pe\n", next_bridge); 311 - return PTR_ERR(next_bridge); 312 - } 313 - 314 - return drm_bridge_attach(bridge->encoder, next_bridge, bridge, 315 - DRM_BRIDGE_ATTACH_NO_CONNECTOR); 316 - } 317 - 318 - static const struct drm_bridge_funcs nb7vpq904m_bridge_funcs = { 319 - .attach = nb7vpq904m_bridge_attach, 320 - }; 321 - 322 - static int nb7vpq904m_register_bridge(struct nb7vpq904m *nb7) 323 - { 324 - nb7->bridge.funcs = &nb7vpq904m_bridge_funcs; 325 - nb7->bridge.of_node = nb7->client->dev.of_node; 326 - 327 - return devm_drm_bridge_add(&nb7->client->dev, &nb7->bridge); 328 - } 329 - #else 330 - static int nb7vpq904m_register_bridge(struct nb7vpq904m *nb7) 331 - { 332 - return 0; 333 - } 334 - #endif 335 - 336 300 static const struct regmap_config nb7_regmap = { 337 301 .max_register = 0x1f, 338 302 .reg_bits = 8, ··· 421 461 422 462 gpiod_set_value(nb7->enable_gpio, 1); 423 463 424 - ret = nb7vpq904m_register_bridge(nb7); 464 + ret = drm_aux_bridge_register(dev); 425 465 if (ret) 426 466 goto err_disable_gpio; 427 467
+1
drivers/usb/typec/tcpm/Kconfig
··· 80 80 tristate "Qualcomm PMIC USB Type-C Port Controller Manager driver" 81 81 depends on ARCH_QCOM || COMPILE_TEST 82 82 depends on DRM || DRM=n 83 + select DRM_AUX_HPD_BRIDGE if DRM_BRIDGE 83 84 help 84 85 A Type-C port and Power Delivery driver which aggregates two 85 86 discrete pieces of silicon in the PM8150b PMIC block: the
+6 -35
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
··· 18 18 #include <linux/usb/tcpm.h> 19 19 #include <linux/usb/typec_mux.h> 20 20 21 - #include <drm/drm_bridge.h> 21 + #include <drm/bridge/aux-bridge.h> 22 22 23 23 #include "qcom_pmic_typec_pdphy.h" 24 24 #include "qcom_pmic_typec_port.h" ··· 36 36 struct pmic_typec_port *pmic_typec_port; 37 37 bool vbus_enabled; 38 38 struct mutex lock; /* VBUS state serialization */ 39 - struct drm_bridge bridge; 40 39 }; 41 40 42 41 #define tcpc_to_tcpm(_tcpc_) container_of(_tcpc_, struct pmic_typec, tcpc) ··· 149 150 return 0; 150 151 } 151 152 152 - #if IS_ENABLED(CONFIG_DRM) 153 - static int qcom_pmic_typec_attach(struct drm_bridge *bridge, 154 - enum drm_bridge_attach_flags flags) 155 - { 156 - return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL; 157 - } 158 - 159 - static const struct drm_bridge_funcs qcom_pmic_typec_bridge_funcs = { 160 - .attach = qcom_pmic_typec_attach, 161 - }; 162 - 163 - static int qcom_pmic_typec_init_drm(struct pmic_typec *tcpm) 164 - { 165 - tcpm->bridge.funcs = &qcom_pmic_typec_bridge_funcs; 166 - #ifdef CONFIG_OF 167 - tcpm->bridge.of_node = of_get_child_by_name(tcpm->dev->of_node, "connector"); 168 - #endif 169 - tcpm->bridge.ops = DRM_BRIDGE_OP_HPD; 170 - tcpm->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; 171 - 172 - return devm_drm_bridge_add(tcpm->dev, &tcpm->bridge); 173 - } 174 - #else 175 - static int qcom_pmic_typec_init_drm(struct pmic_typec *tcpm) 176 - { 177 - return 0; 178 - } 179 - #endif 180 - 181 153 static int qcom_pmic_typec_probe(struct platform_device *pdev) 182 154 { 183 155 struct pmic_typec *tcpm; ··· 156 186 struct device_node *np = dev->of_node; 157 187 const struct pmic_typec_resources *res; 158 188 struct regmap *regmap; 189 + struct device *bridge_dev; 159 190 u32 base[2]; 160 191 int ret; 161 192 ··· 212 241 mutex_init(&tcpm->lock); 213 242 platform_set_drvdata(pdev, tcpm); 214 243 215 - ret = qcom_pmic_typec_init_drm(tcpm); 216 - if (ret) 217 - return ret; 218 - 219 244 tcpm->tcpc.fwnode = device_get_named_child_node(tcpm->dev, "connector"); 220 245 if (!tcpm->tcpc.fwnode) 221 246 return -EINVAL; 247 + 248 + bridge_dev = drm_dp_hpd_bridge_register(tcpm->dev, to_of_node(tcpm->tcpc.fwnode)); 249 + if (IS_ERR(bridge_dev)) 250 + return PTR_ERR(bridge_dev); 222 251 223 252 tcpm->tcpm_port = tcpm_register_port(tcpm->dev, &tcpm->tcpc); 224 253 if (IS_ERR(tcpm->tcpm_port)) {
+12 -38
drivers/video/fbdev/Kconfig
··· 146 146 config FB_CLPS711X 147 147 tristate "CLPS711X LCD support" 148 148 depends on FB && (ARCH_CLPS711X || COMPILE_TEST) 149 + select FB_IOMEM_HELPERS 149 150 select FB_MODE_HELPERS 150 - select FB_SYS_FILLRECT 151 - select FB_SYS_COPYAREA 152 - select FB_SYS_IMAGEBLIT 153 151 select LCD_CLASS_DEVICE 154 152 select VIDEOMODE_HELPERS 155 153 help ··· 178 180 config FB_CYBER2000 179 181 tristate "CyberPro 2000/2010/5000 support" 180 182 depends on FB && PCI && (BROKEN || !SPARC64) 181 - select FB_CFB_FILLRECT 182 - select FB_CFB_COPYAREA 183 - select FB_CFB_IMAGEBLIT 184 - select FB_IOMEM_FOPS 183 + select FB_IOMEM_HELPERS 185 184 select VIDEO_NOMODESET 186 185 help 187 186 This enables support for the Integraphics CyberPro 20x0 and 5000 ··· 267 272 config FB_ARC 268 273 tristate "Arc Monochrome LCD board support" 269 274 depends on FB && (X86 || COMPILE_TEST) 270 - select FB_SYS_FILLRECT 271 - select FB_SYS_COPYAREA 272 - select FB_SYS_IMAGEBLIT 273 - select FB_SYS_FOPS 275 + select FB_SYSMEM_HELPERS_DEFERRED 274 276 help 275 277 This enables support for the Arc Monochrome LCD board. The board 276 278 is based on the KS-108 lcd controller and is typically a matrix ··· 1452 1460 config FB_AU1200 1453 1461 bool "Au1200/Au1300 LCD Driver" 1454 1462 depends on (FB = y) && MIPS_ALCHEMY 1455 - select FB_SYS_FILLRECT 1456 - select FB_SYS_COPYAREA 1457 - select FB_SYS_IMAGEBLIT 1458 - select FB_SYS_FOPS 1463 + select FB_DMAMEM_HELPERS 1459 1464 help 1460 1465 This is the framebuffer driver for the Au1200/Au1300 SOCs. 1461 1466 It can drive various panels and CRTs by passing in kernel cmd line ··· 1464 1475 select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS) 1465 1476 select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS) 1466 1477 select FB_SYS_IMAGEBLIT 1478 + select FB_SYSMEM_FOPS 1467 1479 select FB_MODE_HELPERS 1468 1480 select VIDEOMODE_HELPERS 1469 1481 help ··· 1477 1487 select FB_SYS_FILLRECT if (!FB_WMT_GE_ROPS) 1478 1488 select FB_SYS_COPYAREA if (!FB_WMT_GE_ROPS) 1479 1489 select FB_SYS_IMAGEBLIT 1490 + select FB_SYSMEM_FOPS 1480 1491 select FB_MODE_HELPERS 1481 1492 select VIDEOMODE_HELPERS 1482 1493 help ··· 1628 1637 depends on FB && HAVE_CLK && HAS_IOMEM 1629 1638 depends on SUPERH || ARCH_RENESAS || COMPILE_TEST 1630 1639 depends on FB_DEVICE 1631 - select FB_SYS_FILLRECT 1632 - select FB_SYS_COPYAREA 1633 - select FB_SYS_IMAGEBLIT 1634 - select FB_SYS_FOPS 1635 - select FB_DEFERRED_IO 1636 1640 select FB_BACKLIGHT 1641 + select FB_DEFERRED_IO 1642 + select FB_DMAMEM_HELPERS 1637 1643 help 1638 1644 Frame buffer driver for the on-chip SH-Mobile LCD controller. 1639 1645 ··· 1677 1689 tristate "SMSC UFX6000/7000 USB Framebuffer support" 1678 1690 depends on FB && USB 1679 1691 select FB_MODE_HELPERS 1680 - select FB_SYS_FILLRECT 1681 - select FB_SYS_COPYAREA 1682 - select FB_SYS_IMAGEBLIT 1683 - select FB_SYS_FOPS 1684 - select FB_DEFERRED_IO 1692 + select FB_SYSMEM_HELPERS_DEFERRED 1685 1693 help 1686 1694 This is a kernel framebuffer driver for SMSC UFX USB devices. 1687 1695 Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and ··· 1690 1706 depends on FB && USB 1691 1707 depends on FB_DEVICE 1692 1708 select FB_MODE_HELPERS 1693 - select FB_SYS_FILLRECT 1694 - select FB_SYS_COPYAREA 1695 - select FB_SYS_IMAGEBLIT 1696 - select FB_SYS_FOPS 1697 - select FB_DEFERRED_IO 1709 + select FB_SYSMEM_HELPERS_DEFERRED 1698 1710 help 1699 1711 This is a kernel framebuffer driver for DisplayLink USB devices. 1700 1712 Supports fbdev clients like xf86-video-fbdev, kdrive, fbi, and ··· 1712 1732 config FB_PS3 1713 1733 tristate "PS3 GPU framebuffer driver" 1714 1734 depends on FB && PS3_PS3AV 1715 - select FB_SYS_FILLRECT 1716 - select FB_SYS_COPYAREA 1717 - select FB_SYS_IMAGEBLIT 1718 - select FB_SYS_FOPS 1735 + select FB_SYSMEM_HELPERS 1719 1736 help 1720 1737 Include support for the virtual frame buffer in the PS3 platform. 1721 1738 ··· 1777 1800 config FB_VIRTUAL 1778 1801 tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" 1779 1802 depends on FB 1780 - select FB_SYS_FILLRECT 1781 - select FB_SYS_COPYAREA 1782 - select FB_SYS_IMAGEBLIT 1783 - select FB_SYS_FOPS 1803 + select FB_SYSMEM_HELPERS 1784 1804 help 1785 1805 This is a `virtual' frame buffer device. It operates on a chunk of 1786 1806 unswappable kernel memory instead of on the memory of a graphics
+1 -1
drivers/video/fbdev/acornfb.c
··· 605 605 606 606 static const struct fb_ops acornfb_ops = { 607 607 .owner = THIS_MODULE, 608 - FB_IOMEM_DEFAULT_OPS, 608 + FB_DEFAULT_IOMEM_OPS, 609 609 .fb_check_var = acornfb_check_var, 610 610 .fb_set_par = acornfb_set_par, 611 611 .fb_setcolreg = acornfb_setcolreg,
+2
drivers/video/fbdev/amba-clcd.c
··· 829 829 830 830 static int clcdfb_of_dma_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) 831 831 { 832 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 833 + 832 834 return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base, 833 835 fb->fb.fix.smem_start, fb->fb.fix.smem_len); 834 836 }
+27 -87
drivers/video/fbdev/arcfb.c
··· 363 363 } 364 364 } 365 365 366 - static void arcfb_fillrect(struct fb_info *info, 367 - const struct fb_fillrect *rect) 368 - { 369 - struct arcfb_par *par = info->par; 370 - 371 - sys_fillrect(info, rect); 372 - 373 - /* update the physical lcd */ 374 - arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height); 375 - } 376 - 377 - static void arcfb_copyarea(struct fb_info *info, 378 - const struct fb_copyarea *area) 379 - { 380 - struct arcfb_par *par = info->par; 381 - 382 - sys_copyarea(info, area); 383 - 384 - /* update the physical lcd */ 385 - arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height); 386 - } 387 - 388 - static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image) 389 - { 390 - struct arcfb_par *par = info->par; 391 - 392 - sys_imageblit(info, image); 393 - 394 - /* update the physical lcd */ 395 - arcfb_lcd_update(par, image->dx, image->dy, image->width, 396 - image->height); 397 - } 398 - 399 366 static int arcfb_ioctl(struct fb_info *info, 400 367 unsigned int cmd, unsigned long arg) 401 368 { ··· 403 436 } 404 437 } 405 438 406 - /* 407 - * this is the access path from userspace. they can seek and write to 408 - * the fb. it's inefficient for them to do anything less than 64*8 409 - * writes since we update the lcd in each write() anyway. 410 - */ 411 - static ssize_t arcfb_write(struct fb_info *info, const char __user *buf, 412 - size_t count, loff_t *ppos) 439 + static void arcfb_damage_range(struct fb_info *info, off_t off, size_t len) 413 440 { 414 - /* modded from epson 1355 */ 441 + struct arcfb_par *par = info->par; 442 + unsigned int xres = info->var.xres; 443 + unsigned int bitppos, startpos, endpos, bitcount; 444 + unsigned int x, y, width, height; 415 445 416 - unsigned long p; 417 - int err; 418 - unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount; 419 - struct arcfb_par *par; 420 - unsigned int xres; 421 - 422 - if (!info->screen_buffer) 423 - return -ENODEV; 424 - 425 - p = *ppos; 426 - par = info->par; 427 - xres = info->var.xres; 428 - fbmemlength = (xres * info->var.yres)/8; 429 - 430 - if (p > fbmemlength) 431 - return -ENOSPC; 432 - 433 - err = 0; 434 - if ((count + p) > fbmemlength) { 435 - count = fbmemlength - p; 436 - err = -ENOSPC; 437 - } 438 - 439 - if (count) { 440 - char *base_addr; 441 - 442 - base_addr = info->screen_buffer; 443 - count -= copy_from_user(base_addr + p, buf, count); 444 - *ppos += count; 445 - err = -EFAULT; 446 - } 447 - 448 - 449 - bitppos = p*8; 446 + bitppos = off * 8; 450 447 startpos = floorXres(bitppos, xres); 451 - endpos = ceilXres((bitppos + (count*8)), xres); 448 + endpos = ceilXres((bitppos + (len * 8)), xres); 452 449 bitcount = endpos - startpos; 453 450 454 451 x = startpos % xres; 455 452 y = startpos / xres; 456 - w = xres; 457 - h = bitcount / xres; 458 - arcfb_lcd_update(par, x, y, w, h); 453 + width = xres; 454 + height = bitcount / xres; 459 455 460 - if (count) 461 - return count; 462 - return err; 456 + arcfb_lcd_update(par, x, y, width, height); 463 457 } 458 + 459 + static void arcfb_damage_area(struct fb_info *info, u32 x, u32 y, 460 + u32 width, u32 height) 461 + { 462 + struct arcfb_par *par = info->par; 463 + 464 + /* update the physical lcd */ 465 + arcfb_lcd_update(par, x, y, width, height); 466 + } 467 + 468 + FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(arcfb, 469 + arcfb_damage_range, 470 + arcfb_damage_area) 464 471 465 472 static const struct fb_ops arcfb_ops = { 466 473 .owner = THIS_MODULE, 467 474 .fb_open = arcfb_open, 468 - .fb_read = fb_sys_read, 469 - .fb_write = arcfb_write, 475 + __FB_DEFAULT_DEFERRED_OPS_RDWR(arcfb), 470 476 .fb_release = arcfb_release, 471 477 .fb_pan_display = arcfb_pan_display, 472 - .fb_fillrect = arcfb_fillrect, 473 - .fb_copyarea = arcfb_copyarea, 474 - .fb_imageblit = arcfb_imageblit, 478 + __FB_DEFAULT_DEFERRED_OPS_DRAW(arcfb), 475 479 .fb_ioctl = arcfb_ioctl, 480 + // .fb_mmap reqires deferred I/O 476 481 }; 477 482 478 483 static int arcfb_probe(struct platform_device *dev) ··· 468 529 if (!info) 469 530 goto err_fb_alloc; 470 531 532 + info->flags |= FBINFO_VIRTFB; 471 533 info->screen_buffer = videomemory; 472 534 info->fbops = &arcfb_ops; 473 535
+2
drivers/video/fbdev/au1100fb.c
··· 342 342 { 343 343 struct au1100fb_device *fbdev = to_au1100fb_device(fbi); 344 344 345 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 346 + 345 347 pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6 346 348 347 349 return dma_mmap_coherent(fbdev->dev, vma, fbdev->fb_mem, fbdev->fb_phys,
+6 -5
drivers/video/fbdev/au1200fb.c
··· 1236 1236 { 1237 1237 struct au1200fb_device *fbdev = info->par; 1238 1238 1239 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 1240 + 1239 1241 return dma_mmap_coherent(fbdev->dev, vma, 1240 1242 fbdev->fb_mem, fbdev->fb_phys, fbdev->fb_len); 1241 1243 } ··· 1490 1488 1491 1489 static const struct fb_ops au1200fb_fb_ops = { 1492 1490 .owner = THIS_MODULE, 1491 + __FB_DEFAULT_DMAMEM_OPS_RDWR, 1493 1492 .fb_check_var = au1200fb_fb_check_var, 1494 1493 .fb_set_par = au1200fb_fb_set_par, 1495 1494 .fb_setcolreg = au1200fb_fb_setcolreg, 1496 1495 .fb_blank = au1200fb_fb_blank, 1497 - .fb_fillrect = sys_fillrect, 1498 - .fb_copyarea = sys_copyarea, 1499 - .fb_imageblit = sys_imageblit, 1500 - .fb_read = fb_sys_read, 1501 - .fb_write = fb_sys_write, 1496 + __FB_DEFAULT_DMAMEM_OPS_DRAW, 1502 1497 .fb_sync = NULL, 1503 1498 .fb_ioctl = au1200fb_ioctl, 1504 1499 .fb_mmap = au1200fb_fb_mmap, ··· 1566 1567 fbi->fix.mmio_start = 0; 1567 1568 fbi->fix.mmio_len = 0; 1568 1569 fbi->fix.accel = FB_ACCEL_NONE; 1570 + 1571 + fbi->flags |= FBINFO_VIRTFB; 1569 1572 1570 1573 fbi->screen_buffer = fbdev->fb_mem; 1571 1574
+1 -3
drivers/video/fbdev/clps711x-fb.c
··· 155 155 156 156 static const struct fb_ops clps711x_fb_ops = { 157 157 .owner = THIS_MODULE, 158 + FB_DEFAULT_IOMEM_OPS, 158 159 .fb_setcolreg = clps711x_fb_setcolreg, 159 160 .fb_check_var = clps711x_fb_check_var, 160 161 .fb_set_par = clps711x_fb_set_par, 161 162 .fb_blank = clps711x_fb_blank, 162 - .fb_fillrect = sys_fillrect, 163 - .fb_copyarea = sys_copyarea, 164 - .fb_imageblit = sys_imageblit, 165 163 }; 166 164 167 165 static int clps711x_lcd_check_fb(struct lcd_device *lcddev, struct fb_info *fi)
+3 -4
drivers/video/fbdev/core/Kconfig
··· 4 4 # 5 5 6 6 config FB_CORE 7 - select FB_IOMEM_FOPS 8 7 select VIDEO_CMDLINE 9 8 tristate 10 9 ··· 128 129 129 130 endchoice 130 131 131 - config FB_SYS_FOPS 132 + config FB_SYSMEM_FOPS 132 133 tristate 133 134 depends on FB_CORE 134 135 ··· 141 142 depends on FB_CORE 142 143 select FB_SYS_COPYAREA 143 144 select FB_SYS_FILLRECT 144 - select FB_SYS_FOPS 145 145 select FB_SYS_IMAGEBLIT 146 + select FB_SYSMEM_FOPS 146 147 147 148 config FB_IOMEM_FOPS 148 149 tristate ··· 167 168 depends on FB_CORE 168 169 select FB_SYS_COPYAREA 169 170 select FB_SYS_FILLRECT 170 - select FB_SYS_FOPS 171 171 select FB_SYS_IMAGEBLIT 172 + select FB_SYSMEM_FOPS 172 173 173 174 config FB_SYSMEM_HELPERS_DEFERRED 174 175 bool
+1 -1
drivers/video/fbdev/core/Makefile
··· 32 32 obj-$(CONFIG_FB_SYS_FILLRECT) += sysfillrect.o 33 33 obj-$(CONFIG_FB_SYS_COPYAREA) += syscopyarea.o 34 34 obj-$(CONFIG_FB_SYS_IMAGEBLIT) += sysimgblt.o 35 - obj-$(CONFIG_FB_SYS_FOPS) += fb_sys_fops.o 35 + obj-$(CONFIG_FB_SYSMEM_FOPS) += fb_sys_fops.o 36 36 obj-$(CONFIG_FB_SVGALIB) += svgalib.o 37 37 obj-$(CONFIG_FB_DDC) += fb_ddc.o
+3
drivers/video/fbdev/core/cfbcopyarea.c
··· 391 391 if (p->state != FBINFO_STATE_RUNNING) 392 392 return; 393 393 394 + if (p->flags & FBINFO_VIRTFB) 395 + fb_warn_once(p, "Framebuffer is not in I/O address space."); 396 + 394 397 /* if the beginning of the target area might overlap with the end of 395 398 the source area, be have to copy the area reverse. */ 396 399 if ((dy == sy && dx > sx) || (dy > sy)) {
+3
drivers/video/fbdev/core/cfbfillrect.c
··· 287 287 if (p->state != FBINFO_STATE_RUNNING) 288 288 return; 289 289 290 + if (p->flags & FBINFO_VIRTFB) 291 + fb_warn_once(p, "Framebuffer is not in I/O address space."); 292 + 290 293 if (p->fix.visual == FB_VISUAL_TRUECOLOR || 291 294 p->fix.visual == FB_VISUAL_DIRECTCOLOR ) 292 295 fg = ((u32 *) (p->pseudo_palette))[rect->color];
+3
drivers/video/fbdev/core/cfbimgblt.c
··· 326 326 if (p->state != FBINFO_STATE_RUNNING) 327 327 return; 328 328 329 + if (p->flags & FBINFO_VIRTFB) 330 + fb_warn_once(p, "Framebuffer is not in I/O address space."); 331 + 329 332 bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); 330 333 start_index = bitstart & (32 - 1); 331 334 pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
+13 -55
drivers/video/fbdev/core/fb_chrdev.c
··· 34 34 if (!info) 35 35 return -ENODEV; 36 36 37 + if (fb_WARN_ON_ONCE(info, !info->fbops->fb_read)) 38 + return -EINVAL; 39 + 37 40 if (info->state != FBINFO_STATE_RUNNING) 38 41 return -EPERM; 39 42 40 - if (info->fbops->fb_read) 41 - return info->fbops->fb_read(info, buf, count, ppos); 42 - 43 - return fb_io_read(info, buf, count, ppos); 43 + return info->fbops->fb_read(info, buf, count, ppos); 44 44 } 45 45 46 46 static ssize_t fb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) ··· 50 50 if (!info) 51 51 return -ENODEV; 52 52 53 + if (fb_WARN_ON_ONCE(info, !info->fbops->fb_write)) 54 + return -EINVAL; 55 + 53 56 if (info->state != FBINFO_STATE_RUNNING) 54 57 return -EPERM; 55 58 56 - if (info->fbops->fb_write) 57 - return info->fbops->fb_write(info, buf, count, ppos); 58 - 59 - return fb_io_write(info, buf, count, ppos); 59 + return info->fbops->fb_write(info, buf, count, ppos); 60 60 } 61 61 62 62 static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, ··· 314 314 static int fb_mmap(struct file *file, struct vm_area_struct *vma) 315 315 { 316 316 struct fb_info *info = file_fb_info(file); 317 - unsigned long mmio_pgoff; 318 - unsigned long start; 319 - u32 len; 317 + int res; 320 318 321 319 if (!info) 322 320 return -ENODEV; 323 - mutex_lock(&info->mm_lock); 324 321 325 - if (info->fbops->fb_mmap) { 326 - int res; 327 - 328 - /* 329 - * The framebuffer needs to be accessed decrypted, be sure 330 - * SME protection is removed ahead of the call 331 - */ 332 - vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 333 - res = info->fbops->fb_mmap(info, vma); 334 - mutex_unlock(&info->mm_lock); 335 - return res; 336 - #if IS_ENABLED(CONFIG_FB_DEFERRED_IO) 337 - } else if (info->fbdefio) { 338 - /* 339 - * FB deferred I/O wants you to handle mmap in your drivers. At a 340 - * minimum, point struct fb_ops.fb_mmap to fb_deferred_io_mmap(). 341 - */ 342 - dev_warn_once(info->dev, "fbdev mmap not set up for deferred I/O.\n"); 343 - mutex_unlock(&info->mm_lock); 322 + if (fb_WARN_ON_ONCE(info, !info->fbops->fb_mmap)) 344 323 return -ENODEV; 345 - #endif 346 - } 347 324 348 - /* 349 - * Ugh. This can be either the frame buffer mapping, or 350 - * if pgoff points past it, the mmio mapping. 351 - */ 352 - start = info->fix.smem_start; 353 - len = info->fix.smem_len; 354 - mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT; 355 - if (vma->vm_pgoff >= mmio_pgoff) { 356 - if (info->var.accel_flags) { 357 - mutex_unlock(&info->mm_lock); 358 - return -EINVAL; 359 - } 360 - 361 - vma->vm_pgoff -= mmio_pgoff; 362 - start = info->fix.mmio_start; 363 - len = info->fix.mmio_len; 364 - } 325 + mutex_lock(&info->mm_lock); 326 + res = info->fbops->fb_mmap(info, vma); 365 327 mutex_unlock(&info->mm_lock); 366 328 367 - vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 368 - vma->vm_page_prot = pgprot_framebuffer(vma->vm_page_prot, vma->vm_start, 369 - vma->vm_end, start); 370 - 371 - return vm_iomap_memory(vma, start, len); 329 + return res; 372 330 } 373 331 374 332 static int fb_open(struct inode *inode, struct file *file)
+2
drivers/video/fbdev/core/fb_defio.c
··· 227 227 228 228 int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) 229 229 { 230 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 231 + 230 232 vma->vm_ops = &fb_deferred_io_vm_ops; 231 233 vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP); 232 234 if (!(info->flags & FBINFO_VIRTFB))
+36
drivers/video/fbdev/core/fb_io_fops.c
··· 12 12 int c, cnt = 0, err = 0; 13 13 unsigned long total_size, trailing; 14 14 15 + if (info->flags & FBINFO_VIRTFB) 16 + fb_warn_once(info, "Framebuffer is not in I/O address space."); 17 + 15 18 if (!info->screen_base) 16 19 return -ENODEV; 17 20 ··· 76 73 int c, cnt = 0, err = 0; 77 74 unsigned long total_size, trailing; 78 75 76 + if (info->flags & FBINFO_VIRTFB) 77 + fb_warn_once(info, "Framebuffer is not in I/O address space."); 78 + 79 79 if (!info->screen_base) 80 80 return -ENODEV; 81 81 ··· 137 131 return (cnt) ? cnt : err; 138 132 } 139 133 EXPORT_SYMBOL(fb_io_write); 134 + 135 + int fb_io_mmap(struct fb_info *info, struct vm_area_struct *vma) 136 + { 137 + unsigned long start = info->fix.smem_start; 138 + u32 len = info->fix.smem_len; 139 + unsigned long mmio_pgoff = PAGE_ALIGN((start & ~PAGE_MASK) + len) >> PAGE_SHIFT; 140 + 141 + if (info->flags & FBINFO_VIRTFB) 142 + fb_warn_once(info, "Framebuffer is not in I/O address space."); 143 + 144 + /* 145 + * This can be either the framebuffer mapping, or if pgoff points 146 + * past it, the mmio mapping. 147 + */ 148 + if (vma->vm_pgoff >= mmio_pgoff) { 149 + if (info->var.accel_flags) 150 + return -EINVAL; 151 + 152 + vma->vm_pgoff -= mmio_pgoff; 153 + start = info->fix.mmio_start; 154 + len = info->fix.mmio_len; 155 + } 156 + 157 + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); 158 + vma->vm_page_prot = pgprot_framebuffer(vma->vm_page_prot, vma->vm_start, 159 + vma->vm_end, start); 160 + 161 + return vm_iomap_memory(vma, start, len); 162 + } 163 + EXPORT_SYMBOL(fb_io_mmap); 140 164 141 165 MODULE_DESCRIPTION("Fbdev helpers for framebuffers in I/O memory"); 142 166 MODULE_LICENSE("GPL");
+6
drivers/video/fbdev/core/fb_sys_fops.c
··· 22 22 unsigned long total_size, c; 23 23 ssize_t ret; 24 24 25 + if (!(info->flags & FBINFO_VIRTFB)) 26 + fb_warn_once(info, "Framebuffer is not in virtual address space."); 27 + 25 28 if (!info->screen_buffer) 26 29 return -ENODEV; 27 30 ··· 66 63 int err = 0; 67 64 unsigned long total_size, c; 68 65 size_t ret; 66 + 67 + if (!(info->flags & FBINFO_VIRTFB)) 68 + fb_warn_once(info, "Framebuffer is not in virtual address space."); 69 69 70 70 if (!info->screen_buffer) 71 71 return -ENODEV;
+3
drivers/video/fbdev/core/syscopyarea.c
··· 324 324 if (p->state != FBINFO_STATE_RUNNING) 325 325 return; 326 326 327 + if (!(p->flags & FBINFO_VIRTFB)) 328 + fb_warn_once(p, "Framebuffer is not in virtual address space."); 329 + 327 330 /* if the beginning of the target area might overlap with the end of 328 331 the source area, be have to copy the area reverse. */ 329 332 if ((dy == sy && dx > sx) || (dy > sy)) {
+3
drivers/video/fbdev/core/sysfillrect.c
··· 242 242 if (p->state != FBINFO_STATE_RUNNING) 243 243 return; 244 244 245 + if (!(p->flags & FBINFO_VIRTFB)) 246 + fb_warn_once(p, "Framebuffer is not in virtual address space."); 247 + 245 248 if (p->fix.visual == FB_VISUAL_TRUECOLOR || 246 249 p->fix.visual == FB_VISUAL_DIRECTCOLOR ) 247 250 fg = ((u32 *) (p->pseudo_palette))[rect->color];
+3
drivers/video/fbdev/core/sysimgblt.c
··· 296 296 if (p->state != FBINFO_STATE_RUNNING) 297 297 return; 298 298 299 + if (!(p->flags & FBINFO_VIRTFB)) 300 + fb_warn_once(p, "Framebuffer is not in virtual address space."); 301 + 299 302 bitstart = (dy * p->fix.line_length * 8) + (dx * bpp); 300 303 start_index = bitstart & (32 - 1); 301 304 pitch_index = (p->fix.line_length & (bpl - 1)) * 8;
+1 -8
drivers/video/fbdev/cyber2000fb.c
··· 227 227 CO_REG_CMD_H, cfb); 228 228 } 229 229 230 - static void 231 - cyber2000fb_imageblit(struct fb_info *info, const struct fb_image *image) 232 - { 233 - cfb_imageblit(info, image); 234 - return; 235 - } 236 - 237 230 static int cyber2000fb_sync(struct fb_info *info) 238 231 { 239 232 struct cfb_info *cfb = container_of(info, struct cfb_info, fb); ··· 1062 1069 .fb_pan_display = cyber2000fb_pan_display, 1063 1070 .fb_fillrect = cyber2000fb_fillrect, 1064 1071 .fb_copyarea = cyber2000fb_copyarea, 1065 - .fb_imageblit = cyber2000fb_imageblit, 1072 + .fb_imageblit = cfb_imageblit, 1066 1073 .fb_sync = cyber2000fb_sync, 1067 1074 __FB_DEFAULT_IOMEM_OPS_MMAP, 1068 1075 };
+2
drivers/video/fbdev/ep93xx-fb.c
··· 311 311 { 312 312 unsigned int offset = vma->vm_pgoff << PAGE_SHIFT; 313 313 314 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 315 + 314 316 if (offset < info->fix.smem_len) { 315 317 return dma_mmap_wc(info->device, vma, info->screen_base, 316 318 info->fix.smem_start, info->fix.smem_len);
+2
drivers/video/fbdev/gbefb.c
··· 1000 1000 unsigned long phys_addr, phys_size; 1001 1001 u16 *tile; 1002 1002 1003 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 1004 + 1003 1005 /* check range */ 1004 1006 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) 1005 1007 return -EINVAL;
+2
drivers/video/fbdev/omap/omapfb_main.c
··· 1203 1203 struct omapfb_device *fbdev = plane->fbdev; 1204 1204 int r; 1205 1205 1206 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 1207 + 1206 1208 omapfb_rqueue_lock(fbdev); 1207 1209 r = fbdev->ctrl->mmap(info, vma); 1208 1210 omapfb_rqueue_unlock(fbdev);
+2
drivers/video/fbdev/omap2/omapfb/omapfb-main.c
··· 1095 1095 u32 len; 1096 1096 int r; 1097 1097 1098 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 1099 + 1098 1100 rg = omapfb_get_mem_region(ofbi->region); 1099 1101 1100 1102 start = omapfb_get_region_paddr(ofbi);
+5 -6
drivers/video/fbdev/ps3fb.c
··· 708 708 { 709 709 int r; 710 710 711 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 712 + 711 713 r = vm_iomap_memory(vma, info->fix.smem_start, info->fix.smem_len); 712 714 713 715 dev_dbg(info->device, "ps3fb: mmap framebuffer P(%lx)->V(%lx)\n", ··· 941 939 .owner = THIS_MODULE, 942 940 .fb_open = ps3fb_open, 943 941 .fb_release = ps3fb_release, 944 - .fb_read = fb_sys_read, 945 - .fb_write = fb_sys_write, 942 + __FB_DEFAULT_SYSMEM_OPS_RDWR, 946 943 .fb_check_var = ps3fb_check_var, 947 944 .fb_set_par = ps3fb_set_par, 948 945 .fb_setcolreg = ps3fb_setcolreg, 949 946 .fb_pan_display = ps3fb_pan_display, 950 - .fb_fillrect = sys_fillrect, 951 - .fb_copyarea = sys_copyarea, 952 - .fb_imageblit = sys_imageblit, 947 + __FB_DEFAULT_SYSMEM_OPS_DRAW, 953 948 .fb_mmap = ps3fb_mmap, 954 949 .fb_blank = ps3fb_blank, 955 950 .fb_ioctl = ps3fb_ioctl, ··· 1144 1145 info->fix.smem_len = ps3fb_videomemory.size - GPU_FB_START; 1145 1146 1146 1147 info->pseudo_palette = par->pseudo_palette; 1147 - info->flags = FBINFO_READS_FAST | 1148 + info->flags = FBINFO_VIRTFB | FBINFO_READS_FAST | 1148 1149 FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN; 1149 1150 1150 1151 retval = fb_alloc_cmap(&info->cmap, 256, 0);
+2
drivers/video/fbdev/sa1100fb.c
··· 562 562 container_of(info, struct sa1100fb_info, fb); 563 563 unsigned long off = vma->vm_pgoff << PAGE_SHIFT; 564 564 565 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 566 + 565 567 if (off < info->fix.smem_len) { 566 568 vma->vm_pgoff += 1; /* skip over the palette */ 567 569 return dma_mmap_wc(fbi->dev, vma, fbi->map_cpu, fbi->map_dma,
+3 -2
drivers/video/fbdev/sbuslib.c
··· 48 48 unsigned long map_offset = 0; 49 49 unsigned long off; 50 50 int i; 51 - 51 + 52 52 if (!(vma->vm_flags & (VM_SHARED | VM_MAYSHARE))) 53 53 return -EINVAL; 54 54 ··· 60 60 61 61 /* VM_IO | VM_DONTEXPAND | VM_DONTDUMP are set by remap_pfn_range() */ 62 62 63 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 63 64 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 64 65 65 66 /* Each page, see which map applies */ ··· 73 72 #define POFF_MASK (PAGE_MASK|0x1UL) 74 73 #else 75 74 #define POFF_MASK (PAGE_MASK) 76 - #endif 75 + #endif 77 76 map_offset = (physbase + map[i].poff) & POFF_MASK; 78 77 break; 79 78 }
+9 -7
drivers/video/fbdev/sh_mobile_lcdcfb.c
··· 1482 1482 if (info->fbdefio) 1483 1483 return fb_deferred_io_mmap(info, vma); 1484 1484 1485 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 1486 + 1485 1487 return dma_mmap_coherent(ovl->channel->lcdc->dev, vma, ovl->fb_mem, 1486 1488 ovl->dma_handle, ovl->fb_size); 1487 1489 } 1488 1490 1489 1491 static const struct fb_ops sh_mobile_lcdc_overlay_ops = { 1490 1492 .owner = THIS_MODULE, 1491 - .fb_read = fb_sys_read, 1492 - .fb_write = fb_sys_write, 1493 - .fb_fillrect = sys_fillrect, 1494 - .fb_copyarea = sys_copyarea, 1495 - .fb_imageblit = sys_imageblit, 1493 + __FB_DEFAULT_DMAMEM_OPS_RDWR, 1496 1494 .fb_blank = sh_mobile_lcdc_overlay_blank, 1497 1495 .fb_pan_display = sh_mobile_lcdc_overlay_pan, 1496 + __FB_DEFAULT_DMAMEM_OPS_DRAW, 1498 1497 .fb_ioctl = sh_mobile_lcdc_overlay_ioctl, 1499 1498 .fb_check_var = sh_mobile_lcdc_overlay_check_var, 1500 1499 .fb_set_par = sh_mobile_lcdc_overlay_set_par, ··· 1566 1567 1567 1568 info->fbops = &sh_mobile_lcdc_overlay_ops; 1568 1569 info->device = priv->dev; 1570 + info->flags |= FBINFO_VIRTFB; 1569 1571 info->screen_buffer = ovl->fb_mem; 1570 1572 info->par = ovl; 1571 1573 ··· 1958 1958 if (info->fbdefio) 1959 1959 return fb_deferred_io_mmap(info, vma); 1960 1960 1961 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 1962 + 1961 1963 return dma_mmap_coherent(ch->lcdc->dev, vma, ch->fb_mem, 1962 1964 ch->dma_handle, ch->fb_size); 1963 1965 } ··· 1967 1965 static const struct fb_ops sh_mobile_lcdc_ops = { 1968 1966 .owner = THIS_MODULE, 1969 1967 .fb_setcolreg = sh_mobile_lcdc_setcolreg, 1970 - .fb_read = fb_sys_read, 1971 - .fb_write = fb_sys_write, 1968 + __FB_DEFAULT_DMAMEM_OPS_RDWR, 1972 1969 .fb_fillrect = sh_mobile_lcdc_fillrect, 1973 1970 .fb_copyarea = sh_mobile_lcdc_copyarea, 1974 1971 .fb_imageblit = sh_mobile_lcdc_imageblit, ··· 2054 2053 2055 2054 info->fbops = &sh_mobile_lcdc_ops; 2056 2055 info->device = priv->dev; 2056 + info->flags |= FBINFO_VIRTFB; 2057 2057 info->screen_buffer = ch->fb_mem; 2058 2058 info->pseudo_palette = &ch->pseudo_palette; 2059 2059 info->par = ch;
+2 -4
drivers/video/fbdev/sm712fb.c
··· 1347 1347 1348 1348 static const struct fb_ops smtcfb_ops = { 1349 1349 .owner = THIS_MODULE, 1350 - FB_DEFAULT_IOMEM_OPS, 1351 1350 .fb_check_var = smtc_check_var, 1352 1351 .fb_set_par = smtc_set_par, 1353 1352 .fb_setcolreg = smtc_setcolreg, 1354 1353 .fb_blank = smtc_blank, 1355 - .fb_fillrect = cfb_fillrect, 1356 - .fb_imageblit = cfb_imageblit, 1357 - .fb_copyarea = cfb_copyarea, 1354 + __FB_DEFAULT_IOMEM_OPS_DRAW, 1358 1355 .fb_read = smtcfb_read, 1359 1356 .fb_write = smtcfb_write, 1357 + __FB_DEFAULT_IOMEM_OPS_MMAP, 1360 1358 }; 1361 1359 1362 1360 /*
+2
drivers/video/fbdev/smscufx.c
··· 783 783 if (info->fbdefio) 784 784 return fb_deferred_io_mmap(info, vma); 785 785 786 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 787 + 786 788 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) 787 789 return -EINVAL; 788 790 if (size > info->fix.smem_len)
+2
drivers/video/fbdev/udlfb.c
··· 331 331 if (info->fbdefio) 332 332 return fb_deferred_io_mmap(info, vma); 333 333 334 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 335 + 334 336 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) 335 337 return -EINVAL; 336 338 if (size > info->fix.smem_len)
+2
drivers/video/fbdev/vermilion/vermilion.c
··· 998 998 int ret; 999 999 unsigned long prot; 1000 1000 1001 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 1002 + 1001 1003 ret = vmlfb_vram_offset(vinfo, offset); 1002 1004 if (ret) 1003 1005 return -EINVAL;
+5 -5
drivers/video/fbdev/vfb.c
··· 80 80 81 81 static const struct fb_ops vfb_ops = { 82 82 .owner = THIS_MODULE, 83 - .fb_read = fb_sys_read, 84 - .fb_write = fb_sys_write, 83 + __FB_DEFAULT_SYSMEM_OPS_RDWR, 85 84 .fb_check_var = vfb_check_var, 86 85 .fb_set_par = vfb_set_par, 87 86 .fb_setcolreg = vfb_setcolreg, 88 87 .fb_pan_display = vfb_pan_display, 89 - .fb_fillrect = sys_fillrect, 90 - .fb_copyarea = sys_copyarea, 91 - .fb_imageblit = sys_imageblit, 88 + __FB_DEFAULT_SYSMEM_OPS_DRAW, 92 89 .fb_mmap = vfb_mmap, 93 90 }; 94 91 ··· 382 385 static int vfb_mmap(struct fb_info *info, 383 386 struct vm_area_struct *vma) 384 387 { 388 + vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot); 389 + 385 390 return remap_vmalloc_range(vma, (void *)info->fix.smem_start, vma->vm_pgoff); 386 391 } 387 392 ··· 439 440 if (!info) 440 441 goto err; 441 442 443 + info->flags |= FBINFO_VIRTFB; 442 444 info->screen_buffer = videomemory; 443 445 info->fbops = &vfb_ops; 444 446
+3 -1
drivers/video/fbdev/vt8500lcdfb.c
··· 241 241 242 242 static const struct fb_ops vt8500lcd_ops = { 243 243 .owner = THIS_MODULE, 244 + __FB_DEFAULT_DMAMEM_OPS_RDWR, 244 245 .fb_set_par = vt8500lcd_set_par, 245 246 .fb_setcolreg = vt8500lcd_setcolreg, 246 247 .fb_fillrect = wmt_ge_fillrect, ··· 251 250 .fb_ioctl = vt8500lcd_ioctl, 252 251 .fb_pan_display = vt8500lcd_pan_display, 253 252 .fb_blank = vt8500lcd_blank, 253 + // .fb_mmap needs DMA mmap 254 254 }; 255 255 256 256 static irqreturn_t vt8500lcd_handle_irq(int irq, void *dev_id) ··· 359 357 360 358 fbi->fb.fix.smem_start = fb_mem_phys; 361 359 fbi->fb.fix.smem_len = fb_mem_len; 362 - fbi->fb.screen_base = fb_mem_virt; 360 + fbi->fb.screen_buffer = fb_mem_virt; 363 361 364 362 fbi->palette_size = PAGE_ALIGN(512); 365 363 fbi->palette_cpu = dma_alloc_coherent(&pdev->dev,
+2
drivers/video/fbdev/wm8505fb.c
··· 248 248 249 249 static const struct fb_ops wm8505fb_ops = { 250 250 .owner = THIS_MODULE, 251 + __FB_DEFAULT_DMAMEM_OPS_RDWR, 251 252 .fb_set_par = wm8505fb_set_par, 252 253 .fb_setcolreg = wm8505fb_setcolreg, 253 254 .fb_fillrect = wmt_ge_fillrect, ··· 257 256 .fb_sync = wmt_ge_sync, 258 257 .fb_pan_display = wm8505fb_pan_display, 259 258 .fb_blank = wm8505fb_blank, 259 + __FB_DEFAULT_IOMEM_OPS_MMAP, 260 260 }; 261 261 262 262 static int wm8505fb_probe(struct platform_device *pdev)
+37
include/drm/bridge/aux-bridge.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Copyright (C) 2023 Linaro Ltd. 4 + * 5 + * Author: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> 6 + */ 7 + #ifndef DRM_AUX_BRIDGE_H 8 + #define DRM_AUX_BRIDGE_H 9 + 10 + #include <drm/drm_connector.h> 11 + 12 + #if IS_ENABLED(CONFIG_DRM_AUX_BRIDGE) 13 + int drm_aux_bridge_register(struct device *parent); 14 + #else 15 + static inline int drm_aux_bridge_register(struct device *parent) 16 + { 17 + return 0; 18 + } 19 + #endif 20 + 21 + #if IS_ENABLED(CONFIG_DRM_AUX_HPD_BRIDGE) 22 + struct device *drm_dp_hpd_bridge_register(struct device *parent, 23 + struct device_node *np); 24 + void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status); 25 + #else 26 + static inline struct device *drm_dp_hpd_bridge_register(struct device *parent, 27 + struct device_node *np) 28 + { 29 + return 0; 30 + } 31 + 32 + static inline void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status) 33 + { 34 + } 35 + #endif 36 + 37 + #endif
+3
include/drm/display/drm_dp.h
··· 651 651 # define DP_LINK_QUAL_PATTERN_PRSBS31 0x38 652 652 # define DP_LINK_QUAL_PATTERN_CUSTOM 0x40 653 653 # define DP_LINK_QUAL_PATTERN_SQUARE 0x48 654 + # define DP_LINK_QUAL_PATTERN_SQUARE_PRESHOOT_DISABLED 0x49 655 + # define DP_LINK_QUAL_PATTERN_SQUARE_DEEMPHASIS_DISABLED 0x4a 656 + # define DP_LINK_QUAL_PATTERN_SQUARE_PRESHOOT_DEEMPHASIS_DISABLED 0x4b 654 657 655 658 #define DP_TRAINING_LANE0_1_SET2 0x10f 656 659 #define DP_TRAINING_LANE2_3_SET2 0x110
-22
include/drm/drm_auth.h
··· 33 33 #include <linux/wait.h> 34 34 35 35 struct drm_file; 36 - struct drm_hw_lock; 37 - 38 - /* 39 - * Legacy DRI1 locking data structure. Only here instead of in drm_legacy.h for 40 - * include ordering reasons. 41 - * 42 - * DO NOT USE. 43 - */ 44 - struct drm_lock_data { 45 - struct drm_hw_lock *hw_lock; 46 - struct drm_file *file_priv; 47 - wait_queue_head_t lock_queue; 48 - unsigned long lock_time; 49 - spinlock_t spinlock; 50 - uint32_t kernel_waiters; 51 - uint32_t user_waiters; 52 - int idle_has_lock; 53 - }; 54 36 55 37 /** 56 38 * struct drm_master - drm master structure ··· 127 145 * Protected by &drm_device.mode_config's &drm_mode_config.idr_mutex. 128 146 */ 129 147 struct idr lessee_idr; 130 - /* private: */ 131 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 132 - struct drm_lock_data lock; 133 - #endif 134 148 }; 135 149 136 150 struct drm_master *drm_master_get(struct drm_master *master);
+1 -3
include/drm/drm_bridge.h
··· 194 194 * or &drm_encoder_helper_funcs.dpms hook. 195 195 * 196 196 * The bridge must assume that the display pipe (i.e. clocks and timing 197 - * singals) feeding it is no longer running when this callback is 197 + * signals) feeding it is no longer running when this callback is 198 198 * called. 199 199 * 200 200 * The @post_disable callback is optional. ··· 949 949 return ERR_PTR(-ENODEV); 950 950 } 951 951 #endif 952 - 953 - void drm_bridge_debugfs_init(struct drm_device *dev); 954 952 955 953 #endif
+2 -69
include/drm/drm_device.h
··· 6 6 #include <linux/mutex.h> 7 7 #include <linux/idr.h> 8 8 9 - #include <drm/drm_legacy.h> 10 9 #include <drm/drm_mode_config.h> 11 10 12 11 struct drm_driver; ··· 152 153 * 153 154 * Lock for others (not &drm_minor.master and &drm_file.is_master) 154 155 * 155 - * WARNING: 156 - * Only drivers annotated with DRIVER_LEGACY should be using this. 156 + * TODO: This lock used to be the BKL of the DRM subsystem. Move the 157 + * lock into i915, which is the only remaining user. 157 158 */ 158 159 struct mutex struct_mutex; 159 160 ··· 316 317 * Root directory for debugfs files. 317 318 */ 318 319 struct dentry *debugfs_root; 319 - 320 - /* Everything below here is for legacy driver, never use! */ 321 - /* private: */ 322 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 323 - /* List of devices per driver for stealth attach cleanup */ 324 - struct list_head legacy_dev_list; 325 - 326 - #ifdef __alpha__ 327 - /** @hose: PCI hose, only used on ALPHA platforms. */ 328 - struct pci_controller *hose; 329 - #endif 330 - 331 - /* AGP data */ 332 - struct drm_agp_head *agp; 333 - 334 - /* Context handle management - linked list of context handles */ 335 - struct list_head ctxlist; 336 - 337 - /* Context handle management - mutex for &ctxlist */ 338 - struct mutex ctxlist_mutex; 339 - 340 - /* Context handle management */ 341 - struct idr ctx_idr; 342 - 343 - /* Memory management - linked list of regions */ 344 - struct list_head maplist; 345 - 346 - /* Memory management - user token hash table for maps */ 347 - struct drm_open_hash map_hash; 348 - 349 - /* Context handle management - list of vmas (for debugging) */ 350 - struct list_head vmalist; 351 - 352 - /* Optional pointer for DMA support */ 353 - struct drm_device_dma *dma; 354 - 355 - /* Context swapping flag */ 356 - __volatile__ long context_flag; 357 - 358 - /* Last current context */ 359 - int last_context; 360 - 361 - /* Lock for &buf_use and a few other things. */ 362 - spinlock_t buf_lock; 363 - 364 - /* Usage counter for buffers in use -- cannot alloc */ 365 - int buf_use; 366 - 367 - /* Buffer allocation in progress */ 368 - atomic_t buf_alloc; 369 - 370 - struct { 371 - int context; 372 - struct drm_hw_lock *lock; 373 - } sigdata; 374 - 375 - struct drm_local_map *agp_buffer_map; 376 - unsigned int agp_buffer_token; 377 - 378 - /* Scatter gather memory */ 379 - struct drm_sg_mem *sg; 380 - 381 - /* IRQs */ 382 - bool irq_enabled; 383 - int irq; 384 - #endif 385 320 }; 386 321 387 322 #endif
+9 -19
include/drm/drm_drv.h
··· 110 110 * Driver supports user defined GPU VA bindings for GEM objects. 111 111 */ 112 112 DRIVER_GEM_GPUVA = BIT(8), 113 + /** 114 + * @DRIVER_CURSOR_HOTSPOT: 115 + * 116 + * Driver supports and requires cursor hotspot information in the 117 + * cursor plane (e.g. cursor plane has to actually track the mouse 118 + * cursor and the clients are required to set hotspot in order for 119 + * the cursor planes to work correctly). 120 + */ 121 + DRIVER_CURSOR_HOTSPOT = BIT(9), 113 122 114 123 /* IMPORTANT: Below are all the legacy flags, add new ones above. */ 115 124 ··· 442 433 * some examples. 443 434 */ 444 435 const struct file_operations *fops; 445 - 446 - #ifdef CONFIG_DRM_LEGACY 447 - /* Everything below here is for legacy driver, never use! */ 448 - /* private: */ 449 - 450 - int (*firstopen) (struct drm_device *); 451 - void (*preclose) (struct drm_device *, struct drm_file *file_priv); 452 - int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv); 453 - int (*dma_quiescent) (struct drm_device *); 454 - int (*context_dtor) (struct drm_device *dev, int context); 455 - irqreturn_t (*irq_handler)(int irq, void *arg); 456 - void (*irq_preinstall)(struct drm_device *dev); 457 - int (*irq_postinstall)(struct drm_device *dev); 458 - void (*irq_uninstall)(struct drm_device *dev); 459 - u32 (*get_vblank_counter)(struct drm_device *dev, unsigned int pipe); 460 - int (*enable_vblank)(struct drm_device *dev, unsigned int pipe); 461 - void (*disable_vblank)(struct drm_device *dev, unsigned int pipe); 462 - int dev_priv_size; 463 - #endif 464 436 }; 465 437 466 438 void *__devm_drm_dev_alloc(struct device *parent,
+15 -1
include/drm/drm_encoder.h
··· 60 60 * @late_register: 61 61 * 62 62 * This optional hook can be used to register additional userspace 63 - * interfaces attached to the encoder like debugfs interfaces. 63 + * interfaces attached to the encoder. 64 64 * It is called late in the driver load sequence from drm_dev_register(). 65 65 * Everything added from this callback should be unregistered in 66 66 * the early_unregister callback. ··· 81 81 * before data structures are torndown. 82 82 */ 83 83 void (*early_unregister)(struct drm_encoder *encoder); 84 + 85 + /** 86 + * @debugfs_init: 87 + * 88 + * Allows encoders to create encoder-specific debugfs files. 89 + */ 90 + void (*debugfs_init)(struct drm_encoder *encoder, struct dentry *root); 84 91 }; 85 92 86 93 /** ··· 191 184 192 185 const struct drm_encoder_funcs *funcs; 193 186 const struct drm_encoder_helper_funcs *helper_private; 187 + 188 + /** 189 + * @debugfs_entry: 190 + * 191 + * Debugfs directory for this CRTC. 192 + */ 193 + struct dentry *debugfs_entry; 194 194 }; 195 195 196 196 #define obj_to_encoder(x) container_of(x, struct drm_encoder, base)
+12 -5
include/drm/drm_file.h
··· 227 227 bool is_master; 228 228 229 229 /** 230 + * @supports_virtualized_cursor_plane: 231 + * 232 + * This client is capable of handling the cursor plane with the 233 + * restrictions imposed on it by the virtualized drivers. 234 + * 235 + * This implies that the cursor plane has to behave like a cursor 236 + * i.e. track cursor movement. It also requires setting of the 237 + * hotspot properties by the client on the cursor plane. 238 + */ 239 + bool supports_virtualized_cursor_plane; 240 + 241 + /** 230 242 * @master: 231 243 * 232 244 * Master this node is currently associated with. Protected by struct ··· 386 374 * Per-file buffer caches used by the PRIME buffer sharing code. 387 375 */ 388 376 struct drm_prime_file_private prime; 389 - 390 - /* private: */ 391 - #if IS_ENABLED(CONFIG_DRM_LEGACY) 392 - unsigned long lock_count; /* DRI1 legacy lock count */ 393 - #endif 394 377 }; 395 378 396 379 /**
-12
include/drm/drm_framebuffer.h
··· 189 189 */ 190 190 int flags; 191 191 /** 192 - * @hot_x: X coordinate of the cursor hotspot. Used by the legacy cursor 193 - * IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR 194 - * universal plane. 195 - */ 196 - int hot_x; 197 - /** 198 - * @hot_y: Y coordinate of the cursor hotspot. Used by the legacy cursor 199 - * IOCTL when the driver supports cursor through a DRM_PLANE_TYPE_CURSOR 200 - * universal plane. 201 - */ 202 - int hot_y; 203 - /** 204 192 * @filp_head: Placed on &drm_file.fbs, protected by &drm_file.fbs_lock. 205 193 */ 206 194 struct list_head filp_head;
+4 -21
include/drm/drm_gpuvm.h
··· 544 544 } extra; 545 545 }; 546 546 547 - /** 548 - * drm_gpuvm_prepare_vm() - prepare the GPUVMs common dma-resv 549 - * @gpuvm: the &drm_gpuvm 550 - * @exec: the &drm_exec context 551 - * @num_fences: the amount of &dma_fences to reserve 552 - * 553 - * Calls drm_exec_prepare_obj() for the GPUVMs dummy &drm_gem_object. 554 - * 555 - * Using this function directly, it is the drivers responsibility to call 556 - * drm_exec_init() and drm_exec_fini() accordingly. 557 - * 558 - * Returns: 0 on success, negative error code on failure. 559 - */ 560 - static inline int 561 - drm_gpuvm_prepare_vm(struct drm_gpuvm *gpuvm, 562 - struct drm_exec *exec, 563 - unsigned int num_fences) 564 - { 565 - return drm_exec_prepare_obj(exec, gpuvm->r_obj, num_fences); 566 - } 547 + int drm_gpuvm_prepare_vm(struct drm_gpuvm *gpuvm, 548 + struct drm_exec *exec, 549 + unsigned int num_fences); 567 550 568 551 int drm_gpuvm_prepare_objects(struct drm_gpuvm *gpuvm, 569 552 struct drm_exec *exec, ··· 721 738 return vm_bo; 722 739 } 723 740 724 - void drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo); 741 + bool drm_gpuvm_bo_put(struct drm_gpuvm_bo *vm_bo); 725 742 726 743 struct drm_gpuvm_bo * 727 744 drm_gpuvm_bo_find(struct drm_gpuvm *gpuvm,
-11
include/drm/drm_ioctl.h
··· 110 110 */ 111 111 DRM_ROOT_ONLY = BIT(2), 112 112 /** 113 - * @DRM_UNLOCKED: 114 - * 115 - * Whether &drm_ioctl_desc.func should be called with the DRM BKL held 116 - * or not. Enforced as the default for all modern drivers, hence there 117 - * should never be a need to set this flag. 118 - * 119 - * Do not use anywhere else than for the VBLANK_WAIT IOCTL, which is the 120 - * only legacy IOCTL which needs this. 121 - */ 122 - DRM_UNLOCKED = BIT(4), 123 - /** 124 113 * @DRM_RENDER_ALLOW: 125 114 * 126 115 * This is used for all ioctl needed for rendering only, for drivers
-331
include/drm/drm_legacy.h
··· 1 - #ifndef __DRM_DRM_LEGACY_H__ 2 - #define __DRM_DRM_LEGACY_H__ 3 - /* 4 - * Legacy driver interfaces for the Direct Rendering Manager 5 - * 6 - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. 7 - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. 8 - * Copyright (c) 2009-2010, Code Aurora Forum. 9 - * All rights reserved. 10 - * Copyright © 2014 Intel Corporation 11 - * Daniel Vetter <daniel.vetter@ffwll.ch> 12 - * 13 - * Author: Rickard E. (Rik) Faith <faith@valinux.com> 14 - * Author: Gareth Hughes <gareth@valinux.com> 15 - * 16 - * Permission is hereby granted, free of charge, to any person obtaining a 17 - * copy of this software and associated documentation files (the "Software"), 18 - * to deal in the Software without restriction, including without limitation 19 - * the rights to use, copy, modify, merge, publish, distribute, sublicense, 20 - * and/or sell copies of the Software, and to permit persons to whom the 21 - * Software is furnished to do so, subject to the following conditions: 22 - * 23 - * The above copyright notice and this permission notice (including the next 24 - * paragraph) shall be included in all copies or substantial portions of the 25 - * Software. 26 - * 27 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 28 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 30 - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 31 - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 32 - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 33 - * OTHER DEALINGS IN THE SOFTWARE. 34 - */ 35 - 36 - #include <linux/agp_backend.h> 37 - 38 - #include <drm/drm.h> 39 - #include <drm/drm_auth.h> 40 - 41 - struct drm_device; 42 - struct drm_driver; 43 - struct file; 44 - struct pci_driver; 45 - 46 - /* 47 - * Legacy Support for palateontologic DRM drivers 48 - * 49 - * If you add a new driver and it uses any of these functions or structures, 50 - * you're doing it terribly wrong. 51 - */ 52 - 53 - /* 54 - * Hash-table Support 55 - */ 56 - 57 - struct drm_hash_item { 58 - struct hlist_node head; 59 - unsigned long key; 60 - }; 61 - 62 - struct drm_open_hash { 63 - struct hlist_head *table; 64 - u8 order; 65 - }; 66 - 67 - /** 68 - * DMA buffer. 69 - */ 70 - struct drm_buf { 71 - int idx; /**< Index into master buflist */ 72 - int total; /**< Buffer size */ 73 - int order; /**< log-base-2(total) */ 74 - int used; /**< Amount of buffer in use (for DMA) */ 75 - unsigned long offset; /**< Byte offset (used internally) */ 76 - void *address; /**< Address of buffer */ 77 - unsigned long bus_address; /**< Bus address of buffer */ 78 - struct drm_buf *next; /**< Kernel-only: used for free list */ 79 - __volatile__ int waiting; /**< On kernel DMA queue */ 80 - __volatile__ int pending; /**< On hardware DMA queue */ 81 - struct drm_file *file_priv; /**< Private of holding file descr */ 82 - int context; /**< Kernel queue for this buffer */ 83 - int while_locked; /**< Dispatch this buffer while locked */ 84 - enum { 85 - DRM_LIST_NONE = 0, 86 - DRM_LIST_FREE = 1, 87 - DRM_LIST_WAIT = 2, 88 - DRM_LIST_PEND = 3, 89 - DRM_LIST_PRIO = 4, 90 - DRM_LIST_RECLAIM = 5 91 - } list; /**< Which list we're on */ 92 - 93 - int dev_priv_size; /**< Size of buffer private storage */ 94 - void *dev_private; /**< Per-buffer private storage */ 95 - }; 96 - 97 - typedef struct drm_dma_handle { 98 - dma_addr_t busaddr; 99 - void *vaddr; 100 - size_t size; 101 - } drm_dma_handle_t; 102 - 103 - /** 104 - * Buffer entry. There is one of this for each buffer size order. 105 - */ 106 - struct drm_buf_entry { 107 - int buf_size; /**< size */ 108 - int buf_count; /**< number of buffers */ 109 - struct drm_buf *buflist; /**< buffer list */ 110 - int seg_count; 111 - int page_order; 112 - struct drm_dma_handle **seglist; 113 - 114 - int low_mark; /**< Low water mark */ 115 - int high_mark; /**< High water mark */ 116 - }; 117 - 118 - /** 119 - * DMA data. 120 - */ 121 - struct drm_device_dma { 122 - 123 - struct drm_buf_entry bufs[DRM_MAX_ORDER + 1]; /**< buffers, grouped by their size order */ 124 - int buf_count; /**< total number of buffers */ 125 - struct drm_buf **buflist; /**< Vector of pointers into drm_device_dma::bufs */ 126 - int seg_count; 127 - int page_count; /**< number of pages */ 128 - unsigned long *pagelist; /**< page list */ 129 - unsigned long byte_count; 130 - enum { 131 - _DRM_DMA_USE_AGP = 0x01, 132 - _DRM_DMA_USE_SG = 0x02, 133 - _DRM_DMA_USE_FB = 0x04, 134 - _DRM_DMA_USE_PCI_RO = 0x08 135 - } flags; 136 - 137 - }; 138 - 139 - /** 140 - * Scatter-gather memory. 141 - */ 142 - struct drm_sg_mem { 143 - unsigned long handle; 144 - void *virtual; 145 - int pages; 146 - struct page **pagelist; 147 - dma_addr_t *busaddr; 148 - }; 149 - 150 - /** 151 - * Kernel side of a mapping 152 - */ 153 - struct drm_local_map { 154 - dma_addr_t offset; /**< Requested physical address (0 for SAREA)*/ 155 - unsigned long size; /**< Requested physical size (bytes) */ 156 - enum drm_map_type type; /**< Type of memory to map */ 157 - enum drm_map_flags flags; /**< Flags */ 158 - void *handle; /**< User-space: "Handle" to pass to mmap() */ 159 - /**< Kernel-space: kernel-virtual address */ 160 - int mtrr; /**< MTRR slot used */ 161 - }; 162 - 163 - typedef struct drm_local_map drm_local_map_t; 164 - 165 - /** 166 - * Mappings list 167 - */ 168 - struct drm_map_list { 169 - struct list_head head; /**< list head */ 170 - struct drm_hash_item hash; 171 - struct drm_local_map *map; /**< mapping */ 172 - uint64_t user_token; 173 - struct drm_master *master; 174 - }; 175 - 176 - int drm_legacy_addmap(struct drm_device *d, resource_size_t offset, 177 - unsigned int size, enum drm_map_type type, 178 - enum drm_map_flags flags, struct drm_local_map **map_p); 179 - struct drm_local_map *drm_legacy_findmap(struct drm_device *dev, unsigned int token); 180 - void drm_legacy_rmmap(struct drm_device *d, struct drm_local_map *map); 181 - int drm_legacy_rmmap_locked(struct drm_device *d, struct drm_local_map *map); 182 - struct drm_local_map *drm_legacy_getsarea(struct drm_device *dev); 183 - int drm_legacy_mmap(struct file *filp, struct vm_area_struct *vma); 184 - 185 - int drm_legacy_addbufs_agp(struct drm_device *d, struct drm_buf_desc *req); 186 - int drm_legacy_addbufs_pci(struct drm_device *d, struct drm_buf_desc *req); 187 - 188 - /** 189 - * Test that the hardware lock is held by the caller, returning otherwise. 190 - * 191 - * \param dev DRM device. 192 - * \param filp file pointer of the caller. 193 - */ 194 - #define LOCK_TEST_WITH_RETURN( dev, _file_priv ) \ 195 - do { \ 196 - if (!_DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock) || \ 197 - _file_priv->master->lock.file_priv != _file_priv) { \ 198 - DRM_ERROR( "%s called without lock held, held %d owner %p %p\n",\ 199 - __func__, _DRM_LOCK_IS_HELD(_file_priv->master->lock.hw_lock->lock),\ 200 - _file_priv->master->lock.file_priv, _file_priv); \ 201 - return -EINVAL; \ 202 - } \ 203 - } while (0) 204 - 205 - void drm_legacy_idlelock_take(struct drm_lock_data *lock); 206 - void drm_legacy_idlelock_release(struct drm_lock_data *lock); 207 - 208 - /* drm_irq.c */ 209 - int drm_legacy_irq_uninstall(struct drm_device *dev); 210 - 211 - /* drm_pci.c */ 212 - 213 - #ifdef CONFIG_PCI 214 - 215 - int drm_legacy_pci_init(const struct drm_driver *driver, 216 - struct pci_driver *pdriver); 217 - void drm_legacy_pci_exit(const struct drm_driver *driver, 218 - struct pci_driver *pdriver); 219 - 220 - #else 221 - 222 - static inline struct drm_dma_handle *drm_pci_alloc(struct drm_device *dev, 223 - size_t size, size_t align) 224 - { 225 - return NULL; 226 - } 227 - 228 - static inline void drm_pci_free(struct drm_device *dev, 229 - struct drm_dma_handle *dmah) 230 - { 231 - } 232 - 233 - static inline int drm_legacy_pci_init(const struct drm_driver *driver, 234 - struct pci_driver *pdriver) 235 - { 236 - return -EINVAL; 237 - } 238 - 239 - static inline void drm_legacy_pci_exit(const struct drm_driver *driver, 240 - struct pci_driver *pdriver) 241 - { 242 - } 243 - 244 - #endif 245 - 246 - /* 247 - * AGP Support 248 - */ 249 - 250 - struct drm_agp_head { 251 - struct agp_kern_info agp_info; 252 - struct list_head memory; 253 - unsigned long mode; 254 - struct agp_bridge_data *bridge; 255 - int enabled; 256 - int acquired; 257 - unsigned long base; 258 - int agp_mtrr; 259 - int cant_use_aperture; 260 - unsigned long page_mask; 261 - }; 262 - 263 - #if IS_ENABLED(CONFIG_DRM_LEGACY) && IS_ENABLED(CONFIG_AGP) 264 - struct drm_agp_head *drm_legacy_agp_init(struct drm_device *dev); 265 - int drm_legacy_agp_acquire(struct drm_device *dev); 266 - int drm_legacy_agp_release(struct drm_device *dev); 267 - int drm_legacy_agp_enable(struct drm_device *dev, struct drm_agp_mode mode); 268 - int drm_legacy_agp_info(struct drm_device *dev, struct drm_agp_info *info); 269 - int drm_legacy_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request); 270 - int drm_legacy_agp_free(struct drm_device *dev, struct drm_agp_buffer *request); 271 - int drm_legacy_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request); 272 - int drm_legacy_agp_bind(struct drm_device *dev, struct drm_agp_binding *request); 273 - #else 274 - static inline struct drm_agp_head *drm_legacy_agp_init(struct drm_device *dev) 275 - { 276 - return NULL; 277 - } 278 - 279 - static inline int drm_legacy_agp_acquire(struct drm_device *dev) 280 - { 281 - return -ENODEV; 282 - } 283 - 284 - static inline int drm_legacy_agp_release(struct drm_device *dev) 285 - { 286 - return -ENODEV; 287 - } 288 - 289 - static inline int drm_legacy_agp_enable(struct drm_device *dev, 290 - struct drm_agp_mode mode) 291 - { 292 - return -ENODEV; 293 - } 294 - 295 - static inline int drm_legacy_agp_info(struct drm_device *dev, 296 - struct drm_agp_info *info) 297 - { 298 - return -ENODEV; 299 - } 300 - 301 - static inline int drm_legacy_agp_alloc(struct drm_device *dev, 302 - struct drm_agp_buffer *request) 303 - { 304 - return -ENODEV; 305 - } 306 - 307 - static inline int drm_legacy_agp_free(struct drm_device *dev, 308 - struct drm_agp_buffer *request) 309 - { 310 - return -ENODEV; 311 - } 312 - 313 - static inline int drm_legacy_agp_unbind(struct drm_device *dev, 314 - struct drm_agp_binding *request) 315 - { 316 - return -ENODEV; 317 - } 318 - 319 - static inline int drm_legacy_agp_bind(struct drm_device *dev, 320 - struct drm_agp_binding *request) 321 - { 322 - return -ENODEV; 323 - } 324 - #endif 325 - 326 - /* drm_memory.c */ 327 - void drm_legacy_ioremap(struct drm_local_map *map, struct drm_device *dev); 328 - void drm_legacy_ioremap_wc(struct drm_local_map *map, struct drm_device *dev); 329 - void drm_legacy_ioremapfree(struct drm_local_map *map, struct drm_device *dev); 330 - 331 - #endif /* __DRM_DRM_LEGACY_H__ */
+2
include/drm/drm_mipi_dsi.h
··· 168 168 * struct mipi_dsi_device - DSI peripheral device 169 169 * @host: DSI host for this peripheral 170 170 * @dev: driver model device node for this peripheral 171 + * @attached: the DSI device has been successfully attached 171 172 * @name: DSI peripheral chip type 172 173 * @channel: virtual channel assigned to the peripheral 173 174 * @format: pixel format for video mode ··· 185 184 struct mipi_dsi_device { 186 185 struct mipi_dsi_host *host; 187 186 struct device dev; 187 + bool attached; 188 188 189 189 char name[DSI_DEV_NAME_SIZE]; 190 190 unsigned int channel;
+10
include/drm/drm_modeset_helper_vtables.h
··· 1154 1154 * This operation is optional. 1155 1155 * 1156 1156 * This callback is used by the drm_kms_helper_poll_enable() helpers. 1157 + * 1158 + * This operation does not need to perform any hpd state tracking as 1159 + * the DRM core handles that maintenance and ensures the calls to enable 1160 + * and disable hpd are balanced. 1161 + * 1157 1162 */ 1158 1163 void (*enable_hpd)(struct drm_connector *connector); 1159 1164 ··· 1170 1165 * This operation is optional. 1171 1166 * 1172 1167 * This callback is used by the drm_kms_helper_poll_disable() helpers. 1168 + * 1169 + * This operation does not need to perform any hpd state tracking as 1170 + * the DRM core handles that maintenance and ensures the calls to enable 1171 + * and disable hpd are balanced. 1172 + * 1173 1173 */ 1174 1174 void (*disable_hpd)(struct drm_connector *connector); 1175 1175 };
+24
include/drm/drm_plane.h
··· 116 116 /** @src_h: height of visible portion of plane (in 16.16) */ 117 117 uint32_t src_h, src_w; 118 118 119 + /** @hotspot_x: x offset to mouse cursor hotspot */ 120 + /** @hotspot_y: y offset to mouse cursor hotspot */ 121 + int32_t hotspot_x, hotspot_y; 122 + 119 123 /** 120 124 * @alpha: 121 125 * Opacity of the plane with 0 as completely transparent and 0xffff as ··· 193 189 * drm_plane_get_damage_clips_count() for accessing these. 194 190 */ 195 191 struct drm_property_blob *fb_damage_clips; 192 + 193 + /** 194 + * @ignore_damage_clips: 195 + * 196 + * Set by drivers to indicate the drm_atomic_helper_damage_iter_init() 197 + * helper that the @fb_damage_clips blob property should be ignored. 198 + * 199 + * See :ref:`damage_tracking_properties` for more information. 200 + */ 201 + bool ignore_damage_clips; 196 202 197 203 /** 198 204 * @src: ··· 762 748 * scaling. 763 749 */ 764 750 struct drm_property *scaling_filter_property; 751 + 752 + /** 753 + * @hotspot_x_property: property to set mouse hotspot x offset. 754 + */ 755 + struct drm_property *hotspot_x_property; 756 + 757 + /** 758 + * @hotspot_y_property: property to set mouse hotspot y offset. 759 + */ 760 + struct drm_property *hotspot_y_property; 765 761 }; 766 762 767 763 #define obj_to_plane(x) container_of(x, struct drm_plane, base)
-2
include/drm/drm_plane_helper.h
··· 26 26 27 27 #include <linux/types.h> 28 28 29 - struct drm_atomic_state; 30 29 struct drm_crtc; 31 30 struct drm_framebuffer; 32 31 struct drm_modeset_acquire_ctx; ··· 41 42 int drm_plane_helper_disable_primary(struct drm_plane *plane, 42 43 struct drm_modeset_acquire_ctx *ctx); 43 44 void drm_plane_helper_destroy(struct drm_plane *plane); 44 - int drm_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *state); 45 45 46 46 /** 47 47 * DRM_PLANE_NON_ATOMIC_FUNCS - Default plane functions for non-atomic drivers
+3 -3
include/drm/gpu_scheduler.h
··· 63 63 * to an array, and as such should start at 0. 64 64 */ 65 65 enum drm_sched_priority { 66 - DRM_SCHED_PRIORITY_MIN, 67 - DRM_SCHED_PRIORITY_NORMAL, 68 - DRM_SCHED_PRIORITY_HIGH, 69 66 DRM_SCHED_PRIORITY_KERNEL, 67 + DRM_SCHED_PRIORITY_HIGH, 68 + DRM_SCHED_PRIORITY_NORMAL, 69 + DRM_SCHED_PRIORITY_LOW, 70 70 71 71 DRM_SCHED_PRIORITY_COUNT 72 72 };
+7 -4
include/linux/dma-buf.h
··· 343 343 /** 344 344 * @exp_name: 345 345 * 346 - * Name of the exporter; useful for debugging. See the 347 - * DMA_BUF_SET_NAME IOCTL. 346 + * Name of the exporter; useful for debugging. Must not be NULL 348 347 */ 349 348 const char *exp_name; 350 349 351 350 /** 352 351 * @name: 353 352 * 354 - * Userspace-provided name; useful for accounting and debugging, 355 - * protected by dma_resv_lock() on @resv and @name_lock for read access. 353 + * Userspace-provided name. Default value is NULL. If not NULL, 354 + * length cannot be longer than DMA_BUF_NAME_LEN, including NIL 355 + * char. Useful for accounting and debugging. Read/Write accesses 356 + * are protected by @name_lock 357 + * 358 + * See the IOCTLs DMA_BUF_SET_NAME or DMA_BUF_SET_NAME_A/B 356 359 */ 357 360 const char *name; 358 361
+14 -2
include/linux/fb.h
··· 536 536 size_t count, loff_t *ppos); 537 537 extern ssize_t fb_io_write(struct fb_info *info, const char __user *buf, 538 538 size_t count, loff_t *ppos); 539 + int fb_io_mmap(struct fb_info *info, struct vm_area_struct *vma); 539 540 540 541 #define __FB_DEFAULT_IOMEM_OPS_RDWR \ 541 542 .fb_read = fb_io_read, \ ··· 548 547 .fb_imageblit = cfb_imageblit 549 548 550 549 #define __FB_DEFAULT_IOMEM_OPS_MMAP \ 551 - .fb_mmap = NULL /* default implementation */ 550 + .fb_mmap = fb_io_mmap 552 551 553 552 #define FB_DEFAULT_IOMEM_OPS \ 554 553 __FB_DEFAULT_IOMEM_OPS_RDWR, \ ··· 849 848 } 850 849 #endif 851 850 852 - /* Convenience logging macros */ 851 + /* 852 + * Convenience logging macros 853 + */ 854 + 853 855 #define fb_err(fb_info, fmt, ...) \ 854 856 pr_err("fb%d: " fmt, (fb_info)->node, ##__VA_ARGS__) 855 857 #define fb_notice(info, fmt, ...) \ ··· 863 859 pr_info("fb%d: " fmt, (fb_info)->node, ##__VA_ARGS__) 864 860 #define fb_dbg(fb_info, fmt, ...) \ 865 861 pr_debug("fb%d: " fmt, (fb_info)->node, ##__VA_ARGS__) 862 + 863 + #define fb_warn_once(fb_info, fmt, ...) \ 864 + pr_warn_once("fb%d: " fmt, (fb_info)->node, ##__VA_ARGS__) 865 + 866 + #define fb_WARN_ONCE(fb_info, condition, fmt, ...) \ 867 + WARN_ONCE(condition, "fb%d: " fmt, (fb_info)->node, ##__VA_ARGS__) 868 + #define fb_WARN_ON_ONCE(fb_info, x) \ 869 + fb_WARN_ONCE(fb_info, (x), "%s", "fb_WARN_ON_ONCE(" __stringify(x) ")") 866 870 867 871 #endif /* _LINUX_FB_H */
+51 -1
include/uapi/drm/drm.h
··· 713 713 /** 714 714 * DRM_CAP_ASYNC_PAGE_FLIP 715 715 * 716 - * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC. 716 + * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for legacy 717 + * page-flips. 717 718 */ 718 719 #define DRM_CAP_ASYNC_PAGE_FLIP 0x7 719 720 /** ··· 774 773 * :ref:`drm_sync_objects`. 775 774 */ 776 775 #define DRM_CAP_SYNCOBJ_TIMELINE 0x14 776 + /** 777 + * DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 778 + * 779 + * If set to 1, the driver supports &DRM_MODE_PAGE_FLIP_ASYNC for atomic 780 + * commits. 781 + */ 782 + #define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 0x15 777 783 778 784 /* DRM_IOCTL_GET_CAP ioctl argument type */ 779 785 struct drm_get_cap { ··· 850 842 */ 851 843 #define DRM_CLIENT_CAP_WRITEBACK_CONNECTORS 5 852 844 845 + /** 846 + * DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT 847 + * 848 + * Drivers for para-virtualized hardware (e.g. vmwgfx, qxl, virtio and 849 + * virtualbox) have additional restrictions for cursor planes (thus 850 + * making cursor planes on those drivers not truly universal,) e.g. 851 + * they need cursor planes to act like one would expect from a mouse 852 + * cursor and have correctly set hotspot properties. 853 + * If this client cap is not set the DRM core will hide cursor plane on 854 + * those virtualized drivers because not setting it implies that the 855 + * client is not capable of dealing with those extra restictions. 856 + * Clients which do set cursor hotspot and treat the cursor plane 857 + * like a mouse cursor should set this property. 858 + * The client must enable &DRM_CLIENT_CAP_ATOMIC first. 859 + * 860 + * Setting this property on drivers which do not special case 861 + * cursor planes (i.e. non-virtualized drivers) will return 862 + * EOPNOTSUPP, which can be used by userspace to gauge 863 + * requirements of the hardware/drivers they're running on. 864 + * 865 + * This capability is always supported for atomic-capable virtualized 866 + * drivers starting from kernel version 6.6. 867 + */ 868 + #define DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT 6 869 + 853 870 /* DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ 854 871 struct drm_set_client_cap { 855 872 __u64 capability; ··· 926 893 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) 927 894 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1) 928 895 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point to become available */ 896 + #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE (1 << 3) /* set fence deadline to deadline_nsec */ 929 897 struct drm_syncobj_wait { 930 898 __u64 handles; 931 899 /* absolute timeout */ ··· 935 901 __u32 flags; 936 902 __u32 first_signaled; /* only valid when not waiting all */ 937 903 __u32 pad; 904 + /** 905 + * @deadline_nsec - fence deadline hint 906 + * 907 + * Deadline hint, in absolute CLOCK_MONOTONIC, to set on backing 908 + * fence(s) if the DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE flag is 909 + * set. 910 + */ 911 + __u64 deadline_nsec; 938 912 }; 939 913 940 914 struct drm_syncobj_timeline_wait { ··· 955 913 __u32 flags; 956 914 __u32 first_signaled; /* only valid when not waiting all */ 957 915 __u32 pad; 916 + /** 917 + * @deadline_nsec - fence deadline hint 918 + * 919 + * Deadline hint, in absolute CLOCK_MONOTONIC, to set on backing 920 + * fence(s) if the DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE flag is 921 + * set. 922 + */ 923 + __u64 deadline_nsec; 958 924 }; 959 925 960 926 /**
+9
include/uapi/drm/drm_mode.h
··· 957 957 * Request that the page-flip is performed as soon as possible, ie. with no 958 958 * delay due to waiting for vblank. This may cause tearing to be visible on 959 959 * the screen. 960 + * 961 + * When used with atomic uAPI, the driver will return an error if the hardware 962 + * doesn't support performing an asynchronous page-flip for this update. 963 + * User-space should handle this, e.g. by falling back to a regular page-flip. 964 + * 965 + * Note, some hardware might need to perform one last synchronous page-flip 966 + * before being able to switch to asynchronous page-flips. As an exception, 967 + * the driver will return success even though that first page-flip is not 968 + * asynchronous. 960 969 */ 961 970 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 962 971 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
+4 -6
include/uapi/drm/pvr_drm.h
··· 741 741 */ 742 742 enum drm_pvr_ctx_type { 743 743 /** 744 - * @DRM_PVR_CTX_TYPE_RENDER: Render context. Use &struct 745 - * drm_pvr_ioctl_create_render_context_args for context creation arguments. 744 + * @DRM_PVR_CTX_TYPE_RENDER: Render context. 746 745 */ 747 746 DRM_PVR_CTX_TYPE_RENDER = 0, 748 747 749 748 /** 750 - * @DRM_PVR_CTX_TYPE_COMPUTE: Compute context. Use &struct 751 - * drm_pvr_ioctl_create_compute_context_args for context creation arguments. 749 + * @DRM_PVR_CTX_TYPE_COMPUTE: Compute context. 752 750 */ 753 751 DRM_PVR_CTX_TYPE_COMPUTE, 754 752 755 753 /** 756 - * @DRM_PVR_CTX_TYPE_TRANSFER_FRAG: Transfer context for fragment data masters. Use 757 - * &struct drm_pvr_ioctl_create_transfer_context_args for context creation arguments. 754 + * @DRM_PVR_CTX_TYPE_TRANSFER_FRAG: Transfer context for fragment data 755 + * master. 758 756 */ 759 757 DRM_PVR_CTX_TYPE_TRANSFER_FRAG, 760 758 };
+239 -1
include/uapi/drm/v3d_drm.h
··· 41 41 #define DRM_V3D_PERFMON_CREATE 0x08 42 42 #define DRM_V3D_PERFMON_DESTROY 0x09 43 43 #define DRM_V3D_PERFMON_GET_VALUES 0x0a 44 + #define DRM_V3D_SUBMIT_CPU 0x0b 44 45 45 46 #define DRM_IOCTL_V3D_SUBMIT_CL DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CL, struct drm_v3d_submit_cl) 46 47 #define DRM_IOCTL_V3D_WAIT_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_WAIT_BO, struct drm_v3d_wait_bo) ··· 57 56 struct drm_v3d_perfmon_destroy) 58 57 #define DRM_IOCTL_V3D_PERFMON_GET_VALUES DRM_IOWR(DRM_COMMAND_BASE + DRM_V3D_PERFMON_GET_VALUES, \ 59 58 struct drm_v3d_perfmon_get_values) 59 + #define DRM_IOCTL_V3D_SUBMIT_CPU DRM_IOW(DRM_COMMAND_BASE + DRM_V3D_SUBMIT_CPU, struct drm_v3d_submit_cpu) 60 60 61 61 #define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x01 62 62 #define DRM_V3D_SUBMIT_EXTENSION 0x02 ··· 71 69 struct drm_v3d_extension { 72 70 __u64 next; 73 71 __u32 id; 74 - #define DRM_V3D_EXT_ID_MULTI_SYNC 0x01 72 + #define DRM_V3D_EXT_ID_MULTI_SYNC 0x01 73 + #define DRM_V3D_EXT_ID_CPU_INDIRECT_CSD 0x02 74 + #define DRM_V3D_EXT_ID_CPU_TIMESTAMP_QUERY 0x03 75 + #define DRM_V3D_EXT_ID_CPU_RESET_TIMESTAMP_QUERY 0x04 76 + #define DRM_V3D_EXT_ID_CPU_COPY_TIMESTAMP_QUERY 0x05 77 + #define DRM_V3D_EXT_ID_CPU_RESET_PERFORMANCE_QUERY 0x06 78 + #define DRM_V3D_EXT_ID_CPU_COPY_PERFORMANCE_QUERY 0x07 75 79 __u32 flags; /* mbz */ 76 80 }; 77 81 ··· 101 93 V3D_TFU, 102 94 V3D_CSD, 103 95 V3D_CACHE_CLEAN, 96 + V3D_CPU, 104 97 }; 105 98 106 99 /** ··· 285 276 DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH, 286 277 DRM_V3D_PARAM_SUPPORTS_PERFMON, 287 278 DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT, 279 + DRM_V3D_PARAM_SUPPORTS_CPU_QUEUE, 288 280 }; 289 281 290 282 struct drm_v3d_get_param { ··· 369 359 __u32 flags; 370 360 371 361 __u32 pad; 362 + }; 363 + 364 + /** 365 + * struct drm_v3d_indirect_csd - ioctl extension for the CPU job to create an 366 + * indirect CSD 367 + * 368 + * When an extension of DRM_V3D_EXT_ID_CPU_INDIRECT_CSD id is defined, it 369 + * points to this extension to define a indirect CSD submission. It creates a 370 + * CPU job linked to a CSD job. The CPU job waits for the indirect CSD 371 + * dependencies and, once they are signaled, it updates the CSD job config 372 + * before allowing the CSD job execution. 373 + */ 374 + struct drm_v3d_indirect_csd { 375 + struct drm_v3d_extension base; 376 + 377 + /* Indirect CSD */ 378 + struct drm_v3d_submit_csd submit; 379 + 380 + /* Handle of the indirect BO, that should be also attached to the 381 + * indirect CSD. 382 + */ 383 + __u32 indirect; 384 + 385 + /* Offset within the BO where the workgroup counts are stored */ 386 + __u32 offset; 387 + 388 + /* Workgroups size */ 389 + __u32 wg_size; 390 + 391 + /* Indices of the uniforms with the workgroup dispatch counts 392 + * in the uniform stream. If the uniform rewrite is not needed, 393 + * the offset must be 0xffffffff. 394 + */ 395 + __u32 wg_uniform_offsets[3]; 396 + }; 397 + 398 + /** 399 + * struct drm_v3d_timestamp_query - ioctl extension for the CPU job to calculate 400 + * a timestamp query 401 + * 402 + * When an extension DRM_V3D_EXT_ID_TIMESTAMP_QUERY is defined, it points to 403 + * this extension to define a timestamp query submission. This CPU job will 404 + * calculate the timestamp query and update the query value within the 405 + * timestamp BO. Moreover, it will signal the timestamp syncobj to indicate 406 + * query availability. 407 + */ 408 + struct drm_v3d_timestamp_query { 409 + struct drm_v3d_extension base; 410 + 411 + /* Array of queries' offsets within the timestamp BO for their value */ 412 + __u64 offsets; 413 + 414 + /* Array of timestamp's syncobjs to indicate its availability */ 415 + __u64 syncs; 416 + 417 + /* Number of queries */ 418 + __u32 count; 419 + 420 + /* mbz */ 421 + __u32 pad; 422 + }; 423 + 424 + /** 425 + * struct drm_v3d_reset_timestamp_query - ioctl extension for the CPU job to 426 + * reset timestamp queries 427 + * 428 + * When an extension DRM_V3D_EXT_ID_CPU_RESET_TIMESTAMP_QUERY is defined, it 429 + * points to this extension to define a reset timestamp submission. This CPU 430 + * job will reset the timestamp queries based on value offset of the first 431 + * query. Moreover, it will reset the timestamp syncobj to reset query 432 + * availability. 433 + */ 434 + struct drm_v3d_reset_timestamp_query { 435 + struct drm_v3d_extension base; 436 + 437 + /* Array of timestamp's syncobjs to indicate its availability */ 438 + __u64 syncs; 439 + 440 + /* Offset of the first query within the timestamp BO for its value */ 441 + __u32 offset; 442 + 443 + /* Number of queries */ 444 + __u32 count; 445 + }; 446 + 447 + /** 448 + * struct drm_v3d_copy_timestamp_query - ioctl extension for the CPU job to copy 449 + * query results to a buffer 450 + * 451 + * When an extension DRM_V3D_EXT_ID_CPU_COPY_TIMESTAMP_QUERY is defined, it 452 + * points to this extension to define a copy timestamp query submission. This 453 + * CPU job will copy the timestamp queries results to a BO with the offset 454 + * and stride defined in the extension. 455 + */ 456 + struct drm_v3d_copy_timestamp_query { 457 + struct drm_v3d_extension base; 458 + 459 + /* Define if should write to buffer using 64 or 32 bits */ 460 + __u8 do_64bit; 461 + 462 + /* Define if it can write to buffer even if the query is not available */ 463 + __u8 do_partial; 464 + 465 + /* Define if it should write availability bit to buffer */ 466 + __u8 availability_bit; 467 + 468 + /* mbz */ 469 + __u8 pad; 470 + 471 + /* Offset of the buffer in the BO */ 472 + __u32 offset; 473 + 474 + /* Stride of the buffer in the BO */ 475 + __u32 stride; 476 + 477 + /* Number of queries */ 478 + __u32 count; 479 + 480 + /* Array of queries' offsets within the timestamp BO for their value */ 481 + __u64 offsets; 482 + 483 + /* Array of timestamp's syncobjs to indicate its availability */ 484 + __u64 syncs; 485 + }; 486 + 487 + /** 488 + * struct drm_v3d_reset_performance_query - ioctl extension for the CPU job to 489 + * reset performance queries 490 + * 491 + * When an extension DRM_V3D_EXT_ID_CPU_RESET_PERFORMANCE_QUERY is defined, it 492 + * points to this extension to define a reset performance submission. This CPU 493 + * job will reset the performance queries by resetting the values of the 494 + * performance monitors. Moreover, it will reset the syncobj to reset query 495 + * availability. 496 + */ 497 + struct drm_v3d_reset_performance_query { 498 + struct drm_v3d_extension base; 499 + 500 + /* Array of performance queries's syncobjs to indicate its availability */ 501 + __u64 syncs; 502 + 503 + /* Number of queries */ 504 + __u32 count; 505 + 506 + /* Number of performance monitors */ 507 + __u32 nperfmons; 508 + 509 + /* Array of u64 user-pointers that point to an array of kperfmon_ids */ 510 + __u64 kperfmon_ids; 511 + }; 512 + 513 + /** 514 + * struct drm_v3d_copy_performance_query - ioctl extension for the CPU job to copy 515 + * performance query results to a buffer 516 + * 517 + * When an extension DRM_V3D_EXT_ID_CPU_COPY_PERFORMANCE_QUERY is defined, it 518 + * points to this extension to define a copy performance query submission. This 519 + * CPU job will copy the performance queries results to a BO with the offset 520 + * and stride defined in the extension. 521 + */ 522 + struct drm_v3d_copy_performance_query { 523 + struct drm_v3d_extension base; 524 + 525 + /* Define if should write to buffer using 64 or 32 bits */ 526 + __u8 do_64bit; 527 + 528 + /* Define if it can write to buffer even if the query is not available */ 529 + __u8 do_partial; 530 + 531 + /* Define if it should write availability bit to buffer */ 532 + __u8 availability_bit; 533 + 534 + /* mbz */ 535 + __u8 pad; 536 + 537 + /* Offset of the buffer in the BO */ 538 + __u32 offset; 539 + 540 + /* Stride of the buffer in the BO */ 541 + __u32 stride; 542 + 543 + /* Number of performance monitors */ 544 + __u32 nperfmons; 545 + 546 + /* Number of performance counters related to this query pool */ 547 + __u32 ncounters; 548 + 549 + /* Number of queries */ 550 + __u32 count; 551 + 552 + /* Array of performance queries's syncobjs to indicate its availability */ 553 + __u64 syncs; 554 + 555 + /* Array of u64 user-pointers that point to an array of kperfmon_ids */ 556 + __u64 kperfmon_ids; 557 + }; 558 + 559 + struct drm_v3d_submit_cpu { 560 + /* Pointer to a u32 array of the BOs that are referenced by the job. 561 + * 562 + * For DRM_V3D_EXT_ID_CPU_INDIRECT_CSD, it must contain only one BO, 563 + * that contains the workgroup counts. 564 + * 565 + * For DRM_V3D_EXT_ID_TIMESTAMP_QUERY, it must contain only one BO, 566 + * that will contain the timestamp. 567 + * 568 + * For DRM_V3D_EXT_ID_CPU_RESET_TIMESTAMP_QUERY, it must contain only 569 + * one BO, that contains the timestamp. 570 + * 571 + * For DRM_V3D_EXT_ID_CPU_COPY_TIMESTAMP_QUERY, it must contain two 572 + * BOs. The first is the BO where the timestamp queries will be written 573 + * to. The second is the BO that contains the timestamp. 574 + * 575 + * For DRM_V3D_EXT_ID_CPU_RESET_PERFORMANCE_QUERY, it must contain no 576 + * BOs. 577 + * 578 + * For DRM_V3D_EXT_ID_CPU_COPY_PERFORMANCE_QUERY, it must contain one 579 + * BO, where the performance queries will be written. 580 + */ 581 + __u64 bo_handles; 582 + 583 + /* Number of BO handles passed in (size is that times 4). */ 584 + __u32 bo_handle_count; 585 + 586 + __u32 flags; 587 + 588 + /* Pointer to an array of ioctl extensions*/ 589 + __u64 extensions; 372 590 }; 373 591 374 592 enum {
+22
include/uapi/linux/sync_file.h
··· 76 76 __u64 sync_fence_info; 77 77 }; 78 78 79 + /** 80 + * struct sync_set_deadline - SYNC_IOC_SET_DEADLINE - set a deadline hint on a fence 81 + * @deadline_ns: absolute time of the deadline 82 + * @pad: must be zero 83 + * 84 + * Allows userspace to set a deadline on a fence, see &dma_fence_set_deadline 85 + * 86 + * The timebase for the deadline is CLOCK_MONOTONIC (same as vblank). For 87 + * example 88 + * 89 + * clock_gettime(CLOCK_MONOTONIC, &t); 90 + * deadline_ns = (t.tv_sec * 1000000000L) + t.tv_nsec + ns_until_deadline 91 + */ 92 + struct sync_set_deadline { 93 + __u64 deadline_ns; 94 + /* Not strictly needed for alignment but gives some possibility 95 + * for future extension: 96 + */ 97 + __u64 pad; 98 + }; 99 + 79 100 #define SYNC_IOC_MAGIC '>' 80 101 81 102 /* ··· 108 87 109 88 #define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data) 110 89 #define SYNC_IOC_FILE_INFO _IOWR(SYNC_IOC_MAGIC, 4, struct sync_file_info) 90 + #define SYNC_IOC_SET_DEADLINE _IOW(SYNC_IOC_MAGIC, 5, struct sync_set_deadline) 111 91 112 92 #endif /* _UAPI_LINUX_SYNC_H */