Skip to content

Commit

Permalink
eth: fbnic: add TX packets timestamping support
Browse files Browse the repository at this point in the history
Add TX configuration to ethtool interface. Add processing of TX
timestamp completions as well as configuration to request HW to create
TX timestamp completion.

Signed-off-by: Vadim Fedorenko <vadfed@meta.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Vadim Fedorenko authored and Paolo Abeni committed Oct 10, 2024
1 parent 6a2b3ed commit ad3d9f8
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 3 deletions.
5 changes: 5 additions & 0 deletions drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,14 @@ fbnic_get_ts_info(struct net_device *netdev,

tsinfo->so_timestamping =
SOF_TIMESTAMPING_TX_SOFTWARE |
SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;

tsinfo->tx_types =
BIT(HWTSTAMP_TX_OFF) |
BIT(HWTSTAMP_TX_ON);

tsinfo->rx_filters =
BIT(HWTSTAMP_FILTER_NONE) |
BIT(HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
Expand Down
93 changes: 90 additions & 3 deletions drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@
#include "fbnic_netdev.h"
#include "fbnic_txrx.h"

enum {
FBNIC_XMIT_CB_TS = 0x01,
};

struct fbnic_xmit_cb {
u32 bytecount;
u8 desc_count;
u8 flags;
int hw_head;
};

Expand Down Expand Up @@ -150,11 +155,32 @@ static void fbnic_unmap_page_twd(struct device *dev, __le64 *twd)
#define FBNIC_TWD_TYPE(_type) \
cpu_to_le64(FIELD_PREP(FBNIC_TWD_TYPE_MASK, FBNIC_TWD_TYPE_##_type))

static bool fbnic_tx_tstamp(struct sk_buff *skb)
{
struct fbnic_net *fbn;

if (!unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
return false;

fbn = netdev_priv(skb->dev);
if (fbn->hwtstamp_config.tx_type == HWTSTAMP_TX_OFF)
return false;

skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
FBNIC_XMIT_CB(skb)->flags |= FBNIC_XMIT_CB_TS;
FBNIC_XMIT_CB(skb)->hw_head = -1;

return true;
}

static bool
fbnic_tx_offloads(struct fbnic_ring *ring, struct sk_buff *skb, __le64 *meta)
{
unsigned int l2len, i3len;

if (fbnic_tx_tstamp(skb))
*meta |= cpu_to_le64(FBNIC_TWD_FLAG_REQ_TS);

if (unlikely(skb->ip_summed != CHECKSUM_PARTIAL))
return false;

Expand Down Expand Up @@ -374,6 +400,12 @@ static void fbnic_clean_twq0(struct fbnic_napi_vector *nv, int napi_budget,
if (desc_cnt > clean_desc)
break;

if (unlikely(FBNIC_XMIT_CB(skb)->flags & FBNIC_XMIT_CB_TS)) {
FBNIC_XMIT_CB(skb)->hw_head = hw_head;
if (likely(!discard))
break;
}

ring->tx_buf[head] = NULL;

clean_desc -= desc_cnt;
Expand Down Expand Up @@ -427,6 +459,53 @@ static void fbnic_clean_twq0(struct fbnic_napi_vector *nv, int napi_budget,
FBNIC_TX_DESC_WAKEUP);
}

static void fbnic_clean_tsq(struct fbnic_napi_vector *nv,
struct fbnic_ring *ring,
u64 tcd, int *ts_head, int *head0)
{
struct skb_shared_hwtstamps hwtstamp;
struct fbnic_net *fbn;
struct sk_buff *skb;
int head;
u64 ns;

head = (*ts_head < 0) ? ring->head : *ts_head;

do {
unsigned int desc_cnt;

if (head == ring->tail) {
if (unlikely(net_ratelimit()))
netdev_err(nv->napi.dev,
"Tx timestamp without matching packet\n");
return;
}

skb = ring->tx_buf[head];
desc_cnt = FBNIC_XMIT_CB(skb)->desc_count;

head += desc_cnt;
head &= ring->size_mask;
} while (!(FBNIC_XMIT_CB(skb)->flags & FBNIC_XMIT_CB_TS));

fbn = netdev_priv(nv->napi.dev);
ns = fbnic_ts40_to_ns(fbn, FIELD_GET(FBNIC_TCD_TYPE1_TS_MASK, tcd));

memset(&hwtstamp, 0, sizeof(hwtstamp));
hwtstamp.hwtstamp = ns_to_ktime(ns);

*ts_head = head;

FBNIC_XMIT_CB(skb)->flags &= ~FBNIC_XMIT_CB_TS;
if (*head0 < 0) {
head = FBNIC_XMIT_CB(skb)->hw_head;
if (head >= 0)
*head0 = head;
}

skb_tstamp_tx(skb, &hwtstamp);
}

static void fbnic_page_pool_init(struct fbnic_ring *ring, unsigned int idx,
struct page *page)
{
Expand Down Expand Up @@ -460,20 +539,22 @@ static void fbnic_page_pool_drain(struct fbnic_ring *ring, unsigned int idx,
}

static void fbnic_clean_twq(struct fbnic_napi_vector *nv, int napi_budget,
struct fbnic_q_triad *qt, s32 head0)
struct fbnic_q_triad *qt, s32 ts_head, s32 head0)
{
if (head0 >= 0)
fbnic_clean_twq0(nv, napi_budget, &qt->sub0, false, head0);
else if (ts_head >= 0)
fbnic_clean_twq0(nv, napi_budget, &qt->sub0, false, ts_head);
}

static void
fbnic_clean_tcq(struct fbnic_napi_vector *nv, struct fbnic_q_triad *qt,
int napi_budget)
{
struct fbnic_ring *cmpl = &qt->cmpl;
s32 head0 = -1, ts_head = -1;
__le64 *raw_tcd, done;
u32 head = cmpl->head;
s32 head0 = -1;

done = (head & (cmpl->size_mask + 1)) ? 0 : cpu_to_le64(FBNIC_TCD_DONE);
raw_tcd = &cmpl->desc[head & cmpl->size_mask];
Expand All @@ -496,6 +577,12 @@ fbnic_clean_tcq(struct fbnic_napi_vector *nv, struct fbnic_q_triad *qt,
* they are skipped for now.
*/
break;
case FBNIC_TCD_TYPE_1:
if (WARN_ON_ONCE(tcd & FBNIC_TCD_TWQ1))
break;

fbnic_clean_tsq(nv, &qt->sub0, tcd, &ts_head, &head0);
break;
default:
break;
}
Expand All @@ -515,7 +602,7 @@ fbnic_clean_tcq(struct fbnic_napi_vector *nv, struct fbnic_q_triad *qt,
}

/* Unmap and free processed buffers */
fbnic_clean_twq(nv, napi_budget, qt, head0);
fbnic_clean_twq(nv, napi_budget, qt, ts_head, head0);
}

static void fbnic_clean_bdq(struct fbnic_napi_vector *nv, int napi_budget,
Expand Down

0 comments on commit ad3d9f8

Please sign in to comment.