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 You should have received a copy of the GNU General Public License along with 177ac6653aSJeff Kirsher this program; if not, write to the Free Software Foundation, Inc., 187ac6653aSJeff Kirsher 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 197ac6653aSJeff Kirsher 207ac6653aSJeff Kirsher The full GNU General Public License is included in this distribution in 217ac6653aSJeff Kirsher the file called "COPYING". 227ac6653aSJeff Kirsher 237ac6653aSJeff Kirsher Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 247ac6653aSJeff Kirsher 257ac6653aSJeff Kirsher Documentation available at: 267ac6653aSJeff Kirsher http://www.stlinux.com 277ac6653aSJeff Kirsher Support available at: 287ac6653aSJeff Kirsher https://bugzilla.stlinux.com/ 297ac6653aSJeff Kirsher *******************************************************************************/ 307ac6653aSJeff Kirsher 316a81c26fSViresh Kumar #include <linux/clk.h> 327ac6653aSJeff Kirsher #include <linux/kernel.h> 337ac6653aSJeff Kirsher #include <linux/interrupt.h> 347ac6653aSJeff Kirsher #include <linux/ip.h> 357ac6653aSJeff Kirsher #include <linux/tcp.h> 367ac6653aSJeff Kirsher #include <linux/skbuff.h> 377ac6653aSJeff Kirsher #include <linux/ethtool.h> 387ac6653aSJeff Kirsher #include <linux/if_ether.h> 397ac6653aSJeff Kirsher #include <linux/crc32.h> 407ac6653aSJeff Kirsher #include <linux/mii.h> 4101789349SJiri Pirko #include <linux/if.h> 427ac6653aSJeff Kirsher #include <linux/if_vlan.h> 437ac6653aSJeff Kirsher #include <linux/dma-mapping.h> 447ac6653aSJeff Kirsher #include <linux/slab.h> 457ac6653aSJeff Kirsher #include <linux/prefetch.h> 46db88f10aSSrinivas Kandagatla #include <linux/pinctrl/consumer.h> 4750fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 487ac29055SGiuseppe CAVALLARO #include <linux/debugfs.h> 497ac29055SGiuseppe CAVALLARO #include <linux/seq_file.h> 5050fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */ 51891434b1SRayagond Kokatanur #include <linux/net_tstamp.h> 52891434b1SRayagond Kokatanur #include "stmmac_ptp.h" 53286a8372SGiuseppe CAVALLARO #include "stmmac.h" 54c5e4ddbdSChen-Yu Tsai #include <linux/reset.h> 557ac6653aSJeff Kirsher 567ac6653aSJeff Kirsher #define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x) 577ac6653aSJeff Kirsher 587ac6653aSJeff Kirsher /* Module parameters */ 5932ceabcaSGiuseppe CAVALLARO #define TX_TIMEO 5000 607ac6653aSJeff Kirsher static int watchdog = TX_TIMEO; 617ac6653aSJeff Kirsher module_param(watchdog, int, S_IRUGO | S_IWUSR); 6232ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(watchdog, "Transmit timeout in milliseconds (default 5s)"); 637ac6653aSJeff Kirsher 6432ceabcaSGiuseppe CAVALLARO static int debug = -1; 657ac6653aSJeff Kirsher module_param(debug, int, S_IRUGO | S_IWUSR); 6632ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)"); 677ac6653aSJeff Kirsher 6847d1f71fSstephen hemminger static int phyaddr = -1; 697ac6653aSJeff Kirsher module_param(phyaddr, int, S_IRUGO); 707ac6653aSJeff Kirsher MODULE_PARM_DESC(phyaddr, "Physical device address"); 717ac6653aSJeff Kirsher 727ac6653aSJeff Kirsher #define DMA_TX_SIZE 256 737ac6653aSJeff Kirsher static int dma_txsize = DMA_TX_SIZE; 747ac6653aSJeff Kirsher module_param(dma_txsize, int, S_IRUGO | S_IWUSR); 757ac6653aSJeff Kirsher MODULE_PARM_DESC(dma_txsize, "Number of descriptors in the TX list"); 767ac6653aSJeff Kirsher 777ac6653aSJeff Kirsher #define DMA_RX_SIZE 256 787ac6653aSJeff Kirsher static int dma_rxsize = DMA_RX_SIZE; 797ac6653aSJeff Kirsher module_param(dma_rxsize, int, S_IRUGO | S_IWUSR); 807ac6653aSJeff Kirsher MODULE_PARM_DESC(dma_rxsize, "Number of descriptors in the RX list"); 817ac6653aSJeff Kirsher 827ac6653aSJeff Kirsher static int flow_ctrl = FLOW_OFF; 837ac6653aSJeff Kirsher module_param(flow_ctrl, int, S_IRUGO | S_IWUSR); 847ac6653aSJeff Kirsher MODULE_PARM_DESC(flow_ctrl, "Flow control ability [on/off]"); 857ac6653aSJeff Kirsher 867ac6653aSJeff Kirsher static int pause = PAUSE_TIME; 877ac6653aSJeff Kirsher module_param(pause, int, S_IRUGO | S_IWUSR); 887ac6653aSJeff Kirsher MODULE_PARM_DESC(pause, "Flow Control Pause Time"); 897ac6653aSJeff Kirsher 907ac6653aSJeff Kirsher #define TC_DEFAULT 64 917ac6653aSJeff Kirsher static int tc = TC_DEFAULT; 927ac6653aSJeff Kirsher module_param(tc, int, S_IRUGO | S_IWUSR); 937ac6653aSJeff Kirsher MODULE_PARM_DESC(tc, "DMA threshold control value"); 947ac6653aSJeff Kirsher 95d916701cSGiuseppe CAVALLARO #define DEFAULT_BUFSIZE 1536 96d916701cSGiuseppe CAVALLARO static int buf_sz = DEFAULT_BUFSIZE; 977ac6653aSJeff Kirsher module_param(buf_sz, int, S_IRUGO | S_IWUSR); 987ac6653aSJeff Kirsher MODULE_PARM_DESC(buf_sz, "DMA buffer size"); 997ac6653aSJeff Kirsher 1007ac6653aSJeff Kirsher static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE | 1017ac6653aSJeff Kirsher NETIF_MSG_LINK | NETIF_MSG_IFUP | 1027ac6653aSJeff Kirsher NETIF_MSG_IFDOWN | NETIF_MSG_TIMER); 1037ac6653aSJeff Kirsher 104d765955dSGiuseppe CAVALLARO #define STMMAC_DEFAULT_LPI_TIMER 1000 105d765955dSGiuseppe CAVALLARO static int eee_timer = STMMAC_DEFAULT_LPI_TIMER; 106d765955dSGiuseppe CAVALLARO module_param(eee_timer, int, S_IRUGO | S_IWUSR); 107d765955dSGiuseppe CAVALLARO MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec"); 108f5351ef7SGiuseppe CAVALLARO #define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x)) 109d765955dSGiuseppe CAVALLARO 1104a7d666aSGiuseppe CAVALLARO /* By default the driver will use the ring mode to manage tx and rx descriptors 1114a7d666aSGiuseppe CAVALLARO * but passing this value so user can force to use the chain instead of the ring 1124a7d666aSGiuseppe CAVALLARO */ 1134a7d666aSGiuseppe CAVALLARO static unsigned int chain_mode; 1144a7d666aSGiuseppe CAVALLARO module_param(chain_mode, int, S_IRUGO); 1154a7d666aSGiuseppe CAVALLARO MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode"); 1164a7d666aSGiuseppe CAVALLARO 1177ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id); 1187ac6653aSJeff Kirsher 11950fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 120bfab27a1SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev); 121bfab27a1SGiuseppe CAVALLARO static void stmmac_exit_fs(void); 122bfab27a1SGiuseppe CAVALLARO #endif 123bfab27a1SGiuseppe CAVALLARO 1249125cdd1SGiuseppe CAVALLARO #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x)) 1259125cdd1SGiuseppe CAVALLARO 1267ac6653aSJeff Kirsher /** 1277ac6653aSJeff Kirsher * stmmac_verify_args - verify the driver parameters. 128732fdf0eSGiuseppe CAVALLARO * Description: it checks the driver parameters and set a default in case of 129732fdf0eSGiuseppe CAVALLARO * errors. 1307ac6653aSJeff Kirsher */ 1317ac6653aSJeff Kirsher static void stmmac_verify_args(void) 1327ac6653aSJeff Kirsher { 1337ac6653aSJeff Kirsher if (unlikely(watchdog < 0)) 1347ac6653aSJeff Kirsher watchdog = TX_TIMEO; 1357ac6653aSJeff Kirsher if (unlikely(dma_rxsize < 0)) 1367ac6653aSJeff Kirsher dma_rxsize = DMA_RX_SIZE; 1377ac6653aSJeff Kirsher if (unlikely(dma_txsize < 0)) 1387ac6653aSJeff Kirsher dma_txsize = DMA_TX_SIZE; 139d916701cSGiuseppe CAVALLARO if (unlikely((buf_sz < DEFAULT_BUFSIZE) || (buf_sz > BUF_SIZE_16KiB))) 140d916701cSGiuseppe CAVALLARO buf_sz = DEFAULT_BUFSIZE; 1417ac6653aSJeff Kirsher if (unlikely(flow_ctrl > 1)) 1427ac6653aSJeff Kirsher flow_ctrl = FLOW_AUTO; 1437ac6653aSJeff Kirsher else if (likely(flow_ctrl < 0)) 1447ac6653aSJeff Kirsher flow_ctrl = FLOW_OFF; 1457ac6653aSJeff Kirsher if (unlikely((pause < 0) || (pause > 0xffff))) 1467ac6653aSJeff Kirsher pause = PAUSE_TIME; 147d765955dSGiuseppe CAVALLARO if (eee_timer < 0) 148d765955dSGiuseppe CAVALLARO eee_timer = STMMAC_DEFAULT_LPI_TIMER; 1497ac6653aSJeff Kirsher } 1507ac6653aSJeff Kirsher 15132ceabcaSGiuseppe CAVALLARO /** 15232ceabcaSGiuseppe CAVALLARO * stmmac_clk_csr_set - dynamically set the MDC clock 15332ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 15432ceabcaSGiuseppe CAVALLARO * Description: this is to dynamically set the MDC clock according to the csr 15532ceabcaSGiuseppe CAVALLARO * clock input. 15632ceabcaSGiuseppe CAVALLARO * Note: 15732ceabcaSGiuseppe CAVALLARO * If a specific clk_csr value is passed from the platform 15832ceabcaSGiuseppe CAVALLARO * this means that the CSR Clock Range selection cannot be 15932ceabcaSGiuseppe CAVALLARO * changed at run-time and it is fixed (as reported in the driver 16032ceabcaSGiuseppe CAVALLARO * documentation). Viceversa the driver will try to set the MDC 16132ceabcaSGiuseppe CAVALLARO * clock dynamically according to the actual clock input. 16232ceabcaSGiuseppe CAVALLARO */ 163cd7201f4SGiuseppe CAVALLARO static void stmmac_clk_csr_set(struct stmmac_priv *priv) 164cd7201f4SGiuseppe CAVALLARO { 165cd7201f4SGiuseppe CAVALLARO u32 clk_rate; 166cd7201f4SGiuseppe CAVALLARO 167cd7201f4SGiuseppe CAVALLARO clk_rate = clk_get_rate(priv->stmmac_clk); 168cd7201f4SGiuseppe CAVALLARO 169cd7201f4SGiuseppe CAVALLARO /* Platform provided default clk_csr would be assumed valid 170ceb69499SGiuseppe CAVALLARO * for all other cases except for the below mentioned ones. 171ceb69499SGiuseppe CAVALLARO * For values higher than the IEEE 802.3 specified frequency 172ceb69499SGiuseppe CAVALLARO * we can not estimate the proper divider as it is not known 173ceb69499SGiuseppe CAVALLARO * the frequency of clk_csr_i. So we do not change the default 174ceb69499SGiuseppe CAVALLARO * divider. 175ceb69499SGiuseppe CAVALLARO */ 176cd7201f4SGiuseppe CAVALLARO if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) { 177cd7201f4SGiuseppe CAVALLARO if (clk_rate < CSR_F_35M) 178cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_20_35M; 179cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M)) 180cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_35_60M; 181cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M)) 182cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_60_100M; 183cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M)) 184cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_100_150M; 185cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M)) 186cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_150_250M; 187cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M)) 188cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_250_300M; 189ceb69499SGiuseppe CAVALLARO } 190cd7201f4SGiuseppe CAVALLARO } 191cd7201f4SGiuseppe CAVALLARO 1927ac6653aSJeff Kirsher static void print_pkt(unsigned char *buf, int len) 1937ac6653aSJeff Kirsher { 194424c4f78SAndy Shevchenko pr_debug("len = %d byte, buf addr: 0x%p\n", len, buf); 195424c4f78SAndy Shevchenko print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); 1967ac6653aSJeff Kirsher } 1977ac6653aSJeff Kirsher 1987ac6653aSJeff Kirsher /* minimum number of free TX descriptors required to wake up TX process */ 1997ac6653aSJeff Kirsher #define STMMAC_TX_THRESH(x) (x->dma_tx_size/4) 2007ac6653aSJeff Kirsher 2017ac6653aSJeff Kirsher static inline u32 stmmac_tx_avail(struct stmmac_priv *priv) 2027ac6653aSJeff Kirsher { 2037ac6653aSJeff Kirsher return priv->dirty_tx + priv->dma_tx_size - priv->cur_tx - 1; 2047ac6653aSJeff Kirsher } 2057ac6653aSJeff Kirsher 20632ceabcaSGiuseppe CAVALLARO /** 207732fdf0eSGiuseppe CAVALLARO * stmmac_hw_fix_mac_speed - callback for speed selection 20832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 20932ceabcaSGiuseppe CAVALLARO * Description: on some platforms (e.g. ST), some HW system configuraton 21032ceabcaSGiuseppe CAVALLARO * registers have to be set according to the link speed negotiated. 2117ac6653aSJeff Kirsher */ 2127ac6653aSJeff Kirsher static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv) 2137ac6653aSJeff Kirsher { 2147ac6653aSJeff Kirsher struct phy_device *phydev = priv->phydev; 2157ac6653aSJeff Kirsher 2167ac6653aSJeff Kirsher if (likely(priv->plat->fix_mac_speed)) 217ceb69499SGiuseppe CAVALLARO priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed); 2187ac6653aSJeff Kirsher } 2197ac6653aSJeff Kirsher 22032ceabcaSGiuseppe CAVALLARO /** 221732fdf0eSGiuseppe CAVALLARO * stmmac_enable_eee_mode - check and enter in LPI mode 22232ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 223732fdf0eSGiuseppe CAVALLARO * Description: this function is to verify and enter in LPI mode in case of 224732fdf0eSGiuseppe CAVALLARO * EEE. 22532ceabcaSGiuseppe CAVALLARO */ 226d765955dSGiuseppe CAVALLARO static void stmmac_enable_eee_mode(struct stmmac_priv *priv) 227d765955dSGiuseppe CAVALLARO { 228d765955dSGiuseppe CAVALLARO /* Check and enter in LPI mode */ 229d765955dSGiuseppe CAVALLARO if ((priv->dirty_tx == priv->cur_tx) && 230d765955dSGiuseppe CAVALLARO (priv->tx_path_in_lpi_mode == false)) 2317ed24bbeSVince Bridgers priv->hw->mac->set_eee_mode(priv->hw); 232d765955dSGiuseppe CAVALLARO } 233d765955dSGiuseppe CAVALLARO 23432ceabcaSGiuseppe CAVALLARO /** 235732fdf0eSGiuseppe CAVALLARO * stmmac_disable_eee_mode - disable and exit from LPI mode 23632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 23732ceabcaSGiuseppe CAVALLARO * Description: this function is to exit and disable EEE in case of 23832ceabcaSGiuseppe CAVALLARO * LPI state is true. This is called by the xmit. 23932ceabcaSGiuseppe CAVALLARO */ 240d765955dSGiuseppe CAVALLARO void stmmac_disable_eee_mode(struct stmmac_priv *priv) 241d765955dSGiuseppe CAVALLARO { 2427ed24bbeSVince Bridgers priv->hw->mac->reset_eee_mode(priv->hw); 243d765955dSGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 244d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = false; 245d765955dSGiuseppe CAVALLARO } 246d765955dSGiuseppe CAVALLARO 247d765955dSGiuseppe CAVALLARO /** 248732fdf0eSGiuseppe CAVALLARO * stmmac_eee_ctrl_timer - EEE TX SW timer. 249d765955dSGiuseppe CAVALLARO * @arg : data hook 250d765955dSGiuseppe CAVALLARO * Description: 25132ceabcaSGiuseppe CAVALLARO * if there is no data transfer and if we are not in LPI state, 252d765955dSGiuseppe CAVALLARO * then MAC Transmitter can be moved to LPI state. 253d765955dSGiuseppe CAVALLARO */ 254d765955dSGiuseppe CAVALLARO static void stmmac_eee_ctrl_timer(unsigned long arg) 255d765955dSGiuseppe CAVALLARO { 256d765955dSGiuseppe CAVALLARO struct stmmac_priv *priv = (struct stmmac_priv *)arg; 257d765955dSGiuseppe CAVALLARO 258d765955dSGiuseppe CAVALLARO stmmac_enable_eee_mode(priv); 259f5351ef7SGiuseppe CAVALLARO mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); 260d765955dSGiuseppe CAVALLARO } 261d765955dSGiuseppe CAVALLARO 262d765955dSGiuseppe CAVALLARO /** 263732fdf0eSGiuseppe CAVALLARO * stmmac_eee_init - init EEE 26432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 265d765955dSGiuseppe CAVALLARO * Description: 266732fdf0eSGiuseppe CAVALLARO * if the GMAC supports the EEE (from the HW cap reg) and the phy device 267732fdf0eSGiuseppe CAVALLARO * can also manage EEE, this function enable the LPI state and start related 268732fdf0eSGiuseppe CAVALLARO * timer. 269d765955dSGiuseppe CAVALLARO */ 270d765955dSGiuseppe CAVALLARO bool stmmac_eee_init(struct stmmac_priv *priv) 271d765955dSGiuseppe CAVALLARO { 27256b88c25SGiuseppe CAVALLARO char *phy_bus_name = priv->plat->phy_bus_name; 2734741cf9cSGiuseppe CAVALLARO unsigned long flags; 274d765955dSGiuseppe CAVALLARO bool ret = false; 275d765955dSGiuseppe CAVALLARO 276f5351ef7SGiuseppe CAVALLARO /* Using PCS we cannot dial with the phy registers at this stage 277f5351ef7SGiuseppe CAVALLARO * so we do not support extra feature like EEE. 278f5351ef7SGiuseppe CAVALLARO */ 279f5351ef7SGiuseppe CAVALLARO if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) || 280f5351ef7SGiuseppe CAVALLARO (priv->pcs == STMMAC_PCS_RTBI)) 281f5351ef7SGiuseppe CAVALLARO goto out; 282f5351ef7SGiuseppe CAVALLARO 28356b88c25SGiuseppe CAVALLARO /* Never init EEE in case of a switch is attached */ 28456b88c25SGiuseppe CAVALLARO if (phy_bus_name && (!strcmp(phy_bus_name, "fixed"))) 28556b88c25SGiuseppe CAVALLARO goto out; 28656b88c25SGiuseppe CAVALLARO 287d765955dSGiuseppe CAVALLARO /* MAC core supports the EEE feature. */ 288d765955dSGiuseppe CAVALLARO if (priv->dma_cap.eee) { 28983bf79b6SGiuseppe CAVALLARO int tx_lpi_timer = priv->tx_lpi_timer; 290d765955dSGiuseppe CAVALLARO 29183bf79b6SGiuseppe CAVALLARO /* Check if the PHY supports EEE */ 29283bf79b6SGiuseppe CAVALLARO if (phy_init_eee(priv->phydev, 1)) { 29383bf79b6SGiuseppe CAVALLARO /* To manage at run-time if the EEE cannot be supported 29483bf79b6SGiuseppe CAVALLARO * anymore (for example because the lp caps have been 29583bf79b6SGiuseppe CAVALLARO * changed). 29683bf79b6SGiuseppe CAVALLARO * In that case the driver disable own timers. 29783bf79b6SGiuseppe CAVALLARO */ 2984741cf9cSGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 29983bf79b6SGiuseppe CAVALLARO if (priv->eee_active) { 30083bf79b6SGiuseppe CAVALLARO pr_debug("stmmac: disable EEE\n"); 30183bf79b6SGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 3027ed24bbeSVince Bridgers priv->hw->mac->set_eee_timer(priv->hw, 0, 30383bf79b6SGiuseppe CAVALLARO tx_lpi_timer); 30483bf79b6SGiuseppe CAVALLARO } 30583bf79b6SGiuseppe CAVALLARO priv->eee_active = 0; 3064741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 30783bf79b6SGiuseppe CAVALLARO goto out; 30883bf79b6SGiuseppe CAVALLARO } 30983bf79b6SGiuseppe CAVALLARO /* Activate the EEE and start timers */ 3104741cf9cSGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 311f5351ef7SGiuseppe CAVALLARO if (!priv->eee_active) { 312d765955dSGiuseppe CAVALLARO priv->eee_active = 1; 313d765955dSGiuseppe CAVALLARO init_timer(&priv->eee_ctrl_timer); 314d765955dSGiuseppe CAVALLARO priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer; 315d765955dSGiuseppe CAVALLARO priv->eee_ctrl_timer.data = (unsigned long)priv; 316f5351ef7SGiuseppe CAVALLARO priv->eee_ctrl_timer.expires = STMMAC_LPI_T(eee_timer); 317d765955dSGiuseppe CAVALLARO add_timer(&priv->eee_ctrl_timer); 318d765955dSGiuseppe CAVALLARO 3197ed24bbeSVince Bridgers priv->hw->mac->set_eee_timer(priv->hw, 320f5351ef7SGiuseppe CAVALLARO STMMAC_DEFAULT_LIT_LS, 32183bf79b6SGiuseppe CAVALLARO tx_lpi_timer); 32271965352SGiuseppe CAVALLARO } 323f5351ef7SGiuseppe CAVALLARO /* Set HW EEE according to the speed */ 32471965352SGiuseppe CAVALLARO priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link); 325d765955dSGiuseppe CAVALLARO 326d765955dSGiuseppe CAVALLARO ret = true; 3274741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 3284741cf9cSGiuseppe CAVALLARO 3294741cf9cSGiuseppe CAVALLARO pr_debug("stmmac: Energy-Efficient Ethernet initialized\n"); 330d765955dSGiuseppe CAVALLARO } 331d765955dSGiuseppe CAVALLARO out: 332d765955dSGiuseppe CAVALLARO return ret; 333d765955dSGiuseppe CAVALLARO } 334d765955dSGiuseppe CAVALLARO 335732fdf0eSGiuseppe CAVALLARO /* stmmac_get_tx_hwtstamp - get HW TX timestamps 33632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 337891434b1SRayagond Kokatanur * @entry : descriptor index to be used. 338891434b1SRayagond Kokatanur * @skb : the socket buffer 339891434b1SRayagond Kokatanur * Description : 340891434b1SRayagond Kokatanur * This function will read timestamp from the descriptor & pass it to stack. 341891434b1SRayagond Kokatanur * and also perform some sanity checks. 342891434b1SRayagond Kokatanur */ 343891434b1SRayagond Kokatanur static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, 344ceb69499SGiuseppe CAVALLARO unsigned int entry, struct sk_buff *skb) 345891434b1SRayagond Kokatanur { 346891434b1SRayagond Kokatanur struct skb_shared_hwtstamps shhwtstamp; 347891434b1SRayagond Kokatanur u64 ns; 348891434b1SRayagond Kokatanur void *desc = NULL; 349891434b1SRayagond Kokatanur 350891434b1SRayagond Kokatanur if (!priv->hwts_tx_en) 351891434b1SRayagond Kokatanur return; 352891434b1SRayagond Kokatanur 353ceb69499SGiuseppe CAVALLARO /* exit if skb doesn't support hw tstamp */ 35475e4364fSdamuzi000 if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))) 355891434b1SRayagond Kokatanur return; 356891434b1SRayagond Kokatanur 357891434b1SRayagond Kokatanur if (priv->adv_ts) 358891434b1SRayagond Kokatanur desc = (priv->dma_etx + entry); 359891434b1SRayagond Kokatanur else 360891434b1SRayagond Kokatanur desc = (priv->dma_tx + entry); 361891434b1SRayagond Kokatanur 362891434b1SRayagond Kokatanur /* check tx tstamp status */ 363891434b1SRayagond Kokatanur if (!priv->hw->desc->get_tx_timestamp_status((struct dma_desc *)desc)) 364891434b1SRayagond Kokatanur return; 365891434b1SRayagond Kokatanur 366891434b1SRayagond Kokatanur /* get the valid tstamp */ 367891434b1SRayagond Kokatanur ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts); 368891434b1SRayagond Kokatanur 369891434b1SRayagond Kokatanur memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); 370891434b1SRayagond Kokatanur shhwtstamp.hwtstamp = ns_to_ktime(ns); 371891434b1SRayagond Kokatanur /* pass tstamp to stack */ 372891434b1SRayagond Kokatanur skb_tstamp_tx(skb, &shhwtstamp); 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 379891434b1SRayagond Kokatanur * @entry : descriptor index to be used. 380891434b1SRayagond Kokatanur * @skb : the socket buffer 381891434b1SRayagond Kokatanur * Description : 382891434b1SRayagond Kokatanur * This function will read received packet's timestamp from the descriptor 383891434b1SRayagond Kokatanur * and pass it to stack. It also perform some sanity checks. 384891434b1SRayagond Kokatanur */ 385891434b1SRayagond Kokatanur static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, 386ceb69499SGiuseppe CAVALLARO unsigned int entry, struct sk_buff *skb) 387891434b1SRayagond Kokatanur { 388891434b1SRayagond Kokatanur struct skb_shared_hwtstamps *shhwtstamp = NULL; 389891434b1SRayagond Kokatanur u64 ns; 390891434b1SRayagond Kokatanur void *desc = NULL; 391891434b1SRayagond Kokatanur 392891434b1SRayagond Kokatanur if (!priv->hwts_rx_en) 393891434b1SRayagond Kokatanur return; 394891434b1SRayagond Kokatanur 395891434b1SRayagond Kokatanur if (priv->adv_ts) 396891434b1SRayagond Kokatanur desc = (priv->dma_erx + entry); 397891434b1SRayagond Kokatanur else 398891434b1SRayagond Kokatanur desc = (priv->dma_rx + entry); 399891434b1SRayagond Kokatanur 400ceb69499SGiuseppe CAVALLARO /* exit if rx tstamp is not valid */ 401891434b1SRayagond Kokatanur if (!priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts)) 402891434b1SRayagond Kokatanur return; 403891434b1SRayagond Kokatanur 404891434b1SRayagond Kokatanur /* get valid tstamp */ 405891434b1SRayagond Kokatanur ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts); 406891434b1SRayagond Kokatanur shhwtstamp = skb_hwtstamps(skb); 407891434b1SRayagond Kokatanur memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); 408891434b1SRayagond Kokatanur shhwtstamp->hwtstamp = ns_to_ktime(ns); 409891434b1SRayagond Kokatanur } 410891434b1SRayagond Kokatanur 411891434b1SRayagond Kokatanur /** 412891434b1SRayagond Kokatanur * stmmac_hwtstamp_ioctl - control hardware timestamping. 413891434b1SRayagond Kokatanur * @dev: device pointer. 414891434b1SRayagond Kokatanur * @ifr: An IOCTL specefic structure, that can contain a pointer to 415891434b1SRayagond Kokatanur * a proprietary structure used to pass information to the driver. 416891434b1SRayagond Kokatanur * Description: 417891434b1SRayagond Kokatanur * This function configures the MAC to enable/disable both outgoing(TX) 418891434b1SRayagond Kokatanur * and incoming(RX) packets time stamping based on user input. 419891434b1SRayagond Kokatanur * Return Value: 420891434b1SRayagond Kokatanur * 0 on success and an appropriate -ve integer on failure. 421891434b1SRayagond Kokatanur */ 422891434b1SRayagond Kokatanur static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) 423891434b1SRayagond Kokatanur { 424891434b1SRayagond Kokatanur struct stmmac_priv *priv = netdev_priv(dev); 425891434b1SRayagond Kokatanur struct hwtstamp_config config; 426891434b1SRayagond Kokatanur struct timespec now; 427891434b1SRayagond Kokatanur u64 temp = 0; 428891434b1SRayagond Kokatanur u32 ptp_v2 = 0; 429891434b1SRayagond Kokatanur u32 tstamp_all = 0; 430891434b1SRayagond Kokatanur u32 ptp_over_ipv4_udp = 0; 431891434b1SRayagond Kokatanur u32 ptp_over_ipv6_udp = 0; 432891434b1SRayagond Kokatanur u32 ptp_over_ethernet = 0; 433891434b1SRayagond Kokatanur u32 snap_type_sel = 0; 434891434b1SRayagond Kokatanur u32 ts_master_en = 0; 435891434b1SRayagond Kokatanur u32 ts_event_en = 0; 436891434b1SRayagond Kokatanur u32 value = 0; 437891434b1SRayagond Kokatanur 438891434b1SRayagond Kokatanur if (!(priv->dma_cap.time_stamp || priv->adv_ts)) { 439891434b1SRayagond Kokatanur netdev_alert(priv->dev, "No support for HW time stamping\n"); 440891434b1SRayagond Kokatanur priv->hwts_tx_en = 0; 441891434b1SRayagond Kokatanur priv->hwts_rx_en = 0; 442891434b1SRayagond Kokatanur 443891434b1SRayagond Kokatanur return -EOPNOTSUPP; 444891434b1SRayagond Kokatanur } 445891434b1SRayagond Kokatanur 446891434b1SRayagond Kokatanur if (copy_from_user(&config, ifr->ifr_data, 447891434b1SRayagond Kokatanur sizeof(struct hwtstamp_config))) 448891434b1SRayagond Kokatanur return -EFAULT; 449891434b1SRayagond Kokatanur 450891434b1SRayagond Kokatanur pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n", 451891434b1SRayagond Kokatanur __func__, config.flags, config.tx_type, config.rx_filter); 452891434b1SRayagond Kokatanur 453891434b1SRayagond Kokatanur /* reserved for future extensions */ 454891434b1SRayagond Kokatanur if (config.flags) 455891434b1SRayagond Kokatanur return -EINVAL; 456891434b1SRayagond Kokatanur 4575f3da328SBen Hutchings if (config.tx_type != HWTSTAMP_TX_OFF && 4585f3da328SBen Hutchings config.tx_type != HWTSTAMP_TX_ON) 459891434b1SRayagond Kokatanur return -ERANGE; 460891434b1SRayagond Kokatanur 461891434b1SRayagond Kokatanur if (priv->adv_ts) { 462891434b1SRayagond Kokatanur switch (config.rx_filter) { 463891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_NONE: 464ceb69499SGiuseppe CAVALLARO /* time stamp no incoming packet at all */ 465891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_NONE; 466891434b1SRayagond Kokatanur break; 467891434b1SRayagond Kokatanur 468891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 469ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, any kind of event packet */ 470891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 471891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 472891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 473891434b1SRayagond Kokatanur 474891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 475891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 476891434b1SRayagond Kokatanur break; 477891434b1SRayagond Kokatanur 478891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 479ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, Sync packet */ 480891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; 481891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 482891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 483891434b1SRayagond Kokatanur 484891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 485891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 486891434b1SRayagond Kokatanur break; 487891434b1SRayagond Kokatanur 488891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 489ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, Delay_req packet */ 490891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; 491891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 492891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 493891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 494891434b1SRayagond Kokatanur 495891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 496891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 497891434b1SRayagond Kokatanur break; 498891434b1SRayagond Kokatanur 499891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 500ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, any kind of event packet */ 501891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; 502891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 503891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 504891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 505891434b1SRayagond Kokatanur 506891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 507891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 508891434b1SRayagond Kokatanur break; 509891434b1SRayagond Kokatanur 510891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 511ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, Sync packet */ 512891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC; 513891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 514891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 515891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 516891434b1SRayagond Kokatanur 517891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 518891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 519891434b1SRayagond Kokatanur break; 520891434b1SRayagond Kokatanur 521891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 522ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, Delay_req packet */ 523891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ; 524891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 525891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 526891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 527891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 528891434b1SRayagond Kokatanur 529891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 530891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 531891434b1SRayagond Kokatanur break; 532891434b1SRayagond Kokatanur 533891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_EVENT: 534ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1 any layer, any kind of event packet */ 535891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 536891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 537891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 538891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 539891434b1SRayagond Kokatanur 540891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 541891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 542891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 543891434b1SRayagond Kokatanur break; 544891434b1SRayagond Kokatanur 545891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_SYNC: 546ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1, any layer, Sync packet */ 547891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC; 548891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 549891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 550891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 551891434b1SRayagond Kokatanur 552891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 553891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 554891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 555891434b1SRayagond Kokatanur break; 556891434b1SRayagond Kokatanur 557891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 558ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1, any layer, Delay_req packet */ 559891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ; 560891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 561891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 562891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 563891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 564891434b1SRayagond Kokatanur 565891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 566891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 567891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 568891434b1SRayagond Kokatanur break; 569891434b1SRayagond Kokatanur 570891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_ALL: 571ceb69499SGiuseppe CAVALLARO /* time stamp any incoming packet */ 572891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_ALL; 573891434b1SRayagond Kokatanur tstamp_all = PTP_TCR_TSENALL; 574891434b1SRayagond Kokatanur break; 575891434b1SRayagond Kokatanur 576891434b1SRayagond Kokatanur default: 577891434b1SRayagond Kokatanur return -ERANGE; 578891434b1SRayagond Kokatanur } 579891434b1SRayagond Kokatanur } else { 580891434b1SRayagond Kokatanur switch (config.rx_filter) { 581891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_NONE: 582891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_NONE; 583891434b1SRayagond Kokatanur break; 584891434b1SRayagond Kokatanur default: 585891434b1SRayagond Kokatanur /* PTP v1, UDP, any kind of event packet */ 586891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 587891434b1SRayagond Kokatanur break; 588891434b1SRayagond Kokatanur } 589891434b1SRayagond Kokatanur } 590891434b1SRayagond Kokatanur priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1); 5915f3da328SBen Hutchings priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON; 592891434b1SRayagond Kokatanur 593891434b1SRayagond Kokatanur if (!priv->hwts_tx_en && !priv->hwts_rx_en) 594891434b1SRayagond Kokatanur priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0); 595891434b1SRayagond Kokatanur else { 596891434b1SRayagond Kokatanur value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR | 597891434b1SRayagond Kokatanur tstamp_all | ptp_v2 | ptp_over_ethernet | 598891434b1SRayagond Kokatanur ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en | 599891434b1SRayagond Kokatanur ts_master_en | snap_type_sel); 600891434b1SRayagond Kokatanur 601891434b1SRayagond Kokatanur priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value); 602891434b1SRayagond Kokatanur 603891434b1SRayagond Kokatanur /* program Sub Second Increment reg */ 604891434b1SRayagond Kokatanur priv->hw->ptp->config_sub_second_increment(priv->ioaddr); 605891434b1SRayagond Kokatanur 606891434b1SRayagond Kokatanur /* calculate default added value: 607891434b1SRayagond Kokatanur * formula is : 608891434b1SRayagond Kokatanur * addend = (2^32)/freq_div_ratio; 6095566401fSGiuseppe CAVALLARO * where, freq_div_ratio = clk_ptp_ref_i/50MHz 6105566401fSGiuseppe CAVALLARO * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i; 6115566401fSGiuseppe CAVALLARO * NOTE: clk_ptp_ref_i should be >= 50MHz to 612891434b1SRayagond Kokatanur * achive 20ns accuracy. 613891434b1SRayagond Kokatanur * 614891434b1SRayagond Kokatanur * 2^x * y == (y << x), hence 615891434b1SRayagond Kokatanur * 2^32 * 50000000 ==> (50000000 << 32) 616891434b1SRayagond Kokatanur */ 617891434b1SRayagond Kokatanur temp = (u64) (50000000ULL << 32); 6185566401fSGiuseppe CAVALLARO priv->default_addend = div_u64(temp, priv->clk_ptp_rate); 619891434b1SRayagond Kokatanur priv->hw->ptp->config_addend(priv->ioaddr, 620891434b1SRayagond Kokatanur priv->default_addend); 621891434b1SRayagond Kokatanur 622891434b1SRayagond Kokatanur /* initialize system time */ 623891434b1SRayagond Kokatanur getnstimeofday(&now); 624891434b1SRayagond Kokatanur priv->hw->ptp->init_systime(priv->ioaddr, 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 6445566401fSGiuseppe CAVALLARO /* Fall-back to main clock in case of no PTP ref is passed */ 6455566401fSGiuseppe CAVALLARO priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref"); 6465566401fSGiuseppe CAVALLARO if (IS_ERR(priv->clk_ptp_ref)) { 6475566401fSGiuseppe CAVALLARO priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk); 6485566401fSGiuseppe CAVALLARO priv->clk_ptp_ref = NULL; 6495566401fSGiuseppe CAVALLARO } else { 6505566401fSGiuseppe CAVALLARO clk_prepare_enable(priv->clk_ptp_ref); 6515566401fSGiuseppe CAVALLARO priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref); 6525566401fSGiuseppe CAVALLARO } 6535566401fSGiuseppe CAVALLARO 654891434b1SRayagond Kokatanur priv->adv_ts = 0; 6557cd01399SVince Bridgers if (priv->dma_cap.atime_stamp && priv->extend_desc) 656891434b1SRayagond Kokatanur priv->adv_ts = 1; 6577cd01399SVince Bridgers 6587cd01399SVince Bridgers if (netif_msg_hw(priv) && priv->dma_cap.time_stamp) 6597cd01399SVince Bridgers pr_debug("IEEE 1588-2002 Time Stamp supported\n"); 6607cd01399SVince Bridgers 6617cd01399SVince Bridgers if (netif_msg_hw(priv) && priv->adv_ts) 6627cd01399SVince Bridgers pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n"); 663891434b1SRayagond Kokatanur 664891434b1SRayagond Kokatanur priv->hw->ptp = &stmmac_ptp; 665891434b1SRayagond Kokatanur priv->hwts_tx_en = 0; 666891434b1SRayagond Kokatanur priv->hwts_rx_en = 0; 66792ba6888SRayagond Kokatanur 66892ba6888SRayagond Kokatanur return stmmac_ptp_register(priv); 66992ba6888SRayagond Kokatanur } 67092ba6888SRayagond Kokatanur 67192ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv) 67292ba6888SRayagond Kokatanur { 6735566401fSGiuseppe CAVALLARO if (priv->clk_ptp_ref) 6745566401fSGiuseppe CAVALLARO clk_disable_unprepare(priv->clk_ptp_ref); 67592ba6888SRayagond Kokatanur stmmac_ptp_unregister(priv); 676891434b1SRayagond Kokatanur } 677891434b1SRayagond Kokatanur 6787ac6653aSJeff Kirsher /** 679732fdf0eSGiuseppe CAVALLARO * stmmac_adjust_link - adjusts the link parameters 6807ac6653aSJeff Kirsher * @dev: net device structure 681732fdf0eSGiuseppe CAVALLARO * Description: this is the helper called by the physical abstraction layer 682732fdf0eSGiuseppe CAVALLARO * drivers to communicate the phy link status. According the speed and duplex 683732fdf0eSGiuseppe CAVALLARO * this driver can invoke registered glue-logic as well. 684732fdf0eSGiuseppe CAVALLARO * It also invoke the eee initialization because it could happen when switch 685732fdf0eSGiuseppe CAVALLARO * on different networks (that are eee capable). 6867ac6653aSJeff Kirsher */ 6877ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev) 6887ac6653aSJeff Kirsher { 6897ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 6907ac6653aSJeff Kirsher struct phy_device *phydev = priv->phydev; 6917ac6653aSJeff Kirsher unsigned long flags; 6927ac6653aSJeff Kirsher int new_state = 0; 6937ac6653aSJeff Kirsher unsigned int fc = priv->flow_ctrl, pause_time = priv->pause; 6947ac6653aSJeff Kirsher 6957ac6653aSJeff Kirsher if (phydev == NULL) 6967ac6653aSJeff Kirsher return; 6977ac6653aSJeff Kirsher 6987ac6653aSJeff Kirsher spin_lock_irqsave(&priv->lock, flags); 699d765955dSGiuseppe CAVALLARO 7007ac6653aSJeff Kirsher if (phydev->link) { 7017ac6653aSJeff Kirsher u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG); 7027ac6653aSJeff Kirsher 7037ac6653aSJeff Kirsher /* Now we make sure that we can be in full duplex mode. 7047ac6653aSJeff Kirsher * If not, we operate in half-duplex mode. */ 7057ac6653aSJeff Kirsher if (phydev->duplex != priv->oldduplex) { 7067ac6653aSJeff Kirsher new_state = 1; 7077ac6653aSJeff Kirsher if (!(phydev->duplex)) 7087ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.duplex; 7097ac6653aSJeff Kirsher else 7107ac6653aSJeff Kirsher ctrl |= priv->hw->link.duplex; 7117ac6653aSJeff Kirsher priv->oldduplex = phydev->duplex; 7127ac6653aSJeff Kirsher } 7137ac6653aSJeff Kirsher /* Flow Control operation */ 7147ac6653aSJeff Kirsher if (phydev->pause) 7157ed24bbeSVince Bridgers priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex, 7167ac6653aSJeff Kirsher fc, pause_time); 7177ac6653aSJeff Kirsher 7187ac6653aSJeff Kirsher if (phydev->speed != priv->speed) { 7197ac6653aSJeff Kirsher new_state = 1; 7207ac6653aSJeff Kirsher switch (phydev->speed) { 7217ac6653aSJeff Kirsher case 1000: 7227ac6653aSJeff Kirsher if (likely(priv->plat->has_gmac)) 7237ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.port; 7247ac6653aSJeff Kirsher stmmac_hw_fix_mac_speed(priv); 7257ac6653aSJeff Kirsher break; 7267ac6653aSJeff Kirsher case 100: 7277ac6653aSJeff Kirsher case 10: 7287ac6653aSJeff Kirsher if (priv->plat->has_gmac) { 7297ac6653aSJeff Kirsher ctrl |= priv->hw->link.port; 7307ac6653aSJeff Kirsher if (phydev->speed == SPEED_100) { 7317ac6653aSJeff Kirsher ctrl |= priv->hw->link.speed; 7327ac6653aSJeff Kirsher } else { 7337ac6653aSJeff Kirsher ctrl &= ~(priv->hw->link.speed); 7347ac6653aSJeff Kirsher } 7357ac6653aSJeff Kirsher } else { 7367ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.port; 7377ac6653aSJeff Kirsher } 7387ac6653aSJeff Kirsher stmmac_hw_fix_mac_speed(priv); 7397ac6653aSJeff Kirsher break; 7407ac6653aSJeff Kirsher default: 7417ac6653aSJeff Kirsher if (netif_msg_link(priv)) 742ceb69499SGiuseppe CAVALLARO pr_warn("%s: Speed (%d) not 10/100\n", 743ceb69499SGiuseppe CAVALLARO dev->name, phydev->speed); 7447ac6653aSJeff Kirsher break; 7457ac6653aSJeff Kirsher } 7467ac6653aSJeff Kirsher 7477ac6653aSJeff Kirsher priv->speed = phydev->speed; 7487ac6653aSJeff Kirsher } 7497ac6653aSJeff Kirsher 7507ac6653aSJeff Kirsher writel(ctrl, priv->ioaddr + MAC_CTRL_REG); 7517ac6653aSJeff Kirsher 7527ac6653aSJeff Kirsher if (!priv->oldlink) { 7537ac6653aSJeff Kirsher new_state = 1; 7547ac6653aSJeff Kirsher priv->oldlink = 1; 7557ac6653aSJeff Kirsher } 7567ac6653aSJeff Kirsher } else if (priv->oldlink) { 7577ac6653aSJeff Kirsher new_state = 1; 7587ac6653aSJeff Kirsher priv->oldlink = 0; 7597ac6653aSJeff Kirsher priv->speed = 0; 7607ac6653aSJeff Kirsher priv->oldduplex = -1; 7617ac6653aSJeff Kirsher } 7627ac6653aSJeff Kirsher 7637ac6653aSJeff Kirsher if (new_state && netif_msg_link(priv)) 7647ac6653aSJeff Kirsher phy_print_status(phydev); 7657ac6653aSJeff Kirsher 7664741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 7674741cf9cSGiuseppe CAVALLARO 768f5351ef7SGiuseppe CAVALLARO /* At this stage, it could be needed to setup the EEE or adjust some 769f5351ef7SGiuseppe CAVALLARO * MAC related HW registers. 770f5351ef7SGiuseppe CAVALLARO */ 771f5351ef7SGiuseppe CAVALLARO priv->eee_enabled = stmmac_eee_init(priv); 7727ac6653aSJeff Kirsher } 7737ac6653aSJeff Kirsher 77432ceabcaSGiuseppe CAVALLARO /** 775732fdf0eSGiuseppe CAVALLARO * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported 77632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 77732ceabcaSGiuseppe CAVALLARO * Description: this is to verify if the HW supports the PCS. 77832ceabcaSGiuseppe CAVALLARO * Physical Coding Sublayer (PCS) interface that can be used when the MAC is 77932ceabcaSGiuseppe CAVALLARO * configured for the TBI, RTBI, or SGMII PHY interface. 78032ceabcaSGiuseppe CAVALLARO */ 781e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv) 782e58bb43fSGiuseppe CAVALLARO { 783e58bb43fSGiuseppe CAVALLARO int interface = priv->plat->interface; 784e58bb43fSGiuseppe CAVALLARO 785e58bb43fSGiuseppe CAVALLARO if (priv->dma_cap.pcs) { 7860d909dcdSByungho An if ((interface == PHY_INTERFACE_MODE_RGMII) || 7870d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_ID) || 7880d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_RXID) || 7890d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 790e58bb43fSGiuseppe CAVALLARO pr_debug("STMMAC: PCS RGMII support enable\n"); 791e58bb43fSGiuseppe CAVALLARO priv->pcs = STMMAC_PCS_RGMII; 7920d909dcdSByungho An } else if (interface == PHY_INTERFACE_MODE_SGMII) { 793e58bb43fSGiuseppe CAVALLARO pr_debug("STMMAC: PCS SGMII support enable\n"); 794e58bb43fSGiuseppe CAVALLARO priv->pcs = STMMAC_PCS_SGMII; 795e58bb43fSGiuseppe CAVALLARO } 796e58bb43fSGiuseppe CAVALLARO } 797e58bb43fSGiuseppe CAVALLARO } 798e58bb43fSGiuseppe CAVALLARO 7997ac6653aSJeff Kirsher /** 8007ac6653aSJeff Kirsher * stmmac_init_phy - PHY initialization 8017ac6653aSJeff Kirsher * @dev: net device structure 8027ac6653aSJeff Kirsher * Description: it initializes the driver's PHY state, and attaches the PHY 8037ac6653aSJeff Kirsher * to the mac driver. 8047ac6653aSJeff Kirsher * Return value: 8057ac6653aSJeff Kirsher * 0 on success 8067ac6653aSJeff Kirsher */ 8077ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev) 8087ac6653aSJeff Kirsher { 8097ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 8107ac6653aSJeff Kirsher struct phy_device *phydev; 811d765955dSGiuseppe CAVALLARO char phy_id_fmt[MII_BUS_ID_SIZE + 3]; 8127ac6653aSJeff Kirsher char bus_id[MII_BUS_ID_SIZE]; 81379ee1dc3SSrinivas Kandagatla int interface = priv->plat->interface; 8149cbadf09SSrinivas Kandagatla int max_speed = priv->plat->max_speed; 8157ac6653aSJeff Kirsher priv->oldlink = 0; 8167ac6653aSJeff Kirsher priv->speed = 0; 8177ac6653aSJeff Kirsher priv->oldduplex = -1; 8187ac6653aSJeff Kirsher 819f142af2eSSrinivas Kandagatla if (priv->plat->phy_bus_name) 820f142af2eSSrinivas Kandagatla snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x", 821f142af2eSSrinivas Kandagatla priv->plat->phy_bus_name, priv->plat->bus_id); 822f142af2eSSrinivas Kandagatla else 823f142af2eSSrinivas Kandagatla snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", 824f142af2eSSrinivas Kandagatla priv->plat->bus_id); 825f142af2eSSrinivas Kandagatla 826d765955dSGiuseppe CAVALLARO snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, 8277ac6653aSJeff Kirsher priv->plat->phy_addr); 828d765955dSGiuseppe CAVALLARO pr_debug("stmmac_init_phy: trying to attach to %s\n", phy_id_fmt); 8297ac6653aSJeff Kirsher 830f9a8f83bSFlorian Fainelli phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface); 8317ac6653aSJeff Kirsher 8327ac6653aSJeff Kirsher if (IS_ERR(phydev)) { 8337ac6653aSJeff Kirsher pr_err("%s: Could not attach to PHY\n", dev->name); 8347ac6653aSJeff Kirsher return PTR_ERR(phydev); 8357ac6653aSJeff Kirsher } 8367ac6653aSJeff Kirsher 83779ee1dc3SSrinivas Kandagatla /* Stop Advertising 1000BASE Capability if interface is not GMII */ 838c5b9b4e4SSrinivas Kandagatla if ((interface == PHY_INTERFACE_MODE_MII) || 8399cbadf09SSrinivas Kandagatla (interface == PHY_INTERFACE_MODE_RMII) || 8409cbadf09SSrinivas Kandagatla (max_speed < 1000 && max_speed > 0)) 841c5b9b4e4SSrinivas Kandagatla phydev->advertising &= ~(SUPPORTED_1000baseT_Half | 842c5b9b4e4SSrinivas Kandagatla SUPPORTED_1000baseT_Full); 84379ee1dc3SSrinivas Kandagatla 8447ac6653aSJeff Kirsher /* 8457ac6653aSJeff Kirsher * Broken HW is sometimes missing the pull-up resistor on the 8467ac6653aSJeff Kirsher * MDIO line, which results in reads to non-existent devices returning 8477ac6653aSJeff Kirsher * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent 8487ac6653aSJeff Kirsher * device as well. 8497ac6653aSJeff Kirsher * Note: phydev->phy_id is the result of reading the UID PHY registers. 8507ac6653aSJeff Kirsher */ 8517ac6653aSJeff Kirsher if (phydev->phy_id == 0) { 8527ac6653aSJeff Kirsher phy_disconnect(phydev); 8537ac6653aSJeff Kirsher return -ENODEV; 8547ac6653aSJeff Kirsher } 8557ac6653aSJeff Kirsher pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)" 8567ac6653aSJeff Kirsher " Link = %d\n", dev->name, phydev->phy_id, phydev->link); 8577ac6653aSJeff Kirsher 8587ac6653aSJeff Kirsher priv->phydev = phydev; 8597ac6653aSJeff Kirsher 8607ac6653aSJeff Kirsher return 0; 8617ac6653aSJeff Kirsher } 8627ac6653aSJeff Kirsher 8637ac6653aSJeff Kirsher /** 864732fdf0eSGiuseppe CAVALLARO * stmmac_display_ring - display ring 86532ceabcaSGiuseppe CAVALLARO * @head: pointer to the head of the ring passed. 8667ac6653aSJeff Kirsher * @size: size of the ring. 86732ceabcaSGiuseppe CAVALLARO * @extend_desc: to verify if extended descriptors are used. 868c24602efSGiuseppe CAVALLARO * Description: display the control/status and buffer descriptors. 8697ac6653aSJeff Kirsher */ 870c24602efSGiuseppe CAVALLARO static void stmmac_display_ring(void *head, int size, int extend_desc) 8717ac6653aSJeff Kirsher { 8727ac6653aSJeff Kirsher int i; 873c24602efSGiuseppe CAVALLARO struct dma_extended_desc *ep = (struct dma_extended_desc *)head; 874c24602efSGiuseppe CAVALLARO struct dma_desc *p = (struct dma_desc *)head; 875c24602efSGiuseppe CAVALLARO 8767ac6653aSJeff Kirsher for (i = 0; i < size; i++) { 877c24602efSGiuseppe CAVALLARO u64 x; 878c24602efSGiuseppe CAVALLARO if (extend_desc) { 879c24602efSGiuseppe CAVALLARO x = *(u64 *) ep; 880c24602efSGiuseppe CAVALLARO pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 881c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 882c24602efSGiuseppe CAVALLARO (unsigned int)x, (unsigned int)(x >> 32), 883c24602efSGiuseppe CAVALLARO ep->basic.des2, ep->basic.des3); 884c24602efSGiuseppe CAVALLARO ep++; 885c24602efSGiuseppe CAVALLARO } else { 886c24602efSGiuseppe CAVALLARO x = *(u64 *) p; 887c24602efSGiuseppe CAVALLARO pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x", 888c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(p), 889c24602efSGiuseppe CAVALLARO (unsigned int)x, (unsigned int)(x >> 32), 890c24602efSGiuseppe CAVALLARO p->des2, p->des3); 891c24602efSGiuseppe CAVALLARO p++; 892c24602efSGiuseppe CAVALLARO } 8937ac6653aSJeff Kirsher pr_info("\n"); 8947ac6653aSJeff Kirsher } 8957ac6653aSJeff Kirsher } 8967ac6653aSJeff Kirsher 897c24602efSGiuseppe CAVALLARO static void stmmac_display_rings(struct stmmac_priv *priv) 898c24602efSGiuseppe CAVALLARO { 899c24602efSGiuseppe CAVALLARO unsigned int txsize = priv->dma_tx_size; 900c24602efSGiuseppe CAVALLARO unsigned int rxsize = priv->dma_rx_size; 901c24602efSGiuseppe CAVALLARO 902c24602efSGiuseppe CAVALLARO if (priv->extend_desc) { 903c24602efSGiuseppe CAVALLARO pr_info("Extended RX descriptor ring:\n"); 904c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_erx, rxsize, 1); 905c24602efSGiuseppe CAVALLARO pr_info("Extended TX descriptor ring:\n"); 906c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_etx, txsize, 1); 907c24602efSGiuseppe CAVALLARO } else { 908c24602efSGiuseppe CAVALLARO pr_info("RX descriptor ring:\n"); 909c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_rx, rxsize, 0); 910c24602efSGiuseppe CAVALLARO pr_info("TX descriptor ring:\n"); 911c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_tx, txsize, 0); 912c24602efSGiuseppe CAVALLARO } 913c24602efSGiuseppe CAVALLARO } 914c24602efSGiuseppe CAVALLARO 915286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize) 916286a8372SGiuseppe CAVALLARO { 917286a8372SGiuseppe CAVALLARO int ret = bufsize; 918286a8372SGiuseppe CAVALLARO 919286a8372SGiuseppe CAVALLARO if (mtu >= BUF_SIZE_4KiB) 920286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_8KiB; 921286a8372SGiuseppe CAVALLARO else if (mtu >= BUF_SIZE_2KiB) 922286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_4KiB; 923d916701cSGiuseppe CAVALLARO else if (mtu > DEFAULT_BUFSIZE) 924286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_2KiB; 925286a8372SGiuseppe CAVALLARO else 926d916701cSGiuseppe CAVALLARO ret = DEFAULT_BUFSIZE; 927286a8372SGiuseppe CAVALLARO 928286a8372SGiuseppe CAVALLARO return ret; 929286a8372SGiuseppe CAVALLARO } 930286a8372SGiuseppe CAVALLARO 93132ceabcaSGiuseppe CAVALLARO /** 932732fdf0eSGiuseppe CAVALLARO * stmmac_clear_descriptors - clear descriptors 93332ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 93432ceabcaSGiuseppe CAVALLARO * Description: this function is called to clear the tx and rx descriptors 93532ceabcaSGiuseppe CAVALLARO * in case of both basic and extended descriptors are used. 93632ceabcaSGiuseppe CAVALLARO */ 937c24602efSGiuseppe CAVALLARO static void stmmac_clear_descriptors(struct stmmac_priv *priv) 938c24602efSGiuseppe CAVALLARO { 939c24602efSGiuseppe CAVALLARO int i; 940c24602efSGiuseppe CAVALLARO unsigned int txsize = priv->dma_tx_size; 941c24602efSGiuseppe CAVALLARO unsigned int rxsize = priv->dma_rx_size; 942c24602efSGiuseppe CAVALLARO 943c24602efSGiuseppe CAVALLARO /* Clear the Rx/Tx descriptors */ 944c24602efSGiuseppe CAVALLARO for (i = 0; i < rxsize; i++) 945c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 946c24602efSGiuseppe CAVALLARO priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic, 947c24602efSGiuseppe CAVALLARO priv->use_riwt, priv->mode, 948c24602efSGiuseppe CAVALLARO (i == rxsize - 1)); 949c24602efSGiuseppe CAVALLARO else 950c24602efSGiuseppe CAVALLARO priv->hw->desc->init_rx_desc(&priv->dma_rx[i], 951c24602efSGiuseppe CAVALLARO priv->use_riwt, priv->mode, 952c24602efSGiuseppe CAVALLARO (i == rxsize - 1)); 953c24602efSGiuseppe CAVALLARO for (i = 0; i < txsize; i++) 954c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 955c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic, 956c24602efSGiuseppe CAVALLARO priv->mode, 957c24602efSGiuseppe CAVALLARO (i == txsize - 1)); 958c24602efSGiuseppe CAVALLARO else 959c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_tx[i], 960c24602efSGiuseppe CAVALLARO priv->mode, 961c24602efSGiuseppe CAVALLARO (i == txsize - 1)); 962c24602efSGiuseppe CAVALLARO } 963c24602efSGiuseppe CAVALLARO 964732fdf0eSGiuseppe CAVALLARO /** 965732fdf0eSGiuseppe CAVALLARO * stmmac_init_rx_buffers - init the RX descriptor buffer. 966732fdf0eSGiuseppe CAVALLARO * @priv: driver private structure 967732fdf0eSGiuseppe CAVALLARO * @p: descriptor pointer 968732fdf0eSGiuseppe CAVALLARO * @i: descriptor index 969732fdf0eSGiuseppe CAVALLARO * @flags: gfp flag. 970732fdf0eSGiuseppe CAVALLARO * Description: this function is called to allocate a receive buffer, perform 971732fdf0eSGiuseppe CAVALLARO * the DMA mapping and init the descriptor. 972732fdf0eSGiuseppe CAVALLARO */ 973c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, 974777da230SGiuseppe CAVALLARO int i, gfp_t flags) 975c24602efSGiuseppe CAVALLARO { 976c24602efSGiuseppe CAVALLARO struct sk_buff *skb; 977c24602efSGiuseppe CAVALLARO 978c24602efSGiuseppe CAVALLARO skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN, 979777da230SGiuseppe CAVALLARO flags); 98056329137SBartlomiej Zolnierkiewicz if (!skb) { 981c24602efSGiuseppe CAVALLARO pr_err("%s: Rx init fails; skb is NULL\n", __func__); 98256329137SBartlomiej Zolnierkiewicz return -ENOMEM; 983c24602efSGiuseppe CAVALLARO } 984c24602efSGiuseppe CAVALLARO skb_reserve(skb, NET_IP_ALIGN); 985c24602efSGiuseppe CAVALLARO priv->rx_skbuff[i] = skb; 986c24602efSGiuseppe CAVALLARO priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data, 987c24602efSGiuseppe CAVALLARO priv->dma_buf_sz, 988c24602efSGiuseppe CAVALLARO DMA_FROM_DEVICE); 98956329137SBartlomiej Zolnierkiewicz if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) { 99056329137SBartlomiej Zolnierkiewicz pr_err("%s: DMA mapping error\n", __func__); 99156329137SBartlomiej Zolnierkiewicz dev_kfree_skb_any(skb); 99256329137SBartlomiej Zolnierkiewicz return -EINVAL; 99356329137SBartlomiej Zolnierkiewicz } 994c24602efSGiuseppe CAVALLARO 995c24602efSGiuseppe CAVALLARO p->des2 = priv->rx_skbuff_dma[i]; 996c24602efSGiuseppe CAVALLARO 99729896a67SGiuseppe CAVALLARO if ((priv->hw->mode->init_desc3) && 998c24602efSGiuseppe CAVALLARO (priv->dma_buf_sz == BUF_SIZE_16KiB)) 99929896a67SGiuseppe CAVALLARO priv->hw->mode->init_desc3(p); 1000c24602efSGiuseppe CAVALLARO 1001c24602efSGiuseppe CAVALLARO return 0; 1002c24602efSGiuseppe CAVALLARO } 1003c24602efSGiuseppe CAVALLARO 100456329137SBartlomiej Zolnierkiewicz static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i) 100556329137SBartlomiej Zolnierkiewicz { 100656329137SBartlomiej Zolnierkiewicz if (priv->rx_skbuff[i]) { 100756329137SBartlomiej Zolnierkiewicz dma_unmap_single(priv->device, priv->rx_skbuff_dma[i], 100856329137SBartlomiej Zolnierkiewicz priv->dma_buf_sz, DMA_FROM_DEVICE); 100956329137SBartlomiej Zolnierkiewicz dev_kfree_skb_any(priv->rx_skbuff[i]); 101056329137SBartlomiej Zolnierkiewicz } 101156329137SBartlomiej Zolnierkiewicz priv->rx_skbuff[i] = NULL; 101256329137SBartlomiej Zolnierkiewicz } 101356329137SBartlomiej Zolnierkiewicz 10147ac6653aSJeff Kirsher /** 10157ac6653aSJeff Kirsher * init_dma_desc_rings - init the RX/TX descriptor rings 10167ac6653aSJeff Kirsher * @dev: net device structure 1017732fdf0eSGiuseppe CAVALLARO * @flags: gfp flag. 10187ac6653aSJeff Kirsher * Description: this function initializes the DMA RX/TX descriptors 1019286a8372SGiuseppe CAVALLARO * and allocates the socket buffers. It suppors the chained and ring 1020286a8372SGiuseppe CAVALLARO * modes. 10217ac6653aSJeff Kirsher */ 1022777da230SGiuseppe CAVALLARO static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) 10237ac6653aSJeff Kirsher { 10247ac6653aSJeff Kirsher int i; 10257ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 10267ac6653aSJeff Kirsher unsigned int txsize = priv->dma_tx_size; 10277ac6653aSJeff Kirsher unsigned int rxsize = priv->dma_rx_size; 10284a7d666aSGiuseppe CAVALLARO unsigned int bfsize = 0; 102956329137SBartlomiej Zolnierkiewicz int ret = -ENOMEM; 10307ac6653aSJeff Kirsher 103129896a67SGiuseppe CAVALLARO if (priv->hw->mode->set_16kib_bfsize) 103229896a67SGiuseppe CAVALLARO bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu); 1033286a8372SGiuseppe CAVALLARO 10344a7d666aSGiuseppe CAVALLARO if (bfsize < BUF_SIZE_16KiB) 1035286a8372SGiuseppe CAVALLARO bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz); 10367ac6653aSJeff Kirsher 10372618abb7SVince Bridgers priv->dma_buf_sz = bfsize; 10382618abb7SVince Bridgers 103983d7af64SGiuseppe CAVALLARO if (netif_msg_probe(priv)) 104083d7af64SGiuseppe CAVALLARO pr_debug("%s: txsize %d, rxsize %d, bfsize %d\n", __func__, 10417ac6653aSJeff Kirsher txsize, rxsize, bfsize); 10427ac6653aSJeff Kirsher 104383d7af64SGiuseppe CAVALLARO if (netif_msg_probe(priv)) { 1044c24602efSGiuseppe CAVALLARO pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__, 1045c24602efSGiuseppe CAVALLARO (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy); 10467ac6653aSJeff Kirsher 10477ac6653aSJeff Kirsher /* RX INITIALIZATION */ 104883d7af64SGiuseppe CAVALLARO pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n"); 104983d7af64SGiuseppe CAVALLARO } 10507ac6653aSJeff Kirsher for (i = 0; i < rxsize; i++) { 1051c24602efSGiuseppe CAVALLARO struct dma_desc *p; 1052c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1053c24602efSGiuseppe CAVALLARO p = &((priv->dma_erx + i)->basic); 1054c24602efSGiuseppe CAVALLARO else 1055c24602efSGiuseppe CAVALLARO p = priv->dma_rx + i; 10567ac6653aSJeff Kirsher 1057777da230SGiuseppe CAVALLARO ret = stmmac_init_rx_buffers(priv, p, i, flags); 105856329137SBartlomiej Zolnierkiewicz if (ret) 105956329137SBartlomiej Zolnierkiewicz goto err_init_rx_buffers; 1060286a8372SGiuseppe CAVALLARO 106183d7af64SGiuseppe CAVALLARO if (netif_msg_probe(priv)) 106283d7af64SGiuseppe CAVALLARO pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i], 106383d7af64SGiuseppe CAVALLARO priv->rx_skbuff[i]->data, 106483d7af64SGiuseppe CAVALLARO (unsigned int)priv->rx_skbuff_dma[i]); 10657ac6653aSJeff Kirsher } 10667ac6653aSJeff Kirsher priv->cur_rx = 0; 10677ac6653aSJeff Kirsher priv->dirty_rx = (unsigned int)(i - rxsize); 10687ac6653aSJeff Kirsher buf_sz = bfsize; 10697ac6653aSJeff Kirsher 1070c24602efSGiuseppe CAVALLARO /* Setup the chained descriptor addresses */ 1071c24602efSGiuseppe CAVALLARO if (priv->mode == STMMAC_CHAIN_MODE) { 1072c24602efSGiuseppe CAVALLARO if (priv->extend_desc) { 107329896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy, 1074c24602efSGiuseppe CAVALLARO rxsize, 1); 107529896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy, 1076c24602efSGiuseppe CAVALLARO txsize, 1); 1077c24602efSGiuseppe CAVALLARO } else { 107829896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy, 1079c24602efSGiuseppe CAVALLARO rxsize, 0); 108029896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy, 1081c24602efSGiuseppe CAVALLARO txsize, 0); 1082c24602efSGiuseppe CAVALLARO } 10837ac6653aSJeff Kirsher } 1084286a8372SGiuseppe CAVALLARO 1085c24602efSGiuseppe CAVALLARO /* TX INITIALIZATION */ 1086c24602efSGiuseppe CAVALLARO for (i = 0; i < txsize; i++) { 1087c24602efSGiuseppe CAVALLARO struct dma_desc *p; 1088c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1089c24602efSGiuseppe CAVALLARO p = &((priv->dma_etx + i)->basic); 1090c24602efSGiuseppe CAVALLARO else 1091c24602efSGiuseppe CAVALLARO p = priv->dma_tx + i; 1092c24602efSGiuseppe CAVALLARO p->des2 = 0; 1093362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf = 0; 1094362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].map_as_page = 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 111856329137SBartlomiej Zolnierkiewicz for (i = 0; i < priv->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 11267ac6653aSJeff Kirsher for (i = 0; i < priv->dma_tx_size; i++) { 1127c24602efSGiuseppe CAVALLARO struct dma_desc *p; 112875e4364fSdamuzi000 1129c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1130c24602efSGiuseppe CAVALLARO p = &((priv->dma_etx + i)->basic); 1131c24602efSGiuseppe CAVALLARO else 1132c24602efSGiuseppe CAVALLARO p = priv->dma_tx + i; 1133c24602efSGiuseppe CAVALLARO 1134362b37beSGiuseppe CAVALLARO if (priv->tx_skbuff_dma[i].buf) { 1135362b37beSGiuseppe CAVALLARO if (priv->tx_skbuff_dma[i].map_as_page) 1136362b37beSGiuseppe CAVALLARO dma_unmap_page(priv->device, 1137362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf, 11387ac6653aSJeff Kirsher priv->hw->desc->get_tx_len(p), 11397ac6653aSJeff Kirsher DMA_TO_DEVICE); 1140362b37beSGiuseppe CAVALLARO else 1141362b37beSGiuseppe CAVALLARO dma_unmap_single(priv->device, 1142362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf, 1143362b37beSGiuseppe CAVALLARO priv->hw->desc->get_tx_len(p), 1144362b37beSGiuseppe CAVALLARO DMA_TO_DEVICE); 114575e4364fSdamuzi000 } 114675e4364fSdamuzi000 114775e4364fSdamuzi000 if (priv->tx_skbuff[i] != NULL) { 11487ac6653aSJeff Kirsher dev_kfree_skb_any(priv->tx_skbuff[i]); 11497ac6653aSJeff Kirsher priv->tx_skbuff[i] = NULL; 1150362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf = 0; 1151362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].map_as_page = false; 11527ac6653aSJeff Kirsher } 11537ac6653aSJeff Kirsher } 11547ac6653aSJeff Kirsher } 11557ac6653aSJeff Kirsher 1156732fdf0eSGiuseppe CAVALLARO /** 1157732fdf0eSGiuseppe CAVALLARO * alloc_dma_desc_resources - alloc TX/RX resources. 1158732fdf0eSGiuseppe CAVALLARO * @priv: private structure 1159732fdf0eSGiuseppe CAVALLARO * Description: according to which descriptor can be used (extend or basic) 1160732fdf0eSGiuseppe CAVALLARO * this function allocates the resources for TX and RX paths. In case of 1161732fdf0eSGiuseppe CAVALLARO * reception, for example, it pre-allocated the RX socket buffer in order to 1162732fdf0eSGiuseppe CAVALLARO * allow zero-copy mechanism. 1163732fdf0eSGiuseppe CAVALLARO */ 116409f8d696SSrinivas Kandagatla static int alloc_dma_desc_resources(struct stmmac_priv *priv) 116509f8d696SSrinivas Kandagatla { 116609f8d696SSrinivas Kandagatla unsigned int txsize = priv->dma_tx_size; 116709f8d696SSrinivas Kandagatla unsigned int rxsize = priv->dma_rx_size; 116809f8d696SSrinivas Kandagatla int ret = -ENOMEM; 116909f8d696SSrinivas Kandagatla 117009f8d696SSrinivas Kandagatla priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t), 117109f8d696SSrinivas Kandagatla GFP_KERNEL); 117209f8d696SSrinivas Kandagatla if (!priv->rx_skbuff_dma) 117309f8d696SSrinivas Kandagatla return -ENOMEM; 117409f8d696SSrinivas Kandagatla 117509f8d696SSrinivas Kandagatla priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *), 117609f8d696SSrinivas Kandagatla GFP_KERNEL); 117709f8d696SSrinivas Kandagatla if (!priv->rx_skbuff) 117809f8d696SSrinivas Kandagatla goto err_rx_skbuff; 117909f8d696SSrinivas Kandagatla 1180362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma = kmalloc_array(txsize, 1181362b37beSGiuseppe CAVALLARO sizeof(*priv->tx_skbuff_dma), 118209f8d696SSrinivas Kandagatla GFP_KERNEL); 118309f8d696SSrinivas Kandagatla if (!priv->tx_skbuff_dma) 118409f8d696SSrinivas Kandagatla goto err_tx_skbuff_dma; 118509f8d696SSrinivas Kandagatla 118609f8d696SSrinivas Kandagatla priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *), 118709f8d696SSrinivas Kandagatla GFP_KERNEL); 118809f8d696SSrinivas Kandagatla if (!priv->tx_skbuff) 118909f8d696SSrinivas Kandagatla goto err_tx_skbuff; 119009f8d696SSrinivas Kandagatla 119109f8d696SSrinivas Kandagatla if (priv->extend_desc) { 119209f8d696SSrinivas Kandagatla priv->dma_erx = dma_alloc_coherent(priv->device, rxsize * 119309f8d696SSrinivas Kandagatla sizeof(struct 119409f8d696SSrinivas Kandagatla dma_extended_desc), 119509f8d696SSrinivas Kandagatla &priv->dma_rx_phy, 119609f8d696SSrinivas Kandagatla GFP_KERNEL); 119709f8d696SSrinivas Kandagatla if (!priv->dma_erx) 119809f8d696SSrinivas Kandagatla goto err_dma; 119909f8d696SSrinivas Kandagatla 120009f8d696SSrinivas Kandagatla priv->dma_etx = dma_alloc_coherent(priv->device, txsize * 120109f8d696SSrinivas Kandagatla sizeof(struct 120209f8d696SSrinivas Kandagatla dma_extended_desc), 120309f8d696SSrinivas Kandagatla &priv->dma_tx_phy, 120409f8d696SSrinivas Kandagatla GFP_KERNEL); 120509f8d696SSrinivas Kandagatla if (!priv->dma_etx) { 120609f8d696SSrinivas Kandagatla dma_free_coherent(priv->device, priv->dma_rx_size * 120709f8d696SSrinivas Kandagatla sizeof(struct dma_extended_desc), 120809f8d696SSrinivas Kandagatla priv->dma_erx, priv->dma_rx_phy); 120909f8d696SSrinivas Kandagatla goto err_dma; 121009f8d696SSrinivas Kandagatla } 121109f8d696SSrinivas Kandagatla } else { 121209f8d696SSrinivas Kandagatla priv->dma_rx = dma_alloc_coherent(priv->device, rxsize * 121309f8d696SSrinivas Kandagatla sizeof(struct dma_desc), 121409f8d696SSrinivas Kandagatla &priv->dma_rx_phy, 121509f8d696SSrinivas Kandagatla GFP_KERNEL); 121609f8d696SSrinivas Kandagatla if (!priv->dma_rx) 121709f8d696SSrinivas Kandagatla goto err_dma; 121809f8d696SSrinivas Kandagatla 121909f8d696SSrinivas Kandagatla priv->dma_tx = dma_alloc_coherent(priv->device, txsize * 122009f8d696SSrinivas Kandagatla sizeof(struct dma_desc), 122109f8d696SSrinivas Kandagatla &priv->dma_tx_phy, 122209f8d696SSrinivas Kandagatla GFP_KERNEL); 122309f8d696SSrinivas Kandagatla if (!priv->dma_tx) { 122409f8d696SSrinivas Kandagatla dma_free_coherent(priv->device, priv->dma_rx_size * 122509f8d696SSrinivas Kandagatla sizeof(struct dma_desc), 122609f8d696SSrinivas Kandagatla priv->dma_rx, priv->dma_rx_phy); 122709f8d696SSrinivas Kandagatla goto err_dma; 122809f8d696SSrinivas Kandagatla } 122909f8d696SSrinivas Kandagatla } 123009f8d696SSrinivas Kandagatla 123109f8d696SSrinivas Kandagatla return 0; 123209f8d696SSrinivas Kandagatla 123309f8d696SSrinivas Kandagatla err_dma: 123409f8d696SSrinivas Kandagatla kfree(priv->tx_skbuff); 123509f8d696SSrinivas Kandagatla err_tx_skbuff: 123609f8d696SSrinivas Kandagatla kfree(priv->tx_skbuff_dma); 123709f8d696SSrinivas Kandagatla err_tx_skbuff_dma: 123809f8d696SSrinivas Kandagatla kfree(priv->rx_skbuff); 123909f8d696SSrinivas Kandagatla err_rx_skbuff: 124009f8d696SSrinivas Kandagatla kfree(priv->rx_skbuff_dma); 124109f8d696SSrinivas Kandagatla return ret; 124209f8d696SSrinivas Kandagatla } 124309f8d696SSrinivas Kandagatla 12447ac6653aSJeff Kirsher static void free_dma_desc_resources(struct stmmac_priv *priv) 12457ac6653aSJeff Kirsher { 12467ac6653aSJeff Kirsher /* Release the DMA TX/RX socket buffers */ 12477ac6653aSJeff Kirsher dma_free_rx_skbufs(priv); 12487ac6653aSJeff Kirsher dma_free_tx_skbufs(priv); 12497ac6653aSJeff Kirsher 1250ceb69499SGiuseppe CAVALLARO /* Free DMA regions of consistent memory previously allocated */ 1251c24602efSGiuseppe CAVALLARO if (!priv->extend_desc) { 12527ac6653aSJeff Kirsher dma_free_coherent(priv->device, 12537ac6653aSJeff Kirsher priv->dma_tx_size * sizeof(struct dma_desc), 12547ac6653aSJeff Kirsher priv->dma_tx, priv->dma_tx_phy); 12557ac6653aSJeff Kirsher dma_free_coherent(priv->device, 12567ac6653aSJeff Kirsher priv->dma_rx_size * sizeof(struct dma_desc), 12577ac6653aSJeff Kirsher priv->dma_rx, priv->dma_rx_phy); 1258c24602efSGiuseppe CAVALLARO } else { 1259c24602efSGiuseppe CAVALLARO dma_free_coherent(priv->device, priv->dma_tx_size * 1260c24602efSGiuseppe CAVALLARO sizeof(struct dma_extended_desc), 1261c24602efSGiuseppe CAVALLARO priv->dma_etx, priv->dma_tx_phy); 1262c24602efSGiuseppe CAVALLARO dma_free_coherent(priv->device, priv->dma_rx_size * 1263c24602efSGiuseppe CAVALLARO sizeof(struct dma_extended_desc), 1264c24602efSGiuseppe CAVALLARO priv->dma_erx, priv->dma_rx_phy); 1265c24602efSGiuseppe CAVALLARO } 12667ac6653aSJeff Kirsher kfree(priv->rx_skbuff_dma); 12677ac6653aSJeff Kirsher kfree(priv->rx_skbuff); 1268cf32deecSRayagond Kokatanur kfree(priv->tx_skbuff_dma); 12697ac6653aSJeff Kirsher kfree(priv->tx_skbuff); 12707ac6653aSJeff Kirsher } 12717ac6653aSJeff Kirsher 12727ac6653aSJeff Kirsher /** 12737ac6653aSJeff Kirsher * stmmac_dma_operation_mode - HW DMA operation mode 127432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 1275732fdf0eSGiuseppe CAVALLARO * Description: it is used for configuring the DMA operation mode register in 1276732fdf0eSGiuseppe CAVALLARO * order to program the tx/rx DMA thresholds or Store-And-Forward mode. 12777ac6653aSJeff Kirsher */ 12787ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv) 12797ac6653aSJeff Kirsher { 1280e2a240c7SSonic Zhang if (priv->plat->force_thresh_dma_mode) 1281e2a240c7SSonic Zhang priv->hw->dma->dma_mode(priv->ioaddr, tc, tc); 1282e2a240c7SSonic Zhang else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { 12837ac6653aSJeff Kirsher /* 12847ac6653aSJeff Kirsher * In case of GMAC, SF mode can be enabled 12857ac6653aSJeff Kirsher * to perform the TX COE in HW. This depends on: 12867ac6653aSJeff Kirsher * 1) TX COE if actually supported 12877ac6653aSJeff Kirsher * 2) There is no bugged Jumbo frame support 12887ac6653aSJeff Kirsher * that needs to not insert csum in the TDES. 12897ac6653aSJeff Kirsher */ 1290ceb69499SGiuseppe CAVALLARO priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE); 12917ac6653aSJeff Kirsher tc = SF_DMA_MODE; 12927ac6653aSJeff Kirsher } else 12937ac6653aSJeff Kirsher priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE); 12947ac6653aSJeff Kirsher } 12957ac6653aSJeff Kirsher 12967ac6653aSJeff Kirsher /** 1297732fdf0eSGiuseppe CAVALLARO * stmmac_tx_clean - to manage the transmission completion 129832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 1299732fdf0eSGiuseppe CAVALLARO * Description: it reclaims the transmit resources after transmission completes. 13007ac6653aSJeff Kirsher */ 13019125cdd1SGiuseppe CAVALLARO static void stmmac_tx_clean(struct stmmac_priv *priv) 13027ac6653aSJeff Kirsher { 13037ac6653aSJeff Kirsher unsigned int txsize = priv->dma_tx_size; 130438979574SBeniamino Galvani unsigned int bytes_compl = 0, pkts_compl = 0; 13057ac6653aSJeff Kirsher 1306a9097a96SGiuseppe CAVALLARO spin_lock(&priv->tx_lock); 1307a9097a96SGiuseppe CAVALLARO 13089125cdd1SGiuseppe CAVALLARO priv->xstats.tx_clean++; 13099125cdd1SGiuseppe CAVALLARO 13107ac6653aSJeff Kirsher while (priv->dirty_tx != priv->cur_tx) { 13117ac6653aSJeff Kirsher int last; 13127ac6653aSJeff Kirsher unsigned int entry = priv->dirty_tx % txsize; 13137ac6653aSJeff Kirsher struct sk_buff *skb = priv->tx_skbuff[entry]; 1314c24602efSGiuseppe CAVALLARO struct dma_desc *p; 1315c24602efSGiuseppe CAVALLARO 1316c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1317c24602efSGiuseppe CAVALLARO p = (struct dma_desc *)(priv->dma_etx + entry); 1318c24602efSGiuseppe CAVALLARO else 1319c24602efSGiuseppe CAVALLARO p = priv->dma_tx + entry; 13207ac6653aSJeff Kirsher 13217ac6653aSJeff Kirsher /* Check if the descriptor is owned by the DMA. */ 13227ac6653aSJeff Kirsher if (priv->hw->desc->get_tx_owner(p)) 13237ac6653aSJeff Kirsher break; 13247ac6653aSJeff Kirsher 1325c24602efSGiuseppe CAVALLARO /* Verify tx error by looking at the last segment. */ 13267ac6653aSJeff Kirsher last = priv->hw->desc->get_tx_ls(p); 13277ac6653aSJeff Kirsher if (likely(last)) { 13287ac6653aSJeff Kirsher int tx_error = 13297ac6653aSJeff Kirsher priv->hw->desc->tx_status(&priv->dev->stats, 13307ac6653aSJeff Kirsher &priv->xstats, p, 13317ac6653aSJeff Kirsher priv->ioaddr); 13327ac6653aSJeff Kirsher if (likely(tx_error == 0)) { 13337ac6653aSJeff Kirsher priv->dev->stats.tx_packets++; 13347ac6653aSJeff Kirsher priv->xstats.tx_pkt_n++; 13357ac6653aSJeff Kirsher } else 13367ac6653aSJeff Kirsher priv->dev->stats.tx_errors++; 1337891434b1SRayagond Kokatanur 1338891434b1SRayagond Kokatanur stmmac_get_tx_hwtstamp(priv, entry, skb); 13397ac6653aSJeff Kirsher } 134083d7af64SGiuseppe CAVALLARO if (netif_msg_tx_done(priv)) 134183d7af64SGiuseppe CAVALLARO pr_debug("%s: curr %d, dirty %d\n", __func__, 13427ac6653aSJeff Kirsher priv->cur_tx, priv->dirty_tx); 13437ac6653aSJeff Kirsher 1344362b37beSGiuseppe CAVALLARO if (likely(priv->tx_skbuff_dma[entry].buf)) { 1345362b37beSGiuseppe CAVALLARO if (priv->tx_skbuff_dma[entry].map_as_page) 1346362b37beSGiuseppe CAVALLARO dma_unmap_page(priv->device, 1347362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf, 13487ac6653aSJeff Kirsher priv->hw->desc->get_tx_len(p), 13497ac6653aSJeff Kirsher DMA_TO_DEVICE); 1350362b37beSGiuseppe CAVALLARO else 1351362b37beSGiuseppe CAVALLARO dma_unmap_single(priv->device, 1352362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf, 1353362b37beSGiuseppe CAVALLARO priv->hw->desc->get_tx_len(p), 1354362b37beSGiuseppe CAVALLARO DMA_TO_DEVICE); 1355362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf = 0; 1356362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].map_as_page = false; 1357cf32deecSRayagond Kokatanur } 135829896a67SGiuseppe CAVALLARO priv->hw->mode->clean_desc3(priv, p); 13597ac6653aSJeff Kirsher 13607ac6653aSJeff Kirsher if (likely(skb != NULL)) { 136138979574SBeniamino Galvani pkts_compl++; 136238979574SBeniamino Galvani bytes_compl += skb->len; 13637c565c33SEric W. Biederman dev_consume_skb_any(skb); 13647ac6653aSJeff Kirsher priv->tx_skbuff[entry] = NULL; 13657ac6653aSJeff Kirsher } 13667ac6653aSJeff Kirsher 13674a7d666aSGiuseppe CAVALLARO priv->hw->desc->release_tx_desc(p, priv->mode); 13687ac6653aSJeff Kirsher 136913497f58SGiuseppe CAVALLARO priv->dirty_tx++; 13707ac6653aSJeff Kirsher } 137138979574SBeniamino Galvani 137238979574SBeniamino Galvani netdev_completed_queue(priv->dev, pkts_compl, bytes_compl); 137338979574SBeniamino Galvani 13747ac6653aSJeff Kirsher if (unlikely(netif_queue_stopped(priv->dev) && 13757ac6653aSJeff Kirsher stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv))) { 13767ac6653aSJeff Kirsher netif_tx_lock(priv->dev); 13777ac6653aSJeff Kirsher if (netif_queue_stopped(priv->dev) && 13787ac6653aSJeff Kirsher stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv)) { 137983d7af64SGiuseppe CAVALLARO if (netif_msg_tx_done(priv)) 138083d7af64SGiuseppe CAVALLARO pr_debug("%s: restart transmit\n", __func__); 13817ac6653aSJeff Kirsher netif_wake_queue(priv->dev); 13827ac6653aSJeff Kirsher } 13837ac6653aSJeff Kirsher netif_tx_unlock(priv->dev); 13847ac6653aSJeff Kirsher } 1385d765955dSGiuseppe CAVALLARO 1386d765955dSGiuseppe CAVALLARO if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) { 1387d765955dSGiuseppe CAVALLARO stmmac_enable_eee_mode(priv); 1388f5351ef7SGiuseppe CAVALLARO mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); 1389d765955dSGiuseppe CAVALLARO } 1390a9097a96SGiuseppe CAVALLARO spin_unlock(&priv->tx_lock); 13917ac6653aSJeff Kirsher } 13927ac6653aSJeff Kirsher 13939125cdd1SGiuseppe CAVALLARO static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv) 13947ac6653aSJeff Kirsher { 13957ac6653aSJeff Kirsher priv->hw->dma->enable_dma_irq(priv->ioaddr); 13967ac6653aSJeff Kirsher } 13977ac6653aSJeff Kirsher 13989125cdd1SGiuseppe CAVALLARO static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv) 13997ac6653aSJeff Kirsher { 14007ac6653aSJeff Kirsher priv->hw->dma->disable_dma_irq(priv->ioaddr); 14017ac6653aSJeff Kirsher } 14027ac6653aSJeff Kirsher 14037ac6653aSJeff Kirsher /** 1404732fdf0eSGiuseppe CAVALLARO * stmmac_tx_err - to manage the tx error 140532ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 14067ac6653aSJeff Kirsher * Description: it cleans the descriptors and restarts the transmission 1407732fdf0eSGiuseppe CAVALLARO * in case of transmission errors. 14087ac6653aSJeff Kirsher */ 14097ac6653aSJeff Kirsher static void stmmac_tx_err(struct stmmac_priv *priv) 14107ac6653aSJeff Kirsher { 1411c24602efSGiuseppe CAVALLARO int i; 1412c24602efSGiuseppe CAVALLARO int txsize = priv->dma_tx_size; 14137ac6653aSJeff Kirsher netif_stop_queue(priv->dev); 14147ac6653aSJeff Kirsher 14157ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 14167ac6653aSJeff Kirsher dma_free_tx_skbufs(priv); 1417c24602efSGiuseppe CAVALLARO for (i = 0; i < txsize; i++) 1418c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1419c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic, 1420c24602efSGiuseppe CAVALLARO priv->mode, 1421c24602efSGiuseppe CAVALLARO (i == txsize - 1)); 1422c24602efSGiuseppe CAVALLARO else 1423c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_tx[i], 1424c24602efSGiuseppe CAVALLARO priv->mode, 1425c24602efSGiuseppe CAVALLARO (i == txsize - 1)); 14267ac6653aSJeff Kirsher priv->dirty_tx = 0; 14277ac6653aSJeff Kirsher priv->cur_tx = 0; 142838979574SBeniamino Galvani netdev_reset_queue(priv->dev); 14297ac6653aSJeff Kirsher priv->hw->dma->start_tx(priv->ioaddr); 14307ac6653aSJeff Kirsher 14317ac6653aSJeff Kirsher priv->dev->stats.tx_errors++; 14327ac6653aSJeff Kirsher netif_wake_queue(priv->dev); 14337ac6653aSJeff Kirsher } 14347ac6653aSJeff Kirsher 143532ceabcaSGiuseppe CAVALLARO /** 1436732fdf0eSGiuseppe CAVALLARO * stmmac_dma_interrupt - DMA ISR 143732ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 143832ceabcaSGiuseppe CAVALLARO * Description: this is the DMA ISR. It is called by the main ISR. 1439732fdf0eSGiuseppe CAVALLARO * It calls the dwmac dma routine and schedule poll method in case of some 1440732fdf0eSGiuseppe CAVALLARO * work can be done. 144132ceabcaSGiuseppe CAVALLARO */ 14427ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv) 14437ac6653aSJeff Kirsher { 14447ac6653aSJeff Kirsher int status; 14457ac6653aSJeff Kirsher 14467ac6653aSJeff Kirsher status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); 14479125cdd1SGiuseppe CAVALLARO if (likely((status & handle_rx)) || (status & handle_tx)) { 14489125cdd1SGiuseppe CAVALLARO if (likely(napi_schedule_prep(&priv->napi))) { 14499125cdd1SGiuseppe CAVALLARO stmmac_disable_dma_irq(priv); 14509125cdd1SGiuseppe CAVALLARO __napi_schedule(&priv->napi); 14519125cdd1SGiuseppe CAVALLARO } 14529125cdd1SGiuseppe CAVALLARO } 14539125cdd1SGiuseppe CAVALLARO if (unlikely(status & tx_hard_error_bump_tc)) { 14547ac6653aSJeff Kirsher /* Try to bump up the dma threshold on this failure */ 14557ac6653aSJeff Kirsher if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) { 14567ac6653aSJeff Kirsher tc += 64; 1457c405abe2SSonic Zhang if (priv->plat->force_thresh_dma_mode) 1458c405abe2SSonic Zhang priv->hw->dma->dma_mode(priv->ioaddr, tc, tc); 1459c405abe2SSonic Zhang else 1460c405abe2SSonic Zhang priv->hw->dma->dma_mode(priv->ioaddr, tc, 1461c405abe2SSonic Zhang SF_DMA_MODE); 14627ac6653aSJeff Kirsher priv->xstats.threshold = tc; 14637ac6653aSJeff Kirsher } 14647ac6653aSJeff Kirsher } else if (unlikely(status == tx_hard_error)) 14657ac6653aSJeff Kirsher stmmac_tx_err(priv); 14667ac6653aSJeff Kirsher } 14677ac6653aSJeff Kirsher 146832ceabcaSGiuseppe CAVALLARO /** 146932ceabcaSGiuseppe CAVALLARO * stmmac_mmc_setup: setup the Mac Management Counters (MMC) 147032ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 147132ceabcaSGiuseppe CAVALLARO * Description: this masks the MMC irq, in fact, the counters are managed in SW. 147232ceabcaSGiuseppe CAVALLARO */ 14731c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv) 14741c901a46SGiuseppe CAVALLARO { 14751c901a46SGiuseppe CAVALLARO unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET | 14761c901a46SGiuseppe CAVALLARO MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET; 14771c901a46SGiuseppe CAVALLARO 14781c901a46SGiuseppe CAVALLARO dwmac_mmc_intr_all_mask(priv->ioaddr); 14794f795b25SGiuseppe CAVALLARO 14804f795b25SGiuseppe CAVALLARO if (priv->dma_cap.rmon) { 14811c901a46SGiuseppe CAVALLARO dwmac_mmc_ctrl(priv->ioaddr, mode); 14821c901a46SGiuseppe CAVALLARO memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); 14834f795b25SGiuseppe CAVALLARO } else 1484aae54cffSStefan Roese pr_info(" No MAC Management Counters available\n"); 14851c901a46SGiuseppe CAVALLARO } 14861c901a46SGiuseppe CAVALLARO 1487732fdf0eSGiuseppe CAVALLARO /** 1488732fdf0eSGiuseppe CAVALLARO * stmmac_get_synopsys_id - return the SYINID. 1489732fdf0eSGiuseppe CAVALLARO * @priv: driver private structure 1490732fdf0eSGiuseppe CAVALLARO * Description: this simple function is to decode and return the SYINID 1491732fdf0eSGiuseppe CAVALLARO * starting from the HW core register. 1492732fdf0eSGiuseppe CAVALLARO */ 1493f0b9d786SGiuseppe CAVALLARO static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) 1494f0b9d786SGiuseppe CAVALLARO { 1495f0b9d786SGiuseppe CAVALLARO u32 hwid = priv->hw->synopsys_uid; 1496f0b9d786SGiuseppe CAVALLARO 1497ceb69499SGiuseppe CAVALLARO /* Check Synopsys Id (not available on old chips) */ 1498f0b9d786SGiuseppe CAVALLARO if (likely(hwid)) { 1499f0b9d786SGiuseppe CAVALLARO u32 uid = ((hwid & 0x0000ff00) >> 8); 1500f0b9d786SGiuseppe CAVALLARO u32 synid = (hwid & 0x000000ff); 1501f0b9d786SGiuseppe CAVALLARO 1502cf3f047bSGiuseppe CAVALLARO pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n", 1503f0b9d786SGiuseppe CAVALLARO uid, synid); 1504f0b9d786SGiuseppe CAVALLARO 1505f0b9d786SGiuseppe CAVALLARO return synid; 1506f0b9d786SGiuseppe CAVALLARO } 1507f0b9d786SGiuseppe CAVALLARO return 0; 1508f0b9d786SGiuseppe CAVALLARO } 1509e7434821SGiuseppe CAVALLARO 151019e30c14SGiuseppe CAVALLARO /** 1511732fdf0eSGiuseppe CAVALLARO * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors 151232ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 151332ceabcaSGiuseppe CAVALLARO * Description: select the Enhanced/Alternate or Normal descriptors. 1514732fdf0eSGiuseppe CAVALLARO * In case of Enhanced/Alternate, it checks if the extended descriptors are 1515732fdf0eSGiuseppe CAVALLARO * supported by the HW capability register. 1516ff3dd78cSGiuseppe CAVALLARO */ 151719e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv) 151819e30c14SGiuseppe CAVALLARO { 151919e30c14SGiuseppe CAVALLARO if (priv->plat->enh_desc) { 152019e30c14SGiuseppe CAVALLARO pr_info(" Enhanced/Alternate descriptors\n"); 1521c24602efSGiuseppe CAVALLARO 1522c24602efSGiuseppe CAVALLARO /* GMAC older than 3.50 has no extended descriptors */ 1523c24602efSGiuseppe CAVALLARO if (priv->synopsys_id >= DWMAC_CORE_3_50) { 1524c24602efSGiuseppe CAVALLARO pr_info("\tEnabled extended descriptors\n"); 1525c24602efSGiuseppe CAVALLARO priv->extend_desc = 1; 1526c24602efSGiuseppe CAVALLARO } else 1527c24602efSGiuseppe CAVALLARO pr_warn("Extended descriptors not supported\n"); 1528c24602efSGiuseppe CAVALLARO 152919e30c14SGiuseppe CAVALLARO priv->hw->desc = &enh_desc_ops; 153019e30c14SGiuseppe CAVALLARO } else { 153119e30c14SGiuseppe CAVALLARO pr_info(" Normal descriptors\n"); 153219e30c14SGiuseppe CAVALLARO priv->hw->desc = &ndesc_ops; 153319e30c14SGiuseppe CAVALLARO } 153419e30c14SGiuseppe CAVALLARO } 153519e30c14SGiuseppe CAVALLARO 153619e30c14SGiuseppe CAVALLARO /** 1537732fdf0eSGiuseppe CAVALLARO * stmmac_get_hw_features - get MAC capabilities from the HW cap. register. 153832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 153919e30c14SGiuseppe CAVALLARO * Description: 154019e30c14SGiuseppe CAVALLARO * new GMAC chip generations have a new register to indicate the 1541e7434821SGiuseppe CAVALLARO * presence of the optional feature/functions. 154219e30c14SGiuseppe CAVALLARO * This can be also used to override the value passed through the 154319e30c14SGiuseppe CAVALLARO * platform and necessary for old MAC10/100 and GMAC chips. 1544e7434821SGiuseppe CAVALLARO */ 1545e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv) 1546e7434821SGiuseppe CAVALLARO { 15475e6efe88SGiuseppe CAVALLARO u32 hw_cap = 0; 15483c20f72fSGiuseppe CAVALLARO 15495e6efe88SGiuseppe CAVALLARO if (priv->hw->dma->get_hw_feature) { 15505e6efe88SGiuseppe CAVALLARO hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr); 1551e7434821SGiuseppe CAVALLARO 15521db123fbSRayagond Kokatanur priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL); 15531db123fbSRayagond Kokatanur priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1; 15541db123fbSRayagond Kokatanur priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2; 15551db123fbSRayagond Kokatanur priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4; 1556ceb69499SGiuseppe CAVALLARO priv->dma_cap.multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5; 15571db123fbSRayagond Kokatanur priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6; 15581db123fbSRayagond Kokatanur priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8; 15591db123fbSRayagond Kokatanur priv->dma_cap.pmt_remote_wake_up = 15601db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9; 15611db123fbSRayagond Kokatanur priv->dma_cap.pmt_magic_frame = 15621db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10; 15631db123fbSRayagond Kokatanur /* MMC */ 15641db123fbSRayagond Kokatanur priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11; 1565e7434821SGiuseppe CAVALLARO /* IEEE 1588-2002 */ 15661db123fbSRayagond Kokatanur priv->dma_cap.time_stamp = 15671db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12; 1568e7434821SGiuseppe CAVALLARO /* IEEE 1588-2008 */ 15691db123fbSRayagond Kokatanur priv->dma_cap.atime_stamp = 15701db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13; 1571e7434821SGiuseppe CAVALLARO /* 802.3az - Energy-Efficient Ethernet (EEE) */ 15721db123fbSRayagond Kokatanur priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14; 15731db123fbSRayagond Kokatanur priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15; 1574e7434821SGiuseppe CAVALLARO /* TX and RX csum */ 15751db123fbSRayagond Kokatanur priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16; 15761db123fbSRayagond Kokatanur priv->dma_cap.rx_coe_type1 = 15771db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17; 15781db123fbSRayagond Kokatanur priv->dma_cap.rx_coe_type2 = 15791db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18; 15801db123fbSRayagond Kokatanur priv->dma_cap.rxfifo_over_2048 = 15811db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19; 1582e7434821SGiuseppe CAVALLARO /* TX and RX number of channels */ 15831db123fbSRayagond Kokatanur priv->dma_cap.number_rx_channel = 15841db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20; 15851db123fbSRayagond Kokatanur priv->dma_cap.number_tx_channel = 15861db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22; 1587e7434821SGiuseppe CAVALLARO /* Alternate (enhanced) DESC mode */ 1588ceb69499SGiuseppe CAVALLARO priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24; 158919e30c14SGiuseppe CAVALLARO } 1590e7434821SGiuseppe CAVALLARO 1591e7434821SGiuseppe CAVALLARO return hw_cap; 1592e7434821SGiuseppe CAVALLARO } 1593e7434821SGiuseppe CAVALLARO 159432ceabcaSGiuseppe CAVALLARO /** 1595732fdf0eSGiuseppe CAVALLARO * stmmac_check_ether_addr - check if the MAC addr is valid 159632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 159732ceabcaSGiuseppe CAVALLARO * Description: 159832ceabcaSGiuseppe CAVALLARO * it is to verify if the MAC address is valid, in case of failures it 159932ceabcaSGiuseppe CAVALLARO * generates a random MAC address 160032ceabcaSGiuseppe CAVALLARO */ 1601bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv) 1602bfab27a1SGiuseppe CAVALLARO { 1603bfab27a1SGiuseppe CAVALLARO if (!is_valid_ether_addr(priv->dev->dev_addr)) { 16047ed24bbeSVince Bridgers priv->hw->mac->get_umac_addr(priv->hw, 1605bfab27a1SGiuseppe CAVALLARO priv->dev->dev_addr, 0); 1606bfab27a1SGiuseppe CAVALLARO if (!is_valid_ether_addr(priv->dev->dev_addr)) 1607f2cedb63SDanny Kukawka eth_hw_addr_random(priv->dev); 1608c88460b7SHans de Goede pr_info("%s: device MAC address %pM\n", priv->dev->name, 1609bfab27a1SGiuseppe CAVALLARO priv->dev->dev_addr); 1610bfab27a1SGiuseppe CAVALLARO } 1611c88460b7SHans de Goede } 1612bfab27a1SGiuseppe CAVALLARO 161332ceabcaSGiuseppe CAVALLARO /** 1614732fdf0eSGiuseppe CAVALLARO * stmmac_init_dma_engine - DMA init. 161532ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 161632ceabcaSGiuseppe CAVALLARO * Description: 161732ceabcaSGiuseppe CAVALLARO * It inits the DMA invoking the specific MAC/GMAC callback. 161832ceabcaSGiuseppe CAVALLARO * Some DMA parameters can be passed from the platform; 161932ceabcaSGiuseppe CAVALLARO * in case of these are not passed a default is kept for the MAC or GMAC. 162032ceabcaSGiuseppe CAVALLARO */ 16210f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv) 16220f1f88a8SGiuseppe CAVALLARO { 16230f1f88a8SGiuseppe CAVALLARO int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0; 1624b9cde0a8SGiuseppe CAVALLARO int mixed_burst = 0; 1625c24602efSGiuseppe CAVALLARO int atds = 0; 16260f1f88a8SGiuseppe CAVALLARO 16270f1f88a8SGiuseppe CAVALLARO if (priv->plat->dma_cfg) { 16280f1f88a8SGiuseppe CAVALLARO pbl = priv->plat->dma_cfg->pbl; 16290f1f88a8SGiuseppe CAVALLARO fixed_burst = priv->plat->dma_cfg->fixed_burst; 1630b9cde0a8SGiuseppe CAVALLARO mixed_burst = priv->plat->dma_cfg->mixed_burst; 16310f1f88a8SGiuseppe CAVALLARO burst_len = priv->plat->dma_cfg->burst_len; 16320f1f88a8SGiuseppe CAVALLARO } 16330f1f88a8SGiuseppe CAVALLARO 1634c24602efSGiuseppe CAVALLARO if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE)) 1635c24602efSGiuseppe CAVALLARO atds = 1; 1636c24602efSGiuseppe CAVALLARO 1637b9cde0a8SGiuseppe CAVALLARO return priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst, 16380f1f88a8SGiuseppe CAVALLARO burst_len, priv->dma_tx_phy, 1639c24602efSGiuseppe CAVALLARO priv->dma_rx_phy, atds); 16400f1f88a8SGiuseppe CAVALLARO } 16410f1f88a8SGiuseppe CAVALLARO 1642bfab27a1SGiuseppe CAVALLARO /** 1643732fdf0eSGiuseppe CAVALLARO * stmmac_tx_timer - mitigation sw timer for tx. 16449125cdd1SGiuseppe CAVALLARO * @data: data pointer 16459125cdd1SGiuseppe CAVALLARO * Description: 16469125cdd1SGiuseppe CAVALLARO * This is the timer handler to directly invoke the stmmac_tx_clean. 16479125cdd1SGiuseppe CAVALLARO */ 16489125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data) 16499125cdd1SGiuseppe CAVALLARO { 16509125cdd1SGiuseppe CAVALLARO struct stmmac_priv *priv = (struct stmmac_priv *)data; 16519125cdd1SGiuseppe CAVALLARO 16529125cdd1SGiuseppe CAVALLARO stmmac_tx_clean(priv); 16539125cdd1SGiuseppe CAVALLARO } 16549125cdd1SGiuseppe CAVALLARO 16559125cdd1SGiuseppe CAVALLARO /** 1656732fdf0eSGiuseppe CAVALLARO * stmmac_init_tx_coalesce - init tx mitigation options. 165732ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 16589125cdd1SGiuseppe CAVALLARO * Description: 16599125cdd1SGiuseppe CAVALLARO * This inits the transmit coalesce parameters: i.e. timer rate, 16609125cdd1SGiuseppe CAVALLARO * timer handler and default threshold used for enabling the 16619125cdd1SGiuseppe CAVALLARO * interrupt on completion bit. 16629125cdd1SGiuseppe CAVALLARO */ 16639125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) 16649125cdd1SGiuseppe CAVALLARO { 16659125cdd1SGiuseppe CAVALLARO priv->tx_coal_frames = STMMAC_TX_FRAMES; 16669125cdd1SGiuseppe CAVALLARO priv->tx_coal_timer = STMMAC_COAL_TX_TIMER; 16679125cdd1SGiuseppe CAVALLARO init_timer(&priv->txtimer); 16689125cdd1SGiuseppe CAVALLARO priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer); 16699125cdd1SGiuseppe CAVALLARO priv->txtimer.data = (unsigned long)priv; 16709125cdd1SGiuseppe CAVALLARO priv->txtimer.function = stmmac_tx_timer; 16719125cdd1SGiuseppe CAVALLARO add_timer(&priv->txtimer); 16729125cdd1SGiuseppe CAVALLARO } 16739125cdd1SGiuseppe CAVALLARO 16749125cdd1SGiuseppe CAVALLARO /** 1675732fdf0eSGiuseppe CAVALLARO * stmmac_hw_setup - setup mac in a usable state. 1676523f11b5SSrinivas Kandagatla * @dev : pointer to the device structure. 1677523f11b5SSrinivas Kandagatla * Description: 1678732fdf0eSGiuseppe CAVALLARO * this is the main function to setup the HW in a usable state because the 1679732fdf0eSGiuseppe CAVALLARO * dma engine is reset, the core registers are configured (e.g. AXI, 1680732fdf0eSGiuseppe CAVALLARO * Checksum features, timers). The DMA is ready to start receiving and 1681732fdf0eSGiuseppe CAVALLARO * transmitting. 1682523f11b5SSrinivas Kandagatla * Return value: 1683523f11b5SSrinivas Kandagatla * 0 on success and an appropriate (-)ve integer as defined in errno.h 1684523f11b5SSrinivas Kandagatla * file on failure. 1685523f11b5SSrinivas Kandagatla */ 1686fe131929SHuacai Chen static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) 1687523f11b5SSrinivas Kandagatla { 1688523f11b5SSrinivas Kandagatla struct stmmac_priv *priv = netdev_priv(dev); 1689523f11b5SSrinivas Kandagatla int ret; 1690523f11b5SSrinivas Kandagatla 1691523f11b5SSrinivas Kandagatla /* DMA initialization and SW reset */ 1692523f11b5SSrinivas Kandagatla ret = stmmac_init_dma_engine(priv); 1693523f11b5SSrinivas Kandagatla if (ret < 0) { 1694523f11b5SSrinivas Kandagatla pr_err("%s: DMA engine initialization failed\n", __func__); 1695523f11b5SSrinivas Kandagatla return ret; 1696523f11b5SSrinivas Kandagatla } 1697523f11b5SSrinivas Kandagatla 1698523f11b5SSrinivas Kandagatla /* Copy the MAC addr into the HW */ 16997ed24bbeSVince Bridgers priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0); 1700523f11b5SSrinivas Kandagatla 1701523f11b5SSrinivas Kandagatla /* If required, perform hw setup of the bus. */ 1702523f11b5SSrinivas Kandagatla if (priv->plat->bus_setup) 1703523f11b5SSrinivas Kandagatla priv->plat->bus_setup(priv->ioaddr); 1704523f11b5SSrinivas Kandagatla 1705523f11b5SSrinivas Kandagatla /* Initialize the MAC Core */ 17067ed24bbeSVince Bridgers priv->hw->mac->core_init(priv->hw, dev->mtu); 1707523f11b5SSrinivas Kandagatla 1708978aded4SGiuseppe CAVALLARO ret = priv->hw->mac->rx_ipc(priv->hw); 1709978aded4SGiuseppe CAVALLARO if (!ret) { 1710978aded4SGiuseppe CAVALLARO pr_warn(" RX IPC Checksum Offload disabled\n"); 1711978aded4SGiuseppe CAVALLARO priv->plat->rx_coe = STMMAC_RX_COE_NONE; 1712d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = 0; 1713978aded4SGiuseppe CAVALLARO } 1714978aded4SGiuseppe CAVALLARO 1715523f11b5SSrinivas Kandagatla /* Enable the MAC Rx/Tx */ 1716523f11b5SSrinivas Kandagatla stmmac_set_mac(priv->ioaddr, true); 1717523f11b5SSrinivas Kandagatla 1718523f11b5SSrinivas Kandagatla /* Set the HW DMA mode and the COE */ 1719523f11b5SSrinivas Kandagatla stmmac_dma_operation_mode(priv); 1720523f11b5SSrinivas Kandagatla 1721523f11b5SSrinivas Kandagatla stmmac_mmc_setup(priv); 1722523f11b5SSrinivas Kandagatla 1723fe131929SHuacai Chen if (init_ptp) { 1724523f11b5SSrinivas Kandagatla ret = stmmac_init_ptp(priv); 17257509edd6SHans de Goede if (ret && ret != -EOPNOTSUPP) 1726523f11b5SSrinivas Kandagatla pr_warn("%s: failed PTP initialisation\n", __func__); 1727fe131929SHuacai Chen } 1728523f11b5SSrinivas Kandagatla 172950fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 1730523f11b5SSrinivas Kandagatla ret = stmmac_init_fs(dev); 1731523f11b5SSrinivas Kandagatla if (ret < 0) 1732523f11b5SSrinivas Kandagatla pr_warn("%s: failed debugFS registration\n", __func__); 1733523f11b5SSrinivas Kandagatla #endif 1734523f11b5SSrinivas Kandagatla /* Start the ball rolling... */ 1735523f11b5SSrinivas Kandagatla pr_debug("%s: DMA RX/TX processes started...\n", dev->name); 1736523f11b5SSrinivas Kandagatla priv->hw->dma->start_tx(priv->ioaddr); 1737523f11b5SSrinivas Kandagatla priv->hw->dma->start_rx(priv->ioaddr); 1738523f11b5SSrinivas Kandagatla 1739523f11b5SSrinivas Kandagatla /* Dump DMA/MAC registers */ 1740523f11b5SSrinivas Kandagatla if (netif_msg_hw(priv)) { 17417ed24bbeSVince Bridgers priv->hw->mac->dump_regs(priv->hw); 1742523f11b5SSrinivas Kandagatla priv->hw->dma->dump_regs(priv->ioaddr); 1743523f11b5SSrinivas Kandagatla } 1744523f11b5SSrinivas Kandagatla priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; 1745523f11b5SSrinivas Kandagatla 1746523f11b5SSrinivas Kandagatla if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { 1747523f11b5SSrinivas Kandagatla priv->rx_riwt = MAX_DMA_RIWT; 1748523f11b5SSrinivas Kandagatla priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); 1749523f11b5SSrinivas Kandagatla } 1750523f11b5SSrinivas Kandagatla 1751523f11b5SSrinivas Kandagatla if (priv->pcs && priv->hw->mac->ctrl_ane) 17527ed24bbeSVince Bridgers priv->hw->mac->ctrl_ane(priv->hw, 0); 1753523f11b5SSrinivas Kandagatla 1754523f11b5SSrinivas Kandagatla return 0; 1755523f11b5SSrinivas Kandagatla } 1756523f11b5SSrinivas Kandagatla 1757523f11b5SSrinivas Kandagatla /** 17587ac6653aSJeff Kirsher * stmmac_open - open entry point of the driver 17597ac6653aSJeff Kirsher * @dev : pointer to the device structure. 17607ac6653aSJeff Kirsher * Description: 17617ac6653aSJeff Kirsher * This function is the open entry point of the driver. 17627ac6653aSJeff Kirsher * Return value: 17637ac6653aSJeff Kirsher * 0 on success and an appropriate (-)ve integer as defined in errno.h 17647ac6653aSJeff Kirsher * file on failure. 17657ac6653aSJeff Kirsher */ 17667ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev) 17677ac6653aSJeff Kirsher { 17687ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 17697ac6653aSJeff Kirsher int ret; 17707ac6653aSJeff Kirsher 17714bfcbd7aSFrancesco Virlinzi stmmac_check_ether_addr(priv); 17724bfcbd7aSFrancesco Virlinzi 17734d8f0825SByungho An if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 17744d8f0825SByungho An priv->pcs != STMMAC_PCS_RTBI) { 17757ac6653aSJeff Kirsher ret = stmmac_init_phy(dev); 1776e58bb43fSGiuseppe CAVALLARO if (ret) { 1777e58bb43fSGiuseppe CAVALLARO pr_err("%s: Cannot attach to PHY (error: %d)\n", 1778e58bb43fSGiuseppe CAVALLARO __func__, ret); 177989df20d9SHans de Goede return ret; 17807ac6653aSJeff Kirsher } 1781e58bb43fSGiuseppe CAVALLARO } 17827ac6653aSJeff Kirsher 1783523f11b5SSrinivas Kandagatla /* Extra statistics */ 1784523f11b5SSrinivas Kandagatla memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats)); 1785523f11b5SSrinivas Kandagatla priv->xstats.threshold = tc; 1786523f11b5SSrinivas Kandagatla 17877ac6653aSJeff Kirsher /* Create and initialize the TX/RX descriptors chains. */ 17887ac6653aSJeff Kirsher priv->dma_tx_size = STMMAC_ALIGN(dma_txsize); 17897ac6653aSJeff Kirsher priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize); 17907ac6653aSJeff Kirsher priv->dma_buf_sz = STMMAC_ALIGN(buf_sz); 179156329137SBartlomiej Zolnierkiewicz 17927262b7b2STobias Klauser ret = alloc_dma_desc_resources(priv); 179309f8d696SSrinivas Kandagatla if (ret < 0) { 179409f8d696SSrinivas Kandagatla pr_err("%s: DMA descriptors allocation failed\n", __func__); 179509f8d696SSrinivas Kandagatla goto dma_desc_error; 179609f8d696SSrinivas Kandagatla } 179709f8d696SSrinivas Kandagatla 1798777da230SGiuseppe CAVALLARO ret = init_dma_desc_rings(dev, GFP_KERNEL); 1799777da230SGiuseppe CAVALLARO if (ret < 0) { 1800777da230SGiuseppe CAVALLARO pr_err("%s: DMA descriptors initialization failed\n", __func__); 1801777da230SGiuseppe CAVALLARO goto init_error; 1802777da230SGiuseppe CAVALLARO } 1803777da230SGiuseppe CAVALLARO 1804fe131929SHuacai Chen ret = stmmac_hw_setup(dev, true); 180556329137SBartlomiej Zolnierkiewicz if (ret < 0) { 1806523f11b5SSrinivas Kandagatla pr_err("%s: Hw setup failed\n", __func__); 1807c9324d18SGiuseppe CAVALLARO goto init_error; 18087ac6653aSJeff Kirsher } 18097ac6653aSJeff Kirsher 1810777da230SGiuseppe CAVALLARO stmmac_init_tx_coalesce(priv); 1811777da230SGiuseppe CAVALLARO 1812523f11b5SSrinivas Kandagatla if (priv->phydev) 1813523f11b5SSrinivas Kandagatla phy_start(priv->phydev); 18147ac6653aSJeff Kirsher 18157ac6653aSJeff Kirsher /* Request the IRQ lines */ 18167ac6653aSJeff Kirsher ret = request_irq(dev->irq, stmmac_interrupt, 18177ac6653aSJeff Kirsher IRQF_SHARED, dev->name, dev); 18187ac6653aSJeff Kirsher if (unlikely(ret < 0)) { 18197ac6653aSJeff Kirsher pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n", 18207ac6653aSJeff Kirsher __func__, dev->irq, ret); 1821c9324d18SGiuseppe CAVALLARO goto init_error; 18227ac6653aSJeff Kirsher } 18237ac6653aSJeff Kirsher 18247a13f8f5SFrancesco Virlinzi /* Request the Wake IRQ in case of another line is used for WoL */ 18257a13f8f5SFrancesco Virlinzi if (priv->wol_irq != dev->irq) { 18267a13f8f5SFrancesco Virlinzi ret = request_irq(priv->wol_irq, stmmac_interrupt, 18277a13f8f5SFrancesco Virlinzi IRQF_SHARED, dev->name, dev); 18287a13f8f5SFrancesco Virlinzi if (unlikely(ret < 0)) { 1829ceb69499SGiuseppe CAVALLARO pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n", 1830ceb69499SGiuseppe CAVALLARO __func__, priv->wol_irq, ret); 1831c9324d18SGiuseppe CAVALLARO goto wolirq_error; 18327a13f8f5SFrancesco Virlinzi } 18337a13f8f5SFrancesco Virlinzi } 18347a13f8f5SFrancesco Virlinzi 1835d765955dSGiuseppe CAVALLARO /* Request the IRQ lines */ 1836d7ec8584SChen-Yu Tsai if (priv->lpi_irq > 0) { 1837d765955dSGiuseppe CAVALLARO ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED, 1838d765955dSGiuseppe CAVALLARO dev->name, dev); 1839d765955dSGiuseppe CAVALLARO if (unlikely(ret < 0)) { 1840d765955dSGiuseppe CAVALLARO pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n", 1841d765955dSGiuseppe CAVALLARO __func__, priv->lpi_irq, ret); 1842c9324d18SGiuseppe CAVALLARO goto lpiirq_error; 1843d765955dSGiuseppe CAVALLARO } 1844d765955dSGiuseppe CAVALLARO } 1845d765955dSGiuseppe CAVALLARO 18467ac6653aSJeff Kirsher napi_enable(&priv->napi); 18477ac6653aSJeff Kirsher netif_start_queue(dev); 18487ac6653aSJeff Kirsher 18497ac6653aSJeff Kirsher return 0; 18507ac6653aSJeff Kirsher 1851c9324d18SGiuseppe CAVALLARO lpiirq_error: 1852d765955dSGiuseppe CAVALLARO if (priv->wol_irq != dev->irq) 1853d765955dSGiuseppe CAVALLARO free_irq(priv->wol_irq, dev); 1854c9324d18SGiuseppe CAVALLARO wolirq_error: 18557a13f8f5SFrancesco Virlinzi free_irq(dev->irq, dev); 18567a13f8f5SFrancesco Virlinzi 1857c9324d18SGiuseppe CAVALLARO init_error: 1858c9324d18SGiuseppe CAVALLARO free_dma_desc_resources(priv); 185956329137SBartlomiej Zolnierkiewicz dma_desc_error: 18607ac6653aSJeff Kirsher if (priv->phydev) 18617ac6653aSJeff Kirsher phy_disconnect(priv->phydev); 18624bfcbd7aSFrancesco Virlinzi 18637ac6653aSJeff Kirsher return ret; 18647ac6653aSJeff Kirsher } 18657ac6653aSJeff Kirsher 18667ac6653aSJeff Kirsher /** 18677ac6653aSJeff Kirsher * stmmac_release - close entry point of the driver 18687ac6653aSJeff Kirsher * @dev : device pointer. 18697ac6653aSJeff Kirsher * Description: 18707ac6653aSJeff Kirsher * This is the stop entry point of the driver. 18717ac6653aSJeff Kirsher */ 18727ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev) 18737ac6653aSJeff Kirsher { 18747ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 18757ac6653aSJeff Kirsher 1876d765955dSGiuseppe CAVALLARO if (priv->eee_enabled) 1877d765955dSGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 1878d765955dSGiuseppe CAVALLARO 18797ac6653aSJeff Kirsher /* Stop and disconnect the PHY */ 18807ac6653aSJeff Kirsher if (priv->phydev) { 18817ac6653aSJeff Kirsher phy_stop(priv->phydev); 18827ac6653aSJeff Kirsher phy_disconnect(priv->phydev); 18837ac6653aSJeff Kirsher priv->phydev = NULL; 18847ac6653aSJeff Kirsher } 18857ac6653aSJeff Kirsher 18867ac6653aSJeff Kirsher netif_stop_queue(dev); 18877ac6653aSJeff Kirsher 18887ac6653aSJeff Kirsher napi_disable(&priv->napi); 18897ac6653aSJeff Kirsher 18909125cdd1SGiuseppe CAVALLARO del_timer_sync(&priv->txtimer); 18919125cdd1SGiuseppe CAVALLARO 18927ac6653aSJeff Kirsher /* Free the IRQ lines */ 18937ac6653aSJeff Kirsher free_irq(dev->irq, dev); 18947a13f8f5SFrancesco Virlinzi if (priv->wol_irq != dev->irq) 18957a13f8f5SFrancesco Virlinzi free_irq(priv->wol_irq, dev); 1896d7ec8584SChen-Yu Tsai if (priv->lpi_irq > 0) 1897d765955dSGiuseppe CAVALLARO free_irq(priv->lpi_irq, dev); 18987ac6653aSJeff Kirsher 18997ac6653aSJeff Kirsher /* Stop TX/RX DMA and clear the descriptors */ 19007ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 19017ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 19027ac6653aSJeff Kirsher 19037ac6653aSJeff Kirsher /* Release and free the Rx/Tx resources */ 19047ac6653aSJeff Kirsher free_dma_desc_resources(priv); 19057ac6653aSJeff Kirsher 19067ac6653aSJeff Kirsher /* Disable the MAC Rx/Tx */ 1907bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 19087ac6653aSJeff Kirsher 19097ac6653aSJeff Kirsher netif_carrier_off(dev); 19107ac6653aSJeff Kirsher 191150fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 1912bfab27a1SGiuseppe CAVALLARO stmmac_exit_fs(); 1913bfab27a1SGiuseppe CAVALLARO #endif 1914bfab27a1SGiuseppe CAVALLARO 191592ba6888SRayagond Kokatanur stmmac_release_ptp(priv); 191692ba6888SRayagond Kokatanur 19177ac6653aSJeff Kirsher return 0; 19187ac6653aSJeff Kirsher } 19197ac6653aSJeff Kirsher 19207ac6653aSJeff Kirsher /** 1921732fdf0eSGiuseppe CAVALLARO * stmmac_xmit - Tx entry point of the driver 19227ac6653aSJeff Kirsher * @skb : the socket buffer 19237ac6653aSJeff Kirsher * @dev : device pointer 192432ceabcaSGiuseppe CAVALLARO * Description : this is the tx entry point of the driver. 192532ceabcaSGiuseppe CAVALLARO * It programs the chain or the ring and supports oversized frames 192632ceabcaSGiuseppe CAVALLARO * and SG feature. 19277ac6653aSJeff Kirsher */ 19287ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) 19297ac6653aSJeff Kirsher { 19307ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 19317ac6653aSJeff Kirsher unsigned int txsize = priv->dma_tx_size; 19327ac6653aSJeff Kirsher unsigned int entry; 19334a7d666aSGiuseppe CAVALLARO int i, csum_insertion = 0, is_jumbo = 0; 19347ac6653aSJeff Kirsher int nfrags = skb_shinfo(skb)->nr_frags; 19357ac6653aSJeff Kirsher struct dma_desc *desc, *first; 1936286a8372SGiuseppe CAVALLARO unsigned int nopaged_len = skb_headlen(skb); 193729896a67SGiuseppe CAVALLARO unsigned int enh_desc = priv->plat->enh_desc; 19387ac6653aSJeff Kirsher 193916ee817eSFabrice Gasnier spin_lock(&priv->tx_lock); 194016ee817eSFabrice Gasnier 19417ac6653aSJeff Kirsher if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) { 194216ee817eSFabrice Gasnier spin_unlock(&priv->tx_lock); 19437ac6653aSJeff Kirsher if (!netif_queue_stopped(dev)) { 19447ac6653aSJeff Kirsher netif_stop_queue(dev); 19457ac6653aSJeff Kirsher /* This is a hard error, log it. */ 1946ceb69499SGiuseppe CAVALLARO pr_err("%s: Tx Ring full when queue awake\n", __func__); 19477ac6653aSJeff Kirsher } 19487ac6653aSJeff Kirsher return NETDEV_TX_BUSY; 19497ac6653aSJeff Kirsher } 19507ac6653aSJeff Kirsher 1951d765955dSGiuseppe CAVALLARO if (priv->tx_path_in_lpi_mode) 1952d765955dSGiuseppe CAVALLARO stmmac_disable_eee_mode(priv); 1953d765955dSGiuseppe CAVALLARO 19547ac6653aSJeff Kirsher entry = priv->cur_tx % txsize; 19557ac6653aSJeff Kirsher 19567ac6653aSJeff Kirsher csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL); 19577ac6653aSJeff Kirsher 1958c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1959c24602efSGiuseppe CAVALLARO desc = (struct dma_desc *)(priv->dma_etx + entry); 1960c24602efSGiuseppe CAVALLARO else 19617ac6653aSJeff Kirsher desc = priv->dma_tx + entry; 1962c24602efSGiuseppe CAVALLARO 19637ac6653aSJeff Kirsher first = desc; 19647ac6653aSJeff Kirsher 19654a7d666aSGiuseppe CAVALLARO /* To program the descriptors according to the size of the frame */ 196629896a67SGiuseppe CAVALLARO if (enh_desc) 196729896a67SGiuseppe CAVALLARO is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc); 196829896a67SGiuseppe CAVALLARO 19694a7d666aSGiuseppe CAVALLARO if (likely(!is_jumbo)) { 19707ac6653aSJeff Kirsher desc->des2 = dma_map_single(priv->device, skb->data, 19717ac6653aSJeff Kirsher nopaged_len, DMA_TO_DEVICE); 1972362b37beSGiuseppe CAVALLARO if (dma_mapping_error(priv->device, desc->des2)) 1973362b37beSGiuseppe CAVALLARO goto dma_map_err; 1974362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf = desc->des2; 19757ac6653aSJeff Kirsher priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, 19764a7d666aSGiuseppe CAVALLARO csum_insertion, priv->mode); 197729896a67SGiuseppe CAVALLARO } else { 1978c24602efSGiuseppe CAVALLARO desc = first; 197929896a67SGiuseppe CAVALLARO entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion); 1980362b37beSGiuseppe CAVALLARO if (unlikely(entry < 0)) 1981362b37beSGiuseppe CAVALLARO goto dma_map_err; 198229896a67SGiuseppe CAVALLARO } 19837ac6653aSJeff Kirsher 19847ac6653aSJeff Kirsher for (i = 0; i < nfrags; i++) { 19859e903e08SEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 19869e903e08SEric Dumazet int len = skb_frag_size(frag); 19877ac6653aSJeff Kirsher 198875e4364fSdamuzi000 priv->tx_skbuff[entry] = NULL; 19897ac6653aSJeff Kirsher entry = (++priv->cur_tx) % txsize; 1990c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1991c24602efSGiuseppe CAVALLARO desc = (struct dma_desc *)(priv->dma_etx + entry); 1992c24602efSGiuseppe CAVALLARO else 19937ac6653aSJeff Kirsher desc = priv->dma_tx + entry; 19947ac6653aSJeff Kirsher 1995f722380dSIan Campbell desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len, 1996f722380dSIan Campbell DMA_TO_DEVICE); 1997362b37beSGiuseppe CAVALLARO if (dma_mapping_error(priv->device, desc->des2)) 1998362b37beSGiuseppe CAVALLARO goto dma_map_err; /* should reuse desc w/o issues */ 1999362b37beSGiuseppe CAVALLARO 2000362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf = desc->des2; 2001362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].map_as_page = true; 20024a7d666aSGiuseppe CAVALLARO priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion, 20034a7d666aSGiuseppe CAVALLARO priv->mode); 20047ac6653aSJeff Kirsher wmb(); 20057ac6653aSJeff Kirsher priv->hw->desc->set_tx_owner(desc); 20068e839891SDeepak Sikri wmb(); 20077ac6653aSJeff Kirsher } 20087ac6653aSJeff Kirsher 200975e4364fSdamuzi000 priv->tx_skbuff[entry] = skb; 201075e4364fSdamuzi000 20119125cdd1SGiuseppe CAVALLARO /* Finalize the latest segment. */ 20127ac6653aSJeff Kirsher priv->hw->desc->close_tx_desc(desc); 20137ac6653aSJeff Kirsher 20147ac6653aSJeff Kirsher wmb(); 20159125cdd1SGiuseppe CAVALLARO /* According to the coalesce parameter the IC bit for the latest 20169125cdd1SGiuseppe CAVALLARO * segment could be reset and the timer re-started to invoke the 20179125cdd1SGiuseppe CAVALLARO * stmmac_tx function. This approach takes care about the fragments. 20189125cdd1SGiuseppe CAVALLARO */ 20199125cdd1SGiuseppe CAVALLARO priv->tx_count_frames += nfrags + 1; 20209125cdd1SGiuseppe CAVALLARO if (priv->tx_coal_frames > priv->tx_count_frames) { 20219125cdd1SGiuseppe CAVALLARO priv->hw->desc->clear_tx_ic(desc); 20229125cdd1SGiuseppe CAVALLARO priv->xstats.tx_reset_ic_bit++; 20239125cdd1SGiuseppe CAVALLARO mod_timer(&priv->txtimer, 20249125cdd1SGiuseppe CAVALLARO STMMAC_COAL_TIMER(priv->tx_coal_timer)); 20259125cdd1SGiuseppe CAVALLARO } else 20269125cdd1SGiuseppe CAVALLARO priv->tx_count_frames = 0; 20277ac6653aSJeff Kirsher 20287ac6653aSJeff Kirsher /* To avoid raise condition */ 20297ac6653aSJeff Kirsher priv->hw->desc->set_tx_owner(first); 20308e839891SDeepak Sikri wmb(); 20317ac6653aSJeff Kirsher 20327ac6653aSJeff Kirsher priv->cur_tx++; 20337ac6653aSJeff Kirsher 20347ac6653aSJeff Kirsher if (netif_msg_pktdata(priv)) { 203583d7af64SGiuseppe CAVALLARO pr_debug("%s: curr %d dirty=%d entry=%d, first=%p, nfrags=%d", 2036ceb69499SGiuseppe CAVALLARO __func__, (priv->cur_tx % txsize), 2037ceb69499SGiuseppe CAVALLARO (priv->dirty_tx % txsize), entry, first, nfrags); 203883d7af64SGiuseppe CAVALLARO 2039c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2040c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_etx, txsize, 1); 2041c24602efSGiuseppe CAVALLARO else 2042c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_tx, txsize, 0); 2043c24602efSGiuseppe CAVALLARO 204483d7af64SGiuseppe CAVALLARO pr_debug(">>> frame to be transmitted: "); 20457ac6653aSJeff Kirsher print_pkt(skb->data, skb->len); 20467ac6653aSJeff Kirsher } 20477ac6653aSJeff Kirsher if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { 204883d7af64SGiuseppe CAVALLARO if (netif_msg_hw(priv)) 204983d7af64SGiuseppe CAVALLARO pr_debug("%s: stop transmitted packets\n", __func__); 20507ac6653aSJeff Kirsher netif_stop_queue(dev); 20517ac6653aSJeff Kirsher } 20527ac6653aSJeff Kirsher 20537ac6653aSJeff Kirsher dev->stats.tx_bytes += skb->len; 20547ac6653aSJeff Kirsher 2055891434b1SRayagond Kokatanur if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && 2056891434b1SRayagond Kokatanur priv->hwts_tx_en)) { 2057891434b1SRayagond Kokatanur /* declare that device is doing timestamping */ 2058891434b1SRayagond Kokatanur skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 2059891434b1SRayagond Kokatanur priv->hw->desc->enable_tx_timestamp(first); 2060891434b1SRayagond Kokatanur } 2061891434b1SRayagond Kokatanur 2062891434b1SRayagond Kokatanur if (!priv->hwts_tx_en) 20637ac6653aSJeff Kirsher skb_tx_timestamp(skb); 20647ac6653aSJeff Kirsher 206538979574SBeniamino Galvani netdev_sent_queue(dev, skb->len); 20667ac6653aSJeff Kirsher priv->hw->dma->enable_dma_transmission(priv->ioaddr); 20677ac6653aSJeff Kirsher 2068a9097a96SGiuseppe CAVALLARO spin_unlock(&priv->tx_lock); 2069362b37beSGiuseppe CAVALLARO return NETDEV_TX_OK; 2070a9097a96SGiuseppe CAVALLARO 2071362b37beSGiuseppe CAVALLARO dma_map_err: 2072758a0ab5SFabrice Gasnier spin_unlock(&priv->tx_lock); 2073362b37beSGiuseppe CAVALLARO dev_err(priv->device, "Tx dma map failed\n"); 2074362b37beSGiuseppe CAVALLARO dev_kfree_skb(skb); 2075362b37beSGiuseppe CAVALLARO priv->dev->stats.tx_dropped++; 20767ac6653aSJeff Kirsher return NETDEV_TX_OK; 20777ac6653aSJeff Kirsher } 20787ac6653aSJeff Kirsher 2079b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb) 2080b9381985SVince Bridgers { 2081b9381985SVince Bridgers struct ethhdr *ehdr; 2082b9381985SVince Bridgers u16 vlanid; 2083b9381985SVince Bridgers 2084b9381985SVince Bridgers if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) == 2085b9381985SVince Bridgers NETIF_F_HW_VLAN_CTAG_RX && 2086b9381985SVince Bridgers !__vlan_get_tag(skb, &vlanid)) { 2087b9381985SVince Bridgers /* pop the vlan tag */ 2088b9381985SVince Bridgers ehdr = (struct ethhdr *)skb->data; 2089b9381985SVince Bridgers memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2); 2090b9381985SVince Bridgers skb_pull(skb, VLAN_HLEN); 2091b9381985SVince Bridgers __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid); 2092b9381985SVince Bridgers } 2093b9381985SVince Bridgers } 2094b9381985SVince Bridgers 2095b9381985SVince Bridgers 209632ceabcaSGiuseppe CAVALLARO /** 2097732fdf0eSGiuseppe CAVALLARO * stmmac_rx_refill - refill used skb preallocated buffers 209832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 209932ceabcaSGiuseppe CAVALLARO * Description : this is to reallocate the skb for the reception process 210032ceabcaSGiuseppe CAVALLARO * that is based on zero-copy. 210132ceabcaSGiuseppe CAVALLARO */ 21027ac6653aSJeff Kirsher static inline void stmmac_rx_refill(struct stmmac_priv *priv) 21037ac6653aSJeff Kirsher { 21047ac6653aSJeff Kirsher unsigned int rxsize = priv->dma_rx_size; 21057ac6653aSJeff Kirsher int bfsize = priv->dma_buf_sz; 21067ac6653aSJeff Kirsher 21077ac6653aSJeff Kirsher for (; priv->cur_rx - priv->dirty_rx > 0; priv->dirty_rx++) { 21087ac6653aSJeff Kirsher unsigned int entry = priv->dirty_rx % rxsize; 2109c24602efSGiuseppe CAVALLARO struct dma_desc *p; 2110c24602efSGiuseppe CAVALLARO 2111c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2112c24602efSGiuseppe CAVALLARO p = (struct dma_desc *)(priv->dma_erx + entry); 2113c24602efSGiuseppe CAVALLARO else 2114c24602efSGiuseppe CAVALLARO p = priv->dma_rx + entry; 2115c24602efSGiuseppe CAVALLARO 21167ac6653aSJeff Kirsher if (likely(priv->rx_skbuff[entry] == NULL)) { 21177ac6653aSJeff Kirsher struct sk_buff *skb; 21187ac6653aSJeff Kirsher 2119acb600deSEric Dumazet skb = netdev_alloc_skb_ip_align(priv->dev, bfsize); 21207ac6653aSJeff Kirsher 21217ac6653aSJeff Kirsher if (unlikely(skb == NULL)) 21227ac6653aSJeff Kirsher break; 21237ac6653aSJeff Kirsher 21247ac6653aSJeff Kirsher priv->rx_skbuff[entry] = skb; 21257ac6653aSJeff Kirsher priv->rx_skbuff_dma[entry] = 21267ac6653aSJeff Kirsher dma_map_single(priv->device, skb->data, bfsize, 21277ac6653aSJeff Kirsher DMA_FROM_DEVICE); 2128362b37beSGiuseppe CAVALLARO if (dma_mapping_error(priv->device, 2129362b37beSGiuseppe CAVALLARO priv->rx_skbuff_dma[entry])) { 2130362b37beSGiuseppe CAVALLARO dev_err(priv->device, "Rx dma map failed\n"); 2131362b37beSGiuseppe CAVALLARO dev_kfree_skb(skb); 2132362b37beSGiuseppe CAVALLARO break; 2133362b37beSGiuseppe CAVALLARO } 2134c24602efSGiuseppe CAVALLARO p->des2 = priv->rx_skbuff_dma[entry]; 2135286a8372SGiuseppe CAVALLARO 213629896a67SGiuseppe CAVALLARO priv->hw->mode->refill_desc3(priv, p); 2137286a8372SGiuseppe CAVALLARO 213883d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) 213983d7af64SGiuseppe CAVALLARO pr_debug("\trefill entry #%d\n", entry); 21407ac6653aSJeff Kirsher } 21417ac6653aSJeff Kirsher wmb(); 2142c24602efSGiuseppe CAVALLARO priv->hw->desc->set_rx_owner(p); 21438e839891SDeepak Sikri wmb(); 21447ac6653aSJeff Kirsher } 21457ac6653aSJeff Kirsher } 21467ac6653aSJeff Kirsher 214732ceabcaSGiuseppe CAVALLARO /** 2148732fdf0eSGiuseppe CAVALLARO * stmmac_rx - manage the receive process 214932ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 215032ceabcaSGiuseppe CAVALLARO * @limit: napi bugget. 215132ceabcaSGiuseppe CAVALLARO * Description : this the function called by the napi poll method. 215232ceabcaSGiuseppe CAVALLARO * It gets all the frames inside the ring. 215332ceabcaSGiuseppe CAVALLARO */ 21547ac6653aSJeff Kirsher static int stmmac_rx(struct stmmac_priv *priv, int limit) 21557ac6653aSJeff Kirsher { 21567ac6653aSJeff Kirsher unsigned int rxsize = priv->dma_rx_size; 21577ac6653aSJeff Kirsher unsigned int entry = priv->cur_rx % rxsize; 21587ac6653aSJeff Kirsher unsigned int next_entry; 21597ac6653aSJeff Kirsher unsigned int count = 0; 2160d2afb5bdSGiuseppe CAVALLARO int coe = priv->hw->rx_csum; 21617ac6653aSJeff Kirsher 216283d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) { 216383d7af64SGiuseppe CAVALLARO pr_debug("%s: descriptor ring:\n", __func__); 2164c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2165c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_erx, rxsize, 1); 2166c24602efSGiuseppe CAVALLARO else 2167c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_rx, rxsize, 0); 21687ac6653aSJeff Kirsher } 2169c24602efSGiuseppe CAVALLARO while (count < limit) { 21707ac6653aSJeff Kirsher int status; 21719401bb5cSGiuseppe CAVALLARO struct dma_desc *p; 21727ac6653aSJeff Kirsher 2173c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2174c24602efSGiuseppe CAVALLARO p = (struct dma_desc *)(priv->dma_erx + entry); 2175c24602efSGiuseppe CAVALLARO else 2176c24602efSGiuseppe CAVALLARO p = priv->dma_rx + entry; 2177c24602efSGiuseppe CAVALLARO 2178c24602efSGiuseppe CAVALLARO if (priv->hw->desc->get_rx_owner(p)) 21797ac6653aSJeff Kirsher break; 21807ac6653aSJeff Kirsher 21817ac6653aSJeff Kirsher count++; 21827ac6653aSJeff Kirsher 21837ac6653aSJeff Kirsher next_entry = (++priv->cur_rx) % rxsize; 2184c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 21859401bb5cSGiuseppe CAVALLARO prefetch(priv->dma_erx + next_entry); 2186c24602efSGiuseppe CAVALLARO else 21879401bb5cSGiuseppe CAVALLARO prefetch(priv->dma_rx + next_entry); 21887ac6653aSJeff Kirsher 21897ac6653aSJeff Kirsher /* read the status of the incoming frame */ 2190c24602efSGiuseppe CAVALLARO status = priv->hw->desc->rx_status(&priv->dev->stats, 2191c24602efSGiuseppe CAVALLARO &priv->xstats, p); 2192c24602efSGiuseppe CAVALLARO if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status)) 2193c24602efSGiuseppe CAVALLARO priv->hw->desc->rx_extended_status(&priv->dev->stats, 2194c24602efSGiuseppe CAVALLARO &priv->xstats, 2195c24602efSGiuseppe CAVALLARO priv->dma_erx + 2196c24602efSGiuseppe CAVALLARO entry); 2197891434b1SRayagond Kokatanur if (unlikely(status == discard_frame)) { 21987ac6653aSJeff Kirsher priv->dev->stats.rx_errors++; 2199891434b1SRayagond Kokatanur if (priv->hwts_rx_en && !priv->extend_desc) { 2200891434b1SRayagond Kokatanur /* DESC2 & DESC3 will be overwitten by device 2201891434b1SRayagond Kokatanur * with timestamp value, hence reinitialize 2202891434b1SRayagond Kokatanur * them in stmmac_rx_refill() function so that 2203891434b1SRayagond Kokatanur * device can reuse it. 2204891434b1SRayagond Kokatanur */ 2205891434b1SRayagond Kokatanur priv->rx_skbuff[entry] = NULL; 2206891434b1SRayagond Kokatanur dma_unmap_single(priv->device, 2207891434b1SRayagond Kokatanur priv->rx_skbuff_dma[entry], 2208ceb69499SGiuseppe CAVALLARO priv->dma_buf_sz, 2209ceb69499SGiuseppe CAVALLARO DMA_FROM_DEVICE); 2210891434b1SRayagond Kokatanur } 2211891434b1SRayagond Kokatanur } else { 22127ac6653aSJeff Kirsher struct sk_buff *skb; 22137ac6653aSJeff Kirsher int frame_len; 22147ac6653aSJeff Kirsher 2215ceb69499SGiuseppe CAVALLARO frame_len = priv->hw->desc->get_rx_frame_len(p, coe); 2216ceb69499SGiuseppe CAVALLARO 22177ac6653aSJeff Kirsher /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 2218ceb69499SGiuseppe CAVALLARO * Type frames (LLC/LLC-SNAP) 2219ceb69499SGiuseppe CAVALLARO */ 22207ac6653aSJeff Kirsher if (unlikely(status != llc_snap)) 22217ac6653aSJeff Kirsher frame_len -= ETH_FCS_LEN; 22227ac6653aSJeff Kirsher 222383d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) { 22247ac6653aSJeff Kirsher pr_debug("\tdesc: %p [entry %d] buff=0x%x\n", 22257ac6653aSJeff Kirsher p, entry, p->des2); 222683d7af64SGiuseppe CAVALLARO if (frame_len > ETH_FRAME_LEN) 222783d7af64SGiuseppe CAVALLARO pr_debug("\tframe size %d, COE: %d\n", 222883d7af64SGiuseppe CAVALLARO frame_len, status); 222983d7af64SGiuseppe CAVALLARO } 22307ac6653aSJeff Kirsher skb = priv->rx_skbuff[entry]; 22317ac6653aSJeff Kirsher if (unlikely(!skb)) { 22327ac6653aSJeff Kirsher pr_err("%s: Inconsistent Rx descriptor chain\n", 22337ac6653aSJeff Kirsher priv->dev->name); 22347ac6653aSJeff Kirsher priv->dev->stats.rx_dropped++; 22357ac6653aSJeff Kirsher break; 22367ac6653aSJeff Kirsher } 22377ac6653aSJeff Kirsher prefetch(skb->data - NET_IP_ALIGN); 22387ac6653aSJeff Kirsher priv->rx_skbuff[entry] = NULL; 22397ac6653aSJeff Kirsher 2240891434b1SRayagond Kokatanur stmmac_get_rx_hwtstamp(priv, entry, skb); 2241891434b1SRayagond Kokatanur 22427ac6653aSJeff Kirsher skb_put(skb, frame_len); 22437ac6653aSJeff Kirsher dma_unmap_single(priv->device, 22447ac6653aSJeff Kirsher priv->rx_skbuff_dma[entry], 22457ac6653aSJeff Kirsher priv->dma_buf_sz, DMA_FROM_DEVICE); 224683d7af64SGiuseppe CAVALLARO 22477ac6653aSJeff Kirsher if (netif_msg_pktdata(priv)) { 224883d7af64SGiuseppe CAVALLARO pr_debug("frame received (%dbytes)", frame_len); 22497ac6653aSJeff Kirsher print_pkt(skb->data, frame_len); 22507ac6653aSJeff Kirsher } 225183d7af64SGiuseppe CAVALLARO 2252b9381985SVince Bridgers stmmac_rx_vlan(priv->dev, skb); 2253b9381985SVince Bridgers 22547ac6653aSJeff Kirsher skb->protocol = eth_type_trans(skb, priv->dev); 22557ac6653aSJeff Kirsher 2256ceb69499SGiuseppe CAVALLARO if (unlikely(!coe)) 22577ac6653aSJeff Kirsher skb_checksum_none_assert(skb); 225862a2ab93SGiuseppe CAVALLARO else 22597ac6653aSJeff Kirsher skb->ip_summed = CHECKSUM_UNNECESSARY; 226062a2ab93SGiuseppe CAVALLARO 22617ac6653aSJeff Kirsher napi_gro_receive(&priv->napi, skb); 22627ac6653aSJeff Kirsher 22637ac6653aSJeff Kirsher priv->dev->stats.rx_packets++; 22647ac6653aSJeff Kirsher priv->dev->stats.rx_bytes += frame_len; 22657ac6653aSJeff Kirsher } 22667ac6653aSJeff Kirsher entry = next_entry; 22677ac6653aSJeff Kirsher } 22687ac6653aSJeff Kirsher 22697ac6653aSJeff Kirsher stmmac_rx_refill(priv); 22707ac6653aSJeff Kirsher 22717ac6653aSJeff Kirsher priv->xstats.rx_pkt_n += count; 22727ac6653aSJeff Kirsher 22737ac6653aSJeff Kirsher return count; 22747ac6653aSJeff Kirsher } 22757ac6653aSJeff Kirsher 22767ac6653aSJeff Kirsher /** 22777ac6653aSJeff Kirsher * stmmac_poll - stmmac poll method (NAPI) 22787ac6653aSJeff Kirsher * @napi : pointer to the napi structure. 22797ac6653aSJeff Kirsher * @budget : maximum number of packets that the current CPU can receive from 22807ac6653aSJeff Kirsher * all interfaces. 22817ac6653aSJeff Kirsher * Description : 22829125cdd1SGiuseppe CAVALLARO * To look at the incoming frames and clear the tx resources. 22837ac6653aSJeff Kirsher */ 22847ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget) 22857ac6653aSJeff Kirsher { 22867ac6653aSJeff Kirsher struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi); 22877ac6653aSJeff Kirsher int work_done = 0; 22887ac6653aSJeff Kirsher 22899125cdd1SGiuseppe CAVALLARO priv->xstats.napi_poll++; 22909125cdd1SGiuseppe CAVALLARO stmmac_tx_clean(priv); 22917ac6653aSJeff Kirsher 22929125cdd1SGiuseppe CAVALLARO work_done = stmmac_rx(priv, budget); 22937ac6653aSJeff Kirsher if (work_done < budget) { 22947ac6653aSJeff Kirsher napi_complete(napi); 22959125cdd1SGiuseppe CAVALLARO stmmac_enable_dma_irq(priv); 22967ac6653aSJeff Kirsher } 22977ac6653aSJeff Kirsher return work_done; 22987ac6653aSJeff Kirsher } 22997ac6653aSJeff Kirsher 23007ac6653aSJeff Kirsher /** 23017ac6653aSJeff Kirsher * stmmac_tx_timeout 23027ac6653aSJeff Kirsher * @dev : Pointer to net device structure 23037ac6653aSJeff Kirsher * Description: this function is called when a packet transmission fails to 23047284a3f1SGiuseppe CAVALLARO * complete within a reasonable time. The driver will mark the error in the 23057ac6653aSJeff Kirsher * netdev structure and arrange for the device to be reset to a sane state 23067ac6653aSJeff Kirsher * in order to transmit a new packet. 23077ac6653aSJeff Kirsher */ 23087ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev) 23097ac6653aSJeff Kirsher { 23107ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 23117ac6653aSJeff Kirsher 23127ac6653aSJeff Kirsher /* Clear Tx resources and restart transmitting again */ 23137ac6653aSJeff Kirsher stmmac_tx_err(priv); 23147ac6653aSJeff Kirsher } 23157ac6653aSJeff Kirsher 23167ac6653aSJeff Kirsher /** 231701789349SJiri Pirko * stmmac_set_rx_mode - entry point for multicast addressing 23187ac6653aSJeff Kirsher * @dev : pointer to the device structure 23197ac6653aSJeff Kirsher * Description: 23207ac6653aSJeff Kirsher * This function is a driver entry point which gets called by the kernel 23217ac6653aSJeff Kirsher * whenever multicast addresses must be enabled/disabled. 23227ac6653aSJeff Kirsher * Return value: 23237ac6653aSJeff Kirsher * void. 23247ac6653aSJeff Kirsher */ 232501789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev) 23267ac6653aSJeff Kirsher { 23277ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 23287ac6653aSJeff Kirsher 23293b57de95SVince Bridgers priv->hw->mac->set_filter(priv->hw, dev); 23307ac6653aSJeff Kirsher } 23317ac6653aSJeff Kirsher 23327ac6653aSJeff Kirsher /** 23337ac6653aSJeff Kirsher * stmmac_change_mtu - entry point to change MTU size for the device. 23347ac6653aSJeff Kirsher * @dev : device pointer. 23357ac6653aSJeff Kirsher * @new_mtu : the new MTU size for the device. 23367ac6653aSJeff Kirsher * Description: the Maximum Transfer Unit (MTU) is used by the network layer 23377ac6653aSJeff Kirsher * to drive packet transmission. Ethernet has an MTU of 1500 octets 23387ac6653aSJeff Kirsher * (ETH_DATA_LEN). This value can be changed with ifconfig. 23397ac6653aSJeff Kirsher * Return value: 23407ac6653aSJeff Kirsher * 0 on success and an appropriate (-)ve integer as defined in errno.h 23417ac6653aSJeff Kirsher * file on failure. 23427ac6653aSJeff Kirsher */ 23437ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu) 23447ac6653aSJeff Kirsher { 23457ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 23467ac6653aSJeff Kirsher int max_mtu; 23477ac6653aSJeff Kirsher 23487ac6653aSJeff Kirsher if (netif_running(dev)) { 23497ac6653aSJeff Kirsher pr_err("%s: must be stopped to change its MTU\n", dev->name); 23507ac6653aSJeff Kirsher return -EBUSY; 23517ac6653aSJeff Kirsher } 23527ac6653aSJeff Kirsher 235348febf7eSGiuseppe CAVALLARO if (priv->plat->enh_desc) 23547ac6653aSJeff Kirsher max_mtu = JUMBO_LEN; 23557ac6653aSJeff Kirsher else 235645db81e1SGiuseppe CAVALLARO max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN); 23577ac6653aSJeff Kirsher 23582618abb7SVince Bridgers if (priv->plat->maxmtu < max_mtu) 23592618abb7SVince Bridgers max_mtu = priv->plat->maxmtu; 23602618abb7SVince Bridgers 23617ac6653aSJeff Kirsher if ((new_mtu < 46) || (new_mtu > max_mtu)) { 23627ac6653aSJeff Kirsher pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu); 23637ac6653aSJeff Kirsher return -EINVAL; 23647ac6653aSJeff Kirsher } 23657ac6653aSJeff Kirsher 23667ac6653aSJeff Kirsher dev->mtu = new_mtu; 23677ac6653aSJeff Kirsher netdev_update_features(dev); 23687ac6653aSJeff Kirsher 23697ac6653aSJeff Kirsher return 0; 23707ac6653aSJeff Kirsher } 23717ac6653aSJeff Kirsher 2372c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev, 2373c8f44affSMichał Mirosław netdev_features_t features) 23747ac6653aSJeff Kirsher { 23757ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 23767ac6653aSJeff Kirsher 237738912bdbSDeepak SIKRI if (priv->plat->rx_coe == STMMAC_RX_COE_NONE) 23787ac6653aSJeff Kirsher features &= ~NETIF_F_RXCSUM; 2379d2afb5bdSGiuseppe CAVALLARO 23807ac6653aSJeff Kirsher if (!priv->plat->tx_coe) 23817ac6653aSJeff Kirsher features &= ~NETIF_F_ALL_CSUM; 23827ac6653aSJeff Kirsher 23837ac6653aSJeff Kirsher /* Some GMAC devices have a bugged Jumbo frame support that 23847ac6653aSJeff Kirsher * needs to have the Tx COE disabled for oversized frames 23857ac6653aSJeff Kirsher * (due to limited buffer sizes). In this case we disable 2386ceb69499SGiuseppe CAVALLARO * the TX csum insertionin the TDES and not use SF. 2387ceb69499SGiuseppe CAVALLARO */ 23887ac6653aSJeff Kirsher if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN)) 23897ac6653aSJeff Kirsher features &= ~NETIF_F_ALL_CSUM; 23907ac6653aSJeff Kirsher 23917ac6653aSJeff Kirsher return features; 23927ac6653aSJeff Kirsher } 23937ac6653aSJeff Kirsher 2394d2afb5bdSGiuseppe CAVALLARO static int stmmac_set_features(struct net_device *netdev, 2395d2afb5bdSGiuseppe CAVALLARO netdev_features_t features) 2396d2afb5bdSGiuseppe CAVALLARO { 2397d2afb5bdSGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(netdev); 2398d2afb5bdSGiuseppe CAVALLARO 2399d2afb5bdSGiuseppe CAVALLARO /* Keep the COE Type in case of csum is supporting */ 2400d2afb5bdSGiuseppe CAVALLARO if (features & NETIF_F_RXCSUM) 2401d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = priv->plat->rx_coe; 2402d2afb5bdSGiuseppe CAVALLARO else 2403d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = 0; 2404d2afb5bdSGiuseppe CAVALLARO /* No check needed because rx_coe has been set before and it will be 2405d2afb5bdSGiuseppe CAVALLARO * fixed in case of issue. 2406d2afb5bdSGiuseppe CAVALLARO */ 2407d2afb5bdSGiuseppe CAVALLARO priv->hw->mac->rx_ipc(priv->hw); 2408d2afb5bdSGiuseppe CAVALLARO 2409d2afb5bdSGiuseppe CAVALLARO return 0; 2410d2afb5bdSGiuseppe CAVALLARO } 2411d2afb5bdSGiuseppe CAVALLARO 241232ceabcaSGiuseppe CAVALLARO /** 241332ceabcaSGiuseppe CAVALLARO * stmmac_interrupt - main ISR 241432ceabcaSGiuseppe CAVALLARO * @irq: interrupt number. 241532ceabcaSGiuseppe CAVALLARO * @dev_id: to pass the net device pointer. 241632ceabcaSGiuseppe CAVALLARO * Description: this is the main driver interrupt service routine. 2417732fdf0eSGiuseppe CAVALLARO * It can call: 2418732fdf0eSGiuseppe CAVALLARO * o DMA service routine (to manage incoming frame reception and transmission 2419732fdf0eSGiuseppe CAVALLARO * status) 2420732fdf0eSGiuseppe CAVALLARO * o Core interrupts to manage: remote wake-up, management counter, LPI 242132ceabcaSGiuseppe CAVALLARO * interrupts. 242232ceabcaSGiuseppe CAVALLARO */ 24237ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id) 24247ac6653aSJeff Kirsher { 24257ac6653aSJeff Kirsher struct net_device *dev = (struct net_device *)dev_id; 24267ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 24277ac6653aSJeff Kirsher 242889f7f2cfSSrinivas Kandagatla if (priv->irq_wake) 242989f7f2cfSSrinivas Kandagatla pm_wakeup_event(priv->device, 0); 243089f7f2cfSSrinivas Kandagatla 24317ac6653aSJeff Kirsher if (unlikely(!dev)) { 24327ac6653aSJeff Kirsher pr_err("%s: invalid dev pointer\n", __func__); 24337ac6653aSJeff Kirsher return IRQ_NONE; 24347ac6653aSJeff Kirsher } 24357ac6653aSJeff Kirsher 24367ac6653aSJeff Kirsher /* To handle GMAC own interrupts */ 2437d765955dSGiuseppe CAVALLARO if (priv->plat->has_gmac) { 24387ed24bbeSVince Bridgers int status = priv->hw->mac->host_irq_status(priv->hw, 24390982a0f6SGiuseppe CAVALLARO &priv->xstats); 2440d765955dSGiuseppe CAVALLARO if (unlikely(status)) { 2441d765955dSGiuseppe CAVALLARO /* For LPI we need to save the tx status */ 24420982a0f6SGiuseppe CAVALLARO if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE) 2443d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = true; 24440982a0f6SGiuseppe CAVALLARO if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE) 2445d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = false; 2446d765955dSGiuseppe CAVALLARO } 2447d765955dSGiuseppe CAVALLARO } 2448d765955dSGiuseppe CAVALLARO 2449d765955dSGiuseppe CAVALLARO /* To handle DMA interrupts */ 24507ac6653aSJeff Kirsher stmmac_dma_interrupt(priv); 24517ac6653aSJeff Kirsher 24527ac6653aSJeff Kirsher return IRQ_HANDLED; 24537ac6653aSJeff Kirsher } 24547ac6653aSJeff Kirsher 24557ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 24567ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools 2457ceb69499SGiuseppe CAVALLARO * to allow network I/O with interrupts disabled. 2458ceb69499SGiuseppe CAVALLARO */ 24597ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev) 24607ac6653aSJeff Kirsher { 24617ac6653aSJeff Kirsher disable_irq(dev->irq); 24627ac6653aSJeff Kirsher stmmac_interrupt(dev->irq, dev); 24637ac6653aSJeff Kirsher enable_irq(dev->irq); 24647ac6653aSJeff Kirsher } 24657ac6653aSJeff Kirsher #endif 24667ac6653aSJeff Kirsher 24677ac6653aSJeff Kirsher /** 24687ac6653aSJeff Kirsher * stmmac_ioctl - Entry point for the Ioctl 24697ac6653aSJeff Kirsher * @dev: Device pointer. 24707ac6653aSJeff Kirsher * @rq: An IOCTL specefic structure, that can contain a pointer to 24717ac6653aSJeff Kirsher * a proprietary structure used to pass information to the driver. 24727ac6653aSJeff Kirsher * @cmd: IOCTL command 24737ac6653aSJeff Kirsher * Description: 247432ceabcaSGiuseppe CAVALLARO * Currently it supports the phy_mii_ioctl(...) and HW time stamping. 24757ac6653aSJeff Kirsher */ 24767ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 24777ac6653aSJeff Kirsher { 24787ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 2479891434b1SRayagond Kokatanur int ret = -EOPNOTSUPP; 24807ac6653aSJeff Kirsher 24817ac6653aSJeff Kirsher if (!netif_running(dev)) 24827ac6653aSJeff Kirsher return -EINVAL; 24837ac6653aSJeff Kirsher 2484891434b1SRayagond Kokatanur switch (cmd) { 2485891434b1SRayagond Kokatanur case SIOCGMIIPHY: 2486891434b1SRayagond Kokatanur case SIOCGMIIREG: 2487891434b1SRayagond Kokatanur case SIOCSMIIREG: 24887ac6653aSJeff Kirsher if (!priv->phydev) 24897ac6653aSJeff Kirsher return -EINVAL; 24907ac6653aSJeff Kirsher ret = phy_mii_ioctl(priv->phydev, rq, cmd); 2491891434b1SRayagond Kokatanur break; 2492891434b1SRayagond Kokatanur case SIOCSHWTSTAMP: 2493891434b1SRayagond Kokatanur ret = stmmac_hwtstamp_ioctl(dev, rq); 2494891434b1SRayagond Kokatanur break; 2495891434b1SRayagond Kokatanur default: 2496891434b1SRayagond Kokatanur break; 2497891434b1SRayagond Kokatanur } 24987ac6653aSJeff Kirsher 24997ac6653aSJeff Kirsher return ret; 25007ac6653aSJeff Kirsher } 25017ac6653aSJeff Kirsher 250250fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 25037ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir; 25047ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_rings_status; 2505e7434821SGiuseppe CAVALLARO static struct dentry *stmmac_dma_cap; 25067ac29055SGiuseppe CAVALLARO 2507c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc, 2508c24602efSGiuseppe CAVALLARO struct seq_file *seq) 25097ac29055SGiuseppe CAVALLARO { 25107ac29055SGiuseppe CAVALLARO int i; 2511c24602efSGiuseppe CAVALLARO struct dma_extended_desc *ep = (struct dma_extended_desc *)head; 2512c24602efSGiuseppe CAVALLARO struct dma_desc *p = (struct dma_desc *)head; 25137ac29055SGiuseppe CAVALLARO 2514c24602efSGiuseppe CAVALLARO for (i = 0; i < size; i++) { 2515c24602efSGiuseppe CAVALLARO u64 x; 2516c24602efSGiuseppe CAVALLARO if (extend_desc) { 2517c24602efSGiuseppe CAVALLARO x = *(u64 *) ep; 2518c24602efSGiuseppe CAVALLARO seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 2519c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 2520c24602efSGiuseppe CAVALLARO (unsigned int)x, (unsigned int)(x >> 32), 2521c24602efSGiuseppe CAVALLARO ep->basic.des2, ep->basic.des3); 2522c24602efSGiuseppe CAVALLARO ep++; 2523c24602efSGiuseppe CAVALLARO } else { 2524c24602efSGiuseppe CAVALLARO x = *(u64 *) p; 2525c24602efSGiuseppe CAVALLARO seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 2526c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 2527c24602efSGiuseppe CAVALLARO (unsigned int)x, (unsigned int)(x >> 32), 2528c24602efSGiuseppe CAVALLARO p->des2, p->des3); 2529c24602efSGiuseppe CAVALLARO p++; 2530c24602efSGiuseppe CAVALLARO } 25317ac29055SGiuseppe CAVALLARO seq_printf(seq, "\n"); 25327ac29055SGiuseppe CAVALLARO } 2533c24602efSGiuseppe CAVALLARO } 25347ac29055SGiuseppe CAVALLARO 2535c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v) 2536c24602efSGiuseppe CAVALLARO { 2537c24602efSGiuseppe CAVALLARO struct net_device *dev = seq->private; 2538c24602efSGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(dev); 2539c24602efSGiuseppe CAVALLARO unsigned int txsize = priv->dma_tx_size; 2540c24602efSGiuseppe CAVALLARO unsigned int rxsize = priv->dma_rx_size; 25417ac29055SGiuseppe CAVALLARO 2542c24602efSGiuseppe CAVALLARO if (priv->extend_desc) { 2543c24602efSGiuseppe CAVALLARO seq_printf(seq, "Extended RX descriptor ring:\n"); 2544c24602efSGiuseppe CAVALLARO sysfs_display_ring((void *)priv->dma_erx, rxsize, 1, seq); 2545c24602efSGiuseppe CAVALLARO seq_printf(seq, "Extended TX descriptor ring:\n"); 2546c24602efSGiuseppe CAVALLARO sysfs_display_ring((void *)priv->dma_etx, txsize, 1, seq); 2547c24602efSGiuseppe CAVALLARO } else { 2548c24602efSGiuseppe CAVALLARO seq_printf(seq, "RX descriptor ring:\n"); 2549c24602efSGiuseppe CAVALLARO sysfs_display_ring((void *)priv->dma_rx, rxsize, 0, seq); 2550c24602efSGiuseppe CAVALLARO seq_printf(seq, "TX descriptor ring:\n"); 2551c24602efSGiuseppe CAVALLARO sysfs_display_ring((void *)priv->dma_tx, txsize, 0, seq); 25527ac29055SGiuseppe CAVALLARO } 25537ac29055SGiuseppe CAVALLARO 25547ac29055SGiuseppe CAVALLARO return 0; 25557ac29055SGiuseppe CAVALLARO } 25567ac29055SGiuseppe CAVALLARO 25577ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file) 25587ac29055SGiuseppe CAVALLARO { 25597ac29055SGiuseppe CAVALLARO return single_open(file, stmmac_sysfs_ring_read, inode->i_private); 25607ac29055SGiuseppe CAVALLARO } 25617ac29055SGiuseppe CAVALLARO 25627ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = { 25637ac29055SGiuseppe CAVALLARO .owner = THIS_MODULE, 25647ac29055SGiuseppe CAVALLARO .open = stmmac_sysfs_ring_open, 25657ac29055SGiuseppe CAVALLARO .read = seq_read, 25667ac29055SGiuseppe CAVALLARO .llseek = seq_lseek, 256774863948SDjalal Harouni .release = single_release, 25687ac29055SGiuseppe CAVALLARO }; 25697ac29055SGiuseppe CAVALLARO 2570e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v) 2571e7434821SGiuseppe CAVALLARO { 2572e7434821SGiuseppe CAVALLARO struct net_device *dev = seq->private; 2573e7434821SGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(dev); 2574e7434821SGiuseppe CAVALLARO 257519e30c14SGiuseppe CAVALLARO if (!priv->hw_cap_support) { 2576e7434821SGiuseppe CAVALLARO seq_printf(seq, "DMA HW features not supported\n"); 2577e7434821SGiuseppe CAVALLARO return 0; 2578e7434821SGiuseppe CAVALLARO } 2579e7434821SGiuseppe CAVALLARO 2580e7434821SGiuseppe CAVALLARO seq_printf(seq, "==============================\n"); 2581e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tDMA HW features\n"); 2582e7434821SGiuseppe CAVALLARO seq_printf(seq, "==============================\n"); 2583e7434821SGiuseppe CAVALLARO 2584e7434821SGiuseppe CAVALLARO seq_printf(seq, "\t10/100 Mbps %s\n", 2585e7434821SGiuseppe CAVALLARO (priv->dma_cap.mbps_10_100) ? "Y" : "N"); 2586e7434821SGiuseppe CAVALLARO seq_printf(seq, "\t1000 Mbps %s\n", 2587e7434821SGiuseppe CAVALLARO (priv->dma_cap.mbps_1000) ? "Y" : "N"); 2588e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tHalf duple %s\n", 2589e7434821SGiuseppe CAVALLARO (priv->dma_cap.half_duplex) ? "Y" : "N"); 2590e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tHash Filter: %s\n", 2591e7434821SGiuseppe CAVALLARO (priv->dma_cap.hash_filter) ? "Y" : "N"); 2592e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tMultiple MAC address registers: %s\n", 2593e7434821SGiuseppe CAVALLARO (priv->dma_cap.multi_addr) ? "Y" : "N"); 2594e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n", 2595e7434821SGiuseppe CAVALLARO (priv->dma_cap.pcs) ? "Y" : "N"); 2596e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tSMA (MDIO) Interface: %s\n", 2597e7434821SGiuseppe CAVALLARO (priv->dma_cap.sma_mdio) ? "Y" : "N"); 2598e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPMT Remote wake up: %s\n", 2599e7434821SGiuseppe CAVALLARO (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N"); 2600e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPMT Magic Frame: %s\n", 2601e7434821SGiuseppe CAVALLARO (priv->dma_cap.pmt_magic_frame) ? "Y" : "N"); 2602e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tRMON module: %s\n", 2603e7434821SGiuseppe CAVALLARO (priv->dma_cap.rmon) ? "Y" : "N"); 2604e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n", 2605e7434821SGiuseppe CAVALLARO (priv->dma_cap.time_stamp) ? "Y" : "N"); 2606e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n", 2607e7434821SGiuseppe CAVALLARO (priv->dma_cap.atime_stamp) ? "Y" : "N"); 2608e7434821SGiuseppe CAVALLARO seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n", 2609e7434821SGiuseppe CAVALLARO (priv->dma_cap.eee) ? "Y" : "N"); 2610e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N"); 2611e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tChecksum Offload in TX: %s\n", 2612e7434821SGiuseppe CAVALLARO (priv->dma_cap.tx_coe) ? "Y" : "N"); 2613e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n", 2614e7434821SGiuseppe CAVALLARO (priv->dma_cap.rx_coe_type1) ? "Y" : "N"); 2615e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n", 2616e7434821SGiuseppe CAVALLARO (priv->dma_cap.rx_coe_type2) ? "Y" : "N"); 2617e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n", 2618e7434821SGiuseppe CAVALLARO (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N"); 2619e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tNumber of Additional RX channel: %d\n", 2620e7434821SGiuseppe CAVALLARO priv->dma_cap.number_rx_channel); 2621e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tNumber of Additional TX channel: %d\n", 2622e7434821SGiuseppe CAVALLARO priv->dma_cap.number_tx_channel); 2623e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tEnhanced descriptors: %s\n", 2624e7434821SGiuseppe CAVALLARO (priv->dma_cap.enh_desc) ? "Y" : "N"); 2625e7434821SGiuseppe CAVALLARO 2626e7434821SGiuseppe CAVALLARO return 0; 2627e7434821SGiuseppe CAVALLARO } 2628e7434821SGiuseppe CAVALLARO 2629e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file) 2630e7434821SGiuseppe CAVALLARO { 2631e7434821SGiuseppe CAVALLARO return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private); 2632e7434821SGiuseppe CAVALLARO } 2633e7434821SGiuseppe CAVALLARO 2634e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = { 2635e7434821SGiuseppe CAVALLARO .owner = THIS_MODULE, 2636e7434821SGiuseppe CAVALLARO .open = stmmac_sysfs_dma_cap_open, 2637e7434821SGiuseppe CAVALLARO .read = seq_read, 2638e7434821SGiuseppe CAVALLARO .llseek = seq_lseek, 263974863948SDjalal Harouni .release = single_release, 2640e7434821SGiuseppe CAVALLARO }; 2641e7434821SGiuseppe CAVALLARO 26427ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev) 26437ac29055SGiuseppe CAVALLARO { 26447ac29055SGiuseppe CAVALLARO /* Create debugfs entries */ 26457ac29055SGiuseppe CAVALLARO stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL); 26467ac29055SGiuseppe CAVALLARO 26477ac29055SGiuseppe CAVALLARO if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) { 26487ac29055SGiuseppe CAVALLARO pr_err("ERROR %s, debugfs create directory failed\n", 26497ac29055SGiuseppe CAVALLARO STMMAC_RESOURCE_NAME); 26507ac29055SGiuseppe CAVALLARO 26517ac29055SGiuseppe CAVALLARO return -ENOMEM; 26527ac29055SGiuseppe CAVALLARO } 26537ac29055SGiuseppe CAVALLARO 26547ac29055SGiuseppe CAVALLARO /* Entry to report DMA RX/TX rings */ 26557ac29055SGiuseppe CAVALLARO stmmac_rings_status = debugfs_create_file("descriptors_status", 26567ac29055SGiuseppe CAVALLARO S_IRUGO, stmmac_fs_dir, dev, 26577ac29055SGiuseppe CAVALLARO &stmmac_rings_status_fops); 26587ac29055SGiuseppe CAVALLARO 26597ac29055SGiuseppe CAVALLARO if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) { 26607ac29055SGiuseppe CAVALLARO pr_info("ERROR creating stmmac ring debugfs file\n"); 26617ac29055SGiuseppe CAVALLARO debugfs_remove(stmmac_fs_dir); 26627ac29055SGiuseppe CAVALLARO 26637ac29055SGiuseppe CAVALLARO return -ENOMEM; 26647ac29055SGiuseppe CAVALLARO } 26657ac29055SGiuseppe CAVALLARO 2666e7434821SGiuseppe CAVALLARO /* Entry to report the DMA HW features */ 2667e7434821SGiuseppe CAVALLARO stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir, 2668e7434821SGiuseppe CAVALLARO dev, &stmmac_dma_cap_fops); 2669e7434821SGiuseppe CAVALLARO 2670e7434821SGiuseppe CAVALLARO if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) { 2671e7434821SGiuseppe CAVALLARO pr_info("ERROR creating stmmac MMC debugfs file\n"); 2672e7434821SGiuseppe CAVALLARO debugfs_remove(stmmac_rings_status); 2673e7434821SGiuseppe CAVALLARO debugfs_remove(stmmac_fs_dir); 2674e7434821SGiuseppe CAVALLARO 2675e7434821SGiuseppe CAVALLARO return -ENOMEM; 2676e7434821SGiuseppe CAVALLARO } 2677e7434821SGiuseppe CAVALLARO 26787ac29055SGiuseppe CAVALLARO return 0; 26797ac29055SGiuseppe CAVALLARO } 26807ac29055SGiuseppe CAVALLARO 26817ac29055SGiuseppe CAVALLARO static void stmmac_exit_fs(void) 26827ac29055SGiuseppe CAVALLARO { 26837ac29055SGiuseppe CAVALLARO debugfs_remove(stmmac_rings_status); 2684e7434821SGiuseppe CAVALLARO debugfs_remove(stmmac_dma_cap); 26857ac29055SGiuseppe CAVALLARO debugfs_remove(stmmac_fs_dir); 26867ac29055SGiuseppe CAVALLARO } 268750fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */ 26887ac29055SGiuseppe CAVALLARO 26897ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = { 26907ac6653aSJeff Kirsher .ndo_open = stmmac_open, 26917ac6653aSJeff Kirsher .ndo_start_xmit = stmmac_xmit, 26927ac6653aSJeff Kirsher .ndo_stop = stmmac_release, 26937ac6653aSJeff Kirsher .ndo_change_mtu = stmmac_change_mtu, 26947ac6653aSJeff Kirsher .ndo_fix_features = stmmac_fix_features, 2695d2afb5bdSGiuseppe CAVALLARO .ndo_set_features = stmmac_set_features, 269601789349SJiri Pirko .ndo_set_rx_mode = stmmac_set_rx_mode, 26977ac6653aSJeff Kirsher .ndo_tx_timeout = stmmac_tx_timeout, 26987ac6653aSJeff Kirsher .ndo_do_ioctl = stmmac_ioctl, 26997ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 27007ac6653aSJeff Kirsher .ndo_poll_controller = stmmac_poll_controller, 27017ac6653aSJeff Kirsher #endif 27027ac6653aSJeff Kirsher .ndo_set_mac_address = eth_mac_addr, 27037ac6653aSJeff Kirsher }; 27047ac6653aSJeff Kirsher 27057ac6653aSJeff Kirsher /** 2706cf3f047bSGiuseppe CAVALLARO * stmmac_hw_init - Init the MAC device 270732ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 2708732fdf0eSGiuseppe CAVALLARO * Description: this function is to configure the MAC device according to 2709732fdf0eSGiuseppe CAVALLARO * some platform parameters or the HW capability register. It prepares the 2710732fdf0eSGiuseppe CAVALLARO * driver to use either ring or chain modes and to setup either enhanced or 2711732fdf0eSGiuseppe CAVALLARO * normal descriptors. 2712cf3f047bSGiuseppe CAVALLARO */ 2713cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv) 2714cf3f047bSGiuseppe CAVALLARO { 2715cf3f047bSGiuseppe CAVALLARO struct mac_device_info *mac; 2716cf3f047bSGiuseppe CAVALLARO 2717cf3f047bSGiuseppe CAVALLARO /* Identify the MAC HW device */ 271803f2eecdSMarc Kleine-Budde if (priv->plat->has_gmac) { 271903f2eecdSMarc Kleine-Budde priv->dev->priv_flags |= IFF_UNICAST_FLT; 27203b57de95SVince Bridgers mac = dwmac1000_setup(priv->ioaddr, 27213b57de95SVince Bridgers priv->plat->multicast_filter_bins, 27223b57de95SVince Bridgers priv->plat->unicast_filter_entries); 272303f2eecdSMarc Kleine-Budde } else { 2724cf3f047bSGiuseppe CAVALLARO mac = dwmac100_setup(priv->ioaddr); 272503f2eecdSMarc Kleine-Budde } 2726cf3f047bSGiuseppe CAVALLARO if (!mac) 2727cf3f047bSGiuseppe CAVALLARO return -ENOMEM; 2728cf3f047bSGiuseppe CAVALLARO 2729cf3f047bSGiuseppe CAVALLARO priv->hw = mac; 2730cf3f047bSGiuseppe CAVALLARO 2731cf3f047bSGiuseppe CAVALLARO /* Get and dump the chip ID */ 2732cffb13f4SGiuseppe CAVALLARO priv->synopsys_id = stmmac_get_synopsys_id(priv); 2733cf3f047bSGiuseppe CAVALLARO 27344a7d666aSGiuseppe CAVALLARO /* To use the chained or ring mode */ 27354a7d666aSGiuseppe CAVALLARO if (chain_mode) { 273629896a67SGiuseppe CAVALLARO priv->hw->mode = &chain_mode_ops; 27374a7d666aSGiuseppe CAVALLARO pr_info(" Chain mode enabled\n"); 27384a7d666aSGiuseppe CAVALLARO priv->mode = STMMAC_CHAIN_MODE; 27394a7d666aSGiuseppe CAVALLARO } else { 274029896a67SGiuseppe CAVALLARO priv->hw->mode = &ring_mode_ops; 27414a7d666aSGiuseppe CAVALLARO pr_info(" Ring mode enabled\n"); 27424a7d666aSGiuseppe CAVALLARO priv->mode = STMMAC_RING_MODE; 27434a7d666aSGiuseppe CAVALLARO } 27444a7d666aSGiuseppe CAVALLARO 2745cf3f047bSGiuseppe CAVALLARO /* Get the HW capability (new GMAC newer than 3.50a) */ 2746cf3f047bSGiuseppe CAVALLARO priv->hw_cap_support = stmmac_get_hw_features(priv); 2747cf3f047bSGiuseppe CAVALLARO if (priv->hw_cap_support) { 2748cf3f047bSGiuseppe CAVALLARO pr_info(" DMA HW capability register supported"); 2749cf3f047bSGiuseppe CAVALLARO 2750cf3f047bSGiuseppe CAVALLARO /* We can override some gmac/dma configuration fields: e.g. 2751cf3f047bSGiuseppe CAVALLARO * enh_desc, tx_coe (e.g. that are passed through the 2752cf3f047bSGiuseppe CAVALLARO * platform) with the values from the HW capability 2753cf3f047bSGiuseppe CAVALLARO * register (if supported). 2754cf3f047bSGiuseppe CAVALLARO */ 2755cf3f047bSGiuseppe CAVALLARO priv->plat->enh_desc = priv->dma_cap.enh_desc; 2756cf3f047bSGiuseppe CAVALLARO priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; 275738912bdbSDeepak SIKRI 2758dec2165fSSonic Zhang /* TXCOE doesn't work in thresh DMA mode */ 2759dec2165fSSonic Zhang if (priv->plat->force_thresh_dma_mode) 2760dec2165fSSonic Zhang priv->plat->tx_coe = 0; 2761dec2165fSSonic Zhang else 276238912bdbSDeepak SIKRI priv->plat->tx_coe = priv->dma_cap.tx_coe; 276338912bdbSDeepak SIKRI 276438912bdbSDeepak SIKRI if (priv->dma_cap.rx_coe_type2) 276538912bdbSDeepak SIKRI priv->plat->rx_coe = STMMAC_RX_COE_TYPE2; 276638912bdbSDeepak SIKRI else if (priv->dma_cap.rx_coe_type1) 276738912bdbSDeepak SIKRI priv->plat->rx_coe = STMMAC_RX_COE_TYPE1; 276838912bdbSDeepak SIKRI 2769cf3f047bSGiuseppe CAVALLARO } else 2770cf3f047bSGiuseppe CAVALLARO pr_info(" No HW DMA feature register supported"); 2771cf3f047bSGiuseppe CAVALLARO 277261369d02SByungho An /* To use alternate (extended) or normal descriptor structures */ 277361369d02SByungho An stmmac_selec_desc_mode(priv); 277461369d02SByungho An 2775d2afb5bdSGiuseppe CAVALLARO if (priv->plat->rx_coe) { 2776d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = priv->plat->rx_coe; 277738912bdbSDeepak SIKRI pr_info(" RX Checksum Offload Engine supported (type %d)\n", 277838912bdbSDeepak SIKRI priv->plat->rx_coe); 2779d2afb5bdSGiuseppe CAVALLARO } 2780cf3f047bSGiuseppe CAVALLARO if (priv->plat->tx_coe) 2781cf3f047bSGiuseppe CAVALLARO pr_info(" TX Checksum insertion supported\n"); 2782cf3f047bSGiuseppe CAVALLARO 2783cf3f047bSGiuseppe CAVALLARO if (priv->plat->pmt) { 2784cf3f047bSGiuseppe CAVALLARO pr_info(" Wake-Up On Lan supported\n"); 2785cf3f047bSGiuseppe CAVALLARO device_set_wakeup_capable(priv->device, 1); 2786cf3f047bSGiuseppe CAVALLARO } 2787cf3f047bSGiuseppe CAVALLARO 2788c24602efSGiuseppe CAVALLARO return 0; 2789cf3f047bSGiuseppe CAVALLARO } 2790cf3f047bSGiuseppe CAVALLARO 2791cf3f047bSGiuseppe CAVALLARO /** 2792bfab27a1SGiuseppe CAVALLARO * stmmac_dvr_probe 2793bfab27a1SGiuseppe CAVALLARO * @device: device pointer 2794ff3dd78cSGiuseppe CAVALLARO * @plat_dat: platform data pointer 2795ff3dd78cSGiuseppe CAVALLARO * @addr: iobase memory address 2796bfab27a1SGiuseppe CAVALLARO * Description: this is the main probe function used to 2797bfab27a1SGiuseppe CAVALLARO * call the alloc_etherdev, allocate the priv structure. 27987ac6653aSJeff Kirsher */ 2799bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *stmmac_dvr_probe(struct device *device, 2800cf3f047bSGiuseppe CAVALLARO struct plat_stmmacenet_data *plat_dat, 2801cf3f047bSGiuseppe CAVALLARO void __iomem *addr) 28027ac6653aSJeff Kirsher { 28037ac6653aSJeff Kirsher int ret = 0; 2804bfab27a1SGiuseppe CAVALLARO struct net_device *ndev = NULL; 2805bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *priv; 28067ac6653aSJeff Kirsher 2807bfab27a1SGiuseppe CAVALLARO ndev = alloc_etherdev(sizeof(struct stmmac_priv)); 280841de8d4cSJoe Perches if (!ndev) 2809bfab27a1SGiuseppe CAVALLARO return NULL; 28107ac6653aSJeff Kirsher 2811bfab27a1SGiuseppe CAVALLARO SET_NETDEV_DEV(ndev, device); 28127ac6653aSJeff Kirsher 2813bfab27a1SGiuseppe CAVALLARO priv = netdev_priv(ndev); 2814bfab27a1SGiuseppe CAVALLARO priv->device = device; 2815bfab27a1SGiuseppe CAVALLARO priv->dev = ndev; 2816bfab27a1SGiuseppe CAVALLARO 2817bfab27a1SGiuseppe CAVALLARO stmmac_set_ethtool_ops(ndev); 2818cf3f047bSGiuseppe CAVALLARO priv->pause = pause; 2819cf3f047bSGiuseppe CAVALLARO priv->plat = plat_dat; 2820cf3f047bSGiuseppe CAVALLARO priv->ioaddr = addr; 2821cf3f047bSGiuseppe CAVALLARO priv->dev->base_addr = (unsigned long)addr; 2822bfab27a1SGiuseppe CAVALLARO 2823cf3f047bSGiuseppe CAVALLARO /* Verify driver arguments */ 2824cf3f047bSGiuseppe CAVALLARO stmmac_verify_args(); 2825cf3f047bSGiuseppe CAVALLARO 2826cf3f047bSGiuseppe CAVALLARO /* Override with kernel parameters if supplied XXX CRS XXX 2827ceb69499SGiuseppe CAVALLARO * this needs to have multiple instances 2828ceb69499SGiuseppe CAVALLARO */ 2829cf3f047bSGiuseppe CAVALLARO if ((phyaddr >= 0) && (phyaddr <= 31)) 2830cf3f047bSGiuseppe CAVALLARO priv->plat->phy_addr = phyaddr; 2831cf3f047bSGiuseppe CAVALLARO 283262866e98SChen-Yu Tsai priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME); 283362866e98SChen-Yu Tsai if (IS_ERR(priv->stmmac_clk)) { 283462866e98SChen-Yu Tsai dev_warn(priv->device, "%s: warning: cannot get CSR clock\n", 283562866e98SChen-Yu Tsai __func__); 2836c5bb86c3SKweh, Hock Leong /* If failed to obtain stmmac_clk and specific clk_csr value 2837c5bb86c3SKweh, Hock Leong * is NOT passed from the platform, probe fail. 2838c5bb86c3SKweh, Hock Leong */ 2839c5bb86c3SKweh, Hock Leong if (!priv->plat->clk_csr) { 2840c5e4ddbdSChen-Yu Tsai ret = PTR_ERR(priv->stmmac_clk); 284162866e98SChen-Yu Tsai goto error_clk_get; 2842c5bb86c3SKweh, Hock Leong } else { 2843c5bb86c3SKweh, Hock Leong priv->stmmac_clk = NULL; 2844c5bb86c3SKweh, Hock Leong } 284562866e98SChen-Yu Tsai } 284662866e98SChen-Yu Tsai clk_prepare_enable(priv->stmmac_clk); 284762866e98SChen-Yu Tsai 2848c5e4ddbdSChen-Yu Tsai priv->stmmac_rst = devm_reset_control_get(priv->device, 2849c5e4ddbdSChen-Yu Tsai STMMAC_RESOURCE_NAME); 2850c5e4ddbdSChen-Yu Tsai if (IS_ERR(priv->stmmac_rst)) { 2851c5e4ddbdSChen-Yu Tsai if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) { 2852c5e4ddbdSChen-Yu Tsai ret = -EPROBE_DEFER; 2853c5e4ddbdSChen-Yu Tsai goto error_hw_init; 2854c5e4ddbdSChen-Yu Tsai } 2855c5e4ddbdSChen-Yu Tsai dev_info(priv->device, "no reset control found\n"); 2856c5e4ddbdSChen-Yu Tsai priv->stmmac_rst = NULL; 2857c5e4ddbdSChen-Yu Tsai } 2858c5e4ddbdSChen-Yu Tsai if (priv->stmmac_rst) 2859c5e4ddbdSChen-Yu Tsai reset_control_deassert(priv->stmmac_rst); 2860c5e4ddbdSChen-Yu Tsai 2861cf3f047bSGiuseppe CAVALLARO /* Init MAC and get the capabilities */ 2862c24602efSGiuseppe CAVALLARO ret = stmmac_hw_init(priv); 2863c24602efSGiuseppe CAVALLARO if (ret) 286462866e98SChen-Yu Tsai goto error_hw_init; 2865cf3f047bSGiuseppe CAVALLARO 2866cf3f047bSGiuseppe CAVALLARO ndev->netdev_ops = &stmmac_netdev_ops; 2867cf3f047bSGiuseppe CAVALLARO 2868cf3f047bSGiuseppe CAVALLARO ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | 2869cf3f047bSGiuseppe CAVALLARO NETIF_F_RXCSUM; 2870bfab27a1SGiuseppe CAVALLARO ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; 2871bfab27a1SGiuseppe CAVALLARO ndev->watchdog_timeo = msecs_to_jiffies(watchdog); 28727ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED 28737ac6653aSJeff Kirsher /* Both mac100 and gmac support receive VLAN tag detection */ 2874f646968fSPatrick McHardy ndev->features |= NETIF_F_HW_VLAN_CTAG_RX; 28757ac6653aSJeff Kirsher #endif 28767ac6653aSJeff Kirsher priv->msg_enable = netif_msg_init(debug, default_msg_level); 28777ac6653aSJeff Kirsher 28787ac6653aSJeff Kirsher if (flow_ctrl) 28797ac6653aSJeff Kirsher priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ 28807ac6653aSJeff Kirsher 288162a2ab93SGiuseppe CAVALLARO /* Rx Watchdog is available in the COREs newer than the 3.40. 288262a2ab93SGiuseppe CAVALLARO * In some case, for example on bugged HW this feature 288362a2ab93SGiuseppe CAVALLARO * has to be disable and this can be done by passing the 288462a2ab93SGiuseppe CAVALLARO * riwt_off field from the platform. 288562a2ab93SGiuseppe CAVALLARO */ 288662a2ab93SGiuseppe CAVALLARO if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) { 288762a2ab93SGiuseppe CAVALLARO priv->use_riwt = 1; 288862a2ab93SGiuseppe CAVALLARO pr_info(" Enable RX Mitigation via HW Watchdog Timer\n"); 288962a2ab93SGiuseppe CAVALLARO } 289062a2ab93SGiuseppe CAVALLARO 2891bfab27a1SGiuseppe CAVALLARO netif_napi_add(ndev, &priv->napi, stmmac_poll, 64); 28927ac6653aSJeff Kirsher 28937ac6653aSJeff Kirsher spin_lock_init(&priv->lock); 2894a9097a96SGiuseppe CAVALLARO spin_lock_init(&priv->tx_lock); 28957ac6653aSJeff Kirsher 2896bfab27a1SGiuseppe CAVALLARO ret = register_netdev(ndev); 28977ac6653aSJeff Kirsher if (ret) { 2898cf3f047bSGiuseppe CAVALLARO pr_err("%s: ERROR %i registering the device\n", __func__, ret); 28996a81c26fSViresh Kumar goto error_netdev_register; 29007ac6653aSJeff Kirsher } 29017ac6653aSJeff Kirsher 2902cd7201f4SGiuseppe CAVALLARO /* If a specific clk_csr value is passed from the platform 2903cd7201f4SGiuseppe CAVALLARO * this means that the CSR Clock Range selection cannot be 2904cd7201f4SGiuseppe CAVALLARO * changed at run-time and it is fixed. Viceversa the driver'll try to 2905cd7201f4SGiuseppe CAVALLARO * set the MDC clock dynamically according to the csr actual 2906cd7201f4SGiuseppe CAVALLARO * clock input. 2907cd7201f4SGiuseppe CAVALLARO */ 2908cd7201f4SGiuseppe CAVALLARO if (!priv->plat->clk_csr) 2909cd7201f4SGiuseppe CAVALLARO stmmac_clk_csr_set(priv); 2910cd7201f4SGiuseppe CAVALLARO else 2911cd7201f4SGiuseppe CAVALLARO priv->clk_csr = priv->plat->clk_csr; 2912cd7201f4SGiuseppe CAVALLARO 2913e58bb43fSGiuseppe CAVALLARO stmmac_check_pcs_mode(priv); 2914e58bb43fSGiuseppe CAVALLARO 29154d8f0825SByungho An if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 29164d8f0825SByungho An priv->pcs != STMMAC_PCS_RTBI) { 29174bfcbd7aSFrancesco Virlinzi /* MDIO bus Registration */ 29184bfcbd7aSFrancesco Virlinzi ret = stmmac_mdio_register(ndev); 29194bfcbd7aSFrancesco Virlinzi if (ret < 0) { 29204bfcbd7aSFrancesco Virlinzi pr_debug("%s: MDIO bus (id: %d) registration failed", 29214bfcbd7aSFrancesco Virlinzi __func__, priv->plat->bus_id); 29226a81c26fSViresh Kumar goto error_mdio_register; 29234bfcbd7aSFrancesco Virlinzi } 2924e58bb43fSGiuseppe CAVALLARO } 29254bfcbd7aSFrancesco Virlinzi 2926bfab27a1SGiuseppe CAVALLARO return priv; 29277ac6653aSJeff Kirsher 29286a81c26fSViresh Kumar error_mdio_register: 29297ac6653aSJeff Kirsher unregister_netdev(ndev); 29306a81c26fSViresh Kumar error_netdev_register: 29316a81c26fSViresh Kumar netif_napi_del(&priv->napi); 293262866e98SChen-Yu Tsai error_hw_init: 293362866e98SChen-Yu Tsai clk_disable_unprepare(priv->stmmac_clk); 293462866e98SChen-Yu Tsai error_clk_get: 29357ac6653aSJeff Kirsher free_netdev(ndev); 29367ac6653aSJeff Kirsher 2937c5e4ddbdSChen-Yu Tsai return ERR_PTR(ret); 29387ac6653aSJeff Kirsher } 2939b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_probe); 29407ac6653aSJeff Kirsher 29417ac6653aSJeff Kirsher /** 29427ac6653aSJeff Kirsher * stmmac_dvr_remove 2943bfab27a1SGiuseppe CAVALLARO * @ndev: net device pointer 29447ac6653aSJeff Kirsher * Description: this function resets the TX/RX processes, disables the MAC RX/TX 2945bfab27a1SGiuseppe CAVALLARO * changes the link status, releases the DMA descriptor rings. 29467ac6653aSJeff Kirsher */ 2947bfab27a1SGiuseppe CAVALLARO int stmmac_dvr_remove(struct net_device *ndev) 29487ac6653aSJeff Kirsher { 29497ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 29507ac6653aSJeff Kirsher 29517ac6653aSJeff Kirsher pr_info("%s:\n\tremoving driver", __func__); 29527ac6653aSJeff Kirsher 29537ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 29547ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 29557ac6653aSJeff Kirsher 2956bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 29574d8f0825SByungho An if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 29584d8f0825SByungho An priv->pcs != STMMAC_PCS_RTBI) 29594bfcbd7aSFrancesco Virlinzi stmmac_mdio_unregister(ndev); 29607ac6653aSJeff Kirsher netif_carrier_off(ndev); 29617ac6653aSJeff Kirsher unregister_netdev(ndev); 2962c5e4ddbdSChen-Yu Tsai if (priv->stmmac_rst) 2963c5e4ddbdSChen-Yu Tsai reset_control_assert(priv->stmmac_rst); 296462866e98SChen-Yu Tsai clk_disable_unprepare(priv->stmmac_clk); 29657ac6653aSJeff Kirsher free_netdev(ndev); 29667ac6653aSJeff Kirsher 29677ac6653aSJeff Kirsher return 0; 29687ac6653aSJeff Kirsher } 2969b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_remove); 29707ac6653aSJeff Kirsher 2971732fdf0eSGiuseppe CAVALLARO /** 2972732fdf0eSGiuseppe CAVALLARO * stmmac_suspend - suspend callback 2973732fdf0eSGiuseppe CAVALLARO * @ndev: net device pointer 2974732fdf0eSGiuseppe CAVALLARO * Description: this is the function to suspend the device and it is called 2975732fdf0eSGiuseppe CAVALLARO * by the platform driver to stop the network queue, release the resources, 2976732fdf0eSGiuseppe CAVALLARO * program the PMT register (for WoL), clean and release driver resources. 2977732fdf0eSGiuseppe CAVALLARO */ 2978bfab27a1SGiuseppe CAVALLARO int stmmac_suspend(struct net_device *ndev) 29797ac6653aSJeff Kirsher { 29807ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 2981f8c5a875SGiuseppe CAVALLARO unsigned long flags; 29827ac6653aSJeff Kirsher 29837ac6653aSJeff Kirsher if (!ndev || !netif_running(ndev)) 29847ac6653aSJeff Kirsher return 0; 29857ac6653aSJeff Kirsher 2986102463b1SFrancesco Virlinzi if (priv->phydev) 2987102463b1SFrancesco Virlinzi phy_stop(priv->phydev); 2988102463b1SFrancesco Virlinzi 2989f8c5a875SGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 29907ac6653aSJeff Kirsher 29917ac6653aSJeff Kirsher netif_device_detach(ndev); 29927ac6653aSJeff Kirsher netif_stop_queue(ndev); 29937ac6653aSJeff Kirsher 29947ac6653aSJeff Kirsher napi_disable(&priv->napi); 29957ac6653aSJeff Kirsher 29967ac6653aSJeff Kirsher /* Stop TX/RX DMA */ 29977ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 29987ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 2999c24602efSGiuseppe CAVALLARO 3000c24602efSGiuseppe CAVALLARO stmmac_clear_descriptors(priv); 30017ac6653aSJeff Kirsher 30027ac6653aSJeff Kirsher /* Enable Power down mode by programming the PMT regs */ 300389f7f2cfSSrinivas Kandagatla if (device_may_wakeup(priv->device)) { 30047ed24bbeSVince Bridgers priv->hw->mac->pmt(priv->hw, priv->wolopts); 300589f7f2cfSSrinivas Kandagatla priv->irq_wake = 1; 300689f7f2cfSSrinivas Kandagatla } else { 3007bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 3008db88f10aSSrinivas Kandagatla pinctrl_pm_select_sleep_state(priv->device); 3009ba1377ffSGiuseppe CAVALLARO /* Disable clock in case of PWM is off */ 3010777da230SGiuseppe CAVALLARO clk_disable(priv->stmmac_clk); 3011ba1377ffSGiuseppe CAVALLARO } 3012f8c5a875SGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 30132d871aa0SVince Bridgers 30142d871aa0SVince Bridgers priv->oldlink = 0; 30152d871aa0SVince Bridgers priv->speed = 0; 30162d871aa0SVince Bridgers priv->oldduplex = -1; 30177ac6653aSJeff Kirsher return 0; 30187ac6653aSJeff Kirsher } 3019b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_suspend); 30207ac6653aSJeff Kirsher 3021732fdf0eSGiuseppe CAVALLARO /** 3022732fdf0eSGiuseppe CAVALLARO * stmmac_resume - resume callback 3023732fdf0eSGiuseppe CAVALLARO * @ndev: net device pointer 3024732fdf0eSGiuseppe CAVALLARO * Description: when resume this function is invoked to setup the DMA and CORE 3025732fdf0eSGiuseppe CAVALLARO * in a usable state. 3026732fdf0eSGiuseppe CAVALLARO */ 3027bfab27a1SGiuseppe CAVALLARO int stmmac_resume(struct net_device *ndev) 30287ac6653aSJeff Kirsher { 30297ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 3030f8c5a875SGiuseppe CAVALLARO unsigned long flags; 30317ac6653aSJeff Kirsher 30327ac6653aSJeff Kirsher if (!netif_running(ndev)) 30337ac6653aSJeff Kirsher return 0; 30347ac6653aSJeff Kirsher 3035f8c5a875SGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 30367ac6653aSJeff Kirsher 30377ac6653aSJeff Kirsher /* Power Down bit, into the PM register, is cleared 30387ac6653aSJeff Kirsher * automatically as soon as a magic packet or a Wake-up frame 30397ac6653aSJeff Kirsher * is received. Anyway, it's better to manually clear 30407ac6653aSJeff Kirsher * this bit because it can generate problems while resuming 3041ceb69499SGiuseppe CAVALLARO * from another devices (e.g. serial console). 3042ceb69499SGiuseppe CAVALLARO */ 3043623997fbSSrinivas Kandagatla if (device_may_wakeup(priv->device)) { 30447ed24bbeSVince Bridgers priv->hw->mac->pmt(priv->hw, 0); 304589f7f2cfSSrinivas Kandagatla priv->irq_wake = 0; 3046623997fbSSrinivas Kandagatla } else { 3047db88f10aSSrinivas Kandagatla pinctrl_pm_select_default_state(priv->device); 3048ba1377ffSGiuseppe CAVALLARO /* enable the clk prevously disabled */ 3049777da230SGiuseppe CAVALLARO clk_enable(priv->stmmac_clk); 3050623997fbSSrinivas Kandagatla /* reset the phy so that it's ready */ 3051623997fbSSrinivas Kandagatla if (priv->mii) 3052623997fbSSrinivas Kandagatla stmmac_mdio_reset(priv->mii); 3053623997fbSSrinivas Kandagatla } 30547ac6653aSJeff Kirsher 30557ac6653aSJeff Kirsher netif_device_attach(ndev); 30567ac6653aSJeff Kirsher 3057777da230SGiuseppe CAVALLARO init_dma_desc_rings(ndev, GFP_ATOMIC); 3058fe131929SHuacai Chen stmmac_hw_setup(ndev, false); 3059777da230SGiuseppe CAVALLARO stmmac_init_tx_coalesce(priv); 30607ac6653aSJeff Kirsher 30617ac6653aSJeff Kirsher napi_enable(&priv->napi); 30627ac6653aSJeff Kirsher 30637ac6653aSJeff Kirsher netif_start_queue(ndev); 30647ac6653aSJeff Kirsher 3065f8c5a875SGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 3066102463b1SFrancesco Virlinzi 3067102463b1SFrancesco Virlinzi if (priv->phydev) 3068102463b1SFrancesco Virlinzi phy_start(priv->phydev); 3069102463b1SFrancesco Virlinzi 30707ac6653aSJeff Kirsher return 0; 30717ac6653aSJeff Kirsher } 3072b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_resume); 3073ba27ec66SGiuseppe CAVALLARO 30747ac6653aSJeff Kirsher #ifndef MODULE 30757ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str) 30767ac6653aSJeff Kirsher { 30777ac6653aSJeff Kirsher char *opt; 30787ac6653aSJeff Kirsher 30797ac6653aSJeff Kirsher if (!str || !*str) 30807ac6653aSJeff Kirsher return -EINVAL; 30817ac6653aSJeff Kirsher while ((opt = strsep(&str, ",")) != NULL) { 30827ac6653aSJeff Kirsher if (!strncmp(opt, "debug:", 6)) { 3083ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 6, 0, &debug)) 30847ac6653aSJeff Kirsher goto err; 30857ac6653aSJeff Kirsher } else if (!strncmp(opt, "phyaddr:", 8)) { 3086ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 8, 0, &phyaddr)) 30877ac6653aSJeff Kirsher goto err; 30887ac6653aSJeff Kirsher } else if (!strncmp(opt, "dma_txsize:", 11)) { 3089ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 11, 0, &dma_txsize)) 30907ac6653aSJeff Kirsher goto err; 30917ac6653aSJeff Kirsher } else if (!strncmp(opt, "dma_rxsize:", 11)) { 3092ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 11, 0, &dma_rxsize)) 30937ac6653aSJeff Kirsher goto err; 30947ac6653aSJeff Kirsher } else if (!strncmp(opt, "buf_sz:", 7)) { 3095ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 7, 0, &buf_sz)) 30967ac6653aSJeff Kirsher goto err; 30977ac6653aSJeff Kirsher } else if (!strncmp(opt, "tc:", 3)) { 3098ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 3, 0, &tc)) 30997ac6653aSJeff Kirsher goto err; 31007ac6653aSJeff Kirsher } else if (!strncmp(opt, "watchdog:", 9)) { 3101ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 9, 0, &watchdog)) 31027ac6653aSJeff Kirsher goto err; 31037ac6653aSJeff Kirsher } else if (!strncmp(opt, "flow_ctrl:", 10)) { 3104ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 10, 0, &flow_ctrl)) 31057ac6653aSJeff Kirsher goto err; 31067ac6653aSJeff Kirsher } else if (!strncmp(opt, "pause:", 6)) { 3107ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 6, 0, &pause)) 31087ac6653aSJeff Kirsher goto err; 3109506f669cSGiuseppe CAVALLARO } else if (!strncmp(opt, "eee_timer:", 10)) { 3110d765955dSGiuseppe CAVALLARO if (kstrtoint(opt + 10, 0, &eee_timer)) 3111d765955dSGiuseppe CAVALLARO goto err; 31124a7d666aSGiuseppe CAVALLARO } else if (!strncmp(opt, "chain_mode:", 11)) { 31134a7d666aSGiuseppe CAVALLARO if (kstrtoint(opt + 11, 0, &chain_mode)) 31144a7d666aSGiuseppe CAVALLARO goto err; 31157ac6653aSJeff Kirsher } 31167ac6653aSJeff Kirsher } 31177ac6653aSJeff Kirsher return 0; 31187ac6653aSJeff Kirsher 31197ac6653aSJeff Kirsher err: 31207ac6653aSJeff Kirsher pr_err("%s: ERROR broken module parameter conversion", __func__); 31217ac6653aSJeff Kirsher return -EINVAL; 31227ac6653aSJeff Kirsher } 31237ac6653aSJeff Kirsher 31247ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt); 3125ceb69499SGiuseppe CAVALLARO #endif /* MODULE */ 31266fc0d0f2SGiuseppe Cavallaro 31276fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver"); 31286fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); 31296fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL"); 3130