Commit bc42afa9 authored by Brett Creeley's avatar Brett Creeley Committed by Tony Nguyen
Browse files

ice: Add new VSI VLAN ops



Incoming changes to support 802.1Q and/or 802.1ad VLAN filtering and
offloads require more flexibility when configuring VLANs. The VSI VLAN
interface will allow flexibility for configuring VLANs for all VSI
types. Add new files to separate the VSI VLAN ops and move functions to
make the code more organized.

Signed-off-by: default avatarBrett Creeley <brett.creeley@intel.com>
Tested-by: default avatarGurucharan G <gurucharanx.g@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 3e0b5971
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ ice-y := ice_main.o \
	 ice_txrx_lib.o	\
	 ice_txrx.o	\
	 ice_fltr.o	\
	 ice_vsi_vlan_ops.o \
	 ice_vsi_vlan_lib.o \
	 ice_fdir.o	\
	 ice_ethtool_fdir.o \
	 ice_flex_pipe.o \
+2 −0
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@
#include "ice_repr.h"
#include "ice_eswitch.h"
#include "ice_lag.h"
#include "ice_vsi_vlan_ops.h"

#define ICE_BAR0		0
#define ICE_REQ_DESC_MULTIPLE	32
@@ -368,6 +369,7 @@ struct ice_vsi {
	u8 irqs_ready:1;
	u8 current_isup:1;		 /* Sync 'link up' logging */
	u8 stat_offsets_loaded:1;
	struct ice_vsi_vlan_ops vlan_ops;
	u16 num_vlan;

	/* queue information */
+1 −1
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ static int ice_eswitch_setup_env(struct ice_pf *pf)
	struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi;
	bool rule_added = false;

	ice_vsi_manage_vlan_stripping(ctrl_vsi, false);
	ctrl_vsi->vlan_ops.dis_stripping(ctrl_vsi);

	ice_remove_vsi_fltr(&pf->hw, uplink_vsi->idx);

+5 −201
Original line number Diff line number Diff line
@@ -1737,62 +1737,6 @@ void ice_update_eth_stats(struct ice_vsi *vsi)
	vsi->stat_offsets_loaded = true;
}

/**
 * ice_vsi_add_vlan - Add VSI membership for given VLAN
 * @vsi: the VSI being configured
 * @vid: VLAN ID to be added
 * @action: filter action to be performed on match
 */
int
ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid, enum ice_sw_fwd_act_type action)
{
	struct ice_pf *pf = vsi->back;
	struct device *dev;
	int err = 0;

	dev = ice_pf_to_dev(pf);

	if (!ice_fltr_add_vlan(vsi, vid, action)) {
		vsi->num_vlan++;
	} else {
		err = -ENODEV;
		dev_err(dev, "Failure Adding VLAN %d on VSI %i\n", vid,
			vsi->vsi_num);
	}

	return err;
}

/**
 * ice_vsi_kill_vlan - Remove VSI membership for a given VLAN
 * @vsi: the VSI being configured
 * @vid: VLAN ID to be removed
 *
 * Returns 0 on success and negative on failure
 */
int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid)
{
	struct ice_pf *pf = vsi->back;
	struct device *dev;
	int err;

	dev = ice_pf_to_dev(pf);

	err = ice_fltr_remove_vlan(vsi, vid, ICE_FWD_TO_VSI);
	if (!err) {
		vsi->num_vlan--;
	} else if (err == -ENOENT) {
		dev_dbg(dev, "Failed to remove VLAN %d on VSI %i, it does not exist, error: %d\n",
			vid, vsi->vsi_num, err);
		err = 0;
	} else {
		dev_err(dev, "Error removing VLAN %d on vsi %i error: %d\n",
			vid, vsi->vsi_num, err);
	}

	return err;
}

/**
 * ice_vsi_cfg_frame_size - setup max frame size and Rx buffer length
 * @vsi: VSI
@@ -2120,95 +2064,6 @@ void ice_vsi_cfg_msix(struct ice_vsi *vsi)
	}
}

/**
 * ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx
 * @vsi: the VSI being changed
 */
int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi)
{
	struct ice_hw *hw = &vsi->back->hw;
	struct ice_vsi_ctx *ctxt;
	int ret;

	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
	if (!ctxt)
		return -ENOMEM;

	/* Here we are configuring the VSI to let the driver add VLAN tags by
	 * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag
	 * insertion happens in the Tx hot path, in ice_tx_map.
	 */
	ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL;

	/* Preserve existing VLAN strip setting */
	ctxt->info.vlan_flags |= (vsi->info.vlan_flags &
				  ICE_AQ_VSI_VLAN_EMOD_M);

	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);

	ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
	if (ret) {
		dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN insert failed, err %d aq_err %s\n",
			ret, ice_aq_str(hw->adminq.sq_last_status));
		goto out;
	}

	vsi->info.vlan_flags = ctxt->info.vlan_flags;
out:
	kfree(ctxt);
	return ret;
}

/**
 * ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx
 * @vsi: the VSI being changed
 * @ena: boolean value indicating if this is a enable or disable request
 */
int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena)
{
	struct ice_hw *hw = &vsi->back->hw;
	struct ice_vsi_ctx *ctxt;
	int ret;

	/* do not allow modifying VLAN stripping when a port VLAN is configured
	 * on this VSI
	 */
	if (vsi->info.pvid)
		return 0;

	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
	if (!ctxt)
		return -ENOMEM;

	/* Here we are configuring what the VSI should do with the VLAN tag in
	 * the Rx packet. We can either leave the tag in the packet or put it in
	 * the Rx descriptor.
	 */
	if (ena)
		/* Strip VLAN tag from Rx packet and put it in the desc */
		ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH;
	else
		/* Disable stripping. Leave tag in packet */
		ctxt->info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING;

	/* Allow all packets untagged/tagged */
	ctxt->info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL;

	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);

	ret = ice_update_vsi(hw, vsi->idx, ctxt, NULL);
	if (ret) {
		dev_err(ice_pf_to_dev(vsi->back), "update VSI for VLAN strip failed, ena = %d err %d aq_err %s\n",
			ena, ret, ice_aq_str(hw->adminq.sq_last_status));
		goto out;
	}

	vsi->info.vlan_flags = ctxt->info.vlan_flags;
out:
	kfree(ctxt);
	return ret;
}

/**
 * ice_vsi_start_all_rx_rings - start/enable all of a VSI's Rx rings
 * @vsi: the VSI whose rings are to be enabled
@@ -2302,61 +2157,6 @@ bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi)
	return (vsi->info.sw_flags2 & ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA);
}

/**
 * ice_cfg_vlan_pruning - enable or disable VLAN pruning on the VSI
 * @vsi: VSI to enable or disable VLAN pruning on
 * @ena: set to true to enable VLAN pruning and false to disable it
 *
 * returns 0 if VSI is updated, negative otherwise
 */
int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena)
{
	struct ice_vsi_ctx *ctxt;
	struct ice_pf *pf;
	int status;

	if (!vsi)
		return -EINVAL;

	/* Don't enable VLAN pruning if the netdev is currently in promiscuous
	 * mode. VLAN pruning will be enabled when the interface exits
	 * promiscuous mode if any VLAN filters are active.
	 */
	if (vsi->netdev && vsi->netdev->flags & IFF_PROMISC && ena)
		return 0;

	pf = vsi->back;
	ctxt = kzalloc(sizeof(*ctxt), GFP_KERNEL);
	if (!ctxt)
		return -ENOMEM;

	ctxt->info = vsi->info;

	if (ena)
		ctxt->info.sw_flags2 |= ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;
	else
		ctxt->info.sw_flags2 &= ~ICE_AQ_VSI_SW_FLAG_RX_VLAN_PRUNE_ENA;

	ctxt->info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_SW_VALID);

	status = ice_update_vsi(&pf->hw, vsi->idx, ctxt, NULL);
	if (status) {
		netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %d, aq_err = %s\n",
			   ena ? "En" : "Dis", vsi->idx, vsi->vsi_num,
			   status, ice_aq_str(pf->hw.adminq.sq_last_status));
		goto err_out;
	}

	vsi->info.sw_flags2 = ctxt->info.sw_flags2;

	kfree(ctxt);
	return 0;

err_out:
	kfree(ctxt);
	return -EIO;
}

static void ice_vsi_set_tc_cfg(struct ice_vsi *vsi)
{
	if (!test_bit(ICE_FLAG_DCB_ENA, vsi->back->flags)) {
@@ -2636,6 +2436,8 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
	if (ret)
		goto unroll_get_qs;

	ice_vsi_init_vlan_ops(vsi);

	switch (vsi->type) {
	case ICE_VSI_CTRL:
	case ICE_VSI_SWITCHDEV_CTRL:
@@ -3299,6 +3101,8 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
	if (vtype == ICE_VSI_VF)
		vf = &pf->vf[vsi->vf_id];

	ice_vsi_init_vlan_ops(vsi);

	coalesce = kcalloc(vsi->num_q_vectors,
			   sizeof(struct ice_coalesce_stored), GFP_KERNEL);
	if (!coalesce)
@@ -4117,7 +3921,7 @@ int ice_set_link(struct ice_vsi *vsi, bool ena)
 */
int ice_vsi_add_vlan_zero(struct ice_vsi *vsi)
{
	return ice_vsi_add_vlan(vsi, 0, ICE_FWD_TO_VSI);
	return vsi->vlan_ops.add_vlan(vsi, 0, ICE_FWD_TO_VSI);
}

/**
+0 −11
Original line number Diff line number Diff line
@@ -22,15 +22,6 @@ int ice_vsi_cfg_lan_txqs(struct ice_vsi *vsi);

void ice_vsi_cfg_msix(struct ice_vsi *vsi);

int
ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid, enum ice_sw_fwd_act_type action);

int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid);

int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi);

int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena);

int ice_vsi_start_all_rx_rings(struct ice_vsi *vsi);

int ice_vsi_stop_all_rx_rings(struct ice_vsi *vsi);
@@ -45,8 +36,6 @@ int ice_vsi_stop_xdp_tx_rings(struct ice_vsi *vsi);

bool ice_vsi_is_vlan_pruning_ena(struct ice_vsi *vsi);

int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena);

void ice_cfg_sw_lldp(struct ice_vsi *vsi, bool tx, bool create);

int ice_set_link(struct ice_vsi *vsi, bool ena);
Loading