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 1887ac6653aSJeff Kirsher static inline u32 stmmac_tx_avail(struct stmmac_priv *priv) 1897ac6653aSJeff Kirsher { 190a6a3e026SLABBE Corentin u32 avail; 191e3ad57c9SGiuseppe Cavallaro 192e3ad57c9SGiuseppe Cavallaro if (priv->dirty_tx > priv->cur_tx) 193e3ad57c9SGiuseppe Cavallaro avail = priv->dirty_tx - priv->cur_tx - 1; 194e3ad57c9SGiuseppe Cavallaro else 195e3ad57c9SGiuseppe Cavallaro avail = DMA_TX_SIZE - priv->cur_tx + priv->dirty_tx - 1; 196e3ad57c9SGiuseppe Cavallaro 197e3ad57c9SGiuseppe Cavallaro return avail; 198e3ad57c9SGiuseppe Cavallaro } 199e3ad57c9SGiuseppe Cavallaro 200e3ad57c9SGiuseppe Cavallaro static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv) 201e3ad57c9SGiuseppe Cavallaro { 202a6a3e026SLABBE Corentin u32 dirty; 203e3ad57c9SGiuseppe Cavallaro 204e3ad57c9SGiuseppe Cavallaro if (priv->dirty_rx <= priv->cur_rx) 205e3ad57c9SGiuseppe Cavallaro dirty = priv->cur_rx - priv->dirty_rx; 206e3ad57c9SGiuseppe Cavallaro else 207e3ad57c9SGiuseppe Cavallaro dirty = DMA_RX_SIZE - priv->dirty_rx + priv->cur_rx; 208e3ad57c9SGiuseppe Cavallaro 209e3ad57c9SGiuseppe Cavallaro return dirty; 2107ac6653aSJeff Kirsher } 2117ac6653aSJeff Kirsher 21232ceabcaSGiuseppe CAVALLARO /** 213732fdf0eSGiuseppe CAVALLARO * stmmac_hw_fix_mac_speed - callback for speed selection 21432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 2158d45e42bSLABBE Corentin * Description: on some platforms (e.g. ST), some HW system configuration 21632ceabcaSGiuseppe CAVALLARO * registers have to be set according to the link speed negotiated. 2177ac6653aSJeff Kirsher */ 2187ac6653aSJeff Kirsher static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv) 2197ac6653aSJeff Kirsher { 220d6d50c7eSPhilippe Reynes struct net_device *ndev = priv->dev; 221d6d50c7eSPhilippe Reynes struct phy_device *phydev = ndev->phydev; 2227ac6653aSJeff Kirsher 2237ac6653aSJeff Kirsher if (likely(priv->plat->fix_mac_speed)) 224ceb69499SGiuseppe CAVALLARO priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed); 2257ac6653aSJeff Kirsher } 2267ac6653aSJeff Kirsher 22732ceabcaSGiuseppe CAVALLARO /** 228732fdf0eSGiuseppe CAVALLARO * stmmac_enable_eee_mode - check and enter in LPI mode 22932ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 230732fdf0eSGiuseppe CAVALLARO * Description: this function is to verify and enter in LPI mode in case of 231732fdf0eSGiuseppe CAVALLARO * EEE. 23232ceabcaSGiuseppe CAVALLARO */ 233d765955dSGiuseppe CAVALLARO static void stmmac_enable_eee_mode(struct stmmac_priv *priv) 234d765955dSGiuseppe CAVALLARO { 235d765955dSGiuseppe CAVALLARO /* Check and enter in LPI mode */ 236d765955dSGiuseppe CAVALLARO if ((priv->dirty_tx == priv->cur_tx) && 237d765955dSGiuseppe CAVALLARO (priv->tx_path_in_lpi_mode == false)) 238b4b7b772Sjpinto priv->hw->mac->set_eee_mode(priv->hw, 239b4b7b772Sjpinto priv->plat->en_tx_lpi_clockgating); 240d765955dSGiuseppe CAVALLARO } 241d765955dSGiuseppe CAVALLARO 24232ceabcaSGiuseppe CAVALLARO /** 243732fdf0eSGiuseppe CAVALLARO * stmmac_disable_eee_mode - disable and exit from LPI mode 24432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 24532ceabcaSGiuseppe CAVALLARO * Description: this function is to exit and disable EEE in case of 24632ceabcaSGiuseppe CAVALLARO * LPI state is true. This is called by the xmit. 24732ceabcaSGiuseppe CAVALLARO */ 248d765955dSGiuseppe CAVALLARO void stmmac_disable_eee_mode(struct stmmac_priv *priv) 249d765955dSGiuseppe CAVALLARO { 2507ed24bbeSVince Bridgers priv->hw->mac->reset_eee_mode(priv->hw); 251d765955dSGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 252d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = false; 253d765955dSGiuseppe CAVALLARO } 254d765955dSGiuseppe CAVALLARO 255d765955dSGiuseppe CAVALLARO /** 256732fdf0eSGiuseppe CAVALLARO * stmmac_eee_ctrl_timer - EEE TX SW timer. 257d765955dSGiuseppe CAVALLARO * @arg : data hook 258d765955dSGiuseppe CAVALLARO * Description: 25932ceabcaSGiuseppe CAVALLARO * if there is no data transfer and if we are not in LPI state, 260d765955dSGiuseppe CAVALLARO * then MAC Transmitter can be moved to LPI state. 261d765955dSGiuseppe CAVALLARO */ 262d765955dSGiuseppe CAVALLARO static void stmmac_eee_ctrl_timer(unsigned long arg) 263d765955dSGiuseppe CAVALLARO { 264d765955dSGiuseppe CAVALLARO struct stmmac_priv *priv = (struct stmmac_priv *)arg; 265d765955dSGiuseppe CAVALLARO 266d765955dSGiuseppe CAVALLARO stmmac_enable_eee_mode(priv); 267f5351ef7SGiuseppe CAVALLARO mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); 268d765955dSGiuseppe CAVALLARO } 269d765955dSGiuseppe CAVALLARO 270d765955dSGiuseppe CAVALLARO /** 271732fdf0eSGiuseppe CAVALLARO * stmmac_eee_init - init EEE 27232ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 273d765955dSGiuseppe CAVALLARO * Description: 274732fdf0eSGiuseppe CAVALLARO * if the GMAC supports the EEE (from the HW cap reg) and the phy device 275732fdf0eSGiuseppe CAVALLARO * can also manage EEE, this function enable the LPI state and start related 276732fdf0eSGiuseppe CAVALLARO * timer. 277d765955dSGiuseppe CAVALLARO */ 278d765955dSGiuseppe CAVALLARO bool stmmac_eee_init(struct stmmac_priv *priv) 279d765955dSGiuseppe CAVALLARO { 280d6d50c7eSPhilippe Reynes struct net_device *ndev = priv->dev; 2814741cf9cSGiuseppe CAVALLARO unsigned long flags; 282d765955dSGiuseppe CAVALLARO bool ret = false; 283d765955dSGiuseppe CAVALLARO 284f5351ef7SGiuseppe CAVALLARO /* Using PCS we cannot dial with the phy registers at this stage 285f5351ef7SGiuseppe CAVALLARO * so we do not support extra feature like EEE. 286f5351ef7SGiuseppe CAVALLARO */ 2873fe5cadbSGiuseppe CAVALLARO if ((priv->hw->pcs == STMMAC_PCS_RGMII) || 2883fe5cadbSGiuseppe CAVALLARO (priv->hw->pcs == STMMAC_PCS_TBI) || 2893fe5cadbSGiuseppe CAVALLARO (priv->hw->pcs == STMMAC_PCS_RTBI)) 290f5351ef7SGiuseppe CAVALLARO goto out; 291f5351ef7SGiuseppe CAVALLARO 292d765955dSGiuseppe CAVALLARO /* MAC core supports the EEE feature. */ 293d765955dSGiuseppe CAVALLARO if (priv->dma_cap.eee) { 29483bf79b6SGiuseppe CAVALLARO int tx_lpi_timer = priv->tx_lpi_timer; 295d765955dSGiuseppe CAVALLARO 29683bf79b6SGiuseppe CAVALLARO /* Check if the PHY supports EEE */ 297d6d50c7eSPhilippe Reynes if (phy_init_eee(ndev->phydev, 1)) { 29883bf79b6SGiuseppe CAVALLARO /* To manage at run-time if the EEE cannot be supported 29983bf79b6SGiuseppe CAVALLARO * anymore (for example because the lp caps have been 30083bf79b6SGiuseppe CAVALLARO * changed). 30183bf79b6SGiuseppe CAVALLARO * In that case the driver disable own timers. 30283bf79b6SGiuseppe CAVALLARO */ 3034741cf9cSGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 30483bf79b6SGiuseppe CAVALLARO if (priv->eee_active) { 30538ddc59dSLABBE Corentin netdev_dbg(priv->dev, "disable EEE\n"); 30683bf79b6SGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 3077ed24bbeSVince Bridgers priv->hw->mac->set_eee_timer(priv->hw, 0, 30883bf79b6SGiuseppe CAVALLARO tx_lpi_timer); 30983bf79b6SGiuseppe CAVALLARO } 31083bf79b6SGiuseppe CAVALLARO priv->eee_active = 0; 3114741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 31283bf79b6SGiuseppe CAVALLARO goto out; 31383bf79b6SGiuseppe CAVALLARO } 31483bf79b6SGiuseppe CAVALLARO /* Activate the EEE and start timers */ 3154741cf9cSGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 316f5351ef7SGiuseppe CAVALLARO if (!priv->eee_active) { 317d765955dSGiuseppe CAVALLARO priv->eee_active = 1; 318ccb36da1SVaishali Thakkar setup_timer(&priv->eee_ctrl_timer, 319ccb36da1SVaishali Thakkar stmmac_eee_ctrl_timer, 320ccb36da1SVaishali Thakkar (unsigned long)priv); 321ccb36da1SVaishali Thakkar mod_timer(&priv->eee_ctrl_timer, 322ccb36da1SVaishali Thakkar STMMAC_LPI_T(eee_timer)); 323d765955dSGiuseppe CAVALLARO 3247ed24bbeSVince Bridgers priv->hw->mac->set_eee_timer(priv->hw, 325f5351ef7SGiuseppe CAVALLARO STMMAC_DEFAULT_LIT_LS, 32683bf79b6SGiuseppe CAVALLARO tx_lpi_timer); 32771965352SGiuseppe CAVALLARO } 328f5351ef7SGiuseppe CAVALLARO /* Set HW EEE according to the speed */ 329d6d50c7eSPhilippe Reynes priv->hw->mac->set_eee_pls(priv->hw, ndev->phydev->link); 330d765955dSGiuseppe CAVALLARO 331d765955dSGiuseppe CAVALLARO ret = true; 3324741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 3334741cf9cSGiuseppe CAVALLARO 33438ddc59dSLABBE Corentin netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n"); 335d765955dSGiuseppe CAVALLARO } 336d765955dSGiuseppe CAVALLARO out: 337d765955dSGiuseppe CAVALLARO return ret; 338d765955dSGiuseppe CAVALLARO } 339d765955dSGiuseppe CAVALLARO 340732fdf0eSGiuseppe CAVALLARO /* stmmac_get_tx_hwtstamp - get HW TX timestamps 34132ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 342ba1ffd74SGiuseppe CAVALLARO * @p : descriptor pointer 343891434b1SRayagond Kokatanur * @skb : the socket buffer 344891434b1SRayagond Kokatanur * Description : 345891434b1SRayagond Kokatanur * This function will read timestamp from the descriptor & pass it to stack. 346891434b1SRayagond Kokatanur * and also perform some sanity checks. 347891434b1SRayagond Kokatanur */ 348891434b1SRayagond Kokatanur static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, 349ba1ffd74SGiuseppe CAVALLARO struct dma_desc *p, struct sk_buff *skb) 350891434b1SRayagond Kokatanur { 351891434b1SRayagond Kokatanur struct skb_shared_hwtstamps shhwtstamp; 352891434b1SRayagond Kokatanur u64 ns; 353891434b1SRayagond Kokatanur 354891434b1SRayagond Kokatanur if (!priv->hwts_tx_en) 355891434b1SRayagond Kokatanur return; 356891434b1SRayagond Kokatanur 357ceb69499SGiuseppe CAVALLARO /* exit if skb doesn't support hw tstamp */ 35875e4364fSdamuzi000 if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))) 359891434b1SRayagond Kokatanur return; 360891434b1SRayagond Kokatanur 361891434b1SRayagond Kokatanur /* check tx tstamp status */ 362ba1ffd74SGiuseppe CAVALLARO if (!priv->hw->desc->get_tx_timestamp_status(p)) { 363891434b1SRayagond Kokatanur /* get the valid tstamp */ 364ba1ffd74SGiuseppe CAVALLARO ns = priv->hw->desc->get_timestamp(p, priv->adv_ts); 365891434b1SRayagond Kokatanur 366891434b1SRayagond Kokatanur memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); 367891434b1SRayagond Kokatanur shhwtstamp.hwtstamp = ns_to_ktime(ns); 368ba1ffd74SGiuseppe CAVALLARO 369ba1ffd74SGiuseppe CAVALLARO netdev_info(priv->dev, "get valid TX hw timestamp %llu\n", ns); 370891434b1SRayagond Kokatanur /* pass tstamp to stack */ 371891434b1SRayagond Kokatanur skb_tstamp_tx(skb, &shhwtstamp); 372ba1ffd74SGiuseppe CAVALLARO } 373891434b1SRayagond Kokatanur 374891434b1SRayagond Kokatanur return; 375891434b1SRayagond Kokatanur } 376891434b1SRayagond Kokatanur 377732fdf0eSGiuseppe CAVALLARO /* stmmac_get_rx_hwtstamp - get HW RX timestamps 37832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 379ba1ffd74SGiuseppe CAVALLARO * @p : descriptor pointer 380ba1ffd74SGiuseppe CAVALLARO * @np : next descriptor pointer 381891434b1SRayagond Kokatanur * @skb : the socket buffer 382891434b1SRayagond Kokatanur * Description : 383891434b1SRayagond Kokatanur * This function will read received packet's timestamp from the descriptor 384891434b1SRayagond Kokatanur * and pass it to stack. It also perform some sanity checks. 385891434b1SRayagond Kokatanur */ 386ba1ffd74SGiuseppe CAVALLARO static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, 387ba1ffd74SGiuseppe CAVALLARO struct dma_desc *np, struct sk_buff *skb) 388891434b1SRayagond Kokatanur { 389891434b1SRayagond Kokatanur struct skb_shared_hwtstamps *shhwtstamp = NULL; 390891434b1SRayagond Kokatanur u64 ns; 391891434b1SRayagond Kokatanur 392891434b1SRayagond Kokatanur if (!priv->hwts_rx_en) 393891434b1SRayagond Kokatanur return; 394891434b1SRayagond Kokatanur 395ba1ffd74SGiuseppe CAVALLARO /* Check if timestamp is available */ 396ba1ffd74SGiuseppe CAVALLARO if (!priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) { 397ba1ffd74SGiuseppe CAVALLARO /* For GMAC4, the valid timestamp is from CTX next desc. */ 398ba1ffd74SGiuseppe CAVALLARO if (priv->plat->has_gmac4) 399ba1ffd74SGiuseppe CAVALLARO ns = priv->hw->desc->get_timestamp(np, priv->adv_ts); 400891434b1SRayagond Kokatanur else 401ba1ffd74SGiuseppe CAVALLARO ns = priv->hw->desc->get_timestamp(p, priv->adv_ts); 402891434b1SRayagond Kokatanur 403ba1ffd74SGiuseppe CAVALLARO netdev_info(priv->dev, "get valid RX hw timestamp %llu\n", ns); 404891434b1SRayagond Kokatanur shhwtstamp = skb_hwtstamps(skb); 405891434b1SRayagond Kokatanur memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); 406891434b1SRayagond Kokatanur shhwtstamp->hwtstamp = ns_to_ktime(ns); 407ba1ffd74SGiuseppe CAVALLARO } else { 408ba1ffd74SGiuseppe CAVALLARO netdev_err(priv->dev, "cannot get RX hw timestamp\n"); 409ba1ffd74SGiuseppe CAVALLARO } 410891434b1SRayagond Kokatanur } 411891434b1SRayagond Kokatanur 412891434b1SRayagond Kokatanur /** 413891434b1SRayagond Kokatanur * stmmac_hwtstamp_ioctl - control hardware timestamping. 414891434b1SRayagond Kokatanur * @dev: device pointer. 4158d45e42bSLABBE Corentin * @ifr: An IOCTL specific structure, that can contain a pointer to 416891434b1SRayagond Kokatanur * a proprietary structure used to pass information to the driver. 417891434b1SRayagond Kokatanur * Description: 418891434b1SRayagond Kokatanur * This function configures the MAC to enable/disable both outgoing(TX) 419891434b1SRayagond Kokatanur * and incoming(RX) packets time stamping based on user input. 420891434b1SRayagond Kokatanur * Return Value: 421891434b1SRayagond Kokatanur * 0 on success and an appropriate -ve integer on failure. 422891434b1SRayagond Kokatanur */ 423891434b1SRayagond Kokatanur static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) 424891434b1SRayagond Kokatanur { 425891434b1SRayagond Kokatanur struct stmmac_priv *priv = netdev_priv(dev); 426891434b1SRayagond Kokatanur struct hwtstamp_config config; 4270a624155SArnd Bergmann struct timespec64 now; 428891434b1SRayagond Kokatanur u64 temp = 0; 429891434b1SRayagond Kokatanur u32 ptp_v2 = 0; 430891434b1SRayagond Kokatanur u32 tstamp_all = 0; 431891434b1SRayagond Kokatanur u32 ptp_over_ipv4_udp = 0; 432891434b1SRayagond Kokatanur u32 ptp_over_ipv6_udp = 0; 433891434b1SRayagond Kokatanur u32 ptp_over_ethernet = 0; 434891434b1SRayagond Kokatanur u32 snap_type_sel = 0; 435891434b1SRayagond Kokatanur u32 ts_master_en = 0; 436891434b1SRayagond Kokatanur u32 ts_event_en = 0; 437891434b1SRayagond Kokatanur u32 value = 0; 43819d857c9SPhil Reid u32 sec_inc; 439891434b1SRayagond Kokatanur 440891434b1SRayagond Kokatanur if (!(priv->dma_cap.time_stamp || priv->adv_ts)) { 441891434b1SRayagond Kokatanur netdev_alert(priv->dev, "No support for HW time stamping\n"); 442891434b1SRayagond Kokatanur priv->hwts_tx_en = 0; 443891434b1SRayagond Kokatanur priv->hwts_rx_en = 0; 444891434b1SRayagond Kokatanur 445891434b1SRayagond Kokatanur return -EOPNOTSUPP; 446891434b1SRayagond Kokatanur } 447891434b1SRayagond Kokatanur 448891434b1SRayagond Kokatanur if (copy_from_user(&config, ifr->ifr_data, 449891434b1SRayagond Kokatanur sizeof(struct hwtstamp_config))) 450891434b1SRayagond Kokatanur return -EFAULT; 451891434b1SRayagond Kokatanur 45238ddc59dSLABBE Corentin netdev_dbg(priv->dev, "%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n", 453891434b1SRayagond Kokatanur __func__, config.flags, config.tx_type, config.rx_filter); 454891434b1SRayagond Kokatanur 455891434b1SRayagond Kokatanur /* reserved for future extensions */ 456891434b1SRayagond Kokatanur if (config.flags) 457891434b1SRayagond Kokatanur return -EINVAL; 458891434b1SRayagond Kokatanur 4595f3da328SBen Hutchings if (config.tx_type != HWTSTAMP_TX_OFF && 4605f3da328SBen Hutchings config.tx_type != HWTSTAMP_TX_ON) 461891434b1SRayagond Kokatanur return -ERANGE; 462891434b1SRayagond Kokatanur 463891434b1SRayagond Kokatanur if (priv->adv_ts) { 464891434b1SRayagond Kokatanur switch (config.rx_filter) { 465891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_NONE: 466ceb69499SGiuseppe CAVALLARO /* time stamp no incoming packet at all */ 467891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_NONE; 468891434b1SRayagond Kokatanur break; 469891434b1SRayagond Kokatanur 470891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 471ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, any kind of event packet */ 472891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 473891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 474891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 475891434b1SRayagond Kokatanur 476891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 477891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 478891434b1SRayagond Kokatanur break; 479891434b1SRayagond Kokatanur 480891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 481ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, Sync packet */ 482891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; 483891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 484891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 485891434b1SRayagond Kokatanur 486891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 487891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 488891434b1SRayagond Kokatanur break; 489891434b1SRayagond Kokatanur 490891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 491ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, Delay_req packet */ 492891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; 493891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 494891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 495891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 496891434b1SRayagond Kokatanur 497891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 498891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 499891434b1SRayagond Kokatanur break; 500891434b1SRayagond Kokatanur 501891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 502ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, any kind of event packet */ 503891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; 504891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 505891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 506891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 507891434b1SRayagond Kokatanur 508891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 509891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 510891434b1SRayagond Kokatanur break; 511891434b1SRayagond Kokatanur 512891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 513ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, Sync packet */ 514891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC; 515891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 516891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 517891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 518891434b1SRayagond Kokatanur 519891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 520891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 521891434b1SRayagond Kokatanur break; 522891434b1SRayagond Kokatanur 523891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 524ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, Delay_req packet */ 525891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ; 526891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 527891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 528891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 529891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 530891434b1SRayagond Kokatanur 531891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 532891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 533891434b1SRayagond Kokatanur break; 534891434b1SRayagond Kokatanur 535891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_EVENT: 536ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1 any layer, any kind of event packet */ 537891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 538891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 539891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 540891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 541891434b1SRayagond Kokatanur 542891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 543891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 544891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 545891434b1SRayagond Kokatanur break; 546891434b1SRayagond Kokatanur 547891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_SYNC: 548ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1, any layer, Sync packet */ 549891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC; 550891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 551891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 552891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 553891434b1SRayagond Kokatanur 554891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 555891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 556891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 557891434b1SRayagond Kokatanur break; 558891434b1SRayagond Kokatanur 559891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 560ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1, any layer, Delay_req packet */ 561891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ; 562891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 563891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 564891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 565891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 566891434b1SRayagond Kokatanur 567891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 568891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 569891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 570891434b1SRayagond Kokatanur break; 571891434b1SRayagond Kokatanur 572891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_ALL: 573ceb69499SGiuseppe CAVALLARO /* time stamp any incoming packet */ 574891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_ALL; 575891434b1SRayagond Kokatanur tstamp_all = PTP_TCR_TSENALL; 576891434b1SRayagond Kokatanur break; 577891434b1SRayagond Kokatanur 578891434b1SRayagond Kokatanur default: 579891434b1SRayagond Kokatanur return -ERANGE; 580891434b1SRayagond Kokatanur } 581891434b1SRayagond Kokatanur } else { 582891434b1SRayagond Kokatanur switch (config.rx_filter) { 583891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_NONE: 584891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_NONE; 585891434b1SRayagond Kokatanur break; 586891434b1SRayagond Kokatanur default: 587891434b1SRayagond Kokatanur /* PTP v1, UDP, any kind of event packet */ 588891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 589891434b1SRayagond Kokatanur break; 590891434b1SRayagond Kokatanur } 591891434b1SRayagond Kokatanur } 592891434b1SRayagond Kokatanur priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1); 5935f3da328SBen Hutchings priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON; 594891434b1SRayagond Kokatanur 595891434b1SRayagond Kokatanur if (!priv->hwts_tx_en && !priv->hwts_rx_en) 596ba1ffd74SGiuseppe CAVALLARO priv->hw->ptp->config_hw_tstamping(priv->ptpaddr, 0); 597891434b1SRayagond Kokatanur else { 598891434b1SRayagond Kokatanur value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR | 599891434b1SRayagond Kokatanur tstamp_all | ptp_v2 | ptp_over_ethernet | 600891434b1SRayagond Kokatanur ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en | 601891434b1SRayagond Kokatanur ts_master_en | snap_type_sel); 602ba1ffd74SGiuseppe CAVALLARO priv->hw->ptp->config_hw_tstamping(priv->ptpaddr, value); 603891434b1SRayagond Kokatanur 604891434b1SRayagond Kokatanur /* program Sub Second Increment reg */ 60519d857c9SPhil Reid sec_inc = priv->hw->ptp->config_sub_second_increment( 606f573c0b9Sjpinto priv->ptpaddr, priv->plat->clk_ptp_rate, 607ba1ffd74SGiuseppe CAVALLARO priv->plat->has_gmac4); 60819d857c9SPhil Reid temp = div_u64(1000000000ULL, sec_inc); 609891434b1SRayagond Kokatanur 610891434b1SRayagond Kokatanur /* calculate default added value: 611891434b1SRayagond Kokatanur * formula is : 612891434b1SRayagond Kokatanur * addend = (2^32)/freq_div_ratio; 61319d857c9SPhil Reid * where, freq_div_ratio = 1e9ns/sec_inc 614891434b1SRayagond Kokatanur */ 61519d857c9SPhil Reid temp = (u64)(temp << 32); 616f573c0b9Sjpinto priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate); 617ba1ffd74SGiuseppe CAVALLARO priv->hw->ptp->config_addend(priv->ptpaddr, 618891434b1SRayagond Kokatanur priv->default_addend); 619891434b1SRayagond Kokatanur 620891434b1SRayagond Kokatanur /* initialize system time */ 6210a624155SArnd Bergmann ktime_get_real_ts64(&now); 6220a624155SArnd Bergmann 6230a624155SArnd Bergmann /* lower 32 bits of tv_sec are safe until y2106 */ 624ba1ffd74SGiuseppe CAVALLARO priv->hw->ptp->init_systime(priv->ptpaddr, (u32)now.tv_sec, 625891434b1SRayagond Kokatanur now.tv_nsec); 626891434b1SRayagond Kokatanur } 627891434b1SRayagond Kokatanur 628891434b1SRayagond Kokatanur return copy_to_user(ifr->ifr_data, &config, 629891434b1SRayagond Kokatanur sizeof(struct hwtstamp_config)) ? -EFAULT : 0; 630891434b1SRayagond Kokatanur } 631891434b1SRayagond Kokatanur 63232ceabcaSGiuseppe CAVALLARO /** 633732fdf0eSGiuseppe CAVALLARO * stmmac_init_ptp - init PTP 63432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 635732fdf0eSGiuseppe CAVALLARO * Description: this is to verify if the HW supports the PTPv1 or PTPv2. 63632ceabcaSGiuseppe CAVALLARO * This is done by looking at the HW cap. register. 637732fdf0eSGiuseppe CAVALLARO * This function also registers the ptp driver. 63832ceabcaSGiuseppe CAVALLARO */ 63992ba6888SRayagond Kokatanur static int stmmac_init_ptp(struct stmmac_priv *priv) 640891434b1SRayagond Kokatanur { 64192ba6888SRayagond Kokatanur if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) 64292ba6888SRayagond Kokatanur return -EOPNOTSUPP; 64392ba6888SRayagond Kokatanur 644891434b1SRayagond Kokatanur priv->adv_ts = 0; 645be9b3174SGiuseppe CAVALLARO /* Check if adv_ts can be enabled for dwmac 4.x core */ 646be9b3174SGiuseppe CAVALLARO if (priv->plat->has_gmac4 && priv->dma_cap.atime_stamp) 647be9b3174SGiuseppe CAVALLARO priv->adv_ts = 1; 648be9b3174SGiuseppe CAVALLARO /* Dwmac 3.x core with extend_desc can support adv_ts */ 649be9b3174SGiuseppe CAVALLARO else if (priv->extend_desc && priv->dma_cap.atime_stamp) 650891434b1SRayagond Kokatanur priv->adv_ts = 1; 6517cd01399SVince Bridgers 652be9b3174SGiuseppe CAVALLARO if (priv->dma_cap.time_stamp) 653be9b3174SGiuseppe CAVALLARO netdev_info(priv->dev, "IEEE 1588-2002 Timestamp supported\n"); 6547cd01399SVince Bridgers 655be9b3174SGiuseppe CAVALLARO if (priv->adv_ts) 656be9b3174SGiuseppe CAVALLARO netdev_info(priv->dev, 657be9b3174SGiuseppe CAVALLARO "IEEE 1588-2008 Advanced Timestamp supported\n"); 658891434b1SRayagond Kokatanur 659891434b1SRayagond Kokatanur priv->hw->ptp = &stmmac_ptp; 660891434b1SRayagond Kokatanur priv->hwts_tx_en = 0; 661891434b1SRayagond Kokatanur priv->hwts_rx_en = 0; 66292ba6888SRayagond Kokatanur 663c30a70d3SGiuseppe CAVALLARO stmmac_ptp_register(priv); 664c30a70d3SGiuseppe CAVALLARO 665c30a70d3SGiuseppe CAVALLARO return 0; 66692ba6888SRayagond Kokatanur } 66792ba6888SRayagond Kokatanur 66892ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv) 66992ba6888SRayagond Kokatanur { 670f573c0b9Sjpinto if (priv->plat->clk_ptp_ref) 671f573c0b9Sjpinto clk_disable_unprepare(priv->plat->clk_ptp_ref); 67292ba6888SRayagond Kokatanur stmmac_ptp_unregister(priv); 673891434b1SRayagond Kokatanur } 674891434b1SRayagond Kokatanur 6757ac6653aSJeff Kirsher /** 67629feff39SJoao Pinto * stmmac_mac_flow_ctrl - Configure flow control in all queues 67729feff39SJoao Pinto * @priv: driver private structure 67829feff39SJoao Pinto * Description: It is used for configuring the flow control in all queues 67929feff39SJoao Pinto */ 68029feff39SJoao Pinto static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex) 68129feff39SJoao Pinto { 68229feff39SJoao Pinto u32 tx_cnt = priv->plat->tx_queues_to_use; 68329feff39SJoao Pinto 68429feff39SJoao Pinto priv->hw->mac->flow_ctrl(priv->hw, duplex, priv->flow_ctrl, 68529feff39SJoao Pinto priv->pause, tx_cnt); 68629feff39SJoao Pinto } 68729feff39SJoao Pinto 68829feff39SJoao Pinto /** 689732fdf0eSGiuseppe CAVALLARO * stmmac_adjust_link - adjusts the link parameters 6907ac6653aSJeff Kirsher * @dev: net device structure 691732fdf0eSGiuseppe CAVALLARO * Description: this is the helper called by the physical abstraction layer 692732fdf0eSGiuseppe CAVALLARO * drivers to communicate the phy link status. According the speed and duplex 693732fdf0eSGiuseppe CAVALLARO * this driver can invoke registered glue-logic as well. 694732fdf0eSGiuseppe CAVALLARO * It also invoke the eee initialization because it could happen when switch 695732fdf0eSGiuseppe CAVALLARO * on different networks (that are eee capable). 6967ac6653aSJeff Kirsher */ 6977ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev) 6987ac6653aSJeff Kirsher { 6997ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 700d6d50c7eSPhilippe Reynes struct phy_device *phydev = dev->phydev; 7017ac6653aSJeff Kirsher unsigned long flags; 7027ac6653aSJeff Kirsher int new_state = 0; 7037ac6653aSJeff Kirsher 704662ec2b7SLABBE Corentin if (!phydev) 7057ac6653aSJeff Kirsher return; 7067ac6653aSJeff Kirsher 7077ac6653aSJeff Kirsher spin_lock_irqsave(&priv->lock, flags); 708d765955dSGiuseppe CAVALLARO 7097ac6653aSJeff Kirsher if (phydev->link) { 7107ac6653aSJeff Kirsher u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG); 7117ac6653aSJeff Kirsher 7127ac6653aSJeff Kirsher /* Now we make sure that we can be in full duplex mode. 7137ac6653aSJeff Kirsher * If not, we operate in half-duplex mode. */ 7147ac6653aSJeff Kirsher if (phydev->duplex != priv->oldduplex) { 7157ac6653aSJeff Kirsher new_state = 1; 7167ac6653aSJeff Kirsher if (!(phydev->duplex)) 7177ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.duplex; 7187ac6653aSJeff Kirsher else 7197ac6653aSJeff Kirsher ctrl |= priv->hw->link.duplex; 7207ac6653aSJeff Kirsher priv->oldduplex = phydev->duplex; 7217ac6653aSJeff Kirsher } 7227ac6653aSJeff Kirsher /* Flow Control operation */ 7237ac6653aSJeff Kirsher if (phydev->pause) 72429feff39SJoao Pinto stmmac_mac_flow_ctrl(priv, phydev->duplex); 7257ac6653aSJeff Kirsher 7267ac6653aSJeff Kirsher if (phydev->speed != priv->speed) { 7277ac6653aSJeff Kirsher new_state = 1; 7287ac6653aSJeff Kirsher switch (phydev->speed) { 7297ac6653aSJeff Kirsher case 1000: 7303e12790eSLABBE Corentin if (priv->plat->has_gmac || 7313e12790eSLABBE Corentin priv->plat->has_gmac4) 7327ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.port; 7337ac6653aSJeff Kirsher break; 7347ac6653aSJeff Kirsher case 100: 7359beae261SLABBE Corentin if (priv->plat->has_gmac || 7369beae261SLABBE Corentin priv->plat->has_gmac4) { 7379beae261SLABBE Corentin ctrl |= priv->hw->link.port; 7389beae261SLABBE Corentin ctrl |= priv->hw->link.speed; 7399beae261SLABBE Corentin } else { 7409beae261SLABBE Corentin ctrl &= ~priv->hw->link.port; 7419beae261SLABBE Corentin } 7429beae261SLABBE Corentin break; 7437ac6653aSJeff Kirsher case 10: 7443e12790eSLABBE Corentin if (priv->plat->has_gmac || 7453e12790eSLABBE Corentin priv->plat->has_gmac4) { 7467ac6653aSJeff Kirsher ctrl |= priv->hw->link.port; 7477ac6653aSJeff Kirsher ctrl &= ~(priv->hw->link.speed); 7487ac6653aSJeff Kirsher } else { 7497ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.port; 7507ac6653aSJeff Kirsher } 7517ac6653aSJeff Kirsher break; 7527ac6653aSJeff Kirsher default: 753b3e51069SLABBE Corentin netif_warn(priv, link, priv->dev, 754cba920afSLABBE Corentin "broken speed: %d\n", phydev->speed); 755688495b1SLABBE Corentin phydev->speed = SPEED_UNKNOWN; 7567ac6653aSJeff Kirsher break; 7577ac6653aSJeff Kirsher } 7585db13556SLABBE Corentin if (phydev->speed != SPEED_UNKNOWN) 7595db13556SLABBE Corentin stmmac_hw_fix_mac_speed(priv); 7607ac6653aSJeff Kirsher priv->speed = phydev->speed; 7617ac6653aSJeff Kirsher } 7627ac6653aSJeff Kirsher 7637ac6653aSJeff Kirsher writel(ctrl, priv->ioaddr + MAC_CTRL_REG); 7647ac6653aSJeff Kirsher 7657ac6653aSJeff Kirsher if (!priv->oldlink) { 7667ac6653aSJeff Kirsher new_state = 1; 7677ac6653aSJeff Kirsher priv->oldlink = 1; 7687ac6653aSJeff Kirsher } 7697ac6653aSJeff Kirsher } else if (priv->oldlink) { 7707ac6653aSJeff Kirsher new_state = 1; 7717ac6653aSJeff Kirsher priv->oldlink = 0; 772bd00632cSLABBE Corentin priv->speed = SPEED_UNKNOWN; 773bd00632cSLABBE Corentin priv->oldduplex = DUPLEX_UNKNOWN; 7747ac6653aSJeff Kirsher } 7757ac6653aSJeff Kirsher 7767ac6653aSJeff Kirsher if (new_state && netif_msg_link(priv)) 7777ac6653aSJeff Kirsher phy_print_status(phydev); 7787ac6653aSJeff Kirsher 7794741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 7804741cf9cSGiuseppe CAVALLARO 78152f95bbfSGiuseppe CAVALLARO if (phydev->is_pseudo_fixed_link) 78252f95bbfSGiuseppe CAVALLARO /* Stop PHY layer to call the hook to adjust the link in case 78352f95bbfSGiuseppe CAVALLARO * of a switch is attached to the stmmac driver. 78452f95bbfSGiuseppe CAVALLARO */ 78552f95bbfSGiuseppe CAVALLARO phydev->irq = PHY_IGNORE_INTERRUPT; 78652f95bbfSGiuseppe CAVALLARO else 78752f95bbfSGiuseppe CAVALLARO /* At this stage, init the EEE if supported. 78852f95bbfSGiuseppe CAVALLARO * Never called in case of fixed_link. 789f5351ef7SGiuseppe CAVALLARO */ 790f5351ef7SGiuseppe CAVALLARO priv->eee_enabled = stmmac_eee_init(priv); 7917ac6653aSJeff Kirsher } 7927ac6653aSJeff Kirsher 79332ceabcaSGiuseppe CAVALLARO /** 794732fdf0eSGiuseppe CAVALLARO * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported 79532ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 79632ceabcaSGiuseppe CAVALLARO * Description: this is to verify if the HW supports the PCS. 79732ceabcaSGiuseppe CAVALLARO * Physical Coding Sublayer (PCS) interface that can be used when the MAC is 79832ceabcaSGiuseppe CAVALLARO * configured for the TBI, RTBI, or SGMII PHY interface. 79932ceabcaSGiuseppe CAVALLARO */ 800e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv) 801e58bb43fSGiuseppe CAVALLARO { 802e58bb43fSGiuseppe CAVALLARO int interface = priv->plat->interface; 803e58bb43fSGiuseppe CAVALLARO 804e58bb43fSGiuseppe CAVALLARO if (priv->dma_cap.pcs) { 8050d909dcdSByungho An if ((interface == PHY_INTERFACE_MODE_RGMII) || 8060d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_ID) || 8070d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_RXID) || 8080d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 80938ddc59dSLABBE Corentin netdev_dbg(priv->dev, "PCS RGMII support enabled\n"); 8103fe5cadbSGiuseppe CAVALLARO priv->hw->pcs = STMMAC_PCS_RGMII; 8110d909dcdSByungho An } else if (interface == PHY_INTERFACE_MODE_SGMII) { 81238ddc59dSLABBE Corentin netdev_dbg(priv->dev, "PCS SGMII support enabled\n"); 8133fe5cadbSGiuseppe CAVALLARO priv->hw->pcs = STMMAC_PCS_SGMII; 814e58bb43fSGiuseppe CAVALLARO } 815e58bb43fSGiuseppe CAVALLARO } 816e58bb43fSGiuseppe CAVALLARO } 817e58bb43fSGiuseppe CAVALLARO 8187ac6653aSJeff Kirsher /** 8197ac6653aSJeff Kirsher * stmmac_init_phy - PHY initialization 8207ac6653aSJeff Kirsher * @dev: net device structure 8217ac6653aSJeff Kirsher * Description: it initializes the driver's PHY state, and attaches the PHY 8227ac6653aSJeff Kirsher * to the mac driver. 8237ac6653aSJeff Kirsher * Return value: 8247ac6653aSJeff Kirsher * 0 on success 8257ac6653aSJeff Kirsher */ 8267ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev) 8277ac6653aSJeff Kirsher { 8287ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 8297ac6653aSJeff Kirsher struct phy_device *phydev; 830d765955dSGiuseppe CAVALLARO char phy_id_fmt[MII_BUS_ID_SIZE + 3]; 8317ac6653aSJeff Kirsher char bus_id[MII_BUS_ID_SIZE]; 83279ee1dc3SSrinivas Kandagatla int interface = priv->plat->interface; 8339cbadf09SSrinivas Kandagatla int max_speed = priv->plat->max_speed; 8347ac6653aSJeff Kirsher priv->oldlink = 0; 835bd00632cSLABBE Corentin priv->speed = SPEED_UNKNOWN; 836bd00632cSLABBE Corentin priv->oldduplex = DUPLEX_UNKNOWN; 8377ac6653aSJeff Kirsher 8385790cf3cSMathieu Olivari if (priv->plat->phy_node) { 8395790cf3cSMathieu Olivari phydev = of_phy_connect(dev, priv->plat->phy_node, 8405790cf3cSMathieu Olivari &stmmac_adjust_link, 0, interface); 8415790cf3cSMathieu Olivari } else { 842f142af2eSSrinivas Kandagatla snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", 843f142af2eSSrinivas Kandagatla priv->plat->bus_id); 844f142af2eSSrinivas Kandagatla 845d765955dSGiuseppe CAVALLARO snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, 8467ac6653aSJeff Kirsher priv->plat->phy_addr); 847de9a2165SLABBE Corentin netdev_dbg(priv->dev, "%s: trying to attach to %s\n", __func__, 8485790cf3cSMathieu Olivari phy_id_fmt); 8497ac6653aSJeff Kirsher 8505790cf3cSMathieu Olivari phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, 8515790cf3cSMathieu Olivari interface); 8525790cf3cSMathieu Olivari } 8537ac6653aSJeff Kirsher 854dfc50fcaSAlexey Brodkin if (IS_ERR_OR_NULL(phydev)) { 85538ddc59dSLABBE Corentin netdev_err(priv->dev, "Could not attach to PHY\n"); 856dfc50fcaSAlexey Brodkin if (!phydev) 857dfc50fcaSAlexey Brodkin return -ENODEV; 858dfc50fcaSAlexey Brodkin 8597ac6653aSJeff Kirsher return PTR_ERR(phydev); 8607ac6653aSJeff Kirsher } 8617ac6653aSJeff Kirsher 86279ee1dc3SSrinivas Kandagatla /* Stop Advertising 1000BASE Capability if interface is not GMII */ 863c5b9b4e4SSrinivas Kandagatla if ((interface == PHY_INTERFACE_MODE_MII) || 8649cbadf09SSrinivas Kandagatla (interface == PHY_INTERFACE_MODE_RMII) || 8659cbadf09SSrinivas Kandagatla (max_speed < 1000 && max_speed > 0)) 866c5b9b4e4SSrinivas Kandagatla phydev->advertising &= ~(SUPPORTED_1000baseT_Half | 867c5b9b4e4SSrinivas Kandagatla SUPPORTED_1000baseT_Full); 86879ee1dc3SSrinivas Kandagatla 8697ac6653aSJeff Kirsher /* 8707ac6653aSJeff Kirsher * Broken HW is sometimes missing the pull-up resistor on the 8717ac6653aSJeff Kirsher * MDIO line, which results in reads to non-existent devices returning 8727ac6653aSJeff Kirsher * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent 8737ac6653aSJeff Kirsher * device as well. 8747ac6653aSJeff Kirsher * Note: phydev->phy_id is the result of reading the UID PHY registers. 8757ac6653aSJeff Kirsher */ 87627732381SMathieu Olivari if (!priv->plat->phy_node && phydev->phy_id == 0) { 8777ac6653aSJeff Kirsher phy_disconnect(phydev); 8787ac6653aSJeff Kirsher return -ENODEV; 8797ac6653aSJeff Kirsher } 8808e99fc5fSGiuseppe Cavallaro 881c51e424dSFlorian Fainelli /* stmmac_adjust_link will change this to PHY_IGNORE_INTERRUPT to avoid 882c51e424dSFlorian Fainelli * subsequent PHY polling, make sure we force a link transition if 883c51e424dSFlorian Fainelli * we have a UP/DOWN/UP transition 884c51e424dSFlorian Fainelli */ 885c51e424dSFlorian Fainelli if (phydev->is_pseudo_fixed_link) 886c51e424dSFlorian Fainelli phydev->irq = PHY_POLL; 887c51e424dSFlorian Fainelli 888b05c76a1SLABBE Corentin phy_attached_info(phydev); 8897ac6653aSJeff Kirsher return 0; 8907ac6653aSJeff Kirsher } 8917ac6653aSJeff Kirsher 892c24602efSGiuseppe CAVALLARO static void stmmac_display_rings(struct stmmac_priv *priv) 893c24602efSGiuseppe CAVALLARO { 894d0225e7dSAlexandre TORGUE void *head_rx, *head_tx; 895d0225e7dSAlexandre TORGUE 896c24602efSGiuseppe CAVALLARO if (priv->extend_desc) { 897d0225e7dSAlexandre TORGUE head_rx = (void *)priv->dma_erx; 898d0225e7dSAlexandre TORGUE head_tx = (void *)priv->dma_etx; 899c24602efSGiuseppe CAVALLARO } else { 900d0225e7dSAlexandre TORGUE head_rx = (void *)priv->dma_rx; 901d0225e7dSAlexandre TORGUE head_tx = (void *)priv->dma_tx; 902c24602efSGiuseppe CAVALLARO } 903d0225e7dSAlexandre TORGUE 904d0225e7dSAlexandre TORGUE /* Display Rx ring */ 905d0225e7dSAlexandre TORGUE priv->hw->desc->display_ring(head_rx, DMA_RX_SIZE, true); 906d0225e7dSAlexandre TORGUE /* Display Tx ring */ 907d0225e7dSAlexandre TORGUE priv->hw->desc->display_ring(head_tx, DMA_TX_SIZE, false); 908c24602efSGiuseppe CAVALLARO } 909c24602efSGiuseppe CAVALLARO 910286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize) 911286a8372SGiuseppe CAVALLARO { 912286a8372SGiuseppe CAVALLARO int ret = bufsize; 913286a8372SGiuseppe CAVALLARO 914286a8372SGiuseppe CAVALLARO if (mtu >= BUF_SIZE_4KiB) 915286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_8KiB; 916286a8372SGiuseppe CAVALLARO else if (mtu >= BUF_SIZE_2KiB) 917286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_4KiB; 918d916701cSGiuseppe CAVALLARO else if (mtu > DEFAULT_BUFSIZE) 919286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_2KiB; 920286a8372SGiuseppe CAVALLARO else 921d916701cSGiuseppe CAVALLARO ret = DEFAULT_BUFSIZE; 922286a8372SGiuseppe CAVALLARO 923286a8372SGiuseppe CAVALLARO return ret; 924286a8372SGiuseppe CAVALLARO } 925286a8372SGiuseppe CAVALLARO 92632ceabcaSGiuseppe CAVALLARO /** 927732fdf0eSGiuseppe CAVALLARO * stmmac_clear_descriptors - clear descriptors 92832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 92932ceabcaSGiuseppe CAVALLARO * Description: this function is called to clear the tx and rx descriptors 93032ceabcaSGiuseppe CAVALLARO * in case of both basic and extended descriptors are used. 93132ceabcaSGiuseppe CAVALLARO */ 932c24602efSGiuseppe CAVALLARO static void stmmac_clear_descriptors(struct stmmac_priv *priv) 933c24602efSGiuseppe CAVALLARO { 934c24602efSGiuseppe CAVALLARO int i; 935c24602efSGiuseppe CAVALLARO 936c24602efSGiuseppe CAVALLARO /* Clear the Rx/Tx descriptors */ 937e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_RX_SIZE; i++) 938c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 939c24602efSGiuseppe CAVALLARO priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic, 940c24602efSGiuseppe CAVALLARO priv->use_riwt, priv->mode, 941e3ad57c9SGiuseppe Cavallaro (i == DMA_RX_SIZE - 1)); 942c24602efSGiuseppe CAVALLARO else 943c24602efSGiuseppe CAVALLARO priv->hw->desc->init_rx_desc(&priv->dma_rx[i], 944c24602efSGiuseppe CAVALLARO priv->use_riwt, priv->mode, 945e3ad57c9SGiuseppe Cavallaro (i == DMA_RX_SIZE - 1)); 946e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_TX_SIZE; i++) 947c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 948c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic, 949c24602efSGiuseppe CAVALLARO priv->mode, 950e3ad57c9SGiuseppe Cavallaro (i == DMA_TX_SIZE - 1)); 951c24602efSGiuseppe CAVALLARO else 952c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_tx[i], 953c24602efSGiuseppe CAVALLARO priv->mode, 954e3ad57c9SGiuseppe Cavallaro (i == DMA_TX_SIZE - 1)); 955c24602efSGiuseppe CAVALLARO } 956c24602efSGiuseppe CAVALLARO 957732fdf0eSGiuseppe CAVALLARO /** 958732fdf0eSGiuseppe CAVALLARO * stmmac_init_rx_buffers - init the RX descriptor buffer. 959732fdf0eSGiuseppe CAVALLARO * @priv: driver private structure 960732fdf0eSGiuseppe CAVALLARO * @p: descriptor pointer 961732fdf0eSGiuseppe CAVALLARO * @i: descriptor index 962732fdf0eSGiuseppe CAVALLARO * @flags: gfp flag. 963732fdf0eSGiuseppe CAVALLARO * Description: this function is called to allocate a receive buffer, perform 964732fdf0eSGiuseppe CAVALLARO * the DMA mapping and init the descriptor. 965732fdf0eSGiuseppe CAVALLARO */ 966c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, 967777da230SGiuseppe CAVALLARO int i, gfp_t flags) 968c24602efSGiuseppe CAVALLARO { 969c24602efSGiuseppe CAVALLARO struct sk_buff *skb; 970c24602efSGiuseppe CAVALLARO 9714ec49a37SVineet Gupta skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags); 97256329137SBartlomiej Zolnierkiewicz if (!skb) { 97338ddc59dSLABBE Corentin netdev_err(priv->dev, 97438ddc59dSLABBE Corentin "%s: Rx init fails; skb is NULL\n", __func__); 97556329137SBartlomiej Zolnierkiewicz return -ENOMEM; 976c24602efSGiuseppe CAVALLARO } 977c24602efSGiuseppe CAVALLARO priv->rx_skbuff[i] = skb; 978c24602efSGiuseppe CAVALLARO priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data, 979c24602efSGiuseppe CAVALLARO priv->dma_buf_sz, 980c24602efSGiuseppe CAVALLARO DMA_FROM_DEVICE); 98156329137SBartlomiej Zolnierkiewicz if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) { 98238ddc59dSLABBE Corentin netdev_err(priv->dev, "%s: DMA mapping error\n", __func__); 98356329137SBartlomiej Zolnierkiewicz dev_kfree_skb_any(skb); 98456329137SBartlomiej Zolnierkiewicz return -EINVAL; 98556329137SBartlomiej Zolnierkiewicz } 986c24602efSGiuseppe CAVALLARO 987f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) 988f8be0d78SMichael Weiser p->des0 = cpu_to_le32(priv->rx_skbuff_dma[i]); 989f748be53SAlexandre TORGUE else 990f8be0d78SMichael Weiser p->des2 = cpu_to_le32(priv->rx_skbuff_dma[i]); 991c24602efSGiuseppe CAVALLARO 99229896a67SGiuseppe CAVALLARO if ((priv->hw->mode->init_desc3) && 993c24602efSGiuseppe CAVALLARO (priv->dma_buf_sz == BUF_SIZE_16KiB)) 99429896a67SGiuseppe CAVALLARO priv->hw->mode->init_desc3(p); 995c24602efSGiuseppe CAVALLARO 996c24602efSGiuseppe CAVALLARO return 0; 997c24602efSGiuseppe CAVALLARO } 998c24602efSGiuseppe CAVALLARO 99956329137SBartlomiej Zolnierkiewicz static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i) 100056329137SBartlomiej Zolnierkiewicz { 100156329137SBartlomiej Zolnierkiewicz if (priv->rx_skbuff[i]) { 100256329137SBartlomiej Zolnierkiewicz dma_unmap_single(priv->device, priv->rx_skbuff_dma[i], 100356329137SBartlomiej Zolnierkiewicz priv->dma_buf_sz, DMA_FROM_DEVICE); 100456329137SBartlomiej Zolnierkiewicz dev_kfree_skb_any(priv->rx_skbuff[i]); 100556329137SBartlomiej Zolnierkiewicz } 100656329137SBartlomiej Zolnierkiewicz priv->rx_skbuff[i] = NULL; 100756329137SBartlomiej Zolnierkiewicz } 100856329137SBartlomiej Zolnierkiewicz 10097ac6653aSJeff Kirsher /** 10107ac6653aSJeff Kirsher * init_dma_desc_rings - init the RX/TX descriptor rings 10117ac6653aSJeff Kirsher * @dev: net device structure 1012732fdf0eSGiuseppe CAVALLARO * @flags: gfp flag. 10137ac6653aSJeff Kirsher * Description: this function initializes the DMA RX/TX descriptors 10148d45e42bSLABBE Corentin * and allocates the socket buffers. It supports the chained and ring 1015286a8372SGiuseppe CAVALLARO * modes. 10167ac6653aSJeff Kirsher */ 1017777da230SGiuseppe CAVALLARO static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) 10187ac6653aSJeff Kirsher { 10197ac6653aSJeff Kirsher int i; 10207ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 10214a7d666aSGiuseppe CAVALLARO unsigned int bfsize = 0; 102256329137SBartlomiej Zolnierkiewicz int ret = -ENOMEM; 10237ac6653aSJeff Kirsher 102429896a67SGiuseppe CAVALLARO if (priv->hw->mode->set_16kib_bfsize) 102529896a67SGiuseppe CAVALLARO bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu); 1026286a8372SGiuseppe CAVALLARO 10274a7d666aSGiuseppe CAVALLARO if (bfsize < BUF_SIZE_16KiB) 1028286a8372SGiuseppe CAVALLARO bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz); 10297ac6653aSJeff Kirsher 10302618abb7SVince Bridgers priv->dma_buf_sz = bfsize; 10312618abb7SVince Bridgers 1032b3e51069SLABBE Corentin netif_dbg(priv, probe, priv->dev, 1033b3e51069SLABBE Corentin "(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", 1034b3e51069SLABBE Corentin __func__, (u32)priv->dma_rx_phy, (u32)priv->dma_tx_phy); 10357ac6653aSJeff Kirsher 10367ac6653aSJeff Kirsher /* RX INITIALIZATION */ 1037b3e51069SLABBE Corentin netif_dbg(priv, probe, priv->dev, 1038b3e51069SLABBE Corentin "SKB addresses:\nskb\t\tskb data\tdma data\n"); 1039b3e51069SLABBE Corentin 1040e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_RX_SIZE; i++) { 1041c24602efSGiuseppe CAVALLARO struct dma_desc *p; 1042c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1043c24602efSGiuseppe CAVALLARO p = &((priv->dma_erx + i)->basic); 1044c24602efSGiuseppe CAVALLARO else 1045c24602efSGiuseppe CAVALLARO p = priv->dma_rx + i; 10467ac6653aSJeff Kirsher 1047777da230SGiuseppe CAVALLARO ret = stmmac_init_rx_buffers(priv, p, i, flags); 104856329137SBartlomiej Zolnierkiewicz if (ret) 104956329137SBartlomiej Zolnierkiewicz goto err_init_rx_buffers; 1050286a8372SGiuseppe CAVALLARO 1051b3e51069SLABBE Corentin netif_dbg(priv, probe, priv->dev, "[%p]\t[%p]\t[%x]\n", 1052b3e51069SLABBE Corentin priv->rx_skbuff[i], priv->rx_skbuff[i]->data, 105383d7af64SGiuseppe CAVALLARO (unsigned int)priv->rx_skbuff_dma[i]); 10547ac6653aSJeff Kirsher } 10557ac6653aSJeff Kirsher priv->cur_rx = 0; 1056e3ad57c9SGiuseppe Cavallaro priv->dirty_rx = (unsigned int)(i - DMA_RX_SIZE); 10577ac6653aSJeff Kirsher buf_sz = bfsize; 10587ac6653aSJeff Kirsher 1059c24602efSGiuseppe CAVALLARO /* Setup the chained descriptor addresses */ 1060c24602efSGiuseppe CAVALLARO if (priv->mode == STMMAC_CHAIN_MODE) { 1061c24602efSGiuseppe CAVALLARO if (priv->extend_desc) { 106229896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy, 1063e3ad57c9SGiuseppe Cavallaro DMA_RX_SIZE, 1); 106429896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy, 1065e3ad57c9SGiuseppe Cavallaro DMA_TX_SIZE, 1); 1066c24602efSGiuseppe CAVALLARO } else { 106729896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy, 1068e3ad57c9SGiuseppe Cavallaro DMA_RX_SIZE, 0); 106929896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy, 1070e3ad57c9SGiuseppe Cavallaro DMA_TX_SIZE, 0); 1071c24602efSGiuseppe CAVALLARO } 10727ac6653aSJeff Kirsher } 1073286a8372SGiuseppe CAVALLARO 1074c24602efSGiuseppe CAVALLARO /* TX INITIALIZATION */ 1075e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_TX_SIZE; i++) { 1076c24602efSGiuseppe CAVALLARO struct dma_desc *p; 1077c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1078c24602efSGiuseppe CAVALLARO p = &((priv->dma_etx + i)->basic); 1079c24602efSGiuseppe CAVALLARO else 1080c24602efSGiuseppe CAVALLARO p = priv->dma_tx + i; 1081f748be53SAlexandre TORGUE 1082f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) { 1083f748be53SAlexandre TORGUE p->des0 = 0; 1084f748be53SAlexandre TORGUE p->des1 = 0; 1085c24602efSGiuseppe CAVALLARO p->des2 = 0; 1086f748be53SAlexandre TORGUE p->des3 = 0; 1087f748be53SAlexandre TORGUE } else { 1088f748be53SAlexandre TORGUE p->des2 = 0; 1089f748be53SAlexandre TORGUE } 1090f748be53SAlexandre TORGUE 1091362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf = 0; 1092362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].map_as_page = false; 1093553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[i].len = 0; 10942a6d8e17SGiuseppe Cavallaro priv->tx_skbuff_dma[i].last_segment = false; 1095c24602efSGiuseppe CAVALLARO priv->tx_skbuff[i] = NULL; 10964a7d666aSGiuseppe CAVALLARO } 1097c24602efSGiuseppe CAVALLARO 10987ac6653aSJeff Kirsher priv->dirty_tx = 0; 10997ac6653aSJeff Kirsher priv->cur_tx = 0; 110038979574SBeniamino Galvani netdev_reset_queue(priv->dev); 11017ac6653aSJeff Kirsher 1102c24602efSGiuseppe CAVALLARO stmmac_clear_descriptors(priv); 11037ac6653aSJeff Kirsher 1104c24602efSGiuseppe CAVALLARO if (netif_msg_hw(priv)) 1105c24602efSGiuseppe CAVALLARO stmmac_display_rings(priv); 110656329137SBartlomiej Zolnierkiewicz 110756329137SBartlomiej Zolnierkiewicz return 0; 110856329137SBartlomiej Zolnierkiewicz err_init_rx_buffers: 110956329137SBartlomiej Zolnierkiewicz while (--i >= 0) 111056329137SBartlomiej Zolnierkiewicz stmmac_free_rx_buffers(priv, i); 111156329137SBartlomiej Zolnierkiewicz return ret; 11127ac6653aSJeff Kirsher } 11137ac6653aSJeff Kirsher 11147ac6653aSJeff Kirsher static void dma_free_rx_skbufs(struct stmmac_priv *priv) 11157ac6653aSJeff Kirsher { 11167ac6653aSJeff Kirsher int i; 11177ac6653aSJeff Kirsher 1118e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_RX_SIZE; i++) 111956329137SBartlomiej Zolnierkiewicz stmmac_free_rx_buffers(priv, i); 11207ac6653aSJeff Kirsher } 11217ac6653aSJeff Kirsher 11227ac6653aSJeff Kirsher static void dma_free_tx_skbufs(struct stmmac_priv *priv) 11237ac6653aSJeff Kirsher { 11247ac6653aSJeff Kirsher int i; 11257ac6653aSJeff Kirsher 1126e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_TX_SIZE; i++) { 1127362b37beSGiuseppe CAVALLARO if (priv->tx_skbuff_dma[i].buf) { 1128362b37beSGiuseppe CAVALLARO if (priv->tx_skbuff_dma[i].map_as_page) 1129362b37beSGiuseppe CAVALLARO dma_unmap_page(priv->device, 1130362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf, 1131553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[i].len, 11327ac6653aSJeff Kirsher DMA_TO_DEVICE); 1133362b37beSGiuseppe CAVALLARO else 1134362b37beSGiuseppe CAVALLARO dma_unmap_single(priv->device, 1135362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf, 1136553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[i].len, 1137362b37beSGiuseppe CAVALLARO DMA_TO_DEVICE); 113875e4364fSdamuzi000 } 113975e4364fSdamuzi000 1140662ec2b7SLABBE Corentin if (priv->tx_skbuff[i]) { 11417ac6653aSJeff Kirsher dev_kfree_skb_any(priv->tx_skbuff[i]); 11427ac6653aSJeff Kirsher priv->tx_skbuff[i] = NULL; 1143362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf = 0; 1144362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].map_as_page = false; 11457ac6653aSJeff Kirsher } 11467ac6653aSJeff Kirsher } 11477ac6653aSJeff Kirsher } 11487ac6653aSJeff Kirsher 1149732fdf0eSGiuseppe CAVALLARO /** 1150732fdf0eSGiuseppe CAVALLARO * alloc_dma_desc_resources - alloc TX/RX resources. 1151732fdf0eSGiuseppe CAVALLARO * @priv: private structure 1152732fdf0eSGiuseppe CAVALLARO * Description: according to which descriptor can be used (extend or basic) 1153732fdf0eSGiuseppe CAVALLARO * this function allocates the resources for TX and RX paths. In case of 1154732fdf0eSGiuseppe CAVALLARO * reception, for example, it pre-allocated the RX socket buffer in order to 1155732fdf0eSGiuseppe CAVALLARO * allow zero-copy mechanism. 1156732fdf0eSGiuseppe CAVALLARO */ 115709f8d696SSrinivas Kandagatla static int alloc_dma_desc_resources(struct stmmac_priv *priv) 115809f8d696SSrinivas Kandagatla { 115909f8d696SSrinivas Kandagatla int ret = -ENOMEM; 116009f8d696SSrinivas Kandagatla 1161e3ad57c9SGiuseppe Cavallaro priv->rx_skbuff_dma = kmalloc_array(DMA_RX_SIZE, sizeof(dma_addr_t), 116209f8d696SSrinivas Kandagatla GFP_KERNEL); 116309f8d696SSrinivas Kandagatla if (!priv->rx_skbuff_dma) 116409f8d696SSrinivas Kandagatla return -ENOMEM; 116509f8d696SSrinivas Kandagatla 1166e3ad57c9SGiuseppe Cavallaro priv->rx_skbuff = kmalloc_array(DMA_RX_SIZE, sizeof(struct sk_buff *), 116709f8d696SSrinivas Kandagatla GFP_KERNEL); 116809f8d696SSrinivas Kandagatla if (!priv->rx_skbuff) 116909f8d696SSrinivas Kandagatla goto err_rx_skbuff; 117009f8d696SSrinivas Kandagatla 1171e3ad57c9SGiuseppe Cavallaro priv->tx_skbuff_dma = kmalloc_array(DMA_TX_SIZE, 1172362b37beSGiuseppe CAVALLARO sizeof(*priv->tx_skbuff_dma), 117309f8d696SSrinivas Kandagatla GFP_KERNEL); 117409f8d696SSrinivas Kandagatla if (!priv->tx_skbuff_dma) 117509f8d696SSrinivas Kandagatla goto err_tx_skbuff_dma; 117609f8d696SSrinivas Kandagatla 1177e3ad57c9SGiuseppe Cavallaro priv->tx_skbuff = kmalloc_array(DMA_TX_SIZE, sizeof(struct sk_buff *), 117809f8d696SSrinivas Kandagatla GFP_KERNEL); 117909f8d696SSrinivas Kandagatla if (!priv->tx_skbuff) 118009f8d696SSrinivas Kandagatla goto err_tx_skbuff; 118109f8d696SSrinivas Kandagatla 118209f8d696SSrinivas Kandagatla if (priv->extend_desc) { 1183e3ad57c9SGiuseppe Cavallaro priv->dma_erx = dma_zalloc_coherent(priv->device, DMA_RX_SIZE * 118409f8d696SSrinivas Kandagatla sizeof(struct 118509f8d696SSrinivas Kandagatla dma_extended_desc), 118609f8d696SSrinivas Kandagatla &priv->dma_rx_phy, 118709f8d696SSrinivas Kandagatla GFP_KERNEL); 118809f8d696SSrinivas Kandagatla if (!priv->dma_erx) 118909f8d696SSrinivas Kandagatla goto err_dma; 119009f8d696SSrinivas Kandagatla 1191e3ad57c9SGiuseppe Cavallaro priv->dma_etx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE * 119209f8d696SSrinivas Kandagatla sizeof(struct 119309f8d696SSrinivas Kandagatla dma_extended_desc), 119409f8d696SSrinivas Kandagatla &priv->dma_tx_phy, 119509f8d696SSrinivas Kandagatla GFP_KERNEL); 119609f8d696SSrinivas Kandagatla if (!priv->dma_etx) { 1197e3ad57c9SGiuseppe Cavallaro dma_free_coherent(priv->device, DMA_RX_SIZE * 119809f8d696SSrinivas Kandagatla sizeof(struct dma_extended_desc), 119909f8d696SSrinivas Kandagatla priv->dma_erx, priv->dma_rx_phy); 120009f8d696SSrinivas Kandagatla goto err_dma; 120109f8d696SSrinivas Kandagatla } 120209f8d696SSrinivas Kandagatla } else { 1203e3ad57c9SGiuseppe Cavallaro priv->dma_rx = dma_zalloc_coherent(priv->device, DMA_RX_SIZE * 120409f8d696SSrinivas Kandagatla sizeof(struct dma_desc), 120509f8d696SSrinivas Kandagatla &priv->dma_rx_phy, 120609f8d696SSrinivas Kandagatla GFP_KERNEL); 120709f8d696SSrinivas Kandagatla if (!priv->dma_rx) 120809f8d696SSrinivas Kandagatla goto err_dma; 120909f8d696SSrinivas Kandagatla 1210e3ad57c9SGiuseppe Cavallaro priv->dma_tx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE * 121109f8d696SSrinivas Kandagatla sizeof(struct dma_desc), 121209f8d696SSrinivas Kandagatla &priv->dma_tx_phy, 121309f8d696SSrinivas Kandagatla GFP_KERNEL); 121409f8d696SSrinivas Kandagatla if (!priv->dma_tx) { 1215e3ad57c9SGiuseppe Cavallaro dma_free_coherent(priv->device, DMA_RX_SIZE * 121609f8d696SSrinivas Kandagatla sizeof(struct dma_desc), 121709f8d696SSrinivas Kandagatla priv->dma_rx, priv->dma_rx_phy); 121809f8d696SSrinivas Kandagatla goto err_dma; 121909f8d696SSrinivas Kandagatla } 122009f8d696SSrinivas Kandagatla } 122109f8d696SSrinivas Kandagatla 122209f8d696SSrinivas Kandagatla return 0; 122309f8d696SSrinivas Kandagatla 122409f8d696SSrinivas Kandagatla err_dma: 122509f8d696SSrinivas Kandagatla kfree(priv->tx_skbuff); 122609f8d696SSrinivas Kandagatla err_tx_skbuff: 122709f8d696SSrinivas Kandagatla kfree(priv->tx_skbuff_dma); 122809f8d696SSrinivas Kandagatla err_tx_skbuff_dma: 122909f8d696SSrinivas Kandagatla kfree(priv->rx_skbuff); 123009f8d696SSrinivas Kandagatla err_rx_skbuff: 123109f8d696SSrinivas Kandagatla kfree(priv->rx_skbuff_dma); 123209f8d696SSrinivas Kandagatla return ret; 123309f8d696SSrinivas Kandagatla } 123409f8d696SSrinivas Kandagatla 12357ac6653aSJeff Kirsher static void free_dma_desc_resources(struct stmmac_priv *priv) 12367ac6653aSJeff Kirsher { 12377ac6653aSJeff Kirsher /* Release the DMA TX/RX socket buffers */ 12387ac6653aSJeff Kirsher dma_free_rx_skbufs(priv); 12397ac6653aSJeff Kirsher dma_free_tx_skbufs(priv); 12407ac6653aSJeff Kirsher 1241ceb69499SGiuseppe CAVALLARO /* Free DMA regions of consistent memory previously allocated */ 1242c24602efSGiuseppe CAVALLARO if (!priv->extend_desc) { 12437ac6653aSJeff Kirsher dma_free_coherent(priv->device, 1244e3ad57c9SGiuseppe Cavallaro DMA_TX_SIZE * sizeof(struct dma_desc), 12457ac6653aSJeff Kirsher priv->dma_tx, priv->dma_tx_phy); 12467ac6653aSJeff Kirsher dma_free_coherent(priv->device, 1247e3ad57c9SGiuseppe Cavallaro DMA_RX_SIZE * sizeof(struct dma_desc), 12487ac6653aSJeff Kirsher priv->dma_rx, priv->dma_rx_phy); 1249c24602efSGiuseppe CAVALLARO } else { 1250e3ad57c9SGiuseppe Cavallaro dma_free_coherent(priv->device, DMA_TX_SIZE * 1251c24602efSGiuseppe CAVALLARO sizeof(struct dma_extended_desc), 1252c24602efSGiuseppe CAVALLARO priv->dma_etx, priv->dma_tx_phy); 1253e3ad57c9SGiuseppe Cavallaro dma_free_coherent(priv->device, DMA_RX_SIZE * 1254c24602efSGiuseppe CAVALLARO sizeof(struct dma_extended_desc), 1255c24602efSGiuseppe CAVALLARO priv->dma_erx, priv->dma_rx_phy); 1256c24602efSGiuseppe CAVALLARO } 12577ac6653aSJeff Kirsher kfree(priv->rx_skbuff_dma); 12587ac6653aSJeff Kirsher kfree(priv->rx_skbuff); 1259cf32deecSRayagond Kokatanur kfree(priv->tx_skbuff_dma); 12607ac6653aSJeff Kirsher kfree(priv->tx_skbuff); 12617ac6653aSJeff Kirsher } 12627ac6653aSJeff Kirsher 12637ac6653aSJeff Kirsher /** 12649eb12474Sjpinto * stmmac_mac_enable_rx_queues - Enable MAC rx queues 12659eb12474Sjpinto * @priv: driver private structure 12669eb12474Sjpinto * Description: It is used for enabling the rx queues in the MAC 12679eb12474Sjpinto */ 12689eb12474Sjpinto static void stmmac_mac_enable_rx_queues(struct stmmac_priv *priv) 12699eb12474Sjpinto { 12704f6046f5SJoao Pinto u32 rx_queues_count = priv->plat->rx_queues_to_use; 12714f6046f5SJoao Pinto int queue; 12724f6046f5SJoao Pinto u8 mode; 12739eb12474Sjpinto 12744f6046f5SJoao Pinto for (queue = 0; queue < rx_queues_count; queue++) { 12754f6046f5SJoao Pinto mode = priv->plat->rx_queues_cfg[queue].mode_to_use; 12764f6046f5SJoao Pinto priv->hw->mac->rx_queue_enable(priv->hw, mode, queue); 12774f6046f5SJoao Pinto } 12789eb12474Sjpinto } 12799eb12474Sjpinto 12809eb12474Sjpinto /** 12817ac6653aSJeff Kirsher * stmmac_dma_operation_mode - HW DMA operation mode 128232ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 1283732fdf0eSGiuseppe CAVALLARO * Description: it is used for configuring the DMA operation mode register in 1284732fdf0eSGiuseppe CAVALLARO * order to program the tx/rx DMA thresholds or Store-And-Forward mode. 12857ac6653aSJeff Kirsher */ 12867ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv) 12877ac6653aSJeff Kirsher { 1288f88203a2SVince Bridgers int rxfifosz = priv->plat->rx_fifo_size; 1289f88203a2SVince Bridgers 129011fbf811SThierry Reding if (rxfifosz == 0) 129111fbf811SThierry Reding rxfifosz = priv->dma_cap.rx_fifo_size; 129211fbf811SThierry Reding 1293e2a240c7SSonic Zhang if (priv->plat->force_thresh_dma_mode) 1294f88203a2SVince Bridgers priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz); 1295e2a240c7SSonic Zhang else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { 12967ac6653aSJeff Kirsher /* 12977ac6653aSJeff Kirsher * In case of GMAC, SF mode can be enabled 12987ac6653aSJeff Kirsher * to perform the TX COE in HW. This depends on: 12997ac6653aSJeff Kirsher * 1) TX COE if actually supported 13007ac6653aSJeff Kirsher * 2) There is no bugged Jumbo frame support 13017ac6653aSJeff Kirsher * that needs to not insert csum in the TDES. 13027ac6653aSJeff Kirsher */ 1303f88203a2SVince Bridgers priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE, 1304f88203a2SVince Bridgers rxfifosz); 1305b2dec116SSonic Zhang priv->xstats.threshold = SF_DMA_MODE; 13067ac6653aSJeff Kirsher } else 1307f88203a2SVince Bridgers priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE, 1308f88203a2SVince Bridgers rxfifosz); 13097ac6653aSJeff Kirsher } 13107ac6653aSJeff Kirsher 13117ac6653aSJeff Kirsher /** 1312732fdf0eSGiuseppe CAVALLARO * stmmac_tx_clean - to manage the transmission completion 131332ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 1314732fdf0eSGiuseppe CAVALLARO * Description: it reclaims the transmit resources after transmission completes. 13157ac6653aSJeff Kirsher */ 13169125cdd1SGiuseppe CAVALLARO static void stmmac_tx_clean(struct stmmac_priv *priv) 13177ac6653aSJeff Kirsher { 131838979574SBeniamino Galvani unsigned int bytes_compl = 0, pkts_compl = 0; 1319e3ad57c9SGiuseppe Cavallaro unsigned int entry = priv->dirty_tx; 13207ac6653aSJeff Kirsher 1321739c8e14SLino Sanfilippo netif_tx_lock(priv->dev); 1322a9097a96SGiuseppe CAVALLARO 13239125cdd1SGiuseppe CAVALLARO priv->xstats.tx_clean++; 13249125cdd1SGiuseppe CAVALLARO 1325e3ad57c9SGiuseppe Cavallaro while (entry != priv->cur_tx) { 13267ac6653aSJeff Kirsher struct sk_buff *skb = priv->tx_skbuff[entry]; 1327c24602efSGiuseppe CAVALLARO struct dma_desc *p; 1328c363b658SFabrice Gasnier int status; 1329c24602efSGiuseppe CAVALLARO 1330c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1331c24602efSGiuseppe CAVALLARO p = (struct dma_desc *)(priv->dma_etx + entry); 1332c24602efSGiuseppe CAVALLARO else 1333c24602efSGiuseppe CAVALLARO p = priv->dma_tx + entry; 13347ac6653aSJeff Kirsher 1335c363b658SFabrice Gasnier status = priv->hw->desc->tx_status(&priv->dev->stats, 13367ac6653aSJeff Kirsher &priv->xstats, p, 13377ac6653aSJeff Kirsher priv->ioaddr); 1338c363b658SFabrice Gasnier /* Check if the descriptor is owned by the DMA */ 1339c363b658SFabrice Gasnier if (unlikely(status & tx_dma_own)) 1340c363b658SFabrice Gasnier break; 1341c363b658SFabrice Gasnier 1342c363b658SFabrice Gasnier /* Just consider the last segment and ...*/ 1343c363b658SFabrice Gasnier if (likely(!(status & tx_not_ls))) { 1344c363b658SFabrice Gasnier /* ... verify the status error condition */ 1345c363b658SFabrice Gasnier if (unlikely(status & tx_err)) { 1346c363b658SFabrice Gasnier priv->dev->stats.tx_errors++; 1347c363b658SFabrice Gasnier } else { 13487ac6653aSJeff Kirsher priv->dev->stats.tx_packets++; 13497ac6653aSJeff Kirsher priv->xstats.tx_pkt_n++; 1350c363b658SFabrice Gasnier } 1351ba1ffd74SGiuseppe CAVALLARO stmmac_get_tx_hwtstamp(priv, p, skb); 13527ac6653aSJeff Kirsher } 13537ac6653aSJeff Kirsher 1354362b37beSGiuseppe CAVALLARO if (likely(priv->tx_skbuff_dma[entry].buf)) { 1355362b37beSGiuseppe CAVALLARO if (priv->tx_skbuff_dma[entry].map_as_page) 1356362b37beSGiuseppe CAVALLARO dma_unmap_page(priv->device, 1357362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf, 1358553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].len, 13597ac6653aSJeff Kirsher DMA_TO_DEVICE); 1360362b37beSGiuseppe CAVALLARO else 1361362b37beSGiuseppe CAVALLARO dma_unmap_single(priv->device, 1362362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf, 1363553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].len, 1364362b37beSGiuseppe CAVALLARO DMA_TO_DEVICE); 1365362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf = 0; 1366f748be53SAlexandre TORGUE priv->tx_skbuff_dma[entry].len = 0; 1367362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].map_as_page = false; 1368cf32deecSRayagond Kokatanur } 1369f748be53SAlexandre TORGUE 1370f748be53SAlexandre TORGUE if (priv->hw->mode->clean_desc3) 137129896a67SGiuseppe CAVALLARO priv->hw->mode->clean_desc3(priv, p); 1372f748be53SAlexandre TORGUE 13732a6d8e17SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].last_segment = false; 137496951366SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].is_jumbo = false; 13757ac6653aSJeff Kirsher 13767ac6653aSJeff Kirsher if (likely(skb != NULL)) { 137738979574SBeniamino Galvani pkts_compl++; 137838979574SBeniamino Galvani bytes_compl += skb->len; 13797c565c33SEric W. Biederman dev_consume_skb_any(skb); 13807ac6653aSJeff Kirsher priv->tx_skbuff[entry] = NULL; 13817ac6653aSJeff Kirsher } 13827ac6653aSJeff Kirsher 13834a7d666aSGiuseppe CAVALLARO priv->hw->desc->release_tx_desc(p, priv->mode); 13847ac6653aSJeff Kirsher 1385e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); 13867ac6653aSJeff Kirsher } 1387fbc80823SGiuseppe Cavallaro priv->dirty_tx = entry; 138838979574SBeniamino Galvani 138938979574SBeniamino Galvani netdev_completed_queue(priv->dev, pkts_compl, bytes_compl); 139038979574SBeniamino Galvani 13917ac6653aSJeff Kirsher if (unlikely(netif_queue_stopped(priv->dev) && 1392e3ad57c9SGiuseppe Cavallaro stmmac_tx_avail(priv) > STMMAC_TX_THRESH)) { 1393b3e51069SLABBE Corentin netif_dbg(priv, tx_done, priv->dev, 1394b3e51069SLABBE Corentin "%s: restart transmit\n", __func__); 13957ac6653aSJeff Kirsher netif_wake_queue(priv->dev); 13967ac6653aSJeff Kirsher } 1397d765955dSGiuseppe CAVALLARO 1398d765955dSGiuseppe CAVALLARO if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) { 1399d765955dSGiuseppe CAVALLARO stmmac_enable_eee_mode(priv); 1400f5351ef7SGiuseppe CAVALLARO mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); 1401d765955dSGiuseppe CAVALLARO } 1402739c8e14SLino Sanfilippo netif_tx_unlock(priv->dev); 14037ac6653aSJeff Kirsher } 14047ac6653aSJeff Kirsher 14059125cdd1SGiuseppe CAVALLARO static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv) 14067ac6653aSJeff Kirsher { 14077ac6653aSJeff Kirsher priv->hw->dma->enable_dma_irq(priv->ioaddr); 14087ac6653aSJeff Kirsher } 14097ac6653aSJeff Kirsher 14109125cdd1SGiuseppe CAVALLARO static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv) 14117ac6653aSJeff Kirsher { 14127ac6653aSJeff Kirsher priv->hw->dma->disable_dma_irq(priv->ioaddr); 14137ac6653aSJeff Kirsher } 14147ac6653aSJeff Kirsher 14157ac6653aSJeff Kirsher /** 1416732fdf0eSGiuseppe CAVALLARO * stmmac_tx_err - to manage the tx error 141732ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 14187ac6653aSJeff Kirsher * Description: it cleans the descriptors and restarts the transmission 1419732fdf0eSGiuseppe CAVALLARO * in case of transmission errors. 14207ac6653aSJeff Kirsher */ 14217ac6653aSJeff Kirsher static void stmmac_tx_err(struct stmmac_priv *priv) 14227ac6653aSJeff Kirsher { 1423c24602efSGiuseppe CAVALLARO int i; 14247ac6653aSJeff Kirsher netif_stop_queue(priv->dev); 14257ac6653aSJeff Kirsher 14267ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 14277ac6653aSJeff Kirsher dma_free_tx_skbufs(priv); 1428e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_TX_SIZE; i++) 1429c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1430c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic, 1431c24602efSGiuseppe CAVALLARO priv->mode, 1432e3ad57c9SGiuseppe Cavallaro (i == DMA_TX_SIZE - 1)); 1433c24602efSGiuseppe CAVALLARO else 1434c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_tx[i], 1435c24602efSGiuseppe CAVALLARO priv->mode, 1436e3ad57c9SGiuseppe Cavallaro (i == DMA_TX_SIZE - 1)); 14377ac6653aSJeff Kirsher priv->dirty_tx = 0; 14387ac6653aSJeff Kirsher priv->cur_tx = 0; 143938979574SBeniamino Galvani netdev_reset_queue(priv->dev); 14407ac6653aSJeff Kirsher priv->hw->dma->start_tx(priv->ioaddr); 14417ac6653aSJeff Kirsher 14427ac6653aSJeff Kirsher priv->dev->stats.tx_errors++; 14437ac6653aSJeff Kirsher netif_wake_queue(priv->dev); 14447ac6653aSJeff Kirsher } 14457ac6653aSJeff Kirsher 144632ceabcaSGiuseppe CAVALLARO /** 1447732fdf0eSGiuseppe CAVALLARO * stmmac_dma_interrupt - DMA ISR 144832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 144932ceabcaSGiuseppe CAVALLARO * Description: this is the DMA ISR. It is called by the main ISR. 1450732fdf0eSGiuseppe CAVALLARO * It calls the dwmac dma routine and schedule poll method in case of some 1451732fdf0eSGiuseppe CAVALLARO * work can be done. 145232ceabcaSGiuseppe CAVALLARO */ 14537ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv) 14547ac6653aSJeff Kirsher { 14557ac6653aSJeff Kirsher int status; 1456f88203a2SVince Bridgers int rxfifosz = priv->plat->rx_fifo_size; 14577ac6653aSJeff Kirsher 14587ac6653aSJeff Kirsher status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); 14599125cdd1SGiuseppe CAVALLARO if (likely((status & handle_rx)) || (status & handle_tx)) { 14609125cdd1SGiuseppe CAVALLARO if (likely(napi_schedule_prep(&priv->napi))) { 14619125cdd1SGiuseppe CAVALLARO stmmac_disable_dma_irq(priv); 14629125cdd1SGiuseppe CAVALLARO __napi_schedule(&priv->napi); 14639125cdd1SGiuseppe CAVALLARO } 14649125cdd1SGiuseppe CAVALLARO } 14659125cdd1SGiuseppe CAVALLARO if (unlikely(status & tx_hard_error_bump_tc)) { 14667ac6653aSJeff Kirsher /* Try to bump up the dma threshold on this failure */ 1467b2dec116SSonic Zhang if (unlikely(priv->xstats.threshold != SF_DMA_MODE) && 1468b2dec116SSonic Zhang (tc <= 256)) { 14697ac6653aSJeff Kirsher tc += 64; 1470c405abe2SSonic Zhang if (priv->plat->force_thresh_dma_mode) 1471f88203a2SVince Bridgers priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, 1472f88203a2SVince Bridgers rxfifosz); 1473c405abe2SSonic Zhang else 1474c405abe2SSonic Zhang priv->hw->dma->dma_mode(priv->ioaddr, tc, 1475f88203a2SVince Bridgers SF_DMA_MODE, rxfifosz); 14767ac6653aSJeff Kirsher priv->xstats.threshold = tc; 14777ac6653aSJeff Kirsher } 14787ac6653aSJeff Kirsher } else if (unlikely(status == tx_hard_error)) 14797ac6653aSJeff Kirsher stmmac_tx_err(priv); 14807ac6653aSJeff Kirsher } 14817ac6653aSJeff Kirsher 148232ceabcaSGiuseppe CAVALLARO /** 148332ceabcaSGiuseppe CAVALLARO * stmmac_mmc_setup: setup the Mac Management Counters (MMC) 148432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 148532ceabcaSGiuseppe CAVALLARO * Description: this masks the MMC irq, in fact, the counters are managed in SW. 148632ceabcaSGiuseppe CAVALLARO */ 14871c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv) 14881c901a46SGiuseppe CAVALLARO { 14891c901a46SGiuseppe CAVALLARO unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET | 14901c901a46SGiuseppe CAVALLARO MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET; 14911c901a46SGiuseppe CAVALLARO 1492ba1ffd74SGiuseppe CAVALLARO if (priv->synopsys_id >= DWMAC_CORE_4_00) { 1493ba1ffd74SGiuseppe CAVALLARO priv->ptpaddr = priv->ioaddr + PTP_GMAC4_OFFSET; 1494f748be53SAlexandre TORGUE priv->mmcaddr = priv->ioaddr + MMC_GMAC4_OFFSET; 1495ba1ffd74SGiuseppe CAVALLARO } else { 1496ba1ffd74SGiuseppe CAVALLARO priv->ptpaddr = priv->ioaddr + PTP_GMAC3_X_OFFSET; 149736ff7c1eSAlexandre TORGUE priv->mmcaddr = priv->ioaddr + MMC_GMAC3_X_OFFSET; 1498ba1ffd74SGiuseppe CAVALLARO } 149936ff7c1eSAlexandre TORGUE 150036ff7c1eSAlexandre TORGUE dwmac_mmc_intr_all_mask(priv->mmcaddr); 15014f795b25SGiuseppe CAVALLARO 15024f795b25SGiuseppe CAVALLARO if (priv->dma_cap.rmon) { 150336ff7c1eSAlexandre TORGUE dwmac_mmc_ctrl(priv->mmcaddr, mode); 15041c901a46SGiuseppe CAVALLARO memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); 15054f795b25SGiuseppe CAVALLARO } else 150638ddc59dSLABBE Corentin netdev_info(priv->dev, "No MAC Management Counters available\n"); 15071c901a46SGiuseppe CAVALLARO } 15081c901a46SGiuseppe CAVALLARO 1509732fdf0eSGiuseppe CAVALLARO /** 1510732fdf0eSGiuseppe CAVALLARO * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors 151132ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 151232ceabcaSGiuseppe CAVALLARO * Description: select the Enhanced/Alternate or Normal descriptors. 1513732fdf0eSGiuseppe CAVALLARO * In case of Enhanced/Alternate, it checks if the extended descriptors are 1514732fdf0eSGiuseppe CAVALLARO * supported by the HW capability register. 1515ff3dd78cSGiuseppe CAVALLARO */ 151619e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv) 151719e30c14SGiuseppe CAVALLARO { 151819e30c14SGiuseppe CAVALLARO if (priv->plat->enh_desc) { 151938ddc59dSLABBE Corentin dev_info(priv->device, "Enhanced/Alternate descriptors\n"); 1520c24602efSGiuseppe CAVALLARO 1521c24602efSGiuseppe CAVALLARO /* GMAC older than 3.50 has no extended descriptors */ 1522c24602efSGiuseppe CAVALLARO if (priv->synopsys_id >= DWMAC_CORE_3_50) { 152338ddc59dSLABBE Corentin dev_info(priv->device, "Enabled extended descriptors\n"); 1524c24602efSGiuseppe CAVALLARO priv->extend_desc = 1; 1525c24602efSGiuseppe CAVALLARO } else 152638ddc59dSLABBE Corentin dev_warn(priv->device, "Extended descriptors not supported\n"); 1527c24602efSGiuseppe CAVALLARO 152819e30c14SGiuseppe CAVALLARO priv->hw->desc = &enh_desc_ops; 152919e30c14SGiuseppe CAVALLARO } else { 153038ddc59dSLABBE Corentin dev_info(priv->device, "Normal descriptors\n"); 153119e30c14SGiuseppe CAVALLARO priv->hw->desc = &ndesc_ops; 153219e30c14SGiuseppe CAVALLARO } 153319e30c14SGiuseppe CAVALLARO } 153419e30c14SGiuseppe CAVALLARO 153519e30c14SGiuseppe CAVALLARO /** 1536732fdf0eSGiuseppe CAVALLARO * stmmac_get_hw_features - get MAC capabilities from the HW cap. register. 153732ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 153819e30c14SGiuseppe CAVALLARO * Description: 153919e30c14SGiuseppe CAVALLARO * new GMAC chip generations have a new register to indicate the 1540e7434821SGiuseppe CAVALLARO * presence of the optional feature/functions. 154119e30c14SGiuseppe CAVALLARO * This can be also used to override the value passed through the 154219e30c14SGiuseppe CAVALLARO * platform and necessary for old MAC10/100 and GMAC chips. 1543e7434821SGiuseppe CAVALLARO */ 1544e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv) 1545e7434821SGiuseppe CAVALLARO { 1546f10a6a35SAlexandre TORGUE u32 ret = 0; 15473c20f72fSGiuseppe CAVALLARO 15485e6efe88SGiuseppe CAVALLARO if (priv->hw->dma->get_hw_feature) { 1549f10a6a35SAlexandre TORGUE priv->hw->dma->get_hw_feature(priv->ioaddr, 1550f10a6a35SAlexandre TORGUE &priv->dma_cap); 1551f10a6a35SAlexandre TORGUE ret = 1; 155219e30c14SGiuseppe CAVALLARO } 1553e7434821SGiuseppe CAVALLARO 1554f10a6a35SAlexandre TORGUE return ret; 1555e7434821SGiuseppe CAVALLARO } 1556e7434821SGiuseppe CAVALLARO 155732ceabcaSGiuseppe CAVALLARO /** 1558732fdf0eSGiuseppe CAVALLARO * stmmac_check_ether_addr - check if the MAC addr is valid 155932ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 156032ceabcaSGiuseppe CAVALLARO * Description: 156132ceabcaSGiuseppe CAVALLARO * it is to verify if the MAC address is valid, in case of failures it 156232ceabcaSGiuseppe CAVALLARO * generates a random MAC address 156332ceabcaSGiuseppe CAVALLARO */ 1564bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv) 1565bfab27a1SGiuseppe CAVALLARO { 1566bfab27a1SGiuseppe CAVALLARO if (!is_valid_ether_addr(priv->dev->dev_addr)) { 15677ed24bbeSVince Bridgers priv->hw->mac->get_umac_addr(priv->hw, 1568bfab27a1SGiuseppe CAVALLARO priv->dev->dev_addr, 0); 1569bfab27a1SGiuseppe CAVALLARO if (!is_valid_ether_addr(priv->dev->dev_addr)) 1570f2cedb63SDanny Kukawka eth_hw_addr_random(priv->dev); 157138ddc59dSLABBE Corentin netdev_info(priv->dev, "device MAC address %pM\n", 1572bfab27a1SGiuseppe CAVALLARO priv->dev->dev_addr); 1573bfab27a1SGiuseppe CAVALLARO } 1574c88460b7SHans de Goede } 1575bfab27a1SGiuseppe CAVALLARO 157632ceabcaSGiuseppe CAVALLARO /** 1577732fdf0eSGiuseppe CAVALLARO * stmmac_init_dma_engine - DMA init. 157832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 157932ceabcaSGiuseppe CAVALLARO * Description: 158032ceabcaSGiuseppe CAVALLARO * It inits the DMA invoking the specific MAC/GMAC callback. 158132ceabcaSGiuseppe CAVALLARO * Some DMA parameters can be passed from the platform; 158232ceabcaSGiuseppe CAVALLARO * in case of these are not passed a default is kept for the MAC or GMAC. 158332ceabcaSGiuseppe CAVALLARO */ 15840f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv) 15850f1f88a8SGiuseppe CAVALLARO { 1586c24602efSGiuseppe CAVALLARO int atds = 0; 1587495db273SGiuseppe Cavallaro int ret = 0; 15880f1f88a8SGiuseppe CAVALLARO 1589a332e2faSNiklas Cassel if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) { 1590a332e2faSNiklas Cassel dev_err(priv->device, "Invalid DMA configuration\n"); 159189ab75bfSNiklas Cassel return -EINVAL; 15920f1f88a8SGiuseppe CAVALLARO } 15930f1f88a8SGiuseppe CAVALLARO 1594c24602efSGiuseppe CAVALLARO if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE)) 1595c24602efSGiuseppe CAVALLARO atds = 1; 1596c24602efSGiuseppe CAVALLARO 1597495db273SGiuseppe Cavallaro ret = priv->hw->dma->reset(priv->ioaddr); 1598495db273SGiuseppe Cavallaro if (ret) { 1599495db273SGiuseppe Cavallaro dev_err(priv->device, "Failed to reset the dma\n"); 1600495db273SGiuseppe Cavallaro return ret; 1601495db273SGiuseppe Cavallaro } 1602495db273SGiuseppe Cavallaro 160350ca903aSNiklas Cassel priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg, 160489ab75bfSNiklas Cassel priv->dma_tx_phy, priv->dma_rx_phy, atds); 1605afea0365SGiuseppe Cavallaro 1606f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) { 1607f748be53SAlexandre TORGUE priv->rx_tail_addr = priv->dma_rx_phy + 1608f748be53SAlexandre TORGUE (DMA_RX_SIZE * sizeof(struct dma_desc)); 1609f748be53SAlexandre TORGUE priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, priv->rx_tail_addr, 1610f748be53SAlexandre TORGUE STMMAC_CHAN0); 1611f748be53SAlexandre TORGUE 1612f748be53SAlexandre TORGUE priv->tx_tail_addr = priv->dma_tx_phy + 1613f748be53SAlexandre TORGUE (DMA_TX_SIZE * sizeof(struct dma_desc)); 1614f748be53SAlexandre TORGUE priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, 1615f748be53SAlexandre TORGUE STMMAC_CHAN0); 1616f748be53SAlexandre TORGUE } 1617f748be53SAlexandre TORGUE 1618f748be53SAlexandre TORGUE if (priv->plat->axi && priv->hw->dma->axi) 1619afea0365SGiuseppe Cavallaro priv->hw->dma->axi(priv->ioaddr, priv->plat->axi); 1620afea0365SGiuseppe Cavallaro 1621495db273SGiuseppe Cavallaro return ret; 16220f1f88a8SGiuseppe CAVALLARO } 16230f1f88a8SGiuseppe CAVALLARO 1624bfab27a1SGiuseppe CAVALLARO /** 1625732fdf0eSGiuseppe CAVALLARO * stmmac_tx_timer - mitigation sw timer for tx. 16269125cdd1SGiuseppe CAVALLARO * @data: data pointer 16279125cdd1SGiuseppe CAVALLARO * Description: 16289125cdd1SGiuseppe CAVALLARO * This is the timer handler to directly invoke the stmmac_tx_clean. 16299125cdd1SGiuseppe CAVALLARO */ 16309125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data) 16319125cdd1SGiuseppe CAVALLARO { 16329125cdd1SGiuseppe CAVALLARO struct stmmac_priv *priv = (struct stmmac_priv *)data; 16339125cdd1SGiuseppe CAVALLARO 16349125cdd1SGiuseppe CAVALLARO stmmac_tx_clean(priv); 16359125cdd1SGiuseppe CAVALLARO } 16369125cdd1SGiuseppe CAVALLARO 16379125cdd1SGiuseppe CAVALLARO /** 1638732fdf0eSGiuseppe CAVALLARO * stmmac_init_tx_coalesce - init tx mitigation options. 163932ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 16409125cdd1SGiuseppe CAVALLARO * Description: 16419125cdd1SGiuseppe CAVALLARO * This inits the transmit coalesce parameters: i.e. timer rate, 16429125cdd1SGiuseppe CAVALLARO * timer handler and default threshold used for enabling the 16439125cdd1SGiuseppe CAVALLARO * interrupt on completion bit. 16449125cdd1SGiuseppe CAVALLARO */ 16459125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) 16469125cdd1SGiuseppe CAVALLARO { 16479125cdd1SGiuseppe CAVALLARO priv->tx_coal_frames = STMMAC_TX_FRAMES; 16489125cdd1SGiuseppe CAVALLARO priv->tx_coal_timer = STMMAC_COAL_TX_TIMER; 16499125cdd1SGiuseppe CAVALLARO init_timer(&priv->txtimer); 16509125cdd1SGiuseppe CAVALLARO priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer); 16519125cdd1SGiuseppe CAVALLARO priv->txtimer.data = (unsigned long)priv; 16529125cdd1SGiuseppe CAVALLARO priv->txtimer.function = stmmac_tx_timer; 16539125cdd1SGiuseppe CAVALLARO add_timer(&priv->txtimer); 16549125cdd1SGiuseppe CAVALLARO } 16559125cdd1SGiuseppe CAVALLARO 16569125cdd1SGiuseppe CAVALLARO /** 16576a3a7193SJoao Pinto * stmmac_set_tx_queue_weight - Set TX queue weight 16586a3a7193SJoao Pinto * @priv: driver private structure 16596a3a7193SJoao Pinto * Description: It is used for setting TX queues weight 16606a3a7193SJoao Pinto */ 16616a3a7193SJoao Pinto static void stmmac_set_tx_queue_weight(struct stmmac_priv *priv) 16626a3a7193SJoao Pinto { 16636a3a7193SJoao Pinto u32 tx_queues_count = priv->plat->tx_queues_to_use; 16646a3a7193SJoao Pinto u32 weight; 16656a3a7193SJoao Pinto u32 queue; 16666a3a7193SJoao Pinto 16676a3a7193SJoao Pinto for (queue = 0; queue < tx_queues_count; queue++) { 16686a3a7193SJoao Pinto weight = priv->plat->tx_queues_cfg[queue].weight; 16696a3a7193SJoao Pinto priv->hw->mac->set_mtl_tx_queue_weight(priv->hw, weight, queue); 16706a3a7193SJoao Pinto } 16716a3a7193SJoao Pinto } 16726a3a7193SJoao Pinto 16736a3a7193SJoao Pinto /** 167419d91873SJoao Pinto * stmmac_configure_cbs - Configure CBS in TX queue 167519d91873SJoao Pinto * @priv: driver private structure 167619d91873SJoao Pinto * Description: It is used for configuring CBS in AVB TX queues 167719d91873SJoao Pinto */ 167819d91873SJoao Pinto static void stmmac_configure_cbs(struct stmmac_priv *priv) 167919d91873SJoao Pinto { 168019d91873SJoao Pinto u32 tx_queues_count = priv->plat->tx_queues_to_use; 168119d91873SJoao Pinto u32 mode_to_use; 168219d91873SJoao Pinto u32 queue; 168319d91873SJoao Pinto 168419d91873SJoao Pinto for (queue = 0; queue < tx_queues_count; queue++) { 168519d91873SJoao Pinto mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use; 168619d91873SJoao Pinto if (mode_to_use == MTL_QUEUE_DCB) 168719d91873SJoao Pinto continue; 168819d91873SJoao Pinto 168919d91873SJoao Pinto priv->hw->mac->config_cbs(priv->hw, 169019d91873SJoao Pinto priv->plat->tx_queues_cfg[queue].send_slope, 169119d91873SJoao Pinto priv->plat->tx_queues_cfg[queue].idle_slope, 169219d91873SJoao Pinto priv->plat->tx_queues_cfg[queue].high_credit, 169319d91873SJoao Pinto priv->plat->tx_queues_cfg[queue].low_credit, 169419d91873SJoao Pinto queue); 169519d91873SJoao Pinto } 169619d91873SJoao Pinto } 169719d91873SJoao Pinto 169819d91873SJoao Pinto /** 1699d43042f4SJoao Pinto * stmmac_rx_queue_dma_chan_map - Map RX queue to RX dma channel 1700d43042f4SJoao Pinto * @priv: driver private structure 1701d43042f4SJoao Pinto * Description: It is used for mapping RX queues to RX dma channels 1702d43042f4SJoao Pinto */ 1703d43042f4SJoao Pinto static void stmmac_rx_queue_dma_chan_map(struct stmmac_priv *priv) 1704d43042f4SJoao Pinto { 1705d43042f4SJoao Pinto u32 rx_queues_count = priv->plat->rx_queues_to_use; 1706d43042f4SJoao Pinto u32 queue; 1707d43042f4SJoao Pinto u32 chan; 1708d43042f4SJoao Pinto 1709d43042f4SJoao Pinto for (queue = 0; queue < rx_queues_count; queue++) { 1710d43042f4SJoao Pinto chan = priv->plat->rx_queues_cfg[queue].chan; 1711d43042f4SJoao Pinto priv->hw->mac->map_mtl_to_dma(priv->hw, queue, chan); 1712d43042f4SJoao Pinto } 1713d43042f4SJoao Pinto } 1714d43042f4SJoao Pinto 1715d43042f4SJoao Pinto /** 1716d0a9c9f9SJoao Pinto * stmmac_mtl_configuration - Configure MTL 1717d0a9c9f9SJoao Pinto * @priv: driver private structure 1718d0a9c9f9SJoao Pinto * Description: It is used for configurring MTL 1719d0a9c9f9SJoao Pinto */ 1720d0a9c9f9SJoao Pinto static void stmmac_mtl_configuration(struct stmmac_priv *priv) 1721d0a9c9f9SJoao Pinto { 1722d0a9c9f9SJoao Pinto u32 rx_queues_count = priv->plat->rx_queues_to_use; 1723d0a9c9f9SJoao Pinto u32 tx_queues_count = priv->plat->tx_queues_to_use; 1724d0a9c9f9SJoao Pinto 17256a3a7193SJoao Pinto if (tx_queues_count > 1 && priv->hw->mac->set_mtl_tx_queue_weight) 17266a3a7193SJoao Pinto stmmac_set_tx_queue_weight(priv); 17276a3a7193SJoao Pinto 1728d0a9c9f9SJoao Pinto /* Configure MTL RX algorithms */ 1729d0a9c9f9SJoao Pinto if (rx_queues_count > 1 && priv->hw->mac->prog_mtl_rx_algorithms) 1730d0a9c9f9SJoao Pinto priv->hw->mac->prog_mtl_rx_algorithms(priv->hw, 1731d0a9c9f9SJoao Pinto priv->plat->rx_sched_algorithm); 1732d0a9c9f9SJoao Pinto 1733d0a9c9f9SJoao Pinto /* Configure MTL TX algorithms */ 1734d0a9c9f9SJoao Pinto if (tx_queues_count > 1 && priv->hw->mac->prog_mtl_tx_algorithms) 1735d0a9c9f9SJoao Pinto priv->hw->mac->prog_mtl_tx_algorithms(priv->hw, 1736d0a9c9f9SJoao Pinto priv->plat->tx_sched_algorithm); 1737d0a9c9f9SJoao Pinto 173819d91873SJoao Pinto /* Configure CBS in AVB TX queues */ 173919d91873SJoao Pinto if (tx_queues_count > 1 && priv->hw->mac->config_cbs) 174019d91873SJoao Pinto stmmac_configure_cbs(priv); 174119d91873SJoao Pinto 1742d43042f4SJoao Pinto /* Map RX MTL to DMA channels */ 1743d43042f4SJoao Pinto if (rx_queues_count > 1 && priv->hw->mac->map_mtl_to_dma) 1744d43042f4SJoao Pinto stmmac_rx_queue_dma_chan_map(priv); 1745d43042f4SJoao Pinto 1746d0a9c9f9SJoao Pinto /* Enable MAC RX Queues */ 1747d0a9c9f9SJoao Pinto if (rx_queues_count > 1 && priv->hw->mac->rx_queue_enable) 1748d0a9c9f9SJoao Pinto stmmac_mac_enable_rx_queues(priv); 1749d0a9c9f9SJoao Pinto } 1750d0a9c9f9SJoao Pinto 1751d0a9c9f9SJoao Pinto /** 1752732fdf0eSGiuseppe CAVALLARO * stmmac_hw_setup - setup mac in a usable state. 1753523f11b5SSrinivas Kandagatla * @dev : pointer to the device structure. 1754523f11b5SSrinivas Kandagatla * Description: 1755732fdf0eSGiuseppe CAVALLARO * this is the main function to setup the HW in a usable state because the 1756732fdf0eSGiuseppe CAVALLARO * dma engine is reset, the core registers are configured (e.g. AXI, 1757732fdf0eSGiuseppe CAVALLARO * Checksum features, timers). The DMA is ready to start receiving and 1758732fdf0eSGiuseppe CAVALLARO * transmitting. 1759523f11b5SSrinivas Kandagatla * Return value: 1760523f11b5SSrinivas Kandagatla * 0 on success and an appropriate (-)ve integer as defined in errno.h 1761523f11b5SSrinivas Kandagatla * file on failure. 1762523f11b5SSrinivas Kandagatla */ 1763fe131929SHuacai Chen static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) 1764523f11b5SSrinivas Kandagatla { 1765523f11b5SSrinivas Kandagatla struct stmmac_priv *priv = netdev_priv(dev); 1766523f11b5SSrinivas Kandagatla int ret; 1767523f11b5SSrinivas Kandagatla 1768523f11b5SSrinivas Kandagatla /* DMA initialization and SW reset */ 1769523f11b5SSrinivas Kandagatla ret = stmmac_init_dma_engine(priv); 1770523f11b5SSrinivas Kandagatla if (ret < 0) { 177138ddc59dSLABBE Corentin netdev_err(priv->dev, "%s: DMA engine initialization failed\n", 177238ddc59dSLABBE Corentin __func__); 1773523f11b5SSrinivas Kandagatla return ret; 1774523f11b5SSrinivas Kandagatla } 1775523f11b5SSrinivas Kandagatla 1776523f11b5SSrinivas Kandagatla /* Copy the MAC addr into the HW */ 17777ed24bbeSVince Bridgers priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0); 1778523f11b5SSrinivas Kandagatla 177902e57b9dSGiuseppe CAVALLARO /* PS and related bits will be programmed according to the speed */ 178002e57b9dSGiuseppe CAVALLARO if (priv->hw->pcs) { 178102e57b9dSGiuseppe CAVALLARO int speed = priv->plat->mac_port_sel_speed; 178202e57b9dSGiuseppe CAVALLARO 178302e57b9dSGiuseppe CAVALLARO if ((speed == SPEED_10) || (speed == SPEED_100) || 178402e57b9dSGiuseppe CAVALLARO (speed == SPEED_1000)) { 178502e57b9dSGiuseppe CAVALLARO priv->hw->ps = speed; 178602e57b9dSGiuseppe CAVALLARO } else { 178702e57b9dSGiuseppe CAVALLARO dev_warn(priv->device, "invalid port speed\n"); 178802e57b9dSGiuseppe CAVALLARO priv->hw->ps = 0; 178902e57b9dSGiuseppe CAVALLARO } 179002e57b9dSGiuseppe CAVALLARO } 179102e57b9dSGiuseppe CAVALLARO 1792523f11b5SSrinivas Kandagatla /* Initialize the MAC Core */ 17937ed24bbeSVince Bridgers priv->hw->mac->core_init(priv->hw, dev->mtu); 1794523f11b5SSrinivas Kandagatla 1795d0a9c9f9SJoao Pinto /* Initialize MTL*/ 1796d0a9c9f9SJoao Pinto if (priv->synopsys_id >= DWMAC_CORE_4_00) 1797d0a9c9f9SJoao Pinto stmmac_mtl_configuration(priv); 17989eb12474Sjpinto 1799978aded4SGiuseppe CAVALLARO ret = priv->hw->mac->rx_ipc(priv->hw); 1800978aded4SGiuseppe CAVALLARO if (!ret) { 180138ddc59dSLABBE Corentin netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n"); 1802978aded4SGiuseppe CAVALLARO priv->plat->rx_coe = STMMAC_RX_COE_NONE; 1803d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = 0; 1804978aded4SGiuseppe CAVALLARO } 1805978aded4SGiuseppe CAVALLARO 1806523f11b5SSrinivas Kandagatla /* Enable the MAC Rx/Tx */ 1807f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) 1808f748be53SAlexandre TORGUE stmmac_dwmac4_set_mac(priv->ioaddr, true); 1809f748be53SAlexandre TORGUE else 1810523f11b5SSrinivas Kandagatla stmmac_set_mac(priv->ioaddr, true); 1811523f11b5SSrinivas Kandagatla 1812523f11b5SSrinivas Kandagatla /* Set the HW DMA mode and the COE */ 1813523f11b5SSrinivas Kandagatla stmmac_dma_operation_mode(priv); 1814523f11b5SSrinivas Kandagatla 1815523f11b5SSrinivas Kandagatla stmmac_mmc_setup(priv); 1816523f11b5SSrinivas Kandagatla 1817fe131929SHuacai Chen if (init_ptp) { 18180ad2be79SThierry Reding ret = clk_prepare_enable(priv->plat->clk_ptp_ref); 18190ad2be79SThierry Reding if (ret < 0) 18200ad2be79SThierry Reding netdev_warn(priv->dev, "failed to enable PTP reference clock: %d\n", ret); 18210ad2be79SThierry Reding 1822523f11b5SSrinivas Kandagatla ret = stmmac_init_ptp(priv); 1823722eef28SHeiner Kallweit if (ret == -EOPNOTSUPP) 1824722eef28SHeiner Kallweit netdev_warn(priv->dev, "PTP not supported by HW\n"); 1825722eef28SHeiner Kallweit else if (ret) 1826722eef28SHeiner Kallweit netdev_warn(priv->dev, "PTP init failed\n"); 1827fe131929SHuacai Chen } 1828523f11b5SSrinivas Kandagatla 182950fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 1830523f11b5SSrinivas Kandagatla ret = stmmac_init_fs(dev); 1831523f11b5SSrinivas Kandagatla if (ret < 0) 183238ddc59dSLABBE Corentin netdev_warn(priv->dev, "%s: failed debugFS registration\n", 183338ddc59dSLABBE Corentin __func__); 1834523f11b5SSrinivas Kandagatla #endif 1835523f11b5SSrinivas Kandagatla /* Start the ball rolling... */ 183638ddc59dSLABBE Corentin netdev_dbg(priv->dev, "DMA RX/TX processes started...\n"); 1837523f11b5SSrinivas Kandagatla priv->hw->dma->start_tx(priv->ioaddr); 1838523f11b5SSrinivas Kandagatla priv->hw->dma->start_rx(priv->ioaddr); 1839523f11b5SSrinivas Kandagatla 1840523f11b5SSrinivas Kandagatla priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; 1841523f11b5SSrinivas Kandagatla 1842523f11b5SSrinivas Kandagatla if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { 1843523f11b5SSrinivas Kandagatla priv->rx_riwt = MAX_DMA_RIWT; 1844523f11b5SSrinivas Kandagatla priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); 1845523f11b5SSrinivas Kandagatla } 1846523f11b5SSrinivas Kandagatla 18473fe5cadbSGiuseppe CAVALLARO if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane) 184802e57b9dSGiuseppe CAVALLARO priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, priv->hw->ps, 0); 1849523f11b5SSrinivas Kandagatla 1850f748be53SAlexandre TORGUE /* set TX ring length */ 1851f748be53SAlexandre TORGUE if (priv->hw->dma->set_tx_ring_len) 1852f748be53SAlexandre TORGUE priv->hw->dma->set_tx_ring_len(priv->ioaddr, 1853f748be53SAlexandre TORGUE (DMA_TX_SIZE - 1)); 1854f748be53SAlexandre TORGUE /* set RX ring length */ 1855f748be53SAlexandre TORGUE if (priv->hw->dma->set_rx_ring_len) 1856f748be53SAlexandre TORGUE priv->hw->dma->set_rx_ring_len(priv->ioaddr, 1857f748be53SAlexandre TORGUE (DMA_RX_SIZE - 1)); 1858f748be53SAlexandre TORGUE /* Enable TSO */ 1859f748be53SAlexandre TORGUE if (priv->tso) 1860f748be53SAlexandre TORGUE priv->hw->dma->enable_tso(priv->ioaddr, 1, STMMAC_CHAN0); 1861f748be53SAlexandre TORGUE 1862523f11b5SSrinivas Kandagatla return 0; 1863523f11b5SSrinivas Kandagatla } 1864523f11b5SSrinivas Kandagatla 1865c66f6c37SThierry Reding static void stmmac_hw_teardown(struct net_device *dev) 1866c66f6c37SThierry Reding { 1867c66f6c37SThierry Reding struct stmmac_priv *priv = netdev_priv(dev); 1868c66f6c37SThierry Reding 1869c66f6c37SThierry Reding clk_disable_unprepare(priv->plat->clk_ptp_ref); 1870c66f6c37SThierry Reding } 1871c66f6c37SThierry Reding 1872523f11b5SSrinivas Kandagatla /** 18737ac6653aSJeff Kirsher * stmmac_open - open entry point of the driver 18747ac6653aSJeff Kirsher * @dev : pointer to the device structure. 18757ac6653aSJeff Kirsher * Description: 18767ac6653aSJeff Kirsher * This function is the open entry point of the driver. 18777ac6653aSJeff Kirsher * Return value: 18787ac6653aSJeff Kirsher * 0 on success and an appropriate (-)ve integer as defined in errno.h 18797ac6653aSJeff Kirsher * file on failure. 18807ac6653aSJeff Kirsher */ 18817ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev) 18827ac6653aSJeff Kirsher { 18837ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 18847ac6653aSJeff Kirsher int ret; 18857ac6653aSJeff Kirsher 18864bfcbd7aSFrancesco Virlinzi stmmac_check_ether_addr(priv); 18874bfcbd7aSFrancesco Virlinzi 18883fe5cadbSGiuseppe CAVALLARO if (priv->hw->pcs != STMMAC_PCS_RGMII && 18893fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_TBI && 18903fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_RTBI) { 18917ac6653aSJeff Kirsher ret = stmmac_init_phy(dev); 1892e58bb43fSGiuseppe CAVALLARO if (ret) { 189338ddc59dSLABBE Corentin netdev_err(priv->dev, 189438ddc59dSLABBE Corentin "%s: Cannot attach to PHY (error: %d)\n", 1895e58bb43fSGiuseppe CAVALLARO __func__, ret); 189689df20d9SHans de Goede return ret; 18977ac6653aSJeff Kirsher } 1898e58bb43fSGiuseppe CAVALLARO } 18997ac6653aSJeff Kirsher 1900523f11b5SSrinivas Kandagatla /* Extra statistics */ 1901523f11b5SSrinivas Kandagatla memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats)); 1902523f11b5SSrinivas Kandagatla priv->xstats.threshold = tc; 1903523f11b5SSrinivas Kandagatla 19047ac6653aSJeff Kirsher priv->dma_buf_sz = STMMAC_ALIGN(buf_sz); 190522ad3838SGiuseppe Cavallaro priv->rx_copybreak = STMMAC_RX_COPYBREAK; 190656329137SBartlomiej Zolnierkiewicz 19077262b7b2STobias Klauser ret = alloc_dma_desc_resources(priv); 190809f8d696SSrinivas Kandagatla if (ret < 0) { 190938ddc59dSLABBE Corentin netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n", 191038ddc59dSLABBE Corentin __func__); 191109f8d696SSrinivas Kandagatla goto dma_desc_error; 191209f8d696SSrinivas Kandagatla } 191309f8d696SSrinivas Kandagatla 1914777da230SGiuseppe CAVALLARO ret = init_dma_desc_rings(dev, GFP_KERNEL); 1915777da230SGiuseppe CAVALLARO if (ret < 0) { 191638ddc59dSLABBE Corentin netdev_err(priv->dev, "%s: DMA descriptors initialization failed\n", 191738ddc59dSLABBE Corentin __func__); 1918777da230SGiuseppe CAVALLARO goto init_error; 1919777da230SGiuseppe CAVALLARO } 1920777da230SGiuseppe CAVALLARO 1921fe131929SHuacai Chen ret = stmmac_hw_setup(dev, true); 192256329137SBartlomiej Zolnierkiewicz if (ret < 0) { 192338ddc59dSLABBE Corentin netdev_err(priv->dev, "%s: Hw setup failed\n", __func__); 1924c9324d18SGiuseppe CAVALLARO goto init_error; 19257ac6653aSJeff Kirsher } 19267ac6653aSJeff Kirsher 1927777da230SGiuseppe CAVALLARO stmmac_init_tx_coalesce(priv); 1928777da230SGiuseppe CAVALLARO 1929d6d50c7eSPhilippe Reynes if (dev->phydev) 1930d6d50c7eSPhilippe Reynes phy_start(dev->phydev); 19317ac6653aSJeff Kirsher 19327ac6653aSJeff Kirsher /* Request the IRQ lines */ 19337ac6653aSJeff Kirsher ret = request_irq(dev->irq, stmmac_interrupt, 19347ac6653aSJeff Kirsher IRQF_SHARED, dev->name, dev); 19357ac6653aSJeff Kirsher if (unlikely(ret < 0)) { 193638ddc59dSLABBE Corentin netdev_err(priv->dev, 193738ddc59dSLABBE Corentin "%s: ERROR: allocating the IRQ %d (error: %d)\n", 19387ac6653aSJeff Kirsher __func__, dev->irq, ret); 19396c1e5abeSThierry Reding goto irq_error; 19407ac6653aSJeff Kirsher } 19417ac6653aSJeff Kirsher 19427a13f8f5SFrancesco Virlinzi /* Request the Wake IRQ in case of another line is used for WoL */ 19437a13f8f5SFrancesco Virlinzi if (priv->wol_irq != dev->irq) { 19447a13f8f5SFrancesco Virlinzi ret = request_irq(priv->wol_irq, stmmac_interrupt, 19457a13f8f5SFrancesco Virlinzi IRQF_SHARED, dev->name, dev); 19467a13f8f5SFrancesco Virlinzi if (unlikely(ret < 0)) { 194738ddc59dSLABBE Corentin netdev_err(priv->dev, 194838ddc59dSLABBE Corentin "%s: ERROR: allocating the WoL IRQ %d (%d)\n", 1949ceb69499SGiuseppe CAVALLARO __func__, priv->wol_irq, ret); 1950c9324d18SGiuseppe CAVALLARO goto wolirq_error; 19517a13f8f5SFrancesco Virlinzi } 19527a13f8f5SFrancesco Virlinzi } 19537a13f8f5SFrancesco Virlinzi 1954d765955dSGiuseppe CAVALLARO /* Request the IRQ lines */ 1955d7ec8584SChen-Yu Tsai if (priv->lpi_irq > 0) { 1956d765955dSGiuseppe CAVALLARO ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED, 1957d765955dSGiuseppe CAVALLARO dev->name, dev); 1958d765955dSGiuseppe CAVALLARO if (unlikely(ret < 0)) { 195938ddc59dSLABBE Corentin netdev_err(priv->dev, 196038ddc59dSLABBE Corentin "%s: ERROR: allocating the LPI IRQ %d (%d)\n", 1961d765955dSGiuseppe CAVALLARO __func__, priv->lpi_irq, ret); 1962c9324d18SGiuseppe CAVALLARO goto lpiirq_error; 1963d765955dSGiuseppe CAVALLARO } 1964d765955dSGiuseppe CAVALLARO } 1965d765955dSGiuseppe CAVALLARO 19667ac6653aSJeff Kirsher napi_enable(&priv->napi); 19677ac6653aSJeff Kirsher netif_start_queue(dev); 19687ac6653aSJeff Kirsher 19697ac6653aSJeff Kirsher return 0; 19707ac6653aSJeff Kirsher 1971c9324d18SGiuseppe CAVALLARO lpiirq_error: 1972d765955dSGiuseppe CAVALLARO if (priv->wol_irq != dev->irq) 1973d765955dSGiuseppe CAVALLARO free_irq(priv->wol_irq, dev); 1974c9324d18SGiuseppe CAVALLARO wolirq_error: 19757a13f8f5SFrancesco Virlinzi free_irq(dev->irq, dev); 19766c1e5abeSThierry Reding irq_error: 19776c1e5abeSThierry Reding if (dev->phydev) 19786c1e5abeSThierry Reding phy_stop(dev->phydev); 19797a13f8f5SFrancesco Virlinzi 19806c1e5abeSThierry Reding del_timer_sync(&priv->txtimer); 1981c66f6c37SThierry Reding stmmac_hw_teardown(dev); 1982c9324d18SGiuseppe CAVALLARO init_error: 1983c9324d18SGiuseppe CAVALLARO free_dma_desc_resources(priv); 198456329137SBartlomiej Zolnierkiewicz dma_desc_error: 1985d6d50c7eSPhilippe Reynes if (dev->phydev) 1986d6d50c7eSPhilippe Reynes phy_disconnect(dev->phydev); 19874bfcbd7aSFrancesco Virlinzi 19887ac6653aSJeff Kirsher return ret; 19897ac6653aSJeff Kirsher } 19907ac6653aSJeff Kirsher 19917ac6653aSJeff Kirsher /** 19927ac6653aSJeff Kirsher * stmmac_release - close entry point of the driver 19937ac6653aSJeff Kirsher * @dev : device pointer. 19947ac6653aSJeff Kirsher * Description: 19957ac6653aSJeff Kirsher * This is the stop entry point of the driver. 19967ac6653aSJeff Kirsher */ 19977ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev) 19987ac6653aSJeff Kirsher { 19997ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 20007ac6653aSJeff Kirsher 2001d765955dSGiuseppe CAVALLARO if (priv->eee_enabled) 2002d765955dSGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 2003d765955dSGiuseppe CAVALLARO 20047ac6653aSJeff Kirsher /* Stop and disconnect the PHY */ 2005d6d50c7eSPhilippe Reynes if (dev->phydev) { 2006d6d50c7eSPhilippe Reynes phy_stop(dev->phydev); 2007d6d50c7eSPhilippe Reynes phy_disconnect(dev->phydev); 20087ac6653aSJeff Kirsher } 20097ac6653aSJeff Kirsher 20107ac6653aSJeff Kirsher netif_stop_queue(dev); 20117ac6653aSJeff Kirsher 20127ac6653aSJeff Kirsher napi_disable(&priv->napi); 20137ac6653aSJeff Kirsher 20149125cdd1SGiuseppe CAVALLARO del_timer_sync(&priv->txtimer); 20159125cdd1SGiuseppe CAVALLARO 20167ac6653aSJeff Kirsher /* Free the IRQ lines */ 20177ac6653aSJeff Kirsher free_irq(dev->irq, dev); 20187a13f8f5SFrancesco Virlinzi if (priv->wol_irq != dev->irq) 20197a13f8f5SFrancesco Virlinzi free_irq(priv->wol_irq, dev); 2020d7ec8584SChen-Yu Tsai if (priv->lpi_irq > 0) 2021d765955dSGiuseppe CAVALLARO free_irq(priv->lpi_irq, dev); 20227ac6653aSJeff Kirsher 20237ac6653aSJeff Kirsher /* Stop TX/RX DMA and clear the descriptors */ 20247ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 20257ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 20267ac6653aSJeff Kirsher 20277ac6653aSJeff Kirsher /* Release and free the Rx/Tx resources */ 20287ac6653aSJeff Kirsher free_dma_desc_resources(priv); 20297ac6653aSJeff Kirsher 20307ac6653aSJeff Kirsher /* Disable the MAC Rx/Tx */ 2031bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 20327ac6653aSJeff Kirsher 20337ac6653aSJeff Kirsher netif_carrier_off(dev); 20347ac6653aSJeff Kirsher 203550fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 2036466c5ac8SMathieu Olivari stmmac_exit_fs(dev); 2037bfab27a1SGiuseppe CAVALLARO #endif 2038bfab27a1SGiuseppe CAVALLARO 203992ba6888SRayagond Kokatanur stmmac_release_ptp(priv); 204092ba6888SRayagond Kokatanur 20417ac6653aSJeff Kirsher return 0; 20427ac6653aSJeff Kirsher } 20437ac6653aSJeff Kirsher 20447ac6653aSJeff Kirsher /** 2045f748be53SAlexandre TORGUE * stmmac_tso_allocator - close entry point of the driver 2046f748be53SAlexandre TORGUE * @priv: driver private structure 2047f748be53SAlexandre TORGUE * @des: buffer start address 2048f748be53SAlexandre TORGUE * @total_len: total length to fill in descriptors 2049f748be53SAlexandre TORGUE * @last_segmant: condition for the last descriptor 2050f748be53SAlexandre TORGUE * Description: 2051f748be53SAlexandre TORGUE * This function fills descriptor and request new descriptors according to 2052f748be53SAlexandre TORGUE * buffer length to fill 2053f748be53SAlexandre TORGUE */ 2054f748be53SAlexandre TORGUE static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des, 2055f748be53SAlexandre TORGUE int total_len, bool last_segment) 2056f748be53SAlexandre TORGUE { 2057f748be53SAlexandre TORGUE struct dma_desc *desc; 2058f748be53SAlexandre TORGUE int tmp_len; 2059f748be53SAlexandre TORGUE u32 buff_size; 2060f748be53SAlexandre TORGUE 2061f748be53SAlexandre TORGUE tmp_len = total_len; 2062f748be53SAlexandre TORGUE 2063f748be53SAlexandre TORGUE while (tmp_len > 0) { 2064f748be53SAlexandre TORGUE priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); 2065f748be53SAlexandre TORGUE desc = priv->dma_tx + priv->cur_tx; 2066f748be53SAlexandre TORGUE 2067f8be0d78SMichael Weiser desc->des0 = cpu_to_le32(des + (total_len - tmp_len)); 2068f748be53SAlexandre TORGUE buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ? 2069f748be53SAlexandre TORGUE TSO_MAX_BUFF_SIZE : tmp_len; 2070f748be53SAlexandre TORGUE 2071f748be53SAlexandre TORGUE priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size, 2072f748be53SAlexandre TORGUE 0, 1, 2073f748be53SAlexandre TORGUE (last_segment) && (buff_size < TSO_MAX_BUFF_SIZE), 2074f748be53SAlexandre TORGUE 0, 0); 2075f748be53SAlexandre TORGUE 2076f748be53SAlexandre TORGUE tmp_len -= TSO_MAX_BUFF_SIZE; 2077f748be53SAlexandre TORGUE } 2078f748be53SAlexandre TORGUE } 2079f748be53SAlexandre TORGUE 2080f748be53SAlexandre TORGUE /** 2081f748be53SAlexandre TORGUE * stmmac_tso_xmit - Tx entry point of the driver for oversized frames (TSO) 2082f748be53SAlexandre TORGUE * @skb : the socket buffer 2083f748be53SAlexandre TORGUE * @dev : device pointer 2084f748be53SAlexandre TORGUE * Description: this is the transmit function that is called on TSO frames 2085f748be53SAlexandre TORGUE * (support available on GMAC4 and newer chips). 2086f748be53SAlexandre TORGUE * Diagram below show the ring programming in case of TSO frames: 2087f748be53SAlexandre TORGUE * 2088f748be53SAlexandre TORGUE * First Descriptor 2089f748be53SAlexandre TORGUE * -------- 2090f748be53SAlexandre TORGUE * | DES0 |---> buffer1 = L2/L3/L4 header 2091f748be53SAlexandre TORGUE * | DES1 |---> TCP Payload (can continue on next descr...) 2092f748be53SAlexandre TORGUE * | DES2 |---> buffer 1 and 2 len 2093f748be53SAlexandre TORGUE * | DES3 |---> must set TSE, TCP hdr len-> [22:19]. TCP payload len [17:0] 2094f748be53SAlexandre TORGUE * -------- 2095f748be53SAlexandre TORGUE * | 2096f748be53SAlexandre TORGUE * ... 2097f748be53SAlexandre TORGUE * | 2098f748be53SAlexandre TORGUE * -------- 2099f748be53SAlexandre TORGUE * | DES0 | --| Split TCP Payload on Buffers 1 and 2 2100f748be53SAlexandre TORGUE * | DES1 | --| 2101f748be53SAlexandre TORGUE * | DES2 | --> buffer 1 and 2 len 2102f748be53SAlexandre TORGUE * | DES3 | 2103f748be53SAlexandre TORGUE * -------- 2104f748be53SAlexandre TORGUE * 2105f748be53SAlexandre TORGUE * mss is fixed when enable tso, so w/o programming the TDES3 ctx field. 2106f748be53SAlexandre TORGUE */ 2107f748be53SAlexandre TORGUE static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev) 2108f748be53SAlexandre TORGUE { 2109f748be53SAlexandre TORGUE u32 pay_len, mss; 2110f748be53SAlexandre TORGUE int tmp_pay_len = 0; 2111f748be53SAlexandre TORGUE struct stmmac_priv *priv = netdev_priv(dev); 2112f748be53SAlexandre TORGUE int nfrags = skb_shinfo(skb)->nr_frags; 2113f748be53SAlexandre TORGUE unsigned int first_entry, des; 2114f748be53SAlexandre TORGUE struct dma_desc *desc, *first, *mss_desc = NULL; 2115f748be53SAlexandre TORGUE u8 proto_hdr_len; 2116f748be53SAlexandre TORGUE int i; 2117f748be53SAlexandre TORGUE 2118f748be53SAlexandre TORGUE /* Compute header lengths */ 2119f748be53SAlexandre TORGUE proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); 2120f748be53SAlexandre TORGUE 2121f748be53SAlexandre TORGUE /* Desc availability based on threshold should be enough safe */ 2122f748be53SAlexandre TORGUE if (unlikely(stmmac_tx_avail(priv) < 2123f748be53SAlexandre TORGUE (((skb->len - proto_hdr_len) / TSO_MAX_BUFF_SIZE + 1)))) { 2124f748be53SAlexandre TORGUE if (!netif_queue_stopped(dev)) { 2125f748be53SAlexandre TORGUE netif_stop_queue(dev); 2126f748be53SAlexandre TORGUE /* This is a hard error, log it. */ 212738ddc59dSLABBE Corentin netdev_err(priv->dev, 212838ddc59dSLABBE Corentin "%s: Tx Ring full when queue awake\n", 212938ddc59dSLABBE Corentin __func__); 2130f748be53SAlexandre TORGUE } 2131f748be53SAlexandre TORGUE return NETDEV_TX_BUSY; 2132f748be53SAlexandre TORGUE } 2133f748be53SAlexandre TORGUE 2134f748be53SAlexandre TORGUE pay_len = skb_headlen(skb) - proto_hdr_len; /* no frags */ 2135f748be53SAlexandre TORGUE 2136f748be53SAlexandre TORGUE mss = skb_shinfo(skb)->gso_size; 2137f748be53SAlexandre TORGUE 2138f748be53SAlexandre TORGUE /* set new MSS value if needed */ 2139f748be53SAlexandre TORGUE if (mss != priv->mss) { 2140f748be53SAlexandre TORGUE mss_desc = priv->dma_tx + priv->cur_tx; 2141f748be53SAlexandre TORGUE priv->hw->desc->set_mss(mss_desc, mss); 2142f748be53SAlexandre TORGUE priv->mss = mss; 2143f748be53SAlexandre TORGUE priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); 2144f748be53SAlexandre TORGUE } 2145f748be53SAlexandre TORGUE 2146f748be53SAlexandre TORGUE if (netif_msg_tx_queued(priv)) { 2147f748be53SAlexandre TORGUE pr_info("%s: tcphdrlen %d, hdr_len %d, pay_len %d, mss %d\n", 2148f748be53SAlexandre TORGUE __func__, tcp_hdrlen(skb), proto_hdr_len, pay_len, mss); 2149f748be53SAlexandre TORGUE pr_info("\tskb->len %d, skb->data_len %d\n", skb->len, 2150f748be53SAlexandre TORGUE skb->data_len); 2151f748be53SAlexandre TORGUE } 2152f748be53SAlexandre TORGUE 2153f748be53SAlexandre TORGUE first_entry = priv->cur_tx; 2154f748be53SAlexandre TORGUE 2155f748be53SAlexandre TORGUE desc = priv->dma_tx + first_entry; 2156f748be53SAlexandre TORGUE first = desc; 2157f748be53SAlexandre TORGUE 2158f748be53SAlexandre TORGUE /* first descriptor: fill Headers on Buf1 */ 2159f748be53SAlexandre TORGUE des = dma_map_single(priv->device, skb->data, skb_headlen(skb), 2160f748be53SAlexandre TORGUE DMA_TO_DEVICE); 2161f748be53SAlexandre TORGUE if (dma_mapping_error(priv->device, des)) 2162f748be53SAlexandre TORGUE goto dma_map_err; 2163f748be53SAlexandre TORGUE 2164f748be53SAlexandre TORGUE priv->tx_skbuff_dma[first_entry].buf = des; 2165f748be53SAlexandre TORGUE priv->tx_skbuff_dma[first_entry].len = skb_headlen(skb); 2166f748be53SAlexandre TORGUE priv->tx_skbuff[first_entry] = skb; 2167f748be53SAlexandre TORGUE 2168f8be0d78SMichael Weiser first->des0 = cpu_to_le32(des); 2169f748be53SAlexandre TORGUE 2170f748be53SAlexandre TORGUE /* Fill start of payload in buff2 of first descriptor */ 2171f748be53SAlexandre TORGUE if (pay_len) 2172f8be0d78SMichael Weiser first->des1 = cpu_to_le32(des + proto_hdr_len); 2173f748be53SAlexandre TORGUE 2174f748be53SAlexandre TORGUE /* If needed take extra descriptors to fill the remaining payload */ 2175f748be53SAlexandre TORGUE tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE; 2176f748be53SAlexandre TORGUE 2177f748be53SAlexandre TORGUE stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0)); 2178f748be53SAlexandre TORGUE 2179f748be53SAlexandre TORGUE /* Prepare fragments */ 2180f748be53SAlexandre TORGUE for (i = 0; i < nfrags; i++) { 2181f748be53SAlexandre TORGUE const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 2182f748be53SAlexandre TORGUE 2183f748be53SAlexandre TORGUE des = skb_frag_dma_map(priv->device, frag, 0, 2184f748be53SAlexandre TORGUE skb_frag_size(frag), 2185f748be53SAlexandre TORGUE DMA_TO_DEVICE); 2186937071c1SThierry Reding if (dma_mapping_error(priv->device, des)) 2187937071c1SThierry Reding goto dma_map_err; 2188f748be53SAlexandre TORGUE 2189f748be53SAlexandre TORGUE stmmac_tso_allocator(priv, des, skb_frag_size(frag), 2190f748be53SAlexandre TORGUE (i == nfrags - 1)); 2191f748be53SAlexandre TORGUE 2192f748be53SAlexandre TORGUE priv->tx_skbuff_dma[priv->cur_tx].buf = des; 2193f748be53SAlexandre TORGUE priv->tx_skbuff_dma[priv->cur_tx].len = skb_frag_size(frag); 2194f748be53SAlexandre TORGUE priv->tx_skbuff[priv->cur_tx] = NULL; 2195f748be53SAlexandre TORGUE priv->tx_skbuff_dma[priv->cur_tx].map_as_page = true; 2196f748be53SAlexandre TORGUE } 2197f748be53SAlexandre TORGUE 2198f748be53SAlexandre TORGUE priv->tx_skbuff_dma[priv->cur_tx].last_segment = true; 2199f748be53SAlexandre TORGUE 2200f748be53SAlexandre TORGUE priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE); 2201f748be53SAlexandre TORGUE 2202f748be53SAlexandre TORGUE if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { 2203b3e51069SLABBE Corentin netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n", 220438ddc59dSLABBE Corentin __func__); 2205f748be53SAlexandre TORGUE netif_stop_queue(dev); 2206f748be53SAlexandre TORGUE } 2207f748be53SAlexandre TORGUE 2208f748be53SAlexandre TORGUE dev->stats.tx_bytes += skb->len; 2209f748be53SAlexandre TORGUE priv->xstats.tx_tso_frames++; 2210f748be53SAlexandre TORGUE priv->xstats.tx_tso_nfrags += nfrags; 2211f748be53SAlexandre TORGUE 2212f748be53SAlexandre TORGUE /* Manage tx mitigation */ 2213f748be53SAlexandre TORGUE priv->tx_count_frames += nfrags + 1; 2214f748be53SAlexandre TORGUE if (likely(priv->tx_coal_frames > priv->tx_count_frames)) { 2215f748be53SAlexandre TORGUE mod_timer(&priv->txtimer, 2216f748be53SAlexandre TORGUE STMMAC_COAL_TIMER(priv->tx_coal_timer)); 2217f748be53SAlexandre TORGUE } else { 2218f748be53SAlexandre TORGUE priv->tx_count_frames = 0; 2219f748be53SAlexandre TORGUE priv->hw->desc->set_tx_ic(desc); 2220f748be53SAlexandre TORGUE priv->xstats.tx_set_ic_bit++; 2221f748be53SAlexandre TORGUE } 2222f748be53SAlexandre TORGUE 2223f748be53SAlexandre TORGUE if (!priv->hwts_tx_en) 2224f748be53SAlexandre TORGUE skb_tx_timestamp(skb); 2225f748be53SAlexandre TORGUE 2226f748be53SAlexandre TORGUE if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && 2227f748be53SAlexandre TORGUE priv->hwts_tx_en)) { 2228f748be53SAlexandre TORGUE /* declare that device is doing timestamping */ 2229f748be53SAlexandre TORGUE skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 2230f748be53SAlexandre TORGUE priv->hw->desc->enable_tx_timestamp(first); 2231f748be53SAlexandre TORGUE } 2232f748be53SAlexandre TORGUE 2233f748be53SAlexandre TORGUE /* Complete the first descriptor before granting the DMA */ 2234f748be53SAlexandre TORGUE priv->hw->desc->prepare_tso_tx_desc(first, 1, 2235f748be53SAlexandre TORGUE proto_hdr_len, 2236f748be53SAlexandre TORGUE pay_len, 2237f748be53SAlexandre TORGUE 1, priv->tx_skbuff_dma[first_entry].last_segment, 2238f748be53SAlexandre TORGUE tcp_hdrlen(skb) / 4, (skb->len - proto_hdr_len)); 2239f748be53SAlexandre TORGUE 2240f748be53SAlexandre TORGUE /* If context desc is used to change MSS */ 2241f748be53SAlexandre TORGUE if (mss_desc) 2242f748be53SAlexandre TORGUE priv->hw->desc->set_tx_owner(mss_desc); 2243f748be53SAlexandre TORGUE 2244f748be53SAlexandre TORGUE /* The own bit must be the latest setting done when prepare the 2245f748be53SAlexandre TORGUE * descriptor and then barrier is needed to make sure that 2246f748be53SAlexandre TORGUE * all is coherent before granting the DMA engine. 2247f748be53SAlexandre TORGUE */ 2248ad688cdbSPavel Machek dma_wmb(); 2249f748be53SAlexandre TORGUE 2250f748be53SAlexandre TORGUE if (netif_msg_pktdata(priv)) { 2251f748be53SAlexandre TORGUE pr_info("%s: curr=%d dirty=%d f=%d, e=%d, f_p=%p, nfrags %d\n", 2252f748be53SAlexandre TORGUE __func__, priv->cur_tx, priv->dirty_tx, first_entry, 2253f748be53SAlexandre TORGUE priv->cur_tx, first, nfrags); 2254f748be53SAlexandre TORGUE 2255f748be53SAlexandre TORGUE priv->hw->desc->display_ring((void *)priv->dma_tx, DMA_TX_SIZE, 2256f748be53SAlexandre TORGUE 0); 2257f748be53SAlexandre TORGUE 2258f748be53SAlexandre TORGUE pr_info(">>> frame to be transmitted: "); 2259f748be53SAlexandre TORGUE print_pkt(skb->data, skb_headlen(skb)); 2260f748be53SAlexandre TORGUE } 2261f748be53SAlexandre TORGUE 2262f748be53SAlexandre TORGUE netdev_sent_queue(dev, skb->len); 2263f748be53SAlexandre TORGUE 2264f748be53SAlexandre TORGUE priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, 2265f748be53SAlexandre TORGUE STMMAC_CHAN0); 2266f748be53SAlexandre TORGUE 2267f748be53SAlexandre TORGUE return NETDEV_TX_OK; 2268f748be53SAlexandre TORGUE 2269f748be53SAlexandre TORGUE dma_map_err: 2270f748be53SAlexandre TORGUE dev_err(priv->device, "Tx dma map failed\n"); 2271f748be53SAlexandre TORGUE dev_kfree_skb(skb); 2272f748be53SAlexandre TORGUE priv->dev->stats.tx_dropped++; 2273f748be53SAlexandre TORGUE return NETDEV_TX_OK; 2274f748be53SAlexandre TORGUE } 2275f748be53SAlexandre TORGUE 2276f748be53SAlexandre TORGUE /** 2277732fdf0eSGiuseppe CAVALLARO * stmmac_xmit - Tx entry point of the driver 22787ac6653aSJeff Kirsher * @skb : the socket buffer 22797ac6653aSJeff Kirsher * @dev : device pointer 228032ceabcaSGiuseppe CAVALLARO * Description : this is the tx entry point of the driver. 228132ceabcaSGiuseppe CAVALLARO * It programs the chain or the ring and supports oversized frames 228232ceabcaSGiuseppe CAVALLARO * and SG feature. 22837ac6653aSJeff Kirsher */ 22847ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) 22857ac6653aSJeff Kirsher { 22867ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 22870e80bdc9SGiuseppe Cavallaro unsigned int nopaged_len = skb_headlen(skb); 22884a7d666aSGiuseppe CAVALLARO int i, csum_insertion = 0, is_jumbo = 0; 22897ac6653aSJeff Kirsher int nfrags = skb_shinfo(skb)->nr_frags; 22900e80bdc9SGiuseppe Cavallaro unsigned int entry, first_entry; 22917ac6653aSJeff Kirsher struct dma_desc *desc, *first; 22920e80bdc9SGiuseppe Cavallaro unsigned int enh_desc; 2293f748be53SAlexandre TORGUE unsigned int des; 2294f748be53SAlexandre TORGUE 2295f748be53SAlexandre TORGUE /* Manage oversized TCP frames for GMAC4 device */ 2296f748be53SAlexandre TORGUE if (skb_is_gso(skb) && priv->tso) { 2297f748be53SAlexandre TORGUE if (ip_hdr(skb)->protocol == IPPROTO_TCP) 2298f748be53SAlexandre TORGUE return stmmac_tso_xmit(skb, dev); 2299f748be53SAlexandre TORGUE } 23007ac6653aSJeff Kirsher 23017ac6653aSJeff Kirsher if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) { 23027ac6653aSJeff Kirsher if (!netif_queue_stopped(dev)) { 23037ac6653aSJeff Kirsher netif_stop_queue(dev); 23047ac6653aSJeff Kirsher /* This is a hard error, log it. */ 230538ddc59dSLABBE Corentin netdev_err(priv->dev, 230638ddc59dSLABBE Corentin "%s: Tx Ring full when queue awake\n", 230738ddc59dSLABBE Corentin __func__); 23087ac6653aSJeff Kirsher } 23097ac6653aSJeff Kirsher return NETDEV_TX_BUSY; 23107ac6653aSJeff Kirsher } 23117ac6653aSJeff Kirsher 2312d765955dSGiuseppe CAVALLARO if (priv->tx_path_in_lpi_mode) 2313d765955dSGiuseppe CAVALLARO stmmac_disable_eee_mode(priv); 2314d765955dSGiuseppe CAVALLARO 2315e3ad57c9SGiuseppe Cavallaro entry = priv->cur_tx; 23160e80bdc9SGiuseppe Cavallaro first_entry = entry; 23177ac6653aSJeff Kirsher 23187ac6653aSJeff Kirsher csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL); 23197ac6653aSJeff Kirsher 23200e80bdc9SGiuseppe Cavallaro if (likely(priv->extend_desc)) 2321c24602efSGiuseppe CAVALLARO desc = (struct dma_desc *)(priv->dma_etx + entry); 2322c24602efSGiuseppe CAVALLARO else 23237ac6653aSJeff Kirsher desc = priv->dma_tx + entry; 2324c24602efSGiuseppe CAVALLARO 23257ac6653aSJeff Kirsher first = desc; 23267ac6653aSJeff Kirsher 23270e80bdc9SGiuseppe Cavallaro priv->tx_skbuff[first_entry] = skb; 23280e80bdc9SGiuseppe Cavallaro 23290e80bdc9SGiuseppe Cavallaro enh_desc = priv->plat->enh_desc; 23304a7d666aSGiuseppe CAVALLARO /* To program the descriptors according to the size of the frame */ 233129896a67SGiuseppe CAVALLARO if (enh_desc) 233229896a67SGiuseppe CAVALLARO is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc); 233329896a67SGiuseppe CAVALLARO 2334f748be53SAlexandre TORGUE if (unlikely(is_jumbo) && likely(priv->synopsys_id < 2335f748be53SAlexandre TORGUE DWMAC_CORE_4_00)) { 233629896a67SGiuseppe CAVALLARO entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion); 2337362b37beSGiuseppe CAVALLARO if (unlikely(entry < 0)) 2338362b37beSGiuseppe CAVALLARO goto dma_map_err; 233929896a67SGiuseppe CAVALLARO } 23407ac6653aSJeff Kirsher 23417ac6653aSJeff Kirsher for (i = 0; i < nfrags; i++) { 23429e903e08SEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 23439e903e08SEric Dumazet int len = skb_frag_size(frag); 2344be434d50SGiuseppe Cavallaro bool last_segment = (i == (nfrags - 1)); 23457ac6653aSJeff Kirsher 2346e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); 2347e3ad57c9SGiuseppe Cavallaro 23480e80bdc9SGiuseppe Cavallaro if (likely(priv->extend_desc)) 2349c24602efSGiuseppe CAVALLARO desc = (struct dma_desc *)(priv->dma_etx + entry); 2350c24602efSGiuseppe CAVALLARO else 23517ac6653aSJeff Kirsher desc = priv->dma_tx + entry; 23527ac6653aSJeff Kirsher 2353f748be53SAlexandre TORGUE des = skb_frag_dma_map(priv->device, frag, 0, len, 2354f722380dSIan Campbell DMA_TO_DEVICE); 2355f748be53SAlexandre TORGUE if (dma_mapping_error(priv->device, des)) 2356362b37beSGiuseppe CAVALLARO goto dma_map_err; /* should reuse desc w/o issues */ 2357362b37beSGiuseppe CAVALLARO 23580e80bdc9SGiuseppe Cavallaro priv->tx_skbuff[entry] = NULL; 2359f748be53SAlexandre TORGUE 2360f8be0d78SMichael Weiser priv->tx_skbuff_dma[entry].buf = des; 2361f8be0d78SMichael Weiser if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) 2362f8be0d78SMichael Weiser desc->des0 = cpu_to_le32(des); 2363f8be0d78SMichael Weiser else 2364f8be0d78SMichael Weiser desc->des2 = cpu_to_le32(des); 2365f748be53SAlexandre TORGUE 2366362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].map_as_page = true; 2367553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].len = len; 23680e80bdc9SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].last_segment = last_segment; 23690e80bdc9SGiuseppe Cavallaro 23700e80bdc9SGiuseppe Cavallaro /* Prepare the descriptor and set the own bit too */ 23714a7d666aSGiuseppe CAVALLARO priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion, 2372be434d50SGiuseppe Cavallaro priv->mode, 1, last_segment); 23737ac6653aSJeff Kirsher } 23747ac6653aSJeff Kirsher 2375e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); 2376e3ad57c9SGiuseppe Cavallaro 2377e3ad57c9SGiuseppe Cavallaro priv->cur_tx = entry; 23787ac6653aSJeff Kirsher 23797ac6653aSJeff Kirsher if (netif_msg_pktdata(priv)) { 2380d0225e7dSAlexandre TORGUE void *tx_head; 2381d0225e7dSAlexandre TORGUE 238238ddc59dSLABBE Corentin netdev_dbg(priv->dev, 238338ddc59dSLABBE Corentin "%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d", 23840e80bdc9SGiuseppe Cavallaro __func__, priv->cur_tx, priv->dirty_tx, first_entry, 23850e80bdc9SGiuseppe Cavallaro entry, first, nfrags); 238683d7af64SGiuseppe CAVALLARO 2387c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2388d0225e7dSAlexandre TORGUE tx_head = (void *)priv->dma_etx; 2389c24602efSGiuseppe CAVALLARO else 2390d0225e7dSAlexandre TORGUE tx_head = (void *)priv->dma_tx; 2391d0225e7dSAlexandre TORGUE 2392d0225e7dSAlexandre TORGUE priv->hw->desc->display_ring(tx_head, DMA_TX_SIZE, false); 2393c24602efSGiuseppe CAVALLARO 239438ddc59dSLABBE Corentin netdev_dbg(priv->dev, ">>> frame to be transmitted: "); 23957ac6653aSJeff Kirsher print_pkt(skb->data, skb->len); 23967ac6653aSJeff Kirsher } 23970e80bdc9SGiuseppe Cavallaro 23987ac6653aSJeff Kirsher if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { 2399b3e51069SLABBE Corentin netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n", 2400b3e51069SLABBE Corentin __func__); 24017ac6653aSJeff Kirsher netif_stop_queue(dev); 24027ac6653aSJeff Kirsher } 24037ac6653aSJeff Kirsher 24047ac6653aSJeff Kirsher dev->stats.tx_bytes += skb->len; 24057ac6653aSJeff Kirsher 24060e80bdc9SGiuseppe Cavallaro /* According to the coalesce parameter the IC bit for the latest 24070e80bdc9SGiuseppe Cavallaro * segment is reset and the timer re-started to clean the tx status. 24080e80bdc9SGiuseppe Cavallaro * This approach takes care about the fragments: desc is the first 24090e80bdc9SGiuseppe Cavallaro * element in case of no SG. 24100e80bdc9SGiuseppe Cavallaro */ 24110e80bdc9SGiuseppe Cavallaro priv->tx_count_frames += nfrags + 1; 24120e80bdc9SGiuseppe Cavallaro if (likely(priv->tx_coal_frames > priv->tx_count_frames)) { 24130e80bdc9SGiuseppe Cavallaro mod_timer(&priv->txtimer, 24140e80bdc9SGiuseppe Cavallaro STMMAC_COAL_TIMER(priv->tx_coal_timer)); 24150e80bdc9SGiuseppe Cavallaro } else { 24160e80bdc9SGiuseppe Cavallaro priv->tx_count_frames = 0; 24170e80bdc9SGiuseppe Cavallaro priv->hw->desc->set_tx_ic(desc); 24180e80bdc9SGiuseppe Cavallaro priv->xstats.tx_set_ic_bit++; 24190e80bdc9SGiuseppe Cavallaro } 24200e80bdc9SGiuseppe Cavallaro 24210e80bdc9SGiuseppe Cavallaro if (!priv->hwts_tx_en) 24220e80bdc9SGiuseppe Cavallaro skb_tx_timestamp(skb); 24230e80bdc9SGiuseppe Cavallaro 24240e80bdc9SGiuseppe Cavallaro /* Ready to fill the first descriptor and set the OWN bit w/o any 24250e80bdc9SGiuseppe Cavallaro * problems because all the descriptors are actually ready to be 24260e80bdc9SGiuseppe Cavallaro * passed to the DMA engine. 24270e80bdc9SGiuseppe Cavallaro */ 24280e80bdc9SGiuseppe Cavallaro if (likely(!is_jumbo)) { 24290e80bdc9SGiuseppe Cavallaro bool last_segment = (nfrags == 0); 24300e80bdc9SGiuseppe Cavallaro 2431f748be53SAlexandre TORGUE des = dma_map_single(priv->device, skb->data, 24320e80bdc9SGiuseppe Cavallaro nopaged_len, DMA_TO_DEVICE); 2433f748be53SAlexandre TORGUE if (dma_mapping_error(priv->device, des)) 24340e80bdc9SGiuseppe Cavallaro goto dma_map_err; 24350e80bdc9SGiuseppe Cavallaro 2436f8be0d78SMichael Weiser priv->tx_skbuff_dma[first_entry].buf = des; 2437f8be0d78SMichael Weiser if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) 2438f8be0d78SMichael Weiser first->des0 = cpu_to_le32(des); 2439f8be0d78SMichael Weiser else 2440f8be0d78SMichael Weiser first->des2 = cpu_to_le32(des); 2441f748be53SAlexandre TORGUE 24420e80bdc9SGiuseppe Cavallaro priv->tx_skbuff_dma[first_entry].len = nopaged_len; 24430e80bdc9SGiuseppe Cavallaro priv->tx_skbuff_dma[first_entry].last_segment = last_segment; 24440e80bdc9SGiuseppe Cavallaro 2445891434b1SRayagond Kokatanur if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && 2446891434b1SRayagond Kokatanur priv->hwts_tx_en)) { 2447891434b1SRayagond Kokatanur /* declare that device is doing timestamping */ 2448891434b1SRayagond Kokatanur skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 2449891434b1SRayagond Kokatanur priv->hw->desc->enable_tx_timestamp(first); 2450891434b1SRayagond Kokatanur } 2451891434b1SRayagond Kokatanur 24520e80bdc9SGiuseppe Cavallaro /* Prepare the first descriptor setting the OWN bit too */ 24530e80bdc9SGiuseppe Cavallaro priv->hw->desc->prepare_tx_desc(first, 1, nopaged_len, 24540e80bdc9SGiuseppe Cavallaro csum_insertion, priv->mode, 1, 24550e80bdc9SGiuseppe Cavallaro last_segment); 24560e80bdc9SGiuseppe Cavallaro 24570e80bdc9SGiuseppe Cavallaro /* The own bit must be the latest setting done when prepare the 24580e80bdc9SGiuseppe Cavallaro * descriptor and then barrier is needed to make sure that 24590e80bdc9SGiuseppe Cavallaro * all is coherent before granting the DMA engine. 24600e80bdc9SGiuseppe Cavallaro */ 2461ad688cdbSPavel Machek dma_wmb(); 24620e80bdc9SGiuseppe Cavallaro } 24637ac6653aSJeff Kirsher 246438979574SBeniamino Galvani netdev_sent_queue(dev, skb->len); 2465f748be53SAlexandre TORGUE 2466f748be53SAlexandre TORGUE if (priv->synopsys_id < DWMAC_CORE_4_00) 24677ac6653aSJeff Kirsher priv->hw->dma->enable_dma_transmission(priv->ioaddr); 2468f748be53SAlexandre TORGUE else 2469f748be53SAlexandre TORGUE priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr, 2470f748be53SAlexandre TORGUE STMMAC_CHAN0); 24717ac6653aSJeff Kirsher 2472362b37beSGiuseppe CAVALLARO return NETDEV_TX_OK; 2473a9097a96SGiuseppe CAVALLARO 2474362b37beSGiuseppe CAVALLARO dma_map_err: 247538ddc59dSLABBE Corentin netdev_err(priv->dev, "Tx DMA map failed\n"); 2476362b37beSGiuseppe CAVALLARO dev_kfree_skb(skb); 2477362b37beSGiuseppe CAVALLARO priv->dev->stats.tx_dropped++; 24787ac6653aSJeff Kirsher return NETDEV_TX_OK; 24797ac6653aSJeff Kirsher } 24807ac6653aSJeff Kirsher 2481b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb) 2482b9381985SVince Bridgers { 2483b9381985SVince Bridgers struct ethhdr *ehdr; 2484b9381985SVince Bridgers u16 vlanid; 2485b9381985SVince Bridgers 2486b9381985SVince Bridgers if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) == 2487b9381985SVince Bridgers NETIF_F_HW_VLAN_CTAG_RX && 2488b9381985SVince Bridgers !__vlan_get_tag(skb, &vlanid)) { 2489b9381985SVince Bridgers /* pop the vlan tag */ 2490b9381985SVince Bridgers ehdr = (struct ethhdr *)skb->data; 2491b9381985SVince Bridgers memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2); 2492b9381985SVince Bridgers skb_pull(skb, VLAN_HLEN); 2493b9381985SVince Bridgers __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid); 2494b9381985SVince Bridgers } 2495b9381985SVince Bridgers } 2496b9381985SVince Bridgers 2497b9381985SVince Bridgers 2498120e87f9SGiuseppe Cavallaro static inline int stmmac_rx_threshold_count(struct stmmac_priv *priv) 2499120e87f9SGiuseppe Cavallaro { 2500120e87f9SGiuseppe Cavallaro if (priv->rx_zeroc_thresh < STMMAC_RX_THRESH) 2501120e87f9SGiuseppe Cavallaro return 0; 2502120e87f9SGiuseppe Cavallaro 2503120e87f9SGiuseppe Cavallaro return 1; 2504120e87f9SGiuseppe Cavallaro } 2505120e87f9SGiuseppe Cavallaro 250632ceabcaSGiuseppe CAVALLARO /** 2507732fdf0eSGiuseppe CAVALLARO * stmmac_rx_refill - refill used skb preallocated buffers 250832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 250932ceabcaSGiuseppe CAVALLARO * Description : this is to reallocate the skb for the reception process 251032ceabcaSGiuseppe CAVALLARO * that is based on zero-copy. 251132ceabcaSGiuseppe CAVALLARO */ 25127ac6653aSJeff Kirsher static inline void stmmac_rx_refill(struct stmmac_priv *priv) 25137ac6653aSJeff Kirsher { 25147ac6653aSJeff Kirsher int bfsize = priv->dma_buf_sz; 2515e3ad57c9SGiuseppe Cavallaro unsigned int entry = priv->dirty_rx; 2516e3ad57c9SGiuseppe Cavallaro int dirty = stmmac_rx_dirty(priv); 25177ac6653aSJeff Kirsher 2518e3ad57c9SGiuseppe Cavallaro while (dirty-- > 0) { 2519c24602efSGiuseppe CAVALLARO struct dma_desc *p; 2520c24602efSGiuseppe CAVALLARO 2521c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2522c24602efSGiuseppe CAVALLARO p = (struct dma_desc *)(priv->dma_erx + entry); 2523c24602efSGiuseppe CAVALLARO else 2524c24602efSGiuseppe CAVALLARO p = priv->dma_rx + entry; 2525c24602efSGiuseppe CAVALLARO 25267ac6653aSJeff Kirsher if (likely(priv->rx_skbuff[entry] == NULL)) { 25277ac6653aSJeff Kirsher struct sk_buff *skb; 25287ac6653aSJeff Kirsher 2529acb600deSEric Dumazet skb = netdev_alloc_skb_ip_align(priv->dev, bfsize); 2530120e87f9SGiuseppe Cavallaro if (unlikely(!skb)) { 2531120e87f9SGiuseppe Cavallaro /* so for a while no zero-copy! */ 2532120e87f9SGiuseppe Cavallaro priv->rx_zeroc_thresh = STMMAC_RX_THRESH; 2533120e87f9SGiuseppe Cavallaro if (unlikely(net_ratelimit())) 2534120e87f9SGiuseppe Cavallaro dev_err(priv->device, 2535120e87f9SGiuseppe Cavallaro "fail to alloc skb entry %d\n", 2536120e87f9SGiuseppe Cavallaro entry); 25377ac6653aSJeff Kirsher break; 2538120e87f9SGiuseppe Cavallaro } 25397ac6653aSJeff Kirsher 25407ac6653aSJeff Kirsher priv->rx_skbuff[entry] = skb; 25417ac6653aSJeff Kirsher priv->rx_skbuff_dma[entry] = 25427ac6653aSJeff Kirsher dma_map_single(priv->device, skb->data, bfsize, 25437ac6653aSJeff Kirsher DMA_FROM_DEVICE); 2544362b37beSGiuseppe CAVALLARO if (dma_mapping_error(priv->device, 2545362b37beSGiuseppe CAVALLARO priv->rx_skbuff_dma[entry])) { 254638ddc59dSLABBE Corentin netdev_err(priv->dev, "Rx DMA map failed\n"); 2547362b37beSGiuseppe CAVALLARO dev_kfree_skb(skb); 2548362b37beSGiuseppe CAVALLARO break; 2549362b37beSGiuseppe CAVALLARO } 2550286a8372SGiuseppe CAVALLARO 2551f748be53SAlexandre TORGUE if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) { 2552f8be0d78SMichael Weiser p->des0 = cpu_to_le32(priv->rx_skbuff_dma[entry]); 2553f748be53SAlexandre TORGUE p->des1 = 0; 2554f748be53SAlexandre TORGUE } else { 2555f8be0d78SMichael Weiser p->des2 = cpu_to_le32(priv->rx_skbuff_dma[entry]); 2556f748be53SAlexandre TORGUE } 2557f748be53SAlexandre TORGUE if (priv->hw->mode->refill_desc3) 255829896a67SGiuseppe CAVALLARO priv->hw->mode->refill_desc3(priv, p); 2559286a8372SGiuseppe CAVALLARO 2560120e87f9SGiuseppe Cavallaro if (priv->rx_zeroc_thresh > 0) 2561120e87f9SGiuseppe Cavallaro priv->rx_zeroc_thresh--; 2562120e87f9SGiuseppe Cavallaro 2563b3e51069SLABBE Corentin netif_dbg(priv, rx_status, priv->dev, 256438ddc59dSLABBE Corentin "refill entry #%d\n", entry); 25657ac6653aSJeff Kirsher } 2566ad688cdbSPavel Machek dma_wmb(); 2567f748be53SAlexandre TORGUE 2568f748be53SAlexandre TORGUE if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) 2569f748be53SAlexandre TORGUE priv->hw->desc->init_rx_desc(p, priv->use_riwt, 0, 0); 2570f748be53SAlexandre TORGUE else 2571c24602efSGiuseppe CAVALLARO priv->hw->desc->set_rx_owner(p); 2572f748be53SAlexandre TORGUE 2573ad688cdbSPavel Machek dma_wmb(); 2574e3ad57c9SGiuseppe Cavallaro 2575e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE); 25767ac6653aSJeff Kirsher } 2577e3ad57c9SGiuseppe Cavallaro priv->dirty_rx = entry; 25787ac6653aSJeff Kirsher } 25797ac6653aSJeff Kirsher 258032ceabcaSGiuseppe CAVALLARO /** 2581732fdf0eSGiuseppe CAVALLARO * stmmac_rx - manage the receive process 258232ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 258332ceabcaSGiuseppe CAVALLARO * @limit: napi bugget. 258432ceabcaSGiuseppe CAVALLARO * Description : this the function called by the napi poll method. 258532ceabcaSGiuseppe CAVALLARO * It gets all the frames inside the ring. 258632ceabcaSGiuseppe CAVALLARO */ 25877ac6653aSJeff Kirsher static int stmmac_rx(struct stmmac_priv *priv, int limit) 25887ac6653aSJeff Kirsher { 2589e3ad57c9SGiuseppe Cavallaro unsigned int entry = priv->cur_rx; 25907ac6653aSJeff Kirsher unsigned int next_entry; 25917ac6653aSJeff Kirsher unsigned int count = 0; 2592d2afb5bdSGiuseppe CAVALLARO int coe = priv->hw->rx_csum; 25937ac6653aSJeff Kirsher 259483d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) { 2595d0225e7dSAlexandre TORGUE void *rx_head; 2596d0225e7dSAlexandre TORGUE 259738ddc59dSLABBE Corentin netdev_dbg(priv->dev, "%s: descriptor ring:\n", __func__); 2598c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2599d0225e7dSAlexandre TORGUE rx_head = (void *)priv->dma_erx; 2600c24602efSGiuseppe CAVALLARO else 2601d0225e7dSAlexandre TORGUE rx_head = (void *)priv->dma_rx; 2602d0225e7dSAlexandre TORGUE 2603d0225e7dSAlexandre TORGUE priv->hw->desc->display_ring(rx_head, DMA_RX_SIZE, true); 26047ac6653aSJeff Kirsher } 2605c24602efSGiuseppe CAVALLARO while (count < limit) { 26067ac6653aSJeff Kirsher int status; 26079401bb5cSGiuseppe CAVALLARO struct dma_desc *p; 2608ba1ffd74SGiuseppe CAVALLARO struct dma_desc *np; 26097ac6653aSJeff Kirsher 2610c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2611c24602efSGiuseppe CAVALLARO p = (struct dma_desc *)(priv->dma_erx + entry); 2612c24602efSGiuseppe CAVALLARO else 2613c24602efSGiuseppe CAVALLARO p = priv->dma_rx + entry; 2614c24602efSGiuseppe CAVALLARO 2615c1fa3212SFabrice Gasnier /* read the status of the incoming frame */ 2616c1fa3212SFabrice Gasnier status = priv->hw->desc->rx_status(&priv->dev->stats, 2617c1fa3212SFabrice Gasnier &priv->xstats, p); 2618c1fa3212SFabrice Gasnier /* check if managed by the DMA otherwise go ahead */ 2619c1fa3212SFabrice Gasnier if (unlikely(status & dma_own)) 26207ac6653aSJeff Kirsher break; 26217ac6653aSJeff Kirsher 26227ac6653aSJeff Kirsher count++; 26237ac6653aSJeff Kirsher 2624e3ad57c9SGiuseppe Cavallaro priv->cur_rx = STMMAC_GET_ENTRY(priv->cur_rx, DMA_RX_SIZE); 2625e3ad57c9SGiuseppe Cavallaro next_entry = priv->cur_rx; 2626e3ad57c9SGiuseppe Cavallaro 2627c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2628ba1ffd74SGiuseppe CAVALLARO np = (struct dma_desc *)(priv->dma_erx + next_entry); 2629c24602efSGiuseppe CAVALLARO else 2630ba1ffd74SGiuseppe CAVALLARO np = priv->dma_rx + next_entry; 2631ba1ffd74SGiuseppe CAVALLARO 2632ba1ffd74SGiuseppe CAVALLARO prefetch(np); 26337ac6653aSJeff Kirsher 2634c24602efSGiuseppe CAVALLARO if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status)) 2635c24602efSGiuseppe CAVALLARO priv->hw->desc->rx_extended_status(&priv->dev->stats, 2636c24602efSGiuseppe CAVALLARO &priv->xstats, 2637c24602efSGiuseppe CAVALLARO priv->dma_erx + 2638c24602efSGiuseppe CAVALLARO entry); 2639891434b1SRayagond Kokatanur if (unlikely(status == discard_frame)) { 26407ac6653aSJeff Kirsher priv->dev->stats.rx_errors++; 2641891434b1SRayagond Kokatanur if (priv->hwts_rx_en && !priv->extend_desc) { 26428d45e42bSLABBE Corentin /* DESC2 & DESC3 will be overwritten by device 2643891434b1SRayagond Kokatanur * with timestamp value, hence reinitialize 2644891434b1SRayagond Kokatanur * them in stmmac_rx_refill() function so that 2645891434b1SRayagond Kokatanur * device can reuse it. 2646891434b1SRayagond Kokatanur */ 2647891434b1SRayagond Kokatanur priv->rx_skbuff[entry] = NULL; 2648891434b1SRayagond Kokatanur dma_unmap_single(priv->device, 2649891434b1SRayagond Kokatanur priv->rx_skbuff_dma[entry], 2650ceb69499SGiuseppe CAVALLARO priv->dma_buf_sz, 2651ceb69499SGiuseppe CAVALLARO DMA_FROM_DEVICE); 2652891434b1SRayagond Kokatanur } 2653891434b1SRayagond Kokatanur } else { 26547ac6653aSJeff Kirsher struct sk_buff *skb; 26557ac6653aSJeff Kirsher int frame_len; 2656f748be53SAlexandre TORGUE unsigned int des; 2657f748be53SAlexandre TORGUE 2658f748be53SAlexandre TORGUE if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) 2659f8be0d78SMichael Weiser des = le32_to_cpu(p->des0); 2660f748be53SAlexandre TORGUE else 2661f8be0d78SMichael Weiser des = le32_to_cpu(p->des2); 26627ac6653aSJeff Kirsher 2663ceb69499SGiuseppe CAVALLARO frame_len = priv->hw->desc->get_rx_frame_len(p, coe); 2664ceb69499SGiuseppe CAVALLARO 26658d45e42bSLABBE Corentin /* If frame length is greater than skb buffer size 2666f748be53SAlexandre TORGUE * (preallocated during init) then the packet is 2667f748be53SAlexandre TORGUE * ignored 2668f748be53SAlexandre TORGUE */ 2669e527c4a7SGiuseppe CAVALLARO if (frame_len > priv->dma_buf_sz) { 267038ddc59dSLABBE Corentin netdev_err(priv->dev, 267138ddc59dSLABBE Corentin "len %d larger than size (%d)\n", 267238ddc59dSLABBE Corentin frame_len, priv->dma_buf_sz); 2673e527c4a7SGiuseppe CAVALLARO priv->dev->stats.rx_length_errors++; 2674e527c4a7SGiuseppe CAVALLARO break; 2675e527c4a7SGiuseppe CAVALLARO } 2676e527c4a7SGiuseppe CAVALLARO 26777ac6653aSJeff Kirsher /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 2678ceb69499SGiuseppe CAVALLARO * Type frames (LLC/LLC-SNAP) 2679ceb69499SGiuseppe CAVALLARO */ 26807ac6653aSJeff Kirsher if (unlikely(status != llc_snap)) 26817ac6653aSJeff Kirsher frame_len -= ETH_FCS_LEN; 26827ac6653aSJeff Kirsher 268383d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) { 268438ddc59dSLABBE Corentin netdev_dbg(priv->dev, "\tdesc: %p [entry %d] buff=0x%x\n", 2685f748be53SAlexandre TORGUE p, entry, des); 268683d7af64SGiuseppe CAVALLARO if (frame_len > ETH_FRAME_LEN) 268738ddc59dSLABBE Corentin netdev_dbg(priv->dev, "frame size %d, COE: %d\n", 268883d7af64SGiuseppe CAVALLARO frame_len, status); 268983d7af64SGiuseppe CAVALLARO } 269022ad3838SGiuseppe Cavallaro 2691f748be53SAlexandre TORGUE /* The zero-copy is always used for all the sizes 2692f748be53SAlexandre TORGUE * in case of GMAC4 because it needs 2693f748be53SAlexandre TORGUE * to refill the used descriptors, always. 2694f748be53SAlexandre TORGUE */ 2695f748be53SAlexandre TORGUE if (unlikely(!priv->plat->has_gmac4 && 2696f748be53SAlexandre TORGUE ((frame_len < priv->rx_copybreak) || 2697f748be53SAlexandre TORGUE stmmac_rx_threshold_count(priv)))) { 269822ad3838SGiuseppe Cavallaro skb = netdev_alloc_skb_ip_align(priv->dev, 269922ad3838SGiuseppe Cavallaro frame_len); 270022ad3838SGiuseppe Cavallaro if (unlikely(!skb)) { 270122ad3838SGiuseppe Cavallaro if (net_ratelimit()) 270222ad3838SGiuseppe Cavallaro dev_warn(priv->device, 270322ad3838SGiuseppe Cavallaro "packet dropped\n"); 270422ad3838SGiuseppe Cavallaro priv->dev->stats.rx_dropped++; 270522ad3838SGiuseppe Cavallaro break; 270622ad3838SGiuseppe Cavallaro } 270722ad3838SGiuseppe Cavallaro 270822ad3838SGiuseppe Cavallaro dma_sync_single_for_cpu(priv->device, 270922ad3838SGiuseppe Cavallaro priv->rx_skbuff_dma 271022ad3838SGiuseppe Cavallaro [entry], frame_len, 271122ad3838SGiuseppe Cavallaro DMA_FROM_DEVICE); 271222ad3838SGiuseppe Cavallaro skb_copy_to_linear_data(skb, 271322ad3838SGiuseppe Cavallaro priv-> 271422ad3838SGiuseppe Cavallaro rx_skbuff[entry]->data, 271522ad3838SGiuseppe Cavallaro frame_len); 271622ad3838SGiuseppe Cavallaro 271722ad3838SGiuseppe Cavallaro skb_put(skb, frame_len); 271822ad3838SGiuseppe Cavallaro dma_sync_single_for_device(priv->device, 271922ad3838SGiuseppe Cavallaro priv->rx_skbuff_dma 272022ad3838SGiuseppe Cavallaro [entry], frame_len, 272122ad3838SGiuseppe Cavallaro DMA_FROM_DEVICE); 272222ad3838SGiuseppe Cavallaro } else { 27237ac6653aSJeff Kirsher skb = priv->rx_skbuff[entry]; 27247ac6653aSJeff Kirsher if (unlikely(!skb)) { 272538ddc59dSLABBE Corentin netdev_err(priv->dev, 272638ddc59dSLABBE Corentin "%s: Inconsistent Rx chain\n", 27277ac6653aSJeff Kirsher priv->dev->name); 27287ac6653aSJeff Kirsher priv->dev->stats.rx_dropped++; 27297ac6653aSJeff Kirsher break; 27307ac6653aSJeff Kirsher } 27317ac6653aSJeff Kirsher prefetch(skb->data - NET_IP_ALIGN); 27327ac6653aSJeff Kirsher priv->rx_skbuff[entry] = NULL; 2733120e87f9SGiuseppe Cavallaro priv->rx_zeroc_thresh++; 27347ac6653aSJeff Kirsher 27357ac6653aSJeff Kirsher skb_put(skb, frame_len); 27367ac6653aSJeff Kirsher dma_unmap_single(priv->device, 27377ac6653aSJeff Kirsher priv->rx_skbuff_dma[entry], 273822ad3838SGiuseppe Cavallaro priv->dma_buf_sz, 273922ad3838SGiuseppe Cavallaro DMA_FROM_DEVICE); 274022ad3838SGiuseppe Cavallaro } 274122ad3838SGiuseppe Cavallaro 27427ac6653aSJeff Kirsher if (netif_msg_pktdata(priv)) { 274338ddc59dSLABBE Corentin netdev_dbg(priv->dev, "frame received (%dbytes)", 274438ddc59dSLABBE Corentin frame_len); 27457ac6653aSJeff Kirsher print_pkt(skb->data, frame_len); 27467ac6653aSJeff Kirsher } 274783d7af64SGiuseppe CAVALLARO 2748ba1ffd74SGiuseppe CAVALLARO stmmac_get_rx_hwtstamp(priv, p, np, skb); 2749ba1ffd74SGiuseppe CAVALLARO 2750b9381985SVince Bridgers stmmac_rx_vlan(priv->dev, skb); 2751b9381985SVince Bridgers 27527ac6653aSJeff Kirsher skb->protocol = eth_type_trans(skb, priv->dev); 27537ac6653aSJeff Kirsher 2754ceb69499SGiuseppe CAVALLARO if (unlikely(!coe)) 27557ac6653aSJeff Kirsher skb_checksum_none_assert(skb); 275662a2ab93SGiuseppe CAVALLARO else 27577ac6653aSJeff Kirsher skb->ip_summed = CHECKSUM_UNNECESSARY; 275862a2ab93SGiuseppe CAVALLARO 27597ac6653aSJeff Kirsher napi_gro_receive(&priv->napi, skb); 27607ac6653aSJeff Kirsher 27617ac6653aSJeff Kirsher priv->dev->stats.rx_packets++; 27627ac6653aSJeff Kirsher priv->dev->stats.rx_bytes += frame_len; 27637ac6653aSJeff Kirsher } 27647ac6653aSJeff Kirsher entry = next_entry; 27657ac6653aSJeff Kirsher } 27667ac6653aSJeff Kirsher 27677ac6653aSJeff Kirsher stmmac_rx_refill(priv); 27687ac6653aSJeff Kirsher 27697ac6653aSJeff Kirsher priv->xstats.rx_pkt_n += count; 27707ac6653aSJeff Kirsher 27717ac6653aSJeff Kirsher return count; 27727ac6653aSJeff Kirsher } 27737ac6653aSJeff Kirsher 27747ac6653aSJeff Kirsher /** 27757ac6653aSJeff Kirsher * stmmac_poll - stmmac poll method (NAPI) 27767ac6653aSJeff Kirsher * @napi : pointer to the napi structure. 27777ac6653aSJeff Kirsher * @budget : maximum number of packets that the current CPU can receive from 27787ac6653aSJeff Kirsher * all interfaces. 27797ac6653aSJeff Kirsher * Description : 27809125cdd1SGiuseppe CAVALLARO * To look at the incoming frames and clear the tx resources. 27817ac6653aSJeff Kirsher */ 27827ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget) 27837ac6653aSJeff Kirsher { 27847ac6653aSJeff Kirsher struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi); 27857ac6653aSJeff Kirsher int work_done = 0; 27867ac6653aSJeff Kirsher 27879125cdd1SGiuseppe CAVALLARO priv->xstats.napi_poll++; 27889125cdd1SGiuseppe CAVALLARO stmmac_tx_clean(priv); 27897ac6653aSJeff Kirsher 27909125cdd1SGiuseppe CAVALLARO work_done = stmmac_rx(priv, budget); 27917ac6653aSJeff Kirsher if (work_done < budget) { 27926ad20165SEric Dumazet napi_complete_done(napi, work_done); 27939125cdd1SGiuseppe CAVALLARO stmmac_enable_dma_irq(priv); 27947ac6653aSJeff Kirsher } 27957ac6653aSJeff Kirsher return work_done; 27967ac6653aSJeff Kirsher } 27977ac6653aSJeff Kirsher 27987ac6653aSJeff Kirsher /** 27997ac6653aSJeff Kirsher * stmmac_tx_timeout 28007ac6653aSJeff Kirsher * @dev : Pointer to net device structure 28017ac6653aSJeff Kirsher * Description: this function is called when a packet transmission fails to 28027284a3f1SGiuseppe CAVALLARO * complete within a reasonable time. The driver will mark the error in the 28037ac6653aSJeff Kirsher * netdev structure and arrange for the device to be reset to a sane state 28047ac6653aSJeff Kirsher * in order to transmit a new packet. 28057ac6653aSJeff Kirsher */ 28067ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev) 28077ac6653aSJeff Kirsher { 28087ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 28097ac6653aSJeff Kirsher 28107ac6653aSJeff Kirsher /* Clear Tx resources and restart transmitting again */ 28117ac6653aSJeff Kirsher stmmac_tx_err(priv); 28127ac6653aSJeff Kirsher } 28137ac6653aSJeff Kirsher 28147ac6653aSJeff Kirsher /** 281501789349SJiri Pirko * stmmac_set_rx_mode - entry point for multicast addressing 28167ac6653aSJeff Kirsher * @dev : pointer to the device structure 28177ac6653aSJeff Kirsher * Description: 28187ac6653aSJeff Kirsher * This function is a driver entry point which gets called by the kernel 28197ac6653aSJeff Kirsher * whenever multicast addresses must be enabled/disabled. 28207ac6653aSJeff Kirsher * Return value: 28217ac6653aSJeff Kirsher * void. 28227ac6653aSJeff Kirsher */ 282301789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev) 28247ac6653aSJeff Kirsher { 28257ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 28267ac6653aSJeff Kirsher 28273b57de95SVince Bridgers priv->hw->mac->set_filter(priv->hw, dev); 28287ac6653aSJeff Kirsher } 28297ac6653aSJeff Kirsher 28307ac6653aSJeff Kirsher /** 28317ac6653aSJeff Kirsher * stmmac_change_mtu - entry point to change MTU size for the device. 28327ac6653aSJeff Kirsher * @dev : device pointer. 28337ac6653aSJeff Kirsher * @new_mtu : the new MTU size for the device. 28347ac6653aSJeff Kirsher * Description: the Maximum Transfer Unit (MTU) is used by the network layer 28357ac6653aSJeff Kirsher * to drive packet transmission. Ethernet has an MTU of 1500 octets 28367ac6653aSJeff Kirsher * (ETH_DATA_LEN). This value can be changed with ifconfig. 28377ac6653aSJeff Kirsher * Return value: 28387ac6653aSJeff Kirsher * 0 on success and an appropriate (-)ve integer as defined in errno.h 28397ac6653aSJeff Kirsher * file on failure. 28407ac6653aSJeff Kirsher */ 28417ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu) 28427ac6653aSJeff Kirsher { 284338ddc59dSLABBE Corentin struct stmmac_priv *priv = netdev_priv(dev); 284438ddc59dSLABBE Corentin 28457ac6653aSJeff Kirsher if (netif_running(dev)) { 284638ddc59dSLABBE Corentin netdev_err(priv->dev, "must be stopped to change its MTU\n"); 28477ac6653aSJeff Kirsher return -EBUSY; 28487ac6653aSJeff Kirsher } 28497ac6653aSJeff Kirsher 28507ac6653aSJeff Kirsher dev->mtu = new_mtu; 2851f748be53SAlexandre TORGUE 28527ac6653aSJeff Kirsher netdev_update_features(dev); 28537ac6653aSJeff Kirsher 28547ac6653aSJeff Kirsher return 0; 28557ac6653aSJeff Kirsher } 28567ac6653aSJeff Kirsher 2857c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev, 2858c8f44affSMichał Mirosław netdev_features_t features) 28597ac6653aSJeff Kirsher { 28607ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 28617ac6653aSJeff Kirsher 286238912bdbSDeepak SIKRI if (priv->plat->rx_coe == STMMAC_RX_COE_NONE) 28637ac6653aSJeff Kirsher features &= ~NETIF_F_RXCSUM; 2864d2afb5bdSGiuseppe CAVALLARO 28657ac6653aSJeff Kirsher if (!priv->plat->tx_coe) 2866a188222bSTom Herbert features &= ~NETIF_F_CSUM_MASK; 28677ac6653aSJeff Kirsher 28687ac6653aSJeff Kirsher /* Some GMAC devices have a bugged Jumbo frame support that 28697ac6653aSJeff Kirsher * needs to have the Tx COE disabled for oversized frames 28707ac6653aSJeff Kirsher * (due to limited buffer sizes). In this case we disable 2871ceb69499SGiuseppe CAVALLARO * the TX csum insertion in the TDES and not use SF. 2872ceb69499SGiuseppe CAVALLARO */ 28737ac6653aSJeff Kirsher if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN)) 2874a188222bSTom Herbert features &= ~NETIF_F_CSUM_MASK; 28757ac6653aSJeff Kirsher 2876f748be53SAlexandre TORGUE /* Disable tso if asked by ethtool */ 2877f748be53SAlexandre TORGUE if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { 2878f748be53SAlexandre TORGUE if (features & NETIF_F_TSO) 2879f748be53SAlexandre TORGUE priv->tso = true; 2880f748be53SAlexandre TORGUE else 2881f748be53SAlexandre TORGUE priv->tso = false; 2882f748be53SAlexandre TORGUE } 2883f748be53SAlexandre TORGUE 28847ac6653aSJeff Kirsher return features; 28857ac6653aSJeff Kirsher } 28867ac6653aSJeff Kirsher 2887d2afb5bdSGiuseppe CAVALLARO static int stmmac_set_features(struct net_device *netdev, 2888d2afb5bdSGiuseppe CAVALLARO netdev_features_t features) 2889d2afb5bdSGiuseppe CAVALLARO { 2890d2afb5bdSGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(netdev); 2891d2afb5bdSGiuseppe CAVALLARO 2892d2afb5bdSGiuseppe CAVALLARO /* Keep the COE Type in case of csum is supporting */ 2893d2afb5bdSGiuseppe CAVALLARO if (features & NETIF_F_RXCSUM) 2894d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = priv->plat->rx_coe; 2895d2afb5bdSGiuseppe CAVALLARO else 2896d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = 0; 2897d2afb5bdSGiuseppe CAVALLARO /* No check needed because rx_coe has been set before and it will be 2898d2afb5bdSGiuseppe CAVALLARO * fixed in case of issue. 2899d2afb5bdSGiuseppe CAVALLARO */ 2900d2afb5bdSGiuseppe CAVALLARO priv->hw->mac->rx_ipc(priv->hw); 2901d2afb5bdSGiuseppe CAVALLARO 2902d2afb5bdSGiuseppe CAVALLARO return 0; 2903d2afb5bdSGiuseppe CAVALLARO } 2904d2afb5bdSGiuseppe CAVALLARO 290532ceabcaSGiuseppe CAVALLARO /** 290632ceabcaSGiuseppe CAVALLARO * stmmac_interrupt - main ISR 290732ceabcaSGiuseppe CAVALLARO * @irq: interrupt number. 290832ceabcaSGiuseppe CAVALLARO * @dev_id: to pass the net device pointer. 290932ceabcaSGiuseppe CAVALLARO * Description: this is the main driver interrupt service routine. 2910732fdf0eSGiuseppe CAVALLARO * It can call: 2911732fdf0eSGiuseppe CAVALLARO * o DMA service routine (to manage incoming frame reception and transmission 2912732fdf0eSGiuseppe CAVALLARO * status) 2913732fdf0eSGiuseppe CAVALLARO * o Core interrupts to manage: remote wake-up, management counter, LPI 291432ceabcaSGiuseppe CAVALLARO * interrupts. 291532ceabcaSGiuseppe CAVALLARO */ 29167ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id) 29177ac6653aSJeff Kirsher { 29187ac6653aSJeff Kirsher struct net_device *dev = (struct net_device *)dev_id; 29197ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 29207ac6653aSJeff Kirsher 292189f7f2cfSSrinivas Kandagatla if (priv->irq_wake) 292289f7f2cfSSrinivas Kandagatla pm_wakeup_event(priv->device, 0); 292389f7f2cfSSrinivas Kandagatla 29247ac6653aSJeff Kirsher if (unlikely(!dev)) { 292538ddc59dSLABBE Corentin netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__); 29267ac6653aSJeff Kirsher return IRQ_NONE; 29277ac6653aSJeff Kirsher } 29287ac6653aSJeff Kirsher 29297ac6653aSJeff Kirsher /* To handle GMAC own interrupts */ 2930f748be53SAlexandre TORGUE if ((priv->plat->has_gmac) || (priv->plat->has_gmac4)) { 29317ed24bbeSVince Bridgers int status = priv->hw->mac->host_irq_status(priv->hw, 29320982a0f6SGiuseppe CAVALLARO &priv->xstats); 29338f71a88dSJoao Pinto 29348f71a88dSJoao Pinto if (priv->synopsys_id >= DWMAC_CORE_4_00) 29358f71a88dSJoao Pinto status |= priv->hw->mac->host_mtl_irq_status(priv->hw, 29368f71a88dSJoao Pinto STMMAC_CHAN0); 29378f71a88dSJoao Pinto 2938d765955dSGiuseppe CAVALLARO if (unlikely(status)) { 2939d765955dSGiuseppe CAVALLARO /* For LPI we need to save the tx status */ 29400982a0f6SGiuseppe CAVALLARO if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE) 2941d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = true; 29420982a0f6SGiuseppe CAVALLARO if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE) 2943d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = false; 2944a8b7d770SMatt Corallo if (status & CORE_IRQ_MTL_RX_OVERFLOW && priv->hw->dma->set_rx_tail_ptr) 2945f748be53SAlexandre TORGUE priv->hw->dma->set_rx_tail_ptr(priv->ioaddr, 2946f748be53SAlexandre TORGUE priv->rx_tail_addr, 2947f748be53SAlexandre TORGUE STMMAC_CHAN0); 2948d765955dSGiuseppe CAVALLARO } 294970523e63SGiuseppe CAVALLARO 295070523e63SGiuseppe CAVALLARO /* PCS link status */ 29513fe5cadbSGiuseppe CAVALLARO if (priv->hw->pcs) { 295270523e63SGiuseppe CAVALLARO if (priv->xstats.pcs_link) 295370523e63SGiuseppe CAVALLARO netif_carrier_on(dev); 295470523e63SGiuseppe CAVALLARO else 295570523e63SGiuseppe CAVALLARO netif_carrier_off(dev); 295670523e63SGiuseppe CAVALLARO } 2957d765955dSGiuseppe CAVALLARO } 2958d765955dSGiuseppe CAVALLARO 2959d765955dSGiuseppe CAVALLARO /* To handle DMA interrupts */ 29607ac6653aSJeff Kirsher stmmac_dma_interrupt(priv); 29617ac6653aSJeff Kirsher 29627ac6653aSJeff Kirsher return IRQ_HANDLED; 29637ac6653aSJeff Kirsher } 29647ac6653aSJeff Kirsher 29657ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 29667ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools 2967ceb69499SGiuseppe CAVALLARO * to allow network I/O with interrupts disabled. 2968ceb69499SGiuseppe CAVALLARO */ 29697ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev) 29707ac6653aSJeff Kirsher { 29717ac6653aSJeff Kirsher disable_irq(dev->irq); 29727ac6653aSJeff Kirsher stmmac_interrupt(dev->irq, dev); 29737ac6653aSJeff Kirsher enable_irq(dev->irq); 29747ac6653aSJeff Kirsher } 29757ac6653aSJeff Kirsher #endif 29767ac6653aSJeff Kirsher 29777ac6653aSJeff Kirsher /** 29787ac6653aSJeff Kirsher * stmmac_ioctl - Entry point for the Ioctl 29797ac6653aSJeff Kirsher * @dev: Device pointer. 29807ac6653aSJeff Kirsher * @rq: An IOCTL specefic structure, that can contain a pointer to 29817ac6653aSJeff Kirsher * a proprietary structure used to pass information to the driver. 29827ac6653aSJeff Kirsher * @cmd: IOCTL command 29837ac6653aSJeff Kirsher * Description: 298432ceabcaSGiuseppe CAVALLARO * Currently it supports the phy_mii_ioctl(...) and HW time stamping. 29857ac6653aSJeff Kirsher */ 29867ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 29877ac6653aSJeff Kirsher { 2988891434b1SRayagond Kokatanur int ret = -EOPNOTSUPP; 29897ac6653aSJeff Kirsher 29907ac6653aSJeff Kirsher if (!netif_running(dev)) 29917ac6653aSJeff Kirsher return -EINVAL; 29927ac6653aSJeff Kirsher 2993891434b1SRayagond Kokatanur switch (cmd) { 2994891434b1SRayagond Kokatanur case SIOCGMIIPHY: 2995891434b1SRayagond Kokatanur case SIOCGMIIREG: 2996891434b1SRayagond Kokatanur case SIOCSMIIREG: 2997d6d50c7eSPhilippe Reynes if (!dev->phydev) 29987ac6653aSJeff Kirsher return -EINVAL; 2999d6d50c7eSPhilippe Reynes ret = phy_mii_ioctl(dev->phydev, rq, cmd); 3000891434b1SRayagond Kokatanur break; 3001891434b1SRayagond Kokatanur case SIOCSHWTSTAMP: 3002891434b1SRayagond Kokatanur ret = stmmac_hwtstamp_ioctl(dev, rq); 3003891434b1SRayagond Kokatanur break; 3004891434b1SRayagond Kokatanur default: 3005891434b1SRayagond Kokatanur break; 3006891434b1SRayagond Kokatanur } 30077ac6653aSJeff Kirsher 30087ac6653aSJeff Kirsher return ret; 30097ac6653aSJeff Kirsher } 30107ac6653aSJeff Kirsher 301150fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 30127ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir; 30137ac29055SGiuseppe CAVALLARO 3014c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc, 3015c24602efSGiuseppe CAVALLARO struct seq_file *seq) 30167ac29055SGiuseppe CAVALLARO { 30177ac29055SGiuseppe CAVALLARO int i; 3018c24602efSGiuseppe CAVALLARO struct dma_extended_desc *ep = (struct dma_extended_desc *)head; 3019c24602efSGiuseppe CAVALLARO struct dma_desc *p = (struct dma_desc *)head; 30207ac29055SGiuseppe CAVALLARO 3021c24602efSGiuseppe CAVALLARO for (i = 0; i < size; i++) { 3022c24602efSGiuseppe CAVALLARO if (extend_desc) { 3023c24602efSGiuseppe CAVALLARO seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 3024c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 3025f8be0d78SMichael Weiser le32_to_cpu(ep->basic.des0), 3026f8be0d78SMichael Weiser le32_to_cpu(ep->basic.des1), 3027f8be0d78SMichael Weiser le32_to_cpu(ep->basic.des2), 3028f8be0d78SMichael Weiser le32_to_cpu(ep->basic.des3)); 3029c24602efSGiuseppe CAVALLARO ep++; 3030c24602efSGiuseppe CAVALLARO } else { 3031c24602efSGiuseppe CAVALLARO seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 3032c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 3033f8be0d78SMichael Weiser le32_to_cpu(p->des0), le32_to_cpu(p->des1), 3034f8be0d78SMichael Weiser le32_to_cpu(p->des2), le32_to_cpu(p->des3)); 3035c24602efSGiuseppe CAVALLARO p++; 3036c24602efSGiuseppe CAVALLARO } 30377ac29055SGiuseppe CAVALLARO seq_printf(seq, "\n"); 30387ac29055SGiuseppe CAVALLARO } 3039c24602efSGiuseppe CAVALLARO } 30407ac29055SGiuseppe CAVALLARO 3041c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v) 3042c24602efSGiuseppe CAVALLARO { 3043c24602efSGiuseppe CAVALLARO struct net_device *dev = seq->private; 3044c24602efSGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(dev); 30457ac29055SGiuseppe CAVALLARO 3046c24602efSGiuseppe CAVALLARO if (priv->extend_desc) { 3047c24602efSGiuseppe CAVALLARO seq_printf(seq, "Extended RX descriptor ring:\n"); 3048e3ad57c9SGiuseppe Cavallaro sysfs_display_ring((void *)priv->dma_erx, DMA_RX_SIZE, 1, seq); 3049c24602efSGiuseppe CAVALLARO seq_printf(seq, "Extended TX descriptor ring:\n"); 3050e3ad57c9SGiuseppe Cavallaro sysfs_display_ring((void *)priv->dma_etx, DMA_TX_SIZE, 1, seq); 3051c24602efSGiuseppe CAVALLARO } else { 3052c24602efSGiuseppe CAVALLARO seq_printf(seq, "RX descriptor ring:\n"); 3053e3ad57c9SGiuseppe Cavallaro sysfs_display_ring((void *)priv->dma_rx, DMA_RX_SIZE, 0, seq); 3054c24602efSGiuseppe CAVALLARO seq_printf(seq, "TX descriptor ring:\n"); 3055e3ad57c9SGiuseppe Cavallaro sysfs_display_ring((void *)priv->dma_tx, DMA_TX_SIZE, 0, seq); 30567ac29055SGiuseppe CAVALLARO } 30577ac29055SGiuseppe CAVALLARO 30587ac29055SGiuseppe CAVALLARO return 0; 30597ac29055SGiuseppe CAVALLARO } 30607ac29055SGiuseppe CAVALLARO 30617ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file) 30627ac29055SGiuseppe CAVALLARO { 30637ac29055SGiuseppe CAVALLARO return single_open(file, stmmac_sysfs_ring_read, inode->i_private); 30647ac29055SGiuseppe CAVALLARO } 30657ac29055SGiuseppe CAVALLARO 306622d3efe5SPavel Machek /* Debugfs files, should appear in /sys/kernel/debug/stmmaceth/eth0 */ 306722d3efe5SPavel Machek 30687ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = { 30697ac29055SGiuseppe CAVALLARO .owner = THIS_MODULE, 30707ac29055SGiuseppe CAVALLARO .open = stmmac_sysfs_ring_open, 30717ac29055SGiuseppe CAVALLARO .read = seq_read, 30727ac29055SGiuseppe CAVALLARO .llseek = seq_lseek, 307374863948SDjalal Harouni .release = single_release, 30747ac29055SGiuseppe CAVALLARO }; 30757ac29055SGiuseppe CAVALLARO 3076e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v) 3077e7434821SGiuseppe CAVALLARO { 3078e7434821SGiuseppe CAVALLARO struct net_device *dev = seq->private; 3079e7434821SGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(dev); 3080e7434821SGiuseppe CAVALLARO 308119e30c14SGiuseppe CAVALLARO if (!priv->hw_cap_support) { 3082e7434821SGiuseppe CAVALLARO seq_printf(seq, "DMA HW features not supported\n"); 3083e7434821SGiuseppe CAVALLARO return 0; 3084e7434821SGiuseppe CAVALLARO } 3085e7434821SGiuseppe CAVALLARO 3086e7434821SGiuseppe CAVALLARO seq_printf(seq, "==============================\n"); 3087e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tDMA HW features\n"); 3088e7434821SGiuseppe CAVALLARO seq_printf(seq, "==============================\n"); 3089e7434821SGiuseppe CAVALLARO 309022d3efe5SPavel Machek seq_printf(seq, "\t10/100 Mbps: %s\n", 3091e7434821SGiuseppe CAVALLARO (priv->dma_cap.mbps_10_100) ? "Y" : "N"); 309222d3efe5SPavel Machek seq_printf(seq, "\t1000 Mbps: %s\n", 3093e7434821SGiuseppe CAVALLARO (priv->dma_cap.mbps_1000) ? "Y" : "N"); 309422d3efe5SPavel Machek seq_printf(seq, "\tHalf duplex: %s\n", 3095e7434821SGiuseppe CAVALLARO (priv->dma_cap.half_duplex) ? "Y" : "N"); 3096e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tHash Filter: %s\n", 3097e7434821SGiuseppe CAVALLARO (priv->dma_cap.hash_filter) ? "Y" : "N"); 3098e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tMultiple MAC address registers: %s\n", 3099e7434821SGiuseppe CAVALLARO (priv->dma_cap.multi_addr) ? "Y" : "N"); 31008d45e42bSLABBE Corentin seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfaces): %s\n", 3101e7434821SGiuseppe CAVALLARO (priv->dma_cap.pcs) ? "Y" : "N"); 3102e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tSMA (MDIO) Interface: %s\n", 3103e7434821SGiuseppe CAVALLARO (priv->dma_cap.sma_mdio) ? "Y" : "N"); 3104e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPMT Remote wake up: %s\n", 3105e7434821SGiuseppe CAVALLARO (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N"); 3106e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPMT Magic Frame: %s\n", 3107e7434821SGiuseppe CAVALLARO (priv->dma_cap.pmt_magic_frame) ? "Y" : "N"); 3108e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tRMON module: %s\n", 3109e7434821SGiuseppe CAVALLARO (priv->dma_cap.rmon) ? "Y" : "N"); 3110e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n", 3111e7434821SGiuseppe CAVALLARO (priv->dma_cap.time_stamp) ? "Y" : "N"); 3112e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp: %s\n", 3113e7434821SGiuseppe CAVALLARO (priv->dma_cap.atime_stamp) ? "Y" : "N"); 311422d3efe5SPavel Machek seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE): %s\n", 3115e7434821SGiuseppe CAVALLARO (priv->dma_cap.eee) ? "Y" : "N"); 3116e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N"); 3117e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tChecksum Offload in TX: %s\n", 3118e7434821SGiuseppe CAVALLARO (priv->dma_cap.tx_coe) ? "Y" : "N"); 3119f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) { 3120f748be53SAlexandre TORGUE seq_printf(seq, "\tIP Checksum Offload in RX: %s\n", 3121f748be53SAlexandre TORGUE (priv->dma_cap.rx_coe) ? "Y" : "N"); 3122f748be53SAlexandre TORGUE } else { 3123e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n", 3124e7434821SGiuseppe CAVALLARO (priv->dma_cap.rx_coe_type1) ? "Y" : "N"); 3125e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n", 3126e7434821SGiuseppe CAVALLARO (priv->dma_cap.rx_coe_type2) ? "Y" : "N"); 3127f748be53SAlexandre TORGUE } 3128e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n", 3129e7434821SGiuseppe CAVALLARO (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N"); 3130e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tNumber of Additional RX channel: %d\n", 3131e7434821SGiuseppe CAVALLARO priv->dma_cap.number_rx_channel); 3132e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tNumber of Additional TX channel: %d\n", 3133e7434821SGiuseppe CAVALLARO priv->dma_cap.number_tx_channel); 3134e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tEnhanced descriptors: %s\n", 3135e7434821SGiuseppe CAVALLARO (priv->dma_cap.enh_desc) ? "Y" : "N"); 3136e7434821SGiuseppe CAVALLARO 3137e7434821SGiuseppe CAVALLARO return 0; 3138e7434821SGiuseppe CAVALLARO } 3139e7434821SGiuseppe CAVALLARO 3140e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file) 3141e7434821SGiuseppe CAVALLARO { 3142e7434821SGiuseppe CAVALLARO return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private); 3143e7434821SGiuseppe CAVALLARO } 3144e7434821SGiuseppe CAVALLARO 3145e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = { 3146e7434821SGiuseppe CAVALLARO .owner = THIS_MODULE, 3147e7434821SGiuseppe CAVALLARO .open = stmmac_sysfs_dma_cap_open, 3148e7434821SGiuseppe CAVALLARO .read = seq_read, 3149e7434821SGiuseppe CAVALLARO .llseek = seq_lseek, 315074863948SDjalal Harouni .release = single_release, 3151e7434821SGiuseppe CAVALLARO }; 3152e7434821SGiuseppe CAVALLARO 31537ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev) 31547ac29055SGiuseppe CAVALLARO { 3155466c5ac8SMathieu Olivari struct stmmac_priv *priv = netdev_priv(dev); 31567ac29055SGiuseppe CAVALLARO 3157466c5ac8SMathieu Olivari /* Create per netdev entries */ 3158466c5ac8SMathieu Olivari priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir); 3159466c5ac8SMathieu Olivari 3160466c5ac8SMathieu Olivari if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) { 316138ddc59dSLABBE Corentin netdev_err(priv->dev, "ERROR failed to create debugfs directory\n"); 31627ac29055SGiuseppe CAVALLARO 31637ac29055SGiuseppe CAVALLARO return -ENOMEM; 31647ac29055SGiuseppe CAVALLARO } 31657ac29055SGiuseppe CAVALLARO 31667ac29055SGiuseppe CAVALLARO /* Entry to report DMA RX/TX rings */ 3167466c5ac8SMathieu Olivari priv->dbgfs_rings_status = 3168466c5ac8SMathieu Olivari debugfs_create_file("descriptors_status", S_IRUGO, 3169466c5ac8SMathieu Olivari priv->dbgfs_dir, dev, 31707ac29055SGiuseppe CAVALLARO &stmmac_rings_status_fops); 31717ac29055SGiuseppe CAVALLARO 3172466c5ac8SMathieu Olivari if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) { 317338ddc59dSLABBE Corentin netdev_err(priv->dev, "ERROR creating stmmac ring debugfs file\n"); 3174466c5ac8SMathieu Olivari debugfs_remove_recursive(priv->dbgfs_dir); 31757ac29055SGiuseppe CAVALLARO 31767ac29055SGiuseppe CAVALLARO return -ENOMEM; 31777ac29055SGiuseppe CAVALLARO } 31787ac29055SGiuseppe CAVALLARO 3179e7434821SGiuseppe CAVALLARO /* Entry to report the DMA HW features */ 3180466c5ac8SMathieu Olivari priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, 3181466c5ac8SMathieu Olivari priv->dbgfs_dir, 3182e7434821SGiuseppe CAVALLARO dev, &stmmac_dma_cap_fops); 3183e7434821SGiuseppe CAVALLARO 3184466c5ac8SMathieu Olivari if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) { 318538ddc59dSLABBE Corentin netdev_err(priv->dev, "ERROR creating stmmac MMC debugfs file\n"); 3186466c5ac8SMathieu Olivari debugfs_remove_recursive(priv->dbgfs_dir); 3187e7434821SGiuseppe CAVALLARO 3188e7434821SGiuseppe CAVALLARO return -ENOMEM; 3189e7434821SGiuseppe CAVALLARO } 3190e7434821SGiuseppe CAVALLARO 31917ac29055SGiuseppe CAVALLARO return 0; 31927ac29055SGiuseppe CAVALLARO } 31937ac29055SGiuseppe CAVALLARO 3194466c5ac8SMathieu Olivari static void stmmac_exit_fs(struct net_device *dev) 31957ac29055SGiuseppe CAVALLARO { 3196466c5ac8SMathieu Olivari struct stmmac_priv *priv = netdev_priv(dev); 3197466c5ac8SMathieu Olivari 3198466c5ac8SMathieu Olivari debugfs_remove_recursive(priv->dbgfs_dir); 31997ac29055SGiuseppe CAVALLARO } 320050fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */ 32017ac29055SGiuseppe CAVALLARO 32027ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = { 32037ac6653aSJeff Kirsher .ndo_open = stmmac_open, 32047ac6653aSJeff Kirsher .ndo_start_xmit = stmmac_xmit, 32057ac6653aSJeff Kirsher .ndo_stop = stmmac_release, 32067ac6653aSJeff Kirsher .ndo_change_mtu = stmmac_change_mtu, 32077ac6653aSJeff Kirsher .ndo_fix_features = stmmac_fix_features, 3208d2afb5bdSGiuseppe CAVALLARO .ndo_set_features = stmmac_set_features, 320901789349SJiri Pirko .ndo_set_rx_mode = stmmac_set_rx_mode, 32107ac6653aSJeff Kirsher .ndo_tx_timeout = stmmac_tx_timeout, 32117ac6653aSJeff Kirsher .ndo_do_ioctl = stmmac_ioctl, 32127ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 32137ac6653aSJeff Kirsher .ndo_poll_controller = stmmac_poll_controller, 32147ac6653aSJeff Kirsher #endif 32157ac6653aSJeff Kirsher .ndo_set_mac_address = eth_mac_addr, 32167ac6653aSJeff Kirsher }; 32177ac6653aSJeff Kirsher 32187ac6653aSJeff Kirsher /** 3219cf3f047bSGiuseppe CAVALLARO * stmmac_hw_init - Init the MAC device 322032ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 3221732fdf0eSGiuseppe CAVALLARO * Description: this function is to configure the MAC device according to 3222732fdf0eSGiuseppe CAVALLARO * some platform parameters or the HW capability register. It prepares the 3223732fdf0eSGiuseppe CAVALLARO * driver to use either ring or chain modes and to setup either enhanced or 3224732fdf0eSGiuseppe CAVALLARO * normal descriptors. 3225cf3f047bSGiuseppe CAVALLARO */ 3226cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv) 3227cf3f047bSGiuseppe CAVALLARO { 3228cf3f047bSGiuseppe CAVALLARO struct mac_device_info *mac; 3229cf3f047bSGiuseppe CAVALLARO 3230cf3f047bSGiuseppe CAVALLARO /* Identify the MAC HW device */ 323103f2eecdSMarc Kleine-Budde if (priv->plat->has_gmac) { 323203f2eecdSMarc Kleine-Budde priv->dev->priv_flags |= IFF_UNICAST_FLT; 32333b57de95SVince Bridgers mac = dwmac1000_setup(priv->ioaddr, 32343b57de95SVince Bridgers priv->plat->multicast_filter_bins, 3235c623d149SAlexandre TORGUE priv->plat->unicast_filter_entries, 3236c623d149SAlexandre TORGUE &priv->synopsys_id); 3237f748be53SAlexandre TORGUE } else if (priv->plat->has_gmac4) { 3238f748be53SAlexandre TORGUE priv->dev->priv_flags |= IFF_UNICAST_FLT; 3239f748be53SAlexandre TORGUE mac = dwmac4_setup(priv->ioaddr, 3240f748be53SAlexandre TORGUE priv->plat->multicast_filter_bins, 3241f748be53SAlexandre TORGUE priv->plat->unicast_filter_entries, 3242f748be53SAlexandre TORGUE &priv->synopsys_id); 324303f2eecdSMarc Kleine-Budde } else { 3244c623d149SAlexandre TORGUE mac = dwmac100_setup(priv->ioaddr, &priv->synopsys_id); 324503f2eecdSMarc Kleine-Budde } 3246cf3f047bSGiuseppe CAVALLARO if (!mac) 3247cf3f047bSGiuseppe CAVALLARO return -ENOMEM; 3248cf3f047bSGiuseppe CAVALLARO 3249cf3f047bSGiuseppe CAVALLARO priv->hw = mac; 3250cf3f047bSGiuseppe CAVALLARO 32514a7d666aSGiuseppe CAVALLARO /* To use the chained or ring mode */ 3252f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) { 3253f748be53SAlexandre TORGUE priv->hw->mode = &dwmac4_ring_mode_ops; 3254f748be53SAlexandre TORGUE } else { 32554a7d666aSGiuseppe CAVALLARO if (chain_mode) { 325629896a67SGiuseppe CAVALLARO priv->hw->mode = &chain_mode_ops; 325738ddc59dSLABBE Corentin dev_info(priv->device, "Chain mode enabled\n"); 32584a7d666aSGiuseppe CAVALLARO priv->mode = STMMAC_CHAIN_MODE; 32594a7d666aSGiuseppe CAVALLARO } else { 326029896a67SGiuseppe CAVALLARO priv->hw->mode = &ring_mode_ops; 326138ddc59dSLABBE Corentin dev_info(priv->device, "Ring mode enabled\n"); 32624a7d666aSGiuseppe CAVALLARO priv->mode = STMMAC_RING_MODE; 32634a7d666aSGiuseppe CAVALLARO } 3264f748be53SAlexandre TORGUE } 32654a7d666aSGiuseppe CAVALLARO 3266cf3f047bSGiuseppe CAVALLARO /* Get the HW capability (new GMAC newer than 3.50a) */ 3267cf3f047bSGiuseppe CAVALLARO priv->hw_cap_support = stmmac_get_hw_features(priv); 3268cf3f047bSGiuseppe CAVALLARO if (priv->hw_cap_support) { 326938ddc59dSLABBE Corentin dev_info(priv->device, "DMA HW capability register supported\n"); 3270cf3f047bSGiuseppe CAVALLARO 3271cf3f047bSGiuseppe CAVALLARO /* We can override some gmac/dma configuration fields: e.g. 3272cf3f047bSGiuseppe CAVALLARO * enh_desc, tx_coe (e.g. that are passed through the 3273cf3f047bSGiuseppe CAVALLARO * platform) with the values from the HW capability 3274cf3f047bSGiuseppe CAVALLARO * register (if supported). 3275cf3f047bSGiuseppe CAVALLARO */ 3276cf3f047bSGiuseppe CAVALLARO priv->plat->enh_desc = priv->dma_cap.enh_desc; 3277cf3f047bSGiuseppe CAVALLARO priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; 32783fe5cadbSGiuseppe CAVALLARO priv->hw->pmt = priv->plat->pmt; 327938912bdbSDeepak SIKRI 3280a8df35d4SEzequiel Garcia /* TXCOE doesn't work in thresh DMA mode */ 3281a8df35d4SEzequiel Garcia if (priv->plat->force_thresh_dma_mode) 3282a8df35d4SEzequiel Garcia priv->plat->tx_coe = 0; 3283a8df35d4SEzequiel Garcia else 328438912bdbSDeepak SIKRI priv->plat->tx_coe = priv->dma_cap.tx_coe; 3285a8df35d4SEzequiel Garcia 3286f748be53SAlexandre TORGUE /* In case of GMAC4 rx_coe is from HW cap register. */ 3287f748be53SAlexandre TORGUE priv->plat->rx_coe = priv->dma_cap.rx_coe; 328838912bdbSDeepak SIKRI 328938912bdbSDeepak SIKRI if (priv->dma_cap.rx_coe_type2) 329038912bdbSDeepak SIKRI priv->plat->rx_coe = STMMAC_RX_COE_TYPE2; 329138912bdbSDeepak SIKRI else if (priv->dma_cap.rx_coe_type1) 329238912bdbSDeepak SIKRI priv->plat->rx_coe = STMMAC_RX_COE_TYPE1; 329338912bdbSDeepak SIKRI 329438ddc59dSLABBE Corentin } else { 329538ddc59dSLABBE Corentin dev_info(priv->device, "No HW DMA feature register supported\n"); 329638ddc59dSLABBE Corentin } 3297cf3f047bSGiuseppe CAVALLARO 3298f748be53SAlexandre TORGUE /* To use alternate (extended), normal or GMAC4 descriptor structures */ 3299f748be53SAlexandre TORGUE if (priv->synopsys_id >= DWMAC_CORE_4_00) 3300f748be53SAlexandre TORGUE priv->hw->desc = &dwmac4_desc_ops; 3301f748be53SAlexandre TORGUE else 330261369d02SByungho An stmmac_selec_desc_mode(priv); 330361369d02SByungho An 3304d2afb5bdSGiuseppe CAVALLARO if (priv->plat->rx_coe) { 3305d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = priv->plat->rx_coe; 330638ddc59dSLABBE Corentin dev_info(priv->device, "RX Checksum Offload Engine supported\n"); 3307f748be53SAlexandre TORGUE if (priv->synopsys_id < DWMAC_CORE_4_00) 330838ddc59dSLABBE Corentin dev_info(priv->device, "COE Type %d\n", priv->hw->rx_csum); 3309d2afb5bdSGiuseppe CAVALLARO } 3310cf3f047bSGiuseppe CAVALLARO if (priv->plat->tx_coe) 331138ddc59dSLABBE Corentin dev_info(priv->device, "TX Checksum insertion supported\n"); 3312cf3f047bSGiuseppe CAVALLARO 3313cf3f047bSGiuseppe CAVALLARO if (priv->plat->pmt) { 331438ddc59dSLABBE Corentin dev_info(priv->device, "Wake-Up On Lan supported\n"); 3315cf3f047bSGiuseppe CAVALLARO device_set_wakeup_capable(priv->device, 1); 3316cf3f047bSGiuseppe CAVALLARO } 3317cf3f047bSGiuseppe CAVALLARO 3318f748be53SAlexandre TORGUE if (priv->dma_cap.tsoen) 331938ddc59dSLABBE Corentin dev_info(priv->device, "TSO supported\n"); 3320f748be53SAlexandre TORGUE 3321c24602efSGiuseppe CAVALLARO return 0; 3322cf3f047bSGiuseppe CAVALLARO } 3323cf3f047bSGiuseppe CAVALLARO 3324cf3f047bSGiuseppe CAVALLARO /** 3325bfab27a1SGiuseppe CAVALLARO * stmmac_dvr_probe 3326bfab27a1SGiuseppe CAVALLARO * @device: device pointer 3327ff3dd78cSGiuseppe CAVALLARO * @plat_dat: platform data pointer 3328e56788cfSJoachim Eastwood * @res: stmmac resource pointer 3329bfab27a1SGiuseppe CAVALLARO * Description: this is the main probe function used to 3330bfab27a1SGiuseppe CAVALLARO * call the alloc_etherdev, allocate the priv structure. 33319afec6efSAndy Shevchenko * Return: 333215ffac73SJoachim Eastwood * returns 0 on success, otherwise errno. 33337ac6653aSJeff Kirsher */ 333415ffac73SJoachim Eastwood int stmmac_dvr_probe(struct device *device, 3335cf3f047bSGiuseppe CAVALLARO struct plat_stmmacenet_data *plat_dat, 3336e56788cfSJoachim Eastwood struct stmmac_resources *res) 33377ac6653aSJeff Kirsher { 33387ac6653aSJeff Kirsher int ret = 0; 3339bfab27a1SGiuseppe CAVALLARO struct net_device *ndev = NULL; 3340bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *priv; 33417ac6653aSJeff Kirsher 3342bfab27a1SGiuseppe CAVALLARO ndev = alloc_etherdev(sizeof(struct stmmac_priv)); 334341de8d4cSJoe Perches if (!ndev) 334415ffac73SJoachim Eastwood return -ENOMEM; 33457ac6653aSJeff Kirsher 3346bfab27a1SGiuseppe CAVALLARO SET_NETDEV_DEV(ndev, device); 33477ac6653aSJeff Kirsher 3348bfab27a1SGiuseppe CAVALLARO priv = netdev_priv(ndev); 3349bfab27a1SGiuseppe CAVALLARO priv->device = device; 3350bfab27a1SGiuseppe CAVALLARO priv->dev = ndev; 3351bfab27a1SGiuseppe CAVALLARO 3352bfab27a1SGiuseppe CAVALLARO stmmac_set_ethtool_ops(ndev); 3353cf3f047bSGiuseppe CAVALLARO priv->pause = pause; 3354cf3f047bSGiuseppe CAVALLARO priv->plat = plat_dat; 3355e56788cfSJoachim Eastwood priv->ioaddr = res->addr; 3356e56788cfSJoachim Eastwood priv->dev->base_addr = (unsigned long)res->addr; 3357e56788cfSJoachim Eastwood 3358e56788cfSJoachim Eastwood priv->dev->irq = res->irq; 3359e56788cfSJoachim Eastwood priv->wol_irq = res->wol_irq; 3360e56788cfSJoachim Eastwood priv->lpi_irq = res->lpi_irq; 3361e56788cfSJoachim Eastwood 3362e56788cfSJoachim Eastwood if (res->mac) 3363e56788cfSJoachim Eastwood memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN); 3364bfab27a1SGiuseppe CAVALLARO 3365a7a62685SJoachim Eastwood dev_set_drvdata(device, priv->dev); 3366803f8fc4SJoachim Eastwood 3367cf3f047bSGiuseppe CAVALLARO /* Verify driver arguments */ 3368cf3f047bSGiuseppe CAVALLARO stmmac_verify_args(); 3369cf3f047bSGiuseppe CAVALLARO 3370cf3f047bSGiuseppe CAVALLARO /* Override with kernel parameters if supplied XXX CRS XXX 3371ceb69499SGiuseppe CAVALLARO * this needs to have multiple instances 3372ceb69499SGiuseppe CAVALLARO */ 3373cf3f047bSGiuseppe CAVALLARO if ((phyaddr >= 0) && (phyaddr <= 31)) 3374cf3f047bSGiuseppe CAVALLARO priv->plat->phy_addr = phyaddr; 3375cf3f047bSGiuseppe CAVALLARO 3376f573c0b9Sjpinto if (priv->plat->stmmac_rst) 3377f573c0b9Sjpinto reset_control_deassert(priv->plat->stmmac_rst); 3378c5e4ddbdSChen-Yu Tsai 3379cf3f047bSGiuseppe CAVALLARO /* Init MAC and get the capabilities */ 3380c24602efSGiuseppe CAVALLARO ret = stmmac_hw_init(priv); 3381c24602efSGiuseppe CAVALLARO if (ret) 338262866e98SChen-Yu Tsai goto error_hw_init; 3383cf3f047bSGiuseppe CAVALLARO 3384cf3f047bSGiuseppe CAVALLARO ndev->netdev_ops = &stmmac_netdev_ops; 3385cf3f047bSGiuseppe CAVALLARO 3386cf3f047bSGiuseppe CAVALLARO ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | 3387cf3f047bSGiuseppe CAVALLARO NETIF_F_RXCSUM; 3388f748be53SAlexandre TORGUE 3389f748be53SAlexandre TORGUE if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) { 3390f748be53SAlexandre TORGUE ndev->hw_features |= NETIF_F_TSO; 3391f748be53SAlexandre TORGUE priv->tso = true; 339238ddc59dSLABBE Corentin dev_info(priv->device, "TSO feature enabled\n"); 3393f748be53SAlexandre TORGUE } 3394bfab27a1SGiuseppe CAVALLARO ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; 3395bfab27a1SGiuseppe CAVALLARO ndev->watchdog_timeo = msecs_to_jiffies(watchdog); 33967ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED 33977ac6653aSJeff Kirsher /* Both mac100 and gmac support receive VLAN tag detection */ 3398f646968fSPatrick McHardy ndev->features |= NETIF_F_HW_VLAN_CTAG_RX; 33997ac6653aSJeff Kirsher #endif 34007ac6653aSJeff Kirsher priv->msg_enable = netif_msg_init(debug, default_msg_level); 34017ac6653aSJeff Kirsher 340244770e11SJarod Wilson /* MTU range: 46 - hw-specific max */ 340344770e11SJarod Wilson ndev->min_mtu = ETH_ZLEN - ETH_HLEN; 340444770e11SJarod Wilson if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00)) 340544770e11SJarod Wilson ndev->max_mtu = JUMBO_LEN; 340644770e11SJarod Wilson else 340744770e11SJarod Wilson ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN); 3408a2cd64f3SKweh, Hock Leong /* Will not overwrite ndev->max_mtu if plat->maxmtu > ndev->max_mtu 3409a2cd64f3SKweh, Hock Leong * as well as plat->maxmtu < ndev->min_mtu which is a invalid range. 3410a2cd64f3SKweh, Hock Leong */ 3411a2cd64f3SKweh, Hock Leong if ((priv->plat->maxmtu < ndev->max_mtu) && 3412a2cd64f3SKweh, Hock Leong (priv->plat->maxmtu >= ndev->min_mtu)) 341344770e11SJarod Wilson ndev->max_mtu = priv->plat->maxmtu; 3414a2cd64f3SKweh, Hock Leong else if (priv->plat->maxmtu < ndev->min_mtu) 3415b618ab45SHeiner Kallweit dev_warn(priv->device, 3416a2cd64f3SKweh, Hock Leong "%s: warning: maxmtu having invalid value (%d)\n", 3417a2cd64f3SKweh, Hock Leong __func__, priv->plat->maxmtu); 341844770e11SJarod Wilson 34197ac6653aSJeff Kirsher if (flow_ctrl) 34207ac6653aSJeff Kirsher priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ 34217ac6653aSJeff Kirsher 342262a2ab93SGiuseppe CAVALLARO /* Rx Watchdog is available in the COREs newer than the 3.40. 342362a2ab93SGiuseppe CAVALLARO * In some case, for example on bugged HW this feature 342462a2ab93SGiuseppe CAVALLARO * has to be disable and this can be done by passing the 342562a2ab93SGiuseppe CAVALLARO * riwt_off field from the platform. 342662a2ab93SGiuseppe CAVALLARO */ 342762a2ab93SGiuseppe CAVALLARO if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) { 342862a2ab93SGiuseppe CAVALLARO priv->use_riwt = 1; 3429b618ab45SHeiner Kallweit dev_info(priv->device, 3430b618ab45SHeiner Kallweit "Enable RX Mitigation via HW Watchdog Timer\n"); 343162a2ab93SGiuseppe CAVALLARO } 343262a2ab93SGiuseppe CAVALLARO 3433bfab27a1SGiuseppe CAVALLARO netif_napi_add(ndev, &priv->napi, stmmac_poll, 64); 34347ac6653aSJeff Kirsher 34357ac6653aSJeff Kirsher spin_lock_init(&priv->lock); 34367ac6653aSJeff Kirsher 3437cd7201f4SGiuseppe CAVALLARO /* If a specific clk_csr value is passed from the platform 3438cd7201f4SGiuseppe CAVALLARO * this means that the CSR Clock Range selection cannot be 3439cd7201f4SGiuseppe CAVALLARO * changed at run-time and it is fixed. Viceversa the driver'll try to 3440cd7201f4SGiuseppe CAVALLARO * set the MDC clock dynamically according to the csr actual 3441cd7201f4SGiuseppe CAVALLARO * clock input. 3442cd7201f4SGiuseppe CAVALLARO */ 3443cd7201f4SGiuseppe CAVALLARO if (!priv->plat->clk_csr) 3444cd7201f4SGiuseppe CAVALLARO stmmac_clk_csr_set(priv); 3445cd7201f4SGiuseppe CAVALLARO else 3446cd7201f4SGiuseppe CAVALLARO priv->clk_csr = priv->plat->clk_csr; 3447cd7201f4SGiuseppe CAVALLARO 3448e58bb43fSGiuseppe CAVALLARO stmmac_check_pcs_mode(priv); 3449e58bb43fSGiuseppe CAVALLARO 34503fe5cadbSGiuseppe CAVALLARO if (priv->hw->pcs != STMMAC_PCS_RGMII && 34513fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_TBI && 34523fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_RTBI) { 34534bfcbd7aSFrancesco Virlinzi /* MDIO bus Registration */ 34544bfcbd7aSFrancesco Virlinzi ret = stmmac_mdio_register(ndev); 34554bfcbd7aSFrancesco Virlinzi if (ret < 0) { 3456b618ab45SHeiner Kallweit dev_err(priv->device, 345738ddc59dSLABBE Corentin "%s: MDIO bus (id: %d) registration failed", 34584bfcbd7aSFrancesco Virlinzi __func__, priv->plat->bus_id); 34596a81c26fSViresh Kumar goto error_mdio_register; 34604bfcbd7aSFrancesco Virlinzi } 3461e58bb43fSGiuseppe CAVALLARO } 34624bfcbd7aSFrancesco Virlinzi 346357016590SFlorian Fainelli ret = register_netdev(ndev); 3464b2eb09afSFlorian Fainelli if (ret) { 3465b618ab45SHeiner Kallweit dev_err(priv->device, "%s: ERROR %i registering the device\n", 346657016590SFlorian Fainelli __func__, ret); 3467b2eb09afSFlorian Fainelli goto error_netdev_register; 3468b2eb09afSFlorian Fainelli } 34697ac6653aSJeff Kirsher 347057016590SFlorian Fainelli return ret; 34717ac6653aSJeff Kirsher 34726a81c26fSViresh Kumar error_netdev_register: 3473b2eb09afSFlorian Fainelli if (priv->hw->pcs != STMMAC_PCS_RGMII && 3474b2eb09afSFlorian Fainelli priv->hw->pcs != STMMAC_PCS_TBI && 3475b2eb09afSFlorian Fainelli priv->hw->pcs != STMMAC_PCS_RTBI) 3476b2eb09afSFlorian Fainelli stmmac_mdio_unregister(ndev); 34777ac6653aSJeff Kirsher error_mdio_register: 34786a81c26fSViresh Kumar netif_napi_del(&priv->napi); 347962866e98SChen-Yu Tsai error_hw_init: 34807ac6653aSJeff Kirsher free_netdev(ndev); 34817ac6653aSJeff Kirsher 348215ffac73SJoachim Eastwood return ret; 34837ac6653aSJeff Kirsher } 3484b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_probe); 34857ac6653aSJeff Kirsher 34867ac6653aSJeff Kirsher /** 34877ac6653aSJeff Kirsher * stmmac_dvr_remove 3488f4e7bd81SJoachim Eastwood * @dev: device pointer 34897ac6653aSJeff Kirsher * Description: this function resets the TX/RX processes, disables the MAC RX/TX 3490bfab27a1SGiuseppe CAVALLARO * changes the link status, releases the DMA descriptor rings. 34917ac6653aSJeff Kirsher */ 3492f4e7bd81SJoachim Eastwood int stmmac_dvr_remove(struct device *dev) 34937ac6653aSJeff Kirsher { 3494f4e7bd81SJoachim Eastwood struct net_device *ndev = dev_get_drvdata(dev); 34957ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 34967ac6653aSJeff Kirsher 349738ddc59dSLABBE Corentin netdev_info(priv->dev, "%s: removing driver", __func__); 34987ac6653aSJeff Kirsher 34997ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 35007ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 35017ac6653aSJeff Kirsher 3502bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 35037ac6653aSJeff Kirsher netif_carrier_off(ndev); 35047ac6653aSJeff Kirsher unregister_netdev(ndev); 3505f573c0b9Sjpinto if (priv->plat->stmmac_rst) 3506f573c0b9Sjpinto reset_control_assert(priv->plat->stmmac_rst); 3507f573c0b9Sjpinto clk_disable_unprepare(priv->plat->pclk); 3508f573c0b9Sjpinto clk_disable_unprepare(priv->plat->stmmac_clk); 35093fe5cadbSGiuseppe CAVALLARO if (priv->hw->pcs != STMMAC_PCS_RGMII && 35103fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_TBI && 35113fe5cadbSGiuseppe CAVALLARO priv->hw->pcs != STMMAC_PCS_RTBI) 3512e743471fSBryan O'Donoghue stmmac_mdio_unregister(ndev); 35137ac6653aSJeff Kirsher free_netdev(ndev); 35147ac6653aSJeff Kirsher 35157ac6653aSJeff Kirsher return 0; 35167ac6653aSJeff Kirsher } 3517b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_remove); 35187ac6653aSJeff Kirsher 3519732fdf0eSGiuseppe CAVALLARO /** 3520732fdf0eSGiuseppe CAVALLARO * stmmac_suspend - suspend callback 3521f4e7bd81SJoachim Eastwood * @dev: device pointer 3522732fdf0eSGiuseppe CAVALLARO * Description: this is the function to suspend the device and it is called 3523732fdf0eSGiuseppe CAVALLARO * by the platform driver to stop the network queue, release the resources, 3524732fdf0eSGiuseppe CAVALLARO * program the PMT register (for WoL), clean and release driver resources. 3525732fdf0eSGiuseppe CAVALLARO */ 3526f4e7bd81SJoachim Eastwood int stmmac_suspend(struct device *dev) 35277ac6653aSJeff Kirsher { 3528f4e7bd81SJoachim Eastwood struct net_device *ndev = dev_get_drvdata(dev); 35297ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 3530f8c5a875SGiuseppe CAVALLARO unsigned long flags; 35317ac6653aSJeff Kirsher 35327ac6653aSJeff Kirsher if (!ndev || !netif_running(ndev)) 35337ac6653aSJeff Kirsher return 0; 35347ac6653aSJeff Kirsher 3535d6d50c7eSPhilippe Reynes if (ndev->phydev) 3536d6d50c7eSPhilippe Reynes phy_stop(ndev->phydev); 3537102463b1SFrancesco Virlinzi 3538f8c5a875SGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 35397ac6653aSJeff Kirsher 35407ac6653aSJeff Kirsher netif_device_detach(ndev); 35417ac6653aSJeff Kirsher netif_stop_queue(ndev); 35427ac6653aSJeff Kirsher 35437ac6653aSJeff Kirsher napi_disable(&priv->napi); 35447ac6653aSJeff Kirsher 35457ac6653aSJeff Kirsher /* Stop TX/RX DMA */ 35467ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 35477ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 3548c24602efSGiuseppe CAVALLARO 35497ac6653aSJeff Kirsher /* Enable Power down mode by programming the PMT regs */ 355089f7f2cfSSrinivas Kandagatla if (device_may_wakeup(priv->device)) { 35517ed24bbeSVince Bridgers priv->hw->mac->pmt(priv->hw, priv->wolopts); 355289f7f2cfSSrinivas Kandagatla priv->irq_wake = 1; 355389f7f2cfSSrinivas Kandagatla } else { 3554bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 3555db88f10aSSrinivas Kandagatla pinctrl_pm_select_sleep_state(priv->device); 3556ba1377ffSGiuseppe CAVALLARO /* Disable clock in case of PWM is off */ 3557f573c0b9Sjpinto clk_disable(priv->plat->pclk); 3558f573c0b9Sjpinto clk_disable(priv->plat->stmmac_clk); 3559ba1377ffSGiuseppe CAVALLARO } 3560f8c5a875SGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 35612d871aa0SVince Bridgers 35622d871aa0SVince Bridgers priv->oldlink = 0; 3563bd00632cSLABBE Corentin priv->speed = SPEED_UNKNOWN; 3564bd00632cSLABBE Corentin priv->oldduplex = DUPLEX_UNKNOWN; 35657ac6653aSJeff Kirsher return 0; 35667ac6653aSJeff Kirsher } 3567b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_suspend); 35687ac6653aSJeff Kirsher 3569732fdf0eSGiuseppe CAVALLARO /** 3570732fdf0eSGiuseppe CAVALLARO * stmmac_resume - resume callback 3571f4e7bd81SJoachim Eastwood * @dev: device pointer 3572732fdf0eSGiuseppe CAVALLARO * Description: when resume this function is invoked to setup the DMA and CORE 3573732fdf0eSGiuseppe CAVALLARO * in a usable state. 3574732fdf0eSGiuseppe CAVALLARO */ 3575f4e7bd81SJoachim Eastwood int stmmac_resume(struct device *dev) 35767ac6653aSJeff Kirsher { 3577f4e7bd81SJoachim Eastwood struct net_device *ndev = dev_get_drvdata(dev); 35787ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 3579f8c5a875SGiuseppe CAVALLARO unsigned long flags; 35807ac6653aSJeff Kirsher 35817ac6653aSJeff Kirsher if (!netif_running(ndev)) 35827ac6653aSJeff Kirsher return 0; 35837ac6653aSJeff Kirsher 35847ac6653aSJeff Kirsher /* Power Down bit, into the PM register, is cleared 35857ac6653aSJeff Kirsher * automatically as soon as a magic packet or a Wake-up frame 35867ac6653aSJeff Kirsher * is received. Anyway, it's better to manually clear 35877ac6653aSJeff Kirsher * this bit because it can generate problems while resuming 3588ceb69499SGiuseppe CAVALLARO * from another devices (e.g. serial console). 3589ceb69499SGiuseppe CAVALLARO */ 3590623997fbSSrinivas Kandagatla if (device_may_wakeup(priv->device)) { 3591f55d84b0SVincent Palatin spin_lock_irqsave(&priv->lock, flags); 35927ed24bbeSVince Bridgers priv->hw->mac->pmt(priv->hw, 0); 3593f55d84b0SVincent Palatin spin_unlock_irqrestore(&priv->lock, flags); 359489f7f2cfSSrinivas Kandagatla priv->irq_wake = 0; 3595623997fbSSrinivas Kandagatla } else { 3596db88f10aSSrinivas Kandagatla pinctrl_pm_select_default_state(priv->device); 35978d45e42bSLABBE Corentin /* enable the clk previously disabled */ 3598f573c0b9Sjpinto clk_enable(priv->plat->stmmac_clk); 3599f573c0b9Sjpinto clk_enable(priv->plat->pclk); 3600623997fbSSrinivas Kandagatla /* reset the phy so that it's ready */ 3601623997fbSSrinivas Kandagatla if (priv->mii) 3602623997fbSSrinivas Kandagatla stmmac_mdio_reset(priv->mii); 3603623997fbSSrinivas Kandagatla } 36047ac6653aSJeff Kirsher 36057ac6653aSJeff Kirsher netif_device_attach(ndev); 36067ac6653aSJeff Kirsher 3607f55d84b0SVincent Palatin spin_lock_irqsave(&priv->lock, flags); 3608f55d84b0SVincent Palatin 3609ae79a639SGiuseppe CAVALLARO priv->cur_rx = 0; 3610ae79a639SGiuseppe CAVALLARO priv->dirty_rx = 0; 3611ae79a639SGiuseppe CAVALLARO priv->dirty_tx = 0; 3612ae79a639SGiuseppe CAVALLARO priv->cur_tx = 0; 3613f748be53SAlexandre TORGUE /* reset private mss value to force mss context settings at 3614f748be53SAlexandre TORGUE * next tso xmit (only used for gmac4). 3615f748be53SAlexandre TORGUE */ 3616f748be53SAlexandre TORGUE priv->mss = 0; 3617f748be53SAlexandre TORGUE 3618ae79a639SGiuseppe CAVALLARO stmmac_clear_descriptors(priv); 3619ae79a639SGiuseppe CAVALLARO 3620fe131929SHuacai Chen stmmac_hw_setup(ndev, false); 3621777da230SGiuseppe CAVALLARO stmmac_init_tx_coalesce(priv); 3622ac316c78SGiuseppe CAVALLARO stmmac_set_rx_mode(ndev); 36237ac6653aSJeff Kirsher 36247ac6653aSJeff Kirsher napi_enable(&priv->napi); 36257ac6653aSJeff Kirsher 36267ac6653aSJeff Kirsher netif_start_queue(ndev); 36277ac6653aSJeff Kirsher 3628f8c5a875SGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 3629102463b1SFrancesco Virlinzi 3630d6d50c7eSPhilippe Reynes if (ndev->phydev) 3631d6d50c7eSPhilippe Reynes phy_start(ndev->phydev); 3632102463b1SFrancesco Virlinzi 36337ac6653aSJeff Kirsher return 0; 36347ac6653aSJeff Kirsher } 3635b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_resume); 3636ba27ec66SGiuseppe CAVALLARO 36377ac6653aSJeff Kirsher #ifndef MODULE 36387ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str) 36397ac6653aSJeff Kirsher { 36407ac6653aSJeff Kirsher char *opt; 36417ac6653aSJeff Kirsher 36427ac6653aSJeff Kirsher if (!str || !*str) 36437ac6653aSJeff Kirsher return -EINVAL; 36447ac6653aSJeff Kirsher while ((opt = strsep(&str, ",")) != NULL) { 36457ac6653aSJeff Kirsher if (!strncmp(opt, "debug:", 6)) { 3646ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 6, 0, &debug)) 36477ac6653aSJeff Kirsher goto err; 36487ac6653aSJeff Kirsher } else if (!strncmp(opt, "phyaddr:", 8)) { 3649ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 8, 0, &phyaddr)) 36507ac6653aSJeff Kirsher goto err; 36517ac6653aSJeff Kirsher } else if (!strncmp(opt, "buf_sz:", 7)) { 3652ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 7, 0, &buf_sz)) 36537ac6653aSJeff Kirsher goto err; 36547ac6653aSJeff Kirsher } else if (!strncmp(opt, "tc:", 3)) { 3655ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 3, 0, &tc)) 36567ac6653aSJeff Kirsher goto err; 36577ac6653aSJeff Kirsher } else if (!strncmp(opt, "watchdog:", 9)) { 3658ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 9, 0, &watchdog)) 36597ac6653aSJeff Kirsher goto err; 36607ac6653aSJeff Kirsher } else if (!strncmp(opt, "flow_ctrl:", 10)) { 3661ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 10, 0, &flow_ctrl)) 36627ac6653aSJeff Kirsher goto err; 36637ac6653aSJeff Kirsher } else if (!strncmp(opt, "pause:", 6)) { 3664ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 6, 0, &pause)) 36657ac6653aSJeff Kirsher goto err; 3666506f669cSGiuseppe CAVALLARO } else if (!strncmp(opt, "eee_timer:", 10)) { 3667d765955dSGiuseppe CAVALLARO if (kstrtoint(opt + 10, 0, &eee_timer)) 3668d765955dSGiuseppe CAVALLARO goto err; 36694a7d666aSGiuseppe CAVALLARO } else if (!strncmp(opt, "chain_mode:", 11)) { 36704a7d666aSGiuseppe CAVALLARO if (kstrtoint(opt + 11, 0, &chain_mode)) 36714a7d666aSGiuseppe CAVALLARO goto err; 36727ac6653aSJeff Kirsher } 36737ac6653aSJeff Kirsher } 36747ac6653aSJeff Kirsher return 0; 36757ac6653aSJeff Kirsher 36767ac6653aSJeff Kirsher err: 36777ac6653aSJeff Kirsher pr_err("%s: ERROR broken module parameter conversion", __func__); 36787ac6653aSJeff Kirsher return -EINVAL; 36797ac6653aSJeff Kirsher } 36807ac6653aSJeff Kirsher 36817ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt); 3682ceb69499SGiuseppe CAVALLARO #endif /* MODULE */ 36836fc0d0f2SGiuseppe Cavallaro 3684466c5ac8SMathieu Olivari static int __init stmmac_init(void) 3685466c5ac8SMathieu Olivari { 3686466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS 3687466c5ac8SMathieu Olivari /* Create debugfs main directory if it doesn't exist yet */ 3688466c5ac8SMathieu Olivari if (!stmmac_fs_dir) { 3689466c5ac8SMathieu Olivari stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL); 3690466c5ac8SMathieu Olivari 3691466c5ac8SMathieu Olivari if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) { 3692466c5ac8SMathieu Olivari pr_err("ERROR %s, debugfs create directory failed\n", 3693466c5ac8SMathieu Olivari STMMAC_RESOURCE_NAME); 3694466c5ac8SMathieu Olivari 3695466c5ac8SMathieu Olivari return -ENOMEM; 3696466c5ac8SMathieu Olivari } 3697466c5ac8SMathieu Olivari } 3698466c5ac8SMathieu Olivari #endif 3699466c5ac8SMathieu Olivari 3700466c5ac8SMathieu Olivari return 0; 3701466c5ac8SMathieu Olivari } 3702466c5ac8SMathieu Olivari 3703466c5ac8SMathieu Olivari static void __exit stmmac_exit(void) 3704466c5ac8SMathieu Olivari { 3705466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS 3706466c5ac8SMathieu Olivari debugfs_remove_recursive(stmmac_fs_dir); 3707466c5ac8SMathieu Olivari #endif 3708466c5ac8SMathieu Olivari } 3709466c5ac8SMathieu Olivari 3710466c5ac8SMathieu Olivari module_init(stmmac_init) 3711466c5ac8SMathieu Olivari module_exit(stmmac_exit) 3712466c5ac8SMathieu Olivari 37136fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver"); 37146fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); 37156fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL"); 3716