Skip to content

Commit 288ecf4

Browse files
bmikailenkoanguy11
authored andcommitted
ice: Accumulate ring statistics over reset
Resets may occur with or without user interaction. For example, a TX hang or reconfiguration of parameters will result in a reset. During reset, the VSI is freed, freeing any statistics structures inside as well. This would create an issue for the user where a reset happens in the background, statistics set to zero, and the user checks ring statistics expecting them to be populated. To ensure this doesn't happen, accumulate ring statistics over reset. Define a new ring statistics structure, ice_ring_stats. The new structure lives in the VSI's parent, preserving ring statistics when VSI is freed. 1. Define a new structure vsi_ring_stats in the PF scope 2. Allocate/free stats only during probe, unload, or change in ring size 3. Replace previous ring statistics functionality with new structure Signed-off-by: Benjamin Mikailenko <[email protected]> Tested-by: Gurucharan G <[email protected]> (A Contingent worker at Intel) Signed-off-by: Tony Nguyen <[email protected]>
1 parent 2fd5e43 commit 288ecf4

File tree

9 files changed

+351
-61
lines changed

9 files changed

+351
-61
lines changed

drivers/net/ethernet/intel/ice/ice.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,11 @@ enum ice_vsi_state {
320320
ICE_VSI_STATE_NBITS /* must be last */
321321
};
322322

323+
struct ice_vsi_stats {
324+
struct ice_ring_stats **tx_ring_stats; /* Tx ring stats array */
325+
struct ice_ring_stats **rx_ring_stats; /* Rx ring stats array */
326+
};
327+
323328
/* struct that defines a VSI, associated with a dev */
324329
struct ice_vsi {
325330
struct net_device *netdev;
@@ -541,6 +546,7 @@ struct ice_pf {
541546
u16 ctrl_vsi_idx; /* control VSI index in pf->vsi array */
542547

543548
struct ice_vsi **vsi; /* VSIs created by the driver */
549+
struct ice_vsi_stats **vsi_stats;
544550
struct ice_sw *first_sw; /* first switch created by firmware */
545551
u16 eswitch_mode; /* current mode of eswitch */
546552
struct ice_vfs vfs;

drivers/net/ethernet/intel/ice/ice_ethtool.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,9 +1544,9 @@ __ice_get_ethtool_stats(struct net_device *netdev,
15441544

15451545
ice_for_each_alloc_txq(vsi, j) {
15461546
tx_ring = READ_ONCE(vsi->tx_rings[j]);
1547-
if (tx_ring) {
1548-
data[i++] = tx_ring->stats.pkts;
1549-
data[i++] = tx_ring->stats.bytes;
1547+
if (tx_ring && tx_ring->ring_stats) {
1548+
data[i++] = tx_ring->ring_stats->stats.pkts;
1549+
data[i++] = tx_ring->ring_stats->stats.bytes;
15501550
} else {
15511551
data[i++] = 0;
15521552
data[i++] = 0;
@@ -1555,9 +1555,9 @@ __ice_get_ethtool_stats(struct net_device *netdev,
15551555

15561556
ice_for_each_alloc_rxq(vsi, j) {
15571557
rx_ring = READ_ONCE(vsi->rx_rings[j]);
1558-
if (rx_ring) {
1559-
data[i++] = rx_ring->stats.pkts;
1560-
data[i++] = rx_ring->stats.bytes;
1558+
if (rx_ring && rx_ring->ring_stats) {
1559+
data[i++] = rx_ring->ring_stats->stats.pkts;
1560+
data[i++] = rx_ring->ring_stats->stats.bytes;
15611561
} else {
15621562
data[i++] = 0;
15631563
data[i++] = 0;

drivers/net/ethernet/intel/ice/ice_lib.c

Lines changed: 225 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,49 @@ static irqreturn_t ice_eswitch_msix_clean_rings(int __always_unused irq, void *d
447447
return IRQ_HANDLED;
448448
}
449449

450+
/**
451+
* ice_vsi_alloc_stat_arrays - Allocate statistics arrays
452+
* @vsi: VSI pointer
453+
*/
454+
static int ice_vsi_alloc_stat_arrays(struct ice_vsi *vsi)
455+
{
456+
struct ice_vsi_stats *vsi_stat;
457+
struct ice_pf *pf = vsi->back;
458+
459+
if (vsi->type == ICE_VSI_CHNL)
460+
return 0;
461+
if (!pf->vsi_stats)
462+
return -ENOENT;
463+
464+
vsi_stat = kzalloc(sizeof(*vsi_stat), GFP_KERNEL);
465+
if (!vsi_stat)
466+
return -ENOMEM;
467+
468+
vsi_stat->tx_ring_stats =
469+
kcalloc(vsi->alloc_txq, sizeof(*vsi_stat->tx_ring_stats),
470+
GFP_KERNEL);
471+
if (!vsi_stat->tx_ring_stats)
472+
goto err_alloc_tx;
473+
474+
vsi_stat->rx_ring_stats =
475+
kcalloc(vsi->alloc_rxq, sizeof(*vsi_stat->rx_ring_stats),
476+
GFP_KERNEL);
477+
if (!vsi_stat->rx_ring_stats)
478+
goto err_alloc_rx;
479+
480+
pf->vsi_stats[vsi->idx] = vsi_stat;
481+
482+
return 0;
483+
484+
err_alloc_rx:
485+
kfree(vsi_stat->rx_ring_stats);
486+
err_alloc_tx:
487+
kfree(vsi_stat->tx_ring_stats);
488+
kfree(vsi_stat);
489+
pf->vsi_stats[vsi->idx] = NULL;
490+
return -ENOMEM;
491+
}
492+
450493
/**
451494
* ice_vsi_alloc - Allocates the next available struct VSI in the PF
452495
* @pf: board private structure
@@ -560,6 +603,11 @@ ice_vsi_alloc(struct ice_pf *pf, enum ice_vsi_type vsi_type,
560603

561604
if (vsi->type == ICE_VSI_CTRL && vf)
562605
vf->ctrl_vsi_idx = vsi->idx;
606+
607+
/* allocate memory for Tx/Rx ring stat pointers */
608+
if (ice_vsi_alloc_stat_arrays(vsi))
609+
goto err_rings;
610+
563611
goto unlock_pf;
564612

565613
err_rings:
@@ -1535,6 +1583,106 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
15351583
return -ENOMEM;
15361584
}
15371585

1586+
/**
1587+
* ice_vsi_free_stats - Free the ring statistics structures
1588+
* @vsi: VSI pointer
1589+
*/
1590+
static void ice_vsi_free_stats(struct ice_vsi *vsi)
1591+
{
1592+
struct ice_vsi_stats *vsi_stat;
1593+
struct ice_pf *pf = vsi->back;
1594+
int i;
1595+
1596+
if (vsi->type == ICE_VSI_CHNL)
1597+
return;
1598+
if (!pf->vsi_stats)
1599+
return;
1600+
1601+
vsi_stat = pf->vsi_stats[vsi->idx];
1602+
if (!vsi_stat)
1603+
return;
1604+
1605+
ice_for_each_alloc_txq(vsi, i) {
1606+
if (vsi_stat->tx_ring_stats[i]) {
1607+
kfree_rcu(vsi_stat->tx_ring_stats[i], rcu);
1608+
WRITE_ONCE(vsi_stat->tx_ring_stats[i], NULL);
1609+
}
1610+
}
1611+
1612+
ice_for_each_alloc_rxq(vsi, i) {
1613+
if (vsi_stat->rx_ring_stats[i]) {
1614+
kfree_rcu(vsi_stat->rx_ring_stats[i], rcu);
1615+
WRITE_ONCE(vsi_stat->rx_ring_stats[i], NULL);
1616+
}
1617+
}
1618+
1619+
kfree(vsi_stat->tx_ring_stats);
1620+
kfree(vsi_stat->rx_ring_stats);
1621+
kfree(vsi_stat);
1622+
pf->vsi_stats[vsi->idx] = NULL;
1623+
}
1624+
1625+
/**
1626+
* ice_vsi_alloc_ring_stats - Allocates Tx and Rx ring stats for the VSI
1627+
* @vsi: VSI which is having stats allocated
1628+
*/
1629+
static int ice_vsi_alloc_ring_stats(struct ice_vsi *vsi)
1630+
{
1631+
struct ice_ring_stats **tx_ring_stats;
1632+
struct ice_ring_stats **rx_ring_stats;
1633+
struct ice_vsi_stats *vsi_stats;
1634+
struct ice_pf *pf = vsi->back;
1635+
u16 i;
1636+
1637+
vsi_stats = pf->vsi_stats[vsi->idx];
1638+
tx_ring_stats = vsi_stats->tx_ring_stats;
1639+
rx_ring_stats = vsi_stats->rx_ring_stats;
1640+
1641+
/* Allocate Tx ring stats */
1642+
ice_for_each_alloc_txq(vsi, i) {
1643+
struct ice_ring_stats *ring_stats;
1644+
struct ice_tx_ring *ring;
1645+
1646+
ring = vsi->tx_rings[i];
1647+
ring_stats = tx_ring_stats[i];
1648+
1649+
if (!ring_stats) {
1650+
ring_stats = kzalloc(sizeof(*ring_stats), GFP_KERNEL);
1651+
if (!ring_stats)
1652+
goto err_out;
1653+
1654+
WRITE_ONCE(tx_ring_stats[i], ring_stats);
1655+
}
1656+
1657+
ring->ring_stats = ring_stats;
1658+
}
1659+
1660+
/* Allocate Rx ring stats */
1661+
ice_for_each_alloc_rxq(vsi, i) {
1662+
struct ice_ring_stats *ring_stats;
1663+
struct ice_rx_ring *ring;
1664+
1665+
ring = vsi->rx_rings[i];
1666+
ring_stats = rx_ring_stats[i];
1667+
1668+
if (!ring_stats) {
1669+
ring_stats = kzalloc(sizeof(*ring_stats), GFP_KERNEL);
1670+
if (!ring_stats)
1671+
goto err_out;
1672+
1673+
WRITE_ONCE(rx_ring_stats[i], ring_stats);
1674+
}
1675+
1676+
ring->ring_stats = ring_stats;
1677+
}
1678+
1679+
return 0;
1680+
1681+
err_out:
1682+
ice_vsi_free_stats(vsi);
1683+
return -ENOMEM;
1684+
}
1685+
15381686
/**
15391687
* ice_vsi_manage_rss_lut - disable/enable RSS
15401688
* @vsi: the VSI being changed
@@ -2580,6 +2728,10 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
25802728
if (ret)
25812729
goto unroll_vector_base;
25822730

2731+
ret = ice_vsi_alloc_ring_stats(vsi);
2732+
if (ret)
2733+
goto unroll_vector_base;
2734+
25832735
ice_vsi_map_rings_to_vectors(vsi);
25842736

25852737
/* ICE_VSI_CTRL does not need RSS so skip RSS processing */
@@ -2618,6 +2770,9 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
26182770
if (ret)
26192771
goto unroll_vector_base;
26202772

2773+
ret = ice_vsi_alloc_ring_stats(vsi);
2774+
if (ret)
2775+
goto unroll_vector_base;
26212776
/* Do not exit if configuring RSS had an issue, at least
26222777
* receive traffic on first queue. Hence no need to capture
26232778
* return value
@@ -2631,6 +2786,11 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
26312786
ret = ice_vsi_alloc_rings(vsi);
26322787
if (ret)
26332788
goto unroll_vsi_init;
2789+
2790+
ret = ice_vsi_alloc_ring_stats(vsi);
2791+
if (ret)
2792+
goto unroll_vector_base;
2793+
26342794
break;
26352795
default:
26362796
/* clean up the resources and exit */
@@ -2690,6 +2850,7 @@ ice_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi,
26902850
unroll_alloc_q_vector:
26912851
ice_vsi_free_q_vectors(vsi);
26922852
unroll_vsi_init:
2853+
ice_vsi_free_stats(vsi);
26932854
ice_vsi_delete(vsi);
26942855
unroll_get_qs:
26952856
ice_vsi_put_qs(vsi);
@@ -3081,7 +3242,7 @@ int ice_vsi_release(struct ice_vsi *vsi)
30813242
vsi->agg_node && vsi->agg_node->valid)
30823243
vsi->agg_node->num_vsis--;
30833244
ice_vsi_clear_rings(vsi);
3084-
3245+
ice_vsi_free_stats(vsi);
30853246
ice_vsi_put_qs(vsi);
30863247

30873248
/* retain SW VSI data structure since it is needed to unregister and
@@ -3208,6 +3369,47 @@ ice_vsi_rebuild_set_coalesce(struct ice_vsi *vsi,
32083369
}
32093370
}
32103371

3372+
/**
3373+
* ice_vsi_realloc_stat_arrays - Frees unused stat structures
3374+
* @vsi: VSI pointer
3375+
* @prev_txq: Number of Tx rings before ring reallocation
3376+
* @prev_rxq: Number of Rx rings before ring reallocation
3377+
*/
3378+
static int
3379+
ice_vsi_realloc_stat_arrays(struct ice_vsi *vsi, int prev_txq, int prev_rxq)
3380+
{
3381+
struct ice_vsi_stats *vsi_stat;
3382+
struct ice_pf *pf = vsi->back;
3383+
int i;
3384+
3385+
if (!prev_txq || !prev_rxq)
3386+
return 0;
3387+
if (vsi->type == ICE_VSI_CHNL)
3388+
return 0;
3389+
3390+
vsi_stat = pf->vsi_stats[vsi->idx];
3391+
3392+
if (vsi->num_txq < prev_txq) {
3393+
for (i = vsi->num_txq; i < prev_txq; i++) {
3394+
if (vsi_stat->tx_ring_stats[i]) {
3395+
kfree_rcu(vsi_stat->tx_ring_stats[i], rcu);
3396+
WRITE_ONCE(vsi_stat->tx_ring_stats[i], NULL);
3397+
}
3398+
}
3399+
}
3400+
3401+
if (vsi->num_rxq < prev_rxq) {
3402+
for (i = vsi->num_rxq; i < prev_rxq; i++) {
3403+
if (vsi_stat->rx_ring_stats[i]) {
3404+
kfree_rcu(vsi_stat->rx_ring_stats[i], rcu);
3405+
WRITE_ONCE(vsi_stat->rx_ring_stats[i], NULL);
3406+
}
3407+
}
3408+
}
3409+
3410+
return 0;
3411+
}
3412+
32113413
/**
32123414
* ice_vsi_rebuild - Rebuild VSI after reset
32133415
* @vsi: VSI to be rebuild
@@ -3219,10 +3421,10 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
32193421
{
32203422
u16 max_txqs[ICE_MAX_TRAFFIC_CLASS] = { 0 };
32213423
struct ice_coalesce_stored *coalesce;
3424+
int ret, i, prev_txq, prev_rxq;
32223425
int prev_num_q_vectors = 0;
32233426
enum ice_vsi_type vtype;
32243427
struct ice_pf *pf;
3225-
int ret, i;
32263428

32273429
if (!vsi)
32283430
return -EINVAL;
@@ -3241,6 +3443,9 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
32413443

32423444
prev_num_q_vectors = ice_vsi_rebuild_get_coalesce(vsi, coalesce);
32433445

3446+
prev_txq = vsi->num_txq;
3447+
prev_rxq = vsi->num_rxq;
3448+
32443449
ice_rm_vsi_lan_cfg(vsi->port_info, vsi->idx);
32453450
ret = ice_rm_vsi_rdma_cfg(vsi->port_info, vsi->idx);
32463451
if (ret)
@@ -3307,6 +3512,10 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
33073512
if (ret)
33083513
goto err_vectors;
33093514

3515+
ret = ice_vsi_alloc_ring_stats(vsi);
3516+
if (ret)
3517+
goto err_vectors;
3518+
33103519
ice_vsi_map_rings_to_vectors(vsi);
33113520

33123521
vsi->stat_offsets_loaded = false;
@@ -3346,6 +3555,10 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
33463555
if (ret)
33473556
goto err_vectors;
33483557

3558+
ret = ice_vsi_alloc_ring_stats(vsi);
3559+
if (ret)
3560+
goto err_vectors;
3561+
33493562
vsi->stat_offsets_loaded = false;
33503563
break;
33513564
case ICE_VSI_CHNL:
@@ -3394,6 +3607,10 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
33943607
return ice_schedule_reset(pf, ICE_RESET_PFR);
33953608
}
33963609
}
3610+
3611+
if (ice_vsi_realloc_stat_arrays(vsi, prev_txq, prev_rxq))
3612+
goto err_vectors;
3613+
33973614
ice_vsi_rebuild_set_coalesce(vsi, coalesce, prev_num_q_vectors);
33983615
kfree(coalesce);
33993616

@@ -3735,9 +3952,9 @@ static void ice_update_ring_stats(struct ice_q_stats *stats, u64 pkts, u64 bytes
37353952
*/
37363953
void ice_update_tx_ring_stats(struct ice_tx_ring *tx_ring, u64 pkts, u64 bytes)
37373954
{
3738-
u64_stats_update_begin(&tx_ring->syncp);
3739-
ice_update_ring_stats(&tx_ring->stats, pkts, bytes);
3740-
u64_stats_update_end(&tx_ring->syncp);
3955+
u64_stats_update_begin(&tx_ring->ring_stats->syncp);
3956+
ice_update_ring_stats(&tx_ring->ring_stats->stats, pkts, bytes);
3957+
u64_stats_update_end(&tx_ring->ring_stats->syncp);
37413958
}
37423959

37433960
/**
@@ -3748,9 +3965,9 @@ void ice_update_tx_ring_stats(struct ice_tx_ring *tx_ring, u64 pkts, u64 bytes)
37483965
*/
37493966
void ice_update_rx_ring_stats(struct ice_rx_ring *rx_ring, u64 pkts, u64 bytes)
37503967
{
3751-
u64_stats_update_begin(&rx_ring->syncp);
3752-
ice_update_ring_stats(&rx_ring->stats, pkts, bytes);
3753-
u64_stats_update_end(&rx_ring->syncp);
3968+
u64_stats_update_begin(&rx_ring->ring_stats->syncp);
3969+
ice_update_ring_stats(&rx_ring->ring_stats->stats, pkts, bytes);
3970+
u64_stats_update_end(&rx_ring->ring_stats->syncp);
37543971
}
37553972

37563973
/**

0 commit comments

Comments
 (0)