Subject: linux-next: manual merge of the char-misc tree with the drm-tegra tree

From: Stephen Rothwell <[email-masked]>
Date: Wed, 27 Oct 2021 15:37:39 +1100

Hi all,

Today's linux-next merge of the char-misc tree got a conflict in:

  drivers/gpu/drm/tegra/gem.c

between commit:

  1c4d17a5267b ("drm/tegra: Implement correct DMA-BUF semantics")

from the drm-tegra tree and commit:

  16b0314aa746 ("dma-buf: move dma-buf symbols into the DMA_BUF module namespace")

from the char-misc tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.

-- 
Cheers,
Stephen Rothwell

diff --cc drivers/gpu/drm/tegra/gem.c
index 62fc7e8429d4,d38fd7e12b57..000000000000
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@@ -20,78 -21,60 +21,80 @@@
  #include "drm.h"
  #include "gem.h"
  
+ MODULE_IMPORT_NS(DMA_BUF);
+ 
 -static void tegra_bo_put(struct host1x_bo *bo)
 +static unsigned int sg_dma_count_chunks(struct scatterlist *sgl, unsigned int nents)
  {
 -	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
 +	dma_addr_t next = ~(dma_addr_t)0;
 +	unsigned int count = 0, i;
 +	struct scatterlist *s;
 +
 +	for_each_sg(sgl, s, nents, i) {
 +		/* sg_dma_address(s) is only valid for entries that have sg_dma_len(s) != 0. */
 +		if (!sg_dma_len(s))
 +			continue;
 +
 +		if (sg_dma_address(s) != next) {
 +			next = sg_dma_address(s) + sg_dma_len(s);
 +			count++;
 +		}
 +	}
  
 -	drm_gem_object_put(&obj->gem);
 +	return count;
  }
  
 -/* XXX move this into lib/scatterlist.c? */
 -static int sg_alloc_table_from_sg(struct sg_table *sgt, struct scatterlist *sg,
 -				  unsigned int nents, gfp_t gfp_mask)
 +static inline unsigned int sgt_dma_count_chunks(struct sg_table *sgt)
  {
 -	struct scatterlist *dst;
 -	unsigned int i;
 -	int err;
 -
 -	err = sg_alloc_table(sgt, nents, gfp_mask);
 -	if (err < 0)
 -		return err;
 -
 -	dst = sgt->sgl;
 +	return sg_dma_count_chunks(sgt->sgl, sgt->nents);
 +}
  
 -	for (i = 0; i < nents; i++) {
 -		sg_set_page(dst, sg_page(sg), sg->length, 0);
 -		dst = sg_next(dst);
 -		sg = sg_next(sg);
 -	}
 +static void tegra_bo_put(struct host1x_bo *bo)
 +{
 +	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
  
 -	return 0;
 +	drm_gem_object_put(&obj->gem);
  }
  
 -static struct sg_table *tegra_bo_pin(struct device *dev, struct host1x_bo *bo,
 -				     dma_addr_t *phys)
 +static struct host1x_bo_mapping *tegra_bo_pin(struct device *dev, struct host1x_bo *bo,
 +					      enum dma_data_direction direction)
  {
  	struct tegra_bo *obj = host1x_to_tegra_bo(bo);
 -	struct sg_table *sgt;
 +	struct drm_gem_object *gem = &obj->gem;
 +	struct host1x_bo_mapping *map;
  	int err;
  
 +	map = kzalloc(sizeof(*map), GFP_KERNEL);
 +	if (!map)
 +		return ERR_PTR(-ENOMEM);
 +
 +	kref_init(&map->ref);
 +	map->bo = host1x_bo_get(bo);
 +	map->direction = direction;
 +	map->dev = dev;
 +
  	/*
 -	 * If we've manually mapped the buffer object through the IOMMU, make
 -	 * sure to return the IOVA address of our mapping.
 -	 *
 -	 * Similarly, for buffers that have been allocated by the DMA API the
 -	 * physical address can be used for devices that are not attached to
 -	 * an IOMMU. For these devices, callers must pass a valid pointer via
 -	 * the @phys argument.
 -	 *
 -	 * Imported buffers were also already mapped at import time, so the
 -	 * existing mapping can be reused.
 +	 * Imported buffers need special treatment to satisfy the semantics of DMA-BUF.
  	 */
 -	if (phys) {
 -		*phys = obj->iova;
 -		return NULL;
 +	if (gem->import_attach) {
 +		struct dma_buf *buf = gem->import_attach->dmabuf;
 +
 +		map->attach = dma_buf_attach(buf, dev);
 +		if (IS_ERR(map->attach)) {
 +			err = PTR_ERR(map->attach);
 +			goto free;
 +		}
 +
 +		map->sgt = dma_buf_map_attachment(map->attach, direction);
 +		if (IS_ERR(map->sgt)) {
 +			dma_buf_detach(buf, map->attach);
 +			err = PTR_ERR(map->sgt);
 +			goto free;
 +		}
 +
 +		err = sgt_dma_count_chunks(map->sgt);
 +		map->size = gem->size;
 +
 +		goto out;
  	}
  
  	/*