/* * NetCP driver local header * * Copyright (C) 2014 Texas Instruments Incorporated * Authors: Sandeep Nair * Sandeep Paulraj * Cyril Chemparathy * Santosh Shilimkar * Wingman Kwok * Murali Karicheri * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation version 2. * * This program is distributed "as is" WITHOUT ANY WARRANTY of any * kind, whether express or implied; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef __NETCP_H__ #define __NETCP_H__ #include #include #include /* Maximum Ethernet frame size supported by Keystone switch */ #define NETCP_MAX_FRAME_SIZE 9504 /* to indicate netcp core should drop the packet */ #define NETCP_TX_DROP 1 #define SGMII_LINK_MAC_MAC_AUTONEG 0 #define SGMII_LINK_MAC_PHY 1 #define SGMII_LINK_MAC_MAC_FORCED 2 #define SGMII_LINK_MAC_FIBER 3 #define SGMII_LINK_MAC_PHY_NO_MDIO 4 #define RGMII_LINK_MAC_PHY 5 #define RGMII_LINK_MAC_MAC_FORCED 6 #define RGMII_LINK_MAC_PHY_NO_MDIO 7 #define XGMII_LINK_MAC_PHY 10 #define XGMII_LINK_MAC_MAC_FORCED 11 #define NETCP_MAX_SUBQUEUES 32 struct netcp_device; struct netcp_tx_pipe { struct netcp_device *netcp_device; void *dma_queue; unsigned int dma_queue_id; /* To port for packet forwarded to switch. Used only by ethss */ u8 switch_to_port; #define SWITCH_TO_PORT_IN_TAGINFO BIT(0) u8 flags; void *dma_channel; const char *dma_chan_name; }; #define ADDR_NEW BIT(0) #define ADDR_VALID BIT(1) enum netcp_addr_type { ADDR_ANY, ADDR_DEV, ADDR_UCAST, ADDR_MCAST, ADDR_BCAST }; struct netcp_addr { struct netcp_intf *netcp; unsigned char addr[ETH_ALEN]; enum netcp_addr_type type; unsigned int flags; struct list_head node; }; struct netcp_stats { struct u64_stats_sync syncp_rx ____cacheline_aligned_in_smp; u64 rx_packets; u64 rx_bytes; u32 rx_errors; u32 rx_dropped; struct u64_stats_sync syncp_tx ____cacheline_aligned_in_smp; u64 tx_packets; u64 tx_bytes; u32 tx_errors; u32 tx_dropped; }; struct netcp_pool_info { u32 num_descs; u32 region_id; unsigned int pause_threshold; unsigned int resume_threshold; void *pool; }; struct netcp_intf { struct device *dev; struct device *ndev_dev; struct net_device *ndev; bool big_endian; bool bridged; u32 tx_subqueues; unsigned int tx_compl_qid; u32 tx_compl_budget; void *tx_compl_q; struct list_head txhook_list_head; void *rx_queue; void *rx_pool; struct list_head rxhook_list_head; unsigned int rx_queue_id; void *rx_fdq[KNAV_DMA_FDQ_PER_CHAN]; struct napi_struct rx_napi; struct napi_struct tx_napi; #define ETH_SW_CAN_REMOVE_ETH_FCS BIT(0) u32 hw_cap; /* 64-bit netcp stats */ struct netcp_stats stats; u32 rx_queue_depths[KNAV_DMA_FDQ_PER_CHAN]; /* Non Data path related stuffs below. In future, move any variable * if used on data path to above this for better cache line use */ void *rx_channel; const char *dma_chan_name; u32 rx_pool_size; u32 rx_pool_region_id; struct list_head module_head; struct list_head interface_list; struct list_head addr_list; bool netdev_registered; bool primary_module_attached; /* Lock used for protecting Rx/Tx hook list management */ spinlock_t lock; struct netcp_device *netcp_device; struct device_node *node_interface; /* DMA configuration data */ u32 msg_enable; struct netcp_pool_info tx_pool[1]; /* NB: tx-pools (#tx-subqueues) are allocated dynamically */ }; #define NETCP_EPIB_LEN KNAV_DMA_NUM_EPIB_WORDS #define NETCP_PSDATA_LEN KNAV_DMA_NUM_PS_WORDS struct netcp_packet { struct sk_buff *skb; u32 *epib; u32 *psdata; u32 eflags; unsigned int psdata_len; struct netcp_intf *netcp; struct netcp_tx_pipe *tx_pipe; bool rxtstamp_complete; void *ts_context; void (*txtstamp)(void *ctx, struct sk_buff *skb); }; static inline u32 *netcp_push_psdata(struct netcp_packet *p_info, unsigned int bytes) { u32 *buf; unsigned int words; if ((bytes & 0x03) != 0) return NULL; words = bytes >> 2; if ((p_info->psdata_len + words) > NETCP_PSDATA_LEN) return NULL; p_info->psdata_len += words; buf = &p_info->psdata[NETCP_PSDATA_LEN - p_info->psdata_len]; return buf; } static inline int netcp_align_psdata(struct netcp_packet *p_info, unsigned int byte_align) { int padding; switch (byte_align) { case 0: padding = -EINVAL; break; case 1: case 2: case 4: padding = 0; break; case 8: padding = (p_info->psdata_len << 2) % 8; break; case 16: padding = (p_info->psdata_len << 2) % 16; break; default: padding = (p_info->psdata_len << 2) % byte_align; break; } return padding; } struct netcp_module { const char *name; struct module *owner; bool primary; /* probe/remove: called once per NETCP instance */ int (*probe)(struct netcp_device *netcp_device, struct device *device, struct device_node *node, void **inst_priv); int (*remove)(struct netcp_device *netcp_device, void *inst_priv); /* attach/release: called once per network interface */ int (*attach)(void *inst_priv, struct net_device *ndev, struct device_node *node, void **intf_priv); int (*release)(void *intf_priv); int (*open)(void *intf_priv, struct net_device *ndev); int (*close)(void *intf_priv, struct net_device *ndev); int (*add_addr)(void *intf_priv, struct netcp_addr *naddr); int (*del_addr)(void *intf_priv, struct netcp_addr *naddr); int (*add_vid)(void *intf_priv, int vid); int (*del_vid)(void *intf_priv, int vid); int (*ioctl)(void *intf_priv, struct ifreq *req, int cmd); int (*set_rx_mode)(void *intf_priv, bool promisc); /* used internally */ struct list_head module_list; struct list_head interface_list; }; int netcp_register_module(struct netcp_module *module); void netcp_unregister_module(struct netcp_module *module); void *netcp_module_get_intf_data(struct netcp_module *module, struct netcp_intf *intf); int netcp_txpipe_init(struct netcp_tx_pipe *tx_pipe, struct netcp_device *netcp_device, const char *dma_chan_name, unsigned int dma_queue_id); int netcp_txpipe_open(struct netcp_tx_pipe *tx_pipe); int netcp_txpipe_close(struct netcp_tx_pipe *tx_pipe); typedef int netcp_hook_rtn(int order, void *data, struct netcp_packet *packet); int netcp_register_txhook(struct netcp_intf *netcp_priv, int order, netcp_hook_rtn *hook_rtn, void *hook_data); int netcp_unregister_txhook(struct netcp_intf *netcp_priv, int order, netcp_hook_rtn *hook_rtn, void *hook_data); int netcp_register_rxhook(struct netcp_intf *netcp_priv, int order, netcp_hook_rtn *hook_rtn, void *hook_data); int netcp_unregister_rxhook(struct netcp_intf *netcp_priv, int order, netcp_hook_rtn *hook_rtn, void *hook_data); void *netcp_device_find_module(struct netcp_device *netcp_device, const char *name); /* SGMII functions */ int netcp_sgmii_reset(void __iomem *sgmii_ofs, int port); bool netcp_sgmii_rtreset(void __iomem *sgmii_ofs, int port, bool set); int netcp_sgmii_get_port_link(void __iomem *sgmii_ofs, int port); int netcp_sgmii_config(void __iomem *sgmii_ofs, int port, u32 interface); /* XGBE SERDES init functions */ int netcp_xgbe_serdes_init(void __iomem *serdes_regs, void __iomem *xgbe_regs); #endif /* __NETCP_H__ */