Skip to content

Commit a4fc0da

Browse files
committed
acomp-dpusm: add initial implementation
Add initial implementation of acomp-dpusm plug-in. Signed-off-by: Giovanni Cabiddu <[email protected]>
1 parent a4c90dd commit a4fc0da

File tree

4 files changed

+541
-0
lines changed

4 files changed

+541
-0
lines changed

Makefile

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# SPDX-License-Identifier: GPL-2.0-only
2+
# Copyright (C) 2025 Intel Corporation
3+
# These contents may have been developed with support from one or more
4+
# Intel-operated generative artificial intelligence solutions.
5+
6+
# Define the kernel source directory
7+
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
8+
9+
# Define the module name
10+
MODULE_NAME := acomp-dpusm
11+
12+
# Define the home path for the DPUSM and ZFS source directories
13+
HOME_PATH ?= /devel/zfs
14+
15+
# Define the include paths for DPUSM
16+
DPUSM_INCLUDE := $(HOME_PATH)/dpusm/include
17+
18+
# Define the include paths for ZFS
19+
ZFS_INCLUDE := $(HOME_PATH)/zfs/include
20+
21+
# Define the source files for the module
22+
SRC_FILES := provider.c compress.c
23+
24+
# Define the object files for the module
25+
OBJ_FILES := $(SRC_FILES:.c=.o)
26+
27+
# Define the location of the module symvers file for DPUSM
28+
KBUILD_EXTRA_SYMBOLS := $(HOME_PATH)/dpusm/Module.symvers
29+
30+
ifneq ($(KERNELRELEASE),)
31+
ccflags-y := -I$(DPUSM_INCLUDE) -I$(ZFS_INCLUDE)
32+
obj-m := $(MODULE_NAME).o
33+
$(MODULE_NAME)-y := $(OBJ_FILES)
34+
else
35+
PWD := $(shell pwd)
36+
37+
default:
38+
$(MAKE) -C $(KERNELDIR) M=$(PWD) C=2 W=1 modules
39+
40+
clean:
41+
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
42+
endif
43+
44+
.PHONY: clean

compress.c

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (C) 2025 Intel Corporation
4+
* These contents may have been developed with support from one or more
5+
* Intel-operated generative artificial intelligence solutions.
6+
*/
7+
#include "compress.h"
8+
9+
#include <crypto/acompress.h>
10+
#include <linux/completion.h>
11+
#include <linux/pagemap.h>
12+
#include <linux/scatterlist.h>
13+
#include <linux/slab.h>
14+
#include <linux/types.h>
15+
#include <linux/vmalloc.h>
16+
17+
static struct crypto_acomp *acomp_tfm;
18+
static bool acomp_init_done;
19+
20+
int acomp_init(void)
21+
{
22+
acomp_tfm = crypto_alloc_acomp("zlib-deflate", 0, 0);
23+
if (IS_ERR(acomp_tfm)) {
24+
pr_err("Failed to allocate zlib-deflate acomp transform\n");
25+
return PTR_ERR(acomp_tfm);
26+
}
27+
28+
acomp_init_done = true;
29+
30+
return 0;
31+
}
32+
33+
void acomp_exit(void)
34+
{
35+
if (!acomp_init_done)
36+
return;
37+
38+
if (acomp_tfm) {
39+
crypto_free_acomp(acomp_tfm);
40+
acomp_tfm = NULL;
41+
}
42+
acomp_init_done = false;
43+
}
44+
45+
enum comp_dir {
46+
DECOMPRESS = 0,
47+
COMPRESS = 1,
48+
};
49+
50+
static int acomp_comp_decomp_sg(enum comp_dir dir, struct scatterlist *src, int src_len,
51+
struct scatterlist *dst, int dst_len, size_t *c_len)
52+
{
53+
struct crypto_wait wait;
54+
struct acomp_req *req;
55+
int ret;
56+
57+
pr_debug("[%s] dir: %s, src_len: %d, dst_len: %d\n", __func__,
58+
dir == COMPRESS ? "COMPRESS" : "DECOMPRESS", src_len, dst_len);
59+
60+
req = acomp_request_alloc(acomp_tfm);
61+
if (!req) {
62+
pr_err("Failed to allocate acomp request\n");
63+
return -ENOMEM;
64+
}
65+
66+
crypto_init_wait(&wait);
67+
acomp_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
68+
crypto_req_done, &wait);
69+
70+
acomp_request_set_params(req, src, dst, src_len, dst_len);
71+
72+
if (dir == COMPRESS)
73+
ret = crypto_acomp_compress(req);
74+
else
75+
ret = crypto_acomp_decompress(req);
76+
77+
ret = crypto_wait_req(ret, &wait);
78+
if (ret)
79+
goto out;
80+
81+
*c_len = req->dlen;
82+
83+
out:
84+
acomp_request_free(req);
85+
pr_debug("[%s] ret: %d, dlen=%zu\n", __func__, ret, *c_len);
86+
87+
return ret;
88+
}
89+
90+
static int vmalloc_to_sg(const void *vmem, size_t size, struct scatterlist *sgl, int nents)
91+
{
92+
unsigned long vaddr = (unsigned long)vmem;
93+
unsigned long offset;
94+
size_t remaining = size;
95+
struct page *page;
96+
int sg_count = 0;
97+
98+
sg_init_table(sgl, nents);
99+
100+
while (remaining > 0) {
101+
page = vmalloc_to_page((void *)vaddr);
102+
if (!page) {
103+
pr_err("Failed to retrieve page for vaddr: 0x%lx\n", vaddr);
104+
return -EINVAL;
105+
}
106+
107+
offset = vaddr & (PAGE_SIZE - 1);
108+
size_t len = min((size_t)(PAGE_SIZE - offset), remaining);
109+
110+
sg_set_page(&sgl[sg_count], page, len, offset);
111+
112+
vaddr += len;
113+
remaining -= len;
114+
sg_count++;
115+
116+
if (sg_count >= nents && remaining > 0) {
117+
pr_err("Not enough scatterlist entries for memory size: %zu\n", size);
118+
return -ENOMEM;
119+
}
120+
}
121+
122+
sg_mark_end(&sgl[sg_count - 1]);
123+
124+
return 0;
125+
}
126+
127+
static int count_pages(const void *vmem, size_t size)
128+
{
129+
unsigned long vaddr = (unsigned long)vmem;
130+
size_t remaining = size;
131+
int page_count = 0;
132+
133+
while (remaining > 0) {
134+
size_t len = min((size_t)(PAGE_SIZE - (vaddr & (PAGE_SIZE - 1))), remaining);
135+
136+
vaddr += len;
137+
remaining -= len;
138+
page_count++;
139+
}
140+
141+
return page_count;
142+
}
143+
144+
static int alloc_scatterlist(const void *vmem, size_t size, struct scatterlist **sgl)
145+
{
146+
struct scatterlist *sg = NULL;
147+
int ret = 0;
148+
int pages;
149+
150+
if (!is_vmalloc_addr(vmem)) {
151+
sg = kmalloc(sizeof(*sg), GFP_KERNEL);
152+
if (!sg) {
153+
*sgl = NULL;
154+
return -ENOMEM;
155+
}
156+
157+
sg_init_one(sg, vmem, size);
158+
159+
*sgl = sg;
160+
return 0;
161+
}
162+
163+
pages = count_pages(vmem, size);
164+
if (pages <= 0) {
165+
pr_err("Failed to count pages for memory\n");
166+
return -EINVAL;
167+
}
168+
169+
sg = kmalloc_array(pages, sizeof(struct scatterlist), GFP_KERNEL);
170+
if (!sg)
171+
return -ENOMEM;
172+
173+
memset(sg, 0, sizeof(struct scatterlist) * pages);
174+
175+
ret = vmalloc_to_sg(vmem, size, sg, pages);
176+
if (ret) {
177+
pr_err("Failed to map vmalloc memory to scatterlist\n");
178+
kfree(sg);
179+
*sgl = NULL;
180+
return ret;
181+
}
182+
183+
*sgl = sg;
184+
return ret;
185+
}
186+
187+
static int acomp_comp_decomp(enum comp_dir dir, void *src, int src_len,
188+
void *dst, int dst_len, size_t *c_len)
189+
{
190+
struct scatterlist *src_sg, *dst_sg;
191+
int ret;
192+
193+
ret = alloc_scatterlist(src, src_len, &src_sg);
194+
if (ret) {
195+
pr_err("Failed to allocate scatterlist for SRC memory\n");
196+
return ret;
197+
}
198+
199+
ret = alloc_scatterlist(dst, dst_len, &dst_sg);
200+
if (ret) {
201+
pr_err("Failed to allocate scatterlist for DST memory\n");
202+
kfree(src_sg);
203+
return ret;
204+
}
205+
206+
ret = acomp_comp_decomp_sg(dir, src_sg, src_len, dst_sg, dst_len, c_len);
207+
208+
kfree(src_sg);
209+
kfree(dst_sg);
210+
211+
return ret;
212+
}
213+
214+
int acomp_compress(void *src, int src_len, void *dst, int dst_len, size_t *c_len)
215+
{
216+
return acomp_comp_decomp(COMPRESS, src, src_len, dst, dst_len, c_len);
217+
}
218+
219+
int acomp_decompress(void *src, int src_len, void *dst, int dst_len, size_t *c_len)
220+
{
221+
return acomp_comp_decomp(DECOMPRESS, src, src_len, dst, dst_len, c_len);
222+
}

compress.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/* SPDX-License-Identifier: GPL-2.0-only */
2+
/*
3+
* Copyright (C) 2025 Intel Corporation
4+
* These contents may have been developed with support from one or more
5+
* Intel-operated generative artificial intelligence solutions.
6+
*/
7+
#ifndef _ACOMP_COMPRESS_H
8+
#define _ACOMP_COMPRESS_H
9+
10+
#include <linux/types.h>
11+
12+
int acomp_init(void);
13+
void acomp_exit(void);
14+
int acomp_compress(void *src, int src_len, void *dst, int dst_len, size_t *c_len);
15+
int acomp_decompress(void *src, int src_len, void *dst, int dst_len, size_t *c_len);
16+
17+
#endif /* _ACOMP_COMPRESS_H */

0 commit comments

Comments
 (0)