[PATCH 4/6] zram: Add QPaCE zcomp backend
flat view
WARM1d
From: Georgi Djakov <hidden>
Date: 2026-09-30 14:52:30
Also in:
linux-arm-msm, linux-block, linux-devicetree, lkml
Subsystem:
block layer, the rest, zram compressed ram block device drvier · Maintainers:
Jens Axboe, Linus Torvalds, Minchan Kim, Sergey Senozhatsky
Add a zcomp backend for the Qualcomm Page Compression Engine (QPaCE) so zram can expose qpace-lz4 as a selectable compression algorithm when the QPaCE driver is available. Compress and decompress operations are handled via the QPaCE urgent synchronous path: each request DMA-maps the source and destination buffers, issues a blocking hardware command, and returns the result size. Signed-off-by: Georgi Djakov <redacted> --- drivers/block/zram/Kconfig | 11 +++ drivers/block/zram/Makefile | 1 + drivers/block/zram/backend_qpace.c | 134 +++++++++++++++++++++++++++++ drivers/block/zram/backend_qpace.h | 13 +++ drivers/block/zram/zcomp.c | 11 ++- 5 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 drivers/block/zram/backend_qpace.c create mode 100644 drivers/block/zram/backend_qpace.h
diff --git a/drivers/block/zram/Kconfig b/drivers/block/zram/Kconfig
index 402b7b175863..eece67e7ea83 100644
--- a/drivers/block/zram/Kconfig
+++ b/drivers/block/zram/Kconfig@@ -44,6 +44,17 @@ config ZRAM_BACKEND_842 select 842_COMPRESS select 842_DECOMPRESS +config ZRAM_BACKEND_QPACE + bool "QPaCE compression support" + depends on ZRAM + depends on QCOM_PAGE_COMPRESSION_ENGINE = y || \ + (ZRAM = m && QCOM_PAGE_COMPRESSION_ENGINE = m) + help + Enable Qualcomm Page Compression Engine (QPaCE) hardware + acceleration as a zram backend. When selected, zram offloads + synchronous compress and decompress operations to the QPaCE + urgent command path, reducing CPU overhead. + config ZRAM_BACKEND_FORCE_LZO depends on ZRAM def_bool !ZRAM_BACKEND_LZ4 && !ZRAM_BACKEND_LZ4HC && \
diff --git a/drivers/block/zram/Makefile b/drivers/block/zram/Makefile
index 0fdefd576691..9e1c35f942e0 100644
--- a/drivers/block/zram/Makefile
+++ b/drivers/block/zram/Makefile@@ -8,5 +8,6 @@ zram-$(CONFIG_ZRAM_BACKEND_LZ4HC) += backend_lz4hc.o zram-$(CONFIG_ZRAM_BACKEND_ZSTD) += backend_zstd.o zram-$(CONFIG_ZRAM_BACKEND_DEFLATE) += backend_deflate.o zram-$(CONFIG_ZRAM_BACKEND_842) += backend_842.o +zram-$(CONFIG_ZRAM_BACKEND_QPACE) += backend_qpace.o obj-$(CONFIG_ZRAM) += zram.o
diff --git a/drivers/block/zram/backend_qpace.c b/drivers/block/zram/backend_qpace.c
new file mode 100644
index 000000000000..3af13727adef
--- /dev/null
+++ b/drivers/block/zram/backend_qpace.c@@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#include <linux/dma-mapping.h> +#include <linux/slab.h> +#include <linux/soc/qcom/qpace.h> + +#include "backend_qpace.h" + +struct qpace_ctx { + struct device *dev; + void *in_buf; + dma_addr_t in_dma; + void *out_buf; + dma_addr_t out_dma; +}; + +static int qpace_setup_lz4_params(struct zcomp_params *params) +{ + params->drv_data = (void *)&qpace_lz4_algorithm; + return 0; +} + +static void qpace_release_params(struct zcomp_params *params) +{ +} + +static int qpace_create_ctx(struct zcomp_params *params, struct zcomp_ctx *ctx) +{ + struct device *dev = qpace_get_dma_dev(); + struct qpace_ctx *cc; + + if (!dev) + return -ENODEV; + + cc = kzalloc_obj(*cc, GFP_KERNEL); + if (!cc) + return -ENOMEM; + + cc->dev = dev; + cc->in_buf = dma_alloc_coherent(dev, PAGE_SIZE, &cc->in_dma, GFP_KERNEL); + if (!cc->in_buf) + goto err_free; + + cc->out_buf = dma_alloc_coherent(dev, PAGE_SIZE, &cc->out_dma, GFP_KERNEL); + if (!cc->out_buf) + goto err_free_in; + + ctx->context = cc; + return 0; + +err_free_in: + dma_free_coherent(dev, PAGE_SIZE, cc->in_buf, cc->in_dma); +err_free: + kfree(cc); + return -ENOMEM; +} + +static void qpace_destroy_ctx(struct zcomp_ctx *ctx) +{ + struct qpace_ctx *cc = ctx->context; + + if (!cc) + return; + + dma_free_coherent(cc->dev, PAGE_SIZE, cc->out_buf, cc->out_dma); + dma_free_coherent(cc->dev, PAGE_SIZE, cc->in_buf, cc->in_dma); + kfree(cc); + ctx->context = NULL; +} + +static int qpace_compress(struct zcomp_params *params, struct zcomp_ctx *ctx, + struct zcomp_req *req) +{ + struct qpace_algorithm *algo = params->drv_data; + struct qpace_ctx *cc = ctx->context; + int ret; + + memcpy(cc->in_buf, req->src, req->src_len); + + ret = qpace_urgent_compress(cc->in_dma, cc->out_dma, algo); + + if (ret == -E2BIG || ret >= PAGE_SIZE) { + req->dst_len = PAGE_SIZE; + return 0; + } + if (ret <= 0) + return ret < 0 ? ret : -EIO; + + if (ret > req->dst_len) + return -EIO; + + memcpy(req->dst, cc->out_buf, ret); + req->dst_len = ret; + + return 0; +} + +static int qpace_decompress(struct zcomp_params *params, struct zcomp_ctx *ctx, + struct zcomp_req *req) +{ + struct qpace_algorithm *algo = params->drv_data; + struct qpace_ctx *cc = ctx->context; + int ret; + + if (req->src_len > PAGE_SIZE) + return -EINVAL; + + memcpy(cc->in_buf, req->src, req->src_len); + + ret = qpace_urgent_decompress(cc->in_dma, cc->out_dma, req->src_len, algo); + if (ret <= 0) + return ret < 0 ? ret : -EIO; + + if (ret > req->dst_len) + return -EIO; + + memcpy(req->dst, cc->out_buf, ret); + req->dst_len = ret; + + return 0; +} + +const struct zcomp_ops backend_qpace_lz4 = { + .name = "qpace-lz4", + .setup_params = qpace_setup_lz4_params, + .release_params = qpace_release_params, + .create_ctx = qpace_create_ctx, + .destroy_ctx = qpace_destroy_ctx, + .compress = qpace_compress, + .decompress = qpace_decompress, +};
diff --git a/drivers/block/zram/backend_qpace.h b/drivers/block/zram/backend_qpace.h
new file mode 100644
index 000000000000..03747405edcf
--- /dev/null
+++ b/drivers/block/zram/backend_qpace.h@@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ + +#ifndef __BACKEND_QPACE_H__ +#define __BACKEND_QPACE_H__ + +#include "zcomp.h" + +extern const struct zcomp_ops backend_qpace_lz4; + +#endif /* __BACKEND_QPACE_H__ */
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 028e2f0f587e..b5bd0b11a975 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c@@ -22,6 +22,10 @@ #include "backend_deflate.h" #include "backend_842.h" +#if IS_ENABLED(CONFIG_ZRAM_BACKEND_QPACE) +#include "backend_qpace.h" +#endif + static const struct zcomp_ops *backends[] = { #if IS_ENABLED(CONFIG_ZRAM_BACKEND_LZO) &backend_lzorle,
@@ -41,6 +45,9 @@ static const struct zcomp_ops *backends[] = { #endif #if IS_ENABLED(CONFIG_ZRAM_BACKEND_842) &backend_842, +#endif +#if IS_ENABLED(CONFIG_ZRAM_BACKEND_QPACE) + &backend_qpace_lz4, #endif NULL };
@@ -80,10 +87,10 @@ static const struct zcomp_ops *lookup_backend_ops(const char *comp) while (backends[i]) { if (sysfs_streq(comp, backends[i]->name)) - break; + return backends[i]; i++; } - return backends[i]; + return NULL; } const char *zcomp_lookup_backend_name(const char *comp)