324 lines
7.6 KiB
C
324 lines
7.6 KiB
C
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||
|
|
/*
|
||
|
|
* Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
|
||
|
|
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
||
|
|
*/
|
||
|
|
|
||
|
|
#ifndef __HGSL_H_
|
||
|
|
#define __HGSL_H_
|
||
|
|
|
||
|
|
#include <linux/types.h>
|
||
|
|
#include <linux/cdev.h>
|
||
|
|
#include <linux/dma-buf.h>
|
||
|
|
#include <linux/spinlock.h>
|
||
|
|
#include <linux/sync_file.h>
|
||
|
|
#include "hgsl_hyp.h"
|
||
|
|
#include "hgsl_memory.h"
|
||
|
|
#include "hgsl_tcsr.h"
|
||
|
|
|
||
|
|
#define HGSL_TIMELINE_NAME_LEN 64
|
||
|
|
|
||
|
|
#define HGSL_ISYNC_32BITS_TIMELINE 0
|
||
|
|
#define HGSL_ISYNC_64BITS_TIMELINE 1
|
||
|
|
|
||
|
|
/* Support upto 3 GVMs: 3 DBQs(Low/Medium/High priority) per GVM */
|
||
|
|
#define MAX_DB_QUEUE 9
|
||
|
|
#define HGSL_TCSR_NUM 4
|
||
|
|
|
||
|
|
#define HGSL_CONTEXT_NUM 256
|
||
|
|
|
||
|
|
#define HGSL_IOCTL_FUNC(_cmd, _func) \
|
||
|
|
[_IOC_NR((_cmd))] = \
|
||
|
|
{ .cmd = (_cmd), .func = (_func) }
|
||
|
|
|
||
|
|
struct qcom_hgsl;
|
||
|
|
struct hgsl_hsync_timeline;
|
||
|
|
|
||
|
|
struct hgsl_ioctl {
|
||
|
|
unsigned int cmd;
|
||
|
|
int (*func)(struct file *filep, unsigned long arg);
|
||
|
|
};
|
||
|
|
|
||
|
|
#pragma pack(push, 4)
|
||
|
|
struct shadow_ts {
|
||
|
|
unsigned int sop;
|
||
|
|
unsigned int unused1;
|
||
|
|
unsigned int eop;
|
||
|
|
unsigned int unused2;
|
||
|
|
unsigned int reserved[6];
|
||
|
|
};
|
||
|
|
#pragma pack(pop)
|
||
|
|
|
||
|
|
struct reg {
|
||
|
|
unsigned long paddr;
|
||
|
|
unsigned long size;
|
||
|
|
void __iomem *vaddr;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct hw_version {
|
||
|
|
unsigned int version;
|
||
|
|
unsigned int release;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct db_buffer {
|
||
|
|
int32_t dwords;
|
||
|
|
void *vaddr;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct dbq_ibdesc_priv {
|
||
|
|
bool buf_inuse;
|
||
|
|
uint32_t context_id;
|
||
|
|
uint32_t timestamp;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct doorbell_queue {
|
||
|
|
struct dma_buf *dma;
|
||
|
|
struct dma_buf_map map;
|
||
|
|
void *vbase;
|
||
|
|
uint64_t gmuaddr;
|
||
|
|
struct db_buffer data;
|
||
|
|
uint32_t state;
|
||
|
|
int tcsr_idx;
|
||
|
|
uint32_t dbq_idx;
|
||
|
|
struct dbq_ibdesc_priv ibdesc_priv;
|
||
|
|
uint32_t ibdesc_max_size;
|
||
|
|
struct mutex lock;
|
||
|
|
atomic_t seq_num;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct doorbell_context_queue {
|
||
|
|
struct hgsl_mem_node *queue_mem;
|
||
|
|
struct dma_buf_map map;
|
||
|
|
uint32_t db_signal;
|
||
|
|
uint32_t seq_num;
|
||
|
|
void *queue_header;
|
||
|
|
void *queue_body;
|
||
|
|
void *indirect_ibs;
|
||
|
|
uint32_t queue_header_gmuaddr;
|
||
|
|
uint32_t queue_body_gmuaddr;
|
||
|
|
uint32_t indirect_ibs_gmuaddr;
|
||
|
|
uint32_t queue_size;
|
||
|
|
int irq_idx;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct qcom_hgsl {
|
||
|
|
struct device *dev;
|
||
|
|
|
||
|
|
/* character device info */
|
||
|
|
struct cdev cdev;
|
||
|
|
dev_t device_no;
|
||
|
|
struct class *driver_class;
|
||
|
|
struct device *class_dev;
|
||
|
|
|
||
|
|
/* registers mapping */
|
||
|
|
struct reg reg_ver;
|
||
|
|
struct reg reg_dbidx;
|
||
|
|
|
||
|
|
struct doorbell_queue dbq[MAX_DB_QUEUE];
|
||
|
|
struct hgsl_dbq_info dbq_info[MAX_DB_QUEUE];
|
||
|
|
|
||
|
|
/* Could disable db and use isync only */
|
||
|
|
bool db_off;
|
||
|
|
|
||
|
|
/* global doorbell tcsr */
|
||
|
|
struct hgsl_tcsr *tcsr[HGSL_TCSR_NUM][HGSL_TCSR_ROLE_MAX];
|
||
|
|
int tcsr_idx;
|
||
|
|
struct hgsl_context **contexts;
|
||
|
|
rwlock_t ctxt_lock;
|
||
|
|
|
||
|
|
struct list_head active_wait_list;
|
||
|
|
spinlock_t active_wait_lock;
|
||
|
|
|
||
|
|
struct workqueue_struct *wq;
|
||
|
|
struct work_struct ts_retire_work;
|
||
|
|
|
||
|
|
struct hw_version *ver;
|
||
|
|
struct hgsl_hyp_priv_t global_hyp;
|
||
|
|
bool global_hyp_inited;
|
||
|
|
struct mutex mutex;
|
||
|
|
struct list_head active_list;
|
||
|
|
struct list_head release_list;
|
||
|
|
struct workqueue_struct *release_wq;
|
||
|
|
struct work_struct release_work;
|
||
|
|
struct idr isync_timeline_idr;
|
||
|
|
spinlock_t isync_timeline_lock;
|
||
|
|
atomic64_t total_mem_size;
|
||
|
|
bool default_iocoherency;
|
||
|
|
|
||
|
|
/* Debug nodes */
|
||
|
|
struct kobject sysfs;
|
||
|
|
struct kobject *clients_sysfs;
|
||
|
|
struct dentry *debugfs;
|
||
|
|
struct dentry *clients_debugfs;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* HGSL context define
|
||
|
|
**/
|
||
|
|
struct hgsl_context {
|
||
|
|
struct hgsl_priv *priv;
|
||
|
|
struct dma_buf_map map;
|
||
|
|
uint32_t context_id;
|
||
|
|
uint32_t devhandle;
|
||
|
|
uint32_t flags;
|
||
|
|
struct shadow_ts *shadow_ts;
|
||
|
|
wait_queue_head_t wait_q;
|
||
|
|
pid_t pid;
|
||
|
|
bool dbq_assigned;
|
||
|
|
uint32_t dbq_info;
|
||
|
|
struct doorbell_queue *dbq;
|
||
|
|
struct hgsl_mem_node *shadow_ts_node;
|
||
|
|
uint32_t shadow_ts_flags;
|
||
|
|
bool is_fe_shadow;
|
||
|
|
bool in_destroy;
|
||
|
|
bool destroyed;
|
||
|
|
struct kref kref;
|
||
|
|
|
||
|
|
uint32_t last_ts;
|
||
|
|
struct hgsl_hsync_timeline *timeline;
|
||
|
|
uint32_t queued_ts;
|
||
|
|
bool is_killed;
|
||
|
|
int tcsr_idx;
|
||
|
|
struct mutex lock;
|
||
|
|
struct doorbell_context_queue *dbcq;
|
||
|
|
uint32_t dbcq_export_id;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct hgsl_priv {
|
||
|
|
struct qcom_hgsl *dev;
|
||
|
|
pid_t pid;
|
||
|
|
struct list_head node;
|
||
|
|
struct hgsl_hyp_priv_t hyp_priv;
|
||
|
|
struct mutex lock;
|
||
|
|
struct rb_root mem_mapped;
|
||
|
|
struct rb_root mem_allocated;
|
||
|
|
int open_count;
|
||
|
|
|
||
|
|
atomic64_t total_mem_size;
|
||
|
|
|
||
|
|
/* sysfs stuff */
|
||
|
|
struct kobject kobj;
|
||
|
|
struct kobject sysfs_client;
|
||
|
|
struct kobject sysfs_mem_size;
|
||
|
|
struct dentry *debugfs_client;
|
||
|
|
struct dentry *debugfs_mem;
|
||
|
|
struct dentry *debugfs_memtype;
|
||
|
|
};
|
||
|
|
|
||
|
|
|
||
|
|
static inline bool hgsl_ts32_ge(uint32_t a, uint32_t b)
|
||
|
|
{
|
||
|
|
static const uint32_t TIMESTAMP_WINDOW = 0x80000000;
|
||
|
|
|
||
|
|
return (a - b) < TIMESTAMP_WINDOW;
|
||
|
|
}
|
||
|
|
|
||
|
|
static inline bool hgsl_ts64_ge(uint64_t a, uint64_t b)
|
||
|
|
{
|
||
|
|
static const uint64_t TIMESTAMP_WINDOW = 0x8000000000000000LL;
|
||
|
|
|
||
|
|
return (a - b) < TIMESTAMP_WINDOW;
|
||
|
|
}
|
||
|
|
|
||
|
|
static inline bool hgsl_ts_ge(uint64_t a, uint64_t b, bool is64)
|
||
|
|
{
|
||
|
|
if (is64)
|
||
|
|
return hgsl_ts64_ge(a, b);
|
||
|
|
else
|
||
|
|
return hgsl_ts32_ge((uint32_t)a, (uint32_t)b);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* struct hgsl_hsync_timeline - A sync timeline attached under each hgsl context
|
||
|
|
* @kref: Refcount to keep the struct alive
|
||
|
|
* @name: String to describe this timeline
|
||
|
|
* @fence_context: Used by the fence driver to identify fences belonging to
|
||
|
|
* this context
|
||
|
|
* @child_list_head: List head for all fences on this timeline
|
||
|
|
* @lock: Spinlock to protect this timeline
|
||
|
|
* @last_ts: Last timestamp when signaling fences
|
||
|
|
*/
|
||
|
|
struct hgsl_hsync_timeline {
|
||
|
|
struct kref kref;
|
||
|
|
struct hgsl_context *context;
|
||
|
|
|
||
|
|
char name[HGSL_TIMELINE_NAME_LEN];
|
||
|
|
u64 fence_context;
|
||
|
|
|
||
|
|
spinlock_t lock;
|
||
|
|
struct list_head fence_list;
|
||
|
|
unsigned int last_ts;
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* struct hgsl_hsync_fence - A struct containing a fence and other data
|
||
|
|
* associated with it
|
||
|
|
* @fence: The fence struct
|
||
|
|
* @sync_file: Pointer to the sync file
|
||
|
|
* @parent: Pointer to the hgsl sync timeline this fence is on
|
||
|
|
* @child_list: List of fences on the same timeline
|
||
|
|
* @context_id: hgsl context id
|
||
|
|
* @ts: Context timestamp that this fence is associated with
|
||
|
|
*/
|
||
|
|
struct hgsl_hsync_fence {
|
||
|
|
struct dma_fence fence;
|
||
|
|
struct sync_file *sync_file;
|
||
|
|
struct hgsl_hsync_timeline *timeline;
|
||
|
|
struct list_head child_list;
|
||
|
|
u32 context_id;
|
||
|
|
unsigned int ts;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct hgsl_isync_timeline {
|
||
|
|
struct kref kref;
|
||
|
|
struct list_head free_list;
|
||
|
|
char name[HGSL_TIMELINE_NAME_LEN];
|
||
|
|
int id;
|
||
|
|
struct hgsl_priv *priv;
|
||
|
|
struct list_head fence_list;
|
||
|
|
u64 context;
|
||
|
|
spinlock_t lock;
|
||
|
|
u64 last_ts;
|
||
|
|
u32 flags;
|
||
|
|
bool is64bits;
|
||
|
|
};
|
||
|
|
|
||
|
|
struct hgsl_isync_fence {
|
||
|
|
struct dma_fence fence;
|
||
|
|
struct list_head free_list; /* For free in batch */
|
||
|
|
struct hgsl_isync_timeline *timeline;
|
||
|
|
struct list_head child_list;
|
||
|
|
u64 ts;
|
||
|
|
};
|
||
|
|
|
||
|
|
/* Fence for commands. */
|
||
|
|
struct hgsl_hsync_fence *hgsl_hsync_fence_create(
|
||
|
|
struct hgsl_context *context,
|
||
|
|
uint32_t ts);
|
||
|
|
int hgsl_hsync_fence_create_fd(struct hgsl_context *context,
|
||
|
|
uint32_t ts);
|
||
|
|
int hgsl_hsync_timeline_create(struct hgsl_context *context);
|
||
|
|
void hgsl_hsync_timeline_signal(struct hgsl_hsync_timeline *timeline,
|
||
|
|
unsigned int ts);
|
||
|
|
void hgsl_hsync_timeline_put(struct hgsl_hsync_timeline *timeline);
|
||
|
|
void hgsl_hsync_timeline_fini(struct hgsl_context *context);
|
||
|
|
|
||
|
|
/* Fence for process sync. */
|
||
|
|
int hgsl_isync_timeline_create(struct hgsl_priv *priv,
|
||
|
|
uint32_t *timeline_id,
|
||
|
|
uint32_t flags,
|
||
|
|
uint64_t initial_ts);
|
||
|
|
int hgsl_isync_timeline_destroy(struct hgsl_priv *priv, uint32_t id);
|
||
|
|
void hgsl_isync_fini(struct hgsl_priv *priv);
|
||
|
|
int hgsl_isync_fence_create(struct hgsl_priv *priv, uint32_t timeline_id,
|
||
|
|
uint32_t ts, bool ts_is_valid, int *fence_fd);
|
||
|
|
int hgsl_isync_fence_signal(struct hgsl_priv *priv, uint32_t timeline_id,
|
||
|
|
int fence_fd);
|
||
|
|
int hgsl_isync_forward(struct hgsl_priv *priv, uint32_t timeline_id,
|
||
|
|
uint64_t ts, bool check_owner);
|
||
|
|
int hgsl_isync_query(struct hgsl_priv *priv, uint32_t timeline_id,
|
||
|
|
uint64_t *ts);
|
||
|
|
int hgsl_isync_wait_multiple(struct hgsl_priv *priv, struct hgsl_timeline_wait *param);
|
||
|
|
|
||
|
|
#endif /* __HGSL_H_ */
|