diff options
Diffstat (limited to 'drivers/staging/media/tegra-vde/dmabuf-cache.c')
-rw-r--r-- | drivers/staging/media/tegra-vde/dmabuf-cache.c | 229 |
1 files changed, 0 insertions, 229 deletions
diff --git a/drivers/staging/media/tegra-vde/dmabuf-cache.c b/drivers/staging/media/tegra-vde/dmabuf-cache.c deleted file mode 100644 index a98d03419b8f..000000000000 --- a/drivers/staging/media/tegra-vde/dmabuf-cache.c +++ /dev/null @@ -1,229 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * NVIDIA Tegra Video decoder driver - * - * Copyright (C) 2016-2019 GRATE-DRIVER project - */ - -#include <linux/dma-buf.h> -#include <linux/iova.h> -#include <linux/kernel.h> -#include <linux/list.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/workqueue.h> -#include <linux/module.h> - -#include "vde.h" - -MODULE_IMPORT_NS(DMA_BUF); - -struct tegra_vde_cache_entry { - enum dma_data_direction dma_dir; - struct dma_buf_attachment *a; - struct delayed_work dwork; - struct tegra_vde *vde; - struct list_head list; - struct sg_table *sgt; - struct iova *iova; - unsigned int refcnt; -}; - -static void tegra_vde_release_entry(struct tegra_vde_cache_entry *entry) -{ - struct dma_buf *dmabuf = entry->a->dmabuf; - - WARN_ON_ONCE(entry->refcnt); - - if (entry->vde->domain) - tegra_vde_iommu_unmap(entry->vde, entry->iova); - - dma_buf_unmap_attachment(entry->a, entry->sgt, entry->dma_dir); - dma_buf_detach(dmabuf, entry->a); - dma_buf_put(dmabuf); - - list_del(&entry->list); - kfree(entry); -} - -static void tegra_vde_delayed_unmap(struct work_struct *work) -{ - struct tegra_vde_cache_entry *entry; - struct tegra_vde *vde; - - entry = container_of(work, struct tegra_vde_cache_entry, - dwork.work); - vde = entry->vde; - - mutex_lock(&vde->map_lock); - tegra_vde_release_entry(entry); - mutex_unlock(&vde->map_lock); -} - -int tegra_vde_dmabuf_cache_map(struct tegra_vde *vde, - struct dma_buf *dmabuf, - enum dma_data_direction dma_dir, - struct dma_buf_attachment **ap, - dma_addr_t *addrp) -{ - struct device *dev = vde->miscdev.parent; - struct dma_buf_attachment *attachment; - struct tegra_vde_cache_entry *entry; - struct sg_table *sgt; - struct iova *iova; - int err; - - mutex_lock(&vde->map_lock); - - list_for_each_entry(entry, &vde->map_list, list) { - if (entry->a->dmabuf != dmabuf) - continue; - - if (!cancel_delayed_work(&entry->dwork)) - continue; - - if (entry->dma_dir != dma_dir) - entry->dma_dir = DMA_BIDIRECTIONAL; - - dma_buf_put(dmabuf); - - if (vde->domain) - *addrp = iova_dma_addr(&vde->iova, entry->iova); - else - *addrp = sg_dma_address(entry->sgt->sgl); - - goto ref; - } - - attachment = dma_buf_attach(dmabuf, dev); - if (IS_ERR(attachment)) { - dev_err(dev, "Failed to attach dmabuf\n"); - err = PTR_ERR(attachment); - goto err_unlock; - } - - sgt = dma_buf_map_attachment(attachment, dma_dir); - if (IS_ERR(sgt)) { - dev_err(dev, "Failed to get dmabufs sg_table\n"); - err = PTR_ERR(sgt); - goto err_detach; - } - - if (!vde->domain && sgt->nents > 1) { - dev_err(dev, "Sparse DMA region is unsupported, please enable IOMMU\n"); - err = -EINVAL; - goto err_unmap; - } - - entry = kzalloc(sizeof(*entry), GFP_KERNEL); - if (!entry) { - err = -ENOMEM; - goto err_unmap; - } - - if (vde->domain) { - err = tegra_vde_iommu_map(vde, sgt, &iova, dmabuf->size); - if (err) - goto err_free; - - *addrp = iova_dma_addr(&vde->iova, iova); - } else { - *addrp = sg_dma_address(sgt->sgl); - iova = NULL; - } - - INIT_DELAYED_WORK(&entry->dwork, tegra_vde_delayed_unmap); - list_add(&entry->list, &vde->map_list); - - entry->dma_dir = dma_dir; - entry->iova = iova; - entry->vde = vde; - entry->sgt = sgt; - entry->a = attachment; -ref: - entry->refcnt++; - - *ap = entry->a; - - mutex_unlock(&vde->map_lock); - - return 0; - -err_free: - kfree(entry); -err_unmap: - dma_buf_unmap_attachment(attachment, sgt, dma_dir); -err_detach: - dma_buf_detach(dmabuf, attachment); -err_unlock: - mutex_unlock(&vde->map_lock); - - return err; -} - -void tegra_vde_dmabuf_cache_unmap(struct tegra_vde *vde, - struct dma_buf_attachment *a, - bool release) -{ - struct tegra_vde_cache_entry *entry; - - mutex_lock(&vde->map_lock); - - list_for_each_entry(entry, &vde->map_list, list) { - if (entry->a != a) - continue; - - WARN_ON_ONCE(!entry->refcnt); - - if (--entry->refcnt == 0) { - if (release) - tegra_vde_release_entry(entry); - else - schedule_delayed_work(&entry->dwork, 5 * HZ); - } - break; - } - - mutex_unlock(&vde->map_lock); -} - -void tegra_vde_dmabuf_cache_unmap_sync(struct tegra_vde *vde) -{ - struct tegra_vde_cache_entry *entry, *tmp; - - mutex_lock(&vde->map_lock); - - list_for_each_entry_safe(entry, tmp, &vde->map_list, list) { - if (entry->refcnt) - continue; - - if (!cancel_delayed_work(&entry->dwork)) - continue; - - tegra_vde_release_entry(entry); - } - - mutex_unlock(&vde->map_lock); -} - -void tegra_vde_dmabuf_cache_unmap_all(struct tegra_vde *vde) -{ - struct tegra_vde_cache_entry *entry, *tmp; - - mutex_lock(&vde->map_lock); - - while (!list_empty(&vde->map_list)) { - list_for_each_entry_safe(entry, tmp, &vde->map_list, list) { - if (!cancel_delayed_work(&entry->dwork)) - continue; - - tegra_vde_release_entry(entry); - } - - mutex_unlock(&vde->map_lock); - schedule(); - mutex_lock(&vde->map_lock); - } - - mutex_unlock(&vde->map_lock); -} |