igc: Refactor igc_ethtool_update_nfc_rule()
Current implementation of igc_ethtool_update_nfc_rule() is a bit convoluted since it handles too many things: rule lookup, deletion and addition. This patch breaks it into three functions so we simplify the code and improve code reuse. Code related to rule lookup is refactored out to a new function called igc_get_nfc_rule(). Code related to rule addition is refactored out to a new function called igc_add_nfc_rule(). This function enables the rule in hardware and adds it to the adapter's list. Code related to rule deletion is refactored out to a new function called igc_del_nfc_rule(). This function disables the rule in hardware, removes it from adapter's list, and deletes it. As a byproduct of this refactoring, igc_enable_nfc_rule() and igc_disable_nfc_rule() are moved to igc_main.c since they are not used in igc_ethtool.c anymore, and igc_restore_nfc_rules() and igc_nfc_rule_ exit() are moved around to avoid forward declaration. Also, since this patch already touches igc_ethtool_get_nfc_rule(), it takes the opportunity to remove the 'match_flags' check. Empty flags are not allowed to be added so no need to check that. Signed-off-by: Andre Guedes <andre.guedes@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
d957c6010a
commit
36fa21520f
drivers/net/ethernet/intel/igc
|
@ -232,16 +232,6 @@ void igc_write_rss_indir_tbl(struct igc_adapter *adapter);
|
|||
bool igc_has_link(struct igc_adapter *adapter);
|
||||
void igc_reset(struct igc_adapter *adapter);
|
||||
int igc_set_spd_dplx(struct igc_adapter *adapter, u32 spd, u8 dplx);
|
||||
int igc_add_mac_filter(struct igc_adapter *adapter,
|
||||
enum igc_mac_filter_type type, const u8 *addr,
|
||||
int queue);
|
||||
int igc_del_mac_filter(struct igc_adapter *adapter,
|
||||
enum igc_mac_filter_type type, const u8 *addr);
|
||||
int igc_add_vlan_prio_filter(struct igc_adapter *adapter, int prio,
|
||||
int queue);
|
||||
void igc_del_vlan_prio_filter(struct igc_adapter *adapter, int prio);
|
||||
int igc_add_etype_filter(struct igc_adapter *adapter, u16 etype, int queue);
|
||||
int igc_del_etype_filter(struct igc_adapter *adapter, u16 etype);
|
||||
void igc_update_stats(struct igc_adapter *adapter);
|
||||
|
||||
/* igc_dump declarations */
|
||||
|
@ -544,10 +534,10 @@ static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data)
|
|||
}
|
||||
|
||||
void igc_reinit_locked(struct igc_adapter *);
|
||||
int igc_enable_nfc_rule(struct igc_adapter *adapter,
|
||||
const struct igc_nfc_rule *rule);
|
||||
int igc_disable_nfc_rule(struct igc_adapter *adapter,
|
||||
const struct igc_nfc_rule *rule);
|
||||
struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
|
||||
u32 location);
|
||||
int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
|
||||
void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule);
|
||||
|
||||
void igc_ptp_init(struct igc_adapter *adapter);
|
||||
void igc_ptp_reset(struct igc_adapter *adapter);
|
||||
|
|
|
@ -941,15 +941,8 @@ static int igc_ethtool_get_nfc_rule(struct igc_adapter *adapter,
|
|||
|
||||
spin_lock(&adapter->nfc_rule_lock);
|
||||
|
||||
list_for_each_entry(rule, &adapter->nfc_rule_list, list) {
|
||||
if (fsp->location <= rule->location)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!rule || fsp->location != rule->location)
|
||||
goto out;
|
||||
|
||||
if (!rule->filter.match_flags)
|
||||
rule = igc_get_nfc_rule(adapter, fsp->location);
|
||||
if (!rule)
|
||||
goto out;
|
||||
|
||||
fsp->flow_type = ETHER_FLOW;
|
||||
|
@ -1190,108 +1183,6 @@ static int igc_ethtool_set_rss_hash_opt(struct igc_adapter *adapter,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int igc_enable_nfc_rule(struct igc_adapter *adapter,
|
||||
const struct igc_nfc_rule *rule)
|
||||
{
|
||||
int err = -EINVAL;
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) {
|
||||
err = igc_add_etype_filter(adapter, rule->filter.etype,
|
||||
rule->action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) {
|
||||
err = igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_SRC,
|
||||
rule->filter.src_addr, rule->action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) {
|
||||
err = igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST,
|
||||
rule->filter.dst_addr, rule->action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) {
|
||||
int prio = (rule->filter.vlan_tci & VLAN_PRIO_MASK) >>
|
||||
VLAN_PRIO_SHIFT;
|
||||
|
||||
err = igc_add_vlan_prio_filter(adapter, prio, rule->action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int igc_disable_nfc_rule(struct igc_adapter *adapter,
|
||||
const struct igc_nfc_rule *rule)
|
||||
{
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE)
|
||||
igc_del_etype_filter(adapter, rule->filter.etype);
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) {
|
||||
int prio = (rule->filter.vlan_tci & VLAN_PRIO_MASK) >>
|
||||
VLAN_PRIO_SHIFT;
|
||||
igc_del_vlan_prio_filter(adapter, prio);
|
||||
}
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR)
|
||||
igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_SRC,
|
||||
rule->filter.src_addr);
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR)
|
||||
igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST,
|
||||
rule->filter.dst_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igc_ethtool_update_nfc_rule(struct igc_adapter *adapter,
|
||||
struct igc_nfc_rule *input,
|
||||
u32 location)
|
||||
{
|
||||
struct igc_nfc_rule *rule, *parent;
|
||||
int err = -EINVAL;
|
||||
|
||||
parent = NULL;
|
||||
rule = NULL;
|
||||
|
||||
list_for_each_entry(rule, &adapter->nfc_rule_list, list) {
|
||||
/* hash found, or no matching entry */
|
||||
if (rule->location >= location)
|
||||
break;
|
||||
parent = rule;
|
||||
}
|
||||
|
||||
/* if there is an old rule occupying our place remove it */
|
||||
if (rule && rule->location == location) {
|
||||
err = igc_disable_nfc_rule(adapter, rule);
|
||||
|
||||
list_del(&rule->list);
|
||||
kfree(rule);
|
||||
adapter->nfc_rule_count--;
|
||||
}
|
||||
|
||||
/* If no input this was a delete, err should be 0 if a rule was
|
||||
* successfully found and removed from the list else -EINVAL
|
||||
*/
|
||||
if (!input)
|
||||
return err;
|
||||
|
||||
list_add(&input->list, parent ? &parent->list :
|
||||
&adapter->nfc_rule_list);
|
||||
|
||||
/* update counts */
|
||||
adapter->nfc_rule_count++;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void igc_ethtool_init_nfc_rule(struct igc_nfc_rule *rule,
|
||||
const struct ethtool_rx_flow_spec *fsp)
|
||||
{
|
||||
|
@ -1376,7 +1267,7 @@ static int igc_ethtool_add_nfc_rule(struct igc_adapter *adapter,
|
|||
struct net_device *netdev = adapter->netdev;
|
||||
struct ethtool_rx_flow_spec *fsp =
|
||||
(struct ethtool_rx_flow_spec *)&cmd->fs;
|
||||
struct igc_nfc_rule *rule;
|
||||
struct igc_nfc_rule *rule, *old_rule;
|
||||
int err;
|
||||
|
||||
if (!(netdev->hw_features & NETIF_F_NTUPLE)) {
|
||||
|
@ -1417,12 +1308,14 @@ static int igc_ethtool_add_nfc_rule(struct igc_adapter *adapter,
|
|||
if (err)
|
||||
goto err;
|
||||
|
||||
err = igc_enable_nfc_rule(adapter, rule);
|
||||
old_rule = igc_get_nfc_rule(adapter, fsp->location);
|
||||
if (old_rule)
|
||||
igc_del_nfc_rule(adapter, old_rule);
|
||||
|
||||
err = igc_add_nfc_rule(adapter, rule);
|
||||
if (err)
|
||||
goto err;
|
||||
|
||||
igc_ethtool_update_nfc_rule(adapter, rule, rule->location);
|
||||
|
||||
spin_unlock(&adapter->nfc_rule_lock);
|
||||
return 0;
|
||||
|
||||
|
@ -1437,13 +1330,20 @@ static int igc_ethtool_del_nfc_rule(struct igc_adapter *adapter,
|
|||
{
|
||||
struct ethtool_rx_flow_spec *fsp =
|
||||
(struct ethtool_rx_flow_spec *)&cmd->fs;
|
||||
int err;
|
||||
struct igc_nfc_rule *rule;
|
||||
|
||||
spin_lock(&adapter->nfc_rule_lock);
|
||||
err = igc_ethtool_update_nfc_rule(adapter, NULL, fsp->location);
|
||||
spin_unlock(&adapter->nfc_rule_lock);
|
||||
|
||||
return err;
|
||||
rule = igc_get_nfc_rule(adapter, fsp->location);
|
||||
if (!rule) {
|
||||
spin_unlock(&adapter->nfc_rule_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
igc_del_nfc_rule(adapter, rule);
|
||||
|
||||
spin_unlock(&adapter->nfc_rule_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igc_ethtool_set_rxnfc(struct net_device *dev,
|
||||
|
|
|
@ -2174,18 +2174,6 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
|
|||
return !!budget;
|
||||
}
|
||||
|
||||
static void igc_restore_nfc_rules(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_nfc_rule *rule;
|
||||
|
||||
spin_lock(&adapter->nfc_rule_lock);
|
||||
|
||||
list_for_each_entry_reverse(rule, &adapter->nfc_rule_list, list)
|
||||
igc_enable_nfc_rule(adapter, rule);
|
||||
|
||||
spin_unlock(&adapter->nfc_rule_lock);
|
||||
}
|
||||
|
||||
static int igc_find_mac_filter(struct igc_adapter *adapter,
|
||||
enum igc_mac_filter_type type, const u8 *addr)
|
||||
{
|
||||
|
@ -2242,9 +2230,9 @@ static int igc_get_avail_mac_filter_slot(struct igc_adapter *adapter)
|
|||
*
|
||||
* Return: 0 in case of success, negative errno code otherwise.
|
||||
*/
|
||||
int igc_add_mac_filter(struct igc_adapter *adapter,
|
||||
enum igc_mac_filter_type type, const u8 *addr,
|
||||
int queue)
|
||||
static int igc_add_mac_filter(struct igc_adapter *adapter,
|
||||
enum igc_mac_filter_type type, const u8 *addr,
|
||||
int queue)
|
||||
{
|
||||
struct net_device *dev = adapter->netdev;
|
||||
int index;
|
||||
|
@ -2274,8 +2262,8 @@ update_filter:
|
|||
*
|
||||
* Return: 0 in case of success, negative errno code otherwise.
|
||||
*/
|
||||
int igc_del_mac_filter(struct igc_adapter *adapter,
|
||||
enum igc_mac_filter_type type, const u8 *addr)
|
||||
static int igc_del_mac_filter(struct igc_adapter *adapter,
|
||||
enum igc_mac_filter_type type, const u8 *addr)
|
||||
{
|
||||
struct net_device *dev = adapter->netdev;
|
||||
int index;
|
||||
|
@ -2312,7 +2300,8 @@ int igc_del_mac_filter(struct igc_adapter *adapter,
|
|||
*
|
||||
* Return: 0 in case of success, negative errno code otherwise.
|
||||
*/
|
||||
int igc_add_vlan_prio_filter(struct igc_adapter *adapter, int prio, int queue)
|
||||
static int igc_add_vlan_prio_filter(struct igc_adapter *adapter, int prio,
|
||||
int queue)
|
||||
{
|
||||
struct net_device *dev = adapter->netdev;
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
|
@ -2340,7 +2329,7 @@ int igc_add_vlan_prio_filter(struct igc_adapter *adapter, int prio, int queue)
|
|||
* @adapter: Pointer to adapter where the filter should be deleted from
|
||||
* @prio: VLAN priority value
|
||||
*/
|
||||
void igc_del_vlan_prio_filter(struct igc_adapter *adapter, int prio)
|
||||
static void igc_del_vlan_prio_filter(struct igc_adapter *adapter, int prio)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
u32 vlanpqf;
|
||||
|
@ -2381,7 +2370,8 @@ static int igc_get_avail_etype_filter_slot(struct igc_adapter *adapter)
|
|||
*
|
||||
* Return: 0 in case of success, negative errno code otherwise.
|
||||
*/
|
||||
int igc_add_etype_filter(struct igc_adapter *adapter, u16 etype, int queue)
|
||||
static int igc_add_etype_filter(struct igc_adapter *adapter, u16 etype,
|
||||
int queue)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
int index;
|
||||
|
@ -2433,7 +2423,7 @@ static int igc_find_etype_filter(struct igc_adapter *adapter, u16 etype)
|
|||
*
|
||||
* Return: 0 in case of success, negative errno code otherwise.
|
||||
*/
|
||||
int igc_del_etype_filter(struct igc_adapter *adapter, u16 etype)
|
||||
static int igc_del_etype_filter(struct igc_adapter *adapter, u16 etype)
|
||||
{
|
||||
struct igc_hw *hw = &adapter->hw;
|
||||
int index;
|
||||
|
@ -2449,6 +2439,167 @@ int igc_del_etype_filter(struct igc_adapter *adapter, u16 etype)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int igc_enable_nfc_rule(struct igc_adapter *adapter,
|
||||
const struct igc_nfc_rule *rule)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) {
|
||||
err = igc_add_etype_filter(adapter, rule->filter.etype,
|
||||
rule->action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) {
|
||||
err = igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_SRC,
|
||||
rule->filter.src_addr, rule->action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) {
|
||||
err = igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST,
|
||||
rule->filter.dst_addr, rule->action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) {
|
||||
int prio = (rule->filter.vlan_tci & VLAN_PRIO_MASK) >>
|
||||
VLAN_PRIO_SHIFT;
|
||||
|
||||
err = igc_add_vlan_prio_filter(adapter, prio, rule->action);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int igc_disable_nfc_rule(struct igc_adapter *adapter,
|
||||
const struct igc_nfc_rule *rule)
|
||||
{
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE)
|
||||
igc_del_etype_filter(adapter, rule->filter.etype);
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) {
|
||||
int prio = (rule->filter.vlan_tci & VLAN_PRIO_MASK) >>
|
||||
VLAN_PRIO_SHIFT;
|
||||
|
||||
igc_del_vlan_prio_filter(adapter, prio);
|
||||
}
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR)
|
||||
igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_SRC,
|
||||
rule->filter.src_addr);
|
||||
|
||||
if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR)
|
||||
igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST,
|
||||
rule->filter.dst_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_get_nfc_rule() - Get NFC rule
|
||||
* @adapter: Pointer to adapter
|
||||
* @location: Rule location
|
||||
*
|
||||
* Context: Expects adapter->nfc_rule_lock to be held by caller.
|
||||
*
|
||||
* Return: Pointer to NFC rule at @location. If not found, NULL.
|
||||
*/
|
||||
struct igc_nfc_rule *igc_get_nfc_rule(struct igc_adapter *adapter,
|
||||
u32 location)
|
||||
{
|
||||
struct igc_nfc_rule *rule;
|
||||
|
||||
list_for_each_entry(rule, &adapter->nfc_rule_list, list) {
|
||||
if (rule->location == location)
|
||||
return rule;
|
||||
if (rule->location > location)
|
||||
break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_del_nfc_rule() - Delete NFC rule
|
||||
* @adapter: Pointer to adapter
|
||||
* @rule: Pointer to rule to be deleted
|
||||
*
|
||||
* Disable NFC rule in hardware and delete it from adapter.
|
||||
*
|
||||
* Context: Expects adapter->nfc_rule_lock to be held by caller.
|
||||
*/
|
||||
void igc_del_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule)
|
||||
{
|
||||
igc_disable_nfc_rule(adapter, rule);
|
||||
|
||||
list_del(&rule->list);
|
||||
adapter->nfc_rule_count--;
|
||||
|
||||
kfree(rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_add_nfc_rule() - Add NFC rule
|
||||
* @adapter: Pointer to adapter
|
||||
* @rule: Pointer to rule to be added
|
||||
*
|
||||
* Enable NFC rule in hardware and add it to adapter.
|
||||
*
|
||||
* Context: Expects adapter->nfc_rule_lock to be held by caller.
|
||||
*
|
||||
* Return: 0 on success, negative errno on failure.
|
||||
*/
|
||||
int igc_add_nfc_rule(struct igc_adapter *adapter, struct igc_nfc_rule *rule)
|
||||
{
|
||||
struct igc_nfc_rule *pred, *cur;
|
||||
int err;
|
||||
|
||||
err = igc_enable_nfc_rule(adapter, rule);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pred = NULL;
|
||||
list_for_each_entry(cur, &adapter->nfc_rule_list, list) {
|
||||
if (cur->location >= rule->location)
|
||||
break;
|
||||
pred = cur;
|
||||
}
|
||||
|
||||
list_add(&rule->list, pred ? &pred->list : &adapter->nfc_rule_list);
|
||||
adapter->nfc_rule_count++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void igc_restore_nfc_rules(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_nfc_rule *rule;
|
||||
|
||||
spin_lock(&adapter->nfc_rule_lock);
|
||||
|
||||
list_for_each_entry_reverse(rule, &adapter->nfc_rule_list, list)
|
||||
igc_enable_nfc_rule(adapter, rule);
|
||||
|
||||
spin_unlock(&adapter->nfc_rule_lock);
|
||||
}
|
||||
|
||||
static void igc_nfc_rule_exit(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_nfc_rule *rule;
|
||||
|
||||
spin_lock(&adapter->nfc_rule_lock);
|
||||
|
||||
list_for_each_entry(rule, &adapter->nfc_rule_list, list)
|
||||
igc_disable_nfc_rule(adapter, rule);
|
||||
|
||||
spin_unlock(&adapter->nfc_rule_lock);
|
||||
}
|
||||
|
||||
static int igc_uc_sync(struct net_device *netdev, const unsigned char *addr)
|
||||
{
|
||||
struct igc_adapter *adapter = netdev_priv(netdev);
|
||||
|
@ -3648,18 +3799,6 @@ void igc_update_stats(struct igc_adapter *adapter)
|
|||
adapter->stats.mgpdc += rd32(IGC_MGTPDC);
|
||||
}
|
||||
|
||||
static void igc_nfc_rule_exit(struct igc_adapter *adapter)
|
||||
{
|
||||
struct igc_nfc_rule *rule;
|
||||
|
||||
spin_lock(&adapter->nfc_rule_lock);
|
||||
|
||||
list_for_each_entry(rule, &adapter->nfc_rule_list, list)
|
||||
igc_disable_nfc_rule(adapter, rule);
|
||||
|
||||
spin_unlock(&adapter->nfc_rule_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* igc_down - Close the interface
|
||||
* @adapter: board private structure
|
||||
|
|
Loading…
Reference in New Issue