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

-queue

Tony Nguyen says:

====================
Support rx-fcs on/off for VFs

Ahmed Zaki says:

Allow the user to turn on/off the CRC/FCS stripping through ethtool. We
first add the CRC offload capability in the virtchannel, then the feature
is enabled in ice and iavf drivers.

We make sure that the netdev features are fixed such that CRC stripping
cannot be disabled if VLAN rx offload (VLAN strip) is enabled. Also, VLAN
stripping cannot be enabled unless CRC stripping is ON.

Testing was done using tcpdump to make sure that the CRC is included in
the frame after:

    # ethtool -K <interface> rx-fcs on

and is not included when it is back "off". Also, ethtool should return an
error for the above command if "rx-vlan-offload" is already on and at least
one VLAN interface/filter exists on the VF.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2023-09-17 11:46:19 +01:00
commit 319d9c2a93
6 changed files with 141 additions and 7 deletions

View File

@ -406,6 +406,8 @@ struct iavf_adapter {
VIRTCHNL_VF_OFFLOAD_VLAN)
#define VLAN_V2_ALLOWED(_a) ((_a)->vf_res->vf_cap_flags & \
VIRTCHNL_VF_OFFLOAD_VLAN_V2)
#define CRC_OFFLOAD_ALLOWED(_a) ((_a)->vf_res->vf_cap_flags & \
VIRTCHNL_VF_OFFLOAD_CRC)
#define VLAN_V2_FILTERING_ALLOWED(_a) \
(VLAN_V2_ALLOWED((_a)) && \
((_a)->vlan_v2_caps.filtering.filtering_support.outer || \

View File

@ -4401,6 +4401,9 @@ static int iavf_set_features(struct net_device *netdev,
(features & NETIF_VLAN_OFFLOAD_FEATURES))
iavf_set_vlan_offload_features(adapter, netdev->features,
features);
if (CRC_OFFLOAD_ALLOWED(adapter) &&
((netdev->features & NETIF_F_RXFCS) ^ (features & NETIF_F_RXFCS)))
iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
return 0;
}
@ -4522,6 +4525,9 @@ iavf_get_netdev_vlan_hw_features(struct iavf_adapter *adapter)
}
}
if (CRC_OFFLOAD_ALLOWED(adapter))
hw_features |= NETIF_F_RXFCS;
return hw_features;
}
@ -4685,6 +4691,55 @@ iavf_fix_netdev_vlan_features(struct iavf_adapter *adapter,
return requested_features;
}
/**
* iavf_fix_strip_features - fix NETDEV CRC and VLAN strip features
* @adapter: board private structure
* @requested_features: stack requested NETDEV features
*
* Returns fixed-up features bits
**/
static netdev_features_t
iavf_fix_strip_features(struct iavf_adapter *adapter,
netdev_features_t requested_features)
{
struct net_device *netdev = adapter->netdev;
bool crc_offload_req, is_vlan_strip;
netdev_features_t vlan_strip;
int num_non_zero_vlan;
crc_offload_req = CRC_OFFLOAD_ALLOWED(adapter) &&
(requested_features & NETIF_F_RXFCS);
num_non_zero_vlan = iavf_get_num_vlans_added(adapter);
vlan_strip = (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX);
is_vlan_strip = requested_features & vlan_strip;
if (!crc_offload_req)
return requested_features;
if (!num_non_zero_vlan && (netdev->features & vlan_strip) &&
!(netdev->features & NETIF_F_RXFCS) && is_vlan_strip) {
requested_features &= ~vlan_strip;
netdev_info(netdev, "Disabling VLAN stripping as FCS/CRC stripping is also disabled and there is no VLAN configured\n");
return requested_features;
}
if ((netdev->features & NETIF_F_RXFCS) && is_vlan_strip) {
requested_features &= ~vlan_strip;
if (!(netdev->features & vlan_strip))
netdev_info(netdev, "To enable VLAN stripping, first need to enable FCS/CRC stripping");
return requested_features;
}
if (num_non_zero_vlan && is_vlan_strip &&
!(netdev->features & NETIF_F_RXFCS)) {
requested_features &= ~NETIF_F_RXFCS;
netdev_info(netdev, "To disable FCS/CRC stripping, first need to disable VLAN stripping");
}
return requested_features;
}
/**
* iavf_fix_features - fix up the netdev feature bits
* @netdev: our net device
@ -4697,7 +4752,9 @@ static netdev_features_t iavf_fix_features(struct net_device *netdev,
{
struct iavf_adapter *adapter = netdev_priv(netdev);
return iavf_fix_netdev_vlan_features(adapter, features);
features = iavf_fix_netdev_vlan_features(adapter, features);
return iavf_fix_strip_features(adapter, features);
}
static const struct net_device_ops iavf_netdev_ops = {

View File

@ -142,6 +142,7 @@ int iavf_send_vf_config_msg(struct iavf_adapter *adapter)
VIRTCHNL_VF_OFFLOAD_RSS_PCTYPE_V2 |
VIRTCHNL_VF_OFFLOAD_ENCAP |
VIRTCHNL_VF_OFFLOAD_VLAN_V2 |
VIRTCHNL_VF_OFFLOAD_CRC |
VIRTCHNL_VF_OFFLOAD_ENCAP_CSUM |
VIRTCHNL_VF_OFFLOAD_REQ_QUEUES |
VIRTCHNL_VF_OFFLOAD_ADQ |
@ -312,6 +313,9 @@ void iavf_configure_queues(struct iavf_adapter *adapter)
vqpi->rxq.databuffer_size =
ALIGN(adapter->rx_rings[i].rx_buf_len,
BIT_ULL(IAVF_RXQ_CTX_DBUFF_SHIFT));
if (CRC_OFFLOAD_ALLOWED(adapter))
vqpi->rxq.crc_disable = !!(adapter->netdev->features &
NETIF_F_RXFCS);
vqpi++;
}

View File

@ -123,6 +123,9 @@ struct ice_vf {
u8 num_req_qs; /* num of queue pairs requested by VF */
u16 num_mac;
u16 num_vf_qs; /* num of queue configured per VF */
u8 vlan_strip_ena; /* Outer and Inner VLAN strip enable */
#define ICE_INNER_VLAN_STRIP_ENA BIT(0)
#define ICE_OUTER_VLAN_STRIP_ENA BIT(1)
struct ice_mdd_vf_events mdd_rx_events;
struct ice_mdd_vf_events mdd_tx_events;
DECLARE_BITMAP(opcodes_allowlist, VIRTCHNL_OP_MAX);

View File

@ -486,6 +486,9 @@ static int ice_vc_get_vf_res_msg(struct ice_vf *vf, u8 *msg)
if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_REQ_QUEUES)
vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_REQ_QUEUES;
if (vf->driver_caps & VIRTCHNL_VF_OFFLOAD_CRC)
vfres->vf_cap_flags |= VIRTCHNL_VF_OFFLOAD_CRC;
if (vf->driver_caps & VIRTCHNL_VF_CAP_ADV_LINK_SPEED)
vfres->vf_cap_flags |= VIRTCHNL_VF_CAP_ADV_LINK_SPEED;
@ -1620,6 +1623,15 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
goto error_param;
}
for (i = 0; i < qci->num_queue_pairs; i++) {
if (!qci->qpair[i].rxq.crc_disable)
continue;
if (!(vf->driver_caps & VIRTCHNL_VF_OFFLOAD_CRC) ||
vf->vlan_strip_ena)
goto error_param;
}
for (i = 0; i < qci->num_queue_pairs; i++) {
qpi = &qci->qpair[i];
if (qpi->txq.vsi_id != qci->vsi_id ||
@ -1666,6 +1678,13 @@ static int ice_vc_cfg_qs_msg(struct ice_vf *vf, u8 *msg)
vsi->rx_rings[i]->dma = qpi->rxq.dma_ring_addr;
vsi->rx_rings[i]->count = qpi->rxq.ring_len;
if (qpi->rxq.crc_disable)
vsi->rx_rings[q_idx]->flags |=
ICE_RX_FLAGS_CRC_STRIP_DIS;
else
vsi->rx_rings[q_idx]->flags &=
~ICE_RX_FLAGS_CRC_STRIP_DIS;
if (qpi->rxq.databuffer_size != 0 &&
(qpi->rxq.databuffer_size > ((16 * 1024) - 128) ||
qpi->rxq.databuffer_size < 1024))
@ -2410,6 +2429,21 @@ static int ice_vc_remove_vlan_msg(struct ice_vf *vf, u8 *msg)
return ice_vc_process_vlan_msg(vf, msg, false);
}
/**
* ice_vsi_is_rxq_crc_strip_dis - check if Rx queue CRC strip is disabled or not
* @vsi: pointer to the VF VSI info
*/
static bool ice_vsi_is_rxq_crc_strip_dis(struct ice_vsi *vsi)
{
unsigned int i;
ice_for_each_alloc_rxq(vsi, i)
if (vsi->rx_rings[i]->flags & ICE_RX_FLAGS_CRC_STRIP_DIS)
return true;
return false;
}
/**
* ice_vc_ena_vlan_stripping
* @vf: pointer to the VF info
@ -2439,6 +2473,8 @@ static int ice_vc_ena_vlan_stripping(struct ice_vf *vf)
if (vsi->inner_vlan_ops.ena_stripping(vsi, ETH_P_8021Q))
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
else
vf->vlan_strip_ena |= ICE_INNER_VLAN_STRIP_ENA;
error_param:
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
@ -2474,6 +2510,8 @@ static int ice_vc_dis_vlan_stripping(struct ice_vf *vf)
if (vsi->inner_vlan_ops.dis_stripping(vsi))
v_ret = VIRTCHNL_STATUS_ERR_PARAM;
else
vf->vlan_strip_ena &= ~ICE_INNER_VLAN_STRIP_ENA;
error_param:
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
@ -2649,6 +2687,8 @@ static int ice_vf_init_vlan_stripping(struct ice_vf *vf)
{
struct ice_vsi *vsi = ice_get_vf_vsi(vf);
vf->vlan_strip_ena = 0;
if (!vsi)
return -EINVAL;
@ -2658,10 +2698,16 @@ static int ice_vf_init_vlan_stripping(struct ice_vf *vf)
if (ice_vf_is_port_vlan_ena(vf) && !ice_is_dvm_ena(&vsi->back->hw))
return 0;
if (ice_vf_vlan_offload_ena(vf->driver_caps))
return vsi->inner_vlan_ops.ena_stripping(vsi, ETH_P_8021Q);
else
return vsi->inner_vlan_ops.dis_stripping(vsi);
if (ice_vf_vlan_offload_ena(vf->driver_caps)) {
int err;
err = vsi->inner_vlan_ops.ena_stripping(vsi, ETH_P_8021Q);
if (!err)
vf->vlan_strip_ena |= ICE_INNER_VLAN_STRIP_ENA;
return err;
}
return vsi->inner_vlan_ops.dis_stripping(vsi);
}
static u16 ice_vc_get_max_vlan_fltrs(struct ice_vf *vf)
@ -3435,6 +3481,11 @@ static int ice_vc_ena_vlan_stripping_v2_msg(struct ice_vf *vf, u8 *msg)
goto out;
}
if (ice_vsi_is_rxq_crc_strip_dis(vsi)) {
v_ret = VIRTCHNL_STATUS_ERR_NOT_SUPPORTED;
goto out;
}
ethertype_setting = strip_msg->outer_ethertype_setting;
if (ethertype_setting) {
if (ice_vc_ena_vlan_offload(vsi,
@ -3455,6 +3506,8 @@ static int ice_vc_ena_vlan_stripping_v2_msg(struct ice_vf *vf, u8 *msg)
* enabled, is extracted in L2TAG1.
*/
ice_vsi_update_l2tsel(vsi, l2tsel);
vf->vlan_strip_ena |= ICE_OUTER_VLAN_STRIP_ENA;
}
}
@ -3466,6 +3519,9 @@ static int ice_vc_ena_vlan_stripping_v2_msg(struct ice_vf *vf, u8 *msg)
goto out;
}
if (ethertype_setting)
vf->vlan_strip_ena |= ICE_INNER_VLAN_STRIP_ENA;
out:
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING_V2,
v_ret, NULL, 0);
@ -3527,6 +3583,8 @@ static int ice_vc_dis_vlan_stripping_v2_msg(struct ice_vf *vf, u8 *msg)
* in L2TAG1.
*/
ice_vsi_update_l2tsel(vsi, l2tsel);
vf->vlan_strip_ena &= ~ICE_OUTER_VLAN_STRIP_ENA;
}
}
@ -3536,6 +3594,9 @@ static int ice_vc_dis_vlan_stripping_v2_msg(struct ice_vf *vf, u8 *msg)
goto out;
}
if (ethertype_setting)
vf->vlan_strip_ena &= ~ICE_INNER_VLAN_STRIP_ENA;
out:
return ice_vc_send_msg_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING_V2,
v_ret, NULL, 0);

View File

@ -240,6 +240,7 @@ VIRTCHNL_CHECK_STRUCT_LEN(16, virtchnl_vsi_resource);
#define VIRTCHNL_VF_OFFLOAD_REQ_QUEUES BIT(6)
/* used to negotiate communicating link speeds in Mbps */
#define VIRTCHNL_VF_CAP_ADV_LINK_SPEED BIT(7)
#define VIRTCHNL_VF_OFFLOAD_CRC BIT(10)
#define VIRTCHNL_VF_OFFLOAD_VLAN_V2 BIT(15)
#define VIRTCHNL_VF_OFFLOAD_VLAN BIT(16)
#define VIRTCHNL_VF_OFFLOAD_RX_POLLING BIT(17)
@ -295,7 +296,13 @@ VIRTCHNL_CHECK_STRUCT_LEN(24, virtchnl_txq_info);
/* VIRTCHNL_OP_CONFIG_RX_QUEUE
* VF sends this message to set up parameters for one RX queue.
* External data buffer contains one instance of virtchnl_rxq_info.
* PF configures requested queue and returns a status code.
* PF configures requested queue and returns a status code. The
* crc_disable flag disables CRC stripping on the VF. Setting
* the crc_disable flag to 1 will disable CRC stripping for each
* queue in the VF where the flag is set. The VIRTCHNL_VF_OFFLOAD_CRC
* offload must have been set prior to sending this info or the PF
* will ignore the request. This flag should be set the same for
* all of the queues for a VF.
*/
/* Rx queue config info */
@ -307,7 +314,7 @@ struct virtchnl_rxq_info {
u16 splithdr_enabled; /* deprecated with AVF 1.0 */
u32 databuffer_size;
u32 max_pkt_size;
u8 pad0;
u8 crc_disable;
u8 rxdid;
u8 pad1[2];
u64 dma_ring_addr;