Skip to content

Commit fa3c40b

Browse files
Merge patch series "can: kvaser_usb: Add hardware timestamp support to all devices"
Jimmy Assarsson <[email protected]> says: This patch series add hardware timestamp support to all devices supported by the kvaser_usb driver. The first patches resolves a known issue; "Hardware timestamps are not set for CAN Tx frames". I can't remember why this wasn't implemented in the first version of the hydra driver. Followed by, hardware timestamp support for leaf and usbcan based devices. The final patches are removing code used for selecting the correct ethtool and netdev ops. Note: This patch series depends on patch "can: kvaser_usb: Explicitly initialize family in leafimx..." [1]. [1] https://lore.kernel.org/linux-can/[email protected] Changes in v2: - Replaced patch 3/15 can: kvaser_usb: Add function kvaser_usb_ticks_to_ktime() with a new patch can: kvaser_usb: Add helper functions to convert device timestamp into ktime and put it first in this series - Resolved Vincent MAILHOL's review comments regarding duplicated code when converting timestamps [2] [3] - As pointed out by Vincent MAILHOL [4], the clock overflow commands is not dispatched in this patch moved code from 10/15 can: kvaser_usb: leaf: Add structs for Tx ACK and clock overflow commands to 11/15 can: kvaser_usb: leaf: Store MSB of timestamp where it's actually used [2] https://lore.kernel.org/linux-can/CAMZ6RqKSa-6KjvgfmN9eL7A=A65gMkYsRrnaF41Azhsc45FA2Q@mail.gmail.com/ [3] https://lore.kernel.org/linux-can/CAMZ6Rq+Xd7+th=dKV+vrqzRtS+GY-xq2UziH1CURcQ3HxEXMqQ@mail.gmail.com/ [4] https://lore.kernel.org/linux-can/CAMZ6RqKqJX6eqogS2598BFm-AN1uOBbBGL+MkoJtR=-z379Q=w@mail.gmail.com/ Link: https://lore.kernel.org/all/[email protected] Signed-off-by: Marc Kleine-Budde <[email protected]>
2 parents 0fe41a8 + 88371f8 commit fa3c40b

File tree

4 files changed

+153
-49
lines changed

4 files changed

+153
-49
lines changed

drivers/net/can/usb/kvaser_usb/kvaser_usb.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
*/
2323

2424
#include <linux/completion.h>
25+
#include <linux/ktime.h>
26+
#include <linux/math64.h>
2527
#include <linux/spinlock.h>
2628
#include <linux/types.h>
2729
#include <linux/usb.h>
@@ -39,7 +41,6 @@
3941
#define KVASER_USB_QUIRK_HAS_SILENT_MODE BIT(0)
4042
#define KVASER_USB_QUIRK_HAS_TXRX_ERRORS BIT(1)
4143
#define KVASER_USB_QUIRK_IGNORE_CLK_FREQ BIT(2)
42-
#define KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP BIT(3)
4344

4445
/* Device capabilities */
4546
#define KVASER_USB_CAP_BERR_CAP 0x01
@@ -68,6 +69,7 @@ struct kvaser_usb_dev_card_data {
6869
u32 ctrlmode_supported;
6970
u32 capabilities;
7071
struct kvaser_usb_dev_card_data_hydra hydra;
72+
u32 usbcan_timestamp_msb;
7173
};
7274

7375
/* Context for an outstanding, not yet ACKed, transmission */
@@ -216,4 +218,26 @@ int kvaser_usb_can_rx_over_error(struct net_device *netdev);
216218

217219
extern const struct can_bittiming_const kvaser_usb_flexc_bittiming_const;
218220

221+
static inline ktime_t kvaser_usb_ticks_to_ktime(const struct kvaser_usb_dev_cfg *cfg,
222+
u64 ticks)
223+
{
224+
return ns_to_ktime(div_u64(ticks * 1000, cfg->timestamp_freq));
225+
}
226+
227+
static inline ktime_t kvaser_usb_timestamp48_to_ktime(const struct kvaser_usb_dev_cfg *cfg,
228+
const __le16 *timestamp)
229+
{
230+
u64 ticks = le16_to_cpu(timestamp[0]) |
231+
(u64)(le16_to_cpu(timestamp[1])) << 16 |
232+
(u64)(le16_to_cpu(timestamp[2])) << 32;
233+
234+
return kvaser_usb_ticks_to_ktime(cfg, ticks);
235+
}
236+
237+
static inline ktime_t kvaser_usb_timestamp64_to_ktime(const struct kvaser_usb_dev_cfg *cfg,
238+
__le64 timestamp)
239+
{
240+
return kvaser_usb_ticks_to_ktime(cfg, le64_to_cpu(timestamp));
241+
}
242+
219243
#endif /* KVASER_USB_H */

drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@
9494
#define USB_MINI_PCIE_1XCAN_PRODUCT_ID 0x011B
9595

9696
static const struct kvaser_usb_driver_info kvaser_usb_driver_info_hydra = {
97-
.quirks = KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP,
97+
.quirks = 0,
9898
.ops = &kvaser_usb_hydra_dev_ops,
9999
};
100100

@@ -754,13 +754,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
754754
}
755755

756756
static const struct net_device_ops kvaser_usb_netdev_ops = {
757-
.ndo_open = kvaser_usb_open,
758-
.ndo_stop = kvaser_usb_close,
759-
.ndo_start_xmit = kvaser_usb_start_xmit,
760-
.ndo_change_mtu = can_change_mtu,
761-
};
762-
763-
static const struct net_device_ops kvaser_usb_netdev_ops_hwts = {
764757
.ndo_open = kvaser_usb_open,
765758
.ndo_stop = kvaser_usb_close,
766759
.ndo_eth_ioctl = can_eth_ioctl_hwts,
@@ -769,10 +762,6 @@ static const struct net_device_ops kvaser_usb_netdev_ops_hwts = {
769762
};
770763

771764
static const struct ethtool_ops kvaser_usb_ethtool_ops = {
772-
.get_ts_info = ethtool_op_get_ts_info,
773-
};
774-
775-
static const struct ethtool_ops kvaser_usb_ethtool_ops_hwts = {
776765
.get_ts_info = can_ethtool_op_get_ts_info_hwts,
777766
};
778767

@@ -859,13 +848,7 @@ static int kvaser_usb_init_one(struct kvaser_usb *dev, int channel)
859848
netdev->flags |= IFF_ECHO;
860849

861850
netdev->netdev_ops = &kvaser_usb_netdev_ops;
862-
if (driver_info->quirks & KVASER_USB_QUIRK_HAS_HARDWARE_TIMESTAMP) {
863-
netdev->netdev_ops = &kvaser_usb_netdev_ops_hwts;
864-
netdev->ethtool_ops = &kvaser_usb_ethtool_ops_hwts;
865-
} else {
866-
netdev->netdev_ops = &kvaser_usb_netdev_ops;
867-
netdev->ethtool_ops = &kvaser_usb_ethtool_ops;
868-
}
851+
netdev->ethtool_ops = &kvaser_usb_ethtool_ops;
869852
SET_NETDEV_DEV(netdev, &dev->intf->dev);
870853
netdev->dev_id = channel;
871854

drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
* - Transition from CAN_STATE_ERROR_WARNING to CAN_STATE_ERROR_ACTIVE is only
1111
* reported after a call to do_get_berr_counter(), since firmware does not
1212
* distinguish between ERROR_WARNING and ERROR_ACTIVE.
13-
* - Hardware timestamps are not set for CAN Tx frames.
1413
*/
1514

1615
#include <linux/completion.h>
@@ -261,6 +260,15 @@ struct kvaser_cmd_tx_can {
261260
u8 reserved[11];
262261
} __packed;
263262

263+
struct kvaser_cmd_tx_ack {
264+
__le32 id;
265+
u8 data[8];
266+
u8 dlc;
267+
u8 flags;
268+
__le16 timestamp[3];
269+
u8 reserved0[8];
270+
} __packed;
271+
264272
struct kvaser_cmd_header {
265273
u8 cmd_no;
266274
/* The destination HE address is stored in 0..5 of he_addr.
@@ -297,6 +305,7 @@ struct kvaser_cmd {
297305

298306
struct kvaser_cmd_rx_can rx_can;
299307
struct kvaser_cmd_tx_can tx_can;
308+
struct kvaser_cmd_tx_ack tx_ack;
300309
} __packed;
301310
} __packed;
302311

@@ -522,23 +531,25 @@ kvaser_usb_hydra_net_priv_from_cmd(const struct kvaser_usb *dev,
522531
return priv;
523532
}
524533

525-
static ktime_t
526-
kvaser_usb_hydra_ktime_from_rx_cmd(const struct kvaser_usb_dev_cfg *cfg,
527-
const struct kvaser_cmd *cmd)
534+
static ktime_t kvaser_usb_hydra_ktime_from_cmd(const struct kvaser_usb_dev_cfg *cfg,
535+
const struct kvaser_cmd *cmd)
528536
{
529-
u64 ticks;
537+
ktime_t hwtstamp = 0;
530538

531539
if (cmd->header.cmd_no == CMD_EXTENDED) {
532540
struct kvaser_cmd_ext *cmd_ext = (struct kvaser_cmd_ext *)cmd;
533541

534-
ticks = le64_to_cpu(cmd_ext->rx_can.timestamp);
535-
} else {
536-
ticks = le16_to_cpu(cmd->rx_can.timestamp[0]);
537-
ticks += (u64)(le16_to_cpu(cmd->rx_can.timestamp[1])) << 16;
538-
ticks += (u64)(le16_to_cpu(cmd->rx_can.timestamp[2])) << 32;
542+
if (cmd_ext->cmd_no_ext == CMD_RX_MESSAGE_FD)
543+
hwtstamp = kvaser_usb_timestamp64_to_ktime(cfg, cmd_ext->rx_can.timestamp);
544+
else if (cmd_ext->cmd_no_ext == CMD_TX_ACKNOWLEDGE_FD)
545+
hwtstamp = kvaser_usb_timestamp64_to_ktime(cfg, cmd_ext->tx_ack.timestamp);
546+
} else if (cmd->header.cmd_no == CMD_RX_MESSAGE) {
547+
hwtstamp = kvaser_usb_timestamp48_to_ktime(cfg, cmd->rx_can.timestamp);
548+
} else if (cmd->header.cmd_no == CMD_TX_ACKNOWLEDGE) {
549+
hwtstamp = kvaser_usb_timestamp48_to_ktime(cfg, cmd->tx_ack.timestamp);
539550
}
540551

541-
return ns_to_ktime(div_u64(ticks * 1000, cfg->timestamp_freq));
552+
return hwtstamp;
542553
}
543554

544555
static int kvaser_usb_hydra_send_simple_cmd(struct kvaser_usb *dev,
@@ -1175,6 +1186,7 @@ static void kvaser_usb_hydra_tx_acknowledge(const struct kvaser_usb *dev,
11751186
bool one_shot_fail = false;
11761187
bool is_err_frame = false;
11771188
u16 transid = kvaser_usb_hydra_get_cmd_transid(cmd);
1189+
struct sk_buff *skb;
11781190

11791191
priv = kvaser_usb_hydra_net_priv_from_cmd(dev, cmd);
11801192
if (!priv)
@@ -1201,6 +1213,9 @@ static void kvaser_usb_hydra_tx_acknowledge(const struct kvaser_usb *dev,
12011213

12021214
spin_lock_irqsave(&priv->tx_contexts_lock, irq_flags);
12031215

1216+
skb = priv->can.echo_skb[context->echo_index];
1217+
if (skb)
1218+
skb_hwtstamps(skb)->hwtstamp = kvaser_usb_hydra_ktime_from_cmd(dev->cfg, cmd);
12041219
len = can_get_echo_skb(priv->netdev, context->echo_index, NULL);
12051220
context->echo_index = dev->max_tx_urbs;
12061221
--priv->active_tx_contexts;
@@ -1234,7 +1249,7 @@ static void kvaser_usb_hydra_rx_msg_std(const struct kvaser_usb *dev,
12341249
stats = &priv->netdev->stats;
12351250

12361251
flags = cmd->rx_can.flags;
1237-
hwtstamp = kvaser_usb_hydra_ktime_from_rx_cmd(dev->cfg, cmd);
1252+
hwtstamp = kvaser_usb_hydra_ktime_from_cmd(dev->cfg, cmd);
12381253

12391254
if (flags & KVASER_USB_HYDRA_CF_FLAG_ERROR_FRAME) {
12401255
kvaser_usb_hydra_error_frame(priv, &cmd->rx_can.err_frame_data,
@@ -1302,7 +1317,7 @@ static void kvaser_usb_hydra_rx_msg_ext(const struct kvaser_usb *dev,
13021317
KVASER_USB_KCAN_DATA_DLC_SHIFT;
13031318

13041319
flags = le32_to_cpu(cmd->rx_can.flags);
1305-
hwtstamp = kvaser_usb_hydra_ktime_from_rx_cmd(dev->cfg, std_cmd);
1320+
hwtstamp = kvaser_usb_hydra_ktime_from_cmd(dev->cfg, std_cmd);
13061321

13071322
if (flags & KVASER_USB_HYDRA_CF_FLAG_ERROR_FRAME) {
13081323
kvaser_usb_hydra_error_frame(priv, &cmd->rx_can.err_frame_data,

0 commit comments

Comments
 (0)