Commit a9609d79 authored by David S. Miller's avatar David S. Miller

Merge branch 'dpaa2_eth-support-1588-one-step-timestamping'

Yangbo Lu says:

====================
dpaa2_eth: support 1588 one-step timestamping

This patch-set is to add MC APIs of 1588 one-step timestamping, and
support one-step timestamping for PTP Sync packet on DPAA2.

Before egress, one-step timestamping enablement needs,

- Enabling timestamp and FAS (Frame Annotation Status) in
  dpni buffer layout.

- Write timestamp to frame annotation and set PTP bit in
  FAS to mark as one-step timestamping event.

- Enabling one-step timestamping by dpni_set_single_step_cfg()
  API, with offset provided to insert correction time on frame.
  The offset must respect all MAC headers, VLAN tags and other
  protocol headers accordingly. The correction field update can
  consider delays up to one second. So PTP frame needs to be
  filtered and parsed, and written timestamp into Sync frame
  originTimestamp field.

The operation of API dpni_set_single_step_cfg() has to be done
when no one-step timestamping frames are in flight. So we have
to make sure the last one-step timestamping frame has already
been transmitted on hardware before starting to send the current
one. The resolution is,

- Utilize skb->cb[0] to mark timestamping request per packet.
  If it is one-step timestamping PTP sync packet, queue to skb queue.
  If not, transmit immediately.

- Schedule a work to transmit skbs in skb queue.

- mutex lock is used to ensure the last one-step timestamping packet
  has already been transmitted on hardware through TX confirmation queue
  before transmitting current packet.

Changes for v2:
	- Removed unused variable priv in dpaa2_eth_xdp_create_fd().
Changes for v3:
	- Fixed sparse warnings.
	- Fix build issue on 32-bit.
	- Converted to use ptp_parse_header.
Changes for v4:
	- Used WARN_ONCE instead of netdev_err in data path.
	- Enabled timestamping only when PTP driver is ready.
	- Added comments in using onestep_tstamp_lock.
	- Dropped dpmac.c sparse warning fix-up patch.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7b066d17 c5521189
......@@ -10,6 +10,7 @@
#include <linux/netdevice.h>
#include <linux/if_vlan.h>
#include <linux/fsl/mc.h>
#include <linux/net_tstamp.h>
#include <soc/fsl/dpaa2-io.h>
#include <soc/fsl/dpaa2-fd.h>
......@@ -194,6 +195,24 @@ struct dpaa2_faead {
#define DPAA2_FAEAD_EBDDV 0x00002000
#define DPAA2_FAEAD_UPD 0x00000010
struct ptp_tstamp {
u16 sec_msb;
u32 sec_lsb;
u32 nsec;
};
static inline void ns_to_ptp_tstamp(struct ptp_tstamp *tstamp, u64 ns)
{
u64 sec, nsec;
sec = ns;
nsec = do_div(sec, 1000000000);
tstamp->sec_lsb = sec & 0xFFFFFFFF;
tstamp->sec_msb = (sec >> 32) & 0xFFFF;
tstamp->nsec = nsec;
}
/* Accessors for the hardware annotation fields that we use */
static inline void *dpaa2_get_hwa(void *buf_addr, bool swa)
{
......@@ -433,8 +452,8 @@ struct dpaa2_eth_priv {
u16 bpid;
struct iommu_domain *iommu_domain;
bool tx_tstamp; /* Tx timestamping enabled */
bool rx_tstamp; /* Rx timestamping enabled */
enum hwtstamp_tx_types tx_tstamp_type; /* Tx timestamping type */
bool rx_tstamp; /* Rx timestamping enabled */
u16 tx_qdid;
struct fsl_mc_io *mc_io;
......@@ -473,8 +492,22 @@ struct dpaa2_eth_priv {
#endif
struct dpaa2_mac *mac;
struct workqueue_struct *dpaa2_ptp_wq;
struct work_struct tx_onestep_tstamp;
struct sk_buff_head tx_skbs;
/* The one-step timestamping configuration on hardware
* registers could only be done when no one-step
* timestamping frames are in flight. So we use a mutex
* lock here to make sure the lock is released by last
* one-step timestamping packet through TX confirmation
* queue before transmit current packet.
*/
struct mutex onestep_tstamp_lock;
};
#define TX_TSTAMP 0x1
#define TX_TSTAMP_ONESTEP_SYNC 0x2
#define DPAA2_RXH_SUPPORTED (RXH_L2DA | RXH_VLAN | RXH_L3_PROTO \
| RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 \
| RXH_L4_B_2_3)
......@@ -491,6 +524,7 @@ struct dpaa2_eth_priv {
extern const struct ethtool_ops dpaa2_ethtool_ops;
extern int dpaa2_phc_index;
extern struct ptp_qoriq *dpaa2_ptp;
static inline int dpaa2_eth_cmp_dpni_ver(struct dpaa2_eth_priv *priv,
u16 ver_major, u16 ver_minor)
......@@ -560,9 +594,7 @@ static inline bool dpaa2_eth_rx_pause_enabled(u64 link_options)
return !!(link_options & DPNI_LINK_OPT_PAUSE);
}
static inline
unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv,
struct sk_buff *skb)
static inline unsigned int dpaa2_eth_needed_headroom(struct sk_buff *skb)
{
unsigned int headroom = DPAA2_ETH_SWA_SIZE;
......@@ -579,7 +611,7 @@ unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv,
return 0;
/* If we have Tx timestamping, need 128B hardware annotation */
if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
if (skb->cb[0])
headroom += DPAA2_ETH_TX_HWA_SIZE;
return headroom;
......
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/* Copyright 2014-2016 Freescale Semiconductor Inc.
* Copyright 2016 NXP
* Copyright 2020 NXP
*/
#include <linux/net_tstamp.h>
......@@ -763,6 +764,9 @@ EXPORT_SYMBOL(dpaa2_phc_index);
static int dpaa2_eth_get_ts_info(struct net_device *dev,
struct ethtool_ts_info *info)
{
if (!dpaa2_ptp)
return ethtool_op_get_ts_info(dev, info);
info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
......@@ -770,7 +774,8 @@ static int dpaa2_eth_get_ts_info(struct net_device *dev,
info->phc_index = dpaa2_phc_index;
info->tx_types = (1 << HWTSTAMP_TX_OFF) |
(1 << HWTSTAMP_TX_ON);
(1 << HWTSTAMP_TX_ON) |
(1 << HWTSTAMP_TX_ONESTEP_SYNC);
info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
(1 << HWTSTAMP_FILTER_ALL);
......
......@@ -2,6 +2,7 @@
/*
* Copyright 2013-2016 Freescale Semiconductor Inc.
* Copyright 2016-2018 NXP
* Copyright 2020 NXP
*/
#include <linux/module.h>
......@@ -9,7 +10,6 @@
#include <linux/of_address.h>
#include <linux/msi.h>
#include <linux/fsl/mc.h>
#include <linux/fsl/ptp_qoriq.h>
#include "dpaa2-ptp.h"
......@@ -201,6 +201,7 @@ static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev)
goto err_free_threaded_irq;
dpaa2_phc_index = ptp_qoriq->phc_index;
dpaa2_ptp = ptp_qoriq;
dev_set_drvdata(dev, ptp_qoriq);
return 0;
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright 2018 NXP
* Copyright 2020 NXP
*/
#ifndef __RTC_H
#define __RTC_H
#include <linux/fsl/ptp_qoriq.h>
#include "dprtc.h"
#include "dprtc-cmd.h"
extern int dpaa2_phc_index;
extern struct ptp_qoriq *dpaa2_ptp;
#endif
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
/* Copyright 2013-2016 Freescale Semiconductor Inc.
* Copyright 2016 NXP
* Copyright 2020 NXP
*/
#ifndef _FSL_DPNI_CMD_H
#define _FSL_DPNI_CMD_H
......@@ -90,6 +91,9 @@
#define DPNI_CMDID_SET_RX_HASH_DIST DPNI_CMD(0x274)
#define DPNI_CMDID_GET_LINK_CFG DPNI_CMD(0x278)
#define DPNI_CMDID_SET_SINGLE_STEP_CFG DPNI_CMD(0x279)
#define DPNI_CMDID_GET_SINGLE_STEP_CFG DPNI_CMD(0x27a)
/* Macros for accessing command fields smaller than 1byte */
#define DPNI_MASK(field) \
GENMASK(DPNI_##field##_SHIFT + DPNI_##field##_SIZE - 1, \
......@@ -639,4 +643,21 @@ struct dpni_cmd_set_tx_shaping {
u8 coupled;
};
#define DPNI_PTP_ENABLE_SHIFT 0
#define DPNI_PTP_ENABLE_SIZE 1
#define DPNI_PTP_CH_UPDATE_SHIFT 1
#define DPNI_PTP_CH_UPDATE_SIZE 1
struct dpni_cmd_single_step_cfg {
__le16 flags;
__le16 offset;
__le32 peer_delay;
};
struct dpni_rsp_single_step_cfg {
__le16 flags;
__le16 offset;
__le32 peer_delay;
};
#endif /* _FSL_DPNI_CMD_H */
// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/* Copyright 2013-2016 Freescale Semiconductor Inc.
* Copyright 2016 NXP
* Copyright 2020 NXP
*/
#include <linux/kernel.h>
#include <linux/errno.h>
......@@ -1999,3 +2000,81 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io,
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
/**
* dpni_get_single_step_cfg() - return current configuration for
* single step PTP
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPNI object
* @ptp_cfg: ptp single step configuration
*
* Return: '0' on Success; Error code otherwise.
*
*/
int dpni_get_single_step_cfg(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
struct dpni_single_step_cfg *ptp_cfg)
{
struct dpni_rsp_single_step_cfg *rsp_params;
struct fsl_mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_SINGLE_STEP_CFG,
cmd_flags, token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* read command response */
rsp_params = (struct dpni_rsp_single_step_cfg *)cmd.params;
ptp_cfg->offset = le16_to_cpu(rsp_params->offset);
ptp_cfg->en = dpni_get_field(le16_to_cpu(rsp_params->flags),
PTP_ENABLE) ? 1 : 0;
ptp_cfg->ch_update = dpni_get_field(le16_to_cpu(rsp_params->flags),
PTP_CH_UPDATE) ? 1 : 0;
ptp_cfg->peer_delay = le32_to_cpu(rsp_params->peer_delay);
return err;
}
/**
* dpni_set_single_step_cfg() - enable/disable and configure single step PTP
* @mc_io: Pointer to MC portal's I/O object
* @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
* @token: Token of DPNI object
* @ptp_cfg: ptp single step configuration
*
* Return: '0' on Success; Error code otherwise.
*
* The function has effect only when dpni object is connected to a dpmac
* object. If the dpni is not connected to a dpmac the configuration will
* be stored inside and applied when connection is made.
*/
int dpni_set_single_step_cfg(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
struct dpni_single_step_cfg *ptp_cfg)
{
struct dpni_cmd_single_step_cfg *cmd_params;
struct fsl_mc_command cmd = { 0 };
u16 flags;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_SINGLE_STEP_CFG,
cmd_flags, token);
cmd_params = (struct dpni_cmd_single_step_cfg *)cmd.params;
cmd_params->offset = cpu_to_le16(ptp_cfg->offset);
cmd_params->peer_delay = cpu_to_le32(ptp_cfg->peer_delay);
flags = le16_to_cpu(cmd_params->flags);
dpni_set_field(flags, PTP_ENABLE, !!ptp_cfg->en);
dpni_set_field(flags, PTP_CH_UPDATE, !!ptp_cfg->ch_update);
cmd_params->flags = cpu_to_le16(flags);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
/* Copyright 2013-2016 Freescale Semiconductor Inc.
* Copyright 2016 NXP
* Copyright 2020 NXP
*/
#ifndef __FSL_DPNI_H
#define __FSL_DPNI_H
......@@ -1079,4 +1080,34 @@ int dpni_set_tx_shaping(struct fsl_mc_io *mc_io,
const struct dpni_tx_shaping_cfg *tx_er_shaper,
int coupled);
/**
* struct dpni_single_step_cfg - configure single step PTP (IEEE 1588)
* @en: enable single step PTP. When enabled the PTPv1 functionality
* will not work. If the field is zero, offset and ch_update
* parameters will be ignored
* @offset: start offset from the beginning of the frame where
* timestamp field is found. The offset must respect all MAC
* headers, VLAN tags and other protocol headers
* @ch_update: when set UDP checksum will be updated inside packet
* @peer_delay: For peer-to-peer transparent clocks add this value to the
* correction field in addition to the transient time update.
* The value expresses nanoseconds.
*/
struct dpni_single_step_cfg {
u8 en;
u8 ch_update;
u16 offset;
u32 peer_delay;
};
int dpni_set_single_step_cfg(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
struct dpni_single_step_cfg *ptp_cfg);
int dpni_get_single_step_cfg(struct fsl_mc_io *mc_io,
u32 cmd_flags,
u16 token,
struct dpni_single_step_cfg *ptp_cfg);
#endif /* __FSL_DPNI_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment