Skip to content

Commit

Permalink
i40e/i40evf: support for VF VLAN tag stripping control
Browse files Browse the repository at this point in the history
This patch gives VF capability to control VLAN tag stripping via
ethtool. As rx-vlan-offload was fixed before, now the VF is able to
change it using "ethtool --offload <IF> rxvlan on/off" settings.

Signed-off-by: Mariusz Stachura <mariusz.stachura@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
  • Loading branch information
Mariusz Stachura authored and Jeff Kirsher committed Aug 27, 2017
1 parent 8c9eb35 commit 8774370
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 0 deletions.
60 changes: 60 additions & 0 deletions drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
Original file line number Diff line number Diff line change
Expand Up @@ -2529,6 +2529,60 @@ static int i40e_vc_set_rss_hena(struct i40e_vf *vf, u8 *msg, u16 msglen)
return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_SET_RSS_HENA, aq_ret);
}

/**
* i40e_vc_enable_vlan_stripping
* @vf: pointer to the VF info
* @msg: pointer to the msg buffer
* @msglen: msg length
*
* Enable vlan header stripping for the VF
**/
static int i40e_vc_enable_vlan_stripping(struct i40e_vf *vf, u8 *msg,
u16 msglen)
{
struct i40e_vsi *vsi = vf->pf->vsi[vf->lan_vsi_idx];
i40e_status aq_ret = 0;

if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
aq_ret = I40E_ERR_PARAM;
goto err;
}

i40e_vlan_stripping_enable(vsi);

/* send the response to the VF */
err:
return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
aq_ret);
}

/**
* i40e_vc_disable_vlan_stripping
* @vf: pointer to the VF info
* @msg: pointer to the msg buffer
* @msglen: msg length
*
* Disable vlan header stripping for the VF
**/
static int i40e_vc_disable_vlan_stripping(struct i40e_vf *vf, u8 *msg,
u16 msglen)
{
struct i40e_vsi *vsi = vf->pf->vsi[vf->lan_vsi_idx];
i40e_status aq_ret = 0;

if (!test_bit(I40E_VF_STATE_ACTIVE, &vf->vf_states)) {
aq_ret = I40E_ERR_PARAM;
goto err;
}

i40e_vlan_stripping_disable(vsi);

/* send the response to the VF */
err:
return i40e_vc_send_resp_to_vf(vf, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
aq_ret);
}

/**
* i40e_vc_process_vf_msg
* @pf: pointer to the PF structure
Expand Down Expand Up @@ -2648,6 +2702,12 @@ int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
case VIRTCHNL_OP_SET_RSS_HENA:
ret = i40e_vc_set_rss_hena(vf, msg, msglen);
break;
case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
ret = i40e_vc_enable_vlan_stripping(vf, msg, msglen);
break;
case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
ret = i40e_vc_disable_vlan_stripping(vf, msg, msglen);
break;

case VIRTCHNL_OP_UNKNOWN:
default:
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/intel/i40evf/i40evf.h
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ struct i40evf_adapter {
#define I40EVF_FLAG_AQ_RELEASE_PROMISC BIT(16)
#define I40EVF_FLAG_AQ_REQUEST_ALLMULTI BIT(17)
#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)

/* OS defined structs */
struct net_device *netdev;
Expand Down Expand Up @@ -358,6 +360,8 @@ 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_enable_vlan_stripping(struct i40evf_adapter *adapter);
void i40evf_disable_vlan_stripping(struct i40evf_adapter *adapter);
void i40evf_virtchnl_completion(struct i40evf_adapter *adapter,
enum virtchnl_ops v_opcode,
i40e_status v_retval, u8 *msg, u16 msglen);
Expand Down
33 changes: 33 additions & 0 deletions drivers/net/ethernet/intel/i40evf/i40evf_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1676,6 +1676,16 @@ static void i40evf_watchdog_task(struct work_struct *work)
goto watchdog_done;
}

if (adapter->aq_required & I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING) {
i40evf_enable_vlan_stripping(adapter);
goto watchdog_done;
}

if (adapter->aq_required & I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING) {
i40evf_disable_vlan_stripping(adapter);
goto watchdog_done;
}

if (adapter->aq_required & I40EVF_FLAG_AQ_CONFIGURE_QUEUES) {
i40evf_configure_queues(adapter);
goto watchdog_done;
Expand Down Expand Up @@ -2293,6 +2303,28 @@ static int i40evf_change_mtu(struct net_device *netdev, int new_mtu)
return 0;
}

/**
* i40e_set_features - set the netdev feature flags
* @netdev: ptr to the netdev being adjusted
* @features: the feature set that the stack is suggesting
* Note: expects to be called while under rtnl_lock()
**/
static int i40evf_set_features(struct net_device *netdev,
netdev_features_t features)
{
struct i40evf_adapter *adapter = netdev_priv(netdev);

if (!VLAN_ALLOWED(adapter))
return -EINVAL;

if (features & NETIF_F_HW_VLAN_CTAG_RX)
adapter->aq_required |= I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING;
else
adapter->aq_required |= I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING;

return 0;
}

/**
* i40evf_features_check - Validate encapsulated packet conforms to limits
* @skb: skb buff
Expand Down Expand Up @@ -2386,6 +2418,7 @@ static const struct net_device_ops i40evf_netdev_ops = {
.ndo_vlan_rx_kill_vid = i40evf_vlan_rx_kill_vid,
.ndo_features_check = i40evf_features_check,
.ndo_fix_features = i40evf_fix_features,
.ndo_set_features = i40evf_set_features,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = i40evf_netpoll,
#endif
Expand Down
40 changes: 40 additions & 0 deletions drivers/net/ethernet/intel/i40evf/i40evf_virtchnl.c
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,46 @@ void i40evf_set_rss_lut(struct i40evf_adapter *adapter)
kfree(vrl);
}

/**
* i40evf_enable_vlan_stripping
* @adapter: adapter structure
*
* Request VLAN header stripping to be enabled
**/
void i40evf_enable_vlan_stripping(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 enable stripping, command %d pending\n",
adapter->current_op);
return;
}
adapter->current_op = VIRTCHNL_OP_ENABLE_VLAN_STRIPPING;
adapter->aq_required &= ~I40EVF_FLAG_AQ_ENABLE_VLAN_STRIPPING;
i40evf_send_pf_msg(adapter, VIRTCHNL_OP_ENABLE_VLAN_STRIPPING,
NULL, 0);
}

/**
* i40evf_disable_vlan_stripping
* @adapter: adapter structure
*
* Request VLAN header stripping to be disabled
**/
void i40evf_disable_vlan_stripping(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 disable stripping, command %d pending\n",
adapter->current_op);
return;
}
adapter->current_op = VIRTCHNL_OP_DISABLE_VLAN_STRIPPING;
adapter->aq_required &= ~I40EVF_FLAG_AQ_DISABLE_VLAN_STRIPPING;
i40evf_send_pf_msg(adapter, VIRTCHNL_OP_DISABLE_VLAN_STRIPPING,
NULL, 0);
}

/**
* i40evf_print_link_message - print link up or down
* @adapter: adapter structure
Expand Down
5 changes: 5 additions & 0 deletions include/linux/avf/virtchnl.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ enum virtchnl_ops {
VIRTCHNL_OP_CONFIG_RSS_LUT = 24,
VIRTCHNL_OP_GET_RSS_HENA_CAPS = 25,
VIRTCHNL_OP_SET_RSS_HENA = 26,
VIRTCHNL_OP_ENABLE_VLAN_STRIPPING = 27,
VIRTCHNL_OP_DISABLE_VLAN_STRIPPING = 28,
};

/* This macro is used to generate a compilation error if a structure
Expand Down Expand Up @@ -686,6 +688,9 @@ virtchnl_vc_validate_vf_msg(struct virtchnl_version_info *ver, u32 v_opcode,
case VIRTCHNL_OP_SET_RSS_HENA:
valid_len = sizeof(struct virtchnl_rss_hena);
break;
case VIRTCHNL_OP_ENABLE_VLAN_STRIPPING:
case VIRTCHNL_OP_DISABLE_VLAN_STRIPPING:
break;
/* These are always errors coming from the VF. */
case VIRTCHNL_OP_EVENT:
case VIRTCHNL_OP_UNKNOWN:
Expand Down

0 comments on commit 8774370

Please sign in to comment.