text: /* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 and
   * only version 2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   */
  
  #ifndef _LINUX_MSM_DMA_IOMMU_MAPPING_H
  #define _LINUX_MSM_DMA_IOMMU_MAPPING_H
  
  #include <linux/device.h>
  #include <linux/dma-buf.h>
  #include <linux/scatterlist.h>
  #include <linux/dma-mapping.h>
  
  #ifdef CONFIG_QCOM_LAZY_MAPPING
  /*
   * This function is not taking a reference to the dma_buf here. It is expected
   * that clients hold reference to the dma_buf until they are done with mapping
   * and unmapping.
   */
  int msm_dma_map_sg_attrs(struct device *dev, struct scatterlist *sg, int nents,
  		   enum dma_data_direction dir, struct dma_buf *dma_buf,
  		   unsigned long attrs);
  
  /*
   * This function takes an extra reference to the dma_buf.
   * What this means is that calling msm_dma_unmap_sg will not result in buffer's
   * iommu mapping being removed, which means that subsequent calls to lazy map
   * will simply re-use the existing iommu mapping.
   * The iommu unmapping of the buffer will occur when the ION buffer is
   * destroyed.
   * Using lazy mapping can provide a performance benefit because subsequent
   * mappings are faster.
   *
   * The limitation of using this API are that all subsequent iommu mappings
   * must be the same as the original mapping, ie they must map the same part of
   * the buffer with the same dma data direction. Also there can't be multiple
   * mappings of different parts of the buffer.
   */
  static inline int msm_dma_map_sg_lazy(struct device *dev,
  			       struct scatterlist *sg, int nents,
  			       enum dma_data_direction dir,
  			       struct dma_buf *dma_buf)
  {
  	return msm_dma_map_sg_attrs(dev, sg, nents, dir, dma_buf, 0);
  }
  
  static inline int msm_dma_map_sg(struct device *dev, struct scatterlist *sg,
  				  int nents, enum dma_data_direction dir,
  				  struct dma_buf *dma_buf)
  {
  	unsigned long attrs;
  
  	attrs = DMA_ATTR_NO_DELAYED_UNMAP;
  	return msm_dma_map_sg_attrs(dev, sg, nents, dir, dma_buf, attrs);
  }
  
  void msm_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, int nents,
  		      enum dma_data_direction dir, struct dma_buf *dma_buf);
  
  int msm_dma_unmap_all_for_dev(struct device *dev);
  
  /*
   * Below is private function only to be called by framework (ION) and not by
   * clients.
   */
  void msm_dma_buf_freed(void *buffer);
  
  #else /*CONFIG_QCOM_LAZY_MAPPING*/
  
  static inline int msm_dma_map_sg_attrs(struct device *dev,
  			struct scatterlist *sg, int nents,
  			enum dma_data_direction dir, struct dma_buf *dma_buf,
  			unsigned long attrs)
  {
  	return -EINVAL;
  }
  
  static inline int msm_dma_map_sg_lazy(struct device *dev,
  			       struct scatterlist *sg, int nents,
  			       enum dma_data_direction dir,
  			       struct dma_buf *dma_buf)
  {
  	return -EINVAL;
  }
  
  static inline int msm_dma_map_sg(struct device *dev, struct scatterlist *sg,
  				  int nents, enum dma_data_direction dir,
  				  struct dma_buf *dma_buf)
  {
  	return -EINVAL;
  }
  
  static inline void msm_dma_unmap_sg(struct device *dev,
  					struct scatterlist *sgl, int nents,
  					enum dma_data_direction dir,
  					struct dma_buf *dma_buf)
  {
  }
  
  static inline int msm_dma_unmap_all_for_dev(struct device *dev)
  {
  	return 0;
  }
  
  static inline void msm_dma_buf_freed(void *buffer) {}
  #endif /*CONFIG_QCOM_LAZY_MAPPING*/
  
  #endif
  