From 1da27ee38f49a06f465f5fcf8a61afd3cb97066f Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 7 Feb 2020 16:50:52 +0100 Subject: [PATCH] drm/tegra: Implement buffer object cache This cache is used to avoid mapping and unmapping buffer objects unnecessarily. Mappings are cached per client and stay hot until the buffer object is destroyed. Bug 200768479 Signed-off-by: Thierry Reding Change-Id: Ia2efe2b77b5043b665bae403d9eba4698e6a5228 Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2596399 (cherry picked from commit d23156d94fa9499256e8082250e3bc02559f9c8d) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2620152 Tested-by: Jonathan Hunter Tested-by: mobile promotions Reviewed-by: Jonathan Hunter Reviewed-by: svc_kernel_abi Reviewed-by: Mikko Perttunen Reviewed-by: mobile promotions GVS: Gerrit_Virtual_Submit --- drivers/gpu/drm/tegra/gem.c | 14 +++++++++++--- drivers/gpu/drm/tegra/plane.c | 2 +- drivers/gpu/drm/tegra/uapi/gather_bo.c | 1 + drivers/gpu/drm/tegra/uapi/uapi.c | 2 +- 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index a838b65a..06da8273 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -60,6 +60,7 @@ static struct host1x_bo_mapping *tegra_bo_pin(struct device *dev, struct host1x_ if (!map) return ERR_PTR(-ENOMEM); + kref_init(&map->ref); map->bo = host1x_bo_get(bo); map->direction = direction; map->dev = dev; @@ -150,9 +151,6 @@ free: static void tegra_bo_unpin(struct host1x_bo_mapping *map) { - if (!map) - return; - if (map->attach) { dma_buf_unmap_attachment(map->attach, map->sgt, map->direction); dma_buf_detach(map->attach->dmabuf, map->attach); @@ -503,8 +501,18 @@ free: void tegra_bo_free_object(struct drm_gem_object *gem) { struct tegra_drm *tegra = gem->dev->dev_private; + struct host1x_bo_mapping *mapping, *tmp; struct tegra_bo *bo = to_tegra_bo(gem); + /* remove all mappings of this buffer object from any caches */ + list_for_each_entry_safe(mapping, tmp, &bo->base.mappings, list) { + if (mapping->cache) + host1x_bo_unpin(mapping); + else + dev_err(gem->dev->dev, "mapping %p stale for device %s\n", mapping, + dev_name(mapping->dev)); + } + if (tegra->domain) tegra_bo_iommu_unmap(tegra, bo); diff --git a/drivers/gpu/drm/tegra/plane.c b/drivers/gpu/drm/tegra/plane.c index c5e6106b..5a6ae760 100644 --- a/drivers/gpu/drm/tegra/plane.c +++ b/drivers/gpu/drm/tegra/plane.c @@ -146,7 +146,7 @@ static int tegra_dc_pin(struct tegra_dc *dc, struct tegra_plane_state *state) struct tegra_bo *bo = tegra_fb_get_plane(state->base.fb, i); struct host1x_bo_mapping *map; - map = host1x_bo_pin(dc->dev, &bo->base, DMA_TO_DEVICE); + map = host1x_bo_pin(dc->dev, &bo->base, DMA_TO_DEVICE, &dc->client.cache); if (IS_ERR(map)) { err = PTR_ERR(map); goto unpin; diff --git a/drivers/gpu/drm/tegra/uapi/gather_bo.c b/drivers/gpu/drm/tegra/uapi/gather_bo.c index c20a0343..b474792d 100644 --- a/drivers/gpu/drm/tegra/uapi/gather_bo.c +++ b/drivers/gpu/drm/tegra/uapi/gather_bo.c @@ -43,6 +43,7 @@ gather_bo_pin(struct device *dev, struct host1x_bo *bo, enum dma_data_direction if (!map) return ERR_PTR(-ENOMEM); + kref_init(&map->ref); map->bo = host1x_bo_get(bo); map->direction = direction; map->dev = dev; diff --git a/drivers/gpu/drm/tegra/uapi/uapi.c b/drivers/gpu/drm/tegra/uapi/uapi.c index 6c391164..1d5eca68 100644 --- a/drivers/gpu/drm/tegra/uapi/uapi.c +++ b/drivers/gpu/drm/tegra/uapi/uapi.c @@ -192,7 +192,7 @@ int tegra_drm_ioctl_channel_map(struct drm_device *drm, void *data, else direction = DMA_TO_DEVICE; - mapping->map = host1x_bo_pin(ctx->client->base.dev, mapping->bo, direction); + mapping->map = host1x_bo_pin(ctx->client->base.dev, mapping->bo, direction, NULL); if (IS_ERR(mapping->map)) { err = PTR_ERR(mapping->map); goto put_gem;