@@ -1149,7 +1149,7 @@ void i40e_update_stats(struct i40e_vsi *vsi)
1149
1149
* Returns ptr to the filter object or NULL
1150
1150
**/
1151
1151
static struct i40e_mac_filter * i40e_find_filter (struct i40e_vsi * vsi ,
1152
- u8 * macaddr , s16 vlan )
1152
+ const u8 * macaddr , s16 vlan )
1153
1153
{
1154
1154
struct i40e_mac_filter * f ;
1155
1155
@@ -1172,7 +1172,7 @@ static struct i40e_mac_filter *i40e_find_filter(struct i40e_vsi *vsi,
1172
1172
* Returns the first filter with the provided MAC address or NULL if
1173
1173
* MAC address was not found
1174
1174
**/
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 )
1176
1176
{
1177
1177
struct i40e_mac_filter * f ;
1178
1178
@@ -1217,7 +1217,8 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi)
1217
1217
*
1218
1218
* Returns first filter found on success, else NULL
1219
1219
**/
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 )
1221
1222
{
1222
1223
struct i40e_mac_filter * f ;
1223
1224
@@ -1243,7 +1244,7 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, u8 *macaddr)
1243
1244
*
1244
1245
* Returns 0 for success, or error
1245
1246
**/
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 )
1247
1248
{
1248
1249
struct i40e_mac_filter * f = NULL ;
1249
1250
int changed = 0 ;
@@ -1275,7 +1276,7 @@ int i40e_del_mac_all_vlan(struct i40e_vsi *vsi, u8 *macaddr)
1275
1276
* being held.
1276
1277
**/
1277
1278
struct i40e_mac_filter * i40e_add_filter (struct i40e_vsi * vsi ,
1278
- u8 * macaddr , s16 vlan )
1279
+ const u8 * macaddr , s16 vlan )
1279
1280
{
1280
1281
struct i40e_mac_filter * f ;
1281
1282
@@ -1338,7 +1339,7 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
1338
1339
* the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
1339
1340
* instead of list_for_each_entry().
1340
1341
**/
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 )
1342
1343
{
1343
1344
struct i40e_mac_filter * f ;
1344
1345
@@ -1567,6 +1568,52 @@ static void i40e_vsi_setup_queue_map(struct i40e_vsi *vsi,
1567
1568
ctxt -> info .valid_sections |= cpu_to_le16 (sections );
1568
1569
}
1569
1570
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
+
1570
1617
/**
1571
1618
* i40e_set_rx_mode - NDO callback to set the netdev filters
1572
1619
* @netdev: network interface device structure
@@ -1578,54 +1625,13 @@ static void i40e_set_rx_mode(struct net_device *netdev)
1578
1625
#endif
1579
1626
{
1580
1627
struct i40e_netdev_priv * np = netdev_priv (netdev );
1581
- struct i40e_mac_filter * f , * ftmp ;
1582
1628
struct i40e_vsi * vsi = np -> vsi ;
1583
- struct netdev_hw_addr * uca ;
1584
- struct netdev_hw_addr * mca ;
1585
- struct netdev_hw_addr * ha ;
1586
1629
1587
1630
spin_lock_bh (& vsi -> mac_filter_list_lock );
1588
1631
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 );
1607
1634
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
- }
1629
1635
spin_unlock_bh (& vsi -> mac_filter_list_lock );
1630
1636
1631
1637
/* check for other flag changes */
@@ -9434,8 +9440,17 @@ int i40e_vsi_release(struct i40e_vsi *vsi)
9434
9440
}
9435
9441
9436
9442
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 */
9437
9451
list_for_each_entry_safe (f , ftmp , & vsi -> mac_filter_list , list )
9438
9452
i40e_del_filter (vsi , f -> macaddr , f -> vlan );
9453
+
9439
9454
spin_unlock_bh (& vsi -> mac_filter_list_lock );
9440
9455
9441
9456
i40e_sync_vsi_filters (vsi );
0 commit comments