diff --git a/drivers/accel/amdxdna/amdxdna_gem.c b/drivers/accel/amdxdna/amdxdna_gem.c index 4628a2787265..1c63eff0a4a8 100644 --- a/drivers/accel/amdxdna/amdxdna_gem.c +++ b/drivers/accel/amdxdna/amdxdna_gem.c @@ -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; } diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index b93514023baa..39ab94a73c88 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -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); diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index c989459eb215..00807039f8d7 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -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; diff --git a/drivers/gpu/drm/panthor/panthor_fw.c b/drivers/gpu/drm/panthor/panthor_fw.c index e45933e333b5..fa88b2f9da76 100644 --- a/drivers/gpu/drm/panthor/panthor_fw.c +++ b/drivers/gpu/drm/panthor/panthor_fw.c @@ -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); diff --git a/drivers/gpu/drm/panthor/panthor_gem.c b/drivers/gpu/drm/panthor/panthor_gem.c index a1e2eb1ca7bb..54535bae2b0c 100644 --- a/drivers/gpu/drm/panthor/panthor_gem.c +++ b/drivers/gpu/drm/panthor/panthor_gem.c @@ -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); diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index 423bcfe331a0..8779a42c6508 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -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. */ diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index c35f9f70cf8d..63dd95b828c8 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -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); }