mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-23 09:42:19 +03:00
drm/tegra: Implement correct DMA-BUF semantics
DMA-BUF requires that each device that accesses a DMA-BUF attaches to it separately. To do so the host1x_bo_pin() and host1x_bo_unpin() functions need to be reimplemented so that they can return a mapping, which either represents an attachment or a map of the driver's own GEM object. Bug 200768479 Signed-off-by: Thierry Reding <treding@nvidia.com> Change-Id: Ia380b7dcc371ce47f5f35d44a60fbd6b4ab9d636 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2596398 (cherry picked from commit 28960586000fca025689edfd45645ab28e497bca) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2620137 Tested-by: Jonathan Hunter <jonathanh@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: Jonathan Hunter <jonathanh@nvidia.com> Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
Laxman Dewangan
parent
65450ce220
commit
756aa327f1
@@ -75,7 +75,7 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
copy->iova[i] = DMA_MAPPING_ERROR;
|
||||
copy->sgt[i] = NULL;
|
||||
copy->map[i] = NULL;
|
||||
}
|
||||
|
||||
return ©->base;
|
||||
@@ -139,47 +139,37 @@ const struct drm_plane_funcs tegra_plane_funcs = {
|
||||
|
||||
static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state)
|
||||
{
|
||||
struct iommu_domain *domain = iommu_get_domain_for_dev(dc->dev);
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
for (i = 0; i < state->base.fb->format->num_planes; i++) {
|
||||
struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i);
|
||||
dma_addr_t phys_addr, *phys;
|
||||
struct sg_table *sgt;
|
||||
struct host1x_bo_mapping *map;
|
||||
|
||||
if (!domain || dc->client.group)
|
||||
phys = &phys_addr;
|
||||
else
|
||||
phys = NULL;
|
||||
|
||||
sgt = host1x_bo_pin(dc->dev, &bo->base, phys);
|
||||
if (IS_ERR(sgt)) {
|
||||
err = PTR_ERR(sgt);
|
||||
map = host1x_bo_pin(dc->dev, &bo->base, DMA_TO_DEVICE);
|
||||
if (IS_ERR(map)) {
|
||||
err = PTR_ERR(map);
|
||||
goto unpin;
|
||||
}
|
||||
|
||||
if (sgt) {
|
||||
err = dma_map_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
|
||||
if (err)
|
||||
goto unpin;
|
||||
|
||||
if (!dc->client.group) {
|
||||
/*
|
||||
* The display controller needs contiguous memory, so
|
||||
* fail if the buffer is discontiguous and we fail to
|
||||
* map its SG table to a single contiguous chunk of
|
||||
* I/O virtual memory.
|
||||
*/
|
||||
if (sgt->nents > 1) {
|
||||
if (map->chunks > 1) {
|
||||
err = -EINVAL;
|
||||
goto unpin;
|
||||
}
|
||||
|
||||
state->iova[i] = sg_dma_address(sgt->sgl);
|
||||
state->sgt[i] = sgt;
|
||||
state->iova[i] = map->phys;
|
||||
} else {
|
||||
state->iova[i] = phys_addr;
|
||||
state->iova[i] = bo->iova;
|
||||
}
|
||||
|
||||
state->map[i] = map;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -188,15 +178,9 @@ unpin:
|
||||
dev_err(dc->dev, "failed to map plane %u: %d\n", i, err);
|
||||
|
||||
while (i--) {
|
||||
struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i);
|
||||
struct sg_table *sgt = state->sgt[i];
|
||||
|
||||
if (sgt)
|
||||
dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
|
||||
|
||||
host1x_bo_unpin(dc->dev, &bo->base, sgt);
|
||||
host1x_bo_unpin(state->map[i]);
|
||||
state->iova[i] = DMA_MAPPING_ERROR;
|
||||
state->sgt[i] = NULL;
|
||||
state->map[i] = NULL;
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -207,15 +191,9 @@ static void tegra_dc_unpin(struct tegra_dc *dc, struct tegra_plane_state *state)
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < state->base.fb->format->num_planes; i++) {
|
||||
struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i);
|
||||
struct sg_table *sgt = state->sgt[i];
|
||||
|
||||
if (sgt)
|
||||
dma_unmap_sgtable(dc->dev, sgt, DMA_TO_DEVICE, 0);
|
||||
|
||||
host1x_bo_unpin(dc->dev, &bo->base, sgt);
|
||||
host1x_bo_unpin(state->map[i]);
|
||||
state->iova[i] = DMA_MAPPING_ERROR;
|
||||
state->sgt[i] = NULL;
|
||||
state->map[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user