mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
Revert "drm/shmem-helper: Switch to reservation lock"
This reverts commit 67b7836d44
.
The locking appears incomplete. A caller of SHMEM helper's pin
function never acquires the dma-buf reservation lock. So we get
WARNING: CPU: 3 PID: 967 at drivers/gpu/drm/drm_gem_shmem_helper.c:243 drm_gem_shmem_pin+0x42/0x90 [drm_shmem_helper]
Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Acked-by: Dmitry Osipenko <dmitry.osipenko@collabora.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230228152612.19971-1-tzimmermann@suse.de
This commit is contained in:
parent
f9b9297b1f
commit
e0106ac978
@ -88,6 +88,8 @@ __drm_gem_shmem_create(struct drm_device *dev, size_t size, bool private)
|
||||
if (ret)
|
||||
goto err_release;
|
||||
|
||||
mutex_init(&shmem->pages_lock);
|
||||
mutex_init(&shmem->vmap_lock);
|
||||
INIT_LIST_HEAD(&shmem->madv_list);
|
||||
|
||||
if (!private) {
|
||||
@ -139,13 +141,11 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem)
|
||||
{
|
||||
struct drm_gem_object *obj = &shmem->base;
|
||||
|
||||
drm_WARN_ON(obj->dev, shmem->vmap_use_count);
|
||||
|
||||
if (obj->import_attach) {
|
||||
drm_prime_gem_destroy(obj, shmem->sgt);
|
||||
} else {
|
||||
dma_resv_lock(shmem->base.resv, NULL);
|
||||
|
||||
drm_WARN_ON(obj->dev, shmem->vmap_use_count);
|
||||
|
||||
if (shmem->sgt) {
|
||||
dma_unmap_sgtable(obj->dev->dev, shmem->sgt,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
@ -154,18 +154,18 @@ void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem)
|
||||
}
|
||||
if (shmem->pages)
|
||||
drm_gem_shmem_put_pages(shmem);
|
||||
|
||||
drm_WARN_ON(obj->dev, shmem->pages_use_count);
|
||||
|
||||
dma_resv_unlock(shmem->base.resv);
|
||||
}
|
||||
|
||||
drm_WARN_ON(obj->dev, shmem->pages_use_count);
|
||||
|
||||
drm_gem_object_release(obj);
|
||||
mutex_destroy(&shmem->pages_lock);
|
||||
mutex_destroy(&shmem->vmap_lock);
|
||||
kfree(shmem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_shmem_free);
|
||||
|
||||
static int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem)
|
||||
static int drm_gem_shmem_get_pages_locked(struct drm_gem_shmem_object *shmem)
|
||||
{
|
||||
struct drm_gem_object *obj = &shmem->base;
|
||||
struct page **pages;
|
||||
@ -197,16 +197,35 @@ static int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem)
|
||||
}
|
||||
|
||||
/*
|
||||
* drm_gem_shmem_put_pages - Decrease use count on the backing pages for a shmem GEM object
|
||||
* drm_gem_shmem_get_pages - Allocate backing pages for a shmem GEM object
|
||||
* @shmem: shmem GEM object
|
||||
*
|
||||
* This function decreases the use count and puts the backing pages when use drops to zero.
|
||||
* This function makes sure that backing pages exists for the shmem GEM object
|
||||
* and increases the use count.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
void drm_gem_shmem_put_pages(struct drm_gem_shmem_object *shmem)
|
||||
int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem)
|
||||
{
|
||||
struct drm_gem_object *obj = &shmem->base;
|
||||
int ret;
|
||||
|
||||
dma_resv_assert_held(shmem->base.resv);
|
||||
drm_WARN_ON(obj->dev, obj->import_attach);
|
||||
|
||||
ret = mutex_lock_interruptible(&shmem->pages_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = drm_gem_shmem_get_pages_locked(shmem);
|
||||
mutex_unlock(&shmem->pages_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_get_pages);
|
||||
|
||||
static void drm_gem_shmem_put_pages_locked(struct drm_gem_shmem_object *shmem)
|
||||
{
|
||||
struct drm_gem_object *obj = &shmem->base;
|
||||
|
||||
if (drm_WARN_ON_ONCE(obj->dev, !shmem->pages_use_count))
|
||||
return;
|
||||
@ -224,6 +243,19 @@ void drm_gem_shmem_put_pages(struct drm_gem_shmem_object *shmem)
|
||||
shmem->pages_mark_accessed_on_put);
|
||||
shmem->pages = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* drm_gem_shmem_put_pages - Decrease use count on the backing pages for a shmem GEM object
|
||||
* @shmem: shmem GEM object
|
||||
*
|
||||
* This function decreases the use count and puts the backing pages when use drops to zero.
|
||||
*/
|
||||
void drm_gem_shmem_put_pages(struct drm_gem_shmem_object *shmem)
|
||||
{
|
||||
mutex_lock(&shmem->pages_lock);
|
||||
drm_gem_shmem_put_pages_locked(shmem);
|
||||
mutex_unlock(&shmem->pages_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_put_pages);
|
||||
|
||||
/**
|
||||
@ -240,8 +272,6 @@ int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem)
|
||||
{
|
||||
struct drm_gem_object *obj = &shmem->base;
|
||||
|
||||
dma_resv_assert_held(shmem->base.resv);
|
||||
|
||||
drm_WARN_ON(obj->dev, obj->import_attach);
|
||||
|
||||
return drm_gem_shmem_get_pages(shmem);
|
||||
@ -259,31 +289,14 @@ void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem)
|
||||
{
|
||||
struct drm_gem_object *obj = &shmem->base;
|
||||
|
||||
dma_resv_assert_held(shmem->base.resv);
|
||||
|
||||
drm_WARN_ON(obj->dev, obj->import_attach);
|
||||
|
||||
drm_gem_shmem_put_pages(shmem);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_unpin);
|
||||
|
||||
/*
|
||||
* drm_gem_shmem_vmap - Create a virtual mapping for a shmem GEM object
|
||||
* @shmem: shmem GEM object
|
||||
* @map: Returns the kernel virtual address of the SHMEM GEM object's backing
|
||||
* store.
|
||||
*
|
||||
* This function makes sure that a contiguous kernel virtual address mapping
|
||||
* exists for the buffer backing the shmem GEM object. It hides the differences
|
||||
* between dma-buf imported and natively allocated objects.
|
||||
*
|
||||
* Acquired mappings should be cleaned up by calling drm_gem_shmem_vunmap().
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_gem_shmem_vmap(struct drm_gem_shmem_object *shmem,
|
||||
struct iosys_map *map)
|
||||
static int drm_gem_shmem_vmap_locked(struct drm_gem_shmem_object *shmem,
|
||||
struct iosys_map *map)
|
||||
{
|
||||
struct drm_gem_object *obj = &shmem->base;
|
||||
int ret = 0;
|
||||
@ -299,8 +312,6 @@ int drm_gem_shmem_vmap(struct drm_gem_shmem_object *shmem,
|
||||
} else {
|
||||
pgprot_t prot = PAGE_KERNEL;
|
||||
|
||||
dma_resv_assert_held(shmem->base.resv);
|
||||
|
||||
if (shmem->vmap_use_count++ > 0) {
|
||||
iosys_map_set_vaddr(map, shmem->vaddr);
|
||||
return 0;
|
||||
@ -335,8 +346,58 @@ err_zero_use:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* drm_gem_shmem_vmap - Create a virtual mapping for a shmem GEM object
|
||||
* @shmem: shmem GEM object
|
||||
* @map: Returns the kernel virtual address of the SHMEM GEM object's backing
|
||||
* store.
|
||||
*
|
||||
* This function makes sure that a contiguous kernel virtual address mapping
|
||||
* exists for the buffer backing the shmem GEM object. It hides the differences
|
||||
* between dma-buf imported and natively allocated objects.
|
||||
*
|
||||
* Acquired mappings should be cleaned up by calling drm_gem_shmem_vunmap().
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_gem_shmem_vmap(struct drm_gem_shmem_object *shmem,
|
||||
struct iosys_map *map)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = mutex_lock_interruptible(&shmem->vmap_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = drm_gem_shmem_vmap_locked(shmem, map);
|
||||
mutex_unlock(&shmem->vmap_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_vmap);
|
||||
|
||||
static void drm_gem_shmem_vunmap_locked(struct drm_gem_shmem_object *shmem,
|
||||
struct iosys_map *map)
|
||||
{
|
||||
struct drm_gem_object *obj = &shmem->base;
|
||||
|
||||
if (obj->import_attach) {
|
||||
dma_buf_vunmap(obj->import_attach->dmabuf, map);
|
||||
} else {
|
||||
if (drm_WARN_ON_ONCE(obj->dev, !shmem->vmap_use_count))
|
||||
return;
|
||||
|
||||
if (--shmem->vmap_use_count > 0)
|
||||
return;
|
||||
|
||||
vunmap(shmem->vaddr);
|
||||
drm_gem_shmem_put_pages(shmem);
|
||||
}
|
||||
|
||||
shmem->vaddr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* drm_gem_shmem_vunmap - Unmap a virtual mapping for a shmem GEM object
|
||||
* @shmem: shmem GEM object
|
||||
@ -352,24 +413,9 @@ EXPORT_SYMBOL(drm_gem_shmem_vmap);
|
||||
void drm_gem_shmem_vunmap(struct drm_gem_shmem_object *shmem,
|
||||
struct iosys_map *map)
|
||||
{
|
||||
struct drm_gem_object *obj = &shmem->base;
|
||||
|
||||
if (obj->import_attach) {
|
||||
dma_buf_vunmap(obj->import_attach->dmabuf, map);
|
||||
} else {
|
||||
dma_resv_assert_held(shmem->base.resv);
|
||||
|
||||
if (drm_WARN_ON_ONCE(obj->dev, !shmem->vmap_use_count))
|
||||
return;
|
||||
|
||||
if (--shmem->vmap_use_count > 0)
|
||||
return;
|
||||
|
||||
vunmap(shmem->vaddr);
|
||||
drm_gem_shmem_put_pages(shmem);
|
||||
}
|
||||
|
||||
shmem->vaddr = NULL;
|
||||
mutex_lock(&shmem->vmap_lock);
|
||||
drm_gem_shmem_vunmap_locked(shmem, map);
|
||||
mutex_unlock(&shmem->vmap_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_vunmap);
|
||||
|
||||
@ -401,24 +447,24 @@ drm_gem_shmem_create_with_handle(struct drm_file *file_priv,
|
||||
*/
|
||||
int drm_gem_shmem_madvise(struct drm_gem_shmem_object *shmem, int madv)
|
||||
{
|
||||
dma_resv_assert_held(shmem->base.resv);
|
||||
mutex_lock(&shmem->pages_lock);
|
||||
|
||||
if (shmem->madv >= 0)
|
||||
shmem->madv = madv;
|
||||
|
||||
madv = shmem->madv;
|
||||
|
||||
mutex_unlock(&shmem->pages_lock);
|
||||
|
||||
return (madv >= 0);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_madvise);
|
||||
|
||||
void drm_gem_shmem_purge(struct drm_gem_shmem_object *shmem)
|
||||
void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem)
|
||||
{
|
||||
struct drm_gem_object *obj = &shmem->base;
|
||||
struct drm_device *dev = obj->dev;
|
||||
|
||||
dma_resv_assert_held(shmem->base.resv);
|
||||
|
||||
drm_WARN_ON(obj->dev, !drm_gem_shmem_is_purgeable(shmem));
|
||||
|
||||
dma_unmap_sgtable(dev->dev, shmem->sgt, DMA_BIDIRECTIONAL, 0);
|
||||
@ -426,7 +472,7 @@ void drm_gem_shmem_purge(struct drm_gem_shmem_object *shmem)
|
||||
kfree(shmem->sgt);
|
||||
shmem->sgt = NULL;
|
||||
|
||||
drm_gem_shmem_put_pages(shmem);
|
||||
drm_gem_shmem_put_pages_locked(shmem);
|
||||
|
||||
shmem->madv = -1;
|
||||
|
||||
@ -442,6 +488,17 @@ void drm_gem_shmem_purge(struct drm_gem_shmem_object *shmem)
|
||||
|
||||
invalidate_mapping_pages(file_inode(obj->filp)->i_mapping, 0, (loff_t)-1);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_purge_locked);
|
||||
|
||||
bool drm_gem_shmem_purge(struct drm_gem_shmem_object *shmem)
|
||||
{
|
||||
if (!mutex_trylock(&shmem->pages_lock))
|
||||
return false;
|
||||
drm_gem_shmem_purge_locked(shmem);
|
||||
mutex_unlock(&shmem->pages_lock);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_shmem_purge);
|
||||
|
||||
/**
|
||||
@ -494,7 +551,7 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
|
||||
/* We don't use vmf->pgoff since that has the fake offset */
|
||||
page_offset = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
|
||||
|
||||
dma_resv_lock(shmem->base.resv, NULL);
|
||||
mutex_lock(&shmem->pages_lock);
|
||||
|
||||
if (page_offset >= num_pages ||
|
||||
drm_WARN_ON_ONCE(obj->dev, !shmem->pages) ||
|
||||
@ -506,7 +563,7 @@ static vm_fault_t drm_gem_shmem_fault(struct vm_fault *vmf)
|
||||
ret = vmf_insert_pfn(vma, vmf->address, page_to_pfn(page));
|
||||
}
|
||||
|
||||
dma_resv_unlock(shmem->base.resv);
|
||||
mutex_unlock(&shmem->pages_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -518,7 +575,7 @@ static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
|
||||
|
||||
drm_WARN_ON(obj->dev, obj->import_attach);
|
||||
|
||||
dma_resv_lock(shmem->base.resv, NULL);
|
||||
mutex_lock(&shmem->pages_lock);
|
||||
|
||||
/*
|
||||
* We should have already pinned the pages when the buffer was first
|
||||
@ -528,7 +585,7 @@ static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
|
||||
if (!drm_WARN_ON_ONCE(obj->dev, !shmem->pages_use_count))
|
||||
shmem->pages_use_count++;
|
||||
|
||||
dma_resv_unlock(shmem->base.resv);
|
||||
mutex_unlock(&shmem->pages_lock);
|
||||
|
||||
drm_gem_vm_open(vma);
|
||||
}
|
||||
@ -538,10 +595,7 @@ static void drm_gem_shmem_vm_close(struct vm_area_struct *vma)
|
||||
struct drm_gem_object *obj = vma->vm_private_data;
|
||||
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
|
||||
|
||||
dma_resv_lock(shmem->base.resv, NULL);
|
||||
drm_gem_shmem_put_pages(shmem);
|
||||
dma_resv_unlock(shmem->base.resv);
|
||||
|
||||
drm_gem_vm_close(vma);
|
||||
}
|
||||
|
||||
@ -576,10 +630,7 @@ int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct
|
||||
return dma_buf_mmap(obj->dma_buf, vma, 0);
|
||||
}
|
||||
|
||||
dma_resv_lock(shmem->base.resv, NULL);
|
||||
ret = drm_gem_shmem_get_pages(shmem);
|
||||
dma_resv_unlock(shmem->base.resv);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -645,7 +696,7 @@ static struct sg_table *drm_gem_shmem_get_pages_sgt_locked(struct drm_gem_shmem_
|
||||
|
||||
drm_WARN_ON(obj->dev, obj->import_attach);
|
||||
|
||||
ret = drm_gem_shmem_get_pages(shmem);
|
||||
ret = drm_gem_shmem_get_pages_locked(shmem);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
@ -667,7 +718,7 @@ err_free_sgt:
|
||||
sg_free_table(sgt);
|
||||
kfree(sgt);
|
||||
err_put_pages:
|
||||
drm_gem_shmem_put_pages(shmem);
|
||||
drm_gem_shmem_put_pages_locked(shmem);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
@ -692,11 +743,11 @@ struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem)
|
||||
int ret;
|
||||
struct sg_table *sgt;
|
||||
|
||||
ret = dma_resv_lock_interruptible(shmem->base.resv, NULL);
|
||||
ret = mutex_lock_interruptible(&shmem->pages_lock);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
sgt = drm_gem_shmem_get_pages_sgt_locked(shmem);
|
||||
dma_resv_unlock(shmem->base.resv);
|
||||
mutex_unlock(&shmem->pages_lock);
|
||||
|
||||
return sgt;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm)
|
||||
|
||||
new_size = min(new_size, bo->base.base.size);
|
||||
|
||||
dma_resv_lock(bo->base.base.resv, NULL);
|
||||
mutex_lock(&bo->base.pages_lock);
|
||||
|
||||
if (bo->base.pages) {
|
||||
pages = bo->base.pages;
|
||||
@ -42,7 +42,7 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm)
|
||||
pages = kvmalloc_array(bo->base.base.size >> PAGE_SHIFT,
|
||||
sizeof(*pages), GFP_KERNEL | __GFP_ZERO);
|
||||
if (!pages) {
|
||||
dma_resv_unlock(bo->base.base.resv);
|
||||
mutex_unlock(&bo->base.pages_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
@ -56,13 +56,13 @@ int lima_heap_alloc(struct lima_bo *bo, struct lima_vm *vm)
|
||||
struct page *page = shmem_read_mapping_page(mapping, i);
|
||||
|
||||
if (IS_ERR(page)) {
|
||||
dma_resv_unlock(bo->base.base.resv);
|
||||
mutex_unlock(&bo->base.pages_lock);
|
||||
return PTR_ERR(page);
|
||||
}
|
||||
pages[i] = page;
|
||||
}
|
||||
|
||||
dma_resv_unlock(bo->base.base.resv);
|
||||
mutex_unlock(&bo->base.pages_lock);
|
||||
|
||||
ret = sg_alloc_table_from_pages(&sgt, pages, i, 0,
|
||||
new_size, GFP_KERNEL);
|
||||
|
@ -407,10 +407,6 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data,
|
||||
|
||||
bo = to_panfrost_bo(gem_obj);
|
||||
|
||||
ret = dma_resv_lock_interruptible(bo->base.base.resv, NULL);
|
||||
if (ret)
|
||||
goto out_put_object;
|
||||
|
||||
mutex_lock(&pfdev->shrinker_lock);
|
||||
mutex_lock(&bo->mappings.lock);
|
||||
if (args->madv == PANFROST_MADV_DONTNEED) {
|
||||
@ -448,8 +444,7 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data,
|
||||
out_unlock_mappings:
|
||||
mutex_unlock(&bo->mappings.lock);
|
||||
mutex_unlock(&pfdev->shrinker_lock);
|
||||
dma_resv_unlock(bo->base.base.resv);
|
||||
out_put_object:
|
||||
|
||||
drm_gem_object_put(gem_obj);
|
||||
return ret;
|
||||
}
|
||||
|
@ -48,14 +48,14 @@ static bool panfrost_gem_purge(struct drm_gem_object *obj)
|
||||
if (!mutex_trylock(&bo->mappings.lock))
|
||||
return false;
|
||||
|
||||
if (!dma_resv_trylock(shmem->base.resv))
|
||||
if (!mutex_trylock(&shmem->pages_lock))
|
||||
goto unlock_mappings;
|
||||
|
||||
panfrost_gem_teardown_mappings_locked(bo);
|
||||
drm_gem_shmem_purge(&bo->base);
|
||||
drm_gem_shmem_purge_locked(&bo->base);
|
||||
ret = true;
|
||||
|
||||
dma_resv_unlock(shmem->base.resv);
|
||||
mutex_unlock(&shmem->pages_lock);
|
||||
|
||||
unlock_mappings:
|
||||
mutex_unlock(&bo->mappings.lock);
|
||||
|
@ -443,7 +443,6 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
|
||||
struct panfrost_gem_mapping *bomapping;
|
||||
struct panfrost_gem_object *bo;
|
||||
struct address_space *mapping;
|
||||
struct drm_gem_object *obj;
|
||||
pgoff_t page_offset;
|
||||
struct sg_table *sgt;
|
||||
struct page **pages;
|
||||
@ -466,16 +465,15 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
|
||||
page_offset = addr >> PAGE_SHIFT;
|
||||
page_offset -= bomapping->mmnode.start;
|
||||
|
||||
obj = &bo->base.base;
|
||||
|
||||
dma_resv_lock(obj->resv, NULL);
|
||||
mutex_lock(&bo->base.pages_lock);
|
||||
|
||||
if (!bo->base.pages) {
|
||||
bo->sgts = kvmalloc_array(bo->base.base.size / SZ_2M,
|
||||
sizeof(struct sg_table), GFP_KERNEL | __GFP_ZERO);
|
||||
if (!bo->sgts) {
|
||||
mutex_unlock(&bo->base.pages_lock);
|
||||
ret = -ENOMEM;
|
||||
goto err_unlock;
|
||||
goto err_bo;
|
||||
}
|
||||
|
||||
pages = kvmalloc_array(bo->base.base.size >> PAGE_SHIFT,
|
||||
@ -483,8 +481,9 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
|
||||
if (!pages) {
|
||||
kvfree(bo->sgts);
|
||||
bo->sgts = NULL;
|
||||
mutex_unlock(&bo->base.pages_lock);
|
||||
ret = -ENOMEM;
|
||||
goto err_unlock;
|
||||
goto err_bo;
|
||||
}
|
||||
bo->base.pages = pages;
|
||||
bo->base.pages_use_count = 1;
|
||||
@ -492,6 +491,7 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
|
||||
pages = bo->base.pages;
|
||||
if (pages[page_offset]) {
|
||||
/* Pages are already mapped, bail out. */
|
||||
mutex_unlock(&bo->base.pages_lock);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -502,11 +502,14 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
|
||||
for (i = page_offset; i < page_offset + NUM_FAULT_PAGES; i++) {
|
||||
pages[i] = shmem_read_mapping_page(mapping, i);
|
||||
if (IS_ERR(pages[i])) {
|
||||
mutex_unlock(&bo->base.pages_lock);
|
||||
ret = PTR_ERR(pages[i]);
|
||||
goto err_pages;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&bo->base.pages_lock);
|
||||
|
||||
sgt = &bo->sgts[page_offset / (SZ_2M / PAGE_SIZE)];
|
||||
ret = sg_alloc_table_from_pages(sgt, pages + page_offset,
|
||||
NUM_FAULT_PAGES, 0, SZ_2M, GFP_KERNEL);
|
||||
@ -525,8 +528,6 @@ static int panfrost_mmu_map_fault_addr(struct panfrost_device *pfdev, int as,
|
||||
dev_dbg(pfdev->dev, "mapped page fault @ AS%d %llx", as, addr);
|
||||
|
||||
out:
|
||||
dma_resv_unlock(obj->resv);
|
||||
|
||||
panfrost_gem_mapping_put(bomapping);
|
||||
|
||||
return 0;
|
||||
@ -535,8 +536,6 @@ err_map:
|
||||
sg_free_table(sgt);
|
||||
err_pages:
|
||||
drm_gem_shmem_put_pages(&bo->base);
|
||||
err_unlock:
|
||||
dma_resv_unlock(obj->resv);
|
||||
err_bo:
|
||||
panfrost_gem_mapping_put(bomapping);
|
||||
return ret;
|
||||
|
@ -26,6 +26,11 @@ struct drm_gem_shmem_object {
|
||||
*/
|
||||
struct drm_gem_object base;
|
||||
|
||||
/**
|
||||
* @pages_lock: Protects the page table and use count
|
||||
*/
|
||||
struct mutex pages_lock;
|
||||
|
||||
/**
|
||||
* @pages: Page table
|
||||
*/
|
||||
@ -60,6 +65,11 @@ struct drm_gem_shmem_object {
|
||||
*/
|
||||
struct sg_table *sgt;
|
||||
|
||||
/**
|
||||
* @vmap_lock: Protects the vmap address and use count
|
||||
*/
|
||||
struct mutex vmap_lock;
|
||||
|
||||
/**
|
||||
* @vaddr: Kernel virtual address of the backing memory
|
||||
*/
|
||||
@ -99,6 +109,7 @@ struct drm_gem_shmem_object {
|
||||
struct drm_gem_shmem_object *drm_gem_shmem_create(struct drm_device *dev, size_t size);
|
||||
void drm_gem_shmem_free(struct drm_gem_shmem_object *shmem);
|
||||
|
||||
int drm_gem_shmem_get_pages(struct drm_gem_shmem_object *shmem);
|
||||
void drm_gem_shmem_put_pages(struct drm_gem_shmem_object *shmem);
|
||||
int drm_gem_shmem_pin(struct drm_gem_shmem_object *shmem);
|
||||
void drm_gem_shmem_unpin(struct drm_gem_shmem_object *shmem);
|
||||
@ -117,7 +128,8 @@ static inline bool drm_gem_shmem_is_purgeable(struct drm_gem_shmem_object *shmem
|
||||
!shmem->base.dma_buf && !shmem->base.import_attach;
|
||||
}
|
||||
|
||||
void drm_gem_shmem_purge(struct drm_gem_shmem_object *shmem);
|
||||
void drm_gem_shmem_purge_locked(struct drm_gem_shmem_object *shmem);
|
||||
bool drm_gem_shmem_purge(struct drm_gem_shmem_object *shmem);
|
||||
|
||||
struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem);
|
||||
struct sg_table *drm_gem_shmem_get_pages_sgt(struct drm_gem_shmem_object *shmem);
|
||||
|
Loading…
Reference in New Issue
Block a user