Linux cryptographic layer development
 help / color / mirror / Atom feed
From: Dave Jiang <dave.jiang@intel.com>
To: Vinicius Costa Gomes <vinicius.gomes@intel.com>,
	Vinod Koul <vkoul@kernel.org>, Frank Li <Frank.Li@kernel.org>,
	Kristen Accardi <kristen.c.accardi@intel.com>,
	Herbert Xu <herbert@gondor.apana.org.au>,
	"David S. Miller" <davem@davemloft.net>,
	Andrew Morton <akpm@linux-foundation.org>,
	Yosry Ahmed <yosry@kernel.org>, Nhat Pham <nphamcs@gmail.com>
Cc: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-crypto@vger.kernel.org,
	Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Subject: Re: [PATCH 2/4] crypto: iaa - fall back to software for multi-entry scatterlists
Date: Tue, 14 Jul 2026 14:54:27 -0700	[thread overview]
Message-ID: <d5417906-20d9-43a7-aa80-c130cbd05d53@intel.com> (raw)
In-Reply-To: <20260713-iaa-crypto-fixes-zswap-v1-2-65cac23c684d@intel.com>



On 7/13/26 9:10 PM, Vinicius Costa Gomes wrote:
> From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
> 
> IAA cannot process source or destination scatterlists with more than one
> entry directly. Instead of failing these requests, route them through a
> separate deflate acomp transform and keep the request alive in software.
> 
> Since commit e2c3b6b21c77 ("mm: zswap: use SG list decompression APIs
> from zsmalloc"), zswap passes the raw zsmalloc SG list directly to
> crypto drivers, so objects spanning multiple pages now reach IAA as
> multi-entry sources and would otherwise fail decompression.
> 
> Fallback to the generic DEFLATE implementation for scatterlists with
> more than one entry. After the multi-entry cases fall back early,
> simplify the DMA mapping path to a single scatterlist entry and fall
> back on mapping failure as well.
> 
> Add counters to track the number of bytes processed by the software
> implementation on the compression direction.
> 
> Fixes: e2c3b6b21c77 ("mm: zswap: use SG list decompression APIs from zsmalloc")
> Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>

Missing Vinicius sign off. 

DJ

> ---
>  drivers/crypto/intel/iaa/iaa_crypto_main.c  | 122 ++++++++++++++++------------
>  drivers/crypto/intel/iaa/iaa_crypto_stats.c |  11 ++-
>  drivers/crypto/intel/iaa/iaa_crypto_stats.h |   2 +
>  3 files changed, 84 insertions(+), 51 deletions(-)
> 
> diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c
> index f62b994e18e5..fb154959c2aa 100644
> --- a/drivers/crypto/intel/iaa/iaa_crypto_main.c
> +++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c
> @@ -2,6 +2,7 @@
>  /* Copyright(c) 2021 Intel Corporation. All rights rsvd. */
>  
>  #include <linux/init.h>
> +#include <linux/crypto.h>
>  #include <linux/kernel.h>
>  #include <linux/module.h>
>  #include <linux/pci.h>
> @@ -983,17 +984,43 @@ static inline int check_completion(struct device *dev,
>  	return ret;
>  }
>  
> -static int deflate_generic_decompress(struct acomp_req *req)
> +static int deflate_fallback(struct acomp_req *req, bool compress)
>  {
>  	ACOMP_FBREQ_ON_STACK(fbreq, req);
>  	int ret;
>  
> -	ret = crypto_acomp_decompress(fbreq);
> +	ret = compress ?
> +		crypto_acomp_compress(fbreq) :
> +		crypto_acomp_decompress(fbreq);
>  	req->dlen = fbreq->dlen;
>  
> +	return ret;
> +}
> +
> +static int deflate_generic_decompress(struct acomp_req *req)
> +{
> +	int ret;
> +
> +	ret = deflate_fallback(req, false);
> +	if (ret)
> +		return ret;
> +
>  	update_total_sw_decomp_calls();
>  
> -	return ret;
> +	return 0;
> +}
> +
> +static int deflate_generic_compress(struct acomp_req *req)
> +{
> +	int ret;
> +
> +	ret = deflate_fallback(req, true);
> +	if (ret)
> +		return ret;
> +
> +	update_total_sw_comp_calls();
> +
> +	return 0;
>  }
>  
>  static int iaa_remap_for_verify(struct device *dev, struct iaa_wq *iaa_wq,
> @@ -1472,7 +1499,7 @@ static int iaa_comp_acompress(struct acomp_req *req)
>  	struct iaa_compression_ctx *compression_ctx;
>  	struct crypto_tfm *tfm = req->base.tfm;
>  	dma_addr_t src_addr, dst_addr;
> -	int nr_sgs, cpu, ret = 0;
> +	int cpu, ret = 0;
>  	struct iaa_wq *iaa_wq;
>  	struct idxd_wq *wq;
>  	struct device *dev;
> @@ -1489,6 +1516,10 @@ static int iaa_comp_acompress(struct acomp_req *req)
>  		return -EINVAL;
>  	}
>  
> +	/* Fall back to software if src or dst has multiple sg entries */
> +	if (sg_nents(req->src) > 1 || sg_nents(req->dst) > 1)
> +		return deflate_generic_compress(req);
> +
>  	cpu = get_cpu();
>  	wq = wq_table_next_wq(cpu);
>  	put_cpu();
> @@ -1507,30 +1538,25 @@ static int iaa_comp_acompress(struct acomp_req *req)
>  
>  	dev = &wq->idxd->pdev->dev;
>  
> -	nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);
> -	if (nr_sgs <= 0 || nr_sgs > 1) {
> -		dev_dbg(dev, "couldn't map src sg for iaa device %d,"
> -			" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,
> -			iaa_wq->wq->id, ret);
> -		ret = -EIO;
> -		goto out;
> +	if (!dma_map_sg(dev, req->src, 1, DMA_TO_DEVICE)) {
> +		dev_dbg(dev, "couldn't map src sg for iaa device %d, wq %d\n",
> +			iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id);
> +		iaa_wq_put(wq);
> +		return deflate_generic_compress(req);
>  	}
>  	src_addr = sg_dma_address(req->src);
> -	dev_dbg(dev, "dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p,"
> -		" req->slen %d, sg_dma_len(sg) %d\n", src_addr, nr_sgs,
> +	dev_dbg(dev, "map src %llx req->src %p slen %d sg_len %d\n", src_addr,
>  		req->src, req->slen, sg_dma_len(req->src));
>  
> -	nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);
> -	if (nr_sgs <= 0 || nr_sgs > 1) {
> -		dev_dbg(dev, "couldn't map dst sg for iaa device %d,"
> -			" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,
> -			iaa_wq->wq->id, ret);
> -		ret = -EIO;
> -		goto err_map_dst;
> +	if (!dma_map_sg(dev, req->dst, 1, DMA_FROM_DEVICE)) {
> +		dev_dbg(dev, "couldn't map dst sg for iaa device %d, wq %d\n",
> +			iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id);
> +		dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE);
> +		iaa_wq_put(wq);
> +		return deflate_generic_compress(req);
>  	}
>  	dst_addr = sg_dma_address(req->dst);
> -	dev_dbg(dev, "dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p,"
> -		" req->dlen %d, sg_dma_len(sg) %d\n", dst_addr, nr_sgs,
> +	dev_dbg(dev, "map dst %llx req->dst %p dlen %d sg_len %d\n", dst_addr,
>  		req->dst, req->dlen, sg_dma_len(req->dst));
>  
>  	ret = iaa_compress(tfm, req, wq, src_addr, req->slen, dst_addr,
> @@ -1550,8 +1576,8 @@ static int iaa_comp_acompress(struct acomp_req *req)
>  		if (ret)
>  			dev_dbg(dev, "asynchronous compress verification failed ret=%d\n", ret);
>  
> -		dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_TO_DEVICE);
> -		dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_FROM_DEVICE);
> +		dma_unmap_sg(dev, req->dst, 1, DMA_TO_DEVICE);
> +		dma_unmap_sg(dev, req->src, 1, DMA_FROM_DEVICE);
>  
>  		goto out;
>  	}
> @@ -1559,9 +1585,8 @@ static int iaa_comp_acompress(struct acomp_req *req)
>  	if (ret)
>  		dev_dbg(dev, "asynchronous compress failed ret=%d\n", ret);
>  
> -	dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);
> -err_map_dst:
> -	dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);
> +	dma_unmap_sg(dev, req->dst, 1, DMA_FROM_DEVICE);
> +	dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE);
>  out:
>  	iaa_wq_put(wq);
>  
> @@ -1572,7 +1597,7 @@ static int iaa_comp_adecompress(struct acomp_req *req)
>  {
>  	struct crypto_tfm *tfm = req->base.tfm;
>  	dma_addr_t src_addr, dst_addr;
> -	int nr_sgs, cpu, ret = 0;
> +	int cpu, ret = 0;
>  	struct iaa_wq *iaa_wq;
>  	struct device *dev;
>  	struct idxd_wq *wq;
> @@ -1587,6 +1612,10 @@ static int iaa_comp_adecompress(struct acomp_req *req)
>  		return -EINVAL;
>  	}
>  
> +	/* Fall back to software if src or dst has multiple sg entries */
> +	if (sg_nents(req->src) > 1 || sg_nents(req->dst) > 1)
> +		return deflate_generic_decompress(req);
> +
>  	cpu = get_cpu();
>  	wq = wq_table_next_wq(cpu);
>  	put_cpu();
> @@ -1605,30 +1634,25 @@ static int iaa_comp_adecompress(struct acomp_req *req)
>  
>  	dev = &wq->idxd->pdev->dev;
>  
> -	nr_sgs = dma_map_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);
> -	if (nr_sgs <= 0 || nr_sgs > 1) {
> -		dev_dbg(dev, "couldn't map src sg for iaa device %d,"
> -			" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,
> -			iaa_wq->wq->id, ret);
> -		ret = -EIO;
> -		goto out;
> +	if (!dma_map_sg(dev, req->src, 1, DMA_TO_DEVICE)) {
> +		dev_dbg(dev, "couldn't map src sg for iaa device %d, wq %d\n",
> +			iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id);
> +		iaa_wq_put(wq);
> +		return deflate_generic_decompress(req);
>  	}
>  	src_addr = sg_dma_address(req->src);
> -	dev_dbg(dev, "dma_map_sg, src_addr %llx, nr_sgs %d, req->src %p,"
> -		" req->slen %d, sg_dma_len(sg) %d\n", src_addr, nr_sgs,
> +	dev_dbg(dev, "map src %llx req->src %p slen %d sg_len %d\n", src_addr,
>  		req->src, req->slen, sg_dma_len(req->src));
>  
> -	nr_sgs = dma_map_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);
> -	if (nr_sgs <= 0 || nr_sgs > 1) {
> -		dev_dbg(dev, "couldn't map dst sg for iaa device %d,"
> -			" wq %d: ret=%d\n", iaa_wq->iaa_device->idxd->id,
> -			iaa_wq->wq->id, ret);
> -		ret = -EIO;
> -		goto err_map_dst;
> +	if (!dma_map_sg(dev, req->dst, 1, DMA_FROM_DEVICE)) {
> +		dev_dbg(dev, "couldn't map dst sg for iaa device %d, wq %d\n",
> +			iaa_wq->iaa_device->idxd->id, iaa_wq->wq->id);
> +		dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE);
> +		iaa_wq_put(wq);
> +		return deflate_generic_decompress(req);
>  	}
>  	dst_addr = sg_dma_address(req->dst);
> -	dev_dbg(dev, "dma_map_sg, dst_addr %llx, nr_sgs %d, req->dst %p,"
> -		" req->dlen %d, sg_dma_len(sg) %d\n", dst_addr, nr_sgs,
> +	dev_dbg(dev, "map dst %llx req->dst %p dlen %d sg_len %d\n", dst_addr,
>  		req->dst, req->dlen, sg_dma_len(req->dst));
>  
>  	ret = iaa_decompress(tfm, req, wq, src_addr, req->slen,
> @@ -1639,10 +1663,8 @@ static int iaa_comp_adecompress(struct acomp_req *req)
>  	if (ret != 0)
>  		dev_dbg(dev, "asynchronous decompress failed ret=%d\n", ret);
>  
> -	dma_unmap_sg(dev, req->dst, sg_nents(req->dst), DMA_FROM_DEVICE);
> -err_map_dst:
> -	dma_unmap_sg(dev, req->src, sg_nents(req->src), DMA_TO_DEVICE);
> -out:
> +	dma_unmap_sg(dev, req->dst, 1, DMA_FROM_DEVICE);
> +	dma_unmap_sg(dev, req->src, 1, DMA_TO_DEVICE);
>  	iaa_wq_put(wq);
>  
>  	return ret;
> diff --git a/drivers/crypto/intel/iaa/iaa_crypto_stats.c b/drivers/crypto/intel/iaa/iaa_crypto_stats.c
> index f5cc3d29ca19..55d0d9c6f61a 100644
> --- a/drivers/crypto/intel/iaa/iaa_crypto_stats.c
> +++ b/drivers/crypto/intel/iaa/iaa_crypto_stats.c
> @@ -19,6 +19,7 @@
>  
>  static atomic64_t total_comp_calls;
>  static atomic64_t total_decomp_calls;
> +static atomic64_t total_sw_comp_calls;
>  static atomic64_t total_sw_decomp_calls;
>  static atomic64_t total_comp_bytes_out;
>  static atomic64_t total_decomp_bytes_in;
> @@ -43,6 +44,11 @@ void update_total_decomp_calls(void)
>  	atomic64_inc(&total_decomp_calls);
>  }
>  
> +void update_total_sw_comp_calls(void)
> +{
> +	atomic64_inc(&total_sw_comp_calls);
> +}
> +
>  void update_total_sw_decomp_calls(void)
>  {
>  	atomic64_inc(&total_sw_decomp_calls);
> @@ -104,6 +110,7 @@ static void reset_iaa_crypto_stats(void)
>  {
>  	atomic64_set(&total_comp_calls, 0);
>  	atomic64_set(&total_decomp_calls, 0);
> +	atomic64_set(&total_sw_comp_calls, 0);
>  	atomic64_set(&total_sw_decomp_calls, 0);
>  	atomic64_set(&total_comp_bytes_out, 0);
>  	atomic64_set(&total_decomp_bytes_in, 0);
> @@ -174,6 +181,8 @@ static int global_stats_show(struct seq_file *m, void *v)
>  		   atomic64_read(&total_comp_calls));
>  	seq_printf(m, "  total_decomp_calls: %llu\n",
>  		   atomic64_read(&total_decomp_calls));
> +	seq_printf(m, "  total_sw_comp_calls: %llu\n",
> +		   atomic64_read(&total_sw_comp_calls));
>  	seq_printf(m, "  total_sw_decomp_calls: %llu\n",
>  		   atomic64_read(&total_sw_decomp_calls));
>  	seq_printf(m, "  total_comp_bytes_out: %llu\n",
> @@ -263,7 +272,7 @@ int __init iaa_crypto_debugfs_init(void)
>  	return 0;
>  }
>  
> -void __exit iaa_crypto_debugfs_cleanup(void)
> +void iaa_crypto_debugfs_cleanup(void)
>  {
>  	debugfs_remove_recursive(iaa_crypto_debugfs_root);
>  }
> diff --git a/drivers/crypto/intel/iaa/iaa_crypto_stats.h b/drivers/crypto/intel/iaa/iaa_crypto_stats.h
> index 3787a5f507eb..6e0c6f9939bf 100644
> --- a/drivers/crypto/intel/iaa/iaa_crypto_stats.h
> +++ b/drivers/crypto/intel/iaa/iaa_crypto_stats.h
> @@ -11,6 +11,7 @@ void	iaa_crypto_debugfs_cleanup(void);
>  void	update_total_comp_calls(void);
>  void	update_total_comp_bytes_out(int n);
>  void	update_total_decomp_calls(void);
> +void	update_total_sw_comp_calls(void);
>  void	update_total_sw_decomp_calls(void);
>  void	update_total_decomp_bytes_in(int n);
>  void	update_completion_einval_errs(void);
> @@ -29,6 +30,7 @@ static inline void	iaa_crypto_debugfs_cleanup(void) {}
>  static inline void	update_total_comp_calls(void) {}
>  static inline void	update_total_comp_bytes_out(int n) {}
>  static inline void	update_total_decomp_calls(void) {}
> +static inline void	update_total_sw_comp_calls(void) {}
>  static inline void	update_total_sw_decomp_calls(void) {}
>  static inline void	update_total_decomp_bytes_in(int n) {}
>  static inline void	update_completion_einval_errs(void) {}
> 


  reply	other threads:[~2026-07-14 21:54 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-14  4:10 [PATCH 0/4] crypto: iaa - Fixes for multi entry SG lists Vinicius Costa Gomes
2026-07-14  4:10 ` [PATCH 1/4] dmaengine: idxd: assign all engines to group 0 in IAA defaults Vinicius Costa Gomes
2026-07-14 21:53   ` Dave Jiang
2026-07-14 21:55     ` Dave Jiang
2026-07-15  1:38       ` Vinicius Costa Gomes
2026-07-14  4:10 ` [PATCH 2/4] crypto: iaa - fall back to software for multi-entry scatterlists Vinicius Costa Gomes
2026-07-14 21:54   ` Dave Jiang [this message]
2026-07-14  4:10 ` [PATCH 3/4] crypto: iaa - avoid counting fallback decompression bytes Vinicius Costa Gomes
2026-07-14 21:56   ` Dave Jiang
2026-07-14  4:10 ` [PATCH 4/4] crypto: iaa - use bounce buffer for multi-sg decompress input Vinicius Costa Gomes
2026-07-14 22:01   ` Dave Jiang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=d5417906-20d9-43a7-aa80-c130cbd05d53@intel.com \
    --to=dave.jiang@intel.com \
    --cc=Frank.Li@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=davem@davemloft.net \
    --cc=dmaengine@vger.kernel.org \
    --cc=giovanni.cabiddu@intel.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=kristen.c.accardi@intel.com \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=nphamcs@gmail.com \
    --cc=vinicius.gomes@intel.com \
    --cc=vkoul@kernel.org \
    --cc=yosry@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox