Loading drivers/iommu/msm_dma_iommu_mapping.c +41 −21 Original line number Diff line number Diff line Loading @@ -27,10 +27,11 @@ * @dev - Device this is mapped to. Used as key * @sgl - The scatterlist for this mapping * @nents - Number of entries in sgl * @dir - The direction for the unmap. * @dir - The direction for the map. * @meta - Backpointer to the meta this guy belongs to. * @ref - for reference counting this mapping * @attrs - dma mapping attributes * @buf_start_addr - address of start of buffer * * Represents a mapping of one dma_buf buffer to a particular device * and address range. There may exist other mappings of this buffer in Loading @@ -46,6 +47,7 @@ struct msm_iommu_map { struct msm_iommu_meta *meta; struct kref ref; unsigned long attrs; dma_addr_t buf_start_addr; }; struct msm_iommu_meta { Loading Loading @@ -218,6 +220,9 @@ static inline int __msm_dma_map_sg(struct device *dev, struct scatterlist *sg, } iommu_map->nents = nents; iommu_map->dev = dev; iommu_map->dir = dir; iommu_map->attrs = attrs; iommu_map->buf_start_addr = sg_phys(sg); kref_init(&iommu_map->ref); if (late_unmap) Loading @@ -226,6 +231,11 @@ static inline int __msm_dma_map_sg(struct device *dev, struct scatterlist *sg, msm_iommu_add(iommu_meta, iommu_map); } else { if (nents == iommu_map->nents && dir == iommu_map->dir && (attrs & ~DMA_ATTR_SKIP_CPU_SYNC) == (iommu_map->attrs & ~DMA_ATTR_SKIP_CPU_SYNC) && sg_phys(sg) == iommu_map->buf_start_addr) { sg->dma_address = iommu_map->sgl->dma_address; sg->dma_length = iommu_map->sgl->dma_length; Loading @@ -243,6 +253,20 @@ static inline int __msm_dma_map_sg(struct device *dev, struct scatterlist *sg, */ dmb(ish); ret = nents; } else { bool start_diff = (sg_phys(sg) != iommu_map->buf_start_addr); dev_err(dev, "lazy map request differs:\n" "req dir:%d, original dir:%d\n" "req nents:%d, original nents:%d\n" "req map attrs:%lu, original map attrs:%lu\n" "req buffer start address differs:%d\n", dir, iommu_map->dir, nents, iommu_map->nents, attrs, iommu_map->attrs, start_diff); ret = -EINVAL; } } mutex_unlock(&iommu_meta->lock); return ret; Loading Loading @@ -360,13 +384,9 @@ void msm_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, goto out; } /* * Save direction for later use when we actually unmap. * Not used right now but in the future if we go to coherent mapping * API we might want to call the appropriate API when client asks * to unmap */ iommu_map->dir = dir; if (dir != iommu_map->dir) WARN(1, "%s: (%pK) dir:%d differs from original dir:%d\n", __func__, dma_buf, dir, iommu_map->dir); if (attrs && ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)) dma_sync_sg_for_cpu(dev, iommu_map->sgl, iommu_map->nents, dir); Loading include/linux/msm_dma_iommu_mapping.h +15 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,21 @@ 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, Loading Loading
drivers/iommu/msm_dma_iommu_mapping.c +41 −21 Original line number Diff line number Diff line Loading @@ -27,10 +27,11 @@ * @dev - Device this is mapped to. Used as key * @sgl - The scatterlist for this mapping * @nents - Number of entries in sgl * @dir - The direction for the unmap. * @dir - The direction for the map. * @meta - Backpointer to the meta this guy belongs to. * @ref - for reference counting this mapping * @attrs - dma mapping attributes * @buf_start_addr - address of start of buffer * * Represents a mapping of one dma_buf buffer to a particular device * and address range. There may exist other mappings of this buffer in Loading @@ -46,6 +47,7 @@ struct msm_iommu_map { struct msm_iommu_meta *meta; struct kref ref; unsigned long attrs; dma_addr_t buf_start_addr; }; struct msm_iommu_meta { Loading Loading @@ -218,6 +220,9 @@ static inline int __msm_dma_map_sg(struct device *dev, struct scatterlist *sg, } iommu_map->nents = nents; iommu_map->dev = dev; iommu_map->dir = dir; iommu_map->attrs = attrs; iommu_map->buf_start_addr = sg_phys(sg); kref_init(&iommu_map->ref); if (late_unmap) Loading @@ -226,6 +231,11 @@ static inline int __msm_dma_map_sg(struct device *dev, struct scatterlist *sg, msm_iommu_add(iommu_meta, iommu_map); } else { if (nents == iommu_map->nents && dir == iommu_map->dir && (attrs & ~DMA_ATTR_SKIP_CPU_SYNC) == (iommu_map->attrs & ~DMA_ATTR_SKIP_CPU_SYNC) && sg_phys(sg) == iommu_map->buf_start_addr) { sg->dma_address = iommu_map->sgl->dma_address; sg->dma_length = iommu_map->sgl->dma_length; Loading @@ -243,6 +253,20 @@ static inline int __msm_dma_map_sg(struct device *dev, struct scatterlist *sg, */ dmb(ish); ret = nents; } else { bool start_diff = (sg_phys(sg) != iommu_map->buf_start_addr); dev_err(dev, "lazy map request differs:\n" "req dir:%d, original dir:%d\n" "req nents:%d, original nents:%d\n" "req map attrs:%lu, original map attrs:%lu\n" "req buffer start address differs:%d\n", dir, iommu_map->dir, nents, iommu_map->nents, attrs, iommu_map->attrs, start_diff); ret = -EINVAL; } } mutex_unlock(&iommu_meta->lock); return ret; Loading Loading @@ -360,13 +384,9 @@ void msm_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, goto out; } /* * Save direction for later use when we actually unmap. * Not used right now but in the future if we go to coherent mapping * API we might want to call the appropriate API when client asks * to unmap */ iommu_map->dir = dir; if (dir != iommu_map->dir) WARN(1, "%s: (%pK) dir:%d differs from original dir:%d\n", __func__, dma_buf, dir, iommu_map->dir); if (attrs && ((attrs & DMA_ATTR_SKIP_CPU_SYNC) == 0)) dma_sync_sg_for_cpu(dev, iommu_map->sgl, iommu_map->nents, dir); Loading
include/linux/msm_dma_iommu_mapping.h +15 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,21 @@ 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, Loading