ice: Move common functions out of ice_main.c part 4/7
This patch continues the code move out of ice_main.c The following top level functions (and related dependency functions) were moved to ice_lib.c: ice_vsi_alloc_rings ice_vsi_set_rss_params ice_vsi_set_num_qs ice_get_free_slot ice_vsi_init ice_vsi_clear_rings ice_vsi_alloc_arrays Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
parent
5153a18e57
commit
28c2a64573
|
@ -225,6 +225,102 @@ static int ice_vsi_ctrl_rx_rings(struct ice_vsi *vsi, bool ena)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the VSI
|
||||||
|
* @vsi: VSI pointer
|
||||||
|
* @alloc_qvectors: a bool to specify if q_vectors need to be allocated.
|
||||||
|
*
|
||||||
|
* On error: returns error code (negative)
|
||||||
|
* On success: returns 0
|
||||||
|
*/
|
||||||
|
int ice_vsi_alloc_arrays(struct ice_vsi *vsi, bool alloc_qvectors)
|
||||||
|
{
|
||||||
|
struct ice_pf *pf = vsi->back;
|
||||||
|
|
||||||
|
/* allocate memory for both Tx and Rx ring pointers */
|
||||||
|
vsi->tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq,
|
||||||
|
sizeof(struct ice_ring *), GFP_KERNEL);
|
||||||
|
if (!vsi->tx_rings)
|
||||||
|
goto err_txrings;
|
||||||
|
|
||||||
|
vsi->rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq,
|
||||||
|
sizeof(struct ice_ring *), GFP_KERNEL);
|
||||||
|
if (!vsi->rx_rings)
|
||||||
|
goto err_rxrings;
|
||||||
|
|
||||||
|
if (alloc_qvectors) {
|
||||||
|
/* allocate memory for q_vector pointers */
|
||||||
|
vsi->q_vectors = devm_kcalloc(&pf->pdev->dev,
|
||||||
|
vsi->num_q_vectors,
|
||||||
|
sizeof(struct ice_q_vector *),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!vsi->q_vectors)
|
||||||
|
goto err_vectors;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_vectors:
|
||||||
|
devm_kfree(&pf->pdev->dev, vsi->rx_rings);
|
||||||
|
err_rxrings:
|
||||||
|
devm_kfree(&pf->pdev->dev, vsi->tx_rings);
|
||||||
|
err_txrings:
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_vsi_set_num_qs - Set num queues, descriptors and vectors for a VSI
|
||||||
|
* @vsi: the VSI being configured
|
||||||
|
*
|
||||||
|
* Return 0 on success and a negative value on error
|
||||||
|
*/
|
||||||
|
void ice_vsi_set_num_qs(struct ice_vsi *vsi)
|
||||||
|
{
|
||||||
|
struct ice_pf *pf = vsi->back;
|
||||||
|
|
||||||
|
switch (vsi->type) {
|
||||||
|
case ICE_VSI_PF:
|
||||||
|
vsi->alloc_txq = pf->num_lan_tx;
|
||||||
|
vsi->alloc_rxq = pf->num_lan_rx;
|
||||||
|
vsi->num_desc = ALIGN(ICE_DFLT_NUM_DESC, ICE_REQ_DESC_MULTIPLE);
|
||||||
|
vsi->num_q_vectors = max_t(int, pf->num_lan_rx, pf->num_lan_tx);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_warn(&vsi->back->pdev->dev, "Unknown VSI type %d\n",
|
||||||
|
vsi->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_get_free_slot - get the next non-NULL location index in array
|
||||||
|
* @array: array to search
|
||||||
|
* @size: size of the array
|
||||||
|
* @curr: last known occupied index to be used as a search hint
|
||||||
|
*
|
||||||
|
* void * is being used to keep the functionality generic. This lets us use this
|
||||||
|
* function on any array of pointers.
|
||||||
|
*/
|
||||||
|
int ice_get_free_slot(void *array, int size, int curr)
|
||||||
|
{
|
||||||
|
int **tmp_array = (int **)array;
|
||||||
|
int next;
|
||||||
|
|
||||||
|
if (curr < (size - 1) && !tmp_array[curr + 1]) {
|
||||||
|
next = curr + 1;
|
||||||
|
} else {
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while ((i < size) && (tmp_array[i]))
|
||||||
|
i++;
|
||||||
|
if (i == size)
|
||||||
|
next = ICE_NO_VSI;
|
||||||
|
else
|
||||||
|
next = i;
|
||||||
|
}
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_vsi_delete - delete a VSI from the switch
|
* ice_vsi_delete - delete a VSI from the switch
|
||||||
* @vsi: pointer to VSI being removed
|
* @vsi: pointer to VSI being removed
|
||||||
|
@ -286,6 +382,324 @@ void ice_vsi_put_qs(struct ice_vsi *vsi)
|
||||||
mutex_unlock(&pf->avail_q_mutex);
|
mutex_unlock(&pf->avail_q_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_vsi_set_rss_params - Setup RSS capabilities per VSI type
|
||||||
|
* @vsi: the VSI being configured
|
||||||
|
*/
|
||||||
|
void ice_vsi_set_rss_params(struct ice_vsi *vsi)
|
||||||
|
{
|
||||||
|
struct ice_hw_common_caps *cap;
|
||||||
|
struct ice_pf *pf = vsi->back;
|
||||||
|
|
||||||
|
if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
|
||||||
|
vsi->rss_size = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cap = &pf->hw.func_caps.common_cap;
|
||||||
|
switch (vsi->type) {
|
||||||
|
case ICE_VSI_PF:
|
||||||
|
/* PF VSI will inherit RSS instance of PF */
|
||||||
|
vsi->rss_table_size = cap->rss_table_size;
|
||||||
|
vsi->rss_size = min_t(int, num_online_cpus(),
|
||||||
|
BIT(cap->rss_table_entry_width));
|
||||||
|
vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n",
|
||||||
|
vsi->type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI
|
||||||
|
* @ctxt: the VSI context being set
|
||||||
|
*
|
||||||
|
* This initializes a default VSI context for all sections except the Queues.
|
||||||
|
*/
|
||||||
|
static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt)
|
||||||
|
{
|
||||||
|
u32 table = 0;
|
||||||
|
|
||||||
|
memset(&ctxt->info, 0, sizeof(ctxt->info));
|
||||||
|
/* VSI's should be allocated from shared pool */
|
||||||
|
ctxt->alloc_from_pool = true;
|
||||||
|
/* Src pruning enabled by default */
|
||||||
|
ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE;
|
||||||
|
/* Traffic from VSI can be sent to LAN */
|
||||||
|
ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA;
|
||||||
|
/* By default bits 3 and 4 in vlan_flags are 0's which results in legacy
|
||||||
|
* behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all
|
||||||
|
* packets untagged/tagged.
|
||||||
|
*/
|
||||||
|
ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL &
|
||||||
|
ICE_AQ_VSI_VLAN_MODE_M) >>
|
||||||
|
ICE_AQ_VSI_VLAN_MODE_S);
|
||||||
|
/* Have 1:1 UP mapping for both ingress/egress tables */
|
||||||
|
table |= ICE_UP_TABLE_TRANSLATE(0, 0);
|
||||||
|
table |= ICE_UP_TABLE_TRANSLATE(1, 1);
|
||||||
|
table |= ICE_UP_TABLE_TRANSLATE(2, 2);
|
||||||
|
table |= ICE_UP_TABLE_TRANSLATE(3, 3);
|
||||||
|
table |= ICE_UP_TABLE_TRANSLATE(4, 4);
|
||||||
|
table |= ICE_UP_TABLE_TRANSLATE(5, 5);
|
||||||
|
table |= ICE_UP_TABLE_TRANSLATE(6, 6);
|
||||||
|
table |= ICE_UP_TABLE_TRANSLATE(7, 7);
|
||||||
|
ctxt->info.ingress_table = cpu_to_le32(table);
|
||||||
|
ctxt->info.egress_table = cpu_to_le32(table);
|
||||||
|
/* Have 1:1 UP mapping for outer to inner UP table */
|
||||||
|
ctxt->info.outer_up_table = cpu_to_le32(table);
|
||||||
|
/* No Outer tag support outer_tag_flags remains to zero */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_vsi_setup_q_map - Setup a VSI queue map
|
||||||
|
* @vsi: the VSI being configured
|
||||||
|
* @ctxt: VSI context structure
|
||||||
|
*/
|
||||||
|
static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
|
||||||
|
{
|
||||||
|
u16 offset = 0, qmap = 0, numq_tc;
|
||||||
|
u16 pow = 0, max_rss = 0, qcount;
|
||||||
|
u16 qcount_tx = vsi->alloc_txq;
|
||||||
|
u16 qcount_rx = vsi->alloc_rxq;
|
||||||
|
bool ena_tc0 = false;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* at least TC0 should be enabled by default */
|
||||||
|
if (vsi->tc_cfg.numtc) {
|
||||||
|
if (!(vsi->tc_cfg.ena_tc & BIT(0)))
|
||||||
|
ena_tc0 = true;
|
||||||
|
} else {
|
||||||
|
ena_tc0 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ena_tc0) {
|
||||||
|
vsi->tc_cfg.numtc++;
|
||||||
|
vsi->tc_cfg.ena_tc |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
numq_tc = qcount_rx / vsi->tc_cfg.numtc;
|
||||||
|
|
||||||
|
/* TC mapping is a function of the number of Rx queues assigned to the
|
||||||
|
* VSI for each traffic class and the offset of these queues.
|
||||||
|
* The first 10 bits are for queue offset for TC0, next 4 bits for no:of
|
||||||
|
* queues allocated to TC0. No:of queues is a power-of-2.
|
||||||
|
*
|
||||||
|
* If TC is not enabled, the queue offset is set to 0, and allocate one
|
||||||
|
* queue, this way, traffic for the given TC will be sent to the default
|
||||||
|
* queue.
|
||||||
|
*
|
||||||
|
* Setup number and offset of Rx queues for all TCs for the VSI
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* qcount will change if RSS is enabled */
|
||||||
|
if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) {
|
||||||
|
if (vsi->type == ICE_VSI_PF)
|
||||||
|
max_rss = ICE_MAX_LG_RSS_QS;
|
||||||
|
else
|
||||||
|
max_rss = ICE_MAX_SMALL_RSS_QS;
|
||||||
|
|
||||||
|
qcount = min_t(int, numq_tc, max_rss);
|
||||||
|
qcount = min_t(int, qcount, vsi->rss_size);
|
||||||
|
} else {
|
||||||
|
qcount = numq_tc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the (rounded up) power-of-2 of qcount */
|
||||||
|
pow = order_base_2(qcount);
|
||||||
|
|
||||||
|
for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
|
||||||
|
if (!(vsi->tc_cfg.ena_tc & BIT(i))) {
|
||||||
|
/* TC is not enabled */
|
||||||
|
vsi->tc_cfg.tc_info[i].qoffset = 0;
|
||||||
|
vsi->tc_cfg.tc_info[i].qcount = 1;
|
||||||
|
ctxt->info.tc_mapping[i] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TC is enabled */
|
||||||
|
vsi->tc_cfg.tc_info[i].qoffset = offset;
|
||||||
|
vsi->tc_cfg.tc_info[i].qcount = qcount;
|
||||||
|
|
||||||
|
qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) &
|
||||||
|
ICE_AQ_VSI_TC_Q_OFFSET_M) |
|
||||||
|
((pow << ICE_AQ_VSI_TC_Q_NUM_S) &
|
||||||
|
ICE_AQ_VSI_TC_Q_NUM_M);
|
||||||
|
offset += qcount;
|
||||||
|
ctxt->info.tc_mapping[i] = cpu_to_le16(qmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
vsi->num_txq = qcount_tx;
|
||||||
|
vsi->num_rxq = offset;
|
||||||
|
|
||||||
|
/* Rx queue mapping */
|
||||||
|
ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG);
|
||||||
|
/* q_mapping buffer holds the info for the first queue allocated for
|
||||||
|
* this VSI in the PF space and also the number of queues associated
|
||||||
|
* with this VSI.
|
||||||
|
*/
|
||||||
|
ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]);
|
||||||
|
ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI
|
||||||
|
* @ctxt: the VSI context being set
|
||||||
|
* @vsi: the VSI being configured
|
||||||
|
*/
|
||||||
|
static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)
|
||||||
|
{
|
||||||
|
u8 lut_type, hash_type;
|
||||||
|
|
||||||
|
switch (vsi->type) {
|
||||||
|
case ICE_VSI_PF:
|
||||||
|
/* PF VSI will inherit RSS instance of PF */
|
||||||
|
lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF;
|
||||||
|
hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_warn(&vsi->back->pdev->dev, "Unknown VSI type %d\n",
|
||||||
|
vsi->type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) &
|
||||||
|
ICE_AQ_VSI_Q_OPT_RSS_LUT_M) |
|
||||||
|
((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) &
|
||||||
|
ICE_AQ_VSI_Q_OPT_RSS_HASH_M);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_vsi_init - Create and initialize a VSI
|
||||||
|
* @vsi: the VSI being configured
|
||||||
|
*
|
||||||
|
* This initializes a VSI context depending on the VSI type to be added and
|
||||||
|
* passes it down to the add_vsi aq command to create a new VSI.
|
||||||
|
*/
|
||||||
|
int ice_vsi_init(struct ice_vsi *vsi)
|
||||||
|
{
|
||||||
|
struct ice_vsi_ctx ctxt = { 0 };
|
||||||
|
struct ice_pf *pf = vsi->back;
|
||||||
|
struct ice_hw *hw = &pf->hw;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
switch (vsi->type) {
|
||||||
|
case ICE_VSI_PF:
|
||||||
|
ctxt.flags = ICE_AQ_VSI_TYPE_PF;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
ice_set_dflt_vsi_ctx(&ctxt);
|
||||||
|
/* if the switch is in VEB mode, allow VSI loopback */
|
||||||
|
if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB)
|
||||||
|
ctxt.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
|
||||||
|
|
||||||
|
/* Set LUT type and HASH type if RSS is enabled */
|
||||||
|
if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
|
||||||
|
ice_set_rss_vsi_ctx(&ctxt, vsi);
|
||||||
|
|
||||||
|
ctxt.info.sw_id = vsi->port_info->sw_id;
|
||||||
|
ice_vsi_setup_q_map(vsi, &ctxt);
|
||||||
|
|
||||||
|
ret = ice_add_vsi(hw, vsi->idx, &ctxt, NULL);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&pf->pdev->dev,
|
||||||
|
"Add VSI failed, err %d\n", ret);
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* keep context for update VSI operations */
|
||||||
|
vsi->info = ctxt.info;
|
||||||
|
|
||||||
|
/* record VSI number returned */
|
||||||
|
vsi->vsi_num = ctxt.vsi_num;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI
|
||||||
|
* @vsi: the VSI having rings deallocated
|
||||||
|
*/
|
||||||
|
void ice_vsi_clear_rings(struct ice_vsi *vsi)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (vsi->tx_rings) {
|
||||||
|
for (i = 0; i < vsi->alloc_txq; i++) {
|
||||||
|
if (vsi->tx_rings[i]) {
|
||||||
|
kfree_rcu(vsi->tx_rings[i], rcu);
|
||||||
|
vsi->tx_rings[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vsi->rx_rings) {
|
||||||
|
for (i = 0; i < vsi->alloc_rxq; i++) {
|
||||||
|
if (vsi->rx_rings[i]) {
|
||||||
|
kfree_rcu(vsi->rx_rings[i], rcu);
|
||||||
|
vsi->rx_rings[i] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI
|
||||||
|
* @vsi: VSI which is having rings allocated
|
||||||
|
*/
|
||||||
|
int ice_vsi_alloc_rings(struct ice_vsi *vsi)
|
||||||
|
{
|
||||||
|
struct ice_pf *pf = vsi->back;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Allocate tx_rings */
|
||||||
|
for (i = 0; i < vsi->alloc_txq; i++) {
|
||||||
|
struct ice_ring *ring;
|
||||||
|
|
||||||
|
/* allocate with kzalloc(), free with kfree_rcu() */
|
||||||
|
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
|
||||||
|
|
||||||
|
if (!ring)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
ring->q_index = i;
|
||||||
|
ring->reg_idx = vsi->txq_map[i];
|
||||||
|
ring->ring_active = false;
|
||||||
|
ring->vsi = vsi;
|
||||||
|
ring->dev = &pf->pdev->dev;
|
||||||
|
ring->count = vsi->num_desc;
|
||||||
|
vsi->tx_rings[i] = ring;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Allocate rx_rings */
|
||||||
|
for (i = 0; i < vsi->alloc_rxq; i++) {
|
||||||
|
struct ice_ring *ring;
|
||||||
|
|
||||||
|
/* allocate with kzalloc(), free with kfree_rcu() */
|
||||||
|
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
|
||||||
|
if (!ring)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
|
ring->q_index = i;
|
||||||
|
ring->reg_idx = vsi->rxq_map[i];
|
||||||
|
ring->ring_active = false;
|
||||||
|
ring->vsi = vsi;
|
||||||
|
ring->netdev = vsi->netdev;
|
||||||
|
ring->dev = &pf->pdev->dev;
|
||||||
|
ring->count = vsi->num_desc;
|
||||||
|
vsi->rx_rings[i] = ring;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err_out:
|
||||||
|
ice_vsi_clear_rings(vsi);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_add_mac_to_list - Add a mac address filter entry to the list
|
* ice_add_mac_to_list - Add a mac address filter entry to the list
|
||||||
* @vsi: the VSI to be forwarded to
|
* @vsi: the VSI to be forwarded to
|
||||||
|
|
|
@ -6,6 +6,20 @@
|
||||||
|
|
||||||
#include "ice.h"
|
#include "ice.h"
|
||||||
|
|
||||||
|
int ice_vsi_alloc_rings(struct ice_vsi *vsi);
|
||||||
|
|
||||||
|
void ice_vsi_set_rss_params(struct ice_vsi *vsi);
|
||||||
|
|
||||||
|
void ice_vsi_set_num_qs(struct ice_vsi *vsi);
|
||||||
|
|
||||||
|
int ice_get_free_slot(void *array, int size, int curr);
|
||||||
|
|
||||||
|
int ice_vsi_init(struct ice_vsi *vsi);
|
||||||
|
|
||||||
|
void ice_vsi_clear_rings(struct ice_vsi *vsi);
|
||||||
|
|
||||||
|
int ice_vsi_alloc_arrays(struct ice_vsi *vsi, bool alloc_qvectors);
|
||||||
|
|
||||||
int ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list,
|
int ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list,
|
||||||
const u8 *macaddr);
|
const u8 *macaddr);
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ static const struct net_device_ops ice_netdev_ops;
|
||||||
static void ice_pf_dis_all_vsi(struct ice_pf *pf);
|
static void ice_pf_dis_all_vsi(struct ice_pf *pf);
|
||||||
static void ice_rebuild(struct ice_pf *pf);
|
static void ice_rebuild(struct ice_pf *pf);
|
||||||
static int ice_vsi_release(struct ice_vsi *vsi);
|
static int ice_vsi_release(struct ice_vsi *vsi);
|
||||||
|
|
||||||
static void ice_vsi_release_all(struct ice_pf *pf);
|
static void ice_vsi_release_all(struct ice_pf *pf);
|
||||||
static void ice_update_vsi_stats(struct ice_vsi *vsi);
|
static void ice_update_vsi_stats(struct ice_vsi *vsi);
|
||||||
static void ice_update_pf_stats(struct ice_pf *pf);
|
static void ice_update_pf_stats(struct ice_pf *pf);
|
||||||
|
@ -112,35 +113,6 @@ static void ice_check_for_hang_subtask(struct ice_pf *pf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ice_get_free_slot - get the next non-NULL location index in array
|
|
||||||
* @array: array to search
|
|
||||||
* @size: size of the array
|
|
||||||
* @curr: last known occupied index to be used as a search hint
|
|
||||||
*
|
|
||||||
* void * is being used to keep the functionality generic. This lets us use this
|
|
||||||
* function on any array of pointers.
|
|
||||||
*/
|
|
||||||
static int ice_get_free_slot(void *array, int size, int curr)
|
|
||||||
{
|
|
||||||
int **tmp_array = (int **)array;
|
|
||||||
int next;
|
|
||||||
|
|
||||||
if (curr < (size - 1) && !tmp_array[curr + 1]) {
|
|
||||||
next = curr + 1;
|
|
||||||
} else {
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while ((i < size) && (tmp_array[i]))
|
|
||||||
i++;
|
|
||||||
if (i == size)
|
|
||||||
next = ICE_NO_VSI;
|
|
||||||
else
|
|
||||||
next = i;
|
|
||||||
}
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_add_mac_to_sync_list - creates list of mac addresses to be synced
|
* ice_add_mac_to_sync_list - creates list of mac addresses to be synced
|
||||||
* @netdev: the net device on which the sync is happening
|
* @netdev: the net device on which the sync is happening
|
||||||
|
@ -1210,327 +1182,6 @@ free_q_irqs:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ice_vsi_set_rss_params - Setup RSS capabilities per VSI type
|
|
||||||
* @vsi: the VSI being configured
|
|
||||||
*/
|
|
||||||
static void ice_vsi_set_rss_params(struct ice_vsi *vsi)
|
|
||||||
{
|
|
||||||
struct ice_hw_common_caps *cap;
|
|
||||||
struct ice_pf *pf = vsi->back;
|
|
||||||
|
|
||||||
if (!test_bit(ICE_FLAG_RSS_ENA, pf->flags)) {
|
|
||||||
vsi->rss_size = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cap = &pf->hw.func_caps.common_cap;
|
|
||||||
switch (vsi->type) {
|
|
||||||
case ICE_VSI_PF:
|
|
||||||
/* PF VSI will inherit RSS instance of PF */
|
|
||||||
vsi->rss_table_size = cap->rss_table_size;
|
|
||||||
vsi->rss_size = min_t(int, num_online_cpus(),
|
|
||||||
BIT(cap->rss_table_entry_width));
|
|
||||||
vsi->rss_lut_type = ICE_AQC_GSET_RSS_LUT_TABLE_TYPE_PF;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dev_warn(&pf->pdev->dev, "Unknown VSI type %d\n", vsi->type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ice_vsi_setup_q_map - Setup a VSI queue map
|
|
||||||
* @vsi: the VSI being configured
|
|
||||||
* @ctxt: VSI context structure
|
|
||||||
*/
|
|
||||||
static void ice_vsi_setup_q_map(struct ice_vsi *vsi, struct ice_vsi_ctx *ctxt)
|
|
||||||
{
|
|
||||||
u16 offset = 0, qmap = 0, numq_tc;
|
|
||||||
u16 pow = 0, max_rss = 0, qcount;
|
|
||||||
u16 qcount_tx = vsi->alloc_txq;
|
|
||||||
u16 qcount_rx = vsi->alloc_rxq;
|
|
||||||
bool ena_tc0 = false;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* at least TC0 should be enabled by default */
|
|
||||||
if (vsi->tc_cfg.numtc) {
|
|
||||||
if (!(vsi->tc_cfg.ena_tc & BIT(0)))
|
|
||||||
ena_tc0 = true;
|
|
||||||
} else {
|
|
||||||
ena_tc0 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ena_tc0) {
|
|
||||||
vsi->tc_cfg.numtc++;
|
|
||||||
vsi->tc_cfg.ena_tc |= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
numq_tc = qcount_rx / vsi->tc_cfg.numtc;
|
|
||||||
|
|
||||||
/* TC mapping is a function of the number of Rx queues assigned to the
|
|
||||||
* VSI for each traffic class and the offset of these queues.
|
|
||||||
* The first 10 bits are for queue offset for TC0, next 4 bits for no:of
|
|
||||||
* queues allocated to TC0. No:of queues is a power-of-2.
|
|
||||||
*
|
|
||||||
* If TC is not enabled, the queue offset is set to 0, and allocate one
|
|
||||||
* queue, this way, traffic for the given TC will be sent to the default
|
|
||||||
* queue.
|
|
||||||
*
|
|
||||||
* Setup number and offset of Rx queues for all TCs for the VSI
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* qcount will change if RSS is enabled */
|
|
||||||
if (test_bit(ICE_FLAG_RSS_ENA, vsi->back->flags)) {
|
|
||||||
if (vsi->type == ICE_VSI_PF)
|
|
||||||
max_rss = ICE_MAX_LG_RSS_QS;
|
|
||||||
else
|
|
||||||
max_rss = ICE_MAX_SMALL_RSS_QS;
|
|
||||||
|
|
||||||
qcount = min_t(int, numq_tc, max_rss);
|
|
||||||
qcount = min_t(int, qcount, vsi->rss_size);
|
|
||||||
} else {
|
|
||||||
qcount = numq_tc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find the (rounded up) power-of-2 of qcount */
|
|
||||||
pow = order_base_2(qcount);
|
|
||||||
|
|
||||||
for (i = 0; i < ICE_MAX_TRAFFIC_CLASS; i++) {
|
|
||||||
if (!(vsi->tc_cfg.ena_tc & BIT(i))) {
|
|
||||||
/* TC is not enabled */
|
|
||||||
vsi->tc_cfg.tc_info[i].qoffset = 0;
|
|
||||||
vsi->tc_cfg.tc_info[i].qcount = 1;
|
|
||||||
ctxt->info.tc_mapping[i] = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TC is enabled */
|
|
||||||
vsi->tc_cfg.tc_info[i].qoffset = offset;
|
|
||||||
vsi->tc_cfg.tc_info[i].qcount = qcount;
|
|
||||||
|
|
||||||
qmap = ((offset << ICE_AQ_VSI_TC_Q_OFFSET_S) &
|
|
||||||
ICE_AQ_VSI_TC_Q_OFFSET_M) |
|
|
||||||
((pow << ICE_AQ_VSI_TC_Q_NUM_S) &
|
|
||||||
ICE_AQ_VSI_TC_Q_NUM_M);
|
|
||||||
offset += qcount;
|
|
||||||
ctxt->info.tc_mapping[i] = cpu_to_le16(qmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
vsi->num_txq = qcount_tx;
|
|
||||||
vsi->num_rxq = offset;
|
|
||||||
|
|
||||||
/* Rx queue mapping */
|
|
||||||
ctxt->info.mapping_flags |= cpu_to_le16(ICE_AQ_VSI_Q_MAP_CONTIG);
|
|
||||||
/* q_mapping buffer holds the info for the first queue allocated for
|
|
||||||
* this VSI in the PF space and also the number of queues associated
|
|
||||||
* with this VSI.
|
|
||||||
*/
|
|
||||||
ctxt->info.q_mapping[0] = cpu_to_le16(vsi->rxq_map[0]);
|
|
||||||
ctxt->info.q_mapping[1] = cpu_to_le16(vsi->num_rxq);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ice_set_dflt_vsi_ctx - Set default VSI context before adding a VSI
|
|
||||||
* @ctxt: the VSI context being set
|
|
||||||
*
|
|
||||||
* This initializes a default VSI context for all sections except the Queues.
|
|
||||||
*/
|
|
||||||
static void ice_set_dflt_vsi_ctx(struct ice_vsi_ctx *ctxt)
|
|
||||||
{
|
|
||||||
u32 table = 0;
|
|
||||||
|
|
||||||
memset(&ctxt->info, 0, sizeof(ctxt->info));
|
|
||||||
/* VSI's should be allocated from shared pool */
|
|
||||||
ctxt->alloc_from_pool = true;
|
|
||||||
/* Src pruning enabled by default */
|
|
||||||
ctxt->info.sw_flags = ICE_AQ_VSI_SW_FLAG_SRC_PRUNE;
|
|
||||||
/* Traffic from VSI can be sent to LAN */
|
|
||||||
ctxt->info.sw_flags2 = ICE_AQ_VSI_SW_FLAG_LAN_ENA;
|
|
||||||
|
|
||||||
/* By default bits 3 and 4 in vlan_flags are 0's which results in legacy
|
|
||||||
* behavior (show VLAN, DEI, and UP) in descriptor. Also, allow all
|
|
||||||
* packets untagged/tagged.
|
|
||||||
*/
|
|
||||||
ctxt->info.vlan_flags = ((ICE_AQ_VSI_VLAN_MODE_ALL &
|
|
||||||
ICE_AQ_VSI_VLAN_MODE_M) >>
|
|
||||||
ICE_AQ_VSI_VLAN_MODE_S);
|
|
||||||
|
|
||||||
/* Have 1:1 UP mapping for both ingress/egress tables */
|
|
||||||
table |= ICE_UP_TABLE_TRANSLATE(0, 0);
|
|
||||||
table |= ICE_UP_TABLE_TRANSLATE(1, 1);
|
|
||||||
table |= ICE_UP_TABLE_TRANSLATE(2, 2);
|
|
||||||
table |= ICE_UP_TABLE_TRANSLATE(3, 3);
|
|
||||||
table |= ICE_UP_TABLE_TRANSLATE(4, 4);
|
|
||||||
table |= ICE_UP_TABLE_TRANSLATE(5, 5);
|
|
||||||
table |= ICE_UP_TABLE_TRANSLATE(6, 6);
|
|
||||||
table |= ICE_UP_TABLE_TRANSLATE(7, 7);
|
|
||||||
ctxt->info.ingress_table = cpu_to_le32(table);
|
|
||||||
ctxt->info.egress_table = cpu_to_le32(table);
|
|
||||||
/* Have 1:1 UP mapping for outer to inner UP table */
|
|
||||||
ctxt->info.outer_up_table = cpu_to_le32(table);
|
|
||||||
/* No Outer tag support outer_tag_flags remains to zero */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ice_set_rss_vsi_ctx - Set RSS VSI context before adding a VSI
|
|
||||||
* @ctxt: the VSI context being set
|
|
||||||
* @vsi: the VSI being configured
|
|
||||||
*/
|
|
||||||
static void ice_set_rss_vsi_ctx(struct ice_vsi_ctx *ctxt, struct ice_vsi *vsi)
|
|
||||||
{
|
|
||||||
u8 lut_type, hash_type;
|
|
||||||
|
|
||||||
switch (vsi->type) {
|
|
||||||
case ICE_VSI_PF:
|
|
||||||
/* PF VSI will inherit RSS instance of PF */
|
|
||||||
lut_type = ICE_AQ_VSI_Q_OPT_RSS_LUT_PF;
|
|
||||||
hash_type = ICE_AQ_VSI_Q_OPT_RSS_TPLZ;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dev_warn(&vsi->back->pdev->dev, "Unknown VSI type %d\n",
|
|
||||||
vsi->type);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxt->info.q_opt_rss = ((lut_type << ICE_AQ_VSI_Q_OPT_RSS_LUT_S) &
|
|
||||||
ICE_AQ_VSI_Q_OPT_RSS_LUT_M) |
|
|
||||||
((hash_type << ICE_AQ_VSI_Q_OPT_RSS_HASH_S) &
|
|
||||||
ICE_AQ_VSI_Q_OPT_RSS_HASH_M);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ice_vsi_init - Create and initialize a VSI
|
|
||||||
* @vsi: the VSI being configured
|
|
||||||
*
|
|
||||||
* This initializes a VSI context depending on the VSI type to be added and
|
|
||||||
* passes it down to the add_vsi aq command to create a new VSI.
|
|
||||||
*/
|
|
||||||
static int ice_vsi_init(struct ice_vsi *vsi)
|
|
||||||
{
|
|
||||||
struct ice_vsi_ctx ctxt = { 0 };
|
|
||||||
struct ice_pf *pf = vsi->back;
|
|
||||||
struct ice_hw *hw = &pf->hw;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
switch (vsi->type) {
|
|
||||||
case ICE_VSI_PF:
|
|
||||||
ctxt.flags = ICE_AQ_VSI_TYPE_PF;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return -ENODEV;
|
|
||||||
}
|
|
||||||
|
|
||||||
ice_set_dflt_vsi_ctx(&ctxt);
|
|
||||||
/* if the switch is in VEB mode, allow VSI loopback */
|
|
||||||
if (vsi->vsw->bridge_mode == BRIDGE_MODE_VEB)
|
|
||||||
ctxt.info.sw_flags |= ICE_AQ_VSI_SW_FLAG_ALLOW_LB;
|
|
||||||
|
|
||||||
/* Set LUT type and HASH type if RSS is enabled */
|
|
||||||
if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
|
|
||||||
ice_set_rss_vsi_ctx(&ctxt, vsi);
|
|
||||||
|
|
||||||
ctxt.info.sw_id = vsi->port_info->sw_id;
|
|
||||||
ice_vsi_setup_q_map(vsi, &ctxt);
|
|
||||||
|
|
||||||
ret = ice_add_vsi(hw, vsi->idx, &ctxt, NULL);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(&pf->pdev->dev,
|
|
||||||
"Add VSI failed, err %d\n", ret);
|
|
||||||
return -EIO;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* keep context for update VSI operations */
|
|
||||||
vsi->info = ctxt.info;
|
|
||||||
|
|
||||||
/* record VSI number returned */
|
|
||||||
vsi->vsi_num = ctxt.vsi_num;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ice_vsi_clear_rings - Deallocates the Tx and Rx rings for VSI
|
|
||||||
* @vsi: the VSI having rings deallocated
|
|
||||||
*/
|
|
||||||
static void ice_vsi_clear_rings(struct ice_vsi *vsi)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (vsi->tx_rings) {
|
|
||||||
for (i = 0; i < vsi->alloc_txq; i++) {
|
|
||||||
if (vsi->tx_rings[i]) {
|
|
||||||
kfree_rcu(vsi->tx_rings[i], rcu);
|
|
||||||
vsi->tx_rings[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (vsi->rx_rings) {
|
|
||||||
for (i = 0; i < vsi->alloc_rxq; i++) {
|
|
||||||
if (vsi->rx_rings[i]) {
|
|
||||||
kfree_rcu(vsi->rx_rings[i], rcu);
|
|
||||||
vsi->rx_rings[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ice_vsi_alloc_rings - Allocates Tx and Rx rings for the VSI
|
|
||||||
* @vsi: VSI which is having rings allocated
|
|
||||||
*/
|
|
||||||
static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
|
|
||||||
{
|
|
||||||
struct ice_pf *pf = vsi->back;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Allocate tx_rings */
|
|
||||||
for (i = 0; i < vsi->alloc_txq; i++) {
|
|
||||||
struct ice_ring *ring;
|
|
||||||
|
|
||||||
/* allocate with kzalloc(), free with kfree_rcu() */
|
|
||||||
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
|
|
||||||
|
|
||||||
if (!ring)
|
|
||||||
goto err_out;
|
|
||||||
|
|
||||||
ring->q_index = i;
|
|
||||||
ring->reg_idx = vsi->txq_map[i];
|
|
||||||
ring->ring_active = false;
|
|
||||||
ring->vsi = vsi;
|
|
||||||
ring->netdev = vsi->netdev;
|
|
||||||
ring->dev = &pf->pdev->dev;
|
|
||||||
ring->count = vsi->num_desc;
|
|
||||||
|
|
||||||
vsi->tx_rings[i] = ring;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate rx_rings */
|
|
||||||
for (i = 0; i < vsi->alloc_rxq; i++) {
|
|
||||||
struct ice_ring *ring;
|
|
||||||
|
|
||||||
/* allocate with kzalloc(), free with kfree_rcu() */
|
|
||||||
ring = kzalloc(sizeof(*ring), GFP_KERNEL);
|
|
||||||
if (!ring)
|
|
||||||
goto err_out;
|
|
||||||
|
|
||||||
ring->q_index = i;
|
|
||||||
ring->reg_idx = vsi->rxq_map[i];
|
|
||||||
ring->ring_active = false;
|
|
||||||
ring->vsi = vsi;
|
|
||||||
ring->netdev = vsi->netdev;
|
|
||||||
ring->dev = &pf->pdev->dev;
|
|
||||||
ring->count = vsi->num_desc;
|
|
||||||
vsi->rx_rings[i] = ring;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_out:
|
|
||||||
ice_vsi_clear_rings(vsi);
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_ena_misc_vector - enable the non-queue interrupts
|
* ice_ena_misc_vector - enable the non-queue interrupts
|
||||||
* @pf: board private structure
|
* @pf: board private structure
|
||||||
|
@ -1716,73 +1367,6 @@ static void ice_vsi_map_rings_to_vectors(struct ice_vsi *vsi)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ice_vsi_set_num_qs - Set num queues, descriptors and vectors for a VSI
|
|
||||||
* @vsi: the VSI being configured
|
|
||||||
*
|
|
||||||
* Return 0 on success and a negative value on error
|
|
||||||
*/
|
|
||||||
static void ice_vsi_set_num_qs(struct ice_vsi *vsi)
|
|
||||||
{
|
|
||||||
struct ice_pf *pf = vsi->back;
|
|
||||||
|
|
||||||
switch (vsi->type) {
|
|
||||||
case ICE_VSI_PF:
|
|
||||||
vsi->alloc_txq = pf->num_lan_tx;
|
|
||||||
vsi->alloc_rxq = pf->num_lan_rx;
|
|
||||||
vsi->num_desc = ALIGN(ICE_DFLT_NUM_DESC, ICE_REQ_DESC_MULTIPLE);
|
|
||||||
vsi->num_q_vectors = max_t(int, pf->num_lan_rx, pf->num_lan_tx);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dev_warn(&vsi->back->pdev->dev, "Unknown VSI type %d\n",
|
|
||||||
vsi->type);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ice_vsi_alloc_arrays - Allocate queue and vector pointer arrays for the vsi
|
|
||||||
* @vsi: VSI pointer
|
|
||||||
* @alloc_qvectors: a bool to specify if q_vectors need to be allocated.
|
|
||||||
*
|
|
||||||
* On error: returns error code (negative)
|
|
||||||
* On success: returns 0
|
|
||||||
*/
|
|
||||||
static int ice_vsi_alloc_arrays(struct ice_vsi *vsi, bool alloc_qvectors)
|
|
||||||
{
|
|
||||||
struct ice_pf *pf = vsi->back;
|
|
||||||
|
|
||||||
/* allocate memory for both Tx and Rx ring pointers */
|
|
||||||
vsi->tx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_txq,
|
|
||||||
sizeof(struct ice_ring *), GFP_KERNEL);
|
|
||||||
if (!vsi->tx_rings)
|
|
||||||
goto err_txrings;
|
|
||||||
|
|
||||||
vsi->rx_rings = devm_kcalloc(&pf->pdev->dev, vsi->alloc_rxq,
|
|
||||||
sizeof(struct ice_ring *), GFP_KERNEL);
|
|
||||||
if (!vsi->rx_rings)
|
|
||||||
goto err_rxrings;
|
|
||||||
|
|
||||||
if (alloc_qvectors) {
|
|
||||||
/* allocate memory for q_vector pointers */
|
|
||||||
vsi->q_vectors = devm_kcalloc(&pf->pdev->dev,
|
|
||||||
vsi->num_q_vectors,
|
|
||||||
sizeof(struct ice_q_vector *),
|
|
||||||
GFP_KERNEL);
|
|
||||||
if (!vsi->q_vectors)
|
|
||||||
goto err_vectors;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
err_vectors:
|
|
||||||
devm_kfree(&pf->pdev->dev, vsi->rx_rings);
|
|
||||||
err_rxrings:
|
|
||||||
devm_kfree(&pf->pdev->dev, vsi->tx_rings);
|
|
||||||
err_txrings:
|
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ice_vsi_alloc - Allocates the next available struct vsi in the PF
|
* ice_vsi_alloc - Allocates the next available struct vsi in the PF
|
||||||
* @pf: board private structure
|
* @pf: board private structure
|
||||||
|
|
Loading…
Reference in New Issue