From: Alexander Pavlenko <pavlenko.alexander@huawei.com> hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8422 ---------------------------------------- This commit changes the XPU device memory allocation flow: the xsched subsystem must first successfully register the intended device memory (dmem) region before any physical memory is allocated from the XPU. Signed-off-by: Alexander Pavlenko <pavlenko.alexander@huawei.com> Signed-off-by: Liu Kai <liukai284@huawei.com> --- include/linux/xsched.h | 8 ++++++ include/uapi/linux/xcu_vstream.h | 7 +++++ kernel/xsched/dmem.c | 47 ++++++++++++++++++++++++++++++++ kernel/xsched/vstream.c | 23 ++++++++++++++++ 4 files changed, 85 insertions(+) diff --git a/include/linux/xsched.h b/include/linux/xsched.h index 8809ab22a50c..baf90237dc14 100644 --- a/include/linux/xsched.h +++ b/include/linux/xsched.h @@ -348,6 +348,10 @@ struct xsched_context { struct list_head vstream_list; struct list_head ctx_node; +#ifdef CONFIG_CGROUP_DMEM + struct list_head pool_list; +#endif + struct xsched_entity xse; spinlock_t ctx_lock; @@ -477,6 +481,10 @@ void xsched_quota_refill(struct work_struct *work); #ifdef CONFIG_CGROUP_DMEM /* Dmem interface */ int xsched_dmem_init(void); +int xsched_dmem_alloc(struct xsched_context *ctx, struct vstream_args *args); +#else +static inline int xsched_dmem_alloc( + struct xsched_context *ctx, struct vstream_args *args) { return 0; } #endif /* CONFIG_CGROUP_DMEM */ #endif /* !__LINUX_XSCHED_H__ */ diff --git a/include/uapi/linux/xcu_vstream.h b/include/uapi/linux/xcu_vstream.h index b60c0e0e15f5..d076498e75af 100644 --- a/include/uapi/linux/xcu_vstream.h +++ b/include/uapi/linux/xcu_vstream.h @@ -22,6 +22,7 @@ typedef enum VSTREAM_COMMAND { VSTREAM_ALLOC = 0, VSTREAM_FREE, VSTREAM_KICK, + VSTREAM_ALLOC_HBM, MAX_COMMAND } vstream_command_t; @@ -51,6 +52,11 @@ typedef struct vstream_kick_args { KABI_RESERVE_BYTES(2, 8); } vstream_kick_args_t; +typedef struct vstream_hbm_args { + __u64 size; + __u64 pool_id; +} vstream_hbm_args_t; + typedef struct vstream_args { __u32 channel_id; __u32 fd; @@ -64,6 +70,7 @@ typedef struct vstream_args { vstream_alloc_args_t va_args; vstream_free_args_t vf_args; vstream_kick_args_t vk_args; + vstream_hbm_args_t vh_args; }; __u32 payload_size; diff --git a/kernel/xsched/dmem.c b/kernel/xsched/dmem.c index 27e0c4b1a506..c600e3df2821 100644 --- a/kernel/xsched/dmem.c +++ b/kernel/xsched/dmem.c @@ -59,3 +59,50 @@ int xsched_dmem_init(void) } return retval; } + +int xsched_dmem_alloc(struct xsched_context *ctx, struct vstream_args *args) +{ + struct dmem_cgroup_pool_state *ret_pool, *ret_limit_pool; + struct xsched_dmem_pool *new_pool; + int ret = -EAGAIN; + static uint64_t cur_id; + struct dmem_cgroup_region *hbm_region; + + hbm_region = hbm_regions[args->dev_id]; + if (!hbm_region) { + XSCHED_ERR("Try to charge memory when region is not registered (region HBM%u)\n", + args->dev_id); + goto error_out; + } + + ret = dmem_cgroup_try_charge(hbm_region, args->vh_args.size, &ret_pool, &ret_limit_pool); + if (ret != 0) { + XSCHED_ERR("Fail to charge a new allocation to a HBM region\n"); + goto error_out; + } + + new_pool = kzalloc(sizeof(*new_pool), GFP_KERNEL); + if (!new_pool) { + XSCHED_ERR("Fail to alloc xsched dmem alloc @ %s\n", __func__); + ret = -ENOMEM; + goto error_out; + } + + new_pool->id = cur_id++; + new_pool->pool = ret_pool; + + /* protect list using ctx_lock */ + spin_lock(&ctx->ctx_lock); + list_add_tail(&new_pool->pool_node, &ctx->pool_list); + spin_unlock(&ctx->ctx_lock); + + args->vh_args.pool_id = new_pool->id; + XSCHED_DEBUG("charged %llu bytes, new_alloc = %p with id %llu", + args->vh_args.size, new_pool, new_pool->id); + + return 0; + +error_out: + args->vh_args.pool_id = ULLONG_MAX; + return ret; +} diff --git a/kernel/xsched/vstream.c b/kernel/xsched/vstream.c index d0815e33e081..5d052a33f8e3 100644 --- a/kernel/xsched/vstream.c +++ b/kernel/xsched/vstream.c @@ -158,6 +158,10 @@ static void init_xsched_ctx(struct xsched_context *ctx, INIT_LIST_HEAD(&ctx->vstream_list); INIT_LIST_HEAD(&ctx->ctx_node); +#ifdef CONFIG_CGROUP_DMEM + INIT_LIST_HEAD(&ctx->pool_list); +#endif + spin_lock_init(&ctx->ctx_lock); mutex_init(&ctx->ctx_mutex); } @@ -617,6 +621,24 @@ int vstream_kick(struct vstream_args *arg) return err; } +static int vstream_hbm_alloc(struct vstream_args *arg) +{ + struct xsched_cu *xcu_found; + struct xsched_context *ctx; + + xcu_found = xcu_find(XCU_TYPE_XPU, arg->dev_id, arg->channel_id); + if (!xcu_found) + return -EINVAL; + + ctx = ctx_find_by_tgid_and_xcu(current->tgid, xcu_found); + if (!ctx) { + XSCHED_ERR("Failed to find a context for HBM alloc"); + return -EINVAL; + } + + return xsched_dmem_alloc(ctx, arg); +} + /* * vstream_manage_cmd table */ @@ -624,6 +646,7 @@ static vstream_manage_t(*vstream_command_table[MAX_COMMAND + 1]) = { vstream_alloc, // VSTREAM_ALLOC vstream_free, // VSTREAM_FREE vstream_kick, // VSTREAM_KICK + vstream_hbm_alloc, // VSTREAM_HBM_ALLOC NULL // MAX_COMMAND }; -- 2.34.1