mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 20:54:03 +02:00
drm fixes for 7.2-rc7
shmem: - check VMA boundaries for PMD mappings xe: - Fix memory leak in exec_queue_set_hang_replay_state - Apply RCS/CCS yield policy to SR-IOV VFs amdgpu: - JPEG queue reset fixes - GC 12 fix - GMC 12.1 fixes - Lockdep false positive fix - Userq fix - Bounds checking fixes - Devcoredump fixes - DCN 2.0.1 fix - Aperture mapping fix - DC avmute fix - DC self refresh fix radeon: - Performance regression fix panthor: - skip zero sized firmware segments - check VMA boundaries for PMD mappings bridge: - ps8640: propagate AUX transfer register errors amdxdna: - Improve error handling in amdxdna_insert_pages. v3d: - serialise scheduler timeouts -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEEKbZHaGwW9KfbeusDHTzWXnEhr4FAmp2SKIACgkQDHTzWXnE hr7tMg/8Cr2JwdX1gtShUvxjcuil3Vb4pQbcKVCbAuDBvlXLLThAXqgb13y4CBsJ Isk6t4g4660HTDAmUBEfas0iP01rrp6f0qDVx7qFz6BkZJH9y0I4h4cuybUtKkX4 WXfYxV51+inWRI84++jPEdj6l9+acYVlbU1+/7LlGn2I2ggdxdDT9+Mo2v/92sUV P5tqOP9R7WxOHvDeGpRQqzhBSQYQVxVmjzXuRpQPEjxckYLIfCKZyDUeP4mPkFSE NcYksbB2bl186Vq4+KYd4P0uEAyYl27td0kQsJEpKvIRYrKVkEhq7gru70TBnPlE ZD1mnAhvDuHYoGlYcU5W5N5Pj2FKvpRqxfmwoT/HNP007rvVUOMVK7mDe7xyAj3j feAxFY7tAJduqx+DAOpU1IAtdPikrO/xjhxoGjUMtTeUOOebJNdNKK6O8dCMqcsX rl05bjWecGZwEmt+juEjVGeVjqIzQ+qAydPw/0OmxaQ/oQ307/ijTT61LG3yD81G fHdOdGdbV5JVn/D8TqPk6fPb5Vk+sRE/qznLVQhtI3u7/SstggiHpX6lTgRrOiO0 GI7pZuxl1zxQfV3/tj4jDBYi+ODA1Bs2enJwtq16FMkpqlEp/GpAb3S7qNNP1KI2 jm9NrVCYP0f3x2lT8CIy+mp2t+tg+RMyYK6kAbevRyrC65mQH3U= =6In+ -----END PGP SIGNATURE----- Merge tag 'drm-fixes-2026-08-08' of https://gitlab.freedesktop.org/drm/kernel Pull drm fixes from Dave Airlie: "Weekly fixes for drm, feels relatively quiet for the post-AI world, mostly amdgpu and xe with a few fixes across the board: shmem: - check VMA boundaries for PMD mappings xe: - Fix memory leak in exec_queue_set_hang_replay_state - Apply RCS/CCS yield policy to SR-IOV VFs amdgpu: - JPEG queue reset fixes - GC 12 fix - GMC 12.1 fixes - Lockdep false positive fix - Userq fix - Bounds checking fixes - Devcoredump fixes - DCN 2.0.1 fix - Aperture mapping fix - DC avmute fix - DC self refresh fix radeon: - Performance regression fix panthor: - skip zero sized firmware segments - check VMA boundaries for PMD mappings bridge: - ps8640: propagate AUX transfer register errors amdxdna: - Improve error handling in amdxdna_insert_pages. v3d: - serialise scheduler timeouts" * tag 'drm-fixes-2026-08-08' of https://gitlab.freedesktop.org/drm/kernel: (26 commits) drm/amd/display: allow self-refresh exit while entry is blocked drm/amdgpu: fix aperture iounmap skipped on device removal drm/amd/display: Check for tg ops in dce110_set_avmute Revert "drm/amdgpu: fix aperture mapping leak" drm/radeon: restore hardware polling in fence_is_signaled to fix performance regression drm/amd: Disable DP audio spread spectrum for Cyan Skillfish drm/amdgpu/gmc12.1: fix MMHUB0 check in pasid tlb flush drm/amdgpu: Allocate coredump ring buffers per ring drm/amdgpu: Use virtual alloc during coredump drm/amdgpu: reject oversized IBs with per-ring packet limits drm/amdgpu/userq: serialize queue map against GPU reset drm/amdgpu: Fix lockdep false positive in amdgpu_lockdep_init drm/amdgpu/gmc12.1: implement tlb inv semaphore drm/amdgpu: read TRUNCATE_COORD_MODE on gfx12 drm/amdgpu: fix JPEG v5.3.0 queue reset failure in DPG mode drm/amdgpu: fix JPEG v4.0.5 queue reset failure in DPG mode drm/amdgpu: fix JPEG v5.0.0 queue reset failure in DPG mode drm/panthor: Check VMA boundaries for PMD mappings drm/xe/uc: Apply RCS/CCS yield policy to SR-IOV VFs drm/xe: Fix memory leak in exec_queue_set_hang_replay_state() ...
This commit is contained in:
commit
bcc44b6785
|
|
@ -436,6 +436,23 @@ static void amdxdna_gem_dev_obj_free(struct drm_gem_object *gobj)
|
|||
amdxdna_gem_destroy_obj(abo);
|
||||
}
|
||||
|
||||
static void amdxdna_mark_mapp_invalid(struct amdxdna_gem_obj *abo,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
|
||||
struct amdxdna_umap *mapp;
|
||||
|
||||
down_write(&xdna->notifier_lock);
|
||||
abo->mem.map_invalid = true;
|
||||
list_for_each_entry(mapp, &abo->mem.umap_list, node) {
|
||||
if (compare_range(mapp, vma->vm_mm, vma->vm_start, vma->vm_end)) {
|
||||
mapp->invalid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
up_write(&xdna->notifier_lock);
|
||||
}
|
||||
|
||||
static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
|
||||
struct vm_area_struct *vma)
|
||||
{
|
||||
|
|
@ -450,26 +467,17 @@ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
|
|||
XDNA_ERR(xdna, "Failed shmem mmap %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The buffer is based on memory pages. Fix the flag. */
|
||||
vm_flags_mod(vma, VM_MIXEDMAP, VM_PFNMAP);
|
||||
ret = vm_insert_pages(vma, vma->vm_start, abo->base.pages,
|
||||
&num_pages);
|
||||
} else {
|
||||
vma->vm_private_data = NULL;
|
||||
vma->vm_ops = NULL;
|
||||
ret = dma_buf_mmap(abo->dma_buf, vma, 0);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Failed insert pages %d", ret);
|
||||
vma->vm_ops->close(vma);
|
||||
XDNA_ERR(xdna, "Failed to mmap dma buf %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
vma->vm_private_data = NULL;
|
||||
vma->vm_ops = NULL;
|
||||
ret = dma_buf_mmap(abo->dma_buf, vma, 0);
|
||||
if (ret) {
|
||||
XDNA_ERR(xdna, "Failed to mmap dma buf %d", ret);
|
||||
return ret;
|
||||
/* Drop the reference drm_gem_mmap_obj() acquired.*/
|
||||
drm_gem_object_put(to_gobj(abo));
|
||||
}
|
||||
|
||||
do {
|
||||
|
|
@ -478,17 +486,14 @@ static int amdxdna_insert_pages(struct amdxdna_gem_obj *abo,
|
|||
fault_ret = handle_mm_fault(vma, vma->vm_start + offset,
|
||||
FAULT_FLAG_WRITE, NULL);
|
||||
if (fault_ret & VM_FAULT_ERROR) {
|
||||
vma->vm_ops->close(vma);
|
||||
XDNA_ERR(xdna, "Fault in page failed");
|
||||
return -EFAULT;
|
||||
amdxdna_mark_mapp_invalid(abo, vma);
|
||||
break;
|
||||
}
|
||||
|
||||
offset += PAGE_SIZE;
|
||||
} while (--num_pages);
|
||||
|
||||
/* Drop the reference drm_gem_mmap_obj() acquired.*/
|
||||
drm_gem_object_put(to_gobj(abo));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,26 @@
|
|||
#include "amdgpu_ras.h"
|
||||
#include "amdgpu_hmm.h"
|
||||
|
||||
/*
|
||||
* Maximum IB length (dwords) for rings whose emit_ib packet format
|
||||
* documents a 20-bit size field.
|
||||
*/
|
||||
#define AMDGPU_GFX_SDMA_IB_PACKET_SIZE_MAX_DW 0xFFFFF
|
||||
#define AMDGPU_MM_IB_PACKET_SIZE_MAX_DW 0x7FFFF0
|
||||
|
||||
static u32 amdgpu_cs_ib_packet_size_max_dw(enum amdgpu_ring_type type)
|
||||
{
|
||||
switch (type) {
|
||||
case AMDGPU_RING_TYPE_GFX:
|
||||
case AMDGPU_RING_TYPE_COMPUTE:
|
||||
case AMDGPU_RING_TYPE_SDMA:
|
||||
case AMDGPU_RING_TYPE_VPE:
|
||||
return AMDGPU_GFX_SDMA_IB_PACKET_SIZE_MAX_DW;
|
||||
default:
|
||||
return AMDGPU_MM_IB_PACKET_SIZE_MAX_DW;
|
||||
}
|
||||
}
|
||||
|
||||
static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p,
|
||||
struct amdgpu_device *adev,
|
||||
struct drm_file *filp,
|
||||
|
|
@ -345,7 +365,6 @@ static int amdgpu_cs_p2_ib(struct amdgpu_cs_parser *p,
|
|||
|
||||
job = p->jobs[r];
|
||||
ring = amdgpu_job_ring(job);
|
||||
ib = &job->ibs[job->num_ibs++];
|
||||
|
||||
/* submissions to kernel queues are disabled */
|
||||
if (ring->no_user_submission)
|
||||
|
|
@ -374,6 +393,12 @@ static int amdgpu_cs_p2_ib(struct amdgpu_cs_parser *p,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (chunk_ib->ib_bytes / 4 >
|
||||
amdgpu_cs_ib_packet_size_max_dw(ring->funcs->type))
|
||||
return -EINVAL;
|
||||
|
||||
ib = &job->ibs[job->num_ibs++];
|
||||
|
||||
if (chunk_ib->flags & AMDGPU_IB_FLAG_PREAMBLE)
|
||||
job->preamble_status |= AMDGPU_PREAMBLE_IB_PRESENT;
|
||||
|
||||
|
|
|
|||
|
|
@ -342,7 +342,7 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
|
|||
struct amdgpu_ip_block *ip_block;
|
||||
struct amdgpu_ring *ring;
|
||||
int ver, i, j;
|
||||
u32 ring_idx, off;
|
||||
u32 ring_idx;
|
||||
bool sizing_pass;
|
||||
|
||||
sizing_pass = buffer == NULL;
|
||||
|
|
@ -442,7 +442,6 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
|
|||
for (i = 0; i < coredump->num_rings; i++) {
|
||||
ring_idx = coredump->rings[i].ring_index;
|
||||
ring = coredump->adev->rings[ring_idx];
|
||||
off = coredump->rings[i].offset;
|
||||
|
||||
drm_printf(&p, "ring name: %s\n", ring->name);
|
||||
drm_printf(&p, "Rptr: 0x%llx Wptr: 0x%llx RB mask: %x\n",
|
||||
|
|
@ -451,12 +450,18 @@ amdgpu_devcoredump_format(char *buffer, size_t count, struct amdgpu_coredump_inf
|
|||
ring->buf_mask);
|
||||
drm_printf(&p, "Ring size in dwords: %d\n",
|
||||
ring->ring_size / 4);
|
||||
|
||||
if (!coredump->rings[i].ring_dw) {
|
||||
drm_printf(&p, "Ring contents unavailable\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
drm_printf(&p, "Ring contents\n");
|
||||
drm_printf(&p, "Offset \t Value\n");
|
||||
|
||||
for (j = 0; j < ring->ring_size; j += 4)
|
||||
drm_printf(&p, "0x%x \t 0x%x\n", j,
|
||||
coredump->rings_dw[off + j / 4]);
|
||||
coredump->rings[i].ring_dw[j / 4]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -497,10 +502,12 @@ amdgpu_devcoredump_read(char *buffer, loff_t offset, size_t count,
|
|||
static void amdgpu_devcoredump_free(void *data)
|
||||
{
|
||||
struct amdgpu_coredump_info *coredump = data;
|
||||
u32 i;
|
||||
|
||||
kvfree(coredump->formatted);
|
||||
for (i = 0; i < coredump->num_rings; i++)
|
||||
kvfree(coredump->rings[i].ring_dw);
|
||||
kvfree(coredump->rings);
|
||||
kvfree(coredump->rings_dw);
|
||||
kvfree(data);
|
||||
}
|
||||
|
||||
|
|
@ -542,9 +549,9 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
|||
struct amdgpu_coredump_info *coredump;
|
||||
size_t size = sizeof(*coredump);
|
||||
struct drm_sched_job *s_job;
|
||||
u64 total_ring_size, ring_count;
|
||||
u64 ring_count;
|
||||
struct amdgpu_ring *ring;
|
||||
int i, off, idx;
|
||||
int i, idx;
|
||||
|
||||
/* No need to generate a new coredump if there's one in progress already. */
|
||||
if (work_busy(&adev->coredump_work))
|
||||
|
|
@ -553,7 +560,7 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
|||
if (job && job->pasid)
|
||||
size += sizeof(struct amdgpu_coredump_ib_info) * job->num_ibs;
|
||||
|
||||
coredump = kzalloc(size, GFP_NOWAIT);
|
||||
coredump = kvzalloc(size, GFP_NOWAIT);
|
||||
if (!coredump)
|
||||
return;
|
||||
|
||||
|
|
@ -584,7 +591,6 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
|||
|
||||
/* Dump ring content if memory allocation succeeds. */
|
||||
ring_count = 0;
|
||||
total_ring_size = 0;
|
||||
for (i = 0; i < adev->num_rings; i++) {
|
||||
ring = adev->rings[i];
|
||||
|
||||
|
|
@ -593,34 +599,34 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
|
|||
coredump->ring != ring)
|
||||
continue;
|
||||
|
||||
total_ring_size += ring->ring_size;
|
||||
ring_count++;
|
||||
}
|
||||
coredump->rings_dw = kzalloc(total_ring_size, GFP_NOWAIT);
|
||||
coredump->rings = kcalloc(ring_count, sizeof(struct amdgpu_coredump_ring), GFP_NOWAIT);
|
||||
if (coredump->rings && coredump->rings_dw) {
|
||||
for (i = 0, off = 0, idx = 0; i < adev->num_rings && idx < ring_count; i++) {
|
||||
if (ring_count)
|
||||
coredump->rings = kvcalloc(ring_count,
|
||||
sizeof(struct amdgpu_coredump_ring),
|
||||
GFP_NOWAIT);
|
||||
if (coredump->rings) {
|
||||
for (i = 0, idx = 0; i < adev->num_rings && idx < ring_count; i++) {
|
||||
struct amdgpu_coredump_ring *cdump_ring;
|
||||
|
||||
ring = adev->rings[i];
|
||||
|
||||
if (atomic_read(&ring->fence_drv.last_seq) == ring->fence_drv.sync_seq &&
|
||||
coredump->ring != ring)
|
||||
continue;
|
||||
|
||||
coredump->rings[idx].ring_index = ring->idx;
|
||||
coredump->rings[idx].rptr = amdgpu_ring_get_rptr(ring);
|
||||
coredump->rings[idx].wptr = amdgpu_ring_get_wptr(ring);
|
||||
coredump->rings[idx].offset = off;
|
||||
cdump_ring = &coredump->rings[idx];
|
||||
|
||||
memcpy(&coredump->rings_dw[off], ring->ring, ring->ring_size);
|
||||
off += ring->ring_size / 4;
|
||||
cdump_ring->ring_dw = kvzalloc(ring->ring_size, GFP_NOWAIT);
|
||||
if (cdump_ring->ring_dw)
|
||||
memcpy(cdump_ring->ring_dw, ring->ring, ring->ring_size);
|
||||
|
||||
cdump_ring->ring_index = ring->idx;
|
||||
cdump_ring->rptr = amdgpu_ring_get_rptr(ring);
|
||||
cdump_ring->wptr = amdgpu_ring_get_wptr(ring);
|
||||
idx++;
|
||||
}
|
||||
coredump->num_rings = idx;
|
||||
} else {
|
||||
kvfree(coredump->rings_dw);
|
||||
kvfree(coredump->rings);
|
||||
coredump->rings_dw = NULL;
|
||||
coredump->rings = NULL;
|
||||
}
|
||||
|
||||
coredump->adev = adev;
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@
|
|||
struct amdgpu_coredump_ring {
|
||||
u64 rptr;
|
||||
u64 wptr;
|
||||
u32 *ring_dw;
|
||||
u32 ring_index;
|
||||
u32 offset;
|
||||
};
|
||||
|
||||
struct amdgpu_coredump_ib_info {
|
||||
|
|
@ -53,7 +53,6 @@ struct amdgpu_coredump_info {
|
|||
struct amdgpu_ring *ring;
|
||||
|
||||
struct amdgpu_coredump_ring *rings;
|
||||
u32 *rings_dw;
|
||||
u32 num_rings;
|
||||
|
||||
/* Readable form of coredevdump, generate once to speed up
|
||||
|
|
|
|||
|
|
@ -4194,6 +4194,8 @@ static void amdgpu_device_unmap_mmio(struct amdgpu_device *adev)
|
|||
|
||||
iounmap(adev->rmmio);
|
||||
adev->rmmio = NULL;
|
||||
if (adev->mman.aper_base_kaddr)
|
||||
iounmap(adev->mman.aper_base_kaddr);
|
||||
adev->mman.aper_base_kaddr = NULL;
|
||||
|
||||
/* Memory manager related */
|
||||
|
|
|
|||
|
|
@ -135,6 +135,21 @@ int amdgpu_lockdep_init(void)
|
|||
lockdep_set_class(&locks->srbm_mutex, &amdgpu_srbm_lock_key);
|
||||
lockdep_set_class(&locks->grbm_idx_mutex, &amdgpu_grbm_lock_key);
|
||||
lockdep_set_class(&locks->mmio_idx_lock, &amdgpu_mmio_lock_key);
|
||||
|
||||
/*
|
||||
* Register fs_reclaim lock class FIRST, before taking any locks.
|
||||
*
|
||||
* This acquire/release pair does NOT create a static lockdep edge
|
||||
* (no locks are held between acquire and release). It only registers
|
||||
* the fs_reclaim lock class with lockdep.
|
||||
*
|
||||
* The actual fs_reclaim -> notifier_lock dependency is established at
|
||||
* RUNTIME when memory reclaim invokes MMU notifiers:
|
||||
* fs_reclaim (held by reclaim) -> notifier_lock (acquired in callback)
|
||||
*/
|
||||
fs_reclaim_acquire(GFP_KERNEL);
|
||||
fs_reclaim_release(GFP_KERNEL);
|
||||
|
||||
/*
|
||||
* Take locks in the correct order to train lockdep.
|
||||
* This establishes the dependency chain.
|
||||
|
|
@ -154,11 +169,6 @@ int amdgpu_lockdep_init(void)
|
|||
|
||||
/* Level 6: Reset control lock */
|
||||
mutex_lock(&locks->reset_lock);
|
||||
/*
|
||||
* Mark potential memory reclaim boundary.
|
||||
* GPU operations might trigger memory allocation/reclaim.
|
||||
*/
|
||||
fs_reclaim_acquire(GFP_KERNEL);
|
||||
|
||||
/* Level 7: SRBM register access */
|
||||
mutex_lock(&locks->srbm_mutex);
|
||||
|
|
@ -176,7 +186,6 @@ int amdgpu_lockdep_init(void)
|
|||
spin_unlock_irqrestore(&locks->mmio_idx_lock, flags);
|
||||
mutex_unlock(&locks->grbm_idx_mutex);
|
||||
mutex_unlock(&locks->srbm_mutex);
|
||||
fs_reclaim_release(GFP_KERNEL);
|
||||
|
||||
mutex_unlock(&locks->reset_lock);
|
||||
up_read(&reset_domain->sem);
|
||||
|
|
|
|||
|
|
@ -2120,23 +2120,17 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
|
|||
/* Change the size here instead of the init above so only lpfn is affected */
|
||||
amdgpu_ttm_disable_buffer_funcs(adev);
|
||||
#ifdef CONFIG_64BIT
|
||||
if (adev->gmc.xgmi.connected_to_cpu) {
|
||||
void *kaddr = devm_memremap(adev->dev, adev->gmc.aper_base,
|
||||
adev->gmc.visible_vram_size,
|
||||
MEMREMAP_WB);
|
||||
if (IS_ERR(kaddr))
|
||||
return PTR_ERR(kaddr);
|
||||
adev->mman.aper_base_kaddr = (__force void __iomem *)kaddr;
|
||||
} else if (adev->gmc.is_app_apu) {
|
||||
#ifdef CONFIG_X86
|
||||
if (adev->gmc.xgmi.connected_to_cpu)
|
||||
adev->mman.aper_base_kaddr = ioremap_cache(adev->gmc.aper_base,
|
||||
adev->gmc.visible_vram_size);
|
||||
else if (adev->gmc.is_app_apu)
|
||||
DRM_DEBUG_DRIVER(
|
||||
"No need to ioremap when real vram size is 0\n");
|
||||
} else {
|
||||
adev->mman.aper_base_kaddr = devm_ioremap_wc(adev->dev,
|
||||
adev->gmc.aper_base,
|
||||
adev->gmc.visible_vram_size);
|
||||
if (!adev->mman.aper_base_kaddr)
|
||||
return -ENOMEM;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
adev->mman.aper_base_kaddr = ioremap_wc(adev->gmc.aper_base,
|
||||
adev->gmc.visible_vram_size);
|
||||
#endif
|
||||
|
||||
amdgpu_ttm_init_vram_resv_regions(adev);
|
||||
|
|
@ -2287,7 +2281,10 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
|
|||
amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_FW_VRAM_USAGE);
|
||||
amdgpu_ttm_unmark_vram_reserved(adev, AMDGPU_RESV_DRV_VRAM_USAGE);
|
||||
|
||||
adev->mman.aper_base_kaddr = NULL;
|
||||
if (adev->mman.aper_base_kaddr) {
|
||||
iounmap(adev->mman.aper_base_kaddr);
|
||||
adev->mman.aper_base_kaddr = NULL;
|
||||
}
|
||||
|
||||
if (!adev->gmc.is_app_apu)
|
||||
amdgpu_vram_mgr_fini(adev);
|
||||
|
|
|
|||
|
|
@ -700,7 +700,12 @@ amdgpu_userq_create(struct drm_file *filp, union drm_amdgpu_userq *args)
|
|||
if (!adev->userq_halt_for_enforce_isolation ||
|
||||
((queue->queue_type != AMDGPU_HW_IP_GFX) &&
|
||||
(queue->queue_type != AMDGPU_HW_IP_COMPUTE))) {
|
||||
/* Serialize the map against an in-progress GPU reset (MES is
|
||||
* unresponsive during recovery), matching amdgpu_userq_cleanup().
|
||||
*/
|
||||
down_read(&adev->reset_domain->sem);
|
||||
r = amdgpu_userq_map_helper(queue);
|
||||
up_read(&adev->reset_domain->sem);
|
||||
if (r) {
|
||||
drm_file_err(uq_mgr->file, "Failed to map Queue\n");
|
||||
mutex_unlock(&uq_mgr->userq_mutex);
|
||||
|
|
|
|||
|
|
@ -1823,6 +1823,11 @@ static void gfx_v12_0_constants_init(struct amdgpu_device *adev)
|
|||
gfx_v12_0_get_tcc_info(adev);
|
||||
adev->gfx.config.pa_sc_tile_steering_override = 0;
|
||||
|
||||
/* Set whether texture coordinate truncation is conformant. */
|
||||
tmp = RREG32_SOC15(GC, 0, regTA_CNTL2);
|
||||
adev->gfx.config.ta_cntl2_truncate_coord_mode =
|
||||
REG_GET_FIELD(tmp, TA_CNTL2, TRUNCATE_COORD_MODE);
|
||||
|
||||
/* XXX SH_MEM regs */
|
||||
/* where to put LDS, scratch, GPUVM in FSA64 space */
|
||||
mutex_lock(&adev->srbm_mutex);
|
||||
|
|
|
|||
|
|
@ -267,9 +267,24 @@ static bool gmc_v12_1_get_vmid_pasid_mapping_info(struct amdgpu_device *adev,
|
|||
* by the amdgpu vm/hsa code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* gmc_v12_1_use_invalidate_semaphore - judge whether to use semaphore
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
* @vmhub: vmhub type
|
||||
*
|
||||
*/
|
||||
static bool gmc_v12_1_use_invalidate_semaphore(struct amdgpu_device *adev,
|
||||
uint32_t vmhub)
|
||||
{
|
||||
return ((!AMDGPU_IS_GFXHUB(vmhub)) &&
|
||||
(!amdgpu_sriov_vf(adev)));
|
||||
}
|
||||
|
||||
static void gmc_v12_1_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
|
||||
unsigned int vmhub, uint32_t flush_type)
|
||||
{
|
||||
bool use_semaphore = gmc_v12_1_use_invalidate_semaphore(adev, vmhub);
|
||||
struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
|
||||
u32 inv_req = hub->vmhub_funcs->get_invalidate_req(vmid, flush_type);
|
||||
u32 tmp;
|
||||
|
|
@ -283,6 +298,19 @@ static void gmc_v12_1_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
|
|||
|
||||
spin_lock(&adev->gmc.invalidate_lock);
|
||||
|
||||
if (use_semaphore) {
|
||||
for (i = 0; i < adev->usec_timeout; i++) {
|
||||
/* a read return value of 1 means semaphore acuqire */
|
||||
tmp = RREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem + hub->eng_distance * eng, hub_ip);
|
||||
if (tmp & 0x1)
|
||||
break;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
if (i >= adev->usec_timeout)
|
||||
DRM_ERROR("Timeout waiting for sem acquire in VM flush!\n");
|
||||
}
|
||||
|
||||
WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_req + hub->eng_distance * eng, inv_req, hub_ip);
|
||||
|
||||
/* Wait for ACK with a delay.*/
|
||||
|
|
@ -296,6 +324,9 @@ static void gmc_v12_1_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
|
|||
udelay(1);
|
||||
}
|
||||
|
||||
if (use_semaphore)
|
||||
WREG32_RLC_NO_KIQ(hub->vm_inv_eng0_sem + hub->eng_distance * eng, 0, hub_ip);
|
||||
|
||||
/* Issue additional private vm invalidation to MMHUB */
|
||||
if (!AMDGPU_IS_GFXHUB(vmhub) &&
|
||||
(hub->vm_l2_bank_select_reserved_cid2) &&
|
||||
|
|
@ -396,7 +427,7 @@ static void gmc_v12_1_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
|||
|
||||
if (all_hub) {
|
||||
/* invalidate mm_hub */
|
||||
if (test_bit(AMDGPU_MMHUB1(0), adev->vmhubs_mask)) {
|
||||
if (test_bit(AMDGPU_MMHUB0(0), adev->vmhubs_mask)) {
|
||||
input.hub_id = AMDGPU_MMHUB0(0);
|
||||
adev->mes.funcs->invalidate_tlbs_pasid(&adev->mes, &input);
|
||||
}
|
||||
|
|
@ -431,10 +462,17 @@ static void gmc_v12_1_flush_gpu_tlb_pasid(struct amdgpu_device *adev,
|
|||
static uint64_t gmc_v12_1_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
||||
unsigned vmid, uint64_t pd_addr)
|
||||
{
|
||||
bool use_semaphore = gmc_v12_1_use_invalidate_semaphore(ring->adev, ring->vm_hub);
|
||||
struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->vm_hub];
|
||||
uint32_t req = hub->vmhub_funcs->get_invalidate_req(vmid, 0);
|
||||
unsigned eng = ring->vm_inv_eng;
|
||||
|
||||
if (use_semaphore)
|
||||
/* a read return value of 1 means semaphore acuqire */
|
||||
amdgpu_ring_emit_reg_wait(ring,
|
||||
hub->vm_inv_eng0_sem +
|
||||
hub->eng_distance * eng, 0x1, 0x1);
|
||||
|
||||
amdgpu_ring_emit_wreg(ring, hub->ctx0_ptb_addr_lo32 +
|
||||
(hub->ctx_addr_distance * vmid),
|
||||
lower_32_bits(pd_addr));
|
||||
|
|
@ -449,6 +487,14 @@ static uint64_t gmc_v12_1_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
|
|||
hub->eng_distance * eng,
|
||||
req, 1 << vmid);
|
||||
|
||||
if (use_semaphore)
|
||||
/*
|
||||
* add semaphore release after invalidation,
|
||||
* write with 0 means semaphore release
|
||||
*/
|
||||
amdgpu_ring_emit_wreg(ring, hub->vm_inv_eng0_sem +
|
||||
hub->eng_distance * eng, 0);
|
||||
|
||||
return pd_addr;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -772,15 +772,28 @@ static int jpeg_v4_0_5_ring_reset(struct amdgpu_ring *ring,
|
|||
unsigned int vmid,
|
||||
struct amdgpu_fence *timedout_fence)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
u32 pg_flags = adev->pg_flags;
|
||||
int r;
|
||||
|
||||
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
|
||||
r = jpeg_v4_0_5_stop(ring->adev);
|
||||
if (r)
|
||||
return r;
|
||||
r = jpeg_v4_0_5_start(ring->adev);
|
||||
|
||||
/*
|
||||
* The DPG stop path only clears the JPEG_PG_MODE bit and never resets a
|
||||
* hung JRBC, so the post-reset ring test times out and the driver falls
|
||||
* back to a full MODE1 reset. Temporarily force the static power-gating
|
||||
* path so the stop/start sequence actually power-cycles the JPEG block
|
||||
* (JMI soft reset + static power off/on), matching the working jpeg_v4_0
|
||||
* reset.
|
||||
*/
|
||||
adev->pg_flags &= ~AMD_PG_SUPPORT_JPEG_DPG;
|
||||
r = jpeg_v4_0_5_stop(adev);
|
||||
if (!r)
|
||||
r = jpeg_v4_0_5_start(adev);
|
||||
adev->pg_flags = pg_flags;
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -648,15 +648,28 @@ static int jpeg_v5_0_0_ring_reset(struct amdgpu_ring *ring,
|
|||
unsigned int vmid,
|
||||
struct amdgpu_fence *timedout_fence)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
u32 pg_flags = adev->pg_flags;
|
||||
int r;
|
||||
|
||||
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
|
||||
r = jpeg_v5_0_0_stop(ring->adev);
|
||||
if (r)
|
||||
return r;
|
||||
r = jpeg_v5_0_0_start(ring->adev);
|
||||
|
||||
/*
|
||||
* The DPG stop path only clears the JPEG_PG_MODE bit and never resets a
|
||||
* hung JRBC, so the post-reset ring test times out and the driver falls
|
||||
* back to a full MODE1 reset. Temporarily force the static power-gating
|
||||
* path so the stop/start sequence actually power-cycles the JPEG block
|
||||
* (JMI soft reset + ONO1 power off/on), matching the working jpeg_v4_0
|
||||
* reset.
|
||||
*/
|
||||
adev->pg_flags &= ~AMD_PG_SUPPORT_JPEG_DPG;
|
||||
r = jpeg_v5_0_0_stop(adev);
|
||||
if (!r)
|
||||
r = jpeg_v5_0_0_start(adev);
|
||||
adev->pg_flags = pg_flags;
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -655,15 +655,28 @@ static int jpeg_v5_3_0_ring_reset(struct amdgpu_ring *ring,
|
|||
unsigned int vmid,
|
||||
struct amdgpu_fence *timedout_fence)
|
||||
{
|
||||
struct amdgpu_device *adev = ring->adev;
|
||||
u32 pg_flags = adev->pg_flags;
|
||||
int r;
|
||||
|
||||
amdgpu_ring_reset_helper_begin(ring, timedout_fence);
|
||||
r = jpeg_v5_3_0_stop(ring->adev);
|
||||
if (r)
|
||||
return r;
|
||||
r = jpeg_v5_3_0_start(ring->adev);
|
||||
|
||||
/*
|
||||
* The DPG stop path only clears the JPEG_PG_MODE bit and never resets a
|
||||
* hung JRBC, so the post-reset ring test times out and the driver falls
|
||||
* back to a full MODE1 reset. Temporarily force the static power-gating
|
||||
* path so the stop/start sequence actually power-cycles the JPEG block
|
||||
* (JMI soft reset + static power off/on), matching the working jpeg_v4_0
|
||||
* reset.
|
||||
*/
|
||||
adev->pg_flags &= ~AMD_PG_SUPPORT_JPEG_DPG;
|
||||
r = jpeg_v5_3_0_stop(adev);
|
||||
if (!r)
|
||||
r = jpeg_v5_3_0_start(adev);
|
||||
adev->pg_flags = pg_flags;
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return amdgpu_ring_reset_helper_end(ring, timedout_fence);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2189,6 +2189,11 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
|||
init_data.flags.unify_link_enc_assignment = true;
|
||||
init_data.flags.usb4_bw_alloc_support = true;
|
||||
}
|
||||
|
||||
/* DCN201 audio desyncs using DP SS */
|
||||
if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2)
|
||||
init_data.flags.ignore_dpref_ss = true;
|
||||
|
||||
retrieve_dmi_info(&adev->dm);
|
||||
if (adev->dm.edp0_on_dp1_quirk)
|
||||
init_data.flags.support_edp0_on_dp1 = true;
|
||||
|
|
|
|||
|
|
@ -119,7 +119,11 @@ void amdgpu_dm_crtc_set_static_screen_optimze(
|
|||
struct dc_link *link = stream->link;
|
||||
bool set_vsync_event = !sso_enable;
|
||||
|
||||
if (!allow_sr_entry)
|
||||
/*
|
||||
* allow_sr_entry gates only entry. A disable request must still set
|
||||
* the vsync events to force Replay and PSR1 out and keep them blocked.
|
||||
*/
|
||||
if (sso_enable && !allow_sr_entry)
|
||||
return;
|
||||
|
||||
amdgpu_dm_replay_set_event(dm, stream,
|
||||
|
|
|
|||
|
|
@ -1348,7 +1348,10 @@ void dce110_set_avmute(struct pipe_ctx *pipe_ctx, bool enable)
|
|||
* process the mute state, especially after link re-establishment
|
||||
* with HDMI 2.0 scrambling enabled.
|
||||
*/
|
||||
if (enable && pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg)) {
|
||||
if (enable && pipe_ctx->stream_res.tg &&
|
||||
pipe_ctx->stream_res.tg->funcs->is_tg_enabled &&
|
||||
pipe_ctx->stream_res.tg->funcs->wait_for_state &&
|
||||
pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg)) {
|
||||
int i;
|
||||
|
||||
pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
|
||||
|
|
|
|||
|
|
@ -257,8 +257,14 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
|
|||
addr_len[PAGE0_SWAUX_LENGTH - base] = (len == 0) ? SWAUX_NO_PAYLOAD :
|
||||
((len - 1) & SWAUX_LENGTH_MASK);
|
||||
|
||||
regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
|
||||
ARRAY_SIZE(addr_len));
|
||||
ret = regmap_bulk_write(map, PAGE0_SWAUX_ADDR_7_0, addr_len,
|
||||
ARRAY_SIZE(addr_len));
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev,
|
||||
"failed to write AUX address %#x, len %zu: %d\n",
|
||||
msg->address, len, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (len && (request == DP_AUX_NATIVE_WRITE ||
|
||||
request == DP_AUX_I2C_WRITE)) {
|
||||
|
|
@ -274,13 +280,22 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
|
|||
}
|
||||
}
|
||||
|
||||
regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
|
||||
ret = regmap_write(map, PAGE0_SWAUX_CTRL, SWAUX_SEND);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev, "failed to start AUX transfer: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Zero delay loop because i2c transactions are slow already */
|
||||
regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
|
||||
!(data & SWAUX_SEND), 0, 50 * 1000);
|
||||
ret = regmap_read_poll_timeout(map, PAGE0_SWAUX_CTRL, data,
|
||||
!(data & SWAUX_SEND), 0, 50 * 1000);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev, "failed to complete AUX transfer: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
regmap_read(map, PAGE0_SWAUX_STATUS, &data);
|
||||
ret = regmap_read(map, PAGE0_SWAUX_STATUS, &data);
|
||||
if (ret) {
|
||||
DRM_DEV_ERROR(dev, "failed to read PAGE0_SWAUX_STATUS: %d\n",
|
||||
ret);
|
||||
|
|
|
|||
|
|
@ -597,9 +597,13 @@ static vm_fault_t try_insert_pfn(struct vm_fault *vmf, unsigned int order,
|
|||
#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
|
||||
} else if (order == PMD_ORDER) {
|
||||
unsigned long paddr = pfn << PAGE_SHIFT;
|
||||
struct vm_area_struct *vma = vmf->vma;
|
||||
unsigned long start = ALIGN_DOWN(vmf->address, PMD_SIZE);
|
||||
unsigned long end = start + PMD_SIZE;
|
||||
bool in_range = vma->vm_start <= start && end <= vma->vm_end;
|
||||
bool aligned = (vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK);
|
||||
|
||||
if (aligned &&
|
||||
if (aligned && in_range &&
|
||||
folio_test_pmd_mappable(page_folio(pfn_to_page(pfn)))) {
|
||||
vm_fault_t ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -603,6 +603,9 @@ static int panthor_fw_load_section_entry(struct panthor_device *ptdev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!section_size)
|
||||
return 0;
|
||||
|
||||
name_len = iter->size - iter->offset;
|
||||
|
||||
section = drmm_kzalloc(&ptdev->base, sizeof(*section), GFP_KERNEL);
|
||||
|
|
|
|||
|
|
@ -802,9 +802,13 @@ static vm_fault_t insert_page(struct vm_fault *vmf, unsigned int order, struct p
|
|||
} else if (order == PMD_ORDER) {
|
||||
unsigned long pfn = page_to_pfn(page);
|
||||
unsigned long paddr = pfn << PAGE_SHIFT;
|
||||
struct vm_area_struct *vma = vmf->vma;
|
||||
unsigned long start = ALIGN_DOWN(vmf->address, PMD_SIZE);
|
||||
unsigned long end = start + PMD_SIZE;
|
||||
bool in_range = vma->vm_start <= start && end <= vma->vm_end;
|
||||
bool aligned = (vmf->address & ~PMD_MASK) == (paddr & ~PMD_MASK);
|
||||
|
||||
if (aligned &&
|
||||
if (aligned && in_range &&
|
||||
folio_test_pmd_mappable(page_folio(page))) {
|
||||
pfn &= PMD_MASK >> PAGE_SHIFT;
|
||||
return vmf_insert_pfn_pmd(vmf, pfn, vmf->flags & FAULT_FLAG_WRITE);
|
||||
|
|
|
|||
|
|
@ -360,6 +360,13 @@ static bool radeon_fence_is_signaled(struct dma_fence *f)
|
|||
if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq)
|
||||
return true;
|
||||
|
||||
if (down_read_trylock(&rdev->exclusive_lock)) {
|
||||
radeon_fence_activity(rdev, ring);
|
||||
up_read(&rdev->exclusive_lock);
|
||||
|
||||
if (atomic64_read(&rdev->fence_drv[ring].last_seq) >= seq)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -182,6 +182,12 @@ struct v3d_dev {
|
|||
*/
|
||||
struct mutex reset_lock;
|
||||
|
||||
/* Ordered workqueue shared by every queue's scheduler timeout work.
|
||||
* V3D reset is global to all queues, so the timeout handlers must not
|
||||
* run concurrently.
|
||||
*/
|
||||
struct workqueue_struct *reset_wq;
|
||||
|
||||
/* Lock taken when creating and pushing the GPU scheduler
|
||||
* jobs, to keep the sched-fence seqnos in order.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -837,6 +837,7 @@ v3d_queue_sched_init(struct v3d_dev *v3d, const struct drm_sched_backend_ops *op
|
|||
struct drm_sched_init_args args = {
|
||||
.credit_limit = 1,
|
||||
.timeout = msecs_to_jiffies(500),
|
||||
.timeout_wq = v3d->reset_wq,
|
||||
.dev = v3d->drm.dev,
|
||||
};
|
||||
|
||||
|
|
@ -851,9 +852,13 @@ v3d_sched_init(struct v3d_dev *v3d)
|
|||
{
|
||||
int ret;
|
||||
|
||||
v3d->reset_wq = alloc_ordered_workqueue("v3d_reset", 0);
|
||||
if (!v3d->reset_wq)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = v3d_queue_sched_init(v3d, &v3d_bin_sched_ops, V3D_BIN, "v3d_bin");
|
||||
if (ret)
|
||||
return ret;
|
||||
goto fail;
|
||||
|
||||
ret = v3d_queue_sched_init(v3d, &v3d_render_sched_ops, V3D_RENDER,
|
||||
"v3d_render");
|
||||
|
|
@ -896,4 +901,6 @@ v3d_sched_fini(struct v3d_dev *v3d)
|
|||
if (v3d->queue[q].sched.ready)
|
||||
drm_sched_fini(&v3d->queue[q].sched);
|
||||
}
|
||||
|
||||
destroy_workqueue(v3d->reset_wq);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -805,6 +805,9 @@ static int exec_queue_set_hang_replay_state(struct xe_device *xe,
|
|||
u64 __user *address = u64_to_user_ptr(value);
|
||||
void *ptr;
|
||||
|
||||
if (q->replay_state)
|
||||
return -EINVAL;
|
||||
|
||||
ptr = vmemdup_user(address, size);
|
||||
if (XE_IOCTL_DBG(xe, IS_ERR(ptr)))
|
||||
return PTR_ERR(ptr);
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include "xe_guc_pc.h"
|
||||
#include "xe_guc_rc.h"
|
||||
#include "xe_guc_engine_activity.h"
|
||||
#include "xe_guc_submit.h"
|
||||
#include "xe_huc.h"
|
||||
#include "xe_sriov.h"
|
||||
#include "xe_wopcm.h"
|
||||
|
|
@ -159,12 +160,14 @@ static int vf_uc_load_hw(struct xe_uc *uc)
|
|||
if (err)
|
||||
return err;
|
||||
|
||||
uc->guc.submission_state.enabled = true;
|
||||
|
||||
err = xe_guc_opt_in_features_enable(&uc->guc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = xe_guc_submit_enable(&uc->guc);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = xe_gt_record_default_lrcs(uc_to_gt(uc));
|
||||
if (err)
|
||||
return err;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user