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