xref: /linux/drivers/net/ethernet/engleder/tsnep.h (revision 00e984cb)
1403f69bbSGerhard Engleder /* SPDX-License-Identifier: GPL-2.0 */
2403f69bbSGerhard Engleder /* Copyright (C) 2021 Gerhard Engleder <gerhard@engleder-embedded.com> */
3403f69bbSGerhard Engleder 
4403f69bbSGerhard Engleder #ifndef _TSNEP_H
5403f69bbSGerhard Engleder #define _TSNEP_H
6403f69bbSGerhard Engleder 
7403f69bbSGerhard Engleder #include "tsnep_hw.h"
8403f69bbSGerhard Engleder 
9403f69bbSGerhard Engleder #include <linux/platform_device.h>
10403f69bbSGerhard Engleder #include <linux/dma-mapping.h>
11403f69bbSGerhard Engleder #include <linux/etherdevice.h>
12403f69bbSGerhard Engleder #include <linux/phy.h>
13403f69bbSGerhard Engleder #include <linux/ethtool.h>
14403f69bbSGerhard Engleder #include <linux/net_tstamp.h>
15403f69bbSGerhard Engleder #include <linux/ptp_clock_kernel.h>
16403f69bbSGerhard Engleder #include <linux/miscdevice.h>
1792272ec4SJakub Kicinski #include <net/xdp.h>
18403f69bbSGerhard Engleder 
19403f69bbSGerhard Engleder #define TSNEP "tsnep"
20403f69bbSGerhard Engleder 
21403f69bbSGerhard Engleder #define TSNEP_RING_SIZE 256
2242fb2962SGerhard Engleder #define TSNEP_RING_MASK (TSNEP_RING_SIZE - 1)
23dbadae92SGerhard Engleder #define TSNEP_RING_RX_REFILL 16
24dbadae92SGerhard Engleder #define TSNEP_RING_RX_REUSE (TSNEP_RING_SIZE - TSNEP_RING_SIZE / 4)
25403f69bbSGerhard Engleder #define TSNEP_RING_ENTRIES_PER_PAGE (PAGE_SIZE / TSNEP_DESC_SIZE)
26403f69bbSGerhard Engleder #define TSNEP_RING_PAGE_COUNT (TSNEP_RING_SIZE / TSNEP_RING_ENTRIES_PER_PAGE)
27403f69bbSGerhard Engleder 
28403f69bbSGerhard Engleder struct tsnep_gcl {
29403f69bbSGerhard Engleder 	void __iomem *addr;
30403f69bbSGerhard Engleder 
31403f69bbSGerhard Engleder 	u64 base_time;
32403f69bbSGerhard Engleder 	u64 cycle_time;
33403f69bbSGerhard Engleder 	u64 cycle_time_extension;
34403f69bbSGerhard Engleder 
35403f69bbSGerhard Engleder 	struct tsnep_gcl_operation operation[TSNEP_GCL_COUNT];
36403f69bbSGerhard Engleder 	int count;
37403f69bbSGerhard Engleder 
38403f69bbSGerhard Engleder 	u64 change_limit;
39403f69bbSGerhard Engleder 
40403f69bbSGerhard Engleder 	u64 start_time;
41403f69bbSGerhard Engleder 	bool change;
42403f69bbSGerhard Engleder };
43403f69bbSGerhard Engleder 
44308ce142SGerhard Engleder enum tsnep_rxnfc_filter_type {
45308ce142SGerhard Engleder 	TSNEP_RXNFC_ETHER_TYPE,
46308ce142SGerhard Engleder };
47308ce142SGerhard Engleder 
48308ce142SGerhard Engleder struct tsnep_rxnfc_filter {
49308ce142SGerhard Engleder 	enum tsnep_rxnfc_filter_type type;
50308ce142SGerhard Engleder 	union {
51308ce142SGerhard Engleder 		u16 ether_type;
52308ce142SGerhard Engleder 	};
53308ce142SGerhard Engleder };
54308ce142SGerhard Engleder 
55308ce142SGerhard Engleder struct tsnep_rxnfc_rule {
56308ce142SGerhard Engleder 	struct list_head list;
57308ce142SGerhard Engleder 	struct tsnep_rxnfc_filter filter;
58308ce142SGerhard Engleder 	int queue_index;
59308ce142SGerhard Engleder 	int location;
60308ce142SGerhard Engleder };
61308ce142SGerhard Engleder 
62403f69bbSGerhard Engleder struct tsnep_tx_entry {
63403f69bbSGerhard Engleder 	struct tsnep_tx_desc *desc;
64403f69bbSGerhard Engleder 	struct tsnep_tx_desc_wb *desc_wb;
65403f69bbSGerhard Engleder 	dma_addr_t desc_dma;
66403f69bbSGerhard Engleder 	bool owner_user_flag;
67403f69bbSGerhard Engleder 
68403f69bbSGerhard Engleder 	u32 properties;
69403f69bbSGerhard Engleder 
70d24bc0bcSGerhard Engleder 	u32 type;
71d24bc0bcSGerhard Engleder 	union {
72403f69bbSGerhard Engleder 		struct sk_buff *skb;
73d24bc0bcSGerhard Engleder 		struct xdp_frame *xdpf;
74cd275c23SGerhard Engleder 		bool zc;
75d24bc0bcSGerhard Engleder 	};
76403f69bbSGerhard Engleder 	size_t len;
77403f69bbSGerhard Engleder 	DEFINE_DMA_UNMAP_ADDR(dma);
78403f69bbSGerhard Engleder };
79403f69bbSGerhard Engleder 
80403f69bbSGerhard Engleder struct tsnep_tx {
81403f69bbSGerhard Engleder 	struct tsnep_adapter *adapter;
82403f69bbSGerhard Engleder 	void __iomem *addr;
8358eaa8abSGerhard Engleder 	int queue_index;
84403f69bbSGerhard Engleder 
85403f69bbSGerhard Engleder 	void *page[TSNEP_RING_PAGE_COUNT];
86403f69bbSGerhard Engleder 	dma_addr_t page_dma[TSNEP_RING_PAGE_COUNT];
87403f69bbSGerhard Engleder 
88403f69bbSGerhard Engleder 	struct tsnep_tx_entry entry[TSNEP_RING_SIZE];
89403f69bbSGerhard Engleder 	int write;
90403f69bbSGerhard Engleder 	int read;
91403f69bbSGerhard Engleder 	u32 owner_counter;
92403f69bbSGerhard Engleder 	int increment_owner_counter;
93cd275c23SGerhard Engleder 	struct xsk_buff_pool *xsk_pool;
94403f69bbSGerhard Engleder 
95403f69bbSGerhard Engleder 	u32 packets;
96403f69bbSGerhard Engleder 	u32 bytes;
97403f69bbSGerhard Engleder 	u32 dropped;
98403f69bbSGerhard Engleder };
99403f69bbSGerhard Engleder 
100403f69bbSGerhard Engleder struct tsnep_rx_entry {
101403f69bbSGerhard Engleder 	struct tsnep_rx_desc *desc;
102403f69bbSGerhard Engleder 	struct tsnep_rx_desc_wb *desc_wb;
103403f69bbSGerhard Engleder 	dma_addr_t desc_dma;
104403f69bbSGerhard Engleder 
105403f69bbSGerhard Engleder 	u32 properties;
106403f69bbSGerhard Engleder 
1073fc23339SGerhard Engleder 	union {
108bb837a37SGerhard Engleder 		struct page *page;
1093fc23339SGerhard Engleder 		struct xdp_buff *xdp;
1103fc23339SGerhard Engleder 	};
111403f69bbSGerhard Engleder 	size_t len;
112bb837a37SGerhard Engleder 	dma_addr_t dma;
113403f69bbSGerhard Engleder };
114403f69bbSGerhard Engleder 
115403f69bbSGerhard Engleder struct tsnep_rx {
116403f69bbSGerhard Engleder 	struct tsnep_adapter *adapter;
117403f69bbSGerhard Engleder 	void __iomem *addr;
118d113efb1SGerhard Engleder 	int queue_index;
11965b28c81SGerhard Engleder 	int tx_queue_index;
120403f69bbSGerhard Engleder 
121403f69bbSGerhard Engleder 	void *page[TSNEP_RING_PAGE_COUNT];
122403f69bbSGerhard Engleder 	dma_addr_t page_dma[TSNEP_RING_PAGE_COUNT];
123403f69bbSGerhard Engleder 
124403f69bbSGerhard Engleder 	struct tsnep_rx_entry entry[TSNEP_RING_SIZE];
125dbadae92SGerhard Engleder 	int write;
126403f69bbSGerhard Engleder 	int read;
127403f69bbSGerhard Engleder 	u32 owner_counter;
128403f69bbSGerhard Engleder 	int increment_owner_counter;
129bb837a37SGerhard Engleder 	struct page_pool *page_pool;
1303fc23339SGerhard Engleder 	struct page **page_buffer;
1313fc23339SGerhard Engleder 	struct xsk_buff_pool *xsk_pool;
1323fc23339SGerhard Engleder 	struct xdp_buff **xdp_batch;
133403f69bbSGerhard Engleder 
134403f69bbSGerhard Engleder 	u32 packets;
135403f69bbSGerhard Engleder 	u32 bytes;
136403f69bbSGerhard Engleder 	u32 dropped;
137403f69bbSGerhard Engleder 	u32 multicast;
138dbadae92SGerhard Engleder 	u32 alloc_failed;
139e77832abSGerhard Engleder 
140e77832abSGerhard Engleder 	struct xdp_rxq_info xdp_rxq;
1413fc23339SGerhard Engleder 	struct xdp_rxq_info xdp_rxq_zc;
142403f69bbSGerhard Engleder };
143403f69bbSGerhard Engleder 
144403f69bbSGerhard Engleder struct tsnep_queue {
145403f69bbSGerhard Engleder 	struct tsnep_adapter *adapter;
146*00e984cbSGerhard Engleder 	char name[IFNAMSIZ + 16];
147403f69bbSGerhard Engleder 
148403f69bbSGerhard Engleder 	struct tsnep_tx *tx;
149403f69bbSGerhard Engleder 	struct tsnep_rx *rx;
150403f69bbSGerhard Engleder 
151403f69bbSGerhard Engleder 	struct napi_struct napi;
152403f69bbSGerhard Engleder 
15358eaa8abSGerhard Engleder 	int irq;
154403f69bbSGerhard Engleder 	u32 irq_mask;
155d3dfe8d6SGerhard Engleder 	void __iomem *irq_delay_addr;
156d3dfe8d6SGerhard Engleder 	u8 irq_delay;
157403f69bbSGerhard Engleder };
158403f69bbSGerhard Engleder 
159403f69bbSGerhard Engleder struct tsnep_adapter {
160403f69bbSGerhard Engleder 	struct net_device *netdev;
161403f69bbSGerhard Engleder 	u8 mac_address[ETH_ALEN];
162403f69bbSGerhard Engleder 	struct mii_bus *mdiobus;
163403f69bbSGerhard Engleder 	bool suppress_preamble;
164403f69bbSGerhard Engleder 	phy_interface_t phy_mode;
165403f69bbSGerhard Engleder 	struct phy_device *phydev;
166403f69bbSGerhard Engleder 	int msg_enable;
167403f69bbSGerhard Engleder 
168403f69bbSGerhard Engleder 	struct platform_device *pdev;
169403f69bbSGerhard Engleder 	struct device *dmadev;
170403f69bbSGerhard Engleder 	void __iomem *addr;
171403f69bbSGerhard Engleder 
172403f69bbSGerhard Engleder 	bool gate_control;
173403f69bbSGerhard Engleder 	/* gate control lock */
174403f69bbSGerhard Engleder 	struct mutex gate_control_lock;
175403f69bbSGerhard Engleder 	bool gate_control_active;
176403f69bbSGerhard Engleder 	struct tsnep_gcl gcl[2];
177403f69bbSGerhard Engleder 	int next_gcl;
178403f69bbSGerhard Engleder 
179403f69bbSGerhard Engleder 	struct hwtstamp_config hwtstamp_config;
180403f69bbSGerhard Engleder 	struct ptp_clock *ptp_clock;
181403f69bbSGerhard Engleder 	struct ptp_clock_info ptp_clock_info;
182403f69bbSGerhard Engleder 	/* ptp clock lock */
183403f69bbSGerhard Engleder 	spinlock_t ptp_lock;
184403f69bbSGerhard Engleder 
185308ce142SGerhard Engleder 	/* RX flow classification rules lock */
186308ce142SGerhard Engleder 	struct mutex rxnfc_lock;
187308ce142SGerhard Engleder 	struct list_head rxnfc_rules;
188308ce142SGerhard Engleder 	int rxnfc_count;
189308ce142SGerhard Engleder 	int rxnfc_max;
190308ce142SGerhard Engleder 
19165b28c81SGerhard Engleder 	struct bpf_prog *xdp_prog;
19265b28c81SGerhard Engleder 
193403f69bbSGerhard Engleder 	int num_tx_queues;
194403f69bbSGerhard Engleder 	struct tsnep_tx tx[TSNEP_MAX_QUEUES];
195403f69bbSGerhard Engleder 	int num_rx_queues;
196403f69bbSGerhard Engleder 	struct tsnep_rx rx[TSNEP_MAX_QUEUES];
197403f69bbSGerhard Engleder 
198403f69bbSGerhard Engleder 	int num_queues;
199403f69bbSGerhard Engleder 	struct tsnep_queue queue[TSNEP_MAX_QUEUES];
200403f69bbSGerhard Engleder };
201403f69bbSGerhard Engleder 
202403f69bbSGerhard Engleder extern const struct ethtool_ops tsnep_ethtool_ops;
203403f69bbSGerhard Engleder 
204403f69bbSGerhard Engleder int tsnep_ptp_init(struct tsnep_adapter *adapter);
205403f69bbSGerhard Engleder void tsnep_ptp_cleanup(struct tsnep_adapter *adapter);
206403f69bbSGerhard Engleder int tsnep_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
207403f69bbSGerhard Engleder 
208403f69bbSGerhard Engleder int tsnep_tc_init(struct tsnep_adapter *adapter);
209403f69bbSGerhard Engleder void tsnep_tc_cleanup(struct tsnep_adapter *adapter);
210403f69bbSGerhard Engleder int tsnep_tc_setup(struct net_device *netdev, enum tc_setup_type type,
211403f69bbSGerhard Engleder 		   void *type_data);
212403f69bbSGerhard Engleder 
213308ce142SGerhard Engleder int tsnep_rxnfc_init(struct tsnep_adapter *adapter);
214308ce142SGerhard Engleder void tsnep_rxnfc_cleanup(struct tsnep_adapter *adapter);
215308ce142SGerhard Engleder int tsnep_rxnfc_get_rule(struct tsnep_adapter *adapter,
216308ce142SGerhard Engleder 			 struct ethtool_rxnfc *cmd);
217308ce142SGerhard Engleder int tsnep_rxnfc_get_all(struct tsnep_adapter *adapter,
218308ce142SGerhard Engleder 			struct ethtool_rxnfc *cmd,
219308ce142SGerhard Engleder 			u32 *rule_locs);
220308ce142SGerhard Engleder int tsnep_rxnfc_add_rule(struct tsnep_adapter *adapter,
221308ce142SGerhard Engleder 			 struct ethtool_rxnfc *cmd);
222308ce142SGerhard Engleder int tsnep_rxnfc_del_rule(struct tsnep_adapter *adapter,
223308ce142SGerhard Engleder 			 struct ethtool_rxnfc *cmd);
224308ce142SGerhard Engleder 
225f0f6460fSGerhard Engleder int tsnep_xdp_setup_prog(struct tsnep_adapter *adapter, struct bpf_prog *prog,
226f0f6460fSGerhard Engleder 			 struct netlink_ext_ack *extack);
2273fc23339SGerhard Engleder int tsnep_xdp_setup_pool(struct tsnep_adapter *adapter,
2283fc23339SGerhard Engleder 			 struct xsk_buff_pool *pool, u16 queue_id);
229f0f6460fSGerhard Engleder 
230403f69bbSGerhard Engleder #if IS_ENABLED(CONFIG_TSNEP_SELFTESTS)
231403f69bbSGerhard Engleder int tsnep_ethtool_get_test_count(void);
232403f69bbSGerhard Engleder void tsnep_ethtool_get_test_strings(u8 *data);
233403f69bbSGerhard Engleder void tsnep_ethtool_self_test(struct net_device *netdev,
234403f69bbSGerhard Engleder 			     struct ethtool_test *eth_test, u64 *data);
235403f69bbSGerhard Engleder #else
tsnep_ethtool_get_test_count(void)236403f69bbSGerhard Engleder static inline int tsnep_ethtool_get_test_count(void)
237403f69bbSGerhard Engleder {
238403f69bbSGerhard Engleder 	return -EOPNOTSUPP;
239403f69bbSGerhard Engleder }
240403f69bbSGerhard Engleder 
tsnep_ethtool_get_test_strings(u8 * data)241403f69bbSGerhard Engleder static inline void tsnep_ethtool_get_test_strings(u8 *data)
242403f69bbSGerhard Engleder {
243403f69bbSGerhard Engleder 	/* not enabled */
244403f69bbSGerhard Engleder }
245403f69bbSGerhard Engleder 
tsnep_ethtool_self_test(struct net_device * dev,struct ethtool_test * eth_test,u64 * data)246403f69bbSGerhard Engleder static inline void tsnep_ethtool_self_test(struct net_device *dev,
247403f69bbSGerhard Engleder 					   struct ethtool_test *eth_test,
248403f69bbSGerhard Engleder 					   u64 *data)
249403f69bbSGerhard Engleder {
250403f69bbSGerhard Engleder 	/* not enabled */
251403f69bbSGerhard Engleder }
252403f69bbSGerhard Engleder #endif /* CONFIG_TSNEP_SELFTESTS */
253403f69bbSGerhard Engleder 
254403f69bbSGerhard Engleder void tsnep_get_system_time(struct tsnep_adapter *adapter, u64 *time);
255d3dfe8d6SGerhard Engleder int tsnep_set_irq_coalesce(struct tsnep_queue *queue, u32 usecs);
256d3dfe8d6SGerhard Engleder u32 tsnep_get_irq_coalesce(struct tsnep_queue *queue);
2573fc23339SGerhard Engleder int tsnep_enable_xsk(struct tsnep_queue *queue, struct xsk_buff_pool *pool);
2583fc23339SGerhard Engleder void tsnep_disable_xsk(struct tsnep_queue *queue);
259403f69bbSGerhard Engleder 
260403f69bbSGerhard Engleder #endif /* _TSNEP_H */
261