Commit 80d9f3a0 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 2018-03-14

This series contains updates to i40e and i40evf only.

Corentin Labbe cleans up the left over FCoE files in the i40e driver.

Gustavo A R Silva fixes a cut and paste error.

Paweł fixes a race condition when the VF driver is loaded on a host and
virsh is trying to attach it to the virtual machine and set a MAC
address.  Resolve the issue by adding polling in i40e_ndo_set_vf_mac()
when the VF is in reset mode.

Jake cleans up i40e_vlan_rx_register() since this only used in a single
location, so just inline the contents of the function.  Created a helper
function to proper update the per-filter statistics when we delete it.
Factored out the re-enabling ATR and SB rules.  Fixed an issue when
re-enabling ATR after the last TCPv4 filter is removed and ntuple is
still active, we were not restoring the TCPv4 filter input set.

Filip modifies the permission check function to ensure that it knows how
many filters are being requested, which allows the check to ensure that
the total number of filters in a single request does not cause us to go
over the limit.

Mariusz fixed an issue where the wrong calculation of partition id was
being done on OCP PHY mezzanine cards, which in turn caused wake on LAN
to be disabled on certain ports.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c292566a 089915f0
......@@ -3200,9 +3200,10 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
u32 valid_functions, num_functions;
u32 number, logical_id, phys_id;
struct i40e_hw_capabilities *p;
u16 id, ocp_cfg_word0;
i40e_status status;
u8 major_rev;
u32 i = 0;
u16 id;
cap = (struct i40e_aqc_list_capabilities_element_resp *) buff;
......@@ -3389,6 +3390,26 @@ static void i40e_parse_discover_capabilities(struct i40e_hw *hw, void *buff,
hw->num_ports++;
}
/* OCP cards case: if a mezz is removed the Ethernet port is at
* disabled state in PRTGEN_CNF register. Additional NVM read is
* needed in order to check if we are dealing with OCP card.
* Those cards have 4 PFs at minimum, so using PRTGEN_CNF for counting
* physical ports results in wrong partition id calculation and thus
* not supporting WoL.
*/
if (hw->mac.type == I40E_MAC_X722) {
if (!i40e_acquire_nvm(hw, I40E_RESOURCE_READ)) {
status = i40e_aq_read_nvm(hw, I40E_SR_EMP_MODULE_PTR,
2 * I40E_SR_OCP_CFG_WORD0,
sizeof(ocp_cfg_word0),
&ocp_cfg_word0, true, NULL);
if (!status &&
(ocp_cfg_word0 & I40E_SR_OCP_ENABLED))
hw->num_ports = 4;
i40e_release_nvm(hw);
}
}
valid_functions = p->valid_functions;
num_functions = 0;
while (valid_functions) {
......
This diff is collapsed.
/*******************************************************************************
*
* Intel Ethernet Controller XL710 Family Linux Driver
* 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,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* 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, see <http://www.gnu.org/licenses/>.
*
* The full GNU General Public License is included in this distribution in
* the file called "COPYING".
*
* Contact Information:
* e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
*
******************************************************************************/
#ifndef _I40E_FCOE_H_
#define _I40E_FCOE_H_
/* FCoE HW context helper macros */
#define I40E_DDP_CONTEXT_DESC(R, i) \
(&(((struct i40e_fcoe_ddp_context_desc *)((R)->desc))[i]))
#define I40E_QUEUE_CONTEXT_DESC(R, i) \
(&(((struct i40e_fcoe_queue_context_desc *)((R)->desc))[i]))
#define I40E_FILTER_CONTEXT_DESC(R, i) \
(&(((struct i40e_fcoe_filter_context_desc *)((R)->desc))[i]))
/* receive queue descriptor filter status for FCoE */
#define I40E_RX_DESC_FLTSTAT_FCMASK 0x3
#define I40E_RX_DESC_FLTSTAT_NOMTCH 0x0 /* no ddp context match */
#define I40E_RX_DESC_FLTSTAT_NODDP 0x1 /* no ddp due to error */
#define I40E_RX_DESC_FLTSTAT_DDP 0x2 /* DDPed payload, post header */
#define I40E_RX_DESC_FLTSTAT_FCPRSP 0x3 /* FCP_RSP */
/* receive queue descriptor error codes for FCoE */
#define I40E_RX_DESC_FCOE_ERROR_MASK \
(I40E_RX_DESC_ERROR_L3L4E_PROT | \
I40E_RX_DESC_ERROR_L3L4E_FC | \
I40E_RX_DESC_ERROR_L3L4E_DMAC_ERR | \
I40E_RX_DESC_ERROR_L3L4E_DMAC_WARN)
/* receive queue descriptor programming error */
#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL(e) \
(((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT) & 0x1)
#define I40E_RX_PROG_FCOE_ERROR_CONFLICT(e) \
(((e) >> I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT) & 0x1)
#define I40E_RX_PROG_FCOE_ERROR_TBL_FULL_BIT \
BIT(I40E_RX_PROG_STATUS_DESC_FCOE_TBL_FULL_SHIFT)
#define I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT \
BIT(I40E_RX_PROG_STATUS_DESC_FCOE_CONFLICT_SHIFT)
#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL(e) \
I40E_RX_PROG_FCOE_ERROR_CONFLICT(e)
#define I40E_RX_PROG_FCOE_ERROR_INVLFAIL_BIT \
I40E_RX_PROG_FCOE_ERROR_CONFLICT_BIT
/* FCoE DDP related definitions */
#define I40E_FCOE_MIN_XID 0x0000 /* the min xid supported by fcoe_sw */
#define I40E_FCOE_MAX_XID 0x0FFF /* the max xid supported by fcoe_sw */
#define I40E_FCOE_DDP_BUFFCNT_MAX 512 /* 9 bits bufcnt */
#define I40E_FCOE_DDP_PTR_ALIGN 16
#define I40E_FCOE_DDP_PTR_MAX (I40E_FCOE_DDP_BUFFCNT_MAX * sizeof(dma_addr_t))
#define I40E_FCOE_DDP_BUF_MIN 4096
#define I40E_FCOE_DDP_MAX 2048
#define I40E_FCOE_FILTER_CTX_QW1_PCTYPE_SHIFT 8
/* supported netdev features for FCoE */
#define I40E_FCOE_NETIF_FEATURES (NETIF_F_ALL_FCOE | \
NETIF_F_HW_VLAN_CTAG_TX | \
NETIF_F_HW_VLAN_CTAG_RX | \
NETIF_F_HW_VLAN_CTAG_FILTER)
/* DDP context flags */
enum i40e_fcoe_ddp_flags {
__I40E_FCOE_DDP_NONE = 1,
__I40E_FCOE_DDP_TARGET,
__I40E_FCOE_DDP_INITALIZED,
__I40E_FCOE_DDP_PROGRAMMED,
__I40E_FCOE_DDP_DONE,
__I40E_FCOE_DDP_ABORTED,
__I40E_FCOE_DDP_UNMAPPED,
};
/* DDP SW context struct */
struct i40e_fcoe_ddp {
int len;
u16 xid;
u16 firstoff;
u16 lastsize;
u16 list_len;
u8 fcerr;
u8 prerr;
unsigned long flags;
unsigned int sgc;
struct scatterlist *sgl;
dma_addr_t udp;
u64 *udl;
struct dma_pool *pool;
};
struct i40e_fcoe_ddp_pool {
struct dma_pool *pool;
};
struct i40e_fcoe {
unsigned long mode;
atomic_t refcnt;
struct i40e_fcoe_ddp_pool __percpu *ddp_pool;
struct i40e_fcoe_ddp ddp[I40E_FCOE_DDP_MAX];
};
#endif /* _I40E_FCOE_H_ */
......@@ -2718,22 +2718,6 @@ void i40e_vlan_stripping_disable(struct i40e_vsi *vsi)
}
}
/**
* i40e_vlan_rx_register - Setup or shutdown vlan offload
* @netdev: network interface to be adjusted
* @features: netdev features to test if VLAN offload is enabled or not
**/
static void i40e_vlan_rx_register(struct net_device *netdev, u32 features)
{
struct i40e_netdev_priv *np = netdev_priv(netdev);
struct i40e_vsi *vsi = np->vsi;
if (features & NETIF_F_HW_VLAN_CTAG_RX)
i40e_vlan_stripping_enable(vsi);
else
i40e_vlan_stripping_disable(vsi);
}
/**
* i40e_add_vlan_all_mac - Add a MAC/VLAN filter for each existing MAC address
* @vsi: the vsi being configured
......@@ -2909,7 +2893,10 @@ static void i40e_restore_vlan(struct i40e_vsi *vsi)
if (!vsi->netdev)
return;
i40e_vlan_rx_register(vsi->netdev, vsi->netdev->features);
if (vsi->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
i40e_vlan_stripping_enable(vsi);
else
i40e_vlan_stripping_disable(vsi);
for_each_set_bit(vid, vsi->active_vlans, VLAN_N_VID)
i40e_vlan_rx_add_vid(vsi->netdev, htons(ETH_P_8021Q),
......@@ -8148,6 +8135,88 @@ u32 i40e_get_global_fd_count(struct i40e_pf *pf)
return fcnt_prog;
}
/**
* i40e_reenable_fdir_sb - Restore FDir SB capability
* @pf: board private structure
**/
static void i40e_reenable_fdir_sb(struct i40e_pf *pf)
{
if (pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED) {
pf->flags &= ~I40E_FLAG_FD_SB_AUTO_DISABLED;
if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
(I40E_DEBUG_FD & pf->hw.debug_mask))
dev_info(&pf->pdev->dev, "FD Sideband/ntuple is being enabled since we have space in the table now\n");
}
}
/**
* i40e_reenable_fdir_atr - Restore FDir ATR capability
* @pf: board private structure
**/
static void i40e_reenable_fdir_atr(struct i40e_pf *pf)
{
if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED) {
/* ATR uses the same filtering logic as SB rules. It only
* functions properly if the input set mask is at the default
* settings. It is safe to restore the default input set
* because there are no active TCPv4 filter rules.
*/
i40e_write_fd_input_set(pf, I40E_FILTER_PCTYPE_NONF_IPV4_TCP,
I40E_L3_SRC_MASK | I40E_L3_DST_MASK |
I40E_L4_SRC_MASK | I40E_L4_DST_MASK);
pf->flags &= ~I40E_FLAG_FD_ATR_AUTO_DISABLED;
if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
(I40E_DEBUG_FD & pf->hw.debug_mask))
dev_info(&pf->pdev->dev, "ATR is being enabled since we have space in the table and there are no conflicting ntuple rules\n");
}
}
/**
* i40e_delete_invalid_filter - Delete an invalid FDIR filter
* @pf: board private structure
* @filter: FDir filter to remove
*/
static void i40e_delete_invalid_filter(struct i40e_pf *pf,
struct i40e_fdir_filter *filter)
{
/* Update counters */
pf->fdir_pf_active_filters--;
pf->fd_inv = 0;
switch (filter->flow_type) {
case TCP_V4_FLOW:
pf->fd_tcp4_filter_cnt--;
break;
case UDP_V4_FLOW:
pf->fd_udp4_filter_cnt--;
break;
case SCTP_V4_FLOW:
pf->fd_sctp4_filter_cnt--;
break;
case IP_USER_FLOW:
switch (filter->ip4_proto) {
case IPPROTO_TCP:
pf->fd_tcp4_filter_cnt--;
break;
case IPPROTO_UDP:
pf->fd_udp4_filter_cnt--;
break;
case IPPROTO_SCTP:
pf->fd_sctp4_filter_cnt--;
break;
case IPPROTO_IP:
pf->fd_ip4_filter_cnt--;
break;
}
break;
}
/* Remove the filter from the list and free memory */
hlist_del(&filter->fdir_node);
kfree(filter);
}
/**
* i40e_fdir_check_and_reenable - Function to reenabe FD ATR or SB if disabled
* @pf: board private structure
......@@ -8166,40 +8235,23 @@ void i40e_fdir_check_and_reenable(struct i40e_pf *pf)
fcnt_avail = pf->fdir_pf_filter_count;
if ((fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM)) ||
(pf->fd_add_err == 0) ||
(i40e_get_current_atr_cnt(pf) < pf->fd_atr_cnt)) {
if (pf->flags & I40E_FLAG_FD_SB_AUTO_DISABLED) {
pf->flags &= ~I40E_FLAG_FD_SB_AUTO_DISABLED;
if ((pf->flags & I40E_FLAG_FD_SB_ENABLED) &&
(I40E_DEBUG_FD & pf->hw.debug_mask))
dev_info(&pf->pdev->dev, "FD Sideband/ntuple is being enabled since we have space in the table now\n");
}
}
(i40e_get_current_atr_cnt(pf) < pf->fd_atr_cnt))
i40e_reenable_fdir_sb(pf);
/* We should wait for even more space before re-enabling ATR.
* Additionally, we cannot enable ATR as long as we still have TCP SB
* rules active.
*/
if ((fcnt_prog < (fcnt_avail - I40E_FDIR_BUFFER_HEAD_ROOM_FOR_ATR)) &&
(pf->fd_tcp4_filter_cnt == 0)) {
if (pf->flags & I40E_FLAG_FD_ATR_AUTO_DISABLED) {
pf->flags &= ~I40E_FLAG_FD_ATR_AUTO_DISABLED;
if ((pf->flags & I40E_FLAG_FD_ATR_ENABLED) &&
(I40E_DEBUG_FD & pf->hw.debug_mask))
dev_info(&pf->pdev->dev, "ATR is being enabled since we have space in the table and there are no conflicting ntuple rules\n");
}
}
(pf->fd_tcp4_filter_cnt == 0))
i40e_reenable_fdir_atr(pf);
/* if hw had a problem adding a filter, delete it */
if (pf->fd_inv > 0) {
hlist_for_each_entry_safe(filter, node,
&pf->fdir_filter_list, fdir_node) {
if (filter->fd_id == pf->fd_inv) {
hlist_del(&filter->fdir_node);
kfree(filter);
pf->fdir_pf_active_filters--;
pf->fd_inv = 0;
}
}
&pf->fdir_filter_list, fdir_node)
if (filter->fd_id == pf->fd_inv)
i40e_delete_invalid_filter(pf, filter);
}
}
......
......@@ -1336,6 +1336,9 @@ struct i40e_hw_port_stats {
#define I40E_SR_PCIE_ALT_MODULE_MAX_SIZE 1024
#define I40E_SR_CONTROL_WORD_1_SHIFT 0x06
#define I40E_SR_CONTROL_WORD_1_MASK (0x03 << I40E_SR_CONTROL_WORD_1_SHIFT)
#define I40E_PTR_TYPE BIT(15)
#define I40E_SR_OCP_CFG_WORD0 0x2B
#define I40E_SR_OCP_ENABLED BIT(15)
/* Shadow RAM related */
#define I40E_SR_SECTOR_SIZE_IN_WORDS 0x800
......
......@@ -2368,25 +2368,47 @@ static int i40e_vc_get_stats_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
/**
* i40e_check_vf_permission
* @vf: pointer to the VF info
* @macaddr: pointer to the MAC Address being checked
* @al: MAC address list from virtchnl
*
* Check if the VF has permission to add or delete unicast MAC address
* filters and return error code -EPERM if not. Then check if the
* address filter requested is broadcast or zero and if so return
* an invalid MAC address error code.
* Check that the given list of MAC addresses is allowed. Will return -EPERM
* if any address in the list is not valid. Checks the following conditions:
*
* 1) broadcast and zero addresses are never valid
* 2) unicast addresses are not allowed if the VMM has administratively set
* the VF MAC address, unless the VF is marked as privileged.
* 3) There is enough space to add all the addresses.
*
* Note that to guarantee consistency, it is expected this function be called
* while holding the mac_filter_hash_lock, as otherwise the current number of
* addresses might not be accurate.
**/
static inline int i40e_check_vf_permission(struct i40e_vf *vf, u8 *macaddr)
static inline int i40e_check_vf_permission(struct i40e_vf *vf,
struct virtchnl_ether_addr_list *al)
{
struct i40e_pf *pf = vf->pf;
int ret = 0;
int i;
/* If this VF is not privileged, then we can't add more than a limited
* number of addresses. Check to make sure that the additions do not
* push us over the limit.
*/
if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
(vf->num_mac + al->num_elements) > I40E_VC_MAX_MAC_ADDR_PER_VF) {
dev_err(&pf->pdev->dev,
"Cannot add more MAC addresses, VF is not trusted, switch the VF to trusted to add more functionality\n");
return -EPERM;
}
for (i = 0; i < al->num_elements; i++) {
u8 *addr = al->list[i].addr;
if (is_broadcast_ether_addr(addr) ||
is_zero_ether_addr(addr)) {
dev_err(&pf->pdev->dev, "invalid VF MAC addr %pM\n",
addr);
return I40E_ERR_INVALID_MAC_ADDR;
}
if (is_broadcast_ether_addr(macaddr) ||
is_zero_ether_addr(macaddr)) {
dev_err(&pf->pdev->dev, "invalid VF MAC addr %pM\n", macaddr);
ret = I40E_ERR_INVALID_MAC_ADDR;
} else if (vf->pf_set_mac && !is_multicast_ether_addr(macaddr) &&
!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
!ether_addr_equal(macaddr, vf->default_lan_addr.addr)) {
/* If the host VMM administrator has set the VF MAC address
* administratively via the ndo_set_vf_mac command then deny
* permission to the VF to add or delete unicast MAC addresses.
......@@ -2394,16 +2416,16 @@ static inline int i40e_check_vf_permission(struct i40e_vf *vf, u8 *macaddr)
* The VF may request to set the MAC address filter already
* assigned to it so do not return an error in that case.
*/
dev_err(&pf->pdev->dev,
"VF attempting to override administratively set MAC address, reload the VF driver to resume normal operation\n");
ret = -EPERM;
} else if ((vf->num_mac >= I40E_VC_MAX_MAC_ADDR_PER_VF) &&
!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps)) {
dev_err(&pf->pdev->dev,
"VF is not trusted, switch the VF to trusted to add more functionality\n");
ret = -EPERM;
if (!test_bit(I40E_VIRTCHNL_VF_CAP_PRIVILEGE, &vf->vf_caps) &&
!is_multicast_ether_addr(addr) && vf->pf_set_mac &&
!ether_addr_equal(addr, vf->default_lan_addr.addr)) {
dev_err(&pf->pdev->dev,
"VF attempting to override administratively set MAC address, reload the VF driver to resume normal operation\n");
return -EPERM;
}
}
return ret;
return 0;
}
/**
......@@ -2430,11 +2452,6 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
goto error_param;
}
for (i = 0; i < al->num_elements; i++) {
ret = i40e_check_vf_permission(vf, al->list[i].addr);
if (ret)
goto error_param;
}
vsi = pf->vsi[vf->lan_vsi_idx];
/* Lock once, because all function inside for loop accesses VSI's
......@@ -2442,6 +2459,12 @@ static int i40e_vc_add_mac_addr_msg(struct i40e_vf *vf, u8 *msg, u16 msglen)
*/
spin_lock_bh(&vsi->mac_filter_hash_lock);
ret = i40e_check_vf_permission(vf, al);
if (ret) {
spin_unlock_bh(&vsi->mac_filter_hash_lock);
goto error_param;
}
/* add new addresses to the list */
for (i = 0; i < al->num_elements; i++) {
struct i40e_mac_filter *f;
......@@ -3741,6 +3764,7 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
int ret = 0;
struct hlist_node *h;
int bkt;
u8 i;
/* validate the request */
if (vf_id >= pf->num_alloc_vfs) {
......@@ -3752,6 +3776,16 @@ int i40e_ndo_set_vf_mac(struct net_device *netdev, int vf_id, u8 *mac)
vf = &(pf->vf[vf_id]);
vsi = pf->vsi[vf->lan_vsi_idx];
/* When the VF is resetting wait until it is done.
* It can take up to 200 milliseconds,
* but wait for up to 300 milliseconds to be safe.
*/
for (i = 0; i < 15; i++) {
if (test_bit(I40E_VF_STATE_INIT, &vf->vf_states))
break;
msleep(20);
}
if (!test_bit(I40E_VF_STATE_INIT, &vf->vf_states)) {
dev_err(&pf->pdev->dev, "VF %d still in reset. Try again.\n",
vf_id);
......
......@@ -2749,7 +2749,7 @@ static int i40evf_parse_cls_flower(struct i40evf_adapter *adapter,
if (key->src) {
vf->mask.tcp_spec.src_port |= cpu_to_be16(0xffff);
vf->data.tcp_spec.src_port = key->dst;
vf->data.tcp_spec.src_port = key->src;
}
}
vf->field_flags = field_flags;
......
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