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