Skip to content

Commit 8315ef6

Browse files
Alexander DuyckJeff Kirsher
authored andcommitted
ixgbe: Avoid performing unnecessary resets for macvlan offload
The original implementation for macvlan offload has us performing a full port reset every time we added a new macvlan. This shouldn't be necessary and can be avoided with a few behavior changes. This patches updates the logic for the queues so that we have essentially 3 possible configurations for macvlan offload. They consist of 15 macvlans with 4 queues per macvlan, 31 macvlans with 2 queues per macvlan, and 63 macvlans with 1 queue per macvlan. As macvlans are added you will encounter up to 3 total resets if you add all the way up to 63, and after that the device will stay in the mode supporting up to 63 macvlans until the L2FW flag is cleared. Signed-off-by: Alexander Duyck <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 865255b commit 8315ef6

File tree

2 files changed

+135
-62
lines changed

2 files changed

+135
-62
lines changed

drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

Lines changed: 132 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -5344,15 +5344,11 @@ static int ixgbe_fwd_ring_up(struct ixgbe_adapter *adapter,
53445344
struct net_device *vdev = accel->netdev;
53455345
int i, baseq, err;
53465346

5347-
if (!test_bit(accel->pool, adapter->fwd_bitmask))
5348-
return 0;
5349-
53505347
baseq = accel->pool * adapter->num_rx_queues_per_pool;
53515348
netdev_dbg(vdev, "pool %i:%i queues %i:%i\n",
53525349
accel->pool, adapter->num_rx_pools,
53535350
baseq, baseq + adapter->num_rx_queues_per_pool);
53545351

5355-
accel->netdev = vdev;
53565352
accel->rx_base_queue = baseq;
53575353
accel->tx_base_queue = baseq;
53585354

@@ -5372,9 +5368,17 @@ static int ixgbe_fwd_ring_up(struct ixgbe_adapter *adapter,
53725368
if (err >= 0)
53735369
return 0;
53745370

5371+
/* if we cannot add the MAC rule then disable the offload */
5372+
macvlan_release_l2fw_offload(vdev);
5373+
53755374
for (i = 0; i < adapter->num_rx_queues_per_pool; i++)
53765375
adapter->rx_ring[baseq + i]->netdev = NULL;
53775376

5377+
netdev_err(vdev, "L2FW offload disabled due to L2 filter error\n");
5378+
5379+
clear_bit(accel->pool, adapter->fwd_bitmask);
5380+
kfree(accel);
5381+
53785382
return err;
53795383
}
53805384

@@ -8799,6 +8803,49 @@ static void ixgbe_set_prio_tc_map(struct ixgbe_adapter *adapter)
87998803
}
88008804

88018805
#endif /* CONFIG_IXGBE_DCB */
8806+
static int ixgbe_reassign_macvlan_pool(struct net_device *vdev, void *data)
8807+
{
8808+
struct ixgbe_adapter *adapter = data;
8809+
struct ixgbe_fwd_adapter *accel;
8810+
int pool;
8811+
8812+
/* we only care about macvlans... */
8813+
if (!netif_is_macvlan(vdev))
8814+
return 0;
8815+
8816+
/* that have hardware offload enabled... */
8817+
accel = macvlan_accel_priv(vdev);
8818+
if (!accel)
8819+
return 0;
8820+
8821+
/* If we can relocate to a different bit do so */
8822+
pool = find_first_zero_bit(adapter->fwd_bitmask, adapter->num_rx_pools);
8823+
if (pool < adapter->num_rx_pools) {
8824+
set_bit(pool, adapter->fwd_bitmask);
8825+
accel->pool = pool;
8826+
return 0;
8827+
}
8828+
8829+
/* if we cannot find a free pool then disable the offload */
8830+
netdev_err(vdev, "L2FW offload disabled due to lack of queue resources\n");
8831+
macvlan_release_l2fw_offload(vdev);
8832+
kfree(accel);
8833+
8834+
return 0;
8835+
}
8836+
8837+
static void ixgbe_defrag_macvlan_pools(struct net_device *dev)
8838+
{
8839+
struct ixgbe_adapter *adapter = netdev_priv(dev);
8840+
8841+
/* flush any stale bits out of the fwd bitmask */
8842+
bitmap_clear(adapter->fwd_bitmask, 1, 63);
8843+
8844+
/* walk through upper devices reassigning pools */
8845+
netdev_walk_all_upper_dev_rcu(dev, ixgbe_reassign_macvlan_pool,
8846+
adapter);
8847+
}
8848+
88028849
/**
88038850
* ixgbe_setup_tc - configure net_device for multiple traffic classes
88048851
*
@@ -8866,6 +8913,8 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc)
88668913
#endif /* CONFIG_IXGBE_DCB */
88678914
ixgbe_init_interrupt_scheme(adapter);
88688915

8916+
ixgbe_defrag_macvlan_pools(dev);
8917+
88698918
if (netif_running(dev))
88708919
return ixgbe_open(dev);
88718920

@@ -9415,6 +9464,22 @@ static netdev_features_t ixgbe_fix_features(struct net_device *netdev,
94159464
return features;
94169465
}
94179466

9467+
static void ixgbe_reset_l2fw_offload(struct ixgbe_adapter *adapter)
9468+
{
9469+
int rss = min_t(int, ixgbe_max_rss_indices(adapter),
9470+
num_online_cpus());
9471+
9472+
/* go back to full RSS if we're not running SR-IOV */
9473+
if (!adapter->ring_feature[RING_F_VMDQ].offset)
9474+
adapter->flags &= ~(IXGBE_FLAG_VMDQ_ENABLED |
9475+
IXGBE_FLAG_SRIOV_ENABLED);
9476+
9477+
adapter->ring_feature[RING_F_RSS].limit = rss;
9478+
adapter->ring_feature[RING_F_VMDQ].limit = 1;
9479+
9480+
ixgbe_setup_tc(adapter->netdev, adapter->hw_tcs);
9481+
}
9482+
94189483
static int ixgbe_set_features(struct net_device *netdev,
94199484
netdev_features_t features)
94209485
{
@@ -9495,7 +9560,9 @@ static int ixgbe_set_features(struct net_device *netdev,
94959560
}
94969561
}
94979562

9498-
if (need_reset)
9563+
if ((changed & NETIF_F_HW_L2FW_DOFFLOAD) && adapter->num_rx_pools > 1)
9564+
ixgbe_reset_l2fw_offload(adapter);
9565+
else if (need_reset)
94999566
ixgbe_do_reset(netdev);
95009567
else if (changed & (NETIF_F_HW_VLAN_CTAG_RX |
95019568
NETIF_F_HW_VLAN_CTAG_FILTER))
@@ -9758,11 +9825,9 @@ static int ixgbe_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
97589825

97599826
static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
97609827
{
9761-
struct ixgbe_fwd_adapter *fwd_adapter = NULL;
97629828
struct ixgbe_adapter *adapter = netdev_priv(pdev);
9763-
int used_pools = adapter->num_vfs + adapter->num_rx_pools;
9829+
struct ixgbe_fwd_adapter *accel;
97649830
int tcs = adapter->hw_tcs ? : 1;
9765-
unsigned int limit;
97669831
int pool, err;
97679832

97689833
/* The hardware supported by ixgbe only filters on the destination MAC
@@ -9772,55 +9837,81 @@ static void *ixgbe_fwd_add(struct net_device *pdev, struct net_device *vdev)
97729837
if (!macvlan_supports_dest_filter(vdev))
97739838
return ERR_PTR(-EMEDIUMTYPE);
97749839

9775-
/* Hardware has a limited number of available pools. Each VF, and the
9776-
* PF require a pool. Check to ensure we don't attempt to use more
9777-
* then the available number of pools.
9778-
*/
9779-
if (used_pools >= IXGBE_MAX_VF_FUNCTIONS)
9780-
return ERR_PTR(-EINVAL);
9840+
pool = find_first_zero_bit(adapter->fwd_bitmask, adapter->num_rx_pools);
9841+
if (pool == adapter->num_rx_pools) {
9842+
u16 used_pools = adapter->num_vfs + adapter->num_rx_pools;
9843+
u16 reserved_pools;
9844+
9845+
if (((adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
9846+
adapter->num_rx_pools >= (MAX_TX_QUEUES / tcs)) ||
9847+
adapter->num_rx_pools > IXGBE_MAX_MACVLANS)
9848+
return ERR_PTR(-EBUSY);
9849+
9850+
/* Hardware has a limited number of available pools. Each VF,
9851+
* and the PF require a pool. Check to ensure we don't
9852+
* attempt to use more then the available number of pools.
9853+
*/
9854+
if (used_pools >= IXGBE_MAX_VF_FUNCTIONS)
9855+
return ERR_PTR(-EBUSY);
97819856

9782-
if (((adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
9783-
adapter->num_rx_pools >= (MAX_TX_QUEUES / tcs)) ||
9784-
(adapter->num_rx_pools > IXGBE_MAX_MACVLANS))
9785-
return ERR_PTR(-EBUSY);
9857+
/* Enable VMDq flag so device will be set in VM mode */
9858+
adapter->flags |= IXGBE_FLAG_VMDQ_ENABLED |
9859+
IXGBE_FLAG_SRIOV_ENABLED;
97869860

9787-
fwd_adapter = kzalloc(sizeof(*fwd_adapter), GFP_KERNEL);
9788-
if (!fwd_adapter)
9789-
return ERR_PTR(-ENOMEM);
9861+
/* Try to reserve as many queues per pool as possible,
9862+
* we start with the configurations that support 4 queues
9863+
* per pools, followed by 2, and then by just 1 per pool.
9864+
*/
9865+
if (used_pools < 32 && adapter->num_rx_pools < 16)
9866+
reserved_pools = min_t(u16,
9867+
32 - used_pools,
9868+
16 - adapter->num_rx_pools);
9869+
else if (adapter->num_rx_pools < 32)
9870+
reserved_pools = min_t(u16,
9871+
64 - used_pools,
9872+
32 - adapter->num_rx_pools);
9873+
else
9874+
reserved_pools = 64 - used_pools;
97909875

9791-
pool = find_first_zero_bit(adapter->fwd_bitmask, adapter->num_rx_pools);
9792-
set_bit(pool, adapter->fwd_bitmask);
9793-
limit = find_last_bit(adapter->fwd_bitmask, adapter->num_rx_pools + 1);
97949876

9795-
/* Enable VMDq flag so device will be set in VM mode */
9796-
adapter->flags |= IXGBE_FLAG_VMDQ_ENABLED | IXGBE_FLAG_SRIOV_ENABLED;
9797-
adapter->ring_feature[RING_F_VMDQ].limit = limit + 1;
9877+
if (!reserved_pools)
9878+
return ERR_PTR(-EBUSY);
97989879

9799-
fwd_adapter->pool = pool;
9880+
adapter->ring_feature[RING_F_VMDQ].limit += reserved_pools;
98009881

9801-
/* Force reinit of ring allocation with VMDQ enabled */
9802-
err = ixgbe_setup_tc(pdev, adapter->hw_tcs);
9882+
/* Force reinit of ring allocation with VMDQ enabled */
9883+
err = ixgbe_setup_tc(pdev, adapter->hw_tcs);
9884+
if (err)
9885+
return ERR_PTR(err);
98039886

9804-
if (!err && netif_running(pdev))
9805-
err = ixgbe_fwd_ring_up(adapter, fwd_adapter);
9887+
if (pool >= adapter->num_rx_pools)
9888+
return ERR_PTR(-ENOMEM);
9889+
}
98069890

9807-
if (!err)
9808-
return fwd_adapter;
9891+
accel = kzalloc(sizeof(*accel), GFP_KERNEL);
9892+
if (!accel)
9893+
return ERR_PTR(-ENOMEM);
9894+
9895+
set_bit(pool, adapter->fwd_bitmask);
9896+
accel->pool = pool;
9897+
accel->netdev = vdev;
98099898

9810-
/* unwind counter and free adapter struct */
9811-
netdev_info(pdev,
9812-
"%s: dfwd hardware acceleration failed\n", vdev->name);
9813-
clear_bit(pool, adapter->fwd_bitmask);
9814-
kfree(fwd_adapter);
9815-
return ERR_PTR(err);
9899+
if (!netif_running(pdev))
9900+
return accel;
9901+
9902+
err = ixgbe_fwd_ring_up(adapter, accel);
9903+
if (err)
9904+
return ERR_PTR(err);
9905+
9906+
return accel;
98169907
}
98179908

98189909
static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
98199910
{
98209911
struct ixgbe_fwd_adapter *accel = priv;
98219912
struct ixgbe_adapter *adapter = netdev_priv(pdev);
98229913
unsigned int rxbase = accel->rx_base_queue;
9823-
unsigned int limit, i;
9914+
unsigned int i;
98249915

98259916
/* delete unicast filter associated with offloaded interface */
98269917
ixgbe_del_mac_filter(adapter, accel->netdev->dev_addr,
@@ -9844,25 +9935,6 @@ static void ixgbe_fwd_del(struct net_device *pdev, void *priv)
98449935
}
98459936

98469937
clear_bit(accel->pool, adapter->fwd_bitmask);
9847-
limit = find_last_bit(adapter->fwd_bitmask, adapter->num_rx_pools);
9848-
adapter->ring_feature[RING_F_VMDQ].limit = limit + 1;
9849-
9850-
/* go back to full RSS if we're done with our VMQs */
9851-
if (adapter->ring_feature[RING_F_VMDQ].limit == 1) {
9852-
int rss = min_t(int, ixgbe_max_rss_indices(adapter),
9853-
num_online_cpus());
9854-
9855-
adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED;
9856-
adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
9857-
adapter->ring_feature[RING_F_RSS].limit = rss;
9858-
}
9859-
9860-
ixgbe_setup_tc(pdev, adapter->hw_tcs);
9861-
netdev_dbg(pdev, "pool %i:%i queues %i:%i\n",
9862-
accel->pool, adapter->num_rx_pools,
9863-
accel->rx_base_queue,
9864-
accel->rx_base_queue +
9865-
adapter->num_rx_queues_per_pool);
98669938
kfree(accel);
98679939
}
98689940

drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ int ixgbe_disable_sriov(struct ixgbe_adapter *adapter)
266266
#endif
267267

268268
/* Disable VMDq flag so device will be set in VM mode */
269-
if (adapter->ring_feature[RING_F_VMDQ].limit == 1) {
269+
if (bitmap_weight(adapter->fwd_bitmask, adapter->num_rx_pools) == 1) {
270270
adapter->flags &= ~IXGBE_FLAG_VMDQ_ENABLED;
271271
adapter->flags &= ~IXGBE_FLAG_SRIOV_ENABLED;
272272
rss = min_t(int, ixgbe_max_rss_indices(adapter),
@@ -312,7 +312,8 @@ static int ixgbe_pci_sriov_enable(struct pci_dev *dev, int num_vfs)
312312
* other values out of range.
313313
*/
314314
num_tc = adapter->hw_tcs;
315-
num_rx_pools = adapter->num_rx_pools;
315+
num_rx_pools = bitmap_weight(adapter->fwd_bitmask,
316+
adapter->num_rx_pools);
316317
limit = (num_tc > 4) ? IXGBE_MAX_VFS_8TC :
317318
(num_tc > 1) ? IXGBE_MAX_VFS_4TC : IXGBE_MAX_VFS_1TC;
318319

0 commit comments

Comments
 (0)