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> 555790cf3cSMathieu Olivari #include <linux/of_mdio.h> 5619d857c9SPhil Reid #include "dwmac1000.h" 577ac6653aSJeff Kirsher 587ac6653aSJeff Kirsher #define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x) 597ac6653aSJeff Kirsher 607ac6653aSJeff Kirsher /* Module parameters */ 6132ceabcaSGiuseppe CAVALLARO #define TX_TIMEO 5000 627ac6653aSJeff Kirsher static int watchdog = TX_TIMEO; 637ac6653aSJeff Kirsher module_param(watchdog, int, S_IRUGO | S_IWUSR); 6432ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(watchdog, "Transmit timeout in milliseconds (default 5s)"); 657ac6653aSJeff Kirsher 6632ceabcaSGiuseppe CAVALLARO static int debug = -1; 677ac6653aSJeff Kirsher module_param(debug, int, S_IRUGO | S_IWUSR); 6832ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)"); 697ac6653aSJeff Kirsher 7047d1f71fSstephen hemminger static int phyaddr = -1; 717ac6653aSJeff Kirsher module_param(phyaddr, int, S_IRUGO); 727ac6653aSJeff Kirsher MODULE_PARM_DESC(phyaddr, "Physical device address"); 737ac6653aSJeff Kirsher 74e3ad57c9SGiuseppe Cavallaro #define STMMAC_TX_THRESH (DMA_TX_SIZE / 4) 75120e87f9SGiuseppe Cavallaro #define STMMAC_RX_THRESH (DMA_RX_SIZE / 4) 767ac6653aSJeff Kirsher 777ac6653aSJeff Kirsher static int flow_ctrl = FLOW_OFF; 787ac6653aSJeff Kirsher module_param(flow_ctrl, int, S_IRUGO | S_IWUSR); 797ac6653aSJeff Kirsher MODULE_PARM_DESC(flow_ctrl, "Flow control ability [on/off]"); 807ac6653aSJeff Kirsher 817ac6653aSJeff Kirsher static int pause = PAUSE_TIME; 827ac6653aSJeff Kirsher module_param(pause, int, S_IRUGO | S_IWUSR); 837ac6653aSJeff Kirsher MODULE_PARM_DESC(pause, "Flow Control Pause Time"); 847ac6653aSJeff Kirsher 857ac6653aSJeff Kirsher #define TC_DEFAULT 64 867ac6653aSJeff Kirsher static int tc = TC_DEFAULT; 877ac6653aSJeff Kirsher module_param(tc, int, S_IRUGO | S_IWUSR); 887ac6653aSJeff Kirsher MODULE_PARM_DESC(tc, "DMA threshold control value"); 897ac6653aSJeff Kirsher 90d916701cSGiuseppe CAVALLARO #define DEFAULT_BUFSIZE 1536 91d916701cSGiuseppe CAVALLARO static int buf_sz = DEFAULT_BUFSIZE; 927ac6653aSJeff Kirsher module_param(buf_sz, int, S_IRUGO | S_IWUSR); 937ac6653aSJeff Kirsher MODULE_PARM_DESC(buf_sz, "DMA buffer size"); 947ac6653aSJeff Kirsher 9522ad3838SGiuseppe Cavallaro #define STMMAC_RX_COPYBREAK 256 9622ad3838SGiuseppe Cavallaro 977ac6653aSJeff Kirsher static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE | 987ac6653aSJeff Kirsher NETIF_MSG_LINK | NETIF_MSG_IFUP | 997ac6653aSJeff Kirsher NETIF_MSG_IFDOWN | NETIF_MSG_TIMER); 1007ac6653aSJeff Kirsher 101d765955dSGiuseppe CAVALLARO #define STMMAC_DEFAULT_LPI_TIMER 1000 102d765955dSGiuseppe CAVALLARO static int eee_timer = STMMAC_DEFAULT_LPI_TIMER; 103d765955dSGiuseppe CAVALLARO module_param(eee_timer, int, S_IRUGO | S_IWUSR); 104d765955dSGiuseppe CAVALLARO MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec"); 105f5351ef7SGiuseppe CAVALLARO #define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x)) 106d765955dSGiuseppe CAVALLARO 1074a7d666aSGiuseppe CAVALLARO /* By default the driver will use the ring mode to manage tx and rx descriptors 1084a7d666aSGiuseppe CAVALLARO * but passing this value so user can force to use the chain instead of the ring 1094a7d666aSGiuseppe CAVALLARO */ 1104a7d666aSGiuseppe CAVALLARO static unsigned int chain_mode; 1114a7d666aSGiuseppe CAVALLARO module_param(chain_mode, int, S_IRUGO); 1124a7d666aSGiuseppe CAVALLARO MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode"); 1134a7d666aSGiuseppe CAVALLARO 1147ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id); 1157ac6653aSJeff Kirsher 11650fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 117bfab27a1SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev); 118466c5ac8SMathieu Olivari static void stmmac_exit_fs(struct net_device *dev); 119bfab27a1SGiuseppe CAVALLARO #endif 120bfab27a1SGiuseppe CAVALLARO 1219125cdd1SGiuseppe CAVALLARO #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x)) 1229125cdd1SGiuseppe CAVALLARO 1237ac6653aSJeff Kirsher /** 1247ac6653aSJeff Kirsher * stmmac_verify_args - verify the driver parameters. 125732fdf0eSGiuseppe CAVALLARO * Description: it checks the driver parameters and set a default in case of 126732fdf0eSGiuseppe CAVALLARO * errors. 1277ac6653aSJeff Kirsher */ 1287ac6653aSJeff Kirsher static void stmmac_verify_args(void) 1297ac6653aSJeff Kirsher { 1307ac6653aSJeff Kirsher if (unlikely(watchdog < 0)) 1317ac6653aSJeff Kirsher watchdog = TX_TIMEO; 132d916701cSGiuseppe CAVALLARO if (unlikely((buf_sz < DEFAULT_BUFSIZE) || (buf_sz > BUF_SIZE_16KiB))) 133d916701cSGiuseppe CAVALLARO buf_sz = DEFAULT_BUFSIZE; 1347ac6653aSJeff Kirsher if (unlikely(flow_ctrl > 1)) 1357ac6653aSJeff Kirsher flow_ctrl = FLOW_AUTO; 1367ac6653aSJeff Kirsher else if (likely(flow_ctrl < 0)) 1377ac6653aSJeff Kirsher flow_ctrl = FLOW_OFF; 1387ac6653aSJeff Kirsher if (unlikely((pause < 0) || (pause > 0xffff))) 1397ac6653aSJeff Kirsher pause = PAUSE_TIME; 140d765955dSGiuseppe CAVALLARO if (eee_timer < 0) 141d765955dSGiuseppe CAVALLARO eee_timer = STMMAC_DEFAULT_LPI_TIMER; 1427ac6653aSJeff Kirsher } 1437ac6653aSJeff Kirsher 14432ceabcaSGiuseppe CAVALLARO /** 14532ceabcaSGiuseppe CAVALLARO * stmmac_clk_csr_set - dynamically set the MDC clock 14632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 14732ceabcaSGiuseppe CAVALLARO * Description: this is to dynamically set the MDC clock according to the csr 14832ceabcaSGiuseppe CAVALLARO * clock input. 14932ceabcaSGiuseppe CAVALLARO * Note: 15032ceabcaSGiuseppe CAVALLARO * If a specific clk_csr value is passed from the platform 15132ceabcaSGiuseppe CAVALLARO * this means that the CSR Clock Range selection cannot be 15232ceabcaSGiuseppe CAVALLARO * changed at run-time and it is fixed (as reported in the driver 15332ceabcaSGiuseppe CAVALLARO * documentation). Viceversa the driver will try to set the MDC 15432ceabcaSGiuseppe CAVALLARO * clock dynamically according to the actual clock input. 15532ceabcaSGiuseppe CAVALLARO */ 156cd7201f4SGiuseppe CAVALLARO static void stmmac_clk_csr_set(struct stmmac_priv *priv) 157cd7201f4SGiuseppe CAVALLARO { 158cd7201f4SGiuseppe CAVALLARO u32 clk_rate; 159cd7201f4SGiuseppe CAVALLARO 160cd7201f4SGiuseppe CAVALLARO clk_rate = clk_get_rate(priv->stmmac_clk); 161cd7201f4SGiuseppe CAVALLARO 162cd7201f4SGiuseppe CAVALLARO /* Platform provided default clk_csr would be assumed valid 163ceb69499SGiuseppe CAVALLARO * for all other cases except for the below mentioned ones. 164ceb69499SGiuseppe CAVALLARO * For values higher than the IEEE 802.3 specified frequency 165ceb69499SGiuseppe CAVALLARO * we can not estimate the proper divider as it is not known 166ceb69499SGiuseppe CAVALLARO * the frequency of clk_csr_i. So we do not change the default 167ceb69499SGiuseppe CAVALLARO * divider. 168ceb69499SGiuseppe CAVALLARO */ 169cd7201f4SGiuseppe CAVALLARO if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) { 170cd7201f4SGiuseppe CAVALLARO if (clk_rate < CSR_F_35M) 171cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_20_35M; 172cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M)) 173cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_35_60M; 174cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M)) 175cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_60_100M; 176cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M)) 177cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_100_150M; 178cd7201f4SGiuseppe CAVALLARO else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M)) 179cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_150_250M; 18019d857c9SPhil Reid else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M)) 181cd7201f4SGiuseppe CAVALLARO priv->clk_csr = STMMAC_CSR_250_300M; 182ceb69499SGiuseppe CAVALLARO } 183cd7201f4SGiuseppe CAVALLARO } 184cd7201f4SGiuseppe CAVALLARO 1857ac6653aSJeff Kirsher static void print_pkt(unsigned char *buf, int len) 1867ac6653aSJeff Kirsher { 187424c4f78SAndy Shevchenko pr_debug("len = %d byte, buf addr: 0x%p\n", len, buf); 188424c4f78SAndy Shevchenko print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); 1897ac6653aSJeff Kirsher } 1907ac6653aSJeff Kirsher 1917ac6653aSJeff Kirsher static inline u32 stmmac_tx_avail(struct stmmac_priv *priv) 1927ac6653aSJeff Kirsher { 193e3ad57c9SGiuseppe Cavallaro unsigned avail; 194e3ad57c9SGiuseppe Cavallaro 195e3ad57c9SGiuseppe Cavallaro if (priv->dirty_tx > priv->cur_tx) 196e3ad57c9SGiuseppe Cavallaro avail = priv->dirty_tx - priv->cur_tx - 1; 197e3ad57c9SGiuseppe Cavallaro else 198e3ad57c9SGiuseppe Cavallaro avail = DMA_TX_SIZE - priv->cur_tx + priv->dirty_tx - 1; 199e3ad57c9SGiuseppe Cavallaro 200e3ad57c9SGiuseppe Cavallaro return avail; 201e3ad57c9SGiuseppe Cavallaro } 202e3ad57c9SGiuseppe Cavallaro 203e3ad57c9SGiuseppe Cavallaro static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv) 204e3ad57c9SGiuseppe Cavallaro { 205e3ad57c9SGiuseppe Cavallaro unsigned dirty; 206e3ad57c9SGiuseppe Cavallaro 207e3ad57c9SGiuseppe Cavallaro if (priv->dirty_rx <= priv->cur_rx) 208e3ad57c9SGiuseppe Cavallaro dirty = priv->cur_rx - priv->dirty_rx; 209e3ad57c9SGiuseppe Cavallaro else 210e3ad57c9SGiuseppe Cavallaro dirty = DMA_RX_SIZE - priv->dirty_rx + priv->cur_rx; 211e3ad57c9SGiuseppe Cavallaro 212e3ad57c9SGiuseppe Cavallaro return dirty; 2137ac6653aSJeff Kirsher } 2147ac6653aSJeff Kirsher 21532ceabcaSGiuseppe CAVALLARO /** 216732fdf0eSGiuseppe CAVALLARO * stmmac_hw_fix_mac_speed - callback for speed selection 21732ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 21832ceabcaSGiuseppe CAVALLARO * Description: on some platforms (e.g. ST), some HW system configuraton 21932ceabcaSGiuseppe CAVALLARO * registers have to be set according to the link speed negotiated. 2207ac6653aSJeff Kirsher */ 2217ac6653aSJeff Kirsher static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv) 2227ac6653aSJeff Kirsher { 2237ac6653aSJeff Kirsher struct phy_device *phydev = priv->phydev; 2247ac6653aSJeff Kirsher 2257ac6653aSJeff Kirsher if (likely(priv->plat->fix_mac_speed)) 226ceb69499SGiuseppe CAVALLARO priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed); 2277ac6653aSJeff Kirsher } 2287ac6653aSJeff Kirsher 22932ceabcaSGiuseppe CAVALLARO /** 230732fdf0eSGiuseppe CAVALLARO * stmmac_enable_eee_mode - check and enter in LPI mode 23132ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 232732fdf0eSGiuseppe CAVALLARO * Description: this function is to verify and enter in LPI mode in case of 233732fdf0eSGiuseppe CAVALLARO * EEE. 23432ceabcaSGiuseppe CAVALLARO */ 235d765955dSGiuseppe CAVALLARO static void stmmac_enable_eee_mode(struct stmmac_priv *priv) 236d765955dSGiuseppe CAVALLARO { 237d765955dSGiuseppe CAVALLARO /* Check and enter in LPI mode */ 238d765955dSGiuseppe CAVALLARO if ((priv->dirty_tx == priv->cur_tx) && 239d765955dSGiuseppe CAVALLARO (priv->tx_path_in_lpi_mode == false)) 2407ed24bbeSVince Bridgers priv->hw->mac->set_eee_mode(priv->hw); 241d765955dSGiuseppe CAVALLARO } 242d765955dSGiuseppe CAVALLARO 24332ceabcaSGiuseppe CAVALLARO /** 244732fdf0eSGiuseppe CAVALLARO * stmmac_disable_eee_mode - disable and exit from LPI mode 24532ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 24632ceabcaSGiuseppe CAVALLARO * Description: this function is to exit and disable EEE in case of 24732ceabcaSGiuseppe CAVALLARO * LPI state is true. This is called by the xmit. 24832ceabcaSGiuseppe CAVALLARO */ 249d765955dSGiuseppe CAVALLARO void stmmac_disable_eee_mode(struct stmmac_priv *priv) 250d765955dSGiuseppe CAVALLARO { 2517ed24bbeSVince Bridgers priv->hw->mac->reset_eee_mode(priv->hw); 252d765955dSGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 253d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = false; 254d765955dSGiuseppe CAVALLARO } 255d765955dSGiuseppe CAVALLARO 256d765955dSGiuseppe CAVALLARO /** 257732fdf0eSGiuseppe CAVALLARO * stmmac_eee_ctrl_timer - EEE TX SW timer. 258d765955dSGiuseppe CAVALLARO * @arg : data hook 259d765955dSGiuseppe CAVALLARO * Description: 26032ceabcaSGiuseppe CAVALLARO * if there is no data transfer and if we are not in LPI state, 261d765955dSGiuseppe CAVALLARO * then MAC Transmitter can be moved to LPI state. 262d765955dSGiuseppe CAVALLARO */ 263d765955dSGiuseppe CAVALLARO static void stmmac_eee_ctrl_timer(unsigned long arg) 264d765955dSGiuseppe CAVALLARO { 265d765955dSGiuseppe CAVALLARO struct stmmac_priv *priv = (struct stmmac_priv *)arg; 266d765955dSGiuseppe CAVALLARO 267d765955dSGiuseppe CAVALLARO stmmac_enable_eee_mode(priv); 268f5351ef7SGiuseppe CAVALLARO mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); 269d765955dSGiuseppe CAVALLARO } 270d765955dSGiuseppe CAVALLARO 271d765955dSGiuseppe CAVALLARO /** 272732fdf0eSGiuseppe CAVALLARO * stmmac_eee_init - init EEE 27332ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 274d765955dSGiuseppe CAVALLARO * Description: 275732fdf0eSGiuseppe CAVALLARO * if the GMAC supports the EEE (from the HW cap reg) and the phy device 276732fdf0eSGiuseppe CAVALLARO * can also manage EEE, this function enable the LPI state and start related 277732fdf0eSGiuseppe CAVALLARO * timer. 278d765955dSGiuseppe CAVALLARO */ 279d765955dSGiuseppe CAVALLARO bool stmmac_eee_init(struct stmmac_priv *priv) 280d765955dSGiuseppe CAVALLARO { 2814741cf9cSGiuseppe CAVALLARO unsigned long flags; 282d765955dSGiuseppe CAVALLARO bool ret = false; 283d765955dSGiuseppe CAVALLARO 284f5351ef7SGiuseppe CAVALLARO /* Using PCS we cannot dial with the phy registers at this stage 285f5351ef7SGiuseppe CAVALLARO * so we do not support extra feature like EEE. 286f5351ef7SGiuseppe CAVALLARO */ 287f5351ef7SGiuseppe CAVALLARO if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) || 288f5351ef7SGiuseppe CAVALLARO (priv->pcs == STMMAC_PCS_RTBI)) 289f5351ef7SGiuseppe CAVALLARO goto out; 290f5351ef7SGiuseppe CAVALLARO 291d765955dSGiuseppe CAVALLARO /* MAC core supports the EEE feature. */ 292d765955dSGiuseppe CAVALLARO if (priv->dma_cap.eee) { 29383bf79b6SGiuseppe CAVALLARO int tx_lpi_timer = priv->tx_lpi_timer; 294d765955dSGiuseppe CAVALLARO 29583bf79b6SGiuseppe CAVALLARO /* Check if the PHY supports EEE */ 29683bf79b6SGiuseppe CAVALLARO if (phy_init_eee(priv->phydev, 1)) { 29783bf79b6SGiuseppe CAVALLARO /* To manage at run-time if the EEE cannot be supported 29883bf79b6SGiuseppe CAVALLARO * anymore (for example because the lp caps have been 29983bf79b6SGiuseppe CAVALLARO * changed). 30083bf79b6SGiuseppe CAVALLARO * In that case the driver disable own timers. 30183bf79b6SGiuseppe CAVALLARO */ 3024741cf9cSGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 30383bf79b6SGiuseppe CAVALLARO if (priv->eee_active) { 30483bf79b6SGiuseppe CAVALLARO pr_debug("stmmac: disable EEE\n"); 30583bf79b6SGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 3067ed24bbeSVince Bridgers priv->hw->mac->set_eee_timer(priv->hw, 0, 30783bf79b6SGiuseppe CAVALLARO tx_lpi_timer); 30883bf79b6SGiuseppe CAVALLARO } 30983bf79b6SGiuseppe CAVALLARO priv->eee_active = 0; 3104741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 31183bf79b6SGiuseppe CAVALLARO goto out; 31283bf79b6SGiuseppe CAVALLARO } 31383bf79b6SGiuseppe CAVALLARO /* Activate the EEE and start timers */ 3144741cf9cSGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 315f5351ef7SGiuseppe CAVALLARO if (!priv->eee_active) { 316d765955dSGiuseppe CAVALLARO priv->eee_active = 1; 317ccb36da1SVaishali Thakkar setup_timer(&priv->eee_ctrl_timer, 318ccb36da1SVaishali Thakkar stmmac_eee_ctrl_timer, 319ccb36da1SVaishali Thakkar (unsigned long)priv); 320ccb36da1SVaishali Thakkar mod_timer(&priv->eee_ctrl_timer, 321ccb36da1SVaishali Thakkar STMMAC_LPI_T(eee_timer)); 322d765955dSGiuseppe CAVALLARO 3237ed24bbeSVince Bridgers priv->hw->mac->set_eee_timer(priv->hw, 324f5351ef7SGiuseppe CAVALLARO STMMAC_DEFAULT_LIT_LS, 32583bf79b6SGiuseppe CAVALLARO tx_lpi_timer); 32671965352SGiuseppe CAVALLARO } 327f5351ef7SGiuseppe CAVALLARO /* Set HW EEE according to the speed */ 32871965352SGiuseppe CAVALLARO priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link); 329d765955dSGiuseppe CAVALLARO 330d765955dSGiuseppe CAVALLARO ret = true; 3314741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 3324741cf9cSGiuseppe CAVALLARO 3334741cf9cSGiuseppe CAVALLARO pr_debug("stmmac: Energy-Efficient Ethernet initialized\n"); 334d765955dSGiuseppe CAVALLARO } 335d765955dSGiuseppe CAVALLARO out: 336d765955dSGiuseppe CAVALLARO return ret; 337d765955dSGiuseppe CAVALLARO } 338d765955dSGiuseppe CAVALLARO 339732fdf0eSGiuseppe CAVALLARO /* stmmac_get_tx_hwtstamp - get HW TX timestamps 34032ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 341891434b1SRayagond Kokatanur * @entry : descriptor index to be used. 342891434b1SRayagond Kokatanur * @skb : the socket buffer 343891434b1SRayagond Kokatanur * Description : 344891434b1SRayagond Kokatanur * This function will read timestamp from the descriptor & pass it to stack. 345891434b1SRayagond Kokatanur * and also perform some sanity checks. 346891434b1SRayagond Kokatanur */ 347891434b1SRayagond Kokatanur static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv, 348ceb69499SGiuseppe CAVALLARO unsigned int entry, struct sk_buff *skb) 349891434b1SRayagond Kokatanur { 350891434b1SRayagond Kokatanur struct skb_shared_hwtstamps shhwtstamp; 351891434b1SRayagond Kokatanur u64 ns; 352891434b1SRayagond Kokatanur void *desc = NULL; 353891434b1SRayagond Kokatanur 354891434b1SRayagond Kokatanur if (!priv->hwts_tx_en) 355891434b1SRayagond Kokatanur return; 356891434b1SRayagond Kokatanur 357ceb69499SGiuseppe CAVALLARO /* exit if skb doesn't support hw tstamp */ 35875e4364fSdamuzi000 if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS))) 359891434b1SRayagond Kokatanur return; 360891434b1SRayagond Kokatanur 361891434b1SRayagond Kokatanur if (priv->adv_ts) 362891434b1SRayagond Kokatanur desc = (priv->dma_etx + entry); 363891434b1SRayagond Kokatanur else 364891434b1SRayagond Kokatanur desc = (priv->dma_tx + entry); 365891434b1SRayagond Kokatanur 366891434b1SRayagond Kokatanur /* check tx tstamp status */ 367891434b1SRayagond Kokatanur if (!priv->hw->desc->get_tx_timestamp_status((struct dma_desc *)desc)) 368891434b1SRayagond Kokatanur return; 369891434b1SRayagond Kokatanur 370891434b1SRayagond Kokatanur /* get the valid tstamp */ 371891434b1SRayagond Kokatanur ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts); 372891434b1SRayagond Kokatanur 373891434b1SRayagond Kokatanur memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); 374891434b1SRayagond Kokatanur shhwtstamp.hwtstamp = ns_to_ktime(ns); 375891434b1SRayagond Kokatanur /* pass tstamp to stack */ 376891434b1SRayagond Kokatanur skb_tstamp_tx(skb, &shhwtstamp); 377891434b1SRayagond Kokatanur 378891434b1SRayagond Kokatanur return; 379891434b1SRayagond Kokatanur } 380891434b1SRayagond Kokatanur 381732fdf0eSGiuseppe CAVALLARO /* stmmac_get_rx_hwtstamp - get HW RX timestamps 38232ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 383891434b1SRayagond Kokatanur * @entry : descriptor index to be used. 384891434b1SRayagond Kokatanur * @skb : the socket buffer 385891434b1SRayagond Kokatanur * Description : 386891434b1SRayagond Kokatanur * This function will read received packet's timestamp from the descriptor 387891434b1SRayagond Kokatanur * and pass it to stack. It also perform some sanity checks. 388891434b1SRayagond Kokatanur */ 389891434b1SRayagond Kokatanur static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, 390ceb69499SGiuseppe CAVALLARO unsigned int entry, struct sk_buff *skb) 391891434b1SRayagond Kokatanur { 392891434b1SRayagond Kokatanur struct skb_shared_hwtstamps *shhwtstamp = NULL; 393891434b1SRayagond Kokatanur u64 ns; 394891434b1SRayagond Kokatanur void *desc = NULL; 395891434b1SRayagond Kokatanur 396891434b1SRayagond Kokatanur if (!priv->hwts_rx_en) 397891434b1SRayagond Kokatanur return; 398891434b1SRayagond Kokatanur 399891434b1SRayagond Kokatanur if (priv->adv_ts) 400891434b1SRayagond Kokatanur desc = (priv->dma_erx + entry); 401891434b1SRayagond Kokatanur else 402891434b1SRayagond Kokatanur desc = (priv->dma_rx + entry); 403891434b1SRayagond Kokatanur 404ceb69499SGiuseppe CAVALLARO /* exit if rx tstamp is not valid */ 405891434b1SRayagond Kokatanur if (!priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts)) 406891434b1SRayagond Kokatanur return; 407891434b1SRayagond Kokatanur 408891434b1SRayagond Kokatanur /* get valid tstamp */ 409891434b1SRayagond Kokatanur ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts); 410891434b1SRayagond Kokatanur shhwtstamp = skb_hwtstamps(skb); 411891434b1SRayagond Kokatanur memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); 412891434b1SRayagond Kokatanur shhwtstamp->hwtstamp = ns_to_ktime(ns); 413891434b1SRayagond Kokatanur } 414891434b1SRayagond Kokatanur 415891434b1SRayagond Kokatanur /** 416891434b1SRayagond Kokatanur * stmmac_hwtstamp_ioctl - control hardware timestamping. 417891434b1SRayagond Kokatanur * @dev: device pointer. 418891434b1SRayagond Kokatanur * @ifr: An IOCTL specefic structure, that can contain a pointer to 419891434b1SRayagond Kokatanur * a proprietary structure used to pass information to the driver. 420891434b1SRayagond Kokatanur * Description: 421891434b1SRayagond Kokatanur * This function configures the MAC to enable/disable both outgoing(TX) 422891434b1SRayagond Kokatanur * and incoming(RX) packets time stamping based on user input. 423891434b1SRayagond Kokatanur * Return Value: 424891434b1SRayagond Kokatanur * 0 on success and an appropriate -ve integer on failure. 425891434b1SRayagond Kokatanur */ 426891434b1SRayagond Kokatanur static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr) 427891434b1SRayagond Kokatanur { 428891434b1SRayagond Kokatanur struct stmmac_priv *priv = netdev_priv(dev); 429891434b1SRayagond Kokatanur struct hwtstamp_config config; 4300a624155SArnd Bergmann struct timespec64 now; 431891434b1SRayagond Kokatanur u64 temp = 0; 432891434b1SRayagond Kokatanur u32 ptp_v2 = 0; 433891434b1SRayagond Kokatanur u32 tstamp_all = 0; 434891434b1SRayagond Kokatanur u32 ptp_over_ipv4_udp = 0; 435891434b1SRayagond Kokatanur u32 ptp_over_ipv6_udp = 0; 436891434b1SRayagond Kokatanur u32 ptp_over_ethernet = 0; 437891434b1SRayagond Kokatanur u32 snap_type_sel = 0; 438891434b1SRayagond Kokatanur u32 ts_master_en = 0; 439891434b1SRayagond Kokatanur u32 ts_event_en = 0; 440891434b1SRayagond Kokatanur u32 value = 0; 44119d857c9SPhil Reid u32 sec_inc; 442891434b1SRayagond Kokatanur 443891434b1SRayagond Kokatanur if (!(priv->dma_cap.time_stamp || priv->adv_ts)) { 444891434b1SRayagond Kokatanur netdev_alert(priv->dev, "No support for HW time stamping\n"); 445891434b1SRayagond Kokatanur priv->hwts_tx_en = 0; 446891434b1SRayagond Kokatanur priv->hwts_rx_en = 0; 447891434b1SRayagond Kokatanur 448891434b1SRayagond Kokatanur return -EOPNOTSUPP; 449891434b1SRayagond Kokatanur } 450891434b1SRayagond Kokatanur 451891434b1SRayagond Kokatanur if (copy_from_user(&config, ifr->ifr_data, 452891434b1SRayagond Kokatanur sizeof(struct hwtstamp_config))) 453891434b1SRayagond Kokatanur return -EFAULT; 454891434b1SRayagond Kokatanur 455891434b1SRayagond Kokatanur pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n", 456891434b1SRayagond Kokatanur __func__, config.flags, config.tx_type, config.rx_filter); 457891434b1SRayagond Kokatanur 458891434b1SRayagond Kokatanur /* reserved for future extensions */ 459891434b1SRayagond Kokatanur if (config.flags) 460891434b1SRayagond Kokatanur return -EINVAL; 461891434b1SRayagond Kokatanur 4625f3da328SBen Hutchings if (config.tx_type != HWTSTAMP_TX_OFF && 4635f3da328SBen Hutchings config.tx_type != HWTSTAMP_TX_ON) 464891434b1SRayagond Kokatanur return -ERANGE; 465891434b1SRayagond Kokatanur 466891434b1SRayagond Kokatanur if (priv->adv_ts) { 467891434b1SRayagond Kokatanur switch (config.rx_filter) { 468891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_NONE: 469ceb69499SGiuseppe CAVALLARO /* time stamp no incoming packet at all */ 470891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_NONE; 471891434b1SRayagond Kokatanur break; 472891434b1SRayagond Kokatanur 473891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 474ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, any kind of event packet */ 475891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 476891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 477891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 478891434b1SRayagond Kokatanur 479891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 480891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 481891434b1SRayagond Kokatanur break; 482891434b1SRayagond Kokatanur 483891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 484ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, Sync packet */ 485891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC; 486891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 487891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 488891434b1SRayagond Kokatanur 489891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 490891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 491891434b1SRayagond Kokatanur break; 492891434b1SRayagond Kokatanur 493891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 494ceb69499SGiuseppe CAVALLARO /* PTP v1, UDP, Delay_req packet */ 495891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ; 496891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 497891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 498891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 499891434b1SRayagond Kokatanur 500891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 501891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 502891434b1SRayagond Kokatanur break; 503891434b1SRayagond Kokatanur 504891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 505ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, any kind of event packet */ 506891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; 507891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 508891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 509891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 510891434b1SRayagond Kokatanur 511891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 512891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 513891434b1SRayagond Kokatanur break; 514891434b1SRayagond Kokatanur 515891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 516ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, Sync packet */ 517891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC; 518891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 519891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 520891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 521891434b1SRayagond Kokatanur 522891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 523891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 524891434b1SRayagond Kokatanur break; 525891434b1SRayagond Kokatanur 526891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 527ceb69499SGiuseppe CAVALLARO /* PTP v2, UDP, Delay_req packet */ 528891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ; 529891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 530891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 531891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 532891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 533891434b1SRayagond Kokatanur 534891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 535891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 536891434b1SRayagond Kokatanur break; 537891434b1SRayagond Kokatanur 538891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_EVENT: 539ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1 any layer, any kind of event packet */ 540891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; 541891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 542891434b1SRayagond Kokatanur /* take time stamp for all event messages */ 543891434b1SRayagond Kokatanur snap_type_sel = PTP_TCR_SNAPTYPSEL_1; 544891434b1SRayagond Kokatanur 545891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 546891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 547891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 548891434b1SRayagond Kokatanur break; 549891434b1SRayagond Kokatanur 550891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_SYNC: 551ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1, any layer, Sync packet */ 552891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC; 553891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 554891434b1SRayagond Kokatanur /* take time stamp for SYNC messages only */ 555891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 556891434b1SRayagond Kokatanur 557891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 558891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 559891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 560891434b1SRayagond Kokatanur break; 561891434b1SRayagond Kokatanur 562891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 563ceb69499SGiuseppe CAVALLARO /* PTP v2/802.AS1, any layer, Delay_req packet */ 564891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ; 565891434b1SRayagond Kokatanur ptp_v2 = PTP_TCR_TSVER2ENA; 566891434b1SRayagond Kokatanur /* take time stamp for Delay_Req messages only */ 567891434b1SRayagond Kokatanur ts_master_en = PTP_TCR_TSMSTRENA; 568891434b1SRayagond Kokatanur ts_event_en = PTP_TCR_TSEVNTENA; 569891434b1SRayagond Kokatanur 570891434b1SRayagond Kokatanur ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA; 571891434b1SRayagond Kokatanur ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA; 572891434b1SRayagond Kokatanur ptp_over_ethernet = PTP_TCR_TSIPENA; 573891434b1SRayagond Kokatanur break; 574891434b1SRayagond Kokatanur 575891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_ALL: 576ceb69499SGiuseppe CAVALLARO /* time stamp any incoming packet */ 577891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_ALL; 578891434b1SRayagond Kokatanur tstamp_all = PTP_TCR_TSENALL; 579891434b1SRayagond Kokatanur break; 580891434b1SRayagond Kokatanur 581891434b1SRayagond Kokatanur default: 582891434b1SRayagond Kokatanur return -ERANGE; 583891434b1SRayagond Kokatanur } 584891434b1SRayagond Kokatanur } else { 585891434b1SRayagond Kokatanur switch (config.rx_filter) { 586891434b1SRayagond Kokatanur case HWTSTAMP_FILTER_NONE: 587891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_NONE; 588891434b1SRayagond Kokatanur break; 589891434b1SRayagond Kokatanur default: 590891434b1SRayagond Kokatanur /* PTP v1, UDP, any kind of event packet */ 591891434b1SRayagond Kokatanur config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; 592891434b1SRayagond Kokatanur break; 593891434b1SRayagond Kokatanur } 594891434b1SRayagond Kokatanur } 595891434b1SRayagond Kokatanur priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1); 5965f3da328SBen Hutchings priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON; 597891434b1SRayagond Kokatanur 598891434b1SRayagond Kokatanur if (!priv->hwts_tx_en && !priv->hwts_rx_en) 599891434b1SRayagond Kokatanur priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0); 600891434b1SRayagond Kokatanur else { 601891434b1SRayagond Kokatanur value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR | 602891434b1SRayagond Kokatanur tstamp_all | ptp_v2 | ptp_over_ethernet | 603891434b1SRayagond Kokatanur ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en | 604891434b1SRayagond Kokatanur ts_master_en | snap_type_sel); 605891434b1SRayagond Kokatanur priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value); 606891434b1SRayagond Kokatanur 607891434b1SRayagond Kokatanur /* program Sub Second Increment reg */ 60819d857c9SPhil Reid sec_inc = priv->hw->ptp->config_sub_second_increment( 60919d857c9SPhil Reid priv->ioaddr, priv->clk_ptp_rate); 61019d857c9SPhil Reid temp = div_u64(1000000000ULL, sec_inc); 611891434b1SRayagond Kokatanur 612891434b1SRayagond Kokatanur /* calculate default added value: 613891434b1SRayagond Kokatanur * formula is : 614891434b1SRayagond Kokatanur * addend = (2^32)/freq_div_ratio; 61519d857c9SPhil Reid * where, freq_div_ratio = 1e9ns/sec_inc 616891434b1SRayagond Kokatanur */ 61719d857c9SPhil Reid temp = (u64)(temp << 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 */ 6230a624155SArnd Bergmann ktime_get_real_ts64(&now); 6240a624155SArnd Bergmann 6250a624155SArnd Bergmann /* lower 32 bits of tv_sec are safe until y2106 */ 6260a624155SArnd Bergmann priv->hw->ptp->init_systime(priv->ioaddr, (u32)now.tv_sec, 627891434b1SRayagond Kokatanur now.tv_nsec); 628891434b1SRayagond Kokatanur } 629891434b1SRayagond Kokatanur 630891434b1SRayagond Kokatanur return copy_to_user(ifr->ifr_data, &config, 631891434b1SRayagond Kokatanur sizeof(struct hwtstamp_config)) ? -EFAULT : 0; 632891434b1SRayagond Kokatanur } 633891434b1SRayagond Kokatanur 63432ceabcaSGiuseppe CAVALLARO /** 635732fdf0eSGiuseppe CAVALLARO * stmmac_init_ptp - init PTP 63632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 637732fdf0eSGiuseppe CAVALLARO * Description: this is to verify if the HW supports the PTPv1 or PTPv2. 63832ceabcaSGiuseppe CAVALLARO * This is done by looking at the HW cap. register. 639732fdf0eSGiuseppe CAVALLARO * This function also registers the ptp driver. 64032ceabcaSGiuseppe CAVALLARO */ 64192ba6888SRayagond Kokatanur static int stmmac_init_ptp(struct stmmac_priv *priv) 642891434b1SRayagond Kokatanur { 64392ba6888SRayagond Kokatanur if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp)) 64492ba6888SRayagond Kokatanur return -EOPNOTSUPP; 64592ba6888SRayagond Kokatanur 6465566401fSGiuseppe CAVALLARO /* Fall-back to main clock in case of no PTP ref is passed */ 6475566401fSGiuseppe CAVALLARO priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref"); 6485566401fSGiuseppe CAVALLARO if (IS_ERR(priv->clk_ptp_ref)) { 6495566401fSGiuseppe CAVALLARO priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk); 6505566401fSGiuseppe CAVALLARO priv->clk_ptp_ref = NULL; 6515566401fSGiuseppe CAVALLARO } else { 6525566401fSGiuseppe CAVALLARO clk_prepare_enable(priv->clk_ptp_ref); 6535566401fSGiuseppe CAVALLARO priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref); 6545566401fSGiuseppe CAVALLARO } 6555566401fSGiuseppe CAVALLARO 656891434b1SRayagond Kokatanur priv->adv_ts = 0; 6577cd01399SVince Bridgers if (priv->dma_cap.atime_stamp && priv->extend_desc) 658891434b1SRayagond Kokatanur priv->adv_ts = 1; 6597cd01399SVince Bridgers 6607cd01399SVince Bridgers if (netif_msg_hw(priv) && priv->dma_cap.time_stamp) 6617cd01399SVince Bridgers pr_debug("IEEE 1588-2002 Time Stamp supported\n"); 6627cd01399SVince Bridgers 6637cd01399SVince Bridgers if (netif_msg_hw(priv) && priv->adv_ts) 6647cd01399SVince Bridgers pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n"); 665891434b1SRayagond Kokatanur 666891434b1SRayagond Kokatanur priv->hw->ptp = &stmmac_ptp; 667891434b1SRayagond Kokatanur priv->hwts_tx_en = 0; 668891434b1SRayagond Kokatanur priv->hwts_rx_en = 0; 66992ba6888SRayagond Kokatanur 67092ba6888SRayagond Kokatanur return stmmac_ptp_register(priv); 67192ba6888SRayagond Kokatanur } 67292ba6888SRayagond Kokatanur 67392ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv) 67492ba6888SRayagond Kokatanur { 6755566401fSGiuseppe CAVALLARO if (priv->clk_ptp_ref) 6765566401fSGiuseppe CAVALLARO clk_disable_unprepare(priv->clk_ptp_ref); 67792ba6888SRayagond Kokatanur stmmac_ptp_unregister(priv); 678891434b1SRayagond Kokatanur } 679891434b1SRayagond Kokatanur 6807ac6653aSJeff Kirsher /** 681732fdf0eSGiuseppe CAVALLARO * stmmac_adjust_link - adjusts the link parameters 6827ac6653aSJeff Kirsher * @dev: net device structure 683732fdf0eSGiuseppe CAVALLARO * Description: this is the helper called by the physical abstraction layer 684732fdf0eSGiuseppe CAVALLARO * drivers to communicate the phy link status. According the speed and duplex 685732fdf0eSGiuseppe CAVALLARO * this driver can invoke registered glue-logic as well. 686732fdf0eSGiuseppe CAVALLARO * It also invoke the eee initialization because it could happen when switch 687732fdf0eSGiuseppe CAVALLARO * on different networks (that are eee capable). 6887ac6653aSJeff Kirsher */ 6897ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev) 6907ac6653aSJeff Kirsher { 6917ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 6927ac6653aSJeff Kirsher struct phy_device *phydev = priv->phydev; 6937ac6653aSJeff Kirsher unsigned long flags; 6947ac6653aSJeff Kirsher int new_state = 0; 6957ac6653aSJeff Kirsher unsigned int fc = priv->flow_ctrl, pause_time = priv->pause; 6967ac6653aSJeff Kirsher 6977ac6653aSJeff Kirsher if (phydev == NULL) 6987ac6653aSJeff Kirsher return; 6997ac6653aSJeff Kirsher 7007ac6653aSJeff Kirsher spin_lock_irqsave(&priv->lock, flags); 701d765955dSGiuseppe CAVALLARO 7027ac6653aSJeff Kirsher if (phydev->link) { 7037ac6653aSJeff Kirsher u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG); 7047ac6653aSJeff Kirsher 7057ac6653aSJeff Kirsher /* Now we make sure that we can be in full duplex mode. 7067ac6653aSJeff Kirsher * If not, we operate in half-duplex mode. */ 7077ac6653aSJeff Kirsher if (phydev->duplex != priv->oldduplex) { 7087ac6653aSJeff Kirsher new_state = 1; 7097ac6653aSJeff Kirsher if (!(phydev->duplex)) 7107ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.duplex; 7117ac6653aSJeff Kirsher else 7127ac6653aSJeff Kirsher ctrl |= priv->hw->link.duplex; 7137ac6653aSJeff Kirsher priv->oldduplex = phydev->duplex; 7147ac6653aSJeff Kirsher } 7157ac6653aSJeff Kirsher /* Flow Control operation */ 7167ac6653aSJeff Kirsher if (phydev->pause) 7177ed24bbeSVince Bridgers priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex, 7187ac6653aSJeff Kirsher fc, pause_time); 7197ac6653aSJeff Kirsher 7207ac6653aSJeff Kirsher if (phydev->speed != priv->speed) { 7217ac6653aSJeff Kirsher new_state = 1; 7227ac6653aSJeff Kirsher switch (phydev->speed) { 7237ac6653aSJeff Kirsher case 1000: 7247ac6653aSJeff Kirsher if (likely(priv->plat->has_gmac)) 7257ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.port; 7267ac6653aSJeff Kirsher stmmac_hw_fix_mac_speed(priv); 7277ac6653aSJeff Kirsher break; 7287ac6653aSJeff Kirsher case 100: 7297ac6653aSJeff Kirsher case 10: 7307ac6653aSJeff Kirsher if (priv->plat->has_gmac) { 7317ac6653aSJeff Kirsher ctrl |= priv->hw->link.port; 7327ac6653aSJeff Kirsher if (phydev->speed == SPEED_100) { 7337ac6653aSJeff Kirsher ctrl |= priv->hw->link.speed; 7347ac6653aSJeff Kirsher } else { 7357ac6653aSJeff Kirsher ctrl &= ~(priv->hw->link.speed); 7367ac6653aSJeff Kirsher } 7377ac6653aSJeff Kirsher } else { 7387ac6653aSJeff Kirsher ctrl &= ~priv->hw->link.port; 7397ac6653aSJeff Kirsher } 7407ac6653aSJeff Kirsher stmmac_hw_fix_mac_speed(priv); 7417ac6653aSJeff Kirsher break; 7427ac6653aSJeff Kirsher default: 7437ac6653aSJeff Kirsher if (netif_msg_link(priv)) 744ceb69499SGiuseppe CAVALLARO pr_warn("%s: Speed (%d) not 10/100\n", 745ceb69499SGiuseppe CAVALLARO dev->name, phydev->speed); 7467ac6653aSJeff Kirsher break; 7477ac6653aSJeff Kirsher } 7487ac6653aSJeff Kirsher 7497ac6653aSJeff Kirsher priv->speed = phydev->speed; 7507ac6653aSJeff Kirsher } 7517ac6653aSJeff Kirsher 7527ac6653aSJeff Kirsher writel(ctrl, priv->ioaddr + MAC_CTRL_REG); 7537ac6653aSJeff Kirsher 7547ac6653aSJeff Kirsher if (!priv->oldlink) { 7557ac6653aSJeff Kirsher new_state = 1; 7567ac6653aSJeff Kirsher priv->oldlink = 1; 7577ac6653aSJeff Kirsher } 7587ac6653aSJeff Kirsher } else if (priv->oldlink) { 7597ac6653aSJeff Kirsher new_state = 1; 7607ac6653aSJeff Kirsher priv->oldlink = 0; 7617ac6653aSJeff Kirsher priv->speed = 0; 7627ac6653aSJeff Kirsher priv->oldduplex = -1; 7637ac6653aSJeff Kirsher } 7647ac6653aSJeff Kirsher 7657ac6653aSJeff Kirsher if (new_state && netif_msg_link(priv)) 7667ac6653aSJeff Kirsher phy_print_status(phydev); 7677ac6653aSJeff Kirsher 7684741cf9cSGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 7694741cf9cSGiuseppe CAVALLARO 77052f95bbfSGiuseppe CAVALLARO if (phydev->is_pseudo_fixed_link) 77152f95bbfSGiuseppe CAVALLARO /* Stop PHY layer to call the hook to adjust the link in case 77252f95bbfSGiuseppe CAVALLARO * of a switch is attached to the stmmac driver. 77352f95bbfSGiuseppe CAVALLARO */ 77452f95bbfSGiuseppe CAVALLARO phydev->irq = PHY_IGNORE_INTERRUPT; 77552f95bbfSGiuseppe CAVALLARO else 77652f95bbfSGiuseppe CAVALLARO /* At this stage, init the EEE if supported. 77752f95bbfSGiuseppe CAVALLARO * Never called in case of fixed_link. 778f5351ef7SGiuseppe CAVALLARO */ 779f5351ef7SGiuseppe CAVALLARO priv->eee_enabled = stmmac_eee_init(priv); 7807ac6653aSJeff Kirsher } 7817ac6653aSJeff Kirsher 78232ceabcaSGiuseppe CAVALLARO /** 783732fdf0eSGiuseppe CAVALLARO * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported 78432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 78532ceabcaSGiuseppe CAVALLARO * Description: this is to verify if the HW supports the PCS. 78632ceabcaSGiuseppe CAVALLARO * Physical Coding Sublayer (PCS) interface that can be used when the MAC is 78732ceabcaSGiuseppe CAVALLARO * configured for the TBI, RTBI, or SGMII PHY interface. 78832ceabcaSGiuseppe CAVALLARO */ 789e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv) 790e58bb43fSGiuseppe CAVALLARO { 791e58bb43fSGiuseppe CAVALLARO int interface = priv->plat->interface; 792e58bb43fSGiuseppe CAVALLARO 793e58bb43fSGiuseppe CAVALLARO if (priv->dma_cap.pcs) { 7940d909dcdSByungho An if ((interface == PHY_INTERFACE_MODE_RGMII) || 7950d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_ID) || 7960d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_RXID) || 7970d909dcdSByungho An (interface == PHY_INTERFACE_MODE_RGMII_TXID)) { 798e58bb43fSGiuseppe CAVALLARO pr_debug("STMMAC: PCS RGMII support enable\n"); 799e58bb43fSGiuseppe CAVALLARO priv->pcs = STMMAC_PCS_RGMII; 8000d909dcdSByungho An } else if (interface == PHY_INTERFACE_MODE_SGMII) { 801e58bb43fSGiuseppe CAVALLARO pr_debug("STMMAC: PCS SGMII support enable\n"); 802e58bb43fSGiuseppe CAVALLARO priv->pcs = STMMAC_PCS_SGMII; 803e58bb43fSGiuseppe CAVALLARO } 804e58bb43fSGiuseppe CAVALLARO } 805e58bb43fSGiuseppe CAVALLARO } 806e58bb43fSGiuseppe CAVALLARO 8077ac6653aSJeff Kirsher /** 8087ac6653aSJeff Kirsher * stmmac_init_phy - PHY initialization 8097ac6653aSJeff Kirsher * @dev: net device structure 8107ac6653aSJeff Kirsher * Description: it initializes the driver's PHY state, and attaches the PHY 8117ac6653aSJeff Kirsher * to the mac driver. 8127ac6653aSJeff Kirsher * Return value: 8137ac6653aSJeff Kirsher * 0 on success 8147ac6653aSJeff Kirsher */ 8157ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev) 8167ac6653aSJeff Kirsher { 8177ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 8187ac6653aSJeff Kirsher struct phy_device *phydev; 819d765955dSGiuseppe CAVALLARO char phy_id_fmt[MII_BUS_ID_SIZE + 3]; 8207ac6653aSJeff Kirsher char bus_id[MII_BUS_ID_SIZE]; 82179ee1dc3SSrinivas Kandagatla int interface = priv->plat->interface; 8229cbadf09SSrinivas Kandagatla int max_speed = priv->plat->max_speed; 8237ac6653aSJeff Kirsher priv->oldlink = 0; 8247ac6653aSJeff Kirsher priv->speed = 0; 8257ac6653aSJeff Kirsher priv->oldduplex = -1; 8267ac6653aSJeff Kirsher 8275790cf3cSMathieu Olivari if (priv->plat->phy_node) { 8285790cf3cSMathieu Olivari phydev = of_phy_connect(dev, priv->plat->phy_node, 8295790cf3cSMathieu Olivari &stmmac_adjust_link, 0, interface); 8305790cf3cSMathieu Olivari } else { 831f142af2eSSrinivas Kandagatla snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", 832f142af2eSSrinivas Kandagatla priv->plat->bus_id); 833f142af2eSSrinivas Kandagatla 834d765955dSGiuseppe CAVALLARO snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, 8357ac6653aSJeff Kirsher priv->plat->phy_addr); 8365790cf3cSMathieu Olivari pr_debug("stmmac_init_phy: trying to attach to %s\n", 8375790cf3cSMathieu Olivari phy_id_fmt); 8387ac6653aSJeff Kirsher 8395790cf3cSMathieu Olivari phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, 8405790cf3cSMathieu Olivari interface); 8415790cf3cSMathieu Olivari } 8427ac6653aSJeff Kirsher 843dfc50fcaSAlexey Brodkin if (IS_ERR_OR_NULL(phydev)) { 8447ac6653aSJeff Kirsher pr_err("%s: Could not attach to PHY\n", dev->name); 845dfc50fcaSAlexey Brodkin if (!phydev) 846dfc50fcaSAlexey Brodkin return -ENODEV; 847dfc50fcaSAlexey Brodkin 8487ac6653aSJeff Kirsher return PTR_ERR(phydev); 8497ac6653aSJeff Kirsher } 8507ac6653aSJeff Kirsher 85179ee1dc3SSrinivas Kandagatla /* Stop Advertising 1000BASE Capability if interface is not GMII */ 852c5b9b4e4SSrinivas Kandagatla if ((interface == PHY_INTERFACE_MODE_MII) || 8539cbadf09SSrinivas Kandagatla (interface == PHY_INTERFACE_MODE_RMII) || 8549cbadf09SSrinivas Kandagatla (max_speed < 1000 && max_speed > 0)) 855c5b9b4e4SSrinivas Kandagatla phydev->advertising &= ~(SUPPORTED_1000baseT_Half | 856c5b9b4e4SSrinivas Kandagatla SUPPORTED_1000baseT_Full); 85779ee1dc3SSrinivas Kandagatla 8587ac6653aSJeff Kirsher /* 8597ac6653aSJeff Kirsher * Broken HW is sometimes missing the pull-up resistor on the 8607ac6653aSJeff Kirsher * MDIO line, which results in reads to non-existent devices returning 8617ac6653aSJeff Kirsher * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent 8627ac6653aSJeff Kirsher * device as well. 8637ac6653aSJeff Kirsher * Note: phydev->phy_id is the result of reading the UID PHY registers. 8647ac6653aSJeff Kirsher */ 86527732381SMathieu Olivari if (!priv->plat->phy_node && phydev->phy_id == 0) { 8667ac6653aSJeff Kirsher phy_disconnect(phydev); 8677ac6653aSJeff Kirsher return -ENODEV; 8687ac6653aSJeff Kirsher } 8698e99fc5fSGiuseppe Cavallaro 8707ac6653aSJeff Kirsher pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)" 8717ac6653aSJeff Kirsher " Link = %d\n", dev->name, phydev->phy_id, phydev->link); 8727ac6653aSJeff Kirsher 8737ac6653aSJeff Kirsher priv->phydev = phydev; 8747ac6653aSJeff Kirsher 8757ac6653aSJeff Kirsher return 0; 8767ac6653aSJeff Kirsher } 8777ac6653aSJeff Kirsher 8787ac6653aSJeff Kirsher /** 879732fdf0eSGiuseppe CAVALLARO * stmmac_display_ring - display ring 88032ceabcaSGiuseppe CAVALLARO * @head: pointer to the head of the ring passed. 8817ac6653aSJeff Kirsher * @size: size of the ring. 88232ceabcaSGiuseppe CAVALLARO * @extend_desc: to verify if extended descriptors are used. 883c24602efSGiuseppe CAVALLARO * Description: display the control/status and buffer descriptors. 8847ac6653aSJeff Kirsher */ 885c24602efSGiuseppe CAVALLARO static void stmmac_display_ring(void *head, int size, int extend_desc) 8867ac6653aSJeff Kirsher { 8877ac6653aSJeff Kirsher int i; 888c24602efSGiuseppe CAVALLARO struct dma_extended_desc *ep = (struct dma_extended_desc *)head; 889c24602efSGiuseppe CAVALLARO struct dma_desc *p = (struct dma_desc *)head; 890c24602efSGiuseppe CAVALLARO 8917ac6653aSJeff Kirsher for (i = 0; i < size; i++) { 892c24602efSGiuseppe CAVALLARO u64 x; 893c24602efSGiuseppe CAVALLARO if (extend_desc) { 894c24602efSGiuseppe CAVALLARO x = *(u64 *) ep; 895c24602efSGiuseppe CAVALLARO pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 896c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 897c24602efSGiuseppe CAVALLARO (unsigned int)x, (unsigned int)(x >> 32), 898c24602efSGiuseppe CAVALLARO ep->basic.des2, ep->basic.des3); 899c24602efSGiuseppe CAVALLARO ep++; 900c24602efSGiuseppe CAVALLARO } else { 901c24602efSGiuseppe CAVALLARO x = *(u64 *) p; 902c24602efSGiuseppe CAVALLARO pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x", 903c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(p), 904c24602efSGiuseppe CAVALLARO (unsigned int)x, (unsigned int)(x >> 32), 905c24602efSGiuseppe CAVALLARO p->des2, p->des3); 906c24602efSGiuseppe CAVALLARO p++; 907c24602efSGiuseppe CAVALLARO } 9087ac6653aSJeff Kirsher pr_info("\n"); 9097ac6653aSJeff Kirsher } 9107ac6653aSJeff Kirsher } 9117ac6653aSJeff Kirsher 912c24602efSGiuseppe CAVALLARO static void stmmac_display_rings(struct stmmac_priv *priv) 913c24602efSGiuseppe CAVALLARO { 914c24602efSGiuseppe CAVALLARO if (priv->extend_desc) { 915c24602efSGiuseppe CAVALLARO pr_info("Extended RX descriptor ring:\n"); 916e3ad57c9SGiuseppe Cavallaro stmmac_display_ring((void *)priv->dma_erx, DMA_RX_SIZE, 1); 917c24602efSGiuseppe CAVALLARO pr_info("Extended TX descriptor ring:\n"); 918e3ad57c9SGiuseppe Cavallaro stmmac_display_ring((void *)priv->dma_etx, DMA_TX_SIZE, 1); 919c24602efSGiuseppe CAVALLARO } else { 920c24602efSGiuseppe CAVALLARO pr_info("RX descriptor ring:\n"); 921e3ad57c9SGiuseppe Cavallaro stmmac_display_ring((void *)priv->dma_rx, DMA_RX_SIZE, 0); 922c24602efSGiuseppe CAVALLARO pr_info("TX descriptor ring:\n"); 923e3ad57c9SGiuseppe Cavallaro stmmac_display_ring((void *)priv->dma_tx, DMA_TX_SIZE, 0); 924c24602efSGiuseppe CAVALLARO } 925c24602efSGiuseppe CAVALLARO } 926c24602efSGiuseppe CAVALLARO 927286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize) 928286a8372SGiuseppe CAVALLARO { 929286a8372SGiuseppe CAVALLARO int ret = bufsize; 930286a8372SGiuseppe CAVALLARO 931286a8372SGiuseppe CAVALLARO if (mtu >= BUF_SIZE_4KiB) 932286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_8KiB; 933286a8372SGiuseppe CAVALLARO else if (mtu >= BUF_SIZE_2KiB) 934286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_4KiB; 935d916701cSGiuseppe CAVALLARO else if (mtu > DEFAULT_BUFSIZE) 936286a8372SGiuseppe CAVALLARO ret = BUF_SIZE_2KiB; 937286a8372SGiuseppe CAVALLARO else 938d916701cSGiuseppe CAVALLARO ret = DEFAULT_BUFSIZE; 939286a8372SGiuseppe CAVALLARO 940286a8372SGiuseppe CAVALLARO return ret; 941286a8372SGiuseppe CAVALLARO } 942286a8372SGiuseppe CAVALLARO 94332ceabcaSGiuseppe CAVALLARO /** 944732fdf0eSGiuseppe CAVALLARO * stmmac_clear_descriptors - clear descriptors 94532ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 94632ceabcaSGiuseppe CAVALLARO * Description: this function is called to clear the tx and rx descriptors 94732ceabcaSGiuseppe CAVALLARO * in case of both basic and extended descriptors are used. 94832ceabcaSGiuseppe CAVALLARO */ 949c24602efSGiuseppe CAVALLARO static void stmmac_clear_descriptors(struct stmmac_priv *priv) 950c24602efSGiuseppe CAVALLARO { 951c24602efSGiuseppe CAVALLARO int i; 952c24602efSGiuseppe CAVALLARO 953c24602efSGiuseppe CAVALLARO /* Clear the Rx/Tx descriptors */ 954e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_RX_SIZE; i++) 955c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 956c24602efSGiuseppe CAVALLARO priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic, 957c24602efSGiuseppe CAVALLARO priv->use_riwt, priv->mode, 958e3ad57c9SGiuseppe Cavallaro (i == DMA_RX_SIZE - 1)); 959c24602efSGiuseppe CAVALLARO else 960c24602efSGiuseppe CAVALLARO priv->hw->desc->init_rx_desc(&priv->dma_rx[i], 961c24602efSGiuseppe CAVALLARO priv->use_riwt, priv->mode, 962e3ad57c9SGiuseppe Cavallaro (i == DMA_RX_SIZE - 1)); 963e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_TX_SIZE; i++) 964c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 965c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic, 966c24602efSGiuseppe CAVALLARO priv->mode, 967e3ad57c9SGiuseppe Cavallaro (i == DMA_TX_SIZE - 1)); 968c24602efSGiuseppe CAVALLARO else 969c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_tx[i], 970c24602efSGiuseppe CAVALLARO priv->mode, 971e3ad57c9SGiuseppe Cavallaro (i == DMA_TX_SIZE - 1)); 972c24602efSGiuseppe CAVALLARO } 973c24602efSGiuseppe CAVALLARO 974732fdf0eSGiuseppe CAVALLARO /** 975732fdf0eSGiuseppe CAVALLARO * stmmac_init_rx_buffers - init the RX descriptor buffer. 976732fdf0eSGiuseppe CAVALLARO * @priv: driver private structure 977732fdf0eSGiuseppe CAVALLARO * @p: descriptor pointer 978732fdf0eSGiuseppe CAVALLARO * @i: descriptor index 979732fdf0eSGiuseppe CAVALLARO * @flags: gfp flag. 980732fdf0eSGiuseppe CAVALLARO * Description: this function is called to allocate a receive buffer, perform 981732fdf0eSGiuseppe CAVALLARO * the DMA mapping and init the descriptor. 982732fdf0eSGiuseppe CAVALLARO */ 983c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p, 984777da230SGiuseppe CAVALLARO int i, gfp_t flags) 985c24602efSGiuseppe CAVALLARO { 986c24602efSGiuseppe CAVALLARO struct sk_buff *skb; 987c24602efSGiuseppe CAVALLARO 9884ec49a37SVineet Gupta skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags); 98956329137SBartlomiej Zolnierkiewicz if (!skb) { 990c24602efSGiuseppe CAVALLARO pr_err("%s: Rx init fails; skb is NULL\n", __func__); 99156329137SBartlomiej Zolnierkiewicz return -ENOMEM; 992c24602efSGiuseppe CAVALLARO } 993c24602efSGiuseppe CAVALLARO priv->rx_skbuff[i] = skb; 994c24602efSGiuseppe CAVALLARO priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data, 995c24602efSGiuseppe CAVALLARO priv->dma_buf_sz, 996c24602efSGiuseppe CAVALLARO DMA_FROM_DEVICE); 99756329137SBartlomiej Zolnierkiewicz if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) { 99856329137SBartlomiej Zolnierkiewicz pr_err("%s: DMA mapping error\n", __func__); 99956329137SBartlomiej Zolnierkiewicz dev_kfree_skb_any(skb); 100056329137SBartlomiej Zolnierkiewicz return -EINVAL; 100156329137SBartlomiej Zolnierkiewicz } 1002c24602efSGiuseppe CAVALLARO 1003c24602efSGiuseppe CAVALLARO p->des2 = priv->rx_skbuff_dma[i]; 1004c24602efSGiuseppe CAVALLARO 100529896a67SGiuseppe CAVALLARO if ((priv->hw->mode->init_desc3) && 1006c24602efSGiuseppe CAVALLARO (priv->dma_buf_sz == BUF_SIZE_16KiB)) 100729896a67SGiuseppe CAVALLARO priv->hw->mode->init_desc3(p); 1008c24602efSGiuseppe CAVALLARO 1009c24602efSGiuseppe CAVALLARO return 0; 1010c24602efSGiuseppe CAVALLARO } 1011c24602efSGiuseppe CAVALLARO 101256329137SBartlomiej Zolnierkiewicz static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i) 101356329137SBartlomiej Zolnierkiewicz { 101456329137SBartlomiej Zolnierkiewicz if (priv->rx_skbuff[i]) { 101556329137SBartlomiej Zolnierkiewicz dma_unmap_single(priv->device, priv->rx_skbuff_dma[i], 101656329137SBartlomiej Zolnierkiewicz priv->dma_buf_sz, DMA_FROM_DEVICE); 101756329137SBartlomiej Zolnierkiewicz dev_kfree_skb_any(priv->rx_skbuff[i]); 101856329137SBartlomiej Zolnierkiewicz } 101956329137SBartlomiej Zolnierkiewicz priv->rx_skbuff[i] = NULL; 102056329137SBartlomiej Zolnierkiewicz } 102156329137SBartlomiej Zolnierkiewicz 10227ac6653aSJeff Kirsher /** 10237ac6653aSJeff Kirsher * init_dma_desc_rings - init the RX/TX descriptor rings 10247ac6653aSJeff Kirsher * @dev: net device structure 1025732fdf0eSGiuseppe CAVALLARO * @flags: gfp flag. 10267ac6653aSJeff Kirsher * Description: this function initializes the DMA RX/TX descriptors 1027286a8372SGiuseppe CAVALLARO * and allocates the socket buffers. It suppors the chained and ring 1028286a8372SGiuseppe CAVALLARO * modes. 10297ac6653aSJeff Kirsher */ 1030777da230SGiuseppe CAVALLARO static int init_dma_desc_rings(struct net_device *dev, gfp_t flags) 10317ac6653aSJeff Kirsher { 10327ac6653aSJeff Kirsher int i; 10337ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 10344a7d666aSGiuseppe CAVALLARO unsigned int bfsize = 0; 103556329137SBartlomiej Zolnierkiewicz int ret = -ENOMEM; 10367ac6653aSJeff Kirsher 103729896a67SGiuseppe CAVALLARO if (priv->hw->mode->set_16kib_bfsize) 103829896a67SGiuseppe CAVALLARO bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu); 1039286a8372SGiuseppe CAVALLARO 10404a7d666aSGiuseppe CAVALLARO if (bfsize < BUF_SIZE_16KiB) 1041286a8372SGiuseppe CAVALLARO bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz); 10427ac6653aSJeff Kirsher 10432618abb7SVince Bridgers priv->dma_buf_sz = bfsize; 10442618abb7SVince Bridgers 104583d7af64SGiuseppe CAVALLARO if (netif_msg_probe(priv)) { 1046c24602efSGiuseppe CAVALLARO pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__, 1047c24602efSGiuseppe CAVALLARO (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy); 10487ac6653aSJeff Kirsher 10497ac6653aSJeff Kirsher /* RX INITIALIZATION */ 105083d7af64SGiuseppe CAVALLARO pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n"); 105183d7af64SGiuseppe CAVALLARO } 1052e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_RX_SIZE; i++) { 1053c24602efSGiuseppe CAVALLARO struct dma_desc *p; 1054c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1055c24602efSGiuseppe CAVALLARO p = &((priv->dma_erx + i)->basic); 1056c24602efSGiuseppe CAVALLARO else 1057c24602efSGiuseppe CAVALLARO p = priv->dma_rx + i; 10587ac6653aSJeff Kirsher 1059777da230SGiuseppe CAVALLARO ret = stmmac_init_rx_buffers(priv, p, i, flags); 106056329137SBartlomiej Zolnierkiewicz if (ret) 106156329137SBartlomiej Zolnierkiewicz goto err_init_rx_buffers; 1062286a8372SGiuseppe CAVALLARO 106383d7af64SGiuseppe CAVALLARO if (netif_msg_probe(priv)) 106483d7af64SGiuseppe CAVALLARO pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i], 106583d7af64SGiuseppe CAVALLARO priv->rx_skbuff[i]->data, 106683d7af64SGiuseppe CAVALLARO (unsigned int)priv->rx_skbuff_dma[i]); 10677ac6653aSJeff Kirsher } 10687ac6653aSJeff Kirsher priv->cur_rx = 0; 1069e3ad57c9SGiuseppe Cavallaro priv->dirty_rx = (unsigned int)(i - DMA_RX_SIZE); 10707ac6653aSJeff Kirsher buf_sz = bfsize; 10717ac6653aSJeff Kirsher 1072c24602efSGiuseppe CAVALLARO /* Setup the chained descriptor addresses */ 1073c24602efSGiuseppe CAVALLARO if (priv->mode == STMMAC_CHAIN_MODE) { 1074c24602efSGiuseppe CAVALLARO if (priv->extend_desc) { 107529896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy, 1076e3ad57c9SGiuseppe Cavallaro DMA_RX_SIZE, 1); 107729896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy, 1078e3ad57c9SGiuseppe Cavallaro DMA_TX_SIZE, 1); 1079c24602efSGiuseppe CAVALLARO } else { 108029896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy, 1081e3ad57c9SGiuseppe Cavallaro DMA_RX_SIZE, 0); 108229896a67SGiuseppe CAVALLARO priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy, 1083e3ad57c9SGiuseppe Cavallaro DMA_TX_SIZE, 0); 1084c24602efSGiuseppe CAVALLARO } 10857ac6653aSJeff Kirsher } 1086286a8372SGiuseppe CAVALLARO 1087c24602efSGiuseppe CAVALLARO /* TX INITIALIZATION */ 1088e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_TX_SIZE; i++) { 1089c24602efSGiuseppe CAVALLARO struct dma_desc *p; 1090c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1091c24602efSGiuseppe CAVALLARO p = &((priv->dma_etx + i)->basic); 1092c24602efSGiuseppe CAVALLARO else 1093c24602efSGiuseppe CAVALLARO p = priv->dma_tx + i; 1094c24602efSGiuseppe CAVALLARO p->des2 = 0; 1095362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf = 0; 1096362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].map_as_page = false; 1097553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[i].len = 0; 10982a6d8e17SGiuseppe Cavallaro priv->tx_skbuff_dma[i].last_segment = false; 1099c24602efSGiuseppe CAVALLARO priv->tx_skbuff[i] = NULL; 11004a7d666aSGiuseppe CAVALLARO } 1101c24602efSGiuseppe CAVALLARO 11027ac6653aSJeff Kirsher priv->dirty_tx = 0; 11037ac6653aSJeff Kirsher priv->cur_tx = 0; 110438979574SBeniamino Galvani netdev_reset_queue(priv->dev); 11057ac6653aSJeff Kirsher 1106c24602efSGiuseppe CAVALLARO stmmac_clear_descriptors(priv); 11077ac6653aSJeff Kirsher 1108c24602efSGiuseppe CAVALLARO if (netif_msg_hw(priv)) 1109c24602efSGiuseppe CAVALLARO stmmac_display_rings(priv); 111056329137SBartlomiej Zolnierkiewicz 111156329137SBartlomiej Zolnierkiewicz return 0; 111256329137SBartlomiej Zolnierkiewicz err_init_rx_buffers: 111356329137SBartlomiej Zolnierkiewicz while (--i >= 0) 111456329137SBartlomiej Zolnierkiewicz stmmac_free_rx_buffers(priv, i); 111556329137SBartlomiej Zolnierkiewicz return ret; 11167ac6653aSJeff Kirsher } 11177ac6653aSJeff Kirsher 11187ac6653aSJeff Kirsher static void dma_free_rx_skbufs(struct stmmac_priv *priv) 11197ac6653aSJeff Kirsher { 11207ac6653aSJeff Kirsher int i; 11217ac6653aSJeff Kirsher 1122e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_RX_SIZE; i++) 112356329137SBartlomiej Zolnierkiewicz stmmac_free_rx_buffers(priv, i); 11247ac6653aSJeff Kirsher } 11257ac6653aSJeff Kirsher 11267ac6653aSJeff Kirsher static void dma_free_tx_skbufs(struct stmmac_priv *priv) 11277ac6653aSJeff Kirsher { 11287ac6653aSJeff Kirsher int i; 11297ac6653aSJeff Kirsher 1130e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_TX_SIZE; i++) { 1131c24602efSGiuseppe CAVALLARO struct dma_desc *p; 113275e4364fSdamuzi000 1133c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1134c24602efSGiuseppe CAVALLARO p = &((priv->dma_etx + i)->basic); 1135c24602efSGiuseppe CAVALLARO else 1136c24602efSGiuseppe CAVALLARO p = priv->dma_tx + i; 1137c24602efSGiuseppe CAVALLARO 1138362b37beSGiuseppe CAVALLARO if (priv->tx_skbuff_dma[i].buf) { 1139362b37beSGiuseppe CAVALLARO if (priv->tx_skbuff_dma[i].map_as_page) 1140362b37beSGiuseppe CAVALLARO dma_unmap_page(priv->device, 1141362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf, 1142553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[i].len, 11437ac6653aSJeff Kirsher DMA_TO_DEVICE); 1144362b37beSGiuseppe CAVALLARO else 1145362b37beSGiuseppe CAVALLARO dma_unmap_single(priv->device, 1146362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf, 1147553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[i].len, 1148362b37beSGiuseppe CAVALLARO DMA_TO_DEVICE); 114975e4364fSdamuzi000 } 115075e4364fSdamuzi000 115175e4364fSdamuzi000 if (priv->tx_skbuff[i] != NULL) { 11527ac6653aSJeff Kirsher dev_kfree_skb_any(priv->tx_skbuff[i]); 11537ac6653aSJeff Kirsher priv->tx_skbuff[i] = NULL; 1154362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].buf = 0; 1155362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[i].map_as_page = false; 11567ac6653aSJeff Kirsher } 11577ac6653aSJeff Kirsher } 11587ac6653aSJeff Kirsher } 11597ac6653aSJeff Kirsher 1160732fdf0eSGiuseppe CAVALLARO /** 1161732fdf0eSGiuseppe CAVALLARO * alloc_dma_desc_resources - alloc TX/RX resources. 1162732fdf0eSGiuseppe CAVALLARO * @priv: private structure 1163732fdf0eSGiuseppe CAVALLARO * Description: according to which descriptor can be used (extend or basic) 1164732fdf0eSGiuseppe CAVALLARO * this function allocates the resources for TX and RX paths. In case of 1165732fdf0eSGiuseppe CAVALLARO * reception, for example, it pre-allocated the RX socket buffer in order to 1166732fdf0eSGiuseppe CAVALLARO * allow zero-copy mechanism. 1167732fdf0eSGiuseppe CAVALLARO */ 116809f8d696SSrinivas Kandagatla static int alloc_dma_desc_resources(struct stmmac_priv *priv) 116909f8d696SSrinivas Kandagatla { 117009f8d696SSrinivas Kandagatla int ret = -ENOMEM; 117109f8d696SSrinivas Kandagatla 1172e3ad57c9SGiuseppe Cavallaro priv->rx_skbuff_dma = kmalloc_array(DMA_RX_SIZE, sizeof(dma_addr_t), 117309f8d696SSrinivas Kandagatla GFP_KERNEL); 117409f8d696SSrinivas Kandagatla if (!priv->rx_skbuff_dma) 117509f8d696SSrinivas Kandagatla return -ENOMEM; 117609f8d696SSrinivas Kandagatla 1177e3ad57c9SGiuseppe Cavallaro priv->rx_skbuff = kmalloc_array(DMA_RX_SIZE, sizeof(struct sk_buff *), 117809f8d696SSrinivas Kandagatla GFP_KERNEL); 117909f8d696SSrinivas Kandagatla if (!priv->rx_skbuff) 118009f8d696SSrinivas Kandagatla goto err_rx_skbuff; 118109f8d696SSrinivas Kandagatla 1182e3ad57c9SGiuseppe Cavallaro priv->tx_skbuff_dma = kmalloc_array(DMA_TX_SIZE, 1183362b37beSGiuseppe CAVALLARO sizeof(*priv->tx_skbuff_dma), 118409f8d696SSrinivas Kandagatla GFP_KERNEL); 118509f8d696SSrinivas Kandagatla if (!priv->tx_skbuff_dma) 118609f8d696SSrinivas Kandagatla goto err_tx_skbuff_dma; 118709f8d696SSrinivas Kandagatla 1188e3ad57c9SGiuseppe Cavallaro priv->tx_skbuff = kmalloc_array(DMA_TX_SIZE, sizeof(struct sk_buff *), 118909f8d696SSrinivas Kandagatla GFP_KERNEL); 119009f8d696SSrinivas Kandagatla if (!priv->tx_skbuff) 119109f8d696SSrinivas Kandagatla goto err_tx_skbuff; 119209f8d696SSrinivas Kandagatla 119309f8d696SSrinivas Kandagatla if (priv->extend_desc) { 1194e3ad57c9SGiuseppe Cavallaro priv->dma_erx = dma_zalloc_coherent(priv->device, DMA_RX_SIZE * 119509f8d696SSrinivas Kandagatla sizeof(struct 119609f8d696SSrinivas Kandagatla dma_extended_desc), 119709f8d696SSrinivas Kandagatla &priv->dma_rx_phy, 119809f8d696SSrinivas Kandagatla GFP_KERNEL); 119909f8d696SSrinivas Kandagatla if (!priv->dma_erx) 120009f8d696SSrinivas Kandagatla goto err_dma; 120109f8d696SSrinivas Kandagatla 1202e3ad57c9SGiuseppe Cavallaro priv->dma_etx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE * 120309f8d696SSrinivas Kandagatla sizeof(struct 120409f8d696SSrinivas Kandagatla dma_extended_desc), 120509f8d696SSrinivas Kandagatla &priv->dma_tx_phy, 120609f8d696SSrinivas Kandagatla GFP_KERNEL); 120709f8d696SSrinivas Kandagatla if (!priv->dma_etx) { 1208e3ad57c9SGiuseppe Cavallaro dma_free_coherent(priv->device, DMA_RX_SIZE * 120909f8d696SSrinivas Kandagatla sizeof(struct dma_extended_desc), 121009f8d696SSrinivas Kandagatla priv->dma_erx, priv->dma_rx_phy); 121109f8d696SSrinivas Kandagatla goto err_dma; 121209f8d696SSrinivas Kandagatla } 121309f8d696SSrinivas Kandagatla } else { 1214e3ad57c9SGiuseppe Cavallaro priv->dma_rx = dma_zalloc_coherent(priv->device, DMA_RX_SIZE * 121509f8d696SSrinivas Kandagatla sizeof(struct dma_desc), 121609f8d696SSrinivas Kandagatla &priv->dma_rx_phy, 121709f8d696SSrinivas Kandagatla GFP_KERNEL); 121809f8d696SSrinivas Kandagatla if (!priv->dma_rx) 121909f8d696SSrinivas Kandagatla goto err_dma; 122009f8d696SSrinivas Kandagatla 1221e3ad57c9SGiuseppe Cavallaro priv->dma_tx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE * 122209f8d696SSrinivas Kandagatla sizeof(struct dma_desc), 122309f8d696SSrinivas Kandagatla &priv->dma_tx_phy, 122409f8d696SSrinivas Kandagatla GFP_KERNEL); 122509f8d696SSrinivas Kandagatla if (!priv->dma_tx) { 1226e3ad57c9SGiuseppe Cavallaro dma_free_coherent(priv->device, DMA_RX_SIZE * 122709f8d696SSrinivas Kandagatla sizeof(struct dma_desc), 122809f8d696SSrinivas Kandagatla priv->dma_rx, priv->dma_rx_phy); 122909f8d696SSrinivas Kandagatla goto err_dma; 123009f8d696SSrinivas Kandagatla } 123109f8d696SSrinivas Kandagatla } 123209f8d696SSrinivas Kandagatla 123309f8d696SSrinivas Kandagatla return 0; 123409f8d696SSrinivas Kandagatla 123509f8d696SSrinivas Kandagatla err_dma: 123609f8d696SSrinivas Kandagatla kfree(priv->tx_skbuff); 123709f8d696SSrinivas Kandagatla err_tx_skbuff: 123809f8d696SSrinivas Kandagatla kfree(priv->tx_skbuff_dma); 123909f8d696SSrinivas Kandagatla err_tx_skbuff_dma: 124009f8d696SSrinivas Kandagatla kfree(priv->rx_skbuff); 124109f8d696SSrinivas Kandagatla err_rx_skbuff: 124209f8d696SSrinivas Kandagatla kfree(priv->rx_skbuff_dma); 124309f8d696SSrinivas Kandagatla return ret; 124409f8d696SSrinivas Kandagatla } 124509f8d696SSrinivas Kandagatla 12467ac6653aSJeff Kirsher static void free_dma_desc_resources(struct stmmac_priv *priv) 12477ac6653aSJeff Kirsher { 12487ac6653aSJeff Kirsher /* Release the DMA TX/RX socket buffers */ 12497ac6653aSJeff Kirsher dma_free_rx_skbufs(priv); 12507ac6653aSJeff Kirsher dma_free_tx_skbufs(priv); 12517ac6653aSJeff Kirsher 1252ceb69499SGiuseppe CAVALLARO /* Free DMA regions of consistent memory previously allocated */ 1253c24602efSGiuseppe CAVALLARO if (!priv->extend_desc) { 12547ac6653aSJeff Kirsher dma_free_coherent(priv->device, 1255e3ad57c9SGiuseppe Cavallaro DMA_TX_SIZE * sizeof(struct dma_desc), 12567ac6653aSJeff Kirsher priv->dma_tx, priv->dma_tx_phy); 12577ac6653aSJeff Kirsher dma_free_coherent(priv->device, 1258e3ad57c9SGiuseppe Cavallaro DMA_RX_SIZE * sizeof(struct dma_desc), 12597ac6653aSJeff Kirsher priv->dma_rx, priv->dma_rx_phy); 1260c24602efSGiuseppe CAVALLARO } else { 1261e3ad57c9SGiuseppe Cavallaro dma_free_coherent(priv->device, DMA_TX_SIZE * 1262c24602efSGiuseppe CAVALLARO sizeof(struct dma_extended_desc), 1263c24602efSGiuseppe CAVALLARO priv->dma_etx, priv->dma_tx_phy); 1264e3ad57c9SGiuseppe Cavallaro dma_free_coherent(priv->device, DMA_RX_SIZE * 1265c24602efSGiuseppe CAVALLARO sizeof(struct dma_extended_desc), 1266c24602efSGiuseppe CAVALLARO priv->dma_erx, priv->dma_rx_phy); 1267c24602efSGiuseppe CAVALLARO } 12687ac6653aSJeff Kirsher kfree(priv->rx_skbuff_dma); 12697ac6653aSJeff Kirsher kfree(priv->rx_skbuff); 1270cf32deecSRayagond Kokatanur kfree(priv->tx_skbuff_dma); 12717ac6653aSJeff Kirsher kfree(priv->tx_skbuff); 12727ac6653aSJeff Kirsher } 12737ac6653aSJeff Kirsher 12747ac6653aSJeff Kirsher /** 12757ac6653aSJeff Kirsher * stmmac_dma_operation_mode - HW DMA operation mode 127632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 1277732fdf0eSGiuseppe CAVALLARO * Description: it is used for configuring the DMA operation mode register in 1278732fdf0eSGiuseppe CAVALLARO * order to program the tx/rx DMA thresholds or Store-And-Forward mode. 12797ac6653aSJeff Kirsher */ 12807ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv) 12817ac6653aSJeff Kirsher { 1282f88203a2SVince Bridgers int rxfifosz = priv->plat->rx_fifo_size; 1283f88203a2SVince Bridgers 1284e2a240c7SSonic Zhang if (priv->plat->force_thresh_dma_mode) 1285f88203a2SVince Bridgers priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, rxfifosz); 1286e2a240c7SSonic Zhang else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) { 12877ac6653aSJeff Kirsher /* 12887ac6653aSJeff Kirsher * In case of GMAC, SF mode can be enabled 12897ac6653aSJeff Kirsher * to perform the TX COE in HW. This depends on: 12907ac6653aSJeff Kirsher * 1) TX COE if actually supported 12917ac6653aSJeff Kirsher * 2) There is no bugged Jumbo frame support 12927ac6653aSJeff Kirsher * that needs to not insert csum in the TDES. 12937ac6653aSJeff Kirsher */ 1294f88203a2SVince Bridgers priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE, 1295f88203a2SVince Bridgers rxfifosz); 1296b2dec116SSonic Zhang priv->xstats.threshold = SF_DMA_MODE; 12977ac6653aSJeff Kirsher } else 1298f88203a2SVince Bridgers priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE, 1299f88203a2SVince Bridgers rxfifosz); 13007ac6653aSJeff Kirsher } 13017ac6653aSJeff Kirsher 13027ac6653aSJeff Kirsher /** 1303732fdf0eSGiuseppe CAVALLARO * stmmac_tx_clean - to manage the transmission completion 130432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 1305732fdf0eSGiuseppe CAVALLARO * Description: it reclaims the transmit resources after transmission completes. 13067ac6653aSJeff Kirsher */ 13079125cdd1SGiuseppe CAVALLARO static void stmmac_tx_clean(struct stmmac_priv *priv) 13087ac6653aSJeff Kirsher { 130938979574SBeniamino Galvani unsigned int bytes_compl = 0, pkts_compl = 0; 1310e3ad57c9SGiuseppe Cavallaro unsigned int entry = priv->dirty_tx; 13117ac6653aSJeff Kirsher 1312a9097a96SGiuseppe CAVALLARO spin_lock(&priv->tx_lock); 1313a9097a96SGiuseppe CAVALLARO 13149125cdd1SGiuseppe CAVALLARO priv->xstats.tx_clean++; 13159125cdd1SGiuseppe CAVALLARO 1316e3ad57c9SGiuseppe Cavallaro while (entry != priv->cur_tx) { 13177ac6653aSJeff Kirsher struct sk_buff *skb = priv->tx_skbuff[entry]; 1318c24602efSGiuseppe CAVALLARO struct dma_desc *p; 1319c363b658SFabrice Gasnier int status; 1320c24602efSGiuseppe CAVALLARO 1321c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1322c24602efSGiuseppe CAVALLARO p = (struct dma_desc *)(priv->dma_etx + entry); 1323c24602efSGiuseppe CAVALLARO else 1324c24602efSGiuseppe CAVALLARO p = priv->dma_tx + entry; 13257ac6653aSJeff Kirsher 1326c363b658SFabrice Gasnier status = priv->hw->desc->tx_status(&priv->dev->stats, 13277ac6653aSJeff Kirsher &priv->xstats, p, 13287ac6653aSJeff Kirsher priv->ioaddr); 1329c363b658SFabrice Gasnier /* Check if the descriptor is owned by the DMA */ 1330c363b658SFabrice Gasnier if (unlikely(status & tx_dma_own)) 1331c363b658SFabrice Gasnier break; 1332c363b658SFabrice Gasnier 1333c363b658SFabrice Gasnier /* Just consider the last segment and ...*/ 1334c363b658SFabrice Gasnier if (likely(!(status & tx_not_ls))) { 1335c363b658SFabrice Gasnier /* ... verify the status error condition */ 1336c363b658SFabrice Gasnier if (unlikely(status & tx_err)) { 1337c363b658SFabrice Gasnier priv->dev->stats.tx_errors++; 1338c363b658SFabrice Gasnier } else { 13397ac6653aSJeff Kirsher priv->dev->stats.tx_packets++; 13407ac6653aSJeff Kirsher priv->xstats.tx_pkt_n++; 1341c363b658SFabrice Gasnier } 1342891434b1SRayagond Kokatanur stmmac_get_tx_hwtstamp(priv, entry, skb); 13437ac6653aSJeff Kirsher } 13447ac6653aSJeff Kirsher 1345362b37beSGiuseppe CAVALLARO if (likely(priv->tx_skbuff_dma[entry].buf)) { 1346362b37beSGiuseppe CAVALLARO if (priv->tx_skbuff_dma[entry].map_as_page) 1347362b37beSGiuseppe CAVALLARO dma_unmap_page(priv->device, 1348362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf, 1349553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].len, 13507ac6653aSJeff Kirsher DMA_TO_DEVICE); 1351362b37beSGiuseppe CAVALLARO else 1352362b37beSGiuseppe CAVALLARO dma_unmap_single(priv->device, 1353362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf, 1354553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].len, 1355362b37beSGiuseppe CAVALLARO DMA_TO_DEVICE); 1356362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf = 0; 1357362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].map_as_page = false; 1358cf32deecSRayagond Kokatanur } 135929896a67SGiuseppe CAVALLARO priv->hw->mode->clean_desc3(priv, p); 13602a6d8e17SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].last_segment = false; 136196951366SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].is_jumbo = false; 13627ac6653aSJeff Kirsher 13637ac6653aSJeff Kirsher if (likely(skb != NULL)) { 136438979574SBeniamino Galvani pkts_compl++; 136538979574SBeniamino Galvani bytes_compl += skb->len; 13667c565c33SEric W. Biederman dev_consume_skb_any(skb); 13677ac6653aSJeff Kirsher priv->tx_skbuff[entry] = NULL; 13687ac6653aSJeff Kirsher } 13697ac6653aSJeff Kirsher 13704a7d666aSGiuseppe CAVALLARO priv->hw->desc->release_tx_desc(p, priv->mode); 13717ac6653aSJeff Kirsher 1372e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); 13737ac6653aSJeff Kirsher } 1374fbc80823SGiuseppe Cavallaro priv->dirty_tx = entry; 137538979574SBeniamino Galvani 137638979574SBeniamino Galvani netdev_completed_queue(priv->dev, pkts_compl, bytes_compl); 137738979574SBeniamino Galvani 13787ac6653aSJeff Kirsher if (unlikely(netif_queue_stopped(priv->dev) && 1379e3ad57c9SGiuseppe Cavallaro stmmac_tx_avail(priv) > STMMAC_TX_THRESH)) { 13807ac6653aSJeff Kirsher netif_tx_lock(priv->dev); 13817ac6653aSJeff Kirsher if (netif_queue_stopped(priv->dev) && 1382e3ad57c9SGiuseppe Cavallaro stmmac_tx_avail(priv) > STMMAC_TX_THRESH) { 138383d7af64SGiuseppe CAVALLARO if (netif_msg_tx_done(priv)) 138483d7af64SGiuseppe CAVALLARO pr_debug("%s: restart transmit\n", __func__); 13857ac6653aSJeff Kirsher netif_wake_queue(priv->dev); 13867ac6653aSJeff Kirsher } 13877ac6653aSJeff Kirsher netif_tx_unlock(priv->dev); 13887ac6653aSJeff Kirsher } 1389d765955dSGiuseppe CAVALLARO 1390d765955dSGiuseppe CAVALLARO if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) { 1391d765955dSGiuseppe CAVALLARO stmmac_enable_eee_mode(priv); 1392f5351ef7SGiuseppe CAVALLARO mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer)); 1393d765955dSGiuseppe CAVALLARO } 1394a9097a96SGiuseppe CAVALLARO spin_unlock(&priv->tx_lock); 13957ac6653aSJeff Kirsher } 13967ac6653aSJeff Kirsher 13979125cdd1SGiuseppe CAVALLARO static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv) 13987ac6653aSJeff Kirsher { 13997ac6653aSJeff Kirsher priv->hw->dma->enable_dma_irq(priv->ioaddr); 14007ac6653aSJeff Kirsher } 14017ac6653aSJeff Kirsher 14029125cdd1SGiuseppe CAVALLARO static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv) 14037ac6653aSJeff Kirsher { 14047ac6653aSJeff Kirsher priv->hw->dma->disable_dma_irq(priv->ioaddr); 14057ac6653aSJeff Kirsher } 14067ac6653aSJeff Kirsher 14077ac6653aSJeff Kirsher /** 1408732fdf0eSGiuseppe CAVALLARO * stmmac_tx_err - to manage the tx error 140932ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 14107ac6653aSJeff Kirsher * Description: it cleans the descriptors and restarts the transmission 1411732fdf0eSGiuseppe CAVALLARO * in case of transmission errors. 14127ac6653aSJeff Kirsher */ 14137ac6653aSJeff Kirsher static void stmmac_tx_err(struct stmmac_priv *priv) 14147ac6653aSJeff Kirsher { 1415c24602efSGiuseppe CAVALLARO int i; 14167ac6653aSJeff Kirsher netif_stop_queue(priv->dev); 14177ac6653aSJeff Kirsher 14187ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 14197ac6653aSJeff Kirsher dma_free_tx_skbufs(priv); 1420e3ad57c9SGiuseppe Cavallaro for (i = 0; i < DMA_TX_SIZE; i++) 1421c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 1422c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic, 1423c24602efSGiuseppe CAVALLARO priv->mode, 1424e3ad57c9SGiuseppe Cavallaro (i == DMA_TX_SIZE - 1)); 1425c24602efSGiuseppe CAVALLARO else 1426c24602efSGiuseppe CAVALLARO priv->hw->desc->init_tx_desc(&priv->dma_tx[i], 1427c24602efSGiuseppe CAVALLARO priv->mode, 1428e3ad57c9SGiuseppe Cavallaro (i == DMA_TX_SIZE - 1)); 14297ac6653aSJeff Kirsher priv->dirty_tx = 0; 14307ac6653aSJeff Kirsher priv->cur_tx = 0; 143138979574SBeniamino Galvani netdev_reset_queue(priv->dev); 14327ac6653aSJeff Kirsher priv->hw->dma->start_tx(priv->ioaddr); 14337ac6653aSJeff Kirsher 14347ac6653aSJeff Kirsher priv->dev->stats.tx_errors++; 14357ac6653aSJeff Kirsher netif_wake_queue(priv->dev); 14367ac6653aSJeff Kirsher } 14377ac6653aSJeff Kirsher 143832ceabcaSGiuseppe CAVALLARO /** 1439732fdf0eSGiuseppe CAVALLARO * stmmac_dma_interrupt - DMA ISR 144032ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 144132ceabcaSGiuseppe CAVALLARO * Description: this is the DMA ISR. It is called by the main ISR. 1442732fdf0eSGiuseppe CAVALLARO * It calls the dwmac dma routine and schedule poll method in case of some 1443732fdf0eSGiuseppe CAVALLARO * work can be done. 144432ceabcaSGiuseppe CAVALLARO */ 14457ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv) 14467ac6653aSJeff Kirsher { 14477ac6653aSJeff Kirsher int status; 1448f88203a2SVince Bridgers int rxfifosz = priv->plat->rx_fifo_size; 14497ac6653aSJeff Kirsher 14507ac6653aSJeff Kirsher status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats); 14519125cdd1SGiuseppe CAVALLARO if (likely((status & handle_rx)) || (status & handle_tx)) { 14529125cdd1SGiuseppe CAVALLARO if (likely(napi_schedule_prep(&priv->napi))) { 14539125cdd1SGiuseppe CAVALLARO stmmac_disable_dma_irq(priv); 14549125cdd1SGiuseppe CAVALLARO __napi_schedule(&priv->napi); 14559125cdd1SGiuseppe CAVALLARO } 14569125cdd1SGiuseppe CAVALLARO } 14579125cdd1SGiuseppe CAVALLARO if (unlikely(status & tx_hard_error_bump_tc)) { 14587ac6653aSJeff Kirsher /* Try to bump up the dma threshold on this failure */ 1459b2dec116SSonic Zhang if (unlikely(priv->xstats.threshold != SF_DMA_MODE) && 1460b2dec116SSonic Zhang (tc <= 256)) { 14617ac6653aSJeff Kirsher tc += 64; 1462c405abe2SSonic Zhang if (priv->plat->force_thresh_dma_mode) 1463f88203a2SVince Bridgers priv->hw->dma->dma_mode(priv->ioaddr, tc, tc, 1464f88203a2SVince Bridgers rxfifosz); 1465c405abe2SSonic Zhang else 1466c405abe2SSonic Zhang priv->hw->dma->dma_mode(priv->ioaddr, tc, 1467f88203a2SVince Bridgers SF_DMA_MODE, rxfifosz); 14687ac6653aSJeff Kirsher priv->xstats.threshold = tc; 14697ac6653aSJeff Kirsher } 14707ac6653aSJeff Kirsher } else if (unlikely(status == tx_hard_error)) 14717ac6653aSJeff Kirsher stmmac_tx_err(priv); 14727ac6653aSJeff Kirsher } 14737ac6653aSJeff Kirsher 147432ceabcaSGiuseppe CAVALLARO /** 147532ceabcaSGiuseppe CAVALLARO * stmmac_mmc_setup: setup the Mac Management Counters (MMC) 147632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 147732ceabcaSGiuseppe CAVALLARO * Description: this masks the MMC irq, in fact, the counters are managed in SW. 147832ceabcaSGiuseppe CAVALLARO */ 14791c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv) 14801c901a46SGiuseppe CAVALLARO { 14811c901a46SGiuseppe CAVALLARO unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET | 14821c901a46SGiuseppe CAVALLARO MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET; 14831c901a46SGiuseppe CAVALLARO 14841c901a46SGiuseppe CAVALLARO dwmac_mmc_intr_all_mask(priv->ioaddr); 14854f795b25SGiuseppe CAVALLARO 14864f795b25SGiuseppe CAVALLARO if (priv->dma_cap.rmon) { 14871c901a46SGiuseppe CAVALLARO dwmac_mmc_ctrl(priv->ioaddr, mode); 14881c901a46SGiuseppe CAVALLARO memset(&priv->mmc, 0, sizeof(struct stmmac_counters)); 14894f795b25SGiuseppe CAVALLARO } else 1490aae54cffSStefan Roese pr_info(" No MAC Management Counters available\n"); 14911c901a46SGiuseppe CAVALLARO } 14921c901a46SGiuseppe CAVALLARO 1493732fdf0eSGiuseppe CAVALLARO /** 1494732fdf0eSGiuseppe CAVALLARO * stmmac_get_synopsys_id - return the SYINID. 1495732fdf0eSGiuseppe CAVALLARO * @priv: driver private structure 1496732fdf0eSGiuseppe CAVALLARO * Description: this simple function is to decode and return the SYINID 1497732fdf0eSGiuseppe CAVALLARO * starting from the HW core register. 1498732fdf0eSGiuseppe CAVALLARO */ 1499f0b9d786SGiuseppe CAVALLARO static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv) 1500f0b9d786SGiuseppe CAVALLARO { 1501f0b9d786SGiuseppe CAVALLARO u32 hwid = priv->hw->synopsys_uid; 1502f0b9d786SGiuseppe CAVALLARO 1503ceb69499SGiuseppe CAVALLARO /* Check Synopsys Id (not available on old chips) */ 1504f0b9d786SGiuseppe CAVALLARO if (likely(hwid)) { 1505f0b9d786SGiuseppe CAVALLARO u32 uid = ((hwid & 0x0000ff00) >> 8); 1506f0b9d786SGiuseppe CAVALLARO u32 synid = (hwid & 0x000000ff); 1507f0b9d786SGiuseppe CAVALLARO 1508cf3f047bSGiuseppe CAVALLARO pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n", 1509f0b9d786SGiuseppe CAVALLARO uid, synid); 1510f0b9d786SGiuseppe CAVALLARO 1511f0b9d786SGiuseppe CAVALLARO return synid; 1512f0b9d786SGiuseppe CAVALLARO } 1513f0b9d786SGiuseppe CAVALLARO return 0; 1514f0b9d786SGiuseppe CAVALLARO } 1515e7434821SGiuseppe CAVALLARO 151619e30c14SGiuseppe CAVALLARO /** 1517732fdf0eSGiuseppe CAVALLARO * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors 151832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 151932ceabcaSGiuseppe CAVALLARO * Description: select the Enhanced/Alternate or Normal descriptors. 1520732fdf0eSGiuseppe CAVALLARO * In case of Enhanced/Alternate, it checks if the extended descriptors are 1521732fdf0eSGiuseppe CAVALLARO * supported by the HW capability register. 1522ff3dd78cSGiuseppe CAVALLARO */ 152319e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv) 152419e30c14SGiuseppe CAVALLARO { 152519e30c14SGiuseppe CAVALLARO if (priv->plat->enh_desc) { 152619e30c14SGiuseppe CAVALLARO pr_info(" Enhanced/Alternate descriptors\n"); 1527c24602efSGiuseppe CAVALLARO 1528c24602efSGiuseppe CAVALLARO /* GMAC older than 3.50 has no extended descriptors */ 1529c24602efSGiuseppe CAVALLARO if (priv->synopsys_id >= DWMAC_CORE_3_50) { 1530c24602efSGiuseppe CAVALLARO pr_info("\tEnabled extended descriptors\n"); 1531c24602efSGiuseppe CAVALLARO priv->extend_desc = 1; 1532c24602efSGiuseppe CAVALLARO } else 1533c24602efSGiuseppe CAVALLARO pr_warn("Extended descriptors not supported\n"); 1534c24602efSGiuseppe CAVALLARO 153519e30c14SGiuseppe CAVALLARO priv->hw->desc = &enh_desc_ops; 153619e30c14SGiuseppe CAVALLARO } else { 153719e30c14SGiuseppe CAVALLARO pr_info(" Normal descriptors\n"); 153819e30c14SGiuseppe CAVALLARO priv->hw->desc = &ndesc_ops; 153919e30c14SGiuseppe CAVALLARO } 154019e30c14SGiuseppe CAVALLARO } 154119e30c14SGiuseppe CAVALLARO 154219e30c14SGiuseppe CAVALLARO /** 1543732fdf0eSGiuseppe CAVALLARO * stmmac_get_hw_features - get MAC capabilities from the HW cap. register. 154432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 154519e30c14SGiuseppe CAVALLARO * Description: 154619e30c14SGiuseppe CAVALLARO * new GMAC chip generations have a new register to indicate the 1547e7434821SGiuseppe CAVALLARO * presence of the optional feature/functions. 154819e30c14SGiuseppe CAVALLARO * This can be also used to override the value passed through the 154919e30c14SGiuseppe CAVALLARO * platform and necessary for old MAC10/100 and GMAC chips. 1550e7434821SGiuseppe CAVALLARO */ 1551e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv) 1552e7434821SGiuseppe CAVALLARO { 15535e6efe88SGiuseppe CAVALLARO u32 hw_cap = 0; 15543c20f72fSGiuseppe CAVALLARO 15555e6efe88SGiuseppe CAVALLARO if (priv->hw->dma->get_hw_feature) { 15565e6efe88SGiuseppe CAVALLARO hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr); 1557e7434821SGiuseppe CAVALLARO 15581db123fbSRayagond Kokatanur priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL); 15591db123fbSRayagond Kokatanur priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1; 15601db123fbSRayagond Kokatanur priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2; 15611db123fbSRayagond Kokatanur priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4; 1562ceb69499SGiuseppe CAVALLARO priv->dma_cap.multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5; 15631db123fbSRayagond Kokatanur priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6; 15641db123fbSRayagond Kokatanur priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8; 15651db123fbSRayagond Kokatanur priv->dma_cap.pmt_remote_wake_up = 15661db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9; 15671db123fbSRayagond Kokatanur priv->dma_cap.pmt_magic_frame = 15681db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10; 15691db123fbSRayagond Kokatanur /* MMC */ 15701db123fbSRayagond Kokatanur priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11; 1571e7434821SGiuseppe CAVALLARO /* IEEE 1588-2002 */ 15721db123fbSRayagond Kokatanur priv->dma_cap.time_stamp = 15731db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12; 1574e7434821SGiuseppe CAVALLARO /* IEEE 1588-2008 */ 15751db123fbSRayagond Kokatanur priv->dma_cap.atime_stamp = 15761db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13; 1577e7434821SGiuseppe CAVALLARO /* 802.3az - Energy-Efficient Ethernet (EEE) */ 15781db123fbSRayagond Kokatanur priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14; 15791db123fbSRayagond Kokatanur priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15; 1580e7434821SGiuseppe CAVALLARO /* TX and RX csum */ 15811db123fbSRayagond Kokatanur priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16; 15821db123fbSRayagond Kokatanur priv->dma_cap.rx_coe_type1 = 15831db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17; 15841db123fbSRayagond Kokatanur priv->dma_cap.rx_coe_type2 = 15851db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18; 15861db123fbSRayagond Kokatanur priv->dma_cap.rxfifo_over_2048 = 15871db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19; 1588e7434821SGiuseppe CAVALLARO /* TX and RX number of channels */ 15891db123fbSRayagond Kokatanur priv->dma_cap.number_rx_channel = 15901db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20; 15911db123fbSRayagond Kokatanur priv->dma_cap.number_tx_channel = 15921db123fbSRayagond Kokatanur (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22; 1593e7434821SGiuseppe CAVALLARO /* Alternate (enhanced) DESC mode */ 1594ceb69499SGiuseppe CAVALLARO priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24; 159519e30c14SGiuseppe CAVALLARO } 1596e7434821SGiuseppe CAVALLARO 1597e7434821SGiuseppe CAVALLARO return hw_cap; 1598e7434821SGiuseppe CAVALLARO } 1599e7434821SGiuseppe CAVALLARO 160032ceabcaSGiuseppe CAVALLARO /** 1601732fdf0eSGiuseppe CAVALLARO * stmmac_check_ether_addr - check if the MAC addr is valid 160232ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 160332ceabcaSGiuseppe CAVALLARO * Description: 160432ceabcaSGiuseppe CAVALLARO * it is to verify if the MAC address is valid, in case of failures it 160532ceabcaSGiuseppe CAVALLARO * generates a random MAC address 160632ceabcaSGiuseppe CAVALLARO */ 1607bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv) 1608bfab27a1SGiuseppe CAVALLARO { 1609bfab27a1SGiuseppe CAVALLARO if (!is_valid_ether_addr(priv->dev->dev_addr)) { 16107ed24bbeSVince Bridgers priv->hw->mac->get_umac_addr(priv->hw, 1611bfab27a1SGiuseppe CAVALLARO priv->dev->dev_addr, 0); 1612bfab27a1SGiuseppe CAVALLARO if (!is_valid_ether_addr(priv->dev->dev_addr)) 1613f2cedb63SDanny Kukawka eth_hw_addr_random(priv->dev); 1614c88460b7SHans de Goede pr_info("%s: device MAC address %pM\n", priv->dev->name, 1615bfab27a1SGiuseppe CAVALLARO priv->dev->dev_addr); 1616bfab27a1SGiuseppe CAVALLARO } 1617c88460b7SHans de Goede } 1618bfab27a1SGiuseppe CAVALLARO 161932ceabcaSGiuseppe CAVALLARO /** 1620732fdf0eSGiuseppe CAVALLARO * stmmac_init_dma_engine - DMA init. 162132ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 162232ceabcaSGiuseppe CAVALLARO * Description: 162332ceabcaSGiuseppe CAVALLARO * It inits the DMA invoking the specific MAC/GMAC callback. 162432ceabcaSGiuseppe CAVALLARO * Some DMA parameters can be passed from the platform; 162532ceabcaSGiuseppe CAVALLARO * in case of these are not passed a default is kept for the MAC or GMAC. 162632ceabcaSGiuseppe CAVALLARO */ 16270f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv) 16280f1f88a8SGiuseppe CAVALLARO { 1629afea0365SGiuseppe Cavallaro int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, aal = 0; 1630b9cde0a8SGiuseppe CAVALLARO int mixed_burst = 0; 1631c24602efSGiuseppe CAVALLARO int atds = 0; 1632495db273SGiuseppe Cavallaro int ret = 0; 16330f1f88a8SGiuseppe CAVALLARO 16340f1f88a8SGiuseppe CAVALLARO if (priv->plat->dma_cfg) { 16350f1f88a8SGiuseppe CAVALLARO pbl = priv->plat->dma_cfg->pbl; 16360f1f88a8SGiuseppe CAVALLARO fixed_burst = priv->plat->dma_cfg->fixed_burst; 1637b9cde0a8SGiuseppe CAVALLARO mixed_burst = priv->plat->dma_cfg->mixed_burst; 1638afea0365SGiuseppe Cavallaro aal = priv->plat->dma_cfg->aal; 16390f1f88a8SGiuseppe CAVALLARO } 16400f1f88a8SGiuseppe CAVALLARO 1641c24602efSGiuseppe CAVALLARO if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE)) 1642c24602efSGiuseppe CAVALLARO atds = 1; 1643c24602efSGiuseppe CAVALLARO 1644495db273SGiuseppe Cavallaro ret = priv->hw->dma->reset(priv->ioaddr); 1645495db273SGiuseppe Cavallaro if (ret) { 1646495db273SGiuseppe Cavallaro dev_err(priv->device, "Failed to reset the dma\n"); 1647495db273SGiuseppe Cavallaro return ret; 1648495db273SGiuseppe Cavallaro } 1649495db273SGiuseppe Cavallaro 1650495db273SGiuseppe Cavallaro priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst, 1651afea0365SGiuseppe Cavallaro aal, priv->dma_tx_phy, priv->dma_rx_phy, atds); 1652afea0365SGiuseppe Cavallaro 1653afea0365SGiuseppe Cavallaro if ((priv->synopsys_id >= DWMAC_CORE_3_50) && 1654afea0365SGiuseppe Cavallaro (priv->plat->axi && priv->hw->dma->axi)) 1655afea0365SGiuseppe Cavallaro priv->hw->dma->axi(priv->ioaddr, priv->plat->axi); 1656afea0365SGiuseppe Cavallaro 1657495db273SGiuseppe Cavallaro return ret; 16580f1f88a8SGiuseppe CAVALLARO } 16590f1f88a8SGiuseppe CAVALLARO 1660bfab27a1SGiuseppe CAVALLARO /** 1661732fdf0eSGiuseppe CAVALLARO * stmmac_tx_timer - mitigation sw timer for tx. 16629125cdd1SGiuseppe CAVALLARO * @data: data pointer 16639125cdd1SGiuseppe CAVALLARO * Description: 16649125cdd1SGiuseppe CAVALLARO * This is the timer handler to directly invoke the stmmac_tx_clean. 16659125cdd1SGiuseppe CAVALLARO */ 16669125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data) 16679125cdd1SGiuseppe CAVALLARO { 16689125cdd1SGiuseppe CAVALLARO struct stmmac_priv *priv = (struct stmmac_priv *)data; 16699125cdd1SGiuseppe CAVALLARO 16709125cdd1SGiuseppe CAVALLARO stmmac_tx_clean(priv); 16719125cdd1SGiuseppe CAVALLARO } 16729125cdd1SGiuseppe CAVALLARO 16739125cdd1SGiuseppe CAVALLARO /** 1674732fdf0eSGiuseppe CAVALLARO * stmmac_init_tx_coalesce - init tx mitigation options. 167532ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 16769125cdd1SGiuseppe CAVALLARO * Description: 16779125cdd1SGiuseppe CAVALLARO * This inits the transmit coalesce parameters: i.e. timer rate, 16789125cdd1SGiuseppe CAVALLARO * timer handler and default threshold used for enabling the 16799125cdd1SGiuseppe CAVALLARO * interrupt on completion bit. 16809125cdd1SGiuseppe CAVALLARO */ 16819125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv) 16829125cdd1SGiuseppe CAVALLARO { 16839125cdd1SGiuseppe CAVALLARO priv->tx_coal_frames = STMMAC_TX_FRAMES; 16849125cdd1SGiuseppe CAVALLARO priv->tx_coal_timer = STMMAC_COAL_TX_TIMER; 16859125cdd1SGiuseppe CAVALLARO init_timer(&priv->txtimer); 16869125cdd1SGiuseppe CAVALLARO priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer); 16879125cdd1SGiuseppe CAVALLARO priv->txtimer.data = (unsigned long)priv; 16889125cdd1SGiuseppe CAVALLARO priv->txtimer.function = stmmac_tx_timer; 16899125cdd1SGiuseppe CAVALLARO add_timer(&priv->txtimer); 16909125cdd1SGiuseppe CAVALLARO } 16919125cdd1SGiuseppe CAVALLARO 16929125cdd1SGiuseppe CAVALLARO /** 1693732fdf0eSGiuseppe CAVALLARO * stmmac_hw_setup - setup mac in a usable state. 1694523f11b5SSrinivas Kandagatla * @dev : pointer to the device structure. 1695523f11b5SSrinivas Kandagatla * Description: 1696732fdf0eSGiuseppe CAVALLARO * this is the main function to setup the HW in a usable state because the 1697732fdf0eSGiuseppe CAVALLARO * dma engine is reset, the core registers are configured (e.g. AXI, 1698732fdf0eSGiuseppe CAVALLARO * Checksum features, timers). The DMA is ready to start receiving and 1699732fdf0eSGiuseppe CAVALLARO * transmitting. 1700523f11b5SSrinivas Kandagatla * Return value: 1701523f11b5SSrinivas Kandagatla * 0 on success and an appropriate (-)ve integer as defined in errno.h 1702523f11b5SSrinivas Kandagatla * file on failure. 1703523f11b5SSrinivas Kandagatla */ 1704fe131929SHuacai Chen static int stmmac_hw_setup(struct net_device *dev, bool init_ptp) 1705523f11b5SSrinivas Kandagatla { 1706523f11b5SSrinivas Kandagatla struct stmmac_priv *priv = netdev_priv(dev); 1707523f11b5SSrinivas Kandagatla int ret; 1708523f11b5SSrinivas Kandagatla 1709523f11b5SSrinivas Kandagatla /* DMA initialization and SW reset */ 1710523f11b5SSrinivas Kandagatla ret = stmmac_init_dma_engine(priv); 1711523f11b5SSrinivas Kandagatla if (ret < 0) { 1712523f11b5SSrinivas Kandagatla pr_err("%s: DMA engine initialization failed\n", __func__); 1713523f11b5SSrinivas Kandagatla return ret; 1714523f11b5SSrinivas Kandagatla } 1715523f11b5SSrinivas Kandagatla 1716523f11b5SSrinivas Kandagatla /* Copy the MAC addr into the HW */ 17177ed24bbeSVince Bridgers priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0); 1718523f11b5SSrinivas Kandagatla 1719523f11b5SSrinivas Kandagatla /* If required, perform hw setup of the bus. */ 1720523f11b5SSrinivas Kandagatla if (priv->plat->bus_setup) 1721523f11b5SSrinivas Kandagatla priv->plat->bus_setup(priv->ioaddr); 1722523f11b5SSrinivas Kandagatla 1723523f11b5SSrinivas Kandagatla /* Initialize the MAC Core */ 17247ed24bbeSVince Bridgers priv->hw->mac->core_init(priv->hw, dev->mtu); 1725523f11b5SSrinivas Kandagatla 1726978aded4SGiuseppe CAVALLARO ret = priv->hw->mac->rx_ipc(priv->hw); 1727978aded4SGiuseppe CAVALLARO if (!ret) { 1728978aded4SGiuseppe CAVALLARO pr_warn(" RX IPC Checksum Offload disabled\n"); 1729978aded4SGiuseppe CAVALLARO priv->plat->rx_coe = STMMAC_RX_COE_NONE; 1730d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = 0; 1731978aded4SGiuseppe CAVALLARO } 1732978aded4SGiuseppe CAVALLARO 1733523f11b5SSrinivas Kandagatla /* Enable the MAC Rx/Tx */ 1734523f11b5SSrinivas Kandagatla stmmac_set_mac(priv->ioaddr, true); 1735523f11b5SSrinivas Kandagatla 1736523f11b5SSrinivas Kandagatla /* Set the HW DMA mode and the COE */ 1737523f11b5SSrinivas Kandagatla stmmac_dma_operation_mode(priv); 1738523f11b5SSrinivas Kandagatla 1739523f11b5SSrinivas Kandagatla stmmac_mmc_setup(priv); 1740523f11b5SSrinivas Kandagatla 1741fe131929SHuacai Chen if (init_ptp) { 1742523f11b5SSrinivas Kandagatla ret = stmmac_init_ptp(priv); 17437509edd6SHans de Goede if (ret && ret != -EOPNOTSUPP) 1744523f11b5SSrinivas Kandagatla pr_warn("%s: failed PTP initialisation\n", __func__); 1745fe131929SHuacai Chen } 1746523f11b5SSrinivas Kandagatla 174750fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 1748523f11b5SSrinivas Kandagatla ret = stmmac_init_fs(dev); 1749523f11b5SSrinivas Kandagatla if (ret < 0) 1750523f11b5SSrinivas Kandagatla pr_warn("%s: failed debugFS registration\n", __func__); 1751523f11b5SSrinivas Kandagatla #endif 1752523f11b5SSrinivas Kandagatla /* Start the ball rolling... */ 1753523f11b5SSrinivas Kandagatla pr_debug("%s: DMA RX/TX processes started...\n", dev->name); 1754523f11b5SSrinivas Kandagatla priv->hw->dma->start_tx(priv->ioaddr); 1755523f11b5SSrinivas Kandagatla priv->hw->dma->start_rx(priv->ioaddr); 1756523f11b5SSrinivas Kandagatla 1757523f11b5SSrinivas Kandagatla /* Dump DMA/MAC registers */ 1758523f11b5SSrinivas Kandagatla if (netif_msg_hw(priv)) { 17597ed24bbeSVince Bridgers priv->hw->mac->dump_regs(priv->hw); 1760523f11b5SSrinivas Kandagatla priv->hw->dma->dump_regs(priv->ioaddr); 1761523f11b5SSrinivas Kandagatla } 1762523f11b5SSrinivas Kandagatla priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS; 1763523f11b5SSrinivas Kandagatla 1764523f11b5SSrinivas Kandagatla if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) { 1765523f11b5SSrinivas Kandagatla priv->rx_riwt = MAX_DMA_RIWT; 1766523f11b5SSrinivas Kandagatla priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT); 1767523f11b5SSrinivas Kandagatla } 1768523f11b5SSrinivas Kandagatla 1769523f11b5SSrinivas Kandagatla if (priv->pcs && priv->hw->mac->ctrl_ane) 17707ed24bbeSVince Bridgers priv->hw->mac->ctrl_ane(priv->hw, 0); 1771523f11b5SSrinivas Kandagatla 1772523f11b5SSrinivas Kandagatla return 0; 1773523f11b5SSrinivas Kandagatla } 1774523f11b5SSrinivas Kandagatla 1775523f11b5SSrinivas Kandagatla /** 17767ac6653aSJeff Kirsher * stmmac_open - open entry point of the driver 17777ac6653aSJeff Kirsher * @dev : pointer to the device structure. 17787ac6653aSJeff Kirsher * Description: 17797ac6653aSJeff Kirsher * This function is the open entry point of the driver. 17807ac6653aSJeff Kirsher * Return value: 17817ac6653aSJeff Kirsher * 0 on success and an appropriate (-)ve integer as defined in errno.h 17827ac6653aSJeff Kirsher * file on failure. 17837ac6653aSJeff Kirsher */ 17847ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev) 17857ac6653aSJeff Kirsher { 17867ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 17877ac6653aSJeff Kirsher int ret; 17887ac6653aSJeff Kirsher 17894bfcbd7aSFrancesco Virlinzi stmmac_check_ether_addr(priv); 17904bfcbd7aSFrancesco Virlinzi 17914d8f0825SByungho An if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 17924d8f0825SByungho An priv->pcs != STMMAC_PCS_RTBI) { 17937ac6653aSJeff Kirsher ret = stmmac_init_phy(dev); 1794e58bb43fSGiuseppe CAVALLARO if (ret) { 1795e58bb43fSGiuseppe CAVALLARO pr_err("%s: Cannot attach to PHY (error: %d)\n", 1796e58bb43fSGiuseppe CAVALLARO __func__, ret); 179789df20d9SHans de Goede return ret; 17987ac6653aSJeff Kirsher } 1799e58bb43fSGiuseppe CAVALLARO } 18007ac6653aSJeff Kirsher 1801523f11b5SSrinivas Kandagatla /* Extra statistics */ 1802523f11b5SSrinivas Kandagatla memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats)); 1803523f11b5SSrinivas Kandagatla priv->xstats.threshold = tc; 1804523f11b5SSrinivas Kandagatla 18057ac6653aSJeff Kirsher priv->dma_buf_sz = STMMAC_ALIGN(buf_sz); 180622ad3838SGiuseppe Cavallaro priv->rx_copybreak = STMMAC_RX_COPYBREAK; 180756329137SBartlomiej Zolnierkiewicz 18087262b7b2STobias Klauser ret = alloc_dma_desc_resources(priv); 180909f8d696SSrinivas Kandagatla if (ret < 0) { 181009f8d696SSrinivas Kandagatla pr_err("%s: DMA descriptors allocation failed\n", __func__); 181109f8d696SSrinivas Kandagatla goto dma_desc_error; 181209f8d696SSrinivas Kandagatla } 181309f8d696SSrinivas Kandagatla 1814777da230SGiuseppe CAVALLARO ret = init_dma_desc_rings(dev, GFP_KERNEL); 1815777da230SGiuseppe CAVALLARO if (ret < 0) { 1816777da230SGiuseppe CAVALLARO pr_err("%s: DMA descriptors initialization failed\n", __func__); 1817777da230SGiuseppe CAVALLARO goto init_error; 1818777da230SGiuseppe CAVALLARO } 1819777da230SGiuseppe CAVALLARO 1820fe131929SHuacai Chen ret = stmmac_hw_setup(dev, true); 182156329137SBartlomiej Zolnierkiewicz if (ret < 0) { 1822523f11b5SSrinivas Kandagatla pr_err("%s: Hw setup failed\n", __func__); 1823c9324d18SGiuseppe CAVALLARO goto init_error; 18247ac6653aSJeff Kirsher } 18257ac6653aSJeff Kirsher 1826777da230SGiuseppe CAVALLARO stmmac_init_tx_coalesce(priv); 1827777da230SGiuseppe CAVALLARO 1828523f11b5SSrinivas Kandagatla if (priv->phydev) 1829523f11b5SSrinivas Kandagatla phy_start(priv->phydev); 18307ac6653aSJeff Kirsher 18317ac6653aSJeff Kirsher /* Request the IRQ lines */ 18327ac6653aSJeff Kirsher ret = request_irq(dev->irq, stmmac_interrupt, 18337ac6653aSJeff Kirsher IRQF_SHARED, dev->name, dev); 18347ac6653aSJeff Kirsher if (unlikely(ret < 0)) { 18357ac6653aSJeff Kirsher pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n", 18367ac6653aSJeff Kirsher __func__, dev->irq, ret); 1837c9324d18SGiuseppe CAVALLARO goto init_error; 18387ac6653aSJeff Kirsher } 18397ac6653aSJeff Kirsher 18407a13f8f5SFrancesco Virlinzi /* Request the Wake IRQ in case of another line is used for WoL */ 18417a13f8f5SFrancesco Virlinzi if (priv->wol_irq != dev->irq) { 18427a13f8f5SFrancesco Virlinzi ret = request_irq(priv->wol_irq, stmmac_interrupt, 18437a13f8f5SFrancesco Virlinzi IRQF_SHARED, dev->name, dev); 18447a13f8f5SFrancesco Virlinzi if (unlikely(ret < 0)) { 1845ceb69499SGiuseppe CAVALLARO pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n", 1846ceb69499SGiuseppe CAVALLARO __func__, priv->wol_irq, ret); 1847c9324d18SGiuseppe CAVALLARO goto wolirq_error; 18487a13f8f5SFrancesco Virlinzi } 18497a13f8f5SFrancesco Virlinzi } 18507a13f8f5SFrancesco Virlinzi 1851d765955dSGiuseppe CAVALLARO /* Request the IRQ lines */ 1852d7ec8584SChen-Yu Tsai if (priv->lpi_irq > 0) { 1853d765955dSGiuseppe CAVALLARO ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED, 1854d765955dSGiuseppe CAVALLARO dev->name, dev); 1855d765955dSGiuseppe CAVALLARO if (unlikely(ret < 0)) { 1856d765955dSGiuseppe CAVALLARO pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n", 1857d765955dSGiuseppe CAVALLARO __func__, priv->lpi_irq, ret); 1858c9324d18SGiuseppe CAVALLARO goto lpiirq_error; 1859d765955dSGiuseppe CAVALLARO } 1860d765955dSGiuseppe CAVALLARO } 1861d765955dSGiuseppe CAVALLARO 18627ac6653aSJeff Kirsher napi_enable(&priv->napi); 18637ac6653aSJeff Kirsher netif_start_queue(dev); 18647ac6653aSJeff Kirsher 18657ac6653aSJeff Kirsher return 0; 18667ac6653aSJeff Kirsher 1867c9324d18SGiuseppe CAVALLARO lpiirq_error: 1868d765955dSGiuseppe CAVALLARO if (priv->wol_irq != dev->irq) 1869d765955dSGiuseppe CAVALLARO free_irq(priv->wol_irq, dev); 1870c9324d18SGiuseppe CAVALLARO wolirq_error: 18717a13f8f5SFrancesco Virlinzi free_irq(dev->irq, dev); 18727a13f8f5SFrancesco Virlinzi 1873c9324d18SGiuseppe CAVALLARO init_error: 1874c9324d18SGiuseppe CAVALLARO free_dma_desc_resources(priv); 187556329137SBartlomiej Zolnierkiewicz dma_desc_error: 18767ac6653aSJeff Kirsher if (priv->phydev) 18777ac6653aSJeff Kirsher phy_disconnect(priv->phydev); 18784bfcbd7aSFrancesco Virlinzi 18797ac6653aSJeff Kirsher return ret; 18807ac6653aSJeff Kirsher } 18817ac6653aSJeff Kirsher 18827ac6653aSJeff Kirsher /** 18837ac6653aSJeff Kirsher * stmmac_release - close entry point of the driver 18847ac6653aSJeff Kirsher * @dev : device pointer. 18857ac6653aSJeff Kirsher * Description: 18867ac6653aSJeff Kirsher * This is the stop entry point of the driver. 18877ac6653aSJeff Kirsher */ 18887ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev) 18897ac6653aSJeff Kirsher { 18907ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 18917ac6653aSJeff Kirsher 1892d765955dSGiuseppe CAVALLARO if (priv->eee_enabled) 1893d765955dSGiuseppe CAVALLARO del_timer_sync(&priv->eee_ctrl_timer); 1894d765955dSGiuseppe CAVALLARO 18957ac6653aSJeff Kirsher /* Stop and disconnect the PHY */ 18967ac6653aSJeff Kirsher if (priv->phydev) { 18977ac6653aSJeff Kirsher phy_stop(priv->phydev); 18987ac6653aSJeff Kirsher phy_disconnect(priv->phydev); 18997ac6653aSJeff Kirsher priv->phydev = NULL; 19007ac6653aSJeff Kirsher } 19017ac6653aSJeff Kirsher 19027ac6653aSJeff Kirsher netif_stop_queue(dev); 19037ac6653aSJeff Kirsher 19047ac6653aSJeff Kirsher napi_disable(&priv->napi); 19057ac6653aSJeff Kirsher 19069125cdd1SGiuseppe CAVALLARO del_timer_sync(&priv->txtimer); 19079125cdd1SGiuseppe CAVALLARO 19087ac6653aSJeff Kirsher /* Free the IRQ lines */ 19097ac6653aSJeff Kirsher free_irq(dev->irq, dev); 19107a13f8f5SFrancesco Virlinzi if (priv->wol_irq != dev->irq) 19117a13f8f5SFrancesco Virlinzi free_irq(priv->wol_irq, dev); 1912d7ec8584SChen-Yu Tsai if (priv->lpi_irq > 0) 1913d765955dSGiuseppe CAVALLARO free_irq(priv->lpi_irq, dev); 19147ac6653aSJeff Kirsher 19157ac6653aSJeff Kirsher /* Stop TX/RX DMA and clear the descriptors */ 19167ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 19177ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 19187ac6653aSJeff Kirsher 19197ac6653aSJeff Kirsher /* Release and free the Rx/Tx resources */ 19207ac6653aSJeff Kirsher free_dma_desc_resources(priv); 19217ac6653aSJeff Kirsher 19227ac6653aSJeff Kirsher /* Disable the MAC Rx/Tx */ 1923bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 19247ac6653aSJeff Kirsher 19257ac6653aSJeff Kirsher netif_carrier_off(dev); 19267ac6653aSJeff Kirsher 192750fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 1928466c5ac8SMathieu Olivari stmmac_exit_fs(dev); 1929bfab27a1SGiuseppe CAVALLARO #endif 1930bfab27a1SGiuseppe CAVALLARO 193192ba6888SRayagond Kokatanur stmmac_release_ptp(priv); 193292ba6888SRayagond Kokatanur 19337ac6653aSJeff Kirsher return 0; 19347ac6653aSJeff Kirsher } 19357ac6653aSJeff Kirsher 19367ac6653aSJeff Kirsher /** 1937732fdf0eSGiuseppe CAVALLARO * stmmac_xmit - Tx entry point of the driver 19387ac6653aSJeff Kirsher * @skb : the socket buffer 19397ac6653aSJeff Kirsher * @dev : device pointer 194032ceabcaSGiuseppe CAVALLARO * Description : this is the tx entry point of the driver. 194132ceabcaSGiuseppe CAVALLARO * It programs the chain or the ring and supports oversized frames 194232ceabcaSGiuseppe CAVALLARO * and SG feature. 19437ac6653aSJeff Kirsher */ 19447ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) 19457ac6653aSJeff Kirsher { 19467ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 19470e80bdc9SGiuseppe Cavallaro unsigned int nopaged_len = skb_headlen(skb); 19484a7d666aSGiuseppe CAVALLARO int i, csum_insertion = 0, is_jumbo = 0; 19497ac6653aSJeff Kirsher int nfrags = skb_shinfo(skb)->nr_frags; 19500e80bdc9SGiuseppe Cavallaro unsigned int entry, first_entry; 19517ac6653aSJeff Kirsher struct dma_desc *desc, *first; 19520e80bdc9SGiuseppe Cavallaro unsigned int enh_desc; 19537ac6653aSJeff Kirsher 195416ee817eSFabrice Gasnier spin_lock(&priv->tx_lock); 195516ee817eSFabrice Gasnier 19567ac6653aSJeff Kirsher if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) { 195716ee817eSFabrice Gasnier spin_unlock(&priv->tx_lock); 19587ac6653aSJeff Kirsher if (!netif_queue_stopped(dev)) { 19597ac6653aSJeff Kirsher netif_stop_queue(dev); 19607ac6653aSJeff Kirsher /* This is a hard error, log it. */ 1961ceb69499SGiuseppe CAVALLARO pr_err("%s: Tx Ring full when queue awake\n", __func__); 19627ac6653aSJeff Kirsher } 19637ac6653aSJeff Kirsher return NETDEV_TX_BUSY; 19647ac6653aSJeff Kirsher } 19657ac6653aSJeff Kirsher 1966d765955dSGiuseppe CAVALLARO if (priv->tx_path_in_lpi_mode) 1967d765955dSGiuseppe CAVALLARO stmmac_disable_eee_mode(priv); 1968d765955dSGiuseppe CAVALLARO 1969e3ad57c9SGiuseppe Cavallaro entry = priv->cur_tx; 19700e80bdc9SGiuseppe Cavallaro first_entry = entry; 19717ac6653aSJeff Kirsher 19727ac6653aSJeff Kirsher csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL); 19737ac6653aSJeff Kirsher 19740e80bdc9SGiuseppe Cavallaro if (likely(priv->extend_desc)) 1975c24602efSGiuseppe CAVALLARO desc = (struct dma_desc *)(priv->dma_etx + entry); 1976c24602efSGiuseppe CAVALLARO else 19777ac6653aSJeff Kirsher desc = priv->dma_tx + entry; 1978c24602efSGiuseppe CAVALLARO 19797ac6653aSJeff Kirsher first = desc; 19807ac6653aSJeff Kirsher 19810e80bdc9SGiuseppe Cavallaro priv->tx_skbuff[first_entry] = skb; 19820e80bdc9SGiuseppe Cavallaro 19830e80bdc9SGiuseppe Cavallaro enh_desc = priv->plat->enh_desc; 19844a7d666aSGiuseppe CAVALLARO /* To program the descriptors according to the size of the frame */ 198529896a67SGiuseppe CAVALLARO if (enh_desc) 198629896a67SGiuseppe CAVALLARO is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc); 198729896a67SGiuseppe CAVALLARO 19880e80bdc9SGiuseppe Cavallaro if (unlikely(is_jumbo)) { 198929896a67SGiuseppe CAVALLARO entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion); 1990362b37beSGiuseppe CAVALLARO if (unlikely(entry < 0)) 1991362b37beSGiuseppe CAVALLARO goto dma_map_err; 199229896a67SGiuseppe CAVALLARO } 19937ac6653aSJeff Kirsher 19947ac6653aSJeff Kirsher for (i = 0; i < nfrags; i++) { 19959e903e08SEric Dumazet const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; 19969e903e08SEric Dumazet int len = skb_frag_size(frag); 1997be434d50SGiuseppe Cavallaro bool last_segment = (i == (nfrags - 1)); 19987ac6653aSJeff Kirsher 1999e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); 2000e3ad57c9SGiuseppe Cavallaro 20010e80bdc9SGiuseppe Cavallaro if (likely(priv->extend_desc)) 2002c24602efSGiuseppe CAVALLARO desc = (struct dma_desc *)(priv->dma_etx + entry); 2003c24602efSGiuseppe CAVALLARO else 20047ac6653aSJeff Kirsher desc = priv->dma_tx + entry; 20057ac6653aSJeff Kirsher 2006f722380dSIan Campbell desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len, 2007f722380dSIan Campbell DMA_TO_DEVICE); 2008362b37beSGiuseppe CAVALLARO if (dma_mapping_error(priv->device, desc->des2)) 2009362b37beSGiuseppe CAVALLARO goto dma_map_err; /* should reuse desc w/o issues */ 2010362b37beSGiuseppe CAVALLARO 20110e80bdc9SGiuseppe Cavallaro priv->tx_skbuff[entry] = NULL; 2012362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].buf = desc->des2; 2013362b37beSGiuseppe CAVALLARO priv->tx_skbuff_dma[entry].map_as_page = true; 2014553e2ab3SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].len = len; 20150e80bdc9SGiuseppe Cavallaro priv->tx_skbuff_dma[entry].last_segment = last_segment; 20160e80bdc9SGiuseppe Cavallaro 20170e80bdc9SGiuseppe Cavallaro /* Prepare the descriptor and set the own bit too */ 20184a7d666aSGiuseppe CAVALLARO priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion, 2019be434d50SGiuseppe Cavallaro priv->mode, 1, last_segment); 20207ac6653aSJeff Kirsher } 20217ac6653aSJeff Kirsher 2022e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE); 2023e3ad57c9SGiuseppe Cavallaro 2024e3ad57c9SGiuseppe Cavallaro priv->cur_tx = entry; 20257ac6653aSJeff Kirsher 20267ac6653aSJeff Kirsher if (netif_msg_pktdata(priv)) { 20270e80bdc9SGiuseppe Cavallaro pr_debug("%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d", 20280e80bdc9SGiuseppe Cavallaro __func__, priv->cur_tx, priv->dirty_tx, first_entry, 20290e80bdc9SGiuseppe Cavallaro entry, first, nfrags); 203083d7af64SGiuseppe CAVALLARO 2031c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2032e3ad57c9SGiuseppe Cavallaro stmmac_display_ring((void *)priv->dma_etx, 2033e3ad57c9SGiuseppe Cavallaro DMA_TX_SIZE, 1); 2034c24602efSGiuseppe CAVALLARO else 2035e3ad57c9SGiuseppe Cavallaro stmmac_display_ring((void *)priv->dma_tx, 2036e3ad57c9SGiuseppe Cavallaro DMA_TX_SIZE, 0); 2037c24602efSGiuseppe CAVALLARO 203883d7af64SGiuseppe CAVALLARO pr_debug(">>> frame to be transmitted: "); 20397ac6653aSJeff Kirsher print_pkt(skb->data, skb->len); 20407ac6653aSJeff Kirsher } 20410e80bdc9SGiuseppe Cavallaro 20427ac6653aSJeff Kirsher if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) { 204383d7af64SGiuseppe CAVALLARO if (netif_msg_hw(priv)) 204483d7af64SGiuseppe CAVALLARO pr_debug("%s: stop transmitted packets\n", __func__); 20457ac6653aSJeff Kirsher netif_stop_queue(dev); 20467ac6653aSJeff Kirsher } 20477ac6653aSJeff Kirsher 20487ac6653aSJeff Kirsher dev->stats.tx_bytes += skb->len; 20497ac6653aSJeff Kirsher 20500e80bdc9SGiuseppe Cavallaro /* According to the coalesce parameter the IC bit for the latest 20510e80bdc9SGiuseppe Cavallaro * segment is reset and the timer re-started to clean the tx status. 20520e80bdc9SGiuseppe Cavallaro * This approach takes care about the fragments: desc is the first 20530e80bdc9SGiuseppe Cavallaro * element in case of no SG. 20540e80bdc9SGiuseppe Cavallaro */ 20550e80bdc9SGiuseppe Cavallaro priv->tx_count_frames += nfrags + 1; 20560e80bdc9SGiuseppe Cavallaro if (likely(priv->tx_coal_frames > priv->tx_count_frames)) { 20570e80bdc9SGiuseppe Cavallaro mod_timer(&priv->txtimer, 20580e80bdc9SGiuseppe Cavallaro STMMAC_COAL_TIMER(priv->tx_coal_timer)); 20590e80bdc9SGiuseppe Cavallaro } else { 20600e80bdc9SGiuseppe Cavallaro priv->tx_count_frames = 0; 20610e80bdc9SGiuseppe Cavallaro priv->hw->desc->set_tx_ic(desc); 20620e80bdc9SGiuseppe Cavallaro priv->xstats.tx_set_ic_bit++; 20630e80bdc9SGiuseppe Cavallaro } 20640e80bdc9SGiuseppe Cavallaro 20650e80bdc9SGiuseppe Cavallaro if (!priv->hwts_tx_en) 20660e80bdc9SGiuseppe Cavallaro skb_tx_timestamp(skb); 20670e80bdc9SGiuseppe Cavallaro 20680e80bdc9SGiuseppe Cavallaro /* Ready to fill the first descriptor and set the OWN bit w/o any 20690e80bdc9SGiuseppe Cavallaro * problems because all the descriptors are actually ready to be 20700e80bdc9SGiuseppe Cavallaro * passed to the DMA engine. 20710e80bdc9SGiuseppe Cavallaro */ 20720e80bdc9SGiuseppe Cavallaro if (likely(!is_jumbo)) { 20730e80bdc9SGiuseppe Cavallaro bool last_segment = (nfrags == 0); 20740e80bdc9SGiuseppe Cavallaro 20750e80bdc9SGiuseppe Cavallaro first->des2 = dma_map_single(priv->device, skb->data, 20760e80bdc9SGiuseppe Cavallaro nopaged_len, DMA_TO_DEVICE); 20770e80bdc9SGiuseppe Cavallaro if (dma_mapping_error(priv->device, first->des2)) 20780e80bdc9SGiuseppe Cavallaro goto dma_map_err; 20790e80bdc9SGiuseppe Cavallaro 20800e80bdc9SGiuseppe Cavallaro priv->tx_skbuff_dma[first_entry].buf = first->des2; 20810e80bdc9SGiuseppe Cavallaro priv->tx_skbuff_dma[first_entry].len = nopaged_len; 20820e80bdc9SGiuseppe Cavallaro priv->tx_skbuff_dma[first_entry].last_segment = last_segment; 20830e80bdc9SGiuseppe Cavallaro 2084891434b1SRayagond Kokatanur if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && 2085891434b1SRayagond Kokatanur priv->hwts_tx_en)) { 2086891434b1SRayagond Kokatanur /* declare that device is doing timestamping */ 2087891434b1SRayagond Kokatanur skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 2088891434b1SRayagond Kokatanur priv->hw->desc->enable_tx_timestamp(first); 2089891434b1SRayagond Kokatanur } 2090891434b1SRayagond Kokatanur 20910e80bdc9SGiuseppe Cavallaro /* Prepare the first descriptor setting the OWN bit too */ 20920e80bdc9SGiuseppe Cavallaro priv->hw->desc->prepare_tx_desc(first, 1, nopaged_len, 20930e80bdc9SGiuseppe Cavallaro csum_insertion, priv->mode, 1, 20940e80bdc9SGiuseppe Cavallaro last_segment); 20950e80bdc9SGiuseppe Cavallaro 20960e80bdc9SGiuseppe Cavallaro /* The own bit must be the latest setting done when prepare the 20970e80bdc9SGiuseppe Cavallaro * descriptor and then barrier is needed to make sure that 20980e80bdc9SGiuseppe Cavallaro * all is coherent before granting the DMA engine. 20990e80bdc9SGiuseppe Cavallaro */ 21000e80bdc9SGiuseppe Cavallaro smp_wmb(); 21010e80bdc9SGiuseppe Cavallaro } 21027ac6653aSJeff Kirsher 210338979574SBeniamino Galvani netdev_sent_queue(dev, skb->len); 21047ac6653aSJeff Kirsher priv->hw->dma->enable_dma_transmission(priv->ioaddr); 21057ac6653aSJeff Kirsher 2106a9097a96SGiuseppe CAVALLARO spin_unlock(&priv->tx_lock); 2107362b37beSGiuseppe CAVALLARO return NETDEV_TX_OK; 2108a9097a96SGiuseppe CAVALLARO 2109362b37beSGiuseppe CAVALLARO dma_map_err: 2110758a0ab5SFabrice Gasnier spin_unlock(&priv->tx_lock); 2111362b37beSGiuseppe CAVALLARO dev_err(priv->device, "Tx dma map failed\n"); 2112362b37beSGiuseppe CAVALLARO dev_kfree_skb(skb); 2113362b37beSGiuseppe CAVALLARO priv->dev->stats.tx_dropped++; 21147ac6653aSJeff Kirsher return NETDEV_TX_OK; 21157ac6653aSJeff Kirsher } 21167ac6653aSJeff Kirsher 2117b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb) 2118b9381985SVince Bridgers { 2119b9381985SVince Bridgers struct ethhdr *ehdr; 2120b9381985SVince Bridgers u16 vlanid; 2121b9381985SVince Bridgers 2122b9381985SVince Bridgers if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) == 2123b9381985SVince Bridgers NETIF_F_HW_VLAN_CTAG_RX && 2124b9381985SVince Bridgers !__vlan_get_tag(skb, &vlanid)) { 2125b9381985SVince Bridgers /* pop the vlan tag */ 2126b9381985SVince Bridgers ehdr = (struct ethhdr *)skb->data; 2127b9381985SVince Bridgers memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2); 2128b9381985SVince Bridgers skb_pull(skb, VLAN_HLEN); 2129b9381985SVince Bridgers __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid); 2130b9381985SVince Bridgers } 2131b9381985SVince Bridgers } 2132b9381985SVince Bridgers 2133b9381985SVince Bridgers 2134120e87f9SGiuseppe Cavallaro static inline int stmmac_rx_threshold_count(struct stmmac_priv *priv) 2135120e87f9SGiuseppe Cavallaro { 2136120e87f9SGiuseppe Cavallaro if (priv->rx_zeroc_thresh < STMMAC_RX_THRESH) 2137120e87f9SGiuseppe Cavallaro return 0; 2138120e87f9SGiuseppe Cavallaro 2139120e87f9SGiuseppe Cavallaro return 1; 2140120e87f9SGiuseppe Cavallaro } 2141120e87f9SGiuseppe Cavallaro 214232ceabcaSGiuseppe CAVALLARO /** 2143732fdf0eSGiuseppe CAVALLARO * stmmac_rx_refill - refill used skb preallocated buffers 214432ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 214532ceabcaSGiuseppe CAVALLARO * Description : this is to reallocate the skb for the reception process 214632ceabcaSGiuseppe CAVALLARO * that is based on zero-copy. 214732ceabcaSGiuseppe CAVALLARO */ 21487ac6653aSJeff Kirsher static inline void stmmac_rx_refill(struct stmmac_priv *priv) 21497ac6653aSJeff Kirsher { 21507ac6653aSJeff Kirsher int bfsize = priv->dma_buf_sz; 2151e3ad57c9SGiuseppe Cavallaro unsigned int entry = priv->dirty_rx; 2152e3ad57c9SGiuseppe Cavallaro int dirty = stmmac_rx_dirty(priv); 21537ac6653aSJeff Kirsher 2154e3ad57c9SGiuseppe Cavallaro while (dirty-- > 0) { 2155c24602efSGiuseppe CAVALLARO struct dma_desc *p; 2156c24602efSGiuseppe CAVALLARO 2157c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2158c24602efSGiuseppe CAVALLARO p = (struct dma_desc *)(priv->dma_erx + entry); 2159c24602efSGiuseppe CAVALLARO else 2160c24602efSGiuseppe CAVALLARO p = priv->dma_rx + entry; 2161c24602efSGiuseppe CAVALLARO 21627ac6653aSJeff Kirsher if (likely(priv->rx_skbuff[entry] == NULL)) { 21637ac6653aSJeff Kirsher struct sk_buff *skb; 21647ac6653aSJeff Kirsher 2165acb600deSEric Dumazet skb = netdev_alloc_skb_ip_align(priv->dev, bfsize); 2166120e87f9SGiuseppe Cavallaro if (unlikely(!skb)) { 2167120e87f9SGiuseppe Cavallaro /* so for a while no zero-copy! */ 2168120e87f9SGiuseppe Cavallaro priv->rx_zeroc_thresh = STMMAC_RX_THRESH; 2169120e87f9SGiuseppe Cavallaro if (unlikely(net_ratelimit())) 2170120e87f9SGiuseppe Cavallaro dev_err(priv->device, 2171120e87f9SGiuseppe Cavallaro "fail to alloc skb entry %d\n", 2172120e87f9SGiuseppe Cavallaro entry); 21737ac6653aSJeff Kirsher break; 2174120e87f9SGiuseppe Cavallaro } 21757ac6653aSJeff Kirsher 21767ac6653aSJeff Kirsher priv->rx_skbuff[entry] = skb; 21777ac6653aSJeff Kirsher priv->rx_skbuff_dma[entry] = 21787ac6653aSJeff Kirsher dma_map_single(priv->device, skb->data, bfsize, 21797ac6653aSJeff Kirsher DMA_FROM_DEVICE); 2180362b37beSGiuseppe CAVALLARO if (dma_mapping_error(priv->device, 2181362b37beSGiuseppe CAVALLARO priv->rx_skbuff_dma[entry])) { 2182362b37beSGiuseppe CAVALLARO dev_err(priv->device, "Rx dma map failed\n"); 2183362b37beSGiuseppe CAVALLARO dev_kfree_skb(skb); 2184362b37beSGiuseppe CAVALLARO break; 2185362b37beSGiuseppe CAVALLARO } 2186c24602efSGiuseppe CAVALLARO p->des2 = priv->rx_skbuff_dma[entry]; 2187286a8372SGiuseppe CAVALLARO 218829896a67SGiuseppe CAVALLARO priv->hw->mode->refill_desc3(priv, p); 2189286a8372SGiuseppe CAVALLARO 2190120e87f9SGiuseppe Cavallaro if (priv->rx_zeroc_thresh > 0) 2191120e87f9SGiuseppe Cavallaro priv->rx_zeroc_thresh--; 2192120e87f9SGiuseppe Cavallaro 219383d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) 219483d7af64SGiuseppe CAVALLARO pr_debug("\trefill entry #%d\n", entry); 21957ac6653aSJeff Kirsher } 2196120e87f9SGiuseppe Cavallaro 21977ac6653aSJeff Kirsher wmb(); 2198c24602efSGiuseppe CAVALLARO priv->hw->desc->set_rx_owner(p); 21998e839891SDeepak Sikri wmb(); 2200e3ad57c9SGiuseppe Cavallaro 2201e3ad57c9SGiuseppe Cavallaro entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE); 22027ac6653aSJeff Kirsher } 2203e3ad57c9SGiuseppe Cavallaro priv->dirty_rx = entry; 22047ac6653aSJeff Kirsher } 22057ac6653aSJeff Kirsher 220632ceabcaSGiuseppe CAVALLARO /** 2207732fdf0eSGiuseppe CAVALLARO * stmmac_rx - manage the receive process 220832ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 220932ceabcaSGiuseppe CAVALLARO * @limit: napi bugget. 221032ceabcaSGiuseppe CAVALLARO * Description : this the function called by the napi poll method. 221132ceabcaSGiuseppe CAVALLARO * It gets all the frames inside the ring. 221232ceabcaSGiuseppe CAVALLARO */ 22137ac6653aSJeff Kirsher static int stmmac_rx(struct stmmac_priv *priv, int limit) 22147ac6653aSJeff Kirsher { 2215e3ad57c9SGiuseppe Cavallaro unsigned int entry = priv->cur_rx; 22167ac6653aSJeff Kirsher unsigned int next_entry; 22177ac6653aSJeff Kirsher unsigned int count = 0; 2218d2afb5bdSGiuseppe CAVALLARO int coe = priv->hw->rx_csum; 22197ac6653aSJeff Kirsher 222083d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) { 222183d7af64SGiuseppe CAVALLARO pr_debug("%s: descriptor ring:\n", __func__); 2222c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2223e3ad57c9SGiuseppe Cavallaro stmmac_display_ring((void *)priv->dma_erx, 2224e3ad57c9SGiuseppe Cavallaro DMA_RX_SIZE, 1); 2225c24602efSGiuseppe CAVALLARO else 2226e3ad57c9SGiuseppe Cavallaro stmmac_display_ring((void *)priv->dma_rx, 2227e3ad57c9SGiuseppe Cavallaro DMA_RX_SIZE, 0); 22287ac6653aSJeff Kirsher } 2229c24602efSGiuseppe CAVALLARO while (count < limit) { 22307ac6653aSJeff Kirsher int status; 22319401bb5cSGiuseppe CAVALLARO struct dma_desc *p; 22327ac6653aSJeff Kirsher 2233c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 2234c24602efSGiuseppe CAVALLARO p = (struct dma_desc *)(priv->dma_erx + entry); 2235c24602efSGiuseppe CAVALLARO else 2236c24602efSGiuseppe CAVALLARO p = priv->dma_rx + entry; 2237c24602efSGiuseppe CAVALLARO 2238c1fa3212SFabrice Gasnier /* read the status of the incoming frame */ 2239c1fa3212SFabrice Gasnier status = priv->hw->desc->rx_status(&priv->dev->stats, 2240c1fa3212SFabrice Gasnier &priv->xstats, p); 2241c1fa3212SFabrice Gasnier /* check if managed by the DMA otherwise go ahead */ 2242c1fa3212SFabrice Gasnier if (unlikely(status & dma_own)) 22437ac6653aSJeff Kirsher break; 22447ac6653aSJeff Kirsher 22457ac6653aSJeff Kirsher count++; 22467ac6653aSJeff Kirsher 2247e3ad57c9SGiuseppe Cavallaro priv->cur_rx = STMMAC_GET_ENTRY(priv->cur_rx, DMA_RX_SIZE); 2248e3ad57c9SGiuseppe Cavallaro next_entry = priv->cur_rx; 2249e3ad57c9SGiuseppe Cavallaro 2250c24602efSGiuseppe CAVALLARO if (priv->extend_desc) 22519401bb5cSGiuseppe CAVALLARO prefetch(priv->dma_erx + next_entry); 2252c24602efSGiuseppe CAVALLARO else 22539401bb5cSGiuseppe CAVALLARO prefetch(priv->dma_rx + next_entry); 22547ac6653aSJeff Kirsher 2255c24602efSGiuseppe CAVALLARO if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status)) 2256c24602efSGiuseppe CAVALLARO priv->hw->desc->rx_extended_status(&priv->dev->stats, 2257c24602efSGiuseppe CAVALLARO &priv->xstats, 2258c24602efSGiuseppe CAVALLARO priv->dma_erx + 2259c24602efSGiuseppe CAVALLARO entry); 2260891434b1SRayagond Kokatanur if (unlikely(status == discard_frame)) { 22617ac6653aSJeff Kirsher priv->dev->stats.rx_errors++; 2262891434b1SRayagond Kokatanur if (priv->hwts_rx_en && !priv->extend_desc) { 2263891434b1SRayagond Kokatanur /* DESC2 & DESC3 will be overwitten by device 2264891434b1SRayagond Kokatanur * with timestamp value, hence reinitialize 2265891434b1SRayagond Kokatanur * them in stmmac_rx_refill() function so that 2266891434b1SRayagond Kokatanur * device can reuse it. 2267891434b1SRayagond Kokatanur */ 2268891434b1SRayagond Kokatanur priv->rx_skbuff[entry] = NULL; 2269891434b1SRayagond Kokatanur dma_unmap_single(priv->device, 2270891434b1SRayagond Kokatanur priv->rx_skbuff_dma[entry], 2271ceb69499SGiuseppe CAVALLARO priv->dma_buf_sz, 2272ceb69499SGiuseppe CAVALLARO DMA_FROM_DEVICE); 2273891434b1SRayagond Kokatanur } 2274891434b1SRayagond Kokatanur } else { 22757ac6653aSJeff Kirsher struct sk_buff *skb; 22767ac6653aSJeff Kirsher int frame_len; 22777ac6653aSJeff Kirsher 2278ceb69499SGiuseppe CAVALLARO frame_len = priv->hw->desc->get_rx_frame_len(p, coe); 2279ceb69499SGiuseppe CAVALLARO 2280e527c4a7SGiuseppe CAVALLARO /* check if frame_len fits the preallocated memory */ 2281e527c4a7SGiuseppe CAVALLARO if (frame_len > priv->dma_buf_sz) { 2282e527c4a7SGiuseppe CAVALLARO priv->dev->stats.rx_length_errors++; 2283e527c4a7SGiuseppe CAVALLARO break; 2284e527c4a7SGiuseppe CAVALLARO } 2285e527c4a7SGiuseppe CAVALLARO 22867ac6653aSJeff Kirsher /* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3 2287ceb69499SGiuseppe CAVALLARO * Type frames (LLC/LLC-SNAP) 2288ceb69499SGiuseppe CAVALLARO */ 22897ac6653aSJeff Kirsher if (unlikely(status != llc_snap)) 22907ac6653aSJeff Kirsher frame_len -= ETH_FCS_LEN; 22917ac6653aSJeff Kirsher 229283d7af64SGiuseppe CAVALLARO if (netif_msg_rx_status(priv)) { 22937ac6653aSJeff Kirsher pr_debug("\tdesc: %p [entry %d] buff=0x%x\n", 22947ac6653aSJeff Kirsher p, entry, p->des2); 229583d7af64SGiuseppe CAVALLARO if (frame_len > ETH_FRAME_LEN) 229683d7af64SGiuseppe CAVALLARO pr_debug("\tframe size %d, COE: %d\n", 229783d7af64SGiuseppe CAVALLARO frame_len, status); 229883d7af64SGiuseppe CAVALLARO } 229922ad3838SGiuseppe Cavallaro 2300120e87f9SGiuseppe Cavallaro if (unlikely((frame_len < priv->rx_copybreak) || 2301120e87f9SGiuseppe Cavallaro stmmac_rx_threshold_count(priv))) { 230222ad3838SGiuseppe Cavallaro skb = netdev_alloc_skb_ip_align(priv->dev, 230322ad3838SGiuseppe Cavallaro frame_len); 230422ad3838SGiuseppe Cavallaro if (unlikely(!skb)) { 230522ad3838SGiuseppe Cavallaro if (net_ratelimit()) 230622ad3838SGiuseppe Cavallaro dev_warn(priv->device, 230722ad3838SGiuseppe Cavallaro "packet dropped\n"); 230822ad3838SGiuseppe Cavallaro priv->dev->stats.rx_dropped++; 230922ad3838SGiuseppe Cavallaro break; 231022ad3838SGiuseppe Cavallaro } 231122ad3838SGiuseppe Cavallaro 231222ad3838SGiuseppe Cavallaro dma_sync_single_for_cpu(priv->device, 231322ad3838SGiuseppe Cavallaro priv->rx_skbuff_dma 231422ad3838SGiuseppe Cavallaro [entry], frame_len, 231522ad3838SGiuseppe Cavallaro DMA_FROM_DEVICE); 231622ad3838SGiuseppe Cavallaro skb_copy_to_linear_data(skb, 231722ad3838SGiuseppe Cavallaro priv-> 231822ad3838SGiuseppe Cavallaro rx_skbuff[entry]->data, 231922ad3838SGiuseppe Cavallaro frame_len); 232022ad3838SGiuseppe Cavallaro 232122ad3838SGiuseppe Cavallaro skb_put(skb, frame_len); 232222ad3838SGiuseppe Cavallaro dma_sync_single_for_device(priv->device, 232322ad3838SGiuseppe Cavallaro priv->rx_skbuff_dma 232422ad3838SGiuseppe Cavallaro [entry], frame_len, 232522ad3838SGiuseppe Cavallaro DMA_FROM_DEVICE); 232622ad3838SGiuseppe Cavallaro } else { 23277ac6653aSJeff Kirsher skb = priv->rx_skbuff[entry]; 23287ac6653aSJeff Kirsher if (unlikely(!skb)) { 232922ad3838SGiuseppe Cavallaro pr_err("%s: Inconsistent Rx chain\n", 23307ac6653aSJeff Kirsher priv->dev->name); 23317ac6653aSJeff Kirsher priv->dev->stats.rx_dropped++; 23327ac6653aSJeff Kirsher break; 23337ac6653aSJeff Kirsher } 23347ac6653aSJeff Kirsher prefetch(skb->data - NET_IP_ALIGN); 23357ac6653aSJeff Kirsher priv->rx_skbuff[entry] = NULL; 2336120e87f9SGiuseppe Cavallaro priv->rx_zeroc_thresh++; 23377ac6653aSJeff Kirsher 23387ac6653aSJeff Kirsher skb_put(skb, frame_len); 23397ac6653aSJeff Kirsher dma_unmap_single(priv->device, 23407ac6653aSJeff Kirsher priv->rx_skbuff_dma[entry], 234122ad3838SGiuseppe Cavallaro priv->dma_buf_sz, 234222ad3838SGiuseppe Cavallaro DMA_FROM_DEVICE); 234322ad3838SGiuseppe Cavallaro } 234422ad3838SGiuseppe Cavallaro 234522ad3838SGiuseppe Cavallaro stmmac_get_rx_hwtstamp(priv, entry, skb); 234683d7af64SGiuseppe CAVALLARO 23477ac6653aSJeff Kirsher if (netif_msg_pktdata(priv)) { 234883d7af64SGiuseppe CAVALLARO pr_debug("frame received (%dbytes)", frame_len); 23497ac6653aSJeff Kirsher print_pkt(skb->data, frame_len); 23507ac6653aSJeff Kirsher } 235183d7af64SGiuseppe CAVALLARO 2352b9381985SVince Bridgers stmmac_rx_vlan(priv->dev, skb); 2353b9381985SVince Bridgers 23547ac6653aSJeff Kirsher skb->protocol = eth_type_trans(skb, priv->dev); 23557ac6653aSJeff Kirsher 2356ceb69499SGiuseppe CAVALLARO if (unlikely(!coe)) 23577ac6653aSJeff Kirsher skb_checksum_none_assert(skb); 235862a2ab93SGiuseppe CAVALLARO else 23597ac6653aSJeff Kirsher skb->ip_summed = CHECKSUM_UNNECESSARY; 236062a2ab93SGiuseppe CAVALLARO 23617ac6653aSJeff Kirsher napi_gro_receive(&priv->napi, skb); 23627ac6653aSJeff Kirsher 23637ac6653aSJeff Kirsher priv->dev->stats.rx_packets++; 23647ac6653aSJeff Kirsher priv->dev->stats.rx_bytes += frame_len; 23657ac6653aSJeff Kirsher } 23667ac6653aSJeff Kirsher entry = next_entry; 23677ac6653aSJeff Kirsher } 23687ac6653aSJeff Kirsher 23697ac6653aSJeff Kirsher stmmac_rx_refill(priv); 23707ac6653aSJeff Kirsher 23717ac6653aSJeff Kirsher priv->xstats.rx_pkt_n += count; 23727ac6653aSJeff Kirsher 23737ac6653aSJeff Kirsher return count; 23747ac6653aSJeff Kirsher } 23757ac6653aSJeff Kirsher 23767ac6653aSJeff Kirsher /** 23777ac6653aSJeff Kirsher * stmmac_poll - stmmac poll method (NAPI) 23787ac6653aSJeff Kirsher * @napi : pointer to the napi structure. 23797ac6653aSJeff Kirsher * @budget : maximum number of packets that the current CPU can receive from 23807ac6653aSJeff Kirsher * all interfaces. 23817ac6653aSJeff Kirsher * Description : 23829125cdd1SGiuseppe CAVALLARO * To look at the incoming frames and clear the tx resources. 23837ac6653aSJeff Kirsher */ 23847ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget) 23857ac6653aSJeff Kirsher { 23867ac6653aSJeff Kirsher struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi); 23877ac6653aSJeff Kirsher int work_done = 0; 23887ac6653aSJeff Kirsher 23899125cdd1SGiuseppe CAVALLARO priv->xstats.napi_poll++; 23909125cdd1SGiuseppe CAVALLARO stmmac_tx_clean(priv); 23917ac6653aSJeff Kirsher 23929125cdd1SGiuseppe CAVALLARO work_done = stmmac_rx(priv, budget); 23937ac6653aSJeff Kirsher if (work_done < budget) { 23947ac6653aSJeff Kirsher napi_complete(napi); 23959125cdd1SGiuseppe CAVALLARO stmmac_enable_dma_irq(priv); 23967ac6653aSJeff Kirsher } 23977ac6653aSJeff Kirsher return work_done; 23987ac6653aSJeff Kirsher } 23997ac6653aSJeff Kirsher 24007ac6653aSJeff Kirsher /** 24017ac6653aSJeff Kirsher * stmmac_tx_timeout 24027ac6653aSJeff Kirsher * @dev : Pointer to net device structure 24037ac6653aSJeff Kirsher * Description: this function is called when a packet transmission fails to 24047284a3f1SGiuseppe CAVALLARO * complete within a reasonable time. The driver will mark the error in the 24057ac6653aSJeff Kirsher * netdev structure and arrange for the device to be reset to a sane state 24067ac6653aSJeff Kirsher * in order to transmit a new packet. 24077ac6653aSJeff Kirsher */ 24087ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev) 24097ac6653aSJeff Kirsher { 24107ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 24117ac6653aSJeff Kirsher 24127ac6653aSJeff Kirsher /* Clear Tx resources and restart transmitting again */ 24137ac6653aSJeff Kirsher stmmac_tx_err(priv); 24147ac6653aSJeff Kirsher } 24157ac6653aSJeff Kirsher 24167ac6653aSJeff Kirsher /** 241701789349SJiri Pirko * stmmac_set_rx_mode - entry point for multicast addressing 24187ac6653aSJeff Kirsher * @dev : pointer to the device structure 24197ac6653aSJeff Kirsher * Description: 24207ac6653aSJeff Kirsher * This function is a driver entry point which gets called by the kernel 24217ac6653aSJeff Kirsher * whenever multicast addresses must be enabled/disabled. 24227ac6653aSJeff Kirsher * Return value: 24237ac6653aSJeff Kirsher * void. 24247ac6653aSJeff Kirsher */ 242501789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev) 24267ac6653aSJeff Kirsher { 24277ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 24287ac6653aSJeff Kirsher 24293b57de95SVince Bridgers priv->hw->mac->set_filter(priv->hw, dev); 24307ac6653aSJeff Kirsher } 24317ac6653aSJeff Kirsher 24327ac6653aSJeff Kirsher /** 24337ac6653aSJeff Kirsher * stmmac_change_mtu - entry point to change MTU size for the device. 24347ac6653aSJeff Kirsher * @dev : device pointer. 24357ac6653aSJeff Kirsher * @new_mtu : the new MTU size for the device. 24367ac6653aSJeff Kirsher * Description: the Maximum Transfer Unit (MTU) is used by the network layer 24377ac6653aSJeff Kirsher * to drive packet transmission. Ethernet has an MTU of 1500 octets 24387ac6653aSJeff Kirsher * (ETH_DATA_LEN). This value can be changed with ifconfig. 24397ac6653aSJeff Kirsher * Return value: 24407ac6653aSJeff Kirsher * 0 on success and an appropriate (-)ve integer as defined in errno.h 24417ac6653aSJeff Kirsher * file on failure. 24427ac6653aSJeff Kirsher */ 24437ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu) 24447ac6653aSJeff Kirsher { 24457ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 24467ac6653aSJeff Kirsher int max_mtu; 24477ac6653aSJeff Kirsher 24487ac6653aSJeff Kirsher if (netif_running(dev)) { 24497ac6653aSJeff Kirsher pr_err("%s: must be stopped to change its MTU\n", dev->name); 24507ac6653aSJeff Kirsher return -EBUSY; 24517ac6653aSJeff Kirsher } 24527ac6653aSJeff Kirsher 245348febf7eSGiuseppe CAVALLARO if (priv->plat->enh_desc) 24547ac6653aSJeff Kirsher max_mtu = JUMBO_LEN; 24557ac6653aSJeff Kirsher else 245645db81e1SGiuseppe CAVALLARO max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN); 24577ac6653aSJeff Kirsher 24582618abb7SVince Bridgers if (priv->plat->maxmtu < max_mtu) 24592618abb7SVince Bridgers max_mtu = priv->plat->maxmtu; 24602618abb7SVince Bridgers 24617ac6653aSJeff Kirsher if ((new_mtu < 46) || (new_mtu > max_mtu)) { 24627ac6653aSJeff Kirsher pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu); 24637ac6653aSJeff Kirsher return -EINVAL; 24647ac6653aSJeff Kirsher } 24657ac6653aSJeff Kirsher 24667ac6653aSJeff Kirsher dev->mtu = new_mtu; 24677ac6653aSJeff Kirsher netdev_update_features(dev); 24687ac6653aSJeff Kirsher 24697ac6653aSJeff Kirsher return 0; 24707ac6653aSJeff Kirsher } 24717ac6653aSJeff Kirsher 2472c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev, 2473c8f44affSMichał Mirosław netdev_features_t features) 24747ac6653aSJeff Kirsher { 24757ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 24767ac6653aSJeff Kirsher 247738912bdbSDeepak SIKRI if (priv->plat->rx_coe == STMMAC_RX_COE_NONE) 24787ac6653aSJeff Kirsher features &= ~NETIF_F_RXCSUM; 2479d2afb5bdSGiuseppe CAVALLARO 24807ac6653aSJeff Kirsher if (!priv->plat->tx_coe) 2481a188222bSTom Herbert features &= ~NETIF_F_CSUM_MASK; 24827ac6653aSJeff Kirsher 24837ac6653aSJeff Kirsher /* Some GMAC devices have a bugged Jumbo frame support that 24847ac6653aSJeff Kirsher * needs to have the Tx COE disabled for oversized frames 24857ac6653aSJeff Kirsher * (due to limited buffer sizes). In this case we disable 2486ceb69499SGiuseppe CAVALLARO * the TX csum insertionin the TDES and not use SF. 2487ceb69499SGiuseppe CAVALLARO */ 24887ac6653aSJeff Kirsher if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN)) 2489a188222bSTom Herbert features &= ~NETIF_F_CSUM_MASK; 24907ac6653aSJeff Kirsher 24917ac6653aSJeff Kirsher return features; 24927ac6653aSJeff Kirsher } 24937ac6653aSJeff Kirsher 2494d2afb5bdSGiuseppe CAVALLARO static int stmmac_set_features(struct net_device *netdev, 2495d2afb5bdSGiuseppe CAVALLARO netdev_features_t features) 2496d2afb5bdSGiuseppe CAVALLARO { 2497d2afb5bdSGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(netdev); 2498d2afb5bdSGiuseppe CAVALLARO 2499d2afb5bdSGiuseppe CAVALLARO /* Keep the COE Type in case of csum is supporting */ 2500d2afb5bdSGiuseppe CAVALLARO if (features & NETIF_F_RXCSUM) 2501d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = priv->plat->rx_coe; 2502d2afb5bdSGiuseppe CAVALLARO else 2503d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = 0; 2504d2afb5bdSGiuseppe CAVALLARO /* No check needed because rx_coe has been set before and it will be 2505d2afb5bdSGiuseppe CAVALLARO * fixed in case of issue. 2506d2afb5bdSGiuseppe CAVALLARO */ 2507d2afb5bdSGiuseppe CAVALLARO priv->hw->mac->rx_ipc(priv->hw); 2508d2afb5bdSGiuseppe CAVALLARO 2509d2afb5bdSGiuseppe CAVALLARO return 0; 2510d2afb5bdSGiuseppe CAVALLARO } 2511d2afb5bdSGiuseppe CAVALLARO 251232ceabcaSGiuseppe CAVALLARO /** 251332ceabcaSGiuseppe CAVALLARO * stmmac_interrupt - main ISR 251432ceabcaSGiuseppe CAVALLARO * @irq: interrupt number. 251532ceabcaSGiuseppe CAVALLARO * @dev_id: to pass the net device pointer. 251632ceabcaSGiuseppe CAVALLARO * Description: this is the main driver interrupt service routine. 2517732fdf0eSGiuseppe CAVALLARO * It can call: 2518732fdf0eSGiuseppe CAVALLARO * o DMA service routine (to manage incoming frame reception and transmission 2519732fdf0eSGiuseppe CAVALLARO * status) 2520732fdf0eSGiuseppe CAVALLARO * o Core interrupts to manage: remote wake-up, management counter, LPI 252132ceabcaSGiuseppe CAVALLARO * interrupts. 252232ceabcaSGiuseppe CAVALLARO */ 25237ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id) 25247ac6653aSJeff Kirsher { 25257ac6653aSJeff Kirsher struct net_device *dev = (struct net_device *)dev_id; 25267ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 25277ac6653aSJeff Kirsher 252889f7f2cfSSrinivas Kandagatla if (priv->irq_wake) 252989f7f2cfSSrinivas Kandagatla pm_wakeup_event(priv->device, 0); 253089f7f2cfSSrinivas Kandagatla 25317ac6653aSJeff Kirsher if (unlikely(!dev)) { 25327ac6653aSJeff Kirsher pr_err("%s: invalid dev pointer\n", __func__); 25337ac6653aSJeff Kirsher return IRQ_NONE; 25347ac6653aSJeff Kirsher } 25357ac6653aSJeff Kirsher 25367ac6653aSJeff Kirsher /* To handle GMAC own interrupts */ 2537d765955dSGiuseppe CAVALLARO if (priv->plat->has_gmac) { 25387ed24bbeSVince Bridgers int status = priv->hw->mac->host_irq_status(priv->hw, 25390982a0f6SGiuseppe CAVALLARO &priv->xstats); 2540d765955dSGiuseppe CAVALLARO if (unlikely(status)) { 2541d765955dSGiuseppe CAVALLARO /* For LPI we need to save the tx status */ 25420982a0f6SGiuseppe CAVALLARO if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE) 2543d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = true; 25440982a0f6SGiuseppe CAVALLARO if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE) 2545d765955dSGiuseppe CAVALLARO priv->tx_path_in_lpi_mode = false; 2546d765955dSGiuseppe CAVALLARO } 2547d765955dSGiuseppe CAVALLARO } 2548d765955dSGiuseppe CAVALLARO 2549d765955dSGiuseppe CAVALLARO /* To handle DMA interrupts */ 25507ac6653aSJeff Kirsher stmmac_dma_interrupt(priv); 25517ac6653aSJeff Kirsher 25527ac6653aSJeff Kirsher return IRQ_HANDLED; 25537ac6653aSJeff Kirsher } 25547ac6653aSJeff Kirsher 25557ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 25567ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools 2557ceb69499SGiuseppe CAVALLARO * to allow network I/O with interrupts disabled. 2558ceb69499SGiuseppe CAVALLARO */ 25597ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev) 25607ac6653aSJeff Kirsher { 25617ac6653aSJeff Kirsher disable_irq(dev->irq); 25627ac6653aSJeff Kirsher stmmac_interrupt(dev->irq, dev); 25637ac6653aSJeff Kirsher enable_irq(dev->irq); 25647ac6653aSJeff Kirsher } 25657ac6653aSJeff Kirsher #endif 25667ac6653aSJeff Kirsher 25677ac6653aSJeff Kirsher /** 25687ac6653aSJeff Kirsher * stmmac_ioctl - Entry point for the Ioctl 25697ac6653aSJeff Kirsher * @dev: Device pointer. 25707ac6653aSJeff Kirsher * @rq: An IOCTL specefic structure, that can contain a pointer to 25717ac6653aSJeff Kirsher * a proprietary structure used to pass information to the driver. 25727ac6653aSJeff Kirsher * @cmd: IOCTL command 25737ac6653aSJeff Kirsher * Description: 257432ceabcaSGiuseppe CAVALLARO * Currently it supports the phy_mii_ioctl(...) and HW time stamping. 25757ac6653aSJeff Kirsher */ 25767ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 25777ac6653aSJeff Kirsher { 25787ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(dev); 2579891434b1SRayagond Kokatanur int ret = -EOPNOTSUPP; 25807ac6653aSJeff Kirsher 25817ac6653aSJeff Kirsher if (!netif_running(dev)) 25827ac6653aSJeff Kirsher return -EINVAL; 25837ac6653aSJeff Kirsher 2584891434b1SRayagond Kokatanur switch (cmd) { 2585891434b1SRayagond Kokatanur case SIOCGMIIPHY: 2586891434b1SRayagond Kokatanur case SIOCGMIIREG: 2587891434b1SRayagond Kokatanur case SIOCSMIIREG: 25887ac6653aSJeff Kirsher if (!priv->phydev) 25897ac6653aSJeff Kirsher return -EINVAL; 25907ac6653aSJeff Kirsher ret = phy_mii_ioctl(priv->phydev, rq, cmd); 2591891434b1SRayagond Kokatanur break; 2592891434b1SRayagond Kokatanur case SIOCSHWTSTAMP: 2593891434b1SRayagond Kokatanur ret = stmmac_hwtstamp_ioctl(dev, rq); 2594891434b1SRayagond Kokatanur break; 2595891434b1SRayagond Kokatanur default: 2596891434b1SRayagond Kokatanur break; 2597891434b1SRayagond Kokatanur } 25987ac6653aSJeff Kirsher 25997ac6653aSJeff Kirsher return ret; 26007ac6653aSJeff Kirsher } 26017ac6653aSJeff Kirsher 260250fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS 26037ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir; 26047ac29055SGiuseppe CAVALLARO 2605c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc, 2606c24602efSGiuseppe CAVALLARO struct seq_file *seq) 26077ac29055SGiuseppe CAVALLARO { 26087ac29055SGiuseppe CAVALLARO int i; 2609c24602efSGiuseppe CAVALLARO struct dma_extended_desc *ep = (struct dma_extended_desc *)head; 2610c24602efSGiuseppe CAVALLARO struct dma_desc *p = (struct dma_desc *)head; 26117ac29055SGiuseppe CAVALLARO 2612c24602efSGiuseppe CAVALLARO for (i = 0; i < size; i++) { 2613c24602efSGiuseppe CAVALLARO u64 x; 2614c24602efSGiuseppe CAVALLARO if (extend_desc) { 2615c24602efSGiuseppe CAVALLARO x = *(u64 *) ep; 2616c24602efSGiuseppe CAVALLARO seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 2617c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 2618c24602efSGiuseppe CAVALLARO (unsigned int)x, (unsigned int)(x >> 32), 2619c24602efSGiuseppe CAVALLARO ep->basic.des2, ep->basic.des3); 2620c24602efSGiuseppe CAVALLARO ep++; 2621c24602efSGiuseppe CAVALLARO } else { 2622c24602efSGiuseppe CAVALLARO x = *(u64 *) p; 2623c24602efSGiuseppe CAVALLARO seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n", 2624c24602efSGiuseppe CAVALLARO i, (unsigned int)virt_to_phys(ep), 2625c24602efSGiuseppe CAVALLARO (unsigned int)x, (unsigned int)(x >> 32), 2626c24602efSGiuseppe CAVALLARO p->des2, p->des3); 2627c24602efSGiuseppe CAVALLARO p++; 2628c24602efSGiuseppe CAVALLARO } 26297ac29055SGiuseppe CAVALLARO seq_printf(seq, "\n"); 26307ac29055SGiuseppe CAVALLARO } 2631c24602efSGiuseppe CAVALLARO } 26327ac29055SGiuseppe CAVALLARO 2633c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v) 2634c24602efSGiuseppe CAVALLARO { 2635c24602efSGiuseppe CAVALLARO struct net_device *dev = seq->private; 2636c24602efSGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(dev); 26377ac29055SGiuseppe CAVALLARO 2638c24602efSGiuseppe CAVALLARO if (priv->extend_desc) { 2639c24602efSGiuseppe CAVALLARO seq_printf(seq, "Extended RX descriptor ring:\n"); 2640e3ad57c9SGiuseppe Cavallaro sysfs_display_ring((void *)priv->dma_erx, DMA_RX_SIZE, 1, seq); 2641c24602efSGiuseppe CAVALLARO seq_printf(seq, "Extended TX descriptor ring:\n"); 2642e3ad57c9SGiuseppe Cavallaro sysfs_display_ring((void *)priv->dma_etx, DMA_TX_SIZE, 1, seq); 2643c24602efSGiuseppe CAVALLARO } else { 2644c24602efSGiuseppe CAVALLARO seq_printf(seq, "RX descriptor ring:\n"); 2645e3ad57c9SGiuseppe Cavallaro sysfs_display_ring((void *)priv->dma_rx, DMA_RX_SIZE, 0, seq); 2646c24602efSGiuseppe CAVALLARO seq_printf(seq, "TX descriptor ring:\n"); 2647e3ad57c9SGiuseppe Cavallaro sysfs_display_ring((void *)priv->dma_tx, DMA_TX_SIZE, 0, seq); 26487ac29055SGiuseppe CAVALLARO } 26497ac29055SGiuseppe CAVALLARO 26507ac29055SGiuseppe CAVALLARO return 0; 26517ac29055SGiuseppe CAVALLARO } 26527ac29055SGiuseppe CAVALLARO 26537ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file) 26547ac29055SGiuseppe CAVALLARO { 26557ac29055SGiuseppe CAVALLARO return single_open(file, stmmac_sysfs_ring_read, inode->i_private); 26567ac29055SGiuseppe CAVALLARO } 26577ac29055SGiuseppe CAVALLARO 26587ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = { 26597ac29055SGiuseppe CAVALLARO .owner = THIS_MODULE, 26607ac29055SGiuseppe CAVALLARO .open = stmmac_sysfs_ring_open, 26617ac29055SGiuseppe CAVALLARO .read = seq_read, 26627ac29055SGiuseppe CAVALLARO .llseek = seq_lseek, 266374863948SDjalal Harouni .release = single_release, 26647ac29055SGiuseppe CAVALLARO }; 26657ac29055SGiuseppe CAVALLARO 2666e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v) 2667e7434821SGiuseppe CAVALLARO { 2668e7434821SGiuseppe CAVALLARO struct net_device *dev = seq->private; 2669e7434821SGiuseppe CAVALLARO struct stmmac_priv *priv = netdev_priv(dev); 2670e7434821SGiuseppe CAVALLARO 267119e30c14SGiuseppe CAVALLARO if (!priv->hw_cap_support) { 2672e7434821SGiuseppe CAVALLARO seq_printf(seq, "DMA HW features not supported\n"); 2673e7434821SGiuseppe CAVALLARO return 0; 2674e7434821SGiuseppe CAVALLARO } 2675e7434821SGiuseppe CAVALLARO 2676e7434821SGiuseppe CAVALLARO seq_printf(seq, "==============================\n"); 2677e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tDMA HW features\n"); 2678e7434821SGiuseppe CAVALLARO seq_printf(seq, "==============================\n"); 2679e7434821SGiuseppe CAVALLARO 2680e7434821SGiuseppe CAVALLARO seq_printf(seq, "\t10/100 Mbps %s\n", 2681e7434821SGiuseppe CAVALLARO (priv->dma_cap.mbps_10_100) ? "Y" : "N"); 2682e7434821SGiuseppe CAVALLARO seq_printf(seq, "\t1000 Mbps %s\n", 2683e7434821SGiuseppe CAVALLARO (priv->dma_cap.mbps_1000) ? "Y" : "N"); 2684e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tHalf duple %s\n", 2685e7434821SGiuseppe CAVALLARO (priv->dma_cap.half_duplex) ? "Y" : "N"); 2686e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tHash Filter: %s\n", 2687e7434821SGiuseppe CAVALLARO (priv->dma_cap.hash_filter) ? "Y" : "N"); 2688e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tMultiple MAC address registers: %s\n", 2689e7434821SGiuseppe CAVALLARO (priv->dma_cap.multi_addr) ? "Y" : "N"); 2690e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n", 2691e7434821SGiuseppe CAVALLARO (priv->dma_cap.pcs) ? "Y" : "N"); 2692e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tSMA (MDIO) Interface: %s\n", 2693e7434821SGiuseppe CAVALLARO (priv->dma_cap.sma_mdio) ? "Y" : "N"); 2694e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPMT Remote wake up: %s\n", 2695e7434821SGiuseppe CAVALLARO (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N"); 2696e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tPMT Magic Frame: %s\n", 2697e7434821SGiuseppe CAVALLARO (priv->dma_cap.pmt_magic_frame) ? "Y" : "N"); 2698e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tRMON module: %s\n", 2699e7434821SGiuseppe CAVALLARO (priv->dma_cap.rmon) ? "Y" : "N"); 2700e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n", 2701e7434821SGiuseppe CAVALLARO (priv->dma_cap.time_stamp) ? "Y" : "N"); 2702e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n", 2703e7434821SGiuseppe CAVALLARO (priv->dma_cap.atime_stamp) ? "Y" : "N"); 2704e7434821SGiuseppe CAVALLARO seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n", 2705e7434821SGiuseppe CAVALLARO (priv->dma_cap.eee) ? "Y" : "N"); 2706e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N"); 2707e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tChecksum Offload in TX: %s\n", 2708e7434821SGiuseppe CAVALLARO (priv->dma_cap.tx_coe) ? "Y" : "N"); 2709e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n", 2710e7434821SGiuseppe CAVALLARO (priv->dma_cap.rx_coe_type1) ? "Y" : "N"); 2711e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n", 2712e7434821SGiuseppe CAVALLARO (priv->dma_cap.rx_coe_type2) ? "Y" : "N"); 2713e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n", 2714e7434821SGiuseppe CAVALLARO (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N"); 2715e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tNumber of Additional RX channel: %d\n", 2716e7434821SGiuseppe CAVALLARO priv->dma_cap.number_rx_channel); 2717e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tNumber of Additional TX channel: %d\n", 2718e7434821SGiuseppe CAVALLARO priv->dma_cap.number_tx_channel); 2719e7434821SGiuseppe CAVALLARO seq_printf(seq, "\tEnhanced descriptors: %s\n", 2720e7434821SGiuseppe CAVALLARO (priv->dma_cap.enh_desc) ? "Y" : "N"); 2721e7434821SGiuseppe CAVALLARO 2722e7434821SGiuseppe CAVALLARO return 0; 2723e7434821SGiuseppe CAVALLARO } 2724e7434821SGiuseppe CAVALLARO 2725e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file) 2726e7434821SGiuseppe CAVALLARO { 2727e7434821SGiuseppe CAVALLARO return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private); 2728e7434821SGiuseppe CAVALLARO } 2729e7434821SGiuseppe CAVALLARO 2730e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = { 2731e7434821SGiuseppe CAVALLARO .owner = THIS_MODULE, 2732e7434821SGiuseppe CAVALLARO .open = stmmac_sysfs_dma_cap_open, 2733e7434821SGiuseppe CAVALLARO .read = seq_read, 2734e7434821SGiuseppe CAVALLARO .llseek = seq_lseek, 273574863948SDjalal Harouni .release = single_release, 2736e7434821SGiuseppe CAVALLARO }; 2737e7434821SGiuseppe CAVALLARO 27387ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev) 27397ac29055SGiuseppe CAVALLARO { 2740466c5ac8SMathieu Olivari struct stmmac_priv *priv = netdev_priv(dev); 27417ac29055SGiuseppe CAVALLARO 2742466c5ac8SMathieu Olivari /* Create per netdev entries */ 2743466c5ac8SMathieu Olivari priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir); 2744466c5ac8SMathieu Olivari 2745466c5ac8SMathieu Olivari if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) { 2746466c5ac8SMathieu Olivari pr_err("ERROR %s/%s, debugfs create directory failed\n", 2747466c5ac8SMathieu Olivari STMMAC_RESOURCE_NAME, dev->name); 27487ac29055SGiuseppe CAVALLARO 27497ac29055SGiuseppe CAVALLARO return -ENOMEM; 27507ac29055SGiuseppe CAVALLARO } 27517ac29055SGiuseppe CAVALLARO 27527ac29055SGiuseppe CAVALLARO /* Entry to report DMA RX/TX rings */ 2753466c5ac8SMathieu Olivari priv->dbgfs_rings_status = 2754466c5ac8SMathieu Olivari debugfs_create_file("descriptors_status", S_IRUGO, 2755466c5ac8SMathieu Olivari priv->dbgfs_dir, dev, 27567ac29055SGiuseppe CAVALLARO &stmmac_rings_status_fops); 27577ac29055SGiuseppe CAVALLARO 2758466c5ac8SMathieu Olivari if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) { 27597ac29055SGiuseppe CAVALLARO pr_info("ERROR creating stmmac ring debugfs file\n"); 2760466c5ac8SMathieu Olivari debugfs_remove_recursive(priv->dbgfs_dir); 27617ac29055SGiuseppe CAVALLARO 27627ac29055SGiuseppe CAVALLARO return -ENOMEM; 27637ac29055SGiuseppe CAVALLARO } 27647ac29055SGiuseppe CAVALLARO 2765e7434821SGiuseppe CAVALLARO /* Entry to report the DMA HW features */ 2766466c5ac8SMathieu Olivari priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, 2767466c5ac8SMathieu Olivari priv->dbgfs_dir, 2768e7434821SGiuseppe CAVALLARO dev, &stmmac_dma_cap_fops); 2769e7434821SGiuseppe CAVALLARO 2770466c5ac8SMathieu Olivari if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) { 2771e7434821SGiuseppe CAVALLARO pr_info("ERROR creating stmmac MMC debugfs file\n"); 2772466c5ac8SMathieu Olivari debugfs_remove_recursive(priv->dbgfs_dir); 2773e7434821SGiuseppe CAVALLARO 2774e7434821SGiuseppe CAVALLARO return -ENOMEM; 2775e7434821SGiuseppe CAVALLARO } 2776e7434821SGiuseppe CAVALLARO 27777ac29055SGiuseppe CAVALLARO return 0; 27787ac29055SGiuseppe CAVALLARO } 27797ac29055SGiuseppe CAVALLARO 2780466c5ac8SMathieu Olivari static void stmmac_exit_fs(struct net_device *dev) 27817ac29055SGiuseppe CAVALLARO { 2782466c5ac8SMathieu Olivari struct stmmac_priv *priv = netdev_priv(dev); 2783466c5ac8SMathieu Olivari 2784466c5ac8SMathieu Olivari debugfs_remove_recursive(priv->dbgfs_dir); 27857ac29055SGiuseppe CAVALLARO } 278650fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */ 27877ac29055SGiuseppe CAVALLARO 27887ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = { 27897ac6653aSJeff Kirsher .ndo_open = stmmac_open, 27907ac6653aSJeff Kirsher .ndo_start_xmit = stmmac_xmit, 27917ac6653aSJeff Kirsher .ndo_stop = stmmac_release, 27927ac6653aSJeff Kirsher .ndo_change_mtu = stmmac_change_mtu, 27937ac6653aSJeff Kirsher .ndo_fix_features = stmmac_fix_features, 2794d2afb5bdSGiuseppe CAVALLARO .ndo_set_features = stmmac_set_features, 279501789349SJiri Pirko .ndo_set_rx_mode = stmmac_set_rx_mode, 27967ac6653aSJeff Kirsher .ndo_tx_timeout = stmmac_tx_timeout, 27977ac6653aSJeff Kirsher .ndo_do_ioctl = stmmac_ioctl, 27987ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER 27997ac6653aSJeff Kirsher .ndo_poll_controller = stmmac_poll_controller, 28007ac6653aSJeff Kirsher #endif 28017ac6653aSJeff Kirsher .ndo_set_mac_address = eth_mac_addr, 28027ac6653aSJeff Kirsher }; 28037ac6653aSJeff Kirsher 28047ac6653aSJeff Kirsher /** 2805cf3f047bSGiuseppe CAVALLARO * stmmac_hw_init - Init the MAC device 280632ceabcaSGiuseppe CAVALLARO * @priv: driver private structure 2807732fdf0eSGiuseppe CAVALLARO * Description: this function is to configure the MAC device according to 2808732fdf0eSGiuseppe CAVALLARO * some platform parameters or the HW capability register. It prepares the 2809732fdf0eSGiuseppe CAVALLARO * driver to use either ring or chain modes and to setup either enhanced or 2810732fdf0eSGiuseppe CAVALLARO * normal descriptors. 2811cf3f047bSGiuseppe CAVALLARO */ 2812cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv) 2813cf3f047bSGiuseppe CAVALLARO { 2814cf3f047bSGiuseppe CAVALLARO struct mac_device_info *mac; 2815cf3f047bSGiuseppe CAVALLARO 2816cf3f047bSGiuseppe CAVALLARO /* Identify the MAC HW device */ 281703f2eecdSMarc Kleine-Budde if (priv->plat->has_gmac) { 281803f2eecdSMarc Kleine-Budde priv->dev->priv_flags |= IFF_UNICAST_FLT; 28193b57de95SVince Bridgers mac = dwmac1000_setup(priv->ioaddr, 28203b57de95SVince Bridgers priv->plat->multicast_filter_bins, 28213b57de95SVince Bridgers priv->plat->unicast_filter_entries); 282203f2eecdSMarc Kleine-Budde } else { 2823cf3f047bSGiuseppe CAVALLARO mac = dwmac100_setup(priv->ioaddr); 282403f2eecdSMarc Kleine-Budde } 2825cf3f047bSGiuseppe CAVALLARO if (!mac) 2826cf3f047bSGiuseppe CAVALLARO return -ENOMEM; 2827cf3f047bSGiuseppe CAVALLARO 2828cf3f047bSGiuseppe CAVALLARO priv->hw = mac; 2829cf3f047bSGiuseppe CAVALLARO 2830cf3f047bSGiuseppe CAVALLARO /* Get and dump the chip ID */ 2831cffb13f4SGiuseppe CAVALLARO priv->synopsys_id = stmmac_get_synopsys_id(priv); 2832cf3f047bSGiuseppe CAVALLARO 28334a7d666aSGiuseppe CAVALLARO /* To use the chained or ring mode */ 28344a7d666aSGiuseppe CAVALLARO if (chain_mode) { 283529896a67SGiuseppe CAVALLARO priv->hw->mode = &chain_mode_ops; 28364a7d666aSGiuseppe CAVALLARO pr_info(" Chain mode enabled\n"); 28374a7d666aSGiuseppe CAVALLARO priv->mode = STMMAC_CHAIN_MODE; 28384a7d666aSGiuseppe CAVALLARO } else { 283929896a67SGiuseppe CAVALLARO priv->hw->mode = &ring_mode_ops; 28404a7d666aSGiuseppe CAVALLARO pr_info(" Ring mode enabled\n"); 28414a7d666aSGiuseppe CAVALLARO priv->mode = STMMAC_RING_MODE; 28424a7d666aSGiuseppe CAVALLARO } 28434a7d666aSGiuseppe CAVALLARO 2844cf3f047bSGiuseppe CAVALLARO /* Get the HW capability (new GMAC newer than 3.50a) */ 2845cf3f047bSGiuseppe CAVALLARO priv->hw_cap_support = stmmac_get_hw_features(priv); 2846cf3f047bSGiuseppe CAVALLARO if (priv->hw_cap_support) { 2847cf3f047bSGiuseppe CAVALLARO pr_info(" DMA HW capability register supported"); 2848cf3f047bSGiuseppe CAVALLARO 2849cf3f047bSGiuseppe CAVALLARO /* We can override some gmac/dma configuration fields: e.g. 2850cf3f047bSGiuseppe CAVALLARO * enh_desc, tx_coe (e.g. that are passed through the 2851cf3f047bSGiuseppe CAVALLARO * platform) with the values from the HW capability 2852cf3f047bSGiuseppe CAVALLARO * register (if supported). 2853cf3f047bSGiuseppe CAVALLARO */ 2854cf3f047bSGiuseppe CAVALLARO priv->plat->enh_desc = priv->dma_cap.enh_desc; 2855cf3f047bSGiuseppe CAVALLARO priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; 285638912bdbSDeepak SIKRI 2857dec2165fSSonic Zhang /* TXCOE doesn't work in thresh DMA mode */ 2858dec2165fSSonic Zhang if (priv->plat->force_thresh_dma_mode) 2859dec2165fSSonic Zhang priv->plat->tx_coe = 0; 2860dec2165fSSonic Zhang else 286138912bdbSDeepak SIKRI priv->plat->tx_coe = priv->dma_cap.tx_coe; 286238912bdbSDeepak SIKRI 286338912bdbSDeepak SIKRI if (priv->dma_cap.rx_coe_type2) 286438912bdbSDeepak SIKRI priv->plat->rx_coe = STMMAC_RX_COE_TYPE2; 286538912bdbSDeepak SIKRI else if (priv->dma_cap.rx_coe_type1) 286638912bdbSDeepak SIKRI priv->plat->rx_coe = STMMAC_RX_COE_TYPE1; 286738912bdbSDeepak SIKRI 2868cf3f047bSGiuseppe CAVALLARO } else 2869cf3f047bSGiuseppe CAVALLARO pr_info(" No HW DMA feature register supported"); 2870cf3f047bSGiuseppe CAVALLARO 287161369d02SByungho An /* To use alternate (extended) or normal descriptor structures */ 287261369d02SByungho An stmmac_selec_desc_mode(priv); 287361369d02SByungho An 2874d2afb5bdSGiuseppe CAVALLARO if (priv->plat->rx_coe) { 2875d2afb5bdSGiuseppe CAVALLARO priv->hw->rx_csum = priv->plat->rx_coe; 287638912bdbSDeepak SIKRI pr_info(" RX Checksum Offload Engine supported (type %d)\n", 287738912bdbSDeepak SIKRI priv->plat->rx_coe); 2878d2afb5bdSGiuseppe CAVALLARO } 2879cf3f047bSGiuseppe CAVALLARO if (priv->plat->tx_coe) 2880cf3f047bSGiuseppe CAVALLARO pr_info(" TX Checksum insertion supported\n"); 2881cf3f047bSGiuseppe CAVALLARO 2882cf3f047bSGiuseppe CAVALLARO if (priv->plat->pmt) { 2883cf3f047bSGiuseppe CAVALLARO pr_info(" Wake-Up On Lan supported\n"); 2884cf3f047bSGiuseppe CAVALLARO device_set_wakeup_capable(priv->device, 1); 2885cf3f047bSGiuseppe CAVALLARO } 2886cf3f047bSGiuseppe CAVALLARO 2887c24602efSGiuseppe CAVALLARO return 0; 2888cf3f047bSGiuseppe CAVALLARO } 2889cf3f047bSGiuseppe CAVALLARO 2890cf3f047bSGiuseppe CAVALLARO /** 2891bfab27a1SGiuseppe CAVALLARO * stmmac_dvr_probe 2892bfab27a1SGiuseppe CAVALLARO * @device: device pointer 2893ff3dd78cSGiuseppe CAVALLARO * @plat_dat: platform data pointer 2894e56788cfSJoachim Eastwood * @res: stmmac resource pointer 2895bfab27a1SGiuseppe CAVALLARO * Description: this is the main probe function used to 2896bfab27a1SGiuseppe CAVALLARO * call the alloc_etherdev, allocate the priv structure. 28979afec6efSAndy Shevchenko * Return: 289815ffac73SJoachim Eastwood * returns 0 on success, otherwise errno. 28997ac6653aSJeff Kirsher */ 290015ffac73SJoachim Eastwood int stmmac_dvr_probe(struct device *device, 2901cf3f047bSGiuseppe CAVALLARO struct plat_stmmacenet_data *plat_dat, 2902e56788cfSJoachim Eastwood struct stmmac_resources *res) 29037ac6653aSJeff Kirsher { 29047ac6653aSJeff Kirsher int ret = 0; 2905bfab27a1SGiuseppe CAVALLARO struct net_device *ndev = NULL; 2906bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *priv; 29077ac6653aSJeff Kirsher 2908bfab27a1SGiuseppe CAVALLARO ndev = alloc_etherdev(sizeof(struct stmmac_priv)); 290941de8d4cSJoe Perches if (!ndev) 291015ffac73SJoachim Eastwood return -ENOMEM; 29117ac6653aSJeff Kirsher 2912bfab27a1SGiuseppe CAVALLARO SET_NETDEV_DEV(ndev, device); 29137ac6653aSJeff Kirsher 2914bfab27a1SGiuseppe CAVALLARO priv = netdev_priv(ndev); 2915bfab27a1SGiuseppe CAVALLARO priv->device = device; 2916bfab27a1SGiuseppe CAVALLARO priv->dev = ndev; 2917bfab27a1SGiuseppe CAVALLARO 2918bfab27a1SGiuseppe CAVALLARO stmmac_set_ethtool_ops(ndev); 2919cf3f047bSGiuseppe CAVALLARO priv->pause = pause; 2920cf3f047bSGiuseppe CAVALLARO priv->plat = plat_dat; 2921e56788cfSJoachim Eastwood priv->ioaddr = res->addr; 2922e56788cfSJoachim Eastwood priv->dev->base_addr = (unsigned long)res->addr; 2923e56788cfSJoachim Eastwood 2924e56788cfSJoachim Eastwood priv->dev->irq = res->irq; 2925e56788cfSJoachim Eastwood priv->wol_irq = res->wol_irq; 2926e56788cfSJoachim Eastwood priv->lpi_irq = res->lpi_irq; 2927e56788cfSJoachim Eastwood 2928e56788cfSJoachim Eastwood if (res->mac) 2929e56788cfSJoachim Eastwood memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN); 2930bfab27a1SGiuseppe CAVALLARO 2931a7a62685SJoachim Eastwood dev_set_drvdata(device, priv->dev); 2932803f8fc4SJoachim Eastwood 2933cf3f047bSGiuseppe CAVALLARO /* Verify driver arguments */ 2934cf3f047bSGiuseppe CAVALLARO stmmac_verify_args(); 2935cf3f047bSGiuseppe CAVALLARO 2936cf3f047bSGiuseppe CAVALLARO /* Override with kernel parameters if supplied XXX CRS XXX 2937ceb69499SGiuseppe CAVALLARO * this needs to have multiple instances 2938ceb69499SGiuseppe CAVALLARO */ 2939cf3f047bSGiuseppe CAVALLARO if ((phyaddr >= 0) && (phyaddr <= 31)) 2940cf3f047bSGiuseppe CAVALLARO priv->plat->phy_addr = phyaddr; 2941cf3f047bSGiuseppe CAVALLARO 294262866e98SChen-Yu Tsai priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME); 294362866e98SChen-Yu Tsai if (IS_ERR(priv->stmmac_clk)) { 294462866e98SChen-Yu Tsai dev_warn(priv->device, "%s: warning: cannot get CSR clock\n", 294562866e98SChen-Yu Tsai __func__); 2946c5bb86c3SKweh, Hock Leong /* If failed to obtain stmmac_clk and specific clk_csr value 2947c5bb86c3SKweh, Hock Leong * is NOT passed from the platform, probe fail. 2948c5bb86c3SKweh, Hock Leong */ 2949c5bb86c3SKweh, Hock Leong if (!priv->plat->clk_csr) { 2950c5e4ddbdSChen-Yu Tsai ret = PTR_ERR(priv->stmmac_clk); 295162866e98SChen-Yu Tsai goto error_clk_get; 2952c5bb86c3SKweh, Hock Leong } else { 2953c5bb86c3SKweh, Hock Leong priv->stmmac_clk = NULL; 2954c5bb86c3SKweh, Hock Leong } 295562866e98SChen-Yu Tsai } 295662866e98SChen-Yu Tsai clk_prepare_enable(priv->stmmac_clk); 295762866e98SChen-Yu Tsai 29585f9755d2SAndrew Bresticker priv->pclk = devm_clk_get(priv->device, "pclk"); 29595f9755d2SAndrew Bresticker if (IS_ERR(priv->pclk)) { 29605f9755d2SAndrew Bresticker if (PTR_ERR(priv->pclk) == -EPROBE_DEFER) { 29615f9755d2SAndrew Bresticker ret = -EPROBE_DEFER; 29625f9755d2SAndrew Bresticker goto error_pclk_get; 29635f9755d2SAndrew Bresticker } 29645f9755d2SAndrew Bresticker priv->pclk = NULL; 29655f9755d2SAndrew Bresticker } 29665f9755d2SAndrew Bresticker clk_prepare_enable(priv->pclk); 29675f9755d2SAndrew Bresticker 2968c5e4ddbdSChen-Yu Tsai priv->stmmac_rst = devm_reset_control_get(priv->device, 2969c5e4ddbdSChen-Yu Tsai STMMAC_RESOURCE_NAME); 2970c5e4ddbdSChen-Yu Tsai if (IS_ERR(priv->stmmac_rst)) { 2971c5e4ddbdSChen-Yu Tsai if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) { 2972c5e4ddbdSChen-Yu Tsai ret = -EPROBE_DEFER; 2973c5e4ddbdSChen-Yu Tsai goto error_hw_init; 2974c5e4ddbdSChen-Yu Tsai } 2975c5e4ddbdSChen-Yu Tsai dev_info(priv->device, "no reset control found\n"); 2976c5e4ddbdSChen-Yu Tsai priv->stmmac_rst = NULL; 2977c5e4ddbdSChen-Yu Tsai } 2978c5e4ddbdSChen-Yu Tsai if (priv->stmmac_rst) 2979c5e4ddbdSChen-Yu Tsai reset_control_deassert(priv->stmmac_rst); 2980c5e4ddbdSChen-Yu Tsai 2981cf3f047bSGiuseppe CAVALLARO /* Init MAC and get the capabilities */ 2982c24602efSGiuseppe CAVALLARO ret = stmmac_hw_init(priv); 2983c24602efSGiuseppe CAVALLARO if (ret) 298462866e98SChen-Yu Tsai goto error_hw_init; 2985cf3f047bSGiuseppe CAVALLARO 2986cf3f047bSGiuseppe CAVALLARO ndev->netdev_ops = &stmmac_netdev_ops; 2987cf3f047bSGiuseppe CAVALLARO 2988cf3f047bSGiuseppe CAVALLARO ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | 2989cf3f047bSGiuseppe CAVALLARO NETIF_F_RXCSUM; 2990bfab27a1SGiuseppe CAVALLARO ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA; 2991bfab27a1SGiuseppe CAVALLARO ndev->watchdog_timeo = msecs_to_jiffies(watchdog); 29927ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED 29937ac6653aSJeff Kirsher /* Both mac100 and gmac support receive VLAN tag detection */ 2994f646968fSPatrick McHardy ndev->features |= NETIF_F_HW_VLAN_CTAG_RX; 29957ac6653aSJeff Kirsher #endif 29967ac6653aSJeff Kirsher priv->msg_enable = netif_msg_init(debug, default_msg_level); 29977ac6653aSJeff Kirsher 29987ac6653aSJeff Kirsher if (flow_ctrl) 29997ac6653aSJeff Kirsher priv->flow_ctrl = FLOW_AUTO; /* RX/TX pause on */ 30007ac6653aSJeff Kirsher 300162a2ab93SGiuseppe CAVALLARO /* Rx Watchdog is available in the COREs newer than the 3.40. 300262a2ab93SGiuseppe CAVALLARO * In some case, for example on bugged HW this feature 300362a2ab93SGiuseppe CAVALLARO * has to be disable and this can be done by passing the 300462a2ab93SGiuseppe CAVALLARO * riwt_off field from the platform. 300562a2ab93SGiuseppe CAVALLARO */ 300662a2ab93SGiuseppe CAVALLARO if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) { 300762a2ab93SGiuseppe CAVALLARO priv->use_riwt = 1; 300862a2ab93SGiuseppe CAVALLARO pr_info(" Enable RX Mitigation via HW Watchdog Timer\n"); 300962a2ab93SGiuseppe CAVALLARO } 301062a2ab93SGiuseppe CAVALLARO 3011bfab27a1SGiuseppe CAVALLARO netif_napi_add(ndev, &priv->napi, stmmac_poll, 64); 30127ac6653aSJeff Kirsher 30137ac6653aSJeff Kirsher spin_lock_init(&priv->lock); 3014a9097a96SGiuseppe CAVALLARO spin_lock_init(&priv->tx_lock); 30157ac6653aSJeff Kirsher 3016bfab27a1SGiuseppe CAVALLARO ret = register_netdev(ndev); 30177ac6653aSJeff Kirsher if (ret) { 3018cf3f047bSGiuseppe CAVALLARO pr_err("%s: ERROR %i registering the device\n", __func__, ret); 30196a81c26fSViresh Kumar goto error_netdev_register; 30207ac6653aSJeff Kirsher } 30217ac6653aSJeff Kirsher 3022cd7201f4SGiuseppe CAVALLARO /* If a specific clk_csr value is passed from the platform 3023cd7201f4SGiuseppe CAVALLARO * this means that the CSR Clock Range selection cannot be 3024cd7201f4SGiuseppe CAVALLARO * changed at run-time and it is fixed. Viceversa the driver'll try to 3025cd7201f4SGiuseppe CAVALLARO * set the MDC clock dynamically according to the csr actual 3026cd7201f4SGiuseppe CAVALLARO * clock input. 3027cd7201f4SGiuseppe CAVALLARO */ 3028cd7201f4SGiuseppe CAVALLARO if (!priv->plat->clk_csr) 3029cd7201f4SGiuseppe CAVALLARO stmmac_clk_csr_set(priv); 3030cd7201f4SGiuseppe CAVALLARO else 3031cd7201f4SGiuseppe CAVALLARO priv->clk_csr = priv->plat->clk_csr; 3032cd7201f4SGiuseppe CAVALLARO 3033e58bb43fSGiuseppe CAVALLARO stmmac_check_pcs_mode(priv); 3034e58bb43fSGiuseppe CAVALLARO 30354d8f0825SByungho An if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 30364d8f0825SByungho An priv->pcs != STMMAC_PCS_RTBI) { 30374bfcbd7aSFrancesco Virlinzi /* MDIO bus Registration */ 30384bfcbd7aSFrancesco Virlinzi ret = stmmac_mdio_register(ndev); 30394bfcbd7aSFrancesco Virlinzi if (ret < 0) { 30404bfcbd7aSFrancesco Virlinzi pr_debug("%s: MDIO bus (id: %d) registration failed", 30414bfcbd7aSFrancesco Virlinzi __func__, priv->plat->bus_id); 30426a81c26fSViresh Kumar goto error_mdio_register; 30434bfcbd7aSFrancesco Virlinzi } 3044e58bb43fSGiuseppe CAVALLARO } 30454bfcbd7aSFrancesco Virlinzi 304615ffac73SJoachim Eastwood return 0; 30477ac6653aSJeff Kirsher 30486a81c26fSViresh Kumar error_mdio_register: 30497ac6653aSJeff Kirsher unregister_netdev(ndev); 30506a81c26fSViresh Kumar error_netdev_register: 30516a81c26fSViresh Kumar netif_napi_del(&priv->napi); 305262866e98SChen-Yu Tsai error_hw_init: 30535f9755d2SAndrew Bresticker clk_disable_unprepare(priv->pclk); 30545f9755d2SAndrew Bresticker error_pclk_get: 305562866e98SChen-Yu Tsai clk_disable_unprepare(priv->stmmac_clk); 305662866e98SChen-Yu Tsai error_clk_get: 30577ac6653aSJeff Kirsher free_netdev(ndev); 30587ac6653aSJeff Kirsher 305915ffac73SJoachim Eastwood return ret; 30607ac6653aSJeff Kirsher } 3061b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_probe); 30627ac6653aSJeff Kirsher 30637ac6653aSJeff Kirsher /** 30647ac6653aSJeff Kirsher * stmmac_dvr_remove 3065bfab27a1SGiuseppe CAVALLARO * @ndev: net device pointer 30667ac6653aSJeff Kirsher * Description: this function resets the TX/RX processes, disables the MAC RX/TX 3067bfab27a1SGiuseppe CAVALLARO * changes the link status, releases the DMA descriptor rings. 30687ac6653aSJeff Kirsher */ 3069bfab27a1SGiuseppe CAVALLARO int stmmac_dvr_remove(struct net_device *ndev) 30707ac6653aSJeff Kirsher { 30717ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 30727ac6653aSJeff Kirsher 30737ac6653aSJeff Kirsher pr_info("%s:\n\tremoving driver", __func__); 30747ac6653aSJeff Kirsher 30757ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 30767ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 30777ac6653aSJeff Kirsher 3078bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 30797ac6653aSJeff Kirsher netif_carrier_off(ndev); 30807ac6653aSJeff Kirsher unregister_netdev(ndev); 3081c5e4ddbdSChen-Yu Tsai if (priv->stmmac_rst) 3082c5e4ddbdSChen-Yu Tsai reset_control_assert(priv->stmmac_rst); 30835f9755d2SAndrew Bresticker clk_disable_unprepare(priv->pclk); 308462866e98SChen-Yu Tsai clk_disable_unprepare(priv->stmmac_clk); 3085e743471fSBryan O'Donoghue if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI && 3086e743471fSBryan O'Donoghue priv->pcs != STMMAC_PCS_RTBI) 3087e743471fSBryan O'Donoghue stmmac_mdio_unregister(ndev); 30887ac6653aSJeff Kirsher free_netdev(ndev); 30897ac6653aSJeff Kirsher 30907ac6653aSJeff Kirsher return 0; 30917ac6653aSJeff Kirsher } 3092b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_remove); 30937ac6653aSJeff Kirsher 3094732fdf0eSGiuseppe CAVALLARO /** 3095732fdf0eSGiuseppe CAVALLARO * stmmac_suspend - suspend callback 3096732fdf0eSGiuseppe CAVALLARO * @ndev: net device pointer 3097732fdf0eSGiuseppe CAVALLARO * Description: this is the function to suspend the device and it is called 3098732fdf0eSGiuseppe CAVALLARO * by the platform driver to stop the network queue, release the resources, 3099732fdf0eSGiuseppe CAVALLARO * program the PMT register (for WoL), clean and release driver resources. 3100732fdf0eSGiuseppe CAVALLARO */ 3101bfab27a1SGiuseppe CAVALLARO int stmmac_suspend(struct net_device *ndev) 31027ac6653aSJeff Kirsher { 31037ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 3104f8c5a875SGiuseppe CAVALLARO unsigned long flags; 31057ac6653aSJeff Kirsher 31067ac6653aSJeff Kirsher if (!ndev || !netif_running(ndev)) 31077ac6653aSJeff Kirsher return 0; 31087ac6653aSJeff Kirsher 3109102463b1SFrancesco Virlinzi if (priv->phydev) 3110102463b1SFrancesco Virlinzi phy_stop(priv->phydev); 3111102463b1SFrancesco Virlinzi 3112f8c5a875SGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 31137ac6653aSJeff Kirsher 31147ac6653aSJeff Kirsher netif_device_detach(ndev); 31157ac6653aSJeff Kirsher netif_stop_queue(ndev); 31167ac6653aSJeff Kirsher 31177ac6653aSJeff Kirsher napi_disable(&priv->napi); 31187ac6653aSJeff Kirsher 31197ac6653aSJeff Kirsher /* Stop TX/RX DMA */ 31207ac6653aSJeff Kirsher priv->hw->dma->stop_tx(priv->ioaddr); 31217ac6653aSJeff Kirsher priv->hw->dma->stop_rx(priv->ioaddr); 3122c24602efSGiuseppe CAVALLARO 31237ac6653aSJeff Kirsher /* Enable Power down mode by programming the PMT regs */ 312489f7f2cfSSrinivas Kandagatla if (device_may_wakeup(priv->device)) { 31257ed24bbeSVince Bridgers priv->hw->mac->pmt(priv->hw, priv->wolopts); 312689f7f2cfSSrinivas Kandagatla priv->irq_wake = 1; 312789f7f2cfSSrinivas Kandagatla } else { 3128bfab27a1SGiuseppe CAVALLARO stmmac_set_mac(priv->ioaddr, false); 3129db88f10aSSrinivas Kandagatla pinctrl_pm_select_sleep_state(priv->device); 3130ba1377ffSGiuseppe CAVALLARO /* Disable clock in case of PWM is off */ 31315f9755d2SAndrew Bresticker clk_disable(priv->pclk); 3132777da230SGiuseppe CAVALLARO clk_disable(priv->stmmac_clk); 3133ba1377ffSGiuseppe CAVALLARO } 3134f8c5a875SGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 31352d871aa0SVince Bridgers 31362d871aa0SVince Bridgers priv->oldlink = 0; 31372d871aa0SVince Bridgers priv->speed = 0; 31382d871aa0SVince Bridgers priv->oldduplex = -1; 31397ac6653aSJeff Kirsher return 0; 31407ac6653aSJeff Kirsher } 3141b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_suspend); 31427ac6653aSJeff Kirsher 3143732fdf0eSGiuseppe CAVALLARO /** 3144732fdf0eSGiuseppe CAVALLARO * stmmac_resume - resume callback 3145732fdf0eSGiuseppe CAVALLARO * @ndev: net device pointer 3146732fdf0eSGiuseppe CAVALLARO * Description: when resume this function is invoked to setup the DMA and CORE 3147732fdf0eSGiuseppe CAVALLARO * in a usable state. 3148732fdf0eSGiuseppe CAVALLARO */ 3149bfab27a1SGiuseppe CAVALLARO int stmmac_resume(struct net_device *ndev) 31507ac6653aSJeff Kirsher { 31517ac6653aSJeff Kirsher struct stmmac_priv *priv = netdev_priv(ndev); 3152f8c5a875SGiuseppe CAVALLARO unsigned long flags; 31537ac6653aSJeff Kirsher 31547ac6653aSJeff Kirsher if (!netif_running(ndev)) 31557ac6653aSJeff Kirsher return 0; 31567ac6653aSJeff Kirsher 3157f8c5a875SGiuseppe CAVALLARO spin_lock_irqsave(&priv->lock, flags); 31587ac6653aSJeff Kirsher 31597ac6653aSJeff Kirsher /* Power Down bit, into the PM register, is cleared 31607ac6653aSJeff Kirsher * automatically as soon as a magic packet or a Wake-up frame 31617ac6653aSJeff Kirsher * is received. Anyway, it's better to manually clear 31627ac6653aSJeff Kirsher * this bit because it can generate problems while resuming 3163ceb69499SGiuseppe CAVALLARO * from another devices (e.g. serial console). 3164ceb69499SGiuseppe CAVALLARO */ 3165623997fbSSrinivas Kandagatla if (device_may_wakeup(priv->device)) { 31667ed24bbeSVince Bridgers priv->hw->mac->pmt(priv->hw, 0); 316789f7f2cfSSrinivas Kandagatla priv->irq_wake = 0; 3168623997fbSSrinivas Kandagatla } else { 3169db88f10aSSrinivas Kandagatla pinctrl_pm_select_default_state(priv->device); 3170ba1377ffSGiuseppe CAVALLARO /* enable the clk prevously disabled */ 3171777da230SGiuseppe CAVALLARO clk_enable(priv->stmmac_clk); 31725f9755d2SAndrew Bresticker clk_enable(priv->pclk); 3173623997fbSSrinivas Kandagatla /* reset the phy so that it's ready */ 3174623997fbSSrinivas Kandagatla if (priv->mii) 3175623997fbSSrinivas Kandagatla stmmac_mdio_reset(priv->mii); 3176623997fbSSrinivas Kandagatla } 31777ac6653aSJeff Kirsher 31787ac6653aSJeff Kirsher netif_device_attach(ndev); 31797ac6653aSJeff Kirsher 3180ae79a639SGiuseppe CAVALLARO priv->cur_rx = 0; 3181ae79a639SGiuseppe CAVALLARO priv->dirty_rx = 0; 3182ae79a639SGiuseppe CAVALLARO priv->dirty_tx = 0; 3183ae79a639SGiuseppe CAVALLARO priv->cur_tx = 0; 3184ae79a639SGiuseppe CAVALLARO stmmac_clear_descriptors(priv); 3185ae79a639SGiuseppe CAVALLARO 3186fe131929SHuacai Chen stmmac_hw_setup(ndev, false); 3187777da230SGiuseppe CAVALLARO stmmac_init_tx_coalesce(priv); 3188ac316c78SGiuseppe CAVALLARO stmmac_set_rx_mode(ndev); 31897ac6653aSJeff Kirsher 31907ac6653aSJeff Kirsher napi_enable(&priv->napi); 31917ac6653aSJeff Kirsher 31927ac6653aSJeff Kirsher netif_start_queue(ndev); 31937ac6653aSJeff Kirsher 3194f8c5a875SGiuseppe CAVALLARO spin_unlock_irqrestore(&priv->lock, flags); 3195102463b1SFrancesco Virlinzi 3196102463b1SFrancesco Virlinzi if (priv->phydev) 3197102463b1SFrancesco Virlinzi phy_start(priv->phydev); 3198102463b1SFrancesco Virlinzi 31997ac6653aSJeff Kirsher return 0; 32007ac6653aSJeff Kirsher } 3201b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_resume); 3202ba27ec66SGiuseppe CAVALLARO 32037ac6653aSJeff Kirsher #ifndef MODULE 32047ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str) 32057ac6653aSJeff Kirsher { 32067ac6653aSJeff Kirsher char *opt; 32077ac6653aSJeff Kirsher 32087ac6653aSJeff Kirsher if (!str || !*str) 32097ac6653aSJeff Kirsher return -EINVAL; 32107ac6653aSJeff Kirsher while ((opt = strsep(&str, ",")) != NULL) { 32117ac6653aSJeff Kirsher if (!strncmp(opt, "debug:", 6)) { 3212ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 6, 0, &debug)) 32137ac6653aSJeff Kirsher goto err; 32147ac6653aSJeff Kirsher } else if (!strncmp(opt, "phyaddr:", 8)) { 3215ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 8, 0, &phyaddr)) 32167ac6653aSJeff Kirsher goto err; 32177ac6653aSJeff Kirsher } else if (!strncmp(opt, "buf_sz:", 7)) { 3218ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 7, 0, &buf_sz)) 32197ac6653aSJeff Kirsher goto err; 32207ac6653aSJeff Kirsher } else if (!strncmp(opt, "tc:", 3)) { 3221ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 3, 0, &tc)) 32227ac6653aSJeff Kirsher goto err; 32237ac6653aSJeff Kirsher } else if (!strncmp(opt, "watchdog:", 9)) { 3224ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 9, 0, &watchdog)) 32257ac6653aSJeff Kirsher goto err; 32267ac6653aSJeff Kirsher } else if (!strncmp(opt, "flow_ctrl:", 10)) { 3227ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 10, 0, &flow_ctrl)) 32287ac6653aSJeff Kirsher goto err; 32297ac6653aSJeff Kirsher } else if (!strncmp(opt, "pause:", 6)) { 3230ea2ab871SGiuseppe CAVALLARO if (kstrtoint(opt + 6, 0, &pause)) 32317ac6653aSJeff Kirsher goto err; 3232506f669cSGiuseppe CAVALLARO } else if (!strncmp(opt, "eee_timer:", 10)) { 3233d765955dSGiuseppe CAVALLARO if (kstrtoint(opt + 10, 0, &eee_timer)) 3234d765955dSGiuseppe CAVALLARO goto err; 32354a7d666aSGiuseppe CAVALLARO } else if (!strncmp(opt, "chain_mode:", 11)) { 32364a7d666aSGiuseppe CAVALLARO if (kstrtoint(opt + 11, 0, &chain_mode)) 32374a7d666aSGiuseppe CAVALLARO goto err; 32387ac6653aSJeff Kirsher } 32397ac6653aSJeff Kirsher } 32407ac6653aSJeff Kirsher return 0; 32417ac6653aSJeff Kirsher 32427ac6653aSJeff Kirsher err: 32437ac6653aSJeff Kirsher pr_err("%s: ERROR broken module parameter conversion", __func__); 32447ac6653aSJeff Kirsher return -EINVAL; 32457ac6653aSJeff Kirsher } 32467ac6653aSJeff Kirsher 32477ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt); 3248ceb69499SGiuseppe CAVALLARO #endif /* MODULE */ 32496fc0d0f2SGiuseppe Cavallaro 3250466c5ac8SMathieu Olivari static int __init stmmac_init(void) 3251466c5ac8SMathieu Olivari { 3252466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS 3253466c5ac8SMathieu Olivari /* Create debugfs main directory if it doesn't exist yet */ 3254466c5ac8SMathieu Olivari if (!stmmac_fs_dir) { 3255466c5ac8SMathieu Olivari stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL); 3256466c5ac8SMathieu Olivari 3257466c5ac8SMathieu Olivari if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) { 3258466c5ac8SMathieu Olivari pr_err("ERROR %s, debugfs create directory failed\n", 3259466c5ac8SMathieu Olivari STMMAC_RESOURCE_NAME); 3260466c5ac8SMathieu Olivari 3261466c5ac8SMathieu Olivari return -ENOMEM; 3262466c5ac8SMathieu Olivari } 3263466c5ac8SMathieu Olivari } 3264466c5ac8SMathieu Olivari #endif 3265466c5ac8SMathieu Olivari 3266466c5ac8SMathieu Olivari return 0; 3267466c5ac8SMathieu Olivari } 3268466c5ac8SMathieu Olivari 3269466c5ac8SMathieu Olivari static void __exit stmmac_exit(void) 3270466c5ac8SMathieu Olivari { 3271466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS 3272466c5ac8SMathieu Olivari debugfs_remove_recursive(stmmac_fs_dir); 3273466c5ac8SMathieu Olivari #endif 3274466c5ac8SMathieu Olivari } 3275466c5ac8SMathieu Olivari 3276466c5ac8SMathieu Olivari module_init(stmmac_init) 3277466c5ac8SMathieu Olivari module_exit(stmmac_exit) 3278466c5ac8SMathieu Olivari 32796fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver"); 32806fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); 32816fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL"); 3282