aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/omapdrm/omap_gem.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-05-25 16:18:27 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2022-05-25 16:18:27 -0700
commit2518f226c60d8e04d18ba4295500a5b0b8ac7659 (patch)
treee74de5ca0db01398cbb0c34376f74a81d7583c75 /drivers/gpu/drm/omapdrm/omap_gem.c
parentMerge tag 'devicetree-for-5.19' of git://git.kernel.org/pub/scm/linux/kernel/... (diff)
parentMerge tag 'drm-intel-next-fixes-2022-05-24' of git://anongit.freedesktop.org/... (diff)
downloadlinux-2518f226c60d8e04d18ba4295500a5b0b8ac7659.tar.gz
linux-2518f226c60d8e04d18ba4295500a5b0b8ac7659.zip
Merge tag 'drm-next-2022-05-25' of git://anongit.freedesktop.org/drm/drm
Pull drm updates from Dave Airlie: "Intel have enabled DG2 on certain SKUs for laptops, AMD has started some new GPU support, msm has user allocated VA controls dma-buf: - add dma_resv_replace_fences - add dma_resv_get_singleton - make dma_excl_fence private core: - EDID parser refactorings - switch drivers to drm_mode_copy/duplicate - DRM managed mutex initialization display-helper: - put HDMI, SCDC, HDCP, DSC and DP into new module gem: - rework fence handling ttm: - rework bulk move handling - add common debugfs for resource managers - convert to kvcalloc format helpers: - support monochrome formats - RGB888, RGB565 to XRGB8888 conversions fbdev: - cfb/sys_imageblit fixes - pagelist corruption fix - create offb platform device - deferred io improvements sysfb: - Kconfig rework - support for VESA mode selection bridge: - conversions to devm_drm_of_get_bridge - conversions to panel_bridge - analogix_dp - autosuspend support - it66121 - audio support - tc358767 - DSI to DPI support - icn6211 - PLL/I2C fixes, DT property - adv7611 - enable DRM_BRIDGE_OP_HPD - anx7625 - fill ELD if no monitor - dw_hdmi - add audio support - lontium LT9211 support, i.MXMP LDB - it6505: Kconfig fix, DPCD set power fix - adv7511 - CEC support for ADV7535 panel: - ltk035c5444t, B133UAN01, NV3052C panel support - DataImage FG040346DSSWBG04 support - st7735r - DT bindings fix - ssd130x - fixes i915: - DG2 laptop PCI-IDs ("motherboard down") - Initial RPL-P PCI IDs - compute engine ABI - DG2 Tile4 support - DG2 CCS clear color compression support - DG2 render/media compression formats support - ATS-M platform info - RPL-S PCI IDs added - Bump ADL-P DMC version to v2.16 - Support static DRRS - Support multiple eDP/LVDS native mode refresh rates - DP HDR support for HSW+ - Lots of display refactoring + fixes - GuC hwconfig support and query - sysfs support for multi-tile - fdinfo per-client gpu utilisation - add geometry subslices query - fix prime mmap with LMEM - fix vm open count and remove vma refcounts - contiguous allocation fixes - steered register write support - small PCI BAR enablement - GuC error capture support - sunset igpu legacy mmap support for newer devices - GuC version 70.1.1 support amdgpu: - Initial SoC21 support - SMU 13.x enablement - SMU 13.0.4 support - ttm_eu cleanups - USB-C, GPUVM updates - TMZ fixes for RV - RAS support for VCN - PM sysfs code cleanup - DC FP rework - extend CG/PG flags to 64-bit - SI dpm lockdep fix - runtime PM fixes amdkfd: - RAS/SVM fixes - TLB flush fixes - CRIU GWS support - ignore bogus MEC signals more efficiently msm: - Fourcc modifier for tiled but not compressed layouts - Support for userspace allocated IOVA (GPU virtual address) - DPU: DSC (Display Stream Compression) support - DP: eDP support - DP: conversion to use drm_bridge and drm_bridge_connector - Merge DPU1 and MDP5 MDSS driver - DPU: writeback support nouveau: - make some structures static - make some variables static - switch to drm_gem_plane_helper_prepare_fb radeon: - misc fixes/cleanups mxsfb: - rework crtc mode setting - LCDIF CRC support etnaviv: - fencing improvements - fix address space collisions - cleanup MMU reference handling gma500: - GEM/GTT improvements - connector handling fixes komeda: - switch to plane reset helper mediatek: - MIPI DSI improvements omapdrm: - GEM improvements qxl: - aarch64 support vc4: - add a CL submission tracepoint - HDMI YUV support - HDMI/clock improvements - drop is_hdmi caching virtio: - remove restriction of non-zero blob types vmwgfx: - support for cursormob and cursorbypass 4 - fence improvements tidss: - reset DISPC on startup solomon: - SPI support - DT improvements sun4i: - allwinner D1 support - drop is_hdmi caching imx: - use swap() instead of open-coding - use devm_platform_ioremap_resource - remove redunant initializations ast: - Displayport support rockchip: - Refactor IOMMU initialisation - make some structures static - replace drm_detect_hdmi_monitor with drm_display_info.is_hdmi - support swapped YUV formats, - clock improvements - rk3568 support - VOP2 support mediatek: - MT8186 support tegra: - debugabillity improvements" * tag 'drm-next-2022-05-25' of git://anongit.freedesktop.org/drm/drm: (1740 commits) drm/i915/dsi: fix VBT send packet port selection for ICL+ drm/i915/uc: Fix undefined behavior due to shift overflowing the constant drm/i915/reg: fix undefined behavior due to shift overflowing the constant drm/i915/gt: Fix use of static in macro mismatch drm/i915/audio: fix audio code enable/disable pipe logging drm/i915: Fix CFI violation with show_dynamic_id() drm/i915: Fix 'mixing different enum types' warnings in intel_display_power.c drm/i915/gt: Fix build error without CONFIG_PM drm/msm/dpu: handle pm_runtime_get_sync() errors in bind path drm/msm/dpu: add DRM_MODE_ROTATE_180 back to supported rotations drm/msm: don't free the IRQ if it was not requested drm/msm/dpu: limit writeback modes according to max_linewidth drm/amd: Don't reset dGPUs if the system is going to s2idle drm/amdgpu: Unmap legacy queue when MES is enabled drm: msm: fix possible memory leak in mdp5_crtc_cursor_set() drm/msm: Fix fb plane offset calculation drm/msm/a6xx: Fix refcount leak in a6xx_gpu_init drm/msm/dsi: don't powerup at modeset time for parade-ps8640 drm/rockchip: Change register space names in vop2 dt-bindings: display: rockchip: make reg-names mandatory for VOP2 ...
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_gem.c')
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem.c198
1 files changed, 113 insertions, 85 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index b0fa17409b66..cf571796fd26 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -38,7 +38,7 @@ struct omap_gem_object {
/** roll applied when mapping to DMM */
u32 roll;
- /** protects dma_addr_cnt, block, pages, dma_addrs and vaddr */
+ /** protects pin_cnt, block, pages, dma_addrs and vaddr */
struct mutex lock;
/**
@@ -50,24 +50,24 @@ struct omap_gem_object {
* - buffers imported from dmabuf (with the OMAP_BO_MEM_DMABUF flag set)
* if they are physically contiguous (when sgt->orig_nents == 1)
*
- * - buffers mapped through the TILER when dma_addr_cnt is not zero, in
- * which case the DMA address points to the TILER aperture
+ * - buffers mapped through the TILER when pin_cnt is not zero, in which
+ * case the DMA address points to the TILER aperture
*
* Physically contiguous buffers have their DMA address equal to the
* physical address as we don't remap those buffers through the TILER.
*
* Buffers mapped to the TILER have their DMA address pointing to the
- * TILER aperture. As TILER mappings are refcounted (through
- * dma_addr_cnt) the DMA address must be accessed through omap_gem_pin()
- * to ensure that the mapping won't disappear unexpectedly. References
- * must be released with omap_gem_unpin().
+ * TILER aperture. As TILER mappings are refcounted (through pin_cnt)
+ * the DMA address must be accessed through omap_gem_pin() to ensure
+ * that the mapping won't disappear unexpectedly. References must be
+ * released with omap_gem_unpin().
*/
dma_addr_t dma_addr;
/**
- * # of users of dma_addr
+ * # of users
*/
- refcount_t dma_addr_cnt;
+ refcount_t pin_cnt;
/**
* If the buffer has been imported from a dmabuf the OMAP_DB_DMABUF flag
@@ -750,6 +750,46 @@ void omap_gem_dma_sync_buffer(struct drm_gem_object *obj,
}
}
+static int omap_gem_pin_tiler(struct drm_gem_object *obj)
+{
+ struct omap_gem_object *omap_obj = to_omap_bo(obj);
+ u32 npages = obj->size >> PAGE_SHIFT;
+ enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
+ struct tiler_block *block;
+ int ret;
+
+ BUG_ON(omap_obj->block);
+
+ if (omap_obj->flags & OMAP_BO_TILED_MASK) {
+ block = tiler_reserve_2d(fmt, omap_obj->width, omap_obj->height,
+ PAGE_SIZE);
+ } else {
+ block = tiler_reserve_1d(obj->size);
+ }
+
+ if (IS_ERR(block)) {
+ ret = PTR_ERR(block);
+ dev_err(obj->dev->dev, "could not remap: %d (%d)\n", ret, fmt);
+ goto fail;
+ }
+
+ /* TODO: enable async refill.. */
+ ret = tiler_pin(block, omap_obj->pages, npages, omap_obj->roll, true);
+ if (ret) {
+ tiler_release(block);
+ dev_err(obj->dev->dev, "could not pin: %d\n", ret);
+ goto fail;
+ }
+
+ omap_obj->dma_addr = tiler_ssptr(block);
+ omap_obj->block = block;
+
+ DBG("got dma address: %pad", &omap_obj->dma_addr);
+
+fail:
+ return ret;
+}
+
/**
* omap_gem_pin() - Pin a GEM object in memory
* @obj: the GEM object
@@ -772,63 +812,30 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr)
mutex_lock(&omap_obj->lock);
- if (!omap_gem_is_contiguous(omap_obj) && priv->has_dmm) {
- if (refcount_read(&omap_obj->dma_addr_cnt) == 0) {
- u32 npages = obj->size >> PAGE_SHIFT;
- enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
- struct tiler_block *block;
-
- BUG_ON(omap_obj->block);
+ if (!omap_gem_is_contiguous(omap_obj)) {
+ if (refcount_read(&omap_obj->pin_cnt) == 0) {
- refcount_set(&omap_obj->dma_addr_cnt, 1);
+ refcount_set(&omap_obj->pin_cnt, 1);
ret = omap_gem_attach_pages(obj);
if (ret)
goto fail;
- if (omap_obj->flags & OMAP_BO_TILED_MASK) {
- block = tiler_reserve_2d(fmt,
- omap_obj->width,
- omap_obj->height, PAGE_SIZE);
- } else {
- block = tiler_reserve_1d(obj->size);
- }
-
- if (IS_ERR(block)) {
- ret = PTR_ERR(block);
- dev_err(obj->dev->dev,
- "could not remap: %d (%d)\n", ret, fmt);
- goto fail;
- }
-
- /* TODO: enable async refill.. */
- ret = tiler_pin(block, omap_obj->pages, npages,
- omap_obj->roll, true);
- if (ret) {
- tiler_release(block);
- dev_err(obj->dev->dev,
- "could not pin: %d\n", ret);
- goto fail;
+ if (omap_obj->flags & OMAP_BO_SCANOUT) {
+ if (priv->has_dmm) {
+ ret = omap_gem_pin_tiler(obj);
+ if (ret)
+ goto fail;
+ }
}
-
- omap_obj->dma_addr = tiler_ssptr(block);
- omap_obj->block = block;
-
- DBG("got dma address: %pad", &omap_obj->dma_addr);
} else {
- refcount_inc(&omap_obj->dma_addr_cnt);
+ refcount_inc(&omap_obj->pin_cnt);
}
-
- if (dma_addr)
- *dma_addr = omap_obj->dma_addr;
- } else if (omap_gem_is_contiguous(omap_obj)) {
- if (dma_addr)
- *dma_addr = omap_obj->dma_addr;
- } else {
- ret = -EINVAL;
- goto fail;
}
+ if (dma_addr)
+ *dma_addr = omap_obj->dma_addr;
+
fail:
mutex_unlock(&omap_obj->lock);
@@ -847,27 +854,31 @@ static void omap_gem_unpin_locked(struct drm_gem_object *obj)
struct omap_gem_object *omap_obj = to_omap_bo(obj);
int ret;
- if (omap_gem_is_contiguous(omap_obj) || !priv->has_dmm)
+ if (omap_gem_is_contiguous(omap_obj))
return;
- if (refcount_dec_and_test(&omap_obj->dma_addr_cnt)) {
+ if (refcount_dec_and_test(&omap_obj->pin_cnt)) {
if (omap_obj->sgt) {
sg_free_table(omap_obj->sgt);
kfree(omap_obj->sgt);
omap_obj->sgt = NULL;
}
- ret = tiler_unpin(omap_obj->block);
- if (ret) {
- dev_err(obj->dev->dev,
- "could not unpin pages: %d\n", ret);
- }
- ret = tiler_release(omap_obj->block);
- if (ret) {
- dev_err(obj->dev->dev,
- "could not release unmap: %d\n", ret);
+ if (!(omap_obj->flags & OMAP_BO_SCANOUT))
+ return;
+ if (priv->has_dmm) {
+ ret = tiler_unpin(omap_obj->block);
+ if (ret) {
+ dev_err(obj->dev->dev,
+ "could not unpin pages: %d\n", ret);
+ }
+ ret = tiler_release(omap_obj->block);
+ if (ret) {
+ dev_err(obj->dev->dev,
+ "could not release unmap: %d\n", ret);
+ }
+ omap_obj->dma_addr = 0;
+ omap_obj->block = NULL;
}
- omap_obj->dma_addr = 0;
- omap_obj->block = NULL;
}
}
@@ -900,7 +911,7 @@ int omap_gem_rotated_dma_addr(struct drm_gem_object *obj, u32 orient,
mutex_lock(&omap_obj->lock);
- if ((refcount_read(&omap_obj->dma_addr_cnt) > 0) && omap_obj->block &&
+ if ((refcount_read(&omap_obj->pin_cnt) > 0) && omap_obj->block &&
(omap_obj->flags & OMAP_BO_TILED_MASK)) {
*dma_addr = tiler_tsptr(omap_obj->block, orient, x, y);
ret = 0;
@@ -968,7 +979,8 @@ int omap_gem_put_pages(struct drm_gem_object *obj)
return 0;
}
-struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj)
+struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj,
+ enum dma_data_direction dir)
{
struct omap_gem_object *omap_obj = to_omap_bo(obj);
dma_addr_t addr;
@@ -993,28 +1005,44 @@ struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj)
goto err_unpin;
}
- if (omap_obj->flags & OMAP_BO_TILED_MASK) {
- enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
+ if (addr) {
+ if (omap_obj->flags & OMAP_BO_TILED_MASK) {
+ enum tiler_fmt fmt = gem2fmt(omap_obj->flags);
- len = omap_obj->width << (int)fmt;
- count = omap_obj->height;
- stride = tiler_stride(fmt, 0);
+ len = omap_obj->width << (int)fmt;
+ count = omap_obj->height;
+ stride = tiler_stride(fmt, 0);
+ } else {
+ len = obj->size;
+ count = 1;
+ stride = 0;
+ }
} else {
- len = obj->size;
- count = 1;
- stride = 0;
+ count = obj->size >> PAGE_SHIFT;
}
ret = sg_alloc_table(sgt, count, GFP_KERNEL);
if (ret)
goto err_free;
- for_each_sg(sgt->sgl, sg, count, i) {
- sg_set_page(sg, phys_to_page(addr), len, offset_in_page(addr));
- sg_dma_address(sg) = addr;
- sg_dma_len(sg) = len;
+ /* this must be after omap_gem_pin() to ensure we have pages attached */
+ omap_gem_dma_sync_buffer(obj, dir);
- addr += stride;
+ if (addr) {
+ for_each_sg(sgt->sgl, sg, count, i) {
+ sg_set_page(sg, phys_to_page(addr), len,
+ offset_in_page(addr));
+ sg_dma_address(sg) = addr;
+ sg_dma_len(sg) = len;
+
+ addr += stride;
+ }
+ } else {
+ for_each_sg(sgt->sgl, sg, count, i) {
+ sg_set_page(sg, omap_obj->pages[i], PAGE_SIZE, 0);
+ sg_dma_address(sg) = omap_obj->dma_addrs[i];
+ sg_dma_len(sg) = PAGE_SIZE;
+ }
}
omap_obj->sgt = sgt;
@@ -1124,7 +1152,7 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m)
seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d",
omap_obj->flags, obj->name, kref_read(&obj->refcount),
off, &omap_obj->dma_addr,
- refcount_read(&omap_obj->dma_addr_cnt),
+ refcount_read(&omap_obj->pin_cnt),
omap_obj->vaddr, omap_obj->roll);
if (omap_obj->flags & OMAP_BO_TILED_MASK) {
@@ -1187,7 +1215,7 @@ static void omap_gem_free_object(struct drm_gem_object *obj)
mutex_lock(&omap_obj->lock);
/* The object should not be pinned. */
- WARN_ON(refcount_read(&omap_obj->dma_addr_cnt) > 0);
+ WARN_ON(refcount_read(&omap_obj->pin_cnt) > 0);
if (omap_obj->pages) {
if (omap_obj->flags & OMAP_BO_MEM_DMABUF)