diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/intel/e1000/e1000_main.c | 18 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc.h | 69 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_defines.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_ethtool.c | 468 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_mac.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_main.c | 162 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_regs.h | 11 |
7 files changed, 342 insertions, 393 deletions
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 05bc6e216bca..d9fa4600f745 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -542,8 +542,13 @@ void e1000_reinit_locked(struct e1000_adapter *adapter) WARN_ON(in_interrupt()); while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) msleep(1); - e1000_down(adapter); - e1000_up(adapter); + + /* only run the task if not already down */ + if (!test_bit(__E1000_DOWN, &adapter->flags)) { + e1000_down(adapter); + e1000_up(adapter); + } + clear_bit(__E1000_RESETTING, &adapter->flags); } @@ -1433,10 +1438,15 @@ int e1000_close(struct net_device *netdev) struct e1000_hw *hw = &adapter->hw; int count = E1000_CHECK_RESET_COUNT; - while (test_bit(__E1000_RESETTING, &adapter->flags) && count--) + while (test_and_set_bit(__E1000_RESETTING, &adapter->flags) && count--) usleep_range(10000, 20000); - WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); + WARN_ON(count < 0); + + /* signal that we're down so that the reset task will no longer run */ + set_bit(__E1000_DOWN, &adapter->flags); + clear_bit(__E1000_RESETTING, &adapter->flags); + e1000_down(adapter); e1000_power_down_phy(adapter); e1000_free_irq(adapter); diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 812e1cd695cf..fcc6261d7f67 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h @@ -16,8 +16,7 @@ #include "igc_hw.h" -/* forward declaration */ -void igc_set_ethtool_ops(struct net_device *); +void igc_ethtool_set_ops(struct net_device *); /* Transmit and receive queues */ #define IGC_MAX_RX_QUEUES 4 @@ -29,6 +28,11 @@ void igc_set_ethtool_ops(struct net_device *); #define MAX_ETYPE_FILTER 8 #define IGC_RETA_SIZE 128 +enum igc_mac_filter_type { + IGC_MAC_FILTER_TYPE_DST = 0, + IGC_MAC_FILTER_TYPE_SRC +}; + struct igc_tx_queue_stats { u64 packets; u64 bytes; @@ -183,14 +187,12 @@ struct igc_adapter { u32 rss_queues; u32 rss_indir_tbl_init; - /* RX network flow classification support */ - struct hlist_head nfc_filter_list; - unsigned int nfc_filter_count; - - /* lock for RX network flow classification filter */ - spinlock_t nfc_lock; - - struct igc_mac_addr *mac_table; + /* Any access to elements in nfc_rule_list is protected by the + * nfc_rule_lock. + */ + spinlock_t nfc_rule_lock; + struct hlist_head nfc_rule_list; + unsigned int nfc_rule_count; u8 rss_indir_tbl[IGC_RETA_SIZE]; @@ -230,10 +232,11 @@ 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, const u8 *addr, - const s8 queue, const u8 flags); -int igc_del_mac_filter(struct igc_adapter *adapter, const u8 *addr, - const u8 flags); +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); @@ -449,39 +452,22 @@ enum igc_filter_match_flags { IGC_FILTER_FLAG_DST_MAC_ADDR = 0x8, }; -/* RX network flow classification data structure */ -struct igc_nfc_input { - /* Byte layout in order, all values with MSB first: - * match_flags - 1 byte - * etype - 2 bytes - * vlan_tci - 2 bytes - */ +struct igc_nfc_filter { u8 match_flags; - __be16 etype; - __be16 vlan_tci; + u16 etype; + u16 vlan_tci; u8 src_addr[ETH_ALEN]; u8 dst_addr[ETH_ALEN]; }; -struct igc_nfc_filter { +struct igc_nfc_rule { struct hlist_node nfc_node; - struct igc_nfc_input filter; - unsigned long cookie; + struct igc_nfc_filter filter; u16 sw_idx; u16 action; }; -struct igc_mac_addr { - u8 addr[ETH_ALEN]; - s8 queue; - u8 state; /* bitmask */ -}; - -#define IGC_MAC_STATE_DEFAULT 0x1 -#define IGC_MAC_STATE_IN_USE 0x2 -#define IGC_MAC_STATE_SRC_ADDR 0x4 - -#define IGC_MAX_RXNFC_FILTERS 16 +#define IGC_MAX_RXNFC_RULES 16 /* igc_desc_unused - calculate if we have unused descriptors */ static inline u16 igc_desc_unused(const struct igc_ring *ring) @@ -557,12 +543,11 @@ static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data) return 0; } -/* forward declaration */ void igc_reinit_locked(struct igc_adapter *); -int igc_add_filter(struct igc_adapter *adapter, - struct igc_nfc_filter *input); -int igc_erase_filter(struct igc_adapter *adapter, - struct igc_nfc_filter *input); +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); void igc_ptp_init(struct igc_adapter *adapter); void igc_ptp_reset(struct igc_adapter *adapter); diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 51d8a15e239c..45b567587ca9 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h @@ -62,6 +62,9 @@ * (RAR[15]) for our directed address used by controllers with * manageability enabled, allowing us room for 15 multicast addresses. */ +#define IGC_RAH_RAH_MASK 0x0000FFFF +#define IGC_RAH_ASEL_MASK 0x00030000 +#define IGC_RAH_ASEL_SRC_ADDR BIT(16) #define IGC_RAH_QSEL_MASK 0x000C0000 #define IGC_RAH_QSEL_SHIFT 18 #define IGC_RAH_QSEL_ENABLE BIT(28) diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c index c6586e2be3a8..66e0760a8f9e 100644 --- a/drivers/net/ethernet/intel/igc/igc_ethtool.c +++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c @@ -124,8 +124,8 @@ static const char igc_priv_flags_strings[][ETH_GSTRING_LEN] = { #define IGC_PRIV_FLAGS_STR_LEN ARRAY_SIZE(igc_priv_flags_strings) -static void igc_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) +static void igc_ethtool_get_drvinfo(struct net_device *netdev, + struct ethtool_drvinfo *drvinfo) { struct igc_adapter *adapter = netdev_priv(netdev); @@ -139,13 +139,13 @@ static void igc_get_drvinfo(struct net_device *netdev, drvinfo->n_priv_flags = IGC_PRIV_FLAGS_STR_LEN; } -static int igc_get_regs_len(struct net_device *netdev) +static int igc_ethtool_get_regs_len(struct net_device *netdev) { return IGC_REGS_LEN * sizeof(u32); } -static void igc_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) +static void igc_ethtool_get_regs(struct net_device *netdev, + struct ethtool_regs *regs, void *p) { struct igc_adapter *adapter = netdev_priv(netdev); struct igc_hw *hw = &adapter->hw; @@ -323,7 +323,8 @@ static void igc_get_regs(struct net_device *netdev, regs_buff[205 + i] = rd32(IGC_ETQF(i)); } -static void igc_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +static void igc_ethtool_get_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) { struct igc_adapter *adapter = netdev_priv(netdev); @@ -354,7 +355,8 @@ static void igc_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) wol->wolopts |= WAKE_PHY; } -static int igc_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) +static int igc_ethtool_set_wol(struct net_device *netdev, + struct ethtool_wolinfo *wol) { struct igc_adapter *adapter = netdev_priv(netdev); @@ -382,21 +384,21 @@ static int igc_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) return 0; } -static u32 igc_get_msglevel(struct net_device *netdev) +static u32 igc_ethtool_get_msglevel(struct net_device *netdev) { struct igc_adapter *adapter = netdev_priv(netdev); return adapter->msg_enable; } -static void igc_set_msglevel(struct net_device *netdev, u32 data) +static void igc_ethtool_set_msglevel(struct net_device *netdev, u32 data) { struct igc_adapter *adapter = netdev_priv(netdev); adapter->msg_enable = data; } -static int igc_nway_reset(struct net_device *netdev) +static int igc_ethtool_nway_reset(struct net_device *netdev) { struct igc_adapter *adapter = netdev_priv(netdev); @@ -405,7 +407,7 @@ static int igc_nway_reset(struct net_device *netdev) return 0; } -static u32 igc_get_link(struct net_device *netdev) +static u32 igc_ethtool_get_link(struct net_device *netdev) { struct igc_adapter *adapter = netdev_priv(netdev); struct igc_mac_info *mac = &adapter->hw.mac; @@ -422,15 +424,15 @@ static u32 igc_get_link(struct net_device *netdev) return igc_has_link(adapter); } -static int igc_get_eeprom_len(struct net_device *netdev) +static int igc_ethtool_get_eeprom_len(struct net_device *netdev) { struct igc_adapter *adapter = netdev_priv(netdev); return adapter->hw.nvm.word_size * 2; } -static int igc_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) +static int igc_ethtool_get_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) { struct igc_adapter *adapter = netdev_priv(netdev); struct igc_hw *hw = &adapter->hw; @@ -476,8 +478,8 @@ static int igc_get_eeprom(struct net_device *netdev, return ret_val; } -static int igc_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) +static int igc_ethtool_set_eeprom(struct net_device *netdev, + struct ethtool_eeprom *eeprom, u8 *bytes) { struct igc_adapter *adapter = netdev_priv(netdev); struct igc_hw *hw = &adapter->hw; @@ -544,8 +546,8 @@ static int igc_set_eeprom(struct net_device *netdev, return ret_val; } -static void igc_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) +static void igc_ethtool_get_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) { struct igc_adapter *adapter = netdev_priv(netdev); @@ -555,8 +557,8 @@ static void igc_get_ringparam(struct net_device *netdev, ring->tx_pending = adapter->tx_ring_count; } -static int igc_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) +static int igc_ethtool_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ring) { struct igc_adapter *adapter = netdev_priv(netdev); struct igc_ring *temp_ring; @@ -670,8 +672,8 @@ clear_reset: return err; } -static void igc_get_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) +static void igc_ethtool_get_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) { struct igc_adapter *adapter = netdev_priv(netdev); struct igc_hw *hw = &adapter->hw; @@ -689,8 +691,8 @@ static void igc_get_pauseparam(struct net_device *netdev, } } -static int igc_set_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) +static int igc_ethtool_set_pauseparam(struct net_device *netdev, + struct ethtool_pauseparam *pause) { struct igc_adapter *adapter = netdev_priv(netdev); struct igc_hw *hw = &adapter->hw; @@ -729,7 +731,8 @@ static int igc_set_pauseparam(struct net_device *netdev, return retval; } -static void igc_get_strings(struct net_device *netdev, u32 stringset, u8 *data) +static void igc_ethtool_get_strings(struct net_device *netdev, u32 stringset, + u8 *data) { struct igc_adapter *adapter = netdev_priv(netdev); u8 *p = data; @@ -780,7 +783,7 @@ static void igc_get_strings(struct net_device *netdev, u32 stringset, u8 *data) } } -static int igc_get_sset_count(struct net_device *netdev, int sset) +static int igc_ethtool_get_sset_count(struct net_device *netdev, int sset) { switch (sset) { case ETH_SS_STATS: @@ -794,7 +797,7 @@ static int igc_get_sset_count(struct net_device *netdev, int sset) } } -static void igc_get_ethtool_stats(struct net_device *netdev, +static void igc_ethtool_get_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) { struct igc_adapter *adapter = netdev_priv(netdev); @@ -850,8 +853,8 @@ static void igc_get_ethtool_stats(struct net_device *netdev, spin_unlock(&adapter->stats64_lock); } -static int igc_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) +static int igc_ethtool_get_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) { struct igc_adapter *adapter = netdev_priv(netdev); @@ -870,8 +873,8 @@ static int igc_get_coalesce(struct net_device *netdev, return 0; } -static int igc_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) +static int igc_ethtool_set_coalesce(struct net_device *netdev, + struct ethtool_coalesce *ec) { struct igc_adapter *adapter = netdev_priv(netdev); int i; @@ -928,16 +931,15 @@ static int igc_set_coalesce(struct net_device *netdev, } #define ETHER_TYPE_FULL_MASK ((__force __be16)~0) -static int igc_get_ethtool_nfc_entry(struct igc_adapter *adapter, - struct ethtool_rxnfc *cmd) +static int igc_ethtool_get_nfc_rule(struct igc_adapter *adapter, + struct ethtool_rxnfc *cmd) { struct ethtool_rx_flow_spec *fsp = &cmd->fs; - struct igc_nfc_filter *rule = NULL; + struct igc_nfc_rule *rule = NULL; - /* report total rule count */ - cmd->data = IGC_MAX_RXNFC_FILTERS; + cmd->data = IGC_MAX_RXNFC_RULES; - hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) { + hlist_for_each_entry(rule, &adapter->nfc_rule_list, nfc_node) { if (fsp->location <= rule->sw_idx) break; } @@ -945,51 +947,48 @@ static int igc_get_ethtool_nfc_entry(struct igc_adapter *adapter, if (!rule || fsp->location != rule->sw_idx) return -EINVAL; - if (rule->filter.match_flags) { - fsp->flow_type = ETHER_FLOW; - fsp->ring_cookie = rule->action; - if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) { - fsp->h_u.ether_spec.h_proto = rule->filter.etype; - fsp->m_u.ether_spec.h_proto = ETHER_TYPE_FULL_MASK; - } - if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) { - fsp->flow_type |= FLOW_EXT; - fsp->h_ext.vlan_tci = rule->filter.vlan_tci; - fsp->m_ext.vlan_tci = htons(VLAN_PRIO_MASK); - } - if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) { - ether_addr_copy(fsp->h_u.ether_spec.h_dest, - rule->filter.dst_addr); - /* As we only support matching by the full - * mask, return the mask to userspace - */ - eth_broadcast_addr(fsp->m_u.ether_spec.h_dest); - } - if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) { - ether_addr_copy(fsp->h_u.ether_spec.h_source, - rule->filter.src_addr); - /* As we only support matching by the full - * mask, return the mask to userspace - */ - eth_broadcast_addr(fsp->m_u.ether_spec.h_source); - } + if (!rule->filter.match_flags) + return -EINVAL; - return 0; + fsp->flow_type = ETHER_FLOW; + fsp->ring_cookie = rule->action; + + if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) { + fsp->h_u.ether_spec.h_proto = htons(rule->filter.etype); + fsp->m_u.ether_spec.h_proto = ETHER_TYPE_FULL_MASK; + } + + if (rule->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) { + fsp->flow_type |= FLOW_EXT; + fsp->h_ext.vlan_tci = htons(rule->filter.vlan_tci); + fsp->m_ext.vlan_tci = htons(VLAN_PRIO_MASK); + } + + if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) { + ether_addr_copy(fsp->h_u.ether_spec.h_dest, + rule->filter.dst_addr); + eth_broadcast_addr(fsp->m_u.ether_spec.h_dest); } - return -EINVAL; + + if (rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) { + ether_addr_copy(fsp->h_u.ether_spec.h_source, + rule->filter.src_addr); + eth_broadcast_addr(fsp->m_u.ether_spec.h_source); + } + + return 0; } -static int igc_get_ethtool_nfc_all(struct igc_adapter *adapter, - struct ethtool_rxnfc *cmd, - u32 *rule_locs) +static int igc_ethtool_get_nfc_rules(struct igc_adapter *adapter, + struct ethtool_rxnfc *cmd, + u32 *rule_locs) { - struct igc_nfc_filter *rule; + struct igc_nfc_rule *rule; int cnt = 0; - /* report total rule count */ - cmd->data = IGC_MAX_RXNFC_FILTERS; + cmd->data = IGC_MAX_RXNFC_RULES; - hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) { + hlist_for_each_entry(rule, &adapter->nfc_rule_list, nfc_node) { if (cnt == cmd->rule_cnt) return -EMSGSIZE; rule_locs[cnt] = rule->sw_idx; @@ -1001,8 +1000,8 @@ static int igc_get_ethtool_nfc_all(struct igc_adapter *adapter, return 0; } -static int igc_get_rss_hash_opts(struct igc_adapter *adapter, - struct ethtool_rxnfc *cmd) +static int igc_ethtool_get_rss_hash_opts(struct igc_adapter *adapter, + struct ethtool_rxnfc *cmd) { cmd->data = 0; @@ -1051,41 +1050,33 @@ static int igc_get_rss_hash_opts(struct igc_adapter *adapter, return 0; } -static int igc_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, - u32 *rule_locs) +static int igc_ethtool_get_rxnfc(struct net_device *dev, + struct ethtool_rxnfc *cmd, u32 *rule_locs) { struct igc_adapter *adapter = netdev_priv(dev); - int ret = -EOPNOTSUPP; switch (cmd->cmd) { case ETHTOOL_GRXRINGS: cmd->data = adapter->num_rx_queues; - ret = 0; - break; + return 0; case ETHTOOL_GRXCLSRLCNT: - cmd->rule_cnt = adapter->nfc_filter_count; - ret = 0; - break; + cmd->rule_cnt = adapter->nfc_rule_count; + return 0; case ETHTOOL_GRXCLSRULE: - ret = igc_get_ethtool_nfc_entry(adapter, cmd); - break; + return igc_ethtool_get_nfc_rule(adapter, cmd); case ETHTOOL_GRXCLSRLALL: - ret = igc_get_ethtool_nfc_all(adapter, cmd, rule_locs); - break; + return igc_ethtool_get_nfc_rules(adapter, cmd, rule_locs); case ETHTOOL_GRXFH: - ret = igc_get_rss_hash_opts(adapter, cmd); - break; + return igc_ethtool_get_rss_hash_opts(adapter, cmd); default: - break; + return -EOPNOTSUPP; } - - return ret; } #define UDP_RSS_FLAGS (IGC_FLAG_RSS_FIELD_IPV4_UDP | \ IGC_FLAG_RSS_FIELD_IPV6_UDP) -static int igc_set_rss_hash_opt(struct igc_adapter *adapter, - struct ethtool_rxnfc *nfc) +static int igc_ethtool_set_rss_hash_opt(struct igc_adapter *adapter, + struct ethtool_rxnfc *nfc) { u32 flags = adapter->flags; @@ -1186,45 +1177,37 @@ static int igc_set_rss_hash_opt(struct igc_adapter *adapter, return 0; } -int igc_add_filter(struct igc_adapter *adapter, struct igc_nfc_filter *input) +int igc_enable_nfc_rule(struct igc_adapter *adapter, + const struct igc_nfc_rule *rule) { - struct igc_hw *hw = &adapter->hw; int err = -EINVAL; - if (hw->mac.type == igc_i225 && - !(input->filter.match_flags & ~IGC_FILTER_FLAG_SRC_MAC_ADDR)) { - netdev_err(adapter->netdev, - "i225 doesn't support flow classification rules specifying only source addresses\n"); - return -EOPNOTSUPP; - } - - if (input->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) { - u16 etype = ntohs(input->filter.etype); - - err = igc_add_etype_filter(adapter, etype, input->action); + 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 (input->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) { - err = igc_add_mac_filter(adapter, input->filter.dst_addr, - input->action, 0); + 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 (input->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) { - err = igc_add_mac_filter(adapter, input->filter.src_addr, - input->action, - IGC_MAC_STATE_SRC_ADDR); + 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 (input->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) { - int prio = (ntohs(input->filter.vlan_tci) & VLAN_PRIO_MASK) >> + 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, input->action); + + err = igc_add_vlan_prio_filter(adapter, prio, rule->action); if (err) return err; } @@ -1232,41 +1215,40 @@ int igc_add_filter(struct igc_adapter *adapter, struct igc_nfc_filter *input) return 0; } -int igc_erase_filter(struct igc_adapter *adapter, struct igc_nfc_filter *input) +int igc_disable_nfc_rule(struct igc_adapter *adapter, + const struct igc_nfc_rule *rule) { - if (input->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) { - u16 etype = ntohs(input->filter.etype); + if (rule->filter.match_flags & IGC_FILTER_FLAG_ETHER_TYPE) + igc_del_etype_filter(adapter, rule->filter.etype); - igc_del_etype_filter(adapter, etype); - } - - if (input->filter.match_flags & IGC_FILTER_FLAG_VLAN_TCI) { - int prio = (ntohs(input->filter.vlan_tci) & VLAN_PRIO_MASK) >> + 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 (input->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) - igc_del_mac_filter(adapter, input->filter.src_addr, - IGC_MAC_STATE_SRC_ADDR); + 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 (input->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR) - igc_del_mac_filter(adapter, input->filter.dst_addr, 0); + 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_update_ethtool_nfc_entry(struct igc_adapter *adapter, - struct igc_nfc_filter *input, - u16 sw_idx) +static int igc_ethtool_update_nfc_rule(struct igc_adapter *adapter, + struct igc_nfc_rule *input, + u16 sw_idx) { - struct igc_nfc_filter *rule, *parent; + struct igc_nfc_rule *rule, *parent; int err = -EINVAL; parent = NULL; rule = NULL; - hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) { + hlist_for_each_entry(rule, &adapter->nfc_rule_list, nfc_node) { /* hash found, or no matching entry */ if (rule->sw_idx >= sw_idx) break; @@ -1276,11 +1258,11 @@ static int igc_update_ethtool_nfc_entry(struct igc_adapter *adapter, /* if there is an old rule occupying our place remove it */ if (rule && rule->sw_idx == sw_idx) { if (!input) - err = igc_erase_filter(adapter, rule); + err = igc_disable_nfc_rule(adapter, rule); hlist_del(&rule->nfc_node); kfree(rule); - adapter->nfc_filter_count--; + adapter->nfc_rule_count--; } /* If no input this was a delete, err should be 0 if a rule was @@ -1296,21 +1278,21 @@ static int igc_update_ethtool_nfc_entry(struct igc_adapter *adapter, if (parent) hlist_add_behind(&input->nfc_node, &parent->nfc_node); else - hlist_add_head(&input->nfc_node, &adapter->nfc_filter_list); + hlist_add_head(&input->nfc_node, &adapter->nfc_rule_list); /* update counts */ - adapter->nfc_filter_count++; + adapter->nfc_rule_count++; return 0; } -static int igc_add_ethtool_nfc_entry(struct igc_adapter *adapter, - struct ethtool_rxnfc *cmd) +static int igc_ethtool_add_nfc_rule(struct igc_adapter *adapter, + struct ethtool_rxnfc *cmd) { struct net_device *netdev = adapter->netdev; struct ethtool_rx_flow_spec *fsp = (struct ethtool_rx_flow_spec *)&cmd->fs; - struct igc_nfc_filter *input, *rule; + struct igc_nfc_rule *rule, *tmp; int err = 0; if (!(netdev->hw_features & NETIF_F_NTUPLE)) @@ -1327,7 +1309,7 @@ static int igc_add_ethtool_nfc_entry(struct igc_adapter *adapter, } /* Don't allow indexes to exist outside of available space */ - if (fsp->location >= IGC_MAX_RXNFC_FILTERS) { + if (fsp->location >= IGC_MAX_RXNFC_RULES) { netdev_err(netdev, "Location out of range\n"); return -EINVAL; } @@ -1335,47 +1317,55 @@ static int igc_add_ethtool_nfc_entry(struct igc_adapter *adapter, if ((fsp->flow_type & ~FLOW_EXT) != ETHER_FLOW) return -EINVAL; - input = kzalloc(sizeof(*input), GFP_KERNEL); - if (!input) + rule = kzalloc(sizeof(*rule), GFP_KERNEL); + if (!rule) return -ENOMEM; if (fsp->m_u.ether_spec.h_proto == ETHER_TYPE_FULL_MASK) { - input->filter.etype = fsp->h_u.ether_spec.h_proto; - input->filter.match_flags = IGC_FILTER_FLAG_ETHER_TYPE; + rule->filter.etype = ntohs(fsp->h_u.ether_spec.h_proto); + rule->filter.match_flags = IGC_FILTER_FLAG_ETHER_TYPE; } - /* Only support matching addresses by the full mask */ + /* Both source and destination address filters only support the full + * mask. + */ if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_source)) { - input->filter.match_flags |= IGC_FILTER_FLAG_SRC_MAC_ADDR; - ether_addr_copy(input->filter.src_addr, + rule->filter.match_flags |= IGC_FILTER_FLAG_SRC_MAC_ADDR; + ether_addr_copy(rule->filter.src_addr, fsp->h_u.ether_spec.h_source); } - /* Only support matching addresses by the full mask */ if (is_broadcast_ether_addr(fsp->m_u.ether_spec.h_dest)) { - input->filter.match_flags |= IGC_FILTER_FLAG_DST_MAC_ADDR; - ether_addr_copy(input->filter.dst_addr, + rule->filter.match_flags |= IGC_FILTER_FLAG_DST_MAC_ADDR; + ether_addr_copy(rule->filter.dst_addr, fsp->h_u.ether_spec.h_dest); } + if (rule->filter.match_flags & IGC_FILTER_FLAG_DST_MAC_ADDR && + rule->filter.match_flags & IGC_FILTER_FLAG_SRC_MAC_ADDR) { + netdev_dbg(netdev, "Filters with both dst and src are not supported\n"); + err = -EOPNOTSUPP; + goto err_out; + } + if ((fsp->flow_type & FLOW_EXT) && fsp->m_ext.vlan_tci) { if (fsp->m_ext.vlan_tci != htons(VLAN_PRIO_MASK)) { netdev_dbg(netdev, "VLAN mask not supported\n"); err = -EOPNOTSUPP; goto err_out; } - input->filter.vlan_tci = fsp->h_ext.vlan_tci; - input->filter.match_flags |= IGC_FILTER_FLAG_VLAN_TCI; + rule->filter.vlan_tci = ntohs(fsp->h_ext.vlan_tci); + rule->filter.match_flags |= IGC_FILTER_FLAG_VLAN_TCI; } - input->action = fsp->ring_cookie; - input->sw_idx = fsp->location; + rule->action = fsp->ring_cookie; + rule->sw_idx = fsp->location; - spin_lock(&adapter->nfc_lock); + spin_lock(&adapter->nfc_rule_lock); - hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) { - if (!memcmp(&input->filter, &rule->filter, - sizeof(input->filter))) { + hlist_for_each_entry(tmp, &adapter->nfc_rule_list, nfc_node) { + if (!memcmp(&rule->filter, &tmp->filter, + sizeof(rule->filter))) { err = -EEXIST; netdev_err(netdev, "ethtool: this filter is already set\n"); @@ -1383,55 +1373,51 @@ static int igc_add_ethtool_nfc_entry(struct igc_adapter *adapter, } } - err = igc_add_filter(adapter, input); + err = igc_enable_nfc_rule(adapter, rule); if (err) goto err_out_w_lock; - igc_update_ethtool_nfc_entry(adapter, input, input->sw_idx); + igc_ethtool_update_nfc_rule(adapter, rule, rule->sw_idx); - spin_unlock(&adapter->nfc_lock); + spin_unlock(&adapter->nfc_rule_lock); return 0; err_out_w_lock: - spin_unlock(&adapter->nfc_lock); + spin_unlock(&adapter->nfc_rule_lock); err_out: - kfree(input); + kfree(rule); return err; } -static int igc_del_ethtool_nfc_entry(struct igc_adapter *adapter, - struct ethtool_rxnfc *cmd) +static int igc_ethtool_del_nfc_rule(struct igc_adapter *adapter, + struct ethtool_rxnfc *cmd) { struct ethtool_rx_flow_spec *fsp = (struct ethtool_rx_flow_spec *)&cmd->fs; int err; - spin_lock(&adapter->nfc_lock); - err = igc_update_ethtool_nfc_entry(adapter, NULL, fsp->location); - spin_unlock(&adapter->nfc_lock); + spin_lock(&adapter->nfc_rule_lock); + err = igc_ethtool_update_nfc_rule(adapter, NULL, fsp->location); + spin_unlock(&adapter->nfc_rule_lock); return err; } -static int igc_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) +static int igc_ethtool_set_rxnfc(struct net_device *dev, + struct ethtool_rxnfc *cmd) { struct igc_adapter *adapter = netdev_priv(dev); - int ret = -EOPNOTSUPP; switch (cmd->cmd) { case ETHTOOL_SRXFH: - ret = igc_set_rss_hash_opt(adapter, cmd); - break; + return igc_ethtool_set_rss_hash_opt(adapter, cmd); case ETHTOOL_SRXCLSRLINS: - ret = igc_add_ethtool_nfc_entry(adapter, cmd); - break; + return igc_ethtool_add_nfc_rule(adapter, cmd); case ETHTOOL_SRXCLSRLDEL: - ret = igc_del_ethtool_nfc_entry(adapter, cmd); + return igc_ethtool_del_nfc_rule(adapter, cmd); default: - break; + return -EOPNOTSUPP; } - - return ret; } void igc_write_rss_indir_tbl(struct igc_adapter *adapter) @@ -1456,13 +1442,13 @@ void igc_write_rss_indir_tbl(struct igc_adapter *adapter) } } -static u32 igc_get_rxfh_indir_size(struct net_device *netdev) +static u32 igc_ethtool_get_rxfh_indir_size(struct net_device *netdev) { return IGC_RETA_SIZE; } -static int igc_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, - u8 *hfunc) +static int igc_ethtool_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, + u8 *hfunc) { struct igc_adapter *adapter = netdev_priv(netdev); int i; @@ -1477,8 +1463,8 @@ static int igc_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, return 0; } -static int igc_set_rxfh(struct net_device *netdev, const u32 *indir, - const u8 *key, const u8 hfunc) +static int igc_ethtool_set_rxfh(struct net_device *netdev, const u32 *indir, + const u8 *key, const u8 hfunc) { struct igc_adapter *adapter = netdev_priv(netdev); u32 num_queues; @@ -1506,18 +1492,13 @@ static int igc_set_rxfh(struct net_device *netdev, const u32 *indir, return 0; } -static unsigned int igc_max_channels(struct igc_adapter *adapter) -{ - return igc_get_max_rss_queues(adapter); -} - -static void igc_get_channels(struct net_device *netdev, - struct ethtool_channels *ch) +static void igc_ethtool_get_channels(struct net_device *netdev, + struct ethtool_channels *ch) { struct igc_adapter *adapter = netdev_priv(netdev); /* Report maximum channels */ - ch->max_combined = igc_max_channels(adapter); + ch->max_combined = igc_get_max_rss_queues(adapter); /* Report info for other vector */ if (adapter->flags & IGC_FLAG_HAS_MSIX) { @@ -1528,8 +1509,8 @@ static void igc_get_channels(struct net_device *netdev, ch->combined_count = adapter->rss_queues; } -static int igc_set_channels(struct net_device *netdev, - struct ethtool_channels *ch) +static int igc_ethtool_set_channels(struct net_device *netdev, + struct ethtool_channels *ch) { struct igc_adapter *adapter = netdev_priv(netdev); unsigned int count = ch->combined_count; @@ -1544,7 +1525,7 @@ static int igc_set_channels(struct net_device *netdev, return -EINVAL; /* Verify the number of channels doesn't exceed hw limits */ - max_combined = igc_max_channels(adapter); + max_combined = igc_get_max_rss_queues(adapter); if (count > max_combined) return -EINVAL; @@ -1561,8 +1542,8 @@ static int igc_set_channels(struct net_device *netdev, return 0; } -static int igc_get_ts_info(struct net_device *dev, - struct ethtool_ts_info *info) +static int igc_ethtool_get_ts_info(struct net_device *dev, + struct ethtool_ts_info *info) { struct igc_adapter *adapter = netdev_priv(dev); @@ -1594,7 +1575,7 @@ static int igc_get_ts_info(struct net_device *dev, } } -static u32 igc_get_priv_flags(struct net_device *netdev) +static u32 igc_ethtool_get_priv_flags(struct net_device *netdev) { struct igc_adapter *adapter = netdev_priv(netdev); u32 priv_flags = 0; @@ -1605,7 +1586,7 @@ static u32 igc_get_priv_flags(struct net_device *netdev) return priv_flags; } -static int igc_set_priv_flags(struct net_device *netdev, u32 priv_flags) +static int igc_ethtool_set_priv_flags(struct net_device *netdev, u32 priv_flags) { struct igc_adapter *adapter = netdev_priv(netdev); unsigned int flags = adapter->flags; @@ -1640,8 +1621,8 @@ static void igc_ethtool_complete(struct net_device *netdev) pm_runtime_put(&adapter->pdev->dev); } -static int igc_get_link_ksettings(struct net_device *netdev, - struct ethtool_link_ksettings *cmd) +static int igc_ethtool_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) { struct igc_adapter *adapter = netdev_priv(netdev); struct igc_hw *hw = &adapter->hw; @@ -1747,8 +1728,9 @@ static int igc_get_link_ksettings(struct net_device *netdev, return 0; } -static int igc_set_link_ksettings(struct net_device *netdev, - const struct ethtool_link_ksettings *cmd) +static int +igc_ethtool_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) { struct igc_adapter *adapter = netdev_priv(netdev); struct net_device *dev = adapter->netdev; @@ -1814,8 +1796,8 @@ static int igc_set_link_ksettings(struct net_device *netdev, return 0; } -static void igc_diag_test(struct net_device *netdev, - struct ethtool_test *eth_test, u64 *data) +static void igc_ethtool_diag_test(struct net_device *netdev, + struct ethtool_test *eth_test, u64 *data) { struct igc_adapter *adapter = netdev_priv(netdev); bool if_running = netif_running(netdev); @@ -1874,45 +1856,45 @@ static void igc_diag_test(struct net_device *netdev, static const struct ethtool_ops igc_ethtool_ops = { .supported_coalesce_params = ETHTOOL_COALESCE_USECS, - .get_drvinfo = igc_get_drvinfo, - .get_regs_len = igc_get_regs_len, - .get_regs = igc_get_regs, - .get_wol = igc_get_wol, - .set_wol = igc_set_wol, - .get_msglevel = igc_get_msglevel, - .set_msglevel = igc_set_msglevel, - .nway_reset = igc_nway_reset, - .get_link = igc_get_link, - .get_eeprom_len = igc_get_eeprom_len, - .get_eeprom = igc_get_eeprom, - .set_eeprom = igc_set_eeprom, - .get_ringparam = igc_get_ringparam, - .set_ringparam = igc_set_ringparam, - .get_pauseparam = igc_get_pauseparam, - .set_pauseparam = igc_set_pauseparam, - .get_strings = igc_get_strings, - .get_sset_count = igc_get_sset_count, - .get_ethtool_stats = igc_get_ethtool_stats, - .get_coalesce = igc_get_coalesce, - .set_coalesce = igc_set_coalesce, - .get_rxnfc = igc_get_rxnfc, - .set_rxnfc = igc_set_rxnfc, - .get_rxfh_indir_size = igc_get_rxfh_indir_size, - .get_rxfh = igc_get_rxfh, - .set_rxfh = igc_set_rxfh, - .get_ts_info = igc_get_ts_info, - .get_channels = igc_get_channels, - .set_channels = igc_set_channels, - .get_priv_flags = igc_get_priv_flags, - .set_priv_flags = igc_set_priv_flags, + .get_drvinfo = igc_ethtool_get_drvinfo, + .get_regs_len = igc_ethtool_get_regs_len, + .get_regs = igc_ethtool_get_regs, + .get_wol = igc_ethtool_get_wol, + .set_wol = igc_ethtool_set_wol, + .get_msglevel = igc_ethtool_get_msglevel, + .set_msglevel = igc_ethtool_set_msglevel, + .nway_reset = igc_ethtool_nway_reset, + .get_link = igc_ethtool_get_link, + .get_eeprom_len = igc_ethtool_get_eeprom_len, + .get_eeprom = igc_ethtool_get_eeprom, + .set_eeprom = igc_ethtool_set_eeprom, + .get_ringparam = igc_ethtool_get_ringparam, + .set_ringparam = igc_ethtool_set_ringparam, + .get_pauseparam = igc_ethtool_get_pauseparam, + .set_pauseparam = igc_ethtool_set_pauseparam, + .get_strings = igc_ethtool_get_strings, + .get_sset_count = igc_ethtool_get_sset_count, + .get_ethtool_stats = igc_ethtool_get_stats, + .get_coalesce = igc_ethtool_get_coalesce, + .set_coalesce = igc_ethtool_set_coalesce, + .get_rxnfc = igc_ethtool_get_rxnfc, + .set_rxnfc = igc_ethtool_set_rxnfc, + .get_rxfh_indir_size = igc_ethtool_get_rxfh_indir_size, + .get_rxfh = igc_ethtool_get_rxfh, + .set_rxfh = igc_ethtool_set_rxfh, + .get_ts_info = igc_ethtool_get_ts_info, + .get_channels = igc_ethtool_get_channels, + .set_channels = igc_ethtool_set_channels, + .get_priv_flags = igc_ethtool_get_priv_flags, + .set_priv_flags = igc_ethtool_set_priv_flags, .begin = igc_ethtool_begin, .complete = igc_ethtool_complete, - .get_link_ksettings = igc_get_link_ksettings, - .set_link_ksettings = igc_set_link_ksettings, - .self_test = igc_diag_test, + .get_link_ksettings = igc_ethtool_get_link_ksettings, + .set_link_ksettings = igc_ethtool_set_link_ksettings, + .self_test = igc_ethtool_diag_test, }; -void igc_set_ethtool_ops(struct net_device *netdev) +void igc_ethtool_set_ops(struct net_device *netdev) { netdev->ethtool_ops = &igc_ethtool_ops; } diff --git a/drivers/net/ethernet/intel/igc/igc_mac.c b/drivers/net/ethernet/intel/igc/igc_mac.c index 12aa6b5fcb5d..89445ab02a98 100644 --- a/drivers/net/ethernet/intel/igc/igc_mac.c +++ b/drivers/net/ethernet/intel/igc/igc_mac.c @@ -307,12 +307,8 @@ void igc_clear_hw_cntrs_base(struct igc_hw *hw) rd32(IGC_ICTXQMTC); rd32(IGC_ICRXDMTC); - rd32(IGC_CBTMPC); - rd32(IGC_HTDPMC); - rd32(IGC_CBRMPC); rd32(IGC_RPTHC); rd32(IGC_HGPTC); - rd32(IGC_HTCBDPC); rd32(IGC_HGORCL); rd32(IGC_HGORCH); rd32(IGC_HGOTCL); diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 0df5617eb9d0..f48d6127a220 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -766,12 +766,14 @@ static void igc_setup_tctl(struct igc_adapter *adapter) * igc_set_mac_filter_hw() - Set MAC address filter in hardware * @adapter: Pointer to adapter where the filter should be set * @index: Filter index - * @addr: Destination MAC address + * @type: MAC address filter type (source or destination) + * @addr: MAC address * @queue: If non-negative, queue assignment feature is enabled and frames * matching the filter are enqueued onto 'queue'. Otherwise, queue * assignment is disabled. */ static void igc_set_mac_filter_hw(struct igc_adapter *adapter, int index, + enum igc_mac_filter_type type, const u8 *addr, int queue) { struct net_device *dev = adapter->netdev; @@ -784,6 +786,11 @@ static void igc_set_mac_filter_hw(struct igc_adapter *adapter, int index, ral = le32_to_cpup((__le32 *)(addr)); rah = le16_to_cpup((__le16 *)(addr + 4)); + if (type == IGC_MAC_FILTER_TYPE_SRC) { + rah &= ~IGC_RAH_ASEL_MASK; + rah |= IGC_RAH_ASEL_SRC_ADDR; + } + if (queue >= 0) { rah &= ~IGC_RAH_QSEL_MASK; rah |= (queue << IGC_RAH_QSEL_SHIFT); @@ -820,17 +827,12 @@ static void igc_clear_mac_filter_hw(struct igc_adapter *adapter, int index) /* Set default MAC address for the PF in the first RAR entry */ static void igc_set_default_mac_filter(struct igc_adapter *adapter) { - struct igc_mac_addr *mac_table = &adapter->mac_table[0]; struct net_device *dev = adapter->netdev; u8 *addr = adapter->hw.mac.addr; netdev_dbg(dev, "Set default MAC address filter: address %pM", addr); - ether_addr_copy(mac_table->addr, addr); - mac_table->state = IGC_MAC_STATE_DEFAULT | IGC_MAC_STATE_IN_USE; - mac_table->queue = -1; - - igc_set_mac_filter_hw(adapter, 0, addr, mac_table->queue); + igc_set_mac_filter_hw(adapter, 0, IGC_MAC_FILTER_TYPE_DST, addr, -1); } /** @@ -2172,34 +2174,38 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget) return !!budget; } -static void igc_nfc_filter_restore(struct igc_adapter *adapter) +static void igc_restore_nfc_rules(struct igc_adapter *adapter) { - struct igc_nfc_filter *rule; + struct igc_nfc_rule *rule; - spin_lock(&adapter->nfc_lock); + spin_lock(&adapter->nfc_rule_lock); - hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) - igc_add_filter(adapter, rule); + hlist_for_each_entry(rule, &adapter->nfc_rule_list, nfc_node) + igc_enable_nfc_rule(adapter, rule); - spin_unlock(&adapter->nfc_lock); + spin_unlock(&adapter->nfc_rule_lock); } -static int igc_find_mac_filter(struct igc_adapter *adapter, const u8 *addr, - u8 flags) +static int igc_find_mac_filter(struct igc_adapter *adapter, + enum igc_mac_filter_type type, const u8 *addr) { - int max_entries = adapter->hw.mac.rar_entry_count; - struct igc_mac_addr *entry; + struct igc_hw *hw = &adapter->hw; + int max_entries = hw->mac.rar_entry_count; + u32 ral, rah; int i; for (i = 0; i < max_entries; i++) { - entry = &adapter->mac_table[i]; + ral = rd32(IGC_RAL(i)); + rah = rd32(IGC_RAH(i)); - if (!(entry->state & IGC_MAC_STATE_IN_USE)) + if (!(rah & IGC_RAH_AV)) continue; - if (!ether_addr_equal(addr, entry->addr)) + if (!!(rah & IGC_RAH_ASEL_SRC_ADDR) != type) continue; - if ((entry->state & IGC_MAC_STATE_SRC_ADDR) != - (flags & IGC_MAC_STATE_SRC_ADDR)) + if ((rah & IGC_RAH_RAH_MASK) != + le16_to_cpup((__le16 *)(addr + 4))) + continue; + if (ral != le32_to_cpup((__le32 *)(addr))) continue; return i; @@ -2210,14 +2216,15 @@ static int igc_find_mac_filter(struct igc_adapter *adapter, const u8 *addr, static int igc_get_avail_mac_filter_slot(struct igc_adapter *adapter) { - int max_entries = adapter->hw.mac.rar_entry_count; - struct igc_mac_addr *entry; + struct igc_hw *hw = &adapter->hw; + int max_entries = hw->mac.rar_entry_count; + u32 rah; int i; for (i = 0; i < max_entries; i++) { - entry = &adapter->mac_table[i]; + rah = rd32(IGC_RAH(i)); - if (!(entry->state & IGC_MAC_STATE_IN_USE)) + if (!(rah & IGC_RAH_AV)) return i; } @@ -2227,87 +2234,76 @@ static int igc_get_avail_mac_filter_slot(struct igc_adapter *adapter) /** * igc_add_mac_filter() - Add MAC address filter * @adapter: Pointer to adapter where the filter should be added + * @type: MAC address filter type (source or destination) * @addr: MAC address * @queue: If non-negative, queue assignment feature is enabled and frames * matching the filter are enqueued onto 'queue'. Otherwise, queue * assignment is disabled. - * @flags: Set IGC_MAC_STATE_SRC_ADDR bit to indicate @address is a source - * address * * Return: 0 in case of success, negative errno code otherwise. */ -int igc_add_mac_filter(struct igc_adapter *adapter, const u8 *addr, - const s8 queue, const u8 flags) +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; if (!is_valid_ether_addr(addr)) return -EINVAL; - if (flags & IGC_MAC_STATE_SRC_ADDR) - return -ENOTSUPP; - index = igc_find_mac_filter(adapter, addr, flags); + index = igc_find_mac_filter(adapter, type, addr); if (index >= 0) - goto update_queue_assignment; + goto update_filter; index = igc_get_avail_mac_filter_slot(adapter); if (index < 0) return -ENOSPC; - netdev_dbg(dev, "Add MAC address filter: index %d address %pM queue %d", - index, addr, queue); + netdev_dbg(dev, "Add MAC address filter: index %d type %s address %pM queue %d\n", + index, type == IGC_MAC_FILTER_TYPE_DST ? "dst" : "src", + addr, queue); - ether_addr_copy(adapter->mac_table[index].addr, addr); - adapter->mac_table[index].state |= IGC_MAC_STATE_IN_USE | flags; -update_queue_assignment: - adapter->mac_table[index].queue = queue; - - igc_set_mac_filter_hw(adapter, index, addr, queue); +update_filter: + igc_set_mac_filter_hw(adapter, index, type, addr, queue); return 0; } /** * igc_del_mac_filter() - Delete MAC address filter * @adapter: Pointer to adapter where the filter should be deleted from + * @type: MAC address filter type (source or destination) * @addr: MAC address - * @flags: Set IGC_MAC_STATE_SRC_ADDR bit to indicate @address is a source - * address * * Return: 0 in case of success, negative errno code otherwise. */ -int igc_del_mac_filter(struct igc_adapter *adapter, const u8 *addr, - const u8 flags) +int igc_del_mac_filter(struct igc_adapter *adapter, + enum igc_mac_filter_type type, const u8 *addr) { struct net_device *dev = adapter->netdev; - struct igc_mac_addr *entry; int index; if (!is_valid_ether_addr(addr)) return -EINVAL; - index = igc_find_mac_filter(adapter, addr, flags); + index = igc_find_mac_filter(adapter, type, addr); if (index < 0) return -ENOENT; - entry = &adapter->mac_table[index]; - - if (entry->state & IGC_MAC_STATE_DEFAULT) { + if (index == 0) { /* If this is the default filter, we don't actually delete it. * We just reset to its default value i.e. disable queue * assignment. */ netdev_dbg(dev, "Disable default MAC filter queue assignment"); - entry->queue = -1; - igc_set_mac_filter_hw(adapter, 0, addr, entry->queue); + igc_set_mac_filter_hw(adapter, 0, type, addr, -1); } else { - netdev_dbg(dev, "Delete MAC address filter: index %d address %pM", - index, addr); + netdev_dbg(dev, "Delete MAC address filter: index %d type %s address %pM\n", + index, + type == IGC_MAC_FILTER_TYPE_DST ? "dst" : "src", + addr); - entry->state = 0; - entry->queue = -1; - memset(entry->addr, 0, ETH_ALEN); igc_clear_mac_filter_hw(adapter, index); } @@ -2463,14 +2459,14 @@ static int igc_uc_sync(struct net_device *netdev, const unsigned char *addr) { struct igc_adapter *adapter = netdev_priv(netdev); - return igc_add_mac_filter(adapter, addr, -1, 0); + return igc_add_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, addr, -1); } static int igc_uc_unsync(struct net_device *netdev, const unsigned char *addr) { struct igc_adapter *adapter = netdev_priv(netdev); - return igc_del_mac_filter(adapter, addr, 0); + return igc_del_mac_filter(adapter, IGC_MAC_FILTER_TYPE_DST, addr); } /** @@ -2541,7 +2537,7 @@ static void igc_configure(struct igc_adapter *adapter) igc_setup_rctl(adapter); igc_set_default_mac_filter(adapter); - igc_nfc_filter_restore(adapter); + igc_restore_nfc_rules(adapter); igc_configure_tx(adapter); igc_configure_rx(adapter); @@ -2735,12 +2731,7 @@ void igc_set_flag_queue_pairs(struct igc_adapter *adapter, unsigned int igc_get_max_rss_queues(struct igc_adapter *adapter) { - unsigned int max_rss_queues; - - /* Determine the maximum number of RSS queues supported. */ - max_rss_queues = IGC_MAX_RX_QUEUES; - - return max_rss_queues; + return IGC_MAX_RX_QUEUES; } static void igc_init_queue_configuration(struct igc_adapter *adapter) @@ -3415,8 +3406,6 @@ static int igc_sw_init(struct igc_adapter *adapter) struct pci_dev *pdev = adapter->pdev; struct igc_hw *hw = &adapter->hw; - int size = sizeof(struct igc_mac_addr) * hw->mac.rar_entry_count; - pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); /* set default ring sizes */ @@ -3435,15 +3424,11 @@ static int igc_sw_init(struct igc_adapter *adapter) VLAN_HLEN; adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; - spin_lock_init(&adapter->nfc_lock); + spin_lock_init(&adapter->nfc_rule_lock); spin_lock_init(&adapter->stats64_lock); /* Assume MSI-X interrupts, will be checked during IRQ allocation */ adapter->flags |= IGC_FLAG_HAS_MSIX; - adapter->mac_table = kzalloc(size, GFP_ATOMIC); - if (!adapter->mac_table) - return -ENOMEM; - igc_init_queue_configuration(adapter); /* This call may decrease the number of queues */ @@ -3666,16 +3651,16 @@ void igc_update_stats(struct igc_adapter *adapter) adapter->stats.mgpdc += rd32(IGC_MGTPDC); } -static void igc_nfc_filter_exit(struct igc_adapter *adapter) +static void igc_nfc_rule_exit(struct igc_adapter *adapter) { - struct igc_nfc_filter *rule; + struct igc_nfc_rule *rule; - spin_lock(&adapter->nfc_lock); + spin_lock(&adapter->nfc_rule_lock); - hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node) - igc_erase_filter(adapter, rule); + hlist_for_each_entry(rule, &adapter->nfc_rule_list, nfc_node) + igc_disable_nfc_rule(adapter, rule); - spin_unlock(&adapter->nfc_lock); + spin_unlock(&adapter->nfc_rule_lock); } /** @@ -3696,7 +3681,7 @@ void igc_down(struct igc_adapter *adapter) wr32(IGC_RCTL, rctl & ~IGC_RCTL_EN); /* flush and sleep below */ - igc_nfc_filter_exit(adapter); + igc_nfc_rule_exit(adapter); /* set trans_start so we don't get spurious watchdogs during reset */ netif_trans_update(netdev); @@ -3848,17 +3833,17 @@ static int igc_set_features(struct net_device *netdev, if (!(features & NETIF_F_NTUPLE)) { struct hlist_node *node2; - struct igc_nfc_filter *rule; + struct igc_nfc_rule *rule; - spin_lock(&adapter->nfc_lock); + spin_lock(&adapter->nfc_rule_lock); hlist_for_each_entry_safe(rule, node2, - &adapter->nfc_filter_list, nfc_node) { - igc_erase_filter(adapter, rule); + &adapter->nfc_rule_list, nfc_node) { + igc_disable_nfc_rule(adapter, rule); hlist_del(&rule->nfc_node); kfree(rule); } - spin_unlock(&adapter->nfc_lock); - adapter->nfc_filter_count = 0; + spin_unlock(&adapter->nfc_rule_lock); + adapter->nfc_rule_count = 0; } netdev->features = features; @@ -4947,7 +4932,7 @@ static int igc_probe(struct pci_dev *pdev, hw->hw_addr = adapter->io_addr; netdev->netdev_ops = &igc_netdev_ops; - igc_set_ethtool_ops(netdev); + igc_ethtool_set_ops(netdev); netdev->watchdog_timeo = 5 * HZ; netdev->mem_start = pci_resource_start(pdev, 0); @@ -5146,7 +5131,6 @@ static void igc_remove(struct pci_dev *pdev) pci_iounmap(pdev, adapter->io_addr); pci_release_mem_regions(pdev); - kfree(adapter->mac_table); free_netdev(netdev); pci_disable_pcie_error_reporting(pdev); diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h index 61db951f0947..7f999cfc9b39 100644 --- a/drivers/net/ethernet/intel/igc/igc_regs.h +++ b/drivers/net/ethernet/intel/igc/igc_regs.h @@ -68,13 +68,6 @@ #define IGC_ICRXDMTC 0x04120 /* Rx Descriptor Min Threshold Count */ #define IGC_ICRXOC 0x04124 /* Receiver Overrun Count */ -#define IGC_CBTMPC 0x0402C /* Circuit Breaker TX Packet Count */ -#define IGC_HTDPMC 0x0403C /* Host Transmit Discarded Packets */ -#define IGC_CBRMPC 0x040FC /* Circuit Breaker RX Packet Count */ -#define IGC_RPTHC 0x04104 /* Rx Packets To Host */ -#define IGC_HGPTC 0x04118 /* Host Good Packets TX Count */ -#define IGC_HTCBDPC 0x04124 /* Host TX Circ.Breaker Drop Count */ - /* MSI-X Table Register Descriptions */ #define IGC_PBACL 0x05B68 /* MSIx PBA Clear - R/W 1 to clear */ @@ -131,9 +124,6 @@ #define IGC_MMDAC 13 /* MMD Access Control */ #define IGC_MMDAAD 14 /* MMD Access Address/Data */ -/* Good transmitted packets counter registers */ -#define IGC_PQGPTC(_n) (0x010014 + (0x100 * (_n))) - /* Statistics Register Descriptions */ #define IGC_CRCERRS 0x04000 /* CRC Error Count - R/clr */ #define IGC_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ @@ -206,7 +196,6 @@ #define IGC_HGOTCL 0x04130 /* Host Good Octets Transmit Count Low */ #define IGC_HGOTCH 0x04134 /* Host Good Octets Transmit Count High */ #define IGC_LENERRS 0x04138 /* Length Errors Count */ -#define IGC_HRMPC 0x0A018 /* Header Redirection Missed Packet Count */ /* Time sync registers */ #define IGC_TSICR 0x0B66C /* Time Sync Interrupt Cause */ |