IB/rxe: Offload CRC calculation when possible
authoryonatanc <yonatanc@mellanox.com>
Thu, 20 Apr 2017 17:55:55 +0000 (20:55 +0300)
committerDoug Ledford <dledford@redhat.com>
Fri, 21 Apr 2017 14:45:02 +0000 (10:45 -0400)
Use CPU ability to perform CRC calculations, by
replacing direct calls to crc32_le() with crypto_shash_updata().

The overall performance gain measured with ib_send_bw tool is 10% and it
was tested on "Intel CPU ES-2660 v2 @ 2.20Ghz" CPU.

ib_send_bw -d rxe0  -x 1 -n 9000 -e  -s $((1024 * 1024 )) -l 100

---------------------------------------------------------------------------------------------
|             | bytes   | iterations | BW peak[MB/sec] | BW average[MB/sec] | MsgRate[Mpps] |
---------------------------------------------------------------------------------------------
| crc32_le    | 1048576 | 9000       | inf             | 497.60             | 0.000498      |
| CRC offload | 1048576 | 9000       | inf             | 546.70             | 0.000547      |
---------------------------------------------------------------------------------------------

Fixes: 8700e3e7c485 ("Soft RoCE driver")
Signed-off-by: Yonatan Cohen <yonatanc@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/sw/rxe/Kconfig
drivers/infiniband/sw/rxe/rxe.c
drivers/infiniband/sw/rxe/rxe.h
drivers/infiniband/sw/rxe/rxe_icrc.c
drivers/infiniband/sw/rxe/rxe_mr.c
drivers/infiniband/sw/rxe/rxe_recv.c
drivers/infiniband/sw/rxe/rxe_req.c
drivers/infiniband/sw/rxe/rxe_verbs.c
drivers/infiniband/sw/rxe/rxe_verbs.h

index 6332dedc11e8a3306697e494ab89996b34d453ab..320bffc980d87d3f6f6e968fdb12d754a3ad7386 100644 (file)
@@ -2,6 +2,7 @@ config RDMA_RXE
        tristate "Software RDMA over Ethernet (RoCE) driver"
        depends on INET && PCI && INFINIBAND
        depends on NET_UDP_TUNNEL
+       depends on CRYPTO_CRC32
        select DMA_VIRT_OPS
        ---help---
        This driver implements the InfiniBand RDMA transport over
index b12dd9b5a89d0a382b17a603eb873488a9bcf16c..cfadd8d8593a74acf6ce958a42f48cb927a75128 100644 (file)
@@ -64,6 +64,8 @@ static void rxe_cleanup(struct rxe_dev *rxe)
        rxe_pool_cleanup(&rxe->mc_elem_pool);
 
        rxe_cleanup_ports(rxe);
+
+       crypto_free_shash(rxe->tfm);
 }
 
 /* called when all references have been dropped */
index a696af81e4a54bf67eeecdd9a5d1d65a977ecc52..ecdba2fce0837675f4a9ae6cddb80c7b1c1c0a3d 100644 (file)
@@ -50,6 +50,7 @@
 #include <rdma/ib_umem.h>
 #include <rdma/ib_cache.h>
 #include <rdma/ib_addr.h>
+#include <crypto/hash.h>
 
 #include "rxe_net.h"
 #include "rxe_opcode.h"
 
 #define RXE_ROCE_V2_SPORT              (0xc000)
 
+static inline u32 rxe_crc32(struct rxe_dev *rxe,
+                           u32 crc, void *next, size_t len)
+{
+       int err;
+
+       SHASH_DESC_ON_STACK(shash, rxe->tfm);
+
+       shash->tfm = rxe->tfm;
+       shash->flags = 0;
+       *(u32 *)shash_desc_ctx(shash) = crc;
+       err = crypto_shash_update(shash, next, len);
+       if (unlikely(err)) {
+               pr_warn_ratelimited("failed crc calculation, err: %d\n", err);
+               return crc32_le(crc, next, len);
+       }
+
+       return *(u32 *)shash_desc_ctx(shash);
+}
+
 int rxe_set_mtu(struct rxe_dev *rxe, unsigned int dev_mtu);
 
 int rxe_add(struct rxe_dev *rxe, unsigned int mtu);
index 413b56b23a068e34b8787e0d0617a99c86ef8868..39e0be31aab153860402cdd22b59d54d06284cff 100644 (file)
@@ -87,10 +87,10 @@ u32 rxe_icrc_hdr(struct rxe_pkt_info *pkt, struct sk_buff *skb)
        bth->qpn |= cpu_to_be32(~BTH_QPN_MASK);
 
        length = hdr_size + RXE_BTH_BYTES;
-       crc = crc32_le(crc, pshdr, length);
+       crc = rxe_crc32(pkt->rxe, crc, pshdr, length);
 
        /* And finish to compute the CRC on the remainder of the headers. */
-       crc = crc32_le(crc, pkt->hdr + RXE_BTH_BYTES,
-                      rxe_opcode[pkt->opcode].length - RXE_BTH_BYTES);
+       crc = rxe_crc32(pkt->rxe, crc, pkt->hdr + RXE_BTH_BYTES,
+                       rxe_opcode[pkt->opcode].length - RXE_BTH_BYTES);
        return crc;
 }
index 37eea7441ca4c42378b8551c34a97255fb40d535..154c3ee211aeb8e85913a20e15c028a4a72dddf8 100644 (file)
@@ -370,7 +370,8 @@ int rxe_mem_copy(struct rxe_mem *mem, u64 iova, void *addr, int length,
                        ((void *)(uintptr_t)iova) : addr;
 
                if (crcp)
-                       *crcp = crc32_le(*crcp, src, length);
+                       crc = rxe_crc32(to_rdev(mem->pd->ibpd.device),
+                                       *crcp, src, length);
 
                memcpy(dest, src, length);
 
@@ -403,7 +404,8 @@ int rxe_mem_copy(struct rxe_mem *mem, u64 iova, void *addr, int length,
                        bytes = length;
 
                if (crcp)
-                       crc = crc32_le(crc, src, bytes);
+                       crc = rxe_crc32(to_rdev(mem->pd->ibpd.device),
+                                       crc, src, bytes);
 
                memcpy(dest, src, bytes);
 
index 5af242fc0178540aa02ef181a91ef7a3dc07d1e1..fb8c83e055e14c653eb1f05f42a3265005d8d737 100644 (file)
@@ -387,8 +387,8 @@ int rxe_rcv(struct sk_buff *skb)
        pack_icrc = be32_to_cpu(*icrcp);
 
        calc_icrc = rxe_icrc_hdr(pkt, skb);
-       calc_icrc = crc32_le(calc_icrc, (u8 *)payload_addr(pkt),
-                            payload_size(pkt));
+       calc_icrc = rxe_crc32(rxe, calc_icrc, (u8 *)payload_addr(pkt),
+                             payload_size(pkt));
        calc_icrc = (__force u32)cpu_to_be32(~calc_icrc);
        if (unlikely(calc_icrc != pack_icrc)) {
                if (skb->protocol == htons(ETH_P_IPV6))
index 9f95f50b290904fe67797cacfa5af2f565e3188d..7ee465d1a1e116a26b721d474946e1e5cd84269d 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include <linux/skbuff.h>
+#include <crypto/hash.h>
 
 #include "rxe.h"
 #include "rxe_loc.h"
@@ -483,8 +484,7 @@ static int fill_packet(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
                if (wqe->wr.send_flags & IB_SEND_INLINE) {
                        u8 *tmp = &wqe->dma.inline_data[wqe->dma.sge_offset];
 
-                       crc = crc32_le(crc, tmp, paylen);
-
+                       crc = rxe_crc32(rxe, crc, tmp, paylen);
                        memcpy(payload_addr(pkt), tmp, paylen);
 
                        wqe->dma.resid -= paylen;
index f75210e478024b692bc259aa3c76602cf24b359d..486035a85bac44f02ff171f9e26e8ee59cb16eaf 100644 (file)
@@ -1322,6 +1322,13 @@ int rxe_register_device(struct rxe_dev *rxe)
        dev->get_hw_stats = rxe_ib_get_hw_stats;
        dev->alloc_hw_stats = rxe_ib_alloc_hw_stats;
 
+       rxe->tfm = crypto_alloc_shash("crc32", 0, 0);
+       if (IS_ERR(rxe->tfm)) {
+               pr_err("failed to allocate crc algorithmi err:%ld",
+                      PTR_ERR(rxe->tfm));
+               return PTR_ERR(rxe->tfm);
+       }
+
        err = ib_register_device(dev, NULL);
        if (err) {
                pr_warn("rxe_register_device failed, err = %d\n", err);
@@ -1342,6 +1349,8 @@ int rxe_register_device(struct rxe_dev *rxe)
 err2:
        ib_unregister_device(dev);
 err1:
+       crypto_free_shash(rxe->tfm);
+
        return err;
 }
 
index 8e0a093f04724e64584ac4f62770cc6b137e3750..5a180fbe40d91b850d5bc83951e9f7901e14b468 100644 (file)
@@ -406,6 +406,7 @@ struct rxe_dev {
 
        struct rxe_port         port;
        struct list_head        list;
+       struct crypto_shash     *tfm;
 };
 
 static inline void rxe_counter_inc(struct rxe_dev *rxe, enum rxe_counters cnt)