/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2021 MediaTek Inc. */ #ifndef __MTK_APU_MDW_H__ #define __MTK_APU_MDW_H__ #include #include #include #include #include #include #include #include #include #include #include #include #include #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 #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