i40e/i40evf updates
Subsystems (2)
cover i40e/i40evf updates
Alan Brady adds code to fix mac filters when removing vlans.
Jacob Keller drops is_vf and is_netdev fields in struct i40e_mac_filter, adds code to make use of __dev_uc_sync and __dev_mc_sync, moves i40e_put_mac_in_vlan and i40e_del_mac_all_vlan, fixes i40e_put_mac_in_vlan to return actual filter added, adds code to ignore removed filters When searching all MAC/VLAN filters, implements __i40e_del_filter and use where applicable, adds code to store MAC/VLAN filters in a hash with the MAC Address as key, adds code to properly cleanup on allocation failure in i40e_sync_vsi_filters, adds code to avoid looping to check whether we're in vlan mode, removes duplicate add/ delete adminq command code for filters, corrects check for reading TSYNINDX from the receive descriptor, uses a mutex instead of spinlock in PTP user entry points, replaces PTP Rx timestamp hang logic and adds code to avoid an extra msleep while waiting for reset.
drivers/net/ethernet/intel/i40e/i40e.h | 50 +- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 92 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 949 +++++++++++---------- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 137 +-- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 9 +- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 2 - drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 57 +- drivers/net/ethernet/intel/i40evf/i40evf_main.c | 8 +- 8 files changed, 663 insertions(+), 641 deletions(-)
Signature · 1 line
2.4.11
PATCH 1/15 i40e: drop is_vf and is_netdev fields in struct i40e_mac_filter
From: Jacob Keller <[email protected]>
Originally the is_vf and is_netdev fields were added in order to distinguish between VF and netdev filters in a single VSI. However, it can be noted that we use separate VSI for SRIOV VFs and for netdev VSI. Thus, since a single VSI should only ever have one type of filter, we can simply remove the checks and remove the typing.
In a similar fashion, we can note that the only remaining way to get multiple filters of a single type is through a debug command that was added to debugfs. This command is useless in practice, and results in causing bugs if we keep counter tracking but lose the is_vf and is_netdev protections as desired above.
Since the only time we'd actually have a counter value besides 0 and 1 is through use of this debugfs hook, we can remove this unnecessary command, and the entire counter logic it required.
We vastly simplify mac filters by removing
(a) the distinction between vf and netdev filters
(b) counting logic
(c) the ability to add and remove filters bypassing the stack via debugfs
---
Testing-hints:
Should test add and remove of various filters with high frequency. Ensure that debugfs cannot add or remove filters any more.
drivers/net/ethernet/intel/i40e/i40e.h | 19 +- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 88 +------- drivers/net/ethernet/intel/i40e/i40e_main.c | 227 ++++++--------------- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 19 +- 4 files changed, 85 insertions(+), 268 deletions(-)
drivers/net/ethernet/intel/i40e/i40e.h +6 -13
@@ -458,9 +458,6 @@ struct i40e_mac_filter {u8 macaddr[ETH_ALEN ];#define I40E_VLAN_ANY -1s16 vlan; -u8 counter;/* number of instances of this filter */ -bool is_vf;/* filter belongs to a VF */ -bool is_netdev;/* filter belongs to a netdev */ enum i40e_filter_state state; };
@@ -742,10 +739,8 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf);bool i40e_set_ntuple (struct i40e_pf *pf,netdev_features_t features);void i40e_set_ethtool_ops (struct net_device *netdev);struct i40e_mac_filter *i40e_add_filter (struct i40e_vsi *vsi, -u8 *macaddr,s16 vlan, -bool is_vf,bool is_netdev); -void i40e_del_filter (struct i40e_vsi *vsi,u8 *macaddr,s16 vlan, -bool is_vf,bool is_netdev); +u8 *macaddr,s16 vlan); +void i40e_del_filter (struct i40e_vsi *vsi,u8 *macaddr,s16 vlan);int i40e_sync_vsi_filters (struct i40e_vsi *vsi);struct i40e_vsi *i40e_vsi_setup (struct i40e_pf *pf,u8 type,u16 uplink,u32 param1);
@@ -836,13 +831,11 @@ int i40e_vsi_open(struct i40e_vsi *vsi);void i40e_vlan_stripping_disable (struct i40e_vsi *vsi);int i40e_vsi_add_vlan (struct i40e_vsi *vsi,s16 vid);int i40e_vsi_kill_vlan (struct i40e_vsi *vsi,s16 vid); -struct i40e_mac_filter *i40e_put_mac_in_vlan (struct i40e_vsi *vsi,u8 *macaddr, -bool is_vf,bool is_netdev); -int i40e_del_mac_all_vlan (struct i40e_vsi *vsi,u8 *macaddr, -bool is_vf,bool is_netdev); +struct i40e_mac_filter *i40e_put_mac_in_vlan (struct i40e_vsi *vsi, +u8 *macaddr); +int i40e_del_mac_all_vlan (struct i40e_vsi *vsi,u8 *macaddr);bool i40e_is_vsi_in_vlan (struct i40e_vsi *vsi); -struct i40e_mac_filter *i40e_find_mac (struct i40e_vsi *vsi,u8 *macaddr, -bool is_vf,bool is_netdev); +struct i40e_mac_filter *i40e_find_mac (struct i40e_vsi *vsi,u8 *macaddr);#ifdef I40E_FCOE int __i40e_setup_tc (struct net_device *netdev,u32 handle,__be16 proto,struct tc_to_netdev *tc);
drivers/net/ethernet/intel/i40e/i40e_debugfs.c +3 -85
106 lines not on this page · raw message
drivers/net/ethernet/intel/i40e/i40e_main.c +68 -159
473 lines not on this page · raw message
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +8 -11
@@ -689,8 +689,8 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)spin_lock_bh (&vsi->mac_filter_list_lock);if (is_valid_ether_addr (vf->default_lan_addr.addr)) { f =i40e_add_filter (vsi, vf->default_lan_addr.addr, - vf->port_vlan_id ? vf->port_vlan_id :-1 , - true, false); + vf->port_vlan_id ? + vf->port_vlan_id :-1 );if (!f) dev_info(&pf->pdev->dev, "Could not add MAC filter %pM for VF %d\n",
@@ -1933,14 +1933,12 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)for (i =0 ; i < al->num_elements; i++) {struct i40e_mac_filter *f; - f =i40e_find_mac (vsi, al->list[i].addr, true, false); + f =i40e_find_mac (vsi, al->list[i].addr);if (!f) {if (i40e_is_vsi_in_vlan (vsi)) - f =i40e_put_mac_in_vlan (vsi, al->list[i].addr, - true, false); + f =i40e_put_mac_in_vlan (vsi, al->list[i].addr);else - f =i40e_add_filter (vsi, al->list[i].addr,-1 , - true, false); + f =i40e_add_filter (vsi, al->list[i].addr,-1 ); }if (!f) {
@@ -2006,7 +2004,7 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)spin_lock_bh (&vsi->mac_filter_list_lock);/* delete addresses from the list */ for (i =0 ; i < al->num_elements; i++) -if (i40e_del_mac_all_vlan (vsi, al->list[i].addr, true, false)) { +if (i40e_del_mac_all_vlan (vsi, al->list[i].addr)) { ret =I40E_ERR_INVALID_MAC_ADDR ;spin_unlock_bh (&vsi->mac_filter_list_lock); goto error_param;
@@ -2722,14 +2720,13 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)/* delete the temporary mac address */ if (!is_zero_ether_addr (vf->default_lan_addr.addr))i40e_del_filter (vsi, vf->default_lan_addr.addr, - vf->port_vlan_id ? vf->port_vlan_id :-1 , - true, false); + vf->port_vlan_id ? vf->port_vlan_id :-1 );/* Delete all the filters for this VSI - we're going to kill it * anyway. */ list_for_each_entry (f, &vsi->mac_filter_list, list) -i40e_del_filter (vsi, f->macaddr, f->vlan, true, false); +i40e_del_filter (vsi, f->macaddr, f->vlan);spin_unlock_bh (&vsi->mac_filter_list_lock);
Signature · 1 line
2.4.11
PATCH 1/15 i40e: drop is_vf and is_netdev fields in struct i40e_mac_filter
Quoted 18 lines · Bimmy Pujari
From: Jacob Keller <[email protected]>
Originally the
is_vfandis_netdevfields were added in order to distinguish between VF and netdev filters in a single VSI. However, it can be noted that we use separate VSI for SRIOV VFs and for netdev VSI. Thus, since a single VSI should only ever have one type of filter, we can simply remove the checks and remove the typing.In a similar fashion, we can note that the only remaining way to get multiple filters of a single type is through a debug command that was added to debugfs. This command is useless in practice, and results in causing bugs if we keep counter tracking but lose the
is_vfandis_netdevprotections as desired above.Since the only time we'd actually have a counter value besides 0 and 1 is through use of this debugfs hook, we can remove this unnecessary command, and the entire counter logic it required.
Quoted 8 lines
We vastly simplify mac filters by removing
(a) the distinction between vf and netdev filters
(b) counting logic
(c) the ability to add and remove filters bypassing the stack via debugfsSigned-off-by Jacob Keller <[email protected]>Change-ID Idf916dd2a1159b1188ddbab5bef6b85ea6bf27d9
Does not compile, here are the errors:
[23:59:15 @jtkirshe-linux:next-queue]$ make -j 77 -s
? DESCEND??objtooldrivers/net/ethernet/intel/i40e/i40e_fcoe.c: In function
?i40e_fcoe_config_netdev?:drivers/net/ethernet/intel/i40e/i40e_fcoe.c:1526:2: error: too many
arguments to function ?i40e_add_filter?
? i40e_add_filter(vsi, hw->mac.san_addr, 0, false, false);
? ^~~~~~~~~~~~~~~
In file included from drivers/net/ethernet/intel/i40e/i40e_fcoe.c:37:0:drivers/net/ethernet/intel/i40e/i40e.h:722:25: note: declared here
?struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, ?????????????????????????^~~~~~~~~~~~~~~ drivers/net/ethernet/intel/i40e/i40e_fcoe.c:1527:2: error: too many
arguments to function ?i40e_add_filter?
? i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0, false, false);
? ^~~~~~~~~~~~~~~
In file included from drivers/net/ethernet/intel/i40e/i40e_fcoe.c:37:0:drivers/net/ethernet/intel/i40e/i40e.h:722:25: note: declared here
?struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, ?????????????????????????^~~~~~~~~~~~~~~ drivers/net/ethernet/intel/i40e/i40e_fcoe.c:1528:2: error: too many
arguments to function ?i40e_add_filter?
? i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0, false, false);
? ^~~~~~~~~~~~~~~
In file included from drivers/net/ethernet/intel/i40e/i40e_fcoe.c:37:0:drivers/net/ethernet/intel/i40e/i40e.h:722:25: note: declared here
?struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, ?????????????????????????^~~~~~~~~~~~~~~ drivers/net/ethernet/intel/i40e/i40e_fcoe.c:1529:2: error: too many
arguments to function ?i40e_add_filter?
? i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0, false, false);
? ^~~~~~~~~~~~~~~
In file included from drivers/net/ethernet/intel/i40e/i40e_fcoe.c:37:0:drivers/net/ethernet/intel/i40e/i40e.h:722:25: note: declared here
?struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, ?????????????????????????^~~~~~~~~~~~~~~scripts/Makefile.build:289: recipe for target 'drivers/net/ethernet/intel/i40e/i40e_fcoe.o' failed
make[5]: *** [drivers/net/ethernet/intel/i40e/i40e_fcoe.o] Error 1
make[5]: *** Waiting for unfinished jobs....scripts/Makefile.build:440: recipe for target
'drivers/net/ethernet/intel/i40e' failed
make[4]: *** [drivers/net/ethernet/intel/i40e] Error 2scripts/Makefile.build:440: recipe for target 'drivers/net/ethernet/intel'
failed
make[3]: *** [drivers/net/ethernet/intel] Error 2scripts/Makefile.build:440: recipe for target 'drivers/net/ethernet' failed
make[2]: *** [drivers/net/ethernet] Error 2scripts/Makefile.build:440: recipe for target 'drivers/net' failed
make[1]: *** [drivers/net] Error 2
Makefile:968: recipe for target 'drivers' failed
make: *** [drivers] Error 2
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.osuosl.org/pipermail/intel-wired-lan/attachments/20160930/f6f17b56/attachment.asc>
PATCH 2/15 i40e: make use of __dev_uc_sync and __dev_mc_sync
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
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.
--- drivers/net/ethernet/intel/i40e/i40e.h | 10 +-- drivers/net/ethernet/intel/i40e/i40e_main.c | 113 ++++++++++++++++------------ 2 files changed, 69 insertions(+), 54 deletions(-)
drivers/net/ethernet/intel/i40e/i40e.h +5 -5
@@ -739,8 +739,8 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf);bool i40e_set_ntuple (struct i40e_pf *pf,netdev_features_t features);void i40e_set_ethtool_ops (struct net_device *netdev);struct i40e_mac_filter *i40e_add_filter (struct i40e_vsi *vsi, -u8 *macaddr,s16 vlan); -void i40e_del_filter (struct i40e_vsi *vsi,u8 *macaddr,s16 vlan); +const u8 *macaddr,s16 vlan); +void i40e_del_filter (struct i40e_vsi *vsi,const u8 *macaddr,s16 vlan);int i40e_sync_vsi_filters (struct i40e_vsi *vsi);struct i40e_vsi *i40e_vsi_setup (struct i40e_pf *pf,u8 type,u16 uplink,u32 param1);
@@ -832,10 +832,10 @@ void i40e_vlan_stripping_disable(struct i40e_vsi *vsi);int i40e_vsi_add_vlan (struct i40e_vsi *vsi,s16 vid);int i40e_vsi_kill_vlan (struct i40e_vsi *vsi,s16 vid);struct i40e_mac_filter *i40e_put_mac_in_vlan (struct i40e_vsi *vsi, -u8 *macaddr); -int i40e_del_mac_all_vlan (struct i40e_vsi *vsi,u8 *macaddr); +const u8 *macaddr); +int i40e_del_mac_all_vlan (struct i40e_vsi *vsi,const u8 *macaddr);bool i40e_is_vsi_in_vlan (struct i40e_vsi *vsi); -struct i40e_mac_filter *i40e_find_mac (struct i40e_vsi *vsi,u8 *macaddr); +struct i40e_mac_filter *i40e_find_mac (struct i40e_vsi *vsi,const u8 *macaddr);#ifdef I40E_FCOE int __i40e_setup_tc (struct net_device *netdev,u32 handle,__be16 proto,struct tc_to_netdev *tc);
drivers/net/ethernet/intel/i40e/i40e_main.c +64 -49
174 lines not on this page · raw message
Signature · 1 line
2.4.11
PATCH 3/15 i40e: move i40e_put_mac_in_vlan and i40e_del_mac_all_vlan
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
A future patch will be modifying these functions and making a call to a static function which currently is defined after these functions. Move them in a separate patch to ease review and ensure the moved code is correct.
--- drivers/net/ethernet/intel/i40e/i40e_main.c | 113 ++++++++++++++-------------- 1 file changed, 56 insertions(+), 57 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_main.c +56 -57
@@ -1208,63 +1208,6 @@ bool i40e_is_vsi_in_vlan(struct i40e_vsi *vsi) }/** -* i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans -* @vsi: the VSI to be searched -* @macaddr: the mac address to be filtered -* -* Goes through all the macvlan filters and adds a -* macvlan filter for each unique vlan that already exists -* -* Returns first filter found on success, else NULL -**/ -struct i40e_mac_filter *i40e_put_mac_in_vlan (struct i40e_vsi *vsi, -const u8 *macaddr) -{ -struct i40e_mac_filter *f; - -list_for_each_entry (f, &vsi->mac_filter_list, list) { -if (vsi->info.pvid) - f->vlan =le16_to_cpu (vsi->info.pvid); -if (!i40e_find_filter (vsi, macaddr, f->vlan)) { -if (!i40e_add_filter (vsi, macaddr, f->vlan)) -return NULL ; - } - } - -return list_first_entry_or_null (&vsi->mac_filter_list, - struct i40e_mac_filter, list); -} - -/** -* i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS -* @vsi: the VSI to be searched -* @macaddr: the mac address to be removed -* -* Removes a given MAC address from a VSI, regardless of VLAN -* -* Returns 0 for success, or error -**/ -int i40e_del_mac_all_vlan (struct i40e_vsi *vsi,const u8 *macaddr) -{ -struct i40e_mac_filter *f =NULL ; -int changed =0 ; - -WARN (!spin_is_locked (&vsi->mac_filter_list_lock), -"Missing mac_filter_list_lock\n" ); -list_for_each_entry (f, &vsi->mac_filter_list, list) { -if ((ether_addr_equal (macaddr, f->macaddr))) { - f->state =I40E_FILTER_REMOVE ; - } - } -if (changed) { - vsi->flags |=I40E_VSI_FLAG_FILTER_CHANGED ; - vsi->back->flags |=I40E_FLAG_FILTER_SYNC ; -return 0 ; - } -return -ENOENT ; -} - -/** * i40e_add_filter - Add a mac/vlan filter to the VSI * @vsi: the VSI to be searched * @macaddr: the MAC address
@@ -1365,6 +1308,62 @@ void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan) }/** +* i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans +* @vsi: the VSI to be searched +* @macaddr: the mac address to be filtered +* +* Goes through all the macvlan filters and adds a +* macvlan filter for each unique vlan that already exists +* +* Returns first filter found on success, else NULL +**/ +struct i40e_mac_filter *i40e_put_mac_in_vlan (struct i40e_vsi *vsi, +const u8 *macaddr) +{ +struct i40e_mac_filter *f; + +list_for_each_entry (f, &vsi->mac_filter_list, list) { +if (vsi->info.pvid) + f->vlan =le16_to_cpu (vsi->info.pvid); +if (!i40e_find_filter (vsi, macaddr, f->vlan)) { +if (!i40e_add_filter (vsi, macaddr, f->vlan)) +return NULL ; + } + } + +return list_first_entry_or_null (&vsi->mac_filter_list, + struct i40e_mac_filter, list); +} + +/** +* i40e_del_mac_all_vlan - Remove a MAC filter from all VLANS +* @vsi: the VSI to be searched +* @macaddr: the mac address to be removed +* +* Removes a given MAC address from a VSI, regardless of VLAN +* +* Returns 0 for success, or error +**/ +int i40e_del_mac_all_vlan (struct i40e_vsi *vsi,const u8 *macaddr) +{ +struct i40e_mac_filter *f =NULL ; +int changed =0 ; + +WARN (!spin_is_locked (&vsi->mac_filter_list_lock), +"Missing mac_filter_list_lock\n" ); +list_for_each_entry (f, &vsi->mac_filter_list, list) { +if (ether_addr_equal (macaddr, f->macaddr)) + f->state =I40E_FILTER_REMOVE ; + } +if (changed) { + vsi->flags |=I40E_VSI_FLAG_FILTER_CHANGED ; + vsi->back->flags |=I40E_FLAG_FILTER_SYNC ; +return 0 ; + } +return -ENOENT ; +} + +/** * i40e_set_mac - NDO callback to set mac address * @netdev: network interface device structure * @p: pointer to an address structure
Signature · 1 line
2.4.11
PATCH 4/15 i40e: fix i40e_put_mac_in_vlan to return actual filter added
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
Rather than returning an arbitrary first filter in the list, which will thus return non-null as long as there is even one filter in the list unless an add fails, we should return an actual filter we added. This way, if there is no matching vlan we error out correctly.
--- drivers/net/ethernet/intel/i40e/i40e_main.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_main.c +13 -12
@@ -1312,27 +1312,28 @@ void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)* @vsi: the VSI to be searched * @macaddr: the mac address to be filtered * -* Goes through all the macvlan filters and adds a -* macvlan filter for each unique vlan that already exists +* Goes through all the macvlan filters and adds a macvlan filter for each +* unique vlan that already exists. If a PVID has been assigned, instead only +* add the macaddr to that VLAN. * -* Returns first filter found on success, else NULL +* Returns last filter added on success, else NULL **/ struct i40e_mac_filter *i40e_put_mac_in_vlan (struct i40e_vsi *vsi,const u8 *macaddr) { -struct i40e_mac_filter *f; +struct i40e_mac_filter *f, *add =NULL ; + +if (vsi->info.pvid) +return i40e_add_filter (vsi, macaddr, +le16_to_cpu (vsi->info.pvid));list_for_each_entry (f, &vsi->mac_filter_list, list) { -if (vsi->info.pvid) - f->vlan =le16_to_cpu (vsi->info.pvid); -if (!i40e_find_filter (vsi, macaddr, f->vlan)) { -if (!i40e_add_filter (vsi, macaddr, f->vlan)) -return NULL ; - } + add =i40e_add_filter (vsi, macaddr, f->vlan); +if (!add) +return NULL ; } -return list_first_entry_or_null (&vsi->mac_filter_list, - struct i40e_mac_filter, list); +return add; }/**
Signature · 1 line
2.4.11
PATCH 5/15 i40e: When searching all MAC/VLAN filters, ignore removed filters
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
When adding new MAC address filters, the driver determines if it should behave in VLAN mode (where all MAC addresses get assigned to every existing VLAN) or in non-VLAN mode where MAC addresses get assigned the VLAN_ANY identifier. Under some circumstances it is possible that a VLAN has been marked for removal (such that all filters of that VLAN are set to I40E_FILTER_REMOVE), and a subsequent call to i40e_put_mac_in_vlan may occur prior to the driver subtask that syncs filters to the hardware.
In this case, we may add filters to the new removed VLAN, even though it should have been removed. This is most obvious when first adding a new VLAN. We will delete all filters which are in I40E_VLAN_ANY (-1) and then re-add them as in VLAN 0 (untagged). Then before we sync filters, we will add new MAC address filter, which will be added to every VLAN that exists. Unfortunately, this will include I40E_VLAN_ANY, so we will end up incorrectly adding filters to the -1 VLAN. This can be fixed by simply skipping all filters which are marked for removal.
A similar check is not necessary in i40e_del_mac_all_vlan, since we are deleting, and any filter which we find already marked for removal would simply be deleted again, which doesn't cause any issues.
---
Testing-hints:
1. Load driver and bring link up
modprobe i40e
ip link set enp130s0 up
2. Add a VLAN
ip link add link enp130s0 enp130s0.4000 type vlan id 4000
ip link set enp130s0.4000 up 3. Dump filters:
echo "dump filters" > /sys/kernel/debug/i40e/0000:82:00.0/command dmesg | tail -n40
Note that without this patch you should see some filters repeated with both VLAN 0 and VLAN -1, when we expect only seeing filters on VLAN 0. It may take multiple steps to reproduce as it might be a race condition, though I did not have trouble reproducing the issue.
drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/net/ethernet/intel/i40e/i40e_main.c +6 -0
@@ -1328,6 +1328,8 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi, le16_to_cpu(vsi->info.pvid));list_for_each_entry (f, &vsi->mac_filter_list, list) { +if (f->state ==I40E_FILTER_REMOVE ) +continue ; add =i40e_add_filter (vsi, macaddr, f->vlan);if (!add)return NULL ;
@@ -2264,6 +2266,8 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid) }list_for_each_entry_safe (f, ftmp, &vsi->mac_filter_list, list) { +if (f->state ==I40E_FILTER_REMOVE ) +continue ; add_f =i40e_add_filter (vsi, f->macaddr, vid);if (!add_f) { dev_info(&vsi->back->pdev->dev,
@@ -2298,6 +2302,8 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)/* Do not assume that I40E_VLAN_ANY should be reset to VLAN 0 */ if (vid >0 && !vsi->info.pvid) {list_for_each_entry_safe (f, ftmp, &vsi->mac_filter_list, list) { +if (f->state ==I40E_FILTER_REMOVE ) +continue ;if (!i40e_find_filter (vsi, f->macaddr,I40E_VLAN_ANY ))continue ;i40e_del_filter (vsi, f->macaddr,I40E_VLAN_ANY );
Signature · 1 line
2.4.11
PATCH 6/15 i40e: implement __i40e_del_filter and use where applicable
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
When inside a loop where we call i40e_del_filter we use an O(n^2) pattern where i40e_del_filter calls i40e_find_filter for us. We can avoid this O(n^2) logic by factoring a function, __i40e_del_filter() out from the i40e_del_filter code. This allows us to re-use the delete logic where appropriate without having to search for the filter twice.
This new function benefits several functions including i40e_vsi_add_vlan, i40e_vsi_kill_vlan, i40e_del_mac_vlan_all, and i40e_vsi_release.
--- drivers/net/ethernet/intel/i40e/i40e_main.c | 88 +++++++++++++++++++---------- 1 file changed, 57 insertions(+), 31 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_main.c +57 -31
@@ -1271,10 +1271,13 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, }/** -* i40e_del_filter - Remove a mac/vlan filter from the VSI -* @vsi: the VSI to be searched -* @macaddr: the MAC address -* @vlan: the vlan +* __i40e_del_filter - Remove a specific filter from the VSI +* @vsi: VSI to remove from +* @f: the filter to remove from the list +* +* This function should be called instead of i40e_del_filter only if you know +* the exact filter you will remove already, such as via i40e_find_filter or +* i40e_find_mac. * * NOTE: This function is expected to be called with mac_filter_list_lock * being held.
@@ -1282,14 +1285,8 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,* the "safe" variants of any list iterators, e.g. list_for_each_entry_safe() * instead of list_for_each_entry(). **/ -void i40e_del_filter (struct i40e_vsi *vsi,const u8 *macaddr,s16 vlan) +static void __i40e_del_filter (struct i40e_vsi *vsi,struct i40e_mac_filter *f) { -struct i40e_mac_filter *f; - -if (!vsi || !macaddr) -return ; - - f =i40e_find_filter (vsi, macaddr, vlan);if (!f)return ;
@@ -1308,6 +1305,29 @@ void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan) }/** +* i40e_del_filter - Remove a mac/vlan filter from the VSI +* @vsi: the VSI to be searched +* @macaddr: the MAC address +* @vlan: the vlan +* +* NOTE: This function is expected to be called with mac_filter_list_lock +* being held. +* ANOTHER NOTE: This function MUST be called from within the context of +* the "safe" variants of any list iterators, e.g. list_for_each_entry_safe() +* instead of list_for_each_entry(). +**/ +void i40e_del_filter (struct i40e_vsi *vsi,const u8 *macaddr,s16 vlan) +{ +struct i40e_mac_filter *f; + +if (!vsi || !macaddr) +return ; + + f =i40e_find_filter (vsi, macaddr, vlan); +__i40e_del_filter (vsi, f); +} + +/** * i40e_put_mac_in_vlan - Make macvlan filters from macaddrs and vlans * @vsi: the VSI to be searched * @macaddr: the mac address to be filtered
@@ -1349,21 +1369,22 @@ struct i40e_mac_filter *i40e_put_mac_in_vlan(struct i40e_vsi *vsi,**/ int i40e_del_mac_all_vlan (struct i40e_vsi *vsi,const u8 *macaddr) { -struct i40e_mac_filter *f =NULL ; -int changed =0 ; +struct i40e_mac_filter *f, *ftmp; +bool found = false;WARN (!spin_is_locked (&vsi->mac_filter_list_lock),"Missing mac_filter_list_lock\n" ); -list_for_each_entry (f, &vsi->mac_filter_list, list) { +list_for_each_entry_safe (f, ftmp, &vsi->mac_filter_list, list) {if (ether_addr_equal (macaddr, f->macaddr)) f->state =I40E_FILTER_REMOVE ; +__i40e_del_filter (vsi, f); + found = true; } -if (changed) { - vsi->flags |=I40E_VSI_FLAG_FILTER_CHANGED ; - vsi->back->flags |=I40E_FLAG_FILTER_SYNC ; + +if (found)return 0 ; - } -return -ENOENT ; +else +return -ENOENT ; }/**
@@ -2249,7 +2270,7 @@ static void i40e_vlan_rx_register(struct net_device *netdev, u32 features)**/ int i40e_vsi_add_vlan (struct i40e_vsi *vsi,s16 vid) { -struct i40e_mac_filter *f, *ftmp, *add_f; +struct i40e_mac_filter *f, *ftmp, *add_f, *del_f;/* Locked once because all functions invoked below iterates list*/ spin_lock_bh (&vsi->mac_filter_list_lock);
@@ -2283,11 +2304,11 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)* with 0, so we now accept untagged and specified tagged traffic * (and not all tags along with untagged) */ -if (vid >0 ) { -if (vsi->netdev &&i40e_find_filter (vsi, vsi->netdev->dev_addr, -I40E_VLAN_ANY )) { -i40e_del_filter (vsi, vsi->netdev->dev_addr, -I40E_VLAN_ANY ); +if (vid >0 && vsi->netdev) { + del_f =i40e_find_filter (vsi, vsi->netdev->dev_addr, +I40E_VLAN_ANY ); +if (del_f) { +__i40e_del_filter (vsi, del_f); add_f =i40e_add_filter (vsi, vsi->netdev->dev_addr,0 );if (!add_f) { dev_info(&vsi->back->pdev->dev,
@@ -2304,9 +2325,11 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)list_for_each_entry_safe (f, ftmp, &vsi->mac_filter_list, list) {if (f->state ==I40E_FILTER_REMOVE )continue ; -if (!i40e_find_filter (vsi, f->macaddr,I40E_VLAN_ANY )) + del_f =i40e_find_filter (vsi, f->macaddr, +I40E_VLAN_ANY ); +if (!del_f)continue ; -i40e_del_filter (vsi, f->macaddr,I40E_VLAN_ANY ); +__i40e_del_filter (vsi, del_f); add_f =i40e_add_filter (vsi, f->macaddr,0 );if (!add_f) { dev_info(&vsi->back->pdev->dev,
@@ -2346,8 +2369,10 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)if (vsi->netdev)i40e_del_filter (vsi, netdev->dev_addr, vid); -list_for_each_entry_safe (f, ftmp, &vsi->mac_filter_list, list) -i40e_del_filter (vsi, f->macaddr, vid); +list_for_each_entry_safe (f, ftmp, &vsi->mac_filter_list, list) { +if (f->vlan == vid) +__i40e_del_filter (vsi, f); + }/* go through all the filters for this VSI and if there is only * vid == 0 it means there are no other filters, so vid 0 must
@@ -2379,7 +2404,8 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)if (!filter_count) {list_for_each_entry_safe (f, ftmp, &vsi->mac_filter_list, list) { -i40e_del_filter (vsi, f->macaddr,0 ); +if (!f->vlan) +__i40e_del_filter (vsi, f); add_f =i40e_add_filter (vsi, f->macaddr,I40E_VLAN_ANY );if (!add_f) { dev_info(&vsi->back->pdev->dev,
@@ -9442,7 +9468,7 @@ int i40e_vsi_release(struct i40e_vsi *vsi)/* make sure any remaining filters are marked for deletion */ list_for_each_entry_safe (f, ftmp, &vsi->mac_filter_list, list) -i40e_del_filter (vsi, f->macaddr, f->vlan); +__i40e_del_filter (vsi, f);spin_unlock_bh (&vsi->mac_filter_list_lock);
Signature · 1 line
2.4.11
PATCH 7/15 i40e: store MAC/VLAN filters in a hash with the MAC Address as key
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
Replace the mac_filter_list with a static size hash table of 8bits. The primary advantage of this is a decrease in latency of operations related to searching for specific MAC filters, including .set_rx_mode. Using a linked list resulted in several locations which were O(n^2). Using a hash table should give us latency growth closer to O(n*log(n)).
---
HSD-number: 10020681
drivers/net/ethernet/intel/i40e/i40e.h | 24 ++- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 4 +- drivers/net/ethernet/intel/i40e/i40e_main.c | 198 ++++++++++++--------- drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 38 ++-- 4 files changed, 159 insertions(+), 105 deletions(-)
drivers/net/ethernet/intel/i40e/i40e.h +20 -4
@@ -39,6 +39,7 @@#include <linux/iommu.h> #include <linux/slab.h> #include <linux/list.h> +#include <linux/hashtable.h> #include <linux/string.h> #include <linux/in.h> #include <linux/ip.h>
@@ -445,6 +446,20 @@ struct i40e_pf {u16 phy_led_val; }; +/** +* i40e_mac_to_hkey - Convert a 6-byte MAC Address to a u64 hash key +* @macaddr: the MAC Address as the base key +* +* Simply copies the address and returns it as a u64 for hashing +**/ +static inline u64 i40e_addr_to_hkey (const u8 *macaddr) +{ +u64 key =0 ; + +ether_addr_copy ((u8 *)&key, macaddr); +return key; +} +enum i40e_filter_state {I40E_FILTER_INVALID =0 ,/* Invalid state */ I40E_FILTER_NEW ,/* New, not sent to FW yet */
@@ -454,7 +469,7 @@ enum i40e_filter_state {/* There is no 'removed' state; the filter struct is freed */ };struct i40e_mac_filter { -struct list_head list; +struct hlist_node hlist;u8 macaddr[ETH_ALEN ];#define I40E_VLAN_ANY -1s16 vlan;
@@ -498,9 +513,10 @@ struct i40e_vsi {#define I40E_VSI_FLAG_VEB_OWNER BIT(1)unsigned long flags; -/* Per VSI lock to protect elements/list (MAC filter) */ -spinlock_t mac_filter_list_lock; -struct list_head mac_filter_list; +/* Per VSI lock to protect elements/hash (MAC filter) */ +spinlock_t mac_filter_hash_lock; +/* Fixed size hash table with 2^8 buckets for MAC filters */ +DECLARE_HASHTABLE (mac_filter_hash,8 );/* VSI stats */ struct rtnl_link_stats64 net_stats;
drivers/net/ethernet/intel/i40e/i40e_debugfs.c +2 -2
@@ -134,7 +134,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)struct rtnl_link_stats64 *nstat;struct i40e_mac_filter *f;struct i40e_vsi *vsi; -int i; +int i, bkt; vsi =i40e_dbg_find_vsi (pf, seid);if (!vsi) {
@@ -166,7 +166,7 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid) pf->hw.mac.addr, pf->hw.mac.san_addr, pf->hw.mac.port_addr); -list_for_each_entry (f, &vsi->mac_filter_list, list) { +hash_for_each (vsi->mac_filter_hash, bkt, f, hlist) { dev_info(&pf->pdev->dev, " mac_filter_hash: %pM vid=%d, state %s\n", f->macaddr, f->vlan,
drivers/net/ethernet/intel/i40e/i40e_main.c +117 -81
567 lines not on this page · raw message
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +20 -18
@@ -686,7 +686,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)if (vf->port_vlan_id)i40e_vsi_add_pvid (vsi, vf->port_vlan_id); -spin_lock_bh (&vsi->mac_filter_list_lock); +spin_lock_bh (&vsi->mac_filter_hash_lock);if (is_valid_ether_addr (vf->default_lan_addr.addr)) { f = i40e_add_filter(vsi, vf->default_lan_addr.addr, vf->port_vlan_id ?
@@ -696,7 +696,7 @@ static int i40e_alloc_vsi_res(struct i40e_vf *vf, enum i40e_vsi_type type)"Could not add MAC filter %pM for VF %d\n" , vf->default_lan_addr.addr, vf->vf_id); } -spin_unlock_bh (&vsi->mac_filter_list_lock); +spin_unlock_bh (&vsi->mac_filter_hash_lock);i40e_write_rx_ctl (&pf->hw,I40E_VFQF_HENA1 (0 , vf->vf_id), (u32 )hena); i40e_write_rx_ctl(&pf->hw, I40E_VFQF_HENA1(1, vf->vf_id),
@@ -1449,9 +1449,9 @@ static void i40e_vc_reset_vf_msg(struct i40e_vf *vf)static inline int i40e_getnum_vf_vsi_vlan_filters (struct i40e_vsi *vsi) {struct i40e_mac_filter *f; -int num_vlans =0 ; +int num_vlans =0 , bkt; -list_for_each_entry (f, &vsi->mac_filter_list, list) { +hash_for_each (vsi->mac_filter_hash, bkt, f, hlist) {if (f->vlan >=0 && f->vlan <=I40E_MAX_VLANID ) num_vlans++; }
@@ -1481,6 +1481,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf,struct i40e_vsi *vsi;bool alluni = false;int aq_err =0 ; +int bkt; vsi =i40e_find_vsi_from_id (pf, info->vsi_id); if (!test_bit(I40E_VF_STAT_ACTIVE, &vf->vf_states) ||
@@ -1507,7 +1508,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, vf->port_vlan_id, NULL); }else if (i40e_getnum_vf_vsi_vlan_filters (vsi)) { -list_for_each_entry (f, &vsi->mac_filter_list, list) { +hash_for_each (vsi->mac_filter_hash, bkt, f, hlist) {if (f->vlan <0 || f->vlan >I40E_MAX_VLANID )continue ; aq_ret = i40e_aq_set_vsi_mc_promisc_on_vlan(hw,
@@ -1557,7 +1558,7 @@ static int i40e_vc_config_promiscuous_mode_msg(struct i40e_vf *vf, vf->port_vlan_id, NULL); }else if (i40e_getnum_vf_vsi_vlan_filters (vsi)) { -list_for_each_entry (f, &vsi->mac_filter_list, list) { +hash_for_each (vsi->mac_filter_hash, bkt, f, hlist) { aq_ret =0 ;if (f->vlan >=0 && f->vlan <=I40E_MAX_VLANID ) { aq_ret =
@@ -1927,7 +1928,7 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)/* Lock once, because all function inside for loop accesses VSI's * MAC filter list which needs to be protected using same lock. */ -spin_lock_bh (&vsi->mac_filter_list_lock); +spin_lock_bh (&vsi->mac_filter_hash_lock);/* add new addresses to the list */ for (i =0 ; i < al->num_elements; i++) {
@@ -1946,13 +1947,13 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)"Unable to add MAC filter %pM for VF %d\n" , al->list[i].addr, vf->vf_id); ret =I40E_ERR_PARAM ; -spin_unlock_bh (&vsi->mac_filter_list_lock); +spin_unlock_bh (&vsi->mac_filter_hash_lock); goto error_param; }else { vf->num_mac++; } } -spin_unlock_bh (&vsi->mac_filter_list_lock); +spin_unlock_bh (&vsi->mac_filter_hash_lock);/* program the updated filter list */ ret =i40e_sync_vsi_filters (vsi);
@@ -2001,18 +2002,18 @@ static int i40e_vc_del_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen) } vsi = pf->vsi[vf->lan_vsi_idx]; -spin_lock_bh (&vsi->mac_filter_list_lock); +spin_lock_bh (&vsi->mac_filter_hash_lock);/* delete addresses from the list */ for (i =0 ; i < al->num_elements; i++)if (i40e_del_mac_all_vlan (vsi, al->list[i].addr)) { ret =I40E_ERR_INVALID_MAC_ADDR ; -spin_unlock_bh (&vsi->mac_filter_list_lock); +spin_unlock_bh (&vsi->mac_filter_hash_lock); goto error_param; }else { vf->num_mac--; } -spin_unlock_bh (&vsi->mac_filter_list_lock); +spin_unlock_bh (&vsi->mac_filter_hash_lock);/* program the updated filter list */ ret =i40e_sync_vsi_filters (vsi);
@@ -2687,6 +2688,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)struct i40e_mac_filter *f;struct i40e_vf *vf;int ret =0 ; +int bkt;/* validate the request */ if (vf_id >= pf->num_alloc_vfs) {
@@ -2713,9 +2715,9 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac) }/* Lock once because below invoked function add/del_filter requires -* mac_filter_list_lock to be held +* mac_filter_hash_lock to be held */ -spin_lock_bh (&vsi->mac_filter_list_lock); +spin_lock_bh (&vsi->mac_filter_hash_lock);/* delete the temporary mac address */ if (!is_zero_ether_addr (vf->default_lan_addr.addr))
@@ -2725,10 +2727,10 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)/* Delete all the filters for this VSI - we're going to kill it * anyway. */ -list_for_each_entry (f, &vsi->mac_filter_list, list) +hash_for_each (vsi->mac_filter_hash, bkt, f, hlist)i40e_del_filter (vsi, f->macaddr, f->vlan); -spin_unlock_bh (&vsi->mac_filter_list_lock); +spin_unlock_bh (&vsi->mac_filter_hash_lock);dev_info (&pf->pdev->dev,"Setting MAC %pM on VF %d\n" , mac, vf_id);/* program mac filter */
@@ -2800,9 +2802,9 @@ int i40e_ndo_set_vf_port_vlan(struct net_device *netdev, int vf_id,/* duplicate request, so just return success */ goto error_pvid; -spin_lock_bh (&vsi->mac_filter_list_lock); +spin_lock_bh (&vsi->mac_filter_hash_lock); is_vsi_in_vlan =i40e_is_vsi_in_vlan (vsi); -spin_unlock_bh (&vsi->mac_filter_list_lock); +spin_unlock_bh (&vsi->mac_filter_hash_lock);if (le16_to_cpu (vsi->info.pvid) ==0 && is_vsi_in_vlan) { dev_err(&pf->pdev->dev,
Signature · 1 line
2.4.11
PATCH 8/15 i40e: properly cleanup on allocation failure in i40e_sync_vsi_filters
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
Currently, we fail to correctly restore filters on the temporary add list when we fail to allocate memory either for deletion or addition. Replace calls to "goto out;" with calls to a new location that correctly handles memory allocation failures.
Note that it is safe for us to call i40e_undo_filter_entries on the tmp_del_list even after we've deleted filters because at this point it will be empty, so we don't need to separate the logic for add and delete failure.
---
Testing-hints:
As this is a cleanup flow for handling memory allocation I am not really sure how best to test this case...
drivers/net/ethernet/intel/i40e/i40e_main.c | 39 ++++++++++++++++------------- 1 file changed, 22 insertions(+), 17 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_main.c +22 -17
@@ -1683,15 +1683,16 @@ static void i40e_set_rx_mode(struct net_device *netdev) }/** -* i40e_undo_del_filter_entries - Undo the changes made to MAC filter entries -* @vsi: pointer to vsi struct +* i40e_undo_filter_entries - Undo the changes made to MAC filter entries +* @vsi: Pointer to vsi struct * @from: Pointer to list which contains MAC filter entries - changes to * those entries needs to be undone. * -* MAC filter entries from list were slated to be removed from device. +* MAC filter entries from list were slated to be sent to firmware, either for +* addition or deletion. **/ -static void i40e_undo_del_filter_entries (struct i40e_vsi *vsi, -struct hlist_head *from) +static void i40e_undo_filter_entries (struct i40e_vsi *vsi, +struct hlist_head *from) {struct i40e_mac_filter *f;struct hlist_node *h;
@@ -1840,14 +1841,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) list_size = filter_list_len *sizeof (struct i40e_aqc_remove_macvlan_element_data ); del_list =kzalloc (list_size,GFP_ATOMIC ); -if (!del_list) { -/* Undo VSI's MAC filter entry element updates */ -spin_lock_bh (&vsi->mac_filter_hash_lock); -i40e_undo_del_filter_entries (vsi, &tmp_del_list); -spin_unlock_bh (&vsi->mac_filter_hash_lock); - retval = -ENOMEM ; - goto out; - } +if (!del_list) + goto err_no_memory;hlist_for_each_entry_safe (f, h, &tmp_del_list, hlist) { cmd_flags =0 ;
@@ -1924,10 +1919,9 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) list_size = filter_list_len *sizeof (struct i40e_aqc_add_macvlan_element_data ); add_list =kzalloc (list_size,GFP_ATOMIC ); -if (!add_list) { - retval = -ENOMEM ; - goto out; - } +if (!add_list) + goto err_no_memory; + num_add =0 ;hlist_for_each_entry (f, &tmp_add_list, hlist) { if (test_bit(__I40E_FILTER_OVERFLOW_PROMISC,
@@ -2140,6 +2134,17 @@ out:clear_bit (__I40E_CONFIG_BUSY, &vsi->state);return retval; + +err_no_memory: +/* Restore elements on the temporary add and delete lists */ +spin_lock_bh (&vsi->mac_filter_hash_lock); +i40e_undo_filter_entries (vsi, &tmp_del_list); +i40e_undo_filter_entries (vsi, &tmp_add_list); +spin_unlock_bh (&vsi->mac_filter_hash_lock); + + vsi->flags |=I40E_VSI_FLAG_FILTER_CHANGED ; +clear_bit (__I40E_CONFIG_BUSY, &vsi->state); +return -ENOMEM ; }/**
Signature · 1 line
2.4.11
PATCH 9/15 i40e: fix mac filters when removing vlans
In reply to Bimmy PujariFrom: "Brady, Alan" <[email protected]>
Currently there exists a bug where adding at least one VLAN and then removing all VLANs leaves the mac filters for the VSI with an incorrect value for 'vid' which indicates the mac filter's vlan status.
The current implementation for handling the removal of VLANs is wrong for a couple reasons. The first is that when i40e_vsi_kill_vlan iterates through the mac filters, it fails to account for the mac filter status; i.e. it's not accomdating for filters that are about to be deleted. The second problem is that mac filters can be deleted in other places (specifically i40e_set_rx_mode). Thus if it occurs that all the vlan mac filters get deleted we need to switch out of vlan mode, but the code path through i40e_vsi_kill_vlan has already been executed and we're now stuck in vlan mode.
This patch fixes the issue by removing the check from i40e_vsi_kill_vlan and puts the check instead in i40e_sync_vsi_filters where we're guaranteed to see all filter deletions and can properly detect when we need to switch out of vlan mode.
---
HSD-number: 10020696
drivers/net/ethernet/intel/i40e/i40e_main.c | 120 +++++++++++++++++----------- 1 file changed, 72 insertions(+), 48 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_main.c +72 -48
@@ -1774,19 +1774,22 @@ i40e_update_filter_state(int count,**/ int i40e_sync_vsi_filters (struct i40e_vsi *vsi) { -struct i40e_mac_filter *f, *add_head =NULL ;struct hlist_head tmp_add_list, tmp_del_list; +struct i40e_mac_filter *f, *add_head =NULL ;struct i40e_hw *hw = &vsi->back->hw; +unsigned int vlan_any_filters =0 ; +unsigned int non_vlan_filters =0 ; +unsigned int vlan_filters =0 ;bool promisc_changed = false;char vsi_name[16 ] ="PF" ;int filter_list_len =0 ; -u32 changed_flags =0 ;i40e_status aq_ret =0 ; +u32 changed_flags =0 ;struct hlist_node *h; -int retval =0 ;struct i40e_pf *pf;int num_add =0 ;int num_del =0 ; +int retval =0 ;int aq_err =0 ;u16 cmd_flags;int list_size;
@@ -1825,11 +1828,75 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)hash_del (&f->hlist);hlist_add_head (&f->hlist, &tmp_del_list); vsi->active_filters--; + +/* Avoid counting removed filters */ +continue ; }if (f->state ==I40E_FILTER_NEW ) {hash_del (&f->hlist);hlist_add_head (&f->hlist, &tmp_add_list); } + +/* Count the number of each type of filter we have +* remaining, ignoring any filters we're about to +* delete. +*/ +if (f->vlan >0 ) + vlan_filters++; +else if (!f->vlan) + non_vlan_filters++; +else + vlan_any_filters++; + } + +/* We should never have VLAN=-1 filters at the same time as we +* have either VLAN=0 or VLAN>0 filters, so warn about this +* case here to help catch any issues. +*/ +WARN_ON (vlan_any_filters && (vlan_filters + non_vlan_filters)); + +/* If we only have VLAN=0 filters remaining, and don't have +* any other VLAN filters, we need to convert these VLAN=0 +* filters into VLAN=-1 (I40E_VLAN_ANY) so that we operate +* correctly in non-VLAN mode and receive all traffic tagged +* or untagged. +*/ +if (non_vlan_filters && !vlan_filters) { +hash_for_each_safe (vsi->mac_filter_hash, bkt, h, f, + hlist) { +/* Only replace VLAN=0 filters */ +if (f->vlan) +continue ; + +/* Allocate a replacement element */ + add_head =kzalloc (sizeof (*add_head), +GFP_KERNEL ); +if (!add_head) + goto err_no_memory_locked; + +/* Copy the filter, with new state and VLAN */ + *add_head = *f; + add_head->state =I40E_FILTER_NEW ; + add_head->vlan =I40E_VLAN_ANY ; + +/* Move the replacement to the add list */ +INIT_HLIST_NODE (&add_head->hlist); +hlist_add_head (&add_head->hlist, + &tmp_add_list); + +/* Move the original to the delete list */ + f->state =I40E_FILTER_REMOVE ; +hash_del (&f->hlist); +hlist_add_head (&f->hlist, &tmp_del_list); + vsi->active_filters--; + } + +/* Also update any filters on the tmp_add list */ +hlist_for_each_entry (f, &tmp_add_list, hlist) { +if (!f->vlan) + f->vlan =I40E_VLAN_ANY ; + } + add_head =NULL ; }spin_unlock_bh (&vsi->mac_filter_hash_lock); }
@@ -2138,6 +2205,7 @@ out: err_no_memory:/* Restore elements on the temporary add and delete lists */ spin_lock_bh (&vsi->mac_filter_hash_lock); +err_no_memory_locked:i40e_undo_filter_entries (vsi, &tmp_del_list);i40e_undo_filter_entries (vsi, &tmp_add_list);spin_unlock_bh (&vsi->mac_filter_hash_lock);
@@ -2396,9 +2464,8 @@ int i40e_vsi_add_vlan(struct i40e_vsi *vsi, s16 vid)int i40e_vsi_kill_vlan (struct i40e_vsi *vsi,s16 vid) {struct net_device *netdev = vsi->netdev; -struct i40e_mac_filter *f, *add_f; +struct i40e_mac_filter *f;struct hlist_node *h; -int filter_count =0 ;int bkt;/* Locked once because all functions invoked below iterates list */
@@ -2412,49 +2479,6 @@ int i40e_vsi_kill_vlan(struct i40e_vsi *vsi, s16 vid)__i40e_del_filter (vsi, f); } -/* go through all the filters for this VSI and if there is only -* vid == 0 it means there are no other filters, so vid 0 must -* be replaced with -1. This signifies that we should from now -* on accept any traffic (with any tag present, or untagged) -*/ -hash_for_each (vsi->mac_filter_hash, bkt, f, hlist) { -if (vsi->netdev) { -if (f->vlan && -ether_addr_equal (netdev->dev_addr, f->macaddr)) - filter_count++; - } - -if (f->vlan) - filter_count++; - } - -if (!filter_count && vsi->netdev) { -i40e_del_filter (vsi, netdev->dev_addr,0 ); - f =i40e_add_filter (vsi, netdev->dev_addr,I40E_VLAN_ANY ); -if (!f) { -dev_info (&vsi->back->pdev->dev, -"Could not add filter %d for %pM\n" , -I40E_VLAN_ANY , netdev->dev_addr); -spin_unlock_bh (&vsi->mac_filter_hash_lock); -return -ENOMEM ; - } - } - -if (!filter_count) { -hash_for_each_safe (vsi->mac_filter_hash, bkt, h, f, hlist) { -if (!f->vlan) -__i40e_del_filter (vsi, f); - add_f =i40e_add_filter (vsi, f->macaddr,I40E_VLAN_ANY ); -if (!add_f) { -dev_info (&vsi->back->pdev->dev, -"Could not add filter %d for %pM\n" , -I40E_VLAN_ANY , f->macaddr); -spin_unlock_bh (&vsi->mac_filter_hash_lock); -return -ENOMEM ; - } - } - } -spin_unlock_bh (&vsi->mac_filter_hash_lock);/* schedule our worker thread which will take care of
Signature · 1 line
2.4.11
PATCH 10/15 i40e: avoid looping to check whether we're in vlan mode
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
We determine that a vsi is in vlan_mode whenever it has any filters with a vlan other than -1 (I40E_VLAN_ALL). The previous method of doing so was to perform a loop whenever we needed the check. However, we can notice that only place where filters are added (i40e_add_filter) can change the condition from false to true, and the only place we can return to false is in i40e_vsi_sync_filters_subtask. Thus, we can remove the loop and use a boolean directly.
Doing this avoids looping over filters repeatedly especially while we're already inside a loop over all the filters. This should reduce the latency of filter operations throughout the driver.
--- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_main.c | 48 ++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 11 deletions(-)
drivers/net/ethernet/intel/i40e/i40e.h +1 -0
@@ -517,6 +517,7 @@ struct i40e_vsi {spinlock_t mac_filter_hash_lock;/* Fixed size hash table with 2^8 buckets for MAC filters */ DECLARE_HASHTABLE (mac_filter_hash,8 ); +bool has_vlan_filter;/* VSI stats */ struct rtnl_link_stats64 net_stats;
drivers/net/ethernet/intel/i40e/i40e_main.c +37 -11
68 lines not on this page · raw message
Signature · 1 line
2.4.11
PATCH 11/15 i40e: remove duplicate add/delete adminq command code for filters
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
We duplicate some code around adding and deleting filters using the adminq interface. This is prone to errors in case there are bugs. Use functions which extract the logic to their own portion so that we don't duplicate it twice in code.
--- drivers/net/ethernet/intel/i40e/i40e_main.c | 156 +++++++++++++++------------- 1 file changed, 84 insertions(+), 72 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_main.c +84 -72
@@ -1783,6 +1783,80 @@ i40e_update_filter_state(int count, }/** +* i40e_aqc_del_filters - Request firmware to delete a set of filters +* @vsi: ptr to the VSI +* @vsi_name: name to display in messages +* @list: the list of filters to send to firmware +* @num_del: the number of filters to delete +* @retval: Set to -EIO on failure to delete +* +* Send a request to firmware via AdminQ to delete a set of filters. Uses +* *retval instead of a return value so that success does not force ret_val to +* be set to 0. This ensures that a sequence of calls to this function +* preserve the previous value of *retval on successful delete. +*/ +static +void i40e_aqc_del_filters (struct i40e_vsi *vsi,const char *vsi_name, +struct i40e_aqc_remove_macvlan_element_data *list, +int num_del,int *retval) +{ +struct i40e_hw *hw = &vsi->back->hw; +i40e_status aq_ret; +int aq_err; + + aq_ret =i40e_aq_remove_macvlan (hw, vsi->seid, list, num_del,NULL ); + aq_err = hw->aq.asq_last_status; + +/* Explicitly ignore and do not report when firmware returns ENOENT */ +if (aq_ret && !(aq_err ==I40E_AQ_RC_ENOENT )) { + *retval = -EIO ; +dev_info (&vsi->back->pdev->dev, +"ignoring delete macvlan error on %s, err %s, aq_err %s\n" , + vsi_name,i40e_stat_str (hw, aq_ret), +i40e_aq_str (hw, aq_err)); + } +} + +/** +* i40e_aqc_add_filters - Request firmware to add a set of filters +* @vsi: ptr to the VSI +* @vsi_name: name to display in messages +* @list: the list of filters to send to firmware +* @add_head: Position in the add hlist +* @num_add: the number of filters to add +* @promisc_change: set to true on exit if promiscuous mode was forced on +* +* Send a request to firmware via AdminQ to add a chunk of filters. Will set +* promisc_changed to true if the firmware has run out of space for more +* filters. +*/ +static +void i40e_aqc_add_filters (struct i40e_vsi *vsi,const char *vsi_name, +struct i40e_aqc_add_macvlan_element_data *list, +struct i40e_mac_filter *add_head, +int num_add,bool *promisc_changed) +{ +struct i40e_hw *hw = &vsi->back->hw; +i40e_status aq_ret; +int aq_err, fcnt; + + aq_ret =i40e_aq_add_macvlan (hw, vsi->seid, list, num_add,NULL ); + aq_err = hw->aq.asq_last_status; + fcnt =i40e_update_filter_state (num_add, list, add_head, aq_ret); + vsi->active_filters += fcnt; + +if (fcnt != num_add) { + *promisc_changed = true; +set_bit (__I40E_FILTER_OVERFLOW_PROMISC, &vsi->state); + vsi->promisc_threshold = (vsi->active_filters *3 ) /4 ; +dev_warn (&vsi->back->pdev->dev, +"Error %s adding RX filters on %s, promiscuous mode forced on\n" , +i40e_aq_str (hw, aq_err), + vsi_name); + } +} + +/** * i40e_sync_vsi_filters - Update the VSI filter list to the HW * @vsi: ptr to the VSI *
@@ -1808,10 +1882,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)int num_add =0 ;int num_del =0 ;int retval =0 ; -int aq_err =0 ;u16 cmd_flags;int list_size; -int fcnt;int bkt;/* empty array typed pointers, kcalloc later */
@@ -1948,24 +2020,10 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)/* flush a full buffer */ if (num_del == filter_list_len) { - aq_ret =i40e_aq_remove_macvlan (hw, vsi->seid, - del_list, - num_del,NULL ); - aq_err = hw->aq.asq_last_status; - num_del =0 ; +i40e_aqc_del_filters (vsi, vsi_name, del_list, + num_del, &retval);memset (del_list,0 , list_size); - -/* Explicitly ignore and do not report when -* firmware returns ENOENT. -*/ -if (aq_ret && !(aq_err ==I40E_AQ_RC_ENOENT )) { - retval = -EIO ; -dev_info (&pf->pdev->dev, -"ignoring delete macvlan error on %s, err %s, aq_err %s\n" , - vsi_name, -i40e_stat_str (hw, aq_ret), -i40e_aq_str (hw, aq_err)); - } + num_del =0 ; }/* Release memory for MAC filter entries which were * synced up with HW.
@@ -1975,22 +2033,8 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) }if (num_del) { - aq_ret =i40e_aq_remove_macvlan (hw, vsi->seid, del_list, - num_del,NULL ); - aq_err = hw->aq.asq_last_status; - num_del =0 ; - -/* Explicitly ignore and do not report when firmware -* returns ENOENT. -*/ -if (aq_ret && !(aq_err ==I40E_AQ_RC_ENOENT )) { - retval = -EIO ; -dev_info (&pf->pdev->dev, -"ignoring delete macvlan error on %s, err %s aq_err %s\n" , - vsi_name, -i40e_stat_str (hw, aq_ret), -i40e_aq_str (hw, aq_err)); - } +i40e_aqc_del_filters (vsi, vsi_name, del_list, + num_del, &retval); }kfree (del_list);
@@ -2041,48 +2085,16 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi)/* flush a full buffer */ if (num_add == filter_list_len) { - aq_ret =i40e_aq_add_macvlan (hw, vsi->seid, - add_list, num_add, -NULL ); - aq_err = hw->aq.asq_last_status; - fcnt =i40e_update_filter_state (num_add, - add_list, - add_head, - aq_ret); - vsi->active_filters += fcnt; - -if (fcnt != num_add) { - promisc_changed = true; -set_bit (__I40E_FILTER_OVERFLOW_PROMISC, - &vsi->state); - vsi->promisc_threshold = - (vsi->active_filters *3 ) /4 ; -dev_warn (&pf->pdev->dev, -"Error %s adding RX filters on %s, promiscuous mode forced on\n" , -i40e_aq_str (hw, aq_err), - vsi_name); - } +i40e_aqc_add_filters (vsi, vsi_name, add_list, + add_head, num_add, + &promisc_changed);memset (add_list,0 , list_size); num_add =0 ; } }if (num_add) { - aq_ret =i40e_aq_add_macvlan (hw, vsi->seid, - add_list, num_add,NULL ); - aq_err = hw->aq.asq_last_status; - fcnt =i40e_update_filter_state (num_add, add_list, - add_head, aq_ret); - vsi->active_filters += fcnt; -if (fcnt != num_add) { - promisc_changed = true; -set_bit (__I40E_FILTER_OVERFLOW_PROMISC, - &vsi->state); - vsi->promisc_threshold = - (vsi->active_filters *3 ) /4 ; -dev_warn (&pf->pdev->dev, -"Error %s adding RX filters on %s, promiscuous mode forced on\n" , -i40e_aq_str (hw, aq_err), vsi_name); - } +i40e_aqc_add_filters (vsi, vsi_name, add_list, add_head, + num_add, &promisc_changed); }/* Now move all of the filters from the temp add list back to * the VSI's list.
Signature · 1 line
2.4.11
PATCH 12/15 i40e: correct check for reading TSYNINDX from the receive descriptor
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
When hardware has taken a timestamp for a received packet, it indicates which RXTIME register the timestamp was placed in by some bits in the receive descriptor. It uses 3 bits, one to indicate if the descriptor index is valid (ie: there was a timestamp) and 2 bits to indicate which of the 4 registers to read. However, the driver currently does not check the TSYNVALID bit and only checks the index. It assumes a zero index means no timestamp, and a non zero index means a timestamp occurred. While this appears to be true, it prevents ever reading a timestamp in RXTIME[0], and causes the first timestamp the device captures to be ignored.
Fix this by using the TSYNVALID bit correctly as the true indicator of whether the packet has an associated timestamp.
Also rename the variable rsyn to tsyn as this is more descriptive and matches the register names.
---
Testing-hints:
This is difficult to notice because the hardware has 4 timestamp registers, and we rarely need more than 1 or 2 at a time. I discovered it with a modified driver using trace_printk on the PRTTSYN_STAT_1 register.
drivers/net/ethernet/intel/i40e/i40e_txrx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/ethernet/intel/i40e/i40e_txrx.c +4 -3
@@ -1407,11 +1407,12 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,u64 qword =le64_to_cpu (rx_desc->wb.qword1.status_error_len);u32 rx_status = (qword &I40E_RXD_QW1_STATUS_MASK ) >>I40E_RXD_QW1_STATUS_SHIFT ; -u32 rsyn = (rx_status &I40E_RXD_QW1_STATUS_TSYNINDX_MASK ) >> +u32 tsynvalid = rx_status &I40E_RXD_QW1_STATUS_TSYNVALID_MASK ; +u32 tsyn = (rx_status &I40E_RXD_QW1_STATUS_TSYNINDX_MASK ) >>I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT ; -if (unlikely (rsyn)) { -i40e_ptp_rx_hwtstamp (rx_ring->vsi->back, skb, rsyn); +if (unlikely (tsynvalid)) { +i40e_ptp_rx_hwtstamp (rx_ring->vsi->back, skb, tsyn); rx_ring->last_rx_timestamp = jiffies; }
Signature · 1 line
2.4.11
PATCH 13/15 i40e: use a mutex instead of spinlock in PTP user entry points
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
We need a locking mechanism to protect the hardware SYSTIME register which is split over 2 values, and has internal hardware latching. We can't allow multiple accesses at the same time. However....
The spinlock_t is overkill here, especially use of spin_lock_irqsave, since every PTP access will halt hardirqs. Notice that the only places which need the SYSTIME value are user context and are capable of sleeping. Thus, it is safe to use a mutex here instead of the spinlock.
---
Testing-hints:
Suggested by Alex after seeing that the code flows don't take the lock in irq context. Not sure how to test this directly, but should ensure that PTP functionality remains unchanged, and that driver functionality remains consistent especially when using PTP software.
drivers/net/ethernet/intel/i40e/i40e.h | 2 +- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 20 +++++++------------- 2 files changed, 8 insertions(+), 14 deletions(-)
drivers/net/ethernet/intel/i40e/i40e.h +1 -1
@@ -430,7 +430,7 @@ struct i40e_pf {struct sk_buff *ptp_tx_skb;struct hwtstamp_config tstamp_config;unsigned long last_rx_ptp_check; -spinlock_t tmreg_lock;/* Used to protect the device time registers. */ +struct mutex tmreg_lock;/* Used to protect the SYSTIME registers. */ u64 ptp_base_adj;u32 tx_hwtstamp_timeouts;u32 rx_hwtstamp_cleared;
drivers/net/ethernet/intel/i40e/i40e_ptp.c +7 -13
@@ -159,16 +159,15 @@ static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) { struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps);struct timespec64 now, then; -unsigned long flags; then =ns_to_timespec64 (delta); -spin_lock_irqsave (&pf->tmreg_lock, flags); +mutex_lock (&pf->tmreg_lock);i40e_ptp_read (pf, &now); now =timespec64_add (now, then);i40e_ptp_write (pf, (const struct timespec64 *)&now); -spin_unlock_irqrestore (&pf->tmreg_lock, flags); +mutex_unlock (&pf->tmreg_lock);return 0 ; }
@@ -184,11 +183,10 @@ static int i40e_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)static int i40e_ptp_gettime (struct ptp_clock_info *ptp,struct timespec64 *ts) { struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps); -unsigned long flags; -spin_lock_irqsave (&pf->tmreg_lock, flags); +mutex_lock (&pf->tmreg_lock);i40e_ptp_read (pf, ts); -spin_unlock_irqrestore (&pf->tmreg_lock, flags); +mutex_unlock (&pf->tmreg_lock);return 0 ; }
@@ -205,11 +203,10 @@ static int i40e_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) { struct i40e_pf *pf = container_of(ptp, struct i40e_pf, ptp_caps); -unsigned long flags; -spin_lock_irqsave (&pf->tmreg_lock, flags); +mutex_lock (&pf->tmreg_lock);i40e_ptp_write (pf, ts); -spin_unlock_irqrestore (&pf->tmreg_lock, flags); +mutex_unlock (&pf->tmreg_lock);return 0 ; }
@@ -658,10 +655,7 @@ void i40e_ptp_init(struct i40e_pf *pf)return ; } -/* we have to initialize the lock first, since we can't control -* when the user will enter the PHC device entry points -*/ -spin_lock_init (&pf->tmreg_lock); +mutex_init (&pf->tmreg_lock);/* ensure we have a clock device */ err =i40e_ptp_create_clock (pf);
Signature · 1 line
2.4.11
PATCH 14/15 i40e: replace PTP Rx timestamp hang logic
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
The current Rx timestamp hang logic is not very robust because it does not notice a register is hung until all four timestamps have been latched and we wait a full 5 seconds. Replace this logic with a newer Rx hang detection based on storing the jiffies when we first notice a receive timestamp event. We store each register's time separately, along with a flag indicating if it is currently latched. Upon first transitioning to latch, we will update the latch_events[i] jiffies value. This indicates the time we first noticed this event. The watchdog routine will simply check that the either the flag has been cleared, or we have passed at least one second. In this case, it is able to clear the Rx timestamp register under the assumption that it was for a dropped frame. The benefit if this strategy is that we should be able to detect and clear out stalled RXTIME_H registers before we exhaust the supply of 4, and avoid complete stall of Rx timestamp events.
--- drivers/net/ethernet/intel/i40e/i40e.h | 4 +- drivers/net/ethernet/intel/i40e/i40e_ptp.c | 117 +++++++++++++++++++--------- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 4 +- drivers/net/ethernet/intel/i40e/i40e_txrx.h | 2 - 4 files changed, 83 insertions(+), 44 deletions(-)
drivers/net/ethernet/intel/i40e/i40e.h +3 -1
@@ -429,11 +429,13 @@ struct i40e_pf {struct ptp_clock_info ptp_caps;struct sk_buff *ptp_tx_skb;struct hwtstamp_config tstamp_config; -unsigned long last_rx_ptp_check;struct mutex tmreg_lock;/* Used to protect the SYSTIME registers. */ u64 ptp_base_adj;u32 tx_hwtstamp_timeouts;u32 rx_hwtstamp_cleared; +u32 latch_event_flags; +spinlock_t ptp_rx_lock;/* Used to protect Rx timestamp registers. */ +unsigned long latch_events[4 ];bool ptp_tx;bool ptp_rx;u16 rss_table_size;/* HW RSS table size */
drivers/net/ethernet/intel/i40e/i40e_ptp.c +79 -38
169 lines not on this page · raw message
drivers/net/ethernet/intel/i40e/i40e_txrx.c +1 -3
@@ -1411,10 +1411,8 @@ void i40e_process_skb_fields(struct i40e_ring *rx_ring,u32 tsyn = (rx_status &I40E_RXD_QW1_STATUS_TSYNINDX_MASK ) >>I40E_RXD_QW1_STATUS_TSYNINDX_SHIFT ; -if (unlikely (tsynvalid)) { +if (unlikely (tsynvalid))i40e_ptp_rx_hwtstamp (rx_ring->vsi->back, skb, tsyn); - rx_ring->last_rx_timestamp = jiffies; - }i40e_rx_hash (rx_ring, rx_desc, skb, rx_ptype);
drivers/net/ethernet/intel/i40e/i40e_txrx.h +0 -2
@@ -307,8 +307,6 @@ struct i40e_ring {u8 atr_sample_rate;u8 atr_count; -unsigned long last_rx_timestamp; -bool ring_active;/* is ring online or not */ bool arm_wb;/* do something to arm write back */ u8 packet_stride;
Signature · 1 line
2.4.11
PATCH 15/15 i40evf: avoid an extra msleep while waiting for reset
In reply to Bimmy PujariFrom: Jacob Keller <[email protected]>
Remove the second call to msleep outside the loop, and move the msleep within the loop as the first step. This guarantees that a single loop will wait the minimum time first, and then after the reset finishes we no longer need an extra msleep.
---
HSD-number: 10020117
drivers/net/ethernet/intel/i40evf/i40evf_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/ethernet/intel/i40evf/i40evf_main.c +5 -3
@@ -1746,15 +1746,17 @@ static void i40evf_reset_task(struct work_struct *work)/* wait until the reset is complete and the PF is responding to us */ for (i =0 ; i <I40EVF_RESET_WAIT_COUNT ; i++) { +/* sleep first to make sure a minimum wait time is met */ +msleep (I40EVF_RESET_WAIT_MS ); + reg_val =rd32 (hw,I40E_VFGEN_RSTAT ) &I40E_VFGEN_RSTAT_VFR_STATE_MASK ;if (reg_val ==I40E_VFR_VFACTIVE )break ; -msleep (I40EVF_RESET_WAIT_MS ); } +pci_set_master (adapter->pdev); -/* extra wait to make sure minimum wait is met */ -msleep (I40EVF_RESET_WAIT_MS ); +if (i ==I40EVF_RESET_WAIT_COUNT ) {struct i40evf_mac_filter *ftmp;struct i40evf_vlan_filter *fv, *fvtmp;
Signature · 1 line
2.4.11
cover i40e/i40evf updates
In reply to Bimmy PujariQuoted 28 lines · Bimmy Pujari
Alan Brady adds code to fix mac filters when removing vlans.
Jacob Keller drops
is_vfandis_netdevfields in struct?i40e_mac_filter, adds code to make use of__dev_uc_sync? and__dev_mc_sync, movesi40e_put_mac_in_vlanand?i40e_del_mac_all_vlan, fixesi40e_put_mac_in_vlanto? return actual filter added, adds code to ignore removed? filters When searching all MAC/VLAN filters, implements?__i40e_del_filterand use where applicable, adds code to? store MAC/VLAN filters in a hash with the MAC Address as? key, adds code to properly cleanup on allocation failure? ini40e_sync_vsi_filters, adds code to avoid looping to? check whether we're in vlan mode, removes duplicate add/ delete adminq command code for filters, corrects check? for reading TSYNINDX from the receive descriptor, uses a? mutex instead of spinlock in PTP user entry points, replaces? PTP Rx timestamp hang logic and adds code to avoid an extra? msleep while waiting for reset.?drivers/net/ethernet/intel/i40e/i40e.h?????????????|??50 +- ?drivers/net/ethernet/intel/i40e/i40e_debugfs.c?????|??92 +- ?drivers/net/ethernet/intel/i40e/i40e_main.c????????| 949 +++++++++++-- -------- ?drivers/net/ethernet/intel/i40e/i40e_ptp.c?????????| 137 +-- ?drivers/net/ethernet/intel/i40e/i40e_txrx.c????????|???9 +- ?drivers/net/ethernet/intel/i40e/i40e_txrx.h????????|???2 - ?drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c |??57 +- ?drivers/net/ethernet/intel/i40evf/i40evf_main.c????|???8 +-
Quoted 2 lines
?8 files changed, 663 insertions(+), 641 deletions(-)
I tried to compile the very first patch it does not compile. ?I get the following errors:
[23:59:15 @jtkirshe-linux:next-queue]$ make -j 77 -s
? DESCEND??objtooldrivers/net/ethernet/intel/i40e/i40e_fcoe.c: In function ?i40e_fcoe_config_netdev?:drivers/net/ethernet/intel/i40e/i40e_fcoe.c:1526:2: error: too many arguments to function ?i40e_add_filter?
? i40e_add_filter(vsi, hw->mac.san_addr, 0, false, false);
? ^~~~~~~~~~~~~~~
In file included from drivers/net/ethernet/intel/i40e/i40e_fcoe.c:37:0:drivers/net/ethernet/intel/i40e/i40e.h:722:25: note: declared here ?struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, ?????????????????????????^~~~~~~~~~~~~~~ drivers/net/ethernet/intel/i40e/i40e_fcoe.c:1527:2: error: too many arguments to function ?i40e_add_filter?
? i40e_add_filter(vsi, (u8[6]) FC_FCOE_FLOGI_MAC, 0, false, false); ? ^~~~~~~~~~~~~~~
In file included from drivers/net/ethernet/intel/i40e/i40e_fcoe.c:37:0:drivers/net/ethernet/intel/i40e/i40e.h:722:25: note: declared here ?struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, ?????????????????????????^~~~~~~~~~~~~~~ drivers/net/ethernet/intel/i40e/i40e_fcoe.c:1528:2: error: too many arguments to function ?i40e_add_filter?
? i40e_add_filter(vsi, FIP_ALL_FCOE_MACS, 0, false, false);
? ^~~~~~~~~~~~~~~
In file included from drivers/net/ethernet/intel/i40e/i40e_fcoe.c:37:0:drivers/net/ethernet/intel/i40e/i40e.h:722:25: note: declared here ?struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, ?????????????????????????^~~~~~~~~~~~~~~ drivers/net/ethernet/intel/i40e/i40e_fcoe.c:1529:2: error: too many arguments to function ?i40e_add_filter?
? i40e_add_filter(vsi, FIP_ALL_ENODE_MACS, 0, false, false);
? ^~~~~~~~~~~~~~~
In file included from drivers/net/ethernet/intel/i40e/i40e_fcoe.c:37:0:drivers/net/ethernet/intel/i40e/i40e.h:722:25: note: declared here ?struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi, ?????????????????????????^~~~~~~~~~~~~~~ scripts/Makefile.build:289: recipe for target 'drivers/net/ethernet/intel/i40e/i40e_fcoe.o' failed
make[5]: *** [drivers/net/ethernet/intel/i40e/i40e_fcoe.o] Error 1 make[5]: *** Waiting for unfinished jobs.... scripts/Makefile.build:440: recipe for target 'drivers/net/ethernet/intel/i40e' failed
make[4]: *** [drivers/net/ethernet/intel/i40e] Error 2 scripts/Makefile.build:440: recipe for target 'drivers/net/ethernet/intel' failed
make[3]: *** [drivers/net/ethernet/intel] Error 2 scripts/Makefile.build:440: recipe for target 'drivers/net/ethernet' failed make[2]: *** [drivers/net/ethernet] Error 2 scripts/Makefile.build:440: recipe for target 'drivers/net' failed make[1]: *** [drivers/net] Error 2
Makefile:968: recipe for target 'drivers' failed
make: *** [drivers] Error 2
So I am dropping this series. ?Make sure every patch compiles on its own,
once you fix the first patch (and any other patches that may need changes),
please resubmit the series.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: This is a digitally signed message part
URL: <http://lists.osuosl.org/pipermail/intel-wired-lan/attachments/20160930/b46f98c1/attachment.asc>