linux/drivers/gpu/drm/drm_cache.c
Linus Torvalds b14ffae378 drm for 5.18-rc1
dma-buf:
 - rename dma-buf-map to iosys-map
 
 core:
 - move buddy allocator to core
 - add pci/platform init macros
 - improve EDID parser deep color handling
 - EDID timing type 7 support
 - add GPD Win Max quirk
 - add yes/no helpers to string_helpers
 - flatten syncobj chains
 - add nomodeset support to lots of drivers
 - improve fb-helper clipping support
 - add default property value interface
 
 fbdev:
 - improve fbdev ops speed
 
 ttm:
 - add a backpointer from ttm bo->ttm resource
 
 dp:
 - move displayport headers
 - add a dp helper module
 
 bridge:
 - anx7625 atomic support, HDCP support
 
 panel:
 - split out panel-lvds and lvds bindings
 - find panels in OF subnodes
 
 privacy:
 - add chromeos privacy screen support
 
 fb:
 - hot unplug fw fb on forced removal
 
 simpledrm:
 - request region instead of marking ioresource busy
 - add panel oreintation property
 
 udmabuf:
 - fix oops with 0 pages
 
 amdgpu:
 - power management code cleanup
 - Enable freesync video mode by default
 - RAS code cleanup
 - Improve VRAM access for debug using SDMA
 - SR-IOV rework special register access and fixes
 - profiling power state request ioctl
 - expose IP discovery via sysfs
 - Cyan skillfish updates
 - GC 10.3.7, SDMA 5.2.7, DCN 3.1.6 updates
 - expose benchmark tests via debugfs
 - add module param to disable XGMI for testing
 - GPU reset debugfs register dumping support
 
 amdkfd:
 - CRIU support
 - SDMA queue fixes
 
 radeon:
 - UVD suspend fix
 - iMac backlight fix
 
 i915:
 - minimal parallel submission for execlists
 - DG2-G12 subplatform added
 - DG2 programming workarounds
 - DG2 accelerated migration support
 - flat CCS and CCS engine support for XeHP
 - initial small BAR support
 - drop fake LMEM support
 - ADL-N PCH support
 - bigjoiner updates
 - introduce VMA resources and async unbinding
 - register definitions cleanups
 - multi-FBC refactoring
 - DG1 OPROM over SPI support
 - ADL-N platform enabling
 - opregion mailbox #5 support
 - DP MST ESI improvements
 - drm device based logging
 - async flip optimisation for DG2
 - CPU arch abstraction fixes
 - improve GuC ADS init to work on aarch64
 - tweak TTM LRU priority hint
 - GuC 69.0.3 support
 - remove short term execbuf pins
 
 nouveau:
 - higher DP/eDP bitrates
 - backlight fixes
 
 msm:
 - dpu + dp support for sc8180x
 - dp support for sm8350
 - dpu + dsi support for qcm2290
 - 10nm dsi phy tuning support
 - bridge support for dp encoder
 - gpu support for additional 7c3 SKUs
 
 ingenic:
 - HDMI support for JZ4780
 - aux channel EDID support
 
 ast:
 - AST2600 support
 - add wide screen support
 - create DP/DVI connectors
 
 omapdrm:
 - fix implicit dma_buf fencing
 
 vc4:
 - add CSC + full range support
 - better display firmware handoff
 
 panfrost:
 - add initial dual-core GPU support
 
 stm:
 - new revision support
 - fb handover support
 
 mediatek:
 - transfer display binding document to yaml format.
 - add mt8195 display device binding.
 - allow commands to be sent during video mode.
 - add wait_for_event for crtc disable by cmdq.
 
 tegra:
 - YUV format support
 
 rcar-du:
 - LVDS support for M3-W+ (R8A77961)
 
 exynos:
 - BGR pixel format for FIMD device
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmI71h4ACgkQDHTzWXnE
 hr6wKg//SvKFiEOhptua8Ao8XYkhXpg1/tgdAs4D7bZ0YgJyF4Im0RuFOKMmF3mN
 0Y8AwguqrsmrOAFbK8B1WEysB66DmGlZN/V2Q75X7fui8xs4uGF2Fcxyr+265zhf
 vONPwAoxYr+KXqwOI1p1BP2QEL6bJTdu+nrXRsXIBIrWnw8ehXJlw3fDhgvG5QBn
 RPdbU7lQnd47hdYxkbe5SiZvWnPC46dJmpqsRJir0xjskR6juU36f34C4IKhTGwO
 NDPeWVgusVXtIC/F4X6RebCWG0f66h+CUFa9zeYIleI/2/5yZWXfcw6Obx8HgPkt
 gieiI0R4TpkVxeHCApCQ5UpxWgfSOXdoDoyw172bKQw7JCHVEkSwenyMEEwNet6r
 SCJrRmlB1PBI/iTWmhm9qgrU46ZZyAnQoTlCsXGzJncdP3hzGlA1embl00yfEl7f
 wzM35N20qd5T4VKUEF8QYF0fLZYmKw4cWVASu4hQ3qmGal6frilphz2J8JK8hQNq
 KhFqNbVTnZsQNr9LBCbrf0kOPaMzpmW+2vQG9ApdAb1N3gNPZT7ctti0Xq5N2OUR
 AipWFAsDPS2NPADKmBtDU55PgFH9MqUIsoHHXLV4Qi76dvCqYoN68qRQxrL7rpSu
 b0gr0YKU2QcIB/uytjOPHcgtI5Xvrh+q8JPz/dJ38/Esgjmk4wo=
 =uRsT
 -----END PGP SIGNATURE-----

Merge tag 'drm-next-2022-03-24' of git://anongit.freedesktop.org/drm/drm

Pull drm updates from Dave Airlie:
 "Lots of work all over, Intel improving DG2 support, amdkfd CRIU
  support, msm new hw support, and faster fbdev support.

  dma-buf:
   - rename dma-buf-map to iosys-map

  core:
   - move buddy allocator to core
   - add pci/platform init macros
   - improve EDID parser deep color handling
   - EDID timing type 7 support
   - add GPD Win Max quirk
   - add yes/no helpers to string_helpers
   - flatten syncobj chains
   - add nomodeset support to lots of drivers
   - improve fb-helper clipping support
   - add default property value interface

  fbdev:
   - improve fbdev ops speed

  ttm:
   - add a backpointer from ttm bo->ttm resource

  dp:
   - move displayport headers
   - add a dp helper module

  bridge:
   - anx7625 atomic support, HDCP support

  panel:
   - split out panel-lvds and lvds bindings
   - find panels in OF subnodes

  privacy:
   - add chromeos privacy screen support

  fb:
   - hot unplug fw fb on forced removal

  simpledrm:
   - request region instead of marking ioresource busy
   - add panel oreintation property

  udmabuf:
   - fix oops with 0 pages

  amdgpu:
   - power management code cleanup
   - Enable freesync video mode by default
   - RAS code cleanup
   - Improve VRAM access for debug using SDMA
   - SR-IOV rework special register access and fixes
   - profiling power state request ioctl
   - expose IP discovery via sysfs
   - Cyan skillfish updates
   - GC 10.3.7, SDMA 5.2.7, DCN 3.1.6 updates
   - expose benchmark tests via debugfs
   - add module param to disable XGMI for testing
   - GPU reset debugfs register dumping support

  amdkfd:
   - CRIU support
   - SDMA queue fixes

  radeon:
   - UVD suspend fix
   - iMac backlight fix

  i915:
   - minimal parallel submission for execlists
   - DG2-G12 subplatform added
   - DG2 programming workarounds
   - DG2 accelerated migration support
   - flat CCS and CCS engine support for XeHP
   - initial small BAR support
   - drop fake LMEM support
   - ADL-N PCH support
   - bigjoiner updates
   - introduce VMA resources and async unbinding
   - register definitions cleanups
   - multi-FBC refactoring
   - DG1 OPROM over SPI support
   - ADL-N platform enabling
   - opregion mailbox #5 support
   - DP MST ESI improvements
   - drm device based logging
   - async flip optimisation for DG2
   - CPU arch abstraction fixes
   - improve GuC ADS init to work on aarch64
   - tweak TTM LRU priority hint
   - GuC 69.0.3 support
   - remove short term execbuf pins

  nouveau:
   - higher DP/eDP bitrates
   - backlight fixes

  msm:
   - dpu + dp support for sc8180x
   - dp support for sm8350
   - dpu + dsi support for qcm2290
   - 10nm dsi phy tuning support
   - bridge support for dp encoder
   - gpu support for additional 7c3 SKUs

  ingenic:
   - HDMI support for JZ4780
   - aux channel EDID support

  ast:
   - AST2600 support
   - add wide screen support
   - create DP/DVI connectors

  omapdrm:
   - fix implicit dma_buf fencing

  vc4:
   - add CSC + full range support
   - better display firmware handoff

  panfrost:
   - add initial dual-core GPU support

  stm:
   - new revision support
   - fb handover support

  mediatek:
   - transfer display binding document to yaml format.
   - add mt8195 display device binding.
   - allow commands to be sent during video mode.
   - add wait_for_event for crtc disable by cmdq.

  tegra:
   - YUV format support

  rcar-du:
   - LVDS support for M3-W+ (R8A77961)

  exynos:
   - BGR pixel format for FIMD device"

* tag 'drm-next-2022-03-24' of git://anongit.freedesktop.org/drm/drm: (1529 commits)
  drm/i915/display: Do not re-enable PSR after it was marked as not reliable
  drm/i915/display: Fix HPD short pulse handling for eDP
  drm/amdgpu: Use drm_mode_copy()
  drm/radeon: Use drm_mode_copy()
  drm/amdgpu: Use ternary operator in `vcn_v1_0_start()`
  drm/amdgpu: Remove pointless on stack mode copies
  drm/amd/pm: fix indenting in __smu_cmn_reg_print_error()
  drm/amdgpu/dc: fix typos in comments
  drm/amdgpu: fix typos in comments
  drm/amd/pm: fix typos in comments
  drm/amdgpu: Add stolen reserved memory for MI25 SRIOV.
  drm/amdgpu: Merge get_reserved_allocation to get_vbios_allocations.
  drm/amdkfd: evict svm bo worker handle error
  drm/amdgpu/vcn: fix vcn ring test failure in igt reload test
  drm/amdgpu: only allow secure submission on rings which support that
  drm/amdgpu: fixed the warnings reported by kernel test robot
  drm/amd/display: 3.2.177
  drm/amd/display: [FW Promotion] Release 0.0.108.0
  drm/amd/display: Add save/restore PANEL_PWRSEQ_REF_DIV2
  drm/amd/display: Wait for hubp read line for Pollock
  ...
2022-03-24 16:19:43 -07:00

357 lines
9.6 KiB
C

/**************************************************************************
*
* Copyright (c) 2006-2007 Tungsten Graphics, Inc., Cedar Park, TX., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#include <linux/cc_platform.h>
#include <linux/export.h>
#include <linux/highmem.h>
#include <linux/ioport.h>
#include <linux/iosys-map.h>
#include <xen/xen.h>
#include <drm/drm_cache.h>
/* A small bounce buffer that fits on the stack. */
#define MEMCPY_BOUNCE_SIZE 128
#if defined(CONFIG_X86)
#include <asm/smp.h>
/*
* clflushopt is an unordered instruction which needs fencing with mfence or
* sfence to avoid ordering issues. For drm_clflush_page this fencing happens
* in the caller.
*/
static void
drm_clflush_page(struct page *page)
{
uint8_t *page_virtual;
unsigned int i;
const int size = boot_cpu_data.x86_clflush_size;
if (unlikely(page == NULL))
return;
page_virtual = kmap_atomic(page);
for (i = 0; i < PAGE_SIZE; i += size)
clflushopt(page_virtual + i);
kunmap_atomic(page_virtual);
}
static void drm_cache_flush_clflush(struct page *pages[],
unsigned long num_pages)
{
unsigned long i;
mb(); /*Full memory barrier used before so that CLFLUSH is ordered*/
for (i = 0; i < num_pages; i++)
drm_clflush_page(*pages++);
mb(); /*Also used after CLFLUSH so that all cache is flushed*/
}
#endif
/**
* drm_clflush_pages - Flush dcache lines of a set of pages.
* @pages: List of pages to be flushed.
* @num_pages: Number of pages in the array.
*
* Flush every data cache line entry that points to an address belonging
* to a page in the array.
*/
void
drm_clflush_pages(struct page *pages[], unsigned long num_pages)
{
#if defined(CONFIG_X86)
if (static_cpu_has(X86_FEATURE_CLFLUSH)) {
drm_cache_flush_clflush(pages, num_pages);
return;
}
if (wbinvd_on_all_cpus())
pr_err("Timed out waiting for cache flush\n");
#elif defined(__powerpc__)
unsigned long i;
for (i = 0; i < num_pages; i++) {
struct page *page = pages[i];
void *page_virtual;
if (unlikely(page == NULL))
continue;
page_virtual = kmap_atomic(page);
flush_dcache_range((unsigned long)page_virtual,
(unsigned long)page_virtual + PAGE_SIZE);
kunmap_atomic(page_virtual);
}
#else
WARN_ONCE(1, "Architecture has no drm_cache.c support\n");
#endif
}
EXPORT_SYMBOL(drm_clflush_pages);
/**
* drm_clflush_sg - Flush dcache lines pointing to a scather-gather.
* @st: struct sg_table.
*
* Flush every data cache line entry that points to an address in the
* sg.
*/
void
drm_clflush_sg(struct sg_table *st)
{
#if defined(CONFIG_X86)
if (static_cpu_has(X86_FEATURE_CLFLUSH)) {
struct sg_page_iter sg_iter;
mb(); /*CLFLUSH is ordered only by using memory barriers*/
for_each_sgtable_page(st, &sg_iter, 0)
drm_clflush_page(sg_page_iter_page(&sg_iter));
mb(); /*Make sure that all cache line entry is flushed*/
return;
}
if (wbinvd_on_all_cpus())
pr_err("Timed out waiting for cache flush\n");
#else
WARN_ONCE(1, "Architecture has no drm_cache.c support\n");
#endif
}
EXPORT_SYMBOL(drm_clflush_sg);
/**
* drm_clflush_virt_range - Flush dcache lines of a region
* @addr: Initial kernel memory address.
* @length: Region size.
*
* Flush every data cache line entry that points to an address in the
* region requested.
*/
void
drm_clflush_virt_range(void *addr, unsigned long length)
{
#if defined(CONFIG_X86)
if (static_cpu_has(X86_FEATURE_CLFLUSH)) {
const int size = boot_cpu_data.x86_clflush_size;
void *end = addr + length;
addr = (void *)(((unsigned long)addr) & -size);
mb(); /*CLFLUSH is only ordered with a full memory barrier*/
for (; addr < end; addr += size)
clflushopt(addr);
clflushopt(end - 1); /* force serialisation */
mb(); /*Ensure that every data cache line entry is flushed*/
return;
}
if (wbinvd_on_all_cpus())
pr_err("Timed out waiting for cache flush\n");
#else
WARN_ONCE(1, "Architecture has no drm_cache.c support\n");
#endif
}
EXPORT_SYMBOL(drm_clflush_virt_range);
bool drm_need_swiotlb(int dma_bits)
{
struct resource *tmp;
resource_size_t max_iomem = 0;
/*
* Xen paravirtual hosts require swiotlb regardless of requested dma
* transfer size.
*
* NOTE: Really, what it requires is use of the dma_alloc_coherent
* allocator used in ttm_dma_populate() instead of
* ttm_populate_and_map_pages(), which bounce buffers so much in
* Xen it leads to swiotlb buffer exhaustion.
*/
if (xen_pv_domain())
return true;
/*
* Enforce dma_alloc_coherent when memory encryption is active as well
* for the same reasons as for Xen paravirtual hosts.
*/
if (cc_platform_has(CC_ATTR_MEM_ENCRYPT))
return true;
for (tmp = iomem_resource.child; tmp; tmp = tmp->sibling)
max_iomem = max(max_iomem, tmp->end);
return max_iomem > ((u64)1 << dma_bits);
}
EXPORT_SYMBOL(drm_need_swiotlb);
static void memcpy_fallback(struct iosys_map *dst,
const struct iosys_map *src,
unsigned long len)
{
if (!dst->is_iomem && !src->is_iomem) {
memcpy(dst->vaddr, src->vaddr, len);
} else if (!src->is_iomem) {
iosys_map_memcpy_to(dst, 0, src->vaddr, len);
} else if (!dst->is_iomem) {
memcpy_fromio(dst->vaddr, src->vaddr_iomem, len);
} else {
/*
* Bounce size is not performance tuned, but using a
* bounce buffer like this is significantly faster than
* resorting to ioreadxx() + iowritexx().
*/
char bounce[MEMCPY_BOUNCE_SIZE];
void __iomem *_src = src->vaddr_iomem;
void __iomem *_dst = dst->vaddr_iomem;
while (len >= MEMCPY_BOUNCE_SIZE) {
memcpy_fromio(bounce, _src, MEMCPY_BOUNCE_SIZE);
memcpy_toio(_dst, bounce, MEMCPY_BOUNCE_SIZE);
_src += MEMCPY_BOUNCE_SIZE;
_dst += MEMCPY_BOUNCE_SIZE;
len -= MEMCPY_BOUNCE_SIZE;
}
if (len) {
memcpy_fromio(bounce, _src, MEMCPY_BOUNCE_SIZE);
memcpy_toio(_dst, bounce, MEMCPY_BOUNCE_SIZE);
}
}
}
#ifdef CONFIG_X86
static DEFINE_STATIC_KEY_FALSE(has_movntdqa);
static void __memcpy_ntdqa(void *dst, const void *src, unsigned long len)
{
kernel_fpu_begin();
while (len >= 4) {
asm("movntdqa (%0), %%xmm0\n"
"movntdqa 16(%0), %%xmm1\n"
"movntdqa 32(%0), %%xmm2\n"
"movntdqa 48(%0), %%xmm3\n"
"movaps %%xmm0, (%1)\n"
"movaps %%xmm1, 16(%1)\n"
"movaps %%xmm2, 32(%1)\n"
"movaps %%xmm3, 48(%1)\n"
:: "r" (src), "r" (dst) : "memory");
src += 64;
dst += 64;
len -= 4;
}
while (len--) {
asm("movntdqa (%0), %%xmm0\n"
"movaps %%xmm0, (%1)\n"
:: "r" (src), "r" (dst) : "memory");
src += 16;
dst += 16;
}
kernel_fpu_end();
}
/*
* __drm_memcpy_from_wc copies @len bytes from @src to @dst using
* non-temporal instructions where available. Note that all arguments
* (@src, @dst) must be aligned to 16 bytes and @len must be a multiple
* of 16.
*/
static void __drm_memcpy_from_wc(void *dst, const void *src, unsigned long len)
{
if (unlikely(((unsigned long)dst | (unsigned long)src | len) & 15))
memcpy(dst, src, len);
else if (likely(len))
__memcpy_ntdqa(dst, src, len >> 4);
}
/**
* drm_memcpy_from_wc - Perform the fastest available memcpy from a source
* that may be WC.
* @dst: The destination pointer
* @src: The source pointer
* @len: The size of the area o transfer in bytes
*
* Tries an arch optimized memcpy for prefetching reading out of a WC region,
* and if no such beast is available, falls back to a normal memcpy.
*/
void drm_memcpy_from_wc(struct iosys_map *dst,
const struct iosys_map *src,
unsigned long len)
{
if (WARN_ON(in_interrupt())) {
memcpy_fallback(dst, src, len);
return;
}
if (static_branch_likely(&has_movntdqa)) {
__drm_memcpy_from_wc(dst->is_iomem ?
(void __force *)dst->vaddr_iomem :
dst->vaddr,
src->is_iomem ?
(void const __force *)src->vaddr_iomem :
src->vaddr,
len);
return;
}
memcpy_fallback(dst, src, len);
}
EXPORT_SYMBOL(drm_memcpy_from_wc);
/*
* drm_memcpy_init_early - One time initialization of the WC memcpy code
*/
void drm_memcpy_init_early(void)
{
/*
* Some hypervisors (e.g. KVM) don't support VEX-prefix instructions
* emulation. So don't enable movntdqa in hypervisor guest.
*/
if (static_cpu_has(X86_FEATURE_XMM4_1) &&
!boot_cpu_has(X86_FEATURE_HYPERVISOR))
static_branch_enable(&has_movntdqa);
}
#else
void drm_memcpy_from_wc(struct iosys_map *dst,
const struct iosys_map *src,
unsigned long len)
{
WARN_ON(in_interrupt());
memcpy_fallback(dst, src, len);
}
EXPORT_SYMBOL(drm_memcpy_from_wc);
void drm_memcpy_init_early(void)
{
}
#endif /* CONFIG_X86 */