162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/* Copyright (C) 2021 Gerhard Engleder <gerhard@engleder-embedded.com> */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#ifndef _TSNEP_H
562306a36Sopenharmony_ci#define _TSNEP_H
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "tsnep_hw.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/platform_device.h>
1062306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1162306a36Sopenharmony_ci#include <linux/etherdevice.h>
1262306a36Sopenharmony_ci#include <linux/phy.h>
1362306a36Sopenharmony_ci#include <linux/ethtool.h>
1462306a36Sopenharmony_ci#include <linux/net_tstamp.h>
1562306a36Sopenharmony_ci#include <linux/ptp_clock_kernel.h>
1662306a36Sopenharmony_ci#include <linux/miscdevice.h>
1762306a36Sopenharmony_ci#include <net/xdp.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define TSNEP "tsnep"
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci#define TSNEP_RING_SIZE 256
2262306a36Sopenharmony_ci#define TSNEP_RING_MASK (TSNEP_RING_SIZE - 1)
2362306a36Sopenharmony_ci#define TSNEP_RING_RX_REFILL 16
2462306a36Sopenharmony_ci#define TSNEP_RING_RX_REUSE (TSNEP_RING_SIZE - TSNEP_RING_SIZE / 4)
2562306a36Sopenharmony_ci#define TSNEP_RING_ENTRIES_PER_PAGE (PAGE_SIZE / TSNEP_DESC_SIZE)
2662306a36Sopenharmony_ci#define TSNEP_RING_PAGE_COUNT (TSNEP_RING_SIZE / TSNEP_RING_ENTRIES_PER_PAGE)
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistruct tsnep_gcl {
2962306a36Sopenharmony_ci	void __iomem *addr;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	u64 base_time;
3262306a36Sopenharmony_ci	u64 cycle_time;
3362306a36Sopenharmony_ci	u64 cycle_time_extension;
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci	struct tsnep_gcl_operation operation[TSNEP_GCL_COUNT];
3662306a36Sopenharmony_ci	int count;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	u64 change_limit;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	u64 start_time;
4162306a36Sopenharmony_ci	bool change;
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cienum tsnep_rxnfc_filter_type {
4562306a36Sopenharmony_ci	TSNEP_RXNFC_ETHER_TYPE,
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistruct tsnep_rxnfc_filter {
4962306a36Sopenharmony_ci	enum tsnep_rxnfc_filter_type type;
5062306a36Sopenharmony_ci	union {
5162306a36Sopenharmony_ci		u16 ether_type;
5262306a36Sopenharmony_ci	};
5362306a36Sopenharmony_ci};
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistruct tsnep_rxnfc_rule {
5662306a36Sopenharmony_ci	struct list_head list;
5762306a36Sopenharmony_ci	struct tsnep_rxnfc_filter filter;
5862306a36Sopenharmony_ci	int queue_index;
5962306a36Sopenharmony_ci	int location;
6062306a36Sopenharmony_ci};
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_cistruct tsnep_tx_entry {
6362306a36Sopenharmony_ci	struct tsnep_tx_desc *desc;
6462306a36Sopenharmony_ci	struct tsnep_tx_desc_wb *desc_wb;
6562306a36Sopenharmony_ci	dma_addr_t desc_dma;
6662306a36Sopenharmony_ci	bool owner_user_flag;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	u32 properties;
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	u32 type;
7162306a36Sopenharmony_ci	union {
7262306a36Sopenharmony_ci		struct sk_buff *skb;
7362306a36Sopenharmony_ci		struct xdp_frame *xdpf;
7462306a36Sopenharmony_ci		bool zc;
7562306a36Sopenharmony_ci	};
7662306a36Sopenharmony_ci	size_t len;
7762306a36Sopenharmony_ci	DEFINE_DMA_UNMAP_ADDR(dma);
7862306a36Sopenharmony_ci};
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistruct tsnep_tx {
8162306a36Sopenharmony_ci	struct tsnep_adapter *adapter;
8262306a36Sopenharmony_ci	void __iomem *addr;
8362306a36Sopenharmony_ci	int queue_index;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	void *page[TSNEP_RING_PAGE_COUNT];
8662306a36Sopenharmony_ci	dma_addr_t page_dma[TSNEP_RING_PAGE_COUNT];
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	struct tsnep_tx_entry entry[TSNEP_RING_SIZE];
8962306a36Sopenharmony_ci	int write;
9062306a36Sopenharmony_ci	int read;
9162306a36Sopenharmony_ci	u32 owner_counter;
9262306a36Sopenharmony_ci	int increment_owner_counter;
9362306a36Sopenharmony_ci	struct xsk_buff_pool *xsk_pool;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	u32 packets;
9662306a36Sopenharmony_ci	u32 bytes;
9762306a36Sopenharmony_ci	u32 dropped;
9862306a36Sopenharmony_ci};
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistruct tsnep_rx_entry {
10162306a36Sopenharmony_ci	struct tsnep_rx_desc *desc;
10262306a36Sopenharmony_ci	struct tsnep_rx_desc_wb *desc_wb;
10362306a36Sopenharmony_ci	dma_addr_t desc_dma;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	u32 properties;
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	union {
10862306a36Sopenharmony_ci		struct page *page;
10962306a36Sopenharmony_ci		struct xdp_buff *xdp;
11062306a36Sopenharmony_ci	};
11162306a36Sopenharmony_ci	size_t len;
11262306a36Sopenharmony_ci	dma_addr_t dma;
11362306a36Sopenharmony_ci};
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistruct tsnep_rx {
11662306a36Sopenharmony_ci	struct tsnep_adapter *adapter;
11762306a36Sopenharmony_ci	void __iomem *addr;
11862306a36Sopenharmony_ci	int queue_index;
11962306a36Sopenharmony_ci	int tx_queue_index;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	void *page[TSNEP_RING_PAGE_COUNT];
12262306a36Sopenharmony_ci	dma_addr_t page_dma[TSNEP_RING_PAGE_COUNT];
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	struct tsnep_rx_entry entry[TSNEP_RING_SIZE];
12562306a36Sopenharmony_ci	int write;
12662306a36Sopenharmony_ci	int read;
12762306a36Sopenharmony_ci	u32 owner_counter;
12862306a36Sopenharmony_ci	int increment_owner_counter;
12962306a36Sopenharmony_ci	struct page_pool *page_pool;
13062306a36Sopenharmony_ci	struct page **page_buffer;
13162306a36Sopenharmony_ci	struct xsk_buff_pool *xsk_pool;
13262306a36Sopenharmony_ci	struct xdp_buff **xdp_batch;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	u32 packets;
13562306a36Sopenharmony_ci	u32 bytes;
13662306a36Sopenharmony_ci	u32 dropped;
13762306a36Sopenharmony_ci	u32 multicast;
13862306a36Sopenharmony_ci	u32 alloc_failed;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	struct xdp_rxq_info xdp_rxq;
14162306a36Sopenharmony_ci	struct xdp_rxq_info xdp_rxq_zc;
14262306a36Sopenharmony_ci};
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistruct tsnep_queue {
14562306a36Sopenharmony_ci	struct tsnep_adapter *adapter;
14662306a36Sopenharmony_ci	char name[IFNAMSIZ + 16];
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	struct tsnep_tx *tx;
14962306a36Sopenharmony_ci	struct tsnep_rx *rx;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	struct napi_struct napi;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	int irq;
15462306a36Sopenharmony_ci	u32 irq_mask;
15562306a36Sopenharmony_ci	void __iomem *irq_delay_addr;
15662306a36Sopenharmony_ci	u8 irq_delay;
15762306a36Sopenharmony_ci};
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cistruct tsnep_adapter {
16062306a36Sopenharmony_ci	struct net_device *netdev;
16162306a36Sopenharmony_ci	u8 mac_address[ETH_ALEN];
16262306a36Sopenharmony_ci	struct mii_bus *mdiobus;
16362306a36Sopenharmony_ci	bool suppress_preamble;
16462306a36Sopenharmony_ci	phy_interface_t phy_mode;
16562306a36Sopenharmony_ci	struct phy_device *phydev;
16662306a36Sopenharmony_ci	int msg_enable;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	struct platform_device *pdev;
16962306a36Sopenharmony_ci	struct device *dmadev;
17062306a36Sopenharmony_ci	void __iomem *addr;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	bool gate_control;
17362306a36Sopenharmony_ci	/* gate control lock */
17462306a36Sopenharmony_ci	struct mutex gate_control_lock;
17562306a36Sopenharmony_ci	bool gate_control_active;
17662306a36Sopenharmony_ci	struct tsnep_gcl gcl[2];
17762306a36Sopenharmony_ci	int next_gcl;
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci	struct hwtstamp_config hwtstamp_config;
18062306a36Sopenharmony_ci	struct ptp_clock *ptp_clock;
18162306a36Sopenharmony_ci	struct ptp_clock_info ptp_clock_info;
18262306a36Sopenharmony_ci	/* ptp clock lock */
18362306a36Sopenharmony_ci	spinlock_t ptp_lock;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	/* RX flow classification rules lock */
18662306a36Sopenharmony_ci	struct mutex rxnfc_lock;
18762306a36Sopenharmony_ci	struct list_head rxnfc_rules;
18862306a36Sopenharmony_ci	int rxnfc_count;
18962306a36Sopenharmony_ci	int rxnfc_max;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	struct bpf_prog *xdp_prog;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	int num_tx_queues;
19462306a36Sopenharmony_ci	struct tsnep_tx tx[TSNEP_MAX_QUEUES];
19562306a36Sopenharmony_ci	int num_rx_queues;
19662306a36Sopenharmony_ci	struct tsnep_rx rx[TSNEP_MAX_QUEUES];
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	int num_queues;
19962306a36Sopenharmony_ci	struct tsnep_queue queue[TSNEP_MAX_QUEUES];
20062306a36Sopenharmony_ci};
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ciextern const struct ethtool_ops tsnep_ethtool_ops;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ciint tsnep_ptp_init(struct tsnep_adapter *adapter);
20562306a36Sopenharmony_civoid tsnep_ptp_cleanup(struct tsnep_adapter *adapter);
20662306a36Sopenharmony_ciint tsnep_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd);
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ciint tsnep_tc_init(struct tsnep_adapter *adapter);
20962306a36Sopenharmony_civoid tsnep_tc_cleanup(struct tsnep_adapter *adapter);
21062306a36Sopenharmony_ciint tsnep_tc_setup(struct net_device *netdev, enum tc_setup_type type,
21162306a36Sopenharmony_ci		   void *type_data);
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ciint tsnep_rxnfc_init(struct tsnep_adapter *adapter);
21462306a36Sopenharmony_civoid tsnep_rxnfc_cleanup(struct tsnep_adapter *adapter);
21562306a36Sopenharmony_ciint tsnep_rxnfc_get_rule(struct tsnep_adapter *adapter,
21662306a36Sopenharmony_ci			 struct ethtool_rxnfc *cmd);
21762306a36Sopenharmony_ciint tsnep_rxnfc_get_all(struct tsnep_adapter *adapter,
21862306a36Sopenharmony_ci			struct ethtool_rxnfc *cmd,
21962306a36Sopenharmony_ci			u32 *rule_locs);
22062306a36Sopenharmony_ciint tsnep_rxnfc_add_rule(struct tsnep_adapter *adapter,
22162306a36Sopenharmony_ci			 struct ethtool_rxnfc *cmd);
22262306a36Sopenharmony_ciint tsnep_rxnfc_del_rule(struct tsnep_adapter *adapter,
22362306a36Sopenharmony_ci			 struct ethtool_rxnfc *cmd);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ciint tsnep_xdp_setup_prog(struct tsnep_adapter *adapter, struct bpf_prog *prog,
22662306a36Sopenharmony_ci			 struct netlink_ext_ack *extack);
22762306a36Sopenharmony_ciint tsnep_xdp_setup_pool(struct tsnep_adapter *adapter,
22862306a36Sopenharmony_ci			 struct xsk_buff_pool *pool, u16 queue_id);
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_TSNEP_SELFTESTS)
23162306a36Sopenharmony_ciint tsnep_ethtool_get_test_count(void);
23262306a36Sopenharmony_civoid tsnep_ethtool_get_test_strings(u8 *data);
23362306a36Sopenharmony_civoid tsnep_ethtool_self_test(struct net_device *netdev,
23462306a36Sopenharmony_ci			     struct ethtool_test *eth_test, u64 *data);
23562306a36Sopenharmony_ci#else
23662306a36Sopenharmony_cistatic inline int tsnep_ethtool_get_test_count(void)
23762306a36Sopenharmony_ci{
23862306a36Sopenharmony_ci	return -EOPNOTSUPP;
23962306a36Sopenharmony_ci}
24062306a36Sopenharmony_ci
24162306a36Sopenharmony_cistatic inline void tsnep_ethtool_get_test_strings(u8 *data)
24262306a36Sopenharmony_ci{
24362306a36Sopenharmony_ci	/* not enabled */
24462306a36Sopenharmony_ci}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_cistatic inline void tsnep_ethtool_self_test(struct net_device *dev,
24762306a36Sopenharmony_ci					   struct ethtool_test *eth_test,
24862306a36Sopenharmony_ci					   u64 *data)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	/* not enabled */
25162306a36Sopenharmony_ci}
25262306a36Sopenharmony_ci#endif /* CONFIG_TSNEP_SELFTESTS */
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_civoid tsnep_get_system_time(struct tsnep_adapter *adapter, u64 *time);
25562306a36Sopenharmony_ciint tsnep_set_irq_coalesce(struct tsnep_queue *queue, u32 usecs);
25662306a36Sopenharmony_ciu32 tsnep_get_irq_coalesce(struct tsnep_queue *queue);
25762306a36Sopenharmony_ciint tsnep_enable_xsk(struct tsnep_queue *queue, struct xsk_buff_pool *pool);
25862306a36Sopenharmony_civoid tsnep_disable_xsk(struct tsnep_queue *queue);
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci#endif /* _TSNEP_H */
261