Skip to content

Commit 6622f5c

Browse files
jacob-kellerJeff Kirsher
authored andcommitted
i40e: make use of __dev_uc_sync and __dev_mc_sync
The kernel provides __dev_uc_sync and __dev_mc_sync in order for drivers which need individual notification of add and delete for each filter. These functions allow us to vastly simplify our .set_rx_mode handler. We need to implement two functions for sync and unsync which add and remove filters respectively. This change avoids a very complex and inefficient algorithm which resulted in an abnormal latency for the .set_rx_mode NDO operation. The resulting code after this change is more readable, more efficient, and less code. Due to the callback signature used by these functions we also must update several other functions to take a const u8 * pointer. Change-Id: I2ca7fd4e10c0c07ed2291db1ea41bf5987fc6474 Signed-off-by: Jacob Keller <[email protected]> Tested-by: Andrew Bowers <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 1bc87e8 commit 6622f5c

File tree

2 files changed

+69
-54
lines changed

2 files changed

+69
-54
lines changed

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -720,8 +720,8 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf);
720720
bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
721721
void i40e_set_ethtool_ops(struct net_device *netdev);
722722
struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
723-
u8 *macaddr, s16 vlan);
724-
void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan);
723+
const u8 *macaddr, s16 vlan);
724+
void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan);
725725
int i40e_sync_vsi_filters(struct i40e_vsi *vsi);
726726
struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
727727
u16 uplink, u32 param1);
@@ -813,10 +813,10 @@ void i40e_vlan_stripping_disable(struct i40e_vsi *vsi);
813813
int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid);
814814
int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid);
815815
struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi,
816-
u8 *macaddr);
817-
int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr);
816+
const u8 *macaddr);
817+
int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr);
818818
bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi);
819-
struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr);
819+
struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr);
820820
#ifdef I40E_FCOE
821821
int __i40e_setup_tc(struct net_device *netdev, u32 handle, __be16 proto,
822822
struct tc_to_netdev *tc);

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 64 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,7 +1149,7 @@ void i40e_update_stats(struct i40e_vsi *vsi)
11491149
* Returns ptr to the filter object or NULL
11501150
**/
11511151
static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi,
1152-
u8 *macaddr, s16 vlan)
1152+
const u8 *macaddr, s16 vlan)
11531153
{
11541154
struct i40e_mac_filter *f;
11551155

@@ -1172,7 +1172,7 @@ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi,
11721172
* Returns the first filter with the provided MAC address or NULL if
11731173
* MAC address was not found
11741174
**/
1175-
struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, u8 *macaddr)
1175+
struct i40e_mac_filter *i40e_find_mac(struct i40e_vsi *vsi, const u8 *macaddr)
11761176
{
11771177
struct i40e_mac_filter *f;
11781178

@@ -1217,7 +1217,8 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi)
12171217
*
12181218
* Returns first filter found on success, else NULL
12191219
**/
1220-
struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr)
1220+
struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi,
1221+
const u8 *macaddr)
12211222
{
12221223
struct i40e_mac_filter *f;
12231224

@@ -1243,7 +1244,7 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr)
12431244
*
12441245
* Returns 0 for success, or error
12451246
**/
1246-
int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr)
1247+
int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, const u8 *macaddr)
12471248
{
12481249
struct i40e_mac_filter *f = NULL;
12491250
int changed = 0;
@@ -1275,7 +1276,7 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr)
12751276
* being held.
12761277
**/
12771278
struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
1278-
u8 *macaddr, s16 vlan)
1279+
const u8 *macaddr, s16 vlan)
12791280
{
12801281
struct i40e_mac_filter *f;
12811282

@@ -1338,7 +1339,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
13381339
* the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
13391340
* instead of list_for_each_entry().
13401341
**/
1341-
void i40e_del_filter(struct i40e_vsi *vsi, u8 *macaddr, s16 vlan)
1342+
void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
13421343
{
13431344
struct i40e_mac_filter *f;
13441345

@@ -1567,6 +1568,52 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
15671568
ctxt->info.valid_sections |= cpu_to_le16(sections);
15681569
}
15691570

1571+
/**
1572+
* i40e_addr_sync - Callback for dev_(mc|uc)_sync to add address
1573+
* @netdev: the netdevice
1574+
* @addr: address to add
1575+
*
1576+
* Called by __dev_(mc|uc)_sync when an address needs to be added. We call
1577+
* __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
1578+
*/
1579+
static int i40e_addr_sync(struct net_device *netdev, const u8 *addr)
1580+
{
1581+
struct i40e_netdev_priv *np = netdev_priv(netdev);
1582+
struct i40e_vsi *vsi = np->vsi;
1583+
struct i40e_mac_filter *f;
1584+
1585+
if (i40e_is_vsi_in_vlan(vsi))
1586+
f = i40e_put_mac_in_vlan(vsi, addr);
1587+
else
1588+
f = i40e_add_filter(vsi, addr, I40E_VLAN_ANY);
1589+
1590+
if (f)
1591+
return 0;
1592+
else
1593+
return -ENOMEM;
1594+
}
1595+
1596+
/**
1597+
* i40e_addr_unsync - Callback for dev_(mc|uc)_sync to remove address
1598+
* @netdev: the netdevice
1599+
* @addr: address to add
1600+
*
1601+
* Called by __dev_(mc|uc)_sync when an address needs to be removed. We call
1602+
* __dev_(uc|mc)_sync from .set_rx_mode and guarantee to hold the hash lock.
1603+
*/
1604+
static int i40e_addr_unsync(struct net_device *netdev, const u8 *addr)
1605+
{
1606+
struct i40e_netdev_priv *np = netdev_priv(netdev);
1607+
struct i40e_vsi *vsi = np->vsi;
1608+
1609+
if (i40e_is_vsi_in_vlan(vsi))
1610+
i40e_del_mac_all_vlan(vsi, addr);
1611+
else
1612+
i40e_del_filter(vsi, addr, I40E_VLAN_ANY);
1613+
1614+
return 0;
1615+
}
1616+
15701617
/**
15711618
* i40e_set_rx_mode - NDO callback to set the netdev filters
15721619
* @netdev: network interface device structure
@@ -1578,54 +1625,13 @@ static void i40e_set_rx_mode(struct net_device *netdev)
15781625
#endif
15791626
{
15801627
struct i40e_netdev_priv *np = netdev_priv(netdev);
1581-
struct i40e_mac_filter *f, *ftmp;
15821628
struct i40e_vsi *vsi = np->vsi;
1583-
struct netdev_hw_addr *uca;
1584-
struct netdev_hw_addr *mca;
1585-
struct netdev_hw_addr *ha;
15861629

15871630
spin_lock_bh(&vsi->mac_filter_list_lock);
15881631

1589-
/* add addr if not already in the filter list */
1590-
netdev_for_each_uc_addr(uca, netdev) {
1591-
if (!i40e_find_mac(vsi, uca->addr)) {
1592-
if (i40e_is_vsi_in_vlan(vsi))
1593-
i40e_put_mac_in_vlan(vsi, uca->addr);
1594-
else
1595-
i40e_add_filter(vsi, uca->addr, I40E_VLAN_ANY);
1596-
}
1597-
}
1598-
1599-
netdev_for_each_mc_addr(mca, netdev) {
1600-
if (!i40e_find_mac(vsi, mca->addr)) {
1601-
if (i40e_is_vsi_in_vlan(vsi))
1602-
i40e_put_mac_in_vlan(vsi, mca->addr);
1603-
else
1604-
i40e_add_filter(vsi, mca->addr, I40E_VLAN_ANY);
1605-
}
1606-
}
1632+
__dev_uc_sync(netdev, i40e_addr_sync, i40e_addr_unsync);
1633+
__dev_mc_sync(netdev, i40e_addr_sync, i40e_addr_unsync);
16071634

1608-
/* remove filter if not in netdev list */
1609-
list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list) {
1610-
1611-
netdev_for_each_mc_addr(mca, netdev)
1612-
if (ether_addr_equal(mca->addr, f->macaddr))
1613-
goto bottom_of_search_loop;
1614-
1615-
netdev_for_each_uc_addr(uca, netdev)
1616-
if (ether_addr_equal(uca->addr, f->macaddr))
1617-
goto bottom_of_search_loop;
1618-
1619-
for_each_dev_addr(netdev, ha)
1620-
if (ether_addr_equal(ha->addr, f->macaddr))
1621-
goto bottom_of_search_loop;
1622-
1623-
/* f->macaddr wasn't found in uc, mc, or ha list so delete it */
1624-
i40e_del_filter(vsi, f->macaddr, I40E_VLAN_ANY);
1625-
1626-
bottom_of_search_loop:
1627-
continue;
1628-
}
16291635
spin_unlock_bh(&vsi->mac_filter_list_lock);
16301636

16311637
/* check for other flag changes */
@@ -9434,8 +9440,17 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
94349440
}
94359441

94369442
spin_lock_bh(&vsi->mac_filter_list_lock);
9443+
9444+
/* clear the sync flag on all filters */
9445+
if (vsi->netdev) {
9446+
__dev_uc_unsync(vsi->netdev, NULL);
9447+
__dev_mc_unsync(vsi->netdev, NULL);
9448+
}
9449+
9450+
/* make sure any remaining filters are marked for deletion */
94379451
list_for_each_entry_safe(f, ftmp, &vsi->mac_filter_list, list)
94389452
i40e_del_filter(vsi, f->macaddr, f->vlan);
9453+
94399454
spin_unlock_bh(&vsi->mac_filter_list_lock);
94409455

94419456
i40e_sync_vsi_filters(vsi);

0 commit comments

Comments
 (0)