diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_common.c')
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_common.c | 1139 | 
1 files changed, 931 insertions, 208 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index c21df7bc3b1..6e65f19dd6e 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1,7 +1,7 @@  /*******************************************************************************   *   * Intel Ethernet Controller XL710 Family Linux Driver - * Copyright(c) 2013 Intel Corporation. + * Copyright(c) 2013 - 2014 Intel Corporation.   *   * This program is free software; you can redistribute it and/or modify it   * under the terms and conditions of the GNU General Public License, @@ -12,9 +12,8 @@   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   * more details.   * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * You should have received a copy of the GNU General Public License along + * with this program.  If not, see <http://www.gnu.org/licenses/>.   *   * The full GNU General Public License is included in this distribution in   * the file called "COPYING". @@ -43,20 +42,18 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw)  	if (hw->vendor_id == PCI_VENDOR_ID_INTEL) {  		switch (hw->device_id) { -		case I40E_SFP_XL710_DEVICE_ID: -		case I40E_SFP_X710_DEVICE_ID: -		case I40E_QEMU_DEVICE_ID: -		case I40E_KX_A_DEVICE_ID: -		case I40E_KX_B_DEVICE_ID: -		case I40E_KX_C_DEVICE_ID: -		case I40E_KX_D_DEVICE_ID: -		case I40E_QSFP_A_DEVICE_ID: -		case I40E_QSFP_B_DEVICE_ID: -		case I40E_QSFP_C_DEVICE_ID: +		case I40E_DEV_ID_SFP_XL710: +		case I40E_DEV_ID_QEMU: +		case I40E_DEV_ID_KX_A: +		case I40E_DEV_ID_KX_B: +		case I40E_DEV_ID_KX_C: +		case I40E_DEV_ID_QSFP_A: +		case I40E_DEV_ID_QSFP_B: +		case I40E_DEV_ID_QSFP_C:  			hw->mac.type = I40E_MAC_XL710;  			break; -		case I40E_VF_DEVICE_ID: -		case I40E_VF_HV_DEVICE_ID: +		case I40E_DEV_ID_VF: +		case I40E_DEV_ID_VF_HV:  			hw->mac.type = I40E_MAC_VF;  			break;  		default: @@ -75,7 +72,8 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw)  /**   * i40e_debug_aq   * @hw: debug mask related to admin queue - * @cap: pointer to adminq command descriptor + * @mask: debug mask + * @desc: pointer to admin queue descriptor   * @buffer: pointer to command buffer   *   * Dumps debug log about adminq command with descriptor contents. @@ -126,6 +124,413 @@ void i40e_debug_aq(struct i40e_hw *hw, enum i40e_debug_mask mask, void *desc,  }  /** + * i40e_check_asq_alive + * @hw: pointer to the hw struct + * + * Returns true if Queue is enabled else false. + **/ +bool i40e_check_asq_alive(struct i40e_hw *hw) +{ +	if (hw->aq.asq.len) +		return !!(rd32(hw, hw->aq.asq.len) & +			  I40E_PF_ATQLEN_ATQENABLE_MASK); +	else +		return false; +} + +/** + * i40e_aq_queue_shutdown + * @hw: pointer to the hw struct + * @unloading: is the driver unloading itself + * + * Tell the Firmware that we're shutting down the AdminQ and whether + * or not the driver is unloading as well. + **/ +i40e_status i40e_aq_queue_shutdown(struct i40e_hw *hw, +					     bool unloading) +{ +	struct i40e_aq_desc desc; +	struct i40e_aqc_queue_shutdown *cmd = +		(struct i40e_aqc_queue_shutdown *)&desc.params.raw; +	i40e_status status; + +	i40e_fill_default_direct_cmd_desc(&desc, +					  i40e_aqc_opc_queue_shutdown); + +	if (unloading) +		cmd->driver_unloading = cpu_to_le32(I40E_AQ_DRIVER_UNLOADING); +	status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL); + +	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   * @@ -142,14 +547,6 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw)  	i40e_status status = 0;  	u32 reg; -	hw->phy.get_link_info = true; - -	/* Determine port number */ -	reg = rd32(hw, I40E_PFGEN_PORTNUM); -	reg = ((reg & I40E_PFGEN_PORTNUM_PORT_NUM_MASK) >> -	       I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT); -	hw->port = (u8)reg; -  	i40e_set_mac_type(hw);  	switch (hw->mac.type) { @@ -160,6 +557,21 @@ i40e_status i40e_init_shared_code(struct i40e_hw *hw)  		break;  	} +	hw->phy.get_link_info = true; + +	/* Determine port number */ +	reg = rd32(hw, I40E_PFGEN_PORTNUM); +	reg = ((reg & I40E_PFGEN_PORTNUM_PORT_NUM_MASK) >> +	       I40E_PFGEN_PORTNUM_PORT_NUM_SHIFT); +	hw->port = (u8)reg; + +	/* Determine the PF number based on the PCI fn */ +	reg = rd32(hw, I40E_GLPCI_CAPSUP); +	if (reg & I40E_GLPCI_CAPSUP_ARI_EN_MASK) +		hw->pf_id = (u8)((hw->bus.device << 3) | hw->bus.func); +	else +		hw->pf_id = (u8)hw->bus.func; +  	status = i40e_init_nvm(hw);  	return status;  } @@ -210,8 +622,11 @@ i40e_status i40e_aq_mac_address_write(struct i40e_hw *hw,  	i40e_fill_default_direct_cmd_desc(&desc,  					  i40e_aqc_opc_mac_address_write);  	cmd_data->command_flags = cpu_to_le16(flags); -	memcpy(&cmd_data->mac_sal, &mac_addr[0], 4); -	memcpy(&cmd_data->mac_sah, &mac_addr[4], 2); +	cmd_data->mac_sah = cpu_to_le16((u16)mac_addr[0] << 8 | mac_addr[1]); +	cmd_data->mac_sal = cpu_to_le32(((u32)mac_addr[2] << 24) | +					((u32)mac_addr[3] << 16) | +					((u32)mac_addr[4] << 8) | +					mac_addr[5]);  	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); @@ -240,32 +655,83 @@ i40e_status i40e_get_mac_addr(struct i40e_hw *hw, u8 *mac_addr)  }  /** - * i40e_validate_mac_addr - Validate MAC address - * @mac_addr: pointer to MAC address + * i40e_pre_tx_queue_cfg - pre tx queue configure + * @hw: pointer to the HW structure + * @queue: target pf queue index + * @enable: state change request   * - * Tests a MAC address to ensure it is a valid Individual Address + * Handles hw requirement to indicate intention to enable + * or disable target queue.   **/ -i40e_status i40e_validate_mac_addr(u8 *mac_addr) +void i40e_pre_tx_queue_cfg(struct i40e_hw *hw, u32 queue, bool enable)  { -	i40e_status status = 0; +	u32 abs_queue_idx = hw->func_caps.base_queue + queue; +	u32 reg_block = 0; +	u32 reg_val; -	/* Make sure it is not a multicast address */ -	if (I40E_IS_MULTICAST(mac_addr)) { -		hw_dbg(hw, "MAC address is multicast\n"); -		status = I40E_ERR_INVALID_MAC_ADDR; -	/* Not a broadcast address */ -	} else if (I40E_IS_BROADCAST(mac_addr)) { -		hw_dbg(hw, "MAC address is broadcast\n"); -		status = I40E_ERR_INVALID_MAC_ADDR; -	/* Reject the zero address */ -	} else if (mac_addr[0] == 0 && mac_addr[1] == 0 && mac_addr[2] == 0 && -		   mac_addr[3] == 0 && mac_addr[4] == 0 && mac_addr[5] == 0) { -		hw_dbg(hw, "MAC address is all zeros\n"); -		status = I40E_ERR_INVALID_MAC_ADDR; +	if (abs_queue_idx >= 128) +		reg_block = abs_queue_idx / 128; + +	reg_val = rd32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block)); +	reg_val &= ~I40E_GLLAN_TXPRE_QDIS_QINDX_MASK; +	reg_val |= (abs_queue_idx << I40E_GLLAN_TXPRE_QDIS_QINDX_SHIFT); + +	if (enable) +		reg_val |= I40E_GLLAN_TXPRE_QDIS_CLEAR_QDIS_MASK; +	else +		reg_val |= I40E_GLLAN_TXPRE_QDIS_SET_QDIS_MASK; + +	wr32(hw, I40E_GLLAN_TXPRE_QDIS(reg_block), reg_val); +} + +/** + * i40e_get_media_type - Gets media type + * @hw: pointer to the hardware structure + **/ +static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw) +{ +	enum i40e_media_type media; + +	switch (hw->phy.link_info.phy_type) { +	case I40E_PHY_TYPE_10GBASE_SR: +	case I40E_PHY_TYPE_10GBASE_LR: +	case I40E_PHY_TYPE_40GBASE_SR4: +	case I40E_PHY_TYPE_40GBASE_LR4: +		media = I40E_MEDIA_TYPE_FIBER; +		break; +	case I40E_PHY_TYPE_100BASE_TX: +	case I40E_PHY_TYPE_1000BASE_T: +	case I40E_PHY_TYPE_10GBASE_T: +		media = I40E_MEDIA_TYPE_BASET; +		break; +	case I40E_PHY_TYPE_10GBASE_CR1_CU: +	case I40E_PHY_TYPE_40GBASE_CR4_CU: +	case I40E_PHY_TYPE_10GBASE_CR1: +	case I40E_PHY_TYPE_40GBASE_CR4: +	case I40E_PHY_TYPE_10GBASE_SFPP_CU: +		media = I40E_MEDIA_TYPE_DA; +		break; +	case I40E_PHY_TYPE_1000BASE_KX: +	case I40E_PHY_TYPE_10GBASE_KX4: +	case I40E_PHY_TYPE_10GBASE_KR: +	case I40E_PHY_TYPE_40GBASE_KR4: +		media = I40E_MEDIA_TYPE_BACKPLANE; +		break; +	case I40E_PHY_TYPE_SGMII: +	case I40E_PHY_TYPE_XAUI: +	case I40E_PHY_TYPE_XFI: +	case I40E_PHY_TYPE_XLAUI: +	case I40E_PHY_TYPE_XLPPI: +	default: +		media = I40E_MEDIA_TYPE_UNKNOWN; +		break;  	} -	return status; + +	return media;  } +#define I40E_PF_RESET_WAIT_COUNT_A0	200 +#define I40E_PF_RESET_WAIT_COUNT	100  /**   * i40e_pf_reset - Reset the PF   * @hw: pointer to the hardware structure @@ -275,7 +741,8 @@ i40e_status i40e_validate_mac_addr(u8 *mac_addr)   **/  i40e_status i40e_pf_reset(struct i40e_hw *hw)  { -	u32 wait_cnt = 0; +	u32 cnt = 0; +	u32 cnt1 = 0;  	u32 reg = 0;  	u32 grst_del; @@ -285,7 +752,7 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw)  	 */  	grst_del = rd32(hw, I40E_GLGEN_RSTCTL) & I40E_GLGEN_RSTCTL_GRSTDEL_MASK  			>> I40E_GLGEN_RSTCTL_GRSTDEL_SHIFT; -	for (wait_cnt = 0; wait_cnt < grst_del + 2; wait_cnt++) { +	for (cnt = 0; cnt < grst_del + 2; cnt++) {  		reg = rd32(hw, I40E_GLGEN_RSTAT);  		if (!(reg & I40E_GLGEN_RSTAT_DEVSTATE_MASK))  			break; @@ -296,17 +763,37 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw)  		return I40E_ERR_RESET_FAILED;  	} -	/* Determine the PF number based on the PCI fn */ -	hw->pf_id = (u8)hw->bus.func; +	/* Now Wait for the FW to be ready */ +	for (cnt1 = 0; cnt1 < I40E_PF_RESET_WAIT_COUNT; cnt1++) { +		reg = rd32(hw, I40E_GLNVM_ULD); +		reg &= (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK | +			I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK); +		if (reg == (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK | +			    I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK)) { +			hw_dbg(hw, "Core and Global modules ready %d\n", cnt1); +			break; +		} +		usleep_range(10000, 20000); +	} +	if (!(reg & (I40E_GLNVM_ULD_CONF_CORE_DONE_MASK | +		     I40E_GLNVM_ULD_CONF_GLOBAL_DONE_MASK))) { +		hw_dbg(hw, "wait for FW Reset complete timedout\n"); +		hw_dbg(hw, "I40E_GLNVM_ULD = 0x%x\n", reg); +		return I40E_ERR_RESET_FAILED; +	}  	/* If there was a Global Reset in progress when we got here,  	 * we don't need to do the PF Reset  	 */ -	if (!wait_cnt) { +	if (!cnt) { +		if (hw->revision_id == 0) +			cnt = I40E_PF_RESET_WAIT_COUNT_A0; +		else +			cnt = I40E_PF_RESET_WAIT_COUNT;  		reg = rd32(hw, I40E_PFGEN_CTRL);  		wr32(hw, I40E_PFGEN_CTRL,  		     (reg | I40E_PFGEN_CTRL_PFSWR_MASK)); -		for (wait_cnt = 0; wait_cnt < 10; wait_cnt++) { +		for (; cnt; cnt--) {  			reg = rd32(hw, I40E_PFGEN_CTRL);  			if (!(reg & I40E_PFGEN_CTRL_PFSWR_MASK))  				break; @@ -319,6 +806,7 @@ i40e_status i40e_pf_reset(struct i40e_hw *hw)  	}  	i40e_clear_pxe_mode(hw); +  	return 0;  } @@ -333,12 +821,53 @@ void i40e_clear_pxe_mode(struct i40e_hw *hw)  {  	u32 reg; +	if (i40e_check_asq_alive(hw)) +		i40e_aq_clear_pxe_mode(hw, NULL); +  	/* Clear single descriptor fetch/write-back mode */  	reg = rd32(hw, I40E_GLLAN_RCTL_0); -	wr32(hw, I40E_GLLAN_RCTL_0, (reg | I40E_GLLAN_RCTL_0_PXE_MODE_MASK)); + +	if (hw->revision_id == 0) { +		/* As a work around clear PXE_MODE instead of setting it */ +		wr32(hw, I40E_GLLAN_RCTL_0, (reg & (~I40E_GLLAN_RCTL_0_PXE_MODE_MASK))); +	} else { +		wr32(hw, I40E_GLLAN_RCTL_0, (reg | I40E_GLLAN_RCTL_0_PXE_MODE_MASK)); +	}  }  /** + * i40e_led_is_mine - helper to find matching led + * @hw: pointer to the hw struct + * @idx: index into GPIO registers + * + * returns: 0 if no match, otherwise the value of the GPIO_CTL register + */ +static u32 i40e_led_is_mine(struct i40e_hw *hw, int idx) +{ +	u32 gpio_val = 0; +	u32 port; + +	if (!hw->func_caps.led[idx]) +		return 0; + +	gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(idx)); +	port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) >> +		I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT; + +	/* if PRT_NUM_NA is 1 then this LED is not port specific, OR +	 * if it is not our port then ignore +	 */ +	if ((gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_NA_MASK) || +	    (port != hw->port)) +		return 0; + +	return gpio_val; +} + +#define I40E_LED0 22 +#define I40E_LINK_ACTIVITY 0xC + +/**   * i40e_led_get - return current on/off mode   * @hw: pointer to the hw struct   * @@ -349,24 +878,20 @@ void i40e_clear_pxe_mode(struct i40e_hw *hw)   **/  u32 i40e_led_get(struct i40e_hw *hw)  { -	u32 gpio_val = 0;  	u32 mode = 0; -	u32 port;  	int i; -	for (i = 0; i < I40E_HW_CAP_MAX_GPIO; i++) { -		if (!hw->func_caps.led[i]) -			continue; - -		gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(i)); -		port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) -			>> I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT; +	/* as per the documentation GPIO 22-29 are the LED +	 * GPIO pins named LED0..LED7 +	 */ +	for (i = I40E_LED0; i <= I40E_GLGEN_GPIO_CTL_MAX_INDEX; i++) { +		u32 gpio_val = i40e_led_is_mine(hw, i); -		if (port != hw->port) +		if (!gpio_val)  			continue; -		mode = (gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) -				>> I40E_GLGEN_GPIO_CTL_INT_MODE_SHIFT; +		mode = (gpio_val & I40E_GLGEN_GPIO_CTL_LED_MODE_MASK) >> +			I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT;  		break;  	} @@ -376,57 +901,69 @@ u32 i40e_led_get(struct i40e_hw *hw)  /**   * i40e_led_set - set new on/off mode   * @hw: pointer to the hw struct - * @mode: 0=off, else on (see EAS for mode details) + * @mode: 0=off, 0xf=on (else see manual for mode details) + * @blink: true if the LED should blink when on, false if steady + * + * if this function is used to turn on the blink it should + * be used to disable the blink when restoring the original state.   **/ -void i40e_led_set(struct i40e_hw *hw, u32 mode) +void i40e_led_set(struct i40e_hw *hw, u32 mode, bool blink)  { -	u32 gpio_val = 0; -	u32 led_mode = 0; -	u32 port;  	int i; -	for (i = 0; i < I40E_HW_CAP_MAX_GPIO; i++) { -		if (!hw->func_caps.led[i]) -			continue; +	if (mode & 0xfffffff0) +		hw_dbg(hw, "invalid mode passed in %X\n", mode); -		gpio_val = rd32(hw, I40E_GLGEN_GPIO_CTL(i)); -		port = (gpio_val & I40E_GLGEN_GPIO_CTL_PRT_NUM_MASK) -			>> I40E_GLGEN_GPIO_CTL_PRT_NUM_SHIFT; +	/* as per the documentation GPIO 22-29 are the LED +	 * GPIO pins named LED0..LED7 +	 */ +	for (i = I40E_LED0; i <= I40E_GLGEN_GPIO_CTL_MAX_INDEX; i++) { +		u32 gpio_val = i40e_led_is_mine(hw, i); -		if (port != hw->port) +		if (!gpio_val)  			continue; -		led_mode = (mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) & -			    I40E_GLGEN_GPIO_CTL_LED_MODE_MASK;  		gpio_val &= ~I40E_GLGEN_GPIO_CTL_LED_MODE_MASK; -		gpio_val |= led_mode; +		/* this & is a bit of paranoia, but serves as a range check */ +		gpio_val |= ((mode << I40E_GLGEN_GPIO_CTL_LED_MODE_SHIFT) & +			     I40E_GLGEN_GPIO_CTL_LED_MODE_MASK); + +		if (mode == I40E_LINK_ACTIVITY) +			blink = false; + +		gpio_val |= (blink ? 1 : 0) << +			    I40E_GLGEN_GPIO_CTL_LED_BLINK_SHIFT; +  		wr32(hw, I40E_GLGEN_GPIO_CTL(i), gpio_val); +		break;  	}  }  /* Admin command wrappers */ +  /** - * i40e_aq_queue_shutdown + * i40e_aq_clear_pxe_mode   * @hw: pointer to the hw struct - * @unloading: is the driver unloading itself + * @cmd_details: pointer to command details structure or NULL   * - * Tell the Firmware that we're shutting down the AdminQ and whether - * or not the driver is unloading as well. + * Tell the firmware that the driver is taking over from PXE   **/ -i40e_status i40e_aq_queue_shutdown(struct i40e_hw *hw, -					     bool unloading) +i40e_status i40e_aq_clear_pxe_mode(struct i40e_hw *hw, +				struct i40e_asq_cmd_details *cmd_details)  { -	struct i40e_aq_desc desc; -	struct i40e_aqc_queue_shutdown *cmd = -		(struct i40e_aqc_queue_shutdown *)&desc.params.raw;  	i40e_status status; +	struct i40e_aq_desc desc; +	struct i40e_aqc_clear_pxe *cmd = +		(struct i40e_aqc_clear_pxe *)&desc.params.raw;  	i40e_fill_default_direct_cmd_desc(&desc, -					  i40e_aqc_opc_queue_shutdown); +					  i40e_aqc_opc_clear_pxe_mode); -	if (unloading) -		cmd->driver_unloading = cpu_to_le32(I40E_AQ_DRIVER_UNLOADING); -	status = i40e_asq_send_command(hw, &desc, NULL, 0, NULL); +	cmd->rx_cnt = 0x2; + +	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + +	wr32(hw, I40E_GLLAN_RCTL_0, 0x1);  	return status;  } @@ -490,15 +1027,23 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,  		goto aq_get_link_info_exit;  	/* save off old link status information */ -	memcpy(&hw->phy.link_info_old, hw_link_info, -	       sizeof(struct i40e_link_status)); +	hw->phy.link_info_old = *hw_link_info;  	/* update link status */  	hw_link_info->phy_type = (enum i40e_aq_phy_type)resp->phy_type; +	hw->phy.media_type = i40e_get_media_type(hw);  	hw_link_info->link_speed = (enum i40e_aq_link_speed)resp->link_speed;  	hw_link_info->link_info = resp->link_info;  	hw_link_info->an_info = resp->an_info;  	hw_link_info->ext_info = resp->ext_info; +	hw_link_info->loopback = resp->loopback; +	hw_link_info->max_frame_size = le16_to_cpu(resp->max_frame_size); +	hw_link_info->pacing = resp->config & I40E_AQ_CONFIG_PACING_MASK; + +	if (resp->config & I40E_AQ_CONFIG_CRC_ENA) +		hw_link_info->crc_enable = true; +	else +		hw_link_info->crc_enable = false;  	if (resp->command_flags & cpu_to_le16(I40E_AQ_LSE_ENABLE))  		hw_link_info->lse_enable = true; @@ -507,7 +1052,7 @@ i40e_status i40e_aq_get_link_info(struct i40e_hw *hw,  	/* save link status information */  	if (link) -		memcpy(link, hw_link_info, sizeof(struct i40e_link_status)); +		*link = *hw_link_info;  	/* flag cleared so helper functions don't call AQ again */  	hw->phy.get_link_info = false; @@ -519,7 +1064,7 @@ aq_get_link_info_exit:  /**   * i40e_aq_add_vsi   * @hw: pointer to the hw struct - * @vsi: pointer to a vsi context struct + * @vsi_ctx: pointer to a vsi context struct   * @cmd_details: pointer to command details structure or NULL   *   * Add a VSI context to the hardware. @@ -545,8 +1090,6 @@ i40e_status i40e_aq_add_vsi(struct i40e_hw *hw,  	cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags);  	desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); -	if (sizeof(vsi_ctx->info) > I40E_AQ_LARGE_BUF) -		desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);  	status = i40e_asq_send_command(hw, &desc, &vsi_ctx->info,  				    sizeof(vsi_ctx->info), cmd_details); @@ -571,7 +1114,8 @@ aq_add_vsi_exit:   * @cmd_details: pointer to command details structure or NULL   **/  i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw, -				u16 seid, bool set, struct i40e_asq_cmd_details *cmd_details) +				u16 seid, bool set, +				struct i40e_asq_cmd_details *cmd_details)  {  	struct i40e_aq_desc desc;  	struct i40e_aqc_set_vsi_promiscuous_modes *cmd = @@ -665,7 +1209,7 @@ i40e_status i40e_aq_set_vsi_broadcast(struct i40e_hw *hw,  /**   * i40e_get_vsi_params - get VSI configuration info   * @hw: pointer to the hw struct - * @vsi: pointer to a vsi context struct + * @vsi_ctx: pointer to a vsi context struct   * @cmd_details: pointer to command details structure or NULL   **/  i40e_status i40e_aq_get_vsi_params(struct i40e_hw *hw, @@ -673,8 +1217,8 @@ i40e_status i40e_aq_get_vsi_params(struct i40e_hw *hw,  				struct i40e_asq_cmd_details *cmd_details)  {  	struct i40e_aq_desc desc; -	struct i40e_aqc_switch_seid *cmd = -		(struct i40e_aqc_switch_seid *)&desc.params.raw; +	struct i40e_aqc_add_get_update_vsi *cmd = +		(struct i40e_aqc_add_get_update_vsi *)&desc.params.raw;  	struct i40e_aqc_add_get_update_vsi_completion *resp =  		(struct i40e_aqc_add_get_update_vsi_completion *)  		&desc.params.raw; @@ -683,11 +1227,9 @@ i40e_status i40e_aq_get_vsi_params(struct i40e_hw *hw,  	i40e_fill_default_direct_cmd_desc(&desc,  					  i40e_aqc_opc_get_vsi_parameters); -	cmd->seid = cpu_to_le16(vsi_ctx->seid); +	cmd->uplink_seid = cpu_to_le16(vsi_ctx->seid);  	desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_BUF); -	if (sizeof(vsi_ctx->info) > I40E_AQ_LARGE_BUF) -		desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);  	status = i40e_asq_send_command(hw, &desc, &vsi_ctx->info,  				    sizeof(vsi_ctx->info), NULL); @@ -707,7 +1249,7 @@ aq_get_vsi_params_exit:  /**   * i40e_aq_update_vsi_params   * @hw: pointer to the hw struct - * @vsi: pointer to a vsi context struct + * @vsi_ctx: pointer to a vsi context struct   * @cmd_details: pointer to command details structure or NULL   *   * Update a VSI context. @@ -717,17 +1259,15 @@ i40e_status i40e_aq_update_vsi_params(struct i40e_hw *hw,  				struct i40e_asq_cmd_details *cmd_details)  {  	struct i40e_aq_desc desc; -	struct i40e_aqc_switch_seid *cmd = -		(struct i40e_aqc_switch_seid *)&desc.params.raw; +	struct i40e_aqc_add_get_update_vsi *cmd = +		(struct i40e_aqc_add_get_update_vsi *)&desc.params.raw;  	i40e_status status;  	i40e_fill_default_direct_cmd_desc(&desc,  					  i40e_aqc_opc_update_vsi_parameters); -	cmd->seid = cpu_to_le16(vsi_ctx->seid); +	cmd->uplink_seid = cpu_to_le16(vsi_ctx->seid);  	desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); -	if (sizeof(vsi_ctx->info) > I40E_AQ_LARGE_BUF) -		desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);  	status = i40e_asq_send_command(hw, &desc, &vsi_ctx->info,  				    sizeof(vsi_ctx->info), cmd_details); @@ -810,7 +1350,6 @@ i40e_status i40e_aq_get_firmware_version(struct i40e_hw *hw,  /**   * i40e_aq_send_driver_version   * @hw: pointer to the hw struct - * @event: driver event: driver ok, start or stop   * @dv: driver's major, minor version   * @cmd_details: pointer to command details structure or NULL   * @@ -824,6 +1363,7 @@ i40e_status i40e_aq_send_driver_version(struct i40e_hw *hw,  	struct i40e_aqc_driver_version *cmd =  		(struct i40e_aqc_driver_version *)&desc.params.raw;  	i40e_status status; +	u16 len;  	if (dv == NULL)  		return I40E_ERR_PARAM; @@ -835,7 +1375,14 @@ i40e_status i40e_aq_send_driver_version(struct i40e_hw *hw,  	cmd->driver_minor_ver = dv->minor_version;  	cmd->driver_build_ver = dv->build_version;  	cmd->driver_subbuild_ver = dv->subbuild_version; -	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + +	len = 0; +	while (len < sizeof(dv->driver_string) && +	       (dv->driver_string[len] < 0x80) && +	       dv->driver_string[len]) +		len++; +	status = i40e_asq_send_command(hw, &desc, dv->driver_string, +				       len, cmd_details);  	return status;  } @@ -873,6 +1420,7 @@ i40e_get_link_status_exit:   * @downlink_seid: the VSI SEID   * @enabled_tc: bitmap of TCs to be enabled   * @default_port: true for default port VSI, false for control port + * @enable_l2_filtering: true to add L2 filter table rules to regular forwarding rules for cloud support   * @veb_seid: pointer to where to put the resulting VEB SEID   * @cmd_details: pointer to command details structure or NULL   * @@ -881,7 +1429,8 @@ i40e_get_link_status_exit:   **/  i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid,  				u16 downlink_seid, u8 enabled_tc, -				bool default_port, u16 *veb_seid, +				bool default_port, bool enable_l2_filtering, +				u16 *veb_seid,  				struct i40e_asq_cmd_details *cmd_details)  {  	struct i40e_aq_desc desc; @@ -907,6 +1456,10 @@ i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid,  		veb_flags |= I40E_AQC_ADD_VEB_PORT_TYPE_DEFAULT;  	else  		veb_flags |= I40E_AQC_ADD_VEB_PORT_TYPE_DATA; + +	if (enable_l2_filtering) +		veb_flags |= I40E_AQC_ADD_VEB_ENABLE_L2_FILTER; +  	cmd->veb_flags = cpu_to_le16(veb_flags);  	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); @@ -922,10 +1475,10 @@ i40e_status i40e_aq_add_veb(struct i40e_hw *hw, u16 uplink_seid,   * @hw: pointer to the hw struct   * @veb_seid: the SEID of the VEB to query   * @switch_id: the uplink switch id - * @floating_veb: set to true if the VEB is floating + * @floating: set to true if the VEB is floating   * @statistic_index: index of the stats counter block for this VEB   * @vebs_used: number of VEB's used by function - * @vebs_unallocated: total VEB's not reserved by any function + * @vebs_free: total VEB's not reserved by any function   * @cmd_details: pointer to command details structure or NULL   *   * This retrieves the parameters for a particular VEB, specified by @@ -1059,89 +1612,11 @@ i40e_status i40e_aq_remove_macvlan(struct i40e_hw *hw, u16 seid,  }  /** - * i40e_aq_add_vlan - Add VLAN ids to the HW filtering - * @hw: pointer to the hw struct - * @seid: VSI for the vlan filters - * @v_list: list of vlan filters to be added - * @count: length of the list - * @cmd_details: pointer to command details structure or NULL - **/ -i40e_status i40e_aq_add_vlan(struct i40e_hw *hw, u16 seid, -			struct i40e_aqc_add_remove_vlan_element_data *v_list, -			u8 count, struct i40e_asq_cmd_details *cmd_details) -{ -	struct i40e_aq_desc desc; -	struct i40e_aqc_macvlan *cmd = -		(struct i40e_aqc_macvlan *)&desc.params.raw; -	i40e_status status; -	u16 buf_size; - -	if (count == 0 || !v_list || !hw) -		return I40E_ERR_PARAM; - -	buf_size = count * sizeof(struct i40e_aqc_add_remove_vlan_element_data); - -	/* prep the rest of the request */ -	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_vlan); -	cmd->num_addresses = cpu_to_le16(count); -	cmd->seid[0] = cpu_to_le16(seid | I40E_AQC_MACVLAN_CMD_SEID_VALID); -	cmd->seid[1] = 0; -	cmd->seid[2] = 0; - -	desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); -	if (buf_size > I40E_AQ_LARGE_BUF) -		desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB); - -	status = i40e_asq_send_command(hw, &desc, v_list, buf_size, -				       cmd_details); - -	return status; -} - -/** - * i40e_aq_remove_vlan - Remove VLANs from the HW filtering - * @hw: pointer to the hw struct - * @seid: VSI for the vlan filters - * @v_list: list of macvlans to be removed - * @count: length of the list - * @cmd_details: pointer to command details structure or NULL - **/ -i40e_status i40e_aq_remove_vlan(struct i40e_hw *hw, u16 seid, -			struct i40e_aqc_add_remove_vlan_element_data *v_list, -			u8 count, struct i40e_asq_cmd_details *cmd_details) -{ -	struct i40e_aq_desc desc; -	struct i40e_aqc_macvlan *cmd = -		(struct i40e_aqc_macvlan *)&desc.params.raw; -	i40e_status status; -	u16 buf_size; - -	if (count == 0 || !v_list || !hw) -		return I40E_ERR_PARAM; - -	buf_size = count * sizeof(struct i40e_aqc_add_remove_vlan_element_data); - -	/* prep the rest of the request */ -	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_remove_vlan); -	cmd->num_addresses = cpu_to_le16(count); -	cmd->seid[0] = cpu_to_le16(seid | I40E_AQC_MACVLAN_CMD_SEID_VALID); -	cmd->seid[1] = 0; -	cmd->seid[2] = 0; - -	desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF | I40E_AQ_FLAG_RD)); -	if (buf_size > I40E_AQ_LARGE_BUF) -		desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB); - -	status = i40e_asq_send_command(hw, &desc, v_list, buf_size, -				       cmd_details); - -	return status; -} - -/**   * i40e_aq_send_msg_to_vf   * @hw: pointer to the hardware structure   * @vfid: vf id to send msg + * @v_opcode: opcodes for VF-PF communication + * @v_retval: return error code   * @msg: pointer to the msg buffer   * @msglen: msg length   * @cmd_details: pointer to command details @@ -1371,9 +1846,9 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,  	cap = (struct i40e_aqc_list_capabilities_element_resp *) buff;  	if (list_type_opc == i40e_aqc_opc_list_dev_capabilities) -		p = (struct i40e_hw_capabilities *)&hw->dev_caps; +		p = &hw->dev_caps;  	else if (list_type_opc == i40e_aqc_opc_list_func_capabilities) -		p = (struct i40e_hw_capabilities *)&hw->func_caps; +		p = &hw->func_caps;  	else  		return; @@ -1496,6 +1971,12 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,  		}  	} +	/* Software override ensuring FCoE is disabled if npar or mfp +	 * mode because it is not supported in these modes. +	 */ +	if (p->npar_enable || p->mfp_mode_1) +		p->fcoe = false; +  	/* additional HW specific goodies that might  	 * someday be HW version specific  	 */ @@ -1519,8 +2000,8 @@ i40e_status i40e_aq_discover_capabilities(struct i40e_hw *hw,  				struct i40e_asq_cmd_details *cmd_details)  {  	struct i40e_aqc_list_capabilites *cmd; -	i40e_status status = 0;  	struct i40e_aq_desc desc; +	i40e_status status = 0;  	cmd = (struct i40e_aqc_list_capabilites *)&desc.params.raw; @@ -1681,6 +2162,63 @@ i40e_status i40e_aq_start_lldp(struct i40e_hw *hw,  }  /** + * i40e_aq_add_udp_tunnel + * @hw: pointer to the hw struct + * @udp_port: the UDP port to add + * @header_len: length of the tunneling header length in DWords + * @protocol_index: protocol index type + * @filter_index: pointer to filter index + * @cmd_details: pointer to command details structure or NULL + **/ +i40e_status i40e_aq_add_udp_tunnel(struct i40e_hw *hw, +				u16 udp_port, u8 protocol_index, +				u8 *filter_index, +				struct i40e_asq_cmd_details *cmd_details) +{ +	struct i40e_aq_desc desc; +	struct i40e_aqc_add_udp_tunnel *cmd = +		(struct i40e_aqc_add_udp_tunnel *)&desc.params.raw; +	struct i40e_aqc_del_udp_tunnel_completion *resp = +		(struct i40e_aqc_del_udp_tunnel_completion *)&desc.params.raw; +	i40e_status status; + +	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_add_udp_tunnel); + +	cmd->udp_port = cpu_to_le16(udp_port); +	cmd->protocol_type = protocol_index; + +	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + +	if (!status) +		*filter_index = resp->index; + +	return status; +} + +/** + * i40e_aq_del_udp_tunnel + * @hw: pointer to the hw struct + * @index: filter index + * @cmd_details: pointer to command details structure or NULL + **/ +i40e_status i40e_aq_del_udp_tunnel(struct i40e_hw *hw, u8 index, +				struct i40e_asq_cmd_details *cmd_details) +{ +	struct i40e_aq_desc desc; +	struct i40e_aqc_remove_udp_tunnel *cmd = +		(struct i40e_aqc_remove_udp_tunnel *)&desc.params.raw; +	i40e_status status; + +	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_del_udp_tunnel); + +	cmd->index = index; + +	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + +	return status; +} + +/**   * i40e_aq_delete_element - Delete switch element   * @hw: pointer to the hw struct   * @seid: the SEID to delete from the switch @@ -1709,6 +2247,28 @@ i40e_status i40e_aq_delete_element(struct i40e_hw *hw, u16 seid,  }  /** + * i40e_aq_dcb_updated - DCB Updated Command + * @hw: pointer to the hw struct + * @cmd_details: pointer to command details structure or NULL + * + * EMP will return when the shared RPB settings have been + * recomputed and modified. The retval field in the descriptor + * will be set to 0 when RPB is modified. + **/ +i40e_status i40e_aq_dcb_updated(struct i40e_hw *hw, +				struct i40e_asq_cmd_details *cmd_details) +{ +	struct i40e_aq_desc desc; +	i40e_status status; + +	i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_dcb_updated); + +	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + +	return status; +} + +/**   * i40e_aq_tx_sched_cmd - generic Tx scheduler AQ command handler   * @hw: pointer to the hw struct   * @seid: seid for the physical port/switching component/vsi @@ -1770,6 +2330,35 @@ static i40e_status i40e_aq_tx_sched_cmd(struct i40e_hw *hw, u16 seid,  }  /** + * i40e_aq_config_vsi_bw_limit - Configure VSI BW Limit + * @hw: pointer to the hw struct + * @seid: VSI seid + * @credit: BW limit credits (0 = disabled) + * @max_credit: Max BW limit credits + * @cmd_details: pointer to command details structure or NULL + **/ +i40e_status i40e_aq_config_vsi_bw_limit(struct i40e_hw *hw, +				u16 seid, u16 credit, u8 max_credit, +				struct i40e_asq_cmd_details *cmd_details) +{ +	struct i40e_aq_desc desc; +	struct i40e_aqc_configure_vsi_bw_limit *cmd = +		(struct i40e_aqc_configure_vsi_bw_limit *)&desc.params.raw; +	i40e_status status; + +	i40e_fill_default_direct_cmd_desc(&desc, +					  i40e_aqc_opc_configure_vsi_bw_limit); + +	cmd->vsi_seid = cpu_to_le16(seid); +	cmd->credit = cpu_to_le16(credit); +	cmd->max_credit = max_credit; + +	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + +	return status; +} + +/**   * i40e_aq_config_vsi_tc_bw - Config VSI BW Allocation per TC   * @hw: pointer to the hw struct   * @seid: VSI seid @@ -1787,6 +2376,40 @@ i40e_status i40e_aq_config_vsi_tc_bw(struct i40e_hw *hw,  }  /** + * i40e_aq_config_switch_comp_ets - Enable/Disable/Modify ETS on the port + * @hw: pointer to the hw struct + * @seid: seid of the switching component connected to Physical Port + * @ets_data: Buffer holding ETS parameters + * @cmd_details: pointer to command details structure or NULL + **/ +i40e_status i40e_aq_config_switch_comp_ets(struct i40e_hw *hw, +		u16 seid, +		struct i40e_aqc_configure_switching_comp_ets_data *ets_data, +		enum i40e_admin_queue_opc opcode, +		struct i40e_asq_cmd_details *cmd_details) +{ +	return i40e_aq_tx_sched_cmd(hw, seid, (void *)ets_data, +				    sizeof(*ets_data), opcode, cmd_details); +} + +/** + * i40e_aq_config_switch_comp_bw_config - Config Switch comp BW Alloc per TC + * @hw: pointer to the hw struct + * @seid: seid of the switching component + * @bw_data: Buffer holding enabled TCs, relative/absolute TC BW limit/credits + * @cmd_details: pointer to command details structure or NULL + **/ +i40e_status i40e_aq_config_switch_comp_bw_config(struct i40e_hw *hw, +	u16 seid, +	struct i40e_aqc_configure_switching_comp_bw_config_data *bw_data, +	struct i40e_asq_cmd_details *cmd_details) +{ +	return i40e_aq_tx_sched_cmd(hw, seid, (void *)bw_data, sizeof(*bw_data), +			    i40e_aqc_opc_configure_switching_comp_bw_config, +			    cmd_details); +} + +/**   * i40e_aq_query_vsi_bw_config - Query VSI BW configuration   * @hw: pointer to the hw struct   * @seid: seid of the VSI @@ -1888,7 +2511,7 @@ static i40e_status i40e_validate_filter_settings(struct i40e_hw *hw,  {  	u32 fcoe_cntx_size, fcoe_filt_size;  	u32 pe_cntx_size, pe_filt_size; -	u32 fcoe_fmax, pe_fmax; +	u32 fcoe_fmax;  	u32 val;  	/* Validate FCoE settings passed */ @@ -1963,13 +2586,6 @@ static i40e_status i40e_validate_filter_settings(struct i40e_hw *hw,  	if (fcoe_filt_size + fcoe_cntx_size >  fcoe_fmax)  		return I40E_ERR_INVALID_SIZE; -	/* PEHSIZE + PEDSIZE should not be greater than PMPEXFMAX */ -	val = rd32(hw, I40E_GLHMC_PEXFMAX); -	pe_fmax = (val & I40E_GLHMC_PEXFMAX_PMPEXFMAX_MASK) -		   >> I40E_GLHMC_PEXFMAX_PMPEXFMAX_SHIFT; -	if (pe_filt_size + pe_cntx_size >  pe_fmax) -		return I40E_ERR_INVALID_SIZE; -  	return 0;  } @@ -2039,3 +2655,110 @@ i40e_status i40e_set_filter_control(struct i40e_hw *hw,  	return 0;  } + +/** + * i40e_aq_add_rem_control_packet_filter - Add or Remove Control Packet Filter + * @hw: pointer to the hw struct + * @mac_addr: MAC address to use in the filter + * @ethtype: Ethertype to use in the filter + * @flags: Flags that needs to be applied to the filter + * @vsi_seid: seid of the control VSI + * @queue: VSI queue number to send the packet to + * @is_add: Add control packet filter if True else remove + * @stats: Structure to hold information on control filter counts + * @cmd_details: pointer to command details structure or NULL + * + * This command will Add or Remove control packet filter for a control VSI. + * In return it will update the total number of perfect filter count in + * the stats member. + **/ +i40e_status i40e_aq_add_rem_control_packet_filter(struct i40e_hw *hw, +				u8 *mac_addr, u16 ethtype, u16 flags, +				u16 vsi_seid, u16 queue, bool is_add, +				struct i40e_control_filter_stats *stats, +				struct i40e_asq_cmd_details *cmd_details) +{ +	struct i40e_aq_desc desc; +	struct i40e_aqc_add_remove_control_packet_filter *cmd = +		(struct i40e_aqc_add_remove_control_packet_filter *) +		&desc.params.raw; +	struct i40e_aqc_add_remove_control_packet_filter_completion *resp = +		(struct i40e_aqc_add_remove_control_packet_filter_completion *) +		&desc.params.raw; +	i40e_status status; + +	if (vsi_seid == 0) +		return I40E_ERR_PARAM; + +	if (is_add) { +		i40e_fill_default_direct_cmd_desc(&desc, +				i40e_aqc_opc_add_control_packet_filter); +		cmd->queue = cpu_to_le16(queue); +	} else { +		i40e_fill_default_direct_cmd_desc(&desc, +				i40e_aqc_opc_remove_control_packet_filter); +	} + +	if (mac_addr) +		memcpy(cmd->mac, mac_addr, ETH_ALEN); + +	cmd->etype = cpu_to_le16(ethtype); +	cmd->flags = cpu_to_le16(flags); +	cmd->seid = cpu_to_le16(vsi_seid); + +	status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details); + +	if (!status && stats) { +		stats->mac_etype_used = le16_to_cpu(resp->mac_etype_used); +		stats->etype_used = le16_to_cpu(resp->etype_used); +		stats->mac_etype_free = le16_to_cpu(resp->mac_etype_free); +		stats->etype_free = le16_to_cpu(resp->etype_free); +	} + +	return status; +} + +/** + * i40e_set_pci_config_data - store PCI bus info + * @hw: pointer to hardware structure + * @link_status: the link status word from PCI config space + * + * Stores the PCI bus info (speed, width, type) within the i40e_hw structure + **/ +void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status) +{ +	hw->bus.type = i40e_bus_type_pci_express; + +	switch (link_status & PCI_EXP_LNKSTA_NLW) { +	case PCI_EXP_LNKSTA_NLW_X1: +		hw->bus.width = i40e_bus_width_pcie_x1; +		break; +	case PCI_EXP_LNKSTA_NLW_X2: +		hw->bus.width = i40e_bus_width_pcie_x2; +		break; +	case PCI_EXP_LNKSTA_NLW_X4: +		hw->bus.width = i40e_bus_width_pcie_x4; +		break; +	case PCI_EXP_LNKSTA_NLW_X8: +		hw->bus.width = i40e_bus_width_pcie_x8; +		break; +	default: +		hw->bus.width = i40e_bus_width_unknown; +		break; +	} + +	switch (link_status & PCI_EXP_LNKSTA_CLS) { +	case PCI_EXP_LNKSTA_CLS_2_5GB: +		hw->bus.speed = i40e_bus_speed_2500; +		break; +	case PCI_EXP_LNKSTA_CLS_5_0GB: +		hw->bus.speed = i40e_bus_speed_5000; +		break; +	case PCI_EXP_LNKSTA_CLS_8_0GB: +		hw->bus.speed = i40e_bus_speed_8000; +		break; +	default: +		hw->bus.speed = i40e_bus_speed_unknown; +		break; +	} +}  | 
