diff options
Diffstat (limited to 'drivers/gpu/drm')
26 files changed, 222 insertions, 203 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c index e55508b39496..3e6823fdd939 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c @@ -238,44 +238,40 @@ static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node, * amdgpu_mn_invalidate_range_start_gfx - callback to notify about mm change * * @mn: our notifier - * @mm: the mm this callback is about - * @start: start of updated range - * @end: end of updated range + * @range: mmu notifier context * * Block for operations on BOs to finish and mark pages as accessed and * potentially dirty. */ static int amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn, - struct mm_struct *mm, - unsigned long start, - unsigned long end, - bool blockable) + const struct mmu_notifier_range *range) { struct amdgpu_mn *amn = container_of(mn, struct amdgpu_mn, mn); struct interval_tree_node *it; + unsigned long end; /* notification is exclusive, but interval is inclusive */ - end -= 1; + end = range->end - 1; /* TODO we should be able to split locking for interval tree and * amdgpu_mn_invalidate_node */ - if (amdgpu_mn_read_lock(amn, blockable)) + if (amdgpu_mn_read_lock(amn, range->blockable)) return -EAGAIN; - it = interval_tree_iter_first(&amn->objects, start, end); + it = interval_tree_iter_first(&amn->objects, range->start, end); while (it) { struct amdgpu_mn_node *node; - if (!blockable) { + if (!range->blockable) { amdgpu_mn_read_unlock(amn); return -EAGAIN; } node = container_of(it, struct amdgpu_mn_node, it); - it = interval_tree_iter_next(it, start, end); + it = interval_tree_iter_next(it, range->start, end); - amdgpu_mn_invalidate_node(node, start, end); + amdgpu_mn_invalidate_node(node, range->start, end); } return 0; @@ -294,39 +290,38 @@ static int amdgpu_mn_invalidate_range_start_gfx(struct mmu_notifier *mn, * are restorted in amdgpu_mn_invalidate_range_end_hsa. */ static int amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn, - struct mm_struct *mm, - unsigned long start, - unsigned long end, - bool blockable) + const struct mmu_notifier_range *range) { struct amdgpu_mn *amn = container_of(mn, struct amdgpu_mn, mn); struct interval_tree_node *it; + unsigned long end; /* notification is exclusive, but interval is inclusive */ - end -= 1; + end = range->end - 1; - if (amdgpu_mn_read_lock(amn, blockable)) + if (amdgpu_mn_read_lock(amn, range->blockable)) return -EAGAIN; - it = interval_tree_iter_first(&amn->objects, start, end); + it = interval_tree_iter_first(&amn->objects, range->start, end); while (it) { struct amdgpu_mn_node *node; struct amdgpu_bo *bo; - if (!blockable) { + if (!range->blockable) { amdgpu_mn_read_unlock(amn); return -EAGAIN; } node = container_of(it, struct amdgpu_mn_node, it); - it = interval_tree_iter_next(it, start, end); + it = interval_tree_iter_next(it, range->start, end); list_for_each_entry(bo, &node->bos, mn_list) { struct kgd_mem *mem = bo->kfd_bo; if (amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, - start, end)) - amdgpu_amdkfd_evict_userptr(mem, mm); + range->start, + end)) + amdgpu_amdkfd_evict_userptr(mem, range->mm); } } @@ -344,9 +339,7 @@ static int amdgpu_mn_invalidate_range_start_hsa(struct mmu_notifier *mn, * Release the lock again to allow new command submissions. */ static void amdgpu_mn_invalidate_range_end(struct mmu_notifier *mn, - struct mm_struct *mm, - unsigned long start, - unsigned long end) + const struct mmu_notifier_range *range) { struct amdgpu_mn *amn = container_of(mn, struct amdgpu_mn, mn); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 3623538baf6f..be68752c3469 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -158,8 +158,7 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, } if ((args->ring_base_address) && - (!access_ok(VERIFY_WRITE, - (const void __user *) args->ring_base_address, + (!access_ok((const void __user *) args->ring_base_address, sizeof(uint64_t)))) { pr_err("Can't access ring base address\n"); return -EFAULT; @@ -170,31 +169,27 @@ static int set_queue_properties_from_user(struct queue_properties *q_properties, return -EINVAL; } - if (!access_ok(VERIFY_WRITE, - (const void __user *) args->read_pointer_address, + if (!access_ok((const void __user *) args->read_pointer_address, sizeof(uint32_t))) { pr_err("Can't access read pointer\n"); return -EFAULT; } - if (!access_ok(VERIFY_WRITE, - (const void __user *) args->write_pointer_address, + if (!access_ok((const void __user *) args->write_pointer_address, sizeof(uint32_t))) { pr_err("Can't access write pointer\n"); return -EFAULT; } if (args->eop_buffer_address && - !access_ok(VERIFY_WRITE, - (const void __user *) args->eop_buffer_address, + !access_ok((const void __user *) args->eop_buffer_address, sizeof(uint32_t))) { pr_debug("Can't access eop buffer"); return -EFAULT; } if (args->ctx_save_restore_address && - !access_ok(VERIFY_WRITE, - (const void __user *) args->ctx_save_restore_address, + !access_ok((const void __user *) args->ctx_save_restore_address, sizeof(uint32_t))) { pr_debug("Can't access ctx save restore buffer"); return -EFAULT; @@ -365,8 +360,7 @@ static int kfd_ioctl_update_queue(struct file *filp, struct kfd_process *p, } if ((args->ring_base_address) && - (!access_ok(VERIFY_WRITE, - (const void __user *) args->ring_base_address, + (!access_ok((const void __user *) args->ring_base_address, sizeof(uint64_t)))) { pr_err("Can't access ring base address\n"); return -EFAULT; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c index c02adbbeef2a..b7bc7d7d048f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c @@ -853,7 +853,7 @@ static int kfd_fill_mem_info_for_cpu(int numa_node_id, int *avail_size, */ pgdat = NODE_DATA(numa_node_id); for (zone_type = 0; zone_type < MAX_NR_ZONES; zone_type++) - mem_in_bytes += pgdat->node_zones[zone_type].managed_pages; + mem_in_bytes += zone_managed_pages(&pgdat->node_zones[zone_type]); mem_in_bytes <<= PAGE_SHIFT; sub_type_hdr->length_low = lower_32_bits(mem_in_bytes); diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 892c1d9304bb..642d0e70d0f8 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -334,7 +334,7 @@ int armada_gem_pwrite_ioctl(struct drm_device *dev, void *data, ptr = (char __user *)(uintptr_t)args->ptr; - if (!access_ok(VERIFY_READ, ptr, args->size)) + if (!access_ok(ptr, args->size)) return -EFAULT; ret = fault_in_pages_readable(ptr, args->size); diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index ffa8dc35515f..46f48f245eb5 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -525,7 +525,7 @@ ssize_t drm_read(struct file *filp, char __user *buffer, struct drm_device *dev = file_priv->minor->dev; ssize_t ret; - if (!access_ok(VERIFY_WRITE, buffer, count)) + if (!access_ok(buffer, count)) return -EFAULT; ret = mutex_lock_interruptible(&file_priv->event_read_lock); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c index 7fea74861a87..160ce3c060a5 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c @@ -439,6 +439,4 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state, if (drm_debug & DRM_UT_DRIVER) etnaviv_buffer_dump(gpu, buffer, 0, 0x50); - - gpu->lastctx = cmdbuf->ctx; } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 52802e6049e0..18c27f795cf6 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -72,14 +72,8 @@ static void etnaviv_postclose(struct drm_device *dev, struct drm_file *file) for (i = 0; i < ETNA_MAX_PIPES; i++) { struct etnaviv_gpu *gpu = priv->gpu[i]; - if (gpu) { - mutex_lock(&gpu->lock); - if (gpu->lastctx == ctx) - gpu->lastctx = NULL; - mutex_unlock(&gpu->lock); - + if (gpu) drm_sched_entity_destroy(&ctx->sched_entity[i]); - } } kfree(ctx); @@ -345,7 +339,6 @@ static int etnaviv_ioctl_gem_userptr(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_etnaviv_gem_userptr *args = data; - int access; if (args->flags & ~(ETNA_USERPTR_READ|ETNA_USERPTR_WRITE) || args->flags == 0) @@ -357,12 +350,7 @@ static int etnaviv_ioctl_gem_userptr(struct drm_device *dev, void *data, args->user_ptr & ~PAGE_MASK) return -EINVAL; - if (args->flags & ETNA_USERPTR_WRITE) - access = VERIFY_WRITE; - else - access = VERIFY_READ; - - if (!access_ok(access, (void __user *)(unsigned long)args->user_ptr, + if (!access_ok((void __user *)(unsigned long)args->user_ptr, args->user_size)) return -EFAULT; @@ -523,7 +511,7 @@ static int etnaviv_bind(struct device *dev) if (!priv) { dev_err(dev, "failed to allocate private data\n"); ret = -ENOMEM; - goto out_unref; + goto out_put; } drm->dev_private = priv; @@ -549,7 +537,7 @@ out_register: component_unbind_all(dev, drm); out_bind: kfree(priv); -out_unref: +out_put: drm_dev_put(drm); return ret; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h index 8d02d1b7dcf5..4bf698de5996 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h @@ -107,17 +107,6 @@ static inline size_t size_vstruct(size_t nelem, size_t elem_size, size_t base) return base + nelem * elem_size; } -/* returns true if fence a comes after fence b */ -static inline bool fence_after(u32 a, u32 b) -{ - return (s32)(a - b) > 0; -} - -static inline bool fence_after_eq(u32 a, u32 b) -{ - return (s32)(a - b) >= 0; -} - /* * Etnaviv timeouts are specified wrt CLOCK_MONOTONIC, not jiffies. * We need to calculate the timeout in terms of number of jiffies diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index f225fbc6edd2..6904535475de 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -3,10 +3,12 @@ * Copyright (C) 2015-2018 Etnaviv Project */ +#include <linux/clk.h> #include <linux/component.h> #include <linux/dma-fence.h> #include <linux/moduleparam.h> #include <linux/of_device.h> +#include <linux/regulator/consumer.h> #include <linux/thermal.h> #include "etnaviv_cmdbuf.h" @@ -976,7 +978,6 @@ int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m) void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu) { - unsigned long flags; unsigned int i = 0; dev_err(gpu->dev, "recover hung GPU!\n"); @@ -989,15 +990,13 @@ void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu) etnaviv_hw_reset(gpu); /* complete all events, the GPU won't do it after the reset */ - spin_lock_irqsave(&gpu->event_spinlock, flags); + spin_lock(&gpu->event_spinlock); for_each_set_bit_from(i, gpu->event_bitmap, ETNA_NR_EVENTS) complete(&gpu->event_free); bitmap_zero(gpu->event_bitmap, ETNA_NR_EVENTS); - spin_unlock_irqrestore(&gpu->event_spinlock, flags); - gpu->completed_fence = gpu->active_fence; + spin_unlock(&gpu->event_spinlock); etnaviv_gpu_hw_init(gpu); - gpu->lastctx = NULL; gpu->exec_state = -1; mutex_unlock(&gpu->lock); @@ -1032,7 +1031,7 @@ static bool etnaviv_fence_signaled(struct dma_fence *fence) { struct etnaviv_fence *f = to_etnaviv_fence(fence); - return fence_completed(f->gpu, f->base.seqno); + return (s32)(f->gpu->completed_fence - f->base.seqno) >= 0; } static void etnaviv_fence_release(struct dma_fence *fence) @@ -1071,6 +1070,12 @@ static struct dma_fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu) return &f->base; } +/* returns true if fence a comes after fence b */ +static inline bool fence_after(u32 a, u32 b) +{ + return (s32)(a - b) > 0; +} + /* * event management: */ @@ -1078,7 +1083,7 @@ static struct dma_fence *etnaviv_gpu_fence_alloc(struct etnaviv_gpu *gpu) static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events, unsigned int *events) { - unsigned long flags, timeout = msecs_to_jiffies(10 * 10000); + unsigned long timeout = msecs_to_jiffies(10 * 10000); unsigned i, acquired = 0; for (i = 0; i < nr_events; i++) { @@ -1095,7 +1100,7 @@ static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events, timeout = ret; } - spin_lock_irqsave(&gpu->event_spinlock, flags); + spin_lock(&gpu->event_spinlock); for (i = 0; i < nr_events; i++) { int event = find_first_zero_bit(gpu->event_bitmap, ETNA_NR_EVENTS); @@ -1105,7 +1110,7 @@ static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events, set_bit(event, gpu->event_bitmap); } - spin_unlock_irqrestore(&gpu->event_spinlock, flags); + spin_unlock(&gpu->event_spinlock); return 0; @@ -1118,18 +1123,11 @@ out: static void event_free(struct etnaviv_gpu *gpu, unsigned int event) { - unsigned long flags; - - spin_lock_irqsave(&gpu->event_spinlock, flags); - if (!test_bit(event, gpu->event_bitmap)) { dev_warn(gpu->dev, "event %u is already marked as free", event); - spin_unlock_irqrestore(&gpu->event_spinlock, flags); } else { clear_bit(event, gpu->event_bitmap); - spin_unlock_irqrestore(&gpu->event_spinlock, flags); - complete(&gpu->event_free); } } @@ -1306,8 +1304,6 @@ struct dma_fence *etnaviv_gpu_submit(struct etnaviv_gem_submit *submit) goto out_unlock; } - gpu->active_fence = gpu_fence->seqno; - if (submit->nr_pmrs) { gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre; kref_get(&submit->refcount); @@ -1549,7 +1545,6 @@ static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu) etnaviv_gpu_update_clock(gpu); etnaviv_gpu_hw_init(gpu); - gpu->lastctx = NULL; gpu->exec_state = -1; mutex_unlock(&gpu->lock); @@ -1806,8 +1801,8 @@ static int etnaviv_gpu_rpm_suspend(struct device *dev) struct etnaviv_gpu *gpu = dev_get_drvdata(dev); u32 idle, mask; - /* If we have outstanding fences, we're not idle */ - if (gpu->completed_fence != gpu->active_fence) + /* If there are any jobs in the HW queue, we're not idle */ + if (atomic_read(&gpu->sched.hw_rq_count)) return -EBUSY; /* Check whether the hardware (except FE) is idle */ diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index 9a75a6937268..9bcf151f706b 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -6,9 +6,6 @@ #ifndef __ETNAVIV_GPU_H__ #define __ETNAVIV_GPU_H__ -#include <linux/clk.h> -#include <linux/regulator/consumer.h> - #include "etnaviv_cmdbuf.h" #include "etnaviv_drv.h" @@ -88,6 +85,8 @@ struct etnaviv_event { struct etnaviv_cmdbuf_suballoc; struct etnaviv_cmdbuf; +struct regulator; +struct clk; #define ETNA_NR_EVENTS 30 @@ -98,7 +97,6 @@ struct etnaviv_gpu { struct mutex lock; struct etnaviv_chip_identity identity; enum etnaviv_sec_mode sec_mode; - struct etnaviv_file_private *lastctx; struct workqueue_struct *wq; struct drm_gpu_scheduler sched; @@ -121,7 +119,6 @@ struct etnaviv_gpu { struct mutex fence_lock; struct idr fence_idr; u32 next_fence; - u32 active_fence; u32 completed_fence; wait_queue_head_t fence_event; u64 fence_context; @@ -161,11 +158,6 @@ static inline u32 gpu_read(struct etnaviv_gpu *gpu, u32 reg) return readl(gpu->mmio + reg); } -static inline bool fence_completed(struct etnaviv_gpu *gpu, u32 fence) -{ - return fence_after_eq(gpu->completed_fence, fence); -} - int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value); int etnaviv_gpu_init(struct etnaviv_gpu *gpu); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index e3d6a8584715..786a8ee6f10f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -228,6 +228,21 @@ static const uint32_t fimd_formats[] = { DRM_FORMAT_ARGB8888, }; +static const unsigned int capabilities[WINDOWS_NR] = { + 0, + EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND, + EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND, + EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND, + EXYNOS_DRM_PLANE_CAP_WIN_BLEND | EXYNOS_DRM_PLANE_CAP_PIX_BLEND, +}; + +static inline void fimd_set_bits(struct fimd_context *ctx, u32 reg, u32 mask, + u32 val) +{ + val = (val & mask) | (readl(ctx->regs + reg) & ~mask); + writel(val, ctx->regs + reg); +} + static int fimd_enable_vblank(struct exynos_drm_crtc *crtc) { struct fimd_context *ctx = crtc->ctx; @@ -551,13 +566,88 @@ static void fimd_commit(struct exynos_drm_crtc *crtc) writel(val, ctx->regs + VIDCON0); } +static void fimd_win_set_bldeq(struct fimd_context *ctx, unsigned int win, + unsigned int alpha, unsigned int pixel_alpha) +{ + u32 mask = BLENDEQ_A_FUNC_F(0xf) | BLENDEQ_B_FUNC_F(0xf); + u32 val = 0; + + switch (pixel_alpha) { + case DRM_MODE_BLEND_PIXEL_NONE: + case DRM_MODE_BLEND_COVERAGE: + val |= BLENDEQ_A_FUNC_F(BLENDEQ_ALPHA_A); + val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A); + break; + case DRM_MODE_BLEND_PREMULTI: + default: + if (alpha != DRM_BLEND_ALPHA_OPAQUE) { + val |= BLENDEQ_A_FUNC_F(BLENDEQ_ALPHA0); + val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A); + } else { + val |= BLENDEQ_A_FUNC_F(BLENDEQ_ONE); + val |= BLENDEQ_B_FUNC_F(BLENDEQ_ONE_MINUS_ALPHA_A); + } + break; + } + fimd_set_bits(ctx, BLENDEQx(win), mask, val); +} -static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win, - uint32_t pixel_format, int width) +static void fimd_win_set_bldmod(struct fimd_context *ctx, unsigned int win, + unsigned int alpha, unsigned int pixel_alpha) { - unsigned long val; + u32 win_alpha_l = (alpha >> 8) & 0xf; + u32 win_alpha_h = alpha >> 12; + u32 val = 0; - val = WINCONx_ENWIN; + switch (pixel_alpha) { + case DRM_MODE_BLEND_PIXEL_NONE: + break; + case DRM_MODE_BLEND_COVERAGE: + case DRM_MODE_BLEND_PREMULTI: + default: + val |= WINCON1_ALPHA_SEL; + val |= WINCON1_BLD_PIX; + val |= WINCON1_ALPHA_MUL; + break; + } + fimd_set_bits(ctx, WINCON(win), WINCONx_BLEND_MODE_MASK, val); + + /* OSD alpha */ + val = VIDISD14C_ALPHA0_R(win_alpha_h) | + VIDISD14C_ALPHA0_G(win_alpha_h) | + VIDISD14C_ALPHA0_B(win_alpha_h) | + VIDISD14C_ALPHA1_R(0x0) | + VIDISD14C_ALPHA1_G(0x0) | + VIDISD14C_ALPHA1_B(0x0); + writel(val, ctx->regs + VIDOSD_C(win)); + + val = VIDW_ALPHA_R(win_alpha_l) | VIDW_ALPHA_G(win_alpha_l) | + VIDW_ALPHA_B(win_alpha_l); + writel(val, ctx->regs + VIDWnALPHA0(win)); + + val = VIDW_ALPHA_R(0x0) | VIDW_ALPHA_G(0x0) | + VIDW_ALPHA_B(0x0); + writel(val, ctx->regs + VIDWnALPHA1(win)); + + fimd_set_bits(ctx, BLENDCON, BLENDCON_NEW_MASK, + BLENDCON_NEW_8BIT_ALPHA_VALUE); +} + +static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win, + struct drm_framebuffer *fb, int width) +{ + struct exynos_drm_plane plane = ctx->planes[win]; + struct exynos_drm_plane_state *state = + to_exynos_plane_state(plane.base.state); + uint32_t pixel_format = fb->format->format; + unsigned int alpha = state->base.alpha; + u32 val = WINCONx_ENWIN; + unsigned int pixel_alpha; + + if (fb->format->has_alpha) + pixel_alpha = state->base.pixel_blend_mode; + else + pixel_alpha = DRM_MODE_BLEND_PIXEL_NONE; /* * In case of s3c64xx, window 0 doesn't support alpha channel. @@ -591,8 +681,7 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win, break; case DRM_FORMAT_ARGB8888: default: - val |= WINCON1_BPPMODE_25BPP_A1888 - | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; + val |= WINCON1_BPPMODE_25BPP_A1888; val |= WINCONx_WSWP; val |= WINCONx_BURSTLEN_16WORD; break; @@ -610,25 +699,12 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win, val &= ~WINCONx_BURSTLEN_MASK; val |= WINCONx_BURSTLEN_4WORD; } - - writel(val, ctx->regs + WINCON(win)); + fimd_set_bits(ctx, WINCON(win), ~WINCONx_BLEND_MODE_MASK, val); /* hardware window 0 doesn't support alpha channel. */ if (win != 0) { - /* OSD alpha */ - val = VIDISD14C_ALPHA0_R(0xf) | - VIDISD14C_ALPHA0_G(0xf) | - VIDISD14C_ALPHA0_B(0xf) | - VIDISD14C_ALPHA1_R(0xf) | - VIDISD14C_ALPHA1_G(0xf) | - VIDISD14C_ALPHA1_B(0xf); - - writel(val, ctx->regs + VIDOSD_C(win)); - - val = VIDW_ALPHA_R(0xf) | VIDW_ALPHA_G(0xf) | - VIDW_ALPHA_G(0xf); - writel(val, ctx->regs + VIDWnALPHA0(win)); - writel(val, ctx->regs + VIDWnALPHA1(win)); + fimd_win_set_bldmod(ctx, win, alpha, pixel_alpha); + fimd_win_set_bldeq(ctx, win, alpha, pixel_alpha); } } @@ -785,7 +861,7 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, DRM_DEBUG_KMS("osd size = 0x%x\n", (unsigned int)val); } - fimd_win_set_pixfmt(ctx, win, fb->format->format, state->src.w); + fimd_win_set_pixfmt(ctx, win, fb, state->src.w); /* hardware window 0 doesn't support color key. */ if (win != 0) @@ -987,6 +1063,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats); ctx->configs[i].zpos = i; ctx->configs[i].type = fimd_win_types[i]; + ctx->configs[i].capabilities = capabilities[i]; ret = exynos_plane_init(drm_dev, &ctx->planes[i], i, &ctx->configs[i]); if (ret) diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 33a458b7f1fc..148be8e1a090 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -131,5 +131,5 @@ config DRM_I915_GVT_KVMGT menu "drm/i915 Debugging" depends on DRM_I915 depends on EXPERT -source drivers/gpu/drm/i915/Kconfig.debug +source "drivers/gpu/drm/i915/Kconfig.debug" endmenu diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d36a9755ad91..216f52b744a6 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1282,8 +1282,7 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data, if (args->size == 0) return 0; - if (!access_ok(VERIFY_WRITE, - u64_to_user_ptr(args->data_ptr), + if (!access_ok(u64_to_user_ptr(args->data_ptr), args->size)) return -EFAULT; @@ -1609,9 +1608,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, if (args->size == 0) return 0; - if (!access_ok(VERIFY_READ, - u64_to_user_ptr(args->data_ptr), - args->size)) + if (!access_ok(u64_to_user_ptr(args->data_ptr), args->size)) return -EFAULT; obj = i915_gem_object_lookup(file, args->handle); @@ -2559,7 +2556,7 @@ static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) * If there's no chance of allocating enough pages for the whole * object, bail early. */ - if (page_count > totalram_pages) + if (page_count > totalram_pages()) return -ENOMEM; st = kmalloc(sizeof(*st), GFP_KERNEL); diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 786d719e652d..485b259127c3 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -26,7 +26,7 @@ * */ -#include <linux/dma_remapping.h> +#include <linux/intel-iommu.h> #include <linux/reservation.h> #include <linux/sync_file.h> #include <linux/uaccess.h> @@ -1447,7 +1447,7 @@ static int eb_relocate_vma(struct i915_execbuffer *eb, struct i915_vma *vma) * to read. However, if the array is not writable the user loses * the updated relocation values. */ - if (unlikely(!access_ok(VERIFY_READ, urelocs, remain*sizeof(*urelocs)))) + if (unlikely(!access_ok(urelocs, remain*sizeof(*urelocs)))) return -EFAULT; do { @@ -1554,7 +1554,7 @@ static int check_relocations(const struct drm_i915_gem_exec_object2 *entry) addr = u64_to_user_ptr(entry->relocs_ptr); size *= sizeof(struct drm_i915_gem_relocation_entry); - if (!access_ok(VERIFY_READ, addr, size)) + if (!access_ok(addr, size)) return -EFAULT; end = addr + size; @@ -1605,6 +1605,7 @@ static int eb_copy_relocations(const struct i915_execbuffer *eb) (char __user *)urelocs + copied, len)) { end_user: + user_access_end(); kvfree(relocs); err = -EFAULT; goto err; @@ -1623,7 +1624,9 @@ end_user: * happened we would make the mistake of assuming that the * relocations were valid. */ - user_access_begin(); + if (!user_access_begin(urelocs, size)) + goto end_user; + for (copied = 0; copied < nreloc; copied++) unsafe_put_user(-1, &urelocs[copied].presumed_offset, @@ -2090,7 +2093,7 @@ get_fence_array(struct drm_i915_gem_execbuffer2 *args, return ERR_PTR(-EINVAL); user = u64_to_user_ptr(args->cliprects_ptr); - if (!access_ok(VERIFY_READ, user, nfences * sizeof(*user))) + if (!access_ok(user, nfences * sizeof(*user))) return ERR_PTR(-EFAULT); fences = kvmalloc_array(nfences, sizeof(*fences), @@ -2605,7 +2608,16 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, unsigned int i; /* Copy the new buffer offsets back to the user's exec list. */ - user_access_begin(); + /* + * Note: count * sizeof(*user_exec_list) does not overflow, + * because we checked 'count' in check_buffer_count(). + * + * And this range already got effectively checked earlier + * when we did the "copy_from_user()" above. + */ + if (!user_access_begin(user_exec_list, count * sizeof(*user_exec_list))) + goto end_user; + for (i = 0; i < args->buffer_count; i++) { if (!(exec2_list[i].offset & UPDATE)) continue; diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 2c9b284036d1..9558582c105e 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -113,27 +113,25 @@ static void del_object(struct i915_mmu_object *mo) } static int i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn, - struct mm_struct *mm, - unsigned long start, - unsigned long end, - bool blockable) + const struct mmu_notifier_range *range) { struct i915_mmu_notifier *mn = container_of(_mn, struct i915_mmu_notifier, mn); struct i915_mmu_object *mo; struct interval_tree_node *it; LIST_HEAD(cancelled); + unsigned long end; if (RB_EMPTY_ROOT(&mn->objects.rb_root)) return 0; /* interval ranges are inclusive, but invalidate range is exclusive */ - end--; + end = range->end - 1; spin_lock(&mn->lock); - it = interval_tree_iter_first(&mn->objects, start, end); + it = interval_tree_iter_first(&mn->objects, range->start, end); while (it) { - if (!blockable) { + if (!range->blockable) { spin_unlock(&mn->lock); return -EAGAIN; } @@ -151,7 +149,7 @@ static int i915_gem_userptr_mn_invalidate_range_start(struct mmu_notifier *_mn, queue_work(mn->wq, &mo->work); list_add(&mo->link, &cancelled); - it = interval_tree_iter_next(it, start, end); + it = interval_tree_iter_next(it, range->start, end); } list_for_each_entry(mo, &cancelled, link) del_object(mo); @@ -791,8 +789,7 @@ i915_gem_userptr_ioctl(struct drm_device *dev, if (offset_in_page(args->user_ptr | args->user_size)) return -EINVAL; - if (!access_ok(args->flags & I915_USERPTR_READ_ONLY ? VERIFY_READ : VERIFY_WRITE, - (char __user *)(unsigned long)args->user_ptr, args->user_size)) + if (!access_ok((char __user *)(unsigned long)args->user_ptr, args->user_size)) return -EFAULT; if (args->flags & I915_USERPTR_READ_ONLY) { diff --git a/drivers/gpu/drm/i915/i915_ioc32.c b/drivers/gpu/drm/i915/i915_ioc32.c index 0e5c580d117c..e869daf9c8a9 100644 --- a/drivers/gpu/drm/i915/i915_ioc32.c +++ b/drivers/gpu/drm/i915/i915_ioc32.c @@ -52,7 +52,7 @@ static int compat_i915_getparam(struct file *file, unsigned int cmd, return -EFAULT; request = compat_alloc_user_space(sizeof(*request)); - if (!access_ok(VERIFY_WRITE, request, sizeof(*request)) || + if (!access_ok(request, sizeof(*request)) || __put_user(req32.param, &request->param) || __put_user((void __user *)(unsigned long)req32.value, &request->value)) diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 4529edfdcfc8..2b2eb57ca71f 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -3052,7 +3052,7 @@ static struct i915_oa_reg *alloc_oa_regs(struct drm_i915_private *dev_priv, if (!n_regs) return NULL; - if (!access_ok(VERIFY_READ, regs, n_regs * sizeof(u32) * 2)) + if (!access_ok(regs, n_regs * sizeof(u32) * 2)) return ERR_PTR(-EFAULT); /* No is_valid function means we're not allowing any register to be programmed. */ diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c index 6fc4b8eeab42..fe56465cdfd6 100644 --- a/drivers/gpu/drm/i915/i915_query.c +++ b/drivers/gpu/drm/i915/i915_query.c @@ -46,7 +46,7 @@ static int query_topology_info(struct drm_i915_private *dev_priv, if (topo.flags != 0) return -EINVAL; - if (!access_ok(VERIFY_WRITE, u64_to_user_ptr(query_item->data_ptr), + if (!access_ok(u64_to_user_ptr(query_item->data_ptr), total_length)) return -EFAULT; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 07c861884c70..3da9c0f9e948 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -46,7 +46,7 @@ #include <drm/drm_plane_helper.h> #include <drm/drm_rect.h> #include <drm/drm_atomic_uapi.h> -#include <linux/dma_remapping.h> +#include <linux/intel-iommu.h> #include <linux/reservation.h> /* Primary plane formats for gen <= 3 */ diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 69fe86b30fbb..a9ed0ecc94e2 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -170,7 +170,7 @@ static int igt_ppgtt_alloc(void *arg) * This should ensure that we do not run into the oomkiller during * the test and take down the machine wilfully. */ - limit = totalram_pages << PAGE_SHIFT; + limit = totalram_pages() << PAGE_SHIFT; limit = min(ppgtt->vm.total, limit); /* Check we can allocate the entire range */ @@ -1244,7 +1244,7 @@ static int exercise_mock(struct drm_i915_private *i915, u64 hole_start, u64 hole_end, unsigned long end_time)) { - const u64 limit = totalram_pages << PAGE_SHIFT; + const u64 limit = totalram_pages() << PAGE_SHIFT; struct i915_gem_context *ctx; struct i915_hw_ppgtt *ppgtt; IGT_TIMEOUT(end_time); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index c58e953fefa3..5beb83d1cf87 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -927,26 +927,6 @@ static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu) return ret; } -/* Get the list of RPMh voltage levels from cmd-db */ -static int a6xx_gmu_rpmh_arc_cmds(const char *id, void *vals, int size) -{ - u32 len = cmd_db_read_aux_data_len(id); - - if (!len) - return 0; - - if (WARN_ON(len > size)) - return -EINVAL; - - cmd_db_read_aux_data(id, vals, len); - - /* - * The data comes back as an array of unsigned shorts so adjust the - * count accordingly - */ - return len >> 1; -} - /* Return the 'arc-level' for the given frequency */ static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq) { @@ -974,11 +954,30 @@ static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq) } static int a6xx_gmu_rpmh_arc_votes_init(struct device *dev, u32 *votes, - unsigned long *freqs, int freqs_count, - u16 *pri, int pri_count, - u16 *sec, int sec_count) + unsigned long *freqs, int freqs_count, const char *id) { int i, j; + const u16 *pri, *sec; + size_t pri_count, sec_count; + + pri = cmd_db_read_aux_data(id, &pri_count); + if (IS_ERR(pri)) + return PTR_ERR(pri); + /* + * The data comes back as an array of unsigned shorts so adjust the + * count accordingly + */ + pri_count >>= 1; + if (!pri_count) + return -EINVAL; + + sec = cmd_db_read_aux_data("mx.lvl", &sec_count); + if (IS_ERR(sec)) + return PTR_ERR(sec); + + sec_count >>= 1; + if (!sec_count) + return -EINVAL; /* Construct a vote for each frequency */ for (i = 0; i < freqs_count; i++) { @@ -1037,25 +1036,15 @@ static int a6xx_gmu_rpmh_votes_init(struct a6xx_gmu *gmu) struct a6xx_gpu *a6xx_gpu = container_of(gmu, struct a6xx_gpu, gmu); struct adreno_gpu *adreno_gpu = &a6xx_gpu->base; struct msm_gpu *gpu = &adreno_gpu->base; - - u16 gx[16], cx[16], mx[16]; - u32 gxcount, cxcount, mxcount; int ret; - /* Get the list of available voltage levels for each component */ - gxcount = a6xx_gmu_rpmh_arc_cmds("gfx.lvl", gx, sizeof(gx)); - cxcount = a6xx_gmu_rpmh_arc_cmds("cx.lvl", cx, sizeof(cx)); - mxcount = a6xx_gmu_rpmh_arc_cmds("mx.lvl", mx, sizeof(mx)); - /* Build the GX votes */ ret = a6xx_gmu_rpmh_arc_votes_init(&gpu->pdev->dev, gmu->gx_arc_votes, - gmu->gpu_freqs, gmu->nr_gpu_freqs, - gx, gxcount, mx, mxcount); + gmu->gpu_freqs, gmu->nr_gpu_freqs, "gfx.lvl"); /* Build the CX votes */ ret |= a6xx_gmu_rpmh_arc_votes_init(gmu->dev, gmu->cx_arc_votes, - gmu->gmu_freqs, gmu->nr_gmu_freqs, - cx, cxcount, mx, mxcount); + gmu->gmu_freqs, gmu->nr_gmu_freqs, "cx.lvl"); return ret; } diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index a28465d90529..12b983fc0b56 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -77,7 +77,7 @@ void msm_gem_submit_free(struct msm_gem_submit *submit) static inline unsigned long __must_check copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) { - if (access_ok(VERIFY_READ, from, n)) + if (access_ok(from, n)) return __copy_from_user_inatomic(to, from, n); return -EFAULT; } diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index 4b75ad40dd80..432c440223bb 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -4,7 +4,8 @@ config DRM_NOUVEAU select FW_LOADER select DRM_KMS_HELPER select DRM_TTM - select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT + select BACKLIGHT_CLASS_DEVICE if DRM_NOUVEAU_BACKLIGHT + select BACKLIGHT_LCD_SUPPORT if DRM_NOUVEAU_BACKLIGHT select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && INPUT select X86_PLATFORM_DEVICES if ACPI && X86 select ACPI_WMI if ACPI && X86 diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c index 6e828158bcb0..d410e2925162 100644 --- a/drivers/gpu/drm/qxl/qxl_ioctl.c +++ b/drivers/gpu/drm/qxl/qxl_ioctl.c @@ -163,8 +163,7 @@ static int qxl_process_single_command(struct qxl_device *qdev, if (cmd->command_size > PAGE_SIZE - sizeof(union qxl_release_info)) return -EINVAL; - if (!access_ok(VERIFY_READ, - u64_to_user_ptr(cmd->command), + if (!access_ok(u64_to_user_ptr(cmd->command), cmd->command_size)) return -EFAULT; diff --git a/drivers/gpu/drm/radeon/radeon_mn.c b/drivers/gpu/drm/radeon/radeon_mn.c index f8b35df44c60..b3019505065a 100644 --- a/drivers/gpu/drm/radeon/radeon_mn.c +++ b/drivers/gpu/drm/radeon/radeon_mn.c @@ -119,40 +119,38 @@ static void radeon_mn_release(struct mmu_notifier *mn, * unmap them by move them into system domain again. */ static int radeon_mn_invalidate_range_start(struct mmu_notifier *mn, - struct mm_struct *mm, - unsigned long start, - unsigned long end, - bool blockable) + const struct mmu_notifier_range *range) { struct radeon_mn *rmn = container_of(mn, struct radeon_mn, mn); struct ttm_operation_ctx ctx = { false, false }; struct interval_tree_node *it; + unsigned long end; int ret = 0; /* notification is exclusive, but interval is inclusive */ - end -= 1; + end = range->end - 1; /* TODO we should be able to split locking for interval tree and * the tear down. */ - if (blockable) + if (range->blockable) mutex_lock(&rmn->lock); else if (!mutex_trylock(&rmn->lock)) return -EAGAIN; - it = interval_tree_iter_first(&rmn->objects, start, end); + it = interval_tree_iter_first(&rmn->objects, range->start, end); while (it) { struct radeon_mn_node *node; struct radeon_bo *bo; long r; - if (!blockable) { + if (!range->blockable) { ret = -EAGAIN; goto out_unlock; } node = container_of(it, struct radeon_mn_node, it); - it = interval_tree_iter_next(it, start, end); + it = interval_tree_iter_next(it, range->start, end); list_for_each_entry(bo, &node->bos, mn_list) { diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 9fd5fbe8bebf..25afb1d594e3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -34,7 +34,7 @@ #include <drm/ttm/ttm_placement.h> #include <drm/ttm/ttm_bo_driver.h> #include <drm/ttm/ttm_module.h> -#include <linux/dma_remapping.h> +#include <linux/intel-iommu.h> #define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices" #define VMWGFX_CHIP_SVGAII 0 |