diff options
222 files changed, 1488 insertions, 1433 deletions
diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 4863a4deb0ee..263e5a97c080 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -446,6 +446,23 @@ telemetry information (devcoredump, syslog). This is useful because the first hang is usually the most critical one which can result in consequential hangs or complete wedging. +Task information +--------------- + +The information about which application (if any) was involved in the device +wedging is useful for userspace if they want to notify the user about what +happened (e.g. the compositor display a message to the user "The <task name> +caused a graphical error and the system recovered") or to implement policies +(e.g. the daemon may "ban" an task that keeps resetting the device). If the task +information is available, the uevent will display as ``PID=<pid>`` and +``TASK=<task name>``. Otherwise, ``PID`` and ``TASK`` will not appear in the +event string. + +The reliability of this information is driver and hardware specific, and should +be taken with a caution regarding it's precision. To have a big picture of what +really happened, the devcoredump file provides should have much more detailed +information about the device state and about the event. + Consumer prerequisites ---------------------- diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index fb27be697128..0792f31961ac 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -213,8 +213,10 @@ arch_initcall(init_x86_sysctl); */ struct screen_info screen_info; EXPORT_SYMBOL(screen_info); +#if defined(CONFIG_FIRMWARE_EDID) struct edid_info edid_info; EXPORT_SYMBOL_GPL(edid_info); +#endif extern int root_mountflags; @@ -525,7 +527,9 @@ static void __init parse_boot_params(void) { ROOT_DEV = old_decode_dev(boot_params.hdr.root_dev); screen_info = boot_params.screen_info; +#if defined(CONFIG_FIRMWARE_EDID) edid_info = boot_params.edid_info; +#endif #ifdef CONFIG_X86_32 apm_info.bios = boot_params.apm_bios_info; ist_info = boot_params.ist_info; diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c index 3e38a5f637ea..f20999f2d668 100644 --- a/drivers/accel/amdxdna/aie2_ctx.c +++ b/drivers/accel/amdxdna/aie2_ctx.c @@ -566,7 +566,7 @@ int aie2_hwctx_init(struct amdxdna_hwctx *hwctx) .size = MAX_CHAIN_CMDBUF_SIZE, }; - abo = amdxdna_drm_alloc_dev_bo(&xdna->ddev, &args, client->filp, true); + abo = amdxdna_drm_alloc_dev_bo(&xdna->ddev, &args, client->filp); if (IS_ERR(abo)) { ret = PTR_ERR(abo); goto free_cmd_bufs; diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c index 26831ec69f89..0f85a0105178 100644 --- a/drivers/accel/amdxdna/amdxdna_gem.c +++ b/drivers/accel/amdxdna/amdxdna_gem.c @@ -24,40 +24,79 @@ MODULE_IMPORT_NS("DMA_BUF"); static int -amdxdna_gem_insert_node_locked(struct amdxdna_gem_obj *abo, bool use_vmap) +amdxdna_gem_heap_alloc(struct amdxdna_gem_obj *abo) { struct amdxdna_client *client = abo->client; struct amdxdna_dev *xdna = client->xdna; struct amdxdna_mem *mem = &abo->mem; + struct amdxdna_gem_obj *heap; u64 offset; u32 align; int ret; + mutex_lock(&client->mm_lock); + + heap = client->dev_heap; + if (!heap) { + ret = -EINVAL; + goto unlock_out; + } + + if (heap->mem.userptr == AMDXDNA_INVALID_ADDR) { + XDNA_ERR(xdna, "Invalid dev heap userptr"); + ret = -EINVAL; + goto unlock_out; + } + + if (mem->size == 0 || mem->size > heap->mem.size) { + XDNA_ERR(xdna, "Invalid dev bo size 0x%lx, limit 0x%lx", + mem->size, heap->mem.size); + ret = -EINVAL; + goto unlock_out; + } + align = 1 << max(PAGE_SHIFT, xdna->dev_info->dev_mem_buf_shift); - ret = drm_mm_insert_node_generic(&abo->dev_heap->mm, &abo->mm_node, + ret = drm_mm_insert_node_generic(&heap->mm, &abo->mm_node, mem->size, align, 0, DRM_MM_INSERT_BEST); if (ret) { XDNA_ERR(xdna, "Failed to alloc dev bo memory, ret %d", ret); - return ret; + goto unlock_out; } mem->dev_addr = abo->mm_node.start; - offset = mem->dev_addr - abo->dev_heap->mem.dev_addr; - mem->userptr = abo->dev_heap->mem.userptr + offset; - mem->pages = &abo->dev_heap->base.pages[offset >> PAGE_SHIFT]; - mem->nr_pages = mem->size >> PAGE_SHIFT; - - if (use_vmap) { - mem->kva = vmap(mem->pages, mem->nr_pages, VM_MAP, PAGE_KERNEL); - if (!mem->kva) { - XDNA_ERR(xdna, "Failed to vmap"); - drm_mm_remove_node(&abo->mm_node); - return -EFAULT; - } - } + offset = mem->dev_addr - heap->mem.dev_addr; + mem->userptr = heap->mem.userptr + offset; + mem->kva = heap->mem.kva + offset; - return 0; + drm_gem_object_get(to_gobj(heap)); + +unlock_out: + mutex_unlock(&client->mm_lock); + + return ret; +} + +static void +amdxdna_gem_destroy_obj(struct amdxdna_gem_obj *abo) +{ + mutex_destroy(&abo->lock); + kfree(abo); +} + +static void +amdxdna_gem_heap_free(struct amdxdna_gem_obj *abo) +{ + struct amdxdna_gem_obj *heap; + + mutex_lock(&abo->client->mm_lock); + + drm_mm_remove_node(&abo->mm_node); + + heap = abo->client->dev_heap; + drm_gem_object_put(to_gobj(heap)); + + mutex_unlock(&abo->client->mm_lock); } static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni, @@ -213,6 +252,20 @@ free_map: return ret; } +static void amdxdna_gem_dev_obj_free(struct drm_gem_object *gobj) +{ + struct amdxdna_dev *xdna = to_xdna_dev(gobj->dev); + struct amdxdna_gem_obj *abo = to_xdna_obj(gobj); + + XDNA_DBG(xdna, "BO type %d xdna_addr 0x%llx", abo->type, abo->mem.dev_addr); + if (abo->pinned) + amdxdna_gem_unpin(abo); + + amdxdna_gem_heap_free(abo); + drm_gem_object_release(gobj); + amdxdna_gem_destroy_obj(abo); +} + static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo, struct vm_area_struct *vma) { @@ -374,19 +427,6 @@ static void amdxdna_gem_obj_free(struct drm_gem_object *gobj) if (abo->pinned) amdxdna_gem_unpin(abo); - if (abo->type == AMDXDNA_BO_DEV) { - mutex_lock(&abo->client->mm_lock); - drm_mm_remove_node(&abo->mm_node); - mutex_unlock(&abo->client->mm_lock); - - vunmap(abo->mem.kva); - drm_gem_object_put(to_gobj(abo->dev_heap)); - drm_gem_object_release(gobj); - mutex_destroy(&abo->lock); - kfree(abo); - return; - } - if (abo->type == AMDXDNA_BO_DEV_HEAP) drm_mm_takedown(&abo->mm); @@ -402,7 +442,7 @@ static void amdxdna_gem_obj_free(struct drm_gem_object *gobj) } static const struct drm_gem_object_funcs amdxdna_gem_dev_obj_funcs = { - .free = amdxdna_gem_obj_free, + .free = amdxdna_gem_dev_obj_free, }; static const struct drm_gem_object_funcs amdxdna_gem_shmem_funcs = { @@ -527,6 +567,7 @@ amdxdna_drm_create_dev_heap(struct drm_device *dev, struct drm_file *filp) { struct amdxdna_client *client = filp->driver_priv; + struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL); struct amdxdna_dev *xdna = to_xdna_dev(dev); struct drm_gem_shmem_object *shmem; struct amdxdna_gem_obj *abo; @@ -553,18 +594,26 @@ amdxdna_drm_create_dev_heap(struct drm_device *dev, shmem->map_wc = false; abo = to_xdna_obj(&shmem->base); - abo->type = AMDXDNA_BO_DEV_HEAP; abo->client = client; abo->mem.dev_addr = client->xdna->dev_info->dev_mem_base; drm_mm_init(&abo->mm, abo->mem.dev_addr, abo->mem.size); + ret = drm_gem_vmap(to_gobj(abo), &map); + if (ret) { + XDNA_ERR(xdna, "Vmap heap bo failed, ret %d", ret); + goto release_obj; + } + abo->mem.kva = map.vaddr; + client->dev_heap = abo; drm_gem_object_get(to_gobj(abo)); mutex_unlock(&client->mm_lock); return abo; +release_obj: + drm_gem_object_put(to_gobj(abo)); mm_unlock: mutex_unlock(&client->mm_lock); return ERR_PTR(ret); @@ -573,58 +622,32 @@ mm_unlock: struct amdxdna_gem_obj * amdxdna_drm_alloc_dev_bo(struct drm_device *dev, struct amdxdna_drm_create_bo *args, - struct drm_file *filp, bool use_vmap) + struct drm_file *filp) { struct amdxdna_client *client = filp->driver_priv; struct amdxdna_dev *xdna = to_xdna_dev(dev); size_t aligned_sz = PAGE_ALIGN(args->size); - struct amdxdna_gem_obj *abo, *heap; + struct amdxdna_gem_obj *abo; int ret; - mutex_lock(&client->mm_lock); - heap = client->dev_heap; - if (!heap) { - ret = -EINVAL; - goto mm_unlock; - } - - if (heap->mem.userptr == AMDXDNA_INVALID_ADDR) { - XDNA_ERR(xdna, "Invalid dev heap userptr"); - ret = -EINVAL; - goto mm_unlock; - } - - if (args->size > heap->mem.size) { - XDNA_ERR(xdna, "Invalid dev bo size 0x%llx, limit 0x%lx", - args->size, heap->mem.size); - ret = -EINVAL; - goto mm_unlock; - } - abo = amdxdna_gem_create_obj(&xdna->ddev, aligned_sz); - if (IS_ERR(abo)) { - ret = PTR_ERR(abo); - goto mm_unlock; - } + if (IS_ERR(abo)) + return abo; + to_gobj(abo)->funcs = &amdxdna_gem_dev_obj_funcs; abo->type = AMDXDNA_BO_DEV; abo->client = client; - abo->dev_heap = heap; - ret = amdxdna_gem_insert_node_locked(abo, use_vmap); + + ret = amdxdna_gem_heap_alloc(abo); if (ret) { XDNA_ERR(xdna, "Failed to alloc dev bo memory, ret %d", ret); - goto mm_unlock; + amdxdna_gem_destroy_obj(abo); + return ERR_PTR(ret); } - drm_gem_object_get(to_gobj(heap)); drm_gem_private_object_init(&xdna->ddev, to_gobj(abo), aligned_sz); - mutex_unlock(&client->mm_lock); return abo; - -mm_unlock: - mutex_unlock(&client->mm_lock); - return ERR_PTR(ret); } static struct amdxdna_gem_obj * @@ -632,10 +655,10 @@ amdxdna_drm_create_cmd_bo(struct drm_device *dev, struct amdxdna_drm_create_bo *args, struct drm_file *filp) { + struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL); struct amdxdna_dev *xdna = to_xdna_dev(dev); struct drm_gem_shmem_object *shmem; struct amdxdna_gem_obj *abo; - struct iosys_map map; int ret; if (args->size > XDNA_MAX_CMD_BO_SIZE) { @@ -692,7 +715,7 @@ int amdxdna_drm_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_f abo = amdxdna_drm_create_dev_heap(dev, args, filp); break; case AMDXDNA_BO_DEV: - abo = amdxdna_drm_alloc_dev_bo(dev, args, filp, false); + abo = amdxdna_drm_alloc_dev_bo(dev, args, filp); break; case AMDXDNA_BO_CMD: abo = amdxdna_drm_create_cmd_bo(dev, args, filp); @@ -724,20 +747,13 @@ int amdxdna_gem_pin_nolock(struct amdxdna_gem_obj *abo) struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev); int ret; + if (abo->type == AMDXDNA_BO_DEV) + abo = abo->client->dev_heap; + if (is_import_bo(abo)) return 0; - switch (abo->type) { - case AMDXDNA_BO_SHMEM: - case AMDXDNA_BO_DEV_HEAP: - ret = drm_gem_shmem_pin(&abo->base); - break; - case AMDXDNA_BO_DEV: - ret = drm_gem_shmem_pin(&abo->dev_heap->base); - break; - default: - ret = -EOPNOTSUPP; - } + ret = drm_gem_shmem_pin(&abo->base); XDNA_DBG(xdna, "BO type %d ret %d", abo->type, ret); return ret; @@ -747,9 +763,6 @@ int amdxdna_gem_pin(struct amdxdna_gem_obj *abo) { int ret; - if (abo->type == AMDXDNA_BO_DEV) - abo = abo->dev_heap; - mutex_lock(&abo->lock); ret = amdxdna_gem_pin_nolock(abo); mutex_unlock(&abo->lock); @@ -759,12 +772,12 @@ int amdxdna_gem_pin(struct amdxdna_gem_obj *abo) void amdxdna_gem_unpin(struct amdxdna_gem_obj *abo) { + if (abo->type == AMDXDNA_BO_DEV) + abo = abo->client->dev_heap; + if (is_import_bo(abo)) return; - if (abo->type == AMDXDNA_BO_DEV) - abo = abo->dev_heap; - mutex_lock(&abo->lock); drm_gem_shmem_unpin(&abo->base); mutex_unlock(&abo->lock); @@ -855,10 +868,12 @@ int amdxdna_drm_sync_bo_ioctl(struct drm_device *dev, if (is_import_bo(abo)) drm_clflush_sg(abo->base.sgt); - else if (abo->type == AMDXDNA_BO_DEV) - drm_clflush_pages(abo->mem.pages, abo->mem.nr_pages); - else + else if (abo->mem.kva) + drm_clflush_virt_range(abo->mem.kva + args->offset, args->size); + else if (abo->base.pages) drm_clflush_pages(abo->base.pages, gobj->size >> PAGE_SHIFT); + else + drm_WARN(&xdna->ddev, 1, "Can not get flush memory"); amdxdna_gem_unpin(abo); diff --git a/drivers/accel/amdxdna/amdxdna_gem.h b/drivers/accel/amdxdna/amdxdna_gem.h index aee97e971d6d..ae29db94a9d3 100644 --- a/drivers/accel/amdxdna/amdxdna_gem.h +++ b/drivers/accel/amdxdna/amdxdna_gem.h @@ -41,7 +41,6 @@ struct amdxdna_gem_obj { /* Below members is uninitialized when needed */ struct drm_mm mm; /* For AMDXDNA_BO_DEV_HEAP */ - struct amdxdna_gem_obj *dev_heap; /* For AMDXDNA_BO_DEV */ struct drm_mm_node mm_node; /* For AMDXDNA_BO_DEV */ u32 assigned_hwctx; struct dma_buf *dma_buf; @@ -72,7 +71,7 @@ amdxdna_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); struct amdxdna_gem_obj * amdxdna_drm_alloc_dev_bo(struct drm_device *dev, struct amdxdna_drm_create_bo *args, - struct drm_file *filp, bool use_vmap); + struct drm_file *filp); int amdxdna_gem_pin_nolock(struct amdxdna_gem_obj *abo); int amdxdna_gem_pin(struct amdxdna_gem_obj *abo); diff --git a/drivers/accel/ivpu/ivpu_drv.c b/drivers/accel/ivpu/ivpu_drv.c index 0e7748c5e117..3d6d52492536 100644 --- a/drivers/accel/ivpu/ivpu_drv.c +++ b/drivers/accel/ivpu/ivpu_drv.c @@ -704,6 +704,7 @@ static struct pci_device_id ivpu_pci_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_ARL) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_LNL) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PTL_P) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_WCL) }, { } }; MODULE_DEVICE_TABLE(pci, ivpu_pci_ids); diff --git a/drivers/accel/ivpu/ivpu_drv.h b/drivers/accel/ivpu/ivpu_drv.h index b6d6b3238b59..62ab1c654e63 100644 --- a/drivers/accel/ivpu/ivpu_drv.h +++ b/drivers/accel/ivpu/ivpu_drv.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (C) 2020-2024 Intel Corporation + * Copyright (C) 2020-2025 Intel Corporation */ #ifndef __IVPU_DRV_H__ @@ -26,6 +26,7 @@ #define PCI_DEVICE_ID_ARL 0xad1d #define PCI_DEVICE_ID_LNL 0x643e #define PCI_DEVICE_ID_PTL_P 0xb03e +#define PCI_DEVICE_ID_WCL 0xfd3e #define IVPU_HW_IP_37XX 37 #define IVPU_HW_IP_40XX 40 @@ -208,10 +209,11 @@ extern bool ivpu_force_snoop; #define IVPU_TEST_MODE_D0I3_MSG_ENABLE BIT(5) #define IVPU_TEST_MODE_MIP_DISABLE BIT(6) #define IVPU_TEST_MODE_DISABLE_TIMEOUTS BIT(8) -#define IVPU_TEST_MODE_TURBO BIT(9) -#define IVPU_TEST_MODE_CLK_RELINQ_DISABLE BIT(10) -#define IVPU_TEST_MODE_CLK_RELINQ_ENABLE BIT(11) -#define IVPU_TEST_MODE_D0I2_DISABLE BIT(12) +#define IVPU_TEST_MODE_TURBO_ENABLE BIT(9) +#define IVPU_TEST_MODE_TURBO_DISABLE BIT(10) +#define IVPU_TEST_MODE_CLK_RELINQ_DISABLE BIT(11) +#define IVPU_TEST_MODE_CLK_RELINQ_ENABLE BIT(12) +#define IVPU_TEST_MODE_D0I2_DISABLE BIT(13) extern int ivpu_test_mode; struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv); @@ -241,6 +243,7 @@ static inline int ivpu_hw_ip_gen(struct ivpu_device *vdev) case PCI_DEVICE_ID_LNL: return IVPU_HW_IP_40XX; case PCI_DEVICE_ID_PTL_P: + case PCI_DEVICE_ID_WCL: return IVPU_HW_IP_50XX; default: dump_stack(); @@ -257,6 +260,7 @@ static inline int ivpu_hw_btrs_gen(struct ivpu_device *vdev) return IVPU_HW_BTRS_MTL; case PCI_DEVICE_ID_LNL: case PCI_DEVICE_ID_PTL_P: + case PCI_DEVICE_ID_WCL: return IVPU_HW_BTRS_LNL; default: dump_stack(); diff --git a/drivers/accel/ivpu/ivpu_hw_ip.c b/drivers/accel/ivpu/ivpu_hw_ip.c index 823f6a57dc54..2bf9882ab52e 100644 --- a/drivers/accel/ivpu/ivpu_hw_ip.c +++ b/drivers/accel/ivpu/ivpu_hw_ip.c @@ -683,6 +683,7 @@ static void pwr_island_delay_set(struct ivpu_device *vdev) return; switch (ivpu_device_id(vdev)) { + case PCI_DEVICE_ID_WCL: case PCI_DEVICE_ID_PTL_P: post = high ? 18 : 0; post1 = 0; diff --git a/drivers/accel/ivpu/ivpu_job.c b/drivers/accel/ivpu/ivpu_job.c index fae8351aa330..060f1fc031d3 100644 --- a/drivers/accel/ivpu/ivpu_job.c +++ b/drivers/accel/ivpu/ivpu_job.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (C) 2020-2024 Intel Corporation + * Copyright (C) 2020-2025 Intel Corporation */ #include <drm/drm_file.h> @@ -100,6 +100,43 @@ err_free_cmdq: return NULL; } +/** + * ivpu_cmdq_get_entry_count - Calculate the number of entries in the command queue. + * @cmdq: Pointer to the command queue structure. + * + * Returns the number of entries that can fit in the command queue memory. + */ +static inline u32 ivpu_cmdq_get_entry_count(struct ivpu_cmdq *cmdq) +{ + size_t size = ivpu_bo_size(cmdq->mem) - sizeof(struct vpu_job_queue_header); + + return size / sizeof(struct vpu_job_queue_entry); +} + +/** + * ivpu_cmdq_get_flags - Get command queue flags based on input flags and test mode. + * @vdev: Pointer to the ivpu device structure. + * @flags: Input flags to determine the command queue flags. + * + * Returns the calculated command queue flags, considering both the input flags + * and the current test mode settings. + */ +static u32 ivpu_cmdq_get_flags(struct ivpu_device *vdev, u32 flags) +{ + u32 cmdq_flags = 0; + + if ((flags & DRM_IVPU_CMDQ_FLAG_TURBO) && (ivpu_hw_ip_gen(vdev) >= IVPU_HW_IP_40XX)) + cmdq_flags |= VPU_JOB_QUEUE_FLAGS_TURBO_MODE; + + /* Test mode can override the TURBO flag coming from the application */ + if (ivpu_test_mode & IVPU_TEST_MODE_TURBO_ENABLE) + cmdq_flags |= VPU_JOB_QUEUE_FLAGS_TURBO_MODE; + if (ivpu_test_mode & IVPU_TEST_MODE_TURBO_DISABLE) + cmdq_flags &= ~VPU_JOB_QUEUE_FLAGS_TURBO_MODE; + + return cmdq_flags; +} + static void ivpu_cmdq_free(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) { ivpu_preemption_buffers_free(file_priv->vdev, file_priv, cmdq); @@ -107,8 +144,7 @@ static void ivpu_cmdq_free(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *c kfree(cmdq); } -static struct ivpu_cmdq *ivpu_cmdq_create(struct ivpu_file_priv *file_priv, u8 priority, - bool is_legacy) +static struct ivpu_cmdq *ivpu_cmdq_create(struct ivpu_file_priv *file_priv, u8 priority, u32 flags) { struct ivpu_device *vdev = file_priv->vdev; struct ivpu_cmdq *cmdq = NULL; @@ -121,10 +157,6 @@ static struct ivpu_cmdq *ivpu_cmdq_create(struct ivpu_file_priv *file_priv, u8 p ivpu_err(vdev, "Failed to allocate command queue\n"); return NULL; } - - cmdq->priority = priority; - cmdq->is_legacy = is_legacy; - ret = xa_alloc_cyclic(&file_priv->cmdq_xa, &cmdq->id, cmdq, file_priv->cmdq_limit, &file_priv->cmdq_id_next, GFP_KERNEL); if (ret < 0) { @@ -132,7 +164,15 @@ static struct ivpu_cmdq *ivpu_cmdq_create(struct ivpu_file_priv *file_priv, u8 p goto err_free_cmdq; } - ivpu_dbg(vdev, JOB, "Command queue %d created, ctx %d\n", cmdq->id, file_priv->ctx.id); + cmdq->entry_count = ivpu_cmdq_get_entry_count(cmdq); + cmdq->priority = priority; + + cmdq->jobq = (struct vpu_job_queue *)ivpu_bo_vaddr(cmdq->mem); + cmdq->jobq->header.engine_idx = VPU_ENGINE_COMPUTE; + cmdq->jobq->header.flags = ivpu_cmdq_get_flags(vdev, flags); + + ivpu_dbg(vdev, JOB, "Command queue %d created, ctx %d, flags 0x%08x\n", + cmdq->id, file_priv->ctx.id, cmdq->jobq->header.flags); return cmdq; err_free_cmdq: @@ -188,27 +228,14 @@ static int ivpu_register_db(struct ivpu_file_priv *file_priv, struct ivpu_cmdq * return ret; } -static void ivpu_cmdq_jobq_init(struct ivpu_device *vdev, struct vpu_job_queue *jobq) +static void ivpu_cmdq_jobq_reset(struct ivpu_device *vdev, struct vpu_job_queue *jobq) { - jobq->header.engine_idx = VPU_ENGINE_COMPUTE; jobq->header.head = 0; jobq->header.tail = 0; - if (ivpu_test_mode & IVPU_TEST_MODE_TURBO) { - ivpu_dbg(vdev, JOB, "Turbo mode enabled"); - jobq->header.flags = VPU_JOB_QUEUE_FLAGS_TURBO_MODE; - } - wmb(); /* Flush WC buffer for jobq->header */ } -static inline u32 ivpu_cmdq_get_entry_count(struct ivpu_cmdq *cmdq) -{ - size_t size = ivpu_bo_size(cmdq->mem) - sizeof(struct vpu_job_queue_header); - - return size / sizeof(struct vpu_job_queue_entry); -} - static int ivpu_cmdq_register(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) { struct ivpu_device *vdev = file_priv->vdev; @@ -219,10 +246,7 @@ static int ivpu_cmdq_register(struct ivpu_file_priv *file_priv, struct ivpu_cmdq if (cmdq->db_id) return 0; - cmdq->entry_count = ivpu_cmdq_get_entry_count(cmdq); - cmdq->jobq = (struct vpu_job_queue *)ivpu_bo_vaddr(cmdq->mem); - - ivpu_cmdq_jobq_init(vdev, cmdq->jobq); + ivpu_cmdq_jobq_reset(vdev, cmdq->jobq); if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) { ret = ivpu_hws_cmdq_init(file_priv, cmdq, VPU_ENGINE_COMPUTE, cmdq->priority); @@ -291,9 +315,10 @@ static struct ivpu_cmdq *ivpu_cmdq_acquire_legacy(struct ivpu_file_priv *file_pr break; if (!cmdq) { - cmdq = ivpu_cmdq_create(file_priv, priority, true); + cmdq = ivpu_cmdq_create(file_priv, priority, 0); if (!cmdq) return NULL; + cmdq->is_legacy = true; } return cmdq; @@ -891,7 +916,7 @@ int ivpu_cmdq_create_ioctl(struct drm_device *dev, void *data, struct drm_file * mutex_lock(&file_priv->lock); - cmdq = ivpu_cmdq_create(file_priv, ivpu_job_to_jsm_priority(args->priority), false); + cmdq = ivpu_cmdq_create(file_priv, ivpu_job_to_jsm_priority(args->priority), args->flags); if (cmdq) args->cmdq_id = cmdq->id; diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index 74f9e4b665e3..3f78c56b58dc 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -511,12 +511,20 @@ dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout) dma_fence_enable_sw_signaling(fence); - trace_dma_fence_wait_start(fence); + if (trace_dma_fence_wait_start_enabled()) { + rcu_read_lock(); + trace_dma_fence_wait_start(fence); + rcu_read_unlock(); + } if (fence->ops->wait) ret = fence->ops->wait(fence, intr, timeout); else ret = dma_fence_default_wait(fence, intr, timeout); - trace_dma_fence_wait_end(fence); + if (trace_dma_fence_wait_end_enabled()) { + rcu_read_lock(); + trace_dma_fence_wait_end(fence); + rcu_read_unlock(); + } return ret; } EXPORT_SYMBOL(dma_fence_wait_timeout); @@ -533,16 +541,23 @@ void dma_fence_release(struct kref *kref) struct dma_fence *fence = container_of(kref, struct dma_fence, refcount); + rcu_read_lock(); trace_dma_fence_destroy(fence); - if (WARN(!list_empty(&fence->cb_list) && - !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags), - "Fence %s:%s:%llx:%llx released with pending signals!\n", - dma_fence_driver_name(fence), - dma_fence_timeline_name(fence), - fence->context, fence->seqno)) { + if (!list_empty(&fence->cb_list) && + !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) { + const char __rcu *timeline; + const char __rcu *driver; unsigned long flags; + driver = dma_fence_driver_name(fence); + timeline = dma_fence_timeline_name(fence); + + WARN(1, + "Fence %s:%s:%llx:%llx released with pending signals!\n", + rcu_dereference(driver), rcu_dereference(timeline), + fence->context, fence->seqno); + /* * Failed to signal before release, likely a refcounting issue. * @@ -556,6 +571,8 @@ void dma_fence_release(struct kref *kref) spin_unlock_irqrestore(fence->lock, flags); } + rcu_read_unlock(); + if (fence->ops->release) fence->ops->release(fence); else @@ -982,11 +999,21 @@ EXPORT_SYMBOL(dma_fence_set_deadline); */ void dma_fence_describe(struct dma_fence *fence, struct seq_file *seq) { + const char __rcu *timeline; + const char __rcu *driver; + + rcu_read_lock(); + + timeline = dma_fence_timeline_name(fence); + driver = dma_fence_driver_name(fence); + seq_printf(seq, "%s %s seq %llu %ssignalled\n", - dma_fence_driver_name(fence), - dma_fence_timeline_name(fence), + rcu_dereference(driver), + rcu_dereference(timeline), fence->seqno, dma_fence_is_signaled(fence) ? "" : "un"); + + rcu_read_unlock(); } EXPORT_SYMBOL(dma_fence_describe); @@ -1055,3 +1082,67 @@ dma_fence_init64(struct dma_fence *fence, const struct dma_fence_ops *ops, BIT(DMA_FENCE_FLAG_SEQNO64_BIT)); } EXPORT_SYMBOL(dma_fence_init64); + +/** + * dma_fence_driver_name - Access the driver name + * @fence: the fence to query + * + * Returns a driver name backing the dma-fence implementation. + * + * IMPORTANT CONSIDERATION: + * Dma-fence contract stipulates that access to driver provided data (data not + * directly embedded into the object itself), such as the &dma_fence.lock and + * memory potentially accessed by the &dma_fence.ops functions, is forbidden + * after the fence has been signalled. Drivers are allowed to free that data, + * and some do. + * + * To allow safe access drivers are mandated to guarantee a RCU grace period + * between signalling the fence and freeing said data. + * + * As such access to the driver name is only valid inside a RCU locked section. + * The pointer MUST be both queried and USED ONLY WITHIN a SINGLE block guarded + * by the &rcu_read_lock and &rcu_read_unlock pair. + */ +const char __rcu *dma_fence_driver_name(struct dma_fence *fence) +{ + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), + "RCU protection is required for safe access to returned string"); + + if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + return fence->ops->get_driver_name(fence); + else + return "detached-driver"; +} +EXPORT_SYMBOL(dma_fence_driver_name); + +/** + * dma_fence_timeline_name - Access the timeline name + * @fence: the fence to query + * + * Returns a timeline name provided by the dma-fence implementation. + * + * IMPORTANT CONSIDERATION: + * Dma-fence contract stipulates that access to driver provided data (data not + * directly embedded into the object itself), such as the &dma_fence.lock and + * memory potentially accessed by the &dma_fence.ops functions, is forbidden + * after the fence has been signalled. Drivers are allowed to free that data, + * and some do. + * + * To allow safe access drivers are mandated to guarantee a RCU grace period + * between signalling the fence and freeing said data. + * + * As such access to the driver name is only valid inside a RCU locked section. + * The pointer MUST be both queried and USED ONLY WITHIN a SINGLE block guarded + * by the &rcu_read_lock and &rcu_read_unlock pair. + */ +const char __rcu *dma_fence_timeline_name(struct dma_fence *fence) +{ + RCU_LOCKDEP_WARN(!rcu_read_lock_held(), + "RCU protection is required for safe access to returned string"); + + if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)) + return fence->ops->get_driver_name(fence); + else + return "signaled-timeline"; +} +EXPORT_SYMBOL(dma_fence_timeline_name); diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 212df4b849fe..747e377fb954 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -135,12 +135,18 @@ char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len) strscpy(buf, sync_file->user_name, len); } else { struct dma_fence *fence = sync_file->fence; + const char __rcu *timeline; + const char __rcu *driver; + rcu_read_lock(); + driver = dma_fence_driver_name(fence); + timeline = dma_fence_timeline_name(fence); snprintf(buf, len, "%s-%s%llu-%lld", - dma_fence_driver_name(fence), - dma_fence_timeline_name(fence), + rcu_dereference(driver), + rcu_dereference(timeline), fence->context, fence->seqno); + rcu_read_unlock(); } return buf; @@ -262,9 +268,17 @@ err_put_fd: static int sync_fill_fence_info(struct dma_fence *fence, struct sync_fence_info *info) { - strscpy(info->obj_name, dma_fence_timeline_name(fence), + const char __rcu *timeline; + const char __rcu *driver; + + rcu_read_lock(); + + driver = dma_fence_driver_name(fence); + timeline = dma_fence_timeline_name(fence); + + strscpy(info->obj_name, rcu_dereference(timeline), sizeof(info->obj_name)); - strscpy(info->driver_name, dma_fence_driver_name(fence), + strscpy(info->driver_name, rcu_dereference(driver), sizeof(info->driver_name)); info->status = dma_fence_get_status(fence); @@ -273,6 +287,8 @@ static int sync_fill_fence_info(struct dma_fence *fence, ktime_to_ns(dma_fence_timestamp(fence)) : ktime_set(0, 0); + rcu_read_unlock(); + return info->status; } diff --git a/drivers/gpu/drm/Kconfig.debug b/drivers/gpu/drm/Kconfig.debug index fa6ee76f4d3c..05dc43c0b8c5 100644 --- a/drivers/gpu/drm/Kconfig.debug +++ b/drivers/gpu/drm/Kconfig.debug @@ -70,6 +70,7 @@ config DRM_KUNIT_TEST select DRM_GEM_SHMEM_HELPER select DRM_KUNIT_TEST_HELPERS select DRM_LIB_RANDOM + select DRM_SYSFB_HELPER select PRIME_NUMBERS default KUNIT_ALL_TESTS help diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c index 8e626f50b362..dac4b926e7be 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c @@ -1786,7 +1786,7 @@ static int amdgpu_debugfs_vm_info_show(struct seq_file *m, void *unused) ti = amdgpu_vm_get_task_info_vm(vm); if (ti) { - seq_printf(m, "pid:%d\tProcess:%s ----------\n", ti->pid, ti->process_name); + seq_printf(m, "pid:%d\tProcess:%s ----------\n", ti->task.pid, ti->process_name); amdgpu_vm_put_task_info(ti); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c index 7b50741dc097..8a026bc9ea44 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c @@ -220,10 +220,10 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count, drm_printf(&p, "time: %lld.%09ld\n", coredump->reset_time.tv_sec, coredump->reset_time.tv_nsec); - if (coredump->reset_task_info.pid) + if (coredump->reset_task_info.task.pid) drm_printf(&p, "process_name: %s PID: %d\n", coredump->reset_task_info.process_name, - coredump->reset_task_info.pid); + coredump->reset_task_info.task.pid); /* SOC Information */ drm_printf(&p, "\nSOC Information\n"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index e1bab6a96cb6..a59f194e3360 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -6363,8 +6363,17 @@ end_reset: atomic_set(&adev->reset_domain->reset_res, r); - if (!r) - drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE); + if (!r) { + struct amdgpu_task_info *ti = NULL; + + if (job) + ti = amdgpu_vm_get_task_info_pasid(adev, job->pasid); + + drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE, + ti ? &ti->task : NULL); + + amdgpu_vm_put_task_info(ti); + } return r; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 0ecc88df7208..e5e33a68d935 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -329,7 +329,7 @@ static int amdgpu_gem_object_open(struct drm_gem_object *obj, dev_warn(adev->dev, "validate_and_fence failed: %d\n", r); if (ti) { - dev_warn(adev->dev, "pid %d\n", ti->pid); + dev_warn(adev->dev, "pid %d\n", ti->task.pid); amdgpu_vm_put_task_info(ti); } } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 75262ce8db27..1e24590ae144 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -89,6 +89,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) { struct amdgpu_ring *ring = to_amdgpu_ring(s_job->sched); struct amdgpu_job *job = to_amdgpu_job(s_job); + struct drm_wedge_task_info *info = NULL; struct amdgpu_task_info *ti; struct amdgpu_device *adev = ring->adev; int idx; @@ -124,10 +125,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) ti = amdgpu_vm_get_task_info_pasid(ring->adev, job->pasid); if (ti) { - dev_err(adev->dev, - "Process information: process %s pid %d thread %s pid %d\n", - ti->process_name, ti->tgid, ti->task_name, ti->pid); - amdgpu_vm_put_task_info(ti); + amdgpu_vm_print_task_info(adev, ti); + info = &ti->task; } /* attempt a per ring reset */ @@ -166,13 +165,15 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job) if (amdgpu_ring_sched_ready(ring)) drm_sched_start(&ring->sched, 0); dev_err(adev->dev, "Ring %s reset succeeded\n", ring->sched.name); - drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE); + drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE, info); goto exit; } dev_err(adev->dev, "Ring %s reset failure\n", ring->sched.name); } dma_fence_set_error(&s_job->s_fence->finished, -ETIME); + amdgpu_vm_put_task_info(ti); + if (amdgpu_device_should_recover_gpu(ring->adev)) { struct amdgpu_reset_context reset_context; memset(&reset_context, 0, sizeof(reset_context)); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 3911c78f8282..0ff95a56c2ce 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -622,7 +622,7 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm, pr_warn_ratelimited("Evicted user BO is not reserved\n"); if (ti) { - pr_warn_ratelimited("pid %d\n", ti->pid); + pr_warn_ratelimited("pid %d\n", ti->task.pid); amdgpu_vm_put_task_info(ti); } @@ -2447,7 +2447,8 @@ amdgpu_vm_get_vm_from_pasid(struct amdgpu_device *adev, u32 pasid) */ void amdgpu_vm_put_task_info(struct amdgpu_task_info *task_info) { - kref_put(&task_info->refcount, amdgpu_vm_destroy_task_info); + if (task_info) + kref_put(&task_info->refcount, amdgpu_vm_destroy_task_info); } /** @@ -2507,11 +2508,11 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm) if (!vm->task_info) return; - if (vm->task_info->pid == current->pid) + if (vm->task_info->task.pid == current->pid) return; - vm->task_info->pid = current->pid; - get_task_comm(vm->task_info->task_name, current); + vm->task_info->task.pid = current->pid; + get_task_comm(vm->task_info->task.comm, current); if (current->group_leader->mm != current->mm) return; @@ -2774,7 +2775,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) dev_warn(adev->dev, "VM memory stats for proc %s(%d) task %s(%d) is non-zero when fini\n", - ti->process_name, ti->pid, ti->task_name, ti->tgid); + ti->process_name, ti->task.pid, ti->task.comm, ti->tgid); } amdgpu_vm_put_task_info(vm->task_info); @@ -3156,3 +3157,12 @@ bool amdgpu_vm_is_bo_always_valid(struct amdgpu_vm *vm, struct amdgpu_bo *bo) { return bo && bo->tbo.base.resv == vm->root.bo->tbo.base.resv; } + +void amdgpu_vm_print_task_info(struct amdgpu_device *adev, + struct amdgpu_task_info *task_info) +{ + dev_err(adev->dev, + " Process %s pid %d thread %s pid %d\n", + task_info->process_name, task_info->tgid, + task_info->task.comm, task_info->task.pid); +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index f3ad687125ad..fd086efd8457 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -236,9 +236,8 @@ struct amdgpu_vm_pte_funcs { }; struct amdgpu_task_info { + struct drm_wedge_task_info task; char process_name[TASK_COMM_LEN]; - char task_name[TASK_COMM_LEN]; - pid_t pid; pid_t tgid; struct kref refcount; }; @@ -668,4 +667,7 @@ void amdgpu_vm_tlb_fence_create(struct amdgpu_device *adev, struct amdgpu_vm *vm, struct dma_fence **fence); +void amdgpu_vm_print_task_info(struct amdgpu_device *adev, + struct amdgpu_task_info *task_info); + #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c index a3e2787501f1..7923f491cf73 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c @@ -164,10 +164,7 @@ static int gmc_v10_0_process_interrupt(struct amdgpu_device *adev, entry->src_id, entry->ring_id, entry->vmid, entry->pasid); task_info = amdgpu_vm_get_task_info_pasid(adev, entry->pasid); if (task_info) { - dev_err(adev->dev, - " in process %s pid %d thread %s pid %d\n", - task_info->process_name, task_info->tgid, - task_info->task_name, task_info->pid); + amdgpu_vm_print_task_info(adev, task_info); amdgpu_vm_put_task_info(task_info); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index 72211409227b..f15d691e9a20 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -134,10 +134,7 @@ static int gmc_v11_0_process_interrupt(struct amdgpu_device *adev, entry->src_id, entry->ring_id, entry->vmid, entry->pasid); task_info = amdgpu_vm_get_task_info_pasid(adev, entry->pasid); if (task_info) { - dev_err(adev->dev, - " in process %s pid %d thread %s pid %d)\n", - task_info->process_name, task_info->tgid, - task_info->task_name, task_info->pid); + amdgpu_vm_print_task_info(adev, task_info); amdgpu_vm_put_task_info(task_info); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c index b645d3e6a6c8..de763105fdfd 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v12_0.c @@ -127,10 +127,7 @@ static int gmc_v12_0_process_interrupt(struct amdgpu_device *adev, entry->src_id, entry->ring_id, entry->vmid, entry->pasid); task_info = amdgpu_vm_get_task_info_pasid(adev, entry->pasid); if (task_info) { - dev_err(adev->dev, - " in process %s pid %d thread %s pid %d)\n", - task_info->process_name, task_info->tgid, - task_info->task_name, task_info->pid); + amdgpu_vm_print_task_info(adev, task_info); amdgpu_vm_put_task_info(task_info); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index 99ca08e9bdb5..b45fa0cea9d2 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -1458,9 +1458,7 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev, task_info = amdgpu_vm_get_task_info_pasid(adev, entry->pasid); if (task_info) { - dev_err(adev->dev, " for process %s pid %d thread %s pid %d\n", - task_info->process_name, task_info->tgid, - task_info->task_name, task_info->pid); + amdgpu_vm_print_task_info(adev, task_info); amdgpu_vm_put_task_info(task_info); } diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c index 282197f4ffb1..78f65aea03f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c @@ -641,10 +641,7 @@ static int gmc_v9_0_process_interrupt(struct amdgpu_device *adev, task_info = amdgpu_vm_get_task_info_pasid(adev, entry->pasid); if (task_info) { - dev_err(adev->dev, - " for process %s pid %d thread %s pid %d)\n", - task_info->process_name, task_info->tgid, - task_info->task_name, task_info->pid); + amdgpu_vm_print_task_info(adev, task_info); amdgpu_vm_put_task_info(task_info); } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 33ed2b158fcd..f38004e6064e 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -2187,7 +2187,7 @@ static int sdma_v4_0_print_iv_entry(struct amdgpu_device *adev, dev_dbg_ratelimited(adev->dev, " for process %s pid %d thread %s pid %d\n", task_info->process_name, task_info->tgid, - task_info->task_name, task_info->pid); + task_info->task.comm, task_info->task.pid); amdgpu_vm_put_task_info(task_info); } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c index 9c169112a5e7..bcde34e4e0a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c @@ -1884,7 +1884,7 @@ static int sdma_v4_4_2_print_iv_entry(struct amdgpu_device *adev, if (task_info) { dev_dbg_ratelimited(adev->dev, " for process %s pid %d thread %s pid %d\n", task_info->process_name, task_info->tgid, - task_info->task_name, task_info->pid); + task_info->task.comm, task_info->task.pid); amdgpu_vm_put_task_info(task_info); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index 2b294ada3ec0..82905f3e54dd 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -1302,7 +1302,7 @@ void kfd_signal_reset_event(struct kfd_node *dev) if (ti) { dev_err(dev->adev->dev, "Queues reset on process %s tid %d thread %s pid %d\n", - ti->process_name, ti->tgid, ti->task_name, ti->pid); + ti->process_name, ti->tgid, ti->task.comm, ti->task.pid); amdgpu_vm_put_task_info(ti); } } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c index 83d9384ac815..a499449fcb06 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_smi_events.c @@ -253,9 +253,9 @@ void kfd_smi_event_update_vmfault(struct kfd_node *dev, uint16_t pasid) task_info = amdgpu_vm_get_task_info_pasid(dev->adev, pasid); if (task_info) { /* Report VM faults from user applications, not retry from kernel */ - if (task_info->pid) + if (task_info->task.pid) kfd_smi_event_add(0, dev, KFD_SMI_EVENT_VMFAULT, KFD_EVENT_FMT_VMFAULT( - task_info->pid, task_info->task_name)); + task_info->task.pid, task_info->task.comm)); amdgpu_vm_put_task_info(task_info); } } @@ -359,8 +359,8 @@ void kfd_smi_event_process(struct kfd_process_device *pdd, bool start) kfd_smi_event_add(0, pdd->dev, start ? KFD_SMI_EVENT_PROCESS_START : KFD_SMI_EVENT_PROCESS_END, - KFD_EVENT_FMT_PROCESS(task_info->pid, - task_info->task_name)); + KFD_EVENT_FMT_PROCESS(task_info->task.pid, + task_info->task.comm)); amdgpu_vm_put_task_info(task_info); } } diff --git a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c index b1e482994ffe..e8662168717d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c +++ b/drivers/gpu/drm/bridge/analogix/analogix-i2c-dptx.c @@ -5,6 +5,8 @@ * Based on anx7808 driver obtained from chromeos with copyright: * Copyright(c) 2013, Google Inc. */ + +#include <linux/export.h> #include <linux/regmap.h> #include <drm/display/drm_dp_helper.h> diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 505eec6b819b..a1bc3e96dd35 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -9,6 +9,7 @@ #include <linux/clk.h> #include <linux/component.h> #include <linux/err.h> +#include <linux/export.h> #include <linux/gpio/consumer.h> #include <linux/interrupt.h> #include <linux/io.h> diff --git a/drivers/gpu/drm/bridge/aux-bridge.c b/drivers/gpu/drm/bridge/aux-bridge.c index 5b219e3b87b1..b63304d3a80f 100644 --- a/drivers/gpu/drm/bridge/aux-bridge.c +++ b/drivers/gpu/drm/bridge/aux-bridge.c @@ -5,6 +5,7 @@ * Author: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> */ #include <linux/auxiliary_bus.h> +#include <linux/export.h> #include <linux/module.h> #include <linux/of.h> diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c index 3eb411f874e4..e579f947e15b 100644 --- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c +++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c @@ -5,6 +5,7 @@ * Author: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> */ #include <linux/auxiliary_bus.h> +#include <linux/export.h> #include <linux/module.h> #include <linux/of.h> diff --git a/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c b/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c index 989bc497b050..0e31d5000e7c 100644 --- a/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c +++ b/drivers/gpu/drm/bridge/imx/imx-legacy-bridge.c @@ -5,6 +5,8 @@ * bridge driver for legacy DT bindings, utilizing display-timings node */ +#include <linux/export.h> + #include <drm/drm_bridge.h> #include <drm/drm_modes.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/bridge/panel.c b/drivers/gpu/drm/bridge/panel.c index 6cbbfb1381a4..6361a943e213 100644 --- a/drivers/gpu/drm/bridge/panel.c +++ b/drivers/gpu/drm/bridge/panel.c @@ -5,6 +5,7 @@ */ #include <linux/debugfs.h> +#include <linux/export.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c index 0014c497e3fe..f2f666b27d2d 100644 --- a/drivers/gpu/drm/bridge/samsung-dsim.c +++ b/drivers/gpu/drm/bridge/samsung-dsim.c @@ -14,6 +14,7 @@ #include <linux/clk.h> #include <linux/delay.h> +#include <linux/export.h> #include <linux/irq.h> #include <linux/media-bus-format.h> #include <linux/of.h> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c index 94dddaf49b3c..7ade80f02a94 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-qp.c @@ -8,6 +8,7 @@ */ #include <linux/completion.h> #include <linux/hdmi.h> +#include <linux/export.h> #include <linux/i2c.h> #include <linux/irq.h> #include <linux/module.h> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 8791408dd1ff..76c6570e2a85 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -9,6 +9,7 @@ #include <linux/clk.h> #include <linux/delay.h> #include <linux/err.h> +#include <linux/export.h> #include <linux/hdmi.h> #include <linux/i2c.h> #include <linux/irq.h> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index c0dc0f2976b9..8fc2e282ff11 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -11,6 +11,7 @@ #include <linux/clk.h> #include <linux/component.h> #include <linux/debugfs.h> +#include <linux/export.h> #include <linux/iopoll.h> #include <linux/math64.h> #include <linux/media-bus-format.h> diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c index fc91aca95d12..5926a3a05d79 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi2.c @@ -9,6 +9,7 @@ #include <linux/bitfield.h> #include <linux/clk.h> +#include <linux/export.h> #include <linux/iopoll.h> #include <linux/media-bus-format.h> #include <linux/module.h> diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 60224f476e1d..78a50b947a08 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -447,23 +447,6 @@ DEFINE_SHOW_ATTRIBUTE(status); * Auxiliary Devices (*not* AUX) */ -static void ti_sn65dsi86_uninit_aux(void *data) -{ - auxiliary_device_uninit(data); -} - -static void ti_sn65dsi86_delete_aux(void *data) -{ - auxiliary_device_delete(data); -} - -static void ti_sn65dsi86_aux_device_release(struct device *dev) -{ - struct auxiliary_device *aux = container_of(dev, struct auxiliary_device, dev); - - kfree(aux); -} - static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata, struct auxiliary_device **aux_out, const char *name) @@ -471,34 +454,16 @@ static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata, struct device *dev = pdata->dev; const struct i2c_client *client = to_i2c_client(dev); struct auxiliary_device *aux; - int ret; + int id; - aux = kzalloc(sizeof(*aux), GFP_KERNEL); + id = (client->adapter->nr << 10) | client->addr; + aux = __devm_auxiliary_device_create(dev, KBUILD_MODNAME, name, + NULL, id); if (!aux) - return -ENOMEM; - - aux->name = name; - aux->id = (client->adapter->nr << 10) | client->addr; - aux->dev.parent = dev; - aux->dev.release = ti_sn65dsi86_aux_device_release; - device_set_of_node_from_dev(&aux->dev, dev); - ret = auxiliary_device_init(aux); - if (ret) { - kfree(aux); - return ret; - } - ret = devm_add_action_or_reset(dev, ti_sn65dsi86_uninit_aux, aux); - if (ret) - return ret; - - ret = auxiliary_device_add(aux); - if (ret) - return ret; - ret = devm_add_action_or_reset(dev, ti_sn65dsi86_delete_aux, aux); - if (!ret) - *aux_out = aux; + return -ENODEV; - return ret; + *aux_out = aux; + return 0; } /* ----------------------------------------------------------------------------- @@ -1707,24 +1672,20 @@ static int ti_sn_bridge_gpio_get(struct gpio_chip *chip, unsigned int offset) return !!(val & BIT(SN_GPIO_INPUT_SHIFT + offset)); } -static void ti_sn_bridge_gpio_set(struct gpio_chip *chip, unsigned int offset, - int val) +static int ti_sn_bridge_gpio_set(struct gpio_chip *chip, unsigned int offset, + int val) { struct ti_sn65dsi86 *pdata = gpiochip_get_data(chip); - int ret; if (!test_bit(offset, pdata->gchip_output)) { dev_err(pdata->dev, "Ignoring GPIO set while input\n"); - return; + return -EPERM; } val &= 1; - ret = regmap_update_bits(pdata->regmap, SN_GPIO_IO_REG, - BIT(SN_GPIO_OUTPUT_SHIFT + offset), - val << (SN_GPIO_OUTPUT_SHIFT + offset)); - if (ret) - dev_warn(pdata->dev, - "Failed to set bridge GPIO %u: %d\n", offset, ret); + return regmap_update_bits(pdata->regmap, SN_GPIO_IO_REG, + BIT(SN_GPIO_OUTPUT_SHIFT + offset), + val << (SN_GPIO_OUTPUT_SHIFT + offset)); } static int ti_sn_bridge_gpio_direction_input(struct gpio_chip *chip, @@ -1828,7 +1789,7 @@ static int ti_sn_gpio_probe(struct auxiliary_device *adev, pdata->gchip.direction_input = ti_sn_bridge_gpio_direction_input; pdata->gchip.direction_output = ti_sn_bridge_gpio_direction_output; pdata->gchip.get = ti_sn_bridge_gpio_get; - pdata->gchip.set = ti_sn_bridge_gpio_set; + pdata->gchip.set_rv = ti_sn_bridge_gpio_set; pdata->gchip.can_sleep = true; pdata->gchip.names = ti_sn_bridge_gpio_names; pdata->gchip.ngpio = SN_NUM_GPIOS; diff --git a/drivers/gpu/drm/clients/drm_client_setup.c b/drivers/gpu/drm/clients/drm_client_setup.c index e17265039ca8..aec2fab6d2bf 100644 --- a/drivers/gpu/drm/clients/drm_client_setup.c +++ b/drivers/gpu/drm/clients/drm_client_setup.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT +#include <linux/export.h> + #include <drm/clients/drm_client_setup.h> #include <drm/drm_device.h> #include <drm/drm_fourcc.h> diff --git a/drivers/gpu/drm/display/drm_bridge_connector.c b/drivers/gpu/drm/display/drm_bridge_connector.c index 58846e26f1e1..6cdb432dbc30 100644 --- a/drivers/gpu/drm/display/drm_bridge_connector.c +++ b/drivers/gpu/drm/display/drm_bridge_connector.c @@ -3,6 +3,7 @@ * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com> */ +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> diff --git a/drivers/gpu/drm/display/drm_dp_aux_bus.c b/drivers/gpu/drm/display/drm_dp_aux_bus.c index ec7eac6b595f..7b9afcf48836 100644 --- a/drivers/gpu/drm/display/drm_dp_aux_bus.c +++ b/drivers/gpu/drm/display/drm_dp_aux_bus.c @@ -12,6 +12,7 @@ * to perform transactions on that bus. */ +#include <linux/export.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/module.h> diff --git a/drivers/gpu/drm/display/drm_dp_cec.c b/drivers/gpu/drm/display/drm_dp_cec.c index ed31471bd0e2..3b50d817c839 100644 --- a/drivers/gpu/drm/display/drm_dp_cec.c +++ b/drivers/gpu/drm/display/drm_dp_cec.c @@ -5,6 +5,7 @@ * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved. */ +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> diff --git a/drivers/gpu/drm/display/drm_dp_helper.c b/drivers/gpu/drm/display/drm_dp_helper.c index f2a6559a2710..896bba2adb3b 100644 --- a/drivers/gpu/drm/display/drm_dp_helper.c +++ b/drivers/gpu/drm/display/drm_dp_helper.c @@ -24,6 +24,7 @@ #include <linux/delay.h> #include <linux/dynamic_debug.h> #include <linux/errno.h> +#include <linux/export.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/iopoll.h> diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c index a89f38fd3218..64e5c176d5cc 100644 --- a/drivers/gpu/drm/display/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c @@ -23,6 +23,7 @@ #include <linux/bitfield.h> #include <linux/delay.h> #include <linux/errno.h> +#include <linux/export.h> #include <linux/i2c.h> #include <linux/init.h> #include <linux/kernel.h> diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c b/drivers/gpu/drm/display/drm_dp_tunnel.c index 076edf161048..8a4ef5438f35 100644 --- a/drivers/gpu/drm/display/drm_dp_tunnel.c +++ b/drivers/gpu/drm/display/drm_dp_tunnel.c @@ -3,6 +3,7 @@ * Copyright © 2023 Intel Corporation */ +#include <linux/export.h> #include <linux/ref_tracker.h> #include <linux/types.h> diff --git a/drivers/gpu/drm/display/drm_dsc_helper.c b/drivers/gpu/drm/display/drm_dsc_helper.c index 6900f4dac520..05996c526a8a 100644 --- a/drivers/gpu/drm/display/drm_dsc_helper.c +++ b/drivers/gpu/drm/display/drm_dsc_helper.c @@ -6,6 +6,7 @@ * Manasi Navare <manasi.d.navare@intel.com> */ +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> diff --git a/drivers/gpu/drm/display/drm_hdmi_audio_helper.c b/drivers/gpu/drm/display/drm_hdmi_audio_helper.c index f165166afb2d..7d78b02c1446 100644 --- a/drivers/gpu/drm/display/drm_hdmi_audio_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_audio_helper.c @@ -3,6 +3,7 @@ * Copyright (c) 2024 Linaro Ltd */ +#include <linux/export.h> #include <linux/mutex.h> #include <linux/of_graph.h> #include <linux/platform_device.h> diff --git a/drivers/gpu/drm/display/drm_hdmi_cec_helper.c b/drivers/gpu/drm/display/drm_hdmi_cec_helper.c index a25f60509043..b4273c3522fa 100644 --- a/drivers/gpu/drm/display/drm_hdmi_cec_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_cec_helper.c @@ -8,6 +8,7 @@ #include <drm/drm_managed.h> #include <drm/display/drm_hdmi_cec_helper.h> +#include <linux/export.h> #include <linux/mutex.h> #include <media/cec.h> diff --git a/drivers/gpu/drm/display/drm_hdmi_cec_notifier_helper.c b/drivers/gpu/drm/display/drm_hdmi_cec_notifier_helper.c index 28f8e008cc59..31b8e4a93e24 100644 --- a/drivers/gpu/drm/display/drm_hdmi_cec_notifier_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_cec_notifier_helper.c @@ -8,6 +8,7 @@ #include <drm/drm_managed.h> #include <drm/display/drm_hdmi_cec_helper.h> +#include <linux/export.h> #include <linux/mutex.h> #include <media/cec.h> diff --git a/drivers/gpu/drm/display/drm_hdmi_helper.c b/drivers/gpu/drm/display/drm_hdmi_helper.c index 855cb02b827d..6063c155bdea 100644 --- a/drivers/gpu/drm/display/drm_hdmi_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_helper.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT +#include <linux/export.h> #include <linux/module.h> #include <drm/display/drm_hdmi_helper.h> diff --git a/drivers/gpu/drm/display/drm_hdmi_state_helper.c b/drivers/gpu/drm/display/drm_hdmi_state_helper.c index 2c641add7434..a561f124be99 100644 --- a/drivers/gpu/drm/display/drm_hdmi_state_helper.c +++ b/drivers/gpu/drm/display/drm_hdmi_state_helper.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: MIT +#include <linux/export.h> + #include <drm/drm_atomic.h> #include <drm/drm_connector.h> #include <drm/drm_edid.h> diff --git a/drivers/gpu/drm/display/drm_scdc_helper.c b/drivers/gpu/drm/display/drm_scdc_helper.c index 6d2f244e5830..df878aad4a36 100644 --- a/drivers/gpu/drm/display/drm_scdc_helper.c +++ b/drivers/gpu/drm/display/drm_scdc_helper.c @@ -21,6 +21,7 @@ * DEALINGS IN THE SOFTWARE. */ +#include <linux/export.h> #include <linux/i2c.h> #include <linux/slab.h> #include <linux/delay.h> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 0138cf0b8b63..cd15cf52f0c9 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -26,7 +26,7 @@ * Daniel Vetter <daniel.vetter@ffwll.ch> */ - +#include <linux/export.h> #include <linux/sync_file.h> #include <drm/drm_atomic.h> diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2fe6c91910a1..ef56b474acf5 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -25,6 +25,7 @@ * Daniel Vetter <daniel.vetter@ffwll.ch> */ +#include <linux/export.h> #include <linux/dma-fence.h> #include <linux/ktime.h> diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 519228eb1095..7142e163e618 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -37,6 +37,7 @@ #include <drm/drm_vblank.h> #include <drm/drm_writeback.h> +#include <linux/export.h> #include <linux/slab.h> #include <linux/dma-fence.h> diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index c2726af6698e..ecc73d52bfae 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -36,6 +36,7 @@ #include <drm/drm_writeback.h> #include <drm/drm_vblank.h> +#include <linux/export.h> #include <linux/dma-fence.h> #include <linux/uaccess.h> #include <linux/sync_file.h> diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index d6bf605b4b90..a2556d16bed6 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -28,6 +28,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include <linux/export.h> #include <linux/slab.h> #include <drm/drm_auth.h> diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index bf34cc5ab031..d6ce7b4c019f 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -23,6 +23,7 @@ #include <linux/debugfs.h> #include <linux/err.h> +#include <linux/export.h> #include <linux/media-bus-format.h> #include <linux/module.h> #include <linux/mutex.h> diff --git a/drivers/gpu/drm/drm_bridge_helper.c b/drivers/gpu/drm/drm_bridge_helper.c index af80d2496194..420f29cf3e54 100644 --- a/drivers/gpu/drm/drm_bridge_helper.c +++ b/drivers/gpu/drm/drm_bridge_helper.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later +#include <linux/export.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> diff --git a/drivers/gpu/drm/drm_buddy.c b/drivers/gpu/drm/drm_buddy.c index 241c855f891f..a1e652b7631d 100644 --- a/drivers/gpu/drm/drm_buddy.c +++ b/drivers/gpu/drm/drm_buddy.c @@ -5,6 +5,7 @@ #include <kunit/test-bug.h> +#include <linux/export.h> #include <linux/kmemleak.h> #include <linux/module.h> #include <linux/sizes.h> diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index f7197a07c045..3fa38d4ac70b 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -3,6 +3,7 @@ * Copyright 2018 Noralf Trønnes */ +#include <linux/export.h> #include <linux/iosys-map.h> #include <linux/list.h> #include <linux/mutex.h> diff --git a/drivers/gpu/drm/drm_client_event.c b/drivers/gpu/drm/drm_client_event.c index bd93cd93d519..c83196ad8b59 100644 --- a/drivers/gpu/drm/drm_client_event.c +++ b/drivers/gpu/drm/drm_client_event.c @@ -3,6 +3,7 @@ * Copyright 2018 Noralf Trønnes */ +#include <linux/export.h> #include <linux/list.h> #include <linux/mutex.h> #include <linux/seq_file.h> diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c index 0f9d5ba36c81..9c2c3b0c8c47 100644 --- a/drivers/gpu/drm/drm_client_modeset.c +++ b/drivers/gpu/drm/drm_client_modeset.c @@ -8,6 +8,8 @@ */ #include "drm/drm_modeset_lock.h" + +#include <linux/export.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/slab.h> diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index 5399c111c51f..37a3270bc3c2 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include <linux/export.h> #include <linux/uaccess.h> #include <drm/drm_atomic.h> diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 395e1bf006bd..0167e0e0d425 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -33,6 +33,7 @@ #include <drm/drm_sysfs.h> #include <drm/drm_utils.h> +#include <linux/export.h> #include <linux/platform_device.h> #include <linux/property.h> #include <linux/uaccess.h> diff --git a/drivers/gpu/drm/drm_damage_helper.c b/drivers/gpu/drm/drm_damage_helper.c index 44a5a36806e3..6a49e7a0ab84 100644 --- a/drivers/gpu/drm/drm_damage_helper.c +++ b/drivers/gpu/drm/drm_damage_helper.c @@ -30,6 +30,8 @@ * **************************************************************************/ +#include <linux/export.h> + #include <drm/drm_atomic.h> #include <drm/drm_damage_helper.h> #include <drm/drm_device.h> diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index bbc3bc4ba844..6b43b1cf2327 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -29,6 +29,7 @@ #include <linux/circ_buf.h> #include <linux/ctype.h> #include <linux/debugfs.h> +#include <linux/export.h> #include <linux/poll.h> #include <linux/uaccess.h> diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 56dd61f8e05a..02556363e918 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -29,11 +29,13 @@ #include <linux/bitops.h> #include <linux/cgroup_dmem.h> #include <linux/debugfs.h> +#include <linux/export.h> #include <linux/fs.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/mount.h> #include <linux/pseudo_fs.h> +#include <linux/sched.h> #include <linux/slab.h> #include <linux/sprintf.h> #include <linux/srcu.h> @@ -538,10 +540,15 @@ static const char *drm_get_wedge_recovery(unsigned int opt) } } +#define WEDGE_STR_LEN 32 +#define PID_STR_LEN 15 +#define COMM_STR_LEN (TASK_COMM_LEN + 5) + /** * drm_dev_wedged_event - generate a device wedged uevent * @dev: DRM device * @method: method(s) to be used for recovery + * @info: optional information about the guilty task * * This generates a device wedged uevent for the DRM device specified by @dev. * Recovery @method\(s) of choice will be sent in the uevent environment as @@ -554,13 +561,13 @@ static const char *drm_get_wedge_recovery(unsigned int opt) * * Returns: 0 on success, negative error code otherwise. */ -int drm_dev_wedged_event(struct drm_device *dev, unsigned long method) +int drm_dev_wedged_event(struct drm_device *dev, unsigned long method, + struct drm_wedge_task_info *info) { + char event_string[WEDGE_STR_LEN], pid_string[PID_STR_LEN], comm_string[COMM_STR_LEN]; + char *envp[] = { event_string, NULL, NULL, NULL }; const char *recovery = NULL; unsigned int len, opt; - /* Event string length up to 28+ characters with available methods */ - char event_string[32]; - char *envp[] = { event_string, NULL }; len = scnprintf(event_string, sizeof(event_string), "%s", "WEDGED="); @@ -582,6 +589,13 @@ int drm_dev_wedged_event(struct drm_device *dev, unsigned long method) drm_info(dev, "device wedged, %s\n", method == DRM_WEDGE_RECOVERY_NONE ? "but recovered through reset" : "needs recovery"); + if (info && (info->comm[0] != '\0') && (info->pid >= 0)) { + snprintf(pid_string, sizeof(pid_string), "PID=%u", info->pid); + snprintf(comm_string, sizeof(comm_string), "TASK=%s", info->comm); + envp[1] = pid_string; + envp[2] = comm_string; + } + return kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); } EXPORT_SYMBOL(drm_dev_wedged_event); diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 74e77742b2bd..4b4f27896161 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -31,6 +31,7 @@ #include <linux/bitfield.h> #include <linux/byteorder/generic.h> #include <linux/cec.h> +#include <linux/export.h> #include <linux/hdmi.h> #include <linux/i2c.h> #include <linux/kernel.h> diff --git a/drivers/gpu/drm/drm_exec.c b/drivers/gpu/drm/drm_exec.c index 18e366cc4993..8d0601400182 100644 --- a/drivers/gpu/drm/drm_exec.c +++ b/drivers/gpu/drm/drm_exec.c @@ -2,7 +2,9 @@ #include <drm/drm_exec.h> #include <drm/drm_gem.h> + #include <linux/dma-resv.h> +#include <linux/export.h> /** * DOC: Overview diff --git a/drivers/gpu/drm/drm_fb_dma_helper.c b/drivers/gpu/drm/drm_fb_dma_helper.c index 2c4dc7ebc0c3..fd71969d2fb1 100644 --- a/drivers/gpu/drm/drm_fb_dma_helper.c +++ b/drivers/gpu/drm/drm_fb_dma_helper.c @@ -17,7 +17,9 @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_panic.h> #include <drm/drm_plane.h> + #include <linux/dma-mapping.h> +#include <linux/export.h> #include <linux/module.h> /** diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 937c3939e502..11a5b60cb9ce 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -30,6 +30,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/console.h> +#include <linux/export.h> #include <linux/pci.h> #include <linux/sysrq.h> #include <linux/vga_switcheroo.h> diff --git a/drivers/gpu/drm/drm_fbdev_dma.c b/drivers/gpu/drm/drm_fbdev_dma.c index 02a516e77192..8bd626ef16c7 100644 --- a/drivers/gpu/drm/drm_fbdev_dma.c +++ b/drivers/gpu/drm/drm_fbdev_dma.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT +#include <linux/export.h> #include <linux/fb.h> #include <linux/vmalloc.h> diff --git a/drivers/gpu/drm/drm_fbdev_shmem.c b/drivers/gpu/drm/drm_fbdev_shmem.c index f824369baacd..1e827bf8b815 100644 --- a/drivers/gpu/drm/drm_fbdev_shmem.c +++ b/drivers/gpu/drm/drm_fbdev_shmem.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT +#include <linux/export.h> #include <linux/fb.h> #include <drm/drm_drv.h> diff --git a/drivers/gpu/drm/drm_fbdev_ttm.c b/drivers/gpu/drm/drm_fbdev_ttm.c index 73d35d59590c..85feb55bba11 100644 --- a/drivers/gpu/drm/drm_fbdev_ttm.c +++ b/drivers/gpu/drm/drm_fbdev_ttm.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT +#include <linux/export.h> #include <linux/moduleparam.h> #include <linux/vmalloc.h> diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 818630ba6e0d..3952e27447ee 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -33,6 +33,7 @@ #include <linux/anon_inodes.h> #include <linux/dma-fence.h> +#include <linux/export.h> #include <linux/file.h> #include <linux/module.h> #include <linux/pci.h> diff --git a/drivers/gpu/drm/drm_flip_work.c b/drivers/gpu/drm/drm_flip_work.c index 8c6090a90d56..f5889dd8e7aa 100644 --- a/drivers/gpu/drm/drm_flip_work.c +++ b/drivers/gpu/drm/drm_flip_work.c @@ -21,6 +21,7 @@ * SOFTWARE. */ +#include <linux/export.h> #include <linux/slab.h> #include <drm/drm_flip_work.h> diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index d36e6cacc575..99d9f7bbc261 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -8,6 +8,7 @@ * (at your option) any later version. */ +#include <linux/export.h> #include <linux/io.h> #include <linux/iosys-map.h> #include <linux/module.h> @@ -857,11 +858,33 @@ static void drm_fb_xrgb8888_to_abgr8888_line(void *dbuf, const void *sbuf, unsig drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_abgr8888); } -static void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *src, - const struct drm_framebuffer *fb, - const struct drm_rect *clip, - struct drm_format_conv_state *state) +/** + * drm_fb_xrgb8888_to_abgr8888 - Convert XRGB8888 to ABGR8888 clip buffer + * @dst: Array of ABGR8888 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * @state: Transform and conversion state + * + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. The parameters @dst, @dst_pitch and @src refer + * to arrays. Each array must have at least as many entries as there are planes in + * @fb's format. Each entry stores the value for the format's respective color plane + * at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for ABGR8888 devices that don't support XRGB8888 + * natively. It sets an opaque alpha channel as part of the conversion. + */ +void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, + const struct drm_framebuffer *fb, + const struct drm_rect *clip, + struct drm_format_conv_state *state) { static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 4, @@ -870,17 +893,40 @@ static void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned in drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, drm_fb_xrgb8888_to_abgr8888_line); } +EXPORT_SYMBOL(drm_fb_xrgb8888_to_abgr8888); static void drm_fb_xrgb8888_to_xbgr8888_line(void *dbuf, const void *sbuf, unsigned int pixels) { drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_xbgr8888); } -static void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, - const struct iosys_map *src, - const struct drm_framebuffer *fb, - const struct drm_rect *clip, - struct drm_format_conv_state *state) +/** + * drm_fb_xrgb8888_to_xbgr8888 - Convert XRGB8888 to XBGR8888 clip buffer + * @dst: Array of XBGR8888 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * @state: Transform and conversion state + * + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. The parameters @dst, @dst_pitch and @src refer + * to arrays. Each array must have at least as many entries as there are planes in + * @fb's format. Each entry stores the value for the format's respective color plane + * at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for XBGR8888 devices that don't support XRGB8888 + * natively. + */ +void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, + const struct drm_framebuffer *fb, + const struct drm_rect *clip, + struct drm_format_conv_state *state) { static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { 4, @@ -889,6 +935,49 @@ static void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned in drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, drm_fb_xrgb8888_to_xbgr8888_line); } +EXPORT_SYMBOL(drm_fb_xrgb8888_to_xbgr8888); + +static void drm_fb_xrgb8888_to_bgrx8888_line(void *dbuf, const void *sbuf, unsigned int pixels) +{ + drm_fb_xfrm_line_32to32(dbuf, sbuf, pixels, drm_pixel_xrgb8888_to_bgrx8888); +} + +/** + * drm_fb_xrgb8888_to_bgrx8888 - Convert XRGB8888 to BGRX8888 clip buffer + * @dst: Array of BGRX8888 destination buffers + * @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines + * within @dst; can be NULL if scanlines are stored next to each other. + * @src: Array of XRGB8888 source buffer + * @fb: DRM framebuffer + * @clip: Clip rectangle area to copy + * @state: Transform and conversion state + * + * This function copies parts of a framebuffer to display memory and converts the + * color format during the process. The parameters @dst, @dst_pitch and @src refer + * to arrays. Each array must have at least as many entries as there are planes in + * @fb's format. Each entry stores the value for the format's respective color plane + * at the same index. + * + * This function does not apply clipping on @dst (i.e. the destination is at the + * top-left corner). + * + * Drivers can use this function for BGRX8888 devices that don't support XRGB8888 + * natively. + */ +void drm_fb_xrgb8888_to_bgrx8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, + const struct drm_framebuffer *fb, + const struct drm_rect *clip, + struct drm_format_conv_state *state) +{ + static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = { + 4, + }; + + drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, state, + drm_fb_xrgb8888_to_bgrx8888_line); +} +EXPORT_SYMBOL(drm_fb_xrgb8888_to_bgrx8888); static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels) { @@ -1250,141 +1339,3 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc } } EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono); - -static uint32_t drm_fb_nonalpha_fourcc(uint32_t fourcc) -{ - /* only handle formats with depth != 0 and alpha channel */ - switch (fourcc) { - case DRM_FORMAT_ARGB1555: - return DRM_FORMAT_XRGB1555; - case DRM_FORMAT_ABGR1555: - return DRM_FORMAT_XBGR1555; - case DRM_FORMAT_RGBA5551: - return DRM_FORMAT_RGBX5551; - case DRM_FORMAT_BGRA5551: - return DRM_FORMAT_BGRX5551; - case DRM_FORMAT_ARGB8888: - return DRM_FORMAT_XRGB8888; - case DRM_FORMAT_ABGR8888: - return DRM_FORMAT_XBGR8888; - case DRM_FORMAT_RGBA8888: - return DRM_FORMAT_RGBX8888; - case DRM_FORMAT_BGRA8888: - return DRM_FORMAT_BGRX8888; - case DRM_FORMAT_ARGB2101010: - return DRM_FORMAT_XRGB2101010; - case DRM_FORMAT_ABGR2101010: - return DRM_FORMAT_XBGR2101010; - case DRM_FORMAT_RGBA1010102: - return DRM_FORMAT_RGBX1010102; - case DRM_FORMAT_BGRA1010102: - return DRM_FORMAT_BGRX1010102; - } - - return fourcc; -} - -static bool is_listed_fourcc(const uint32_t *fourccs, size_t nfourccs, uint32_t fourcc) -{ - const uint32_t *fourccs_end = fourccs + nfourccs; - - while (fourccs < fourccs_end) { - if (*fourccs == fourcc) - return true; - ++fourccs; - } - return false; -} - -/** - * drm_fb_build_fourcc_list - Filters a list of supported color formats against - * the device's native formats - * @dev: DRM device - * @native_fourccs: 4CC codes of natively supported color formats - * @native_nfourccs: The number of entries in @native_fourccs - * @fourccs_out: Returns 4CC codes of supported color formats - * @nfourccs_out: The number of available entries in @fourccs_out - * - * This function create a list of supported color format from natively - * supported formats and additional emulated formats. - * At a minimum, most userspace programs expect at least support for - * XRGB8888 on the primary plane. Devices that have to emulate the - * format, and possibly others, can use drm_fb_build_fourcc_list() to - * create a list of supported color formats. The returned list can - * be handed over to drm_universal_plane_init() et al. Native formats - * will go before emulated formats. Native formats with alpha channel - * will be replaced by such without, as primary planes usually don't - * support alpha. Other heuristics might be applied - * to optimize the order. Formats near the beginning of the list are - * usually preferred over formats near the end of the list. - * - * Returns: - * The number of color-formats 4CC codes returned in @fourccs_out. - */ -size_t drm_fb_build_fourcc_list(struct drm_device *dev, - const u32 *native_fourccs, size_t native_nfourccs, - u32 *fourccs_out, size_t nfourccs_out) -{ - /* - * XRGB8888 is the default fallback format for most of userspace - * and it's currently the only format that should be emulated for - * the primary plane. Only if there's ever another default fallback, - * it should be added here. - */ - static const uint32_t extra_fourccs[] = { - DRM_FORMAT_XRGB8888, - }; - static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs); - - u32 *fourccs = fourccs_out; - const u32 *fourccs_end = fourccs_out + nfourccs_out; - size_t i; - - /* - * The device's native formats go first. - */ - - for (i = 0; i < native_nfourccs; ++i) { - /* - * Several DTs, boot loaders and firmware report native - * alpha formats that are non-alpha formats instead. So - * replace alpha formats by non-alpha formats. - */ - u32 fourcc = drm_fb_nonalpha_fourcc(native_fourccs[i]); - - if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { - continue; /* skip duplicate entries */ - } else if (fourccs == fourccs_end) { - drm_warn(dev, "Ignoring native format %p4cc\n", &fourcc); - continue; /* end of available output buffer */ - } - - drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc); - - *fourccs = fourcc; - ++fourccs; - } - - /* - * The extra formats, emulated by the driver, go second. - */ - - for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) { - u32 fourcc = extra_fourccs[i]; - - if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { - continue; /* skip duplicate and native entries */ - } else if (fourccs == fourccs_end) { - drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc); - continue; /* end of available output buffer */ - } - - drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc); - - *fourccs = fourcc; - ++fourccs; - } - - return fourccs - fourccs_out; -} -EXPORT_SYMBOL(drm_fb_build_fourcc_list); diff --git a/drivers/gpu/drm/drm_format_internal.h b/drivers/gpu/drm/drm_format_internal.h index 9f857bfa368d..9428d5cfebc5 100644 --- a/drivers/gpu/drm/drm_format_internal.h +++ b/drivers/gpu/drm/drm_format_internal.h @@ -42,7 +42,7 @@ static inline u32 drm_pixel_xrgb8888_to_r8_bt601(u32 pix) u32 b = pix & 0x000000ff; /* ITU-R BT.601: Y = 0.299 R + 0.587 G + 0.114 B */ - return (3 * r + 6 * g + b) / 10; + return (77 * r + 150 * g + 29 * b) / 256; } static inline u32 drm_pixel_xrgb8888_to_rgb332(u32 pix) @@ -111,6 +111,14 @@ static inline u32 drm_pixel_xrgb8888_to_xbgr8888(u32 pix) ((pix & 0x000000ff) << 16); } +static inline u32 drm_pixel_xrgb8888_to_bgrx8888(u32 pix) +{ + return ((pix & 0xff000000) >> 24) | /* also copy filler bits */ + ((pix & 0x00ff0000) >> 8) | + ((pix & 0x0000ff00) << 8) | + ((pix & 0x000000ff) << 24); +} + static inline u32 drm_pixel_xrgb8888_to_abgr8888(u32 pix) { return GENMASK(31, 24) | /* fill alpha bits */ diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index a0a3b6baa569..19d50d254fe6 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -26,6 +26,7 @@ */ #include <linux/dma-buf.h> +#include <linux/export.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/iosys-map.h> diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c index 93337543aac3..ebf305fb24f0 100644 --- a/drivers/gpu/drm/drm_gem_atomic_helper.c +++ b/drivers/gpu/drm/drm_gem_atomic_helper.c @@ -2,6 +2,7 @@ #include <linux/dma-resv.h> #include <linux/dma-fence-chain.h> +#include <linux/export.h> #include <drm/drm_atomic_state_helper.h> #include <drm/drm_atomic_uapi.h> diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index baf99a68bdb5..618ce725cd75 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -5,6 +5,7 @@ * Copyright (C) 2017 Noralf Trønnes */ +#include <linux/export.h> #include <linux/slab.h> #include <linux/module.h> diff --git a/drivers/gpu/drm/drm_gem_ttm_helper.c b/drivers/gpu/drm/drm_gem_ttm_helper.c index 3734aa2d1c5b..257cca4cb97a 100644 --- a/drivers/gpu/drm/drm_gem_ttm_helper.c +++ b/drivers/gpu/drm/drm_gem_ttm_helper.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later +#include <linux/export.h> #include <linux/module.h> #include <drm/drm_gem_ttm_helper.h> diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index ead50fef5e7d..b04cde4a60e7 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later +#include <linux/export.h> #include <linux/iosys-map.h> #include <linux/module.h> diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index 7ff81aa0a1ca..ab198645d90f 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -7,6 +7,7 @@ */ #include <linux/dma-mapping.h> +#include <linux/export.h> #include <linux/hmm.h> #include <linux/memremap.h> #include <linux/migrate.h> diff --git a/drivers/gpu/drm/drm_gpuvm.c b/drivers/gpu/drm/drm_gpuvm.c index f9eb56f24bef..e89b932e987c 100644 --- a/drivers/gpu/drm/drm_gpuvm.c +++ b/drivers/gpu/drm/drm_gpuvm.c @@ -27,6 +27,7 @@ #include <drm/drm_gpuvm.h> +#include <linux/export.h> #include <linux/interval_tree_generic.h> #include <linux/mm.h> diff --git a/drivers/gpu/drm/drm_managed.c b/drivers/gpu/drm/drm_managed.c index cc4c463daae7..247f468731de 100644 --- a/drivers/gpu/drm/drm_managed.c +++ b/drivers/gpu/drm/drm_managed.c @@ -7,6 +7,7 @@ #include <drm/drm_managed.h> +#include <linux/export.h> #include <linux/list.h> #include <linux/mutex.h> #include <linux/slab.h> diff --git a/drivers/gpu/drm/drm_mipi_dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index a4cd476f9b30..ba4be6be5d28 100644 --- a/drivers/gpu/drm/drm_mipi_dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -8,6 +8,7 @@ #include <linux/backlight.h> #include <linux/debugfs.h> #include <linux/delay.h> +#include <linux/export.h> #include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/regulator/consumer.h> diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index e5184a0c2465..a00d76443128 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -26,6 +26,7 @@ */ #include <linux/device.h> +#include <linux/export.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_device.h> diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index b4239fd04e9d..25f376869b3a 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include <linux/export.h> #include <linux/uaccess.h> #include <drm/drm_drv.h> diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index 5565464c1734..ef32f6af10d4 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -20,6 +20,8 @@ * OF THIS SOFTWARE. */ +#include <linux/export.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_client_event.h> #include <drm/drm_fourcc.h> diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c index 7694b85e75e3..beb91a13a312 100644 --- a/drivers/gpu/drm/drm_modeset_lock.c +++ b/drivers/gpu/drm/drm_modeset_lock.c @@ -21,6 +21,8 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include <linux/export.h> + #include <drm/drm_atomic.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c index 805b4151ccef..c8bb28dccdc1 100644 --- a/drivers/gpu/drm/drm_panel.c +++ b/drivers/gpu/drm/drm_panel.c @@ -23,6 +23,7 @@ #include <linux/backlight.h> #include <linux/err.h> +#include <linux/export.h> #include <linux/module.h> #include <linux/of.h> diff --git a/drivers/gpu/drm/drm_panel_backlight_quirks.c b/drivers/gpu/drm/drm_panel_backlight_quirks.c index c477d98ade2b..598f812b7cb3 100644 --- a/drivers/gpu/drm/drm_panel_backlight_quirks.c +++ b/drivers/gpu/drm/drm_panel_backlight_quirks.c @@ -2,6 +2,7 @@ #include <linux/array_size.h> #include <linux/dmi.h> +#include <linux/export.h> #include <linux/mod_devicetable.h> #include <linux/module.h> #include <drm/drm_edid.h> diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 7ac0fd5391fe..3a218fb592ce 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -9,6 +9,7 @@ */ #include <linux/dmi.h> +#include <linux/export.h> #include <linux/module.h> #include <drm/drm_connector.h> #include <drm/drm_utils.h> diff --git a/drivers/gpu/drm/drm_panic.c b/drivers/gpu/drm/drm_panic.c index b4de79583805..1d6312fa1429 100644 --- a/drivers/gpu/drm/drm_panic.c +++ b/drivers/gpu/drm/drm_panic.c @@ -6,6 +6,7 @@ * Tux Ascii art taken from cowsay written by Tony Monroe */ +#include <linux/export.h> #include <linux/font.h> #include <linux/highmem.h> #include <linux/init.h> diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index c585f1e8803e..cb0f68d7f8ea 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -23,7 +23,6 @@ */ #include <linux/dma-mapping.h> -#include <linux/export.h> #include <linux/list.h> #include <linux/mutex.h> #include <linux/pci.h> diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 04992dfd4c79..38f82391bfda 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -20,6 +20,7 @@ * OF THIS SOFTWARE. */ +#include <linux/export.h> #include <linux/slab.h> #include <linux/uaccess.h> diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 7982be4b0306..747d248aaf02 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -23,6 +23,7 @@ * SOFTWARE. */ +#include <linux/export.h> #include <linux/list.h> #include <drm/drm_atomic.h> diff --git a/drivers/gpu/drm/drm_print.c b/drivers/gpu/drm/drm_print.c index 79517bd4418f..ded9461df5f2 100644 --- a/drivers/gpu/drm/drm_print.c +++ b/drivers/gpu/drm/drm_print.c @@ -25,6 +25,7 @@ #include <linux/debugfs.h> #include <linux/dynamic_debug.h> +#include <linux/export.h> #include <linux/io.h> #include <linux/moduleparam.h> #include <linux/seq_file.h> diff --git a/drivers/gpu/drm/drm_privacy_screen.c b/drivers/gpu/drm/drm_privacy_screen.c index 6cc39e30781f..8959f7084e0b 100644 --- a/drivers/gpu/drm/drm_privacy_screen.c +++ b/drivers/gpu/drm/drm_privacy_screen.c @@ -7,6 +7,7 @@ */ #include <linux/device.h> +#include <linux/export.h> #include <linux/kernel.h> #include <linux/list.h> #include <linux/module.h> diff --git a/drivers/gpu/drm/drm_self_refresh_helper.c b/drivers/gpu/drm/drm_self_refresh_helper.c index dd33fec5aabd..c0948586b7fd 100644 --- a/drivers/gpu/drm/drm_self_refresh_helper.c +++ b/drivers/gpu/drm/drm_self_refresh_helper.c @@ -7,6 +7,7 @@ */ #include <linux/average.h> #include <linux/bitops.h> +#include <linux/export.h> #include <linux/slab.h> #include <linux/workqueue.h> diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c index 250819fbc5ce..fcbcaaa36b5f 100644 --- a/drivers/gpu/drm/drm_simple_kms_helper.c +++ b/drivers/gpu/drm/drm_simple_kms_helper.c @@ -3,6 +3,7 @@ * Copyright (C) 2016 Noralf Trønnes */ +#include <linux/export.h> #include <linux/module.h> #include <linux/slab.h> diff --git a/drivers/gpu/drm/drm_suballoc.c b/drivers/gpu/drm/drm_suballoc.c index 38cc7a123819..879ea33dbbc4 100644 --- a/drivers/gpu/drm/drm_suballoc.c +++ b/drivers/gpu/drm/drm_suballoc.c @@ -42,6 +42,8 @@ #include <drm/drm_suballoc.h> #include <drm/drm_print.h> + +#include <linux/export.h> #include <linux/slab.h> #include <linux/sched.h> #include <linux/wait.h> diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 636cd83ca29e..e1b0fa4000cd 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -195,6 +195,7 @@ #include <linux/anon_inodes.h> #include <linux/dma-fence-unwrap.h> #include <linux/eventfd.h> +#include <linux/export.h> #include <linux/file.h> #include <linux/fs.h> #include <linux/sched/signal.h> diff --git a/drivers/gpu/drm/drm_vblank_work.c b/drivers/gpu/drm/drm_vblank_work.c index 9cc71120246f..e4e1873f0e1e 100644 --- a/drivers/gpu/drm/drm_vblank_work.c +++ b/drivers/gpu/drm/drm_vblank_work.c @@ -2,6 +2,8 @@ #include <uapi/linux/sched/types.h> +#include <linux/export.h> + #include <drm/drm_print.h> #include <drm/drm_vblank.h> #include <drm/drm_vblank_work.h> diff --git a/drivers/gpu/drm/drm_vma_manager.c b/drivers/gpu/drm/drm_vma_manager.c index 83229a031af0..58659c16874c 100644 --- a/drivers/gpu/drm/drm_vma_manager.c +++ b/drivers/gpu/drm/drm_vma_manager.c @@ -23,6 +23,7 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include <linux/export.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/rbtree.h> diff --git a/drivers/gpu/drm/drm_writeback.c b/drivers/gpu/drm/drm_writeback.c index edbeab88ff2b..ace8c98c3e04 100644 --- a/drivers/gpu/drm/drm_writeback.c +++ b/drivers/gpu/drm/drm_writeback.c @@ -10,6 +10,7 @@ */ #include <linux/dma-fence.h> +#include <linux/export.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> diff --git a/drivers/gpu/drm/i915/gt/intel_gt_requests.c b/drivers/gpu/drm/i915/gt/intel_gt_requests.c index ae3557ed6c1e..93298820bee2 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_requests.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_requests.c @@ -250,11 +250,17 @@ void intel_gt_watchdog_work(struct work_struct *work) llist_for_each_entry_safe(rq, rn, first, watchdog.link) { if (!i915_request_completed(rq)) { struct dma_fence *f = &rq->fence; + const char __rcu *timeline; + const char __rcu *driver; + rcu_read_lock(); + driver = dma_fence_driver_name(f); + timeline = dma_fence_timeline_name(f); pr_notice("Fence expiration time out i915-%s:%s:%llx!\n", - dma_fence_driver_name(f), - dma_fence_timeline_name(f), + rcu_dereference(driver), + rcu_dereference(timeline), f->seqno); + rcu_read_unlock(); i915_request_cancel(rq, -EINTR); } i915_request_put(rq); diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index dbdcfe130ad4..ba1d8fdc3c7b 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1448,7 +1448,8 @@ static void intel_gt_reset_global(struct intel_gt *gt, kobject_uevent_env(kobj, KOBJ_CHANGE, reset_done_event); else drm_dev_wedged_event(>->i915->drm, - DRM_WEDGE_RECOVERY_REBIND | DRM_WEDGE_RECOVERY_BUS_RESET); + DRM_WEDGE_RECOVERY_REBIND | DRM_WEDGE_RECOVERY_BUS_RESET, + NULL); } /** diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c index 4874c4f1e4ab..b9a2b2194c8f 100644 --- a/drivers/gpu/drm/i915/i915_request.c +++ b/drivers/gpu/drm/i915/i915_request.c @@ -2184,7 +2184,7 @@ void i915_request_show(struct drm_printer *m, const char *prefix, int indent) { - const char *name = dma_fence_timeline_name((struct dma_fence *)&rq->fence); + const char __rcu *timeline; char buf[80] = ""; int x = 0; @@ -2220,6 +2220,8 @@ void i915_request_show(struct drm_printer *m, x = print_sched_attr(&rq->sched.attr, buf, x, sizeof(buf)); + rcu_read_lock(); + timeline = dma_fence_timeline_name((struct dma_fence *)&rq->fence); drm_printf(m, "%s%.*s%c %llx:%lld%s%s %s @ %dms: %s\n", prefix, indent, " ", queue_status(rq), @@ -2228,7 +2230,8 @@ void i915_request_show(struct drm_printer *m, fence_status(rq), buf, jiffies_to_msecs(jiffies - rq->emitted_jiffies), - name); + rcu_dereference(timeline)); + rcu_read_unlock(); } static bool engine_match_ring(struct intel_engine_cs *engine, struct i915_request *rq) diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index 9edf659d18db..73e89b168fc3 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -430,16 +430,22 @@ static void timer_i915_sw_fence_wake(struct timer_list *t) struct i915_sw_dma_fence_cb_timer *cb = timer_container_of(cb, t, timer); struct i915_sw_fence *fence; + const char __rcu *timeline; + const char __rcu *driver; fence = xchg(&cb->base.fence, NULL); if (!fence) return; + rcu_read_lock(); + driver = dma_fence_driver_name(cb->dma); + timeline = dma_fence_timeline_name(cb->dma); pr_notice("Asynchronous wait on fence %s:%s:%llx timed out (hint:%ps)\n", - dma_fence_driver_name(cb->dma), - dma_fence_timeline_name(cb->dma), + rcu_dereference(driver), + rcu_dereference(timeline), cb->dma->seqno, i915_sw_fence_debug_hint(fence)); + rcu_read_unlock(); i915_sw_fence_set_error_once(fence, -ETIMEDOUT); i915_sw_fence_complete(fence); diff --git a/drivers/gpu/drm/lib/drm_random.c b/drivers/gpu/drm/lib/drm_random.c index 31b5a3e21911..0e9dba1ef4af 100644 --- a/drivers/gpu/drm/lib/drm_random.c +++ b/drivers/gpu/drm/lib/drm_random.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 #include <linux/bitops.h> +#include <linux/export.h> #include <linux/kernel.h> #include <linux/random.h> #include <linux/slab.h> diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 533f70e8a4a6..cf055815077c 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -524,7 +524,7 @@ static void dispc_save_context(struct dispc_device *dispc) DSSDBG("context saved\n"); } -static void dispc_restore_context(struct dispc_device *dispc) +static noinline_for_stack void dispc_restore_context(struct dispc_device *dispc) { int i, j; diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c index 6917ffda5b2b..ea241c89593b 100644 --- a/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c +++ b/drivers/gpu/drm/panel/panel-samsung-s6e63m0.c @@ -13,6 +13,7 @@ #include <linux/backlight.h> #include <linux/delay.h> +#include <linux/export.h> #include <linux/gpio/consumer.h> #include <linux/module.h> #include <linux/property.h> diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c index 50ec109aa6ed..f87337c3cbb5 100644 --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c @@ -11,6 +11,7 @@ #include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/iopoll.h> +#include <linux/math.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_graph.h> @@ -18,6 +19,7 @@ #include <linux/pm_runtime.h> #include <linux/reset.h> #include <linux/slab.h> +#include <linux/units.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> @@ -32,10 +34,31 @@ #define RZG2L_DCS_BUF_SIZE 128 /* Maximum DCS buffer size in external memory. */ +#define RZ_MIPI_DSI_FEATURE_16BPP BIT(0) + +struct rzg2l_mipi_dsi; + +struct rzg2l_mipi_dsi_hw_info { + int (*dphy_init)(struct rzg2l_mipi_dsi *dsi, u64 hsfreq_millihz); + void (*dphy_startup_late_init)(struct rzg2l_mipi_dsi *dsi); + void (*dphy_exit)(struct rzg2l_mipi_dsi *dsi); + int (*dphy_conf_clks)(struct rzg2l_mipi_dsi *dsi, unsigned long mode_freq, + u64 *hsfreq_millihz); + unsigned int (*dphy_mode_clk_check)(struct rzg2l_mipi_dsi *dsi, + unsigned long mode_freq); + u32 phy_reg_offset; + u32 link_reg_offset; + unsigned long min_dclk; + unsigned long max_dclk; + u8 features; +}; + struct rzg2l_mipi_dsi { struct device *dev; void __iomem *mmio; + const struct rzg2l_mipi_dsi_hw_info *info; + struct reset_control *rstc; struct reset_control *arstc; struct reset_control *prstc; @@ -85,7 +108,7 @@ struct rzg2l_mipi_dsi_timings { static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = { { - .hsfreq_max = 80000, + .hsfreq_max = 80000000, .t_init = 79801, .tclk_prepare = 8, .ths_prepare = 13, @@ -99,7 +122,7 @@ static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = { .tlpx = 6, }, { - .hsfreq_max = 125000, + .hsfreq_max = 125000000, .t_init = 79801, .tclk_prepare = 8, .ths_prepare = 12, @@ -113,7 +136,7 @@ static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = { .tlpx = 6, }, { - .hsfreq_max = 250000, + .hsfreq_max = 250000000, .t_init = 79801, .tclk_prepare = 8, .ths_prepare = 12, @@ -127,7 +150,7 @@ static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = { .tlpx = 6, }, { - .hsfreq_max = 360000, + .hsfreq_max = 360000000, .t_init = 79801, .tclk_prepare = 8, .ths_prepare = 10, @@ -141,7 +164,7 @@ static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = { .tlpx = 6, }, { - .hsfreq_max = 720000, + .hsfreq_max = 720000000, .t_init = 79801, .tclk_prepare = 8, .ths_prepare = 9, @@ -155,7 +178,7 @@ static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = { .tlpx = 6, }, { - .hsfreq_max = 1500000, + .hsfreq_max = 1500000000, .t_init = 79801, .tclk_prepare = 8, .ths_prepare = 9, @@ -172,22 +195,22 @@ static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = { static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data) { - iowrite32(data, dsi->mmio + reg); + iowrite32(data, dsi->mmio + dsi->info->phy_reg_offset + reg); } static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data) { - iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg); + iowrite32(data, dsi->mmio + dsi->info->link_reg_offset + reg); } static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg) { - return ioread32(dsi->mmio + reg); + return ioread32(dsi->mmio + dsi->info->phy_reg_offset + reg); } static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg) { - return ioread32(dsi->mmio + LINK_REG_OFFSET + reg); + return ioread32(dsi->mmio + dsi->info->link_reg_offset + reg); } /* ----------------------------------------------------------------------------- @@ -195,8 +218,9 @@ static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg) */ static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi, - unsigned long hsfreq) + u64 hsfreq_millihz) { + unsigned long hsfreq = DIV_ROUND_CLOSEST_ULL(hsfreq_millihz, MILLI); const struct rzg2l_mipi_dsi_timings *dphy_timings; unsigned int i; u32 dphyctrl0; @@ -265,21 +289,17 @@ static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi) reset_control_assert(dsi->rstc); } -static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, - const struct drm_display_mode *mode) +static int rzg2l_dphy_conf_clks(struct rzg2l_mipi_dsi *dsi, unsigned long mode_freq, + u64 *hsfreq_millihz) { - unsigned long hsfreq; + unsigned long vclk_rate; unsigned int bpp; - u32 txsetr; - u32 clstptsetr; - u32 lptrnstsetr; - u32 clkkpt; - u32 clkbfht; - u32 clkstpt; - u32 golpbkt; - u32 dsisetr; - int ret; + clk_set_rate(dsi->vclk, mode_freq * KILO); + vclk_rate = clk_get_rate(dsi->vclk); + if (vclk_rate != mode_freq * KILO) + dev_dbg(dsi->dev, "Requested vclk rate %lu, actual %lu mismatch\n", + mode_freq * KILO, vclk_rate); /* * Relationship between hsclk and vclk must follow * vclk * bpp = hsclk * 8 * lanes @@ -288,18 +308,39 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, * hsclk: DSI HS Byte clock frequency (Hz) * lanes: number of data lanes * - * hsclk(bit) = hsclk(byte) * 8 + * hsclk(bit) = hsclk(byte) * 8 = hsfreq */ bpp = mipi_dsi_pixel_format_to_bpp(dsi->format); - hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes); + *hsfreq_millihz = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(vclk_rate, bpp * MILLI), + dsi->lanes); + + return 0; +} + +static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, + const struct drm_display_mode *mode) +{ + unsigned long hsfreq; + u64 hsfreq_millihz; + u32 txsetr; + u32 clstptsetr; + u32 lptrnstsetr; + u32 clkkpt; + u32 clkbfht; + u32 clkstpt; + u32 golpbkt; + u32 dsisetr; + int ret; ret = pm_runtime_resume_and_get(dsi->dev); if (ret < 0) return ret; - clk_set_rate(dsi->vclk, mode->clock * 1000); + ret = dsi->info->dphy_conf_clks(dsi, mode->clock, &hsfreq_millihz); + if (ret < 0) + goto err_phy; - ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq); + ret = dsi->info->dphy_init(dsi, hsfreq_millihz); if (ret < 0) goto err_phy; @@ -307,6 +348,10 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN; rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr); + if (dsi->info->dphy_startup_late_init) + dsi->info->dphy_startup_late_init(dsi); + + hsfreq = DIV_ROUND_CLOSEST_ULL(hsfreq_millihz, MILLI); /* * Global timings characteristic depends on high speed Clock Frequency * Currently MIPI DSI-IF just supports maximum FHD@60 with: @@ -315,12 +360,12 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, * - data lanes: maximum 4 lanes * Therefore maximum hsclk will be 891 Mbps. */ - if (hsfreq > 445500) { + if (hsfreq > 445500000) { clkkpt = 12; clkbfht = 15; clkstpt = 48; golpbkt = 75; - } else if (hsfreq > 250000) { + } else if (hsfreq > 250000000) { clkkpt = 7; clkbfht = 8; clkstpt = 27; @@ -351,7 +396,7 @@ static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi, return 0; err_phy: - rzg2l_mipi_dsi_dphy_exit(dsi); + dsi->info->dphy_exit(dsi); pm_runtime_put(dsi->dev); return ret; @@ -359,7 +404,7 @@ err_phy: static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi) { - rzg2l_mipi_dsi_dphy_exit(dsi); + dsi->info->dphy_exit(dsi); pm_runtime_put(dsi->dev); } @@ -609,9 +654,22 @@ rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, const struct drm_display_mode *mode) { - if (mode->clock > 148500) + struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge); + + if (mode->clock > dsi->info->max_dclk) return MODE_CLOCK_HIGH; + if (mode->clock < dsi->info->min_dclk) + return MODE_CLOCK_LOW; + + if (dsi->info->dphy_mode_clk_check) { + enum drm_mode_status status; + + status = dsi->info->dphy_mode_clk_check(dsi, mode->clock); + if (status != MODE_OK) + return status; + } + return MODE_OK; } @@ -645,8 +703,16 @@ static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host, switch (mipi_dsi_pixel_format_to_bpp(device->format)) { case 24: + break; case 18: break; + case 16: + if (!(dsi->info->features & RZ_MIPI_DSI_FEATURE_16BPP)) { + dev_err(dsi->dev, "Unsupported format 0x%04x\n", + device->format); + return -EINVAL; + } + break; default: dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format); return -EINVAL; @@ -896,6 +962,8 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, dsi); dsi->dev = &pdev->dev; + dsi->info = of_device_get_match_data(&pdev->dev); + ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4); if (ret < 0) return dev_err_probe(dsi->dev, ret, @@ -911,7 +979,7 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) if (IS_ERR(dsi->vclk)) return PTR_ERR(dsi->vclk); - dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst"); + dsi->rstc = devm_reset_control_get_optional_exclusive(dsi->dev, "rst"); if (IS_ERR(dsi->rstc)) return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc), "failed to get rst\n"); @@ -939,13 +1007,13 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) * mode->clock and format are not available. So initialize DPHY with * timing parameters for 80Mbps. */ - ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000); + ret = dsi->info->dphy_init(dsi, 80000000ULL * MILLI); if (ret < 0) goto err_phy; txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR); dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes); - rzg2l_mipi_dsi_dphy_exit(dsi); + dsi->info->dphy_exit(dsi); pm_runtime_put(dsi->dev); /* Initialize the DRM bridge. */ @@ -966,7 +1034,7 @@ static int rzg2l_mipi_dsi_probe(struct platform_device *pdev) return 0; err_phy: - rzg2l_mipi_dsi_dphy_exit(dsi); + dsi->info->dphy_exit(dsi); pm_runtime_put(dsi->dev); err_pm_disable: pm_runtime_disable(dsi->dev); @@ -983,8 +1051,17 @@ static void rzg2l_mipi_dsi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); } +static const struct rzg2l_mipi_dsi_hw_info rzg2l_mipi_dsi_info = { + .dphy_init = rzg2l_mipi_dsi_dphy_init, + .dphy_exit = rzg2l_mipi_dsi_dphy_exit, + .dphy_conf_clks = rzg2l_dphy_conf_clks, + .link_reg_offset = 0x10000, + .min_dclk = 5803, + .max_dclk = 148500, +}; + static const struct of_device_id rzg2l_mipi_dsi_of_table[] = { - { .compatible = "renesas,rzg2l-mipi-dsi" }, + { .compatible = "renesas,rzg2l-mipi-dsi", .data = &rzg2l_mipi_dsi_info, }, { /* sentinel */ } }; diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h index 26d8a37ee635..d8082a87d874 100644 --- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h +++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi_regs.h @@ -41,8 +41,6 @@ #define DSIDPHYTIM3_THS_ZERO(x) ((x) << 0) /* --------------------------------------------------------*/ -/* Link Registers */ -#define LINK_REG_OFFSET 0x10000 /* Link Status Register */ #define LINKSR 0x10 diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 86214b6e02d7..5635b3a826d8 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -21,6 +21,7 @@ * */ +#include <linux/export.h> #include <linux/slab.h> #include <linux/completion.h> diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c index 725de257d60d..9391d6f0dc01 100644 --- a/drivers/gpu/drm/scheduler/sched_fence.c +++ b/drivers/gpu/drm/scheduler/sched_fence.c @@ -21,6 +21,7 @@ * */ +#include <linux/export.h> #include <linux/module.h> #include <linux/sched.h> #include <linux/slab.h> diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index d20726d7adf0..c63543132f9d 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -66,6 +66,7 @@ * This implies waiting for previously executed jobs. */ +#include <linux/export.h> #include <linux/wait.h> #include <linux/sched.h> #include <linux/completion.h> diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h index cb08a88242cc..1424b63dde99 100644 --- a/drivers/gpu/drm/sysfb/drm_sysfb_helper.h +++ b/drivers/gpu/drm/sysfb/drm_sysfb_helper.h @@ -93,6 +93,10 @@ static inline struct drm_sysfb_device *to_drm_sysfb_device(struct drm_device *de * Plane */ +size_t drm_sysfb_build_fourcc_list(struct drm_device *dev, + const u32 *native_fourccs, size_t native_nfourccs, + u32 *fourccs_out, size_t nfourccs_out); + int drm_sysfb_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *new_state); void drm_sysfb_plane_helper_atomic_update(struct drm_plane *plane, diff --git a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c index ffaa2522ab96..1bcdb5ee8f09 100644 --- a/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c +++ b/drivers/gpu/drm/sysfb/drm_sysfb_modeset.c @@ -47,6 +47,144 @@ EXPORT_SYMBOL(drm_sysfb_mode); * Plane */ +static u32 to_nonalpha_fourcc(u32 fourcc) +{ + /* only handle formats with depth != 0 and alpha channel */ + switch (fourcc) { + case DRM_FORMAT_ARGB1555: + return DRM_FORMAT_XRGB1555; + case DRM_FORMAT_ABGR1555: + return DRM_FORMAT_XBGR1555; + case DRM_FORMAT_RGBA5551: + return DRM_FORMAT_RGBX5551; + case DRM_FORMAT_BGRA5551: + return DRM_FORMAT_BGRX5551; + case DRM_FORMAT_ARGB8888: + return DRM_FORMAT_XRGB8888; + case DRM_FORMAT_ABGR8888: + return DRM_FORMAT_XBGR8888; + case DRM_FORMAT_RGBA8888: + return DRM_FORMAT_RGBX8888; + case DRM_FORMAT_BGRA8888: + return DRM_FORMAT_BGRX8888; + case DRM_FORMAT_ARGB2101010: + return DRM_FORMAT_XRGB2101010; + case DRM_FORMAT_ABGR2101010: + return DRM_FORMAT_XBGR2101010; + case DRM_FORMAT_RGBA1010102: + return DRM_FORMAT_RGBX1010102; + case DRM_FORMAT_BGRA1010102: + return DRM_FORMAT_BGRX1010102; + } + + return fourcc; +} + +static bool is_listed_fourcc(const u32 *fourccs, size_t nfourccs, u32 fourcc) +{ + const u32 *fourccs_end = fourccs + nfourccs; + + while (fourccs < fourccs_end) { + if (*fourccs == fourcc) + return true; + ++fourccs; + } + return false; +} + +/** + * drm_sysfb_build_fourcc_list - Filters a list of supported color formats against + * the device's native formats + * @dev: DRM device + * @native_fourccs: 4CC codes of natively supported color formats + * @native_nfourccs: The number of entries in @native_fourccs + * @fourccs_out: Returns 4CC codes of supported color formats + * @nfourccs_out: The number of available entries in @fourccs_out + * + * This function create a list of supported color format from natively + * supported formats and additional emulated formats. + * At a minimum, most userspace programs expect at least support for + * XRGB8888 on the primary plane. Sysfb devices that have to emulate + * the format should use drm_sysfb_build_fourcc_list() to create a list + * of supported color formats. The returned list can be handed over to + * drm_universal_plane_init() et al. Native formats will go before + * emulated formats. Native formats with alpha channel will be replaced + * by equal formats without alpha channel, as primary planes usually + * don't support alpha. Other heuristics might be applied to optimize + * the sorting order. Formats near the beginning of the list are usually + * preferred over formats near the end of the list. + * + * Returns: + * The number of color-formats 4CC codes returned in @fourccs_out. + */ +size_t drm_sysfb_build_fourcc_list(struct drm_device *dev, + const u32 *native_fourccs, size_t native_nfourccs, + u32 *fourccs_out, size_t nfourccs_out) +{ + /* + * XRGB8888 is the default fallback format for most of userspace + * and it's currently the only format that should be emulated for + * the primary plane. Only if there's ever another default fallback, + * it should be added here. + */ + static const u32 extra_fourccs[] = { + DRM_FORMAT_XRGB8888, + }; + static const size_t extra_nfourccs = ARRAY_SIZE(extra_fourccs); + + u32 *fourccs = fourccs_out; + const u32 *fourccs_end = fourccs_out + nfourccs_out; + size_t i; + + /* + * The device's native formats go first. + */ + + for (i = 0; i < native_nfourccs; ++i) { + /* + * Several DTs, boot loaders and firmware report native + * alpha formats that are non-alpha formats instead. So + * replace alpha formats by non-alpha formats. + */ + u32 fourcc = to_nonalpha_fourcc(native_fourccs[i]); + + if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { + continue; /* skip duplicate entries */ + } else if (fourccs == fourccs_end) { + drm_warn(dev, "Ignoring native format %p4cc\n", &fourcc); + continue; /* end of available output buffer */ + } + + drm_dbg_kms(dev, "adding native format %p4cc\n", &fourcc); + + *fourccs = fourcc; + ++fourccs; + } + + /* + * The extra formats, emulated by the driver, go second. + */ + + for (i = 0; (i < extra_nfourccs) && (fourccs < fourccs_end); ++i) { + u32 fourcc = extra_fourccs[i]; + + if (is_listed_fourcc(fourccs_out, fourccs - fourccs_out, fourcc)) { + continue; /* skip duplicate and native entries */ + } else if (fourccs == fourccs_end) { + drm_warn(dev, "Ignoring emulated format %p4cc\n", &fourcc); + continue; /* end of available output buffer */ + } + + drm_dbg_kms(dev, "adding emulated format %p4cc\n", &fourcc); + + *fourccs = fourcc; + ++fourccs; + } + + return fourccs - fourccs_out; +} +EXPORT_SYMBOL(drm_sysfb_build_fourcc_list); + int drm_sysfb_plane_helper_atomic_check(struct drm_plane *plane, struct drm_atomic_state *new_state) { diff --git a/drivers/gpu/drm/sysfb/efidrm.c b/drivers/gpu/drm/sysfb/efidrm.c index 46912924636a..1883c4a8604c 100644 --- a/drivers/gpu/drm/sysfb/efidrm.c +++ b/drivers/gpu/drm/sysfb/efidrm.c @@ -202,7 +202,7 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv, drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, stride=%d bytes\n", &format->format, width, height, stride); -#ifdef CONFIG_X86 +#if defined(CONFIG_FIRMWARE_EDID) if (drm_edid_header_is_valid(edid_info.dummy) == 8) sysfb->edid = edid_info.dummy; #endif @@ -271,8 +271,8 @@ static struct efidrm_device *efidrm_device_create(struct drm_driver *drv, /* Primary plane */ - nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, - efi->formats, ARRAY_SIZE(efi->formats)); + nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1, + efi->formats, ARRAY_SIZE(efi->formats)); primary_plane = &efi->primary_plane; ret = drm_universal_plane_init(dev, primary_plane, 0, &efidrm_primary_plane_funcs, diff --git a/drivers/gpu/drm/sysfb/ofdrm.c b/drivers/gpu/drm/sysfb/ofdrm.c index c9415f0cb3ed..8d8ab39c5f36 100644 --- a/drivers/gpu/drm/sysfb/ofdrm.c +++ b/drivers/gpu/drm/sysfb/ofdrm.c @@ -15,7 +15,6 @@ #include <drm/drm_drv.h> #include <drm/drm_edid.h> #include <drm/drm_fbdev_shmem.h> -#include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> @@ -1015,8 +1014,8 @@ static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv, /* Primary plane */ - nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, - odev->formats, ARRAY_SIZE(odev->formats)); + nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1, + odev->formats, ARRAY_SIZE(odev->formats)); primary_plane = &odev->primary_plane; ret = drm_universal_plane_init(dev, primary_plane, 0, &ofdrm_primary_plane_funcs, diff --git a/drivers/gpu/drm/sysfb/simpledrm.c b/drivers/gpu/drm/sysfb/simpledrm.c index a1c3119330de..8530a3ef8a7a 100644 --- a/drivers/gpu/drm/sysfb/simpledrm.c +++ b/drivers/gpu/drm/sysfb/simpledrm.c @@ -18,7 +18,6 @@ #include <drm/drm_device.h> #include <drm/drm_drv.h> #include <drm/drm_fbdev_shmem.h> -#include <drm/drm_format_helper.h> #include <drm/drm_framebuffer.h> #include <drm/drm_gem_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> @@ -765,8 +764,8 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, /* Primary plane */ - nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, - sdev->formats, ARRAY_SIZE(sdev->formats)); + nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1, + sdev->formats, ARRAY_SIZE(sdev->formats)); primary_plane = &sdev->primary_plane; ret = drm_universal_plane_init(dev, primary_plane, 0, &simpledrm_primary_plane_funcs, diff --git a/drivers/gpu/drm/sysfb/vesadrm.c b/drivers/gpu/drm/sysfb/vesadrm.c index 7945544ba73e..2b107958942c 100644 --- a/drivers/gpu/drm/sysfb/vesadrm.c +++ b/drivers/gpu/drm/sysfb/vesadrm.c @@ -344,7 +344,7 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv, #endif } -#ifdef CONFIG_X86 +#if defined(CONFIG_FIRMWARE_EDID) if (drm_edid_header_is_valid(edid_info.dummy) == 8) sysfb->edid = edid_info.dummy; #endif @@ -402,8 +402,8 @@ static struct vesadrm_device *vesadrm_device_create(struct drm_driver *drv, /* Primary plane */ - nformats = drm_fb_build_fourcc_list(dev, &format->format, 1, - vesa->formats, ARRAY_SIZE(vesa->formats)); + nformats = drm_sysfb_build_fourcc_list(dev, &format->format, 1, + vesa->formats, ARRAY_SIZE(vesa->formats)); primary_plane = &vesa->primary_plane; ret = drm_universal_plane_init(dev, primary_plane, 0, &vesadrm_primary_plane_funcs, diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile index 3afd6587df08..c0e952293ad0 100644 --- a/drivers/gpu/drm/tests/Makefile +++ b/drivers/gpu/drm/tests/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_DRM_KUNIT_TEST) += \ drm_modes_test.o \ drm_plane_helper_test.o \ drm_probe_helper_test.o \ - drm_rect_test.o + drm_rect_test.o \ + drm_sysfb_modeset_test.o CFLAGS_drm_mm_test.o := $(DISABLE_STRUCTLEAK_PLUGIN) diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c index 35cd3405d045..ad06762db671 100644 --- a/drivers/gpu/drm/tests/drm_format_helper_test.c +++ b/drivers/gpu/drm/tests/drm_format_helper_test.c @@ -279,9 +279,9 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .dst_pitch = TEST_USE_DEFAULT_PITCH, .expected = { 0xFF, 0x00, - 0x4C, 0x99, - 0x19, 0x66, - 0xE5, 0xB2, + 0x4C, 0x95, + 0x1C, 0x69, + 0xE2, 0xB2, }, }, .rgb332_result = { @@ -430,9 +430,9 @@ static struct convert_xrgb8888_case convert_xrgb8888_cases[] = { .gray8_result = { .dst_pitch = 5, .expected = { - 0x3C, 0x33, 0xC4, 0x00, 0x00, - 0xBB, 0x3C, 0x33, 0x00, 0x00, - 0x34, 0xBB, 0x3C, 0x00, 0x00, + 0x3D, 0x32, 0xC1, 0x00, 0x00, + 0xBA, 0x3D, 0x32, 0x00, 0x00, + 0x34, 0xBA, 0x3D, 0x00, 0x00, }, }, .rgb332_result = { @@ -748,14 +748,9 @@ static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test) buf = dst.vaddr; memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGB565, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_rgb565(&dst, dst_pitch, &src, &fb, ¶ms->clip, + &fmtcnv_state, false); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -795,14 +790,8 @@ static void drm_test_fb_xrgb8888_to_xrgb1555(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB1555, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_xrgb1555(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -842,14 +831,8 @@ static void drm_test_fb_xrgb8888_to_argb1555(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB1555, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_argb1555(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -889,14 +872,8 @@ static void drm_test_fb_xrgb8888_to_rgba5551(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGBA5551, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_rgba5551(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le16buf_to_cpu(test, (__force const __le16 *)buf, dst_size / sizeof(__le16)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -939,12 +916,7 @@ static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_RGB888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - - KUNIT_EXPECT_FALSE(test, blit_result); + drm_fb_xrgb8888_to_rgb888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -985,12 +957,8 @@ static void drm_test_fb_xrgb8888_to_bgr888(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, &result->dst_pitch, DRM_FORMAT_BGR888, &src, &fb, ¶ms->clip, + drm_fb_xrgb8888_to_bgr888(&dst, &result->dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1030,14 +998,8 @@ static void drm_test_fb_xrgb8888_to_argb8888(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_argb8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1077,12 +1039,7 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB2101010, &src, &fb, - ¶ms->clip, &fmtcnv_state); - - KUNIT_EXPECT_FALSE(test, blit_result); + drm_fb_xrgb8888_to_xrgb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1122,14 +1079,8 @@ static void drm_test_fb_xrgb8888_to_argb2101010(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ARGB2101010, &src, &fb, - ¶ms->clip, &fmtcnv_state); - + drm_fb_xrgb8888_to_argb2101010(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1202,23 +1153,15 @@ static void drm_test_fb_swab(struct kunit *test) buf = dst.vaddr; /* restore original value of buf */ memset(buf, 0, dst_size); - int blit_result; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB8888 | DRM_FORMAT_BIG_ENDIAN, - &src, &fb, ¶ms->clip, &fmtcnv_state); + drm_fb_swab(&dst, dst_pitch, &src, &fb, ¶ms->clip, false, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); buf = dst.vaddr; memset(buf, 0, dst_size); - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_BGRX8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); + drm_fb_xrgb8888_to_bgrx8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); buf = dst.vaddr; @@ -1229,11 +1172,8 @@ static void drm_test_fb_swab(struct kunit *test) mock_format.format |= DRM_FORMAT_BIG_ENDIAN; fb.format = &mock_format; - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XRGB8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); + drm_fb_swab(&dst, dst_pitch, &src, &fb, ¶ms->clip, false, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1266,14 +1206,8 @@ static void drm_test_fb_xrgb8888_to_abgr8888(struct kunit *test) const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ? NULL : &result->dst_pitch; - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_ABGR8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_abgr8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1306,14 +1240,8 @@ static void drm_test_fb_xrgb8888_to_xbgr8888(struct kunit *test) const unsigned int *dst_pitch = (result->dst_pitch == TEST_USE_DEFAULT_PITCH) ? NULL : &result->dst_pitch; - int blit_result = 0; - - blit_result = drm_fb_blit(&dst, dst_pitch, DRM_FORMAT_XBGR8888, &src, &fb, ¶ms->clip, - &fmtcnv_state); - + drm_fb_xrgb8888_to_xbgr8888(&dst, dst_pitch, &src, &fb, ¶ms->clip, &fmtcnv_state); buf = le32buf_to_cpu(test, (__force const __le32 *)buf, dst_size / sizeof(u32)); - - KUNIT_EXPECT_FALSE(test, blit_result); KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size); } @@ -1407,147 +1335,6 @@ static void drm_test_fb_clip_offset(struct kunit *test) KUNIT_EXPECT_EQ(test, offset, params->expected_offset); } -struct fb_build_fourcc_list_case { - const char *name; - u32 native_fourccs[TEST_BUF_SIZE]; - size_t native_fourccs_size; - u32 expected[TEST_BUF_SIZE]; - size_t expected_fourccs_size; -}; - -static struct fb_build_fourcc_list_case fb_build_fourcc_list_cases[] = { - { - .name = "no native formats", - .native_fourccs = { }, - .native_fourccs_size = 0, - .expected = { DRM_FORMAT_XRGB8888 }, - .expected_fourccs_size = 1, - }, - { - .name = "XRGB8888 as native format", - .native_fourccs = { DRM_FORMAT_XRGB8888 }, - .native_fourccs_size = 1, - .expected = { DRM_FORMAT_XRGB8888 }, - .expected_fourccs_size = 1, - }, - { - .name = "remove duplicates", - .native_fourccs = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, - DRM_FORMAT_RGB888, - DRM_FORMAT_RGB888, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, - DRM_FORMAT_RGB565, - DRM_FORMAT_RGB888, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB565, - DRM_FORMAT_RGB565, - DRM_FORMAT_XRGB8888, - }, - .native_fourccs_size = 11, - .expected = { - DRM_FORMAT_XRGB8888, - DRM_FORMAT_RGB888, - DRM_FORMAT_RGB565, - }, - .expected_fourccs_size = 3, - }, - { - .name = "convert alpha formats", - .native_fourccs = { - DRM_FORMAT_ARGB1555, - DRM_FORMAT_ABGR1555, - DRM_FORMAT_RGBA5551, - DRM_FORMAT_BGRA5551, - DRM_FORMAT_ARGB8888, - DRM_FORMAT_ABGR8888, - DRM_FORMAT_RGBA8888, - DRM_FORMAT_BGRA8888, - DRM_FORMAT_ARGB2101010, - DRM_FORMAT_ABGR2101010, - DRM_FORMAT_RGBA1010102, - DRM_FORMAT_BGRA1010102, - }, - .native_fourccs_size = 12, - .expected = { - DRM_FORMAT_XRGB1555, - DRM_FORMAT_XBGR1555, - DRM_FORMAT_RGBX5551, - DRM_FORMAT_BGRX5551, - DRM_FORMAT_XRGB8888, - DRM_FORMAT_XBGR8888, - DRM_FORMAT_RGBX8888, - DRM_FORMAT_BGRX8888, - DRM_FORMAT_XRGB2101010, - DRM_FORMAT_XBGR2101010, - DRM_FORMAT_RGBX1010102, - DRM_FORMAT_BGRX1010102, - }, - .expected_fourccs_size = 12, - }, - { - .name = "random formats", - .native_fourccs = { - DRM_FORMAT_Y212, - DRM_FORMAT_ARGB1555, - DRM_FORMAT_ABGR16161616F, - DRM_FORMAT_C8, - DRM_FORMAT_BGR888, - DRM_FORMAT_XRGB1555, - DRM_FORMAT_RGBA5551, - DRM_FORMAT_BGR565_A8, - DRM_FORMAT_R10, - DRM_FORMAT_XYUV8888, - }, - .native_fourccs_size = 10, - .expected = { - DRM_FORMAT_Y212, - DRM_FORMAT_XRGB1555, - DRM_FORMAT_ABGR16161616F, - DRM_FORMAT_C8, - DRM_FORMAT_BGR888, - DRM_FORMAT_RGBX5551, - DRM_FORMAT_BGR565_A8, - DRM_FORMAT_R10, - DRM_FORMAT_XYUV8888, - DRM_FORMAT_XRGB8888, - }, - .expected_fourccs_size = 10, - }, -}; - -static void fb_build_fourcc_list_case_desc(struct fb_build_fourcc_list_case *t, char *desc) -{ - strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); -} - -KUNIT_ARRAY_PARAM(fb_build_fourcc_list, fb_build_fourcc_list_cases, fb_build_fourcc_list_case_desc); - -static void drm_test_fb_build_fourcc_list(struct kunit *test) -{ - const struct fb_build_fourcc_list_case *params = test->param_value; - u32 fourccs_out[TEST_BUF_SIZE] = {0}; - size_t nfourccs_out; - struct drm_device *drm; - struct device *dev; - - dev = drm_kunit_helper_alloc_device(test); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); - - drm = __drm_kunit_helper_alloc_drm_device(test, dev, sizeof(*drm), 0, DRIVER_MODESET); - KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm); - - nfourccs_out = drm_fb_build_fourcc_list(drm, params->native_fourccs, - params->native_fourccs_size, - fourccs_out, TEST_BUF_SIZE); - - KUNIT_EXPECT_EQ(test, nfourccs_out, params->expected_fourccs_size); - KUNIT_EXPECT_MEMEQ(test, fourccs_out, params->expected, TEST_BUF_SIZE); -} - struct fb_memcpy_case { const char *name; u32 format; @@ -1910,12 +1697,8 @@ static void drm_test_fb_memcpy(struct kunit *test) memset(buf[i], 0, dst_size[i]); } - int blit_result; - - blit_result = drm_fb_blit(dst, dst_pitches, params->format, src, &fb, ¶ms->clip, - &fmtcnv_state); + drm_fb_memcpy(dst, dst_pitches, src, &fb, ¶ms->clip); - KUNIT_EXPECT_FALSE(test, blit_result); for (size_t i = 0; i < fb.format->num_planes; i++) { expected[i] = cpubuf_to_le32(test, params->expected[i], TEST_BUF_SIZE); KUNIT_EXPECT_MEMEQ_MSG(test, buf[i], expected[i], dst_size[i], @@ -1940,7 +1723,6 @@ static struct kunit_case drm_format_helper_test_cases[] = { KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_xbgr8888, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_xrgb8888_to_abgr8888, convert_xrgb8888_gen_params), KUNIT_CASE_PARAM(drm_test_fb_clip_offset, clip_offset_gen_params), - KUNIT_CASE_PARAM(drm_test_fb_build_fourcc_list, fb_build_fourcc_list_gen_params), KUNIT_CASE_PARAM(drm_test_fb_memcpy, fb_memcpy_gen_params), {} }; diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c index 5f7257840d8e..04edb6079c0d 100644 --- a/drivers/gpu/drm/tests/drm_kunit_helpers.c +++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c @@ -13,6 +13,7 @@ #include <kunit/resource.h> #include <linux/device.h> +#include <linux/export.h> #include <linux/platform_device.h> #define KUNIT_DEVICE_NAME "drm-kunit-mock-device" diff --git a/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c b/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c new file mode 100644 index 000000000000..e875d876118f --- /dev/null +++ b/drivers/gpu/drm/tests/drm_sysfb_modeset_test.c @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <kunit/test.h> + +#include <drm/drm_fourcc.h> +#include <drm/drm_kunit_helpers.h> + +#include "../sysfb/drm_sysfb_helper.h" + +#define TEST_BUF_SIZE 50 + +struct sysfb_build_fourcc_list_case { + const char *name; + u32 native_fourccs[TEST_BUF_SIZE]; + size_t native_fourccs_size; + u32 expected[TEST_BUF_SIZE]; + size_t expected_fourccs_size; +}; + +static struct sysfb_build_fourcc_list_case sysfb_build_fourcc_list_cases[] = { + { + .name = "no native formats", + .native_fourccs = { }, + .native_fourccs_size = 0, + .expected = { DRM_FORMAT_XRGB8888 }, + .expected_fourccs_size = 1, + }, + { + .name = "XRGB8888 as native format", + .native_fourccs = { DRM_FORMAT_XRGB8888 }, + .native_fourccs_size = 1, + .expected = { DRM_FORMAT_XRGB8888 }, + .expected_fourccs_size = 1, + }, + { + .name = "remove duplicates", + .native_fourccs = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGB888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB8888, + }, + .native_fourccs_size = 11, + .expected = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGB565, + }, + .expected_fourccs_size = 3, + }, + { + .name = "convert alpha formats", + .native_fourccs = { + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ABGR1555, + DRM_FORMAT_RGBA5551, + DRM_FORMAT_BGRA5551, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_BGRA8888, + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_RGBA1010102, + DRM_FORMAT_BGRA1010102, + }, + .native_fourccs_size = 12, + .expected = { + DRM_FORMAT_XRGB1555, + DRM_FORMAT_XBGR1555, + DRM_FORMAT_RGBX5551, + DRM_FORMAT_BGRX5551, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGBX8888, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_RGBX1010102, + DRM_FORMAT_BGRX1010102, + }, + .expected_fourccs_size = 12, + }, + { + .name = "random formats", + .native_fourccs = { + DRM_FORMAT_Y212, + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ABGR16161616F, + DRM_FORMAT_C8, + DRM_FORMAT_BGR888, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_RGBA5551, + DRM_FORMAT_BGR565_A8, + DRM_FORMAT_R10, + DRM_FORMAT_XYUV8888, + }, + .native_fourccs_size = 10, + .expected = { + DRM_FORMAT_Y212, + DRM_FORMAT_XRGB1555, + DRM_FORMAT_ABGR16161616F, + DRM_FORMAT_C8, + DRM_FORMAT_BGR888, + DRM_FORMAT_RGBX5551, + DRM_FORMAT_BGR565_A8, + DRM_FORMAT_R10, + DRM_FORMAT_XYUV8888, + DRM_FORMAT_XRGB8888, + }, + .expected_fourccs_size = 10, + }, +}; + +static void sysfb_build_fourcc_list_case_desc(struct sysfb_build_fourcc_list_case *t, char *desc) +{ + strscpy(desc, t->name, KUNIT_PARAM_DESC_SIZE); +} + +KUNIT_ARRAY_PARAM(sysfb_build_fourcc_list, sysfb_build_fourcc_list_cases, + sysfb_build_fourcc_list_case_desc); + +static void drm_test_sysfb_build_fourcc_list(struct kunit *test) +{ + const struct sysfb_build_fourcc_list_case *params = test->param_value; + u32 fourccs_out[TEST_BUF_SIZE] = {0}; + size_t nfourccs_out; + struct drm_device *drm; + struct device *dev; + + dev = drm_kunit_helper_alloc_device(test); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev); + + drm = __drm_kunit_helper_alloc_drm_device(test, dev, sizeof(*drm), 0, DRIVER_MODESET); + KUNIT_ASSERT_NOT_ERR_OR_NULL(test, drm); + + nfourccs_out = drm_sysfb_build_fourcc_list(drm, params->native_fourccs, + params->native_fourccs_size, + fourccs_out, TEST_BUF_SIZE); + + KUNIT_EXPECT_EQ(test, nfourccs_out, params->expected_fourccs_size); + KUNIT_EXPECT_MEMEQ(test, fourccs_out, params->expected, TEST_BUF_SIZE); +} + +static struct kunit_case drm_sysfb_modeset_test_cases[] = { + KUNIT_CASE_PARAM(drm_test_sysfb_build_fourcc_list, sysfb_build_fourcc_list_gen_params), + {} +}; + +static struct kunit_suite drm_sysfb_modeset_test_suite = { + .name = "drm_sysfb_modeset_test", + .test_cases = drm_sysfb_modeset_test_cases, +}; + +kunit_test_suite(drm_sysfb_modeset_test_suite); + +MODULE_DESCRIPTION("KUnit tests for the drm_sysfb_modeset APIs"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("José Expósito <jose.exposito89@gmail.com>"); diff --git a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c index b91c13f46225..7aaf0d1395ff 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c +++ b/drivers/gpu/drm/ttm/tests/ttm_kunit_helpers.c @@ -2,6 +2,9 @@ /* * Copyright © 2023 Intel Corporation */ + +#include <linux/export.h> + #include <drm/ttm/ttm_tt.h> #include "ttm_kunit_helpers.h" diff --git a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c index f6d1c8a2845d..d7eb6471f2ed 100644 --- a/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c +++ b/drivers/gpu/drm/ttm/tests/ttm_mock_manager.c @@ -2,6 +2,9 @@ /* * Copyright © 2023 Intel Corporation */ + +#include <linux/export.h> + #include <drm/ttm/ttm_resource.h> #include <drm/ttm/ttm_device.h> #include <drm/ttm/ttm_placement.h> diff --git a/drivers/gpu/drm/ttm/ttm_agp_backend.c b/drivers/gpu/drm/ttm/ttm_agp_backend.c index d27691f2e451..fca0a1a3c6fd 100644 --- a/drivers/gpu/drm/ttm/ttm_agp_backend.c +++ b/drivers/gpu/drm/ttm/ttm_agp_backend.c @@ -36,6 +36,7 @@ #include <drm/ttm/ttm_tt.h> #include <drm/ttm/ttm_resource.h> #include <linux/agp_backend.h> +#include <linux/export.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/io.h> diff --git a/drivers/gpu/drm/ttm/ttm_backup.c b/drivers/gpu/drm/ttm/ttm_backup.c index ffaab68bd5dd..cb1b8e5dadf5 100644 --- a/drivers/gpu/drm/ttm/ttm_backup.c +++ b/drivers/gpu/drm/ttm/ttm_backup.c @@ -4,6 +4,8 @@ */ #include <drm/ttm/ttm_backup.h> + +#include <linux/export.h> #include <linux/page-flags.h> #include <linux/swap.h> diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 0f874f1e2526..bb9c5c8e16b5 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -35,6 +35,7 @@ #include <drm/ttm/ttm_placement.h> #include <drm/ttm/ttm_tt.h> +#include <linux/export.h> #include <linux/jiffies.h> #include <linux/slab.h> #include <linux/sched.h> diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index b78365dc1fed..b9a772b26fa1 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -28,6 +28,8 @@ /* * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com> */ + +#include <linux/export.h> #include <linux/swap.h> #include <linux/vmalloc.h> diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index bdfa6ecfef05..b47020fca199 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -31,6 +31,8 @@ #define pr_fmt(fmt) "[TTM] " fmt +#include <linux/export.h> + #include <drm/ttm/ttm_bo.h> #include <drm/ttm/ttm_placement.h> #include <drm/ttm/ttm_tt.h> diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index 36075772555a..816e2cba6016 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -28,6 +28,7 @@ #define pr_fmt(fmt) "[TTM DEVICE] " fmt #include <linux/debugfs.h> +#include <linux/export.h> #include <linux/mm.h> #include <drm/ttm/ttm_bo.h> diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c index f1c60fa80c2d..bc7a83a9fe44 100644 --- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c +++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c @@ -26,6 +26,8 @@ * **************************************************************************/ +#include <linux/export.h> + #include <drm/ttm/ttm_execbuf_util.h> #include <drm/ttm/ttm_bo.h> diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c index a0436971b6a6..baf27c70a419 100644 --- a/drivers/gpu/drm/ttm/ttm_pool.c +++ b/drivers/gpu/drm/ttm/ttm_pool.c @@ -31,6 +31,7 @@ * cause they are rather slow compared to alloc_pages+map. */ +#include <linux/export.h> #include <linux/module.h> #include <linux/dma-mapping.h> #include <linux/debugfs.h> diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c index ae11d07eb63a..db854b581d83 100644 --- a/drivers/gpu/drm/ttm/ttm_range_manager.c +++ b/drivers/gpu/drm/ttm/ttm_range_manager.c @@ -34,6 +34,8 @@ #include <drm/ttm/ttm_range_manager.h> #include <drm/ttm/ttm_bo.h> #include <drm/drm_mm.h> + +#include <linux/export.h> #include <linux/slab.h> #include <linux/spinlock.h> diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 006202fcd3c2..e2c82ad07eb4 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -23,6 +23,7 @@ */ #include <linux/debugfs.h> +#include <linux/export.h> #include <linux/io-mapping.h> #include <linux/iosys-map.h> #include <linux/scatterlist.h> diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 698cd4bf5e46..506e257dfba8 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -33,6 +33,7 @@ #include <linux/cc_platform.h> #include <linux/debugfs.h> +#include <linux/export.h> #include <linux/file.h> #include <linux/module.h> #include <linux/sched.h> diff --git a/drivers/gpu/drm/vkms/tests/Makefile b/drivers/gpu/drm/vkms/tests/Makefile index 0ee077942ae2..5750f0bd9d40 100644 --- a/drivers/gpu/drm/vkms/tests/Makefile +++ b/drivers/gpu/drm/vkms/tests/Makefile @@ -1,4 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_DRM_VKMS_KUNIT_TEST) += vkms_config_test.o -obj-$(CONFIG_DRM_VKMS_KUNIT_TESTS) += vkms_format_test.o +vkms-kunit-tests-y := \ + vkms_config_test.o \ + vkms_format_test.o + +obj-$(CONFIG_DRM_VKMS_KUNIT_TEST) += vkms-kunit-tests.o diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c index dd4ca6a9c690..8fe02131a6c4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c @@ -544,7 +544,7 @@ int vmw_cmd_send_fence(struct vmw_private *dev_priv, uint32_t *seqno) cmd_fence = (struct svga_fifo_cmd_fence *) fm; cmd_fence->fence = *seqno; vmw_cmd_commit_flush(dev_priv, bytes); - vmw_update_seqno(dev_priv); + vmw_fences_update(dev_priv->fman); out_err: return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 37b832e552a4..bc0342c58b4b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -440,8 +440,10 @@ static int vmw_device_init(struct vmw_private *dev_priv) vmw_write(dev_priv, SVGA_REG_CONFIG_DONE, 1); } - dev_priv->last_read_seqno = vmw_fence_read(dev_priv); - atomic_set(&dev_priv->marker_seq, dev_priv->last_read_seqno); + u32 seqno = vmw_fence_read(dev_priv); + + atomic_set(&dev_priv->last_read_seqno, seqno); + atomic_set(&dev_priv->marker_seq, seqno); return 0; } @@ -454,7 +456,7 @@ static void vmw_device_fini(struct vmw_private *vmw) while (vmw_read(vmw, SVGA_REG_BUSY) != 0) ; - vmw->last_read_seqno = vmw_fence_read(vmw); + atomic_set(&vmw->last_read_seqno, vmw_fence_read(vmw)); vmw_write(vmw, SVGA_REG_CONFIG_DONE, vmw->config_done_state); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 594af8eb04c6..eda5b6f8f4c4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -522,7 +522,7 @@ struct vmw_private { int cmdbuf_waiters; /* Protected by waiter_lock */ int error_waiters; /* Protected by waiter_lock */ int fifo_queue_waiters; /* Protected by waiter_lock */ - uint32_t last_read_seqno; + atomic_t last_read_seqno; struct vmw_fence_manager *fman; uint32_t irq_mask; /* Updates protected by waiter_lock */ @@ -1006,15 +1006,14 @@ extern int vmw_fallback_wait(struct vmw_private *dev_priv, uint32_t seqno, bool interruptible, unsigned long timeout); -extern void vmw_update_seqno(struct vmw_private *dev_priv); -extern void vmw_seqno_waiter_add(struct vmw_private *dev_priv); -extern void vmw_seqno_waiter_remove(struct vmw_private *dev_priv); -extern void vmw_goal_waiter_add(struct vmw_private *dev_priv); -extern void vmw_goal_waiter_remove(struct vmw_private *dev_priv); -extern void vmw_generic_waiter_add(struct vmw_private *dev_priv, u32 flag, - int *waiter_count); -extern void vmw_generic_waiter_remove(struct vmw_private *dev_priv, - u32 flag, int *waiter_count); +bool vmw_seqno_waiter_add(struct vmw_private *dev_priv); +bool vmw_seqno_waiter_remove(struct vmw_private *dev_priv); +bool vmw_goal_waiter_add(struct vmw_private *dev_priv); +bool vmw_goal_waiter_remove(struct vmw_private *dev_priv); +bool vmw_generic_waiter_add(struct vmw_private *dev_priv, u32 flag, + int *waiter_count); +bool vmw_generic_waiter_remove(struct vmw_private *dev_priv, + u32 flag, int *waiter_count); /** * Kernel modesetting - vmwgfx_kms.c diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index e831e324e737..819704ac675d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -3878,8 +3878,7 @@ vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, fence_rep.handle = fence_handle; fence_rep.seqno = fence->base.seqno; - vmw_update_seqno(dev_priv); - fence_rep.passed_seqno = dev_priv->last_read_seqno; + fence_rep.passed_seqno = vmw_fences_update(dev_priv->fman); } /* @@ -4068,23 +4067,6 @@ static int vmw_execbuf_tie_context(struct vmw_private *dev_priv, return 0; } -/* - * DMA fence callback to remove a seqno_waiter - */ -struct seqno_waiter_rm_context { - struct dma_fence_cb base; - struct vmw_private *dev_priv; -}; - -static void seqno_waiter_rm_cb(struct dma_fence *f, struct dma_fence_cb *cb) -{ - struct seqno_waiter_rm_context *ctx = - container_of(cb, struct seqno_waiter_rm_context, base); - - vmw_seqno_waiter_remove(ctx->dev_priv); - kfree(ctx); -} - int vmw_execbuf_process(struct drm_file *file_priv, struct vmw_private *dev_priv, void __user *user_commands, void *kernel_commands, @@ -4265,15 +4247,6 @@ int vmw_execbuf_process(struct drm_file *file_priv, } else { /* Link the fence with the FD created earlier */ fd_install(out_fence_fd, sync_file->file); - struct seqno_waiter_rm_context *ctx = - kmalloc(sizeof(*ctx), GFP_KERNEL); - ctx->dev_priv = dev_priv; - vmw_seqno_waiter_add(dev_priv); - if (dma_fence_add_callback(&fence->base, &ctx->base, - seqno_waiter_rm_cb) < 0) { - vmw_seqno_waiter_remove(dev_priv); - kfree(ctx); - } } } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 588d50ababf6..c2294abbe753 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -1,32 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2011-2023 VMware, Inc., Palo Alto, CA., USA - * - * 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. + * Copyright (c) 2009-2025 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. * **************************************************************************/ -#include <linux/sched/signal.h> - #include "vmwgfx_drv.h" #define VMW_FENCE_WRAP (1 << 31) @@ -35,14 +14,7 @@ struct vmw_fence_manager { struct vmw_private *dev_priv; spinlock_t lock; struct list_head fence_list; - struct work_struct work; bool fifo_down; - struct list_head cleanup_list; - uint32_t pending_actions[VMW_ACTION_MAX]; - struct mutex goal_irq_mutex; - bool goal_irq_on; /* Protected by @goal_irq_mutex */ - bool seqno_valid; /* Protected by @lock, and may not be set to true - without the @goal_irq_mutex held. */ u64 ctx; }; @@ -52,12 +24,10 @@ struct vmw_user_fence { }; /** - * struct vmw_event_fence_action - fence action that delivers a drm event. + * struct vmw_event_fence_action - fence callback that delivers a DRM event. * - * @action: A struct vmw_fence_action to hook up to a fence. + * @base: For use with dma_fence_add_callback(...) * @event: A pointer to the pending event. - * @fence: A referenced pointer to the fence to keep it alive while @action - * hangs on it. * @dev: Pointer to a struct drm_device so we can access the event stuff. * @tv_sec: If non-null, the variable pointed to will be assigned * current time tv_sec val when the fence signals. @@ -65,10 +35,9 @@ struct vmw_user_fence { * be assigned the current time tv_usec val when the fence signals. */ struct vmw_event_fence_action { - struct vmw_fence_action action; + struct dma_fence_cb base; struct drm_pending_event *event; - struct vmw_fence_obj *fence; struct drm_device *dev; uint32_t *tv_sec; @@ -81,44 +50,6 @@ fman_from_fence(struct vmw_fence_obj *fence) return container_of(fence->base.lock, struct vmw_fence_manager, lock); } -static u32 vmw_fence_goal_read(struct vmw_private *vmw) -{ - if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0) - return vmw_read(vmw, SVGA_REG_FENCE_GOAL); - else - return vmw_fifo_mem_read(vmw, SVGA_FIFO_FENCE_GOAL); -} - -static void vmw_fence_goal_write(struct vmw_private *vmw, u32 value) -{ - if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0) - vmw_write(vmw, SVGA_REG_FENCE_GOAL, value); - else - vmw_fifo_mem_write(vmw, SVGA_FIFO_FENCE_GOAL, value); -} - -/* - * Note on fencing subsystem usage of irqs: - * Typically the vmw_fences_update function is called - * - * a) When a new fence seqno has been submitted by the fifo code. - * b) On-demand when we have waiters. Sleeping waiters will switch on the - * ANY_FENCE irq and call vmw_fences_update function each time an ANY_FENCE - * irq is received. When the last fence waiter is gone, that IRQ is masked - * away. - * - * In situations where there are no waiters and we don't submit any new fences, - * fence objects may not be signaled. This is perfectly OK, since there are - * no consumers of the signaled data, but that is NOT ok when there are fence - * actions attached to a fence. The fencing subsystem then makes use of the - * FENCE_GOAL irq and sets the fence goal seqno to that of the next fence - * which has an action attached, and each time vmw_fences_update is called, - * the subsystem makes sure the fence goal seqno is updated. - * - * The fence goal seqno irq is on as long as there are unsignaled fence - * objects with actions attached to them. - */ - static void vmw_fence_obj_destroy(struct dma_fence *f) { struct vmw_fence_obj *fence = @@ -126,8 +57,21 @@ static void vmw_fence_obj_destroy(struct dma_fence *f) struct vmw_fence_manager *fman = fman_from_fence(fence); if (!list_empty(&fence->head)) { + /* The fence manager still has an implicit reference to this + * fence via the fence list if head is set. Because the lock is + * required to be held when the fence manager updates the fence + * list either the fence will have been removed after we get + * the lock below or we can safely remove it and the fence + * manager will never see it. This implies the fence is being + * deleted without being signaled which is dubious but valid + * if there are no callbacks. The dma_fence code that calls + * this hook will warn about deleted unsignaled with callbacks + * so no need to warn again here. + */ spin_lock(&fman->lock); list_del_init(&fence->head); + if (fence->waiter_added) + vmw_seqno_waiter_remove(fman->dev_priv); spin_unlock(&fman->lock); } fence->destroy(fence); @@ -143,165 +87,46 @@ static const char *vmw_fence_get_timeline_name(struct dma_fence *f) return "svga"; } +/* When we toggle signaling for the SVGA device there is a race period from + * the time we first read the fence seqno to the time we enable interrupts. + * If we miss the interrupt for a fence during this period its likely the driver + * will stall. As a result we need to re-read the seqno after interrupts are + * enabled. If interrupts were already enabled we just increment the number of + * seqno waiters. + */ static bool vmw_fence_enable_signaling(struct dma_fence *f) { + u32 seqno; struct vmw_fence_obj *fence = container_of(f, struct vmw_fence_obj, base); struct vmw_fence_manager *fman = fman_from_fence(fence); struct vmw_private *dev_priv = fman->dev_priv; - - u32 seqno = vmw_fence_read(dev_priv); - if (seqno - fence->base.seqno < VMW_FENCE_WRAP) +check_for_race: + seqno = vmw_fence_read(dev_priv); + if (seqno - fence->base.seqno < VMW_FENCE_WRAP) { + if (fence->waiter_added) { + vmw_seqno_waiter_remove(dev_priv); + fence->waiter_added = false; + } return false; - + } else if (!fence->waiter_added) { + fence->waiter_added = true; + if (vmw_seqno_waiter_add(dev_priv)) + goto check_for_race; + } return true; } -struct vmwgfx_wait_cb { - struct dma_fence_cb base; - struct task_struct *task; -}; - -static void -vmwgfx_wait_cb(struct dma_fence *fence, struct dma_fence_cb *cb) -{ - struct vmwgfx_wait_cb *wait = - container_of(cb, struct vmwgfx_wait_cb, base); - - wake_up_process(wait->task); -} - -static void __vmw_fences_update(struct vmw_fence_manager *fman); - -static long vmw_fence_wait(struct dma_fence *f, bool intr, signed long timeout) -{ - struct vmw_fence_obj *fence = - container_of(f, struct vmw_fence_obj, base); - - struct vmw_fence_manager *fman = fman_from_fence(fence); - struct vmw_private *dev_priv = fman->dev_priv; - struct vmwgfx_wait_cb cb; - long ret = timeout; - - if (likely(vmw_fence_obj_signaled(fence))) - return timeout; - - vmw_seqno_waiter_add(dev_priv); - - spin_lock(f->lock); - - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &f->flags)) - goto out; - - if (intr && signal_pending(current)) { - ret = -ERESTARTSYS; - goto out; - } - - cb.base.func = vmwgfx_wait_cb; - cb.task = current; - list_add(&cb.base.node, &f->cb_list); - - for (;;) { - __vmw_fences_update(fman); - - /* - * We can use the barrier free __set_current_state() since - * DMA_FENCE_FLAG_SIGNALED_BIT + wakeup is protected by the - * fence spinlock. - */ - if (intr) - __set_current_state(TASK_INTERRUPTIBLE); - else - __set_current_state(TASK_UNINTERRUPTIBLE); - - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &f->flags)) { - if (ret == 0 && timeout > 0) - ret = 1; - break; - } - - if (intr && signal_pending(current)) { - ret = -ERESTARTSYS; - break; - } - - if (ret == 0) - break; - - spin_unlock(f->lock); - - ret = schedule_timeout(ret); - - spin_lock(f->lock); - } - __set_current_state(TASK_RUNNING); - if (!list_empty(&cb.base.node)) - list_del(&cb.base.node); - -out: - spin_unlock(f->lock); - - vmw_seqno_waiter_remove(dev_priv); - - return ret; -} +static u32 __vmw_fences_update(struct vmw_fence_manager *fman); static const struct dma_fence_ops vmw_fence_ops = { .get_driver_name = vmw_fence_get_driver_name, .get_timeline_name = vmw_fence_get_timeline_name, .enable_signaling = vmw_fence_enable_signaling, - .wait = vmw_fence_wait, .release = vmw_fence_obj_destroy, }; -/* - * Execute signal actions on fences recently signaled. - * This is done from a workqueue so we don't have to execute - * signal actions from atomic context. - */ - -static void vmw_fence_work_func(struct work_struct *work) -{ - struct vmw_fence_manager *fman = - container_of(work, struct vmw_fence_manager, work); - struct list_head list; - struct vmw_fence_action *action, *next_action; - bool seqno_valid; - - do { - INIT_LIST_HEAD(&list); - mutex_lock(&fman->goal_irq_mutex); - - spin_lock(&fman->lock); - list_splice_init(&fman->cleanup_list, &list); - seqno_valid = fman->seqno_valid; - spin_unlock(&fman->lock); - - if (!seqno_valid && fman->goal_irq_on) { - fman->goal_irq_on = false; - vmw_goal_waiter_remove(fman->dev_priv); - } - mutex_unlock(&fman->goal_irq_mutex); - - if (list_empty(&list)) - return; - - /* - * At this point, only we should be able to manipulate the - * list heads of the actions we have on the private list. - * hence fman::lock not held. - */ - - list_for_each_entry_safe(action, next_action, &list, head) { - list_del_init(&action->head); - if (action->cleanup) - action->cleanup(action); - } - } while (1); -} - struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv) { struct vmw_fence_manager *fman = kzalloc(sizeof(*fman), GFP_KERNEL); @@ -312,10 +137,7 @@ struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv) fman->dev_priv = dev_priv; spin_lock_init(&fman->lock); INIT_LIST_HEAD(&fman->fence_list); - INIT_LIST_HEAD(&fman->cleanup_list); - INIT_WORK(&fman->work, &vmw_fence_work_func); fman->fifo_down = true; - mutex_init(&fman->goal_irq_mutex); fman->ctx = dma_fence_context_alloc(1); return fman; @@ -325,11 +147,8 @@ void vmw_fence_manager_takedown(struct vmw_fence_manager *fman) { bool lists_empty; - (void) cancel_work_sync(&fman->work); - spin_lock(&fman->lock); - lists_empty = list_empty(&fman->fence_list) && - list_empty(&fman->cleanup_list); + lists_empty = list_empty(&fman->fence_list); spin_unlock(&fman->lock); BUG_ON(!lists_empty); @@ -344,7 +163,6 @@ static int vmw_fence_obj_init(struct vmw_fence_manager *fman, dma_fence_init(&fence->base, &vmw_fence_ops, &fman->lock, fman->ctx, seqno); - INIT_LIST_HEAD(&fence->seq_passed_actions); fence->destroy = destroy; spin_lock(&fman->lock); @@ -352,6 +170,11 @@ static int vmw_fence_obj_init(struct vmw_fence_manager *fman, ret = -EBUSY; goto out_unlock; } + /* This creates an implicit reference to the fence from the fence + * manager. It will be dropped when the fence is signaled which is + * expected to happen before deletion. The dtor has code to catch + * the rare deletion before signaling case. + */ list_add_tail(&fence->head, &fman->fence_list); out_unlock: @@ -360,148 +183,35 @@ out_unlock: } -static void vmw_fences_perform_actions(struct vmw_fence_manager *fman, - struct list_head *list) -{ - struct vmw_fence_action *action, *next_action; - - list_for_each_entry_safe(action, next_action, list, head) { - list_del_init(&action->head); - fman->pending_actions[action->type]--; - if (action->seq_passed != NULL) - action->seq_passed(action); - - /* - * Add the cleanup action to the cleanup list so that - * it will be performed by a worker task. - */ - - list_add_tail(&action->head, &fman->cleanup_list); - } -} - -/** - * vmw_fence_goal_new_locked - Figure out a new device fence goal - * seqno if needed. - * - * @fman: Pointer to a fence manager. - * @passed_seqno: The seqno the device currently signals as passed. - * - * This function should be called with the fence manager lock held. - * It is typically called when we have a new passed_seqno, and - * we might need to update the fence goal. It checks to see whether - * the current fence goal has already passed, and, in that case, - * scans through all unsignaled fences to get the next fence object with an - * action attached, and sets the seqno of that fence as a new fence goal. - * - * returns true if the device goal seqno was updated. False otherwise. - */ -static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman, - u32 passed_seqno) -{ - u32 goal_seqno; - struct vmw_fence_obj *fence, *next_fence; - - if (likely(!fman->seqno_valid)) - return false; - - goal_seqno = vmw_fence_goal_read(fman->dev_priv); - if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP)) - return false; - - fman->seqno_valid = false; - list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) { - if (!list_empty(&fence->seq_passed_actions)) { - fman->seqno_valid = true; - vmw_fence_goal_write(fman->dev_priv, - fence->base.seqno); - break; - } - } - - return true; -} - - -/** - * vmw_fence_goal_check_locked - Replace the device fence goal seqno if - * needed. - * - * @fence: Pointer to a struct vmw_fence_obj the seqno of which should be - * considered as a device fence goal. - * - * This function should be called with the fence manager lock held. - * It is typically called when an action has been attached to a fence to - * check whether the seqno of that fence should be used for a fence - * goal interrupt. This is typically needed if the current fence goal is - * invalid, or has a higher seqno than that of the current fence object. - * - * returns true if the device goal seqno was updated. False otherwise. - */ -static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence) -{ - struct vmw_fence_manager *fman = fman_from_fence(fence); - u32 goal_seqno; - - if (dma_fence_is_signaled_locked(&fence->base)) - return false; - - goal_seqno = vmw_fence_goal_read(fman->dev_priv); - if (likely(fman->seqno_valid && - goal_seqno - fence->base.seqno < VMW_FENCE_WRAP)) - return false; - - vmw_fence_goal_write(fman->dev_priv, fence->base.seqno); - fman->seqno_valid = true; - - return true; -} - -static void __vmw_fences_update(struct vmw_fence_manager *fman) +static u32 __vmw_fences_update(struct vmw_fence_manager *fman) { struct vmw_fence_obj *fence, *next_fence; - struct list_head action_list; - bool needs_rerun; - uint32_t seqno, new_seqno; + const bool cookie = dma_fence_begin_signalling(); + const u32 seqno = vmw_fence_read(fman->dev_priv); - seqno = vmw_fence_read(fman->dev_priv); -rerun: list_for_each_entry_safe(fence, next_fence, &fman->fence_list, head) { if (seqno - fence->base.seqno < VMW_FENCE_WRAP) { list_del_init(&fence->head); + if (fence->waiter_added) { + vmw_seqno_waiter_remove(fman->dev_priv); + fence->waiter_added = false; + } dma_fence_signal_locked(&fence->base); - INIT_LIST_HEAD(&action_list); - list_splice_init(&fence->seq_passed_actions, - &action_list); - vmw_fences_perform_actions(fman, &action_list); } else break; } - - /* - * Rerun if the fence goal seqno was updated, and the - * hardware might have raced with that update, so that - * we missed a fence_goal irq. - */ - - needs_rerun = vmw_fence_goal_new_locked(fman, seqno); - if (unlikely(needs_rerun)) { - new_seqno = vmw_fence_read(fman->dev_priv); - if (new_seqno != seqno) { - seqno = new_seqno; - goto rerun; - } - } - - if (!list_empty(&fman->cleanup_list)) - (void) schedule_work(&fman->work); + dma_fence_end_signalling(cookie); + atomic_set_release(&fman->dev_priv->last_read_seqno, seqno); + return seqno; } -void vmw_fences_update(struct vmw_fence_manager *fman) +u32 vmw_fences_update(struct vmw_fence_manager *fman) { + u32 seqno; spin_lock(&fman->lock); - __vmw_fences_update(fman); + seqno = __vmw_fences_update(fman); spin_unlock(&fman->lock); + return seqno; } bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence) @@ -539,14 +249,13 @@ int vmw_fence_create(struct vmw_fence_manager *fman, struct vmw_fence_obj **p_fence) { struct vmw_fence_obj *fence; - int ret; + int ret; fence = kzalloc(sizeof(*fence), GFP_KERNEL); if (unlikely(!fence)) return -ENOMEM; - ret = vmw_fence_obj_init(fman, fence, seqno, - vmw_fence_destroy); + ret = vmw_fence_obj_init(fman, fence, seqno, vmw_fence_destroy); if (unlikely(ret != 0)) goto out_err_init; @@ -638,7 +347,6 @@ out_no_object: void vmw_fence_fifo_down(struct vmw_fence_manager *fman) { - struct list_head action_list; int ret; /* @@ -661,10 +369,6 @@ void vmw_fence_fifo_down(struct vmw_fence_manager *fman) if (unlikely(ret != 0)) { list_del_init(&fence->head); dma_fence_signal(&fence->base); - INIT_LIST_HEAD(&action_list); - list_splice_init(&fence->seq_passed_actions, - &action_list); - vmw_fences_perform_actions(fman, &action_list); } BUG_ON(!list_empty(&fence->head)); @@ -778,7 +482,6 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data, (struct drm_vmw_fence_signaled_arg *) data; struct ttm_base_object *base; struct vmw_fence_obj *fence; - struct vmw_fence_manager *fman; struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; struct vmw_private *dev_priv = vmw_priv(dev); @@ -787,14 +490,11 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data, return PTR_ERR(base); fence = &(container_of(base, struct vmw_user_fence, base)->fence); - fman = fman_from_fence(fence); arg->signaled = vmw_fence_obj_signaled(fence); arg->signaled_flags = arg->flags; - spin_lock(&fman->lock); - arg->passed_seqno = dev_priv->last_read_seqno; - spin_unlock(&fman->lock); + arg->passed_seqno = atomic_read_acquire(&dev_priv->last_read_seqno); ttm_base_object_unref(&base); @@ -822,10 +522,11 @@ int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data, * attached has passed. It queues the event on the submitter's event list. * This function is always called from atomic context. */ -static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) +static void vmw_event_fence_action_seq_passed(struct dma_fence *f, + struct dma_fence_cb *cb) { struct vmw_event_fence_action *eaction = - container_of(action, struct vmw_event_fence_action, action); + container_of(cb, struct vmw_event_fence_action, base); struct drm_device *dev = eaction->dev; struct drm_pending_event *event = eaction->event; @@ -837,7 +538,7 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) if (likely(eaction->tv_sec != NULL)) { struct timespec64 ts; - ktime_get_ts64(&ts); + ktime_to_timespec64(f->timestamp); /* monotonic time, so no y2038 overflow */ *eaction->tv_sec = ts.tv_sec; *eaction->tv_usec = ts.tv_nsec / NSEC_PER_USEC; @@ -846,75 +547,10 @@ static void vmw_event_fence_action_seq_passed(struct vmw_fence_action *action) drm_send_event_locked(dev, eaction->event); eaction->event = NULL; spin_unlock_irq(&dev->event_lock); -} - -/** - * vmw_event_fence_action_cleanup - * - * @action: The struct vmw_fence_action embedded in a struct - * vmw_event_fence_action. - * - * This function is the struct vmw_fence_action destructor. It's typically - * called from a workqueue. - */ -static void vmw_event_fence_action_cleanup(struct vmw_fence_action *action) -{ - struct vmw_event_fence_action *eaction = - container_of(action, struct vmw_event_fence_action, action); - - vmw_fence_obj_unreference(&eaction->fence); + dma_fence_put(f); kfree(eaction); } - -/** - * vmw_fence_obj_add_action - Add an action to a fence object. - * - * @fence: The fence object. - * @action: The action to add. - * - * Note that the action callbacks may be executed before this function - * returns. - */ -static void vmw_fence_obj_add_action(struct vmw_fence_obj *fence, - struct vmw_fence_action *action) -{ - struct vmw_fence_manager *fman = fman_from_fence(fence); - bool run_update = false; - - mutex_lock(&fman->goal_irq_mutex); - spin_lock(&fman->lock); - - fman->pending_actions[action->type]++; - if (dma_fence_is_signaled_locked(&fence->base)) { - struct list_head action_list; - - INIT_LIST_HEAD(&action_list); - list_add_tail(&action->head, &action_list); - vmw_fences_perform_actions(fman, &action_list); - } else { - list_add_tail(&action->head, &fence->seq_passed_actions); - - /* - * This function may set fman::seqno_valid, so it must - * be run with the goal_irq_mutex held. - */ - run_update = vmw_fence_goal_check_locked(fence); - } - - spin_unlock(&fman->lock); - - if (run_update) { - if (!fman->goal_irq_on) { - fman->goal_irq_on = true; - vmw_goal_waiter_add(fman->dev_priv); - } - vmw_fences_update(fman); - } - mutex_unlock(&fman->goal_irq_mutex); - -} - /** * vmw_event_fence_action_queue - Post an event for sending when a fence * object seqno has passed. @@ -949,18 +585,14 @@ int vmw_event_fence_action_queue(struct drm_file *file_priv, return -ENOMEM; eaction->event = event; - - eaction->action.seq_passed = vmw_event_fence_action_seq_passed; - eaction->action.cleanup = vmw_event_fence_action_cleanup; - eaction->action.type = VMW_ACTION_EVENT; - - eaction->fence = vmw_fence_obj_reference(fence); eaction->dev = &fman->dev_priv->drm; eaction->tv_sec = tv_sec; eaction->tv_usec = tv_usec; - vmw_fence_obj_add_action(fence, &eaction->action); - + vmw_fence_obj_reference(fence); // Dropped in CB + if (dma_fence_add_callback(&fence->base, &eaction->base, + vmw_event_fence_action_seq_passed) < 0) + vmw_event_fence_action_seq_passed(&fence->base, &eaction->base); return 0; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h index a7eee579c76a..e897cccae1ae 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.h @@ -39,27 +39,10 @@ struct drm_pending_event; struct vmw_private; struct vmw_fence_manager; -/** - * - * - */ -enum vmw_action_type { - VMW_ACTION_EVENT = 0, - VMW_ACTION_MAX -}; - -struct vmw_fence_action { - struct list_head head; - enum vmw_action_type type; - void (*seq_passed) (struct vmw_fence_action *action); - void (*cleanup) (struct vmw_fence_action *action); -}; - struct vmw_fence_obj { struct dma_fence base; - + bool waiter_added; struct list_head head; - struct list_head seq_passed_actions; void (*destroy)(struct vmw_fence_obj *fence); }; @@ -86,7 +69,7 @@ vmw_fence_obj_reference(struct vmw_fence_obj *fence) return fence; } -extern void vmw_fences_update(struct vmw_fence_manager *fman); +u32 vmw_fences_update(struct vmw_fence_manager *fman); extern bool vmw_fence_obj_signaled(struct vmw_fence_obj *fence); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index 086e69a130d4..05773eb394d3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c @@ -123,26 +123,17 @@ static bool vmw_fifo_idle(struct vmw_private *dev_priv, uint32_t seqno) return (vmw_read(dev_priv, SVGA_REG_BUSY) == 0); } -void vmw_update_seqno(struct vmw_private *dev_priv) -{ - uint32_t seqno = vmw_fence_read(dev_priv); - - if (dev_priv->last_read_seqno != seqno) { - dev_priv->last_read_seqno = seqno; - vmw_fences_update(dev_priv->fman); - } -} - bool vmw_seqno_passed(struct vmw_private *dev_priv, uint32_t seqno) { bool ret; + u32 last_read_seqno = atomic_read_acquire(&dev_priv->last_read_seqno); - if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP)) + if (last_read_seqno - seqno < VMW_FENCE_WRAP) return true; - vmw_update_seqno(dev_priv); - if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP)) + last_read_seqno = vmw_fences_update(dev_priv->fman); + if (last_read_seqno - seqno < VMW_FENCE_WRAP) return true; if (!vmw_has_fences(dev_priv) && vmw_fifo_idle(dev_priv, seqno)) @@ -239,51 +230,59 @@ out_err: return ret; } -void vmw_generic_waiter_add(struct vmw_private *dev_priv, +bool vmw_generic_waiter_add(struct vmw_private *dev_priv, u32 flag, int *waiter_count) { - spin_lock_bh(&dev_priv->waiter_lock); + bool hw_programmed = false; + + spin_lock(&dev_priv->waiter_lock); if ((*waiter_count)++ == 0) { vmw_irq_status_write(dev_priv, flag); dev_priv->irq_mask |= flag; vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); + hw_programmed = true; } - spin_unlock_bh(&dev_priv->waiter_lock); + spin_unlock(&dev_priv->waiter_lock); + return hw_programmed; } -void vmw_generic_waiter_remove(struct vmw_private *dev_priv, +bool vmw_generic_waiter_remove(struct vmw_private *dev_priv, u32 flag, int *waiter_count) { - spin_lock_bh(&dev_priv->waiter_lock); + bool hw_programmed = false; + + spin_lock(&dev_priv->waiter_lock); if (--(*waiter_count) == 0) { dev_priv->irq_mask &= ~flag; vmw_write(dev_priv, SVGA_REG_IRQMASK, dev_priv->irq_mask); + hw_programmed = true; } - spin_unlock_bh(&dev_priv->waiter_lock); + spin_unlock(&dev_priv->waiter_lock); + return hw_programmed; } -void vmw_seqno_waiter_add(struct vmw_private *dev_priv) +bool vmw_seqno_waiter_add(struct vmw_private *dev_priv) { - vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_ANY_FENCE, - &dev_priv->fence_queue_waiters); + return vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_ANY_FENCE, + &dev_priv->fence_queue_waiters); } -void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) +bool vmw_seqno_waiter_remove(struct vmw_private *dev_priv) { - vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_ANY_FENCE, - &dev_priv->fence_queue_waiters); + return vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_ANY_FENCE, + &dev_priv->fence_queue_waiters); } -void vmw_goal_waiter_add(struct vmw_private *dev_priv) +bool vmw_goal_waiter_add(struct vmw_private *dev_priv) { - vmw_generic_waiter_add(dev_priv, vmw_irqflag_fence_goal(dev_priv), - &dev_priv->goal_queue_waiters); + return vmw_generic_waiter_add(dev_priv, vmw_irqflag_fence_goal(dev_priv), + &dev_priv->goal_queue_waiters); } -void vmw_goal_waiter_remove(struct vmw_private *dev_priv) +bool vmw_goal_waiter_remove(struct vmw_private *dev_priv) { - vmw_generic_waiter_remove(dev_priv, vmw_irqflag_fence_goal(dev_priv), - &dev_priv->goal_queue_waiters); + return vmw_generic_waiter_remove(dev_priv, vmw_irqflag_fence_goal(dev_priv), + &dev_priv->goal_queue_waiters); } static void vmw_irq_preinstall(struct drm_device *dev) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c index 7fb1c88bcc47..69dfe69ce0f8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c @@ -896,7 +896,7 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv, .busy_domain = VMW_BO_DOMAIN_SYS, .bo_type = ttm_bo_type_device, .size = size, - .pin = true, + .pin = false, .keep_resv = true, }; diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c index 7d9a31868ea9..0f598e7bb159 100644 --- a/drivers/gpu/drm/xe/xe_device.c +++ b/drivers/gpu/drm/xe/xe_device.c @@ -1167,7 +1167,8 @@ void xe_device_declare_wedged(struct xe_device *xe) /* Notify userspace of wedged device */ drm_dev_wedged_event(&xe->drm, - DRM_WEDGE_RECOVERY_REBIND | DRM_WEDGE_RECOVERY_BUS_RESET); + DRM_WEDGE_RECOVERY_REBIND | DRM_WEDGE_RECOVERY_BUS_RESET, + NULL); } for_each_gt(gt, xe, id) diff --git a/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h b/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h index 4c39f01e4f52..a3f421e2adc0 100644 --- a/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h +++ b/drivers/gpu/drm/xe/xe_guc_exec_queue_types.h @@ -20,6 +20,8 @@ struct xe_exec_queue; struct xe_guc_exec_queue { /** @q: Backpointer to parent xe_exec_queue */ struct xe_exec_queue *q; + /** @rcu: For safe freeing of exported dma fences */ + struct rcu_head rcu; /** @sched: GPU scheduler for this xe_exec_queue */ struct xe_gpu_scheduler sched; /** @entity: Scheduler entity for this xe_exec_queue */ diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c index 7170e78e5b8e..df7a5a4eec74 100644 --- a/drivers/gpu/drm/xe/xe_guc_submit.c +++ b/drivers/gpu/drm/xe/xe_guc_submit.c @@ -1299,7 +1299,11 @@ static void __guc_exec_queue_fini_async(struct work_struct *w) xe_sched_entity_fini(&ge->entity); xe_sched_fini(&ge->sched); - kfree(ge); + /* + * RCU free due sched being exported via DRM scheduler fences + * (timeline name). + */ + kfree_rcu(ge, rcu); xe_exec_queue_fini(q); xe_pm_runtime_put(guc_to_xe(guc)); } @@ -1482,6 +1486,7 @@ static int guc_exec_queue_init(struct xe_exec_queue *q) q->guc = ge; ge->q = q; + init_rcu_head(&ge->rcu); init_waitqueue_head(&ge->suspend_wait); for (i = 0; i < MAX_STATIC_MSG_TYPE; ++i) diff --git a/drivers/gpu/drm/xe/xe_hw_fence.c b/drivers/gpu/drm/xe/xe_hw_fence.c index 03eb8c6d1616..b2a0c46dfcd4 100644 --- a/drivers/gpu/drm/xe/xe_hw_fence.c +++ b/drivers/gpu/drm/xe/xe_hw_fence.c @@ -100,6 +100,9 @@ void xe_hw_fence_irq_finish(struct xe_hw_fence_irq *irq) spin_unlock_irqrestore(&irq->lock, flags); dma_fence_end_signalling(tmp); } + + /* Safe release of the irq->lock used in dma_fence_init. */ + synchronize_rcu(); } void xe_hw_fence_irq_run(struct xe_hw_fence_irq *irq) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 5df981920a94..c3da6c0bfca6 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -61,6 +61,23 @@ config HDMI endif # HAS_IOMEM +config FIRMWARE_EDID + bool "Enable firmware EDID" + depends on X86 + help + This enables access to the EDID transferred from the firmware. + On x86, this is from the VESA BIOS. DRM display drivers will + be able to export the information to userspace. + + Also enable this if DDC/I2C transfers do not work for your driver + and if you are using nvidiafb, i810fb or savagefb. + + In general, choosing Y for this option is safe. If you + experience extremely long delays while booting before you get + something on your display, try setting this to N. Matrox cards in + combination with certain motherboards and monitors are known to + suffer from this problem. + if VT source "drivers/video/console/Kconfig" endif @@ -70,5 +87,4 @@ if FB_CORE || SGI_NEWPORT_CONSOLE endif - endmenu diff --git a/drivers/video/fbdev/c2p_iplan2.c b/drivers/video/fbdev/c2p_iplan2.c index cfd2361f24b1..ee4b315d3f40 100644 --- a/drivers/video/fbdev/c2p_iplan2.c +++ b/drivers/video/fbdev/c2p_iplan2.c @@ -8,6 +8,7 @@ * for more details. */ +#include <linux/export.h> #include <linux/module.h> #include <linux/string.h> diff --git a/drivers/video/fbdev/c2p_planar.c b/drivers/video/fbdev/c2p_planar.c index 819c82a98ac0..236aad5137ef 100644 --- a/drivers/video/fbdev/c2p_planar.c +++ b/drivers/video/fbdev/c2p_planar.c @@ -8,6 +8,7 @@ * for more details. */ +#include <linux/export.h> #include <linux/module.h> #include <linux/string.h> diff --git a/drivers/video/fbdev/core/Kconfig b/drivers/video/fbdev/core/Kconfig index 4abe12db7594..b38c3b776bce 100644 --- a/drivers/video/fbdev/core/Kconfig +++ b/drivers/video/fbdev/core/Kconfig @@ -10,21 +10,6 @@ config FB_CORE config FB_NOTIFY bool -config FIRMWARE_EDID - bool "Enable firmware EDID" - depends on FB - help - This enables access to the EDID transferred from the firmware. - On the i386, this is from the Video BIOS. Enable this if DDC/I2C - transfers do not work for your driver and if you are using - nvidiafb, i810fb or savagefb. - - In general, choosing Y for this option is safe. If you - experience extremely long delays while booting before you get - something on your display, try setting this to N. Matrox cards in - combination with certain motherboards and monitors are known to - suffer from this problem. - config FB_DEVICE bool "Provide legacy /dev/fb* device" depends on FB_CORE diff --git a/drivers/video/fbdev/core/cfbcopyarea.c b/drivers/video/fbdev/core/cfbcopyarea.c index 23fbf3a8df7c..ce2e6807be60 100644 --- a/drivers/video/fbdev/core/cfbcopyarea.c +++ b/drivers/video/fbdev/core/cfbcopyarea.c @@ -2,6 +2,8 @@ /* * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ + +#include <linux/export.h> #include <linux/module.h> #include <linux/fb.h> #include <linux/bitrev.h> diff --git a/drivers/video/fbdev/core/cfbfillrect.c b/drivers/video/fbdev/core/cfbfillrect.c index 615de89256d5..bd2fbbda10c6 100644 --- a/drivers/video/fbdev/core/cfbfillrect.c +++ b/drivers/video/fbdev/core/cfbfillrect.c @@ -2,6 +2,8 @@ /* * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ + +#include <linux/export.h> #include <linux/module.h> #include <linux/fb.h> #include <linux/bitrev.h> diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c index bcec4e32c0e7..e116cd1d8a39 100644 --- a/drivers/video/fbdev/core/cfbimgblt.c +++ b/drivers/video/fbdev/core/cfbimgblt.c @@ -2,6 +2,8 @@ /* * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ + +#include <linux/export.h> #include <linux/module.h> #include <linux/fb.h> #include <linux/bitrev.h> diff --git a/drivers/video/fbdev/core/fb_ddc.c b/drivers/video/fbdev/core/fb_ddc.c index e25143219862..824796361367 100644 --- a/drivers/video/fbdev/core/fb_ddc.c +++ b/drivers/video/fbdev/core/fb_ddc.c @@ -10,6 +10,7 @@ #include <linux/delay.h> #include <linux/device.h> +#include <linux/export.h> #include <linux/module.h> #include <linux/fb.h> #include <linux/i2c-algo-bit.h> diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c index 4fc93f253e06..8df2e51e3390 100644 --- a/drivers/video/fbdev/core/fb_defio.c +++ b/drivers/video/fbdev/core/fb_defio.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> +#include <linux/export.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/vmalloc.h> diff --git a/drivers/video/fbdev/core/fb_io_fops.c b/drivers/video/fbdev/core/fb_io_fops.c index 3408ff1b2b7a..6ab60fcd0050 100644 --- a/drivers/video/fbdev/core/fb_io_fops.c +++ b/drivers/video/fbdev/core/fb_io_fops.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 +#include <linux/export.h> #include <linux/fb.h> #include <linux/module.h> #include <linux/uaccess.h> diff --git a/drivers/video/fbdev/core/fb_sys_fops.c b/drivers/video/fbdev/core/fb_sys_fops.c index a9aa6519a5b3..be96b3b3942e 100644 --- a/drivers/video/fbdev/core/fb_sys_fops.c +++ b/drivers/video/fbdev/core/fb_sys_fops.c @@ -9,6 +9,8 @@ * for more details. * */ + +#include <linux/export.h> #include <linux/fb.h> #include <linux/module.h> #include <linux/uaccess.h> diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c index ff09e57f3c38..9cc3e87da14b 100644 --- a/drivers/video/fbdev/core/fbcmap.c +++ b/drivers/video/fbdev/core/fbcmap.c @@ -11,6 +11,7 @@ * more details. */ +#include <linux/export.h> #include <linux/string.h> #include <linux/module.h> #include <linux/fb.h> diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 2df48037688d..25684f5d6523 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -56,6 +56,7 @@ * more details. */ +#include <linux/export.h> #include <linux/module.h> #include <linux/types.h> #include <linux/fs.h> diff --git a/drivers/video/fbdev/core/fbmon.c b/drivers/video/fbdev/core/fbmon.c index 0a26399dbc89..3b779c27c271 100644 --- a/drivers/video/fbdev/core/fbmon.c +++ b/drivers/video/fbdev/core/fbmon.c @@ -26,6 +26,8 @@ * for more details. * */ + +#include <linux/export.h> #include <linux/fb.h> #include <linux/module.h> #include <linux/pci.h> @@ -1482,13 +1484,12 @@ int fb_validate_mode(const struct fb_var_screeninfo *var, struct fb_info *info) -EINVAL : 0; } -#if defined(CONFIG_FIRMWARE_EDID) && defined(CONFIG_X86) - /* * We need to ensure that the EDID block is only returned for * the primary graphics adapter. */ +#if defined(CONFIG_FIRMWARE_EDID) const unsigned char *fb_firmware_edid(struct device *device) { struct pci_dev *dev = NULL; diff --git a/drivers/video/fbdev/core/modedb.c b/drivers/video/fbdev/core/modedb.c index 7196b055f2bd..53a610948c4a 100644 --- a/drivers/video/fbdev/core/modedb.c +++ b/drivers/video/fbdev/core/modedb.c @@ -11,6 +11,7 @@ * more details. */ +#include <linux/export.h> #include <linux/module.h> #include <linux/slab.h> #include <linux/fb.h> diff --git a/drivers/video/fbdev/core/svgalib.c b/drivers/video/fbdev/core/svgalib.c index 821b89a0a645..d6053af749f6 100644 --- a/drivers/video/fbdev/core/svgalib.c +++ b/drivers/video/fbdev/core/svgalib.c @@ -10,6 +10,7 @@ * Some parts are based on David Boucher's viafb (http://davesdomain.org.uk/viafb/) */ +#include <linux/export.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/string.h> diff --git a/drivers/video/fbdev/core/syscopyarea.c b/drivers/video/fbdev/core/syscopyarea.c index b634e2d21208..773569bce67c 100644 --- a/drivers/video/fbdev/core/syscopyarea.c +++ b/drivers/video/fbdev/core/syscopyarea.c @@ -2,6 +2,8 @@ /* * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ + +#include <linux/export.h> #include <linux/module.h> #include <linux/fb.h> #include <linux/bitrev.h> diff --git a/drivers/video/fbdev/core/sysfillrect.c b/drivers/video/fbdev/core/sysfillrect.c index 372ca6a324c2..12eea3e424bb 100644 --- a/drivers/video/fbdev/core/sysfillrect.c +++ b/drivers/video/fbdev/core/sysfillrect.c @@ -2,6 +2,8 @@ /* * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ + +#include <linux/export.h> #include <linux/module.h> #include <linux/fb.h> #include <linux/bitrev.h> diff --git a/drivers/video/fbdev/core/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c index c756cc658b7d..0a5bfd8ad095 100644 --- a/drivers/video/fbdev/core/sysimgblt.c +++ b/drivers/video/fbdev/core/sysimgblt.c @@ -2,6 +2,8 @@ /* * Copyright (C) 2025 Zsolt Kajtar (soci@c64.rulez.org) */ + +#include <linux/export.h> #include <linux/module.h> #include <linux/fb.h> #include <linux/bitrev.h> diff --git a/drivers/video/fbdev/cyber2000fb.c b/drivers/video/fbdev/cyber2000fb.c index 986760b90465..5cb5ee517f81 100644 --- a/drivers/video/fbdev/cyber2000fb.c +++ b/drivers/video/fbdev/cyber2000fb.c @@ -1089,7 +1089,6 @@ void cyber2000fb_enable_extregs(struct cfb_info *cfb) cyber2000_grphw(EXT_FUNC_CTL, old, cfb); } } -EXPORT_SYMBOL(cyber2000fb_enable_extregs); /* * Disable access to the extended registers @@ -1109,41 +1108,6 @@ void cyber2000fb_disable_extregs(struct cfb_info *cfb) else cfb->func_use_count -= 1; } -EXPORT_SYMBOL(cyber2000fb_disable_extregs); - -/* - * Attach a capture/tv driver to the core CyberX0X0 driver. - */ -int cyber2000fb_attach(struct cyberpro_info *info, int idx) -{ - if (int_cfb_info != NULL) { - info->dev = int_cfb_info->fb.device; -#ifdef CONFIG_FB_CYBER2000_I2C - info->i2c = &int_cfb_info->i2c_adapter; -#else - info->i2c = NULL; -#endif - info->regs = int_cfb_info->regs; - info->irq = int_cfb_info->irq; - info->fb = int_cfb_info->fb.screen_base; - info->fb_size = int_cfb_info->fb.fix.smem_len; - info->info = int_cfb_info; - - strscpy(info->dev_name, int_cfb_info->fb.fix.id, - sizeof(info->dev_name)); - } - - return int_cfb_info != NULL; -} -EXPORT_SYMBOL(cyber2000fb_attach); - -/* - * Detach a capture/tv driver from the core CyberX0X0 driver. - */ -void cyber2000fb_detach(int idx) -{ -} -EXPORT_SYMBOL(cyber2000fb_detach); #ifdef CONFIG_FB_CYBER2000_DDC diff --git a/drivers/video/fbdev/cyber2000fb.h b/drivers/video/fbdev/cyber2000fb.h index 04641aa13acc..21095df8fdb0 100644 --- a/drivers/video/fbdev/cyber2000fb.h +++ b/drivers/video/fbdev/cyber2000fb.h @@ -488,7 +488,5 @@ struct cyberpro_info { * Note! Writing to the Cyber20x0 registers from an interrupt * routine is definitely a bad idea atm. */ -int cyber2000fb_attach(struct cyberpro_info *info, int idx); -void cyber2000fb_detach(int idx); void cyber2000fb_enable_extregs(struct cfb_info *cfb); void cyber2000fb_disable_extregs(struct cfb_info *cfb); diff --git a/drivers/video/fbdev/macmodes.c b/drivers/video/fbdev/macmodes.c index d6be3c67d3df..b16a9d9bef98 100644 --- a/drivers/video/fbdev/macmodes.c +++ b/drivers/video/fbdev/macmodes.c @@ -16,6 +16,7 @@ */ #include <linux/errno.h> +#include <linux/export.h> #include <linux/fb.h> #include <linux/string.h> #include <linux/module.h> @@ -236,7 +237,7 @@ int mac_vmode_to_var(int vmode, int cmode, struct fb_var_screeninfo *var) case CMODE_8: var->bits_per_pixel = 8; var->red.offset = 0; - var->red.length = 8; + var->red.length = 8; var->green.offset = 0; var->green.length = 8; var->blue.offset = 0; diff --git a/drivers/video/fbdev/matrox/g450_pll.c b/drivers/video/fbdev/matrox/g450_pll.c index ff8e321a22ce..e2c1478aa47f 100644 --- a/drivers/video/fbdev/matrox/g450_pll.c +++ b/drivers/video/fbdev/matrox/g450_pll.c @@ -14,6 +14,8 @@ * */ +#include <linux/export.h> + #include "g450_pll.h" #include "matroxfb_DAC1064.h" @@ -258,13 +260,13 @@ static inline unsigned int g450_findworkingpll(struct matrox_fb_info *minfo, unsigned int found = 0; unsigned int idx; unsigned int mnpfound = mnparray[0]; - + for (idx = 0; idx < mnpcount; idx++) { unsigned int sarray[3]; unsigned int *sptr; { unsigned int mnp; - + sptr = sarray; mnp = mnparray[idx]; if (mnp & 0x38) { @@ -277,7 +279,7 @@ static inline unsigned int g450_findworkingpll(struct matrox_fb_info *minfo, } while (sptr >= sarray) { unsigned int mnp = *sptr--; - + if (g450_testpll(minfo, mnp - 0x0300, pll) && g450_testpll(minfo, mnp + 0x0300, pll) && g450_testpll(minfo, mnp - 0x0200, pll) && @@ -310,12 +312,12 @@ static int g450_checkcache(struct matrox_fb_info *minfo, struct matrox_pll_cache *ci, unsigned int mnp_key) { unsigned int i; - + mnp_key &= G450_MNP_FREQBITS; for (i = 0; i < ci->valid; i++) { if (ci->data[i].mnp_key == mnp_key) { unsigned int mnp; - + mnp = ci->data[i].mnp_value; if (i) { memmove(ci->data + 1, ci->data, i * sizeof(*ci->data)); @@ -343,7 +345,7 @@ static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout, { u_int8_t tmp, xpwrctrl; unsigned long flags; - + matroxfb_DAC_lock_irqsave(flags); xpwrctrl = matroxfb_DAC_in(minfo, M1064_XPWRCTRL); @@ -375,7 +377,7 @@ static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout, } { u_int8_t misc; - + misc = mga_inb(M_MISC_REG_READ) & ~0x0C; switch (pll) { case M_PIXEL_PLL_A: @@ -409,13 +411,13 @@ static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout, u_int8_t tmp; unsigned int mnp; unsigned long flags; - + matroxfb_DAC_lock_irqsave(flags); tmp = matroxfb_DAC_in(minfo, M1064_XPWRCTRL); if (!(tmp & 2)) { matroxfb_DAC_out(minfo, M1064_XPWRCTRL, tmp | 2); } - + mnp = matroxfb_DAC_in(minfo, M1064_XPIXPLLCM) << 16; mnp |= matroxfb_DAC_in(minfo, M1064_XPIXPLLCN) << 8; matroxfb_DAC_unlock_irqrestore(flags); @@ -441,7 +443,7 @@ static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout, delta = pll_freq_delta(fout, g450_vco2f(mnp, vco)); for (idx = mnpcount; idx > 0; idx--) { /* == is important; due to nextpll algorithm we get - sorted equally good frequencies from lower VCO + sorted equally good frequencies from lower VCO frequency to higher - with <= lowest wins, while with < highest one wins */ if (delta <= deltaarray[idx-1]) { @@ -472,7 +474,7 @@ static int __g450_setclk(struct matrox_fb_info *minfo, unsigned int fout, { unsigned long flags; unsigned int mnp; - + matroxfb_DAC_lock_irqsave(flags); mnp = g450_checkcache(minfo, ci, mnparray[0]); if (mnp != NO_MORE_MNP) { @@ -495,7 +497,7 @@ int matroxfb_g450_setclk(struct matrox_fb_info *minfo, unsigned int fout, unsigned int pll) { unsigned int* arr; - + arr = kmalloc(sizeof(*arr) * MNP_TABLE_SIZE * 2, GFP_KERNEL); if (arr) { int r; diff --git a/drivers/video/fbdev/matrox/matroxfb_DAC1064.c b/drivers/video/fbdev/matrox/matroxfb_DAC1064.c index 398b7035f5a9..9a893b70ab19 100644 --- a/drivers/video/fbdev/matrox/matroxfb_DAC1064.c +++ b/drivers/video/fbdev/matrox/matroxfb_DAC1064.c @@ -13,6 +13,7 @@ * */ +#include <linux/export.h> #include "matroxfb_DAC1064.h" #include "matroxfb_misc.h" @@ -43,11 +44,11 @@ static void DAC1064_calcclock(const struct matrox_fb_info *minfo, unsigned int p; DBG(__func__) - + /* only for devices older than G450 */ fvco = PLL_calcclock(minfo, freq, fmax, in, feed, &p); - + p = (1 << p) - 1; if (fvco <= 100000) ; @@ -169,7 +170,7 @@ static void g450_set_plls(struct matrox_fb_info *minfo) struct matrox_hw_state *hw = &minfo->hw; int pixelmnp; int videomnp; - + c2_ctl = hw->crtc2.ctl & ~0x4007; /* Clear PLL + enable for CRTC2 */ c2_ctl |= 0x0001; /* Enable CRTC2 */ hw->DACreg[POS1064_XPWRCTRL] &= ~0x02; /* Stop VIDEO PLL */ @@ -192,7 +193,7 @@ static void g450_set_plls(struct matrox_fb_info *minfo) } c2_ctl |= 0x0006; /* Use video PLL */ hw->DACreg[POS1064_XPWRCTRL] |= 0x02; - + outDAC1064(minfo, M1064_XPWRCTRL, hw->DACreg[POS1064_XPWRCTRL]); matroxfb_g450_setpll_cond(minfo, videomnp, M_VIDEO_PLL); } @@ -200,7 +201,7 @@ static void g450_set_plls(struct matrox_fb_info *minfo) hw->DACreg[POS1064_XPIXCLKCTRL] &= ~M1064_XPIXCLKCTRL_PLL_UP; if (pixelmnp >= 0) { hw->DACreg[POS1064_XPIXCLKCTRL] |= M1064_XPIXCLKCTRL_PLL_UP; - + outDAC1064(minfo, M1064_XPIXCLKCTRL, hw->DACreg[POS1064_XPIXCLKCTRL]); matroxfb_g450_setpll_cond(minfo, pixelmnp, M_PIXEL_PLL_C); } @@ -303,9 +304,9 @@ void DAC1064_global_init(struct matrox_fb_info *minfo) poweroff TMDS. But if we boot with DFP connected, TMDS generated clocks are used instead of ALL pixclocks available... If someone knows which register - handles it, please reveal this secret to me... */ + handles it, please reveal this secret to me... */ hw->DACreg[POS1064_XPWRCTRL] &= ~0x04; /* Poweroff TMDS */ -#endif +#endif break; } /* Now set timming related variables... */ @@ -728,14 +729,14 @@ static void g450_mclk_init(struct matrox_fb_info *minfo) } else { unsigned long flags; unsigned int pwr; - + matroxfb_DAC_lock_irqsave(flags); pwr = inDAC1064(minfo, M1064_XPWRCTRL) & ~0x02; outDAC1064(minfo, M1064_XPWRCTRL, pwr); matroxfb_DAC_unlock_irqrestore(flags); } matroxfb_g450_setclk(minfo, minfo->values.pll.system, M_SYSTEM_PLL); - + /* switch clocks to their real PLL source(s) */ pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg | 4); pci_write_config_dword(minfo->pcidev, PCI_OPTION3_REG, minfo->values.reg.opt3); @@ -748,15 +749,15 @@ static void g450_memory_init(struct matrox_fb_info *minfo) /* disable memory refresh */ minfo->hw.MXoptionReg &= ~0x001F8000; pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); - + /* set memory interface parameters */ minfo->hw.MXoptionReg &= ~0x00207E00; minfo->hw.MXoptionReg |= 0x00207E00 & minfo->values.reg.opt; pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); pci_write_config_dword(minfo->pcidev, PCI_OPTION2_REG, minfo->values.reg.opt2); - + mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst); - + /* first set up memory interface with disabled memory interface clocks */ pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc & ~0x80000000U); mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk); @@ -765,25 +766,25 @@ static void g450_memory_init(struct matrox_fb_info *minfo) pci_write_config_dword(minfo->pcidev, PCI_MEMMISC_REG, minfo->values.reg.memmisc | 0x80000000U); udelay(200); - + if (minfo->values.memory.ddr && (!minfo->values.memory.emrswen || !minfo->values.memory.dll)) { mga_outl(M_MEMRDBK, minfo->values.reg.memrdbk & ~0x1000); } mga_outl(M_MACCESS, minfo->values.reg.maccess | 0x8000); - + udelay(200); - + minfo->hw.MXoptionReg |= 0x001F8000 & minfo->values.reg.opt; pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); - + /* value is written to memory chips only if old != new */ mga_outl(M_PLNWT, 0); mga_outl(M_PLNWT, ~0); - + if (minfo->values.reg.mctlwtst != minfo->values.reg.mctlwtst_core) { mga_outl(M_CTLWTST, minfo->values.reg.mctlwtst_core); } - + } static void g450_preinit(struct matrox_fb_info *minfo) @@ -791,7 +792,7 @@ static void g450_preinit(struct matrox_fb_info *minfo) u_int32_t c2ctl; u_int8_t curctl; u_int8_t c1ctl; - + /* minfo->hw.MXoptionReg = minfo->values.reg.opt; */ minfo->hw.MXoptionReg &= 0xC0000100; minfo->hw.MXoptionReg |= 0x00000020; @@ -805,7 +806,7 @@ static void g450_preinit(struct matrox_fb_info *minfo) pci_write_config_dword(minfo->pcidev, PCI_OPTION_REG, minfo->hw.MXoptionReg); /* Init system clocks */ - + /* stop crtc2 */ c2ctl = mga_inl(M_C2CTL); mga_outl(M_C2CTL, c2ctl & ~1); @@ -818,20 +819,20 @@ static void g450_preinit(struct matrox_fb_info *minfo) g450_mclk_init(minfo); g450_memory_init(minfo); - + /* set legacy VGA clock sources for DOSEmu or VMware... */ matroxfb_g450_setclk(minfo, 25175, M_PIXEL_PLL_A); matroxfb_g450_setclk(minfo, 28322, M_PIXEL_PLL_B); /* restore crtc1 */ mga_setr(M_SEQ_INDEX, 1, c1ctl); - + /* restore cursor */ outDAC1064(minfo, M1064_XCURCTRL, curctl); /* restore crtc2 */ mga_outl(M_C2CTL, c2ctl); - + return; } diff --git a/drivers/video/fbdev/matrox/matroxfb_Ti3026.c b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c index f53b8066e8a5..4eb636cd1f89 100644 --- a/drivers/video/fbdev/matrox/matroxfb_Ti3026.c +++ b/drivers/video/fbdev/matrox/matroxfb_Ti3026.c @@ -79,6 +79,7 @@ * */ +#include <linux/export.h> #include "matroxfb_Ti3026.h" #include "matroxfb_misc.h" diff --git a/drivers/video/fbdev/matrox/matroxfb_accel.c b/drivers/video/fbdev/matrox/matroxfb_accel.c index 52e15dc6f45b..2670db392da2 100644 --- a/drivers/video/fbdev/matrox/matroxfb_accel.c +++ b/drivers/video/fbdev/matrox/matroxfb_accel.c @@ -77,6 +77,8 @@ * */ +#include <linux/export.h> + #include "matroxfb_accel.h" #include "matroxfb_DAC1064.h" #include "matroxfb_Ti3026.h" diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c index 81603ce05a22..5be0cdcd7c71 100644 --- a/drivers/video/fbdev/matrox/matroxfb_base.c +++ b/drivers/video/fbdev/matrox/matroxfb_base.c @@ -101,6 +101,7 @@ */ #include <linux/aperture.h> +#include <linux/export.h> #include <linux/version.h> #include "matroxfb_base.h" diff --git a/drivers/video/fbdev/matrox/matroxfb_g450.c b/drivers/video/fbdev/matrox/matroxfb_g450.c index df3309fd14f3..800c05b70ee3 100644 --- a/drivers/video/fbdev/matrox/matroxfb_g450.c +++ b/drivers/video/fbdev/matrox/matroxfb_g450.c @@ -13,6 +13,8 @@ * */ +#include <linux/export.h> + #include "matroxfb_base.h" #include "matroxfb_misc.h" #include "matroxfb_DAC1064.h" @@ -32,29 +34,29 @@ struct mctl { #define WLMAX 0x3FF static const struct mctl g450_controls[] = -{ { { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER, +{ { { V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER, "brightness", - 0, WLMAX-BLMIN, 1, 370-BLMIN, + 0, WLMAX-BLMIN, 1, 370-BLMIN, 0, }, offsetof(struct matrox_fb_info, altout.tvo_params.brightness) }, - { { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER, + { { V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER, "contrast", - 0, 1023, 1, 127, + 0, 1023, 1, 127, 0, }, offsetof(struct matrox_fb_info, altout.tvo_params.contrast) }, { { V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER, "saturation", - 0, 255, 1, 165, + 0, 255, 1, 165, 0, }, offsetof(struct matrox_fb_info, altout.tvo_params.saturation) }, { { V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER, "hue", - 0, 255, 1, 0, + 0, 255, 1, 0, 0, }, offsetof(struct matrox_fb_info, altout.tvo_params.hue) }, { { MATROXFB_CID_TESTOUT, V4L2_CTRL_TYPE_BOOLEAN, "test output", - 0, 1, 1, 0, + 0, 1, 1, 0, 0, }, offsetof(struct matrox_fb_info, altout.tvo_params.testout) }, }; @@ -89,7 +91,7 @@ static inline int *get_ctrl_ptr(struct matrox_fb_info *minfo, unsigned int idx) static void tvo_fill_defaults(struct matrox_fb_info *minfo) { unsigned int i; - + for (i = 0; i < G450CTRLS; i++) { *get_ctrl_ptr(minfo, i) = g450_controls[i].desc.default_value; } @@ -99,7 +101,7 @@ static int cve2_get_reg(struct matrox_fb_info *minfo, int reg) { unsigned long flags; int val; - + matroxfb_DAC_lock_irqsave(flags); matroxfb_DAC_out(minfo, 0x87, reg); val = matroxfb_DAC_in(minfo, 0x88); @@ -141,16 +143,16 @@ static void g450_compute_bwlevel(const struct matrox_fb_info *minfo, int *bl, static int g450_query_ctrl(void* md, struct v4l2_queryctrl *p) { int i; - + i = get_ctrl_id(p->id); if (i >= 0) { *p = g450_controls[i].desc; return 0; } if (i == -ENOENT) { - static const struct v4l2_queryctrl disctrl = + static const struct v4l2_queryctrl disctrl = { .flags = V4L2_CTRL_FLAG_DISABLED }; - + i = p->id; *p = disctrl; p->id = i; @@ -163,7 +165,7 @@ static int g450_query_ctrl(void* md, struct v4l2_queryctrl *p) { static int g450_set_ctrl(void* md, struct v4l2_control *p) { int i; struct matrox_fb_info *minfo = md; - + i = get_ctrl_id(p->id); if (i < 0) return -EINVAL; @@ -209,7 +211,7 @@ static int g450_set_ctrl(void* md, struct v4l2_control *p) { } break; } - + return 0; } @@ -217,7 +219,7 @@ static int g450_set_ctrl(void* md, struct v4l2_control *p) { static int g450_get_ctrl(void* md, struct v4l2_control *p) { int i; struct matrox_fb_info *minfo = md; - + i = get_ctrl_id(p->id); if (i < 0) return -EINVAL; p->value = *get_ctrl_ptr(minfo, i); @@ -247,22 +249,22 @@ static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r, unsigned long long piic; int mnp; int over; - + r->regs[0x80] = 0x03; /* | 0x40 for SCART */ hvis = ((mt->HDisplay << 1) + 3) & ~3; - + if (hvis >= 2048) { hvis = 2044; } - + piic = 1000000000ULL * hvis; do_div(piic, outd->h_vis); dprintk(KERN_DEBUG "Want %u kHz pixclock\n", (unsigned int)piic); - + mnp = matroxfb_g450_setclk(minfo, piic, M_VIDEO_PLL); - + mt->mnp = mnp; mt->pixclock = g450_mnp2f(minfo, mnp); @@ -275,7 +277,7 @@ static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r, piic = outd->chromasc; do_div(piic, mt->pixclock); chromasc = piic; - + dprintk(KERN_DEBUG "Chroma is %08X\n", chromasc); r->regs[0] = piic >> 24; @@ -287,7 +289,7 @@ static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r, hsl = (((outd->h_sync + pixclock) / pixclock)) & ~1; hlen = hvis + hfp + hsl + hbp; over = hlen & 0x0F; - + dprintk(KERN_DEBUG "WL: vis=%u, hf=%u, hs=%u, hb=%u, total=%u\n", hvis, hfp, hsl, hbp, hlen); if (over) { @@ -310,14 +312,14 @@ static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r, r->regs[0x2C] = hfp; r->regs[0x31] = hvis / 8; r->regs[0x32] = hvis & 7; - + dprintk(KERN_DEBUG "PG: vis=%04X, hf=%02X, hs=%02X, hb=%02X, total=%04X\n", hvis, hfp, hsl, hbp, hlen); r->regs[0x84] = 1; /* x sync point */ r->regs[0x85] = 0; hvis = hvis >> 1; hlen = hlen >> 1; - + dprintk(KERN_DEBUG "hlen=%u hvis=%u\n", hlen, hvis); mt->interlaced = 1; @@ -332,13 +334,13 @@ static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r, unsigned int vtotal; unsigned int vsyncend; unsigned int vdisplay; - + vtotal = mt->VTotal; vsyncend = mt->VSyncEnd; vdisplay = mt->VDisplay; if (vtotal < outd->v_total) { unsigned int yovr = outd->v_total - vtotal; - + vsyncend += yovr >> 1; } else if (vtotal > outd->v_total) { vdisplay = outd->v_total - 4; @@ -350,7 +352,7 @@ static void computeRegs(struct matrox_fb_info *minfo, struct mavenregs *r, r->regs[0x33] = upper - 1; /* upper blanking */ r->regs[0x82] = upper; /* y sync point */ r->regs[0x83] = upper >> 8; - + mt->VDisplay = vdisplay; mt->VSyncStart = outd->v_total - 2; mt->VSyncEnd = outd->v_total; @@ -509,9 +511,9 @@ static void cve2_init_TV(struct matrox_fb_info *minfo, LR(0x80); LR(0x82); LR(0x83); LR(0x84); LR(0x85); - + cve2_set_reg(minfo, 0x3E, 0x01); - + for (i = 0; i < 0x3E; i++) { LR(i); } @@ -558,7 +560,7 @@ static int matroxfb_g450_compute(void* md, struct my_timming* mt) { static int matroxfb_g450_program(void* md) { struct matrox_fb_info *minfo = md; - + if (minfo->outputs[1].mode != MATROXFB_OUTPUT_MODE_MONITOR) { cve2_init_TV(minfo, &minfo->hw.maven); } diff --git a/drivers/video/fbdev/matrox/matroxfb_misc.c b/drivers/video/fbdev/matrox/matroxfb_misc.c index 8f159a2ad8d0..2c5f0099532b 100644 --- a/drivers/video/fbdev/matrox/matroxfb_misc.c +++ b/drivers/video/fbdev/matrox/matroxfb_misc.c @@ -85,6 +85,7 @@ * */ +#include <linux/export.h> #include "matroxfb_misc.h" #include <linux/interrupt.h> @@ -390,7 +391,7 @@ void matroxfb_vgaHWrestore(struct matrox_fb_info *minfo) static void get_pins(unsigned char __iomem* pins, struct matrox_bios* bd) { unsigned int b0 = readb(pins); - + if (b0 == 0x2E && readb(pins+1) == 0x41) { unsigned int pins_len = readb(pins+2); unsigned int i; @@ -426,7 +427,7 @@ static void get_pins(unsigned char __iomem* pins, struct matrox_bios* bd) { static void get_bios_version(unsigned char __iomem * vbios, struct matrox_bios* bd) { unsigned int pcir_offset; - + pcir_offset = readb(vbios + 24) | (readb(vbios + 25) << 8); if (pcir_offset >= 26 && pcir_offset < 0xFFE0 && readb(vbios + pcir_offset ) == 'P' && @@ -451,7 +452,7 @@ static void get_bios_version(unsigned char __iomem * vbios, struct matrox_bios* static void get_bios_output(unsigned char __iomem* vbios, struct matrox_bios* bd) { unsigned char b; - + b = readb(vbios + 0x7FF1); if (b == 0xFF) { b = 0; @@ -461,7 +462,7 @@ static void get_bios_output(unsigned char __iomem* vbios, struct matrox_bios* bd static void get_bios_tvout(unsigned char __iomem* vbios, struct matrox_bios* bd) { unsigned int i; - + /* Check for 'IBM .*(V....TVO' string - it means TVO BIOS */ bd->output.tvout = 0; if (readb(vbios + 0x1D) != 'I' || @@ -472,7 +473,7 @@ static void get_bios_tvout(unsigned char __iomem* vbios, struct matrox_bios* bd) } for (i = 0x2D; i < 0x2D + 128; i++) { unsigned char b = readb(vbios + i); - + if (b == '(' && readb(vbios + i + 1) == 'V') { if (readb(vbios + i + 6) == 'T' && readb(vbios + i + 7) == 'V' && @@ -488,7 +489,7 @@ static void get_bios_tvout(unsigned char __iomem* vbios, struct matrox_bios* bd) static void parse_bios(unsigned char __iomem* vbios, struct matrox_bios* bd) { unsigned int pins_offset; - + if (readb(vbios) != 0x55 || readb(vbios + 1) != 0xAA) { return; } @@ -648,9 +649,9 @@ static int parse_pins5(struct matrox_fb_info *minfo, const struct matrox_bios *bd) { unsigned int mult; - + mult = bd->pins[4]?8000:6000; - + minfo->limits.pixel.vcomax = (bd->pins[ 38] == 0xFF) ? 600000 : bd->pins[ 38] * mult; minfo->limits.system.vcomax = (bd->pins[ 36] == 0xFF) ? minfo->limits.pixel.vcomax : bd->pins[ 36] * mult; minfo->limits.video.vcomax = (bd->pins[ 37] == 0xFF) ? minfo->limits.system.vcomax : bd->pins[ 37] * mult; @@ -770,7 +771,7 @@ void matroxfb_read_pins(struct matrox_fb_info *minfo) u32 biosbase; u32 fbbase; struct pci_dev *pdev = minfo->pcidev; - + memset(&minfo->bios, 0, sizeof(minfo->bios)); pci_read_config_dword(pdev, PCI_OPTION_REG, &opt); pci_write_config_dword(pdev, PCI_OPTION_REG, opt | PCI_OPTION_ENABLE_ROM); @@ -790,7 +791,7 @@ void matroxfb_read_pins(struct matrox_fb_info *minfo) } else { unsigned int ven = readb(b+0x64+0) | (readb(b+0x64+1) << 8); unsigned int dev = readb(b+0x64+2) | (readb(b+0x64+3) << 8); - + if (ven != pdev->vendor || dev != pdev->device) { printk(KERN_INFO "matroxfb: Legacy BIOS is for %04X:%04X, while this device is %04X:%04X\n", ven, dev, pdev->vendor, pdev->device); diff --git a/drivers/video/fbdev/mb862xx/mb862xx-i2c.c b/drivers/video/fbdev/mb862xx/mb862xx-i2c.c index ffdb1597d303..08b7f19a67a5 100644 --- a/drivers/video/fbdev/mb862xx/mb862xx-i2c.c +++ b/drivers/video/fbdev/mb862xx/mb862xx-i2c.c @@ -9,7 +9,6 @@ #include <linux/i2c.h> #include <linux/io.h> #include <linux/delay.h> -#include <linux/export.h> #include "mb862xxfb.h" #include "mb862xx_reg.h" diff --git a/drivers/video/fbdev/omap/lcd_dma.c b/drivers/video/fbdev/omap/lcd_dma.c index 0da23c57e475..56300be71c57 100644 --- a/drivers/video/fbdev/omap/lcd_dma.c +++ b/drivers/video/fbdev/omap/lcd_dma.c @@ -18,6 +18,7 @@ * Support functions for the OMAP internal DMA channels. */ +#include <linux/export.h> #include <linux/module.h> #include <linux/spinlock.h> #include <linux/interrupt.h> diff --git a/drivers/video/fbdev/omap/lcdc.c b/drivers/video/fbdev/omap/lcdc.c index abb8b11464e8..53ca58ec5eed 100644 --- a/drivers/video/fbdev/omap/lcdc.c +++ b/drivers/video/fbdev/omap/lcdc.c @@ -5,8 +5,10 @@ * Copyright (C) 2004 Nokia Corporation * Author: Imre Deak <imre.deak@nokia.com> */ + #include <linux/module.h> #include <linux/device.h> +#include <linux/export.h> #include <linux/interrupt.h> #include <linux/spinlock.h> #include <linux/err.h> diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c index 2682b20d184a..106d21e74738 100644 --- a/drivers/video/fbdev/omap/omapfb_main.c +++ b/drivers/video/fbdev/omap/omapfb_main.c @@ -11,6 +11,8 @@ * Dirk Behme <dirk.behme@de.bosch.com> - changes for 2.6 kernel API * Texas Instruments - H3 support */ + +#include <linux/export.h> #include <linux/platform_device.h> #include <linux/mm.h> #include <linux/slab.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/apply.c b/drivers/video/fbdev/omap2/omapfb/dss/apply.c index acca991c7540..39947e569a54 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/apply.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/apply.c @@ -6,6 +6,7 @@ #define DSS_SUBSYS_NAME "APPLY" +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/core.c b/drivers/video/fbdev/omap2/omapfb/dss/core.c index 55b640f2f245..02ea41f6c8f4 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/core.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/core.c @@ -15,6 +15,7 @@ #include <linux/module.h> #include <linux/clk.h> #include <linux/err.h> +#include <linux/export.h> #include <linux/platform_device.h> #include <linux/seq_file.h> #include <linux/debugfs.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dispc-compat.c b/drivers/video/fbdev/omap2/omapfb/dss/dispc-compat.c index cc2ad787d493..7831c6a2eedb 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dispc-compat.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc-compat.c @@ -6,6 +6,7 @@ #define DSS_SUBSYS_NAME "APPLY" +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/slab.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/display.c b/drivers/video/fbdev/omap2/omapfb/dss/display.c index f91db94c9905..16543425bd84 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/display.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/display.c @@ -11,6 +11,7 @@ #define DSS_SUBSYS_NAME "DISPLAY" +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/jiffies.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dpi.c b/drivers/video/fbdev/omap2/omapfb/dss/dpi.c index 86ed4c077c30..ad8ae1727966 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dpi.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dpi.c @@ -13,7 +13,6 @@ #include <linux/kernel.h> #include <linux/delay.h> -#include <linux/export.h> #include <linux/err.h> #include <linux/errno.h> #include <linux/platform_device.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dss-of.c b/drivers/video/fbdev/omap2/omapfb/dss/dss-of.c index 7c636db79882..f90a8eff7259 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dss-of.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss-of.c @@ -6,6 +6,7 @@ #include <linux/device.h> #include <linux/err.h> +#include <linux/export.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_graph.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dss_features.c b/drivers/video/fbdev/omap2/omapfb/dss/dss_features.c index 62c2d48d9e09..38be57ba8c28 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dss_features.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss_features.c @@ -6,6 +6,7 @@ * Author: Archit Taneja <archit@ti.com> */ +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/types.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/manager.c b/drivers/video/fbdev/omap2/omapfb/dss/manager.c index 2c2da35345d0..c59e5689d6cc 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/manager.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/manager.c @@ -11,6 +11,7 @@ #define DSS_SUBSYS_NAME "MANAGER" +#include <linux/export.h> #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/output.c b/drivers/video/fbdev/omap2/omapfb/dss/output.c index 4e2992a0ce50..48cbfb75443f 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/output.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/output.c @@ -4,6 +4,7 @@ * Author: Archit Taneja <archit@ti.com> */ +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/platform_device.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/overlay.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay.c index 8c8e627da13d..bbbdc233ee61 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/overlay.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay.c @@ -14,6 +14,7 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/err.h> +#include <linux/export.h> #include <linux/sysfs.h> #include <linux/platform_device.h> #include <linux/delay.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/sdi.c b/drivers/video/fbdev/omap2/omapfb/dss/sdi.c index 2d3e5d4467c5..68e569ec0f83 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/sdi.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/sdi.c @@ -12,7 +12,6 @@ #include <linux/delay.h> #include <linux/err.h> #include <linux/regulator/consumer.h> -#include <linux/export.h> #include <linux/platform_device.h> #include <linux/string.h> #include <linux/of.h> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/venc.c b/drivers/video/fbdev/omap2/omapfb/dss/venc.c index f99dda9e55a5..ed283029ad95 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/venc.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/venc.c @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/clk.h> #include <linux/err.h> +#include <linux/export.h> #include <linux/io.h> #include <linux/mutex.h> #include <linux/completion.h> diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c index ea8c88aa4477..152dbeaa6451 100644 --- a/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c +++ b/drivers/video/fbdev/omap2/omapfb/omapfb-ioctl.c @@ -16,7 +16,6 @@ #include <linux/mm.h> #include <linux/omapfb.h> #include <linux/vmalloc.h> -#include <linux/export.h> #include <linux/sizes.h> #include <video/omapfb_dss.h> diff --git a/drivers/video/fbdev/omap2/omapfb/vrfb.c b/drivers/video/fbdev/omap2/omapfb/vrfb.c index 568e6e1eca62..675482cde519 100644 --- a/drivers/video/fbdev/omap2/omapfb/vrfb.c +++ b/drivers/video/fbdev/omap2/omapfb/vrfb.c @@ -9,6 +9,7 @@ /*#define DEBUG*/ #include <linux/err.h> +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/ioport.h> diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c index ee6da5084242..baf87f34cc24 100644 --- a/drivers/video/fbdev/pxafb.c +++ b/drivers/video/fbdev/pxafb.c @@ -1030,9 +1030,8 @@ static inline unsigned int get_pcd(struct pxafb_info *fbi, /* * Some touchscreens need hsync information from the video driver to - * function correctly. We export it here. Note that 'hsync_time' and - * the value returned from pxafb_get_hsync_time() is the *reciprocal* - * of the hsync period in seconds. + * function correctly. We export it here. Note that 'hsync_time' is + * the *reciprocal* of the hsync period in seconds. */ static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd) { @@ -1048,18 +1047,6 @@ static inline void set_hsync_time(struct pxafb_info *fbi, unsigned int pcd) fbi->hsync_time = htime; } -unsigned long pxafb_get_hsync_time(struct device *dev) -{ - struct pxafb_info *fbi = dev_get_drvdata(dev); - - /* If display is blanked/suspended, hsync isn't active */ - if (!fbi || (fbi->state != C_ENABLE)) - return 0; - - return fbi->hsync_time; -} -EXPORT_SYMBOL(pxafb_get_hsync_time); - static int setup_frame_dma(struct pxafb_info *fbi, int dma, int pal, unsigned long start, size_t size) { diff --git a/drivers/video/fbdev/sbuslib.c b/drivers/video/fbdev/sbuslib.c index 4c79654bda30..dd2002d0810f 100644 --- a/drivers/video/fbdev/sbuslib.c +++ b/drivers/video/fbdev/sbuslib.c @@ -5,6 +5,7 @@ */ #include <linux/compat.h> +#include <linux/export.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/string.h> diff --git a/drivers/video/fbdev/sis/sis.h b/drivers/video/fbdev/sis/sis.h index d632f096083b..3d658482c69d 100644 --- a/drivers/video/fbdev/sis/sis.h +++ b/drivers/video/fbdev/sis/sis.h @@ -673,9 +673,7 @@ unsigned int sisfb_read_mio_pci_word(struct SiS_Private *SiS_Pr, int reg); /* SiS-specific exported functions */ void sis_malloc(struct sis_memreq *req); -void sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req); void sis_free(u32 base); -void sis_free_new(struct pci_dev *pdev, u32 base); /* Routines from init.c/init301.c */ extern unsigned short SiS_GetModeID_LCD(int VGAEngine, unsigned int VBFlags, int HDisplay, diff --git a/drivers/video/fbdev/sis/sis_main.c b/drivers/video/fbdev/sis/sis_main.c index 75033e6be15a..84567d67f71d 100644 --- a/drivers/video/fbdev/sis/sis_main.c +++ b/drivers/video/fbdev/sis/sis_main.c @@ -3421,14 +3421,6 @@ sis_malloc(struct sis_memreq *req) req->offset = req->size = 0; } -void -sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req) -{ - struct sis_video_info *ivideo = pci_get_drvdata(pdev); - - sis_int_malloc(ivideo, req); -} - /* sis_free: u32 because "base" is offset inside video ram, can never be >4GB */ static void @@ -3455,14 +3447,6 @@ sis_free(u32 base) sis_int_free(ivideo, base); } -void -sis_free_new(struct pci_dev *pdev, u32 base) -{ - struct sis_video_info *ivideo = pci_get_drvdata(pdev); - - sis_int_free(ivideo, base); -} - /* --------------------- SetMode routines ------------------------- */ static void @@ -6832,12 +6816,3 @@ MODULE_PARM_DESC(videoram, #endif #endif /* /MODULE */ - -/* _GPL only for new symbols. */ -EXPORT_SYMBOL(sis_malloc); -EXPORT_SYMBOL(sis_free); -EXPORT_SYMBOL_GPL(sis_malloc_new); -EXPORT_SYMBOL_GPL(sis_free_new); - - - diff --git a/drivers/video/fbdev/via/via-core.c b/drivers/video/fbdev/via/via-core.c index 908524a74a38..a8d4a3e2c65e 100644 --- a/drivers/video/fbdev/via/via-core.c +++ b/drivers/video/fbdev/via/via-core.c @@ -9,6 +9,7 @@ * Core code for the Via multifunction framebuffer device. */ #include <linux/aperture.h> +#include <linux/export.h> #include <linux/via-core.h> #include <linux/via_i2c.h> #include "via-gpio.h" diff --git a/drivers/video/fbdev/via/via-gpio.c b/drivers/video/fbdev/via/via-gpio.c index 27226a8f3f42..72302384bf77 100644 --- a/drivers/video/fbdev/via/via-gpio.c +++ b/drivers/video/fbdev/via/via-gpio.c @@ -10,7 +10,6 @@ #include <linux/gpio/machine.h> #include <linux/platform_device.h> #include <linux/via-core.h> -#include <linux/export.h> #include "via-gpio.h" /* diff --git a/drivers/video/fbdev/via/via_i2c.c b/drivers/video/fbdev/via/via_i2c.c index cdbd7a9b8817..42c378425586 100644 --- a/drivers/video/fbdev/via/via_i2c.c +++ b/drivers/video/fbdev/via/via_i2c.c @@ -7,6 +7,7 @@ #include <linux/platform_device.h> #include <linux/delay.h> +#include <linux/export.h> #include <linux/spinlock.h> #include <linux/module.h> #include <linux/via-core.h> diff --git a/drivers/video/fbdev/wmt_ge_rops.c b/drivers/video/fbdev/wmt_ge_rops.c index 92fbb3f3a0d3..2bd26bfb2b46 100644 --- a/drivers/video/fbdev/wmt_ge_rops.c +++ b/drivers/video/fbdev/wmt_ge_rops.c @@ -7,6 +7,7 @@ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> */ +#include <linux/export.h> #include <linux/module.h> #include <linux/fb.h> #include <linux/io.h> diff --git a/include/drm/drm_device.h b/include/drm/drm_device.h index e2f894f1b90a..08b3b2467c4c 100644 --- a/include/drm/drm_device.h +++ b/include/drm/drm_device.h @@ -5,6 +5,7 @@ #include <linux/kref.h> #include <linux/mutex.h> #include <linux/idr.h> +#include <linux/sched.h> #include <drm/drm_mode_config.h> @@ -31,6 +32,14 @@ struct pci_controller; #define DRM_WEDGE_RECOVERY_BUS_RESET BIT(2) /* unbind + reset bus device + bind */ /** + * struct drm_wedge_task_info - information about the guilty task of a wedge dev + */ +struct drm_wedge_task_info { + pid_t pid; + char comm[TASK_COMM_LEN]; +}; + +/** * enum switch_power_state - power state of drm device */ diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 63b51942d606..3f76a32d6b84 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -487,7 +487,8 @@ void drm_put_dev(struct drm_device *dev); bool drm_dev_enter(struct drm_device *dev, int *idx); void drm_dev_exit(int idx); void drm_dev_unplug(struct drm_device *dev); -int drm_dev_wedged_event(struct drm_device *dev, unsigned long method); +int drm_dev_wedged_event(struct drm_device *dev, unsigned long method, + struct drm_wedge_task_info *info); /** * drm_dev_is_unplugged - is a DRM device unplugged diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index d8539174ca11..0d3ee2a1313f 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -102,6 +102,15 @@ void drm_fb_xrgb8888_to_bgr888(struct iosys_map *dst, const unsigned int *dst_pi void drm_fb_xrgb8888_to_argb8888(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, struct drm_format_conv_state *state); +void drm_fb_xrgb8888_to_abgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state); +void drm_fb_xrgb8888_to_xbgr8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state); +void drm_fb_xrgb8888_to_bgrx8888(struct iosys_map *dst, const unsigned int *dst_pitch, + const struct iosys_map *src, const struct drm_framebuffer *fb, + const struct drm_rect *clip, struct drm_format_conv_state *state); void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch, const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, @@ -125,8 +134,4 @@ void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitc const struct iosys_map *src, const struct drm_framebuffer *fb, const struct drm_rect *clip, struct drm_format_conv_state *state); -size_t drm_fb_build_fourcc_list(struct drm_device *dev, - const u32 *native_fourccs, size_t native_nfourccs, - u32 *fourccs_out, size_t nfourccs_out); - #endif /* __LINUX_DRM_FORMAT_HELPER_H */ diff --git a/include/linux/dma-fence.h b/include/linux/dma-fence.h index 10a849cb2d3f..64639e104110 100644 --- a/include/linux/dma-fence.h +++ b/include/linux/dma-fence.h @@ -378,15 +378,28 @@ bool dma_fence_remove_callback(struct dma_fence *fence, struct dma_fence_cb *cb); void dma_fence_enable_sw_signaling(struct dma_fence *fence); -static inline const char *dma_fence_driver_name(struct dma_fence *fence) -{ - return fence->ops->get_driver_name(fence); -} - -static inline const char *dma_fence_timeline_name(struct dma_fence *fence) -{ - return fence->ops->get_timeline_name(fence); -} +/** + * DOC: Safe external access to driver provided object members + * + * All data not stored directly in the dma-fence object, such as the + * &dma_fence.lock and memory potentially accessed by functions in the + * &dma_fence.ops table, MUST NOT be accessed after the fence has been signalled + * because after that point drivers are allowed to free it. + * + * All code accessing that data via the dma-fence API (or directly, which is + * discouraged), MUST make sure to contain the complete access within a + * &rcu_read_lock and &rcu_read_unlock pair. + * + * Some dma-fence API handles this automatically, while other, as for example + * &dma_fence_driver_name and &dma_fence_timeline_name, leave that + * responsibility to the caller. + * + * To enable this scheme to work drivers MUST ensure a RCU grace period elapses + * between signalling the fence and freeing the said data. + * + */ +const char __rcu *dma_fence_driver_name(struct dma_fence *fence); +const char __rcu *dma_fence_timeline_name(struct dma_fence *fence); /** * dma_fence_is_signaled_locked - Return an indication if the fence diff --git a/include/linux/platform_data/video-pxafb.h b/include/linux/platform_data/video-pxafb.h index 6333bac166a5..38c24c77ba43 100644 --- a/include/linux/platform_data/video-pxafb.h +++ b/include/linux/platform_data/video-pxafb.h @@ -150,7 +150,6 @@ struct pxafb_mach_info { }; void pxa_set_fb_info(struct device *, struct pxafb_mach_info *); -unsigned long pxafb_get_hsync_time(struct device *dev); /* smartpanel related */ #define SMART_CMD_A0 (0x1 << 8) diff --git a/include/trace/events/dma_fence.h b/include/trace/events/dma_fence.h index 84c83074ee81..4814a65b68dc 100644 --- a/include/trace/events/dma_fence.h +++ b/include/trace/events/dma_fence.h @@ -34,14 +34,44 @@ DECLARE_EVENT_CLASS(dma_fence, __entry->seqno) ); -DEFINE_EVENT(dma_fence, dma_fence_emit, +/* + * Safe only for call sites which are guaranteed to not race with fence + * signaling,holding the fence->lock and having checked for not signaled, or the + * signaling path itself. + */ +DECLARE_EVENT_CLASS(dma_fence_unsignaled, + + TP_PROTO(struct dma_fence *fence), + + TP_ARGS(fence), + + TP_STRUCT__entry( + __string(driver, fence->ops->get_driver_name(fence)) + __string(timeline, fence->ops->get_timeline_name(fence)) + __field(unsigned int, context) + __field(unsigned int, seqno) + ), + + TP_fast_assign( + __assign_str(driver); + __assign_str(timeline); + __entry->context = fence->context; + __entry->seqno = fence->seqno; + ), + + TP_printk("driver=%s timeline=%s context=%u seqno=%u", + __get_str(driver), __get_str(timeline), __entry->context, + __entry->seqno) +); + +DEFINE_EVENT(dma_fence_unsignaled, dma_fence_emit, TP_PROTO(struct dma_fence *fence), TP_ARGS(fence) ); -DEFINE_EVENT(dma_fence, dma_fence_init, +DEFINE_EVENT(dma_fence_unsignaled, dma_fence_init, TP_PROTO(struct dma_fence *fence), @@ -55,14 +85,14 @@ DEFINE_EVENT(dma_fence, dma_fence_destroy, TP_ARGS(fence) ); -DEFINE_EVENT(dma_fence, dma_fence_enable_signal, +DEFINE_EVENT(dma_fence_unsignaled, dma_fence_enable_signal, TP_PROTO(struct dma_fence *fence), TP_ARGS(fence) ); -DEFINE_EVENT(dma_fence, dma_fence_signaled, +DEFINE_EVENT(dma_fence_unsignaled, dma_fence_signaled, TP_PROTO(struct dma_fence *fence), diff --git a/include/uapi/drm/ivpu_accel.h b/include/uapi/drm/ivpu_accel.h index 2f24103f4533..160ee1411d4a 100644 --- a/include/uapi/drm/ivpu_accel.h +++ b/include/uapi/drm/ivpu_accel.h @@ -445,6 +445,9 @@ struct drm_ivpu_metric_streamer_get_data { __u64 data_size; }; +/* Command queue flags */ +#define DRM_IVPU_CMDQ_FLAG_TURBO 0x00000001 + /** * struct drm_ivpu_cmdq_create - Create command queue for job submission */ @@ -462,6 +465,17 @@ struct drm_ivpu_cmdq_create { * %DRM_IVPU_JOB_PRIORITY_REALTIME */ __u32 priority; + /** + * @flags: + * + * Supported flags: + * + * %DRM_IVPU_CMDQ_FLAG_TURBO + * + * Enable low-latency mode for the command queue. The NPU will maximize performance + * when executing jobs from such queue at the cost of increased power usage. + */ + __u32 flags; }; /** diff --git a/include/video/edid.h b/include/video/edid.h index f614371e9116..c2b186b1933a 100644 --- a/include/video/edid.h +++ b/include/video/edid.h @@ -4,7 +4,8 @@ #include <uapi/video/edid.h> -#ifdef CONFIG_X86 +#if defined(CONFIG_FIRMWARE_EDID) extern struct edid_info edid_info; #endif + #endif /* __linux_video_edid_h__ */ diff --git a/include/video/sisfb.h b/include/video/sisfb.h index 76ff628a1220..54e6632cd4a2 100644 --- a/include/video/sisfb.h +++ b/include/video/sisfb.h @@ -15,10 +15,4 @@ #define SIS_300_VGA 1 #define SIS_315_VGA 2 -#define SISFB_HAVE_MALLOC_NEW -extern void sis_malloc(struct sis_memreq *req); -extern void sis_malloc_new(struct pci_dev *pdev, struct sis_memreq *req); - -extern void sis_free(u32 base); -extern void sis_free_new(struct pci_dev *pdev, u32 base); #endif |