diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-16 07:42:10 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-16 07:42:10 +0300 |
commit | e60e1ee60630cafef5e430c2ae364877e061d980 (patch) | |
tree | 816aeef8fe8d4a2c6a1ebbc7a350839bac8dd4c2 /drivers/gpu/drm/etnaviv/etnaviv_mmu.c | |
parent | 5d352e69c60e54b5f04d6e337a1d2bf0dbf3d94a (diff) | |
parent | f150891fd9878ef0d9197c4e8451ce67c3bdd014 (diff) | |
download | linux-e60e1ee60630cafef5e430c2ae364877e061d980.tar.xz |
Merge tag 'drm-for-v4.15' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"This is the main drm pull request for v4.15.
Core:
- Atomic object lifetime fixes
- Atomic iterator improvements
- Sparse/smatch fixes
- Legacy kms ioctls to be interruptible
- EDID override improvements
- fb/gem helper cleanups
- Simple outreachy patches
- Documentation improvements
- Fix dma-buf rcu races
- DRM mode object leasing for improving VR use cases.
- vgaarb improvements for non-x86 platforms.
New driver:
- tve200: Faraday Technology TVE200 block.
This "TV Encoder" encodes a ITU-T BT.656 stream and can be found in
the StorLink SL3516 (later Cortina Systems CS3516) as well as the
Grain Media GM8180.
New bridges:
- SiI9234 support
New panels:
- S6E63J0X03, OTM8009A, Seiko 43WVF1G, 7" rpi touch panel, Toshiba
LT089AC19000, Innolux AT043TN24
i915:
- Remove Coffeelake from alpha support
- Cannonlake workarounds
- Infoframe refactoring for DisplayPort
- VBT updates
- DisplayPort vswing/emph/buffer translation refactoring
- CCS fixes
- Restore GPU clock boost on missed vblanks
- Scatter list updates for userptr allocations
- Gen9+ transition watermarks
- Display IPC (Isochronous Priority Control)
- Private PAT management
- GVT: improved error handling and pci config sanitizing
- Execlist refactoring
- Transparent Huge Page support
- User defined priorities support
- HuC/GuC firmware refactoring
- DP MST fixes
- eDP power sequencing fixes
- Use RCU instead of stop_machine
- PSR state tracking support
- Eviction fixes
- BDW DP aux channel timeout fixes
- LSPCON fixes
- Cannonlake PLL fixes
amdgpu:
- Per VM BO support
- Powerplay cleanups
- CI powerplay support
- PASID mgr for kfd
- SR-IOV fixes
- initial GPU reset for vega10
- Prime mmap support
- TTM updates
- Clock query interface for Raven
- Fence to handle ioctl
- UVD encode ring support on Polaris
- Transparent huge page DMA support
- Compute LRU pipe tweaks
- BO flag to allow buffers to opt out of implicit sync
- CTX priority setting API
- VRAM lost infrastructure plumbing
qxl:
- fix flicker since atomic rework
amdkfd:
- Further improvements from internal AMD tree
- Usermode events
- Drop radeon support
nouveau:
- Pascal temperature sensor support
- Improved BAR2 handling
- MMU rework to support Pascal MMU
exynos:
- Improved HDMI/mixer support
- HDMI audio interface support
tegra:
- Prep work for tegra186
- Cleanup/fixes
msm:
- Preemption support for a5xx
- Display fixes for 8x96 (snapdragon 820)
- Async cursor plane fixes
- FW loading rework
- GPU debugging improvements
vc4:
- Prep for DSI panels
- fix T-format tiling scanout
- New madvise ioctl
Rockchip:
- LVDS support
omapdrm:
- omap4 HDMI CEC support
etnaviv:
- GPU performance counters groundwork
sun4i:
- refactor driver load + TCON backend
- HDMI improvements
- A31 support
- Misc fixes
udl:
- Probe/EDID read fixes.
tilcdc:
- Misc fixes.
pl111:
- Support more variants
adv7511:
- Improve EDID handling.
- HDMI CEC support
sii8620:
- Add remote control support"
* tag 'drm-for-v4.15' of git://people.freedesktop.org/~airlied/linux: (1480 commits)
drm/rockchip: analogix_dp: Use mutex rather than spinlock
drm/mode_object: fix documentation for object lookups.
drm/i915: Reorder context-close to avoid calling i915_vma_close() under RCU
drm/i915: Move init_clock_gating() back to where it was
drm/i915: Prune the reservation shared fence array
drm/i915: Idle the GPU before shinking everything
drm/i915: Lock llist_del_first() vs llist_del_all()
drm/i915: Calculate ironlake intermediate watermarks correctly, v2.
drm/i915: Disable lazy PPGTT page table optimization for vGPU
drm/i915/execlists: Remove the priority "optimisation"
drm/i915: Filter out spurious execlists context-switch interrupts
drm/amdgpu: use irq-safe lock for kiq->ring_lock
drm/amdgpu: bypass lru touch for KIQ ring submission
drm/amdgpu: Potential uninitialized variable in amdgpu_vm_update_directories()
drm/amdgpu: potential uninitialized variable in amdgpu_vce_ring_parse_cs()
drm/amd/powerplay: initialize a variable before using it
drm/amd/powerplay: suppress KASAN out of bounds warning in vega10_populate_all_memory_levels
drm/amd/amdgpu: fix evicted VRAM bo adjudgement condition
drm/vblank: Tune drm_crtc_accurate_vblank_count() WARN down to a debug
drm/rockchip: add CONFIG_OF dependency for lvds
...
Diffstat (limited to 'drivers/gpu/drm/etnaviv/etnaviv_mmu.c')
-rw-r--r-- | drivers/gpu/drm/etnaviv/etnaviv_mmu.c | 106 |
1 files changed, 68 insertions, 38 deletions
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c index f103e787de94..35074b944778 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c @@ -22,17 +22,64 @@ #include "etnaviv_iommu.h" #include "etnaviv_mmu.h" -static int etnaviv_fault_handler(struct iommu_domain *iommu, struct device *dev, - unsigned long iova, int flags, void *arg) +static void etnaviv_domain_unmap(struct etnaviv_iommu_domain *domain, + unsigned long iova, size_t size) { - DBG("*** fault: iova=%08lx, flags=%d", iova, flags); - return 0; + size_t unmapped_page, unmapped = 0; + size_t pgsize = SZ_4K; + + if (!IS_ALIGNED(iova | size, pgsize)) { + pr_err("unaligned: iova 0x%lx size 0x%zx min_pagesz 0x%x\n", + iova, size, pgsize); + return; + } + + while (unmapped < size) { + unmapped_page = domain->ops->unmap(domain, iova, pgsize); + if (!unmapped_page) + break; + + iova += unmapped_page; + unmapped += unmapped_page; + } } -int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova, - struct sg_table *sgt, unsigned len, int prot) +static int etnaviv_domain_map(struct etnaviv_iommu_domain *domain, + unsigned long iova, phys_addr_t paddr, + size_t size, int prot) { - struct iommu_domain *domain = iommu->domain; + unsigned long orig_iova = iova; + size_t pgsize = SZ_4K; + size_t orig_size = size; + int ret = 0; + + if (!IS_ALIGNED(iova | paddr | size, pgsize)) { + pr_err("unaligned: iova 0x%lx pa %pa size 0x%zx min_pagesz 0x%x\n", + iova, &paddr, size, pgsize); + return -EINVAL; + } + + while (size) { + ret = domain->ops->map(domain, iova, paddr, pgsize, prot); + if (ret) + break; + + iova += pgsize; + paddr += pgsize; + size -= pgsize; + } + + /* unroll mapping in case something went wrong */ + if (ret) + etnaviv_domain_unmap(domain, orig_iova, orig_size - size); + + return ret; +} + +static int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova, + struct sg_table *sgt, unsigned len, int prot) +{ + struct etnaviv_iommu_domain *domain = iommu->domain; struct scatterlist *sg; unsigned int da = iova; unsigned int i, j; @@ -47,7 +94,7 @@ int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova, VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes); - ret = iommu_map(domain, da, pa, bytes, prot); + ret = etnaviv_domain_map(domain, da, pa, bytes, prot); if (ret) goto fail; @@ -62,27 +109,24 @@ fail: for_each_sg(sgt->sgl, sg, i, j) { size_t bytes = sg_dma_len(sg) + sg->offset; - iommu_unmap(domain, da, bytes); + etnaviv_domain_unmap(domain, da, bytes); da += bytes; } return ret; } -int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova, - struct sg_table *sgt, unsigned len) +static void etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova, + struct sg_table *sgt, unsigned len) { - struct iommu_domain *domain = iommu->domain; + struct etnaviv_iommu_domain *domain = iommu->domain; struct scatterlist *sg; unsigned int da = iova; int i; for_each_sg(sgt->sgl, sg, sgt->nents, i) { size_t bytes = sg_dma_len(sg) + sg->offset; - size_t unmapped; - unmapped = iommu_unmap(domain, da, bytes); - if (unmapped < bytes) - return unmapped; + etnaviv_domain_unmap(domain, da, bytes); VERB("unmap[%d]: %08x(%zx)", i, iova, bytes); @@ -90,8 +134,6 @@ int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova, da += bytes; } - - return 0; } static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu *mmu, @@ -237,7 +279,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu, mmu->last_iova = node->start + etnaviv_obj->base.size; mapping->iova = node->start; ret = etnaviv_iommu_map(mmu, node->start, sgt, etnaviv_obj->base.size, - IOMMU_READ | IOMMU_WRITE); + ETNAVIV_PROT_READ | ETNAVIV_PROT_WRITE); if (ret < 0) { drm_mm_remove_node(node); @@ -271,7 +313,7 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu, void etnaviv_iommu_destroy(struct etnaviv_iommu *mmu) { drm_mm_takedown(&mmu->mm); - iommu_domain_free(mmu->domain); + mmu->domain->ops->free(mmu->domain); kfree(mmu); } @@ -303,11 +345,7 @@ struct etnaviv_iommu *etnaviv_iommu_new(struct etnaviv_gpu *gpu) mutex_init(&mmu->lock); INIT_LIST_HEAD(&mmu->mappings); - drm_mm_init(&mmu->mm, mmu->domain->geometry.aperture_start, - mmu->domain->geometry.aperture_end - - mmu->domain->geometry.aperture_start + 1); - - iommu_set_fault_handler(mmu->domain, etnaviv_fault_handler, gpu->dev); + drm_mm_init(&mmu->mm, mmu->domain->base, mmu->domain->size); return mmu; } @@ -338,8 +376,8 @@ int etnaviv_iommu_get_suballoc_va(struct etnaviv_gpu *gpu, dma_addr_t paddr, mutex_unlock(&mmu->lock); return ret; } - ret = iommu_map(mmu->domain, vram_node->start, paddr, size, - IOMMU_READ); + ret = etnaviv_domain_map(mmu->domain, vram_node->start, paddr, + size, ETNAVIV_PROT_READ); if (ret < 0) { drm_mm_remove_node(vram_node); mutex_unlock(&mmu->lock); @@ -362,25 +400,17 @@ void etnaviv_iommu_put_suballoc_va(struct etnaviv_gpu *gpu, if (mmu->version == ETNAVIV_IOMMU_V2) { mutex_lock(&mmu->lock); - iommu_unmap(mmu->domain,iova, size); + etnaviv_domain_unmap(mmu->domain, iova, size); drm_mm_remove_node(vram_node); mutex_unlock(&mmu->lock); } } size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu) { - struct etnaviv_iommu_ops *ops; - - ops = container_of(iommu->domain->ops, struct etnaviv_iommu_ops, ops); - - return ops->dump_size(iommu->domain); + return iommu->domain->ops->dump_size(iommu->domain); } void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf) { - struct etnaviv_iommu_ops *ops; - - ops = container_of(iommu->domain->ops, struct etnaviv_iommu_ops, ops); - - ops->dump(iommu->domain, buf); + iommu->domain->ops->dump(iommu->domain, buf); } |