Skip to content

Commit

Permalink
can: mcp251xfd: clarify the meaning of timestamp
Browse files Browse the repository at this point in the history
[ Upstream commit e793c72 ]

The mcp251xfd chip is configured to provide a timestamp with each
received and transmitted CAN frame. The timestamp is derived from the
internal free-running timer, which can also be read from the TBC
register via SPI. The timer is 32 bits wide and is clocked by the
external oscillator (typically 20 or 40 MHz).

To avoid confusion, we call this timestamp "timestamp_raw" or "ts_raw"
for short.

Using the timecounter framework, the "ts_raw" is converted to 64 bit
nanoseconds since the epoch. This is what we call "timestamp".

This is a preparation for the next patches which use the "timestamp"
to work around a bug where so far only the "ts_raw" is used.

Tested-by: Stefan Althöfer <[email protected]>
Tested-by: Thomas Kopp <[email protected]>
Signed-off-by: Marc Kleine-Budde <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
  • Loading branch information
marckleinebudde authored and gregkh committed Sep 12, 2024
1 parent bf501ab commit 6cdc3fc
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 38 deletions.
28 changes: 14 additions & 14 deletions drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// mcp251xfd - Microchip MCP251xFD Family CAN controller driver
//
// Copyright (c) 2019, 2020, 2021 Pengutronix,
// Copyright (c) 2019, 2020, 2021, 2023 Pengutronix,
// Marc Kleine-Budde <[email protected]>
//
// Based on:
Expand Down Expand Up @@ -867,18 +867,18 @@ static int mcp251xfd_get_berr_counter(const struct net_device *ndev,

static struct sk_buff *
mcp251xfd_alloc_can_err_skb(struct mcp251xfd_priv *priv,
struct can_frame **cf, u32 *timestamp)
struct can_frame **cf, u32 *ts_raw)
{
struct sk_buff *skb;
int err;

err = mcp251xfd_get_timestamp(priv, timestamp);
err = mcp251xfd_get_timestamp_raw(priv, ts_raw);
if (err)
return NULL;

skb = alloc_can_err_skb(priv->ndev, cf);
if (skb)
mcp251xfd_skb_set_timestamp(priv, skb, *timestamp);
mcp251xfd_skb_set_timestamp_raw(priv, skb, *ts_raw);

return skb;
}
Expand All @@ -889,7 +889,7 @@ static int mcp251xfd_handle_rxovif(struct mcp251xfd_priv *priv)
struct mcp251xfd_rx_ring *ring;
struct sk_buff *skb;
struct can_frame *cf;
u32 timestamp, rxovif;
u32 ts_raw, rxovif;
int err, i;

stats->rx_over_errors++;
Expand Down Expand Up @@ -924,14 +924,14 @@ static int mcp251xfd_handle_rxovif(struct mcp251xfd_priv *priv)
return err;
}

skb = mcp251xfd_alloc_can_err_skb(priv, &cf, &timestamp);
skb = mcp251xfd_alloc_can_err_skb(priv, &cf, &ts_raw);
if (!skb)
return 0;

cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;

err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp);
err = can_rx_offload_queue_timestamp(&priv->offload, skb, ts_raw);
if (err)
stats->rx_fifo_errors++;

Expand All @@ -948,12 +948,12 @@ static int mcp251xfd_handle_txatif(struct mcp251xfd_priv *priv)
static int mcp251xfd_handle_ivmif(struct mcp251xfd_priv *priv)
{
struct net_device_stats *stats = &priv->ndev->stats;
u32 bdiag1, timestamp;
u32 bdiag1, ts_raw;
struct sk_buff *skb;
struct can_frame *cf = NULL;
int err;

err = mcp251xfd_get_timestamp(priv, &timestamp);
err = mcp251xfd_get_timestamp_raw(priv, &ts_raw);
if (err)
return err;

Expand Down Expand Up @@ -1035,8 +1035,8 @@ static int mcp251xfd_handle_ivmif(struct mcp251xfd_priv *priv)
if (!cf)
return 0;

mcp251xfd_skb_set_timestamp(priv, skb, timestamp);
err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp);
mcp251xfd_skb_set_timestamp_raw(priv, skb, ts_raw);
err = can_rx_offload_queue_timestamp(&priv->offload, skb, ts_raw);
if (err)
stats->rx_fifo_errors++;

Expand All @@ -1049,7 +1049,7 @@ static int mcp251xfd_handle_cerrif(struct mcp251xfd_priv *priv)
struct sk_buff *skb;
struct can_frame *cf = NULL;
enum can_state new_state, rx_state, tx_state;
u32 trec, timestamp;
u32 trec, ts_raw;
int err;

err = regmap_read(priv->map_reg, MCP251XFD_REG_TREC, &trec);
Expand Down Expand Up @@ -1079,7 +1079,7 @@ static int mcp251xfd_handle_cerrif(struct mcp251xfd_priv *priv)
/* The skb allocation might fail, but can_change_state()
* handles cf == NULL.
*/
skb = mcp251xfd_alloc_can_err_skb(priv, &cf, &timestamp);
skb = mcp251xfd_alloc_can_err_skb(priv, &cf, &ts_raw);
can_change_state(priv->ndev, cf, tx_state, rx_state);

if (new_state == CAN_STATE_BUS_OFF) {
Expand Down Expand Up @@ -1110,7 +1110,7 @@ static int mcp251xfd_handle_cerrif(struct mcp251xfd_priv *priv)
cf->data[7] = bec.rxerr;
}

err = can_rx_offload_queue_timestamp(&priv->offload, skb, timestamp);
err = can_rx_offload_queue_timestamp(&priv->offload, skb, ts_raw);
if (err)
stats->rx_fifo_errors++;

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ mcp251xfd_hw_rx_obj_to_skb(const struct mcp251xfd_priv *priv,
if (!(hw_rx_obj->flags & MCP251XFD_OBJ_FLAGS_RTR))
memcpy(cfd->data, hw_rx_obj->data, cfd->len);

mcp251xfd_skb_set_timestamp(priv, skb, hw_rx_obj->ts);
mcp251xfd_skb_set_timestamp_raw(priv, skb, hw_rx_obj->ts);
}

static int
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
tef_tail = mcp251xfd_get_tef_tail(priv);
skb = priv->can.echo_skb[tef_tail];
if (skb)
mcp251xfd_skb_set_timestamp(priv, skb, hw_tef_obj->ts);
mcp251xfd_skb_set_timestamp_raw(priv, skb, hw_tef_obj->ts);
stats->tx_bytes +=
can_rx_offload_get_echo_skb_queue_timestamp(&priv->offload,
tef_tail, hw_tef_obj->ts,
Expand Down
22 changes: 6 additions & 16 deletions drivers/net/can/spi/mcp251xfd/mcp251xfd-timestamp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// mcp251xfd - Microchip MCP251xFD Family CAN controller driver
//
// Copyright (c) 2021 Pengutronix,
// Copyright (c) 2021, 2023 Pengutronix,
// Marc Kleine-Budde <[email protected]>
//

Expand All @@ -11,20 +11,20 @@

#include "mcp251xfd.h"

static u64 mcp251xfd_timestamp_read(const struct cyclecounter *cc)
static u64 mcp251xfd_timestamp_raw_read(const struct cyclecounter *cc)
{
const struct mcp251xfd_priv *priv;
u32 timestamp = 0;
u32 ts_raw = 0;
int err;

priv = container_of(cc, struct mcp251xfd_priv, cc);
err = mcp251xfd_get_timestamp(priv, &timestamp);
err = mcp251xfd_get_timestamp_raw(priv, &ts_raw);
if (err)
netdev_err(priv->ndev,
"Error %d while reading timestamp. HW timestamps may be inaccurate.",
err);

return timestamp;
return ts_raw;
}

static void mcp251xfd_timestamp_work(struct work_struct *work)
Expand All @@ -39,21 +39,11 @@ static void mcp251xfd_timestamp_work(struct work_struct *work)
MCP251XFD_TIMESTAMP_WORK_DELAY_SEC * HZ);
}

void mcp251xfd_skb_set_timestamp(const struct mcp251xfd_priv *priv,
struct sk_buff *skb, u32 timestamp)
{
struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
u64 ns;

ns = timecounter_cyc2time(&priv->tc, timestamp);
hwtstamps->hwtstamp = ns_to_ktime(ns);
}

void mcp251xfd_timestamp_init(struct mcp251xfd_priv *priv)
{
struct cyclecounter *cc = &priv->cc;

cc->read = mcp251xfd_timestamp_read;
cc->read = mcp251xfd_timestamp_raw_read;
cc->mask = CYCLECOUNTER_MASK(32);
cc->shift = 1;
cc->mult = clocksource_hz2mult(priv->can.clock.freq, cc->shift);
Expand Down
27 changes: 21 additions & 6 deletions drivers/net/can/spi/mcp251xfd/mcp251xfd.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
*
* mcp251xfd - Microchip MCP251xFD Family CAN controller driver
*
* Copyright (c) 2019, 2020, 2021 Pengutronix,
* Copyright (c) 2019, 2020, 2021, 2023 Pengutronix,
* Marc Kleine-Budde <[email protected]>
* Copyright (c) 2019 Martin Sperl <[email protected]>
*/
Expand Down Expand Up @@ -812,10 +812,27 @@ mcp251xfd_spi_cmd_write(const struct mcp251xfd_priv *priv,
return data;
}

static inline int mcp251xfd_get_timestamp(const struct mcp251xfd_priv *priv,
u32 *timestamp)
static inline int mcp251xfd_get_timestamp_raw(const struct mcp251xfd_priv *priv,
u32 *ts_raw)
{
return regmap_read(priv->map_reg, MCP251XFD_REG_TBC, timestamp);
return regmap_read(priv->map_reg, MCP251XFD_REG_TBC, ts_raw);
}

static inline void mcp251xfd_skb_set_timestamp(struct sk_buff *skb, u64 ns)
{
struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);

hwtstamps->hwtstamp = ns_to_ktime(ns);
}

static inline
void mcp251xfd_skb_set_timestamp_raw(const struct mcp251xfd_priv *priv,
struct sk_buff *skb, u32 ts_raw)
{
u64 ns;

ns = timecounter_cyc2time(&priv->tc, ts_raw);
mcp251xfd_skb_set_timestamp(skb, ns);
}

static inline u16 mcp251xfd_get_tef_obj_addr(u8 n)
Expand Down Expand Up @@ -936,8 +953,6 @@ void mcp251xfd_ring_free(struct mcp251xfd_priv *priv);
int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv);
int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv);
int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv);
void mcp251xfd_skb_set_timestamp(const struct mcp251xfd_priv *priv,
struct sk_buff *skb, u32 timestamp);
void mcp251xfd_timestamp_init(struct mcp251xfd_priv *priv);
void mcp251xfd_timestamp_stop(struct mcp251xfd_priv *priv);

Expand Down

0 comments on commit 6cdc3fc

Please sign in to comment.