Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'gve-implement-xdp-hw-rx-timestamping-support-for-dq'

Tim Hostetler says:

====================
gve: Implement XDP HW RX Timestamping support for DQ

From: Tim Hostetler <thostet@google.com>

This patch series adds support for bpf_xdp_metadata_rx_timestamp from an
XDP program loaded into the driver on its own or bound to an XSK. This
is only supported for DQ.
====================

Link: https://patch.msgid.link/20251114211146.292068-1-joshwash@google.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+79 -23
+7
drivers/net/ethernet/google/gve/gve.h
··· 205 205 s16 next; 206 206 }; 207 207 208 + /* Wrapper for XDP Rx metadata */ 209 + struct gve_xdp_buff { 210 + struct xdp_buff xdp; 211 + struct gve_priv *gve; 212 + const struct gve_rx_compl_desc_dqo *compl_desc; 213 + }; 214 + 208 215 /* `head` and `tail` are indices into an array, or -1 if empty. */ 209 216 struct gve_index_list { 210 217 s16 head;
+1
drivers/net/ethernet/google/gve/gve_dqo.h
··· 36 36 netdev_features_t gve_features_check_dqo(struct sk_buff *skb, 37 37 struct net_device *dev, 38 38 netdev_features_t features); 39 + int gve_xdp_rx_timestamp(const struct xdp_md *_ctx, u64 *timestamp); 39 40 bool gve_tx_poll_dqo(struct gve_notify_block *block, bool do_clean); 40 41 bool gve_xdp_poll_dqo(struct gve_notify_block *block); 41 42 bool gve_xsk_tx_poll_dqo(struct gve_notify_block *block, int budget);
+7 -4
drivers/net/ethernet/google/gve/gve_main.c
··· 2188 2188 } 2189 2189 2190 2190 kernel_config->rx_filter = HWTSTAMP_FILTER_ALL; 2191 - gve_clock_nic_ts_read(priv); 2192 - ptp_schedule_worker(priv->ptp->clock, 0); 2193 - } else { 2194 - ptp_cancel_worker_sync(priv->ptp->clock); 2195 2191 } 2196 2192 2197 2193 priv->ts_config.rx_filter = kernel_config->rx_filter; ··· 2348 2352 xdp_set_features_flag_locked(priv->dev, xdp_features); 2349 2353 } 2350 2354 2355 + static const struct xdp_metadata_ops gve_xdp_metadata_ops = { 2356 + .xmo_rx_timestamp = gve_xdp_rx_timestamp, 2357 + }; 2358 + 2351 2359 static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device) 2352 2360 { 2353 2361 int num_ntfy; ··· 2447 2447 } 2448 2448 2449 2449 gve_set_netdev_xdp_features(priv); 2450 + if (!gve_is_gqi(priv)) 2451 + priv->dev->xdp_metadata_ops = &gve_xdp_metadata_ops; 2452 + 2450 2453 err = gve_setup_device_resources(priv); 2451 2454 if (err) 2452 2455 goto err_free_xsk_bitmap;
+12
drivers/net/ethernet/google/gve/gve_ptp.c
··· 133 133 err = -ENOMEM; 134 134 goto release_ptp; 135 135 } 136 + err = gve_clock_nic_ts_read(priv); 137 + if (err) { 138 + dev_err(&priv->pdev->dev, "failed to read NIC clock %d\n", err); 139 + goto release_nic_ts_report; 140 + } 141 + ptp_schedule_worker(priv->ptp->clock, 142 + msecs_to_jiffies(GVE_NIC_TS_SYNC_INTERVAL_MS)); 136 143 137 144 return 0; 138 145 146 + release_nic_ts_report: 147 + dma_free_coherent(&priv->pdev->dev, 148 + sizeof(struct gve_nic_ts_report), 149 + priv->nic_ts_report, priv->nic_ts_report_bus); 150 + priv->nic_ts_report = NULL; 139 151 release_ptp: 140 152 gve_ptp_release(priv); 141 153 return err;
+52 -19
drivers/net/ethernet/google/gve/gve_rx_dqo.c
··· 240 240 rx->rx_headroom = 0; 241 241 } 242 242 243 + /* struct gve_xdp_buff is overlaid on struct xdp_buff_xsk and utilizes 244 + * the 24 byte field cb to store gve specific data. 245 + */ 246 + XSK_CHECK_PRIV_TYPE(struct gve_xdp_buff); 247 + 243 248 rx->dqo.num_buf_states = cfg->raw_addressing ? buffer_queue_slots : 244 249 gve_get_rx_pages_per_qpl_dqo(cfg->ring_size); 245 250 rx->dqo.buf_states = kvcalloc_node(rx->dqo.num_buf_states, ··· 461 456 * Note that this means if the time delta between packet reception and the last 462 457 * clock read is greater than ~2 seconds, this will provide invalid results. 463 458 */ 459 + static ktime_t gve_rx_get_hwtstamp(struct gve_priv *gve, u32 hwts) 460 + { 461 + u64 last_read = READ_ONCE(gve->last_sync_nic_counter); 462 + u32 low = (u32)last_read; 463 + s32 diff = hwts - low; 464 + 465 + return ns_to_ktime(last_read + diff); 466 + } 467 + 464 468 static void gve_rx_skb_hwtstamp(struct gve_rx_ring *rx, 465 469 const struct gve_rx_compl_desc_dqo *desc) 466 470 { 467 - u64 last_read = READ_ONCE(rx->gve->last_sync_nic_counter); 468 471 struct sk_buff *skb = rx->ctx.skb_head; 469 - u32 ts, low; 470 - s32 diff; 471 472 472 - if (desc->ts_sub_nsecs_low & GVE_DQO_RX_HWTSTAMP_VALID) { 473 - ts = le32_to_cpu(desc->ts); 474 - low = (u32)last_read; 475 - diff = ts - low; 476 - skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(last_read + diff); 477 - } 473 + if (desc->ts_sub_nsecs_low & GVE_DQO_RX_HWTSTAMP_VALID) 474 + skb_hwtstamps(skb)->hwtstamp = 475 + gve_rx_get_hwtstamp(rx->gve, le32_to_cpu(desc->ts)); 476 + } 477 + 478 + int gve_xdp_rx_timestamp(const struct xdp_md *_ctx, u64 *timestamp) 479 + { 480 + const struct gve_xdp_buff *ctx = (void *)_ctx; 481 + 482 + if (!ctx->gve->nic_ts_report) 483 + return -ENODATA; 484 + 485 + if (!(ctx->compl_desc->ts_sub_nsecs_low & GVE_DQO_RX_HWTSTAMP_VALID)) 486 + return -ENODATA; 487 + 488 + *timestamp = gve_rx_get_hwtstamp(ctx->gve, 489 + le32_to_cpu(ctx->compl_desc->ts)); 490 + return 0; 478 491 } 479 492 480 493 static void gve_rx_free_skb(struct napi_struct *napi, struct gve_rx_ring *rx) ··· 706 683 } 707 684 708 685 static int gve_rx_xsk_dqo(struct napi_struct *napi, struct gve_rx_ring *rx, 709 - struct gve_rx_buf_state_dqo *buf_state, int buf_len, 686 + const struct gve_rx_compl_desc_dqo *compl_desc, 687 + struct gve_rx_buf_state_dqo *buf_state, 710 688 struct bpf_prog *xprog) 711 689 { 712 690 struct xdp_buff *xdp = buf_state->xsk_buff; 691 + int buf_len = compl_desc->packet_len; 713 692 struct gve_priv *priv = rx->gve; 693 + struct gve_xdp_buff *gve_xdp; 714 694 int xdp_act; 715 695 716 696 xdp->data_end = xdp->data + buf_len; 717 697 xsk_buff_dma_sync_for_cpu(xdp); 698 + 699 + gve_xdp = (void *)xdp; 700 + gve_xdp->gve = priv; 701 + gve_xdp->compl_desc = compl_desc; 718 702 719 703 if (xprog) { 720 704 xdp_act = bpf_prog_run_xdp(xprog, xdp); ··· 812 782 813 783 xprog = READ_ONCE(priv->xdp_prog); 814 784 if (buf_state->xsk_buff) 815 - return gve_rx_xsk_dqo(napi, rx, buf_state, buf_len, xprog); 785 + return gve_rx_xsk_dqo(napi, rx, compl_desc, buf_state, xprog); 816 786 817 787 /* Page might have not been used for awhile and was likely last written 818 788 * by a different thread. ··· 870 840 } 871 841 872 842 if (xprog) { 873 - struct xdp_buff xdp; 843 + struct gve_xdp_buff gve_xdp; 874 844 void *old_data; 875 845 int xdp_act; 876 846 877 - xdp_init_buff(&xdp, buf_state->page_info.buf_size, 847 + xdp_init_buff(&gve_xdp.xdp, buf_state->page_info.buf_size, 878 848 &rx->xdp_rxq); 879 - xdp_prepare_buff(&xdp, 849 + xdp_prepare_buff(&gve_xdp.xdp, 880 850 buf_state->page_info.page_address + 881 851 buf_state->page_info.page_offset, 882 852 buf_state->page_info.pad, 883 853 buf_len, false); 884 - old_data = xdp.data; 885 - xdp_act = bpf_prog_run_xdp(xprog, &xdp); 886 - buf_state->page_info.pad += xdp.data - old_data; 887 - buf_len = xdp.data_end - xdp.data; 854 + gve_xdp.gve = priv; 855 + gve_xdp.compl_desc = compl_desc; 856 + 857 + old_data = gve_xdp.xdp.data; 858 + xdp_act = bpf_prog_run_xdp(xprog, &gve_xdp.xdp); 859 + buf_state->page_info.pad += gve_xdp.xdp.data - old_data; 860 + buf_len = gve_xdp.xdp.data_end - gve_xdp.xdp.data; 888 861 if (xdp_act != XDP_PASS) { 889 - gve_xdp_done_dqo(priv, rx, &xdp, xprog, xdp_act, 862 + gve_xdp_done_dqo(priv, rx, &gve_xdp.xdp, xprog, xdp_act, 890 863 buf_state); 891 864 return 0; 892 865 }