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; 313ccb36da1SVaishali Thakkar setup_timer(&priv->eee_ctrl_timer, 314ccb36da1SVaishali Thakkar stmmac_eee_ctrl_timer, 315ccb36da1SVaishali Thakkar (unsigned long)priv); 316ccb36da1SVaishali Thakkar mod_timer(&priv->eee_ctrl_timer, 317ccb36da1SVaishali Thakkar STMMAC_LPI_T(eee_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 612dbedd44eSJoe Perches * achieve 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); 1291b2dec116SSonic Zhang priv->xstats.threshold = 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 */ 1455b2dec116SSonic Zhang if (unlikely(priv->xstats.threshold != SF_DMA_MODE) && 1456b2dec116SSonic Zhang (tc <= 256)) { 14577ac6653aSJeff Kirsher tc += 64; 1458c405abe2SSonic Zhang if (priv->plat->force_thresh_dma_mode) 1459c405abe2SSonic Zhang priv->hw->dma->dma_mode(priv->ioaddr, tc, tc); 1460c405abe2SSonic Zhang else 1461c405abe2SSonic Zhang priv->hw->dma->dma_mode(priv->ioaddr, tc, 1462c405abe2SSonic Zhang SF_DMA_MODE); 14637ac6653aSJeff Kirsher priv->xstats.threshold = tc; 14647ac6653aSJeff Kirsher } 14657ac6653aSJeff Kirsher } else if (unlikely(status == tx_hard_error)) 14667ac6653aSJeff Kirsher stmmac_tx_err(priv); 14677ac6653aSJeff Kirsher } 14687ac6653aSJeff Kirsher 146932ceabcaSGiuseppe CAVALLARO /** 147032ceabcaSGiuseppe CAVALLARO * stmmac_mmc_setup: setup the Mac Management Counters (MMC) 147132ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 147232ceabcaSGiuseppe CAVALLARO * Description: this masks the MMC irq, in fact, the counters are managed in SW. 147332ceabcaSGiuseppe CAVALLARO */ 14741c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv) 14751c901a46SGiuseppe CAVALLARO { 14761c901a46SGiuseppe CAVALLARO unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET | 14771c901a46SGiuseppe CAVALLARO MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET; 14781c901a46SGiuseppe CAVALLARO 14791c901a46SGiuseppe CAVALLARO dwmac_mmc_intr_all_mask(priv->ioaddr); 14804f795b25SGiuseppe CAVALLARO 14814f795b25SGiuseppe CAVALLARO if (priv->dma_cap.rmon) { 14821c901a46SGiuseppe CAVALLARO dwmac_mmc_ctrl(priv->ioaddr, mode); 14831c901a46SGiuseppe CAVALLARO memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); 14844f795b25SGiuseppe CAVALLARO } else 1485aae54cffSStefan Roese pr_info(" No MAC Management Counters available\n"); 14861c901a46SGiuseppe CAVALLARO } 14871c901a46SGiuseppe CAVALLARO 1488732fdf0eSGiuseppe CAVALLARO /** 1489732fdf0eSGiuseppe CAVALLARO * stmmac_get_synopsys_id - return the SYINID. 1490732fdf0eSGiuseppe CAVALLARO * @priv: driver private structure 1491732fdf0eSGiuseppe CAVALLARO * Description: this simple function is to decode and return the SYINID 1492732fdf0eSGiuseppe CAVALLARO * starting from the HW core register. 1493732fdf0eSGiuseppe CAVALLARO */ 1494f0b9d786SGiuseppe CAVALLARO static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) 1495f0b9d786SGiuseppe CAVALLARO { 1496f0b9d786SGiuseppe CAVALLARO u32 hwid = priv->hw->synopsys_uid; 1497f0b9d786SGiuseppe CAVALLARO 1498ceb69499SGiuseppe CAVALLARO /* Check Synopsys Id (not available on old chips) */ 1499f0b9d786SGiuseppe CAVALLARO if (likely(hwid)) { 1500f0b9d786SGiuseppe CAVALLARO u32 uid = ((hwid & 0x0000ff00) >> 8); 1501f0b9d786SGiuseppe CAVALLARO u32 synid = (hwid & 0x000000ff); 1502f0b9d786SGiuseppe CAVALLARO 1503cf3f047bSGiuseppe CAVALLARO pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n", 1504f0b9d786SGiuseppe CAVALLARO uid, synid); 1505f0b9d786SGiuseppe CAVALLARO 1506f0b9d786SGiuseppe CAVALLARO return synid; 1507f0b9d786SGiuseppe CAVALLARO } 1508f0b9d786SGiuseppe CAVALLARO return 0; 1509f0b9d786SGiuseppe CAVALLARO } 1510e7434821SGiuseppe CAVALLARO 151119e30c14SGiuseppe CAVALLARO /** 1512732fdf0eSGiuseppe CAVALLARO * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors 151332ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 151432ceabcaSGiuseppe CAVALLARO * Description: select the Enhanced/Alternate or Normal descriptors. 1515732fdf0eSGiuseppe CAVALLARO * In case of Enhanced/Alternate, it checks if the extended descriptors are 1516732fdf0eSGiuseppe CAVALLARO * supported by the HW capability register. 1517ff3dd78cSGiuseppe CAVALLARO */ 151819e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv) 151919e30c14SGiuseppe CAVALLARO { 152019e30c14SGiuseppe CAVALLARO if (priv->plat->enh_desc) { 152119e30c14SGiuseppe CAVALLARO pr_info(" Enhanced/Alternate descriptors\n"); 1522c24602efSGiuseppe CAVALLARO 1523c24602efSGiuseppe CAVALLARO /* GMAC older than 3.50 has no extended descriptors */ 1524c24602efSGiuseppe CAVALLARO if (priv->synopsys_id >= DWMAC_CORE_3_50) { 1525c24602efSGiuseppe CAVALLARO pr_info("\tEnabled extended descriptors\n"); 1526c24602efSGiuseppe CAVALLARO priv->extend_desc = 1; 1527c24602efSGiuseppe CAVALLARO } else 1528c24602efSGiuseppe CAVALLARO pr_warn("Extended descriptors not supported\n"); 1529c24602efSGiuseppe CAVALLARO 153019e30c14SGiuseppe CAVALLARO priv->hw->desc = &enh_desc_ops; 153119e30c14SGiuseppe CAVALLARO } else { 153219e30c14SGiuseppe CAVALLARO pr_info(" Normal descriptors\n"); 153319e30c14SGiuseppe CAVALLARO priv->hw->desc = &ndesc_ops; 153419e30c14SGiuseppe CAVALLARO } 153519e30c14SGiuseppe CAVALLARO } 153619e30c14SGiuseppe CAVALLARO 153719e30c14SGiuseppe CAVALLARO /** 1538732fdf0eSGiuseppe CAVALLARO * stmmac_get_hw_features - get MAC capabilities from the HW cap. register. 153932ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 154019e30c14SGiuseppe CAVALLARO * Description: 154119e30c14SGiuseppe CAVALLARO * new GMAC chip generations have a new register to indicate the 1542e7434821SGiuseppe CAVALLARO * presence of the optional feature/functions. 154319e30c14SGiuseppe CAVALLARO * This can be also used to override the value passed through the 154419e30c14SGiuseppe CAVALLARO * platform and necessary for old MAC10/100 and GMAC chips. 1545e7434821SGiuseppe CAVALLARO */ 1546e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv) 1547e7434821SGiuseppe CAVALLARO { 15485e6efe88SGiuseppe CAVALLARO u32 hw_cap = 0; 15493c20f72fSGiuseppe CAVALLARO 15505e6efe88SGiuseppe CAVALLARO if (priv->hw->dma->get_hw_feature) { 15515e6efe88SGiuseppe CAVALLARO hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr); 1552e7434821SGiuseppe CAVALLARO 15531db123fbSRayagond Kokatanur priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL); 15541db123fbSRayagond Kokatanur priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1; 15551db123fbSRayagond Kokatanur priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2; 15561db123fbSRayagond Kokatanur priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4; 1557ceb69499SGiuseppe CAVALLARO priv->dma_cap.multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5; 15581db123fbSRayagond Kokatanur priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6; 15591db123fbSRayagond Kokatanur priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8; 15601db123fbSRayagond Kokatanur priv->dma_cap.pmt_remote_wake_up = 15611db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9; 15621db123fbSRayagond Kokatanur priv->dma_cap.pmt_magic_frame = 15631db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10; 15641db123fbSRayagond Kokatanur /* MMC */ 15651db123fbSRayagond Kokatanur priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11; 1566e7434821SGiuseppe CAVALLARO /* IEEE 1588-2002 */ 15671db123fbSRayagond Kokatanur priv->dma_cap.time_stamp = 15681db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12; 1569e7434821SGiuseppe CAVALLARO /* IEEE 1588-2008 */ 15701db123fbSRayagond Kokatanur priv->dma_cap.atime_stamp = 15711db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13; 1572e7434821SGiuseppe CAVALLARO /* 802.3az - Energy-Efficient Ethernet (EEE) */ 15731db123fbSRayagond Kokatanur priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14; 15741db123fbSRayagond Kokatanur priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15; 1575e7434821SGiuseppe CAVALLARO /* TX and RX csum */ 15761db123fbSRayagond Kokatanur priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16; 15771db123fbSRayagond Kokatanur priv->dma_cap.rx_coe_type1 = 15781db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17; 15791db123fbSRayagond Kokatanur priv->dma_cap.rx_coe_type2 = 15801db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18; 15811db123fbSRayagond Kokatanur priv->dma_cap.rxfifo_over_2048 = 15821db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19; 1583e7434821SGiuseppe CAVALLARO /* TX and RX number of channels */ 15841db123fbSRayagond Kokatanur priv->dma_cap.number_rx_channel = 15851db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20; 15861db123fbSRayagond Kokatanur priv->dma_cap.number_tx_channel = 15871db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22; 1588e7434821SGiuseppe CAVALLARO /* Alternate (enhanced) DESC mode */ 1589ceb69499SGiuseppe CAVALLARO priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24; 159019e30c14SGiuseppe CAVALLARO } 1591e7434821SGiuseppe CAVALLARO 1592e7434821SGiuseppe CAVALLARO return hw_cap; 1593e7434821SGiuseppe CAVALLARO } 1594e7434821SGiuseppe CAVALLARO 159532ceabcaSGiuseppe CAVALLARO /** 1596732fdf0eSGiuseppe CAVALLARO * stmmac_check_ether_addr - check if the MAC addr is valid 159732ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 159832ceabcaSGiuseppe CAVALLARO * Description: 159932ceabcaSGiuseppe CAVALLARO * it is to verify if the MAC address is valid, in case of failures it 160032ceabcaSGiuseppe CAVALLARO * generates a random MAC address 160132ceabcaSGiuseppe CAVALLARO */ 1602bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv) 1603bfab27a1SGiuseppe CAVALLARO { 1604bfab27a1SGiuseppe CAVALLARO if (!is_valid_ether_addr(priv->dev->dev_addr)) { 16057ed24bbeSVince Bridgers priv->hw->mac->get_umac_addr(priv->hw, 1606bfab27a1SGiuseppe CAVALLARO priv->dev->dev_addr, 0); 1607bfab27a1SGiuseppe CAVALLARO if (!is_valid_ether_addr(priv->dev->dev_addr)) 1608f2cedb63SDanny Kukawka eth_hw_addr_random(priv->dev); 1609c88460b7SHans de Goede pr_info("%s: device MAC address %pM\n", priv->dev->name, 1610bfab27a1SGiuseppe CAVALLARO priv->dev->dev_addr); 1611bfab27a1SGiuseppe CAVALLARO } 1612c88460b7SHans de Goede } 1613bfab27a1SGiuseppe CAVALLARO 161432ceabcaSGiuseppe CAVALLARO /** 1615732fdf0eSGiuseppe CAVALLARO * stmmac_init_dma_engine - DMA init. 161632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 161732ceabcaSGiuseppe CAVALLARO * Description: 161832ceabcaSGiuseppe CAVALLARO * It inits the DMA invoking the specific MAC/GMAC callback. 161932ceabcaSGiuseppe CAVALLARO * Some DMA parameters can be passed from the platform; 162032ceabcaSGiuseppe CAVALLARO * in case of these are not passed a default is kept for the MAC or GMAC. 162132ceabcaSGiuseppe CAVALLARO */ 16220f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv) 16230f1f88a8SGiuseppe CAVALLARO { 16240f1f88a8SGiuseppe CAVALLARO int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0; 1625b9cde0a8SGiuseppe CAVALLARO int mixed_burst = 0; 1626c24602efSGiuseppe CAVALLARO int atds = 0; 16270f1f88a8SGiuseppe CAVALLARO 16280f1f88a8SGiuseppe CAVALLARO if (priv->plat->dma_cfg) { 16290f1f88a8SGiuseppe CAVALLARO pbl = priv->plat->dma_cfg->pbl; 16300f1f88a8SGiuseppe CAVALLARO fixed_burst = priv->plat->dma_cfg->fixed_burst; 1631b9cde0a8SGiuseppe CAVALLARO mixed_burst = priv->plat->dma_cfg->mixed_burst; 16320f1f88a8SGiuseppe CAVALLARO burst_len = priv->plat->dma_cfg->burst_len; 16330f1f88a8SGiuseppe CAVALLARO } 16340f1f88a8SGiuseppe CAVALLARO 1635c24602efSGiuseppe CAVALLARO if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE)) 1636c24602efSGiuseppe CAVALLARO atds = 1; 1637c24602efSGiuseppe CAVALLARO 1638b9cde0a8SGiuseppe CAVALLARO return priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst, 16390f1f88a8SGiuseppe CAVALLARO burst_len, priv->dma_tx_phy, 1640c24602efSGiuseppe CAVALLARO priv->dma_rx_phy, atds); 16410f1f88a8SGiuseppe CAVALLARO } 16420f1f88a8SGiuseppe CAVALLARO 1643bfab27a1SGiuseppe CAVALLARO /** 1644732fdf0eSGiuseppe CAVALLARO * stmmac_tx_timer - mitigation sw timer for tx. 16459125cdd1SGiuseppe CAVALLARO * @data: data pointer 16469125cdd1SGiuseppe CAVALLARO * Description: 16479125cdd1SGiuseppe CAVALLARO * This is the timer handler to directly invoke the stmmac_tx_clean. 16489125cdd1SGiuseppe CAVALLARO */ 16499125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data) 16509125cdd1SGiuseppe CAVALLARO { 16519125cdd1SGiuseppe CAVALLARO struct stmmac_priv *priv = (struct stmmac_priv *)data; 16529125cdd1SGiuseppe CAVALLARO 16539125cdd1SGiuseppe CAVALLARO stmmac_tx_clean(priv); 16549125cdd1SGiuseppe CAVALLARO } 16559125cdd1SGiuseppe CAVALLARO 16569125cdd1SGiuseppe CAVALLARO /** 1657732fdf0eSGiuseppe CAVALLARO * stmmac_init_tx_coalesce - init tx mitigation options. 165832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 16599125cdd1SGiuseppe CAVALLARO * Description: 16609125cdd1SGiuseppe CAVALLARO * This inits the transmit coalesce parameters: i.e. timer rate, 16619125cdd1SGiuseppe CAVALLARO * timer handler and default threshold used for enabling the 16629125cdd1SGiuseppe CAVALLARO * interrupt on completion bit. 16639125cdd1SGiuseppe CAVALLARO */ 16649125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) 16659125cdd1SGiuseppe CAVALLARO { 16669125cdd1SGiuseppe CAVALLARO priv->tx_coal_frames = STMMAC_TX_FRAMES; 16679125cdd1SGiuseppe CAVALLARO priv->tx_coal_timer = STMMAC_COAL_TX_TIMER; 16689125cdd1SGiuseppe CAVALLARO init_timer(&priv->txtimer); 16699125cdd1SGiuseppe CAVALLARO priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer); 16709125cdd1SGiuseppe CAVALLARO priv->txtimer.data = (unsigned long)priv; 16719125cdd1SGiuseppe CAVALLARO priv->txtimer.function = stmmac_tx_timer; 16729125cdd1SGiuseppe CAVALLARO add_timer(&priv->txtimer); 16739125cdd1SGiuseppe CAVALLARO } 16749125cdd1SGiuseppe CAVALLARO 16759125cdd1SGiuseppe CAVALLARO /** 1676732fdf0eSGiuseppe CAVALLARO * stmmac_hw_setup - setup mac in a usable state. 1677523f11b5SSrinivas Kandagatla * @dev : pointer to the device structure. 1678523f11b5SSrinivas Kandagatla * Description: 1679732fdf0eSGiuseppe CAVALLARO * this is the main function to setup the HW in a usable state because the 1680732fdf0eSGiuseppe CAVALLARO * dma engine is reset, the core registers are configured (e.g. AXI, 1681732fdf0eSGiuseppe CAVALLARO * Checksum features, timers). The DMA is ready to start receiving and 1682732fdf0eSGiuseppe CAVALLARO * transmitting. 1683523f11b5SSrinivas Kandagatla * Return value: 1684523f11b5SSrinivas Kandagatla * 0 on success and an appropriate (-)ve integer as defined in errno.h 1685523f11b5SSrinivas Kandagatla * file on failure. 1686523f11b5SSrinivas Kandagatla */ 1687fe131929SHuacai Chen static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) 1688523f11b5SSrinivas Kandagatla { 1689523f11b5SSrinivas Kandagatla struct stmmac_priv *priv = netdev_priv(dev); 1690523f11b5SSrinivas Kandagatla int ret; 1691523f11b5SSrinivas Kandagatla 1692523f11b5SSrinivas Kandagatla /* DMA initialization and SW reset */ 1693523f11b5SSrinivas Kandagatla ret = stmmac_init_dma_engine(priv); 1694523f11b5SSrinivas Kandagatla if (ret < 0) { 1695523f11b5SSrinivas Kandagatla pr_err("%s: DMA engine initialization failed\n", __func__); 1696523f11b5SSrinivas Kandagatla return ret; 1697523f11b5SSrinivas Kandagatla } 1698523f11b5SSrinivas Kandagatla 1699523f11b5SSrinivas Kandagatla /* Copy the MAC addr into the HW */ 17007ed24bbeSVince Bridgers priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0); 1701523f11b5SSrinivas Kandagatla 1702523f11b5SSrinivas Kandagatla /* If required, perform hw setup of the bus. */ 1703523f11b5SSrinivas Kandagatla if (priv->plat->bus_setup) 1704523f11b5SSrinivas Kandagatla priv->plat->bus_setup(priv->ioaddr); 1705523f11b5SSrinivas Kandagatla 1706523f11b5SSrinivas Kandagatla /* Initialize the MAC Core */ 17077ed24bbeSVince Bridgers priv->hw->mac->core_init(priv->hw, dev->mtu); 1708523f11b5SSrinivas Kandagatla 1709978aded4SGiuseppe CAVALLARO ret = priv->hw->mac->rx_ipc(priv->hw); 1710978aded4SGiuseppe CAVALLARO if (!ret) { 1711978aded4SGiuseppe CAVALLARO pr_warn(" RX IPC Checksum Offload disabled\n"); 1712978aded4SGiuseppe CAVALLARO priv->plat->rx_coe = STMMAC_RX_COE_NONE; 1713d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = 0; 1714978aded4SGiuseppe CAVALLARO } 1715978aded4SGiuseppe CAVALLARO 1716523f11b5SSrinivas Kandagatla /* Enable the MAC Rx/Tx */ 1717523f11b5SSrinivas Kandagatla stmmac_set_mac(priv->ioaddr, true); 1718523f11b5SSrinivas Kandagatla 1719523f11b5SSrinivas Kandagatla /* Set the HW DMA mode and the COE */ 1720523f11b5SSrinivas Kandagatla stmmac_dma_operation_mode(priv); 1721523f11b5SSrinivas Kandagatla 1722523f11b5SSrinivas Kandagatla stmmac_mmc_setup(priv); 1723523f11b5SSrinivas Kandagatla 1724fe131929SHuacai Chen if (init_ptp) { 1725523f11b5SSrinivas Kandagatla ret = stmmac_init_ptp(priv); 17267509edd6SHans de Goede if (ret && ret != -EOPNOTSUPP) 1727523f11b5SSrinivas Kandagatla pr_warn("%s: failed PTP initialisation\n", __func__); 1728fe131929SHuacai Chen } 1729523f11b5SSrinivas Kandagatla 173050fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 1731523f11b5SSrinivas Kandagatla ret = stmmac_init_fs(dev); 1732523f11b5SSrinivas Kandagatla if (ret < 0) 1733523f11b5SSrinivas Kandagatla pr_warn("%s: failed debugFS registration\n", __func__); 1734523f11b5SSrinivas Kandagatla #endif 1735523f11b5SSrinivas Kandagatla /* Start the ball rolling... */ 1736523f11b5SSrinivas Kandagatla pr_debug("%s: DMA RX/TX processes started...\n", dev->name); 1737523f11b5SSrinivas Kandagatla priv->hw->dma->start_tx(priv->ioaddr); 1738523f11b5SSrinivas Kandagatla priv->hw->dma->start_rx(priv->ioaddr); 1739523f11b5SSrinivas Kandagatla 1740523f11b5SSrinivas Kandagatla /* Dump DMA/MAC registers */ 1741523f11b5SSrinivas Kandagatla if (netif_msg_hw(priv)) { 17427ed24bbeSVince Bridgers priv->hw->mac->dump_regs(priv->hw); 1743523f11b5SSrinivas Kandagatla priv->hw->dma->dump_regs(priv->ioaddr); 1744523f11b5SSrinivas Kandagatla } 1745523f11b5SSrinivas Kandagatla priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; 1746523f11b5SSrinivas Kandagatla 1747523f11b5SSrinivas Kandagatla if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { 1748523f11b5SSrinivas Kandagatla priv->rx_riwt = MAX_DMA_RIWT; 1749523f11b5SSrinivas Kandagatla priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); 1750523f11b5SSrinivas Kandagatla } 1751523f11b5SSrinivas Kandagatla 1752523f11b5SSrinivas Kandagatla if (priv->pcs && priv->hw->mac->ctrl_ane) 17537ed24bbeSVince Bridgers priv->hw->mac->ctrl_ane(priv->hw, 0); 1754523f11b5SSrinivas Kandagatla 1755523f11b5SSrinivas Kandagatla return 0; 1756523f11b5SSrinivas Kandagatla } 1757523f11b5SSrinivas Kandagatla 1758523f11b5SSrinivas Kandagatla /** 17597ac6653aSJeff Kirsher * stmmac_open - open entry point of the driver 17607ac6653aSJeff Kirsher * @dev : pointer to the device structure. 17617ac6653aSJeff Kirsher * Description: 17627ac6653aSJeff Kirsher * This function is the open entry point of the driver. 17637ac6653aSJeff Kirsher * Return value: 17647ac6653aSJeff Kirsher * 0 on success and an appropriate (-)ve integer as defined in errno.h 17657ac6653aSJeff Kirsher * file on failure. 17667ac6653aSJeff Kirsher */ 17677ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev) 17687ac6653aSJeff Kirsher { 17697ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 17707ac6653aSJeff Kirsher int ret; 17717ac6653aSJeff Kirsher 17724bfcbd7aSFrancesco Virlinzi stmmac_check_ether_addr(priv); 17734bfcbd7aSFrancesco Virlinzi 17744d8f0825SByungho An if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 17754d8f0825SByungho An priv->pcs != STMMAC_PCS_RTBI) { 17767ac6653aSJeff Kirsher ret = stmmac_init_phy(dev); 1777e58bb43fSGiuseppe CAVALLARO if (ret) { 1778e58bb43fSGiuseppe CAVALLARO pr_err("%s: Cannot attach to PHY (error: %d)\n", 1779e58bb43fSGiuseppe CAVALLARO __func__, ret); 178089df20d9SHans de Goede return ret; 17817ac6653aSJeff Kirsher } 1782e58bb43fSGiuseppe CAVALLARO } 17837ac6653aSJeff Kirsher 1784523f11b5SSrinivas Kandagatla /* Extra statistics */ 1785523f11b5SSrinivas Kandagatla memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats)); 1786523f11b5SSrinivas Kandagatla priv->xstats.threshold = tc; 1787523f11b5SSrinivas Kandagatla 17887ac6653aSJeff Kirsher /* Create and initialize the TX/RX descriptors chains. */ 17897ac6653aSJeff Kirsher priv->dma_tx_size = STMMAC_ALIGN(dma_txsize); 17907ac6653aSJeff Kirsher priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize); 17917ac6653aSJeff Kirsher priv->dma_buf_sz = STMMAC_ALIGN(buf_sz); 179256329137SBartlomiej Zolnierkiewicz 17937262b7b2STobias Klauser ret = alloc_dma_desc_resources(priv); 179409f8d696SSrinivas Kandagatla if (ret < 0) { 179509f8d696SSrinivas Kandagatla pr_err("%s: DMA descriptors allocation failed\n", __func__); 179609f8d696SSrinivas Kandagatla goto dma_desc_error; 179709f8d696SSrinivas Kandagatla } 179809f8d696SSrinivas Kandagatla 1799777da230SGiuseppe CAVALLARO ret = init_dma_desc_rings(dev, GFP_KERNEL); 1800777da230SGiuseppe CAVALLARO if (ret < 0) { 1801777da230SGiuseppe CAVALLARO pr_err("%s: DMA descriptors initialization failed\n", __func__); 1802777da230SGiuseppe CAVALLARO goto init_error; 1803777da230SGiuseppe CAVALLARO } 1804777da230SGiuseppe CAVALLARO 1805fe131929SHuacai Chen ret = stmmac_hw_setup(dev, true); 180656329137SBartlomiej Zolnierkiewicz if (ret < 0) { 1807523f11b5SSrinivas Kandagatla pr_err("%s: Hw setup failed\n", __func__); 1808c9324d18SGiuseppe CAVALLARO goto init_error; 18097ac6653aSJeff Kirsher } 18107ac6653aSJeff Kirsher 1811777da230SGiuseppe CAVALLARO stmmac_init_tx_coalesce(priv); 1812777da230SGiuseppe CAVALLARO 1813523f11b5SSrinivas Kandagatla if (priv->phydev) 1814523f11b5SSrinivas Kandagatla phy_start(priv->phydev); 18157ac6653aSJeff Kirsher 18167ac6653aSJeff Kirsher /* Request the IRQ lines */ 18177ac6653aSJeff Kirsher ret = request_irq(dev->irq, stmmac_interrupt, 18187ac6653aSJeff Kirsher IRQF_SHARED, dev->name, dev); 18197ac6653aSJeff Kirsher if (unlikely(ret < 0)) { 18207ac6653aSJeff Kirsher pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n", 18217ac6653aSJeff Kirsher __func__, dev->irq, ret); 1822c9324d18SGiuseppe CAVALLARO goto init_error; 18237ac6653aSJeff Kirsher } 18247ac6653aSJeff Kirsher 18257a13f8f5SFrancesco Virlinzi /* Request the Wake IRQ in case of another line is used for WoL */ 18267a13f8f5SFrancesco Virlinzi if (priv->wol_irq != dev->irq) { 18277a13f8f5SFrancesco Virlinzi ret = request_irq(priv->wol_irq, stmmac_interrupt, 18287a13f8f5SFrancesco Virlinzi IRQF_SHARED, dev->name, dev); 18297a13f8f5SFrancesco Virlinzi if (unlikely(ret < 0)) { 1830ceb69499SGiuseppe CAVALLARO pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n", 1831ceb69499SGiuseppe CAVALLARO __func__, priv->wol_irq, ret); 1832c9324d18SGiuseppe CAVALLARO goto wolirq_error; 18337a13f8f5SFrancesco Virlinzi } 18347a13f8f5SFrancesco Virlinzi } 18357a13f8f5SFrancesco Virlinzi 1836d765955dSGiuseppe CAVALLARO /* Request the IRQ lines */ 1837d7ec8584SChen-Yu Tsai if (priv->lpi_irq > 0) { 1838d765955dSGiuseppe CAVALLARO ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED, 1839d765955dSGiuseppe CAVALLARO dev->name, dev); 1840d765955dSGiuseppe CAVALLARO if (unlikely(ret < 0)) { 1841d765955dSGiuseppe CAVALLARO pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n", 1842d765955dSGiuseppe CAVALLARO __func__, priv->lpi_irq, ret); 1843c9324d18SGiuseppe CAVALLARO goto lpiirq_error; 1844d765955dSGiuseppe CAVALLARO } 1845d765955dSGiuseppe CAVALLARO } 1846d765955dSGiuseppe CAVALLARO 18477ac6653aSJeff Kirsher napi_enable(&priv->napi); 18487ac6653aSJeff Kirsher netif_start_queue(dev); 18497ac6653aSJeff Kirsher 18507ac6653aSJeff Kirsher return 0; 18517ac6653aSJeff Kirsher 1852c9324d18SGiuseppe CAVALLARO lpiirq_error: 1853d765955dSGiuseppe CAVALLARO if (priv->wol_irq != dev->irq) 1854d765955dSGiuseppe CAVALLARO free_irq(priv->wol_irq, dev); 1855c9324d18SGiuseppe CAVALLARO wolirq_error: 18567a13f8f5SFrancesco Virlinzi free_irq(dev->irq, dev); 18577a13f8f5SFrancesco Virlinzi 1858c9324d18SGiuseppe CAVALLARO init_error: 1859c9324d18SGiuseppe CAVALLARO free_dma_desc_resources(priv); 186056329137SBartlomiej Zolnierkiewicz dma_desc_error: 18617ac6653aSJeff Kirsher if (priv->phydev) 18627ac6653aSJeff Kirsher phy_disconnect(priv->phydev); 18634bfcbd7aSFrancesco Virlinzi 18647ac6653aSJeff Kirsher return ret; 18657ac6653aSJeff Kirsher } 18667ac6653aSJeff Kirsher 18677ac6653aSJeff Kirsher /** 18687ac6653aSJeff Kirsher * stmmac_release - close entry point of the driver 18697ac6653aSJeff Kirsher * @dev : device pointer. 18707ac6653aSJeff Kirsher * Description: 18717ac6653aSJeff Kirsher * This is the stop entry point of the driver. 18727ac6653aSJeff Kirsher */ 18737ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev) 18747ac6653aSJeff Kirsher { 18757ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 18767ac6653aSJeff Kirsher 1877d765955dSGiuseppe CAVALLARO if (priv->eee_enabled) 1878d765955dSGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 1879d765955dSGiuseppe CAVALLARO 18807ac6653aSJeff Kirsher /* Stop and disconnect the PHY */ 18817ac6653aSJeff Kirsher if (priv->phydev) { 18827ac6653aSJeff Kirsher phy_stop(priv->phydev); 18837ac6653aSJeff Kirsher phy_disconnect(priv->phydev); 18847ac6653aSJeff Kirsher priv->phydev = NULL; 18857ac6653aSJeff Kirsher } 18867ac6653aSJeff Kirsher 18877ac6653aSJeff Kirsher netif_stop_queue(dev); 18887ac6653aSJeff Kirsher 18897ac6653aSJeff Kirsher napi_disable(&priv->napi); 18907ac6653aSJeff Kirsher 18919125cdd1SGiuseppe CAVALLARO del_timer_sync(&priv->txtimer); 18929125cdd1SGiuseppe CAVALLARO 18937ac6653aSJeff Kirsher /* Free the IRQ lines */ 18947ac6653aSJeff Kirsher free_irq(dev->irq, dev); 18957a13f8f5SFrancesco Virlinzi if (priv->wol_irq != dev->irq) 18967a13f8f5SFrancesco Virlinzi free_irq(priv->wol_irq, dev); 1897d7ec8584SChen-Yu Tsai if (priv->lpi_irq > 0) 1898d765955dSGiuseppe CAVALLARO free_irq(priv->lpi_irq, dev); 18997ac6653aSJeff Kirsher 19007ac6653aSJeff Kirsher /* Stop TX/RX DMA and clear the descriptors */ 19017ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 19027ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 19037ac6653aSJeff Kirsher 19047ac6653aSJeff Kirsher /* Release and free the Rx/Tx resources */ 19057ac6653aSJeff Kirsher free_dma_desc_resources(priv); 19067ac6653aSJeff Kirsher 19077ac6653aSJeff Kirsher /* Disable the MAC Rx/Tx */ 1908bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 19097ac6653aSJeff Kirsher 19107ac6653aSJeff Kirsher netif_carrier_off(dev); 19117ac6653aSJeff Kirsher 191250fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 1913bfab27a1SGiuseppe CAVALLARO stmmac_exit_fs(); 1914bfab27a1SGiuseppe CAVALLARO #endif 1915bfab27a1SGiuseppe CAVALLARO 191692ba6888SRayagond Kokatanur stmmac_release_ptp(priv); 191792ba6888SRayagond Kokatanur 19187ac6653aSJeff Kirsher return 0; 19197ac6653aSJeff Kirsher } 19207ac6653aSJeff Kirsher 19217ac6653aSJeff Kirsher /** 1922732fdf0eSGiuseppe CAVALLARO * stmmac_xmit - Tx entry point of the driver 19237ac6653aSJeff Kirsher * @skb : the socket buffer 19247ac6653aSJeff Kirsher * @dev : device pointer 192532ceabcaSGiuseppe CAVALLARO * Description : this is the tx entry point of the driver. 192632ceabcaSGiuseppe CAVALLARO * It programs the chain or the ring and supports oversized frames 192732ceabcaSGiuseppe CAVALLARO * and SG feature. 19287ac6653aSJeff Kirsher */ 19297ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) 19307ac6653aSJeff Kirsher { 19317ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 19327ac6653aSJeff Kirsher unsigned int txsize = priv->dma_tx_size; 19337ac6653aSJeff Kirsher unsigned int entry; 19344a7d666aSGiuseppe CAVALLARO int i, csum_insertion = 0, is_jumbo = 0; 19357ac6653aSJeff Kirsher int nfrags = skb_shinfo(skb)->nr_frags; 19367ac6653aSJeff Kirsher struct dma_desc *desc, *first; 1937286a8372SGiuseppe CAVALLARO unsigned int nopaged_len = skb_headlen(skb); 193829896a67SGiuseppe CAVALLARO unsigned int enh_desc = priv->plat->enh_desc; 19397ac6653aSJeff Kirsher 194016ee817eSFabrice Gasnier spin_lock(&priv->tx_lock); 194116ee817eSFabrice Gasnier 19427ac6653aSJeff Kirsher if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) { 194316ee817eSFabrice Gasnier spin_unlock(&priv->tx_lock); 19447ac6653aSJeff Kirsher if (!netif_queue_stopped(dev)) { 19457ac6653aSJeff Kirsher netif_stop_queue(dev); 19467ac6653aSJeff Kirsher /* This is a hard error, log it. */ 1947ceb69499SGiuseppe CAVALLARO pr_err("%s: Tx Ring full when queue awake\n", __func__); 19487ac6653aSJeff Kirsher } 19497ac6653aSJeff Kirsher return NETDEV_TX_BUSY; 19507ac6653aSJeff Kirsher } 19517ac6653aSJeff Kirsher 1952d765955dSGiuseppe CAVALLARO if (priv->tx_path_in_lpi_mode) 1953d765955dSGiuseppe CAVALLARO stmmac_disable_eee_mode(priv); 1954d765955dSGiuseppe CAVALLARO 19557ac6653aSJeff Kirsher entry = priv->cur_tx % txsize; 19567ac6653aSJeff Kirsher 19577ac6653aSJeff Kirsher csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL); 19587ac6653aSJeff Kirsher 1959c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1960c24602efSGiuseppe CAVALLARO desc = (struct dma_desc *)(priv->dma_etx + entry); 1961c24602efSGiuseppe CAVALLARO else 19627ac6653aSJeff Kirsher desc = priv->dma_tx + entry; 1963c24602efSGiuseppe CAVALLARO 19647ac6653aSJeff Kirsher first = desc; 19657ac6653aSJeff Kirsher 19664a7d666aSGiuseppe CAVALLARO /* To program the descriptors according to the size of the frame */ 196729896a67SGiuseppe CAVALLARO if (enh_desc) 196829896a67SGiuseppe CAVALLARO is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc); 196929896a67SGiuseppe CAVALLARO 19704a7d666aSGiuseppe CAVALLARO if (likely(!is_jumbo)) { 19717ac6653aSJeff Kirsher desc->des2 = dma_map_single(priv->device, skb->data, 19727ac6653aSJeff Kirsher nopaged_len, DMA_TO_DEVICE); 1973362b37beSGiuseppe CAVALLARO if (dma_mapping_error(priv->device, desc->des2)) 1974362b37beSGiuseppe CAVALLARO goto dma_map_err; 1975362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf = desc->des2; 19767ac6653aSJeff Kirsher priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len, 19774a7d666aSGiuseppe CAVALLARO csum_insertion, priv->mode); 197829896a67SGiuseppe CAVALLARO } else { 1979c24602efSGiuseppe CAVALLARO desc = first; 198029896a67SGiuseppe CAVALLARO entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion); 1981362b37beSGiuseppe CAVALLARO if (unlikely(entry < 0)) 1982362b37beSGiuseppe CAVALLARO goto dma_map_err; 198329896a67SGiuseppe CAVALLARO } 19847ac6653aSJeff Kirsher 19857ac6653aSJeff Kirsher for (i = 0; i < nfrags; i++) { 19869e903e08SEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 19879e903e08SEric Dumazet int len = skb_frag_size(frag); 19887ac6653aSJeff Kirsher 198975e4364fSdamuzi000 priv->tx_skbuff[entry] = NULL; 19907ac6653aSJeff Kirsher entry = (++priv->cur_tx) % txsize; 1991c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1992c24602efSGiuseppe CAVALLARO desc = (struct dma_desc *)(priv->dma_etx + entry); 1993c24602efSGiuseppe CAVALLARO else 19947ac6653aSJeff Kirsher desc = priv->dma_tx + entry; 19957ac6653aSJeff Kirsher 1996f722380dSIan Campbell desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len, 1997f722380dSIan Campbell DMA_TO_DEVICE); 1998362b37beSGiuseppe CAVALLARO if (dma_mapping_error(priv->device, desc->des2)) 1999362b37beSGiuseppe CAVALLARO goto dma_map_err; /* should reuse desc w/o issues */ 2000362b37beSGiuseppe CAVALLARO 2001362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf = desc->des2; 2002362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].map_as_page = true; 20034a7d666aSGiuseppe CAVALLARO priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion, 20044a7d666aSGiuseppe CAVALLARO priv->mode); 20057ac6653aSJeff Kirsher wmb(); 20067ac6653aSJeff Kirsher priv->hw->desc->set_tx_owner(desc); 20078e839891SDeepak Sikri wmb(); 20087ac6653aSJeff Kirsher } 20097ac6653aSJeff Kirsher 201075e4364fSdamuzi000 priv->tx_skbuff[entry] = skb; 201175e4364fSdamuzi000 20129125cdd1SGiuseppe CAVALLARO /* Finalize the latest segment. */ 20137ac6653aSJeff Kirsher priv->hw->desc->close_tx_desc(desc); 20147ac6653aSJeff Kirsher 20157ac6653aSJeff Kirsher wmb(); 20169125cdd1SGiuseppe CAVALLARO /* According to the coalesce parameter the IC bit for the latest 20179125cdd1SGiuseppe CAVALLARO * segment could be reset and the timer re-started to invoke the 20189125cdd1SGiuseppe CAVALLARO * stmmac_tx function. This approach takes care about the fragments. 20199125cdd1SGiuseppe CAVALLARO */ 20209125cdd1SGiuseppe CAVALLARO priv->tx_count_frames += nfrags + 1; 20219125cdd1SGiuseppe CAVALLARO if (priv->tx_coal_frames > priv->tx_count_frames) { 20229125cdd1SGiuseppe CAVALLARO priv->hw->desc->clear_tx_ic(desc); 20239125cdd1SGiuseppe CAVALLARO priv->xstats.tx_reset_ic_bit++; 20249125cdd1SGiuseppe CAVALLARO mod_timer(&priv->txtimer, 20259125cdd1SGiuseppe CAVALLARO STMMAC_COAL_TIMER(priv->tx_coal_timer)); 20269125cdd1SGiuseppe CAVALLARO } else 20279125cdd1SGiuseppe CAVALLARO priv->tx_count_frames = 0; 20287ac6653aSJeff Kirsher 20297ac6653aSJeff Kirsher /* To avoid raise condition */ 20307ac6653aSJeff Kirsher priv->hw->desc->set_tx_owner(first); 20318e839891SDeepak Sikri wmb(); 20327ac6653aSJeff Kirsher 20337ac6653aSJeff Kirsher priv->cur_tx++; 20347ac6653aSJeff Kirsher 20357ac6653aSJeff Kirsher if (netif_msg_pktdata(priv)) { 203683d7af64SGiuseppe CAVALLARO pr_debug("%s: curr %d dirty=%d entry=%d, first=%p, nfrags=%d", 2037ceb69499SGiuseppe CAVALLARO __func__, (priv->cur_tx % txsize), 2038ceb69499SGiuseppe CAVALLARO (priv->dirty_tx % txsize), entry, first, nfrags); 203983d7af64SGiuseppe CAVALLARO 2040c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2041c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_etx, txsize, 1); 2042c24602efSGiuseppe CAVALLARO else 2043c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_tx, txsize, 0); 2044c24602efSGiuseppe CAVALLARO 204583d7af64SGiuseppe CAVALLARO pr_debug(">>> frame to be transmitted: "); 20467ac6653aSJeff Kirsher print_pkt(skb->data, skb->len); 20477ac6653aSJeff Kirsher } 20487ac6653aSJeff Kirsher if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { 204983d7af64SGiuseppe CAVALLARO if (netif_msg_hw(priv)) 205083d7af64SGiuseppe CAVALLARO pr_debug("%s: stop transmitted packets\n", __func__); 20517ac6653aSJeff Kirsher netif_stop_queue(dev); 20527ac6653aSJeff Kirsher } 20537ac6653aSJeff Kirsher 20547ac6653aSJeff Kirsher dev->stats.tx_bytes += skb->len; 20557ac6653aSJeff Kirsher 2056891434b1SRayagond Kokatanur if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && 2057891434b1SRayagond Kokatanur priv->hwts_tx_en)) { 2058891434b1SRayagond Kokatanur /* declare that device is doing timestamping */ 2059891434b1SRayagond Kokatanur skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 2060891434b1SRayagond Kokatanur priv->hw->desc->enable_tx_timestamp(first); 2061891434b1SRayagond Kokatanur } 2062891434b1SRayagond Kokatanur 2063891434b1SRayagond Kokatanur if (!priv->hwts_tx_en) 20647ac6653aSJeff Kirsher skb_tx_timestamp(skb); 20657ac6653aSJeff Kirsher 206638979574SBeniamino Galvani netdev_sent_queue(dev, skb->len); 20677ac6653aSJeff Kirsher priv->hw->dma->enable_dma_transmission(priv->ioaddr); 20687ac6653aSJeff Kirsher 2069a9097a96SGiuseppe CAVALLARO spin_unlock(&priv->tx_lock); 2070362b37beSGiuseppe CAVALLARO return NETDEV_TX_OK; 2071a9097a96SGiuseppe CAVALLARO 2072362b37beSGiuseppe CAVALLARO dma_map_err: 2073758a0ab5SFabrice Gasnier spin_unlock(&priv->tx_lock); 2074362b37beSGiuseppe CAVALLARO dev_err(priv->device, "Tx dma map failed\n"); 2075362b37beSGiuseppe CAVALLARO dev_kfree_skb(skb); 2076362b37beSGiuseppe CAVALLARO priv->dev->stats.tx_dropped++; 20777ac6653aSJeff Kirsher return NETDEV_TX_OK; 20787ac6653aSJeff Kirsher } 20797ac6653aSJeff Kirsher 2080b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb) 2081b9381985SVince Bridgers { 2082b9381985SVince Bridgers struct ethhdr *ehdr; 2083b9381985SVince Bridgers u16 vlanid; 2084b9381985SVince Bridgers 2085b9381985SVince Bridgers if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) == 2086b9381985SVince Bridgers NETIF_F_HW_VLAN_CTAG_RX && 2087b9381985SVince Bridgers !__vlan_get_tag(skb, &vlanid)) { 2088b9381985SVince Bridgers /* pop the vlan tag */ 2089b9381985SVince Bridgers ehdr = (struct ethhdr *)skb->data; 2090b9381985SVince Bridgers memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2); 2091b9381985SVince Bridgers skb_pull(skb, VLAN_HLEN); 2092b9381985SVince Bridgers __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid); 2093b9381985SVince Bridgers } 2094b9381985SVince Bridgers } 2095b9381985SVince Bridgers 2096b9381985SVince Bridgers 209732ceabcaSGiuseppe CAVALLARO /** 2098732fdf0eSGiuseppe CAVALLARO * stmmac_rx_refill - refill used skb preallocated buffers 209932ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 210032ceabcaSGiuseppe CAVALLARO * Description : this is to reallocate the skb for the reception process 210132ceabcaSGiuseppe CAVALLARO * that is based on zero-copy. 210232ceabcaSGiuseppe CAVALLARO */ 21037ac6653aSJeff Kirsher static inline void stmmac_rx_refill(struct stmmac_priv *priv) 21047ac6653aSJeff Kirsher { 21057ac6653aSJeff Kirsher unsigned int rxsize = priv->dma_rx_size; 21067ac6653aSJeff Kirsher int bfsize = priv->dma_buf_sz; 21077ac6653aSJeff Kirsher 21087ac6653aSJeff Kirsher for (; priv->cur_rx - priv->dirty_rx > 0; priv->dirty_rx++) { 21097ac6653aSJeff Kirsher unsigned int entry = priv->dirty_rx % rxsize; 2110c24602efSGiuseppe CAVALLARO struct dma_desc *p; 2111c24602efSGiuseppe CAVALLARO 2112c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2113c24602efSGiuseppe CAVALLARO p = (struct dma_desc *)(priv->dma_erx + entry); 2114c24602efSGiuseppe CAVALLARO else 2115c24602efSGiuseppe CAVALLARO p = priv->dma_rx + entry; 2116c24602efSGiuseppe CAVALLARO 21177ac6653aSJeff Kirsher if (likely(priv->rx_skbuff[entry] == NULL)) { 21187ac6653aSJeff Kirsher struct sk_buff *skb; 21197ac6653aSJeff Kirsher 2120acb600deSEric Dumazet skb = netdev_alloc_skb_ip_align(priv->dev, bfsize); 21217ac6653aSJeff Kirsher 21227ac6653aSJeff Kirsher if (unlikely(skb == NULL)) 21237ac6653aSJeff Kirsher break; 21247ac6653aSJeff Kirsher 21257ac6653aSJeff Kirsher priv->rx_skbuff[entry] = skb; 21267ac6653aSJeff Kirsher priv->rx_skbuff_dma[entry] = 21277ac6653aSJeff Kirsher dma_map_single(priv->device, skb->data, bfsize, 21287ac6653aSJeff Kirsher DMA_FROM_DEVICE); 2129362b37beSGiuseppe CAVALLARO if (dma_mapping_error(priv->device, 2130362b37beSGiuseppe CAVALLARO priv->rx_skbuff_dma[entry])) { 2131362b37beSGiuseppe CAVALLARO dev_err(priv->device, "Rx dma map failed\n"); 2132362b37beSGiuseppe CAVALLARO dev_kfree_skb(skb); 2133362b37beSGiuseppe CAVALLARO break; 2134362b37beSGiuseppe CAVALLARO } 2135c24602efSGiuseppe CAVALLARO p->des2 = priv->rx_skbuff_dma[entry]; 2136286a8372SGiuseppe CAVALLARO 213729896a67SGiuseppe CAVALLARO priv->hw->mode->refill_desc3(priv, p); 2138286a8372SGiuseppe CAVALLARO 213983d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) 214083d7af64SGiuseppe CAVALLARO pr_debug("\trefill entry #%d\n", entry); 21417ac6653aSJeff Kirsher } 21427ac6653aSJeff Kirsher wmb(); 2143c24602efSGiuseppe CAVALLARO priv->hw->desc->set_rx_owner(p); 21448e839891SDeepak Sikri wmb(); 21457ac6653aSJeff Kirsher } 21467ac6653aSJeff Kirsher } 21477ac6653aSJeff Kirsher 214832ceabcaSGiuseppe CAVALLARO /** 2149732fdf0eSGiuseppe CAVALLARO * stmmac_rx - manage the receive process 215032ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 215132ceabcaSGiuseppe CAVALLARO * @limit: napi bugget. 215232ceabcaSGiuseppe CAVALLARO * Description : this the function called by the napi poll method. 215332ceabcaSGiuseppe CAVALLARO * It gets all the frames inside the ring. 215432ceabcaSGiuseppe CAVALLARO */ 21557ac6653aSJeff Kirsher static int stmmac_rx(struct stmmac_priv *priv, int limit) 21567ac6653aSJeff Kirsher { 21577ac6653aSJeff Kirsher unsigned int rxsize = priv->dma_rx_size; 21587ac6653aSJeff Kirsher unsigned int entry = priv->cur_rx % rxsize; 21597ac6653aSJeff Kirsher unsigned int next_entry; 21607ac6653aSJeff Kirsher unsigned int count = 0; 2161d2afb5bdSGiuseppe CAVALLARO int coe = priv->hw->rx_csum; 21627ac6653aSJeff Kirsher 216383d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) { 216483d7af64SGiuseppe CAVALLARO pr_debug("%s: descriptor ring:\n", __func__); 2165c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2166c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_erx, rxsize, 1); 2167c24602efSGiuseppe CAVALLARO else 2168c24602efSGiuseppe CAVALLARO stmmac_display_ring((void *)priv->dma_rx, rxsize, 0); 21697ac6653aSJeff Kirsher } 2170c24602efSGiuseppe CAVALLARO while (count < limit) { 21717ac6653aSJeff Kirsher int status; 21729401bb5cSGiuseppe CAVALLARO struct dma_desc *p; 21737ac6653aSJeff Kirsher 2174c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2175c24602efSGiuseppe CAVALLARO p = (struct dma_desc *)(priv->dma_erx + entry); 2176c24602efSGiuseppe CAVALLARO else 2177c24602efSGiuseppe CAVALLARO p = priv->dma_rx + entry; 2178c24602efSGiuseppe CAVALLARO 2179c24602efSGiuseppe CAVALLARO if (priv->hw->desc->get_rx_owner(p)) 21807ac6653aSJeff Kirsher break; 21817ac6653aSJeff Kirsher 21827ac6653aSJeff Kirsher count++; 21837ac6653aSJeff Kirsher 21847ac6653aSJeff Kirsher next_entry = (++priv->cur_rx) % rxsize; 2185c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 21869401bb5cSGiuseppe CAVALLARO prefetch(priv->dma_erx + next_entry); 2187c24602efSGiuseppe CAVALLARO else 21889401bb5cSGiuseppe CAVALLARO prefetch(priv->dma_rx + next_entry); 21897ac6653aSJeff Kirsher 21907ac6653aSJeff Kirsher /* read the status of the incoming frame */ 2191c24602efSGiuseppe CAVALLARO status = priv->hw->desc->rx_status(&priv->dev->stats, 2192c24602efSGiuseppe CAVALLARO &priv->xstats, p); 2193c24602efSGiuseppe CAVALLARO if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status)) 2194c24602efSGiuseppe CAVALLARO priv->hw->desc->rx_extended_status(&priv->dev->stats, 2195c24602efSGiuseppe CAVALLARO &priv->xstats, 2196c24602efSGiuseppe CAVALLARO priv->dma_erx + 2197c24602efSGiuseppe CAVALLARO entry); 2198891434b1SRayagond Kokatanur if (unlikely(status == discard_frame)) { 21997ac6653aSJeff Kirsher priv->dev->stats.rx_errors++; 2200891434b1SRayagond Kokatanur if (priv->hwts_rx_en && !priv->extend_desc) { 2201891434b1SRayagond Kokatanur /* DESC2 & DESC3 will be overwitten by device 2202891434b1SRayagond Kokatanur * with timestamp value, hence reinitialize 2203891434b1SRayagond Kokatanur * them in stmmac_rx_refill() function so that 2204891434b1SRayagond Kokatanur * device can reuse it. 2205891434b1SRayagond Kokatanur */ 2206891434b1SRayagond Kokatanur priv->rx_skbuff[entry] = NULL; 2207891434b1SRayagond Kokatanur dma_unmap_single(priv->device, 2208891434b1SRayagond Kokatanur priv->rx_skbuff_dma[entry], 2209ceb69499SGiuseppe CAVALLARO priv->dma_buf_sz, 2210ceb69499SGiuseppe CAVALLARO DMA_FROM_DEVICE); 2211891434b1SRayagond Kokatanur } 2212891434b1SRayagond Kokatanur } else { 22137ac6653aSJeff Kirsher struct sk_buff *skb; 22147ac6653aSJeff Kirsher int frame_len; 22157ac6653aSJeff Kirsher 2216ceb69499SGiuseppe CAVALLARO frame_len = priv->hw->desc->get_rx_frame_len(p, coe); 2217ceb69499SGiuseppe CAVALLARO 22187ac6653aSJeff Kirsher /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 2219ceb69499SGiuseppe CAVALLARO * Type frames (LLC/LLC-SNAP) 2220ceb69499SGiuseppe CAVALLARO */ 22217ac6653aSJeff Kirsher if (unlikely(status != llc_snap)) 22227ac6653aSJeff Kirsher frame_len -= ETH_FCS_LEN; 22237ac6653aSJeff Kirsher 222483d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) { 22257ac6653aSJeff Kirsher pr_debug("\tdesc: %p [entry %d] buff=0x%x\n", 22267ac6653aSJeff Kirsher p, entry, p->des2); 222783d7af64SGiuseppe CAVALLARO if (frame_len > ETH_FRAME_LEN) 222883d7af64SGiuseppe CAVALLARO pr_debug("\tframe size %d, COE: %d\n", 222983d7af64SGiuseppe CAVALLARO frame_len, status); 223083d7af64SGiuseppe CAVALLARO } 22317ac6653aSJeff Kirsher skb = priv->rx_skbuff[entry]; 22327ac6653aSJeff Kirsher if (unlikely(!skb)) { 22337ac6653aSJeff Kirsher pr_err("%s: Inconsistent Rx descriptor chain\n", 22347ac6653aSJeff Kirsher priv->dev->name); 22357ac6653aSJeff Kirsher priv->dev->stats.rx_dropped++; 22367ac6653aSJeff Kirsher break; 22377ac6653aSJeff Kirsher } 22387ac6653aSJeff Kirsher prefetch(skb->data - NET_IP_ALIGN); 22397ac6653aSJeff Kirsher priv->rx_skbuff[entry] = NULL; 22407ac6653aSJeff Kirsher 2241891434b1SRayagond Kokatanur stmmac_get_rx_hwtstamp(priv, entry, skb); 2242891434b1SRayagond Kokatanur 22437ac6653aSJeff Kirsher skb_put(skb, frame_len); 22447ac6653aSJeff Kirsher dma_unmap_single(priv->device, 22457ac6653aSJeff Kirsher priv->rx_skbuff_dma[entry], 22467ac6653aSJeff Kirsher priv->dma_buf_sz, DMA_FROM_DEVICE); 224783d7af64SGiuseppe CAVALLARO 22487ac6653aSJeff Kirsher if (netif_msg_pktdata(priv)) { 224983d7af64SGiuseppe CAVALLARO pr_debug("frame received (%dbytes)", frame_len); 22507ac6653aSJeff Kirsher print_pkt(skb->data, frame_len); 22517ac6653aSJeff Kirsher } 225283d7af64SGiuseppe CAVALLARO 2253b9381985SVince Bridgers stmmac_rx_vlan(priv->dev, skb); 2254b9381985SVince Bridgers 22557ac6653aSJeff Kirsher skb->protocol = eth_type_trans(skb, priv->dev); 22567ac6653aSJeff Kirsher 2257ceb69499SGiuseppe CAVALLARO if (unlikely(!coe)) 22587ac6653aSJeff Kirsher skb_checksum_none_assert(skb); 225962a2ab93SGiuseppe CAVALLARO else 22607ac6653aSJeff Kirsher skb->ip_summed = CHECKSUM_UNNECESSARY; 226162a2ab93SGiuseppe CAVALLARO 22627ac6653aSJeff Kirsher napi_gro_receive(&priv->napi, skb); 22637ac6653aSJeff Kirsher 22647ac6653aSJeff Kirsher priv->dev->stats.rx_packets++; 22657ac6653aSJeff Kirsher priv->dev->stats.rx_bytes += frame_len; 22667ac6653aSJeff Kirsher } 22677ac6653aSJeff Kirsher entry = next_entry; 22687ac6653aSJeff Kirsher } 22697ac6653aSJeff Kirsher 22707ac6653aSJeff Kirsher stmmac_rx_refill(priv); 22717ac6653aSJeff Kirsher 22727ac6653aSJeff Kirsher priv->xstats.rx_pkt_n += count; 22737ac6653aSJeff Kirsher 22747ac6653aSJeff Kirsher return count; 22757ac6653aSJeff Kirsher } 22767ac6653aSJeff Kirsher 22777ac6653aSJeff Kirsher /** 22787ac6653aSJeff Kirsher * stmmac_poll - stmmac poll method (NAPI) 22797ac6653aSJeff Kirsher * @napi : pointer to the napi structure. 22807ac6653aSJeff Kirsher * @budget : maximum number of packets that the current CPU can receive from 22817ac6653aSJeff Kirsher * all interfaces. 22827ac6653aSJeff Kirsher * Description : 22839125cdd1SGiuseppe CAVALLARO * To look at the incoming frames and clear the tx resources. 22847ac6653aSJeff Kirsher */ 22857ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget) 22867ac6653aSJeff Kirsher { 22877ac6653aSJeff Kirsher struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi); 22887ac6653aSJeff Kirsher int work_done = 0; 22897ac6653aSJeff Kirsher 22909125cdd1SGiuseppe CAVALLARO priv->xstats.napi_poll++; 22919125cdd1SGiuseppe CAVALLARO stmmac_tx_clean(priv); 22927ac6653aSJeff Kirsher 22939125cdd1SGiuseppe CAVALLARO work_done = stmmac_rx(priv, budget); 22947ac6653aSJeff Kirsher if (work_done < budget) { 22957ac6653aSJeff Kirsher napi_complete(napi); 22969125cdd1SGiuseppe CAVALLARO stmmac_enable_dma_irq(priv); 22977ac6653aSJeff Kirsher } 22987ac6653aSJeff Kirsher return work_done; 22997ac6653aSJeff Kirsher } 23007ac6653aSJeff Kirsher 23017ac6653aSJeff Kirsher /** 23027ac6653aSJeff Kirsher * stmmac_tx_timeout 23037ac6653aSJeff Kirsher * @dev : Pointer to net device structure 23047ac6653aSJeff Kirsher * Description: this function is called when a packet transmission fails to 23057284a3f1SGiuseppe CAVALLARO * complete within a reasonable time. The driver will mark the error in the 23067ac6653aSJeff Kirsher * netdev structure and arrange for the device to be reset to a sane state 23077ac6653aSJeff Kirsher * in order to transmit a new packet. 23087ac6653aSJeff Kirsher */ 23097ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev) 23107ac6653aSJeff Kirsher { 23117ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 23127ac6653aSJeff Kirsher 23137ac6653aSJeff Kirsher /* Clear Tx resources and restart transmitting again */ 23147ac6653aSJeff Kirsher stmmac_tx_err(priv); 23157ac6653aSJeff Kirsher } 23167ac6653aSJeff Kirsher 23177ac6653aSJeff Kirsher /** 231801789349SJiri Pirko * stmmac_set_rx_mode - entry point for multicast addressing 23197ac6653aSJeff Kirsher * @dev : pointer to the device structure 23207ac6653aSJeff Kirsher * Description: 23217ac6653aSJeff Kirsher * This function is a driver entry point which gets called by the kernel 23227ac6653aSJeff Kirsher * whenever multicast addresses must be enabled/disabled. 23237ac6653aSJeff Kirsher * Return value: 23247ac6653aSJeff Kirsher * void. 23257ac6653aSJeff Kirsher */ 232601789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev) 23277ac6653aSJeff Kirsher { 23287ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 23297ac6653aSJeff Kirsher 23303b57de95SVince Bridgers priv->hw->mac->set_filter(priv->hw, dev); 23317ac6653aSJeff Kirsher } 23327ac6653aSJeff Kirsher 23337ac6653aSJeff Kirsher /** 23347ac6653aSJeff Kirsher * stmmac_change_mtu - entry point to change MTU size for the device. 23357ac6653aSJeff Kirsher * @dev : device pointer. 23367ac6653aSJeff Kirsher * @new_mtu : the new MTU size for the device. 23377ac6653aSJeff Kirsher * Description: the Maximum Transfer Unit (MTU) is used by the network layer 23387ac6653aSJeff Kirsher * to drive packet transmission. Ethernet has an MTU of 1500 octets 23397ac6653aSJeff Kirsher * (ETH_DATA_LEN). This value can be changed with ifconfig. 23407ac6653aSJeff Kirsher * Return value: 23417ac6653aSJeff Kirsher * 0 on success and an appropriate (-)ve integer as defined in errno.h 23427ac6653aSJeff Kirsher * file on failure. 23437ac6653aSJeff Kirsher */ 23447ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu) 23457ac6653aSJeff Kirsher { 23467ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 23477ac6653aSJeff Kirsher int max_mtu; 23487ac6653aSJeff Kirsher 23497ac6653aSJeff Kirsher if (netif_running(dev)) { 23507ac6653aSJeff Kirsher pr_err("%s: must be stopped to change its MTU\n", dev->name); 23517ac6653aSJeff Kirsher return -EBUSY; 23527ac6653aSJeff Kirsher } 23537ac6653aSJeff Kirsher 235448febf7eSGiuseppe CAVALLARO if (priv->plat->enh_desc) 23557ac6653aSJeff Kirsher max_mtu = JUMBO_LEN; 23567ac6653aSJeff Kirsher else 235745db81e1SGiuseppe CAVALLARO max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN); 23587ac6653aSJeff Kirsher 23592618abb7SVince Bridgers if (priv->plat->maxmtu < max_mtu) 23602618abb7SVince Bridgers max_mtu = priv->plat->maxmtu; 23612618abb7SVince Bridgers 23627ac6653aSJeff Kirsher if ((new_mtu < 46) || (new_mtu > max_mtu)) { 23637ac6653aSJeff Kirsher pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu); 23647ac6653aSJeff Kirsher return -EINVAL; 23657ac6653aSJeff Kirsher } 23667ac6653aSJeff Kirsher 23677ac6653aSJeff Kirsher dev->mtu = new_mtu; 23687ac6653aSJeff Kirsher netdev_update_features(dev); 23697ac6653aSJeff Kirsher 23707ac6653aSJeff Kirsher return 0; 23717ac6653aSJeff Kirsher } 23727ac6653aSJeff Kirsher 2373c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev, 2374c8f44affSMichał Mirosław netdev_features_t features) 23757ac6653aSJeff Kirsher { 23767ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 23777ac6653aSJeff Kirsher 237838912bdbSDeepak SIKRI if (priv->plat->rx_coe == STMMAC_RX_COE_NONE) 23797ac6653aSJeff Kirsher features &= ~NETIF_F_RXCSUM; 2380d2afb5bdSGiuseppe CAVALLARO 23817ac6653aSJeff Kirsher if (!priv->plat->tx_coe) 23827ac6653aSJeff Kirsher features &= ~NETIF_F_ALL_CSUM; 23837ac6653aSJeff Kirsher 23847ac6653aSJeff Kirsher /* Some GMAC devices have a bugged Jumbo frame support that 23857ac6653aSJeff Kirsher * needs to have the Tx COE disabled for oversized frames 23867ac6653aSJeff Kirsher * (due to limited buffer sizes). In this case we disable 2387ceb69499SGiuseppe CAVALLARO * the TX csum insertionin the TDES and not use SF. 2388ceb69499SGiuseppe CAVALLARO */ 23897ac6653aSJeff Kirsher if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN)) 23907ac6653aSJeff Kirsher features &= ~NETIF_F_ALL_CSUM; 23917ac6653aSJeff Kirsher 23927ac6653aSJeff Kirsher return features; 23937ac6653aSJeff Kirsher } 23947ac6653aSJeff Kirsher 2395d2afb5bdSGiuseppe CAVALLARO static int stmmac_set_features(struct net_device *netdev, 2396d2afb5bdSGiuseppe CAVALLARO netdev_features_t features) 2397d2afb5bdSGiuseppe CAVALLARO { 2398d2afb5bdSGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(netdev); 2399d2afb5bdSGiuseppe CAVALLARO 2400d2afb5bdSGiuseppe CAVALLARO /* Keep the COE Type in case of csum is supporting */ 2401d2afb5bdSGiuseppe CAVALLARO if (features & NETIF_F_RXCSUM) 2402d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = priv->plat->rx_coe; 2403d2afb5bdSGiuseppe CAVALLARO else 2404d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = 0; 2405d2afb5bdSGiuseppe CAVALLARO /* No check needed because rx_coe has been set before and it will be 2406d2afb5bdSGiuseppe CAVALLARO * fixed in case of issue. 2407d2afb5bdSGiuseppe CAVALLARO */ 2408d2afb5bdSGiuseppe CAVALLARO priv->hw->mac->rx_ipc(priv->hw); 2409d2afb5bdSGiuseppe CAVALLARO 2410d2afb5bdSGiuseppe CAVALLARO return 0; 2411d2afb5bdSGiuseppe CAVALLARO } 2412d2afb5bdSGiuseppe CAVALLARO 241332ceabcaSGiuseppe CAVALLARO /** 241432ceabcaSGiuseppe CAVALLARO * stmmac_interrupt - main ISR 241532ceabcaSGiuseppe CAVALLARO * @irq: interrupt number. 241632ceabcaSGiuseppe CAVALLARO * @dev_id: to pass the net device pointer. 241732ceabcaSGiuseppe CAVALLARO * Description: this is the main driver interrupt service routine. 2418732fdf0eSGiuseppe CAVALLARO * It can call: 2419732fdf0eSGiuseppe CAVALLARO * o DMA service routine (to manage incoming frame reception and transmission 2420732fdf0eSGiuseppe CAVALLARO * status) 2421732fdf0eSGiuseppe CAVALLARO * o Core interrupts to manage: remote wake-up, management counter, LPI 242232ceabcaSGiuseppe CAVALLARO * interrupts. 242332ceabcaSGiuseppe CAVALLARO */ 24247ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id) 24257ac6653aSJeff Kirsher { 24267ac6653aSJeff Kirsher struct net_device *dev = (struct net_device *)dev_id; 24277ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 24287ac6653aSJeff Kirsher 242989f7f2cfSSrinivas Kandagatla if (priv->irq_wake) 243089f7f2cfSSrinivas Kandagatla pm_wakeup_event(priv->device, 0); 243189f7f2cfSSrinivas Kandagatla 24327ac6653aSJeff Kirsher if (unlikely(!dev)) { 24337ac6653aSJeff Kirsher pr_err("%s: invalid dev pointer\n", __func__); 24347ac6653aSJeff Kirsher return IRQ_NONE; 24357ac6653aSJeff Kirsher } 24367ac6653aSJeff Kirsher 24377ac6653aSJeff Kirsher /* To handle GMAC own interrupts */ 2438d765955dSGiuseppe CAVALLARO if (priv->plat->has_gmac) { 24397ed24bbeSVince Bridgers int status = priv->hw->mac->host_irq_status(priv->hw, 24400982a0f6SGiuseppe CAVALLARO &priv->xstats); 2441d765955dSGiuseppe CAVALLARO if (unlikely(status)) { 2442d765955dSGiuseppe CAVALLARO /* For LPI we need to save the tx status */ 24430982a0f6SGiuseppe CAVALLARO if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE) 2444d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = true; 24450982a0f6SGiuseppe CAVALLARO if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE) 2446d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = false; 2447d765955dSGiuseppe CAVALLARO } 2448d765955dSGiuseppe CAVALLARO } 2449d765955dSGiuseppe CAVALLARO 2450d765955dSGiuseppe CAVALLARO /* To handle DMA interrupts */ 24517ac6653aSJeff Kirsher stmmac_dma_interrupt(priv); 24527ac6653aSJeff Kirsher 24537ac6653aSJeff Kirsher return IRQ_HANDLED; 24547ac6653aSJeff Kirsher } 24557ac6653aSJeff Kirsher 24567ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 24577ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools 2458ceb69499SGiuseppe CAVALLARO * to allow network I/O with interrupts disabled. 2459ceb69499SGiuseppe CAVALLARO */ 24607ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev) 24617ac6653aSJeff Kirsher { 24627ac6653aSJeff Kirsher disable_irq(dev->irq); 24637ac6653aSJeff Kirsher stmmac_interrupt(dev->irq, dev); 24647ac6653aSJeff Kirsher enable_irq(dev->irq); 24657ac6653aSJeff Kirsher } 24667ac6653aSJeff Kirsher #endif 24677ac6653aSJeff Kirsher 24687ac6653aSJeff Kirsher /** 24697ac6653aSJeff Kirsher * stmmac_ioctl - Entry point for the Ioctl 24707ac6653aSJeff Kirsher * @dev: Device pointer. 24717ac6653aSJeff Kirsher * @rq: An IOCTL specefic structure, that can contain a pointer to 24727ac6653aSJeff Kirsher * a proprietary structure used to pass information to the driver. 24737ac6653aSJeff Kirsher * @cmd: IOCTL command 24747ac6653aSJeff Kirsher * Description: 247532ceabcaSGiuseppe CAVALLARO * Currently it supports the phy_mii_ioctl(...) and HW time stamping. 24767ac6653aSJeff Kirsher */ 24777ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 24787ac6653aSJeff Kirsher { 24797ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 2480891434b1SRayagond Kokatanur int ret = -EOPNOTSUPP; 24817ac6653aSJeff Kirsher 24827ac6653aSJeff Kirsher if (!netif_running(dev)) 24837ac6653aSJeff Kirsher return -EINVAL; 24847ac6653aSJeff Kirsher 2485891434b1SRayagond Kokatanur switch (cmd) { 2486891434b1SRayagond Kokatanur case SIOCGMIIPHY: 2487891434b1SRayagond Kokatanur case SIOCGMIIREG: 2488891434b1SRayagond Kokatanur case SIOCSMIIREG: 24897ac6653aSJeff Kirsher if (!priv->phydev) 24907ac6653aSJeff Kirsher return -EINVAL; 24917ac6653aSJeff Kirsher ret = phy_mii_ioctl(priv->phydev, rq, cmd); 2492891434b1SRayagond Kokatanur break; 2493891434b1SRayagond Kokatanur case SIOCSHWTSTAMP: 2494891434b1SRayagond Kokatanur ret = stmmac_hwtstamp_ioctl(dev, rq); 2495891434b1SRayagond Kokatanur break; 2496891434b1SRayagond Kokatanur default: 2497891434b1SRayagond Kokatanur break; 2498891434b1SRayagond Kokatanur } 24997ac6653aSJeff Kirsher 25007ac6653aSJeff Kirsher return ret; 25017ac6653aSJeff Kirsher } 25027ac6653aSJeff Kirsher 250350fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 25047ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir; 25057ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_rings_status; 2506e7434821SGiuseppe CAVALLARO static struct dentry *stmmac_dma_cap; 25077ac29055SGiuseppe CAVALLARO 2508c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc, 2509c24602efSGiuseppe CAVALLARO struct seq_file *seq) 25107ac29055SGiuseppe CAVALLARO { 25117ac29055SGiuseppe CAVALLARO int i; 2512c24602efSGiuseppe CAVALLARO struct dma_extended_desc *ep = (struct dma_extended_desc *)head; 2513c24602efSGiuseppe CAVALLARO struct dma_desc *p = (struct dma_desc *)head; 25147ac29055SGiuseppe CAVALLARO 2515c24602efSGiuseppe CAVALLARO for (i = 0; i < size; i++) { 2516c24602efSGiuseppe CAVALLARO u64 x; 2517c24602efSGiuseppe CAVALLARO if (extend_desc) { 2518c24602efSGiuseppe CAVALLARO x = *(u64 *) ep; 2519c24602efSGiuseppe CAVALLARO seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 2520c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 2521c24602efSGiuseppe CAVALLARO (unsigned int)x, (unsigned int)(x >> 32), 2522c24602efSGiuseppe CAVALLARO ep->basic.des2, ep->basic.des3); 2523c24602efSGiuseppe CAVALLARO ep++; 2524c24602efSGiuseppe CAVALLARO } else { 2525c24602efSGiuseppe CAVALLARO x = *(u64 *) p; 2526c24602efSGiuseppe CAVALLARO seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 2527c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 2528c24602efSGiuseppe CAVALLARO (unsigned int)x, (unsigned int)(x >> 32), 2529c24602efSGiuseppe CAVALLARO p->des2, p->des3); 2530c24602efSGiuseppe CAVALLARO p++; 2531c24602efSGiuseppe CAVALLARO } 25327ac29055SGiuseppe CAVALLARO seq_printf(seq, "\n"); 25337ac29055SGiuseppe CAVALLARO } 2534c24602efSGiuseppe CAVALLARO } 25357ac29055SGiuseppe CAVALLARO 2536c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v) 2537c24602efSGiuseppe CAVALLARO { 2538c24602efSGiuseppe CAVALLARO struct net_device *dev = seq->private; 2539c24602efSGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(dev); 2540c24602efSGiuseppe CAVALLARO unsigned int txsize = priv->dma_tx_size; 2541c24602efSGiuseppe CAVALLARO unsigned int rxsize = priv->dma_rx_size; 25427ac29055SGiuseppe CAVALLARO 2543c24602efSGiuseppe CAVALLARO if (priv->extend_desc) { 2544c24602efSGiuseppe CAVALLARO seq_printf(seq, "Extended RX descriptor ring:\n"); 2545c24602efSGiuseppe CAVALLARO sysfs_display_ring((void *)priv->dma_erx, rxsize, 1, seq); 2546c24602efSGiuseppe CAVALLARO seq_printf(seq, "Extended TX descriptor ring:\n"); 2547c24602efSGiuseppe CAVALLARO sysfs_display_ring((void *)priv->dma_etx, txsize, 1, seq); 2548c24602efSGiuseppe CAVALLARO } else { 2549c24602efSGiuseppe CAVALLARO seq_printf(seq, "RX descriptor ring:\n"); 2550c24602efSGiuseppe CAVALLARO sysfs_display_ring((void *)priv->dma_rx, rxsize, 0, seq); 2551c24602efSGiuseppe CAVALLARO seq_printf(seq, "TX descriptor ring:\n"); 2552c24602efSGiuseppe CAVALLARO sysfs_display_ring((void *)priv->dma_tx, txsize, 0, seq); 25537ac29055SGiuseppe CAVALLARO } 25547ac29055SGiuseppe CAVALLARO 25557ac29055SGiuseppe CAVALLARO return 0; 25567ac29055SGiuseppe CAVALLARO } 25577ac29055SGiuseppe CAVALLARO 25587ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file) 25597ac29055SGiuseppe CAVALLARO { 25607ac29055SGiuseppe CAVALLARO return single_open(file, stmmac_sysfs_ring_read, inode->i_private); 25617ac29055SGiuseppe CAVALLARO } 25627ac29055SGiuseppe CAVALLARO 25637ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = { 25647ac29055SGiuseppe CAVALLARO .owner = THIS_MODULE, 25657ac29055SGiuseppe CAVALLARO .open = stmmac_sysfs_ring_open, 25667ac29055SGiuseppe CAVALLARO .read = seq_read, 25677ac29055SGiuseppe CAVALLARO .llseek = seq_lseek, 256874863948SDjalal Harouni .release = single_release, 25697ac29055SGiuseppe CAVALLARO }; 25707ac29055SGiuseppe CAVALLARO 2571e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v) 2572e7434821SGiuseppe CAVALLARO { 2573e7434821SGiuseppe CAVALLARO struct net_device *dev = seq->private; 2574e7434821SGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(dev); 2575e7434821SGiuseppe CAVALLARO 257619e30c14SGiuseppe CAVALLARO if (!priv->hw_cap_support) { 2577e7434821SGiuseppe CAVALLARO seq_printf(seq, "DMA HW features not supported\n"); 2578e7434821SGiuseppe CAVALLARO return 0; 2579e7434821SGiuseppe CAVALLARO } 2580e7434821SGiuseppe CAVALLARO 2581e7434821SGiuseppe CAVALLARO seq_printf(seq, "==============================\n"); 2582e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tDMA HW features\n"); 2583e7434821SGiuseppe CAVALLARO seq_printf(seq, "==============================\n"); 2584e7434821SGiuseppe CAVALLARO 2585e7434821SGiuseppe CAVALLARO seq_printf(seq, "\t10/100 Mbps %s\n", 2586e7434821SGiuseppe CAVALLARO (priv->dma_cap.mbps_10_100) ? "Y" : "N"); 2587e7434821SGiuseppe CAVALLARO seq_printf(seq, "\t1000 Mbps %s\n", 2588e7434821SGiuseppe CAVALLARO (priv->dma_cap.mbps_1000) ? "Y" : "N"); 2589e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tHalf duple %s\n", 2590e7434821SGiuseppe CAVALLARO (priv->dma_cap.half_duplex) ? "Y" : "N"); 2591e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tHash Filter: %s\n", 2592e7434821SGiuseppe CAVALLARO (priv->dma_cap.hash_filter) ? "Y" : "N"); 2593e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tMultiple MAC address registers: %s\n", 2594e7434821SGiuseppe CAVALLARO (priv->dma_cap.multi_addr) ? "Y" : "N"); 2595e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n", 2596e7434821SGiuseppe CAVALLARO (priv->dma_cap.pcs) ? "Y" : "N"); 2597e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tSMA (MDIO) Interface: %s\n", 2598e7434821SGiuseppe CAVALLARO (priv->dma_cap.sma_mdio) ? "Y" : "N"); 2599e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPMT Remote wake up: %s\n", 2600e7434821SGiuseppe CAVALLARO (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N"); 2601e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPMT Magic Frame: %s\n", 2602e7434821SGiuseppe CAVALLARO (priv->dma_cap.pmt_magic_frame) ? "Y" : "N"); 2603e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tRMON module: %s\n", 2604e7434821SGiuseppe CAVALLARO (priv->dma_cap.rmon) ? "Y" : "N"); 2605e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n", 2606e7434821SGiuseppe CAVALLARO (priv->dma_cap.time_stamp) ? "Y" : "N"); 2607e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n", 2608e7434821SGiuseppe CAVALLARO (priv->dma_cap.atime_stamp) ? "Y" : "N"); 2609e7434821SGiuseppe CAVALLARO seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n", 2610e7434821SGiuseppe CAVALLARO (priv->dma_cap.eee) ? "Y" : "N"); 2611e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N"); 2612e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tChecksum Offload in TX: %s\n", 2613e7434821SGiuseppe CAVALLARO (priv->dma_cap.tx_coe) ? "Y" : "N"); 2614e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n", 2615e7434821SGiuseppe CAVALLARO (priv->dma_cap.rx_coe_type1) ? "Y" : "N"); 2616e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n", 2617e7434821SGiuseppe CAVALLARO (priv->dma_cap.rx_coe_type2) ? "Y" : "N"); 2618e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n", 2619e7434821SGiuseppe CAVALLARO (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N"); 2620e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tNumber of Additional RX channel: %d\n", 2621e7434821SGiuseppe CAVALLARO priv->dma_cap.number_rx_channel); 2622e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tNumber of Additional TX channel: %d\n", 2623e7434821SGiuseppe CAVALLARO priv->dma_cap.number_tx_channel); 2624e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tEnhanced descriptors: %s\n", 2625e7434821SGiuseppe CAVALLARO (priv->dma_cap.enh_desc) ? "Y" : "N"); 2626e7434821SGiuseppe CAVALLARO 2627e7434821SGiuseppe CAVALLARO return 0; 2628e7434821SGiuseppe CAVALLARO } 2629e7434821SGiuseppe CAVALLARO 2630e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file) 2631e7434821SGiuseppe CAVALLARO { 2632e7434821SGiuseppe CAVALLARO return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private); 2633e7434821SGiuseppe CAVALLARO } 2634e7434821SGiuseppe CAVALLARO 2635e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = { 2636e7434821SGiuseppe CAVALLARO .owner = THIS_MODULE, 2637e7434821SGiuseppe CAVALLARO .open = stmmac_sysfs_dma_cap_open, 2638e7434821SGiuseppe CAVALLARO .read = seq_read, 2639e7434821SGiuseppe CAVALLARO .llseek = seq_lseek, 264074863948SDjalal Harouni .release = single_release, 2641e7434821SGiuseppe CAVALLARO }; 2642e7434821SGiuseppe CAVALLARO 26437ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev) 26447ac29055SGiuseppe CAVALLARO { 26457ac29055SGiuseppe CAVALLARO /* Create debugfs entries */ 26467ac29055SGiuseppe CAVALLARO stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL); 26477ac29055SGiuseppe CAVALLARO 26487ac29055SGiuseppe CAVALLARO if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) { 26497ac29055SGiuseppe CAVALLARO pr_err("ERROR %s, debugfs create directory failed\n", 26507ac29055SGiuseppe CAVALLARO STMMAC_RESOURCE_NAME); 26517ac29055SGiuseppe CAVALLARO 26527ac29055SGiuseppe CAVALLARO return -ENOMEM; 26537ac29055SGiuseppe CAVALLARO } 26547ac29055SGiuseppe CAVALLARO 26557ac29055SGiuseppe CAVALLARO /* Entry to report DMA RX/TX rings */ 26567ac29055SGiuseppe CAVALLARO stmmac_rings_status = debugfs_create_file("descriptors_status", 26577ac29055SGiuseppe CAVALLARO S_IRUGO, stmmac_fs_dir, dev, 26587ac29055SGiuseppe CAVALLARO &stmmac_rings_status_fops); 26597ac29055SGiuseppe CAVALLARO 26607ac29055SGiuseppe CAVALLARO if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) { 26617ac29055SGiuseppe CAVALLARO pr_info("ERROR creating stmmac ring debugfs file\n"); 26627ac29055SGiuseppe CAVALLARO debugfs_remove(stmmac_fs_dir); 26637ac29055SGiuseppe CAVALLARO 26647ac29055SGiuseppe CAVALLARO return -ENOMEM; 26657ac29055SGiuseppe CAVALLARO } 26667ac29055SGiuseppe CAVALLARO 2667e7434821SGiuseppe CAVALLARO /* Entry to report the DMA HW features */ 2668e7434821SGiuseppe CAVALLARO stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir, 2669e7434821SGiuseppe CAVALLARO dev, &stmmac_dma_cap_fops); 2670e7434821SGiuseppe CAVALLARO 2671e7434821SGiuseppe CAVALLARO if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) { 2672e7434821SGiuseppe CAVALLARO pr_info("ERROR creating stmmac MMC debugfs file\n"); 2673e7434821SGiuseppe CAVALLARO debugfs_remove(stmmac_rings_status); 2674e7434821SGiuseppe CAVALLARO debugfs_remove(stmmac_fs_dir); 2675e7434821SGiuseppe CAVALLARO 2676e7434821SGiuseppe CAVALLARO return -ENOMEM; 2677e7434821SGiuseppe CAVALLARO } 2678e7434821SGiuseppe CAVALLARO 26797ac29055SGiuseppe CAVALLARO return 0; 26807ac29055SGiuseppe CAVALLARO } 26817ac29055SGiuseppe CAVALLARO 26827ac29055SGiuseppe CAVALLARO static void stmmac_exit_fs(void) 26837ac29055SGiuseppe CAVALLARO { 26847ac29055SGiuseppe CAVALLARO debugfs_remove(stmmac_rings_status); 2685e7434821SGiuseppe CAVALLARO debugfs_remove(stmmac_dma_cap); 26867ac29055SGiuseppe CAVALLARO debugfs_remove(stmmac_fs_dir); 26877ac29055SGiuseppe CAVALLARO } 268850fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */ 26897ac29055SGiuseppe CAVALLARO 26907ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = { 26917ac6653aSJeff Kirsher .ndo_open = stmmac_open, 26927ac6653aSJeff Kirsher .ndo_start_xmit = stmmac_xmit, 26937ac6653aSJeff Kirsher .ndo_stop = stmmac_release, 26947ac6653aSJeff Kirsher .ndo_change_mtu = stmmac_change_mtu, 26957ac6653aSJeff Kirsher .ndo_fix_features = stmmac_fix_features, 2696d2afb5bdSGiuseppe CAVALLARO .ndo_set_features = stmmac_set_features, 269701789349SJiri Pirko .ndo_set_rx_mode = stmmac_set_rx_mode, 26987ac6653aSJeff Kirsher .ndo_tx_timeout = stmmac_tx_timeout, 26997ac6653aSJeff Kirsher .ndo_do_ioctl = stmmac_ioctl, 27007ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 27017ac6653aSJeff Kirsher .ndo_poll_controller = stmmac_poll_controller, 27027ac6653aSJeff Kirsher #endif 27037ac6653aSJeff Kirsher .ndo_set_mac_address = eth_mac_addr, 27047ac6653aSJeff Kirsher }; 27057ac6653aSJeff Kirsher 27067ac6653aSJeff Kirsher /** 2707cf3f047bSGiuseppe CAVALLARO * stmmac_hw_init - Init the MAC device 270832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 2709732fdf0eSGiuseppe CAVALLARO * Description: this function is to configure the MAC device according to 2710732fdf0eSGiuseppe CAVALLARO * some platform parameters or the HW capability register. It prepares the 2711732fdf0eSGiuseppe CAVALLARO * driver to use either ring or chain modes and to setup either enhanced or 2712732fdf0eSGiuseppe CAVALLARO * normal descriptors. 2713cf3f047bSGiuseppe CAVALLARO */ 2714cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv) 2715cf3f047bSGiuseppe CAVALLARO { 2716cf3f047bSGiuseppe CAVALLARO struct mac_device_info *mac; 2717cf3f047bSGiuseppe CAVALLARO 2718cf3f047bSGiuseppe CAVALLARO /* Identify the MAC HW device */ 271903f2eecdSMarc Kleine-Budde if (priv->plat->has_gmac) { 272003f2eecdSMarc Kleine-Budde priv->dev->priv_flags |= IFF_UNICAST_FLT; 27213b57de95SVince Bridgers mac = dwmac1000_setup(priv->ioaddr, 27223b57de95SVince Bridgers priv->plat->multicast_filter_bins, 27233b57de95SVince Bridgers priv->plat->unicast_filter_entries); 272403f2eecdSMarc Kleine-Budde } else { 2725cf3f047bSGiuseppe CAVALLARO mac = dwmac100_setup(priv->ioaddr); 272603f2eecdSMarc Kleine-Budde } 2727cf3f047bSGiuseppe CAVALLARO if (!mac) 2728cf3f047bSGiuseppe CAVALLARO return -ENOMEM; 2729cf3f047bSGiuseppe CAVALLARO 2730cf3f047bSGiuseppe CAVALLARO priv->hw = mac; 2731cf3f047bSGiuseppe CAVALLARO 2732cf3f047bSGiuseppe CAVALLARO /* Get and dump the chip ID */ 2733cffb13f4SGiuseppe CAVALLARO priv->synopsys_id = stmmac_get_synopsys_id(priv); 2734cf3f047bSGiuseppe CAVALLARO 27354a7d666aSGiuseppe CAVALLARO /* To use the chained or ring mode */ 27364a7d666aSGiuseppe CAVALLARO if (chain_mode) { 273729896a67SGiuseppe CAVALLARO priv->hw->mode = &chain_mode_ops; 27384a7d666aSGiuseppe CAVALLARO pr_info(" Chain mode enabled\n"); 27394a7d666aSGiuseppe CAVALLARO priv->mode = STMMAC_CHAIN_MODE; 27404a7d666aSGiuseppe CAVALLARO } else { 274129896a67SGiuseppe CAVALLARO priv->hw->mode = &ring_mode_ops; 27424a7d666aSGiuseppe CAVALLARO pr_info(" Ring mode enabled\n"); 27434a7d666aSGiuseppe CAVALLARO priv->mode = STMMAC_RING_MODE; 27444a7d666aSGiuseppe CAVALLARO } 27454a7d666aSGiuseppe CAVALLARO 2746cf3f047bSGiuseppe CAVALLARO /* Get the HW capability (new GMAC newer than 3.50a) */ 2747cf3f047bSGiuseppe CAVALLARO priv->hw_cap_support = stmmac_get_hw_features(priv); 2748cf3f047bSGiuseppe CAVALLARO if (priv->hw_cap_support) { 2749cf3f047bSGiuseppe CAVALLARO pr_info(" DMA HW capability register supported"); 2750cf3f047bSGiuseppe CAVALLARO 2751cf3f047bSGiuseppe CAVALLARO /* We can override some gmac/dma configuration fields: e.g. 2752cf3f047bSGiuseppe CAVALLARO * enh_desc, tx_coe (e.g. that are passed through the 2753cf3f047bSGiuseppe CAVALLARO * platform) with the values from the HW capability 2754cf3f047bSGiuseppe CAVALLARO * register (if supported). 2755cf3f047bSGiuseppe CAVALLARO */ 2756cf3f047bSGiuseppe CAVALLARO priv->plat->enh_desc = priv->dma_cap.enh_desc; 2757cf3f047bSGiuseppe CAVALLARO priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; 275838912bdbSDeepak SIKRI 2759dec2165fSSonic Zhang /* TXCOE doesn't work in thresh DMA mode */ 2760dec2165fSSonic Zhang if (priv->plat->force_thresh_dma_mode) 2761dec2165fSSonic Zhang priv->plat->tx_coe = 0; 2762dec2165fSSonic Zhang else 276338912bdbSDeepak SIKRI priv->plat->tx_coe = priv->dma_cap.tx_coe; 276438912bdbSDeepak SIKRI 276538912bdbSDeepak SIKRI if (priv->dma_cap.rx_coe_type2) 276638912bdbSDeepak SIKRI priv->plat->rx_coe = STMMAC_RX_COE_TYPE2; 276738912bdbSDeepak SIKRI else if (priv->dma_cap.rx_coe_type1) 276838912bdbSDeepak SIKRI priv->plat->rx_coe = STMMAC_RX_COE_TYPE1; 276938912bdbSDeepak SIKRI 2770cf3f047bSGiuseppe CAVALLARO } else 2771cf3f047bSGiuseppe CAVALLARO pr_info(" No HW DMA feature register supported"); 2772cf3f047bSGiuseppe CAVALLARO 277361369d02SByungho An /* To use alternate (extended) or normal descriptor structures */ 277461369d02SByungho An stmmac_selec_desc_mode(priv); 277561369d02SByungho An 2776d2afb5bdSGiuseppe CAVALLARO if (priv->plat->rx_coe) { 2777d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = priv->plat->rx_coe; 277838912bdbSDeepak SIKRI pr_info(" RX Checksum Offload Engine supported (type %d)\n", 277938912bdbSDeepak SIKRI priv->plat->rx_coe); 2780d2afb5bdSGiuseppe CAVALLARO } 2781cf3f047bSGiuseppe CAVALLARO if (priv->plat->tx_coe) 2782cf3f047bSGiuseppe CAVALLARO pr_info(" TX Checksum insertion supported\n"); 2783cf3f047bSGiuseppe CAVALLARO 2784cf3f047bSGiuseppe CAVALLARO if (priv->plat->pmt) { 2785cf3f047bSGiuseppe CAVALLARO pr_info(" Wake-Up On Lan supported\n"); 2786cf3f047bSGiuseppe CAVALLARO device_set_wakeup_capable(priv->device, 1); 2787cf3f047bSGiuseppe CAVALLARO } 2788cf3f047bSGiuseppe CAVALLARO 2789c24602efSGiuseppe CAVALLARO return 0; 2790cf3f047bSGiuseppe CAVALLARO } 2791cf3f047bSGiuseppe CAVALLARO 2792cf3f047bSGiuseppe CAVALLARO /** 2793bfab27a1SGiuseppe CAVALLARO * stmmac_dvr_probe 2794bfab27a1SGiuseppe CAVALLARO * @device: device pointer 2795ff3dd78cSGiuseppe CAVALLARO * @plat_dat: platform data pointer 2796ff3dd78cSGiuseppe CAVALLARO * @addr: iobase memory address 2797bfab27a1SGiuseppe CAVALLARO * Description: this is the main probe function used to 2798bfab27a1SGiuseppe CAVALLARO * call the alloc_etherdev, allocate the priv structure. 27999afec6efSAndy Shevchenko * Return: 28009afec6efSAndy Shevchenko * on success the new private structure is returned, otherwise the error 28019afec6efSAndy Shevchenko * pointer. 28027ac6653aSJeff Kirsher */ 2803bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *stmmac_dvr_probe(struct device *device, 2804cf3f047bSGiuseppe CAVALLARO struct plat_stmmacenet_data *plat_dat, 2805cf3f047bSGiuseppe CAVALLARO void __iomem *addr) 28067ac6653aSJeff Kirsher { 28077ac6653aSJeff Kirsher int ret = 0; 2808bfab27a1SGiuseppe CAVALLARO struct net_device *ndev = NULL; 2809bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *priv; 28107ac6653aSJeff Kirsher 2811bfab27a1SGiuseppe CAVALLARO ndev = alloc_etherdev(sizeof(struct stmmac_priv)); 281241de8d4cSJoe Perches if (!ndev) 28139afec6efSAndy Shevchenko return ERR_PTR(-ENOMEM); 28147ac6653aSJeff Kirsher 2815bfab27a1SGiuseppe CAVALLARO SET_NETDEV_DEV(ndev, device); 28167ac6653aSJeff Kirsher 2817bfab27a1SGiuseppe CAVALLARO priv = netdev_priv(ndev); 2818bfab27a1SGiuseppe CAVALLARO priv->device = device; 2819bfab27a1SGiuseppe CAVALLARO priv->dev = ndev; 2820bfab27a1SGiuseppe CAVALLARO 2821bfab27a1SGiuseppe CAVALLARO stmmac_set_ethtool_ops(ndev); 2822cf3f047bSGiuseppe CAVALLARO priv->pause = pause; 2823cf3f047bSGiuseppe CAVALLARO priv->plat = plat_dat; 2824cf3f047bSGiuseppe CAVALLARO priv->ioaddr = addr; 2825cf3f047bSGiuseppe CAVALLARO priv->dev->base_addr = (unsigned long)addr; 2826bfab27a1SGiuseppe CAVALLARO 2827cf3f047bSGiuseppe CAVALLARO /* Verify driver arguments */ 2828cf3f047bSGiuseppe CAVALLARO stmmac_verify_args(); 2829cf3f047bSGiuseppe CAVALLARO 2830cf3f047bSGiuseppe CAVALLARO /* Override with kernel parameters if supplied XXX CRS XXX 2831ceb69499SGiuseppe CAVALLARO * this needs to have multiple instances 2832ceb69499SGiuseppe CAVALLARO */ 2833cf3f047bSGiuseppe CAVALLARO if ((phyaddr >= 0) && (phyaddr <= 31)) 2834cf3f047bSGiuseppe CAVALLARO priv->plat->phy_addr = phyaddr; 2835cf3f047bSGiuseppe CAVALLARO 283662866e98SChen-Yu Tsai priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME); 283762866e98SChen-Yu Tsai if (IS_ERR(priv->stmmac_clk)) { 283862866e98SChen-Yu Tsai dev_warn(priv->device, "%s: warning: cannot get CSR clock\n", 283962866e98SChen-Yu Tsai __func__); 2840c5bb86c3SKweh, Hock Leong /* If failed to obtain stmmac_clk and specific clk_csr value 2841c5bb86c3SKweh, Hock Leong * is NOT passed from the platform, probe fail. 2842c5bb86c3SKweh, Hock Leong */ 2843c5bb86c3SKweh, Hock Leong if (!priv->plat->clk_csr) { 2844c5e4ddbdSChen-Yu Tsai ret = PTR_ERR(priv->stmmac_clk); 284562866e98SChen-Yu Tsai goto error_clk_get; 2846c5bb86c3SKweh, Hock Leong } else { 2847c5bb86c3SKweh, Hock Leong priv->stmmac_clk = NULL; 2848c5bb86c3SKweh, Hock Leong } 284962866e98SChen-Yu Tsai } 285062866e98SChen-Yu Tsai clk_prepare_enable(priv->stmmac_clk); 285162866e98SChen-Yu Tsai 28525f9755d2SAndrew Bresticker priv->pclk = devm_clk_get(priv->device, "pclk"); 28535f9755d2SAndrew Bresticker if (IS_ERR(priv->pclk)) { 28545f9755d2SAndrew Bresticker if (PTR_ERR(priv->pclk) == -EPROBE_DEFER) { 28555f9755d2SAndrew Bresticker ret = -EPROBE_DEFER; 28565f9755d2SAndrew Bresticker goto error_pclk_get; 28575f9755d2SAndrew Bresticker } 28585f9755d2SAndrew Bresticker priv->pclk = NULL; 28595f9755d2SAndrew Bresticker } 28605f9755d2SAndrew Bresticker clk_prepare_enable(priv->pclk); 28615f9755d2SAndrew Bresticker 2862c5e4ddbdSChen-Yu Tsai priv->stmmac_rst = devm_reset_control_get(priv->device, 2863c5e4ddbdSChen-Yu Tsai STMMAC_RESOURCE_NAME); 2864c5e4ddbdSChen-Yu Tsai if (IS_ERR(priv->stmmac_rst)) { 2865c5e4ddbdSChen-Yu Tsai if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) { 2866c5e4ddbdSChen-Yu Tsai ret = -EPROBE_DEFER; 2867c5e4ddbdSChen-Yu Tsai goto error_hw_init; 2868c5e4ddbdSChen-Yu Tsai } 2869c5e4ddbdSChen-Yu Tsai dev_info(priv->device, "no reset control found\n"); 2870c5e4ddbdSChen-Yu Tsai priv->stmmac_rst = NULL; 2871c5e4ddbdSChen-Yu Tsai } 2872c5e4ddbdSChen-Yu Tsai if (priv->stmmac_rst) 2873c5e4ddbdSChen-Yu Tsai reset_control_deassert(priv->stmmac_rst); 2874c5e4ddbdSChen-Yu Tsai 2875cf3f047bSGiuseppe CAVALLARO /* Init MAC and get the capabilities */ 2876c24602efSGiuseppe CAVALLARO ret = stmmac_hw_init(priv); 2877c24602efSGiuseppe CAVALLARO if (ret) 287862866e98SChen-Yu Tsai goto error_hw_init; 2879cf3f047bSGiuseppe CAVALLARO 2880cf3f047bSGiuseppe CAVALLARO ndev->netdev_ops = &stmmac_netdev_ops; 2881cf3f047bSGiuseppe CAVALLARO 2882cf3f047bSGiuseppe CAVALLARO ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | 2883cf3f047bSGiuseppe CAVALLARO NETIF_F_RXCSUM; 2884bfab27a1SGiuseppe CAVALLARO ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; 2885bfab27a1SGiuseppe CAVALLARO ndev->watchdog_timeo = msecs_to_jiffies(watchdog); 28867ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED 28877ac6653aSJeff Kirsher /* Both mac100 and gmac support receive VLAN tag detection */ 2888f646968fSPatrick McHardy ndev->features |= NETIF_F_HW_VLAN_CTAG_RX; 28897ac6653aSJeff Kirsher #endif 28907ac6653aSJeff Kirsher priv->msg_enable = netif_msg_init(debug, default_msg_level); 28917ac6653aSJeff Kirsher 28927ac6653aSJeff Kirsher if (flow_ctrl) 28937ac6653aSJeff Kirsher priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ 28947ac6653aSJeff Kirsher 289562a2ab93SGiuseppe CAVALLARO /* Rx Watchdog is available in the COREs newer than the 3.40. 289662a2ab93SGiuseppe CAVALLARO * In some case, for example on bugged HW this feature 289762a2ab93SGiuseppe CAVALLARO * has to be disable and this can be done by passing the 289862a2ab93SGiuseppe CAVALLARO * riwt_off field from the platform. 289962a2ab93SGiuseppe CAVALLARO */ 290062a2ab93SGiuseppe CAVALLARO if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) { 290162a2ab93SGiuseppe CAVALLARO priv->use_riwt = 1; 290262a2ab93SGiuseppe CAVALLARO pr_info(" Enable RX Mitigation via HW Watchdog Timer\n"); 290362a2ab93SGiuseppe CAVALLARO } 290462a2ab93SGiuseppe CAVALLARO 2905bfab27a1SGiuseppe CAVALLARO netif_napi_add(ndev, &priv->napi, stmmac_poll, 64); 29067ac6653aSJeff Kirsher 29077ac6653aSJeff Kirsher spin_lock_init(&priv->lock); 2908a9097a96SGiuseppe CAVALLARO spin_lock_init(&priv->tx_lock); 29097ac6653aSJeff Kirsher 2910bfab27a1SGiuseppe CAVALLARO ret = register_netdev(ndev); 29117ac6653aSJeff Kirsher if (ret) { 2912cf3f047bSGiuseppe CAVALLARO pr_err("%s: ERROR %i registering the device\n", __func__, ret); 29136a81c26fSViresh Kumar goto error_netdev_register; 29147ac6653aSJeff Kirsher } 29157ac6653aSJeff Kirsher 2916cd7201f4SGiuseppe CAVALLARO /* If a specific clk_csr value is passed from the platform 2917cd7201f4SGiuseppe CAVALLARO * this means that the CSR Clock Range selection cannot be 2918cd7201f4SGiuseppe CAVALLARO * changed at run-time and it is fixed. Viceversa the driver'll try to 2919cd7201f4SGiuseppe CAVALLARO * set the MDC clock dynamically according to the csr actual 2920cd7201f4SGiuseppe CAVALLARO * clock input. 2921cd7201f4SGiuseppe CAVALLARO */ 2922cd7201f4SGiuseppe CAVALLARO if (!priv->plat->clk_csr) 2923cd7201f4SGiuseppe CAVALLARO stmmac_clk_csr_set(priv); 2924cd7201f4SGiuseppe CAVALLARO else 2925cd7201f4SGiuseppe CAVALLARO priv->clk_csr = priv->plat->clk_csr; 2926cd7201f4SGiuseppe CAVALLARO 2927e58bb43fSGiuseppe CAVALLARO stmmac_check_pcs_mode(priv); 2928e58bb43fSGiuseppe CAVALLARO 29294d8f0825SByungho An if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 29304d8f0825SByungho An priv->pcs != STMMAC_PCS_RTBI) { 29314bfcbd7aSFrancesco Virlinzi /* MDIO bus Registration */ 29324bfcbd7aSFrancesco Virlinzi ret = stmmac_mdio_register(ndev); 29334bfcbd7aSFrancesco Virlinzi if (ret < 0) { 29344bfcbd7aSFrancesco Virlinzi pr_debug("%s: MDIO bus (id: %d) registration failed", 29354bfcbd7aSFrancesco Virlinzi __func__, priv->plat->bus_id); 29366a81c26fSViresh Kumar goto error_mdio_register; 29374bfcbd7aSFrancesco Virlinzi } 2938e58bb43fSGiuseppe CAVALLARO } 29394bfcbd7aSFrancesco Virlinzi 2940bfab27a1SGiuseppe CAVALLARO return priv; 29417ac6653aSJeff Kirsher 29426a81c26fSViresh Kumar error_mdio_register: 29437ac6653aSJeff Kirsher unregister_netdev(ndev); 29446a81c26fSViresh Kumar error_netdev_register: 29456a81c26fSViresh Kumar netif_napi_del(&priv->napi); 294662866e98SChen-Yu Tsai error_hw_init: 29475f9755d2SAndrew Bresticker clk_disable_unprepare(priv->pclk); 29485f9755d2SAndrew Bresticker error_pclk_get: 294962866e98SChen-Yu Tsai clk_disable_unprepare(priv->stmmac_clk); 295062866e98SChen-Yu Tsai error_clk_get: 29517ac6653aSJeff Kirsher free_netdev(ndev); 29527ac6653aSJeff Kirsher 2953c5e4ddbdSChen-Yu Tsai return ERR_PTR(ret); 29547ac6653aSJeff Kirsher } 2955b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_probe); 29567ac6653aSJeff Kirsher 29577ac6653aSJeff Kirsher /** 29587ac6653aSJeff Kirsher * stmmac_dvr_remove 2959bfab27a1SGiuseppe CAVALLARO * @ndev: net device pointer 29607ac6653aSJeff Kirsher * Description: this function resets the TX/RX processes, disables the MAC RX/TX 2961bfab27a1SGiuseppe CAVALLARO * changes the link status, releases the DMA descriptor rings. 29627ac6653aSJeff Kirsher */ 2963bfab27a1SGiuseppe CAVALLARO int stmmac_dvr_remove(struct net_device *ndev) 29647ac6653aSJeff Kirsher { 29657ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 29667ac6653aSJeff Kirsher 29677ac6653aSJeff Kirsher pr_info("%s:\n\tremoving driver", __func__); 29687ac6653aSJeff Kirsher 29697ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 29707ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 29717ac6653aSJeff Kirsher 2972bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 29734d8f0825SByungho An if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 29744d8f0825SByungho An priv->pcs != STMMAC_PCS_RTBI) 29754bfcbd7aSFrancesco Virlinzi stmmac_mdio_unregister(ndev); 29767ac6653aSJeff Kirsher netif_carrier_off(ndev); 29777ac6653aSJeff Kirsher unregister_netdev(ndev); 2978c5e4ddbdSChen-Yu Tsai if (priv->stmmac_rst) 2979c5e4ddbdSChen-Yu Tsai reset_control_assert(priv->stmmac_rst); 29805f9755d2SAndrew Bresticker clk_disable_unprepare(priv->pclk); 298162866e98SChen-Yu Tsai clk_disable_unprepare(priv->stmmac_clk); 29827ac6653aSJeff Kirsher free_netdev(ndev); 29837ac6653aSJeff Kirsher 29847ac6653aSJeff Kirsher return 0; 29857ac6653aSJeff Kirsher } 2986b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_remove); 29877ac6653aSJeff Kirsher 2988732fdf0eSGiuseppe CAVALLARO /** 2989732fdf0eSGiuseppe CAVALLARO * stmmac_suspend - suspend callback 2990732fdf0eSGiuseppe CAVALLARO * @ndev: net device pointer 2991732fdf0eSGiuseppe CAVALLARO * Description: this is the function to suspend the device and it is called 2992732fdf0eSGiuseppe CAVALLARO * by the platform driver to stop the network queue, release the resources, 2993732fdf0eSGiuseppe CAVALLARO * program the PMT register (for WoL), clean and release driver resources. 2994732fdf0eSGiuseppe CAVALLARO */ 2995bfab27a1SGiuseppe CAVALLARO int stmmac_suspend(struct net_device *ndev) 29967ac6653aSJeff Kirsher { 29977ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 2998f8c5a875SGiuseppe CAVALLARO unsigned long flags; 29997ac6653aSJeff Kirsher 30007ac6653aSJeff Kirsher if (!ndev || !netif_running(ndev)) 30017ac6653aSJeff Kirsher return 0; 30027ac6653aSJeff Kirsher 3003102463b1SFrancesco Virlinzi if (priv->phydev) 3004102463b1SFrancesco Virlinzi phy_stop(priv->phydev); 3005102463b1SFrancesco Virlinzi 3006f8c5a875SGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 30077ac6653aSJeff Kirsher 30087ac6653aSJeff Kirsher netif_device_detach(ndev); 30097ac6653aSJeff Kirsher netif_stop_queue(ndev); 30107ac6653aSJeff Kirsher 30117ac6653aSJeff Kirsher napi_disable(&priv->napi); 30127ac6653aSJeff Kirsher 30137ac6653aSJeff Kirsher /* Stop TX/RX DMA */ 30147ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 30157ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 3016c24602efSGiuseppe CAVALLARO 3017c24602efSGiuseppe CAVALLARO stmmac_clear_descriptors(priv); 30187ac6653aSJeff Kirsher 30197ac6653aSJeff Kirsher /* Enable Power down mode by programming the PMT regs */ 302089f7f2cfSSrinivas Kandagatla if (device_may_wakeup(priv->device)) { 30217ed24bbeSVince Bridgers priv->hw->mac->pmt(priv->hw, priv->wolopts); 302289f7f2cfSSrinivas Kandagatla priv->irq_wake = 1; 302389f7f2cfSSrinivas Kandagatla } else { 3024bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 3025db88f10aSSrinivas Kandagatla pinctrl_pm_select_sleep_state(priv->device); 3026ba1377ffSGiuseppe CAVALLARO /* Disable clock in case of PWM is off */ 30275f9755d2SAndrew Bresticker clk_disable(priv->pclk); 3028777da230SGiuseppe CAVALLARO clk_disable(priv->stmmac_clk); 3029ba1377ffSGiuseppe CAVALLARO } 3030f8c5a875SGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 30312d871aa0SVince Bridgers 30322d871aa0SVince Bridgers priv->oldlink = 0; 30332d871aa0SVince Bridgers priv->speed = 0; 30342d871aa0SVince Bridgers priv->oldduplex = -1; 30357ac6653aSJeff Kirsher return 0; 30367ac6653aSJeff Kirsher } 3037b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_suspend); 30387ac6653aSJeff Kirsher 3039732fdf0eSGiuseppe CAVALLARO /** 3040732fdf0eSGiuseppe CAVALLARO * stmmac_resume - resume callback 3041732fdf0eSGiuseppe CAVALLARO * @ndev: net device pointer 3042732fdf0eSGiuseppe CAVALLARO * Description: when resume this function is invoked to setup the DMA and CORE 3043732fdf0eSGiuseppe CAVALLARO * in a usable state. 3044732fdf0eSGiuseppe CAVALLARO */ 3045bfab27a1SGiuseppe CAVALLARO int stmmac_resume(struct net_device *ndev) 30467ac6653aSJeff Kirsher { 30477ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 3048f8c5a875SGiuseppe CAVALLARO unsigned long flags; 30497ac6653aSJeff Kirsher 30507ac6653aSJeff Kirsher if (!netif_running(ndev)) 30517ac6653aSJeff Kirsher return 0; 30527ac6653aSJeff Kirsher 3053f8c5a875SGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 30547ac6653aSJeff Kirsher 30557ac6653aSJeff Kirsher /* Power Down bit, into the PM register, is cleared 30567ac6653aSJeff Kirsher * automatically as soon as a magic packet or a Wake-up frame 30577ac6653aSJeff Kirsher * is received. Anyway, it's better to manually clear 30587ac6653aSJeff Kirsher * this bit because it can generate problems while resuming 3059ceb69499SGiuseppe CAVALLARO * from another devices (e.g. serial console). 3060ceb69499SGiuseppe CAVALLARO */ 3061623997fbSSrinivas Kandagatla if (device_may_wakeup(priv->device)) { 30627ed24bbeSVince Bridgers priv->hw->mac->pmt(priv->hw, 0); 306389f7f2cfSSrinivas Kandagatla priv->irq_wake = 0; 3064623997fbSSrinivas Kandagatla } else { 3065db88f10aSSrinivas Kandagatla pinctrl_pm_select_default_state(priv->device); 3066ba1377ffSGiuseppe CAVALLARO /* enable the clk prevously disabled */ 3067777da230SGiuseppe CAVALLARO clk_enable(priv->stmmac_clk); 30685f9755d2SAndrew Bresticker clk_enable(priv->pclk); 3069623997fbSSrinivas Kandagatla /* reset the phy so that it's ready */ 3070623997fbSSrinivas Kandagatla if (priv->mii) 3071623997fbSSrinivas Kandagatla stmmac_mdio_reset(priv->mii); 3072623997fbSSrinivas Kandagatla } 30737ac6653aSJeff Kirsher 30747ac6653aSJeff Kirsher netif_device_attach(ndev); 30757ac6653aSJeff Kirsher 3076777da230SGiuseppe CAVALLARO init_dma_desc_rings(ndev, GFP_ATOMIC); 3077fe131929SHuacai Chen stmmac_hw_setup(ndev, false); 3078777da230SGiuseppe CAVALLARO stmmac_init_tx_coalesce(priv); 30797ac6653aSJeff Kirsher 30807ac6653aSJeff Kirsher napi_enable(&priv->napi); 30817ac6653aSJeff Kirsher 30827ac6653aSJeff Kirsher netif_start_queue(ndev); 30837ac6653aSJeff Kirsher 3084f8c5a875SGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 3085102463b1SFrancesco Virlinzi 3086102463b1SFrancesco Virlinzi if (priv->phydev) 3087102463b1SFrancesco Virlinzi phy_start(priv->phydev); 3088102463b1SFrancesco Virlinzi 30897ac6653aSJeff Kirsher return 0; 30907ac6653aSJeff Kirsher } 3091b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_resume); 3092ba27ec66SGiuseppe CAVALLARO 30937ac6653aSJeff Kirsher #ifndef MODULE 30947ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str) 30957ac6653aSJeff Kirsher { 30967ac6653aSJeff Kirsher char *opt; 30977ac6653aSJeff Kirsher 30987ac6653aSJeff Kirsher if (!str || !*str) 30997ac6653aSJeff Kirsher return -EINVAL; 31007ac6653aSJeff Kirsher while ((opt = strsep(&str, ",")) != NULL) { 31017ac6653aSJeff Kirsher if (!strncmp(opt, "debug:", 6)) { 3102ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 6, 0, &debug)) 31037ac6653aSJeff Kirsher goto err; 31047ac6653aSJeff Kirsher } else if (!strncmp(opt, "phyaddr:", 8)) { 3105ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 8, 0, &phyaddr)) 31067ac6653aSJeff Kirsher goto err; 31077ac6653aSJeff Kirsher } else if (!strncmp(opt, "dma_txsize:", 11)) { 3108ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 11, 0, &dma_txsize)) 31097ac6653aSJeff Kirsher goto err; 31107ac6653aSJeff Kirsher } else if (!strncmp(opt, "dma_rxsize:", 11)) { 3111ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 11, 0, &dma_rxsize)) 31127ac6653aSJeff Kirsher goto err; 31137ac6653aSJeff Kirsher } else if (!strncmp(opt, "buf_sz:", 7)) { 3114ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 7, 0, &buf_sz)) 31157ac6653aSJeff Kirsher goto err; 31167ac6653aSJeff Kirsher } else if (!strncmp(opt, "tc:", 3)) { 3117ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 3, 0, &tc)) 31187ac6653aSJeff Kirsher goto err; 31197ac6653aSJeff Kirsher } else if (!strncmp(opt, "watchdog:", 9)) { 3120ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 9, 0, &watchdog)) 31217ac6653aSJeff Kirsher goto err; 31227ac6653aSJeff Kirsher } else if (!strncmp(opt, "flow_ctrl:", 10)) { 3123ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 10, 0, &flow_ctrl)) 31247ac6653aSJeff Kirsher goto err; 31257ac6653aSJeff Kirsher } else if (!strncmp(opt, "pause:", 6)) { 3126ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 6, 0, &pause)) 31277ac6653aSJeff Kirsher goto err; 3128506f669cSGiuseppe CAVALLARO } else if (!strncmp(opt, "eee_timer:", 10)) { 3129d765955dSGiuseppe CAVALLARO if (kstrtoint(opt + 10, 0, &eee_timer)) 3130d765955dSGiuseppe CAVALLARO goto err; 31314a7d666aSGiuseppe CAVALLARO } else if (!strncmp(opt, "chain_mode:", 11)) { 31324a7d666aSGiuseppe CAVALLARO if (kstrtoint(opt + 11, 0, &chain_mode)) 31334a7d666aSGiuseppe CAVALLARO goto err; 31347ac6653aSJeff Kirsher } 31357ac6653aSJeff Kirsher } 31367ac6653aSJeff Kirsher return 0; 31377ac6653aSJeff Kirsher 31387ac6653aSJeff Kirsher err: 31397ac6653aSJeff Kirsher pr_err("%s: ERROR broken module parameter conversion", __func__); 31407ac6653aSJeff Kirsher return -EINVAL; 31417ac6653aSJeff Kirsher } 31427ac6653aSJeff Kirsher 31437ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt); 3144ceb69499SGiuseppe CAVALLARO #endif /* MODULE */ 31456fc0d0f2SGiuseppe Cavallaro 31466fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver"); 31476fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); 31486fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL"); 3149