Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2018-08-24 13:56:29 +0200
committerTakashi Iwai <tiwai@suse.de>2018-08-24 13:56:29 +0200
commit20844d3ae8aa6f647c8434f281140cb2aae92e52 (patch)
tree7c79d6d9a03ec8df54cffff524da07155cc045aa
parent05d48cc98ab935763c2c7d57d760131dc409b414 (diff)
parente2ad5f8ccfa46543a1e8d9186a90772cda0c822e (diff)
Merge branch 'users/tbogendoerfer/SLE15/for-next' into SLE15
Pull ixgbe fixes from Thomas Bogendoerfer
-rw-r--r--patches.drivers/ixgbe-Refactor-queue-disable-logic-to-take-completio.patch401
-rw-r--r--patches.drivers/ixgbe-Reorder-Tx-Rx-shutdown-to-reduce-time-needed-t.patch58
-rw-r--r--series.conf2
3 files changed, 461 insertions, 0 deletions
diff --git a/patches.drivers/ixgbe-Refactor-queue-disable-logic-to-take-completio.patch b/patches.drivers/ixgbe-Refactor-queue-disable-logic-to-take-completio.patch
new file mode 100644
index 0000000000..3579b5141e
--- /dev/null
+++ b/patches.drivers/ixgbe-Refactor-queue-disable-logic-to-take-completio.patch
@@ -0,0 +1,401 @@
+From: Alexander Duyck <alexander.h.duyck@intel.com>
+Date: Fri, 20 Jul 2018 18:29:34 -0400
+Subject: ixgbe: Refactor queue disable logic to take completion time into
+ account
+Patch-mainline: v4.17-rc6
+Git-commit: 1918e937ca3b4270181e6f05734d5240306bd2cf
+References: bsc#1101557
+
+This change is meant to allow us to take completion time into account when
+disabling queues. Previously we were just working with hard coded values
+for how long we should wait. This worked fine for the standard case where
+completion timeout was operating in the 50us to 50ms range, however on
+platforms that have higher completion timeout times this was resulting in
+Rx queues disable messages being displayed as we weren't waiting long
+enough for outstanding Rx DMA completions.
+
+Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
+Tested-by: Don Buchholz <donald.buchholz@intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
+---
+ drivers/net/ethernet/intel/ixgbe/ixgbe.h | 3
+ drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 32 --
+ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 280 +++++++++++++++++------
+ 3 files changed, 224 insertions(+), 91 deletions(-)
+
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+@@ -871,7 +871,8 @@ void ixgbe_free_rx_resources(struct ixgb
+ void ixgbe_free_tx_resources(struct ixgbe_ring *);
+ void ixgbe_configure_rx_ring(struct ixgbe_adapter *, struct ixgbe_ring *);
+ void ixgbe_configure_tx_ring(struct ixgbe_adapter *, struct ixgbe_ring *);
+-void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter, struct ixgbe_ring *);
++void ixgbe_disable_rx(struct ixgbe_adapter *adapter);
++void ixgbe_disable_tx(struct ixgbe_adapter *adapter);
+ void ixgbe_update_stats(struct ixgbe_adapter *adapter);
+ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter);
+ bool ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+@@ -1709,35 +1709,17 @@ static int ixgbe_intr_test(struct ixgbe_
+
+ static void ixgbe_free_desc_rings(struct ixgbe_adapter *adapter)
+ {
+- struct ixgbe_ring *tx_ring = &adapter->test_tx_ring;
+- struct ixgbe_ring *rx_ring = &adapter->test_rx_ring;
+- struct ixgbe_hw *hw = &adapter->hw;
+- u32 reg_ctl;
+-
+- /* shut down the DMA engines now so they can be reinitialized later */
++ /* Shut down the DMA engines now so they can be reinitialized later,
++ * since the test rings and normally used rings should overlap on
++ * queue 0 we can just use the standard disable Rx/Tx calls and they
++ * will take care of disabling the test rings for us.
++ */
+
+ /* first Rx */
+- hw->mac.ops.disable_rx(hw);
+- ixgbe_disable_rx_queue(adapter, rx_ring);
++ ixgbe_disable_rx(adapter);
+
+ /* now Tx */
+- reg_ctl = IXGBE_READ_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx));
+- reg_ctl &= ~IXGBE_TXDCTL_ENABLE;
+- IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(tx_ring->reg_idx), reg_ctl);
+-
+- switch (hw->mac.type) {
+- case ixgbe_mac_82599EB:
+- case ixgbe_mac_X540:
+- case ixgbe_mac_X550:
+- case ixgbe_mac_X550EM_x:
+- case ixgbe_mac_x550em_a:
+- reg_ctl = IXGBE_READ_REG(hw, IXGBE_DMATXCTL);
+- reg_ctl &= ~IXGBE_DMATXCTL_TE;
+- IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL, reg_ctl);
+- break;
+- default:
+- break;
+- }
++ ixgbe_disable_tx(adapter);
+
+ ixgbe_reset(adapter);
+
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+@@ -4040,38 +4040,6 @@ static void ixgbe_rx_desc_queue_enable(s
+ }
+ }
+
+-void ixgbe_disable_rx_queue(struct ixgbe_adapter *adapter,
+- struct ixgbe_ring *ring)
+-{
+- struct ixgbe_hw *hw = &adapter->hw;
+- int wait_loop = IXGBE_MAX_RX_DESC_POLL;
+- u32 rxdctl;
+- u8 reg_idx = ring->reg_idx;
+-
+- if (ixgbe_removed(hw->hw_addr))
+- return;
+- rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
+- rxdctl &= ~IXGBE_RXDCTL_ENABLE;
+-
+- /* write value back with RXDCTL.ENABLE bit cleared */
+- IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
+-
+- if (hw->mac.type == ixgbe_mac_82598EB &&
+- !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
+- return;
+-
+- /* the hardware may take up to 100us to really disable the rx queue */
+- do {
+- udelay(10);
+- rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
+- } while (--wait_loop && (rxdctl & IXGBE_RXDCTL_ENABLE));
+-
+- if (!wait_loop) {
+- e_err(drv, "RXDCTL.ENABLE on Rx queue %d not cleared within "
+- "the polling period\n", reg_idx);
+- }
+-}
+-
+ void ixgbe_configure_rx_ring(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *ring)
+ {
+@@ -4081,9 +4049,13 @@ void ixgbe_configure_rx_ring(struct ixgb
+ u32 rxdctl;
+ u8 reg_idx = ring->reg_idx;
+
+- /* disable queue to avoid issues while updating state */
++ /* disable queue to avoid use of these values while updating state */
+ rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
+- ixgbe_disable_rx_queue(adapter, ring);
++ rxdctl &= ~IXGBE_RXDCTL_ENABLE;
++
++ /* write value back with RXDCTL.ENABLE bit cleared */
++ IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
++ IXGBE_WRITE_FLUSH(hw);
+
+ IXGBE_WRITE_REG(hw, IXGBE_RDBAL(reg_idx), (rdba & DMA_BIT_MASK(32)));
+ IXGBE_WRITE_REG(hw, IXGBE_RDBAH(reg_idx), (rdba >> 32));
+@@ -5647,6 +5619,212 @@ void ixgbe_up(struct ixgbe_adapter *adap
+ ixgbe_up_complete(adapter);
+ }
+
++static unsigned long ixgbe_get_completion_timeout(struct ixgbe_adapter *adapter)
++{
++ u16 devctl2;
++
++ pcie_capability_read_word(adapter->pdev, PCI_EXP_DEVCTL2, &devctl2);
++
++ switch (devctl2 & IXGBE_PCIDEVCTRL2_TIMEO_MASK) {
++ case IXGBE_PCIDEVCTRL2_17_34s:
++ case IXGBE_PCIDEVCTRL2_4_8s:
++ /* For now we cap the upper limit on delay to 2 seconds
++ * as we end up going up to 34 seconds of delay in worst
++ * case timeout value.
++ */
++ case IXGBE_PCIDEVCTRL2_1_2s:
++ return 2000000ul; /* 2.0 s */
++ case IXGBE_PCIDEVCTRL2_260_520ms:
++ return 520000ul; /* 520 ms */
++ case IXGBE_PCIDEVCTRL2_65_130ms:
++ return 130000ul; /* 130 ms */
++ case IXGBE_PCIDEVCTRL2_16_32ms:
++ return 32000ul; /* 32 ms */
++ case IXGBE_PCIDEVCTRL2_1_2ms:
++ return 2000ul; /* 2 ms */
++ case IXGBE_PCIDEVCTRL2_50_100us:
++ return 100ul; /* 100 us */
++ case IXGBE_PCIDEVCTRL2_16_32ms_def:
++ return 32000ul; /* 32 ms */
++ default:
++ break;
++ }
++
++ /* We shouldn't need to hit this path, but just in case default as
++ * though completion timeout is not supported and support 32ms.
++ */
++ return 32000ul;
++}
++
++void ixgbe_disable_rx(struct ixgbe_adapter *adapter)
++{
++ unsigned long wait_delay, delay_interval;
++ struct ixgbe_hw *hw = &adapter->hw;
++ int i, wait_loop;
++ u32 rxdctl;
++
++ /* disable receives */
++ hw->mac.ops.disable_rx(hw);
++
++ if (ixgbe_removed(hw->hw_addr))
++ return;
++
++ /* disable all enabled Rx queues */
++ for (i = 0; i < adapter->num_rx_queues; i++) {
++ struct ixgbe_ring *ring = adapter->rx_ring[i];
++ u8 reg_idx = ring->reg_idx;
++
++ rxdctl = IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
++ rxdctl &= ~IXGBE_RXDCTL_ENABLE;
++ rxdctl |= IXGBE_RXDCTL_SWFLSH;
++
++ /* write value back with RXDCTL.ENABLE bit cleared */
++ IXGBE_WRITE_REG(hw, IXGBE_RXDCTL(reg_idx), rxdctl);
++ }
++
++ /* RXDCTL.EN may not change on 82598 if link is down, so skip it */
++ if (hw->mac.type == ixgbe_mac_82598EB &&
++ !(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
++ return;
++
++ /* Determine our minimum delay interval. We will increase this value
++ * with each subsequent test. This way if the device returns quickly
++ * we should spend as little time as possible waiting, however as
++ * the time increases we will wait for larger periods of time.
++ *
++ * The trick here is that we increase the interval using the
++ * following pattern: 1x 3x 5x 7x 9x 11x 13x 15x 17x 19x. The result
++ * of that wait is that it totals up to 100x whatever interval we
++ * choose. Since our minimum wait is 100us we can just divide the
++ * total timeout by 100 to get our minimum delay interval.
++ */
++ delay_interval = ixgbe_get_completion_timeout(adapter) / 100;
++
++ wait_loop = IXGBE_MAX_RX_DESC_POLL;
++ wait_delay = delay_interval;
++
++ while (wait_loop--) {
++ usleep_range(wait_delay, wait_delay + 10);
++ wait_delay += delay_interval * 2;
++ rxdctl = 0;
++
++ /* OR together the reading of all the active RXDCTL registers,
++ * and then test the result. We need the disable to complete
++ * before we start freeing the memory and invalidating the
++ * DMA mappings.
++ */
++ for (i = 0; i < adapter->num_rx_queues; i++) {
++ struct ixgbe_ring *ring = adapter->rx_ring[i];
++ u8 reg_idx = ring->reg_idx;
++
++ rxdctl |= IXGBE_READ_REG(hw, IXGBE_RXDCTL(reg_idx));
++ }
++
++ if (!(rxdctl & IXGBE_RXDCTL_ENABLE))
++ return;
++ }
++
++ e_err(drv,
++ "RXDCTL.ENABLE for one or more queues not cleared within the polling period\n");
++}
++
++void ixgbe_disable_tx(struct ixgbe_adapter *adapter)
++{
++ unsigned long wait_delay, delay_interval;
++ struct ixgbe_hw *hw = &adapter->hw;
++ int i, wait_loop;
++ u32 txdctl;
++
++ if (ixgbe_removed(hw->hw_addr))
++ return;
++
++ /* disable all enabled Tx queues */
++ for (i = 0; i < adapter->num_tx_queues; i++) {
++ struct ixgbe_ring *ring = adapter->tx_ring[i];
++ u8 reg_idx = ring->reg_idx;
++
++ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH);
++ }
++
++ /* disable all enabled XDP Tx queues */
++ for (i = 0; i < adapter->num_xdp_queues; i++) {
++ struct ixgbe_ring *ring = adapter->xdp_ring[i];
++ u8 reg_idx = ring->reg_idx;
++
++ IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH);
++ }
++
++ /* If the link is not up there shouldn't be much in the way of
++ * pending transactions. Those that are left will be flushed out
++ * when the reset logic goes through the flush sequence to clean out
++ * the pending Tx transactions.
++ */
++ if (!(IXGBE_READ_REG(hw, IXGBE_LINKS) & IXGBE_LINKS_UP))
++ goto dma_engine_disable;
++
++ /* Determine our minimum delay interval. We will increase this value
++ * with each subsequent test. This way if the device returns quickly
++ * we should spend as little time as possible waiting, however as
++ * the time increases we will wait for larger periods of time.
++ *
++ * The trick here is that we increase the interval using the
++ * following pattern: 1x 3x 5x 7x 9x 11x 13x 15x 17x 19x. The result
++ * of that wait is that it totals up to 100x whatever interval we
++ * choose. Since our minimum wait is 100us we can just divide the
++ * total timeout by 100 to get our minimum delay interval.
++ */
++ delay_interval = ixgbe_get_completion_timeout(adapter) / 100;
++
++ wait_loop = IXGBE_MAX_RX_DESC_POLL;
++ wait_delay = delay_interval;
++
++ while (wait_loop--) {
++ usleep_range(wait_delay, wait_delay + 10);
++ wait_delay += delay_interval * 2;
++ txdctl = 0;
++
++ /* OR together the reading of all the active TXDCTL registers,
++ * and then test the result. We need the disable to complete
++ * before we start freeing the memory and invalidating the
++ * DMA mappings.
++ */
++ for (i = 0; i < adapter->num_tx_queues; i++) {
++ struct ixgbe_ring *ring = adapter->tx_ring[i];
++ u8 reg_idx = ring->reg_idx;
++
++ txdctl |= IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
++ }
++ for (i = 0; i < adapter->num_xdp_queues; i++) {
++ struct ixgbe_ring *ring = adapter->xdp_ring[i];
++ u8 reg_idx = ring->reg_idx;
++
++ txdctl |= IXGBE_READ_REG(hw, IXGBE_TXDCTL(reg_idx));
++ }
++
++ if (!(txdctl & IXGBE_TXDCTL_ENABLE))
++ goto dma_engine_disable;
++ }
++
++ e_err(drv,
++ "TXDCTL.ENABLE for one or more queues not cleared within the polling period\n");
++
++dma_engine_disable:
++ /* Disable the Tx DMA engine on 82599 and later MAC */
++ switch (hw->mac.type) {
++ case ixgbe_mac_82599EB:
++ case ixgbe_mac_X540:
++ case ixgbe_mac_X550:
++ case ixgbe_mac_X550EM_x:
++ case ixgbe_mac_x550em_a:
++ IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
++ (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
++ ~IXGBE_DMATXCTL_TE));
++ /* fall through */
++ default:
++ break;
++ }
++}
++
+ void ixgbe_reset(struct ixgbe_adapter *adapter)
+ {
+ struct ixgbe_hw *hw = &adapter->hw;
+@@ -5835,13 +6013,8 @@ void ixgbe_down(struct ixgbe_adapter *ad
+ netif_carrier_off(netdev);
+ netif_tx_disable(netdev);
+
+- /* disable receives */
+- hw->mac.ops.disable_rx(hw);
+-
+- /* disable all enabled rx queues */
+- for (i = 0; i < adapter->num_rx_queues; i++)
+- /* this call also flushes the previous write */
+- ixgbe_disable_rx_queue(adapter, adapter->rx_ring[i]);
++ /* Disable Rx */
++ ixgbe_disable_rx(adapter);
+
+ ixgbe_irq_disable(adapter);
+
+@@ -5869,30 +6042,7 @@ void ixgbe_down(struct ixgbe_adapter *ad
+ }
+
+ /* disable transmits in the hardware now that interrupts are off */
+- for (i = 0; i < adapter->num_tx_queues; i++) {
+- u8 reg_idx = adapter->tx_ring[i]->reg_idx;
+- IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH);
+- }
+- for (i = 0; i < adapter->num_xdp_queues; i++) {
+- u8 reg_idx = adapter->xdp_ring[i]->reg_idx;
+-
+- IXGBE_WRITE_REG(hw, IXGBE_TXDCTL(reg_idx), IXGBE_TXDCTL_SWFLSH);
+- }
+-
+- /* Disable the Tx DMA engine on 82599 and later MAC */
+- switch (hw->mac.type) {
+- case ixgbe_mac_82599EB:
+- case ixgbe_mac_X540:
+- case ixgbe_mac_X550:
+- case ixgbe_mac_X550EM_x:
+- case ixgbe_mac_x550em_a:
+- IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
+- (IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
+- ~IXGBE_DMATXCTL_TE));
+- break;
+- default:
+- break;
+- }
++ ixgbe_disable_tx(adapter);
+
+ if (!pci_channel_offline(adapter->pdev))
+ ixgbe_reset(adapter);
diff --git a/patches.drivers/ixgbe-Reorder-Tx-Rx-shutdown-to-reduce-time-needed-t.patch b/patches.drivers/ixgbe-Reorder-Tx-Rx-shutdown-to-reduce-time-needed-t.patch
new file mode 100644
index 0000000000..742593266c
--- /dev/null
+++ b/patches.drivers/ixgbe-Reorder-Tx-Rx-shutdown-to-reduce-time-needed-t.patch
@@ -0,0 +1,58 @@
+From: Alexander Duyck <alexander.h.duyck@intel.com>
+Date: Fri, 20 Jul 2018 18:29:29 -0400
+Subject: ixgbe: Reorder Tx/Rx shutdown to reduce time needed to stop device
+Patch-mainline: v4.17-rc6
+Git-commit: 3b5f14b50ee2079190ae6cfe7477e74676651665
+References: bsc#1101557
+
+This change is meant to help reduce the time needed to shutdown the
+transmit and receive paths for the device. Specifically what we now do
+after this patch is disable the transmit path first at the netdev level,
+and then work on disabling the Rx. This way while we are waiting on the Rx
+queues to be disabled the Tx queues have an opportunity to drain out.
+
+In addition I have dropped the 10ms timeout that was left in the ixgbe_down
+function that seems to have been carried through from back in e1000 as far
+as I can tell. We shouldn't need it since we don't actually disable the Tx
+until much later and we have additional logic in place for verifying the Tx
+queues have been disabled.
+
+Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com>
+Tested-by: Don Buchholz <donald.buchholz@intel.com>
+Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
+Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
+---
+ drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 15 +++++++--------
+ 1 file changed, 7 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+@@ -5828,6 +5828,13 @@ void ixgbe_down(struct ixgbe_adapter *ad
+ if (test_and_set_bit(__IXGBE_DOWN, &adapter->state))
+ return; /* do nothing if already down */
+
++ /* Shut off incoming Tx traffic */
++ netif_tx_stop_all_queues(netdev);
++
++ /* call carrier off first to avoid false dev_watchdog timeouts */
++ netif_carrier_off(netdev);
++ netif_tx_disable(netdev);
++
+ /* disable receives */
+ hw->mac.ops.disable_rx(hw);
+
+@@ -5836,14 +5843,6 @@ void ixgbe_down(struct ixgbe_adapter *ad
+ /* this call also flushes the previous write */
+ ixgbe_disable_rx_queue(adapter, adapter->rx_ring[i]);
+
+- usleep_range(10000, 20000);
+-
+- netif_tx_stop_all_queues(netdev);
+-
+- /* call carrier off first to avoid false dev_watchdog timeouts */
+- netif_carrier_off(netdev);
+- netif_tx_disable(netdev);
+-
+ ixgbe_irq_disable(adapter);
+
+ ixgbe_napi_disable_all(adapter);
diff --git a/series.conf b/series.conf
index 492b6666de..fa5ee01b99 100644
--- a/series.conf
+++ b/series.conf
@@ -16476,6 +16476,8 @@
patches.drivers/brcmsmac-fix-wrap-around-in-conversion-from-constant
patches.drivers/rndis_wlan-potential-buffer-overflow-in-rndis_wlan_a
patches.drivers/libertas-fix-suspend-and-resume-for-SDIO-connected-c
+ patches.drivers/ixgbe-Reorder-Tx-Rx-shutdown-to-reduce-time-needed-t.patch
+ patches.drivers/ixgbe-Refactor-queue-disable-logic-to-take-completio.patch
patches.drivers/qed-remove-redundant-functions-qed_set_gft_event_id_.patch
patches.drivers/qed-remove-redundant-functions-qed_get_cm_pq_idx_rl.patch
patches.drivers/qed-Make-some-functions-static.patch