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