已开启
uadk: fix memory safety, BD3 stream issues and optimize ctx scheduling #128
uadk: fix memory safety, BD3 stream issues and optimize ctx scheduling #128
已开启
dorei_bin创建于 11 天前
共 16 个文件变更+2153-1
@@ -0,0 +1,78 @@
1+From 5eb5a55de2020692104cc0cb8c76499df9d63256 Mon Sep 17 00:00:00 2001
2+From: Junchong Pan <panjunchong@h-partners.com>
3+Date: Wed, 2 Sep 2026 14:16:07 +0800
4+Subject: [PATCH 23/37] uadk: fix -Wmaybe-uninitialized and -Wsign-compare
5+ warnings
6+ 
7+Initialize ret to 0 in wd_ctx_param_init() to fix -Wmaybe-uninitialized
8+warning. Change ret type from int to size_t in get_str_attr() to fix
9+-Wsign-compare warning. Move sched_uninit and set_param to the end of
10+struct wd_sched to maintain ABI compatibility.
11+ 
12+Signed-off-by: Junchong Pan <panjunchong@h-partners.com>
13+Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
14+---
15+ include/wd_alg_common.h | 4 ++--
16+ wd.c | 2 +-
17+ wd_util.c | 5 +++--
18+ 3 files changed, 6 insertions(+), 5 deletions(-)
19+ 
20+diff --git a/include/wd_alg_common.h b/include/wd_alg_common.h
21+index 05cc5c0..f0e13bb 100644
22+--- a/include/wd_alg_common.h
23++++ b/include/wd_alg_common.h
24+@@ -165,13 +165,13 @@ struct wd_sched {
25+ const char *name;
26+ int sched_policy;
27+ handle_t (*sched_init)(handle_t h_sched_ctx, void *sched_param);
28+- void (*sched_uninit)(handle_t h_sched_ctx, handle_t h_sched_key);
29+ __u32 (*pick_next_ctx)(handle_t h_sched_ctx,
30+ void *sched_key,
31+ const int sched_mode);
32+ int (*poll_policy)(handle_t h_sched_ctx, __u32 expect, __u32 *count);
33+- void (*set_param)(handle_t h_sched_ctx, void *sched_key, void *sched_param);
34+ handle_t h_sched_ctx;
35++ void (*sched_uninit)(handle_t h_sched_ctx, handle_t h_sched_key);
36++ void (*set_param)(handle_t h_sched_ctx, void *sched_key, void *sched_param);
37+ };
38+
39+ typedef int (*wd_alg_init)(struct wd_ctx_config *config, struct wd_sched *sched);
40+diff --git a/wd.c b/wd.c
41+index f973c70..1c28bb3 100644
42+--- a/wd.c
43++++ b/wd.c
44+@@ -203,7 +203,7 @@ static int get_int_attr(struct uacce_dev *dev, const char *attr, int *val)
45+ static int get_str_attr(struct uacce_dev *dev, const char *attr, char *buf,
46+ size_t buf_sz)
47+ {
48+- int ret;
49++ size_t ret;
50+ int size;
51+
52+ size = get_raw_attr(dev->dev_root, attr, buf, buf_sz);
53+diff --git a/wd_util.c b/wd_util.c
54+index 1b4c74e..bf6d380 100644
55+--- a/wd_util.c
56++++ b/wd_util.c
57+@@ -1765,7 +1765,7 @@ static int wd_env_set_ctx_nums(const char *alg_name, const char *name, const cha
58+ {
59+ char *left, *section, *start;
60+ int is_comp;
61+- int ret;
62++ int ret = 0;
63+
64+ /* COMP environment variable's format is different, mark it */
65+ is_comp = strncmp(name, "WD_COMP_CTX_NUM", sizeof("WD_COMP_CTX_NUM") - 1) ? 0 : 1;
66+@@ -1799,7 +1799,8 @@ int wd_ctx_param_init(struct wd_ctx_params *ctx_params,
67+ {
68+ const char *env_name = wd_env_name[type];
69+ const char *var_s;
70+- int i, ret;
71++ int ret = 0;
72++ int i;
73+
74+ ctx_params->bmp = numa_allocate_nodemask();
75+ if (!ctx_params->bmp) {
76+--
77+2.25.1
78+ 
@@ -0,0 +1,432 @@
1+From 090ec971cd35aac3bab33043f63cb0a1ece77da8 Mon Sep 17 00:00:00 2001
2+From: Chenghai Huang <huangchenghai2@huawei.com>
3+Date: Fri, 16 Oct 2026 17:17:36 +0800
4+Subject: [PATCH 24/37] uadk: bind sync/async ctx to same device under
5+ SCHED_POLICY_DEV
6+ 
7+Under SCHED_POLICY_DEV, allocating sync then async ctxs in two passes
8+let concurrent contention split them across devices, leaving the async
9+domain empty (async picks returned 65535, sends failed with -22).
10+ 
11+Add a DEV-only path that opens sync/async ctxs interleaved on ONE device:
12+the first ctx auto-selects via NUMA scan, its dev_path pins every later
13+ctx through preferred_dev_path, and wd_hw_alloc_ctx opens that device
14+without NUMA fallback. Other policies unchanged.
15+ 
16+Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
17+---
18+ drv/wd_drv.c | 26 +++++
19+ include/wd_alg.h | 3 +
20+ wd_util.c | 283 ++++++++++++++++++++++++++++++++++++++---------
21+ 3 files changed, 261 insertions(+), 51 deletions(-)
22+ 
23+diff --git a/drv/wd_drv.c b/drv/wd_drv.c
24+index 381cee1..c839ed4 100644
25+--- a/drv/wd_drv.c
26++++ b/drv/wd_drv.c
27+@@ -220,6 +220,32 @@ int wd_hw_alloc_ctx(char *alg_name, void *params, handle_t *ctx)
28+ goto out;
29+ }
30+
31++ /*
32++ * Preferred-device binding (SCHED_POLICY_DEV): open exactly this device
33++ * and fail strictly if unavailable, so the sync and async ctxs of one
34++ * (driver, op_type, numa) stay on the same device. No NUMA fallback.
35++ */
36++ if (ctx_params->preferred_dev_path) {
37++ for (curr = used_list; curr; curr = curr->next) {
38++ if (curr->dev && !strcmp(curr->dev->char_dev_path,
39++ ctx_params->preferred_dev_path))
40++ break;
41++ }
42++
43++ if (!curr) {
44++ ret = -WD_ENODEV;
45++ goto out;
46++ }
47++
48++ hctx = wd_request_ctx(curr->dev);
49++ if (!hctx) {
50++ ret = -WD_EBUSY;
51++ goto out;
52++ }
53++
54++ goto success;
55++ }
56++
57+ curr = used_list;
58+ while (curr) {
59+ if (curr->dev) {
60+diff --git a/include/wd_alg.h b/include/wd_alg.h
61+index b256a2f..3cc4e43 100644
62+--- a/include/wd_alg.h
63++++ b/include/wd_alg.h
64+@@ -96,6 +96,8 @@ enum alg_drv_type {
65+ * @ctx_mode: CTX_MODE_SYNC or CTX_MODE_ASYNC
66+ * @op_type: Operation type
67+ * @bmp: NUMA node bitmask (optional, NULL if not needed)
68++ * @preferred_dev_path: Preferred device char_dev_path; NULL/empty = auto-select,
69++ * non-empty = open only this device and fail strictly if unavailable
70+ */
71+ struct wd_drv_ctx_params {
72+ __u8 ctx_mode;
73+@@ -103,6 +105,7 @@ struct wd_drv_ctx_params {
74+ int numa_id;
75+ bool epoll_en;
76+ struct bitmask *bmp;
77++ const char *preferred_dev_path;
78+ };
79+
80+ /**
81+diff --git a/wd_util.c b/wd_util.c
82+index bf6d380..cc89837 100644
83+--- a/wd_util.c
84++++ b/wd_util.c
85+@@ -2614,17 +2614,17 @@ static int wd_alg_sched_instance(struct wd_sched *sched,
86+ return WD_SUCCESS;
87+ }
88+
89+-static void wd_free_ctxs_batch(struct wd_init_attrs *attrs,
90+- __u32 allocated_count)
91++static void wd_free_ctxs_batch_range(struct wd_init_attrs *attrs,
92++ __u32 start_idx, __u32 end_idx)
93+ {
94+ struct wd_ctx_config_internal *internal_config = attrs->ctx_config_internal;
95+ struct wd_alg_driver *drv;
96+ __u32 i;
97+
98+- if (!internal_config || !internal_config->ctxs || !allocated_count)
99++ if (!internal_config || !internal_config->ctxs || start_idx >= end_idx)
100+ return;
101+
102+- for (i = 0; i < allocated_count; i++) {
103++ for (i = start_idx; i < end_idx; i++) {
104+ if (!internal_config->ctxs[i].ctx)
105+ continue;
106+
107+@@ -2636,21 +2636,76 @@ static void wd_free_ctxs_batch(struct wd_init_attrs *attrs,
108+ }
109+ }
110+
111++static void wd_free_ctxs_batch(struct wd_init_attrs *attrs,
112++ __u32 allocated_count)
113++{
114++ wd_free_ctxs_batch_range(attrs, 0, allocated_count);
115++}
116++
117++static void wd_collect_numa_nodes(struct bitmask *bmp, int *numa_nodes,
118++ __u8 *numa_count)
119++{
120++ int max_node, n;
121++
122++ max_node = numa_max_node() + 1;
123++ if (max_node <= 0 || max_node > UADK_MAX_NUMA_NODES)
124++ max_node = UADK_MAX_NUMA_NODES;
125++
126++ *numa_count = 0;
127++
128++ for (n = 0; n < max_node; n++) {
129++ if (numa_bitmask_isbitset(bmp, n))
130++ numa_nodes[(*numa_count)++] = n;
131++ }
132++
133++ if (!*numa_count) {
134++ numa_nodes[0] = 0;
135++ *numa_count = 1;
136++ }
137++}
138++
139++static int wd_alloc_one_ctx(struct wd_init_attrs *attrs,
140++ struct wd_alg_driver *drv,
141++ struct wd_drv_ctx_params *dparams,
142++ __u32 *ctx_idx)
143++{
144++ struct wd_ctx_config_internal *internal_config = attrs->ctx_config_internal;
145++ handle_t ctx;
146++ int ret;
147++
148++ ret = drv->alloc_ctx(attrs->alg, dparams, &ctx);
149++ if (ret < 0)
150++ return ret;
151++
152++ if (!ctx)
153++ return -WD_EINVAL;
154++
155++ internal_config->ctxs[*ctx_idx].ctx = ctx;
156++ internal_config->ctxs[*ctx_idx].op_type = dparams->op_type;
157++ internal_config->ctxs[*ctx_idx].ctx_mode = dparams->ctx_mode;
158++ internal_config->ctxs[*ctx_idx].ctx_type = drv->calc_type;
159++ internal_config->ctxs[*ctx_idx].drv = drv;
160++ (*ctx_idx)++;
161++ return WD_SUCCESS;
162++}
163++
164+ static int wd_alloc_single_drv_ctxs(struct wd_init_attrs *attrs,
165+ struct wd_alg_driver *drv,
166+ __u8 ctx_mode, __u8 op_type,
167+ __u32 *ctx_idx)
168+ {
169+- struct wd_ctx_config_internal *internal_config = attrs->ctx_config_internal;
170+ struct wd_ctx_params *ctx_params = attrs->ctx_params;
171+- struct wd_drv_ctx_params dparams;
172++ struct wd_drv_ctx_params dparams = {0};
173+ int numa_nodes[UADK_MAX_NUMA_NODES];
174+- __u32 mode_ctx_num, numa_count = 0;
175+- __u32 numa_idx, j;
176+- int max_node, n;
177+- handle_t ctx;
178++ __u32 mode_ctx_num, numa_idx, j;
179++ __u8 numa_count;
180+ int ret;
181+
182++ dparams.ctx_mode = ctx_mode;
183++ dparams.op_type = op_type;
184++ dparams.bmp = ctx_params->bmp;
185++ dparams.epoll_en = false;
186++
187+ if (ctx_mode == CTX_MODE_SYNC)
188+ mode_ctx_num = ctx_params->ctx_set_num[op_type].sync_ctx_num;
189+ else
190+@@ -2662,46 +2717,26 @@ static int wd_alloc_single_drv_ctxs(struct wd_init_attrs *attrs,
191+ attrs->sched_type == SCHED_POLICY_SINGLE) && mode_ctx_num > 1)
192+ mode_ctx_num = 1;
193+
194+- if (drv->calc_type == UADK_ALG_HW) {
195+- max_node = numa_max_node() + 1;
196+- if (max_node <= 0 || max_node > UADK_MAX_NUMA_NODES)
197+- max_node = UADK_MAX_NUMA_NODES;
198+- for (n = 0; n < max_node; n++) {
199+- if (numa_bitmask_isbitset(ctx_params->bmp, n))
200+- numa_nodes[numa_count++] = n;
201+- }
202+- } else {
203+- numa_nodes[0] = 0;
204+- numa_count = 1;
205+- }
206+- if (!numa_count) {
207++ if (drv->calc_type != UADK_ALG_HW) {
208+ numa_nodes[0] = 0;
209+ numa_count = 1;
210++ } else {
211++ wd_collect_numa_nodes(ctx_params->bmp, numa_nodes, &numa_count);
212+ }
213+
214+ for (numa_idx = 0; numa_idx < numa_count; numa_idx++) {
215++ dparams.numa_id = numa_nodes[numa_idx];
216++
217+ for (j = 0; j < mode_ctx_num; j++) {
218+- memset(&dparams, 0, sizeof(dparams));
219+- dparams.ctx_mode = ctx_mode;
220+- dparams.op_type = op_type;
221+- dparams.numa_id = numa_nodes[numa_idx];
222+- dparams.bmp = ctx_params->bmp;
223+- dparams.epoll_en = false;
224+- ret = drv->alloc_ctx(attrs->alg, &dparams, &ctx);
225+- if (!ctx || ret < 0) {
226+- if (ret == -WD_ENODEV)
227+- break;
228++ ret = wd_alloc_one_ctx(attrs, drv, &dparams, ctx_idx);
229++ if (ret == -WD_ENODEV)
230++ break;
231++
232++ if (ret) {
233+ WD_ERR("failed to alloc ctx %u from driver %s on numa %d!\n",
234+ *ctx_idx, drv->drv_name, numa_nodes[numa_idx]);
235+ return ret;
236+ }
237+-
238+- internal_config->ctxs[*ctx_idx].ctx = ctx;
239+- internal_config->ctxs[*ctx_idx].op_type = dparams.op_type;
240+- internal_config->ctxs[*ctx_idx].ctx_mode = dparams.ctx_mode;
241+- internal_config->ctxs[*ctx_idx].ctx_type = drv->calc_type;
242+- internal_config->ctxs[*ctx_idx].drv = drv;
243+- (*ctx_idx)++;
244+ }
245+ }
246+
247+@@ -2750,6 +2785,146 @@ err_ctxs:
248+ return ret;
249+ }
250+
251++/*
252++ * SCHED_POLICY_DEV: open sync/async ctxs of (drv, op_type, numa) interleaved on
253++ * ONE device. The caller pins the device via dparams->preferred_dev_path.
254++ * Stop when both counts are met or the device is full. If both modes are
255++ * requested but only one could be opened, roll back and return -WD_ENODEV so
256++ * the caller can try the next device; partial within one mode is kept.
257++ */
258++static int wd_alloc_dev_group(struct wd_init_attrs *attrs,
259++ struct wd_alg_driver *drv,
260++ struct wd_drv_ctx_params *dparams,
261++ __u32 *ctx_idx)
262++{
263++ struct wd_ctx_nums *nums = &attrs->ctx_params->ctx_set_num[dparams->op_type];
264++ __u32 want[2] = {nums->sync_ctx_num, nums->async_ctx_num};
265++ __u8 modes[2] = {CTX_MODE_SYNC, CTX_MODE_ASYNC};
266++ __u32 group_start = *ctx_idx;
267++ __u32 done[2] = {0, 0};
268++ __u32 i;
269++ int ret;
270++
271++ while (done[0] < want[0] || done[1] < want[1]) {
272++ for (i = 0; i < 2; i++) {
273++ if (done[i] >= want[i])
274++ continue;
275++
276++ dparams->ctx_mode = modes[i];
277++ ret = wd_alloc_one_ctx(attrs, drv, dparams, ctx_idx);
278++ if (ret) {
279++ if (ret != -WD_EBUSY && ret != -WD_ENODEV)
280++ return ret;
281++ /*
282++ * Device full. If both modes were requested
283++ * but only one got ctxs, the empty domain
284++ * would cause idx 65535 at runtime. Roll back
285++ * this group so the caller tries another dev.
286++ */
287++ if (want[0] && want[1] &&
288++ (!done[0] || !done[1])) {
289++ wd_free_ctxs_batch_range(attrs, group_start, *ctx_idx);
290++ *ctx_idx = group_start;
291++ return -WD_ENODEV;
292++ }
293++ return WD_SUCCESS;
294++ }
295++ done[i]++;
296++ }
297++ }
298++ return WD_SUCCESS;
299++}
300++
301++/*
302++ * SCHED_POLICY_DEV: per (drv, op_type, numa) open sync/async on one device
303++ * (interleaved, partial allowed). Enumerates devices on each numa node and
304++ * pins each group to one device via preferred_dev_path, trying the next
305++ * device if the current one cannot hold both modes.
306++ */
307++static int wd_alloc_ctxs_batch_dev(struct wd_init_attrs *attrs, __u32 *start_idx)
308++{
309++ struct wd_ctx_config_internal *internal_config = attrs->ctx_config_internal;
310++ struct wd_ctx_params *ctx_params = attrs->ctx_params;
311++ struct uacce_dev_list *dev_list, *p;
312++ int numa_nodes[UADK_MAX_NUMA_NODES];
313++ char alg_type[CRYPTO_MAX_ALG_NAME];
314++ struct wd_drv_ctx_params dparams;
315++ __u32 ctx_idx, drv_idx, start;
316++ struct wd_alg_driver *drv;
317++ __u8 op_type, numa_count;
318++ struct wd_ctx_nums *nums;
319++ int n, ret;
320++
321++ memset(&dparams, 0, sizeof(dparams));
322++ dparams.bmp = ctx_params->bmp;
323++ dparams.epoll_en = false;
324++
325++ start = *start_idx;
326++ ctx_idx = start;
327++ for (drv_idx = 0; drv_idx < internal_config->drv_count; drv_idx++) {
328++ drv = internal_config->drv_array[drv_idx];
329++ if (!drv || !drv->alloc_ctx) {
330++ WD_ERR("failed to check driver %s alloc_ctx!\n",
331++ drv ? drv->drv_name : "unknown");
332++ ret = -WD_EINVAL;
333++ goto err_ctxs;
334++ }
335++ if (drv->calc_type != UADK_ALG_HW)
336++ continue;
337++
338++ ret = wd_get_alg_type(attrs->alg, alg_type);
339++ if (ret) {
340++ ret = -WD_EINVAL;
341++ goto err_ctxs;
342++ }
343++ if (!strcmp(alg_type, "ecc"))
344++ (void)strcpy(alg_type, "sm2");
345++ if (!strcmp(alg_type, "comp"))
346++ (void)strcpy(alg_type, "zlib");
347++
348++ dev_list = wd_get_accel_list(alg_type);
349++ if (!dev_list)
350++ continue;
351++
352++ wd_collect_numa_nodes(ctx_params->bmp, numa_nodes, &numa_count);
353++
354++ for (op_type = 0; op_type < ctx_params->op_type_num; op_type++) {
355++ nums = &ctx_params->ctx_set_num[op_type];
356++ if (!nums->sync_ctx_num && !nums->async_ctx_num)
357++ continue;
358++
359++ dparams.op_type = op_type;
360++ for (n = 0; n < numa_count; n++) {
361++ dparams.numa_id = numa_nodes[n];
362++ for (p = dev_list; p; p = p->next) {
363++ if (!p->dev || p->dev->numa_id != numa_nodes[n])
364++ continue;
365++
366++ dparams.preferred_dev_path = p->dev->char_dev_path;
367++ ret = wd_alloc_dev_group(attrs, drv,
368++ &dparams,
369++ &ctx_idx);
370++ if (!ret)
371++ break;
372++ if (ret != -WD_ENODEV)
373++ goto err_ctxs;
374++ }
375++ }
376++ }
377++ wd_free_list_accels(dev_list);
378++ dev_list = NULL;
379++ }
380++
381++ *start_idx = ctx_idx;
382++ return ctx_idx == start ? -WD_ENODEV : WD_SUCCESS;
383++
384++err_ctxs:
385++ if (dev_list)
386++ wd_free_list_accels(dev_list);
387++ wd_free_ctxs_batch(attrs, ctx_idx);
388++ return ret;
389++}
390++
391+ /**
392+ * wd_alg_ctx_uninit() - Release ctxs, scheduler, ctx_config.
393+ *
394+@@ -2881,18 +3056,24 @@ int wd_alg_ctx_init(struct wd_init_attrs *attrs)
395+ return -WD_EINVAL;
396+ }
397+
398+- /*
399+- * Ensure that contexts (ctx) with the same attributes are allocated first,
400+- * thereby maintaining queue continuity within the contexts.
401+- */
402+- ret = wd_alloc_ctxs_batch(attrs, CTX_MODE_SYNC, &ctx_idx);
403+- if (ret)
404+- return -WD_EINVAL;
405++ if (attrs->sched_type == SCHED_POLICY_DEV) {
406++ ret = wd_alloc_ctxs_batch_dev(attrs, &ctx_idx);
407++ /* DEV tolerates partial: only a truly empty result fails. */
408++ if (ret == -WD_ENODEV)
409++ return -WD_EINVAL;
410+
411+- /* wd_alloc_ctxs_batch already cleaned up via its internal err_ctxs. */
412+- ret = wd_alloc_ctxs_batch(attrs, CTX_MODE_ASYNC, &ctx_idx);
413+- if (ret)
414+- return -WD_EINVAL;
415++ if (ret)
416++ return ret;
417++ } else {
418++ ret = wd_alloc_ctxs_batch(attrs, CTX_MODE_SYNC, &ctx_idx);
419++ if (ret)
420++ return -WD_EINVAL;
421++
422++ /* wd_alloc_ctxs_batch already cleaned up via its internal err_ctxs. */
423++ ret = wd_alloc_ctxs_batch(attrs, CTX_MODE_ASYNC, &ctx_idx);
424++ if (ret)
425++ return -WD_EINVAL;
426++ }
427+
428+ /* Backfill actual allocated count */
429+ internal_config = attrs->ctx_config_internal;
430+--
431+2.25.1
432+ 
@@ -0,0 +1,143 @@
1+From 6501898995a32968f79247bba555bb8d3ffb3b56 Mon Sep 17 00:00:00 2001
2+From: Chenghai Huang <huangchenghai2@huawei.com>
3+Date: Fri, 16 Oct 2026 17:17:37 +0800
4+Subject: [PATCH 25/37] uadk: simplify SCHED_POLICY_DEV ctx alloc to
5+ non-interleaved whole-group
6+ 
7+Replace interleaved sync/async alloc with linear two-pass per device:
8+open all sync then all async; any shortfall rolls back the whole group
9+and tries the next device. Add per-op_type gap check, device capacity
10+pre-check, and dev_list NULL init.
11+ 
12+Signed-off-by: Chenghai Huang <huangchenghai2@huawei.com>
13+---
14+ wd_util.c | 62 ++++++++++++++++++++++++++-----------------------------
15+ 1 file changed, 29 insertions(+), 33 deletions(-)
16+ 
17+diff --git a/wd_util.c b/wd_util.c
18+index cc89837..ebe6a56 100644
19+--- a/wd_util.c
20++++ b/wd_util.c
21+@@ -2786,11 +2786,10 @@ err_ctxs:
22+ }
23+
24+ /*
25+- * SCHED_POLICY_DEV: open sync/async ctxs of (drv, op_type, numa) interleaved on
26+- * ONE device. The caller pins the device via dparams->preferred_dev_path.
27+- * Stop when both counts are met or the device is full. If both modes are
28+- * requested but only one could be opened, roll back and return -WD_ENODEV so
29+- * the caller can try the next device; partial within one mode is kept.
30++ * SCHED_POLICY_DEV: open all sync ctxs then all async ctxs of
31++ * (drv, op_type, numa) on ONE device pinned by dparams->preferred_dev_path.
32++ * If the device cannot hold the whole group, roll back every ctx opened on
33++ * it and return -WD_ENODEV so the caller tries the next device.
34+ */
35+ static int wd_alloc_dev_group(struct wd_init_attrs *attrs,
36+ struct wd_alg_driver *drv,
37+@@ -2801,58 +2800,44 @@ static int wd_alloc_dev_group(struct wd_init_attrs *attrs,
38+ __u32 want[2] = {nums->sync_ctx_num, nums->async_ctx_num};
39+ __u8 modes[2] = {CTX_MODE_SYNC, CTX_MODE_ASYNC};
40+ __u32 group_start = *ctx_idx;
41+- __u32 done[2] = {0, 0};
42+- __u32 i;
43++ __u32 i, j;
44+ int ret;
45+
46+- while (done[0] < want[0] || done[1] < want[1]) {
47+- for (i = 0; i < 2; i++) {
48+- if (done[i] >= want[i])
49+- continue;
50+-
51+- dparams->ctx_mode = modes[i];
52++ for (i = 0; i < 2; i++) {
53++ dparams->ctx_mode = modes[i];
54++ for (j = 0; j < want[i]; j++) {
55+ ret = wd_alloc_one_ctx(attrs, drv, dparams, ctx_idx);
56+ if (ret) {
57++ wd_free_ctxs_batch_range(attrs, group_start, *ctx_idx);
58++ *ctx_idx = group_start;
59+ if (ret != -WD_EBUSY && ret != -WD_ENODEV)
60+ return ret;
61+- /*
62+- * Device full. If both modes were requested
63+- * but only one got ctxs, the empty domain
64+- * would cause idx 65535 at runtime. Roll back
65+- * this group so the caller tries another dev.
66+- */
67+- if (want[0] && want[1] &&
68+- (!done[0] || !done[1])) {
69+- wd_free_ctxs_batch_range(attrs, group_start, *ctx_idx);
70+- *ctx_idx = group_start;
71+- return -WD_ENODEV;
72+- }
73+- return WD_SUCCESS;
74++ return -WD_ENODEV;
75+ }
76+- done[i]++;
77+ }
78+ }
79+ return WD_SUCCESS;
80+ }
81+
82+ /*
83+- * SCHED_POLICY_DEV: per (drv, op_type, numa) open sync/async on one device
84+- * (interleaved, partial allowed). Enumerates devices on each numa node and
85+- * pins each group to one device via preferred_dev_path, trying the next
86+- * device if the current one cannot hold both modes.
87++ * SCHED_POLICY_DEV: per (drv, op_type, numa) open all sync+async ctxs on one
88++ * device. Enumerates devices on each numa node and pins each group to one
89++ * device via preferred_dev_path, trying the next device if the current one
90++ * cannot hold the whole group. All devices exhausted => error out.
91+ */
92+ static int wd_alloc_ctxs_batch_dev(struct wd_init_attrs *attrs, __u32 *start_idx)
93+ {
94+ struct wd_ctx_config_internal *internal_config = attrs->ctx_config_internal;
95+ struct wd_ctx_params *ctx_params = attrs->ctx_params;
96+- struct uacce_dev_list *dev_list, *p;
97++ __u32 ctx_idx, drv_idx, start, group_start;
98++ struct uacce_dev_list *dev_list = NULL;
99+ int numa_nodes[UADK_MAX_NUMA_NODES];
100+ char alg_type[CRYPTO_MAX_ALG_NAME];
101+ struct wd_drv_ctx_params dparams;
102+- __u32 ctx_idx, drv_idx, start;
103+ struct wd_alg_driver *drv;
104+ __u8 op_type, numa_count;
105+ struct wd_ctx_nums *nums;
106++ struct uacce_dev_list *p;
107+ int n, ret;
108+
109+ memset(&dparams, 0, sizeof(dparams));
110+@@ -2894,12 +2879,18 @@ static int wd_alloc_ctxs_batch_dev(struct wd_init_attrs *attrs, __u32 *start_idx
111+ continue;
112+
113+ dparams.op_type = op_type;
114++ group_start = ctx_idx;
115+ for (n = 0; n < numa_count; n++) {
116+ dparams.numa_id = numa_nodes[n];
117+ for (p = dev_list; p; p = p->next) {
118+ if (!p->dev || p->dev->numa_id != numa_nodes[n])
119+ continue;
120+
121++ /* Skip devices that cannot hold the whole group */
122++ if (wd_get_avail_ctx(p->dev) < (int)(nums->sync_ctx_num +
123++ nums->async_ctx_num))
124++ continue;
125++
126+ dparams.preferred_dev_path = p->dev->char_dev_path;
127+ ret = wd_alloc_dev_group(attrs, drv,
128+ &dparams,
129+@@ -2910,6 +2901,11 @@ static int wd_alloc_ctxs_batch_dev(struct wd_init_attrs *attrs, __u32 *start_idx
130+ goto err_ctxs;
131+ }
132+ }
133++
134++ if (ctx_idx == group_start) {
135++ ret = -WD_ENODEV;
136++ goto err_ctxs;
137++ }
138+ }
139+ wd_free_list_accels(dev_list);
140+ dev_list = NULL;
141+--
142+2.25.1
143+ 
@@ -0,0 +1,87 @@
1+From 29dd74a2047bdb7a3b0a0af9a33d0a8c1206f6cb Mon Sep 17 00:00:00 2001
2+From: Wenkai Lin <linwenkai6@hisilicon.com>
3+Date: Fri, 16 Oct 2026 17:17:38 +0800
4+Subject: [PATCH 26/37] uadk: balance ctx allocation across devices by
5+ available contexts
6+ 
7+wd_hw_alloc_ctx picked the first device whose wd_request_ctx() succeeded.
8+When PF and VFs share the same NUMA node, the NUMA-distance sort is a
9+no-op, so the device order comes from readdir() over /sys/class/uacce.
10+Each concurrent business independently starts from the list head and
11+binds all ctxs to the same leading device, starving the others.
12+ 
13+Select the device with the most available contexts (wd_get_avail_ctx)
14+instead, with a fallback to the remaining devices if the chosen one
15+fails to open. NUMA distance priority is unchanged.
16+ 
17+Signed-off-by: Wenkai Lin <linwenkai6@hisilicon.com>
18+---
19+ drv/wd_drv.c | 41 +++++++++++++++++++++++++++++++----------
20+ 1 file changed, 31 insertions(+), 10 deletions(-)
21+ 
22+diff --git a/drv/wd_drv.c b/drv/wd_drv.c
23+index c839ed4..08014dd 100644
24+--- a/drv/wd_drv.c
25++++ b/drv/wd_drv.c
26+@@ -181,12 +181,12 @@ int wd_hw_alloc_ctx(char *alg_name, void *params, handle_t *ctx)
27+ {
28+ struct wd_drv_ctx_params *ctx_params = (struct wd_drv_ctx_params *)params;
29+ struct uacce_dev_list *dev_list, *used_list = NULL;
30++ struct uacce_dev_list *curr, *best = NULL;
31+ char alg_type[CRYPTO_MAX_ALG_NAME];
32+- struct uacce_dev_list *curr;
33++ int target_numa, best_avail = 0;
34+ struct wd_ctx_h *ctx_h;
35+- int target_numa;
36++ int ret, avail;
37+ handle_t hctx;
38+- int ret;
39+
40+ if (!params || !ctx) {
41+ WD_ERR("invalid: parameters are NULL!\n");
42+@@ -246,14 +246,35 @@ int wd_hw_alloc_ctx(char *alg_name, void *params, handle_t *ctx)
43+ goto success;
44+ }
45+
46+- curr = used_list;
47+- while (curr) {
48+- if (curr->dev) {
49+- hctx = wd_request_ctx(curr->dev);
50+- if (hctx)
51+- goto success;
52++ /* Pick the device with the most available contexts to balance load. */
53++ for (curr = used_list; curr; curr = curr->next) {
54++ if (!curr->dev)
55++ continue;
56++ avail = wd_get_avail_ctx(curr->dev);
57++ if (avail > best_avail) {
58++ best_avail = avail;
59++ best = curr;
60+ }
61+- curr = curr->next;
62++ }
63++
64++ if (!best) {
65++ WD_ERR("failed to request ctx on NUMA node %d for %s\n",
66++ target_numa, alg_name);
67++ ret = -WD_EBUSY;
68++ goto out;
69++ }
70++
71++ hctx = wd_request_ctx(best->dev);
72++ if (hctx)
73++ goto success;
74++
75++ /* Fall back to remaining devices if the best one fails to open */
76++ for (curr = used_list; curr; curr = curr->next) {
77++ if (curr == best || !curr->dev)
78++ continue;
79++ hctx = wd_request_ctx(curr->dev);
80++ if (hctx)
81++ goto success;
82+ }
83+
84+ WD_ERR("failed to request ctx on NUMA node %d for %s\n",
85+--
86+2.25.1
87+ 
@@ -0,0 +1,42 @@
1+From 7276c3c16a6c95fe7aa9fcbc95dfd62ef6f5b066 Mon Sep 17 00:00:00 2001
2+From: Wenkai Lin <linwenkai6@hisilicon.com>
3+Date: Fri, 16 Oct 2026 17:17:40 +0800
4+Subject: [PATCH 28/37] uadk: fix digest BD3 stream mode issue
5+ 
6+Common digests (SHA/SM3) need SCENE_STREAM for streaming hash but only
7+CTR/GCM streaming was described in the FS, so hash streaming was
8+misconfigured. GMAC uses SCENE_IPSEC independently.
9+ 
10+Use SCENE_STREAM for common digests; keep SCENE_IPSEC for GMAC only.
11+ 
12+Signed-off-by: Wenkai Lin <linwenkai6@hisilicon.com>
13+---
14+ v1/drv/hisi_sec_udrv.c | 12 +++++++++++-
15+ 1 file changed, 11 insertions(+), 1 deletion(-)
16+ 
17+diff --git a/v1/drv/hisi_sec_udrv.c b/v1/drv/hisi_sec_udrv.c
18+index 7eba121..6ad6c57 100644
19+--- a/v1/drv/hisi_sec_udrv.c
20++++ b/v1/drv/hisi_sec_udrv.c
21+@@ -1827,7 +1827,17 @@ static int fill_digest_bd3(struct wd_queue *q, struct hisi_sec_bd3_sqe *sqe,
22+ return ret;
23+
24+ sqe->type = BD_TYPE3;
25+- sqe->scene = is_storage ? SCENE_STORAGE : SCENE_IPSEC;
26++
27++ /*
28++ * GMAC is an IPSEC-specific auth algo (RFC4543); other digests use
29++ * stream scene for long-data hash processing.
30++ */
31++ if (is_storage)
32++ sqe->scene = SCENE_STORAGE;
33++ else if (msg->alg == WCRYPTO_AES_GMAC)
34++ sqe->scene = SCENE_IPSEC;
35++ else
36++ sqe->scene = SCENE_STREAM;
37+
38+ sqe->auth = AUTH_MAC_CALCULATE;
39+ sqe->a_len = msg->in_bytes;
40+--
41+2.25.1
42+ 
@@ -0,0 +1,49 @@
1+From bf9dbb3756f0769395aa78d5d547a74626491c2d Mon Sep 17 00:00:00 2001
2+From: Wenkai Lin <linwenkai6@hisilicon.com>
3+Date: Fri, 16 Oct 2026 17:17:41 +0800
4+Subject: [PATCH 29/37] uadk: check CE digest/cipher result before get_sqe
5+ 
6+In sm3_ce_drv_send and isa_ce_cipher_send, the return value of the
7+software digest/cipher computation (do_sm3_ce, do_hmac_sm3_ce,
8+sm4_xts_encrypt, sm4_xts_decrypt) is silently overwritten by the
9+subsequent wd_get_sqe_from_queue call. If the computation fails,
10+the error is swallowed and the function may return success.
11+ 
12+Add an early return on error before calling wd_get_sqe_from_queue
13+so that a failed computation does not proceed to queue operations.
14+ 
15+Signed-off-by: Wenkai Lin <linwenkai6@hisilicon.com>
16+---
17+ drv/isa_ce_sm3.c | 2 ++
18+ drv/isa_ce_sm4.c | 2 ++
19+ 2 files changed, 4 insertions(+)
20+ 
21+diff --git a/drv/isa_ce_sm3.c b/drv/isa_ce_sm3.c
22+index b41f6c5..117b95e 100644
23+--- a/drv/isa_ce_sm3.c
24++++ b/drv/isa_ce_sm3.c
25+@@ -374,6 +374,8 @@ static int sm3_ce_drv_send(handle_t ctx, void *digest_msg)
26+ WD_ERR("invalid digest mode!\n");
27+ ret = -WD_EINVAL;
28+ }
29++ if (ret)
30++ return ret;
31+
32+ ret = wd_get_sqe_from_queue(sfctx, msg->tag);
33+ if (ret)
34+diff --git a/drv/isa_ce_sm4.c b/drv/isa_ce_sm4.c
35+index 863b99e..7547c00 100644
36+--- a/drv/isa_ce_sm4.c
37++++ b/drv/isa_ce_sm4.c
38+@@ -399,6 +399,8 @@ static int isa_ce_cipher_send(handle_t ctx, void *wd_msg)
39+ ret = sm4_xts_encrypt(msg, &rkey);
40+ else
41+ ret = sm4_xts_decrypt(msg, &rkey);
42++ if (ret)
43++ return ret;
44+ break;
45+ default:
46+ WD_ERR("The current block cipher mode is not supported!\n");
47+--
48+2.25.1
49+ 
@@ -0,0 +1,33 @@
1+From 48ef855d71a7a3105b2f7f7430e84e1398f70a12 Mon Sep 17 00:00:00 2001
2+From: Weili Qian <qianweili@huawei.com>
3+Date: Fri, 16 Oct 2026 17:17:42 +0800
4+Subject: [PATCH 30/37] uadk: fix alloc/free pairing in rsa session key error
5+ path
6+ 
7+In wd_rsa.c create_sess_key, prikey is allocated via sess->mm_ops.alloc
8+which may be backed by mmap (WD_MMAP_MEM), but the pubkey alloc failure
9+path freed it with free(), causing undefined behavior on mmap memory.
10+Use sess->mm_ops.free to match the allocator and the normal release
11+path in del_sess_key.
12+ 
13+Signed-off-by: Weili Qian <qianweili@huawei.com>
14+---
15+ wd_rsa.c | 2 +-
16+ 1 file changed, 1 insertion(+), 1 deletion(-)
17+ 
18+diff --git a/wd_rsa.c b/wd_rsa.c
19+index c1f2d9a..59c230d 100644
20+--- a/wd_rsa.c
21++++ b/wd_rsa.c
22+@@ -930,7 +930,7 @@ static int create_sess_key(struct wd_rsa_sess_setup *setup,
23+ (int)GEN_PARAMS_SZ(sess->key_size);
24+ sess->pubkey = sess->mm_ops.alloc(sess->mm_ops.usr, len);
25+ if (!sess->pubkey) {
26+- free(sess->prikey);
27++ sess->mm_ops.free(sess->mm_ops.usr, sess->prikey);
28+ WD_ERR("failed to alloc sess pubkey!\n");
29+ return -WD_ENOMEM;
30+ }
31+--
32+2.25.1
33+ 
@@ -0,0 +1,50 @@
1+From 6f3b7c3f177a6bdea0add561c478d1d3abd99ea9 Mon Sep 17 00:00:00 2001
2+From: Weili Qian <qianweili@huawei.com>
3+Date: Fri, 16 Oct 2026 17:17:43 +0800
4+Subject: [PATCH 31/37] uadk: fix return values overwritten by sqe queue call
5+ 
6+wd_alg_init_fallback in wd_util.c discarded fb_driver->init() return
7+value and always returned 0, and wd_agg_rehash_sync_inner in wd_agg.c
8+ignored wd_agg_set_col_size return value, allowing invalid column
9+sizes to hardware DMA. Propagate the init return value and check
10+wd_agg_set_col_size so callers can detect failures.
11+ 
12+Signed-off-by: Weili Qian <qianweili@huawei.com>
13+---
14+ wd_agg.c | 4 +++-
15+ wd_util.c | 4 +---
16+ 2 files changed, 4 insertions(+), 4 deletions(-)
17+ 
18+diff --git a/wd_agg.c b/wd_agg.c
19+index 95cb869..951e03d 100644
20+--- a/wd_agg.c
21++++ b/wd_agg.c
22+@@ -1500,7 +1500,9 @@ static int wd_agg_rehash_sync_inner(struct wd_agg_sess *sess, struct wd_agg_req
23+ }
24+
25+ out_req->real_out_row_count = msg.out_row_count;
26+- wd_agg_set_col_size(sess, in_req, out_req->real_out_row_count);
27++ ret = wd_agg_set_col_size(sess, in_req, out_req->real_out_row_count);
28++ if (unlikely(ret))
29++ return ret;
30+ in_req->in_row_count = out_req->real_out_row_count;
31+
32+ fill_request_msg_input(&in_msg, in_req, sess, true);
33+diff --git a/wd_util.c b/wd_util.c
34+index ebe6a56..79bed19 100644
35+--- a/wd_util.c
36++++ b/wd_util.c
37+@@ -1566,9 +1566,7 @@ static int wd_alg_init_fallback(struct wd_alg_driver *fb_driver)
38+ return -WD_EINVAL;
39+ }
40+
41+- fb_driver->init(NULL, NULL);
42+-
43+- return 0;
44++ return fb_driver->init(NULL, NULL);
45+ }
46+
47+ static void wd_alg_uninit_fallback(struct wd_alg_driver *fb_driver)
48+--
49+2.25.1
50+ 
@@ -0,0 +1,52 @@
1+From 8d8909502d5feb4e19f51659a7b3c130c3390bbd Mon Sep 17 00:00:00 2001
2+From: Weili Qian <qianweili@huawei.com>
3+Date: Fri, 16 Oct 2026 17:17:44 +0800
4+Subject: [PATCH 32/37] uadk: fix buffer overflow and out-of-bounds access
5+ 
6+wd_parse_log_level in wd.c allocated st_size bytes but fscanf "%[^\n ]"
7+appends a '\0', causing off-by-one heap overflow when a token is exactly
8+st_size long. _find_next_bit in wd_mempool.c used "start > bits" in the
9+loop guard while the initial guard used "start >= bits", reading map out
10+of bounds when bits is a multiple of BITS_PER_LONG. Allocate st_size + 1
11+and use ">=" for the loop guard.
12+ 
13+Signed-off-by: Weili Qian <qianweili@huawei.com>
14+---
15+ wd.c | 3 ++-
16+ wd_mempool.c | 2 +-
17+ 2 files changed, 3 insertions(+), 2 deletions(-)
18+ 
19+diff --git a/wd.c b/wd.c
20+index 1c28bb3..13852f7 100644
21+--- a/wd.c
22++++ b/wd.c
23+@@ -114,11 +114,12 @@ static void wd_parse_log_level(void)
24+ goto close_file;
25+ }
26+
27+- file_contents = malloc(file_info.st_size);
28++ file_contents = malloc(file_info.st_size + 1);
29+ if (!file_contents) {
30+ WD_ERR("failed to get file contents memory.\n");
31+ goto close_file;
32+ }
33++ file_contents[file_info.st_size] = '\0';
34+
35+ while (fscanf(in_file, " %[^\n ] ", file_contents) != EOF) {
36+ if (!strcmp("local5.debug", file_contents))
37+diff --git a/wd_mempool.c b/wd_mempool.c
38+index 3ce9ef0..15c8d45 100644
39+--- a/wd_mempool.c
40++++ b/wd_mempool.c
41+@@ -239,7 +239,7 @@ static unsigned long _find_next_bit(unsigned long *map, unsigned long bits,
42+
43+ while (!tmp) {
44+ start += BITS_PER_LONG;
45+- if (start > bits)
46++ if (start >= bits)
47+ return bits;
48+
49+ tmp = map[start / BITS_PER_LONG];
50+--
51+2.25.1
52+ 
@@ -0,0 +1,77 @@
1+From 77ee79f5c083d819503b6c6ee5c84d382f37a5a2 Mon Sep 17 00:00:00 2001
2+From: Weili Qian <qianweili@huawei.com>
3+Date: Fri, 16 Oct 2026 17:17:45 +0800
4+Subject: [PATCH 33/37] uadk: fix lock init failure detection
5+ 
6+pthread_spin_init returns a positive errno on failure, but
7+wd_blockpool_create/wd_mempool_create checked "if (ret < 0)" which was
8+always false, and wd_soft_alloc_ctx did not check the return value at
9+all, leaving spinlocks uninitialized. Use "if (ret)" to detect failure,
10+check both spin_init calls in wd_soft_alloc_ctx, clean up on failure,
11+and return -ret so callers using "if (ret < 0)" can detect the error.
12+ 
13+Signed-off-by: Weili Qian <qianweili@huawei.com>
14+---
15+ drv/wd_drv.c | 16 ++++++++++++++--
16+ wd_mempool.c | 4 ++--
17+ 2 files changed, 16 insertions(+), 4 deletions(-)
18+ 
19+diff --git a/drv/wd_drv.c b/drv/wd_drv.c
20+index 08014dd..4bac551 100644
21+--- a/drv/wd_drv.c
22++++ b/drv/wd_drv.c
23+@@ -11,6 +11,7 @@
24+ int wd_soft_alloc_ctx(char *alg_name, void *params, handle_t *ctx)
25+ {
26+ struct wd_soft_ctx *sfctx;
27++ int ret;
28+
29+ if (!params || !ctx) {
30+ WD_ERR("invalid: params, or ctx is NULL!\n");
31+@@ -27,8 +28,19 @@ int wd_soft_alloc_ctx(char *alg_name, void *params, handle_t *ctx)
32+ /* Initialize as software context */
33+ sfctx->fd = -1;
34+ sfctx->ctx_type = UADK_ALG_SOFT;
35+- pthread_spin_init(&sfctx->slock, PTHREAD_PROCESS_PRIVATE);
36+- pthread_spin_init(&sfctx->rlock, PTHREAD_PROCESS_PRIVATE);
37++ ret = pthread_spin_init(&sfctx->slock, PTHREAD_PROCESS_PRIVATE);
38++ if (ret) {
39++ WD_ERR("failed to init slock!\n");
40++ free(sfctx);
41++ return -ret;
42++ }
43++ ret = pthread_spin_init(&sfctx->rlock, PTHREAD_PROCESS_PRIVATE);
44++ if (ret) {
45++ WD_ERR("failed to init rlock!\n");
46++ pthread_spin_destroy(&sfctx->slock);
47++ free(sfctx);
48++ return -ret;
49++ }
50+
51+ /* Return context handle */
52+ *ctx = (handle_t)sfctx;
53+diff --git a/wd_mempool.c b/wd_mempool.c
54+index 15c8d45..4081130 100644
55+--- a/wd_mempool.c
56++++ b/wd_mempool.c
57+@@ -561,7 +561,7 @@ handle_t wd_blockpool_create(handle_t mempool, size_t block_size,
58+ bp->free_block_num = block_num;
59+ bp->mp = mp;
60+ ret = pthread_spin_init(&bp->lock, PTHREAD_PROCESS_PRIVATE);
61+- if (ret < 0)
62++ if (ret)
63+ goto err_free_bp;
64+
65+ ret = alloc_mem_from_mempool(mp, bp);
66+@@ -910,7 +910,7 @@ handle_t wd_mempool_create(size_t size, int node)
67+ mp->size = tmp;
68+ mp->blk_size = WD_MEMPOOL_BLOCK_SIZE;
69+ ret = pthread_spin_init(&mp->lock, PTHREAD_PROCESS_PRIVATE);
70+- if (ret < 0)
71++ if (ret)
72+ goto free_pool;
73+
74+ ret = alloc_mem_from_hugepage(mp);
75+--
76+2.25.1
77+ 
@@ -0,0 +1,147 @@
1+From 420700bf8853928b002238bb66d79cb306e975de Mon Sep 17 00:00:00 2001
2+From: Weili Qian <qianweili@huawei.com>
3+Date: Fri, 16 Oct 2026 17:17:46 +0800
4+Subject: [PATCH 34/37] uadk: fix SGL/DMA resource leak and missing NULL checks
5+ 
6+hisi_qm_create_sglpool missed NULL check on hisi_qm_align_sgl and set
7+sgl_num to i instead of i + 1 on failure, leaking the already-allocated
8+sgl[i]. hisi_qm_get_hw_sgl, hisi_sec_cipher_send/_v3, cipher/digest/aead
9+recv and fill_zip_comp_sqe also leaked SGL/DMA resources or passed NULL
10+to hardware on error paths. Add NULL checks, fix sgl_num, and recycle
11+SGL entries on error paths.
12+ 
13+Signed-off-by: Weili Qian <qianweili@huawei.com>
14+---
15+ drv/hisi_comp.c | 7 ++++++-
16+ drv/hisi_qm_udrv.c | 15 +++++++++++++--
17+ drv/hisi_sec.c | 34 ++++++++++++++++++++--------------
18+ 3 files changed, 39 insertions(+), 17 deletions(-)
19+ 
20+diff --git a/drv/hisi_comp.c b/drv/hisi_comp.c
21+index b798811..c1b83c3 100644
22+--- a/drv/hisi_comp.c
23++++ b/drv/hisi_comp.c
24+@@ -1555,8 +1555,13 @@ static int fill_zip_comp_sqe(struct hisi_qp *qp, struct wd_comp_msg *msg,
25+ ops[alg_type].fill_alg(sqe);
26+
27+ ret = ops[alg_type].fill_comp_level(sqe, msg->comp_lv);
28+- if (unlikely(ret))
29++ if (unlikely(ret)) {
30++ if (msg->mm_ops && !msg->mm_ops->sva_mode)
31++ zip_mem_unmap(msg, sqe);
32++ if (msg->req.data_fmt == WD_SGL_BUF)
33++ free_hw_sgl((handle_t)qp, &msg->c_sgl, msg->mm_ops);
34+ return ret;
35++ }
36+
37+ ops[alg_type].fill_tag(sqe, msg->tag);
38+
39+diff --git a/drv/hisi_qm_udrv.c b/drv/hisi_qm_udrv.c
40+index 6da9887..8617b10 100644
41+--- a/drv/hisi_qm_udrv.c
42++++ b/drv/hisi_qm_udrv.c
43+@@ -803,6 +803,10 @@ handle_t hisi_qm_create_sglpool(__u32 sgl_num, __u32 sge_num, struct wd_mm_ops *
44+
45+ sgl_pool->sgl_align[i] = hisi_qm_align_sgl(sgl_pool->sgl[i],
46+ sge_num, sgl_pool->mm_ops);
47++ if (!sgl_pool->sgl_align[i]) {
48++ sgl_pool->sgl_num = i + 1;
49++ goto err_out;
50++ }
51+ }
52+
53+ sgl_pool->sgl_num = sgl_num;
54+@@ -999,11 +1003,18 @@ void *hisi_qm_get_hw_sgl(handle_t sgl_pool, struct wd_datalist *sgl)
55+ ret = WD_ERR_PTR(-WD_EBUSY);
56+ goto err_out;
57+ }
58+- if (mm_ops)
59++ if (mm_ops) {
60+ cur->next_dma = (uintptr_t)mm_ops->iova_map(mm_ops->usr,
61+ next, sizeof(*next));
62+- else
63++ if (!cur->next_dma) {
64++ WD_ERR("invalid: iova_map for sgl chain failed!\n");
65++ hisi_qm_sgl_push(pool, next);
66++ ret = WD_ERR_PTR(-WD_ENOMEM);
67++ goto err_out;
68++ }
69++ } else {
70+ cur->next_dma = (uintptr_t)next;
71++ }
72+ cur->next = next;
73+ cur = next;
74+ head->entry_sum_in_chain += pool->sge_num;
75+diff --git a/drv/hisi_sec.c b/drv/hisi_sec.c
76+index 10bb34e..df086d7 100644
77+--- a/drv/hisi_sec.c
78++++ b/drv/hisi_sec.c
79+@@ -1439,22 +1439,25 @@ static int hisi_sec_cipher_send(handle_t ctx, void *wd_msg)
80+ ret = fill_cipher_bd2_addr(msg, &sqe);
81+ if (ret < 0) {
82+ WD_ERR("cipher map memory is err(%d)!\n", ret);
83+- return ret;
84++ goto put_sgl;
85+ }
86+
87+ ret = hisi_qm_send(h_qp, &sqe, 1, &count);
88+ if (ret < 0) {
89+ if (ret != -WD_EBUSY)
90+ WD_ERR("cipher send sqe is err(%d)!\n", ret);
91+-
92+- if (msg->data_fmt == WD_SGL_BUF)
93+- hisi_sec_put_sgl(h_qp, msg->alg_type, msg->in,
94+- msg->out, msg->mm_ops);
95+- destroy_cipher_bd2_addr(msg, &sqe);
96+- return ret;
97++ goto destroy_addr;
98+ }
99+
100+ return 0;
101++
102++destroy_addr:
103++ destroy_cipher_bd2_addr(msg, &sqe);
104++put_sgl:
105++ if (msg->data_fmt == WD_SGL_BUF)
106++ hisi_sec_put_sgl(h_qp, msg->alg_type, msg->in,
107++ msg->out, msg->mm_ops);
108++ return ret;
109+ }
110+
111+ int hisi_sec_cipher_recv(handle_t ctx, void *wd_msg)
112+@@ -1735,22 +1738,25 @@ static int hisi_sec_cipher_send_v3(handle_t ctx, void *wd_msg)
113+ ret = fill_cipher_bd3_addr(msg, &sqe);
114+ if (ret < 0) {
115+ WD_ERR("cipher map memory is err(%d)!\n", ret);
116+- return ret;
117++ goto put_sgl;
118+ }
119+
120+ ret = hisi_qm_send(h_qp, &sqe, 1, &count);
121+ if (ret < 0) {
122+ if (ret != -WD_EBUSY)
123+ WD_ERR("cipher send sqe is err(%d)!\n", ret);
124+-
125+- if (msg->data_fmt == WD_SGL_BUF)
126+- hisi_sec_put_sgl(h_qp, msg->alg_type, msg->in,
127+- msg->out, msg->mm_ops);
128+- destroy_cipher_bd3_addr(msg, &sqe);
129+- return ret;
130++ goto destroy_addr;
131+ }
132+
133+ return 0;
134++
135++destroy_addr:
136++ destroy_cipher_bd3_addr(msg, &sqe);
137++put_sgl:
138++ if (msg->data_fmt == WD_SGL_BUF)
139++ hisi_sec_put_sgl(h_qp, msg->alg_type, msg->in,
140++ msg->out, msg->mm_ops);
141++ return ret;
142+ }
143+
144+ static void parse_cipher_bd3(struct hisi_qp *qp, struct hisi_sec_sqe3 *sqe,
145+--
146+2.25.1
147+ 
@@ -0,0 +1,90 @@
1+From 639da114e09715646355b0bcc496cd8c07ee6ba7 Mon Sep 17 00:00:00 2001
2+From: Weili Qian <qianweili@huawei.com>
3+Date: Fri, 16 Oct 2026 17:17:47 +0800
4+Subject: [PATCH 35/37] uadk: fix message pool pollution and memory leak
5+ 
6+wd_*_poll_ctx in wd_ecc/rsa/dh/udma.c put recv_msg.tag (0 from
7+zero-initialized recv_msg) back into the message pool on drv->recv
8+failure, marking slot 0 as free even when in use and causing double-use
9+or use-after-free. sm2_enc_parse in hisi_hpre.c leaked the second SQE
10+and its DMA mappings when parse_second_sqe partially succeeded.
11+Remove the wd_put_msg_to_pool call on recv failure to align with
12+aead/cipher/digest, and free the second SQE before jumping to free_first.
13+ 
14+Signed-off-by: Weili Qian <qianweili@huawei.com>
15+---
16+ drv/hisi_hpre.c | 2 ++
17+ wd_dh.c | 2 --
18+ wd_ecc.c | 2 --
19+ wd_rsa.c | 2 --
20+ wd_udma.c | 2 --
21+ 5 files changed, 2 insertions(+), 8 deletions(-)
22+ 
23+diff --git a/drv/hisi_hpre.c b/drv/hisi_hpre.c
24+index 70abe92..6d61fa4 100644
25+--- a/drv/hisi_hpre.c
26++++ b/drv/hisi_hpre.c
27+@@ -2713,6 +2713,8 @@ static int sm2_enc_parse(handle_t h_qp, struct wd_ecc_msg *msg,
28+ ret = parse_second_sqe(h_qp, msg, &second);
29+ if (unlikely(ret)) {
30+ WD_ERR("failed to parse second BD, ret = %d!\n", ret);
31++ if (second)
32++ free_req(second);
33+ goto free_first;
34+ }
35+
36+diff --git a/wd_dh.c b/wd_dh.c
37+index 8026fd6..f9958b2 100644
38+--- a/wd_dh.c
39++++ b/wd_dh.c
40+@@ -520,8 +520,6 @@ int wd_dh_poll_ctx(__u32 idx, __u32 expt, __u32 *count)
41+ } else if (unlikely(ret)) {
42+ WD_ERR("failed to async recv, ret = %d!\n", ret);
43+ *count = rcv_cnt;
44+- wd_put_msg_to_pool(&wd_dh_setting.pool, idx,
45+- rcv_msg.tag);
46+ return ret;
47+ }
48+ rcv_cnt++;
49+diff --git a/wd_ecc.c b/wd_ecc.c
50+index 4b141c4..679a3fb 100644
51+--- a/wd_ecc.c
52++++ b/wd_ecc.c
53+@@ -2519,8 +2519,6 @@ int wd_ecc_poll_ctx(__u32 idx, __u32 expt, __u32 *count)
54+ } else if (ret < 0) {
55+ WD_ERR("failed to async recv, ret = %d!\n", ret);
56+ *count = rcv_cnt;
57+- wd_put_msg_to_pool(&wd_ecc_setting.pool, idx,
58+- recv_msg.tag);
59+ return ret;
60+ }
61+ rcv_cnt++;
62+diff --git a/wd_rsa.c b/wd_rsa.c
63+index 59c230d..539285d 100644
64+--- a/wd_rsa.c
65++++ b/wd_rsa.c
66+@@ -583,8 +583,6 @@ int wd_rsa_poll_ctx(__u32 idx, __u32 expt, __u32 *count)
67+ return ret;
68+ } else if (ret < 0) {
69+ WD_ERR("failed to async recv, ret = %d!\n", ret);
70+- wd_put_msg_to_pool(&wd_rsa_setting.pool, idx,
71+- recv_msg.tag);
72+ return ret;
73+ }
74+ rcv_cnt++;
75+diff --git a/wd_udma.c b/wd_udma.c
76+index 582c8d1..e329838 100644
77+--- a/wd_udma.c
78++++ b/wd_udma.c
79+@@ -337,8 +337,6 @@ static int wd_udma_poll_ctx(__u32 idx, __u32 expt, __u32 *count)
80+ } else if (unlikely(ret)) {
81+ WD_ERR("failed to async recv, ret = %d!\n", ret);
82+ *count = rcv_cnt;
83+- wd_put_msg_to_pool(&wd_udma_setting.pool, idx,
84+- rcv_msg.tag);
85+ return ret;
86+ }
87+ rcv_cnt++;
88+--
89+2.25.1
90+ 
@@ -0,0 +1,53 @@
1+From a275a5830c8e44a27641cc2d6efea9dcbbbab839 Mon Sep 17 00:00:00 2001
2+From: Weili Qian <qianweili@huawei.com>
3+Date: Fri, 16 Oct 2026 17:17:48 +0800
4+Subject: [PATCH 36/37] uadk: fix uninit memory and redundant driver init call
5+ 
6+wd_pool_init in wd_bmm.c allocated blk_array with malloc, leaving
7+elements uninitialized and passing garbage blk/blk_dma to wd_iova_unmap
8+on the error cleanup path. wd_comp_init_nolock in wd_comp.c called
9+wd_alg_init_driver redundantly since the caller already invokes it,
10+causing double initialization. Use calloc to zero-initialize blk_array
11+and remove the redundant wd_alg_init_driver call to match other modules.
12+ 
13+Signed-off-by: Weili Qian <qianweili@huawei.com>
14+---
15+ wd_bmm.c | 2 +-
16+ wd_comp.c | 6 ------
17+ 2 files changed, 1 insertion(+), 7 deletions(-)
18+ 
19+diff --git a/wd_bmm.c b/wd_bmm.c
20+index 811afa2..e393e59 100644
21+--- a/wd_bmm.c
22++++ b/wd_bmm.c
23+@@ -707,7 +707,7 @@ static int wd_pool_init(struct wd_blkpool *p)
24+ }
25+
26+ /* Allocate block array */
27+- p->blk_array = (struct wd_blk_hd *)malloc(act_num * sizeof(struct wd_blk_hd));
28++ p->blk_array = (struct wd_blk_hd *)calloc(act_num, sizeof(struct wd_blk_hd));
29+ if (!p->blk_array) {
30+ WD_ERR("Failed to allocate block array.\n");
31+ return -WD_ENOMEM;
32+diff --git a/wd_comp.c b/wd_comp.c
33+index 35af141..523a189 100644
34+--- a/wd_comp.c
35++++ b/wd_comp.c
36+@@ -156,14 +156,8 @@ static int wd_comp_init_nolock(struct wd_ctx_config *config, struct wd_sched *sc
37+ if (ret < 0)
38+ goto out_clear_sched;
39+
40+- ret = wd_alg_init_driver(&wd_comp_setting.config);
41+- if (ret)
42+- goto out_clear_pool;
43+-
44+ return 0;
45+
46+-out_clear_pool:
47+- wd_uninit_async_request_pool(&wd_comp_setting.pool);
48+ out_clear_sched:
49+ wd_clear_sched(&wd_comp_setting.sched);
50+ out_clear_ctx_config:
51+--
52+2.25.1
53+ 
@@ -0,0 +1,63 @@
1+From 013f8e17cfc4c69fb203ff7fc1f119684681c80e Mon Sep 17 00:00:00 2001
2+From: Weili Qian <qianweili@huawei.com>
3+Date: Fri, 16 Oct 2026 17:17:49 +0800
4+Subject: [PATCH 37/37] uadk: initialize wd_sched_params to avoid uninitialized
5+ field reads
6+ 
7+Several session alloc functions (agg, join_gather, udma) declared a local
8+struct wd_sched_params without initialization, setting only alg_name and
9+ctxs before passing to wd_sched_set_param, which reads pkt_size, data_mode
10+and prio_mode unconditionally. Uninitialized stack values caused
11+nondeterministic scheduling.
12+ 
13+Initialize with = {0} at declaration, consistent with wd_comp_alloc_sess.
14+ 
15+Signed-off-by: Weili Qian <qianweili@huawei.com>
16+---
17+ wd_agg.c | 2 +-
18+ wd_join_gather.c | 2 +-
19+ wd_udma.c | 2 +-
20+ 3 files changed, 3 insertions(+), 3 deletions(-)
21+ 
22+diff --git a/wd_agg.c b/wd_agg.c
23+index 951e03d..ed4ba74 100644
24+--- a/wd_agg.c
25++++ b/wd_agg.c
26+@@ -446,7 +446,7 @@ static int wd_agg_uninit_sess_priv(struct wd_agg_sess *sess)
27+
28+ handle_t wd_agg_alloc_sess(struct wd_agg_sess_setup *setup)
29+ {
30+- struct wd_sched_params params;
31++ struct wd_sched_params params = {0};
32+ struct wd_agg_sess *sess;
33+ __u32 out_agg_cols_num = 0;
34+ int ret;
35+diff --git a/wd_join_gather.c b/wd_join_gather.c
36+index e43dbf9..27472d3 100644
37+--- a/wd_join_gather.c
38++++ b/wd_join_gather.c
39+@@ -533,7 +533,7 @@ static int wd_join_gather_init_sess(struct wd_join_gather_sess *sess,
40+
41+ handle_t wd_join_gather_alloc_sess(struct wd_join_gather_sess_setup *setup)
42+ {
43+- struct wd_sched_params params;
44++ struct wd_sched_params params = {0};
45+ struct wd_join_gather_sess *sess;
46+ int ret;
47+
48+diff --git a/wd_udma.c b/wd_udma.c
49+index e329838..b92e75b 100644
50+--- a/wd_udma.c
51++++ b/wd_udma.c
52+@@ -78,7 +78,7 @@ void wd_udma_free_sess(handle_t sess)
53+
54+ handle_t wd_udma_alloc_sess(struct wd_udma_sess_setup *setup)
55+ {
56+- struct wd_sched_params params;
57++ struct wd_sched_params params = {0};
58+ struct wd_udma_sess *sess;
59+ int ret;
60+
61+--
62+2.25.1
63+ 
@@ -2,7 +2,7 @@
2Name: libwd2Name: libwd
3Summary: User Space Accelerator Development Kit3Summary: User Space Accelerator Development Kit
4Version: 2.11.04Version: 2.11.0
5-Release: 35+Release: 4
6License: Apache-2.06License: Apache-2.0
7Source: %{name}-%{version}.tar.gz7Source: %{name}-%{version}.tar.gz
8 8 
@@ -38,6 +38,21 @@ Patch0019: 0019-uadk-add-debug-configure-option-for-full-stack-trace.patch
38Patch0020: 0020-uadk-remove-redundant-code-and-unused-variables.patch38Patch0020: 0020-uadk-remove-redundant-code-and-unused-variables.patch
39Patch0021: 0021-uadk-fix-big-number-sign-compare-and-add-non-ARM-HWC.patch39Patch0021: 0021-uadk-fix-big-number-sign-compare-and-add-non-ARM-HWC.patch
40Patch0022: 0022-uadk_tool-fix-segfault-in-digest-aead-init1-from-uni.patch40Patch0022: 0022-uadk_tool-fix-segfault-in-digest-aead-init1-from-uni.patch
41+Patch0023: 0023-uadk-fix-Wmaybe-uninitialized-and-Wsign-compare-warn.patch
42+Patch0024: 0024-uadk-bind-sync-async-ctx-to-same-device-under-SCHED_.patch
43+Patch0025: 0025-uadk-simplify-SCHED_POLICY_DEV-ctx-alloc-to-non-inte.patch
44+Patch0026: 0026-uadk-balance-ctx-allocation-across-devices-by-availa.patch
45+Patch0027: 0027-uadk-unify-cipher-digest-aead-BD3-fill-and-parse-pat.patch
46+Patch0028: 0028-uadk-fix-digest-BD3-stream-mode-issue.patch
47+Patch0029: 0029-uadk-check-CE-digest-cipher-result-before-get_sqe.patch
48+Patch0030: 0030-uadk-fix-alloc-free-pairing-in-rsa-session-key-error.patch
49+Patch0031: 0031-uadk-fix-return-values-overwritten-by-sqe-queue-call.patch
50+Patch0032: 0032-uadk-fix-buffer-overflow-and-out-of-bounds-access.patch
51+Patch0033: 0033-uadk-fix-lock-init-failure-detection.patch
52+Patch0034: 0034-uadk-fix-SGL-DMA-resource-leak-and-missing-NULL-chec.patch
53+Patch0035: 0035-uadk-fix-message-pool-pollution-and-memory-leak.patch
54+Patch0036: 0036-uadk-fix-uninit-memory-and-redundant-driver-init-cal.patch
55+Patch0037: 0037-uadk-initialize-wd_sched_params-to-avoid-uninitializ.patch
41 56 
42%description57%description
43This package contains the User Space Accelerator Library58This package contains the User Space Accelerator Library
@@ -119,6 +134,9 @@ rm -rf ${RPM_BUILD_ROOT}
119/sbin/ldconfig134/sbin/ldconfig
120 135 
121%changelog136%changelog
137+* Thu Oct 22 2026 RuiBin Deng <dengruibin@h-partners.com> 2.11.0-4
138+- uadk: fix memory safety, BD3 stream issues and optimize ctx scheduling
139+ 
122* Mon Aug 31 2026 RuiBin Deng <dengruibin@h-partners.com> 2.11.0-3140* Mon Aug 31 2026 RuiBin Deng <dengruibin@h-partners.com> 2.11.0-3
123- uadk: add heterogeneous scheduling support and fix critical issues141- uadk: add heterogeneous scheduling support and fix critical issues
124 142