Skip to content

Commit ccdd0b4

Browse files
Raghu Vatsavayidavem330
authored andcommitted
liquidio: prevent rx queues from getting stalled
This commit has fix for RX traffic issues when we stress test the driver with continuous ifconfig up/down under very high traffic conditions. Reason for the issue is that, in existing liquidio_stop function NAPI is disabled even before actual FW/HW interface is brought down via send_rx_ctrl_cmd(lio, 0). Between time frame of NAPI disable and actual interface down in firmware, firmware continuously enqueues rx traffic to host. When interrupt happens for new packets, host irq handler fails in scheduling NAPI as the NAPI is already disabled. After "ifconfig <iface> up", Host re-enables NAPI but cannot schedule it until it receives another Rx interrupt. Host never receives Rx interrupt as it never cleared the Rx interrupt it received during interface down operation. NIC Rx interrupt gets cleared only when Host processes queue and clears the queue counts. Above anomaly leads to other issues like packet overflow in FW/HW queues, backpressure. Fix: This commit fixes this issue by disabling NAPI only after informing firmware to stop queueing packets to host via send_rx_ctrl_cmd(lio, 0). send_rx_ctrl_cmd is not visible in the patch as it is already there in the code. The DOWN command also waits for any pending packets to be processed by NAPI so that the deadlock will not occur. Signed-off-by: Raghu Vatsavayi <[email protected]> Acked-by: Derek Chickles <[email protected]> Signed-off-by: Felix Manlunas <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6f14f49 commit ccdd0b4

File tree

4 files changed

+53
-19
lines changed

4 files changed

+53
-19
lines changed

drivers/net/ethernet/cavium/liquidio/lio_core.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1146,3 +1146,26 @@ int liquidio_change_mtu(struct net_device *netdev, int new_mtu)
11461146
octeon_free_soft_command(oct, sc);
11471147
return 0;
11481148
}
1149+
1150+
int lio_wait_for_clean_oq(struct octeon_device *oct)
1151+
{
1152+
int retry = 100, pending_pkts = 0;
1153+
int idx;
1154+
1155+
do {
1156+
pending_pkts = 0;
1157+
1158+
for (idx = 0; idx < MAX_OCTEON_OUTPUT_QUEUES(oct); idx++) {
1159+
if (!(oct->io_qmask.oq & BIT_ULL(idx)))
1160+
continue;
1161+
pending_pkts +=
1162+
atomic_read(&oct->droq[idx]->pkts_pending);
1163+
}
1164+
1165+
if (pending_pkts > 0)
1166+
schedule_timeout_uninterruptible(1);
1167+
1168+
} while (retry-- && pending_pkts);
1169+
1170+
return pending_pkts;
1171+
}

drivers/net/ethernet/cavium/liquidio/lio_main.c

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,16 +2084,6 @@ static int liquidio_stop(struct net_device *netdev)
20842084
struct octeon_device *oct = lio->oct_dev;
20852085
struct napi_struct *napi, *n;
20862086

2087-
if (oct->props[lio->ifidx].napi_enabled) {
2088-
list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
2089-
napi_disable(napi);
2090-
2091-
oct->props[lio->ifidx].napi_enabled = 0;
2092-
2093-
if (OCTEON_CN23XX_PF(oct))
2094-
oct->droq[0]->ops.poll_mode = 0;
2095-
}
2096-
20972087
ifstate_reset(lio, LIO_IFSTATE_RUNNING);
20982088

20992089
netif_tx_disable(netdev);
@@ -2119,6 +2109,21 @@ static int liquidio_stop(struct net_device *netdev)
21192109
lio->ptp_clock = NULL;
21202110
}
21212111

2112+
/* Wait for any pending Rx descriptors */
2113+
if (lio_wait_for_clean_oq(oct))
2114+
netif_info(lio, rx_err, lio->netdev,
2115+
"Proceeding with stop interface after partial RX desc processing\n");
2116+
2117+
if (oct->props[lio->ifidx].napi_enabled == 1) {
2118+
list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
2119+
napi_disable(napi);
2120+
2121+
oct->props[lio->ifidx].napi_enabled = 0;
2122+
2123+
if (OCTEON_CN23XX_PF(oct))
2124+
oct->droq[0]->ops.poll_mode = 0;
2125+
}
2126+
21222127
dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
21232128

21242129
return 0;

drivers/net/ethernet/cavium/liquidio/lio_vf_main.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,15 +1138,6 @@ static int liquidio_stop(struct net_device *netdev)
11381138
/* tell Octeon to stop forwarding packets to host */
11391139
send_rx_ctrl_cmd(lio, 0);
11401140

1141-
if (oct->props[lio->ifidx].napi_enabled) {
1142-
list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
1143-
napi_disable(napi);
1144-
1145-
oct->props[lio->ifidx].napi_enabled = 0;
1146-
1147-
oct->droq[0]->ops.poll_mode = 0;
1148-
}
1149-
11501141
netif_info(lio, ifdown, lio->netdev, "Stopping interface!\n");
11511142
/* Inform that netif carrier is down */
11521143
lio->intf_open = 0;
@@ -1159,6 +1150,20 @@ static int liquidio_stop(struct net_device *netdev)
11591150

11601151
stop_txqs(netdev);
11611152

1153+
/* Wait for any pending Rx descriptors */
1154+
if (lio_wait_for_clean_oq(oct))
1155+
netif_info(lio, rx_err, lio->netdev,
1156+
"Proceeding with stop interface after partial RX desc processing\n");
1157+
1158+
if (oct->props[lio->ifidx].napi_enabled == 1) {
1159+
list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list)
1160+
napi_disable(napi);
1161+
1162+
oct->props[lio->ifidx].napi_enabled = 0;
1163+
1164+
oct->droq[0]->ops.poll_mode = 0;
1165+
}
1166+
11621167
dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
11631168

11641169
return 0;

drivers/net/ethernet/cavium/liquidio/octeon_network.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ irqreturn_t liquidio_msix_intr_handler(int irq __attribute__((unused)),
190190

191191
int octeon_setup_interrupt(struct octeon_device *oct, u32 num_ioqs);
192192

193+
int lio_wait_for_clean_oq(struct octeon_device *oct);
193194
/**
194195
* \brief Register ethtool operations
195196
* @param netdev pointer to network device

0 commit comments

Comments
 (0)