
From: Konstantin Meskhidze <konstantin.meskhidze@huawei.com> hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC5EHB ----------------------------------------- Add vstream_alloc() and xcu_finish() implementation. Signed-off-by: Konstantin Meskhidze <konstantin.meskhidze@huawei.com> Signed-off-by: Hui Tang <tanghui20@.huawei.com> --- drivers/xcu/xcu_group.c | 6 +++- include/linux/xsched.h | 1 + kernel/xsched/core.c | 29 +++++++++++++++ kernel/xsched/vstream.c | 80 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 114 insertions(+), 2 deletions(-) diff --git a/drivers/xcu/xcu_group.c b/drivers/xcu/xcu_group.c index b70e9e7392e3..9b513b06bbc5 100644 --- a/drivers/xcu/xcu_group.c +++ b/drivers/xcu/xcu_group.c @@ -181,7 +181,11 @@ int xcu_complete(struct xcu_op_handler_params *params) */ int xcu_finish(struct xcu_op_handler_params *params) { - return 0; + if (!params->group->opt || !params->group->opt->finish) { + XSCHED_DEBUG("No function [finish] called.\n"); + return 0; + } + return params->group->opt->finish(params); } /* This function runs a "alloc" callback for a given xcu_group diff --git a/include/linux/xsched.h b/include/linux/xsched.h index dc930d7692ba..15c67bb1ac95 100644 --- a/include/linux/xsched.h +++ b/include/linux/xsched.h @@ -157,6 +157,7 @@ static inline struct xsched_context *find_ctx_by_tgid(pid_t tgid) } int xsched_register_xcu(struct xcu_group *group); +void xsched_free_task(struct kref *kref); int xsched_ctx_init_xse(struct xsched_context *ctx, struct vstream_info *vs); int bind_ctx_to_xcu(vstream_info_t *vstream_info, struct xsched_context *ctx); int bind_vstream_to_xcu(vstream_info_t *vstream_info); diff --git a/kernel/xsched/core.c b/kernel/xsched/core.c index 52a600b945f4..98f412c1ca7b 100644 --- a/kernel/xsched/core.c +++ b/kernel/xsched/core.c @@ -36,6 +36,35 @@ struct xsched_cu *xsched_cu_mgr[XSCHED_NR_CUS]; struct list_head xsched_ctx_list; DEFINE_MUTEX(xsched_ctx_list_mutex); +/* 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. + */ +void xsched_free_task(struct kref *kref) +{ + struct xsched_context *ctx; + vstream_info_t *vs, *tmp; + + XSCHED_CALL_STUB(); + + ctx = container_of(kref, struct xsched_context, kref); + + mutex_lock(&xsched_ctx_list_mutex); + list_for_each_entry_safe(vs, tmp, &ctx->vstream_list, ctx_node) { + list_del(&vs->ctx_node); + kfree(vs->data); + kfree(vs); + } + + list_del(&ctx->ctx_node); + + mutex_unlock(&xsched_ctx_list_mutex); + XSCHED_INFO("Ctx list mutex released @ %s\n", __func__); + + kfree(ctx); +} + + int bind_vstream_to_xcu(vstream_info_t *vstream_info) { struct xsched_cu *xcu_found = NULL; diff --git a/kernel/xsched/vstream.c b/kernel/xsched/vstream.c index 73017da55ff2..30f8073593ab 100644 --- a/kernel/xsched/vstream.c +++ b/kernel/xsched/vstream.c @@ -178,6 +178,44 @@ static int vstream_add(vstream_info_t *vstream, uint32_t id) return 0; } +static int vstream_del(uint32_t vstreamid) +{ + XSCHED_INFO("Deleting vstream %u @ %s\n", vstreamid, __func__); + + if (vstreamid >= MAX_VSTREAM_NUM) { + XSCHED_ERR("VstreamId=%u out of range.\n", vstreamid); + return -EINVAL; + } + + mutex_lock(&vs_mutex); + if (vstream_array[vstreamid] != NULL) { + vstream_array[vstreamid] = NULL; + mutex_unlock(&vs_mutex); + return 0; + } + mutex_unlock(&vs_mutex); + + XSCHED_ERR("vstream_array[%u] is already empty.\n", vstreamid); + + return 0; +} + +static vstream_info_t *vstream_get(uint32_t vstreamid) +{ + vstream_info_t *vstream = NULL; + + if (vstreamid >= MAX_VSTREAM_NUM) { + XSCHED_ERR("VstreamId=%u out of range.\n", vstreamid); + return NULL; + } + + mutex_lock(&vs_mutex); + vstream = vstream_array[vstreamid]; + mutex_unlock(&vs_mutex); + + return vstream; +} + static vstream_info_t * vstream_get_by_user_stream_id(uint32_t user_streamId) { @@ -385,7 +423,47 @@ int vstream_alloc(struct vstream_args *arg) int vstream_free(struct vstream_args *arg) { - return 0; + struct xcu_op_handler_params params; + uint32_t vstreamId = arg->sq_id; + struct xsched_context *ctx = NULL; + struct xsched_entity *xse = NULL; + vstream_info_t *vstream = NULL; + int err = 0; + + XSCHED_CALL_STUB(); + + vstream = vstream_get(vstreamId); + if (!vstream) { + XSCHED_ERR("Vstream get failed, vstreamId=%u.\n", + vstreamId); + err = -ENOMEM; + goto out_err; + } + + err = vstream_del(vstream->id); + if (err) + goto out_err; + + params.group = vstream->xcu->group; + params.fd = arg->fd; + params.payload = arg->payload; + err = xcu_finish(¶ms); + + if (err) { + XSCHED_ERR( + "Failed to free vstream's SQ/CQ queues on the device sqId=%u, cqId=%u.\n", + arg->sq_id, arg->cq_id); + goto out_err; + } + + xse = &vstream->ctx->xse; + ctx = vstream->ctx; + kref_put(&ctx->kref, xsched_free_task); + +out_err: + XSCHED_EXIT_STUB(); + + return err; } int vstream_kick(struct vstream_args *arg) -- 2.34.1