Commit 2995aea5 authored by David S. Miller's avatar David S. Miller

Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/jkirsher/next-queue

Jeff Kirsher says:

====================
40GbE Intel Wired LAN Driver Updates 2016-04-27

This series contains updates to i40e and i40evf.

Alex Duyck cleans up the feature flags since they are becoming pretty
"massive", the primary change being that we now build our features list
around hw_encap_features.  Added support for IPIP and SIT offloads,
which should improvement in throughput for IPIP and SIT tunnels with
the offload enabled.

Mitch adds support for configuring RSS on behalf of the VFs, which removes
the burden of dealing with different hardware interfaces from the VF
drivers and improves future compatibility.  Fix to ensure that we do not
panic by checking that the vsi_res pointer is valid before dereferencing
it, after which we can drink beer and eat peanuts.

Shannon does come housekeeping in i40e_add_fdir_ethtool() in preparation
for more cloud filter work.  Added flexibility to the nvmupdate
facility by adding the ability to specify an AQ event opcode to wait on
after Exec_AQ request.

Michal adds device capability which defines if an update is available and
if a security check is needed during the update process.

Kamil just adds a device id to support X722 QSFP+ device.

Greg fixes an issue where a mirror rule ID may be zero, so do not return
invalid parameter when the user passes in a zero for a rule ID.  Adds
support to steer packets to VSIs by VLAN tag alone while being in
promiscuous mode for multicast and unicast MAC addresses.

Jesse fixes the driver from offloading the VLAN tag into the skb any
time there was a VLAN tag and the hardware stripping was enabled, to
making sure it is enabled before put_tag.

v2: Dropped patch 8 ("i40e: Allow user to change input set mask for flow
    director") while Kiran reworks a more generalized solution based
    on feedback from David Miller.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 501e7ef5 47d34839
......@@ -202,6 +202,7 @@ struct i40e_lump_tracking {
#define I40E_HKEY_ARRAY_SIZE ((I40E_PFQF_HKEY_MAX_INDEX + 1) * 4)
#define I40E_HLUT_ARRAY_SIZE ((I40E_PFQF_HLUT_MAX_INDEX + 1) * 4)
#define I40E_VF_HLUT_ARRAY_SIZE ((I40E_VFQF_HLUT1_MAX_INDEX + 1) * 4)
enum i40e_fd_stat_idx {
I40E_FD_STAT_ATR,
......
......@@ -429,6 +429,7 @@ struct i40e_aqc_list_capabilities_element_resp {
#define I40E_AQ_CAP_ID_SDP 0x0062
#define I40E_AQ_CAP_ID_MDIO 0x0063
#define I40E_AQ_CAP_ID_WSR_PROT 0x0064
#define I40E_AQ_CAP_ID_NVM_MGMT 0x0080
#define I40E_AQ_CAP_ID_FLEX10 0x00F1
#define I40E_AQ_CAP_ID_CEM 0x00F2
......
......@@ -61,6 +61,7 @@ static i40e_status i40e_set_mac_type(struct i40e_hw *hw)
case I40E_DEV_ID_1G_BASE_T_X722:
case I40E_DEV_ID_10G_BASE_T_X722:
case I40E_DEV_ID_SFP_I_X722:
case I40E_DEV_ID_QSFP_I_X722:
hw->mac.type = I40E_MAC_X722;
break;
default:
......@@ -2037,6 +2038,76 @@ i40e_status i40e_aq_set_vsi_multicast_promiscuous(struct i40e_hw *hw,
return status;
}
/**
* i40e_aq_set_vsi_mc_promisc_on_vlan
* @hw: pointer to the hw struct
* @seid: vsi number
* @enable: set MAC L2 layer unicast promiscuous enable/disable for a given VLAN
* @vid: The VLAN tag filter - capture any multicast packet with this VLAN tag
* @cmd_details: pointer to command details structure or NULL
**/
enum i40e_status_code i40e_aq_set_vsi_mc_promisc_on_vlan(struct i40e_hw *hw,
u16 seid, bool enable,
u16 vid,
struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_desc desc;
struct i40e_aqc_set_vsi_promiscuous_modes *cmd =
(struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw;
enum i40e_status_code status;
u16 flags = 0;
i40e_fill_default_direct_cmd_desc(&desc,
i40e_aqc_opc_set_vsi_promiscuous_modes);
if (enable)
flags |= I40E_AQC_SET_VSI_PROMISC_MULTICAST;
cmd->promiscuous_flags = cpu_to_le16(flags);
cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_MULTICAST);
cmd->seid = cpu_to_le16(seid);
cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID);
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
return status;
}
/**
* i40e_aq_set_vsi_uc_promisc_on_vlan
* @hw: pointer to the hw struct
* @seid: vsi number
* @enable: set MAC L2 layer unicast promiscuous enable/disable for a given VLAN
* @vid: The VLAN tag filter - capture any unicast packet with this VLAN tag
* @cmd_details: pointer to command details structure or NULL
**/
enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,
u16 seid, bool enable,
u16 vid,
struct i40e_asq_cmd_details *cmd_details)
{
struct i40e_aq_desc desc;
struct i40e_aqc_set_vsi_promiscuous_modes *cmd =
(struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw;
enum i40e_status_code status;
u16 flags = 0;
i40e_fill_default_direct_cmd_desc(&desc,
i40e_aqc_opc_set_vsi_promiscuous_modes);
if (enable)
flags |= I40E_AQC_SET_VSI_PROMISC_UNICAST;
cmd->promiscuous_flags = cpu_to_le16(flags);
cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_UNICAST);
cmd->seid = cpu_to_le16(seid);
cmd->vlan_tag = cpu_to_le16(vid | I40E_AQC_SET_VSI_VLAN_VALID);
status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
return status;
}
/**
* i40e_aq_set_vsi_broadcast
* @hw: pointer to the hw struct
......@@ -2667,10 +2738,7 @@ i40e_status i40e_aq_delete_mirrorrule(struct i40e_hw *hw, u16 sw_seid,
u16 *rules_used, u16 *rules_free)
{
/* Rule ID has to be valid except rule_type: INGRESS VLAN mirroring */
if (rule_type != I40E_AQC_MIRROR_RULE_TYPE_VLAN) {
if (!rule_id)
return I40E_ERR_PARAM;
} else {
if (rule_type == I40E_AQC_MIRROR_RULE_TYPE_VLAN) {
/* count and mr_list shall be valid for rule_type INGRESS VLAN
* mirroring. For other rule_type, count and rule_type should
* not matter.
......@@ -3138,6 +3206,12 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
p->wr_csr_prot = (u64)number;
p->wr_csr_prot |= (u64)logical_id << 32;
break;
case I40E_AQ_CAP_ID_NVM_MGMT:
if (number & I40E_NVM_MGMT_SEC_REV_DISABLED)
p->sec_rev_disabled = true;
if (number & I40E_NVM_MGMT_UPDATE_DISABLED)
p->update_disabled = true;
break;
default:
break;
}
......
......@@ -45,6 +45,7 @@
#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1
#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2
#define I40E_DEV_ID_SFP_I_X722 0x37D3
#define I40E_DEV_ID_QSFP_I_X722 0x37D4
#define i40e_is_40G_device(d) ((d) == I40E_DEV_ID_QSFP_A || \
(d) == I40E_DEV_ID_QSFP_B || \
......
......@@ -2506,7 +2506,6 @@ static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
if (!vsi)
return -EINVAL;
pf = vsi->back;
if (!(pf->flags & I40E_FLAG_FD_SB_ENABLED))
......@@ -2564,15 +2563,18 @@ static int i40e_add_fdir_ethtool(struct i40e_vsi *vsi,
input->src_ip[0] = fsp->h_u.tcp_ip4_spec.ip4dst;
if (ntohl(fsp->m_ext.data[1])) {
if (ntohl(fsp->h_ext.data[1]) >= pf->num_alloc_vfs) {
netif_info(pf, drv, vsi->netdev, "Invalid VF id\n");
vf_id = ntohl(fsp->h_ext.data[1]);
if (vf_id >= pf->num_alloc_vfs) {
netif_info(pf, drv, vsi->netdev,
"Invalid VF id %d\n", vf_id);
goto free_input;
}
vf_id = ntohl(fsp->h_ext.data[1]);
/* Find vsi id from vf id and override dest vsi */
input->dest_vsi = pf->vf[vf_id].lan_vsi_id;
if (input->q_index >= pf->vf[vf_id].num_queue_pairs) {
netif_info(pf, drv, vsi->netdev, "Invalid queue id\n");
netif_info(pf, drv, vsi->netdev,
"Invalid queue id %d for VF %d\n",
input->q_index, vf_id);
goto free_input;
}
}
......
......@@ -8082,24 +8082,45 @@ static int i40e_config_rss_reg(struct i40e_vsi *vsi, const u8 *seed,
{
struct i40e_pf *pf = vsi->back;
struct i40e_hw *hw = &pf->hw;
u16 vf_id = vsi->vf_id;
u8 i;
/* Fill out hash function seed */
if (seed) {
u32 *seed_dw = (u32 *)seed;
for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++)
i40e_write_rx_ctl(hw, I40E_PFQF_HKEY(i), seed_dw[i]);
if (vsi->type == I40E_VSI_MAIN) {
for (i = 0; i <= I40E_PFQF_HKEY_MAX_INDEX; i++)
i40e_write_rx_ctl(hw, I40E_PFQF_HKEY(i),
seed_dw[i]);
} else if (vsi->type == I40E_VSI_SRIOV) {
for (i = 0; i <= I40E_VFQF_HKEY1_MAX_INDEX; i++)
i40e_write_rx_ctl(hw,
I40E_VFQF_HKEY1(i, vf_id),
seed_dw[i]);
} else {
dev_err(&pf->pdev->dev, "Cannot set RSS seed - invalid VSI type\n");
}
}
if (lut) {
u32 *lut_dw = (u32 *)lut;
if (lut_size != I40E_HLUT_ARRAY_SIZE)
return -EINVAL;
for (i = 0; i <= I40E_PFQF_HLUT_MAX_INDEX; i++)
wr32(hw, I40E_PFQF_HLUT(i), lut_dw[i]);
if (vsi->type == I40E_VSI_MAIN) {
if (lut_size != I40E_HLUT_ARRAY_SIZE)
return -EINVAL;
for (i = 0; i <= I40E_PFQF_HLUT_MAX_INDEX; i++)
wr32(hw, I40E_PFQF_HLUT(i), lut_dw[i]);
} else if (vsi->type == I40E_VSI_SRIOV) {
if (lut_size != I40E_VF_HLUT_ARRAY_SIZE)
return -EINVAL;
for (i = 0; i <= I40E_VFQF_HLUT_MAX_INDEX; i++)
i40e_write_rx_ctl(hw,
I40E_VFQF_HLUT1(i, vf_id),
lut_dw[i]);
} else {
dev_err(&pf->pdev->dev, "Cannot set RSS LUT - invalid VSI type\n");
}
}
i40e_flush(hw);
......@@ -9111,40 +9132,38 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
np = netdev_priv(netdev);
np->vsi = vsi;
netdev->hw_enc_features |= NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM |
NETIF_F_TSO |
NETIF_F_TSO6 |
NETIF_F_TSO_ECN |
NETIF_F_GSO_GRE |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM |
netdev->hw_enc_features |= NETIF_F_SG |
NETIF_F_IP_CSUM |
NETIF_F_IPV6_CSUM |
NETIF_F_HIGHDMA |
NETIF_F_SOFT_FEATURES |
NETIF_F_TSO |
NETIF_F_TSO_ECN |
NETIF_F_TSO6 |
NETIF_F_GSO_GRE |
NETIF_F_GSO_IPIP |
NETIF_F_GSO_SIT |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_UDP_TUNNEL_CSUM |
NETIF_F_SCTP_CRC |
NETIF_F_RXHASH |
NETIF_F_RXCSUM |
0;
netdev->features = NETIF_F_SG |
NETIF_F_IP_CSUM |
NETIF_F_SCTP_CRC |
NETIF_F_HIGHDMA |
NETIF_F_GSO_UDP_TUNNEL |
NETIF_F_GSO_GRE |
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER |
NETIF_F_IPV6_CSUM |
NETIF_F_TSO |
NETIF_F_TSO_ECN |
NETIF_F_TSO6 |
NETIF_F_RXCSUM |
NETIF_F_RXHASH |
0;
if (!(pf->flags & I40E_FLAG_OUTER_UDP_CSUM_CAPABLE))
netdev->hw_enc_features ^= NETIF_F_GSO_UDP_TUNNEL_CSUM;
/* record features VLANs can make use of */
netdev->vlan_features |= netdev->hw_enc_features;
if (!(pf->flags & I40E_FLAG_MFP_ENABLED))
netdev->features |= NETIF_F_NTUPLE;
if (pf->flags & I40E_FLAG_OUTER_UDP_CSUM_CAPABLE)
netdev->features |= NETIF_F_GSO_UDP_TUNNEL_CSUM;
netdev->hw_features |= NETIF_F_NTUPLE;
/* copy netdev features into list of user selectable features */
netdev->hw_features |= netdev->features;
netdev->hw_features |= netdev->hw_enc_features |
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX;
netdev->features |= netdev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER;
if (vsi->type == I40E_VSI_MAIN) {
SET_NETDEV_DEV(netdev, &pf->pdev->dev);
......@@ -9183,12 +9202,7 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)
ether_addr_copy(netdev->dev_addr, mac_addr);
ether_addr_copy(netdev->perm_addr, mac_addr);
/* vlan gets same features (except vlan offload)
* after any tweaks for specific VSI types
*/
netdev->vlan_features = netdev->features & ~(NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER);
netdev->priv_flags |= IFF_UNICAST_FLT;
netdev->priv_flags |= IFF_SUPP_NOFCS;
/* Setup netdev TC information */
......
......@@ -693,10 +693,10 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
/* early check for status command and debug msgs */
upd_cmd = i40e_nvmupd_validate_command(hw, cmd, perrno);
i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d cmd 0x%08x config 0x%08x offset 0x%08x data_size 0x%08x\n",
i40e_debug(hw, I40E_DEBUG_NVM, "%s state %d nvm_release_on_hold %d opc 0x%04x cmd 0x%08x config 0x%08x offset 0x%08x data_size 0x%08x\n",
i40e_nvm_update_state_str[upd_cmd],
hw->nvmupd_state,
hw->nvm_release_on_done,
hw->nvm_release_on_done, hw->nvm_wait_opcode,
cmd->command, cmd->config, cmd->offset, cmd->data_size);
if (upd_cmd == I40E_NVMUPD_INVALID) {
......@@ -710,7 +710,18 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
* going into the state machine
*/
if (upd_cmd == I40E_NVMUPD_STATUS) {
if (!cmd->data_size) {
*perrno = -EFAULT;
return I40E_ERR_BUF_TOO_SHORT;
}
bytes[0] = hw->nvmupd_state;
if (cmd->data_size >= 4) {
bytes[1] = 0;
*((u16 *)&bytes[2]) = hw->nvm_wait_opcode;
}
return 0;
}
......@@ -729,6 +740,14 @@ i40e_status i40e_nvmupd_command(struct i40e_hw *hw,
case I40E_NVMUPD_STATE_INIT_WAIT:
case I40E_NVMUPD_STATE_WRITE_WAIT:
/* if we need to stop waiting for an event, clear
* the wait info and return before doing anything else
*/
if (cmd->offset == 0xffff) {
i40e_nvmupd_check_wait_event(hw, hw->nvm_wait_opcode);
return 0;
}
status = I40E_ERR_NOT_READY;
*perrno = -EBUSY;
break;
......@@ -800,6 +819,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
i40e_release_nvm(hw);
} else {
hw->nvm_release_on_done = true;
hw->nvm_wait_opcode = i40e_aqc_opc_nvm_erase;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
}
}
......@@ -816,6 +836,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
i40e_release_nvm(hw);
} else {
hw->nvm_release_on_done = true;
hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
}
}
......@@ -828,10 +849,12 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
hw->aq.asq_last_status);
} else {
status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
if (status)
if (status) {
i40e_release_nvm(hw);
else
} else {
hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
}
}
break;
......@@ -850,6 +873,7 @@ static i40e_status i40e_nvmupd_state_init(struct i40e_hw *hw,
i40e_release_nvm(hw);
} else {
hw->nvm_release_on_done = true;
hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
}
}
......@@ -940,8 +964,10 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
switch (upd_cmd) {
case I40E_NVMUPD_WRITE_CON:
status = i40e_nvmupd_nvm_write(hw, cmd, bytes, perrno);
if (!status)
if (!status) {
hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
}
break;
case I40E_NVMUPD_WRITE_LCB:
......@@ -954,6 +980,7 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
} else {
hw->nvm_release_on_done = true;
hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
}
break;
......@@ -967,6 +994,7 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
-EIO;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
} else {
hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
hw->nvmupd_state = I40E_NVMUPD_STATE_WRITE_WAIT;
}
break;
......@@ -981,6 +1009,7 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT;
} else {
hw->nvm_release_on_done = true;
hw->nvm_wait_opcode = i40e_aqc_opc_nvm_update;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
}
break;
......@@ -1036,14 +1065,14 @@ static i40e_status i40e_nvmupd_state_writing(struct i40e_hw *hw,
**/
void i40e_nvmupd_check_wait_event(struct i40e_hw *hw, u16 opcode)
{
if (opcode == i40e_aqc_opc_nvm_erase ||
opcode == i40e_aqc_opc_nvm_update) {
if (opcode == hw->nvm_wait_opcode) {
i40e_debug(hw, I40E_DEBUG_NVM,
"NVMUPD: clearing wait on opcode 0x%04x\n", opcode);
if (hw->nvm_release_on_done) {
i40e_release_nvm(hw);
hw->nvm_release_on_done = false;
}
hw->nvm_wait_opcode = 0;
switch (hw->nvmupd_state) {
case I40E_NVMUPD_STATE_INIT_WAIT:
......@@ -1220,6 +1249,12 @@ static i40e_status i40e_nvmupd_exec_aq(struct i40e_hw *hw,
*perrno = i40e_aq_rc_to_posix(status, hw->aq.asq_last_status);
}
/* should we wait for a followup event? */
if (cmd->offset) {
hw->nvm_wait_opcode = cmd->offset;
hw->nvmupd_state = I40E_NVMUPD_STATE_INIT_WAIT;
}
return status;
}
......
......@@ -133,6 +133,14 @@ i40e_status i40e_aq_set_vsi_unicast_promiscuous(struct i40e_hw *hw,
u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_set_vsi_multicast_promiscuous(struct i40e_hw *hw,
u16 vsi_id, bool set, struct i40e_asq_cmd_details *cmd_details);
enum i40e_status_code i40e_aq_set_vsi_mc_promisc_on_vlan(struct i40e_hw *hw,
u16 seid, bool enable,
u16 vid,
struct i40e_asq_cmd_details *cmd_details);
enum i40e_status_code i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,
u16 seid, bool enable,
u16 vid,
struct i40e_asq_cmd_details *cmd_details);
i40e_status i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw,
u16 seid, bool enable,
struct i40e_asq_cmd_details *cmd_details);
......
......@@ -1370,7 +1370,8 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring,
{
struct i40e_q_vector *q_vector = rx_ring->q_vector;
if (vlan_tag & VLAN_VID_MASK)
if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
(vlan_tag & VLAN_VID_MASK))
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
napi_gro_receive(&q_vector->napi, skb);
......@@ -2299,7 +2300,10 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
ip.v6->payload_len = 0;
}
if (skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | SKB_GSO_GRE |
if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
SKB_GSO_IPIP |
SKB_GSO_SIT |
SKB_GSO_UDP_TUNNEL |
SKB_GSO_UDP_TUNNEL_CSUM)) {
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM) {
/* determine offset of outer transport header */
......@@ -2442,13 +2446,6 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
&l4_proto, &frag_off);
}
/* compute outer L3 header size */
tunnel |= ((l4.hdr - ip.hdr) / 4) <<
I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT;
/* switch IP header pointer from outer to inner header */
ip.hdr = skb_inner_network_header(skb);
/* define outer transport */
switch (l4_proto) {
case IPPROTO_UDP:
......@@ -2459,6 +2456,11 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
tunnel |= I40E_TXD_CTX_GRE_TUNNELING;
*tx_flags |= I40E_TX_FLAGS_UDP_TUNNEL;
break;
case IPPROTO_IPIP:
case IPPROTO_IPV6:
*tx_flags |= I40E_TX_FLAGS_UDP_TUNNEL;
l4.hdr = skb_inner_network_header(skb);
break;
default:
if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
......@@ -2467,6 +2469,13 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
return 0;
}
/* compute outer L3 header size */
tunnel |= ((l4.hdr - ip.hdr) / 4) <<
I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT;
/* switch IP header pointer from outer to inner header */
ip.hdr = skb_inner_network_header(skb);
/* compute tunnel header size */
tunnel |= ((ip.hdr - l4.hdr) / 2) <<
I40E_TXD_CTX_QW0_NATLEN_SHIFT;
......
......@@ -275,6 +275,11 @@ struct i40e_hw_capabilities {
#define I40E_FLEX10_STATUS_DCC_ERROR 0x1
#define I40E_FLEX10_STATUS_VC_MODE 0x2
bool sec_rev_disabled;
bool update_disabled;
#define I40E_NVM_MGMT_SEC_REV_DISABLED 0x1
#define I40E_NVM_MGMT_UPDATE_DISABLED 0x2
bool mgmt_cem;
bool ieee_1588;
bool iwarp;
......@@ -550,6 +555,7 @@ struct i40e_hw {
struct i40e_aq_desc nvm_wb_desc;
struct i40e_virt_mem nvm_buff;
bool nvm_release_on_done;
u16 nvm_wait_opcode;
/* HMC info */
struct i40e_hmc_info hmc; /* HMC info struct */
......
......@@ -61,6 +61,8 @@ enum i40e_vf_states {
I40E_VF_STAT_IWARPENA,
I40E_VF_STAT_FCOEENA,
I40E_VF_STAT_DISABLED,
I40E_VF_STAT_MC_PROMISC,
I40E_VF_STAT_UC_PROMISC,
};
/* VF capabilities */
......
......@@ -426,6 +426,7 @@ struct i40e_aqc_list_capabilities_element_resp {
#define I40E_AQ_CAP_ID_SDP 0x0062
#define I40E_AQ_CAP_ID_MDIO 0x0063
#define I40E_AQ_CAP_ID_WSR_PROT 0x0064
#define I40E_AQ_CAP_ID_NVM_MGMT 0x0080
#define I40E_AQ_CAP_ID_FLEX10 0x00F1
#define I40E_AQ_CAP_ID_CEM 0x00F2
......
......@@ -59,6 +59,7 @@ i40e_status i40e_set_mac_type(struct i40e_hw *hw)
case I40E_DEV_ID_1G_BASE_T_X722:
case I40E_DEV_ID_10G_BASE_T_X722:
case I40E_DEV_ID_SFP_I_X722:
case I40E_DEV_ID_QSFP_I_X722:
hw->mac.type = I40E_MAC_X722;
break;
case I40E_DEV_ID_X722_VF:
......
......@@ -45,6 +45,7 @@
#define I40E_DEV_ID_1G_BASE_T_X722 0x37D1
#define I40E_DEV_ID_10G_BASE_T_X722 0x37D2
#define I40E_DEV_ID_SFP_I_X722 0x37D3
#define I40E_DEV_ID_QSFP_I_X722 0x37D4
#define I40E_DEV_ID_X722_VF 0x37CD
#define I40E_DEV_ID_X722_VF_HV 0x37D9
......
......@@ -842,7 +842,8 @@ static void i40e_receive_skb(struct i40e_ring *rx_ring,
{
struct i40e_q_vector *q_vector = rx_ring->q_vector;
if (vlan_tag & VLAN_VID_MASK)
if ((rx_ring->netdev->features & NETIF_F_HW_VLAN_CTAG_RX) &&
(vlan_tag & VLAN_VID_MASK))
__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag);
napi_gro_receive(&q_vector->napi, skb);
......@@ -1564,7 +1565,10 @@ static int i40e_tso(struct sk_buff *skb, u8 *hdr_len, u64 *cd_type_cmd_tso_mss)
ip.v6->payload_len = 0;
}
if (skb_shinfo(skb)->gso_type & (SKB_GSO_UDP_TUNNEL | SKB_GSO_GRE |
if (skb_shinfo(skb)->gso_type & (SKB_GSO_GRE |
SKB_GSO_IPIP |
SKB_GSO_SIT |
SKB_GSO_UDP_TUNNEL |
SKB_GSO_UDP_TUNNEL_CSUM)) {
if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM) {
/* determine offset of outer transport header */
......@@ -1665,13 +1669,6 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
&l4_proto, &frag_off);
}
/* compute outer L3 header size */
tunnel |= ((l4.hdr - ip.hdr) / 4) <<
I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT;
/* switch IP header pointer from outer to inner header */
ip.hdr = skb_inner_network_header(skb);
/* define outer transport */
switch (l4_proto) {
case IPPROTO_UDP:
......@@ -1682,6 +1679,11 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
tunnel |= I40E_TXD_CTX_GRE_TUNNELING;
*tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
break;
case IPPROTO_IPIP:
case IPPROTO_IPV6:
*tx_flags |= I40E_TX_FLAGS_VXLAN_TUNNEL;
l4.hdr = skb_inner_network_header(skb);
break;
default:
if (*tx_flags & I40E_TX_FLAGS_TSO)
return -1;
......@@ -1690,6 +1692,13 @@ static int i40e_tx_enable_csum(struct sk_buff *skb, u32 *tx_flags,
return 0;
}
/* compute outer L3 header size */
tunnel |= ((l4.hdr - ip.hdr) / 4) <<
I40E_TXD_CTX_QW0_EXT_IPLEN_SHIFT;
/* switch IP header pointer from outer to inner header */
ip.hdr = skb_inner_network_header(skb);
/* compute tunnel header size */
tunnel |= ((ip.hdr - l4.hdr) / 2) <<
I40E_TXD_CTX_QW0_NATLEN_SHIFT;
......
......@@ -258,6 +258,11 @@ struct i40e_hw_capabilities {
#define I40E_FLEX10_STATUS_DCC_ERROR 0x1
#define I40E_FLEX10_STATUS_VC_MODE 0x2
bool sec_rev_disabled;
bool update_disabled;
#define I40E_NVM_MGMT_SEC_REV_DISABLED 0x1
#define I40E_NVM_MGMT_UPDATE_DISABLED 0x2
bool mgmt_cem;
bool ieee_1588;
bool iwarp;
......@@ -523,6 +528,7 @@ struct i40e_hw {
struct i40e_aq_desc nvm_wb_desc;
struct i40e_virt_mem nvm_buff;
bool nvm_release_on_done;
u16 nvm_wait_opcode;
/* HMC info */
struct i40e_hmc_info hmc; /* HMC info struct */
......
......@@ -67,8 +67,6 @@ struct i40e_vsi {
u16 rx_itr_setting;
u16 tx_itr_setting;
u16 qs_handle;
u8 *rss_hkey_user; /* User configured hash keys */
u8 *rss_lut_user; /* User configured lookup table entries */
};
/* How many Rx Buffers do we bundle into one write to the hardware ? */
......@@ -222,6 +220,7 @@ struct i40evf_adapter {
#define I40EVF_FLAG_WB_ON_ITR_CAPABLE BIT(11)
#define I40EVF_FLAG_OUTER_UDP_CSUM_CAPABLE BIT(12)
#define I40EVF_FLAG_ADDR_SET_BY_PF BIT(13)
#define I40EVF_FLAG_PROMISC_ON BIT(15)
/* duplicates for common code */
#define I40E_FLAG_FDIR_ATR_ENABLED 0
#define I40E_FLAG_DCB_ENABLED 0
......@@ -239,8 +238,15 @@ struct i40evf_adapter {
#define I40EVF_FLAG_AQ_CONFIGURE_QUEUES BIT(6)
#define I40EVF_FLAG_AQ_MAP_VECTORS BIT(7)
#define I40EVF_FLAG_AQ_HANDLE_RESET BIT(8)
#define I40EVF_FLAG_AQ_CONFIGURE_RSS BIT(9)
#define I40EVF_FLAG_AQ_CONFIGURE_RSS BIT(9) /* direct AQ config */
#define I40EVF_FLAG_AQ_GET_CONFIG BIT(10)
/* Newer style, RSS done by the PF so we can ignore hardware vagaries. */
#define I40EVF_FLAG_AQ_GET_HENA BIT(11)
#define I40EVF_FLAG_AQ_SET_HENA BIT(12)
#define I40EVF_FLAG_AQ_SET_RSS_KEY BIT(13)
#define I40EVF_FLAG_AQ_SET_RSS_LUT BIT(14)
#define I40EVF_FLAG_AQ_REQUEST_PROMISC BIT(15)
#define I40EVF_FLAG_AQ_RELEASE_PROMISC BIT(16)
/* OS defined structs */
struct net_device *netdev;
......@@ -256,10 +262,18 @@ struct i40evf_adapter {
bool netdev_registered;
bool link_up;
enum i40e_virtchnl_ops current_op;
#define CLIENT_ENABLED(_a) ((_a)->vf_res->vf_offload_flags & \
I40E_VIRTCHNL_VF_OFFLOAD_IWARP)
#define CLIENT_ENABLED(_a) ((_a)->vf_res ? \
(_a)->vf_res->vf_offload_flags & \
I40E_VIRTCHNL_VF_OFFLOAD_IWARP : \
0)
/* RSS by the PF should be preferred over RSS via other methods. */
#define RSS_PF(_a) ((_a)->vf_res->vf_offload_flags & \
I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)
#define RSS_AQ(_a) ((_a)->vf_res->vf_offload_flags & \
I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ)
#define RSS_REG(_a) (!((_a)->vf_res->vf_offload_flags & \
(I40E_VIRTCHNL_VF_OFFLOAD_RSS_AQ | \
I40E_VIRTCHNL_VF_OFFLOAD_RSS_PF)))
#define VLAN_ALLOWED(_a) ((_a)->vf_res->vf_offload_flags & \
I40E_VIRTCHNL_VF_OFFLOAD_VLAN)
struct i40e_virtchnl_vf_resource *vf_res; /* incl. all VSIs */
......@@ -271,6 +285,12 @@ struct i40evf_adapter {
struct i40e_eth_stats current_stats;
struct i40e_vsi vsi;
u32 aq_wait_count;
/* RSS stuff */
u64 hena;
u16 rss_key_size;
u16 rss_lut_size;
u8 *rss_key;
u8 *rss_lut;
};
......@@ -314,11 +334,12 @@ void i40evf_del_vlans(struct i40evf_adapter *adapter);
void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags);
void i40evf_request_stats(struct i40evf_adapter *adapter);
void i40evf_request_reset(struct i40evf_adapter *adapter);
void i40evf_get_hena(struct i40evf_adapter *adapter);
void i40evf_set_hena(struct i40evf_adapter *adapter);
void i40evf_set_rss_key(struct i40evf_adapter *adapter);
void i40evf_set_rss_lut(struct i40evf_adapter *adapter);
void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
enum i40e_virtchnl_ops v_opcode,
i40e_status v_retval, u8 *msg, u16 msglen);
int i40evf_config_rss(struct i40e_vsi *vsi, const u8 *seed, u8 *lut,
u16 lut_size);
int i40evf_get_rss(struct i40e_vsi *vsi, const u8 *seed, u8 *lut,
u16 lut_size);
int i40evf_config_rss(struct i40evf_adapter *adapter);
#endif /* _I40EVF_H_ */
......@@ -387,20 +387,16 @@ static int i40evf_set_coalesce(struct net_device *netdev,
static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter,
struct ethtool_rxnfc *cmd)
{
struct i40e_hw *hw = &adapter->hw;
u64 hena = (u64)rd32(hw, I40E_VFQF_HENA(0)) |
((u64)rd32(hw, I40E_VFQF_HENA(1)) << 32);
/* We always hash on IP src and dest addresses */
cmd->data = RXH_IP_SRC | RXH_IP_DST;
switch (cmd->flow_type) {
case TCP_V4_FLOW:
if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP))
if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP))
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
break;
case UDP_V4_FLOW:
if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP))
if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP))
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
break;
......@@ -412,11 +408,11 @@ static int i40evf_get_rss_hash_opts(struct i40evf_adapter *adapter,
break;
case TCP_V6_FLOW:
if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP))
if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP))
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
break;
case UDP_V6_FLOW:
if (hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP))
if (adapter->hena & BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP))
cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
break;
......@@ -476,9 +472,6 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter,
struct i40e_hw *hw = &adapter->hw;
u32 flags = adapter->vf_res->vf_offload_flags;
u64 hena = (u64)rd32(hw, I40E_VFQF_HENA(0)) |
((u64)rd32(hw, I40E_VFQF_HENA(1)) << 32);
/* RSS does not support anything other than hashing
* to queues on src and dst IPs and ports
*/
......@@ -495,10 +488,11 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter,
case TCP_V4_FLOW:
if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
hena |=
adapter->hena |=
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP_SYN_NO_ACK);
hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
adapter->hena |=
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_TCP);
} else {
return -EINVAL;
}
......@@ -506,10 +500,11 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter,
case TCP_V6_FLOW:
if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
hena |=
adapter->hena |=
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP_SYN_NO_ACK);
hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
adapter->hena |=
BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_TCP);
} else {
return -EINVAL;
}
......@@ -517,11 +512,12 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter,
case UDP_V4_FLOW:
if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
hena |=
adapter->hena |=
BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV4_UDP) |
BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV4_UDP);
hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
adapter->hena |=
(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_UDP) |
BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
} else {
return -EINVAL;
......@@ -530,11 +526,12 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter,
case UDP_V6_FLOW:
if (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
if (flags & I40E_VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2)
hena |=
adapter->hena |=
BIT_ULL(I40E_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) |
BIT_ULL(I40E_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP);
hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
adapter->hena |=
(BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_UDP) |
BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
} else {
return -EINVAL;
......@@ -547,7 +544,7 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter,
if ((nfc->data & RXH_L4_B_0_1) ||
(nfc->data & RXH_L4_B_2_3))
return -EINVAL;
hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER);
adapter->hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER);
break;
case AH_ESP_V6_FLOW:
case AH_V6_FLOW:
......@@ -556,23 +553,27 @@ static int i40evf_set_rss_hash_opt(struct i40evf_adapter *adapter,
if ((nfc->data & RXH_L4_B_0_1) ||
(nfc->data & RXH_L4_B_2_3))
return -EINVAL;
hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER);
adapter->hena |= BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER);
break;
case IPV4_FLOW:
hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) |
BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
adapter->hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV4_OTHER) |
BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV4));
break;
case IPV6_FLOW:
hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) |
BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
adapter->hena |= (BIT_ULL(I40E_FILTER_PCTYPE_NONF_IPV6_OTHER) |
BIT_ULL(I40E_FILTER_PCTYPE_FRAG_IPV6));
break;
default:
return -EINVAL;
}
wr32(hw, I40E_VFQF_HENA(0), (u32)hena);
wr32(hw, I40E_VFQF_HENA(1), (u32)(hena >> 32));
i40e_flush(hw);
if (RSS_PF(adapter)) {
adapter->aq_required = I40EVF_FLAG_AQ_SET_HENA;
} else {
wr32(hw, I40E_VFQF_HENA(0), (u32)adapter->hena);
wr32(hw, I40E_VFQF_HENA(1), (u32)(adapter->hena >> 32));
i40e_flush(hw);
}
return 0;
}
......@@ -623,6 +624,19 @@ static void i40evf_get_channels(struct net_device *netdev,
ch->combined_count = adapter->num_active_queues;
}
/**
* i40evf_get_rxfh_key_size - get the RSS hash key size
* @netdev: network interface device structure
*
* Returns the table size.
**/
static u32 i40evf_get_rxfh_key_size(struct net_device *netdev)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
return adapter->rss_key_size;
}
/**
* i40evf_get_rxfh_indir_size - get the rx flow hash indirection table size
* @netdev: network interface device structure
......@@ -631,7 +645,9 @@ static void i40evf_get_channels(struct net_device *netdev,
**/
static u32 i40evf_get_rxfh_indir_size(struct net_device *netdev)
{
return (I40E_VFQF_HLUT_MAX_INDEX + 1) * 4;
struct i40evf_adapter *adapter = netdev_priv(netdev);
return adapter->rss_lut_size;
}
/**
......@@ -646,9 +662,6 @@ static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
u8 *hfunc)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_vsi *vsi = &adapter->vsi;
u8 *seed = NULL, *lut;
int ret;
u16 i;
if (hfunc)
......@@ -656,24 +669,13 @@ static int i40evf_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
if (!indir)
return 0;
seed = key;
lut = kzalloc(I40EVF_HLUT_ARRAY_SIZE, GFP_KERNEL);
if (!lut)
return -ENOMEM;
ret = i40evf_get_rss(vsi, seed, lut, I40EVF_HLUT_ARRAY_SIZE);
if (ret)
goto out;
memcpy(key, adapter->rss_key, adapter->rss_key_size);
/* Each 32 bits pointed by 'indir' is stored with a lut entry */
for (i = 0; i < I40EVF_HLUT_ARRAY_SIZE; i++)
indir[i] = (u32)lut[i];
for (i = 0; i < adapter->rss_lut_size; i++)
indir[i] = (u32)adapter->rss_lut[i];
out:
kfree(lut);
return ret;
return 0;
}
/**
......@@ -689,8 +691,6 @@ static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
const u8 *key, const u8 hfunc)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);
struct i40e_vsi *vsi = &adapter->vsi;
u8 *seed = NULL;
u16 i;
/* We do not allow change in unsupported parameters */
......@@ -701,28 +701,14 @@ static int i40evf_set_rxfh(struct net_device *netdev, const u32 *indir,
return 0;
if (key) {
if (!vsi->rss_hkey_user) {
vsi->rss_hkey_user = kzalloc(I40EVF_HKEY_ARRAY_SIZE,
GFP_KERNEL);
if (!vsi->rss_hkey_user)
return -ENOMEM;
}
memcpy(vsi->rss_hkey_user, key, I40EVF_HKEY_ARRAY_SIZE);
seed = vsi->rss_hkey_user;
}
if (!vsi->rss_lut_user) {
vsi->rss_lut_user = kzalloc(I40EVF_HLUT_ARRAY_SIZE,
GFP_KERNEL);
if (!vsi->rss_lut_user)
return -ENOMEM;
memcpy(adapter->rss_key, key, adapter->rss_key_size);
}
/* Each 32 bits pointed by 'indir' is stored with a lut entry */
for (i = 0; i < I40EVF_HLUT_ARRAY_SIZE; i++)
vsi->rss_lut_user[i] = (u8)(indir[i]);
for (i = 0; i < adapter->rss_lut_size; i++)
adapter->rss_lut[i] = (u8)(indir[i]);
return i40evf_config_rss(vsi, seed, vsi->rss_lut_user,
I40EVF_HLUT_ARRAY_SIZE);
return i40evf_config_rss(adapter);
}
/**
......@@ -794,6 +780,7 @@ static const struct ethtool_ops i40evf_ethtool_ops = {
.get_rxfh = i40evf_get_rxfh,
.set_rxfh = i40evf_set_rxfh,
.get_channels = i40evf_get_channels,
.get_rxfh_key_size = i40evf_get_rxfh_key_size,
};
/**
......
......@@ -652,6 +652,17 @@ void i40evf_set_promiscuous(struct i40evf_adapter *adapter, int flags)
adapter->current_op);
return;
}
if (flags) {
adapter->flags |= I40EVF_FLAG_PROMISC_ON;
adapter->aq_required &= ~I40EVF_FLAG_AQ_REQUEST_PROMISC;
dev_info(&adapter->pdev->dev, "Entering promiscuous mode\n");
} else {
adapter->flags &= ~I40EVF_FLAG_PROMISC_ON;
adapter->aq_required &= ~I40EVF_FLAG_AQ_RELEASE_PROMISC;
dev_info(&adapter->pdev->dev, "Leaving promiscuous mode\n");
}
adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_PROMISCUOUS_MODE;
vpi.vsi_id = adapter->vsi_res->vsi_id;
vpi.flags = flags;
......@@ -681,6 +692,115 @@ void i40evf_request_stats(struct i40evf_adapter *adapter)
/* if the request failed, don't lock out others */
adapter->current_op = I40E_VIRTCHNL_OP_UNKNOWN;
}
/**
* i40evf_get_hena
* @adapter: adapter structure
*
* Request hash enable capabilities from PF
**/
void i40evf_get_hena(struct i40evf_adapter *adapter)
{
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
dev_err(&adapter->pdev->dev, "Cannot get RSS hash capabilities, command %d pending\n",
adapter->current_op);
return;
}
adapter->current_op = I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS;
adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_HENA;
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS,
NULL, 0);
}
/**
* i40evf_set_hena
* @adapter: adapter structure
*
* Request the PF to set our RSS hash capabilities
**/
void i40evf_set_hena(struct i40evf_adapter *adapter)
{
struct i40e_virtchnl_rss_hena vrh;
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
dev_err(&adapter->pdev->dev, "Cannot set RSS hash enable, command %d pending\n",
adapter->current_op);
return;
}
vrh.hena = adapter->hena;
adapter->current_op = I40E_VIRTCHNL_OP_SET_RSS_HENA;
adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_HENA;
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_SET_RSS_HENA,
(u8 *)&vrh, sizeof(vrh));
}
/**
* i40evf_set_rss_key
* @adapter: adapter structure
*
* Request the PF to set our RSS hash key
**/
void i40evf_set_rss_key(struct i40evf_adapter *adapter)
{
struct i40e_virtchnl_rss_key *vrk;
int len;
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
dev_err(&adapter->pdev->dev, "Cannot set RSS key, command %d pending\n",
adapter->current_op);
return;
}
len = sizeof(struct i40e_virtchnl_rss_key) +
(adapter->rss_key_size * sizeof(u8)) - 1;
vrk = kzalloc(len, GFP_KERNEL);
if (!vrk)
return;
vrk->vsi_id = adapter->vsi.id;
vrk->key_len = adapter->rss_key_size;
memcpy(vrk->key, adapter->rss_key, adapter->rss_key_size);
adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_RSS_KEY;
adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_RSS_KEY;
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_CONFIG_RSS_KEY,
(u8 *)vrk, len);
kfree(vrk);
}
/**
* i40evf_set_rss_lut
* @adapter: adapter structure
*
* Request the PF to set our RSS lookup table
**/
void i40evf_set_rss_lut(struct i40evf_adapter *adapter)
{
struct i40e_virtchnl_rss_lut *vrl;
int len;
if (adapter->current_op != I40E_VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
dev_err(&adapter->pdev->dev, "Cannot set RSS LUT, command %d pending\n",
adapter->current_op);
return;
}
len = sizeof(struct i40e_virtchnl_rss_lut) +
(adapter->rss_lut_size * sizeof(u8)) - 1;
vrl = kzalloc(len, GFP_KERNEL);
if (!vrl)
return;
vrl->vsi_id = adapter->vsi.id;
vrl->lut_entries = adapter->rss_lut_size;
memcpy(vrl->lut, adapter->rss_lut, adapter->rss_lut_size);
adapter->current_op = I40E_VIRTCHNL_OP_CONFIG_RSS_LUT;
adapter->aq_required &= ~I40EVF_FLAG_AQ_SET_RSS_LUT;
i40evf_send_pf_msg(adapter, I40E_VIRTCHNL_OP_CONFIG_RSS_LUT,
(u8 *)vrl, len);
kfree(vrl);
}
/**
* i40evf_request_reset
* @adapter: adapter structure
......@@ -820,6 +940,16 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
if (v_opcode != adapter->current_op)
return;
break;
case I40E_VIRTCHNL_OP_GET_RSS_HENA_CAPS: {
struct i40e_virtchnl_rss_hena *vrh =
(struct i40e_virtchnl_rss_hena *)msg;
if (msglen == sizeof(*vrh))
adapter->hena = vrh->hena;
else
dev_warn(&adapter->pdev->dev,
"Invalid message %d from PF\n", v_opcode);
}
break;
default:
if (v_opcode != adapter->current_op)
dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment