Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/net-next

Jeff Kirsher says:

====================
Intel Wired LAN Driver Updates

This series contains updates to i40e and i40evf.

Most notable are:
Joseph completes the implementation of the ethtool ntuple rule
management interface by adding the get, update and delete interface
reset.

Akeem provides a fix to prevent a possible overflow due to multiplication
of number and size by using kzalloc, so use kcalloc.

Jesse provides an implementation for skb_set_hash() and adds the L4 type
return when we know it is an L4 hash.  He also adds a counter to
statistics for Tx timeouts to help users.  Lastly he provides a change
to stay away from the cache line where the done bit may be getting
written back for the transmit ring since the hardware may be writing the
whole cache line for a partial update.

Shannon cleans up code comments.

Anjali removes a firmware workaround for newer firmware since the number
of MSIx vectors are being reported correctly.

v2:
 -  dropped patch 01 of the series based on feedback from the author
    Joe Perches and Shannon Nelson.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2014-03-07 16:12:43 -05:00
commit 91bd66e4c8
14 changed files with 1441 additions and 364 deletions

View file

@ -86,12 +86,12 @@
#define I40E_NVM_VERSION_LO_SHIFT 0
#define I40E_NVM_VERSION_LO_MASK (0xff << I40E_NVM_VERSION_LO_SHIFT)
#define I40E_NVM_VERSION_HI_SHIFT 8
#define I40E_NVM_VERSION_HI_MASK (0xff << I40E_NVM_VERSION_HI_SHIFT)
#define I40E_NVM_VERSION_HI_SHIFT 12
#define I40E_NVM_VERSION_HI_MASK (0xf << I40E_NVM_VERSION_HI_SHIFT)
/* The values in here are decimal coded as hex as is the case in the NVM map*/
#define I40E_CURRENT_NVM_VERSION_HI 0x2
#define I40E_CURRENT_NVM_VERSION_LO 0x30
#define I40E_CURRENT_NVM_VERSION_LO 0x40
/* magic for getting defines into strings */
#define STRINGIFY(foo) #foo
@ -152,8 +152,18 @@ struct i40e_lump_tracking {
};
#define I40E_DEFAULT_ATR_SAMPLE_RATE 20
#define I40E_FDIR_MAX_RAW_PACKET_LOOKUP 512
struct i40e_fdir_data {
#define I40E_FDIR_MAX_RAW_PACKET_SIZE 512
struct i40e_fdir_filter {
struct hlist_node fdir_node;
/* filter ipnut set */
u8 flow_type;
u8 ip4_proto;
__be32 dst_ip[4];
__be32 src_ip[4];
__be16 src_port;
__be16 dst_port;
__be32 sctp_v_tag;
/* filter control */
u16 q_index;
u8 flex_off;
u8 pctype;
@ -162,7 +172,6 @@ struct i40e_fdir_data {
u8 fd_status;
u16 cnt_index;
u32 fd_id;
u8 *raw_packet;
};
#define I40E_ETH_P_LLDP 0x88cc
@ -210,6 +219,9 @@ struct i40e_pf {
u8 atr_sample_rate;
bool wol_en;
struct hlist_head fdir_filter_list;
u16 fdir_pf_active_filters;
#ifdef CONFIG_I40E_VXLAN
__be16 vxlan_ports[I40E_MAX_PF_UDP_OFFLOAD_PORTS];
u16 pending_vxlan_bitmap;
@ -477,10 +489,10 @@ static inline char *i40e_fw_version_str(struct i40e_hw *hw)
"f%d.%d a%d.%d n%02x.%02x e%08x",
hw->aq.fw_maj_ver, hw->aq.fw_min_ver,
hw->aq.api_maj_ver, hw->aq.api_min_ver,
(hw->nvm.version & I40E_NVM_VERSION_HI_MASK)
>> I40E_NVM_VERSION_HI_SHIFT,
(hw->nvm.version & I40E_NVM_VERSION_LO_MASK)
>> I40E_NVM_VERSION_LO_SHIFT,
(hw->nvm.version & I40E_NVM_VERSION_HI_MASK) >>
I40E_NVM_VERSION_HI_SHIFT,
(hw->nvm.version & I40E_NVM_VERSION_LO_MASK) >>
I40E_NVM_VERSION_LO_SHIFT,
hw->nvm.eetrack);
return buf;
@ -534,9 +546,10 @@ struct rtnl_link_stats64 *i40e_get_vsi_stats_struct(struct i40e_vsi *vsi);
int i40e_fetch_switch_configuration(struct i40e_pf *pf,
bool printconfig);
int i40e_program_fdir_filter(struct i40e_fdir_data *fdir_data,
int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
struct i40e_pf *pf, bool add);
int i40e_add_del_fdir(struct i40e_vsi *vsi,
struct i40e_fdir_filter *input, bool add);
void i40e_set_ethtool_ops(struct net_device *netdev);
struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
u8 *macaddr, s16 vlan,

View file

@ -162,6 +162,372 @@ i40e_status i40e_aq_queue_shutdown(struct i40e_hw *hw,
return status;
}
/* The i40e_ptype_lookup table is used to convert from the 8-bit ptype in the
* hardware to a bit-field that can be used by SW to more easily determine the
* packet type.
*
* Macros are used to shorten the table lines and make this table human
* readable.
*
* We store the PTYPE in the top byte of the bit field - this is just so that
* we can check that the table doesn't have a row missing, as the index into
* the table should be the PTYPE.
*
* Typical work flow:
*
* IF NOT i40e_ptype_lookup[ptype].known
* THEN
* Packet is unknown
* ELSE IF i40e_ptype_lookup[ptype].outer_ip == I40E_RX_PTYPE_OUTER_IP
* Use the rest of the fields to look at the tunnels, inner protocols, etc
* ELSE
* Use the enum i40e_rx_l2_ptype to decode the packet type
* ENDIF
*/
/* macro to make the table lines short */
#define I40E_PTT(PTYPE, OUTER_IP, OUTER_IP_VER, OUTER_FRAG, T, TE, TEF, I, PL)\
{ PTYPE, \
1, \
I40E_RX_PTYPE_OUTER_##OUTER_IP, \
I40E_RX_PTYPE_OUTER_##OUTER_IP_VER, \
I40E_RX_PTYPE_##OUTER_FRAG, \
I40E_RX_PTYPE_TUNNEL_##T, \
I40E_RX_PTYPE_TUNNEL_END_##TE, \
I40E_RX_PTYPE_##TEF, \
I40E_RX_PTYPE_INNER_PROT_##I, \
I40E_RX_PTYPE_PAYLOAD_LAYER_##PL }
#define I40E_PTT_UNUSED_ENTRY(PTYPE) \
{ PTYPE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
/* shorter macros makes the table fit but are terse */
#define I40E_RX_PTYPE_NOF I40E_RX_PTYPE_NOT_FRAG
#define I40E_RX_PTYPE_FRG I40E_RX_PTYPE_FRAG
#define I40E_RX_PTYPE_INNER_PROT_TS I40E_RX_PTYPE_INNER_PROT_TIMESYNC
/* Lookup table mapping the HW PTYPE to the bit field for decoding */
struct i40e_rx_ptype_decoded i40e_ptype_lookup[] = {
/* L2 Packet types */
I40E_PTT_UNUSED_ENTRY(0),
I40E_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
I40E_PTT(2, L2, NONE, NOF, NONE, NONE, NOF, TS, PAY2),
I40E_PTT(3, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
I40E_PTT_UNUSED_ENTRY(4),
I40E_PTT_UNUSED_ENTRY(5),
I40E_PTT(6, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
I40E_PTT(7, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
I40E_PTT_UNUSED_ENTRY(8),
I40E_PTT_UNUSED_ENTRY(9),
I40E_PTT(10, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
I40E_PTT(11, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE),
I40E_PTT(12, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(13, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(14, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(15, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(16, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(17, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(18, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(19, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(20, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(21, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
/* Non Tunneled IPv4 */
I40E_PTT(22, IP, IPV4, FRG, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(23, IP, IPV4, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(24, IP, IPV4, NOF, NONE, NONE, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(25),
I40E_PTT(26, IP, IPV4, NOF, NONE, NONE, NOF, TCP, PAY4),
I40E_PTT(27, IP, IPV4, NOF, NONE, NONE, NOF, SCTP, PAY4),
I40E_PTT(28, IP, IPV4, NOF, NONE, NONE, NOF, ICMP, PAY4),
/* IPv4 --> IPv4 */
I40E_PTT(29, IP, IPV4, NOF, IP_IP, IPV4, FRG, NONE, PAY3),
I40E_PTT(30, IP, IPV4, NOF, IP_IP, IPV4, NOF, NONE, PAY3),
I40E_PTT(31, IP, IPV4, NOF, IP_IP, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(32),
I40E_PTT(33, IP, IPV4, NOF, IP_IP, IPV4, NOF, TCP, PAY4),
I40E_PTT(34, IP, IPV4, NOF, IP_IP, IPV4, NOF, SCTP, PAY4),
I40E_PTT(35, IP, IPV4, NOF, IP_IP, IPV4, NOF, ICMP, PAY4),
/* IPv4 --> IPv6 */
I40E_PTT(36, IP, IPV4, NOF, IP_IP, IPV6, FRG, NONE, PAY3),
I40E_PTT(37, IP, IPV4, NOF, IP_IP, IPV6, NOF, NONE, PAY3),
I40E_PTT(38, IP, IPV4, NOF, IP_IP, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(39),
I40E_PTT(40, IP, IPV4, NOF, IP_IP, IPV6, NOF, TCP, PAY4),
I40E_PTT(41, IP, IPV4, NOF, IP_IP, IPV6, NOF, SCTP, PAY4),
I40E_PTT(42, IP, IPV4, NOF, IP_IP, IPV6, NOF, ICMP, PAY4),
/* IPv4 --> GRE/NAT */
I40E_PTT(43, IP, IPV4, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3),
/* IPv4 --> GRE/NAT --> IPv4 */
I40E_PTT(44, IP, IPV4, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3),
I40E_PTT(45, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3),
I40E_PTT(46, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(47),
I40E_PTT(48, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4),
I40E_PTT(49, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4),
I40E_PTT(50, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4),
/* IPv4 --> GRE/NAT --> IPv6 */
I40E_PTT(51, IP, IPV4, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3),
I40E_PTT(52, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3),
I40E_PTT(53, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(54),
I40E_PTT(55, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4),
I40E_PTT(56, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4),
I40E_PTT(57, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4),
/* IPv4 --> GRE/NAT --> MAC */
I40E_PTT(58, IP, IPV4, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3),
/* IPv4 --> GRE/NAT --> MAC --> IPv4 */
I40E_PTT(59, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3),
I40E_PTT(60, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3),
I40E_PTT(61, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(62),
I40E_PTT(63, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4),
I40E_PTT(64, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4),
I40E_PTT(65, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4),
/* IPv4 --> GRE/NAT -> MAC --> IPv6 */
I40E_PTT(66, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3),
I40E_PTT(67, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3),
I40E_PTT(68, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(69),
I40E_PTT(70, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4),
I40E_PTT(71, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4),
I40E_PTT(72, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4),
/* IPv4 --> GRE/NAT --> MAC/VLAN */
I40E_PTT(73, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3),
/* IPv4 ---> GRE/NAT -> MAC/VLAN --> IPv4 */
I40E_PTT(74, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3),
I40E_PTT(75, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3),
I40E_PTT(76, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(77),
I40E_PTT(78, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4),
I40E_PTT(79, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4),
I40E_PTT(80, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4),
/* IPv4 -> GRE/NAT -> MAC/VLAN --> IPv6 */
I40E_PTT(81, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3),
I40E_PTT(82, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3),
I40E_PTT(83, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(84),
I40E_PTT(85, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4),
I40E_PTT(86, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4),
I40E_PTT(87, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4),
/* Non Tunneled IPv6 */
I40E_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY3),
I40E_PTT_UNUSED_ENTRY(91),
I40E_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4),
I40E_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4),
I40E_PTT(94, IP, IPV6, NOF, NONE, NONE, NOF, ICMP, PAY4),
/* IPv6 --> IPv4 */
I40E_PTT(95, IP, IPV6, NOF, IP_IP, IPV4, FRG, NONE, PAY3),
I40E_PTT(96, IP, IPV6, NOF, IP_IP, IPV4, NOF, NONE, PAY3),
I40E_PTT(97, IP, IPV6, NOF, IP_IP, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(98),
I40E_PTT(99, IP, IPV6, NOF, IP_IP, IPV4, NOF, TCP, PAY4),
I40E_PTT(100, IP, IPV6, NOF, IP_IP, IPV4, NOF, SCTP, PAY4),
I40E_PTT(101, IP, IPV6, NOF, IP_IP, IPV4, NOF, ICMP, PAY4),
/* IPv6 --> IPv6 */
I40E_PTT(102, IP, IPV6, NOF, IP_IP, IPV6, FRG, NONE, PAY3),
I40E_PTT(103, IP, IPV6, NOF, IP_IP, IPV6, NOF, NONE, PAY3),
I40E_PTT(104, IP, IPV6, NOF, IP_IP, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(105),
I40E_PTT(106, IP, IPV6, NOF, IP_IP, IPV6, NOF, TCP, PAY4),
I40E_PTT(107, IP, IPV6, NOF, IP_IP, IPV6, NOF, SCTP, PAY4),
I40E_PTT(108, IP, IPV6, NOF, IP_IP, IPV6, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT */
I40E_PTT(109, IP, IPV6, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3),
/* IPv6 --> GRE/NAT -> IPv4 */
I40E_PTT(110, IP, IPV6, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3),
I40E_PTT(111, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3),
I40E_PTT(112, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(113),
I40E_PTT(114, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4),
I40E_PTT(115, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4),
I40E_PTT(116, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT -> IPv6 */
I40E_PTT(117, IP, IPV6, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3),
I40E_PTT(118, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3),
I40E_PTT(119, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(120),
I40E_PTT(121, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4),
I40E_PTT(122, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4),
I40E_PTT(123, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT -> MAC */
I40E_PTT(124, IP, IPV6, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3),
/* IPv6 --> GRE/NAT -> MAC -> IPv4 */
I40E_PTT(125, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3),
I40E_PTT(126, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3),
I40E_PTT(127, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(128),
I40E_PTT(129, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4),
I40E_PTT(130, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4),
I40E_PTT(131, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT -> MAC -> IPv6 */
I40E_PTT(132, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3),
I40E_PTT(133, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3),
I40E_PTT(134, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(135),
I40E_PTT(136, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4),
I40E_PTT(137, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4),
I40E_PTT(138, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT -> MAC/VLAN */
I40E_PTT(139, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3),
/* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv4 */
I40E_PTT(140, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3),
I40E_PTT(141, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3),
I40E_PTT(142, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(143),
I40E_PTT(144, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4),
I40E_PTT(145, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4),
I40E_PTT(146, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv6 */
I40E_PTT(147, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3),
I40E_PTT(148, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3),
I40E_PTT(149, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(150),
I40E_PTT(151, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4),
I40E_PTT(152, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4),
I40E_PTT(153, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4),
/* unused entries */
I40E_PTT_UNUSED_ENTRY(154),
I40E_PTT_UNUSED_ENTRY(155),
I40E_PTT_UNUSED_ENTRY(156),
I40E_PTT_UNUSED_ENTRY(157),
I40E_PTT_UNUSED_ENTRY(158),
I40E_PTT_UNUSED_ENTRY(159),
I40E_PTT_UNUSED_ENTRY(160),
I40E_PTT_UNUSED_ENTRY(161),
I40E_PTT_UNUSED_ENTRY(162),
I40E_PTT_UNUSED_ENTRY(163),
I40E_PTT_UNUSED_ENTRY(164),
I40E_PTT_UNUSED_ENTRY(165),
I40E_PTT_UNUSED_ENTRY(166),
I40E_PTT_UNUSED_ENTRY(167),
I40E_PTT_UNUSED_ENTRY(168),
I40E_PTT_UNUSED_ENTRY(169),
I40E_PTT_UNUSED_ENTRY(170),
I40E_PTT_UNUSED_ENTRY(171),
I40E_PTT_UNUSED_ENTRY(172),
I40E_PTT_UNUSED_ENTRY(173),
I40E_PTT_UNUSED_ENTRY(174),
I40E_PTT_UNUSED_ENTRY(175),
I40E_PTT_UNUSED_ENTRY(176),
I40E_PTT_UNUSED_ENTRY(177),
I40E_PTT_UNUSED_ENTRY(178),
I40E_PTT_UNUSED_ENTRY(179),
I40E_PTT_UNUSED_ENTRY(180),
I40E_PTT_UNUSED_ENTRY(181),
I40E_PTT_UNUSED_ENTRY(182),
I40E_PTT_UNUSED_ENTRY(183),
I40E_PTT_UNUSED_ENTRY(184),
I40E_PTT_UNUSED_ENTRY(185),
I40E_PTT_UNUSED_ENTRY(186),
I40E_PTT_UNUSED_ENTRY(187),
I40E_PTT_UNUSED_ENTRY(188),
I40E_PTT_UNUSED_ENTRY(189),
I40E_PTT_UNUSED_ENTRY(190),
I40E_PTT_UNUSED_ENTRY(191),
I40E_PTT_UNUSED_ENTRY(192),
I40E_PTT_UNUSED_ENTRY(193),
I40E_PTT_UNUSED_ENTRY(194),
I40E_PTT_UNUSED_ENTRY(195),
I40E_PTT_UNUSED_ENTRY(196),
I40E_PTT_UNUSED_ENTRY(197),
I40E_PTT_UNUSED_ENTRY(198),
I40E_PTT_UNUSED_ENTRY(199),
I40E_PTT_UNUSED_ENTRY(200),
I40E_PTT_UNUSED_ENTRY(201),
I40E_PTT_UNUSED_ENTRY(202),
I40E_PTT_UNUSED_ENTRY(203),
I40E_PTT_UNUSED_ENTRY(204),
I40E_PTT_UNUSED_ENTRY(205),
I40E_PTT_UNUSED_ENTRY(206),
I40E_PTT_UNUSED_ENTRY(207),
I40E_PTT_UNUSED_ENTRY(208),
I40E_PTT_UNUSED_ENTRY(209),
I40E_PTT_UNUSED_ENTRY(210),
I40E_PTT_UNUSED_ENTRY(211),
I40E_PTT_UNUSED_ENTRY(212),
I40E_PTT_UNUSED_ENTRY(213),
I40E_PTT_UNUSED_ENTRY(214),
I40E_PTT_UNUSED_ENTRY(215),
I40E_PTT_UNUSED_ENTRY(216),
I40E_PTT_UNUSED_ENTRY(217),
I40E_PTT_UNUSED_ENTRY(218),
I40E_PTT_UNUSED_ENTRY(219),
I40E_PTT_UNUSED_ENTRY(220),
I40E_PTT_UNUSED_ENTRY(221),
I40E_PTT_UNUSED_ENTRY(222),
I40E_PTT_UNUSED_ENTRY(223),
I40E_PTT_UNUSED_ENTRY(224),
I40E_PTT_UNUSED_ENTRY(225),
I40E_PTT_UNUSED_ENTRY(226),
I40E_PTT_UNUSED_ENTRY(227),
I40E_PTT_UNUSED_ENTRY(228),
I40E_PTT_UNUSED_ENTRY(229),
I40E_PTT_UNUSED_ENTRY(230),
I40E_PTT_UNUSED_ENTRY(231),
I40E_PTT_UNUSED_ENTRY(232),
I40E_PTT_UNUSED_ENTRY(233),
I40E_PTT_UNUSED_ENTRY(234),
I40E_PTT_UNUSED_ENTRY(235),
I40E_PTT_UNUSED_ENTRY(236),
I40E_PTT_UNUSED_ENTRY(237),
I40E_PTT_UNUSED_ENTRY(238),
I40E_PTT_UNUSED_ENTRY(239),
I40E_PTT_UNUSED_ENTRY(240),
I40E_PTT_UNUSED_ENTRY(241),
I40E_PTT_UNUSED_ENTRY(242),
I40E_PTT_UNUSED_ENTRY(243),
I40E_PTT_UNUSED_ENTRY(244),
I40E_PTT_UNUSED_ENTRY(245),
I40E_PTT_UNUSED_ENTRY(246),
I40E_PTT_UNUSED_ENTRY(247),
I40E_PTT_UNUSED_ENTRY(248),
I40E_PTT_UNUSED_ENTRY(249),
I40E_PTT_UNUSED_ENTRY(250),
I40E_PTT_UNUSED_ENTRY(251),
I40E_PTT_UNUSED_ENTRY(252),
I40E_PTT_UNUSED_ENTRY(253),
I40E_PTT_UNUSED_ENTRY(254),
I40E_PTT_UNUSED_ENTRY(255)
};
/**
* i40e_init_shared_code - Initialize the shared code
* @hw: pointer to hardware structure

View file

@ -332,6 +332,7 @@ i40e_status i40e_lldp_to_dcb_config(u8 *lldpmib,
u16 type;
u16 length;
u16 typelength;
u16 offset = 0;
if (!lldpmib || !dcbcfg)
return I40E_ERR_PARAM;
@ -339,15 +340,17 @@ i40e_status i40e_lldp_to_dcb_config(u8 *lldpmib,
/* set to the start of LLDPDU */
lldpmib += ETH_HLEN;
tlv = (struct i40e_lldp_org_tlv *)lldpmib;
while (tlv) {
while (1) {
typelength = ntohs(tlv->typelength);
type = (u16)((typelength & I40E_LLDP_TLV_TYPE_MASK) >>
I40E_LLDP_TLV_TYPE_SHIFT);
length = (u16)((typelength & I40E_LLDP_TLV_LEN_MASK) >>
I40E_LLDP_TLV_LEN_SHIFT);
offset += sizeof(typelength) + length;
if (type == I40E_TLV_TYPE_END)
break;/* END TLV break out */
/* END TLV or beyond LLDPDU size */
if ((type == I40E_TLV_TYPE_END) || (offset > I40E_LLDPDU_SIZE))
break;
switch (type) {
case I40E_TLV_TYPE_ORG:

View file

@ -1663,21 +1663,22 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
desc = NULL;
} else if ((strncmp(cmd_buf, "add fd_filter", 13) == 0) ||
(strncmp(cmd_buf, "rem fd_filter", 13) == 0)) {
struct i40e_fdir_data fd_data;
struct i40e_fdir_filter fd_data;
u16 packet_len, i, j = 0;
char *asc_packet;
u8 *raw_packet;
bool add = false;
int ret;
asc_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_LOOKUP,
asc_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE,
GFP_KERNEL);
if (!asc_packet)
goto command_write_done;
fd_data.raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_LOOKUP,
GFP_KERNEL);
raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE,
GFP_KERNEL);
if (!fd_data.raw_packet) {
if (!raw_packet) {
kfree(asc_packet);
asc_packet = NULL;
goto command_write_done;
@ -1698,36 +1699,36 @@ static ssize_t i40e_dbg_command_write(struct file *filp,
cnt);
kfree(asc_packet);
asc_packet = NULL;
kfree(fd_data.raw_packet);
kfree(raw_packet);
goto command_write_done;
}
/* fix packet length if user entered 0 */
if (packet_len == 0)
packet_len = I40E_FDIR_MAX_RAW_PACKET_LOOKUP;
packet_len = I40E_FDIR_MAX_RAW_PACKET_SIZE;
/* make sure to check the max as well */
packet_len = min_t(u16,
packet_len, I40E_FDIR_MAX_RAW_PACKET_LOOKUP);
packet_len, I40E_FDIR_MAX_RAW_PACKET_SIZE);
for (i = 0; i < packet_len; i++) {
sscanf(&asc_packet[j], "%2hhx ",
&fd_data.raw_packet[i]);
&raw_packet[i]);
j += 3;
}
dev_info(&pf->pdev->dev, "FD raw packet dump\n");
print_hex_dump(KERN_INFO, "FD raw packet: ",
DUMP_PREFIX_OFFSET, 16, 1,
fd_data.raw_packet, packet_len, true);
ret = i40e_program_fdir_filter(&fd_data, pf, add);
raw_packet, packet_len, true);
ret = i40e_program_fdir_filter(&fd_data, raw_packet, pf, add);
if (!ret) {
dev_info(&pf->pdev->dev, "Filter command send Status : Success\n");
} else {
dev_info(&pf->pdev->dev,
"Filter command send failed %d\n", ret);
}
kfree(fd_data.raw_packet);
fd_data.raw_packet = NULL;
kfree(raw_packet);
raw_packet = NULL;
kfree(asc_packet);
asc_packet = NULL;
} else if (strncmp(cmd_buf, "fd-atr off", 10) == 0) {

View file

@ -62,6 +62,9 @@ static const struct i40e_stats i40e_gstrings_net_stats[] = {
I40E_NETDEV_STAT(rx_crc_errors),
};
static int i40e_add_del_fdir_ethtool(struct i40e_vsi *vsi,
struct ethtool_rxnfc *cmd, bool add);
/* These PF_STATs might look like duplicates of some NETDEV_STATs,
* but they are separate. This device supports Virtualization, and
* as such might have several netdevs supporting VMDq and FCoE going
@ -84,6 +87,7 @@ static struct i40e_stats i40e_gstrings_stats[] = {
I40E_PF_STAT("illegal_bytes", stats.illegal_bytes),
I40E_PF_STAT("mac_local_faults", stats.mac_local_faults),
I40E_PF_STAT("mac_remote_faults", stats.mac_remote_faults),
I40E_PF_STAT("tx_timeout", tx_timeout_count),
I40E_PF_STAT("rx_length_errors", stats.rx_length_errors),
I40E_PF_STAT("link_xon_rx", stats.link_xon_rx),
I40E_PF_STAT("link_xoff_rx", stats.link_xoff_rx),
@ -1111,6 +1115,84 @@ static int i40e_get_rss_hash_opts(struct i40e_pf *pf, struct ethtool_rxnfc *cmd)
return 0;
}
/**
* i40e_get_ethtool_fdir_all - Populates the rule count of a command
* @pf: Pointer to the physical function struct
* @cmd: The command to get or set Rx flow classification rules
* @rule_locs: Array of used rule locations
*
* This function populates both the total and actual rule count of
* the ethtool flow classification command
*
* Returns 0 on success or -EMSGSIZE if entry not found
**/
static int i40e_get_ethtool_fdir_all(struct i40e_pf *pf,
struct ethtool_rxnfc *cmd,
u32 *rule_locs)
{
struct i40e_fdir_filter *rule;
struct hlist_node *node2;
int cnt = 0;
/* report total rule count */
cmd->data = pf->hw.fdir_shared_filter_count +
pf->fdir_pf_filter_count;
hlist_for_each_entry_safe(rule, node2,
&pf->fdir_filter_list, fdir_node) {
if (cnt == cmd->rule_cnt)
return -EMSGSIZE;
rule_locs[cnt] = rule->fd_id;
cnt++;
}
cmd->rule_cnt = cnt;
return 0;
}
/**
* i40e_get_ethtool_fdir_entry - Look up a filter based on Rx flow
* @pf: Pointer to the physical function struct
* @cmd: The command to get or set Rx flow classification rules
*
* This function looks up a filter based on the Rx flow classification
* command and fills the flow spec info for it if found
*
* Returns 0 on success or -EINVAL if filter not found
**/
static int i40e_get_ethtool_fdir_entry(struct i40e_pf *pf,
struct ethtool_rxnfc *cmd)
{
struct ethtool_rx_flow_spec *fsp =
(struct ethtool_rx_flow_spec *)&cmd->fs;
struct i40e_fdir_filter *rule = NULL;
struct hlist_node *node2;
/* report total rule count */
cmd->data = pf->hw.fdir_shared_filter_count +
pf->fdir_pf_filter_count;
hlist_for_each_entry_safe(rule, node2,
&pf->fdir_filter_list, fdir_node) {
if (fsp->location <= rule->fd_id)
break;
}
if (!rule || fsp->location != rule->fd_id)
return -EINVAL;
fsp->flow_type = rule->flow_type;
fsp->h_u.tcp_ip4_spec.psrc = rule->src_port;
fsp->h_u.tcp_ip4_spec.pdst = rule->dst_port;
fsp->h_u.tcp_ip4_spec.ip4src = rule->src_ip[0];
fsp->h_u.tcp_ip4_spec.ip4dst = rule->dst_ip[0];
fsp->ring_cookie = rule->q_index;
return 0;
}
/**
* i40e_get_rxnfc - command to get RX flow classification rules
* @netdev: network interface device structure
@ -1135,15 +1217,15 @@ static int i40e_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd,
ret = i40e_get_rss_hash_opts(pf, cmd);
break;
case ETHTOOL_GRXCLSRLCNT:
cmd->rule_cnt = 10;
cmd->rule_cnt = pf->fdir_pf_active_filters;
ret = 0;
break;
case ETHTOOL_GRXCLSRULE:
ret = 0;
ret = i40e_get_ethtool_fdir_entry(pf, cmd);
break;
case ETHTOOL_GRXCLSRLALL:
cmd->data = 500;
ret = 0;
ret = i40e_get_ethtool_fdir_all(pf, cmd, rule_locs);
break;
default:
break;
}
@ -1274,289 +1356,158 @@ static int i40e_set_rss_hash_opt(struct i40e_pf *pf, struct ethtool_rxnfc *nfc)
return 0;
}
#define IP_HEADER_OFFSET 14
#define I40E_UDPIP_DUMMY_PACKET_LEN 42
/**
* i40e_add_del_fdir_udpv4 - Add/Remove UDPv4 Flow Director filters for
* a specific flow spec
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required from the FDir descriptor
* @ethtool_rx_flow_spec: the flow spec
* @add: true adds a filter, false removes it
* i40e_update_ethtool_fdir_entry - Updates the fdir filter entry
* @vsi: Pointer to the targeted VSI
* @input: The filter to update or NULL to indicate deletion
* @sw_idx: Software index to the filter
* @cmd: The command to get or set Rx flow classification rules
*
* Returns 0 if the filters were successfully added or removed
* This function updates (or deletes) a Flow Director entry from
* the hlist of the corresponding PF
*
* Returns 0 on success
**/
static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
struct i40e_fdir_data *fd_data,
struct ethtool_rx_flow_spec *fsp, bool add)
static int i40e_update_ethtool_fdir_entry(struct i40e_vsi *vsi,
struct i40e_fdir_filter *input,
u16 sw_idx,
struct ethtool_rxnfc *cmd)
{
struct i40e_fdir_filter *rule, *parent;
struct i40e_pf *pf = vsi->back;
struct udphdr *udp;
struct iphdr *ip;
bool err = false;
int ret;
int i;
char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
0x45, 0, 0, 0x1c, 0, 0, 0x40, 0, 0x40, 0x11,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
struct hlist_node *node2;
int err = -EINVAL;
memcpy(fd_data->raw_packet, packet, I40E_UDPIP_DUMMY_PACKET_LEN);
parent = NULL;
rule = NULL;
ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET);
udp = (struct udphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET
+ sizeof(struct iphdr));
ip->saddr = fsp->h_u.tcp_ip4_spec.ip4src;
ip->daddr = fsp->h_u.tcp_ip4_spec.ip4dst;
udp->source = fsp->h_u.tcp_ip4_spec.psrc;
udp->dest = fsp->h_u.tcp_ip4_spec.pdst;
for (i = I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP;
i <= I40E_FILTER_PCTYPE_NONF_IPV4_UDP; i++) {
fd_data->pctype = i;
ret = i40e_program_fdir_filter(fd_data, pf, add);
if (ret) {
dev_info(&pf->pdev->dev,
"Filter command send failed for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
err = true;
} else {
dev_info(&pf->pdev->dev,
"Filter OK for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
}
hlist_for_each_entry_safe(rule, node2,
&pf->fdir_filter_list, fdir_node) {
/* hash found, or no matching entry */
if (rule->fd_id >= sw_idx)
break;
parent = rule;
}
return err ? -EOPNOTSUPP : 0;
/* if there is an old rule occupying our place remove it */
if (rule && (rule->fd_id == sw_idx)) {
if (!input || (rule->fd_id != input->fd_id)) {
cmd->fs.flow_type = rule->flow_type;
err = i40e_add_del_fdir_ethtool(vsi, cmd, false);
}
hlist_del(&rule->fdir_node);
kfree(rule);
pf->fdir_pf_active_filters--;
}
/* 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;
/* initialize node and set software index */
INIT_HLIST_NODE(&input->fdir_node);
/* add filter to the list */
if (parent)
hlist_add_after(&parent->fdir_node, &input->fdir_node);
else
hlist_add_head(&input->fdir_node,
&pf->fdir_filter_list);
/* update counts */
pf->fdir_pf_active_filters++;
return 0;
}
#define I40E_TCPIP_DUMMY_PACKET_LEN 54
/**
* i40e_add_del_fdir_tcpv4 - Add/Remove TCPv4 Flow Director filters for
* a specific flow spec
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required from the FDir descriptor
* @ethtool_rx_flow_spec: the flow spec
* @add: true adds a filter, false removes it
* i40e_del_fdir_entry - Deletes a Flow Director filter entry
* @vsi: Pointer to the targeted VSI
* @cmd: The command to get or set Rx flow classification rules
*
* Returns 0 if the filters were successfully added or removed
**/
static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
struct i40e_fdir_data *fd_data,
struct ethtool_rx_flow_spec *fsp, bool add)
* The function removes a Flow Director filter entry from the
* hlist of the corresponding PF
*
* Returns 0 on success
*/
static int i40e_del_fdir_entry(struct i40e_vsi *vsi,
struct ethtool_rxnfc *cmd)
{
struct ethtool_rx_flow_spec *fsp =
(struct ethtool_rx_flow_spec *)&cmd->fs;
struct i40e_pf *pf = vsi->back;
struct tcphdr *tcp;
struct iphdr *ip;
bool err = false;
int ret;
/* Dummy packet */
char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
0x45, 0, 0, 0x28, 0, 0, 0x40, 0, 0x40, 0x6,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0x80, 0x11, 0x0, 0x72, 0, 0, 0, 0};
int ret = 0;
memcpy(fd_data->raw_packet, packet, I40E_TCPIP_DUMMY_PACKET_LEN);
ret = i40e_update_ethtool_fdir_entry(vsi, NULL, fsp->location, cmd);
ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET);
tcp = (struct tcphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET
+ sizeof(struct iphdr));
ip->daddr = fsp->h_u.tcp_ip4_spec.ip4dst;
tcp->dest = fsp->h_u.tcp_ip4_spec.pdst;
ip->saddr = fsp->h_u.tcp_ip4_spec.ip4src;
tcp->source = fsp->h_u.tcp_ip4_spec.psrc;
if (add) {
if (pf->flags & I40E_FLAG_FD_ATR_ENABLED) {
dev_info(&pf->pdev->dev, "Forcing ATR off, sideband rules for TCP/IPv4 flow being applied\n");
pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
}
}
fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN;
ret = i40e_program_fdir_filter(fd_data, pf, add);
if (ret) {
dev_info(&pf->pdev->dev,
"Filter command send failed for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
err = true;
} else {
dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
}
fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
ret = i40e_program_fdir_filter(fd_data, pf, add);
if (ret) {
dev_info(&pf->pdev->dev,
"Filter command send failed for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
err = true;
} else {
dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
}
return err ? -EOPNOTSUPP : 0;
return ret;
}
/**
* i40e_add_del_fdir_sctpv4 - Add/Remove SCTPv4 Flow Director filters for
* a specific flow spec
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required from the FDir descriptor
* @ethtool_rx_flow_spec: the flow spec
* @add: true adds a filter, false removes it
*
* Returns 0 if the filters were successfully added or removed
**/
static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
struct i40e_fdir_data *fd_data,
struct ethtool_rx_flow_spec *fsp, bool add)
{
return -EOPNOTSUPP;
}
#define I40E_IP_DUMMY_PACKET_LEN 34
/**
* i40e_add_del_fdir_ipv4 - Add/Remove IPv4 Flow Director filters for
* a specific flow spec
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required for the FDir descriptor
* @fsp: the ethtool flow spec
* @add: true adds a filter, false removes it
*
* Returns 0 if the filters were successfully added or removed
**/
static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi,
struct i40e_fdir_data *fd_data,
struct ethtool_rx_flow_spec *fsp, bool add)
{
struct i40e_pf *pf = vsi->back;
struct iphdr *ip;
bool err = false;
int ret;
int i;
char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
0x45, 0, 0, 0x14, 0, 0, 0x40, 0, 0x40, 0x10,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
memcpy(fd_data->raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN);
ip = (struct iphdr *)(fd_data->raw_packet + IP_HEADER_OFFSET);
ip->saddr = fsp->h_u.usr_ip4_spec.ip4src;
ip->daddr = fsp->h_u.usr_ip4_spec.ip4dst;
ip->protocol = fsp->h_u.usr_ip4_spec.proto;
for (i = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
i <= I40E_FILTER_PCTYPE_FRAG_IPV4; i++) {
fd_data->pctype = i;
ret = i40e_program_fdir_filter(fd_data, pf, add);
if (ret) {
dev_info(&pf->pdev->dev,
"Filter command send failed for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
err = true;
} else {
dev_info(&pf->pdev->dev,
"Filter OK for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
}
}
return err ? -EOPNOTSUPP : 0;
}
/**
* i40e_add_del_fdir_ethtool - Add/Remove Flow Director filters for
* a specific flow spec based on their protocol
* i40e_add_del_fdir_ethtool - Add/Remove Flow Director filters
* @vsi: pointer to the targeted VSI
* @cmd: command to get or set RX flow classification rules
* @add: true adds a filter, false removes it
*
* Returns 0 if the filters were successfully added or removed
* Add/Remove Flow Director filters for a specific flow spec based on their
* protocol. Returns 0 if the filters were successfully added or removed.
**/
static int i40e_add_del_fdir_ethtool(struct i40e_vsi *vsi,
struct ethtool_rxnfc *cmd, bool add)
struct ethtool_rxnfc *cmd, bool add)
{
struct i40e_fdir_data fd_data;
int ret = -EINVAL;
struct ethtool_rx_flow_spec *fsp;
struct i40e_fdir_filter *input;
struct i40e_pf *pf;
struct ethtool_rx_flow_spec *fsp =
(struct ethtool_rx_flow_spec *)&cmd->fs;
int ret = -EINVAL;
if (!vsi)
return -EINVAL;
fsp = (struct ethtool_rx_flow_spec *)&cmd->fs;
pf = vsi->back;
if ((fsp->ring_cookie != RX_CLS_FLOW_DISC) &&
(fsp->ring_cookie >= vsi->num_queue_pairs))
if (fsp->location >= (pf->hw.func_caps.fd_filters_best_effort +
pf->hw.func_caps.fd_filters_guaranteed)) {
return -EINVAL;
}
if ((fsp->ring_cookie >= vsi->num_queue_pairs) && add)
return -EINVAL;
/* Populate the Flow Director that we have at the moment
* and allocate the raw packet buffer for the calling functions
*/
fd_data.raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_LOOKUP,
GFP_KERNEL);
input = kzalloc(sizeof(*input), GFP_KERNEL);
if (!fd_data.raw_packet) {
dev_info(&pf->pdev->dev, "Could not allocate memory\n");
if (!input)
return -ENOMEM;
input->fd_id = fsp->location;
input->q_index = fsp->ring_cookie;
input->flex_off = 0;
input->pctype = 0;
input->dest_vsi = vsi->id;
input->dest_ctl = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
input->fd_status = I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID;
input->cnt_index = 0;
input->flow_type = fsp->flow_type;
input->ip4_proto = fsp->h_u.usr_ip4_spec.proto;
input->src_port = fsp->h_u.tcp_ip4_spec.psrc;
input->dst_port = fsp->h_u.tcp_ip4_spec.pdst;
input->src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4src;
input->dst_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;
ret = i40e_add_del_fdir(vsi, input, add);
if (ret) {
kfree(input);
return ret;
}
fd_data.q_index = fsp->ring_cookie;
fd_data.flex_off = 0;
fd_data.pctype = 0;
fd_data.dest_vsi = vsi->id;
fd_data.dest_ctl = I40E_FILTER_PROGRAM_DESC_DEST_DIRECT_PACKET_QINDEX;
fd_data.fd_status = I40E_FILTER_PROGRAM_DESC_FD_STATUS_FD_ID;
fd_data.cnt_index = 0;
fd_data.fd_id = 0;
switch (fsp->flow_type & ~FLOW_EXT) {
case TCP_V4_FLOW:
ret = i40e_add_del_fdir_tcpv4(vsi, &fd_data, fsp, add);
break;
case UDP_V4_FLOW:
ret = i40e_add_del_fdir_udpv4(vsi, &fd_data, fsp, add);
break;
case SCTP_V4_FLOW:
ret = i40e_add_del_fdir_sctpv4(vsi, &fd_data, fsp, add);
break;
case IPV4_FLOW:
ret = i40e_add_del_fdir_ipv4(vsi, &fd_data, fsp, add);
break;
case IP_USER_FLOW:
switch (fsp->h_u.usr_ip4_spec.proto) {
case IPPROTO_TCP:
ret = i40e_add_del_fdir_tcpv4(vsi, &fd_data, fsp, add);
break;
case IPPROTO_UDP:
ret = i40e_add_del_fdir_udpv4(vsi, &fd_data, fsp, add);
break;
case IPPROTO_SCTP:
ret = i40e_add_del_fdir_sctpv4(vsi, &fd_data, fsp, add);
break;
default:
ret = i40e_add_del_fdir_ipv4(vsi, &fd_data, fsp, add);
break;
}
break;
default:
dev_info(&pf->pdev->dev, "Could not specify spec type\n");
ret = -EINVAL;
}
kfree(fd_data.raw_packet);
fd_data.raw_packet = NULL;
if (!ret && add)
i40e_update_ethtool_fdir_entry(vsi, input, fsp->location, NULL);
else
kfree(input);
return ret;
}
@ -1583,7 +1534,7 @@ static int i40e_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
ret = i40e_add_del_fdir_ethtool(vsi, cmd, true);
break;
case ETHTOOL_SRXCLSRLDEL:
ret = i40e_add_del_fdir_ethtool(vsi, cmd, false);
ret = i40e_del_fdir_entry(vsi, cmd);
break;
default:
break;

View file

@ -38,7 +38,7 @@ static const char i40e_driver_string[] =
#define DRV_VERSION_MAJOR 0
#define DRV_VERSION_MINOR 3
#define DRV_VERSION_BUILD 32
#define DRV_VERSION_BUILD 34
#define DRV_VERSION __stringify(DRV_VERSION_MAJOR) "." \
__stringify(DRV_VERSION_MINOR) "." \
__stringify(DRV_VERSION_BUILD) DRV_KERN
@ -1965,11 +1965,14 @@ static int i40e_vlan_rx_add_vid(struct net_device *netdev,
netdev_info(netdev, "adding %pM vid=%d\n", netdev->dev_addr, vid);
/* If the network stack called us with vid = 0, we should
* indicate to i40e_vsi_add_vlan() that we want to receive
* any traffic (i.e. with any vlan tag, or untagged)
/* If the network stack called us with vid = 0 then
* it is asking to receive priority tagged packets with
* vlan id 0. Our HW receives them by default when configured
* to receive untagged packets so there is no need to add an
* extra filter for vlan 0 tagged packets.
*/
ret = i40e_vsi_add_vlan(vsi, vid ? vid : I40E_VLAN_ANY);
if (vid)
ret = i40e_vsi_add_vlan(vsi, vid);
if (!ret && (vid < VLAN_N_VID))
set_bit(vid, vsi->active_vlans);
@ -2420,6 +2423,25 @@ static void i40e_set_vsi_rx_mode(struct i40e_vsi *vsi)
i40e_set_rx_mode(vsi->netdev);
}
/**
* i40e_fdir_filter_restore - Restore the Sideband Flow Director filters
* @vsi: Pointer to the targeted VSI
*
* This function replays the hlist on the hw where all the SB Flow Director
* filters were saved.
**/
static void i40e_fdir_filter_restore(struct i40e_vsi *vsi)
{
struct i40e_fdir_filter *filter;
struct i40e_pf *pf = vsi->back;
struct hlist_node *node;
hlist_for_each_entry_safe(filter, node,
&pf->fdir_filter_list, fdir_node) {
i40e_add_del_fdir(vsi, filter, true);
}
}
/**
* i40e_vsi_configure - Set up the VSI for action
* @vsi: the VSI being configured
@ -2431,6 +2453,8 @@ static int i40e_vsi_configure(struct i40e_vsi *vsi)
i40e_set_vsi_rx_mode(vsi);
i40e_restore_vlan(vsi);
i40e_vsi_config_dcb_rings(vsi);
if (vsi->type == I40E_VSI_FDIR)
i40e_fdir_filter_restore(vsi);
err = i40e_vsi_configure_tx(vsi);
if (!err)
err = i40e_vsi_configure_rx(vsi);
@ -4267,6 +4291,26 @@ err_setup_tx:
return err;
}
/**
* i40e_fdir_filter_exit - Cleans up the Flow Director accounting
* @pf: Pointer to pf
*
* This function destroys the hlist where all the Flow Director
* filters were saved.
**/
static void i40e_fdir_filter_exit(struct i40e_pf *pf)
{
struct i40e_fdir_filter *filter;
struct hlist_node *node2;
hlist_for_each_entry_safe(filter, node2,
&pf->fdir_filter_list, fdir_node) {
hlist_del(&filter->fdir_node);
kfree(filter);
}
pf->fdir_pf_active_filters = 0;
}
/**
* i40e_close - Disables a network interface
* @netdev: network interface device structure
@ -5052,6 +5096,12 @@ static int i40e_get_capabilities(struct i40e_pf *pf)
/* increment MSI-X count because current FW skips one */
pf->hw.func_caps.num_msix_vectors++;
if (((pf->hw.aq.fw_maj_ver == 2) && (pf->hw.aq.fw_min_ver < 22)) ||
(pf->hw.aq.fw_maj_ver < 2)) {
pf->hw.func_caps.num_msix_vectors++;
pf->hw.func_caps.num_msix_vectors_vf++;
}
if (pf->hw.debug_mask & I40E_DEBUG_USER)
dev_info(&pf->pdev->dev,
"pf=%d, num_vfs=%d, msix_pf=%d, msix_vf=%d, fd_g=%d, fd_b=%d, pf_max_q=%d num_vsi=%d\n",
@ -5131,9 +5181,9 @@ static void i40e_fdir_sb_setup(struct i40e_pf *pf)
err = i40e_up_complete(vsi);
if (err)
goto err_up_complete;
clear_bit(__I40E_NEEDS_RESTART, &vsi->state);
}
clear_bit(__I40E_NEEDS_RESTART, &vsi->state);
return;
err_up_complete:
@ -5156,6 +5206,7 @@ static void i40e_fdir_teardown(struct i40e_pf *pf)
{
int i;
i40e_fdir_filter_exit(pf);
for (i = 0; i < pf->hw.func_caps.num_vsis; i++) {
if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) {
i40e_vsi_release(pf->vsi[i]);
@ -7930,13 +7981,6 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err = i40e_init_adminq(hw);
dev_info(&pdev->dev, "%s\n", i40e_fw_version_str(hw));
if (((hw->nvm.version & I40E_NVM_VERSION_HI_MASK)
>> I40E_NVM_VERSION_HI_SHIFT) != I40E_CURRENT_NVM_VERSION_HI) {
dev_info(&pdev->dev,
"warning: NVM version not supported, supported version: %02x.%02x\n",
I40E_CURRENT_NVM_VERSION_HI,
I40E_CURRENT_NVM_VERSION_LO);
}
if (err) {
dev_info(&pdev->dev,
"init_adminq failed: %d expecting API %02x.%02x\n",

View file

@ -27,14 +27,14 @@
#include "i40e_prototype.h"
/**
* i40e_init_nvm_ops - Initialize NVM function pointers.
* @hw: pointer to the HW structure.
* i40e_init_nvm_ops - Initialize NVM function pointers
* @hw: pointer to the HW structure
*
* Setups the function pointers and the NVM info structure. Should be called
* once per NVM initialization, e.g. inside the i40e_init_shared_code().
* Please notice that the NVM term is used here (& in all methods covered
* in this file) as an equivalent of the FLASH part mapped into the SR.
* We are accessing FLASH always thru the Shadow RAM.
* Setup the function pointers and the NVM info structure. Should be called
* once per NVM initialization, e.g. inside the i40e_init_shared_code().
* Please notice that the NVM term is used here (& in all methods covered
* in this file) as an equivalent of the FLASH part mapped into the SR.
* We are accessing FLASH always thru the Shadow RAM.
**/
i40e_status i40e_init_nvm(struct i40e_hw *hw)
{
@ -49,16 +49,16 @@ i40e_status i40e_init_nvm(struct i40e_hw *hw)
gens = rd32(hw, I40E_GLNVM_GENS);
sr_size = ((gens & I40E_GLNVM_GENS_SR_SIZE_MASK) >>
I40E_GLNVM_GENS_SR_SIZE_SHIFT);
/* Switching to words (sr_size contains power of 2KB). */
/* Switching to words (sr_size contains power of 2KB) */
nvm->sr_size = (1 << sr_size) * I40E_SR_WORDS_IN_1KB;
/* Check if we are in the normal or blank NVM programming mode. */
/* Check if we are in the normal or blank NVM programming mode */
fla = rd32(hw, I40E_GLNVM_FLA);
if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode. */
/* Max NVM timeout. */
if (fla & I40E_GLNVM_FLA_LOCKED_MASK) { /* Normal programming mode */
/* Max NVM timeout */
nvm->timeout = I40E_MAX_NVM_TIMEOUT;
nvm->blank_nvm_mode = false;
} else { /* Blank programming mode. */
} else { /* Blank programming mode */
nvm->blank_nvm_mode = true;
ret_code = I40E_ERR_NVM_BLANK_MODE;
hw_dbg(hw, "NVM init error: unsupported blank mode.\n");
@ -68,12 +68,12 @@ i40e_status i40e_init_nvm(struct i40e_hw *hw)
}
/**
* i40e_acquire_nvm - Generic request for acquiring the NVM ownership.
* @hw: pointer to the HW structure.
* @access: NVM access type (read or write).
* i40e_acquire_nvm - Generic request for acquiring the NVM ownership
* @hw: pointer to the HW structure
* @access: NVM access type (read or write)
*
* This function will request NVM ownership for reading
* via the proper Admin Command.
* This function will request NVM ownership for reading
* via the proper Admin Command.
**/
i40e_status i40e_acquire_nvm(struct i40e_hw *hw,
enum i40e_aq_resource_access_type access)
@ -87,20 +87,20 @@ i40e_status i40e_acquire_nvm(struct i40e_hw *hw,
ret_code = i40e_aq_request_resource(hw, I40E_NVM_RESOURCE_ID, access,
0, &time, NULL);
/* Reading the Global Device Timer. */
/* Reading the Global Device Timer */
gtime = rd32(hw, I40E_GLVFGEN_TIMER);
/* Store the timeout. */
/* Store the timeout */
hw->nvm.hw_semaphore_timeout = I40E_MS_TO_GTIME(time) + gtime;
if (ret_code) {
/* Set the polling timeout. */
/* Set the polling timeout */
if (time > I40E_MAX_NVM_TIMEOUT)
timeout = I40E_MS_TO_GTIME(I40E_MAX_NVM_TIMEOUT)
+ gtime;
else
timeout = hw->nvm.hw_semaphore_timeout;
/* Poll until the current NVM owner timeouts. */
/* Poll until the current NVM owner timeouts */
while (gtime < timeout) {
usleep_range(10000, 20000);
ret_code = i40e_aq_request_resource(hw,
@ -128,10 +128,10 @@ i40e_i40e_acquire_nvm_exit:
}
/**
* i40e_release_nvm - Generic request for releasing the NVM ownership.
* @hw: pointer to the HW structure.
* i40e_release_nvm - Generic request for releasing the NVM ownership
* @hw: pointer to the HW structure
*
* This function will release NVM resource via the proper Admin Command.
* This function will release NVM resource via the proper Admin Command.
**/
void i40e_release_nvm(struct i40e_hw *hw)
{
@ -140,17 +140,17 @@ void i40e_release_nvm(struct i40e_hw *hw)
}
/**
* i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit.
* @hw: pointer to the HW structure.
* i40e_poll_sr_srctl_done_bit - Polls the GLNVM_SRCTL done bit
* @hw: pointer to the HW structure
*
* Polls the SRCTL Shadow RAM register done bit.
* Polls the SRCTL Shadow RAM register done bit.
**/
static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
{
i40e_status ret_code = I40E_ERR_TIMEOUT;
u32 srctl, wait_cnt;
/* Poll the I40E_GLNVM_SRCTL until the done bit is set. */
/* Poll the I40E_GLNVM_SRCTL until the done bit is set */
for (wait_cnt = 0; wait_cnt < I40E_SRRD_SRCTL_ATTEMPTS; wait_cnt++) {
srctl = rd32(hw, I40E_GLNVM_SRCTL);
if (srctl & I40E_GLNVM_SRCTL_DONE_MASK) {
@ -165,12 +165,12 @@ static i40e_status i40e_poll_sr_srctl_done_bit(struct i40e_hw *hw)
}
/**
* i40e_read_nvm_word - Reads Shadow RAM
* @hw: pointer to the HW structure.
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
* @data: word read from the Shadow RAM.
* i40e_read_nvm_word - Reads Shadow RAM
* @hw: pointer to the HW structure
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
* @data: word read from the Shadow RAM
*
* Reads 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
* Reads one 16 bit word from the Shadow RAM using the GLNVM_SRCTL register.
**/
i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
u16 *data)
@ -184,15 +184,15 @@ i40e_status i40e_read_nvm_word(struct i40e_hw *hw, u16 offset,
goto read_nvm_exit;
}
/* Poll the done bit first. */
/* Poll the done bit first */
ret_code = i40e_poll_sr_srctl_done_bit(hw);
if (!ret_code) {
/* Write the address and start reading. */
/* Write the address and start reading */
sr_reg = (u32)(offset << I40E_GLNVM_SRCTL_ADDR_SHIFT) |
(1 << I40E_GLNVM_SRCTL_START_SHIFT);
wr32(hw, I40E_GLNVM_SRCTL, sr_reg);
/* Poll I40E_GLNVM_SRCTL until the done bit is set. */
/* Poll I40E_GLNVM_SRCTL until the done bit is set */
ret_code = i40e_poll_sr_srctl_done_bit(hw);
if (!ret_code) {
sr_reg = rd32(hw, I40E_GLNVM_SRDATA);
@ -210,16 +210,15 @@ read_nvm_exit:
}
/**
* i40e_read_nvm_buffer - Reads Shadow RAM buffer.
* @hw: pointer to the HW structure.
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
* @words: number of words to read (in) &
* number of words read before the NVM ownership timeout (out).
* @data: words read from the Shadow RAM.
* i40e_read_nvm_buffer - Reads Shadow RAM buffer
* @hw: pointer to the HW structure
* @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF).
* @words: (in) number of words to read; (out) number of words actually read
* @data: words read from the Shadow RAM
*
* Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
* method. The buffer read is preceded by the NVM ownership take
* and followed by the release.
* Reads 16 bit words (data buffer) from the SR using the i40e_read_nvm_srrd()
* method. The buffer read is preceded by the NVM ownership take
* and followed by the release.
**/
i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
u16 *words, u16 *data)
@ -227,7 +226,7 @@ i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
i40e_status ret_code = 0;
u16 index, word;
/* Loop thru the selected region. */
/* Loop thru the selected region */
for (word = 0; word < *words; word++) {
index = offset + word;
ret_code = i40e_read_nvm_word(hw, index, &data[word]);
@ -235,21 +234,21 @@ i40e_status i40e_read_nvm_buffer(struct i40e_hw *hw, u16 offset,
break;
}
/* Update the number of words read from the Shadow RAM. */
/* Update the number of words read from the Shadow RAM */
*words = word;
return ret_code;
}
/**
* i40e_calc_nvm_checksum - Calculates and returns the checksum
* @hw: pointer to hardware structure
* @checksum: pointer to the checksum
* i40e_calc_nvm_checksum - Calculates and returns the checksum
* @hw: pointer to hardware structure
* @checksum: pointer to the checksum
*
* This function calculate SW Checksum that covers the whole 64kB shadow RAM
* except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
* is customer specific and unknown. Therefore, this function skips all maximum
* possible size of VPD (1kB).
* This function calculates SW Checksum that covers the whole 64kB shadow RAM
* except the VPD and PCIe ALT Auto-load modules. The structure and size of VPD
* is customer specific and unknown. Therefore, this function skips all maximum
* possible size of VPD (1kB).
**/
static i40e_status i40e_calc_nvm_checksum(struct i40e_hw *hw,
u16 *checksum)
@ -311,12 +310,12 @@ i40e_calc_nvm_checksum_exit:
}
/**
* i40e_validate_nvm_checksum - Validate EEPROM checksum
* @hw: pointer to hardware structure
* @checksum: calculated checksum
* i40e_validate_nvm_checksum - Validate EEPROM checksum
* @hw: pointer to hardware structure
* @checksum: calculated checksum
*
* Performs checksum calculation and validates the NVM SW checksum. If the
* caller does not need checksum, the value can be NULL.
* Performs checksum calculation and validates the NVM SW checksum. If the
* caller does not need checksum, the value can be NULL.
**/
i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
u16 *checksum)

View file

@ -231,6 +231,13 @@ i40e_status i40e_validate_nvm_checksum(struct i40e_hw *hw,
u16 *checksum);
void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status);
extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[];
static inline struct i40e_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype)
{
return i40e_ptype_lookup[ptype];
}
/* prototype for functions used for SW locks */
/* i40e_common for VF drivers*/

View file

@ -25,6 +25,7 @@
******************************************************************************/
#include "i40e.h"
#include "i40e_prototype.h"
static inline __le64 build_ctob(u32 td_cmd, u32 td_offset, unsigned int size,
u32 td_tag)
@ -39,11 +40,12 @@ static inline __le64 build_ctob(u32 td_cmd, u32 td_offset, unsigned int size,
#define I40E_TXD_CMD (I40E_TX_DESC_CMD_EOP | I40E_TX_DESC_CMD_RS)
/**
* i40e_program_fdir_filter - Program a Flow Director filter
* @fdir_input: Packet data that will be filter parameters
* @fdir_data: Packet data that will be filter parameters
* @raw_packet: the pre-allocated packet buffer for FDir
* @pf: The pf pointer
* @add: True for add/update, False for remove
**/
int i40e_program_fdir_filter(struct i40e_fdir_data *fdir_data,
int i40e_program_fdir_filter(struct i40e_fdir_filter *fdir_data, u8 *raw_packet,
struct i40e_pf *pf, bool add)
{
struct i40e_filter_program_desc *fdir_desc;
@ -68,8 +70,8 @@ int i40e_program_fdir_filter(struct i40e_fdir_data *fdir_data,
tx_ring = vsi->tx_rings[0];
dev = tx_ring->dev;
dma = dma_map_single(dev, fdir_data->raw_packet,
I40E_FDIR_MAX_RAW_PACKET_LOOKUP, DMA_TO_DEVICE);
dma = dma_map_single(dev, raw_packet,
I40E_FDIR_MAX_RAW_PACKET_SIZE, DMA_TO_DEVICE);
if (dma_mapping_error(dev, dma))
goto dma_fail;
@ -132,14 +134,14 @@ int i40e_program_fdir_filter(struct i40e_fdir_data *fdir_data,
tx_ring->next_to_use = (i + 1 < tx_ring->count) ? i + 1 : 0;
/* record length, and DMA address */
dma_unmap_len_set(tx_buf, len, I40E_FDIR_MAX_RAW_PACKET_LOOKUP);
dma_unmap_len_set(tx_buf, len, I40E_FDIR_MAX_RAW_PACKET_SIZE);
dma_unmap_addr_set(tx_buf, dma, dma);
tx_desc->buffer_addr = cpu_to_le64(dma);
td_cmd = I40E_TXD_CMD | I40E_TX_DESC_CMD_DUMMY;
tx_desc->cmd_type_offset_bsz =
build_ctob(td_cmd, 0, I40E_FDIR_MAX_RAW_PACKET_LOOKUP, 0);
build_ctob(td_cmd, 0, I40E_FDIR_MAX_RAW_PACKET_SIZE, 0);
/* set the timestamp */
tx_buf->time_stamp = jiffies;
@ -161,6 +163,270 @@ dma_fail:
return -1;
}
#define IP_HEADER_OFFSET 14
#define I40E_UDPIP_DUMMY_PACKET_LEN 42
/**
* i40e_add_del_fdir_udpv4 - Add/Remove UDPv4 filters
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required for the FDir descriptor
* @raw_packet: the pre-allocated packet buffer for FDir
* @add: true adds a filter, false removes it
*
* Returns 0 if the filters were successfully added or removed
**/
static int i40e_add_del_fdir_udpv4(struct i40e_vsi *vsi,
struct i40e_fdir_filter *fd_data,
u8 *raw_packet, bool add)
{
struct i40e_pf *pf = vsi->back;
struct udphdr *udp;
struct iphdr *ip;
bool err = false;
int ret;
int i;
static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
0x45, 0, 0, 0x1c, 0, 0, 0x40, 0, 0x40, 0x11, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
memcpy(raw_packet, packet, I40E_UDPIP_DUMMY_PACKET_LEN);
ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
udp = (struct udphdr *)(raw_packet + IP_HEADER_OFFSET
+ sizeof(struct iphdr));
ip->daddr = fd_data->dst_ip[0];
udp->dest = fd_data->dst_port;
ip->saddr = fd_data->src_ip[0];
udp->source = fd_data->src_port;
for (i = I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP;
i <= I40E_FILTER_PCTYPE_NONF_IPV4_UDP; i++) {
fd_data->pctype = i;
ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
if (ret) {
dev_info(&pf->pdev->dev,
"Filter command send failed for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
err = true;
} else {
dev_info(&pf->pdev->dev,
"Filter OK for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
}
}
return err ? -EOPNOTSUPP : 0;
}
#define I40E_TCPIP_DUMMY_PACKET_LEN 54
/**
* i40e_add_del_fdir_tcpv4 - Add/Remove TCPv4 filters
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required for the FDir descriptor
* @raw_packet: the pre-allocated packet buffer for FDir
* @add: true adds a filter, false removes it
*
* Returns 0 if the filters were successfully added or removed
**/
static int i40e_add_del_fdir_tcpv4(struct i40e_vsi *vsi,
struct i40e_fdir_filter *fd_data,
u8 *raw_packet, bool add)
{
struct i40e_pf *pf = vsi->back;
struct tcphdr *tcp;
struct iphdr *ip;
bool err = false;
int ret;
/* Dummy packet */
static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
0x45, 0, 0, 0x28, 0, 0, 0x40, 0, 0x40, 0x6, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x11,
0x0, 0x72, 0, 0, 0, 0};
memcpy(raw_packet, packet, I40E_TCPIP_DUMMY_PACKET_LEN);
ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
tcp = (struct tcphdr *)(raw_packet + IP_HEADER_OFFSET
+ sizeof(struct iphdr));
ip->daddr = fd_data->dst_ip[0];
tcp->dest = fd_data->dst_port;
ip->saddr = fd_data->src_ip[0];
tcp->source = fd_data->src_port;
if (add) {
if (pf->flags & I40E_FLAG_FD_ATR_ENABLED) {
dev_info(&pf->pdev->dev, "Forcing ATR off, sideband rules for TCP/IPv4 flow being applied\n");
pf->flags &= ~I40E_FLAG_FD_ATR_ENABLED;
}
}
fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN;
ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
if (ret) {
dev_info(&pf->pdev->dev,
"Filter command send failed for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
err = true;
} else {
dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
}
fd_data->pctype = I40E_FILTER_PCTYPE_NONF_IPV4_TCP;
ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
if (ret) {
dev_info(&pf->pdev->dev,
"Filter command send failed for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
err = true;
} else {
dev_info(&pf->pdev->dev, "Filter OK for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
}
return err ? -EOPNOTSUPP : 0;
}
/**
* i40e_add_del_fdir_sctpv4 - Add/Remove SCTPv4 Flow Director filters for
* a specific flow spec
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required for the FDir descriptor
* @raw_packet: the pre-allocated packet buffer for FDir
* @add: true adds a filter, false removes it
*
* Returns 0 if the filters were successfully added or removed
**/
static int i40e_add_del_fdir_sctpv4(struct i40e_vsi *vsi,
struct i40e_fdir_filter *fd_data,
u8 *raw_packet, bool add)
{
return -EOPNOTSUPP;
}
#define I40E_IP_DUMMY_PACKET_LEN 34
/**
* i40e_add_del_fdir_ipv4 - Add/Remove IPv4 Flow Director filters for
* a specific flow spec
* @vsi: pointer to the targeted VSI
* @fd_data: the flow director data required for the FDir descriptor
* @raw_packet: the pre-allocated packet buffer for FDir
* @add: true adds a filter, false removes it
*
* Returns 0 if the filters were successfully added or removed
**/
static int i40e_add_del_fdir_ipv4(struct i40e_vsi *vsi,
struct i40e_fdir_filter *fd_data,
u8 *raw_packet, bool add)
{
struct i40e_pf *pf = vsi->back;
struct iphdr *ip;
bool err = false;
int ret;
int i;
static char packet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0,
0x45, 0, 0, 0x14, 0, 0, 0x40, 0, 0x40, 0x10, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0};
memcpy(raw_packet, packet, I40E_IP_DUMMY_PACKET_LEN);
ip = (struct iphdr *)(raw_packet + IP_HEADER_OFFSET);
ip->saddr = fd_data->src_ip[0];
ip->daddr = fd_data->dst_ip[0];
ip->protocol = 0;
for (i = I40E_FILTER_PCTYPE_NONF_IPV4_OTHER;
i <= I40E_FILTER_PCTYPE_FRAG_IPV4; i++) {
fd_data->pctype = i;
ret = i40e_program_fdir_filter(fd_data, raw_packet, pf, add);
if (ret) {
dev_info(&pf->pdev->dev,
"Filter command send failed for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
err = true;
} else {
dev_info(&pf->pdev->dev,
"Filter OK for PCTYPE %d (ret = %d)\n",
fd_data->pctype, ret);
}
}
return err ? -EOPNOTSUPP : 0;
}
/**
* i40e_add_del_fdir - Build raw packets to add/del fdir filter
* @vsi: pointer to the targeted VSI
* @cmd: command to get or set RX flow classification rules
* @add: true adds a filter, false removes it
*
**/
int i40e_add_del_fdir(struct i40e_vsi *vsi,
struct i40e_fdir_filter *input, bool add)
{
struct i40e_pf *pf = vsi->back;
u8 *raw_packet;
int ret;
/* Populate the Flow Director that we have at the moment
* and allocate the raw packet buffer for the calling functions
*/
raw_packet = kzalloc(I40E_FDIR_MAX_RAW_PACKET_SIZE, GFP_KERNEL);
if (!raw_packet)
return -ENOMEM;
switch (input->flow_type & ~FLOW_EXT) {
case TCP_V4_FLOW:
ret = i40e_add_del_fdir_tcpv4(vsi, input, raw_packet,
add);
break;
case UDP_V4_FLOW:
ret = i40e_add_del_fdir_udpv4(vsi, input, raw_packet,
add);
break;
case SCTP_V4_FLOW:
ret = i40e_add_del_fdir_sctpv4(vsi, input, raw_packet,
add);
break;
case IPV4_FLOW:
ret = i40e_add_del_fdir_ipv4(vsi, input, raw_packet,
add);
break;
case IP_USER_FLOW:
switch (input->ip4_proto) {
case IPPROTO_TCP:
ret = i40e_add_del_fdir_tcpv4(vsi, input,
raw_packet, add);
break;
case IPPROTO_UDP:
ret = i40e_add_del_fdir_udpv4(vsi, input,
raw_packet, add);
break;
case IPPROTO_SCTP:
ret = i40e_add_del_fdir_sctpv4(vsi, input,
raw_packet, add);
break;
default:
ret = i40e_add_del_fdir_ipv4(vsi, input,
raw_packet, add);
break;
}
break;
default:
dev_info(&pf->pdev->dev, "Could not specify spec type %d",
input->flow_type);
ret = -EINVAL;
}
kfree(raw_packet);
return ret;
}
/**
* i40e_fd_handle_status - check the Programming Status for FD
* @rx_ring: the Rx ring for this descriptor
@ -955,6 +1221,29 @@ static inline u32 i40e_rx_hash(struct i40e_ring *ring,
return 0;
}
/**
* i40e_ptype_to_hash - get a hash type
* @ptype: the ptype value from the descriptor
*
* Returns a hash type to be used by skb_set_hash
**/
static inline enum pkt_hash_types i40e_ptype_to_hash(u8 ptype)
{
struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype);
if (!decoded.known)
return PKT_HASH_TYPE_NONE;
if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP &&
decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4)
return PKT_HASH_TYPE_L4;
else if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP &&
decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3)
return PKT_HASH_TYPE_L3;
else
return PKT_HASH_TYPE_L2;
}
/**
* i40e_clean_rx_irq - Reclaim resources after receive completes
* @rx_ring: rx ring to clean
@ -972,8 +1261,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
u16 i = rx_ring->next_to_clean;
union i40e_rx_desc *rx_desc;
u32 rx_error, rx_status;
u8 rx_ptype;
u64 qword;
u16 rx_ptype;
rx_desc = I40E_RX_DESC(rx_ring, i);
qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
@ -1087,7 +1376,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
goto next_desc;
}
skb->rxhash = i40e_rx_hash(rx_ring, rx_desc);
skb_set_hash(skb, i40e_rx_hash(rx_ring, rx_desc),
i40e_ptype_to_hash(rx_ptype));
if (unlikely(rx_status & I40E_RXD_QW1_STATUS_TSYNVALID_MASK)) {
i40e_ptp_rx_hwtstamp(vsi->back, skb, (rx_status &
I40E_RXD_QW1_STATUS_TSYNINDX_MASK) >>
@ -1812,7 +2102,7 @@ static int i40e_xmit_descriptor_count(struct sk_buff *skb,
/* need: 1 descriptor per page * PAGE_SIZE/I40E_MAX_DATA_PER_TXD,
* + 1 desc for skb_head_len/I40E_MAX_DATA_PER_TXD,
* + 2 desc gap to keep tail from touching head,
* + 4 desc gap to avoid the cache line where head is,
* + 1 desc for context descriptor,
* otherwise try next time
*/
@ -1823,7 +2113,7 @@ static int i40e_xmit_descriptor_count(struct sk_buff *skb,
count += skb_shinfo(skb)->nr_frags;
#endif
count += TXD_USE_COUNT(skb_headlen(skb));
if (i40e_maybe_stop_tx(tx_ring, count + 3)) {
if (i40e_maybe_stop_tx(tx_ring, count + 4 + 1)) {
tx_ring->tx_stats.tx_busy++;
return 0;
}

View file

@ -858,7 +858,7 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs)
}
}
/* allocate memory */
vfs = kzalloc(num_alloc_vfs * sizeof(struct i40e_vf), GFP_KERNEL);
vfs = kcalloc(num_alloc_vfs, sizeof(struct i40e_vf), GFP_KERNEL);
if (!vfs) {
ret = -ENOMEM;
goto err_alloc;

View file

@ -160,6 +160,372 @@ i40e_status i40evf_aq_queue_shutdown(struct i40e_hw *hw,
}
/* The i40e_ptype_lookup table is used to convert from the 8-bit ptype in the
* hardware to a bit-field that can be used by SW to more easily determine the
* packet type.
*
* Macros are used to shorten the table lines and make this table human
* readable.
*
* We store the PTYPE in the top byte of the bit field - this is just so that
* we can check that the table doesn't have a row missing, as the index into
* the table should be the PTYPE.
*
* Typical work flow:
*
* IF NOT i40e_ptype_lookup[ptype].known
* THEN
* Packet is unknown
* ELSE IF i40e_ptype_lookup[ptype].outer_ip == I40E_RX_PTYPE_OUTER_IP
* Use the rest of the fields to look at the tunnels, inner protocols, etc
* ELSE
* Use the enum i40e_rx_l2_ptype to decode the packet type
* ENDIF
*/
/* macro to make the table lines short */
#define I40E_PTT(PTYPE, OUTER_IP, OUTER_IP_VER, OUTER_FRAG, T, TE, TEF, I, PL)\
{ PTYPE, \
1, \
I40E_RX_PTYPE_OUTER_##OUTER_IP, \
I40E_RX_PTYPE_OUTER_##OUTER_IP_VER, \
I40E_RX_PTYPE_##OUTER_FRAG, \
I40E_RX_PTYPE_TUNNEL_##T, \
I40E_RX_PTYPE_TUNNEL_END_##TE, \
I40E_RX_PTYPE_##TEF, \
I40E_RX_PTYPE_INNER_PROT_##I, \
I40E_RX_PTYPE_PAYLOAD_LAYER_##PL }
#define I40E_PTT_UNUSED_ENTRY(PTYPE) \
{ PTYPE, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
/* shorter macros makes the table fit but are terse */
#define I40E_RX_PTYPE_NOF I40E_RX_PTYPE_NOT_FRAG
#define I40E_RX_PTYPE_FRG I40E_RX_PTYPE_FRAG
#define I40E_RX_PTYPE_INNER_PROT_TS I40E_RX_PTYPE_INNER_PROT_TIMESYNC
/* Lookup table mapping the HW PTYPE to the bit field for decoding */
struct i40e_rx_ptype_decoded i40e_ptype_lookup[] = {
/* L2 Packet types */
I40E_PTT_UNUSED_ENTRY(0),
I40E_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
I40E_PTT(2, L2, NONE, NOF, NONE, NONE, NOF, TS, PAY2),
I40E_PTT(3, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
I40E_PTT_UNUSED_ENTRY(4),
I40E_PTT_UNUSED_ENTRY(5),
I40E_PTT(6, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
I40E_PTT(7, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
I40E_PTT_UNUSED_ENTRY(8),
I40E_PTT_UNUSED_ENTRY(9),
I40E_PTT(10, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2),
I40E_PTT(11, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE),
I40E_PTT(12, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(13, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(14, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(15, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(16, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(17, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(18, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(19, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(20, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(21, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3),
/* Non Tunneled IPv4 */
I40E_PTT(22, IP, IPV4, FRG, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(23, IP, IPV4, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(24, IP, IPV4, NOF, NONE, NONE, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(25),
I40E_PTT(26, IP, IPV4, NOF, NONE, NONE, NOF, TCP, PAY4),
I40E_PTT(27, IP, IPV4, NOF, NONE, NONE, NOF, SCTP, PAY4),
I40E_PTT(28, IP, IPV4, NOF, NONE, NONE, NOF, ICMP, PAY4),
/* IPv4 --> IPv4 */
I40E_PTT(29, IP, IPV4, NOF, IP_IP, IPV4, FRG, NONE, PAY3),
I40E_PTT(30, IP, IPV4, NOF, IP_IP, IPV4, NOF, NONE, PAY3),
I40E_PTT(31, IP, IPV4, NOF, IP_IP, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(32),
I40E_PTT(33, IP, IPV4, NOF, IP_IP, IPV4, NOF, TCP, PAY4),
I40E_PTT(34, IP, IPV4, NOF, IP_IP, IPV4, NOF, SCTP, PAY4),
I40E_PTT(35, IP, IPV4, NOF, IP_IP, IPV4, NOF, ICMP, PAY4),
/* IPv4 --> IPv6 */
I40E_PTT(36, IP, IPV4, NOF, IP_IP, IPV6, FRG, NONE, PAY3),
I40E_PTT(37, IP, IPV4, NOF, IP_IP, IPV6, NOF, NONE, PAY3),
I40E_PTT(38, IP, IPV4, NOF, IP_IP, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(39),
I40E_PTT(40, IP, IPV4, NOF, IP_IP, IPV6, NOF, TCP, PAY4),
I40E_PTT(41, IP, IPV4, NOF, IP_IP, IPV6, NOF, SCTP, PAY4),
I40E_PTT(42, IP, IPV4, NOF, IP_IP, IPV6, NOF, ICMP, PAY4),
/* IPv4 --> GRE/NAT */
I40E_PTT(43, IP, IPV4, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3),
/* IPv4 --> GRE/NAT --> IPv4 */
I40E_PTT(44, IP, IPV4, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3),
I40E_PTT(45, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3),
I40E_PTT(46, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(47),
I40E_PTT(48, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4),
I40E_PTT(49, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4),
I40E_PTT(50, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4),
/* IPv4 --> GRE/NAT --> IPv6 */
I40E_PTT(51, IP, IPV4, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3),
I40E_PTT(52, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3),
I40E_PTT(53, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(54),
I40E_PTT(55, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4),
I40E_PTT(56, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4),
I40E_PTT(57, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4),
/* IPv4 --> GRE/NAT --> MAC */
I40E_PTT(58, IP, IPV4, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3),
/* IPv4 --> GRE/NAT --> MAC --> IPv4 */
I40E_PTT(59, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3),
I40E_PTT(60, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3),
I40E_PTT(61, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(62),
I40E_PTT(63, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4),
I40E_PTT(64, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4),
I40E_PTT(65, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4),
/* IPv4 --> GRE/NAT -> MAC --> IPv6 */
I40E_PTT(66, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3),
I40E_PTT(67, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3),
I40E_PTT(68, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(69),
I40E_PTT(70, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4),
I40E_PTT(71, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4),
I40E_PTT(72, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4),
/* IPv4 --> GRE/NAT --> MAC/VLAN */
I40E_PTT(73, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3),
/* IPv4 ---> GRE/NAT -> MAC/VLAN --> IPv4 */
I40E_PTT(74, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3),
I40E_PTT(75, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3),
I40E_PTT(76, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(77),
I40E_PTT(78, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4),
I40E_PTT(79, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4),
I40E_PTT(80, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4),
/* IPv4 -> GRE/NAT -> MAC/VLAN --> IPv6 */
I40E_PTT(81, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3),
I40E_PTT(82, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3),
I40E_PTT(83, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(84),
I40E_PTT(85, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4),
I40E_PTT(86, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4),
I40E_PTT(87, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4),
/* Non Tunneled IPv6 */
I40E_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3),
I40E_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY3),
I40E_PTT_UNUSED_ENTRY(91),
I40E_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4),
I40E_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4),
I40E_PTT(94, IP, IPV6, NOF, NONE, NONE, NOF, ICMP, PAY4),
/* IPv6 --> IPv4 */
I40E_PTT(95, IP, IPV6, NOF, IP_IP, IPV4, FRG, NONE, PAY3),
I40E_PTT(96, IP, IPV6, NOF, IP_IP, IPV4, NOF, NONE, PAY3),
I40E_PTT(97, IP, IPV6, NOF, IP_IP, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(98),
I40E_PTT(99, IP, IPV6, NOF, IP_IP, IPV4, NOF, TCP, PAY4),
I40E_PTT(100, IP, IPV6, NOF, IP_IP, IPV4, NOF, SCTP, PAY4),
I40E_PTT(101, IP, IPV6, NOF, IP_IP, IPV4, NOF, ICMP, PAY4),
/* IPv6 --> IPv6 */
I40E_PTT(102, IP, IPV6, NOF, IP_IP, IPV6, FRG, NONE, PAY3),
I40E_PTT(103, IP, IPV6, NOF, IP_IP, IPV6, NOF, NONE, PAY3),
I40E_PTT(104, IP, IPV6, NOF, IP_IP, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(105),
I40E_PTT(106, IP, IPV6, NOF, IP_IP, IPV6, NOF, TCP, PAY4),
I40E_PTT(107, IP, IPV6, NOF, IP_IP, IPV6, NOF, SCTP, PAY4),
I40E_PTT(108, IP, IPV6, NOF, IP_IP, IPV6, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT */
I40E_PTT(109, IP, IPV6, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3),
/* IPv6 --> GRE/NAT -> IPv4 */
I40E_PTT(110, IP, IPV6, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3),
I40E_PTT(111, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3),
I40E_PTT(112, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(113),
I40E_PTT(114, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4),
I40E_PTT(115, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4),
I40E_PTT(116, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT -> IPv6 */
I40E_PTT(117, IP, IPV6, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3),
I40E_PTT(118, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3),
I40E_PTT(119, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(120),
I40E_PTT(121, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4),
I40E_PTT(122, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4),
I40E_PTT(123, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT -> MAC */
I40E_PTT(124, IP, IPV6, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3),
/* IPv6 --> GRE/NAT -> MAC -> IPv4 */
I40E_PTT(125, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3),
I40E_PTT(126, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3),
I40E_PTT(127, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(128),
I40E_PTT(129, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4),
I40E_PTT(130, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4),
I40E_PTT(131, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT -> MAC -> IPv6 */
I40E_PTT(132, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3),
I40E_PTT(133, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3),
I40E_PTT(134, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(135),
I40E_PTT(136, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4),
I40E_PTT(137, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4),
I40E_PTT(138, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT -> MAC/VLAN */
I40E_PTT(139, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3),
/* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv4 */
I40E_PTT(140, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3),
I40E_PTT(141, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3),
I40E_PTT(142, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(143),
I40E_PTT(144, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4),
I40E_PTT(145, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4),
I40E_PTT(146, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4),
/* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv6 */
I40E_PTT(147, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3),
I40E_PTT(148, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3),
I40E_PTT(149, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4),
I40E_PTT_UNUSED_ENTRY(150),
I40E_PTT(151, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4),
I40E_PTT(152, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4),
I40E_PTT(153, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4),
/* unused entries */
I40E_PTT_UNUSED_ENTRY(154),
I40E_PTT_UNUSED_ENTRY(155),
I40E_PTT_UNUSED_ENTRY(156),
I40E_PTT_UNUSED_ENTRY(157),
I40E_PTT_UNUSED_ENTRY(158),
I40E_PTT_UNUSED_ENTRY(159),
I40E_PTT_UNUSED_ENTRY(160),
I40E_PTT_UNUSED_ENTRY(161),
I40E_PTT_UNUSED_ENTRY(162),
I40E_PTT_UNUSED_ENTRY(163),
I40E_PTT_UNUSED_ENTRY(164),
I40E_PTT_UNUSED_ENTRY(165),
I40E_PTT_UNUSED_ENTRY(166),
I40E_PTT_UNUSED_ENTRY(167),
I40E_PTT_UNUSED_ENTRY(168),
I40E_PTT_UNUSED_ENTRY(169),
I40E_PTT_UNUSED_ENTRY(170),
I40E_PTT_UNUSED_ENTRY(171),
I40E_PTT_UNUSED_ENTRY(172),
I40E_PTT_UNUSED_ENTRY(173),
I40E_PTT_UNUSED_ENTRY(174),
I40E_PTT_UNUSED_ENTRY(175),
I40E_PTT_UNUSED_ENTRY(176),
I40E_PTT_UNUSED_ENTRY(177),
I40E_PTT_UNUSED_ENTRY(178),
I40E_PTT_UNUSED_ENTRY(179),
I40E_PTT_UNUSED_ENTRY(180),
I40E_PTT_UNUSED_ENTRY(181),
I40E_PTT_UNUSED_ENTRY(182),
I40E_PTT_UNUSED_ENTRY(183),
I40E_PTT_UNUSED_ENTRY(184),
I40E_PTT_UNUSED_ENTRY(185),
I40E_PTT_UNUSED_ENTRY(186),
I40E_PTT_UNUSED_ENTRY(187),
I40E_PTT_UNUSED_ENTRY(188),
I40E_PTT_UNUSED_ENTRY(189),
I40E_PTT_UNUSED_ENTRY(190),
I40E_PTT_UNUSED_ENTRY(191),
I40E_PTT_UNUSED_ENTRY(192),
I40E_PTT_UNUSED_ENTRY(193),
I40E_PTT_UNUSED_ENTRY(194),
I40E_PTT_UNUSED_ENTRY(195),
I40E_PTT_UNUSED_ENTRY(196),
I40E_PTT_UNUSED_ENTRY(197),
I40E_PTT_UNUSED_ENTRY(198),
I40E_PTT_UNUSED_ENTRY(199),
I40E_PTT_UNUSED_ENTRY(200),
I40E_PTT_UNUSED_ENTRY(201),
I40E_PTT_UNUSED_ENTRY(202),
I40E_PTT_UNUSED_ENTRY(203),
I40E_PTT_UNUSED_ENTRY(204),
I40E_PTT_UNUSED_ENTRY(205),
I40E_PTT_UNUSED_ENTRY(206),
I40E_PTT_UNUSED_ENTRY(207),
I40E_PTT_UNUSED_ENTRY(208),
I40E_PTT_UNUSED_ENTRY(209),
I40E_PTT_UNUSED_ENTRY(210),
I40E_PTT_UNUSED_ENTRY(211),
I40E_PTT_UNUSED_ENTRY(212),
I40E_PTT_UNUSED_ENTRY(213),
I40E_PTT_UNUSED_ENTRY(214),
I40E_PTT_UNUSED_ENTRY(215),
I40E_PTT_UNUSED_ENTRY(216),
I40E_PTT_UNUSED_ENTRY(217),
I40E_PTT_UNUSED_ENTRY(218),
I40E_PTT_UNUSED_ENTRY(219),
I40E_PTT_UNUSED_ENTRY(220),
I40E_PTT_UNUSED_ENTRY(221),
I40E_PTT_UNUSED_ENTRY(222),
I40E_PTT_UNUSED_ENTRY(223),
I40E_PTT_UNUSED_ENTRY(224),
I40E_PTT_UNUSED_ENTRY(225),
I40E_PTT_UNUSED_ENTRY(226),
I40E_PTT_UNUSED_ENTRY(227),
I40E_PTT_UNUSED_ENTRY(228),
I40E_PTT_UNUSED_ENTRY(229),
I40E_PTT_UNUSED_ENTRY(230),
I40E_PTT_UNUSED_ENTRY(231),
I40E_PTT_UNUSED_ENTRY(232),
I40E_PTT_UNUSED_ENTRY(233),
I40E_PTT_UNUSED_ENTRY(234),
I40E_PTT_UNUSED_ENTRY(235),
I40E_PTT_UNUSED_ENTRY(236),
I40E_PTT_UNUSED_ENTRY(237),
I40E_PTT_UNUSED_ENTRY(238),
I40E_PTT_UNUSED_ENTRY(239),
I40E_PTT_UNUSED_ENTRY(240),
I40E_PTT_UNUSED_ENTRY(241),
I40E_PTT_UNUSED_ENTRY(242),
I40E_PTT_UNUSED_ENTRY(243),
I40E_PTT_UNUSED_ENTRY(244),
I40E_PTT_UNUSED_ENTRY(245),
I40E_PTT_UNUSED_ENTRY(246),
I40E_PTT_UNUSED_ENTRY(247),
I40E_PTT_UNUSED_ENTRY(248),
I40E_PTT_UNUSED_ENTRY(249),
I40E_PTT_UNUSED_ENTRY(250),
I40E_PTT_UNUSED_ENTRY(251),
I40E_PTT_UNUSED_ENTRY(252),
I40E_PTT_UNUSED_ENTRY(253),
I40E_PTT_UNUSED_ENTRY(254),
I40E_PTT_UNUSED_ENTRY(255)
};
/**
* i40e_aq_send_msg_to_pf
* @hw: pointer to the hardware structure

View file

@ -63,6 +63,13 @@ i40e_status i40evf_aq_queue_shutdown(struct i40e_hw *hw,
i40e_status i40e_set_mac_type(struct i40e_hw *hw);
extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[];
static inline struct i40e_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype)
{
return i40e_ptype_lookup[ptype];
}
/* prototype for functions used for SW locks */
/* i40e_common for VF drivers*/

View file

@ -24,6 +24,7 @@
#include <linux/prefetch.h>
#include "i40evf.h"
#include "i40e_prototype.h"
static inline __le64 build_ctob(u32 td_cmd, u32 td_offset, unsigned int size,
u32 td_tag)
@ -785,6 +786,29 @@ static inline u32 i40e_rx_hash(struct i40e_ring *ring,
return 0;
}
/**
* i40e_ptype_to_hash - get a hash type
* @ptype: the ptype value from the descriptor
*
* Returns a hash type to be used by skb_set_hash
**/
static inline enum pkt_hash_types i40e_ptype_to_hash(u8 ptype)
{
struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype);
if (!decoded.known)
return PKT_HASH_TYPE_NONE;
if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP &&
decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4)
return PKT_HASH_TYPE_L4;
else if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP &&
decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3)
return PKT_HASH_TYPE_L3;
else
return PKT_HASH_TYPE_L2;
}
/**
* i40e_clean_rx_irq - Reclaim resources after receive completes
* @rx_ring: rx ring to clean
@ -802,8 +826,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
u16 i = rx_ring->next_to_clean;
union i40e_rx_desc *rx_desc;
u32 rx_error, rx_status;
u8 rx_ptype;
u64 qword;
u16 rx_ptype;
rx_desc = I40E_RX_DESC(rx_ring, i);
qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len);
@ -912,7 +936,8 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
goto next_desc;
}
skb->rxhash = i40e_rx_hash(rx_ring, rx_desc);
skb_set_hash(skb, i40e_rx_hash(rx_ring, rx_desc),
i40e_ptype_to_hash(rx_ptype));
/* probably a little skewed due to removing CRC */
total_rx_bytes += skb->len;
total_rx_packets++;
@ -1457,7 +1482,7 @@ static int i40e_xmit_descriptor_count(struct sk_buff *skb,
/* need: 1 descriptor per page * PAGE_SIZE/I40E_MAX_DATA_PER_TXD,
* + 1 desc for skb_head_len/I40E_MAX_DATA_PER_TXD,
* + 2 desc gap to keep tail from touching head,
* + 4 desc gap to avoid the cache line where head is,
* + 1 desc for context descriptor,
* otherwise try next time
*/
@ -1468,7 +1493,7 @@ static int i40e_xmit_descriptor_count(struct sk_buff *skb,
count += skb_shinfo(skb)->nr_frags;
#endif
count += TXD_USE_COUNT(skb_headlen(skb));
if (i40e_maybe_stop_tx(tx_ring, count + 3)) {
if (i40e_maybe_stop_tx(tx_ring, count + 4 + 1)) {
tx_ring->tx_stats.tx_busy++;
return 0;
}

View file

@ -31,7 +31,7 @@ char i40evf_driver_name[] = "i40evf";
static const char i40evf_driver_string[] =
"Intel(R) XL710 X710 Virtual Function Network Driver";
#define DRV_VERSION "0.9.13"
#define DRV_VERSION "0.9.14"
const char i40evf_driver_version[] = DRV_VERSION;
static const char i40evf_copyright[] =
"Copyright (c) 2013 - 2014 Intel Corporation.";
@ -2036,6 +2036,7 @@ static void i40evf_init_task(struct work_struct *work)
NETIF_F_IPV6_CSUM |
NETIF_F_TSO |
NETIF_F_TSO6 |
NETIF_F_RXCSUM |
NETIF_F_GRO;
if (adapter->vf_res->vf_offload_flags
@ -2046,6 +2047,10 @@ static void i40evf_init_task(struct work_struct *work)
NETIF_F_HW_VLAN_CTAG_FILTER;
}
/* copy netdev features into list of user selectable features */
netdev->hw_features |= netdev->features;
netdev->hw_features &= ~NETIF_F_RXCSUM;
if (!is_valid_ether_addr(adapter->hw.mac.addr)) {
dev_info(&pdev->dev, "Invalid MAC address %pMAC, using random\n",
adapter->hw.mac.addr);