Commit bfdd7416 authored by Tim Hostetler's avatar Tim Hostetler Committed by Jakub Kicinski
Browse files

gve: Check valid ts bit on RX descriptor before hw timestamping



The device returns a valid bit in the LSB of the low timestamp byte in
the completion descriptor that the driver should check before
setting the SKB's hardware timestamp. If the timestamp is not valid, do not
hardware timestamp the SKB.

Cc: stable@vger.kernel.org
Fixes: b2c7aeb4 ("gve: Implement ndo_hwtstamp_get/set for RX timestamping")
Reviewed-by: default avatarJoshua Washington <joshwash@google.com>
Signed-off-by: default avatarTim Hostetler <thostet@google.com>
Signed-off-by: default avatarHarshitha Ramamurthy <hramamurthy@google.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Reviewed-by: default avatarWillem de Bruijn <willemb@google.com>
Reviewed-by: default avatarVadim Fedorenko <vadim.fedorenko@linux.dev>
Link: https://patch.msgid.link/20251014004740.2775957-1-hramamurthy@google.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 7f0fddd8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -100,6 +100,8 @@
 */
#define GVE_DQO_QPL_ONDEMAND_ALLOC_THRESHOLD 96

#define GVE_DQO_RX_HWTSTAMP_VALID 0x1

/* Each slot in the desc ring has a 1:1 mapping to a slot in the data ring */
struct gve_rx_desc_queue {
	struct gve_rx_desc *desc_ring; /* the descriptor ring */
+2 −1
Original line number Diff line number Diff line
@@ -236,7 +236,8 @@ struct gve_rx_compl_desc_dqo {

	u8 status_error1;

	__le16 reserved5;
	u8 reserved5;
	u8 ts_sub_nsecs_low;
	__le16 buf_id; /* Buffer ID which was sent on the buffer queue. */

	union {
+12 −6
Original line number Diff line number Diff line
@@ -456,15 +456,21 @@ static void gve_rx_skb_hash(struct sk_buff *skb,
 * Note that this means if the time delta between packet reception and the last
 * clock read is greater than ~2 seconds, this will provide invalid results.
 */
static void gve_rx_skb_hwtstamp(struct gve_rx_ring *rx, u32 hwts)
static void gve_rx_skb_hwtstamp(struct gve_rx_ring *rx,
				const struct gve_rx_compl_desc_dqo *desc)
{
	u64 last_read = READ_ONCE(rx->gve->last_sync_nic_counter);
	struct sk_buff *skb = rx->ctx.skb_head;
	u32 low = (u32)last_read;
	s32 diff = hwts - low;
	u32 ts, low;
	s32 diff;

	if (desc->ts_sub_nsecs_low & GVE_DQO_RX_HWTSTAMP_VALID) {
		ts = le32_to_cpu(desc->ts);
		low = (u32)last_read;
		diff = ts - low;
		skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(last_read + diff);
	}
}

static void gve_rx_free_skb(struct napi_struct *napi, struct gve_rx_ring *rx)
{
@@ -944,7 +950,7 @@ static int gve_rx_complete_skb(struct gve_rx_ring *rx, struct napi_struct *napi,
		gve_rx_skb_csum(rx->ctx.skb_head, desc, ptype);

	if (rx->gve->ts_config.rx_filter == HWTSTAMP_FILTER_ALL)
		gve_rx_skb_hwtstamp(rx, le32_to_cpu(desc->ts));
		gve_rx_skb_hwtstamp(rx, desc);

	/* RSC packets must set gso_size otherwise the TCP stack will complain
	 * that packets are larger than MTU.