提交 bdc8587a 编写于 作者: D 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-02-14

This patch series enables the new mqprio hardware offload mechanism
creating traffic classes on VFs for XL710 devices. The parameters
needed to configure these traffic classes/queue channels are provides
by the user via the tc tool. A maximum of four traffic classes can be
created on each VF. This patch series also enables application of cloud
filters to each of these traffic classes. The cloud filters are applied
using the tc-flower classifier.

Example:
    1. tc qdisc add dev vf0 root mqprio num_tc 4 map 0 0 0 0 1 2 2 3\
        queues 2@0 2@2 1@4 1@5 hw 1 mode channel
    2. tc qdisc add dev vf0 ingress
    3. ethtool -K vf0 hw-tc-offload on
    4. ip link set eth0 vf 0 spoofchk off
    5. tc filter add dev vf0 protocol ip parent ffff: prio 1 flower dst_ip\
        192.168.3.5/32 ip_proto udp dst_port 25 skip_sw hw_tc 2
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
......@@ -1109,4 +1109,10 @@ static inline bool i40e_enabled_xdp_vsi(struct i40e_vsi *vsi)
int i40e_create_queue_channel(struct i40e_vsi *vsi, struct i40e_channel *ch);
int i40e_set_bw_limit(struct i40e_vsi *vsi, u16 seid, u64 max_tx_rate);
int i40e_add_del_cloud_filter(struct i40e_vsi *vsi,
struct i40e_cloud_filter *filter,
bool add);
int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi,
struct i40e_cloud_filter *filter,
bool add);
#endif /* _I40E_H_ */
......@@ -69,12 +69,6 @@ static int i40e_reset(struct i40e_pf *pf);
static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired);
static void i40e_fdir_sb_setup(struct i40e_pf *pf);
static int i40e_veb_get_bw_info(struct i40e_veb *veb);
static int i40e_add_del_cloud_filter(struct i40e_vsi *vsi,
struct i40e_cloud_filter *filter,
bool add);
static int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi,
struct i40e_cloud_filter *filter,
bool add);
static int i40e_get_capabilities(struct i40e_pf *pf,
enum i40e_admin_queue_opc list_type);
......@@ -6841,8 +6835,8 @@ i40e_set_cld_element(struct i40e_cloud_filter *filter,
* Add or delete a cloud filter for a specific flow spec.
* Returns 0 if the filter were successfully added.
**/
static int i40e_add_del_cloud_filter(struct i40e_vsi *vsi,
struct i40e_cloud_filter *filter, bool add)
int i40e_add_del_cloud_filter(struct i40e_vsi *vsi,
struct i40e_cloud_filter *filter, bool add)
{
struct i40e_aqc_cloud_filters_element_data cld_filter;
struct i40e_pf *pf = vsi->back;
......@@ -6908,9 +6902,9 @@ static int i40e_add_del_cloud_filter(struct i40e_vsi *vsi,
* Add or delete a cloud filter for a specific flow spec using big buffer.
* Returns 0 if the filter were successfully added.
**/
static int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi,
struct i40e_cloud_filter *filter,
bool add)
int i40e_add_del_cloud_filter_big_buf(struct i40e_vsi *vsi,
struct i40e_cloud_filter *filter,
bool add)
{
struct i40e_aqc_cloud_filters_element_bb cld_filter;
struct i40e_pf *pf = vsi->back;
......
......@@ -39,7 +39,7 @@
#define I40E_MASK(mask, shift) ((u32)(mask) << (shift))
#define I40E_MAX_VSI_QP 16
#define I40E_MAX_VF_VSI 3
#define I40E_MAX_VF_VSI 4
#define I40E_MAX_CHAINED_RX_BUFFERS 5
#define I40E_MAX_PF_UDP_OFFLOAD_PORTS 16
......
......@@ -69,6 +69,19 @@ enum i40e_vf_capabilities {
I40E_VIRTCHNL_VF_CAP_IWARP,
};
/* In ADq, max 4 VSI's can be allocated per VF including primary VF VSI.
* These variables are used to store indices, id's and number of queues
* for each VSI including that of primary VF VSI. Each Traffic class is
* termed as channel and each channel can in-turn have 4 queues which
* means max 16 queues overall per VF.
*/
struct i40evf_channel {
u16 vsi_idx; /* index in PF struct for all channel VSIs */
u16 vsi_id; /* VSI ID used by firmware */
u16 num_qps; /* number of queue pairs requested by user */
u64 max_tx_rate; /* bandwidth rate allocation for VSIs */
};
/* VF information structure */
struct i40e_vf {
struct i40e_pf *pf;
......@@ -111,6 +124,13 @@ struct i40e_vf {
u16 num_mac;
u16 num_vlan;
/* ADq related variables */
bool adq_enabled; /* flag to enable adq */
u8 num_tc;
struct i40evf_channel ch[I40E_MAX_VF_VSI];
struct hlist_head cloud_filter_list;
u16 num_cloud_filters;
/* RDMA Client */
struct virtchnl_iwarp_qvlist_info *qvlist_info;
};
......
......@@ -52,7 +52,10 @@
#include <linux/socket.h>
#include <linux/jiffies.h>
#include <net/ip6_checksum.h>
#include <net/pkt_cls.h>
#include <net/udp.h>
#include <net/tc_act/tc_gact.h>
#include <net/tc_act/tc_mirred.h>
#include "i40e_type.h"
#include <linux/avf/virtchnl.h>
......@@ -106,6 +109,7 @@ struct i40e_vsi {
#define I40EVF_HKEY_ARRAY_SIZE ((I40E_VFQF_HKEY_MAX_INDEX + 1) * 4)
#define I40EVF_HLUT_ARRAY_SIZE ((I40E_VFQF_HLUT_MAX_INDEX + 1) * 4)
#define I40EVF_MBPS_DIVISOR 125000 /* divisor to convert to Mbps */
/* MAX_MSIX_Q_VECTORS of these are allocated,
* but we only use one per queue-specific vector.
......@@ -168,6 +172,28 @@ struct i40evf_vlan_filter {
bool add; /* filter needs to be added */
};
#define I40EVF_MAX_TRAFFIC_CLASS 4
/* State of traffic class creation */
enum i40evf_tc_state_t {
__I40EVF_TC_INVALID, /* no traffic class, default state */
__I40EVF_TC_RUNNING, /* traffic classes have been created */
};
/* channel info */
struct i40evf_channel_config {
struct virtchnl_channel_info ch_info[I40EVF_MAX_TRAFFIC_CLASS];
enum i40evf_tc_state_t state;
u8 total_qps;
};
/* State of cloud filter */
enum i40evf_cloud_filter_state_t {
__I40EVF_CF_INVALID, /* cloud filter not added */
__I40EVF_CF_ADD_PENDING, /* cloud filter pending add by the PF */
__I40EVF_CF_DEL_PENDING, /* cloud filter pending del by the PF */
__I40EVF_CF_ACTIVE, /* cloud filter is active */
};
/* Driver state. The order of these is important! */
enum i40evf_state_t {
__I40EVF_STARTUP, /* driver loaded, probe complete */
......@@ -189,6 +215,36 @@ enum i40evf_critical_section_t {
__I40EVF_IN_REMOVE_TASK, /* device being removed */
};
#define I40EVF_CLOUD_FIELD_OMAC 0x01
#define I40EVF_CLOUD_FIELD_IMAC 0x02
#define I40EVF_CLOUD_FIELD_IVLAN 0x04
#define I40EVF_CLOUD_FIELD_TEN_ID 0x08
#define I40EVF_CLOUD_FIELD_IIP 0x10
#define I40EVF_CF_FLAGS_OMAC I40EVF_CLOUD_FIELD_OMAC
#define I40EVF_CF_FLAGS_IMAC I40EVF_CLOUD_FIELD_IMAC
#define I40EVF_CF_FLAGS_IMAC_IVLAN (I40EVF_CLOUD_FIELD_IMAC |\
I40EVF_CLOUD_FIELD_IVLAN)
#define I40EVF_CF_FLAGS_IMAC_TEN_ID (I40EVF_CLOUD_FIELD_IMAC |\
I40EVF_CLOUD_FIELD_TEN_ID)
#define I40EVF_CF_FLAGS_OMAC_TEN_ID_IMAC (I40EVF_CLOUD_FIELD_OMAC |\
I40EVF_CLOUD_FIELD_IMAC |\
I40EVF_CLOUD_FIELD_TEN_ID)
#define I40EVF_CF_FLAGS_IMAC_IVLAN_TEN_ID (I40EVF_CLOUD_FIELD_IMAC |\
I40EVF_CLOUD_FIELD_IVLAN |\
I40EVF_CLOUD_FIELD_TEN_ID)
#define I40EVF_CF_FLAGS_IIP I40E_CLOUD_FIELD_IIP
/* bookkeeping of cloud filters */
struct i40evf_cloud_filter {
enum i40evf_cloud_filter_state_t state;
struct list_head list;
struct virtchnl_filter f;
unsigned long cookie;
bool del; /* filter needs to be deleted */
bool add; /* filter needs to be added */
};
/* board specific private data structure */
struct i40evf_adapter {
struct timer_list watchdog_timer;
......@@ -240,6 +296,7 @@ struct i40evf_adapter {
#define I40EVF_FLAG_ALLMULTI_ON BIT(14)
#define I40EVF_FLAG_LEGACY_RX BIT(15)
#define I40EVF_FLAG_REINIT_ITR_NEEDED BIT(16)
#define I40EVF_FLAG_QUEUES_DISABLED BIT(17)
/* duplicates for common code */
#define I40E_FLAG_DCB_ENABLED 0
#define I40E_FLAG_RX_CSUM_ENABLED I40EVF_FLAG_RX_CSUM_ENABLED
......@@ -268,6 +325,10 @@ struct i40evf_adapter {
#define I40EVF_FLAG_AQ_RELEASE_ALLMULTI BIT(18)
#define I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING BIT(19)
#define I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING BIT(20)
#define I40EVF_FLAG_AQ_ENABLE_CHANNELS BIT(21)
#define I40EVF_FLAG_AQ_DISABLE_CHANNELS BIT(22)
#define I40EVF_FLAG_AQ_ADD_CLOUD_FILTER BIT(23)
#define I40EVF_FLAG_AQ_DEL_CLOUD_FILTER BIT(24)
/* OS defined structs */
struct net_device *netdev;
......@@ -313,6 +374,13 @@ struct i40evf_adapter {
u16 rss_lut_size;
u8 *rss_key;
u8 *rss_lut;
/* ADQ related members */
struct i40evf_channel_config ch_config;
u8 num_tc;
struct list_head cloud_filter_list;
/* lock to protest access to the cloud filter list */
spinlock_t cloud_filter_list_lock;
u16 num_cloud_filters;
};
......@@ -379,4 +447,8 @@ void i40evf_notify_client_message(struct i40e_vsi *vsi, u8 *msg, u16 len);
void i40evf_notify_client_l2_params(struct i40e_vsi *vsi);
void i40evf_notify_client_open(struct i40e_vsi *vsi);
void i40evf_notify_client_close(struct i40e_vsi *vsi, bool reset);
void i40evf_enable_channels(struct i40evf_adapter *adapter);
void i40evf_disable_channels(struct i40evf_adapter *adapter);
void i40evf_add_cloud_filter(struct i40evf_adapter *adapter);
void i40evf_del_cloud_filter(struct i40evf_adapter *adapter);
#endif /* _I40EVF_H_ */
......@@ -695,6 +695,12 @@ static int i40evf_set_channels(struct net_device *netdev,
return -EINVAL;
}
if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
adapter->num_tc) {
dev_info(&adapter->pdev->dev, "Cannot set channels since ADq is enabled.\n");
return -EINVAL;
}
/* All of these should have already been checked by ethtool before this
* even gets to us, but just to be sure.
*/
......
......@@ -161,7 +161,8 @@ int i40evf_send_vf_config_msg(struct i40evf_adapter *adapter)
VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 |
VIRTCHNL_VF_OFFLOAD_ENCAP |
VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM |
VIRTCHNL_VF_OFFLOAD_REQ_QUEUES;
VIRTCHNL_VF_OFFLOAD_REQ_QUEUES |
VIRTCHNL_VF_OFFLOAD_ADQ;
adapter->current_op = VIRTCHNL_OP_GET_VF_RESOURCES;
adapter->aq_required &= ~I40EVF_FLAG_AQ_GET_CONFIG;
......@@ -972,6 +973,201 @@ static void i40evf_print_link_message(struct i40evf_adapter *adapter)
netdev_info(netdev, "NIC Link is Up %sbps Full Duplex\n", speed);
}
/**
* i40evf_enable_channel
* @adapter: adapter structure
*
* Request that the PF enable channels as specified by
* the user via tc tool.
**/
void i40evf_enable_channels(struct i40evf_adapter *adapter)
{
struct virtchnl_tc_info *vti = NULL;
u16 len;
int i;
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
dev_err(&adapter->pdev->dev, "Cannot configure mqprio, command %d pending\n",
adapter->current_op);
return;
}
len = (adapter->num_tc * sizeof(struct virtchnl_channel_info)) +
sizeof(struct virtchnl_tc_info);
vti = kzalloc(len, GFP_KERNEL);
if (!vti)
return;
vti->num_tc = adapter->num_tc;
for (i = 0; i < vti->num_tc; i++) {
vti->list[i].count = adapter->ch_config.ch_info[i].count;
vti->list[i].offset = adapter->ch_config.ch_info[i].offset;
vti->list[i].pad = 0;
vti->list[i].max_tx_rate =
adapter->ch_config.ch_info[i].max_tx_rate;
}
adapter->ch_config.state = __I40EVF_TC_RUNNING;
adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
adapter->current_op = VIRTCHNL_OP_ENABLE_CHANNELS;
adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_CHANNELS;
i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ENABLE_CHANNELS,
(u8 *)vti, len);
kfree(vti);
}
/**
* i40evf_disable_channel
* @adapter: adapter structure
*
* Request that the PF disable channels that are configured
**/
void i40evf_disable_channels(struct i40evf_adapter *adapter)
{
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
dev_err(&adapter->pdev->dev, "Cannot configure mqprio, command %d pending\n",
adapter->current_op);
return;
}
adapter->ch_config.state = __I40EVF_TC_INVALID;
adapter->flags |= I40EVF_FLAG_REINIT_ITR_NEEDED;
adapter->current_op = VIRTCHNL_OP_DISABLE_CHANNELS;
adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_CHANNELS;
i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_CHANNELS,
NULL, 0);
}
/**
* i40evf_print_cloud_filter
* @adapter: adapter structure
* @f: cloud filter to print
*
* Print the cloud filter
**/
static void i40evf_print_cloud_filter(struct i40evf_adapter *adapter,
struct virtchnl_filter f)
{
switch (f.flow_type) {
case VIRTCHNL_TCP_V4_FLOW:
dev_info(&adapter->pdev->dev, "dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI4 src_ip %pI4 dst_port %hu src_port %hu\n",
&f.data.tcp_spec.dst_mac, &f.data.tcp_spec.src_mac,
ntohs(f.data.tcp_spec.vlan_id),
&f.data.tcp_spec.dst_ip[0], &f.data.tcp_spec.src_ip[0],
ntohs(f.data.tcp_spec.dst_port),
ntohs(f.data.tcp_spec.src_port));
break;
case VIRTCHNL_TCP_V6_FLOW:
dev_info(&adapter->pdev->dev, "dst_mac: %pM src_mac: %pM vlan_id: %hu dst_ip: %pI6 src_ip %pI6 dst_port %hu src_port %hu\n",
&f.data.tcp_spec.dst_mac, &f.data.tcp_spec.src_mac,
ntohs(f.data.tcp_spec.vlan_id),
&f.data.tcp_spec.dst_ip, &f.data.tcp_spec.src_ip,
ntohs(f.data.tcp_spec.dst_port),
ntohs(f.data.tcp_spec.src_port));
break;
}
}
/**
* i40evf_add_cloud_filter
* @adapter: adapter structure
*
* Request that the PF add cloud filters as specified
* by the user via tc tool.
**/
void i40evf_add_cloud_filter(struct i40evf_adapter *adapter)
{
struct i40evf_cloud_filter *cf;
struct virtchnl_filter *f;
int len = 0, count = 0;
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
dev_err(&adapter->pdev->dev, "Cannot add cloud filter, command %d pending\n",
adapter->current_op);
return;
}
list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
if (cf->add) {
count++;
break;
}
}
if (!count) {
adapter->aq_required &= ~I40EVF_FLAG_AQ_ADD_CLOUD_FILTER;
return;
}
adapter->current_op = VIRTCHNL_OP_ADD_CLOUD_FILTER;
len = sizeof(struct virtchnl_filter);
f = kzalloc(len, GFP_KERNEL);
if (!f)
return;
list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
if (cf->add) {
memcpy(f, &cf->f, sizeof(struct virtchnl_filter));
cf->add = false;
cf->state = __I40EVF_CF_ADD_PENDING;
i40evf_send_pf_msg(adapter,
VIRTCHNL_OP_ADD_CLOUD_FILTER,
(u8 *)f, len);
}
}
kfree(f);
}
/**
* i40evf_del_cloud_filter
* @adapter: adapter structure
*
* Request that the PF delete cloud filters as specified
* by the user via tc tool.
**/
void i40evf_del_cloud_filter(struct i40evf_adapter *adapter)
{
struct i40evf_cloud_filter *cf, *cftmp;
struct virtchnl_filter *f;
int len = 0, count = 0;
if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) {
/* bail because we already have a command pending */
dev_err(&adapter->pdev->dev, "Cannot remove cloud filter, command %d pending\n",
adapter->current_op);
return;
}
list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
if (cf->del) {
count++;
break;
}
}
if (!count) {
adapter->aq_required &= ~I40EVF_FLAG_AQ_DEL_CLOUD_FILTER;
return;
}
adapter->current_op = VIRTCHNL_OP_DEL_CLOUD_FILTER;
len = sizeof(struct virtchnl_filter);
f = kzalloc(len, GFP_KERNEL);
if (!f)
return;
list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list, list) {
if (cf->del) {
memcpy(f, &cf->f, sizeof(struct virtchnl_filter));
cf->del = false;
cf->state = __I40EVF_CF_DEL_PENDING;
i40evf_send_pf_msg(adapter,
VIRTCHNL_OP_DEL_CLOUD_FILTER,
(u8 *)f, len);
}
}
kfree(f);
}
/**
* i40evf_request_reset
* @adapter: adapter structure
......@@ -1017,14 +1213,25 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
if (adapter->link_up == link_up)
break;
/* If we get link up message and start queues before
* our queues are configured it will trigger a TX hang.
* In that case, just ignore the link status message,
* we'll get another one after we enable queues and
* actually prepared to send traffic.
*/
if (link_up && adapter->state != __I40EVF_RUNNING)
break;
if (link_up) {
/* If we get link up message and start queues
* before our queues are configured it will
* trigger a TX hang. In that case, just ignore
* the link status message,we'll get another one
* after we enable queues and actually prepared
* to send traffic.
*/
if (adapter->state != __I40EVF_RUNNING)
break;
/* For ADq enabled VF, we reconfigure VSIs and
* re-allocate queues. Hence wait till all
* queues are enabled.
*/
if (adapter->flags &
I40EVF_FLAG_QUEUES_DISABLED)
break;
}
adapter->link_up = link_up;
if (link_up) {
......@@ -1069,6 +1276,57 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
dev_err(&adapter->pdev->dev, "Failed to delete MAC filter, error %s\n",
i40evf_stat_str(&adapter->hw, v_retval));
break;
case VIRTCHNL_OP_ENABLE_CHANNELS:
dev_err(&adapter->pdev->dev, "Failed to configure queue channels, error %s\n",
i40evf_stat_str(&adapter->hw, v_retval));
adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
adapter->ch_config.state = __I40EVF_TC_INVALID;
netdev_reset_tc(netdev);
netif_tx_start_all_queues(netdev);
break;
case VIRTCHNL_OP_DISABLE_CHANNELS:
dev_err(&adapter->pdev->dev, "Failed to disable queue channels, error %s\n",
i40evf_stat_str(&adapter->hw, v_retval));
adapter->flags &= ~I40EVF_FLAG_REINIT_ITR_NEEDED;
adapter->ch_config.state = __I40EVF_TC_RUNNING;
netif_tx_start_all_queues(netdev);
break;
case VIRTCHNL_OP_ADD_CLOUD_FILTER: {
struct i40evf_cloud_filter *cf, *cftmp;
list_for_each_entry_safe(cf, cftmp,
&adapter->cloud_filter_list,
list) {
if (cf->state == __I40EVF_CF_ADD_PENDING) {
cf->state = __I40EVF_CF_INVALID;
dev_info(&adapter->pdev->dev, "Failed to add cloud filter, error %s\n",
i40evf_stat_str(&adapter->hw,
v_retval));
i40evf_print_cloud_filter(adapter,
cf->f);
list_del(&cf->list);
kfree(cf);
adapter->num_cloud_filters--;
}
}
}
break;
case VIRTCHNL_OP_DEL_CLOUD_FILTER: {
struct i40evf_cloud_filter *cf;
list_for_each_entry(cf, &adapter->cloud_filter_list,
list) {
if (cf->state == __I40EVF_CF_DEL_PENDING) {
cf->state = __I40EVF_CF_ACTIVE;
dev_info(&adapter->pdev->dev, "Failed to del cloud filter, error %s\n",
i40evf_stat_str(&adapter->hw,
v_retval));
i40evf_print_cloud_filter(adapter,
cf->f);
}
}
}
break;
default:
dev_err(&adapter->pdev->dev, "PF returned error %d (%s) to our request %d\n",
v_retval,
......@@ -1108,6 +1366,7 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
case VIRTCHNL_OP_ENABLE_QUEUES:
/* enable transmits */
i40evf_irq_enable(adapter, true);
adapter->flags &= ~I40EVF_FLAG_QUEUES_DISABLED;
break;
case VIRTCHNL_OP_DISABLE_QUEUES:
i40evf_free_all_tx_resources(adapter);
......@@ -1162,6 +1421,29 @@ void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
}
}
break;
case VIRTCHNL_OP_ADD_CLOUD_FILTER: {
struct i40evf_cloud_filter *cf;
list_for_each_entry(cf, &adapter->cloud_filter_list, list) {
if (cf->state == __I40EVF_CF_ADD_PENDING)
cf->state = __I40EVF_CF_ACTIVE;
}
}
break;
case VIRTCHNL_OP_DEL_CLOUD_FILTER: {
struct i40evf_cloud_filter *cf, *cftmp;
list_for_each_entry_safe(cf, cftmp, &adapter->cloud_filter_list,
list) {
if (cf->state == __I40EVF_CF_DEL_PENDING) {
cf->state = __I40EVF_CF_INVALID;
list_del(&cf->list);
kfree(cf);
adapter->num_cloud_filters--;
}
}
}
break;
default:
if (adapter->current_op && (v_opcode != adapter->current_op))
dev_warn(&adapter->pdev->dev, "Expected response %d from PF, received %d\n",
......
......@@ -136,15 +136,21 @@ enum virtchnl_ops {
VIRTCHNL_OP_ENABLE_VLAN_STRIPPING = 27,
VIRTCHNL_OP_DISABLE_VLAN_STRIPPING = 28,
VIRTCHNL_OP_REQUEST_QUEUES = 29,
VIRTCHNL_OP_ENABLE_CHANNELS = 30,
VIRTCHNL_OP_DISABLE_CHANNELS = 31,
VIRTCHNL_OP_ADD_CLOUD_FILTER = 32,
VIRTCHNL_OP_DEL_CLOUD_FILTER = 33,
};
/* This macro is used to generate a compilation error if a structure
/* These macros are used to generate compilation errors if a structure/union
* is not exactly the correct length. It gives a divide by zero error if the
* structure is not of the correct size, otherwise it creates an enum that is
* never used.
* structure/union is not of the correct size, otherwise it creates an enum
* that is never used.
*/
#define VIRTCHNL_CHECK_STRUCT_LEN(n, X) enum virtchnl_static_assert_enum_##X \
{ virtchnl_static_assert_##X = (n)/((sizeof(struct X) == (n)) ? 1 : 0) }
#define VIRTCHNL_CHECK_UNION_LEN(n, X) enum virtchnl_static_asset_enum_##X \
{ virtchnl_static_assert_##X = (n)/((sizeof(union X) == (n)) ? 1 : 0) }
/* Virtual channel message descriptor. This overlays the admin queue
* descriptor. All other data is passed in external buffers.
......@@ -244,6 +250,7 @@ VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_vsi_resource);
#define VIRTCHNL_VF_OFFLOAD_ENCAP 0X00100000
#define VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM 0X00200000
#define VIRTCHNL_VF_OFFLOAD_RX_ENCAP_CSUM 0X00400000
#define VIRTCHNL_VF_OFFLOAD_ADQ 0X00800000
#define VF_BASE_MODE_OFFLOADS (VIRTCHNL_VF_OFFLOAD_L2 | \
VIRTCHNL_VF_OFFLOAD_VLAN | \
......@@ -496,6 +503,81 @@ struct virtchnl_rss_hena {
VIRTCHNL_CHECK_STRUCT_LEN(8, virtchnl_rss_hena);
/* VIRTCHNL_OP_ENABLE_CHANNELS
* VIRTCHNL_OP_DISABLE_CHANNELS
* VF sends these messages to enable or disable channels based on
* the user specified queue count and queue offset for each traffic class.
* This struct encompasses all the information that the PF needs from
* VF to create a channel.
*/
struct virtchnl_channel_info {
u16 count; /* number of queues in a channel */
u16 offset; /* queues in a channel start from 'offset' */
u32 pad;
u64 max_tx_rate;
};
VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_channel_info);
struct virtchnl_tc_info {
u32 num_tc;
u32 pad;
struct virtchnl_channel_info list[1];
};
VIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_tc_info);
/* VIRTCHNL_ADD_CLOUD_FILTER
* VIRTCHNL_DEL_CLOUD_FILTER
* VF sends these messages to add or delete a cloud filter based on the
* user specified match and action filters. These structures encompass
* all the information that the PF needs from the VF to add/delete a
* cloud filter.
*/
struct virtchnl_l4_spec {
u8 src_mac[ETH_ALEN];
u8 dst_mac[ETH_ALEN];
__be16 vlan_id;
__be16 pad; /* reserved for future use */
__be32 src_ip[4];
__be32 dst_ip[4];
__be16 src_port;
__be16 dst_port;
};
VIRTCHNL_CHECK_STRUCT_LEN(52, virtchnl_l4_spec);
union virtchnl_flow_spec {
struct virtchnl_l4_spec tcp_spec;
u8 buffer[128]; /* reserved for future use */
};
VIRTCHNL_CHECK_UNION_LEN(128, virtchnl_flow_spec);
enum virtchnl_action {
/* action types */
VIRTCHNL_ACTION_DROP = 0,
VIRTCHNL_ACTION_TC_REDIRECT,
};
enum virtchnl_flow_type {
/* flow types */
VIRTCHNL_TCP_V4_FLOW = 0,
VIRTCHNL_TCP_V6_FLOW,
};
struct virtchnl_filter {
union virtchnl_flow_spec data;
union virtchnl_flow_spec mask;
enum virtchnl_flow_type flow_type;
enum virtchnl_action action;
u32 action_meta;
__u8 field_flags;
};
VIRTCHNL_CHECK_STRUCT_LEN(272, virtchnl_filter);
/* VIRTCHNL_OP_EVENT
* PF sends this message to inform the VF driver of events that may affect it.
* No direct response is expected from the VF, though it may generate other
......@@ -711,6 +793,25 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
case VIRTCHNL_OP_REQUEST_QUEUES:
valid_len = sizeof(struct virtchnl_vf_res_request);
break;
case VIRTCHNL_OP_ENABLE_CHANNELS:
valid_len = sizeof(struct virtchnl_tc_info);
if (msglen >= valid_len) {
struct virtchnl_tc_info *vti =
(struct virtchnl_tc_info *)msg;
valid_len += vti->num_tc *
sizeof(struct virtchnl_channel_info);
if (vti->num_tc == 0)
err_msg_format = true;
}
break;
case VIRTCHNL_OP_DISABLE_CHANNELS:
break;
case VIRTCHNL_OP_ADD_CLOUD_FILTER:
valid_len = sizeof(struct virtchnl_filter);
break;
case VIRTCHNL_OP_DEL_CLOUD_FILTER:
valid_len = sizeof(struct virtchnl_filter);
break;
/* These are always errors coming from the VF. */
case VIRTCHNL_OP_EVENT:
case VIRTCHNL_OP_UNKNOWN:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册