2018-05-08 22:20:54 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
2015-12-04 01:21:29 +08:00
|
|
|
/*
|
2018-05-08 22:20:54 +08:00
|
|
|
* Copyright (C) 2015-2018 Etnaviv Project
|
2015-12-04 01:21:29 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __ETNAVIV_DRV_H__
|
|
|
|
#define __ETNAVIV_DRV_H__
|
|
|
|
|
2019-06-30 13:21:03 +08:00
|
|
|
#include <linux/list.h>
|
|
|
|
#include <linux/mm_types.h>
|
|
|
|
#include <linux/sizes.h>
|
2018-02-20 17:22:22 +08:00
|
|
|
#include <linux/time64.h>
|
2015-12-04 01:21:29 +08:00
|
|
|
#include <linux/types.h>
|
|
|
|
|
|
|
|
#include <drm/drm_fb_helper.h>
|
|
|
|
#include <drm/drm_gem.h>
|
|
|
|
#include <drm/etnaviv_drm.h>
|
2017-12-05 01:41:58 +08:00
|
|
|
#include <drm/gpu_scheduler.h>
|
2015-12-04 01:21:29 +08:00
|
|
|
|
|
|
|
struct etnaviv_cmdbuf;
|
|
|
|
struct etnaviv_gpu;
|
|
|
|
struct etnaviv_mmu;
|
|
|
|
struct etnaviv_gem_object;
|
|
|
|
struct etnaviv_gem_submit;
|
drm/etnaviv: rework MMU handling
This reworks the MMU handling to make it possible to have multiple MMU contexts.
A context is basically one instance of GPU page tables. Currently we have one
set of page tables per GPU, which isn't all that clever, as it has the
following two consequences:
1. All GPU clients (aka processes) are sharing the same pagetables, which means
there is no isolation between clients, but only between GPU assigned memory
spaces and the rest of the system. Better than nothing, but also not great.
2. Clients operating on the same set of buffers with different etnaviv GPU
cores, e.g. a workload using both the 2D and 3D GPU, need to map the used
buffers into the pagetable sets of each used GPU.
This patch reworks all the MMU handling to introduce the abstraction of the
MMU context. A context can be shared across different GPU cores, as long as
they have compatible MMU implementations, which is the case for all systems
with Vivante GPUs seen in the wild.
As MMUv1 is not able to change pagetables on the fly, without a
"stop the world" operation, which stops GPU, changes pagetables via CPU
interaction, restarts GPU, the implementation introduces a shared context on
MMUv1, which is returned whenever there is a request for a new context.
This patch assigns a MMU context to each GPU, so on MMUv2 systems there is
still one set of pagetables per GPU, but due to the shared context MMUv1
systems see a change in behavior as now a single pagetable set is used
across all GPU cores.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Guido Günther <agx@sigxcpu.org>
2019-07-06 01:17:24 +08:00
|
|
|
struct etnaviv_iommu_global;
|
2015-12-04 01:21:29 +08:00
|
|
|
|
2019-08-02 20:27:33 +08:00
|
|
|
#define ETNAVIV_SOFTPIN_START_ADDRESS SZ_4M /* must be >= SUBALLOC_SIZE */
|
|
|
|
|
2015-12-04 01:21:29 +08:00
|
|
|
struct etnaviv_file_private {
|
2019-07-06 01:17:27 +08:00
|
|
|
struct etnaviv_iommu_context *mmu;
|
2017-12-05 01:41:58 +08:00
|
|
|
struct drm_sched_entity sched_entity[ETNA_MAX_PIPES];
|
2015-12-04 01:21:29 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct etnaviv_drm_private {
|
|
|
|
int num_gpus;
|
|
|
|
struct etnaviv_gpu *gpu[ETNA_MAX_PIPES];
|
2020-02-27 19:09:25 +08:00
|
|
|
gfp_t shm_gfp_mask;
|
2015-12-04 01:21:29 +08:00
|
|
|
|
2019-07-06 01:17:22 +08:00
|
|
|
struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc;
|
drm/etnaviv: rework MMU handling
This reworks the MMU handling to make it possible to have multiple MMU contexts.
A context is basically one instance of GPU page tables. Currently we have one
set of page tables per GPU, which isn't all that clever, as it has the
following two consequences:
1. All GPU clients (aka processes) are sharing the same pagetables, which means
there is no isolation between clients, but only between GPU assigned memory
spaces and the rest of the system. Better than nothing, but also not great.
2. Clients operating on the same set of buffers with different etnaviv GPU
cores, e.g. a workload using both the 2D and 3D GPU, need to map the used
buffers into the pagetable sets of each used GPU.
This patch reworks all the MMU handling to introduce the abstraction of the
MMU context. A context can be shared across different GPU cores, as long as
they have compatible MMU implementations, which is the case for all systems
with Vivante GPUs seen in the wild.
As MMUv1 is not able to change pagetables on the fly, without a
"stop the world" operation, which stops GPU, changes pagetables via CPU
interaction, restarts GPU, the implementation introduces a shared context on
MMUv1, which is returned whenever there is a request for a new context.
This patch assigns a MMU context to each GPU, so on MMUv2 systems there is
still one set of pagetables per GPU, but due to the shared context MMUv1
systems see a change in behavior as now a single pagetable set is used
across all GPU cores.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Guido Günther <agx@sigxcpu.org>
2019-07-06 01:17:24 +08:00
|
|
|
struct etnaviv_iommu_global *mmu_global;
|
2019-07-06 01:17:22 +08:00
|
|
|
|
2015-12-04 01:21:29 +08:00
|
|
|
/* list of GEM objects: */
|
|
|
|
struct mutex gem_lock;
|
|
|
|
struct list_head gem_list;
|
|
|
|
};
|
|
|
|
|
|
|
|
int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
|
|
|
|
struct drm_file *file);
|
|
|
|
|
|
|
|
int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset);
|
|
|
|
struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj);
|
2020-11-03 17:30:11 +08:00
|
|
|
int etnaviv_gem_prime_vmap(struct drm_gem_object *obj, struct dma_buf_map *map);
|
2015-12-04 01:21:29 +08:00
|
|
|
struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
|
|
|
|
struct dma_buf_attachment *attach, struct sg_table *sg);
|
|
|
|
int etnaviv_gem_prime_pin(struct drm_gem_object *obj);
|
|
|
|
void etnaviv_gem_prime_unpin(struct drm_gem_object *obj);
|
2016-01-27 01:10:32 +08:00
|
|
|
void *etnaviv_gem_vmap(struct drm_gem_object *obj);
|
2015-12-04 01:21:29 +08:00
|
|
|
int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op,
|
2017-11-06 20:28:52 +08:00
|
|
|
struct drm_etnaviv_timespec *timeout);
|
2015-12-04 01:21:29 +08:00
|
|
|
int etnaviv_gem_cpu_fini(struct drm_gem_object *obj);
|
|
|
|
void etnaviv_gem_free_object(struct drm_gem_object *obj);
|
|
|
|
int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file,
|
|
|
|
u32 size, u32 flags, u32 *handle);
|
|
|
|
int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file,
|
|
|
|
uintptr_t ptr, u32 size, u32 flags, u32 *handle);
|
|
|
|
u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu);
|
2016-08-20 05:53:59 +08:00
|
|
|
u16 etnaviv_buffer_config_mmuv2(struct etnaviv_gpu *gpu, u32 mtlb_addr, u32 safe_addr);
|
drm/etnaviv: rework MMU handling
This reworks the MMU handling to make it possible to have multiple MMU contexts.
A context is basically one instance of GPU page tables. Currently we have one
set of page tables per GPU, which isn't all that clever, as it has the
following two consequences:
1. All GPU clients (aka processes) are sharing the same pagetables, which means
there is no isolation between clients, but only between GPU assigned memory
spaces and the rest of the system. Better than nothing, but also not great.
2. Clients operating on the same set of buffers with different etnaviv GPU
cores, e.g. a workload using both the 2D and 3D GPU, need to map the used
buffers into the pagetable sets of each used GPU.
This patch reworks all the MMU handling to introduce the abstraction of the
MMU context. A context can be shared across different GPU cores, as long as
they have compatible MMU implementations, which is the case for all systems
with Vivante GPUs seen in the wild.
As MMUv1 is not able to change pagetables on the fly, without a
"stop the world" operation, which stops GPU, changes pagetables via CPU
interaction, restarts GPU, the implementation introduces a shared context on
MMUv1, which is returned whenever there is a request for a new context.
This patch assigns a MMU context to each GPU, so on MMUv2 systems there is
still one set of pagetables per GPU, but due to the shared context MMUv1
systems see a change in behavior as now a single pagetable set is used
across all GPU cores.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Guido Günther <agx@sigxcpu.org>
2019-07-06 01:17:24 +08:00
|
|
|
u16 etnaviv_buffer_config_pta(struct etnaviv_gpu *gpu, unsigned short id);
|
2015-12-04 01:21:29 +08:00
|
|
|
void etnaviv_buffer_end(struct etnaviv_gpu *gpu);
|
2017-09-24 21:15:28 +08:00
|
|
|
void etnaviv_sync_point_queue(struct etnaviv_gpu *gpu, unsigned int event);
|
2017-11-24 22:16:58 +08:00
|
|
|
void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state,
|
2019-07-06 01:17:27 +08:00
|
|
|
struct etnaviv_iommu_context *mmu,
|
2017-11-24 22:16:58 +08:00
|
|
|
unsigned int event, struct etnaviv_cmdbuf *cmdbuf);
|
2015-12-04 01:21:29 +08:00
|
|
|
void etnaviv_validate_init(void);
|
|
|
|
bool etnaviv_cmd_validate_one(struct etnaviv_gpu *gpu,
|
|
|
|
u32 *stream, unsigned int size,
|
|
|
|
struct drm_etnaviv_gem_submit_reloc *relocs, unsigned int reloc_size);
|
|
|
|
|
|
|
|
#ifdef CONFIG_DEBUG_FS
|
|
|
|
void etnaviv_gem_describe_objects(struct etnaviv_drm_private *priv,
|
|
|
|
struct seq_file *m);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
|
|
|
|
#define VERB(fmt, ...) if (0) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the storage size of a structure with a variable length array.
|
|
|
|
* The array is nelem elements of elem_size, where the base structure
|
|
|
|
* is defined by base. If the size overflows size_t, return zero.
|
|
|
|
*/
|
|
|
|
static inline size_t size_vstruct(size_t nelem, size_t elem_size, size_t base)
|
|
|
|
{
|
|
|
|
if (elem_size && nelem > (SIZE_MAX - base) / elem_size)
|
|
|
|
return 0;
|
|
|
|
return base + nelem * elem_size;
|
|
|
|
}
|
|
|
|
|
2018-02-20 17:22:22 +08:00
|
|
|
/*
|
|
|
|
* Etnaviv timeouts are specified wrt CLOCK_MONOTONIC, not jiffies.
|
|
|
|
* We need to calculate the timeout in terms of number of jiffies
|
|
|
|
* between the specified timeout and the current CLOCK_MONOTONIC time.
|
|
|
|
*/
|
2015-12-04 01:21:29 +08:00
|
|
|
static inline unsigned long etnaviv_timeout_to_jiffies(
|
2017-11-06 20:28:52 +08:00
|
|
|
const struct drm_etnaviv_timespec *timeout)
|
2015-12-04 01:21:29 +08:00
|
|
|
{
|
2017-11-06 20:28:52 +08:00
|
|
|
struct timespec64 ts, to = {
|
|
|
|
.tv_sec = timeout->tv_sec,
|
|
|
|
.tv_nsec = timeout->tv_nsec,
|
|
|
|
};
|
2018-02-20 17:22:22 +08:00
|
|
|
|
|
|
|
ktime_get_ts64(&ts);
|
|
|
|
|
|
|
|
/* timeouts before "now" have already expired */
|
|
|
|
if (timespec64_compare(&to, &ts) <= 0)
|
|
|
|
return 0;
|
2015-12-04 01:21:29 +08:00
|
|
|
|
2018-02-20 17:22:22 +08:00
|
|
|
ts = timespec64_sub(to, ts);
|
2015-12-04 01:21:29 +08:00
|
|
|
|
2018-02-20 17:22:22 +08:00
|
|
|
return timespec64_to_jiffies(&ts);
|
2015-12-04 01:21:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* __ETNAVIV_DRV_H__ */
|