diff --git a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml new file mode 100644 index 000000000000..60585a4fc22b --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml @@ -0,0 +1,95 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright 2019 Analogix Semiconductor, Inc. +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/display/bridge/analogix,anx7625.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Analogix ANX7625 SlimPort (4K Mobile HD Transmitter) + +maintainers: + - Xin Ji + +description: | + The ANX7625 is an ultra-low power 4K Mobile HD Transmitter + designed for portable devices. + +properties: + compatible: + items: + - const: analogix,anx7625 + + reg: + maxItems: 1 + + interrupts: + description: used for interrupt pin B8. + maxItems: 1 + + enable-gpios: + description: used for power on chip control, POWER_EN pin D2. + maxItems: 1 + + reset-gpios: + description: used for reset chip control, RESET_N pin B7. + maxItems: 1 + + ports: + type: object + + properties: + port@0: + type: object + description: + Video port for MIPI DSI input. + + port@1: + type: object + description: + Video port for panel or connector. + + required: + - port@0 + - port@1 + +required: + - compatible + - reg + - ports + +additionalProperties: false + +examples: + - | + #include + + i2c0 { + #address-cells = <1>; + #size-cells = <0>; + + encoder@58 { + compatible = "analogix,anx7625"; + reg = <0x58>; + enable-gpios = <&pio 45 GPIO_ACTIVE_HIGH>; + reset-gpios = <&pio 73 GPIO_ACTIVE_HIGH>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + mipi2dp_bridge_in: port@0 { + reg = <0>; + anx7625_in: endpoint { + remote-endpoint = <&mipi_dsi>; + }; + }; + + mipi2dp_bridge_out: port@1 { + reg = <1>; + anx7625_out: endpoint { + remote-endpoint = <&panel_in>; + }; + }; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml b/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml new file mode 100644 index 000000000000..d2170de6b723 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/novatek,nt36672a.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Novatek NT36672A based DSI display Panels + +maintainers: + - Sumit Semwal + +description: | + The nt36672a IC from Novatek is a generic DSI Panel IC used to drive dsi + panels. + Right now, support is added only for a Tianma FHD+ LCD display panel with a + resolution of 1080x2246. It is a video mode DSI panel. + +allOf: + - $ref: panel-common.yaml# + +properties: + compatible: + items: + - enum: + - tianma,fhd-video + - const: novatek,nt36672a + description: This indicates the panel manufacturer of the panel that is + in turn using the NT36672A panel driver. This compatible string + determines how the NT36672A panel driver is configured for the indicated + panel. The novatek,nt36672a compatible shall always be provided as a fallback. + + reset-gpios: + description: phandle of gpio for reset line - This should be 8mA, gpio + can be configured using mux, pinctrl, pinctrl-names (active high) + + vddio-supply: + description: phandle of the regulator that provides the supply voltage + Power IC supply + + vddpos-supply: + description: phandle of the positive boost supply regulator + + vddneg-supply: + description: phandle of the negative boost supply regulator + + reg: true + port: true + +required: + - compatible + - reg + - vddi0-supply + - vddpos-supply + - vddneg-supply + - reset-gpios + - port + +unevaluatedProperties: false + +examples: + - |+ + #include + + dsi0 { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "tianma,fhd-video", "novatek,nt36672a"; + reg = <0>; + vddi0-supply = <&vreg_l14a_1p88>; + vddpos-supply = <&lab>; + vddneg-supply = <&ibb>; + + reset-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>; + + #address-cells = <1>; + #size-cells = <0>; + port { + tianma_nt36672a_in_0: endpoint { + remote-endpoint = <&dsi0_out>; + }; + }; + }; + }; + +... diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml index c0dd9fa29f1d..a29ab65507f0 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple-dsi.yaml @@ -47,6 +47,8 @@ properties: - panasonic,vvx10f004b00 # Panasonic 10" WUXGA TFT LCD panel - panasonic,vvx10f034n00 + # Shangai Top Display Optoelectronics 7" TL070WSH30 1024x600 TFT LCD panel + - tdo,tl070wsh30 reg: maxItems: 1 @@ -54,6 +56,7 @@ properties: backlight: true enable-gpios: true + reset-gpios: true port: true power-supply: true diff --git a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml index edb53ab0d9eb..f9750b0b6708 100644 --- a/Documentation/devicetree/bindings/display/panel/panel-simple.yaml +++ b/Documentation/devicetree/bindings/display/panel/panel-simple.yaml @@ -282,6 +282,8 @@ properties: - vxt,vl050-8048nt-c01 # Winstar Display Corporation 3.5" QVGA (320x240) TFT LCD panel - winstar,wf35ltiacd + # Yes Optoelectronics YTC700TLAG-05-201C 7" TFT LCD panel + - yes-optoelectronics,ytc700tlag-05-201c backlight: true enable-gpios: true diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml index 4f9185462ed3..4dc30738ee57 100644 --- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml +++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml @@ -55,6 +55,14 @@ properties: - const: vp1 - const: vp2 + assigned-clocks: + minItems: 1 + maxItems: 3 + + assigned-clock-parents: + minItems: 1 + maxItems: 3 + interrupts: maxItems: 1 @@ -62,6 +70,9 @@ properties: maxItems: 1 description: phandle to the associated power domain + dma-coherent: + type: boolean + ports: type: object description: diff --git a/Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml b/Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml index 173730d56334..c9a947d55fa4 100644 --- a/Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml +++ b/Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml @@ -77,6 +77,14 @@ properties: - const: vp3 - const: vp4 + assigned-clocks: + minItems: 1 + maxItems: 5 + + assigned-clock-parents: + minItems: 1 + maxItems: 5 + interrupts: items: - description: common_m DSS Master common @@ -95,6 +103,9 @@ properties: maxItems: 1 description: phandle to the associated power domain + dma-coherent: + type: boolean + ports: type: object description: diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml index 2735be1a8470..12e1419823d4 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml @@ -1053,6 +1053,8 @@ patternProperties: description: Trusted Computing Group "^tcl,.*": description: Toby Churchill Ltd. + "^tdo,.*": + description: Shangai Top Display Optoelectronics Co., Ltd "^technexion,.*": description: TechNexion "^technologic,.*": @@ -1210,6 +1212,8 @@ patternProperties: description: Shenzhen Xunlong Software CO.,Limited "^xylon,.*": description: Xylon + "^yes-optoelectronics,.*": + description: Yes Optoelectronics Co.,Ltd. "^ylm,.*": description: Shenzhen Yangliming Electronic Technology Co., Ltd. "^yna,.*": diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst index 4144b669e80c..d6b2a195dbed 100644 --- a/Documentation/driver-api/dma-buf.rst +++ b/Documentation/driver-api/dma-buf.rst @@ -115,6 +115,15 @@ Kernel Functions and Structures Reference .. kernel-doc:: include/linux/dma-buf.h :internal: +Buffer Mapping Helpers +~~~~~~~~~~~~~~~~~~~~~~ + +.. kernel-doc:: include/linux/dma-buf-map.h + :doc: overview + +.. kernel-doc:: include/linux/dma-buf-map.h + :internal: + Reservation Objects ------------------- diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index 9abee1589c1e..21be6deadc12 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -182,11 +182,11 @@ acquired and release by calling drm_gem_object_get() and drm_gem_object_put() respectively. When the last reference to a GEM object is released the GEM core calls -the :c:type:`struct drm_driver ` gem_free_object_unlocked +the :c:type:`struct drm_gem_object_funcs ` free operation. That operation is mandatory for GEM-enabled drivers and must free the GEM object and all associated resources. -void (\*gem_free_object) (struct drm_gem_object \*obj); Drivers are +void (\*free) (struct drm_gem_object \*obj); Drivers are responsible for freeing all GEM object resources. This includes the resources created by the GEM core, which need to be released with drm_gem_object_release(). diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index b0ea17da8ff6..700637e25ecd 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -149,7 +149,7 @@ have to keep track of that lock and either call ``unreference`` or ``unreference_locked`` depending upon context. Core GEM doesn't have a need for ``struct_mutex`` any more since kernel 4.8, -and there's a ``gem_free_object_unlocked`` callback for any drivers which are +and there's a GEM object ``free`` callback for any drivers which are entirely ``struct_mutex`` free. For drivers that need ``struct_mutex`` it should be replaced with a driver- @@ -289,11 +289,8 @@ struct drm_gem_object_funcs --------------------------- GEM objects can now have a function table instead of having the callbacks on the -DRM driver struct. This is now the preferred way and drivers can be moved over. - -We also need a 2nd version of the CMA define that doesn't require the -vmapping to be present (different hook for prime importing). Plus this needs to -be rolled out to all drivers using their own implementations, too. +DRM driver struct. This is now the preferred way. Callbacks in drivers have been +converted, except for struct drm_driver.gem_prime_mmap. Level: Intermediate @@ -518,9 +515,6 @@ There's a bunch of issues with it: this (together with the drm_minor->drm_device move) would allow us to remove debugfs_init. -- Drop the return code and error checking from all debugfs functions. Greg KH is - working on this already. - Contact: Daniel Vetter Level: Intermediate diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst index 61586fc861bb..13bab1d93bb3 100644 --- a/Documentation/gpu/vkms.rst +++ b/Documentation/gpu/vkms.rst @@ -10,36 +10,24 @@ TODO ==== -CRC API Improvements --------------------- +If you want to do any of the items listed below, please share your interest +with VKMS maintainers. -- Optimize CRC computation ``compute_crc()`` and plane blending ``blend()`` +IGT better support +------------------ -- Use the alpha value to blend vaddr_src with vaddr_dst instead of - overwriting it in ``blend()``. +- Investigate: (1) test cases on kms_plane that are failing due to timeout on + capturing CRC; (2) when running kms_flip test cases in sequence, some + successful individual test cases are failing randomly. -- Add igt test to check cleared alpha value for XRGB plane format. - -- Add igt test to check extreme alpha values i.e. fully opaque and fully - transparent (intermediate values are affected by hw-specific rounding modes). - -Runtime Configuration ---------------------- - -We want to be able to reconfigure vkms instance without having to reload the -module. Use/Test-cases: - -- Hotplug/hotremove connectors on the fly (to be able to test DP MST handling of - compositors). - -- Configure planes/crtcs/connectors (we'd need some code to have more than 1 of - them first). - -- Change output configuration: Plug/unplug screens, change EDID, allow changing - the refresh rate. - -The currently proposed solution is to expose vkms configuration through -configfs. All existing module options should be supported through configfs too. +- VKMS already has support for vblanks simulated via hrtimers, which can be + tested with kms_flip test; in some way, we can say that VKMS already mimics + the real hardware vblank. However, we also have virtual hardware that does + not support vblank interrupt and completes page_flip events right away; in + this case, compositor developers may end up creating a busy loop on virtual + hardware. It would be useful to support Virtual Hardware behavior in VKMS + because this can help compositor developers to test their features in + multiple scenarios. Add Plane Features ------------------ @@ -55,33 +43,49 @@ There's lots of plane features we could add support for: - Additional buffer formats, especially YUV formats for video like NV12. Low/high bpp RGB formats would also be interesting. -- Async updates (currently only possible on cursor plane using the legacy cursor - api). +- Async updates (currently only possible on cursor plane using the legacy + cursor api). -For all of these, we also want to review the igt test coverage and make sure all -relevant igt testcases work on vkms. - -Writeback support ------------------ - -Currently vkms only computes a CRC for each frame. Once we have additional plane -features, we could write back the entire composited frame, and expose it as: - -- Writeback connector. This is useful for testing compositors if you don't have - hardware with writeback support. - -- As a v4l device. This is useful for debugging compositors on special vkms - configurations, so that developers see what's really going on. +For all of these, we also want to review the igt test coverage and make sure +all relevant igt testcases work on vkms. Prime Buffer Sharing -------------------- -We already have vgem, which is a gem driver for testing rendering, similar to -how vkms is for testing the modeset side. Adding buffer sharing support to vkms -allows us to test them together, to test synchronization and lots of other -features. Also, this allows compositors to test whether they work correctly on -SoC chips, where the display and rendering is very often split between 2 -drivers. +- Syzbot report - WARNING in vkms_gem_free_object: + https://syzkaller.appspot.com/bug?extid=e7ad70d406e74d8fc9d0 + +Runtime Configuration +--------------------- + +We want to be able to reconfigure vkms instance without having to reload the +module. Use/Test-cases: + +- Hotplug/hotremove connectors on the fly (to be able to test DP MST handling + of compositors). + +- Configure planes/crtcs/connectors (we'd need some code to have more than 1 of + them first). + +- Change output configuration: Plug/unplug screens, change EDID, allow changing + the refresh rate. + +The currently proposed solution is to expose vkms configuration through +configfs. All existing module options should be supported through configfs +too. + +Writeback support +----------------- + +- The writeback and CRC capture operations share the use of composer_enabled + boolean to ensure vblanks. Probably, when these operations work together, + composer_enabled needs to refcounting the composer state to proper work. + +- Add support for cloned writeback outputs and related test cases using a + cloned output in the IGT kms_writeback. + +- As a v4l device. This is useful for debugging compositors on special vkms + configurations, so that developers see what's really going on. Output Features --------------- @@ -93,7 +97,10 @@ Output Features - Add support for link status, so that compositors can validate their runtime fallbacks when e.g. a Display Port link goes bad. -- All the hotplug handling describe under "Runtime Configuration". +CRC API Improvements +-------------------- + +- Optimize CRC computation ``compute_crc()`` and plane blending ``blend()`` Atomic Check using eBPF ----------------------- diff --git a/MAINTAINERS b/MAINTAINERS index b516bb34a8d5..71e29dc0ab9d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5576,6 +5576,13 @@ T: git git://anongit.freedesktop.org/drm/drm-misc F: Documentation/devicetree/bindings/display/panel/novatek,nt35510.yaml F: drivers/gpu/drm/panel/panel-novatek-nt35510.c +DRM DRIVER FOR NOVATEK NT36672A PANELS +M: Sumit Semwal +S: Maintained +T: git git://anongit.freedesktop.org/drm/drm-misc +F: Documentation/devicetree/bindings/display/panel/novatek,nt36672a.yaml +F: drivers/gpu/drm/panel/panel-novatek-nt36672a.c + DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS M: Ben Skeggs L: dri-devel@lists.freedesktop.org @@ -5955,6 +5962,7 @@ F: include/uapi/drm/v3d_drm.h DRM DRIVERS FOR VC4 M: Eric Anholt +M: Maxime Ripard S: Supported T: git git://github.com/anholt/linux T: git git://anongit.freedesktop.org/drm/drm-misc @@ -6911,10 +6919,9 @@ F: drivers/net/wan/dlci.c F: drivers/net/wan/sdla.c FRAMEBUFFER LAYER -M: Bartlomiej Zolnierkiewicz L: dri-devel@lists.freedesktop.org L: linux-fbdev@vger.kernel.org -S: Maintained +S: Orphan Q: http://patchwork.kernel.org/project/linux-fbdev/list/ T: git git://anongit.freedesktop.org/drm/drm-misc F: Documentation/fb/ diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 844967f98866..556f62e8b196 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -851,6 +851,9 @@ EXPORT_SYMBOL_GPL(dma_buf_unpin); * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR * on error. May return -EINTR if it is interrupted by a signal. * + * On success, the DMA addresses and lengths in the returned scatterlist are + * PAGE_SIZE aligned. + * * A mapping must be unmapped by using dma_buf_unmap_attachment(). Note that * the underlying backing storage is pinned for as long as a mapping exists, * therefore users/importers should not hold onto a mapping for undue amounts of @@ -904,6 +907,24 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, attach->dir = direction; } +#ifdef CONFIG_DMA_API_DEBUG + { + struct scatterlist *sg; + u64 addr; + int len; + int i; + + for_each_sgtable_dma_sg(sg_table, sg, i) { + addr = sg_dma_address(sg); + len = sg_dma_len(sg); + if (!PAGE_ALIGNED(addr) || !PAGE_ALIGNED(len)) { + pr_debug("%s: addr %llx or len %x is not page aligned!\n", + __func__, addr, len); + } + } + } +#endif /* CONFIG_DMA_API_DEBUG */ + return sg_table; } EXPORT_SYMBOL_GPL(dma_buf_map_attachment); @@ -1188,68 +1209,72 @@ EXPORT_SYMBOL_GPL(dma_buf_mmap); * dma_buf_vmap - Create virtual mapping for the buffer object into kernel * address space. Same restrictions as for vmap and friends apply. * @dmabuf: [in] buffer to vmap + * @map: [out] returns the vmap pointer * * This call may fail due to lack of virtual mapping address space. * These calls are optional in drivers. The intended use for them * is for mapping objects linear in kernel space for high use objects. * Please attempt to use kmap/kunmap before thinking about these interfaces. * - * Returns NULL on error. + * Returns 0 on success, or a negative errno code otherwise. */ -void *dma_buf_vmap(struct dma_buf *dmabuf) +int dma_buf_vmap(struct dma_buf *dmabuf, struct dma_buf_map *map) { - void *ptr; + struct dma_buf_map ptr; + int ret = 0; + + dma_buf_map_clear(map); if (WARN_ON(!dmabuf)) - return NULL; + return -EINVAL; if (!dmabuf->ops->vmap) - return NULL; + return -EINVAL; mutex_lock(&dmabuf->lock); if (dmabuf->vmapping_counter) { dmabuf->vmapping_counter++; - BUG_ON(!dmabuf->vmap_ptr); - ptr = dmabuf->vmap_ptr; + BUG_ON(dma_buf_map_is_null(&dmabuf->vmap_ptr)); + *map = dmabuf->vmap_ptr; goto out_unlock; } - BUG_ON(dmabuf->vmap_ptr); + BUG_ON(dma_buf_map_is_set(&dmabuf->vmap_ptr)); - ptr = dmabuf->ops->vmap(dmabuf); - if (WARN_ON_ONCE(IS_ERR(ptr))) - ptr = NULL; - if (!ptr) + ret = dmabuf->ops->vmap(dmabuf, &ptr); + if (WARN_ON_ONCE(ret)) goto out_unlock; dmabuf->vmap_ptr = ptr; dmabuf->vmapping_counter = 1; + *map = dmabuf->vmap_ptr; + out_unlock: mutex_unlock(&dmabuf->lock); - return ptr; + return ret; } EXPORT_SYMBOL_GPL(dma_buf_vmap); /** * dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap. * @dmabuf: [in] buffer to vunmap - * @vaddr: [in] vmap to vunmap + * @map: [in] vmap pointer to vunmap */ -void dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) +void dma_buf_vunmap(struct dma_buf *dmabuf, struct dma_buf_map *map) { if (WARN_ON(!dmabuf)) return; - BUG_ON(!dmabuf->vmap_ptr); + BUG_ON(dma_buf_map_is_null(&dmabuf->vmap_ptr)); BUG_ON(dmabuf->vmapping_counter == 0); - BUG_ON(dmabuf->vmap_ptr != vaddr); + BUG_ON(!dma_buf_map_is_equal(&dmabuf->vmap_ptr, map)); mutex_lock(&dmabuf->lock); if (--dmabuf->vmapping_counter == 0) { if (dmabuf->ops->vunmap) - dmabuf->ops->vunmap(dmabuf, vaddr); - dmabuf->vmap_ptr = NULL; + dmabuf->ops->vunmap(dmabuf, map); + dma_buf_map_clear(&dmabuf->vmap_ptr); } mutex_unlock(&dmabuf->lock); } diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index 1c8f2581cb09..bb5a42b10c29 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -63,7 +63,7 @@ static struct dma_resv_list *dma_resv_list_alloc(unsigned int shared_max) { struct dma_resv_list *list; - list = kmalloc(offsetof(typeof(*list), shared[shared_max]), GFP_KERNEL); + list = kmalloc(struct_size(list, shared, shared_max), GFP_KERNEL); if (!list) return NULL; diff --git a/drivers/dma-buf/heaps/heap-helpers.c b/drivers/dma-buf/heaps/heap-helpers.c index d0696cf937af..fcf4ce3e2cbb 100644 --- a/drivers/dma-buf/heaps/heap-helpers.c +++ b/drivers/dma-buf/heaps/heap-helpers.c @@ -235,7 +235,7 @@ static int dma_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, return 0; } -static void *dma_heap_dma_buf_vmap(struct dma_buf *dmabuf) +static int dma_heap_dma_buf_vmap(struct dma_buf *dmabuf, struct dma_buf_map *map) { struct heap_helper_buffer *buffer = dmabuf->priv; void *vaddr; @@ -244,10 +244,14 @@ static void *dma_heap_dma_buf_vmap(struct dma_buf *dmabuf) vaddr = dma_heap_buffer_vmap_get(buffer); mutex_unlock(&buffer->lock); - return vaddr; + if (!vaddr) + return -ENOMEM; + dma_buf_map_set_vaddr(map, vaddr); + + return 0; } -static void dma_heap_dma_buf_vunmap(struct dma_buf *dmabuf, void *vaddr) +static void dma_heap_dma_buf_vunmap(struct dma_buf *dmabuf, struct dma_buf_map *map) { struct heap_helper_buffer *buffer = dmabuf->priv; diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 147d61b9674e..32257189e09b 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -287,6 +287,7 @@ config DRM_VKMS tristate "Virtual KMS (EXPERIMENTAL)" depends on DRM select DRM_KMS_HELPER + select DRM_GEM_SHMEM_HELPER select CRC32 default n help diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 5da487b64a66..054a1c2d5054 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1479,7 +1479,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( } } - if (!amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) && !bo->pin_count) + if (!amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) && !bo->tbo.pin_count) amdgpu_bo_fence(bo, &avm->process_info->eviction_fence->base, true); @@ -1558,7 +1558,8 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( * required. */ if (mem->mapped_to_gpu_memory == 0 && - !amdgpu_ttm_tt_get_usermm(mem->bo->tbo.ttm) && !mem->bo->pin_count) + !amdgpu_ttm_tt_get_usermm(mem->bo->tbo.ttm) && + !mem->bo->tbo.pin_count) amdgpu_amdkfd_remove_eviction_fence(mem->bo, process_info->eviction_fence); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 12598a4b5c78..d50b63a93d37 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -410,7 +410,7 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p, uint32_t domain; int r; - if (bo->pin_count) + if (bo->tbo.pin_count) return 0; /* Don't move this buffer if we have depleted our allowance diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 2d125b8b15ee..065937482239 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1319,6 +1319,7 @@ static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data) struct drm_info_node *node = (struct drm_info_node *)m->private; struct drm_device *dev = node->minor->dev; struct amdgpu_device *adev = drm_to_adev(dev); + struct ttm_resource_manager *man; int r; r = pm_runtime_get_sync(dev->dev); @@ -1327,7 +1328,9 @@ static int amdgpu_debugfs_evict_gtt(struct seq_file *m, void *data) return r; } - seq_printf(m, "(%d)\n", ttm_bo_evict_mm(&adev->mman.bdev, TTM_PL_TT)); + man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); + r = ttm_resource_manager_evict_all(&adev->mman.bdev, man); + seq_printf(m, "(%d)\n", r); pm_runtime_mark_last_busy(dev->dev); pm_runtime_put_autosuspend(dev->dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 7cc7af2a6822..b25faaee6f0e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -132,10 +132,7 @@ static void amdgpu_display_unpin_work_func(struct work_struct *__work) /* unpin of the old buffer */ r = amdgpu_bo_reserve(work->old_abo, true); if (likely(r == 0)) { - r = amdgpu_bo_unpin(work->old_abo); - if (unlikely(r != 0)) { - DRM_ERROR("failed to unpin buffer after flip\n"); - } + amdgpu_bo_unpin(work->old_abo); amdgpu_bo_unreserve(work->old_abo); } else DRM_ERROR("failed to reserve buffer after flip\n"); @@ -249,8 +246,7 @@ pflip_cleanup: } unpin: if (!adev->enable_virtual_display) - if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) - DRM_ERROR("failed to unpin new abo in error path\n"); + amdgpu_bo_unpin(new_abo); unreserve: amdgpu_bo_unreserve(new_abo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index 957934926b24..5b465ab774d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -281,7 +281,7 @@ static struct sg_table *amdgpu_dma_buf_map(struct dma_buf_attachment *attach, struct sg_table *sgt; long r; - if (!bo->pin_count) { + if (!bo->tbo.pin_count) { /* move buffer into GTT or VRAM */ struct ttm_operation_ctx ctx = { false, false }; unsigned domains = AMDGPU_GEM_DOMAIN_GTT; @@ -390,7 +390,8 @@ static int amdgpu_dma_buf_begin_cpu_access(struct dma_buf *dma_buf, if (unlikely(ret != 0)) return ret; - if (!bo->pin_count && (bo->allowed_domains & AMDGPU_GEM_DOMAIN_GTT)) { + if (!bo->tbo.pin_count && + (bo->allowed_domains & AMDGPU_GEM_DOMAIN_GTT)) { amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_GTT); ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 42d9748921f5..8b30915aa972 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1520,19 +1520,13 @@ static struct drm_driver kms_driver = { .lastclose = amdgpu_driver_lastclose_kms, .irq_handler = amdgpu_irq_handler, .ioctls = amdgpu_ioctls_kms, - .gem_free_object_unlocked = amdgpu_gem_object_free, - .gem_open_object = amdgpu_gem_object_open, - .gem_close_object = amdgpu_gem_object_close, .dumb_create = amdgpu_mode_dumb_create, .dumb_map_offset = amdgpu_mode_dumb_mmap, .fops = &amdgpu_driver_kms_fops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = amdgpu_gem_prime_export, .gem_prime_import = amdgpu_gem_prime_import, - .gem_prime_vmap = amdgpu_gem_prime_vmap, - .gem_prime_vunmap = amdgpu_gem_prime_vunmap, .gem_prime_mmap = amdgpu_gem_prime_mmap, .name = DRIVER_NAME, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 7e8265da9f25..8ea6fc745769 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -36,9 +36,12 @@ #include "amdgpu.h" #include "amdgpu_display.h" +#include "amdgpu_dma_buf.h" #include "amdgpu_xgmi.h" -void amdgpu_gem_object_free(struct drm_gem_object *gobj) +static const struct drm_gem_object_funcs amdgpu_gem_object_funcs; + +static void amdgpu_gem_object_free(struct drm_gem_object *gobj) { struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj); @@ -87,6 +90,7 @@ retry: return r; } *obj = &bo->tbo.base; + (*obj)->funcs = &amdgpu_gem_object_funcs; return 0; } @@ -119,8 +123,8 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev) * Call from drm_gem_handle_create which appear in both new and open ioctl * case. */ -int amdgpu_gem_object_open(struct drm_gem_object *obj, - struct drm_file *file_priv) +static int amdgpu_gem_object_open(struct drm_gem_object *obj, + struct drm_file *file_priv) { struct amdgpu_bo *abo = gem_to_amdgpu_bo(obj); struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); @@ -152,8 +156,8 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, return 0; } -void amdgpu_gem_object_close(struct drm_gem_object *obj, - struct drm_file *file_priv) +static void amdgpu_gem_object_close(struct drm_gem_object *obj, + struct drm_file *file_priv) { struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); @@ -211,6 +215,15 @@ out_unlock: ttm_eu_backoff_reservation(&ticket, &list); } +static const struct drm_gem_object_funcs amdgpu_gem_object_funcs = { + .free = amdgpu_gem_object_free, + .open = amdgpu_gem_object_open, + .close = amdgpu_gem_object_close, + .export = amdgpu_gem_prime_export, + .vmap = amdgpu_gem_prime_vmap, + .vunmap = amdgpu_gem_prime_vunmap, +}; + /* * GEM ioctls. */ @@ -870,7 +883,7 @@ static int amdgpu_debugfs_gem_bo_info(int id, void *ptr, void *data) seq_printf(m, "\t0x%08x: %12ld byte %s", id, amdgpu_bo_size(bo), placement); - pin_count = READ_ONCE(bo->pin_count); + pin_count = READ_ONCE(bo->tbo.pin_count); if (pin_count) seq_printf(m, " pin count %d", pin_count); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h index e0f025dd1b14..637bf51dbf06 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h @@ -33,11 +33,6 @@ #define AMDGPU_GEM_DOMAIN_MAX 0x3 #define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, tbo.base) -void amdgpu_gem_object_free(struct drm_gem_object *obj); -int amdgpu_gem_object_open(struct drm_gem_object *obj, - struct drm_file *file_priv); -void amdgpu_gem_object_close(struct drm_gem_object *obj, - struct drm_file *file_priv); unsigned long amdgpu_gem_timeout(uint64_t timeout_ns); /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 36604d751d62..cc86f431a3d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -45,12 +45,10 @@ void amdgpu_gmc_get_pde_for_bo(struct amdgpu_bo *bo, int level, uint64_t *addr, uint64_t *flags) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - struct ttm_dma_tt *ttm; switch (bo->tbo.mem.mem_type) { case TTM_PL_TT: - ttm = container_of(bo->tbo.ttm, struct ttm_dma_tt, ttm); - *addr = ttm->dma_address[0]; + *addr = bo->tbo.ttm->dma_address[0]; break; case TTM_PL_VRAM: *addr = amdgpu_bo_gpu_offset(bo); @@ -122,16 +120,14 @@ int amdgpu_gmc_set_pte_pde(struct amdgpu_device *adev, void *cpu_pt_addr, uint64_t amdgpu_gmc_agp_addr(struct ttm_buffer_object *bo) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); - struct ttm_dma_tt *ttm; - if (bo->num_pages != 1 || bo->ttm->caching_state == tt_cached) + if (bo->num_pages != 1 || bo->ttm->caching == ttm_cached) return AMDGPU_BO_INVALID_OFFSET; - ttm = container_of(bo->ttm, struct ttm_dma_tt, ttm); - if (ttm->dma_address[0] + PAGE_SIZE >= adev->gmc.agp_size) + if (bo->ttm->dma_address[0] + PAGE_SIZE >= adev->gmc.agp_size) return AMDGPU_BO_INVALID_OFFSET; - return adev->gmc.agp_start + ttm->dma_address[0]; + return adev->gmc.agp_start + bo->ttm->dma_address[0]; } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index f203e4a6a3f2..1721739def84 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -136,7 +136,7 @@ void amdgpu_gtt_mgr_fini(struct amdgpu_device *adev) ttm_resource_manager_set_used(man, false); - ret = ttm_resource_manager_force_list_clean(&adev->mman.bdev, man); + ret = ttm_resource_manager_evict_all(&adev->mman.bdev, man); if (ret) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index ac043baac05d..1aa516429c80 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -78,7 +78,7 @@ static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo) struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo); - if (bo->pin_count > 0) + if (bo->tbo.pin_count > 0) amdgpu_bo_subtract_pin_size(bo); amdgpu_bo_kunmap(bo); @@ -137,7 +137,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) places[c].fpfn = 0; places[c].lpfn = 0; places[c].mem_type = TTM_PL_VRAM; - places[c].flags = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED; + places[c].flags = 0; if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) places[c].lpfn = visible_pfn; @@ -154,11 +154,6 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) places[c].lpfn = 0; places[c].mem_type = TTM_PL_TT; places[c].flags = 0; - if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) - places[c].flags |= TTM_PL_FLAG_WC | - TTM_PL_FLAG_UNCACHED; - else - places[c].flags |= TTM_PL_FLAG_CACHED; c++; } @@ -167,11 +162,6 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) places[c].lpfn = 0; places[c].mem_type = TTM_PL_SYSTEM; places[c].flags = 0; - if (flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) - places[c].flags |= TTM_PL_FLAG_WC | - TTM_PL_FLAG_UNCACHED; - else - places[c].flags |= TTM_PL_FLAG_CACHED; c++; } @@ -179,7 +169,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) places[c].fpfn = 0; places[c].lpfn = 0; places[c].mem_type = AMDGPU_PL_GDS; - places[c].flags = TTM_PL_FLAG_UNCACHED; + places[c].flags = 0; c++; } @@ -187,7 +177,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) places[c].fpfn = 0; places[c].lpfn = 0; places[c].mem_type = AMDGPU_PL_GWS; - places[c].flags = TTM_PL_FLAG_UNCACHED; + places[c].flags = 0; c++; } @@ -195,7 +185,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) places[c].fpfn = 0; places[c].lpfn = 0; places[c].mem_type = AMDGPU_PL_OA; - places[c].flags = TTM_PL_FLAG_UNCACHED; + places[c].flags = 0; c++; } @@ -203,7 +193,7 @@ void amdgpu_bo_placement_from_domain(struct amdgpu_bo *abo, u32 domain) places[c].fpfn = 0; places[c].lpfn = 0; places[c].mem_type = TTM_PL_SYSTEM; - places[c].flags = TTM_PL_MASK_CACHING; + places[c].flags = 0; c++; } @@ -721,7 +711,7 @@ int amdgpu_bo_validate(struct amdgpu_bo *bo) uint32_t domain; int r; - if (bo->pin_count) + if (bo->tbo.pin_count) return 0; domain = bo->preferred_domains; @@ -918,13 +908,13 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, */ domain = amdgpu_bo_get_preferred_pin_domain(adev, domain); - if (bo->pin_count) { + if (bo->tbo.pin_count) { uint32_t mem_type = bo->tbo.mem.mem_type; if (!(domain & amdgpu_mem_type_to_domain(mem_type))) return -EINVAL; - bo->pin_count++; + ttm_bo_pin(&bo->tbo); if (max_offset != 0) { u64 domain_start = amdgpu_ttm_domain_start(adev, @@ -955,7 +945,6 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, if (!bo->placements[i].lpfn || (lpfn && lpfn < bo->placements[i].lpfn)) bo->placements[i].lpfn = lpfn; - bo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; } r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); @@ -964,7 +953,7 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, goto error; } - bo->pin_count = 1; + ttm_bo_pin(&bo->tbo); domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type); if (domain == AMDGPU_GEM_DOMAIN_VRAM) { @@ -1006,34 +995,16 @@ int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain) * Returns: * 0 for success or a negative error code on failure. */ -int amdgpu_bo_unpin(struct amdgpu_bo *bo) +void amdgpu_bo_unpin(struct amdgpu_bo *bo) { - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); - struct ttm_operation_ctx ctx = { false, false }; - int r, i; - - if (WARN_ON_ONCE(!bo->pin_count)) { - dev_warn(adev->dev, "%p unpin not necessary\n", bo); - return 0; - } - bo->pin_count--; - if (bo->pin_count) - return 0; + ttm_bo_unpin(&bo->tbo); + if (bo->tbo.pin_count) + return; amdgpu_bo_subtract_pin_size(bo); if (bo->tbo.base.import_attach) dma_buf_unpin(bo->tbo.base.import_attach); - - for (i = 0; i < bo->placement.num_placement; i++) { - bo->placements[i].lpfn = 0; - bo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; - } - r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); - if (unlikely(r)) - dev_err(adev->dev, "%p validate failed for unpin\n", bo); - - return r; } /** @@ -1048,6 +1019,8 @@ int amdgpu_bo_unpin(struct amdgpu_bo *bo) */ int amdgpu_bo_evict_vram(struct amdgpu_device *adev) { + struct ttm_resource_manager *man; + /* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */ #ifndef CONFIG_HIBERNATION if (adev->flags & AMD_IS_APU) { @@ -1055,7 +1028,9 @@ int amdgpu_bo_evict_vram(struct amdgpu_device *adev) return 0; } #endif - return ttm_bo_evict_mm(&adev->mman.bdev, TTM_PL_VRAM); + + man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + return ttm_resource_manager_evict_all(&adev->mman.bdev, man); } static const char *amdgpu_vram_names[] = { @@ -1360,19 +1335,14 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo) * Returns: * 0 for success or a negative error code on failure. */ -int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) +vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); struct ttm_operation_ctx ctx = { false, false }; - struct amdgpu_bo *abo; + struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); unsigned long offset, size; int r; - if (!amdgpu_bo_is_amdgpu_bo(bo)) - return 0; - - abo = ttm_to_amdgpu_bo(bo); - /* Remember that this BO was accessed by the CPU */ abo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; @@ -1385,8 +1355,8 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) return 0; /* Can't move a pinned BO to visible VRAM */ - if (abo->pin_count > 0) - return -EINVAL; + if (abo->tbo.pin_count > 0) + return VM_FAULT_SIGBUS; /* hurrah the memory is not visible ! */ atomic64_inc(&adev->num_vram_cpu_page_faults); @@ -1398,15 +1368,18 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) abo->placement.busy_placement = &abo->placements[1]; r = ttm_bo_validate(bo, &abo->placement, &ctx); - if (unlikely(r != 0)) - return r; + if (unlikely(r == -EBUSY || r == -ERESTARTSYS)) + return VM_FAULT_NOPAGE; + else if (unlikely(r)) + return VM_FAULT_SIGBUS; offset = bo->mem.start << PAGE_SHIFT; /* this should never happen */ if (bo->mem.mem_type == TTM_PL_VRAM && (offset + size) > adev->gmc.visible_vram_size) - return -EINVAL; + return VM_FAULT_SIGBUS; + ttm_bo_move_to_lru_tail_unlocked(bo); return 0; } @@ -1489,7 +1462,7 @@ u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo) { WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM); WARN_ON_ONCE(!dma_resv_is_locked(bo->tbo.base.resv) && - !bo->pin_count && bo->tbo.type != ttm_bo_type_kernel); + !bo->tbo.pin_count && bo->tbo.type != ttm_bo_type_kernel); WARN_ON_ONCE(bo->tbo.mem.start == AMDGPU_BO_INVALID_OFFSET); WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_VRAM && !(bo->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 5ddb6cf96030..132e5f955180 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -89,7 +89,6 @@ struct amdgpu_bo { struct ttm_buffer_object tbo; struct ttm_bo_kmap_obj kmap; u64 flags; - unsigned pin_count; u64 tiling_flags; u64 metadata_flags; void *metadata; @@ -267,7 +266,7 @@ void amdgpu_bo_unref(struct amdgpu_bo **bo); int amdgpu_bo_pin(struct amdgpu_bo *bo, u32 domain); int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain, u64 min_offset, u64 max_offset); -int amdgpu_bo_unpin(struct amdgpu_bo *bo); +void amdgpu_bo_unpin(struct amdgpu_bo *bo); int amdgpu_bo_evict_vram(struct amdgpu_device *adev); int amdgpu_bo_init(struct amdgpu_device *adev); int amdgpu_bo_late_init(struct amdgpu_device *adev); @@ -285,7 +284,7 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, bool evict, struct ttm_resource *new_mem); void amdgpu_bo_release_notify(struct ttm_buffer_object *bo); -int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); +vm_fault_t amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo); void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, bool shared); int amdgpu_bo_sync_wait_resv(struct amdgpu_device *adev, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 8039d2399584..ddb1c8e9eea4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -66,6 +66,8 @@ static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev, struct ttm_tt *ttm, struct ttm_resource *bo_mem); +static void amdgpu_ttm_backend_unbind(struct ttm_bo_device *bdev, + struct ttm_tt *ttm); static int amdgpu_ttm_init_on_chip(struct amdgpu_device *adev, unsigned int type, @@ -92,7 +94,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, .fpfn = 0, .lpfn = 0, .mem_type = TTM_PL_SYSTEM, - .flags = TTM_PL_MASK_CACHING + .flags = 0 }; /* Don't handle scatter gather BOs */ @@ -292,11 +294,9 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo, cpu_addr = &job->ibs[0].ptr[num_dw]; if (mem->mem_type == TTM_PL_TT) { - struct ttm_dma_tt *dma; dma_addr_t *dma_address; - dma = container_of(bo->ttm, struct ttm_dma_tt, ttm); - dma_address = &dma->dma_address[offset >> PAGE_SHIFT]; + dma_address = &bo->ttm->dma_address[offset >> PAGE_SHIFT]; r = amdgpu_gart_map(adev, 0, num_pages, dma_address, flags, cpu_addr); if (r) @@ -538,19 +538,13 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, placements.fpfn = 0; placements.lpfn = 0; placements.mem_type = TTM_PL_TT; - placements.flags = TTM_PL_MASK_CACHING; + placements.flags = 0; r = ttm_bo_mem_space(bo, &placement, &tmp_mem, ctx); if (unlikely(r)) { pr_err("Failed to find GTT space for blit from VRAM\n"); return r; } - /* set caching flags */ - r = ttm_tt_set_placement_caching(bo->ttm, tmp_mem.placement); - if (unlikely(r)) { - goto out_cleanup; - } - r = ttm_tt_populate(bo->bdev, bo->ttm, ctx); if (unlikely(r)) goto out_cleanup; @@ -567,8 +561,13 @@ static int amdgpu_move_vram_ram(struct ttm_buffer_object *bo, bool evict, goto out_cleanup; } - /* move BO (in tmp_mem) to new_mem */ - r = ttm_bo_move_ttm(bo, ctx, new_mem); + r = ttm_bo_wait_ctx(bo, ctx); + if (unlikely(r)) + goto out_cleanup; + + amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm); + ttm_resource_free(bo, &bo->mem); + ttm_bo_assign_mem(bo, new_mem); out_cleanup: ttm_resource_free(bo, &tmp_mem); return r; @@ -599,7 +598,7 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, placements.fpfn = 0; placements.lpfn = 0; placements.mem_type = TTM_PL_TT; - placements.flags = TTM_PL_MASK_CACHING; + placements.flags = 0; r = ttm_bo_mem_space(bo, &placement, &tmp_mem, ctx); if (unlikely(r)) { pr_err("Failed to find GTT space for blit to VRAM\n"); @@ -607,11 +606,16 @@ static int amdgpu_move_ram_vram(struct ttm_buffer_object *bo, bool evict, } /* move/bind old memory to GTT space */ - r = ttm_bo_move_ttm(bo, ctx, &tmp_mem); + r = ttm_tt_populate(bo->bdev, bo->ttm, ctx); + if (unlikely(r)) + return r; + + r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, &tmp_mem); if (unlikely(r)) { goto out_cleanup; } + ttm_bo_assign_mem(bo, &tmp_mem); /* copy to VRAM */ r = amdgpu_move_blit(bo, evict, new_mem, old_mem); if (unlikely(r)) { @@ -660,9 +664,17 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, struct ttm_resource *old_mem = &bo->mem; int r; + if (new_mem->mem_type == TTM_PL_TT) { + r = amdgpu_ttm_backend_bind(bo->bdev, bo->ttm, new_mem); + if (r) + return r; + } + + amdgpu_bo_move_notify(bo, evict, new_mem); + /* Can't move a pinned BO */ abo = ttm_to_amdgpu_bo(bo); - if (WARN_ON_ONCE(abo->pin_count > 0)) + if (WARN_ON_ONCE(abo->tbo.pin_count > 0)) return -EINVAL; adev = amdgpu_ttm_adev(bo->bdev); @@ -671,14 +683,24 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict, ttm_bo_move_null(bo, new_mem); return 0; } - if ((old_mem->mem_type == TTM_PL_TT && - new_mem->mem_type == TTM_PL_SYSTEM) || - (old_mem->mem_type == TTM_PL_SYSTEM && - new_mem->mem_type == TTM_PL_TT)) { - /* bind is enough */ + if (old_mem->mem_type == TTM_PL_SYSTEM && + new_mem->mem_type == TTM_PL_TT) { ttm_bo_move_null(bo, new_mem); return 0; } + + if (old_mem->mem_type == TTM_PL_TT && + new_mem->mem_type == TTM_PL_SYSTEM) { + r = ttm_bo_wait_ctx(bo, ctx); + if (r) + goto fail; + + amdgpu_ttm_backend_unbind(bo->bdev, bo->ttm); + ttm_resource_free(bo, &bo->mem); + ttm_bo_assign_mem(bo, new_mem); + return 0; + } + if (old_mem->mem_type == AMDGPU_PL_GDS || old_mem->mem_type == AMDGPU_PL_GWS || old_mem->mem_type == AMDGPU_PL_OA || @@ -712,12 +734,12 @@ memcpy: if (!amdgpu_mem_visible(adev, old_mem) || !amdgpu_mem_visible(adev, new_mem)) { pr_err("Move buffer fallback to memcpy unavailable\n"); - return r; + goto fail; } r = ttm_bo_move_memcpy(bo, ctx, new_mem); if (r) - return r; + goto fail; } if (bo->type == ttm_bo_type_device && @@ -732,6 +754,11 @@ memcpy: /* update statistics */ atomic64_add((u64)bo->num_pages << PAGE_SHIFT, &adev->num_bytes_moved); return 0; +fail: + swap(*new_mem, bo->mem); + amdgpu_bo_move_notify(bo, false, new_mem); + swap(*new_mem, bo->mem); + return r; } /** @@ -767,6 +794,7 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_reso mem->bus.offset += adev->gmc.aper_base; mem->bus.is_iomem = true; + mem->bus.caching = ttm_write_combined; break; default: return -EINVAL; @@ -811,7 +839,7 @@ uint64_t amdgpu_ttm_domain_start(struct amdgpu_device *adev, uint32_t type) * TTM backend functions. */ struct amdgpu_ttm_tt { - struct ttm_dma_tt ttm; + struct ttm_tt ttm; struct drm_gem_object *gobj; u64 offset; uint64_t userptr; @@ -943,7 +971,7 @@ bool amdgpu_ttm_tt_get_user_pages_done(struct ttm_tt *ttm) if (!gtt || !gtt->userptr) return false; - DRM_DEBUG_DRIVER("user_pages_done 0x%llx pages 0x%lx\n", + DRM_DEBUG_DRIVER("user_pages_done 0x%llx pages 0x%x\n", gtt->userptr, ttm->num_pages); WARN_ONCE(!gtt->range || !gtt->range->hmm_pfns, @@ -1095,7 +1123,7 @@ static int amdgpu_ttm_gart_bind(struct amdgpu_device *adev, gart_bind_fail: if (r) - DRM_ERROR("failed to bind %lu pages at 0x%08llX\n", + DRM_ERROR("failed to bind %u pages at 0x%08llX\n", ttm->num_pages, gtt->offset); return r; @@ -1130,7 +1158,7 @@ static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev, } } if (!ttm->num_pages) { - WARN(1, "nothing to bind %lu pages for mreg %p back %p!\n", + WARN(1, "nothing to bind %u pages for mreg %p back %p!\n", ttm->num_pages, bo_mem, ttm); } @@ -1153,7 +1181,7 @@ static int amdgpu_ttm_backend_bind(struct ttm_bo_device *bdev, ttm->pages, gtt->ttm.dma_address, flags); if (r) - DRM_ERROR("failed to bind %lu pages at 0x%08llX\n", + DRM_ERROR("failed to bind %u pages at 0x%08llX\n", ttm->num_pages, gtt->offset); gtt->bound = true; return r; @@ -1267,8 +1295,8 @@ static void amdgpu_ttm_backend_unbind(struct ttm_bo_device *bdev, /* unbind shouldn't be done for GDS/GWS/OA in ttm_bo_clean_mm */ r = amdgpu_gart_unbind(adev, gtt->offset, ttm->num_pages); if (r) - DRM_ERROR("failed to unbind %lu pages at 0x%08llX\n", - gtt->ttm.ttm.num_pages, gtt->offset); + DRM_ERROR("failed to unbind %u pages at 0x%08llX\n", + gtt->ttm.num_pages, gtt->offset); gtt->bound = false; } @@ -1282,7 +1310,7 @@ static void amdgpu_ttm_backend_destroy(struct ttm_bo_device *bdev, if (gtt->usertask) put_task_struct(gtt->usertask); - ttm_dma_tt_fini(>t->ttm); + ttm_tt_fini(>t->ttm); kfree(gtt); } @@ -1296,7 +1324,9 @@ static void amdgpu_ttm_backend_destroy(struct ttm_bo_device *bdev, static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, uint32_t page_flags) { + struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); struct amdgpu_ttm_tt *gtt; + enum ttm_caching caching; gtt = kzalloc(sizeof(struct amdgpu_ttm_tt), GFP_KERNEL); if (gtt == NULL) { @@ -1304,12 +1334,17 @@ static struct ttm_tt *amdgpu_ttm_tt_create(struct ttm_buffer_object *bo, } gtt->gobj = &bo->base; + if (abo->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) + caching = ttm_write_combined; + else + caching = ttm_cached; + /* allocate space for the uninitialized page entries */ - if (ttm_sg_tt_init(>t->ttm, bo, page_flags)) { + if (ttm_sg_tt_init(>t->ttm, bo, page_flags, caching)) { kfree(gtt); return NULL; } - return >t->ttm.ttm; + return >t->ttm; } /** @@ -1332,7 +1367,6 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device *bdev, return -ENOMEM; ttm->page_flags |= TTM_PAGE_FLAG_SG; - ttm_tt_set_populated(ttm); return 0; } @@ -1352,7 +1386,6 @@ static int amdgpu_ttm_tt_populate(struct ttm_bo_device *bdev, drm_prime_sg_to_page_addr_arrays(ttm->sg, ttm->pages, gtt->ttm.dma_address, ttm->num_pages); - ttm_tt_set_populated(ttm); return 0; } @@ -1478,7 +1511,7 @@ bool amdgpu_ttm_tt_affect_userptr(struct ttm_tt *ttm, unsigned long start, /* Return false if no part of the ttm_tt object lies within * the range */ - size = (unsigned long)gtt->ttm.ttm.num_pages * PAGE_SIZE; + size = (unsigned long)gtt->ttm.num_pages * PAGE_SIZE; if (gtt->userptr > end || gtt->userptr + size <= start) return false; @@ -1529,7 +1562,7 @@ uint64_t amdgpu_ttm_tt_pde_flags(struct ttm_tt *ttm, struct ttm_resource *mem) if (mem && mem->mem_type == TTM_PL_TT) { flags |= AMDGPU_PTE_SYSTEM; - if (ttm->caching_state == tt_cached) + if (ttm->caching == ttm_cached) flags |= AMDGPU_PTE_SNOOPED; } @@ -1699,20 +1732,23 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, return ret; } +static void +amdgpu_bo_delete_mem_notify(struct ttm_buffer_object *bo) +{ + amdgpu_bo_move_notify(bo, false, NULL); +} + static struct ttm_bo_driver amdgpu_bo_driver = { .ttm_tt_create = &amdgpu_ttm_tt_create, .ttm_tt_populate = &amdgpu_ttm_tt_populate, .ttm_tt_unpopulate = &amdgpu_ttm_tt_unpopulate, - .ttm_tt_bind = &amdgpu_ttm_backend_bind, - .ttm_tt_unbind = &amdgpu_ttm_backend_unbind, .ttm_tt_destroy = &amdgpu_ttm_backend_destroy, .eviction_valuable = amdgpu_ttm_bo_eviction_valuable, .evict_flags = &amdgpu_evict_flags, .move = &amdgpu_bo_move, .verify_access = &amdgpu_verify_access, - .move_notify = &amdgpu_bo_move_notify, + .delete_mem_notify = &amdgpu_bo_delete_mem_notify, .release_notify = &amdgpu_bo_release_notify, - .fault_reserve_notify = &amdgpu_bo_fault_reserve_notify, .io_mem_reserve = &amdgpu_ttm_io_mem_reserve, .io_mem_pfn = amdgpu_ttm_io_mem_pfn, .access_memory = &amdgpu_ttm_access_memory, @@ -2092,15 +2128,48 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable) adev->mman.buffer_funcs_enabled = enable; } +static vm_fault_t amdgpu_ttm_fault(struct vm_fault *vmf) +{ + struct ttm_buffer_object *bo = vmf->vma->vm_private_data; + vm_fault_t ret; + + ret = ttm_bo_vm_reserve(bo, vmf); + if (ret) + return ret; + + ret = amdgpu_bo_fault_reserve_notify(bo); + if (ret) + goto unlock; + + ret = ttm_bo_vm_fault_reserved(vmf, vmf->vma->vm_page_prot, + TTM_BO_VM_NUM_PREFAULT, 1); + if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) + return ret; + +unlock: + dma_resv_unlock(bo->base.resv); + return ret; +} + +static struct vm_operations_struct amdgpu_ttm_vm_ops = { + .fault = amdgpu_ttm_fault, + .open = ttm_bo_vm_open, + .close = ttm_bo_vm_close, + .access = ttm_bo_vm_access +}; + int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) { struct drm_file *file_priv = filp->private_data; struct amdgpu_device *adev = drm_to_adev(file_priv->minor->dev); + int r; - if (adev == NULL) - return -EINVAL; + r = ttm_bo_mmap(filp, vma, &adev->mman.bdev); + if (unlikely(r != 0)) + return r; - return ttm_bo_mmap(filp, vma, &adev->mman.bdev); + vma->vm_ops = &amdgpu_ttm_vm_ops; + return 0; } int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index df110afa97bf..38b59a4fc04c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -609,7 +609,7 @@ void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo) if (!amdgpu_bo_is_amdgpu_bo(bo)) return; - if (bo->mem.placement & TTM_PL_FLAG_NO_EVICT) + if (bo->pin_count) return; abo = ttm_to_amdgpu_bo(bo); @@ -1790,7 +1790,6 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, resv = vm->root.base.bo->tbo.base.resv; } else { struct drm_gem_object *obj = &bo->tbo.base; - struct ttm_dma_tt *ttm; resv = bo->tbo.base.resv; if (obj->import_attach && bo_va->is_xgmi) { @@ -1803,10 +1802,8 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, } mem = &bo->tbo.mem; nodes = mem->mm_node; - if (mem->mem_type == TTM_PL_TT) { - ttm = container_of(bo->tbo.ttm, struct ttm_dma_tt, ttm); - pages_addr = ttm->dma_address; - } + if (mem->mem_type == TTM_PL_TT) + pages_addr = bo->tbo.ttm->dma_address; } if (bo) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 01c1171afbe0..7747be644dd0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -212,7 +212,7 @@ void amdgpu_vram_mgr_fini(struct amdgpu_device *adev) ttm_resource_manager_set_used(man, false); - ret = ttm_resource_manager_force_list_clean(&adev->mman.bdev, man); + ret = ttm_resource_manager_evict_all(&adev->mman.bdev, man); if (ret) return; diff --git a/drivers/gpu/drm/arc/arcpgu_crtc.c b/drivers/gpu/drm/arc/arcpgu_crtc.c index be7c29cec318..042d7b54a6de 100644 --- a/drivers/gpu/drm/arc/arcpgu_crtc.c +++ b/drivers/gpu/drm/arc/arcpgu_crtc.c @@ -116,7 +116,7 @@ static void arc_pgu_crtc_mode_set_nofb(struct drm_crtc *crtc) } static void arc_pgu_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) + struct drm_atomic_state *state) { struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); @@ -127,7 +127,7 @@ static void arc_pgu_crtc_atomic_enable(struct drm_crtc *crtc, } static void arc_pgu_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) + struct drm_atomic_state *state) { struct arcpgu_drm_private *arcpgu = crtc_to_arcpgu_priv(crtc); diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index f33418d6e1a0..a4bbf56a7fc1 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c @@ -273,8 +273,10 @@ komeda_crtc_do_flush(struct drm_crtc *crtc, static void komeda_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_crtc_state *old) + struct drm_atomic_state *state) { + struct drm_crtc_state *old = drm_atomic_get_old_crtc_state(state, + crtc); pm_runtime_get_sync(crtc->dev->dev); komeda_crtc_prepare(to_kcrtc(crtc)); drm_crtc_vblank_on(crtc); @@ -319,8 +321,10 @@ komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc, static void komeda_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_crtc_state *old) + struct drm_atomic_state *state) { + struct drm_crtc_state *old = drm_atomic_get_old_crtc_state(state, + crtc); struct komeda_crtc *kcrtc = to_kcrtc(crtc); struct komeda_crtc_state *old_st = to_kcrtc_st(old); struct komeda_pipeline *master = kcrtc->master; diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c index 1d767473ba8a..1f8195bad536 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c @@ -41,18 +41,7 @@ static int komeda_register_show(struct seq_file *sf, void *x) return 0; } -static int komeda_register_open(struct inode *inode, struct file *filp) -{ - return single_open(filp, komeda_register_show, inode->i_private); -} - -static const struct file_operations komeda_register_fops = { - .owner = THIS_MODULE, - .open = komeda_register_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(komeda_register); #ifdef CONFIG_DEBUG_FS static void komeda_debugfs_init(struct komeda_dev *mdev) @@ -261,8 +250,7 @@ struct komeda_dev *komeda_dev_create(struct device *dev) goto disable_clk; } - dev->dma_parms = &mdev->dma_parms; - dma_set_max_seg_size(dev, DMA_BIT_MASK(32)); + dma_set_max_seg_size(dev, U32_MAX); mdev->iommu = iommu_get_domain_for_dev(mdev->dev); if (!mdev->iommu) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h index ce27f2f27c24..5b536f0cb548 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.h @@ -163,8 +163,6 @@ struct komeda_dev { struct device *dev; /** @reg_base: the base address of komeda io space */ u32 __iomem *reg_base; - /** @dma_parms: the dma parameters of komeda */ - struct device_dma_parameters dma_parms; /** @chip: the basic chip information */ struct komeda_chip_info chip; diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index af67fefed38d..84ac10d59485 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -168,7 +168,7 @@ static void hdlcd_crtc_mode_set_nofb(struct drm_crtc *crtc) } static void hdlcd_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) + struct drm_atomic_state *state) { struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); @@ -179,7 +179,7 @@ static void hdlcd_crtc_atomic_enable(struct drm_crtc *crtc, } static void hdlcd_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) + struct drm_atomic_state *state) { struct hdlcd_drm_private *hdlcd = crtc_to_hdlcd_priv(crtc); diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 587d94798f5c..49766eb7a554 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -46,7 +46,7 @@ static enum drm_mode_status malidp_crtc_mode_valid(struct drm_crtc *crtc, } static void malidp_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) + struct drm_atomic_state *state) { struct malidp_drm *malidp = crtc_to_malidp_device(crtc); struct malidp_hw_device *hwdev = malidp->dev; @@ -70,8 +70,10 @@ static void malidp_crtc_atomic_enable(struct drm_crtc *crtc, } static void malidp_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) + struct drm_atomic_state *state) { + struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, + crtc); struct malidp_drm *malidp = crtc_to_malidp_device(crtc); struct malidp_hw_device *hwdev = malidp->dev; int err; diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c index a887b6a5f8bd..e0fbfc9ce386 100644 --- a/drivers/gpu/drm/armada/armada_crtc.c +++ b/drivers/gpu/drm/armada/armada_crtc.c @@ -467,8 +467,10 @@ static void armada_drm_crtc_atomic_flush(struct drm_crtc *crtc, } static void armada_drm_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) + struct drm_atomic_state *state) { + struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, + crtc); struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); struct drm_pending_vblank_event *event; @@ -503,8 +505,10 @@ static void armada_drm_crtc_atomic_disable(struct drm_crtc *crtc, } static void armada_drm_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_crtc_state *old_state) + struct drm_atomic_state *state) { + struct drm_crtc_state *old_state = drm_atomic_get_old_crtc_state(state, + crtc); struct armada_crtc *dcrtc = drm_to_armada_crtc(crtc); DRM_DEBUG_KMS("[CRTC:%d:%s]\n", crtc->base.id, crtc->name); diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 980d3f1f8f16..22247cfce80b 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -37,13 +37,10 @@ DEFINE_DRM_GEM_FOPS(armada_drm_fops); static struct drm_driver armada_drm_driver = { .lastclose = drm_fb_helper_lastclose, - .gem_free_object_unlocked = armada_gem_free_object, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = armada_gem_prime_export, .gem_prime_import = armada_gem_prime_import, .dumb_create = armada_gem_dumb_create, - .gem_vm_ops = &armada_gem_vm_ops, .major = 1, .minor = 0, .name = "armada-drm", diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 6654bccd9466..21909642ee4c 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -25,7 +25,7 @@ static vm_fault_t armada_gem_vm_fault(struct vm_fault *vmf) return vmf_insert_pfn(vmf->vma, vmf->address, pfn); } -const struct vm_operations_struct armada_gem_vm_ops = { +static const struct vm_operations_struct armada_gem_vm_ops = { .fault = armada_gem_vm_fault, .open = drm_gem_vm_open, .close = drm_gem_vm_close, @@ -184,6 +184,12 @@ armada_gem_map_object(struct drm_device *dev, struct armada_gem_object *dobj) return dobj->addr; } +static const struct drm_gem_object_funcs armada_gem_object_funcs = { + .free = armada_gem_free_object, + .export = armada_gem_prime_export, + .vm_ops = &armada_gem_vm_ops, +}; + struct armada_gem_object * armada_gem_alloc_private_object(struct drm_device *dev, size_t size) { @@ -195,6 +201,8 @@ armada_gem_alloc_private_object(struct drm_device *dev, size_t size) if (!obj) return NULL; + obj->obj.funcs = &armada_gem_object_funcs; + drm_gem_private_object_init(dev, &obj->obj, size); DRM_DEBUG_DRIVER("alloc private obj %p size %zu\n", obj, size); @@ -214,6 +222,8 @@ static struct armada_gem_object *armada_gem_alloc_object(struct drm_device *dev, if (!obj) return NULL; + obj->obj.funcs = &armada_gem_object_funcs; + if (drm_gem_object_init(dev, &obj->obj, size)) { kfree(obj); return NULL; diff --git a/drivers/gpu/drm/armada/armada_gem.h b/drivers/gpu/drm/armada/armada_gem.h index de04cc2c8f0e..ffcc7e8dd351 100644 --- a/drivers/gpu/drm/armada/armada_gem.h +++ b/drivers/gpu/drm/armada/armada_gem.h @@ -21,8 +21,6 @@ struct armada_gem_object { void *update_data; }; -extern const struct vm_operations_struct armada_gem_vm_ops; - #define drm_to_armada_gem(o) container_of(o, struct armada_gem_object, obj) void armada_gem_free_object(struct drm_gem_object *); diff --git a/drivers/gpu/drm/aspeed/Kconfig b/drivers/gpu/drm/aspeed/Kconfig index 018383cfcfa7..5e95bcea43e9 100644 --- a/drivers/gpu/drm/aspeed/Kconfig +++ b/drivers/gpu/drm/aspeed/Kconfig @@ -3,6 +3,7 @@ config DRM_ASPEED_GFX tristate "ASPEED BMC Display Controller" depends on DRM && OF depends on (COMPILE_TEST || ARCH_ASPEED) + depends on MMU select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER select DMA_CMA if HAVE_DMA_CONTIGUOUS diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx.h b/drivers/gpu/drm/aspeed/aspeed_gfx.h index e7ca95827ae8..f1e7e56abc02 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx.h +++ b/drivers/gpu/drm/aspeed/aspeed_gfx.h @@ -75,7 +75,7 @@ int aspeed_gfx_create_output(struct drm_device *drm); /* CTRL2 */ #define CRT_CTRL_DAC_EN BIT(0) #define CRT_CTRL_VBLANK_LINE(x) (((x) << 20) & CRT_CTRL_VBLANK_LINE_MASK) -#define CRT_CTRL_VBLANK_LINE_MASK GENMASK(20, 31) +#define CRT_CTRL_VBLANK_LINE_MASK GENMASK(31, 20) /* CRT_HORIZ0 */ #define CRT_H_TOTAL(x) (x) diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c index 2b424b2b85cc..771ad71cd340 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c @@ -193,12 +193,7 @@ DEFINE_DRM_GEM_CMA_FOPS(fops); static struct drm_driver aspeed_gfx_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, - .gem_create_object = drm_gem_cma_create_object_default_funcs, - .dumb_create = drm_gem_cma_dumb_create, - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, - .gem_prime_mmap = drm_gem_prime_mmap, + DRM_GEM_CMA_DRIVER_OPS, .fops = &fops, .name = "aspeed-gfx-drm", .desc = "ASPEED GFX DRM", @@ -212,6 +207,69 @@ static const struct of_device_id aspeed_gfx_match[] = { { } }; +#define ASPEED_SCU_VGA0 0x50 +#define ASPEED_SCU_MISC_CTRL 0x2c + +static ssize_t dac_mux_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct aspeed_gfx *priv = dev_get_drvdata(dev); + u32 val; + int rc; + + rc = kstrtou32(buf, 0, &val); + if (rc) + return rc; + + if (val > 3) + return -EINVAL; + + rc = regmap_update_bits(priv->scu, ASPEED_SCU_MISC_CTRL, 0x30000, val << 16); + if (rc < 0) + return 0; + + return count; +} + +static ssize_t dac_mux_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct aspeed_gfx *priv = dev_get_drvdata(dev); + u32 reg; + int rc; + + rc = regmap_read(priv->scu, ASPEED_SCU_MISC_CTRL, ®); + if (rc) + return rc; + + return sprintf(buf, "%u\n", (reg >> 16) & 0x3); +} +static DEVICE_ATTR_RW(dac_mux); + +static ssize_t +vga_pw_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct aspeed_gfx *priv = dev_get_drvdata(dev); + u32 reg; + int rc; + + rc = regmap_read(priv->scu, ASPEED_SCU_VGA0, ®); + if (rc) + return rc; + + return sprintf(buf, "%u\n", reg & 1); +} +static DEVICE_ATTR_RO(vga_pw); + +static struct attribute *aspeed_sysfs_entries[] = { + &dev_attr_vga_pw.attr, + &dev_attr_dac_mux.attr, + NULL, +}; + +static struct attribute_group aspeed_sysfs_attr_group = { + .attrs = aspeed_sysfs_entries, +}; + static int aspeed_gfx_probe(struct platform_device *pdev) { struct aspeed_gfx *priv; @@ -226,6 +284,12 @@ static int aspeed_gfx_probe(struct platform_device *pdev) if (ret) return ret; + dev_set_drvdata(&pdev->dev, priv); + + ret = sysfs_create_group(&pdev->dev.kobj, &aspeed_sysfs_attr_group); + if (ret) + return ret; + ret = drm_dev_register(&priv->drm, 0); if (ret) goto err_unload; @@ -234,6 +298,7 @@ static int aspeed_gfx_probe(struct platform_device *pdev) return 0; err_unload: + sysfs_remove_group(&pdev->dev.kobj, &aspeed_sysfs_attr_group); aspeed_gfx_unload(&priv->drm); return ret; @@ -243,6 +308,7 @@ static int aspeed_gfx_remove(struct platform_device *pdev) { struct drm_device *drm = platform_get_drvdata(pdev); + sysfs_remove_group(&pdev->dev.kobj, &aspeed_sysfs_attr_group); drm_dev_unregister(drm); aspeed_gfx_unload(drm); diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 834a156e3a75..bd03a8a67e3a 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -742,7 +742,6 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) case DRM_MODE_DPMS_SUSPEND: if (ast->tx_chip_type == AST_TX_DP501) ast_set_dp501_video_output(crtc->dev, 1); - ast_crtc_load_lut(ast, crtc); break; case DRM_MODE_DPMS_OFF: if (ast->tx_chip_type == AST_TX_DP501) @@ -777,9 +776,24 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc, return 0; } +static void +ast_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) +{ + struct ast_private *ast = to_ast_private(crtc->dev); + struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc->state); + struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state); + + /* + * The gamma LUT has to be reloaded after changing the primary + * plane's color format. + */ + if (old_ast_crtc_state->format != ast_crtc_state->format) + ast_crtc_load_lut(ast, crtc); +} + static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) + struct drm_atomic_state *state) { struct drm_device *dev = crtc->dev; struct ast_private *ast = to_ast_private(dev); @@ -802,8 +816,10 @@ ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, - struct drm_crtc_state *old_crtc_state) + struct drm_atomic_state *state) { + struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, + crtc); struct drm_device *dev = crtc->dev; struct ast_private *ast = to_ast_private(dev); @@ -830,6 +846,7 @@ ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = { .atomic_check = ast_crtc_helper_atomic_check, + .atomic_flush = ast_crtc_helper_atomic_flush, .atomic_enable = ast_crtc_helper_atomic_enable, .atomic_disable = ast_crtc_helper_atomic_disable, }; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index ce246b96330b..2b3888df22f8 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -165,7 +165,7 @@ atmel_hlcdc_crtc_mode_valid(struct drm_crtc *c, } static void atmel_hlcdc_crtc_atomic_disable(struct drm_crtc *c, - struct drm_crtc_state *old_state) + struct drm_atomic_state *state) { struct drm_device *dev = c->dev; struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); @@ -200,7 +200,7 @@ static void atmel_hlcdc_crtc_atomic_disable(struct drm_crtc *c, } static void atmel_hlcdc_crtc_atomic_enable(struct drm_crtc *c, - struct drm_crtc_state *old_state) + struct drm_atomic_state *state) { struct drm_device *dev = c->dev; struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c index f101dd2819b5..45838bd08d37 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c @@ -55,9 +55,9 @@ static int adv7511_update_cts_n(struct adv7511 *adv7511) return 0; } -int adv7511_hdmi_hw_params(struct device *dev, void *data, - struct hdmi_codec_daifmt *fmt, - struct hdmi_codec_params *hparms) +static int adv7511_hdmi_hw_params(struct device *dev, void *data, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms) { struct adv7511 *adv7511 = dev_get_drvdata(dev); unsigned int audio_source, i2s_format = 0; diff --git a/drivers/gpu/drm/bridge/analogix/Kconfig b/drivers/gpu/drm/bridge/analogix/Kconfig index e1fa7d820373..024ea2a570e7 100644 --- a/drivers/gpu/drm/bridge/analogix/Kconfig +++ b/drivers/gpu/drm/bridge/analogix/Kconfig @@ -25,3 +25,12 @@ config DRM_ANALOGIX_ANX78XX config DRM_ANALOGIX_DP tristate depends on DRM + +config DRM_ANALOGIX_ANX7625 + tristate "Analogix Anx7625 MIPI to DP interface support" + depends on DRM + depends on OF + help + ANX7625 is an ultra-low power 4K mobile HD transmitter + designed for portable devices. It converts MIPI/DPI to + DisplayPort1.3 4K. diff --git a/drivers/gpu/drm/bridge/analogix/Makefile b/drivers/gpu/drm/bridge/analogix/Makefile index 97669b374098..44da392bb9f9 100644 --- a/drivers/gpu/drm/bridge/analogix/Makefile +++ b/drivers/gpu/drm/bridge/analogix/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only analogix_dp-objs := analogix_dp_core.o analogix_dp_reg.o analogix-i2c-dptx.o obj-$(CONFIG_DRM_ANALOGIX_ANX6345) += analogix-anx6345.o +obj-$(CONFIG_DRM_ANALOGIX_ANX7625) += anx7625.o obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix_dp.o diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 914c569ab8c1..fafb4b492ea0 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -524,7 +524,7 @@ void analogix_dp_enable_sw_function(struct analogix_dp_device *dp) writel(reg, dp->reg_base + ANALOGIX_DP_FUNC_EN_1); } -int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp) +static int analogix_dp_start_aux_transaction(struct analogix_dp_device *dp) { int reg; int retval = 0; diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c new file mode 100644 index 000000000000..65cc05982f82 --- /dev/null +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -0,0 +1,1850 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright(c) 2020, Analogix Semiconductor. All rights reserved. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include