1 | /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ |
2 | /* Copyright (c) 2020 Mellanox Technologies. */ |
3 | |
4 | #ifndef __MLX5_EN_PTP_H__ |
5 | #define __MLX5_EN_PTP_H__ |
6 | |
7 | #include "en.h" |
8 | #include "en_stats.h" |
9 | #include "en/txrx.h" |
10 | #include <linux/ktime.h> |
11 | #include <linux/ptp_classify.h> |
12 | #include <linux/time64.h> |
13 | #include <linux/workqueue.h> |
14 | |
15 | #define MLX5E_PTP_CHANNEL_IX 0 |
16 | #define MLX5E_PTP_MAX_LOG_SQ_SIZE (8U) |
17 | #define MLX5E_PTP_TS_CQE_UNDELIVERED_TIMEOUT (1 * NSEC_PER_SEC) |
18 | |
19 | struct mlx5e_ptp_metadata_fifo { |
20 | u8 cc; |
21 | u8 pc; |
22 | u8 mask; |
23 | u8 *data; |
24 | }; |
25 | |
26 | struct mlx5e_ptp_metadata_map { |
27 | u16 undelivered_counter; |
28 | u16 capacity; |
29 | struct sk_buff **data; |
30 | }; |
31 | |
32 | struct mlx5e_ptpsq { |
33 | struct mlx5e_txqsq txqsq; |
34 | struct mlx5e_cq ts_cq; |
35 | struct mlx5e_ptp_cq_stats *cq_stats; |
36 | u16 ts_cqe_ctr_mask; |
37 | |
38 | struct work_struct report_unhealthy_work; |
39 | struct mlx5e_ptp_port_ts_cqe_list *ts_cqe_pending_list; |
40 | struct mlx5e_ptp_metadata_fifo metadata_freelist; |
41 | struct mlx5e_ptp_metadata_map metadata_map; |
42 | }; |
43 | |
44 | enum { |
45 | MLX5E_PTP_STATE_TX, |
46 | MLX5E_PTP_STATE_RX, |
47 | MLX5E_PTP_STATE_NUM_STATES, |
48 | }; |
49 | |
50 | struct mlx5e_ptp { |
51 | /* data path */ |
52 | struct mlx5e_ptpsq ptpsq[MLX5_MAX_NUM_TC]; |
53 | struct mlx5e_rq rq; |
54 | struct napi_struct napi; |
55 | struct device *pdev; |
56 | struct net_device *netdev; |
57 | __be32 mkey_be; |
58 | u8 num_tc; |
59 | u8 lag_port; |
60 | |
61 | /* data path - accessed per napi poll */ |
62 | struct mlx5e_ch_stats *stats; |
63 | |
64 | /* control */ |
65 | struct mlx5e_priv *priv; |
66 | struct mlx5_core_dev *mdev; |
67 | struct hwtstamp_config *tstamp; |
68 | DECLARE_BITMAP(state, MLX5E_PTP_STATE_NUM_STATES); |
69 | }; |
70 | |
71 | static inline bool mlx5e_use_ptpsq(struct sk_buff *skb) |
72 | { |
73 | struct flow_keys fk; |
74 | |
75 | if (!(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) |
76 | return false; |
77 | |
78 | if (!skb_flow_dissect_flow_keys(skb, flow: &fk, flags: 0)) |
79 | return false; |
80 | |
81 | if (fk.basic.n_proto == htons(ETH_P_1588)) |
82 | return true; |
83 | |
84 | if (fk.basic.n_proto != htons(ETH_P_IP) && |
85 | fk.basic.n_proto != htons(ETH_P_IPV6)) |
86 | return false; |
87 | |
88 | return (fk.basic.ip_proto == IPPROTO_UDP && |
89 | fk.ports.dst == htons(PTP_EV_PORT)); |
90 | } |
91 | |
92 | static inline void mlx5e_ptp_metadata_fifo_push(struct mlx5e_ptp_metadata_fifo *fifo, u8 metadata) |
93 | { |
94 | fifo->data[fifo->mask & fifo->pc++] = metadata; |
95 | } |
96 | |
97 | static inline u8 |
98 | mlx5e_ptp_metadata_fifo_peek(struct mlx5e_ptp_metadata_fifo *fifo) |
99 | { |
100 | return fifo->data[fifo->mask & fifo->cc]; |
101 | } |
102 | |
103 | static inline void |
104 | mlx5e_ptp_metadata_fifo_pop(struct mlx5e_ptp_metadata_fifo *fifo) |
105 | { |
106 | fifo->cc++; |
107 | } |
108 | |
109 | static inline void |
110 | mlx5e_ptp_metadata_map_put(struct mlx5e_ptp_metadata_map *map, |
111 | struct sk_buff *skb, u8 metadata) |
112 | { |
113 | WARN_ON_ONCE(map->data[metadata]); |
114 | map->data[metadata] = skb; |
115 | } |
116 | |
117 | static inline bool mlx5e_ptpsq_metadata_freelist_empty(struct mlx5e_ptpsq *ptpsq) |
118 | { |
119 | struct mlx5e_ptp_metadata_fifo *freelist; |
120 | |
121 | if (likely(!ptpsq)) |
122 | return false; |
123 | |
124 | freelist = &ptpsq->metadata_freelist; |
125 | |
126 | return freelist->pc == freelist->cc; |
127 | } |
128 | |
129 | int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params, |
130 | u8 lag_port, struct mlx5e_ptp **cp); |
131 | void mlx5e_ptp_close(struct mlx5e_ptp *c); |
132 | void mlx5e_ptp_activate_channel(struct mlx5e_ptp *c); |
133 | void mlx5e_ptp_deactivate_channel(struct mlx5e_ptp *c); |
134 | int mlx5e_ptp_get_rqn(struct mlx5e_ptp *c, u32 *rqn); |
135 | int mlx5e_ptp_alloc_rx_fs(struct mlx5e_flow_steering *fs, |
136 | const struct mlx5e_profile *profile); |
137 | void mlx5e_ptp_free_rx_fs(struct mlx5e_flow_steering *fs, |
138 | const struct mlx5e_profile *profile); |
139 | int mlx5e_ptp_rx_manage_fs(struct mlx5e_priv *priv, bool set); |
140 | |
141 | void mlx5e_ptpsq_track_metadata(struct mlx5e_ptpsq *ptpsq, u8 metadata); |
142 | |
143 | enum { |
144 | MLX5E_SKB_CB_CQE_HWTSTAMP = BIT(0), |
145 | MLX5E_SKB_CB_PORT_HWTSTAMP = BIT(1), |
146 | }; |
147 | |
148 | void mlx5e_skb_cb_hwtstamp_handler(struct sk_buff *skb, int hwtstamp_type, |
149 | ktime_t hwtstamp, |
150 | struct mlx5e_ptp_cq_stats *cq_stats); |
151 | |
152 | void mlx5e_skb_cb_hwtstamp_init(struct sk_buff *skb); |
153 | #endif /* __MLX5_EN_PTP_H__ */ |
154 | |