411 lines
10 KiB
C
411 lines
10 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (c) 2021 MediaTek Inc.
|
|
*/
|
|
|
|
#ifndef __MTK_APU_MDW_H__
|
|
#define __MTK_APU_MDW_H__
|
|
|
|
#include <linux/miscdevice.h>
|
|
#include <linux/iopoll.h>
|
|
#include <linux/irqreturn.h>
|
|
#include <linux/dma-fence.h>
|
|
#include <linux/of_device.h>
|
|
#include <linux/dma-direction.h>
|
|
#include <linux/scatterlist.h>
|
|
#include <linux/hashtable.h>
|
|
#include <linux/types.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/dma-fence.h>
|
|
#include <linux/hashtable.h>
|
|
#include <linux/genalloc.h>
|
|
|
|
#include "apusys_core.h"
|
|
#include "apusys_device.h"
|
|
#include "mdw_ioctl.h"
|
|
#include "mdw_import.h"
|
|
|
|
#define MDW_NAME "apusys"
|
|
#define MDW_DEV_MAX (APUSYS_DEVICE_MAX)
|
|
#define MDW_DEV_TAB_DEV_MAX (16)
|
|
#define MDW_CMD_MAX (32)
|
|
#define MDW_SUBCMD_MAX (64)
|
|
#define MDW_PRIORITY_MAX (32)
|
|
#define MDW_DEFAULT_TIMEOUT_MS (30*1000)
|
|
#define MDW_BOOST_MAX (100)
|
|
#define MDW_DEFAULT_ALIGN (16)
|
|
#define MDW_UTIL_CMD_MAX_SIZE (1*1024*1024)
|
|
|
|
#define MDW_CMD_IDR_MIN (1)
|
|
#define MDW_CMD_IDR_MAX (64)
|
|
#define MDW_FENCE_MAX_RINGS (64)
|
|
|
|
#define MDW_ALIGN(x, align) ((x+align-1) & (~(align-1)))
|
|
|
|
|
|
struct mdw_fpriv;
|
|
struct mdw_device;
|
|
struct mdw_mem;
|
|
|
|
enum mdw_mem_op {
|
|
MDW_MEM_OP_NONE,
|
|
MDW_MEM_OP_INTERNAL,
|
|
MDW_MEM_OP_ALLOC,
|
|
MDW_MEM_OP_IMPORT,
|
|
};
|
|
|
|
struct mdw_mem_map {
|
|
struct dma_buf_attachment *attach;
|
|
struct sg_table *sgt;
|
|
struct kref map_ref;
|
|
struct mdw_mem *m;
|
|
void (*get)(struct mdw_mem_map *map);
|
|
void (*put)(struct mdw_mem_map *map);
|
|
};
|
|
|
|
struct mdw_mem_invoke {
|
|
struct list_head map_node; //to mdw_mem_map
|
|
struct list_head u_node; //to mpriv
|
|
struct kref ref;
|
|
struct mdw_mem *m;
|
|
struct mdw_fpriv *invoker;
|
|
void (*get)(struct mdw_mem_invoke *m_invoke);
|
|
void (*put)(struct mdw_mem_invoke *m_invoke);
|
|
};
|
|
|
|
enum mdw_queue_type {
|
|
MDW_QUEUE_COMMON,
|
|
MDW_QUEUE_NORMAL,
|
|
MDW_QUEUE_DEADLINE,
|
|
|
|
MDW_QUEUE_MAX,
|
|
};
|
|
|
|
struct mdw_mem {
|
|
/* in */
|
|
enum mdw_mem_type type;
|
|
unsigned int size;
|
|
unsigned int align;
|
|
uint64_t flags;
|
|
|
|
/* out */
|
|
void *vaddr;
|
|
struct device *mdev;
|
|
struct dma_buf *dbuf;
|
|
void *priv;
|
|
int (*bind)(void *session, struct mdw_mem *m);
|
|
void (*unbind)(void *session, struct mdw_mem *m);
|
|
|
|
/* map */
|
|
uint64_t device_va;
|
|
uint32_t dva_size;
|
|
struct mdw_mem_map *map;
|
|
|
|
/* control */
|
|
int handle;
|
|
bool belong_apu;
|
|
bool need_handle;
|
|
struct list_head maps;
|
|
struct mdw_fpriv *mpriv;
|
|
struct mdw_mem_pool *pool;
|
|
struct list_head u_item; //to mpriv
|
|
struct list_head d_node; //to mdev
|
|
struct list_head p_chunk; //to mem pool
|
|
struct mutex mtx;
|
|
void (*release)(struct mdw_mem *m);
|
|
};
|
|
|
|
/* default chunk size of memory pool */
|
|
#define MDW_MEM_POOL_CHUNK_SIZE (4*1024*1024)
|
|
|
|
struct mdw_mem_pool {
|
|
struct mdw_fpriv *mpriv;
|
|
/* pool attribute */
|
|
enum mdw_mem_type type;
|
|
uint64_t flags;
|
|
uint32_t align;
|
|
uint32_t chunk_size;
|
|
/* container and lock */
|
|
struct gen_pool *gp;
|
|
struct mutex m_mtx;
|
|
/* list of resource chunks */
|
|
struct list_head m_chunks;
|
|
/* list of allocated memories from gp */
|
|
struct list_head m_list;
|
|
/* ref count for cmd/mem */
|
|
struct kref m_ref;
|
|
void (*get)(struct mdw_mem_pool *pool);
|
|
void (*put)(struct mdw_mem_pool *pool);
|
|
};
|
|
|
|
struct mdw_dinfo {
|
|
uint32_t type;
|
|
uint32_t num;
|
|
uint8_t meta[MDW_DEV_META_SIZE];
|
|
};
|
|
|
|
enum mdw_driver_type {
|
|
MDW_DRIVER_TYPE_PLATFORM,
|
|
MDW_DRIVER_TYPE_RPMSG,
|
|
};
|
|
|
|
enum mdw_info_type {
|
|
MDW_INFO_KLOG,
|
|
MDW_INFO_ULOG,
|
|
MDW_INFO_PREEMPT_POLICY,
|
|
MDW_INFO_SCHED_POLICY,
|
|
|
|
MDW_INFO_NORMAL_TASK_DLA,
|
|
MDW_INFO_NORMAL_TASK_DSP,
|
|
MDW_INFO_NORMAL_TASK_DMA,
|
|
|
|
MDW_INFO_MIN_DTIME,
|
|
MDW_INFO_MIN_ETIME,
|
|
|
|
MDW_INFO_RESERV_TIME_REMAIN,
|
|
|
|
MDW_INFO_MAX,
|
|
};
|
|
|
|
enum mdw_info_dir {
|
|
MDW_INFO_SET,
|
|
MDW_INFO_GET
|
|
};
|
|
|
|
enum {
|
|
MDW_POWERPOLICY_DEFAULT = 0, //do nothing
|
|
MDW_POWERPOLICY_SUSTAINABLE = 1,
|
|
MDW_POWERPOLICY_PERFORMANCE = 2,
|
|
MDW_POWERPOLICY_POWERSAVING = 3,
|
|
};
|
|
|
|
enum {
|
|
MDW_APPTYPE_DEFAULT = 0,
|
|
MDW_APPTYPE_ONESHOT = 1,
|
|
MDW_APPTYPE_STREAMING = 2,
|
|
};
|
|
|
|
struct mdw_device {
|
|
enum mdw_driver_type driver_type;
|
|
union {
|
|
struct platform_device *pdev;
|
|
struct rpmsg_device *rpdev;
|
|
};
|
|
struct device *dev;
|
|
struct miscdevice *misc_dev;
|
|
|
|
/* init flag */
|
|
bool inited;
|
|
|
|
/* cores enable bitmask */
|
|
uint32_t dsp_mask;
|
|
uint32_t dla_mask;
|
|
uint32_t dma_mask;
|
|
|
|
/* mdw version */
|
|
uint32_t mdw_ver;
|
|
/* user interface version */
|
|
uint32_t uapi_ver;
|
|
|
|
/* device */
|
|
struct apusys_device *adevs[MDW_DEV_MAX];
|
|
|
|
/* device support information */
|
|
unsigned long dev_mask[BITS_TO_LONGS(MDW_DEV_MAX)];
|
|
struct mdw_dinfo *dinfos[MDW_DEV_MAX];
|
|
/* memory support information */
|
|
unsigned long mem_mask[BITS_TO_LONGS(MDW_MEM_TYPE_MAX)];
|
|
struct mdw_mem minfos[MDW_MEM_TYPE_MAX];
|
|
|
|
/* memory hlist */
|
|
struct list_head m_list;
|
|
struct mutex m_mtx;
|
|
struct mutex mctl_mtx;
|
|
|
|
/* cmd clear wq */
|
|
struct mutex c_mtx;
|
|
struct list_head d_cmds;
|
|
struct work_struct c_wk;
|
|
|
|
/* device functions */
|
|
const struct mdw_dev_func *dev_funcs;
|
|
void *dev_specific;
|
|
|
|
/* fence info */
|
|
uint64_t base_fence_ctx;
|
|
uint32_t num_fence_ctx;
|
|
unsigned long fence_ctx_mask[BITS_TO_LONGS(MDW_FENCE_MAX_RINGS)];
|
|
struct mutex f_mtx;
|
|
};
|
|
|
|
struct mdw_fpriv {
|
|
struct mdw_device *mdev;
|
|
|
|
struct list_head mems;
|
|
struct list_head invokes;
|
|
struct mutex mtx;
|
|
struct mdw_mem_pool cmd_buf_pool;
|
|
struct idr cmds;
|
|
atomic_t active_cmds;
|
|
atomic_t exec_seqno;
|
|
|
|
/* ref count for cmd/mem */
|
|
atomic_t active;
|
|
struct kref ref;
|
|
void (*get)(struct mdw_fpriv *mpriv);
|
|
void (*put)(struct mdw_fpriv *mpriv);
|
|
};
|
|
|
|
struct mdw_exec_info {
|
|
struct mdw_cmd_exec_info c;
|
|
struct mdw_subcmd_exec_info sc;
|
|
};
|
|
|
|
struct mdw_subcmd_kinfo {
|
|
struct mdw_subcmd_info *info; //c->subcmds
|
|
struct mdw_subcmd_cmdbuf *cmdbufs; //from usr
|
|
struct mdw_mem **ori_cbs; //pointer to original cmdbuf
|
|
struct mdw_subcmd_exec_info *sc_einfo;
|
|
uint64_t *kvaddrs; //pointer to duplicated buf
|
|
uint64_t *daddrs; //pointer to duplicated buf
|
|
void *priv; //mdw_ap_sc
|
|
};
|
|
|
|
struct mdw_fence {
|
|
struct dma_fence base_fence;
|
|
struct mdw_device *mdev;
|
|
spinlock_t lock;
|
|
char name[32];
|
|
};
|
|
|
|
struct mdw_cmd_map_invoke {
|
|
struct list_head c_node;
|
|
struct mdw_mem_map *map;
|
|
};
|
|
|
|
struct mdw_cmd {
|
|
pid_t pid;
|
|
pid_t tgid;
|
|
char comm[16];
|
|
uint64_t kid;
|
|
uint64_t uid;
|
|
uint64_t rvid;
|
|
uint32_t priority;
|
|
uint32_t hardlimit;
|
|
uint32_t softlimit;
|
|
uint32_t power_save;
|
|
uint32_t power_plcy;
|
|
uint32_t power_dtime;
|
|
uint32_t fastmem_ms;
|
|
uint32_t app_type;
|
|
uint32_t num_subcmds;
|
|
uint32_t num_links;
|
|
struct mdw_subcmd_info *subcmds; //from usr
|
|
struct mdw_subcmd_kinfo *ksubcmds;
|
|
uint32_t num_cmdbufs;
|
|
uint32_t size_cmdbufs;
|
|
struct mdw_mem *cmdbufs;
|
|
struct mdw_mem *exec_infos;
|
|
struct mdw_exec_info *einfos;
|
|
uint8_t *adj_matrix;
|
|
struct mdw_subcmd_link_v1 *links;
|
|
|
|
struct mutex mtx;
|
|
struct list_head map_invokes; //mdw_cmd_map_invoke
|
|
struct list_head d_node; //mdev->d_cmds
|
|
|
|
int id;
|
|
struct kref ref;
|
|
atomic_t is_running;
|
|
|
|
uint64_t start_ts;
|
|
uint64_t end_ts;
|
|
|
|
struct mdw_fpriv *mpriv;
|
|
void *internal_cmd;
|
|
int (*complete)(struct mdw_cmd *c, int ret);
|
|
int (*del_internal)(struct mdw_cmd *c);
|
|
|
|
struct mdw_fence *fence;
|
|
struct work_struct t_wk;
|
|
struct dma_fence *wait_fence;
|
|
};
|
|
|
|
struct mdw_dev_func {
|
|
int (*late_init)(struct mdw_device *mdev);
|
|
void (*late_deinit)(struct mdw_device *mdev);
|
|
int (*sw_init)(struct mdw_device *mdev);
|
|
void (*sw_deinit)(struct mdw_device *mdev);
|
|
int (*run_cmd)(struct mdw_fpriv *mpriv, struct mdw_cmd *c);
|
|
int (*set_power)(struct mdw_device *mdev, uint32_t type, uint32_t idx, uint32_t boost);
|
|
int (*ucmd)(struct mdw_device *mdev, uint32_t type, void *vaddr, uint32_t size);
|
|
int (*set_param)(struct mdw_device *mdev, enum mdw_info_type type, uint32_t val);
|
|
uint32_t (*get_info)(struct mdw_device *mdev, enum mdw_info_type type);
|
|
int (*register_device)(struct apusys_device *adev);
|
|
int (*unregister_device)(struct apusys_device *adev);
|
|
};
|
|
|
|
#if IS_ENABLED(CONFIG_MTK_AEE_FEATURE)
|
|
#include <aee.h>
|
|
#define _mdw_exception(key, reason, args...) \
|
|
do { \
|
|
char info[150];\
|
|
mdw_drv_err(reason, args); \
|
|
if (snprintf(info, 150, "apu_mdw:" reason, args) > 0) { \
|
|
aee_kernel_exception(info, \
|
|
"\nCRDISPATCH_KEY:%s\n", key); \
|
|
} else { \
|
|
mdw_drv_err("apu_mdw: %s snprintf fail(%d)\n", __func__, __LINE__); \
|
|
} \
|
|
} while (0)
|
|
#define mdw_exception(reason, args...) _mdw_exception("APUSYS_MIDDLEWARE", reason, ##args)
|
|
#define dma_exception(reason, args...) _mdw_exception("APUSYS_EDMA", reason, ##args)
|
|
#define aps_exception(reason, args...) _mdw_exception("APUSYS_APS", reason, ##args)
|
|
#else
|
|
#define mdw_exception(reason, args...)
|
|
#define dma_exception(reason, args...)
|
|
#define aps_exception(reason, args...)
|
|
#endif
|
|
|
|
void mdw_rv_set_func(struct mdw_device *mdev);
|
|
|
|
long mdw_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
|
|
int mdw_hs_ioctl(struct mdw_fpriv *mpriv, void *data);
|
|
int mdw_mem_ioctl(struct mdw_fpriv *mpriv, void *data);
|
|
int mdw_cmd_ioctl(struct mdw_fpriv *mpriv, void *data);
|
|
int mdw_util_ioctl(struct mdw_fpriv *mpriv, void *data);
|
|
|
|
void mdw_cmd_delete(struct mdw_cmd *c);
|
|
int mdw_cmd_invoke_map(struct mdw_cmd *c, struct mdw_mem_map *map);
|
|
void mdw_cmd_mpriv_release(struct mdw_fpriv *mpriv);
|
|
void mdw_mem_mpriv_release(struct mdw_fpriv *mpriv);
|
|
|
|
void mdw_mem_all_print(struct mdw_fpriv *mpriv);
|
|
|
|
void mdw_mem_put(struct mdw_fpriv *mpriv, struct mdw_mem *m);
|
|
struct mdw_mem *mdw_mem_get(struct mdw_fpriv *mpriv, int handle);
|
|
struct mdw_mem *mdw_mem_alloc(struct mdw_fpriv *mpriv, enum mdw_mem_type type,
|
|
uint32_t size, uint32_t align, uint64_t flags, bool need_handle);
|
|
void mdw_mem_free(struct mdw_fpriv *mpriv, struct mdw_mem *m);
|
|
long mdw_mem_set_name(struct mdw_mem *m, const char *buf);
|
|
int mdw_mem_map(struct mdw_fpriv *mpriv, struct mdw_mem *m);
|
|
int mdw_mem_unmap(struct mdw_fpriv *mpriv, struct mdw_mem *m);
|
|
int mdw_mem_flush(struct mdw_fpriv *mpriv, struct mdw_mem *m);
|
|
int mdw_mem_invalidate(struct mdw_fpriv *mpriv, struct mdw_mem *m);
|
|
int mdw_mem_init(struct mdw_device *mdev);
|
|
void mdw_mem_deinit(struct mdw_device *mdev);
|
|
|
|
int mdw_sysfs_init(struct mdw_device *mdev);
|
|
void mdw_sysfs_deinit(struct mdw_device *mdev);
|
|
|
|
int mdw_dbg_init(struct apusys_core_info *info);
|
|
void mdw_dbg_deinit(void);
|
|
|
|
int mdw_dev_init(struct mdw_device *mdev);
|
|
void mdw_dev_deinit(struct mdw_device *mdev);
|
|
void mdw_dev_session_create(struct mdw_fpriv *mpriv);
|
|
void mdw_dev_session_delete(struct mdw_fpriv *mpriv);
|
|
int mdw_dev_validation(struct mdw_fpriv *mpriv, uint32_t dtype,
|
|
struct mdw_cmd *cmd, struct apusys_cmdbuf *cbs, uint32_t num);
|
|
|
|
#endif
|