// SPDX-License-Identifier: GPL-2.0-only /* 10G controller driver for Samsung SoCs * * Copyright (C) 2013 Samsung Electronics Co., Ltd. * http://www.samsung.com * * Author: Siva Reddy Kallam <[email protected]> */ #define pr_fmt(fmt) … #include <linux/clk.h> #include <linux/crc32.h> #include <linux/dma-mapping.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/if.h> #include <linux/if_ether.h> #include <linux/if_vlan.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/ip.h> #include <linux/kernel.h> #include <linux/mii.h> #include <linux/module.h> #include <linux/net_tstamp.h> #include <linux/netdevice.h> #include <linux/phy.h> #include <linux/platform_device.h> #include <linux/prefetch.h> #include <linux/skbuff.h> #include <linux/slab.h> #include <linux/tcp.h> #include <linux/sxgbe_platform.h> #include "sxgbe_common.h" #include "sxgbe_desc.h" #include "sxgbe_dma.h" #include "sxgbe_mtl.h" #include "sxgbe_reg.h" #define SXGBE_ALIGN(x) … #define JUMBO_LEN … /* Module parameters */ #define TX_TIMEO … #define DMA_TX_SIZE … #define DMA_RX_SIZE … #define TC_DEFAULT … #define DMA_BUFFER_SIZE … /* The default timer value as per the sxgbe specification 1 sec(1000 ms) */ #define SXGBE_DEFAULT_LPI_TIMER … static int debug = …; static int eee_timer = …; module_param(eee_timer, int, 0644); module_param(debug, int, 0644); static const u32 default_msg_level = …; static irqreturn_t sxgbe_common_interrupt(int irq, void *dev_id); static irqreturn_t sxgbe_tx_interrupt(int irq, void *dev_id); static irqreturn_t sxgbe_rx_interrupt(int irq, void *dev_id); #define SXGBE_COAL_TIMER(x) … #define SXGBE_LPI_TIMER(x) … /** * sxgbe_verify_args - verify the driver parameters. * Description: it verifies if some wrong parameter is passed to the driver. * Note that wrong parameters are replaced with the default values. */ static void sxgbe_verify_args(void) { … } static void sxgbe_enable_eee_mode(const struct sxgbe_priv_data *priv) { … } void sxgbe_disable_eee_mode(struct sxgbe_priv_data * const priv) { … } /** * sxgbe_eee_ctrl_timer * @t: timer list containing a data * Description: * If there is no data transfer and if we are not in LPI state, * then MAC Transmitter can be moved to LPI state. */ static void sxgbe_eee_ctrl_timer(struct timer_list *t) { … } /** * sxgbe_eee_init * @priv: private device pointer * Description: * If the EEE support has been enabled while configuring the driver, * if the GMAC actually supports the EEE (from the HW cap reg) and the * phy can also manage EEE, so enable the LPI state and start the timer * to verify if the tx path can enter in LPI state. */ bool sxgbe_eee_init(struct sxgbe_priv_data * const priv) { … } static void sxgbe_eee_adjust(const struct sxgbe_priv_data *priv) { … } /** * sxgbe_clk_csr_set - dynamically set the MDC clock * @priv: driver private structure * Description: this is to dynamically set the MDC clock according to the csr * clock input. */ static void sxgbe_clk_csr_set(struct sxgbe_priv_data *priv) { … } /* minimum number of free TX descriptors required to wake up TX process */ #define SXGBE_TX_THRESH(x) … static inline u32 sxgbe_tx_avail(struct sxgbe_tx_queue *queue, int tx_qsize) { … } /** * sxgbe_adjust_link * @dev: net device structure * Description: it adjusts the link parameters. */ static void sxgbe_adjust_link(struct net_device *dev) { … } /** * sxgbe_init_phy - PHY initialization * @ndev: net device structure * Description: it initializes the driver's PHY state, and attaches the PHY * to the mac driver. * Return value: * 0 on success */ static int sxgbe_init_phy(struct net_device *ndev) { … } /** * sxgbe_clear_descriptors: clear descriptors * @priv: driver private structure * Description: this function is called to clear the tx and rx descriptors * in case of both basic and extended descriptors are used. */ static void sxgbe_clear_descriptors(struct sxgbe_priv_data *priv) { … } static int sxgbe_init_rx_buffers(struct net_device *dev, struct sxgbe_rx_norm_desc *p, int i, unsigned int dma_buf_sz, struct sxgbe_rx_queue *rx_ring) { … } /** * sxgbe_free_rx_buffers - free what sxgbe_init_rx_buffers() allocated * @dev: net device structure * @p: dec pointer * @i: index * @dma_buf_sz: size * @rx_ring: ring to be freed * * Description: this function initializes the DMA RX descriptor */ static void sxgbe_free_rx_buffers(struct net_device *dev, struct sxgbe_rx_norm_desc *p, int i, unsigned int dma_buf_sz, struct sxgbe_rx_queue *rx_ring) { … } /** * init_tx_ring - init the TX descriptor ring * @dev: net device structure * @queue_no: queue * @tx_ring: ring to be initialised * @tx_rsize: ring size * Description: this function initializes the DMA TX descriptor */ static int init_tx_ring(struct device *dev, u8 queue_no, struct sxgbe_tx_queue *tx_ring, int tx_rsize) { … } /** * free_rx_ring - free the RX descriptor ring * @dev: net device structure * @rx_ring: ring to be initialised * @rx_rsize: ring size * Description: this function initializes the DMA RX descriptor */ static void free_rx_ring(struct device *dev, struct sxgbe_rx_queue *rx_ring, int rx_rsize) { … } /** * init_rx_ring - init the RX descriptor ring * @dev: net device structure * @queue_no: queue * @rx_ring: ring to be initialised * @rx_rsize: ring size * Description: this function initializes the DMA RX descriptor */ static int init_rx_ring(struct net_device *dev, u8 queue_no, struct sxgbe_rx_queue *rx_ring, int rx_rsize) { … } /** * free_tx_ring - free the TX descriptor ring * @dev: net device structure * @tx_ring: ring to be initialised * @tx_rsize: ring size * Description: this function initializes the DMA TX descriptor */ static void free_tx_ring(struct device *dev, struct sxgbe_tx_queue *tx_ring, int tx_rsize) { … } /** * init_dma_desc_rings - init the RX/TX descriptor rings * @netd: net device structure * Description: this function initializes the DMA RX/TX descriptors * and allocates the socket buffers. It suppors the chained and ring * modes. */ static int init_dma_desc_rings(struct net_device *netd) { … } static void tx_free_ring_skbufs(struct sxgbe_tx_queue *txqueue) { … } static void dma_free_tx_skbufs(struct sxgbe_priv_data *priv) { … } static void free_dma_desc_resources(struct sxgbe_priv_data *priv) { … } static int txring_mem_alloc(struct sxgbe_priv_data *priv) { … } static int rxring_mem_alloc(struct sxgbe_priv_data *priv) { … } /** * sxgbe_mtl_operation_mode - HW MTL operation mode * @priv: driver private structure * Description: it sets the MTL operation mode: tx/rx MTL thresholds * or Store-And-Forward capability. */ static void sxgbe_mtl_operation_mode(struct sxgbe_priv_data *priv) { … } /** * sxgbe_tx_queue_clean: * @tqueue: queue pointer * Description: it reclaims resources after transmission completes. */ static void sxgbe_tx_queue_clean(struct sxgbe_tx_queue *tqueue) { … } /** * sxgbe_tx_all_clean: * @priv: driver private structure * Description: it reclaims resources after transmission completes. */ static void sxgbe_tx_all_clean(struct sxgbe_priv_data * const priv) { … } /** * sxgbe_restart_tx_queue: irq tx error mng function * @priv: driver private structure * @queue_num: queue number * Description: it cleans the descriptors and restarts the transmission * in case of errors. */ static void sxgbe_restart_tx_queue(struct sxgbe_priv_data *priv, int queue_num) { … } /** * sxgbe_reset_all_tx_queues: irq tx error mng function * @priv: driver private structure * Description: it cleans all the descriptors and * restarts the transmission on all queues in case of errors. */ static void sxgbe_reset_all_tx_queues(struct sxgbe_priv_data *priv) { … } /** * sxgbe_get_hw_features: get XMAC capabilities from the HW cap. register. * @priv: driver private structure * Description: * new GMAC chip generations have a new register to indicate the * presence of the optional feature/functions. * This can be also used to override the value passed through the * platform and necessary for old MAC10/100 and GMAC chips. */ static int sxgbe_get_hw_features(struct sxgbe_priv_data * const priv) { … } /** * sxgbe_check_ether_addr: check if the MAC addr is valid * @priv: driver private structure * Description: * it is to verify if the MAC address is valid, in case of failures it * generates a random MAC address */ static void sxgbe_check_ether_addr(struct sxgbe_priv_data *priv) { … } /** * sxgbe_init_dma_engine: DMA init. * @priv: driver private structure * Description: * It inits the DMA invoking the specific SXGBE callback. * Some DMA parameters can be passed from the platform; * in case of these are not passed a default is kept for the MAC or GMAC. */ static int sxgbe_init_dma_engine(struct sxgbe_priv_data *priv) { … } /** * sxgbe_init_mtl_engine: MTL init. * @priv: driver private structure * Description: * It inits the MTL invoking the specific SXGBE callback. */ static void sxgbe_init_mtl_engine(struct sxgbe_priv_data *priv) { … } /** * sxgbe_disable_mtl_engine: MTL disable. * @priv: driver private structure * Description: * It disables the MTL queues by invoking the specific SXGBE callback. */ static void sxgbe_disable_mtl_engine(struct sxgbe_priv_data *priv) { … } /** * sxgbe_tx_timer: mitigation sw timer for tx. * @t: timer pointer * Description: * This is the timer handler to directly invoke the sxgbe_tx_clean. */ static void sxgbe_tx_timer(struct timer_list *t) { … } /** * sxgbe_tx_init_coalesce: init tx mitigation options. * @priv: driver private structure * Description: * This inits the transmit coalesce parameters: i.e. timer rate, * timer handler and default threshold used for enabling the * interrupt on completion bit. */ static void sxgbe_tx_init_coalesce(struct sxgbe_priv_data *priv) { … } static void sxgbe_tx_del_timer(struct sxgbe_priv_data *priv) { … } /** * sxgbe_open - open entry point of the driver * @dev : pointer to the device structure. * Description: * This function is the open entry point of the driver. * Return value: * 0 on success and an appropriate (-)ve integer as defined in errno.h * file on failure. */ static int sxgbe_open(struct net_device *dev) { … } /** * sxgbe_release - close entry point of the driver * @dev : device pointer. * Description: * This is the stop entry point of the driver. */ static int sxgbe_release(struct net_device *dev) { … } /* Prepare first Tx descriptor for doing TSO operation */ static void sxgbe_tso_prepare(struct sxgbe_priv_data *priv, struct sxgbe_tx_norm_desc *first_desc, struct sk_buff *skb) { … } /** * sxgbe_xmit: Tx entry point of the driver * @skb : the socket buffer * @dev : device pointer * Description : this is the tx entry point of the driver. * It programs the chain or the ring and supports oversized frames * and SG feature. */ static netdev_tx_t sxgbe_xmit(struct sk_buff *skb, struct net_device *dev) { … } /** * sxgbe_rx_refill: refill used skb preallocated buffers * @priv: driver private structure * Description : this is to reallocate the skb for the reception process * that is based on zero-copy. */ static void sxgbe_rx_refill(struct sxgbe_priv_data *priv) { … } /** * sxgbe_rx: receive the frames from the remote host * @priv: driver private structure * @limit: napi bugget. * Description : this the function called by the napi poll method. * It gets all the frames inside the ring. */ static int sxgbe_rx(struct sxgbe_priv_data *priv, int limit) { … } /** * sxgbe_poll - sxgbe poll method (NAPI) * @napi : pointer to the napi structure. * @budget : maximum number of packets that the current CPU can receive from * all interfaces. * Description : * To look at the incoming frames and clear the tx resources. */ static int sxgbe_poll(struct napi_struct *napi, int budget) { … } /** * sxgbe_tx_timeout * @dev : Pointer to net device structure * @txqueue: index of the hanging queue * Description: this function is called when a packet transmission fails to * complete within a reasonable time. The driver will mark the error in the * netdev structure and arrange for the device to be reset to a sane state * in order to transmit a new packet. */ static void sxgbe_tx_timeout(struct net_device *dev, unsigned int txqueue) { … } /** * sxgbe_common_interrupt - main ISR * @irq: interrupt number. * @dev_id: to pass the net device pointer. * Description: this is the main driver interrupt service routine. * It calls the DMA ISR and also the core ISR to manage PMT, MMC, LPI * interrupts. */ static irqreturn_t sxgbe_common_interrupt(int irq, void *dev_id) { … } /** * sxgbe_tx_interrupt - TX DMA ISR * @irq: interrupt number. * @dev_id: to pass the net device pointer. * Description: this is the tx dma interrupt service routine. */ static irqreturn_t sxgbe_tx_interrupt(int irq, void *dev_id) { … } /** * sxgbe_rx_interrupt - RX DMA ISR * @irq: interrupt number. * @dev_id: to pass the net device pointer. * Description: this is the rx dma interrupt service routine. */ static irqreturn_t sxgbe_rx_interrupt(int irq, void *dev_id) { … } static inline u64 sxgbe_get_stat64(void __iomem *ioaddr, int reg_lo, int reg_hi) { … } /* sxgbe_get_stats64 - entry point to see statistical information of device * @dev : device pointer. * @stats : pointer to hold all the statistical information of device. * Description: * This function is a driver entry point whenever ifconfig command gets * executed to see device statistics. Statistics are number of * bytes sent or received, errors occurred etc. */ static void sxgbe_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { … } /* sxgbe_set_features - entry point to set offload features of the device. * @dev : device pointer. * @features : features which are required to be set. * Description: * This function is a driver entry point and called by Linux kernel whenever * any device features are set or reset by user. * Return value: * This function returns 0 after setting or resetting device features. */ static int sxgbe_set_features(struct net_device *dev, netdev_features_t features) { … } /* sxgbe_change_mtu - entry point to change MTU size for the device. * @dev : device pointer. * @new_mtu : the new MTU size for the device. * Description: the Maximum Transfer Unit (MTU) is used by the network layer * to drive packet transmission. Ethernet has an MTU of 1500 octets * (ETH_DATA_LEN). This value can be changed with ifconfig. * Return value: * 0 on success and an appropriate (-)ve integer as defined in errno.h * file on failure. */ static int sxgbe_change_mtu(struct net_device *dev, int new_mtu) { … } static void sxgbe_set_umac_addr(void __iomem *ioaddr, unsigned char *addr, unsigned int reg_n) { … } /** * sxgbe_set_rx_mode - entry point for setting different receive mode of * a device. unicast, multicast addressing * @dev : pointer to the device structure * Description: * This function is a driver entry point which gets called by the kernel * whenever different receive mode like unicast, multicast and promiscuous * must be enabled/disabled. * Return value: * void. */ static void sxgbe_set_rx_mode(struct net_device *dev) { … } #ifdef CONFIG_NET_POLL_CONTROLLER /** * sxgbe_poll_controller - entry point for polling receive by device * @dev : pointer to the device structure * Description: * This function is used by NETCONSOLE and other diagnostic tools * to allow network I/O with interrupts disabled. * Return value: * Void. */ static void sxgbe_poll_controller(struct net_device *dev) { … } #endif /* sxgbe_ioctl - Entry point for the Ioctl * @dev: Device pointer. * @rq: An IOCTL specefic structure, that can contain a pointer to * a proprietary structure used to pass information to the driver. * @cmd: IOCTL command * Description: * Currently it supports the phy_mii_ioctl(...) and HW time stamping. */ static int sxgbe_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) { … } static const struct net_device_ops sxgbe_netdev_ops = …; /* Get the hardware ops */ static void sxgbe_get_ops(struct sxgbe_ops * const ops_ptr) { … } /** * sxgbe_hw_init - Init the GMAC device * @priv: driver private structure * Description: this function checks the HW capability * (if supported) and sets the driver's features. */ static int sxgbe_hw_init(struct sxgbe_priv_data * const priv) { … } static int sxgbe_sw_reset(void __iomem *addr) { … } /** * sxgbe_drv_probe * @device: device pointer * @plat_dat: platform data pointer * @addr: iobase memory address * Description: this is the main probe function used to * call the alloc_etherdev, allocate the priv structure. */ struct sxgbe_priv_data *sxgbe_drv_probe(struct device *device, struct sxgbe_plat_data *plat_dat, void __iomem *addr) { … } /** * sxgbe_drv_remove * @ndev: net device pointer * Description: this function resets the TX/RX processes, disables the MAC RX/TX * changes the link status, releases the DMA descriptor rings. */ void sxgbe_drv_remove(struct net_device *ndev) { … } #ifdef CONFIG_PM int sxgbe_suspend(struct net_device *ndev) { … } int sxgbe_resume(struct net_device *ndev) { … } int sxgbe_freeze(struct net_device *ndev) { … } int sxgbe_restore(struct net_device *ndev) { … } #endif /* CONFIG_PM */ /* Driver is configured as Platform driver */ static int __init sxgbe_init(void) { … } static void __exit sxgbe_exit(void) { … } module_init(…) …; module_exit(sxgbe_exit); #ifndef MODULE static int __init sxgbe_cmdline_opt(char *str) { … } __setup(…); #endif /* MODULE */ MODULE_DESCRIPTION(…) …; MODULE_PARM_DESC(…) …; MODULE_PARM_DESC(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …;