can: mcp251xfd: clarify the meaning of timestamp

[ Upstream commit e793c724b4 ]

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 <Stefan.Althoefer@janztec.com>
Tested-by: Thomas Kopp <thomas.kopp@microchip.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Marc Kleine-Budde 2023-01-11 11:48:16 +01:00 committed by Greg Kroah-Hartman
parent bf501ab4cb
commit 6cdc3fc4fb
5 changed files with 43 additions and 38 deletions

View file

@ -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 <kernel@pengutronix.de>
//
// Based on:
@ -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;
}
@ -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++;
@ -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++;
@ -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;
@ -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++;
@ -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);
@ -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) {
@ -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++;

View file

@ -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

View file

@ -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,

View file

@ -2,7 +2,7 @@
//
// mcp251xfd - Microchip MCP251xFD Family CAN controller driver
//
// Copyright (c) 2021 Pengutronix,
// Copyright (c) 2021, 2023 Pengutronix,
// Marc Kleine-Budde <kernel@pengutronix.de>
//
@ -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)
@ -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);

View file

@ -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 <kernel@pengutronix.de>
* Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
*/
@ -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)
@ -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);