Skip to content

Commit

Permalink
RDMA/siw: Switch to using the crc32c library
Browse files Browse the repository at this point in the history
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: Eric Biggers <ebiggers@google.com>
Link: https://patch.msgid.link/20250227051207.19470-1-ebiggers@kernel.org
Acked-by: Bernard Metzler <bmt@zurich.ibm.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
  • Loading branch information
Eric Biggers authored and Leon Romanovsky committed Mar 3, 2025
1 parent 230804a commit 426370c
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 113 deletions.
4 changes: 1 addition & 3 deletions drivers/infiniband/sw/siw/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
37 changes: 31 additions & 6 deletions drivers/infiniband/sw/siw/siw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand All @@ -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, ...) \
Expand Down
22 changes: 1 addition & 21 deletions drivers/infiniband/sw/siw/siw_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand All @@ -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();
Expand All @@ -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");
}

Expand Down
54 changes: 11 additions & 43 deletions drivers/infiniband/sw/siw/siw_qp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -583,28 +556,22 @@ 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);
siw_dbg_qp(qp, "sent TERM: %s, layer %d, type %d, code %d (%d bytes)\n",
rv == len_terminate ? "success" : "failure",
__rdmap_term_layer(term), __rdmap_term_etype(term),
__rdmap_term_ecode(term), rv);
out:
kfree(term);
kfree(err_hdr);
}
Expand Down Expand Up @@ -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");
Expand Down
23 changes: 11 additions & 12 deletions drivers/infiniband/sw/siw/siw_qp_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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;
Expand Down
44 changes: 19 additions & 25 deletions drivers/infiniband/sw/siw/siw_qp_tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -248,10 +248,8 @@ static int siw_qp_prepare_tx(struct siw_iwarp_tx *c_tx)
/*
* Do complete CRC if enabled and short packet
*/
if (c_tx->mpa_crc_hd &&
crypto_shash_digest(c_tx->mpa_crc_hd, (u8 *)&c_tx->pkt,
c_tx->ctrl_len, (u8 *)crc) != 0)
return -EINVAL;
if (c_tx->mpa_crc_enabled)
siw_crc_oneshot(&c_tx->pkt, c_tx->ctrl_len, (u8 *)crc);
c_tx->ctrl_len += MPA_CRC_SIZE;

return PKT_COMPLETE;
Expand Down Expand Up @@ -482,9 +480,8 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
iov[seg].iov_len = sge_len;

if (do_crc)
crypto_shash_update(c_tx->mpa_crc_hd,
iov[seg].iov_base,
sge_len);
siw_crc_update(&c_tx->mpa_crc,
iov[seg].iov_base, sge_len);
sge_off += sge_len;
data_len -= sge_len;
seg++;
Expand Down Expand Up @@ -516,15 +513,14 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
iov[seg].iov_len = plen;

if (do_crc)
crypto_shash_update(
c_tx->mpa_crc_hd,
siw_crc_update(
&c_tx->mpa_crc,
iov[seg].iov_base,
plen);
} else if (do_crc) {
kaddr = kmap_local_page(p);
crypto_shash_update(c_tx->mpa_crc_hd,
kaddr + fp_off,
plen);
siw_crc_update(&c_tx->mpa_crc,
kaddr + fp_off, plen);
kunmap_local(kaddr);
}
} else {
Expand All @@ -536,10 +532,9 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)

page_array[seg] = ib_virt_dma_to_page(va);
if (do_crc)
crypto_shash_update(
c_tx->mpa_crc_hd,
ib_virt_dma_to_ptr(va),
plen);
siw_crc_update(&c_tx->mpa_crc,
ib_virt_dma_to_ptr(va),
plen);
}

sge_len -= plen;
Expand Down Expand Up @@ -576,14 +571,14 @@ static int siw_tx_hdt(struct siw_iwarp_tx *c_tx, struct socket *s)
if (c_tx->pad) {
*(u32 *)c_tx->trailer.pad = 0;
if (do_crc)
crypto_shash_update(c_tx->mpa_crc_hd,
(u8 *)&c_tx->trailer.crc - c_tx->pad,
c_tx->pad);
siw_crc_update(&c_tx->mpa_crc,
(u8 *)&c_tx->trailer.crc - c_tx->pad,
c_tx->pad);
}
if (!c_tx->mpa_crc_hd)
if (!c_tx->mpa_crc_enabled)
c_tx->trailer.crc = 0;
else if (do_crc)
crypto_shash_final(c_tx->mpa_crc_hd, (u8 *)&c_tx->trailer.crc);
siw_crc_final(&c_tx->mpa_crc, (u8 *)&c_tx->trailer.crc);

data_len = c_tx->bytes_unsent;

Expand Down Expand Up @@ -736,10 +731,9 @@ static void siw_prepare_fpdu(struct siw_qp *qp, struct siw_wqe *wqe)
/*
* Init MPA CRC computation
*/
if (c_tx->mpa_crc_hd) {
crypto_shash_init(c_tx->mpa_crc_hd);
crypto_shash_update(c_tx->mpa_crc_hd, (u8 *)&c_tx->pkt,
c_tx->ctrl_len);
if (c_tx->mpa_crc_enabled) {
siw_crc_init(&c_tx->mpa_crc);
siw_crc_update(&c_tx->mpa_crc, &c_tx->pkt, c_tx->ctrl_len);
c_tx->do_crc = 1;
}
}
Expand Down
3 changes: 0 additions & 3 deletions drivers/infiniband/sw/siw/siw_verbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,9 +631,6 @@ int siw_destroy_qp(struct ib_qp *base_qp, struct ib_udata *udata)
}
up_write(&qp->state_lock);

kfree(qp->tx_ctx.mpa_crc_hd);
kfree(qp->rx_stream.mpa_crc_hd);

qp->scq = qp->rcq = NULL;

siw_qp_put(qp);
Expand Down

0 comments on commit 426370c

Please sign in to comment.