Merge branch '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue

Tony Nguyen says:

====================
Intel Wired LAN Driver Updates 2026-01-26 (ice, idpf)

For ice:
Jake converts ring stats to utilize u64_stats APIs and performs some
cleanups along the way.

Alexander reorganizes layout of Tx and Rx rings for cacheline
locality and utilizes __cacheline_group* macros on the new layouts.

For idpf:
YiFei Zhu adds support for BPF kfunc reporting of hardware Rx timestamps.

* '100GbE' of git://git.kernel.org/pub/scm/linux/kernel/git/tnguy/next-queue:
  idpf: export RX hardware timestamping information to XDP
  ice: reshuffle and group Rx and Tx queue fields by cachelines
  ice: convert all ring stats to u64_stats_t
  ice: shorten ring stat names and add accessors
  ice: use u64_stats API to access pkts/bytes in dim sample
  ice: remove ice_q_stats struct and use struct_group
  ice: pass pointer to ice_fetch_u64_stats_per_ring
====================

Link: https://patch.msgid.link/20260126224313.3847849-1-anthony.l.nguyen@intel.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski
2026-01-27 17:33:59 -08:00
13 changed files with 398 additions and 209 deletions

View File

@@ -957,9 +957,6 @@ u16 ice_get_avail_rxq_count(struct ice_pf *pf);
int ice_vsi_recfg_qs(struct ice_vsi *vsi, int new_rx, int new_tx, bool locked);
void ice_update_vsi_stats(struct ice_vsi *vsi);
void ice_update_pf_stats(struct ice_pf *pf);
void
ice_fetch_u64_stats_per_ring(struct u64_stats_sync *syncp,
struct ice_q_stats stats, u64 *pkts, u64 *bytes);
int ice_up(struct ice_vsi *vsi);
int ice_down(struct ice_vsi *vsi);
int ice_down_up(struct ice_vsi *vsi);

View File

@@ -1414,8 +1414,8 @@ static void ice_qp_reset_stats(struct ice_vsi *vsi, u16 q_idx)
if (!vsi_stat)
return;
memset(&vsi_stat->rx_ring_stats[q_idx]->rx_stats, 0,
sizeof(vsi_stat->rx_ring_stats[q_idx]->rx_stats));
memset(&vsi_stat->rx_ring_stats[q_idx]->stats, 0,
sizeof(vsi_stat->rx_ring_stats[q_idx]->stats));
memset(&vsi_stat->tx_ring_stats[q_idx]->stats, 0,
sizeof(vsi_stat->tx_ring_stats[q_idx]->stats));
if (vsi->xdp_rings)

View File

@@ -33,8 +33,8 @@ static int ice_q_stats_len(struct net_device *netdev)
{
struct ice_netdev_priv *np = netdev_priv(netdev);
return ((np->vsi->alloc_txq + np->vsi->alloc_rxq) *
(sizeof(struct ice_q_stats) / sizeof(u64)));
/* One packets and one bytes count per queue */
return ((np->vsi->alloc_txq + np->vsi->alloc_rxq) * 2);
}
#define ICE_PF_STATS_LEN ARRAY_SIZE(ice_gstrings_pf_stats)
@@ -1942,25 +1942,35 @@ __ice_get_ethtool_stats(struct net_device *netdev,
rcu_read_lock();
ice_for_each_alloc_txq(vsi, j) {
u64 pkts, bytes;
tx_ring = READ_ONCE(vsi->tx_rings[j]);
if (tx_ring && tx_ring->ring_stats) {
data[i++] = tx_ring->ring_stats->stats.pkts;
data[i++] = tx_ring->ring_stats->stats.bytes;
} else {
if (!tx_ring || !tx_ring->ring_stats) {
data[i++] = 0;
data[i++] = 0;
continue;
}
ice_fetch_tx_ring_stats(tx_ring, &pkts, &bytes);
data[i++] = pkts;
data[i++] = bytes;
}
ice_for_each_alloc_rxq(vsi, j) {
u64 pkts, bytes;
rx_ring = READ_ONCE(vsi->rx_rings[j]);
if (rx_ring && rx_ring->ring_stats) {
data[i++] = rx_ring->ring_stats->stats.pkts;
data[i++] = rx_ring->ring_stats->stats.bytes;
} else {
if (!rx_ring || !rx_ring->ring_stats) {
data[i++] = 0;
data[i++] = 0;
continue;
}
ice_fetch_rx_ring_stats(rx_ring, &pkts, &bytes);
data[i++] = pkts;
data[i++] = bytes;
}
rcu_read_unlock();
@@ -3378,7 +3388,6 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
*/
rx_rings[i].next_to_use = 0;
rx_rings[i].next_to_clean = 0;
rx_rings[i].next_to_alloc = 0;
*vsi->rx_rings[i] = rx_rings[i];
}
kfree(rx_rings);

View File

@@ -3432,20 +3432,6 @@ int ice_vsi_cfg_tc(struct ice_vsi *vsi, u8 ena_tc)
return ret;
}
/**
* ice_update_ring_stats - Update ring statistics
* @stats: stats to be updated
* @pkts: number of processed packets
* @bytes: number of processed bytes
*
* This function assumes that caller has acquired a u64_stats_sync lock.
*/
static void ice_update_ring_stats(struct ice_q_stats *stats, u64 pkts, u64 bytes)
{
stats->bytes += bytes;
stats->pkts += pkts;
}
/**
* ice_update_tx_ring_stats - Update Tx ring specific counters
* @tx_ring: ring to update
@@ -3455,7 +3441,8 @@ static void ice_update_ring_stats(struct ice_q_stats *stats, u64 pkts, u64 bytes
void ice_update_tx_ring_stats(struct ice_tx_ring *tx_ring, u64 pkts, u64 bytes)
{
u64_stats_update_begin(&tx_ring->ring_stats->syncp);
ice_update_ring_stats(&tx_ring->ring_stats->stats, pkts, bytes);
u64_stats_add(&tx_ring->ring_stats->pkts, pkts);
u64_stats_add(&tx_ring->ring_stats->bytes, bytes);
u64_stats_update_end(&tx_ring->ring_stats->syncp);
}
@@ -3468,10 +3455,47 @@ void ice_update_tx_ring_stats(struct ice_tx_ring *tx_ring, u64 pkts, u64 bytes)
void ice_update_rx_ring_stats(struct ice_rx_ring *rx_ring, u64 pkts, u64 bytes)
{
u64_stats_update_begin(&rx_ring->ring_stats->syncp);
ice_update_ring_stats(&rx_ring->ring_stats->stats, pkts, bytes);
u64_stats_add(&rx_ring->ring_stats->pkts, pkts);
u64_stats_add(&rx_ring->ring_stats->bytes, bytes);
u64_stats_update_end(&rx_ring->ring_stats->syncp);
}
/**
* ice_fetch_tx_ring_stats - Fetch Tx ring packet and byte counters
* @ring: ring to update
* @pkts: number of processed packets
* @bytes: number of processed bytes
*/
void ice_fetch_tx_ring_stats(const struct ice_tx_ring *ring,
u64 *pkts, u64 *bytes)
{
unsigned int start;
do {
start = u64_stats_fetch_begin(&ring->ring_stats->syncp);
*pkts = u64_stats_read(&ring->ring_stats->pkts);
*bytes = u64_stats_read(&ring->ring_stats->bytes);
} while (u64_stats_fetch_retry(&ring->ring_stats->syncp, start));
}
/**
* ice_fetch_rx_ring_stats - Fetch Rx ring packet and byte counters
* @ring: ring to read
* @pkts: number of processed packets
* @bytes: number of processed bytes
*/
void ice_fetch_rx_ring_stats(const struct ice_rx_ring *ring,
u64 *pkts, u64 *bytes)
{
unsigned int start;
do {
start = u64_stats_fetch_begin(&ring->ring_stats->syncp);
*pkts = u64_stats_read(&ring->ring_stats->pkts);
*bytes = u64_stats_read(&ring->ring_stats->bytes);
} while (u64_stats_fetch_retry(&ring->ring_stats->syncp, start));
}
/**
* ice_is_dflt_vsi_in_use - check if the default forwarding VSI is being used
* @pi: port info of the switch with default VSI

View File

@@ -92,6 +92,12 @@ void ice_update_tx_ring_stats(struct ice_tx_ring *ring, u64 pkts, u64 bytes);
void ice_update_rx_ring_stats(struct ice_rx_ring *ring, u64 pkts, u64 bytes);
void ice_fetch_tx_ring_stats(const struct ice_tx_ring *ring,
u64 *pkts, u64 *bytes);
void ice_fetch_rx_ring_stats(const struct ice_rx_ring *ring,
u64 *pkts, u64 *bytes);
void ice_write_intrl(struct ice_q_vector *q_vector, u8 intrl);
void ice_write_itr(struct ice_ring_container *rc, u16 itr);
void ice_set_q_vector_intrl(struct ice_q_vector *q_vector);

View File

@@ -159,8 +159,8 @@ static void ice_check_for_hang_subtask(struct ice_pf *pf)
* prev_pkt would be negative if there was no
* pending work.
*/
packets = ring_stats->stats.pkts & INT_MAX;
if (ring_stats->tx_stats.prev_pkt == packets) {
packets = ice_stats_read(ring_stats, pkts) & INT_MAX;
if (ring_stats->tx.prev_pkt == packets) {
/* Trigger sw interrupt to revive the queue */
ice_trigger_sw_intr(hw, tx_ring->q_vector);
continue;
@@ -170,7 +170,7 @@ static void ice_check_for_hang_subtask(struct ice_pf *pf)
* to ice_get_tx_pending()
*/
smp_rmb();
ring_stats->tx_stats.prev_pkt =
ring_stats->tx.prev_pkt =
ice_get_tx_pending(tx_ring) ? packets : -1;
}
}
@@ -6822,58 +6822,132 @@ int ice_up(struct ice_vsi *vsi)
return err;
}
struct ice_vsi_tx_stats {
u64 pkts;
u64 bytes;
u64 tx_restart_q;
u64 tx_busy;
u64 tx_linearize;
};
struct ice_vsi_rx_stats {
u64 pkts;
u64 bytes;
u64 rx_non_eop_descs;
u64 rx_page_failed;
u64 rx_buf_failed;
};
/**
* ice_fetch_u64_stats_per_ring - get packets and bytes stats per ring
* @syncp: pointer to u64_stats_sync
* @stats: stats that pkts and bytes count will be taken from
* @pkts: packets stats counter
* @bytes: bytes stats counter
* ice_fetch_u64_tx_stats - get Tx stats from a ring
* @ring: the Tx ring to copy stats from
* @copy: temporary storage for the ring statistics
*
* This function fetches stats from the ring considering the atomic operations
* that needs to be performed to read u64 values in 32 bit machine.
* Fetch the u64 stats from the ring using u64_stats_fetch. This ensures each
* stat value is self-consistent, though not necessarily consistent w.r.t
* other stats.
*/
void
ice_fetch_u64_stats_per_ring(struct u64_stats_sync *syncp,
struct ice_q_stats stats, u64 *pkts, u64 *bytes)
static void ice_fetch_u64_tx_stats(struct ice_tx_ring *ring,
struct ice_vsi_tx_stats *copy)
{
struct ice_ring_stats *stats = ring->ring_stats;
unsigned int start;
do {
start = u64_stats_fetch_begin(syncp);
*pkts = stats.pkts;
*bytes = stats.bytes;
} while (u64_stats_fetch_retry(syncp, start));
start = u64_stats_fetch_begin(&stats->syncp);
copy->pkts = u64_stats_read(&stats->pkts);
copy->bytes = u64_stats_read(&stats->bytes);
copy->tx_restart_q = u64_stats_read(&stats->tx_restart_q);
copy->tx_busy = u64_stats_read(&stats->tx_busy);
copy->tx_linearize = u64_stats_read(&stats->tx_linearize);
} while (u64_stats_fetch_retry(&stats->syncp, start));
}
/**
* ice_fetch_u64_rx_stats - get Rx stats from a ring
* @ring: the Rx ring to copy stats from
* @copy: temporary storage for the ring statistics
*
* Fetch the u64 stats from the ring using u64_stats_fetch. This ensures each
* stat value is self-consistent, though not necessarily consistent w.r.t
* other stats.
*/
static void ice_fetch_u64_rx_stats(struct ice_rx_ring *ring,
struct ice_vsi_rx_stats *copy)
{
struct ice_ring_stats *stats = ring->ring_stats;
unsigned int start;
do {
start = u64_stats_fetch_begin(&stats->syncp);
copy->pkts = u64_stats_read(&stats->pkts);
copy->bytes = u64_stats_read(&stats->bytes);
copy->rx_non_eop_descs =
u64_stats_read(&stats->rx_non_eop_descs);
copy->rx_page_failed = u64_stats_read(&stats->rx_page_failed);
copy->rx_buf_failed = u64_stats_read(&stats->rx_buf_failed);
} while (u64_stats_fetch_retry(&stats->syncp, start));
}
/**
* ice_update_vsi_tx_ring_stats - Update VSI Tx ring stats counters
* @vsi: the VSI to be updated
* @vsi_stats: the stats struct to be updated
* @vsi_stats: accumulated stats for this VSI
* @rings: rings to work on
* @count: number of rings
*/
static void
ice_update_vsi_tx_ring_stats(struct ice_vsi *vsi,
struct rtnl_link_stats64 *vsi_stats,
struct ice_tx_ring **rings, u16 count)
static void ice_update_vsi_tx_ring_stats(struct ice_vsi *vsi,
struct ice_vsi_tx_stats *vsi_stats,
struct ice_tx_ring **rings, u16 count)
{
struct ice_vsi_tx_stats copy = {};
u16 i;
for (i = 0; i < count; i++) {
struct ice_tx_ring *ring;
u64 pkts = 0, bytes = 0;
ring = READ_ONCE(rings[i]);
if (!ring || !ring->ring_stats)
continue;
ice_fetch_u64_stats_per_ring(&ring->ring_stats->syncp,
ring->ring_stats->stats, &pkts,
&bytes);
vsi_stats->tx_packets += pkts;
vsi_stats->tx_bytes += bytes;
vsi->tx_restart += ring->ring_stats->tx_stats.restart_q;
vsi->tx_busy += ring->ring_stats->tx_stats.tx_busy;
vsi->tx_linearize += ring->ring_stats->tx_stats.tx_linearize;
ice_fetch_u64_tx_stats(ring, &copy);
vsi_stats->pkts += copy.pkts;
vsi_stats->bytes += copy.bytes;
vsi_stats->tx_restart_q += copy.tx_restart_q;
vsi_stats->tx_busy += copy.tx_busy;
vsi_stats->tx_linearize += copy.tx_linearize;
}
}
/**
* ice_update_vsi_rx_ring_stats - Update VSI Rx ring stats counters
* @vsi: the VSI to be updated
* @vsi_stats: accumulated stats for this VSI
* @rings: rings to work on
* @count: number of rings
*/
static void ice_update_vsi_rx_ring_stats(struct ice_vsi *vsi,
struct ice_vsi_rx_stats *vsi_stats,
struct ice_rx_ring **rings, u16 count)
{
struct ice_vsi_rx_stats copy = {};
u16 i;
for (i = 0; i < count; i++) {
struct ice_rx_ring *ring;
ring = READ_ONCE(rings[i]);
if (!ring || !ring->ring_stats)
continue;
ice_fetch_u64_rx_stats(ring, &copy);
vsi_stats->pkts += copy.pkts;
vsi_stats->bytes += copy.bytes;
vsi_stats->rx_non_eop_descs += copy.rx_non_eop_descs;
vsi_stats->rx_page_failed += copy.rx_page_failed;
vsi_stats->rx_buf_failed += copy.rx_buf_failed;
}
}
@@ -6884,50 +6958,34 @@ ice_update_vsi_tx_ring_stats(struct ice_vsi *vsi,
static void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
{
struct rtnl_link_stats64 *net_stats, *stats_prev;
struct rtnl_link_stats64 *vsi_stats;
struct ice_vsi_tx_stats tx_stats = {};
struct ice_vsi_rx_stats rx_stats = {};
struct ice_pf *pf = vsi->back;
u64 pkts, bytes;
int i;
vsi_stats = kzalloc(sizeof(*vsi_stats), GFP_ATOMIC);
if (!vsi_stats)
return;
/* reset non-netdev (extended) stats */
vsi->tx_restart = 0;
vsi->tx_busy = 0;
vsi->tx_linearize = 0;
vsi->rx_buf_failed = 0;
vsi->rx_page_failed = 0;
rcu_read_lock();
/* update Tx rings counters */
ice_update_vsi_tx_ring_stats(vsi, vsi_stats, vsi->tx_rings,
ice_update_vsi_tx_ring_stats(vsi, &tx_stats, vsi->tx_rings,
vsi->num_txq);
/* update Rx rings counters */
ice_for_each_rxq(vsi, i) {
struct ice_rx_ring *ring = READ_ONCE(vsi->rx_rings[i]);
struct ice_ring_stats *ring_stats;
ring_stats = ring->ring_stats;
ice_fetch_u64_stats_per_ring(&ring_stats->syncp,
ring_stats->stats, &pkts,
&bytes);
vsi_stats->rx_packets += pkts;
vsi_stats->rx_bytes += bytes;
vsi->rx_buf_failed += ring_stats->rx_stats.alloc_buf_failed;
vsi->rx_page_failed += ring_stats->rx_stats.alloc_page_failed;
}
ice_update_vsi_rx_ring_stats(vsi, &rx_stats, vsi->rx_rings,
vsi->num_rxq);
/* update XDP Tx rings counters */
if (ice_is_xdp_ena_vsi(vsi))
ice_update_vsi_tx_ring_stats(vsi, vsi_stats, vsi->xdp_rings,
ice_update_vsi_tx_ring_stats(vsi, &tx_stats, vsi->xdp_rings,
vsi->num_xdp_txq);
rcu_read_unlock();
/* Save non-netdev (extended) stats */
vsi->tx_restart = tx_stats.tx_restart_q;
vsi->tx_busy = tx_stats.tx_busy;
vsi->tx_linearize = tx_stats.tx_linearize;
vsi->rx_buf_failed = rx_stats.rx_buf_failed;
vsi->rx_page_failed = rx_stats.rx_page_failed;
net_stats = &vsi->net_stats;
stats_prev = &vsi->net_stats_prev;
@@ -6937,18 +6995,16 @@ static void ice_update_vsi_ring_stats(struct ice_vsi *vsi)
* let's skip this round.
*/
if (likely(pf->stat_prev_loaded)) {
net_stats->tx_packets += vsi_stats->tx_packets - stats_prev->tx_packets;
net_stats->tx_bytes += vsi_stats->tx_bytes - stats_prev->tx_bytes;
net_stats->rx_packets += vsi_stats->rx_packets - stats_prev->rx_packets;
net_stats->rx_bytes += vsi_stats->rx_bytes - stats_prev->rx_bytes;
net_stats->tx_packets += tx_stats.pkts - stats_prev->tx_packets;
net_stats->tx_bytes += tx_stats.bytes - stats_prev->tx_bytes;
net_stats->rx_packets += rx_stats.pkts - stats_prev->rx_packets;
net_stats->rx_bytes += rx_stats.bytes - stats_prev->rx_bytes;
}
stats_prev->tx_packets = vsi_stats->tx_packets;
stats_prev->tx_bytes = vsi_stats->tx_bytes;
stats_prev->rx_packets = vsi_stats->rx_packets;
stats_prev->rx_bytes = vsi_stats->rx_bytes;
kfree(vsi_stats);
stats_prev->tx_packets = tx_stats.pkts;
stats_prev->tx_bytes = tx_stats.bytes;
stats_prev->rx_packets = rx_stats.pkts;
stats_prev->rx_bytes = rx_stats.bytes;
}
/**

View File

@@ -379,7 +379,7 @@ static bool ice_clean_tx_irq(struct ice_tx_ring *tx_ring, int napi_budget)
if (netif_tx_queue_stopped(txring_txq(tx_ring)) &&
!test_bit(ICE_VSI_DOWN, vsi->state)) {
netif_tx_wake_queue(txring_txq(tx_ring));
++tx_ring->ring_stats->tx_stats.restart_q;
ice_stats_inc(tx_ring->ring_stats, tx_restart_q);
}
}
@@ -499,7 +499,7 @@ int ice_setup_tx_ring(struct ice_tx_ring *tx_ring)
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
tx_ring->ring_stats->tx_stats.prev_pkt = -1;
tx_ring->ring_stats->tx.prev_pkt = -1;
return 0;
err:
@@ -574,7 +574,6 @@ void ice_clean_rx_ring(struct ice_rx_ring *rx_ring)
PAGE_SIZE);
memset(rx_ring->desc, 0, size);
rx_ring->next_to_alloc = 0;
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
}
@@ -849,7 +848,7 @@ bool ice_alloc_rx_bufs(struct ice_rx_ring *rx_ring, unsigned int cleaned_count)
addr = libeth_rx_alloc(&fq, ntu);
if (addr == DMA_MAPPING_ERROR) {
rx_ring->ring_stats->rx_stats.alloc_page_failed++;
ice_stats_inc(rx_ring->ring_stats, rx_page_failed);
break;
}
@@ -863,7 +862,7 @@ bool ice_alloc_rx_bufs(struct ice_rx_ring *rx_ring, unsigned int cleaned_count)
addr = libeth_rx_alloc(&hdr_fq, ntu);
if (addr == DMA_MAPPING_ERROR) {
rx_ring->ring_stats->rx_stats.alloc_page_failed++;
ice_stats_inc(rx_ring->ring_stats, rx_page_failed);
libeth_rx_recycle_slow(fq.fqes[ntu].netmem);
break;
@@ -1045,7 +1044,7 @@ static int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget)
/* exit if we failed to retrieve a buffer */
if (!skb) {
libeth_xdp_return_buff_slow(xdp);
rx_ring->ring_stats->rx_stats.alloc_buf_failed++;
ice_stats_inc(rx_ring->ring_stats, rx_buf_failed);
continue;
}
@@ -1087,35 +1086,36 @@ static void __ice_update_sample(struct ice_q_vector *q_vector,
struct dim_sample *sample,
bool is_tx)
{
u64 packets = 0, bytes = 0;
u64 total_packets = 0, total_bytes = 0, pkts, bytes;
if (is_tx) {
struct ice_tx_ring *tx_ring;
ice_for_each_tx_ring(tx_ring, *rc) {
struct ice_ring_stats *ring_stats;
ring_stats = tx_ring->ring_stats;
if (!ring_stats)
if (!tx_ring->ring_stats)
continue;
packets += ring_stats->stats.pkts;
bytes += ring_stats->stats.bytes;
ice_fetch_tx_ring_stats(tx_ring, &pkts, &bytes);
total_packets += pkts;
total_bytes += bytes;
}
} else {
struct ice_rx_ring *rx_ring;
ice_for_each_rx_ring(rx_ring, *rc) {
struct ice_ring_stats *ring_stats;
ring_stats = rx_ring->ring_stats;
if (!ring_stats)
if (!rx_ring->ring_stats)
continue;
packets += ring_stats->stats.pkts;
bytes += ring_stats->stats.bytes;
ice_fetch_rx_ring_stats(rx_ring, &pkts, &bytes);
total_packets += pkts;
total_bytes += bytes;
}
}
dim_update_sample(q_vector->total_events, packets, bytes, sample);
dim_update_sample(q_vector->total_events,
total_packets, total_bytes, sample);
sample->comp_ctr = 0;
/* if dim settings get stale, like when not updated for 1
@@ -1362,7 +1362,7 @@ static int __ice_maybe_stop_tx(struct ice_tx_ring *tx_ring, unsigned int size)
/* A reprieve! - use start_queue because it doesn't call schedule */
netif_tx_start_queue(txring_txq(tx_ring));
++tx_ring->ring_stats->tx_stats.restart_q;
ice_stats_inc(tx_ring->ring_stats, tx_restart_q);
return 0;
}
@@ -2164,7 +2164,7 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
if (__skb_linearize(skb))
goto out_drop;
count = ice_txd_use_count(skb->len);
tx_ring->ring_stats->tx_stats.tx_linearize++;
ice_stats_inc(tx_ring->ring_stats, tx_linearize);
}
/* need: 1 descriptor per page * PAGE_SIZE/ICE_MAX_DATA_PER_TXD,
@@ -2175,7 +2175,7 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_tx_ring *tx_ring)
*/
if (ice_maybe_stop_tx(tx_ring, count + ICE_DESCS_PER_CACHE_LINE +
ICE_DESCS_FOR_CTX_DESC)) {
tx_ring->ring_stats->tx_stats.tx_busy++;
ice_stats_inc(tx_ring->ring_stats, tx_busy);
return NETDEV_TX_BUSY;
}

View File

@@ -129,34 +129,65 @@ struct ice_tx_offload_params {
u8 header_len;
};
struct ice_q_stats {
u64 pkts;
u64 bytes;
};
struct ice_txq_stats {
u64 restart_q;
u64 tx_busy;
u64 tx_linearize;
int prev_pkt; /* negative if no pending Tx descriptors */
};
struct ice_rxq_stats {
u64 non_eop_descs;
u64 alloc_page_failed;
u64 alloc_buf_failed;
};
struct ice_ring_stats {
struct rcu_head rcu; /* to avoid race on free */
struct ice_q_stats stats;
struct u64_stats_sync syncp;
union {
struct ice_txq_stats tx_stats;
struct ice_rxq_stats rx_stats;
};
struct_group(stats,
u64_stats_t pkts;
u64_stats_t bytes;
union {
struct_group(tx,
u64_stats_t tx_restart_q;
u64_stats_t tx_busy;
u64_stats_t tx_linearize;
/* negative if no pending Tx descriptors */
int prev_pkt;
);
struct_group(rx,
u64_stats_t rx_non_eop_descs;
u64_stats_t rx_page_failed;
u64_stats_t rx_buf_failed;
);
};
);
};
/**
* ice_stats_read - Read a single ring stat value
* @stats: pointer to ring_stats structure for a queue
* @member: the ice_ring_stats member to read
*
* Shorthand for reading a single 64-bit stat value from struct
* ice_ring_stats.
*
* Return: the value of the requested stat.
*/
#define ice_stats_read(stats, member) ({ \
struct ice_ring_stats *__stats = (stats); \
unsigned int start; \
u64 val; \
do { \
start = u64_stats_fetch_begin(&__stats->syncp); \
val = u64_stats_read(&__stats->member); \
} while (u64_stats_fetch_retry(&__stats->syncp, start)); \
val; \
})
/**
* ice_stats_inc - Increment a single ring stat value
* @stats: pointer to the ring_stats structure for a queue
* @member: the ice_ring_stats member to increment
*
* Shorthand for incrementing a single 64-bit stat value in struct
* ice_ring_stats.
*/
#define ice_stats_inc(stats, member) do { \
struct ice_ring_stats *__stats = (stats); \
u64_stats_update_begin(&__stats->syncp); \
u64_stats_inc(&__stats->member); \
u64_stats_update_end(&__stats->syncp); \
} while (0)
enum ice_ring_state_t {
ICE_TX_XPS_INIT_DONE,
ICE_TX_NBITS,
@@ -236,34 +267,49 @@ struct ice_tstamp_ring {
} ____cacheline_internodealigned_in_smp;
struct ice_rx_ring {
/* CL1 - 1st cacheline starts here */
__cacheline_group_begin_aligned(read_mostly);
void *desc; /* Descriptor ring memory */
struct page_pool *pp;
struct net_device *netdev; /* netdev ring maps to */
struct ice_vsi *vsi; /* Backreference to associated VSI */
struct ice_q_vector *q_vector; /* Backreference to associated vector */
u8 __iomem *tail;
u16 q_index; /* Queue number of ring */
u16 count; /* Number of descriptors */
u16 reg_idx; /* HW register index of the ring */
u16 next_to_alloc;
union {
struct libeth_fqe *rx_fqes;
struct xdp_buff **xdp_buf;
};
/* CL2 - 2nd cacheline starts here */
struct libeth_fqe *hdr_fqes;
struct page_pool *hdr_pp;
u16 count; /* Number of descriptors */
u8 ptp_rx;
u8 flags;
#define ICE_RX_FLAGS_CRC_STRIP_DIS BIT(2)
#define ICE_RX_FLAGS_MULTIDEV BIT(3)
#define ICE_RX_FLAGS_RING_GCS BIT(4)
u32 truesize;
struct page_pool *hdr_pp;
struct libeth_fqe *hdr_fqes;
struct bpf_prog *xdp_prog;
struct ice_tx_ring *xdp_ring;
struct xsk_buff_pool *xsk_pool;
/* stats structs */
struct ice_ring_stats *ring_stats;
struct ice_rx_ring *next; /* pointer to next ring in q_vector */
u32 hdr_truesize;
struct xdp_rxq_info xdp_rxq;
__cacheline_group_end_aligned(read_mostly);
__cacheline_group_begin_aligned(read_write);
union {
struct libeth_xdp_buff_stash xdp;
struct libeth_xdp_buff *xsk;
};
/* CL3 - 3rd cacheline starts here */
union {
struct ice_pkt_ctx pkt_ctx;
struct {
@@ -271,75 +317,78 @@ struct ice_rx_ring {
__be16 vlan_proto;
};
};
struct bpf_prog *xdp_prog;
/* used in interrupt processing */
u16 next_to_use;
u16 next_to_clean;
__cacheline_group_end_aligned(read_write);
u32 hdr_truesize;
u32 truesize;
/* stats structs */
struct ice_ring_stats *ring_stats;
__cacheline_group_begin_aligned(cold);
struct rcu_head rcu; /* to avoid race on free */
/* CL4 - 4th cacheline starts here */
struct ice_vsi *vsi; /* Backreference to associated VSI */
struct ice_channel *ch;
struct ice_tx_ring *xdp_ring;
struct ice_rx_ring *next; /* pointer to next ring in q_vector */
struct xsk_buff_pool *xsk_pool;
dma_addr_t dma; /* physical address of ring */
u16 q_index; /* Queue number of ring */
u16 reg_idx; /* HW register index of the ring */
u8 dcb_tc; /* Traffic class of ring */
u16 rx_hdr_len;
u16 rx_buf_len;
dma_addr_t dma; /* physical address of ring */
u8 dcb_tc; /* Traffic class of ring */
u8 ptp_rx;
#define ICE_RX_FLAGS_CRC_STRIP_DIS BIT(2)
#define ICE_RX_FLAGS_MULTIDEV BIT(3)
#define ICE_RX_FLAGS_RING_GCS BIT(4)
u8 flags;
/* CL5 - 5th cacheline starts here */
struct xdp_rxq_info xdp_rxq;
__cacheline_group_end_aligned(cold);
} ____cacheline_internodealigned_in_smp;
struct ice_tx_ring {
/* CL1 - 1st cacheline starts here */
struct ice_tx_ring *next; /* pointer to next ring in q_vector */
__cacheline_group_begin_aligned(read_mostly);
void *desc; /* Descriptor ring memory */
struct device *dev; /* Used for DMA mapping */
u8 __iomem *tail;
struct ice_tx_buf *tx_buf;
struct ice_q_vector *q_vector; /* Backreference to associated vector */
struct net_device *netdev; /* netdev ring maps to */
struct ice_vsi *vsi; /* Backreference to associated VSI */
/* CL2 - 2nd cacheline starts here */
dma_addr_t dma; /* physical address of ring */
struct xsk_buff_pool *xsk_pool;
u16 next_to_use;
u16 next_to_clean;
u16 q_handle; /* Queue handle per TC */
u16 reg_idx; /* HW register index of the ring */
u16 count; /* Number of descriptors */
u16 q_index; /* Queue number of ring */
u16 xdp_tx_active;
/* stats structs */
struct ice_ring_stats *ring_stats;
/* CL3 - 3rd cacheline starts here */
struct rcu_head rcu; /* to avoid race on free */
DECLARE_BITMAP(xps_state, ICE_TX_NBITS); /* XPS Config State */
struct ice_channel *ch;
struct ice_ptp_tx *tx_tstamps;
spinlock_t tx_lock;
u32 txq_teid; /* Added Tx queue TEID */
/* CL4 - 4th cacheline starts here */
struct ice_tstamp_ring *tstamp_ring;
u8 flags;
#define ICE_TX_FLAGS_RING_XDP BIT(0)
#define ICE_TX_FLAGS_RING_VLAN_L2TAG1 BIT(1)
#define ICE_TX_FLAGS_RING_VLAN_L2TAG2 BIT(2)
#define ICE_TX_FLAGS_TXTIME BIT(3)
u8 flags;
struct xsk_buff_pool *xsk_pool;
/* stats structs */
struct ice_ring_stats *ring_stats;
struct ice_tx_ring *next; /* pointer to next ring in q_vector */
struct ice_tstamp_ring *tstamp_ring;
struct ice_ptp_tx *tx_tstamps;
__cacheline_group_end_aligned(read_mostly);
__cacheline_group_begin_aligned(read_write);
u16 next_to_use;
u16 next_to_clean;
u16 xdp_tx_active;
spinlock_t tx_lock;
__cacheline_group_end_aligned(read_write);
__cacheline_group_begin_aligned(cold);
struct rcu_head rcu; /* to avoid race on free */
DECLARE_BITMAP(xps_state, ICE_TX_NBITS); /* XPS Config State */
struct ice_channel *ch;
dma_addr_t dma; /* physical address of ring */
u16 q_handle; /* Queue handle per TC */
u16 reg_idx; /* HW register index of the ring */
u8 dcb_tc; /* Traffic class of ring */
u16 quanta_prof_id;
u32 txq_teid; /* Added Tx queue TEID */
__cacheline_group_end_aligned(cold);
} ____cacheline_internodealigned_in_smp;
static inline bool ice_ring_ch_enabled(struct ice_tx_ring *ring)

View File

@@ -20,9 +20,6 @@ void ice_release_rx_desc(struct ice_rx_ring *rx_ring, u16 val)
rx_ring->next_to_use = val;
/* update next to alloc since we have filled the ring */
rx_ring->next_to_alloc = val;
/* QRX_TAIL will be updated with any tail value, but hardware ignores
* the lower 3 bits. This makes it so we only bump tail on meaningful
* boundaries. Also, this allows us to bump tail on intervals of 8 up to
@@ -480,7 +477,7 @@ int __ice_xmit_xdp_ring(struct xdp_buff *xdp, struct ice_tx_ring *xdp_ring,
return ICE_XDP_CONSUMED;
busy:
xdp_ring->ring_stats->tx_stats.tx_busy++;
ice_stats_inc(xdp_ring->ring_stats, tx_busy);
return ICE_XDP_CONSUMED;
}

View File

@@ -38,7 +38,7 @@ ice_is_non_eop(const struct ice_rx_ring *rx_ring,
if (likely(ice_test_staterr(rx_desc->wb.status_error0, ICE_RXD_EOF)))
return false;
rx_ring->ring_stats->rx_stats.non_eop_descs++;
ice_stats_inc(rx_ring->ring_stats, rx_non_eop_descs);
return true;
}

View File

@@ -497,7 +497,7 @@ static int ice_xmit_xdp_tx_zc(struct xdp_buff *xdp,
return ICE_XDP_TX;
busy:
xdp_ring->ring_stats->tx_stats.tx_busy++;
ice_stats_inc(xdp_ring->ring_stats, tx_busy);
return ICE_XDP_CONSUMED;
}
@@ -659,7 +659,7 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring,
xsk_buff_free(first);
first = NULL;
rx_ring->ring_stats->rx_stats.alloc_buf_failed++;
ice_stats_inc(rx_ring->ring_stats, rx_buf_failed);
continue;
}

View File

@@ -2,6 +2,7 @@
/* Copyright (C) 2025 Intel Corporation */
#include "idpf.h"
#include "idpf_ptp.h"
#include "idpf_virtchnl.h"
#include "xdp.h"
#include "xsk.h"
@@ -398,8 +399,38 @@ static int idpf_xdpmo_rx_hash(const struct xdp_md *ctx, u32 *hash,
pt);
}
static int idpf_xdpmo_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
{
const struct libeth_xdp_buff *xdp = (typeof(xdp))ctx;
struct idpf_xdp_rx_desc desc __uninitialized;
const struct idpf_rx_queue *rxq;
u64 cached_time, ts_ns;
u32 ts_high;
rxq = libeth_xdp_buff_to_rq(xdp, typeof(*rxq), xdp_rxq);
if (!idpf_queue_has(PTP, rxq))
return -ENODATA;
idpf_xdp_get_qw1(&desc, xdp->desc);
if (!(idpf_xdp_rx_ts_low(&desc) & VIRTCHNL2_RX_FLEX_TSTAMP_VALID))
return -ENODATA;
cached_time = READ_ONCE(rxq->cached_phc_time);
idpf_xdp_get_qw3(&desc, xdp->desc);
ts_high = idpf_xdp_rx_ts_high(&desc);
ts_ns = idpf_ptp_tstamp_extend_32b_to_64b(cached_time, ts_high);
*timestamp = ts_ns;
return 0;
}
static const struct xdp_metadata_ops idpf_xdpmo = {
.xmo_rx_hash = idpf_xdpmo_rx_hash,
.xmo_rx_timestamp = idpf_xdpmo_rx_timestamp,
};
void idpf_xdp_set_features(const struct idpf_vport *vport)

View File

@@ -112,11 +112,13 @@ struct idpf_xdp_rx_desc {
aligned_u64 qw1;
#define IDPF_XDP_RX_BUF GENMASK_ULL(47, 32)
#define IDPF_XDP_RX_EOP BIT_ULL(1)
#define IDPF_XDP_RX_TS_LOW GENMASK_ULL(31, 24)
aligned_u64 qw2;
#define IDPF_XDP_RX_HASH GENMASK_ULL(31, 0)
aligned_u64 qw3;
#define IDPF_XDP_RX_TS_HIGH GENMASK_ULL(63, 32)
} __aligned(4 * sizeof(u64));
static_assert(sizeof(struct idpf_xdp_rx_desc) ==
sizeof(struct virtchnl2_rx_flex_desc_adv_nic_3));
@@ -128,6 +130,8 @@ static_assert(sizeof(struct idpf_xdp_rx_desc) ==
#define idpf_xdp_rx_buf(desc) FIELD_GET(IDPF_XDP_RX_BUF, (desc)->qw1)
#define idpf_xdp_rx_eop(desc) !!((desc)->qw1 & IDPF_XDP_RX_EOP)
#define idpf_xdp_rx_hash(desc) FIELD_GET(IDPF_XDP_RX_HASH, (desc)->qw2)
#define idpf_xdp_rx_ts_low(desc) FIELD_GET(IDPF_XDP_RX_TS_LOW, (desc)->qw1)
#define idpf_xdp_rx_ts_high(desc) FIELD_GET(IDPF_XDP_RX_TS_HIGH, (desc)->qw3)
static inline void
idpf_xdp_get_qw0(struct idpf_xdp_rx_desc *desc,
@@ -149,6 +153,9 @@ idpf_xdp_get_qw1(struct idpf_xdp_rx_desc *desc,
desc->qw1 = ((const typeof(desc))rxd)->qw1;
#else
desc->qw1 = ((u64)le16_to_cpu(rxd->buf_id) << 32) |
((u64)rxd->ts_low << 24) |
((u64)rxd->fflags1 << 16) |
((u64)rxd->status_err1 << 8) |
rxd->status_err0_qw1;
#endif
}
@@ -166,6 +173,19 @@ idpf_xdp_get_qw2(struct idpf_xdp_rx_desc *desc,
#endif
}
static inline void
idpf_xdp_get_qw3(struct idpf_xdp_rx_desc *desc,
const struct virtchnl2_rx_flex_desc_adv_nic_3 *rxd)
{
#ifdef __LIBETH_WORD_ACCESS
desc->qw3 = ((const typeof(desc))rxd)->qw3;
#else
desc->qw3 = ((u64)le32_to_cpu(rxd->ts_high) << 32) |
((u64)le16_to_cpu(rxd->fmd6) << 16) |
le16_to_cpu(rxd->l2tag1);
#endif
}
void idpf_xdp_set_features(const struct idpf_vport *vport);
int idpf_xdp(struct net_device *dev, struct netdev_bpf *xdp);