Skip to content

Commit 493fb30

Browse files
Alexander DuyckJeff Kirsher
authored andcommitted
i40e: Move q_vectors from pointer to array to array of pointers
Allocate the q_vectors individually. The advantage to this is that it allows for easier freeing and allocation. In addition it makes it so that we could do node specific allocations at some point in the future. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
1 parent a114d0a commit 493fb30

File tree

4 files changed

+112
-60
lines changed

4 files changed

+112
-60
lines changed

drivers/net/ethernet/intel/i40e/i40e.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ struct i40e_vsi {
366366
u8 dtype;
367367

368368
/* List of q_vectors allocated to this VSI */
369-
struct i40e_q_vector *q_vectors;
369+
struct i40e_q_vector **q_vectors;
370370
int num_q_vectors;
371371
int base_vector;
372372

@@ -422,8 +422,9 @@ struct i40e_q_vector {
422422

423423
u8 num_ringpairs; /* total number of ring pairs in vector */
424424

425-
char name[IFNAMSIZ + 9];
426425
cpumask_t affinity_mask;
426+
struct rcu_head rcu; /* to avoid race with update stats on free */
427+
char name[IFNAMSIZ + 9];
427428
} ____cacheline_internodealigned_in_smp;
428429

429430
/* lan device */

drivers/net/ethernet/intel/i40e/i40e_debugfs.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -586,15 +586,6 @@ static void i40e_dbg_dump_vsi_seid(struct i40e_pf *pf, int seid)
586586
dev_info(&pf->pdev->dev,
587587
" max_frame = %d, rx_hdr_len = %d, rx_buf_len = %d dtype = %d\n",
588588
vsi->max_frame, vsi->rx_hdr_len, vsi->rx_buf_len, vsi->dtype);
589-
if (vsi->q_vectors) {
590-
for (i = 0; i < vsi->num_q_vectors; i++) {
591-
dev_info(&pf->pdev->dev,
592-
" q_vectors[%i]: base index = %ld\n",
593-
i, ((long int)*vsi->q_vectors[i].rx.ring-
594-
(long int)*vsi->q_vectors[0].rx.ring)/
595-
sizeof(struct i40e_ring));
596-
}
597-
}
598589
dev_info(&pf->pdev->dev,
599590
" num_q_vectors = %i, base_vector = %i\n",
600591
vsi->num_q_vectors, vsi->base_vector);
@@ -1995,7 +1986,7 @@ static ssize_t i40e_dbg_netdev_ops_write(struct file *filp,
19951986
goto netdev_ops_write_done;
19961987
}
19971988
for (i = 0; i < vsi->num_q_vectors; i++)
1998-
napi_schedule(&vsi->q_vectors[i].napi);
1989+
napi_schedule(&vsi->q_vectors[i]->napi);
19991990
dev_info(&pf->pdev->dev, "napi called\n");
20001991
} else {
20011992
dev_info(&pf->pdev->dev, "unknown command '%s'\n",

drivers/net/ethernet/intel/i40e/i40e_ethtool.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -906,8 +906,8 @@ static int i40e_set_coalesce(struct net_device *netdev,
906906
}
907907

908908
vector = vsi->base_vector;
909-
q_vector = vsi->q_vectors;
910-
for (i = 0; i < vsi->num_q_vectors; i++, vector++, q_vector++) {
909+
for (i = 0; i < vsi->num_q_vectors; i++, vector++) {
910+
q_vector = vsi->q_vectors[i];
911911
q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);
912912
wr32(hw, I40E_PFINT_ITRN(0, vector - 1), q_vector->rx.itr);
913913
q_vector->tx.itr = ITR_TO_REG(vsi->tx_itr_setting);

drivers/net/ethernet/intel/i40e/i40e_main.c

Lines changed: 106 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,8 +2358,8 @@ static void i40e_vsi_configure_msix(struct i40e_vsi *vsi)
23582358
*/
23592359
qp = vsi->base_queue;
23602360
vector = vsi->base_vector;
2361-
q_vector = vsi->q_vectors;
2362-
for (i = 0; i < vsi->num_q_vectors; i++, q_vector++, vector++) {
2361+
for (i = 0; i < vsi->num_q_vectors; i++, vector++) {
2362+
q_vector = vsi->q_vectors[i];
23632363
q_vector->rx.itr = ITR_TO_REG(vsi->rx_itr_setting);
23642364
q_vector->rx.latency_range = I40E_LOW_LATENCY;
23652365
wr32(hw, I40E_PFINT_ITRN(I40E_RX_ITR, vector - 1),
@@ -2439,7 +2439,7 @@ static void i40e_enable_misc_int_causes(struct i40e_hw *hw)
24392439
**/
24402440
static void i40e_configure_msi_and_legacy(struct i40e_vsi *vsi)
24412441
{
2442-
struct i40e_q_vector *q_vector = vsi->q_vectors;
2442+
struct i40e_q_vector *q_vector = vsi->q_vectors[0];
24432443
struct i40e_pf *pf = vsi->back;
24442444
struct i40e_hw *hw = &pf->hw;
24452445
u32 val;
@@ -2558,7 +2558,7 @@ static int i40e_vsi_request_irq_msix(struct i40e_vsi *vsi, char *basename)
25582558
int vector, err;
25592559

25602560
for (vector = 0; vector < q_vectors; vector++) {
2561-
struct i40e_q_vector *q_vector = &(vsi->q_vectors[vector]);
2561+
struct i40e_q_vector *q_vector = vsi->q_vectors[vector];
25622562

25632563
if (q_vector->tx.ring[0] && q_vector->rx.ring[0]) {
25642564
snprintf(q_vector->name, sizeof(q_vector->name) - 1,
@@ -2709,7 +2709,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
27092709
i40e_flush(hw);
27102710

27112711
if (!test_bit(__I40E_DOWN, &pf->state))
2712-
napi_schedule(&pf->vsi[pf->lan_vsi]->q_vectors[0].napi);
2712+
napi_schedule(&pf->vsi[pf->lan_vsi]->q_vectors[0]->napi);
27132713
}
27142714

27152715
if (icr0 & I40E_PFINT_ICR0_ADMINQ_MASK) {
@@ -2785,7 +2785,7 @@ static irqreturn_t i40e_intr(int irq, void *data)
27852785
**/
27862786
static void map_vector_to_rxq(struct i40e_vsi *vsi, int v_idx, int r_idx)
27872787
{
2788-
struct i40e_q_vector *q_vector = &(vsi->q_vectors[v_idx]);
2788+
struct i40e_q_vector *q_vector = vsi->q_vectors[v_idx];
27892789
struct i40e_ring *rx_ring = &(vsi->rx_rings[r_idx]);
27902790

27912791
rx_ring->q_vector = q_vector;
@@ -2803,7 +2803,7 @@ static void map_vector_to_rxq(struct i40e_vsi *vsi, int v_idx, int r_idx)
28032803
**/
28042804
static void map_vector_to_txq(struct i40e_vsi *vsi, int v_idx, int t_idx)
28052805
{
2806-
struct i40e_q_vector *q_vector = &(vsi->q_vectors[v_idx]);
2806+
struct i40e_q_vector *q_vector = vsi->q_vectors[v_idx];
28072807
struct i40e_ring *tx_ring = &(vsi->tx_rings[t_idx]);
28082808

28092809
tx_ring->q_vector = q_vector;
@@ -2891,7 +2891,7 @@ static void i40e_netpoll(struct net_device *netdev)
28912891
pf->flags |= I40E_FLAG_IN_NETPOLL;
28922892
if (pf->flags & I40E_FLAG_MSIX_ENABLED) {
28932893
for (i = 0; i < vsi->num_q_vectors; i++)
2894-
i40e_msix_clean_rings(0, &vsi->q_vectors[i]);
2894+
i40e_msix_clean_rings(0, vsi->q_vectors[i]);
28952895
} else {
28962896
i40e_intr(pf->pdev->irq, netdev);
28972897
}
@@ -3077,14 +3077,14 @@ static void i40e_vsi_free_irq(struct i40e_vsi *vsi)
30773077
u16 vector = i + base;
30783078

30793079
/* free only the irqs that were actually requested */
3080-
if (vsi->q_vectors[i].num_ringpairs == 0)
3080+
if (vsi->q_vectors[i]->num_ringpairs == 0)
30813081
continue;
30823082

30833083
/* clear the affinity_mask in the IRQ descriptor */
30843084
irq_set_affinity_hint(pf->msix_entries[vector].vector,
30853085
NULL);
30863086
free_irq(pf->msix_entries[vector].vector,
3087-
&vsi->q_vectors[i]);
3087+
vsi->q_vectors[i]);
30883088

30893089
/* Tear down the interrupt queue link list
30903090
*
@@ -3167,6 +3167,38 @@ static void i40e_vsi_free_irq(struct i40e_vsi *vsi)
31673167
}
31683168
}
31693169

3170+
/**
3171+
* i40e_free_q_vector - Free memory allocated for specific interrupt vector
3172+
* @vsi: the VSI being configured
3173+
* @v_idx: Index of vector to be freed
3174+
*
3175+
* This function frees the memory allocated to the q_vector. In addition if
3176+
* NAPI is enabled it will delete any references to the NAPI struct prior
3177+
* to freeing the q_vector.
3178+
**/
3179+
static void i40e_free_q_vector(struct i40e_vsi *vsi, int v_idx)
3180+
{
3181+
struct i40e_q_vector *q_vector = vsi->q_vectors[v_idx];
3182+
int r_idx;
3183+
3184+
if (!q_vector)
3185+
return;
3186+
3187+
/* disassociate q_vector from rings */
3188+
for (r_idx = 0; r_idx < q_vector->tx.count; r_idx++)
3189+
q_vector->tx.ring[r_idx]->q_vector = NULL;
3190+
for (r_idx = 0; r_idx < q_vector->rx.count; r_idx++)
3191+
q_vector->rx.ring[r_idx]->q_vector = NULL;
3192+
3193+
/* only VSI w/ an associated netdev is set up w/ NAPI */
3194+
if (vsi->netdev)
3195+
netif_napi_del(&q_vector->napi);
3196+
3197+
vsi->q_vectors[v_idx] = NULL;
3198+
3199+
kfree_rcu(q_vector, rcu);
3200+
}
3201+
31703202
/**
31713203
* i40e_vsi_free_q_vectors - Free memory allocated for interrupt vectors
31723204
* @vsi: the VSI being un-configured
@@ -3178,24 +3210,8 @@ static void i40e_vsi_free_q_vectors(struct i40e_vsi *vsi)
31783210
{
31793211
int v_idx;
31803212

3181-
for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++) {
3182-
struct i40e_q_vector *q_vector = &vsi->q_vectors[v_idx];
3183-
int r_idx;
3184-
3185-
if (!q_vector)
3186-
continue;
3187-
3188-
/* disassociate q_vector from rings */
3189-
for (r_idx = 0; r_idx < q_vector->tx.count; r_idx++)
3190-
q_vector->tx.ring[r_idx]->q_vector = NULL;
3191-
for (r_idx = 0; r_idx < q_vector->rx.count; r_idx++)
3192-
q_vector->rx.ring[r_idx]->q_vector = NULL;
3193-
3194-
/* only VSI w/ an associated netdev is set up w/ NAPI */
3195-
if (vsi->netdev)
3196-
netif_napi_del(&q_vector->napi);
3197-
}
3198-
kfree(vsi->q_vectors);
3213+
for (v_idx = 0; v_idx < vsi->num_q_vectors; v_idx++)
3214+
i40e_free_q_vector(vsi, v_idx);
31993215
}
32003216

32013217
/**
@@ -3245,7 +3261,7 @@ static void i40e_napi_enable_all(struct i40e_vsi *vsi)
32453261
return;
32463262

32473263
for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++)
3248-
napi_enable(&vsi->q_vectors[q_idx].napi);
3264+
napi_enable(&vsi->q_vectors[q_idx]->napi);
32493265
}
32503266

32513267
/**
@@ -3260,7 +3276,7 @@ static void i40e_napi_disable_all(struct i40e_vsi *vsi)
32603276
return;
32613277

32623278
for (q_idx = 0; q_idx < vsi->num_q_vectors; q_idx++)
3263-
napi_disable(&vsi->q_vectors[q_idx].napi);
3279+
napi_disable(&vsi->q_vectors[q_idx]->napi);
32643280
}
32653281

32663282
/**
@@ -4945,6 +4961,7 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
49454961
{
49464962
int ret = -ENODEV;
49474963
struct i40e_vsi *vsi;
4964+
int sz_vectors;
49484965
int vsi_idx;
49494966
int i;
49504967

@@ -4970,14 +4987,14 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
49704987
vsi_idx = i; /* Found one! */
49714988
} else {
49724989
ret = -ENODEV;
4973-
goto err_alloc_vsi; /* out of VSI slots! */
4990+
goto unlock_pf; /* out of VSI slots! */
49744991
}
49754992
pf->next_vsi = ++i;
49764993

49774994
vsi = kzalloc(sizeof(*vsi), GFP_KERNEL);
49784995
if (!vsi) {
49794996
ret = -ENOMEM;
4980-
goto err_alloc_vsi;
4997+
goto unlock_pf;
49814998
}
49824999
vsi->type = type;
49835000
vsi->back = pf;
@@ -4992,12 +5009,25 @@ static int i40e_vsi_mem_alloc(struct i40e_pf *pf, enum i40e_vsi_type type)
49925009

49935010
i40e_set_num_rings_in_vsi(vsi);
49945011

5012+
/* allocate memory for q_vector pointers */
5013+
sz_vectors = sizeof(struct i40e_q_vectors *) * vsi->num_q_vectors;
5014+
vsi->q_vectors = kzalloc(sz_vectors, GFP_KERNEL);
5015+
if (!vsi->q_vectors) {
5016+
ret = -ENOMEM;
5017+
goto err_vectors;
5018+
}
5019+
49955020
/* Setup default MSIX irq handler for VSI */
49965021
i40e_vsi_setup_irqhandler(vsi, i40e_msix_clean_rings);
49975022

49985023
pf->vsi[vsi_idx] = vsi;
49995024
ret = vsi_idx;
5000-
err_alloc_vsi:
5025+
goto unlock_pf;
5026+
5027+
err_vectors:
5028+
pf->next_vsi = i - 1;
5029+
kfree(vsi);
5030+
unlock_pf:
50015031
mutex_unlock(&pf->switch_mutex);
50025032
return ret;
50035033
}
@@ -5038,6 +5068,9 @@ static int i40e_vsi_clear(struct i40e_vsi *vsi)
50385068
i40e_put_lump(pf->qp_pile, vsi->base_queue, vsi->idx);
50395069
i40e_put_lump(pf->irq_pile, vsi->base_vector, vsi->idx);
50405070

5071+
/* free the ring and vector containers */
5072+
kfree(vsi->q_vectors);
5073+
50415074
pf->vsi[vsi->idx] = NULL;
50425075
if (vsi->idx < pf->next_vsi)
50435076
pf->next_vsi = vsi->idx;
@@ -5256,6 +5289,35 @@ static int i40e_init_msix(struct i40e_pf *pf)
52565289
return err;
52575290
}
52585291

5292+
/**
5293+
* i40e_alloc_q_vector - Allocate memory for a single interrupt vector
5294+
* @vsi: the VSI being configured
5295+
* @v_idx: index of the vector in the vsi struct
5296+
*
5297+
* We allocate one q_vector. If allocation fails we return -ENOMEM.
5298+
**/
5299+
static int i40e_alloc_q_vector(struct i40e_vsi *vsi, int v_idx)
5300+
{
5301+
struct i40e_q_vector *q_vector;
5302+
5303+
/* allocate q_vector */
5304+
q_vector = kzalloc(sizeof(struct i40e_q_vector), GFP_KERNEL);
5305+
if (!q_vector)
5306+
return -ENOMEM;
5307+
5308+
q_vector->vsi = vsi;
5309+
q_vector->v_idx = v_idx;
5310+
cpumask_set_cpu(v_idx, &q_vector->affinity_mask);
5311+
if (vsi->netdev)
5312+
netif_napi_add(vsi->netdev, &q_vector->napi,
5313+
i40e_napi_poll, vsi->work_limit);
5314+
5315+
/* tie q_vector and vsi together */
5316+
vsi->q_vectors[v_idx] = q_vector;
5317+
5318+
return 0;
5319+
}
5320+
52595321
/**
52605322
* i40e_alloc_q_vectors - Allocate memory for interrupt vectors
52615323
* @vsi: the VSI being configured
@@ -5267,6 +5329,7 @@ static int i40e_alloc_q_vectors(struct i40e_vsi *vsi)
52675329
{
52685330
struct i40e_pf *pf = vsi->back;
52695331
int v_idx, num_q_vectors;
5332+
int err;
52705333

52715334
/* if not MSIX, give the one vector only to the LAN VSI */
52725335
if (pf->flags & I40E_FLAG_MSIX_ENABLED)
@@ -5276,22 +5339,19 @@ static int i40e_alloc_q_vectors(struct i40e_vsi *vsi)
52765339
else
52775340
return -EINVAL;
52785341

5279-
vsi->q_vectors = kcalloc(num_q_vectors,
5280-
sizeof(struct i40e_q_vector),
5281-
GFP_KERNEL);
5282-
if (!vsi->q_vectors)
5283-
return -ENOMEM;
5284-
52855342
for (v_idx = 0; v_idx < num_q_vectors; v_idx++) {
5286-
vsi->q_vectors[v_idx].vsi = vsi;
5287-
vsi->q_vectors[v_idx].v_idx = v_idx;
5288-
cpumask_set_cpu(v_idx, &vsi->q_vectors[v_idx].affinity_mask);
5289-
if (vsi->netdev)
5290-
netif_napi_add(vsi->netdev, &vsi->q_vectors[v_idx].napi,
5291-
i40e_napi_poll, vsi->work_limit);
5343+
err = i40e_alloc_q_vector(vsi, v_idx);
5344+
if (err)
5345+
goto err_out;
52925346
}
52935347

52945348
return 0;
5349+
5350+
err_out:
5351+
while (v_idx--)
5352+
i40e_free_q_vector(vsi, v_idx);
5353+
5354+
return err;
52955355
}
52965356

52975357
/**
@@ -5958,7 +6018,7 @@ static int i40e_vsi_setup_vectors(struct i40e_vsi *vsi)
59586018
int ret = -ENOENT;
59596019
struct i40e_pf *pf = vsi->back;
59606020

5961-
if (vsi->q_vectors) {
6021+
if (vsi->q_vectors[0]) {
59626022
dev_info(&pf->pdev->dev, "VSI %d has existing q_vectors\n",
59636023
vsi->seid);
59646024
return -EEXIST;

0 commit comments

Comments
 (0)