diff mbox series

[net,V2] Crypto/chcr: Registering cxgb4 to xfrmdev_ops

Message ID 20200724084124.21651-1-ayush.sawal@chelsio.com
State Changes Requested
Delegated to: David Miller
Headers show
Series [net,V2] Crypto/chcr: Registering cxgb4 to xfrmdev_ops | expand

Commit Message

Ayush Sawal July 24, 2020, 8:41 a.m. UTC
As chcr was removed without clearing xfrmdev_ops and netdev
feature(esp-hw-offload). When a recalculation of netdev feature is
triggered by changing tls feature(tls-hw-tx-offload) from user request,
it causes a page fault due to absence of valid xfrmdev_ops.

So fixing this by registering chcr_xfrmdev_ops with cxgb4.

V1->V2

-Added checks for CONFIG_CHELSIO_IPSEC_INLINE and
 CONFIG_CHELSIO_TLS_DEVICE options in chcr_offload_state(),
 to fix compilation errors, when kernel is compiled without
 this options.

   drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c: In function
'chcr_offload_state':
>> drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:6081:35: error:
>> 'struct cxgb4_uld_info' has no member named 'tlsdev_ops'
    6081 |   if (!adap->uld[CXGB4_ULD_CRYPTO].tlsdev_ops) {
         |                                   ^
>> drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c:6088:35: error:
>> 'struct cxgb4_uld_info' has no member named 'xfrmdev_ops'
    6088 |   if (!adap->uld[CXGB4_ULD_CRYPTO].xfrmdev_ops) {

Fixes: 6dad4e8ab3ec ("chcr: Add support for Inline IPSec")
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Ayush Sawal <ayush.sawal@chelsio.com>
---
 drivers/crypto/chelsio/chcr_core.c            |  35 ++--
 drivers/crypto/chelsio/chcr_core.h            |   7 +
 drivers/crypto/chelsio/chcr_ipsec.c           |  41 +----
 drivers/net/ethernet/chelsio/cxgb4/cxgb4.h    |   5 +
 .../net/ethernet/chelsio/cxgb4/cxgb4_main.c   | 158 +++++++++++++++---
 .../net/ethernet/chelsio/cxgb4/cxgb4_uld.h    |   3 +
 6 files changed, 168 insertions(+), 81 deletions(-)

Comments

David Miller July 25, 2020, 12:01 a.m. UTC | #1
Please start submitting chcr patches to the crypto subsystem, where it
belongs, instead of the networking GIT trees.

This has been going on for far too long.

Thank you.
Herbert Xu July 25, 2020, 6:20 a.m. UTC | #2
On Fri, Jul 24, 2020 at 05:01:08PM -0700, David Miller wrote:
> 
> Please start submitting chcr patches to the crypto subsystem, where it
> belongs, instead of the networking GIT trees.

Hi Dave:

I think this patch belongs to the networking tree.  The reason is
that it's related to xfrm offload which has nothing to do with the
Crypto API.

Do xfrm offload drivers usually go through the networking tree or
would it be better directed through the xfrm tree?

There's really nobody on the crypto mailing list who could give
this the proper review that it deserves.

Of course I'm happy to continue taking anything that touches
chcr_algo.c as that resides wholly within the Crypto API.

Cheers,
Steffen Klassert July 27, 2020, 9:16 a.m. UTC | #3
On Sat, Jul 25, 2020 at 04:20:34PM +1000, Herbert Xu wrote:
> On Fri, Jul 24, 2020 at 05:01:08PM -0700, David Miller wrote:
> > 
> > Please start submitting chcr patches to the crypto subsystem, where it
> > belongs, instead of the networking GIT trees.
> 
> Hi Dave:
> 
> I think this patch belongs to the networking tree.  The reason is
> that it's related to xfrm offload which has nothing to do with the
> Crypto API.

Hm, I think some of this code is just misplaced under drivers/crypto.
All functions in 'drivers/crypto/chelsio/chcr_ipsec.c' implement
networking (IPsec). So it should be under drivers/net, then it
can be merged via the net or net-next tree as usual for network
drivers.

> Do xfrm offload drivers usually go through the networking tree or
> would it be better directed through the xfrm tree?

The drivers go through the networking trees, and I think it should
stay like this. Otherwise we would create needless merge conflicts.
Ayush Sawal July 27, 2020, 9:59 a.m. UTC | #4
On 7/27/2020 2:46 PM, Steffen Klassert wrote:
> On Sat, Jul 25, 2020 at 04:20:34PM +1000, Herbert Xu wrote:
>> On Fri, Jul 24, 2020 at 05:01:08PM -0700, David Miller wrote:
>>> Please start submitting chcr patches to the crypto subsystem, where it
>>> belongs, instead of the networking GIT trees.
>> Hi Dave:
>>
>> I think this patch belongs to the networking tree.  The reason is
>> that it's related to xfrm offload which has nothing to do with the
>> Crypto API.
> Hm, I think some of this code is just misplaced under drivers/crypto.
> All functions in 'drivers/crypto/chelsio/chcr_ipsec.c' implement
> networking (IPsec). So it should be under drivers/net, then it
> can be merged via the net or net-next tree as usual for network
> drivers.

Ok,
We have started the work towards shifting inline ipsec, nic tls & chtls 
code present in drivers/crypto/chelsio/ into 
drivers/net/ethernet/chelsio/. Only co-processor code will exist in the 
drivers/crypto/chelsio directory.

Thanks,
Ayush

>> Do xfrm offload drivers usually go through the networking tree or
>> would it be better directed through the xfrm tree?
> The drivers go through the networking trees, and I think it should
> stay like this. Otherwise we would create needless merge conflicts.
>
Vinay Kumar Yadav July 28, 2020, 1:01 p.m. UTC | #5
Hi Herbert, David

On 7/27/2020 3:29 PM, Ayush Sawal wrote:
> 
> On 7/27/2020 2:46 PM, Steffen Klassert wrote:
>> On Sat, Jul 25, 2020 at 04:20:34PM +1000, Herbert Xu wrote:
>>> On Fri, Jul 24, 2020 at 05:01:08PM -0700, David Miller wrote:
>>>> Please start submitting chcr patches to the crypto subsystem, where it
>>>> belongs, instead of the networking GIT trees.
>>> Hi Dave:
>>>
>>> I think this patch belongs to the networking tree.  The reason is
>>> that it's related to xfrm offload which has nothing to do with the
>>> Crypto API.
>> Hm, I think some of this code is just misplaced under drivers/crypto.
>> All functions in 'drivers/crypto/chelsio/chcr_ipsec.c' implement
>> networking (IPsec). So it should be under drivers/net, then it
>> can be merged via the net or net-next tree as usual for network
>> drivers.
> 
> Ok,
> We have started the work towards shifting inline ipsec, nic tls & chtls 
> code present in drivers/crypto/chelsio/ into 
> drivers/net/ethernet/chelsio/. Only co-processor code will exist in the 
> drivers/crypto/chelsio directory.
> 
> Thanks,
> Ayush
> 

In the process of moving inline tls stuff from crypto to net, we have
directory structure change.
Can you please suggest correct tree to submit changes to avoid merge 
conflicts ?

Here is the file diff stats:

MAINTAINERS                                   |  9 ++
drivers/crypto/chelsio/Kconfig                | 11 ---
drivers/crypto/chelsio/Makefile               |  1 -
drivers/crypto/chelsio/chcr_algo.h            | 33 -------
drivers/crypto/chelsio/chcr_core.h            | 53 ------------
drivers/net/ethernet/chelsio/Kconfig          | 11 +++
drivers/net/ethernet/chelsio/Makefile         |  1 +
.../ethernet}/chelsio/chtls/Makefile          |  0
.../ethernet}/chelsio/chtls/chtls.h           | 86 +++++++++++++++++++
.../ethernet}/chelsio/chtls/chtls_cm.c        |  0
.../ethernet}/chelsio/chtls/chtls_cm.h        |  0
.../ethernet}/chelsio/chtls/chtls_hw.c        |  0
.../ethernet}/chelsio/chtls/chtls_io.c        |  0
.../ethernet}/chelsio/chtls/chtls_main.c      |  0
14 files changed, 107 insertions(+), 98 deletions(-)
rename drivers/{crypto => net/ethernet}/chelsio/chtls/Makefile (100%)
rename drivers/{crypto => net/ethernet}/chelsio/chtls/chtls.h (81%)
rename drivers/{crypto => net/ethernet}/chelsio/chtls/chtls_cm.c (100%)
rename drivers/{crypto => net/ethernet}/chelsio/chtls/chtls_cm.h (100%)
rename drivers/{crypto => net/ethernet}/chelsio/chtls/chtls_hw.c (100%)
rename drivers/{crypto => net/ethernet}/chelsio/chtls/chtls_io.c (100%)
rename drivers/{crypto => net/ethernet}/chelsio/chtls/chtls_main.c (100%)


>>> Do xfrm offload drivers usually go through the networking tree or
>>> would it be better directed through the xfrm tree?
>> The drivers go through the networking trees, and I think it should
>> stay like this. Otherwise we would create needless merge conflicts.
>>
David Miller July 29, 2020, 12:18 a.m. UTC | #6
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Sat, 25 Jul 2020 16:20:34 +1000

> I think this patch belongs to the networking tree.  The reason is
> that it's related to xfrm offload which has nothing to do with the
> Crypto API.
> 
> Do xfrm offload drivers usually go through the networking tree or
> would it be better directed through the xfrm tree?
> 
> There's really nobody on the crypto mailing list who could give
> this the proper review that it deserves.
> 
> Of course I'm happy to continue taking anything that touches
> chcr_algo.c as that resides wholly within the Crypto API.

Meanwhile it looks like the restructuring effort is underway so
hopefully this is less painful in the future.
diff mbox series

Patch

diff --git a/drivers/crypto/chelsio/chcr_core.c b/drivers/crypto/chelsio/chcr_core.c
index bd8dac806e7a..c8aa2d1a5664 100644
--- a/drivers/crypto/chelsio/chcr_core.c
+++ b/drivers/crypto/chelsio/chcr_core.c
@@ -41,7 +41,13 @@  static const struct tlsdev_ops chcr_ktls_ops = {
 #endif
 
 #ifdef CONFIG_CHELSIO_IPSEC_INLINE
-static void update_netdev_features(void);
+static const struct xfrmdev_ops chcr_xfrmdev_ops = {
+	.xdo_dev_state_add      = chcr_xfrm_add_state,
+	.xdo_dev_state_delete   = chcr_xfrm_del_state,
+	.xdo_dev_state_free     = chcr_xfrm_free_state,
+	.xdo_dev_offload_ok     = chcr_ipsec_offload_ok,
+	.xdo_dev_state_advance_esn = chcr_advance_esn_state,
+};
 #endif /* CONFIG_CHELSIO_IPSEC_INLINE */
 
 static chcr_handler_func work_handlers[NUM_CPL_CMDS] = {
@@ -66,6 +72,9 @@  static struct cxgb4_uld_info chcr_uld_info = {
 #if defined(CONFIG_CHELSIO_TLS_DEVICE)
 	.tlsdev_ops = &chcr_ktls_ops,
 #endif
+#if defined(CONFIG_CHELSIO_IPSEC_INLINE)
+	.xfrmdev_ops = &chcr_xfrmdev_ops,
+#endif
 };
 
 static void detach_work_fn(struct work_struct *work)
@@ -305,24 +314,6 @@  static int chcr_uld_state_change(void *handle, enum cxgb4_state state)
 	return ret;
 }
 
-#ifdef CONFIG_CHELSIO_IPSEC_INLINE
-static void update_netdev_features(void)
-{
-	struct uld_ctx *u_ctx, *tmp;
-
-	mutex_lock(&drv_data.drv_mutex);
-	list_for_each_entry_safe(u_ctx, tmp, &drv_data.inact_dev, entry) {
-		if (u_ctx->lldi.crypto & ULP_CRYPTO_IPSEC_INLINE)
-			chcr_add_xfrmops(&u_ctx->lldi);
-	}
-	list_for_each_entry_safe(u_ctx, tmp, &drv_data.act_dev, entry) {
-		if (u_ctx->lldi.crypto & ULP_CRYPTO_IPSEC_INLINE)
-			chcr_add_xfrmops(&u_ctx->lldi);
-	}
-	mutex_unlock(&drv_data.drv_mutex);
-}
-#endif /* CONFIG_CHELSIO_IPSEC_INLINE */
-
 static int __init chcr_crypto_init(void)
 {
 	INIT_LIST_HEAD(&drv_data.act_dev);
@@ -332,12 +323,6 @@  static int __init chcr_crypto_init(void)
 	drv_data.last_dev = NULL;
 	cxgb4_register_uld(CXGB4_ULD_CRYPTO, &chcr_uld_info);
 
-	#ifdef CONFIG_CHELSIO_IPSEC_INLINE
-	rtnl_lock();
-	update_netdev_features();
-	rtnl_unlock();
-	#endif /* CONFIG_CHELSIO_IPSEC_INLINE */
-
 	return 0;
 }
 
diff --git a/drivers/crypto/chelsio/chcr_core.h b/drivers/crypto/chelsio/chcr_core.h
index 67d77abd6775..098017b5bb9f 100644
--- a/drivers/crypto/chelsio/chcr_core.h
+++ b/drivers/crypto/chelsio/chcr_core.h
@@ -235,4 +235,11 @@  extern void chcr_ktls_dev_del(struct net_device *netdev,
 			      struct tls_context *tls_ctx,
 			      enum tls_offload_ctx_dir direction);
 #endif
+#ifdef CONFIG_CHELSIO_IPSEC_INLINE
+int chcr_xfrm_add_state(struct xfrm_state *x);
+void chcr_xfrm_del_state(struct xfrm_state *x);
+void chcr_xfrm_free_state(struct xfrm_state *x);
+bool chcr_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x);
+void chcr_advance_esn_state(struct xfrm_state *x);
+#endif /* CONFIG_CHELSIO_IPSEC_INLINE */
 #endif /* __CHCR_CORE_H__ */
diff --git a/drivers/crypto/chelsio/chcr_ipsec.c b/drivers/crypto/chelsio/chcr_ipsec.c
index 967babd67a51..9f2e3cf2c4b3 100644
--- a/drivers/crypto/chelsio/chcr_ipsec.c
+++ b/drivers/crypto/chelsio/chcr_ipsec.c
@@ -71,37 +71,6 @@ 
 #define MAX_IMM_TX_PKT_LEN 256
 #define GCM_ESP_IV_SIZE     8
 
-static int chcr_xfrm_add_state(struct xfrm_state *x);
-static void chcr_xfrm_del_state(struct xfrm_state *x);
-static void chcr_xfrm_free_state(struct xfrm_state *x);
-static bool chcr_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x);
-static void chcr_advance_esn_state(struct xfrm_state *x);
-
-static const struct xfrmdev_ops chcr_xfrmdev_ops = {
-	.xdo_dev_state_add      = chcr_xfrm_add_state,
-	.xdo_dev_state_delete   = chcr_xfrm_del_state,
-	.xdo_dev_state_free     = chcr_xfrm_free_state,
-	.xdo_dev_offload_ok     = chcr_ipsec_offload_ok,
-	.xdo_dev_state_advance_esn = chcr_advance_esn_state,
-};
-
-/* Add offload xfrms to Chelsio Interface */
-void chcr_add_xfrmops(const struct cxgb4_lld_info *lld)
-{
-	struct net_device *netdev = NULL;
-	int i;
-
-	for (i = 0; i < lld->nports; i++) {
-		netdev = lld->ports[i];
-		if (!netdev)
-			continue;
-		netdev->xfrmdev_ops = &chcr_xfrmdev_ops;
-		netdev->hw_enc_features |= NETIF_F_HW_ESP;
-		netdev->features |= NETIF_F_HW_ESP;
-		netdev_change_features(netdev);
-	}
-}
-
 static inline int chcr_ipsec_setauthsize(struct xfrm_state *x,
 					 struct ipsec_sa_entry *sa_entry)
 {
@@ -189,7 +158,7 @@  static inline int chcr_ipsec_setkey(struct xfrm_state *x,
  * returns 0 on success, negative error if failed to send message to FPGA
  * positive error if FPGA returned a bad response
  */
-static int chcr_xfrm_add_state(struct xfrm_state *x)
+int chcr_xfrm_add_state(struct xfrm_state *x)
 {
 	struct ipsec_sa_entry *sa_entry;
 	int res = 0;
@@ -263,14 +232,14 @@  static int chcr_xfrm_add_state(struct xfrm_state *x)
 	return res;
 }
 
-static void chcr_xfrm_del_state(struct xfrm_state *x)
+void chcr_xfrm_del_state(struct xfrm_state *x)
 {
 	/* do nothing */
 	if (!x->xso.offload_handle)
 		return;
 }
 
-static void chcr_xfrm_free_state(struct xfrm_state *x)
+void chcr_xfrm_free_state(struct xfrm_state *x)
 {
 	struct ipsec_sa_entry *sa_entry;
 
@@ -282,7 +251,7 @@  static void chcr_xfrm_free_state(struct xfrm_state *x)
 	module_put(THIS_MODULE);
 }
 
-static bool chcr_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
+bool chcr_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
 {
 	if (x->props.family == AF_INET) {
 		/* Offload with IP options is not supported yet */
@@ -296,7 +265,7 @@  static bool chcr_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
 	return true;
 }
 
-static void chcr_advance_esn_state(struct xfrm_state *x)
+void chcr_advance_esn_state(struct xfrm_state *x)
 {
 	/* do nothing */
 	if (!x->xso.offload_handle)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index cf69c6edcfec..9e947d64d146 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -139,6 +139,11 @@  enum cc_fec {
 	FEC_BASER_RS  = 1 << 2   /* BaseR/Reed-Solomon */
 };
 
+enum cxgb4_netdev_tls_ops {
+	CXGB4_TLSDEV_OPS  = 1,
+	CXGB4_XFRMDEV_OPS
+};
+
 struct port_stats {
 	u64 tx_octets;            /* total # of octets in good frames */
 	u64 tx_frames;            /* all good frames */
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 0329a6b52087..72b32963b43d 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -6068,6 +6068,46 @@  static int cxgb4_iov_configure(struct pci_dev *pdev, int num_vfs)
 }
 #endif /* CONFIG_PCI_IOV */
 
+#if defined(CONFIG_CHELSIO_TLS_DEVICE) || defined(CONFIG_CHELSIO_IPSEC_INLINE)
+
+static int chcr_offload_state(struct adapter *adap,
+			      enum cxgb4_netdev_tls_ops op_val)
+{
+	if (!adap->uld[CXGB4_ULD_CRYPTO].handle) {
+		dev_dbg(adap->pdev_dev, "chcr driver is not loaded\n");
+			return -EOPNOTSUPP;
+	}
+
+	switch (op_val) {
+#if defined(CONFIG_CHELSIO_TLS_DEVICE)
+	case CXGB4_TLSDEV_OPS:
+		if (!adap->uld[CXGB4_ULD_CRYPTO].tlsdev_ops) {
+			dev_dbg(adap->pdev_dev,
+				"chcr driver has no registered tlsdev_ops\n");
+			return -EOPNOTSUPP;
+		}
+		break;
+#endif /* CONFIG_CHELSIO_TLS_DEVICE */
+#if defined(CONFIG_CHELSIO_IPSEC_INLINE)
+	case CXGB4_XFRMDEV_OPS:
+		if (!adap->uld[CXGB4_ULD_CRYPTO].xfrmdev_ops) {
+			dev_dbg(adap->pdev_dev,
+				"chcr driver has no registered xfrmdev_ops\n");
+			return -EOPNOTSUPP;
+		}
+		break;
+#endif /* CONFIG_CHELSIO_IPSEC_INLINE */
+	default:
+		dev_dbg(adap->pdev_dev,
+			"chcr driver has no support for offload %d\n", op_val);
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+#endif /* CONFIG_CHELSIO_TLS_DEVICE || CONFIG_CHELSIO_IPSEC_INLINE */
+
 #if defined(CONFIG_CHELSIO_TLS_DEVICE)
 
 static int cxgb4_ktls_dev_add(struct net_device *netdev, struct sock *sk,
@@ -6076,21 +6116,12 @@  static int cxgb4_ktls_dev_add(struct net_device *netdev, struct sock *sk,
 			      u32 tcp_sn)
 {
 	struct adapter *adap = netdev2adap(netdev);
-	int ret = 0;
+	int ret;
 
 	mutex_lock(&uld_mutex);
-	if (!adap->uld[CXGB4_ULD_CRYPTO].handle) {
-		dev_err(adap->pdev_dev, "chcr driver is not loaded\n");
-		ret = -EOPNOTSUPP;
-		goto out_unlock;
-	}
-
-	if (!adap->uld[CXGB4_ULD_CRYPTO].tlsdev_ops) {
-		dev_err(adap->pdev_dev,
-			"chcr driver has no registered tlsdev_ops()\n");
-		ret = -EOPNOTSUPP;
+	ret = chcr_offload_state(adap, CXGB4_TLSDEV_OPS);
+	if (ret)
 		goto out_unlock;
-	}
 
 	ret = cxgb4_set_ktls_feature(adap, FW_PARAMS_PARAM_DEV_KTLS_HW_ENABLE);
 	if (ret)
@@ -6116,16 +6147,9 @@  static void cxgb4_ktls_dev_del(struct net_device *netdev,
 	struct adapter *adap = netdev2adap(netdev);
 
 	mutex_lock(&uld_mutex);
-	if (!adap->uld[CXGB4_ULD_CRYPTO].handle) {
-		dev_err(adap->pdev_dev, "chcr driver is not loaded\n");
-		goto out_unlock;
-	}
 
-	if (!adap->uld[CXGB4_ULD_CRYPTO].tlsdev_ops) {
-		dev_err(adap->pdev_dev,
-			"chcr driver has no registered tlsdev_ops\n");
+	if (chcr_offload_state(adap, CXGB4_TLSDEV_OPS))
 		goto out_unlock;
-	}
 
 	adap->uld[CXGB4_ULD_CRYPTO].tlsdev_ops->tls_dev_del(netdev, tls_ctx,
 							    direction);
@@ -6141,6 +6165,93 @@  static const struct tlsdev_ops cxgb4_ktls_ops = {
 };
 #endif /* CONFIG_CHELSIO_TLS_DEVICE */
 
+#if defined(CONFIG_CHELSIO_IPSEC_INLINE)
+
+static int cxgb4_xfrm_add_state(struct xfrm_state *x)
+{
+	struct adapter *adap = netdev2adap(x->xso.dev);
+	int ret;
+
+	mutex_lock(&uld_mutex);
+	ret = chcr_offload_state(adap, CXGB4_XFRMDEV_OPS);
+	if (ret)
+		goto out_unlock;
+
+	ret = adap->uld[CXGB4_ULD_CRYPTO].xfrmdev_ops->xdo_dev_state_add(x);
+
+out_unlock:
+	mutex_unlock(&uld_mutex);
+	return ret;
+}
+
+static void cxgb4_xfrm_del_state(struct xfrm_state *x)
+{
+	struct adapter *adap = netdev2adap(x->xso.dev);
+
+	mutex_lock(&uld_mutex);
+	if (chcr_offload_state(adap, CXGB4_XFRMDEV_OPS))
+		goto out_unlock;
+
+	adap->uld[CXGB4_ULD_CRYPTO].xfrmdev_ops->xdo_dev_state_delete(x);
+
+out_unlock:
+	mutex_unlock(&uld_mutex);
+}
+
+static void cxgb4_xfrm_free_state(struct xfrm_state *x)
+{
+	struct adapter *adap = netdev2adap(x->xso.dev);
+
+	mutex_lock(&uld_mutex);
+	if (chcr_offload_state(adap, CXGB4_XFRMDEV_OPS))
+		goto out_unlock;
+
+	adap->uld[CXGB4_ULD_CRYPTO].xfrmdev_ops->xdo_dev_state_free(x);
+
+out_unlock:
+	mutex_unlock(&uld_mutex);
+}
+
+static bool cxgb4_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
+{
+	struct adapter *adap = netdev2adap(x->xso.dev);
+	bool ret = false;
+
+	mutex_lock(&uld_mutex);
+	if (chcr_offload_state(adap, CXGB4_XFRMDEV_OPS))
+		goto out_unlock;
+
+	ret = adap->uld[CXGB4_ULD_CRYPTO].xfrmdev_ops->xdo_dev_offload_ok(skb, x);
+
+out_unlock:
+	mutex_unlock(&uld_mutex);
+	return ret;
+}
+
+static void cxgb4_advance_esn_state(struct xfrm_state *x)
+{
+	struct adapter *adap = netdev2adap(x->xso.dev);
+
+	mutex_lock(&uld_mutex);
+	if (chcr_offload_state(adap, CXGB4_XFRMDEV_OPS))
+		goto out_unlock;
+
+	adap->uld[CXGB4_ULD_CRYPTO].xfrmdev_ops->xdo_dev_state_advance_esn(x);
+
+out_unlock:
+	mutex_unlock(&uld_mutex);
+}
+
+static const struct xfrmdev_ops cxgb4_xfrmdev_ops = {
+	.xdo_dev_state_add      = cxgb4_xfrm_add_state,
+	.xdo_dev_state_delete   = cxgb4_xfrm_del_state,
+	.xdo_dev_state_free     = cxgb4_xfrm_free_state,
+	.xdo_dev_offload_ok     = cxgb4_ipsec_offload_ok,
+	.xdo_dev_state_advance_esn = cxgb4_advance_esn_state,
+};
+
+#endif /* CONFIG_CHELSIO_IPSEC_INLINE */
+
 static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	struct net_device *netdev;
@@ -6397,6 +6508,13 @@  static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 			/* initialize the refcount */
 			refcount_set(&pi->adapter->chcr_ktls.ktls_refcount, 0);
 		}
+#endif
+#if defined(CONFIG_CHELSIO_IPSEC_INLINE)
+		if (pi->adapter->params.crypto & FW_CAPS_CONFIG_IPSEC_INLINE) {
+			netdev->hw_enc_features |= NETIF_F_HW_ESP;
+			netdev->features |= NETIF_F_HW_ESP;
+			netdev->xfrmdev_ops = &cxgb4_xfrmdev_ops;
+		}
 #endif
 		netdev->priv_flags |= IFF_UNICAST_FLT;
 
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
index dbce99b209d6..db8d71e7652f 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.h
@@ -471,6 +471,9 @@  struct cxgb4_uld_info {
 #if IS_ENABLED(CONFIG_TLS_DEVICE)
 	const struct tlsdev_ops *tlsdev_ops;
 #endif
+#if IS_ENABLED(CONFIG_XFRM_OFFLOAD)
+	const struct xfrmdev_ops *xfrmdev_ops;
+#endif
 };
 
 void cxgb4_uld_enable(struct adapter *adap);