From: Raghu Vatsavayi
Signed-off-by: Raghu Vatsavayi
Acked-by: Derek Chickles
Signed-off-by: Felix Manlunas
---
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(>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, >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, >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(>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, >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, >napi_list, dev_list)
+ napi_disable(napi);
+
+ oct->props[lio->ifidx].napi_enabled = 0;
+
+ oct->droq[0]->ops.poll_mode = 0;
+ }
+
dev_info(>pci_dev->dev, "%s interface is stopped\n", netdev->name);
return 0;
diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_network.h