Commit 426370c8 authored by Eric Biggers's avatar Eric Biggers Committed by Leon Romanovsky
Browse files

RDMA/siw: Switch to using the crc32c library



Now that the crc32c() library function directly takes advantage of
architecture-specific optimizations, it is unnecessary to go through the
crypto API.  Just use crc32c().  This is much simpler, and it improves
performance due to eliminating the crypto API overhead.

Signed-off-by: default avatarEric Biggers <ebiggers@google.com>
Link: https://patch.msgid.link/20250227051207.19470-1-ebiggers@kernel.org


Acked-by: default avatarBernard Metzler <bmt@zurich.ibm.com>
Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
parent 230804a8
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -2,9 +2,7 @@ config RDMA_SIW
	tristate "Software RDMA over TCP/IP (iWARP) driver"
	depends on INET && INFINIBAND
	depends on INFINIBAND_VIRT_DMA
	select LIBCRC32C
	select CRYPTO
	select CRYPTO_CRC32C
	select CRC32
	help
	This driver implements the iWARP RDMA transport over
	the Linux TCP/IP network stack. It enables a system with a
+31 −6
Original line number Diff line number Diff line
@@ -10,9 +10,9 @@
#include <rdma/restrack.h>
#include <linux/socket.h>
#include <linux/skbuff.h>
#include <crypto/hash.h>
#include <linux/crc32.h>
#include <linux/crc32c.h>
#include <linux/unaligned.h>

#include <rdma/siw-abi.h>
#include "iwarp.h"
@@ -289,7 +289,8 @@ struct siw_rx_stream {

	union iwarp_hdr hdr;
	struct mpa_trailer trailer;
	struct shash_desc *mpa_crc_hd;
	u32 mpa_crc;
	bool mpa_crc_enabled;

	/*
	 * For each FPDU, main RX loop runs through 3 stages:
@@ -390,7 +391,8 @@ struct siw_iwarp_tx {
	int burst;
	int bytes_unsent; /* ddp payload bytes */

	struct shash_desc *mpa_crc_hd;
	u32 mpa_crc;
	bool mpa_crc_enabled;

	u8 do_crc : 1; /* do crc for segment */
	u8 use_sendpage : 1; /* send w/o copy */
@@ -496,7 +498,6 @@ extern u_char mpa_version;
extern const bool peer_to_peer;
extern struct task_struct *siw_tx_thread[];

extern struct crypto_shash *siw_crypto_shash;
extern struct iwarp_msg_info iwarp_pktinfo[RDMAP_TERMINATE + 1];

/* QP general functions */
@@ -668,6 +669,30 @@ static inline struct siw_sqe *irq_alloc_free(struct siw_qp *qp)
	return NULL;
}

static inline void siw_crc_init(u32 *crc)
{
	*crc = ~0;
}

static inline void siw_crc_update(u32 *crc, const void *data, size_t len)
{
	*crc = crc32c(*crc, data, len);
}

static inline void siw_crc_final(u32 *crc, u8 out[4])
{
	put_unaligned_le32(~*crc, out);
}

static inline void siw_crc_oneshot(const void *data, size_t len, u8 out[4])
{
	u32 crc;

	siw_crc_init(&crc);
	siw_crc_update(&crc, data, len);
	return siw_crc_final(&crc, out);
}

static inline __wsum siw_csum_update(const void *buff, int len, __wsum sum)
{
	return (__force __wsum)crc32c((__force __u32)sum, buff, len);
@@ -686,11 +711,11 @@ static inline void siw_crc_skb(struct siw_rx_stream *srx, unsigned int len)
		.update = siw_csum_update,
		.combine = siw_csum_combine,
	};
	__wsum crc = *(u32 *)shash_desc_ctx(srx->mpa_crc_hd);
	__wsum crc = (__force __wsum)srx->mpa_crc;

	crc = __skb_checksum(srx->skb, srx->skb_offset, len, crc,
			     &siw_cs_ops);
	*(u32 *)shash_desc_ctx(srx->mpa_crc_hd) = crc;
	srx->mpa_crc = (__force u32)crc;
}

#define siw_dbg(ibdev, fmt, ...)                                               \
+1 −21
Original line number Diff line number Diff line
@@ -59,7 +59,6 @@ u_char mpa_version = MPA_REVISION_2;
const bool peer_to_peer;

struct task_struct *siw_tx_thread[NR_CPUS];
struct crypto_shash *siw_crypto_shash;

static int siw_device_register(struct siw_device *sdev, const char *name)
{
@@ -467,20 +466,7 @@ static __init int siw_init_module(void)
		rv = -ENOMEM;
		goto out_error;
	}
	/*
	 * Locate CRC32 algorithm. If unsuccessful, fail
	 * loading siw only, if CRC is required.
	 */
	siw_crypto_shash = crypto_alloc_shash("crc32c", 0, 0);
	if (IS_ERR(siw_crypto_shash)) {
		pr_info("siw: Loading CRC32c failed: %ld\n",
			PTR_ERR(siw_crypto_shash));
		siw_crypto_shash = NULL;
		if (mpa_crc_required) {
			rv = -EOPNOTSUPP;
			goto out_error;
		}
	}

	rv = register_netdevice_notifier(&siw_netdev_nb);
	if (rv)
		goto out_error;
@@ -493,9 +479,6 @@ static __init int siw_init_module(void)
out_error:
	siw_stop_tx_threads();

	if (siw_crypto_shash)
		crypto_free_shash(siw_crypto_shash);

	pr_info("SoftIWARP attach failed. Error: %d\n", rv);

	siw_cm_exit();
@@ -516,9 +499,6 @@ static void __exit siw_exit_module(void)

	siw_destroy_cpulist(siw_cpu_info.num_nodes);

	if (siw_crypto_shash)
		crypto_free_shash(siw_crypto_shash);

	pr_info("SoftiWARP detached\n");
}

+11 −43
Original line number Diff line number Diff line
@@ -226,33 +226,6 @@ static int siw_qp_readq_init(struct siw_qp *qp, int irq_size, int orq_size)
	return 0;
}

static int siw_qp_enable_crc(struct siw_qp *qp)
{
	struct siw_rx_stream *c_rx = &qp->rx_stream;
	struct siw_iwarp_tx *c_tx = &qp->tx_ctx;
	int size;

	if (siw_crypto_shash == NULL)
		return -ENOENT;

	size = crypto_shash_descsize(siw_crypto_shash) +
		sizeof(struct shash_desc);

	c_tx->mpa_crc_hd = kzalloc(size, GFP_KERNEL);
	c_rx->mpa_crc_hd = kzalloc(size, GFP_KERNEL);
	if (!c_tx->mpa_crc_hd || !c_rx->mpa_crc_hd) {
		kfree(c_tx->mpa_crc_hd);
		kfree(c_rx->mpa_crc_hd);
		c_tx->mpa_crc_hd = NULL;
		c_rx->mpa_crc_hd = NULL;
		return -ENOMEM;
	}
	c_tx->mpa_crc_hd->tfm = siw_crypto_shash;
	c_rx->mpa_crc_hd->tfm = siw_crypto_shash;

	return 0;
}

/*
 * Send a non signalled READ or WRITE to peer side as negotiated
 * with MPAv2 P2P setup protocol. The work request is only created
@@ -583,20 +556,15 @@ void siw_send_terminate(struct siw_qp *qp)

	term->ctrl.mpa_len =
		cpu_to_be16(len_terminate - (MPA_HDR_SIZE + MPA_CRC_SIZE));
	if (qp->tx_ctx.mpa_crc_hd) {
		crypto_shash_init(qp->tx_ctx.mpa_crc_hd);
		if (crypto_shash_update(qp->tx_ctx.mpa_crc_hd,
					(u8 *)iov[0].iov_base,
					iov[0].iov_len))
			goto out;

	if (qp->tx_ctx.mpa_crc_enabled) {
		siw_crc_init(&qp->tx_ctx.mpa_crc);
		siw_crc_update(&qp->tx_ctx.mpa_crc,
			       iov[0].iov_base, iov[0].iov_len);
		if (num_frags == 3) {
			if (crypto_shash_update(qp->tx_ctx.mpa_crc_hd,
						(u8 *)iov[1].iov_base,
						iov[1].iov_len))
				goto out;
			siw_crc_update(&qp->tx_ctx.mpa_crc,
				       iov[1].iov_base, iov[1].iov_len);
		}
		crypto_shash_final(qp->tx_ctx.mpa_crc_hd, (u8 *)&crc);
		siw_crc_final(&qp->tx_ctx.mpa_crc, (u8 *)&crc);
	}

	rv = kernel_sendmsg(s, &msg, iov, num_frags, len_terminate);
@@ -604,7 +572,6 @@ void siw_send_terminate(struct siw_qp *qp)
		   rv == len_terminate ? "success" : "failure",
		   __rdmap_term_layer(term), __rdmap_term_etype(term),
		   __rdmap_term_ecode(term), rv);
out:
	kfree(term);
	kfree(err_hdr);
}
@@ -643,9 +610,10 @@ static int siw_qp_nextstate_from_idle(struct siw_qp *qp,
	switch (attrs->state) {
	case SIW_QP_STATE_RTS:
		if (attrs->flags & SIW_MPA_CRC) {
			rv = siw_qp_enable_crc(qp);
			if (rv)
				break;
			siw_crc_init(&qp->tx_ctx.mpa_crc);
			qp->tx_ctx.mpa_crc_enabled = true;
			siw_crc_init(&qp->rx_stream.mpa_crc);
			qp->rx_stream.mpa_crc_enabled = true;
		}
		if (!(mask & SIW_QP_ATTR_LLP_HANDLE)) {
			siw_dbg_qp(qp, "no socket\n");
+11 −12
Original line number Diff line number Diff line
@@ -67,10 +67,10 @@ static int siw_rx_umem(struct siw_rx_stream *srx, struct siw_umem *umem,

			return -EFAULT;
		}
		if (srx->mpa_crc_hd) {
		if (srx->mpa_crc_enabled) {
			if (rdma_is_kernel_res(&rx_qp(srx)->base_qp.res)) {
				crypto_shash_update(srx->mpa_crc_hd,
					(u8 *)(dest + pg_off), bytes);
				siw_crc_update(&srx->mpa_crc, dest + pg_off,
					       bytes);
				kunmap_atomic(dest);
			} else {
				kunmap_atomic(dest);
@@ -114,8 +114,8 @@ static int siw_rx_kva(struct siw_rx_stream *srx, void *kva, int len)

		return rv;
	}
	if (srx->mpa_crc_hd)
		crypto_shash_update(srx->mpa_crc_hd, (u8 *)kva, len);
	if (srx->mpa_crc_enabled)
		siw_crc_update(&srx->mpa_crc, kva, len);

	srx->skb_offset += len;
	srx->skb_copied += len;
@@ -966,16 +966,16 @@ static int siw_get_trailer(struct siw_qp *qp, struct siw_rx_stream *srx)
	if (srx->fpdu_part_rem)
		return -EAGAIN;

	if (!srx->mpa_crc_hd)
	if (!srx->mpa_crc_enabled)
		return 0;

	if (srx->pad)
		crypto_shash_update(srx->mpa_crc_hd, tbuf, srx->pad);
		siw_crc_update(&srx->mpa_crc, tbuf, srx->pad);
	/*
	 * CRC32 is computed, transmitted and received directly in NBO,
	 * so there's never a reason to convert byte order.
	 */
	crypto_shash_final(srx->mpa_crc_hd, (u8 *)&crc_own);
	siw_crc_final(&srx->mpa_crc, (u8 *)&crc_own);
	crc_in = (__force __wsum)srx->trailer.crc;

	if (unlikely(crc_in != crc_own)) {
@@ -1093,13 +1093,12 @@ static int siw_get_hdr(struct siw_rx_stream *srx)
	 * (tagged/untagged). E.g., a WRITE can get intersected by a SEND,
	 * but not by a READ RESPONSE etc.
	 */
	if (srx->mpa_crc_hd) {
	if (srx->mpa_crc_enabled) {
		/*
		 * Restart CRC computation
		 */
		crypto_shash_init(srx->mpa_crc_hd);
		crypto_shash_update(srx->mpa_crc_hd, (u8 *)c_hdr,
				    srx->fpdu_part_rcvd);
		siw_crc_init(&srx->mpa_crc);
		siw_crc_update(&srx->mpa_crc, c_hdr, srx->fpdu_part_rcvd);
	}
	if (frx->more_ddp_segs) {
		frx->first_ddp_seg = 0;
Loading