17ac6653aSJeff Kirsher /******************************************************************************* 27ac6653aSJeff Kirsher This is the driver for the ST MAC 10/100/1000 on-chip Ethernet controllers. 37ac6653aSJeff Kirsher ST Ethernet IPs are built around a Synopsys IP Core. 47ac6653aSJeff Kirsher 5286a8372SGiuseppe CAVALLARO Copyright(C) 2007-2011 STMicroelectronics Ltd 67ac6653aSJeff Kirsher 77ac6653aSJeff Kirsher This program is free software; you can redistribute it and/or modify it 87ac6653aSJeff Kirsher under the terms and conditions of the GNU General Public License, 97ac6653aSJeff Kirsher version 2, as published by the Free Software Foundation. 107ac6653aSJeff Kirsher 117ac6653aSJeff Kirsher This program is distributed in the hope it will be useful, but WITHOUT 127ac6653aSJeff Kirsher ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 137ac6653aSJeff Kirsher FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 147ac6653aSJeff Kirsher more details. 157ac6653aSJeff Kirsher 167ac6653aSJeff Kirsher The full GNU General Public License is included in this distribution in 177ac6653aSJeff Kirsher the file called "COPYING". 187ac6653aSJeff Kirsher 197ac6653aSJeff Kirsher Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 207ac6653aSJeff Kirsher 217ac6653aSJeff Kirsher Documentation available at: 227ac6653aSJeff Kirsher http://www.stlinux.com 237ac6653aSJeff Kirsher Support available at: 247ac6653aSJeff Kirsher https://bugzilla.stlinux.com/ 257ac6653aSJeff Kirsher *******************************************************************************/ 267ac6653aSJeff Kirsher 276a81c26fSViresh Kumar #include <linux/clk.h> 287ac6653aSJeff Kirsher #include <linux/kernel.h> 297ac6653aSJeff Kirsher #include <linux/interrupt.h> 307ac6653aSJeff Kirsher #include <linux/ip.h> 317ac6653aSJeff Kirsher #include <linux/tcp.h> 327ac6653aSJeff Kirsher #include <linux/skbuff.h> 337ac6653aSJeff Kirsher #include <linux/ethtool.h> 347ac6653aSJeff Kirsher #include <linux/if_ether.h> 357ac6653aSJeff Kirsher #include <linux/crc32.h> 367ac6653aSJeff Kirsher #include <linux/mii.h> 3701789349SJiri Pirko #include <linux/if.h> 387ac6653aSJeff Kirsher #include <linux/if_vlan.h> 397ac6653aSJeff Kirsher #include <linux/dma-mapping.h> 407ac6653aSJeff Kirsher #include <linux/slab.h> 417ac6653aSJeff Kirsher #include <linux/prefetch.h> 42db88f10aSSrinivas Kandagatla #include <linux/pinctrl/consumer.h> 4350fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 447ac29055SGiuseppe CAVALLARO #include <linux/debugfs.h> 457ac29055SGiuseppe CAVALLARO #include <linux/seq_file.h> 4650fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */ 47891434b1SRayagond Kokatanur #include <linux/net_tstamp.h> 48891434b1SRayagond Kokatanur #include "stmmac_ptp.h" 49286a8372SGiuseppe CAVALLARO #include "stmmac.h" 50c5e4ddbdSChen-Yu Tsai #include <linux/reset.h> 515790cf3cSMathieu Olivari #include <linux/of_mdio.h> 5219d857c9SPhil Reid #include "dwmac1000.h" 537ac6653aSJeff Kirsher 547ac6653aSJeff Kirsher #define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x) 55f748be53SAlexandre TORGUE #define TSO_MAX_BUFF_SIZE (SZ_16K - 1) 567ac6653aSJeff Kirsher 577ac6653aSJeff Kirsher /* Module parameters */ 5832ceabcaSGiuseppe CAVALLARO #define TX_TIMEO 5000 597ac6653aSJeff Kirsher static int watchdog = TX_TIMEO; 607ac6653aSJeff Kirsher module_param(watchdog, int, S_IRUGO | S_IWUSR); 6132ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(watchdog, "Transmit timeout in milliseconds (default 5s)"); 627ac6653aSJeff Kirsher 6332ceabcaSGiuseppe CAVALLARO static int debug = -1; 647ac6653aSJeff Kirsher module_param(debug, int, S_IRUGO | S_IWUSR); 6532ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)"); 667ac6653aSJeff Kirsher 6747d1f71fSstephen hemminger static int phyaddr = -1; 687ac6653aSJeff Kirsher module_param(phyaddr, int, S_IRUGO); 697ac6653aSJeff Kirsher MODULE_PARM_DESC(phyaddr, "Physical device address"); 707ac6653aSJeff Kirsher 71e3ad57c9SGiuseppe Cavallaro #define STMMAC_TX_THRESH (DMA_TX_SIZE / 4) 72120e87f9SGiuseppe Cavallaro #define STMMAC_RX_THRESH (DMA_RX_SIZE / 4) 737ac6653aSJeff Kirsher 747ac6653aSJeff Kirsher static int flow_ctrl = FLOW_OFF; 757ac6653aSJeff Kirsher module_param(flow_ctrl, int, S_IRUGO | S_IWUSR); 767ac6653aSJeff Kirsher MODULE_PARM_DESC(flow_ctrl, "Flow control ability [on/off]"); 777ac6653aSJeff Kirsher 787ac6653aSJeff Kirsher static int pause = PAUSE_TIME; 797ac6653aSJeff Kirsher module_param(pause, int, S_IRUGO | S_IWUSR); 807ac6653aSJeff Kirsher MODULE_PARM_DESC(pause, "Flow Control Pause Time"); 817ac6653aSJeff Kirsher 827ac6653aSJeff Kirsher #define TC_DEFAULT 64 837ac6653aSJeff Kirsher static int tc = TC_DEFAULT; 847ac6653aSJeff Kirsher module_param(tc, int, S_IRUGO | S_IWUSR); 857ac6653aSJeff Kirsher MODULE_PARM_DESC(tc, "DMA threshold control value"); 867ac6653aSJeff Kirsher 87d916701cSGiuseppe CAVALLARO #define DEFAULT_BUFSIZE 1536 88d916701cSGiuseppe CAVALLARO static int buf_sz = DEFAULT_BUFSIZE; 897ac6653aSJeff Kirsher module_param(buf_sz, int, S_IRUGO | S_IWUSR); 907ac6653aSJeff Kirsher MODULE_PARM_DESC(buf_sz, "DMA buffer size"); 917ac6653aSJeff Kirsher 9222ad3838SGiuseppe Cavallaro #define STMMAC_RX_COPYBREAK 256 9322ad3838SGiuseppe Cavallaro 947ac6653aSJeff Kirsher static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE | 957ac6653aSJeff Kirsher NETIF_MSG_LINK | NETIF_MSG_IFUP | 967ac6653aSJeff Kirsher NETIF_MSG_IFDOWN | NETIF_MSG_TIMER); 977ac6653aSJeff Kirsher 98d765955dSGiuseppe CAVALLARO #define STMMAC_DEFAULT_LPI_TIMER 1000 99d765955dSGiuseppe CAVALLARO static int eee_timer = STMMAC_DEFAULT_LPI_TIMER; 100d765955dSGiuseppe CAVALLARO module_param(eee_timer, int, S_IRUGO | S_IWUSR); 101d765955dSGiuseppe CAVALLARO MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec"); 102f5351ef7SGiuseppe CAVALLARO #define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x)) 103d765955dSGiuseppe CAVALLARO 10422d3efe5SPavel Machek /* By default the driver will use the ring mode to manage tx and rx descriptors, 10522d3efe5SPavel Machek * but allow user to force to use the chain instead of the ring 1064a7d666aSGiuseppe CAVALLARO */ 1074a7d666aSGiuseppe CAVALLARO static unsigned int chain_mode; 1084a7d666aSGiuseppe CAVALLARO module_param(chain_mode, int, S_IRUGO); 1094a7d666aSGiuseppe CAVALLARO MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode"); 1104a7d666aSGiuseppe CAVALLARO 1117ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id); 1127ac6653aSJeff Kirsher 11350fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 114bfab27a1SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev); 115466c5ac8SMathieu Olivari static void stmmac_exit_fs(struct net_device *dev); 116bfab27a1SGiuseppe CAVALLARO #endif 117bfab27a1SGiuseppe CAVALLARO 1189125cdd1SGiuseppe CAVALLARO #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x)) 1199125cdd1SGiuseppe CAVALLARO 1207ac6653aSJeff Kirsher /** 1217ac6653aSJeff Kirsher * stmmac_verify_args - verify the driver parameters. 122732fdf0eSGiuseppe CAVALLARO * Description: it checks the driver parameters and set a default in case of 123732fdf0eSGiuseppe CAVALLARO * errors. 1247ac6653aSJeff Kirsher */ 1257ac6653aSJeff Kirsher static void stmmac_verify_args(void) 1267ac6653aSJeff Kirsher { 1277ac6653aSJeff Kirsher if (unlikely(watchdog < 0)) 1287ac6653aSJeff Kirsher watchdog = TX_TIMEO; 129d916701cSGiuseppe CAVALLARO if (unlikely((buf_sz < DEFAULT_BUFSIZE) || (buf_sz > BUF_SIZE_16KiB))) 130d916701cSGiuseppe CAVALLARO buf_sz = DEFAULT_BUFSIZE; 1317ac6653aSJeff Kirsher if (unlikely(flow_ctrl > 1)) 1327ac6653aSJeff Kirsher flow_ctrl = FLOW_AUTO; 1337ac6653aSJeff Kirsher else if (likely(flow_ctrl < 0)) 1347ac6653aSJeff Kirsher flow_ctrl = FLOW_OFF; 1357ac6653aSJeff Kirsher if (unlikely((pause < 0) || (pause > 0xffff))) 1367ac6653aSJeff Kirsher pause = PAUSE_TIME; 137d765955dSGiuseppe CAVALLARO if (eee_timer < 0) 138d765955dSGiuseppe CAVALLARO eee_timer = STMMAC_DEFAULT_LPI_TIMER; 1397ac6653aSJeff Kirsher } 1407ac6653aSJeff Kirsher 14132ceabcaSGiuseppe CAVALLARO /** 14232ceabcaSGiuseppe CAVALLARO * stmmac_clk_csr_set - dynamically set the MDC clock 14332ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 14432ceabcaSGiuseppe CAVALLARO * Description: this is to dynamically set the MDC clock according to the csr 14532ceabcaSGiuseppe CAVALLARO * clock input. 14632ceabcaSGiuseppe CAVALLARO * Note: 14732ceabcaSGiuseppe CAVALLARO * If a specific clk_csr value is passed from the platform 14832ceabcaSGiuseppe CAVALLARO * this means that the CSR Clock Range selection cannot be 14932ceabcaSGiuseppe CAVALLARO * changed at run-time and it is fixed (as reported in the driver 15032ceabcaSGiuseppe CAVALLARO * documentation). Viceversa the driver will try to set the MDC 15132ceabcaSGiuseppe CAVALLARO * clock dynamically according to the actual clock input. 15232ceabcaSGiuseppe CAVALLARO */ 153cd7201f4SGiuseppe CAVALLARO static void stmmac_clk_csr_set(struct stmmac_priv *priv) 154cd7201f4SGiuseppe CAVALLARO { 155cd7201f4SGiuseppe CAVALLARO u32 clk_rate; 156cd7201f4SGiuseppe CAVALLARO 157f573c0b9Sjpinto clk_rate = clk_get_rate(priv->plat->stmmac_clk); 158cd7201f4SGiuseppe CAVALLARO 159cd7201f4SGiuseppe CAVALLARO /* Platform provided default clk_csr would be assumed valid 160ceb69499SGiuseppe CAVALLARO * for all other cases except for the below mentioned ones. 161ceb69499SGiuseppe CAVALLARO * For values higher than the IEEE 802.3 specified frequency 162ceb69499SGiuseppe CAVALLARO * we can not estimate the proper divider as it is not known 163ceb69499SGiuseppe CAVALLARO * the frequency of clk_csr_i. So we do not change the default 164ceb69499SGiuseppe CAVALLARO * divider. 165ceb69499SGiuseppe CAVALLARO */ 166cd7201f4SGiuseppe CAVALLARO if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) { 167cd7201f4SGiuseppe CAVALLARO if (clk_rate < CSR_F_35M) 168cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_20_35M; 169cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M)) 170cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_35_60M; 171cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M)) 172cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_60_100M; 173cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M)) 174cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_100_150M; 175cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M)) 176cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_150_250M; 17719d857c9SPhil Reid else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M)) 178cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_250_300M; 179ceb69499SGiuseppe CAVALLARO } 180cd7201f4SGiuseppe CAVALLARO } 181cd7201f4SGiuseppe CAVALLARO 1827ac6653aSJeff Kirsher static void print_pkt(unsigned char *buf, int len) 1837ac6653aSJeff Kirsher { 184424c4f78SAndy Shevchenko pr_debug("len = %d byte, buf addr: 0x%p\n", len, buf); 185424c4f78SAndy Shevchenko print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); 1867ac6653aSJeff Kirsher } 1877ac6653aSJeff Kirsher 188ce736788SJoao Pinto static inline u32 stmmac_tx_avail(struct stmmac_priv *priv, u32 queue) 1897ac6653aSJeff Kirsher { 190ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 191a6a3e026SLABBE Corentin u32 avail; 192e3ad57c9SGiuseppe Cavallaro 193ce736788SJoao Pinto if (tx_q->dirty_tx > tx_q->cur_tx) 194ce736788SJoao Pinto avail = tx_q->dirty_tx - tx_q->cur_tx - 1; 195e3ad57c9SGiuseppe Cavallaro else 196ce736788SJoao Pinto avail = DMA_TX_SIZE - tx_q->cur_tx + tx_q->dirty_tx - 1; 197e3ad57c9SGiuseppe Cavallaro 198e3ad57c9SGiuseppe Cavallaro return avail; 199e3ad57c9SGiuseppe Cavallaro } 200e3ad57c9SGiuseppe Cavallaro 20154139cf3SJoao Pinto /** 20254139cf3SJoao Pinto * stmmac_rx_dirty - Get RX queue dirty 20354139cf3SJoao Pinto * @priv: driver private structure 20454139cf3SJoao Pinto * @queue: RX queue index 20554139cf3SJoao Pinto */ 20654139cf3SJoao Pinto static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv, u32 queue) 207e3ad57c9SGiuseppe Cavallaro { 20854139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 209a6a3e026SLABBE Corentin u32 dirty; 210e3ad57c9SGiuseppe Cavallaro 21154139cf3SJoao Pinto if (rx_q->dirty_rx <= rx_q->cur_rx) 21254139cf3SJoao Pinto dirty = rx_q->cur_rx - rx_q->dirty_rx; 213e3ad57c9SGiuseppe Cavallaro else 21454139cf3SJoao Pinto dirty = DMA_RX_SIZE - rx_q->dirty_rx + rx_q->cur_rx; 215e3ad57c9SGiuseppe Cavallaro 216e3ad57c9SGiuseppe Cavallaro return dirty; 2177ac6653aSJeff Kirsher } 2187ac6653aSJeff Kirsher 21932ceabcaSGiuseppe CAVALLARO /** 220732fdf0eSGiuseppe CAVALLARO * stmmac_hw_fix_mac_speed - callback for speed selection 22132ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 2228d45e42bSLABBE Corentin * Description: on some platforms (e.g. ST), some HW system configuration 22332ceabcaSGiuseppe CAVALLARO * registers have to be set according to the link speed negotiated. 2247ac6653aSJeff Kirsher */ 2257ac6653aSJeff Kirsher static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv) 2267ac6653aSJeff Kirsher { 227d6d50c7eSPhilippe Reynes struct net_device *ndev = priv->dev; 228d6d50c7eSPhilippe Reynes struct phy_device *phydev = ndev->phydev; 2297ac6653aSJeff Kirsher 2307ac6653aSJeff Kirsher if (likely(priv->plat->fix_mac_speed)) 231ceb69499SGiuseppe CAVALLARO priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed); 2327ac6653aSJeff Kirsher } 2337ac6653aSJeff Kirsher 23432ceabcaSGiuseppe CAVALLARO /** 235732fdf0eSGiuseppe CAVALLARO * stmmac_enable_eee_mode - check and enter in LPI mode 23632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 237732fdf0eSGiuseppe CAVALLARO * Description: this function is to verify and enter in LPI mode in case of 238732fdf0eSGiuseppe CAVALLARO * EEE. 23932ceabcaSGiuseppe CAVALLARO */ 240d765955dSGiuseppe CAVALLARO static void stmmac_enable_eee_mode(struct stmmac_priv *priv) 241d765955dSGiuseppe CAVALLARO { 242ce736788SJoao Pinto u32 tx_cnt = priv->plat->tx_queues_to_use; 243ce736788SJoao Pinto u32 queue; 244ce736788SJoao Pinto 245ce736788SJoao Pinto /* check if all TX queues have the work finished */ 246ce736788SJoao Pinto for (queue = 0; queue < tx_cnt; queue++) { 247ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 248ce736788SJoao Pinto 249ce736788SJoao Pinto if (tx_q->dirty_tx != tx_q->cur_tx) 250ce736788SJoao Pinto return; /* still unfinished work */ 251ce736788SJoao Pinto } 252ce736788SJoao Pinto 253d765955dSGiuseppe CAVALLARO /* Check and enter in LPI mode */ 254ce736788SJoao Pinto if (!priv->tx_path_in_lpi_mode) 255b4b7b772Sjpinto priv->hw->mac->set_eee_mode(priv->hw, 256b4b7b772Sjpinto priv->plat->en_tx_lpi_clockgating); 257d765955dSGiuseppe CAVALLARO } 258d765955dSGiuseppe CAVALLARO 25932ceabcaSGiuseppe CAVALLARO /** 260732fdf0eSGiuseppe CAVALLARO * stmmac_disable_eee_mode - disable and exit from LPI mode 26132ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 26232ceabcaSGiuseppe CAVALLARO * Description: this function is to exit and disable EEE in case of 26332ceabcaSGiuseppe CAVALLARO * LPI state is true. This is called by the xmit. 26432ceabcaSGiuseppe CAVALLARO */ 265d765955dSGiuseppe CAVALLARO void stmmac_disable_eee_mode(struct stmmac_priv *priv) 266d765955dSGiuseppe CAVALLARO { 2677ed24bbeSVince Bridgers priv->hw->mac->reset_eee_mode(priv->hw); 268d765955dSGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 269d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = false; 270d765955dSGiuseppe CAVALLARO } 271d765955dSGiuseppe CAVALLARO 272d765955dSGiuseppe CAVALLARO /** 273732fdf0eSGiuseppe CAVALLARO * stmmac_eee_ctrl_timer - EEE TX SW timer. 274d765955dSGiuseppe CAVALLARO * @arg : data hook 275d765955dSGiuseppe CAVALLARO * Description: 27632ceabcaSGiuseppe CAVALLARO * if there is no data transfer and if we are not in LPI state, 277d765955dSGiuseppe CAVALLARO * then MAC Transmitter can be moved to LPI state. 278d765955dSGiuseppe CAVALLARO */ 279d765955dSGiuseppe CAVALLARO static void stmmac_eee_ctrl_timer(unsigned long arg) 280d765955dSGiuseppe CAVALLARO { 281d765955dSGiuseppe CAVALLARO struct stmmac_priv *priv = (struct stmmac_priv *)arg; 282d765955dSGiuseppe CAVALLARO 283d765955dSGiuseppe CAVALLARO stmmac_enable_eee_mode(priv); 284f5351ef7SGiuseppe CAVALLARO mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); 285d765955dSGiuseppe CAVALLARO } 286d765955dSGiuseppe CAVALLARO 287d765955dSGiuseppe CAVALLARO /** 288732fdf0eSGiuseppe CAVALLARO * stmmac_eee_init - init EEE 28932ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 290d765955dSGiuseppe CAVALLARO * Description: 291732fdf0eSGiuseppe CAVALLARO * if the GMAC supports the EEE (from the HW cap reg) and the phy device 292732fdf0eSGiuseppe CAVALLARO * can also manage EEE, this function enable the LPI state and start related 293732fdf0eSGiuseppe CAVALLARO * timer. 294d765955dSGiuseppe CAVALLARO */ 295d765955dSGiuseppe CAVALLARO bool stmmac_eee_init(struct stmmac_priv *priv) 296d765955dSGiuseppe CAVALLARO { 297d6d50c7eSPhilippe Reynes struct net_device *ndev = priv->dev; 2984741cf9cSGiuseppe CAVALLARO unsigned long flags; 299d765955dSGiuseppe CAVALLARO bool ret = false; 300d765955dSGiuseppe CAVALLARO 301f5351ef7SGiuseppe CAVALLARO /* Using PCS we cannot dial with the phy registers at this stage 302f5351ef7SGiuseppe CAVALLARO * so we do not support extra feature like EEE. 303f5351ef7SGiuseppe CAVALLARO */ 3043fe5cadbSGiuseppe CAVALLARO if ((priv->hw->pcs == STMMAC_PCS_RGMII) || 3053fe5cadbSGiuseppe CAVALLARO (priv->hw->pcs == STMMAC_PCS_TBI) || 3063fe5cadbSGiuseppe CAVALLARO (priv->hw->pcs == STMMAC_PCS_RTBI)) 307f5351ef7SGiuseppe CAVALLARO goto out; 308f5351ef7SGiuseppe CAVALLARO 309d765955dSGiuseppe CAVALLARO /* MAC core supports the EEE feature. */ 310d765955dSGiuseppe CAVALLARO if (priv->dma_cap.eee) { 31183bf79b6SGiuseppe CAVALLARO int tx_lpi_timer = priv->tx_lpi_timer; 312d765955dSGiuseppe CAVALLARO 31383bf79b6SGiuseppe CAVALLARO /* Check if the PHY supports EEE */ 314d6d50c7eSPhilippe Reynes if (phy_init_eee(ndev->phydev, 1)) { 31583bf79b6SGiuseppe CAVALLARO /* To manage at run-time if the EEE cannot be supported 31683bf79b6SGiuseppe CAVALLARO * anymore (for example because the lp caps have been 31783bf79b6SGiuseppe CAVALLARO * changed). 31883bf79b6SGiuseppe CAVALLARO * In that case the driver disable own timers. 31983bf79b6SGiuseppe CAVALLARO */ 3204741cf9cSGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 32183bf79b6SGiuseppe CAVALLARO if (priv->eee_active) { 32238ddc59dSLABBE Corentin netdev_dbg(priv->dev, "disable EEE\n"); 32383bf79b6SGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 3247ed24bbeSVince Bridgers priv->hw->mac->set_eee_timer(priv->hw, 0, 32583bf79b6SGiuseppe CAVALLARO tx_lpi_timer); 32683bf79b6SGiuseppe CAVALLARO } 32783bf79b6SGiuseppe CAVALLARO priv->eee_active = 0; 3284741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 32983bf79b6SGiuseppe CAVALLARO goto out; 33083bf79b6SGiuseppe CAVALLARO } 33183bf79b6SGiuseppe CAVALLARO /* Activate the EEE and start timers */ 3324741cf9cSGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 333f5351ef7SGiuseppe CAVALLARO if (!priv->eee_active) { 334d765955dSGiuseppe CAVALLARO priv->eee_active = 1; 335ccb36da1SVaishali Thakkar setup_timer(&priv->eee_ctrl_timer, 336ccb36da1SVaishali Thakkar stmmac_eee_ctrl_timer, 337ccb36da1SVaishali Thakkar (unsigned long)priv); 338ccb36da1SVaishali Thakkar mod_timer(&priv->eee_ctrl_timer, 339ccb36da1SVaishali Thakkar STMMAC_LPI_T(eee_timer)); 340d765955dSGiuseppe CAVALLARO 3417ed24bbeSVince Bridgers priv->hw->mac->set_eee_timer(priv->hw, 342f5351ef7SGiuseppe CAVALLARO STMMAC_DEFAULT_LIT_LS, 34383bf79b6SGiuseppe CAVALLARO tx_lpi_timer); 34471965352SGiuseppe CAVALLARO } 345f5351ef7SGiuseppe CAVALLARO /* Set HW EEE according to the speed */ 346d6d50c7eSPhilippe Reynes priv->hw->mac->set_eee_pls(priv->hw, ndev->phydev->link); 347d765955dSGiuseppe CAVALLARO 348d765955dSGiuseppe CAVALLARO ret = true; 3494741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 3504741cf9cSGiuseppe CAVALLARO 35138ddc59dSLABBE Corentin netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n"); 352d765955dSGiuseppe CAVALLARO } 353d765955dSGiuseppe CAVALLARO out: 354d765955dSGiuseppe CAVALLARO return ret; 355d765955dSGiuseppe CAVALLARO } 356d765955dSGiuseppe CAVALLARO 357732fdf0eSGiuseppe CAVALLARO /* stmmac_get_tx_hwtstamp - get HW TX timestamps 35832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 359ba1ffd74SGiuseppe CAVALLARO * @p : descriptor pointer 360891434b1SRayagond Kokatanur * @skb : the socket buffer 361891434b1SRayagond Kokatanur * Description : 362891434b1SRayagond Kokatanur * This function will read timestamp from the descriptor & pass it to stack. 363891434b1SRayagond Kokatanur * and also perform some sanity checks. 364891434b1SRayagond Kokatanur */ 365891434b1SRayagond Kokatanur static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, 366ba1ffd74SGiuseppe CAVALLARO struct dma_desc *p, struct sk_buff *skb) 367891434b1SRayagond Kokatanur { 368891434b1SRayagond Kokatanur struct skb_shared_hwtstamps shhwtstamp; 369891434b1SRayagond Kokatanur u64 ns; 370891434b1SRayagond Kokatanur 371891434b1SRayagond Kokatanur if (!priv->hwts_tx_en) 372891434b1SRayagond Kokatanur return; 373891434b1SRayagond Kokatanur 374ceb69499SGiuseppe CAVALLARO /* exit if skb doesn't support hw tstamp */ 37575e4364fSdamuzi000 if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))) 376891434b1SRayagond Kokatanur return; 377891434b1SRayagond Kokatanur 378891434b1SRayagond Kokatanur /* check tx tstamp status */ 379ba1ffd74SGiuseppe CAVALLARO if (!priv->hw->desc->get_tx_timestamp_status(p)) { 380891434b1SRayagond Kokatanur /* get the valid tstamp */ 381ba1ffd74SGiuseppe CAVALLARO ns = priv->hw->desc->get_timestamp(p, priv->adv_ts); 382891434b1SRayagond Kokatanur 383891434b1SRayagond Kokatanur memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); 384891434b1SRayagond Kokatanur shhwtstamp.hwtstamp = ns_to_ktime(ns); 385ba1ffd74SGiuseppe CAVALLARO 386ba1ffd74SGiuseppe CAVALLARO netdev_info(priv->dev, "get valid TX hw timestamp %llu\n", ns); 387891434b1SRayagond Kokatanur /* pass tstamp to stack */ 388891434b1SRayagond Kokatanur skb_tstamp_tx(skb, &shhwtstamp); 389ba1ffd74SGiuseppe CAVALLARO } 390891434b1SRayagond Kokatanur 391891434b1SRayagond Kokatanur return; 392891434b1SRayagond Kokatanur } 393891434b1SRayagond Kokatanur 394732fdf0eSGiuseppe CAVALLARO /* stmmac_get_rx_hwtstamp - get HW RX timestamps 39532ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 396ba1ffd74SGiuseppe CAVALLARO * @p : descriptor pointer 397ba1ffd74SGiuseppe CAVALLARO * @np : next descriptor pointer 398891434b1SRayagond Kokatanur * @skb : the socket buffer 399891434b1SRayagond Kokatanur * Description : 400891434b1SRayagond Kokatanur * This function will read received packet's timestamp from the descriptor 401891434b1SRayagond Kokatanur * and pass it to stack. It also perform some sanity checks. 402891434b1SRayagond Kokatanur */ 403ba1ffd74SGiuseppe CAVALLARO static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, 404ba1ffd74SGiuseppe CAVALLARO struct dma_desc *np, struct sk_buff *skb) 405891434b1SRayagond Kokatanur { 406891434b1SRayagond Kokatanur struct skb_shared_hwtstamps *shhwtstamp = NULL; 407891434b1SRayagond Kokatanur u64 ns; 408891434b1SRayagond Kokatanur 409891434b1SRayagond Kokatanur if (!priv->hwts_rx_en) 410891434b1SRayagond Kokatanur return; 411891434b1SRayagond Kokatanur 412ba1ffd74SGiuseppe CAVALLARO /* Check if timestamp is available */ 413ba1ffd74SGiuseppe CAVALLARO if (!priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) { 414ba1ffd74SGiuseppe CAVALLARO /* For GMAC4, the valid timestamp is from CTX next desc. */ 415ba1ffd74SGiuseppe CAVALLARO if (priv->plat->has_gmac4) 416ba1ffd74SGiuseppe CAVALLARO ns = priv->hw->desc->get_timestamp(np, priv->adv_ts); 417891434b1SRayagond Kokatanur else 418ba1ffd74SGiuseppe CAVALLARO ns = priv->hw->desc->get_timestamp(p, priv->adv_ts); 419891434b1SRayagond Kokatanur 420ba1ffd74SGiuseppe CAVALLARO netdev_info(priv->dev, "get valid RX hw timestamp %llu\n", ns); 421891434b1SRayagond Kokatanur shhwtstamp = skb_hwtstamps(skb); 422891434b1SRayagond Kokatanur memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); 423891434b1SRayagond Kokatanur shhwtstamp->hwtstamp = ns_to_ktime(ns); 424ba1ffd74SGiuseppe CAVALLARO } else { 425ba1ffd74SGiuseppe CAVALLARO netdev_err(priv->dev, "cannot get RX hw timestamp\n"); 426ba1ffd74SGiuseppe CAVALLARO } 427891434b1SRayagond Kokatanur } 428891434b1SRayagond Kokatanur 429891434b1SRayagond Kokatanur /** 430891434b1SRayagond Kokatanur * stmmac_hwtstamp_ioctl - control hardware timestamping. 431891434b1SRayagond Kokatanur * @dev: device pointer. 4328d45e42bSLABBE Corentin * @ifr: An IOCTL specific structure, that can contain a pointer to 433891434b1SRayagond Kokatanur * a proprietary structure used to pass information to the driver. 434891434b1SRayagond Kokatanur * Description: 435891434b1SRayagond Kokatanur * This function configures the MAC to enable/disable both outgoing(TX) 436891434b1SRayagond Kokatanur * and incoming(RX) packets time stamping based on user input. 437891434b1SRayagond Kokatanur * Return Value: 438891434b1SRayagond Kokatanur * 0 on success and an appropriate -ve integer on failure. 439891434b1SRayagond Kokatanur */ 440891434b1SRayagond Kokatanur static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) 441891434b1SRayagond Kokatanur { 442891434b1SRayagond Kokatanur struct stmmac_priv *priv = netdev_priv(dev); 443891434b1SRayagond Kokatanur struct hwtstamp_config config; 4440a624155SArnd Bergmann struct timespec64 now; 445891434b1SRayagond Kokatanur u64 temp = 0; 446891434b1SRayagond Kokatanur u32 ptp_v2 = 0; 447891434b1SRayagond Kokatanur u32 tstamp_all = 0; 448891434b1SRayagond Kokatanur u32 ptp_over_ipv4_udp = 0; 449891434b1SRayagond Kokatanur u32 ptp_over_ipv6_udp = 0; 450891434b1SRayagond Kokatanur u32 ptp_over_ethernet = 0; 451891434b1SRayagond Kokatanur u32 snap_type_sel = 0; 452891434b1SRayagond Kokatanur u32 ts_master_en = 0; 453891434b1SRayagond Kokatanur u32 ts_event_en = 0; 454891434b1SRayagond Kokatanur u32 value = 0; 45519d857c9SPhil Reid u32 sec_inc; 456891434b1SRayagond Kokatanur 457891434b1SRayagond Kokatanur if (!(priv->dma_cap.time_stamp || priv->adv_ts)) { 458891434b1SRayagond Kokatanur netdev_alert(priv->dev, "No support for HW time stamping\n"); 459891434b1SRayagond Kokatanur priv->hwts_tx_en = 0; 460891434b1SRayagond Kokatanur priv->hwts_rx_en = 0; 461891434b1SRayagond Kokatanur 462891434b1SRayagond Kokatanur return -EOPNOTSUPP; 463891434b1SRayagond Kokatanur } 464891434b1SRayagond Kokatanur 465891434b1SRayagond Kokatanur if (copy_from_user(&config, ifr->ifr_data, 466891434b1SRayagond Kokatanur sizeof(struct hwtstamp_config))) 467891434b1SRayagond Kokatanur return -EFAULT; 468891434b1SRayagond Kokatanur 46938ddc59dSLABBE Corentin netdev_dbg(priv->dev, "%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n", 470891434b1SRayagond Kokatanur __func__, config.flags, config.tx_type, config.rx_filter); 471891434b1SRayagond Kokatanur 472891434b1SRayagond Kokatanur /* reserved for future extensions */ 473891434b1SRayagond Kokatanur if (config.flags) 474891434b1SRayagond Kokatanur return -EINVAL; 475891434b1SRayagond Kokatanur 4765f3da328SBen Hutchings if (config.tx_type != HWTSTAMP_TX_OFF && 4775f3da328SBen Hutchings config.tx_type != HWTSTAMP_TX_ON) 478891434b1SRayagond Kokatanur return -ERANGE; 479891434b1SRayagond Kokatanur 480891434b1SRayagond Kokatanur if (priv->adv_ts) { 481891434b1SRayagond Kokatanur switch (config.rx_filter) { 482891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_NONE: 483ceb69499SGiuseppe CAVALLARO /* time stamp no incoming packet at all */ 484891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_NONE; 485891434b1SRayagond Kokatanur break; 486891434b1SRayagond Kokatanur 487891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 488ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, any kind of event packet */ 489891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 490891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 491891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 492891434b1SRayagond Kokatanur 493891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 494891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 495891434b1SRayagond Kokatanur break; 496891434b1SRayagond Kokatanur 497891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 498ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, Sync packet */ 499891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; 500891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 501891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 502891434b1SRayagond Kokatanur 503891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 504891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 505891434b1SRayagond Kokatanur break; 506891434b1SRayagond Kokatanur 507891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 508ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, Delay_req packet */ 509891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; 510891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 511891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 512891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 513891434b1SRayagond Kokatanur 514891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 515891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 516891434b1SRayagond Kokatanur break; 517891434b1SRayagond Kokatanur 518891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 519ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, any kind of event packet */ 520891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; 521891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 522891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 523891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 524891434b1SRayagond Kokatanur 525891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 526891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 527891434b1SRayagond Kokatanur break; 528891434b1SRayagond Kokatanur 529891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 530ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, Sync packet */ 531891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC; 532891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 533891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 534891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 535891434b1SRayagond Kokatanur 536891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 537891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 538891434b1SRayagond Kokatanur break; 539891434b1SRayagond Kokatanur 540891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 541ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, Delay_req packet */ 542891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ; 543891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 544891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 545891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 546891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 547891434b1SRayagond Kokatanur 548891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 549891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 550891434b1SRayagond Kokatanur break; 551891434b1SRayagond Kokatanur 552891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_EVENT: 553ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1 any layer, any kind of event packet */ 554891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 555891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 556891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 557891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 558891434b1SRayagond Kokatanur 559891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 560891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 561891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 562891434b1SRayagond Kokatanur break; 563891434b1SRayagond Kokatanur 564891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_SYNC: 565ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1, any layer, Sync packet */ 566891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC; 567891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 568891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 569891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 570891434b1SRayagond Kokatanur 571891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 572891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 573891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 574891434b1SRayagond Kokatanur break; 575891434b1SRayagond Kokatanur 576891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 577ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1, any layer, Delay_req packet */ 578891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ; 579891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 580891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 581891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 582891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 583891434b1SRayagond Kokatanur 584891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 585891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 586891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 587891434b1SRayagond Kokatanur break; 588891434b1SRayagond Kokatanur 589891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_ALL: 590ceb69499SGiuseppe CAVALLARO /* time stamp any incoming packet */ 591891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_ALL; 592891434b1SRayagond Kokatanur tstamp_all = PTP_TCR_TSENALL; 593891434b1SRayagond Kokatanur break; 594891434b1SRayagond Kokatanur 595891434b1SRayagond Kokatanur default: 596891434b1SRayagond Kokatanur return -ERANGE; 597891434b1SRayagond Kokatanur } 598891434b1SRayagond Kokatanur } else { 599891434b1SRayagond Kokatanur switch (config.rx_filter) { 600891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_NONE: 601891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_NONE; 602891434b1SRayagond Kokatanur break; 603891434b1SRayagond Kokatanur default: 604891434b1SRayagond Kokatanur /* PTP v1, UDP, any kind of event packet */ 605891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 606891434b1SRayagond Kokatanur break; 607891434b1SRayagond Kokatanur } 608891434b1SRayagond Kokatanur } 609891434b1SRayagond Kokatanur priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1); 6105f3da328SBen Hutchings priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON; 611891434b1SRayagond Kokatanur 612891434b1SRayagond Kokatanur if (!priv->hwts_tx_en && !priv->hwts_rx_en) 613ba1ffd74SGiuseppe CAVALLARO priv->hw->ptp->config_hw_tstamping(priv->ptpaddr, 0); 614891434b1SRayagond Kokatanur else { 615891434b1SRayagond Kokatanur value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR | 616891434b1SRayagond Kokatanur tstamp_all | ptp_v2 | ptp_over_ethernet | 617891434b1SRayagond Kokatanur ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en | 618891434b1SRayagond Kokatanur ts_master_en | snap_type_sel); 619ba1ffd74SGiuseppe CAVALLARO priv->hw->ptp->config_hw_tstamping(priv->ptpaddr, value); 620891434b1SRayagond Kokatanur 621891434b1SRayagond Kokatanur /* program Sub Second Increment reg */ 62219d857c9SPhil Reid sec_inc = priv->hw->ptp->config_sub_second_increment( 623f573c0b9Sjpinto priv->ptpaddr, priv->plat->clk_ptp_rate, 624ba1ffd74SGiuseppe CAVALLARO priv->plat->has_gmac4); 62519d857c9SPhil Reid temp = div_u64(1000000000ULL, sec_inc); 626891434b1SRayagond Kokatanur 627891434b1SRayagond Kokatanur /* calculate default added value: 628891434b1SRayagond Kokatanur * formula is : 629891434b1SRayagond Kokatanur * addend = (2^32)/freq_div_ratio; 63019d857c9SPhil Reid * where, freq_div_ratio = 1e9ns/sec_inc 631891434b1SRayagond Kokatanur */ 63219d857c9SPhil Reid temp = (u64)(temp << 32); 633f573c0b9Sjpinto priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate); 634ba1ffd74SGiuseppe CAVALLARO priv->hw->ptp->config_addend(priv->ptpaddr, 635891434b1SRayagond Kokatanur priv->default_addend); 636891434b1SRayagond Kokatanur 637891434b1SRayagond Kokatanur /* initialize system time */ 6380a624155SArnd Bergmann ktime_get_real_ts64(&now); 6390a624155SArnd Bergmann 6400a624155SArnd Bergmann /* lower 32 bits of tv_sec are safe until y2106 */ 641ba1ffd74SGiuseppe CAVALLARO priv->hw->ptp->init_systime(priv->ptpaddr, (u32)now.tv_sec, 642891434b1SRayagond Kokatanur now.tv_nsec); 643891434b1SRayagond Kokatanur } 644891434b1SRayagond Kokatanur 645891434b1SRayagond Kokatanur return copy_to_user(ifr->ifr_data, &config, 646891434b1SRayagond Kokatanur sizeof(struct hwtstamp_config)) ? -EFAULT : 0; 647891434b1SRayagond Kokatanur } 648891434b1SRayagond Kokatanur 64932ceabcaSGiuseppe CAVALLARO /** 650732fdf0eSGiuseppe CAVALLARO * stmmac_init_ptp - init PTP 65132ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 652732fdf0eSGiuseppe CAVALLARO * Description: this is to verify if the HW supports the PTPv1 or PTPv2. 65332ceabcaSGiuseppe CAVALLARO * This is done by looking at the HW cap. register. 654732fdf0eSGiuseppe CAVALLARO * This function also registers the ptp driver. 65532ceabcaSGiuseppe CAVALLARO */ 65692ba6888SRayagond Kokatanur static int stmmac_init_ptp(struct stmmac_priv *priv) 657891434b1SRayagond Kokatanur { 65892ba6888SRayagond Kokatanur if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) 65992ba6888SRayagond Kokatanur return -EOPNOTSUPP; 66092ba6888SRayagond Kokatanur 661891434b1SRayagond Kokatanur priv->adv_ts = 0; 662be9b3174SGiuseppe CAVALLARO /* Check if adv_ts can be enabled for dwmac 4.x core */ 663be9b3174SGiuseppe CAVALLARO if (priv->plat->has_gmac4 && priv->dma_cap.atime_stamp) 664be9b3174SGiuseppe CAVALLARO priv->adv_ts = 1; 665be9b3174SGiuseppe CAVALLARO /* Dwmac 3.x core with extend_desc can support adv_ts */ 666be9b3174SGiuseppe CAVALLARO else if (priv->extend_desc && priv->dma_cap.atime_stamp) 667891434b1SRayagond Kokatanur priv->adv_ts = 1; 6687cd01399SVince Bridgers 669be9b3174SGiuseppe CAVALLARO if (priv->dma_cap.time_stamp) 670be9b3174SGiuseppe CAVALLARO netdev_info(priv->dev, "IEEE 1588-2002 Timestamp supported\n"); 6717cd01399SVince Bridgers 672be9b3174SGiuseppe CAVALLARO if (priv->adv_ts) 673be9b3174SGiuseppe CAVALLARO netdev_info(priv->dev, 674be9b3174SGiuseppe CAVALLARO "IEEE 1588-2008 Advanced Timestamp supported\n"); 675891434b1SRayagond Kokatanur 676891434b1SRayagond Kokatanur priv->hw->ptp = &stmmac_ptp; 677891434b1SRayagond Kokatanur priv->hwts_tx_en = 0; 678891434b1SRayagond Kokatanur priv->hwts_rx_en = 0; 67992ba6888SRayagond Kokatanur 680c30a70d3SGiuseppe CAVALLARO stmmac_ptp_register(priv); 681c30a70d3SGiuseppe CAVALLARO 682c30a70d3SGiuseppe CAVALLARO return 0; 68392ba6888SRayagond Kokatanur } 68492ba6888SRayagond Kokatanur 68592ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv) 68692ba6888SRayagond Kokatanur { 687f573c0b9Sjpinto if (priv->plat->clk_ptp_ref) 688f573c0b9Sjpinto clk_disable_unprepare(priv->plat->clk_ptp_ref); 68992ba6888SRayagond Kokatanur stmmac_ptp_unregister(priv); 690891434b1SRayagond Kokatanur } 691891434b1SRayagond Kokatanur 6927ac6653aSJeff Kirsher /** 69329feff39SJoao Pinto * stmmac_mac_flow_ctrl - Configure flow control in all queues 69429feff39SJoao Pinto * @priv: driver private structure 69529feff39SJoao Pinto * Description: It is used for configuring the flow control in all queues 69629feff39SJoao Pinto */ 69729feff39SJoao Pinto static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex) 69829feff39SJoao Pinto { 69929feff39SJoao Pinto u32 tx_cnt = priv->plat->tx_queues_to_use; 70029feff39SJoao Pinto 70129feff39SJoao Pinto priv->hw->mac->flow_ctrl(priv->hw, duplex, priv->flow_ctrl, 70229feff39SJoao Pinto priv->pause, tx_cnt); 70329feff39SJoao Pinto } 70429feff39SJoao Pinto 70529feff39SJoao Pinto /** 706732fdf0eSGiuseppe CAVALLARO * stmmac_adjust_link - adjusts the link parameters 7077ac6653aSJeff Kirsher * @dev: net device structure 708732fdf0eSGiuseppe CAVALLARO * Description: this is the helper called by the physical abstraction layer 709732fdf0eSGiuseppe CAVALLARO * drivers to communicate the phy link status. According the speed and duplex 710732fdf0eSGiuseppe CAVALLARO * this driver can invoke registered glue-logic as well. 711732fdf0eSGiuseppe CAVALLARO * It also invoke the eee initialization because it could happen when switch 712732fdf0eSGiuseppe CAVALLARO * on different networks (that are eee capable). 7137ac6653aSJeff Kirsher */ 7147ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev) 7157ac6653aSJeff Kirsher { 7167ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 717d6d50c7eSPhilippe Reynes struct phy_device *phydev = dev->phydev; 7187ac6653aSJeff Kirsher unsigned long flags; 7197ac6653aSJeff Kirsher int new_state = 0; 7207ac6653aSJeff Kirsher 721662ec2b7SLABBE Corentin if (!phydev) 7227ac6653aSJeff Kirsher return; 7237ac6653aSJeff Kirsher 7247ac6653aSJeff Kirsher spin_lock_irqsave(&priv->lock, flags); 725d765955dSGiuseppe CAVALLARO 7267ac6653aSJeff Kirsher if (phydev->link) { 7277ac6653aSJeff Kirsher u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG); 7287ac6653aSJeff Kirsher 7297ac6653aSJeff Kirsher /* Now we make sure that we can be in full duplex mode. 7307ac6653aSJeff Kirsher * If not, we operate in half-duplex mode. */ 7317ac6653aSJeff Kirsher if (phydev->duplex != priv->oldduplex) { 7327ac6653aSJeff Kirsher new_state = 1; 7337ac6653aSJeff Kirsher if (!(phydev->duplex)) 7347ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.duplex; 7357ac6653aSJeff Kirsher else 7367ac6653aSJeff Kirsher ctrl |= priv->hw->link.duplex; 7377ac6653aSJeff Kirsher priv->oldduplex = phydev->duplex; 7387ac6653aSJeff Kirsher } 7397ac6653aSJeff Kirsher /* Flow Control operation */ 7407ac6653aSJeff Kirsher if (phydev->pause) 74129feff39SJoao Pinto stmmac_mac_flow_ctrl(priv, phydev->duplex); 7427ac6653aSJeff Kirsher 7437ac6653aSJeff Kirsher if (phydev->speed != priv->speed) { 7447ac6653aSJeff Kirsher new_state = 1; 7457ac6653aSJeff Kirsher switch (phydev->speed) { 7467ac6653aSJeff Kirsher case 1000: 7473e12790eSLABBE Corentin if (priv->plat->has_gmac || 7483e12790eSLABBE Corentin priv->plat->has_gmac4) 7497ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.port; 7507ac6653aSJeff Kirsher break; 7517ac6653aSJeff Kirsher case 100: 7529beae261SLABBE Corentin if (priv->plat->has_gmac || 7539beae261SLABBE Corentin priv->plat->has_gmac4) { 7549beae261SLABBE Corentin ctrl |= priv->hw->link.port; 7559beae261SLABBE Corentin ctrl |= priv->hw->link.speed; 7569beae261SLABBE Corentin } else { 7579beae261SLABBE Corentin ctrl &= ~priv->hw->link.port; 7589beae261SLABBE Corentin } 7599beae261SLABBE Corentin break; 7607ac6653aSJeff Kirsher case 10: 7613e12790eSLABBE Corentin if (priv->plat->has_gmac || 7623e12790eSLABBE Corentin priv->plat->has_gmac4) { 7637ac6653aSJeff Kirsher ctrl |= priv->hw->link.port; 7647ac6653aSJeff Kirsher ctrl &= ~(priv->hw->link.speed); 7657ac6653aSJeff Kirsher } else { 7667ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.port; 7677ac6653aSJeff Kirsher } 7687ac6653aSJeff Kirsher break; 7697ac6653aSJeff Kirsher default: 770b3e51069SLABBE Corentin netif_warn(priv, link, priv->dev, 771cba920afSLABBE Corentin "broken speed: %d\n", phydev->speed); 772688495b1SLABBE Corentin phydev->speed = SPEED_UNKNOWN; 7737ac6653aSJeff Kirsher break; 7747ac6653aSJeff Kirsher } 7755db13556SLABBE Corentin if (phydev->speed != SPEED_UNKNOWN) 7765db13556SLABBE Corentin stmmac_hw_fix_mac_speed(priv); 7777ac6653aSJeff Kirsher priv->speed = phydev->speed; 7787ac6653aSJeff Kirsher } 7797ac6653aSJeff Kirsher 7807ac6653aSJeff Kirsher writel(ctrl, priv->ioaddr + MAC_CTRL_REG); 7817ac6653aSJeff Kirsher 7827ac6653aSJeff Kirsher if (!priv->oldlink) { 7837ac6653aSJeff Kirsher new_state = 1; 7847ac6653aSJeff Kirsher priv->oldlink = 1; 7857ac6653aSJeff Kirsher } 7867ac6653aSJeff Kirsher } else if (priv->oldlink) { 7877ac6653aSJeff Kirsher new_state = 1; 7887ac6653aSJeff Kirsher priv->oldlink = 0; 789bd00632cSLABBE Corentin priv->speed = SPEED_UNKNOWN; 790bd00632cSLABBE Corentin priv->oldduplex = DUPLEX_UNKNOWN; 7917ac6653aSJeff Kirsher } 7927ac6653aSJeff Kirsher 7937ac6653aSJeff Kirsher if (new_state && netif_msg_link(priv)) 7947ac6653aSJeff Kirsher phy_print_status(phydev); 7957ac6653aSJeff Kirsher 7964741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 7974741cf9cSGiuseppe CAVALLARO 79852f95bbfSGiuseppe CAVALLARO if (phydev->is_pseudo_fixed_link) 79952f95bbfSGiuseppe CAVALLARO /* Stop PHY layer to call the hook to adjust the link in case 80052f95bbfSGiuseppe CAVALLARO * of a switch is attached to the stmmac driver. 80152f95bbfSGiuseppe CAVALLARO */ 80252f95bbfSGiuseppe CAVALLARO phydev->irq = PHY_IGNORE_INTERRUPT; 80352f95bbfSGiuseppe CAVALLARO else 80452f95bbfSGiuseppe CAVALLARO /* At this stage, init the EEE if supported. 80552f95bbfSGiuseppe CAVALLARO * Never called in case of fixed_link. 806f5351ef7SGiuseppe CAVALLARO */ 807f5351ef7SGiuseppe CAVALLARO priv->eee_enabled = stmmac_eee_init(priv); 8087ac6653aSJeff Kirsher } 8097ac6653aSJeff Kirsher 81032ceabcaSGiuseppe CAVALLARO /** 811732fdf0eSGiuseppe CAVALLARO * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported 81232ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 81332ceabcaSGiuseppe CAVALLARO * Description: this is to verify if the HW supports the PCS. 81432ceabcaSGiuseppe CAVALLARO * Physical Coding Sublayer (PCS) interface that can be used when the MAC is 81532ceabcaSGiuseppe CAVALLARO * configured for the TBI, RTBI, or SGMII PHY interface. 81632ceabcaSGiuseppe CAVALLARO */ 817e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv) 818e58bb43fSGiuseppe CAVALLARO { 819e58bb43fSGiuseppe CAVALLARO int interface = priv->plat->interface; 820e58bb43fSGiuseppe CAVALLARO 821e58bb43fSGiuseppe CAVALLARO if (priv->dma_cap.pcs) { 8220d909dcdSByungho An if ((interface == PHY_INTERFACE_MODE_RGMII) || 8230d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_ID) || 8240d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_RXID) || 8250d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 82638ddc59dSLABBE Corentin netdev_dbg(priv->dev, "PCS RGMII support enabled\n"); 8273fe5cadbSGiuseppe CAVALLARO priv->hw->pcs = STMMAC_PCS_RGMII; 8280d909dcdSByungho An } else if (interface == PHY_INTERFACE_MODE_SGMII) { 82938ddc59dSLABBE Corentin netdev_dbg(priv->dev, "PCS SGMII support enabled\n"); 8303fe5cadbSGiuseppe CAVALLARO priv->hw->pcs = STMMAC_PCS_SGMII; 831e58bb43fSGiuseppe CAVALLARO } 832e58bb43fSGiuseppe CAVALLARO } 833e58bb43fSGiuseppe CAVALLARO } 834e58bb43fSGiuseppe CAVALLARO 8357ac6653aSJeff Kirsher /** 8367ac6653aSJeff Kirsher * stmmac_init_phy - PHY initialization 8377ac6653aSJeff Kirsher * @dev: net device structure 8387ac6653aSJeff Kirsher * Description: it initializes the driver's PHY state, and attaches the PHY 8397ac6653aSJeff Kirsher * to the mac driver. 8407ac6653aSJeff Kirsher * Return value: 8417ac6653aSJeff Kirsher * 0 on success 8427ac6653aSJeff Kirsher */ 8437ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev) 8447ac6653aSJeff Kirsher { 8457ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 8467ac6653aSJeff Kirsher struct phy_device *phydev; 847d765955dSGiuseppe CAVALLARO char phy_id_fmt[MII_BUS_ID_SIZE + 3]; 8487ac6653aSJeff Kirsher char bus_id[MII_BUS_ID_SIZE]; 84979ee1dc3SSrinivas Kandagatla int interface = priv->plat->interface; 8509cbadf09SSrinivas Kandagatla int max_speed = priv->plat->max_speed; 8517ac6653aSJeff Kirsher priv->oldlink = 0; 852bd00632cSLABBE Corentin priv->speed = SPEED_UNKNOWN; 853bd00632cSLABBE Corentin priv->oldduplex = DUPLEX_UNKNOWN; 8547ac6653aSJeff Kirsher 8555790cf3cSMathieu Olivari if (priv->plat->phy_node) { 8565790cf3cSMathieu Olivari phydev = of_phy_connect(dev, priv->plat->phy_node, 8575790cf3cSMathieu Olivari &stmmac_adjust_link, 0, interface); 8585790cf3cSMathieu Olivari } else { 859f142af2eSSrinivas Kandagatla snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", 860f142af2eSSrinivas Kandagatla priv->plat->bus_id); 861f142af2eSSrinivas Kandagatla 862d765955dSGiuseppe CAVALLARO snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, 8637ac6653aSJeff Kirsher priv->plat->phy_addr); 864de9a2165SLABBE Corentin netdev_dbg(priv->dev, "%s: trying to attach to %s\n", __func__, 8655790cf3cSMathieu Olivari phy_id_fmt); 8667ac6653aSJeff Kirsher 8675790cf3cSMathieu Olivari phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, 8685790cf3cSMathieu Olivari interface); 8695790cf3cSMathieu Olivari } 8707ac6653aSJeff Kirsher 871dfc50fcaSAlexey Brodkin if (IS_ERR_OR_NULL(phydev)) { 87238ddc59dSLABBE Corentin netdev_err(priv->dev, "Could not attach to PHY\n"); 873dfc50fcaSAlexey Brodkin if (!phydev) 874dfc50fcaSAlexey Brodkin return -ENODEV; 875dfc50fcaSAlexey Brodkin 8767ac6653aSJeff Kirsher return PTR_ERR(phydev); 8777ac6653aSJeff Kirsher } 8787ac6653aSJeff Kirsher 87979ee1dc3SSrinivas Kandagatla /* Stop Advertising 1000BASE Capability if interface is not GMII */ 880c5b9b4e4SSrinivas Kandagatla if ((interface == PHY_INTERFACE_MODE_MII) || 8819cbadf09SSrinivas Kandagatla (interface == PHY_INTERFACE_MODE_RMII) || 8829cbadf09SSrinivas Kandagatla (max_speed < 1000 && max_speed > 0)) 883c5b9b4e4SSrinivas Kandagatla phydev->advertising &= ~(SUPPORTED_1000baseT_Half | 884c5b9b4e4SSrinivas Kandagatla SUPPORTED_1000baseT_Full); 88579ee1dc3SSrinivas Kandagatla 8867ac6653aSJeff Kirsher /* 8877ac6653aSJeff Kirsher * Broken HW is sometimes missing the pull-up resistor on the 8887ac6653aSJeff Kirsher * MDIO line, which results in reads to non-existent devices returning 8897ac6653aSJeff Kirsher * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent 8907ac6653aSJeff Kirsher * device as well. 8917ac6653aSJeff Kirsher * Note: phydev->phy_id is the result of reading the UID PHY registers. 8927ac6653aSJeff Kirsher */ 89327732381SMathieu Olivari if (!priv->plat->phy_node && phydev->phy_id == 0) { 8947ac6653aSJeff Kirsher phy_disconnect(phydev); 8957ac6653aSJeff Kirsher return -ENODEV; 8967ac6653aSJeff Kirsher } 8978e99fc5fSGiuseppe Cavallaro 898c51e424dSFlorian Fainelli /* stmmac_adjust_link will change this to PHY_IGNORE_INTERRUPT to avoid 899c51e424dSFlorian Fainelli * subsequent PHY polling, make sure we force a link transition if 900c51e424dSFlorian Fainelli * we have a UP/DOWN/UP transition 901c51e424dSFlorian Fainelli */ 902c51e424dSFlorian Fainelli if (phydev->is_pseudo_fixed_link) 903c51e424dSFlorian Fainelli phydev->irq = PHY_POLL; 904c51e424dSFlorian Fainelli 905b05c76a1SLABBE Corentin phy_attached_info(phydev); 9067ac6653aSJeff Kirsher return 0; 9077ac6653aSJeff Kirsher } 9087ac6653aSJeff Kirsher 90971fedb01SJoao Pinto static void stmmac_display_rx_rings(struct stmmac_priv *priv) 910c24602efSGiuseppe CAVALLARO { 91154139cf3SJoao Pinto u32 rx_cnt = priv->plat->rx_queues_to_use; 91271fedb01SJoao Pinto void *head_rx; 91354139cf3SJoao Pinto u32 queue; 91454139cf3SJoao Pinto 91554139cf3SJoao Pinto /* Display RX rings */ 91654139cf3SJoao Pinto for (queue = 0; queue < rx_cnt; queue++) { 91754139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 91854139cf3SJoao Pinto 91954139cf3SJoao Pinto pr_info("\tRX Queue %u rings\n", queue); 920d0225e7dSAlexandre TORGUE 92171fedb01SJoao Pinto if (priv->extend_desc) 92254139cf3SJoao Pinto head_rx = (void *)rx_q->dma_erx; 92371fedb01SJoao Pinto else 92454139cf3SJoao Pinto head_rx = (void *)rx_q->dma_rx; 92571fedb01SJoao Pinto 92671fedb01SJoao Pinto /* Display RX ring */ 92771fedb01SJoao Pinto priv->hw->desc->display_ring(head_rx, DMA_RX_SIZE, true); 9285bacd778SLABBE Corentin } 92954139cf3SJoao Pinto } 930d0225e7dSAlexandre TORGUE 93171fedb01SJoao Pinto static void stmmac_display_tx_rings(struct stmmac_priv *priv) 93271fedb01SJoao Pinto { 933ce736788SJoao Pinto u32 tx_cnt = priv->plat->tx_queues_to_use; 93471fedb01SJoao Pinto void *head_tx; 935ce736788SJoao Pinto u32 queue; 936ce736788SJoao Pinto 937ce736788SJoao Pinto /* Display TX rings */ 938ce736788SJoao Pinto for (queue = 0; queue < tx_cnt; queue++) { 939ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 940ce736788SJoao Pinto 941ce736788SJoao Pinto pr_info("\tTX Queue %d rings\n", queue); 94271fedb01SJoao Pinto 94371fedb01SJoao Pinto if (priv->extend_desc) 944ce736788SJoao Pinto head_tx = (void *)tx_q->dma_etx; 94571fedb01SJoao Pinto else 946ce736788SJoao Pinto head_tx = (void *)tx_q->dma_tx; 94771fedb01SJoao Pinto 948d0225e7dSAlexandre TORGUE priv->hw->desc->display_ring(head_tx, DMA_TX_SIZE, false); 949c24602efSGiuseppe CAVALLARO } 950ce736788SJoao Pinto } 951c24602efSGiuseppe CAVALLARO 95271fedb01SJoao Pinto static void stmmac_display_rings(struct stmmac_priv *priv) 95371fedb01SJoao Pinto { 95471fedb01SJoao Pinto /* Display RX ring */ 95571fedb01SJoao Pinto stmmac_display_rx_rings(priv); 95671fedb01SJoao Pinto 95771fedb01SJoao Pinto /* Display TX ring */ 95871fedb01SJoao Pinto stmmac_display_tx_rings(priv); 95971fedb01SJoao Pinto } 96071fedb01SJoao Pinto 961286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize) 962286a8372SGiuseppe CAVALLARO { 963286a8372SGiuseppe CAVALLARO int ret = bufsize; 964286a8372SGiuseppe CAVALLARO 965286a8372SGiuseppe CAVALLARO if (mtu >= BUF_SIZE_4KiB) 966286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_8KiB; 967286a8372SGiuseppe CAVALLARO else if (mtu >= BUF_SIZE_2KiB) 968286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_4KiB; 969d916701cSGiuseppe CAVALLARO else if (mtu > DEFAULT_BUFSIZE) 970286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_2KiB; 971286a8372SGiuseppe CAVALLARO else 972d916701cSGiuseppe CAVALLARO ret = DEFAULT_BUFSIZE; 973286a8372SGiuseppe CAVALLARO 974286a8372SGiuseppe CAVALLARO return ret; 975286a8372SGiuseppe CAVALLARO } 976286a8372SGiuseppe CAVALLARO 97732ceabcaSGiuseppe CAVALLARO /** 97871fedb01SJoao Pinto * stmmac_clear_rx_descriptors - clear RX descriptors 97932ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 98054139cf3SJoao Pinto * @queue: RX queue index 98171fedb01SJoao Pinto * Description: this function is called to clear the RX descriptors 98232ceabcaSGiuseppe CAVALLARO * in case of both basic and extended descriptors are used. 98332ceabcaSGiuseppe CAVALLARO */ 98454139cf3SJoao Pinto static void stmmac_clear_rx_descriptors(struct stmmac_priv *priv, u32 queue) 985c24602efSGiuseppe CAVALLARO { 98654139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 9875bacd778SLABBE Corentin int i; 988c24602efSGiuseppe CAVALLARO 98971fedb01SJoao Pinto /* Clear the RX descriptors */ 9905bacd778SLABBE Corentin for (i = 0; i < DMA_RX_SIZE; i++) 9915bacd778SLABBE Corentin if (priv->extend_desc) 99254139cf3SJoao Pinto priv->hw->desc->init_rx_desc(&rx_q->dma_erx[i].basic, 9935bacd778SLABBE Corentin priv->use_riwt, priv->mode, 9945bacd778SLABBE Corentin (i == DMA_RX_SIZE - 1)); 9955bacd778SLABBE Corentin else 99654139cf3SJoao Pinto priv->hw->desc->init_rx_desc(&rx_q->dma_rx[i], 9975bacd778SLABBE Corentin priv->use_riwt, priv->mode, 9985bacd778SLABBE Corentin (i == DMA_RX_SIZE - 1)); 99971fedb01SJoao Pinto } 100071fedb01SJoao Pinto 100171fedb01SJoao Pinto /** 100271fedb01SJoao Pinto * stmmac_clear_tx_descriptors - clear tx descriptors 100371fedb01SJoao Pinto * @priv: driver private structure 1004ce736788SJoao Pinto * @queue: TX queue index. 100571fedb01SJoao Pinto * Description: this function is called to clear the TX descriptors 100671fedb01SJoao Pinto * in case of both basic and extended descriptors are used. 100771fedb01SJoao Pinto */ 1008ce736788SJoao Pinto static void stmmac_clear_tx_descriptors(struct stmmac_priv *priv, u32 queue) 100971fedb01SJoao Pinto { 1010ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 101171fedb01SJoao Pinto int i; 101271fedb01SJoao Pinto 101371fedb01SJoao Pinto /* Clear the TX descriptors */ 10145bacd778SLABBE Corentin for (i = 0; i < DMA_TX_SIZE; i++) 10155bacd778SLABBE Corentin if (priv->extend_desc) 1016ce736788SJoao Pinto priv->hw->desc->init_tx_desc(&tx_q->dma_etx[i].basic, 10175bacd778SLABBE Corentin priv->mode, 10185bacd778SLABBE Corentin (i == DMA_TX_SIZE - 1)); 10195bacd778SLABBE Corentin else 1020ce736788SJoao Pinto priv->hw->desc->init_tx_desc(&tx_q->dma_tx[i], 10215bacd778SLABBE Corentin priv->mode, 10225bacd778SLABBE Corentin (i == DMA_TX_SIZE - 1)); 1023c24602efSGiuseppe CAVALLARO } 1024c24602efSGiuseppe CAVALLARO 1025732fdf0eSGiuseppe CAVALLARO /** 102671fedb01SJoao Pinto * stmmac_clear_descriptors - clear descriptors 102771fedb01SJoao Pinto * @priv: driver private structure 102871fedb01SJoao Pinto * Description: this function is called to clear the TX and RX descriptors 102971fedb01SJoao Pinto * in case of both basic and extended descriptors are used. 103071fedb01SJoao Pinto */ 103171fedb01SJoao Pinto static void stmmac_clear_descriptors(struct stmmac_priv *priv) 103271fedb01SJoao Pinto { 103354139cf3SJoao Pinto u32 rx_queue_cnt = priv->plat->rx_queues_to_use; 1034ce736788SJoao Pinto u32 tx_queue_cnt = priv->plat->tx_queues_to_use; 103554139cf3SJoao Pinto u32 queue; 103654139cf3SJoao Pinto 103771fedb01SJoao Pinto /* Clear the RX descriptors */ 103854139cf3SJoao Pinto for (queue = 0; queue < rx_queue_cnt; queue++) 103954139cf3SJoao Pinto stmmac_clear_rx_descriptors(priv, queue); 104071fedb01SJoao Pinto 104171fedb01SJoao Pinto /* Clear the TX descriptors */ 1042ce736788SJoao Pinto for (queue = 0; queue < tx_queue_cnt; queue++) 1043ce736788SJoao Pinto stmmac_clear_tx_descriptors(priv, queue); 104471fedb01SJoao Pinto } 104571fedb01SJoao Pinto 104671fedb01SJoao Pinto /** 1047732fdf0eSGiuseppe CAVALLARO * stmmac_init_rx_buffers - init the RX descriptor buffer. 1048732fdf0eSGiuseppe CAVALLARO * @priv: driver private structure 1049732fdf0eSGiuseppe CAVALLARO * @p: descriptor pointer 1050732fdf0eSGiuseppe CAVALLARO * @i: descriptor index 105154139cf3SJoao Pinto * @flags: gfp flag 105254139cf3SJoao Pinto * @queue: RX queue index 1053732fdf0eSGiuseppe CAVALLARO * Description: this function is called to allocate a receive buffer, perform 1054732fdf0eSGiuseppe CAVALLARO * the DMA mapping and init the descriptor. 1055732fdf0eSGiuseppe CAVALLARO */ 1056c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, 105754139cf3SJoao Pinto int i, gfp_t flags, u32 queue) 1058c24602efSGiuseppe CAVALLARO { 105954139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 1060c24602efSGiuseppe CAVALLARO struct sk_buff *skb; 1061c24602efSGiuseppe CAVALLARO 10624ec49a37SVineet Gupta skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags); 106356329137SBartlomiej Zolnierkiewicz if (!skb) { 106438ddc59dSLABBE Corentin netdev_err(priv->dev, 106538ddc59dSLABBE Corentin "%s: Rx init fails; skb is NULL\n", __func__); 106656329137SBartlomiej Zolnierkiewicz return -ENOMEM; 1067c24602efSGiuseppe CAVALLARO } 106854139cf3SJoao Pinto rx_q->rx_skbuff[i] = skb; 106954139cf3SJoao Pinto rx_q->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data, 1070c24602efSGiuseppe CAVALLARO priv->dma_buf_sz, 1071c24602efSGiuseppe CAVALLARO DMA_FROM_DEVICE); 107254139cf3SJoao Pinto if (dma_mapping_error(priv->device, rx_q->rx_skbuff_dma[i])) { 107338ddc59dSLABBE Corentin netdev_err(priv->dev, "%s: DMA mapping error\n", __func__); 107456329137SBartlomiej Zolnierkiewicz dev_kfree_skb_any(skb); 107556329137SBartlomiej Zolnierkiewicz return -EINVAL; 107656329137SBartlomiej Zolnierkiewicz } 1077c24602efSGiuseppe CAVALLARO 1078f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) 107954139cf3SJoao Pinto p->des0 = cpu_to_le32(rx_q->rx_skbuff_dma[i]); 1080f748be53SAlexandre TORGUE else 108154139cf3SJoao Pinto p->des2 = cpu_to_le32(rx_q->rx_skbuff_dma[i]); 1082c24602efSGiuseppe CAVALLARO 108329896a67SGiuseppe CAVALLARO if ((priv->hw->mode->init_desc3) && 1084c24602efSGiuseppe CAVALLARO (priv->dma_buf_sz == BUF_SIZE_16KiB)) 108529896a67SGiuseppe CAVALLARO priv->hw->mode->init_desc3(p); 1086c24602efSGiuseppe CAVALLARO 1087c24602efSGiuseppe CAVALLARO return 0; 1088c24602efSGiuseppe CAVALLARO } 1089c24602efSGiuseppe CAVALLARO 109071fedb01SJoao Pinto /** 109171fedb01SJoao Pinto * stmmac_free_rx_buffer - free RX dma buffers 109271fedb01SJoao Pinto * @priv: private structure 109354139cf3SJoao Pinto * @queue: RX queue index 109471fedb01SJoao Pinto * @i: buffer index. 109571fedb01SJoao Pinto */ 109654139cf3SJoao Pinto static void stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i) 109756329137SBartlomiej Zolnierkiewicz { 109854139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 109954139cf3SJoao Pinto 110054139cf3SJoao Pinto if (rx_q->rx_skbuff[i]) { 110154139cf3SJoao Pinto dma_unmap_single(priv->device, rx_q->rx_skbuff_dma[i], 110256329137SBartlomiej Zolnierkiewicz priv->dma_buf_sz, DMA_FROM_DEVICE); 110354139cf3SJoao Pinto dev_kfree_skb_any(rx_q->rx_skbuff[i]); 110456329137SBartlomiej Zolnierkiewicz } 110554139cf3SJoao Pinto rx_q->rx_skbuff[i] = NULL; 110656329137SBartlomiej Zolnierkiewicz } 110756329137SBartlomiej Zolnierkiewicz 11087ac6653aSJeff Kirsher /** 110971fedb01SJoao Pinto * stmmac_free_tx_buffer - free RX dma buffers 111071fedb01SJoao Pinto * @priv: private structure 1111ce736788SJoao Pinto * @queue: RX queue index 111271fedb01SJoao Pinto * @i: buffer index. 111371fedb01SJoao Pinto */ 1114ce736788SJoao Pinto static void stmmac_free_tx_buffer(struct stmmac_priv *priv, u32 queue, int i) 111571fedb01SJoao Pinto { 1116ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 1117ce736788SJoao Pinto 1118ce736788SJoao Pinto if (tx_q->tx_skbuff_dma[i].buf) { 1119ce736788SJoao Pinto if (tx_q->tx_skbuff_dma[i].map_as_page) 112071fedb01SJoao Pinto dma_unmap_page(priv->device, 1121ce736788SJoao Pinto tx_q->tx_skbuff_dma[i].buf, 1122ce736788SJoao Pinto tx_q->tx_skbuff_dma[i].len, 112371fedb01SJoao Pinto DMA_TO_DEVICE); 112471fedb01SJoao Pinto else 112571fedb01SJoao Pinto dma_unmap_single(priv->device, 1126ce736788SJoao Pinto tx_q->tx_skbuff_dma[i].buf, 1127ce736788SJoao Pinto tx_q->tx_skbuff_dma[i].len, 112871fedb01SJoao Pinto DMA_TO_DEVICE); 112971fedb01SJoao Pinto } 113071fedb01SJoao Pinto 1131ce736788SJoao Pinto if (tx_q->tx_skbuff[i]) { 1132ce736788SJoao Pinto dev_kfree_skb_any(tx_q->tx_skbuff[i]); 1133ce736788SJoao Pinto tx_q->tx_skbuff[i] = NULL; 1134ce736788SJoao Pinto tx_q->tx_skbuff_dma[i].buf = 0; 1135ce736788SJoao Pinto tx_q->tx_skbuff_dma[i].map_as_page = false; 113671fedb01SJoao Pinto } 113771fedb01SJoao Pinto } 113871fedb01SJoao Pinto 113971fedb01SJoao Pinto /** 114071fedb01SJoao Pinto * init_dma_rx_desc_rings - init the RX descriptor rings 11417ac6653aSJeff Kirsher * @dev: net device structure 11425bacd778SLABBE Corentin * @flags: gfp flag. 114371fedb01SJoao Pinto * Description: this function initializes the DMA RX descriptors 11445bacd778SLABBE Corentin * and allocates the socket buffers. It supports the chained and ring 1145286a8372SGiuseppe CAVALLARO * modes. 11467ac6653aSJeff Kirsher */ 114771fedb01SJoao Pinto static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags) 11487ac6653aSJeff Kirsher { 11497ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 115054139cf3SJoao Pinto u32 rx_count = priv->plat->rx_queues_to_use; 11515bacd778SLABBE Corentin unsigned int bfsize = 0; 11525bacd778SLABBE Corentin int ret = -ENOMEM; 115354139cf3SJoao Pinto u32 queue; 115454139cf3SJoao Pinto int i; 11557ac6653aSJeff Kirsher 11565bacd778SLABBE Corentin if (priv->hw->mode->set_16kib_bfsize) 11575bacd778SLABBE Corentin bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu); 11585bacd778SLABBE Corentin 11595bacd778SLABBE Corentin if (bfsize < BUF_SIZE_16KiB) 11605bacd778SLABBE Corentin bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz); 11615bacd778SLABBE Corentin 11625bacd778SLABBE Corentin priv->dma_buf_sz = bfsize; 11632618abb7SVince Bridgers 116454139cf3SJoao Pinto /* RX INITIALIZATION */ 11655bacd778SLABBE Corentin netif_dbg(priv, probe, priv->dev, 11665bacd778SLABBE Corentin "SKB addresses:\nskb\t\tskb data\tdma data\n"); 11675bacd778SLABBE Corentin 116854139cf3SJoao Pinto for (queue = 0; queue < rx_count; queue++) { 116954139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 117054139cf3SJoao Pinto 117154139cf3SJoao Pinto netif_dbg(priv, probe, priv->dev, 117254139cf3SJoao Pinto "(%s) dma_rx_phy=0x%08x\n", __func__, 117354139cf3SJoao Pinto (u32)rx_q->dma_rx_phy); 117454139cf3SJoao Pinto 11755bacd778SLABBE Corentin for (i = 0; i < DMA_RX_SIZE; i++) { 11765bacd778SLABBE Corentin struct dma_desc *p; 11775bacd778SLABBE Corentin 117854139cf3SJoao Pinto if (priv->extend_desc) 117954139cf3SJoao Pinto p = &((rx_q->dma_erx + i)->basic); 118054139cf3SJoao Pinto else 118154139cf3SJoao Pinto p = rx_q->dma_rx + i; 118254139cf3SJoao Pinto 118354139cf3SJoao Pinto ret = stmmac_init_rx_buffers(priv, p, i, flags, 118454139cf3SJoao Pinto queue); 11855bacd778SLABBE Corentin if (ret) 11865bacd778SLABBE Corentin goto err_init_rx_buffers; 11875bacd778SLABBE Corentin 11885bacd778SLABBE Corentin netif_dbg(priv, probe, priv->dev, "[%p]\t[%p]\t[%x]\n", 118954139cf3SJoao Pinto rx_q->rx_skbuff[i], rx_q->rx_skbuff[i]->data, 119054139cf3SJoao Pinto (unsigned int)rx_q->rx_skbuff_dma[i]); 11915bacd778SLABBE Corentin } 119254139cf3SJoao Pinto 119354139cf3SJoao Pinto rx_q->cur_rx = 0; 119454139cf3SJoao Pinto rx_q->dirty_rx = (unsigned int)(i - DMA_RX_SIZE); 119554139cf3SJoao Pinto 119654139cf3SJoao Pinto stmmac_clear_rx_descriptors(priv, queue); 11977ac6653aSJeff Kirsher 1198c24602efSGiuseppe CAVALLARO /* Setup the chained descriptor addresses */ 1199c24602efSGiuseppe CAVALLARO if (priv->mode == STMMAC_CHAIN_MODE) { 120071fedb01SJoao Pinto if (priv->extend_desc) 120154139cf3SJoao Pinto priv->hw->mode->init(rx_q->dma_erx, 120254139cf3SJoao Pinto rx_q->dma_rx_phy, 12035bacd778SLABBE Corentin DMA_RX_SIZE, 1); 120471fedb01SJoao Pinto else 120554139cf3SJoao Pinto priv->hw->mode->init(rx_q->dma_rx, 120654139cf3SJoao Pinto rx_q->dma_rx_phy, 12075bacd778SLABBE Corentin DMA_RX_SIZE, 0); 120871fedb01SJoao Pinto } 120954139cf3SJoao Pinto } 121054139cf3SJoao Pinto 121154139cf3SJoao Pinto buf_sz = bfsize; 121271fedb01SJoao Pinto 121371fedb01SJoao Pinto return 0; 121454139cf3SJoao Pinto 121571fedb01SJoao Pinto err_init_rx_buffers: 121654139cf3SJoao Pinto while (queue >= 0) { 121771fedb01SJoao Pinto while (--i >= 0) 121854139cf3SJoao Pinto stmmac_free_rx_buffer(priv, queue, i); 121954139cf3SJoao Pinto 122054139cf3SJoao Pinto if (queue == 0) 122154139cf3SJoao Pinto break; 122254139cf3SJoao Pinto 122354139cf3SJoao Pinto i = DMA_RX_SIZE; 122454139cf3SJoao Pinto queue--; 122554139cf3SJoao Pinto } 122654139cf3SJoao Pinto 122771fedb01SJoao Pinto return ret; 122871fedb01SJoao Pinto } 122971fedb01SJoao Pinto 123071fedb01SJoao Pinto /** 123171fedb01SJoao Pinto * init_dma_tx_desc_rings - init the TX descriptor rings 123271fedb01SJoao Pinto * @dev: net device structure. 123371fedb01SJoao Pinto * Description: this function initializes the DMA TX descriptors 123471fedb01SJoao Pinto * and allocates the socket buffers. It supports the chained and ring 123571fedb01SJoao Pinto * modes. 123671fedb01SJoao Pinto */ 123771fedb01SJoao Pinto static int init_dma_tx_desc_rings(struct net_device *dev) 123871fedb01SJoao Pinto { 123971fedb01SJoao Pinto struct stmmac_priv *priv = netdev_priv(dev); 1240ce736788SJoao Pinto u32 tx_queue_cnt = priv->plat->tx_queues_to_use; 1241ce736788SJoao Pinto u32 queue; 124271fedb01SJoao Pinto int i; 124371fedb01SJoao Pinto 1244ce736788SJoao Pinto for (queue = 0; queue < tx_queue_cnt; queue++) { 1245ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 1246ce736788SJoao Pinto 124771fedb01SJoao Pinto netif_dbg(priv, probe, priv->dev, 1248ce736788SJoao Pinto "(%s) dma_tx_phy=0x%08x\n", __func__, 1249ce736788SJoao Pinto (u32)tx_q->dma_tx_phy); 125071fedb01SJoao Pinto 125171fedb01SJoao Pinto /* Setup the chained descriptor addresses */ 125271fedb01SJoao Pinto if (priv->mode == STMMAC_CHAIN_MODE) { 125371fedb01SJoao Pinto if (priv->extend_desc) 1254ce736788SJoao Pinto priv->hw->mode->init(tx_q->dma_etx, 1255ce736788SJoao Pinto tx_q->dma_tx_phy, 125671fedb01SJoao Pinto DMA_TX_SIZE, 1); 125771fedb01SJoao Pinto else 1258ce736788SJoao Pinto priv->hw->mode->init(tx_q->dma_tx, 1259ce736788SJoao Pinto tx_q->dma_tx_phy, 1260e3ad57c9SGiuseppe Cavallaro DMA_TX_SIZE, 0); 1261c24602efSGiuseppe CAVALLARO } 1262286a8372SGiuseppe CAVALLARO 1263e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_TX_SIZE; i++) { 1264c24602efSGiuseppe CAVALLARO struct dma_desc *p; 1265ce736788SJoao Pinto 1266c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1267ce736788SJoao Pinto p = &((tx_q->dma_etx + i)->basic); 1268c24602efSGiuseppe CAVALLARO else 1269ce736788SJoao Pinto p = tx_q->dma_tx + i; 1270f748be53SAlexandre TORGUE 1271f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) { 1272f748be53SAlexandre TORGUE p->des0 = 0; 1273f748be53SAlexandre TORGUE p->des1 = 0; 1274c24602efSGiuseppe CAVALLARO p->des2 = 0; 1275f748be53SAlexandre TORGUE p->des3 = 0; 1276f748be53SAlexandre TORGUE } else { 1277f748be53SAlexandre TORGUE p->des2 = 0; 1278f748be53SAlexandre TORGUE } 1279f748be53SAlexandre TORGUE 1280ce736788SJoao Pinto tx_q->tx_skbuff_dma[i].buf = 0; 1281ce736788SJoao Pinto tx_q->tx_skbuff_dma[i].map_as_page = false; 1282ce736788SJoao Pinto tx_q->tx_skbuff_dma[i].len = 0; 1283ce736788SJoao Pinto tx_q->tx_skbuff_dma[i].last_segment = false; 1284ce736788SJoao Pinto tx_q->tx_skbuff[i] = NULL; 12854a7d666aSGiuseppe CAVALLARO } 1286c24602efSGiuseppe CAVALLARO 1287ce736788SJoao Pinto tx_q->dirty_tx = 0; 1288ce736788SJoao Pinto tx_q->cur_tx = 0; 1289ce736788SJoao Pinto } 1290ce736788SJoao Pinto 12915bacd778SLABBE Corentin netdev_reset_queue(priv->dev); 12927ac6653aSJeff Kirsher 129371fedb01SJoao Pinto return 0; 129471fedb01SJoao Pinto } 129571fedb01SJoao Pinto 129671fedb01SJoao Pinto /** 129771fedb01SJoao Pinto * init_dma_desc_rings - init the RX/TX descriptor rings 129871fedb01SJoao Pinto * @dev: net device structure 129971fedb01SJoao Pinto * @flags: gfp flag. 130071fedb01SJoao Pinto * Description: this function initializes the DMA RX/TX descriptors 130171fedb01SJoao Pinto * and allocates the socket buffers. It supports the chained and ring 130271fedb01SJoao Pinto * modes. 130371fedb01SJoao Pinto */ 130471fedb01SJoao Pinto static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) 130571fedb01SJoao Pinto { 130671fedb01SJoao Pinto struct stmmac_priv *priv = netdev_priv(dev); 130771fedb01SJoao Pinto int ret; 130871fedb01SJoao Pinto 130971fedb01SJoao Pinto ret = init_dma_rx_desc_rings(dev, flags); 131071fedb01SJoao Pinto if (ret) 131171fedb01SJoao Pinto return ret; 131271fedb01SJoao Pinto 131371fedb01SJoao Pinto ret = init_dma_tx_desc_rings(dev); 131471fedb01SJoao Pinto 13155bacd778SLABBE Corentin stmmac_clear_descriptors(priv); 13167ac6653aSJeff Kirsher 1317c24602efSGiuseppe CAVALLARO if (netif_msg_hw(priv)) 1318c24602efSGiuseppe CAVALLARO stmmac_display_rings(priv); 131956329137SBartlomiej Zolnierkiewicz 132056329137SBartlomiej Zolnierkiewicz return ret; 13217ac6653aSJeff Kirsher } 13227ac6653aSJeff Kirsher 132371fedb01SJoao Pinto /** 132471fedb01SJoao Pinto * dma_free_rx_skbufs - free RX dma buffers 132571fedb01SJoao Pinto * @priv: private structure 132654139cf3SJoao Pinto * @queue: RX queue index 132771fedb01SJoao Pinto */ 132854139cf3SJoao Pinto static void dma_free_rx_skbufs(struct stmmac_priv *priv, u32 queue) 13297ac6653aSJeff Kirsher { 13307ac6653aSJeff Kirsher int i; 13317ac6653aSJeff Kirsher 1332e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_RX_SIZE; i++) 133354139cf3SJoao Pinto stmmac_free_rx_buffer(priv, queue, i); 13347ac6653aSJeff Kirsher } 13357ac6653aSJeff Kirsher 133671fedb01SJoao Pinto /** 133771fedb01SJoao Pinto * dma_free_tx_skbufs - free TX dma buffers 133871fedb01SJoao Pinto * @priv: private structure 1339ce736788SJoao Pinto * @queue: TX queue index 134071fedb01SJoao Pinto */ 1341ce736788SJoao Pinto static void dma_free_tx_skbufs(struct stmmac_priv *priv, u32 queue) 13427ac6653aSJeff Kirsher { 13437ac6653aSJeff Kirsher int i; 13447ac6653aSJeff Kirsher 134571fedb01SJoao Pinto for (i = 0; i < DMA_TX_SIZE; i++) 1346ce736788SJoao Pinto stmmac_free_tx_buffer(priv, queue, i); 13477ac6653aSJeff Kirsher } 13487ac6653aSJeff Kirsher 1349732fdf0eSGiuseppe CAVALLARO /** 135054139cf3SJoao Pinto * free_dma_rx_desc_resources - free RX dma desc resources 135154139cf3SJoao Pinto * @priv: private structure 135254139cf3SJoao Pinto */ 135354139cf3SJoao Pinto static void free_dma_rx_desc_resources(struct stmmac_priv *priv) 135454139cf3SJoao Pinto { 135554139cf3SJoao Pinto u32 rx_count = priv->plat->rx_queues_to_use; 135654139cf3SJoao Pinto u32 queue; 135754139cf3SJoao Pinto 135854139cf3SJoao Pinto /* Free RX queue resources */ 135954139cf3SJoao Pinto for (queue = 0; queue < rx_count; queue++) { 136054139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 136154139cf3SJoao Pinto 136254139cf3SJoao Pinto /* Release the DMA RX socket buffers */ 136354139cf3SJoao Pinto dma_free_rx_skbufs(priv, queue); 136454139cf3SJoao Pinto 136554139cf3SJoao Pinto /* Free DMA regions of consistent memory previously allocated */ 136654139cf3SJoao Pinto if (!priv->extend_desc) 136754139cf3SJoao Pinto dma_free_coherent(priv->device, 136854139cf3SJoao Pinto DMA_RX_SIZE * sizeof(struct dma_desc), 136954139cf3SJoao Pinto rx_q->dma_rx, rx_q->dma_rx_phy); 137054139cf3SJoao Pinto else 137154139cf3SJoao Pinto dma_free_coherent(priv->device, DMA_RX_SIZE * 137254139cf3SJoao Pinto sizeof(struct dma_extended_desc), 137354139cf3SJoao Pinto rx_q->dma_erx, rx_q->dma_rx_phy); 137454139cf3SJoao Pinto 137554139cf3SJoao Pinto kfree(rx_q->rx_skbuff_dma); 137654139cf3SJoao Pinto kfree(rx_q->rx_skbuff); 137754139cf3SJoao Pinto } 137854139cf3SJoao Pinto } 137954139cf3SJoao Pinto 138054139cf3SJoao Pinto /** 1381ce736788SJoao Pinto * free_dma_tx_desc_resources - free TX dma desc resources 1382ce736788SJoao Pinto * @priv: private structure 1383ce736788SJoao Pinto */ 1384ce736788SJoao Pinto static void free_dma_tx_desc_resources(struct stmmac_priv *priv) 1385ce736788SJoao Pinto { 1386ce736788SJoao Pinto u32 tx_count = priv->plat->tx_queues_to_use; 1387ce736788SJoao Pinto u32 queue = 0; 1388ce736788SJoao Pinto 1389ce736788SJoao Pinto /* Free TX queue resources */ 1390ce736788SJoao Pinto for (queue = 0; queue < tx_count; queue++) { 1391ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 1392ce736788SJoao Pinto 1393ce736788SJoao Pinto /* Release the DMA TX socket buffers */ 1394ce736788SJoao Pinto dma_free_tx_skbufs(priv, queue); 1395ce736788SJoao Pinto 1396ce736788SJoao Pinto /* Free DMA regions of consistent memory previously allocated */ 1397ce736788SJoao Pinto if (!priv->extend_desc) 1398ce736788SJoao Pinto dma_free_coherent(priv->device, 1399ce736788SJoao Pinto DMA_TX_SIZE * sizeof(struct dma_desc), 1400ce736788SJoao Pinto tx_q->dma_tx, tx_q->dma_tx_phy); 1401ce736788SJoao Pinto else 1402ce736788SJoao Pinto dma_free_coherent(priv->device, DMA_TX_SIZE * 1403ce736788SJoao Pinto sizeof(struct dma_extended_desc), 1404ce736788SJoao Pinto tx_q->dma_etx, tx_q->dma_tx_phy); 1405ce736788SJoao Pinto 1406ce736788SJoao Pinto kfree(tx_q->tx_skbuff_dma); 1407ce736788SJoao Pinto kfree(tx_q->tx_skbuff); 1408ce736788SJoao Pinto } 1409ce736788SJoao Pinto } 1410ce736788SJoao Pinto 1411ce736788SJoao Pinto /** 141271fedb01SJoao Pinto * alloc_dma_rx_desc_resources - alloc RX resources. 1413732fdf0eSGiuseppe CAVALLARO * @priv: private structure 1414732fdf0eSGiuseppe CAVALLARO * Description: according to which descriptor can be used (extend or basic) 1415732fdf0eSGiuseppe CAVALLARO * this function allocates the resources for TX and RX paths. In case of 1416732fdf0eSGiuseppe CAVALLARO * reception, for example, it pre-allocated the RX socket buffer in order to 1417732fdf0eSGiuseppe CAVALLARO * allow zero-copy mechanism. 1418732fdf0eSGiuseppe CAVALLARO */ 141971fedb01SJoao Pinto static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv) 142009f8d696SSrinivas Kandagatla { 142154139cf3SJoao Pinto u32 rx_count = priv->plat->rx_queues_to_use; 14225bacd778SLABBE Corentin int ret = -ENOMEM; 142354139cf3SJoao Pinto u32 queue; 142409f8d696SSrinivas Kandagatla 142554139cf3SJoao Pinto /* RX queues buffers and DMA */ 142654139cf3SJoao Pinto for (queue = 0; queue < rx_count; queue++) { 142754139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 142854139cf3SJoao Pinto 142954139cf3SJoao Pinto rx_q->queue_index = queue; 143054139cf3SJoao Pinto rx_q->priv_data = priv; 143154139cf3SJoao Pinto 143254139cf3SJoao Pinto rx_q->rx_skbuff_dma = kmalloc_array(DMA_RX_SIZE, 143354139cf3SJoao Pinto sizeof(dma_addr_t), 14345bacd778SLABBE Corentin GFP_KERNEL); 143554139cf3SJoao Pinto if (!rx_q->rx_skbuff_dma) 14365bacd778SLABBE Corentin return -ENOMEM; 14375bacd778SLABBE Corentin 143854139cf3SJoao Pinto rx_q->rx_skbuff = kmalloc_array(DMA_RX_SIZE, 143954139cf3SJoao Pinto sizeof(struct sk_buff *), 14405bacd778SLABBE Corentin GFP_KERNEL); 144154139cf3SJoao Pinto if (!rx_q->rx_skbuff) 144254139cf3SJoao Pinto goto err_dma; 14435bacd778SLABBE Corentin 14445bacd778SLABBE Corentin if (priv->extend_desc) { 144554139cf3SJoao Pinto rx_q->dma_erx = dma_zalloc_coherent(priv->device, 144654139cf3SJoao Pinto DMA_RX_SIZE * 14475bacd778SLABBE Corentin sizeof(struct 14485bacd778SLABBE Corentin dma_extended_desc), 144954139cf3SJoao Pinto &rx_q->dma_rx_phy, 14505bacd778SLABBE Corentin GFP_KERNEL); 145154139cf3SJoao Pinto if (!rx_q->dma_erx) 14525bacd778SLABBE Corentin goto err_dma; 14535bacd778SLABBE Corentin 145471fedb01SJoao Pinto } else { 145554139cf3SJoao Pinto rx_q->dma_rx = dma_zalloc_coherent(priv->device, 145654139cf3SJoao Pinto DMA_RX_SIZE * 145754139cf3SJoao Pinto sizeof(struct 145854139cf3SJoao Pinto dma_desc), 145954139cf3SJoao Pinto &rx_q->dma_rx_phy, 146071fedb01SJoao Pinto GFP_KERNEL); 146154139cf3SJoao Pinto if (!rx_q->dma_rx) 146271fedb01SJoao Pinto goto err_dma; 146371fedb01SJoao Pinto } 146454139cf3SJoao Pinto } 146571fedb01SJoao Pinto 146671fedb01SJoao Pinto return 0; 146771fedb01SJoao Pinto 146871fedb01SJoao Pinto err_dma: 146954139cf3SJoao Pinto free_dma_rx_desc_resources(priv); 147054139cf3SJoao Pinto 147171fedb01SJoao Pinto return ret; 147271fedb01SJoao Pinto } 147371fedb01SJoao Pinto 147471fedb01SJoao Pinto /** 147571fedb01SJoao Pinto * alloc_dma_tx_desc_resources - alloc TX resources. 147671fedb01SJoao Pinto * @priv: private structure 147771fedb01SJoao Pinto * Description: according to which descriptor can be used (extend or basic) 147871fedb01SJoao Pinto * this function allocates the resources for TX and RX paths. In case of 147971fedb01SJoao Pinto * reception, for example, it pre-allocated the RX socket buffer in order to 148071fedb01SJoao Pinto * allow zero-copy mechanism. 148171fedb01SJoao Pinto */ 148271fedb01SJoao Pinto static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv) 148371fedb01SJoao Pinto { 1484ce736788SJoao Pinto u32 tx_count = priv->plat->tx_queues_to_use; 148571fedb01SJoao Pinto int ret = -ENOMEM; 1486ce736788SJoao Pinto u32 queue; 148771fedb01SJoao Pinto 1488ce736788SJoao Pinto /* TX queues buffers and DMA */ 1489ce736788SJoao Pinto for (queue = 0; queue < tx_count; queue++) { 1490ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 1491ce736788SJoao Pinto 1492ce736788SJoao Pinto tx_q->queue_index = queue; 1493ce736788SJoao Pinto tx_q->priv_data = priv; 1494ce736788SJoao Pinto 1495ce736788SJoao Pinto tx_q->tx_skbuff_dma = kmalloc_array(DMA_TX_SIZE, 1496ce736788SJoao Pinto sizeof(*tx_q->tx_skbuff_dma), 149771fedb01SJoao Pinto GFP_KERNEL); 1498ce736788SJoao Pinto if (!tx_q->tx_skbuff_dma) 149971fedb01SJoao Pinto return -ENOMEM; 150071fedb01SJoao Pinto 1501ce736788SJoao Pinto tx_q->tx_skbuff = kmalloc_array(DMA_TX_SIZE, 1502ce736788SJoao Pinto sizeof(struct sk_buff *), 150371fedb01SJoao Pinto GFP_KERNEL); 1504ce736788SJoao Pinto if (!tx_q->tx_skbuff) 1505ce736788SJoao Pinto goto err_dma_buffers; 150671fedb01SJoao Pinto 150771fedb01SJoao Pinto if (priv->extend_desc) { 1508ce736788SJoao Pinto tx_q->dma_etx = dma_zalloc_coherent(priv->device, 1509ce736788SJoao Pinto DMA_TX_SIZE * 15105bacd778SLABBE Corentin sizeof(struct 15115bacd778SLABBE Corentin dma_extended_desc), 1512ce736788SJoao Pinto &tx_q->dma_tx_phy, 15135bacd778SLABBE Corentin GFP_KERNEL); 1514ce736788SJoao Pinto if (!tx_q->dma_etx) 1515ce736788SJoao Pinto goto err_dma_buffers; 15165bacd778SLABBE Corentin } else { 1517ce736788SJoao Pinto tx_q->dma_tx = dma_zalloc_coherent(priv->device, 1518ce736788SJoao Pinto DMA_TX_SIZE * 1519ce736788SJoao Pinto sizeof(struct 1520ce736788SJoao Pinto dma_desc), 1521ce736788SJoao Pinto &tx_q->dma_tx_phy, 15225bacd778SLABBE Corentin GFP_KERNEL); 1523ce736788SJoao Pinto if (!tx_q->dma_tx) 1524ce736788SJoao Pinto goto err_dma_buffers; 1525ce736788SJoao Pinto } 15265bacd778SLABBE Corentin } 15275bacd778SLABBE Corentin 15285bacd778SLABBE Corentin return 0; 15295bacd778SLABBE Corentin 1530ce736788SJoao Pinto err_dma_buffers: 1531ce736788SJoao Pinto free_dma_tx_desc_resources(priv); 1532ce736788SJoao Pinto 153309f8d696SSrinivas Kandagatla return ret; 15345bacd778SLABBE Corentin } 153509f8d696SSrinivas Kandagatla 153671fedb01SJoao Pinto /** 153771fedb01SJoao Pinto * alloc_dma_desc_resources - alloc TX/RX resources. 153871fedb01SJoao Pinto * @priv: private structure 153971fedb01SJoao Pinto * Description: according to which descriptor can be used (extend or basic) 154071fedb01SJoao Pinto * this function allocates the resources for TX and RX paths. In case of 154171fedb01SJoao Pinto * reception, for example, it pre-allocated the RX socket buffer in order to 154271fedb01SJoao Pinto * allow zero-copy mechanism. 154371fedb01SJoao Pinto */ 154471fedb01SJoao Pinto static int alloc_dma_desc_resources(struct stmmac_priv *priv) 15455bacd778SLABBE Corentin { 154654139cf3SJoao Pinto /* RX Allocation */ 154771fedb01SJoao Pinto int ret = alloc_dma_rx_desc_resources(priv); 154871fedb01SJoao Pinto 154971fedb01SJoao Pinto if (ret) 155071fedb01SJoao Pinto return ret; 155171fedb01SJoao Pinto 155271fedb01SJoao Pinto ret = alloc_dma_tx_desc_resources(priv); 155371fedb01SJoao Pinto 155471fedb01SJoao Pinto return ret; 155571fedb01SJoao Pinto } 155671fedb01SJoao Pinto 155771fedb01SJoao Pinto /** 155871fedb01SJoao Pinto * free_dma_desc_resources - free dma desc resources 155971fedb01SJoao Pinto * @priv: private structure 156071fedb01SJoao Pinto */ 156171fedb01SJoao Pinto static void free_dma_desc_resources(struct stmmac_priv *priv) 156271fedb01SJoao Pinto { 156371fedb01SJoao Pinto /* Release the DMA RX socket buffers */ 156471fedb01SJoao Pinto free_dma_rx_desc_resources(priv); 156571fedb01SJoao Pinto 156671fedb01SJoao Pinto /* Release the DMA TX socket buffers */ 156771fedb01SJoao Pinto free_dma_tx_desc_resources(priv); 156871fedb01SJoao Pinto } 156971fedb01SJoao Pinto 157071fedb01SJoao Pinto /** 15719eb12474Sjpinto * stmmac_mac_enable_rx_queues - Enable MAC rx queues 15729eb12474Sjpinto * @priv: driver private structure 15739eb12474Sjpinto * Description: It is used for enabling the rx queues in the MAC 15749eb12474Sjpinto */ 15759eb12474Sjpinto static void stmmac_mac_enable_rx_queues(struct stmmac_priv *priv) 15769eb12474Sjpinto { 15774f6046f5SJoao Pinto u32 rx_queues_count = priv->plat->rx_queues_to_use; 15784f6046f5SJoao Pinto int queue; 15794f6046f5SJoao Pinto u8 mode; 15809eb12474Sjpinto 15814f6046f5SJoao Pinto for (queue = 0; queue < rx_queues_count; queue++) { 15824f6046f5SJoao Pinto mode = priv->plat->rx_queues_cfg[queue].mode_to_use; 15834f6046f5SJoao Pinto priv->hw->mac->rx_queue_enable(priv->hw, mode, queue); 15844f6046f5SJoao Pinto } 15859eb12474Sjpinto } 15869eb12474Sjpinto 15879eb12474Sjpinto /** 1588ae4f0d46SJoao Pinto * stmmac_start_rx_dma - start RX DMA channel 1589ae4f0d46SJoao Pinto * @priv: driver private structure 1590ae4f0d46SJoao Pinto * @chan: RX channel index 1591ae4f0d46SJoao Pinto * Description: 1592ae4f0d46SJoao Pinto * This starts a RX DMA channel 1593ae4f0d46SJoao Pinto */ 1594ae4f0d46SJoao Pinto static void stmmac_start_rx_dma(struct stmmac_priv *priv, u32 chan) 1595ae4f0d46SJoao Pinto { 1596ae4f0d46SJoao Pinto netdev_dbg(priv->dev, "DMA RX processes started in channel %d\n", chan); 1597ae4f0d46SJoao Pinto priv->hw->dma->start_rx(priv->ioaddr, chan); 1598ae4f0d46SJoao Pinto } 1599ae4f0d46SJoao Pinto 1600ae4f0d46SJoao Pinto /** 1601ae4f0d46SJoao Pinto * stmmac_start_tx_dma - start TX DMA channel 1602ae4f0d46SJoao Pinto * @priv: driver private structure 1603ae4f0d46SJoao Pinto * @chan: TX channel index 1604ae4f0d46SJoao Pinto * Description: 1605ae4f0d46SJoao Pinto * This starts a TX DMA channel 1606ae4f0d46SJoao Pinto */ 1607ae4f0d46SJoao Pinto static void stmmac_start_tx_dma(struct stmmac_priv *priv, u32 chan) 1608ae4f0d46SJoao Pinto { 1609ae4f0d46SJoao Pinto netdev_dbg(priv->dev, "DMA TX processes started in channel %d\n", chan); 1610ae4f0d46SJoao Pinto priv->hw->dma->start_tx(priv->ioaddr, chan); 1611ae4f0d46SJoao Pinto } 1612ae4f0d46SJoao Pinto 1613ae4f0d46SJoao Pinto /** 1614ae4f0d46SJoao Pinto * stmmac_stop_rx_dma - stop RX DMA channel 1615ae4f0d46SJoao Pinto * @priv: driver private structure 1616ae4f0d46SJoao Pinto * @chan: RX channel index 1617ae4f0d46SJoao Pinto * Description: 1618ae4f0d46SJoao Pinto * This stops a RX DMA channel 1619ae4f0d46SJoao Pinto */ 1620ae4f0d46SJoao Pinto static void stmmac_stop_rx_dma(struct stmmac_priv *priv, u32 chan) 1621ae4f0d46SJoao Pinto { 1622ae4f0d46SJoao Pinto netdev_dbg(priv->dev, "DMA RX processes stopped in channel %d\n", chan); 1623ae4f0d46SJoao Pinto priv->hw->dma->stop_rx(priv->ioaddr, chan); 1624ae4f0d46SJoao Pinto } 1625ae4f0d46SJoao Pinto 1626ae4f0d46SJoao Pinto /** 1627ae4f0d46SJoao Pinto * stmmac_stop_tx_dma - stop TX DMA channel 1628ae4f0d46SJoao Pinto * @priv: driver private structure 1629ae4f0d46SJoao Pinto * @chan: TX channel index 1630ae4f0d46SJoao Pinto * Description: 1631ae4f0d46SJoao Pinto * This stops a TX DMA channel 1632ae4f0d46SJoao Pinto */ 1633ae4f0d46SJoao Pinto static void stmmac_stop_tx_dma(struct stmmac_priv *priv, u32 chan) 1634ae4f0d46SJoao Pinto { 1635ae4f0d46SJoao Pinto netdev_dbg(priv->dev, "DMA TX processes stopped in channel %d\n", chan); 1636ae4f0d46SJoao Pinto priv->hw->dma->stop_tx(priv->ioaddr, chan); 1637ae4f0d46SJoao Pinto } 1638ae4f0d46SJoao Pinto 1639ae4f0d46SJoao Pinto /** 1640ae4f0d46SJoao Pinto * stmmac_start_all_dma - start all RX and TX DMA channels 1641ae4f0d46SJoao Pinto * @priv: driver private structure 1642ae4f0d46SJoao Pinto * Description: 1643ae4f0d46SJoao Pinto * This starts all the RX and TX DMA channels 1644ae4f0d46SJoao Pinto */ 1645ae4f0d46SJoao Pinto static void stmmac_start_all_dma(struct stmmac_priv *priv) 1646ae4f0d46SJoao Pinto { 1647ae4f0d46SJoao Pinto u32 rx_channels_count = priv->plat->rx_queues_to_use; 1648ae4f0d46SJoao Pinto u32 tx_channels_count = priv->plat->tx_queues_to_use; 1649ae4f0d46SJoao Pinto u32 chan = 0; 1650ae4f0d46SJoao Pinto 1651ae4f0d46SJoao Pinto for (chan = 0; chan < rx_channels_count; chan++) 1652ae4f0d46SJoao Pinto stmmac_start_rx_dma(priv, chan); 1653ae4f0d46SJoao Pinto 1654ae4f0d46SJoao Pinto for (chan = 0; chan < tx_channels_count; chan++) 1655ae4f0d46SJoao Pinto stmmac_start_tx_dma(priv, chan); 1656ae4f0d46SJoao Pinto } 1657ae4f0d46SJoao Pinto 1658ae4f0d46SJoao Pinto /** 1659ae4f0d46SJoao Pinto * stmmac_stop_all_dma - stop all RX and TX DMA channels 1660ae4f0d46SJoao Pinto * @priv: driver private structure 1661ae4f0d46SJoao Pinto * Description: 1662ae4f0d46SJoao Pinto * This stops the RX and TX DMA channels 1663ae4f0d46SJoao Pinto */ 1664ae4f0d46SJoao Pinto static void stmmac_stop_all_dma(struct stmmac_priv *priv) 1665ae4f0d46SJoao Pinto { 1666ae4f0d46SJoao Pinto u32 rx_channels_count = priv->plat->rx_queues_to_use; 1667ae4f0d46SJoao Pinto u32 tx_channels_count = priv->plat->tx_queues_to_use; 1668ae4f0d46SJoao Pinto u32 chan = 0; 1669ae4f0d46SJoao Pinto 1670ae4f0d46SJoao Pinto for (chan = 0; chan < rx_channels_count; chan++) 1671ae4f0d46SJoao Pinto stmmac_stop_rx_dma(priv, chan); 1672ae4f0d46SJoao Pinto 1673ae4f0d46SJoao Pinto for (chan = 0; chan < tx_channels_count; chan++) 1674ae4f0d46SJoao Pinto stmmac_stop_tx_dma(priv, chan); 1675ae4f0d46SJoao Pinto } 1676ae4f0d46SJoao Pinto 1677ae4f0d46SJoao Pinto /** 16787ac6653aSJeff Kirsher * stmmac_dma_operation_mode - HW DMA operation mode 167932ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 1680732fdf0eSGiuseppe CAVALLARO * Description: it is used for configuring the DMA operation mode register in 1681732fdf0eSGiuseppe CAVALLARO * order to program the tx/rx DMA thresholds or Store-And-Forward mode. 16827ac6653aSJeff Kirsher */ 16837ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv) 16847ac6653aSJeff Kirsher { 16856deee222SJoao Pinto u32 rx_channels_count = priv->plat->rx_queues_to_use; 16866deee222SJoao Pinto u32 tx_channels_count = priv->plat->tx_queues_to_use; 1687f88203a2SVince Bridgers int rxfifosz = priv->plat->rx_fifo_size; 16886deee222SJoao Pinto u32 txmode = 0; 16896deee222SJoao Pinto u32 rxmode = 0; 16906deee222SJoao Pinto u32 chan = 0; 1691f88203a2SVince Bridgers 169211fbf811SThierry Reding if (rxfifosz == 0) 169311fbf811SThierry Reding rxfifosz = priv->dma_cap.rx_fifo_size; 169411fbf811SThierry Reding 16956deee222SJoao Pinto if (priv->plat->force_thresh_dma_mode) { 16966deee222SJoao Pinto txmode = tc; 16976deee222SJoao Pinto rxmode = tc; 16986deee222SJoao Pinto } else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { 16997ac6653aSJeff Kirsher /* 17007ac6653aSJeff Kirsher * In case of GMAC, SF mode can be enabled 17017ac6653aSJeff Kirsher * to perform the TX COE in HW. This depends on: 17027ac6653aSJeff Kirsher * 1) TX COE if actually supported 17037ac6653aSJeff Kirsher * 2) There is no bugged Jumbo frame support 17047ac6653aSJeff Kirsher * that needs to not insert csum in the TDES. 17057ac6653aSJeff Kirsher */ 17066deee222SJoao Pinto txmode = SF_DMA_MODE; 17076deee222SJoao Pinto rxmode = SF_DMA_MODE; 1708b2dec116SSonic Zhang priv->xstats.threshold = SF_DMA_MODE; 17096deee222SJoao Pinto } else { 17106deee222SJoao Pinto txmode = tc; 17116deee222SJoao Pinto rxmode = SF_DMA_MODE; 17126deee222SJoao Pinto } 17136deee222SJoao Pinto 17146deee222SJoao Pinto /* configure all channels */ 17156deee222SJoao Pinto if (priv->synopsys_id >= DWMAC_CORE_4_00) { 17166deee222SJoao Pinto for (chan = 0; chan < rx_channels_count; chan++) 17176deee222SJoao Pinto priv->hw->dma->dma_rx_mode(priv->ioaddr, rxmode, chan, 1718f88203a2SVince Bridgers rxfifosz); 17196deee222SJoao Pinto 17206deee222SJoao Pinto for (chan = 0; chan < tx_channels_count; chan++) 17216deee222SJoao Pinto priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan); 17226deee222SJoao Pinto } else { 17236deee222SJoao Pinto priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode, 17246deee222SJoao Pinto rxfifosz); 17256deee222SJoao Pinto } 17267ac6653aSJeff Kirsher } 17277ac6653aSJeff Kirsher 17287ac6653aSJeff Kirsher /** 1729732fdf0eSGiuseppe CAVALLARO * stmmac_tx_clean - to manage the transmission completion 173032ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 1731ce736788SJoao Pinto * @queue: TX queue index 1732732fdf0eSGiuseppe CAVALLARO * Description: it reclaims the transmit resources after transmission completes. 17337ac6653aSJeff Kirsher */ 1734ce736788SJoao Pinto static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue) 17357ac6653aSJeff Kirsher { 1736ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 173738979574SBeniamino Galvani unsigned int bytes_compl = 0, pkts_compl = 0; 1738ce736788SJoao Pinto unsigned int entry = tx_q->dirty_tx; 17397ac6653aSJeff Kirsher 1740739c8e14SLino Sanfilippo netif_tx_lock(priv->dev); 1741a9097a96SGiuseppe CAVALLARO 17429125cdd1SGiuseppe CAVALLARO priv->xstats.tx_clean++; 17439125cdd1SGiuseppe CAVALLARO 1744ce736788SJoao Pinto while (entry != tx_q->cur_tx) { 1745ce736788SJoao Pinto struct sk_buff *skb = tx_q->tx_skbuff[entry]; 1746c24602efSGiuseppe CAVALLARO struct dma_desc *p; 1747c363b658SFabrice Gasnier int status; 1748c24602efSGiuseppe CAVALLARO 1749c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1750ce736788SJoao Pinto p = (struct dma_desc *)(tx_q->dma_etx + entry); 1751c24602efSGiuseppe CAVALLARO else 1752ce736788SJoao Pinto p = tx_q->dma_tx + entry; 17537ac6653aSJeff Kirsher 1754c363b658SFabrice Gasnier status = priv->hw->desc->tx_status(&priv->dev->stats, 17557ac6653aSJeff Kirsher &priv->xstats, p, 17567ac6653aSJeff Kirsher priv->ioaddr); 1757c363b658SFabrice Gasnier /* Check if the descriptor is owned by the DMA */ 1758c363b658SFabrice Gasnier if (unlikely(status & tx_dma_own)) 1759c363b658SFabrice Gasnier break; 1760c363b658SFabrice Gasnier 1761c363b658SFabrice Gasnier /* Just consider the last segment and ...*/ 1762c363b658SFabrice Gasnier if (likely(!(status & tx_not_ls))) { 1763c363b658SFabrice Gasnier /* ... verify the status error condition */ 1764c363b658SFabrice Gasnier if (unlikely(status & tx_err)) { 1765c363b658SFabrice Gasnier priv->dev->stats.tx_errors++; 1766c363b658SFabrice Gasnier } else { 17677ac6653aSJeff Kirsher priv->dev->stats.tx_packets++; 17687ac6653aSJeff Kirsher priv->xstats.tx_pkt_n++; 1769c363b658SFabrice Gasnier } 1770ba1ffd74SGiuseppe CAVALLARO stmmac_get_tx_hwtstamp(priv, p, skb); 17717ac6653aSJeff Kirsher } 17727ac6653aSJeff Kirsher 1773ce736788SJoao Pinto if (likely(tx_q->tx_skbuff_dma[entry].buf)) { 1774ce736788SJoao Pinto if (tx_q->tx_skbuff_dma[entry].map_as_page) 1775362b37beSGiuseppe CAVALLARO dma_unmap_page(priv->device, 1776ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].buf, 1777ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].len, 17787ac6653aSJeff Kirsher DMA_TO_DEVICE); 1779362b37beSGiuseppe CAVALLARO else 1780362b37beSGiuseppe CAVALLARO dma_unmap_single(priv->device, 1781ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].buf, 1782ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].len, 1783362b37beSGiuseppe CAVALLARO DMA_TO_DEVICE); 1784ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].buf = 0; 1785ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].len = 0; 1786ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].map_as_page = false; 1787cf32deecSRayagond Kokatanur } 1788f748be53SAlexandre TORGUE 1789f748be53SAlexandre TORGUE if (priv->hw->mode->clean_desc3) 1790ce736788SJoao Pinto priv->hw->mode->clean_desc3(tx_q, p); 1791f748be53SAlexandre TORGUE 1792ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].last_segment = false; 1793ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].is_jumbo = false; 17947ac6653aSJeff Kirsher 17957ac6653aSJeff Kirsher if (likely(skb != NULL)) { 179638979574SBeniamino Galvani pkts_compl++; 179738979574SBeniamino Galvani bytes_compl += skb->len; 17987c565c33SEric W. Biederman dev_consume_skb_any(skb); 1799ce736788SJoao Pinto tx_q->tx_skbuff[entry] = NULL; 18007ac6653aSJeff Kirsher } 18017ac6653aSJeff Kirsher 18024a7d666aSGiuseppe CAVALLARO priv->hw->desc->release_tx_desc(p, priv->mode); 18037ac6653aSJeff Kirsher 1804e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); 18057ac6653aSJeff Kirsher } 1806ce736788SJoao Pinto tx_q->dirty_tx = entry; 180738979574SBeniamino Galvani 18085bacd778SLABBE Corentin netdev_completed_queue(priv->dev, pkts_compl, bytes_compl); 180938979574SBeniamino Galvani 18105bacd778SLABBE Corentin if (unlikely(netif_queue_stopped(priv->dev) && 1811ce736788SJoao Pinto stmmac_tx_avail(priv, queue) > STMMAC_TX_THRESH)) { 1812b3e51069SLABBE Corentin netif_dbg(priv, tx_done, priv->dev, 1813b3e51069SLABBE Corentin "%s: restart transmit\n", __func__); 18145bacd778SLABBE Corentin netif_wake_queue(priv->dev); 18157ac6653aSJeff Kirsher } 1816d765955dSGiuseppe CAVALLARO 1817d765955dSGiuseppe CAVALLARO if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) { 1818d765955dSGiuseppe CAVALLARO stmmac_enable_eee_mode(priv); 1819f5351ef7SGiuseppe CAVALLARO mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); 1820d765955dSGiuseppe CAVALLARO } 1821739c8e14SLino Sanfilippo netif_tx_unlock(priv->dev); 18227ac6653aSJeff Kirsher } 18237ac6653aSJeff Kirsher 18244f513ecdSJoao Pinto static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv, u32 chan) 18257ac6653aSJeff Kirsher { 18264f513ecdSJoao Pinto priv->hw->dma->enable_dma_irq(priv->ioaddr, chan); 18277ac6653aSJeff Kirsher } 18287ac6653aSJeff Kirsher 18294f513ecdSJoao Pinto static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv, u32 chan) 18307ac6653aSJeff Kirsher { 18314f513ecdSJoao Pinto priv->hw->dma->disable_dma_irq(priv->ioaddr, chan); 18327ac6653aSJeff Kirsher } 18337ac6653aSJeff Kirsher 18347ac6653aSJeff Kirsher /** 1835732fdf0eSGiuseppe CAVALLARO * stmmac_tx_err - to manage the tx error 183632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 18375bacd778SLABBE Corentin * @chan: channel index 18387ac6653aSJeff Kirsher * Description: it cleans the descriptors and restarts the transmission 1839732fdf0eSGiuseppe CAVALLARO * in case of transmission errors. 18407ac6653aSJeff Kirsher */ 18415bacd778SLABBE Corentin static void stmmac_tx_err(struct stmmac_priv *priv, u32 chan) 18427ac6653aSJeff Kirsher { 1843ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[chan]; 1844c24602efSGiuseppe CAVALLARO int i; 1845ce736788SJoao Pinto 18465bacd778SLABBE Corentin netif_stop_queue(priv->dev); 18477ac6653aSJeff Kirsher 1848ae4f0d46SJoao Pinto stmmac_stop_tx_dma(priv, chan); 1849ce736788SJoao Pinto dma_free_tx_skbufs(priv, chan); 1850e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_TX_SIZE; i++) 1851c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1852ce736788SJoao Pinto priv->hw->desc->init_tx_desc(&tx_q->dma_etx[i].basic, 1853c24602efSGiuseppe CAVALLARO priv->mode, 1854e3ad57c9SGiuseppe Cavallaro (i == DMA_TX_SIZE - 1)); 1855c24602efSGiuseppe CAVALLARO else 1856ce736788SJoao Pinto priv->hw->desc->init_tx_desc(&tx_q->dma_tx[i], 1857c24602efSGiuseppe CAVALLARO priv->mode, 1858e3ad57c9SGiuseppe Cavallaro (i == DMA_TX_SIZE - 1)); 1859ce736788SJoao Pinto tx_q->dirty_tx = 0; 1860ce736788SJoao Pinto tx_q->cur_tx = 0; 18615bacd778SLABBE Corentin netdev_reset_queue(priv->dev); 1862ae4f0d46SJoao Pinto stmmac_start_tx_dma(priv, chan); 18637ac6653aSJeff Kirsher 18647ac6653aSJeff Kirsher priv->dev->stats.tx_errors++; 18655bacd778SLABBE Corentin netif_wake_queue(priv->dev); 18667ac6653aSJeff Kirsher } 18677ac6653aSJeff Kirsher 186832ceabcaSGiuseppe CAVALLARO /** 18696deee222SJoao Pinto * stmmac_set_dma_operation_mode - Set DMA operation mode by channel 18706deee222SJoao Pinto * @priv: driver private structure 18716deee222SJoao Pinto * @txmode: TX operating mode 18726deee222SJoao Pinto * @rxmode: RX operating mode 18736deee222SJoao Pinto * @chan: channel index 18746deee222SJoao Pinto * Description: it is used for configuring of the DMA operation mode in 18756deee222SJoao Pinto * runtime in order to program the tx/rx DMA thresholds or Store-And-Forward 18766deee222SJoao Pinto * mode. 18776deee222SJoao Pinto */ 18786deee222SJoao Pinto static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode, 18796deee222SJoao Pinto u32 rxmode, u32 chan) 18806deee222SJoao Pinto { 18816deee222SJoao Pinto int rxfifosz = priv->plat->rx_fifo_size; 18826deee222SJoao Pinto 18836deee222SJoao Pinto if (rxfifosz == 0) 18846deee222SJoao Pinto rxfifosz = priv->dma_cap.rx_fifo_size; 18856deee222SJoao Pinto 18866deee222SJoao Pinto if (priv->synopsys_id >= DWMAC_CORE_4_00) { 18876deee222SJoao Pinto priv->hw->dma->dma_rx_mode(priv->ioaddr, rxmode, chan, 18886deee222SJoao Pinto rxfifosz); 18896deee222SJoao Pinto priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan); 18906deee222SJoao Pinto } else { 18916deee222SJoao Pinto priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode, 18926deee222SJoao Pinto rxfifosz); 18936deee222SJoao Pinto } 18946deee222SJoao Pinto } 18956deee222SJoao Pinto 18966deee222SJoao Pinto /** 1897732fdf0eSGiuseppe CAVALLARO * stmmac_dma_interrupt - DMA ISR 189832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 189932ceabcaSGiuseppe CAVALLARO * Description: this is the DMA ISR. It is called by the main ISR. 1900732fdf0eSGiuseppe CAVALLARO * It calls the dwmac dma routine and schedule poll method in case of some 1901732fdf0eSGiuseppe CAVALLARO * work can be done. 190232ceabcaSGiuseppe CAVALLARO */ 19037ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv) 19047ac6653aSJeff Kirsher { 1905d62a107aSJoao Pinto u32 tx_channel_count = priv->plat->tx_queues_to_use; 19067ac6653aSJeff Kirsher int status; 1907d62a107aSJoao Pinto u32 chan; 190868e5cfafSJoao Pinto 1909d62a107aSJoao Pinto for (chan = 0; chan < tx_channel_count; chan++) { 1910d62a107aSJoao Pinto status = priv->hw->dma->dma_interrupt(priv->ioaddr, 1911d62a107aSJoao Pinto &priv->xstats, chan); 19129125cdd1SGiuseppe CAVALLARO if (likely((status & handle_rx)) || (status & handle_tx)) { 19135bacd778SLABBE Corentin if (likely(napi_schedule_prep(&priv->napi))) { 19144f513ecdSJoao Pinto stmmac_disable_dma_irq(priv, chan); 19155bacd778SLABBE Corentin __napi_schedule(&priv->napi); 19169125cdd1SGiuseppe CAVALLARO } 19179125cdd1SGiuseppe CAVALLARO } 1918d62a107aSJoao Pinto 19199125cdd1SGiuseppe CAVALLARO if (unlikely(status & tx_hard_error_bump_tc)) { 19207ac6653aSJeff Kirsher /* Try to bump up the dma threshold on this failure */ 1921b2dec116SSonic Zhang if (unlikely(priv->xstats.threshold != SF_DMA_MODE) && 1922b2dec116SSonic Zhang (tc <= 256)) { 19237ac6653aSJeff Kirsher tc += 64; 1924c405abe2SSonic Zhang if (priv->plat->force_thresh_dma_mode) 1925d62a107aSJoao Pinto stmmac_set_dma_operation_mode(priv, 1926d62a107aSJoao Pinto tc, 1927d62a107aSJoao Pinto tc, 1928d62a107aSJoao Pinto chan); 1929c405abe2SSonic Zhang else 1930d62a107aSJoao Pinto stmmac_set_dma_operation_mode(priv, 1931d62a107aSJoao Pinto tc, 1932d62a107aSJoao Pinto SF_DMA_MODE, 1933d62a107aSJoao Pinto chan); 19347ac6653aSJeff Kirsher priv->xstats.threshold = tc; 19357ac6653aSJeff Kirsher } 1936d62a107aSJoao Pinto } else if (unlikely(status == tx_hard_error)) { 19374e593262SJoao Pinto stmmac_tx_err(priv, chan); 19387ac6653aSJeff Kirsher } 1939d62a107aSJoao Pinto } 1940d62a107aSJoao Pinto } 19417ac6653aSJeff Kirsher 194232ceabcaSGiuseppe CAVALLARO /** 194332ceabcaSGiuseppe CAVALLARO * stmmac_mmc_setup: setup the Mac Management Counters (MMC) 194432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 194532ceabcaSGiuseppe CAVALLARO * Description: this masks the MMC irq, in fact, the counters are managed in SW. 194632ceabcaSGiuseppe CAVALLARO */ 19471c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv) 19481c901a46SGiuseppe CAVALLARO { 19491c901a46SGiuseppe CAVALLARO unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET | 19501c901a46SGiuseppe CAVALLARO MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET; 19511c901a46SGiuseppe CAVALLARO 1952ba1ffd74SGiuseppe CAVALLARO if (priv->synopsys_id >= DWMAC_CORE_4_00) { 1953ba1ffd74SGiuseppe CAVALLARO priv->ptpaddr = priv->ioaddr + PTP_GMAC4_OFFSET; 1954f748be53SAlexandre TORGUE priv->mmcaddr = priv->ioaddr + MMC_GMAC4_OFFSET; 1955ba1ffd74SGiuseppe CAVALLARO } else { 1956ba1ffd74SGiuseppe CAVALLARO priv->ptpaddr = priv->ioaddr + PTP_GMAC3_X_OFFSET; 195736ff7c1eSAlexandre TORGUE priv->mmcaddr = priv->ioaddr + MMC_GMAC3_X_OFFSET; 1958ba1ffd74SGiuseppe CAVALLARO } 195936ff7c1eSAlexandre TORGUE 196036ff7c1eSAlexandre TORGUE dwmac_mmc_intr_all_mask(priv->mmcaddr); 19614f795b25SGiuseppe CAVALLARO 19624f795b25SGiuseppe CAVALLARO if (priv->dma_cap.rmon) { 196336ff7c1eSAlexandre TORGUE dwmac_mmc_ctrl(priv->mmcaddr, mode); 19641c901a46SGiuseppe CAVALLARO memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); 19654f795b25SGiuseppe CAVALLARO } else 196638ddc59dSLABBE Corentin netdev_info(priv->dev, "No MAC Management Counters available\n"); 19671c901a46SGiuseppe CAVALLARO } 19681c901a46SGiuseppe CAVALLARO 1969732fdf0eSGiuseppe CAVALLARO /** 1970732fdf0eSGiuseppe CAVALLARO * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors 197132ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 197232ceabcaSGiuseppe CAVALLARO * Description: select the Enhanced/Alternate or Normal descriptors. 1973732fdf0eSGiuseppe CAVALLARO * In case of Enhanced/Alternate, it checks if the extended descriptors are 1974732fdf0eSGiuseppe CAVALLARO * supported by the HW capability register. 1975ff3dd78cSGiuseppe CAVALLARO */ 197619e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv) 197719e30c14SGiuseppe CAVALLARO { 197819e30c14SGiuseppe CAVALLARO if (priv->plat->enh_desc) { 197938ddc59dSLABBE Corentin dev_info(priv->device, "Enhanced/Alternate descriptors\n"); 1980c24602efSGiuseppe CAVALLARO 1981c24602efSGiuseppe CAVALLARO /* GMAC older than 3.50 has no extended descriptors */ 1982c24602efSGiuseppe CAVALLARO if (priv->synopsys_id >= DWMAC_CORE_3_50) { 198338ddc59dSLABBE Corentin dev_info(priv->device, "Enabled extended descriptors\n"); 1984c24602efSGiuseppe CAVALLARO priv->extend_desc = 1; 1985c24602efSGiuseppe CAVALLARO } else 198638ddc59dSLABBE Corentin dev_warn(priv->device, "Extended descriptors not supported\n"); 1987c24602efSGiuseppe CAVALLARO 198819e30c14SGiuseppe CAVALLARO priv->hw->desc = &enh_desc_ops; 198919e30c14SGiuseppe CAVALLARO } else { 199038ddc59dSLABBE Corentin dev_info(priv->device, "Normal descriptors\n"); 199119e30c14SGiuseppe CAVALLARO priv->hw->desc = &ndesc_ops; 199219e30c14SGiuseppe CAVALLARO } 199319e30c14SGiuseppe CAVALLARO } 199419e30c14SGiuseppe CAVALLARO 199519e30c14SGiuseppe CAVALLARO /** 1996732fdf0eSGiuseppe CAVALLARO * stmmac_get_hw_features - get MAC capabilities from the HW cap. register. 199732ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 199819e30c14SGiuseppe CAVALLARO * Description: 199919e30c14SGiuseppe CAVALLARO * new GMAC chip generations have a new register to indicate the 2000e7434821SGiuseppe CAVALLARO * presence of the optional feature/functions. 200119e30c14SGiuseppe CAVALLARO * This can be also used to override the value passed through the 200219e30c14SGiuseppe CAVALLARO * platform and necessary for old MAC10/100 and GMAC chips. 2003e7434821SGiuseppe CAVALLARO */ 2004e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv) 2005e7434821SGiuseppe CAVALLARO { 2006f10a6a35SAlexandre TORGUE u32 ret = 0; 20073c20f72fSGiuseppe CAVALLARO 20085e6efe88SGiuseppe CAVALLARO if (priv->hw->dma->get_hw_feature) { 2009f10a6a35SAlexandre TORGUE priv->hw->dma->get_hw_feature(priv->ioaddr, 2010f10a6a35SAlexandre TORGUE &priv->dma_cap); 2011f10a6a35SAlexandre TORGUE ret = 1; 201219e30c14SGiuseppe CAVALLARO } 2013e7434821SGiuseppe CAVALLARO 2014f10a6a35SAlexandre TORGUE return ret; 2015e7434821SGiuseppe CAVALLARO } 2016e7434821SGiuseppe CAVALLARO 201732ceabcaSGiuseppe CAVALLARO /** 2018732fdf0eSGiuseppe CAVALLARO * stmmac_check_ether_addr - check if the MAC addr is valid 201932ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 202032ceabcaSGiuseppe CAVALLARO * Description: 202132ceabcaSGiuseppe CAVALLARO * it is to verify if the MAC address is valid, in case of failures it 202232ceabcaSGiuseppe CAVALLARO * generates a random MAC address 202332ceabcaSGiuseppe CAVALLARO */ 2024bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv) 2025bfab27a1SGiuseppe CAVALLARO { 2026bfab27a1SGiuseppe CAVALLARO if (!is_valid_ether_addr(priv->dev->dev_addr)) { 20277ed24bbeSVince Bridgers priv->hw->mac->get_umac_addr(priv->hw, 2028bfab27a1SGiuseppe CAVALLARO priv->dev->dev_addr, 0); 2029bfab27a1SGiuseppe CAVALLARO if (!is_valid_ether_addr(priv->dev->dev_addr)) 2030f2cedb63SDanny Kukawka eth_hw_addr_random(priv->dev); 203138ddc59dSLABBE Corentin netdev_info(priv->dev, "device MAC address %pM\n", 2032bfab27a1SGiuseppe CAVALLARO priv->dev->dev_addr); 2033bfab27a1SGiuseppe CAVALLARO } 2034c88460b7SHans de Goede } 2035bfab27a1SGiuseppe CAVALLARO 203632ceabcaSGiuseppe CAVALLARO /** 2037732fdf0eSGiuseppe CAVALLARO * stmmac_init_dma_engine - DMA init. 203832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 203932ceabcaSGiuseppe CAVALLARO * Description: 204032ceabcaSGiuseppe CAVALLARO * It inits the DMA invoking the specific MAC/GMAC callback. 204132ceabcaSGiuseppe CAVALLARO * Some DMA parameters can be passed from the platform; 204232ceabcaSGiuseppe CAVALLARO * in case of these are not passed a default is kept for the MAC or GMAC. 204332ceabcaSGiuseppe CAVALLARO */ 20440f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv) 20450f1f88a8SGiuseppe CAVALLARO { 204647f2a9ceSJoao Pinto u32 rx_channels_count = priv->plat->rx_queues_to_use; 204747f2a9ceSJoao Pinto u32 tx_channels_count = priv->plat->tx_queues_to_use; 204854139cf3SJoao Pinto struct stmmac_rx_queue *rx_q; 2049ce736788SJoao Pinto struct stmmac_tx_queue *tx_q; 205047f2a9ceSJoao Pinto u32 dummy_dma_rx_phy = 0; 205147f2a9ceSJoao Pinto u32 dummy_dma_tx_phy = 0; 205247f2a9ceSJoao Pinto u32 chan = 0; 2053c24602efSGiuseppe CAVALLARO int atds = 0; 2054495db273SGiuseppe Cavallaro int ret = 0; 20550f1f88a8SGiuseppe CAVALLARO 2056a332e2faSNiklas Cassel if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) { 2057a332e2faSNiklas Cassel dev_err(priv->device, "Invalid DMA configuration\n"); 205889ab75bfSNiklas Cassel return -EINVAL; 20590f1f88a8SGiuseppe CAVALLARO } 20600f1f88a8SGiuseppe CAVALLARO 2061c24602efSGiuseppe CAVALLARO if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE)) 2062c24602efSGiuseppe CAVALLARO atds = 1; 2063c24602efSGiuseppe CAVALLARO 2064495db273SGiuseppe Cavallaro ret = priv->hw->dma->reset(priv->ioaddr); 2065495db273SGiuseppe Cavallaro if (ret) { 2066495db273SGiuseppe Cavallaro dev_err(priv->device, "Failed to reset the dma\n"); 2067495db273SGiuseppe Cavallaro return ret; 2068495db273SGiuseppe Cavallaro } 2069495db273SGiuseppe Cavallaro 2070f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) { 207147f2a9ceSJoao Pinto /* DMA Configuration */ 207247f2a9ceSJoao Pinto priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg, 207347f2a9ceSJoao Pinto dummy_dma_tx_phy, dummy_dma_rx_phy, atds); 207447f2a9ceSJoao Pinto 207547f2a9ceSJoao Pinto /* DMA RX Channel Configuration */ 207647f2a9ceSJoao Pinto for (chan = 0; chan < rx_channels_count; chan++) { 207754139cf3SJoao Pinto rx_q = &priv->rx_queue[chan]; 207854139cf3SJoao Pinto 207947f2a9ceSJoao Pinto priv->hw->dma->init_rx_chan(priv->ioaddr, 208047f2a9ceSJoao Pinto priv->plat->dma_cfg, 208154139cf3SJoao Pinto rx_q->dma_rx_phy, chan); 208247f2a9ceSJoao Pinto 208354139cf3SJoao Pinto rx_q->rx_tail_addr = rx_q->dma_rx_phy + 2084f748be53SAlexandre TORGUE (DMA_RX_SIZE * sizeof(struct dma_desc)); 208547f2a9ceSJoao Pinto priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, 208654139cf3SJoao Pinto rx_q->rx_tail_addr, 208747f2a9ceSJoao Pinto chan); 208847f2a9ceSJoao Pinto } 208947f2a9ceSJoao Pinto 209047f2a9ceSJoao Pinto /* DMA TX Channel Configuration */ 209147f2a9ceSJoao Pinto for (chan = 0; chan < tx_channels_count; chan++) { 2092ce736788SJoao Pinto tx_q = &priv->tx_queue[chan]; 2093ce736788SJoao Pinto 209447f2a9ceSJoao Pinto priv->hw->dma->init_chan(priv->ioaddr, 209547f2a9ceSJoao Pinto priv->plat->dma_cfg, 209647f2a9ceSJoao Pinto chan); 209747f2a9ceSJoao Pinto 209847f2a9ceSJoao Pinto priv->hw->dma->init_tx_chan(priv->ioaddr, 209947f2a9ceSJoao Pinto priv->plat->dma_cfg, 2100ce736788SJoao Pinto tx_q->dma_tx_phy, chan); 2101f748be53SAlexandre TORGUE 2102ce736788SJoao Pinto tx_q->tx_tail_addr = tx_q->dma_tx_phy + 2103f748be53SAlexandre TORGUE (DMA_TX_SIZE * sizeof(struct dma_desc)); 210447f2a9ceSJoao Pinto priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, 2105ce736788SJoao Pinto tx_q->tx_tail_addr, 210647f2a9ceSJoao Pinto chan); 210747f2a9ceSJoao Pinto } 210847f2a9ceSJoao Pinto } else { 210954139cf3SJoao Pinto rx_q = &priv->rx_queue[chan]; 2110ce736788SJoao Pinto tx_q = &priv->tx_queue[chan]; 211147f2a9ceSJoao Pinto priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg, 2112ce736788SJoao Pinto tx_q->dma_tx_phy, rx_q->dma_rx_phy, atds); 2113f748be53SAlexandre TORGUE } 2114f748be53SAlexandre TORGUE 2115f748be53SAlexandre TORGUE if (priv->plat->axi && priv->hw->dma->axi) 2116afea0365SGiuseppe Cavallaro priv->hw->dma->axi(priv->ioaddr, priv->plat->axi); 2117afea0365SGiuseppe Cavallaro 2118495db273SGiuseppe Cavallaro return ret; 21190f1f88a8SGiuseppe CAVALLARO } 21200f1f88a8SGiuseppe CAVALLARO 2121bfab27a1SGiuseppe CAVALLARO /** 2122732fdf0eSGiuseppe CAVALLARO * stmmac_tx_timer - mitigation sw timer for tx. 21239125cdd1SGiuseppe CAVALLARO * @data: data pointer 21249125cdd1SGiuseppe CAVALLARO * Description: 21259125cdd1SGiuseppe CAVALLARO * This is the timer handler to directly invoke the stmmac_tx_clean. 21269125cdd1SGiuseppe CAVALLARO */ 21279125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data) 21289125cdd1SGiuseppe CAVALLARO { 21299125cdd1SGiuseppe CAVALLARO struct stmmac_priv *priv = (struct stmmac_priv *)data; 2130ce736788SJoao Pinto u32 tx_queues_count = priv->plat->tx_queues_to_use; 2131ce736788SJoao Pinto u32 queue; 21329125cdd1SGiuseppe CAVALLARO 2133ce736788SJoao Pinto /* let's scan all the tx queues */ 2134ce736788SJoao Pinto for (queue = 0; queue < tx_queues_count; queue++) 2135ce736788SJoao Pinto stmmac_tx_clean(priv, queue); 21369125cdd1SGiuseppe CAVALLARO } 21379125cdd1SGiuseppe CAVALLARO 21389125cdd1SGiuseppe CAVALLARO /** 2139732fdf0eSGiuseppe CAVALLARO * stmmac_init_tx_coalesce - init tx mitigation options. 214032ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 21419125cdd1SGiuseppe CAVALLARO * Description: 21429125cdd1SGiuseppe CAVALLARO * This inits the transmit coalesce parameters: i.e. timer rate, 21439125cdd1SGiuseppe CAVALLARO * timer handler and default threshold used for enabling the 21449125cdd1SGiuseppe CAVALLARO * interrupt on completion bit. 21459125cdd1SGiuseppe CAVALLARO */ 21469125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) 21479125cdd1SGiuseppe CAVALLARO { 21489125cdd1SGiuseppe CAVALLARO priv->tx_coal_frames = STMMAC_TX_FRAMES; 21499125cdd1SGiuseppe CAVALLARO priv->tx_coal_timer = STMMAC_COAL_TX_TIMER; 21509125cdd1SGiuseppe CAVALLARO init_timer(&priv->txtimer); 21519125cdd1SGiuseppe CAVALLARO priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer); 21529125cdd1SGiuseppe CAVALLARO priv->txtimer.data = (unsigned long)priv; 21539125cdd1SGiuseppe CAVALLARO priv->txtimer.function = stmmac_tx_timer; 21549125cdd1SGiuseppe CAVALLARO add_timer(&priv->txtimer); 21559125cdd1SGiuseppe CAVALLARO } 21569125cdd1SGiuseppe CAVALLARO 21574854ab99SJoao Pinto static void stmmac_set_rings_length(struct stmmac_priv *priv) 21584854ab99SJoao Pinto { 21594854ab99SJoao Pinto u32 rx_channels_count = priv->plat->rx_queues_to_use; 21604854ab99SJoao Pinto u32 tx_channels_count = priv->plat->tx_queues_to_use; 21614854ab99SJoao Pinto u32 chan; 21624854ab99SJoao Pinto 21634854ab99SJoao Pinto /* set TX ring length */ 21644854ab99SJoao Pinto if (priv->hw->dma->set_tx_ring_len) { 21654854ab99SJoao Pinto for (chan = 0; chan < tx_channels_count; chan++) 21664854ab99SJoao Pinto priv->hw->dma->set_tx_ring_len(priv->ioaddr, 21674854ab99SJoao Pinto (DMA_TX_SIZE - 1), chan); 21684854ab99SJoao Pinto } 21694854ab99SJoao Pinto 21704854ab99SJoao Pinto /* set RX ring length */ 21714854ab99SJoao Pinto if (priv->hw->dma->set_rx_ring_len) { 21724854ab99SJoao Pinto for (chan = 0; chan < rx_channels_count; chan++) 21734854ab99SJoao Pinto priv->hw->dma->set_rx_ring_len(priv->ioaddr, 21744854ab99SJoao Pinto (DMA_RX_SIZE - 1), chan); 21754854ab99SJoao Pinto } 21764854ab99SJoao Pinto } 21774854ab99SJoao Pinto 21789125cdd1SGiuseppe CAVALLARO /** 21796a3a7193SJoao Pinto * stmmac_set_tx_queue_weight - Set TX queue weight 21806a3a7193SJoao Pinto * @priv: driver private structure 21816a3a7193SJoao Pinto * Description: It is used for setting TX queues weight 21826a3a7193SJoao Pinto */ 21836a3a7193SJoao Pinto static void stmmac_set_tx_queue_weight(struct stmmac_priv *priv) 21846a3a7193SJoao Pinto { 21856a3a7193SJoao Pinto u32 tx_queues_count = priv->plat->tx_queues_to_use; 21866a3a7193SJoao Pinto u32 weight; 21876a3a7193SJoao Pinto u32 queue; 21886a3a7193SJoao Pinto 21896a3a7193SJoao Pinto for (queue = 0; queue < tx_queues_count; queue++) { 21906a3a7193SJoao Pinto weight = priv->plat->tx_queues_cfg[queue].weight; 21916a3a7193SJoao Pinto priv->hw->mac->set_mtl_tx_queue_weight(priv->hw, weight, queue); 21926a3a7193SJoao Pinto } 21936a3a7193SJoao Pinto } 21946a3a7193SJoao Pinto 21956a3a7193SJoao Pinto /** 219619d91873SJoao Pinto * stmmac_configure_cbs - Configure CBS in TX queue 219719d91873SJoao Pinto * @priv: driver private structure 219819d91873SJoao Pinto * Description: It is used for configuring CBS in AVB TX queues 219919d91873SJoao Pinto */ 220019d91873SJoao Pinto static void stmmac_configure_cbs(struct stmmac_priv *priv) 220119d91873SJoao Pinto { 220219d91873SJoao Pinto u32 tx_queues_count = priv->plat->tx_queues_to_use; 220319d91873SJoao Pinto u32 mode_to_use; 220419d91873SJoao Pinto u32 queue; 220519d91873SJoao Pinto 220644781fefSJoao Pinto /* queue 0 is reserved for legacy traffic */ 220744781fefSJoao Pinto for (queue = 1; queue < tx_queues_count; queue++) { 220819d91873SJoao Pinto mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use; 220919d91873SJoao Pinto if (mode_to_use == MTL_QUEUE_DCB) 221019d91873SJoao Pinto continue; 221119d91873SJoao Pinto 221219d91873SJoao Pinto priv->hw->mac->config_cbs(priv->hw, 221319d91873SJoao Pinto priv->plat->tx_queues_cfg[queue].send_slope, 221419d91873SJoao Pinto priv->plat->tx_queues_cfg[queue].idle_slope, 221519d91873SJoao Pinto priv->plat->tx_queues_cfg[queue].high_credit, 221619d91873SJoao Pinto priv->plat->tx_queues_cfg[queue].low_credit, 221719d91873SJoao Pinto queue); 221819d91873SJoao Pinto } 221919d91873SJoao Pinto } 222019d91873SJoao Pinto 222119d91873SJoao Pinto /** 2222d43042f4SJoao Pinto * stmmac_rx_queue_dma_chan_map - Map RX queue to RX dma channel 2223d43042f4SJoao Pinto * @priv: driver private structure 2224d43042f4SJoao Pinto * Description: It is used for mapping RX queues to RX dma channels 2225d43042f4SJoao Pinto */ 2226d43042f4SJoao Pinto static void stmmac_rx_queue_dma_chan_map(struct stmmac_priv *priv) 2227d43042f4SJoao Pinto { 2228d43042f4SJoao Pinto u32 rx_queues_count = priv->plat->rx_queues_to_use; 2229d43042f4SJoao Pinto u32 queue; 2230d43042f4SJoao Pinto u32 chan; 2231d43042f4SJoao Pinto 2232d43042f4SJoao Pinto for (queue = 0; queue < rx_queues_count; queue++) { 2233d43042f4SJoao Pinto chan = priv->plat->rx_queues_cfg[queue].chan; 2234d43042f4SJoao Pinto priv->hw->mac->map_mtl_to_dma(priv->hw, queue, chan); 2235d43042f4SJoao Pinto } 2236d43042f4SJoao Pinto } 2237d43042f4SJoao Pinto 2238d43042f4SJoao Pinto /** 2239a8f5102aSJoao Pinto * stmmac_mac_config_rx_queues_prio - Configure RX Queue priority 2240a8f5102aSJoao Pinto * @priv: driver private structure 2241a8f5102aSJoao Pinto * Description: It is used for configuring the RX Queue Priority 2242a8f5102aSJoao Pinto */ 2243a8f5102aSJoao Pinto static void stmmac_mac_config_rx_queues_prio(struct stmmac_priv *priv) 2244a8f5102aSJoao Pinto { 2245a8f5102aSJoao Pinto u32 rx_queues_count = priv->plat->rx_queues_to_use; 2246a8f5102aSJoao Pinto u32 queue; 2247a8f5102aSJoao Pinto u32 prio; 2248a8f5102aSJoao Pinto 2249a8f5102aSJoao Pinto for (queue = 0; queue < rx_queues_count; queue++) { 2250a8f5102aSJoao Pinto if (!priv->plat->rx_queues_cfg[queue].use_prio) 2251a8f5102aSJoao Pinto continue; 2252a8f5102aSJoao Pinto 2253a8f5102aSJoao Pinto prio = priv->plat->rx_queues_cfg[queue].prio; 2254a8f5102aSJoao Pinto priv->hw->mac->rx_queue_prio(priv->hw, prio, queue); 2255a8f5102aSJoao Pinto } 2256a8f5102aSJoao Pinto } 2257a8f5102aSJoao Pinto 2258a8f5102aSJoao Pinto /** 2259a8f5102aSJoao Pinto * stmmac_mac_config_tx_queues_prio - Configure TX Queue priority 2260a8f5102aSJoao Pinto * @priv: driver private structure 2261a8f5102aSJoao Pinto * Description: It is used for configuring the TX Queue Priority 2262a8f5102aSJoao Pinto */ 2263a8f5102aSJoao Pinto static void stmmac_mac_config_tx_queues_prio(struct stmmac_priv *priv) 2264a8f5102aSJoao Pinto { 2265a8f5102aSJoao Pinto u32 tx_queues_count = priv->plat->tx_queues_to_use; 2266a8f5102aSJoao Pinto u32 queue; 2267a8f5102aSJoao Pinto u32 prio; 2268a8f5102aSJoao Pinto 2269a8f5102aSJoao Pinto for (queue = 0; queue < tx_queues_count; queue++) { 2270a8f5102aSJoao Pinto if (!priv->plat->tx_queues_cfg[queue].use_prio) 2271a8f5102aSJoao Pinto continue; 2272a8f5102aSJoao Pinto 2273a8f5102aSJoao Pinto prio = priv->plat->tx_queues_cfg[queue].prio; 2274a8f5102aSJoao Pinto priv->hw->mac->tx_queue_prio(priv->hw, prio, queue); 2275a8f5102aSJoao Pinto } 2276a8f5102aSJoao Pinto } 2277a8f5102aSJoao Pinto 2278a8f5102aSJoao Pinto /** 2279abe80fdcSJoao Pinto * stmmac_mac_config_rx_queues_routing - Configure RX Queue Routing 2280abe80fdcSJoao Pinto * @priv: driver private structure 2281abe80fdcSJoao Pinto * Description: It is used for configuring the RX queue routing 2282abe80fdcSJoao Pinto */ 2283abe80fdcSJoao Pinto static void stmmac_mac_config_rx_queues_routing(struct stmmac_priv *priv) 2284abe80fdcSJoao Pinto { 2285abe80fdcSJoao Pinto u32 rx_queues_count = priv->plat->rx_queues_to_use; 2286abe80fdcSJoao Pinto u32 queue; 2287abe80fdcSJoao Pinto u8 packet; 2288abe80fdcSJoao Pinto 2289abe80fdcSJoao Pinto for (queue = 0; queue < rx_queues_count; queue++) { 2290abe80fdcSJoao Pinto /* no specific packet type routing specified for the queue */ 2291abe80fdcSJoao Pinto if (priv->plat->rx_queues_cfg[queue].pkt_route == 0x0) 2292abe80fdcSJoao Pinto continue; 2293abe80fdcSJoao Pinto 2294abe80fdcSJoao Pinto packet = priv->plat->rx_queues_cfg[queue].pkt_route; 2295abe80fdcSJoao Pinto priv->hw->mac->rx_queue_prio(priv->hw, packet, queue); 2296abe80fdcSJoao Pinto } 2297abe80fdcSJoao Pinto } 2298abe80fdcSJoao Pinto 2299abe80fdcSJoao Pinto /** 2300d0a9c9f9SJoao Pinto * stmmac_mtl_configuration - Configure MTL 2301d0a9c9f9SJoao Pinto * @priv: driver private structure 2302d0a9c9f9SJoao Pinto * Description: It is used for configurring MTL 2303d0a9c9f9SJoao Pinto */ 2304d0a9c9f9SJoao Pinto static void stmmac_mtl_configuration(struct stmmac_priv *priv) 2305d0a9c9f9SJoao Pinto { 2306d0a9c9f9SJoao Pinto u32 rx_queues_count = priv->plat->rx_queues_to_use; 2307d0a9c9f9SJoao Pinto u32 tx_queues_count = priv->plat->tx_queues_to_use; 2308d0a9c9f9SJoao Pinto 23096a3a7193SJoao Pinto if (tx_queues_count > 1 && priv->hw->mac->set_mtl_tx_queue_weight) 23106a3a7193SJoao Pinto stmmac_set_tx_queue_weight(priv); 23116a3a7193SJoao Pinto 2312d0a9c9f9SJoao Pinto /* Configure MTL RX algorithms */ 2313d0a9c9f9SJoao Pinto if (rx_queues_count > 1 && priv->hw->mac->prog_mtl_rx_algorithms) 2314d0a9c9f9SJoao Pinto priv->hw->mac->prog_mtl_rx_algorithms(priv->hw, 2315d0a9c9f9SJoao Pinto priv->plat->rx_sched_algorithm); 2316d0a9c9f9SJoao Pinto 2317d0a9c9f9SJoao Pinto /* Configure MTL TX algorithms */ 2318d0a9c9f9SJoao Pinto if (tx_queues_count > 1 && priv->hw->mac->prog_mtl_tx_algorithms) 2319d0a9c9f9SJoao Pinto priv->hw->mac->prog_mtl_tx_algorithms(priv->hw, 2320d0a9c9f9SJoao Pinto priv->plat->tx_sched_algorithm); 2321d0a9c9f9SJoao Pinto 232219d91873SJoao Pinto /* Configure CBS in AVB TX queues */ 232319d91873SJoao Pinto if (tx_queues_count > 1 && priv->hw->mac->config_cbs) 232419d91873SJoao Pinto stmmac_configure_cbs(priv); 232519d91873SJoao Pinto 2326d43042f4SJoao Pinto /* Map RX MTL to DMA channels */ 232703cf65a9SJoao Pinto if (priv->hw->mac->map_mtl_to_dma) 2328d43042f4SJoao Pinto stmmac_rx_queue_dma_chan_map(priv); 2329d43042f4SJoao Pinto 2330d0a9c9f9SJoao Pinto /* Enable MAC RX Queues */ 2331f3976874SThierry Reding if (priv->hw->mac->rx_queue_enable) 2332d0a9c9f9SJoao Pinto stmmac_mac_enable_rx_queues(priv); 23336deee222SJoao Pinto 2334a8f5102aSJoao Pinto /* Set RX priorities */ 2335a8f5102aSJoao Pinto if (rx_queues_count > 1 && priv->hw->mac->rx_queue_prio) 2336a8f5102aSJoao Pinto stmmac_mac_config_rx_queues_prio(priv); 2337a8f5102aSJoao Pinto 2338a8f5102aSJoao Pinto /* Set TX priorities */ 2339a8f5102aSJoao Pinto if (tx_queues_count > 1 && priv->hw->mac->tx_queue_prio) 2340a8f5102aSJoao Pinto stmmac_mac_config_tx_queues_prio(priv); 2341abe80fdcSJoao Pinto 2342abe80fdcSJoao Pinto /* Set RX routing */ 2343abe80fdcSJoao Pinto if (rx_queues_count > 1 && priv->hw->mac->rx_queue_routing) 2344abe80fdcSJoao Pinto stmmac_mac_config_rx_queues_routing(priv); 2345d0a9c9f9SJoao Pinto } 2346d0a9c9f9SJoao Pinto 2347d0a9c9f9SJoao Pinto /** 2348732fdf0eSGiuseppe CAVALLARO * stmmac_hw_setup - setup mac in a usable state. 2349523f11b5SSrinivas Kandagatla * @dev : pointer to the device structure. 2350523f11b5SSrinivas Kandagatla * Description: 2351732fdf0eSGiuseppe CAVALLARO * this is the main function to setup the HW in a usable state because the 2352732fdf0eSGiuseppe CAVALLARO * dma engine is reset, the core registers are configured (e.g. AXI, 2353732fdf0eSGiuseppe CAVALLARO * Checksum features, timers). The DMA is ready to start receiving and 2354732fdf0eSGiuseppe CAVALLARO * transmitting. 2355523f11b5SSrinivas Kandagatla * Return value: 2356523f11b5SSrinivas Kandagatla * 0 on success and an appropriate (-)ve integer as defined in errno.h 2357523f11b5SSrinivas Kandagatla * file on failure. 2358523f11b5SSrinivas Kandagatla */ 2359fe131929SHuacai Chen static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) 2360523f11b5SSrinivas Kandagatla { 2361523f11b5SSrinivas Kandagatla struct stmmac_priv *priv = netdev_priv(dev); 23623c55d4d0SJoao Pinto u32 rx_cnt = priv->plat->rx_queues_to_use; 2363146617b8SJoao Pinto u32 tx_cnt = priv->plat->tx_queues_to_use; 2364146617b8SJoao Pinto u32 chan; 2365523f11b5SSrinivas Kandagatla int ret; 2366523f11b5SSrinivas Kandagatla 2367523f11b5SSrinivas Kandagatla /* DMA initialization and SW reset */ 2368523f11b5SSrinivas Kandagatla ret = stmmac_init_dma_engine(priv); 2369523f11b5SSrinivas Kandagatla if (ret < 0) { 237038ddc59dSLABBE Corentin netdev_err(priv->dev, "%s: DMA engine initialization failed\n", 237138ddc59dSLABBE Corentin __func__); 2372523f11b5SSrinivas Kandagatla return ret; 2373523f11b5SSrinivas Kandagatla } 2374523f11b5SSrinivas Kandagatla 2375523f11b5SSrinivas Kandagatla /* Copy the MAC addr into the HW */ 23767ed24bbeSVince Bridgers priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0); 2377523f11b5SSrinivas Kandagatla 237802e57b9dSGiuseppe CAVALLARO /* PS and related bits will be programmed according to the speed */ 237902e57b9dSGiuseppe CAVALLARO if (priv->hw->pcs) { 238002e57b9dSGiuseppe CAVALLARO int speed = priv->plat->mac_port_sel_speed; 238102e57b9dSGiuseppe CAVALLARO 238202e57b9dSGiuseppe CAVALLARO if ((speed == SPEED_10) || (speed == SPEED_100) || 238302e57b9dSGiuseppe CAVALLARO (speed == SPEED_1000)) { 238402e57b9dSGiuseppe CAVALLARO priv->hw->ps = speed; 238502e57b9dSGiuseppe CAVALLARO } else { 238602e57b9dSGiuseppe CAVALLARO dev_warn(priv->device, "invalid port speed\n"); 238702e57b9dSGiuseppe CAVALLARO priv->hw->ps = 0; 238802e57b9dSGiuseppe CAVALLARO } 238902e57b9dSGiuseppe CAVALLARO } 239002e57b9dSGiuseppe CAVALLARO 2391523f11b5SSrinivas Kandagatla /* Initialize the MAC Core */ 23927ed24bbeSVince Bridgers priv->hw->mac->core_init(priv->hw, dev->mtu); 2393523f11b5SSrinivas Kandagatla 2394d0a9c9f9SJoao Pinto /* Initialize MTL*/ 2395d0a9c9f9SJoao Pinto if (priv->synopsys_id >= DWMAC_CORE_4_00) 2396d0a9c9f9SJoao Pinto stmmac_mtl_configuration(priv); 23979eb12474Sjpinto 2398978aded4SGiuseppe CAVALLARO ret = priv->hw->mac->rx_ipc(priv->hw); 2399978aded4SGiuseppe CAVALLARO if (!ret) { 240038ddc59dSLABBE Corentin netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n"); 2401978aded4SGiuseppe CAVALLARO priv->plat->rx_coe = STMMAC_RX_COE_NONE; 2402d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = 0; 2403978aded4SGiuseppe CAVALLARO } 2404978aded4SGiuseppe CAVALLARO 2405523f11b5SSrinivas Kandagatla /* Enable the MAC Rx/Tx */ 2406270c7759SLABBE Corentin priv->hw->mac->set_mac(priv->ioaddr, true); 2407523f11b5SSrinivas Kandagatla 2408b4f0a661SJoao Pinto /* Set the HW DMA mode and the COE */ 2409b4f0a661SJoao Pinto stmmac_dma_operation_mode(priv); 2410b4f0a661SJoao Pinto 2411523f11b5SSrinivas Kandagatla stmmac_mmc_setup(priv); 2412523f11b5SSrinivas Kandagatla 2413fe131929SHuacai Chen if (init_ptp) { 24140ad2be79SThierry Reding ret = clk_prepare_enable(priv->plat->clk_ptp_ref); 24150ad2be79SThierry Reding if (ret < 0) 24160ad2be79SThierry Reding netdev_warn(priv->dev, "failed to enable PTP reference clock: %d\n", ret); 24170ad2be79SThierry Reding 2418523f11b5SSrinivas Kandagatla ret = stmmac_init_ptp(priv); 2419722eef28SHeiner Kallweit if (ret == -EOPNOTSUPP) 2420722eef28SHeiner Kallweit netdev_warn(priv->dev, "PTP not supported by HW\n"); 2421722eef28SHeiner Kallweit else if (ret) 2422722eef28SHeiner Kallweit netdev_warn(priv->dev, "PTP init failed\n"); 2423fe131929SHuacai Chen } 2424523f11b5SSrinivas Kandagatla 242550fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 2426523f11b5SSrinivas Kandagatla ret = stmmac_init_fs(dev); 2427523f11b5SSrinivas Kandagatla if (ret < 0) 242838ddc59dSLABBE Corentin netdev_warn(priv->dev, "%s: failed debugFS registration\n", 242938ddc59dSLABBE Corentin __func__); 2430523f11b5SSrinivas Kandagatla #endif 2431523f11b5SSrinivas Kandagatla /* Start the ball rolling... */ 2432ae4f0d46SJoao Pinto stmmac_start_all_dma(priv); 2433523f11b5SSrinivas Kandagatla 2434523f11b5SSrinivas Kandagatla priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; 2435523f11b5SSrinivas Kandagatla 2436523f11b5SSrinivas Kandagatla if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { 2437523f11b5SSrinivas Kandagatla priv->rx_riwt = MAX_DMA_RIWT; 24383c55d4d0SJoao Pinto priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT, rx_cnt); 2439523f11b5SSrinivas Kandagatla } 2440523f11b5SSrinivas Kandagatla 24413fe5cadbSGiuseppe CAVALLARO if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane) 244202e57b9dSGiuseppe CAVALLARO priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, priv->hw->ps, 0); 2443523f11b5SSrinivas Kandagatla 24444854ab99SJoao Pinto /* set TX and RX rings length */ 24454854ab99SJoao Pinto stmmac_set_rings_length(priv); 24464854ab99SJoao Pinto 2447f748be53SAlexandre TORGUE /* Enable TSO */ 2448146617b8SJoao Pinto if (priv->tso) { 2449146617b8SJoao Pinto for (chan = 0; chan < tx_cnt; chan++) 2450146617b8SJoao Pinto priv->hw->dma->enable_tso(priv->ioaddr, 1, chan); 2451146617b8SJoao Pinto } 2452f748be53SAlexandre TORGUE 2453523f11b5SSrinivas Kandagatla return 0; 2454523f11b5SSrinivas Kandagatla } 2455523f11b5SSrinivas Kandagatla 2456c66f6c37SThierry Reding static void stmmac_hw_teardown(struct net_device *dev) 2457c66f6c37SThierry Reding { 2458c66f6c37SThierry Reding struct stmmac_priv *priv = netdev_priv(dev); 2459c66f6c37SThierry Reding 2460c66f6c37SThierry Reding clk_disable_unprepare(priv->plat->clk_ptp_ref); 2461c66f6c37SThierry Reding } 2462c66f6c37SThierry Reding 2463523f11b5SSrinivas Kandagatla /** 24647ac6653aSJeff Kirsher * stmmac_open - open entry point of the driver 24657ac6653aSJeff Kirsher * @dev : pointer to the device structure. 24667ac6653aSJeff Kirsher * Description: 24677ac6653aSJeff Kirsher * This function is the open entry point of the driver. 24687ac6653aSJeff Kirsher * Return value: 24697ac6653aSJeff Kirsher * 0 on success and an appropriate (-)ve integer as defined in errno.h 24707ac6653aSJeff Kirsher * file on failure. 24717ac6653aSJeff Kirsher */ 24727ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev) 24737ac6653aSJeff Kirsher { 24747ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 24757ac6653aSJeff Kirsher int ret; 24767ac6653aSJeff Kirsher 24774bfcbd7aSFrancesco Virlinzi stmmac_check_ether_addr(priv); 24784bfcbd7aSFrancesco Virlinzi 24793fe5cadbSGiuseppe CAVALLARO if (priv->hw->pcs != STMMAC_PCS_RGMII && 24803fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_TBI && 24813fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_RTBI) { 24827ac6653aSJeff Kirsher ret = stmmac_init_phy(dev); 2483e58bb43fSGiuseppe CAVALLARO if (ret) { 248438ddc59dSLABBE Corentin netdev_err(priv->dev, 248538ddc59dSLABBE Corentin "%s: Cannot attach to PHY (error: %d)\n", 2486e58bb43fSGiuseppe CAVALLARO __func__, ret); 248789df20d9SHans de Goede return ret; 24887ac6653aSJeff Kirsher } 2489e58bb43fSGiuseppe CAVALLARO } 24907ac6653aSJeff Kirsher 2491523f11b5SSrinivas Kandagatla /* Extra statistics */ 2492523f11b5SSrinivas Kandagatla memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats)); 2493523f11b5SSrinivas Kandagatla priv->xstats.threshold = tc; 2494523f11b5SSrinivas Kandagatla 24955bacd778SLABBE Corentin priv->dma_buf_sz = STMMAC_ALIGN(buf_sz); 249622ad3838SGiuseppe Cavallaro priv->rx_copybreak = STMMAC_RX_COPYBREAK; 249756329137SBartlomiej Zolnierkiewicz 24985bacd778SLABBE Corentin ret = alloc_dma_desc_resources(priv); 24995bacd778SLABBE Corentin if (ret < 0) { 25005bacd778SLABBE Corentin netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n", 25015bacd778SLABBE Corentin __func__); 25025bacd778SLABBE Corentin goto dma_desc_error; 25035bacd778SLABBE Corentin } 25045bacd778SLABBE Corentin 25055bacd778SLABBE Corentin ret = init_dma_desc_rings(dev, GFP_KERNEL); 25065bacd778SLABBE Corentin if (ret < 0) { 25075bacd778SLABBE Corentin netdev_err(priv->dev, "%s: DMA descriptors initialization failed\n", 25085bacd778SLABBE Corentin __func__); 25095bacd778SLABBE Corentin goto init_error; 25105bacd778SLABBE Corentin } 25115bacd778SLABBE Corentin 2512fe131929SHuacai Chen ret = stmmac_hw_setup(dev, true); 251356329137SBartlomiej Zolnierkiewicz if (ret < 0) { 251438ddc59dSLABBE Corentin netdev_err(priv->dev, "%s: Hw setup failed\n", __func__); 2515c9324d18SGiuseppe CAVALLARO goto init_error; 25167ac6653aSJeff Kirsher } 25177ac6653aSJeff Kirsher 2518777da230SGiuseppe CAVALLARO stmmac_init_tx_coalesce(priv); 2519777da230SGiuseppe CAVALLARO 2520d6d50c7eSPhilippe Reynes if (dev->phydev) 2521d6d50c7eSPhilippe Reynes phy_start(dev->phydev); 25227ac6653aSJeff Kirsher 25237ac6653aSJeff Kirsher /* Request the IRQ lines */ 25247ac6653aSJeff Kirsher ret = request_irq(dev->irq, stmmac_interrupt, 25257ac6653aSJeff Kirsher IRQF_SHARED, dev->name, dev); 25267ac6653aSJeff Kirsher if (unlikely(ret < 0)) { 252738ddc59dSLABBE Corentin netdev_err(priv->dev, 252838ddc59dSLABBE Corentin "%s: ERROR: allocating the IRQ %d (error: %d)\n", 25297ac6653aSJeff Kirsher __func__, dev->irq, ret); 25306c1e5abeSThierry Reding goto irq_error; 25317ac6653aSJeff Kirsher } 25327ac6653aSJeff Kirsher 25337a13f8f5SFrancesco Virlinzi /* Request the Wake IRQ in case of another line is used for WoL */ 25347a13f8f5SFrancesco Virlinzi if (priv->wol_irq != dev->irq) { 25357a13f8f5SFrancesco Virlinzi ret = request_irq(priv->wol_irq, stmmac_interrupt, 25367a13f8f5SFrancesco Virlinzi IRQF_SHARED, dev->name, dev); 25377a13f8f5SFrancesco Virlinzi if (unlikely(ret < 0)) { 253838ddc59dSLABBE Corentin netdev_err(priv->dev, 253938ddc59dSLABBE Corentin "%s: ERROR: allocating the WoL IRQ %d (%d)\n", 2540ceb69499SGiuseppe CAVALLARO __func__, priv->wol_irq, ret); 2541c9324d18SGiuseppe CAVALLARO goto wolirq_error; 25427a13f8f5SFrancesco Virlinzi } 25437a13f8f5SFrancesco Virlinzi } 25447a13f8f5SFrancesco Virlinzi 2545d765955dSGiuseppe CAVALLARO /* Request the IRQ lines */ 2546d7ec8584SChen-Yu Tsai if (priv->lpi_irq > 0) { 2547d765955dSGiuseppe CAVALLARO ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED, 2548d765955dSGiuseppe CAVALLARO dev->name, dev); 2549d765955dSGiuseppe CAVALLARO if (unlikely(ret < 0)) { 255038ddc59dSLABBE Corentin netdev_err(priv->dev, 255138ddc59dSLABBE Corentin "%s: ERROR: allocating the LPI IRQ %d (%d)\n", 2552d765955dSGiuseppe CAVALLARO __func__, priv->lpi_irq, ret); 2553c9324d18SGiuseppe CAVALLARO goto lpiirq_error; 2554d765955dSGiuseppe CAVALLARO } 2555d765955dSGiuseppe CAVALLARO } 2556d765955dSGiuseppe CAVALLARO 25575bacd778SLABBE Corentin napi_enable(&priv->napi); 25585bacd778SLABBE Corentin netif_start_queue(dev); 25597ac6653aSJeff Kirsher 25607ac6653aSJeff Kirsher return 0; 25617ac6653aSJeff Kirsher 2562c9324d18SGiuseppe CAVALLARO lpiirq_error: 2563d765955dSGiuseppe CAVALLARO if (priv->wol_irq != dev->irq) 2564d765955dSGiuseppe CAVALLARO free_irq(priv->wol_irq, dev); 2565c9324d18SGiuseppe CAVALLARO wolirq_error: 25667a13f8f5SFrancesco Virlinzi free_irq(dev->irq, dev); 25676c1e5abeSThierry Reding irq_error: 25686c1e5abeSThierry Reding if (dev->phydev) 25696c1e5abeSThierry Reding phy_stop(dev->phydev); 25707a13f8f5SFrancesco Virlinzi 25716c1e5abeSThierry Reding del_timer_sync(&priv->txtimer); 2572c66f6c37SThierry Reding stmmac_hw_teardown(dev); 2573c9324d18SGiuseppe CAVALLARO init_error: 2574c9324d18SGiuseppe CAVALLARO free_dma_desc_resources(priv); 25755bacd778SLABBE Corentin dma_desc_error: 2576d6d50c7eSPhilippe Reynes if (dev->phydev) 2577d6d50c7eSPhilippe Reynes phy_disconnect(dev->phydev); 25784bfcbd7aSFrancesco Virlinzi 25797ac6653aSJeff Kirsher return ret; 25807ac6653aSJeff Kirsher } 25817ac6653aSJeff Kirsher 25827ac6653aSJeff Kirsher /** 25837ac6653aSJeff Kirsher * stmmac_release - close entry point of the driver 25847ac6653aSJeff Kirsher * @dev : device pointer. 25857ac6653aSJeff Kirsher * Description: 25867ac6653aSJeff Kirsher * This is the stop entry point of the driver. 25877ac6653aSJeff Kirsher */ 25887ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev) 25897ac6653aSJeff Kirsher { 25907ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 25917ac6653aSJeff Kirsher 2592d765955dSGiuseppe CAVALLARO if (priv->eee_enabled) 2593d765955dSGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 2594d765955dSGiuseppe CAVALLARO 25957ac6653aSJeff Kirsher /* Stop and disconnect the PHY */ 2596d6d50c7eSPhilippe Reynes if (dev->phydev) { 2597d6d50c7eSPhilippe Reynes phy_stop(dev->phydev); 2598d6d50c7eSPhilippe Reynes phy_disconnect(dev->phydev); 25997ac6653aSJeff Kirsher } 26007ac6653aSJeff Kirsher 26015bacd778SLABBE Corentin netif_stop_queue(dev); 26027ac6653aSJeff Kirsher 26035bacd778SLABBE Corentin napi_disable(&priv->napi); 26047ac6653aSJeff Kirsher 26059125cdd1SGiuseppe CAVALLARO del_timer_sync(&priv->txtimer); 26069125cdd1SGiuseppe CAVALLARO 26077ac6653aSJeff Kirsher /* Free the IRQ lines */ 26087ac6653aSJeff Kirsher free_irq(dev->irq, dev); 26097a13f8f5SFrancesco Virlinzi if (priv->wol_irq != dev->irq) 26107a13f8f5SFrancesco Virlinzi free_irq(priv->wol_irq, dev); 2611d7ec8584SChen-Yu Tsai if (priv->lpi_irq > 0) 2612d765955dSGiuseppe CAVALLARO free_irq(priv->lpi_irq, dev); 26137ac6653aSJeff Kirsher 26147ac6653aSJeff Kirsher /* Stop TX/RX DMA and clear the descriptors */ 2615ae4f0d46SJoao Pinto stmmac_stop_all_dma(priv); 26167ac6653aSJeff Kirsher 26177ac6653aSJeff Kirsher /* Release and free the Rx/Tx resources */ 26187ac6653aSJeff Kirsher free_dma_desc_resources(priv); 26197ac6653aSJeff Kirsher 26207ac6653aSJeff Kirsher /* Disable the MAC Rx/Tx */ 2621270c7759SLABBE Corentin priv->hw->mac->set_mac(priv->ioaddr, false); 26227ac6653aSJeff Kirsher 26237ac6653aSJeff Kirsher netif_carrier_off(dev); 26247ac6653aSJeff Kirsher 262550fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 2626466c5ac8SMathieu Olivari stmmac_exit_fs(dev); 2627bfab27a1SGiuseppe CAVALLARO #endif 2628bfab27a1SGiuseppe CAVALLARO 262992ba6888SRayagond Kokatanur stmmac_release_ptp(priv); 263092ba6888SRayagond Kokatanur 26317ac6653aSJeff Kirsher return 0; 26327ac6653aSJeff Kirsher } 26337ac6653aSJeff Kirsher 26347ac6653aSJeff Kirsher /** 2635f748be53SAlexandre TORGUE * stmmac_tso_allocator - close entry point of the driver 2636f748be53SAlexandre TORGUE * @priv: driver private structure 2637f748be53SAlexandre TORGUE * @des: buffer start address 2638f748be53SAlexandre TORGUE * @total_len: total length to fill in descriptors 2639f748be53SAlexandre TORGUE * @last_segmant: condition for the last descriptor 2640ce736788SJoao Pinto * @queue: TX queue index 2641f748be53SAlexandre TORGUE * Description: 2642f748be53SAlexandre TORGUE * This function fills descriptor and request new descriptors according to 2643f748be53SAlexandre TORGUE * buffer length to fill 2644f748be53SAlexandre TORGUE */ 2645f748be53SAlexandre TORGUE static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des, 2646ce736788SJoao Pinto int total_len, bool last_segment, u32 queue) 2647f748be53SAlexandre TORGUE { 2648ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 2649f748be53SAlexandre TORGUE struct dma_desc *desc; 26505bacd778SLABBE Corentin u32 buff_size; 2651ce736788SJoao Pinto int tmp_len; 2652f748be53SAlexandre TORGUE 2653f748be53SAlexandre TORGUE tmp_len = total_len; 2654f748be53SAlexandre TORGUE 2655f748be53SAlexandre TORGUE while (tmp_len > 0) { 2656ce736788SJoao Pinto tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE); 2657ce736788SJoao Pinto desc = tx_q->dma_tx + tx_q->cur_tx; 2658f748be53SAlexandre TORGUE 2659f8be0d78SMichael Weiser desc->des0 = cpu_to_le32(des + (total_len - tmp_len)); 2660f748be53SAlexandre TORGUE buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ? 2661f748be53SAlexandre TORGUE TSO_MAX_BUFF_SIZE : tmp_len; 2662f748be53SAlexandre TORGUE 2663f748be53SAlexandre TORGUE priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size, 2664f748be53SAlexandre TORGUE 0, 1, 2665f748be53SAlexandre TORGUE (last_segment) && (buff_size < TSO_MAX_BUFF_SIZE), 2666f748be53SAlexandre TORGUE 0, 0); 2667f748be53SAlexandre TORGUE 2668f748be53SAlexandre TORGUE tmp_len -= TSO_MAX_BUFF_SIZE; 2669f748be53SAlexandre TORGUE } 2670f748be53SAlexandre TORGUE } 2671f748be53SAlexandre TORGUE 2672f748be53SAlexandre TORGUE /** 2673f748be53SAlexandre TORGUE * stmmac_tso_xmit - Tx entry point of the driver for oversized frames (TSO) 2674f748be53SAlexandre TORGUE * @skb : the socket buffer 2675f748be53SAlexandre TORGUE * @dev : device pointer 2676f748be53SAlexandre TORGUE * Description: this is the transmit function that is called on TSO frames 2677f748be53SAlexandre TORGUE * (support available on GMAC4 and newer chips). 2678f748be53SAlexandre TORGUE * Diagram below show the ring programming in case of TSO frames: 2679f748be53SAlexandre TORGUE * 2680f748be53SAlexandre TORGUE * First Descriptor 2681f748be53SAlexandre TORGUE * -------- 2682f748be53SAlexandre TORGUE * | DES0 |---> buffer1 = L2/L3/L4 header 2683f748be53SAlexandre TORGUE * | DES1 |---> TCP Payload (can continue on next descr...) 2684f748be53SAlexandre TORGUE * | DES2 |---> buffer 1 and 2 len 2685f748be53SAlexandre TORGUE * | DES3 |---> must set TSE, TCP hdr len-> [22:19]. TCP payload len [17:0] 2686f748be53SAlexandre TORGUE * -------- 2687f748be53SAlexandre TORGUE * | 2688f748be53SAlexandre TORGUE * ... 2689f748be53SAlexandre TORGUE * | 2690f748be53SAlexandre TORGUE * -------- 2691f748be53SAlexandre TORGUE * | DES0 | --| Split TCP Payload on Buffers 1 and 2 2692f748be53SAlexandre TORGUE * | DES1 | --| 2693f748be53SAlexandre TORGUE * | DES2 | --> buffer 1 and 2 len 2694f748be53SAlexandre TORGUE * | DES3 | 2695f748be53SAlexandre TORGUE * -------- 2696f748be53SAlexandre TORGUE * 2697f748be53SAlexandre TORGUE * mss is fixed when enable tso, so w/o programming the TDES3 ctx field. 2698f748be53SAlexandre TORGUE */ 2699f748be53SAlexandre TORGUE static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) 2700f748be53SAlexandre TORGUE { 2701ce736788SJoao Pinto struct dma_desc *desc, *first, *mss_desc = NULL; 2702f748be53SAlexandre TORGUE struct stmmac_priv *priv = netdev_priv(dev); 2703f748be53SAlexandre TORGUE int nfrags = skb_shinfo(skb)->nr_frags; 2704ce736788SJoao Pinto u32 queue = skb_get_queue_mapping(skb); 2705f748be53SAlexandre TORGUE unsigned int first_entry, des; 2706ce736788SJoao Pinto struct stmmac_tx_queue *tx_q; 2707ce736788SJoao Pinto int tmp_pay_len = 0; 2708ce736788SJoao Pinto u32 pay_len, mss; 2709f748be53SAlexandre TORGUE u8 proto_hdr_len; 2710f748be53SAlexandre TORGUE int i; 2711f748be53SAlexandre TORGUE 2712ce736788SJoao Pinto tx_q = &priv->tx_queue[queue]; 2713ce736788SJoao Pinto 2714f748be53SAlexandre TORGUE /* Compute header lengths */ 2715f748be53SAlexandre TORGUE proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); 2716f748be53SAlexandre TORGUE 2717f748be53SAlexandre TORGUE /* Desc availability based on threshold should be enough safe */ 2718ce736788SJoao Pinto if (unlikely(stmmac_tx_avail(priv, queue) < 2719f748be53SAlexandre TORGUE (((skb->len - proto_hdr_len) / TSO_MAX_BUFF_SIZE + 1)))) { 27205bacd778SLABBE Corentin if (!netif_queue_stopped(dev)) { 27215bacd778SLABBE Corentin netif_stop_queue(dev); 2722f748be53SAlexandre TORGUE /* This is a hard error, log it. */ 272338ddc59dSLABBE Corentin netdev_err(priv->dev, 272438ddc59dSLABBE Corentin "%s: Tx Ring full when queue awake\n", 272538ddc59dSLABBE Corentin __func__); 2726f748be53SAlexandre TORGUE } 2727f748be53SAlexandre TORGUE return NETDEV_TX_BUSY; 2728f748be53SAlexandre TORGUE } 2729f748be53SAlexandre TORGUE 2730f748be53SAlexandre TORGUE pay_len = skb_headlen(skb) - proto_hdr_len; /* no frags */ 2731f748be53SAlexandre TORGUE 2732f748be53SAlexandre TORGUE mss = skb_shinfo(skb)->gso_size; 2733f748be53SAlexandre TORGUE 2734f748be53SAlexandre TORGUE /* set new MSS value if needed */ 2735f748be53SAlexandre TORGUE if (mss != priv->mss) { 2736ce736788SJoao Pinto mss_desc = tx_q->dma_tx + tx_q->cur_tx; 2737f748be53SAlexandre TORGUE priv->hw->desc->set_mss(mss_desc, mss); 2738f748be53SAlexandre TORGUE priv->mss = mss; 2739ce736788SJoao Pinto tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE); 2740f748be53SAlexandre TORGUE } 2741f748be53SAlexandre TORGUE 2742f748be53SAlexandre TORGUE if (netif_msg_tx_queued(priv)) { 2743f748be53SAlexandre TORGUE pr_info("%s: tcphdrlen %d, hdr_len %d, pay_len %d, mss %d\n", 2744f748be53SAlexandre TORGUE __func__, tcp_hdrlen(skb), proto_hdr_len, pay_len, mss); 2745f748be53SAlexandre TORGUE pr_info("\tskb->len %d, skb->data_len %d\n", skb->len, 2746f748be53SAlexandre TORGUE skb->data_len); 2747f748be53SAlexandre TORGUE } 2748f748be53SAlexandre TORGUE 2749ce736788SJoao Pinto first_entry = tx_q->cur_tx; 2750f748be53SAlexandre TORGUE 2751ce736788SJoao Pinto desc = tx_q->dma_tx + first_entry; 2752f748be53SAlexandre TORGUE first = desc; 2753f748be53SAlexandre TORGUE 2754f748be53SAlexandre TORGUE /* first descriptor: fill Headers on Buf1 */ 2755f748be53SAlexandre TORGUE des = dma_map_single(priv->device, skb->data, skb_headlen(skb), 2756f748be53SAlexandre TORGUE DMA_TO_DEVICE); 2757f748be53SAlexandre TORGUE if (dma_mapping_error(priv->device, des)) 2758f748be53SAlexandre TORGUE goto dma_map_err; 2759f748be53SAlexandre TORGUE 2760ce736788SJoao Pinto tx_q->tx_skbuff_dma[first_entry].buf = des; 2761ce736788SJoao Pinto tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb); 2762ce736788SJoao Pinto tx_q->tx_skbuff[first_entry] = skb; 2763f748be53SAlexandre TORGUE 2764f8be0d78SMichael Weiser first->des0 = cpu_to_le32(des); 2765f748be53SAlexandre TORGUE 2766f748be53SAlexandre TORGUE /* Fill start of payload in buff2 of first descriptor */ 2767f748be53SAlexandre TORGUE if (pay_len) 2768f8be0d78SMichael Weiser first->des1 = cpu_to_le32(des + proto_hdr_len); 2769f748be53SAlexandre TORGUE 2770f748be53SAlexandre TORGUE /* If needed take extra descriptors to fill the remaining payload */ 2771f748be53SAlexandre TORGUE tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE; 2772f748be53SAlexandre TORGUE 2773ce736788SJoao Pinto stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue); 2774f748be53SAlexandre TORGUE 2775f748be53SAlexandre TORGUE /* Prepare fragments */ 2776f748be53SAlexandre TORGUE for (i = 0; i < nfrags; i++) { 2777f748be53SAlexandre TORGUE const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 2778f748be53SAlexandre TORGUE 2779f748be53SAlexandre TORGUE des = skb_frag_dma_map(priv->device, frag, 0, 2780f748be53SAlexandre TORGUE skb_frag_size(frag), 2781f748be53SAlexandre TORGUE DMA_TO_DEVICE); 2782937071c1SThierry Reding if (dma_mapping_error(priv->device, des)) 2783937071c1SThierry Reding goto dma_map_err; 2784f748be53SAlexandre TORGUE 2785f748be53SAlexandre TORGUE stmmac_tso_allocator(priv, des, skb_frag_size(frag), 2786ce736788SJoao Pinto (i == nfrags - 1), queue); 2787f748be53SAlexandre TORGUE 2788ce736788SJoao Pinto tx_q->tx_skbuff_dma[tx_q->cur_tx].buf = des; 2789ce736788SJoao Pinto tx_q->tx_skbuff_dma[tx_q->cur_tx].len = skb_frag_size(frag); 2790ce736788SJoao Pinto tx_q->tx_skbuff[tx_q->cur_tx] = NULL; 2791ce736788SJoao Pinto tx_q->tx_skbuff_dma[tx_q->cur_tx].map_as_page = true; 2792f748be53SAlexandre TORGUE } 2793f748be53SAlexandre TORGUE 2794ce736788SJoao Pinto tx_q->tx_skbuff_dma[tx_q->cur_tx].last_segment = true; 2795f748be53SAlexandre TORGUE 2796ce736788SJoao Pinto tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE); 2797f748be53SAlexandre TORGUE 2798ce736788SJoao Pinto if (unlikely(stmmac_tx_avail(priv, queue) <= (MAX_SKB_FRAGS + 1))) { 2799b3e51069SLABBE Corentin netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n", 280038ddc59dSLABBE Corentin __func__); 28015bacd778SLABBE Corentin netif_stop_queue(dev); 2802f748be53SAlexandre TORGUE } 2803f748be53SAlexandre TORGUE 2804f748be53SAlexandre TORGUE dev->stats.tx_bytes += skb->len; 2805f748be53SAlexandre TORGUE priv->xstats.tx_tso_frames++; 2806f748be53SAlexandre TORGUE priv->xstats.tx_tso_nfrags += nfrags; 2807f748be53SAlexandre TORGUE 2808f748be53SAlexandre TORGUE /* Manage tx mitigation */ 2809f748be53SAlexandre TORGUE priv->tx_count_frames += nfrags + 1; 2810f748be53SAlexandre TORGUE if (likely(priv->tx_coal_frames > priv->tx_count_frames)) { 2811f748be53SAlexandre TORGUE mod_timer(&priv->txtimer, 2812f748be53SAlexandre TORGUE STMMAC_COAL_TIMER(priv->tx_coal_timer)); 2813f748be53SAlexandre TORGUE } else { 2814f748be53SAlexandre TORGUE priv->tx_count_frames = 0; 2815f748be53SAlexandre TORGUE priv->hw->desc->set_tx_ic(desc); 2816f748be53SAlexandre TORGUE priv->xstats.tx_set_ic_bit++; 2817f748be53SAlexandre TORGUE } 2818f748be53SAlexandre TORGUE 2819f748be53SAlexandre TORGUE if (!priv->hwts_tx_en) 2820f748be53SAlexandre TORGUE skb_tx_timestamp(skb); 2821f748be53SAlexandre TORGUE 2822f748be53SAlexandre TORGUE if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && 2823f748be53SAlexandre TORGUE priv->hwts_tx_en)) { 2824f748be53SAlexandre TORGUE /* declare that device is doing timestamping */ 2825f748be53SAlexandre TORGUE skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 2826f748be53SAlexandre TORGUE priv->hw->desc->enable_tx_timestamp(first); 2827f748be53SAlexandre TORGUE } 2828f748be53SAlexandre TORGUE 2829f748be53SAlexandre TORGUE /* Complete the first descriptor before granting the DMA */ 2830f748be53SAlexandre TORGUE priv->hw->desc->prepare_tso_tx_desc(first, 1, 2831f748be53SAlexandre TORGUE proto_hdr_len, 2832f748be53SAlexandre TORGUE pay_len, 2833ce736788SJoao Pinto 1, tx_q->tx_skbuff_dma[first_entry].last_segment, 2834f748be53SAlexandre TORGUE tcp_hdrlen(skb) / 4, (skb->len - proto_hdr_len)); 2835f748be53SAlexandre TORGUE 2836f748be53SAlexandre TORGUE /* If context desc is used to change MSS */ 2837f748be53SAlexandre TORGUE if (mss_desc) 2838f748be53SAlexandre TORGUE priv->hw->desc->set_tx_owner(mss_desc); 2839f748be53SAlexandre TORGUE 2840f748be53SAlexandre TORGUE /* The own bit must be the latest setting done when prepare the 2841f748be53SAlexandre TORGUE * descriptor and then barrier is needed to make sure that 2842f748be53SAlexandre TORGUE * all is coherent before granting the DMA engine. 2843f748be53SAlexandre TORGUE */ 2844ad688cdbSPavel Machek dma_wmb(); 2845f748be53SAlexandre TORGUE 2846f748be53SAlexandre TORGUE if (netif_msg_pktdata(priv)) { 2847f748be53SAlexandre TORGUE pr_info("%s: curr=%d dirty=%d f=%d, e=%d, f_p=%p, nfrags %d\n", 2848ce736788SJoao Pinto __func__, tx_q->cur_tx, tx_q->dirty_tx, first_entry, 2849ce736788SJoao Pinto tx_q->cur_tx, first, nfrags); 2850f748be53SAlexandre TORGUE 2851ce736788SJoao Pinto priv->hw->desc->display_ring((void *)tx_q->dma_tx, DMA_TX_SIZE, 2852f748be53SAlexandre TORGUE 0); 2853f748be53SAlexandre TORGUE 2854f748be53SAlexandre TORGUE pr_info(">>> frame to be transmitted: "); 2855f748be53SAlexandre TORGUE print_pkt(skb->data, skb_headlen(skb)); 2856f748be53SAlexandre TORGUE } 2857f748be53SAlexandre TORGUE 28585bacd778SLABBE Corentin netdev_sent_queue(dev, skb->len); 2859f748be53SAlexandre TORGUE 2860ce736788SJoao Pinto priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, tx_q->tx_tail_addr, 2861ce736788SJoao Pinto queue); 2862f748be53SAlexandre TORGUE 2863f748be53SAlexandre TORGUE return NETDEV_TX_OK; 2864f748be53SAlexandre TORGUE 2865f748be53SAlexandre TORGUE dma_map_err: 2866f748be53SAlexandre TORGUE dev_err(priv->device, "Tx dma map failed\n"); 2867f748be53SAlexandre TORGUE dev_kfree_skb(skb); 2868f748be53SAlexandre TORGUE priv->dev->stats.tx_dropped++; 2869f748be53SAlexandre TORGUE return NETDEV_TX_OK; 2870f748be53SAlexandre TORGUE } 2871f748be53SAlexandre TORGUE 2872f748be53SAlexandre TORGUE /** 2873732fdf0eSGiuseppe CAVALLARO * stmmac_xmit - Tx entry point of the driver 28747ac6653aSJeff Kirsher * @skb : the socket buffer 28757ac6653aSJeff Kirsher * @dev : device pointer 287632ceabcaSGiuseppe CAVALLARO * Description : this is the tx entry point of the driver. 287732ceabcaSGiuseppe CAVALLARO * It programs the chain or the ring and supports oversized frames 287832ceabcaSGiuseppe CAVALLARO * and SG feature. 28797ac6653aSJeff Kirsher */ 28807ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) 28817ac6653aSJeff Kirsher { 28827ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 28830e80bdc9SGiuseppe Cavallaro unsigned int nopaged_len = skb_headlen(skb); 28844a7d666aSGiuseppe CAVALLARO int i, csum_insertion = 0, is_jumbo = 0; 2885ce736788SJoao Pinto u32 queue = skb_get_queue_mapping(skb); 28867ac6653aSJeff Kirsher int nfrags = skb_shinfo(skb)->nr_frags; 28870e80bdc9SGiuseppe Cavallaro unsigned int entry, first_entry; 28887ac6653aSJeff Kirsher struct dma_desc *desc, *first; 2889ce736788SJoao Pinto struct stmmac_tx_queue *tx_q; 28900e80bdc9SGiuseppe Cavallaro unsigned int enh_desc; 2891f748be53SAlexandre TORGUE unsigned int des; 2892f748be53SAlexandre TORGUE 2893ce736788SJoao Pinto tx_q = &priv->tx_queue[queue]; 2894ce736788SJoao Pinto 2895f748be53SAlexandre TORGUE /* Manage oversized TCP frames for GMAC4 device */ 2896f748be53SAlexandre TORGUE if (skb_is_gso(skb) && priv->tso) { 2897f748be53SAlexandre TORGUE if (ip_hdr(skb)->protocol == IPPROTO_TCP) 2898f748be53SAlexandre TORGUE return stmmac_tso_xmit(skb, dev); 2899f748be53SAlexandre TORGUE } 29007ac6653aSJeff Kirsher 2901ce736788SJoao Pinto if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) { 29025bacd778SLABBE Corentin if (!netif_queue_stopped(dev)) { 29035bacd778SLABBE Corentin netif_stop_queue(dev); 29047ac6653aSJeff Kirsher /* This is a hard error, log it. */ 290538ddc59dSLABBE Corentin netdev_err(priv->dev, 290638ddc59dSLABBE Corentin "%s: Tx Ring full when queue awake\n", 290738ddc59dSLABBE Corentin __func__); 29087ac6653aSJeff Kirsher } 29097ac6653aSJeff Kirsher return NETDEV_TX_BUSY; 29107ac6653aSJeff Kirsher } 29117ac6653aSJeff Kirsher 2912d765955dSGiuseppe CAVALLARO if (priv->tx_path_in_lpi_mode) 2913d765955dSGiuseppe CAVALLARO stmmac_disable_eee_mode(priv); 2914d765955dSGiuseppe CAVALLARO 2915ce736788SJoao Pinto entry = tx_q->cur_tx; 29160e80bdc9SGiuseppe Cavallaro first_entry = entry; 29177ac6653aSJeff Kirsher 29187ac6653aSJeff Kirsher csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL); 29197ac6653aSJeff Kirsher 29200e80bdc9SGiuseppe Cavallaro if (likely(priv->extend_desc)) 2921ce736788SJoao Pinto desc = (struct dma_desc *)(tx_q->dma_etx + entry); 2922c24602efSGiuseppe CAVALLARO else 2923ce736788SJoao Pinto desc = tx_q->dma_tx + entry; 2924c24602efSGiuseppe CAVALLARO 29257ac6653aSJeff Kirsher first = desc; 29267ac6653aSJeff Kirsher 2927ce736788SJoao Pinto tx_q->tx_skbuff[first_entry] = skb; 29280e80bdc9SGiuseppe Cavallaro 29290e80bdc9SGiuseppe Cavallaro enh_desc = priv->plat->enh_desc; 29304a7d666aSGiuseppe CAVALLARO /* To program the descriptors according to the size of the frame */ 293129896a67SGiuseppe CAVALLARO if (enh_desc) 293229896a67SGiuseppe CAVALLARO is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc); 293329896a67SGiuseppe CAVALLARO 2934f748be53SAlexandre TORGUE if (unlikely(is_jumbo) && likely(priv->synopsys_id < 2935f748be53SAlexandre TORGUE DWMAC_CORE_4_00)) { 2936ce736788SJoao Pinto entry = priv->hw->mode->jumbo_frm(tx_q, skb, csum_insertion); 2937362b37beSGiuseppe CAVALLARO if (unlikely(entry < 0)) 2938362b37beSGiuseppe CAVALLARO goto dma_map_err; 293929896a67SGiuseppe CAVALLARO } 29407ac6653aSJeff Kirsher 29417ac6653aSJeff Kirsher for (i = 0; i < nfrags; i++) { 29429e903e08SEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 29439e903e08SEric Dumazet int len = skb_frag_size(frag); 2944be434d50SGiuseppe Cavallaro bool last_segment = (i == (nfrags - 1)); 29457ac6653aSJeff Kirsher 2946e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); 2947e3ad57c9SGiuseppe Cavallaro 29480e80bdc9SGiuseppe Cavallaro if (likely(priv->extend_desc)) 2949ce736788SJoao Pinto desc = (struct dma_desc *)(tx_q->dma_etx + entry); 2950c24602efSGiuseppe CAVALLARO else 2951ce736788SJoao Pinto desc = tx_q->dma_tx + entry; 29527ac6653aSJeff Kirsher 2953f748be53SAlexandre TORGUE des = skb_frag_dma_map(priv->device, frag, 0, len, 2954f722380dSIan Campbell DMA_TO_DEVICE); 2955f748be53SAlexandre TORGUE if (dma_mapping_error(priv->device, des)) 2956362b37beSGiuseppe CAVALLARO goto dma_map_err; /* should reuse desc w/o issues */ 2957362b37beSGiuseppe CAVALLARO 2958ce736788SJoao Pinto tx_q->tx_skbuff[entry] = NULL; 2959f748be53SAlexandre TORGUE 2960ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].buf = des; 2961f8be0d78SMichael Weiser if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) 2962f8be0d78SMichael Weiser desc->des0 = cpu_to_le32(des); 2963f8be0d78SMichael Weiser else 2964f8be0d78SMichael Weiser desc->des2 = cpu_to_le32(des); 2965f748be53SAlexandre TORGUE 2966ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].map_as_page = true; 2967ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].len = len; 2968ce736788SJoao Pinto tx_q->tx_skbuff_dma[entry].last_segment = last_segment; 29690e80bdc9SGiuseppe Cavallaro 29700e80bdc9SGiuseppe Cavallaro /* Prepare the descriptor and set the own bit too */ 29714a7d666aSGiuseppe CAVALLARO priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion, 2972be434d50SGiuseppe Cavallaro priv->mode, 1, last_segment); 29737ac6653aSJeff Kirsher } 29747ac6653aSJeff Kirsher 2975e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); 2976e3ad57c9SGiuseppe Cavallaro 2977ce736788SJoao Pinto tx_q->cur_tx = entry; 29787ac6653aSJeff Kirsher 29797ac6653aSJeff Kirsher if (netif_msg_pktdata(priv)) { 2980d0225e7dSAlexandre TORGUE void *tx_head; 2981d0225e7dSAlexandre TORGUE 298238ddc59dSLABBE Corentin netdev_dbg(priv->dev, 298338ddc59dSLABBE Corentin "%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d", 2984ce736788SJoao Pinto __func__, tx_q->cur_tx, tx_q->dirty_tx, first_entry, 29850e80bdc9SGiuseppe Cavallaro entry, first, nfrags); 298683d7af64SGiuseppe CAVALLARO 2987c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2988ce736788SJoao Pinto tx_head = (void *)tx_q->dma_etx; 2989c24602efSGiuseppe CAVALLARO else 2990ce736788SJoao Pinto tx_head = (void *)tx_q->dma_tx; 2991d0225e7dSAlexandre TORGUE 2992d0225e7dSAlexandre TORGUE priv->hw->desc->display_ring(tx_head, DMA_TX_SIZE, false); 2993c24602efSGiuseppe CAVALLARO 299438ddc59dSLABBE Corentin netdev_dbg(priv->dev, ">>> frame to be transmitted: "); 29957ac6653aSJeff Kirsher print_pkt(skb->data, skb->len); 29967ac6653aSJeff Kirsher } 29970e80bdc9SGiuseppe Cavallaro 2998ce736788SJoao Pinto if (unlikely(stmmac_tx_avail(priv, queue) <= (MAX_SKB_FRAGS + 1))) { 2999b3e51069SLABBE Corentin netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n", 3000b3e51069SLABBE Corentin __func__); 30015bacd778SLABBE Corentin netif_stop_queue(dev); 30027ac6653aSJeff Kirsher } 30037ac6653aSJeff Kirsher 30047ac6653aSJeff Kirsher dev->stats.tx_bytes += skb->len; 30057ac6653aSJeff Kirsher 30060e80bdc9SGiuseppe Cavallaro /* According to the coalesce parameter the IC bit for the latest 30070e80bdc9SGiuseppe Cavallaro * segment is reset and the timer re-started to clean the tx status. 30080e80bdc9SGiuseppe Cavallaro * This approach takes care about the fragments: desc is the first 30090e80bdc9SGiuseppe Cavallaro * element in case of no SG. 30100e80bdc9SGiuseppe Cavallaro */ 30110e80bdc9SGiuseppe Cavallaro priv->tx_count_frames += nfrags + 1; 30120e80bdc9SGiuseppe Cavallaro if (likely(priv->tx_coal_frames > priv->tx_count_frames)) { 30130e80bdc9SGiuseppe Cavallaro mod_timer(&priv->txtimer, 30140e80bdc9SGiuseppe Cavallaro STMMAC_COAL_TIMER(priv->tx_coal_timer)); 30150e80bdc9SGiuseppe Cavallaro } else { 30160e80bdc9SGiuseppe Cavallaro priv->tx_count_frames = 0; 30170e80bdc9SGiuseppe Cavallaro priv->hw->desc->set_tx_ic(desc); 30180e80bdc9SGiuseppe Cavallaro priv->xstats.tx_set_ic_bit++; 30190e80bdc9SGiuseppe Cavallaro } 30200e80bdc9SGiuseppe Cavallaro 30210e80bdc9SGiuseppe Cavallaro if (!priv->hwts_tx_en) 30220e80bdc9SGiuseppe Cavallaro skb_tx_timestamp(skb); 30230e80bdc9SGiuseppe Cavallaro 30240e80bdc9SGiuseppe Cavallaro /* Ready to fill the first descriptor and set the OWN bit w/o any 30250e80bdc9SGiuseppe Cavallaro * problems because all the descriptors are actually ready to be 30260e80bdc9SGiuseppe Cavallaro * passed to the DMA engine. 30270e80bdc9SGiuseppe Cavallaro */ 30280e80bdc9SGiuseppe Cavallaro if (likely(!is_jumbo)) { 30290e80bdc9SGiuseppe Cavallaro bool last_segment = (nfrags == 0); 30300e80bdc9SGiuseppe Cavallaro 3031f748be53SAlexandre TORGUE des = dma_map_single(priv->device, skb->data, 30320e80bdc9SGiuseppe Cavallaro nopaged_len, DMA_TO_DEVICE); 3033f748be53SAlexandre TORGUE if (dma_mapping_error(priv->device, des)) 30340e80bdc9SGiuseppe Cavallaro goto dma_map_err; 30350e80bdc9SGiuseppe Cavallaro 3036ce736788SJoao Pinto tx_q->tx_skbuff_dma[first_entry].buf = des; 3037f8be0d78SMichael Weiser if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) 3038f8be0d78SMichael Weiser first->des0 = cpu_to_le32(des); 3039f8be0d78SMichael Weiser else 3040f8be0d78SMichael Weiser first->des2 = cpu_to_le32(des); 3041f748be53SAlexandre TORGUE 3042ce736788SJoao Pinto tx_q->tx_skbuff_dma[first_entry].len = nopaged_len; 3043ce736788SJoao Pinto tx_q->tx_skbuff_dma[first_entry].last_segment = last_segment; 30440e80bdc9SGiuseppe Cavallaro 3045891434b1SRayagond Kokatanur if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && 3046891434b1SRayagond Kokatanur priv->hwts_tx_en)) { 3047891434b1SRayagond Kokatanur /* declare that device is doing timestamping */ 3048891434b1SRayagond Kokatanur skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 3049891434b1SRayagond Kokatanur priv->hw->desc->enable_tx_timestamp(first); 3050891434b1SRayagond Kokatanur } 3051891434b1SRayagond Kokatanur 30520e80bdc9SGiuseppe Cavallaro /* Prepare the first descriptor setting the OWN bit too */ 30530e80bdc9SGiuseppe Cavallaro priv->hw->desc->prepare_tx_desc(first, 1, nopaged_len, 30540e80bdc9SGiuseppe Cavallaro csum_insertion, priv->mode, 1, 30550e80bdc9SGiuseppe Cavallaro last_segment); 30560e80bdc9SGiuseppe Cavallaro 30570e80bdc9SGiuseppe Cavallaro /* The own bit must be the latest setting done when prepare the 30580e80bdc9SGiuseppe Cavallaro * descriptor and then barrier is needed to make sure that 30590e80bdc9SGiuseppe Cavallaro * all is coherent before granting the DMA engine. 30600e80bdc9SGiuseppe Cavallaro */ 3061ad688cdbSPavel Machek dma_wmb(); 30620e80bdc9SGiuseppe Cavallaro } 30637ac6653aSJeff Kirsher 30645bacd778SLABBE Corentin netdev_sent_queue(dev, skb->len); 3065f748be53SAlexandre TORGUE 3066f748be53SAlexandre TORGUE if (priv->synopsys_id < DWMAC_CORE_4_00) 30677ac6653aSJeff Kirsher priv->hw->dma->enable_dma_transmission(priv->ioaddr); 3068f748be53SAlexandre TORGUE else 3069ce736788SJoao Pinto priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, tx_q->tx_tail_addr, 3070ce736788SJoao Pinto queue); 30717ac6653aSJeff Kirsher 3072362b37beSGiuseppe CAVALLARO return NETDEV_TX_OK; 3073a9097a96SGiuseppe CAVALLARO 3074362b37beSGiuseppe CAVALLARO dma_map_err: 307538ddc59dSLABBE Corentin netdev_err(priv->dev, "Tx DMA map failed\n"); 3076362b37beSGiuseppe CAVALLARO dev_kfree_skb(skb); 3077362b37beSGiuseppe CAVALLARO priv->dev->stats.tx_dropped++; 30787ac6653aSJeff Kirsher return NETDEV_TX_OK; 30797ac6653aSJeff Kirsher } 30807ac6653aSJeff Kirsher 3081b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb) 3082b9381985SVince Bridgers { 3083b9381985SVince Bridgers struct ethhdr *ehdr; 3084b9381985SVince Bridgers u16 vlanid; 3085b9381985SVince Bridgers 3086b9381985SVince Bridgers if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) == 3087b9381985SVince Bridgers NETIF_F_HW_VLAN_CTAG_RX && 3088b9381985SVince Bridgers !__vlan_get_tag(skb, &vlanid)) { 3089b9381985SVince Bridgers /* pop the vlan tag */ 3090b9381985SVince Bridgers ehdr = (struct ethhdr *)skb->data; 3091b9381985SVince Bridgers memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2); 3092b9381985SVince Bridgers skb_pull(skb, VLAN_HLEN); 3093b9381985SVince Bridgers __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid); 3094b9381985SVince Bridgers } 3095b9381985SVince Bridgers } 3096b9381985SVince Bridgers 3097b9381985SVince Bridgers 309854139cf3SJoao Pinto static inline int stmmac_rx_threshold_count(struct stmmac_rx_queue *rx_q) 3099120e87f9SGiuseppe Cavallaro { 310054139cf3SJoao Pinto if (rx_q->rx_zeroc_thresh < STMMAC_RX_THRESH) 3101120e87f9SGiuseppe Cavallaro return 0; 3102120e87f9SGiuseppe Cavallaro 3103120e87f9SGiuseppe Cavallaro return 1; 3104120e87f9SGiuseppe Cavallaro } 3105120e87f9SGiuseppe Cavallaro 310632ceabcaSGiuseppe CAVALLARO /** 3107732fdf0eSGiuseppe CAVALLARO * stmmac_rx_refill - refill used skb preallocated buffers 310832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 310954139cf3SJoao Pinto * @queue: RX queue index 311032ceabcaSGiuseppe CAVALLARO * Description : this is to reallocate the skb for the reception process 311132ceabcaSGiuseppe CAVALLARO * that is based on zero-copy. 311232ceabcaSGiuseppe CAVALLARO */ 311354139cf3SJoao Pinto static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) 31147ac6653aSJeff Kirsher { 311554139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 311654139cf3SJoao Pinto int dirty = stmmac_rx_dirty(priv, queue); 311754139cf3SJoao Pinto unsigned int entry = rx_q->dirty_rx; 311854139cf3SJoao Pinto 31197ac6653aSJeff Kirsher int bfsize = priv->dma_buf_sz; 31207ac6653aSJeff Kirsher 3121e3ad57c9SGiuseppe Cavallaro while (dirty-- > 0) { 3122c24602efSGiuseppe CAVALLARO struct dma_desc *p; 3123c24602efSGiuseppe CAVALLARO 3124c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 312554139cf3SJoao Pinto p = (struct dma_desc *)(rx_q->dma_erx + entry); 3126c24602efSGiuseppe CAVALLARO else 312754139cf3SJoao Pinto p = rx_q->dma_rx + entry; 3128c24602efSGiuseppe CAVALLARO 312954139cf3SJoao Pinto if (likely(!rx_q->rx_skbuff[entry])) { 31307ac6653aSJeff Kirsher struct sk_buff *skb; 31317ac6653aSJeff Kirsher 3132acb600deSEric Dumazet skb = netdev_alloc_skb_ip_align(priv->dev, bfsize); 3133120e87f9SGiuseppe Cavallaro if (unlikely(!skb)) { 3134120e87f9SGiuseppe Cavallaro /* so for a while no zero-copy! */ 313554139cf3SJoao Pinto rx_q->rx_zeroc_thresh = STMMAC_RX_THRESH; 3136120e87f9SGiuseppe Cavallaro if (unlikely(net_ratelimit())) 3137120e87f9SGiuseppe Cavallaro dev_err(priv->device, 3138120e87f9SGiuseppe Cavallaro "fail to alloc skb entry %d\n", 3139120e87f9SGiuseppe Cavallaro entry); 31407ac6653aSJeff Kirsher break; 3141120e87f9SGiuseppe Cavallaro } 31427ac6653aSJeff Kirsher 314354139cf3SJoao Pinto rx_q->rx_skbuff[entry] = skb; 314454139cf3SJoao Pinto rx_q->rx_skbuff_dma[entry] = 31457ac6653aSJeff Kirsher dma_map_single(priv->device, skb->data, bfsize, 31467ac6653aSJeff Kirsher DMA_FROM_DEVICE); 3147362b37beSGiuseppe CAVALLARO if (dma_mapping_error(priv->device, 314854139cf3SJoao Pinto rx_q->rx_skbuff_dma[entry])) { 314938ddc59dSLABBE Corentin netdev_err(priv->dev, "Rx DMA map failed\n"); 3150362b37beSGiuseppe CAVALLARO dev_kfree_skb(skb); 3151362b37beSGiuseppe CAVALLARO break; 3152362b37beSGiuseppe CAVALLARO } 3153286a8372SGiuseppe CAVALLARO 3154f748be53SAlexandre TORGUE if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) { 315554139cf3SJoao Pinto p->des0 = cpu_to_le32(rx_q->rx_skbuff_dma[entry]); 3156f748be53SAlexandre TORGUE p->des1 = 0; 3157f748be53SAlexandre TORGUE } else { 315854139cf3SJoao Pinto p->des2 = cpu_to_le32(rx_q->rx_skbuff_dma[entry]); 3159f748be53SAlexandre TORGUE } 3160f748be53SAlexandre TORGUE if (priv->hw->mode->refill_desc3) 316154139cf3SJoao Pinto priv->hw->mode->refill_desc3(rx_q, p); 3162286a8372SGiuseppe CAVALLARO 316354139cf3SJoao Pinto if (rx_q->rx_zeroc_thresh > 0) 316454139cf3SJoao Pinto rx_q->rx_zeroc_thresh--; 3165120e87f9SGiuseppe Cavallaro 3166b3e51069SLABBE Corentin netif_dbg(priv, rx_status, priv->dev, 316738ddc59dSLABBE Corentin "refill entry #%d\n", entry); 31687ac6653aSJeff Kirsher } 3169ad688cdbSPavel Machek dma_wmb(); 3170f748be53SAlexandre TORGUE 3171f748be53SAlexandre TORGUE if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) 3172f748be53SAlexandre TORGUE priv->hw->desc->init_rx_desc(p, priv->use_riwt, 0, 0); 3173f748be53SAlexandre TORGUE else 3174c24602efSGiuseppe CAVALLARO priv->hw->desc->set_rx_owner(p); 3175f748be53SAlexandre TORGUE 3176ad688cdbSPavel Machek dma_wmb(); 3177e3ad57c9SGiuseppe Cavallaro 3178e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE); 31797ac6653aSJeff Kirsher } 318054139cf3SJoao Pinto rx_q->dirty_rx = entry; 31817ac6653aSJeff Kirsher } 31827ac6653aSJeff Kirsher 318332ceabcaSGiuseppe CAVALLARO /** 3184732fdf0eSGiuseppe CAVALLARO * stmmac_rx - manage the receive process 318532ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 318654139cf3SJoao Pinto * @limit: napi bugget 318754139cf3SJoao Pinto * @queue: RX queue index. 318832ceabcaSGiuseppe CAVALLARO * Description : this the function called by the napi poll method. 318932ceabcaSGiuseppe CAVALLARO * It gets all the frames inside the ring. 319032ceabcaSGiuseppe CAVALLARO */ 319154139cf3SJoao Pinto static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) 31927ac6653aSJeff Kirsher { 319354139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 319454139cf3SJoao Pinto unsigned int entry = rx_q->cur_rx; 319554139cf3SJoao Pinto int coe = priv->hw->rx_csum; 31967ac6653aSJeff Kirsher unsigned int next_entry; 31977ac6653aSJeff Kirsher unsigned int count = 0; 31987ac6653aSJeff Kirsher 319983d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) { 3200d0225e7dSAlexandre TORGUE void *rx_head; 3201d0225e7dSAlexandre TORGUE 320238ddc59dSLABBE Corentin netdev_dbg(priv->dev, "%s: descriptor ring:\n", __func__); 3203c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 320454139cf3SJoao Pinto rx_head = (void *)rx_q->dma_erx; 3205c24602efSGiuseppe CAVALLARO else 320654139cf3SJoao Pinto rx_head = (void *)rx_q->dma_rx; 3207d0225e7dSAlexandre TORGUE 3208d0225e7dSAlexandre TORGUE priv->hw->desc->display_ring(rx_head, DMA_RX_SIZE, true); 32097ac6653aSJeff Kirsher } 3210c24602efSGiuseppe CAVALLARO while (count < limit) { 32117ac6653aSJeff Kirsher int status; 32129401bb5cSGiuseppe CAVALLARO struct dma_desc *p; 3213ba1ffd74SGiuseppe CAVALLARO struct dma_desc *np; 32147ac6653aSJeff Kirsher 3215c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 321654139cf3SJoao Pinto p = (struct dma_desc *)(rx_q->dma_erx + entry); 3217c24602efSGiuseppe CAVALLARO else 321854139cf3SJoao Pinto p = rx_q->dma_rx + entry; 3219c24602efSGiuseppe CAVALLARO 3220c1fa3212SFabrice Gasnier /* read the status of the incoming frame */ 3221c1fa3212SFabrice Gasnier status = priv->hw->desc->rx_status(&priv->dev->stats, 3222c1fa3212SFabrice Gasnier &priv->xstats, p); 3223c1fa3212SFabrice Gasnier /* check if managed by the DMA otherwise go ahead */ 3224c1fa3212SFabrice Gasnier if (unlikely(status & dma_own)) 32257ac6653aSJeff Kirsher break; 32267ac6653aSJeff Kirsher 32277ac6653aSJeff Kirsher count++; 32287ac6653aSJeff Kirsher 322954139cf3SJoao Pinto rx_q->cur_rx = STMMAC_GET_ENTRY(rx_q->cur_rx, DMA_RX_SIZE); 323054139cf3SJoao Pinto next_entry = rx_q->cur_rx; 3231e3ad57c9SGiuseppe Cavallaro 3232c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 323354139cf3SJoao Pinto np = (struct dma_desc *)(rx_q->dma_erx + next_entry); 3234c24602efSGiuseppe CAVALLARO else 323554139cf3SJoao Pinto np = rx_q->dma_rx + next_entry; 3236ba1ffd74SGiuseppe CAVALLARO 3237ba1ffd74SGiuseppe CAVALLARO prefetch(np); 32387ac6653aSJeff Kirsher 3239c24602efSGiuseppe CAVALLARO if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status)) 3240c24602efSGiuseppe CAVALLARO priv->hw->desc->rx_extended_status(&priv->dev->stats, 3241c24602efSGiuseppe CAVALLARO &priv->xstats, 324254139cf3SJoao Pinto rx_q->dma_erx + 3243c24602efSGiuseppe CAVALLARO entry); 3244891434b1SRayagond Kokatanur if (unlikely(status == discard_frame)) { 32457ac6653aSJeff Kirsher priv->dev->stats.rx_errors++; 3246891434b1SRayagond Kokatanur if (priv->hwts_rx_en && !priv->extend_desc) { 32478d45e42bSLABBE Corentin /* DESC2 & DESC3 will be overwritten by device 3248891434b1SRayagond Kokatanur * with timestamp value, hence reinitialize 3249891434b1SRayagond Kokatanur * them in stmmac_rx_refill() function so that 3250891434b1SRayagond Kokatanur * device can reuse it. 3251891434b1SRayagond Kokatanur */ 325254139cf3SJoao Pinto rx_q->rx_skbuff[entry] = NULL; 3253891434b1SRayagond Kokatanur dma_unmap_single(priv->device, 325454139cf3SJoao Pinto rx_q->rx_skbuff_dma[entry], 3255ceb69499SGiuseppe CAVALLARO priv->dma_buf_sz, 3256ceb69499SGiuseppe CAVALLARO DMA_FROM_DEVICE); 3257891434b1SRayagond Kokatanur } 3258891434b1SRayagond Kokatanur } else { 32597ac6653aSJeff Kirsher struct sk_buff *skb; 32607ac6653aSJeff Kirsher int frame_len; 3261f748be53SAlexandre TORGUE unsigned int des; 3262f748be53SAlexandre TORGUE 3263f748be53SAlexandre TORGUE if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) 3264f8be0d78SMichael Weiser des = le32_to_cpu(p->des0); 3265f748be53SAlexandre TORGUE else 3266f8be0d78SMichael Weiser des = le32_to_cpu(p->des2); 32677ac6653aSJeff Kirsher 3268ceb69499SGiuseppe CAVALLARO frame_len = priv->hw->desc->get_rx_frame_len(p, coe); 3269ceb69499SGiuseppe CAVALLARO 32708d45e42bSLABBE Corentin /* If frame length is greater than skb buffer size 3271f748be53SAlexandre TORGUE * (preallocated during init) then the packet is 3272f748be53SAlexandre TORGUE * ignored 3273f748be53SAlexandre TORGUE */ 3274e527c4a7SGiuseppe CAVALLARO if (frame_len > priv->dma_buf_sz) { 327538ddc59dSLABBE Corentin netdev_err(priv->dev, 327638ddc59dSLABBE Corentin "len %d larger than size (%d)\n", 327738ddc59dSLABBE Corentin frame_len, priv->dma_buf_sz); 3278e527c4a7SGiuseppe CAVALLARO priv->dev->stats.rx_length_errors++; 3279e527c4a7SGiuseppe CAVALLARO break; 3280e527c4a7SGiuseppe CAVALLARO } 3281e527c4a7SGiuseppe CAVALLARO 32827ac6653aSJeff Kirsher /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 3283ceb69499SGiuseppe CAVALLARO * Type frames (LLC/LLC-SNAP) 3284ceb69499SGiuseppe CAVALLARO */ 32857ac6653aSJeff Kirsher if (unlikely(status != llc_snap)) 32867ac6653aSJeff Kirsher frame_len -= ETH_FCS_LEN; 32877ac6653aSJeff Kirsher 328883d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) { 328938ddc59dSLABBE Corentin netdev_dbg(priv->dev, "\tdesc: %p [entry %d] buff=0x%x\n", 3290f748be53SAlexandre TORGUE p, entry, des); 329183d7af64SGiuseppe CAVALLARO if (frame_len > ETH_FRAME_LEN) 329238ddc59dSLABBE Corentin netdev_dbg(priv->dev, "frame size %d, COE: %d\n", 329383d7af64SGiuseppe CAVALLARO frame_len, status); 329483d7af64SGiuseppe CAVALLARO } 329522ad3838SGiuseppe Cavallaro 3296f748be53SAlexandre TORGUE /* The zero-copy is always used for all the sizes 3297f748be53SAlexandre TORGUE * in case of GMAC4 because it needs 3298f748be53SAlexandre TORGUE * to refill the used descriptors, always. 3299f748be53SAlexandre TORGUE */ 3300f748be53SAlexandre TORGUE if (unlikely(!priv->plat->has_gmac4 && 3301f748be53SAlexandre TORGUE ((frame_len < priv->rx_copybreak) || 330254139cf3SJoao Pinto stmmac_rx_threshold_count(rx_q)))) { 330322ad3838SGiuseppe Cavallaro skb = netdev_alloc_skb_ip_align(priv->dev, 330422ad3838SGiuseppe Cavallaro frame_len); 330522ad3838SGiuseppe Cavallaro if (unlikely(!skb)) { 330622ad3838SGiuseppe Cavallaro if (net_ratelimit()) 330722ad3838SGiuseppe Cavallaro dev_warn(priv->device, 330822ad3838SGiuseppe Cavallaro "packet dropped\n"); 330922ad3838SGiuseppe Cavallaro priv->dev->stats.rx_dropped++; 331022ad3838SGiuseppe Cavallaro break; 331122ad3838SGiuseppe Cavallaro } 331222ad3838SGiuseppe Cavallaro 331322ad3838SGiuseppe Cavallaro dma_sync_single_for_cpu(priv->device, 331454139cf3SJoao Pinto rx_q->rx_skbuff_dma 331522ad3838SGiuseppe Cavallaro [entry], frame_len, 331622ad3838SGiuseppe Cavallaro DMA_FROM_DEVICE); 331722ad3838SGiuseppe Cavallaro skb_copy_to_linear_data(skb, 331854139cf3SJoao Pinto rx_q-> 331922ad3838SGiuseppe Cavallaro rx_skbuff[entry]->data, 332022ad3838SGiuseppe Cavallaro frame_len); 332122ad3838SGiuseppe Cavallaro 332222ad3838SGiuseppe Cavallaro skb_put(skb, frame_len); 332322ad3838SGiuseppe Cavallaro dma_sync_single_for_device(priv->device, 332454139cf3SJoao Pinto rx_q->rx_skbuff_dma 332522ad3838SGiuseppe Cavallaro [entry], frame_len, 332622ad3838SGiuseppe Cavallaro DMA_FROM_DEVICE); 332722ad3838SGiuseppe Cavallaro } else { 332854139cf3SJoao Pinto skb = rx_q->rx_skbuff[entry]; 33297ac6653aSJeff Kirsher if (unlikely(!skb)) { 333038ddc59dSLABBE Corentin netdev_err(priv->dev, 333138ddc59dSLABBE Corentin "%s: Inconsistent Rx chain\n", 33327ac6653aSJeff Kirsher priv->dev->name); 33337ac6653aSJeff Kirsher priv->dev->stats.rx_dropped++; 33347ac6653aSJeff Kirsher break; 33357ac6653aSJeff Kirsher } 33367ac6653aSJeff Kirsher prefetch(skb->data - NET_IP_ALIGN); 333754139cf3SJoao Pinto rx_q->rx_skbuff[entry] = NULL; 333854139cf3SJoao Pinto rx_q->rx_zeroc_thresh++; 33397ac6653aSJeff Kirsher 33407ac6653aSJeff Kirsher skb_put(skb, frame_len); 33417ac6653aSJeff Kirsher dma_unmap_single(priv->device, 334254139cf3SJoao Pinto rx_q->rx_skbuff_dma[entry], 334322ad3838SGiuseppe Cavallaro priv->dma_buf_sz, 334422ad3838SGiuseppe Cavallaro DMA_FROM_DEVICE); 334522ad3838SGiuseppe Cavallaro } 334622ad3838SGiuseppe Cavallaro 33477ac6653aSJeff Kirsher if (netif_msg_pktdata(priv)) { 334838ddc59dSLABBE Corentin netdev_dbg(priv->dev, "frame received (%dbytes)", 334938ddc59dSLABBE Corentin frame_len); 33507ac6653aSJeff Kirsher print_pkt(skb->data, frame_len); 33517ac6653aSJeff Kirsher } 335283d7af64SGiuseppe CAVALLARO 3353ba1ffd74SGiuseppe CAVALLARO stmmac_get_rx_hwtstamp(priv, p, np, skb); 3354ba1ffd74SGiuseppe CAVALLARO 3355b9381985SVince Bridgers stmmac_rx_vlan(priv->dev, skb); 3356b9381985SVince Bridgers 33577ac6653aSJeff Kirsher skb->protocol = eth_type_trans(skb, priv->dev); 33587ac6653aSJeff Kirsher 3359ceb69499SGiuseppe CAVALLARO if (unlikely(!coe)) 33607ac6653aSJeff Kirsher skb_checksum_none_assert(skb); 336162a2ab93SGiuseppe CAVALLARO else 33627ac6653aSJeff Kirsher skb->ip_summed = CHECKSUM_UNNECESSARY; 336362a2ab93SGiuseppe CAVALLARO 33645bacd778SLABBE Corentin napi_gro_receive(&priv->napi, skb); 33657ac6653aSJeff Kirsher 33667ac6653aSJeff Kirsher priv->dev->stats.rx_packets++; 33677ac6653aSJeff Kirsher priv->dev->stats.rx_bytes += frame_len; 33687ac6653aSJeff Kirsher } 33697ac6653aSJeff Kirsher entry = next_entry; 33707ac6653aSJeff Kirsher } 33717ac6653aSJeff Kirsher 337254139cf3SJoao Pinto stmmac_rx_refill(priv, queue); 33737ac6653aSJeff Kirsher 33747ac6653aSJeff Kirsher priv->xstats.rx_pkt_n += count; 33757ac6653aSJeff Kirsher 33767ac6653aSJeff Kirsher return count; 33777ac6653aSJeff Kirsher } 33787ac6653aSJeff Kirsher 33797ac6653aSJeff Kirsher /** 33807ac6653aSJeff Kirsher * stmmac_poll - stmmac poll method (NAPI) 33817ac6653aSJeff Kirsher * @napi : pointer to the napi structure. 33827ac6653aSJeff Kirsher * @budget : maximum number of packets that the current CPU can receive from 33837ac6653aSJeff Kirsher * all interfaces. 33847ac6653aSJeff Kirsher * Description : 33859125cdd1SGiuseppe CAVALLARO * To look at the incoming frames and clear the tx resources. 33867ac6653aSJeff Kirsher */ 33877ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget) 33887ac6653aSJeff Kirsher { 33895bacd778SLABBE Corentin struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi); 3390ce736788SJoao Pinto u32 tx_count = priv->plat->tx_queues_to_use; 33915bacd778SLABBE Corentin u32 chan = STMMAC_CHAN0; 339254139cf3SJoao Pinto int work_done = 0; 339354139cf3SJoao Pinto u32 queue = chan; 33947ac6653aSJeff Kirsher 33959125cdd1SGiuseppe CAVALLARO priv->xstats.napi_poll++; 3396ce736788SJoao Pinto 3397ce736788SJoao Pinto /* check all the queues */ 3398ce736788SJoao Pinto for (queue = 0; queue < tx_count; queue++) 3399ce736788SJoao Pinto stmmac_tx_clean(priv, queue); 3400ce736788SJoao Pinto 3401ce736788SJoao Pinto queue = chan; 34027ac6653aSJeff Kirsher 340354139cf3SJoao Pinto work_done = stmmac_rx(priv, budget, queue); 34047ac6653aSJeff Kirsher if (work_done < budget) { 34056ad20165SEric Dumazet napi_complete_done(napi, work_done); 34064f513ecdSJoao Pinto stmmac_enable_dma_irq(priv, chan); 34077ac6653aSJeff Kirsher } 34087ac6653aSJeff Kirsher return work_done; 34097ac6653aSJeff Kirsher } 34107ac6653aSJeff Kirsher 34117ac6653aSJeff Kirsher /** 34127ac6653aSJeff Kirsher * stmmac_tx_timeout 34137ac6653aSJeff Kirsher * @dev : Pointer to net device structure 34147ac6653aSJeff Kirsher * Description: this function is called when a packet transmission fails to 34157284a3f1SGiuseppe CAVALLARO * complete within a reasonable time. The driver will mark the error in the 34167ac6653aSJeff Kirsher * netdev structure and arrange for the device to be reset to a sane state 34177ac6653aSJeff Kirsher * in order to transmit a new packet. 34187ac6653aSJeff Kirsher */ 34197ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev) 34207ac6653aSJeff Kirsher { 34217ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 3422ce736788SJoao Pinto u32 tx_count = priv->plat->tx_queues_to_use; 3423ce736788SJoao Pinto u32 chan; 34247ac6653aSJeff Kirsher 34257ac6653aSJeff Kirsher /* Clear Tx resources and restart transmitting again */ 3426ce736788SJoao Pinto for (chan = 0; chan < tx_count; chan++) 34274e593262SJoao Pinto stmmac_tx_err(priv, chan); 34287ac6653aSJeff Kirsher } 34297ac6653aSJeff Kirsher 34307ac6653aSJeff Kirsher /** 343101789349SJiri Pirko * stmmac_set_rx_mode - entry point for multicast addressing 34327ac6653aSJeff Kirsher * @dev : pointer to the device structure 34337ac6653aSJeff Kirsher * Description: 34347ac6653aSJeff Kirsher * This function is a driver entry point which gets called by the kernel 34357ac6653aSJeff Kirsher * whenever multicast addresses must be enabled/disabled. 34367ac6653aSJeff Kirsher * Return value: 34377ac6653aSJeff Kirsher * void. 34387ac6653aSJeff Kirsher */ 343901789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev) 34407ac6653aSJeff Kirsher { 34417ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 34427ac6653aSJeff Kirsher 34433b57de95SVince Bridgers priv->hw->mac->set_filter(priv->hw, dev); 34447ac6653aSJeff Kirsher } 34457ac6653aSJeff Kirsher 34467ac6653aSJeff Kirsher /** 34477ac6653aSJeff Kirsher * stmmac_change_mtu - entry point to change MTU size for the device. 34487ac6653aSJeff Kirsher * @dev : device pointer. 34497ac6653aSJeff Kirsher * @new_mtu : the new MTU size for the device. 34507ac6653aSJeff Kirsher * Description: the Maximum Transfer Unit (MTU) is used by the network layer 34517ac6653aSJeff Kirsher * to drive packet transmission. Ethernet has an MTU of 1500 octets 34527ac6653aSJeff Kirsher * (ETH_DATA_LEN). This value can be changed with ifconfig. 34537ac6653aSJeff Kirsher * Return value: 34547ac6653aSJeff Kirsher * 0 on success and an appropriate (-)ve integer as defined in errno.h 34557ac6653aSJeff Kirsher * file on failure. 34567ac6653aSJeff Kirsher */ 34577ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu) 34587ac6653aSJeff Kirsher { 345938ddc59dSLABBE Corentin struct stmmac_priv *priv = netdev_priv(dev); 346038ddc59dSLABBE Corentin 34617ac6653aSJeff Kirsher if (netif_running(dev)) { 346238ddc59dSLABBE Corentin netdev_err(priv->dev, "must be stopped to change its MTU\n"); 34637ac6653aSJeff Kirsher return -EBUSY; 34647ac6653aSJeff Kirsher } 34657ac6653aSJeff Kirsher 34667ac6653aSJeff Kirsher dev->mtu = new_mtu; 3467f748be53SAlexandre TORGUE 34687ac6653aSJeff Kirsher netdev_update_features(dev); 34697ac6653aSJeff Kirsher 34707ac6653aSJeff Kirsher return 0; 34717ac6653aSJeff Kirsher } 34727ac6653aSJeff Kirsher 3473c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev, 3474c8f44affSMichał Mirosław netdev_features_t features) 34757ac6653aSJeff Kirsher { 34767ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 34777ac6653aSJeff Kirsher 347838912bdbSDeepak SIKRI if (priv->plat->rx_coe == STMMAC_RX_COE_NONE) 34797ac6653aSJeff Kirsher features &= ~NETIF_F_RXCSUM; 3480d2afb5bdSGiuseppe CAVALLARO 34817ac6653aSJeff Kirsher if (!priv->plat->tx_coe) 3482a188222bSTom Herbert features &= ~NETIF_F_CSUM_MASK; 34837ac6653aSJeff Kirsher 34847ac6653aSJeff Kirsher /* Some GMAC devices have a bugged Jumbo frame support that 34857ac6653aSJeff Kirsher * needs to have the Tx COE disabled for oversized frames 34867ac6653aSJeff Kirsher * (due to limited buffer sizes). In this case we disable 3487ceb69499SGiuseppe CAVALLARO * the TX csum insertion in the TDES and not use SF. 3488ceb69499SGiuseppe CAVALLARO */ 34897ac6653aSJeff Kirsher if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN)) 3490a188222bSTom Herbert features &= ~NETIF_F_CSUM_MASK; 34917ac6653aSJeff Kirsher 3492f748be53SAlexandre TORGUE /* Disable tso if asked by ethtool */ 3493f748be53SAlexandre TORGUE if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { 3494f748be53SAlexandre TORGUE if (features & NETIF_F_TSO) 3495f748be53SAlexandre TORGUE priv->tso = true; 3496f748be53SAlexandre TORGUE else 3497f748be53SAlexandre TORGUE priv->tso = false; 3498f748be53SAlexandre TORGUE } 3499f748be53SAlexandre TORGUE 35007ac6653aSJeff Kirsher return features; 35017ac6653aSJeff Kirsher } 35027ac6653aSJeff Kirsher 3503d2afb5bdSGiuseppe CAVALLARO static int stmmac_set_features(struct net_device *netdev, 3504d2afb5bdSGiuseppe CAVALLARO netdev_features_t features) 3505d2afb5bdSGiuseppe CAVALLARO { 3506d2afb5bdSGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(netdev); 3507d2afb5bdSGiuseppe CAVALLARO 3508d2afb5bdSGiuseppe CAVALLARO /* Keep the COE Type in case of csum is supporting */ 3509d2afb5bdSGiuseppe CAVALLARO if (features & NETIF_F_RXCSUM) 3510d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = priv->plat->rx_coe; 3511d2afb5bdSGiuseppe CAVALLARO else 3512d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = 0; 3513d2afb5bdSGiuseppe CAVALLARO /* No check needed because rx_coe has been set before and it will be 3514d2afb5bdSGiuseppe CAVALLARO * fixed in case of issue. 3515d2afb5bdSGiuseppe CAVALLARO */ 3516d2afb5bdSGiuseppe CAVALLARO priv->hw->mac->rx_ipc(priv->hw); 3517d2afb5bdSGiuseppe CAVALLARO 3518d2afb5bdSGiuseppe CAVALLARO return 0; 3519d2afb5bdSGiuseppe CAVALLARO } 3520d2afb5bdSGiuseppe CAVALLARO 352132ceabcaSGiuseppe CAVALLARO /** 352232ceabcaSGiuseppe CAVALLARO * stmmac_interrupt - main ISR 352332ceabcaSGiuseppe CAVALLARO * @irq: interrupt number. 352432ceabcaSGiuseppe CAVALLARO * @dev_id: to pass the net device pointer. 352532ceabcaSGiuseppe CAVALLARO * Description: this is the main driver interrupt service routine. 3526732fdf0eSGiuseppe CAVALLARO * It can call: 3527732fdf0eSGiuseppe CAVALLARO * o DMA service routine (to manage incoming frame reception and transmission 3528732fdf0eSGiuseppe CAVALLARO * status) 3529732fdf0eSGiuseppe CAVALLARO * o Core interrupts to manage: remote wake-up, management counter, LPI 353032ceabcaSGiuseppe CAVALLARO * interrupts. 353132ceabcaSGiuseppe CAVALLARO */ 35327ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id) 35337ac6653aSJeff Kirsher { 35347ac6653aSJeff Kirsher struct net_device *dev = (struct net_device *)dev_id; 35357ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 35367bac4e1eSJoao Pinto u32 rx_cnt = priv->plat->rx_queues_to_use; 35377bac4e1eSJoao Pinto u32 tx_cnt = priv->plat->tx_queues_to_use; 35387bac4e1eSJoao Pinto u32 queues_count; 35397bac4e1eSJoao Pinto u32 queue; 35407bac4e1eSJoao Pinto 35417bac4e1eSJoao Pinto queues_count = (rx_cnt > tx_cnt) ? rx_cnt : tx_cnt; 35427ac6653aSJeff Kirsher 354389f7f2cfSSrinivas Kandagatla if (priv->irq_wake) 354489f7f2cfSSrinivas Kandagatla pm_wakeup_event(priv->device, 0); 354589f7f2cfSSrinivas Kandagatla 35467ac6653aSJeff Kirsher if (unlikely(!dev)) { 354738ddc59dSLABBE Corentin netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__); 35487ac6653aSJeff Kirsher return IRQ_NONE; 35497ac6653aSJeff Kirsher } 35507ac6653aSJeff Kirsher 35517ac6653aSJeff Kirsher /* To handle GMAC own interrupts */ 3552f748be53SAlexandre TORGUE if ((priv->plat->has_gmac) || (priv->plat->has_gmac4)) { 35537ed24bbeSVince Bridgers int status = priv->hw->mac->host_irq_status(priv->hw, 35540982a0f6SGiuseppe CAVALLARO &priv->xstats); 35558f71a88dSJoao Pinto 3556d765955dSGiuseppe CAVALLARO if (unlikely(status)) { 3557d765955dSGiuseppe CAVALLARO /* For LPI we need to save the tx status */ 35580982a0f6SGiuseppe CAVALLARO if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE) 3559d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = true; 35600982a0f6SGiuseppe CAVALLARO if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE) 3561d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = false; 35627bac4e1eSJoao Pinto } 35637bac4e1eSJoao Pinto 35647bac4e1eSJoao Pinto if (priv->synopsys_id >= DWMAC_CORE_4_00) { 35657bac4e1eSJoao Pinto for (queue = 0; queue < queues_count; queue++) { 356654139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = 356754139cf3SJoao Pinto &priv->rx_queue[queue]; 356854139cf3SJoao Pinto 35697bac4e1eSJoao Pinto status |= 35707bac4e1eSJoao Pinto priv->hw->mac->host_mtl_irq_status(priv->hw, 35717bac4e1eSJoao Pinto queue); 35727bac4e1eSJoao Pinto 35737bac4e1eSJoao Pinto if (status & CORE_IRQ_MTL_RX_OVERFLOW && 35747bac4e1eSJoao Pinto priv->hw->dma->set_rx_tail_ptr) 3575f748be53SAlexandre TORGUE priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, 357654139cf3SJoao Pinto rx_q->rx_tail_addr, 35777bac4e1eSJoao Pinto queue); 35787bac4e1eSJoao Pinto } 3579d765955dSGiuseppe CAVALLARO } 358070523e63SGiuseppe CAVALLARO 358170523e63SGiuseppe CAVALLARO /* PCS link status */ 35823fe5cadbSGiuseppe CAVALLARO if (priv->hw->pcs) { 358370523e63SGiuseppe CAVALLARO if (priv->xstats.pcs_link) 358470523e63SGiuseppe CAVALLARO netif_carrier_on(dev); 358570523e63SGiuseppe CAVALLARO else 358670523e63SGiuseppe CAVALLARO netif_carrier_off(dev); 358770523e63SGiuseppe CAVALLARO } 3588d765955dSGiuseppe CAVALLARO } 3589d765955dSGiuseppe CAVALLARO 3590d765955dSGiuseppe CAVALLARO /* To handle DMA interrupts */ 35917ac6653aSJeff Kirsher stmmac_dma_interrupt(priv); 35927ac6653aSJeff Kirsher 35937ac6653aSJeff Kirsher return IRQ_HANDLED; 35947ac6653aSJeff Kirsher } 35957ac6653aSJeff Kirsher 35967ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 35977ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools 3598ceb69499SGiuseppe CAVALLARO * to allow network I/O with interrupts disabled. 3599ceb69499SGiuseppe CAVALLARO */ 36007ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev) 36017ac6653aSJeff Kirsher { 36027ac6653aSJeff Kirsher disable_irq(dev->irq); 36037ac6653aSJeff Kirsher stmmac_interrupt(dev->irq, dev); 36047ac6653aSJeff Kirsher enable_irq(dev->irq); 36057ac6653aSJeff Kirsher } 36067ac6653aSJeff Kirsher #endif 36077ac6653aSJeff Kirsher 36087ac6653aSJeff Kirsher /** 36097ac6653aSJeff Kirsher * stmmac_ioctl - Entry point for the Ioctl 36107ac6653aSJeff Kirsher * @dev: Device pointer. 36117ac6653aSJeff Kirsher * @rq: An IOCTL specefic structure, that can contain a pointer to 36127ac6653aSJeff Kirsher * a proprietary structure used to pass information to the driver. 36137ac6653aSJeff Kirsher * @cmd: IOCTL command 36147ac6653aSJeff Kirsher * Description: 361532ceabcaSGiuseppe CAVALLARO * Currently it supports the phy_mii_ioctl(...) and HW time stamping. 36167ac6653aSJeff Kirsher */ 36177ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 36187ac6653aSJeff Kirsher { 3619891434b1SRayagond Kokatanur int ret = -EOPNOTSUPP; 36207ac6653aSJeff Kirsher 36217ac6653aSJeff Kirsher if (!netif_running(dev)) 36227ac6653aSJeff Kirsher return -EINVAL; 36237ac6653aSJeff Kirsher 3624891434b1SRayagond Kokatanur switch (cmd) { 3625891434b1SRayagond Kokatanur case SIOCGMIIPHY: 3626891434b1SRayagond Kokatanur case SIOCGMIIREG: 3627891434b1SRayagond Kokatanur case SIOCSMIIREG: 3628d6d50c7eSPhilippe Reynes if (!dev->phydev) 36297ac6653aSJeff Kirsher return -EINVAL; 3630d6d50c7eSPhilippe Reynes ret = phy_mii_ioctl(dev->phydev, rq, cmd); 3631891434b1SRayagond Kokatanur break; 3632891434b1SRayagond Kokatanur case SIOCSHWTSTAMP: 3633891434b1SRayagond Kokatanur ret = stmmac_hwtstamp_ioctl(dev, rq); 3634891434b1SRayagond Kokatanur break; 3635891434b1SRayagond Kokatanur default: 3636891434b1SRayagond Kokatanur break; 3637891434b1SRayagond Kokatanur } 36387ac6653aSJeff Kirsher 36397ac6653aSJeff Kirsher return ret; 36407ac6653aSJeff Kirsher } 36417ac6653aSJeff Kirsher 364250fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 36437ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir; 36447ac29055SGiuseppe CAVALLARO 3645c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc, 3646c24602efSGiuseppe CAVALLARO struct seq_file *seq) 36477ac29055SGiuseppe CAVALLARO { 36487ac29055SGiuseppe CAVALLARO int i; 3649c24602efSGiuseppe CAVALLARO struct dma_extended_desc *ep = (struct dma_extended_desc *)head; 3650c24602efSGiuseppe CAVALLARO struct dma_desc *p = (struct dma_desc *)head; 36517ac29055SGiuseppe CAVALLARO 3652c24602efSGiuseppe CAVALLARO for (i = 0; i < size; i++) { 3653c24602efSGiuseppe CAVALLARO if (extend_desc) { 3654c24602efSGiuseppe CAVALLARO seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 3655c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 3656f8be0d78SMichael Weiser le32_to_cpu(ep->basic.des0), 3657f8be0d78SMichael Weiser le32_to_cpu(ep->basic.des1), 3658f8be0d78SMichael Weiser le32_to_cpu(ep->basic.des2), 3659f8be0d78SMichael Weiser le32_to_cpu(ep->basic.des3)); 3660c24602efSGiuseppe CAVALLARO ep++; 3661c24602efSGiuseppe CAVALLARO } else { 3662c24602efSGiuseppe CAVALLARO seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 3663c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 3664f8be0d78SMichael Weiser le32_to_cpu(p->des0), le32_to_cpu(p->des1), 3665f8be0d78SMichael Weiser le32_to_cpu(p->des2), le32_to_cpu(p->des3)); 3666c24602efSGiuseppe CAVALLARO p++; 3667c24602efSGiuseppe CAVALLARO } 36687ac29055SGiuseppe CAVALLARO seq_printf(seq, "\n"); 36697ac29055SGiuseppe CAVALLARO } 3670c24602efSGiuseppe CAVALLARO } 36717ac29055SGiuseppe CAVALLARO 3672c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v) 3673c24602efSGiuseppe CAVALLARO { 3674c24602efSGiuseppe CAVALLARO struct net_device *dev = seq->private; 3675c24602efSGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(dev); 367654139cf3SJoao Pinto u32 rx_count = priv->plat->rx_queues_to_use; 3677ce736788SJoao Pinto u32 tx_count = priv->plat->tx_queues_to_use; 367854139cf3SJoao Pinto u32 queue; 367954139cf3SJoao Pinto 368054139cf3SJoao Pinto for (queue = 0; queue < rx_count; queue++) { 368154139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 368254139cf3SJoao Pinto 368354139cf3SJoao Pinto seq_printf(seq, "RX Queue %d:\n", queue); 36847ac29055SGiuseppe CAVALLARO 3685c24602efSGiuseppe CAVALLARO if (priv->extend_desc) { 368654139cf3SJoao Pinto seq_printf(seq, "Extended descriptor ring:\n"); 368754139cf3SJoao Pinto sysfs_display_ring((void *)rx_q->dma_erx, 368854139cf3SJoao Pinto DMA_RX_SIZE, 1, seq); 368954139cf3SJoao Pinto } else { 369054139cf3SJoao Pinto seq_printf(seq, "Descriptor ring:\n"); 369154139cf3SJoao Pinto sysfs_display_ring((void *)rx_q->dma_rx, 369254139cf3SJoao Pinto DMA_RX_SIZE, 0, seq); 369354139cf3SJoao Pinto } 369454139cf3SJoao Pinto } 369554139cf3SJoao Pinto 3696ce736788SJoao Pinto for (queue = 0; queue < tx_count; queue++) { 3697ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 3698ce736788SJoao Pinto 3699ce736788SJoao Pinto seq_printf(seq, "TX Queue %d:\n", queue); 3700ce736788SJoao Pinto 370154139cf3SJoao Pinto if (priv->extend_desc) { 3702ce736788SJoao Pinto seq_printf(seq, "Extended descriptor ring:\n"); 3703ce736788SJoao Pinto sysfs_display_ring((void *)tx_q->dma_etx, 3704ce736788SJoao Pinto DMA_TX_SIZE, 1, seq); 3705c24602efSGiuseppe CAVALLARO } else { 3706ce736788SJoao Pinto seq_printf(seq, "Descriptor ring:\n"); 3707ce736788SJoao Pinto sysfs_display_ring((void *)tx_q->dma_tx, 3708ce736788SJoao Pinto DMA_TX_SIZE, 0, seq); 3709ce736788SJoao Pinto } 37107ac29055SGiuseppe CAVALLARO } 37117ac29055SGiuseppe CAVALLARO 37127ac29055SGiuseppe CAVALLARO return 0; 37137ac29055SGiuseppe CAVALLARO } 37147ac29055SGiuseppe CAVALLARO 37157ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file) 37167ac29055SGiuseppe CAVALLARO { 37177ac29055SGiuseppe CAVALLARO return single_open(file, stmmac_sysfs_ring_read, inode->i_private); 37187ac29055SGiuseppe CAVALLARO } 37197ac29055SGiuseppe CAVALLARO 372022d3efe5SPavel Machek /* Debugfs files, should appear in /sys/kernel/debug/stmmaceth/eth0 */ 372122d3efe5SPavel Machek 37227ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = { 37237ac29055SGiuseppe CAVALLARO .owner = THIS_MODULE, 37247ac29055SGiuseppe CAVALLARO .open = stmmac_sysfs_ring_open, 37257ac29055SGiuseppe CAVALLARO .read = seq_read, 37267ac29055SGiuseppe CAVALLARO .llseek = seq_lseek, 372774863948SDjalal Harouni .release = single_release, 37287ac29055SGiuseppe CAVALLARO }; 37297ac29055SGiuseppe CAVALLARO 3730e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v) 3731e7434821SGiuseppe CAVALLARO { 3732e7434821SGiuseppe CAVALLARO struct net_device *dev = seq->private; 3733e7434821SGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(dev); 3734e7434821SGiuseppe CAVALLARO 373519e30c14SGiuseppe CAVALLARO if (!priv->hw_cap_support) { 3736e7434821SGiuseppe CAVALLARO seq_printf(seq, "DMA HW features not supported\n"); 3737e7434821SGiuseppe CAVALLARO return 0; 3738e7434821SGiuseppe CAVALLARO } 3739e7434821SGiuseppe CAVALLARO 3740e7434821SGiuseppe CAVALLARO seq_printf(seq, "==============================\n"); 3741e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tDMA HW features\n"); 3742e7434821SGiuseppe CAVALLARO seq_printf(seq, "==============================\n"); 3743e7434821SGiuseppe CAVALLARO 374422d3efe5SPavel Machek seq_printf(seq, "\t10/100 Mbps: %s\n", 3745e7434821SGiuseppe CAVALLARO (priv->dma_cap.mbps_10_100) ? "Y" : "N"); 374622d3efe5SPavel Machek seq_printf(seq, "\t1000 Mbps: %s\n", 3747e7434821SGiuseppe CAVALLARO (priv->dma_cap.mbps_1000) ? "Y" : "N"); 374822d3efe5SPavel Machek seq_printf(seq, "\tHalf duplex: %s\n", 3749e7434821SGiuseppe CAVALLARO (priv->dma_cap.half_duplex) ? "Y" : "N"); 3750e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tHash Filter: %s\n", 3751e7434821SGiuseppe CAVALLARO (priv->dma_cap.hash_filter) ? "Y" : "N"); 3752e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tMultiple MAC address registers: %s\n", 3753e7434821SGiuseppe CAVALLARO (priv->dma_cap.multi_addr) ? "Y" : "N"); 37548d45e42bSLABBE Corentin seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfaces): %s\n", 3755e7434821SGiuseppe CAVALLARO (priv->dma_cap.pcs) ? "Y" : "N"); 3756e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tSMA (MDIO) Interface: %s\n", 3757e7434821SGiuseppe CAVALLARO (priv->dma_cap.sma_mdio) ? "Y" : "N"); 3758e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPMT Remote wake up: %s\n", 3759e7434821SGiuseppe CAVALLARO (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N"); 3760e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPMT Magic Frame: %s\n", 3761e7434821SGiuseppe CAVALLARO (priv->dma_cap.pmt_magic_frame) ? "Y" : "N"); 3762e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tRMON module: %s\n", 3763e7434821SGiuseppe CAVALLARO (priv->dma_cap.rmon) ? "Y" : "N"); 3764e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n", 3765e7434821SGiuseppe CAVALLARO (priv->dma_cap.time_stamp) ? "Y" : "N"); 3766e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp: %s\n", 3767e7434821SGiuseppe CAVALLARO (priv->dma_cap.atime_stamp) ? "Y" : "N"); 376822d3efe5SPavel Machek seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE): %s\n", 3769e7434821SGiuseppe CAVALLARO (priv->dma_cap.eee) ? "Y" : "N"); 3770e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N"); 3771e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tChecksum Offload in TX: %s\n", 3772e7434821SGiuseppe CAVALLARO (priv->dma_cap.tx_coe) ? "Y" : "N"); 3773f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) { 3774f748be53SAlexandre TORGUE seq_printf(seq, "\tIP Checksum Offload in RX: %s\n", 3775f748be53SAlexandre TORGUE (priv->dma_cap.rx_coe) ? "Y" : "N"); 3776f748be53SAlexandre TORGUE } else { 3777e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n", 3778e7434821SGiuseppe CAVALLARO (priv->dma_cap.rx_coe_type1) ? "Y" : "N"); 3779e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n", 3780e7434821SGiuseppe CAVALLARO (priv->dma_cap.rx_coe_type2) ? "Y" : "N"); 3781f748be53SAlexandre TORGUE } 3782e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n", 3783e7434821SGiuseppe CAVALLARO (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N"); 3784e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tNumber of Additional RX channel: %d\n", 3785e7434821SGiuseppe CAVALLARO priv->dma_cap.number_rx_channel); 3786e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tNumber of Additional TX channel: %d\n", 3787e7434821SGiuseppe CAVALLARO priv->dma_cap.number_tx_channel); 3788e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tEnhanced descriptors: %s\n", 3789e7434821SGiuseppe CAVALLARO (priv->dma_cap.enh_desc) ? "Y" : "N"); 3790e7434821SGiuseppe CAVALLARO 3791e7434821SGiuseppe CAVALLARO return 0; 3792e7434821SGiuseppe CAVALLARO } 3793e7434821SGiuseppe CAVALLARO 3794e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file) 3795e7434821SGiuseppe CAVALLARO { 3796e7434821SGiuseppe CAVALLARO return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private); 3797e7434821SGiuseppe CAVALLARO } 3798e7434821SGiuseppe CAVALLARO 3799e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = { 3800e7434821SGiuseppe CAVALLARO .owner = THIS_MODULE, 3801e7434821SGiuseppe CAVALLARO .open = stmmac_sysfs_dma_cap_open, 3802e7434821SGiuseppe CAVALLARO .read = seq_read, 3803e7434821SGiuseppe CAVALLARO .llseek = seq_lseek, 380474863948SDjalal Harouni .release = single_release, 3805e7434821SGiuseppe CAVALLARO }; 3806e7434821SGiuseppe CAVALLARO 38077ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev) 38087ac29055SGiuseppe CAVALLARO { 3809466c5ac8SMathieu Olivari struct stmmac_priv *priv = netdev_priv(dev); 38107ac29055SGiuseppe CAVALLARO 3811466c5ac8SMathieu Olivari /* Create per netdev entries */ 3812466c5ac8SMathieu Olivari priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir); 3813466c5ac8SMathieu Olivari 3814466c5ac8SMathieu Olivari if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) { 381538ddc59dSLABBE Corentin netdev_err(priv->dev, "ERROR failed to create debugfs directory\n"); 38167ac29055SGiuseppe CAVALLARO 38177ac29055SGiuseppe CAVALLARO return -ENOMEM; 38187ac29055SGiuseppe CAVALLARO } 38197ac29055SGiuseppe CAVALLARO 38207ac29055SGiuseppe CAVALLARO /* Entry to report DMA RX/TX rings */ 3821466c5ac8SMathieu Olivari priv->dbgfs_rings_status = 3822466c5ac8SMathieu Olivari debugfs_create_file("descriptors_status", S_IRUGO, 3823466c5ac8SMathieu Olivari priv->dbgfs_dir, dev, 38247ac29055SGiuseppe CAVALLARO &stmmac_rings_status_fops); 38257ac29055SGiuseppe CAVALLARO 3826466c5ac8SMathieu Olivari if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) { 382738ddc59dSLABBE Corentin netdev_err(priv->dev, "ERROR creating stmmac ring debugfs file\n"); 3828466c5ac8SMathieu Olivari debugfs_remove_recursive(priv->dbgfs_dir); 38297ac29055SGiuseppe CAVALLARO 38307ac29055SGiuseppe CAVALLARO return -ENOMEM; 38317ac29055SGiuseppe CAVALLARO } 38327ac29055SGiuseppe CAVALLARO 3833e7434821SGiuseppe CAVALLARO /* Entry to report the DMA HW features */ 3834466c5ac8SMathieu Olivari priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, 3835466c5ac8SMathieu Olivari priv->dbgfs_dir, 3836e7434821SGiuseppe CAVALLARO dev, &stmmac_dma_cap_fops); 3837e7434821SGiuseppe CAVALLARO 3838466c5ac8SMathieu Olivari if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) { 383938ddc59dSLABBE Corentin netdev_err(priv->dev, "ERROR creating stmmac MMC debugfs file\n"); 3840466c5ac8SMathieu Olivari debugfs_remove_recursive(priv->dbgfs_dir); 3841e7434821SGiuseppe CAVALLARO 3842e7434821SGiuseppe CAVALLARO return -ENOMEM; 3843e7434821SGiuseppe CAVALLARO } 3844e7434821SGiuseppe CAVALLARO 38457ac29055SGiuseppe CAVALLARO return 0; 38467ac29055SGiuseppe CAVALLARO } 38477ac29055SGiuseppe CAVALLARO 3848466c5ac8SMathieu Olivari static void stmmac_exit_fs(struct net_device *dev) 38497ac29055SGiuseppe CAVALLARO { 3850466c5ac8SMathieu Olivari struct stmmac_priv *priv = netdev_priv(dev); 3851466c5ac8SMathieu Olivari 3852466c5ac8SMathieu Olivari debugfs_remove_recursive(priv->dbgfs_dir); 38537ac29055SGiuseppe CAVALLARO } 385450fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */ 38557ac29055SGiuseppe CAVALLARO 38567ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = { 38577ac6653aSJeff Kirsher .ndo_open = stmmac_open, 38587ac6653aSJeff Kirsher .ndo_start_xmit = stmmac_xmit, 38597ac6653aSJeff Kirsher .ndo_stop = stmmac_release, 38607ac6653aSJeff Kirsher .ndo_change_mtu = stmmac_change_mtu, 38617ac6653aSJeff Kirsher .ndo_fix_features = stmmac_fix_features, 3862d2afb5bdSGiuseppe CAVALLARO .ndo_set_features = stmmac_set_features, 386301789349SJiri Pirko .ndo_set_rx_mode = stmmac_set_rx_mode, 38647ac6653aSJeff Kirsher .ndo_tx_timeout = stmmac_tx_timeout, 38657ac6653aSJeff Kirsher .ndo_do_ioctl = stmmac_ioctl, 38667ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 38677ac6653aSJeff Kirsher .ndo_poll_controller = stmmac_poll_controller, 38687ac6653aSJeff Kirsher #endif 38697ac6653aSJeff Kirsher .ndo_set_mac_address = eth_mac_addr, 38707ac6653aSJeff Kirsher }; 38717ac6653aSJeff Kirsher 38727ac6653aSJeff Kirsher /** 3873cf3f047bSGiuseppe CAVALLARO * stmmac_hw_init - Init the MAC device 387432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 3875732fdf0eSGiuseppe CAVALLARO * Description: this function is to configure the MAC device according to 3876732fdf0eSGiuseppe CAVALLARO * some platform parameters or the HW capability register. It prepares the 3877732fdf0eSGiuseppe CAVALLARO * driver to use either ring or chain modes and to setup either enhanced or 3878732fdf0eSGiuseppe CAVALLARO * normal descriptors. 3879cf3f047bSGiuseppe CAVALLARO */ 3880cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv) 3881cf3f047bSGiuseppe CAVALLARO { 3882cf3f047bSGiuseppe CAVALLARO struct mac_device_info *mac; 3883cf3f047bSGiuseppe CAVALLARO 3884cf3f047bSGiuseppe CAVALLARO /* Identify the MAC HW device */ 388503f2eecdSMarc Kleine-Budde if (priv->plat->has_gmac) { 388603f2eecdSMarc Kleine-Budde priv->dev->priv_flags |= IFF_UNICAST_FLT; 38873b57de95SVince Bridgers mac = dwmac1000_setup(priv->ioaddr, 38883b57de95SVince Bridgers priv->plat->multicast_filter_bins, 3889c623d149SAlexandre TORGUE priv->plat->unicast_filter_entries, 3890c623d149SAlexandre TORGUE &priv->synopsys_id); 3891f748be53SAlexandre TORGUE } else if (priv->plat->has_gmac4) { 3892f748be53SAlexandre TORGUE priv->dev->priv_flags |= IFF_UNICAST_FLT; 3893f748be53SAlexandre TORGUE mac = dwmac4_setup(priv->ioaddr, 3894f748be53SAlexandre TORGUE priv->plat->multicast_filter_bins, 3895f748be53SAlexandre TORGUE priv->plat->unicast_filter_entries, 3896f748be53SAlexandre TORGUE &priv->synopsys_id); 389703f2eecdSMarc Kleine-Budde } else { 3898c623d149SAlexandre TORGUE mac = dwmac100_setup(priv->ioaddr, &priv->synopsys_id); 389903f2eecdSMarc Kleine-Budde } 3900cf3f047bSGiuseppe CAVALLARO if (!mac) 3901cf3f047bSGiuseppe CAVALLARO return -ENOMEM; 3902cf3f047bSGiuseppe CAVALLARO 3903cf3f047bSGiuseppe CAVALLARO priv->hw = mac; 3904cf3f047bSGiuseppe CAVALLARO 39054a7d666aSGiuseppe CAVALLARO /* To use the chained or ring mode */ 3906f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) { 3907f748be53SAlexandre TORGUE priv->hw->mode = &dwmac4_ring_mode_ops; 3908f748be53SAlexandre TORGUE } else { 39094a7d666aSGiuseppe CAVALLARO if (chain_mode) { 391029896a67SGiuseppe CAVALLARO priv->hw->mode = &chain_mode_ops; 391138ddc59dSLABBE Corentin dev_info(priv->device, "Chain mode enabled\n"); 39124a7d666aSGiuseppe CAVALLARO priv->mode = STMMAC_CHAIN_MODE; 39134a7d666aSGiuseppe CAVALLARO } else { 391429896a67SGiuseppe CAVALLARO priv->hw->mode = &ring_mode_ops; 391538ddc59dSLABBE Corentin dev_info(priv->device, "Ring mode enabled\n"); 39164a7d666aSGiuseppe CAVALLARO priv->mode = STMMAC_RING_MODE; 39174a7d666aSGiuseppe CAVALLARO } 3918f748be53SAlexandre TORGUE } 39194a7d666aSGiuseppe CAVALLARO 3920cf3f047bSGiuseppe CAVALLARO /* Get the HW capability (new GMAC newer than 3.50a) */ 3921cf3f047bSGiuseppe CAVALLARO priv->hw_cap_support = stmmac_get_hw_features(priv); 3922cf3f047bSGiuseppe CAVALLARO if (priv->hw_cap_support) { 392338ddc59dSLABBE Corentin dev_info(priv->device, "DMA HW capability register supported\n"); 3924cf3f047bSGiuseppe CAVALLARO 3925cf3f047bSGiuseppe CAVALLARO /* We can override some gmac/dma configuration fields: e.g. 3926cf3f047bSGiuseppe CAVALLARO * enh_desc, tx_coe (e.g. that are passed through the 3927cf3f047bSGiuseppe CAVALLARO * platform) with the values from the HW capability 3928cf3f047bSGiuseppe CAVALLARO * register (if supported). 3929cf3f047bSGiuseppe CAVALLARO */ 3930cf3f047bSGiuseppe CAVALLARO priv->plat->enh_desc = priv->dma_cap.enh_desc; 3931cf3f047bSGiuseppe CAVALLARO priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; 39323fe5cadbSGiuseppe CAVALLARO priv->hw->pmt = priv->plat->pmt; 393338912bdbSDeepak SIKRI 3934a8df35d4SEzequiel Garcia /* TXCOE doesn't work in thresh DMA mode */ 3935a8df35d4SEzequiel Garcia if (priv->plat->force_thresh_dma_mode) 3936a8df35d4SEzequiel Garcia priv->plat->tx_coe = 0; 3937a8df35d4SEzequiel Garcia else 393838912bdbSDeepak SIKRI priv->plat->tx_coe = priv->dma_cap.tx_coe; 3939a8df35d4SEzequiel Garcia 3940f748be53SAlexandre TORGUE /* In case of GMAC4 rx_coe is from HW cap register. */ 3941f748be53SAlexandre TORGUE priv->plat->rx_coe = priv->dma_cap.rx_coe; 394238912bdbSDeepak SIKRI 394338912bdbSDeepak SIKRI if (priv->dma_cap.rx_coe_type2) 394438912bdbSDeepak SIKRI priv->plat->rx_coe = STMMAC_RX_COE_TYPE2; 394538912bdbSDeepak SIKRI else if (priv->dma_cap.rx_coe_type1) 394638912bdbSDeepak SIKRI priv->plat->rx_coe = STMMAC_RX_COE_TYPE1; 394738912bdbSDeepak SIKRI 394838ddc59dSLABBE Corentin } else { 394938ddc59dSLABBE Corentin dev_info(priv->device, "No HW DMA feature register supported\n"); 395038ddc59dSLABBE Corentin } 3951cf3f047bSGiuseppe CAVALLARO 3952f748be53SAlexandre TORGUE /* To use alternate (extended), normal or GMAC4 descriptor structures */ 3953f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) 3954f748be53SAlexandre TORGUE priv->hw->desc = &dwmac4_desc_ops; 3955f748be53SAlexandre TORGUE else 395661369d02SByungho An stmmac_selec_desc_mode(priv); 395761369d02SByungho An 3958d2afb5bdSGiuseppe CAVALLARO if (priv->plat->rx_coe) { 3959d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = priv->plat->rx_coe; 396038ddc59dSLABBE Corentin dev_info(priv->device, "RX Checksum Offload Engine supported\n"); 3961f748be53SAlexandre TORGUE if (priv->synopsys_id < DWMAC_CORE_4_00) 396238ddc59dSLABBE Corentin dev_info(priv->device, "COE Type %d\n", priv->hw->rx_csum); 3963d2afb5bdSGiuseppe CAVALLARO } 3964cf3f047bSGiuseppe CAVALLARO if (priv->plat->tx_coe) 396538ddc59dSLABBE Corentin dev_info(priv->device, "TX Checksum insertion supported\n"); 3966cf3f047bSGiuseppe CAVALLARO 3967cf3f047bSGiuseppe CAVALLARO if (priv->plat->pmt) { 396838ddc59dSLABBE Corentin dev_info(priv->device, "Wake-Up On Lan supported\n"); 3969cf3f047bSGiuseppe CAVALLARO device_set_wakeup_capable(priv->device, 1); 3970cf3f047bSGiuseppe CAVALLARO } 3971cf3f047bSGiuseppe CAVALLARO 3972f748be53SAlexandre TORGUE if (priv->dma_cap.tsoen) 397338ddc59dSLABBE Corentin dev_info(priv->device, "TSO supported\n"); 3974f748be53SAlexandre TORGUE 3975c24602efSGiuseppe CAVALLARO return 0; 3976cf3f047bSGiuseppe CAVALLARO } 3977cf3f047bSGiuseppe CAVALLARO 3978cf3f047bSGiuseppe CAVALLARO /** 3979bfab27a1SGiuseppe CAVALLARO * stmmac_dvr_probe 3980bfab27a1SGiuseppe CAVALLARO * @device: device pointer 3981ff3dd78cSGiuseppe CAVALLARO * @plat_dat: platform data pointer 3982e56788cfSJoachim Eastwood * @res: stmmac resource pointer 3983bfab27a1SGiuseppe CAVALLARO * Description: this is the main probe function used to 3984bfab27a1SGiuseppe CAVALLARO * call the alloc_etherdev, allocate the priv structure. 39859afec6efSAndy Shevchenko * Return: 398615ffac73SJoachim Eastwood * returns 0 on success, otherwise errno. 39877ac6653aSJeff Kirsher */ 398815ffac73SJoachim Eastwood int stmmac_dvr_probe(struct device *device, 3989cf3f047bSGiuseppe CAVALLARO struct plat_stmmacenet_data *plat_dat, 3990e56788cfSJoachim Eastwood struct stmmac_resources *res) 39917ac6653aSJeff Kirsher { 39925bacd778SLABBE Corentin int ret = 0; 3993bfab27a1SGiuseppe CAVALLARO struct net_device *ndev = NULL; 3994bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *priv; 39957ac6653aSJeff Kirsher 39965bacd778SLABBE Corentin ndev = alloc_etherdev(sizeof(struct stmmac_priv)); 399741de8d4cSJoe Perches if (!ndev) 399815ffac73SJoachim Eastwood return -ENOMEM; 39997ac6653aSJeff Kirsher 4000bfab27a1SGiuseppe CAVALLARO SET_NETDEV_DEV(ndev, device); 40017ac6653aSJeff Kirsher 4002bfab27a1SGiuseppe CAVALLARO priv = netdev_priv(ndev); 4003bfab27a1SGiuseppe CAVALLARO priv->device = device; 4004bfab27a1SGiuseppe CAVALLARO priv->dev = ndev; 4005bfab27a1SGiuseppe CAVALLARO 4006bfab27a1SGiuseppe CAVALLARO stmmac_set_ethtool_ops(ndev); 4007cf3f047bSGiuseppe CAVALLARO priv->pause = pause; 4008cf3f047bSGiuseppe CAVALLARO priv->plat = plat_dat; 4009e56788cfSJoachim Eastwood priv->ioaddr = res->addr; 4010e56788cfSJoachim Eastwood priv->dev->base_addr = (unsigned long)res->addr; 4011e56788cfSJoachim Eastwood 4012e56788cfSJoachim Eastwood priv->dev->irq = res->irq; 4013e56788cfSJoachim Eastwood priv->wol_irq = res->wol_irq; 4014e56788cfSJoachim Eastwood priv->lpi_irq = res->lpi_irq; 4015e56788cfSJoachim Eastwood 4016e56788cfSJoachim Eastwood if (res->mac) 4017e56788cfSJoachim Eastwood memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN); 4018bfab27a1SGiuseppe CAVALLARO 4019a7a62685SJoachim Eastwood dev_set_drvdata(device, priv->dev); 4020803f8fc4SJoachim Eastwood 4021cf3f047bSGiuseppe CAVALLARO /* Verify driver arguments */ 4022cf3f047bSGiuseppe CAVALLARO stmmac_verify_args(); 4023cf3f047bSGiuseppe CAVALLARO 4024cf3f047bSGiuseppe CAVALLARO /* Override with kernel parameters if supplied XXX CRS XXX 4025ceb69499SGiuseppe CAVALLARO * this needs to have multiple instances 4026ceb69499SGiuseppe CAVALLARO */ 4027cf3f047bSGiuseppe CAVALLARO if ((phyaddr >= 0) && (phyaddr <= 31)) 4028cf3f047bSGiuseppe CAVALLARO priv->plat->phy_addr = phyaddr; 4029cf3f047bSGiuseppe CAVALLARO 4030f573c0b9Sjpinto if (priv->plat->stmmac_rst) 4031f573c0b9Sjpinto reset_control_deassert(priv->plat->stmmac_rst); 4032c5e4ddbdSChen-Yu Tsai 4033cf3f047bSGiuseppe CAVALLARO /* Init MAC and get the capabilities */ 4034c24602efSGiuseppe CAVALLARO ret = stmmac_hw_init(priv); 4035c24602efSGiuseppe CAVALLARO if (ret) 403662866e98SChen-Yu Tsai goto error_hw_init; 4037cf3f047bSGiuseppe CAVALLARO 4038cf3f047bSGiuseppe CAVALLARO ndev->netdev_ops = &stmmac_netdev_ops; 4039cf3f047bSGiuseppe CAVALLARO 4040cf3f047bSGiuseppe CAVALLARO ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | 4041cf3f047bSGiuseppe CAVALLARO NETIF_F_RXCSUM; 4042f748be53SAlexandre TORGUE 4043f748be53SAlexandre TORGUE if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { 4044f748be53SAlexandre TORGUE ndev->hw_features |= NETIF_F_TSO; 4045f748be53SAlexandre TORGUE priv->tso = true; 404638ddc59dSLABBE Corentin dev_info(priv->device, "TSO feature enabled\n"); 4047f748be53SAlexandre TORGUE } 4048bfab27a1SGiuseppe CAVALLARO ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; 4049bfab27a1SGiuseppe CAVALLARO ndev->watchdog_timeo = msecs_to_jiffies(watchdog); 40507ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED 40517ac6653aSJeff Kirsher /* Both mac100 and gmac support receive VLAN tag detection */ 4052f646968fSPatrick McHardy ndev->features |= NETIF_F_HW_VLAN_CTAG_RX; 40537ac6653aSJeff Kirsher #endif 40547ac6653aSJeff Kirsher priv->msg_enable = netif_msg_init(debug, default_msg_level); 40557ac6653aSJeff Kirsher 405644770e11SJarod Wilson /* MTU range: 46 - hw-specific max */ 405744770e11SJarod Wilson ndev->min_mtu = ETH_ZLEN - ETH_HLEN; 405844770e11SJarod Wilson if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00)) 405944770e11SJarod Wilson ndev->max_mtu = JUMBO_LEN; 406044770e11SJarod Wilson else 406144770e11SJarod Wilson ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN); 4062a2cd64f3SKweh, Hock Leong /* Will not overwrite ndev->max_mtu if plat->maxmtu > ndev->max_mtu 4063a2cd64f3SKweh, Hock Leong * as well as plat->maxmtu < ndev->min_mtu which is a invalid range. 4064a2cd64f3SKweh, Hock Leong */ 4065a2cd64f3SKweh, Hock Leong if ((priv->plat->maxmtu < ndev->max_mtu) && 4066a2cd64f3SKweh, Hock Leong (priv->plat->maxmtu >= ndev->min_mtu)) 406744770e11SJarod Wilson ndev->max_mtu = priv->plat->maxmtu; 4068a2cd64f3SKweh, Hock Leong else if (priv->plat->maxmtu < ndev->min_mtu) 4069b618ab45SHeiner Kallweit dev_warn(priv->device, 4070a2cd64f3SKweh, Hock Leong "%s: warning: maxmtu having invalid value (%d)\n", 4071a2cd64f3SKweh, Hock Leong __func__, priv->plat->maxmtu); 407244770e11SJarod Wilson 40737ac6653aSJeff Kirsher if (flow_ctrl) 40747ac6653aSJeff Kirsher priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ 40757ac6653aSJeff Kirsher 407662a2ab93SGiuseppe CAVALLARO /* Rx Watchdog is available in the COREs newer than the 3.40. 407762a2ab93SGiuseppe CAVALLARO * In some case, for example on bugged HW this feature 407862a2ab93SGiuseppe CAVALLARO * has to be disable and this can be done by passing the 407962a2ab93SGiuseppe CAVALLARO * riwt_off field from the platform. 408062a2ab93SGiuseppe CAVALLARO */ 408162a2ab93SGiuseppe CAVALLARO if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) { 408262a2ab93SGiuseppe CAVALLARO priv->use_riwt = 1; 4083b618ab45SHeiner Kallweit dev_info(priv->device, 4084b618ab45SHeiner Kallweit "Enable RX Mitigation via HW Watchdog Timer\n"); 408562a2ab93SGiuseppe CAVALLARO } 408662a2ab93SGiuseppe CAVALLARO 40875bacd778SLABBE Corentin netif_napi_add(ndev, &priv->napi, stmmac_poll, 64); 40887ac6653aSJeff Kirsher 40897ac6653aSJeff Kirsher spin_lock_init(&priv->lock); 40907ac6653aSJeff Kirsher 4091cd7201f4SGiuseppe CAVALLARO /* If a specific clk_csr value is passed from the platform 4092cd7201f4SGiuseppe CAVALLARO * this means that the CSR Clock Range selection cannot be 4093cd7201f4SGiuseppe CAVALLARO * changed at run-time and it is fixed. Viceversa the driver'll try to 4094cd7201f4SGiuseppe CAVALLARO * set the MDC clock dynamically according to the csr actual 4095cd7201f4SGiuseppe CAVALLARO * clock input. 4096cd7201f4SGiuseppe CAVALLARO */ 4097cd7201f4SGiuseppe CAVALLARO if (!priv->plat->clk_csr) 4098cd7201f4SGiuseppe CAVALLARO stmmac_clk_csr_set(priv); 4099cd7201f4SGiuseppe CAVALLARO else 4100cd7201f4SGiuseppe CAVALLARO priv->clk_csr = priv->plat->clk_csr; 4101cd7201f4SGiuseppe CAVALLARO 4102e58bb43fSGiuseppe CAVALLARO stmmac_check_pcs_mode(priv); 4103e58bb43fSGiuseppe CAVALLARO 41043fe5cadbSGiuseppe CAVALLARO if (priv->hw->pcs != STMMAC_PCS_RGMII && 41053fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_TBI && 41063fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_RTBI) { 41074bfcbd7aSFrancesco Virlinzi /* MDIO bus Registration */ 41084bfcbd7aSFrancesco Virlinzi ret = stmmac_mdio_register(ndev); 41094bfcbd7aSFrancesco Virlinzi if (ret < 0) { 4110b618ab45SHeiner Kallweit dev_err(priv->device, 411138ddc59dSLABBE Corentin "%s: MDIO bus (id: %d) registration failed", 41124bfcbd7aSFrancesco Virlinzi __func__, priv->plat->bus_id); 41136a81c26fSViresh Kumar goto error_mdio_register; 41144bfcbd7aSFrancesco Virlinzi } 4115e58bb43fSGiuseppe CAVALLARO } 41164bfcbd7aSFrancesco Virlinzi 411757016590SFlorian Fainelli ret = register_netdev(ndev); 4118b2eb09afSFlorian Fainelli if (ret) { 4119b618ab45SHeiner Kallweit dev_err(priv->device, "%s: ERROR %i registering the device\n", 412057016590SFlorian Fainelli __func__, ret); 4121b2eb09afSFlorian Fainelli goto error_netdev_register; 4122b2eb09afSFlorian Fainelli } 41237ac6653aSJeff Kirsher 412457016590SFlorian Fainelli return ret; 41257ac6653aSJeff Kirsher 41266a81c26fSViresh Kumar error_netdev_register: 4127b2eb09afSFlorian Fainelli if (priv->hw->pcs != STMMAC_PCS_RGMII && 4128b2eb09afSFlorian Fainelli priv->hw->pcs != STMMAC_PCS_TBI && 4129b2eb09afSFlorian Fainelli priv->hw->pcs != STMMAC_PCS_RTBI) 4130b2eb09afSFlorian Fainelli stmmac_mdio_unregister(ndev); 41317ac6653aSJeff Kirsher error_mdio_register: 41325bacd778SLABBE Corentin netif_napi_del(&priv->napi); 413362866e98SChen-Yu Tsai error_hw_init: 41347ac6653aSJeff Kirsher free_netdev(ndev); 41357ac6653aSJeff Kirsher 413615ffac73SJoachim Eastwood return ret; 41377ac6653aSJeff Kirsher } 4138b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_probe); 41397ac6653aSJeff Kirsher 41407ac6653aSJeff Kirsher /** 41417ac6653aSJeff Kirsher * stmmac_dvr_remove 4142f4e7bd81SJoachim Eastwood * @dev: device pointer 41437ac6653aSJeff Kirsher * Description: this function resets the TX/RX processes, disables the MAC RX/TX 4144bfab27a1SGiuseppe CAVALLARO * changes the link status, releases the DMA descriptor rings. 41457ac6653aSJeff Kirsher */ 4146f4e7bd81SJoachim Eastwood int stmmac_dvr_remove(struct device *dev) 41477ac6653aSJeff Kirsher { 4148f4e7bd81SJoachim Eastwood struct net_device *ndev = dev_get_drvdata(dev); 41497ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 41507ac6653aSJeff Kirsher 415138ddc59dSLABBE Corentin netdev_info(priv->dev, "%s: removing driver", __func__); 41527ac6653aSJeff Kirsher 4153ae4f0d46SJoao Pinto stmmac_stop_all_dma(priv); 41547ac6653aSJeff Kirsher 4155270c7759SLABBE Corentin priv->hw->mac->set_mac(priv->ioaddr, false); 41567ac6653aSJeff Kirsher netif_carrier_off(ndev); 41577ac6653aSJeff Kirsher unregister_netdev(ndev); 4158f573c0b9Sjpinto if (priv->plat->stmmac_rst) 4159f573c0b9Sjpinto reset_control_assert(priv->plat->stmmac_rst); 4160f573c0b9Sjpinto clk_disable_unprepare(priv->plat->pclk); 4161f573c0b9Sjpinto clk_disable_unprepare(priv->plat->stmmac_clk); 41623fe5cadbSGiuseppe CAVALLARO if (priv->hw->pcs != STMMAC_PCS_RGMII && 41633fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_TBI && 41643fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_RTBI) 4165e743471fSBryan O'Donoghue stmmac_mdio_unregister(ndev); 41667ac6653aSJeff Kirsher free_netdev(ndev); 41677ac6653aSJeff Kirsher 41687ac6653aSJeff Kirsher return 0; 41697ac6653aSJeff Kirsher } 4170b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_remove); 41717ac6653aSJeff Kirsher 4172732fdf0eSGiuseppe CAVALLARO /** 4173732fdf0eSGiuseppe CAVALLARO * stmmac_suspend - suspend callback 4174f4e7bd81SJoachim Eastwood * @dev: device pointer 4175732fdf0eSGiuseppe CAVALLARO * Description: this is the function to suspend the device and it is called 4176732fdf0eSGiuseppe CAVALLARO * by the platform driver to stop the network queue, release the resources, 4177732fdf0eSGiuseppe CAVALLARO * program the PMT register (for WoL), clean and release driver resources. 4178732fdf0eSGiuseppe CAVALLARO */ 4179f4e7bd81SJoachim Eastwood int stmmac_suspend(struct device *dev) 41807ac6653aSJeff Kirsher { 4181f4e7bd81SJoachim Eastwood struct net_device *ndev = dev_get_drvdata(dev); 41827ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 4183f8c5a875SGiuseppe CAVALLARO unsigned long flags; 41847ac6653aSJeff Kirsher 41857ac6653aSJeff Kirsher if (!ndev || !netif_running(ndev)) 41867ac6653aSJeff Kirsher return 0; 41877ac6653aSJeff Kirsher 4188d6d50c7eSPhilippe Reynes if (ndev->phydev) 4189d6d50c7eSPhilippe Reynes phy_stop(ndev->phydev); 4190102463b1SFrancesco Virlinzi 4191f8c5a875SGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 41927ac6653aSJeff Kirsher 41937ac6653aSJeff Kirsher netif_device_detach(ndev); 41945bacd778SLABBE Corentin netif_stop_queue(ndev); 41957ac6653aSJeff Kirsher 41965bacd778SLABBE Corentin napi_disable(&priv->napi); 41977ac6653aSJeff Kirsher 41987ac6653aSJeff Kirsher /* Stop TX/RX DMA */ 4199ae4f0d46SJoao Pinto stmmac_stop_all_dma(priv); 4200c24602efSGiuseppe CAVALLARO 42017ac6653aSJeff Kirsher /* Enable Power down mode by programming the PMT regs */ 420289f7f2cfSSrinivas Kandagatla if (device_may_wakeup(priv->device)) { 42037ed24bbeSVince Bridgers priv->hw->mac->pmt(priv->hw, priv->wolopts); 420489f7f2cfSSrinivas Kandagatla priv->irq_wake = 1; 420589f7f2cfSSrinivas Kandagatla } else { 4206270c7759SLABBE Corentin priv->hw->mac->set_mac(priv->ioaddr, false); 4207db88f10aSSrinivas Kandagatla pinctrl_pm_select_sleep_state(priv->device); 4208ba1377ffSGiuseppe CAVALLARO /* Disable clock in case of PWM is off */ 4209f573c0b9Sjpinto clk_disable(priv->plat->pclk); 4210f573c0b9Sjpinto clk_disable(priv->plat->stmmac_clk); 4211ba1377ffSGiuseppe CAVALLARO } 4212f8c5a875SGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 42132d871aa0SVince Bridgers 42142d871aa0SVince Bridgers priv->oldlink = 0; 4215bd00632cSLABBE Corentin priv->speed = SPEED_UNKNOWN; 4216bd00632cSLABBE Corentin priv->oldduplex = DUPLEX_UNKNOWN; 42177ac6653aSJeff Kirsher return 0; 42187ac6653aSJeff Kirsher } 4219b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_suspend); 42207ac6653aSJeff Kirsher 4221732fdf0eSGiuseppe CAVALLARO /** 422254139cf3SJoao Pinto * stmmac_reset_queues_param - reset queue parameters 422354139cf3SJoao Pinto * @dev: device pointer 422454139cf3SJoao Pinto */ 422554139cf3SJoao Pinto static void stmmac_reset_queues_param(struct stmmac_priv *priv) 422654139cf3SJoao Pinto { 422754139cf3SJoao Pinto u32 rx_cnt = priv->plat->rx_queues_to_use; 4228ce736788SJoao Pinto u32 tx_cnt = priv->plat->tx_queues_to_use; 422954139cf3SJoao Pinto u32 queue; 423054139cf3SJoao Pinto 423154139cf3SJoao Pinto for (queue = 0; queue < rx_cnt; queue++) { 423254139cf3SJoao Pinto struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; 423354139cf3SJoao Pinto 423454139cf3SJoao Pinto rx_q->cur_rx = 0; 423554139cf3SJoao Pinto rx_q->dirty_rx = 0; 423654139cf3SJoao Pinto } 423754139cf3SJoao Pinto 4238ce736788SJoao Pinto for (queue = 0; queue < tx_cnt; queue++) { 4239ce736788SJoao Pinto struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; 4240ce736788SJoao Pinto 4241ce736788SJoao Pinto tx_q->cur_tx = 0; 4242ce736788SJoao Pinto tx_q->dirty_tx = 0; 4243ce736788SJoao Pinto } 424454139cf3SJoao Pinto } 424554139cf3SJoao Pinto 424654139cf3SJoao Pinto /** 4247732fdf0eSGiuseppe CAVALLARO * stmmac_resume - resume callback 4248f4e7bd81SJoachim Eastwood * @dev: device pointer 4249732fdf0eSGiuseppe CAVALLARO * Description: when resume this function is invoked to setup the DMA and CORE 4250732fdf0eSGiuseppe CAVALLARO * in a usable state. 4251732fdf0eSGiuseppe CAVALLARO */ 4252f4e7bd81SJoachim Eastwood int stmmac_resume(struct device *dev) 42537ac6653aSJeff Kirsher { 4254f4e7bd81SJoachim Eastwood struct net_device *ndev = dev_get_drvdata(dev); 42557ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 4256f8c5a875SGiuseppe CAVALLARO unsigned long flags; 42577ac6653aSJeff Kirsher 42587ac6653aSJeff Kirsher if (!netif_running(ndev)) 42597ac6653aSJeff Kirsher return 0; 42607ac6653aSJeff Kirsher 42617ac6653aSJeff Kirsher /* Power Down bit, into the PM register, is cleared 42627ac6653aSJeff Kirsher * automatically as soon as a magic packet or a Wake-up frame 42637ac6653aSJeff Kirsher * is received. Anyway, it's better to manually clear 42647ac6653aSJeff Kirsher * this bit because it can generate problems while resuming 4265ceb69499SGiuseppe CAVALLARO * from another devices (e.g. serial console). 4266ceb69499SGiuseppe CAVALLARO */ 4267623997fbSSrinivas Kandagatla if (device_may_wakeup(priv->device)) { 4268f55d84b0SVincent Palatin spin_lock_irqsave(&priv->lock, flags); 42697ed24bbeSVince Bridgers priv->hw->mac->pmt(priv->hw, 0); 4270f55d84b0SVincent Palatin spin_unlock_irqrestore(&priv->lock, flags); 427189f7f2cfSSrinivas Kandagatla priv->irq_wake = 0; 4272623997fbSSrinivas Kandagatla } else { 4273db88f10aSSrinivas Kandagatla pinctrl_pm_select_default_state(priv->device); 42748d45e42bSLABBE Corentin /* enable the clk previously disabled */ 4275f573c0b9Sjpinto clk_enable(priv->plat->stmmac_clk); 4276f573c0b9Sjpinto clk_enable(priv->plat->pclk); 4277623997fbSSrinivas Kandagatla /* reset the phy so that it's ready */ 4278623997fbSSrinivas Kandagatla if (priv->mii) 4279623997fbSSrinivas Kandagatla stmmac_mdio_reset(priv->mii); 4280623997fbSSrinivas Kandagatla } 42817ac6653aSJeff Kirsher 42827ac6653aSJeff Kirsher netif_device_attach(ndev); 42837ac6653aSJeff Kirsher 4284f55d84b0SVincent Palatin spin_lock_irqsave(&priv->lock, flags); 4285f55d84b0SVincent Palatin 428654139cf3SJoao Pinto stmmac_reset_queues_param(priv); 428754139cf3SJoao Pinto 4288f748be53SAlexandre TORGUE /* reset private mss value to force mss context settings at 4289f748be53SAlexandre TORGUE * next tso xmit (only used for gmac4). 4290f748be53SAlexandre TORGUE */ 4291f748be53SAlexandre TORGUE priv->mss = 0; 4292f748be53SAlexandre TORGUE 4293ae79a639SGiuseppe CAVALLARO stmmac_clear_descriptors(priv); 4294ae79a639SGiuseppe CAVALLARO 4295fe131929SHuacai Chen stmmac_hw_setup(ndev, false); 4296777da230SGiuseppe CAVALLARO stmmac_init_tx_coalesce(priv); 4297ac316c78SGiuseppe CAVALLARO stmmac_set_rx_mode(ndev); 42987ac6653aSJeff Kirsher 42995bacd778SLABBE Corentin napi_enable(&priv->napi); 43007ac6653aSJeff Kirsher 43015bacd778SLABBE Corentin netif_start_queue(ndev); 43027ac6653aSJeff Kirsher 4303f8c5a875SGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 4304102463b1SFrancesco Virlinzi 4305d6d50c7eSPhilippe Reynes if (ndev->phydev) 4306d6d50c7eSPhilippe Reynes phy_start(ndev->phydev); 4307102463b1SFrancesco Virlinzi 43087ac6653aSJeff Kirsher return 0; 43097ac6653aSJeff Kirsher } 4310b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_resume); 4311ba27ec66SGiuseppe CAVALLARO 43127ac6653aSJeff Kirsher #ifndef MODULE 43137ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str) 43147ac6653aSJeff Kirsher { 43157ac6653aSJeff Kirsher char *opt; 43167ac6653aSJeff Kirsher 43177ac6653aSJeff Kirsher if (!str || !*str) 43187ac6653aSJeff Kirsher return -EINVAL; 43197ac6653aSJeff Kirsher while ((opt = strsep(&str, ",")) != NULL) { 43207ac6653aSJeff Kirsher if (!strncmp(opt, "debug:", 6)) { 4321ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 6, 0, &debug)) 43227ac6653aSJeff Kirsher goto err; 43237ac6653aSJeff Kirsher } else if (!strncmp(opt, "phyaddr:", 8)) { 4324ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 8, 0, &phyaddr)) 43257ac6653aSJeff Kirsher goto err; 43267ac6653aSJeff Kirsher } else if (!strncmp(opt, "buf_sz:", 7)) { 4327ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 7, 0, &buf_sz)) 43287ac6653aSJeff Kirsher goto err; 43297ac6653aSJeff Kirsher } else if (!strncmp(opt, "tc:", 3)) { 4330ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 3, 0, &tc)) 43317ac6653aSJeff Kirsher goto err; 43327ac6653aSJeff Kirsher } else if (!strncmp(opt, "watchdog:", 9)) { 4333ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 9, 0, &watchdog)) 43347ac6653aSJeff Kirsher goto err; 43357ac6653aSJeff Kirsher } else if (!strncmp(opt, "flow_ctrl:", 10)) { 4336ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 10, 0, &flow_ctrl)) 43377ac6653aSJeff Kirsher goto err; 43387ac6653aSJeff Kirsher } else if (!strncmp(opt, "pause:", 6)) { 4339ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 6, 0, &pause)) 43407ac6653aSJeff Kirsher goto err; 4341506f669cSGiuseppe CAVALLARO } else if (!strncmp(opt, "eee_timer:", 10)) { 4342d765955dSGiuseppe CAVALLARO if (kstrtoint(opt + 10, 0, &eee_timer)) 4343d765955dSGiuseppe CAVALLARO goto err; 43444a7d666aSGiuseppe CAVALLARO } else if (!strncmp(opt, "chain_mode:", 11)) { 43454a7d666aSGiuseppe CAVALLARO if (kstrtoint(opt + 11, 0, &chain_mode)) 43464a7d666aSGiuseppe CAVALLARO goto err; 43477ac6653aSJeff Kirsher } 43487ac6653aSJeff Kirsher } 43497ac6653aSJeff Kirsher return 0; 43507ac6653aSJeff Kirsher 43517ac6653aSJeff Kirsher err: 43527ac6653aSJeff Kirsher pr_err("%s: ERROR broken module parameter conversion", __func__); 43537ac6653aSJeff Kirsher return -EINVAL; 43547ac6653aSJeff Kirsher } 43557ac6653aSJeff Kirsher 43567ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt); 4357ceb69499SGiuseppe CAVALLARO #endif /* MODULE */ 43586fc0d0f2SGiuseppe Cavallaro 4359466c5ac8SMathieu Olivari static int __init stmmac_init(void) 4360466c5ac8SMathieu Olivari { 4361466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS 4362466c5ac8SMathieu Olivari /* Create debugfs main directory if it doesn't exist yet */ 4363466c5ac8SMathieu Olivari if (!stmmac_fs_dir) { 4364466c5ac8SMathieu Olivari stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL); 4365466c5ac8SMathieu Olivari 4366466c5ac8SMathieu Olivari if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) { 4367466c5ac8SMathieu Olivari pr_err("ERROR %s, debugfs create directory failed\n", 4368466c5ac8SMathieu Olivari STMMAC_RESOURCE_NAME); 4369466c5ac8SMathieu Olivari 4370466c5ac8SMathieu Olivari return -ENOMEM; 4371466c5ac8SMathieu Olivari } 4372466c5ac8SMathieu Olivari } 4373466c5ac8SMathieu Olivari #endif 4374466c5ac8SMathieu Olivari 4375466c5ac8SMathieu Olivari return 0; 4376466c5ac8SMathieu Olivari } 4377466c5ac8SMathieu Olivari 4378466c5ac8SMathieu Olivari static void __exit stmmac_exit(void) 4379466c5ac8SMathieu Olivari { 4380466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS 4381466c5ac8SMathieu Olivari debugfs_remove_recursive(stmmac_fs_dir); 4382466c5ac8SMathieu Olivari #endif 4383466c5ac8SMathieu Olivari } 4384466c5ac8SMathieu Olivari 4385466c5ac8SMathieu Olivari module_init(stmmac_init) 4386466c5ac8SMathieu Olivari module_exit(stmmac_exit) 4387466c5ac8SMathieu Olivari 43886fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver"); 43896fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); 43906fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL"); 4391