Skip to content

Commit

Permalink
Merge branch '40GbE' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/tnguy/next-queue

Tony Nguyen says:

====================
40GbE Intel Wired LAN Driver Updates 2021-04-23

This series contains updates to i40e and iavf drivers.

Aleksandr adds support for VIRTCHNL_VF_CAP_ADV_LINK_SPEED in i40e which
allows for reporting link speed to VF as a value instead of using an
enum; helper functions are created to remove repeated code.

Coiby Xu reduces memory use of i40e when using kdump by reducing Tx, Rx,
and admin queue to minimum values. Current use causes failure of kdump.

Stefan Assmann removes duplicated free calls in iavf.

Haiyue cleans up a loop to return directly when if the value is found
and changes some magic numbers to defines for better maintainability
in iavf.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 23, 2021
2 parents cbf2ec5 + 1f70dfc commit b1ce98c
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 55 deletions.
2 changes: 2 additions & 0 deletions drivers/net/ethernet/intel/i40e/i40e.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
#define I40E_FDIR_RING_COUNT 32
#define I40E_MAX_AQ_BUF_SIZE 4096
#define I40E_AQ_LEN 256
#define I40E_MIN_ARQ_LEN 1
#define I40E_MIN_ASQ_LEN 2
#define I40E_AQ_WORK_LIMIT 66 /* max number of VFs + a little */
#define I40E_MAX_USER_PRIORITY 8
#define I40E_DEFAULT_TRAFFIC_CLASS BIT(0)
Expand Down
23 changes: 21 additions & 2 deletions drivers/net/ethernet/intel/i40e/i40e_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <linux/pci.h>
#include <linux/bpf.h>
#include <generated/utsrelease.h>
#include <linux/crash_dump.h>

/* Local includes */
#include "i40e.h"
Expand Down Expand Up @@ -11039,6 +11040,11 @@ static int i40e_set_num_rings_in_vsi(struct i40e_vsi *vsi)
return -ENODATA;
}

if (is_kdump_kernel()) {
vsi->num_tx_desc = I40E_MIN_NUM_DESCRIPTORS;
vsi->num_rx_desc = I40E_MIN_NUM_DESCRIPTORS;
}

return 0;
}

Expand Down Expand Up @@ -15342,8 +15348,13 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)

i40e_check_recovery_mode(pf);

hw->aq.num_arq_entries = I40E_AQ_LEN;
hw->aq.num_asq_entries = I40E_AQ_LEN;
if (is_kdump_kernel()) {
hw->aq.num_arq_entries = I40E_MIN_ARQ_LEN;
hw->aq.num_asq_entries = I40E_MIN_ASQ_LEN;
} else {
hw->aq.num_arq_entries = I40E_AQ_LEN;
hw->aq.num_asq_entries = I40E_AQ_LEN;
}
hw->aq.arq_buf_size = I40E_MAX_AQ_BUF_SIZE;
hw->aq.asq_buf_size = I40E_MAX_AQ_BUF_SIZE;
pf->adminq_work_limit = I40E_AQ_WORK_LIMIT;
Expand Down Expand Up @@ -15506,6 +15517,14 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_switch_setup;

/* Reduce Tx and Rx pairs for kdump
* When MSI-X is enabled, it's not allowed to use more TC queue
* pairs than MSI-X vectors (pf->num_lan_msix) exist. Thus
* vsi->num_queue_pairs will be equal to pf->num_lan_msix, i.e., 1.
*/
if (is_kdump_kernel())
pf->num_lan_msix = 1;

pf->udp_tunnel_nic.set_port = i40e_udp_tunnel_set_port;
pf->udp_tunnel_nic.unset_port = i40e_udp_tunnel_unset_port;
pf->udp_tunnel_nic.flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP;
Expand Down
108 changes: 69 additions & 39 deletions drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,66 @@ static void i40e_vc_vf_broadcast(struct i40e_pf *pf,
}
}

/**
* i40e_vc_link_speed2mbps
* converts i40e_aq_link_speed to integer value of Mbps
* @link_speed: the speed to convert
*
* return the speed as direct value of Mbps.
**/
static u32
i40e_vc_link_speed2mbps(enum i40e_aq_link_speed link_speed)
{
switch (link_speed) {
case I40E_LINK_SPEED_100MB:
return SPEED_100;
case I40E_LINK_SPEED_1GB:
return SPEED_1000;
case I40E_LINK_SPEED_2_5GB:
return SPEED_2500;
case I40E_LINK_SPEED_5GB:
return SPEED_5000;
case I40E_LINK_SPEED_10GB:
return SPEED_10000;
case I40E_LINK_SPEED_20GB:
return SPEED_20000;
case I40E_LINK_SPEED_25GB:
return SPEED_25000;
case I40E_LINK_SPEED_40GB:
return SPEED_40000;
case I40E_LINK_SPEED_UNKNOWN:
return SPEED_UNKNOWN;
}
return SPEED_UNKNOWN;
}

/**
* i40e_set_vf_link_state
* @vf: pointer to the VF structure
* @pfe: pointer to PF event structure
* @ls: pointer to link status structure
*
* set a link state on a single vf
**/
static void i40e_set_vf_link_state(struct i40e_vf *vf,
struct virtchnl_pf_event *pfe, struct i40e_link_status *ls)
{
u8 link_status = ls->link_info & I40E_AQ_LINK_UP;

if (vf->link_forced)
link_status = vf->link_up;

if (vf->driver_caps & VIRTCHNL_VF_CAP_ADV_LINK_SPEED) {
pfe->event_data.link_event_adv.link_speed = link_status ?
i40e_vc_link_speed2mbps(ls->link_speed) : 0;
pfe->event_data.link_event_adv.link_status = link_status;
} else {
pfe->event_data.link_event.link_speed = link_status ?
i40e_virtchnl_link_speed(ls->link_speed) : 0;
pfe->event_data.link_event.link_status = link_status;
}
}

/**
* i40e_vc_notify_vf_link_state
* @vf: pointer to the VF structure
Expand All @@ -55,16 +115,9 @@ static void i40e_vc_notify_vf_link_state(struct i40e_vf *vf)

pfe.event = VIRTCHNL_EVENT_LINK_CHANGE;
pfe.severity = PF_EVENT_SEVERITY_INFO;
if (vf->link_forced) {
pfe.event_data.link_event.link_status = vf->link_up;
pfe.event_data.link_event.link_speed =
(vf->link_up ? i40e_virtchnl_link_speed(ls->link_speed) : 0);
} else {
pfe.event_data.link_event.link_status =
ls->link_info & I40E_AQ_LINK_UP;
pfe.event_data.link_event.link_speed =
i40e_virtchnl_link_speed(ls->link_speed);
}

i40e_set_vf_link_state(vf, &pfe, ls);

i40e_aq_send_msg_to_vf(hw, abs_vf_id, VIRTCHNL_OP_EVENT,
0, (u8 *)&pfe, sizeof(pfe), NULL);
}
Expand Down Expand Up @@ -1949,6 +2002,7 @@ static int i40e_vc_get_vf_resources_msg(struct i40e_vf *vf, u8 *msg)
VIRTCHNL_VF_OFFLOAD_VLAN;

vfres->vf_cap_flags = VIRTCHNL_VF_OFFLOAD_L2;
vfres->vf_cap_flags |= VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
vsi = pf->vsi[vf->lan_vsi_idx];
if (!vsi->info.pvid)
vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_VLAN;
Expand Down Expand Up @@ -3696,26 +3750,8 @@ static int i40e_vc_add_qch_msg(struct i40e_vf *vf, u8 *msg)
}

/* get link speed in MB to validate rate limit */
switch (ls->link_speed) {
case VIRTCHNL_LINK_SPEED_100MB:
speed = SPEED_100;
break;
case VIRTCHNL_LINK_SPEED_1GB:
speed = SPEED_1000;
break;
case VIRTCHNL_LINK_SPEED_10GB:
speed = SPEED_10000;
break;
case VIRTCHNL_LINK_SPEED_20GB:
speed = SPEED_20000;
break;
case VIRTCHNL_LINK_SPEED_25GB:
speed = SPEED_25000;
break;
case VIRTCHNL_LINK_SPEED_40GB:
speed = SPEED_40000;
break;
default:
speed = i40e_vc_link_speed2mbps(ls->link_speed);
if (speed == SPEED_UNKNOWN) {
dev_err(&pf->pdev->dev,
"Cannot detect link speed\n");
aq_ret = I40E_ERR_PARAM;
Expand Down Expand Up @@ -4464,23 +4500,17 @@ int i40e_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
switch (link) {
case IFLA_VF_LINK_STATE_AUTO:
vf->link_forced = false;
pfe.event_data.link_event.link_status =
pf->hw.phy.link_info.link_info & I40E_AQ_LINK_UP;
pfe.event_data.link_event.link_speed =
(enum virtchnl_link_speed)
pf->hw.phy.link_info.link_speed;
i40e_set_vf_link_state(vf, &pfe, ls);
break;
case IFLA_VF_LINK_STATE_ENABLE:
vf->link_forced = true;
vf->link_up = true;
pfe.event_data.link_event.link_status = true;
pfe.event_data.link_event.link_speed = i40e_virtchnl_link_speed(ls->link_speed);
i40e_set_vf_link_state(vf, &pfe, ls);
break;
case IFLA_VF_LINK_STATE_DISABLE:
vf->link_forced = true;
vf->link_up = false;
pfe.event_data.link_event.link_status = false;
pfe.event_data.link_event.link_speed = 0;
i40e_set_vf_link_state(vf, &pfe, ls);
break;
default:
ret = -EINVAL;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/iavf/iavf_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -939,7 +939,7 @@ iavf_parse_rx_flow_user_data(struct ethtool_rx_flow_spec *fsp,
if (!(fsp->flow_type & FLOW_EXT))
return 0;

for (i = 0; i < 2; i++) {
for (i = 0; i < IAVF_FLEX_WORD_NUM; i++) {
#define IAVF_USERDEF_FLEX_WORD_M GENMASK(15, 0)
#define IAVF_USERDEF_FLEX_OFFS_S 16
#define IAVF_USERDEF_FLEX_OFFS_M GENMASK(31, IAVF_USERDEF_FLEX_OFFS_S)
Expand Down
24 changes: 15 additions & 9 deletions drivers/net/ethernet/intel/iavf/iavf_fdir.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,13 @@ iavf_fill_fdir_gtpu_hdr(struct iavf_fdir_fltr *fltr,
#define IAVF_GTPU_HDR_TEID_OFFS0 4
#define IAVF_GTPU_HDR_TEID_OFFS1 6
#define IAVF_GTPU_HDR_N_PDU_AND_NEXT_EXTHDR_OFFS 10
#define IAVF_GTPU_HDR_NEXT_EXTHDR_TYPE_MASK 0x00FF /* skip N_PDU */
/* PDU Session Container Extension Header (PSC) */
#define IAVF_GTPU_PSC_EXTHDR_TYPE 0x85
#define IAVF_GTPU_HDR_PSC_PDU_TYPE_AND_QFI_OFFS 13
#define IAVF_GTPU_PSC_EXTHDR_TYPE 0x85 /* PDU Session Container Extension Header */
#define IAVF_GTPU_HDR_PSC_PDU_QFI_MASK 0x3F /* skip Type */
#define IAVF_GTPU_EH_QFI_IDX 1

if (fltr->flex_words[i].offset < adj_offs)
return -EINVAL;

Expand All @@ -71,7 +76,9 @@ iavf_fill_fdir_gtpu_hdr(struct iavf_fdir_fltr *fltr,
}
break;
case IAVF_GTPU_HDR_N_PDU_AND_NEXT_EXTHDR_OFFS:
if ((fltr->flex_words[i].word & 0xff) != IAVF_GTPU_PSC_EXTHDR_TYPE)
if ((fltr->flex_words[i].word &
IAVF_GTPU_HDR_NEXT_EXTHDR_TYPE_MASK) !=
IAVF_GTPU_PSC_EXTHDR_TYPE)
return -EOPNOTSUPP;
if (!ehdr)
ehdr = &proto_hdrs->proto_hdr[proto_hdrs->count++];
Expand All @@ -80,7 +87,9 @@ iavf_fill_fdir_gtpu_hdr(struct iavf_fdir_fltr *fltr,
case IAVF_GTPU_HDR_PSC_PDU_TYPE_AND_QFI_OFFS:
if (!ehdr)
return -EINVAL;
ehdr->buffer[1] = fltr->flex_words[i].word & 0x3F;
ehdr->buffer[IAVF_GTPU_EH_QFI_IDX] =
fltr->flex_words[i].word &
IAVF_GTPU_HDR_PSC_PDU_QFI_MASK;
VIRTCHNL_ADD_PROTO_HDR_FIELD_BIT(ehdr, GTPU_EH, QFI);
break;
default:
Expand Down Expand Up @@ -713,7 +722,6 @@ void iavf_print_fdir_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *f
bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *fltr)
{
struct iavf_fdir_fltr *tmp;
bool ret = false;

list_for_each_entry(tmp, &adapter->fdir_list_head, list) {
if (tmp->flow_type != fltr->flow_type)
Expand All @@ -724,13 +732,11 @@ bool iavf_fdir_is_dup_fltr(struct iavf_adapter *adapter, struct iavf_fdir_fltr *
!memcmp(&tmp->ip_data, &fltr->ip_data,
sizeof(fltr->ip_data)) &&
!memcmp(&tmp->ext_data, &fltr->ext_data,
sizeof(fltr->ext_data))) {
ret = true;
break;
}
sizeof(fltr->ext_data)))
return true;
}

return ret;
return false;
}

/**
Expand Down
9 changes: 7 additions & 2 deletions drivers/net/ethernet/intel/iavf/iavf_fdir.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ enum iavf_fdir_flow_type {
IAVF_FDIR_FLOW_PTYPE_MAX,
};

/* Must not exceed the array element number of '__be32 data[2]' in the ethtool
* 'struct ethtool_rx_flow_spec.m_ext.data[2]' to express the flex-byte (word).
*/
#define IAVF_FLEX_WORD_NUM 2

struct iavf_flex_word {
u16 offset;
u16 word;
Expand Down Expand Up @@ -71,7 +76,7 @@ struct iavf_fdir_ip {
};

struct iavf_fdir_extra {
u32 usr_def[2];
u32 usr_def[IAVF_FLEX_WORD_NUM];
};

/* bookkeeping of Flow Director filters */
Expand All @@ -95,7 +100,7 @@ struct iavf_fdir_fltr {
/* flex byte filter data */
u8 ip_ver; /* used to adjust the flex offset, 4 : IPv4, 6 : IPv6 */
u8 flex_cnt;
struct iavf_flex_word flex_words[2];
struct iavf_flex_word flex_words[IAVF_FLEX_WORD_NUM];

u32 flow_id;

Expand Down
2 changes: 0 additions & 2 deletions drivers/net/ethernet/intel/iavf/iavf_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3940,8 +3940,6 @@ static void iavf_remove(struct pci_dev *pdev)

iounmap(hw->hw_addr);
pci_release_regions(pdev);
iavf_free_all_tx_resources(adapter);
iavf_free_all_rx_resources(adapter);
iavf_free_queues(adapter);
kfree(adapter->vf_res);
spin_lock_bh(&adapter->mac_vlan_list_lock);
Expand Down

0 comments on commit b1ce98c

Please sign in to comment.