145d3d428SAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0
245d3d428SAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */
345d3d428SAnirudh Venkataramanan 
445d3d428SAnirudh Venkataramanan #include "ice.h"
545d3d428SAnirudh Venkataramanan #include "ice_lib.h"
645d3d428SAnirudh Venkataramanan 
745d3d428SAnirudh Venkataramanan /**
845d3d428SAnirudh Venkataramanan  * ice_add_mac_to_list - Add a mac address filter entry to the list
945d3d428SAnirudh Venkataramanan  * @vsi: the VSI to be forwarded to
1045d3d428SAnirudh Venkataramanan  * @add_list: pointer to the list which contains MAC filter entries
1145d3d428SAnirudh Venkataramanan  * @macaddr: the MAC address to be added.
1245d3d428SAnirudh Venkataramanan  *
1345d3d428SAnirudh Venkataramanan  * Adds mac address filter entry to the temp list
1445d3d428SAnirudh Venkataramanan  *
1545d3d428SAnirudh Venkataramanan  * Returns 0 on success or ENOMEM on failure.
1645d3d428SAnirudh Venkataramanan  */
1745d3d428SAnirudh Venkataramanan int ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list,
1845d3d428SAnirudh Venkataramanan 			const u8 *macaddr)
1945d3d428SAnirudh Venkataramanan {
2045d3d428SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
2145d3d428SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
2245d3d428SAnirudh Venkataramanan 
2345d3d428SAnirudh Venkataramanan 	tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_ATOMIC);
2445d3d428SAnirudh Venkataramanan 	if (!tmp)
2545d3d428SAnirudh Venkataramanan 		return -ENOMEM;
2645d3d428SAnirudh Venkataramanan 
2745d3d428SAnirudh Venkataramanan 	tmp->fltr_info.flag = ICE_FLTR_TX;
2845d3d428SAnirudh Venkataramanan 	tmp->fltr_info.src = vsi->vsi_num;
2945d3d428SAnirudh Venkataramanan 	tmp->fltr_info.lkup_type = ICE_SW_LKUP_MAC;
3045d3d428SAnirudh Venkataramanan 	tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
3145d3d428SAnirudh Venkataramanan 	tmp->fltr_info.fwd_id.vsi_id = vsi->vsi_num;
3245d3d428SAnirudh Venkataramanan 	ether_addr_copy(tmp->fltr_info.l_data.mac.mac_addr, macaddr);
3345d3d428SAnirudh Venkataramanan 
3445d3d428SAnirudh Venkataramanan 	INIT_LIST_HEAD(&tmp->list_entry);
3545d3d428SAnirudh Venkataramanan 	list_add(&tmp->list_entry, add_list);
3645d3d428SAnirudh Venkataramanan 
3745d3d428SAnirudh Venkataramanan 	return 0;
3845d3d428SAnirudh Venkataramanan }
3945d3d428SAnirudh Venkataramanan 
4045d3d428SAnirudh Venkataramanan /**
4145d3d428SAnirudh Venkataramanan  * ice_update_eth_stats - Update VSI-specific ethernet statistics counters
4245d3d428SAnirudh Venkataramanan  * @vsi: the VSI to be updated
4345d3d428SAnirudh Venkataramanan  */
4445d3d428SAnirudh Venkataramanan void ice_update_eth_stats(struct ice_vsi *vsi)
4545d3d428SAnirudh Venkataramanan {
4645d3d428SAnirudh Venkataramanan 	struct ice_eth_stats *prev_es, *cur_es;
4745d3d428SAnirudh Venkataramanan 	struct ice_hw *hw = &vsi->back->hw;
4845d3d428SAnirudh Venkataramanan 	u16 vsi_num = vsi->vsi_num;    /* HW absolute index of a VSI */
4945d3d428SAnirudh Venkataramanan 
5045d3d428SAnirudh Venkataramanan 	prev_es = &vsi->eth_stats_prev;
5145d3d428SAnirudh Venkataramanan 	cur_es = &vsi->eth_stats;
5245d3d428SAnirudh Venkataramanan 
5345d3d428SAnirudh Venkataramanan 	ice_stat_update40(hw, GLV_GORCH(vsi_num), GLV_GORCL(vsi_num),
5445d3d428SAnirudh Venkataramanan 			  vsi->stat_offsets_loaded, &prev_es->rx_bytes,
5545d3d428SAnirudh Venkataramanan 			  &cur_es->rx_bytes);
5645d3d428SAnirudh Venkataramanan 
5745d3d428SAnirudh Venkataramanan 	ice_stat_update40(hw, GLV_UPRCH(vsi_num), GLV_UPRCL(vsi_num),
5845d3d428SAnirudh Venkataramanan 			  vsi->stat_offsets_loaded, &prev_es->rx_unicast,
5945d3d428SAnirudh Venkataramanan 			  &cur_es->rx_unicast);
6045d3d428SAnirudh Venkataramanan 
6145d3d428SAnirudh Venkataramanan 	ice_stat_update40(hw, GLV_MPRCH(vsi_num), GLV_MPRCL(vsi_num),
6245d3d428SAnirudh Venkataramanan 			  vsi->stat_offsets_loaded, &prev_es->rx_multicast,
6345d3d428SAnirudh Venkataramanan 			  &cur_es->rx_multicast);
6445d3d428SAnirudh Venkataramanan 
6545d3d428SAnirudh Venkataramanan 	ice_stat_update40(hw, GLV_BPRCH(vsi_num), GLV_BPRCL(vsi_num),
6645d3d428SAnirudh Venkataramanan 			  vsi->stat_offsets_loaded, &prev_es->rx_broadcast,
6745d3d428SAnirudh Venkataramanan 			  &cur_es->rx_broadcast);
6845d3d428SAnirudh Venkataramanan 
6945d3d428SAnirudh Venkataramanan 	ice_stat_update32(hw, GLV_RDPC(vsi_num), vsi->stat_offsets_loaded,
7045d3d428SAnirudh Venkataramanan 			  &prev_es->rx_discards, &cur_es->rx_discards);
7145d3d428SAnirudh Venkataramanan 
7245d3d428SAnirudh Venkataramanan 	ice_stat_update40(hw, GLV_GOTCH(vsi_num), GLV_GOTCL(vsi_num),
7345d3d428SAnirudh Venkataramanan 			  vsi->stat_offsets_loaded, &prev_es->tx_bytes,
7445d3d428SAnirudh Venkataramanan 			  &cur_es->tx_bytes);
7545d3d428SAnirudh Venkataramanan 
7645d3d428SAnirudh Venkataramanan 	ice_stat_update40(hw, GLV_UPTCH(vsi_num), GLV_UPTCL(vsi_num),
7745d3d428SAnirudh Venkataramanan 			  vsi->stat_offsets_loaded, &prev_es->tx_unicast,
7845d3d428SAnirudh Venkataramanan 			  &cur_es->tx_unicast);
7945d3d428SAnirudh Venkataramanan 
8045d3d428SAnirudh Venkataramanan 	ice_stat_update40(hw, GLV_MPTCH(vsi_num), GLV_MPTCL(vsi_num),
8145d3d428SAnirudh Venkataramanan 			  vsi->stat_offsets_loaded, &prev_es->tx_multicast,
8245d3d428SAnirudh Venkataramanan 			  &cur_es->tx_multicast);
8345d3d428SAnirudh Venkataramanan 
8445d3d428SAnirudh Venkataramanan 	ice_stat_update40(hw, GLV_BPTCH(vsi_num), GLV_BPTCL(vsi_num),
8545d3d428SAnirudh Venkataramanan 			  vsi->stat_offsets_loaded, &prev_es->tx_broadcast,
8645d3d428SAnirudh Venkataramanan 			  &cur_es->tx_broadcast);
8745d3d428SAnirudh Venkataramanan 
8845d3d428SAnirudh Venkataramanan 	ice_stat_update32(hw, GLV_TEPC(vsi_num), vsi->stat_offsets_loaded,
8945d3d428SAnirudh Venkataramanan 			  &prev_es->tx_errors, &cur_es->tx_errors);
9045d3d428SAnirudh Venkataramanan 
9145d3d428SAnirudh Venkataramanan 	vsi->stat_offsets_loaded = true;
9245d3d428SAnirudh Venkataramanan }
9345d3d428SAnirudh Venkataramanan 
9445d3d428SAnirudh Venkataramanan /**
9545d3d428SAnirudh Venkataramanan  * ice_free_fltr_list - free filter lists helper
9645d3d428SAnirudh Venkataramanan  * @dev: pointer to the device struct
9745d3d428SAnirudh Venkataramanan  * @h: pointer to the list head to be freed
9845d3d428SAnirudh Venkataramanan  *
9945d3d428SAnirudh Venkataramanan  * Helper function to free filter lists previously created using
10045d3d428SAnirudh Venkataramanan  * ice_add_mac_to_list
10145d3d428SAnirudh Venkataramanan  */
10245d3d428SAnirudh Venkataramanan void ice_free_fltr_list(struct device *dev, struct list_head *h)
10345d3d428SAnirudh Venkataramanan {
10445d3d428SAnirudh Venkataramanan 	struct ice_fltr_list_entry *e, *tmp;
10545d3d428SAnirudh Venkataramanan 
10645d3d428SAnirudh Venkataramanan 	list_for_each_entry_safe(e, tmp, h, list_entry) {
10745d3d428SAnirudh Venkataramanan 		list_del(&e->list_entry);
10845d3d428SAnirudh Venkataramanan 		devm_kfree(dev, e);
10945d3d428SAnirudh Venkataramanan 	}
11045d3d428SAnirudh Venkataramanan }
11145d3d428SAnirudh Venkataramanan 
11245d3d428SAnirudh Venkataramanan /**
11345d3d428SAnirudh Venkataramanan  * ice_vsi_add_vlan - Add VSI membership for given VLAN
11445d3d428SAnirudh Venkataramanan  * @vsi: the VSI being configured
11545d3d428SAnirudh Venkataramanan  * @vid: VLAN id to be added
11645d3d428SAnirudh Venkataramanan  */
11745d3d428SAnirudh Venkataramanan int ice_vsi_add_vlan(struct ice_vsi *vsi, u16 vid)
11845d3d428SAnirudh Venkataramanan {
11945d3d428SAnirudh Venkataramanan 	struct ice_fltr_list_entry *tmp;
12045d3d428SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
12145d3d428SAnirudh Venkataramanan 	LIST_HEAD(tmp_add_list);
12245d3d428SAnirudh Venkataramanan 	enum ice_status status;
12345d3d428SAnirudh Venkataramanan 	int err = 0;
12445d3d428SAnirudh Venkataramanan 
12545d3d428SAnirudh Venkataramanan 	tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_KERNEL);
12645d3d428SAnirudh Venkataramanan 	if (!tmp)
12745d3d428SAnirudh Venkataramanan 		return -ENOMEM;
12845d3d428SAnirudh Venkataramanan 
12945d3d428SAnirudh Venkataramanan 	tmp->fltr_info.lkup_type = ICE_SW_LKUP_VLAN;
13045d3d428SAnirudh Venkataramanan 	tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
13145d3d428SAnirudh Venkataramanan 	tmp->fltr_info.flag = ICE_FLTR_TX;
13245d3d428SAnirudh Venkataramanan 	tmp->fltr_info.src = vsi->vsi_num;
13345d3d428SAnirudh Venkataramanan 	tmp->fltr_info.fwd_id.vsi_id = vsi->vsi_num;
13445d3d428SAnirudh Venkataramanan 	tmp->fltr_info.l_data.vlan.vlan_id = vid;
13545d3d428SAnirudh Venkataramanan 
13645d3d428SAnirudh Venkataramanan 	INIT_LIST_HEAD(&tmp->list_entry);
13745d3d428SAnirudh Venkataramanan 	list_add(&tmp->list_entry, &tmp_add_list);
13845d3d428SAnirudh Venkataramanan 
13945d3d428SAnirudh Venkataramanan 	status = ice_add_vlan(&pf->hw, &tmp_add_list);
14045d3d428SAnirudh Venkataramanan 	if (status) {
14145d3d428SAnirudh Venkataramanan 		err = -ENODEV;
14245d3d428SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "Failure Adding VLAN %d on VSI %i\n",
14345d3d428SAnirudh Venkataramanan 			vid, vsi->vsi_num);
14445d3d428SAnirudh Venkataramanan 	}
14545d3d428SAnirudh Venkataramanan 
14645d3d428SAnirudh Venkataramanan 	ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
14745d3d428SAnirudh Venkataramanan 	return err;
14845d3d428SAnirudh Venkataramanan }
14945d3d428SAnirudh Venkataramanan 
15045d3d428SAnirudh Venkataramanan /**
15145d3d428SAnirudh Venkataramanan  * ice_vsi_kill_vlan - Remove VSI membership for a given VLAN
15245d3d428SAnirudh Venkataramanan  * @vsi: the VSI being configured
15345d3d428SAnirudh Venkataramanan  * @vid: VLAN id to be removed
15445d3d428SAnirudh Venkataramanan  *
15545d3d428SAnirudh Venkataramanan  * Returns 0 on success and negative on failure
15645d3d428SAnirudh Venkataramanan  */
15745d3d428SAnirudh Venkataramanan int ice_vsi_kill_vlan(struct ice_vsi *vsi, u16 vid)
15845d3d428SAnirudh Venkataramanan {
15945d3d428SAnirudh Venkataramanan 	struct ice_fltr_list_entry *list;
16045d3d428SAnirudh Venkataramanan 	struct ice_pf *pf = vsi->back;
16145d3d428SAnirudh Venkataramanan 	LIST_HEAD(tmp_add_list);
16245d3d428SAnirudh Venkataramanan 	int status = 0;
16345d3d428SAnirudh Venkataramanan 
16445d3d428SAnirudh Venkataramanan 	list = devm_kzalloc(&pf->pdev->dev, sizeof(*list), GFP_KERNEL);
16545d3d428SAnirudh Venkataramanan 	if (!list)
16645d3d428SAnirudh Venkataramanan 		return -ENOMEM;
16745d3d428SAnirudh Venkataramanan 
16845d3d428SAnirudh Venkataramanan 	list->fltr_info.lkup_type = ICE_SW_LKUP_VLAN;
16945d3d428SAnirudh Venkataramanan 	list->fltr_info.fwd_id.vsi_id = vsi->vsi_num;
17045d3d428SAnirudh Venkataramanan 	list->fltr_info.fltr_act = ICE_FWD_TO_VSI;
17145d3d428SAnirudh Venkataramanan 	list->fltr_info.l_data.vlan.vlan_id = vid;
17245d3d428SAnirudh Venkataramanan 	list->fltr_info.flag = ICE_FLTR_TX;
17345d3d428SAnirudh Venkataramanan 	list->fltr_info.src = vsi->vsi_num;
17445d3d428SAnirudh Venkataramanan 
17545d3d428SAnirudh Venkataramanan 	INIT_LIST_HEAD(&list->list_entry);
17645d3d428SAnirudh Venkataramanan 	list_add(&list->list_entry, &tmp_add_list);
17745d3d428SAnirudh Venkataramanan 
17845d3d428SAnirudh Venkataramanan 	if (ice_remove_vlan(&pf->hw, &tmp_add_list)) {
17945d3d428SAnirudh Venkataramanan 		dev_err(&pf->pdev->dev, "Error removing VLAN %d on vsi %i\n",
18045d3d428SAnirudh Venkataramanan 			vid, vsi->vsi_num);
18145d3d428SAnirudh Venkataramanan 		status = -EIO;
18245d3d428SAnirudh Venkataramanan 	}
18345d3d428SAnirudh Venkataramanan 
18445d3d428SAnirudh Venkataramanan 	ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
18545d3d428SAnirudh Venkataramanan 	return status;
18645d3d428SAnirudh Venkataramanan }
18745d3d428SAnirudh Venkataramanan 
18845d3d428SAnirudh Venkataramanan /**
18945d3d428SAnirudh Venkataramanan  * ice_vsi_manage_vlan_insertion - Manage VLAN insertion for the VSI for Tx
19045d3d428SAnirudh Venkataramanan  * @vsi: the VSI being changed
19145d3d428SAnirudh Venkataramanan  */
19245d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_insertion(struct ice_vsi *vsi)
19345d3d428SAnirudh Venkataramanan {
19445d3d428SAnirudh Venkataramanan 	struct device *dev = &vsi->back->pdev->dev;
19545d3d428SAnirudh Venkataramanan 	struct ice_hw *hw = &vsi->back->hw;
19645d3d428SAnirudh Venkataramanan 	struct ice_vsi_ctx ctxt = { 0 };
19745d3d428SAnirudh Venkataramanan 	enum ice_status status;
19845d3d428SAnirudh Venkataramanan 
19945d3d428SAnirudh Venkataramanan 	/* Here we are configuring the VSI to let the driver add VLAN tags by
20045d3d428SAnirudh Venkataramanan 	 * setting vlan_flags to ICE_AQ_VSI_VLAN_MODE_ALL. The actual VLAN tag
20145d3d428SAnirudh Venkataramanan 	 * insertion happens in the Tx hot path, in ice_tx_map.
20245d3d428SAnirudh Venkataramanan 	 */
20345d3d428SAnirudh Venkataramanan 	ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_ALL;
20445d3d428SAnirudh Venkataramanan 
20545d3d428SAnirudh Venkataramanan 	ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
20645d3d428SAnirudh Venkataramanan 	ctxt.vsi_num = vsi->vsi_num;
20745d3d428SAnirudh Venkataramanan 
20845d3d428SAnirudh Venkataramanan 	status = ice_aq_update_vsi(hw, &ctxt, NULL);
20945d3d428SAnirudh Venkataramanan 	if (status) {
21045d3d428SAnirudh Venkataramanan 		dev_err(dev, "update VSI for VLAN insert failed, err %d aq_err %d\n",
21145d3d428SAnirudh Venkataramanan 			status, hw->adminq.sq_last_status);
21245d3d428SAnirudh Venkataramanan 		return -EIO;
21345d3d428SAnirudh Venkataramanan 	}
21445d3d428SAnirudh Venkataramanan 
21545d3d428SAnirudh Venkataramanan 	vsi->info.vlan_flags = ctxt.info.vlan_flags;
21645d3d428SAnirudh Venkataramanan 	return 0;
21745d3d428SAnirudh Venkataramanan }
21845d3d428SAnirudh Venkataramanan 
21945d3d428SAnirudh Venkataramanan /**
22045d3d428SAnirudh Venkataramanan  * ice_vsi_manage_vlan_stripping - Manage VLAN stripping for the VSI for Rx
22145d3d428SAnirudh Venkataramanan  * @vsi: the VSI being changed
22245d3d428SAnirudh Venkataramanan  * @ena: boolean value indicating if this is a enable or disable request
22345d3d428SAnirudh Venkataramanan  */
22445d3d428SAnirudh Venkataramanan int ice_vsi_manage_vlan_stripping(struct ice_vsi *vsi, bool ena)
22545d3d428SAnirudh Venkataramanan {
22645d3d428SAnirudh Venkataramanan 	struct device *dev = &vsi->back->pdev->dev;
22745d3d428SAnirudh Venkataramanan 	struct ice_hw *hw = &vsi->back->hw;
22845d3d428SAnirudh Venkataramanan 	struct ice_vsi_ctx ctxt = { 0 };
22945d3d428SAnirudh Venkataramanan 	enum ice_status status;
23045d3d428SAnirudh Venkataramanan 
23145d3d428SAnirudh Venkataramanan 	/* Here we are configuring what the VSI should do with the VLAN tag in
23245d3d428SAnirudh Venkataramanan 	 * the Rx packet. We can either leave the tag in the packet or put it in
23345d3d428SAnirudh Venkataramanan 	 * the Rx descriptor.
23445d3d428SAnirudh Venkataramanan 	 */
23545d3d428SAnirudh Venkataramanan 	if (ena) {
23645d3d428SAnirudh Venkataramanan 		/* Strip VLAN tag from Rx packet and put it in the desc */
23745d3d428SAnirudh Venkataramanan 		ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_STR_BOTH;
23845d3d428SAnirudh Venkataramanan 	} else {
23945d3d428SAnirudh Venkataramanan 		/* Disable stripping. Leave tag in packet */
24045d3d428SAnirudh Venkataramanan 		ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_EMOD_NOTHING;
24145d3d428SAnirudh Venkataramanan 	}
24245d3d428SAnirudh Venkataramanan 
24345d3d428SAnirudh Venkataramanan 	/* Allow all packets untagged/tagged */
24445d3d428SAnirudh Venkataramanan 	ctxt.info.vlan_flags |= ICE_AQ_VSI_VLAN_MODE_ALL;
24545d3d428SAnirudh Venkataramanan 
24645d3d428SAnirudh Venkataramanan 	ctxt.info.valid_sections = cpu_to_le16(ICE_AQ_VSI_PROP_VLAN_VALID);
24745d3d428SAnirudh Venkataramanan 	ctxt.vsi_num = vsi->vsi_num;
24845d3d428SAnirudh Venkataramanan 
24945d3d428SAnirudh Venkataramanan 	status = ice_aq_update_vsi(hw, &ctxt, NULL);
25045d3d428SAnirudh Venkataramanan 	if (status) {
25145d3d428SAnirudh Venkataramanan 		dev_err(dev, "update VSI for VLAN strip failed, ena = %d err %d aq_err %d\n",
25245d3d428SAnirudh Venkataramanan 			ena, status, hw->adminq.sq_last_status);
25345d3d428SAnirudh Venkataramanan 		return -EIO;
25445d3d428SAnirudh Venkataramanan 	}
25545d3d428SAnirudh Venkataramanan 
25645d3d428SAnirudh Venkataramanan 	vsi->info.vlan_flags = ctxt.info.vlan_flags;
25745d3d428SAnirudh Venkataramanan 	return 0;
25845d3d428SAnirudh Venkataramanan }
259