From 3551a9fa2c5d3f3b0a34af67d33a0f2a5fecd94c Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 2 Aug 2019 13:57:27 -0600 Subject: drm/panfrost: Remove completed features still in TODO There's a few features the driver supports which we forgot to remove, so remove them now. Cc: Tomeu Vizoso Signed-off-by: Rob Herring Reviewed-by: Boris Brezillon Link: https://patchwork.freedesktop.org/patch/msgid/20190802195727.1963-1-robh@kernel.org --- drivers/gpu/drm/panfrost/TODO | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panfrost/TODO b/drivers/gpu/drm/panfrost/TODO index c2e44add37d8..a01eae4bd8ba 100644 --- a/drivers/gpu/drm/panfrost/TODO +++ b/drivers/gpu/drm/panfrost/TODO @@ -6,10 +6,6 @@ - Bifrost specific feature and issue handling - Coherent DMA support -- Support for 2MB pages. The io-pgtable code already supports this. Finishing - support involves either copying or adapting the iommu API to handle passing - aligned addresses and sizes to the io-pgtable code. - - Per FD address space support. The h/w supports multiple addresses spaces. The hard part is handling when more address spaces are needed than what the h/w provides. @@ -22,6 +18,3 @@ - Compute job support. So called 'compute only' jobs need to be plumbed up to userspace. - -- Performance counter support. (Boris) - -- cgit v1.2.3 From 17acb9f35ed736c177f85b8ee711f278e7aff421 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 5 Aug 2019 08:33:57 -0600 Subject: drm/shmem: Add madvise state and purge helpers Add support to the shmem GEM helpers for tracking madvise state and purging pages. This is based on the msm implementation. The BO provides a list_head, but the list management is handled outside of the shmem helpers as there are different locking requirements. Cc: Tomeu Vizoso Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Sean Paul Cc: David Airlie Cc: Daniel Vetter Cc: Eric Anholt Acked-by: Acked-by: Alyssa Rosenzweig Signed-off-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20190805143358.21245-1-robh@kernel.org --- drivers/gpu/drm/drm_gem_shmem_helper.c | 57 ++++++++++++++++++++++++++++++++++ include/drm/drm_gem_shmem_helper.h | 15 +++++++++ 2 files changed, 72 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index 2f64667ac805..4b442576de1c 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -75,6 +75,7 @@ struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t shmem = to_drm_gem_shmem_obj(obj); mutex_init(&shmem->pages_lock); mutex_init(&shmem->vmap_lock); + INIT_LIST_HEAD(&shmem->madv_list); /* * Our buffers are kept pinned, so allocating them @@ -362,6 +363,62 @@ drm_gem_shmem_create_with_handle(struct drm_file *file_priv, } EXPORT_SYMBOL(drm_gem_shmem_create_with_handle); +/* Update madvise status, returns true if not purged, else + * false or -errno. + */ +int drm_gem_shmem_madvise(struct drm_gem_object *obj, int madv) +{ + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); + + mutex_lock(&shmem->pages_lock); + + if (shmem->madv >= 0) + shmem->madv = madv; + + madv = shmem->madv; + + mutex_unlock(&shmem->pages_lock); + + return (madv >= 0); +} +EXPORT_SYMBOL(drm_gem_shmem_madvise); + +void drm_gem_shmem_purge_locked(struct drm_gem_object *obj) +{ + struct drm_device *dev = obj->dev; + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); + + WARN_ON(!drm_gem_shmem_is_purgeable(shmem)); + + drm_gem_shmem_put_pages_locked(shmem); + + shmem->madv = -1; + + drm_vma_node_unmap(&obj->vma_node, dev->anon_inode->i_mapping); + drm_gem_free_mmap_offset(obj); + + /* Our goal here is to return as much of the memory as + * is possible back to the system as we are called from OOM. + * To do this we must instruct the shmfs to drop all of its + * backing pages, *now*. + */ + shmem_truncate_range(file_inode(obj->filp), 0, (loff_t)-1); + + invalidate_mapping_pages(file_inode(obj->filp)->i_mapping, + 0, (loff_t)-1); +} +EXPORT_SYMBOL(drm_gem_shmem_purge_locked); + +void drm_gem_shmem_purge(struct drm_gem_object *obj) +{ + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); + + mutex_lock(&shmem->pages_lock); + drm_gem_shmem_purge_locked(obj); + mutex_unlock(&shmem->pages_lock); +} +EXPORT_SYMBOL(drm_gem_shmem_purge); + /** * drm_gem_shmem_dumb_create - Create a dumb shmem buffer object * @file: DRM file structure to create the dumb buffer for diff --git a/include/drm/drm_gem_shmem_helper.h b/include/drm/drm_gem_shmem_helper.h index 038b6d313447..ce1600fdfc3e 100644 --- a/include/drm/drm_gem_shmem_helper.h +++ b/include/drm/drm_gem_shmem_helper.h @@ -44,6 +44,9 @@ struct drm_gem_shmem_object { */ unsigned int pages_use_count; + int madv; + struct list_head madv_list; + /** * @pages_mark_dirty_on_put: * @@ -121,6 +124,18 @@ void drm_gem_shmem_unpin(struct drm_gem_object *obj); void *drm_gem_shmem_vmap(struct drm_gem_object *obj); void drm_gem_shmem_vunmap(struct drm_gem_object *obj, void *vaddr); +int drm_gem_shmem_madvise(struct drm_gem_object *obj, int madv); + +static inline bool drm_gem_shmem_is_purgeable(struct drm_gem_shmem_object *shmem) +{ + return (shmem->madv > 0) && + !shmem->vmap_use_count && shmem->sgt && + !shmem->base.dma_buf && !shmem->base.import_attach; +} + +void drm_gem_shmem_purge_locked(struct drm_gem_object *obj); +void drm_gem_shmem_purge(struct drm_gem_object *obj); + struct drm_gem_shmem_object * drm_gem_shmem_create_with_handle(struct drm_file *file_priv, struct drm_device *dev, size_t size, -- cgit v1.2.3 From 013b6510131568ce4e01856d5360bfdfe9c3632f Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 5 Aug 2019 08:33:58 -0600 Subject: drm/panfrost: Add madvise and shrinker support Add support for madvise and a shrinker similar to other drivers. This allows userspace to mark BOs which can be freed when there is memory pressure. Unlike other implementations, we don't depend on struct_mutex. The driver maintains a list of BOs which can be freed when the shrinker is called. Access to the list is serialized with the shrinker_lock. Cc: Tomeu Vizoso Cc: David Airlie Cc: Daniel Vetter Acked-by: Alyssa Rosenzweig Signed-off-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20190805143358.21245-2-robh@kernel.org --- drivers/gpu/drm/panfrost/Makefile | 1 + drivers/gpu/drm/panfrost/TODO | 2 - drivers/gpu/drm/panfrost/panfrost_device.h | 4 + drivers/gpu/drm/panfrost/panfrost_drv.c | 38 ++++++++ drivers/gpu/drm/panfrost/panfrost_gem.c | 5 ++ drivers/gpu/drm/panfrost/panfrost_gem.h | 3 + drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c | 107 +++++++++++++++++++++++ include/uapi/drm/panfrost_drm.h | 22 +++++ 8 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panfrost/Makefile b/drivers/gpu/drm/panfrost/Makefile index ecf0864cb515..b71935862417 100644 --- a/drivers/gpu/drm/panfrost/Makefile +++ b/drivers/gpu/drm/panfrost/Makefile @@ -5,6 +5,7 @@ panfrost-y := \ panfrost_device.o \ panfrost_devfreq.o \ panfrost_gem.o \ + panfrost_gem_shrinker.o \ panfrost_gpu.o \ panfrost_job.o \ panfrost_mmu.o \ diff --git a/drivers/gpu/drm/panfrost/TODO b/drivers/gpu/drm/panfrost/TODO index a01eae4bd8ba..d4c7fb7e7d13 100644 --- a/drivers/gpu/drm/panfrost/TODO +++ b/drivers/gpu/drm/panfrost/TODO @@ -14,7 +14,5 @@ - Support userspace controlled GPU virtual addresses. Needed for Vulkan. (Tomeu) -- Support for madvise and a shrinker. - - Compute job support. So called 'compute only' jobs need to be plumbed up to userspace. diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h index ea5948ff3647..038b32c62484 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.h +++ b/drivers/gpu/drm/panfrost/panfrost_device.h @@ -85,6 +85,10 @@ struct panfrost_device { struct mutex sched_lock; struct mutex reset_lock; + struct mutex shrinker_lock; + struct list_head shrinker_list; + struct shrinker shrinker; + struct { struct devfreq *devfreq; struct thermal_cooling_device *cooling; diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index b187daa4da85..926d021ee202 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -333,6 +333,38 @@ static int panfrost_ioctl_get_bo_offset(struct drm_device *dev, void *data, return 0; } +static int panfrost_ioctl_madvise(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_panfrost_madvise *args = data; + struct panfrost_device *pfdev = dev->dev_private; + struct drm_gem_object *gem_obj; + + gem_obj = drm_gem_object_lookup(file_priv, args->handle); + if (!gem_obj) { + DRM_DEBUG("Failed to look up GEM BO %d\n", args->handle); + return -ENOENT; + } + + args->retained = drm_gem_shmem_madvise(gem_obj, args->madv); + + if (args->retained) { + struct panfrost_gem_object *bo = to_panfrost_bo(gem_obj); + + mutex_lock(&pfdev->shrinker_lock); + + if (args->madv == PANFROST_MADV_DONTNEED) + list_add_tail(&bo->base.madv_list, &pfdev->shrinker_list); + else if (args->madv == PANFROST_MADV_WILLNEED) + list_del_init(&bo->base.madv_list); + + mutex_unlock(&pfdev->shrinker_lock); + } + + drm_gem_object_put_unlocked(gem_obj); + return 0; +} + int panfrost_unstable_ioctl_check(void) { if (!unstable_ioctls) @@ -384,6 +416,7 @@ static const struct drm_ioctl_desc panfrost_drm_driver_ioctls[] = { PANFROST_IOCTL(GET_BO_OFFSET, get_bo_offset, DRM_RENDER_ALLOW), PANFROST_IOCTL(PERFCNT_ENABLE, perfcnt_enable, DRM_RENDER_ALLOW), PANFROST_IOCTL(PERFCNT_DUMP, perfcnt_dump, DRM_RENDER_ALLOW), + PANFROST_IOCTL(MADVISE, madvise, DRM_RENDER_ALLOW), }; DEFINE_DRM_GEM_SHMEM_FOPS(panfrost_drm_driver_fops); @@ -432,6 +465,8 @@ static int panfrost_probe(struct platform_device *pdev) pfdev->ddev = ddev; spin_lock_init(&pfdev->mm_lock); + mutex_init(&pfdev->shrinker_lock); + INIT_LIST_HEAD(&pfdev->shrinker_list); /* 4G enough for now. can be 48-bit */ drm_mm_init(&pfdev->mm, SZ_32M >> PAGE_SHIFT, (SZ_4G - SZ_32M) >> PAGE_SHIFT); @@ -462,6 +497,8 @@ static int panfrost_probe(struct platform_device *pdev) if (err < 0) goto err_out1; + panfrost_gem_shrinker_init(ddev); + return 0; err_out1: @@ -478,6 +515,7 @@ static int panfrost_remove(struct platform_device *pdev) struct drm_device *ddev = pfdev->ddev; drm_dev_unregister(ddev); + panfrost_gem_shrinker_cleanup(ddev); pm_runtime_get_sync(pfdev->dev); pm_runtime_put_sync_autosuspend(pfdev->dev); pm_runtime_disable(pfdev->dev); diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index 543ab1b81bd5..67d374184340 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -26,6 +26,11 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj) drm_mm_remove_node(&bo->node); spin_unlock(&pfdev->mm_lock); + mutex_lock(&pfdev->shrinker_lock); + if (!list_empty(&bo->base.madv_list)) + list_del(&bo->base.madv_list); + mutex_unlock(&pfdev->shrinker_lock); + drm_gem_shmem_free_object(obj); } diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.h b/drivers/gpu/drm/panfrost/panfrost_gem.h index 6dbcaba020fc..5f51f881ea3f 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.h +++ b/drivers/gpu/drm/panfrost/panfrost_gem.h @@ -27,4 +27,7 @@ panfrost_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt); +void panfrost_gem_shrinker_init(struct drm_device *dev); +void panfrost_gem_shrinker_cleanup(struct drm_device *dev); + #endif /* __PANFROST_GEM_H__ */ diff --git a/drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c b/drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c new file mode 100644 index 000000000000..d191632b6197 --- /dev/null +++ b/drivers/gpu/drm/panfrost/panfrost_gem_shrinker.c @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (C) 2019 Arm Ltd. + * + * Based on msm_gem_freedreno.c: + * Copyright (C) 2016 Red Hat + * Author: Rob Clark + */ + +#include + +#include +#include + +#include "panfrost_device.h" +#include "panfrost_gem.h" +#include "panfrost_mmu.h" + +static unsigned long +panfrost_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) +{ + struct panfrost_device *pfdev = + container_of(shrinker, struct panfrost_device, shrinker); + struct drm_gem_shmem_object *shmem; + unsigned long count = 0; + + if (!mutex_trylock(&pfdev->shrinker_lock)) + return 0; + + list_for_each_entry(shmem, &pfdev->shrinker_list, madv_list) { + if (drm_gem_shmem_is_purgeable(shmem)) + count += shmem->base.size >> PAGE_SHIFT; + } + + mutex_unlock(&pfdev->shrinker_lock); + + return count; +} + +static void panfrost_gem_purge(struct drm_gem_object *obj) +{ + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj); + mutex_lock(&shmem->pages_lock); + + panfrost_mmu_unmap(to_panfrost_bo(obj)); + drm_gem_shmem_purge_locked(obj); + + mutex_unlock(&shmem->pages_lock); +} + +static unsigned long +panfrost_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) +{ + struct panfrost_device *pfdev = + container_of(shrinker, struct panfrost_device, shrinker); + struct drm_gem_shmem_object *shmem, *tmp; + unsigned long freed = 0; + + if (!mutex_trylock(&pfdev->shrinker_lock)) + return SHRINK_STOP; + + list_for_each_entry_safe(shmem, tmp, &pfdev->shrinker_list, madv_list) { + if (freed >= sc->nr_to_scan) + break; + if (drm_gem_shmem_is_purgeable(shmem)) { + panfrost_gem_purge(&shmem->base); + freed += shmem->base.size >> PAGE_SHIFT; + list_del_init(&shmem->madv_list); + } + } + + mutex_unlock(&pfdev->shrinker_lock); + + if (freed > 0) + pr_info_ratelimited("Purging %lu bytes\n", freed << PAGE_SHIFT); + + return freed; +} + +/** + * panfrost_gem_shrinker_init - Initialize panfrost shrinker + * @dev: DRM device + * + * This function registers and sets up the panfrost shrinker. + */ +void panfrost_gem_shrinker_init(struct drm_device *dev) +{ + struct panfrost_device *pfdev = dev->dev_private; + pfdev->shrinker.count_objects = panfrost_gem_shrinker_count; + pfdev->shrinker.scan_objects = panfrost_gem_shrinker_scan; + pfdev->shrinker.seeks = DEFAULT_SEEKS; + WARN_ON(register_shrinker(&pfdev->shrinker)); +} + +/** + * panfrost_gem_shrinker_cleanup - Clean up panfrost shrinker + * @dev: DRM device + * + * This function unregisters the panfrost shrinker. + */ +void panfrost_gem_shrinker_cleanup(struct drm_device *dev) +{ + struct panfrost_device *pfdev = dev->dev_private; + + if (pfdev->shrinker.nr_deferred) { + unregister_shrinker(&pfdev->shrinker); + } +} diff --git a/include/uapi/drm/panfrost_drm.h b/include/uapi/drm/panfrost_drm.h index cb577fb96b38..1e547f9692e9 100644 --- a/include/uapi/drm/panfrost_drm.h +++ b/include/uapi/drm/panfrost_drm.h @@ -20,6 +20,7 @@ extern "C" { #define DRM_PANFROST_GET_BO_OFFSET 0x05 #define DRM_PANFROST_PERFCNT_ENABLE 0x06 #define DRM_PANFROST_PERFCNT_DUMP 0x07 +#define DRM_PANFROST_MADVISE 0x08 #define DRM_IOCTL_PANFROST_SUBMIT DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_SUBMIT, struct drm_panfrost_submit) #define DRM_IOCTL_PANFROST_WAIT_BO DRM_IOW(DRM_COMMAND_BASE + DRM_PANFROST_WAIT_BO, struct drm_panfrost_wait_bo) @@ -27,6 +28,7 @@ extern "C" { #define DRM_IOCTL_PANFROST_MMAP_BO DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_MMAP_BO, struct drm_panfrost_mmap_bo) #define DRM_IOCTL_PANFROST_GET_PARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_GET_PARAM, struct drm_panfrost_get_param) #define DRM_IOCTL_PANFROST_GET_BO_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_GET_BO_OFFSET, struct drm_panfrost_get_bo_offset) +#define DRM_IOCTL_PANFROST_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_PANFROST_MADVISE, struct drm_panfrost_madvise) /* * Unstable ioctl(s): only exposed when the unsafe unstable_ioctls module @@ -198,6 +200,26 @@ struct drm_panfrost_perfcnt_dump { __u64 buf_ptr; }; +/* madvise provides a way to tell the kernel in case a buffers contents + * can be discarded under memory pressure, which is useful for userspace + * bo cache where we want to optimistically hold on to buffer allocate + * and potential mmap, but allow the pages to be discarded under memory + * pressure. + * + * Typical usage would involve madvise(DONTNEED) when buffer enters BO + * cache, and madvise(WILLNEED) if trying to recycle buffer from BO cache. + * In the WILLNEED case, 'retained' indicates to userspace whether the + * backing pages still exist. + */ +#define PANFROST_MADV_WILLNEED 0 /* backing pages are needed, status returned in 'retained' */ +#define PANFROST_MADV_DONTNEED 1 /* backing pages not needed */ + +struct drm_panfrost_madvise { + __u32 handle; /* in, GEM handle */ + __u32 madv; /* in, PANFROST_MADV_x */ + __u32 retained; /* out, whether backing store still exists */ +}; + #if defined(__cplusplus) } #endif -- cgit v1.2.3 From 43f847d0b9540dd1de4cfd626448fb4294422874 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 5 Aug 2019 10:58:44 +0200 Subject: drm/pl111: Support grayscale Migrating the TI nspire calculators to use the PL111 driver for framebuffer requires grayscale support for the elder panel which uses 8bit grayscale only. DRM does not support 8bit grayscale framebuffers in memory, but by defining the bus format to be MEDIA_BUS_FMT_Y8_1X8 we can get the hardware to turn on a grayscaling feature and convert the RGB framebuffer to grayscale for us. Cc: Daniel Tang Cc: Fabian Vogt Tested-by: Fabian Vogt Acked-by: Sam Ravnborg Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20190805085847.25554-2-linus.walleij@linaro.org --- drivers/gpu/drm/pl111/pl111_display.c | 29 +++++++++++++++++++++++++++-- include/linux/amba/clcd-regs.h | 1 + 2 files changed, 28 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index 9a153125e5d2..024771a4083e 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -128,6 +128,7 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, struct drm_framebuffer *fb = plane->state->fb; struct drm_connector *connector = priv->connector; struct drm_bridge *bridge = priv->bridge; + bool grayscale = false; u32 cntl; u32 ppl, hsw, hfp, hbp; u32 lpp, vsw, vfp, vbp; @@ -187,6 +188,20 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, if (connector->display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) tim2 |= TIM2_IPC; + + if (connector->display_info.num_bus_formats == 1 && + connector->display_info.bus_formats[0] == + MEDIA_BUS_FMT_Y8_1X8) + grayscale = true; + + /* + * The AC pin bias frequency is set to max count when using + * grayscale so at least once in a while we will reverse + * polarity and get rid of any DC built up that could + * damage the display. + */ + if (grayscale) + tim2 |= TIM2_ACB_MASK; } if (bridge) { @@ -218,8 +233,18 @@ static void pl111_display_enable(struct drm_simple_display_pipe *pipe, writel(0, priv->regs + CLCD_TIM3); - /* Hard-code TFT panel */ - cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDVCOMP(1); + /* + * Detect grayscale bus format. We do not support a grayscale mode + * toward userspace, instead we expose an RGB24 buffer and then the + * hardware will activate its grayscaler to convert to the grayscale + * format. + */ + if (grayscale) + cntl = CNTL_LCDEN | CNTL_LCDMONO8; + else + /* Else we assume TFT display */ + cntl = CNTL_LCDEN | CNTL_LCDTFT | CNTL_LCDVCOMP(1); + /* On the ST Micro variant, assume all 24 bits are connected */ if (priv->variant->st_bitmux_control) cntl |= CNTL_ST_CDWID_24; diff --git a/include/linux/amba/clcd-regs.h b/include/linux/amba/clcd-regs.h index 516a6fda83c5..421b0fa90d6a 100644 --- a/include/linux/amba/clcd-regs.h +++ b/include/linux/amba/clcd-regs.h @@ -42,6 +42,7 @@ #define TIM2_PCD_LO_MASK GENMASK(4, 0) #define TIM2_PCD_LO_BITS 5 #define TIM2_CLKSEL (1 << 5) +#define TIM2_ACB_MASK GENMASK(10, 6) #define TIM2_IVS (1 << 11) #define TIM2_IHS (1 << 12) #define TIM2_IPC (1 << 13) -- cgit v1.2.3 From d8a0d6a3b7810fe3de723505c75f7f34ee6891df Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 5 Aug 2019 10:58:46 +0200 Subject: drm/panel: simple: Support TI nspire panels This adds support for the TI nspire panels to the simple panel roster. This code is based on arch/arm/mach-nspire/clcd.c. This includes likely the first grayscale panel supported. These panels will be used with the PL11x DRM driver. Cc: Daniel Tang Cc: Fabian Vogt Tested-by: Fabian Vogt Reviewed-by: Sam Ravnborg Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20190805085847.25554-4-linus.walleij@linaro.org --- drivers/gpu/drm/panel/panel-simple.c | 64 ++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index bff7578f84dd..28fa6ba7b767 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -2833,6 +2833,64 @@ static const struct panel_desc tianma_tm070rvhg71 = { .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG, }; +static const struct drm_display_mode ti_nspire_cx_lcd_mode[] = { + { + .clock = 10000, + .hdisplay = 320, + .hsync_start = 320 + 50, + .hsync_end = 320 + 50 + 6, + .htotal = 320 + 50 + 6 + 38, + .vdisplay = 240, + .vsync_start = 240 + 3, + .vsync_end = 240 + 3 + 1, + .vtotal = 240 + 3 + 1 + 17, + .vrefresh = 60, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, + }, +}; + +static const struct panel_desc ti_nspire_cx_lcd_panel = { + .modes = ti_nspire_cx_lcd_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 65, + .height = 49, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_PIXDATA_NEGEDGE, +}; + +static const struct drm_display_mode ti_nspire_classic_lcd_mode[] = { + { + .clock = 10000, + .hdisplay = 320, + .hsync_start = 320 + 6, + .hsync_end = 320 + 6 + 6, + .htotal = 320 + 6 + 6 + 6, + .vdisplay = 240, + .vsync_start = 240 + 0, + .vsync_end = 240 + 0 + 1, + .vtotal = 240 + 0 + 1 + 0, + .vrefresh = 60, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, + }, +}; + +static const struct panel_desc ti_nspire_classic_lcd_panel = { + .modes = ti_nspire_classic_lcd_mode, + .num_modes = 1, + /* The grayscale panel has 8 bit for the color .. Y (black) */ + .bpc = 8, + .size = { + .width = 71, + .height = 53, + }, + /* This is the grayscale bus format */ + .bus_format = MEDIA_BUS_FMT_Y8_1X8, + .bus_flags = DRM_BUS_FLAG_PIXDATA_POSEDGE, +}; + static const struct drm_display_mode toshiba_lt089ac29000_mode = { .clock = 79500, .hdisplay = 1280, @@ -3302,6 +3360,12 @@ static const struct of_device_id platform_of_match[] = { }, { .compatible = "tianma,tm070rvhg71", .data = &tianma_tm070rvhg71, + }, { + .compatible = "ti,nspire-cx-lcd-panel", + .data = &ti_nspire_cx_lcd_panel, + }, { + .compatible = "ti,nspire-classic-lcd-panel", + .data = &ti_nspire_classic_lcd_panel, }, { .compatible = "toshiba,lt089ac29000", .data = &toshiba_lt089ac29000, -- cgit v1.2.3 From f237bf2de82eafd224eb981c6c0bca8a9e039af6 Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Mon, 24 Jun 2019 16:47:56 +0200 Subject: drm: meson: mask value when writing bits relaxed The value used in the macro writel_bits_relaxed has to be masked since we don't want change the bits outside the mask. Signed-off-by: Julien Masson Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/86y31r82fo.fsf@baylibre.com --- drivers/gpu/drm/meson/meson_registers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h index 057453ce027c..f8dd1be0131e 100644 --- a/drivers/gpu/drm/meson/meson_registers.h +++ b/drivers/gpu/drm/meson/meson_registers.h @@ -12,7 +12,7 @@ #define _REG(reg) ((reg) << 2) #define writel_bits_relaxed(mask, val, addr) \ - writel_relaxed((readl_relaxed(addr) & ~(mask)) | (val), addr) + writel_relaxed((readl_relaxed(addr) & ~(mask)) | ((val) & (mask)), addr) /* vpp2 */ #define VPP2_DUMMY_DATA 0x1900 -- cgit v1.2.3 From 39bf9985b8598f20a3bf49844d2ac538a0d5697f Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Mon, 24 Jun 2019 16:48:12 +0200 Subject: drm: meson: crtc: use proper macros instead of magic constants This patch add new macros which describe couple bits field of the following registers: - VD1_BLEND_SRC_CTRL - VPP_SC_MISC Signed-off-by: Julien Masson Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/86wohb82fa.fsf@baylibre.com --- drivers/gpu/drm/meson/meson_crtc.c | 17 +++++++++++------ drivers/gpu/drm/meson/meson_registers.h | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c index 3320a74e67fa..bba25325aa9c 100644 --- a/drivers/gpu/drm/meson/meson_crtc.c +++ b/drivers/gpu/drm/meson/meson_crtc.c @@ -265,11 +265,11 @@ static void meson_crtc_enable_vd1(struct meson_drm *priv) static void meson_g12a_crtc_enable_vd1(struct meson_drm *priv) { - writel_relaxed(((1 << 16) | /* post bld premult*/ - (1 << 8) | /* post src */ - (1 << 4) | /* pre bld premult*/ - (1 << 0)), - priv->io_base + _REG(VD1_BLEND_SRC_CTRL)); + writel_relaxed(VD_BLEND_PREBLD_SRC_VD1 | + VD_BLEND_PREBLD_PREMULT_EN | + VD_BLEND_POSTBLD_SRC_VD1 | + VD_BLEND_POSTBLD_PREMULT_EN, + priv->io_base + _REG(VD1_BLEND_SRC_CTRL)); } void meson_crtc_irq(struct meson_drm *priv) @@ -487,7 +487,12 @@ void meson_crtc_irq(struct meson_drm *priv) writel_relaxed(priv->viu.vd1_range_map_cr, priv->io_base + meson_crtc->viu_offset + _REG(VD1_IF0_RANGE_MAP_CR)); - writel_relaxed(0x78404, + writel_relaxed(VPP_VSC_BANK_LENGTH(4) | + VPP_HSC_BANK_LENGTH(4) | + VPP_SC_VD_EN_ENABLE | + VPP_SC_TOP_EN_ENABLE | + VPP_SC_HSC_EN_ENABLE | + VPP_SC_VSC_EN_ENABLE, priv->io_base + _REG(VPP_SC_MISC)); writel_relaxed(priv->viu.vpp_pic_in_height, priv->io_base + _REG(VPP_PIC_IN_HEIGHT)); diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h index f8dd1be0131e..e5e87c2303b7 100644 --- a/drivers/gpu/drm/meson/meson_registers.h +++ b/drivers/gpu/drm/meson/meson_registers.h @@ -362,6 +362,12 @@ #define VPP_HSC_REGION4_PHASE_SLOPE 0x1d17 #define VPP_HSC_PHASE_CTRL 0x1d18 #define VPP_SC_MISC 0x1d19 +#define VPP_SC_VD_EN_ENABLE BIT(15) +#define VPP_SC_TOP_EN_ENABLE BIT(16) +#define VPP_SC_HSC_EN_ENABLE BIT(17) +#define VPP_SC_VSC_EN_ENABLE BIT(18) +#define VPP_VSC_BANK_LENGTH(length) (length & 0x7) +#define VPP_HSC_BANK_LENGTH(length) ((length & 0x7) << 8) #define VPP_PREBLEND_VD1_H_START_END 0x1d1a #define VPP_PREBLEND_VD1_V_START_END 0x1d1b #define VPP_POSTBLEND_VD1_H_START_END 0x1d1c @@ -1630,6 +1636,16 @@ #define VPP_SLEEP_CTRL 0x1dfa #define VD1_BLEND_SRC_CTRL 0x1dfb #define VD2_BLEND_SRC_CTRL 0x1dfc +#define VD_BLEND_PREBLD_SRC_VD1 (1 << 0) +#define VD_BLEND_PREBLD_SRC_VD2 (2 << 0) +#define VD_BLEND_PREBLD_SRC_OSD1 (3 << 0) +#define VD_BLEND_PREBLD_SRC_OSD2 (4 << 0) +#define VD_BLEND_PREBLD_PREMULT_EN BIT(4) +#define VD_BLEND_POSTBLD_SRC_VD1 (1 << 8) +#define VD_BLEND_POSTBLD_SRC_VD2 (2 << 8) +#define VD_BLEND_POSTBLD_SRC_OSD1 (3 << 8) +#define VD_BLEND_POSTBLD_SRC_OSD2 (4 << 8) +#define VD_BLEND_POSTBLD_PREMULT_EN BIT(16) #define OSD1_BLEND_SRC_CTRL 0x1dfd #define OSD2_BLEND_SRC_CTRL 0x1dfe -- cgit v1.2.3 From bfb86819829e5ed5eaba4b9449ecfe6db4f9f91e Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Mon, 24 Jun 2019 16:48:27 +0200 Subject: drm: meson: drv: use macro when initializing vpu This patch add new macro which is used to set WRARB/RDARB mode of the VPU. Signed-off-by: Julien Masson Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/86v9wv82f1.fsf@baylibre.com --- drivers/gpu/drm/meson/meson_drv.c | 26 ++++++++++++++++++++++---- drivers/gpu/drm/meson/meson_registers.h | 1 + 2 files changed, 23 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 42af49afdd75..ae0166181606 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -140,10 +140,28 @@ static struct regmap_config meson_regmap_config = { static void meson_vpu_init(struct meson_drm *priv) { - writel_relaxed(0x210000, priv->io_base + _REG(VPU_RDARB_MODE_L1C1)); - writel_relaxed(0x10000, priv->io_base + _REG(VPU_RDARB_MODE_L1C2)); - writel_relaxed(0x900000, priv->io_base + _REG(VPU_RDARB_MODE_L2C1)); - writel_relaxed(0x20000, priv->io_base + _REG(VPU_WRARB_MODE_L2C1)); + u32 value; + + /* + * Slave dc0 and dc5 connected to master port 1. + * By default other slaves are connected to master port 0. + */ + value = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1) | + VPU_RDARB_SLAVE_TO_MASTER_PORT(5, 1); + writel_relaxed(value, priv->io_base + _REG(VPU_RDARB_MODE_L1C1)); + + /* Slave dc0 connected to master port 1 */ + value = VPU_RDARB_SLAVE_TO_MASTER_PORT(0, 1); + writel_relaxed(value, priv->io_base + _REG(VPU_RDARB_MODE_L1C2)); + + /* Slave dc4 and dc7 connected to master port 1 */ + value = VPU_RDARB_SLAVE_TO_MASTER_PORT(4, 1) | + VPU_RDARB_SLAVE_TO_MASTER_PORT(7, 1); + writel_relaxed(value, priv->io_base + _REG(VPU_RDARB_MODE_L2C1)); + + /* Slave dc1 connected to master port 1 */ + value = VPU_RDARB_SLAVE_TO_MASTER_PORT(1, 1); + writel_relaxed(value, priv->io_base + _REG(VPU_WRARB_MODE_L2C1)); } static void meson_remove_framebuffers(void) diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h index e5e87c2303b7..dfa693c3f16a 100644 --- a/drivers/gpu/drm/meson/meson_registers.h +++ b/drivers/gpu/drm/meson/meson_registers.h @@ -1488,6 +1488,7 @@ #define VPU_RDARB_MODE_L1C2 0x2799 #define VPU_RDARB_MODE_L2C1 0x279d #define VPU_WRARB_MODE_L2C1 0x27a2 +#define VPU_RDARB_SLAVE_TO_MASTER_PORT(dc, port) (port << (16 + dc)) /* osd super scale */ #define OSDSR_HV_SIZEIN 0x3130 -- cgit v1.2.3 From 0ce266d018f4749c7049df76d7f670a675bfa9c6 Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Mon, 24 Jun 2019 16:48:35 +0200 Subject: drm: meson: vpp: use proper macros instead of magic constants This patch add new macros which are used to set the following registers: - VPP_OSD_SCALE_COEF_IDX - VPP_DOLBY_CTRL - VPP_OFIFO_SIZE - VPP_HOLD_LINES - VPP_SC_MISC - VPP_VADJ_CTRL Signed-off-by: Julien Masson Reviewed-by: Neil Armstrong [narmstrong: put back 0x1020080 in VPP_DUMMY_DATA1 for GXM] Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/86tvcf82eu.fsf@baylibre.com --- drivers/gpu/drm/meson/meson_registers.h | 8 ++++++++ drivers/gpu/drm/meson/meson_vpp.c | 25 ++++++++++++++++--------- 2 files changed, 24 insertions(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h index dfa693c3f16a..ffaf04e1305b 100644 --- a/drivers/gpu/drm/meson/meson_registers.h +++ b/drivers/gpu/drm/meson/meson_registers.h @@ -341,6 +341,7 @@ #define VPP_LINE_IN_LENGTH 0x1d01 #define VPP_PIC_IN_HEIGHT 0x1d02 #define VPP_SCALE_COEF_IDX 0x1d03 +#define VPP_SCALE_HORIZONTAL_COEF BIT(8) #define VPP_SCALE_COEF 0x1d04 #define VPP_VSC_REGION12_STARTP 0x1d05 #define VPP_VSC_REGION34_STARTP 0x1d06 @@ -377,6 +378,8 @@ #define VPP_PREBLEND_H_SIZE 0x1d20 #define VPP_POSTBLEND_H_SIZE 0x1d21 #define VPP_HOLD_LINES 0x1d22 +#define VPP_POSTBLEND_HOLD_LINES(lines) (lines & 0xf) +#define VPP_PREBLEND_HOLD_LINES(lines) ((lines & 0xf) << 8) #define VPP_BLEND_ONECOLOR_CTRL 0x1d23 #define VPP_PREBLEND_CURRENT_XY 0x1d24 #define VPP_POSTBLEND_CURRENT_XY 0x1d25 @@ -395,6 +398,8 @@ #define VPP_OSD2_PREBLEND BIT(17) #define VPP_COLOR_MNG_ENABLE BIT(28) #define VPP_OFIFO_SIZE 0x1d27 +#define VPP_OFIFO_SIZE_MASK GENMASK(13, 0) +#define VPP_OFIFO_SIZE_DEFAULT (0xfff << 20 | 0x1000) #define VPP_FIFO_STATUS 0x1d28 #define VPP_SMOKE_CTRL 0x1d29 #define VPP_SMOKE1_VAL 0x1d2a @@ -410,6 +415,8 @@ #define VPP_HSC_PHASE_CTRL1 0x1d34 #define VPP_HSC_INI_PAT_CTRL 0x1d35 #define VPP_VADJ_CTRL 0x1d40 +#define VPP_MINUS_BLACK_LVL_VADJ1_ENABLE BIT(1) + #define VPP_VADJ1_Y 0x1d41 #define VPP_VADJ1_MA_MB 0x1d42 #define VPP_VADJ1_MC_MD 0x1d43 @@ -469,6 +476,7 @@ #define VPP_PEAKING_VGAIN 0x1d92 #define VPP_PEAKING_NLP_1 0x1d93 #define VPP_DOLBY_CTRL 0x1d93 +#define VPP_PPS_DUMMY_DATA_MODE (1 << 17) #define VPP_PEAKING_NLP_2 0x1d94 #define VPP_PEAKING_NLP_3 0x1d95 #define VPP_PEAKING_NLP_4 0x1d96 diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c index cbe6cf46e541..1429f3be6028 100644 --- a/drivers/gpu/drm/meson/meson_vpp.c +++ b/drivers/gpu/drm/meson/meson_vpp.c @@ -56,7 +56,7 @@ static void meson_vpp_write_scaling_filter_coefs(struct meson_drm *priv, { int i; - writel_relaxed(is_horizontal ? BIT(8) : 0, + writel_relaxed(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0, priv->io_base + _REG(VPP_OSD_SCALE_COEF_IDX)); for (i = 0; i < 33; i++) writel_relaxed(coefs[i], @@ -81,7 +81,7 @@ static void meson_vpp_write_vd_scaling_filter_coefs(struct meson_drm *priv, { int i; - writel_relaxed(is_horizontal ? BIT(8) : 0, + writel_relaxed(is_horizontal ? VPP_SCALE_HORIZONTAL_COEF : 0, priv->io_base + _REG(VPP_SCALE_COEF_IDX)); for (i = 0; i < 33; i++) writel_relaxed(coefs[i], @@ -96,7 +96,8 @@ void meson_vpp_init(struct meson_drm *priv) else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu")) { writel_bits_relaxed(0xff << 16, 0xff << 16, priv->io_base + _REG(VIU_MISC_CTRL1)); - writel_relaxed(0x20000, priv->io_base + _REG(VPP_DOLBY_CTRL)); + writel_relaxed(VPP_PPS_DUMMY_DATA_MODE, + priv->io_base + _REG(VPP_DOLBY_CTRL)); writel_relaxed(0x1020080, priv->io_base + _REG(VPP_DUMMY_DATA1)); } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) @@ -104,12 +105,13 @@ void meson_vpp_init(struct meson_drm *priv) /* Initialize vpu fifo control registers */ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) - writel_relaxed(0xfff << 20 | 0x1000, + writel_relaxed(VPP_OFIFO_SIZE_DEFAULT, priv->io_base + _REG(VPP_OFIFO_SIZE)); else - writel_relaxed(readl_relaxed(priv->io_base + _REG(VPP_OFIFO_SIZE)) | - 0x77f, priv->io_base + _REG(VPP_OFIFO_SIZE)); - writel_relaxed(0x08080808, priv->io_base + _REG(VPP_HOLD_LINES)); + writel_bits_relaxed(VPP_OFIFO_SIZE_MASK, 0x77f, + priv->io_base + _REG(VPP_OFIFO_SIZE)); + writel_relaxed(VPP_POSTBLEND_HOLD_LINES(4) | VPP_PREBLEND_HOLD_LINES(4), + priv->io_base + _REG(VPP_HOLD_LINES)); if (!meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) { /* Turn off preblend */ @@ -137,10 +139,15 @@ void meson_vpp_init(struct meson_drm *priv) writel_relaxed(0, priv->io_base + _REG(VPP_OSD_SC_CTRL0)); writel_relaxed(0, priv->io_base + _REG(VPP_OSD_VSC_CTRL0)); writel_relaxed(0, priv->io_base + _REG(VPP_OSD_HSC_CTRL0)); - writel_relaxed(4 | (4 << 8) | BIT(15), + + /* Set horizontal/vertical bank length and enable video scale out */ + writel_relaxed(VPP_VSC_BANK_LENGTH(4) | VPP_HSC_BANK_LENGTH(4) | + VPP_SC_VD_EN_ENABLE, priv->io_base + _REG(VPP_SC_MISC)); - writel_relaxed(1, priv->io_base + _REG(VPP_VADJ_CTRL)); + /* Enable minus black level for vadj1 */ + writel_relaxed(VPP_MINUS_BLACK_LVL_VADJ1_ENABLE, + priv->io_base + _REG(VPP_VADJ_CTRL)); /* Write in the proper filter coefficients. */ meson_vpp_write_scaling_filter_coefs(priv, -- cgit v1.2.3 From 147ae1cbaa18429b9450fd47136a29653294aaad Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Mon, 24 Jun 2019 16:48:43 +0200 Subject: drm: meson: viu: use proper macros instead of magic constants This patch add new macros which are used to set the following registers: - VIU_SW_RESET - VIU_OSD1_CTRL_STAT - VIU_OSD2_CTRL_STAT - VIU_OSD1_FIFO_CTRL_STAT - VIU_OSD2_FIFO_CTRL_STAT - VIU_MISC_CTRL0 - VIU_OSD_BLEND_CTRL - OSD1_BLEND_SRC_CTRL - OSD2_BLEND_SRC_CTRL - DOLBY_PATH_CTRL Signed-off-by: Julien Masson Reviewed-by: Neil Armstrong [narmstrong: fix OSD1_BLEND_SRC_CTRL register init value for G12A] Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/86sgrz82em.fsf@baylibre.com --- drivers/gpu/drm/meson/meson_plane.c | 2 +- drivers/gpu/drm/meson/meson_registers.h | 27 +++++++++++ drivers/gpu/drm/meson/meson_viu.c | 82 ++++++++++++++++++--------------- 3 files changed, 72 insertions(+), 39 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index 80b8d70c4d75..b9e1e117fb85 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -328,7 +328,7 @@ static void meson_plane_atomic_disable(struct drm_plane *plane, /* Disable OSD1 */ if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) - writel_bits_relaxed(3 << 8, 0, + writel_bits_relaxed(VIU_OSD1_POSTBLD_SRC_OSD1, 0, priv->io_base + _REG(OSD1_BLEND_SRC_CTRL)); else writel_bits_relaxed(VPP_OSD1_POSTBLEND, 0, diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h index ffaf04e1305b..d67f74f2883a 100644 --- a/drivers/gpu/drm/meson/meson_registers.h +++ b/drivers/gpu/drm/meson/meson_registers.h @@ -138,11 +138,19 @@ #define VIU_ADDR_START 0x1a00 #define VIU_ADDR_END 0x1aff #define VIU_SW_RESET 0x1a01 +#define VIU_SW_RESET_OSD1 BIT(0) #define VIU_MISC_CTRL0 0x1a06 +#define VIU_CTRL0_VD1_AFBC_MASK 0x170000 #define VIU_MISC_CTRL1 0x1a07 #define D2D3_INTF_LENGTH 0x1a08 #define D2D3_INTF_CTRL0 0x1a09 #define VIU_OSD1_CTRL_STAT 0x1a10 +#define VIU_OSD1_OSD_BLK_ENABLE BIT(0) +#define VIU_OSD1_POSTBLD_SRC_VD1 (1 << 8) +#define VIU_OSD1_POSTBLD_SRC_VD2 (2 << 8) +#define VIU_OSD1_POSTBLD_SRC_OSD1 (3 << 8) +#define VIU_OSD1_POSTBLD_SRC_OSD2 (4 << 8) +#define VIU_OSD1_OSD_ENABLE BIT(21) #define VIU_OSD1_CTRL_STAT2 0x1a2d #define VIU_OSD1_COLOR_ADDR 0x1a11 #define VIU_OSD1_COLOR 0x1a12 @@ -232,6 +240,12 @@ #define VIU_OSD3_MALI_UNPACK_CTRL 0x3d9f #define VIU_OSD3_DIMM_CTRL 0x3da0 +#define VIU_OSD_DDR_PRIORITY_URGENT BIT(0) +#define VIU_OSD_HOLD_FIFO_LINES(lines) ((lines & 0x1f) << 5) +#define VIU_OSD_FIFO_DEPTH_VAL(val) ((val & 0x7f) << 12) +#define VIU_OSD_WORDS_PER_BURST(words) (((words & 0x4) >> 1) << 22) +#define VIU_OSD_FIFO_LIMITS(size) ((size & 0xf) << 24) + #define VD1_IF0_GEN_REG 0x1a50 #define VD1_IF0_CANVAS0 0x1a51 #define VD1_IF0_CANVAS1 0x1a52 @@ -1612,10 +1626,18 @@ #define VPU_MAFBC_PREFETCH_CFG_S3 0x3a7c #define DOLBY_PATH_CTRL 0x1a0c +#define DOLBY_BYPASS_EN(val) (val & 0xf) #define OSD_PATH_MISC_CTRL 0x1a0e #define MALI_AFBCD_TOP_CTRL 0x1a0f #define VIU_OSD_BLEND_CTRL 0x39b0 +#define VIU_OSD_BLEND_REORDER(dest, src) ((src) << (dest * 4)) +#define VIU_OSD_BLEND_DIN_EN(bits) ((bits & 0xf) << 20) +#define VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 BIT(24) +#define VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 BIT(25) +#define VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 BIT(26) +#define VIU_OSD_BLEND_BLEN2_PREMULT_EN(input) ((input & 0x3) << 27) +#define VIU_OSD_BLEND_HOLD_LINES(lines) ((lines & 0x7) << 29) #define VIU_OSD_BLEND_CTRL1 0x39c0 #define VIU_OSD_BLEND_DIN0_SCOPE_H 0x39b1 #define VIU_OSD_BLEND_DIN0_SCOPE_V 0x39b2 @@ -1657,6 +1679,11 @@ #define VD_BLEND_POSTBLD_PREMULT_EN BIT(16) #define OSD1_BLEND_SRC_CTRL 0x1dfd #define OSD2_BLEND_SRC_CTRL 0x1dfe +#define OSD_BLEND_POSTBLD_SRC_VD1 (1 << 8) +#define OSD_BLEND_POSTBLD_SRC_VD2 (2 << 8) +#define OSD_BLEND_POSTBLD_SRC_OSD1 (3 << 8) +#define OSD_BLEND_POSTBLD_SRC_OSD2 (4 << 8) +#define OSD_BLEND_PATH_SEL_ENABLE BIT(20) #define VPP_POST_BLEND_BLEND_DUMMY_DATA 0x3968 #define VPP_POST_BLEND_DUMMY_ALPHA 0x3969 diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c index 9f8a450d50d5..e70cd55d56c9 100644 --- a/drivers/gpu/drm/meson/meson_viu.c +++ b/drivers/gpu/drm/meson/meson_viu.c @@ -320,9 +320,9 @@ void meson_viu_osd1_reset(struct meson_drm *priv) priv->io_base + _REG(VIU_OSD1_CTRL_STAT2)); /* Reset OSD1 */ - writel_bits_relaxed(BIT(0), BIT(0), + writel_bits_relaxed(VIU_SW_RESET_OSD1, VIU_SW_RESET_OSD1, priv->io_base + _REG(VIU_SW_RESET)); - writel_bits_relaxed(BIT(0), 0, + writel_bits_relaxed(VIU_SW_RESET_OSD1, 0, priv->io_base + _REG(VIU_SW_RESET)); /* Rewrite these registers state lost in the reset */ @@ -335,15 +335,22 @@ void meson_viu_osd1_reset(struct meson_drm *priv) meson_viu_load_matrix(priv); } +static inline uint32_t meson_viu_osd_burst_length_reg(uint32_t length) +{ + uint32_t val = (((length & 0x80) % 24) / 12); + + return (((val & 0x3) << 10) | (((val & 0x4) >> 2) << 31)); +} + void meson_viu_init(struct meson_drm *priv) { uint32_t reg; /* Disable OSDs */ - writel_bits_relaxed(BIT(0) | BIT(21), 0, - priv->io_base + _REG(VIU_OSD1_CTRL_STAT)); - writel_bits_relaxed(BIT(0) | BIT(21), 0, - priv->io_base + _REG(VIU_OSD2_CTRL_STAT)); + writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0, + priv->io_base + _REG(VIU_OSD1_CTRL_STAT)); + writel_bits_relaxed(VIU_OSD1_OSD_BLK_ENABLE | VIU_OSD1_OSD_ENABLE, 0, + priv->io_base + _REG(VIU_OSD2_CTRL_STAT)); /* On GXL/GXM, Use the 10bit HDR conversion matrix */ if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || @@ -354,19 +361,17 @@ void meson_viu_init(struct meson_drm *priv) true); /* Initialize OSD1 fifo control register */ - reg = BIT(0) | /* Urgent DDR request priority */ - (4 << 5); /* hold_fifo_lines */ + reg = VIU_OSD_DDR_PRIORITY_URGENT | + VIU_OSD_HOLD_FIFO_LINES(4) | + VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */ + VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */ + VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */ + if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) - reg |= (1 << 10) | /* burst length 32 */ - (32 << 12) | /* fifo_depth_val: 32*8=256 */ - (2 << 22) | /* 4 words in 1 burst */ - (2 << 24) | - (1 << 31); + reg |= meson_viu_osd_burst_length_reg(32); else - reg |= (3 << 10) | /* burst length 64 */ - (32 << 12) | /* fifo_depth_val: 32*8=256 */ - (2 << 22) | /* 4 words in 1 burst */ - (2 << 24); + reg |= meson_viu_osd_burst_length_reg(64); + writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT)); @@ -379,12 +384,9 @@ void meson_viu_init(struct meson_drm *priv) priv->io_base + _REG(VIU_OSD2_CTRL_STAT2)); /* Disable VD1 AFBC */ - /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 */ - writel_bits_relaxed(0x7 << 16, 0, - priv->io_base + _REG(VIU_MISC_CTRL0)); - /* afbc vd1 set=0 */ - writel_bits_relaxed(BIT(20), 0, - priv->io_base + _REG(VIU_MISC_CTRL0)); + /* di_mif0_en=0 mif0_to_vpp_en=0 di_mad_en=0 and afbc vd1 set=0*/ + writel_bits_relaxed(VIU_CTRL0_VD1_AFBC_MASK, 0, + priv->io_base + _REG(VIU_MISC_CTRL0)); writel_relaxed(0, priv->io_base + _REG(AFBC_ENABLE)); writel_relaxed(0x00FF00C0, @@ -393,27 +395,31 @@ void meson_viu_init(struct meson_drm *priv) priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE)); if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) { - writel_relaxed(4 << 29 | - 1 << 27 | - 1 << 26 | /* blend_din0 input to blend0 */ - 1 << 25 | /* blend1_dout to blend2 */ - 1 << 24 | /* blend1_din3 input to blend1 */ - 1 << 20 | - 0 << 16 | - 1, - priv->io_base + _REG(VIU_OSD_BLEND_CTRL)); - writel_relaxed(1 << 20, - priv->io_base + _REG(OSD1_BLEND_SRC_CTRL)); - writel_relaxed(1 << 20, - priv->io_base + _REG(OSD2_BLEND_SRC_CTRL)); + writel_relaxed(VIU_OSD_BLEND_REORDER(0, 1) | + VIU_OSD_BLEND_REORDER(1, 0) | + VIU_OSD_BLEND_REORDER(2, 0) | + VIU_OSD_BLEND_REORDER(3, 0) | + VIU_OSD_BLEND_DIN_EN(1) | + VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 | + VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 | + VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 | + VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) | + VIU_OSD_BLEND_HOLD_LINES(4), + priv->io_base + _REG(VIU_OSD_BLEND_CTRL)); + + writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE, + priv->io_base + _REG(OSD1_BLEND_SRC_CTRL)); + writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE, + priv->io_base + _REG(OSD2_BLEND_SRC_CTRL)); writel_relaxed(0, priv->io_base + _REG(VD1_BLEND_SRC_CTRL)); writel_relaxed(0, priv->io_base + _REG(VD2_BLEND_SRC_CTRL)); writel_relaxed(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_DATA0)); writel_relaxed(0, priv->io_base + _REG(VIU_OSD_BLEND_DUMMY_ALPHA)); - writel_bits_relaxed(0x3 << 2, 0x3 << 2, - priv->io_base + _REG(DOLBY_PATH_CTRL)); + + writel_bits_relaxed(DOLBY_BYPASS_EN(0xc), DOLBY_BYPASS_EN(0xc), + priv->io_base + _REG(DOLBY_PATH_CTRL)); } priv->viu.osd1_enabled = false; -- cgit v1.2.3 From 7eef9e6104545e3aed75ac84129ab332e71b6557 Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Mon, 24 Jun 2019 16:48:50 +0200 Subject: drm: meson: venc: use proper macros instead of magic constants This patch add new macros which are used to set the following registers: - ENCI_CFILT_CTRL - ENCI_CFILT_CTRL2 - ENCI_MACV_MAX_AMP - ENCI_VIDEO_MODE_ADV - ENCI_VFIFO2VD_CTL - ENCI_VIDEO_EN - ENCP_VIDEO_MODE - VPU_HDMI_SETTING - VENC_UPSAMPLE_CTRL0 - VENC_UPSAMPLE_CTRL1 - VENC_UPSAMPLE_CTRL2 - VENC_VDAC_FIFO_CTRL - VENC_VDAC_DAC0_FILT_CTRL0 - VENC_INTCTRL Signed-off-by: Julien Masson Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/86r27j82ef.fsf@baylibre.com --- drivers/gpu/drm/meson/meson_registers.h | 51 +++++++++++ drivers/gpu/drm/meson/meson_venc.c | 155 +++++++++++++++++++++++++------- drivers/gpu/drm/meson/meson_venc_cvbs.c | 3 +- 3 files changed, 177 insertions(+), 32 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h index d67f74f2883a..a96293880e82 100644 --- a/drivers/gpu/drm/meson/meson_registers.h +++ b/drivers/gpu/drm/meson/meson_registers.h @@ -734,6 +734,25 @@ #define VENC_UPSAMPLE_CTRL0 0x1b64 #define VENC_UPSAMPLE_CTRL1 0x1b65 #define VENC_UPSAMPLE_CTRL2 0x1b66 +#define VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO BIT(0) +#define VENC_UPSAMPLE_CTRL_F1_EN BIT(5) +#define VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN BIT(6) +#define VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA (0x0 << 12) +#define VENC_UPSAMPLE_CTRL_CVBS (0x1 << 12) +#define VENC_UPSAMPLE_CTRL_S_VIDEO_LUMA (0x2 << 12) +#define VENC_UPSAMPLE_CTRL_S_VIDEO_CHROMA (0x3 << 12) +#define VENC_UPSAMPLE_CTRL_INTERLACE_PB (0x4 << 12) +#define VENC_UPSAMPLE_CTRL_INTERLACE_PR (0x5 << 12) +#define VENC_UPSAMPLE_CTRL_INTERLACE_R (0x6 << 12) +#define VENC_UPSAMPLE_CTRL_INTERLACE_G (0x7 << 12) +#define VENC_UPSAMPLE_CTRL_INTERLACE_B (0x8 << 12) +#define VENC_UPSAMPLE_CTRL_PROGRESSIVE_Y (0x9 << 12) +#define VENC_UPSAMPLE_CTRL_PROGRESSIVE_PB (0xa << 12) +#define VENC_UPSAMPLE_CTRL_PROGRESSIVE_PR (0xb << 12) +#define VENC_UPSAMPLE_CTRL_PROGRESSIVE_R (0xc << 12) +#define VENC_UPSAMPLE_CTRL_PROGRESSIVE_G (0xd << 12) +#define VENC_UPSAMPLE_CTRL_PROGRESSIVE_B (0xe << 12) +#define VENC_UPSAMPLE_CTRL_VDAC_TEST_VALUE (0xf << 12) #define TCON_INVERT_CTL 0x1b67 #define VENC_VIDEO_PROG_MODE 0x1b68 #define VENC_ENCI_LINE 0x1b69 @@ -742,6 +761,7 @@ #define VENC_ENCP_PIXEL 0x1b6c #define VENC_STATA 0x1b6d #define VENC_INTCTRL 0x1b6e +#define VENC_INTCTRL_ENCI_LNRST_INT_EN BIT(1) #define VENC_INTFLAG 0x1b6f #define VENC_VIDEO_TST_EN 0x1b70 #define VENC_VIDEO_TST_MDSEL 0x1b71 @@ -752,6 +772,7 @@ #define VENC_VIDEO_TST_CLRBAR_WIDTH 0x1b76 #define VENC_VIDEO_TST_VDCNT_STSET 0x1b77 #define VENC_VDAC_DACSEL0 0x1b78 +#define VENC_VDAC_SEL_ATV_DMD BIT(5) #define VENC_VDAC_DACSEL1 0x1b79 #define VENC_VDAC_DACSEL2 0x1b7a #define VENC_VDAC_DACSEL3 0x1b7b @@ -772,6 +793,7 @@ #define VENC_VDAC_DAC5_GAINCTRL 0x1bfa #define VENC_VDAC_DAC5_OFFSET 0x1bfb #define VENC_VDAC_FIFO_CTRL 0x1bfc +#define VENC_VDAC_FIFO_EN_ENCI_ENABLE BIT(13) #define ENCL_TCON_INVERT_CTL 0x1bfd #define ENCP_VIDEO_EN 0x1b80 #define ENCP_VIDEO_SYNC_MODE 0x1b81 @@ -787,6 +809,7 @@ #define ENCP_VIDEO_SYNC_OFFST 0x1b8b #define ENCP_VIDEO_MACV_OFFST 0x1b8c #define ENCP_VIDEO_MODE 0x1b8d +#define ENCP_VIDEO_MODE_DE_V_HIGH BIT(14) #define ENCP_VIDEO_MODE_ADV 0x1b8e #define ENCP_DBG_PX_RST 0x1b90 #define ENCP_DBG_LN_RST 0x1b91 @@ -865,6 +888,11 @@ #define C656_FS_LNED 0x1be7 #define ENCI_VIDEO_MODE 0x1b00 #define ENCI_VIDEO_MODE_ADV 0x1b01 +#define ENCI_VIDEO_MODE_ADV_DMXMD(val) (val & 0x3) +#define ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 BIT(2) +#define ENCI_VIDEO_MODE_ADV_YBW_MEDIUM (0 << 4) +#define ENCI_VIDEO_MODE_ADV_YBW_LOW (0x1 << 4) +#define ENCI_VIDEO_MODE_ADV_YBW_HIGH (0x2 << 4) #define ENCI_VIDEO_FSC_ADJ 0x1b02 #define ENCI_VIDEO_BRIGHT 0x1b03 #define ENCI_VIDEO_CONT 0x1b04 @@ -935,13 +963,17 @@ #define ENCI_DBG_MAXPX 0x1b4c #define ENCI_DBG_MAXLN 0x1b4d #define ENCI_MACV_MAX_AMP 0x1b50 +#define ENCI_MACV_MAX_AMP_ENABLE_CHANGE BIT(15) +#define ENCI_MACV_MAX_AMP_VAL(val) (val & 0x83ff) #define ENCI_MACV_PULSE_LO 0x1b51 #define ENCI_MACV_PULSE_HI 0x1b52 #define ENCI_MACV_BKP_MAX 0x1b53 #define ENCI_CFILT_CTRL 0x1b54 +#define ENCI_CFILT_CMPT_SEL_HIGH BIT(1) #define ENCI_CFILT7 0x1b55 #define ENCI_YC_DELAY 0x1b56 #define ENCI_VIDEO_EN 0x1b57 +#define ENCI_VIDEO_EN_ENABLE BIT(0) #define ENCI_DVI_HSO_BEGIN 0x1c00 #define ENCI_DVI_HSO_END 0x1c01 #define ENCI_DVI_VSO_BLINE_EVN 0x1c02 @@ -953,6 +985,10 @@ #define ENCI_DVI_VSO_END_EVN 0x1c08 #define ENCI_DVI_VSO_END_ODD 0x1c09 #define ENCI_CFILT_CTRL2 0x1c0a +#define ENCI_CFILT_CMPT_CR_DLY(delay) (delay & 0xf) +#define ENCI_CFILT_CMPT_CB_DLY(delay) ((delay & 0xf) << 4) +#define ENCI_CFILT_CVBS_CR_DLY(delay) ((delay & 0xf) << 8) +#define ENCI_CFILT_CVBS_CB_DLY(delay) ((delay & 0xf) << 12) #define ENCI_DACSEL_0 0x1c0b #define ENCI_DACSEL_1 0x1c0c #define ENCP_DACSEL_0 0x1c0d @@ -967,6 +1003,8 @@ #define ENCI_TST_CLRBAR_WIDTH 0x1c16 #define ENCI_TST_VDCNT_STSET 0x1c17 #define ENCI_VFIFO2VD_CTL 0x1c18 +#define ENCI_VFIFO2VD_CTL_ENABLE BIT(0) +#define ENCI_VFIFO2VD_CTL_VD_SEL(val) ((val & 0xff) << 8) #define ENCI_VFIFO2VD_PIXEL_START 0x1c19 #define ENCI_VFIFO2VD_PIXEL_END 0x1c1a #define ENCI_VFIFO2VD_LINE_TOP_START 0x1c1b @@ -1029,6 +1067,7 @@ #define VENC_VDAC_DAC5_FILT_CTRL0 0x1c56 #define VENC_VDAC_DAC5_FILT_CTRL1 0x1c57 #define VENC_VDAC_DAC0_FILT_CTRL0 0x1c58 +#define VENC_VDAC_DAC0_FILT_CTRL0_EN BIT(0) #define VENC_VDAC_DAC0_FILT_CTRL1 0x1c59 #define VENC_VDAC_DAC1_FILT_CTRL0 0x1c5a #define VENC_VDAC_DAC1_FILT_CTRL1 0x1c5b @@ -1434,6 +1473,18 @@ #define VIU2_SEL_VENC_ENCP (2 << 2) #define VIU2_SEL_VENC_ENCT (3 << 2) #define VPU_HDMI_SETTING 0x271b +#define VPU_HDMI_ENCI_DATA_TO_HDMI BIT(0) +#define VPU_HDMI_ENCP_DATA_TO_HDMI BIT(1) +#define VPU_HDMI_INV_HSYNC BIT(2) +#define VPU_HDMI_INV_VSYNC BIT(3) +#define VPU_HDMI_OUTPUT_CRYCB (0 << 5) +#define VPU_HDMI_OUTPUT_YCBCR (1 << 5) +#define VPU_HDMI_OUTPUT_YCRCB (2 << 5) +#define VPU_HDMI_OUTPUT_CBCRY (3 << 5) +#define VPU_HDMI_OUTPUT_CBYCR (4 << 5) +#define VPU_HDMI_OUTPUT_CRCBY (5 << 5) +#define VPU_HDMI_WR_RATE(rate) (((rate & 0x1f) - 1) << 8) +#define VPU_HDMI_RD_RATE(rate) (((rate & 0x1f) - 1) << 12) #define ENCI_INFO_READ 0x271c #define ENCP_INFO_READ 0x271d #define ENCT_INFO_READ 0x271e diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c index 3d4791798ae0..9defedaac60c 100644 --- a/drivers/gpu/drm/meson/meson_venc.c +++ b/drivers/gpu/drm/meson/meson_venc.c @@ -976,6 +976,7 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, unsigned int eof_lines; unsigned int sof_lines; unsigned int vsync_lines; + u32 reg; /* Use VENCI for 480i and 576i and double HDMI pixels */ if (mode->flags & DRM_MODE_FLAG_DBLCLK) { @@ -1048,8 +1049,11 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, unsigned int lines_f1; /* CVBS Filter settings */ - writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL)); - writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2)); + writel_relaxed(ENCI_CFILT_CMPT_SEL_HIGH | 0x10, + priv->io_base + _REG(ENCI_CFILT_CTRL)); + writel_relaxed(ENCI_CFILT_CMPT_CR_DLY(2) | + ENCI_CFILT_CMPT_CB_DLY(1), + priv->io_base + _REG(ENCI_CFILT_CTRL2)); /* Digital Video Select : Interlace, clk27 clk, external */ writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING)); @@ -1071,8 +1075,9 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN)); /* Macrovision max amplitude change */ - writel_relaxed(vmode->enci.macv_max_amp, - priv->io_base + _REG(ENCI_MACV_MAX_AMP)); + writel_relaxed(ENCI_MACV_MAX_AMP_ENABLE_CHANGE | + ENCI_MACV_MAX_AMP_VAL(vmode->enci.macv_max_amp), + priv->io_base + _REG(ENCI_MACV_MAX_AMP)); /* Video mode */ writel_relaxed(vmode->enci.video_prog_mode, @@ -1088,7 +1093,10 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, * Bypass luma low pass filter * No macrovision on CSYNC */ - writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); + writel_relaxed(ENCI_VIDEO_MODE_ADV_DMXMD(2) | + ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 | + ENCI_VIDEO_MODE_ADV_YBW_HIGH, + priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); writel(vmode->enci.sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH)); @@ -1104,8 +1112,17 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, /* UNreset Interlaced TV Encoder */ writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST)); - /* Enable Vfifo2vd, Y_Cb_Y_Cr select */ - writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL)); + /* + * Enable Vfifo2vd and set Y_Cb_Y_Cr: + * Corresponding value: + * Y => 00 or 10 + * Cb => 01 + * Cr => 11 + * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y + */ + writel_relaxed(ENCI_VFIFO2VD_CTL_ENABLE | + ENCI_VFIFO2VD_CTL_VD_SEL(0x4e), + priv->io_base + _REG(ENCI_VFIFO2VD_CTL)); /* Timings */ writel_relaxed(vmode->enci.pixel_start, @@ -1127,7 +1144,8 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI); /* Interlace video enable */ - writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN)); + writel_relaxed(ENCI_VIDEO_EN_ENABLE, + priv->io_base + _REG(ENCI_VIDEO_EN)); lines_f0 = mode->vtotal >> 1; lines_f1 = lines_f0 + 1; @@ -1374,7 +1392,8 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN)); /* Set DE signal’s polarity is active high */ - writel_bits_relaxed(BIT(14), BIT(14), + writel_bits_relaxed(ENCP_VIDEO_MODE_DE_V_HIGH, + ENCP_VIDEO_MODE_DE_V_HIGH, priv->io_base + _REG(ENCP_VIDEO_MODE)); /* Program DE timing */ @@ -1493,13 +1512,39 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCP); } - writel_relaxed((use_enci ? 1 : 2) | - (mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 << 2 : 0) | - (mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 << 3 : 0) | - 4 << 5 | - (venc_repeat ? 1 << 8 : 0) | - (hdmi_repeat ? 1 << 12 : 0), - priv->io_base + _REG(VPU_HDMI_SETTING)); + /* Set VPU HDMI setting */ + /* Select ENCP or ENCI data to HDMI */ + if (use_enci) + reg = VPU_HDMI_ENCI_DATA_TO_HDMI; + else + reg = VPU_HDMI_ENCP_DATA_TO_HDMI; + + /* Invert polarity of HSYNC from VENC */ + if (mode->flags & DRM_MODE_FLAG_PHSYNC) + reg |= VPU_HDMI_INV_HSYNC; + + /* Invert polarity of VSYNC from VENC */ + if (mode->flags & DRM_MODE_FLAG_PVSYNC) + reg |= VPU_HDMI_INV_VSYNC; + + /* Output data format: CbYCr */ + reg |= VPU_HDMI_OUTPUT_CBYCR; + + /* + * Write rate to the async FIFO between VENC and HDMI. + * One write every 2 wr_clk. + */ + if (venc_repeat) + reg |= VPU_HDMI_WR_RATE(2); + + /* + * Read rate to the async FIFO between VENC and HDMI. + * One read every 2 wr_clk. + */ + if (hdmi_repeat) + reg |= VPU_HDMI_RD_RATE(2); + + writel_relaxed(reg, priv->io_base + _REG(VPU_HDMI_SETTING)); priv->venc.hdmi_repeat = hdmi_repeat; priv->venc.venc_repeat = venc_repeat; @@ -1512,12 +1557,17 @@ EXPORT_SYMBOL_GPL(meson_venc_hdmi_mode_set); void meson_venci_cvbs_mode_set(struct meson_drm *priv, struct meson_cvbs_enci_mode *mode) { + u32 reg; + if (mode->mode_tag == priv->venc.current_mode) return; /* CVBS Filter settings */ - writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL)); - writel_relaxed(0x12, priv->io_base + _REG(ENCI_CFILT_CTRL2)); + writel_relaxed(ENCI_CFILT_CMPT_SEL_HIGH | 0x10, + priv->io_base + _REG(ENCI_CFILT_CTRL)); + writel_relaxed(ENCI_CFILT_CMPT_CR_DLY(2) | + ENCI_CFILT_CMPT_CB_DLY(1), + priv->io_base + _REG(ENCI_CFILT_CTRL2)); /* Digital Video Select : Interlace, clk27 clk, external */ writel_relaxed(0, priv->io_base + _REG(VENC_DVI_SETTING)); @@ -1539,8 +1589,9 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv, priv->io_base + _REG(ENCI_SYNC_VSO_ODDLN)); /* Macrovision max amplitude change */ - writel_relaxed(0x8100 + mode->macv_max_amp, - priv->io_base + _REG(ENCI_MACV_MAX_AMP)); + writel_relaxed(ENCI_MACV_MAX_AMP_ENABLE_CHANGE | + ENCI_MACV_MAX_AMP_VAL(mode->macv_max_amp), + priv->io_base + _REG(ENCI_MACV_MAX_AMP)); /* Video mode */ writel_relaxed(mode->video_prog_mode, @@ -1556,7 +1607,10 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv, * Bypass luma low pass filter * No macrovision on CSYNC */ - writel_relaxed(0x26, priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); + writel_relaxed(ENCI_VIDEO_MODE_ADV_DMXMD(2) | + ENCI_VIDEO_MODE_ADV_VBICTL_LINE_17_22 | + ENCI_VIDEO_MODE_ADV_YBW_HIGH, + priv->io_base + _REG(ENCI_VIDEO_MODE_ADV)); writel(mode->sch_adjust, priv->io_base + _REG(ENCI_VIDEO_SCH)); @@ -1588,16 +1642,50 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv, /* UNreset Interlaced TV Encoder */ writel_relaxed(0, priv->io_base + _REG(ENCI_DBG_PX_RST)); - /* Enable Vfifo2vd, Y_Cb_Y_Cr select */ - writel_relaxed(0x4e01, priv->io_base + _REG(ENCI_VFIFO2VD_CTL)); + /* + * Enable Vfifo2vd and set Y_Cb_Y_Cr: + * Corresponding value: + * Y => 00 or 10 + * Cb => 01 + * Cr => 11 + * Ex: 0x4e => 01001110 would mean Cb/Y/Cr/Y + */ + writel_relaxed(ENCI_VFIFO2VD_CTL_ENABLE | + ENCI_VFIFO2VD_CTL_VD_SEL(0x4e), + priv->io_base + _REG(ENCI_VFIFO2VD_CTL)); /* Power UP Dacs */ writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_SETTING)); /* Video Upsampling */ - writel_relaxed(0x0061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL0)); - writel_relaxed(0x4061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL1)); - writel_relaxed(0x5061, priv->io_base + _REG(VENC_UPSAMPLE_CTRL2)); + /* + * CTRL0, CTRL1 and CTRL2: + * Filter0: input data sample every 2 cloks + * Filter1: filtering and upsample enable + */ + reg = VENC_UPSAMPLE_CTRL_F0_2_CLK_RATIO | VENC_UPSAMPLE_CTRL_F1_EN | + VENC_UPSAMPLE_CTRL_F1_UPSAMPLE_EN; + + /* + * Upsample CTRL0: + * Interlace High Bandwidth Luma + */ + writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_HIGH_LUMA | reg, + priv->io_base + _REG(VENC_UPSAMPLE_CTRL0)); + + /* + * Upsample CTRL1: + * Interlace Pb + */ + writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_PB | reg, + priv->io_base + _REG(VENC_UPSAMPLE_CTRL1)); + + /* + * Upsample CTRL2: + * Interlace R + */ + writel_relaxed(VENC_UPSAMPLE_CTRL_INTERLACE_PR | reg, + priv->io_base + _REG(VENC_UPSAMPLE_CTRL2)); /* Select Interlace Y DACs */ writel_relaxed(0, priv->io_base + _REG(VENC_VDAC_DACSEL0)); @@ -1611,14 +1699,16 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv, meson_vpp_setup_mux(priv, MESON_VIU_VPP_MUX_ENCI); /* Enable ENCI FIFO */ - writel_relaxed(0x2000, priv->io_base + _REG(VENC_VDAC_FIFO_CTRL)); + writel_relaxed(VENC_VDAC_FIFO_EN_ENCI_ENABLE, + priv->io_base + _REG(VENC_VDAC_FIFO_CTRL)); /* Select ENCI DACs 0, 1, 4, and 5 */ writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_0)); writel_relaxed(0x11, priv->io_base + _REG(ENCI_DACSEL_1)); /* Interlace video enable */ - writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN)); + writel_relaxed(ENCI_VIDEO_EN_ENABLE, + priv->io_base + _REG(ENCI_VIDEO_EN)); /* Configure Video Saturation / Contrast / Brightness / Hue */ writel_relaxed(mode->video_saturation, @@ -1631,7 +1721,8 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv, priv->io_base + _REG(ENCI_VIDEO_HUE)); /* Enable DAC0 Filter */ - writel_relaxed(0x1, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0)); + writel_relaxed(VENC_VDAC_DAC0_FILT_CTRL0_EN, + priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL0)); writel_relaxed(0xfc48, priv->io_base + _REG(VENC_VDAC_DAC0_FILT_CTRL1)); /* 0 in Macrovision register 0 */ @@ -1652,7 +1743,8 @@ unsigned int meson_venci_get_field(struct meson_drm *priv) void meson_venc_enable_vsync(struct meson_drm *priv) { - writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL)); + writel_relaxed(VENC_INTCTRL_ENCI_LNRST_INT_EN, + priv->io_base + _REG(VENC_INTCTRL)); regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25)); } @@ -1680,7 +1772,8 @@ void meson_venc_init(struct meson_drm *priv) regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0); /* Disable HDMI */ - writel_bits_relaxed(0x3, 0, + writel_bits_relaxed(VPU_HDMI_ENCI_DATA_TO_HDMI | + VPU_HDMI_ENCP_DATA_TO_HDMI, 0, priv->io_base + _REG(VPU_HDMI_SETTING)); /* Disable all encoders */ diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c index 45a467f10b9b..6dc130a24070 100644 --- a/drivers/gpu/drm/meson/meson_venc_cvbs.c +++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c @@ -171,7 +171,8 @@ static void meson_venc_cvbs_encoder_enable(struct drm_encoder *encoder) struct meson_drm *priv = meson_venc_cvbs->priv; /* VDAC0 source is not from ATV */ - writel_bits_relaxed(BIT(5), 0, priv->io_base + _REG(VENC_VDAC_DACSEL0)); + writel_bits_relaxed(VENC_VDAC_SEL_ATV_DMD, 0, + priv->io_base + _REG(VENC_VDAC_DACSEL0)); if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) { regmap_write(priv->hhi, HHI_VDAC_CNTL0, 1); -- cgit v1.2.3 From e1012141242db89259175eeaac36b3de04377664 Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Mon, 24 Jun 2019 16:48:57 +0200 Subject: drm: meson: global clean-up This patch aims to: - Add general and TODO comments - Respect coding style for multi-line comments - Align macro definitions - Remove useless macro Signed-off-by: Julien Masson Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/86pnn382e8.fsf@baylibre.com --- drivers/gpu/drm/meson/meson_dw_hdmi.c | 2 ++ drivers/gpu/drm/meson/meson_dw_hdmi.h | 12 ++++++++---- drivers/gpu/drm/meson/meson_registers.h | 31 ++++++++++++++----------------- drivers/gpu/drm/meson/meson_vclk.c | 4 +++- drivers/gpu/drm/meson/meson_venc.c | 10 ++++++---- 5 files changed, 33 insertions(+), 26 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c index 9f0b08eaf003..f893ebd0b799 100644 --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c @@ -429,6 +429,8 @@ static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, /* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */ dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL, 0x3, 0x3); + + /* Enable cec_clk and hdcp22_tmdsclk_en */ dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL, 0x3 << 4, 0x3 << 4); diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.h b/drivers/gpu/drm/meson/meson_dw_hdmi.h index 1b2ef043eb5c..08e1c14e4ea0 100644 --- a/drivers/gpu/drm/meson/meson_dw_hdmi.h +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.h @@ -100,7 +100,8 @@ #define HDMITX_TOP_INTR_RXSENSE_RISE BIT(6) #define HDMITX_TOP_INTR_RXSENSE_FALL BIT(7) -/* Bit 14:12 RW tmds_sel: 3'b000=Output zero; 3'b001=Output normal TMDS data; +/* + * Bit 14:12 RW tmds_sel: 3'b000=Output zero; 3'b001=Output normal TMDS data; * 3'b010=Output PRBS data; 3'b100=Output shift pattern. Default 0. * Bit 11: 9 RW shift_pttn_repeat: 0=New pattern every clk cycle; 1=New pattern * every 2 clk cycles; ...; 7=New pattern every 8 clk cycles. Default 0. @@ -135,7 +136,8 @@ /* Bit 9: 0 RW tmds_clk_pttn[29:20]. Default 0. */ #define HDMITX_TOP_TMDS_CLK_PTTN_23 (0x00B) -/* Bit 1 RW shift_tmds_clk_pttn:1=Enable shifting clk pattern, +/* + * Bit 1 RW shift_tmds_clk_pttn:1=Enable shifting clk pattern, * used when TMDS CLK rate = TMDS character rate /4. Default 0. * Bit 0 R Reserved. Default 0. * [ 1] shift_tmds_clk_pttn @@ -143,12 +145,14 @@ */ #define HDMITX_TOP_TMDS_CLK_PTTN_CNTL (0x00C) -/* Bit 0 RW revocmem_wr_fail: Read back 1 to indicate Host write REVOC MEM +/* + * Bit 0 RW revocmem_wr_fail: Read back 1 to indicate Host write REVOC MEM * failure, write 1 to clear the failure flag. Default 0. */ #define HDMITX_TOP_REVOCMEM_STAT (0x00D) -/* Bit 1 R filtered RxSense status +/* + * Bit 1 R filtered RxSense status * Bit 0 R filtered HPD status. */ #define HDMITX_TOP_STAT0 (0x00E) diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h index a96293880e82..05fce48ceee0 100644 --- a/drivers/gpu/drm/meson/meson_registers.h +++ b/drivers/gpu/drm/meson/meson_registers.h @@ -398,19 +398,19 @@ #define VPP_PREBLEND_CURRENT_XY 0x1d24 #define VPP_POSTBLEND_CURRENT_XY 0x1d25 #define VPP_MISC 0x1d26 -#define VPP_PREBLEND_ENABLE BIT(6) -#define VPP_POSTBLEND_ENABLE BIT(7) -#define VPP_OSD2_ALPHA_PREMULT BIT(8) -#define VPP_OSD1_ALPHA_PREMULT BIT(9) -#define VPP_VD1_POSTBLEND BIT(10) -#define VPP_VD2_POSTBLEND BIT(11) -#define VPP_OSD1_POSTBLEND BIT(12) -#define VPP_OSD2_POSTBLEND BIT(13) -#define VPP_VD1_PREBLEND BIT(14) -#define VPP_VD2_PREBLEND BIT(15) -#define VPP_OSD1_PREBLEND BIT(16) -#define VPP_OSD2_PREBLEND BIT(17) -#define VPP_COLOR_MNG_ENABLE BIT(28) +#define VPP_PREBLEND_ENABLE BIT(6) +#define VPP_POSTBLEND_ENABLE BIT(7) +#define VPP_OSD2_ALPHA_PREMULT BIT(8) +#define VPP_OSD1_ALPHA_PREMULT BIT(9) +#define VPP_VD1_POSTBLEND BIT(10) +#define VPP_VD2_POSTBLEND BIT(11) +#define VPP_OSD1_POSTBLEND BIT(12) +#define VPP_OSD2_POSTBLEND BIT(13) +#define VPP_VD1_PREBLEND BIT(14) +#define VPP_VD2_PREBLEND BIT(15) +#define VPP_OSD1_PREBLEND BIT(16) +#define VPP_OSD2_PREBLEND BIT(17) +#define VPP_COLOR_MNG_ENABLE BIT(28) #define VPP_OFIFO_SIZE 0x1d27 #define VPP_OFIFO_SIZE_MASK GENMASK(13, 0) #define VPP_OFIFO_SIZE_DEFAULT (0xfff << 20 | 0x1000) @@ -621,6 +621,7 @@ #define OSD34_SCI_WH_M1 0x3d29 #define OSD34_SCO_H_START_END 0x3d2a #define OSD34_SCO_V_START_END 0x3d2b + /* viu2 */ #define VIU2_ADDR_START 0x1e00 #define VIU2_ADDR_END 0x1eff @@ -1603,7 +1604,6 @@ #define OSD1_AFBCD_STATUS 0x31a8 #define OSD1_AFBCD_PIXEL_HSCOPE 0x31a9 #define OSD1_AFBCD_PIXEL_VSCOPE 0x31aa -#define VIU_MISC_CTRL1 0x1a07 /* add for gxm and 962e dv core2 */ #define DOLBY_CORE2A_SWAP_CTRL1 0x3434 @@ -1618,8 +1618,6 @@ #define VPU_MAFBC_COMMAND 0x3a05 #define VPU_MAFBC_STATUS 0x3a06 #define VPU_MAFBC_SURFACE_CFG 0x3a07 - -/* osd afbc on g12a */ #define VPU_MAFBC_HEADER_BUF_ADDR_LOW_S0 0x3a10 #define VPU_MAFBC_HEADER_BUF_ADDR_HIGH_S0 0x3a11 #define VPU_MAFBC_FORMAT_SPECIFIER_S0 0x3a12 @@ -1740,6 +1738,5 @@ #define VPP_POST_BLEND_DUMMY_ALPHA 0x3969 #define VPP_RDARB_MODE 0x3978 #define VPP_RDARB_REQEN_SLV 0x3979 -#define VPU_RDARB_MODE_L2C1 0x279d #endif /* __MESON_REGISTERS_H */ diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c index 8abff51f937d..c11b55237917 100644 --- a/drivers/gpu/drm/meson/meson_vclk.c +++ b/drivers/gpu/drm/meson/meson_vclk.c @@ -496,6 +496,7 @@ void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m, regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m); /* Enable and reset */ + /* TODO: add specific macro for g12a here */ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, 0x3 << 28, 0x3 << 28); @@ -970,7 +971,8 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, meson_venci_cvbs_clock_config(priv); return; } else if (target == MESON_VCLK_TARGET_DMT) { - /* The DMT clock path is fixed after the PLL: + /* + * The DMT clock path is fixed after the PLL: * - automatic PLL freq + OD management * - vid_pll_div = VID_PLL_DIV_5 * - vclk_div = 2 diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c index 9defedaac60c..cb569d3104a8 100644 --- a/drivers/gpu/drm/meson/meson_venc.c +++ b/drivers/gpu/drm/meson/meson_venc.c @@ -61,9 +61,9 @@ /* HHI Registers */ #define HHI_GCLK_MPEG2 0x148 /* 0x52 offset in data sheet */ #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */ -#define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbd offset in data sheet */ +#define HHI_VDAC_CNTL0_G12A 0x2EC /* 0xbb offset in data sheet */ #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */ -#define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbe offset in data sheet */ +#define HHI_VDAC_CNTL1_G12A 0x2F0 /* 0xbc offset in data sheet */ #define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 offset in data sheet */ struct meson_cvbs_enci_mode meson_cvbs_enci_pal = { @@ -1085,7 +1085,8 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic, writel_relaxed(vmode->enci.video_mode, priv->io_base + _REG(ENCI_VIDEO_MODE)); - /* Advanced Video Mode : + /* + * Advanced Video Mode : * Demux shifting 0x2 * Blank line end at line17/22 * High bandwidth Luma Filter @@ -1599,7 +1600,8 @@ void meson_venci_cvbs_mode_set(struct meson_drm *priv, writel_relaxed(mode->video_mode, priv->io_base + _REG(ENCI_VIDEO_MODE)); - /* Advanced Video Mode : + /* + * Advanced Video Mode : * Demux shifting 0x2 * Blank line end at line17/22 * High bandwidth Luma Filter -- cgit v1.2.3 From 0703146060786f972aaa22cad9c877a6067fd47d Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Mon, 24 Jun 2019 16:49:04 +0200 Subject: drm: meson: add macro used to enable HDMI PLL This patch add new macro HHI_HDMI_PLL_CNTL_EN which is used to enable HDMI PLL. Signed-off-by: Julien Masson Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/86o92n82e1.fsf@baylibre.com --- drivers/gpu/drm/meson/meson_vclk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c index c11b55237917..869231c93617 100644 --- a/drivers/gpu/drm/meson/meson_vclk.c +++ b/drivers/gpu/drm/meson/meson_vclk.c @@ -97,6 +97,7 @@ #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */ #define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */ +#define HHI_HDMI_PLL_CNTL_EN BIT(30) #define HHI_HDMI_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */ #define HHI_HDMI_PLL_CNTL3 0x328 /* 0xca offset in data sheet */ #define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */ @@ -469,7 +470,7 @@ void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m, /* Enable and unreset */ regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL, - 0x7 << 28, 0x4 << 28); + 0x7 << 28, HHI_HDMI_PLL_CNTL_EN); /* Poll for lock bit */ regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, -- cgit v1.2.3 From a84ddb83806ed43a67f6fe6a03b0b4695cc314c3 Mon Sep 17 00:00:00 2001 From: Julien Masson Date: Mon, 24 Jun 2019 16:49:12 +0200 Subject: drm: meson: venc: set the correct macrovision max amplitude value According to the register description of ENCI_MACV_MAX_AMP, the macrovision max amplitude value should be: - hdmi 480i => 0xb - hdmi 576i => 0x7 The max value is 0x7ff (10 bits). Signed-off-by: Julien Masson Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/86mui782dt.fsf@baylibre.com --- drivers/gpu/drm/meson/meson_venc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c index cb569d3104a8..679d2274531c 100644 --- a/drivers/gpu/drm/meson/meson_venc.c +++ b/drivers/gpu/drm/meson/meson_venc.c @@ -192,7 +192,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_480i = { .hso_end = 129, .vso_even = 3, .vso_odd = 260, - .macv_max_amp = 0x810b, + .macv_max_amp = 0xb, .video_prog_mode = 0xf0, .video_mode = 0x8, .sch_adjust = 0x20, @@ -212,7 +212,7 @@ union meson_hdmi_venc_mode meson_hdmi_enci_mode_576i = { .hso_end = 129, .vso_even = 3, .vso_odd = 260, - .macv_max_amp = 8107, + .macv_max_amp = 0x7, .video_prog_mode = 0xff, .video_mode = 0x13, .sch_adjust = 0x28, -- cgit v1.2.3 From dd7a7d1ff2f199a8a80ee233480922d4f17adc6d Mon Sep 17 00:00:00 2001 From: Christian König Date: Tue, 6 Aug 2019 16:30:33 +0200 Subject: drm/i915: use new reservation_object_fences helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of open coding the sequence loop use the new helper. Signed-off-by: Christian König Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/322377/?series=64837&rev=1 --- drivers/gpu/drm/i915/gem/i915_gem_busy.c | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c b/drivers/gpu/drm/i915/gem/i915_gem_busy.c index 6ad93a09968c..8473292096cb 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c @@ -83,7 +83,8 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, struct drm_i915_gem_busy *args = data; struct drm_i915_gem_object *obj; struct reservation_object_list *list; - unsigned int seq; + unsigned int i, shared_count; + struct dma_fence *excl; int err; err = -ENOENT; @@ -109,29 +110,18 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, * to report the overall busyness. This is what the wait-ioctl does. * */ -retry: - seq = raw_read_seqcount(&obj->base.resv->seq); + reservation_object_fences(obj->base.resv, &excl, &list, &shared_count); /* Translate the exclusive fence to the READ *and* WRITE engine */ - args->busy = - busy_check_writer(rcu_dereference(obj->base.resv->fence_excl)); + args->busy = busy_check_writer(excl); /* Translate shared fences to READ set of engines */ - list = rcu_dereference(obj->base.resv->fence); - if (list) { - unsigned int shared_count = list->shared_count, i; + for (i = 0; i < shared_count; ++i) { + struct dma_fence *fence = rcu_dereference(list->shared[i]); - for (i = 0; i < shared_count; ++i) { - struct dma_fence *fence = - rcu_dereference(list->shared[i]); - - args->busy |= busy_check_reader(fence); - } + args->busy |= busy_check_reader(fence); } - if (args->busy && read_seqcount_retry(&obj->base.resv->seq, seq)) - goto retry; - err = 0; out: rcu_read_unlock(); -- cgit v1.2.3 From 0e1d8083bddb38b7169f6240905422f95d3c31b9 Mon Sep 17 00:00:00 2001 From: Christian König Date: Mon, 5 Aug 2019 11:16:12 +0200 Subject: dma-buf: further relax reservation_object_add_shared_fence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Other cores don't busy wait any more and we removed the last user of checking the seqno for changes. Drop updating the number for shared fences altogether. Signed-off-by: Christian König Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/322379/?series=64837&rev=1 --- drivers/dma-buf/reservation.c | 6 ------ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 7 +------ 2 files changed, 1 insertion(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c index 8fcaddffd5d4..90bc6ef03598 100644 --- a/drivers/dma-buf/reservation.c +++ b/drivers/dma-buf/reservation.c @@ -237,9 +237,6 @@ void reservation_object_add_shared_fence(struct reservation_object *obj, fobj = reservation_object_get_list(obj); count = fobj->shared_count; - preempt_disable(); - write_seqcount_begin(&obj->seq); - for (i = 0; i < count; ++i) { old = rcu_dereference_protected(fobj->shared[i], @@ -257,9 +254,6 @@ replace: RCU_INIT_POINTER(fobj->shared[i], fence); /* pointer update must be visible before we extend the shared_count */ smp_store_mb(fobj->shared_count, count); - - write_seqcount_end(&obj->seq); - preempt_enable(); dma_fence_put(old); } EXPORT_SYMBOL(reservation_object_add_shared_fence); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index fe062b76ec91..a4640ddc24d1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -251,12 +251,7 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, new->shared_max = old->shared_max; new->shared_count = k; - /* Install the new fence list, seqcount provides the barriers */ - preempt_disable(); - write_seqcount_begin(&resv->seq); - RCU_INIT_POINTER(resv->fence, new); - write_seqcount_end(&resv->seq); - preempt_enable(); + rcu_assign_pointer(resv->fence, new); /* Drop the references to the removed fences or move them to ef_list */ for (i = j, k = 0; i < old->shared_count; ++i) { -- cgit v1.2.3 From 7bb0a60aa57818a9c49c5b4ec64e5f75581c369d Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 4 Aug 2019 22:16:22 +0200 Subject: drm/bridge: tc358767: fix opencoded use of drm_panel_* Replace open coded version with call to drm_panel_get_modes(). Include change to deal with the possible negative return values from drm_panel_get_modes() v2: - Added more info to changelog (Philipp) Signed-off-by: Sam Ravnborg Reviewed-by: Philipp Zabel Reviewed-by: Emil Velikov Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec Link: https://patchwork.freedesktop.org/patch/msgid/20190804201637.1240-2-sam@ravnborg.org --- drivers/gpu/drm/bridge/tc358767.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 42f03a985ac0..cebc8e620820 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1312,7 +1312,7 @@ static int tc_connector_get_modes(struct drm_connector *connector) { struct tc_data *tc = connector_to_tc(connector); struct edid *edid; - unsigned int count; + int count; int ret; ret = tc_get_display_props(tc); @@ -1321,11 +1321,9 @@ static int tc_connector_get_modes(struct drm_connector *connector) return 0; } - if (tc->panel && tc->panel->funcs && tc->panel->funcs->get_modes) { - count = tc->panel->funcs->get_modes(tc->panel); - if (count > 0) - return count; - } + count = drm_panel_get_modes(tc->panel); + if (count > 0) + return count; edid = drm_get_edid(connector, &tc->aux.ddc); -- cgit v1.2.3 From 90fbc5105653c1c757eb5889b32106cdd754e69f Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 4 Aug 2019 22:16:25 +0200 Subject: drm/imx: fix opencoded use of drm_panel_* Use the drm_panel_get_modes() function to get the modes. This patch leave one test for the function pointer: panel->funcs->get_modes This is used to check if the panel may have any modes. There is no direct replacement. We may be able to just check that drm_panel_get_modes() return > 0, but as this is not the same functionality it is left for later. Signed-off-by: Sam Ravnborg Acked-by: Philipp Zabel Reviewed-by: Emil Velikov Cc: Shawn Guo Cc: Sascha Hauer Cc: Pengutronix Kernel Team Cc: Fabio Estevam Cc: NXP Linux Team Cc: linux-arm-kernel@lists.infradead.org Link: https://patchwork.freedesktop.org/patch/msgid/20190804201637.1240-5-sam@ravnborg.org --- drivers/gpu/drm/imx/imx-ldb.c | 11 ++++------- drivers/gpu/drm/imx/parallel-display.c | 11 ++++------- 2 files changed, 8 insertions(+), 14 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index db461b6a257f..695f307f36b2 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -124,14 +124,11 @@ static void imx_ldb_ch_set_bus_format(struct imx_ldb_channel *imx_ldb_ch, static int imx_ldb_connector_get_modes(struct drm_connector *connector) { struct imx_ldb_channel *imx_ldb_ch = con_to_imx_ldb_ch(connector); - int num_modes = 0; + int num_modes; - if (imx_ldb_ch->panel && imx_ldb_ch->panel->funcs && - imx_ldb_ch->panel->funcs->get_modes) { - num_modes = imx_ldb_ch->panel->funcs->get_modes(imx_ldb_ch->panel); - if (num_modes > 0) - return num_modes; - } + num_modes = drm_panel_get_modes(imx_ldb_ch->panel); + if (num_modes > 0) + return num_modes; if (!imx_ldb_ch->edid && imx_ldb_ch->ddc) imx_ldb_ch->edid = drm_get_edid(connector, imx_ldb_ch->ddc); diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 2e51b2fade75..e7ce17503ae1 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -47,14 +47,11 @@ static int imx_pd_connector_get_modes(struct drm_connector *connector) { struct imx_parallel_display *imxpd = con_to_imxpd(connector); struct device_node *np = imxpd->dev->of_node; - int num_modes = 0; + int num_modes; - if (imxpd->panel && imxpd->panel->funcs && - imxpd->panel->funcs->get_modes) { - num_modes = imxpd->panel->funcs->get_modes(imxpd->panel); - if (num_modes > 0) - return num_modes; - } + num_modes = drm_panel_get_modes(imxpd->panel); + if (num_modes > 0) + return num_modes; if (imxpd->edid) { drm_connector_update_edid_property(connector, imxpd->edid); -- cgit v1.2.3 From 24bc3e9ce68a41c73b32af8cd077fdf26b31516c Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 4 Aug 2019 22:16:26 +0200 Subject: drm/fsl-dcu: fix opencoded use of drm_panel_* Use drm_panel_get_modes() to access modes. This has a nice side effect to simplify the code. drm_panel_get_modes() may return a negative value if for example panel is NULL. This is a small change compared to before, but really what we want. v2: - Add more info to changelog (Stefan) Signed-off-by: Sam Ravnborg Acked-by: Stefan Agner Reviewed-by: Emil Velikov Cc: Alison Wang Link: https://patchwork.freedesktop.org/patch/msgid/20190804201637.1240-6-sam@ravnborg.org --- drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c index 279d83eaffc0..a92fd6c70b09 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c @@ -65,17 +65,9 @@ static const struct drm_connector_funcs fsl_dcu_drm_connector_funcs = { static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector) { struct fsl_dcu_drm_connector *fsl_connector; - int (*get_modes)(struct drm_panel *panel); - int num_modes = 0; fsl_connector = to_fsl_dcu_connector(connector); - if (fsl_connector->panel && fsl_connector->panel->funcs && - fsl_connector->panel->funcs->get_modes) { - get_modes = fsl_connector->panel->funcs->get_modes; - num_modes = get_modes(fsl_connector->panel); - } - - return num_modes; + return drm_panel_get_modes(fsl_connector->panel); } static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector, -- cgit v1.2.3 From ce7d93aa2a080d94cca16948b9e3bef54f7ba031 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 4 Aug 2019 22:16:28 +0200 Subject: drm/mxsfb: fix opencoded use of drm_panel_* Use the drm_panel_get_modes() function. Signed-off-by: Sam Ravnborg Cc: Marek Vasut Acked-by: Stefan Agner Reviewed-by: Emil Velikov Cc: Shawn Guo Cc: Sascha Hauer Cc: Pengutronix Kernel Team Cc: Fabio Estevam Cc: NXP Linux Team Cc: linux-arm-kernel@lists.infradead.org Link: https://patchwork.freedesktop.org/patch/msgid/20190804201637.1240-8-sam@ravnborg.org --- drivers/gpu/drm/mxsfb/mxsfb_out.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c index 231d016c6f47..be36f4d6cc96 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_out.c @@ -30,7 +30,7 @@ static int mxsfb_panel_get_modes(struct drm_connector *connector) drm_connector_to_mxsfb_drm_private(connector); if (mxsfb->panel) - return mxsfb->panel->funcs->get_modes(mxsfb->panel); + return drm_panel_get_modes(mxsfb->panel); return 0; } -- cgit v1.2.3 From 9d027b8e5a5754571a6b803f3635442fbc2abcdc Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 4 Aug 2019 22:16:31 +0200 Subject: drm/panel: ili9322: move bus_flags to get_modes() To prepare the driver to receive drm_connector only in the get_modes() callback, move bus_flags handling to ili9322_get_modes(). Signed-off-by: Sam Ravnborg Acked-by: Linus Walleij Reviewed-by: Emil Velikov Cc: Thierry Reding Cc: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20190804201637.1240-11-sam@ravnborg.org --- drivers/gpu/drm/panel/panel-ilitek-ili9322.c | 34 +++++++++++++--------------- 1 file changed, 16 insertions(+), 18 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c index 53dd1e128795..3c58f63adbf7 100644 --- a/drivers/gpu/drm/panel/panel-ilitek-ili9322.c +++ b/drivers/gpu/drm/panel/panel-ilitek-ili9322.c @@ -349,7 +349,6 @@ static const struct regmap_config ili9322_regmap_config = { static int ili9322_init(struct drm_panel *panel, struct ili9322 *ili) { - struct drm_connector *connector = panel->connector; u8 reg; int ret; int i; @@ -407,23 +406,11 @@ static int ili9322_init(struct drm_panel *panel, struct ili9322 *ili) * Polarity and inverted color order for RGB input. * None of this applies in the BT.656 mode. */ - if (ili->conf->dclk_active_high) { + reg = 0; + if (ili->conf->dclk_active_high) reg = ILI9322_POL_DCLK; - connector->display_info.bus_flags |= - DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE; - } else { - reg = 0; - connector->display_info.bus_flags |= - DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE; - } - if (ili->conf->de_active_high) { + if (ili->conf->de_active_high) reg |= ILI9322_POL_DE; - connector->display_info.bus_flags |= - DRM_BUS_FLAG_DE_HIGH; - } else { - connector->display_info.bus_flags |= - DRM_BUS_FLAG_DE_LOW; - } if (ili->conf->hsync_active_high) reg |= ILI9322_POL_HSYNC; if (ili->conf->vsync_active_high) @@ -659,9 +646,20 @@ static int ili9322_get_modes(struct drm_panel *panel) struct drm_connector *connector = panel->connector; struct ili9322 *ili = panel_to_ili9322(panel); struct drm_display_mode *mode; + struct drm_display_info *info; + + info = &connector->display_info; + info->width_mm = ili->conf->width_mm; + info->height_mm = ili->conf->height_mm; + if (ili->conf->dclk_active_high) + info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE; + else + info->bus_flags |= DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE; - connector->display_info.width_mm = ili->conf->width_mm; - connector->display_info.height_mm = ili->conf->height_mm; + if (ili->conf->de_active_high) + info->bus_flags |= DRM_BUS_FLAG_DE_HIGH; + else + info->bus_flags |= DRM_BUS_FLAG_DE_LOW; switch (ili->input) { case ILI9322_INPUT_SRGB_DUMMY_320X240: -- cgit v1.2.3 From 7a833d307cd828e5f214f8d490f16fefabf8dbff Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 4 Aug 2019 22:16:32 +0200 Subject: drm/panel: move drm_panel functions to .c file Move inline functions from include/drm/drm_panel.h to drm_panel.c. This is in preparation for follow-up patches that will add extra logic to the functions. As they are no longer static inline, EXPORT them. v2: - align order of functions in drm_panel.h and drm_panel.c (Laurent) Signed-off-by: Sam Ravnborg Reviewed-by: Laurent Pinchart Reviewed-by: Emil Velikov Cc: Thierry Reding Cc: Sam Ravnborg Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Sean Paul Cc: David Airlie Cc: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20190804201637.1240-12-sam@ravnborg.org --- drivers/gpu/drm/drm_panel.c | 96 +++++++++++++++++++++++++++++++++++++++++++ include/drm/drm_panel.h | 99 ++++----------------------------------------- 2 files changed, 104 insertions(+), 91 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index dbd5b873e8f2..a5fe28b17fb9 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -135,6 +135,102 @@ int drm_panel_detach(struct drm_panel *panel) } EXPORT_SYMBOL(drm_panel_detach); +/** + * drm_panel_prepare - power on a panel + * @panel: DRM panel + * + * Calling this function will enable power and deassert any reset signals to + * the panel. After this has completed it is possible to communicate with any + * integrated circuitry via a command bus. + * + * Return: 0 on success or a negative error code on failure. + */ +int drm_panel_prepare(struct drm_panel *panel) +{ + if (panel && panel->funcs && panel->funcs->prepare) + return panel->funcs->prepare(panel); + + return panel ? -ENOSYS : -EINVAL; +} +EXPORT_SYMBOL(drm_panel_prepare); + +/** + * drm_panel_unprepare - power off a panel + * @panel: DRM panel + * + * Calling this function will completely power off a panel (assert the panel's + * reset, turn off power supplies, ...). After this function has completed, it + * is usually no longer possible to communicate with the panel until another + * call to drm_panel_prepare(). + * + * Return: 0 on success or a negative error code on failure. + */ +int drm_panel_unprepare(struct drm_panel *panel) +{ + if (panel && panel->funcs && panel->funcs->unprepare) + return panel->funcs->unprepare(panel); + + return panel ? -ENOSYS : -EINVAL; +} +EXPORT_SYMBOL(drm_panel_unprepare); + +/** + * drm_panel_enable - enable a panel + * @panel: DRM panel + * + * Calling this function will cause the panel display drivers to be turned on + * and the backlight to be enabled. Content will be visible on screen after + * this call completes. + * + * Return: 0 on success or a negative error code on failure. + */ +int drm_panel_enable(struct drm_panel *panel) +{ + if (panel && panel->funcs && panel->funcs->enable) + return panel->funcs->enable(panel); + + return panel ? -ENOSYS : -EINVAL; +} +EXPORT_SYMBOL(drm_panel_enable); + +/** + * drm_panel_disable - disable a panel + * @panel: DRM panel + * + * This will typically turn off the panel's backlight or disable the display + * drivers. For smart panels it should still be possible to communicate with + * the integrated circuitry via any command bus after this call. + * + * Return: 0 on success or a negative error code on failure. + */ +int drm_panel_disable(struct drm_panel *panel) +{ + if (panel && panel->funcs && panel->funcs->disable) + return panel->funcs->disable(panel); + + return panel ? -ENOSYS : -EINVAL; +} +EXPORT_SYMBOL(drm_panel_disable); + +/** + * drm_panel_get_modes - probe the available display modes of a panel + * @panel: DRM panel + * + * The modes probed from the panel are automatically added to the connector + * that the panel is attached to. + * + * Return: The number of modes available from the panel on success or a + * negative error code on failure. + */ +int drm_panel_get_modes(struct drm_panel *panel) +{ + if (panel && panel->funcs && panel->funcs->get_modes) + return panel->funcs->get_modes(panel); + + return panel ? -ENOSYS : -EINVAL; +} +EXPORT_SYMBOL(drm_panel_get_modes); + #ifdef CONFIG_OF /** * of_drm_find_panel - look up a panel using a device tree node diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 26377836141c..053d611656b9 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -97,97 +97,6 @@ struct drm_panel { struct list_head list; }; -/** - * drm_disable_unprepare - power off a panel - * @panel: DRM panel - * - * Calling this function will completely power off a panel (assert the panel's - * reset, turn off power supplies, ...). After this function has completed, it - * is usually no longer possible to communicate with the panel until another - * call to drm_panel_prepare(). - * - * Return: 0 on success or a negative error code on failure. - */ -static inline int drm_panel_unprepare(struct drm_panel *panel) -{ - if (panel && panel->funcs && panel->funcs->unprepare) - return panel->funcs->unprepare(panel); - - return panel ? -ENOSYS : -EINVAL; -} - -/** - * drm_panel_disable - disable a panel - * @panel: DRM panel - * - * This will typically turn off the panel's backlight or disable the display - * drivers. For smart panels it should still be possible to communicate with - * the integrated circuitry via any command bus after this call. - * - * Return: 0 on success or a negative error code on failure. - */ -static inline int drm_panel_disable(struct drm_panel *panel) -{ - if (panel && panel->funcs && panel->funcs->disable) - return panel->funcs->disable(panel); - - return panel ? -ENOSYS : -EINVAL; -} - -/** - * drm_panel_prepare - power on a panel - * @panel: DRM panel - * - * Calling this function will enable power and deassert any reset signals to - * the panel. After this has completed it is possible to communicate with any - * integrated circuitry via a command bus. - * - * Return: 0 on success or a negative error code on failure. - */ -static inline int drm_panel_prepare(struct drm_panel *panel) -{ - if (panel && panel->funcs && panel->funcs->prepare) - return panel->funcs->prepare(panel); - - return panel ? -ENOSYS : -EINVAL; -} - -/** - * drm_panel_enable - enable a panel - * @panel: DRM panel - * - * Calling this function will cause the panel display drivers to be turned on - * and the backlight to be enabled. Content will be visible on screen after - * this call completes. - * - * Return: 0 on success or a negative error code on failure. - */ -static inline int drm_panel_enable(struct drm_panel *panel) -{ - if (panel && panel->funcs && panel->funcs->enable) - return panel->funcs->enable(panel); - - return panel ? -ENOSYS : -EINVAL; -} - -/** - * drm_panel_get_modes - probe the available display modes of a panel - * @panel: DRM panel - * - * The modes probed from the panel are automatically added to the connector - * that the panel is attached to. - * - * Return: The number of modes available from the panel on success or a - * negative error code on failure. - */ -static inline int drm_panel_get_modes(struct drm_panel *panel) -{ - if (panel && panel->funcs && panel->funcs->get_modes) - return panel->funcs->get_modes(panel); - - return panel ? -ENOSYS : -EINVAL; -} - void drm_panel_init(struct drm_panel *panel); int drm_panel_add(struct drm_panel *panel); @@ -196,6 +105,14 @@ void drm_panel_remove(struct drm_panel *panel); int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector); int drm_panel_detach(struct drm_panel *panel); +int drm_panel_prepare(struct drm_panel *panel); +int drm_panel_unprepare(struct drm_panel *panel); + +int drm_panel_enable(struct drm_panel *panel); +int drm_panel_disable(struct drm_panel *panel); + +int drm_panel_get_modes(struct drm_panel *panel); + #if defined(CONFIG_OF) && defined(CONFIG_DRM_PANEL) struct drm_panel *of_drm_find_panel(const struct device_node *np); #else -- cgit v1.2.3 From e0d409ff16201e76e07ebb5ec942abfbaf21c661 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 4 Aug 2019 22:16:34 +0200 Subject: drm/panel: drop return code from drm_panel_detach() There are no errors that can be reported by this function, so drop the return code. Fix the only bridge driver that checked the return result. Signed-off-by: Sam Ravnborg Reviewed-by: Laurent Pinchart Reviewed-by: Emil Velikov Cc: Thierry Reding Cc: Sam Ravnborg Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Sean Paul Cc: David Airlie Cc: Daniel Vetter Cc: Laurent Pinchart Cc: Andrzej Hajda Cc: Gwan-gyeong Mun Cc: Thomas Gleixner Cc: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20190804201637.1240-14-sam@ravnborg.org --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 3 +-- drivers/gpu/drm/drm_panel.c | 6 +----- include/drm/drm_panel.h | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index f2f7f69d6cc3..22885dceaa17 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1780,8 +1780,7 @@ void analogix_dp_unbind(struct analogix_dp_device *dp) if (dp->plat_data->panel) { if (drm_panel_unprepare(dp->plat_data->panel)) DRM_ERROR("failed to turnoff the panel\n"); - if (drm_panel_detach(dp->plat_data->panel)) - DRM_ERROR("failed to detach the panel\n"); + drm_panel_detach(dp->plat_data->panel); } drm_dp_aux_unregister(&dp->aux); diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index a5fe28b17fb9..6b0bf42039cf 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -123,15 +123,11 @@ EXPORT_SYMBOL(drm_panel_attach); * * This function should not be called by the panel device itself. It * is only for the drm device that called drm_panel_attach(). - * - * Return: 0 on success or a negative error code on failure. */ -int drm_panel_detach(struct drm_panel *panel) +void drm_panel_detach(struct drm_panel *panel) { panel->connector = NULL; panel->drm = NULL; - - return 0; } EXPORT_SYMBOL(drm_panel_detach); diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h index 5e62deea49ba..624bd15ecfab 100644 --- a/include/drm/drm_panel.h +++ b/include/drm/drm_panel.h @@ -153,7 +153,7 @@ int drm_panel_add(struct drm_panel *panel); void drm_panel_remove(struct drm_panel *panel); int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector); -int drm_panel_detach(struct drm_panel *panel); +void drm_panel_detach(struct drm_panel *panel); int drm_panel_prepare(struct drm_panel *panel); int drm_panel_unprepare(struct drm_panel *panel); -- cgit v1.2.3 From 4c8b4c3855b0049f31be5bbfb19042005e98e822 Mon Sep 17 00:00:00 2001 From: Ondrej Jirman Date: Tue, 6 Aug 2019 17:57:42 +0200 Subject: drm: sun4i: Add support for enabling DDC I2C bus to sun8i_dw_hdmi glue Orange Pi 3 board requires enabling a voltage shifting circuit via GPIO for the DDC bus to be usable. Add support for hdmi-connector node's optional ddc-en-gpios property to support this use case. Signed-off-by: Ondrej Jirman Reviewed-by: Jernej Skrabec Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20190806155744.10263-4-megous@megous.com --- drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c | 54 ++++++++++++++++++++++++++++++++--- drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 2 ++ 2 files changed, 52 insertions(+), 4 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c index 8ca5af0c912f..a44dca4b0219 100644 --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c @@ -97,10 +97,34 @@ crtcs_exit: return crtcs; } +static int sun8i_dw_hdmi_find_connector_pdev(struct device *dev, + struct platform_device **pdev_out) +{ + struct platform_device *pdev; + struct device_node *remote; + + remote = of_graph_get_remote_node(dev->of_node, 1, -1); + if (!remote) + return -ENODEV; + + if (!of_device_is_compatible(remote, "hdmi-connector")) { + of_node_put(remote); + return -ENODEV; + } + + pdev = of_find_device_by_node(remote); + of_node_put(remote); + if (!pdev) + return -ENODEV; + + *pdev_out = pdev; + return 0; +} + static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, void *data) { - struct platform_device *pdev = to_platform_device(dev); + struct platform_device *pdev = to_platform_device(dev), *connector_pdev; struct dw_hdmi_plat_data *plat_data; struct drm_device *drm = data; struct device_node *phy_node; @@ -150,16 +174,30 @@ static int sun8i_dw_hdmi_bind(struct device *dev, struct device *master, return PTR_ERR(hdmi->regulator); } + ret = sun8i_dw_hdmi_find_connector_pdev(dev, &connector_pdev); + if (!ret) { + hdmi->ddc_en = gpiod_get_optional(&connector_pdev->dev, + "ddc-en", GPIOD_OUT_HIGH); + platform_device_put(connector_pdev); + + if (IS_ERR(hdmi->ddc_en)) { + dev_err(dev, "Couldn't get ddc-en gpio\n"); + return PTR_ERR(hdmi->ddc_en); + } + } + ret = regulator_enable(hdmi->regulator); if (ret) { dev_err(dev, "Failed to enable regulator\n"); - return ret; + goto err_unref_ddc_en; } + gpiod_set_value(hdmi->ddc_en, 1); + ret = reset_control_deassert(hdmi->rst_ctrl); if (ret) { dev_err(dev, "Could not deassert ctrl reset control\n"); - goto err_disable_regulator; + goto err_disable_ddc_en; } ret = clk_prepare_enable(hdmi->clk_tmds); @@ -212,8 +250,12 @@ err_disable_clk_tmds: clk_disable_unprepare(hdmi->clk_tmds); err_assert_ctrl_reset: reset_control_assert(hdmi->rst_ctrl); -err_disable_regulator: +err_disable_ddc_en: + gpiod_set_value(hdmi->ddc_en, 0); regulator_disable(hdmi->regulator); +err_unref_ddc_en: + if (hdmi->ddc_en) + gpiod_put(hdmi->ddc_en); return ret; } @@ -227,7 +269,11 @@ static void sun8i_dw_hdmi_unbind(struct device *dev, struct device *master, sun8i_hdmi_phy_remove(hdmi); clk_disable_unprepare(hdmi->clk_tmds); reset_control_assert(hdmi->rst_ctrl); + gpiod_set_value(hdmi->ddc_en, 0); regulator_disable(hdmi->regulator); + + if (hdmi->ddc_en) + gpiod_put(hdmi->ddc_en); } static const struct component_ops sun8i_dw_hdmi_ops = { diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h index 720c5aa8adc1..d707c9171824 100644 --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -190,6 +191,7 @@ struct sun8i_dw_hdmi { struct regulator *regulator; const struct sun8i_dw_hdmi_quirks *quirks; struct reset_control *rst_ctrl; + struct gpio_desc *ddc_en; }; static inline struct sun8i_dw_hdmi * -- cgit v1.2.3 From c550b60c647941b581e4b0f4f2b1526b34f4a8e5 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Sun, 11 Aug 2019 19:08:01 -0500 Subject: drm/komeda: Fix potential integer overflow in komeda_crtc_update_clock_ratio Add suffix ULL to constant 1000 in order to avoid a potential integer overflow and give the compiler complete information about the proper arithmetic to use. Notice that this constant is being used in a context that expects an expression of type u64, but it's currently evaluated using 32-bit arithmetic. Addresses-Coverity-ID: 1485796 ("Unintentional integer overflow") Fixes: ed22c6d9304d ("drm/komeda: Use drm_display_mode "crtc_" prefixed hardware timings") Signed-off-by: Gustavo A. R. Silva Reviewed-by: James Qian Wang (Arm Technology China) Signed-off-by: james qian wang (Arm Technology China) Link: https://patchwork.freedesktop.org/patch/msgid/20190812000801.GA29204@embeddedor --- drivers/gpu/drm/arm/display/komeda/komeda_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index fa9a4593bb37..624d257da20f 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c @@ -27,7 +27,7 @@ static void komeda_crtc_update_clock_ratio(struct komeda_crtc_state *kcrtc_st) return; } - pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000; + pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000ULL; aclk = komeda_crtc_get_aclk(kcrtc_st); kcrtc_st->clock_ratio = div64_u64(aclk << 32, pxlclk); -- cgit v1.2.3 From 12db36bc3cec76aae1c214d787eb0a54bc40fceb Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Mon, 12 Aug 2019 10:01:03 -0400 Subject: drm: Fix kerneldoc warns in connector-related docs Fixes the following warnings: ../drivers/gpu/drm/drm_connector.c:989: WARNING: Unexpected indentation. ../drivers/gpu/drm/drm_connector.c:993: WARNING: Unexpected indentation. ../include/drm/drm_connector.h:544: WARNING: Inline interpreted text or phrase reference start-string without end-string. ../include/drm/drm_connector.h:544: WARNING: Inline interpreted text or phrase reference start-string without end-string. Changes in v2: - Use () instead of & for functions (Sam) Fixes: 1b27fbdde1df ("drm: Add drm_atomic_get_(old|new)_connector_for_encoder() helpers") Fixes: bb5a45d40d50 ("drm/hdcp: update content protection property with uevent") Cc: Ramalingam C Cc: Daniel Vetter Cc: Pekka Paalanen Cc: Sam Ravnborg Cc: Laurent Pinchart Cc: Jani Nikula Cc: Sean Paul Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Sean Paul Cc: David Airlie Cc: dri-devel@lists.freedesktop.org Reviewed-by: Sam Ravnborg Signed-off-by: Sean Paul Link: https://patchwork.freedesktop.org/patch/msgid/20190812140112.6702-1-sean@poorly.run --- drivers/gpu/drm/drm_connector.c | 10 ++++++---- include/drm/drm_connector.h | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 354798bad576..4c766624b20d 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -986,12 +986,14 @@ static const struct drm_prop_enum_list hdmi_colorspaces[] = { * - Kernel sends uevent with the connector id and property id through * @drm_hdcp_update_content_protection, upon below kernel triggered * scenarios: - * DESIRED -> ENABLED (authentication success) - * ENABLED -> DESIRED (termination of authentication) + * + * - DESIRED -> ENABLED (authentication success) + * - ENABLED -> DESIRED (termination of authentication) * - Please note no uevents for userspace triggered property state changes, * which can't fail such as - * DESIRED/ENABLED -> UNDESIRED - * UNDESIRED -> DESIRED + * + * - DESIRED/ENABLED -> UNDESIRED + * - UNDESIRED -> DESIRED * - Userspace is responsible for polling the property or listen to uevents * to determine when the value transitions from ENABLED to DESIRED. * This signifies the link is no longer protected and userspace should diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 0b9997e27689..681cb590f952 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -543,8 +543,8 @@ struct drm_connector_state { * * This is also used in the atomic helpers to map encoders to their * current and previous connectors, see - * &drm_atomic_get_old_connector_for_encoder() and - * &drm_atomic_get_new_connector_for_encoder(). + * drm_atomic_get_old_connector_for_encoder() and + * drm_atomic_get_new_connector_for_encoder(). * * NOTE: Atomic drivers must fill this out (either themselves or through * helpers), for otherwise the GETCONNECTOR and GETENCODER IOCTLs will -- cgit v1.2.3 From f246ff5c232596dbd5e7a9d227113031fb0bfebe Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Mon, 12 Aug 2019 09:22:11 -0500 Subject: drm/syncobj: Add better overview documentation for syncobj (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch only brings the syncobj documentation up-to-date for the original form of syncobj. It does not contain any information about the design of timeline syncobjs. v2: Incorporate feedback from Lionel and Christian: - Mention actual ioctl and flag names - Better language around reference counting - Misc. language cleanups Signed-off-by: Jason Ekstrand Reviewed-by: Lionel Landwerlin Acked-by: Christian König Signed-off-by: Lionel Landwerlin Link: https://patchwork.freedesktop.org/patch/msgid/20190812142211.15885-1-jason@jlekstrand.net --- drivers/gpu/drm/drm_syncobj.c | 98 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 87 insertions(+), 11 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 1438dcb3ebb1..4b5c7b0ed714 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -29,21 +29,97 @@ /** * DOC: Overview * - * DRM synchronisation objects (syncobj, see struct &drm_syncobj) are - * persistent objects that contain an optional fence. The fence can be updated - * with a new fence, or be NULL. + * DRM synchronisation objects (syncobj, see struct &drm_syncobj) provide a + * container for a synchronization primitive which can be used by userspace + * to explicitly synchronize GPU commands, can be shared between userspace + * processes, and can be shared between different DRM drivers. + * Their primary use-case is to implement Vulkan fences and semaphores. + * The syncobj userspace API provides ioctls for several operations: * - * syncobj's can be waited upon, where it will wait for the underlying - * fence. + * - Creation and destruction of syncobjs + * - Import and export of syncobjs to/from a syncobj file descriptor + * - Import and export a syncobj's underlying fence to/from a sync file + * - Reset a syncobj (set its fence to NULL) + * - Signal a syncobj (set a trivially signaled fence) + * - Wait for a syncobj's fence to appear and be signaled * - * syncobj's can be export to fd's and back, these fd's are opaque and - * have no other use case, except passing the syncobj between processes. + * At it's core, a syncobj is simply a wrapper around a pointer to a struct + * &dma_fence which may be NULL. + * When a syncobj is first created, its pointer is either NULL or a pointer + * to an already signaled fence depending on whether the + * &DRM_SYNCOBJ_CREATE_SIGNALED flag is passed to + * &DRM_IOCTL_SYNCOBJ_CREATE. + * When GPU work which signals a syncobj is enqueued in a DRM driver, + * the syncobj fence is replaced with a fence which will be signaled by the + * completion of that work. + * When GPU work which waits on a syncobj is enqueued in a DRM driver, the + * driver retrieves syncobj's current fence at the time the work is enqueued + * waits on that fence before submitting the work to hardware. + * If the syncobj's fence is NULL, the enqueue operation is expected to fail. + * All manipulation of the syncobjs's fence happens in terms of the current + * fence at the time the ioctl is called by userspace regardless of whether + * that operation is an immediate host-side operation (signal or reset) or + * or an operation which is enqueued in some driver queue. + * &DRM_IOCTL_SYNCOBJ_RESET and &DRM_IOCTL_SYNCOBJ_SIGNAL can be used to + * manipulate a syncobj from the host by resetting its pointer to NULL or + * setting its pointer to a fence which is already signaled. * - * Their primary use-case is to implement Vulkan fences and semaphores. * - * syncobj have a kref reference count, but also have an optional file. - * The file is only created once the syncobj is exported. - * The file takes a reference on the kref. + * Host-side wait on syncobjs + * -------------------------- + * + * &DRM_IOCTL_SYNCOBJ_WAIT takes an array of syncobj handles and does a + * host-side wait on all of the syncobj fences simultaneously. + * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL is set, the wait ioctl will wait on + * all of the syncobj fences to be signaled before it returns. + * Otherwise, it returns once at least one syncobj fence has been signaled + * and the index of a signaled fence is written back to the client. + * + * Unlike the enqueued GPU work dependencies which fail if they see a NULL + * fence in a syncobj, if &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT is set, + * the host-side wait will first wait for the syncobj to receive a non-NULL + * fence and then wait on that fence. + * If &DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT is not set and any one of the + * syncobjs in the array has a NULL fence, -EINVAL will be returned. + * Assuming the syncobj starts off with a NULL fence, this allows a client + * to do a host wait in one thread (or process) which waits on GPU work + * submitted in another thread (or process) without having to manually + * synchronize between the two. + * This requirement is inherited from the Vulkan fence API. + * + * + * Import/export of syncobjs + * ------------------------- + * + * &DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE and &DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD + * provide two mechanisms for import/export of syncobjs. + * + * The first lets the client import or export an entire syncobj to a file + * descriptor. + * These fd's are opaque and have no other use case, except passing the + * syncobj between processes. + * All exported file descriptors and any syncobj handles created as a + * result of importing those file descriptors own a reference to the + * same underlying struct &drm_syncobj and the syncobj can be used + * persistently across all the processes with which it is shared. + * The syncobj is freed only once the last reference is dropped. + * Unlike dma-buf, importing a syncobj creates a new handle (with its own + * reference) for every import instead of de-duplicating. + * The primary use-case of this persistent import/export is for shared + * Vulkan fences and semaphores. + * + * The second import/export mechanism, which is indicated by + * &DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE or + * &DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE lets the client + * import/export the syncobj's current fence from/to a &sync_file. + * When a syncobj is exported to a sync file, that sync file wraps the + * sycnobj's fence at the time of export and any later signal or reset + * operations on the syncobj will not affect the exported sync file. + * When a sync file is imported into a syncobj, the syncobj's fence is set + * to the fence wrapped by that sync file. + * Because sync files are immutable, resetting or signaling the syncobj + * will not affect any sync files whose fences have been imported into the + * syncobj. */ #include -- cgit v1.2.3 From 8515090ce51441c29feb51e0634eb9c5a857469f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 30 Jul 2019 15:38:56 +0200 Subject: drm: gm12u320: Some minor cleanups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3 small cleanups: 1) Drop unused DRIVER_PATCHLEVEL 2) We do not set mode_config.preferred_depth, so instead of passing the unset mode_config.preferred_depth to drm_fbdev_generic_setup simply pass 0 3) Use __maybe_unused instead of #ifdef CONFIG_PM around the suspend / resume functions Cc: Sam Ravnborg Suggested-by: Sam Ravnborg Suggested-by: Noralf Trønnes Reviewed-by: Sam Ravnborg Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20190730133857.30778-1-hdegoede@redhat.com --- drivers/gpu/drm/tiny/gm12u320.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c index b6f47b8cf240..eba064623acf 100644 --- a/drivers/gpu/drm/tiny/gm12u320.c +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -33,7 +33,6 @@ MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)"); #define DRIVER_DATE "2019" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 -#define DRIVER_PATCHLEVEL 1 /* * The DLP has an actual width of 854 pixels, but that is not a multiple @@ -746,7 +745,7 @@ static int gm12u320_usb_probe(struct usb_interface *interface, if (ret) goto err_put; - drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth); + drm_fbdev_generic_setup(dev, 0); return 0; @@ -765,9 +764,8 @@ static void gm12u320_usb_disconnect(struct usb_interface *interface) drm_dev_put(dev); } -#ifdef CONFIG_PM -static int gm12u320_suspend(struct usb_interface *interface, - pm_message_t message) +static __maybe_unused int gm12u320_suspend(struct usb_interface *interface, + pm_message_t message) { struct drm_device *dev = usb_get_intfdata(interface); struct gm12u320_device *gm12u320 = dev->dev_private; @@ -778,7 +776,7 @@ static int gm12u320_suspend(struct usb_interface *interface, return 0; } -static int gm12u320_resume(struct usb_interface *interface) +static __maybe_unused int gm12u320_resume(struct usb_interface *interface) { struct drm_device *dev = usb_get_intfdata(interface); struct gm12u320_device *gm12u320 = dev->dev_private; @@ -789,7 +787,6 @@ static int gm12u320_resume(struct usb_interface *interface) return 0; } -#endif static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1de1, 0xc102) }, -- cgit v1.2.3 From 4abfa2e4e74f22fff67d561d01f8e080b5b547be Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 30 Jul 2019 15:38:57 +0200 Subject: drm: gm12u320: Use DRM_DEV_ERROR everywhere Previously the driver was using a mix of DRM_ERROR and dev_err, be consisent and use DRM_DEV_ERROR everywhere instead. Cc: Sam Ravnborg Suggested-by: Sam Ravnborg Reviewed-by: Sam Ravnborg Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20190730133857.30778-2-hdegoede@redhat.com --- drivers/gpu/drm/tiny/gm12u320.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c index eba064623acf..1fd6db52af92 100644 --- a/drivers/gpu/drm/tiny/gm12u320.c +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -44,6 +44,9 @@ MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)"); #define GM12U320_BLOCK_COUNT 20 +#define GM12U320_ERR(fmt, ...) \ + DRM_DEV_ERROR(&gm12u320->udev->dev, fmt, ##__VA_ARGS__) + #define MISC_RCV_EPT 1 #define DATA_RCV_EPT 2 #define DATA_SND_EPT 3 @@ -219,7 +222,7 @@ static int gm12u320_misc_request(struct gm12u320_device *gm12u320, usb_sndbulkpipe(gm12u320->udev, MISC_SND_EPT), gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT); if (ret || len != CMD_SIZE) { - dev_err(&gm12u320->udev->dev, "Misc. req. error %d\n", ret); + GM12U320_ERR("Misc. req. error %d\n", ret); return -EIO; } @@ -229,7 +232,7 @@ static int gm12u320_misc_request(struct gm12u320_device *gm12u320, gm12u320->cmd_buf, MISC_VALUE_SIZE, &len, DATA_TIMEOUT); if (ret || len != MISC_VALUE_SIZE) { - dev_err(&gm12u320->udev->dev, "Misc. value error %d\n", ret); + GM12U320_ERR("Misc. value error %d\n", ret); return -EIO; } /* cmd_buf[0] now contains the read value, which we don't use */ @@ -240,7 +243,7 @@ static int gm12u320_misc_request(struct gm12u320_device *gm12u320, gm12u320->cmd_buf, READ_STATUS_SIZE, &len, CMD_TIMEOUT); if (ret || len != READ_STATUS_SIZE) { - dev_err(&gm12u320->udev->dev, "Misc. status error %d\n", ret); + GM12U320_ERR("Misc. status error %d\n", ret); return -EIO; } @@ -277,7 +280,7 @@ static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320) vaddr = drm_gem_shmem_vmap(fb->obj[0]); if (IS_ERR(vaddr)) { - DRM_ERROR("failed to vmap fb: %ld\n", PTR_ERR(vaddr)); + GM12U320_ERR("failed to vmap fb: %ld\n", PTR_ERR(vaddr)); goto put_fb; } @@ -285,7 +288,7 @@ static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320) ret = dma_buf_begin_cpu_access( fb->obj[0]->import_attach->dmabuf, DMA_FROM_DEVICE); if (ret) { - DRM_ERROR("dma_buf_begin_cpu_access err: %d\n", ret); + GM12U320_ERR("dma_buf_begin_cpu_access err: %d\n", ret); goto vunmap; } } @@ -328,7 +331,7 @@ static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320) ret = dma_buf_end_cpu_access(fb->obj[0]->import_attach->dmabuf, DMA_FROM_DEVICE); if (ret) - DRM_ERROR("dma_buf_end_cpu_access err: %d\n", ret); + GM12U320_ERR("dma_buf_end_cpu_access err: %d\n", ret); } vunmap: drm_gem_shmem_vunmap(fb->obj[0], vaddr); @@ -430,7 +433,7 @@ static void gm12u320_fb_update_work(struct work_struct *work) err: /* Do not log errors caused by module unload or device unplug */ if (ret != -ECONNRESET && ret != -ESHUTDOWN) - dev_err(&gm12u320->udev->dev, "Frame update error: %d\n", ret); + GM12U320_ERR("Frame update error: %d\n", ret); } static void gm12u320_fb_mark_dirty(struct drm_framebuffer *fb, -- cgit v1.2.3 From 9b61db1aed5c62180a374ab4dd774d1625bdd8d4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 11 Aug 2019 16:37:24 +0200 Subject: drm: gm12u320: Do not take a mutex from a wait_event condition I made the condition of the wait_event_timeout call in gm12u320_fb_update_work a helper which takes a mutex to make sure that any writes to fb_update.run or fb_update.fb from other CPU cores are seen before the check is done. This is not necessary as the wait_event helpers contain the necessary barriers for this themselves. More over it is harmfull since by the time the check is done the task is no longer in the TASK_RUNNING state and calling mutex_lock while not in task-running is not allowed, leading to this warning when the kernel is build with some extra locking checks enabled: [11947.450011] do not call blocking ops when !TASK_RUNNING; state=2 set at [<00000000e4306de6>] prepare_to_wait_event+0x61/0x190 This commit fixes this by dropping the helper and simply directly checking the condition (without unnecessary locking) in the wait_event_timeout call. Acked-by: Sam Ravnborg Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20190811143725.5951-1-hdegoede@redhat.com --- drivers/gpu/drm/tiny/gm12u320.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c index 1fd6db52af92..aa4b46e47e19 100644 --- a/drivers/gpu/drm/tiny/gm12u320.c +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -342,17 +342,6 @@ unlock: mutex_unlock(&gm12u320->fb_update.lock); } -static int gm12u320_fb_update_ready(struct gm12u320_device *gm12u320) -{ - int ret; - - mutex_lock(&gm12u320->fb_update.lock); - ret = !gm12u320->fb_update.run || gm12u320->fb_update.fb != NULL; - mutex_unlock(&gm12u320->fb_update.lock); - - return ret; -} - static void gm12u320_fb_update_work(struct work_struct *work) { struct gm12u320_device *gm12u320 = @@ -426,7 +415,8 @@ static void gm12u320_fb_update_work(struct work_struct *work) * switches back to showing its logo. */ wait_event_timeout(gm12u320->fb_update.waitq, - gm12u320_fb_update_ready(gm12u320), + !gm12u320->fb_update.run || + gm12u320->fb_update.fb != NULL, IDLE_TIMEOUT); } return; -- cgit v1.2.3 From ac9fd659ef8cac9a71f0ef943ef6da04f1939775 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 11 Aug 2019 16:37:25 +0200 Subject: drm: gm12u320: Add -ENODEV to list of errors to ignore Add -ENODEV to the list of usb-transfer errors which we ignore to avoid logging Frame update errors when the device gets unplugged. Acked-by: Sam Ravnborg Signed-off-by: Hans de Goede Link: https://patchwork.freedesktop.org/patch/msgid/20190811143725.5951-2-hdegoede@redhat.com --- drivers/gpu/drm/tiny/gm12u320.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c index aa4b46e47e19..03d0e2df6774 100644 --- a/drivers/gpu/drm/tiny/gm12u320.c +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -422,7 +422,7 @@ static void gm12u320_fb_update_work(struct work_struct *work) return; err: /* Do not log errors caused by module unload or device unplug */ - if (ret != -ECONNRESET && ret != -ESHUTDOWN) + if (ret != -ENODEV && ret != -ECONNRESET && ret != -ESHUTDOWN) GM12U320_ERR("Frame update error: %d\n", ret); } -- cgit v1.2.3 From 930a402485b205214231f1141632afdca8ff89cb Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 19 Jul 2019 08:28:51 -0600 Subject: drm/gem: Allow sparsely populated page arrays in drm_gem_put_pages Panfrost has a need for pages allocated on demand via GPU page faults. When releasing the pages, the only thing preventing using drm_gem_put_pages() is needing to skip over unpopulated pages, so allow for skipping over NULL struct page pointers. Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Sean Paul Cc: David Airlie Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Reviewed-by: Steven Price Acked-by: Alyssa Rosenzweig Reviewed-by: Eric Anholt Signed-off-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20190808222200.13176-2-robh@kernel.org --- drivers/gpu/drm/drm_gem.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index afc38cece3f5..a2dd198177f2 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -633,6 +633,9 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages, pagevec_init(&pvec); for (i = 0; i < npages; i++) { + if (!pages[i]) + continue; + if (dirty) set_page_dirty(pages[i]); -- cgit v1.2.3 From 3bf5189d93d04519e93e16bf3aa60589e136c666 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 19 Jul 2019 08:30:12 -0600 Subject: drm/shmem: Put pages independent of a SG table being set If a driver does its own management of pages, the shmem helper object's pages array could be allocated when a SG table is not. There's not really any good reason to tie putting pages with having a SG table when freeing the object, so just put pages if the pages array is populated. Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Sean Paul Cc: David Airlie Cc: Daniel Vetter Reviewed-by: Steven Price Acked-by: Alyssa Rosenzweig Reviewed-by: Eric Anholt Signed-off-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20190808222200.13176-3-robh@kernel.org --- drivers/gpu/drm/drm_gem_shmem_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index 4b442576de1c..df8f2c8adb2b 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -119,11 +119,11 @@ void drm_gem_shmem_free_object(struct drm_gem_object *obj) if (shmem->sgt) { dma_unmap_sg(obj->dev->dev, shmem->sgt->sgl, shmem->sgt->nents, DMA_BIDIRECTIONAL); - - drm_gem_shmem_put_pages(shmem); sg_free_table(shmem->sgt); kfree(shmem->sgt); } + if (shmem->pages) + drm_gem_shmem_put_pages(shmem); } WARN_ON(shmem->pages_use_count); -- cgit v1.2.3 From a5efb4c9a562aa1c2ffa27b0477ae7b20c309344 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 1 Jul 2019 17:03:30 -0600 Subject: drm/panfrost: Restructure the GEM object creation Setting the GPU VA when creating the GEM object doesn't allow for any conditional adjustments to the mapping. In preparation to support adjusting the mapping and per FD address spaces, restructure the GEM object creation to map and unmap the GEM object in the GEM object .open() and .close() hooks. While panfrost_gem_free_object() and panfrost_gem_prime_import_sg_table() are not really needed after this commit, keep them as we'll need them in subsequent commits. Cc: Tomeu Vizoso Cc: Boris Brezillon Cc: Robin Murphy Reviewed-by: Steven Price Acked-by: Alyssa Rosenzweig Signed-off-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20190808222200.13176-4-robh@kernel.org --- drivers/gpu/drm/panfrost/panfrost_drv.c | 9 ----- drivers/gpu/drm/panfrost/panfrost_gem.c | 68 +++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 38 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index 926d021ee202..2894cfbbce2b 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -78,7 +78,6 @@ static int panfrost_ioctl_get_param(struct drm_device *ddev, void *data, struct static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *file) { - int ret; struct drm_gem_shmem_object *shmem; struct drm_panfrost_create_bo *args = data; @@ -90,17 +89,9 @@ static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, if (IS_ERR(shmem)) return PTR_ERR(shmem); - ret = panfrost_mmu_map(to_panfrost_bo(&shmem->base)); - if (ret) - goto err_free; - args->offset = to_panfrost_bo(&shmem->base)->node.start << PAGE_SHIFT; return 0; - -err_free: - drm_gem_handle_delete(file, args->handle); - return ret; } /** diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index 67d374184340..d0b0f5f2270e 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -19,13 +19,6 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj) struct panfrost_gem_object *bo = to_panfrost_bo(obj); struct panfrost_device *pfdev = obj->dev->dev_private; - if (bo->is_mapped) - panfrost_mmu_unmap(bo); - - spin_lock(&pfdev->mm_lock); - drm_mm_remove_node(&bo->node); - spin_unlock(&pfdev->mm_lock); - mutex_lock(&pfdev->shrinker_lock); if (!list_empty(&bo->base.madv_list)) list_del(&bo->base.madv_list); @@ -34,8 +27,47 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj) drm_gem_shmem_free_object(obj); } +static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv) +{ + int ret; + size_t size = obj->size; + u64 align = size >= SZ_2M ? SZ_2M >> PAGE_SHIFT : 0; + struct panfrost_gem_object *bo = to_panfrost_bo(obj); + struct panfrost_device *pfdev = obj->dev->dev_private; + + spin_lock(&pfdev->mm_lock); + ret = drm_mm_insert_node_generic(&pfdev->mm, &bo->node, + size >> PAGE_SHIFT, align, 0, 0); + if (ret) + goto out; + + ret = panfrost_mmu_map(bo); + if (ret) + drm_mm_remove_node(&bo->node); + +out: + spin_unlock(&pfdev->mm_lock); + return ret; +} + +static void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv) +{ + struct panfrost_gem_object *bo = to_panfrost_bo(obj); + struct panfrost_device *pfdev = obj->dev->dev_private; + + if (bo->is_mapped) + panfrost_mmu_unmap(bo); + + spin_lock(&pfdev->mm_lock); + if (drm_mm_node_allocated(&bo->node)) + drm_mm_remove_node(&bo->node); + spin_unlock(&pfdev->mm_lock); +} + static const struct drm_gem_object_funcs panfrost_gem_funcs = { .free = panfrost_gem_free_object, + .open = panfrost_gem_open, + .close = panfrost_gem_close, .print_info = drm_gem_shmem_print_info, .pin = drm_gem_shmem_pin, .unpin = drm_gem_shmem_unpin, @@ -55,10 +87,7 @@ static const struct drm_gem_object_funcs panfrost_gem_funcs = { */ struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t size) { - int ret; - struct panfrost_device *pfdev = dev->dev_private; struct panfrost_gem_object *obj; - u64 align; obj = kzalloc(sizeof(*obj), GFP_KERNEL); if (!obj) @@ -66,21 +95,7 @@ struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t obj->base.base.funcs = &panfrost_gem_funcs; - size = roundup(size, PAGE_SIZE); - align = size >= SZ_2M ? SZ_2M >> PAGE_SHIFT : 0; - - spin_lock(&pfdev->mm_lock); - ret = drm_mm_insert_node_generic(&pfdev->mm, &obj->node, - size >> PAGE_SHIFT, align, 0, 0); - spin_unlock(&pfdev->mm_lock); - if (ret) - goto free_obj; - return &obj->base.base; - -free_obj: - kfree(obj); - return ERR_PTR(ret); } struct drm_gem_object * @@ -89,15 +104,10 @@ panfrost_gem_prime_import_sg_table(struct drm_device *dev, struct sg_table *sgt) { struct drm_gem_object *obj; - struct panfrost_gem_object *pobj; obj = drm_gem_shmem_prime_import_sg_table(dev, attach, sgt); if (IS_ERR(obj)) return ERR_CAST(obj); - pobj = to_panfrost_bo(obj); - - panfrost_mmu_map(pobj); - return obj; } -- cgit v1.2.3 From eecbb3cdcccac24e1e67e92fec24f9035fe19784 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 1 Jul 2019 17:05:43 -0600 Subject: drm/panfrost: Split panfrost_mmu_map SG list mapping to its own function In preparation to create partial GPU mappings of BOs on page faults, split out the SG list handling of panfrost_mmu_map(). Cc: Tomeu Vizoso Cc: Boris Brezillon Cc: Robin Murphy Reviewed: Steven Price Acked-by: Alyssa Rosenzweig Signed-off-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20190808222200.13176-5-robh@kernel.org --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 52 ++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index 92ac995dd9c6..b4ac149b2399 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -145,27 +145,13 @@ static size_t get_pgsize(u64 addr, size_t size) return SZ_2M; } -int panfrost_mmu_map(struct panfrost_gem_object *bo) +static int mmu_map_sg(struct panfrost_device *pfdev, u64 iova, + int prot, struct sg_table *sgt) { - struct drm_gem_object *obj = &bo->base.base; - struct panfrost_device *pfdev = to_panfrost_device(obj->dev); - struct io_pgtable_ops *ops = pfdev->mmu->pgtbl_ops; - u64 iova = bo->node.start << PAGE_SHIFT; unsigned int count; struct scatterlist *sgl; - struct sg_table *sgt; - int ret; - - if (WARN_ON(bo->is_mapped)) - return 0; - - sgt = drm_gem_shmem_get_pages_sgt(obj); - if (WARN_ON(IS_ERR(sgt))) - return PTR_ERR(sgt); - - ret = pm_runtime_get_sync(pfdev->dev); - if (ret < 0) - return ret; + struct io_pgtable_ops *ops = pfdev->mmu->pgtbl_ops; + u64 start_iova = iova; mutex_lock(&pfdev->mmu->lock); @@ -178,18 +164,42 @@ int panfrost_mmu_map(struct panfrost_gem_object *bo) while (len) { size_t pgsize = get_pgsize(iova | paddr, len); - ops->map(ops, iova, paddr, pgsize, IOMMU_WRITE | IOMMU_READ); + ops->map(ops, iova, paddr, pgsize, prot); iova += pgsize; paddr += pgsize; len -= pgsize; } } - mmu_hw_do_operation(pfdev, 0, bo->node.start << PAGE_SHIFT, - bo->node.size << PAGE_SHIFT, AS_COMMAND_FLUSH_PT); + mmu_hw_do_operation(pfdev, 0, start_iova, iova - start_iova, + AS_COMMAND_FLUSH_PT); mutex_unlock(&pfdev->mmu->lock); + return 0; +} + +int panfrost_mmu_map(struct panfrost_gem_object *bo) +{ + struct drm_gem_object *obj = &bo->base.base; + struct panfrost_device *pfdev = to_panfrost_device(obj->dev); + struct sg_table *sgt; + int ret; + int prot = IOMMU_READ | IOMMU_WRITE; + + if (WARN_ON(bo->is_mapped)) + return 0; + + sgt = drm_gem_shmem_get_pages_sgt(obj); + if (WARN_ON(IS_ERR(sgt))) + return PTR_ERR(sgt); + + ret = pm_runtime_get_sync(pfdev->dev); + if (ret < 0) + return ret; + + mmu_map_sg(pfdev, bo->node.start << PAGE_SHIFT, prot, sgt); + pm_runtime_mark_last_busy(pfdev->dev); pm_runtime_put_autosuspend(pfdev->dev); bo->is_mapped = true; -- cgit v1.2.3 From 203270c025be02d52feca729d9193860317c2e82 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 11 Jul 2019 15:56:14 -0600 Subject: drm/panfrost: Add a no execute flag for BO allocations Executable buffers have an alignment restriction that they can't cross 16MB boundary as the GPU program counter is 24-bits. This restriction is currently not handled and we just get lucky. As current userspace assumes all BOs are executable, that has to remain the default. So add a new PANFROST_BO_NOEXEC flag to allow userspace to indicate which BOs are not executable. There is also a restriction that executable buffers cannot start or end on a 4GB boundary. This is mostly avoided as there is only 4GB of space currently and the beginning is already blocked out for NULL ptr detection. Add support to handle this restriction fully regardless of the current constraints. For existing userspace, all created BOs remain executable, but the GPU VA alignment will be increased to the size of the BO. This shouldn't matter as there is plenty of GPU VA space. Cc: Tomeu Vizoso Cc: Boris Brezillon Cc: Robin Murphy Reviewed-by: Steven Price Acked-by: Alyssa Rosenzweig Signed-off-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20190808222200.13176-6-robh@kernel.org --- drivers/gpu/drm/panfrost/panfrost_drv.c | 42 ++++++++++++++++++++++----- drivers/gpu/drm/panfrost/panfrost_gem.c | 50 +++++++++++++++++++++++++++++++-- drivers/gpu/drm/panfrost/panfrost_gem.h | 9 +++++- drivers/gpu/drm/panfrost/panfrost_mmu.c | 3 ++ include/uapi/drm/panfrost_drm.h | 2 ++ 5 files changed, 96 insertions(+), 10 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index 2894cfbbce2b..f070f2dd9f84 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -78,18 +78,19 @@ static int panfrost_ioctl_get_param(struct drm_device *ddev, void *data, struct static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_file *file) { - struct drm_gem_shmem_object *shmem; + struct panfrost_gem_object *bo; struct drm_panfrost_create_bo *args = data; - if (!args->size || args->flags || args->pad) + if (!args->size || args->pad || + (args->flags & ~PANFROST_BO_NOEXEC)) return -EINVAL; - shmem = drm_gem_shmem_create_with_handle(file, dev, args->size, - &args->handle); - if (IS_ERR(shmem)) - return PTR_ERR(shmem); + bo = panfrost_gem_create_with_handle(file, dev, args->size, args->flags, + &args->handle); + if (IS_ERR(bo)) + return PTR_ERR(bo); - args->offset = to_panfrost_bo(&shmem->base)->node.start << PAGE_SHIFT; + args->offset = bo->node.start << PAGE_SHIFT; return 0; } @@ -364,6 +365,32 @@ int panfrost_unstable_ioctl_check(void) return 0; } +#define PFN_4G (SZ_4G >> PAGE_SHIFT) +#define PFN_4G_MASK (PFN_4G - 1) +#define PFN_16M (SZ_16M >> PAGE_SHIFT) + +static void panfrost_drm_mm_color_adjust(const struct drm_mm_node *node, + unsigned long color, + u64 *start, u64 *end) +{ + /* Executable buffers can't start or end on a 4GB boundary */ + if (!(color & PANFROST_BO_NOEXEC)) { + u64 next_seg; + + if ((*start & PFN_4G_MASK) == 0) + (*start)++; + + if ((*end & PFN_4G_MASK) == 0) + (*end)--; + + next_seg = ALIGN(*start, PFN_4G); + if (next_seg - *start <= PFN_16M) + *start = next_seg + 1; + + *end = min(*end, ALIGN(*start, PFN_4G) - 1); + } +} + static int panfrost_open(struct drm_device *dev, struct drm_file *file) { @@ -461,6 +488,7 @@ static int panfrost_probe(struct platform_device *pdev) /* 4G enough for now. can be 48-bit */ drm_mm_init(&pfdev->mm, SZ_32M >> PAGE_SHIFT, (SZ_4G - SZ_32M) >> PAGE_SHIFT); + pfdev->mm.color_adjust = panfrost_drm_mm_color_adjust; pm_runtime_use_autosuspend(pfdev->dev); pm_runtime_set_autosuspend_delay(pfdev->dev, 50); /* ~3 frames */ diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index d0b0f5f2270e..1a3bde3dc662 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -31,13 +31,25 @@ static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_p { int ret; size_t size = obj->size; - u64 align = size >= SZ_2M ? SZ_2M >> PAGE_SHIFT : 0; + u64 align; struct panfrost_gem_object *bo = to_panfrost_bo(obj); struct panfrost_device *pfdev = obj->dev->dev_private; + unsigned long color = bo->noexec ? PANFROST_BO_NOEXEC : 0; + + /* + * Executable buffers cannot cross a 16MB boundary as the program + * counter is 24-bits. We assume executable buffers will be less than + * 16MB and aligning executable buffers to their size will avoid + * crossing a 16MB boundary. + */ + if (!bo->noexec) + align = size >> PAGE_SHIFT; + else + align = size >= SZ_2M ? SZ_2M >> PAGE_SHIFT : 0; spin_lock(&pfdev->mm_lock); ret = drm_mm_insert_node_generic(&pfdev->mm, &bo->node, - size >> PAGE_SHIFT, align, 0, 0); + size >> PAGE_SHIFT, align, color, 0); if (ret) goto out; @@ -98,16 +110,50 @@ struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t return &obj->base.base; } +struct panfrost_gem_object * +panfrost_gem_create_with_handle(struct drm_file *file_priv, + struct drm_device *dev, size_t size, + u32 flags, + uint32_t *handle) +{ + int ret; + struct drm_gem_shmem_object *shmem; + struct panfrost_gem_object *bo; + + shmem = drm_gem_shmem_create(dev, size); + if (IS_ERR(shmem)) + return ERR_CAST(shmem); + + bo = to_panfrost_bo(&shmem->base); + bo->noexec = !!(flags & PANFROST_BO_NOEXEC); + + /* + * Allocate an id of idr table where the obj is registered + * and handle has the id what user can see. + */ + ret = drm_gem_handle_create(file_priv, &shmem->base, handle); + /* drop reference from allocate - handle holds it now. */ + drm_gem_object_put_unlocked(&shmem->base); + if (ret) + return ERR_PTR(ret); + + return bo; +} + struct drm_gem_object * panfrost_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt) { struct drm_gem_object *obj; + struct panfrost_gem_object *bo; obj = drm_gem_shmem_prime_import_sg_table(dev, attach, sgt); if (IS_ERR(obj)) return ERR_CAST(obj); + bo = to_panfrost_bo(obj); + bo->noexec = true; + return obj; } diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.h b/drivers/gpu/drm/panfrost/panfrost_gem.h index 5f51f881ea3f..d4c7aa1790a7 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.h +++ b/drivers/gpu/drm/panfrost/panfrost_gem.h @@ -11,7 +11,8 @@ struct panfrost_gem_object { struct drm_gem_shmem_object base; struct drm_mm_node node; - bool is_mapped; + bool is_mapped :1; + bool noexec :1; }; static inline @@ -27,6 +28,12 @@ panfrost_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sgt); +struct panfrost_gem_object * +panfrost_gem_create_with_handle(struct drm_file *file_priv, + struct drm_device *dev, size_t size, + u32 flags, + uint32_t *handle); + void panfrost_gem_shrinker_init(struct drm_device *dev); void panfrost_gem_shrinker_cleanup(struct drm_device *dev); diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index b4ac149b2399..eba6ce785ef0 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -190,6 +190,9 @@ int panfrost_mmu_map(struct panfrost_gem_object *bo) if (WARN_ON(bo->is_mapped)) return 0; + if (bo->noexec) + prot |= IOMMU_NOEXEC; + sgt = drm_gem_shmem_get_pages_sgt(obj); if (WARN_ON(IS_ERR(sgt))) return PTR_ERR(sgt); diff --git a/include/uapi/drm/panfrost_drm.h b/include/uapi/drm/panfrost_drm.h index 1e547f9692e9..b80c20d17dec 100644 --- a/include/uapi/drm/panfrost_drm.h +++ b/include/uapi/drm/panfrost_drm.h @@ -84,6 +84,8 @@ struct drm_panfrost_wait_bo { __s64 timeout_ns; /* absolute */ }; +#define PANFROST_BO_NOEXEC 1 + /** * struct drm_panfrost_create_bo - ioctl argument for creating Panfrost BOs. * -- cgit v1.2.3 From 73e467f60acdabd480d1b377a623ba13db0e5dd2 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Thu, 8 Aug 2019 14:30:39 -0600 Subject: drm/panfrost: Consolidate reset handling Runtime PM resume and job timeouts both call the same sequence of functions, so consolidate them to a common function. This will make changing the reset related code easier. The MMU also needs some re-initialization on reset, so rework its call. In the process, we hide the address space details within the MMU code in preparation to support multiple address spaces. Cc: Tomeu Vizoso Cc: David Airlie Cc: Daniel Vetter Cc: Robin Murphy Cc: Alyssa Rosenzweig Reviewed-by: Steven Price Signed-off-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20190808222200.13176-7-robh@kernel.org --- drivers/gpu/drm/panfrost/panfrost_device.c | 16 ++++++++++------ drivers/gpu/drm/panfrost/panfrost_device.h | 1 + drivers/gpu/drm/panfrost/panfrost_job.c | 7 +------ drivers/gpu/drm/panfrost/panfrost_mmu.c | 16 +++++++++------- drivers/gpu/drm/panfrost/panfrost_mmu.h | 3 +-- 5 files changed, 22 insertions(+), 21 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panfrost/panfrost_device.c b/drivers/gpu/drm/panfrost/panfrost_device.c index 8a111d7c0200..9814f4ccbd26 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.c +++ b/drivers/gpu/drm/panfrost/panfrost_device.c @@ -254,18 +254,22 @@ const char *panfrost_exception_name(struct panfrost_device *pfdev, u32 exception return "UNKNOWN"; } +void panfrost_device_reset(struct panfrost_device *pfdev) +{ + panfrost_gpu_soft_reset(pfdev); + + panfrost_gpu_power_on(pfdev); + panfrost_mmu_reset(pfdev); + panfrost_job_enable_interrupts(pfdev); +} + #ifdef CONFIG_PM int panfrost_device_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct panfrost_device *pfdev = platform_get_drvdata(pdev); - panfrost_gpu_soft_reset(pfdev); - - /* TODO: Re-enable all other address spaces */ - panfrost_gpu_power_on(pfdev); - panfrost_mmu_enable(pfdev, 0); - panfrost_job_enable_interrupts(pfdev); + panfrost_device_reset(pfdev); panfrost_devfreq_resume(pfdev); return 0; diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h index 038b32c62484..4e5641db9c7e 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.h +++ b/drivers/gpu/drm/panfrost/panfrost_device.h @@ -132,6 +132,7 @@ int panfrost_unstable_ioctl_check(void); int panfrost_device_init(struct panfrost_device *pfdev); void panfrost_device_fini(struct panfrost_device *pfdev); +void panfrost_device_reset(struct panfrost_device *pfdev); int panfrost_device_resume(struct device *dev); int panfrost_device_suspend(struct device *dev); diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index 9bb9260d9181..d567ce98494c 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -395,12 +395,7 @@ static void panfrost_job_timedout(struct drm_sched_job *sched_job) /* panfrost_core_dump(pfdev); */ panfrost_devfreq_record_transition(pfdev, js); - panfrost_gpu_soft_reset(pfdev); - - /* TODO: Re-enable all other address spaces */ - panfrost_mmu_enable(pfdev, 0); - panfrost_gpu_power_on(pfdev); - panfrost_job_enable_interrupts(pfdev); + panfrost_device_reset(pfdev); for (i = 0; i < NUM_JOB_SLOTS; i++) drm_sched_resubmit_jobs(&pfdev->js->queue[i].sched); diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index eba6ce785ef0..13757427b886 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -105,15 +105,12 @@ static int mmu_hw_do_operation(struct panfrost_device *pfdev, u32 as_nr, return ret; } -void panfrost_mmu_enable(struct panfrost_device *pfdev, u32 as_nr) +static void panfrost_mmu_enable(struct panfrost_device *pfdev, u32 as_nr) { struct io_pgtable_cfg *cfg = &pfdev->mmu->pgtbl_cfg; u64 transtab = cfg->arm_mali_lpae_cfg.transtab; u64 memattr = cfg->arm_mali_lpae_cfg.memattr; - mmu_write(pfdev, MMU_INT_CLEAR, ~0); - mmu_write(pfdev, MMU_INT_MASK, ~0); - mmu_write(pfdev, AS_TRANSTAB_LO(as_nr), transtab & 0xffffffffUL); mmu_write(pfdev, AS_TRANSTAB_HI(as_nr), transtab >> 32); @@ -137,6 +134,14 @@ static void mmu_disable(struct panfrost_device *pfdev, u32 as_nr) write_cmd(pfdev, as_nr, AS_COMMAND_UPDATE); } +void panfrost_mmu_reset(struct panfrost_device *pfdev) +{ + panfrost_mmu_enable(pfdev, 0); + + mmu_write(pfdev, MMU_INT_CLEAR, ~0); + mmu_write(pfdev, MMU_INT_MASK, ~0); +} + static size_t get_pgsize(u64 addr, size_t size) { if (addr & (SZ_2M - 1) || size < SZ_2M) @@ -375,9 +380,6 @@ int panfrost_mmu_init(struct panfrost_device *pfdev) dev_err(pfdev->dev, "failed to request mmu irq"); return err; } - mmu_write(pfdev, MMU_INT_CLEAR, ~0); - mmu_write(pfdev, MMU_INT_MASK, ~0); - pfdev->mmu->pgtbl_cfg = (struct io_pgtable_cfg) { .pgsize_bitmap = SZ_4K | SZ_2M, .ias = FIELD_GET(0xff, pfdev->features.mmu_features), diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.h b/drivers/gpu/drm/panfrost/panfrost_mmu.h index f5878d86a5ce..d5f9b24537db 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.h +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.h @@ -11,7 +11,6 @@ void panfrost_mmu_unmap(struct panfrost_gem_object *bo); int panfrost_mmu_init(struct panfrost_device *pfdev); void panfrost_mmu_fini(struct panfrost_device *pfdev); - -void panfrost_mmu_enable(struct panfrost_device *pfdev, u32 as_nr); +void panfrost_mmu_reset(struct panfrost_device *pfdev); #endif -- cgit v1.2.3 From b31bdd1389fc765c07ab3d5b341092cb16807d29 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 26 Jul 2019 16:06:57 -0600 Subject: drm/panfrost: Convert MMU IRQ handler to threaded handler In preparation to handle mapping of page faults, we need the MMU handler to be threaded as code paths take a mutex. As the IRQ may be shared, we can't use the default handler and must disable the MMU interrupts locally. Cc: Tomeu Vizoso Cc: Boris Brezillon Cc: Robin Murphy Reviewed-by: Steven Price Acked-by: Alyssa Rosenzweig Signed-off-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20190808222200.13176-8-robh@kernel.org --- drivers/gpu/drm/panfrost/panfrost_mmu.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index 13757427b886..b609ee55a872 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -305,12 +305,20 @@ static const char *access_type_name(struct panfrost_device *pfdev, static irqreturn_t panfrost_mmu_irq_handler(int irq, void *data) { struct panfrost_device *pfdev = data; - u32 status = mmu_read(pfdev, MMU_INT_STAT); - int i; - if (!status) + if (!mmu_read(pfdev, MMU_INT_STAT)) return IRQ_NONE; + mmu_write(pfdev, MMU_INT_MASK, 0); + return IRQ_WAKE_THREAD; +} + +static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data) +{ + struct panfrost_device *pfdev = data; + u32 status = mmu_read(pfdev, MMU_INT_RAWSTAT); + int i; + dev_err(pfdev->dev, "mmu irq status=%x\n", status); for (i = 0; status; i++) { @@ -355,6 +363,7 @@ static irqreturn_t panfrost_mmu_irq_handler(int irq, void *data) status &= ~mask; } + mmu_write(pfdev, MMU_INT_MASK, ~0); return IRQ_HANDLED; }; @@ -373,8 +382,9 @@ int panfrost_mmu_init(struct panfrost_device *pfdev) if (irq <= 0) return -ENODEV; - err = devm_request_irq(pfdev->dev, irq, panfrost_mmu_irq_handler, - IRQF_SHARED, "mmu", pfdev); + err = devm_request_threaded_irq(pfdev->dev, irq, panfrost_mmu_irq_handler, + panfrost_mmu_irq_handler_thread, + IRQF_SHARED, "mmu", pfdev); if (err) { dev_err(pfdev->dev, "failed to request mmu irq"); -- cgit v1.2.3 From 187d2929206e6b098312c174ea873e4cedf5420d Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 26 Jul 2019 16:09:43 -0600 Subject: drm/panfrost: Add support for GPU heap allocations The midgard/bifrost GPUs need to allocate GPU heap memory which is allocated on GPU page faults and not pinned in memory. The vendor driver calls this functionality GROW_ON_GPF. This implementation assumes that BOs allocated with the PANFROST_BO_NOEXEC flag are never mmapped or exported. Both of those may actually work, but I'm unsure if there's some interaction there. It would cause the whole object to be pinned in memory which would defeat the point of this. On faults, we map in 2MB at a time in order to utilize huge pages (if enabled). Currently, once we've mapped pages in, they are only unmapped if the BO is freed. Once we add shrinker support, we can unmap pages with the shrinker. Cc: Tomeu Vizoso Cc: Boris Brezillon Cc: Robin Murphy Acked-by: Alyssa Rosenzweig Reviewed-by: Steven Price Signed-off-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20190808222200.13176-9-robh@kernel.org --- drivers/gpu/drm/panfrost/TODO | 2 - drivers/gpu/drm/panfrost/panfrost_drv.c | 11 ++- drivers/gpu/drm/panfrost/panfrost_gem.c | 38 ++++++++-- drivers/gpu/drm/panfrost/panfrost_gem.h | 8 ++ drivers/gpu/drm/panfrost/panfrost_mmu.c | 129 +++++++++++++++++++++++++++++--- include/uapi/drm/panfrost_drm.h | 1 + 6 files changed, 172 insertions(+), 17 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panfrost/TODO b/drivers/gpu/drm/panfrost/TODO index d4c7fb7e7d13..e7727b292355 100644 --- a/drivers/gpu/drm/panfrost/TODO +++ b/drivers/gpu/drm/panfrost/TODO @@ -10,8 +10,6 @@ The hard part is handling when more address spaces are needed than what the h/w provides. -- Support pinning pages on demand (GPU page faults). - - Support userspace controlled GPU virtual addresses. Needed for Vulkan. (Tomeu) - Compute job support. So called 'compute only' jobs need to be plumbed up to diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index f070f2dd9f84..994dbc37e4d0 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -82,7 +82,12 @@ static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, struct drm_panfrost_create_bo *args = data; if (!args->size || args->pad || - (args->flags & ~PANFROST_BO_NOEXEC)) + (args->flags & ~(PANFROST_BO_NOEXEC | PANFROST_BO_HEAP))) + return -EINVAL; + + /* Heaps should never be executable */ + if ((args->flags & PANFROST_BO_HEAP) && + !(args->flags & PANFROST_BO_NOEXEC)) return -EINVAL; bo = panfrost_gem_create_with_handle(file, dev, args->size, args->flags, @@ -297,6 +302,10 @@ static int panfrost_ioctl_mmap_bo(struct drm_device *dev, void *data, return -ENOENT; } + /* Don't allow mmapping of heap objects as pages are not pinned. */ + if (to_panfrost_bo(gem_obj)->is_heap) + return -EINVAL; + ret = drm_gem_create_mmap_offset(gem_obj); if (ret == 0) args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node); diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index 1a3bde3dc662..e71f27c4041e 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -19,6 +19,20 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj) struct panfrost_gem_object *bo = to_panfrost_bo(obj); struct panfrost_device *pfdev = obj->dev->dev_private; + if (bo->sgts) { + int i; + int n_sgt = bo->base.base.size / SZ_2M; + + for (i = 0; i < n_sgt; i++) { + if (bo->sgts[i].sgl) { + dma_unmap_sg(pfdev->dev, bo->sgts[i].sgl, + bo->sgts[i].nents, DMA_BIDIRECTIONAL); + sg_free_table(&bo->sgts[i]); + } + } + kfree(bo->sgts); + } + mutex_lock(&pfdev->shrinker_lock); if (!list_empty(&bo->base.madv_list)) list_del(&bo->base.madv_list); @@ -53,10 +67,11 @@ static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_p if (ret) goto out; - ret = panfrost_mmu_map(bo); - if (ret) - drm_mm_remove_node(&bo->node); - + if (!bo->is_heap) { + ret = panfrost_mmu_map(bo); + if (ret) + drm_mm_remove_node(&bo->node); + } out: spin_unlock(&pfdev->mm_lock); return ret; @@ -76,12 +91,20 @@ static void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file spin_unlock(&pfdev->mm_lock); } +static int panfrost_gem_pin(struct drm_gem_object *obj) +{ + if (to_panfrost_bo(obj)->is_heap) + return -EINVAL; + + return drm_gem_shmem_pin(obj); +} + static const struct drm_gem_object_funcs panfrost_gem_funcs = { .free = panfrost_gem_free_object, .open = panfrost_gem_open, .close = panfrost_gem_close, .print_info = drm_gem_shmem_print_info, - .pin = drm_gem_shmem_pin, + .pin = panfrost_gem_pin, .unpin = drm_gem_shmem_unpin, .get_sg_table = drm_gem_shmem_get_sg_table, .vmap = drm_gem_shmem_vmap, @@ -120,12 +143,17 @@ panfrost_gem_create_with_handle(struct drm_file *file_priv, struct drm_gem_shmem_object *shmem; struct panfrost_gem_object *bo; + /* Round up heap allocations to 2MB to keep fault handling simple */ + if (flags & PANFROST_BO_HEAP) + size = roundup(size, SZ_2M); + shmem = drm_gem_shmem_create(dev, size); if (IS_ERR(shmem)) return ERR_CAST(shmem); bo = to_panfrost_bo(&shmem->base); bo->noexec = !!(flags & PANFROST_BO_NOEXEC); + bo->is_heap = !!(flags & PANFROST_BO_HEAP); /* * Allocate an id of idr table where the obj is registered diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.h b/drivers/gpu/drm/panfrost/panfrost_gem.h index d4c7aa1790a7..e10f58316915 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.h +++ b/drivers/gpu/drm/panfrost/panfrost_gem.h @@ -9,10 +9,12 @@ struct panfrost_gem_object { struct drm_gem_shmem_object base; + struct sg_table *sgts; struct drm_mm_node node; bool is_mapped :1; bool noexec :1; + bool is_heap :1; }; static inline @@ -21,6 +23,12 @@ struct panfrost_gem_object *to_panfrost_bo(struct drm_gem_object *obj) return container_of(to_drm_gem_shmem_obj(obj), struct panfrost_gem_object, base); } +static inline +struct panfrost_gem_object *drm_mm_node_to_panfrost_bo(struct drm_mm_node *node) +{ + return container_of(node, struct panfrost_gem_object, node); +} + struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t size); struct drm_gem_object * diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index b609ee55a872..2ed411f09d80 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -2,6 +2,7 @@ /* Copyright 2019 Linaro, Ltd, Rob Herring */ #include #include +#include #include #include #include @@ -9,6 +10,7 @@ #include #include #include +#include #include #include "panfrost_device.h" @@ -240,12 +242,12 @@ void panfrost_mmu_unmap(struct panfrost_gem_object *bo) size_t unmapped_page; size_t pgsize = get_pgsize(iova, len - unmapped_len); - unmapped_page = ops->unmap(ops, iova, pgsize); - if (!unmapped_page) - break; - - iova += unmapped_page; - unmapped_len += unmapped_page; + if (ops->iova_to_phys(ops, iova)) { + unmapped_page = ops->unmap(ops, iova, pgsize); + WARN_ON(unmapped_page != pgsize); + } + iova += pgsize; + unmapped_len += pgsize; } mmu_hw_do_operation(pfdev, 0, bo->node.start << PAGE_SHIFT, @@ -281,6 +283,105 @@ static const struct iommu_gather_ops mmu_tlb_ops = { .tlb_sync = mmu_tlb_sync_context, }; +static struct drm_mm_node *addr_to_drm_mm_node(struct panfrost_device *pfdev, int as, u64 addr) +{ + struct drm_mm_node *node; + u64 offset = addr >> PAGE_SHIFT; + + drm_mm_for_each_node(node, &pfdev->mm) { + if (offset >= node->start && offset < (node->start + node->size)) + return node; + } + return NULL; +} + +#define NUM_FAULT_PAGES (SZ_2M / PAGE_SIZE) + +int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as, u64 addr) +{ + int ret, i; + struct drm_mm_node *node; + struct panfrost_gem_object *bo; + struct address_space *mapping; + pgoff_t page_offset; + struct sg_table *sgt; + struct page **pages; + + node = addr_to_drm_mm_node(pfdev, as, addr); + if (!node) + return -ENOENT; + + bo = drm_mm_node_to_panfrost_bo(node); + if (!bo->is_heap) { + dev_WARN(pfdev->dev, "matching BO is not heap type (GPU VA = %llx)", + node->start << PAGE_SHIFT); + return -EINVAL; + } + /* Assume 2MB alignment and size multiple */ + addr &= ~((u64)SZ_2M - 1); + page_offset = addr >> PAGE_SHIFT; + page_offset -= node->start; + + mutex_lock(&bo->base.pages_lock); + + if (!bo->base.pages) { + bo->sgts = kvmalloc_array(bo->base.base.size / SZ_2M, + sizeof(struct sg_table), GFP_KERNEL | __GFP_ZERO); + if (!bo->sgts) + return -ENOMEM; + + pages = kvmalloc_array(bo->base.base.size >> PAGE_SHIFT, + sizeof(struct page *), GFP_KERNEL | __GFP_ZERO); + if (!pages) { + kfree(bo->sgts); + bo->sgts = NULL; + return -ENOMEM; + } + bo->base.pages = pages; + bo->base.pages_use_count = 1; + } else + pages = bo->base.pages; + + mapping = bo->base.base.filp->f_mapping; + mapping_set_unevictable(mapping); + + for (i = page_offset; i < page_offset + NUM_FAULT_PAGES; i++) { + pages[i] = shmem_read_mapping_page(mapping, i); + if (IS_ERR(pages[i])) { + mutex_unlock(&bo->base.pages_lock); + ret = PTR_ERR(pages[i]); + goto err_pages; + } + } + + mutex_unlock(&bo->base.pages_lock); + + sgt = &bo->sgts[page_offset / (SZ_2M / PAGE_SIZE)]; + ret = sg_alloc_table_from_pages(sgt, pages + page_offset, + NUM_FAULT_PAGES, 0, SZ_2M, GFP_KERNEL); + if (ret) + goto err_pages; + + if (!dma_map_sg(pfdev->dev, sgt->sgl, sgt->nents, DMA_BIDIRECTIONAL)) { + ret = -EINVAL; + goto err_map; + } + + mmu_map_sg(pfdev, addr, IOMMU_WRITE | IOMMU_READ | IOMMU_NOEXEC, sgt); + + bo->is_mapped = true; + + dev_dbg(pfdev->dev, "mapped page fault @ %llx", addr); + + return 0; + +err_map: + sg_free_table(sgt); +err_pages: + drm_gem_shmem_put_pages(&bo->base); + return ret; +} + static const char *access_type_name(struct panfrost_device *pfdev, u32 fault_status) { @@ -317,9 +418,7 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data) { struct panfrost_device *pfdev = data; u32 status = mmu_read(pfdev, MMU_INT_RAWSTAT); - int i; - - dev_err(pfdev->dev, "mmu irq status=%x\n", status); + int i, ret; for (i = 0; status; i++) { u32 mask = BIT(i) | BIT(i + 16); @@ -341,6 +440,18 @@ static irqreturn_t panfrost_mmu_irq_handler_thread(int irq, void *data) access_type = (fault_status >> 8) & 0x3; source_id = (fault_status >> 16); + /* Page fault only */ + if ((status & mask) == BIT(i)) { + WARN_ON(exception_type < 0xC1 || exception_type > 0xC4); + + ret = panfrost_mmu_map_fault_addr(pfdev, i, addr); + if (!ret) { + mmu_write(pfdev, MMU_INT_CLEAR, BIT(i)); + status &= ~mask; + continue; + } + } + /* terminal fault, print info about the fault */ dev_err(pfdev->dev, "Unhandled Page fault in AS%d at VA 0x%016llX\n" diff --git a/include/uapi/drm/panfrost_drm.h b/include/uapi/drm/panfrost_drm.h index b80c20d17dec..ec19db1eead8 100644 --- a/include/uapi/drm/panfrost_drm.h +++ b/include/uapi/drm/panfrost_drm.h @@ -85,6 +85,7 @@ struct drm_panfrost_wait_bo { }; #define PANFROST_BO_NOEXEC 1 +#define PANFROST_BO_HEAP 2 /** * struct drm_panfrost_create_bo - ioctl argument for creating Panfrost BOs. -- cgit v1.2.3 From 1c2b93902faf8654d13eac8c86876365d6f0da6f Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 2 Jul 2019 12:49:36 -0600 Subject: drm/panfrost: Bump driver version to 1.1 Increment the driver version to expose the new BO allocation flags. Cc: Tomeu Vizoso Cc: Boris Brezillon Cc: Robin Murphy Cc: Steven Price Acked-by: Alyssa Rosenzweig Signed-off-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20190808222200.13176-10-robh@kernel.org --- drivers/gpu/drm/panfrost/panfrost_drv.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index 994dbc37e4d0..a1352750984c 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -448,6 +448,11 @@ static const struct drm_ioctl_desc panfrost_drm_driver_ioctls[] = { DEFINE_DRM_GEM_SHMEM_FOPS(panfrost_drm_driver_fops); +/* + * Panfrost driver version: + * - 1.0 - initial interface + * - 1.1 - adds HEAP and NOEXEC flags for CREATE_BO + */ static struct drm_driver panfrost_drm_driver = { .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ, .open = panfrost_open, @@ -459,7 +464,7 @@ static struct drm_driver panfrost_drm_driver = { .desc = "panfrost DRM", .date = "20180908", .major = 1, - .minor = 0, + .minor = 1, .gem_create_object = panfrost_gem_create_object, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, -- cgit v1.2.3 From 52791eeec1d9f4a7e7fe08aaba0b1553149d93bc Mon Sep 17 00:00:00 2001 From: Christian König Date: Sun, 11 Aug 2019 10:06:32 +0200 Subject: dma-buf: rename reservation_object to dma_resv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Be more consistent with the naming of the other DMA-buf objects. Signed-off-by: Christian König Reviewed-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/323401/ --- drivers/dma-buf/Makefile | 2 +- drivers/dma-buf/dma-buf.c | 32 +- drivers/dma-buf/dma-fence.c | 2 +- drivers/dma-buf/dma-resv.c | 603 +++++++++++++++++++++ drivers/dma-buf/reservation.c | 610 ---------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c | 20 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 18 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 10 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 14 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 20 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/drm_atomic_uapi.c | 2 +- drivers/gpu/drm/drm_gem.c | 26 +- drivers/gpu/drm/drm_gem_framebuffer_helper.c | 4 +- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 8 +- drivers/gpu/drm/etnaviv/etnaviv_gem.h | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 14 +- drivers/gpu/drm/i915/display/intel_display.c | 4 +- drivers/gpu/drm/i915/gem/i915_gem_busy.c | 6 +- drivers/gpu/drm/i915/gem/i915_gem_clflush.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_client_blt.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 6 +- drivers/gpu/drm/i915/gem/i915_gem_fence.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_object.h | 10 +- drivers/gpu/drm/i915/gem/i915_gem_wait.c | 18 +- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/i915_gem_batch_pool.c | 12 +- drivers/gpu/drm/i915/i915_request.c | 4 +- drivers/gpu/drm/i915/i915_sw_fence.c | 8 +- drivers/gpu/drm/i915/i915_sw_fence.h | 4 +- drivers/gpu/drm/i915/i915_vma.c | 16 +- drivers/gpu/drm/i915/i915_vma.h | 8 +- drivers/gpu/drm/lima/lima_gem.c | 8 +- drivers/gpu/drm/mediatek/mtk_drm_fb.c | 2 +- drivers/gpu/drm/msm/msm_gem.c | 18 +- drivers/gpu/drm/msm/msm_gem.h | 2 +- drivers/gpu/drm/msm/msm_gem_submit.c | 2 +- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/wndw.c | 2 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 10 +- drivers/gpu/drm/nouveau/nouveau_bo.h | 2 +- drivers/gpu/drm/nouveau/nouveau_fence.c | 12 +- drivers/gpu/drm/nouveau/nouveau_gem.c | 2 +- drivers/gpu/drm/nouveau/nouveau_prime.c | 6 +- drivers/gpu/drm/panfrost/panfrost_drv.c | 2 +- drivers/gpu/drm/panfrost/panfrost_job.c | 6 +- drivers/gpu/drm/qxl/qxl_debugfs.c | 2 +- drivers/gpu/drm/qxl/qxl_release.c | 6 +- drivers/gpu/drm/radeon/cik.c | 2 +- drivers/gpu/drm/radeon/cik_sdma.c | 2 +- drivers/gpu/drm/radeon/evergreen_dma.c | 2 +- drivers/gpu/drm/radeon/r100.c | 2 +- drivers/gpu/drm/radeon/r200.c | 2 +- drivers/gpu/drm/radeon/r600.c | 2 +- drivers/gpu/drm/radeon/r600_dma.c | 2 +- drivers/gpu/drm/radeon/radeon.h | 8 +- drivers/gpu/drm/radeon/radeon_asic.h | 18 +- drivers/gpu/drm/radeon/radeon_benchmark.c | 2 +- drivers/gpu/drm/radeon/radeon_cs.c | 2 +- drivers/gpu/drm/radeon/radeon_display.c | 2 +- drivers/gpu/drm/radeon/radeon_gem.c | 6 +- drivers/gpu/drm/radeon/radeon_mn.c | 2 +- drivers/gpu/drm/radeon/radeon_object.c | 14 +- drivers/gpu/drm/radeon/radeon_object.h | 2 +- drivers/gpu/drm/radeon/radeon_prime.c | 6 +- drivers/gpu/drm/radeon/radeon_sync.c | 10 +- drivers/gpu/drm/radeon/radeon_uvd.c | 2 +- drivers/gpu/drm/radeon/radeon_vm.c | 2 +- drivers/gpu/drm/radeon/rv770_dma.c | 2 +- drivers/gpu/drm/radeon/si_dma.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 118 ++--- drivers/gpu/drm/ttm/ttm_bo_util.c | 16 +- drivers/gpu/drm/ttm/ttm_bo_vm.c | 6 +- drivers/gpu/drm/ttm/ttm_execbuf_util.c | 20 +- drivers/gpu/drm/ttm/ttm_tt.c | 2 +- drivers/gpu/drm/v3d/v3d_gem.c | 4 +- drivers/gpu/drm/vc4/vc4_gem.c | 6 +- drivers/gpu/drm/vgem/vgem_fence.c | 16 +- drivers/gpu/drm/virtio/virtgpu_ioctl.c | 4 +- drivers/gpu/drm/virtio/virtgpu_plane.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_blit.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 8 +- drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 6 +- include/drm/drmP.h | 2 +- include/drm/drm_gem.h | 8 +- include/drm/ttm/ttm_bo_api.h | 12 +- include/drm/ttm/ttm_bo_driver.h | 14 +- include/linux/dma-buf.h | 4 +- include/linux/dma-fence.h | 4 +- include/linux/dma-resv.h | 312 +++++++++++ include/linux/reservation.h | 332 ------------ 106 files changed, 1302 insertions(+), 1329 deletions(-) create mode 100644 drivers/dma-buf/dma-resv.c delete mode 100644 drivers/dma-buf/reservation.c create mode 100644 include/linux/dma-resv.h delete mode 100644 include/linux/reservation.h (limited to 'drivers/gpu') diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile index e8c7310cb800..dcfb01e7c6f4 100644 --- a/drivers/dma-buf/Makefile +++ b/drivers/dma-buf/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only obj-y := dma-buf.o dma-fence.o dma-fence-array.o dma-fence-chain.o \ - reservation.o seqno-fence.o + dma-resv.o seqno-fence.o obj-$(CONFIG_SYNC_FILE) += sync_file.o obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o obj-$(CONFIG_UDMABUF) += udmabuf.o diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 67510f2be8bc..b3400d6524ab 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include @@ -104,8 +104,8 @@ static int dma_buf_release(struct inode *inode, struct file *file) list_del(&dmabuf->list_node); mutex_unlock(&db_list.lock); - if (dmabuf->resv == (struct reservation_object *)&dmabuf[1]) - reservation_object_fini(dmabuf->resv); + if (dmabuf->resv == (struct dma_resv *)&dmabuf[1]) + dma_resv_fini(dmabuf->resv); module_put(dmabuf->owner); kfree(dmabuf); @@ -165,7 +165,7 @@ static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence) * To support cross-device and cross-driver synchronization of buffer access * implicit fences (represented internally in the kernel with &struct fence) can * be attached to a &dma_buf. The glue for that and a few related things are - * provided in the &reservation_object structure. + * provided in the &dma_resv structure. * * Userspace can query the state of these implicitly tracked fences using poll() * and related system calls: @@ -195,8 +195,8 @@ static void dma_buf_poll_cb(struct dma_fence *fence, struct dma_fence_cb *cb) static __poll_t dma_buf_poll(struct file *file, poll_table *poll) { struct dma_buf *dmabuf; - struct reservation_object *resv; - struct reservation_object_list *fobj; + struct dma_resv *resv; + struct dma_resv_list *fobj; struct dma_fence *fence_excl; __poll_t events; unsigned shared_count; @@ -214,7 +214,7 @@ static __poll_t dma_buf_poll(struct file *file, poll_table *poll) return 0; rcu_read_lock(); - reservation_object_fences(resv, &fence_excl, &fobj, &shared_count); + dma_resv_fences(resv, &fence_excl, &fobj, &shared_count); if (fence_excl && (!(events & EPOLLOUT) || shared_count == 0)) { struct dma_buf_poll_cb_t *dcb = &dmabuf->cb_excl; __poll_t pevents = EPOLLIN; @@ -493,13 +493,13 @@ err_alloc_file: struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) { struct dma_buf *dmabuf; - struct reservation_object *resv = exp_info->resv; + struct dma_resv *resv = exp_info->resv; struct file *file; size_t alloc_size = sizeof(struct dma_buf); int ret; if (!exp_info->resv) - alloc_size += sizeof(struct reservation_object); + alloc_size += sizeof(struct dma_resv); else /* prevent &dma_buf[1] == dma_buf->resv */ alloc_size += 1; @@ -531,8 +531,8 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info) dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0; if (!resv) { - resv = (struct reservation_object *)&dmabuf[1]; - reservation_object_init(resv); + resv = (struct dma_resv *)&dmabuf[1]; + dma_resv_init(resv); } dmabuf->resv = resv; @@ -896,11 +896,11 @@ static int __dma_buf_begin_cpu_access(struct dma_buf *dmabuf, { bool write = (direction == DMA_BIDIRECTIONAL || direction == DMA_TO_DEVICE); - struct reservation_object *resv = dmabuf->resv; + struct dma_resv *resv = dmabuf->resv; long ret; /* Wait on any implicit rendering fences */ - ret = reservation_object_wait_timeout_rcu(resv, write, true, + ret = dma_resv_wait_timeout_rcu(resv, write, true, MAX_SCHEDULE_TIMEOUT); if (ret < 0) return ret; @@ -1141,8 +1141,8 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused) int ret; struct dma_buf *buf_obj; struct dma_buf_attachment *attach_obj; - struct reservation_object *robj; - struct reservation_object_list *fobj; + struct dma_resv *robj; + struct dma_resv_list *fobj; struct dma_fence *fence; int count = 0, attach_count, shared_count, i; size_t size = 0; @@ -1175,7 +1175,7 @@ static int dma_buf_debug_show(struct seq_file *s, void *unused) robj = buf_obj->resv; rcu_read_lock(); - reservation_object_fences(robj, &fence, &fobj, &shared_count); + dma_resv_fences(robj, &fence, &fobj, &shared_count); rcu_read_unlock(); if (fence) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index 59ac96ec7ba8..8025a891d3e9 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -60,7 +60,7 @@ static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(1); * * - Then there's also implicit fencing, where the synchronization points are * implicitly passed around as part of shared &dma_buf instances. Such - * implicit fences are stored in &struct reservation_object through the + * implicit fences are stored in &struct dma_resv through the * &dma_buf.resv pointer. */ diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c new file mode 100644 index 000000000000..f5142683c851 --- /dev/null +++ b/drivers/dma-buf/dma-resv.c @@ -0,0 +1,603 @@ +/* + * Copyright (C) 2012-2014 Canonical Ltd (Maarten Lankhorst) + * + * Based on bo.c which bears the following copyright notice, + * but is dual licensed: + * + * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., 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 Hellstrom + */ + +#include +#include + +/** + * DOC: Reservation Object Overview + * + * The reservation object provides a mechanism to manage shared and + * exclusive fences associated with a buffer. A reservation object + * can have attached one exclusive fence (normally associated with + * write operations) or N shared fences (read operations). The RCU + * mechanism is used to protect read access to fences from locked + * write-side updates. + */ + +DEFINE_WD_CLASS(reservation_ww_class); +EXPORT_SYMBOL(reservation_ww_class); + +/** + * dma_resv_list_alloc - allocate fence list + * @shared_max: number of fences we need space for + * + * Allocate a new dma_resv_list and make sure to correctly initialize + * shared_max. + */ +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); + if (!list) + return NULL; + + list->shared_max = (ksize(list) - offsetof(typeof(*list), shared)) / + sizeof(*list->shared); + + return list; +} + +/** + * dma_resv_list_free - free fence list + * @list: list to free + * + * Free a dma_resv_list and make sure to drop all references. + */ +static void dma_resv_list_free(struct dma_resv_list *list) +{ + unsigned int i; + + if (!list) + return; + + for (i = 0; i < list->shared_count; ++i) + dma_fence_put(rcu_dereference_protected(list->shared[i], true)); + + kfree_rcu(list, rcu); +} + +/** + * dma_resv_init - initialize a reservation object + * @obj: the reservation object + */ +void dma_resv_init(struct dma_resv *obj) +{ + ww_mutex_init(&obj->lock, &reservation_ww_class); + RCU_INIT_POINTER(obj->fence, NULL); + RCU_INIT_POINTER(obj->fence_excl, NULL); +} +EXPORT_SYMBOL(dma_resv_init); + +/** + * dma_resv_fini - destroys a reservation object + * @obj: the reservation object + */ +void dma_resv_fini(struct dma_resv *obj) +{ + struct dma_resv_list *fobj; + struct dma_fence *excl; + + /* + * This object should be dead and all references must have + * been released to it, so no need to be protected with rcu. + */ + excl = rcu_dereference_protected(obj->fence_excl, 1); + if (excl) + dma_fence_put(excl); + + fobj = rcu_dereference_protected(obj->fence, 1); + dma_resv_list_free(fobj); + ww_mutex_destroy(&obj->lock); +} +EXPORT_SYMBOL(dma_resv_fini); + +/** + * dma_resv_reserve_shared - Reserve space to add shared fences to + * a dma_resv. + * @obj: reservation object + * @num_fences: number of fences we want to add + * + * Should be called before dma_resv_add_shared_fence(). Must + * be called with obj->lock held. + * + * RETURNS + * Zero for success, or -errno + */ +int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences) +{ + struct dma_resv_list *old, *new; + unsigned int i, j, k, max; + + dma_resv_assert_held(obj); + + old = dma_resv_get_list(obj); + + if (old && old->shared_max) { + if ((old->shared_count + num_fences) <= old->shared_max) + return 0; + else + max = max(old->shared_count + num_fences, + old->shared_max * 2); + } else { + max = 4; + } + + new = dma_resv_list_alloc(max); + if (!new) + return -ENOMEM; + + /* + * no need to bump fence refcounts, rcu_read access + * requires the use of kref_get_unless_zero, and the + * references from the old struct are carried over to + * the new. + */ + for (i = 0, j = 0, k = max; i < (old ? old->shared_count : 0); ++i) { + struct dma_fence *fence; + + fence = rcu_dereference_protected(old->shared[i], + dma_resv_held(obj)); + if (dma_fence_is_signaled(fence)) + RCU_INIT_POINTER(new->shared[--k], fence); + else + RCU_INIT_POINTER(new->shared[j++], fence); + } + new->shared_count = j; + + /* + * We are not changing the effective set of fences here so can + * merely update the pointer to the new array; both existing + * readers and new readers will see exactly the same set of + * active (unsignaled) shared fences. Individual fences and the + * old array are protected by RCU and so will not vanish under + * the gaze of the rcu_read_lock() readers. + */ + rcu_assign_pointer(obj->fence, new); + + if (!old) + return 0; + + /* Drop the references to the signaled fences */ + for (i = k; i < max; ++i) { + struct dma_fence *fence; + + fence = rcu_dereference_protected(new->shared[i], + dma_resv_held(obj)); + dma_fence_put(fence); + } + kfree_rcu(old, rcu); + + return 0; +} +EXPORT_SYMBOL(dma_resv_reserve_shared); + +/** + * dma_resv_add_shared_fence - Add a fence to a shared slot + * @obj: the reservation object + * @fence: the shared fence to add + * + * Add a fence to a shared slot, obj->lock must be held, and + * dma_resv_reserve_shared() has been called. + */ +void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence) +{ + struct dma_resv_list *fobj; + struct dma_fence *old; + unsigned int i, count; + + dma_fence_get(fence); + + dma_resv_assert_held(obj); + + fobj = dma_resv_get_list(obj); + count = fobj->shared_count; + + for (i = 0; i < count; ++i) { + + old = rcu_dereference_protected(fobj->shared[i], + dma_resv_held(obj)); + if (old->context == fence->context || + dma_fence_is_signaled(old)) + goto replace; + } + + BUG_ON(fobj->shared_count >= fobj->shared_max); + old = NULL; + count++; + +replace: + RCU_INIT_POINTER(fobj->shared[i], fence); + /* pointer update must be visible before we extend the shared_count */ + smp_store_mb(fobj->shared_count, count); + dma_fence_put(old); +} +EXPORT_SYMBOL(dma_resv_add_shared_fence); + +/** + * dma_resv_add_excl_fence - Add an exclusive fence. + * @obj: the reservation object + * @fence: the shared fence to add + * + * Add a fence to the exclusive slot. The obj->lock must be held. + */ +void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence) +{ + struct dma_fence *old_fence = dma_resv_get_excl(obj); + struct dma_resv_list *old; + u32 i = 0; + + dma_resv_assert_held(obj); + + old = dma_resv_get_list(obj); + if (old) + i = old->shared_count; + + if (fence) + dma_fence_get(fence); + + preempt_disable(); + rcu_assign_pointer(obj->fence_excl, fence); + /* pointer update must be visible before we modify the shared_count */ + if (old) + smp_store_mb(old->shared_count, 0); + preempt_enable(); + + /* inplace update, no shared fences */ + while (i--) + dma_fence_put(rcu_dereference_protected(old->shared[i], + dma_resv_held(obj))); + + dma_fence_put(old_fence); +} +EXPORT_SYMBOL(dma_resv_add_excl_fence); + +/** +* dma_resv_copy_fences - Copy all fences from src to dst. +* @dst: the destination reservation object +* @src: the source reservation object +* +* Copy all fences from src to dst. dst-lock must be held. +*/ +int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src) +{ + struct dma_resv_list *src_list, *dst_list; + struct dma_fence *old, *new; + unsigned int i, shared_count; + + dma_resv_assert_held(dst); + + rcu_read_lock(); + +retry: + dma_resv_fences(src, &new, &src_list, &shared_count); + if (shared_count) { + rcu_read_unlock(); + + dst_list = dma_resv_list_alloc(shared_count); + if (!dst_list) + return -ENOMEM; + + rcu_read_lock(); + dma_resv_fences(src, &new, &src_list, &shared_count); + if (!src_list || shared_count > dst_list->shared_max) { + kfree(dst_list); + goto retry; + } + + dst_list->shared_count = 0; + for (i = 0; i < shared_count; ++i) { + struct dma_fence *fence; + + fence = rcu_dereference(src_list->shared[i]); + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, + &fence->flags)) + continue; + + if (!dma_fence_get_rcu(fence)) { + dma_resv_list_free(dst_list); + goto retry; + } + + if (dma_fence_is_signaled(fence)) { + dma_fence_put(fence); + continue; + } + + rcu_assign_pointer(dst_list->shared[dst_list->shared_count++], fence); + } + } else { + dst_list = NULL; + } + + if (new && !dma_fence_get_rcu(new)) { + dma_resv_list_free(dst_list); + goto retry; + } + rcu_read_unlock(); + + src_list = dma_resv_get_list(dst); + old = dma_resv_get_excl(dst); + + preempt_disable(); + rcu_assign_pointer(dst->fence_excl, new); + rcu_assign_pointer(dst->fence, dst_list); + preempt_enable(); + + dma_resv_list_free(src_list); + dma_fence_put(old); + + return 0; +} +EXPORT_SYMBOL(dma_resv_copy_fences); + +/** + * dma_resv_get_fences_rcu - Get an object's shared and exclusive + * fences without update side lock held + * @obj: the reservation object + * @pfence_excl: the returned exclusive fence (or NULL) + * @pshared_count: the number of shared fences returned + * @pshared: the array of shared fence ptrs returned (array is krealloc'd to + * the required size, and must be freed by caller) + * + * Retrieve all fences from the reservation object. If the pointer for the + * exclusive fence is not specified the fence is put into the array of the + * shared fences as well. Returns either zero or -ENOMEM. + */ +int dma_resv_get_fences_rcu(struct dma_resv *obj, + struct dma_fence **pfence_excl, + unsigned *pshared_count, + struct dma_fence ***pshared) +{ + struct dma_fence **shared = NULL; + struct dma_fence *fence_excl; + unsigned int shared_count; + int ret = 1; + + do { + struct dma_resv_list *fobj; + unsigned int i; + size_t sz = 0; + + i = 0; + + rcu_read_lock(); + dma_resv_fences(obj, &fence_excl, &fobj, + &shared_count); + + if (fence_excl && !dma_fence_get_rcu(fence_excl)) + goto unlock; + + if (fobj) + sz += sizeof(*shared) * fobj->shared_max; + + if (!pfence_excl && fence_excl) + sz += sizeof(*shared); + + if (sz) { + struct dma_fence **nshared; + + nshared = krealloc(shared, sz, + GFP_NOWAIT | __GFP_NOWARN); + if (!nshared) { + rcu_read_unlock(); + + dma_fence_put(fence_excl); + fence_excl = NULL; + + nshared = krealloc(shared, sz, GFP_KERNEL); + if (nshared) { + shared = nshared; + continue; + } + + ret = -ENOMEM; + break; + } + shared = nshared; + for (i = 0; i < shared_count; ++i) { + shared[i] = rcu_dereference(fobj->shared[i]); + if (!dma_fence_get_rcu(shared[i])) + break; + } + } + + if (i != shared_count) { + while (i--) + dma_fence_put(shared[i]); + dma_fence_put(fence_excl); + goto unlock; + } + + ret = 0; +unlock: + rcu_read_unlock(); + } while (ret); + + if (pfence_excl) + *pfence_excl = fence_excl; + else if (fence_excl) + shared[++shared_count] = fence_excl; + + if (!shared_count) { + kfree(shared); + shared = NULL; + } + + *pshared_count = shared_count; + *pshared = shared; + return ret; +} +EXPORT_SYMBOL_GPL(dma_resv_get_fences_rcu); + +/** + * dma_resv_wait_timeout_rcu - Wait on reservation's objects + * shared and/or exclusive fences. + * @obj: the reservation object + * @wait_all: if true, wait on all fences, else wait on just exclusive fence + * @intr: if true, do interruptible wait + * @timeout: timeout value in jiffies or zero to return immediately + * + * RETURNS + * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or + * greater than zer on success. + */ +long dma_resv_wait_timeout_rcu(struct dma_resv *obj, + bool wait_all, bool intr, + unsigned long timeout) +{ + struct dma_resv_list *fobj; + struct dma_fence *fence; + unsigned shared_count; + long ret = timeout ? timeout : 1; + int i; + +retry: + rcu_read_lock(); + i = -1; + + dma_resv_fences(obj, &fence, &fobj, &shared_count); + if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { + if (!dma_fence_get_rcu(fence)) + goto unlock_retry; + + if (dma_fence_is_signaled(fence)) { + dma_fence_put(fence); + fence = NULL; + } + + } else { + fence = NULL; + } + + if (wait_all) { + for (i = 0; !fence && i < shared_count; ++i) { + struct dma_fence *lfence = rcu_dereference(fobj->shared[i]); + + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, + &lfence->flags)) + continue; + + if (!dma_fence_get_rcu(lfence)) + goto unlock_retry; + + if (dma_fence_is_signaled(lfence)) { + dma_fence_put(lfence); + continue; + } + + fence = lfence; + break; + } + } + + rcu_read_unlock(); + if (fence) { + ret = dma_fence_wait_timeout(fence, intr, ret); + dma_fence_put(fence); + if (ret > 0 && wait_all && (i + 1 < shared_count)) + goto retry; + } + return ret; + +unlock_retry: + rcu_read_unlock(); + goto retry; +} +EXPORT_SYMBOL_GPL(dma_resv_wait_timeout_rcu); + + +static inline int dma_resv_test_signaled_single(struct dma_fence *passed_fence) +{ + struct dma_fence *fence, *lfence = passed_fence; + int ret = 1; + + if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) { + fence = dma_fence_get_rcu(lfence); + if (!fence) + return -1; + + ret = !!dma_fence_is_signaled(fence); + dma_fence_put(fence); + } + return ret; +} + +/** + * dma_resv_test_signaled_rcu - Test if a reservation object's + * fences have been signaled. + * @obj: the reservation object + * @test_all: if true, test all fences, otherwise only test the exclusive + * fence + * + * RETURNS + * true if all fences signaled, else false + */ +bool dma_resv_test_signaled_rcu(struct dma_resv *obj, bool test_all) +{ + struct dma_resv_list *fobj; + struct dma_fence *fence_excl; + unsigned shared_count; + int ret; + + rcu_read_lock(); +retry: + ret = true; + + dma_resv_fences(obj, &fence_excl, &fobj, &shared_count); + if (test_all) { + unsigned i; + + for (i = 0; i < shared_count; ++i) { + struct dma_fence *fence = rcu_dereference(fobj->shared[i]); + + ret = dma_resv_test_signaled_single(fence); + if (ret < 0) + goto retry; + else if (!ret) + break; + } + } + + if (!shared_count && fence_excl) { + ret = dma_resv_test_signaled_single(fence_excl); + if (ret < 0) + goto retry; + } + + rcu_read_unlock(); + return ret; +} +EXPORT_SYMBOL_GPL(dma_resv_test_signaled_rcu); diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c deleted file mode 100644 index f7f4a0858c2a..000000000000 --- a/drivers/dma-buf/reservation.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Copyright (C) 2012-2014 Canonical Ltd (Maarten Lankhorst) - * - * Based on bo.c which bears the following copyright notice, - * but is dual licensed: - * - * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., 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 Hellstrom - */ - -#include -#include - -/** - * DOC: Reservation Object Overview - * - * The reservation object provides a mechanism to manage shared and - * exclusive fences associated with a buffer. A reservation object - * can have attached one exclusive fence (normally associated with - * write operations) or N shared fences (read operations). The RCU - * mechanism is used to protect read access to fences from locked - * write-side updates. - */ - -DEFINE_WD_CLASS(reservation_ww_class); -EXPORT_SYMBOL(reservation_ww_class); - -/** - * reservation_object_list_alloc - allocate fence list - * @shared_max: number of fences we need space for - * - * Allocate a new reservation_object_list and make sure to correctly initialize - * shared_max. - */ -static struct reservation_object_list * -reservation_object_list_alloc(unsigned int shared_max) -{ - struct reservation_object_list *list; - - list = kmalloc(offsetof(typeof(*list), shared[shared_max]), GFP_KERNEL); - if (!list) - return NULL; - - list->shared_max = (ksize(list) - offsetof(typeof(*list), shared)) / - sizeof(*list->shared); - - return list; -} - -/** - * reservation_object_list_free - free fence list - * @list: list to free - * - * Free a reservation_object_list and make sure to drop all references. - */ -static void reservation_object_list_free(struct reservation_object_list *list) -{ - unsigned int i; - - if (!list) - return; - - for (i = 0; i < list->shared_count; ++i) - dma_fence_put(rcu_dereference_protected(list->shared[i], true)); - - kfree_rcu(list, rcu); -} - -/** - * reservation_object_init - initialize a reservation object - * @obj: the reservation object - */ -void reservation_object_init(struct reservation_object *obj) -{ - ww_mutex_init(&obj->lock, &reservation_ww_class); - RCU_INIT_POINTER(obj->fence, NULL); - RCU_INIT_POINTER(obj->fence_excl, NULL); -} -EXPORT_SYMBOL(reservation_object_init); - -/** - * reservation_object_fini - destroys a reservation object - * @obj: the reservation object - */ -void reservation_object_fini(struct reservation_object *obj) -{ - struct reservation_object_list *fobj; - struct dma_fence *excl; - - /* - * This object should be dead and all references must have - * been released to it, so no need to be protected with rcu. - */ - excl = rcu_dereference_protected(obj->fence_excl, 1); - if (excl) - dma_fence_put(excl); - - fobj = rcu_dereference_protected(obj->fence, 1); - reservation_object_list_free(fobj); - ww_mutex_destroy(&obj->lock); -} -EXPORT_SYMBOL(reservation_object_fini); - -/** - * reservation_object_reserve_shared - Reserve space to add shared fences to - * a reservation_object. - * @obj: reservation object - * @num_fences: number of fences we want to add - * - * Should be called before reservation_object_add_shared_fence(). Must - * be called with obj->lock held. - * - * RETURNS - * Zero for success, or -errno - */ -int reservation_object_reserve_shared(struct reservation_object *obj, - unsigned int num_fences) -{ - struct reservation_object_list *old, *new; - unsigned int i, j, k, max; - - reservation_object_assert_held(obj); - - old = reservation_object_get_list(obj); - - if (old && old->shared_max) { - if ((old->shared_count + num_fences) <= old->shared_max) - return 0; - else - max = max(old->shared_count + num_fences, - old->shared_max * 2); - } else { - max = 4; - } - - new = reservation_object_list_alloc(max); - if (!new) - return -ENOMEM; - - /* - * no need to bump fence refcounts, rcu_read access - * requires the use of kref_get_unless_zero, and the - * references from the old struct are carried over to - * the new. - */ - for (i = 0, j = 0, k = max; i < (old ? old->shared_count : 0); ++i) { - struct dma_fence *fence; - - fence = rcu_dereference_protected(old->shared[i], - reservation_object_held(obj)); - if (dma_fence_is_signaled(fence)) - RCU_INIT_POINTER(new->shared[--k], fence); - else - RCU_INIT_POINTER(new->shared[j++], fence); - } - new->shared_count = j; - - /* - * We are not changing the effective set of fences here so can - * merely update the pointer to the new array; both existing - * readers and new readers will see exactly the same set of - * active (unsignaled) shared fences. Individual fences and the - * old array are protected by RCU and so will not vanish under - * the gaze of the rcu_read_lock() readers. - */ - rcu_assign_pointer(obj->fence, new); - - if (!old) - return 0; - - /* Drop the references to the signaled fences */ - for (i = k; i < max; ++i) { - struct dma_fence *fence; - - fence = rcu_dereference_protected(new->shared[i], - reservation_object_held(obj)); - dma_fence_put(fence); - } - kfree_rcu(old, rcu); - - return 0; -} -EXPORT_SYMBOL(reservation_object_reserve_shared); - -/** - * reservation_object_add_shared_fence - Add a fence to a shared slot - * @obj: the reservation object - * @fence: the shared fence to add - * - * Add a fence to a shared slot, obj->lock must be held, and - * reservation_object_reserve_shared() has been called. - */ -void reservation_object_add_shared_fence(struct reservation_object *obj, - struct dma_fence *fence) -{ - struct reservation_object_list *fobj; - struct dma_fence *old; - unsigned int i, count; - - dma_fence_get(fence); - - reservation_object_assert_held(obj); - - fobj = reservation_object_get_list(obj); - count = fobj->shared_count; - - for (i = 0; i < count; ++i) { - - old = rcu_dereference_protected(fobj->shared[i], - reservation_object_held(obj)); - if (old->context == fence->context || - dma_fence_is_signaled(old)) - goto replace; - } - - BUG_ON(fobj->shared_count >= fobj->shared_max); - old = NULL; - count++; - -replace: - RCU_INIT_POINTER(fobj->shared[i], fence); - /* pointer update must be visible before we extend the shared_count */ - smp_store_mb(fobj->shared_count, count); - dma_fence_put(old); -} -EXPORT_SYMBOL(reservation_object_add_shared_fence); - -/** - * reservation_object_add_excl_fence - Add an exclusive fence. - * @obj: the reservation object - * @fence: the shared fence to add - * - * Add a fence to the exclusive slot. The obj->lock must be held. - */ -void reservation_object_add_excl_fence(struct reservation_object *obj, - struct dma_fence *fence) -{ - struct dma_fence *old_fence = reservation_object_get_excl(obj); - struct reservation_object_list *old; - u32 i = 0; - - reservation_object_assert_held(obj); - - old = reservation_object_get_list(obj); - if (old) - i = old->shared_count; - - if (fence) - dma_fence_get(fence); - - preempt_disable(); - rcu_assign_pointer(obj->fence_excl, fence); - /* pointer update must be visible before we modify the shared_count */ - if (old) - smp_store_mb(old->shared_count, 0); - preempt_enable(); - - /* inplace update, no shared fences */ - while (i--) - dma_fence_put(rcu_dereference_protected(old->shared[i], - reservation_object_held(obj))); - - dma_fence_put(old_fence); -} -EXPORT_SYMBOL(reservation_object_add_excl_fence); - -/** -* reservation_object_copy_fences - Copy all fences from src to dst. -* @dst: the destination reservation object -* @src: the source reservation object -* -* Copy all fences from src to dst. dst-lock must be held. -*/ -int reservation_object_copy_fences(struct reservation_object *dst, - struct reservation_object *src) -{ - struct reservation_object_list *src_list, *dst_list; - struct dma_fence *old, *new; - unsigned int i, shared_count; - - reservation_object_assert_held(dst); - - rcu_read_lock(); - -retry: - reservation_object_fences(src, &new, &src_list, &shared_count); - if (shared_count) { - rcu_read_unlock(); - - dst_list = reservation_object_list_alloc(shared_count); - if (!dst_list) - return -ENOMEM; - - rcu_read_lock(); - reservation_object_fences(src, &new, &src_list, &shared_count); - if (!src_list || shared_count > dst_list->shared_max) { - kfree(dst_list); - goto retry; - } - - dst_list->shared_count = 0; - for (i = 0; i < shared_count; ++i) { - struct dma_fence *fence; - - fence = rcu_dereference(src_list->shared[i]); - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, - &fence->flags)) - continue; - - if (!dma_fence_get_rcu(fence)) { - reservation_object_list_free(dst_list); - goto retry; - } - - if (dma_fence_is_signaled(fence)) { - dma_fence_put(fence); - continue; - } - - rcu_assign_pointer(dst_list->shared[dst_list->shared_count++], fence); - } - } else { - dst_list = NULL; - } - - if (new && !dma_fence_get_rcu(new)) { - reservation_object_list_free(dst_list); - goto retry; - } - rcu_read_unlock(); - - src_list = reservation_object_get_list(dst); - old = reservation_object_get_excl(dst); - - preempt_disable(); - rcu_assign_pointer(dst->fence_excl, new); - rcu_assign_pointer(dst->fence, dst_list); - preempt_enable(); - - reservation_object_list_free(src_list); - dma_fence_put(old); - - return 0; -} -EXPORT_SYMBOL(reservation_object_copy_fences); - -/** - * reservation_object_get_fences_rcu - Get an object's shared and exclusive - * fences without update side lock held - * @obj: the reservation object - * @pfence_excl: the returned exclusive fence (or NULL) - * @pshared_count: the number of shared fences returned - * @pshared: the array of shared fence ptrs returned (array is krealloc'd to - * the required size, and must be freed by caller) - * - * Retrieve all fences from the reservation object. If the pointer for the - * exclusive fence is not specified the fence is put into the array of the - * shared fences as well. Returns either zero or -ENOMEM. - */ -int reservation_object_get_fences_rcu(struct reservation_object *obj, - struct dma_fence **pfence_excl, - unsigned *pshared_count, - struct dma_fence ***pshared) -{ - struct dma_fence **shared = NULL; - struct dma_fence *fence_excl; - unsigned int shared_count; - int ret = 1; - - do { - struct reservation_object_list *fobj; - unsigned int i; - size_t sz = 0; - - i = 0; - - rcu_read_lock(); - reservation_object_fences(obj, &fence_excl, &fobj, - &shared_count); - - if (fence_excl && !dma_fence_get_rcu(fence_excl)) - goto unlock; - - if (fobj) - sz += sizeof(*shared) * fobj->shared_max; - - if (!pfence_excl && fence_excl) - sz += sizeof(*shared); - - if (sz) { - struct dma_fence **nshared; - - nshared = krealloc(shared, sz, - GFP_NOWAIT | __GFP_NOWARN); - if (!nshared) { - rcu_read_unlock(); - - dma_fence_put(fence_excl); - fence_excl = NULL; - - nshared = krealloc(shared, sz, GFP_KERNEL); - if (nshared) { - shared = nshared; - continue; - } - - ret = -ENOMEM; - break; - } - shared = nshared; - for (i = 0; i < shared_count; ++i) { - shared[i] = rcu_dereference(fobj->shared[i]); - if (!dma_fence_get_rcu(shared[i])) - break; - } - } - - if (i != shared_count) { - while (i--) - dma_fence_put(shared[i]); - dma_fence_put(fence_excl); - goto unlock; - } - - ret = 0; -unlock: - rcu_read_unlock(); - } while (ret); - - if (pfence_excl) - *pfence_excl = fence_excl; - else if (fence_excl) - shared[++shared_count] = fence_excl; - - if (!shared_count) { - kfree(shared); - shared = NULL; - } - - *pshared_count = shared_count; - *pshared = shared; - return ret; -} -EXPORT_SYMBOL_GPL(reservation_object_get_fences_rcu); - -/** - * reservation_object_wait_timeout_rcu - Wait on reservation's objects - * shared and/or exclusive fences. - * @obj: the reservation object - * @wait_all: if true, wait on all fences, else wait on just exclusive fence - * @intr: if true, do interruptible wait - * @timeout: timeout value in jiffies or zero to return immediately - * - * RETURNS - * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or - * greater than zer on success. - */ -long reservation_object_wait_timeout_rcu(struct reservation_object *obj, - bool wait_all, bool intr, - unsigned long timeout) -{ - struct reservation_object_list *fobj; - struct dma_fence *fence; - unsigned shared_count; - long ret = timeout ? timeout : 1; - int i; - -retry: - rcu_read_lock(); - i = -1; - - reservation_object_fences(obj, &fence, &fobj, &shared_count); - if (fence && !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { - if (!dma_fence_get_rcu(fence)) - goto unlock_retry; - - if (dma_fence_is_signaled(fence)) { - dma_fence_put(fence); - fence = NULL; - } - - } else { - fence = NULL; - } - - if (wait_all) { - for (i = 0; !fence && i < shared_count; ++i) { - struct dma_fence *lfence = rcu_dereference(fobj->shared[i]); - - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, - &lfence->flags)) - continue; - - if (!dma_fence_get_rcu(lfence)) - goto unlock_retry; - - if (dma_fence_is_signaled(lfence)) { - dma_fence_put(lfence); - continue; - } - - fence = lfence; - break; - } - } - - rcu_read_unlock(); - if (fence) { - ret = dma_fence_wait_timeout(fence, intr, ret); - dma_fence_put(fence); - if (ret > 0 && wait_all && (i + 1 < shared_count)) - goto retry; - } - return ret; - -unlock_retry: - rcu_read_unlock(); - goto retry; -} -EXPORT_SYMBOL_GPL(reservation_object_wait_timeout_rcu); - - -static inline int -reservation_object_test_signaled_single(struct dma_fence *passed_fence) -{ - struct dma_fence *fence, *lfence = passed_fence; - int ret = 1; - - if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &lfence->flags)) { - fence = dma_fence_get_rcu(lfence); - if (!fence) - return -1; - - ret = !!dma_fence_is_signaled(fence); - dma_fence_put(fence); - } - return ret; -} - -/** - * reservation_object_test_signaled_rcu - Test if a reservation object's - * fences have been signaled. - * @obj: the reservation object - * @test_all: if true, test all fences, otherwise only test the exclusive - * fence - * - * RETURNS - * true if all fences signaled, else false - */ -bool reservation_object_test_signaled_rcu(struct reservation_object *obj, - bool test_all) -{ - struct reservation_object_list *fobj; - struct dma_fence *fence_excl; - unsigned shared_count; - int ret; - - rcu_read_lock(); -retry: - ret = true; - - reservation_object_fences(obj, &fence_excl, &fobj, &shared_count); - if (test_all) { - unsigned i; - - for (i = 0; i < shared_count; ++i) { - struct dma_fence *fence = rcu_dereference(fobj->shared[i]); - - ret = reservation_object_test_signaled_single(fence); - if (ret < 0) - goto retry; - else if (!ret) - break; - } - } - - if (!shared_count && fence_excl) { - ret = reservation_object_test_signaled_single(fence_excl); - if (ret < 0) - goto retry; - } - - rcu_read_unlock(); - return ret; -} -EXPORT_SYMBOL_GPL(reservation_object_test_signaled_rcu); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index a4640ddc24d1..bc4ec6b20a87 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -218,14 +218,14 @@ void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo) static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, struct amdgpu_amdkfd_fence *ef) { - struct reservation_object *resv = bo->tbo.base.resv; - struct reservation_object_list *old, *new; + struct dma_resv *resv = bo->tbo.base.resv; + struct dma_resv_list *old, *new; unsigned int i, j, k; if (!ef) return -EINVAL; - old = reservation_object_get_list(resv); + old = dma_resv_get_list(resv); if (!old) return 0; @@ -241,7 +241,7 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, struct dma_fence *f; f = rcu_dereference_protected(old->shared[i], - reservation_object_held(resv)); + dma_resv_held(resv)); if (f->context == ef->base.context) RCU_INIT_POINTER(new->shared[--j], f); @@ -258,7 +258,7 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, struct dma_fence *f; f = rcu_dereference_protected(new->shared[i], - reservation_object_held(resv)); + dma_resv_held(resv)); dma_fence_put(f); } kfree_rcu(old, rcu); @@ -882,7 +882,7 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info, AMDGPU_FENCE_OWNER_KFD, false); if (ret) goto wait_pd_fail; - ret = reservation_object_reserve_shared(vm->root.base.bo->tbo.base.resv, 1); + ret = dma_resv_reserve_shared(vm->root.base.bo->tbo.base.resv, 1); if (ret) goto reserve_shared_fail; amdgpu_bo_fence(vm->root.base.bo, @@ -2127,7 +2127,7 @@ int amdgpu_amdkfd_add_gws_to_process(void *info, void *gws, struct kgd_mem **mem * Add process eviction fence to bo so they can * evict each other. */ - ret = reservation_object_reserve_shared(gws_bo->tbo.base.resv, 1); + ret = dma_resv_reserve_shared(gws_bo->tbo.base.resv, 1); if (ret) goto reserve_shared_fail; amdgpu_bo_fence(gws_bo, &process_info->eviction_fence->base, true); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index e748cd284780..22236d367e26 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -730,7 +730,7 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p) list_for_each_entry(e, &p->validated, tv.head) { struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); - struct reservation_object *resv = bo->tbo.base.resv; + struct dma_resv *resv = bo->tbo.base.resv; r = amdgpu_sync_resv(p->adev, &p->job->sync, resv, p->filp, amdgpu_bo_explicit_sync(bo)); @@ -1729,7 +1729,7 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, *map = mapping; /* Double check that the BO is reserved by this CS */ - if (reservation_object_locking_ctx((*bo)->tbo.base.resv) != &parser->ticket) + if (dma_resv_locking_ctx((*bo)->tbo.base.resv) != &parser->ticket) return -EINVAL; if (!((*bo)->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index b5d020e15c35..8a48cb5b5875 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -204,7 +204,7 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc, goto unpin; } - r = reservation_object_get_fences_rcu(new_abo->tbo.base.resv, &work->excl, + r = dma_resv_get_fences_rcu(new_abo->tbo.base.resv, &work->excl, &work->shared_count, &work->shared); if (unlikely(r != 0)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index b88e27da7c28..bf0f00508987 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -137,23 +137,23 @@ int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, } static int -__reservation_object_make_exclusive(struct reservation_object *obj) +__dma_resv_make_exclusive(struct dma_resv *obj) { struct dma_fence **fences; unsigned int count; int r; - if (!reservation_object_get_list(obj)) /* no shared fences to convert */ + if (!dma_resv_get_list(obj)) /* no shared fences to convert */ return 0; - r = reservation_object_get_fences_rcu(obj, NULL, &count, &fences); + r = dma_resv_get_fences_rcu(obj, NULL, &count, &fences); if (r) return r; if (count == 0) { /* Now that was unexpected. */ } else if (count == 1) { - reservation_object_add_excl_fence(obj, fences[0]); + dma_resv_add_excl_fence(obj, fences[0]); dma_fence_put(fences[0]); kfree(fences); } else { @@ -165,7 +165,7 @@ __reservation_object_make_exclusive(struct reservation_object *obj) if (!array) goto err_fences_put; - reservation_object_add_excl_fence(obj, &array->base); + dma_resv_add_excl_fence(obj, &array->base); dma_fence_put(&array->base); } @@ -216,7 +216,7 @@ static int amdgpu_dma_buf_map_attach(struct dma_buf *dma_buf, * fences on the reservation object into a single exclusive * fence. */ - r = __reservation_object_make_exclusive(bo->tbo.base.resv); + r = __dma_resv_make_exclusive(bo->tbo.base.resv); if (r) goto error_unreserve; } @@ -367,7 +367,7 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sg) { - struct reservation_object *resv = attach->dmabuf->resv; + struct dma_resv *resv = attach->dmabuf->resv; struct amdgpu_device *adev = dev->dev_private; struct amdgpu_bo *bo; struct amdgpu_bo_param bp; @@ -380,7 +380,7 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev, bp.flags = 0; bp.type = ttm_bo_type_sg; bp.resv = resv; - reservation_object_lock(resv, NULL); + dma_resv_lock(resv, NULL); ret = amdgpu_bo_create(adev, &bp, &bo); if (ret) goto error; @@ -392,11 +392,11 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev, if (attach->dmabuf->ops != &amdgpu_dmabuf_ops) bo->prime_shared_count = 1; - reservation_object_unlock(resv); + dma_resv_unlock(resv); return &bo->tbo.base; error: - reservation_object_unlock(resv); + dma_resv_unlock(resv); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index bff9173a1a94..40f673cfbbfe 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -50,7 +50,7 @@ void amdgpu_gem_object_free(struct drm_gem_object *gobj) int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, int alignment, u32 initial_domain, u64 flags, enum ttm_bo_type type, - struct reservation_object *resv, + struct dma_resv *resv, struct drm_gem_object **obj) { struct amdgpu_bo *bo; @@ -215,7 +215,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, union drm_amdgpu_gem_create *args = data; uint64_t flags = args->in.domain_flags; uint64_t size = args->in.bo_size; - struct reservation_object *resv = NULL; + struct dma_resv *resv = NULL; struct drm_gem_object *gobj; uint32_t handle; int r; @@ -433,7 +433,7 @@ int amdgpu_gem_wait_idle_ioctl(struct drm_device *dev, void *data, return -ENOENT; } robj = gem_to_amdgpu_bo(gobj); - ret = reservation_object_wait_timeout_rcu(robj->tbo.base.resv, true, true, + ret = dma_resv_wait_timeout_rcu(robj->tbo.base.resv, true, true, timeout); /* ret == 0 means not signaled, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h index 2f17150e26e1..0b66d2e6b5d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h @@ -47,7 +47,7 @@ void amdgpu_gem_force_release(struct amdgpu_device *adev); int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size, int alignment, u32 initial_domain, u64 flags, enum ttm_bo_type type, - struct reservation_object *resv, + struct dma_resv *resv, struct drm_gem_object **obj); int amdgpu_mode_dumb_create(struct drm_file *file_priv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c index 57b3d8a9bef3..b3823f657bdf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c @@ -104,7 +104,7 @@ static void amdgpu_pasid_free_cb(struct dma_fence *fence, * * Free the pasid only after all the fences in resv are signaled. */ -void amdgpu_pasid_free_delayed(struct reservation_object *resv, +void amdgpu_pasid_free_delayed(struct dma_resv *resv, unsigned int pasid) { struct dma_fence *fence, **fences; @@ -112,7 +112,7 @@ void amdgpu_pasid_free_delayed(struct reservation_object *resv, unsigned count; int r; - r = reservation_object_get_fences_rcu(resv, NULL, &count, &fences); + r = dma_resv_get_fences_rcu(resv, NULL, &count, &fences); if (r) goto fallback; @@ -156,7 +156,7 @@ fallback: /* Not enough memory for the delayed delete, as last resort * block for all the fences to complete. */ - reservation_object_wait_timeout_rcu(resv, true, false, + dma_resv_wait_timeout_rcu(resv, true, false, MAX_SCHEDULE_TIMEOUT); amdgpu_pasid_free(pasid); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h index 7625419f0fc2..8e58325bbca2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h @@ -72,7 +72,7 @@ struct amdgpu_vmid_mgr { int amdgpu_pasid_alloc(unsigned int bits); void amdgpu_pasid_free(unsigned int pasid); -void amdgpu_pasid_free_delayed(struct reservation_object *resv, +void amdgpu_pasid_free_delayed(struct dma_resv *resv, unsigned int pasid); bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c index 50022acc8a81..f1f8cdd695d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c @@ -179,7 +179,7 @@ static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node, if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end)) continue; - r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv, + r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false, MAX_SCHEDULE_TIMEOUT); if (r <= 0) DRM_ERROR("(%ld) failed to wait for user bo\n", r); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 8ae44d383a13..2f11ebd95528 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -544,7 +544,7 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, fail_unreserve: if (!bp->resv) - reservation_object_unlock(bo->tbo.base.resv); + dma_resv_unlock(bo->tbo.base.resv); amdgpu_bo_unref(&bo); return r; } @@ -606,13 +606,13 @@ int amdgpu_bo_create(struct amdgpu_device *adev, if ((flags & AMDGPU_GEM_CREATE_SHADOW) && !(adev->flags & AMD_IS_APU)) { if (!bp->resv) - WARN_ON(reservation_object_lock((*bo_ptr)->tbo.base.resv, + WARN_ON(dma_resv_lock((*bo_ptr)->tbo.base.resv, NULL)); r = amdgpu_bo_create_shadow(adev, bp->size, *bo_ptr); if (!bp->resv) - reservation_object_unlock((*bo_ptr)->tbo.base.resv); + dma_resv_unlock((*bo_ptr)->tbo.base.resv); if (r) amdgpu_bo_unref(bo_ptr); @@ -709,7 +709,7 @@ int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr) return 0; } - r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv, false, false, + r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, false, false, MAX_SCHEDULE_TIMEOUT); if (r < 0) return r; @@ -1087,7 +1087,7 @@ int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags) */ void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags) { - reservation_object_assert_held(bo->tbo.base.resv); + dma_resv_assert_held(bo->tbo.base.resv); if (tiling_flags) *tiling_flags = bo->tiling_flags; @@ -1283,12 +1283,12 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, bool shared) { - struct reservation_object *resv = bo->tbo.base.resv; + struct dma_resv *resv = bo->tbo.base.resv; if (shared) - reservation_object_add_shared_fence(resv, fence); + dma_resv_add_shared_fence(resv, fence); else - reservation_object_add_excl_fence(resv, fence); + dma_resv_add_excl_fence(resv, fence); } /** @@ -1328,7 +1328,7 @@ int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr) u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo) { WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM); - WARN_ON_ONCE(!reservation_object_is_locked(bo->tbo.base.resv) && + WARN_ON_ONCE(!dma_resv_is_locked(bo->tbo.base.resv) && !bo->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 && diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 113fb2feb437..1a555b0fd3b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -41,7 +41,7 @@ struct amdgpu_bo_param { u32 preferred_domain; u64 flags; enum ttm_bo_type type; - struct reservation_object *resv; + struct dma_resv *resv; }; /* bo virtual addresses in a vm */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c index 9828f3c7c655..95e5e93edd18 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c @@ -190,10 +190,10 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, */ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync, - struct reservation_object *resv, + struct dma_resv *resv, void *owner, bool explicit_sync) { - struct reservation_object_list *flist; + struct dma_resv_list *flist; struct dma_fence *f; void *fence_owner; unsigned i; @@ -203,16 +203,16 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, return -EINVAL; /* always sync to the exclusive fence */ - f = reservation_object_get_excl(resv); + f = dma_resv_get_excl(resv); r = amdgpu_sync_fence(adev, sync, f, false); - flist = reservation_object_get_list(resv); + flist = dma_resv_get_list(resv); if (!flist || r) return r; for (i = 0; i < flist->shared_count; ++i) { f = rcu_dereference_protected(flist->shared[i], - reservation_object_held(resv)); + dma_resv_held(resv)); /* We only want to trigger KFD eviction fences on * evict or move jobs. Skip KFD fences otherwise. */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h index 10cf23a57f17..b5f1778a2319 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h @@ -27,7 +27,7 @@ #include struct dma_fence; -struct reservation_object; +struct dma_resv; struct amdgpu_device; struct amdgpu_ring; @@ -44,7 +44,7 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, struct dma_fence *f, bool explicit); int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync, - struct reservation_object *resv, + struct dma_resv *resv, void *owner, bool explicit_sync); struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 63e7d1e01b76..fb09314bcfd4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -303,7 +303,7 @@ int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, struct amdgpu_copy_mem *src, struct amdgpu_copy_mem *dst, uint64_t size, - struct reservation_object *resv, + struct dma_resv *resv, struct dma_fence **f) { struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; @@ -1470,7 +1470,7 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, { unsigned long num_pages = bo->mem.num_pages; struct drm_mm_node *node = bo->mem.mm_node; - struct reservation_object_list *flist; + struct dma_resv_list *flist; struct dma_fence *f; int i; @@ -1478,18 +1478,18 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, * cleanly handle page faults. */ if (bo->type == ttm_bo_type_kernel && - !reservation_object_test_signaled_rcu(bo->base.resv, true)) + !dma_resv_test_signaled_rcu(bo->base.resv, true)) return false; /* If bo is a KFD BO, check if the bo belongs to the current process. * If true, then return false as any KFD process needs all its BOs to * be resident to run successfully */ - flist = reservation_object_get_list(bo->base.resv); + flist = dma_resv_get_list(bo->base.resv); if (flist) { for (i = 0; i < flist->shared_count; ++i) { f = rcu_dereference_protected(flist->shared[i], - reservation_object_held(bo->base.resv)); + dma_resv_held(bo->base.resv)); if (amdkfd_fence_check_mm(f, current->mm)) return false; } @@ -1992,7 +1992,7 @@ error_free: int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, - struct reservation_object *resv, + struct dma_resv *resv, struct dma_fence **fence, bool direct_submit, bool vm_needs_flush) { @@ -2066,7 +2066,7 @@ error_free: int amdgpu_fill_buffer(struct amdgpu_bo *bo, uint32_t src_data, - struct reservation_object *resv, + struct dma_resv *resv, struct dma_fence **fence) { struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index caa76c693700..80896bd6b972 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -83,18 +83,18 @@ void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, - struct reservation_object *resv, + struct dma_resv *resv, struct dma_fence **fence, bool direct_submit, bool vm_needs_flush); int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, struct amdgpu_copy_mem *src, struct amdgpu_copy_mem *dst, uint64_t size, - struct reservation_object *resv, + struct dma_resv *resv, struct dma_fence **f); int amdgpu_fill_buffer(struct amdgpu_bo *bo, uint32_t src_data, - struct reservation_object *resv, + struct dma_resv *resv, struct dma_fence **fence); int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index f858607b17a5..b2c364b8695f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -1073,7 +1073,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, ib->length_dw = 16; if (direct) { - r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv, + r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false, msecs_to_jiffies(10)); if (r == 0) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 95eef0ac2829..07dcad7ecb26 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1702,7 +1702,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, ttm = container_of(bo->tbo.ttm, struct ttm_dma_tt, ttm); pages_addr = ttm->dma_address; } - exclusive = reservation_object_get_excl(bo->tbo.base.resv); + exclusive = dma_resv_get_excl(bo->tbo.base.resv); } if (bo) { @@ -1879,18 +1879,18 @@ static void amdgpu_vm_free_mapping(struct amdgpu_device *adev, */ static void amdgpu_vm_prt_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) { - struct reservation_object *resv = vm->root.base.bo->tbo.base.resv; + struct dma_resv *resv = vm->root.base.bo->tbo.base.resv; struct dma_fence *excl, **shared; unsigned i, shared_count; int r; - r = reservation_object_get_fences_rcu(resv, &excl, + r = dma_resv_get_fences_rcu(resv, &excl, &shared_count, &shared); if (r) { /* Not enough memory to grab the fence list, as last resort * block for all the fences to complete. */ - reservation_object_wait_timeout_rcu(resv, true, false, + dma_resv_wait_timeout_rcu(resv, true, false, MAX_SCHEDULE_TIMEOUT); return; } @@ -1978,7 +1978,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, struct amdgpu_vm *vm) { struct amdgpu_bo_va *bo_va, *tmp; - struct reservation_object *resv; + struct dma_resv *resv; bool clear; int r; @@ -1997,7 +1997,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, spin_unlock(&vm->invalidated_lock); /* Try to reserve the BO to avoid clearing its ptes */ - if (!amdgpu_vm_debug && reservation_object_trylock(resv)) + if (!amdgpu_vm_debug && dma_resv_trylock(resv)) clear = false; /* Somebody else is using the BO right now */ else @@ -2008,7 +2008,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, return r; if (!clear) - reservation_object_unlock(resv); + dma_resv_unlock(resv); spin_lock(&vm->invalidated_lock); } spin_unlock(&vm->invalidated_lock); @@ -2416,7 +2416,7 @@ void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket) struct amdgpu_bo *bo; bo = mapping->bo_va->base.bo; - if (reservation_object_locking_ctx(bo->tbo.base.resv) != + if (dma_resv_locking_ctx(bo->tbo.base.resv) != ticket) continue; } @@ -2649,7 +2649,7 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size, */ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout) { - return reservation_object_wait_timeout_rcu(vm->root.base.bo->tbo.base.resv, + return dma_resv_wait_timeout_rcu(vm->root.base.bo->tbo.base.resv, true, true, timeout); } @@ -2724,7 +2724,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, if (r) goto error_free_root; - r = reservation_object_reserve_shared(root->tbo.base.resv, 1); + r = dma_resv_reserve_shared(root->tbo.base.resv, 1); if (r) goto error_unreserve; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 381a5345f195..cb7cfa9b34f2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5693,7 +5693,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, * deadlock during GPU reset when this fence will not signal * but we hold reservation lock for the BO. */ - r = reservation_object_wait_timeout_rcu(abo->tbo.base.resv, true, + r = dma_resv_wait_timeout_rcu(abo->tbo.base.resv, true, false, msecs_to_jiffies(5000)); if (unlikely(r <= 0)) diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 19ae119f1a5d..5a5b42db6f2a 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1037,7 +1037,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, * As a contrast, with implicit fencing the kernel keeps track of any * ongoing rendering, and automatically ensures that the atomic update waits * for any pending rendering to complete. For shared buffers represented with - * a &struct dma_buf this is tracked in &struct reservation_object. + * a &struct dma_buf this is tracked in &struct dma_resv. * Implicit syncing is how Linux traditionally worked (e.g. DRI2/3 on X.org), * whereas explicit fencing is what Android wants. * diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index a2dd198177f2..6854f5867d51 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -159,7 +159,7 @@ void drm_gem_private_object_init(struct drm_device *dev, kref_init(&obj->refcount); obj->handle_count = 0; obj->size = size; - reservation_object_init(&obj->_resv); + dma_resv_init(&obj->_resv); if (!obj->resv) obj->resv = &obj->_resv; @@ -755,7 +755,7 @@ drm_gem_object_lookup(struct drm_file *filp, u32 handle) EXPORT_SYMBOL(drm_gem_object_lookup); /** - * drm_gem_reservation_object_wait - Wait on GEM object's reservation's objects + * drm_gem_dma_resv_wait - Wait on GEM object's reservation's objects * shared and/or exclusive fences. * @filep: DRM file private date * @handle: userspace handle @@ -767,7 +767,7 @@ EXPORT_SYMBOL(drm_gem_object_lookup); * Returns -ERESTARTSYS if interrupted, 0 if the wait timed out, or * greater than 0 on success. */ -long drm_gem_reservation_object_wait(struct drm_file *filep, u32 handle, +long drm_gem_dma_resv_wait(struct drm_file *filep, u32 handle, bool wait_all, unsigned long timeout) { long ret; @@ -779,7 +779,7 @@ long drm_gem_reservation_object_wait(struct drm_file *filep, u32 handle, return -EINVAL; } - ret = reservation_object_wait_timeout_rcu(obj->resv, wait_all, + ret = dma_resv_wait_timeout_rcu(obj->resv, wait_all, true, timeout); if (ret == 0) ret = -ETIME; @@ -790,7 +790,7 @@ long drm_gem_reservation_object_wait(struct drm_file *filep, u32 handle, return ret; } -EXPORT_SYMBOL(drm_gem_reservation_object_wait); +EXPORT_SYMBOL(drm_gem_dma_resv_wait); /** * drm_gem_close_ioctl - implementation of the GEM_CLOSE ioctl @@ -956,7 +956,7 @@ drm_gem_object_release(struct drm_gem_object *obj) if (obj->filp) fput(obj->filp); - reservation_object_fini(&obj->_resv); + dma_resv_fini(&obj->_resv); drm_gem_free_mmap_offset(obj); } EXPORT_SYMBOL(drm_gem_object_release); @@ -1291,7 +1291,7 @@ retry: if (contended != -1) { struct drm_gem_object *obj = objs[contended]; - ret = reservation_object_lock_slow_interruptible(obj->resv, + ret = dma_resv_lock_slow_interruptible(obj->resv, acquire_ctx); if (ret) { ww_acquire_done(acquire_ctx); @@ -1303,16 +1303,16 @@ retry: if (i == contended) continue; - ret = reservation_object_lock_interruptible(objs[i]->resv, + ret = dma_resv_lock_interruptible(objs[i]->resv, acquire_ctx); if (ret) { int j; for (j = 0; j < i; j++) - reservation_object_unlock(objs[j]->resv); + dma_resv_unlock(objs[j]->resv); if (contended != -1 && contended >= i) - reservation_object_unlock(objs[contended]->resv); + dma_resv_unlock(objs[contended]->resv); if (ret == -EDEADLK) { contended = i; @@ -1337,7 +1337,7 @@ drm_gem_unlock_reservations(struct drm_gem_object **objs, int count, int i; for (i = 0; i < count; i++) - reservation_object_unlock(objs[i]->resv); + dma_resv_unlock(objs[i]->resv); ww_acquire_fini(acquire_ctx); } @@ -1413,12 +1413,12 @@ int drm_gem_fence_array_add_implicit(struct xarray *fence_array, if (!write) { struct dma_fence *fence = - reservation_object_get_excl_rcu(obj->resv); + dma_resv_get_excl_rcu(obj->resv); return drm_gem_fence_array_add(fence_array, fence); } - ret = reservation_object_get_fences_rcu(obj->resv, NULL, + ret = dma_resv_get_fences_rcu(obj->resv, NULL, &fence_count, &fences); if (ret || !fence_count) return ret; diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index f61304054786..b9bcd310ca2d 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -7,7 +7,7 @@ #include #include -#include +#include #include #include @@ -294,7 +294,7 @@ int drm_gem_fb_prepare_fb(struct drm_plane *plane, return 0; obj = drm_gem_fb_get_obj(state->fb, 0); - fence = reservation_object_get_excl_rcu(obj->resv); + fence = dma_resv_get_excl_rcu(obj->resv); drm_atomic_set_fence_for_plane(state, fence); return 0; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 17ca602db60a..7d83e04ec36e 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -397,13 +397,13 @@ int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op, } if (op & ETNA_PREP_NOSYNC) { - if (!reservation_object_test_signaled_rcu(obj->resv, + if (!dma_resv_test_signaled_rcu(obj->resv, write)) return -EBUSY; } else { unsigned long remain = etnaviv_timeout_to_jiffies(timeout); - ret = reservation_object_wait_timeout_rcu(obj->resv, + ret = dma_resv_wait_timeout_rcu(obj->resv, write, true, remain); if (ret <= 0) return ret == 0 ? -ETIMEDOUT : ret; @@ -459,8 +459,8 @@ static void etnaviv_gem_describe_fence(struct dma_fence *fence, static void etnaviv_gem_describe(struct drm_gem_object *obj, struct seq_file *m) { struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); - struct reservation_object *robj = obj->resv; - struct reservation_object_list *fobj; + struct dma_resv *robj = obj->resv; + struct dma_resv_list *fobj; struct dma_fence *fence; unsigned long off = drm_vma_node_start(&obj->vma_node); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h index fcd5d71b502f..28379e4df253 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h @@ -6,7 +6,7 @@ #ifndef __ETNAVIV_GEM_H__ #define __ETNAVIV_GEM_H__ -#include +#include #include "etnaviv_cmdbuf.h" #include "etnaviv_drv.h" diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index 1a636469eeda..998c96b40d8a 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include "etnaviv_cmdbuf.h" #include "etnaviv_drv.h" @@ -165,10 +165,10 @@ static int submit_fence_sync(struct etnaviv_gem_submit *submit) for (i = 0; i < submit->nr_bos; i++) { struct etnaviv_gem_submit_bo *bo = &submit->bos[i]; - struct reservation_object *robj = bo->obj->base.resv; + struct dma_resv *robj = bo->obj->base.resv; if (!(bo->flags & ETNA_SUBMIT_BO_WRITE)) { - ret = reservation_object_reserve_shared(robj, 1); + ret = dma_resv_reserve_shared(robj, 1); if (ret) return ret; } @@ -177,13 +177,13 @@ static int submit_fence_sync(struct etnaviv_gem_submit *submit) continue; if (bo->flags & ETNA_SUBMIT_BO_WRITE) { - ret = reservation_object_get_fences_rcu(robj, &bo->excl, + ret = dma_resv_get_fences_rcu(robj, &bo->excl, &bo->nr_shared, &bo->shared); if (ret) return ret; } else { - bo->excl = reservation_object_get_excl_rcu(robj); + bo->excl = dma_resv_get_excl_rcu(robj); } } @@ -199,10 +199,10 @@ static void submit_attach_object_fences(struct etnaviv_gem_submit *submit) struct drm_gem_object *obj = &submit->bos[i].obj->base; if (submit->bos[i].flags & ETNA_SUBMIT_BO_WRITE) - reservation_object_add_excl_fence(obj->resv, + dma_resv_add_excl_fence(obj->resv, submit->out_fence); else - reservation_object_add_shared_fence(obj->resv, + dma_resv_add_shared_fence(obj->resv, submit->out_fence); submit_unlock_object(submit, i); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 8592a7d422de..21c71fdceec0 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include @@ -14317,7 +14317,7 @@ intel_prepare_plane_fb(struct drm_plane *plane, if (ret < 0) return ret; - fence = reservation_object_get_excl_rcu(obj->base.resv); + fence = dma_resv_get_excl_rcu(obj->base.resv); if (fence) { add_rps_boost_after_vblank(new_state->crtc, fence); dma_fence_put(fence); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_busy.c b/drivers/gpu/drm/i915/gem/i915_gem_busy.c index 8473292096cb..a2aff1d8290e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_busy.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_busy.c @@ -82,7 +82,7 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, { struct drm_i915_gem_busy *args = data; struct drm_i915_gem_object *obj; - struct reservation_object_list *list; + struct dma_resv_list *list; unsigned int i, shared_count; struct dma_fence *excl; int err; @@ -106,11 +106,11 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, * Alternatively, we can trade that extra information on read/write * activity with * args->busy = - * !reservation_object_test_signaled_rcu(obj->resv, true); + * !dma_resv_test_signaled_rcu(obj->resv, true); * to report the overall busyness. This is what the wait-ioctl does. * */ - reservation_object_fences(obj->base.resv, &excl, &list, &shared_count); + dma_resv_fences(obj->base.resv, &excl, &list, &shared_count); /* Translate the exclusive fence to the READ *and* WRITE engine */ args->busy = busy_check_writer(excl); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c index 5295285d5843..88ee8ca7967f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c @@ -147,7 +147,7 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj, true, I915_FENCE_TIMEOUT, I915_FENCE_GFP); - reservation_object_add_excl_fence(obj->base.resv, + dma_resv_add_excl_fence(obj->base.resv, &clflush->dma); i915_sw_fence_commit(&clflush->wait); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c index 1fdab0767a47..693fcfce5d69 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_client_blt.c @@ -288,7 +288,7 @@ int i915_gem_schedule_fill_pages_blt(struct drm_i915_gem_object *obj, if (err < 0) { dma_fence_set_error(&work->dma, err); } else { - reservation_object_add_excl_fence(obj->base.resv, &work->dma); + dma_resv_add_excl_fence(obj->base.resv, &work->dma); err = 0; } i915_gem_object_unlock(obj); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index 570b20ad9e58..96ce95c8ac5a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include "i915_drv.h" #include "i915_gem_object.h" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 5fae0e50aad0..2d71653ede00 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -5,7 +5,7 @@ */ #include -#include +#include #include #include @@ -1246,7 +1246,7 @@ static int __reloc_gpu_alloc(struct i915_execbuffer *eb, goto skip_request; i915_vma_lock(batch); - GEM_BUG_ON(!reservation_object_test_signaled_rcu(batch->resv, true)); + GEM_BUG_ON(!dma_resv_test_signaled_rcu(batch->resv, true)); err = i915_vma_move_to_active(batch, rq, 0); i915_vma_unlock(batch); if (err) @@ -1317,7 +1317,7 @@ relocate_entry(struct i915_vma *vma, if (!eb->reloc_cache.vaddr && (DBG_FORCE_RELOC == FORCE_GPU_RELOC || - !reservation_object_test_signaled_rcu(vma->resv, true))) { + !dma_resv_test_signaled_rcu(vma->resv, true))) { const unsigned int gen = eb->reloc_cache.gen; unsigned int len; u32 *batch; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_fence.c b/drivers/gpu/drm/i915/gem/i915_gem_fence.c index cf0439e6be83..5496f33a9064 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_fence.c @@ -78,7 +78,7 @@ i915_gem_object_lock_fence(struct drm_i915_gem_object *obj) I915_FENCE_GFP) < 0) goto err; - reservation_object_add_excl_fence(obj->base.resv, &stub->dma); + dma_resv_add_excl_fence(obj->base.resv, &stub->dma); return &stub->dma; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index dfebd5706f16..d5f8fdc95fd9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -99,22 +99,22 @@ i915_gem_object_put(struct drm_i915_gem_object *obj) __drm_gem_object_put(&obj->base); } -#define assert_object_held(obj) reservation_object_assert_held((obj)->base.resv) +#define assert_object_held(obj) dma_resv_assert_held((obj)->base.resv) static inline void i915_gem_object_lock(struct drm_i915_gem_object *obj) { - reservation_object_lock(obj->base.resv, NULL); + dma_resv_lock(obj->base.resv, NULL); } static inline int i915_gem_object_lock_interruptible(struct drm_i915_gem_object *obj) { - return reservation_object_lock_interruptible(obj->base.resv, NULL); + return dma_resv_lock_interruptible(obj->base.resv, NULL); } static inline void i915_gem_object_unlock(struct drm_i915_gem_object *obj) { - reservation_object_unlock(obj->base.resv); + dma_resv_unlock(obj->base.resv); } struct dma_fence * @@ -373,7 +373,7 @@ i915_gem_object_last_write_engine(struct drm_i915_gem_object *obj) struct dma_fence *fence; rcu_read_lock(); - fence = reservation_object_get_excl_rcu(obj->base.resv); + fence = dma_resv_get_excl_rcu(obj->base.resv); rcu_read_unlock(); if (fence && dma_fence_is_i915(fence) && !dma_fence_is_signaled(fence)) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c index fa46a54bcbe7..8af55cd3e690 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c @@ -31,7 +31,7 @@ i915_gem_object_wait_fence(struct dma_fence *fence, } static long -i915_gem_object_wait_reservation(struct reservation_object *resv, +i915_gem_object_wait_reservation(struct dma_resv *resv, unsigned int flags, long timeout) { @@ -43,7 +43,7 @@ i915_gem_object_wait_reservation(struct reservation_object *resv, unsigned int count, i; int ret; - ret = reservation_object_get_fences_rcu(resv, + ret = dma_resv_get_fences_rcu(resv, &excl, &count, &shared); if (ret) return ret; @@ -72,7 +72,7 @@ i915_gem_object_wait_reservation(struct reservation_object *resv, */ prune_fences = count && timeout >= 0; } else { - excl = reservation_object_get_excl_rcu(resv); + excl = dma_resv_get_excl_rcu(resv); } if (excl && timeout >= 0) @@ -84,10 +84,10 @@ i915_gem_object_wait_reservation(struct reservation_object *resv, * Opportunistically prune the fences iff we know they have *all* been * signaled. */ - if (prune_fences && reservation_object_trylock(resv)) { - if (reservation_object_test_signaled_rcu(resv, true)) - reservation_object_add_excl_fence(resv, NULL); - reservation_object_unlock(resv); + if (prune_fences && dma_resv_trylock(resv)) { + if (dma_resv_test_signaled_rcu(resv, true)) + dma_resv_add_excl_fence(resv, NULL); + dma_resv_unlock(resv); } return timeout; @@ -140,7 +140,7 @@ i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, unsigned int count, i; int ret; - ret = reservation_object_get_fences_rcu(obj->base.resv, + ret = dma_resv_get_fences_rcu(obj->base.resv, &excl, &count, &shared); if (ret) return ret; @@ -152,7 +152,7 @@ i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, kfree(shared); } else { - excl = reservation_object_get_excl_rcu(obj->base.resv); + excl = dma_resv_get_excl_rcu(obj->base.resv); } if (excl) { diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bdd596604e93..b62db22b37a1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -43,7 +43,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 190ad54fb072..a5a439cb8c06 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/gpu/drm/i915/i915_gem_batch_pool.c b/drivers/gpu/drm/i915/i915_gem_batch_pool.c index 25a3e4d09a2f..5f82a763e64c 100644 --- a/drivers/gpu/drm/i915/i915_gem_batch_pool.c +++ b/drivers/gpu/drm/i915/i915_gem_batch_pool.c @@ -96,9 +96,9 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, list_for_each_entry(obj, list, batch_pool_link) { /* The batches are strictly LRU ordered */ if (i915_gem_object_is_active(obj)) { - struct reservation_object *resv = obj->base.resv; + struct dma_resv *resv = obj->base.resv; - if (!reservation_object_test_signaled_rcu(resv, true)) + if (!dma_resv_test_signaled_rcu(resv, true)) break; i915_retire_requests(pool->engine->i915); @@ -113,13 +113,13 @@ i915_gem_batch_pool_get(struct i915_gem_batch_pool *pool, * than replace the existing fence. */ if (rcu_access_pointer(resv->fence)) { - reservation_object_lock(resv, NULL); - reservation_object_add_excl_fence(resv, NULL); - reservation_object_unlock(resv); + dma_resv_lock(resv, NULL); + dma_resv_add_excl_fence(resv, NULL); + dma_resv_unlock(resv); } } - GEM_BUG_ON(!reservation_object_test_signaled_rcu(obj->base.resv, + GEM_BUG_ON(!dma_resv_test_signaled_rcu(obj->base.resv, true)); if (obj->base.size >= size) diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index a195a92d0105..0d1bd3f56c21 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -1027,7 +1027,7 @@ i915_request_await_object(struct i915_request *to, struct dma_fence **shared; unsigned int count, i; - ret = reservation_object_get_fences_rcu(obj->base.resv, + ret = dma_resv_get_fences_rcu(obj->base.resv, &excl, &count, &shared); if (ret) return ret; @@ -1044,7 +1044,7 @@ i915_request_await_object(struct i915_request *to, dma_fence_put(shared[i]); kfree(shared); } else { - excl = reservation_object_get_excl_rcu(obj->base.resv); + excl = dma_resv_get_excl_rcu(obj->base.resv); } if (excl) { diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 5387aafd3424..362e4e00b4c6 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "i915_sw_fence.h" #include "i915_selftest.h" @@ -510,7 +510,7 @@ int __i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, } int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, - struct reservation_object *resv, + struct dma_resv *resv, const struct dma_fence_ops *exclude, bool write, unsigned long timeout, @@ -526,7 +526,7 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, struct dma_fence **shared; unsigned int count, i; - ret = reservation_object_get_fences_rcu(resv, + ret = dma_resv_get_fences_rcu(resv, &excl, &count, &shared); if (ret) return ret; @@ -551,7 +551,7 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, dma_fence_put(shared[i]); kfree(shared); } else { - excl = reservation_object_get_excl_rcu(resv); + excl = dma_resv_get_excl_rcu(resv); } if (ret >= 0 && excl && excl->ops != exclude) { diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h index 9cb5c3b307a6..8cf353e8c3e0 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.h +++ b/drivers/gpu/drm/i915/i915_sw_fence.h @@ -16,7 +16,7 @@ #include struct completion; -struct reservation_object; +struct dma_resv; struct i915_sw_fence { wait_queue_head_t wait; @@ -82,7 +82,7 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, gfp_t gfp); int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, - struct reservation_object *resv, + struct dma_resv *resv, const struct dma_fence_ops *exclude, bool write, unsigned long timeout, diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index a57729be8312..ebfd03d117cd 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -99,10 +99,10 @@ static void __i915_vma_retire(struct i915_active *ref) return; /* Prune the shared fence arrays iff completely idle (inc. external) */ - if (reservation_object_trylock(obj->base.resv)) { - if (reservation_object_test_signaled_rcu(obj->base.resv, true)) - reservation_object_add_excl_fence(obj->base.resv, NULL); - reservation_object_unlock(obj->base.resv); + if (dma_resv_trylock(obj->base.resv)) { + if (dma_resv_test_signaled_rcu(obj->base.resv, true)) + dma_resv_add_excl_fence(obj->base.resv, NULL); + dma_resv_unlock(obj->base.resv); } /* @@ -903,7 +903,7 @@ static void export_fence(struct i915_vma *vma, struct i915_request *rq, unsigned int flags) { - struct reservation_object *resv = vma->resv; + struct dma_resv *resv = vma->resv; /* * Ignore errors from failing to allocate the new fence, we can't @@ -911,9 +911,9 @@ static void export_fence(struct i915_vma *vma, * synchronisation leading to rendering corruption. */ if (flags & EXEC_OBJECT_WRITE) - reservation_object_add_excl_fence(resv, &rq->fence); - else if (reservation_object_reserve_shared(resv, 1) == 0) - reservation_object_add_shared_fence(resv, &rq->fence); + dma_resv_add_excl_fence(resv, &rq->fence); + else if (dma_resv_reserve_shared(resv, 1) == 0) + dma_resv_add_shared_fence(resv, &rq->fence); } int i915_vma_move_to_active(struct i915_vma *vma, diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index 4b769db649bf..59a497561fc4 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -55,7 +55,7 @@ struct i915_vma { struct i915_address_space *vm; const struct i915_vma_ops *ops; struct i915_fence_reg *fence; - struct reservation_object *resv; /** Alias of obj->resv */ + struct dma_resv *resv; /** Alias of obj->resv */ struct sg_table *pages; void __iomem *iomap; void *private; /* owned by creator */ @@ -299,16 +299,16 @@ void i915_vma_close(struct i915_vma *vma); void i915_vma_reopen(struct i915_vma *vma); void i915_vma_destroy(struct i915_vma *vma); -#define assert_vma_held(vma) reservation_object_assert_held((vma)->resv) +#define assert_vma_held(vma) dma_resv_assert_held((vma)->resv) static inline void i915_vma_lock(struct i915_vma *vma) { - reservation_object_lock(vma->resv, NULL); + dma_resv_lock(vma->resv, NULL); } static inline void i915_vma_unlock(struct i915_vma *vma) { - reservation_object_unlock(vma->resv); + dma_resv_unlock(vma->resv); } int __i915_vma_do_pin(struct i915_vma *vma, diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c index fd1a024703d2..ff3d9acc24fc 100644 --- a/drivers/gpu/drm/lima/lima_gem.c +++ b/drivers/gpu/drm/lima/lima_gem.c @@ -136,7 +136,7 @@ static int lima_gem_sync_bo(struct lima_sched_task *task, struct lima_bo *bo, int err = 0; if (!write) { - err = reservation_object_reserve_shared(bo->gem.resv, 1); + err = dma_resv_reserve_shared(bo->gem.resv, 1); if (err) return err; } @@ -296,9 +296,9 @@ int lima_gem_submit(struct drm_file *file, struct lima_submit *submit) for (i = 0; i < submit->nr_bos; i++) { if (submit->bos[i].flags & LIMA_SUBMIT_BO_WRITE) - reservation_object_add_excl_fence(bos[i]->gem.resv, fence); + dma_resv_add_excl_fence(bos[i]->gem.resv, fence); else - reservation_object_add_shared_fence(bos[i]->gem.resv, fence); + dma_resv_add_shared_fence(bos[i]->gem.resv, fence); } lima_gem_unlock_bos(bos, submit->nr_bos, &ctx); @@ -341,7 +341,7 @@ int lima_gem_wait(struct drm_file *file, u32 handle, u32 op, s64 timeout_ns) timeout = drm_timeout_abs_to_jiffies(timeout_ns); - ret = drm_gem_reservation_object_wait(file, handle, write, timeout); + ret = drm_gem_dma_resv_wait(file, handle, write, timeout); if (ret == 0) ret = timeout ? -ETIMEDOUT : -EBUSY; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c index ae40b080ae47..3f230a28a2dc 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c @@ -4,7 +4,7 @@ */ #include -#include +#include #include #include diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 18da8d6ffc51..348a7ad2c044 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -663,13 +663,13 @@ void msm_gem_vunmap(struct drm_gem_object *obj, enum msm_gem_lock subclass) int msm_gem_sync_object(struct drm_gem_object *obj, struct msm_fence_context *fctx, bool exclusive) { - struct reservation_object_list *fobj; + struct dma_resv_list *fobj; struct dma_fence *fence; int i, ret; - fobj = reservation_object_get_list(obj->resv); + fobj = dma_resv_get_list(obj->resv); if (!fobj || (fobj->shared_count == 0)) { - fence = reservation_object_get_excl(obj->resv); + fence = dma_resv_get_excl(obj->resv); /* don't need to wait on our own fences, since ring is fifo */ if (fence && (fence->context != fctx->context)) { ret = dma_fence_wait(fence, true); @@ -683,7 +683,7 @@ int msm_gem_sync_object(struct drm_gem_object *obj, for (i = 0; i < fobj->shared_count; i++) { fence = rcu_dereference_protected(fobj->shared[i], - reservation_object_held(obj->resv)); + dma_resv_held(obj->resv)); if (fence->context != fctx->context) { ret = dma_fence_wait(fence, true); if (ret) @@ -701,9 +701,9 @@ void msm_gem_move_to_active(struct drm_gem_object *obj, WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED); msm_obj->gpu = gpu; if (exclusive) - reservation_object_add_excl_fence(obj->resv, fence); + dma_resv_add_excl_fence(obj->resv, fence); else - reservation_object_add_shared_fence(obj->resv, fence); + dma_resv_add_shared_fence(obj->resv, fence); list_del_init(&msm_obj->mm_list); list_add_tail(&msm_obj->mm_list, &gpu->active_list); } @@ -728,7 +728,7 @@ int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout) op & MSM_PREP_NOSYNC ? 0 : timeout_to_jiffies(timeout); long ret; - ret = reservation_object_wait_timeout_rcu(obj->resv, write, + ret = dma_resv_wait_timeout_rcu(obj->resv, write, true, remain); if (ret == 0) return remain == 0 ? -EBUSY : -ETIMEDOUT; @@ -760,8 +760,8 @@ static void describe_fence(struct dma_fence *fence, const char *type, void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m) { struct msm_gem_object *msm_obj = to_msm_bo(obj); - struct reservation_object *robj = obj->resv; - struct reservation_object_list *fobj; + struct dma_resv *robj = obj->resv; + struct dma_resv_list *fobj; struct dma_fence *fence; struct msm_gem_vma *vma; uint64_t off = drm_vma_node_start(&obj->vma_node); diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 8cfcf8f09e3e..9e0953c2b7ce 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -8,7 +8,7 @@ #define __MSM_GEM_H__ #include -#include +#include #include "msm_drv.h" /* Additional internal-use only BO flags: */ diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 348f8c2be806..2e1556b7af26 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -225,7 +225,7 @@ static int submit_fence_sync(struct msm_gem_submit *submit, bool no_implicit) * strange place to call it. OTOH this is a * convenient can-fail point to hook it in. */ - ret = reservation_object_reserve_shared(msm_obj->base.resv, + ret = dma_resv_reserve_shared(msm_obj->base.resv, 1); if (ret) return ret; diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 878ef6822812..e8506335cd15 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index 89f8e76a2d7d..027a01b97d1c 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -457,7 +457,7 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) asyw->image.handle[0] = ctxdma->object.handle; } - asyw->state.fence = reservation_object_get_excl_rcu(fb->nvbo->bo.base.resv); + asyw->state.fence = dma_resv_get_excl_rcu(fb->nvbo->bo.base.resv); asyw->image.offset[0] = fb->nvbo->bo.offset; if (wndw->func->prepare) { diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 99e391be9370..e0b1bbee936f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -188,7 +188,7 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, int nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, uint32_t flags, uint32_t tile_mode, uint32_t tile_flags, - struct sg_table *sg, struct reservation_object *robj, + struct sg_table *sg, struct dma_resv *robj, struct nouveau_bo **pnvbo) { struct nouveau_drm *drm = cli->drm; @@ -1324,7 +1324,7 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct drm_device *dev = drm->dev; - struct dma_fence *fence = reservation_object_get_excl(bo->base.resv); + struct dma_fence *fence = dma_resv_get_excl(bo->base.resv); nv10_bo_put_tile_region(dev, *old_tile, fence); *old_tile = new_tile; @@ -1655,12 +1655,12 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) void nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence, bool exclusive) { - struct reservation_object *resv = nvbo->bo.base.resv; + struct dma_resv *resv = nvbo->bo.base.resv; if (exclusive) - reservation_object_add_excl_fence(resv, &fence->base); + dma_resv_add_excl_fence(resv, &fence->base); else if (fence) - reservation_object_add_shared_fence(resv, &fence->base); + dma_resv_add_shared_fence(resv, &fence->base); } struct ttm_bo_driver nouveau_bo_driver = { diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index d675efe8e7f9..3ae84834bd5c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -73,7 +73,7 @@ extern struct ttm_bo_driver nouveau_bo_driver; void nouveau_bo_move_init(struct nouveau_drm *); int nouveau_bo_new(struct nouveau_cli *, u64 size, int align, u32 flags, u32 tile_mode, u32 tile_flags, struct sg_table *sg, - struct reservation_object *robj, + struct dma_resv *robj, struct nouveau_bo **); int nouveau_bo_pin(struct nouveau_bo *, u32 flags, bool contig); int nouveau_bo_unpin(struct nouveau_bo *); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index e5f249ab216a..8df390078c85 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -335,20 +335,20 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e { struct nouveau_fence_chan *fctx = chan->fence; struct dma_fence *fence; - struct reservation_object *resv = nvbo->bo.base.resv; - struct reservation_object_list *fobj; + struct dma_resv *resv = nvbo->bo.base.resv; + struct dma_resv_list *fobj; struct nouveau_fence *f; int ret = 0, i; if (!exclusive) { - ret = reservation_object_reserve_shared(resv, 1); + ret = dma_resv_reserve_shared(resv, 1); if (ret) return ret; } - fobj = reservation_object_get_list(resv); - fence = reservation_object_get_excl(resv); + fobj = dma_resv_get_list(resv); + fence = dma_resv_get_excl(resv); if (fence && (!exclusive || !fobj || !fobj->shared_count)) { struct nouveau_channel *prev = NULL; @@ -377,7 +377,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e bool must_wait = true; fence = rcu_dereference_protected(fobj->shared[i], - reservation_object_held(resv)); + dma_resv_held(resv)); f = nouveau_local_fence(fence, chan->drm); if (f) { diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index c7368aa0bdec..c77302f969e8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -887,7 +887,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, return -ENOENT; nvbo = nouveau_gem_object(gem); - lret = reservation_object_wait_timeout_rcu(nvbo->bo.base.resv, write, true, + lret = dma_resv_wait_timeout_rcu(nvbo->bo.base.resv, write, true, no_wait ? 0 : 30 * HZ); if (!lret) ret = -EBUSY; diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index e86ad7ae622b..7262ced9688a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -62,16 +62,16 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, { struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_bo *nvbo; - struct reservation_object *robj = attach->dmabuf->resv; + struct dma_resv *robj = attach->dmabuf->resv; u32 flags = 0; int ret; flags = TTM_PL_FLAG_TT; - reservation_object_lock(robj, NULL); + dma_resv_lock(robj, NULL); ret = nouveau_bo_new(&drm->client, attach->dmabuf->size, 0, flags, 0, 0, sg, robj, &nvbo); - reservation_object_unlock(robj); + dma_resv_unlock(robj); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index a1352750984c..b41754658681 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -274,7 +274,7 @@ panfrost_ioctl_wait_bo(struct drm_device *dev, void *data, if (!gem_obj) return -ENOENT; - ret = reservation_object_wait_timeout_rcu(gem_obj->resv, true, + ret = dma_resv_wait_timeout_rcu(gem_obj->resv, true, true, timeout); if (!ret) ret = timeout ? -ETIMEDOUT : -EBUSY; diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index d567ce98494c..0fc4539fd08d 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include @@ -199,7 +199,7 @@ static void panfrost_acquire_object_fences(struct drm_gem_object **bos, int i; for (i = 0; i < bo_count; i++) - implicit_fences[i] = reservation_object_get_excl_rcu(bos[i]->resv); + implicit_fences[i] = dma_resv_get_excl_rcu(bos[i]->resv); } static void panfrost_attach_object_fences(struct drm_gem_object **bos, @@ -209,7 +209,7 @@ static void panfrost_attach_object_fences(struct drm_gem_object **bos, int i; for (i = 0; i < bo_count; i++) - reservation_object_add_excl_fence(bos[i]->resv, fence); + dma_resv_add_excl_fence(bos[i]->resv, fence); } int panfrost_job_push(struct panfrost_job *job) diff --git a/drivers/gpu/drm/qxl/qxl_debugfs.c b/drivers/gpu/drm/qxl/qxl_debugfs.c index 94439212a5c5..a4f4175bbdbe 100644 --- a/drivers/gpu/drm/qxl/qxl_debugfs.c +++ b/drivers/gpu/drm/qxl/qxl_debugfs.c @@ -57,7 +57,7 @@ qxl_debugfs_buffers_info(struct seq_file *m, void *data) struct qxl_bo *bo; list_for_each_entry(bo, &qdev->gem.objects, list) { - struct reservation_object_list *fobj; + struct dma_resv_list *fobj; int rel; rcu_read_lock(); diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c index df55b83e0a55..312216caeea2 100644 --- a/drivers/gpu/drm/qxl/qxl_release.c +++ b/drivers/gpu/drm/qxl/qxl_release.c @@ -238,7 +238,7 @@ static int qxl_release_validate_bo(struct qxl_bo *bo) return ret; } - ret = reservation_object_reserve_shared(bo->tbo.base.resv, 1); + ret = dma_resv_reserve_shared(bo->tbo.base.resv, 1); if (ret) return ret; @@ -458,9 +458,9 @@ void qxl_release_fence_buffer_objects(struct qxl_release *release) list_for_each_entry(entry, &release->bos, head) { bo = entry->bo; - reservation_object_add_shared_fence(bo->base.resv, &release->base); + dma_resv_add_shared_fence(bo->base.resv, &release->base); ttm_bo_add_to_lru(bo); - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); } spin_unlock(&glob->lru_lock); ww_acquire_fini(&release->ticket); diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 40f4d29edfe2..62eab82a64f9 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -3659,7 +3659,7 @@ bool cik_semaphore_ring_emit(struct radeon_device *rdev, struct radeon_fence *cik_copy_cpdma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv) + struct dma_resv *resv) { struct radeon_fence *fence; struct radeon_sync sync; diff --git a/drivers/gpu/drm/radeon/cik_sdma.c b/drivers/gpu/drm/radeon/cik_sdma.c index 589217a7e435..35b9dc6ce46a 100644 --- a/drivers/gpu/drm/radeon/cik_sdma.c +++ b/drivers/gpu/drm/radeon/cik_sdma.c @@ -579,7 +579,7 @@ void cik_sdma_fini(struct radeon_device *rdev) struct radeon_fence *cik_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv) + struct dma_resv *resv) { struct radeon_fence *fence; struct radeon_sync sync; diff --git a/drivers/gpu/drm/radeon/evergreen_dma.c b/drivers/gpu/drm/radeon/evergreen_dma.c index 5505a04ca402..a46ee6c2099d 100644 --- a/drivers/gpu/drm/radeon/evergreen_dma.c +++ b/drivers/gpu/drm/radeon/evergreen_dma.c @@ -108,7 +108,7 @@ struct radeon_fence *evergreen_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv) + struct dma_resv *resv) { struct radeon_fence *fence; struct radeon_sync sync; diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 5c05193da520..7089dfc8c2a9 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -891,7 +891,7 @@ struct radeon_fence *r100_copy_blit(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv) + struct dma_resv *resv) { struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; struct radeon_fence *fence; diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c index 9ce6dd83d284..840401413c58 100644 --- a/drivers/gpu/drm/radeon/r200.c +++ b/drivers/gpu/drm/radeon/r200.c @@ -84,7 +84,7 @@ struct radeon_fence *r200_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv) + struct dma_resv *resv) { struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; struct radeon_fence *fence; diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 7d175a9e8330..e937cc01910d 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2963,7 +2963,7 @@ bool r600_semaphore_ring_emit(struct radeon_device *rdev, struct radeon_fence *r600_copy_cpdma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv) + struct dma_resv *resv) { struct radeon_fence *fence; struct radeon_sync sync; diff --git a/drivers/gpu/drm/radeon/r600_dma.c b/drivers/gpu/drm/radeon/r600_dma.c index 35d92ef8a0d4..af6c0da45f28 100644 --- a/drivers/gpu/drm/radeon/r600_dma.c +++ b/drivers/gpu/drm/radeon/r600_dma.c @@ -444,7 +444,7 @@ void r600_dma_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) struct radeon_fence *r600_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv) + struct dma_resv *resv) { struct radeon_fence *fence; struct radeon_sync sync; diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 3f7701321d21..de1d090df034 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -619,7 +619,7 @@ void radeon_sync_fence(struct radeon_sync *sync, struct radeon_fence *fence); int radeon_sync_resv(struct radeon_device *rdev, struct radeon_sync *sync, - struct reservation_object *resv, + struct dma_resv *resv, bool shared); int radeon_sync_rings(struct radeon_device *rdev, struct radeon_sync *sync, @@ -1912,20 +1912,20 @@ struct radeon_asic { uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); u32 blit_ring_index; struct radeon_fence *(*dma)(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); u32 dma_ring_index; /* method used for bo copy */ struct radeon_fence *(*copy)(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); /* ring used for bo copies */ u32 copy_ring_index; } copy; diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index e3f036c20d64..a74fa18cd27b 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -86,7 +86,7 @@ struct radeon_fence *r100_copy_blit(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); int r100_set_surface_reg(struct radeon_device *rdev, int reg, uint32_t tiling_flags, uint32_t pitch, uint32_t offset, uint32_t obj_size); @@ -157,7 +157,7 @@ struct radeon_fence *r200_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); void r200_set_safe_registers(struct radeon_device *rdev); /* @@ -347,11 +347,11 @@ int r600_dma_ring_test(struct radeon_device *rdev, struct radeon_ring *cp); struct radeon_fence *r600_copy_cpdma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); struct radeon_fence *r600_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); void r600_hpd_init(struct radeon_device *rdev); void r600_hpd_fini(struct radeon_device *rdev); bool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd); @@ -473,7 +473,7 @@ void r700_cp_fini(struct radeon_device *rdev); struct radeon_fence *rv770_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); u32 rv770_get_xclk(struct radeon_device *rdev); int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); int rv770_get_temp(struct radeon_device *rdev); @@ -547,7 +547,7 @@ void evergreen_dma_ring_ib_execute(struct radeon_device *rdev, struct radeon_fence *evergreen_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); int evergreen_get_temp(struct radeon_device *rdev); int evergreen_get_allowed_info_register(struct radeon_device *rdev, u32 reg, u32 *val); @@ -725,7 +725,7 @@ int si_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib); struct radeon_fence *si_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); void si_dma_vm_copy_pages(struct radeon_device *rdev, struct radeon_ib *ib, @@ -796,11 +796,11 @@ void cik_sdma_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib); struct radeon_fence *cik_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); struct radeon_fence *cik_copy_cpdma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv); + struct dma_resv *resv); int cik_sdma_ring_test(struct radeon_device *rdev, struct radeon_ring *ring); int cik_sdma_ib_test(struct radeon_device *rdev, struct radeon_ring *ring); bool cik_sdma_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring); diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index 1ea50ce16312..ac9a5ec481c3 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c @@ -35,7 +35,7 @@ static int radeon_benchmark_do_move(struct radeon_device *rdev, unsigned size, uint64_t saddr, uint64_t daddr, int flag, int n, - struct reservation_object *resv) + struct dma_resv *resv) { unsigned long start_jiffies; unsigned long end_jiffies; diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 7e5254a34e84..7b5460678382 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -255,7 +255,7 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser *p) int r; list_for_each_entry(reloc, &p->validated, tv.head) { - struct reservation_object *resv; + struct dma_resv *resv; resv = reloc->robj->tbo.base.resv; r = radeon_sync_resv(p->rdev, &p->ib.sync, resv, diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 7bf73230ac0b..e81b01f8db90 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -533,7 +533,7 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc, DRM_ERROR("failed to pin new rbo buffer before flip\n"); goto cleanup; } - work->fence = dma_fence_get(reservation_object_get_excl(new_rbo->tbo.base.resv)); + work->fence = dma_fence_get(dma_resv_get_excl(new_rbo->tbo.base.resv)); radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL); radeon_bo_unreserve(new_rbo); diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index 03873f21a734..4cf58dbbe439 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -114,7 +114,7 @@ static int radeon_gem_set_domain(struct drm_gem_object *gobj, } if (domain == RADEON_GEM_DOMAIN_CPU) { /* Asking for cpu access wait for object idle */ - r = reservation_object_wait_timeout_rcu(robj->tbo.base.resv, true, true, 30 * HZ); + r = dma_resv_wait_timeout_rcu(robj->tbo.base.resv, true, true, 30 * HZ); if (!r) r = -EBUSY; @@ -449,7 +449,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, } robj = gem_to_radeon_bo(gobj); - r = reservation_object_test_signaled_rcu(robj->tbo.base.resv, true); + r = dma_resv_test_signaled_rcu(robj->tbo.base.resv, true); if (r == 0) r = -EBUSY; else @@ -478,7 +478,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, } robj = gem_to_radeon_bo(gobj); - ret = reservation_object_wait_timeout_rcu(robj->tbo.base.resv, true, true, 30 * HZ); + ret = dma_resv_wait_timeout_rcu(robj->tbo.base.resv, true, true, 30 * HZ); if (ret == 0) r = -EBUSY; else if (ret < 0) diff --git a/drivers/gpu/drm/radeon/radeon_mn.c b/drivers/gpu/drm/radeon/radeon_mn.c index 0d64ace0e6c1..6902f998ede9 100644 --- a/drivers/gpu/drm/radeon/radeon_mn.c +++ b/drivers/gpu/drm/radeon/radeon_mn.c @@ -163,7 +163,7 @@ static int radeon_mn_invalidate_range_start(struct mmu_notifier *mn, continue; } - r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv, + r = dma_resv_wait_timeout_rcu(bo->tbo.base.resv, true, false, MAX_SCHEDULE_TIMEOUT); if (r <= 0) DRM_ERROR("(%ld) failed to wait for user bo\n", r); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 9db8ba29ef68..2abe1eab471f 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -183,7 +183,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) int radeon_bo_create(struct radeon_device *rdev, unsigned long size, int byte_align, bool kernel, u32 domain, u32 flags, struct sg_table *sg, - struct reservation_object *resv, + struct dma_resv *resv, struct radeon_bo **bo_ptr) { struct radeon_bo *bo; @@ -610,7 +610,7 @@ int radeon_bo_get_surface_reg(struct radeon_bo *bo) int steal; int i; - reservation_object_assert_held(bo->tbo.base.resv); + dma_resv_assert_held(bo->tbo.base.resv); if (!bo->tiling_flags) return 0; @@ -736,7 +736,7 @@ void radeon_bo_get_tiling_flags(struct radeon_bo *bo, uint32_t *tiling_flags, uint32_t *pitch) { - reservation_object_assert_held(bo->tbo.base.resv); + dma_resv_assert_held(bo->tbo.base.resv); if (tiling_flags) *tiling_flags = bo->tiling_flags; @@ -748,7 +748,7 @@ int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, bool force_drop) { if (!force_drop) - reservation_object_assert_held(bo->tbo.base.resv); + dma_resv_assert_held(bo->tbo.base.resv); if (!(bo->tiling_flags & RADEON_TILING_SURFACE)) return 0; @@ -870,10 +870,10 @@ int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, bool no_wait) void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence, bool shared) { - struct reservation_object *resv = bo->tbo.base.resv; + struct dma_resv *resv = bo->tbo.base.resv; if (shared) - reservation_object_add_shared_fence(resv, &fence->base); + dma_resv_add_shared_fence(resv, &fence->base); else - reservation_object_add_excl_fence(resv, &fence->base); + dma_resv_add_excl_fence(resv, &fence->base); } diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index e5554bf9140e..d23f2ed4126e 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -126,7 +126,7 @@ extern int radeon_bo_create(struct radeon_device *rdev, unsigned long size, int byte_align, bool kernel, u32 domain, u32 flags, struct sg_table *sg, - struct reservation_object *resv, + struct dma_resv *resv, struct radeon_bo **bo_ptr); extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr); extern void radeon_bo_kunmap(struct radeon_bo *bo); diff --git a/drivers/gpu/drm/radeon/radeon_prime.c b/drivers/gpu/drm/radeon/radeon_prime.c index 52b0d0cd8cbe..b906e8fbd5f3 100644 --- a/drivers/gpu/drm/radeon/radeon_prime.c +++ b/drivers/gpu/drm/radeon/radeon_prime.c @@ -63,15 +63,15 @@ struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sg) { - struct reservation_object *resv = attach->dmabuf->resv; + struct dma_resv *resv = attach->dmabuf->resv; struct radeon_device *rdev = dev->dev_private; struct radeon_bo *bo; int ret; - reservation_object_lock(resv, NULL); + dma_resv_lock(resv, NULL); ret = radeon_bo_create(rdev, attach->dmabuf->size, PAGE_SIZE, false, RADEON_GEM_DOMAIN_GTT, 0, sg, resv, &bo); - reservation_object_unlock(resv); + dma_resv_unlock(resv); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/radeon/radeon_sync.c b/drivers/gpu/drm/radeon/radeon_sync.c index 8c9780b5a884..55cc77a73c7b 100644 --- a/drivers/gpu/drm/radeon/radeon_sync.c +++ b/drivers/gpu/drm/radeon/radeon_sync.c @@ -87,30 +87,30 @@ void radeon_sync_fence(struct radeon_sync *sync, */ int radeon_sync_resv(struct radeon_device *rdev, struct radeon_sync *sync, - struct reservation_object *resv, + struct dma_resv *resv, bool shared) { - struct reservation_object_list *flist; + struct dma_resv_list *flist; struct dma_fence *f; struct radeon_fence *fence; unsigned i; int r = 0; /* always sync to the exclusive fence */ - f = reservation_object_get_excl(resv); + f = dma_resv_get_excl(resv); fence = f ? to_radeon_fence(f) : NULL; if (fence && fence->rdev == rdev) radeon_sync_fence(sync, fence); else if (f) r = dma_fence_wait(f, true); - flist = reservation_object_get_list(resv); + flist = dma_resv_get_list(resv); if (shared || !flist || r) return r; for (i = 0; i < flist->shared_count; ++i) { f = rcu_dereference_protected(flist->shared[i], - reservation_object_held(resv)); + dma_resv_held(resv)); fence = to_radeon_fence(f); if (fence && fence->rdev == rdev) radeon_sync_fence(sync, fence); diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index 311e69c2ed7f..1ad5c3b86b64 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -477,7 +477,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, return -EINVAL; } - f = reservation_object_get_excl(bo->tbo.base.resv); + f = dma_resv_get_excl(bo->tbo.base.resv); if (f) { r = radeon_fence_wait((struct radeon_fence *)f, false); if (r) { diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index e48a05533126..e0ad547786e8 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -831,7 +831,7 @@ static int radeon_vm_update_ptes(struct radeon_device *rdev, int r; radeon_sync_resv(rdev, &ib->sync, pt->tbo.base.resv, true); - r = reservation_object_reserve_shared(pt->tbo.base.resv, 1); + r = dma_resv_reserve_shared(pt->tbo.base.resv, 1); if (r) return r; diff --git a/drivers/gpu/drm/radeon/rv770_dma.c b/drivers/gpu/drm/radeon/rv770_dma.c index 0866b38ef264..4c91614b5e70 100644 --- a/drivers/gpu/drm/radeon/rv770_dma.c +++ b/drivers/gpu/drm/radeon/rv770_dma.c @@ -42,7 +42,7 @@ struct radeon_fence *rv770_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv) + struct dma_resv *resv) { struct radeon_fence *fence; struct radeon_sync sync; diff --git a/drivers/gpu/drm/radeon/si_dma.c b/drivers/gpu/drm/radeon/si_dma.c index 4773bb7d947e..d2fa302a5be9 100644 --- a/drivers/gpu/drm/radeon/si_dma.c +++ b/drivers/gpu/drm/radeon/si_dma.c @@ -231,7 +231,7 @@ void si_dma_vm_flush(struct radeon_device *rdev, struct radeon_ring *ring, struct radeon_fence *si_copy_dma(struct radeon_device *rdev, uint64_t src_offset, uint64_t dst_offset, unsigned num_gpu_pages, - struct reservation_object *resv) + struct dma_resv *resv) { struct radeon_fence *fence; struct radeon_sync sync; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 10a861a1690c..58d1f2b28132 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -41,7 +41,7 @@ #include #include #include -#include +#include static void ttm_bo_global_kobj_release(struct kobject *kobj); @@ -161,7 +161,7 @@ static void ttm_bo_release_list(struct kref *list_kref) atomic_dec(&bo->bdev->glob->bo_count); dma_fence_put(bo->moving); if (!ttm_bo_uses_embedded_gem_object(bo)) - reservation_object_fini(&bo->base._resv); + dma_resv_fini(&bo->base._resv); mutex_destroy(&bo->wu_mutex); bo->destroy(bo); ttm_mem_global_free(bdev->glob->mem_glob, acc_size); @@ -173,7 +173,7 @@ static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo, struct ttm_bo_device *bdev = bo->bdev; struct ttm_mem_type_manager *man; - reservation_object_assert_held(bo->base.resv); + dma_resv_assert_held(bo->base.resv); if (!list_empty(&bo->lru)) return; @@ -244,7 +244,7 @@ static void ttm_bo_bulk_move_set_pos(struct ttm_lru_bulk_move_pos *pos, void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo, struct ttm_lru_bulk_move *bulk) { - reservation_object_assert_held(bo->base.resv); + dma_resv_assert_held(bo->base.resv); ttm_bo_del_from_lru(bo); ttm_bo_add_to_lru(bo); @@ -277,8 +277,8 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) if (!pos->first) continue; - reservation_object_assert_held(pos->first->base.resv); - reservation_object_assert_held(pos->last->base.resv); + dma_resv_assert_held(pos->first->base.resv); + dma_resv_assert_held(pos->last->base.resv); man = &pos->first->bdev->man[TTM_PL_TT]; list_bulk_move_tail(&man->lru[i], &pos->first->lru, @@ -292,8 +292,8 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) if (!pos->first) continue; - reservation_object_assert_held(pos->first->base.resv); - reservation_object_assert_held(pos->last->base.resv); + dma_resv_assert_held(pos->first->base.resv); + dma_resv_assert_held(pos->last->base.resv); man = &pos->first->bdev->man[TTM_PL_VRAM]; list_bulk_move_tail(&man->lru[i], &pos->first->lru, @@ -307,8 +307,8 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) if (!pos->first) continue; - reservation_object_assert_held(pos->first->base.resv); - reservation_object_assert_held(pos->last->base.resv); + dma_resv_assert_held(pos->first->base.resv); + dma_resv_assert_held(pos->last->base.resv); lru = &pos->first->bdev->glob->swap_lru[i]; list_bulk_move_tail(lru, &pos->first->swap, &pos->last->swap); @@ -442,29 +442,29 @@ static int ttm_bo_individualize_resv(struct ttm_buffer_object *bo) if (bo->base.resv == &bo->base._resv) return 0; - BUG_ON(!reservation_object_trylock(&bo->base._resv)); + BUG_ON(!dma_resv_trylock(&bo->base._resv)); - r = reservation_object_copy_fences(&bo->base._resv, bo->base.resv); + r = dma_resv_copy_fences(&bo->base._resv, bo->base.resv); if (r) - reservation_object_unlock(&bo->base._resv); + dma_resv_unlock(&bo->base._resv); return r; } static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo) { - struct reservation_object_list *fobj; + struct dma_resv_list *fobj; struct dma_fence *fence; int i; - fobj = reservation_object_get_list(&bo->base._resv); - fence = reservation_object_get_excl(&bo->base._resv); + fobj = dma_resv_get_list(&bo->base._resv); + fence = dma_resv_get_excl(&bo->base._resv); if (fence && !fence->ops->signaled) dma_fence_enable_sw_signaling(fence); for (i = 0; fobj && i < fobj->shared_count; ++i) { fence = rcu_dereference_protected(fobj->shared[i], - reservation_object_held(bo->base.resv)); + dma_resv_held(bo->base.resv)); if (!fence->ops->signaled) dma_fence_enable_sw_signaling(fence); @@ -482,23 +482,23 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) /* Last resort, if we fail to allocate memory for the * fences block for the BO to become idle */ - reservation_object_wait_timeout_rcu(bo->base.resv, true, false, + dma_resv_wait_timeout_rcu(bo->base.resv, true, false, 30 * HZ); spin_lock(&glob->lru_lock); goto error; } spin_lock(&glob->lru_lock); - ret = reservation_object_trylock(bo->base.resv) ? 0 : -EBUSY; + ret = dma_resv_trylock(bo->base.resv) ? 0 : -EBUSY; if (!ret) { - if (reservation_object_test_signaled_rcu(&bo->base._resv, true)) { + if (dma_resv_test_signaled_rcu(&bo->base._resv, true)) { ttm_bo_del_from_lru(bo); spin_unlock(&glob->lru_lock); if (bo->base.resv != &bo->base._resv) - reservation_object_unlock(&bo->base._resv); + dma_resv_unlock(&bo->base._resv); ttm_bo_cleanup_memtype_use(bo); - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); return; } @@ -514,10 +514,10 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) ttm_bo_add_to_lru(bo); } - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); } if (bo->base.resv != &bo->base._resv) - reservation_object_unlock(&bo->base._resv); + dma_resv_unlock(&bo->base._resv); error: kref_get(&bo->list_kref); @@ -546,7 +546,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool unlock_resv) { struct ttm_bo_global *glob = bo->bdev->glob; - struct reservation_object *resv; + struct dma_resv *resv; int ret; if (unlikely(list_empty(&bo->ddestroy))) @@ -554,7 +554,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, else resv = &bo->base._resv; - if (reservation_object_test_signaled_rcu(resv, true)) + if (dma_resv_test_signaled_rcu(resv, true)) ret = 0; else ret = -EBUSY; @@ -563,10 +563,10 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, long lret; if (unlock_resv) - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); spin_unlock(&glob->lru_lock); - lret = reservation_object_wait_timeout_rcu(resv, true, + lret = dma_resv_wait_timeout_rcu(resv, true, interruptible, 30 * HZ); @@ -576,7 +576,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, return -EBUSY; spin_lock(&glob->lru_lock); - if (unlock_resv && !reservation_object_trylock(bo->base.resv)) { + if (unlock_resv && !dma_resv_trylock(bo->base.resv)) { /* * We raced, and lost, someone else holds the reservation now, * and is probably busy in ttm_bo_cleanup_memtype_use. @@ -593,7 +593,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, if (ret || unlikely(list_empty(&bo->ddestroy))) { if (unlock_resv) - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); spin_unlock(&glob->lru_lock); return ret; } @@ -606,7 +606,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, ttm_bo_cleanup_memtype_use(bo); if (unlock_resv) - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); return 0; } @@ -634,12 +634,12 @@ static bool ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all) if (remove_all || bo->base.resv != &bo->base._resv) { spin_unlock(&glob->lru_lock); - reservation_object_lock(bo->base.resv, NULL); + dma_resv_lock(bo->base.resv, NULL); spin_lock(&glob->lru_lock); ttm_bo_cleanup_refs(bo, false, !remove_all, true); - } else if (reservation_object_trylock(bo->base.resv)) { + } else if (dma_resv_trylock(bo->base.resv)) { ttm_bo_cleanup_refs(bo, false, !remove_all, true); } else { spin_unlock(&glob->lru_lock); @@ -708,7 +708,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, struct ttm_placement placement; int ret = 0; - reservation_object_assert_held(bo->base.resv); + dma_resv_assert_held(bo->base.resv); placement.num_placement = 0; placement.num_busy_placement = 0; @@ -779,7 +779,7 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, bool ret = false; if (bo->base.resv == ctx->resv) { - reservation_object_assert_held(bo->base.resv); + dma_resv_assert_held(bo->base.resv); if (ctx->flags & TTM_OPT_FLAG_ALLOW_RES_EVICT || !list_empty(&bo->ddestroy)) ret = true; @@ -787,7 +787,7 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, if (busy) *busy = false; } else { - ret = reservation_object_trylock(bo->base.resv); + ret = dma_resv_trylock(bo->base.resv); *locked = ret; if (busy) *busy = !ret; @@ -815,10 +815,10 @@ static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo, return -EBUSY; if (ctx->interruptible) - r = reservation_object_lock_interruptible(busy_bo->base.resv, + r = dma_resv_lock_interruptible(busy_bo->base.resv, ticket); else - r = reservation_object_lock(busy_bo->base.resv, ticket); + r = dma_resv_lock(busy_bo->base.resv, ticket); /* * TODO: It would be better to keep the BO locked until allocation is at @@ -826,7 +826,7 @@ static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo, * of TTM. */ if (!r) - reservation_object_unlock(busy_bo->base.resv); + dma_resv_unlock(busy_bo->base.resv); return r == -EDEADLK ? -EBUSY : r; } @@ -852,7 +852,7 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, if (!ttm_bo_evict_swapout_allowable(bo, ctx, &locked, &busy)) { if (busy && !busy_bo && ticket != - reservation_object_locking_ctx(bo->base.resv)) + dma_resv_locking_ctx(bo->base.resv)) busy_bo = bo; continue; } @@ -860,7 +860,7 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, if (place && !bdev->driver->eviction_valuable(bo, place)) { if (locked) - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); continue; } break; @@ -932,9 +932,9 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo, spin_unlock(&man->move_lock); if (fence) { - reservation_object_add_shared_fence(bo->base.resv, fence); + dma_resv_add_shared_fence(bo->base.resv, fence); - ret = reservation_object_reserve_shared(bo->base.resv, 1); + ret = dma_resv_reserve_shared(bo->base.resv, 1); if (unlikely(ret)) { dma_fence_put(fence); return ret; @@ -961,7 +961,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, struct ww_acquire_ctx *ticket; int ret; - ticket = reservation_object_locking_ctx(bo->base.resv); + ticket = dma_resv_locking_ctx(bo->base.resv); do { ret = (*man->func->get_node)(man, bo, place, mem); if (unlikely(ret != 0)) @@ -1091,7 +1091,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, bool type_found = false; int i, ret; - ret = reservation_object_reserve_shared(bo->base.resv, 1); + ret = dma_resv_reserve_shared(bo->base.resv, 1); if (unlikely(ret)) return ret; @@ -1172,7 +1172,7 @@ static int ttm_bo_move_buffer(struct ttm_buffer_object *bo, int ret = 0; struct ttm_mem_reg mem; - reservation_object_assert_held(bo->base.resv); + dma_resv_assert_held(bo->base.resv); mem.num_pages = bo->num_pages; mem.size = mem.num_pages << PAGE_SHIFT; @@ -1242,7 +1242,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, int ret; uint32_t new_flags; - reservation_object_assert_held(bo->base.resv); + dma_resv_assert_held(bo->base.resv); /* * Check whether we need to move buffer. */ @@ -1279,7 +1279,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, struct ttm_operation_ctx *ctx, size_t acc_size, struct sg_table *sg, - struct reservation_object *resv, + struct dma_resv *resv, void (*destroy) (struct ttm_buffer_object *)) { int ret = 0; @@ -1333,7 +1333,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, bo->sg = sg; if (resv) { bo->base.resv = resv; - reservation_object_assert_held(bo->base.resv); + dma_resv_assert_held(bo->base.resv); } else { bo->base.resv = &bo->base._resv; } @@ -1342,7 +1342,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, * bo.gem is not initialized, so we have to setup the * struct elements we want use regardless. */ - reservation_object_init(&bo->base._resv); + dma_resv_init(&bo->base._resv); drm_vma_node_reset(&bo->base.vma_node); } atomic_inc(&bo->bdev->glob->bo_count); @@ -1360,7 +1360,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, * since otherwise lockdep will be angered in radeon. */ if (!resv) { - locked = reservation_object_trylock(bo->base.resv); + locked = dma_resv_trylock(bo->base.resv); WARN_ON(!locked); } @@ -1394,7 +1394,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev, bool interruptible, size_t acc_size, struct sg_table *sg, - struct reservation_object *resv, + struct dma_resv *resv, void (*destroy) (struct ttm_buffer_object *)) { struct ttm_operation_ctx ctx = { interruptible, false }; @@ -1804,13 +1804,13 @@ int ttm_bo_wait(struct ttm_buffer_object *bo, long timeout = 15 * HZ; if (no_wait) { - if (reservation_object_test_signaled_rcu(bo->base.resv, true)) + if (dma_resv_test_signaled_rcu(bo->base.resv, true)) return 0; else return -EBUSY; } - timeout = reservation_object_wait_timeout_rcu(bo->base.resv, true, + timeout = dma_resv_wait_timeout_rcu(bo->base.resv, true, interruptible, timeout); if (timeout < 0) return timeout; @@ -1818,7 +1818,7 @@ int ttm_bo_wait(struct ttm_buffer_object *bo, if (timeout == 0) return -EBUSY; - reservation_object_add_excl_fence(bo->base.resv, NULL); + dma_resv_add_excl_fence(bo->base.resv, NULL); return 0; } EXPORT_SYMBOL(ttm_bo_wait); @@ -1934,7 +1934,7 @@ out: * already swapped buffer. */ if (locked) - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); kref_put(&bo->list_kref, ttm_bo_release_list); return ret; } @@ -1972,14 +1972,14 @@ int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo) ret = mutex_lock_interruptible(&bo->wu_mutex); if (unlikely(ret != 0)) return -ERESTARTSYS; - if (!reservation_object_is_locked(bo->base.resv)) + if (!dma_resv_is_locked(bo->base.resv)) goto out_unlock; - ret = reservation_object_lock_interruptible(bo->base.resv, NULL); + ret = dma_resv_lock_interruptible(bo->base.resv, NULL); if (ret == -EINTR) ret = -ERESTARTSYS; if (unlikely(ret != 0)) goto out_unlock; - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); out_unlock: mutex_unlock(&bo->wu_mutex); diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 425a6d627b30..fe81c565e7ef 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include struct ttm_transfer_obj { struct ttm_buffer_object base; @@ -518,8 +518,8 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, fbo->base.destroy = &ttm_transfered_destroy; fbo->base.acc_size = 0; fbo->base.base.resv = &fbo->base.base._resv; - reservation_object_init(fbo->base.base.resv); - ret = reservation_object_trylock(fbo->base.base.resv); + dma_resv_init(fbo->base.base.resv); + ret = dma_resv_trylock(fbo->base.base.resv); WARN_ON(!ret); *new_obj = &fbo->base; @@ -689,7 +689,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, int ret; struct ttm_buffer_object *ghost_obj; - reservation_object_add_excl_fence(bo->base.resv, fence); + dma_resv_add_excl_fence(bo->base.resv, fence); if (evict) { ret = ttm_bo_wait(bo, false, false); if (ret) @@ -716,7 +716,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, if (ret) return ret; - reservation_object_add_excl_fence(ghost_obj->base.resv, fence); + dma_resv_add_excl_fence(ghost_obj->base.resv, fence); /** * If we're not moving to fixed memory, the TTM object @@ -752,7 +752,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, int ret; - reservation_object_add_excl_fence(bo->base.resv, fence); + dma_resv_add_excl_fence(bo->base.resv, fence); if (!evict) { struct ttm_buffer_object *ghost_obj; @@ -772,7 +772,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, if (ret) return ret; - reservation_object_add_excl_fence(ghost_obj->base.resv, fence); + dma_resv_add_excl_fence(ghost_obj->base.resv, fence); /** * If we're not moving to fixed memory, the TTM object @@ -841,7 +841,7 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) if (ret) return ret; - ret = reservation_object_copy_fences(ghost->base.resv, bo->base.resv); + ret = dma_resv_copy_fences(ghost->base.resv, bo->base.resv); /* Last resort, wait for the BO to be idle when we are OOM */ if (ret) ttm_bo_wait(bo, false, false); diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 85f5bcbe0c76..76eedb963693 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -71,7 +71,7 @@ static vm_fault_t ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo, ttm_bo_get(bo); up_read(&vmf->vma->vm_mm->mmap_sem); (void) dma_fence_wait(bo->moving, true); - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); ttm_bo_put(bo); goto out_unlock; } @@ -131,7 +131,7 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf) * for reserve, and if it fails, retry the fault after waiting * for the buffer to become unreserved. */ - if (unlikely(!reservation_object_trylock(bo->base.resv))) { + if (unlikely(!dma_resv_trylock(bo->base.resv))) { if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) { if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) { ttm_bo_get(bo); @@ -296,7 +296,7 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf) out_io_unlock: ttm_mem_io_unlock(man); out_unlock: - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); return ret; } diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c index 3aefe72fb5cb..131dae8f4170 100644 --- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c +++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c @@ -39,7 +39,7 @@ static void ttm_eu_backoff_reservation_reverse(struct list_head *list, list_for_each_entry_continue_reverse(entry, list, head) { struct ttm_buffer_object *bo = entry->bo; - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); } } @@ -71,7 +71,7 @@ void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket, if (list_empty(&bo->lru)) ttm_bo_add_to_lru(bo); - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); } spin_unlock(&glob->lru_lock); @@ -114,7 +114,7 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, ret = __ttm_bo_reserve(bo, intr, (ticket == NULL), ticket); if (!ret && unlikely(atomic_read(&bo->cpu_writers) > 0)) { - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); ret = -EBUSY; @@ -130,7 +130,7 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, if (!entry->num_shared) continue; - ret = reservation_object_reserve_shared(bo->base.resv, + ret = dma_resv_reserve_shared(bo->base.resv, entry->num_shared); if (!ret) continue; @@ -144,16 +144,16 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, if (ret == -EDEADLK) { if (intr) { - ret = reservation_object_lock_slow_interruptible(bo->base.resv, + ret = dma_resv_lock_slow_interruptible(bo->base.resv, ticket); } else { - reservation_object_lock_slow(bo->base.resv, ticket); + dma_resv_lock_slow(bo->base.resv, ticket); ret = 0; } } if (!ret && entry->num_shared) - ret = reservation_object_reserve_shared(bo->base.resv, + ret = dma_resv_reserve_shared(bo->base.resv, entry->num_shared); if (unlikely(ret != 0)) { @@ -201,14 +201,14 @@ void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket, list_for_each_entry(entry, list, head) { bo = entry->bo; if (entry->num_shared) - reservation_object_add_shared_fence(bo->base.resv, fence); + dma_resv_add_shared_fence(bo->base.resv, fence); else - reservation_object_add_excl_fence(bo->base.resv, fence); + dma_resv_add_excl_fence(bo->base.resv, fence); if (list_empty(&bo->lru)) ttm_bo_add_to_lru(bo); else ttm_bo_move_to_lru_tail(bo, NULL); - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); } spin_unlock(&glob->lru_lock); if (ticket) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 00b4a3337840..e0e9b4f69db6 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -48,7 +48,7 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc) struct ttm_bo_device *bdev = bo->bdev; uint32_t page_flags = 0; - reservation_object_assert_held(bo->base.resv); + dma_resv_assert_held(bo->base.resv); if (bdev->need_dma32) page_flags |= TTM_PAGE_FLAG_DMA32; diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 79744137d89f..5d80507b539b 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -409,7 +409,7 @@ v3d_wait_bo_ioctl(struct drm_device *dev, void *data, if (args->pad != 0) return -EINVAL; - ret = drm_gem_reservation_object_wait(file_priv, args->handle, + ret = drm_gem_dma_resv_wait(file_priv, args->handle, true, timeout_jiffies); /* Decrement the user's timeout, in case we got interrupted @@ -495,7 +495,7 @@ v3d_attach_fences_and_unlock_reservation(struct drm_file *file_priv, for (i = 0; i < job->bo_count; i++) { /* XXX: Use shared fences for read-only objects. */ - reservation_object_add_excl_fence(job->bo[i]->resv, + dma_resv_add_excl_fence(job->bo[i]->resv, job->done_fence); } diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index b72b760e3018..7a06cb6e31c5 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -543,7 +543,7 @@ vc4_update_bo_seqnos(struct vc4_exec_info *exec, uint64_t seqno) bo = to_vc4_bo(&exec->bo[i]->base); bo->seqno = seqno; - reservation_object_add_shared_fence(bo->base.base.resv, exec->fence); + dma_resv_add_shared_fence(bo->base.base.resv, exec->fence); } list_for_each_entry(bo, &exec->unref_list, unref_head) { @@ -554,7 +554,7 @@ vc4_update_bo_seqnos(struct vc4_exec_info *exec, uint64_t seqno) bo = to_vc4_bo(&exec->rcl_write_bo[i]->base); bo->write_seqno = seqno; - reservation_object_add_excl_fence(bo->base.base.resv, exec->fence); + dma_resv_add_excl_fence(bo->base.base.resv, exec->fence); } } @@ -642,7 +642,7 @@ retry: for (i = 0; i < exec->bo_count; i++) { bo = &exec->bo[i]->base; - ret = reservation_object_reserve_shared(bo->resv, 1); + ret = dma_resv_reserve_shared(bo->resv, 1); if (ret) { vc4_unlock_bo_reservations(dev, exec, acquire_ctx); return ret; diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c index d8630467549c..9268f6fc3f66 100644 --- a/drivers/gpu/drm/vgem/vgem_fence.c +++ b/drivers/gpu/drm/vgem/vgem_fence.c @@ -21,7 +21,7 @@ */ #include -#include +#include #include @@ -128,7 +128,7 @@ int vgem_fence_attach_ioctl(struct drm_device *dev, { struct drm_vgem_fence_attach *arg = data; struct vgem_file *vfile = file->driver_priv; - struct reservation_object *resv; + struct dma_resv *resv; struct drm_gem_object *obj; struct dma_fence *fence; int ret; @@ -151,7 +151,7 @@ int vgem_fence_attach_ioctl(struct drm_device *dev, /* Check for a conflicting fence */ resv = obj->resv; - if (!reservation_object_test_signaled_rcu(resv, + if (!dma_resv_test_signaled_rcu(resv, arg->flags & VGEM_FENCE_WRITE)) { ret = -EBUSY; goto err_fence; @@ -159,12 +159,12 @@ int vgem_fence_attach_ioctl(struct drm_device *dev, /* Expose the fence via the dma-buf */ ret = 0; - reservation_object_lock(resv, NULL); + dma_resv_lock(resv, NULL); if (arg->flags & VGEM_FENCE_WRITE) - reservation_object_add_excl_fence(resv, fence); - else if ((ret = reservation_object_reserve_shared(resv, 1)) == 0) - reservation_object_add_shared_fence(resv, fence); - reservation_object_unlock(resv); + dma_resv_add_excl_fence(resv, fence); + else if ((ret = dma_resv_reserve_shared(resv, 1)) == 0) + dma_resv_add_shared_fence(resv, fence); + dma_resv_unlock(resv); /* Record the fence in our idr for later signaling */ if (ret == 0) { diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index 3c430dd65f67..0a88ef11b9d3 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -396,7 +396,7 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev, (vgdev, qobj->hw_res_handle, vfpriv->ctx_id, offset, args->level, &box, fence); - reservation_object_add_excl_fence(qobj->tbo.base.resv, + dma_resv_add_excl_fence(qobj->tbo.base.resv, &fence->f); dma_fence_put(&fence->f); @@ -450,7 +450,7 @@ static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data, (vgdev, qobj, vfpriv ? vfpriv->ctx_id : 0, offset, args->level, &box, fence); - reservation_object_add_excl_fence(qobj->tbo.base.resv, + dma_resv_add_excl_fence(qobj->tbo.base.resv, &fence->f); dma_fence_put(&fence->f); } diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 3dc08f991a8d..a492ac3f4a7e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -212,7 +212,7 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane, 0, 0, vgfb->fence); ret = virtio_gpu_object_reserve(bo, false); if (!ret) { - reservation_object_add_excl_fence(bo->tbo.base.resv, + dma_resv_add_excl_fence(bo->tbo.base.resv, &vgfb->fence->f); dma_fence_put(&vgfb->fence->f); vgfb->fence = NULL; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c index 6c01ad2785dd..bb46ca0c458f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c @@ -459,9 +459,9 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, /* Buffer objects need to be either pinned or reserved: */ if (!(dst->mem.placement & TTM_PL_FLAG_NO_EVICT)) - reservation_object_assert_held(dst->base.resv); + dma_resv_assert_held(dst->base.resv); if (!(src->mem.placement & TTM_PL_FLAG_NO_EVICT)) - reservation_object_assert_held(src->base.resv); + dma_resv_assert_held(src->base.resv); if (dst->ttm->state == tt_unpopulated) { ret = dst->ttm->bdev->driver->ttm_tt_populate(dst->ttm, &ctx); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index 369034c0de31..a05ef9d0a2e7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -342,7 +342,7 @@ void vmw_bo_pin_reserved(struct vmw_buffer_object *vbo, bool pin) uint32_t old_mem_type = bo->mem.mem_type; int ret; - reservation_object_assert_held(bo->base.resv); + dma_resv_assert_held(bo->base.resv); if (pin) { if (vbo->pin_count++ > 0) @@ -689,7 +689,7 @@ static int vmw_user_bo_synccpu_grab(struct vmw_user_buffer_object *user_bo, bool nonblock = !!(flags & drm_vmw_synccpu_dontblock); long lret; - lret = reservation_object_wait_timeout_rcu + lret = dma_resv_wait_timeout_rcu (bo->base.resv, true, true, nonblock ? 0 : MAX_SCHEDULE_TIMEOUT); if (!lret) @@ -1007,10 +1007,10 @@ void vmw_bo_fence_single(struct ttm_buffer_object *bo, if (fence == NULL) { vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); - reservation_object_add_excl_fence(bo->base.resv, &fence->base); + dma_resv_add_excl_fence(bo->base.resv, &fence->base); dma_fence_put(&fence->base); } else - reservation_object_add_excl_fence(bo->base.resv, &fence->base); + dma_resv_add_excl_fence(bo->base.resv, &fence->base); } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c index 7984f172ec4a..1e3bd58bc2d4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c @@ -169,7 +169,7 @@ static int vmw_cotable_unscrub(struct vmw_resource *res) } *cmd; WARN_ON_ONCE(bo->mem.mem_type != VMW_PL_MOB); - reservation_object_assert_held(bo->base.resv); + dma_resv_assert_held(bo->base.resv); cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); if (!cmd) @@ -311,7 +311,7 @@ static int vmw_cotable_unbind(struct vmw_resource *res, return 0; WARN_ON_ONCE(bo->mem.mem_type != VMW_PL_MOB); - reservation_object_assert_held(bo->base.resv); + dma_resv_assert_held(bo->base.resv); mutex_lock(&dev_priv->binding_mutex); if (!vcotbl->scrubbed) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 701643b7b0c4..0b5472450633 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -402,14 +402,14 @@ void vmw_resource_unreserve(struct vmw_resource *res, if (switch_backup && new_backup != res->backup) { if (res->backup) { - reservation_object_assert_held(res->backup->base.base.resv); + dma_resv_assert_held(res->backup->base.base.resv); list_del_init(&res->mob_head); vmw_bo_unreference(&res->backup); } if (new_backup) { res->backup = vmw_bo_reference(new_backup); - reservation_object_assert_held(new_backup->base.base.resv); + dma_resv_assert_held(new_backup->base.base.resv); list_add_tail(&res->mob_head, &new_backup->res_list); } else { res->backup = NULL; @@ -691,7 +691,7 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo) .num_shared = 0 }; - reservation_object_assert_held(vbo->base.base.resv); + dma_resv_assert_held(vbo->base.base.resv); list_for_each_entry_safe(res, next, &vbo->res_list, mob_head) { if (!res->func->unbind) continue; diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 94aae87b1138..037b1f7a87a5 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h @@ -87,7 +87,7 @@ struct module; struct device_node; struct videomode; -struct reservation_object; +struct dma_resv; struct dma_buf_attachment; struct pci_dev; diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index ae693c0666cd..6aaba14f5972 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -35,7 +35,7 @@ */ #include -#include +#include #include @@ -276,7 +276,7 @@ struct drm_gem_object { * * Normally (@resv == &@_resv) except for imported GEM objects. */ - struct reservation_object *resv; + struct dma_resv *resv; /** * @_resv: @@ -285,7 +285,7 @@ struct drm_gem_object { * * This is unused for imported GEM objects. */ - struct reservation_object _resv; + struct dma_resv _resv; /** * @funcs: @@ -390,7 +390,7 @@ void drm_gem_put_pages(struct drm_gem_object *obj, struct page **pages, int drm_gem_objects_lookup(struct drm_file *filp, void __user *bo_handles, int count, struct drm_gem_object ***objs_out); struct drm_gem_object *drm_gem_object_lookup(struct drm_file *filp, u32 handle); -long drm_gem_reservation_object_wait(struct drm_file *filep, u32 handle, +long drm_gem_dma_resv_wait(struct drm_file *filep, u32 handle, bool wait_all, unsigned long timeout); int drm_gem_lock_reservations(struct drm_gem_object **objs, int count, struct ww_acquire_ctx *acquire_ctx); diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 65ef5376de59..43c4929a2171 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -40,7 +40,7 @@ #include #include #include -#include +#include struct ttm_bo_global; @@ -273,7 +273,7 @@ struct ttm_bo_kmap_obj { struct ttm_operation_ctx { bool interruptible; bool no_wait_gpu; - struct reservation_object *resv; + struct dma_resv *resv; uint64_t bytes_moved; uint32_t flags; }; @@ -493,7 +493,7 @@ size_t ttm_bo_dma_acc_size(struct ttm_bo_device *bdev, * @page_alignment: Data alignment in pages. * @ctx: TTM operation context for memory allocation. * @acc_size: Accounted size for this object. - * @resv: Pointer to a reservation_object, or NULL to let ttm allocate one. + * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one. * @destroy: Destroy function. Use NULL for kfree(). * * This function initializes a pre-allocated struct ttm_buffer_object. @@ -526,7 +526,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, struct ttm_operation_ctx *ctx, size_t acc_size, struct sg_table *sg, - struct reservation_object *resv, + struct dma_resv *resv, void (*destroy) (struct ttm_buffer_object *)); /** @@ -545,7 +545,7 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, * point to the shmem object backing a GEM object if TTM is used to back a * GEM user interface. * @acc_size: Accounted size for this object. - * @resv: Pointer to a reservation_object, or NULL to let ttm allocate one. + * @resv: Pointer to a dma_resv, or NULL to let ttm allocate one. * @destroy: Destroy function. Use NULL for kfree(). * * This function initializes a pre-allocated struct ttm_buffer_object. @@ -570,7 +570,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev, struct ttm_buffer_object *bo, unsigned long size, enum ttm_bo_type type, struct ttm_placement *placement, uint32_t page_alignment, bool interrubtible, size_t acc_size, - struct sg_table *sg, struct reservation_object *resv, + struct sg_table *sg, struct dma_resv *resv, void (*destroy) (struct ttm_buffer_object *)); /** diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 3f1935c19a66..e88e00c6cbf2 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -35,7 +35,7 @@ #include #include #include -#include +#include #include "ttm_bo_api.h" #include "ttm_memory.h" @@ -654,14 +654,14 @@ static inline int __ttm_bo_reserve(struct ttm_buffer_object *bo, if (WARN_ON(ticket)) return -EBUSY; - success = reservation_object_trylock(bo->base.resv); + success = dma_resv_trylock(bo->base.resv); return success ? 0 : -EBUSY; } if (interruptible) - ret = reservation_object_lock_interruptible(bo->base.resv, ticket); + ret = dma_resv_lock_interruptible(bo->base.resv, ticket); else - ret = reservation_object_lock(bo->base.resv, ticket); + ret = dma_resv_lock(bo->base.resv, ticket); if (ret == -EINTR) return -ERESTARTSYS; return ret; @@ -745,10 +745,10 @@ static inline int ttm_bo_reserve_slowpath(struct ttm_buffer_object *bo, WARN_ON(!kref_read(&bo->kref)); if (interruptible) - ret = reservation_object_lock_slow_interruptible(bo->base.resv, + ret = dma_resv_lock_slow_interruptible(bo->base.resv, ticket); else - reservation_object_lock_slow(bo->base.resv, ticket); + dma_resv_lock_slow(bo->base.resv, ticket); if (likely(ret == 0)) ttm_bo_del_sub_from_lru(bo); @@ -773,7 +773,7 @@ static inline void ttm_bo_unreserve(struct ttm_buffer_object *bo) else ttm_bo_move_to_lru_tail(bo, NULL); spin_unlock(&bo->bdev->glob->lru_lock); - reservation_object_unlock(bo->base.resv); + dma_resv_unlock(bo->base.resv); } /* diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h index bae060fae862..ec212cb27fdc 100644 --- a/include/linux/dma-buf.h +++ b/include/linux/dma-buf.h @@ -306,7 +306,7 @@ struct dma_buf { struct module *owner; struct list_head list_node; void *priv; - struct reservation_object *resv; + struct dma_resv *resv; /* poll support */ wait_queue_head_t poll; @@ -365,7 +365,7 @@ struct dma_buf_export_info { const struct dma_buf_ops *ops; size_t size; int flags; - struct reservation_object *resv; + struct dma_resv *resv; void *priv; }; diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h index bea1d05cf51e..404aa748eda6 100644 --- a/include/linux/dma-fence.h +++ b/include/linux/dma-fence.h @@ -279,7 +279,7 @@ static inline struct dma_fence *dma_fence_get(struct dma_fence *fence) } /** - * dma_fence_get_rcu - get a fence from a reservation_object_list with + * dma_fence_get_rcu - get a fence from a dma_resv_list with * rcu read lock * @fence: fence to increase refcount of * @@ -303,7 +303,7 @@ static inline struct dma_fence *dma_fence_get_rcu(struct dma_fence *fence) * so long as the caller is using RCU on the pointer to the fence. * * An alternative mechanism is to employ a seqlock to protect a bunch of - * fences, such as used by struct reservation_object. When using a seqlock, + * fences, such as used by struct dma_resv. When using a seqlock, * the seqlock must be taken before and checked after a reference to the * fence is acquired (as shown here). * diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h new file mode 100644 index 000000000000..38f2802afabb --- /dev/null +++ b/include/linux/dma-resv.h @@ -0,0 +1,312 @@ +/* + * Header file for reservations for dma-buf and ttm + * + * Copyright(C) 2011 Linaro Limited. All rights reserved. + * Copyright (C) 2012-2013 Canonical Ltd + * Copyright (C) 2012 Texas Instruments + * + * Authors: + * Rob Clark + * Maarten Lankhorst + * Thomas Hellstrom + * + * Based on bo.c which bears the following copyright notice, + * but is dual licensed: + * + * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., 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. + */ +#ifndef _LINUX_RESERVATION_H +#define _LINUX_RESERVATION_H + +#include +#include +#include +#include +#include + +extern struct ww_class reservation_ww_class; + +/** + * struct dma_resv_list - a list of shared fences + * @rcu: for internal use + * @shared_count: table of shared fences + * @shared_max: for growing shared fence table + * @shared: shared fence table + */ +struct dma_resv_list { + struct rcu_head rcu; + u32 shared_count, shared_max; + struct dma_fence __rcu *shared[]; +}; + +/** + * struct dma_resv - a reservation object manages fences for a buffer + * @lock: update side lock + * @seq: sequence count for managing RCU read-side synchronization + * @fence_excl: the exclusive fence, if there is one currently + * @fence: list of current shared fences + */ +struct dma_resv { + struct ww_mutex lock; + + struct dma_fence __rcu *fence_excl; + struct dma_resv_list __rcu *fence; +}; + +#define dma_resv_held(obj) lockdep_is_held(&(obj)->lock.base) +#define dma_resv_assert_held(obj) lockdep_assert_held(&(obj)->lock.base) + +/** + * dma_resv_get_excl - get the reservation object's + * exclusive fence, with update-side lock held + * @obj: the reservation object + * + * Returns the exclusive fence (if any). Does NOT take a + * reference. Writers must hold obj->lock, readers may only + * hold a RCU read side lock. + * + * RETURNS + * The exclusive fence or NULL + */ +static inline struct dma_fence *dma_resv_get_excl(struct dma_resv *obj) +{ + return rcu_dereference_protected(obj->fence_excl, + dma_resv_held(obj)); +} + +/** + * dma_resv_get_list - get the reservation object's + * shared fence list, with update-side lock held + * @obj: the reservation object + * + * Returns the shared fence list. Does NOT take references to + * the fence. The obj->lock must be held. + */ +static inline struct dma_resv_list *dma_resv_get_list(struct dma_resv *obj) +{ + return rcu_dereference_protected(obj->fence, + dma_resv_held(obj)); +} + +/** + * dma_resv_fences - read consistent fence pointers + * @obj: reservation object where we get the fences from + * @excl: pointer for the exclusive fence + * @list: pointer for the shared fence list + * + * Make sure we have a consisten exclusive fence and shared fence list. + * Must be called with rcu read side lock held. + */ +static inline void dma_resv_fences(struct dma_resv *obj, + struct dma_fence **excl, + struct dma_resv_list **list, + u32 *shared_count) +{ + do { + *excl = rcu_dereference(obj->fence_excl); + *list = rcu_dereference(obj->fence); + *shared_count = *list ? (*list)->shared_count : 0; + smp_rmb(); /* See dma_resv_add_excl_fence */ + } while (rcu_access_pointer(obj->fence_excl) != *excl); +} + +/** + * dma_resv_get_excl_rcu - get the reservation object's + * exclusive fence, without lock held. + * @obj: the reservation object + * + * If there is an exclusive fence, this atomically increments it's + * reference count and returns it. + * + * RETURNS + * The exclusive fence or NULL if none + */ +static inline struct dma_fence *dma_resv_get_excl_rcu(struct dma_resv *obj) +{ + struct dma_fence *fence; + + if (!rcu_access_pointer(obj->fence_excl)) + return NULL; + + rcu_read_lock(); + fence = dma_fence_get_rcu_safe(&obj->fence_excl); + rcu_read_unlock(); + + return fence; +} + +/** + * dma_resv_lock - lock the reservation object + * @obj: the reservation object + * @ctx: the locking context + * + * Locks the reservation object for exclusive access and modification. Note, + * that the lock is only against other writers, readers will run concurrently + * with a writer under RCU. The seqlock is used to notify readers if they + * overlap with a writer. + * + * As the reservation object may be locked by multiple parties in an + * undefined order, a #ww_acquire_ctx is passed to unwind if a cycle + * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation + * object may be locked by itself by passing NULL as @ctx. + */ +static inline int dma_resv_lock(struct dma_resv *obj, + struct ww_acquire_ctx *ctx) +{ + return ww_mutex_lock(&obj->lock, ctx); +} + +/** + * dma_resv_lock_interruptible - lock the reservation object + * @obj: the reservation object + * @ctx: the locking context + * + * Locks the reservation object interruptible for exclusive access and + * modification. Note, that the lock is only against other writers, readers + * will run concurrently with a writer under RCU. The seqlock is used to + * notify readers if they overlap with a writer. + * + * As the reservation object may be locked by multiple parties in an + * undefined order, a #ww_acquire_ctx is passed to unwind if a cycle + * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation + * object may be locked by itself by passing NULL as @ctx. + */ +static inline int dma_resv_lock_interruptible(struct dma_resv *obj, + struct ww_acquire_ctx *ctx) +{ + return ww_mutex_lock_interruptible(&obj->lock, ctx); +} + +/** + * dma_resv_lock_slow - slowpath lock the reservation object + * @obj: the reservation object + * @ctx: the locking context + * + * Acquires the reservation object after a die case. This function + * will sleep until the lock becomes available. See dma_resv_lock() as + * well. + */ +static inline void dma_resv_lock_slow(struct dma_resv *obj, + struct ww_acquire_ctx *ctx) +{ + ww_mutex_lock_slow(&obj->lock, ctx); +} + +/** + * dma_resv_lock_slow_interruptible - slowpath lock the reservation + * object, interruptible + * @obj: the reservation object + * @ctx: the locking context + * + * Acquires the reservation object interruptible after a die case. This function + * will sleep until the lock becomes available. See + * dma_resv_lock_interruptible() as well. + */ +static inline int dma_resv_lock_slow_interruptible(struct dma_resv *obj, + struct ww_acquire_ctx *ctx) +{ + return ww_mutex_lock_slow_interruptible(&obj->lock, ctx); +} + +/** + * dma_resv_trylock - trylock the reservation object + * @obj: the reservation object + * + * Tries to lock the reservation object for exclusive access and modification. + * Note, that the lock is only against other writers, readers will run + * concurrently with a writer under RCU. The seqlock is used to notify readers + * if they overlap with a writer. + * + * Also note that since no context is provided, no deadlock protection is + * possible. + * + * Returns true if the lock was acquired, false otherwise. + */ +static inline bool __must_check dma_resv_trylock(struct dma_resv *obj) +{ + return ww_mutex_trylock(&obj->lock); +} + +/** + * dma_resv_is_locked - is the reservation object locked + * @obj: the reservation object + * + * Returns true if the mutex is locked, false if unlocked. + */ +static inline bool dma_resv_is_locked(struct dma_resv *obj) +{ + return ww_mutex_is_locked(&obj->lock); +} + +/** + * dma_resv_locking_ctx - returns the context used to lock the object + * @obj: the reservation object + * + * Returns the context used to lock a reservation object or NULL if no context + * was used or the object is not locked at all. + */ +static inline struct ww_acquire_ctx *dma_resv_locking_ctx(struct dma_resv *obj) +{ + return READ_ONCE(obj->lock.ctx); +} + +/** + * dma_resv_unlock - unlock the reservation object + * @obj: the reservation object + * + * Unlocks the reservation object following exclusive access. + */ +static inline void dma_resv_unlock(struct dma_resv *obj) +{ +#ifdef CONFIG_DEBUG_MUTEXES + /* Test shared fence slot reservation */ + if (rcu_access_pointer(obj->fence)) { + struct dma_resv_list *fence = dma_resv_get_list(obj); + + fence->shared_max = fence->shared_count; + } +#endif + ww_mutex_unlock(&obj->lock); +} + +void dma_resv_init(struct dma_resv *obj); +void dma_resv_fini(struct dma_resv *obj); +int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences); +void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence); + +void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence); + +int dma_resv_get_fences_rcu(struct dma_resv *obj, + struct dma_fence **pfence_excl, + unsigned *pshared_count, + struct dma_fence ***pshared); + +int dma_resv_copy_fences(struct dma_resv *dst, struct dma_resv *src); + +long dma_resv_wait_timeout_rcu(struct dma_resv *obj, bool wait_all, bool intr, + unsigned long timeout); + +bool dma_resv_test_signaled_rcu(struct dma_resv *obj, bool test_all); + +#endif /* _LINUX_RESERVATION_H */ diff --git a/include/linux/reservation.h b/include/linux/reservation.h deleted file mode 100644 index acddefea694f..000000000000 --- a/include/linux/reservation.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Header file for reservations for dma-buf and ttm - * - * Copyright(C) 2011 Linaro Limited. All rights reserved. - * Copyright (C) 2012-2013 Canonical Ltd - * Copyright (C) 2012 Texas Instruments - * - * Authors: - * Rob Clark - * Maarten Lankhorst - * Thomas Hellstrom - * - * Based on bo.c which bears the following copyright notice, - * but is dual licensed: - * - * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., 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. - */ -#ifndef _LINUX_RESERVATION_H -#define _LINUX_RESERVATION_H - -#include -#include -#include -#include -#include - -extern struct ww_class reservation_ww_class; - -/** - * struct reservation_object_list - a list of shared fences - * @rcu: for internal use - * @shared_count: table of shared fences - * @shared_max: for growing shared fence table - * @shared: shared fence table - */ -struct reservation_object_list { - struct rcu_head rcu; - u32 shared_count, shared_max; - struct dma_fence __rcu *shared[]; -}; - -/** - * struct reservation_object - a reservation object manages fences for a buffer - * @lock: update side lock - * @seq: sequence count for managing RCU read-side synchronization - * @fence_excl: the exclusive fence, if there is one currently - * @fence: list of current shared fences - */ -struct reservation_object { - struct ww_mutex lock; - - struct dma_fence __rcu *fence_excl; - struct reservation_object_list __rcu *fence; -}; - -#define reservation_object_held(obj) lockdep_is_held(&(obj)->lock.base) -#define reservation_object_assert_held(obj) \ - lockdep_assert_held(&(obj)->lock.base) - -/** - * reservation_object_get_excl - get the reservation object's - * exclusive fence, with update-side lock held - * @obj: the reservation object - * - * Returns the exclusive fence (if any). Does NOT take a - * reference. Writers must hold obj->lock, readers may only - * hold a RCU read side lock. - * - * RETURNS - * The exclusive fence or NULL - */ -static inline struct dma_fence * -reservation_object_get_excl(struct reservation_object *obj) -{ - return rcu_dereference_protected(obj->fence_excl, - reservation_object_held(obj)); -} - -/** - * reservation_object_get_list - get the reservation object's - * shared fence list, with update-side lock held - * @obj: the reservation object - * - * Returns the shared fence list. Does NOT take references to - * the fence. The obj->lock must be held. - */ -static inline struct reservation_object_list * -reservation_object_get_list(struct reservation_object *obj) -{ - return rcu_dereference_protected(obj->fence, - reservation_object_held(obj)); -} - -/** - * reservation_object_fences - read consistent fence pointers - * @obj: reservation object where we get the fences from - * @excl: pointer for the exclusive fence - * @list: pointer for the shared fence list - * - * Make sure we have a consisten exclusive fence and shared fence list. - * Must be called with rcu read side lock held. - */ -static inline void -reservation_object_fences(struct reservation_object *obj, - struct dma_fence **excl, - struct reservation_object_list **list, - u32 *shared_count) -{ - do { - *excl = rcu_dereference(obj->fence_excl); - *list = rcu_dereference(obj->fence); - *shared_count = *list ? (*list)->shared_count : 0; - smp_rmb(); /* See reservation_object_add_excl_fence */ - } while (rcu_access_pointer(obj->fence_excl) != *excl); -} - -/** - * reservation_object_get_excl_rcu - get the reservation object's - * exclusive fence, without lock held. - * @obj: the reservation object - * - * If there is an exclusive fence, this atomically increments it's - * reference count and returns it. - * - * RETURNS - * The exclusive fence or NULL if none - */ -static inline struct dma_fence * -reservation_object_get_excl_rcu(struct reservation_object *obj) -{ - struct dma_fence *fence; - - if (!rcu_access_pointer(obj->fence_excl)) - return NULL; - - rcu_read_lock(); - fence = dma_fence_get_rcu_safe(&obj->fence_excl); - rcu_read_unlock(); - - return fence; -} - -/** - * reservation_object_lock - lock the reservation object - * @obj: the reservation object - * @ctx: the locking context - * - * Locks the reservation object for exclusive access and modification. Note, - * that the lock is only against other writers, readers will run concurrently - * with a writer under RCU. The seqlock is used to notify readers if they - * overlap with a writer. - * - * As the reservation object may be locked by multiple parties in an - * undefined order, a #ww_acquire_ctx is passed to unwind if a cycle - * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation - * object may be locked by itself by passing NULL as @ctx. - */ -static inline int -reservation_object_lock(struct reservation_object *obj, - struct ww_acquire_ctx *ctx) -{ - return ww_mutex_lock(&obj->lock, ctx); -} - -/** - * reservation_object_lock_interruptible - lock the reservation object - * @obj: the reservation object - * @ctx: the locking context - * - * Locks the reservation object interruptible for exclusive access and - * modification. Note, that the lock is only against other writers, readers - * will run concurrently with a writer under RCU. The seqlock is used to - * notify readers if they overlap with a writer. - * - * As the reservation object may be locked by multiple parties in an - * undefined order, a #ww_acquire_ctx is passed to unwind if a cycle - * is detected. See ww_mutex_lock() and ww_acquire_init(). A reservation - * object may be locked by itself by passing NULL as @ctx. - */ -static inline int -reservation_object_lock_interruptible(struct reservation_object *obj, - struct ww_acquire_ctx *ctx) -{ - return ww_mutex_lock_interruptible(&obj->lock, ctx); -} - -/** - * reservation_object_lock_slow - slowpath lock the reservation object - * @obj: the reservation object - * @ctx: the locking context - * - * Acquires the reservation object after a die case. This function - * will sleep until the lock becomes available. See reservation_object_lock() as - * well. - */ -static inline void -reservation_object_lock_slow(struct reservation_object *obj, - struct ww_acquire_ctx *ctx) -{ - ww_mutex_lock_slow(&obj->lock, ctx); -} - -/** - * reservation_object_lock_slow_interruptible - slowpath lock the reservation - * object, interruptible - * @obj: the reservation object - * @ctx: the locking context - * - * Acquires the reservation object interruptible after a die case. This function - * will sleep until the lock becomes available. See - * reservation_object_lock_interruptible() as well. - */ -static inline int -reservation_object_lock_slow_interruptible(struct reservation_object *obj, - struct ww_acquire_ctx *ctx) -{ - return ww_mutex_lock_slow_interruptible(&obj->lock, ctx); -} - -/** - * reservation_object_trylock - trylock the reservation object - * @obj: the reservation object - * - * Tries to lock the reservation object for exclusive access and modification. - * Note, that the lock is only against other writers, readers will run - * concurrently with a writer under RCU. The seqlock is used to notify readers - * if they overlap with a writer. - * - * Also note that since no context is provided, no deadlock protection is - * possible. - * - * Returns true if the lock was acquired, false otherwise. - */ -static inline bool __must_check -reservation_object_trylock(struct reservation_object *obj) -{ - return ww_mutex_trylock(&obj->lock); -} - -/** - * reservation_object_is_locked - is the reservation object locked - * @obj: the reservation object - * - * Returns true if the mutex is locked, false if unlocked. - */ -static inline bool -reservation_object_is_locked(struct reservation_object *obj) -{ - return ww_mutex_is_locked(&obj->lock); -} - -/** - * reservation_object_locking_ctx - returns the context used to lock the object - * @obj: the reservation object - * - * Returns the context used to lock a reservation object or NULL if no context - * was used or the object is not locked at all. - */ -static inline struct ww_acquire_ctx * -reservation_object_locking_ctx(struct reservation_object *obj) -{ - return READ_ONCE(obj->lock.ctx); -} - -/** - * reservation_object_unlock - unlock the reservation object - * @obj: the reservation object - * - * Unlocks the reservation object following exclusive access. - */ -static inline void -reservation_object_unlock(struct reservation_object *obj) -{ -#ifdef CONFIG_DEBUG_MUTEXES - /* Test shared fence slot reservation */ - if (rcu_access_pointer(obj->fence)) { - struct reservation_object_list *fence = - reservation_object_get_list(obj); - - fence->shared_max = fence->shared_count; - } -#endif - ww_mutex_unlock(&obj->lock); -} - -void reservation_object_init(struct reservation_object *obj); -void reservation_object_fini(struct reservation_object *obj); -int reservation_object_reserve_shared(struct reservation_object *obj, - unsigned int num_fences); -void reservation_object_add_shared_fence(struct reservation_object *obj, - struct dma_fence *fence); - -void reservation_object_add_excl_fence(struct reservation_object *obj, - struct dma_fence *fence); - -int reservation_object_get_fences_rcu(struct reservation_object *obj, - struct dma_fence **pfence_excl, - unsigned *pshared_count, - struct dma_fence ***pshared); - -int reservation_object_copy_fences(struct reservation_object *dst, - struct reservation_object *src); - -long reservation_object_wait_timeout_rcu(struct reservation_object *obj, - bool wait_all, bool intr, - unsigned long timeout); - -bool reservation_object_test_signaled_rcu(struct reservation_object *obj, - bool test_all); - -#endif /* _LINUX_RESERVATION_H */ -- cgit v1.2.3 From 8067f62bccaff4d5c7e0900431e8ab4372dcb8ab Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Aug 2019 14:07:19 +0200 Subject: drm/bridge: dw-hdmi-i2s: support more i2s format The dw-hdmi-i2s supports more formats than just regular i2s. Add support for left justified, right justified and dsp modes A and B. Reviewed-by: Jonas Karlman Signed-off-by: Jerome Brunet Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20190812120726.1528-2-jbrunet@baylibre.com --- .../gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 26 +++++++++++++++++++--- drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 6 +++-- 2 files changed, 27 insertions(+), 5 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index 5cbb71a866d5..2b624cff541d 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c @@ -44,9 +44,8 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, u8 inputclkfs = 0; /* it cares I2S only */ - if ((fmt->fmt != HDMI_I2S) || - (fmt->bit_clk_master | fmt->frame_clk_master)) { - dev_err(dev, "unsupported format/settings\n"); + if (fmt->bit_clk_master | fmt->frame_clk_master) { + dev_err(dev, "unsupported clock settings\n"); return -EINVAL; } @@ -63,6 +62,27 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, break; } + switch (fmt->fmt) { + case HDMI_I2S: + conf1 |= HDMI_AUD_CONF1_MODE_I2S; + break; + case HDMI_RIGHT_J: + conf1 |= HDMI_AUD_CONF1_MODE_RIGHT_J; + break; + case HDMI_LEFT_J: + conf1 |= HDMI_AUD_CONF1_MODE_LEFT_J; + break; + case HDMI_DSP_A: + conf1 |= HDMI_AUD_CONF1_MODE_BURST_1; + break; + case HDMI_DSP_B: + conf1 |= HDMI_AUD_CONF1_MODE_BURST_2; + break; + default: + dev_err(dev, "unsupported format\n"); + return -EINVAL; + } + dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate); hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h index 4e3ec09d3ca4..091d7c28aa17 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h @@ -869,8 +869,10 @@ enum { /* AUD_CONF1 field values */ HDMI_AUD_CONF1_MODE_I2S = 0x00, - HDMI_AUD_CONF1_MODE_RIGHT_J = 0x02, - HDMI_AUD_CONF1_MODE_LEFT_J = 0x04, + HDMI_AUD_CONF1_MODE_RIGHT_J = 0x20, + HDMI_AUD_CONF1_MODE_LEFT_J = 0x40, + HDMI_AUD_CONF1_MODE_BURST_1 = 0x60, + HDMI_AUD_CONF1_MODE_BURST_2 = 0x80, HDMI_AUD_CONF1_WIDTH_16 = 0x10, HDMI_AUD_CONF1_WIDTH_24 = 0x18, -- cgit v1.2.3 From 2a2a3d2ff799d62f25a9d222ad0fc73753c8a6c6 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Aug 2019 14:07:20 +0200 Subject: drm/bridge: dw-hdmi: move audio channel setup out of ahb Part of the channel count setup done in dw-hdmi ahb should actually be done whatever the interface providing the data. Let's move it to dw-hdmi driver instead. Reviewed-by: Jonas Karlman Signed-off-by: Jerome Brunet Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20190812120726.1528-3-jbrunet@baylibre.com --- .../gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c | 20 +++----------- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 32 ++++++++++++++++++++++ include/drm/bridge/dw_hdmi.h | 2 ++ 3 files changed, 38 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c index a494186ae6ce..2b7539701b42 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c @@ -63,10 +63,6 @@ enum { HDMI_REVISION_ID = 0x0001, HDMI_IH_AHBDMAAUD_STAT0 = 0x0109, HDMI_IH_MUTE_AHBDMAAUD_STAT0 = 0x0189, - HDMI_FC_AUDICONF2 = 0x1027, - HDMI_FC_AUDSCONF = 0x1063, - HDMI_FC_AUDSCONF_LAYOUT1 = 1 << 0, - HDMI_FC_AUDSCONF_LAYOUT0 = 0 << 0, HDMI_AHB_DMA_CONF0 = 0x3600, HDMI_AHB_DMA_START = 0x3601, HDMI_AHB_DMA_STOP = 0x3602, @@ -403,7 +399,7 @@ static int dw_hdmi_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_dw_hdmi *dw = substream->private_data; - u8 threshold, conf0, conf1, layout, ca; + u8 threshold, conf0, conf1, ca; /* Setup as per 3.0.5 FSL 4.1.0 BSP */ switch (dw->revision) { @@ -434,20 +430,12 @@ static int dw_hdmi_prepare(struct snd_pcm_substream *substream) conf1 = default_hdmi_channel_config[runtime->channels - 2].conf1; ca = default_hdmi_channel_config[runtime->channels - 2].ca; - /* - * For >2 channel PCM audio, we need to select layout 1 - * and set an appropriate channel map. - */ - if (runtime->channels > 2) - layout = HDMI_FC_AUDSCONF_LAYOUT1; - else - layout = HDMI_FC_AUDSCONF_LAYOUT0; - writeb_relaxed(threshold, dw->data.base + HDMI_AHB_DMA_THRSLD); writeb_relaxed(conf0, dw->data.base + HDMI_AHB_DMA_CONF0); writeb_relaxed(conf1, dw->data.base + HDMI_AHB_DMA_CONF1); - writeb_relaxed(layout, dw->data.base + HDMI_FC_AUDSCONF); - writeb_relaxed(ca, dw->data.base + HDMI_FC_AUDICONF2); + + dw_hdmi_set_channel_count(dw->data.hdmi, runtime->channels); + dw_hdmi_set_channel_allocation(dw->data.hdmi, ca); switch (runtime->format) { case SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE: diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 83b94b66e464..ae46b770943e 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -645,6 +645,38 @@ void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate) } EXPORT_SYMBOL_GPL(dw_hdmi_set_sample_rate); +void dw_hdmi_set_channel_count(struct dw_hdmi *hdmi, unsigned int cnt) +{ + u8 layout; + + mutex_lock(&hdmi->audio_mutex); + + /* + * For >2 channel PCM audio, we need to select layout 1 + * and set an appropriate channel map. + */ + if (cnt > 2) + layout = HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1; + else + layout = HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0; + + hdmi_modb(hdmi, layout, HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK, + HDMI_FC_AUDSCONF); + + mutex_unlock(&hdmi->audio_mutex); +} +EXPORT_SYMBOL_GPL(dw_hdmi_set_channel_count); + +void dw_hdmi_set_channel_allocation(struct dw_hdmi *hdmi, unsigned int ca) +{ + mutex_lock(&hdmi->audio_mutex); + + hdmi_writeb(hdmi, ca, HDMI_FC_AUDICONF2); + + mutex_unlock(&hdmi->audio_mutex); +} +EXPORT_SYMBOL_GPL(dw_hdmi_set_channel_allocation); + static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable) { if (enable) diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h index c402364aec0d..cf528c289857 100644 --- a/include/drm/bridge/dw_hdmi.h +++ b/include/drm/bridge/dw_hdmi.h @@ -155,6 +155,8 @@ void dw_hdmi_resume(struct dw_hdmi *hdmi); void dw_hdmi_setup_rx_sense(struct dw_hdmi *hdmi, bool hpd, bool rx_sense); void dw_hdmi_set_sample_rate(struct dw_hdmi *hdmi, unsigned int rate); +void dw_hdmi_set_channel_count(struct dw_hdmi *hdmi, unsigned int cnt); +void dw_hdmi_set_channel_allocation(struct dw_hdmi *hdmi, unsigned int ca); void dw_hdmi_audio_enable(struct dw_hdmi *hdmi); void dw_hdmi_audio_disable(struct dw_hdmi *hdmi); void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi); -- cgit v1.2.3 From da5f5bc92f49f5b3acf8b07d95fb7d8a8f098d25 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Aug 2019 14:07:21 +0200 Subject: drm/bridge: dw-hdmi: set channel count in the infoframes Set the number of channel in the infoframes Reviewed-by: Jonas Karlman Signed-off-by: Jerome Brunet Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20190812120726.1528-4-jbrunet@baylibre.com --- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index ae46b770943e..4e57b984b244 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -663,6 +663,10 @@ void dw_hdmi_set_channel_count(struct dw_hdmi *hdmi, unsigned int cnt) hdmi_modb(hdmi, layout, HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK, HDMI_FC_AUDSCONF); + /* Set the audio infoframes channel count */ + hdmi_modb(hdmi, (cnt - 1) << HDMI_FC_AUDICONF0_CC_OFFSET, + HDMI_FC_AUDICONF0_CC_MASK, HDMI_FC_AUDICONF0); + mutex_unlock(&hdmi->audio_mutex); } EXPORT_SYMBOL_GPL(dw_hdmi_set_channel_count); -- cgit v1.2.3 From 17a1e555b608a847c903e093718d0a768843c586 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Aug 2019 14:07:22 +0200 Subject: drm/bridge: dw-hdmi-i2s: enable lpcm multi channels Properly setup the channel count and layout in dw-hdmi i2s driver so we are not limited to 2 channels. Also correct the maximum channel reported by the DAI from 6 to 8 ch Reviewed-by: Jonas Karlman Signed-off-by: Jerome Brunet Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20190812120726.1528-5-jbrunet@baylibre.com --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index 2b624cff541d..caf8aed78fea 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c @@ -84,6 +84,7 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, } dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate); + dw_hdmi_set_channel_count(hdmi, hparms->channels); hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS); hdmi_write(audio, conf0, HDMI_AUD_CONF0); @@ -139,7 +140,7 @@ static int snd_dw_hdmi_probe(struct platform_device *pdev) pdata.ops = &dw_hdmi_i2s_ops; pdata.i2s = 1; - pdata.max_i2s_channels = 6; + pdata.max_i2s_channels = 8; pdata.data = audio; memset(&pdevinfo, 0, sizeof(pdevinfo)); -- cgit v1.2.3 From 0c6098859176ffa250b196498722dc7844e41048 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Aug 2019 14:07:23 +0200 Subject: drm/bridge: dw-hdmi-i2s: set the channel allocation setup the channel allocation provided by the generic hdmi-codec driver Reviewed-by: Jonas Karlman Signed-off-by: Jerome Brunet Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20190812120726.1528-6-jbrunet@baylibre.com --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index caf8aed78fea..0864dee8d180 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c @@ -85,6 +85,7 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, dw_hdmi_set_sample_rate(hdmi, hparms->sample_rate); dw_hdmi_set_channel_count(hdmi, hparms->channels); + dw_hdmi_set_channel_allocation(hdmi, hparms->cea.channel_allocation); hdmi_write(audio, inputclkfs, HDMI_AUD_INPUTCLKFS); hdmi_write(audio, conf0, HDMI_AUD_CONF0); -- cgit v1.2.3 From 46cecde310bba81243f906955f5fd6f64d5668f0 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Aug 2019 14:07:24 +0200 Subject: drm/bridge: dw-hdmi-i2s: reset audio fifo before applying new params When changing the audio hw params, reset the audio fifo to make sure any old remaining data is flushed. The databook mentions that such reset should be followed by a reset of the i2s block to make sure the samples stay aligned Reviewed-by: Jonas Karlman Signed-off-by: Jerome Brunet Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20190812120726.1528-7-jbrunet@baylibre.com --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 6 ++++-- drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index 0864dee8d180..41bee0099578 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c @@ -49,6 +49,10 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, return -EINVAL; } + /* Reset the FIFOs before applying new params */ + hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); + hdmi_write(audio, (u8)~HDMI_MC_SWRSTZ_I2SSWRST_REQ, HDMI_MC_SWRSTZ); + inputclkfs = HDMI_AUD_INPUTCLKFS_64FS; conf0 = HDMI_AUD_CONF0_I2S_ALL_ENABLE; @@ -102,8 +106,6 @@ static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data) struct dw_hdmi *hdmi = audio->hdmi; dw_hdmi_audio_disable(hdmi); - - hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0); } static int dw_hdmi_i2s_get_dai_id(struct snd_soc_component *component, diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h index 091d7c28aa17..a272fa393ae6 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h @@ -940,6 +940,7 @@ enum { HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1, /* MC_SWRSTZ field values */ + HDMI_MC_SWRSTZ_I2SSWRST_REQ = 0x08, HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02, /* MC_FLOWCTRL field values */ -- cgit v1.2.3 From 43e88f670a5e4618609822853a5f659631c32505 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Aug 2019 14:07:25 +0200 Subject: drm/bridge: dw-hdmi-i2s: enable only the required i2s lanes Enable the i2s lanes depending on the number of channel in the stream Reviewed-by: Jonas Karlman Signed-off-by: Jerome Brunet Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20190812120726.1528-8-jbrunet@baylibre.com --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 15 ++++++++++++++- drivers/gpu/drm/bridge/synopsys/dw-hdmi.h | 6 +++++- 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index 41bee0099578..b8ece9c1ba2c 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c @@ -54,7 +54,20 @@ static int dw_hdmi_i2s_hw_params(struct device *dev, void *data, hdmi_write(audio, (u8)~HDMI_MC_SWRSTZ_I2SSWRST_REQ, HDMI_MC_SWRSTZ); inputclkfs = HDMI_AUD_INPUTCLKFS_64FS; - conf0 = HDMI_AUD_CONF0_I2S_ALL_ENABLE; + conf0 = (HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_EN0); + + /* Enable the required i2s lanes */ + switch (hparms->channels) { + case 7 ... 8: + conf0 |= HDMI_AUD_CONF0_I2S_EN3; + /* Fall-thru */ + case 5 ... 6: + conf0 |= HDMI_AUD_CONF0_I2S_EN2; + /* Fall-thru */ + case 3 ... 4: + conf0 |= HDMI_AUD_CONF0_I2S_EN1; + /* Fall-thru */ + } switch (hparms->sample_width) { case 16: diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h index a272fa393ae6..6988f12d89d9 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.h @@ -865,7 +865,11 @@ enum { /* AUD_CONF0 field values */ HDMI_AUD_CONF0_SW_RESET = 0x80, - HDMI_AUD_CONF0_I2S_ALL_ENABLE = 0x2F, + HDMI_AUD_CONF0_I2S_SELECT = 0x20, + HDMI_AUD_CONF0_I2S_EN3 = 0x08, + HDMI_AUD_CONF0_I2S_EN2 = 0x04, + HDMI_AUD_CONF0_I2S_EN1 = 0x02, + HDMI_AUD_CONF0_I2S_EN0 = 0x01, /* AUD_CONF1 field values */ HDMI_AUD_CONF1_MODE_I2S = 0x00, -- cgit v1.2.3 From fc1ca6e01d0a71fd4bd7a5a7cb8309a9dd48ddbc Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Aug 2019 14:50:16 +0200 Subject: drm/bridge: dw-hdmi-i2s: add .get_eld support Provide the eld to the generic hdmi-codec driver. This will let the driver enforce the maximum channel number and set the channel allocation depending on the hdmi sink. Cc: Jonas Karlman Signed-off-by: Jerome Brunet Reviewed-by: Jonas Karlman Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20190812125016.20169-1-jbrunet@baylibre.com --- drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h | 1 + drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c | 11 +++++++++++ drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 1 + 3 files changed, 13 insertions(+) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h index 63b5756f463b..cb07dc0da5a7 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h @@ -14,6 +14,7 @@ struct dw_hdmi_audio_data { struct dw_hdmi_i2s_audio_data { struct dw_hdmi *hdmi; + u8 *eld; void (*write)(struct dw_hdmi *hdmi, u8 val, int offset); u8 (*read)(struct dw_hdmi *hdmi, int offset); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c index b8ece9c1ba2c..1d15cf9b6821 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c @@ -10,6 +10,7 @@ #include #include +#include #include @@ -121,6 +122,15 @@ static void dw_hdmi_i2s_audio_shutdown(struct device *dev, void *data) dw_hdmi_audio_disable(hdmi); } +static int dw_hdmi_i2s_get_eld(struct device *dev, void *data, uint8_t *buf, + size_t len) +{ + struct dw_hdmi_i2s_audio_data *audio = data; + + memcpy(buf, audio->eld, min_t(size_t, MAX_ELD_BYTES, len)); + return 0; +} + static int dw_hdmi_i2s_get_dai_id(struct snd_soc_component *component, struct device_node *endpoint) { @@ -144,6 +154,7 @@ static int dw_hdmi_i2s_get_dai_id(struct snd_soc_component *component, static struct hdmi_codec_ops dw_hdmi_i2s_ops = { .hw_params = dw_hdmi_i2s_hw_params, .audio_shutdown = dw_hdmi_i2s_audio_shutdown, + .get_eld = dw_hdmi_i2s_get_eld, .get_dai_id = dw_hdmi_i2s_get_dai_id, }; diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 4e57b984b244..4044071090c4 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2799,6 +2799,7 @@ __dw_hdmi_probe(struct platform_device *pdev, struct dw_hdmi_i2s_audio_data audio; audio.hdmi = hdmi; + audio.eld = hdmi->connector.eld; audio.write = hdmi_writeb; audio.read = hdmi_readb; hdmi->enable_audio = dw_hdmi_i2s_audio_enable; -- cgit v1.2.3 From 5ad773f9a92f6a0b8d7433921e89b9beb567e5d0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 13 Aug 2019 11:30:46 +0200 Subject: drm/bridge: dumb-vga-dac: Fix dereferencing -ENODEV DDC channel If the VGA connector has no DDC channel, an error pointer will be dereferenced, e.g. on Salvator-XS: Unable to handle kernel NULL pointer dereference at virtual address 000000000000017d ... Call trace: sysfs_do_create_link_sd.isra.0+0x40/0x108 sysfs_create_link+0x20/0x40 drm_sysfs_connector_add+0xa8/0xc8 drm_connector_register.part.3+0x54/0xb0 drm_connector_register_all+0xb0/0xd0 drm_modeset_register_all+0x54/0x88 drm_dev_register+0x18c/0x1d8 rcar_du_probe+0xe4/0x150 ... This happens because vga->ddc either contains a valid DDC channel pointer, or -ENODEV, and drm_connector_init_with_ddc() expects a valid DDC channel pointer, or NULL. Fix this by resetting vga->ddc to NULL in case of -ENODEV, and replacing the existing error checks by non-NULL checks. This is similar to what the HDMI connector driver does. Fixes: a4f9087e85de141e ("drm/bridge: dumb-vga-dac: Provide ddc symlink in connector sysfs directory") Signed-off-by: Geert Uytterhoeven Reviewed-by: Neil Armstrong Tested-by: Guenter Roeck Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20190813093046.4976-1-geert+renesas@glider.be --- drivers/gpu/drm/bridge/dumb-vga-dac.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c index 8ef6539ae78a..7aa789c35882 100644 --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c @@ -42,7 +42,7 @@ static int dumb_vga_get_modes(struct drm_connector *connector) struct edid *edid; int ret; - if (IS_ERR(vga->ddc)) + if (!vga->ddc) goto fallback; edid = drm_get_edid(connector, vga->ddc); @@ -84,7 +84,7 @@ dumb_vga_connector_detect(struct drm_connector *connector, bool force) * wire the DDC pins, or the I2C bus might not be working at * all. */ - if (!IS_ERR(vga->ddc) && drm_probe_ddc(vga->ddc)) + if (vga->ddc && drm_probe_ddc(vga->ddc)) return connector_status_connected; return connector_status_unknown; @@ -197,6 +197,7 @@ static int dumb_vga_probe(struct platform_device *pdev) if (PTR_ERR(vga->ddc) == -ENODEV) { dev_dbg(&pdev->dev, "No i2c bus specified. Disabling EDID readout\n"); + vga->ddc = NULL; } else { dev_err(&pdev->dev, "Couldn't retrieve i2c bus\n"); return PTR_ERR(vga->ddc); @@ -218,7 +219,7 @@ static int dumb_vga_remove(struct platform_device *pdev) drm_bridge_remove(&vga->bridge); - if (!IS_ERR(vga->ddc)) + if (vga->ddc) i2c_put_adapter(vga->ddc); return 0; -- cgit v1.2.3 From 5c8a5f1d78d84faff0e5578abb4b53adab8aaa59 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 4 Aug 2019 11:41:29 +0200 Subject: drm/i2c/tda998x: drop use of drmP.h Drop use of the deprecated drmP.h header file. Fix fallout. Signed-off-by: Sam Ravnborg Reviewed-by: Thierry Reding Cc: Russell King Cc: David Airlie Cc: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20190804094132.29463-2-sam@ravnborg.org --- drivers/gpu/drm/i2c/tda998x_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c index 61e042918a7f..84c6d4c91c65 100644 --- a/drivers/gpu/drm/i2c/tda998x_drv.c +++ b/drivers/gpu/drm/i2c/tda998x_drv.c @@ -13,10 +13,10 @@ #include #include -#include #include #include #include +#include #include #include -- cgit v1.2.3 From eb1df694cd7271632763bb99f7fb3891357461d8 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Sun, 4 Aug 2019 11:41:30 +0200 Subject: drm/tegra: drop use of drmP.h Drop use of the deprecated drmP.h header file. For all touched files divide include files into blocks, and sort them within the blocks. Fix fallout. Signed-off-by: Sam Ravnborg Reviewed-by: Thierry Reding Cc: Thierry Reding Cc: Jonathan Hunter Cc: linux-tegra@vger.kernel.org Link: https://patchwork.freedesktop.org/patch/msgid/20190804094132.29463-3-sam@ravnborg.org --- drivers/gpu/drm/tegra/dc.c | 13 +++++++++---- drivers/gpu/drm/tegra/dpaux.c | 5 +++-- drivers/gpu/drm/tegra/drm.c | 8 ++++++++ drivers/gpu/drm/tegra/drm.h | 3 +-- drivers/gpu/drm/tegra/dsi.c | 8 +++++--- drivers/gpu/drm/tegra/fb.c | 6 ++++-- drivers/gpu/drm/tegra/gem.c | 3 +++ drivers/gpu/drm/tegra/gem.h | 1 - drivers/gpu/drm/tegra/gr2d.c | 1 + drivers/gpu/drm/tegra/hdmi.c | 5 +++++ drivers/gpu/drm/tegra/hub.c | 3 ++- drivers/gpu/drm/tegra/hub.h | 1 - drivers/gpu/drm/tegra/plane.c | 1 + drivers/gpu/drm/tegra/sor.c | 3 +++ drivers/gpu/drm/tegra/vic.c | 1 + 15 files changed, 46 insertions(+), 16 deletions(-) (limited to 'drivers/gpu') diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 4a75d149e368..fbf57bc3cdab 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -6,23 +6,28 @@ #include #include +#include #include +#include #include #include #include #include +#include +#include +#include +#include +#include +#include + #include "dc.h" #include "drm.h" #include "gem.h" #include "hub.h" #include "plane.h" -#include -#include -#include - static void tegra_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state); diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c index 2d94da225e51..a0f6f9b0d258 100644 --- a/drivers/gpu/drm/tegra/dpaux.c +++ b/drivers/gpu/drm/tegra/dpaux.c @@ -8,14 +8,15 @@ #include #include #include +#include #include #include #include #include -#include #include -#include +#include #include +#include #include #include diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 870904bfad78..6fb7d74ff553 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -8,9 +8,17 @@ #include #include #include +#include +#include #include #include +#include +#include +#include +#include +#include +#include #if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) #include diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 86daa19fcf24..29911eff9ceb 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -7,18 +7,17 @@ #ifndef HOST1X_DRM_H #define HOST1X_DRM_H 1 -#include #include #include #include -#include #include #include #include #include #include #include +#include #include "gem.h" #include "hub.h" diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c index 2fbfefe9cb42..a5d47e301c5f 100644 --- a/drivers/gpu/drm/tegra/dsi.c +++ b/drivers/gpu/drm/tegra/dsi.c @@ -5,22 +5,24 @@ #include #include +#include #include #include #include #include #include #include +#include #include -#include +#include