1145e5637SEran Ben Elisha /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
2145e5637SEran Ben Elisha /* Copyright (c) 2020 Mellanox Technologies. */
3145e5637SEran Ben Elisha 
4145e5637SEran Ben Elisha #ifndef __MLX5_EN_PTP_H__
5145e5637SEran Ben Elisha #define __MLX5_EN_PTP_H__
6145e5637SEran Ben Elisha 
7145e5637SEran Ben Elisha #include "en.h"
8145e5637SEran Ben Elisha #include "en_stats.h"
919b43a43SAya Levin #include "en/txrx.h"
103178308aSRahul Rameshbabu #include <linux/ktime.h>
11a6ee6f5fSAya Levin #include <linux/ptp_classify.h>
123178308aSRahul Rameshbabu #include <linux/time64.h>
1353b836a4SRahul Rameshbabu #include <linux/workqueue.h>
14145e5637SEran Ben Elisha 
15dd1979cfSLama Kayal #define MLX5E_PTP_CHANNEL_IX 0
163178308aSRahul Rameshbabu #define MLX5E_PTP_MAX_LOG_SQ_SIZE (8U)
173178308aSRahul Rameshbabu #define MLX5E_PTP_TS_CQE_UNDELIVERED_TIMEOUT (1 * NSEC_PER_SEC)
183178308aSRahul Rameshbabu 
193178308aSRahul Rameshbabu struct mlx5e_ptp_metadata_fifo {
203178308aSRahul Rameshbabu 	u8  cc;
213178308aSRahul Rameshbabu 	u8  pc;
223178308aSRahul Rameshbabu 	u8  mask;
233178308aSRahul Rameshbabu 	u8  *data;
243178308aSRahul Rameshbabu };
253178308aSRahul Rameshbabu 
263178308aSRahul Rameshbabu struct mlx5e_ptp_metadata_map {
273178308aSRahul Rameshbabu 	u16             undelivered_counter;
283178308aSRahul Rameshbabu 	u16             capacity;
293178308aSRahul Rameshbabu 	struct sk_buff  **data;
303178308aSRahul Rameshbabu };
31dd1979cfSLama Kayal 
32145e5637SEran Ben Elisha struct mlx5e_ptpsq {
33145e5637SEran Ben Elisha 	struct mlx5e_txqsq       txqsq;
341880bc4eSEran Ben Elisha 	struct mlx5e_cq          ts_cq;
351880bc4eSEran Ben Elisha 	struct mlx5e_ptp_cq_stats *cq_stats;
3658a51894SAya Levin 	u16                      ts_cqe_ctr_mask;
373178308aSRahul Rameshbabu 
3853b836a4SRahul Rameshbabu 	struct work_struct                 report_unhealthy_work;
393178308aSRahul Rameshbabu 	struct mlx5e_ptp_port_ts_cqe_list  *ts_cqe_pending_list;
403178308aSRahul Rameshbabu 	struct mlx5e_ptp_metadata_fifo     metadata_freelist;
413178308aSRahul Rameshbabu 	struct mlx5e_ptp_metadata_map      metadata_map;
42145e5637SEran Ben Elisha };
43145e5637SEran Ben Elisha 
4424c22dd0SAya Levin enum {
4524c22dd0SAya Levin 	MLX5E_PTP_STATE_TX,
46a099da8fSAya Levin 	MLX5E_PTP_STATE_RX,
4724c22dd0SAya Levin 	MLX5E_PTP_STATE_NUM_STATES,
4824c22dd0SAya Levin };
4924c22dd0SAya Levin 
50b0d35de4SAya Levin struct mlx5e_ptp {
51145e5637SEran Ben Elisha 	/* data path */
52145e5637SEran Ben Elisha 	struct mlx5e_ptpsq         ptpsq[MLX5E_MAX_NUM_TC];
53a099da8fSAya Levin 	struct mlx5e_rq            rq;
54145e5637SEran Ben Elisha 	struct napi_struct         napi;
55145e5637SEran Ben Elisha 	struct device             *pdev;
56145e5637SEran Ben Elisha 	struct net_device         *netdev;
57145e5637SEran Ben Elisha 	__be32                     mkey_be;
58145e5637SEran Ben Elisha 	u8                         num_tc;
59145e5637SEran Ben Elisha 	u8                         lag_port;
60145e5637SEran Ben Elisha 
61145e5637SEran Ben Elisha 	/* data path - accessed per napi poll */
62145e5637SEran Ben Elisha 	struct mlx5e_ch_stats     *stats;
63145e5637SEran Ben Elisha 
64145e5637SEran Ben Elisha 	/* control */
65145e5637SEran Ben Elisha 	struct mlx5e_priv         *priv;
66145e5637SEran Ben Elisha 	struct mlx5_core_dev      *mdev;
67145e5637SEran Ben Elisha 	struct hwtstamp_config    *tstamp;
6824c22dd0SAya Levin 	DECLARE_BITMAP(state, MLX5E_PTP_STATE_NUM_STATES);
69145e5637SEran Ben Elisha };
70145e5637SEran Ben Elisha 
mlx5e_use_ptpsq(struct sk_buff * skb)71a6ee6f5fSAya Levin static inline bool mlx5e_use_ptpsq(struct sk_buff *skb)
72a6ee6f5fSAya Levin {
73a6ee6f5fSAya Levin 	struct flow_keys fk;
74a6ee6f5fSAya Levin 
75a6ee6f5fSAya Levin 	if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP))
76a6ee6f5fSAya Levin 		return false;
77a6ee6f5fSAya Levin 
78a6ee6f5fSAya Levin 	if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
79a6ee6f5fSAya Levin 		return false;
80a6ee6f5fSAya Levin 
81a6ee6f5fSAya Levin 	if (fk.basic.n_proto == htons(ETH_P_1588))
82a6ee6f5fSAya Levin 		return true;
83a6ee6f5fSAya Levin 
84a6ee6f5fSAya Levin 	if (fk.basic.n_proto != htons(ETH_P_IP) &&
85a6ee6f5fSAya Levin 	    fk.basic.n_proto != htons(ETH_P_IPV6))
86a6ee6f5fSAya Levin 		return false;
87a6ee6f5fSAya Levin 
88a6ee6f5fSAya Levin 	return (fk.basic.ip_proto == IPPROTO_UDP &&
89a6ee6f5fSAya Levin 		fk.ports.dst == htons(PTP_EV_PORT));
90a6ee6f5fSAya Levin }
91a6ee6f5fSAya Levin 
mlx5e_ptp_metadata_fifo_push(struct mlx5e_ptp_metadata_fifo * fifo,u8 metadata)923178308aSRahul Rameshbabu static inline void mlx5e_ptp_metadata_fifo_push(struct mlx5e_ptp_metadata_fifo *fifo, u8 metadata)
9319b43a43SAya Levin {
943178308aSRahul Rameshbabu 	fifo->data[fifo->mask & fifo->pc++] = metadata;
953178308aSRahul Rameshbabu }
9619b43a43SAya Levin 
973178308aSRahul Rameshbabu static inline u8
mlx5e_ptp_metadata_fifo_peek(struct mlx5e_ptp_metadata_fifo * fifo)98292a7647SRahul Rameshbabu mlx5e_ptp_metadata_fifo_peek(struct mlx5e_ptp_metadata_fifo *fifo)
99292a7647SRahul Rameshbabu {
100292a7647SRahul Rameshbabu 	return fifo->data[fifo->mask & fifo->cc];
101292a7647SRahul Rameshbabu }
102292a7647SRahul Rameshbabu 
103292a7647SRahul Rameshbabu static inline void
mlx5e_ptp_metadata_fifo_pop(struct mlx5e_ptp_metadata_fifo * fifo)1043178308aSRahul Rameshbabu mlx5e_ptp_metadata_fifo_pop(struct mlx5e_ptp_metadata_fifo *fifo)
1053178308aSRahul Rameshbabu {
106292a7647SRahul Rameshbabu 	fifo->cc++;
1073178308aSRahul Rameshbabu }
1083178308aSRahul Rameshbabu 
1093178308aSRahul Rameshbabu static inline void
mlx5e_ptp_metadata_map_put(struct mlx5e_ptp_metadata_map * map,struct sk_buff * skb,u8 metadata)1103178308aSRahul Rameshbabu mlx5e_ptp_metadata_map_put(struct mlx5e_ptp_metadata_map *map,
1113178308aSRahul Rameshbabu 			   struct sk_buff *skb, u8 metadata)
1123178308aSRahul Rameshbabu {
1133178308aSRahul Rameshbabu 	WARN_ON_ONCE(map->data[metadata]);
1143178308aSRahul Rameshbabu 	map->data[metadata] = skb;
1153178308aSRahul Rameshbabu }
1163178308aSRahul Rameshbabu 
mlx5e_ptpsq_metadata_freelist_empty(struct mlx5e_ptpsq * ptpsq)1173178308aSRahul Rameshbabu static inline bool mlx5e_ptpsq_metadata_freelist_empty(struct mlx5e_ptpsq *ptpsq)
1183178308aSRahul Rameshbabu {
1193178308aSRahul Rameshbabu 	struct mlx5e_ptp_metadata_fifo *freelist;
1203178308aSRahul Rameshbabu 
1213178308aSRahul Rameshbabu 	if (likely(!ptpsq))
1223178308aSRahul Rameshbabu 		return false;
1233178308aSRahul Rameshbabu 
1243178308aSRahul Rameshbabu 	freelist = &ptpsq->metadata_freelist;
1253178308aSRahul Rameshbabu 
1263178308aSRahul Rameshbabu 	return freelist->pc == freelist->cc;
12719b43a43SAya Levin }
12819b43a43SAya Levin 
129b0d35de4SAya Levin int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params,
130b0d35de4SAya Levin 		   u8 lag_port, struct mlx5e_ptp **cp);
131b0d35de4SAya Levin void mlx5e_ptp_close(struct mlx5e_ptp *c);
132b0d35de4SAya Levin void mlx5e_ptp_activate_channel(struct mlx5e_ptp *c);
133b0d35de4SAya Levin void mlx5e_ptp_deactivate_channel(struct mlx5e_ptp *c);
1343adb60b6SAya Levin int mlx5e_ptp_get_rqn(struct mlx5e_ptp *c, u32 *rqn);
13581a0b241SLama Kayal int mlx5e_ptp_alloc_rx_fs(struct mlx5e_flow_steering *fs,
13681a0b241SLama Kayal 			  const struct mlx5e_profile *profile);
13781a0b241SLama Kayal void mlx5e_ptp_free_rx_fs(struct mlx5e_flow_steering *fs,
13881a0b241SLama Kayal 			  const struct mlx5e_profile *profile);
139e5fe4946SAya Levin int mlx5e_ptp_rx_manage_fs(struct mlx5e_priv *priv, bool set);
140145e5637SEran Ben Elisha 
1413178308aSRahul Rameshbabu void mlx5e_ptpsq_track_metadata(struct mlx5e_ptpsq *ptpsq, u8 metadata);
1423178308aSRahul Rameshbabu 
1431880bc4eSEran Ben Elisha enum {
1441880bc4eSEran Ben Elisha 	MLX5E_SKB_CB_CQE_HWTSTAMP  = BIT(0),
1451880bc4eSEran Ben Elisha 	MLX5E_SKB_CB_PORT_HWTSTAMP = BIT(1),
1461880bc4eSEran Ben Elisha };
1471880bc4eSEran Ben Elisha 
1481880bc4eSEran Ben Elisha void mlx5e_skb_cb_hwtstamp_handler(struct sk_buff *skb, int hwtstamp_type,
1491880bc4eSEran Ben Elisha 				   ktime_t hwtstamp,
1501880bc4eSEran Ben Elisha 				   struct mlx5e_ptp_cq_stats *cq_stats);
1511880bc4eSEran Ben Elisha 
1521880bc4eSEran Ben Elisha void mlx5e_skb_cb_hwtstamp_init(struct sk_buff *skb);
153145e5637SEran Ben Elisha #endif /* __MLX5_EN_PTP_H__ */
154