diff --git a/msm/msm_gem.c b/msm/msm_gem.c index a17f7ea139..4e08fb15fb 100644 --- a/msm/msm_gem.c +++ b/msm/msm_gem.c @@ -28,6 +28,9 @@ #include "msm_mmu.h" #include "sde_dbg.h" +#define GUARD_BYTES (BIT(8) - 1) +#define ALIGNED_OFFSET (U32_MAX & ~(GUARD_BYTES)) + static void msm_gem_vunmap_locked(struct drm_gem_object *obj); @@ -1395,3 +1398,72 @@ void msm_gem_object_set_name(struct drm_gem_object *bo, const char *fmt, ...) vsnprintf(msm_obj->name, sizeof(msm_obj->name), fmt, ap); va_end(ap); } + +void msm_gem_put_buffer(struct drm_gem_object *gem) +{ + struct msm_gem_object *msm_gem; + + if (!gem) + return; + + msm_gem = to_msm_bo(gem); + + msm_gem_put_iova(gem, msm_gem->aspace); + msm_gem_put_vaddr(gem); +} + +int msm_gem_get_buffer(struct drm_gem_object *gem, + struct drm_device *dev, struct drm_framebuffer *fb, + uint32_t align_size) +{ + struct msm_gem_object *msm_gem; + uint32_t size; + uint64_t iova_aligned; + int ret = -EINVAL; + + if (!gem) { + DRM_ERROR("invalid drm gem"); + return ret; + } + + msm_gem = to_msm_bo(gem); + + size = PAGE_ALIGN(gem->size); + if (size < (align_size + GUARD_BYTES)) { + DRM_ERROR("invalid gem size"); + goto exit; + } + + msm_gem_smmu_address_space_get(dev, MSM_SMMU_DOMAIN_UNSECURE); + + if (PTR_ERR(msm_gem->aspace) == -ENODEV) { + DRM_DEBUG("IOMMU not present, relying on VRAM."); + } else if (IS_ERR_OR_NULL(msm_gem->aspace)) { + ret = PTR_ERR(msm_gem->aspace); + DRM_ERROR("failed to get aspace"); + goto exit; + } + + ret = msm_gem_get_iova(gem, msm_gem->aspace, &msm_gem->iova); + if (ret) { + DRM_ERROR("failed to get the iova ret %d", ret); + goto exit; + } + + msm_gem_get_vaddr(gem); + if (IS_ERR_OR_NULL(msm_gem->vaddr)) { + DRM_ERROR("failed to get vaddr"); + goto exit; + } + + iova_aligned = (msm_gem->iova + GUARD_BYTES) & ALIGNED_OFFSET; + msm_gem->offset = iova_aligned - msm_gem->iova; + msm_gem->iova = msm_gem->iova + msm_gem->offset; + + return 0; + +exit: + msm_gem_put_buffer(gem); + + return ret; +} diff --git a/msm/msm_gem.h b/msm/msm_gem.h index eba6f94d4a..2473d6a85a 100644 --- a/msm/msm_gem.h +++ b/msm/msm_gem.h @@ -146,6 +146,10 @@ struct msm_gem_object { * new pagetables due to cb switch */ bool obj_dirty; + + /* iova address and aligned offset */ + uint64_t iova; + uint32_t offset; }; #define to_msm_bo(x) container_of(x, struct msm_gem_object, base) @@ -219,4 +223,21 @@ struct msm_gem_submit { } bos[0]; }; +/** + * msm_gem_put_buffer - put gem buffer + * @gem: pointer to gem buffer object + */ +void msm_gem_put_buffer(struct drm_gem_object *gem); + +/** + * msm_gem_gem_buffer - get a gem buffer + * @gem: drm gem object + * @drm_device: pointer to drm device + * @fb: frame buffer object + * @align_size: size to align the buffer to + */ +int msm_gem_get_buffer(struct drm_gem_object *gem, + struct drm_device *dev, struct drm_framebuffer *fb, + uint32_t align_size); + #endif /* __MSM_GEM_H__ */