Commit 6245c848 authored by Sasha Neftin's avatar Sasha Neftin Committed by Jeff Kirsher

igc: Extend the ethtool supporting

Add show and configure network flow classification (NFC) methods
to the ethtool. Show the specifies Rx ntuple filters.
Configures receive network flow classification option or rules.
Signed-off-by: default avatarSasha Neftin <sasha.neftin@intel.com>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 2121c271
......@@ -33,6 +33,10 @@ 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_steering_filter(struct igc_adapter *adapter,
const u8 *addr, u8 queue, u8 flags);
int igc_del_mac_steering_filter(struct igc_adapter *adapter,
const u8 *addr, u8 queue, u8 flags);
extern char igc_driver_name[];
extern char igc_driver_version[];
......@@ -292,15 +296,50 @@ struct igc_q_vector {
struct igc_ring ring[0] ____cacheline_internodealigned_in_smp;
};
#define MAX_ETYPE_FILTER (4 - 1)
enum igc_filter_match_flags {
IGC_FILTER_FLAG_ETHER_TYPE = 0x1,
IGC_FILTER_FLAG_VLAN_TCI = 0x2,
IGC_FILTER_FLAG_SRC_MAC_ADDR = 0x4,
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
*/
u8 match_flags;
__be16 etype;
__be16 vlan_tci;
u8 src_addr[ETH_ALEN];
u8 dst_addr[ETH_ALEN];
};
struct igc_nfc_filter {
struct hlist_node nfc_node;
struct igc_nfc_input filter;
unsigned long cookie;
u16 etype_reg_index;
u16 sw_idx;
u16 action;
};
struct igc_mac_addr {
u8 addr[ETH_ALEN];
u8 queue;
u8 state; /* bitmask */
};
#define IGC_MAC_STATE_DEFAULT 0x1
#define IGC_MAC_STATE_MODIFIED 0x2
#define IGC_MAC_STATE_IN_USE 0x4
#define IGC_MAC_STATE_DEFAULT 0x1
#define IGC_MAC_STATE_IN_USE 0x2
#define IGC_MAC_STATE_SRC_ADDR 0x4
#define IGC_MAC_STATE_QUEUE_STEERING 0x8
#define IGC_MAX_RXNFC_FILTERS 16
/* Board specific private data structure */
struct igc_adapter {
......@@ -369,8 +408,14 @@ struct igc_adapter {
u32 rss_queues;
u32 rss_indir_tbl_init;
/* RX network flow classification support */
struct hlist_head nfc_filter_list;
struct hlist_head cls_flower_list;
unsigned int nfc_filter_count;
/* lock for RX network flow classification filter */
spinlock_t nfc_lock;
bool etype_bitmap[MAX_ETYPE_FILTER];
struct igc_mac_addr *mac_table;
......@@ -456,6 +501,10 @@ static inline s32 igc_read_phy_reg(struct igc_hw *hw, u32 offset, u16 *data)
/* 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);
#define igc_rx_pg_size(_ring) (PAGE_SIZE << igc_rx_pg_order(_ring))
......
......@@ -400,4 +400,8 @@
#define IGC_N0_QUEUE -1
#define IGC_VLAPQF_QUEUE_SEL(_n, q_idx) ((q_idx) << ((_n) * 4))
#define IGC_VLAPQF_P_VALID(_n) (0x1 << (3 + (_n) * 4))
#define IGC_VLAPQF_QUEUE_MASK 0x03
#endif /* _IGC_DEFINES_H_ */
......@@ -1793,6 +1793,29 @@ static void igc_update_stats(struct igc_adapter *adapter)
static void igc_nfc_filter_exit(struct igc_adapter *adapter)
{
struct igc_nfc_filter *rule;
spin_lock(&adapter->nfc_lock);
hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node)
igc_erase_filter(adapter, rule);
hlist_for_each_entry(rule, &adapter->cls_flower_list, nfc_node)
igc_erase_filter(adapter, rule);
spin_unlock(&adapter->nfc_lock);
}
static void igc_nfc_filter_restore(struct igc_adapter *adapter)
{
struct igc_nfc_filter *rule;
spin_lock(&adapter->nfc_lock);
hlist_for_each_entry(rule, &adapter->nfc_filter_list, nfc_node)
igc_add_filter(adapter, rule);
spin_unlock(&adapter->nfc_lock);
}
/**
......@@ -1955,6 +1978,7 @@ static void igc_configure(struct igc_adapter *adapter)
igc_setup_mrqc(adapter);
igc_setup_rctl(adapter);
igc_nfc_filter_restore(adapter);
igc_configure_tx(adapter);
igc_configure_rx(adapter);
......@@ -2016,6 +2040,127 @@ static void igc_set_default_mac_filter(struct igc_adapter *adapter)
igc_rar_set_index(adapter, 0);
}
/* If the filter to be added and an already existing filter express
* the same address and address type, it should be possible to only
* override the other configurations, for example the queue to steer
* traffic.
*/
static bool igc_mac_entry_can_be_used(const struct igc_mac_addr *entry,
const u8 *addr, const u8 flags)
{
if (!(entry->state & IGC_MAC_STATE_IN_USE))
return true;
if ((entry->state & IGC_MAC_STATE_SRC_ADDR) !=
(flags & IGC_MAC_STATE_SRC_ADDR))
return false;
if (!ether_addr_equal(addr, entry->addr))
return false;
return true;
}
/* Add a MAC filter for 'addr' directing matching traffic to 'queue',
* 'flags' is used to indicate what kind of match is made, match is by
* default for the destination address, if matching by source address
* is desired the flag IGC_MAC_STATE_SRC_ADDR can be used.
*/
static int igc_add_mac_filter_flags(struct igc_adapter *adapter,
const u8 *addr, const u8 queue,
const u8 flags)
{
struct igc_hw *hw = &adapter->hw;
int rar_entries = hw->mac.rar_entry_count;
int i;
if (is_zero_ether_addr(addr))
return -EINVAL;
/* Search for the first empty entry in the MAC table.
* Do not touch entries at the end of the table reserved for the VF MAC
* addresses.
*/
for (i = 0; i < rar_entries; i++) {
if (!igc_mac_entry_can_be_used(&adapter->mac_table[i],
addr, flags))
continue;
ether_addr_copy(adapter->mac_table[i].addr, addr);
adapter->mac_table[i].queue = queue;
adapter->mac_table[i].state |= IGC_MAC_STATE_IN_USE | flags;
igc_rar_set_index(adapter, i);
return i;
}
return -ENOSPC;
}
int igc_add_mac_steering_filter(struct igc_adapter *adapter,
const u8 *addr, u8 queue, u8 flags)
{
return igc_add_mac_filter_flags(adapter, addr, queue,
IGC_MAC_STATE_QUEUE_STEERING | flags);
}
/* Remove a MAC filter for 'addr' directing matching traffic to
* 'queue', 'flags' is used to indicate what kind of match need to be
* removed, match is by default for the destination address, if
* matching by source address is to be removed the flag
* IGC_MAC_STATE_SRC_ADDR can be used.
*/
static int igc_del_mac_filter_flags(struct igc_adapter *adapter,
const u8 *addr, const u8 queue,
const u8 flags)
{
struct igc_hw *hw = &adapter->hw;
int rar_entries = hw->mac.rar_entry_count;
int i;
if (is_zero_ether_addr(addr))
return -EINVAL;
/* Search for matching entry in the MAC table based on given address
* and queue. Do not touch entries at the end of the table reserved
* for the VF MAC addresses.
*/
for (i = 0; i < rar_entries; i++) {
if (!(adapter->mac_table[i].state & IGC_MAC_STATE_IN_USE))
continue;
if ((adapter->mac_table[i].state & flags) != flags)
continue;
if (adapter->mac_table[i].queue != queue)
continue;
if (!ether_addr_equal(adapter->mac_table[i].addr, addr))
continue;
/* When a filter for the default address is "deleted",
* we return it to its initial configuration
*/
if (adapter->mac_table[i].state & IGC_MAC_STATE_DEFAULT) {
adapter->mac_table[i].state =
IGC_MAC_STATE_DEFAULT | IGC_MAC_STATE_IN_USE;
} else {
adapter->mac_table[i].state = 0;
adapter->mac_table[i].queue = 0;
memset(adapter->mac_table[i].addr, 0, ETH_ALEN);
}
igc_rar_set_index(adapter, i);
return 0;
}
return -ENOENT;
}
int igc_del_mac_steering_filter(struct igc_adapter *adapter,
const u8 *addr, u8 queue, u8 flags)
{
return igc_del_mac_filter_flags(adapter, addr, queue,
IGC_MAC_STATE_QUEUE_STEERING | flags);
}
/**
* igc_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set
* @netdev: network interface device structure
......
......@@ -83,6 +83,16 @@
/* RSS registers */
#define IGC_MRQC 0x05818 /* Multiple Receive Control - RW */
/* Filtering Registers */
#define IGC_ETQF(_n) (0x05CB0 + (4 * (_n))) /* EType Queue Fltr */
/* ETQF register bit definitions */
#define IGC_ETQF_FILTER_ENABLE BIT(26)
#define IGC_ETQF_QUEUE_ENABLE BIT(31)
#define IGC_ETQF_QUEUE_SHIFT 16
#define IGC_ETQF_QUEUE_MASK 0x00070000
#define IGC_ETQF_ETYPE_MASK 0x0000FFFF
/* Redirection Table - RW Array */
#define IGC_RETA(_i) (0x05C00 + ((_i) * 4))
/* RSS Random Key - RW Array */
......@@ -106,6 +116,7 @@
#define IGC_UTA 0x0A000 /* Unicast Table Array - RW */
#define IGC_RAL(_n) (0x05400 + ((_n) * 0x08))
#define IGC_RAH(_n) (0x05404 + ((_n) * 0x08))
#define IGC_VLAPQF 0x055B0 /* VLAN Priority Queue Filter VLAPQF */
/* Transmit Register Descriptions */
#define IGC_TCTL 0x00400 /* Tx Control - RW */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment