From 9d39578ff15fe4c045c5b70244f059a446999119 Mon Sep 17 00:00:00 2001
From: Aastha Mehta <aasthakm@mpi-sws.org>
Date: Fri, 6 Apr 2018 08:30:48 +0000
Subject: [PATCH] intercept skb freeing code at nic unload

required for the case when txq times out and nic unloads and reloads.
it tries to free up all pkts queued between prod and cons. some of
these maybe our special dummy pkt, which should not be freed until
rmmod.
---
 drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c      |  7 +++++++
 drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme.c    | 12 ++++++++++++
 drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme.h    |  2 ++
 .../net/ethernet/broadcom/bnx2x/sme/xen_sme_hooks.c  |  8 ++++++++
 .../net/ethernet/broadcom/bnx2x/sme/xen_sme_hooks.h  |  1 +
 5 files changed, 30 insertions(+)

diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 97a3adca1..da44c8277 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -2748,6 +2748,13 @@ static void bnx2x_free_tx_skbs_queue(struct bnx2x_fastpath *fp)
 	u8 cos;
 	struct bnx2x *bp = fp->bp;
 
+#ifdef CONFIG_XEN_SME
+  if (lnk_intercept_rx_path) {
+    xsl_intercept_free_tx_skbs_queue(fp);
+    return;
+  }
+#endif
+
 	for_each_cos_in_tx_queue(fp, cos) {
 		struct bnx2x_fp_txdata *txdata = fp->txdata_ptr[cos];
 		unsigned pkts_compl = 0, bytes_compl = 0;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme.c b/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme.c
index 91790e1c9..263ce52c0 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme.c
@@ -99,6 +99,17 @@ sme_intercept_tx_int(struct net_device *dev, struct bnx2x_fp_txdata *txdata)
   return ret;
 }
 
+void
+(*lnk_intercept_free_tx_skbs_queue) (struct bnx2x_fastpath *fp) = 0;
+EXPORT_SYMBOL(lnk_intercept_free_tx_skbs_queue);
+static void
+sme_intercept_free_tx_skbs_queue(struct bnx2x_fastpath *fp)
+{
+  if (lnk_intercept_free_tx_skbs_queue) {
+    lnk_intercept_free_tx_skbs_queue(fp);
+  }
+}
+
 void
 (*lnk_parse_rx_data) (void *dev, int fp_idx, uint16_t rx_bd_prod,
 		uint16_t rx_bd_cons, uint16_t comp_prod, uint16_t comp_cons,
@@ -178,6 +189,7 @@ static struct sme_hook_list xen_sme_hooks[] = {
 	SME_HOOK_INIT(intercept_sk_buff, sme_intercept_sk_buff),
   SME_HOOK_INIT(intercept_xmit_stop_queue, sme_intercept_xmit_stop_queue),
   SME_HOOK_INIT(intercept_tx_int, sme_intercept_tx_int),
+  SME_HOOK_INIT(intercept_free_tx_skbs_queue, sme_intercept_free_tx_skbs_queue),
 	SME_HOOK_INIT(parse_rx_data, sme_parse_rx_data),
 	SME_HOOK_INIT(print_sk_buff, sme_print_sk_buff),
 	SME_HOOK_INIT(intercept_rx_path, sme_intercept_rx_path),
diff --git a/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme.h b/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme.h
index d4634bd08..e13f8bfa5 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme.h
@@ -35,6 +35,7 @@ union sme_list_options {
   void (*intercept_xmit_stop_queue) (struct net_device *dev,
       struct netdev_queue *txq, struct bnx2x_fp_txdata *txdata);
   int (*intercept_tx_int) (struct net_device *dev, struct bnx2x_fp_txdata *txdata);
+  void (*intercept_free_tx_skbs_queue) (struct bnx2x_fastpath *fp);
 	void (*parse_rx_data) (void *dev, int fp_idx, uint16_t rx_bd_prod,
 			uint16_t rx_bd_cons, uint16_t comp_prod, uint16_t comp_cons,
 			char *data, int data_len, char *extra_dbg_string);
@@ -55,6 +56,7 @@ struct sme_hook_heads {
 	struct list_head intercept_sk_buff;
   struct list_head intercept_xmit_stop_queue;
   struct list_head intercept_tx_int;
+  struct list_head intercept_free_tx_skbs_queue;
 	struct list_head parse_rx_data;
 	struct list_head print_sk_buff;
 	struct list_head intercept_rx_path;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme_hooks.c b/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme_hooks.c
index e081d0d0f..a9bb086eb 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme_hooks.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme_hooks.c
@@ -45,6 +45,8 @@ struct sme_hook_heads xen_sme_hook_heads = {
   .intercept_xmit_stop_queue =
     LIST_HEAD_INIT(xen_sme_hook_heads.intercept_xmit_stop_queue),
   .intercept_tx_int = LIST_HEAD_INIT(xen_sme_hook_heads.intercept_tx_int),
+  .intercept_free_tx_skbs_queue =
+    LIST_HEAD_INIT(xen_sme_hook_heads.intercept_free_tx_skbs_queue),
 	.parse_rx_data = LIST_HEAD_INIT(xen_sme_hook_heads.parse_rx_data),
 	.print_sk_buff = LIST_HEAD_INIT(xen_sme_hook_heads.print_sk_buff),
 	.intercept_rx_path = LIST_HEAD_INIT(xen_sme_hook_heads.intercept_rx_path),
@@ -95,6 +97,12 @@ int xsl_intercept_tx_int(struct net_device *dev, struct bnx2x_fp_txdata *txdata)
 }
 EXPORT_SYMBOL(xsl_intercept_tx_int);
 
+void xsl_intercept_free_tx_skbs_queue(struct bnx2x_fastpath *fp)
+{
+  return call_sme_void_hook(intercept_free_tx_skbs_queue, fp);
+}
+EXPORT_SYMBOL(xsl_intercept_free_tx_skbs_queue);
+
 void xsl_parse_rx_data(void *dev, int fp_idx, uint16_t rx_bd_prod,
 		uint16_t rx_bd_cons, uint16_t comp_prod, uint16_t comp_cons,
 		char *data, int data_len, char *extra_dbg_string)
diff --git a/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme_hooks.h b/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme_hooks.h
index 40951ee41..66363a624 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme_hooks.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/sme/xen_sme_hooks.h
@@ -27,6 +27,7 @@ int xsl_intercept_sk_buff(struct sk_buff *skb, char *extra_dbg_string);
 void xsl_intercept_xmit_stop_queue(struct net_device *dev, struct netdev_queue *txq,
     struct bnx2x_fp_txdata *txdata);
 int xsl_intercept_tx_int(struct net_device *dev, struct bnx2x_fp_txdata *txdata);
+void xsl_intercept_free_tx_skbs_queue(struct bnx2x_fastpath *fp);
 
 void xsl_parse_rx_data(void *dev, int fp_idx, uint16_t rx_bd_prod,
 		uint16_t rx_bd_cons, uint16_t comp_prod, uint16_t comp_cons, char *data,
-- 
GitLab