aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2017-11-22 13:57:29 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2018-01-12 11:20:28 -0500
commitb5f69ccf6765804b550dfd6c165b0c35d07bbc65 (patch)
tree562cb41c35aa132d9171aa7c9d4ae71175a63ad2
parent16be45bca8d10ba2f9400bbc97958a437c3439de (diff)
ixgbe: avoid bringing rings up/down as macvlans are added/removed
This change makes it so that instead of bringing rings up/down for various we just update the netdev pointer for the Rx ring and set or clear the MAC filter for the interface. By doing it this way we can avoid a number of races and issues in the code as things were getting messy with the macvlan clean-up racing with the interface clean-up to bring the rings down on shutdown. With this change we opt to leave the rings owned by the PF interface for both Tx and Rx and just direct the packets once they are received to the macvlan netdev. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.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_lib.c28
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c102
2 files changed, 72 insertions, 58 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index dc7f3ef2957b..cfe5a6af04d0 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -46,7 +46,7 @@ static bool ixgbe_cache_ring_dcb_sriov(struct ixgbe_adapter *adapter)
46#endif /* IXGBE_FCOE */ 46#endif /* IXGBE_FCOE */
47 struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; 47 struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ];
48 int i; 48 int i;
49 u16 reg_idx; 49 u16 reg_idx, pool;
50 u8 tcs = adapter->hw_tcs; 50 u8 tcs = adapter->hw_tcs;
51 51
52 /* verify we have DCB queueing enabled before proceeding */ 52 /* verify we have DCB queueing enabled before proceeding */
@@ -58,12 +58,16 @@ static bool ixgbe_cache_ring_dcb_sriov(struct ixgbe_adapter *adapter)
58 return false; 58 return false;
59 59
60 /* start at VMDq register offset for SR-IOV enabled setups */ 60 /* start at VMDq register offset for SR-IOV enabled setups */
61 pool = 0;
61 reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask); 62 reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask);
62 for (i = 0; i < adapter->num_rx_queues; i++, reg_idx++) { 63 for (i = 0, pool = 0; i < adapter->num_rx_queues; i++, reg_idx++) {
63 /* If we are greater than indices move to next pool */ 64 /* If we are greater than indices move to next pool */
64 if ((reg_idx & ~vmdq->mask) >= tcs) 65 if ((reg_idx & ~vmdq->mask) >= tcs) {
66 pool++;
65 reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask); 67 reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask);
68 }
66 adapter->rx_ring[i]->reg_idx = reg_idx; 69 adapter->rx_ring[i]->reg_idx = reg_idx;
70 adapter->rx_ring[i]->netdev = pool ? NULL : adapter->netdev;
67 } 71 }
68 72
69 reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask); 73 reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask);
@@ -92,6 +96,7 @@ static bool ixgbe_cache_ring_dcb_sriov(struct ixgbe_adapter *adapter)
92 for (i = fcoe->offset; i < adapter->num_rx_queues; i++) { 96 for (i = fcoe->offset; i < adapter->num_rx_queues; i++) {
93 reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask) + fcoe_tc; 97 reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask) + fcoe_tc;
94 adapter->rx_ring[i]->reg_idx = reg_idx; 98 adapter->rx_ring[i]->reg_idx = reg_idx;
99 adapter->rx_ring[i]->netdev = adapter->netdev;
95 reg_idx++; 100 reg_idx++;
96 } 101 }
97 102
@@ -182,6 +187,7 @@ static bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter)
182 for (i = 0; i < rss_i; i++, tx_idx++, rx_idx++) { 187 for (i = 0; i < rss_i; i++, tx_idx++, rx_idx++) {
183 adapter->tx_ring[offset + i]->reg_idx = tx_idx; 188 adapter->tx_ring[offset + i]->reg_idx = tx_idx;
184 adapter->rx_ring[offset + i]->reg_idx = rx_idx; 189 adapter->rx_ring[offset + i]->reg_idx = rx_idx;
190 adapter->rx_ring[offset + i]->netdev = adapter->netdev;
185 adapter->tx_ring[offset + i]->dcb_tc = tc; 191 adapter->tx_ring[offset + i]->dcb_tc = tc;
186 adapter->rx_ring[offset + i]->dcb_tc = tc; 192 adapter->rx_ring[offset + i]->dcb_tc = tc;
187 } 193 }
@@ -206,14 +212,15 @@ static bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter)
206#endif /* IXGBE_FCOE */ 212#endif /* IXGBE_FCOE */
207 struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ]; 213 struct ixgbe_ring_feature *vmdq = &adapter->ring_feature[RING_F_VMDQ];
208 struct ixgbe_ring_feature *rss = &adapter->ring_feature[RING_F_RSS]; 214 struct ixgbe_ring_feature *rss = &adapter->ring_feature[RING_F_RSS];
215 u16 reg_idx, pool;
209 int i; 216 int i;
210 u16 reg_idx;
211 217
212 /* only proceed if VMDq is enabled */ 218 /* only proceed if VMDq is enabled */
213 if (!(adapter->flags & IXGBE_FLAG_VMDQ_ENABLED)) 219 if (!(adapter->flags & IXGBE_FLAG_VMDQ_ENABLED))
214 return false; 220 return false;
215 221
216 /* start at VMDq register offset for SR-IOV enabled setups */ 222 /* start at VMDq register offset for SR-IOV enabled setups */
223 pool = 0;
217 reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask); 224 reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask);
218 for (i = 0; i < adapter->num_rx_queues; i++, reg_idx++) { 225 for (i = 0; i < adapter->num_rx_queues; i++, reg_idx++) {
219#ifdef IXGBE_FCOE 226#ifdef IXGBE_FCOE
@@ -222,15 +229,20 @@ static bool ixgbe_cache_ring_sriov(struct ixgbe_adapter *adapter)
222 break; 229 break;
223#endif 230#endif
224 /* If we are greater than indices move to next pool */ 231 /* If we are greater than indices move to next pool */
225 if ((reg_idx & ~vmdq->mask) >= rss->indices) 232 if ((reg_idx & ~vmdq->mask) >= rss->indices) {
233 pool++;
226 reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask); 234 reg_idx = __ALIGN_MASK(reg_idx, ~vmdq->mask);
235 }
227 adapter->rx_ring[i]->reg_idx = reg_idx; 236 adapter->rx_ring[i]->reg_idx = reg_idx;
237 adapter->rx_ring[i]->netdev = pool ? NULL : adapter->netdev;
228 } 238 }
229 239
230#ifdef IXGBE_FCOE 240#ifdef IXGBE_FCOE
231 /* FCoE uses a linear block of queues so just assigning 1:1 */ 241 /* FCoE uses a linear block of queues so just assigning 1:1 */
232 for (; i < adapter->num_rx_queues; i++, reg_idx++) 242 for (; i < adapter->num_rx_queues; i++, reg_idx++) {
233 adapter->rx_ring[i]->reg_idx = reg_idx; 243 adapter->rx_ring[i]->reg_idx = reg_idx;
244 adapter->rx_ring[i]->netdev = adapter->netdev;
245 }
234 246
235#endif 247#endif
236 reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask); 248 reg_idx = vmdq->offset * __ALIGN_MASK(1, ~vmdq->mask);
@@ -267,8 +279,10 @@ static bool ixgbe_cache_ring_rss(struct ixgbe_adapter *adapter)
267{ 279{
268 int i, reg_idx; 280 int i, reg_idx;
269 281
270 for (i = 0; i < adapter->num_rx_queues; i++) 282 for (i = 0; i < adapter->num_rx_queues; i++) {
271 adapter->rx_ring[i]->reg_idx = i; 283 adapter->rx_ring[i]->reg_idx = i;
284 adapter->rx_ring[i]->netdev = adapter->netdev;
285 }
272 for (i = 0, reg_idx = 0; i < adapter->num_tx_queues; i++, reg_idx++) 286 for (i = 0, reg_idx = 0; i < adapter->num_tx_queues; i++, reg_idx++)
273 adapter->tx_ring[i]->reg_idx = reg_idx; 287 adapter->tx_ring[i]->reg_idx = reg_idx;
274 for (i = 0; i < adapter->num_xdp_queues; i++, reg_idx++) 288 for (i = 0; i < adapter->num_xdp_queues; i++, reg_idx++)
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 89f7b16c47b7..cdb8502ae473 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1922,10 +1922,13 @@ static bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring,
1922 if (IS_ERR(skb)) 1922 if (IS_ERR(skb))
1923 return true; 1923 return true;
1924 1924
1925 /* verify that the packet does not have any known errors */ 1925 /* Verify netdev is present, and that packet does not have any
1926 if (unlikely(ixgbe_test_staterr(rx_desc, 1926 * errors that would be unacceptable to the netdev.
1927 IXGBE_RXDADV_ERR_FRAME_ERR_MASK) && 1927 */
1928 !(netdev->features & NETIF_F_RXALL))) { 1928 if (!netdev ||
1929 (unlikely(ixgbe_test_staterr(rx_desc,
1930 IXGBE_RXDADV_ERR_FRAME_ERR_MASK) &&
1931 !(netdev->features & NETIF_F_RXALL)))) {
1929 dev_kfree_skb_any(skb); 1932 dev_kfree_skb_any(skb);
1930 return true; 1933 return true;
1931 } 1934 }
@@ -5337,33 +5340,6 @@ static void ixgbe_clean_rx_ring(struct ixgbe_ring *rx_ring)
5337 rx_ring->next_to_use = 0; 5340 rx_ring->next_to_use = 0;
5338} 5341}
5339 5342
5340static void ixgbe_disable_fwd_ring(struct ixgbe_fwd_adapter *vadapter,
5341 struct ixgbe_ring *rx_ring)
5342{
5343 struct ixgbe_adapter *adapter = vadapter->real_adapter;
5344
5345 /* shutdown specific queue receive and wait for dma to settle */
5346 ixgbe_disable_rx_queue(adapter, rx_ring);
5347 usleep_range(10000, 20000);
5348 ixgbe_irq_disable_queues(adapter, BIT_ULL(rx_ring->queue_index));
5349 ixgbe_clean_rx_ring(rx_ring);
5350}
5351
5352static int ixgbe_fwd_ring_down(struct net_device *vdev,
5353 struct ixgbe_fwd_adapter *accel)
5354{
5355 struct ixgbe_adapter *adapter = accel->real_adapter;
5356 unsigned int rxbase = accel->rx_base_queue;
5357 int i;
5358
5359 for (i = 0; i < adapter->num_rx_queues_per_pool; i++) {
5360 ixgbe_disable_fwd_ring(accel, adapter->rx_ring[rxbase + i]);
5361 adapter->rx_ring[rxbase + i]->netdev = adapter->netdev;
5362 }
5363
5364 return 0;
5365}
5366
5367static int ixgbe_fwd_ring_up(struct net_device *vdev, 5343static int ixgbe_fwd_ring_up(struct net_device *vdev,
5368 struct ixgbe_fwd_adapter *accel) 5344 struct ixgbe_fwd_adapter *accel)
5369{ 5345{
@@ -5383,25 +5359,26 @@ static int ixgbe_fwd_ring_up(struct net_device *vdev,
5383 accel->tx_base_queue = baseq; 5359 accel->tx_base_queue = baseq;
5384 5360
5385 for (i = 0; i < adapter->num_rx_queues_per_pool; i++) 5361 for (i = 0; i < adapter->num_rx_queues_per_pool; i++)
5386 ixgbe_disable_fwd_ring(accel, adapter->rx_ring[baseq + i]);
5387
5388 for (i = 0; i < adapter->num_rx_queues_per_pool; i++) {
5389 adapter->rx_ring[baseq + i]->netdev = vdev; 5362 adapter->rx_ring[baseq + i]->netdev = vdev;
5390 ixgbe_configure_rx_ring(adapter, adapter->rx_ring[baseq + i]); 5363
5391 } 5364 /* Guarantee all rings are updated before we update the
5365 * MAC address filter.
5366 */
5367 wmb();
5392 5368
5393 /* ixgbe_add_mac_filter will return an index if it succeeds, so we 5369 /* ixgbe_add_mac_filter will return an index if it succeeds, so we
5394 * need to only treat it as an error value if it is negative. 5370 * need to only treat it as an error value if it is negative.
5395 */ 5371 */
5396 err = ixgbe_add_mac_filter(adapter, vdev->dev_addr, 5372 err = ixgbe_add_mac_filter(adapter, vdev->dev_addr,
5397 VMDQ_P(accel->pool)); 5373 VMDQ_P(accel->pool));
5398 if (err < 0) 5374 if (err >= 0) {
5399 goto fwd_queue_err; 5375 ixgbe_macvlan_set_rx_mode(vdev, accel->pool, adapter);
5376 return 0;
5377 }
5378
5379 for (i = 0; i < adapter->num_rx_queues_per_pool; i++)
5380 adapter->rx_ring[baseq + i]->netdev = NULL;
5400 5381
5401 ixgbe_macvlan_set_rx_mode(vdev, VMDQ_P(accel->pool), adapter);
5402 return 0;
5403fwd_queue_err:
5404 ixgbe_fwd_ring_down(vdev, accel);
5405 return err; 5382 return err;
5406} 5383}
5407 5384
@@ -9801,15 +9778,38 @@ static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
9801 9778
9802static void ixgbe_fwd_del(struct net_device *pdev, void *priv) 9779static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
9803{ 9780{
9804 struct ixgbe_fwd_adapter *fwd_adapter = priv; 9781 struct ixgbe_fwd_adapter *accel = priv;
9805 struct ixgbe_adapter *adapter = fwd_adapter->real_adapter; 9782 struct ixgbe_adapter *adapter = accel->real_adapter;
9806 unsigned int limit; 9783 unsigned int rxbase = accel->rx_base_queue;
9784 unsigned int limit, i;
9807 9785
9808 clear_bit(fwd_adapter->pool, adapter->fwd_bitmask); 9786 /* delete unicast filter associated with offloaded interface */
9787 ixgbe_del_mac_filter(adapter, accel->netdev->dev_addr,
9788 VMDQ_P(accel->pool));
9809 9789
9790 /* disable ability to receive packets for this pool */
9791 IXGBE_WRITE_REG(&adapter->hw, IXGBE_VMOLR(accel->pool), 0);
9792
9793 /* Allow remaining Rx packets to get flushed out of the
9794 * Rx FIFO before we drop the netdev for the ring.
9795 */
9796 usleep_range(10000, 20000);
9797
9798 for (i = 0; i < adapter->num_rx_queues_per_pool; i++) {
9799 struct ixgbe_ring *ring = adapter->rx_ring[rxbase + i];
9800 struct ixgbe_q_vector *qv = ring->q_vector;
9801
9802 /* Make sure we aren't processing any packets and clear
9803 * netdev to shut down the ring.
9804 */
9805 if (netif_running(adapter->netdev))
9806 napi_synchronize(&qv->napi);
9807 ring->netdev = NULL;
9808 }
9809
9810 clear_bit(accel->pool, adapter->fwd_bitmask);
9810 limit = find_last_bit(adapter->fwd_bitmask, adapter->num_rx_pools); 9811 limit = find_last_bit(adapter->fwd_bitmask, adapter->num_rx_pools);
9811 adapter->ring_feature[RING_F_VMDQ].limit = limit + 1; 9812 adapter->ring_feature[RING_F_VMDQ].limit = limit + 1;
9812 ixgbe_fwd_ring_down(fwd_adapter->netdev, fwd_adapter);
9813 9813
9814 /* go back to full RSS if we're done with our VMQs */ 9814 /* go back to full RSS if we're done with our VMQs */
9815 if (adapter->ring_feature[RING_F_VMDQ].limit == 1) { 9815 if (adapter->ring_feature[RING_F_VMDQ].limit == 1) {
@@ -9823,11 +9823,11 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
9823 9823
9824 ixgbe_setup_tc(pdev, adapter->hw_tcs); 9824 ixgbe_setup_tc(pdev, adapter->hw_tcs);
9825 netdev_dbg(pdev, "pool %i:%i queues %i:%i\n", 9825 netdev_dbg(pdev, "pool %i:%i queues %i:%i\n",
9826 fwd_adapter->pool, adapter->num_rx_pools, 9826 accel->pool, adapter->num_rx_pools,
9827 fwd_adapter->rx_base_queue, 9827 accel->rx_base_queue,
9828 fwd_adapter->rx_base_queue + 9828 accel->rx_base_queue +
9829 adapter->num_rx_queues_per_pool); 9829 adapter->num_rx_queues_per_pool);
9830 kfree(fwd_adapter); 9830 kfree(accel);
9831} 9831}
9832 9832
9833#define IXGBE_MAX_MAC_HDR_LEN 127 9833#define IXGBE_MAX_MAC_HDR_LEN 127