
From: Konstantin Meskhidze <konstantin.meskhidze@huawei.com> hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC5EHB ----------------------------------------- Add xsched_ctx_init_xse() implementation: - Add 2 atomics kicks_pending_ctx_cnt and kicks_submited members to - xsched_entity structure. - Add GET_VS_TASK_TYPE macro helper. - Add xsched_xse_set_class() and bind_ctx_to_xcu() stubs. Add bind_ctx_to_xcu() implementation: - Add ctx_revmap hash table to save XCUs' history. - Add XCU_HASH_ORDER to set hashtable order. - Add additional data structure ctx_devid_revmap_data to xcu_group that is used to save XCU history in hashtable by devid. Signed-off-by: Konstantin Meskhidze <konstantin.meskhidze@huawei.com> Signed-off-by: Hui Tang <tanghui20@.huawei.com> --- include/linux/xcu_group.h | 11 +++ include/linux/xsched.h | 15 ++++- kernel/xsched/core.c | 138 +++++++++++++++++++++++++++++++++++++- 3 files changed, 162 insertions(+), 2 deletions(-) diff --git a/include/linux/xcu_group.h b/include/linux/xcu_group.h index fc4f23fce726..a2ecfbe87dc8 100644 --- a/include/linux/xcu_group.h +++ b/include/linux/xcu_group.h @@ -22,6 +22,17 @@ enum xcu_version { XCU_HW_V2 }; +/** + * @group: value for this entry. + * @hash_node: hash node list. + * @devId: device id to bind with ctx. + */ +struct ctx_devid_revmap_data { + unsigned int devId; + struct xcu_group *group; + struct hlist_node hash_node; +}; + struct xcu_op_handler_params { int fd; struct xcu_group *group; diff --git a/include/linux/xsched.h b/include/linux/xsched.h index 902f4a4fba34..465b61b07fd6 100644 --- a/include/linux/xsched.h +++ b/include/linux/xsched.h @@ -2,6 +2,8 @@ #ifndef __LINUX_XSCHED_H__ #define __LINUX_XSCHED_H__ +#include <linux/hash.h> +#include <linux/hashtable.h> #include <linux/xcu_group.h> #include <linux/kref.h> #include <linux/vstream.h> @@ -51,6 +53,12 @@ #define __XSCHED_TRACE(fmt, ...) #endif +#define XCU_HASH_ORDER 6 + +#define __GET_VS_TASK_TYPE(t) ((t)&0xFF) + +#define GET_VS_TASK_TYPE(vs_ptr) __GET_VS_TASK_TYPE((vs_ptr)->task_type) + enum xcu_state { XCU_INACTIVE, XCU_IDLE, @@ -98,6 +106,12 @@ struct xsched_entity { pid_t owner_pid; pid_t tgid; + /* Amount of pending kicks currently sitting on this context. */ + atomic_t kicks_pending_ctx_cnt; + + /* Amount of submitted kicks context, used for resched decision. */ + atomic_t kicks_submited; + /* File descriptor coming from an associated context * used for identifying a given xsched entity in * info and error prints. @@ -156,7 +170,6 @@ static inline struct xsched_context *find_ctx_by_tgid(pid_t tgid) return ret; } - static inline void xsched_init_vsm(struct vstream_metadata *vsm, struct vstream_info *vs, vstream_args_t *arg) diff --git a/kernel/xsched/core.c b/kernel/xsched/core.c index 8e531297d4c5..3ae3c78d8222 100644 --- a/kernel/xsched/core.c +++ b/kernel/xsched/core.c @@ -36,6 +36,9 @@ struct xsched_cu *xsched_cu_mgr[XSCHED_NR_CUS]; struct list_head xsched_ctx_list; DEFINE_MUTEX(xsched_ctx_list_mutex); +static DEFINE_MUTEX(revmap_mutex); +static DEFINE_HASHTABLE(ctx_revmap, XCU_HASH_ORDER); + /* Frees a given vstream and also frees and dequeues it's context * if a given vstream is the last and only vstream attached to it's * corresponding context object. @@ -64,6 +67,97 @@ void xsched_free_task(struct kref *kref) kfree(ctx); } +int bind_ctx_to_xcu(vstream_info_t *vstream_info, struct xsched_context *ctx) +{ + struct ctx_devid_revmap_data *revmap_data; + int target_chan_id = 0; + + /* Find XCU history. */ + hash_for_each_possible(ctx_revmap, revmap_data, hash_node, + (unsigned long)ctx->devId) { + if (revmap_data && revmap_data->group) { + /* Bind ctx to group xcu.*/ + ctx->xse.xcu = revmap_data->group->xcu; + return 0; + } + } + + revmap_data = kzalloc(sizeof(struct ctx_devid_revmap_data), GFP_KERNEL); + + if (revmap_data == NULL) { + XSCHED_ERR("Revmap_data is NULL @ %s\n", __func__); + return -1; + } + + /* Find a real XCU group and if it doesn't exist then try + * to find or allocate a XCU_TYPE_NPU group. + */ + revmap_data->group = + xcu_group_find_noalloc(xcu_group_root, XCU_TYPE_NPU); + target_chan_id = vstream_info->channel_id; + + if (revmap_data->group == NULL) { + target_chan_id = 0; + + XSCHED_INFO( + "Failed to find an XCU group for a real device @ %s\n", + __func__); + XSCHED_INFO("Creating a test QEMU XCU group"); + + revmap_data->group = + xcu_group_find_noalloc(xcu_group_root, XCU_TYPE_NPU); + + /* If XCU_TYPE_NPU device creation failed then something + * went very wrong and we need to return an error. + */ + if (revmap_data->group == NULL) { + XSCHED_ERR( + "Failed to find or create a QEMU test XCU group @ %s\n", + __func__); + return -1; + } + } + + /* Find a device group. */ + revmap_data->group = + xcu_group_find_noalloc(revmap_data->group, ctx->devId); + if (revmap_data->group == NULL) { + XSCHED_ERR( + "Failed to find a device group for dev_id 0x%X @ %s\n", + ctx->devId, __func__); + return -1; + } + + XSCHED_INFO("Found a dev group 0x%X @ %s\n", revmap_data->group->id, + __func__); + + /* Find a channel group. */ + revmap_data->group = + xcu_group_find_noalloc(revmap_data->group, target_chan_id); + if (revmap_data->group == NULL) { + XSCHED_ERR( + "Failed to find a channel group for dev_id 0x%X and chan_id %d @ %s\n", + ctx->devId, target_chan_id, __func__); + return -1; + } + + XSCHED_INFO("Found a channel group 0x%X with XCU %p @ %s\n", + revmap_data->group->id, revmap_data->group->xcu, __func__); + + revmap_data->devId = vstream_info->devId; + + /* Bind ctx to an XCU from channel group. */ + ctx->xse.xcu = revmap_data->group->xcu; + vstream_info->xcu = ctx->xse.xcu; + + XSCHED_INFO("Bound an XCU %p @ %s\n", ctx->xse.xcu, __func__); + + revmap_data->devId = vstream_info->devId; + hash_add(ctx_revmap, &revmap_data->hash_node, + (unsigned long)ctx->devId); + + return 0; +} int bind_vstream_to_xcu(vstream_info_t *vstream_info) { @@ -123,11 +217,53 @@ struct xsched_cu *xcu_find(__u32 *type, __u32 devId, __u32 channel_id) return group->xcu; } -int xsched_ctx_init_xse(struct xsched_context *ctx, struct vstream_info *vs) +int xsched_xse_set_class(struct xsched_entity *xse) { return 0; } +int xsched_ctx_init_xse(struct xsched_context *ctx, struct vstream_info *vs) +{ + int err = 0; + struct xsched_entity *xse = &ctx->xse; + + XSCHED_CALL_STUB(); + + atomic_set(&xse->kicks_pending_ctx_cnt, 0); + atomic_set(&xse->kicks_submited, 0); + + xse->fd = ctx->fd; + xse->tgid = ctx->tgid; + + err = bind_ctx_to_xcu(vs, ctx); + if (err) { + XSCHED_ERR( + "Couldn't find valid xcu for vstream %u dev_id %u @ %s\n", + vs->id, vs->devId, __func__); + err = -EINVAL; + goto out_err; + } + + xse->ctx = ctx; + + if (vs->xcu != NULL) + xse->xcu = vs->xcu; + + err = xsched_xse_set_class(xse); + if (err) { + XSCHED_ERR("Failed to set xse class @ %s\n", __func__); + goto out_err; + } + + WRITE_ONCE(xse->on_rq, false); + + spin_lock_init(&xse->xse_lock); +out_err: + XSCHED_EXIT_STUB(); + + return err; +} + static int xsched_schedule(void *input_xcu) { return 0; -- 2.34.1