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 
1885bacd778SLABBE Corentin static inline u32 stmmac_tx_avail(struct stmmac_priv *priv)
1897ac6653aSJeff Kirsher {
190a6a3e026SLABBE Corentin 	u32 avail;
191e3ad57c9SGiuseppe Cavallaro 
1925bacd778SLABBE Corentin 	if (priv->dirty_tx > priv->cur_tx)
1935bacd778SLABBE Corentin 		avail = priv->dirty_tx - priv->cur_tx - 1;
194e3ad57c9SGiuseppe Cavallaro 	else
1955bacd778SLABBE Corentin 		avail = DMA_TX_SIZE - priv->cur_tx + priv->dirty_tx - 1;
196e3ad57c9SGiuseppe Cavallaro 
197e3ad57c9SGiuseppe Cavallaro 	return avail;
198e3ad57c9SGiuseppe Cavallaro }
199e3ad57c9SGiuseppe Cavallaro 
2005bacd778SLABBE Corentin static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv)
201e3ad57c9SGiuseppe Cavallaro {
202a6a3e026SLABBE Corentin 	u32 dirty;
203e3ad57c9SGiuseppe Cavallaro 
2045bacd778SLABBE Corentin 	if (priv->dirty_rx <= priv->cur_rx)
2055bacd778SLABBE Corentin 		dirty = priv->cur_rx - priv->dirty_rx;
206e3ad57c9SGiuseppe Cavallaro 	else
2075bacd778SLABBE Corentin 		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 */
2365bacd778SLABBE Corentin 	if ((priv->dirty_tx == priv->cur_tx) &&
2375bacd778SLABBE Corentin 	    (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 
8965bacd778SLABBE Corentin 	if (priv->extend_desc) {
8975bacd778SLABBE Corentin 		head_rx = (void *)priv->dma_erx;
8985bacd778SLABBE Corentin 		head_tx = (void *)priv->dma_etx;
8995bacd778SLABBE Corentin 	} else {
9005bacd778SLABBE Corentin 		head_rx = (void *)priv->dma_rx;
9015bacd778SLABBE Corentin 		head_tx = (void *)priv->dma_tx;
9025bacd778SLABBE Corentin 	}
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 {
9345bacd778SLABBE Corentin 	int i;
935c24602efSGiuseppe CAVALLARO 
9365bacd778SLABBE Corentin 	/* Clear the Rx/Tx descriptors */
9375bacd778SLABBE Corentin 	for (i = 0; i < DMA_RX_SIZE; i++)
9385bacd778SLABBE Corentin 		if (priv->extend_desc)
9395bacd778SLABBE Corentin 			priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
9405bacd778SLABBE Corentin 						     priv->use_riwt, priv->mode,
9415bacd778SLABBE Corentin 						     (i == DMA_RX_SIZE - 1));
9425bacd778SLABBE Corentin 		else
9435bacd778SLABBE Corentin 			priv->hw->desc->init_rx_desc(&priv->dma_rx[i],
9445bacd778SLABBE Corentin 						     priv->use_riwt, priv->mode,
9455bacd778SLABBE Corentin 						     (i == DMA_RX_SIZE - 1));
9465bacd778SLABBE Corentin 	for (i = 0; i < DMA_TX_SIZE; i++)
9475bacd778SLABBE Corentin 		if (priv->extend_desc)
9485bacd778SLABBE Corentin 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
9495bacd778SLABBE Corentin 						     priv->mode,
9505bacd778SLABBE Corentin 						     (i == DMA_TX_SIZE - 1));
9515bacd778SLABBE Corentin 		else
9525bacd778SLABBE Corentin 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
9535bacd778SLABBE Corentin 						     priv->mode,
9545bacd778SLABBE Corentin 						     (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,
9675bacd778SLABBE Corentin 				  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 	}
9775bacd778SLABBE Corentin 	priv->rx_skbuff[i] = skb;
9785bacd778SLABBE Corentin 	priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
979c24602efSGiuseppe CAVALLARO 						priv->dma_buf_sz,
980c24602efSGiuseppe CAVALLARO 						DMA_FROM_DEVICE);
9815bacd778SLABBE Corentin 	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)
9885bacd778SLABBE Corentin 		p->des0 = cpu_to_le32(priv->rx_skbuff_dma[i]);
989f748be53SAlexandre TORGUE 	else
9905bacd778SLABBE Corentin 		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 
9995bacd778SLABBE Corentin static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i)
100056329137SBartlomiej Zolnierkiewicz {
10015bacd778SLABBE Corentin 	if (priv->rx_skbuff[i]) {
10025bacd778SLABBE Corentin 		dma_unmap_single(priv->device, priv->rx_skbuff_dma[i],
100356329137SBartlomiej Zolnierkiewicz 				 priv->dma_buf_sz, DMA_FROM_DEVICE);
10045bacd778SLABBE Corentin 		dev_kfree_skb_any(priv->rx_skbuff[i]);
100556329137SBartlomiej Zolnierkiewicz 	}
10065bacd778SLABBE Corentin 	priv->rx_skbuff[i] = NULL;
100756329137SBartlomiej Zolnierkiewicz }
100856329137SBartlomiej Zolnierkiewicz 
10097ac6653aSJeff Kirsher /**
10105bacd778SLABBE Corentin  * init_dma_desc_rings - init the RX/TX descriptor rings
10117ac6653aSJeff Kirsher  * @dev: net device structure
10125bacd778SLABBE Corentin  * @flags: gfp flag.
10135bacd778SLABBE Corentin  * Description: this function initializes the DMA RX/TX descriptors
10145bacd778SLABBE Corentin  * and allocates the socket buffers. It supports the chained and ring
1015286a8372SGiuseppe CAVALLARO  * modes.
10167ac6653aSJeff Kirsher  */
10175bacd778SLABBE Corentin static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)
10187ac6653aSJeff Kirsher {
10195bacd778SLABBE Corentin 	int i;
10207ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
10215bacd778SLABBE Corentin 	unsigned int bfsize = 0;
10225bacd778SLABBE Corentin 	int ret = -ENOMEM;
10237ac6653aSJeff Kirsher 
10245bacd778SLABBE Corentin 	if (priv->hw->mode->set_16kib_bfsize)
10255bacd778SLABBE Corentin 		bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu);
10265bacd778SLABBE Corentin 
10275bacd778SLABBE Corentin 	if (bfsize < BUF_SIZE_16KiB)
10285bacd778SLABBE Corentin 		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
10295bacd778SLABBE Corentin 
10305bacd778SLABBE Corentin 	priv->dma_buf_sz = bfsize;
10312618abb7SVince Bridgers 
1032b3e51069SLABBE Corentin 	netif_dbg(priv, probe, priv->dev,
10335bacd778SLABBE Corentin 		  "(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n",
10345bacd778SLABBE Corentin 		  __func__, (u32)priv->dma_rx_phy, (u32)priv->dma_tx_phy);
10355bacd778SLABBE Corentin 
10365bacd778SLABBE Corentin 	/* RX INITIALIZATION */
10375bacd778SLABBE Corentin 	netif_dbg(priv, probe, priv->dev,
10385bacd778SLABBE Corentin 		  "SKB addresses:\nskb\t\tskb data\tdma data\n");
10395bacd778SLABBE Corentin 
10405bacd778SLABBE Corentin 	for (i = 0; i < DMA_RX_SIZE; i++) {
10415bacd778SLABBE Corentin 		struct dma_desc *p;
10425bacd778SLABBE Corentin 		if (priv->extend_desc)
10435bacd778SLABBE Corentin 			p = &((priv->dma_erx + i)->basic);
10445bacd778SLABBE Corentin 		else
10455bacd778SLABBE Corentin 			p = priv->dma_rx + i;
10465bacd778SLABBE Corentin 
10475bacd778SLABBE Corentin 		ret = stmmac_init_rx_buffers(priv, p, i, flags);
10485bacd778SLABBE Corentin 		if (ret)
10495bacd778SLABBE Corentin 			goto err_init_rx_buffers;
10505bacd778SLABBE Corentin 
10515bacd778SLABBE Corentin 		netif_dbg(priv, probe, priv->dev, "[%p]\t[%p]\t[%x]\n",
10525bacd778SLABBE Corentin 			  priv->rx_skbuff[i], priv->rx_skbuff[i]->data,
10535bacd778SLABBE Corentin 			  (unsigned int)priv->rx_skbuff_dma[i]);
10545bacd778SLABBE Corentin 	}
10555bacd778SLABBE Corentin 	priv->cur_rx = 0;
10565bacd778SLABBE Corentin 	priv->dirty_rx = (unsigned int)(i - DMA_RX_SIZE);
10575bacd778SLABBE Corentin 	buf_sz = bfsize;
10587ac6653aSJeff Kirsher 
1059c24602efSGiuseppe CAVALLARO 	/* Setup the chained descriptor addresses */
1060c24602efSGiuseppe CAVALLARO 	if (priv->mode == STMMAC_CHAIN_MODE) {
10615bacd778SLABBE Corentin 		if (priv->extend_desc) {
10625bacd778SLABBE Corentin 			priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy,
10635bacd778SLABBE Corentin 					     DMA_RX_SIZE, 1);
10645bacd778SLABBE Corentin 			priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy,
1065e3ad57c9SGiuseppe Cavallaro 					     DMA_TX_SIZE, 1);
10665bacd778SLABBE Corentin 		} else {
10675bacd778SLABBE Corentin 			priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy,
10685bacd778SLABBE Corentin 					     DMA_RX_SIZE, 0);
10695bacd778SLABBE Corentin 			priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy,
1070e3ad57c9SGiuseppe Cavallaro 					     DMA_TX_SIZE, 0);
1071c24602efSGiuseppe CAVALLARO 		}
10725bacd778SLABBE Corentin 	}
1073286a8372SGiuseppe CAVALLARO 
10745bacd778SLABBE Corentin 	/* TX INITIALIZATION */
1075e3ad57c9SGiuseppe Cavallaro 	for (i = 0; i < DMA_TX_SIZE; i++) {
1076c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1077c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
10785bacd778SLABBE Corentin 			p = &((priv->dma_etx + i)->basic);
1079c24602efSGiuseppe CAVALLARO 		else
10805bacd778SLABBE Corentin 			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 
10915bacd778SLABBE Corentin 		priv->tx_skbuff_dma[i].buf = 0;
10925bacd778SLABBE Corentin 		priv->tx_skbuff_dma[i].map_as_page = false;
10935bacd778SLABBE Corentin 		priv->tx_skbuff_dma[i].len = 0;
10945bacd778SLABBE Corentin 		priv->tx_skbuff_dma[i].last_segment = false;
10955bacd778SLABBE Corentin 		priv->tx_skbuff[i] = NULL;
10964a7d666aSGiuseppe CAVALLARO 	}
1097c24602efSGiuseppe CAVALLARO 
10985bacd778SLABBE Corentin 	priv->dirty_tx = 0;
10995bacd778SLABBE Corentin 	priv->cur_tx = 0;
11005bacd778SLABBE Corentin 	netdev_reset_queue(priv->dev);
11017ac6653aSJeff Kirsher 
11025bacd778SLABBE Corentin 	stmmac_clear_descriptors(priv);
11037ac6653aSJeff Kirsher 
1104c24602efSGiuseppe CAVALLARO 	if (netif_msg_hw(priv))
1105c24602efSGiuseppe CAVALLARO 		stmmac_display_rings(priv);
110656329137SBartlomiej Zolnierkiewicz 
11075bacd778SLABBE Corentin 	return 0;
11085bacd778SLABBE Corentin err_init_rx_buffers:
11095bacd778SLABBE Corentin 	while (--i >= 0)
11105bacd778SLABBE Corentin 		stmmac_free_rx_buffers(priv, i);
111156329137SBartlomiej Zolnierkiewicz 	return ret;
11127ac6653aSJeff Kirsher }
11137ac6653aSJeff Kirsher 
11145bacd778SLABBE Corentin 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++)
11195bacd778SLABBE Corentin 		stmmac_free_rx_buffers(priv, i);
11207ac6653aSJeff Kirsher }
11217ac6653aSJeff Kirsher 
11225bacd778SLABBE Corentin static void dma_free_tx_skbufs(struct stmmac_priv *priv)
11237ac6653aSJeff Kirsher {
11247ac6653aSJeff Kirsher 	int i;
11257ac6653aSJeff Kirsher 
11265bacd778SLABBE Corentin 	for (i = 0; i < DMA_TX_SIZE; i++) {
11275bacd778SLABBE Corentin 		if (priv->tx_skbuff_dma[i].buf) {
11285bacd778SLABBE Corentin 			if (priv->tx_skbuff_dma[i].map_as_page)
11295bacd778SLABBE Corentin 				dma_unmap_page(priv->device,
11305bacd778SLABBE Corentin 					       priv->tx_skbuff_dma[i].buf,
11315bacd778SLABBE Corentin 					       priv->tx_skbuff_dma[i].len,
11325bacd778SLABBE Corentin 					       DMA_TO_DEVICE);
1133aff3d9efSJoao Pinto 			else
11345bacd778SLABBE Corentin 				dma_unmap_single(priv->device,
11355bacd778SLABBE Corentin 						 priv->tx_skbuff_dma[i].buf,
11365bacd778SLABBE Corentin 						 priv->tx_skbuff_dma[i].len,
11375bacd778SLABBE Corentin 						 DMA_TO_DEVICE);
1138aff3d9efSJoao Pinto 		}
1139aff3d9efSJoao Pinto 
11405bacd778SLABBE Corentin 		if (priv->tx_skbuff[i]) {
11415bacd778SLABBE Corentin 			dev_kfree_skb_any(priv->tx_skbuff[i]);
11425bacd778SLABBE Corentin 			priv->tx_skbuff[i] = NULL;
11435bacd778SLABBE Corentin 			priv->tx_skbuff_dma[i].buf = 0;
11445bacd778SLABBE Corentin 			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 {
11595bacd778SLABBE Corentin 	int ret = -ENOMEM;
116009f8d696SSrinivas Kandagatla 
11615bacd778SLABBE Corentin 	priv->rx_skbuff_dma = kmalloc_array(DMA_RX_SIZE, sizeof(dma_addr_t),
11625bacd778SLABBE Corentin 					    GFP_KERNEL);
11635bacd778SLABBE Corentin 	if (!priv->rx_skbuff_dma)
11645bacd778SLABBE Corentin 		return -ENOMEM;
11655bacd778SLABBE Corentin 
11665bacd778SLABBE Corentin 	priv->rx_skbuff = kmalloc_array(DMA_RX_SIZE, sizeof(struct sk_buff *),
11675bacd778SLABBE Corentin 					GFP_KERNEL);
11685bacd778SLABBE Corentin 	if (!priv->rx_skbuff)
11695bacd778SLABBE Corentin 		goto err_rx_skbuff;
11705bacd778SLABBE Corentin 
11715bacd778SLABBE Corentin 	priv->tx_skbuff_dma = kmalloc_array(DMA_TX_SIZE,
11725bacd778SLABBE Corentin 					    sizeof(*priv->tx_skbuff_dma),
11735bacd778SLABBE Corentin 					    GFP_KERNEL);
11745bacd778SLABBE Corentin 	if (!priv->tx_skbuff_dma)
11755bacd778SLABBE Corentin 		goto err_tx_skbuff_dma;
11765bacd778SLABBE Corentin 
11775bacd778SLABBE Corentin 	priv->tx_skbuff = kmalloc_array(DMA_TX_SIZE, sizeof(struct sk_buff *),
11785bacd778SLABBE Corentin 					GFP_KERNEL);
11795bacd778SLABBE Corentin 	if (!priv->tx_skbuff)
11805bacd778SLABBE Corentin 		goto err_tx_skbuff;
11815bacd778SLABBE Corentin 
11825bacd778SLABBE Corentin 	if (priv->extend_desc) {
11835bacd778SLABBE Corentin 		priv->dma_erx = dma_zalloc_coherent(priv->device, DMA_RX_SIZE *
11845bacd778SLABBE Corentin 						    sizeof(struct
11855bacd778SLABBE Corentin 							   dma_extended_desc),
11865bacd778SLABBE Corentin 						    &priv->dma_rx_phy,
11875bacd778SLABBE Corentin 						    GFP_KERNEL);
11885bacd778SLABBE Corentin 		if (!priv->dma_erx)
11895bacd778SLABBE Corentin 			goto err_dma;
11905bacd778SLABBE Corentin 
11915bacd778SLABBE Corentin 		priv->dma_etx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE *
11925bacd778SLABBE Corentin 						    sizeof(struct
11935bacd778SLABBE Corentin 							   dma_extended_desc),
11945bacd778SLABBE Corentin 						    &priv->dma_tx_phy,
11955bacd778SLABBE Corentin 						    GFP_KERNEL);
11965bacd778SLABBE Corentin 		if (!priv->dma_etx) {
11975bacd778SLABBE Corentin 			dma_free_coherent(priv->device, DMA_RX_SIZE *
11985bacd778SLABBE Corentin 					  sizeof(struct dma_extended_desc),
11995bacd778SLABBE Corentin 					  priv->dma_erx, priv->dma_rx_phy);
12005bacd778SLABBE Corentin 			goto err_dma;
12015bacd778SLABBE Corentin 		}
12025bacd778SLABBE Corentin 	} else {
12035bacd778SLABBE Corentin 		priv->dma_rx = dma_zalloc_coherent(priv->device, DMA_RX_SIZE *
12045bacd778SLABBE Corentin 						   sizeof(struct dma_desc),
12055bacd778SLABBE Corentin 						   &priv->dma_rx_phy,
12065bacd778SLABBE Corentin 						   GFP_KERNEL);
12075bacd778SLABBE Corentin 		if (!priv->dma_rx)
12085bacd778SLABBE Corentin 			goto err_dma;
12095bacd778SLABBE Corentin 
12105bacd778SLABBE Corentin 		priv->dma_tx = dma_zalloc_coherent(priv->device, DMA_TX_SIZE *
12115bacd778SLABBE Corentin 						   sizeof(struct dma_desc),
12125bacd778SLABBE Corentin 						   &priv->dma_tx_phy,
12135bacd778SLABBE Corentin 						   GFP_KERNEL);
12145bacd778SLABBE Corentin 		if (!priv->dma_tx) {
12155bacd778SLABBE Corentin 			dma_free_coherent(priv->device, DMA_RX_SIZE *
12165bacd778SLABBE Corentin 					  sizeof(struct dma_desc),
12175bacd778SLABBE Corentin 					  priv->dma_rx, priv->dma_rx_phy);
12185bacd778SLABBE Corentin 			goto err_dma;
12195bacd778SLABBE Corentin 		}
12205bacd778SLABBE Corentin 	}
12215bacd778SLABBE Corentin 
12225bacd778SLABBE Corentin 	return 0;
12235bacd778SLABBE Corentin 
12245bacd778SLABBE Corentin err_dma:
12255bacd778SLABBE Corentin 	kfree(priv->tx_skbuff);
12265bacd778SLABBE Corentin err_tx_skbuff:
12275bacd778SLABBE Corentin 	kfree(priv->tx_skbuff_dma);
12285bacd778SLABBE Corentin err_tx_skbuff_dma:
12295bacd778SLABBE Corentin 	kfree(priv->rx_skbuff);
12305bacd778SLABBE Corentin err_rx_skbuff:
12315bacd778SLABBE Corentin 	kfree(priv->rx_skbuff_dma);
123209f8d696SSrinivas Kandagatla 	return ret;
12335bacd778SLABBE Corentin }
123409f8d696SSrinivas Kandagatla 
12355bacd778SLABBE Corentin static void free_dma_desc_resources(struct stmmac_priv *priv)
12365bacd778SLABBE Corentin {
12375bacd778SLABBE Corentin 	/* Release the DMA TX/RX socket buffers */
12385bacd778SLABBE Corentin 	dma_free_rx_skbufs(priv);
12395bacd778SLABBE Corentin 	dma_free_tx_skbufs(priv);
12407ac6653aSJeff Kirsher 
12415bacd778SLABBE Corentin 	/* Free DMA regions of consistent memory previously allocated */
12425bacd778SLABBE Corentin 	if (!priv->extend_desc) {
12435bacd778SLABBE Corentin 		dma_free_coherent(priv->device,
12445bacd778SLABBE Corentin 				  DMA_TX_SIZE * sizeof(struct dma_desc),
12455bacd778SLABBE Corentin 				  priv->dma_tx, priv->dma_tx_phy);
12465bacd778SLABBE Corentin 		dma_free_coherent(priv->device,
12475bacd778SLABBE Corentin 				  DMA_RX_SIZE * sizeof(struct dma_desc),
12485bacd778SLABBE Corentin 				  priv->dma_rx, priv->dma_rx_phy);
12495bacd778SLABBE Corentin 	} else {
12505bacd778SLABBE Corentin 		dma_free_coherent(priv->device, DMA_TX_SIZE *
12515bacd778SLABBE Corentin 				  sizeof(struct dma_extended_desc),
12525bacd778SLABBE Corentin 				  priv->dma_etx, priv->dma_tx_phy);
12535bacd778SLABBE Corentin 		dma_free_coherent(priv->device, DMA_RX_SIZE *
12545bacd778SLABBE Corentin 				  sizeof(struct dma_extended_desc),
12555bacd778SLABBE Corentin 				  priv->dma_erx, priv->dma_rx_phy);
12565bacd778SLABBE Corentin 	}
12575bacd778SLABBE Corentin 	kfree(priv->rx_skbuff_dma);
12585bacd778SLABBE Corentin 	kfree(priv->rx_skbuff);
12595bacd778SLABBE Corentin 	kfree(priv->tx_skbuff_dma);
12605bacd778SLABBE Corentin 	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 /**
1281ae4f0d46SJoao Pinto  * stmmac_start_rx_dma - start RX DMA channel
1282ae4f0d46SJoao Pinto  * @priv: driver private structure
1283ae4f0d46SJoao Pinto  * @chan: RX channel index
1284ae4f0d46SJoao Pinto  * Description:
1285ae4f0d46SJoao Pinto  * This starts a RX DMA channel
1286ae4f0d46SJoao Pinto  */
1287ae4f0d46SJoao Pinto static void stmmac_start_rx_dma(struct stmmac_priv *priv, u32 chan)
1288ae4f0d46SJoao Pinto {
1289ae4f0d46SJoao Pinto 	netdev_dbg(priv->dev, "DMA RX processes started in channel %d\n", chan);
1290ae4f0d46SJoao Pinto 	priv->hw->dma->start_rx(priv->ioaddr, chan);
1291ae4f0d46SJoao Pinto }
1292ae4f0d46SJoao Pinto 
1293ae4f0d46SJoao Pinto /**
1294ae4f0d46SJoao Pinto  * stmmac_start_tx_dma - start TX DMA channel
1295ae4f0d46SJoao Pinto  * @priv: driver private structure
1296ae4f0d46SJoao Pinto  * @chan: TX channel index
1297ae4f0d46SJoao Pinto  * Description:
1298ae4f0d46SJoao Pinto  * This starts a TX DMA channel
1299ae4f0d46SJoao Pinto  */
1300ae4f0d46SJoao Pinto static void stmmac_start_tx_dma(struct stmmac_priv *priv, u32 chan)
1301ae4f0d46SJoao Pinto {
1302ae4f0d46SJoao Pinto 	netdev_dbg(priv->dev, "DMA TX processes started in channel %d\n", chan);
1303ae4f0d46SJoao Pinto 	priv->hw->dma->start_tx(priv->ioaddr, chan);
1304ae4f0d46SJoao Pinto }
1305ae4f0d46SJoao Pinto 
1306ae4f0d46SJoao Pinto /**
1307ae4f0d46SJoao Pinto  * stmmac_stop_rx_dma - stop RX DMA channel
1308ae4f0d46SJoao Pinto  * @priv: driver private structure
1309ae4f0d46SJoao Pinto  * @chan: RX channel index
1310ae4f0d46SJoao Pinto  * Description:
1311ae4f0d46SJoao Pinto  * This stops a RX DMA channel
1312ae4f0d46SJoao Pinto  */
1313ae4f0d46SJoao Pinto static void stmmac_stop_rx_dma(struct stmmac_priv *priv, u32 chan)
1314ae4f0d46SJoao Pinto {
1315ae4f0d46SJoao Pinto 	netdev_dbg(priv->dev, "DMA RX processes stopped in channel %d\n", chan);
1316ae4f0d46SJoao Pinto 	priv->hw->dma->stop_rx(priv->ioaddr, chan);
1317ae4f0d46SJoao Pinto }
1318ae4f0d46SJoao Pinto 
1319ae4f0d46SJoao Pinto /**
1320ae4f0d46SJoao Pinto  * stmmac_stop_tx_dma - stop TX DMA channel
1321ae4f0d46SJoao Pinto  * @priv: driver private structure
1322ae4f0d46SJoao Pinto  * @chan: TX channel index
1323ae4f0d46SJoao Pinto  * Description:
1324ae4f0d46SJoao Pinto  * This stops a TX DMA channel
1325ae4f0d46SJoao Pinto  */
1326ae4f0d46SJoao Pinto static void stmmac_stop_tx_dma(struct stmmac_priv *priv, u32 chan)
1327ae4f0d46SJoao Pinto {
1328ae4f0d46SJoao Pinto 	netdev_dbg(priv->dev, "DMA TX processes stopped in channel %d\n", chan);
1329ae4f0d46SJoao Pinto 	priv->hw->dma->stop_tx(priv->ioaddr, chan);
1330ae4f0d46SJoao Pinto }
1331ae4f0d46SJoao Pinto 
1332ae4f0d46SJoao Pinto /**
1333ae4f0d46SJoao Pinto  * stmmac_start_all_dma - start all RX and TX DMA channels
1334ae4f0d46SJoao Pinto  * @priv: driver private structure
1335ae4f0d46SJoao Pinto  * Description:
1336ae4f0d46SJoao Pinto  * This starts all the RX and TX DMA channels
1337ae4f0d46SJoao Pinto  */
1338ae4f0d46SJoao Pinto static void stmmac_start_all_dma(struct stmmac_priv *priv)
1339ae4f0d46SJoao Pinto {
1340ae4f0d46SJoao Pinto 	u32 rx_channels_count = priv->plat->rx_queues_to_use;
1341ae4f0d46SJoao Pinto 	u32 tx_channels_count = priv->plat->tx_queues_to_use;
1342ae4f0d46SJoao Pinto 	u32 chan = 0;
1343ae4f0d46SJoao Pinto 
1344ae4f0d46SJoao Pinto 	for (chan = 0; chan < rx_channels_count; chan++)
1345ae4f0d46SJoao Pinto 		stmmac_start_rx_dma(priv, chan);
1346ae4f0d46SJoao Pinto 
1347ae4f0d46SJoao Pinto 	for (chan = 0; chan < tx_channels_count; chan++)
1348ae4f0d46SJoao Pinto 		stmmac_start_tx_dma(priv, chan);
1349ae4f0d46SJoao Pinto }
1350ae4f0d46SJoao Pinto 
1351ae4f0d46SJoao Pinto /**
1352ae4f0d46SJoao Pinto  * stmmac_stop_all_dma - stop all RX and TX DMA channels
1353ae4f0d46SJoao Pinto  * @priv: driver private structure
1354ae4f0d46SJoao Pinto  * Description:
1355ae4f0d46SJoao Pinto  * This stops the RX and TX DMA channels
1356ae4f0d46SJoao Pinto  */
1357ae4f0d46SJoao Pinto static void stmmac_stop_all_dma(struct stmmac_priv *priv)
1358ae4f0d46SJoao Pinto {
1359ae4f0d46SJoao Pinto 	u32 rx_channels_count = priv->plat->rx_queues_to_use;
1360ae4f0d46SJoao Pinto 	u32 tx_channels_count = priv->plat->tx_queues_to_use;
1361ae4f0d46SJoao Pinto 	u32 chan = 0;
1362ae4f0d46SJoao Pinto 
1363ae4f0d46SJoao Pinto 	for (chan = 0; chan < rx_channels_count; chan++)
1364ae4f0d46SJoao Pinto 		stmmac_stop_rx_dma(priv, chan);
1365ae4f0d46SJoao Pinto 
1366ae4f0d46SJoao Pinto 	for (chan = 0; chan < tx_channels_count; chan++)
1367ae4f0d46SJoao Pinto 		stmmac_stop_tx_dma(priv, chan);
1368ae4f0d46SJoao Pinto }
1369ae4f0d46SJoao Pinto 
1370ae4f0d46SJoao Pinto /**
13717ac6653aSJeff Kirsher  *  stmmac_dma_operation_mode - HW DMA operation mode
137232ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
1373732fdf0eSGiuseppe CAVALLARO  *  Description: it is used for configuring the DMA operation mode register in
1374732fdf0eSGiuseppe CAVALLARO  *  order to program the tx/rx DMA thresholds or Store-And-Forward mode.
13757ac6653aSJeff Kirsher  */
13767ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
13777ac6653aSJeff Kirsher {
13786deee222SJoao Pinto 	u32 rx_channels_count = priv->plat->rx_queues_to_use;
13796deee222SJoao Pinto 	u32 tx_channels_count = priv->plat->tx_queues_to_use;
1380f88203a2SVince Bridgers 	int rxfifosz = priv->plat->rx_fifo_size;
13816deee222SJoao Pinto 	u32 txmode = 0;
13826deee222SJoao Pinto 	u32 rxmode = 0;
13836deee222SJoao Pinto 	u32 chan = 0;
1384f88203a2SVince Bridgers 
138511fbf811SThierry Reding 	if (rxfifosz == 0)
138611fbf811SThierry Reding 		rxfifosz = priv->dma_cap.rx_fifo_size;
138711fbf811SThierry Reding 
13886deee222SJoao Pinto 	if (priv->plat->force_thresh_dma_mode) {
13896deee222SJoao Pinto 		txmode = tc;
13906deee222SJoao Pinto 		rxmode = tc;
13916deee222SJoao Pinto 	} else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
13927ac6653aSJeff Kirsher 		/*
13937ac6653aSJeff Kirsher 		 * In case of GMAC, SF mode can be enabled
13947ac6653aSJeff Kirsher 		 * to perform the TX COE in HW. This depends on:
13957ac6653aSJeff Kirsher 		 * 1) TX COE if actually supported
13967ac6653aSJeff Kirsher 		 * 2) There is no bugged Jumbo frame support
13977ac6653aSJeff Kirsher 		 *    that needs to not insert csum in the TDES.
13987ac6653aSJeff Kirsher 		 */
13996deee222SJoao Pinto 		txmode = SF_DMA_MODE;
14006deee222SJoao Pinto 		rxmode = SF_DMA_MODE;
1401b2dec116SSonic Zhang 		priv->xstats.threshold = SF_DMA_MODE;
14026deee222SJoao Pinto 	} else {
14036deee222SJoao Pinto 		txmode = tc;
14046deee222SJoao Pinto 		rxmode = SF_DMA_MODE;
14056deee222SJoao Pinto 	}
14066deee222SJoao Pinto 
14076deee222SJoao Pinto 	/* configure all channels */
14086deee222SJoao Pinto 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
14096deee222SJoao Pinto 		for (chan = 0; chan < rx_channels_count; chan++)
14106deee222SJoao Pinto 			priv->hw->dma->dma_rx_mode(priv->ioaddr, rxmode, chan,
1411f88203a2SVince Bridgers 						   rxfifosz);
14126deee222SJoao Pinto 
14136deee222SJoao Pinto 		for (chan = 0; chan < tx_channels_count; chan++)
14146deee222SJoao Pinto 			priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan);
14156deee222SJoao Pinto 	} else {
14166deee222SJoao Pinto 		priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode,
14176deee222SJoao Pinto 					rxfifosz);
14186deee222SJoao Pinto 	}
14197ac6653aSJeff Kirsher }
14207ac6653aSJeff Kirsher 
14217ac6653aSJeff Kirsher /**
1422732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_clean - to manage the transmission completion
142332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
1424732fdf0eSGiuseppe CAVALLARO  * Description: it reclaims the transmit resources after transmission completes.
14257ac6653aSJeff Kirsher  */
14265bacd778SLABBE Corentin static void stmmac_tx_clean(struct stmmac_priv *priv)
14277ac6653aSJeff Kirsher {
142838979574SBeniamino Galvani 	unsigned int bytes_compl = 0, pkts_compl = 0;
14295bacd778SLABBE Corentin 	unsigned int entry = priv->dirty_tx;
14307ac6653aSJeff Kirsher 
1431739c8e14SLino Sanfilippo 	netif_tx_lock(priv->dev);
1432a9097a96SGiuseppe CAVALLARO 
14339125cdd1SGiuseppe CAVALLARO 	priv->xstats.tx_clean++;
14349125cdd1SGiuseppe CAVALLARO 
14355bacd778SLABBE Corentin 	while (entry != priv->cur_tx) {
14365bacd778SLABBE Corentin 		struct sk_buff *skb = priv->tx_skbuff[entry];
1437c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1438c363b658SFabrice Gasnier 		int status;
1439c24602efSGiuseppe CAVALLARO 
1440c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
14415bacd778SLABBE Corentin 			p = (struct dma_desc *)(priv->dma_etx + entry);
1442c24602efSGiuseppe CAVALLARO 		else
14435bacd778SLABBE Corentin 			p = priv->dma_tx + entry;
14447ac6653aSJeff Kirsher 
1445c363b658SFabrice Gasnier 		status = priv->hw->desc->tx_status(&priv->dev->stats,
14467ac6653aSJeff Kirsher 						      &priv->xstats, p,
14477ac6653aSJeff Kirsher 						      priv->ioaddr);
1448c363b658SFabrice Gasnier 		/* Check if the descriptor is owned by the DMA */
1449c363b658SFabrice Gasnier 		if (unlikely(status & tx_dma_own))
1450c363b658SFabrice Gasnier 			break;
1451c363b658SFabrice Gasnier 
1452c363b658SFabrice Gasnier 		/* Just consider the last segment and ...*/
1453c363b658SFabrice Gasnier 		if (likely(!(status & tx_not_ls))) {
1454c363b658SFabrice Gasnier 			/* ... verify the status error condition */
1455c363b658SFabrice Gasnier 			if (unlikely(status & tx_err)) {
1456c363b658SFabrice Gasnier 				priv->dev->stats.tx_errors++;
1457c363b658SFabrice Gasnier 			} else {
14587ac6653aSJeff Kirsher 				priv->dev->stats.tx_packets++;
14597ac6653aSJeff Kirsher 				priv->xstats.tx_pkt_n++;
1460c363b658SFabrice Gasnier 			}
1461ba1ffd74SGiuseppe CAVALLARO 			stmmac_get_tx_hwtstamp(priv, p, skb);
14627ac6653aSJeff Kirsher 		}
14637ac6653aSJeff Kirsher 
14645bacd778SLABBE Corentin 		if (likely(priv->tx_skbuff_dma[entry].buf)) {
14655bacd778SLABBE Corentin 			if (priv->tx_skbuff_dma[entry].map_as_page)
1466362b37beSGiuseppe CAVALLARO 				dma_unmap_page(priv->device,
14675bacd778SLABBE Corentin 					       priv->tx_skbuff_dma[entry].buf,
14685bacd778SLABBE Corentin 					       priv->tx_skbuff_dma[entry].len,
14697ac6653aSJeff Kirsher 					       DMA_TO_DEVICE);
1470362b37beSGiuseppe CAVALLARO 			else
1471362b37beSGiuseppe CAVALLARO 				dma_unmap_single(priv->device,
14725bacd778SLABBE Corentin 						 priv->tx_skbuff_dma[entry].buf,
14735bacd778SLABBE Corentin 						 priv->tx_skbuff_dma[entry].len,
1474362b37beSGiuseppe CAVALLARO 						 DMA_TO_DEVICE);
14755bacd778SLABBE Corentin 			priv->tx_skbuff_dma[entry].buf = 0;
14765bacd778SLABBE Corentin 			priv->tx_skbuff_dma[entry].len = 0;
14775bacd778SLABBE Corentin 			priv->tx_skbuff_dma[entry].map_as_page = false;
1478cf32deecSRayagond Kokatanur 		}
1479f748be53SAlexandre TORGUE 
1480f748be53SAlexandre TORGUE 		if (priv->hw->mode->clean_desc3)
14815bacd778SLABBE Corentin 			priv->hw->mode->clean_desc3(priv, p);
1482f748be53SAlexandre TORGUE 
14835bacd778SLABBE Corentin 		priv->tx_skbuff_dma[entry].last_segment = false;
14845bacd778SLABBE Corentin 		priv->tx_skbuff_dma[entry].is_jumbo = false;
14857ac6653aSJeff Kirsher 
14867ac6653aSJeff Kirsher 		if (likely(skb != NULL)) {
148738979574SBeniamino Galvani 			pkts_compl++;
148838979574SBeniamino Galvani 			bytes_compl += skb->len;
14897c565c33SEric W. Biederman 			dev_consume_skb_any(skb);
14905bacd778SLABBE Corentin 			priv->tx_skbuff[entry] = NULL;
14917ac6653aSJeff Kirsher 		}
14927ac6653aSJeff Kirsher 
14934a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->release_tx_desc(p, priv->mode);
14947ac6653aSJeff Kirsher 
1495e3ad57c9SGiuseppe Cavallaro 		entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
14967ac6653aSJeff Kirsher 	}
14975bacd778SLABBE Corentin 	priv->dirty_tx = entry;
149838979574SBeniamino Galvani 
14995bacd778SLABBE Corentin 	netdev_completed_queue(priv->dev, pkts_compl, bytes_compl);
150038979574SBeniamino Galvani 
15015bacd778SLABBE Corentin 	if (unlikely(netif_queue_stopped(priv->dev) &&
15025bacd778SLABBE Corentin 	    stmmac_tx_avail(priv) > STMMAC_TX_THRESH)) {
1503b3e51069SLABBE Corentin 		netif_dbg(priv, tx_done, priv->dev,
1504b3e51069SLABBE Corentin 			  "%s: restart transmit\n", __func__);
15055bacd778SLABBE Corentin 		netif_wake_queue(priv->dev);
15067ac6653aSJeff Kirsher 	}
1507d765955dSGiuseppe CAVALLARO 
1508d765955dSGiuseppe CAVALLARO 	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
1509d765955dSGiuseppe CAVALLARO 		stmmac_enable_eee_mode(priv);
1510f5351ef7SGiuseppe CAVALLARO 		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
1511d765955dSGiuseppe CAVALLARO 	}
1512739c8e14SLino Sanfilippo 	netif_tx_unlock(priv->dev);
15137ac6653aSJeff Kirsher }
15147ac6653aSJeff Kirsher 
15154f513ecdSJoao Pinto static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv, u32 chan)
15167ac6653aSJeff Kirsher {
15174f513ecdSJoao Pinto 	priv->hw->dma->enable_dma_irq(priv->ioaddr, chan);
15187ac6653aSJeff Kirsher }
15197ac6653aSJeff Kirsher 
15204f513ecdSJoao Pinto static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv, u32 chan)
15217ac6653aSJeff Kirsher {
15224f513ecdSJoao Pinto 	priv->hw->dma->disable_dma_irq(priv->ioaddr, chan);
15237ac6653aSJeff Kirsher }
15247ac6653aSJeff Kirsher 
15257ac6653aSJeff Kirsher /**
1526732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_err - to manage the tx error
152732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
15285bacd778SLABBE Corentin  * @chan: channel index
15297ac6653aSJeff Kirsher  * Description: it cleans the descriptors and restarts the transmission
1530732fdf0eSGiuseppe CAVALLARO  * in case of transmission errors.
15317ac6653aSJeff Kirsher  */
15325bacd778SLABBE Corentin static void stmmac_tx_err(struct stmmac_priv *priv, u32 chan)
15337ac6653aSJeff Kirsher {
1534c24602efSGiuseppe CAVALLARO 	int i;
15355bacd778SLABBE Corentin 	netif_stop_queue(priv->dev);
15367ac6653aSJeff Kirsher 
1537ae4f0d46SJoao Pinto 	stmmac_stop_tx_dma(priv, chan);
15385bacd778SLABBE Corentin 	dma_free_tx_skbufs(priv);
1539e3ad57c9SGiuseppe Cavallaro 	for (i = 0; i < DMA_TX_SIZE; i++)
1540c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
15415bacd778SLABBE Corentin 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
1542c24602efSGiuseppe CAVALLARO 						     priv->mode,
1543e3ad57c9SGiuseppe Cavallaro 						     (i == DMA_TX_SIZE - 1));
1544c24602efSGiuseppe CAVALLARO 		else
15455bacd778SLABBE Corentin 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
1546c24602efSGiuseppe CAVALLARO 						     priv->mode,
1547e3ad57c9SGiuseppe Cavallaro 						     (i == DMA_TX_SIZE - 1));
15485bacd778SLABBE Corentin 	priv->dirty_tx = 0;
15495bacd778SLABBE Corentin 	priv->cur_tx = 0;
15505bacd778SLABBE Corentin 	netdev_reset_queue(priv->dev);
1551ae4f0d46SJoao Pinto 	stmmac_start_tx_dma(priv, chan);
15527ac6653aSJeff Kirsher 
15537ac6653aSJeff Kirsher 	priv->dev->stats.tx_errors++;
15545bacd778SLABBE Corentin 	netif_wake_queue(priv->dev);
15557ac6653aSJeff Kirsher }
15567ac6653aSJeff Kirsher 
155732ceabcaSGiuseppe CAVALLARO /**
15586deee222SJoao Pinto  *  stmmac_set_dma_operation_mode - Set DMA operation mode by channel
15596deee222SJoao Pinto  *  @priv: driver private structure
15606deee222SJoao Pinto  *  @txmode: TX operating mode
15616deee222SJoao Pinto  *  @rxmode: RX operating mode
15626deee222SJoao Pinto  *  @chan: channel index
15636deee222SJoao Pinto  *  Description: it is used for configuring of the DMA operation mode in
15646deee222SJoao Pinto  *  runtime in order to program the tx/rx DMA thresholds or Store-And-Forward
15656deee222SJoao Pinto  *  mode.
15666deee222SJoao Pinto  */
15676deee222SJoao Pinto static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode,
15686deee222SJoao Pinto 					  u32 rxmode, u32 chan)
15696deee222SJoao Pinto {
15706deee222SJoao Pinto 	int rxfifosz = priv->plat->rx_fifo_size;
15716deee222SJoao Pinto 
15726deee222SJoao Pinto 	if (rxfifosz == 0)
15736deee222SJoao Pinto 		rxfifosz = priv->dma_cap.rx_fifo_size;
15746deee222SJoao Pinto 
15756deee222SJoao Pinto 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
15766deee222SJoao Pinto 		priv->hw->dma->dma_rx_mode(priv->ioaddr, rxmode, chan,
15776deee222SJoao Pinto 					   rxfifosz);
15786deee222SJoao Pinto 		priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan);
15796deee222SJoao Pinto 	} else {
15806deee222SJoao Pinto 		priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode,
15816deee222SJoao Pinto 					rxfifosz);
15826deee222SJoao Pinto 	}
15836deee222SJoao Pinto }
15846deee222SJoao Pinto 
15856deee222SJoao Pinto /**
1586732fdf0eSGiuseppe CAVALLARO  * stmmac_dma_interrupt - DMA ISR
158732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
158832ceabcaSGiuseppe CAVALLARO  * Description: this is the DMA ISR. It is called by the main ISR.
1589732fdf0eSGiuseppe CAVALLARO  * It calls the dwmac dma routine and schedule poll method in case of some
1590732fdf0eSGiuseppe CAVALLARO  * work can be done.
159132ceabcaSGiuseppe CAVALLARO  */
15927ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv)
15937ac6653aSJeff Kirsher {
1594d62a107aSJoao Pinto 	u32 tx_channel_count = priv->plat->tx_queues_to_use;
15957ac6653aSJeff Kirsher 	int status;
1596d62a107aSJoao Pinto 	u32 chan;
159768e5cfafSJoao Pinto 
1598d62a107aSJoao Pinto 	for (chan = 0; chan < tx_channel_count; chan++) {
1599d62a107aSJoao Pinto 		status = priv->hw->dma->dma_interrupt(priv->ioaddr,
1600d62a107aSJoao Pinto 						      &priv->xstats, chan);
16019125cdd1SGiuseppe CAVALLARO 		if (likely((status & handle_rx)) || (status & handle_tx)) {
16025bacd778SLABBE Corentin 			if (likely(napi_schedule_prep(&priv->napi))) {
16034f513ecdSJoao Pinto 				stmmac_disable_dma_irq(priv, chan);
16045bacd778SLABBE Corentin 				__napi_schedule(&priv->napi);
16059125cdd1SGiuseppe CAVALLARO 			}
16069125cdd1SGiuseppe CAVALLARO 		}
1607d62a107aSJoao Pinto 
16089125cdd1SGiuseppe CAVALLARO 		if (unlikely(status & tx_hard_error_bump_tc)) {
16097ac6653aSJeff Kirsher 			/* Try to bump up the dma threshold on this failure */
1610b2dec116SSonic Zhang 			if (unlikely(priv->xstats.threshold != SF_DMA_MODE) &&
1611b2dec116SSonic Zhang 			    (tc <= 256)) {
16127ac6653aSJeff Kirsher 				tc += 64;
1613c405abe2SSonic Zhang 				if (priv->plat->force_thresh_dma_mode)
1614d62a107aSJoao Pinto 					stmmac_set_dma_operation_mode(priv,
1615d62a107aSJoao Pinto 								      tc,
1616d62a107aSJoao Pinto 								      tc,
1617d62a107aSJoao Pinto 								      chan);
1618c405abe2SSonic Zhang 				else
1619d62a107aSJoao Pinto 					stmmac_set_dma_operation_mode(priv,
1620d62a107aSJoao Pinto 								    tc,
1621d62a107aSJoao Pinto 								    SF_DMA_MODE,
1622d62a107aSJoao Pinto 								    chan);
16237ac6653aSJeff Kirsher 				priv->xstats.threshold = tc;
16247ac6653aSJeff Kirsher 			}
1625d62a107aSJoao Pinto 		} else if (unlikely(status == tx_hard_error)) {
16264e593262SJoao Pinto 			stmmac_tx_err(priv, chan);
16277ac6653aSJeff Kirsher 		}
1628d62a107aSJoao Pinto 	}
1629d62a107aSJoao Pinto }
16307ac6653aSJeff Kirsher 
163132ceabcaSGiuseppe CAVALLARO /**
163232ceabcaSGiuseppe CAVALLARO  * stmmac_mmc_setup: setup the Mac Management Counters (MMC)
163332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
163432ceabcaSGiuseppe CAVALLARO  * Description: this masks the MMC irq, in fact, the counters are managed in SW.
163532ceabcaSGiuseppe CAVALLARO  */
16361c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv)
16371c901a46SGiuseppe CAVALLARO {
16381c901a46SGiuseppe CAVALLARO 	unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
16391c901a46SGiuseppe CAVALLARO 			    MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
16401c901a46SGiuseppe CAVALLARO 
1641ba1ffd74SGiuseppe CAVALLARO 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
1642ba1ffd74SGiuseppe CAVALLARO 		priv->ptpaddr = priv->ioaddr + PTP_GMAC4_OFFSET;
1643f748be53SAlexandre TORGUE 		priv->mmcaddr = priv->ioaddr + MMC_GMAC4_OFFSET;
1644ba1ffd74SGiuseppe CAVALLARO 	} else {
1645ba1ffd74SGiuseppe CAVALLARO 		priv->ptpaddr = priv->ioaddr + PTP_GMAC3_X_OFFSET;
164636ff7c1eSAlexandre TORGUE 		priv->mmcaddr = priv->ioaddr + MMC_GMAC3_X_OFFSET;
1647ba1ffd74SGiuseppe CAVALLARO 	}
164836ff7c1eSAlexandre TORGUE 
164936ff7c1eSAlexandre TORGUE 	dwmac_mmc_intr_all_mask(priv->mmcaddr);
16504f795b25SGiuseppe CAVALLARO 
16514f795b25SGiuseppe CAVALLARO 	if (priv->dma_cap.rmon) {
165236ff7c1eSAlexandre TORGUE 		dwmac_mmc_ctrl(priv->mmcaddr, mode);
16531c901a46SGiuseppe CAVALLARO 		memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
16544f795b25SGiuseppe CAVALLARO 	} else
165538ddc59dSLABBE Corentin 		netdev_info(priv->dev, "No MAC Management Counters available\n");
16561c901a46SGiuseppe CAVALLARO }
16571c901a46SGiuseppe CAVALLARO 
1658732fdf0eSGiuseppe CAVALLARO /**
1659732fdf0eSGiuseppe CAVALLARO  * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors
166032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
166132ceabcaSGiuseppe CAVALLARO  * Description: select the Enhanced/Alternate or Normal descriptors.
1662732fdf0eSGiuseppe CAVALLARO  * In case of Enhanced/Alternate, it checks if the extended descriptors are
1663732fdf0eSGiuseppe CAVALLARO  * supported by the HW capability register.
1664ff3dd78cSGiuseppe CAVALLARO  */
166519e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
166619e30c14SGiuseppe CAVALLARO {
166719e30c14SGiuseppe CAVALLARO 	if (priv->plat->enh_desc) {
166838ddc59dSLABBE Corentin 		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
1669c24602efSGiuseppe CAVALLARO 
1670c24602efSGiuseppe CAVALLARO 		/* GMAC older than 3.50 has no extended descriptors */
1671c24602efSGiuseppe CAVALLARO 		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
167238ddc59dSLABBE Corentin 			dev_info(priv->device, "Enabled extended descriptors\n");
1673c24602efSGiuseppe CAVALLARO 			priv->extend_desc = 1;
1674c24602efSGiuseppe CAVALLARO 		} else
167538ddc59dSLABBE Corentin 			dev_warn(priv->device, "Extended descriptors not supported\n");
1676c24602efSGiuseppe CAVALLARO 
167719e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &enh_desc_ops;
167819e30c14SGiuseppe CAVALLARO 	} else {
167938ddc59dSLABBE Corentin 		dev_info(priv->device, "Normal descriptors\n");
168019e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &ndesc_ops;
168119e30c14SGiuseppe CAVALLARO 	}
168219e30c14SGiuseppe CAVALLARO }
168319e30c14SGiuseppe CAVALLARO 
168419e30c14SGiuseppe CAVALLARO /**
1685732fdf0eSGiuseppe CAVALLARO  * stmmac_get_hw_features - get MAC capabilities from the HW cap. register.
168632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
168719e30c14SGiuseppe CAVALLARO  * Description:
168819e30c14SGiuseppe CAVALLARO  *  new GMAC chip generations have a new register to indicate the
1689e7434821SGiuseppe CAVALLARO  *  presence of the optional feature/functions.
169019e30c14SGiuseppe CAVALLARO  *  This can be also used to override the value passed through the
169119e30c14SGiuseppe CAVALLARO  *  platform and necessary for old MAC10/100 and GMAC chips.
1692e7434821SGiuseppe CAVALLARO  */
1693e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv)
1694e7434821SGiuseppe CAVALLARO {
1695f10a6a35SAlexandre TORGUE 	u32 ret = 0;
16963c20f72fSGiuseppe CAVALLARO 
16975e6efe88SGiuseppe CAVALLARO 	if (priv->hw->dma->get_hw_feature) {
1698f10a6a35SAlexandre TORGUE 		priv->hw->dma->get_hw_feature(priv->ioaddr,
1699f10a6a35SAlexandre TORGUE 					      &priv->dma_cap);
1700f10a6a35SAlexandre TORGUE 		ret = 1;
170119e30c14SGiuseppe CAVALLARO 	}
1702e7434821SGiuseppe CAVALLARO 
1703f10a6a35SAlexandre TORGUE 	return ret;
1704e7434821SGiuseppe CAVALLARO }
1705e7434821SGiuseppe CAVALLARO 
170632ceabcaSGiuseppe CAVALLARO /**
1707732fdf0eSGiuseppe CAVALLARO  * stmmac_check_ether_addr - check if the MAC addr is valid
170832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
170932ceabcaSGiuseppe CAVALLARO  * Description:
171032ceabcaSGiuseppe CAVALLARO  * it is to verify if the MAC address is valid, in case of failures it
171132ceabcaSGiuseppe CAVALLARO  * generates a random MAC address
171232ceabcaSGiuseppe CAVALLARO  */
1713bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv)
1714bfab27a1SGiuseppe CAVALLARO {
1715bfab27a1SGiuseppe CAVALLARO 	if (!is_valid_ether_addr(priv->dev->dev_addr)) {
17167ed24bbeSVince Bridgers 		priv->hw->mac->get_umac_addr(priv->hw,
1717bfab27a1SGiuseppe CAVALLARO 					     priv->dev->dev_addr, 0);
1718bfab27a1SGiuseppe CAVALLARO 		if (!is_valid_ether_addr(priv->dev->dev_addr))
1719f2cedb63SDanny Kukawka 			eth_hw_addr_random(priv->dev);
172038ddc59dSLABBE Corentin 		netdev_info(priv->dev, "device MAC address %pM\n",
1721bfab27a1SGiuseppe CAVALLARO 			    priv->dev->dev_addr);
1722bfab27a1SGiuseppe CAVALLARO 	}
1723c88460b7SHans de Goede }
1724bfab27a1SGiuseppe CAVALLARO 
172532ceabcaSGiuseppe CAVALLARO /**
1726732fdf0eSGiuseppe CAVALLARO  * stmmac_init_dma_engine - DMA init.
172732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
172832ceabcaSGiuseppe CAVALLARO  * Description:
172932ceabcaSGiuseppe CAVALLARO  * It inits the DMA invoking the specific MAC/GMAC callback.
173032ceabcaSGiuseppe CAVALLARO  * Some DMA parameters can be passed from the platform;
173132ceabcaSGiuseppe CAVALLARO  * in case of these are not passed a default is kept for the MAC or GMAC.
173232ceabcaSGiuseppe CAVALLARO  */
17330f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv)
17340f1f88a8SGiuseppe CAVALLARO {
173547f2a9ceSJoao Pinto 	u32 rx_channels_count = priv->plat->rx_queues_to_use;
173647f2a9ceSJoao Pinto 	u32 tx_channels_count = priv->plat->tx_queues_to_use;
173747f2a9ceSJoao Pinto 	u32 dummy_dma_rx_phy = 0;
173847f2a9ceSJoao Pinto 	u32 dummy_dma_tx_phy = 0;
173947f2a9ceSJoao Pinto 	u32 chan = 0;
1740c24602efSGiuseppe CAVALLARO 	int atds = 0;
1741495db273SGiuseppe Cavallaro 	int ret = 0;
17420f1f88a8SGiuseppe CAVALLARO 
1743a332e2faSNiklas Cassel 	if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) {
1744a332e2faSNiklas Cassel 		dev_err(priv->device, "Invalid DMA configuration\n");
174589ab75bfSNiklas Cassel 		return -EINVAL;
17460f1f88a8SGiuseppe CAVALLARO 	}
17470f1f88a8SGiuseppe CAVALLARO 
1748c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
1749c24602efSGiuseppe CAVALLARO 		atds = 1;
1750c24602efSGiuseppe CAVALLARO 
1751495db273SGiuseppe Cavallaro 	ret = priv->hw->dma->reset(priv->ioaddr);
1752495db273SGiuseppe Cavallaro 	if (ret) {
1753495db273SGiuseppe Cavallaro 		dev_err(priv->device, "Failed to reset the dma\n");
1754495db273SGiuseppe Cavallaro 		return ret;
1755495db273SGiuseppe Cavallaro 	}
1756495db273SGiuseppe Cavallaro 
1757f748be53SAlexandre TORGUE 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
175847f2a9ceSJoao Pinto 		/* DMA Configuration */
175947f2a9ceSJoao Pinto 		priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg,
176047f2a9ceSJoao Pinto 				    dummy_dma_tx_phy, dummy_dma_rx_phy, atds);
176147f2a9ceSJoao Pinto 
176247f2a9ceSJoao Pinto 		/* DMA RX Channel Configuration */
176347f2a9ceSJoao Pinto 		for (chan = 0; chan < rx_channels_count; chan++) {
176447f2a9ceSJoao Pinto 			priv->hw->dma->init_rx_chan(priv->ioaddr,
176547f2a9ceSJoao Pinto 						    priv->plat->dma_cfg,
17665bacd778SLABBE Corentin 						    priv->dma_rx_phy, chan);
176747f2a9ceSJoao Pinto 
17685bacd778SLABBE Corentin 			priv->rx_tail_addr = priv->dma_rx_phy +
1769f748be53SAlexandre TORGUE 				    (DMA_RX_SIZE * sizeof(struct dma_desc));
177047f2a9ceSJoao Pinto 			priv->hw->dma->set_rx_tail_ptr(priv->ioaddr,
17715bacd778SLABBE Corentin 						       priv->rx_tail_addr,
177247f2a9ceSJoao Pinto 						       chan);
177347f2a9ceSJoao Pinto 		}
177447f2a9ceSJoao Pinto 
177547f2a9ceSJoao Pinto 		/* DMA TX Channel Configuration */
177647f2a9ceSJoao Pinto 		for (chan = 0; chan < tx_channels_count; chan++) {
177747f2a9ceSJoao Pinto 			priv->hw->dma->init_chan(priv->ioaddr,
177847f2a9ceSJoao Pinto 							priv->plat->dma_cfg,
177947f2a9ceSJoao Pinto 							chan);
178047f2a9ceSJoao Pinto 
178147f2a9ceSJoao Pinto 			priv->hw->dma->init_tx_chan(priv->ioaddr,
178247f2a9ceSJoao Pinto 						    priv->plat->dma_cfg,
17835bacd778SLABBE Corentin 						    priv->dma_tx_phy, chan);
1784f748be53SAlexandre TORGUE 
17855bacd778SLABBE Corentin 			priv->tx_tail_addr = priv->dma_tx_phy +
1786f748be53SAlexandre TORGUE 				    (DMA_TX_SIZE * sizeof(struct dma_desc));
178747f2a9ceSJoao Pinto 			priv->hw->dma->set_tx_tail_ptr(priv->ioaddr,
17885bacd778SLABBE Corentin 						       priv->tx_tail_addr,
178947f2a9ceSJoao Pinto 						       chan);
179047f2a9ceSJoao Pinto 		}
179147f2a9ceSJoao Pinto 	} else {
179247f2a9ceSJoao Pinto 		priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg,
17935bacd778SLABBE Corentin 				    priv->dma_tx_phy, priv->dma_rx_phy, atds);
1794f748be53SAlexandre TORGUE 	}
1795f748be53SAlexandre TORGUE 
1796f748be53SAlexandre TORGUE 	if (priv->plat->axi && priv->hw->dma->axi)
1797afea0365SGiuseppe Cavallaro 		priv->hw->dma->axi(priv->ioaddr, priv->plat->axi);
1798afea0365SGiuseppe Cavallaro 
1799495db273SGiuseppe Cavallaro 	return ret;
18000f1f88a8SGiuseppe CAVALLARO }
18010f1f88a8SGiuseppe CAVALLARO 
1802bfab27a1SGiuseppe CAVALLARO /**
1803732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_timer - mitigation sw timer for tx.
18049125cdd1SGiuseppe CAVALLARO  * @data: data pointer
18059125cdd1SGiuseppe CAVALLARO  * Description:
18069125cdd1SGiuseppe CAVALLARO  * This is the timer handler to directly invoke the stmmac_tx_clean.
18079125cdd1SGiuseppe CAVALLARO  */
18089125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data)
18099125cdd1SGiuseppe CAVALLARO {
18109125cdd1SGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)data;
18119125cdd1SGiuseppe CAVALLARO 
18125bacd778SLABBE Corentin 	stmmac_tx_clean(priv);
18139125cdd1SGiuseppe CAVALLARO }
18149125cdd1SGiuseppe CAVALLARO 
18159125cdd1SGiuseppe CAVALLARO /**
1816732fdf0eSGiuseppe CAVALLARO  * stmmac_init_tx_coalesce - init tx mitigation options.
181732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
18189125cdd1SGiuseppe CAVALLARO  * Description:
18199125cdd1SGiuseppe CAVALLARO  * This inits the transmit coalesce parameters: i.e. timer rate,
18209125cdd1SGiuseppe CAVALLARO  * timer handler and default threshold used for enabling the
18219125cdd1SGiuseppe CAVALLARO  * interrupt on completion bit.
18229125cdd1SGiuseppe CAVALLARO  */
18239125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
18249125cdd1SGiuseppe CAVALLARO {
18259125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_frames = STMMAC_TX_FRAMES;
18269125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
18279125cdd1SGiuseppe CAVALLARO 	init_timer(&priv->txtimer);
18289125cdd1SGiuseppe CAVALLARO 	priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
18299125cdd1SGiuseppe CAVALLARO 	priv->txtimer.data = (unsigned long)priv;
18309125cdd1SGiuseppe CAVALLARO 	priv->txtimer.function = stmmac_tx_timer;
18319125cdd1SGiuseppe CAVALLARO 	add_timer(&priv->txtimer);
18329125cdd1SGiuseppe CAVALLARO }
18339125cdd1SGiuseppe CAVALLARO 
18344854ab99SJoao Pinto static void stmmac_set_rings_length(struct stmmac_priv *priv)
18354854ab99SJoao Pinto {
18364854ab99SJoao Pinto 	u32 rx_channels_count = priv->plat->rx_queues_to_use;
18374854ab99SJoao Pinto 	u32 tx_channels_count = priv->plat->tx_queues_to_use;
18384854ab99SJoao Pinto 	u32 chan;
18394854ab99SJoao Pinto 
18404854ab99SJoao Pinto 	/* set TX ring length */
18414854ab99SJoao Pinto 	if (priv->hw->dma->set_tx_ring_len) {
18424854ab99SJoao Pinto 		for (chan = 0; chan < tx_channels_count; chan++)
18434854ab99SJoao Pinto 			priv->hw->dma->set_tx_ring_len(priv->ioaddr,
18444854ab99SJoao Pinto 						       (DMA_TX_SIZE - 1), chan);
18454854ab99SJoao Pinto 	}
18464854ab99SJoao Pinto 
18474854ab99SJoao Pinto 	/* set RX ring length */
18484854ab99SJoao Pinto 	if (priv->hw->dma->set_rx_ring_len) {
18494854ab99SJoao Pinto 		for (chan = 0; chan < rx_channels_count; chan++)
18504854ab99SJoao Pinto 			priv->hw->dma->set_rx_ring_len(priv->ioaddr,
18514854ab99SJoao Pinto 						       (DMA_RX_SIZE - 1), chan);
18524854ab99SJoao Pinto 	}
18534854ab99SJoao Pinto }
18544854ab99SJoao Pinto 
18559125cdd1SGiuseppe CAVALLARO /**
18566a3a7193SJoao Pinto  *  stmmac_set_tx_queue_weight - Set TX queue weight
18576a3a7193SJoao Pinto  *  @priv: driver private structure
18586a3a7193SJoao Pinto  *  Description: It is used for setting TX queues weight
18596a3a7193SJoao Pinto  */
18606a3a7193SJoao Pinto static void stmmac_set_tx_queue_weight(struct stmmac_priv *priv)
18616a3a7193SJoao Pinto {
18626a3a7193SJoao Pinto 	u32 tx_queues_count = priv->plat->tx_queues_to_use;
18636a3a7193SJoao Pinto 	u32 weight;
18646a3a7193SJoao Pinto 	u32 queue;
18656a3a7193SJoao Pinto 
18666a3a7193SJoao Pinto 	for (queue = 0; queue < tx_queues_count; queue++) {
18676a3a7193SJoao Pinto 		weight = priv->plat->tx_queues_cfg[queue].weight;
18686a3a7193SJoao Pinto 		priv->hw->mac->set_mtl_tx_queue_weight(priv->hw, weight, queue);
18696a3a7193SJoao Pinto 	}
18706a3a7193SJoao Pinto }
18716a3a7193SJoao Pinto 
18726a3a7193SJoao Pinto /**
187319d91873SJoao Pinto  *  stmmac_configure_cbs - Configure CBS in TX queue
187419d91873SJoao Pinto  *  @priv: driver private structure
187519d91873SJoao Pinto  *  Description: It is used for configuring CBS in AVB TX queues
187619d91873SJoao Pinto  */
187719d91873SJoao Pinto static void stmmac_configure_cbs(struct stmmac_priv *priv)
187819d91873SJoao Pinto {
187919d91873SJoao Pinto 	u32 tx_queues_count = priv->plat->tx_queues_to_use;
188019d91873SJoao Pinto 	u32 mode_to_use;
188119d91873SJoao Pinto 	u32 queue;
188219d91873SJoao Pinto 
188344781fefSJoao Pinto 	/* queue 0 is reserved for legacy traffic */
188444781fefSJoao Pinto 	for (queue = 1; queue < tx_queues_count; queue++) {
188519d91873SJoao Pinto 		mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use;
188619d91873SJoao Pinto 		if (mode_to_use == MTL_QUEUE_DCB)
188719d91873SJoao Pinto 			continue;
188819d91873SJoao Pinto 
188919d91873SJoao Pinto 		priv->hw->mac->config_cbs(priv->hw,
189019d91873SJoao Pinto 				priv->plat->tx_queues_cfg[queue].send_slope,
189119d91873SJoao Pinto 				priv->plat->tx_queues_cfg[queue].idle_slope,
189219d91873SJoao Pinto 				priv->plat->tx_queues_cfg[queue].high_credit,
189319d91873SJoao Pinto 				priv->plat->tx_queues_cfg[queue].low_credit,
189419d91873SJoao Pinto 				queue);
189519d91873SJoao Pinto 	}
189619d91873SJoao Pinto }
189719d91873SJoao Pinto 
189819d91873SJoao Pinto /**
1899d43042f4SJoao Pinto  *  stmmac_rx_queue_dma_chan_map - Map RX queue to RX dma channel
1900d43042f4SJoao Pinto  *  @priv: driver private structure
1901d43042f4SJoao Pinto  *  Description: It is used for mapping RX queues to RX dma channels
1902d43042f4SJoao Pinto  */
1903d43042f4SJoao Pinto static void stmmac_rx_queue_dma_chan_map(struct stmmac_priv *priv)
1904d43042f4SJoao Pinto {
1905d43042f4SJoao Pinto 	u32 rx_queues_count = priv->plat->rx_queues_to_use;
1906d43042f4SJoao Pinto 	u32 queue;
1907d43042f4SJoao Pinto 	u32 chan;
1908d43042f4SJoao Pinto 
1909d43042f4SJoao Pinto 	for (queue = 0; queue < rx_queues_count; queue++) {
1910d43042f4SJoao Pinto 		chan = priv->plat->rx_queues_cfg[queue].chan;
1911d43042f4SJoao Pinto 		priv->hw->mac->map_mtl_to_dma(priv->hw, queue, chan);
1912d43042f4SJoao Pinto 	}
1913d43042f4SJoao Pinto }
1914d43042f4SJoao Pinto 
1915d43042f4SJoao Pinto /**
1916a8f5102aSJoao Pinto  *  stmmac_mac_config_rx_queues_prio - Configure RX Queue priority
1917a8f5102aSJoao Pinto  *  @priv: driver private structure
1918a8f5102aSJoao Pinto  *  Description: It is used for configuring the RX Queue Priority
1919a8f5102aSJoao Pinto  */
1920a8f5102aSJoao Pinto static void stmmac_mac_config_rx_queues_prio(struct stmmac_priv *priv)
1921a8f5102aSJoao Pinto {
1922a8f5102aSJoao Pinto 	u32 rx_queues_count = priv->plat->rx_queues_to_use;
1923a8f5102aSJoao Pinto 	u32 queue;
1924a8f5102aSJoao Pinto 	u32 prio;
1925a8f5102aSJoao Pinto 
1926a8f5102aSJoao Pinto 	for (queue = 0; queue < rx_queues_count; queue++) {
1927a8f5102aSJoao Pinto 		if (!priv->plat->rx_queues_cfg[queue].use_prio)
1928a8f5102aSJoao Pinto 			continue;
1929a8f5102aSJoao Pinto 
1930a8f5102aSJoao Pinto 		prio = priv->plat->rx_queues_cfg[queue].prio;
1931a8f5102aSJoao Pinto 		priv->hw->mac->rx_queue_prio(priv->hw, prio, queue);
1932a8f5102aSJoao Pinto 	}
1933a8f5102aSJoao Pinto }
1934a8f5102aSJoao Pinto 
1935a8f5102aSJoao Pinto /**
1936a8f5102aSJoao Pinto  *  stmmac_mac_config_tx_queues_prio - Configure TX Queue priority
1937a8f5102aSJoao Pinto  *  @priv: driver private structure
1938a8f5102aSJoao Pinto  *  Description: It is used for configuring the TX Queue Priority
1939a8f5102aSJoao Pinto  */
1940a8f5102aSJoao Pinto static void stmmac_mac_config_tx_queues_prio(struct stmmac_priv *priv)
1941a8f5102aSJoao Pinto {
1942a8f5102aSJoao Pinto 	u32 tx_queues_count = priv->plat->tx_queues_to_use;
1943a8f5102aSJoao Pinto 	u32 queue;
1944a8f5102aSJoao Pinto 	u32 prio;
1945a8f5102aSJoao Pinto 
1946a8f5102aSJoao Pinto 	for (queue = 0; queue < tx_queues_count; queue++) {
1947a8f5102aSJoao Pinto 		if (!priv->plat->tx_queues_cfg[queue].use_prio)
1948a8f5102aSJoao Pinto 			continue;
1949a8f5102aSJoao Pinto 
1950a8f5102aSJoao Pinto 		prio = priv->plat->tx_queues_cfg[queue].prio;
1951a8f5102aSJoao Pinto 		priv->hw->mac->tx_queue_prio(priv->hw, prio, queue);
1952a8f5102aSJoao Pinto 	}
1953a8f5102aSJoao Pinto }
1954a8f5102aSJoao Pinto 
1955a8f5102aSJoao Pinto /**
1956abe80fdcSJoao Pinto  *  stmmac_mac_config_rx_queues_routing - Configure RX Queue Routing
1957abe80fdcSJoao Pinto  *  @priv: driver private structure
1958abe80fdcSJoao Pinto  *  Description: It is used for configuring the RX queue routing
1959abe80fdcSJoao Pinto  */
1960abe80fdcSJoao Pinto static void stmmac_mac_config_rx_queues_routing(struct stmmac_priv *priv)
1961abe80fdcSJoao Pinto {
1962abe80fdcSJoao Pinto 	u32 rx_queues_count = priv->plat->rx_queues_to_use;
1963abe80fdcSJoao Pinto 	u32 queue;
1964abe80fdcSJoao Pinto 	u8 packet;
1965abe80fdcSJoao Pinto 
1966abe80fdcSJoao Pinto 	for (queue = 0; queue < rx_queues_count; queue++) {
1967abe80fdcSJoao Pinto 		/* no specific packet type routing specified for the queue */
1968abe80fdcSJoao Pinto 		if (priv->plat->rx_queues_cfg[queue].pkt_route == 0x0)
1969abe80fdcSJoao Pinto 			continue;
1970abe80fdcSJoao Pinto 
1971abe80fdcSJoao Pinto 		packet = priv->plat->rx_queues_cfg[queue].pkt_route;
1972abe80fdcSJoao Pinto 		priv->hw->mac->rx_queue_prio(priv->hw, packet, queue);
1973abe80fdcSJoao Pinto 	}
1974abe80fdcSJoao Pinto }
1975abe80fdcSJoao Pinto 
1976abe80fdcSJoao Pinto /**
1977d0a9c9f9SJoao Pinto  *  stmmac_mtl_configuration - Configure MTL
1978d0a9c9f9SJoao Pinto  *  @priv: driver private structure
1979d0a9c9f9SJoao Pinto  *  Description: It is used for configurring MTL
1980d0a9c9f9SJoao Pinto  */
1981d0a9c9f9SJoao Pinto static void stmmac_mtl_configuration(struct stmmac_priv *priv)
1982d0a9c9f9SJoao Pinto {
1983d0a9c9f9SJoao Pinto 	u32 rx_queues_count = priv->plat->rx_queues_to_use;
1984d0a9c9f9SJoao Pinto 	u32 tx_queues_count = priv->plat->tx_queues_to_use;
1985d0a9c9f9SJoao Pinto 
19866a3a7193SJoao Pinto 	if (tx_queues_count > 1 && priv->hw->mac->set_mtl_tx_queue_weight)
19876a3a7193SJoao Pinto 		stmmac_set_tx_queue_weight(priv);
19886a3a7193SJoao Pinto 
1989d0a9c9f9SJoao Pinto 	/* Configure MTL RX algorithms */
1990d0a9c9f9SJoao Pinto 	if (rx_queues_count > 1 && priv->hw->mac->prog_mtl_rx_algorithms)
1991d0a9c9f9SJoao Pinto 		priv->hw->mac->prog_mtl_rx_algorithms(priv->hw,
1992d0a9c9f9SJoao Pinto 						priv->plat->rx_sched_algorithm);
1993d0a9c9f9SJoao Pinto 
1994d0a9c9f9SJoao Pinto 	/* Configure MTL TX algorithms */
1995d0a9c9f9SJoao Pinto 	if (tx_queues_count > 1 && priv->hw->mac->prog_mtl_tx_algorithms)
1996d0a9c9f9SJoao Pinto 		priv->hw->mac->prog_mtl_tx_algorithms(priv->hw,
1997d0a9c9f9SJoao Pinto 						priv->plat->tx_sched_algorithm);
1998d0a9c9f9SJoao Pinto 
199919d91873SJoao Pinto 	/* Configure CBS in AVB TX queues */
200019d91873SJoao Pinto 	if (tx_queues_count > 1 && priv->hw->mac->config_cbs)
200119d91873SJoao Pinto 		stmmac_configure_cbs(priv);
200219d91873SJoao Pinto 
2003d43042f4SJoao Pinto 	/* Map RX MTL to DMA channels */
200403cf65a9SJoao Pinto 	if (priv->hw->mac->map_mtl_to_dma)
2005d43042f4SJoao Pinto 		stmmac_rx_queue_dma_chan_map(priv);
2006d43042f4SJoao Pinto 
2007d0a9c9f9SJoao Pinto 	/* Enable MAC RX Queues */
2008f3976874SThierry Reding 	if (priv->hw->mac->rx_queue_enable)
2009d0a9c9f9SJoao Pinto 		stmmac_mac_enable_rx_queues(priv);
20106deee222SJoao Pinto 
2011a8f5102aSJoao Pinto 	/* Set RX priorities */
2012a8f5102aSJoao Pinto 	if (rx_queues_count > 1 && priv->hw->mac->rx_queue_prio)
2013a8f5102aSJoao Pinto 		stmmac_mac_config_rx_queues_prio(priv);
2014a8f5102aSJoao Pinto 
2015a8f5102aSJoao Pinto 	/* Set TX priorities */
2016a8f5102aSJoao Pinto 	if (tx_queues_count > 1 && priv->hw->mac->tx_queue_prio)
2017a8f5102aSJoao Pinto 		stmmac_mac_config_tx_queues_prio(priv);
2018abe80fdcSJoao Pinto 
2019abe80fdcSJoao Pinto 	/* Set RX routing */
2020abe80fdcSJoao Pinto 	if (rx_queues_count > 1 && priv->hw->mac->rx_queue_routing)
2021abe80fdcSJoao Pinto 		stmmac_mac_config_rx_queues_routing(priv);
2022d0a9c9f9SJoao Pinto }
2023d0a9c9f9SJoao Pinto 
2024d0a9c9f9SJoao Pinto /**
2025732fdf0eSGiuseppe CAVALLARO  * stmmac_hw_setup - setup mac in a usable state.
2026523f11b5SSrinivas Kandagatla  *  @dev : pointer to the device structure.
2027523f11b5SSrinivas Kandagatla  *  Description:
2028732fdf0eSGiuseppe CAVALLARO  *  this is the main function to setup the HW in a usable state because the
2029732fdf0eSGiuseppe CAVALLARO  *  dma engine is reset, the core registers are configured (e.g. AXI,
2030732fdf0eSGiuseppe CAVALLARO  *  Checksum features, timers). The DMA is ready to start receiving and
2031732fdf0eSGiuseppe CAVALLARO  *  transmitting.
2032523f11b5SSrinivas Kandagatla  *  Return value:
2033523f11b5SSrinivas Kandagatla  *  0 on success and an appropriate (-)ve integer as defined in errno.h
2034523f11b5SSrinivas Kandagatla  *  file on failure.
2035523f11b5SSrinivas Kandagatla  */
2036fe131929SHuacai Chen static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
2037523f11b5SSrinivas Kandagatla {
2038523f11b5SSrinivas Kandagatla 	struct stmmac_priv *priv = netdev_priv(dev);
20393c55d4d0SJoao Pinto 	u32 rx_cnt = priv->plat->rx_queues_to_use;
2040146617b8SJoao Pinto 	u32 tx_cnt = priv->plat->tx_queues_to_use;
2041146617b8SJoao Pinto 	u32 chan;
2042523f11b5SSrinivas Kandagatla 	int ret;
2043523f11b5SSrinivas Kandagatla 
2044523f11b5SSrinivas Kandagatla 	/* DMA initialization and SW reset */
2045523f11b5SSrinivas Kandagatla 	ret = stmmac_init_dma_engine(priv);
2046523f11b5SSrinivas Kandagatla 	if (ret < 0) {
204738ddc59dSLABBE Corentin 		netdev_err(priv->dev, "%s: DMA engine initialization failed\n",
204838ddc59dSLABBE Corentin 			   __func__);
2049523f11b5SSrinivas Kandagatla 		return ret;
2050523f11b5SSrinivas Kandagatla 	}
2051523f11b5SSrinivas Kandagatla 
2052523f11b5SSrinivas Kandagatla 	/* Copy the MAC addr into the HW  */
20537ed24bbeSVince Bridgers 	priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0);
2054523f11b5SSrinivas Kandagatla 
205502e57b9dSGiuseppe CAVALLARO 	/* PS and related bits will be programmed according to the speed */
205602e57b9dSGiuseppe CAVALLARO 	if (priv->hw->pcs) {
205702e57b9dSGiuseppe CAVALLARO 		int speed = priv->plat->mac_port_sel_speed;
205802e57b9dSGiuseppe CAVALLARO 
205902e57b9dSGiuseppe CAVALLARO 		if ((speed == SPEED_10) || (speed == SPEED_100) ||
206002e57b9dSGiuseppe CAVALLARO 		    (speed == SPEED_1000)) {
206102e57b9dSGiuseppe CAVALLARO 			priv->hw->ps = speed;
206202e57b9dSGiuseppe CAVALLARO 		} else {
206302e57b9dSGiuseppe CAVALLARO 			dev_warn(priv->device, "invalid port speed\n");
206402e57b9dSGiuseppe CAVALLARO 			priv->hw->ps = 0;
206502e57b9dSGiuseppe CAVALLARO 		}
206602e57b9dSGiuseppe CAVALLARO 	}
206702e57b9dSGiuseppe CAVALLARO 
2068523f11b5SSrinivas Kandagatla 	/* Initialize the MAC Core */
20697ed24bbeSVince Bridgers 	priv->hw->mac->core_init(priv->hw, dev->mtu);
2070523f11b5SSrinivas Kandagatla 
2071d0a9c9f9SJoao Pinto 	/* Initialize MTL*/
2072d0a9c9f9SJoao Pinto 	if (priv->synopsys_id >= DWMAC_CORE_4_00)
2073d0a9c9f9SJoao Pinto 		stmmac_mtl_configuration(priv);
20749eb12474Sjpinto 
2075978aded4SGiuseppe CAVALLARO 	ret = priv->hw->mac->rx_ipc(priv->hw);
2076978aded4SGiuseppe CAVALLARO 	if (!ret) {
207738ddc59dSLABBE Corentin 		netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n");
2078978aded4SGiuseppe CAVALLARO 		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
2079d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
2080978aded4SGiuseppe CAVALLARO 	}
2081978aded4SGiuseppe CAVALLARO 
2082523f11b5SSrinivas Kandagatla 	/* Enable the MAC Rx/Tx */
2083270c7759SLABBE Corentin 	priv->hw->mac->set_mac(priv->ioaddr, true);
2084523f11b5SSrinivas Kandagatla 
2085b4f0a661SJoao Pinto 	/* Set the HW DMA mode and the COE */
2086b4f0a661SJoao Pinto 	stmmac_dma_operation_mode(priv);
2087b4f0a661SJoao Pinto 
2088523f11b5SSrinivas Kandagatla 	stmmac_mmc_setup(priv);
2089523f11b5SSrinivas Kandagatla 
2090fe131929SHuacai Chen 	if (init_ptp) {
20910ad2be79SThierry Reding 		ret = clk_prepare_enable(priv->plat->clk_ptp_ref);
20920ad2be79SThierry Reding 		if (ret < 0)
20930ad2be79SThierry Reding 			netdev_warn(priv->dev, "failed to enable PTP reference clock: %d\n", ret);
20940ad2be79SThierry Reding 
2095523f11b5SSrinivas Kandagatla 		ret = stmmac_init_ptp(priv);
2096722eef28SHeiner Kallweit 		if (ret == -EOPNOTSUPP)
2097722eef28SHeiner Kallweit 			netdev_warn(priv->dev, "PTP not supported by HW\n");
2098722eef28SHeiner Kallweit 		else if (ret)
2099722eef28SHeiner Kallweit 			netdev_warn(priv->dev, "PTP init failed\n");
2100fe131929SHuacai Chen 	}
2101523f11b5SSrinivas Kandagatla 
210250fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
2103523f11b5SSrinivas Kandagatla 	ret = stmmac_init_fs(dev);
2104523f11b5SSrinivas Kandagatla 	if (ret < 0)
210538ddc59dSLABBE Corentin 		netdev_warn(priv->dev, "%s: failed debugFS registration\n",
210638ddc59dSLABBE Corentin 			    __func__);
2107523f11b5SSrinivas Kandagatla #endif
2108523f11b5SSrinivas Kandagatla 	/* Start the ball rolling... */
2109ae4f0d46SJoao Pinto 	stmmac_start_all_dma(priv);
2110523f11b5SSrinivas Kandagatla 
2111523f11b5SSrinivas Kandagatla 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
2112523f11b5SSrinivas Kandagatla 
2113523f11b5SSrinivas Kandagatla 	if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
2114523f11b5SSrinivas Kandagatla 		priv->rx_riwt = MAX_DMA_RIWT;
21153c55d4d0SJoao Pinto 		priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT, rx_cnt);
2116523f11b5SSrinivas Kandagatla 	}
2117523f11b5SSrinivas Kandagatla 
21183fe5cadbSGiuseppe CAVALLARO 	if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane)
211902e57b9dSGiuseppe CAVALLARO 		priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, priv->hw->ps, 0);
2120523f11b5SSrinivas Kandagatla 
21214854ab99SJoao Pinto 	/* set TX and RX rings length */
21224854ab99SJoao Pinto 	stmmac_set_rings_length(priv);
21234854ab99SJoao Pinto 
2124f748be53SAlexandre TORGUE 	/* Enable TSO */
2125146617b8SJoao Pinto 	if (priv->tso) {
2126146617b8SJoao Pinto 		for (chan = 0; chan < tx_cnt; chan++)
2127146617b8SJoao Pinto 			priv->hw->dma->enable_tso(priv->ioaddr, 1, chan);
2128146617b8SJoao Pinto 	}
2129f748be53SAlexandre TORGUE 
2130523f11b5SSrinivas Kandagatla 	return 0;
2131523f11b5SSrinivas Kandagatla }
2132523f11b5SSrinivas Kandagatla 
2133c66f6c37SThierry Reding static void stmmac_hw_teardown(struct net_device *dev)
2134c66f6c37SThierry Reding {
2135c66f6c37SThierry Reding 	struct stmmac_priv *priv = netdev_priv(dev);
2136c66f6c37SThierry Reding 
2137c66f6c37SThierry Reding 	clk_disable_unprepare(priv->plat->clk_ptp_ref);
2138c66f6c37SThierry Reding }
2139c66f6c37SThierry Reding 
2140523f11b5SSrinivas Kandagatla /**
21417ac6653aSJeff Kirsher  *  stmmac_open - open entry point of the driver
21427ac6653aSJeff Kirsher  *  @dev : pointer to the device structure.
21437ac6653aSJeff Kirsher  *  Description:
21447ac6653aSJeff Kirsher  *  This function is the open entry point of the driver.
21457ac6653aSJeff Kirsher  *  Return value:
21467ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
21477ac6653aSJeff Kirsher  *  file on failure.
21487ac6653aSJeff Kirsher  */
21497ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev)
21507ac6653aSJeff Kirsher {
21517ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
21527ac6653aSJeff Kirsher 	int ret;
21537ac6653aSJeff Kirsher 
21544bfcbd7aSFrancesco Virlinzi 	stmmac_check_ether_addr(priv);
21554bfcbd7aSFrancesco Virlinzi 
21563fe5cadbSGiuseppe CAVALLARO 	if (priv->hw->pcs != STMMAC_PCS_RGMII &&
21573fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_TBI &&
21583fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_RTBI) {
21597ac6653aSJeff Kirsher 		ret = stmmac_init_phy(dev);
2160e58bb43fSGiuseppe CAVALLARO 		if (ret) {
216138ddc59dSLABBE Corentin 			netdev_err(priv->dev,
216238ddc59dSLABBE Corentin 				   "%s: Cannot attach to PHY (error: %d)\n",
2163e58bb43fSGiuseppe CAVALLARO 				   __func__, ret);
216489df20d9SHans de Goede 			return ret;
21657ac6653aSJeff Kirsher 		}
2166e58bb43fSGiuseppe CAVALLARO 	}
21677ac6653aSJeff Kirsher 
2168523f11b5SSrinivas Kandagatla 	/* Extra statistics */
2169523f11b5SSrinivas Kandagatla 	memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
2170523f11b5SSrinivas Kandagatla 	priv->xstats.threshold = tc;
2171523f11b5SSrinivas Kandagatla 
21725bacd778SLABBE Corentin 	priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
217322ad3838SGiuseppe Cavallaro 	priv->rx_copybreak = STMMAC_RX_COPYBREAK;
217456329137SBartlomiej Zolnierkiewicz 
21755bacd778SLABBE Corentin 	ret = alloc_dma_desc_resources(priv);
21765bacd778SLABBE Corentin 	if (ret < 0) {
21775bacd778SLABBE Corentin 		netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n",
21785bacd778SLABBE Corentin 			   __func__);
21795bacd778SLABBE Corentin 		goto dma_desc_error;
21805bacd778SLABBE Corentin 	}
21815bacd778SLABBE Corentin 
21825bacd778SLABBE Corentin 	ret = init_dma_desc_rings(dev, GFP_KERNEL);
21835bacd778SLABBE Corentin 	if (ret < 0) {
21845bacd778SLABBE Corentin 		netdev_err(priv->dev, "%s: DMA descriptors initialization failed\n",
21855bacd778SLABBE Corentin 			   __func__);
21865bacd778SLABBE Corentin 		goto init_error;
21875bacd778SLABBE Corentin 	}
21885bacd778SLABBE Corentin 
2189fe131929SHuacai Chen 	ret = stmmac_hw_setup(dev, true);
219056329137SBartlomiej Zolnierkiewicz 	if (ret < 0) {
219138ddc59dSLABBE Corentin 		netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
2192c9324d18SGiuseppe CAVALLARO 		goto init_error;
21937ac6653aSJeff Kirsher 	}
21947ac6653aSJeff Kirsher 
2195777da230SGiuseppe CAVALLARO 	stmmac_init_tx_coalesce(priv);
2196777da230SGiuseppe CAVALLARO 
2197d6d50c7eSPhilippe Reynes 	if (dev->phydev)
2198d6d50c7eSPhilippe Reynes 		phy_start(dev->phydev);
21997ac6653aSJeff Kirsher 
22007ac6653aSJeff Kirsher 	/* Request the IRQ lines */
22017ac6653aSJeff Kirsher 	ret = request_irq(dev->irq, stmmac_interrupt,
22027ac6653aSJeff Kirsher 			  IRQF_SHARED, dev->name, dev);
22037ac6653aSJeff Kirsher 	if (unlikely(ret < 0)) {
220438ddc59dSLABBE Corentin 		netdev_err(priv->dev,
220538ddc59dSLABBE Corentin 			   "%s: ERROR: allocating the IRQ %d (error: %d)\n",
22067ac6653aSJeff Kirsher 			   __func__, dev->irq, ret);
22076c1e5abeSThierry Reding 		goto irq_error;
22087ac6653aSJeff Kirsher 	}
22097ac6653aSJeff Kirsher 
22107a13f8f5SFrancesco Virlinzi 	/* Request the Wake IRQ in case of another line is used for WoL */
22117a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq) {
22127a13f8f5SFrancesco Virlinzi 		ret = request_irq(priv->wol_irq, stmmac_interrupt,
22137a13f8f5SFrancesco Virlinzi 				  IRQF_SHARED, dev->name, dev);
22147a13f8f5SFrancesco Virlinzi 		if (unlikely(ret < 0)) {
221538ddc59dSLABBE Corentin 			netdev_err(priv->dev,
221638ddc59dSLABBE Corentin 				   "%s: ERROR: allocating the WoL IRQ %d (%d)\n",
2217ceb69499SGiuseppe CAVALLARO 				   __func__, priv->wol_irq, ret);
2218c9324d18SGiuseppe CAVALLARO 			goto wolirq_error;
22197a13f8f5SFrancesco Virlinzi 		}
22207a13f8f5SFrancesco Virlinzi 	}
22217a13f8f5SFrancesco Virlinzi 
2222d765955dSGiuseppe CAVALLARO 	/* Request the IRQ lines */
2223d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0) {
2224d765955dSGiuseppe CAVALLARO 		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
2225d765955dSGiuseppe CAVALLARO 				  dev->name, dev);
2226d765955dSGiuseppe CAVALLARO 		if (unlikely(ret < 0)) {
222738ddc59dSLABBE Corentin 			netdev_err(priv->dev,
222838ddc59dSLABBE Corentin 				   "%s: ERROR: allocating the LPI IRQ %d (%d)\n",
2229d765955dSGiuseppe CAVALLARO 				   __func__, priv->lpi_irq, ret);
2230c9324d18SGiuseppe CAVALLARO 			goto lpiirq_error;
2231d765955dSGiuseppe CAVALLARO 		}
2232d765955dSGiuseppe CAVALLARO 	}
2233d765955dSGiuseppe CAVALLARO 
22345bacd778SLABBE Corentin 	napi_enable(&priv->napi);
22355bacd778SLABBE Corentin 	netif_start_queue(dev);
22367ac6653aSJeff Kirsher 
22377ac6653aSJeff Kirsher 	return 0;
22387ac6653aSJeff Kirsher 
2239c9324d18SGiuseppe CAVALLARO lpiirq_error:
2240d765955dSGiuseppe CAVALLARO 	if (priv->wol_irq != dev->irq)
2241d765955dSGiuseppe CAVALLARO 		free_irq(priv->wol_irq, dev);
2242c9324d18SGiuseppe CAVALLARO wolirq_error:
22437a13f8f5SFrancesco Virlinzi 	free_irq(dev->irq, dev);
22446c1e5abeSThierry Reding irq_error:
22456c1e5abeSThierry Reding 	if (dev->phydev)
22466c1e5abeSThierry Reding 		phy_stop(dev->phydev);
22477a13f8f5SFrancesco Virlinzi 
22486c1e5abeSThierry Reding 	del_timer_sync(&priv->txtimer);
2249c66f6c37SThierry Reding 	stmmac_hw_teardown(dev);
2250c9324d18SGiuseppe CAVALLARO init_error:
2251c9324d18SGiuseppe CAVALLARO 	free_dma_desc_resources(priv);
22525bacd778SLABBE Corentin dma_desc_error:
2253d6d50c7eSPhilippe Reynes 	if (dev->phydev)
2254d6d50c7eSPhilippe Reynes 		phy_disconnect(dev->phydev);
22554bfcbd7aSFrancesco Virlinzi 
22567ac6653aSJeff Kirsher 	return ret;
22577ac6653aSJeff Kirsher }
22587ac6653aSJeff Kirsher 
22597ac6653aSJeff Kirsher /**
22607ac6653aSJeff Kirsher  *  stmmac_release - close entry point of the driver
22617ac6653aSJeff Kirsher  *  @dev : device pointer.
22627ac6653aSJeff Kirsher  *  Description:
22637ac6653aSJeff Kirsher  *  This is the stop entry point of the driver.
22647ac6653aSJeff Kirsher  */
22657ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev)
22667ac6653aSJeff Kirsher {
22677ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22687ac6653aSJeff Kirsher 
2269d765955dSGiuseppe CAVALLARO 	if (priv->eee_enabled)
2270d765955dSGiuseppe CAVALLARO 		del_timer_sync(&priv->eee_ctrl_timer);
2271d765955dSGiuseppe CAVALLARO 
22727ac6653aSJeff Kirsher 	/* Stop and disconnect the PHY */
2273d6d50c7eSPhilippe Reynes 	if (dev->phydev) {
2274d6d50c7eSPhilippe Reynes 		phy_stop(dev->phydev);
2275d6d50c7eSPhilippe Reynes 		phy_disconnect(dev->phydev);
22767ac6653aSJeff Kirsher 	}
22777ac6653aSJeff Kirsher 
22785bacd778SLABBE Corentin 	netif_stop_queue(dev);
22797ac6653aSJeff Kirsher 
22805bacd778SLABBE Corentin 	napi_disable(&priv->napi);
22817ac6653aSJeff Kirsher 
22829125cdd1SGiuseppe CAVALLARO 	del_timer_sync(&priv->txtimer);
22839125cdd1SGiuseppe CAVALLARO 
22847ac6653aSJeff Kirsher 	/* Free the IRQ lines */
22857ac6653aSJeff Kirsher 	free_irq(dev->irq, dev);
22867a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq)
22877a13f8f5SFrancesco Virlinzi 		free_irq(priv->wol_irq, dev);
2288d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0)
2289d765955dSGiuseppe CAVALLARO 		free_irq(priv->lpi_irq, dev);
22907ac6653aSJeff Kirsher 
22917ac6653aSJeff Kirsher 	/* Stop TX/RX DMA and clear the descriptors */
2292ae4f0d46SJoao Pinto 	stmmac_stop_all_dma(priv);
22937ac6653aSJeff Kirsher 
22947ac6653aSJeff Kirsher 	/* Release and free the Rx/Tx resources */
22957ac6653aSJeff Kirsher 	free_dma_desc_resources(priv);
22967ac6653aSJeff Kirsher 
22977ac6653aSJeff Kirsher 	/* Disable the MAC Rx/Tx */
2298270c7759SLABBE Corentin 	priv->hw->mac->set_mac(priv->ioaddr, false);
22997ac6653aSJeff Kirsher 
23007ac6653aSJeff Kirsher 	netif_carrier_off(dev);
23017ac6653aSJeff Kirsher 
230250fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
2303466c5ac8SMathieu Olivari 	stmmac_exit_fs(dev);
2304bfab27a1SGiuseppe CAVALLARO #endif
2305bfab27a1SGiuseppe CAVALLARO 
230692ba6888SRayagond Kokatanur 	stmmac_release_ptp(priv);
230792ba6888SRayagond Kokatanur 
23087ac6653aSJeff Kirsher 	return 0;
23097ac6653aSJeff Kirsher }
23107ac6653aSJeff Kirsher 
23117ac6653aSJeff Kirsher /**
2312f748be53SAlexandre TORGUE  *  stmmac_tso_allocator - close entry point of the driver
2313f748be53SAlexandre TORGUE  *  @priv: driver private structure
2314f748be53SAlexandre TORGUE  *  @des: buffer start address
2315f748be53SAlexandre TORGUE  *  @total_len: total length to fill in descriptors
2316f748be53SAlexandre TORGUE  *  @last_segmant: condition for the last descriptor
2317f748be53SAlexandre TORGUE  *  Description:
2318f748be53SAlexandre TORGUE  *  This function fills descriptor and request new descriptors according to
2319f748be53SAlexandre TORGUE  *  buffer length to fill
2320f748be53SAlexandre TORGUE  */
2321f748be53SAlexandre TORGUE static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
23225bacd778SLABBE Corentin 				 int total_len, bool last_segment)
2323f748be53SAlexandre TORGUE {
2324f748be53SAlexandre TORGUE 	struct dma_desc *desc;
2325aff3d9efSJoao Pinto 	int tmp_len;
23265bacd778SLABBE Corentin 	u32 buff_size;
2327f748be53SAlexandre TORGUE 
2328f748be53SAlexandre TORGUE 	tmp_len = total_len;
2329f748be53SAlexandre TORGUE 
2330f748be53SAlexandre TORGUE 	while (tmp_len > 0) {
23315bacd778SLABBE Corentin 		priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE);
23325bacd778SLABBE Corentin 		desc = priv->dma_tx + priv->cur_tx;
2333f748be53SAlexandre TORGUE 
2334f8be0d78SMichael Weiser 		desc->des0 = cpu_to_le32(des + (total_len - tmp_len));
2335f748be53SAlexandre TORGUE 		buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ?
2336f748be53SAlexandre TORGUE 			    TSO_MAX_BUFF_SIZE : tmp_len;
2337f748be53SAlexandre TORGUE 
2338f748be53SAlexandre TORGUE 		priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size,
2339f748be53SAlexandre TORGUE 			0, 1,
2340f748be53SAlexandre TORGUE 			(last_segment) && (buff_size < TSO_MAX_BUFF_SIZE),
2341f748be53SAlexandre TORGUE 			0, 0);
2342f748be53SAlexandre TORGUE 
2343f748be53SAlexandre TORGUE 		tmp_len -= TSO_MAX_BUFF_SIZE;
2344f748be53SAlexandre TORGUE 	}
2345f748be53SAlexandre TORGUE }
2346f748be53SAlexandre TORGUE 
2347f748be53SAlexandre TORGUE /**
2348f748be53SAlexandre TORGUE  *  stmmac_tso_xmit - Tx entry point of the driver for oversized frames (TSO)
2349f748be53SAlexandre TORGUE  *  @skb : the socket buffer
2350f748be53SAlexandre TORGUE  *  @dev : device pointer
2351f748be53SAlexandre TORGUE  *  Description: this is the transmit function that is called on TSO frames
2352f748be53SAlexandre TORGUE  *  (support available on GMAC4 and newer chips).
2353f748be53SAlexandre TORGUE  *  Diagram below show the ring programming in case of TSO frames:
2354f748be53SAlexandre TORGUE  *
2355f748be53SAlexandre TORGUE  *  First Descriptor
2356f748be53SAlexandre TORGUE  *   --------
2357f748be53SAlexandre TORGUE  *   | DES0 |---> buffer1 = L2/L3/L4 header
2358f748be53SAlexandre TORGUE  *   | DES1 |---> TCP Payload (can continue on next descr...)
2359f748be53SAlexandre TORGUE  *   | DES2 |---> buffer 1 and 2 len
2360f748be53SAlexandre TORGUE  *   | DES3 |---> must set TSE, TCP hdr len-> [22:19]. TCP payload len [17:0]
2361f748be53SAlexandre TORGUE  *   --------
2362f748be53SAlexandre TORGUE  *	|
2363f748be53SAlexandre TORGUE  *     ...
2364f748be53SAlexandre TORGUE  *	|
2365f748be53SAlexandre TORGUE  *   --------
2366f748be53SAlexandre TORGUE  *   | DES0 | --| Split TCP Payload on Buffers 1 and 2
2367f748be53SAlexandre TORGUE  *   | DES1 | --|
2368f748be53SAlexandre TORGUE  *   | DES2 | --> buffer 1 and 2 len
2369f748be53SAlexandre TORGUE  *   | DES3 |
2370f748be53SAlexandre TORGUE  *   --------
2371f748be53SAlexandre TORGUE  *
2372f748be53SAlexandre TORGUE  * mss is fixed when enable tso, so w/o programming the TDES3 ctx field.
2373f748be53SAlexandre TORGUE  */
2374f748be53SAlexandre TORGUE static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
2375f748be53SAlexandre TORGUE {
23765bacd778SLABBE Corentin 	u32 pay_len, mss;
23775bacd778SLABBE Corentin 	int tmp_pay_len = 0;
2378f748be53SAlexandre TORGUE 	struct stmmac_priv *priv = netdev_priv(dev);
2379f748be53SAlexandre TORGUE 	int nfrags = skb_shinfo(skb)->nr_frags;
2380f748be53SAlexandre TORGUE 	unsigned int first_entry, des;
23815bacd778SLABBE Corentin 	struct dma_desc *desc, *first, *mss_desc = NULL;
2382f748be53SAlexandre TORGUE 	u8 proto_hdr_len;
2383f748be53SAlexandre TORGUE 	int i;
2384f748be53SAlexandre TORGUE 
2385f748be53SAlexandre TORGUE 	/* Compute header lengths */
2386f748be53SAlexandre TORGUE 	proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
2387f748be53SAlexandre TORGUE 
2388f748be53SAlexandre TORGUE 	/* Desc availability based on threshold should be enough safe */
23895bacd778SLABBE Corentin 	if (unlikely(stmmac_tx_avail(priv) <
2390f748be53SAlexandre TORGUE 		(((skb->len - proto_hdr_len) / TSO_MAX_BUFF_SIZE + 1)))) {
23915bacd778SLABBE Corentin 		if (!netif_queue_stopped(dev)) {
23925bacd778SLABBE Corentin 			netif_stop_queue(dev);
2393f748be53SAlexandre TORGUE 			/* This is a hard error, log it. */
239438ddc59dSLABBE Corentin 			netdev_err(priv->dev,
239538ddc59dSLABBE Corentin 				   "%s: Tx Ring full when queue awake\n",
239638ddc59dSLABBE Corentin 				   __func__);
2397f748be53SAlexandre TORGUE 		}
2398f748be53SAlexandre TORGUE 		return NETDEV_TX_BUSY;
2399f748be53SAlexandre TORGUE 	}
2400f748be53SAlexandre TORGUE 
2401f748be53SAlexandre TORGUE 	pay_len = skb_headlen(skb) - proto_hdr_len; /* no frags */
2402f748be53SAlexandre TORGUE 
2403f748be53SAlexandre TORGUE 	mss = skb_shinfo(skb)->gso_size;
2404f748be53SAlexandre TORGUE 
2405f748be53SAlexandre TORGUE 	/* set new MSS value if needed */
2406f748be53SAlexandre TORGUE 	if (mss != priv->mss) {
24075bacd778SLABBE Corentin 		mss_desc = priv->dma_tx + priv->cur_tx;
2408f748be53SAlexandre TORGUE 		priv->hw->desc->set_mss(mss_desc, mss);
2409f748be53SAlexandre TORGUE 		priv->mss = mss;
24105bacd778SLABBE Corentin 		priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE);
2411f748be53SAlexandre TORGUE 	}
2412f748be53SAlexandre TORGUE 
2413f748be53SAlexandre TORGUE 	if (netif_msg_tx_queued(priv)) {
2414f748be53SAlexandre TORGUE 		pr_info("%s: tcphdrlen %d, hdr_len %d, pay_len %d, mss %d\n",
2415f748be53SAlexandre TORGUE 			__func__, tcp_hdrlen(skb), proto_hdr_len, pay_len, mss);
2416f748be53SAlexandre TORGUE 		pr_info("\tskb->len %d, skb->data_len %d\n", skb->len,
2417f748be53SAlexandre TORGUE 			skb->data_len);
2418f748be53SAlexandre TORGUE 	}
2419f748be53SAlexandre TORGUE 
24205bacd778SLABBE Corentin 	first_entry = priv->cur_tx;
2421f748be53SAlexandre TORGUE 
24225bacd778SLABBE Corentin 	desc = priv->dma_tx + first_entry;
2423f748be53SAlexandre TORGUE 	first = desc;
2424f748be53SAlexandre TORGUE 
2425f748be53SAlexandre TORGUE 	/* first descriptor: fill Headers on Buf1 */
2426f748be53SAlexandre TORGUE 	des = dma_map_single(priv->device, skb->data, skb_headlen(skb),
2427f748be53SAlexandre TORGUE 			     DMA_TO_DEVICE);
2428f748be53SAlexandre TORGUE 	if (dma_mapping_error(priv->device, des))
2429f748be53SAlexandre TORGUE 		goto dma_map_err;
2430f748be53SAlexandre TORGUE 
24315bacd778SLABBE Corentin 	priv->tx_skbuff_dma[first_entry].buf = des;
24325bacd778SLABBE Corentin 	priv->tx_skbuff_dma[first_entry].len = skb_headlen(skb);
24335bacd778SLABBE Corentin 	priv->tx_skbuff[first_entry] = skb;
2434f748be53SAlexandre TORGUE 
2435f8be0d78SMichael Weiser 	first->des0 = cpu_to_le32(des);
2436f748be53SAlexandre TORGUE 
2437f748be53SAlexandre TORGUE 	/* Fill start of payload in buff2 of first descriptor */
2438f748be53SAlexandre TORGUE 	if (pay_len)
2439f8be0d78SMichael Weiser 		first->des1 = cpu_to_le32(des + proto_hdr_len);
2440f748be53SAlexandre TORGUE 
2441f748be53SAlexandre TORGUE 	/* If needed take extra descriptors to fill the remaining payload */
2442f748be53SAlexandre TORGUE 	tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE;
2443f748be53SAlexandre TORGUE 
24445bacd778SLABBE Corentin 	stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0));
2445f748be53SAlexandre TORGUE 
2446f748be53SAlexandre TORGUE 	/* Prepare fragments */
2447f748be53SAlexandre TORGUE 	for (i = 0; i < nfrags; i++) {
2448f748be53SAlexandre TORGUE 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
2449f748be53SAlexandre TORGUE 
2450f748be53SAlexandre TORGUE 		des = skb_frag_dma_map(priv->device, frag, 0,
2451f748be53SAlexandre TORGUE 				       skb_frag_size(frag),
2452f748be53SAlexandre TORGUE 				       DMA_TO_DEVICE);
2453937071c1SThierry Reding 		if (dma_mapping_error(priv->device, des))
2454937071c1SThierry Reding 			goto dma_map_err;
2455f748be53SAlexandre TORGUE 
2456f748be53SAlexandre TORGUE 		stmmac_tso_allocator(priv, des, skb_frag_size(frag),
24575bacd778SLABBE Corentin 				     (i == nfrags - 1));
2458f748be53SAlexandre TORGUE 
24595bacd778SLABBE Corentin 		priv->tx_skbuff_dma[priv->cur_tx].buf = des;
24605bacd778SLABBE Corentin 		priv->tx_skbuff_dma[priv->cur_tx].len = skb_frag_size(frag);
24615bacd778SLABBE Corentin 		priv->tx_skbuff[priv->cur_tx] = NULL;
24625bacd778SLABBE Corentin 		priv->tx_skbuff_dma[priv->cur_tx].map_as_page = true;
2463f748be53SAlexandre TORGUE 	}
2464f748be53SAlexandre TORGUE 
24655bacd778SLABBE Corentin 	priv->tx_skbuff_dma[priv->cur_tx].last_segment = true;
2466f748be53SAlexandre TORGUE 
24675bacd778SLABBE Corentin 	priv->cur_tx = STMMAC_GET_ENTRY(priv->cur_tx, DMA_TX_SIZE);
2468f748be53SAlexandre TORGUE 
24695bacd778SLABBE Corentin 	if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
2470b3e51069SLABBE Corentin 		netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n",
247138ddc59dSLABBE Corentin 			  __func__);
24725bacd778SLABBE Corentin 		netif_stop_queue(dev);
2473f748be53SAlexandre TORGUE 	}
2474f748be53SAlexandre TORGUE 
2475f748be53SAlexandre TORGUE 	dev->stats.tx_bytes += skb->len;
2476f748be53SAlexandre TORGUE 	priv->xstats.tx_tso_frames++;
2477f748be53SAlexandre TORGUE 	priv->xstats.tx_tso_nfrags += nfrags;
2478f748be53SAlexandre TORGUE 
2479f748be53SAlexandre TORGUE 	/* Manage tx mitigation */
2480f748be53SAlexandre TORGUE 	priv->tx_count_frames += nfrags + 1;
2481f748be53SAlexandre TORGUE 	if (likely(priv->tx_coal_frames > priv->tx_count_frames)) {
2482f748be53SAlexandre TORGUE 		mod_timer(&priv->txtimer,
2483f748be53SAlexandre TORGUE 			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
2484f748be53SAlexandre TORGUE 	} else {
2485f748be53SAlexandre TORGUE 		priv->tx_count_frames = 0;
2486f748be53SAlexandre TORGUE 		priv->hw->desc->set_tx_ic(desc);
2487f748be53SAlexandre TORGUE 		priv->xstats.tx_set_ic_bit++;
2488f748be53SAlexandre TORGUE 	}
2489f748be53SAlexandre TORGUE 
2490f748be53SAlexandre TORGUE 	if (!priv->hwts_tx_en)
2491f748be53SAlexandre TORGUE 		skb_tx_timestamp(skb);
2492f748be53SAlexandre TORGUE 
2493f748be53SAlexandre TORGUE 	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
2494f748be53SAlexandre TORGUE 		     priv->hwts_tx_en)) {
2495f748be53SAlexandre TORGUE 		/* declare that device is doing timestamping */
2496f748be53SAlexandre TORGUE 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
2497f748be53SAlexandre TORGUE 		priv->hw->desc->enable_tx_timestamp(first);
2498f748be53SAlexandre TORGUE 	}
2499f748be53SAlexandre TORGUE 
2500f748be53SAlexandre TORGUE 	/* Complete the first descriptor before granting the DMA */
2501f748be53SAlexandre TORGUE 	priv->hw->desc->prepare_tso_tx_desc(first, 1,
2502f748be53SAlexandre TORGUE 			proto_hdr_len,
2503f748be53SAlexandre TORGUE 			pay_len,
25045bacd778SLABBE Corentin 			1, priv->tx_skbuff_dma[first_entry].last_segment,
2505f748be53SAlexandre TORGUE 			tcp_hdrlen(skb) / 4, (skb->len - proto_hdr_len));
2506f748be53SAlexandre TORGUE 
2507f748be53SAlexandre TORGUE 	/* If context desc is used to change MSS */
2508f748be53SAlexandre TORGUE 	if (mss_desc)
2509f748be53SAlexandre TORGUE 		priv->hw->desc->set_tx_owner(mss_desc);
2510f748be53SAlexandre TORGUE 
2511f748be53SAlexandre TORGUE 	/* The own bit must be the latest setting done when prepare the
2512f748be53SAlexandre TORGUE 	 * descriptor and then barrier is needed to make sure that
2513f748be53SAlexandre TORGUE 	 * all is coherent before granting the DMA engine.
2514f748be53SAlexandre TORGUE 	 */
2515ad688cdbSPavel Machek 	dma_wmb();
2516f748be53SAlexandre TORGUE 
2517f748be53SAlexandre TORGUE 	if (netif_msg_pktdata(priv)) {
2518f748be53SAlexandre TORGUE 		pr_info("%s: curr=%d dirty=%d f=%d, e=%d, f_p=%p, nfrags %d\n",
25195bacd778SLABBE Corentin 			__func__, priv->cur_tx, priv->dirty_tx, first_entry,
25205bacd778SLABBE Corentin 			priv->cur_tx, first, nfrags);
2521f748be53SAlexandre TORGUE 
25225bacd778SLABBE Corentin 		priv->hw->desc->display_ring((void *)priv->dma_tx, DMA_TX_SIZE,
2523f748be53SAlexandre TORGUE 					     0);
2524f748be53SAlexandre TORGUE 
2525f748be53SAlexandre TORGUE 		pr_info(">>> frame to be transmitted: ");
2526f748be53SAlexandre TORGUE 		print_pkt(skb->data, skb_headlen(skb));
2527f748be53SAlexandre TORGUE 	}
2528f748be53SAlexandre TORGUE 
25295bacd778SLABBE Corentin 	netdev_sent_queue(dev, skb->len);
2530f748be53SAlexandre TORGUE 
25315bacd778SLABBE Corentin 	priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr,
25325bacd778SLABBE Corentin 				       STMMAC_CHAN0);
2533f748be53SAlexandre TORGUE 
2534f748be53SAlexandre TORGUE 	return NETDEV_TX_OK;
2535f748be53SAlexandre TORGUE 
2536f748be53SAlexandre TORGUE dma_map_err:
2537f748be53SAlexandre TORGUE 	dev_err(priv->device, "Tx dma map failed\n");
2538f748be53SAlexandre TORGUE 	dev_kfree_skb(skb);
2539f748be53SAlexandre TORGUE 	priv->dev->stats.tx_dropped++;
2540f748be53SAlexandre TORGUE 	return NETDEV_TX_OK;
2541f748be53SAlexandre TORGUE }
2542f748be53SAlexandre TORGUE 
2543f748be53SAlexandre TORGUE /**
2544732fdf0eSGiuseppe CAVALLARO  *  stmmac_xmit - Tx entry point of the driver
25457ac6653aSJeff Kirsher  *  @skb : the socket buffer
25467ac6653aSJeff Kirsher  *  @dev : device pointer
254732ceabcaSGiuseppe CAVALLARO  *  Description : this is the tx entry point of the driver.
254832ceabcaSGiuseppe CAVALLARO  *  It programs the chain or the ring and supports oversized frames
254932ceabcaSGiuseppe CAVALLARO  *  and SG feature.
25507ac6653aSJeff Kirsher  */
25517ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
25527ac6653aSJeff Kirsher {
25537ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
25540e80bdc9SGiuseppe Cavallaro 	unsigned int nopaged_len = skb_headlen(skb);
25554a7d666aSGiuseppe CAVALLARO 	int i, csum_insertion = 0, is_jumbo = 0;
25567ac6653aSJeff Kirsher 	int nfrags = skb_shinfo(skb)->nr_frags;
25570e80bdc9SGiuseppe Cavallaro 	unsigned int entry, first_entry;
25587ac6653aSJeff Kirsher 	struct dma_desc *desc, *first;
25590e80bdc9SGiuseppe Cavallaro 	unsigned int enh_desc;
2560f748be53SAlexandre TORGUE 	unsigned int des;
2561f748be53SAlexandre TORGUE 
2562f748be53SAlexandre TORGUE 	/* Manage oversized TCP frames for GMAC4 device */
2563f748be53SAlexandre TORGUE 	if (skb_is_gso(skb) && priv->tso) {
2564f748be53SAlexandre TORGUE 		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
2565f748be53SAlexandre TORGUE 			return stmmac_tso_xmit(skb, dev);
2566f748be53SAlexandre TORGUE 	}
25677ac6653aSJeff Kirsher 
25685bacd778SLABBE Corentin 	if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
25695bacd778SLABBE Corentin 		if (!netif_queue_stopped(dev)) {
25705bacd778SLABBE Corentin 			netif_stop_queue(dev);
25717ac6653aSJeff Kirsher 			/* This is a hard error, log it. */
257238ddc59dSLABBE Corentin 			netdev_err(priv->dev,
257338ddc59dSLABBE Corentin 				   "%s: Tx Ring full when queue awake\n",
257438ddc59dSLABBE Corentin 				   __func__);
25757ac6653aSJeff Kirsher 		}
25767ac6653aSJeff Kirsher 		return NETDEV_TX_BUSY;
25777ac6653aSJeff Kirsher 	}
25787ac6653aSJeff Kirsher 
2579d765955dSGiuseppe CAVALLARO 	if (priv->tx_path_in_lpi_mode)
2580d765955dSGiuseppe CAVALLARO 		stmmac_disable_eee_mode(priv);
2581d765955dSGiuseppe CAVALLARO 
25825bacd778SLABBE Corentin 	entry = priv->cur_tx;
25830e80bdc9SGiuseppe Cavallaro 	first_entry = entry;
25847ac6653aSJeff Kirsher 
25857ac6653aSJeff Kirsher 	csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
25867ac6653aSJeff Kirsher 
25870e80bdc9SGiuseppe Cavallaro 	if (likely(priv->extend_desc))
25885bacd778SLABBE Corentin 		desc = (struct dma_desc *)(priv->dma_etx + entry);
2589c24602efSGiuseppe CAVALLARO 	else
25905bacd778SLABBE Corentin 		desc = priv->dma_tx + entry;
2591c24602efSGiuseppe CAVALLARO 
25927ac6653aSJeff Kirsher 	first = desc;
25937ac6653aSJeff Kirsher 
25945bacd778SLABBE Corentin 	priv->tx_skbuff[first_entry] = skb;
25950e80bdc9SGiuseppe Cavallaro 
25960e80bdc9SGiuseppe Cavallaro 	enh_desc = priv->plat->enh_desc;
25974a7d666aSGiuseppe CAVALLARO 	/* To program the descriptors according to the size of the frame */
259829896a67SGiuseppe CAVALLARO 	if (enh_desc)
259929896a67SGiuseppe CAVALLARO 		is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc);
260029896a67SGiuseppe CAVALLARO 
2601f748be53SAlexandre TORGUE 	if (unlikely(is_jumbo) && likely(priv->synopsys_id <
2602f748be53SAlexandre TORGUE 					 DWMAC_CORE_4_00)) {
26035bacd778SLABBE Corentin 		entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion);
2604362b37beSGiuseppe CAVALLARO 		if (unlikely(entry < 0))
2605362b37beSGiuseppe CAVALLARO 			goto dma_map_err;
260629896a67SGiuseppe CAVALLARO 	}
26077ac6653aSJeff Kirsher 
26087ac6653aSJeff Kirsher 	for (i = 0; i < nfrags; i++) {
26099e903e08SEric Dumazet 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
26109e903e08SEric Dumazet 		int len = skb_frag_size(frag);
2611be434d50SGiuseppe Cavallaro 		bool last_segment = (i == (nfrags - 1));
26127ac6653aSJeff Kirsher 
2613e3ad57c9SGiuseppe Cavallaro 		entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
2614e3ad57c9SGiuseppe Cavallaro 
26150e80bdc9SGiuseppe Cavallaro 		if (likely(priv->extend_desc))
26165bacd778SLABBE Corentin 			desc = (struct dma_desc *)(priv->dma_etx + entry);
2617c24602efSGiuseppe CAVALLARO 		else
26185bacd778SLABBE Corentin 			desc = priv->dma_tx + entry;
26197ac6653aSJeff Kirsher 
2620f748be53SAlexandre TORGUE 		des = skb_frag_dma_map(priv->device, frag, 0, len,
2621f722380dSIan Campbell 				       DMA_TO_DEVICE);
2622f748be53SAlexandre TORGUE 		if (dma_mapping_error(priv->device, des))
2623362b37beSGiuseppe CAVALLARO 			goto dma_map_err; /* should reuse desc w/o issues */
2624362b37beSGiuseppe CAVALLARO 
26255bacd778SLABBE Corentin 		priv->tx_skbuff[entry] = NULL;
2626f748be53SAlexandre TORGUE 
26275bacd778SLABBE Corentin 		priv->tx_skbuff_dma[entry].buf = des;
2628f8be0d78SMichael Weiser 		if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
2629f8be0d78SMichael Weiser 			desc->des0 = cpu_to_le32(des);
2630f8be0d78SMichael Weiser 		else
2631f8be0d78SMichael Weiser 			desc->des2 = cpu_to_le32(des);
2632f748be53SAlexandre TORGUE 
26335bacd778SLABBE Corentin 		priv->tx_skbuff_dma[entry].map_as_page = true;
26345bacd778SLABBE Corentin 		priv->tx_skbuff_dma[entry].len = len;
26355bacd778SLABBE Corentin 		priv->tx_skbuff_dma[entry].last_segment = last_segment;
26360e80bdc9SGiuseppe Cavallaro 
26370e80bdc9SGiuseppe Cavallaro 		/* Prepare the descriptor and set the own bit too */
26384a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
2639be434d50SGiuseppe Cavallaro 						priv->mode, 1, last_segment);
26407ac6653aSJeff Kirsher 	}
26417ac6653aSJeff Kirsher 
2642e3ad57c9SGiuseppe Cavallaro 	entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
2643e3ad57c9SGiuseppe Cavallaro 
26445bacd778SLABBE Corentin 	priv->cur_tx = entry;
26457ac6653aSJeff Kirsher 
26467ac6653aSJeff Kirsher 	if (netif_msg_pktdata(priv)) {
2647d0225e7dSAlexandre TORGUE 		void *tx_head;
2648d0225e7dSAlexandre TORGUE 
264938ddc59dSLABBE Corentin 		netdev_dbg(priv->dev,
265038ddc59dSLABBE Corentin 			   "%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d",
26515bacd778SLABBE Corentin 			   __func__, priv->cur_tx, priv->dirty_tx, first_entry,
26520e80bdc9SGiuseppe Cavallaro 			   entry, first, nfrags);
265383d7af64SGiuseppe CAVALLARO 
2654c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
26555bacd778SLABBE Corentin 			tx_head = (void *)priv->dma_etx;
2656c24602efSGiuseppe CAVALLARO 		else
26575bacd778SLABBE Corentin 			tx_head = (void *)priv->dma_tx;
2658d0225e7dSAlexandre TORGUE 
2659d0225e7dSAlexandre TORGUE 		priv->hw->desc->display_ring(tx_head, DMA_TX_SIZE, false);
2660c24602efSGiuseppe CAVALLARO 
266138ddc59dSLABBE Corentin 		netdev_dbg(priv->dev, ">>> frame to be transmitted: ");
26627ac6653aSJeff Kirsher 		print_pkt(skb->data, skb->len);
26637ac6653aSJeff Kirsher 	}
26640e80bdc9SGiuseppe Cavallaro 
26655bacd778SLABBE Corentin 	if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
2666b3e51069SLABBE Corentin 		netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n",
2667b3e51069SLABBE Corentin 			  __func__);
26685bacd778SLABBE Corentin 		netif_stop_queue(dev);
26697ac6653aSJeff Kirsher 	}
26707ac6653aSJeff Kirsher 
26717ac6653aSJeff Kirsher 	dev->stats.tx_bytes += skb->len;
26727ac6653aSJeff Kirsher 
26730e80bdc9SGiuseppe Cavallaro 	/* According to the coalesce parameter the IC bit for the latest
26740e80bdc9SGiuseppe Cavallaro 	 * segment is reset and the timer re-started to clean the tx status.
26750e80bdc9SGiuseppe Cavallaro 	 * This approach takes care about the fragments: desc is the first
26760e80bdc9SGiuseppe Cavallaro 	 * element in case of no SG.
26770e80bdc9SGiuseppe Cavallaro 	 */
26780e80bdc9SGiuseppe Cavallaro 	priv->tx_count_frames += nfrags + 1;
26790e80bdc9SGiuseppe Cavallaro 	if (likely(priv->tx_coal_frames > priv->tx_count_frames)) {
26800e80bdc9SGiuseppe Cavallaro 		mod_timer(&priv->txtimer,
26810e80bdc9SGiuseppe Cavallaro 			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
26820e80bdc9SGiuseppe Cavallaro 	} else {
26830e80bdc9SGiuseppe Cavallaro 		priv->tx_count_frames = 0;
26840e80bdc9SGiuseppe Cavallaro 		priv->hw->desc->set_tx_ic(desc);
26850e80bdc9SGiuseppe Cavallaro 		priv->xstats.tx_set_ic_bit++;
26860e80bdc9SGiuseppe Cavallaro 	}
26870e80bdc9SGiuseppe Cavallaro 
26880e80bdc9SGiuseppe Cavallaro 	if (!priv->hwts_tx_en)
26890e80bdc9SGiuseppe Cavallaro 		skb_tx_timestamp(skb);
26900e80bdc9SGiuseppe Cavallaro 
26910e80bdc9SGiuseppe Cavallaro 	/* Ready to fill the first descriptor and set the OWN bit w/o any
26920e80bdc9SGiuseppe Cavallaro 	 * problems because all the descriptors are actually ready to be
26930e80bdc9SGiuseppe Cavallaro 	 * passed to the DMA engine.
26940e80bdc9SGiuseppe Cavallaro 	 */
26950e80bdc9SGiuseppe Cavallaro 	if (likely(!is_jumbo)) {
26960e80bdc9SGiuseppe Cavallaro 		bool last_segment = (nfrags == 0);
26970e80bdc9SGiuseppe Cavallaro 
2698f748be53SAlexandre TORGUE 		des = dma_map_single(priv->device, skb->data,
26990e80bdc9SGiuseppe Cavallaro 				     nopaged_len, DMA_TO_DEVICE);
2700f748be53SAlexandre TORGUE 		if (dma_mapping_error(priv->device, des))
27010e80bdc9SGiuseppe Cavallaro 			goto dma_map_err;
27020e80bdc9SGiuseppe Cavallaro 
27035bacd778SLABBE Corentin 		priv->tx_skbuff_dma[first_entry].buf = des;
2704f8be0d78SMichael Weiser 		if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
2705f8be0d78SMichael Weiser 			first->des0 = cpu_to_le32(des);
2706f8be0d78SMichael Weiser 		else
2707f8be0d78SMichael Weiser 			first->des2 = cpu_to_le32(des);
2708f748be53SAlexandre TORGUE 
27095bacd778SLABBE Corentin 		priv->tx_skbuff_dma[first_entry].len = nopaged_len;
27105bacd778SLABBE Corentin 		priv->tx_skbuff_dma[first_entry].last_segment = last_segment;
27110e80bdc9SGiuseppe Cavallaro 
2712891434b1SRayagond Kokatanur 		if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
2713891434b1SRayagond Kokatanur 			     priv->hwts_tx_en)) {
2714891434b1SRayagond Kokatanur 			/* declare that device is doing timestamping */
2715891434b1SRayagond Kokatanur 			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
2716891434b1SRayagond Kokatanur 			priv->hw->desc->enable_tx_timestamp(first);
2717891434b1SRayagond Kokatanur 		}
2718891434b1SRayagond Kokatanur 
27190e80bdc9SGiuseppe Cavallaro 		/* Prepare the first descriptor setting the OWN bit too */
27200e80bdc9SGiuseppe Cavallaro 		priv->hw->desc->prepare_tx_desc(first, 1, nopaged_len,
27210e80bdc9SGiuseppe Cavallaro 						csum_insertion, priv->mode, 1,
27220e80bdc9SGiuseppe Cavallaro 						last_segment);
27230e80bdc9SGiuseppe Cavallaro 
27240e80bdc9SGiuseppe Cavallaro 		/* The own bit must be the latest setting done when prepare the
27250e80bdc9SGiuseppe Cavallaro 		 * descriptor and then barrier is needed to make sure that
27260e80bdc9SGiuseppe Cavallaro 		 * all is coherent before granting the DMA engine.
27270e80bdc9SGiuseppe Cavallaro 		 */
2728ad688cdbSPavel Machek 		dma_wmb();
27290e80bdc9SGiuseppe Cavallaro 	}
27307ac6653aSJeff Kirsher 
27315bacd778SLABBE Corentin 	netdev_sent_queue(dev, skb->len);
2732f748be53SAlexandre TORGUE 
2733f748be53SAlexandre TORGUE 	if (priv->synopsys_id < DWMAC_CORE_4_00)
27347ac6653aSJeff Kirsher 		priv->hw->dma->enable_dma_transmission(priv->ioaddr);
2735f748be53SAlexandre TORGUE 	else
27365bacd778SLABBE Corentin 		priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, priv->tx_tail_addr,
27375bacd778SLABBE Corentin 					       STMMAC_CHAN0);
27387ac6653aSJeff Kirsher 
2739362b37beSGiuseppe CAVALLARO 	return NETDEV_TX_OK;
2740a9097a96SGiuseppe CAVALLARO 
2741362b37beSGiuseppe CAVALLARO dma_map_err:
274238ddc59dSLABBE Corentin 	netdev_err(priv->dev, "Tx DMA map failed\n");
2743362b37beSGiuseppe CAVALLARO 	dev_kfree_skb(skb);
2744362b37beSGiuseppe CAVALLARO 	priv->dev->stats.tx_dropped++;
27457ac6653aSJeff Kirsher 	return NETDEV_TX_OK;
27467ac6653aSJeff Kirsher }
27477ac6653aSJeff Kirsher 
2748b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
2749b9381985SVince Bridgers {
2750b9381985SVince Bridgers 	struct ethhdr *ehdr;
2751b9381985SVince Bridgers 	u16 vlanid;
2752b9381985SVince Bridgers 
2753b9381985SVince Bridgers 	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
2754b9381985SVince Bridgers 	    NETIF_F_HW_VLAN_CTAG_RX &&
2755b9381985SVince Bridgers 	    !__vlan_get_tag(skb, &vlanid)) {
2756b9381985SVince Bridgers 		/* pop the vlan tag */
2757b9381985SVince Bridgers 		ehdr = (struct ethhdr *)skb->data;
2758b9381985SVince Bridgers 		memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
2759b9381985SVince Bridgers 		skb_pull(skb, VLAN_HLEN);
2760b9381985SVince Bridgers 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
2761b9381985SVince Bridgers 	}
2762b9381985SVince Bridgers }
2763b9381985SVince Bridgers 
2764b9381985SVince Bridgers 
27655bacd778SLABBE Corentin static inline int stmmac_rx_threshold_count(struct stmmac_priv *priv)
2766120e87f9SGiuseppe Cavallaro {
27675bacd778SLABBE Corentin 	if (priv->rx_zeroc_thresh < STMMAC_RX_THRESH)
2768120e87f9SGiuseppe Cavallaro 		return 0;
2769120e87f9SGiuseppe Cavallaro 
2770120e87f9SGiuseppe Cavallaro 	return 1;
2771120e87f9SGiuseppe Cavallaro }
2772120e87f9SGiuseppe Cavallaro 
277332ceabcaSGiuseppe CAVALLARO /**
2774732fdf0eSGiuseppe CAVALLARO  * stmmac_rx_refill - refill used skb preallocated buffers
277532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
277632ceabcaSGiuseppe CAVALLARO  * Description : this is to reallocate the skb for the reception process
277732ceabcaSGiuseppe CAVALLARO  * that is based on zero-copy.
277832ceabcaSGiuseppe CAVALLARO  */
27795bacd778SLABBE Corentin static inline void stmmac_rx_refill(struct stmmac_priv *priv)
27807ac6653aSJeff Kirsher {
27817ac6653aSJeff Kirsher 	int bfsize = priv->dma_buf_sz;
27825bacd778SLABBE Corentin 	unsigned int entry = priv->dirty_rx;
27835bacd778SLABBE Corentin 	int dirty = stmmac_rx_dirty(priv);
27847ac6653aSJeff Kirsher 
2785e3ad57c9SGiuseppe Cavallaro 	while (dirty-- > 0) {
2786c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
2787c24602efSGiuseppe CAVALLARO 
2788c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
27895bacd778SLABBE Corentin 			p = (struct dma_desc *)(priv->dma_erx + entry);
2790c24602efSGiuseppe CAVALLARO 		else
27915bacd778SLABBE Corentin 			p = priv->dma_rx + entry;
2792c24602efSGiuseppe CAVALLARO 
27935bacd778SLABBE Corentin 		if (likely(priv->rx_skbuff[entry] == NULL)) {
27947ac6653aSJeff Kirsher 			struct sk_buff *skb;
27957ac6653aSJeff Kirsher 
2796acb600deSEric Dumazet 			skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
2797120e87f9SGiuseppe Cavallaro 			if (unlikely(!skb)) {
2798120e87f9SGiuseppe Cavallaro 				/* so for a while no zero-copy! */
27995bacd778SLABBE Corentin 				priv->rx_zeroc_thresh = STMMAC_RX_THRESH;
2800120e87f9SGiuseppe Cavallaro 				if (unlikely(net_ratelimit()))
2801120e87f9SGiuseppe Cavallaro 					dev_err(priv->device,
2802120e87f9SGiuseppe Cavallaro 						"fail to alloc skb entry %d\n",
2803120e87f9SGiuseppe Cavallaro 						entry);
28047ac6653aSJeff Kirsher 				break;
2805120e87f9SGiuseppe Cavallaro 			}
28067ac6653aSJeff Kirsher 
28075bacd778SLABBE Corentin 			priv->rx_skbuff[entry] = skb;
28085bacd778SLABBE Corentin 			priv->rx_skbuff_dma[entry] =
28097ac6653aSJeff Kirsher 			    dma_map_single(priv->device, skb->data, bfsize,
28107ac6653aSJeff Kirsher 					   DMA_FROM_DEVICE);
2811362b37beSGiuseppe CAVALLARO 			if (dma_mapping_error(priv->device,
28125bacd778SLABBE Corentin 					      priv->rx_skbuff_dma[entry])) {
281338ddc59dSLABBE Corentin 				netdev_err(priv->dev, "Rx DMA map failed\n");
2814362b37beSGiuseppe CAVALLARO 				dev_kfree_skb(skb);
2815362b37beSGiuseppe CAVALLARO 				break;
2816362b37beSGiuseppe CAVALLARO 			}
2817286a8372SGiuseppe CAVALLARO 
2818f748be53SAlexandre TORGUE 			if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) {
28195bacd778SLABBE Corentin 				p->des0 = cpu_to_le32(priv->rx_skbuff_dma[entry]);
2820f748be53SAlexandre TORGUE 				p->des1 = 0;
2821f748be53SAlexandre TORGUE 			} else {
28225bacd778SLABBE Corentin 				p->des2 = cpu_to_le32(priv->rx_skbuff_dma[entry]);
2823f748be53SAlexandre TORGUE 			}
2824f748be53SAlexandre TORGUE 			if (priv->hw->mode->refill_desc3)
28255bacd778SLABBE Corentin 				priv->hw->mode->refill_desc3(priv, p);
2826286a8372SGiuseppe CAVALLARO 
28275bacd778SLABBE Corentin 			if (priv->rx_zeroc_thresh > 0)
28285bacd778SLABBE Corentin 				priv->rx_zeroc_thresh--;
2829120e87f9SGiuseppe Cavallaro 
2830b3e51069SLABBE Corentin 			netif_dbg(priv, rx_status, priv->dev,
283138ddc59dSLABBE Corentin 				  "refill entry #%d\n", entry);
28327ac6653aSJeff Kirsher 		}
2833ad688cdbSPavel Machek 		dma_wmb();
2834f748be53SAlexandre TORGUE 
2835f748be53SAlexandre TORGUE 		if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
2836f748be53SAlexandre TORGUE 			priv->hw->desc->init_rx_desc(p, priv->use_riwt, 0, 0);
2837f748be53SAlexandre TORGUE 		else
2838c24602efSGiuseppe CAVALLARO 			priv->hw->desc->set_rx_owner(p);
2839f748be53SAlexandre TORGUE 
2840ad688cdbSPavel Machek 		dma_wmb();
2841e3ad57c9SGiuseppe Cavallaro 
2842e3ad57c9SGiuseppe Cavallaro 		entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE);
28437ac6653aSJeff Kirsher 	}
28445bacd778SLABBE Corentin 	priv->dirty_rx = entry;
28457ac6653aSJeff Kirsher }
28467ac6653aSJeff Kirsher 
284732ceabcaSGiuseppe CAVALLARO /**
2848732fdf0eSGiuseppe CAVALLARO  * stmmac_rx - manage the receive process
284932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
285032ceabcaSGiuseppe CAVALLARO  * @limit: napi bugget.
285132ceabcaSGiuseppe CAVALLARO  * Description :  this the function called by the napi poll method.
285232ceabcaSGiuseppe CAVALLARO  * It gets all the frames inside the ring.
285332ceabcaSGiuseppe CAVALLARO  */
28545bacd778SLABBE Corentin static int stmmac_rx(struct stmmac_priv *priv, int limit)
28557ac6653aSJeff Kirsher {
28565bacd778SLABBE Corentin 	unsigned int entry = priv->cur_rx;
28577ac6653aSJeff Kirsher 	unsigned int next_entry;
28587ac6653aSJeff Kirsher 	unsigned int count = 0;
28595bacd778SLABBE Corentin 	int coe = priv->hw->rx_csum;
28607ac6653aSJeff Kirsher 
286183d7af64SGiuseppe CAVALLARO 	if (netif_msg_rx_status(priv)) {
2862d0225e7dSAlexandre TORGUE 		void *rx_head;
2863d0225e7dSAlexandre TORGUE 
286438ddc59dSLABBE Corentin 		netdev_dbg(priv->dev, "%s: descriptor ring:\n", __func__);
2865c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
28665bacd778SLABBE Corentin 			rx_head = (void *)priv->dma_erx;
2867c24602efSGiuseppe CAVALLARO 		else
28685bacd778SLABBE Corentin 			rx_head = (void *)priv->dma_rx;
2869d0225e7dSAlexandre TORGUE 
2870d0225e7dSAlexandre TORGUE 		priv->hw->desc->display_ring(rx_head, DMA_RX_SIZE, true);
28717ac6653aSJeff Kirsher 	}
2872c24602efSGiuseppe CAVALLARO 	while (count < limit) {
28737ac6653aSJeff Kirsher 		int status;
28749401bb5cSGiuseppe CAVALLARO 		struct dma_desc *p;
2875ba1ffd74SGiuseppe CAVALLARO 		struct dma_desc *np;
28767ac6653aSJeff Kirsher 
2877c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
28785bacd778SLABBE Corentin 			p = (struct dma_desc *)(priv->dma_erx + entry);
2879c24602efSGiuseppe CAVALLARO 		else
28805bacd778SLABBE Corentin 			p = priv->dma_rx + entry;
2881c24602efSGiuseppe CAVALLARO 
2882c1fa3212SFabrice Gasnier 		/* read the status of the incoming frame */
2883c1fa3212SFabrice Gasnier 		status = priv->hw->desc->rx_status(&priv->dev->stats,
2884c1fa3212SFabrice Gasnier 						   &priv->xstats, p);
2885c1fa3212SFabrice Gasnier 		/* check if managed by the DMA otherwise go ahead */
2886c1fa3212SFabrice Gasnier 		if (unlikely(status & dma_own))
28877ac6653aSJeff Kirsher 			break;
28887ac6653aSJeff Kirsher 
28897ac6653aSJeff Kirsher 		count++;
28907ac6653aSJeff Kirsher 
28915bacd778SLABBE Corentin 		priv->cur_rx = STMMAC_GET_ENTRY(priv->cur_rx, DMA_RX_SIZE);
28925bacd778SLABBE Corentin 		next_entry = priv->cur_rx;
2893e3ad57c9SGiuseppe Cavallaro 
2894c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
28955bacd778SLABBE Corentin 			np = (struct dma_desc *)(priv->dma_erx + next_entry);
2896c24602efSGiuseppe CAVALLARO 		else
28975bacd778SLABBE Corentin 			np = priv->dma_rx + next_entry;
2898ba1ffd74SGiuseppe CAVALLARO 
2899ba1ffd74SGiuseppe CAVALLARO 		prefetch(np);
29007ac6653aSJeff Kirsher 
2901c24602efSGiuseppe CAVALLARO 		if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status))
2902c24602efSGiuseppe CAVALLARO 			priv->hw->desc->rx_extended_status(&priv->dev->stats,
2903c24602efSGiuseppe CAVALLARO 							   &priv->xstats,
29045bacd778SLABBE Corentin 							   priv->dma_erx +
2905c24602efSGiuseppe CAVALLARO 							   entry);
2906891434b1SRayagond Kokatanur 		if (unlikely(status == discard_frame)) {
29077ac6653aSJeff Kirsher 			priv->dev->stats.rx_errors++;
2908891434b1SRayagond Kokatanur 			if (priv->hwts_rx_en && !priv->extend_desc) {
29098d45e42bSLABBE Corentin 				/* DESC2 & DESC3 will be overwritten by device
2910891434b1SRayagond Kokatanur 				 * with timestamp value, hence reinitialize
2911891434b1SRayagond Kokatanur 				 * them in stmmac_rx_refill() function so that
2912891434b1SRayagond Kokatanur 				 * device can reuse it.
2913891434b1SRayagond Kokatanur 				 */
29145bacd778SLABBE Corentin 				priv->rx_skbuff[entry] = NULL;
2915891434b1SRayagond Kokatanur 				dma_unmap_single(priv->device,
29165bacd778SLABBE Corentin 						 priv->rx_skbuff_dma[entry],
2917ceb69499SGiuseppe CAVALLARO 						 priv->dma_buf_sz,
2918ceb69499SGiuseppe CAVALLARO 						 DMA_FROM_DEVICE);
2919891434b1SRayagond Kokatanur 			}
2920891434b1SRayagond Kokatanur 		} else {
29217ac6653aSJeff Kirsher 			struct sk_buff *skb;
29227ac6653aSJeff Kirsher 			int frame_len;
2923f748be53SAlexandre TORGUE 			unsigned int des;
2924f748be53SAlexandre TORGUE 
2925f748be53SAlexandre TORGUE 			if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
2926f8be0d78SMichael Weiser 				des = le32_to_cpu(p->des0);
2927f748be53SAlexandre TORGUE 			else
2928f8be0d78SMichael Weiser 				des = le32_to_cpu(p->des2);
29297ac6653aSJeff Kirsher 
2930ceb69499SGiuseppe CAVALLARO 			frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
2931ceb69499SGiuseppe CAVALLARO 
29328d45e42bSLABBE Corentin 			/*  If frame length is greater than skb buffer size
2933f748be53SAlexandre TORGUE 			 *  (preallocated during init) then the packet is
2934f748be53SAlexandre TORGUE 			 *  ignored
2935f748be53SAlexandre TORGUE 			 */
2936e527c4a7SGiuseppe CAVALLARO 			if (frame_len > priv->dma_buf_sz) {
293738ddc59dSLABBE Corentin 				netdev_err(priv->dev,
293838ddc59dSLABBE Corentin 					   "len %d larger than size (%d)\n",
293938ddc59dSLABBE Corentin 					   frame_len, priv->dma_buf_sz);
2940e527c4a7SGiuseppe CAVALLARO 				priv->dev->stats.rx_length_errors++;
2941e527c4a7SGiuseppe CAVALLARO 				break;
2942e527c4a7SGiuseppe CAVALLARO 			}
2943e527c4a7SGiuseppe CAVALLARO 
29447ac6653aSJeff Kirsher 			/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
2945ceb69499SGiuseppe CAVALLARO 			 * Type frames (LLC/LLC-SNAP)
2946ceb69499SGiuseppe CAVALLARO 			 */
29477ac6653aSJeff Kirsher 			if (unlikely(status != llc_snap))
29487ac6653aSJeff Kirsher 				frame_len -= ETH_FCS_LEN;
29497ac6653aSJeff Kirsher 
295083d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv)) {
295138ddc59dSLABBE Corentin 				netdev_dbg(priv->dev, "\tdesc: %p [entry %d] buff=0x%x\n",
2952f748be53SAlexandre TORGUE 					   p, entry, des);
295383d7af64SGiuseppe CAVALLARO 				if (frame_len > ETH_FRAME_LEN)
295438ddc59dSLABBE Corentin 					netdev_dbg(priv->dev, "frame size %d, COE: %d\n",
295583d7af64SGiuseppe CAVALLARO 						   frame_len, status);
295683d7af64SGiuseppe CAVALLARO 			}
295722ad3838SGiuseppe Cavallaro 
2958f748be53SAlexandre TORGUE 			/* The zero-copy is always used for all the sizes
2959f748be53SAlexandre TORGUE 			 * in case of GMAC4 because it needs
2960f748be53SAlexandre TORGUE 			 * to refill the used descriptors, always.
2961f748be53SAlexandre TORGUE 			 */
2962f748be53SAlexandre TORGUE 			if (unlikely(!priv->plat->has_gmac4 &&
2963f748be53SAlexandre TORGUE 				     ((frame_len < priv->rx_copybreak) ||
29645bacd778SLABBE Corentin 				     stmmac_rx_threshold_count(priv)))) {
296522ad3838SGiuseppe Cavallaro 				skb = netdev_alloc_skb_ip_align(priv->dev,
296622ad3838SGiuseppe Cavallaro 								frame_len);
296722ad3838SGiuseppe Cavallaro 				if (unlikely(!skb)) {
296822ad3838SGiuseppe Cavallaro 					if (net_ratelimit())
296922ad3838SGiuseppe Cavallaro 						dev_warn(priv->device,
297022ad3838SGiuseppe Cavallaro 							 "packet dropped\n");
297122ad3838SGiuseppe Cavallaro 					priv->dev->stats.rx_dropped++;
297222ad3838SGiuseppe Cavallaro 					break;
297322ad3838SGiuseppe Cavallaro 				}
297422ad3838SGiuseppe Cavallaro 
297522ad3838SGiuseppe Cavallaro 				dma_sync_single_for_cpu(priv->device,
29765bacd778SLABBE Corentin 							priv->rx_skbuff_dma
297722ad3838SGiuseppe Cavallaro 							[entry], frame_len,
297822ad3838SGiuseppe Cavallaro 							DMA_FROM_DEVICE);
297922ad3838SGiuseppe Cavallaro 				skb_copy_to_linear_data(skb,
29805bacd778SLABBE Corentin 							priv->
298122ad3838SGiuseppe Cavallaro 							rx_skbuff[entry]->data,
298222ad3838SGiuseppe Cavallaro 							frame_len);
298322ad3838SGiuseppe Cavallaro 
298422ad3838SGiuseppe Cavallaro 				skb_put(skb, frame_len);
298522ad3838SGiuseppe Cavallaro 				dma_sync_single_for_device(priv->device,
29865bacd778SLABBE Corentin 							   priv->rx_skbuff_dma
298722ad3838SGiuseppe Cavallaro 							   [entry], frame_len,
298822ad3838SGiuseppe Cavallaro 							   DMA_FROM_DEVICE);
298922ad3838SGiuseppe Cavallaro 			} else {
29905bacd778SLABBE Corentin 				skb = priv->rx_skbuff[entry];
29917ac6653aSJeff Kirsher 				if (unlikely(!skb)) {
299238ddc59dSLABBE Corentin 					netdev_err(priv->dev,
299338ddc59dSLABBE Corentin 						   "%s: Inconsistent Rx chain\n",
29947ac6653aSJeff Kirsher 						   priv->dev->name);
29957ac6653aSJeff Kirsher 					priv->dev->stats.rx_dropped++;
29967ac6653aSJeff Kirsher 					break;
29977ac6653aSJeff Kirsher 				}
29987ac6653aSJeff Kirsher 				prefetch(skb->data - NET_IP_ALIGN);
29995bacd778SLABBE Corentin 				priv->rx_skbuff[entry] = NULL;
30005bacd778SLABBE Corentin 				priv->rx_zeroc_thresh++;
30017ac6653aSJeff Kirsher 
30027ac6653aSJeff Kirsher 				skb_put(skb, frame_len);
30037ac6653aSJeff Kirsher 				dma_unmap_single(priv->device,
30045bacd778SLABBE Corentin 						 priv->rx_skbuff_dma[entry],
300522ad3838SGiuseppe Cavallaro 						 priv->dma_buf_sz,
300622ad3838SGiuseppe Cavallaro 						 DMA_FROM_DEVICE);
300722ad3838SGiuseppe Cavallaro 			}
300822ad3838SGiuseppe Cavallaro 
30097ac6653aSJeff Kirsher 			if (netif_msg_pktdata(priv)) {
301038ddc59dSLABBE Corentin 				netdev_dbg(priv->dev, "frame received (%dbytes)",
301138ddc59dSLABBE Corentin 					   frame_len);
30127ac6653aSJeff Kirsher 				print_pkt(skb->data, frame_len);
30137ac6653aSJeff Kirsher 			}
301483d7af64SGiuseppe CAVALLARO 
3015ba1ffd74SGiuseppe CAVALLARO 			stmmac_get_rx_hwtstamp(priv, p, np, skb);
3016ba1ffd74SGiuseppe CAVALLARO 
3017b9381985SVince Bridgers 			stmmac_rx_vlan(priv->dev, skb);
3018b9381985SVince Bridgers 
30197ac6653aSJeff Kirsher 			skb->protocol = eth_type_trans(skb, priv->dev);
30207ac6653aSJeff Kirsher 
3021ceb69499SGiuseppe CAVALLARO 			if (unlikely(!coe))
30227ac6653aSJeff Kirsher 				skb_checksum_none_assert(skb);
302362a2ab93SGiuseppe CAVALLARO 			else
30247ac6653aSJeff Kirsher 				skb->ip_summed = CHECKSUM_UNNECESSARY;
302562a2ab93SGiuseppe CAVALLARO 
30265bacd778SLABBE Corentin 			napi_gro_receive(&priv->napi, skb);
30277ac6653aSJeff Kirsher 
30287ac6653aSJeff Kirsher 			priv->dev->stats.rx_packets++;
30297ac6653aSJeff Kirsher 			priv->dev->stats.rx_bytes += frame_len;
30307ac6653aSJeff Kirsher 		}
30317ac6653aSJeff Kirsher 		entry = next_entry;
30327ac6653aSJeff Kirsher 	}
30337ac6653aSJeff Kirsher 
30345bacd778SLABBE Corentin 	stmmac_rx_refill(priv);
30357ac6653aSJeff Kirsher 
30367ac6653aSJeff Kirsher 	priv->xstats.rx_pkt_n += count;
30377ac6653aSJeff Kirsher 
30387ac6653aSJeff Kirsher 	return count;
30397ac6653aSJeff Kirsher }
30407ac6653aSJeff Kirsher 
30417ac6653aSJeff Kirsher /**
30427ac6653aSJeff Kirsher  *  stmmac_poll - stmmac poll method (NAPI)
30437ac6653aSJeff Kirsher  *  @napi : pointer to the napi structure.
30447ac6653aSJeff Kirsher  *  @budget : maximum number of packets that the current CPU can receive from
30457ac6653aSJeff Kirsher  *	      all interfaces.
30467ac6653aSJeff Kirsher  *  Description :
30479125cdd1SGiuseppe CAVALLARO  *  To look at the incoming frames and clear the tx resources.
30487ac6653aSJeff Kirsher  */
30497ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget)
30507ac6653aSJeff Kirsher {
30515bacd778SLABBE Corentin 	struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
30525bacd778SLABBE Corentin 	int work_done = 0;
30535bacd778SLABBE Corentin 	u32 chan = STMMAC_CHAN0;
30547ac6653aSJeff Kirsher 
30559125cdd1SGiuseppe CAVALLARO 	priv->xstats.napi_poll++;
30565bacd778SLABBE Corentin 	stmmac_tx_clean(priv);
30577ac6653aSJeff Kirsher 
30585bacd778SLABBE Corentin 	work_done = stmmac_rx(priv, budget);
30597ac6653aSJeff Kirsher 	if (work_done < budget) {
30606ad20165SEric Dumazet 		napi_complete_done(napi, work_done);
30614f513ecdSJoao Pinto 		stmmac_enable_dma_irq(priv, chan);
30627ac6653aSJeff Kirsher 	}
30637ac6653aSJeff Kirsher 	return work_done;
30647ac6653aSJeff Kirsher }
30657ac6653aSJeff Kirsher 
30667ac6653aSJeff Kirsher /**
30677ac6653aSJeff Kirsher  *  stmmac_tx_timeout
30687ac6653aSJeff Kirsher  *  @dev : Pointer to net device structure
30697ac6653aSJeff Kirsher  *  Description: this function is called when a packet transmission fails to
30707284a3f1SGiuseppe CAVALLARO  *   complete within a reasonable time. The driver will mark the error in the
30717ac6653aSJeff Kirsher  *   netdev structure and arrange for the device to be reset to a sane state
30727ac6653aSJeff Kirsher  *   in order to transmit a new packet.
30737ac6653aSJeff Kirsher  */
30747ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev)
30757ac6653aSJeff Kirsher {
30767ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
30775bacd778SLABBE Corentin 	u32 chan = STMMAC_CHAN0;
30787ac6653aSJeff Kirsher 
30797ac6653aSJeff Kirsher 	/* Clear Tx resources and restart transmitting again */
30804e593262SJoao Pinto 	stmmac_tx_err(priv, chan);
30817ac6653aSJeff Kirsher }
30827ac6653aSJeff Kirsher 
30837ac6653aSJeff Kirsher /**
308401789349SJiri Pirko  *  stmmac_set_rx_mode - entry point for multicast addressing
30857ac6653aSJeff Kirsher  *  @dev : pointer to the device structure
30867ac6653aSJeff Kirsher  *  Description:
30877ac6653aSJeff Kirsher  *  This function is a driver entry point which gets called by the kernel
30887ac6653aSJeff Kirsher  *  whenever multicast addresses must be enabled/disabled.
30897ac6653aSJeff Kirsher  *  Return value:
30907ac6653aSJeff Kirsher  *  void.
30917ac6653aSJeff Kirsher  */
309201789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev)
30937ac6653aSJeff Kirsher {
30947ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
30957ac6653aSJeff Kirsher 
30963b57de95SVince Bridgers 	priv->hw->mac->set_filter(priv->hw, dev);
30977ac6653aSJeff Kirsher }
30987ac6653aSJeff Kirsher 
30997ac6653aSJeff Kirsher /**
31007ac6653aSJeff Kirsher  *  stmmac_change_mtu - entry point to change MTU size for the device.
31017ac6653aSJeff Kirsher  *  @dev : device pointer.
31027ac6653aSJeff Kirsher  *  @new_mtu : the new MTU size for the device.
31037ac6653aSJeff Kirsher  *  Description: the Maximum Transfer Unit (MTU) is used by the network layer
31047ac6653aSJeff Kirsher  *  to drive packet transmission. Ethernet has an MTU of 1500 octets
31057ac6653aSJeff Kirsher  *  (ETH_DATA_LEN). This value can be changed with ifconfig.
31067ac6653aSJeff Kirsher  *  Return value:
31077ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
31087ac6653aSJeff Kirsher  *  file on failure.
31097ac6653aSJeff Kirsher  */
31107ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
31117ac6653aSJeff Kirsher {
311238ddc59dSLABBE Corentin 	struct stmmac_priv *priv = netdev_priv(dev);
311338ddc59dSLABBE Corentin 
31147ac6653aSJeff Kirsher 	if (netif_running(dev)) {
311538ddc59dSLABBE Corentin 		netdev_err(priv->dev, "must be stopped to change its MTU\n");
31167ac6653aSJeff Kirsher 		return -EBUSY;
31177ac6653aSJeff Kirsher 	}
31187ac6653aSJeff Kirsher 
31197ac6653aSJeff Kirsher 	dev->mtu = new_mtu;
3120f748be53SAlexandre TORGUE 
31217ac6653aSJeff Kirsher 	netdev_update_features(dev);
31227ac6653aSJeff Kirsher 
31237ac6653aSJeff Kirsher 	return 0;
31247ac6653aSJeff Kirsher }
31257ac6653aSJeff Kirsher 
3126c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev,
3127c8f44affSMichał Mirosław 					     netdev_features_t features)
31287ac6653aSJeff Kirsher {
31297ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
31307ac6653aSJeff Kirsher 
313138912bdbSDeepak SIKRI 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
31327ac6653aSJeff Kirsher 		features &= ~NETIF_F_RXCSUM;
3133d2afb5bdSGiuseppe CAVALLARO 
31347ac6653aSJeff Kirsher 	if (!priv->plat->tx_coe)
3135a188222bSTom Herbert 		features &= ~NETIF_F_CSUM_MASK;
31367ac6653aSJeff Kirsher 
31377ac6653aSJeff Kirsher 	/* Some GMAC devices have a bugged Jumbo frame support that
31387ac6653aSJeff Kirsher 	 * needs to have the Tx COE disabled for oversized frames
31397ac6653aSJeff Kirsher 	 * (due to limited buffer sizes). In this case we disable
3140ceb69499SGiuseppe CAVALLARO 	 * the TX csum insertion in the TDES and not use SF.
3141ceb69499SGiuseppe CAVALLARO 	 */
31427ac6653aSJeff Kirsher 	if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
3143a188222bSTom Herbert 		features &= ~NETIF_F_CSUM_MASK;
31447ac6653aSJeff Kirsher 
3145f748be53SAlexandre TORGUE 	/* Disable tso if asked by ethtool */
3146f748be53SAlexandre TORGUE 	if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
3147f748be53SAlexandre TORGUE 		if (features & NETIF_F_TSO)
3148f748be53SAlexandre TORGUE 			priv->tso = true;
3149f748be53SAlexandre TORGUE 		else
3150f748be53SAlexandre TORGUE 			priv->tso = false;
3151f748be53SAlexandre TORGUE 	}
3152f748be53SAlexandre TORGUE 
31537ac6653aSJeff Kirsher 	return features;
31547ac6653aSJeff Kirsher }
31557ac6653aSJeff Kirsher 
3156d2afb5bdSGiuseppe CAVALLARO static int stmmac_set_features(struct net_device *netdev,
3157d2afb5bdSGiuseppe CAVALLARO 			       netdev_features_t features)
3158d2afb5bdSGiuseppe CAVALLARO {
3159d2afb5bdSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(netdev);
3160d2afb5bdSGiuseppe CAVALLARO 
3161d2afb5bdSGiuseppe CAVALLARO 	/* Keep the COE Type in case of csum is supporting */
3162d2afb5bdSGiuseppe CAVALLARO 	if (features & NETIF_F_RXCSUM)
3163d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
3164d2afb5bdSGiuseppe CAVALLARO 	else
3165d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
3166d2afb5bdSGiuseppe CAVALLARO 	/* No check needed because rx_coe has been set before and it will be
3167d2afb5bdSGiuseppe CAVALLARO 	 * fixed in case of issue.
3168d2afb5bdSGiuseppe CAVALLARO 	 */
3169d2afb5bdSGiuseppe CAVALLARO 	priv->hw->mac->rx_ipc(priv->hw);
3170d2afb5bdSGiuseppe CAVALLARO 
3171d2afb5bdSGiuseppe CAVALLARO 	return 0;
3172d2afb5bdSGiuseppe CAVALLARO }
3173d2afb5bdSGiuseppe CAVALLARO 
317432ceabcaSGiuseppe CAVALLARO /**
317532ceabcaSGiuseppe CAVALLARO  *  stmmac_interrupt - main ISR
317632ceabcaSGiuseppe CAVALLARO  *  @irq: interrupt number.
317732ceabcaSGiuseppe CAVALLARO  *  @dev_id: to pass the net device pointer.
317832ceabcaSGiuseppe CAVALLARO  *  Description: this is the main driver interrupt service routine.
3179732fdf0eSGiuseppe CAVALLARO  *  It can call:
3180732fdf0eSGiuseppe CAVALLARO  *  o DMA service routine (to manage incoming frame reception and transmission
3181732fdf0eSGiuseppe CAVALLARO  *    status)
3182732fdf0eSGiuseppe CAVALLARO  *  o Core interrupts to manage: remote wake-up, management counter, LPI
318332ceabcaSGiuseppe CAVALLARO  *    interrupts.
318432ceabcaSGiuseppe CAVALLARO  */
31857ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
31867ac6653aSJeff Kirsher {
31877ac6653aSJeff Kirsher 	struct net_device *dev = (struct net_device *)dev_id;
31887ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
31897bac4e1eSJoao Pinto 	u32 rx_cnt = priv->plat->rx_queues_to_use;
31907bac4e1eSJoao Pinto 	u32 tx_cnt = priv->plat->tx_queues_to_use;
31917bac4e1eSJoao Pinto 	u32 queues_count;
31927bac4e1eSJoao Pinto 	u32 queue;
31937bac4e1eSJoao Pinto 
31947bac4e1eSJoao Pinto 	queues_count = (rx_cnt > tx_cnt) ? rx_cnt : tx_cnt;
31957ac6653aSJeff Kirsher 
319689f7f2cfSSrinivas Kandagatla 	if (priv->irq_wake)
319789f7f2cfSSrinivas Kandagatla 		pm_wakeup_event(priv->device, 0);
319889f7f2cfSSrinivas Kandagatla 
31997ac6653aSJeff Kirsher 	if (unlikely(!dev)) {
320038ddc59dSLABBE Corentin 		netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
32017ac6653aSJeff Kirsher 		return IRQ_NONE;
32027ac6653aSJeff Kirsher 	}
32037ac6653aSJeff Kirsher 
32047ac6653aSJeff Kirsher 	/* To handle GMAC own interrupts */
3205f748be53SAlexandre TORGUE 	if ((priv->plat->has_gmac) || (priv->plat->has_gmac4)) {
32067ed24bbeSVince Bridgers 		int status = priv->hw->mac->host_irq_status(priv->hw,
32070982a0f6SGiuseppe CAVALLARO 							    &priv->xstats);
32088f71a88dSJoao Pinto 
3209d765955dSGiuseppe CAVALLARO 		if (unlikely(status)) {
3210d765955dSGiuseppe CAVALLARO 			/* For LPI we need to save the tx status */
32110982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
3212d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = true;
32130982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
3214d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = false;
32157bac4e1eSJoao Pinto 		}
32167bac4e1eSJoao Pinto 
32177bac4e1eSJoao Pinto 		if (priv->synopsys_id >= DWMAC_CORE_4_00) {
32187bac4e1eSJoao Pinto 			for (queue = 0; queue < queues_count; queue++) {
32197bac4e1eSJoao Pinto 				status |=
32207bac4e1eSJoao Pinto 				priv->hw->mac->host_mtl_irq_status(priv->hw,
32217bac4e1eSJoao Pinto 								   queue);
32227bac4e1eSJoao Pinto 
32237bac4e1eSJoao Pinto 				if (status & CORE_IRQ_MTL_RX_OVERFLOW &&
32247bac4e1eSJoao Pinto 				    priv->hw->dma->set_rx_tail_ptr)
3225f748be53SAlexandre TORGUE 					priv->hw->dma->set_rx_tail_ptr(priv->ioaddr,
32265bacd778SLABBE Corentin 								priv->rx_tail_addr,
32277bac4e1eSJoao Pinto 								queue);
32287bac4e1eSJoao Pinto 			}
3229d765955dSGiuseppe CAVALLARO 		}
323070523e63SGiuseppe CAVALLARO 
323170523e63SGiuseppe CAVALLARO 		/* PCS link status */
32323fe5cadbSGiuseppe CAVALLARO 		if (priv->hw->pcs) {
323370523e63SGiuseppe CAVALLARO 			if (priv->xstats.pcs_link)
323470523e63SGiuseppe CAVALLARO 				netif_carrier_on(dev);
323570523e63SGiuseppe CAVALLARO 			else
323670523e63SGiuseppe CAVALLARO 				netif_carrier_off(dev);
323770523e63SGiuseppe CAVALLARO 		}
3238d765955dSGiuseppe CAVALLARO 	}
3239d765955dSGiuseppe CAVALLARO 
3240d765955dSGiuseppe CAVALLARO 	/* To handle DMA interrupts */
32417ac6653aSJeff Kirsher 	stmmac_dma_interrupt(priv);
32427ac6653aSJeff Kirsher 
32437ac6653aSJeff Kirsher 	return IRQ_HANDLED;
32447ac6653aSJeff Kirsher }
32457ac6653aSJeff Kirsher 
32467ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
32477ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools
3248ceb69499SGiuseppe CAVALLARO  * to allow network I/O with interrupts disabled.
3249ceb69499SGiuseppe CAVALLARO  */
32507ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev)
32517ac6653aSJeff Kirsher {
32527ac6653aSJeff Kirsher 	disable_irq(dev->irq);
32537ac6653aSJeff Kirsher 	stmmac_interrupt(dev->irq, dev);
32547ac6653aSJeff Kirsher 	enable_irq(dev->irq);
32557ac6653aSJeff Kirsher }
32567ac6653aSJeff Kirsher #endif
32577ac6653aSJeff Kirsher 
32587ac6653aSJeff Kirsher /**
32597ac6653aSJeff Kirsher  *  stmmac_ioctl - Entry point for the Ioctl
32607ac6653aSJeff Kirsher  *  @dev: Device pointer.
32617ac6653aSJeff Kirsher  *  @rq: An IOCTL specefic structure, that can contain a pointer to
32627ac6653aSJeff Kirsher  *  a proprietary structure used to pass information to the driver.
32637ac6653aSJeff Kirsher  *  @cmd: IOCTL command
32647ac6653aSJeff Kirsher  *  Description:
326532ceabcaSGiuseppe CAVALLARO  *  Currently it supports the phy_mii_ioctl(...) and HW time stamping.
32667ac6653aSJeff Kirsher  */
32677ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
32687ac6653aSJeff Kirsher {
3269891434b1SRayagond Kokatanur 	int ret = -EOPNOTSUPP;
32707ac6653aSJeff Kirsher 
32717ac6653aSJeff Kirsher 	if (!netif_running(dev))
32727ac6653aSJeff Kirsher 		return -EINVAL;
32737ac6653aSJeff Kirsher 
3274891434b1SRayagond Kokatanur 	switch (cmd) {
3275891434b1SRayagond Kokatanur 	case SIOCGMIIPHY:
3276891434b1SRayagond Kokatanur 	case SIOCGMIIREG:
3277891434b1SRayagond Kokatanur 	case SIOCSMIIREG:
3278d6d50c7eSPhilippe Reynes 		if (!dev->phydev)
32797ac6653aSJeff Kirsher 			return -EINVAL;
3280d6d50c7eSPhilippe Reynes 		ret = phy_mii_ioctl(dev->phydev, rq, cmd);
3281891434b1SRayagond Kokatanur 		break;
3282891434b1SRayagond Kokatanur 	case SIOCSHWTSTAMP:
3283891434b1SRayagond Kokatanur 		ret = stmmac_hwtstamp_ioctl(dev, rq);
3284891434b1SRayagond Kokatanur 		break;
3285891434b1SRayagond Kokatanur 	default:
3286891434b1SRayagond Kokatanur 		break;
3287891434b1SRayagond Kokatanur 	}
32887ac6653aSJeff Kirsher 
32897ac6653aSJeff Kirsher 	return ret;
32907ac6653aSJeff Kirsher }
32917ac6653aSJeff Kirsher 
329250fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
32937ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir;
32947ac29055SGiuseppe CAVALLARO 
3295c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc,
3296c24602efSGiuseppe CAVALLARO 			       struct seq_file *seq)
32977ac29055SGiuseppe CAVALLARO {
32987ac29055SGiuseppe CAVALLARO 	int i;
3299c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
3300c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
33017ac29055SGiuseppe CAVALLARO 
3302c24602efSGiuseppe CAVALLARO 	for (i = 0; i < size; i++) {
3303c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
3304c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
3305c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
3306f8be0d78SMichael Weiser 				   le32_to_cpu(ep->basic.des0),
3307f8be0d78SMichael Weiser 				   le32_to_cpu(ep->basic.des1),
3308f8be0d78SMichael Weiser 				   le32_to_cpu(ep->basic.des2),
3309f8be0d78SMichael Weiser 				   le32_to_cpu(ep->basic.des3));
3310c24602efSGiuseppe CAVALLARO 			ep++;
3311c24602efSGiuseppe CAVALLARO 		} else {
3312c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
3313c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
3314f8be0d78SMichael Weiser 				   le32_to_cpu(p->des0), le32_to_cpu(p->des1),
3315f8be0d78SMichael Weiser 				   le32_to_cpu(p->des2), le32_to_cpu(p->des3));
3316c24602efSGiuseppe CAVALLARO 			p++;
3317c24602efSGiuseppe CAVALLARO 		}
33187ac29055SGiuseppe CAVALLARO 		seq_printf(seq, "\n");
33197ac29055SGiuseppe CAVALLARO 	}
3320c24602efSGiuseppe CAVALLARO }
33217ac29055SGiuseppe CAVALLARO 
3322c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
3323c24602efSGiuseppe CAVALLARO {
3324c24602efSGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
3325c24602efSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
33267ac29055SGiuseppe CAVALLARO 
3327c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
33285bacd778SLABBE Corentin 		seq_printf(seq, "Extended RX descriptor ring:\n");
33295bacd778SLABBE Corentin 		sysfs_display_ring((void *)priv->dma_erx, DMA_RX_SIZE, 1, seq);
33305bacd778SLABBE Corentin 		seq_printf(seq, "Extended TX descriptor ring:\n");
33315bacd778SLABBE Corentin 		sysfs_display_ring((void *)priv->dma_etx, DMA_TX_SIZE, 1, seq);
3332c24602efSGiuseppe CAVALLARO 	} else {
33335bacd778SLABBE Corentin 		seq_printf(seq, "RX descriptor ring:\n");
33345bacd778SLABBE Corentin 		sysfs_display_ring((void *)priv->dma_rx, DMA_RX_SIZE, 0, seq);
33355bacd778SLABBE Corentin 		seq_printf(seq, "TX descriptor ring:\n");
33365bacd778SLABBE Corentin 		sysfs_display_ring((void *)priv->dma_tx, DMA_TX_SIZE, 0, seq);
33377ac29055SGiuseppe CAVALLARO 	}
33387ac29055SGiuseppe CAVALLARO 
33397ac29055SGiuseppe CAVALLARO 	return 0;
33407ac29055SGiuseppe CAVALLARO }
33417ac29055SGiuseppe CAVALLARO 
33427ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
33437ac29055SGiuseppe CAVALLARO {
33447ac29055SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
33457ac29055SGiuseppe CAVALLARO }
33467ac29055SGiuseppe CAVALLARO 
334722d3efe5SPavel Machek /* Debugfs files, should appear in /sys/kernel/debug/stmmaceth/eth0 */
334822d3efe5SPavel Machek 
33497ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = {
33507ac29055SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
33517ac29055SGiuseppe CAVALLARO 	.open = stmmac_sysfs_ring_open,
33527ac29055SGiuseppe CAVALLARO 	.read = seq_read,
33537ac29055SGiuseppe CAVALLARO 	.llseek = seq_lseek,
335474863948SDjalal Harouni 	.release = single_release,
33557ac29055SGiuseppe CAVALLARO };
33567ac29055SGiuseppe CAVALLARO 
3357e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
3358e7434821SGiuseppe CAVALLARO {
3359e7434821SGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
3360e7434821SGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
3361e7434821SGiuseppe CAVALLARO 
336219e30c14SGiuseppe CAVALLARO 	if (!priv->hw_cap_support) {
3363e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "DMA HW features not supported\n");
3364e7434821SGiuseppe CAVALLARO 		return 0;
3365e7434821SGiuseppe CAVALLARO 	}
3366e7434821SGiuseppe CAVALLARO 
3367e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
3368e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tDMA HW features\n");
3369e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
3370e7434821SGiuseppe CAVALLARO 
337122d3efe5SPavel Machek 	seq_printf(seq, "\t10/100 Mbps: %s\n",
3372e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_10_100) ? "Y" : "N");
337322d3efe5SPavel Machek 	seq_printf(seq, "\t1000 Mbps: %s\n",
3374e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_1000) ? "Y" : "N");
337522d3efe5SPavel Machek 	seq_printf(seq, "\tHalf duplex: %s\n",
3376e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.half_duplex) ? "Y" : "N");
3377e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHash Filter: %s\n",
3378e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.hash_filter) ? "Y" : "N");
3379e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tMultiple MAC address registers: %s\n",
3380e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.multi_addr) ? "Y" : "N");
33818d45e42bSLABBE Corentin 	seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfaces): %s\n",
3382e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pcs) ? "Y" : "N");
3383e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
3384e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.sma_mdio) ? "Y" : "N");
3385e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Remote wake up: %s\n",
3386e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
3387e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Magic Frame: %s\n",
3388e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
3389e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRMON module: %s\n",
3390e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rmon) ? "Y" : "N");
3391e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
3392e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.time_stamp) ? "Y" : "N");
3393e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp: %s\n",
3394e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.atime_stamp) ? "Y" : "N");
339522d3efe5SPavel Machek 	seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE): %s\n",
3396e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.eee) ? "Y" : "N");
3397e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
3398e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tChecksum Offload in TX: %s\n",
3399e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.tx_coe) ? "Y" : "N");
3400f748be53SAlexandre TORGUE 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
3401f748be53SAlexandre TORGUE 		seq_printf(seq, "\tIP Checksum Offload in RX: %s\n",
3402f748be53SAlexandre TORGUE 			   (priv->dma_cap.rx_coe) ? "Y" : "N");
3403f748be53SAlexandre TORGUE 	} else {
3404e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
3405e7434821SGiuseppe CAVALLARO 			   (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
3406e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
3407e7434821SGiuseppe CAVALLARO 			   (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
3408f748be53SAlexandre TORGUE 	}
3409e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
3410e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
3411e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
3412e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_rx_channel);
3413e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
3414e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_tx_channel);
3415e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tEnhanced descriptors: %s\n",
3416e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.enh_desc) ? "Y" : "N");
3417e7434821SGiuseppe CAVALLARO 
3418e7434821SGiuseppe CAVALLARO 	return 0;
3419e7434821SGiuseppe CAVALLARO }
3420e7434821SGiuseppe CAVALLARO 
3421e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
3422e7434821SGiuseppe CAVALLARO {
3423e7434821SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
3424e7434821SGiuseppe CAVALLARO }
3425e7434821SGiuseppe CAVALLARO 
3426e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = {
3427e7434821SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
3428e7434821SGiuseppe CAVALLARO 	.open = stmmac_sysfs_dma_cap_open,
3429e7434821SGiuseppe CAVALLARO 	.read = seq_read,
3430e7434821SGiuseppe CAVALLARO 	.llseek = seq_lseek,
343174863948SDjalal Harouni 	.release = single_release,
3432e7434821SGiuseppe CAVALLARO };
3433e7434821SGiuseppe CAVALLARO 
34347ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev)
34357ac29055SGiuseppe CAVALLARO {
3436466c5ac8SMathieu Olivari 	struct stmmac_priv *priv = netdev_priv(dev);
34377ac29055SGiuseppe CAVALLARO 
3438466c5ac8SMathieu Olivari 	/* Create per netdev entries */
3439466c5ac8SMathieu Olivari 	priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
3440466c5ac8SMathieu Olivari 
3441466c5ac8SMathieu Olivari 	if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) {
344238ddc59dSLABBE Corentin 		netdev_err(priv->dev, "ERROR failed to create debugfs directory\n");
34437ac29055SGiuseppe CAVALLARO 
34447ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
34457ac29055SGiuseppe CAVALLARO 	}
34467ac29055SGiuseppe CAVALLARO 
34477ac29055SGiuseppe CAVALLARO 	/* Entry to report DMA RX/TX rings */
3448466c5ac8SMathieu Olivari 	priv->dbgfs_rings_status =
3449466c5ac8SMathieu Olivari 		debugfs_create_file("descriptors_status", S_IRUGO,
3450466c5ac8SMathieu Olivari 				    priv->dbgfs_dir, dev,
34517ac29055SGiuseppe CAVALLARO 				    &stmmac_rings_status_fops);
34527ac29055SGiuseppe CAVALLARO 
3453466c5ac8SMathieu Olivari 	if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) {
345438ddc59dSLABBE Corentin 		netdev_err(priv->dev, "ERROR creating stmmac ring debugfs file\n");
3455466c5ac8SMathieu Olivari 		debugfs_remove_recursive(priv->dbgfs_dir);
34567ac29055SGiuseppe CAVALLARO 
34577ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
34587ac29055SGiuseppe CAVALLARO 	}
34597ac29055SGiuseppe CAVALLARO 
3460e7434821SGiuseppe CAVALLARO 	/* Entry to report the DMA HW features */
3461466c5ac8SMathieu Olivari 	priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", S_IRUGO,
3462466c5ac8SMathieu Olivari 					    priv->dbgfs_dir,
3463e7434821SGiuseppe CAVALLARO 					    dev, &stmmac_dma_cap_fops);
3464e7434821SGiuseppe CAVALLARO 
3465466c5ac8SMathieu Olivari 	if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) {
346638ddc59dSLABBE Corentin 		netdev_err(priv->dev, "ERROR creating stmmac MMC debugfs file\n");
3467466c5ac8SMathieu Olivari 		debugfs_remove_recursive(priv->dbgfs_dir);
3468e7434821SGiuseppe CAVALLARO 
3469e7434821SGiuseppe CAVALLARO 		return -ENOMEM;
3470e7434821SGiuseppe CAVALLARO 	}
3471e7434821SGiuseppe CAVALLARO 
34727ac29055SGiuseppe CAVALLARO 	return 0;
34737ac29055SGiuseppe CAVALLARO }
34747ac29055SGiuseppe CAVALLARO 
3475466c5ac8SMathieu Olivari static void stmmac_exit_fs(struct net_device *dev)
34767ac29055SGiuseppe CAVALLARO {
3477466c5ac8SMathieu Olivari 	struct stmmac_priv *priv = netdev_priv(dev);
3478466c5ac8SMathieu Olivari 
3479466c5ac8SMathieu Olivari 	debugfs_remove_recursive(priv->dbgfs_dir);
34807ac29055SGiuseppe CAVALLARO }
348150fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */
34827ac29055SGiuseppe CAVALLARO 
34837ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = {
34847ac6653aSJeff Kirsher 	.ndo_open = stmmac_open,
34857ac6653aSJeff Kirsher 	.ndo_start_xmit = stmmac_xmit,
34867ac6653aSJeff Kirsher 	.ndo_stop = stmmac_release,
34877ac6653aSJeff Kirsher 	.ndo_change_mtu = stmmac_change_mtu,
34887ac6653aSJeff Kirsher 	.ndo_fix_features = stmmac_fix_features,
3489d2afb5bdSGiuseppe CAVALLARO 	.ndo_set_features = stmmac_set_features,
349001789349SJiri Pirko 	.ndo_set_rx_mode = stmmac_set_rx_mode,
34917ac6653aSJeff Kirsher 	.ndo_tx_timeout = stmmac_tx_timeout,
34927ac6653aSJeff Kirsher 	.ndo_do_ioctl = stmmac_ioctl,
34937ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
34947ac6653aSJeff Kirsher 	.ndo_poll_controller = stmmac_poll_controller,
34957ac6653aSJeff Kirsher #endif
34967ac6653aSJeff Kirsher 	.ndo_set_mac_address = eth_mac_addr,
34977ac6653aSJeff Kirsher };
34987ac6653aSJeff Kirsher 
34997ac6653aSJeff Kirsher /**
3500cf3f047bSGiuseppe CAVALLARO  *  stmmac_hw_init - Init the MAC device
350132ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
3502732fdf0eSGiuseppe CAVALLARO  *  Description: this function is to configure the MAC device according to
3503732fdf0eSGiuseppe CAVALLARO  *  some platform parameters or the HW capability register. It prepares the
3504732fdf0eSGiuseppe CAVALLARO  *  driver to use either ring or chain modes and to setup either enhanced or
3505732fdf0eSGiuseppe CAVALLARO  *  normal descriptors.
3506cf3f047bSGiuseppe CAVALLARO  */
3507cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv)
3508cf3f047bSGiuseppe CAVALLARO {
3509cf3f047bSGiuseppe CAVALLARO 	struct mac_device_info *mac;
3510cf3f047bSGiuseppe CAVALLARO 
3511cf3f047bSGiuseppe CAVALLARO 	/* Identify the MAC HW device */
351203f2eecdSMarc Kleine-Budde 	if (priv->plat->has_gmac) {
351303f2eecdSMarc Kleine-Budde 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
35143b57de95SVince Bridgers 		mac = dwmac1000_setup(priv->ioaddr,
35153b57de95SVince Bridgers 				      priv->plat->multicast_filter_bins,
3516c623d149SAlexandre TORGUE 				      priv->plat->unicast_filter_entries,
3517c623d149SAlexandre TORGUE 				      &priv->synopsys_id);
3518f748be53SAlexandre TORGUE 	} else if (priv->plat->has_gmac4) {
3519f748be53SAlexandre TORGUE 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
3520f748be53SAlexandre TORGUE 		mac = dwmac4_setup(priv->ioaddr,
3521f748be53SAlexandre TORGUE 				   priv->plat->multicast_filter_bins,
3522f748be53SAlexandre TORGUE 				   priv->plat->unicast_filter_entries,
3523f748be53SAlexandre TORGUE 				   &priv->synopsys_id);
352403f2eecdSMarc Kleine-Budde 	} else {
3525c623d149SAlexandre TORGUE 		mac = dwmac100_setup(priv->ioaddr, &priv->synopsys_id);
352603f2eecdSMarc Kleine-Budde 	}
3527cf3f047bSGiuseppe CAVALLARO 	if (!mac)
3528cf3f047bSGiuseppe CAVALLARO 		return -ENOMEM;
3529cf3f047bSGiuseppe CAVALLARO 
3530cf3f047bSGiuseppe CAVALLARO 	priv->hw = mac;
3531cf3f047bSGiuseppe CAVALLARO 
35324a7d666aSGiuseppe CAVALLARO 	/* To use the chained or ring mode */
3533f748be53SAlexandre TORGUE 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
3534f748be53SAlexandre TORGUE 		priv->hw->mode = &dwmac4_ring_mode_ops;
3535f748be53SAlexandre TORGUE 	} else {
35364a7d666aSGiuseppe CAVALLARO 		if (chain_mode) {
353729896a67SGiuseppe CAVALLARO 			priv->hw->mode = &chain_mode_ops;
353838ddc59dSLABBE Corentin 			dev_info(priv->device, "Chain mode enabled\n");
35394a7d666aSGiuseppe CAVALLARO 			priv->mode = STMMAC_CHAIN_MODE;
35404a7d666aSGiuseppe CAVALLARO 		} else {
354129896a67SGiuseppe CAVALLARO 			priv->hw->mode = &ring_mode_ops;
354238ddc59dSLABBE Corentin 			dev_info(priv->device, "Ring mode enabled\n");
35434a7d666aSGiuseppe CAVALLARO 			priv->mode = STMMAC_RING_MODE;
35444a7d666aSGiuseppe CAVALLARO 		}
3545f748be53SAlexandre TORGUE 	}
35464a7d666aSGiuseppe CAVALLARO 
3547cf3f047bSGiuseppe CAVALLARO 	/* Get the HW capability (new GMAC newer than 3.50a) */
3548cf3f047bSGiuseppe CAVALLARO 	priv->hw_cap_support = stmmac_get_hw_features(priv);
3549cf3f047bSGiuseppe CAVALLARO 	if (priv->hw_cap_support) {
355038ddc59dSLABBE Corentin 		dev_info(priv->device, "DMA HW capability register supported\n");
3551cf3f047bSGiuseppe CAVALLARO 
3552cf3f047bSGiuseppe CAVALLARO 		/* We can override some gmac/dma configuration fields: e.g.
3553cf3f047bSGiuseppe CAVALLARO 		 * enh_desc, tx_coe (e.g. that are passed through the
3554cf3f047bSGiuseppe CAVALLARO 		 * platform) with the values from the HW capability
3555cf3f047bSGiuseppe CAVALLARO 		 * register (if supported).
3556cf3f047bSGiuseppe CAVALLARO 		 */
3557cf3f047bSGiuseppe CAVALLARO 		priv->plat->enh_desc = priv->dma_cap.enh_desc;
3558cf3f047bSGiuseppe CAVALLARO 		priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
35593fe5cadbSGiuseppe CAVALLARO 		priv->hw->pmt = priv->plat->pmt;
356038912bdbSDeepak SIKRI 
3561a8df35d4SEzequiel Garcia 		/* TXCOE doesn't work in thresh DMA mode */
3562a8df35d4SEzequiel Garcia 		if (priv->plat->force_thresh_dma_mode)
3563a8df35d4SEzequiel Garcia 			priv->plat->tx_coe = 0;
3564a8df35d4SEzequiel Garcia 		else
356538912bdbSDeepak SIKRI 			priv->plat->tx_coe = priv->dma_cap.tx_coe;
3566a8df35d4SEzequiel Garcia 
3567f748be53SAlexandre TORGUE 		/* In case of GMAC4 rx_coe is from HW cap register. */
3568f748be53SAlexandre TORGUE 		priv->plat->rx_coe = priv->dma_cap.rx_coe;
356938912bdbSDeepak SIKRI 
357038912bdbSDeepak SIKRI 		if (priv->dma_cap.rx_coe_type2)
357138912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
357238912bdbSDeepak SIKRI 		else if (priv->dma_cap.rx_coe_type1)
357338912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
357438912bdbSDeepak SIKRI 
357538ddc59dSLABBE Corentin 	} else {
357638ddc59dSLABBE Corentin 		dev_info(priv->device, "No HW DMA feature register supported\n");
357738ddc59dSLABBE Corentin 	}
3578cf3f047bSGiuseppe CAVALLARO 
3579f748be53SAlexandre TORGUE 	/* To use alternate (extended), normal or GMAC4 descriptor structures */
3580f748be53SAlexandre TORGUE 	if (priv->synopsys_id >= DWMAC_CORE_4_00)
3581f748be53SAlexandre TORGUE 		priv->hw->desc = &dwmac4_desc_ops;
3582f748be53SAlexandre TORGUE 	else
358361369d02SByungho An 		stmmac_selec_desc_mode(priv);
358461369d02SByungho An 
3585d2afb5bdSGiuseppe CAVALLARO 	if (priv->plat->rx_coe) {
3586d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
358738ddc59dSLABBE Corentin 		dev_info(priv->device, "RX Checksum Offload Engine supported\n");
3588f748be53SAlexandre TORGUE 		if (priv->synopsys_id < DWMAC_CORE_4_00)
358938ddc59dSLABBE Corentin 			dev_info(priv->device, "COE Type %d\n", priv->hw->rx_csum);
3590d2afb5bdSGiuseppe CAVALLARO 	}
3591cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->tx_coe)
359238ddc59dSLABBE Corentin 		dev_info(priv->device, "TX Checksum insertion supported\n");
3593cf3f047bSGiuseppe CAVALLARO 
3594cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->pmt) {
359538ddc59dSLABBE Corentin 		dev_info(priv->device, "Wake-Up On Lan supported\n");
3596cf3f047bSGiuseppe CAVALLARO 		device_set_wakeup_capable(priv->device, 1);
3597cf3f047bSGiuseppe CAVALLARO 	}
3598cf3f047bSGiuseppe CAVALLARO 
3599f748be53SAlexandre TORGUE 	if (priv->dma_cap.tsoen)
360038ddc59dSLABBE Corentin 		dev_info(priv->device, "TSO supported\n");
3601f748be53SAlexandre TORGUE 
3602c24602efSGiuseppe CAVALLARO 	return 0;
3603cf3f047bSGiuseppe CAVALLARO }
3604cf3f047bSGiuseppe CAVALLARO 
3605cf3f047bSGiuseppe CAVALLARO /**
3606bfab27a1SGiuseppe CAVALLARO  * stmmac_dvr_probe
3607bfab27a1SGiuseppe CAVALLARO  * @device: device pointer
3608ff3dd78cSGiuseppe CAVALLARO  * @plat_dat: platform data pointer
3609e56788cfSJoachim Eastwood  * @res: stmmac resource pointer
3610bfab27a1SGiuseppe CAVALLARO  * Description: this is the main probe function used to
3611bfab27a1SGiuseppe CAVALLARO  * call the alloc_etherdev, allocate the priv structure.
36129afec6efSAndy Shevchenko  * Return:
361315ffac73SJoachim Eastwood  * returns 0 on success, otherwise errno.
36147ac6653aSJeff Kirsher  */
361515ffac73SJoachim Eastwood int stmmac_dvr_probe(struct device *device,
3616cf3f047bSGiuseppe CAVALLARO 		     struct plat_stmmacenet_data *plat_dat,
3617e56788cfSJoachim Eastwood 		     struct stmmac_resources *res)
36187ac6653aSJeff Kirsher {
36195bacd778SLABBE Corentin 	int ret = 0;
3620bfab27a1SGiuseppe CAVALLARO 	struct net_device *ndev = NULL;
3621bfab27a1SGiuseppe CAVALLARO 	struct stmmac_priv *priv;
36227ac6653aSJeff Kirsher 
36235bacd778SLABBE Corentin 	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
362441de8d4cSJoe Perches 	if (!ndev)
362515ffac73SJoachim Eastwood 		return -ENOMEM;
36267ac6653aSJeff Kirsher 
3627bfab27a1SGiuseppe CAVALLARO 	SET_NETDEV_DEV(ndev, device);
36287ac6653aSJeff Kirsher 
3629bfab27a1SGiuseppe CAVALLARO 	priv = netdev_priv(ndev);
3630bfab27a1SGiuseppe CAVALLARO 	priv->device = device;
3631bfab27a1SGiuseppe CAVALLARO 	priv->dev = ndev;
3632bfab27a1SGiuseppe CAVALLARO 
3633bfab27a1SGiuseppe CAVALLARO 	stmmac_set_ethtool_ops(ndev);
3634cf3f047bSGiuseppe CAVALLARO 	priv->pause = pause;
3635cf3f047bSGiuseppe CAVALLARO 	priv->plat = plat_dat;
3636e56788cfSJoachim Eastwood 	priv->ioaddr = res->addr;
3637e56788cfSJoachim Eastwood 	priv->dev->base_addr = (unsigned long)res->addr;
3638e56788cfSJoachim Eastwood 
3639e56788cfSJoachim Eastwood 	priv->dev->irq = res->irq;
3640e56788cfSJoachim Eastwood 	priv->wol_irq = res->wol_irq;
3641e56788cfSJoachim Eastwood 	priv->lpi_irq = res->lpi_irq;
3642e56788cfSJoachim Eastwood 
3643e56788cfSJoachim Eastwood 	if (res->mac)
3644e56788cfSJoachim Eastwood 		memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN);
3645bfab27a1SGiuseppe CAVALLARO 
3646a7a62685SJoachim Eastwood 	dev_set_drvdata(device, priv->dev);
3647803f8fc4SJoachim Eastwood 
3648cf3f047bSGiuseppe CAVALLARO 	/* Verify driver arguments */
3649cf3f047bSGiuseppe CAVALLARO 	stmmac_verify_args();
3650cf3f047bSGiuseppe CAVALLARO 
3651cf3f047bSGiuseppe CAVALLARO 	/* Override with kernel parameters if supplied XXX CRS XXX
3652ceb69499SGiuseppe CAVALLARO 	 * this needs to have multiple instances
3653ceb69499SGiuseppe CAVALLARO 	 */
3654cf3f047bSGiuseppe CAVALLARO 	if ((phyaddr >= 0) && (phyaddr <= 31))
3655cf3f047bSGiuseppe CAVALLARO 		priv->plat->phy_addr = phyaddr;
3656cf3f047bSGiuseppe CAVALLARO 
3657f573c0b9Sjpinto 	if (priv->plat->stmmac_rst)
3658f573c0b9Sjpinto 		reset_control_deassert(priv->plat->stmmac_rst);
3659c5e4ddbdSChen-Yu Tsai 
3660cf3f047bSGiuseppe CAVALLARO 	/* Init MAC and get the capabilities */
3661c24602efSGiuseppe CAVALLARO 	ret = stmmac_hw_init(priv);
3662c24602efSGiuseppe CAVALLARO 	if (ret)
366362866e98SChen-Yu Tsai 		goto error_hw_init;
3664cf3f047bSGiuseppe CAVALLARO 
3665cf3f047bSGiuseppe CAVALLARO 	ndev->netdev_ops = &stmmac_netdev_ops;
3666cf3f047bSGiuseppe CAVALLARO 
3667cf3f047bSGiuseppe CAVALLARO 	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
3668cf3f047bSGiuseppe CAVALLARO 			    NETIF_F_RXCSUM;
3669f748be53SAlexandre TORGUE 
3670f748be53SAlexandre TORGUE 	if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
3671f748be53SAlexandre TORGUE 		ndev->hw_features |= NETIF_F_TSO;
3672f748be53SAlexandre TORGUE 		priv->tso = true;
367338ddc59dSLABBE Corentin 		dev_info(priv->device, "TSO feature enabled\n");
3674f748be53SAlexandre TORGUE 	}
3675bfab27a1SGiuseppe CAVALLARO 	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
3676bfab27a1SGiuseppe CAVALLARO 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
36777ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED
36787ac6653aSJeff Kirsher 	/* Both mac100 and gmac support receive VLAN tag detection */
3679f646968fSPatrick McHardy 	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
36807ac6653aSJeff Kirsher #endif
36817ac6653aSJeff Kirsher 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
36827ac6653aSJeff Kirsher 
368344770e11SJarod Wilson 	/* MTU range: 46 - hw-specific max */
368444770e11SJarod Wilson 	ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
368544770e11SJarod Wilson 	if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00))
368644770e11SJarod Wilson 		ndev->max_mtu = JUMBO_LEN;
368744770e11SJarod Wilson 	else
368844770e11SJarod Wilson 		ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
3689a2cd64f3SKweh, Hock Leong 	/* Will not overwrite ndev->max_mtu if plat->maxmtu > ndev->max_mtu
3690a2cd64f3SKweh, Hock Leong 	 * as well as plat->maxmtu < ndev->min_mtu which is a invalid range.
3691a2cd64f3SKweh, Hock Leong 	 */
3692a2cd64f3SKweh, Hock Leong 	if ((priv->plat->maxmtu < ndev->max_mtu) &&
3693a2cd64f3SKweh, Hock Leong 	    (priv->plat->maxmtu >= ndev->min_mtu))
369444770e11SJarod Wilson 		ndev->max_mtu = priv->plat->maxmtu;
3695a2cd64f3SKweh, Hock Leong 	else if (priv->plat->maxmtu < ndev->min_mtu)
3696b618ab45SHeiner Kallweit 		dev_warn(priv->device,
3697a2cd64f3SKweh, Hock Leong 			 "%s: warning: maxmtu having invalid value (%d)\n",
3698a2cd64f3SKweh, Hock Leong 			 __func__, priv->plat->maxmtu);
369944770e11SJarod Wilson 
37007ac6653aSJeff Kirsher 	if (flow_ctrl)
37017ac6653aSJeff Kirsher 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
37027ac6653aSJeff Kirsher 
370362a2ab93SGiuseppe CAVALLARO 	/* Rx Watchdog is available in the COREs newer than the 3.40.
370462a2ab93SGiuseppe CAVALLARO 	 * In some case, for example on bugged HW this feature
370562a2ab93SGiuseppe CAVALLARO 	 * has to be disable and this can be done by passing the
370662a2ab93SGiuseppe CAVALLARO 	 * riwt_off field from the platform.
370762a2ab93SGiuseppe CAVALLARO 	 */
370862a2ab93SGiuseppe CAVALLARO 	if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
370962a2ab93SGiuseppe CAVALLARO 		priv->use_riwt = 1;
3710b618ab45SHeiner Kallweit 		dev_info(priv->device,
3711b618ab45SHeiner Kallweit 			 "Enable RX Mitigation via HW Watchdog Timer\n");
371262a2ab93SGiuseppe CAVALLARO 	}
371362a2ab93SGiuseppe CAVALLARO 
37145bacd778SLABBE Corentin 	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
37157ac6653aSJeff Kirsher 
37167ac6653aSJeff Kirsher 	spin_lock_init(&priv->lock);
37177ac6653aSJeff Kirsher 
3718cd7201f4SGiuseppe CAVALLARO 	/* If a specific clk_csr value is passed from the platform
3719cd7201f4SGiuseppe CAVALLARO 	 * this means that the CSR Clock Range selection cannot be
3720cd7201f4SGiuseppe CAVALLARO 	 * changed at run-time and it is fixed. Viceversa the driver'll try to
3721cd7201f4SGiuseppe CAVALLARO 	 * set the MDC clock dynamically according to the csr actual
3722cd7201f4SGiuseppe CAVALLARO 	 * clock input.
3723cd7201f4SGiuseppe CAVALLARO 	 */
3724cd7201f4SGiuseppe CAVALLARO 	if (!priv->plat->clk_csr)
3725cd7201f4SGiuseppe CAVALLARO 		stmmac_clk_csr_set(priv);
3726cd7201f4SGiuseppe CAVALLARO 	else
3727cd7201f4SGiuseppe CAVALLARO 		priv->clk_csr = priv->plat->clk_csr;
3728cd7201f4SGiuseppe CAVALLARO 
3729e58bb43fSGiuseppe CAVALLARO 	stmmac_check_pcs_mode(priv);
3730e58bb43fSGiuseppe CAVALLARO 
37313fe5cadbSGiuseppe CAVALLARO 	if (priv->hw->pcs != STMMAC_PCS_RGMII  &&
37323fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_TBI &&
37333fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_RTBI) {
37344bfcbd7aSFrancesco Virlinzi 		/* MDIO bus Registration */
37354bfcbd7aSFrancesco Virlinzi 		ret = stmmac_mdio_register(ndev);
37364bfcbd7aSFrancesco Virlinzi 		if (ret < 0) {
3737b618ab45SHeiner Kallweit 			dev_err(priv->device,
373838ddc59dSLABBE Corentin 				"%s: MDIO bus (id: %d) registration failed",
37394bfcbd7aSFrancesco Virlinzi 				__func__, priv->plat->bus_id);
37406a81c26fSViresh Kumar 			goto error_mdio_register;
37414bfcbd7aSFrancesco Virlinzi 		}
3742e58bb43fSGiuseppe CAVALLARO 	}
37434bfcbd7aSFrancesco Virlinzi 
374457016590SFlorian Fainelli 	ret = register_netdev(ndev);
3745b2eb09afSFlorian Fainelli 	if (ret) {
3746b618ab45SHeiner Kallweit 		dev_err(priv->device, "%s: ERROR %i registering the device\n",
374757016590SFlorian Fainelli 			__func__, ret);
3748b2eb09afSFlorian Fainelli 		goto error_netdev_register;
3749b2eb09afSFlorian Fainelli 	}
37507ac6653aSJeff Kirsher 
375157016590SFlorian Fainelli 	return ret;
37527ac6653aSJeff Kirsher 
37536a81c26fSViresh Kumar error_netdev_register:
3754b2eb09afSFlorian Fainelli 	if (priv->hw->pcs != STMMAC_PCS_RGMII &&
3755b2eb09afSFlorian Fainelli 	    priv->hw->pcs != STMMAC_PCS_TBI &&
3756b2eb09afSFlorian Fainelli 	    priv->hw->pcs != STMMAC_PCS_RTBI)
3757b2eb09afSFlorian Fainelli 		stmmac_mdio_unregister(ndev);
37587ac6653aSJeff Kirsher error_mdio_register:
37595bacd778SLABBE Corentin 	netif_napi_del(&priv->napi);
376062866e98SChen-Yu Tsai error_hw_init:
37617ac6653aSJeff Kirsher 	free_netdev(ndev);
37627ac6653aSJeff Kirsher 
376315ffac73SJoachim Eastwood 	return ret;
37647ac6653aSJeff Kirsher }
3765b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_probe);
37667ac6653aSJeff Kirsher 
37677ac6653aSJeff Kirsher /**
37687ac6653aSJeff Kirsher  * stmmac_dvr_remove
3769f4e7bd81SJoachim Eastwood  * @dev: device pointer
37707ac6653aSJeff Kirsher  * Description: this function resets the TX/RX processes, disables the MAC RX/TX
3771bfab27a1SGiuseppe CAVALLARO  * changes the link status, releases the DMA descriptor rings.
37727ac6653aSJeff Kirsher  */
3773f4e7bd81SJoachim Eastwood int stmmac_dvr_remove(struct device *dev)
37747ac6653aSJeff Kirsher {
3775f4e7bd81SJoachim Eastwood 	struct net_device *ndev = dev_get_drvdata(dev);
37767ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
37777ac6653aSJeff Kirsher 
377838ddc59dSLABBE Corentin 	netdev_info(priv->dev, "%s: removing driver", __func__);
37797ac6653aSJeff Kirsher 
3780ae4f0d46SJoao Pinto 	stmmac_stop_all_dma(priv);
37817ac6653aSJeff Kirsher 
3782270c7759SLABBE Corentin 	priv->hw->mac->set_mac(priv->ioaddr, false);
37837ac6653aSJeff Kirsher 	netif_carrier_off(ndev);
37847ac6653aSJeff Kirsher 	unregister_netdev(ndev);
3785f573c0b9Sjpinto 	if (priv->plat->stmmac_rst)
3786f573c0b9Sjpinto 		reset_control_assert(priv->plat->stmmac_rst);
3787f573c0b9Sjpinto 	clk_disable_unprepare(priv->plat->pclk);
3788f573c0b9Sjpinto 	clk_disable_unprepare(priv->plat->stmmac_clk);
37893fe5cadbSGiuseppe CAVALLARO 	if (priv->hw->pcs != STMMAC_PCS_RGMII &&
37903fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_TBI &&
37913fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_RTBI)
3792e743471fSBryan O'Donoghue 		stmmac_mdio_unregister(ndev);
37937ac6653aSJeff Kirsher 	free_netdev(ndev);
37947ac6653aSJeff Kirsher 
37957ac6653aSJeff Kirsher 	return 0;
37967ac6653aSJeff Kirsher }
3797b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_remove);
37987ac6653aSJeff Kirsher 
3799732fdf0eSGiuseppe CAVALLARO /**
3800732fdf0eSGiuseppe CAVALLARO  * stmmac_suspend - suspend callback
3801f4e7bd81SJoachim Eastwood  * @dev: device pointer
3802732fdf0eSGiuseppe CAVALLARO  * Description: this is the function to suspend the device and it is called
3803732fdf0eSGiuseppe CAVALLARO  * by the platform driver to stop the network queue, release the resources,
3804732fdf0eSGiuseppe CAVALLARO  * program the PMT register (for WoL), clean and release driver resources.
3805732fdf0eSGiuseppe CAVALLARO  */
3806f4e7bd81SJoachim Eastwood int stmmac_suspend(struct device *dev)
38077ac6653aSJeff Kirsher {
3808f4e7bd81SJoachim Eastwood 	struct net_device *ndev = dev_get_drvdata(dev);
38097ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
3810f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
38117ac6653aSJeff Kirsher 
38127ac6653aSJeff Kirsher 	if (!ndev || !netif_running(ndev))
38137ac6653aSJeff Kirsher 		return 0;
38147ac6653aSJeff Kirsher 
3815d6d50c7eSPhilippe Reynes 	if (ndev->phydev)
3816d6d50c7eSPhilippe Reynes 		phy_stop(ndev->phydev);
3817102463b1SFrancesco Virlinzi 
3818f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
38197ac6653aSJeff Kirsher 
38207ac6653aSJeff Kirsher 	netif_device_detach(ndev);
38215bacd778SLABBE Corentin 	netif_stop_queue(ndev);
38227ac6653aSJeff Kirsher 
38235bacd778SLABBE Corentin 	napi_disable(&priv->napi);
38247ac6653aSJeff Kirsher 
38257ac6653aSJeff Kirsher 	/* Stop TX/RX DMA */
3826ae4f0d46SJoao Pinto 	stmmac_stop_all_dma(priv);
3827c24602efSGiuseppe CAVALLARO 
38287ac6653aSJeff Kirsher 	/* Enable Power down mode by programming the PMT regs */
382989f7f2cfSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
38307ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, priv->wolopts);
383189f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 1;
383289f7f2cfSSrinivas Kandagatla 	} else {
3833270c7759SLABBE Corentin 		priv->hw->mac->set_mac(priv->ioaddr, false);
3834db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_sleep_state(priv->device);
3835ba1377ffSGiuseppe CAVALLARO 		/* Disable clock in case of PWM is off */
3836f573c0b9Sjpinto 		clk_disable(priv->plat->pclk);
3837f573c0b9Sjpinto 		clk_disable(priv->plat->stmmac_clk);
3838ba1377ffSGiuseppe CAVALLARO 	}
3839f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
38402d871aa0SVince Bridgers 
38412d871aa0SVince Bridgers 	priv->oldlink = 0;
3842bd00632cSLABBE Corentin 	priv->speed = SPEED_UNKNOWN;
3843bd00632cSLABBE Corentin 	priv->oldduplex = DUPLEX_UNKNOWN;
38447ac6653aSJeff Kirsher 	return 0;
38457ac6653aSJeff Kirsher }
3846b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_suspend);
38477ac6653aSJeff Kirsher 
3848732fdf0eSGiuseppe CAVALLARO /**
3849732fdf0eSGiuseppe CAVALLARO  * stmmac_resume - resume callback
3850f4e7bd81SJoachim Eastwood  * @dev: device pointer
3851732fdf0eSGiuseppe CAVALLARO  * Description: when resume this function is invoked to setup the DMA and CORE
3852732fdf0eSGiuseppe CAVALLARO  * in a usable state.
3853732fdf0eSGiuseppe CAVALLARO  */
3854f4e7bd81SJoachim Eastwood int stmmac_resume(struct device *dev)
38557ac6653aSJeff Kirsher {
3856f4e7bd81SJoachim Eastwood 	struct net_device *ndev = dev_get_drvdata(dev);
38577ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
3858f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
38597ac6653aSJeff Kirsher 
38607ac6653aSJeff Kirsher 	if (!netif_running(ndev))
38617ac6653aSJeff Kirsher 		return 0;
38627ac6653aSJeff Kirsher 
38637ac6653aSJeff Kirsher 	/* Power Down bit, into the PM register, is cleared
38647ac6653aSJeff Kirsher 	 * automatically as soon as a magic packet or a Wake-up frame
38657ac6653aSJeff Kirsher 	 * is received. Anyway, it's better to manually clear
38667ac6653aSJeff Kirsher 	 * this bit because it can generate problems while resuming
3867ceb69499SGiuseppe CAVALLARO 	 * from another devices (e.g. serial console).
3868ceb69499SGiuseppe CAVALLARO 	 */
3869623997fbSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
3870f55d84b0SVincent Palatin 		spin_lock_irqsave(&priv->lock, flags);
38717ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, 0);
3872f55d84b0SVincent Palatin 		spin_unlock_irqrestore(&priv->lock, flags);
387389f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 0;
3874623997fbSSrinivas Kandagatla 	} else {
3875db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_default_state(priv->device);
38768d45e42bSLABBE Corentin 		/* enable the clk previously disabled */
3877f573c0b9Sjpinto 		clk_enable(priv->plat->stmmac_clk);
3878f573c0b9Sjpinto 		clk_enable(priv->plat->pclk);
3879623997fbSSrinivas Kandagatla 		/* reset the phy so that it's ready */
3880623997fbSSrinivas Kandagatla 		if (priv->mii)
3881623997fbSSrinivas Kandagatla 			stmmac_mdio_reset(priv->mii);
3882623997fbSSrinivas Kandagatla 	}
38837ac6653aSJeff Kirsher 
38847ac6653aSJeff Kirsher 	netif_device_attach(ndev);
38857ac6653aSJeff Kirsher 
3886f55d84b0SVincent Palatin 	spin_lock_irqsave(&priv->lock, flags);
3887f55d84b0SVincent Palatin 
38885bacd778SLABBE Corentin 	priv->cur_rx = 0;
38895bacd778SLABBE Corentin 	priv->dirty_rx = 0;
38905bacd778SLABBE Corentin 	priv->dirty_tx = 0;
38915bacd778SLABBE Corentin 	priv->cur_tx = 0;
3892f748be53SAlexandre TORGUE 	/* reset private mss value to force mss context settings at
3893f748be53SAlexandre TORGUE 	 * next tso xmit (only used for gmac4).
3894f748be53SAlexandre TORGUE 	 */
3895f748be53SAlexandre TORGUE 	priv->mss = 0;
3896f748be53SAlexandre TORGUE 
3897ae79a639SGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
3898ae79a639SGiuseppe CAVALLARO 
3899fe131929SHuacai Chen 	stmmac_hw_setup(ndev, false);
3900777da230SGiuseppe CAVALLARO 	stmmac_init_tx_coalesce(priv);
3901ac316c78SGiuseppe CAVALLARO 	stmmac_set_rx_mode(ndev);
39027ac6653aSJeff Kirsher 
39035bacd778SLABBE Corentin 	napi_enable(&priv->napi);
39047ac6653aSJeff Kirsher 
39055bacd778SLABBE Corentin 	netif_start_queue(ndev);
39067ac6653aSJeff Kirsher 
3907f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
3908102463b1SFrancesco Virlinzi 
3909d6d50c7eSPhilippe Reynes 	if (ndev->phydev)
3910d6d50c7eSPhilippe Reynes 		phy_start(ndev->phydev);
3911102463b1SFrancesco Virlinzi 
39127ac6653aSJeff Kirsher 	return 0;
39137ac6653aSJeff Kirsher }
3914b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_resume);
3915ba27ec66SGiuseppe CAVALLARO 
39167ac6653aSJeff Kirsher #ifndef MODULE
39177ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str)
39187ac6653aSJeff Kirsher {
39197ac6653aSJeff Kirsher 	char *opt;
39207ac6653aSJeff Kirsher 
39217ac6653aSJeff Kirsher 	if (!str || !*str)
39227ac6653aSJeff Kirsher 		return -EINVAL;
39237ac6653aSJeff Kirsher 	while ((opt = strsep(&str, ",")) != NULL) {
39247ac6653aSJeff Kirsher 		if (!strncmp(opt, "debug:", 6)) {
3925ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &debug))
39267ac6653aSJeff Kirsher 				goto err;
39277ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "phyaddr:", 8)) {
3928ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 8, 0, &phyaddr))
39297ac6653aSJeff Kirsher 				goto err;
39307ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "buf_sz:", 7)) {
3931ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 7, 0, &buf_sz))
39327ac6653aSJeff Kirsher 				goto err;
39337ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "tc:", 3)) {
3934ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 3, 0, &tc))
39357ac6653aSJeff Kirsher 				goto err;
39367ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "watchdog:", 9)) {
3937ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 9, 0, &watchdog))
39387ac6653aSJeff Kirsher 				goto err;
39397ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "flow_ctrl:", 10)) {
3940ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &flow_ctrl))
39417ac6653aSJeff Kirsher 				goto err;
39427ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "pause:", 6)) {
3943ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &pause))
39447ac6653aSJeff Kirsher 				goto err;
3945506f669cSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "eee_timer:", 10)) {
3946d765955dSGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &eee_timer))
3947d765955dSGiuseppe CAVALLARO 				goto err;
39484a7d666aSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "chain_mode:", 11)) {
39494a7d666aSGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &chain_mode))
39504a7d666aSGiuseppe CAVALLARO 				goto err;
39517ac6653aSJeff Kirsher 		}
39527ac6653aSJeff Kirsher 	}
39537ac6653aSJeff Kirsher 	return 0;
39547ac6653aSJeff Kirsher 
39557ac6653aSJeff Kirsher err:
39567ac6653aSJeff Kirsher 	pr_err("%s: ERROR broken module parameter conversion", __func__);
39577ac6653aSJeff Kirsher 	return -EINVAL;
39587ac6653aSJeff Kirsher }
39597ac6653aSJeff Kirsher 
39607ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt);
3961ceb69499SGiuseppe CAVALLARO #endif /* MODULE */
39626fc0d0f2SGiuseppe Cavallaro 
3963466c5ac8SMathieu Olivari static int __init stmmac_init(void)
3964466c5ac8SMathieu Olivari {
3965466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS
3966466c5ac8SMathieu Olivari 	/* Create debugfs main directory if it doesn't exist yet */
3967466c5ac8SMathieu Olivari 	if (!stmmac_fs_dir) {
3968466c5ac8SMathieu Olivari 		stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
3969466c5ac8SMathieu Olivari 
3970466c5ac8SMathieu Olivari 		if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
3971466c5ac8SMathieu Olivari 			pr_err("ERROR %s, debugfs create directory failed\n",
3972466c5ac8SMathieu Olivari 			       STMMAC_RESOURCE_NAME);
3973466c5ac8SMathieu Olivari 
3974466c5ac8SMathieu Olivari 			return -ENOMEM;
3975466c5ac8SMathieu Olivari 		}
3976466c5ac8SMathieu Olivari 	}
3977466c5ac8SMathieu Olivari #endif
3978466c5ac8SMathieu Olivari 
3979466c5ac8SMathieu Olivari 	return 0;
3980466c5ac8SMathieu Olivari }
3981466c5ac8SMathieu Olivari 
3982466c5ac8SMathieu Olivari static void __exit stmmac_exit(void)
3983466c5ac8SMathieu Olivari {
3984466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS
3985466c5ac8SMathieu Olivari 	debugfs_remove_recursive(stmmac_fs_dir);
3986466c5ac8SMathieu Olivari #endif
3987466c5ac8SMathieu Olivari }
3988466c5ac8SMathieu Olivari 
3989466c5ac8SMathieu Olivari module_init(stmmac_init)
3990466c5ac8SMathieu Olivari module_exit(stmmac_exit)
3991466c5ac8SMathieu Olivari 
39926fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
39936fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
39946fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL");
3995