diff options
author | Dave Airlie <airlied@redhat.com> | 2020-11-04 10:55:11 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2020-11-04 11:49:10 +1000 |
commit | 1cd260a7905e3ba2e5dfa39b110ad6cf8f466f49 (patch) | |
tree | bfb701fdb0fcb32f8e6e53fb1692361c8fa33a6a /drivers/gpu/drm/drm_gem_vram_helper.c | |
parent | 3cea11cd5e3b00d91caf0b4730194039b45c5891 (diff) | |
parent | 4dfec0d1d7b9970f36931de714b379dbeaed83f8 (diff) |
Merge tag 'drm-misc-next-2020-10-27' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 5.11:
UAPI Changes:
- doc: rules for EBUSY on non-blocking commits; requirements for fourcc
modifiers; on parsing EDID
- fbdev/sbuslib: Remove unused FBIOSCURSOR32
- fourcc: deprecate DRM_FORMAT_MOD_NONE
- virtio: Support blob resources for memory allocations; Expose host-visible
and cross-device features
Cross-subsystem Changes:
- devicetree: Add vendor Prefix for Yes Optoelectronics, Shanghai Top Display
Optoelectronics
- dma-buf: Add struct dma_buf_map that stores DMA pointer and I/O-memory flag;
dma_buf_vmap()/vunmap() return address in dma_buf_map; Use struct_size() macro
Core Changes:
- atomic: pass full state to CRTC atomic enable/disable; warn for EBUSY during
non-blocking commits
- dp: Prepare for DP 2.0 DPCD
- dp_mst: Receive extended DPCD caps
- dma-buf: Documentation
- doc: Format modifiers; dma-buf-map; Cleanups
- fbdev: Don't use compat_alloc_user_space(); mark as orphaned
- fb-helper: Take lock in drm_fb_helper_restore_work_fb()
- gem: Convert implementation and drivers to GEM object functions, remove
GEM callbacks from struct drm_driver (expect gem_prime_mmap)
- panel: Cleanups
- pci: Add legacy infix to drm_irq_by_busid()
- sched: Avoid infinite waits in drm_sched_entity_destroy()
- switcheroo: Cleanups
- ttm: Remove AGP support; Don't modify caching during swapout; Major
refactoring of the implementation and API that affects all depending
drivers; Add ttm_bo_wait_ctx(); Add ttm_bo_pin()/unpin() in favor of
TTM_PL_FLAG_NO_EVICT; Remove ttm_bo_create(); Remove fault_reserve_notify()
callback; Push move() implementation into drivers; Remove TTM_PAGE_FLAG_WRITE;
Replace caching flags with init-time cache setting; Push ttm_tt_bind() into
drivers; Replace move_notify() with delete_mem_notify(); No overlapping memcpy();
no more ttm_set_populated()
- vram-helper: Fix BO top-down placement; TTM-related changes; Init GEM
object functions with defaults; Default placement in system memory; Cleanups
Driver Changes:
- amdgpu: Use GEM object functions
- armada: Use GEM object functions
- aspeed: Configure output via sysfs; Init struct drm_driver with
- ast: Reload LUT after FB format changes
- bridge: Add driver and DT bindings for anx7625; Cleanups
- bridge/dw-hdmi: Constify ops
- bridge/ti-sn65dsi86: Add retries for link training
- bridge/lvds-codec: Add support for regulator
- bridge/tc358768: Restore connector support DRM_GEM_CMA_DRIVEROPS; Cleanups
- display/ti,j721e-dss: Add DT properies assigned-clocks, assigned-clocks-parent and
dma-coherent
- display/ti,am65s-dss: Add DT properies assigned-clocks, assigned-clocks-parent and
dma-coherent
- etnaviv: Use GEM object functions
- exynos: Use GEM object functions
- fbdev: Cleanups and compiler fixes throughout framebuffer drivers
- fbdev/cirrusfb: Avoid division by 0
- gma500: Use GEM object functions; Fix double-free of connector; Cleanups
- hisilicon/hibmc: I2C-based DDC support; Use to_hibmc_drm_device(); Cleanups
- i915: Use GEM object functions
- imx/dcss: Init driver with DRM_GEM_CMA_DRIVER_OPS; Cleanups
- ingenic: Reset pixel clock when parent clock changes; support reserved
memory; Alloc F0 and F1 DMA channels at once; Support different pixel formats;
Revert support for cached mmap buffers
on F0/F1; support 30-bit/24-bit/8-bit-palette modes
- komeda: Use DEFINE_SHOW_ATTRIBUTE
- mcde: Detect platform_get_irq() errors
- mediatek: Use GEM object functions
- msm: Use GEM object functions
- nouveau: Cleanups; TTM-related changes; Use GEM object functions
- omapdrm: Use GEM object functions
- panel: Add driver and DT bindings for Novatak nt36672a; Add driver and DT
bindings for YTC700TLAG-05-201C; Add driver and DT bindings for TDO TL070WSH30;
Cleanups
- panel/mantix: Fix reset; Fix deref of NULL pointer in mantix_get_modes()
- panel/otm8009a: Allow non-continuous dsi clock; Cleanups
- panel/rm68200: Allow non-continuous dsi clock; Fix mode to 50 FPS
- panfrost: Fix job timeout handling; Cleanups
- pl111: Use GEM object functions
- qxl: Cleanups; TTM-related changes; Pin new BOs with ttm_bo_init_reserved()
- radeon: Cleanups; TTM-related changes; Use GEM object functions
- rockchip: Use GEM object functions
- shmobile: Cleanups
- tegra: Use GEM object functions
- tidss: Set drm_plane_helper_funcs.prepare_fb
- tilcdc: Don't keep vblank interrupt enabled all the time
- tve200: Detect platform_get_irq() errors
- vc4: Use GEM object functions; Only register components once DSI is attached;
Add Maxime as maintainer
- vgem: Use GEM object functions
- via: Simplify critical section in via_mem_alloc()
- virtgpu: Use GEM object functions
- virtio: Implement blob resources, host-visible and cross-device features;
Support mapping of host-allocated resources; Use UUID APi; Cleanups
- vkms: Use GEM object functions; Switch to SHMEM
- vmwgfx: TTM-related changes; Inline ttm_bo_swapout_all()
- xen: Use GEM object functions
- xlnx: Use GEM object functions
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Thomas Zimmermann <tzimmermann@suse.de>
Link: https://patchwork.freedesktop.org/patch/msgid/20201027100936.GA4858@linux-uq9g
Diffstat (limited to 'drivers/gpu/drm/drm_gem_vram_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_gem_vram_helper.c | 175 |
1 files changed, 85 insertions, 90 deletions
diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 50cad0e4a92e..9da823eb0edd 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -140,22 +140,19 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, unsigned int c = 0; if (pl_flag & DRM_GEM_VRAM_PL_FLAG_TOPDOWN) - pl_flag = TTM_PL_FLAG_TOPDOWN; + invariant_flags = TTM_PL_FLAG_TOPDOWN; gbo->placement.placement = gbo->placements; gbo->placement.busy_placement = gbo->placements; if (pl_flag & DRM_GEM_VRAM_PL_FLAG_VRAM) { gbo->placements[c].mem_type = TTM_PL_VRAM; - gbo->placements[c++].flags = TTM_PL_FLAG_WC | - TTM_PL_FLAG_UNCACHED | - invariant_flags; + gbo->placements[c++].flags = invariant_flags; } if (pl_flag & DRM_GEM_VRAM_PL_FLAG_SYSTEM || !c) { gbo->placements[c].mem_type = TTM_PL_SYSTEM; - gbo->placements[c++].flags = TTM_PL_MASK_CACHING | - invariant_flags; + gbo->placements[c++].flags = invariant_flags; } gbo->placement.num_placement = c; @@ -167,58 +164,18 @@ static void drm_gem_vram_placement(struct drm_gem_vram_object *gbo, } } -/* - * Note that on error, drm_gem_vram_init will free the buffer object. - */ - -static int drm_gem_vram_init(struct drm_device *dev, - struct drm_gem_vram_object *gbo, - size_t size, unsigned long pg_align) -{ - struct drm_vram_mm *vmm = dev->vram_mm; - struct ttm_bo_device *bdev; - int ret; - size_t acc_size; - - if (WARN_ONCE(!vmm, "VRAM MM not initialized")) { - kfree(gbo); - return -EINVAL; - } - bdev = &vmm->bdev; - - gbo->bo.base.funcs = &drm_gem_vram_object_funcs; - - ret = drm_gem_object_init(dev, &gbo->bo.base, size); - if (ret) { - kfree(gbo); - return ret; - } - - acc_size = ttm_bo_dma_acc_size(bdev, size, sizeof(*gbo)); - - gbo->bo.bdev = bdev; - drm_gem_vram_placement(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM | - DRM_GEM_VRAM_PL_FLAG_SYSTEM); - - ret = ttm_bo_init(bdev, &gbo->bo, size, ttm_bo_type_device, - &gbo->placement, pg_align, false, acc_size, - NULL, NULL, ttm_buffer_object_destroy); - if (ret) - /* - * A failing ttm_bo_init will call ttm_buffer_object_destroy - * to release gbo->bo.base and kfree gbo. - */ - return ret; - - return 0; -} - /** * drm_gem_vram_create() - Creates a VRAM-backed GEM object * @dev: the DRM device * @size: the buffer size in bytes * @pg_align: the buffer's alignment in multiples of the page size * + * GEM objects are allocated by calling struct drm_driver.gem_create_object, + * if set. Otherwise kzalloc() will be used. Drivers can set their own GEM + * object functions in struct drm_driver.gem_create_object. If no functions + * are set, the new GEM object will use the default functions from GEM VRAM + * helpers. + * * Returns: * A new instance of &struct drm_gem_vram_object on success, or * an ERR_PTR()-encoded error code otherwise. @@ -228,11 +185,17 @@ struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, unsigned long pg_align) { struct drm_gem_vram_object *gbo; + struct drm_gem_object *gem; + struct drm_vram_mm *vmm = dev->vram_mm; + struct ttm_bo_device *bdev; int ret; + size_t acc_size; + + if (WARN_ONCE(!vmm, "VRAM MM not initialized")) + return ERR_PTR(-EINVAL); if (dev->driver->gem_create_object) { - struct drm_gem_object *gem = - dev->driver->gem_create_object(dev, size); + gem = dev->driver->gem_create_object(dev, size); if (!gem) return ERR_PTR(-ENOMEM); gbo = drm_gem_vram_of_gem(gem); @@ -240,10 +203,32 @@ struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev, gbo = kzalloc(sizeof(*gbo), GFP_KERNEL); if (!gbo) return ERR_PTR(-ENOMEM); + gem = &gbo->bo.base; } - ret = drm_gem_vram_init(dev, gbo, size, pg_align); - if (ret < 0) + if (!gem->funcs) + gem->funcs = &drm_gem_vram_object_funcs; + + ret = drm_gem_object_init(dev, gem, size); + if (ret) { + kfree(gbo); + return ERR_PTR(ret); + } + + bdev = &vmm->bdev; + acc_size = ttm_bo_dma_acc_size(bdev, size, sizeof(*gbo)); + + gbo->bo.bdev = bdev; + drm_gem_vram_placement(gbo, DRM_GEM_VRAM_PL_FLAG_SYSTEM); + + /* + * A failing ttm_bo_init will call ttm_buffer_object_destroy + * to release gbo->bo.base and kfree gbo. + */ + ret = ttm_bo_init(bdev, &gbo->bo, size, ttm_bo_type_device, + &gbo->placement, pg_align, false, acc_size, + NULL, NULL, ttm_buffer_object_destroy); + if (ret) return ERR_PTR(ret); return gbo; @@ -301,7 +286,7 @@ static u64 drm_gem_vram_pg_offset(struct drm_gem_vram_object *gbo) */ s64 drm_gem_vram_offset(struct drm_gem_vram_object *gbo) { - if (WARN_ON_ONCE(!gbo->pin_count)) + if (WARN_ON_ONCE(!gbo->bo.pin_count)) return (s64)-ENODEV; return drm_gem_vram_pg_offset(gbo) << PAGE_SHIFT; } @@ -310,24 +295,21 @@ EXPORT_SYMBOL(drm_gem_vram_offset); static int drm_gem_vram_pin_locked(struct drm_gem_vram_object *gbo, unsigned long pl_flag) { - int i, ret; struct ttm_operation_ctx ctx = { false, false }; + int ret; - if (gbo->pin_count) + if (gbo->bo.pin_count) goto out; if (pl_flag) drm_gem_vram_placement(gbo, pl_flag); - for (i = 0; i < gbo->placement.num_placement; ++i) - gbo->placements[i].flags |= TTM_PL_FLAG_NO_EVICT; - ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx); if (ret < 0) return ret; out: - ++gbo->pin_count; + ttm_bo_pin(&gbo->bo); return 0; } @@ -369,26 +351,9 @@ int drm_gem_vram_pin(struct drm_gem_vram_object *gbo, unsigned long pl_flag) } EXPORT_SYMBOL(drm_gem_vram_pin); -static int drm_gem_vram_unpin_locked(struct drm_gem_vram_object *gbo) +static void drm_gem_vram_unpin_locked(struct drm_gem_vram_object *gbo) { - int i, ret; - struct ttm_operation_ctx ctx = { false, false }; - - if (WARN_ON_ONCE(!gbo->pin_count)) - return 0; - - --gbo->pin_count; - if (gbo->pin_count) - return 0; - - for (i = 0; i < gbo->placement.num_placement ; ++i) - gbo->placements[i].flags &= ~TTM_PL_FLAG_NO_EVICT; - - ret = ttm_bo_validate(&gbo->bo, &gbo->placement, &ctx); - if (ret < 0) - return ret; - - return 0; + ttm_bo_unpin(&gbo->bo); } /** @@ -406,10 +371,11 @@ int drm_gem_vram_unpin(struct drm_gem_vram_object *gbo) ret = ttm_bo_reserve(&gbo->bo, true, false, NULL); if (ret) return ret; - ret = drm_gem_vram_unpin_locked(gbo); + + drm_gem_vram_unpin_locked(gbo); ttm_bo_unreserve(&gbo->bo); - return ret; + return 0; } EXPORT_SYMBOL(drm_gem_vram_unpin); @@ -619,6 +585,23 @@ static void drm_gem_vram_bo_driver_move_notify(struct drm_gem_vram_object *gbo, kmap->virtual = NULL; } +static int drm_gem_vram_bo_driver_move(struct drm_gem_vram_object *gbo, + bool evict, + struct ttm_operation_ctx *ctx, + struct ttm_resource *new_mem) +{ + int ret; + + drm_gem_vram_bo_driver_move_notify(gbo, evict, new_mem); + ret = ttm_bo_move_memcpy(&gbo->bo, ctx, new_mem); + if (ret) { + swap(*new_mem, gbo->bo.mem); + drm_gem_vram_bo_driver_move_notify(gbo, false, new_mem); + swap(*new_mem, gbo->bo.mem); + } + return ret; +} + /* * Helpers for struct drm_gem_object_funcs */ @@ -941,7 +924,7 @@ static struct ttm_tt *bo_driver_ttm_tt_create(struct ttm_buffer_object *bo, if (!tt) return NULL; - ret = ttm_tt_init(tt, bo, page_flags); + ret = ttm_tt_init(tt, bo, page_flags, ttm_cached); if (ret < 0) goto err_ttm_tt_init; @@ -966,9 +949,7 @@ static void bo_driver_evict_flags(struct ttm_buffer_object *bo, drm_gem_vram_bo_driver_evict_flags(gbo, placement); } -static void bo_driver_move_notify(struct ttm_buffer_object *bo, - bool evict, - struct ttm_resource *new_mem) +static void bo_driver_delete_mem_notify(struct ttm_buffer_object *bo) { struct drm_gem_vram_object *gbo; @@ -978,7 +959,19 @@ static void bo_driver_move_notify(struct ttm_buffer_object *bo, gbo = drm_gem_vram_of_bo(bo); - drm_gem_vram_bo_driver_move_notify(gbo, evict, new_mem); + drm_gem_vram_bo_driver_move_notify(gbo, false, NULL); +} + +static int bo_driver_move(struct ttm_buffer_object *bo, + bool evict, + struct ttm_operation_ctx *ctx, + struct ttm_resource *new_mem) +{ + struct drm_gem_vram_object *gbo; + + gbo = drm_gem_vram_of_bo(bo); + + return drm_gem_vram_bo_driver_move(gbo, evict, ctx, new_mem); } static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev, @@ -992,6 +985,7 @@ static int bo_driver_io_mem_reserve(struct ttm_bo_device *bdev, case TTM_PL_VRAM: mem->bus.offset = (mem->start << PAGE_SHIFT) + vmm->vram_base; mem->bus.is_iomem = true; + mem->bus.caching = ttm_write_combined; break; default: return -EINVAL; @@ -1005,7 +999,8 @@ static struct ttm_bo_driver bo_driver = { .ttm_tt_destroy = bo_driver_ttm_tt_destroy, .eviction_valuable = ttm_bo_eviction_valuable, .evict_flags = bo_driver_evict_flags, - .move_notify = bo_driver_move_notify, + .move = bo_driver_move, + .delete_mem_notify = bo_driver_delete_mem_notify, .io_mem_reserve = bo_driver_io_mem_reserve, }; |