From: Raghu Vatsavayi <raghu.vatsav...@cavium.com>

Signed-off-by: Raghu Vatsavayi <raghu.vatsav...@cavium.com>
Acked-by: Derek Chickles <derek.chick...@cavium.com>
Signed-off-by: Felix Manlunas <felix.manlu...@cavium.com>
---
 drivers/net/ethernet/cavium/liquidio/lio_core.c    | 23 ++++++++++++++++++++
 drivers/net/ethernet/cavium/liquidio/lio_main.c    | 25 +++++++++++++---------
 drivers/net/ethernet/cavium/liquidio/lio_vf_main.c | 23 ++++++++++++--------
 .../net/ethernet/cavium/liquidio/octeon_network.h  |  1 +
 4 files changed, 53 insertions(+), 19 deletions(-)

diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c 
b/drivers/net/ethernet/cavium/liquidio/lio_core.c
index e7b6eb8..8e4716a 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_core.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c
@@ -1157,3 +1157,26 @@ int liquidio_change_mtu(struct net_device *netdev, int 
new_mtu)
        octeon_free_soft_command(oct, sc);
        return 0;
 }
+
+int lio_wait_for_clean_oq(struct octeon_device *oct)
+{
+       int retry = 100, pending_pkts = 0;
+       int idx;
+
+       do {
+               pending_pkts = 0;
+
+               for (idx = 0; idx < MAX_OCTEON_OUTPUT_QUEUES(oct); idx++) {
+                       if (!(oct->io_qmask.oq & BIT_ULL(idx)))
+                               continue;
+                       pending_pkts +=
+                               atomic_read(&oct->droq[idx]->pkts_pending);
+               }
+
+               if (pending_pkts > 0)
+                       schedule_timeout_uninterruptible(1);
+
+       } while (retry-- && pending_pkts);
+
+       return pending_pkts;
+}
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c 
b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 140085b..345fe6e 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -2240,16 +2240,6 @@ static int liquidio_stop(struct net_device *netdev)
        struct octeon_device *oct = lio->oct_dev;
        struct napi_struct *napi, *n;
 
-       if (oct->props[lio->ifidx].napi_enabled) {
-               list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
-                       napi_disable(napi);
-
-               oct->props[lio->ifidx].napi_enabled = 0;
-
-               if (OCTEON_CN23XX_PF(oct))
-                       oct->droq[0]->ops.poll_mode = 0;
-       }
-
        ifstate_reset(lio, LIO_IFSTATE_RUNNING);
 
        netif_tx_disable(netdev);
@@ -2275,6 +2265,21 @@ static int liquidio_stop(struct net_device *netdev)
                lio->ptp_clock = NULL;
        }
 
+       /* Wait for any pending Rx descriptors */
+       if (lio_wait_for_clean_oq(oct))
+               netif_info(lio, rx_err, lio->netdev,
+                          "Proceeding with stop interface after partial RX 
desc processing\n");
+
+       if (oct->props[lio->ifidx].napi_enabled == 1) {
+               list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
+                       napi_disable(napi);
+
+               oct->props[lio->ifidx].napi_enabled = 0;
+
+               if (OCTEON_CN23XX_PF(oct))
+                       oct->droq[0]->ops.poll_mode = 0;
+       }
+
        dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
 
        return 0;
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c 
b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
index 3342d64..66655df 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
@@ -1281,15 +1281,6 @@ static int liquidio_stop(struct net_device *netdev)
        /* tell Octeon to stop forwarding packets to host */
        send_rx_ctrl_cmd(lio, 0);
 
-       if (oct->props[lio->ifidx].napi_enabled) {
-               list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
-                       napi_disable(napi);
-
-               oct->props[lio->ifidx].napi_enabled = 0;
-
-               oct->droq[0]->ops.poll_mode = 0;
-       }
-
        netif_info(lio, ifdown, lio->netdev, "Stopping interface!\n");
        /* Inform that netif carrier is down */
        lio->intf_open = 0;
@@ -1302,6 +1293,20 @@ static int liquidio_stop(struct net_device *netdev)
 
        txqs_stop(netdev);
 
+       /* Wait for any pending Rx descriptors */
+       if (lio_wait_for_clean_oq(oct))
+               netif_info(lio, rx_err, lio->netdev,
+                          "Proceeding with stop interface after partial RX 
desc processing\n");
+
+       if (oct->props[lio->ifidx].napi_enabled == 1) {
+               list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
+                       napi_disable(napi);
+
+               oct->props[lio->ifidx].napi_enabled = 0;
+
+               oct->droq[0]->ops.poll_mode = 0;
+       }
+
        dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
 
        return 0;
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_network.h 
b/drivers/net/ethernet/cavium/liquidio/octeon_network.h
index 76803a5..b7ee2d3 100644
--- a/drivers/net/ethernet/cavium/liquidio/octeon_network.h
+++ b/drivers/net/ethernet/cavium/liquidio/octeon_network.h
@@ -190,6 +190,7 @@ irqreturn_t liquidio_msix_intr_handler(int irq 
__attribute__((unused)),
 
 int octeon_setup_interrupt(struct octeon_device *oct, u32 num_ioqs);
 
+int lio_wait_for_clean_oq(struct octeon_device *oct);
 /**
  * \brief Register ethtool operations
  * @param netdev    pointer to network device

Reply via email to