From: Alexander Pavlenko <pavlenko.alexander@huawei.com> hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8422 ---------------------------------------- This commit enforces a strict teardown order when releasing memory associated with an XPU device: the device memory (dmem) region must first be unregistered from the xsched subsystem before the underlying physical memory is deallocated. Signed-off-by: Alexander Pavlenko <pavlenko.alexander@huawei.com> Signed-off-by: Liu Kai <liukai284@huawei.com> --- include/linux/xsched.h | 3 +++ include/uapi/linux/xcu_vstream.h | 1 + kernel/xsched/dmem.c | 27 +++++++++++++++++++++++++++ kernel/xsched/vstream.c | 19 +++++++++++++++++++ 4 files changed, 50 insertions(+) diff --git a/include/linux/xsched.h b/include/linux/xsched.h index baf90237dc14..8cd1295fbefb 100644 --- a/include/linux/xsched.h +++ b/include/linux/xsched.h @@ -482,9 +482,12 @@ void xsched_quota_refill(struct work_struct *work); /* Dmem interface */ int xsched_dmem_init(void); int xsched_dmem_alloc(struct xsched_context *ctx, struct vstream_args *args); +int xsched_dmem_free(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; } +static inline int xsched_dmem_free( + 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 d076498e75af..14552fae2159 100644 --- a/include/uapi/linux/xcu_vstream.h +++ b/include/uapi/linux/xcu_vstream.h @@ -23,6 +23,7 @@ typedef enum VSTREAM_COMMAND { VSTREAM_FREE, VSTREAM_KICK, VSTREAM_ALLOC_HBM, + VSTREAM_HBM_FREE, MAX_COMMAND } vstream_command_t; diff --git a/kernel/xsched/dmem.c b/kernel/xsched/dmem.c index c600e3df2821..27d55a8aab0a 100644 --- a/kernel/xsched/dmem.c +++ b/kernel/xsched/dmem.c @@ -106,3 +106,30 @@ int xsched_dmem_alloc(struct xsched_context *ctx, struct vstream_args *args) args->vh_args.pool_id = ULLONG_MAX; return ret; } + +int xsched_dmem_free(struct xsched_context *ctx, struct vstream_args *args) +{ + struct xsched_dmem_pool *pool, *target = NULL; + + spin_lock(&ctx->ctx_lock); + list_for_each_entry(pool, &ctx->pool_list, pool_node) { + if (pool->id == args->vh_args.pool_id) { + list_del(&pool->pool_node); + target = pool; + break; + } + } + spin_unlock(&ctx->ctx_lock); + + if (!target) { + XSCHED_ERR("pool with id %llu is not found\n", args->vh_args.pool_id); + return -EINVAL; + } + + XSCHED_DEBUG("uncharged %llu bytes for pool = %p with id %llu\n", + args->vh_args.size, target, target->id); + dmem_cgroup_uncharge(target->pool, args->vh_args.size); + kfree(target); + + return 0; +} diff --git a/kernel/xsched/vstream.c b/kernel/xsched/vstream.c index 5d052a33f8e3..7b769a2e2545 100644 --- a/kernel/xsched/vstream.c +++ b/kernel/xsched/vstream.c @@ -639,6 +639,24 @@ static int vstream_hbm_alloc(struct vstream_args *arg) return xsched_dmem_alloc(ctx, arg); } +static int vstream_hbm_free(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 free"); + return -EINVAL; + } + + return xsched_dmem_free(ctx, arg); +} + /* * vstream_manage_cmd table */ @@ -647,6 +665,7 @@ static vstream_manage_t(*vstream_command_table[MAX_COMMAND + 1]) = { vstream_free, // VSTREAM_FREE vstream_kick, // VSTREAM_KICK vstream_hbm_alloc, // VSTREAM_HBM_ALLOC + vstream_hbm_free, // VSTREAM_HBM_FREE NULL // MAX_COMMAND }; -- 2.34.1