mirror of
https://github.com/torvalds/linux.git
synced 2025-11-02 01:29:02 +02:00
Add a GEM implementation based on drm_gem_shmem, and support code for the
PowerVR GPU MMU. The GPU VA manager is used for address space management.
Changes since v8:
- Updated for changes to drm_gpuvm
- Switched to dma_resv locking for vm ops
- Removed linked lists for collecting BOs in vm_context and for freeing
after ops. This is now done internally in drm_gpuvm
- Corrected license identifiers
Changes since v7:
- kernel-doc fixes
- Remove prefixes from DRM_PVR_BO_* flags
- CREATE_BO ioctl now returns an error if provided size isn't page aligned
- Optimised MMU flushes
Changes since v6:
- Don't initialise kernel_vm_ctx when using MIPS firmware processor
- Rename drm_gpuva_manager uses to drm_gpuvm
- Sync GEM object to device on creation
Changes since v5:
- Use WRITE_ONCE() when writing to page tables
- Add memory barriers to page table insertion
- Fixed double backing page alloc on page table objects
- Fix BO mask checks in DRM_IOCTL_PVR_CREATE_BO handler
- Document use of pvr_page_table_*_idx when preallocing page table objs
- Remove pvr_vm_gpuva_mapping_init()
- Remove NULL check for unmap op in remap function
- Protect gem object with mutex during drm_gpuva_link/unlink
- Defer free or release of page table pages until after TLB flush
- Use drm_gpuva_op_remap_get_unmap_range() helper
Changes since v4:
- Correct sync function in vmap/vunmap function documentation
- Update for upstream GPU VA manager
- Fix missing frees when unmapping drm_gpuva objects
- Always zero GEM BOs on creation
Changes since v3:
- Split MMU and VM code
- Register page table allocations with kmemleak
- Use drm_dev_{enter,exit}
Changes since v2:
- Use GPU VA manager
- Use drm_gem_shmem
Co-developed-by: Matt Coster <matt.coster@imgtec.com>
Signed-off-by: Matt Coster <matt.coster@imgtec.com>
Co-developed-by: Donald Robson <donald.robson@imgtec.com>
Signed-off-by: Donald Robson <donald.robson@imgtec.com>
Signed-off-by: Sarah Walker <sarah.walker@imgtec.com>
Link: https://lore.kernel.org/r/3c96dd170efe759b73897e3675d7310a7c4b06d0.1700668843.git.donald.robson@imgtec.com
Signed-off-by: Maxime Ripard <mripard@kernel.org>
108 lines
3.6 KiB
C
108 lines
3.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
|
|
/* Copyright (c) 2023 Imagination Technologies Ltd. */
|
|
|
|
#ifndef PVR_MMU_H
|
|
#define PVR_MMU_H
|
|
|
|
#include <linux/memory.h>
|
|
#include <linux/types.h>
|
|
|
|
/* Forward declaration from "pvr_device.h" */
|
|
struct pvr_device;
|
|
|
|
/* Forward declaration from "pvr_mmu.c" */
|
|
struct pvr_mmu_context;
|
|
struct pvr_mmu_op_context;
|
|
|
|
/* Forward declaration from "pvr_vm.c" */
|
|
struct pvr_vm_context;
|
|
|
|
/* Forward declaration from <linux/scatterlist.h> */
|
|
struct sg_table;
|
|
|
|
/**
|
|
* DOC: Public API (constants)
|
|
*
|
|
* .. c:macro:: PVR_DEVICE_PAGE_SIZE
|
|
*
|
|
* Fixed page size referenced by leaf nodes in the page table tree
|
|
* structure. In the current implementation, this value is pegged to the
|
|
* CPU page size (%PAGE_SIZE). It is therefore an error to specify a CPU
|
|
* page size which is not also a supported device page size. The supported
|
|
* device page sizes are: 4KiB, 16KiB, 64KiB, 256KiB, 1MiB and 2MiB.
|
|
*
|
|
* .. c:macro:: PVR_DEVICE_PAGE_SHIFT
|
|
*
|
|
* Shift value used to efficiently multiply or divide by
|
|
* %PVR_DEVICE_PAGE_SIZE.
|
|
*
|
|
* This value is derived from %PVR_DEVICE_PAGE_SIZE.
|
|
*
|
|
* .. c:macro:: PVR_DEVICE_PAGE_MASK
|
|
*
|
|
* Mask used to round a value down to the nearest multiple of
|
|
* %PVR_DEVICE_PAGE_SIZE. When bitwise negated, it will indicate whether a
|
|
* value is already a multiple of %PVR_DEVICE_PAGE_SIZE.
|
|
*
|
|
* This value is derived from %PVR_DEVICE_PAGE_SIZE.
|
|
*/
|
|
|
|
/* PVR_DEVICE_PAGE_SIZE determines the page size */
|
|
#define PVR_DEVICE_PAGE_SIZE (PAGE_SIZE)
|
|
#define PVR_DEVICE_PAGE_SHIFT (PAGE_SHIFT)
|
|
#define PVR_DEVICE_PAGE_MASK (PAGE_MASK)
|
|
|
|
/**
|
|
* DOC: Page table index utilities (constants)
|
|
*
|
|
* .. c:macro:: PVR_PAGE_TABLE_ADDR_SPACE_SIZE
|
|
*
|
|
* Size of device-virtual address space which can be represented in the page
|
|
* table structure.
|
|
*
|
|
* This value is checked at runtime against
|
|
* &pvr_device_features.virtual_address_space_bits by
|
|
* pvr_vm_create_context(), which will return an error if the feature value
|
|
* does not match this constant.
|
|
*
|
|
* .. admonition:: Future work
|
|
*
|
|
* It should be possible to support other values of
|
|
* &pvr_device_features.virtual_address_space_bits, but so far no
|
|
* hardware has been created which advertises an unsupported value.
|
|
*
|
|
* .. c:macro:: PVR_PAGE_TABLE_ADDR_BITS
|
|
*
|
|
* Number of bits needed to represent any value less than
|
|
* %PVR_PAGE_TABLE_ADDR_SPACE_SIZE exactly.
|
|
*
|
|
* .. c:macro:: PVR_PAGE_TABLE_ADDR_MASK
|
|
*
|
|
* Bitmask of device-virtual addresses which are valid in the page table
|
|
* structure.
|
|
*
|
|
* This value is derived from %PVR_PAGE_TABLE_ADDR_SPACE_SIZE, so the same
|
|
* notes on that constant apply here.
|
|
*/
|
|
#define PVR_PAGE_TABLE_ADDR_SPACE_SIZE SZ_1T
|
|
#define PVR_PAGE_TABLE_ADDR_BITS __ffs(PVR_PAGE_TABLE_ADDR_SPACE_SIZE)
|
|
#define PVR_PAGE_TABLE_ADDR_MASK (PVR_PAGE_TABLE_ADDR_SPACE_SIZE - 1)
|
|
|
|
void pvr_mmu_flush_request_all(struct pvr_device *pvr_dev);
|
|
int pvr_mmu_flush_exec(struct pvr_device *pvr_dev, bool wait);
|
|
|
|
struct pvr_mmu_context *pvr_mmu_context_create(struct pvr_device *pvr_dev);
|
|
void pvr_mmu_context_destroy(struct pvr_mmu_context *ctx);
|
|
|
|
dma_addr_t pvr_mmu_get_root_table_dma_addr(struct pvr_mmu_context *ctx);
|
|
|
|
void pvr_mmu_op_context_destroy(struct pvr_mmu_op_context *op_ctx);
|
|
struct pvr_mmu_op_context *
|
|
pvr_mmu_op_context_create(struct pvr_mmu_context *ctx,
|
|
struct sg_table *sgt, u64 sgt_offset, u64 size);
|
|
|
|
int pvr_mmu_map(struct pvr_mmu_op_context *op_ctx, u64 size, u64 flags,
|
|
u64 device_addr);
|
|
int pvr_mmu_unmap(struct pvr_mmu_op_context *op_ctx, u64 device_addr, u64 size);
|
|
|
|
#endif /* PVR_MMU_H */
|