aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Töpel <bjorn.topel@intel.com>2018-10-02 04:00:30 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2018-10-03 15:38:40 -0400
commit024aa5800f3246875ac824fab4bee3b4dc82f499 (patch)
tree5df69ea1228270d1937090e5eb4d660a46df6323
parent5d826d209164b0752c883607be4cdbbcf7cab494 (diff)
ixgbe: added Rx/Tx ring disable/enable functions
Add functions for Rx/Tx ring enable/disable. Instead of resetting the whole device, only the affected ring is disabled or enabled. This plumbing is used in later commits, when zero-copy AF_XDP support is introduced. Signed-off-by: Björn Töpel <bjorn.topel@intel.com> Tested-by: William Tu <u9012063@gmail.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h1
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c158
2 files changed, 159 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 5c6fd42e90ed..265db172042a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -271,6 +271,7 @@ enum ixgbe_ring_state_t {
271 __IXGBE_TX_DETECT_HANG, 271 __IXGBE_TX_DETECT_HANG,
272 __IXGBE_HANG_CHECK_ARMED, 272 __IXGBE_HANG_CHECK_ARMED,
273 __IXGBE_TX_XDP_RING, 273 __IXGBE_TX_XDP_RING,
274 __IXGBE_TX_DISABLED,
274}; 275};
275 276
276#define ring_uses_build_skb(ring) \ 277#define ring_uses_build_skb(ring) \
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 2928ce7653eb..47e28d9ce1e3 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -8692,6 +8692,8 @@ static netdev_tx_t __ixgbe_xmit_frame(struct sk_buff *skb,
8692 return NETDEV_TX_OK; 8692 return NETDEV_TX_OK;
8693 8693
8694 tx_ring = ring ? ring : adapter->tx_ring[skb->queue_mapping]; 8694 tx_ring = ring ? ring : adapter->tx_ring[skb->queue_mapping];
8695 if (unlikely(test_bit(__IXGBE_TX_DISABLED, &tx_ring->state)))
8696 return NETDEV_TX_BUSY;
8695 8697
8696 return ixgbe_xmit_frame_ring(skb, adapter, tx_ring); 8698 return ixgbe_xmit_frame_ring(skb, adapter, tx_ring);
8697} 8699}
@@ -10238,6 +10240,9 @@ static int ixgbe_xdp_xmit(struct net_device *dev, int n,
10238 if (unlikely(!ring)) 10240 if (unlikely(!ring))
10239 return -ENXIO; 10241 return -ENXIO;
10240 10242
10243 if (unlikely(test_bit(__IXGBE_TX_DISABLED, &ring->state)))
10244 return -ENXIO;
10245
10241 for (i = 0; i < n; i++) { 10246 for (i = 0; i < n; i++) {
10242 struct xdp_frame *xdpf = frames[i]; 10247 struct xdp_frame *xdpf = frames[i];
10243 int err; 10248 int err;
@@ -10301,6 +10306,159 @@ static const struct net_device_ops ixgbe_netdev_ops = {
10301 .ndo_xdp_xmit = ixgbe_xdp_xmit, 10306 .ndo_xdp_xmit = ixgbe_xdp_xmit,
10302}; 10307};
10303 10308
10309static void ixgbe_disable_txr_hw(struct ixgbe_adapter *adapter,
10310 struct ixgbe_ring *tx_ring)
10311{
10312 unsigned long wait_delay, delay_interval;
10313 struct ixgbe_hw *hw = &adapter->hw;
10314 u8 reg_idx = tx_ring->reg_idx;
10315 int wait_loop;
10316 u32 txdctl;
10317
10318 IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH);
10319
10320 /* delay mechanism from ixgbe_disable_tx */
10321 delay_interval = ixgbe_get_completion_timeout(adapter) / 100;
10322
10323 wait_loop = IXGBE_MAX_RX_DESC_POLL;
10324 wait_delay = delay_interval;
10325
10326 while (wait_loop--) {
10327 usleep_range(wait_delay, wait_delay + 10);
10328 wait_delay += delay_interval * 2;
10329 txdctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
10330
10331 if (!(txdctl & IXGBE_TXDCTL_ENABLE))
10332 return;
10333 }
10334
10335 e_err(drv, "TXDCTL.ENABLE not cleared within the polling period\n");
10336}
10337
10338static void ixgbe_disable_txr(struct ixgbe_adapter *adapter,
10339 struct ixgbe_ring *tx_ring)
10340{
10341 set_bit(__IXGBE_TX_DISABLED, &tx_ring->state);
10342 ixgbe_disable_txr_hw(adapter, tx_ring);
10343}
10344
10345static void ixgbe_disable_rxr_hw(struct ixgbe_adapter *adapter,
10346 struct ixgbe_ring *rx_ring)
10347{
10348 unsigned long wait_delay, delay_interval;
10349 struct ixgbe_hw *hw = &adapter->hw;
10350 u8 reg_idx = rx_ring->reg_idx;
10351 int wait_loop;
10352 u32 rxdctl;
10353
10354 rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
10355 rxdctl &= ~IXGBE_RXDCTL_ENABLE;
10356 rxdctl |= IXGBE_RXDCTL_SWFLSH;
10357
10358 /* write value back with RXDCTL.ENABLE bit cleared */
10359 IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
10360
10361 /* RXDCTL.EN may not change on 82598 if link is down, so skip it */
10362 if (hw->mac.type == ixgbe_mac_82598EB &&
10363 !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
10364 return;
10365
10366 /* delay mechanism from ixgbe_disable_rx */
10367 delay_interval = ixgbe_get_completion_timeout(adapter) / 100;
10368
10369 wait_loop = IXGBE_MAX_RX_DESC_POLL;
10370 wait_delay = delay_interval;
10371
10372 while (wait_loop--) {
10373 usleep_range(wait_delay, wait_delay + 10);
10374 wait_delay += delay_interval * 2;
10375 rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
10376
10377 if (!(rxdctl & IXGBE_RXDCTL_ENABLE))
10378 return;
10379 }
10380
10381 e_err(drv, "RXDCTL.ENABLE not cleared within the polling period\n");
10382}
10383
10384static void ixgbe_reset_txr_stats(struct ixgbe_ring *tx_ring)
10385{
10386 memset(&tx_ring->stats, 0, sizeof(tx_ring->stats));
10387 memset(&tx_ring->tx_stats, 0, sizeof(tx_ring->tx_stats));
10388}
10389
10390static void ixgbe_reset_rxr_stats(struct ixgbe_ring *rx_ring)
10391{
10392 memset(&rx_ring->stats, 0, sizeof(rx_ring->stats));
10393 memset(&rx_ring->rx_stats, 0, sizeof(rx_ring->rx_stats));
10394}
10395
10396/**
10397 * ixgbe_txrx_ring_disable - Disable Rx/Tx/XDP Tx rings
10398 * @adapter: adapter structure
10399 * @ring: ring index
10400 *
10401 * This function disables a certain Rx/Tx/XDP Tx ring. The function
10402 * assumes that the netdev is running.
10403 **/
10404void ixgbe_txrx_ring_disable(struct ixgbe_adapter *adapter, int ring)
10405{
10406 struct ixgbe_ring *rx_ring, *tx_ring, *xdp_ring;
10407
10408 rx_ring = adapter->rx_ring[ring];
10409 tx_ring = adapter->tx_ring[ring];
10410 xdp_ring = adapter->xdp_ring[ring];
10411
10412 ixgbe_disable_txr(adapter, tx_ring);
10413 if (xdp_ring)
10414 ixgbe_disable_txr(adapter, xdp_ring);
10415 ixgbe_disable_rxr_hw(adapter, rx_ring);
10416
10417 if (xdp_ring)
10418 synchronize_sched();
10419
10420 /* Rx/Tx/XDP Tx share the same napi context. */
10421 napi_disable(&rx_ring->q_vector->napi);
10422
10423 ixgbe_clean_tx_ring(tx_ring);
10424 if (xdp_ring)
10425 ixgbe_clean_tx_ring(xdp_ring);
10426 ixgbe_clean_rx_ring(rx_ring);
10427
10428 ixgbe_reset_txr_stats(tx_ring);
10429 if (xdp_ring)
10430 ixgbe_reset_txr_stats(xdp_ring);
10431 ixgbe_reset_rxr_stats(rx_ring);
10432}
10433
10434/**
10435 * ixgbe_txrx_ring_enable - Enable Rx/Tx/XDP Tx rings
10436 * @adapter: adapter structure
10437 * @ring: ring index
10438 *
10439 * This function enables a certain Rx/Tx/XDP Tx ring. The function
10440 * assumes that the netdev is running.
10441 **/
10442void ixgbe_txrx_ring_enable(struct ixgbe_adapter *adapter, int ring)
10443{
10444 struct ixgbe_ring *rx_ring, *tx_ring, *xdp_ring;
10445
10446 rx_ring = adapter->rx_ring[ring];
10447 tx_ring = adapter->tx_ring[ring];
10448 xdp_ring = adapter->xdp_ring[ring];
10449
10450 /* Rx/Tx/XDP Tx share the same napi context. */
10451 napi_enable(&rx_ring->q_vector->napi);
10452
10453 ixgbe_configure_tx_ring(adapter, tx_ring);
10454 if (xdp_ring)
10455 ixgbe_configure_tx_ring(adapter, xdp_ring);
10456 ixgbe_configure_rx_ring(adapter, rx_ring);
10457
10458 clear_bit(__IXGBE_TX_DISABLED, &tx_ring->state);
10459 clear_bit(__IXGBE_TX_DISABLED, &xdp_ring->state);
10460}
10461
10304/** 10462/**
10305 * ixgbe_enumerate_functions - Get the number of ports this device has 10463 * ixgbe_enumerate_functions - Get the number of ports this device has
10306 * @adapter: adapter structure 10464 * @adapter: adapter structure