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 
188ce736788SJoao Pinto static inline u32 stmmac_tx_avail(struct stmmac_priv *priv, u32 queue)
1897ac6653aSJeff Kirsher {
190ce736788SJoao Pinto 	struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
191a6a3e026SLABBE Corentin 	u32 avail;
192e3ad57c9SGiuseppe Cavallaro 
193ce736788SJoao Pinto 	if (tx_q->dirty_tx > tx_q->cur_tx)
194ce736788SJoao Pinto 		avail = tx_q->dirty_tx - tx_q->cur_tx - 1;
195e3ad57c9SGiuseppe Cavallaro 	else
196ce736788SJoao Pinto 		avail = DMA_TX_SIZE - tx_q->cur_tx + tx_q->dirty_tx - 1;
197e3ad57c9SGiuseppe Cavallaro 
198e3ad57c9SGiuseppe Cavallaro 	return avail;
199e3ad57c9SGiuseppe Cavallaro }
200e3ad57c9SGiuseppe Cavallaro 
20154139cf3SJoao Pinto /**
20254139cf3SJoao Pinto  * stmmac_rx_dirty - Get RX queue dirty
20354139cf3SJoao Pinto  * @priv: driver private structure
20454139cf3SJoao Pinto  * @queue: RX queue index
20554139cf3SJoao Pinto  */
20654139cf3SJoao Pinto static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv, u32 queue)
207e3ad57c9SGiuseppe Cavallaro {
20854139cf3SJoao Pinto 	struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
209a6a3e026SLABBE Corentin 	u32 dirty;
210e3ad57c9SGiuseppe Cavallaro 
21154139cf3SJoao Pinto 	if (rx_q->dirty_rx <= rx_q->cur_rx)
21254139cf3SJoao Pinto 		dirty = rx_q->cur_rx - rx_q->dirty_rx;
213e3ad57c9SGiuseppe Cavallaro 	else
21454139cf3SJoao Pinto 		dirty = DMA_RX_SIZE - rx_q->dirty_rx + rx_q->cur_rx;
215e3ad57c9SGiuseppe Cavallaro 
216e3ad57c9SGiuseppe Cavallaro 	return dirty;
2177ac6653aSJeff Kirsher }
2187ac6653aSJeff Kirsher 
21932ceabcaSGiuseppe CAVALLARO /**
220732fdf0eSGiuseppe CAVALLARO  * stmmac_hw_fix_mac_speed - callback for speed selection
22132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
2228d45e42bSLABBE Corentin  * Description: on some platforms (e.g. ST), some HW system configuration
22332ceabcaSGiuseppe CAVALLARO  * registers have to be set according to the link speed negotiated.
2247ac6653aSJeff Kirsher  */
2257ac6653aSJeff Kirsher static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
2267ac6653aSJeff Kirsher {
227d6d50c7eSPhilippe Reynes 	struct net_device *ndev = priv->dev;
228d6d50c7eSPhilippe Reynes 	struct phy_device *phydev = ndev->phydev;
2297ac6653aSJeff Kirsher 
2307ac6653aSJeff Kirsher 	if (likely(priv->plat->fix_mac_speed))
231ceb69499SGiuseppe CAVALLARO 		priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
2327ac6653aSJeff Kirsher }
2337ac6653aSJeff Kirsher 
23432ceabcaSGiuseppe CAVALLARO /**
235732fdf0eSGiuseppe CAVALLARO  * stmmac_enable_eee_mode - check and enter in LPI mode
23632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
237732fdf0eSGiuseppe CAVALLARO  * Description: this function is to verify and enter in LPI mode in case of
238732fdf0eSGiuseppe CAVALLARO  * EEE.
23932ceabcaSGiuseppe CAVALLARO  */
240d765955dSGiuseppe CAVALLARO static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
241d765955dSGiuseppe CAVALLARO {
242ce736788SJoao Pinto 	u32 tx_cnt = priv->plat->tx_queues_to_use;
243ce736788SJoao Pinto 	u32 queue;
244ce736788SJoao Pinto 
245ce736788SJoao Pinto 	/* check if all TX queues have the work finished */
246ce736788SJoao Pinto 	for (queue = 0; queue < tx_cnt; queue++) {
247ce736788SJoao Pinto 		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
248ce736788SJoao Pinto 
249ce736788SJoao Pinto 		if (tx_q->dirty_tx != tx_q->cur_tx)
250ce736788SJoao Pinto 			return; /* still unfinished work */
251ce736788SJoao Pinto 	}
252ce736788SJoao Pinto 
253d765955dSGiuseppe CAVALLARO 	/* Check and enter in LPI mode */
254ce736788SJoao Pinto 	if (!priv->tx_path_in_lpi_mode)
255b4b7b772Sjpinto 		priv->hw->mac->set_eee_mode(priv->hw,
256b4b7b772Sjpinto 					    priv->plat->en_tx_lpi_clockgating);
257d765955dSGiuseppe CAVALLARO }
258d765955dSGiuseppe CAVALLARO 
25932ceabcaSGiuseppe CAVALLARO /**
260732fdf0eSGiuseppe CAVALLARO  * stmmac_disable_eee_mode - disable and exit from LPI mode
26132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
26232ceabcaSGiuseppe CAVALLARO  * Description: this function is to exit and disable EEE in case of
26332ceabcaSGiuseppe CAVALLARO  * LPI state is true. This is called by the xmit.
26432ceabcaSGiuseppe CAVALLARO  */
265d765955dSGiuseppe CAVALLARO void stmmac_disable_eee_mode(struct stmmac_priv *priv)
266d765955dSGiuseppe CAVALLARO {
2677ed24bbeSVince Bridgers 	priv->hw->mac->reset_eee_mode(priv->hw);
268d765955dSGiuseppe CAVALLARO 	del_timer_sync(&priv->eee_ctrl_timer);
269d765955dSGiuseppe CAVALLARO 	priv->tx_path_in_lpi_mode = false;
270d765955dSGiuseppe CAVALLARO }
271d765955dSGiuseppe CAVALLARO 
272d765955dSGiuseppe CAVALLARO /**
273732fdf0eSGiuseppe CAVALLARO  * stmmac_eee_ctrl_timer - EEE TX SW timer.
274d765955dSGiuseppe CAVALLARO  * @arg : data hook
275d765955dSGiuseppe CAVALLARO  * Description:
27632ceabcaSGiuseppe CAVALLARO  *  if there is no data transfer and if we are not in LPI state,
277d765955dSGiuseppe CAVALLARO  *  then MAC Transmitter can be moved to LPI state.
278d765955dSGiuseppe CAVALLARO  */
279d765955dSGiuseppe CAVALLARO static void stmmac_eee_ctrl_timer(unsigned long arg)
280d765955dSGiuseppe CAVALLARO {
281d765955dSGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)arg;
282d765955dSGiuseppe CAVALLARO 
283d765955dSGiuseppe CAVALLARO 	stmmac_enable_eee_mode(priv);
284f5351ef7SGiuseppe CAVALLARO 	mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
285d765955dSGiuseppe CAVALLARO }
286d765955dSGiuseppe CAVALLARO 
287d765955dSGiuseppe CAVALLARO /**
288732fdf0eSGiuseppe CAVALLARO  * stmmac_eee_init - init EEE
28932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
290d765955dSGiuseppe CAVALLARO  * Description:
291732fdf0eSGiuseppe CAVALLARO  *  if the GMAC supports the EEE (from the HW cap reg) and the phy device
292732fdf0eSGiuseppe CAVALLARO  *  can also manage EEE, this function enable the LPI state and start related
293732fdf0eSGiuseppe CAVALLARO  *  timer.
294d765955dSGiuseppe CAVALLARO  */
295d765955dSGiuseppe CAVALLARO bool stmmac_eee_init(struct stmmac_priv *priv)
296d765955dSGiuseppe CAVALLARO {
297d6d50c7eSPhilippe Reynes 	struct net_device *ndev = priv->dev;
2984741cf9cSGiuseppe CAVALLARO 	unsigned long flags;
299d765955dSGiuseppe CAVALLARO 	bool ret = false;
300d765955dSGiuseppe CAVALLARO 
301f5351ef7SGiuseppe CAVALLARO 	/* Using PCS we cannot dial with the phy registers at this stage
302f5351ef7SGiuseppe CAVALLARO 	 * so we do not support extra feature like EEE.
303f5351ef7SGiuseppe CAVALLARO 	 */
3043fe5cadbSGiuseppe CAVALLARO 	if ((priv->hw->pcs == STMMAC_PCS_RGMII) ||
3053fe5cadbSGiuseppe CAVALLARO 	    (priv->hw->pcs == STMMAC_PCS_TBI) ||
3063fe5cadbSGiuseppe CAVALLARO 	    (priv->hw->pcs == STMMAC_PCS_RTBI))
307f5351ef7SGiuseppe CAVALLARO 		goto out;
308f5351ef7SGiuseppe CAVALLARO 
309d765955dSGiuseppe CAVALLARO 	/* MAC core supports the EEE feature. */
310d765955dSGiuseppe CAVALLARO 	if (priv->dma_cap.eee) {
31183bf79b6SGiuseppe CAVALLARO 		int tx_lpi_timer = priv->tx_lpi_timer;
312d765955dSGiuseppe CAVALLARO 
31383bf79b6SGiuseppe CAVALLARO 		/* Check if the PHY supports EEE */
314d6d50c7eSPhilippe Reynes 		if (phy_init_eee(ndev->phydev, 1)) {
31583bf79b6SGiuseppe CAVALLARO 			/* To manage at run-time if the EEE cannot be supported
31683bf79b6SGiuseppe CAVALLARO 			 * anymore (for example because the lp caps have been
31783bf79b6SGiuseppe CAVALLARO 			 * changed).
31883bf79b6SGiuseppe CAVALLARO 			 * In that case the driver disable own timers.
31983bf79b6SGiuseppe CAVALLARO 			 */
3204741cf9cSGiuseppe CAVALLARO 			spin_lock_irqsave(&priv->lock, flags);
32183bf79b6SGiuseppe CAVALLARO 			if (priv->eee_active) {
32238ddc59dSLABBE Corentin 				netdev_dbg(priv->dev, "disable EEE\n");
32383bf79b6SGiuseppe CAVALLARO 				del_timer_sync(&priv->eee_ctrl_timer);
3247ed24bbeSVince Bridgers 				priv->hw->mac->set_eee_timer(priv->hw, 0,
32583bf79b6SGiuseppe CAVALLARO 							     tx_lpi_timer);
32683bf79b6SGiuseppe CAVALLARO 			}
32783bf79b6SGiuseppe CAVALLARO 			priv->eee_active = 0;
3284741cf9cSGiuseppe CAVALLARO 			spin_unlock_irqrestore(&priv->lock, flags);
32983bf79b6SGiuseppe CAVALLARO 			goto out;
33083bf79b6SGiuseppe CAVALLARO 		}
33183bf79b6SGiuseppe CAVALLARO 		/* Activate the EEE and start timers */
3324741cf9cSGiuseppe CAVALLARO 		spin_lock_irqsave(&priv->lock, flags);
333f5351ef7SGiuseppe CAVALLARO 		if (!priv->eee_active) {
334d765955dSGiuseppe CAVALLARO 			priv->eee_active = 1;
335ccb36da1SVaishali Thakkar 			setup_timer(&priv->eee_ctrl_timer,
336ccb36da1SVaishali Thakkar 				    stmmac_eee_ctrl_timer,
337ccb36da1SVaishali Thakkar 				    (unsigned long)priv);
338ccb36da1SVaishali Thakkar 			mod_timer(&priv->eee_ctrl_timer,
339ccb36da1SVaishali Thakkar 				  STMMAC_LPI_T(eee_timer));
340d765955dSGiuseppe CAVALLARO 
3417ed24bbeSVince Bridgers 			priv->hw->mac->set_eee_timer(priv->hw,
342f5351ef7SGiuseppe CAVALLARO 						     STMMAC_DEFAULT_LIT_LS,
34383bf79b6SGiuseppe CAVALLARO 						     tx_lpi_timer);
34471965352SGiuseppe CAVALLARO 		}
345f5351ef7SGiuseppe CAVALLARO 		/* Set HW EEE according to the speed */
346d6d50c7eSPhilippe Reynes 		priv->hw->mac->set_eee_pls(priv->hw, ndev->phydev->link);
347d765955dSGiuseppe CAVALLARO 
348d765955dSGiuseppe CAVALLARO 		ret = true;
3494741cf9cSGiuseppe CAVALLARO 		spin_unlock_irqrestore(&priv->lock, flags);
3504741cf9cSGiuseppe CAVALLARO 
35138ddc59dSLABBE Corentin 		netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
352d765955dSGiuseppe CAVALLARO 	}
353d765955dSGiuseppe CAVALLARO out:
354d765955dSGiuseppe CAVALLARO 	return ret;
355d765955dSGiuseppe CAVALLARO }
356d765955dSGiuseppe CAVALLARO 
357732fdf0eSGiuseppe CAVALLARO /* stmmac_get_tx_hwtstamp - get HW TX timestamps
35832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
359ba1ffd74SGiuseppe CAVALLARO  * @p : descriptor pointer
360891434b1SRayagond Kokatanur  * @skb : the socket buffer
361891434b1SRayagond Kokatanur  * Description :
362891434b1SRayagond Kokatanur  * This function will read timestamp from the descriptor & pass it to stack.
363891434b1SRayagond Kokatanur  * and also perform some sanity checks.
364891434b1SRayagond Kokatanur  */
365891434b1SRayagond Kokatanur static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
366ba1ffd74SGiuseppe CAVALLARO 				   struct dma_desc *p, struct sk_buff *skb)
367891434b1SRayagond Kokatanur {
368891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps shhwtstamp;
369891434b1SRayagond Kokatanur 	u64 ns;
370891434b1SRayagond Kokatanur 
371891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
372891434b1SRayagond Kokatanur 		return;
373891434b1SRayagond Kokatanur 
374ceb69499SGiuseppe CAVALLARO 	/* exit if skb doesn't support hw tstamp */
37575e4364fSdamuzi000 	if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
376891434b1SRayagond Kokatanur 		return;
377891434b1SRayagond Kokatanur 
378891434b1SRayagond Kokatanur 	/* check tx tstamp status */
379ba1ffd74SGiuseppe CAVALLARO 	if (!priv->hw->desc->get_tx_timestamp_status(p)) {
380891434b1SRayagond Kokatanur 		/* get the valid tstamp */
381ba1ffd74SGiuseppe CAVALLARO 		ns = priv->hw->desc->get_timestamp(p, priv->adv_ts);
382891434b1SRayagond Kokatanur 
383891434b1SRayagond Kokatanur 		memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
384891434b1SRayagond Kokatanur 		shhwtstamp.hwtstamp = ns_to_ktime(ns);
385ba1ffd74SGiuseppe CAVALLARO 
386ba1ffd74SGiuseppe CAVALLARO 		netdev_info(priv->dev, "get valid TX hw timestamp %llu\n", ns);
387891434b1SRayagond Kokatanur 		/* pass tstamp to stack */
388891434b1SRayagond Kokatanur 		skb_tstamp_tx(skb, &shhwtstamp);
389ba1ffd74SGiuseppe CAVALLARO 	}
390891434b1SRayagond Kokatanur 
391891434b1SRayagond Kokatanur 	return;
392891434b1SRayagond Kokatanur }
393891434b1SRayagond Kokatanur 
394732fdf0eSGiuseppe CAVALLARO /* stmmac_get_rx_hwtstamp - get HW RX timestamps
39532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
396ba1ffd74SGiuseppe CAVALLARO  * @p : descriptor pointer
397ba1ffd74SGiuseppe CAVALLARO  * @np : next descriptor pointer
398891434b1SRayagond Kokatanur  * @skb : the socket buffer
399891434b1SRayagond Kokatanur  * Description :
400891434b1SRayagond Kokatanur  * This function will read received packet's timestamp from the descriptor
401891434b1SRayagond Kokatanur  * and pass it to stack. It also perform some sanity checks.
402891434b1SRayagond Kokatanur  */
403ba1ffd74SGiuseppe CAVALLARO static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
404ba1ffd74SGiuseppe CAVALLARO 				   struct dma_desc *np, struct sk_buff *skb)
405891434b1SRayagond Kokatanur {
406891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps *shhwtstamp = NULL;
407891434b1SRayagond Kokatanur 	u64 ns;
408891434b1SRayagond Kokatanur 
409891434b1SRayagond Kokatanur 	if (!priv->hwts_rx_en)
410891434b1SRayagond Kokatanur 		return;
411891434b1SRayagond Kokatanur 
412ba1ffd74SGiuseppe CAVALLARO 	/* Check if timestamp is available */
413ba1ffd74SGiuseppe CAVALLARO 	if (!priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) {
414ba1ffd74SGiuseppe CAVALLARO 		/* For GMAC4, the valid timestamp is from CTX next desc. */
415ba1ffd74SGiuseppe CAVALLARO 		if (priv->plat->has_gmac4)
416ba1ffd74SGiuseppe CAVALLARO 			ns = priv->hw->desc->get_timestamp(np, priv->adv_ts);
417891434b1SRayagond Kokatanur 		else
418ba1ffd74SGiuseppe CAVALLARO 			ns = priv->hw->desc->get_timestamp(p, priv->adv_ts);
419891434b1SRayagond Kokatanur 
420ba1ffd74SGiuseppe CAVALLARO 		netdev_info(priv->dev, "get valid RX hw timestamp %llu\n", ns);
421891434b1SRayagond Kokatanur 		shhwtstamp = skb_hwtstamps(skb);
422891434b1SRayagond Kokatanur 		memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
423891434b1SRayagond Kokatanur 		shhwtstamp->hwtstamp = ns_to_ktime(ns);
424ba1ffd74SGiuseppe CAVALLARO 	} else  {
425ba1ffd74SGiuseppe CAVALLARO 		netdev_err(priv->dev, "cannot get RX hw timestamp\n");
426ba1ffd74SGiuseppe CAVALLARO 	}
427891434b1SRayagond Kokatanur }
428891434b1SRayagond Kokatanur 
429891434b1SRayagond Kokatanur /**
430891434b1SRayagond Kokatanur  *  stmmac_hwtstamp_ioctl - control hardware timestamping.
431891434b1SRayagond Kokatanur  *  @dev: device pointer.
4328d45e42bSLABBE Corentin  *  @ifr: An IOCTL specific structure, that can contain a pointer to
433891434b1SRayagond Kokatanur  *  a proprietary structure used to pass information to the driver.
434891434b1SRayagond Kokatanur  *  Description:
435891434b1SRayagond Kokatanur  *  This function configures the MAC to enable/disable both outgoing(TX)
436891434b1SRayagond Kokatanur  *  and incoming(RX) packets time stamping based on user input.
437891434b1SRayagond Kokatanur  *  Return Value:
438891434b1SRayagond Kokatanur  *  0 on success and an appropriate -ve integer on failure.
439891434b1SRayagond Kokatanur  */
440891434b1SRayagond Kokatanur static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
441891434b1SRayagond Kokatanur {
442891434b1SRayagond Kokatanur 	struct stmmac_priv *priv = netdev_priv(dev);
443891434b1SRayagond Kokatanur 	struct hwtstamp_config config;
4440a624155SArnd Bergmann 	struct timespec64 now;
445891434b1SRayagond Kokatanur 	u64 temp = 0;
446891434b1SRayagond Kokatanur 	u32 ptp_v2 = 0;
447891434b1SRayagond Kokatanur 	u32 tstamp_all = 0;
448891434b1SRayagond Kokatanur 	u32 ptp_over_ipv4_udp = 0;
449891434b1SRayagond Kokatanur 	u32 ptp_over_ipv6_udp = 0;
450891434b1SRayagond Kokatanur 	u32 ptp_over_ethernet = 0;
451891434b1SRayagond Kokatanur 	u32 snap_type_sel = 0;
452891434b1SRayagond Kokatanur 	u32 ts_master_en = 0;
453891434b1SRayagond Kokatanur 	u32 ts_event_en = 0;
454891434b1SRayagond Kokatanur 	u32 value = 0;
45519d857c9SPhil Reid 	u32 sec_inc;
456891434b1SRayagond Kokatanur 
457891434b1SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
458891434b1SRayagond Kokatanur 		netdev_alert(priv->dev, "No support for HW time stamping\n");
459891434b1SRayagond Kokatanur 		priv->hwts_tx_en = 0;
460891434b1SRayagond Kokatanur 		priv->hwts_rx_en = 0;
461891434b1SRayagond Kokatanur 
462891434b1SRayagond Kokatanur 		return -EOPNOTSUPP;
463891434b1SRayagond Kokatanur 	}
464891434b1SRayagond Kokatanur 
465891434b1SRayagond Kokatanur 	if (copy_from_user(&config, ifr->ifr_data,
466891434b1SRayagond Kokatanur 			   sizeof(struct hwtstamp_config)))
467891434b1SRayagond Kokatanur 		return -EFAULT;
468891434b1SRayagond Kokatanur 
46938ddc59dSLABBE Corentin 	netdev_dbg(priv->dev, "%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
470891434b1SRayagond Kokatanur 		   __func__, config.flags, config.tx_type, config.rx_filter);
471891434b1SRayagond Kokatanur 
472891434b1SRayagond Kokatanur 	/* reserved for future extensions */
473891434b1SRayagond Kokatanur 	if (config.flags)
474891434b1SRayagond Kokatanur 		return -EINVAL;
475891434b1SRayagond Kokatanur 
4765f3da328SBen Hutchings 	if (config.tx_type != HWTSTAMP_TX_OFF &&
4775f3da328SBen Hutchings 	    config.tx_type != HWTSTAMP_TX_ON)
478891434b1SRayagond Kokatanur 		return -ERANGE;
479891434b1SRayagond Kokatanur 
480891434b1SRayagond Kokatanur 	if (priv->adv_ts) {
481891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
482891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
483ceb69499SGiuseppe CAVALLARO 			/* time stamp no incoming packet at all */
484891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
485891434b1SRayagond Kokatanur 			break;
486891434b1SRayagond Kokatanur 
487891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
488ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, any kind of event packet */
489891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
490891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
491891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
492891434b1SRayagond Kokatanur 
493891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
494891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
495891434b1SRayagond Kokatanur 			break;
496891434b1SRayagond Kokatanur 
497891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
498ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Sync packet */
499891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
500891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
501891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
502891434b1SRayagond Kokatanur 
503891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
504891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
505891434b1SRayagond Kokatanur 			break;
506891434b1SRayagond Kokatanur 
507891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
508ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Delay_req packet */
509891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
510891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
511891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
512891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
513891434b1SRayagond Kokatanur 
514891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
515891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
516891434b1SRayagond Kokatanur 			break;
517891434b1SRayagond Kokatanur 
518891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
519ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, any kind of event packet */
520891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
521891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
522891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
523891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
524891434b1SRayagond Kokatanur 
525891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
526891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
527891434b1SRayagond Kokatanur 			break;
528891434b1SRayagond Kokatanur 
529891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
530ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Sync packet */
531891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
532891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
533891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
534891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
535891434b1SRayagond Kokatanur 
536891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
537891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
538891434b1SRayagond Kokatanur 			break;
539891434b1SRayagond Kokatanur 
540891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
541ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Delay_req packet */
542891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
543891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
544891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
545891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
546891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
547891434b1SRayagond Kokatanur 
548891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
549891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
550891434b1SRayagond Kokatanur 			break;
551891434b1SRayagond Kokatanur 
552891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_EVENT:
553ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1 any layer, any kind of event packet */
554891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
555891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
556891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
557891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
558891434b1SRayagond Kokatanur 
559891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
560891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
561891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
562891434b1SRayagond Kokatanur 			break;
563891434b1SRayagond Kokatanur 
564891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_SYNC:
565ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Sync packet */
566891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
567891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
568891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
569891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
570891434b1SRayagond Kokatanur 
571891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
572891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
573891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
574891434b1SRayagond Kokatanur 			break;
575891434b1SRayagond Kokatanur 
576891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
577ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Delay_req packet */
578891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
579891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
580891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
581891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
582891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
583891434b1SRayagond Kokatanur 
584891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
585891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
586891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
587891434b1SRayagond Kokatanur 			break;
588891434b1SRayagond Kokatanur 
589891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_ALL:
590ceb69499SGiuseppe CAVALLARO 			/* time stamp any incoming packet */
591891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_ALL;
592891434b1SRayagond Kokatanur 			tstamp_all = PTP_TCR_TSENALL;
593891434b1SRayagond Kokatanur 			break;
594891434b1SRayagond Kokatanur 
595891434b1SRayagond Kokatanur 		default:
596891434b1SRayagond Kokatanur 			return -ERANGE;
597891434b1SRayagond Kokatanur 		}
598891434b1SRayagond Kokatanur 	} else {
599891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
600891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
601891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
602891434b1SRayagond Kokatanur 			break;
603891434b1SRayagond Kokatanur 		default:
604891434b1SRayagond Kokatanur 			/* PTP v1, UDP, any kind of event packet */
605891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
606891434b1SRayagond Kokatanur 			break;
607891434b1SRayagond Kokatanur 		}
608891434b1SRayagond Kokatanur 	}
609891434b1SRayagond Kokatanur 	priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1);
6105f3da328SBen Hutchings 	priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON;
611891434b1SRayagond Kokatanur 
612891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en && !priv->hwts_rx_en)
613ba1ffd74SGiuseppe CAVALLARO 		priv->hw->ptp->config_hw_tstamping(priv->ptpaddr, 0);
614891434b1SRayagond Kokatanur 	else {
615891434b1SRayagond Kokatanur 		value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
616891434b1SRayagond Kokatanur 			 tstamp_all | ptp_v2 | ptp_over_ethernet |
617891434b1SRayagond Kokatanur 			 ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
618891434b1SRayagond Kokatanur 			 ts_master_en | snap_type_sel);
619ba1ffd74SGiuseppe CAVALLARO 		priv->hw->ptp->config_hw_tstamping(priv->ptpaddr, value);
620891434b1SRayagond Kokatanur 
621891434b1SRayagond Kokatanur 		/* program Sub Second Increment reg */
62219d857c9SPhil Reid 		sec_inc = priv->hw->ptp->config_sub_second_increment(
623f573c0b9Sjpinto 			priv->ptpaddr, priv->plat->clk_ptp_rate,
624ba1ffd74SGiuseppe CAVALLARO 			priv->plat->has_gmac4);
62519d857c9SPhil Reid 		temp = div_u64(1000000000ULL, sec_inc);
626891434b1SRayagond Kokatanur 
627891434b1SRayagond Kokatanur 		/* calculate default added value:
628891434b1SRayagond Kokatanur 		 * formula is :
629891434b1SRayagond Kokatanur 		 * addend = (2^32)/freq_div_ratio;
63019d857c9SPhil Reid 		 * where, freq_div_ratio = 1e9ns/sec_inc
631891434b1SRayagond Kokatanur 		 */
63219d857c9SPhil Reid 		temp = (u64)(temp << 32);
633f573c0b9Sjpinto 		priv->default_addend = div_u64(temp, priv->plat->clk_ptp_rate);
634ba1ffd74SGiuseppe CAVALLARO 		priv->hw->ptp->config_addend(priv->ptpaddr,
635891434b1SRayagond Kokatanur 					     priv->default_addend);
636891434b1SRayagond Kokatanur 
637891434b1SRayagond Kokatanur 		/* initialize system time */
6380a624155SArnd Bergmann 		ktime_get_real_ts64(&now);
6390a624155SArnd Bergmann 
6400a624155SArnd Bergmann 		/* lower 32 bits of tv_sec are safe until y2106 */
641ba1ffd74SGiuseppe CAVALLARO 		priv->hw->ptp->init_systime(priv->ptpaddr, (u32)now.tv_sec,
642891434b1SRayagond Kokatanur 					    now.tv_nsec);
643891434b1SRayagond Kokatanur 	}
644891434b1SRayagond Kokatanur 
645891434b1SRayagond Kokatanur 	return copy_to_user(ifr->ifr_data, &config,
646891434b1SRayagond Kokatanur 			    sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
647891434b1SRayagond Kokatanur }
648891434b1SRayagond Kokatanur 
64932ceabcaSGiuseppe CAVALLARO /**
650732fdf0eSGiuseppe CAVALLARO  * stmmac_init_ptp - init PTP
65132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
652732fdf0eSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PTPv1 or PTPv2.
65332ceabcaSGiuseppe CAVALLARO  * This is done by looking at the HW cap. register.
654732fdf0eSGiuseppe CAVALLARO  * This function also registers the ptp driver.
65532ceabcaSGiuseppe CAVALLARO  */
65692ba6888SRayagond Kokatanur static int stmmac_init_ptp(struct stmmac_priv *priv)
657891434b1SRayagond Kokatanur {
65892ba6888SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
65992ba6888SRayagond Kokatanur 		return -EOPNOTSUPP;
66092ba6888SRayagond Kokatanur 
661891434b1SRayagond Kokatanur 	priv->adv_ts = 0;
662be9b3174SGiuseppe CAVALLARO 	/* Check if adv_ts can be enabled for dwmac 4.x core */
663be9b3174SGiuseppe CAVALLARO 	if (priv->plat->has_gmac4 && priv->dma_cap.atime_stamp)
664be9b3174SGiuseppe CAVALLARO 		priv->adv_ts = 1;
665be9b3174SGiuseppe CAVALLARO 	/* Dwmac 3.x core with extend_desc can support adv_ts */
666be9b3174SGiuseppe CAVALLARO 	else if (priv->extend_desc && priv->dma_cap.atime_stamp)
667891434b1SRayagond Kokatanur 		priv->adv_ts = 1;
6687cd01399SVince Bridgers 
669be9b3174SGiuseppe CAVALLARO 	if (priv->dma_cap.time_stamp)
670be9b3174SGiuseppe CAVALLARO 		netdev_info(priv->dev, "IEEE 1588-2002 Timestamp supported\n");
6717cd01399SVince Bridgers 
672be9b3174SGiuseppe CAVALLARO 	if (priv->adv_ts)
673be9b3174SGiuseppe CAVALLARO 		netdev_info(priv->dev,
674be9b3174SGiuseppe CAVALLARO 			    "IEEE 1588-2008 Advanced Timestamp supported\n");
675891434b1SRayagond Kokatanur 
676891434b1SRayagond Kokatanur 	priv->hw->ptp = &stmmac_ptp;
677891434b1SRayagond Kokatanur 	priv->hwts_tx_en = 0;
678891434b1SRayagond Kokatanur 	priv->hwts_rx_en = 0;
67992ba6888SRayagond Kokatanur 
680c30a70d3SGiuseppe CAVALLARO 	stmmac_ptp_register(priv);
681c30a70d3SGiuseppe CAVALLARO 
682c30a70d3SGiuseppe CAVALLARO 	return 0;
68392ba6888SRayagond Kokatanur }
68492ba6888SRayagond Kokatanur 
68592ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv)
68692ba6888SRayagond Kokatanur {
687f573c0b9Sjpinto 	if (priv->plat->clk_ptp_ref)
688f573c0b9Sjpinto 		clk_disable_unprepare(priv->plat->clk_ptp_ref);
68992ba6888SRayagond Kokatanur 	stmmac_ptp_unregister(priv);
690891434b1SRayagond Kokatanur }
691891434b1SRayagond Kokatanur 
6927ac6653aSJeff Kirsher /**
69329feff39SJoao Pinto  *  stmmac_mac_flow_ctrl - Configure flow control in all queues
69429feff39SJoao Pinto  *  @priv: driver private structure
69529feff39SJoao Pinto  *  Description: It is used for configuring the flow control in all queues
69629feff39SJoao Pinto  */
69729feff39SJoao Pinto static void stmmac_mac_flow_ctrl(struct stmmac_priv *priv, u32 duplex)
69829feff39SJoao Pinto {
69929feff39SJoao Pinto 	u32 tx_cnt = priv->plat->tx_queues_to_use;
70029feff39SJoao Pinto 
70129feff39SJoao Pinto 	priv->hw->mac->flow_ctrl(priv->hw, duplex, priv->flow_ctrl,
70229feff39SJoao Pinto 				 priv->pause, tx_cnt);
70329feff39SJoao Pinto }
70429feff39SJoao Pinto 
70529feff39SJoao Pinto /**
706732fdf0eSGiuseppe CAVALLARO  * stmmac_adjust_link - adjusts the link parameters
7077ac6653aSJeff Kirsher  * @dev: net device structure
708732fdf0eSGiuseppe CAVALLARO  * Description: this is the helper called by the physical abstraction layer
709732fdf0eSGiuseppe CAVALLARO  * drivers to communicate the phy link status. According the speed and duplex
710732fdf0eSGiuseppe CAVALLARO  * this driver can invoke registered glue-logic as well.
711732fdf0eSGiuseppe CAVALLARO  * It also invoke the eee initialization because it could happen when switch
712732fdf0eSGiuseppe CAVALLARO  * on different networks (that are eee capable).
7137ac6653aSJeff Kirsher  */
7147ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev)
7157ac6653aSJeff Kirsher {
7167ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
717d6d50c7eSPhilippe Reynes 	struct phy_device *phydev = dev->phydev;
7187ac6653aSJeff Kirsher 	unsigned long flags;
7197ac6653aSJeff Kirsher 	int new_state = 0;
7207ac6653aSJeff Kirsher 
721662ec2b7SLABBE Corentin 	if (!phydev)
7227ac6653aSJeff Kirsher 		return;
7237ac6653aSJeff Kirsher 
7247ac6653aSJeff Kirsher 	spin_lock_irqsave(&priv->lock, flags);
725d765955dSGiuseppe CAVALLARO 
7267ac6653aSJeff Kirsher 	if (phydev->link) {
7277ac6653aSJeff Kirsher 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
7287ac6653aSJeff Kirsher 
7297ac6653aSJeff Kirsher 		/* Now we make sure that we can be in full duplex mode.
7307ac6653aSJeff Kirsher 		 * If not, we operate in half-duplex mode. */
7317ac6653aSJeff Kirsher 		if (phydev->duplex != priv->oldduplex) {
7327ac6653aSJeff Kirsher 			new_state = 1;
7337ac6653aSJeff Kirsher 			if (!(phydev->duplex))
7347ac6653aSJeff Kirsher 				ctrl &= ~priv->hw->link.duplex;
7357ac6653aSJeff Kirsher 			else
7367ac6653aSJeff Kirsher 				ctrl |= priv->hw->link.duplex;
7377ac6653aSJeff Kirsher 			priv->oldduplex = phydev->duplex;
7387ac6653aSJeff Kirsher 		}
7397ac6653aSJeff Kirsher 		/* Flow Control operation */
7407ac6653aSJeff Kirsher 		if (phydev->pause)
74129feff39SJoao Pinto 			stmmac_mac_flow_ctrl(priv, phydev->duplex);
7427ac6653aSJeff Kirsher 
7437ac6653aSJeff Kirsher 		if (phydev->speed != priv->speed) {
7447ac6653aSJeff Kirsher 			new_state = 1;
7457ac6653aSJeff Kirsher 			switch (phydev->speed) {
7467ac6653aSJeff Kirsher 			case 1000:
7473e12790eSLABBE Corentin 				if (priv->plat->has_gmac ||
7483e12790eSLABBE Corentin 				    priv->plat->has_gmac4)
7497ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7507ac6653aSJeff Kirsher 				break;
7517ac6653aSJeff Kirsher 			case 100:
7529beae261SLABBE Corentin 				if (priv->plat->has_gmac ||
7539beae261SLABBE Corentin 				    priv->plat->has_gmac4) {
7549beae261SLABBE Corentin 					ctrl |= priv->hw->link.port;
7559beae261SLABBE Corentin 					ctrl |= priv->hw->link.speed;
7569beae261SLABBE Corentin 				} else {
7579beae261SLABBE Corentin 					ctrl &= ~priv->hw->link.port;
7589beae261SLABBE Corentin 				}
7599beae261SLABBE Corentin 				break;
7607ac6653aSJeff Kirsher 			case 10:
7613e12790eSLABBE Corentin 				if (priv->plat->has_gmac ||
7623e12790eSLABBE Corentin 				    priv->plat->has_gmac4) {
7637ac6653aSJeff Kirsher 					ctrl |= priv->hw->link.port;
7647ac6653aSJeff Kirsher 					ctrl &= ~(priv->hw->link.speed);
7657ac6653aSJeff Kirsher 				} else {
7667ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7677ac6653aSJeff Kirsher 				}
7687ac6653aSJeff Kirsher 				break;
7697ac6653aSJeff Kirsher 			default:
770b3e51069SLABBE Corentin 				netif_warn(priv, link, priv->dev,
771cba920afSLABBE Corentin 					   "broken speed: %d\n", phydev->speed);
772688495b1SLABBE Corentin 				phydev->speed = SPEED_UNKNOWN;
7737ac6653aSJeff Kirsher 				break;
7747ac6653aSJeff Kirsher 			}
7755db13556SLABBE Corentin 			if (phydev->speed != SPEED_UNKNOWN)
7765db13556SLABBE Corentin 				stmmac_hw_fix_mac_speed(priv);
7777ac6653aSJeff Kirsher 			priv->speed = phydev->speed;
7787ac6653aSJeff Kirsher 		}
7797ac6653aSJeff Kirsher 
7807ac6653aSJeff Kirsher 		writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
7817ac6653aSJeff Kirsher 
7827ac6653aSJeff Kirsher 		if (!priv->oldlink) {
7837ac6653aSJeff Kirsher 			new_state = 1;
7847ac6653aSJeff Kirsher 			priv->oldlink = 1;
7857ac6653aSJeff Kirsher 		}
7867ac6653aSJeff Kirsher 	} else if (priv->oldlink) {
7877ac6653aSJeff Kirsher 		new_state = 1;
7887ac6653aSJeff Kirsher 		priv->oldlink = 0;
789bd00632cSLABBE Corentin 		priv->speed = SPEED_UNKNOWN;
790bd00632cSLABBE Corentin 		priv->oldduplex = DUPLEX_UNKNOWN;
7917ac6653aSJeff Kirsher 	}
7927ac6653aSJeff Kirsher 
7937ac6653aSJeff Kirsher 	if (new_state && netif_msg_link(priv))
7947ac6653aSJeff Kirsher 		phy_print_status(phydev);
7957ac6653aSJeff Kirsher 
7964741cf9cSGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
7974741cf9cSGiuseppe CAVALLARO 
79852f95bbfSGiuseppe CAVALLARO 	if (phydev->is_pseudo_fixed_link)
79952f95bbfSGiuseppe CAVALLARO 		/* Stop PHY layer to call the hook to adjust the link in case
80052f95bbfSGiuseppe CAVALLARO 		 * of a switch is attached to the stmmac driver.
80152f95bbfSGiuseppe CAVALLARO 		 */
80252f95bbfSGiuseppe CAVALLARO 		phydev->irq = PHY_IGNORE_INTERRUPT;
80352f95bbfSGiuseppe CAVALLARO 	else
80452f95bbfSGiuseppe CAVALLARO 		/* At this stage, init the EEE if supported.
80552f95bbfSGiuseppe CAVALLARO 		 * Never called in case of fixed_link.
806f5351ef7SGiuseppe CAVALLARO 		 */
807f5351ef7SGiuseppe CAVALLARO 		priv->eee_enabled = stmmac_eee_init(priv);
8087ac6653aSJeff Kirsher }
8097ac6653aSJeff Kirsher 
81032ceabcaSGiuseppe CAVALLARO /**
811732fdf0eSGiuseppe CAVALLARO  * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported
81232ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
81332ceabcaSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PCS.
81432ceabcaSGiuseppe CAVALLARO  * Physical Coding Sublayer (PCS) interface that can be used when the MAC is
81532ceabcaSGiuseppe CAVALLARO  * configured for the TBI, RTBI, or SGMII PHY interface.
81632ceabcaSGiuseppe CAVALLARO  */
817e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
818e58bb43fSGiuseppe CAVALLARO {
819e58bb43fSGiuseppe CAVALLARO 	int interface = priv->plat->interface;
820e58bb43fSGiuseppe CAVALLARO 
821e58bb43fSGiuseppe CAVALLARO 	if (priv->dma_cap.pcs) {
8220d909dcdSByungho An 		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
8230d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
8240d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
8250d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
82638ddc59dSLABBE Corentin 			netdev_dbg(priv->dev, "PCS RGMII support enabled\n");
8273fe5cadbSGiuseppe CAVALLARO 			priv->hw->pcs = STMMAC_PCS_RGMII;
8280d909dcdSByungho An 		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
82938ddc59dSLABBE Corentin 			netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
8303fe5cadbSGiuseppe CAVALLARO 			priv->hw->pcs = STMMAC_PCS_SGMII;
831e58bb43fSGiuseppe CAVALLARO 		}
832e58bb43fSGiuseppe CAVALLARO 	}
833e58bb43fSGiuseppe CAVALLARO }
834e58bb43fSGiuseppe CAVALLARO 
8357ac6653aSJeff Kirsher /**
8367ac6653aSJeff Kirsher  * stmmac_init_phy - PHY initialization
8377ac6653aSJeff Kirsher  * @dev: net device structure
8387ac6653aSJeff Kirsher  * Description: it initializes the driver's PHY state, and attaches the PHY
8397ac6653aSJeff Kirsher  * to the mac driver.
8407ac6653aSJeff Kirsher  *  Return value:
8417ac6653aSJeff Kirsher  *  0 on success
8427ac6653aSJeff Kirsher  */
8437ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev)
8447ac6653aSJeff Kirsher {
8457ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
8467ac6653aSJeff Kirsher 	struct phy_device *phydev;
847d765955dSGiuseppe CAVALLARO 	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
8487ac6653aSJeff Kirsher 	char bus_id[MII_BUS_ID_SIZE];
84979ee1dc3SSrinivas Kandagatla 	int interface = priv->plat->interface;
8509cbadf09SSrinivas Kandagatla 	int max_speed = priv->plat->max_speed;
8517ac6653aSJeff Kirsher 	priv->oldlink = 0;
852bd00632cSLABBE Corentin 	priv->speed = SPEED_UNKNOWN;
853bd00632cSLABBE Corentin 	priv->oldduplex = DUPLEX_UNKNOWN;
8547ac6653aSJeff Kirsher 
8555790cf3cSMathieu Olivari 	if (priv->plat->phy_node) {
8565790cf3cSMathieu Olivari 		phydev = of_phy_connect(dev, priv->plat->phy_node,
8575790cf3cSMathieu Olivari 					&stmmac_adjust_link, 0, interface);
8585790cf3cSMathieu Olivari 	} else {
859f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
860f142af2eSSrinivas Kandagatla 			 priv->plat->bus_id);
861f142af2eSSrinivas Kandagatla 
862d765955dSGiuseppe CAVALLARO 		snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
8637ac6653aSJeff Kirsher 			 priv->plat->phy_addr);
864de9a2165SLABBE Corentin 		netdev_dbg(priv->dev, "%s: trying to attach to %s\n", __func__,
8655790cf3cSMathieu Olivari 			   phy_id_fmt);
8667ac6653aSJeff Kirsher 
8675790cf3cSMathieu Olivari 		phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link,
8685790cf3cSMathieu Olivari 				     interface);
8695790cf3cSMathieu Olivari 	}
8707ac6653aSJeff Kirsher 
871dfc50fcaSAlexey Brodkin 	if (IS_ERR_OR_NULL(phydev)) {
87238ddc59dSLABBE Corentin 		netdev_err(priv->dev, "Could not attach to PHY\n");
873dfc50fcaSAlexey Brodkin 		if (!phydev)
874dfc50fcaSAlexey Brodkin 			return -ENODEV;
875dfc50fcaSAlexey Brodkin 
8767ac6653aSJeff Kirsher 		return PTR_ERR(phydev);
8777ac6653aSJeff Kirsher 	}
8787ac6653aSJeff Kirsher 
87979ee1dc3SSrinivas Kandagatla 	/* Stop Advertising 1000BASE Capability if interface is not GMII */
880c5b9b4e4SSrinivas Kandagatla 	if ((interface == PHY_INTERFACE_MODE_MII) ||
8819cbadf09SSrinivas Kandagatla 	    (interface == PHY_INTERFACE_MODE_RMII) ||
8829cbadf09SSrinivas Kandagatla 		(max_speed < 1000 && max_speed > 0))
883c5b9b4e4SSrinivas Kandagatla 		phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
884c5b9b4e4SSrinivas Kandagatla 					 SUPPORTED_1000baseT_Full);
88579ee1dc3SSrinivas Kandagatla 
8867ac6653aSJeff Kirsher 	/*
8877ac6653aSJeff Kirsher 	 * Broken HW is sometimes missing the pull-up resistor on the
8887ac6653aSJeff Kirsher 	 * MDIO line, which results in reads to non-existent devices returning
8897ac6653aSJeff Kirsher 	 * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
8907ac6653aSJeff Kirsher 	 * device as well.
8917ac6653aSJeff Kirsher 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
8927ac6653aSJeff Kirsher 	 */
89327732381SMathieu Olivari 	if (!priv->plat->phy_node && phydev->phy_id == 0) {
8947ac6653aSJeff Kirsher 		phy_disconnect(phydev);
8957ac6653aSJeff Kirsher 		return -ENODEV;
8967ac6653aSJeff Kirsher 	}
8978e99fc5fSGiuseppe Cavallaro 
898c51e424dSFlorian Fainelli 	/* stmmac_adjust_link will change this to PHY_IGNORE_INTERRUPT to avoid
899c51e424dSFlorian Fainelli 	 * subsequent PHY polling, make sure we force a link transition if
900c51e424dSFlorian Fainelli 	 * we have a UP/DOWN/UP transition
901c51e424dSFlorian Fainelli 	 */
902c51e424dSFlorian Fainelli 	if (phydev->is_pseudo_fixed_link)
903c51e424dSFlorian Fainelli 		phydev->irq = PHY_POLL;
904c51e424dSFlorian Fainelli 
905b05c76a1SLABBE Corentin 	phy_attached_info(phydev);
9067ac6653aSJeff Kirsher 	return 0;
9077ac6653aSJeff Kirsher }
9087ac6653aSJeff Kirsher 
90971fedb01SJoao Pinto static void stmmac_display_rx_rings(struct stmmac_priv *priv)
910c24602efSGiuseppe CAVALLARO {
91154139cf3SJoao Pinto 	u32 rx_cnt = priv->plat->rx_queues_to_use;
91271fedb01SJoao Pinto 	void *head_rx;
91354139cf3SJoao Pinto 	u32 queue;
91454139cf3SJoao Pinto 
91554139cf3SJoao Pinto 	/* Display RX rings */
91654139cf3SJoao Pinto 	for (queue = 0; queue < rx_cnt; queue++) {
91754139cf3SJoao Pinto 		struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
91854139cf3SJoao Pinto 
91954139cf3SJoao Pinto 		pr_info("\tRX Queue %u rings\n", queue);
920d0225e7dSAlexandre TORGUE 
92171fedb01SJoao Pinto 		if (priv->extend_desc)
92254139cf3SJoao Pinto 			head_rx = (void *)rx_q->dma_erx;
92371fedb01SJoao Pinto 		else
92454139cf3SJoao Pinto 			head_rx = (void *)rx_q->dma_rx;
92571fedb01SJoao Pinto 
92671fedb01SJoao Pinto 		/* Display RX ring */
92771fedb01SJoao Pinto 		priv->hw->desc->display_ring(head_rx, DMA_RX_SIZE, true);
9285bacd778SLABBE Corentin 	}
92954139cf3SJoao Pinto }
930d0225e7dSAlexandre TORGUE 
93171fedb01SJoao Pinto static void stmmac_display_tx_rings(struct stmmac_priv *priv)
93271fedb01SJoao Pinto {
933ce736788SJoao Pinto 	u32 tx_cnt = priv->plat->tx_queues_to_use;
93471fedb01SJoao Pinto 	void *head_tx;
935ce736788SJoao Pinto 	u32 queue;
936ce736788SJoao Pinto 
937ce736788SJoao Pinto 	/* Display TX rings */
938ce736788SJoao Pinto 	for (queue = 0; queue < tx_cnt; queue++) {
939ce736788SJoao Pinto 		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
940ce736788SJoao Pinto 
941ce736788SJoao Pinto 		pr_info("\tTX Queue %d rings\n", queue);
94271fedb01SJoao Pinto 
94371fedb01SJoao Pinto 		if (priv->extend_desc)
944ce736788SJoao Pinto 			head_tx = (void *)tx_q->dma_etx;
94571fedb01SJoao Pinto 		else
946ce736788SJoao Pinto 			head_tx = (void *)tx_q->dma_tx;
94771fedb01SJoao Pinto 
948d0225e7dSAlexandre TORGUE 		priv->hw->desc->display_ring(head_tx, DMA_TX_SIZE, false);
949c24602efSGiuseppe CAVALLARO 	}
950ce736788SJoao Pinto }
951c24602efSGiuseppe CAVALLARO 
95271fedb01SJoao Pinto static void stmmac_display_rings(struct stmmac_priv *priv)
95371fedb01SJoao Pinto {
95471fedb01SJoao Pinto 	/* Display RX ring */
95571fedb01SJoao Pinto 	stmmac_display_rx_rings(priv);
95671fedb01SJoao Pinto 
95771fedb01SJoao Pinto 	/* Display TX ring */
95871fedb01SJoao Pinto 	stmmac_display_tx_rings(priv);
95971fedb01SJoao Pinto }
96071fedb01SJoao Pinto 
961286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize)
962286a8372SGiuseppe CAVALLARO {
963286a8372SGiuseppe CAVALLARO 	int ret = bufsize;
964286a8372SGiuseppe CAVALLARO 
965286a8372SGiuseppe CAVALLARO 	if (mtu >= BUF_SIZE_4KiB)
966286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_8KiB;
967286a8372SGiuseppe CAVALLARO 	else if (mtu >= BUF_SIZE_2KiB)
968286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_4KiB;
969d916701cSGiuseppe CAVALLARO 	else if (mtu > DEFAULT_BUFSIZE)
970286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_2KiB;
971286a8372SGiuseppe CAVALLARO 	else
972d916701cSGiuseppe CAVALLARO 		ret = DEFAULT_BUFSIZE;
973286a8372SGiuseppe CAVALLARO 
974286a8372SGiuseppe CAVALLARO 	return ret;
975286a8372SGiuseppe CAVALLARO }
976286a8372SGiuseppe CAVALLARO 
97732ceabcaSGiuseppe CAVALLARO /**
97871fedb01SJoao Pinto  * stmmac_clear_rx_descriptors - clear RX descriptors
97932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
98054139cf3SJoao Pinto  * @queue: RX queue index
98171fedb01SJoao Pinto  * Description: this function is called to clear the RX descriptors
98232ceabcaSGiuseppe CAVALLARO  * in case of both basic and extended descriptors are used.
98332ceabcaSGiuseppe CAVALLARO  */
98454139cf3SJoao Pinto static void stmmac_clear_rx_descriptors(struct stmmac_priv *priv, u32 queue)
985c24602efSGiuseppe CAVALLARO {
98654139cf3SJoao Pinto 	struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
9875bacd778SLABBE Corentin 	int i;
988c24602efSGiuseppe CAVALLARO 
98971fedb01SJoao Pinto 	/* Clear the RX descriptors */
9905bacd778SLABBE Corentin 	for (i = 0; i < DMA_RX_SIZE; i++)
9915bacd778SLABBE Corentin 		if (priv->extend_desc)
99254139cf3SJoao Pinto 			priv->hw->desc->init_rx_desc(&rx_q->dma_erx[i].basic,
9935bacd778SLABBE Corentin 						     priv->use_riwt, priv->mode,
9945bacd778SLABBE Corentin 						     (i == DMA_RX_SIZE - 1));
9955bacd778SLABBE Corentin 		else
99654139cf3SJoao Pinto 			priv->hw->desc->init_rx_desc(&rx_q->dma_rx[i],
9975bacd778SLABBE Corentin 						     priv->use_riwt, priv->mode,
9985bacd778SLABBE Corentin 						     (i == DMA_RX_SIZE - 1));
99971fedb01SJoao Pinto }
100071fedb01SJoao Pinto 
100171fedb01SJoao Pinto /**
100271fedb01SJoao Pinto  * stmmac_clear_tx_descriptors - clear tx descriptors
100371fedb01SJoao Pinto  * @priv: driver private structure
1004ce736788SJoao Pinto  * @queue: TX queue index.
100571fedb01SJoao Pinto  * Description: this function is called to clear the TX descriptors
100671fedb01SJoao Pinto  * in case of both basic and extended descriptors are used.
100771fedb01SJoao Pinto  */
1008ce736788SJoao Pinto static void stmmac_clear_tx_descriptors(struct stmmac_priv *priv, u32 queue)
100971fedb01SJoao Pinto {
1010ce736788SJoao Pinto 	struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
101171fedb01SJoao Pinto 	int i;
101271fedb01SJoao Pinto 
101371fedb01SJoao Pinto 	/* Clear the TX descriptors */
10145bacd778SLABBE Corentin 	for (i = 0; i < DMA_TX_SIZE; i++)
10155bacd778SLABBE Corentin 		if (priv->extend_desc)
1016ce736788SJoao Pinto 			priv->hw->desc->init_tx_desc(&tx_q->dma_etx[i].basic,
10175bacd778SLABBE Corentin 						     priv->mode,
10185bacd778SLABBE Corentin 						     (i == DMA_TX_SIZE - 1));
10195bacd778SLABBE Corentin 		else
1020ce736788SJoao Pinto 			priv->hw->desc->init_tx_desc(&tx_q->dma_tx[i],
10215bacd778SLABBE Corentin 						     priv->mode,
10225bacd778SLABBE Corentin 						     (i == DMA_TX_SIZE - 1));
1023c24602efSGiuseppe CAVALLARO }
1024c24602efSGiuseppe CAVALLARO 
1025732fdf0eSGiuseppe CAVALLARO /**
102671fedb01SJoao Pinto  * stmmac_clear_descriptors - clear descriptors
102771fedb01SJoao Pinto  * @priv: driver private structure
102871fedb01SJoao Pinto  * Description: this function is called to clear the TX and RX descriptors
102971fedb01SJoao Pinto  * in case of both basic and extended descriptors are used.
103071fedb01SJoao Pinto  */
103171fedb01SJoao Pinto static void stmmac_clear_descriptors(struct stmmac_priv *priv)
103271fedb01SJoao Pinto {
103354139cf3SJoao Pinto 	u32 rx_queue_cnt = priv->plat->rx_queues_to_use;
1034ce736788SJoao Pinto 	u32 tx_queue_cnt = priv->plat->tx_queues_to_use;
103554139cf3SJoao Pinto 	u32 queue;
103654139cf3SJoao Pinto 
103771fedb01SJoao Pinto 	/* Clear the RX descriptors */
103854139cf3SJoao Pinto 	for (queue = 0; queue < rx_queue_cnt; queue++)
103954139cf3SJoao Pinto 		stmmac_clear_rx_descriptors(priv, queue);
104071fedb01SJoao Pinto 
104171fedb01SJoao Pinto 	/* Clear the TX descriptors */
1042ce736788SJoao Pinto 	for (queue = 0; queue < tx_queue_cnt; queue++)
1043ce736788SJoao Pinto 		stmmac_clear_tx_descriptors(priv, queue);
104471fedb01SJoao Pinto }
104571fedb01SJoao Pinto 
104671fedb01SJoao Pinto /**
1047732fdf0eSGiuseppe CAVALLARO  * stmmac_init_rx_buffers - init the RX descriptor buffer.
1048732fdf0eSGiuseppe CAVALLARO  * @priv: driver private structure
1049732fdf0eSGiuseppe CAVALLARO  * @p: descriptor pointer
1050732fdf0eSGiuseppe CAVALLARO  * @i: descriptor index
105154139cf3SJoao Pinto  * @flags: gfp flag
105254139cf3SJoao Pinto  * @queue: RX queue index
1053732fdf0eSGiuseppe CAVALLARO  * Description: this function is called to allocate a receive buffer, perform
1054732fdf0eSGiuseppe CAVALLARO  * the DMA mapping and init the descriptor.
1055732fdf0eSGiuseppe CAVALLARO  */
1056c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
105754139cf3SJoao Pinto 				  int i, gfp_t flags, u32 queue)
1058c24602efSGiuseppe CAVALLARO {
105954139cf3SJoao Pinto 	struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
1060c24602efSGiuseppe CAVALLARO 	struct sk_buff *skb;
1061c24602efSGiuseppe CAVALLARO 
10624ec49a37SVineet Gupta 	skb = __netdev_alloc_skb_ip_align(priv->dev, priv->dma_buf_sz, flags);
106356329137SBartlomiej Zolnierkiewicz 	if (!skb) {
106438ddc59dSLABBE Corentin 		netdev_err(priv->dev,
106538ddc59dSLABBE Corentin 			   "%s: Rx init fails; skb is NULL\n", __func__);
106656329137SBartlomiej Zolnierkiewicz 		return -ENOMEM;
1067c24602efSGiuseppe CAVALLARO 	}
106854139cf3SJoao Pinto 	rx_q->rx_skbuff[i] = skb;
106954139cf3SJoao Pinto 	rx_q->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
1070c24602efSGiuseppe CAVALLARO 						priv->dma_buf_sz,
1071c24602efSGiuseppe CAVALLARO 						DMA_FROM_DEVICE);
107254139cf3SJoao Pinto 	if (dma_mapping_error(priv->device, rx_q->rx_skbuff_dma[i])) {
107338ddc59dSLABBE Corentin 		netdev_err(priv->dev, "%s: DMA mapping error\n", __func__);
107456329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(skb);
107556329137SBartlomiej Zolnierkiewicz 		return -EINVAL;
107656329137SBartlomiej Zolnierkiewicz 	}
1077c24602efSGiuseppe CAVALLARO 
1078f748be53SAlexandre TORGUE 	if (priv->synopsys_id >= DWMAC_CORE_4_00)
107954139cf3SJoao Pinto 		p->des0 = cpu_to_le32(rx_q->rx_skbuff_dma[i]);
1080f748be53SAlexandre TORGUE 	else
108154139cf3SJoao Pinto 		p->des2 = cpu_to_le32(rx_q->rx_skbuff_dma[i]);
1082c24602efSGiuseppe CAVALLARO 
108329896a67SGiuseppe CAVALLARO 	if ((priv->hw->mode->init_desc3) &&
1084c24602efSGiuseppe CAVALLARO 	    (priv->dma_buf_sz == BUF_SIZE_16KiB))
108529896a67SGiuseppe CAVALLARO 		priv->hw->mode->init_desc3(p);
1086c24602efSGiuseppe CAVALLARO 
1087c24602efSGiuseppe CAVALLARO 	return 0;
1088c24602efSGiuseppe CAVALLARO }
1089c24602efSGiuseppe CAVALLARO 
109071fedb01SJoao Pinto /**
109171fedb01SJoao Pinto  * stmmac_free_rx_buffer - free RX dma buffers
109271fedb01SJoao Pinto  * @priv: private structure
109354139cf3SJoao Pinto  * @queue: RX queue index
109471fedb01SJoao Pinto  * @i: buffer index.
109571fedb01SJoao Pinto  */
109654139cf3SJoao Pinto static void stmmac_free_rx_buffer(struct stmmac_priv *priv, u32 queue, int i)
109756329137SBartlomiej Zolnierkiewicz {
109854139cf3SJoao Pinto 	struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
109954139cf3SJoao Pinto 
110054139cf3SJoao Pinto 	if (rx_q->rx_skbuff[i]) {
110154139cf3SJoao Pinto 		dma_unmap_single(priv->device, rx_q->rx_skbuff_dma[i],
110256329137SBartlomiej Zolnierkiewicz 				 priv->dma_buf_sz, DMA_FROM_DEVICE);
110354139cf3SJoao Pinto 		dev_kfree_skb_any(rx_q->rx_skbuff[i]);
110456329137SBartlomiej Zolnierkiewicz 	}
110554139cf3SJoao Pinto 	rx_q->rx_skbuff[i] = NULL;
110656329137SBartlomiej Zolnierkiewicz }
110756329137SBartlomiej Zolnierkiewicz 
11087ac6653aSJeff Kirsher /**
110971fedb01SJoao Pinto  * stmmac_free_tx_buffer - free RX dma buffers
111071fedb01SJoao Pinto  * @priv: private structure
1111ce736788SJoao Pinto  * @queue: RX queue index
111271fedb01SJoao Pinto  * @i: buffer index.
111371fedb01SJoao Pinto  */
1114ce736788SJoao Pinto static void stmmac_free_tx_buffer(struct stmmac_priv *priv, u32 queue, int i)
111571fedb01SJoao Pinto {
1116ce736788SJoao Pinto 	struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
1117ce736788SJoao Pinto 
1118ce736788SJoao Pinto 	if (tx_q->tx_skbuff_dma[i].buf) {
1119ce736788SJoao Pinto 		if (tx_q->tx_skbuff_dma[i].map_as_page)
112071fedb01SJoao Pinto 			dma_unmap_page(priv->device,
1121ce736788SJoao Pinto 				       tx_q->tx_skbuff_dma[i].buf,
1122ce736788SJoao Pinto 				       tx_q->tx_skbuff_dma[i].len,
112371fedb01SJoao Pinto 				       DMA_TO_DEVICE);
112471fedb01SJoao Pinto 		else
112571fedb01SJoao Pinto 			dma_unmap_single(priv->device,
1126ce736788SJoao Pinto 					 tx_q->tx_skbuff_dma[i].buf,
1127ce736788SJoao Pinto 					 tx_q->tx_skbuff_dma[i].len,
112871fedb01SJoao Pinto 					 DMA_TO_DEVICE);
112971fedb01SJoao Pinto 	}
113071fedb01SJoao Pinto 
1131ce736788SJoao Pinto 	if (tx_q->tx_skbuff[i]) {
1132ce736788SJoao Pinto 		dev_kfree_skb_any(tx_q->tx_skbuff[i]);
1133ce736788SJoao Pinto 		tx_q->tx_skbuff[i] = NULL;
1134ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[i].buf = 0;
1135ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[i].map_as_page = false;
113671fedb01SJoao Pinto 	}
113771fedb01SJoao Pinto }
113871fedb01SJoao Pinto 
113971fedb01SJoao Pinto /**
114071fedb01SJoao Pinto  * init_dma_rx_desc_rings - init the RX descriptor rings
11417ac6653aSJeff Kirsher  * @dev: net device structure
11425bacd778SLABBE Corentin  * @flags: gfp flag.
114371fedb01SJoao Pinto  * Description: this function initializes the DMA RX descriptors
11445bacd778SLABBE Corentin  * and allocates the socket buffers. It supports the chained and ring
1145286a8372SGiuseppe CAVALLARO  * modes.
11467ac6653aSJeff Kirsher  */
114771fedb01SJoao Pinto static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
11487ac6653aSJeff Kirsher {
11497ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
115054139cf3SJoao Pinto 	u32 rx_count = priv->plat->rx_queues_to_use;
11515bacd778SLABBE Corentin 	unsigned int bfsize = 0;
11525bacd778SLABBE Corentin 	int ret = -ENOMEM;
115354139cf3SJoao Pinto 	u32 queue;
115454139cf3SJoao Pinto 	int i;
11557ac6653aSJeff Kirsher 
11565bacd778SLABBE Corentin 	if (priv->hw->mode->set_16kib_bfsize)
11575bacd778SLABBE Corentin 		bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu);
11585bacd778SLABBE Corentin 
11595bacd778SLABBE Corentin 	if (bfsize < BUF_SIZE_16KiB)
11605bacd778SLABBE Corentin 		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
11615bacd778SLABBE Corentin 
11625bacd778SLABBE Corentin 	priv->dma_buf_sz = bfsize;
11632618abb7SVince Bridgers 
116454139cf3SJoao Pinto 	/* RX INITIALIZATION */
11655bacd778SLABBE Corentin 	netif_dbg(priv, probe, priv->dev,
11665bacd778SLABBE Corentin 		  "SKB addresses:\nskb\t\tskb data\tdma data\n");
11675bacd778SLABBE Corentin 
116854139cf3SJoao Pinto 	for (queue = 0; queue < rx_count; queue++) {
116954139cf3SJoao Pinto 		struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
117054139cf3SJoao Pinto 
117154139cf3SJoao Pinto 		netif_dbg(priv, probe, priv->dev,
117254139cf3SJoao Pinto 			  "(%s) dma_rx_phy=0x%08x\n", __func__,
117354139cf3SJoao Pinto 			  (u32)rx_q->dma_rx_phy);
117454139cf3SJoao Pinto 
11755bacd778SLABBE Corentin 		for (i = 0; i < DMA_RX_SIZE; i++) {
11765bacd778SLABBE Corentin 			struct dma_desc *p;
11775bacd778SLABBE Corentin 
117854139cf3SJoao Pinto 			if (priv->extend_desc)
117954139cf3SJoao Pinto 				p = &((rx_q->dma_erx + i)->basic);
118054139cf3SJoao Pinto 			else
118154139cf3SJoao Pinto 				p = rx_q->dma_rx + i;
118254139cf3SJoao Pinto 
118354139cf3SJoao Pinto 			ret = stmmac_init_rx_buffers(priv, p, i, flags,
118454139cf3SJoao Pinto 						     queue);
11855bacd778SLABBE Corentin 			if (ret)
11865bacd778SLABBE Corentin 				goto err_init_rx_buffers;
11875bacd778SLABBE Corentin 
11885bacd778SLABBE Corentin 			netif_dbg(priv, probe, priv->dev, "[%p]\t[%p]\t[%x]\n",
118954139cf3SJoao Pinto 				  rx_q->rx_skbuff[i], rx_q->rx_skbuff[i]->data,
119054139cf3SJoao Pinto 				  (unsigned int)rx_q->rx_skbuff_dma[i]);
11915bacd778SLABBE Corentin 		}
119254139cf3SJoao Pinto 
119354139cf3SJoao Pinto 		rx_q->cur_rx = 0;
119454139cf3SJoao Pinto 		rx_q->dirty_rx = (unsigned int)(i - DMA_RX_SIZE);
119554139cf3SJoao Pinto 
119654139cf3SJoao Pinto 		stmmac_clear_rx_descriptors(priv, queue);
11977ac6653aSJeff Kirsher 
1198c24602efSGiuseppe CAVALLARO 		/* Setup the chained descriptor addresses */
1199c24602efSGiuseppe CAVALLARO 		if (priv->mode == STMMAC_CHAIN_MODE) {
120071fedb01SJoao Pinto 			if (priv->extend_desc)
120154139cf3SJoao Pinto 				priv->hw->mode->init(rx_q->dma_erx,
120254139cf3SJoao Pinto 						     rx_q->dma_rx_phy,
12035bacd778SLABBE Corentin 						     DMA_RX_SIZE, 1);
120471fedb01SJoao Pinto 			else
120554139cf3SJoao Pinto 				priv->hw->mode->init(rx_q->dma_rx,
120654139cf3SJoao Pinto 						     rx_q->dma_rx_phy,
12075bacd778SLABBE Corentin 						     DMA_RX_SIZE, 0);
120871fedb01SJoao Pinto 		}
120954139cf3SJoao Pinto 	}
121054139cf3SJoao Pinto 
121154139cf3SJoao Pinto 	buf_sz = bfsize;
121271fedb01SJoao Pinto 
121371fedb01SJoao Pinto 	return 0;
121454139cf3SJoao Pinto 
121571fedb01SJoao Pinto err_init_rx_buffers:
121654139cf3SJoao Pinto 	while (queue >= 0) {
121771fedb01SJoao Pinto 		while (--i >= 0)
121854139cf3SJoao Pinto 			stmmac_free_rx_buffer(priv, queue, i);
121954139cf3SJoao Pinto 
122054139cf3SJoao Pinto 		if (queue == 0)
122154139cf3SJoao Pinto 			break;
122254139cf3SJoao Pinto 
122354139cf3SJoao Pinto 		i = DMA_RX_SIZE;
122454139cf3SJoao Pinto 		queue--;
122554139cf3SJoao Pinto 	}
122654139cf3SJoao Pinto 
122771fedb01SJoao Pinto 	return ret;
122871fedb01SJoao Pinto }
122971fedb01SJoao Pinto 
123071fedb01SJoao Pinto /**
123171fedb01SJoao Pinto  * init_dma_tx_desc_rings - init the TX descriptor rings
123271fedb01SJoao Pinto  * @dev: net device structure.
123371fedb01SJoao Pinto  * Description: this function initializes the DMA TX descriptors
123471fedb01SJoao Pinto  * and allocates the socket buffers. It supports the chained and ring
123571fedb01SJoao Pinto  * modes.
123671fedb01SJoao Pinto  */
123771fedb01SJoao Pinto static int init_dma_tx_desc_rings(struct net_device *dev)
123871fedb01SJoao Pinto {
123971fedb01SJoao Pinto 	struct stmmac_priv *priv = netdev_priv(dev);
1240ce736788SJoao Pinto 	u32 tx_queue_cnt = priv->plat->tx_queues_to_use;
1241ce736788SJoao Pinto 	u32 queue;
124271fedb01SJoao Pinto 	int i;
124371fedb01SJoao Pinto 
1244ce736788SJoao Pinto 	for (queue = 0; queue < tx_queue_cnt; queue++) {
1245ce736788SJoao Pinto 		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
1246ce736788SJoao Pinto 
124771fedb01SJoao Pinto 		netif_dbg(priv, probe, priv->dev,
1248ce736788SJoao Pinto 			  "(%s) dma_tx_phy=0x%08x\n", __func__,
1249ce736788SJoao Pinto 			 (u32)tx_q->dma_tx_phy);
125071fedb01SJoao Pinto 
125171fedb01SJoao Pinto 		/* Setup the chained descriptor addresses */
125271fedb01SJoao Pinto 		if (priv->mode == STMMAC_CHAIN_MODE) {
125371fedb01SJoao Pinto 			if (priv->extend_desc)
1254ce736788SJoao Pinto 				priv->hw->mode->init(tx_q->dma_etx,
1255ce736788SJoao Pinto 						     tx_q->dma_tx_phy,
125671fedb01SJoao Pinto 						     DMA_TX_SIZE, 1);
125771fedb01SJoao Pinto 			else
1258ce736788SJoao Pinto 				priv->hw->mode->init(tx_q->dma_tx,
1259ce736788SJoao Pinto 						     tx_q->dma_tx_phy,
1260e3ad57c9SGiuseppe Cavallaro 						     DMA_TX_SIZE, 0);
1261c24602efSGiuseppe CAVALLARO 		}
1262286a8372SGiuseppe CAVALLARO 
1263e3ad57c9SGiuseppe Cavallaro 		for (i = 0; i < DMA_TX_SIZE; i++) {
1264c24602efSGiuseppe CAVALLARO 			struct dma_desc *p;
1265ce736788SJoao Pinto 
1266c24602efSGiuseppe CAVALLARO 			if (priv->extend_desc)
1267ce736788SJoao Pinto 				p = &((tx_q->dma_etx + i)->basic);
1268c24602efSGiuseppe CAVALLARO 			else
1269ce736788SJoao Pinto 				p = tx_q->dma_tx + i;
1270f748be53SAlexandre TORGUE 
1271f748be53SAlexandre TORGUE 			if (priv->synopsys_id >= DWMAC_CORE_4_00) {
1272f748be53SAlexandre TORGUE 				p->des0 = 0;
1273f748be53SAlexandre TORGUE 				p->des1 = 0;
1274c24602efSGiuseppe CAVALLARO 				p->des2 = 0;
1275f748be53SAlexandre TORGUE 				p->des3 = 0;
1276f748be53SAlexandre TORGUE 			} else {
1277f748be53SAlexandre TORGUE 				p->des2 = 0;
1278f748be53SAlexandre TORGUE 			}
1279f748be53SAlexandre TORGUE 
1280ce736788SJoao Pinto 			tx_q->tx_skbuff_dma[i].buf = 0;
1281ce736788SJoao Pinto 			tx_q->tx_skbuff_dma[i].map_as_page = false;
1282ce736788SJoao Pinto 			tx_q->tx_skbuff_dma[i].len = 0;
1283ce736788SJoao Pinto 			tx_q->tx_skbuff_dma[i].last_segment = false;
1284ce736788SJoao Pinto 			tx_q->tx_skbuff[i] = NULL;
12854a7d666aSGiuseppe CAVALLARO 		}
1286c24602efSGiuseppe CAVALLARO 
1287ce736788SJoao Pinto 		tx_q->dirty_tx = 0;
1288ce736788SJoao Pinto 		tx_q->cur_tx = 0;
1289ce736788SJoao Pinto 	}
1290ce736788SJoao Pinto 
12915bacd778SLABBE Corentin 	netdev_reset_queue(priv->dev);
12927ac6653aSJeff Kirsher 
129371fedb01SJoao Pinto 	return 0;
129471fedb01SJoao Pinto }
129571fedb01SJoao Pinto 
129671fedb01SJoao Pinto /**
129771fedb01SJoao Pinto  * init_dma_desc_rings - init the RX/TX descriptor rings
129871fedb01SJoao Pinto  * @dev: net device structure
129971fedb01SJoao Pinto  * @flags: gfp flag.
130071fedb01SJoao Pinto  * Description: this function initializes the DMA RX/TX descriptors
130171fedb01SJoao Pinto  * and allocates the socket buffers. It supports the chained and ring
130271fedb01SJoao Pinto  * modes.
130371fedb01SJoao Pinto  */
130471fedb01SJoao Pinto static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)
130571fedb01SJoao Pinto {
130671fedb01SJoao Pinto 	struct stmmac_priv *priv = netdev_priv(dev);
130771fedb01SJoao Pinto 	int ret;
130871fedb01SJoao Pinto 
130971fedb01SJoao Pinto 	ret = init_dma_rx_desc_rings(dev, flags);
131071fedb01SJoao Pinto 	if (ret)
131171fedb01SJoao Pinto 		return ret;
131271fedb01SJoao Pinto 
131371fedb01SJoao Pinto 	ret = init_dma_tx_desc_rings(dev);
131471fedb01SJoao Pinto 
13155bacd778SLABBE Corentin 	stmmac_clear_descriptors(priv);
13167ac6653aSJeff Kirsher 
1317c24602efSGiuseppe CAVALLARO 	if (netif_msg_hw(priv))
1318c24602efSGiuseppe CAVALLARO 		stmmac_display_rings(priv);
131956329137SBartlomiej Zolnierkiewicz 
132056329137SBartlomiej Zolnierkiewicz 	return ret;
13217ac6653aSJeff Kirsher }
13227ac6653aSJeff Kirsher 
132371fedb01SJoao Pinto /**
132471fedb01SJoao Pinto  * dma_free_rx_skbufs - free RX dma buffers
132571fedb01SJoao Pinto  * @priv: private structure
132654139cf3SJoao Pinto  * @queue: RX queue index
132771fedb01SJoao Pinto  */
132854139cf3SJoao Pinto static void dma_free_rx_skbufs(struct stmmac_priv *priv, u32 queue)
13297ac6653aSJeff Kirsher {
13307ac6653aSJeff Kirsher 	int i;
13317ac6653aSJeff Kirsher 
1332e3ad57c9SGiuseppe Cavallaro 	for (i = 0; i < DMA_RX_SIZE; i++)
133354139cf3SJoao Pinto 		stmmac_free_rx_buffer(priv, queue, i);
13347ac6653aSJeff Kirsher }
13357ac6653aSJeff Kirsher 
133671fedb01SJoao Pinto /**
133771fedb01SJoao Pinto  * dma_free_tx_skbufs - free TX dma buffers
133871fedb01SJoao Pinto  * @priv: private structure
1339ce736788SJoao Pinto  * @queue: TX queue index
134071fedb01SJoao Pinto  */
1341ce736788SJoao Pinto static void dma_free_tx_skbufs(struct stmmac_priv *priv, u32 queue)
13427ac6653aSJeff Kirsher {
13437ac6653aSJeff Kirsher 	int i;
13447ac6653aSJeff Kirsher 
134571fedb01SJoao Pinto 	for (i = 0; i < DMA_TX_SIZE; i++)
1346ce736788SJoao Pinto 		stmmac_free_tx_buffer(priv, queue, i);
13477ac6653aSJeff Kirsher }
13487ac6653aSJeff Kirsher 
1349732fdf0eSGiuseppe CAVALLARO /**
135054139cf3SJoao Pinto  * free_dma_rx_desc_resources - free RX dma desc resources
135154139cf3SJoao Pinto  * @priv: private structure
135254139cf3SJoao Pinto  */
135354139cf3SJoao Pinto static void free_dma_rx_desc_resources(struct stmmac_priv *priv)
135454139cf3SJoao Pinto {
135554139cf3SJoao Pinto 	u32 rx_count = priv->plat->rx_queues_to_use;
135654139cf3SJoao Pinto 	u32 queue;
135754139cf3SJoao Pinto 
135854139cf3SJoao Pinto 	/* Free RX queue resources */
135954139cf3SJoao Pinto 	for (queue = 0; queue < rx_count; queue++) {
136054139cf3SJoao Pinto 		struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
136154139cf3SJoao Pinto 
136254139cf3SJoao Pinto 		/* Release the DMA RX socket buffers */
136354139cf3SJoao Pinto 		dma_free_rx_skbufs(priv, queue);
136454139cf3SJoao Pinto 
136554139cf3SJoao Pinto 		/* Free DMA regions of consistent memory previously allocated */
136654139cf3SJoao Pinto 		if (!priv->extend_desc)
136754139cf3SJoao Pinto 			dma_free_coherent(priv->device,
136854139cf3SJoao Pinto 					  DMA_RX_SIZE * sizeof(struct dma_desc),
136954139cf3SJoao Pinto 					  rx_q->dma_rx, rx_q->dma_rx_phy);
137054139cf3SJoao Pinto 		else
137154139cf3SJoao Pinto 			dma_free_coherent(priv->device, DMA_RX_SIZE *
137254139cf3SJoao Pinto 					  sizeof(struct dma_extended_desc),
137354139cf3SJoao Pinto 					  rx_q->dma_erx, rx_q->dma_rx_phy);
137454139cf3SJoao Pinto 
137554139cf3SJoao Pinto 		kfree(rx_q->rx_skbuff_dma);
137654139cf3SJoao Pinto 		kfree(rx_q->rx_skbuff);
137754139cf3SJoao Pinto 	}
137854139cf3SJoao Pinto }
137954139cf3SJoao Pinto 
138054139cf3SJoao Pinto /**
1381ce736788SJoao Pinto  * free_dma_tx_desc_resources - free TX dma desc resources
1382ce736788SJoao Pinto  * @priv: private structure
1383ce736788SJoao Pinto  */
1384ce736788SJoao Pinto static void free_dma_tx_desc_resources(struct stmmac_priv *priv)
1385ce736788SJoao Pinto {
1386ce736788SJoao Pinto 	u32 tx_count = priv->plat->tx_queues_to_use;
1387ce736788SJoao Pinto 	u32 queue = 0;
1388ce736788SJoao Pinto 
1389ce736788SJoao Pinto 	/* Free TX queue resources */
1390ce736788SJoao Pinto 	for (queue = 0; queue < tx_count; queue++) {
1391ce736788SJoao Pinto 		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
1392ce736788SJoao Pinto 
1393ce736788SJoao Pinto 		/* Release the DMA TX socket buffers */
1394ce736788SJoao Pinto 		dma_free_tx_skbufs(priv, queue);
1395ce736788SJoao Pinto 
1396ce736788SJoao Pinto 		/* Free DMA regions of consistent memory previously allocated */
1397ce736788SJoao Pinto 		if (!priv->extend_desc)
1398ce736788SJoao Pinto 			dma_free_coherent(priv->device,
1399ce736788SJoao Pinto 					  DMA_TX_SIZE * sizeof(struct dma_desc),
1400ce736788SJoao Pinto 					  tx_q->dma_tx, tx_q->dma_tx_phy);
1401ce736788SJoao Pinto 		else
1402ce736788SJoao Pinto 			dma_free_coherent(priv->device, DMA_TX_SIZE *
1403ce736788SJoao Pinto 					  sizeof(struct dma_extended_desc),
1404ce736788SJoao Pinto 					  tx_q->dma_etx, tx_q->dma_tx_phy);
1405ce736788SJoao Pinto 
1406ce736788SJoao Pinto 		kfree(tx_q->tx_skbuff_dma);
1407ce736788SJoao Pinto 		kfree(tx_q->tx_skbuff);
1408ce736788SJoao Pinto 	}
1409ce736788SJoao Pinto }
1410ce736788SJoao Pinto 
1411ce736788SJoao Pinto /**
141271fedb01SJoao Pinto  * alloc_dma_rx_desc_resources - alloc RX resources.
1413732fdf0eSGiuseppe CAVALLARO  * @priv: private structure
1414732fdf0eSGiuseppe CAVALLARO  * Description: according to which descriptor can be used (extend or basic)
1415732fdf0eSGiuseppe CAVALLARO  * this function allocates the resources for TX and RX paths. In case of
1416732fdf0eSGiuseppe CAVALLARO  * reception, for example, it pre-allocated the RX socket buffer in order to
1417732fdf0eSGiuseppe CAVALLARO  * allow zero-copy mechanism.
1418732fdf0eSGiuseppe CAVALLARO  */
141971fedb01SJoao Pinto static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
142009f8d696SSrinivas Kandagatla {
142154139cf3SJoao Pinto 	u32 rx_count = priv->plat->rx_queues_to_use;
14225bacd778SLABBE Corentin 	int ret = -ENOMEM;
142354139cf3SJoao Pinto 	u32 queue;
142409f8d696SSrinivas Kandagatla 
142554139cf3SJoao Pinto 	/* RX queues buffers and DMA */
142654139cf3SJoao Pinto 	for (queue = 0; queue < rx_count; queue++) {
142754139cf3SJoao Pinto 		struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
142854139cf3SJoao Pinto 
142954139cf3SJoao Pinto 		rx_q->queue_index = queue;
143054139cf3SJoao Pinto 		rx_q->priv_data = priv;
143154139cf3SJoao Pinto 
143254139cf3SJoao Pinto 		rx_q->rx_skbuff_dma = kmalloc_array(DMA_RX_SIZE,
143354139cf3SJoao Pinto 						    sizeof(dma_addr_t),
14345bacd778SLABBE Corentin 						    GFP_KERNEL);
143554139cf3SJoao Pinto 		if (!rx_q->rx_skbuff_dma)
14365bacd778SLABBE Corentin 			return -ENOMEM;
14375bacd778SLABBE Corentin 
143854139cf3SJoao Pinto 		rx_q->rx_skbuff = kmalloc_array(DMA_RX_SIZE,
143954139cf3SJoao Pinto 						sizeof(struct sk_buff *),
14405bacd778SLABBE Corentin 						GFP_KERNEL);
144154139cf3SJoao Pinto 		if (!rx_q->rx_skbuff)
144254139cf3SJoao Pinto 			goto err_dma;
14435bacd778SLABBE Corentin 
14445bacd778SLABBE Corentin 		if (priv->extend_desc) {
144554139cf3SJoao Pinto 			rx_q->dma_erx = dma_zalloc_coherent(priv->device,
144654139cf3SJoao Pinto 							    DMA_RX_SIZE *
14475bacd778SLABBE Corentin 							    sizeof(struct
14485bacd778SLABBE Corentin 							    dma_extended_desc),
144954139cf3SJoao Pinto 							    &rx_q->dma_rx_phy,
14505bacd778SLABBE Corentin 							    GFP_KERNEL);
145154139cf3SJoao Pinto 			if (!rx_q->dma_erx)
14525bacd778SLABBE Corentin 				goto err_dma;
14535bacd778SLABBE Corentin 
145471fedb01SJoao Pinto 		} else {
145554139cf3SJoao Pinto 			rx_q->dma_rx = dma_zalloc_coherent(priv->device,
145654139cf3SJoao Pinto 							   DMA_RX_SIZE *
145754139cf3SJoao Pinto 							   sizeof(struct
145854139cf3SJoao Pinto 							   dma_desc),
145954139cf3SJoao Pinto 							   &rx_q->dma_rx_phy,
146071fedb01SJoao Pinto 							   GFP_KERNEL);
146154139cf3SJoao Pinto 			if (!rx_q->dma_rx)
146271fedb01SJoao Pinto 				goto err_dma;
146371fedb01SJoao Pinto 		}
146454139cf3SJoao Pinto 	}
146571fedb01SJoao Pinto 
146671fedb01SJoao Pinto 	return 0;
146771fedb01SJoao Pinto 
146871fedb01SJoao Pinto err_dma:
146954139cf3SJoao Pinto 	free_dma_rx_desc_resources(priv);
147054139cf3SJoao Pinto 
147171fedb01SJoao Pinto 	return ret;
147271fedb01SJoao Pinto }
147371fedb01SJoao Pinto 
147471fedb01SJoao Pinto /**
147571fedb01SJoao Pinto  * alloc_dma_tx_desc_resources - alloc TX resources.
147671fedb01SJoao Pinto  * @priv: private structure
147771fedb01SJoao Pinto  * Description: according to which descriptor can be used (extend or basic)
147871fedb01SJoao Pinto  * this function allocates the resources for TX and RX paths. In case of
147971fedb01SJoao Pinto  * reception, for example, it pre-allocated the RX socket buffer in order to
148071fedb01SJoao Pinto  * allow zero-copy mechanism.
148171fedb01SJoao Pinto  */
148271fedb01SJoao Pinto static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv)
148371fedb01SJoao Pinto {
1484ce736788SJoao Pinto 	u32 tx_count = priv->plat->tx_queues_to_use;
148571fedb01SJoao Pinto 	int ret = -ENOMEM;
1486ce736788SJoao Pinto 	u32 queue;
148771fedb01SJoao Pinto 
1488ce736788SJoao Pinto 	/* TX queues buffers and DMA */
1489ce736788SJoao Pinto 	for (queue = 0; queue < tx_count; queue++) {
1490ce736788SJoao Pinto 		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
1491ce736788SJoao Pinto 
1492ce736788SJoao Pinto 		tx_q->queue_index = queue;
1493ce736788SJoao Pinto 		tx_q->priv_data = priv;
1494ce736788SJoao Pinto 
1495ce736788SJoao Pinto 		tx_q->tx_skbuff_dma = kmalloc_array(DMA_TX_SIZE,
1496ce736788SJoao Pinto 						    sizeof(*tx_q->tx_skbuff_dma),
149771fedb01SJoao Pinto 						    GFP_KERNEL);
1498ce736788SJoao Pinto 		if (!tx_q->tx_skbuff_dma)
149971fedb01SJoao Pinto 			return -ENOMEM;
150071fedb01SJoao Pinto 
1501ce736788SJoao Pinto 		tx_q->tx_skbuff = kmalloc_array(DMA_TX_SIZE,
1502ce736788SJoao Pinto 						sizeof(struct sk_buff *),
150371fedb01SJoao Pinto 						GFP_KERNEL);
1504ce736788SJoao Pinto 		if (!tx_q->tx_skbuff)
1505ce736788SJoao Pinto 			goto err_dma_buffers;
150671fedb01SJoao Pinto 
150771fedb01SJoao Pinto 		if (priv->extend_desc) {
1508ce736788SJoao Pinto 			tx_q->dma_etx = dma_zalloc_coherent(priv->device,
1509ce736788SJoao Pinto 							    DMA_TX_SIZE *
15105bacd778SLABBE Corentin 							    sizeof(struct
15115bacd778SLABBE Corentin 							    dma_extended_desc),
1512ce736788SJoao Pinto 							    &tx_q->dma_tx_phy,
15135bacd778SLABBE Corentin 							    GFP_KERNEL);
1514ce736788SJoao Pinto 			if (!tx_q->dma_etx)
1515ce736788SJoao Pinto 				goto err_dma_buffers;
15165bacd778SLABBE Corentin 		} else {
1517ce736788SJoao Pinto 			tx_q->dma_tx = dma_zalloc_coherent(priv->device,
1518ce736788SJoao Pinto 							   DMA_TX_SIZE *
1519ce736788SJoao Pinto 							   sizeof(struct
1520ce736788SJoao Pinto 								  dma_desc),
1521ce736788SJoao Pinto 							   &tx_q->dma_tx_phy,
15225bacd778SLABBE Corentin 							   GFP_KERNEL);
1523ce736788SJoao Pinto 			if (!tx_q->dma_tx)
1524ce736788SJoao Pinto 				goto err_dma_buffers;
1525ce736788SJoao Pinto 		}
15265bacd778SLABBE Corentin 	}
15275bacd778SLABBE Corentin 
15285bacd778SLABBE Corentin 	return 0;
15295bacd778SLABBE Corentin 
1530ce736788SJoao Pinto err_dma_buffers:
1531ce736788SJoao Pinto 	free_dma_tx_desc_resources(priv);
1532ce736788SJoao Pinto 
153309f8d696SSrinivas Kandagatla 	return ret;
15345bacd778SLABBE Corentin }
153509f8d696SSrinivas Kandagatla 
153671fedb01SJoao Pinto /**
153771fedb01SJoao Pinto  * alloc_dma_desc_resources - alloc TX/RX resources.
153871fedb01SJoao Pinto  * @priv: private structure
153971fedb01SJoao Pinto  * Description: according to which descriptor can be used (extend or basic)
154071fedb01SJoao Pinto  * this function allocates the resources for TX and RX paths. In case of
154171fedb01SJoao Pinto  * reception, for example, it pre-allocated the RX socket buffer in order to
154271fedb01SJoao Pinto  * allow zero-copy mechanism.
154371fedb01SJoao Pinto  */
154471fedb01SJoao Pinto static int alloc_dma_desc_resources(struct stmmac_priv *priv)
15455bacd778SLABBE Corentin {
154654139cf3SJoao Pinto 	/* RX Allocation */
154771fedb01SJoao Pinto 	int ret = alloc_dma_rx_desc_resources(priv);
154871fedb01SJoao Pinto 
154971fedb01SJoao Pinto 	if (ret)
155071fedb01SJoao Pinto 		return ret;
155171fedb01SJoao Pinto 
155271fedb01SJoao Pinto 	ret = alloc_dma_tx_desc_resources(priv);
155371fedb01SJoao Pinto 
155471fedb01SJoao Pinto 	return ret;
155571fedb01SJoao Pinto }
155671fedb01SJoao Pinto 
155771fedb01SJoao Pinto /**
155871fedb01SJoao Pinto  * free_dma_desc_resources - free dma desc resources
155971fedb01SJoao Pinto  * @priv: private structure
156071fedb01SJoao Pinto  */
156171fedb01SJoao Pinto static void free_dma_desc_resources(struct stmmac_priv *priv)
156271fedb01SJoao Pinto {
156371fedb01SJoao Pinto 	/* Release the DMA RX socket buffers */
156471fedb01SJoao Pinto 	free_dma_rx_desc_resources(priv);
156571fedb01SJoao Pinto 
156671fedb01SJoao Pinto 	/* Release the DMA TX socket buffers */
156771fedb01SJoao Pinto 	free_dma_tx_desc_resources(priv);
156871fedb01SJoao Pinto }
156971fedb01SJoao Pinto 
157071fedb01SJoao Pinto /**
15719eb12474Sjpinto  *  stmmac_mac_enable_rx_queues - Enable MAC rx queues
15729eb12474Sjpinto  *  @priv: driver private structure
15739eb12474Sjpinto  *  Description: It is used for enabling the rx queues in the MAC
15749eb12474Sjpinto  */
15759eb12474Sjpinto static void stmmac_mac_enable_rx_queues(struct stmmac_priv *priv)
15769eb12474Sjpinto {
15774f6046f5SJoao Pinto 	u32 rx_queues_count = priv->plat->rx_queues_to_use;
15784f6046f5SJoao Pinto 	int queue;
15794f6046f5SJoao Pinto 	u8 mode;
15809eb12474Sjpinto 
15814f6046f5SJoao Pinto 	for (queue = 0; queue < rx_queues_count; queue++) {
15824f6046f5SJoao Pinto 		mode = priv->plat->rx_queues_cfg[queue].mode_to_use;
15834f6046f5SJoao Pinto 		priv->hw->mac->rx_queue_enable(priv->hw, mode, queue);
15844f6046f5SJoao Pinto 	}
15859eb12474Sjpinto }
15869eb12474Sjpinto 
15879eb12474Sjpinto /**
1588ae4f0d46SJoao Pinto  * stmmac_start_rx_dma - start RX DMA channel
1589ae4f0d46SJoao Pinto  * @priv: driver private structure
1590ae4f0d46SJoao Pinto  * @chan: RX channel index
1591ae4f0d46SJoao Pinto  * Description:
1592ae4f0d46SJoao Pinto  * This starts a RX DMA channel
1593ae4f0d46SJoao Pinto  */
1594ae4f0d46SJoao Pinto static void stmmac_start_rx_dma(struct stmmac_priv *priv, u32 chan)
1595ae4f0d46SJoao Pinto {
1596ae4f0d46SJoao Pinto 	netdev_dbg(priv->dev, "DMA RX processes started in channel %d\n", chan);
1597ae4f0d46SJoao Pinto 	priv->hw->dma->start_rx(priv->ioaddr, chan);
1598ae4f0d46SJoao Pinto }
1599ae4f0d46SJoao Pinto 
1600ae4f0d46SJoao Pinto /**
1601ae4f0d46SJoao Pinto  * stmmac_start_tx_dma - start TX DMA channel
1602ae4f0d46SJoao Pinto  * @priv: driver private structure
1603ae4f0d46SJoao Pinto  * @chan: TX channel index
1604ae4f0d46SJoao Pinto  * Description:
1605ae4f0d46SJoao Pinto  * This starts a TX DMA channel
1606ae4f0d46SJoao Pinto  */
1607ae4f0d46SJoao Pinto static void stmmac_start_tx_dma(struct stmmac_priv *priv, u32 chan)
1608ae4f0d46SJoao Pinto {
1609ae4f0d46SJoao Pinto 	netdev_dbg(priv->dev, "DMA TX processes started in channel %d\n", chan);
1610ae4f0d46SJoao Pinto 	priv->hw->dma->start_tx(priv->ioaddr, chan);
1611ae4f0d46SJoao Pinto }
1612ae4f0d46SJoao Pinto 
1613ae4f0d46SJoao Pinto /**
1614ae4f0d46SJoao Pinto  * stmmac_stop_rx_dma - stop RX DMA channel
1615ae4f0d46SJoao Pinto  * @priv: driver private structure
1616ae4f0d46SJoao Pinto  * @chan: RX channel index
1617ae4f0d46SJoao Pinto  * Description:
1618ae4f0d46SJoao Pinto  * This stops a RX DMA channel
1619ae4f0d46SJoao Pinto  */
1620ae4f0d46SJoao Pinto static void stmmac_stop_rx_dma(struct stmmac_priv *priv, u32 chan)
1621ae4f0d46SJoao Pinto {
1622ae4f0d46SJoao Pinto 	netdev_dbg(priv->dev, "DMA RX processes stopped in channel %d\n", chan);
1623ae4f0d46SJoao Pinto 	priv->hw->dma->stop_rx(priv->ioaddr, chan);
1624ae4f0d46SJoao Pinto }
1625ae4f0d46SJoao Pinto 
1626ae4f0d46SJoao Pinto /**
1627ae4f0d46SJoao Pinto  * stmmac_stop_tx_dma - stop TX DMA channel
1628ae4f0d46SJoao Pinto  * @priv: driver private structure
1629ae4f0d46SJoao Pinto  * @chan: TX channel index
1630ae4f0d46SJoao Pinto  * Description:
1631ae4f0d46SJoao Pinto  * This stops a TX DMA channel
1632ae4f0d46SJoao Pinto  */
1633ae4f0d46SJoao Pinto static void stmmac_stop_tx_dma(struct stmmac_priv *priv, u32 chan)
1634ae4f0d46SJoao Pinto {
1635ae4f0d46SJoao Pinto 	netdev_dbg(priv->dev, "DMA TX processes stopped in channel %d\n", chan);
1636ae4f0d46SJoao Pinto 	priv->hw->dma->stop_tx(priv->ioaddr, chan);
1637ae4f0d46SJoao Pinto }
1638ae4f0d46SJoao Pinto 
1639ae4f0d46SJoao Pinto /**
1640ae4f0d46SJoao Pinto  * stmmac_start_all_dma - start all RX and TX DMA channels
1641ae4f0d46SJoao Pinto  * @priv: driver private structure
1642ae4f0d46SJoao Pinto  * Description:
1643ae4f0d46SJoao Pinto  * This starts all the RX and TX DMA channels
1644ae4f0d46SJoao Pinto  */
1645ae4f0d46SJoao Pinto static void stmmac_start_all_dma(struct stmmac_priv *priv)
1646ae4f0d46SJoao Pinto {
1647ae4f0d46SJoao Pinto 	u32 rx_channels_count = priv->plat->rx_queues_to_use;
1648ae4f0d46SJoao Pinto 	u32 tx_channels_count = priv->plat->tx_queues_to_use;
1649ae4f0d46SJoao Pinto 	u32 chan = 0;
1650ae4f0d46SJoao Pinto 
1651ae4f0d46SJoao Pinto 	for (chan = 0; chan < rx_channels_count; chan++)
1652ae4f0d46SJoao Pinto 		stmmac_start_rx_dma(priv, chan);
1653ae4f0d46SJoao Pinto 
1654ae4f0d46SJoao Pinto 	for (chan = 0; chan < tx_channels_count; chan++)
1655ae4f0d46SJoao Pinto 		stmmac_start_tx_dma(priv, chan);
1656ae4f0d46SJoao Pinto }
1657ae4f0d46SJoao Pinto 
1658ae4f0d46SJoao Pinto /**
1659ae4f0d46SJoao Pinto  * stmmac_stop_all_dma - stop all RX and TX DMA channels
1660ae4f0d46SJoao Pinto  * @priv: driver private structure
1661ae4f0d46SJoao Pinto  * Description:
1662ae4f0d46SJoao Pinto  * This stops the RX and TX DMA channels
1663ae4f0d46SJoao Pinto  */
1664ae4f0d46SJoao Pinto static void stmmac_stop_all_dma(struct stmmac_priv *priv)
1665ae4f0d46SJoao Pinto {
1666ae4f0d46SJoao Pinto 	u32 rx_channels_count = priv->plat->rx_queues_to_use;
1667ae4f0d46SJoao Pinto 	u32 tx_channels_count = priv->plat->tx_queues_to_use;
1668ae4f0d46SJoao Pinto 	u32 chan = 0;
1669ae4f0d46SJoao Pinto 
1670ae4f0d46SJoao Pinto 	for (chan = 0; chan < rx_channels_count; chan++)
1671ae4f0d46SJoao Pinto 		stmmac_stop_rx_dma(priv, chan);
1672ae4f0d46SJoao Pinto 
1673ae4f0d46SJoao Pinto 	for (chan = 0; chan < tx_channels_count; chan++)
1674ae4f0d46SJoao Pinto 		stmmac_stop_tx_dma(priv, chan);
1675ae4f0d46SJoao Pinto }
1676ae4f0d46SJoao Pinto 
1677ae4f0d46SJoao Pinto /**
16787ac6653aSJeff Kirsher  *  stmmac_dma_operation_mode - HW DMA operation mode
167932ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
1680732fdf0eSGiuseppe CAVALLARO  *  Description: it is used for configuring the DMA operation mode register in
1681732fdf0eSGiuseppe CAVALLARO  *  order to program the tx/rx DMA thresholds or Store-And-Forward mode.
16827ac6653aSJeff Kirsher  */
16837ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
16847ac6653aSJeff Kirsher {
16856deee222SJoao Pinto 	u32 rx_channels_count = priv->plat->rx_queues_to_use;
16866deee222SJoao Pinto 	u32 tx_channels_count = priv->plat->tx_queues_to_use;
1687f88203a2SVince Bridgers 	int rxfifosz = priv->plat->rx_fifo_size;
16886deee222SJoao Pinto 	u32 txmode = 0;
16896deee222SJoao Pinto 	u32 rxmode = 0;
16906deee222SJoao Pinto 	u32 chan = 0;
1691f88203a2SVince Bridgers 
169211fbf811SThierry Reding 	if (rxfifosz == 0)
169311fbf811SThierry Reding 		rxfifosz = priv->dma_cap.rx_fifo_size;
169411fbf811SThierry Reding 
16956deee222SJoao Pinto 	if (priv->plat->force_thresh_dma_mode) {
16966deee222SJoao Pinto 		txmode = tc;
16976deee222SJoao Pinto 		rxmode = tc;
16986deee222SJoao Pinto 	} else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
16997ac6653aSJeff Kirsher 		/*
17007ac6653aSJeff Kirsher 		 * In case of GMAC, SF mode can be enabled
17017ac6653aSJeff Kirsher 		 * to perform the TX COE in HW. This depends on:
17027ac6653aSJeff Kirsher 		 * 1) TX COE if actually supported
17037ac6653aSJeff Kirsher 		 * 2) There is no bugged Jumbo frame support
17047ac6653aSJeff Kirsher 		 *    that needs to not insert csum in the TDES.
17057ac6653aSJeff Kirsher 		 */
17066deee222SJoao Pinto 		txmode = SF_DMA_MODE;
17076deee222SJoao Pinto 		rxmode = SF_DMA_MODE;
1708b2dec116SSonic Zhang 		priv->xstats.threshold = SF_DMA_MODE;
17096deee222SJoao Pinto 	} else {
17106deee222SJoao Pinto 		txmode = tc;
17116deee222SJoao Pinto 		rxmode = SF_DMA_MODE;
17126deee222SJoao Pinto 	}
17136deee222SJoao Pinto 
17146deee222SJoao Pinto 	/* configure all channels */
17156deee222SJoao Pinto 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
17166deee222SJoao Pinto 		for (chan = 0; chan < rx_channels_count; chan++)
17176deee222SJoao Pinto 			priv->hw->dma->dma_rx_mode(priv->ioaddr, rxmode, chan,
1718f88203a2SVince Bridgers 						   rxfifosz);
17196deee222SJoao Pinto 
17206deee222SJoao Pinto 		for (chan = 0; chan < tx_channels_count; chan++)
17216deee222SJoao Pinto 			priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan);
17226deee222SJoao Pinto 	} else {
17236deee222SJoao Pinto 		priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode,
17246deee222SJoao Pinto 					rxfifosz);
17256deee222SJoao Pinto 	}
17267ac6653aSJeff Kirsher }
17277ac6653aSJeff Kirsher 
17287ac6653aSJeff Kirsher /**
1729732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_clean - to manage the transmission completion
173032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
1731ce736788SJoao Pinto  * @queue: TX queue index
1732732fdf0eSGiuseppe CAVALLARO  * Description: it reclaims the transmit resources after transmission completes.
17337ac6653aSJeff Kirsher  */
1734ce736788SJoao Pinto static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
17357ac6653aSJeff Kirsher {
1736ce736788SJoao Pinto 	struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
173738979574SBeniamino Galvani 	unsigned int bytes_compl = 0, pkts_compl = 0;
1738ce736788SJoao Pinto 	unsigned int entry = tx_q->dirty_tx;
17397ac6653aSJeff Kirsher 
1740739c8e14SLino Sanfilippo 	netif_tx_lock(priv->dev);
1741a9097a96SGiuseppe CAVALLARO 
17429125cdd1SGiuseppe CAVALLARO 	priv->xstats.tx_clean++;
17439125cdd1SGiuseppe CAVALLARO 
1744ce736788SJoao Pinto 	while (entry != tx_q->cur_tx) {
1745ce736788SJoao Pinto 		struct sk_buff *skb = tx_q->tx_skbuff[entry];
1746c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1747c363b658SFabrice Gasnier 		int status;
1748c24602efSGiuseppe CAVALLARO 
1749c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1750ce736788SJoao Pinto 			p = (struct dma_desc *)(tx_q->dma_etx + entry);
1751c24602efSGiuseppe CAVALLARO 		else
1752ce736788SJoao Pinto 			p = tx_q->dma_tx + entry;
17537ac6653aSJeff Kirsher 
1754c363b658SFabrice Gasnier 		status = priv->hw->desc->tx_status(&priv->dev->stats,
17557ac6653aSJeff Kirsher 						      &priv->xstats, p,
17567ac6653aSJeff Kirsher 						      priv->ioaddr);
1757c363b658SFabrice Gasnier 		/* Check if the descriptor is owned by the DMA */
1758c363b658SFabrice Gasnier 		if (unlikely(status & tx_dma_own))
1759c363b658SFabrice Gasnier 			break;
1760c363b658SFabrice Gasnier 
1761c363b658SFabrice Gasnier 		/* Just consider the last segment and ...*/
1762c363b658SFabrice Gasnier 		if (likely(!(status & tx_not_ls))) {
1763c363b658SFabrice Gasnier 			/* ... verify the status error condition */
1764c363b658SFabrice Gasnier 			if (unlikely(status & tx_err)) {
1765c363b658SFabrice Gasnier 				priv->dev->stats.tx_errors++;
1766c363b658SFabrice Gasnier 			} else {
17677ac6653aSJeff Kirsher 				priv->dev->stats.tx_packets++;
17687ac6653aSJeff Kirsher 				priv->xstats.tx_pkt_n++;
1769c363b658SFabrice Gasnier 			}
1770ba1ffd74SGiuseppe CAVALLARO 			stmmac_get_tx_hwtstamp(priv, p, skb);
17717ac6653aSJeff Kirsher 		}
17727ac6653aSJeff Kirsher 
1773ce736788SJoao Pinto 		if (likely(tx_q->tx_skbuff_dma[entry].buf)) {
1774ce736788SJoao Pinto 			if (tx_q->tx_skbuff_dma[entry].map_as_page)
1775362b37beSGiuseppe CAVALLARO 				dma_unmap_page(priv->device,
1776ce736788SJoao Pinto 					       tx_q->tx_skbuff_dma[entry].buf,
1777ce736788SJoao Pinto 					       tx_q->tx_skbuff_dma[entry].len,
17787ac6653aSJeff Kirsher 					       DMA_TO_DEVICE);
1779362b37beSGiuseppe CAVALLARO 			else
1780362b37beSGiuseppe CAVALLARO 				dma_unmap_single(priv->device,
1781ce736788SJoao Pinto 						 tx_q->tx_skbuff_dma[entry].buf,
1782ce736788SJoao Pinto 						 tx_q->tx_skbuff_dma[entry].len,
1783362b37beSGiuseppe CAVALLARO 						 DMA_TO_DEVICE);
1784ce736788SJoao Pinto 			tx_q->tx_skbuff_dma[entry].buf = 0;
1785ce736788SJoao Pinto 			tx_q->tx_skbuff_dma[entry].len = 0;
1786ce736788SJoao Pinto 			tx_q->tx_skbuff_dma[entry].map_as_page = false;
1787cf32deecSRayagond Kokatanur 		}
1788f748be53SAlexandre TORGUE 
1789f748be53SAlexandre TORGUE 		if (priv->hw->mode->clean_desc3)
1790ce736788SJoao Pinto 			priv->hw->mode->clean_desc3(tx_q, p);
1791f748be53SAlexandre TORGUE 
1792ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[entry].last_segment = false;
1793ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[entry].is_jumbo = false;
17947ac6653aSJeff Kirsher 
17957ac6653aSJeff Kirsher 		if (likely(skb != NULL)) {
179638979574SBeniamino Galvani 			pkts_compl++;
179738979574SBeniamino Galvani 			bytes_compl += skb->len;
17987c565c33SEric W. Biederman 			dev_consume_skb_any(skb);
1799ce736788SJoao Pinto 			tx_q->tx_skbuff[entry] = NULL;
18007ac6653aSJeff Kirsher 		}
18017ac6653aSJeff Kirsher 
18024a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->release_tx_desc(p, priv->mode);
18037ac6653aSJeff Kirsher 
1804e3ad57c9SGiuseppe Cavallaro 		entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
18057ac6653aSJeff Kirsher 	}
1806ce736788SJoao Pinto 	tx_q->dirty_tx = entry;
180738979574SBeniamino Galvani 
18085bacd778SLABBE Corentin 	netdev_completed_queue(priv->dev, pkts_compl, bytes_compl);
180938979574SBeniamino Galvani 
18105bacd778SLABBE Corentin 	if (unlikely(netif_queue_stopped(priv->dev) &&
1811ce736788SJoao Pinto 	    stmmac_tx_avail(priv, queue) > STMMAC_TX_THRESH)) {
1812b3e51069SLABBE Corentin 		netif_dbg(priv, tx_done, priv->dev,
1813b3e51069SLABBE Corentin 			  "%s: restart transmit\n", __func__);
18145bacd778SLABBE Corentin 		netif_wake_queue(priv->dev);
18157ac6653aSJeff Kirsher 	}
1816d765955dSGiuseppe CAVALLARO 
1817d765955dSGiuseppe CAVALLARO 	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
1818d765955dSGiuseppe CAVALLARO 		stmmac_enable_eee_mode(priv);
1819f5351ef7SGiuseppe CAVALLARO 		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
1820d765955dSGiuseppe CAVALLARO 	}
1821739c8e14SLino Sanfilippo 	netif_tx_unlock(priv->dev);
18227ac6653aSJeff Kirsher }
18237ac6653aSJeff Kirsher 
18244f513ecdSJoao Pinto static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv, u32 chan)
18257ac6653aSJeff Kirsher {
18264f513ecdSJoao Pinto 	priv->hw->dma->enable_dma_irq(priv->ioaddr, chan);
18277ac6653aSJeff Kirsher }
18287ac6653aSJeff Kirsher 
18294f513ecdSJoao Pinto static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv, u32 chan)
18307ac6653aSJeff Kirsher {
18314f513ecdSJoao Pinto 	priv->hw->dma->disable_dma_irq(priv->ioaddr, chan);
18327ac6653aSJeff Kirsher }
18337ac6653aSJeff Kirsher 
18347ac6653aSJeff Kirsher /**
1835732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_err - to manage the tx error
183632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
18375bacd778SLABBE Corentin  * @chan: channel index
18387ac6653aSJeff Kirsher  * Description: it cleans the descriptors and restarts the transmission
1839732fdf0eSGiuseppe CAVALLARO  * in case of transmission errors.
18407ac6653aSJeff Kirsher  */
18415bacd778SLABBE Corentin static void stmmac_tx_err(struct stmmac_priv *priv, u32 chan)
18427ac6653aSJeff Kirsher {
1843ce736788SJoao Pinto 	struct stmmac_tx_queue *tx_q = &priv->tx_queue[chan];
1844c24602efSGiuseppe CAVALLARO 	int i;
1845ce736788SJoao Pinto 
18465bacd778SLABBE Corentin 	netif_stop_queue(priv->dev);
18477ac6653aSJeff Kirsher 
1848ae4f0d46SJoao Pinto 	stmmac_stop_tx_dma(priv, chan);
1849ce736788SJoao Pinto 	dma_free_tx_skbufs(priv, chan);
1850e3ad57c9SGiuseppe Cavallaro 	for (i = 0; i < DMA_TX_SIZE; i++)
1851c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1852ce736788SJoao Pinto 			priv->hw->desc->init_tx_desc(&tx_q->dma_etx[i].basic,
1853c24602efSGiuseppe CAVALLARO 						     priv->mode,
1854e3ad57c9SGiuseppe Cavallaro 						     (i == DMA_TX_SIZE - 1));
1855c24602efSGiuseppe CAVALLARO 		else
1856ce736788SJoao Pinto 			priv->hw->desc->init_tx_desc(&tx_q->dma_tx[i],
1857c24602efSGiuseppe CAVALLARO 						     priv->mode,
1858e3ad57c9SGiuseppe Cavallaro 						     (i == DMA_TX_SIZE - 1));
1859ce736788SJoao Pinto 	tx_q->dirty_tx = 0;
1860ce736788SJoao Pinto 	tx_q->cur_tx = 0;
18615bacd778SLABBE Corentin 	netdev_reset_queue(priv->dev);
1862ae4f0d46SJoao Pinto 	stmmac_start_tx_dma(priv, chan);
18637ac6653aSJeff Kirsher 
18647ac6653aSJeff Kirsher 	priv->dev->stats.tx_errors++;
18655bacd778SLABBE Corentin 	netif_wake_queue(priv->dev);
18667ac6653aSJeff Kirsher }
18677ac6653aSJeff Kirsher 
186832ceabcaSGiuseppe CAVALLARO /**
18696deee222SJoao Pinto  *  stmmac_set_dma_operation_mode - Set DMA operation mode by channel
18706deee222SJoao Pinto  *  @priv: driver private structure
18716deee222SJoao Pinto  *  @txmode: TX operating mode
18726deee222SJoao Pinto  *  @rxmode: RX operating mode
18736deee222SJoao Pinto  *  @chan: channel index
18746deee222SJoao Pinto  *  Description: it is used for configuring of the DMA operation mode in
18756deee222SJoao Pinto  *  runtime in order to program the tx/rx DMA thresholds or Store-And-Forward
18766deee222SJoao Pinto  *  mode.
18776deee222SJoao Pinto  */
18786deee222SJoao Pinto static void stmmac_set_dma_operation_mode(struct stmmac_priv *priv, u32 txmode,
18796deee222SJoao Pinto 					  u32 rxmode, u32 chan)
18806deee222SJoao Pinto {
18816deee222SJoao Pinto 	int rxfifosz = priv->plat->rx_fifo_size;
18826deee222SJoao Pinto 
18836deee222SJoao Pinto 	if (rxfifosz == 0)
18846deee222SJoao Pinto 		rxfifosz = priv->dma_cap.rx_fifo_size;
18856deee222SJoao Pinto 
18866deee222SJoao Pinto 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
18876deee222SJoao Pinto 		priv->hw->dma->dma_rx_mode(priv->ioaddr, rxmode, chan,
18886deee222SJoao Pinto 					   rxfifosz);
18896deee222SJoao Pinto 		priv->hw->dma->dma_tx_mode(priv->ioaddr, txmode, chan);
18906deee222SJoao Pinto 	} else {
18916deee222SJoao Pinto 		priv->hw->dma->dma_mode(priv->ioaddr, txmode, rxmode,
18926deee222SJoao Pinto 					rxfifosz);
18936deee222SJoao Pinto 	}
18946deee222SJoao Pinto }
18956deee222SJoao Pinto 
18966deee222SJoao Pinto /**
1897732fdf0eSGiuseppe CAVALLARO  * stmmac_dma_interrupt - DMA ISR
189832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
189932ceabcaSGiuseppe CAVALLARO  * Description: this is the DMA ISR. It is called by the main ISR.
1900732fdf0eSGiuseppe CAVALLARO  * It calls the dwmac dma routine and schedule poll method in case of some
1901732fdf0eSGiuseppe CAVALLARO  * work can be done.
190232ceabcaSGiuseppe CAVALLARO  */
19037ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv)
19047ac6653aSJeff Kirsher {
1905d62a107aSJoao Pinto 	u32 tx_channel_count = priv->plat->tx_queues_to_use;
19067ac6653aSJeff Kirsher 	int status;
1907d62a107aSJoao Pinto 	u32 chan;
190868e5cfafSJoao Pinto 
1909d62a107aSJoao Pinto 	for (chan = 0; chan < tx_channel_count; chan++) {
1910d62a107aSJoao Pinto 		status = priv->hw->dma->dma_interrupt(priv->ioaddr,
1911d62a107aSJoao Pinto 						      &priv->xstats, chan);
19129125cdd1SGiuseppe CAVALLARO 		if (likely((status & handle_rx)) || (status & handle_tx)) {
19135bacd778SLABBE Corentin 			if (likely(napi_schedule_prep(&priv->napi))) {
19144f513ecdSJoao Pinto 				stmmac_disable_dma_irq(priv, chan);
19155bacd778SLABBE Corentin 				__napi_schedule(&priv->napi);
19169125cdd1SGiuseppe CAVALLARO 			}
19179125cdd1SGiuseppe CAVALLARO 		}
1918d62a107aSJoao Pinto 
19199125cdd1SGiuseppe CAVALLARO 		if (unlikely(status & tx_hard_error_bump_tc)) {
19207ac6653aSJeff Kirsher 			/* Try to bump up the dma threshold on this failure */
1921b2dec116SSonic Zhang 			if (unlikely(priv->xstats.threshold != SF_DMA_MODE) &&
1922b2dec116SSonic Zhang 			    (tc <= 256)) {
19237ac6653aSJeff Kirsher 				tc += 64;
1924c405abe2SSonic Zhang 				if (priv->plat->force_thresh_dma_mode)
1925d62a107aSJoao Pinto 					stmmac_set_dma_operation_mode(priv,
1926d62a107aSJoao Pinto 								      tc,
1927d62a107aSJoao Pinto 								      tc,
1928d62a107aSJoao Pinto 								      chan);
1929c405abe2SSonic Zhang 				else
1930d62a107aSJoao Pinto 					stmmac_set_dma_operation_mode(priv,
1931d62a107aSJoao Pinto 								    tc,
1932d62a107aSJoao Pinto 								    SF_DMA_MODE,
1933d62a107aSJoao Pinto 								    chan);
19347ac6653aSJeff Kirsher 				priv->xstats.threshold = tc;
19357ac6653aSJeff Kirsher 			}
1936d62a107aSJoao Pinto 		} else if (unlikely(status == tx_hard_error)) {
19374e593262SJoao Pinto 			stmmac_tx_err(priv, chan);
19387ac6653aSJeff Kirsher 		}
1939d62a107aSJoao Pinto 	}
1940d62a107aSJoao Pinto }
19417ac6653aSJeff Kirsher 
194232ceabcaSGiuseppe CAVALLARO /**
194332ceabcaSGiuseppe CAVALLARO  * stmmac_mmc_setup: setup the Mac Management Counters (MMC)
194432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
194532ceabcaSGiuseppe CAVALLARO  * Description: this masks the MMC irq, in fact, the counters are managed in SW.
194632ceabcaSGiuseppe CAVALLARO  */
19471c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv)
19481c901a46SGiuseppe CAVALLARO {
19491c901a46SGiuseppe CAVALLARO 	unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
19501c901a46SGiuseppe CAVALLARO 			    MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
19511c901a46SGiuseppe CAVALLARO 
1952ba1ffd74SGiuseppe CAVALLARO 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
1953ba1ffd74SGiuseppe CAVALLARO 		priv->ptpaddr = priv->ioaddr + PTP_GMAC4_OFFSET;
1954f748be53SAlexandre TORGUE 		priv->mmcaddr = priv->ioaddr + MMC_GMAC4_OFFSET;
1955ba1ffd74SGiuseppe CAVALLARO 	} else {
1956ba1ffd74SGiuseppe CAVALLARO 		priv->ptpaddr = priv->ioaddr + PTP_GMAC3_X_OFFSET;
195736ff7c1eSAlexandre TORGUE 		priv->mmcaddr = priv->ioaddr + MMC_GMAC3_X_OFFSET;
1958ba1ffd74SGiuseppe CAVALLARO 	}
195936ff7c1eSAlexandre TORGUE 
196036ff7c1eSAlexandre TORGUE 	dwmac_mmc_intr_all_mask(priv->mmcaddr);
19614f795b25SGiuseppe CAVALLARO 
19624f795b25SGiuseppe CAVALLARO 	if (priv->dma_cap.rmon) {
196336ff7c1eSAlexandre TORGUE 		dwmac_mmc_ctrl(priv->mmcaddr, mode);
19641c901a46SGiuseppe CAVALLARO 		memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
19654f795b25SGiuseppe CAVALLARO 	} else
196638ddc59dSLABBE Corentin 		netdev_info(priv->dev, "No MAC Management Counters available\n");
19671c901a46SGiuseppe CAVALLARO }
19681c901a46SGiuseppe CAVALLARO 
1969732fdf0eSGiuseppe CAVALLARO /**
1970732fdf0eSGiuseppe CAVALLARO  * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors
197132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
197232ceabcaSGiuseppe CAVALLARO  * Description: select the Enhanced/Alternate or Normal descriptors.
1973732fdf0eSGiuseppe CAVALLARO  * In case of Enhanced/Alternate, it checks if the extended descriptors are
1974732fdf0eSGiuseppe CAVALLARO  * supported by the HW capability register.
1975ff3dd78cSGiuseppe CAVALLARO  */
197619e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
197719e30c14SGiuseppe CAVALLARO {
197819e30c14SGiuseppe CAVALLARO 	if (priv->plat->enh_desc) {
197938ddc59dSLABBE Corentin 		dev_info(priv->device, "Enhanced/Alternate descriptors\n");
1980c24602efSGiuseppe CAVALLARO 
1981c24602efSGiuseppe CAVALLARO 		/* GMAC older than 3.50 has no extended descriptors */
1982c24602efSGiuseppe CAVALLARO 		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
198338ddc59dSLABBE Corentin 			dev_info(priv->device, "Enabled extended descriptors\n");
1984c24602efSGiuseppe CAVALLARO 			priv->extend_desc = 1;
1985c24602efSGiuseppe CAVALLARO 		} else
198638ddc59dSLABBE Corentin 			dev_warn(priv->device, "Extended descriptors not supported\n");
1987c24602efSGiuseppe CAVALLARO 
198819e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &enh_desc_ops;
198919e30c14SGiuseppe CAVALLARO 	} else {
199038ddc59dSLABBE Corentin 		dev_info(priv->device, "Normal descriptors\n");
199119e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &ndesc_ops;
199219e30c14SGiuseppe CAVALLARO 	}
199319e30c14SGiuseppe CAVALLARO }
199419e30c14SGiuseppe CAVALLARO 
199519e30c14SGiuseppe CAVALLARO /**
1996732fdf0eSGiuseppe CAVALLARO  * stmmac_get_hw_features - get MAC capabilities from the HW cap. register.
199732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
199819e30c14SGiuseppe CAVALLARO  * Description:
199919e30c14SGiuseppe CAVALLARO  *  new GMAC chip generations have a new register to indicate the
2000e7434821SGiuseppe CAVALLARO  *  presence of the optional feature/functions.
200119e30c14SGiuseppe CAVALLARO  *  This can be also used to override the value passed through the
200219e30c14SGiuseppe CAVALLARO  *  platform and necessary for old MAC10/100 and GMAC chips.
2003e7434821SGiuseppe CAVALLARO  */
2004e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv)
2005e7434821SGiuseppe CAVALLARO {
2006f10a6a35SAlexandre TORGUE 	u32 ret = 0;
20073c20f72fSGiuseppe CAVALLARO 
20085e6efe88SGiuseppe CAVALLARO 	if (priv->hw->dma->get_hw_feature) {
2009f10a6a35SAlexandre TORGUE 		priv->hw->dma->get_hw_feature(priv->ioaddr,
2010f10a6a35SAlexandre TORGUE 					      &priv->dma_cap);
2011f10a6a35SAlexandre TORGUE 		ret = 1;
201219e30c14SGiuseppe CAVALLARO 	}
2013e7434821SGiuseppe CAVALLARO 
2014f10a6a35SAlexandre TORGUE 	return ret;
2015e7434821SGiuseppe CAVALLARO }
2016e7434821SGiuseppe CAVALLARO 
201732ceabcaSGiuseppe CAVALLARO /**
2018732fdf0eSGiuseppe CAVALLARO  * stmmac_check_ether_addr - check if the MAC addr is valid
201932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
202032ceabcaSGiuseppe CAVALLARO  * Description:
202132ceabcaSGiuseppe CAVALLARO  * it is to verify if the MAC address is valid, in case of failures it
202232ceabcaSGiuseppe CAVALLARO  * generates a random MAC address
202332ceabcaSGiuseppe CAVALLARO  */
2024bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv)
2025bfab27a1SGiuseppe CAVALLARO {
2026bfab27a1SGiuseppe CAVALLARO 	if (!is_valid_ether_addr(priv->dev->dev_addr)) {
20277ed24bbeSVince Bridgers 		priv->hw->mac->get_umac_addr(priv->hw,
2028bfab27a1SGiuseppe CAVALLARO 					     priv->dev->dev_addr, 0);
2029bfab27a1SGiuseppe CAVALLARO 		if (!is_valid_ether_addr(priv->dev->dev_addr))
2030f2cedb63SDanny Kukawka 			eth_hw_addr_random(priv->dev);
203138ddc59dSLABBE Corentin 		netdev_info(priv->dev, "device MAC address %pM\n",
2032bfab27a1SGiuseppe CAVALLARO 			    priv->dev->dev_addr);
2033bfab27a1SGiuseppe CAVALLARO 	}
2034c88460b7SHans de Goede }
2035bfab27a1SGiuseppe CAVALLARO 
203632ceabcaSGiuseppe CAVALLARO /**
2037732fdf0eSGiuseppe CAVALLARO  * stmmac_init_dma_engine - DMA init.
203832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
203932ceabcaSGiuseppe CAVALLARO  * Description:
204032ceabcaSGiuseppe CAVALLARO  * It inits the DMA invoking the specific MAC/GMAC callback.
204132ceabcaSGiuseppe CAVALLARO  * Some DMA parameters can be passed from the platform;
204232ceabcaSGiuseppe CAVALLARO  * in case of these are not passed a default is kept for the MAC or GMAC.
204332ceabcaSGiuseppe CAVALLARO  */
20440f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv)
20450f1f88a8SGiuseppe CAVALLARO {
204647f2a9ceSJoao Pinto 	u32 rx_channels_count = priv->plat->rx_queues_to_use;
204747f2a9ceSJoao Pinto 	u32 tx_channels_count = priv->plat->tx_queues_to_use;
204854139cf3SJoao Pinto 	struct stmmac_rx_queue *rx_q;
2049ce736788SJoao Pinto 	struct stmmac_tx_queue *tx_q;
205047f2a9ceSJoao Pinto 	u32 dummy_dma_rx_phy = 0;
205147f2a9ceSJoao Pinto 	u32 dummy_dma_tx_phy = 0;
205247f2a9ceSJoao Pinto 	u32 chan = 0;
2053c24602efSGiuseppe CAVALLARO 	int atds = 0;
2054495db273SGiuseppe Cavallaro 	int ret = 0;
20550f1f88a8SGiuseppe CAVALLARO 
2056a332e2faSNiklas Cassel 	if (!priv->plat->dma_cfg || !priv->plat->dma_cfg->pbl) {
2057a332e2faSNiklas Cassel 		dev_err(priv->device, "Invalid DMA configuration\n");
205889ab75bfSNiklas Cassel 		return -EINVAL;
20590f1f88a8SGiuseppe CAVALLARO 	}
20600f1f88a8SGiuseppe CAVALLARO 
2061c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
2062c24602efSGiuseppe CAVALLARO 		atds = 1;
2063c24602efSGiuseppe CAVALLARO 
2064495db273SGiuseppe Cavallaro 	ret = priv->hw->dma->reset(priv->ioaddr);
2065495db273SGiuseppe Cavallaro 	if (ret) {
2066495db273SGiuseppe Cavallaro 		dev_err(priv->device, "Failed to reset the dma\n");
2067495db273SGiuseppe Cavallaro 		return ret;
2068495db273SGiuseppe Cavallaro 	}
2069495db273SGiuseppe Cavallaro 
2070f748be53SAlexandre TORGUE 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
207147f2a9ceSJoao Pinto 		/* DMA Configuration */
207247f2a9ceSJoao Pinto 		priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg,
207347f2a9ceSJoao Pinto 				    dummy_dma_tx_phy, dummy_dma_rx_phy, atds);
207447f2a9ceSJoao Pinto 
207547f2a9ceSJoao Pinto 		/* DMA RX Channel Configuration */
207647f2a9ceSJoao Pinto 		for (chan = 0; chan < rx_channels_count; chan++) {
207754139cf3SJoao Pinto 			rx_q = &priv->rx_queue[chan];
207854139cf3SJoao Pinto 
207947f2a9ceSJoao Pinto 			priv->hw->dma->init_rx_chan(priv->ioaddr,
208047f2a9ceSJoao Pinto 						    priv->plat->dma_cfg,
208154139cf3SJoao Pinto 						    rx_q->dma_rx_phy, chan);
208247f2a9ceSJoao Pinto 
208354139cf3SJoao Pinto 			rx_q->rx_tail_addr = rx_q->dma_rx_phy +
2084f748be53SAlexandre TORGUE 				    (DMA_RX_SIZE * sizeof(struct dma_desc));
208547f2a9ceSJoao Pinto 			priv->hw->dma->set_rx_tail_ptr(priv->ioaddr,
208654139cf3SJoao Pinto 						       rx_q->rx_tail_addr,
208747f2a9ceSJoao Pinto 						       chan);
208847f2a9ceSJoao Pinto 		}
208947f2a9ceSJoao Pinto 
209047f2a9ceSJoao Pinto 		/* DMA TX Channel Configuration */
209147f2a9ceSJoao Pinto 		for (chan = 0; chan < tx_channels_count; chan++) {
2092ce736788SJoao Pinto 			tx_q = &priv->tx_queue[chan];
2093ce736788SJoao Pinto 
209447f2a9ceSJoao Pinto 			priv->hw->dma->init_chan(priv->ioaddr,
209547f2a9ceSJoao Pinto 						 priv->plat->dma_cfg,
209647f2a9ceSJoao Pinto 						 chan);
209747f2a9ceSJoao Pinto 
209847f2a9ceSJoao Pinto 			priv->hw->dma->init_tx_chan(priv->ioaddr,
209947f2a9ceSJoao Pinto 						    priv->plat->dma_cfg,
2100ce736788SJoao Pinto 						    tx_q->dma_tx_phy, chan);
2101f748be53SAlexandre TORGUE 
2102ce736788SJoao Pinto 			tx_q->tx_tail_addr = tx_q->dma_tx_phy +
2103f748be53SAlexandre TORGUE 				    (DMA_TX_SIZE * sizeof(struct dma_desc));
210447f2a9ceSJoao Pinto 			priv->hw->dma->set_tx_tail_ptr(priv->ioaddr,
2105ce736788SJoao Pinto 						       tx_q->tx_tail_addr,
210647f2a9ceSJoao Pinto 						       chan);
210747f2a9ceSJoao Pinto 		}
210847f2a9ceSJoao Pinto 	} else {
210954139cf3SJoao Pinto 		rx_q = &priv->rx_queue[chan];
2110ce736788SJoao Pinto 		tx_q = &priv->tx_queue[chan];
211147f2a9ceSJoao Pinto 		priv->hw->dma->init(priv->ioaddr, priv->plat->dma_cfg,
2112ce736788SJoao Pinto 				    tx_q->dma_tx_phy, rx_q->dma_rx_phy, atds);
2113f748be53SAlexandre TORGUE 	}
2114f748be53SAlexandre TORGUE 
2115f748be53SAlexandre TORGUE 	if (priv->plat->axi && priv->hw->dma->axi)
2116afea0365SGiuseppe Cavallaro 		priv->hw->dma->axi(priv->ioaddr, priv->plat->axi);
2117afea0365SGiuseppe Cavallaro 
2118495db273SGiuseppe Cavallaro 	return ret;
21190f1f88a8SGiuseppe CAVALLARO }
21200f1f88a8SGiuseppe CAVALLARO 
2121bfab27a1SGiuseppe CAVALLARO /**
2122732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_timer - mitigation sw timer for tx.
21239125cdd1SGiuseppe CAVALLARO  * @data: data pointer
21249125cdd1SGiuseppe CAVALLARO  * Description:
21259125cdd1SGiuseppe CAVALLARO  * This is the timer handler to directly invoke the stmmac_tx_clean.
21269125cdd1SGiuseppe CAVALLARO  */
21279125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data)
21289125cdd1SGiuseppe CAVALLARO {
21299125cdd1SGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)data;
2130ce736788SJoao Pinto 	u32 tx_queues_count = priv->plat->tx_queues_to_use;
2131ce736788SJoao Pinto 	u32 queue;
21329125cdd1SGiuseppe CAVALLARO 
2133ce736788SJoao Pinto 	/* let's scan all the tx queues */
2134ce736788SJoao Pinto 	for (queue = 0; queue < tx_queues_count; queue++)
2135ce736788SJoao Pinto 		stmmac_tx_clean(priv, queue);
21369125cdd1SGiuseppe CAVALLARO }
21379125cdd1SGiuseppe CAVALLARO 
21389125cdd1SGiuseppe CAVALLARO /**
2139732fdf0eSGiuseppe CAVALLARO  * stmmac_init_tx_coalesce - init tx mitigation options.
214032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
21419125cdd1SGiuseppe CAVALLARO  * Description:
21429125cdd1SGiuseppe CAVALLARO  * This inits the transmit coalesce parameters: i.e. timer rate,
21439125cdd1SGiuseppe CAVALLARO  * timer handler and default threshold used for enabling the
21449125cdd1SGiuseppe CAVALLARO  * interrupt on completion bit.
21459125cdd1SGiuseppe CAVALLARO  */
21469125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
21479125cdd1SGiuseppe CAVALLARO {
21489125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_frames = STMMAC_TX_FRAMES;
21499125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
21509125cdd1SGiuseppe CAVALLARO 	init_timer(&priv->txtimer);
21519125cdd1SGiuseppe CAVALLARO 	priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
21529125cdd1SGiuseppe CAVALLARO 	priv->txtimer.data = (unsigned long)priv;
21539125cdd1SGiuseppe CAVALLARO 	priv->txtimer.function = stmmac_tx_timer;
21549125cdd1SGiuseppe CAVALLARO 	add_timer(&priv->txtimer);
21559125cdd1SGiuseppe CAVALLARO }
21569125cdd1SGiuseppe CAVALLARO 
21574854ab99SJoao Pinto static void stmmac_set_rings_length(struct stmmac_priv *priv)
21584854ab99SJoao Pinto {
21594854ab99SJoao Pinto 	u32 rx_channels_count = priv->plat->rx_queues_to_use;
21604854ab99SJoao Pinto 	u32 tx_channels_count = priv->plat->tx_queues_to_use;
21614854ab99SJoao Pinto 	u32 chan;
21624854ab99SJoao Pinto 
21634854ab99SJoao Pinto 	/* set TX ring length */
21644854ab99SJoao Pinto 	if (priv->hw->dma->set_tx_ring_len) {
21654854ab99SJoao Pinto 		for (chan = 0; chan < tx_channels_count; chan++)
21664854ab99SJoao Pinto 			priv->hw->dma->set_tx_ring_len(priv->ioaddr,
21674854ab99SJoao Pinto 						       (DMA_TX_SIZE - 1), chan);
21684854ab99SJoao Pinto 	}
21694854ab99SJoao Pinto 
21704854ab99SJoao Pinto 	/* set RX ring length */
21714854ab99SJoao Pinto 	if (priv->hw->dma->set_rx_ring_len) {
21724854ab99SJoao Pinto 		for (chan = 0; chan < rx_channels_count; chan++)
21734854ab99SJoao Pinto 			priv->hw->dma->set_rx_ring_len(priv->ioaddr,
21744854ab99SJoao Pinto 						       (DMA_RX_SIZE - 1), chan);
21754854ab99SJoao Pinto 	}
21764854ab99SJoao Pinto }
21774854ab99SJoao Pinto 
21789125cdd1SGiuseppe CAVALLARO /**
21796a3a7193SJoao Pinto  *  stmmac_set_tx_queue_weight - Set TX queue weight
21806a3a7193SJoao Pinto  *  @priv: driver private structure
21816a3a7193SJoao Pinto  *  Description: It is used for setting TX queues weight
21826a3a7193SJoao Pinto  */
21836a3a7193SJoao Pinto static void stmmac_set_tx_queue_weight(struct stmmac_priv *priv)
21846a3a7193SJoao Pinto {
21856a3a7193SJoao Pinto 	u32 tx_queues_count = priv->plat->tx_queues_to_use;
21866a3a7193SJoao Pinto 	u32 weight;
21876a3a7193SJoao Pinto 	u32 queue;
21886a3a7193SJoao Pinto 
21896a3a7193SJoao Pinto 	for (queue = 0; queue < tx_queues_count; queue++) {
21906a3a7193SJoao Pinto 		weight = priv->plat->tx_queues_cfg[queue].weight;
21916a3a7193SJoao Pinto 		priv->hw->mac->set_mtl_tx_queue_weight(priv->hw, weight, queue);
21926a3a7193SJoao Pinto 	}
21936a3a7193SJoao Pinto }
21946a3a7193SJoao Pinto 
21956a3a7193SJoao Pinto /**
219619d91873SJoao Pinto  *  stmmac_configure_cbs - Configure CBS in TX queue
219719d91873SJoao Pinto  *  @priv: driver private structure
219819d91873SJoao Pinto  *  Description: It is used for configuring CBS in AVB TX queues
219919d91873SJoao Pinto  */
220019d91873SJoao Pinto static void stmmac_configure_cbs(struct stmmac_priv *priv)
220119d91873SJoao Pinto {
220219d91873SJoao Pinto 	u32 tx_queues_count = priv->plat->tx_queues_to_use;
220319d91873SJoao Pinto 	u32 mode_to_use;
220419d91873SJoao Pinto 	u32 queue;
220519d91873SJoao Pinto 
220644781fefSJoao Pinto 	/* queue 0 is reserved for legacy traffic */
220744781fefSJoao Pinto 	for (queue = 1; queue < tx_queues_count; queue++) {
220819d91873SJoao Pinto 		mode_to_use = priv->plat->tx_queues_cfg[queue].mode_to_use;
220919d91873SJoao Pinto 		if (mode_to_use == MTL_QUEUE_DCB)
221019d91873SJoao Pinto 			continue;
221119d91873SJoao Pinto 
221219d91873SJoao Pinto 		priv->hw->mac->config_cbs(priv->hw,
221319d91873SJoao Pinto 				priv->plat->tx_queues_cfg[queue].send_slope,
221419d91873SJoao Pinto 				priv->plat->tx_queues_cfg[queue].idle_slope,
221519d91873SJoao Pinto 				priv->plat->tx_queues_cfg[queue].high_credit,
221619d91873SJoao Pinto 				priv->plat->tx_queues_cfg[queue].low_credit,
221719d91873SJoao Pinto 				queue);
221819d91873SJoao Pinto 	}
221919d91873SJoao Pinto }
222019d91873SJoao Pinto 
222119d91873SJoao Pinto /**
2222d43042f4SJoao Pinto  *  stmmac_rx_queue_dma_chan_map - Map RX queue to RX dma channel
2223d43042f4SJoao Pinto  *  @priv: driver private structure
2224d43042f4SJoao Pinto  *  Description: It is used for mapping RX queues to RX dma channels
2225d43042f4SJoao Pinto  */
2226d43042f4SJoao Pinto static void stmmac_rx_queue_dma_chan_map(struct stmmac_priv *priv)
2227d43042f4SJoao Pinto {
2228d43042f4SJoao Pinto 	u32 rx_queues_count = priv->plat->rx_queues_to_use;
2229d43042f4SJoao Pinto 	u32 queue;
2230d43042f4SJoao Pinto 	u32 chan;
2231d43042f4SJoao Pinto 
2232d43042f4SJoao Pinto 	for (queue = 0; queue < rx_queues_count; queue++) {
2233d43042f4SJoao Pinto 		chan = priv->plat->rx_queues_cfg[queue].chan;
2234d43042f4SJoao Pinto 		priv->hw->mac->map_mtl_to_dma(priv->hw, queue, chan);
2235d43042f4SJoao Pinto 	}
2236d43042f4SJoao Pinto }
2237d43042f4SJoao Pinto 
2238d43042f4SJoao Pinto /**
2239a8f5102aSJoao Pinto  *  stmmac_mac_config_rx_queues_prio - Configure RX Queue priority
2240a8f5102aSJoao Pinto  *  @priv: driver private structure
2241a8f5102aSJoao Pinto  *  Description: It is used for configuring the RX Queue Priority
2242a8f5102aSJoao Pinto  */
2243a8f5102aSJoao Pinto static void stmmac_mac_config_rx_queues_prio(struct stmmac_priv *priv)
2244a8f5102aSJoao Pinto {
2245a8f5102aSJoao Pinto 	u32 rx_queues_count = priv->plat->rx_queues_to_use;
2246a8f5102aSJoao Pinto 	u32 queue;
2247a8f5102aSJoao Pinto 	u32 prio;
2248a8f5102aSJoao Pinto 
2249a8f5102aSJoao Pinto 	for (queue = 0; queue < rx_queues_count; queue++) {
2250a8f5102aSJoao Pinto 		if (!priv->plat->rx_queues_cfg[queue].use_prio)
2251a8f5102aSJoao Pinto 			continue;
2252a8f5102aSJoao Pinto 
2253a8f5102aSJoao Pinto 		prio = priv->plat->rx_queues_cfg[queue].prio;
2254a8f5102aSJoao Pinto 		priv->hw->mac->rx_queue_prio(priv->hw, prio, queue);
2255a8f5102aSJoao Pinto 	}
2256a8f5102aSJoao Pinto }
2257a8f5102aSJoao Pinto 
2258a8f5102aSJoao Pinto /**
2259a8f5102aSJoao Pinto  *  stmmac_mac_config_tx_queues_prio - Configure TX Queue priority
2260a8f5102aSJoao Pinto  *  @priv: driver private structure
2261a8f5102aSJoao Pinto  *  Description: It is used for configuring the TX Queue Priority
2262a8f5102aSJoao Pinto  */
2263a8f5102aSJoao Pinto static void stmmac_mac_config_tx_queues_prio(struct stmmac_priv *priv)
2264a8f5102aSJoao Pinto {
2265a8f5102aSJoao Pinto 	u32 tx_queues_count = priv->plat->tx_queues_to_use;
2266a8f5102aSJoao Pinto 	u32 queue;
2267a8f5102aSJoao Pinto 	u32 prio;
2268a8f5102aSJoao Pinto 
2269a8f5102aSJoao Pinto 	for (queue = 0; queue < tx_queues_count; queue++) {
2270a8f5102aSJoao Pinto 		if (!priv->plat->tx_queues_cfg[queue].use_prio)
2271a8f5102aSJoao Pinto 			continue;
2272a8f5102aSJoao Pinto 
2273a8f5102aSJoao Pinto 		prio = priv->plat->tx_queues_cfg[queue].prio;
2274a8f5102aSJoao Pinto 		priv->hw->mac->tx_queue_prio(priv->hw, prio, queue);
2275a8f5102aSJoao Pinto 	}
2276a8f5102aSJoao Pinto }
2277a8f5102aSJoao Pinto 
2278a8f5102aSJoao Pinto /**
2279abe80fdcSJoao Pinto  *  stmmac_mac_config_rx_queues_routing - Configure RX Queue Routing
2280abe80fdcSJoao Pinto  *  @priv: driver private structure
2281abe80fdcSJoao Pinto  *  Description: It is used for configuring the RX queue routing
2282abe80fdcSJoao Pinto  */
2283abe80fdcSJoao Pinto static void stmmac_mac_config_rx_queues_routing(struct stmmac_priv *priv)
2284abe80fdcSJoao Pinto {
2285abe80fdcSJoao Pinto 	u32 rx_queues_count = priv->plat->rx_queues_to_use;
2286abe80fdcSJoao Pinto 	u32 queue;
2287abe80fdcSJoao Pinto 	u8 packet;
2288abe80fdcSJoao Pinto 
2289abe80fdcSJoao Pinto 	for (queue = 0; queue < rx_queues_count; queue++) {
2290abe80fdcSJoao Pinto 		/* no specific packet type routing specified for the queue */
2291abe80fdcSJoao Pinto 		if (priv->plat->rx_queues_cfg[queue].pkt_route == 0x0)
2292abe80fdcSJoao Pinto 			continue;
2293abe80fdcSJoao Pinto 
2294abe80fdcSJoao Pinto 		packet = priv->plat->rx_queues_cfg[queue].pkt_route;
2295abe80fdcSJoao Pinto 		priv->hw->mac->rx_queue_prio(priv->hw, packet, queue);
2296abe80fdcSJoao Pinto 	}
2297abe80fdcSJoao Pinto }
2298abe80fdcSJoao Pinto 
2299abe80fdcSJoao Pinto /**
2300d0a9c9f9SJoao Pinto  *  stmmac_mtl_configuration - Configure MTL
2301d0a9c9f9SJoao Pinto  *  @priv: driver private structure
2302d0a9c9f9SJoao Pinto  *  Description: It is used for configurring MTL
2303d0a9c9f9SJoao Pinto  */
2304d0a9c9f9SJoao Pinto static void stmmac_mtl_configuration(struct stmmac_priv *priv)
2305d0a9c9f9SJoao Pinto {
2306d0a9c9f9SJoao Pinto 	u32 rx_queues_count = priv->plat->rx_queues_to_use;
2307d0a9c9f9SJoao Pinto 	u32 tx_queues_count = priv->plat->tx_queues_to_use;
2308d0a9c9f9SJoao Pinto 
23096a3a7193SJoao Pinto 	if (tx_queues_count > 1 && priv->hw->mac->set_mtl_tx_queue_weight)
23106a3a7193SJoao Pinto 		stmmac_set_tx_queue_weight(priv);
23116a3a7193SJoao Pinto 
2312d0a9c9f9SJoao Pinto 	/* Configure MTL RX algorithms */
2313d0a9c9f9SJoao Pinto 	if (rx_queues_count > 1 && priv->hw->mac->prog_mtl_rx_algorithms)
2314d0a9c9f9SJoao Pinto 		priv->hw->mac->prog_mtl_rx_algorithms(priv->hw,
2315d0a9c9f9SJoao Pinto 						priv->plat->rx_sched_algorithm);
2316d0a9c9f9SJoao Pinto 
2317d0a9c9f9SJoao Pinto 	/* Configure MTL TX algorithms */
2318d0a9c9f9SJoao Pinto 	if (tx_queues_count > 1 && priv->hw->mac->prog_mtl_tx_algorithms)
2319d0a9c9f9SJoao Pinto 		priv->hw->mac->prog_mtl_tx_algorithms(priv->hw,
2320d0a9c9f9SJoao Pinto 						priv->plat->tx_sched_algorithm);
2321d0a9c9f9SJoao Pinto 
232219d91873SJoao Pinto 	/* Configure CBS in AVB TX queues */
232319d91873SJoao Pinto 	if (tx_queues_count > 1 && priv->hw->mac->config_cbs)
232419d91873SJoao Pinto 		stmmac_configure_cbs(priv);
232519d91873SJoao Pinto 
2326d43042f4SJoao Pinto 	/* Map RX MTL to DMA channels */
232703cf65a9SJoao Pinto 	if (priv->hw->mac->map_mtl_to_dma)
2328d43042f4SJoao Pinto 		stmmac_rx_queue_dma_chan_map(priv);
2329d43042f4SJoao Pinto 
2330d0a9c9f9SJoao Pinto 	/* Enable MAC RX Queues */
2331f3976874SThierry Reding 	if (priv->hw->mac->rx_queue_enable)
2332d0a9c9f9SJoao Pinto 		stmmac_mac_enable_rx_queues(priv);
23336deee222SJoao Pinto 
2334a8f5102aSJoao Pinto 	/* Set RX priorities */
2335a8f5102aSJoao Pinto 	if (rx_queues_count > 1 && priv->hw->mac->rx_queue_prio)
2336a8f5102aSJoao Pinto 		stmmac_mac_config_rx_queues_prio(priv);
2337a8f5102aSJoao Pinto 
2338a8f5102aSJoao Pinto 	/* Set TX priorities */
2339a8f5102aSJoao Pinto 	if (tx_queues_count > 1 && priv->hw->mac->tx_queue_prio)
2340a8f5102aSJoao Pinto 		stmmac_mac_config_tx_queues_prio(priv);
2341abe80fdcSJoao Pinto 
2342abe80fdcSJoao Pinto 	/* Set RX routing */
2343abe80fdcSJoao Pinto 	if (rx_queues_count > 1 && priv->hw->mac->rx_queue_routing)
2344abe80fdcSJoao Pinto 		stmmac_mac_config_rx_queues_routing(priv);
2345d0a9c9f9SJoao Pinto }
2346d0a9c9f9SJoao Pinto 
2347d0a9c9f9SJoao Pinto /**
2348732fdf0eSGiuseppe CAVALLARO  * stmmac_hw_setup - setup mac in a usable state.
2349523f11b5SSrinivas Kandagatla  *  @dev : pointer to the device structure.
2350523f11b5SSrinivas Kandagatla  *  Description:
2351732fdf0eSGiuseppe CAVALLARO  *  this is the main function to setup the HW in a usable state because the
2352732fdf0eSGiuseppe CAVALLARO  *  dma engine is reset, the core registers are configured (e.g. AXI,
2353732fdf0eSGiuseppe CAVALLARO  *  Checksum features, timers). The DMA is ready to start receiving and
2354732fdf0eSGiuseppe CAVALLARO  *  transmitting.
2355523f11b5SSrinivas Kandagatla  *  Return value:
2356523f11b5SSrinivas Kandagatla  *  0 on success and an appropriate (-)ve integer as defined in errno.h
2357523f11b5SSrinivas Kandagatla  *  file on failure.
2358523f11b5SSrinivas Kandagatla  */
2359fe131929SHuacai Chen static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
2360523f11b5SSrinivas Kandagatla {
2361523f11b5SSrinivas Kandagatla 	struct stmmac_priv *priv = netdev_priv(dev);
23623c55d4d0SJoao Pinto 	u32 rx_cnt = priv->plat->rx_queues_to_use;
2363146617b8SJoao Pinto 	u32 tx_cnt = priv->plat->tx_queues_to_use;
2364146617b8SJoao Pinto 	u32 chan;
2365523f11b5SSrinivas Kandagatla 	int ret;
2366523f11b5SSrinivas Kandagatla 
2367523f11b5SSrinivas Kandagatla 	/* DMA initialization and SW reset */
2368523f11b5SSrinivas Kandagatla 	ret = stmmac_init_dma_engine(priv);
2369523f11b5SSrinivas Kandagatla 	if (ret < 0) {
237038ddc59dSLABBE Corentin 		netdev_err(priv->dev, "%s: DMA engine initialization failed\n",
237138ddc59dSLABBE Corentin 			   __func__);
2372523f11b5SSrinivas Kandagatla 		return ret;
2373523f11b5SSrinivas Kandagatla 	}
2374523f11b5SSrinivas Kandagatla 
2375523f11b5SSrinivas Kandagatla 	/* Copy the MAC addr into the HW  */
23767ed24bbeSVince Bridgers 	priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0);
2377523f11b5SSrinivas Kandagatla 
237802e57b9dSGiuseppe CAVALLARO 	/* PS and related bits will be programmed according to the speed */
237902e57b9dSGiuseppe CAVALLARO 	if (priv->hw->pcs) {
238002e57b9dSGiuseppe CAVALLARO 		int speed = priv->plat->mac_port_sel_speed;
238102e57b9dSGiuseppe CAVALLARO 
238202e57b9dSGiuseppe CAVALLARO 		if ((speed == SPEED_10) || (speed == SPEED_100) ||
238302e57b9dSGiuseppe CAVALLARO 		    (speed == SPEED_1000)) {
238402e57b9dSGiuseppe CAVALLARO 			priv->hw->ps = speed;
238502e57b9dSGiuseppe CAVALLARO 		} else {
238602e57b9dSGiuseppe CAVALLARO 			dev_warn(priv->device, "invalid port speed\n");
238702e57b9dSGiuseppe CAVALLARO 			priv->hw->ps = 0;
238802e57b9dSGiuseppe CAVALLARO 		}
238902e57b9dSGiuseppe CAVALLARO 	}
239002e57b9dSGiuseppe CAVALLARO 
2391523f11b5SSrinivas Kandagatla 	/* Initialize the MAC Core */
23927ed24bbeSVince Bridgers 	priv->hw->mac->core_init(priv->hw, dev->mtu);
2393523f11b5SSrinivas Kandagatla 
2394d0a9c9f9SJoao Pinto 	/* Initialize MTL*/
2395d0a9c9f9SJoao Pinto 	if (priv->synopsys_id >= DWMAC_CORE_4_00)
2396d0a9c9f9SJoao Pinto 		stmmac_mtl_configuration(priv);
23979eb12474Sjpinto 
2398978aded4SGiuseppe CAVALLARO 	ret = priv->hw->mac->rx_ipc(priv->hw);
2399978aded4SGiuseppe CAVALLARO 	if (!ret) {
240038ddc59dSLABBE Corentin 		netdev_warn(priv->dev, "RX IPC Checksum Offload disabled\n");
2401978aded4SGiuseppe CAVALLARO 		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
2402d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
2403978aded4SGiuseppe CAVALLARO 	}
2404978aded4SGiuseppe CAVALLARO 
2405523f11b5SSrinivas Kandagatla 	/* Enable the MAC Rx/Tx */
2406270c7759SLABBE Corentin 	priv->hw->mac->set_mac(priv->ioaddr, true);
2407523f11b5SSrinivas Kandagatla 
2408b4f0a661SJoao Pinto 	/* Set the HW DMA mode and the COE */
2409b4f0a661SJoao Pinto 	stmmac_dma_operation_mode(priv);
2410b4f0a661SJoao Pinto 
2411523f11b5SSrinivas Kandagatla 	stmmac_mmc_setup(priv);
2412523f11b5SSrinivas Kandagatla 
2413fe131929SHuacai Chen 	if (init_ptp) {
24140ad2be79SThierry Reding 		ret = clk_prepare_enable(priv->plat->clk_ptp_ref);
24150ad2be79SThierry Reding 		if (ret < 0)
24160ad2be79SThierry Reding 			netdev_warn(priv->dev, "failed to enable PTP reference clock: %d\n", ret);
24170ad2be79SThierry Reding 
2418523f11b5SSrinivas Kandagatla 		ret = stmmac_init_ptp(priv);
2419722eef28SHeiner Kallweit 		if (ret == -EOPNOTSUPP)
2420722eef28SHeiner Kallweit 			netdev_warn(priv->dev, "PTP not supported by HW\n");
2421722eef28SHeiner Kallweit 		else if (ret)
2422722eef28SHeiner Kallweit 			netdev_warn(priv->dev, "PTP init failed\n");
2423fe131929SHuacai Chen 	}
2424523f11b5SSrinivas Kandagatla 
242550fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
2426523f11b5SSrinivas Kandagatla 	ret = stmmac_init_fs(dev);
2427523f11b5SSrinivas Kandagatla 	if (ret < 0)
242838ddc59dSLABBE Corentin 		netdev_warn(priv->dev, "%s: failed debugFS registration\n",
242938ddc59dSLABBE Corentin 			    __func__);
2430523f11b5SSrinivas Kandagatla #endif
2431523f11b5SSrinivas Kandagatla 	/* Start the ball rolling... */
2432ae4f0d46SJoao Pinto 	stmmac_start_all_dma(priv);
2433523f11b5SSrinivas Kandagatla 
2434523f11b5SSrinivas Kandagatla 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
2435523f11b5SSrinivas Kandagatla 
2436523f11b5SSrinivas Kandagatla 	if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
2437523f11b5SSrinivas Kandagatla 		priv->rx_riwt = MAX_DMA_RIWT;
24383c55d4d0SJoao Pinto 		priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT, rx_cnt);
2439523f11b5SSrinivas Kandagatla 	}
2440523f11b5SSrinivas Kandagatla 
24413fe5cadbSGiuseppe CAVALLARO 	if (priv->hw->pcs && priv->hw->mac->pcs_ctrl_ane)
244202e57b9dSGiuseppe CAVALLARO 		priv->hw->mac->pcs_ctrl_ane(priv->hw, 1, priv->hw->ps, 0);
2443523f11b5SSrinivas Kandagatla 
24444854ab99SJoao Pinto 	/* set TX and RX rings length */
24454854ab99SJoao Pinto 	stmmac_set_rings_length(priv);
24464854ab99SJoao Pinto 
2447f748be53SAlexandre TORGUE 	/* Enable TSO */
2448146617b8SJoao Pinto 	if (priv->tso) {
2449146617b8SJoao Pinto 		for (chan = 0; chan < tx_cnt; chan++)
2450146617b8SJoao Pinto 			priv->hw->dma->enable_tso(priv->ioaddr, 1, chan);
2451146617b8SJoao Pinto 	}
2452f748be53SAlexandre TORGUE 
2453523f11b5SSrinivas Kandagatla 	return 0;
2454523f11b5SSrinivas Kandagatla }
2455523f11b5SSrinivas Kandagatla 
2456c66f6c37SThierry Reding static void stmmac_hw_teardown(struct net_device *dev)
2457c66f6c37SThierry Reding {
2458c66f6c37SThierry Reding 	struct stmmac_priv *priv = netdev_priv(dev);
2459c66f6c37SThierry Reding 
2460c66f6c37SThierry Reding 	clk_disable_unprepare(priv->plat->clk_ptp_ref);
2461c66f6c37SThierry Reding }
2462c66f6c37SThierry Reding 
2463523f11b5SSrinivas Kandagatla /**
24647ac6653aSJeff Kirsher  *  stmmac_open - open entry point of the driver
24657ac6653aSJeff Kirsher  *  @dev : pointer to the device structure.
24667ac6653aSJeff Kirsher  *  Description:
24677ac6653aSJeff Kirsher  *  This function is the open entry point of the driver.
24687ac6653aSJeff Kirsher  *  Return value:
24697ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
24707ac6653aSJeff Kirsher  *  file on failure.
24717ac6653aSJeff Kirsher  */
24727ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev)
24737ac6653aSJeff Kirsher {
24747ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
24757ac6653aSJeff Kirsher 	int ret;
24767ac6653aSJeff Kirsher 
24774bfcbd7aSFrancesco Virlinzi 	stmmac_check_ether_addr(priv);
24784bfcbd7aSFrancesco Virlinzi 
24793fe5cadbSGiuseppe CAVALLARO 	if (priv->hw->pcs != STMMAC_PCS_RGMII &&
24803fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_TBI &&
24813fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_RTBI) {
24827ac6653aSJeff Kirsher 		ret = stmmac_init_phy(dev);
2483e58bb43fSGiuseppe CAVALLARO 		if (ret) {
248438ddc59dSLABBE Corentin 			netdev_err(priv->dev,
248538ddc59dSLABBE Corentin 				   "%s: Cannot attach to PHY (error: %d)\n",
2486e58bb43fSGiuseppe CAVALLARO 				   __func__, ret);
248789df20d9SHans de Goede 			return ret;
24887ac6653aSJeff Kirsher 		}
2489e58bb43fSGiuseppe CAVALLARO 	}
24907ac6653aSJeff Kirsher 
2491523f11b5SSrinivas Kandagatla 	/* Extra statistics */
2492523f11b5SSrinivas Kandagatla 	memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
2493523f11b5SSrinivas Kandagatla 	priv->xstats.threshold = tc;
2494523f11b5SSrinivas Kandagatla 
24955bacd778SLABBE Corentin 	priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
249622ad3838SGiuseppe Cavallaro 	priv->rx_copybreak = STMMAC_RX_COPYBREAK;
249756329137SBartlomiej Zolnierkiewicz 
24985bacd778SLABBE Corentin 	ret = alloc_dma_desc_resources(priv);
24995bacd778SLABBE Corentin 	if (ret < 0) {
25005bacd778SLABBE Corentin 		netdev_err(priv->dev, "%s: DMA descriptors allocation failed\n",
25015bacd778SLABBE Corentin 			   __func__);
25025bacd778SLABBE Corentin 		goto dma_desc_error;
25035bacd778SLABBE Corentin 	}
25045bacd778SLABBE Corentin 
25055bacd778SLABBE Corentin 	ret = init_dma_desc_rings(dev, GFP_KERNEL);
25065bacd778SLABBE Corentin 	if (ret < 0) {
25075bacd778SLABBE Corentin 		netdev_err(priv->dev, "%s: DMA descriptors initialization failed\n",
25085bacd778SLABBE Corentin 			   __func__);
25095bacd778SLABBE Corentin 		goto init_error;
25105bacd778SLABBE Corentin 	}
25115bacd778SLABBE Corentin 
2512fe131929SHuacai Chen 	ret = stmmac_hw_setup(dev, true);
251356329137SBartlomiej Zolnierkiewicz 	if (ret < 0) {
251438ddc59dSLABBE Corentin 		netdev_err(priv->dev, "%s: Hw setup failed\n", __func__);
2515c9324d18SGiuseppe CAVALLARO 		goto init_error;
25167ac6653aSJeff Kirsher 	}
25177ac6653aSJeff Kirsher 
2518777da230SGiuseppe CAVALLARO 	stmmac_init_tx_coalesce(priv);
2519777da230SGiuseppe CAVALLARO 
2520d6d50c7eSPhilippe Reynes 	if (dev->phydev)
2521d6d50c7eSPhilippe Reynes 		phy_start(dev->phydev);
25227ac6653aSJeff Kirsher 
25237ac6653aSJeff Kirsher 	/* Request the IRQ lines */
25247ac6653aSJeff Kirsher 	ret = request_irq(dev->irq, stmmac_interrupt,
25257ac6653aSJeff Kirsher 			  IRQF_SHARED, dev->name, dev);
25267ac6653aSJeff Kirsher 	if (unlikely(ret < 0)) {
252738ddc59dSLABBE Corentin 		netdev_err(priv->dev,
252838ddc59dSLABBE Corentin 			   "%s: ERROR: allocating the IRQ %d (error: %d)\n",
25297ac6653aSJeff Kirsher 			   __func__, dev->irq, ret);
25306c1e5abeSThierry Reding 		goto irq_error;
25317ac6653aSJeff Kirsher 	}
25327ac6653aSJeff Kirsher 
25337a13f8f5SFrancesco Virlinzi 	/* Request the Wake IRQ in case of another line is used for WoL */
25347a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq) {
25357a13f8f5SFrancesco Virlinzi 		ret = request_irq(priv->wol_irq, stmmac_interrupt,
25367a13f8f5SFrancesco Virlinzi 				  IRQF_SHARED, dev->name, dev);
25377a13f8f5SFrancesco Virlinzi 		if (unlikely(ret < 0)) {
253838ddc59dSLABBE Corentin 			netdev_err(priv->dev,
253938ddc59dSLABBE Corentin 				   "%s: ERROR: allocating the WoL IRQ %d (%d)\n",
2540ceb69499SGiuseppe CAVALLARO 				   __func__, priv->wol_irq, ret);
2541c9324d18SGiuseppe CAVALLARO 			goto wolirq_error;
25427a13f8f5SFrancesco Virlinzi 		}
25437a13f8f5SFrancesco Virlinzi 	}
25447a13f8f5SFrancesco Virlinzi 
2545d765955dSGiuseppe CAVALLARO 	/* Request the IRQ lines */
2546d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0) {
2547d765955dSGiuseppe CAVALLARO 		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
2548d765955dSGiuseppe CAVALLARO 				  dev->name, dev);
2549d765955dSGiuseppe CAVALLARO 		if (unlikely(ret < 0)) {
255038ddc59dSLABBE Corentin 			netdev_err(priv->dev,
255138ddc59dSLABBE Corentin 				   "%s: ERROR: allocating the LPI IRQ %d (%d)\n",
2552d765955dSGiuseppe CAVALLARO 				   __func__, priv->lpi_irq, ret);
2553c9324d18SGiuseppe CAVALLARO 			goto lpiirq_error;
2554d765955dSGiuseppe CAVALLARO 		}
2555d765955dSGiuseppe CAVALLARO 	}
2556d765955dSGiuseppe CAVALLARO 
25575bacd778SLABBE Corentin 	napi_enable(&priv->napi);
25585bacd778SLABBE Corentin 	netif_start_queue(dev);
25597ac6653aSJeff Kirsher 
25607ac6653aSJeff Kirsher 	return 0;
25617ac6653aSJeff Kirsher 
2562c9324d18SGiuseppe CAVALLARO lpiirq_error:
2563d765955dSGiuseppe CAVALLARO 	if (priv->wol_irq != dev->irq)
2564d765955dSGiuseppe CAVALLARO 		free_irq(priv->wol_irq, dev);
2565c9324d18SGiuseppe CAVALLARO wolirq_error:
25667a13f8f5SFrancesco Virlinzi 	free_irq(dev->irq, dev);
25676c1e5abeSThierry Reding irq_error:
25686c1e5abeSThierry Reding 	if (dev->phydev)
25696c1e5abeSThierry Reding 		phy_stop(dev->phydev);
25707a13f8f5SFrancesco Virlinzi 
25716c1e5abeSThierry Reding 	del_timer_sync(&priv->txtimer);
2572c66f6c37SThierry Reding 	stmmac_hw_teardown(dev);
2573c9324d18SGiuseppe CAVALLARO init_error:
2574c9324d18SGiuseppe CAVALLARO 	free_dma_desc_resources(priv);
25755bacd778SLABBE Corentin dma_desc_error:
2576d6d50c7eSPhilippe Reynes 	if (dev->phydev)
2577d6d50c7eSPhilippe Reynes 		phy_disconnect(dev->phydev);
25784bfcbd7aSFrancesco Virlinzi 
25797ac6653aSJeff Kirsher 	return ret;
25807ac6653aSJeff Kirsher }
25817ac6653aSJeff Kirsher 
25827ac6653aSJeff Kirsher /**
25837ac6653aSJeff Kirsher  *  stmmac_release - close entry point of the driver
25847ac6653aSJeff Kirsher  *  @dev : device pointer.
25857ac6653aSJeff Kirsher  *  Description:
25867ac6653aSJeff Kirsher  *  This is the stop entry point of the driver.
25877ac6653aSJeff Kirsher  */
25887ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev)
25897ac6653aSJeff Kirsher {
25907ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
25917ac6653aSJeff Kirsher 
2592d765955dSGiuseppe CAVALLARO 	if (priv->eee_enabled)
2593d765955dSGiuseppe CAVALLARO 		del_timer_sync(&priv->eee_ctrl_timer);
2594d765955dSGiuseppe CAVALLARO 
25957ac6653aSJeff Kirsher 	/* Stop and disconnect the PHY */
2596d6d50c7eSPhilippe Reynes 	if (dev->phydev) {
2597d6d50c7eSPhilippe Reynes 		phy_stop(dev->phydev);
2598d6d50c7eSPhilippe Reynes 		phy_disconnect(dev->phydev);
25997ac6653aSJeff Kirsher 	}
26007ac6653aSJeff Kirsher 
26015bacd778SLABBE Corentin 	netif_stop_queue(dev);
26027ac6653aSJeff Kirsher 
26035bacd778SLABBE Corentin 	napi_disable(&priv->napi);
26047ac6653aSJeff Kirsher 
26059125cdd1SGiuseppe CAVALLARO 	del_timer_sync(&priv->txtimer);
26069125cdd1SGiuseppe CAVALLARO 
26077ac6653aSJeff Kirsher 	/* Free the IRQ lines */
26087ac6653aSJeff Kirsher 	free_irq(dev->irq, dev);
26097a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq)
26107a13f8f5SFrancesco Virlinzi 		free_irq(priv->wol_irq, dev);
2611d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0)
2612d765955dSGiuseppe CAVALLARO 		free_irq(priv->lpi_irq, dev);
26137ac6653aSJeff Kirsher 
26147ac6653aSJeff Kirsher 	/* Stop TX/RX DMA and clear the descriptors */
2615ae4f0d46SJoao Pinto 	stmmac_stop_all_dma(priv);
26167ac6653aSJeff Kirsher 
26177ac6653aSJeff Kirsher 	/* Release and free the Rx/Tx resources */
26187ac6653aSJeff Kirsher 	free_dma_desc_resources(priv);
26197ac6653aSJeff Kirsher 
26207ac6653aSJeff Kirsher 	/* Disable the MAC Rx/Tx */
2621270c7759SLABBE Corentin 	priv->hw->mac->set_mac(priv->ioaddr, false);
26227ac6653aSJeff Kirsher 
26237ac6653aSJeff Kirsher 	netif_carrier_off(dev);
26247ac6653aSJeff Kirsher 
262550fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
2626466c5ac8SMathieu Olivari 	stmmac_exit_fs(dev);
2627bfab27a1SGiuseppe CAVALLARO #endif
2628bfab27a1SGiuseppe CAVALLARO 
262992ba6888SRayagond Kokatanur 	stmmac_release_ptp(priv);
263092ba6888SRayagond Kokatanur 
26317ac6653aSJeff Kirsher 	return 0;
26327ac6653aSJeff Kirsher }
26337ac6653aSJeff Kirsher 
26347ac6653aSJeff Kirsher /**
2635f748be53SAlexandre TORGUE  *  stmmac_tso_allocator - close entry point of the driver
2636f748be53SAlexandre TORGUE  *  @priv: driver private structure
2637f748be53SAlexandre TORGUE  *  @des: buffer start address
2638f748be53SAlexandre TORGUE  *  @total_len: total length to fill in descriptors
2639f748be53SAlexandre TORGUE  *  @last_segmant: condition for the last descriptor
2640ce736788SJoao Pinto  *  @queue: TX queue index
2641f748be53SAlexandre TORGUE  *  Description:
2642f748be53SAlexandre TORGUE  *  This function fills descriptor and request new descriptors according to
2643f748be53SAlexandre TORGUE  *  buffer length to fill
2644f748be53SAlexandre TORGUE  */
2645f748be53SAlexandre TORGUE static void stmmac_tso_allocator(struct stmmac_priv *priv, unsigned int des,
2646ce736788SJoao Pinto 				 int total_len, bool last_segment, u32 queue)
2647f748be53SAlexandre TORGUE {
2648ce736788SJoao Pinto 	struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
2649f748be53SAlexandre TORGUE 	struct dma_desc *desc;
26505bacd778SLABBE Corentin 	u32 buff_size;
2651ce736788SJoao Pinto 	int tmp_len;
2652f748be53SAlexandre TORGUE 
2653f748be53SAlexandre TORGUE 	tmp_len = total_len;
2654f748be53SAlexandre TORGUE 
2655f748be53SAlexandre TORGUE 	while (tmp_len > 0) {
2656ce736788SJoao Pinto 		tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE);
2657ce736788SJoao Pinto 		desc = tx_q->dma_tx + tx_q->cur_tx;
2658f748be53SAlexandre TORGUE 
2659f8be0d78SMichael Weiser 		desc->des0 = cpu_to_le32(des + (total_len - tmp_len));
2660f748be53SAlexandre TORGUE 		buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ?
2661f748be53SAlexandre TORGUE 			    TSO_MAX_BUFF_SIZE : tmp_len;
2662f748be53SAlexandre TORGUE 
2663f748be53SAlexandre TORGUE 		priv->hw->desc->prepare_tso_tx_desc(desc, 0, buff_size,
2664f748be53SAlexandre TORGUE 			0, 1,
2665f748be53SAlexandre TORGUE 			(last_segment) && (buff_size < TSO_MAX_BUFF_SIZE),
2666f748be53SAlexandre TORGUE 			0, 0);
2667f748be53SAlexandre TORGUE 
2668f748be53SAlexandre TORGUE 		tmp_len -= TSO_MAX_BUFF_SIZE;
2669f748be53SAlexandre TORGUE 	}
2670f748be53SAlexandre TORGUE }
2671f748be53SAlexandre TORGUE 
2672f748be53SAlexandre TORGUE /**
2673f748be53SAlexandre TORGUE  *  stmmac_tso_xmit - Tx entry point of the driver for oversized frames (TSO)
2674f748be53SAlexandre TORGUE  *  @skb : the socket buffer
2675f748be53SAlexandre TORGUE  *  @dev : device pointer
2676f748be53SAlexandre TORGUE  *  Description: this is the transmit function that is called on TSO frames
2677f748be53SAlexandre TORGUE  *  (support available on GMAC4 and newer chips).
2678f748be53SAlexandre TORGUE  *  Diagram below show the ring programming in case of TSO frames:
2679f748be53SAlexandre TORGUE  *
2680f748be53SAlexandre TORGUE  *  First Descriptor
2681f748be53SAlexandre TORGUE  *   --------
2682f748be53SAlexandre TORGUE  *   | DES0 |---> buffer1 = L2/L3/L4 header
2683f748be53SAlexandre TORGUE  *   | DES1 |---> TCP Payload (can continue on next descr...)
2684f748be53SAlexandre TORGUE  *   | DES2 |---> buffer 1 and 2 len
2685f748be53SAlexandre TORGUE  *   | DES3 |---> must set TSE, TCP hdr len-> [22:19]. TCP payload len [17:0]
2686f748be53SAlexandre TORGUE  *   --------
2687f748be53SAlexandre TORGUE  *	|
2688f748be53SAlexandre TORGUE  *     ...
2689f748be53SAlexandre TORGUE  *	|
2690f748be53SAlexandre TORGUE  *   --------
2691f748be53SAlexandre TORGUE  *   | DES0 | --| Split TCP Payload on Buffers 1 and 2
2692f748be53SAlexandre TORGUE  *   | DES1 | --|
2693f748be53SAlexandre TORGUE  *   | DES2 | --> buffer 1 and 2 len
2694f748be53SAlexandre TORGUE  *   | DES3 |
2695f748be53SAlexandre TORGUE  *   --------
2696f748be53SAlexandre TORGUE  *
2697f748be53SAlexandre TORGUE  * mss is fixed when enable tso, so w/o programming the TDES3 ctx field.
2698f748be53SAlexandre TORGUE  */
2699f748be53SAlexandre TORGUE static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
2700f748be53SAlexandre TORGUE {
2701ce736788SJoao Pinto 	struct dma_desc *desc, *first, *mss_desc = NULL;
2702f748be53SAlexandre TORGUE 	struct stmmac_priv *priv = netdev_priv(dev);
2703f748be53SAlexandre TORGUE 	int nfrags = skb_shinfo(skb)->nr_frags;
2704ce736788SJoao Pinto 	u32 queue = skb_get_queue_mapping(skb);
2705f748be53SAlexandre TORGUE 	unsigned int first_entry, des;
2706ce736788SJoao Pinto 	struct stmmac_tx_queue *tx_q;
2707ce736788SJoao Pinto 	int tmp_pay_len = 0;
2708ce736788SJoao Pinto 	u32 pay_len, mss;
2709f748be53SAlexandre TORGUE 	u8 proto_hdr_len;
2710f748be53SAlexandre TORGUE 	int i;
2711f748be53SAlexandre TORGUE 
2712ce736788SJoao Pinto 	tx_q = &priv->tx_queue[queue];
2713ce736788SJoao Pinto 
2714f748be53SAlexandre TORGUE 	/* Compute header lengths */
2715f748be53SAlexandre TORGUE 	proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb);
2716f748be53SAlexandre TORGUE 
2717f748be53SAlexandre TORGUE 	/* Desc availability based on threshold should be enough safe */
2718ce736788SJoao Pinto 	if (unlikely(stmmac_tx_avail(priv, queue) <
2719f748be53SAlexandre TORGUE 		(((skb->len - proto_hdr_len) / TSO_MAX_BUFF_SIZE + 1)))) {
27205bacd778SLABBE Corentin 		if (!netif_queue_stopped(dev)) {
27215bacd778SLABBE Corentin 			netif_stop_queue(dev);
2722f748be53SAlexandre TORGUE 			/* This is a hard error, log it. */
272338ddc59dSLABBE Corentin 			netdev_err(priv->dev,
272438ddc59dSLABBE Corentin 				   "%s: Tx Ring full when queue awake\n",
272538ddc59dSLABBE Corentin 				   __func__);
2726f748be53SAlexandre TORGUE 		}
2727f748be53SAlexandre TORGUE 		return NETDEV_TX_BUSY;
2728f748be53SAlexandre TORGUE 	}
2729f748be53SAlexandre TORGUE 
2730f748be53SAlexandre TORGUE 	pay_len = skb_headlen(skb) - proto_hdr_len; /* no frags */
2731f748be53SAlexandre TORGUE 
2732f748be53SAlexandre TORGUE 	mss = skb_shinfo(skb)->gso_size;
2733f748be53SAlexandre TORGUE 
2734f748be53SAlexandre TORGUE 	/* set new MSS value if needed */
2735f748be53SAlexandre TORGUE 	if (mss != priv->mss) {
2736ce736788SJoao Pinto 		mss_desc = tx_q->dma_tx + tx_q->cur_tx;
2737f748be53SAlexandre TORGUE 		priv->hw->desc->set_mss(mss_desc, mss);
2738f748be53SAlexandre TORGUE 		priv->mss = mss;
2739ce736788SJoao Pinto 		tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE);
2740f748be53SAlexandre TORGUE 	}
2741f748be53SAlexandre TORGUE 
2742f748be53SAlexandre TORGUE 	if (netif_msg_tx_queued(priv)) {
2743f748be53SAlexandre TORGUE 		pr_info("%s: tcphdrlen %d, hdr_len %d, pay_len %d, mss %d\n",
2744f748be53SAlexandre TORGUE 			__func__, tcp_hdrlen(skb), proto_hdr_len, pay_len, mss);
2745f748be53SAlexandre TORGUE 		pr_info("\tskb->len %d, skb->data_len %d\n", skb->len,
2746f748be53SAlexandre TORGUE 			skb->data_len);
2747f748be53SAlexandre TORGUE 	}
2748f748be53SAlexandre TORGUE 
2749ce736788SJoao Pinto 	first_entry = tx_q->cur_tx;
2750f748be53SAlexandre TORGUE 
2751ce736788SJoao Pinto 	desc = tx_q->dma_tx + first_entry;
2752f748be53SAlexandre TORGUE 	first = desc;
2753f748be53SAlexandre TORGUE 
2754f748be53SAlexandre TORGUE 	/* first descriptor: fill Headers on Buf1 */
2755f748be53SAlexandre TORGUE 	des = dma_map_single(priv->device, skb->data, skb_headlen(skb),
2756f748be53SAlexandre TORGUE 			     DMA_TO_DEVICE);
2757f748be53SAlexandre TORGUE 	if (dma_mapping_error(priv->device, des))
2758f748be53SAlexandre TORGUE 		goto dma_map_err;
2759f748be53SAlexandre TORGUE 
2760ce736788SJoao Pinto 	tx_q->tx_skbuff_dma[first_entry].buf = des;
2761ce736788SJoao Pinto 	tx_q->tx_skbuff_dma[first_entry].len = skb_headlen(skb);
2762ce736788SJoao Pinto 	tx_q->tx_skbuff[first_entry] = skb;
2763f748be53SAlexandre TORGUE 
2764f8be0d78SMichael Weiser 	first->des0 = cpu_to_le32(des);
2765f748be53SAlexandre TORGUE 
2766f748be53SAlexandre TORGUE 	/* Fill start of payload in buff2 of first descriptor */
2767f748be53SAlexandre TORGUE 	if (pay_len)
2768f8be0d78SMichael Weiser 		first->des1 = cpu_to_le32(des + proto_hdr_len);
2769f748be53SAlexandre TORGUE 
2770f748be53SAlexandre TORGUE 	/* If needed take extra descriptors to fill the remaining payload */
2771f748be53SAlexandre TORGUE 	tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE;
2772f748be53SAlexandre TORGUE 
2773ce736788SJoao Pinto 	stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue);
2774f748be53SAlexandre TORGUE 
2775f748be53SAlexandre TORGUE 	/* Prepare fragments */
2776f748be53SAlexandre TORGUE 	for (i = 0; i < nfrags; i++) {
2777f748be53SAlexandre TORGUE 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
2778f748be53SAlexandre TORGUE 
2779f748be53SAlexandre TORGUE 		des = skb_frag_dma_map(priv->device, frag, 0,
2780f748be53SAlexandre TORGUE 				       skb_frag_size(frag),
2781f748be53SAlexandre TORGUE 				       DMA_TO_DEVICE);
2782937071c1SThierry Reding 		if (dma_mapping_error(priv->device, des))
2783937071c1SThierry Reding 			goto dma_map_err;
2784f748be53SAlexandre TORGUE 
2785f748be53SAlexandre TORGUE 		stmmac_tso_allocator(priv, des, skb_frag_size(frag),
2786ce736788SJoao Pinto 				     (i == nfrags - 1), queue);
2787f748be53SAlexandre TORGUE 
2788ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[tx_q->cur_tx].buf = des;
2789ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[tx_q->cur_tx].len = skb_frag_size(frag);
2790ce736788SJoao Pinto 		tx_q->tx_skbuff[tx_q->cur_tx] = NULL;
2791ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[tx_q->cur_tx].map_as_page = true;
2792f748be53SAlexandre TORGUE 	}
2793f748be53SAlexandre TORGUE 
2794ce736788SJoao Pinto 	tx_q->tx_skbuff_dma[tx_q->cur_tx].last_segment = true;
2795f748be53SAlexandre TORGUE 
2796ce736788SJoao Pinto 	tx_q->cur_tx = STMMAC_GET_ENTRY(tx_q->cur_tx, DMA_TX_SIZE);
2797f748be53SAlexandre TORGUE 
2798ce736788SJoao Pinto 	if (unlikely(stmmac_tx_avail(priv, queue) <= (MAX_SKB_FRAGS + 1))) {
2799b3e51069SLABBE Corentin 		netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n",
280038ddc59dSLABBE Corentin 			  __func__);
28015bacd778SLABBE Corentin 		netif_stop_queue(dev);
2802f748be53SAlexandre TORGUE 	}
2803f748be53SAlexandre TORGUE 
2804f748be53SAlexandre TORGUE 	dev->stats.tx_bytes += skb->len;
2805f748be53SAlexandre TORGUE 	priv->xstats.tx_tso_frames++;
2806f748be53SAlexandre TORGUE 	priv->xstats.tx_tso_nfrags += nfrags;
2807f748be53SAlexandre TORGUE 
2808f748be53SAlexandre TORGUE 	/* Manage tx mitigation */
2809f748be53SAlexandre TORGUE 	priv->tx_count_frames += nfrags + 1;
2810f748be53SAlexandre TORGUE 	if (likely(priv->tx_coal_frames > priv->tx_count_frames)) {
2811f748be53SAlexandre TORGUE 		mod_timer(&priv->txtimer,
2812f748be53SAlexandre TORGUE 			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
2813f748be53SAlexandre TORGUE 	} else {
2814f748be53SAlexandre TORGUE 		priv->tx_count_frames = 0;
2815f748be53SAlexandre TORGUE 		priv->hw->desc->set_tx_ic(desc);
2816f748be53SAlexandre TORGUE 		priv->xstats.tx_set_ic_bit++;
2817f748be53SAlexandre TORGUE 	}
2818f748be53SAlexandre TORGUE 
2819f748be53SAlexandre TORGUE 	if (!priv->hwts_tx_en)
2820f748be53SAlexandre TORGUE 		skb_tx_timestamp(skb);
2821f748be53SAlexandre TORGUE 
2822f748be53SAlexandre TORGUE 	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
2823f748be53SAlexandre TORGUE 		     priv->hwts_tx_en)) {
2824f748be53SAlexandre TORGUE 		/* declare that device is doing timestamping */
2825f748be53SAlexandre TORGUE 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
2826f748be53SAlexandre TORGUE 		priv->hw->desc->enable_tx_timestamp(first);
2827f748be53SAlexandre TORGUE 	}
2828f748be53SAlexandre TORGUE 
2829f748be53SAlexandre TORGUE 	/* Complete the first descriptor before granting the DMA */
2830f748be53SAlexandre TORGUE 	priv->hw->desc->prepare_tso_tx_desc(first, 1,
2831f748be53SAlexandre TORGUE 			proto_hdr_len,
2832f748be53SAlexandre TORGUE 			pay_len,
2833ce736788SJoao Pinto 			1, tx_q->tx_skbuff_dma[first_entry].last_segment,
2834f748be53SAlexandre TORGUE 			tcp_hdrlen(skb) / 4, (skb->len - proto_hdr_len));
2835f748be53SAlexandre TORGUE 
2836f748be53SAlexandre TORGUE 	/* If context desc is used to change MSS */
2837f748be53SAlexandre TORGUE 	if (mss_desc)
2838f748be53SAlexandre TORGUE 		priv->hw->desc->set_tx_owner(mss_desc);
2839f748be53SAlexandre TORGUE 
2840f748be53SAlexandre TORGUE 	/* The own bit must be the latest setting done when prepare the
2841f748be53SAlexandre TORGUE 	 * descriptor and then barrier is needed to make sure that
2842f748be53SAlexandre TORGUE 	 * all is coherent before granting the DMA engine.
2843f748be53SAlexandre TORGUE 	 */
2844ad688cdbSPavel Machek 	dma_wmb();
2845f748be53SAlexandre TORGUE 
2846f748be53SAlexandre TORGUE 	if (netif_msg_pktdata(priv)) {
2847f748be53SAlexandre TORGUE 		pr_info("%s: curr=%d dirty=%d f=%d, e=%d, f_p=%p, nfrags %d\n",
2848ce736788SJoao Pinto 			__func__, tx_q->cur_tx, tx_q->dirty_tx, first_entry,
2849ce736788SJoao Pinto 			tx_q->cur_tx, first, nfrags);
2850f748be53SAlexandre TORGUE 
2851ce736788SJoao Pinto 		priv->hw->desc->display_ring((void *)tx_q->dma_tx, DMA_TX_SIZE,
2852f748be53SAlexandre TORGUE 					     0);
2853f748be53SAlexandre TORGUE 
2854f748be53SAlexandre TORGUE 		pr_info(">>> frame to be transmitted: ");
2855f748be53SAlexandre TORGUE 		print_pkt(skb->data, skb_headlen(skb));
2856f748be53SAlexandre TORGUE 	}
2857f748be53SAlexandre TORGUE 
28585bacd778SLABBE Corentin 	netdev_sent_queue(dev, skb->len);
2859f748be53SAlexandre TORGUE 
2860ce736788SJoao Pinto 	priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, tx_q->tx_tail_addr,
2861ce736788SJoao Pinto 				       queue);
2862f748be53SAlexandre TORGUE 
2863f748be53SAlexandre TORGUE 	return NETDEV_TX_OK;
2864f748be53SAlexandre TORGUE 
2865f748be53SAlexandre TORGUE dma_map_err:
2866f748be53SAlexandre TORGUE 	dev_err(priv->device, "Tx dma map failed\n");
2867f748be53SAlexandre TORGUE 	dev_kfree_skb(skb);
2868f748be53SAlexandre TORGUE 	priv->dev->stats.tx_dropped++;
2869f748be53SAlexandre TORGUE 	return NETDEV_TX_OK;
2870f748be53SAlexandre TORGUE }
2871f748be53SAlexandre TORGUE 
2872f748be53SAlexandre TORGUE /**
2873732fdf0eSGiuseppe CAVALLARO  *  stmmac_xmit - Tx entry point of the driver
28747ac6653aSJeff Kirsher  *  @skb : the socket buffer
28757ac6653aSJeff Kirsher  *  @dev : device pointer
287632ceabcaSGiuseppe CAVALLARO  *  Description : this is the tx entry point of the driver.
287732ceabcaSGiuseppe CAVALLARO  *  It programs the chain or the ring and supports oversized frames
287832ceabcaSGiuseppe CAVALLARO  *  and SG feature.
28797ac6653aSJeff Kirsher  */
28807ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
28817ac6653aSJeff Kirsher {
28827ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
28830e80bdc9SGiuseppe Cavallaro 	unsigned int nopaged_len = skb_headlen(skb);
28844a7d666aSGiuseppe CAVALLARO 	int i, csum_insertion = 0, is_jumbo = 0;
2885ce736788SJoao Pinto 	u32 queue = skb_get_queue_mapping(skb);
28867ac6653aSJeff Kirsher 	int nfrags = skb_shinfo(skb)->nr_frags;
28870e80bdc9SGiuseppe Cavallaro 	unsigned int entry, first_entry;
28887ac6653aSJeff Kirsher 	struct dma_desc *desc, *first;
2889ce736788SJoao Pinto 	struct stmmac_tx_queue *tx_q;
28900e80bdc9SGiuseppe Cavallaro 	unsigned int enh_desc;
2891f748be53SAlexandre TORGUE 	unsigned int des;
2892f748be53SAlexandre TORGUE 
2893ce736788SJoao Pinto 	tx_q = &priv->tx_queue[queue];
2894ce736788SJoao Pinto 
2895f748be53SAlexandre TORGUE 	/* Manage oversized TCP frames for GMAC4 device */
2896f748be53SAlexandre TORGUE 	if (skb_is_gso(skb) && priv->tso) {
2897f748be53SAlexandre TORGUE 		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
2898f748be53SAlexandre TORGUE 			return stmmac_tso_xmit(skb, dev);
2899f748be53SAlexandre TORGUE 	}
29007ac6653aSJeff Kirsher 
2901ce736788SJoao Pinto 	if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) {
29025bacd778SLABBE Corentin 		if (!netif_queue_stopped(dev)) {
29035bacd778SLABBE Corentin 			netif_stop_queue(dev);
29047ac6653aSJeff Kirsher 			/* This is a hard error, log it. */
290538ddc59dSLABBE Corentin 			netdev_err(priv->dev,
290638ddc59dSLABBE Corentin 				   "%s: Tx Ring full when queue awake\n",
290738ddc59dSLABBE Corentin 				   __func__);
29087ac6653aSJeff Kirsher 		}
29097ac6653aSJeff Kirsher 		return NETDEV_TX_BUSY;
29107ac6653aSJeff Kirsher 	}
29117ac6653aSJeff Kirsher 
2912d765955dSGiuseppe CAVALLARO 	if (priv->tx_path_in_lpi_mode)
2913d765955dSGiuseppe CAVALLARO 		stmmac_disable_eee_mode(priv);
2914d765955dSGiuseppe CAVALLARO 
2915ce736788SJoao Pinto 	entry = tx_q->cur_tx;
29160e80bdc9SGiuseppe Cavallaro 	first_entry = entry;
29177ac6653aSJeff Kirsher 
29187ac6653aSJeff Kirsher 	csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
29197ac6653aSJeff Kirsher 
29200e80bdc9SGiuseppe Cavallaro 	if (likely(priv->extend_desc))
2921ce736788SJoao Pinto 		desc = (struct dma_desc *)(tx_q->dma_etx + entry);
2922c24602efSGiuseppe CAVALLARO 	else
2923ce736788SJoao Pinto 		desc = tx_q->dma_tx + entry;
2924c24602efSGiuseppe CAVALLARO 
29257ac6653aSJeff Kirsher 	first = desc;
29267ac6653aSJeff Kirsher 
2927ce736788SJoao Pinto 	tx_q->tx_skbuff[first_entry] = skb;
29280e80bdc9SGiuseppe Cavallaro 
29290e80bdc9SGiuseppe Cavallaro 	enh_desc = priv->plat->enh_desc;
29304a7d666aSGiuseppe CAVALLARO 	/* To program the descriptors according to the size of the frame */
293129896a67SGiuseppe CAVALLARO 	if (enh_desc)
293229896a67SGiuseppe CAVALLARO 		is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc);
293329896a67SGiuseppe CAVALLARO 
2934f748be53SAlexandre TORGUE 	if (unlikely(is_jumbo) && likely(priv->synopsys_id <
2935f748be53SAlexandre TORGUE 					 DWMAC_CORE_4_00)) {
2936ce736788SJoao Pinto 		entry = priv->hw->mode->jumbo_frm(tx_q, skb, csum_insertion);
2937362b37beSGiuseppe CAVALLARO 		if (unlikely(entry < 0))
2938362b37beSGiuseppe CAVALLARO 			goto dma_map_err;
293929896a67SGiuseppe CAVALLARO 	}
29407ac6653aSJeff Kirsher 
29417ac6653aSJeff Kirsher 	for (i = 0; i < nfrags; i++) {
29429e903e08SEric Dumazet 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
29439e903e08SEric Dumazet 		int len = skb_frag_size(frag);
2944be434d50SGiuseppe Cavallaro 		bool last_segment = (i == (nfrags - 1));
29457ac6653aSJeff Kirsher 
2946e3ad57c9SGiuseppe Cavallaro 		entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
2947e3ad57c9SGiuseppe Cavallaro 
29480e80bdc9SGiuseppe Cavallaro 		if (likely(priv->extend_desc))
2949ce736788SJoao Pinto 			desc = (struct dma_desc *)(tx_q->dma_etx + entry);
2950c24602efSGiuseppe CAVALLARO 		else
2951ce736788SJoao Pinto 			desc = tx_q->dma_tx + entry;
29527ac6653aSJeff Kirsher 
2953f748be53SAlexandre TORGUE 		des = skb_frag_dma_map(priv->device, frag, 0, len,
2954f722380dSIan Campbell 				       DMA_TO_DEVICE);
2955f748be53SAlexandre TORGUE 		if (dma_mapping_error(priv->device, des))
2956362b37beSGiuseppe CAVALLARO 			goto dma_map_err; /* should reuse desc w/o issues */
2957362b37beSGiuseppe CAVALLARO 
2958ce736788SJoao Pinto 		tx_q->tx_skbuff[entry] = NULL;
2959f748be53SAlexandre TORGUE 
2960ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[entry].buf = des;
2961f8be0d78SMichael Weiser 		if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
2962f8be0d78SMichael Weiser 			desc->des0 = cpu_to_le32(des);
2963f8be0d78SMichael Weiser 		else
2964f8be0d78SMichael Weiser 			desc->des2 = cpu_to_le32(des);
2965f748be53SAlexandre TORGUE 
2966ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[entry].map_as_page = true;
2967ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[entry].len = len;
2968ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[entry].last_segment = last_segment;
29690e80bdc9SGiuseppe Cavallaro 
29700e80bdc9SGiuseppe Cavallaro 		/* Prepare the descriptor and set the own bit too */
29714a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
2972be434d50SGiuseppe Cavallaro 						priv->mode, 1, last_segment);
29737ac6653aSJeff Kirsher 	}
29747ac6653aSJeff Kirsher 
2975e3ad57c9SGiuseppe Cavallaro 	entry = STMMAC_GET_ENTRY(entry, DMA_TX_SIZE);
2976e3ad57c9SGiuseppe Cavallaro 
2977ce736788SJoao Pinto 	tx_q->cur_tx = entry;
29787ac6653aSJeff Kirsher 
29797ac6653aSJeff Kirsher 	if (netif_msg_pktdata(priv)) {
2980d0225e7dSAlexandre TORGUE 		void *tx_head;
2981d0225e7dSAlexandre TORGUE 
298238ddc59dSLABBE Corentin 		netdev_dbg(priv->dev,
298338ddc59dSLABBE Corentin 			   "%s: curr=%d dirty=%d f=%d, e=%d, first=%p, nfrags=%d",
2984ce736788SJoao Pinto 			   __func__, tx_q->cur_tx, tx_q->dirty_tx, first_entry,
29850e80bdc9SGiuseppe Cavallaro 			   entry, first, nfrags);
298683d7af64SGiuseppe CAVALLARO 
2987c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2988ce736788SJoao Pinto 			tx_head = (void *)tx_q->dma_etx;
2989c24602efSGiuseppe CAVALLARO 		else
2990ce736788SJoao Pinto 			tx_head = (void *)tx_q->dma_tx;
2991d0225e7dSAlexandre TORGUE 
2992d0225e7dSAlexandre TORGUE 		priv->hw->desc->display_ring(tx_head, DMA_TX_SIZE, false);
2993c24602efSGiuseppe CAVALLARO 
299438ddc59dSLABBE Corentin 		netdev_dbg(priv->dev, ">>> frame to be transmitted: ");
29957ac6653aSJeff Kirsher 		print_pkt(skb->data, skb->len);
29967ac6653aSJeff Kirsher 	}
29970e80bdc9SGiuseppe Cavallaro 
2998ce736788SJoao Pinto 	if (unlikely(stmmac_tx_avail(priv, queue) <= (MAX_SKB_FRAGS + 1))) {
2999b3e51069SLABBE Corentin 		netif_dbg(priv, hw, priv->dev, "%s: stop transmitted packets\n",
3000b3e51069SLABBE Corentin 			  __func__);
30015bacd778SLABBE Corentin 		netif_stop_queue(dev);
30027ac6653aSJeff Kirsher 	}
30037ac6653aSJeff Kirsher 
30047ac6653aSJeff Kirsher 	dev->stats.tx_bytes += skb->len;
30057ac6653aSJeff Kirsher 
30060e80bdc9SGiuseppe Cavallaro 	/* According to the coalesce parameter the IC bit for the latest
30070e80bdc9SGiuseppe Cavallaro 	 * segment is reset and the timer re-started to clean the tx status.
30080e80bdc9SGiuseppe Cavallaro 	 * This approach takes care about the fragments: desc is the first
30090e80bdc9SGiuseppe Cavallaro 	 * element in case of no SG.
30100e80bdc9SGiuseppe Cavallaro 	 */
30110e80bdc9SGiuseppe Cavallaro 	priv->tx_count_frames += nfrags + 1;
30120e80bdc9SGiuseppe Cavallaro 	if (likely(priv->tx_coal_frames > priv->tx_count_frames)) {
30130e80bdc9SGiuseppe Cavallaro 		mod_timer(&priv->txtimer,
30140e80bdc9SGiuseppe Cavallaro 			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
30150e80bdc9SGiuseppe Cavallaro 	} else {
30160e80bdc9SGiuseppe Cavallaro 		priv->tx_count_frames = 0;
30170e80bdc9SGiuseppe Cavallaro 		priv->hw->desc->set_tx_ic(desc);
30180e80bdc9SGiuseppe Cavallaro 		priv->xstats.tx_set_ic_bit++;
30190e80bdc9SGiuseppe Cavallaro 	}
30200e80bdc9SGiuseppe Cavallaro 
30210e80bdc9SGiuseppe Cavallaro 	if (!priv->hwts_tx_en)
30220e80bdc9SGiuseppe Cavallaro 		skb_tx_timestamp(skb);
30230e80bdc9SGiuseppe Cavallaro 
30240e80bdc9SGiuseppe Cavallaro 	/* Ready to fill the first descriptor and set the OWN bit w/o any
30250e80bdc9SGiuseppe Cavallaro 	 * problems because all the descriptors are actually ready to be
30260e80bdc9SGiuseppe Cavallaro 	 * passed to the DMA engine.
30270e80bdc9SGiuseppe Cavallaro 	 */
30280e80bdc9SGiuseppe Cavallaro 	if (likely(!is_jumbo)) {
30290e80bdc9SGiuseppe Cavallaro 		bool last_segment = (nfrags == 0);
30300e80bdc9SGiuseppe Cavallaro 
3031f748be53SAlexandre TORGUE 		des = dma_map_single(priv->device, skb->data,
30320e80bdc9SGiuseppe Cavallaro 				     nopaged_len, DMA_TO_DEVICE);
3033f748be53SAlexandre TORGUE 		if (dma_mapping_error(priv->device, des))
30340e80bdc9SGiuseppe Cavallaro 			goto dma_map_err;
30350e80bdc9SGiuseppe Cavallaro 
3036ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[first_entry].buf = des;
3037f8be0d78SMichael Weiser 		if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
3038f8be0d78SMichael Weiser 			first->des0 = cpu_to_le32(des);
3039f8be0d78SMichael Weiser 		else
3040f8be0d78SMichael Weiser 			first->des2 = cpu_to_le32(des);
3041f748be53SAlexandre TORGUE 
3042ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[first_entry].len = nopaged_len;
3043ce736788SJoao Pinto 		tx_q->tx_skbuff_dma[first_entry].last_segment = last_segment;
30440e80bdc9SGiuseppe Cavallaro 
3045891434b1SRayagond Kokatanur 		if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
3046891434b1SRayagond Kokatanur 			     priv->hwts_tx_en)) {
3047891434b1SRayagond Kokatanur 			/* declare that device is doing timestamping */
3048891434b1SRayagond Kokatanur 			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
3049891434b1SRayagond Kokatanur 			priv->hw->desc->enable_tx_timestamp(first);
3050891434b1SRayagond Kokatanur 		}
3051891434b1SRayagond Kokatanur 
30520e80bdc9SGiuseppe Cavallaro 		/* Prepare the first descriptor setting the OWN bit too */
30530e80bdc9SGiuseppe Cavallaro 		priv->hw->desc->prepare_tx_desc(first, 1, nopaged_len,
30540e80bdc9SGiuseppe Cavallaro 						csum_insertion, priv->mode, 1,
30550e80bdc9SGiuseppe Cavallaro 						last_segment);
30560e80bdc9SGiuseppe Cavallaro 
30570e80bdc9SGiuseppe Cavallaro 		/* The own bit must be the latest setting done when prepare the
30580e80bdc9SGiuseppe Cavallaro 		 * descriptor and then barrier is needed to make sure that
30590e80bdc9SGiuseppe Cavallaro 		 * all is coherent before granting the DMA engine.
30600e80bdc9SGiuseppe Cavallaro 		 */
3061ad688cdbSPavel Machek 		dma_wmb();
30620e80bdc9SGiuseppe Cavallaro 	}
30637ac6653aSJeff Kirsher 
30645bacd778SLABBE Corentin 	netdev_sent_queue(dev, skb->len);
3065f748be53SAlexandre TORGUE 
3066f748be53SAlexandre TORGUE 	if (priv->synopsys_id < DWMAC_CORE_4_00)
30677ac6653aSJeff Kirsher 		priv->hw->dma->enable_dma_transmission(priv->ioaddr);
3068f748be53SAlexandre TORGUE 	else
3069ce736788SJoao Pinto 		priv->hw->dma->set_tx_tail_ptr(priv->ioaddr, tx_q->tx_tail_addr,
3070ce736788SJoao Pinto 					       queue);
30717ac6653aSJeff Kirsher 
3072362b37beSGiuseppe CAVALLARO 	return NETDEV_TX_OK;
3073a9097a96SGiuseppe CAVALLARO 
3074362b37beSGiuseppe CAVALLARO dma_map_err:
307538ddc59dSLABBE Corentin 	netdev_err(priv->dev, "Tx DMA map failed\n");
3076362b37beSGiuseppe CAVALLARO 	dev_kfree_skb(skb);
3077362b37beSGiuseppe CAVALLARO 	priv->dev->stats.tx_dropped++;
30787ac6653aSJeff Kirsher 	return NETDEV_TX_OK;
30797ac6653aSJeff Kirsher }
30807ac6653aSJeff Kirsher 
3081b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
3082b9381985SVince Bridgers {
3083b9381985SVince Bridgers 	struct ethhdr *ehdr;
3084b9381985SVince Bridgers 	u16 vlanid;
3085b9381985SVince Bridgers 
3086b9381985SVince Bridgers 	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
3087b9381985SVince Bridgers 	    NETIF_F_HW_VLAN_CTAG_RX &&
3088b9381985SVince Bridgers 	    !__vlan_get_tag(skb, &vlanid)) {
3089b9381985SVince Bridgers 		/* pop the vlan tag */
3090b9381985SVince Bridgers 		ehdr = (struct ethhdr *)skb->data;
3091b9381985SVince Bridgers 		memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
3092b9381985SVince Bridgers 		skb_pull(skb, VLAN_HLEN);
3093b9381985SVince Bridgers 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
3094b9381985SVince Bridgers 	}
3095b9381985SVince Bridgers }
3096b9381985SVince Bridgers 
3097b9381985SVince Bridgers 
309854139cf3SJoao Pinto static inline int stmmac_rx_threshold_count(struct stmmac_rx_queue *rx_q)
3099120e87f9SGiuseppe Cavallaro {
310054139cf3SJoao Pinto 	if (rx_q->rx_zeroc_thresh < STMMAC_RX_THRESH)
3101120e87f9SGiuseppe Cavallaro 		return 0;
3102120e87f9SGiuseppe Cavallaro 
3103120e87f9SGiuseppe Cavallaro 	return 1;
3104120e87f9SGiuseppe Cavallaro }
3105120e87f9SGiuseppe Cavallaro 
310632ceabcaSGiuseppe CAVALLARO /**
3107732fdf0eSGiuseppe CAVALLARO  * stmmac_rx_refill - refill used skb preallocated buffers
310832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
310954139cf3SJoao Pinto  * @queue: RX queue index
311032ceabcaSGiuseppe CAVALLARO  * Description : this is to reallocate the skb for the reception process
311132ceabcaSGiuseppe CAVALLARO  * that is based on zero-copy.
311232ceabcaSGiuseppe CAVALLARO  */
311354139cf3SJoao Pinto static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
31147ac6653aSJeff Kirsher {
311554139cf3SJoao Pinto 	struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
311654139cf3SJoao Pinto 	int dirty = stmmac_rx_dirty(priv, queue);
311754139cf3SJoao Pinto 	unsigned int entry = rx_q->dirty_rx;
311854139cf3SJoao Pinto 
31197ac6653aSJeff Kirsher 	int bfsize = priv->dma_buf_sz;
31207ac6653aSJeff Kirsher 
3121e3ad57c9SGiuseppe Cavallaro 	while (dirty-- > 0) {
3122c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
3123c24602efSGiuseppe CAVALLARO 
3124c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
312554139cf3SJoao Pinto 			p = (struct dma_desc *)(rx_q->dma_erx + entry);
3126c24602efSGiuseppe CAVALLARO 		else
312754139cf3SJoao Pinto 			p = rx_q->dma_rx + entry;
3128c24602efSGiuseppe CAVALLARO 
312954139cf3SJoao Pinto 		if (likely(!rx_q->rx_skbuff[entry])) {
31307ac6653aSJeff Kirsher 			struct sk_buff *skb;
31317ac6653aSJeff Kirsher 
3132acb600deSEric Dumazet 			skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
3133120e87f9SGiuseppe Cavallaro 			if (unlikely(!skb)) {
3134120e87f9SGiuseppe Cavallaro 				/* so for a while no zero-copy! */
313554139cf3SJoao Pinto 				rx_q->rx_zeroc_thresh = STMMAC_RX_THRESH;
3136120e87f9SGiuseppe Cavallaro 				if (unlikely(net_ratelimit()))
3137120e87f9SGiuseppe Cavallaro 					dev_err(priv->device,
3138120e87f9SGiuseppe Cavallaro 						"fail to alloc skb entry %d\n",
3139120e87f9SGiuseppe Cavallaro 						entry);
31407ac6653aSJeff Kirsher 				break;
3141120e87f9SGiuseppe Cavallaro 			}
31427ac6653aSJeff Kirsher 
314354139cf3SJoao Pinto 			rx_q->rx_skbuff[entry] = skb;
314454139cf3SJoao Pinto 			rx_q->rx_skbuff_dma[entry] =
31457ac6653aSJeff Kirsher 			    dma_map_single(priv->device, skb->data, bfsize,
31467ac6653aSJeff Kirsher 					   DMA_FROM_DEVICE);
3147362b37beSGiuseppe CAVALLARO 			if (dma_mapping_error(priv->device,
314854139cf3SJoao Pinto 					      rx_q->rx_skbuff_dma[entry])) {
314938ddc59dSLABBE Corentin 				netdev_err(priv->dev, "Rx DMA map failed\n");
3150362b37beSGiuseppe CAVALLARO 				dev_kfree_skb(skb);
3151362b37beSGiuseppe CAVALLARO 				break;
3152362b37beSGiuseppe CAVALLARO 			}
3153286a8372SGiuseppe CAVALLARO 
3154f748be53SAlexandre TORGUE 			if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00)) {
315554139cf3SJoao Pinto 				p->des0 = cpu_to_le32(rx_q->rx_skbuff_dma[entry]);
3156f748be53SAlexandre TORGUE 				p->des1 = 0;
3157f748be53SAlexandre TORGUE 			} else {
315854139cf3SJoao Pinto 				p->des2 = cpu_to_le32(rx_q->rx_skbuff_dma[entry]);
3159f748be53SAlexandre TORGUE 			}
3160f748be53SAlexandre TORGUE 			if (priv->hw->mode->refill_desc3)
316154139cf3SJoao Pinto 				priv->hw->mode->refill_desc3(rx_q, p);
3162286a8372SGiuseppe CAVALLARO 
316354139cf3SJoao Pinto 			if (rx_q->rx_zeroc_thresh > 0)
316454139cf3SJoao Pinto 				rx_q->rx_zeroc_thresh--;
3165120e87f9SGiuseppe Cavallaro 
3166b3e51069SLABBE Corentin 			netif_dbg(priv, rx_status, priv->dev,
316738ddc59dSLABBE Corentin 				  "refill entry #%d\n", entry);
31687ac6653aSJeff Kirsher 		}
3169ad688cdbSPavel Machek 		dma_wmb();
3170f748be53SAlexandre TORGUE 
3171f748be53SAlexandre TORGUE 		if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
3172f748be53SAlexandre TORGUE 			priv->hw->desc->init_rx_desc(p, priv->use_riwt, 0, 0);
3173f748be53SAlexandre TORGUE 		else
3174c24602efSGiuseppe CAVALLARO 			priv->hw->desc->set_rx_owner(p);
3175f748be53SAlexandre TORGUE 
3176ad688cdbSPavel Machek 		dma_wmb();
3177e3ad57c9SGiuseppe Cavallaro 
3178e3ad57c9SGiuseppe Cavallaro 		entry = STMMAC_GET_ENTRY(entry, DMA_RX_SIZE);
31797ac6653aSJeff Kirsher 	}
318054139cf3SJoao Pinto 	rx_q->dirty_rx = entry;
31817ac6653aSJeff Kirsher }
31827ac6653aSJeff Kirsher 
318332ceabcaSGiuseppe CAVALLARO /**
3184732fdf0eSGiuseppe CAVALLARO  * stmmac_rx - manage the receive process
318532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
318654139cf3SJoao Pinto  * @limit: napi bugget
318754139cf3SJoao Pinto  * @queue: RX queue index.
318832ceabcaSGiuseppe CAVALLARO  * Description :  this the function called by the napi poll method.
318932ceabcaSGiuseppe CAVALLARO  * It gets all the frames inside the ring.
319032ceabcaSGiuseppe CAVALLARO  */
319154139cf3SJoao Pinto static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
31927ac6653aSJeff Kirsher {
319354139cf3SJoao Pinto 	struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
319454139cf3SJoao Pinto 	unsigned int entry = rx_q->cur_rx;
319554139cf3SJoao Pinto 	int coe = priv->hw->rx_csum;
31967ac6653aSJeff Kirsher 	unsigned int next_entry;
31977ac6653aSJeff Kirsher 	unsigned int count = 0;
31987ac6653aSJeff Kirsher 
319983d7af64SGiuseppe CAVALLARO 	if (netif_msg_rx_status(priv)) {
3200d0225e7dSAlexandre TORGUE 		void *rx_head;
3201d0225e7dSAlexandre TORGUE 
320238ddc59dSLABBE Corentin 		netdev_dbg(priv->dev, "%s: descriptor ring:\n", __func__);
3203c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
320454139cf3SJoao Pinto 			rx_head = (void *)rx_q->dma_erx;
3205c24602efSGiuseppe CAVALLARO 		else
320654139cf3SJoao Pinto 			rx_head = (void *)rx_q->dma_rx;
3207d0225e7dSAlexandre TORGUE 
3208d0225e7dSAlexandre TORGUE 		priv->hw->desc->display_ring(rx_head, DMA_RX_SIZE, true);
32097ac6653aSJeff Kirsher 	}
3210c24602efSGiuseppe CAVALLARO 	while (count < limit) {
32117ac6653aSJeff Kirsher 		int status;
32129401bb5cSGiuseppe CAVALLARO 		struct dma_desc *p;
3213ba1ffd74SGiuseppe CAVALLARO 		struct dma_desc *np;
32147ac6653aSJeff Kirsher 
3215c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
321654139cf3SJoao Pinto 			p = (struct dma_desc *)(rx_q->dma_erx + entry);
3217c24602efSGiuseppe CAVALLARO 		else
321854139cf3SJoao Pinto 			p = rx_q->dma_rx + entry;
3219c24602efSGiuseppe CAVALLARO 
3220c1fa3212SFabrice Gasnier 		/* read the status of the incoming frame */
3221c1fa3212SFabrice Gasnier 		status = priv->hw->desc->rx_status(&priv->dev->stats,
3222c1fa3212SFabrice Gasnier 						   &priv->xstats, p);
3223c1fa3212SFabrice Gasnier 		/* check if managed by the DMA otherwise go ahead */
3224c1fa3212SFabrice Gasnier 		if (unlikely(status & dma_own))
32257ac6653aSJeff Kirsher 			break;
32267ac6653aSJeff Kirsher 
32277ac6653aSJeff Kirsher 		count++;
32287ac6653aSJeff Kirsher 
322954139cf3SJoao Pinto 		rx_q->cur_rx = STMMAC_GET_ENTRY(rx_q->cur_rx, DMA_RX_SIZE);
323054139cf3SJoao Pinto 		next_entry = rx_q->cur_rx;
3231e3ad57c9SGiuseppe Cavallaro 
3232c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
323354139cf3SJoao Pinto 			np = (struct dma_desc *)(rx_q->dma_erx + next_entry);
3234c24602efSGiuseppe CAVALLARO 		else
323554139cf3SJoao Pinto 			np = rx_q->dma_rx + next_entry;
3236ba1ffd74SGiuseppe CAVALLARO 
3237ba1ffd74SGiuseppe CAVALLARO 		prefetch(np);
32387ac6653aSJeff Kirsher 
3239c24602efSGiuseppe CAVALLARO 		if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status))
3240c24602efSGiuseppe CAVALLARO 			priv->hw->desc->rx_extended_status(&priv->dev->stats,
3241c24602efSGiuseppe CAVALLARO 							   &priv->xstats,
324254139cf3SJoao Pinto 							   rx_q->dma_erx +
3243c24602efSGiuseppe CAVALLARO 							   entry);
3244891434b1SRayagond Kokatanur 		if (unlikely(status == discard_frame)) {
32457ac6653aSJeff Kirsher 			priv->dev->stats.rx_errors++;
3246891434b1SRayagond Kokatanur 			if (priv->hwts_rx_en && !priv->extend_desc) {
32478d45e42bSLABBE Corentin 				/* DESC2 & DESC3 will be overwritten by device
3248891434b1SRayagond Kokatanur 				 * with timestamp value, hence reinitialize
3249891434b1SRayagond Kokatanur 				 * them in stmmac_rx_refill() function so that
3250891434b1SRayagond Kokatanur 				 * device can reuse it.
3251891434b1SRayagond Kokatanur 				 */
325254139cf3SJoao Pinto 				rx_q->rx_skbuff[entry] = NULL;
3253891434b1SRayagond Kokatanur 				dma_unmap_single(priv->device,
325454139cf3SJoao Pinto 						 rx_q->rx_skbuff_dma[entry],
3255ceb69499SGiuseppe CAVALLARO 						 priv->dma_buf_sz,
3256ceb69499SGiuseppe CAVALLARO 						 DMA_FROM_DEVICE);
3257891434b1SRayagond Kokatanur 			}
3258891434b1SRayagond Kokatanur 		} else {
32597ac6653aSJeff Kirsher 			struct sk_buff *skb;
32607ac6653aSJeff Kirsher 			int frame_len;
3261f748be53SAlexandre TORGUE 			unsigned int des;
3262f748be53SAlexandre TORGUE 
3263f748be53SAlexandre TORGUE 			if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00))
3264f8be0d78SMichael Weiser 				des = le32_to_cpu(p->des0);
3265f748be53SAlexandre TORGUE 			else
3266f8be0d78SMichael Weiser 				des = le32_to_cpu(p->des2);
32677ac6653aSJeff Kirsher 
3268ceb69499SGiuseppe CAVALLARO 			frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
3269ceb69499SGiuseppe CAVALLARO 
32708d45e42bSLABBE Corentin 			/*  If frame length is greater than skb buffer size
3271f748be53SAlexandre TORGUE 			 *  (preallocated during init) then the packet is
3272f748be53SAlexandre TORGUE 			 *  ignored
3273f748be53SAlexandre TORGUE 			 */
3274e527c4a7SGiuseppe CAVALLARO 			if (frame_len > priv->dma_buf_sz) {
327538ddc59dSLABBE Corentin 				netdev_err(priv->dev,
327638ddc59dSLABBE Corentin 					   "len %d larger than size (%d)\n",
327738ddc59dSLABBE Corentin 					   frame_len, priv->dma_buf_sz);
3278e527c4a7SGiuseppe CAVALLARO 				priv->dev->stats.rx_length_errors++;
3279e527c4a7SGiuseppe CAVALLARO 				break;
3280e527c4a7SGiuseppe CAVALLARO 			}
3281e527c4a7SGiuseppe CAVALLARO 
32827ac6653aSJeff Kirsher 			/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
3283ceb69499SGiuseppe CAVALLARO 			 * Type frames (LLC/LLC-SNAP)
3284ceb69499SGiuseppe CAVALLARO 			 */
32857ac6653aSJeff Kirsher 			if (unlikely(status != llc_snap))
32867ac6653aSJeff Kirsher 				frame_len -= ETH_FCS_LEN;
32877ac6653aSJeff Kirsher 
328883d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv)) {
328938ddc59dSLABBE Corentin 				netdev_dbg(priv->dev, "\tdesc: %p [entry %d] buff=0x%x\n",
3290f748be53SAlexandre TORGUE 					   p, entry, des);
329183d7af64SGiuseppe CAVALLARO 				if (frame_len > ETH_FRAME_LEN)
329238ddc59dSLABBE Corentin 					netdev_dbg(priv->dev, "frame size %d, COE: %d\n",
329383d7af64SGiuseppe CAVALLARO 						   frame_len, status);
329483d7af64SGiuseppe CAVALLARO 			}
329522ad3838SGiuseppe Cavallaro 
3296f748be53SAlexandre TORGUE 			/* The zero-copy is always used for all the sizes
3297f748be53SAlexandre TORGUE 			 * in case of GMAC4 because it needs
3298f748be53SAlexandre TORGUE 			 * to refill the used descriptors, always.
3299f748be53SAlexandre TORGUE 			 */
3300f748be53SAlexandre TORGUE 			if (unlikely(!priv->plat->has_gmac4 &&
3301f748be53SAlexandre TORGUE 				     ((frame_len < priv->rx_copybreak) ||
330254139cf3SJoao Pinto 				     stmmac_rx_threshold_count(rx_q)))) {
330322ad3838SGiuseppe Cavallaro 				skb = netdev_alloc_skb_ip_align(priv->dev,
330422ad3838SGiuseppe Cavallaro 								frame_len);
330522ad3838SGiuseppe Cavallaro 				if (unlikely(!skb)) {
330622ad3838SGiuseppe Cavallaro 					if (net_ratelimit())
330722ad3838SGiuseppe Cavallaro 						dev_warn(priv->device,
330822ad3838SGiuseppe Cavallaro 							 "packet dropped\n");
330922ad3838SGiuseppe Cavallaro 					priv->dev->stats.rx_dropped++;
331022ad3838SGiuseppe Cavallaro 					break;
331122ad3838SGiuseppe Cavallaro 				}
331222ad3838SGiuseppe Cavallaro 
331322ad3838SGiuseppe Cavallaro 				dma_sync_single_for_cpu(priv->device,
331454139cf3SJoao Pinto 							rx_q->rx_skbuff_dma
331522ad3838SGiuseppe Cavallaro 							[entry], frame_len,
331622ad3838SGiuseppe Cavallaro 							DMA_FROM_DEVICE);
331722ad3838SGiuseppe Cavallaro 				skb_copy_to_linear_data(skb,
331854139cf3SJoao Pinto 							rx_q->
331922ad3838SGiuseppe Cavallaro 							rx_skbuff[entry]->data,
332022ad3838SGiuseppe Cavallaro 							frame_len);
332122ad3838SGiuseppe Cavallaro 
332222ad3838SGiuseppe Cavallaro 				skb_put(skb, frame_len);
332322ad3838SGiuseppe Cavallaro 				dma_sync_single_for_device(priv->device,
332454139cf3SJoao Pinto 							   rx_q->rx_skbuff_dma
332522ad3838SGiuseppe Cavallaro 							   [entry], frame_len,
332622ad3838SGiuseppe Cavallaro 							   DMA_FROM_DEVICE);
332722ad3838SGiuseppe Cavallaro 			} else {
332854139cf3SJoao Pinto 				skb = rx_q->rx_skbuff[entry];
33297ac6653aSJeff Kirsher 				if (unlikely(!skb)) {
333038ddc59dSLABBE Corentin 					netdev_err(priv->dev,
333138ddc59dSLABBE Corentin 						   "%s: Inconsistent Rx chain\n",
33327ac6653aSJeff Kirsher 						   priv->dev->name);
33337ac6653aSJeff Kirsher 					priv->dev->stats.rx_dropped++;
33347ac6653aSJeff Kirsher 					break;
33357ac6653aSJeff Kirsher 				}
33367ac6653aSJeff Kirsher 				prefetch(skb->data - NET_IP_ALIGN);
333754139cf3SJoao Pinto 				rx_q->rx_skbuff[entry] = NULL;
333854139cf3SJoao Pinto 				rx_q->rx_zeroc_thresh++;
33397ac6653aSJeff Kirsher 
33407ac6653aSJeff Kirsher 				skb_put(skb, frame_len);
33417ac6653aSJeff Kirsher 				dma_unmap_single(priv->device,
334254139cf3SJoao Pinto 						 rx_q->rx_skbuff_dma[entry],
334322ad3838SGiuseppe Cavallaro 						 priv->dma_buf_sz,
334422ad3838SGiuseppe Cavallaro 						 DMA_FROM_DEVICE);
334522ad3838SGiuseppe Cavallaro 			}
334622ad3838SGiuseppe Cavallaro 
33477ac6653aSJeff Kirsher 			if (netif_msg_pktdata(priv)) {
334838ddc59dSLABBE Corentin 				netdev_dbg(priv->dev, "frame received (%dbytes)",
334938ddc59dSLABBE Corentin 					   frame_len);
33507ac6653aSJeff Kirsher 				print_pkt(skb->data, frame_len);
33517ac6653aSJeff Kirsher 			}
335283d7af64SGiuseppe CAVALLARO 
3353ba1ffd74SGiuseppe CAVALLARO 			stmmac_get_rx_hwtstamp(priv, p, np, skb);
3354ba1ffd74SGiuseppe CAVALLARO 
3355b9381985SVince Bridgers 			stmmac_rx_vlan(priv->dev, skb);
3356b9381985SVince Bridgers 
33577ac6653aSJeff Kirsher 			skb->protocol = eth_type_trans(skb, priv->dev);
33587ac6653aSJeff Kirsher 
3359ceb69499SGiuseppe CAVALLARO 			if (unlikely(!coe))
33607ac6653aSJeff Kirsher 				skb_checksum_none_assert(skb);
336162a2ab93SGiuseppe CAVALLARO 			else
33627ac6653aSJeff Kirsher 				skb->ip_summed = CHECKSUM_UNNECESSARY;
336362a2ab93SGiuseppe CAVALLARO 
33645bacd778SLABBE Corentin 			napi_gro_receive(&priv->napi, skb);
33657ac6653aSJeff Kirsher 
33667ac6653aSJeff Kirsher 			priv->dev->stats.rx_packets++;
33677ac6653aSJeff Kirsher 			priv->dev->stats.rx_bytes += frame_len;
33687ac6653aSJeff Kirsher 		}
33697ac6653aSJeff Kirsher 		entry = next_entry;
33707ac6653aSJeff Kirsher 	}
33717ac6653aSJeff Kirsher 
337254139cf3SJoao Pinto 	stmmac_rx_refill(priv, queue);
33737ac6653aSJeff Kirsher 
33747ac6653aSJeff Kirsher 	priv->xstats.rx_pkt_n += count;
33757ac6653aSJeff Kirsher 
33767ac6653aSJeff Kirsher 	return count;
33777ac6653aSJeff Kirsher }
33787ac6653aSJeff Kirsher 
33797ac6653aSJeff Kirsher /**
33807ac6653aSJeff Kirsher  *  stmmac_poll - stmmac poll method (NAPI)
33817ac6653aSJeff Kirsher  *  @napi : pointer to the napi structure.
33827ac6653aSJeff Kirsher  *  @budget : maximum number of packets that the current CPU can receive from
33837ac6653aSJeff Kirsher  *	      all interfaces.
33847ac6653aSJeff Kirsher  *  Description :
33859125cdd1SGiuseppe CAVALLARO  *  To look at the incoming frames and clear the tx resources.
33867ac6653aSJeff Kirsher  */
33877ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget)
33887ac6653aSJeff Kirsher {
33895bacd778SLABBE Corentin 	struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
3390ce736788SJoao Pinto 	u32 tx_count = priv->plat->tx_queues_to_use;
33915bacd778SLABBE Corentin 	u32 chan = STMMAC_CHAN0;
339254139cf3SJoao Pinto 	int work_done = 0;
339354139cf3SJoao Pinto 	u32 queue = chan;
33947ac6653aSJeff Kirsher 
33959125cdd1SGiuseppe CAVALLARO 	priv->xstats.napi_poll++;
3396ce736788SJoao Pinto 
3397ce736788SJoao Pinto 	/* check all the queues */
3398ce736788SJoao Pinto 	for (queue = 0; queue < tx_count; queue++)
3399ce736788SJoao Pinto 		stmmac_tx_clean(priv, queue);
3400ce736788SJoao Pinto 
3401ce736788SJoao Pinto 	queue = chan;
34027ac6653aSJeff Kirsher 
340354139cf3SJoao Pinto 	work_done = stmmac_rx(priv, budget, queue);
34047ac6653aSJeff Kirsher 	if (work_done < budget) {
34056ad20165SEric Dumazet 		napi_complete_done(napi, work_done);
34064f513ecdSJoao Pinto 		stmmac_enable_dma_irq(priv, chan);
34077ac6653aSJeff Kirsher 	}
34087ac6653aSJeff Kirsher 	return work_done;
34097ac6653aSJeff Kirsher }
34107ac6653aSJeff Kirsher 
34117ac6653aSJeff Kirsher /**
34127ac6653aSJeff Kirsher  *  stmmac_tx_timeout
34137ac6653aSJeff Kirsher  *  @dev : Pointer to net device structure
34147ac6653aSJeff Kirsher  *  Description: this function is called when a packet transmission fails to
34157284a3f1SGiuseppe CAVALLARO  *   complete within a reasonable time. The driver will mark the error in the
34167ac6653aSJeff Kirsher  *   netdev structure and arrange for the device to be reset to a sane state
34177ac6653aSJeff Kirsher  *   in order to transmit a new packet.
34187ac6653aSJeff Kirsher  */
34197ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev)
34207ac6653aSJeff Kirsher {
34217ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
3422ce736788SJoao Pinto 	u32 tx_count = priv->plat->tx_queues_to_use;
3423ce736788SJoao Pinto 	u32 chan;
34247ac6653aSJeff Kirsher 
34257ac6653aSJeff Kirsher 	/* Clear Tx resources and restart transmitting again */
3426ce736788SJoao Pinto 	for (chan = 0; chan < tx_count; chan++)
34274e593262SJoao Pinto 		stmmac_tx_err(priv, chan);
34287ac6653aSJeff Kirsher }
34297ac6653aSJeff Kirsher 
34307ac6653aSJeff Kirsher /**
343101789349SJiri Pirko  *  stmmac_set_rx_mode - entry point for multicast addressing
34327ac6653aSJeff Kirsher  *  @dev : pointer to the device structure
34337ac6653aSJeff Kirsher  *  Description:
34347ac6653aSJeff Kirsher  *  This function is a driver entry point which gets called by the kernel
34357ac6653aSJeff Kirsher  *  whenever multicast addresses must be enabled/disabled.
34367ac6653aSJeff Kirsher  *  Return value:
34377ac6653aSJeff Kirsher  *  void.
34387ac6653aSJeff Kirsher  */
343901789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev)
34407ac6653aSJeff Kirsher {
34417ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
34427ac6653aSJeff Kirsher 
34433b57de95SVince Bridgers 	priv->hw->mac->set_filter(priv->hw, dev);
34447ac6653aSJeff Kirsher }
34457ac6653aSJeff Kirsher 
34467ac6653aSJeff Kirsher /**
34477ac6653aSJeff Kirsher  *  stmmac_change_mtu - entry point to change MTU size for the device.
34487ac6653aSJeff Kirsher  *  @dev : device pointer.
34497ac6653aSJeff Kirsher  *  @new_mtu : the new MTU size for the device.
34507ac6653aSJeff Kirsher  *  Description: the Maximum Transfer Unit (MTU) is used by the network layer
34517ac6653aSJeff Kirsher  *  to drive packet transmission. Ethernet has an MTU of 1500 octets
34527ac6653aSJeff Kirsher  *  (ETH_DATA_LEN). This value can be changed with ifconfig.
34537ac6653aSJeff Kirsher  *  Return value:
34547ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
34557ac6653aSJeff Kirsher  *  file on failure.
34567ac6653aSJeff Kirsher  */
34577ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
34587ac6653aSJeff Kirsher {
345938ddc59dSLABBE Corentin 	struct stmmac_priv *priv = netdev_priv(dev);
346038ddc59dSLABBE Corentin 
34617ac6653aSJeff Kirsher 	if (netif_running(dev)) {
346238ddc59dSLABBE Corentin 		netdev_err(priv->dev, "must be stopped to change its MTU\n");
34637ac6653aSJeff Kirsher 		return -EBUSY;
34647ac6653aSJeff Kirsher 	}
34657ac6653aSJeff Kirsher 
34667ac6653aSJeff Kirsher 	dev->mtu = new_mtu;
3467f748be53SAlexandre TORGUE 
34687ac6653aSJeff Kirsher 	netdev_update_features(dev);
34697ac6653aSJeff Kirsher 
34707ac6653aSJeff Kirsher 	return 0;
34717ac6653aSJeff Kirsher }
34727ac6653aSJeff Kirsher 
3473c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev,
3474c8f44affSMichał Mirosław 					     netdev_features_t features)
34757ac6653aSJeff Kirsher {
34767ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
34777ac6653aSJeff Kirsher 
347838912bdbSDeepak SIKRI 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
34797ac6653aSJeff Kirsher 		features &= ~NETIF_F_RXCSUM;
3480d2afb5bdSGiuseppe CAVALLARO 
34817ac6653aSJeff Kirsher 	if (!priv->plat->tx_coe)
3482a188222bSTom Herbert 		features &= ~NETIF_F_CSUM_MASK;
34837ac6653aSJeff Kirsher 
34847ac6653aSJeff Kirsher 	/* Some GMAC devices have a bugged Jumbo frame support that
34857ac6653aSJeff Kirsher 	 * needs to have the Tx COE disabled for oversized frames
34867ac6653aSJeff Kirsher 	 * (due to limited buffer sizes). In this case we disable
3487ceb69499SGiuseppe CAVALLARO 	 * the TX csum insertion in the TDES and not use SF.
3488ceb69499SGiuseppe CAVALLARO 	 */
34897ac6653aSJeff Kirsher 	if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
3490a188222bSTom Herbert 		features &= ~NETIF_F_CSUM_MASK;
34917ac6653aSJeff Kirsher 
3492f748be53SAlexandre TORGUE 	/* Disable tso if asked by ethtool */
3493f748be53SAlexandre TORGUE 	if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
3494f748be53SAlexandre TORGUE 		if (features & NETIF_F_TSO)
3495f748be53SAlexandre TORGUE 			priv->tso = true;
3496f748be53SAlexandre TORGUE 		else
3497f748be53SAlexandre TORGUE 			priv->tso = false;
3498f748be53SAlexandre TORGUE 	}
3499f748be53SAlexandre TORGUE 
35007ac6653aSJeff Kirsher 	return features;
35017ac6653aSJeff Kirsher }
35027ac6653aSJeff Kirsher 
3503d2afb5bdSGiuseppe CAVALLARO static int stmmac_set_features(struct net_device *netdev,
3504d2afb5bdSGiuseppe CAVALLARO 			       netdev_features_t features)
3505d2afb5bdSGiuseppe CAVALLARO {
3506d2afb5bdSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(netdev);
3507d2afb5bdSGiuseppe CAVALLARO 
3508d2afb5bdSGiuseppe CAVALLARO 	/* Keep the COE Type in case of csum is supporting */
3509d2afb5bdSGiuseppe CAVALLARO 	if (features & NETIF_F_RXCSUM)
3510d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
3511d2afb5bdSGiuseppe CAVALLARO 	else
3512d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
3513d2afb5bdSGiuseppe CAVALLARO 	/* No check needed because rx_coe has been set before and it will be
3514d2afb5bdSGiuseppe CAVALLARO 	 * fixed in case of issue.
3515d2afb5bdSGiuseppe CAVALLARO 	 */
3516d2afb5bdSGiuseppe CAVALLARO 	priv->hw->mac->rx_ipc(priv->hw);
3517d2afb5bdSGiuseppe CAVALLARO 
3518d2afb5bdSGiuseppe CAVALLARO 	return 0;
3519d2afb5bdSGiuseppe CAVALLARO }
3520d2afb5bdSGiuseppe CAVALLARO 
352132ceabcaSGiuseppe CAVALLARO /**
352232ceabcaSGiuseppe CAVALLARO  *  stmmac_interrupt - main ISR
352332ceabcaSGiuseppe CAVALLARO  *  @irq: interrupt number.
352432ceabcaSGiuseppe CAVALLARO  *  @dev_id: to pass the net device pointer.
352532ceabcaSGiuseppe CAVALLARO  *  Description: this is the main driver interrupt service routine.
3526732fdf0eSGiuseppe CAVALLARO  *  It can call:
3527732fdf0eSGiuseppe CAVALLARO  *  o DMA service routine (to manage incoming frame reception and transmission
3528732fdf0eSGiuseppe CAVALLARO  *    status)
3529732fdf0eSGiuseppe CAVALLARO  *  o Core interrupts to manage: remote wake-up, management counter, LPI
353032ceabcaSGiuseppe CAVALLARO  *    interrupts.
353132ceabcaSGiuseppe CAVALLARO  */
35327ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
35337ac6653aSJeff Kirsher {
35347ac6653aSJeff Kirsher 	struct net_device *dev = (struct net_device *)dev_id;
35357ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
35367bac4e1eSJoao Pinto 	u32 rx_cnt = priv->plat->rx_queues_to_use;
35377bac4e1eSJoao Pinto 	u32 tx_cnt = priv->plat->tx_queues_to_use;
35387bac4e1eSJoao Pinto 	u32 queues_count;
35397bac4e1eSJoao Pinto 	u32 queue;
35407bac4e1eSJoao Pinto 
35417bac4e1eSJoao Pinto 	queues_count = (rx_cnt > tx_cnt) ? rx_cnt : tx_cnt;
35427ac6653aSJeff Kirsher 
354389f7f2cfSSrinivas Kandagatla 	if (priv->irq_wake)
354489f7f2cfSSrinivas Kandagatla 		pm_wakeup_event(priv->device, 0);
354589f7f2cfSSrinivas Kandagatla 
35467ac6653aSJeff Kirsher 	if (unlikely(!dev)) {
354738ddc59dSLABBE Corentin 		netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
35487ac6653aSJeff Kirsher 		return IRQ_NONE;
35497ac6653aSJeff Kirsher 	}
35507ac6653aSJeff Kirsher 
35517ac6653aSJeff Kirsher 	/* To handle GMAC own interrupts */
3552f748be53SAlexandre TORGUE 	if ((priv->plat->has_gmac) || (priv->plat->has_gmac4)) {
35537ed24bbeSVince Bridgers 		int status = priv->hw->mac->host_irq_status(priv->hw,
35540982a0f6SGiuseppe CAVALLARO 							    &priv->xstats);
35558f71a88dSJoao Pinto 
3556d765955dSGiuseppe CAVALLARO 		if (unlikely(status)) {
3557d765955dSGiuseppe CAVALLARO 			/* For LPI we need to save the tx status */
35580982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
3559d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = true;
35600982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
3561d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = false;
35627bac4e1eSJoao Pinto 		}
35637bac4e1eSJoao Pinto 
35647bac4e1eSJoao Pinto 		if (priv->synopsys_id >= DWMAC_CORE_4_00) {
35657bac4e1eSJoao Pinto 			for (queue = 0; queue < queues_count; queue++) {
356654139cf3SJoao Pinto 				struct stmmac_rx_queue *rx_q =
356754139cf3SJoao Pinto 				&priv->rx_queue[queue];
356854139cf3SJoao Pinto 
35697bac4e1eSJoao Pinto 				status |=
35707bac4e1eSJoao Pinto 				priv->hw->mac->host_mtl_irq_status(priv->hw,
35717bac4e1eSJoao Pinto 								   queue);
35727bac4e1eSJoao Pinto 
35737bac4e1eSJoao Pinto 				if (status & CORE_IRQ_MTL_RX_OVERFLOW &&
35747bac4e1eSJoao Pinto 				    priv->hw->dma->set_rx_tail_ptr)
3575f748be53SAlexandre TORGUE 					priv->hw->dma->set_rx_tail_ptr(priv->ioaddr,
357654139cf3SJoao Pinto 								rx_q->rx_tail_addr,
35777bac4e1eSJoao Pinto 								queue);
35787bac4e1eSJoao Pinto 			}
3579d765955dSGiuseppe CAVALLARO 		}
358070523e63SGiuseppe CAVALLARO 
358170523e63SGiuseppe CAVALLARO 		/* PCS link status */
35823fe5cadbSGiuseppe CAVALLARO 		if (priv->hw->pcs) {
358370523e63SGiuseppe CAVALLARO 			if (priv->xstats.pcs_link)
358470523e63SGiuseppe CAVALLARO 				netif_carrier_on(dev);
358570523e63SGiuseppe CAVALLARO 			else
358670523e63SGiuseppe CAVALLARO 				netif_carrier_off(dev);
358770523e63SGiuseppe CAVALLARO 		}
3588d765955dSGiuseppe CAVALLARO 	}
3589d765955dSGiuseppe CAVALLARO 
3590d765955dSGiuseppe CAVALLARO 	/* To handle DMA interrupts */
35917ac6653aSJeff Kirsher 	stmmac_dma_interrupt(priv);
35927ac6653aSJeff Kirsher 
35937ac6653aSJeff Kirsher 	return IRQ_HANDLED;
35947ac6653aSJeff Kirsher }
35957ac6653aSJeff Kirsher 
35967ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
35977ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools
3598ceb69499SGiuseppe CAVALLARO  * to allow network I/O with interrupts disabled.
3599ceb69499SGiuseppe CAVALLARO  */
36007ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev)
36017ac6653aSJeff Kirsher {
36027ac6653aSJeff Kirsher 	disable_irq(dev->irq);
36037ac6653aSJeff Kirsher 	stmmac_interrupt(dev->irq, dev);
36047ac6653aSJeff Kirsher 	enable_irq(dev->irq);
36057ac6653aSJeff Kirsher }
36067ac6653aSJeff Kirsher #endif
36077ac6653aSJeff Kirsher 
36087ac6653aSJeff Kirsher /**
36097ac6653aSJeff Kirsher  *  stmmac_ioctl - Entry point for the Ioctl
36107ac6653aSJeff Kirsher  *  @dev: Device pointer.
36117ac6653aSJeff Kirsher  *  @rq: An IOCTL specefic structure, that can contain a pointer to
36127ac6653aSJeff Kirsher  *  a proprietary structure used to pass information to the driver.
36137ac6653aSJeff Kirsher  *  @cmd: IOCTL command
36147ac6653aSJeff Kirsher  *  Description:
361532ceabcaSGiuseppe CAVALLARO  *  Currently it supports the phy_mii_ioctl(...) and HW time stamping.
36167ac6653aSJeff Kirsher  */
36177ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
36187ac6653aSJeff Kirsher {
3619891434b1SRayagond Kokatanur 	int ret = -EOPNOTSUPP;
36207ac6653aSJeff Kirsher 
36217ac6653aSJeff Kirsher 	if (!netif_running(dev))
36227ac6653aSJeff Kirsher 		return -EINVAL;
36237ac6653aSJeff Kirsher 
3624891434b1SRayagond Kokatanur 	switch (cmd) {
3625891434b1SRayagond Kokatanur 	case SIOCGMIIPHY:
3626891434b1SRayagond Kokatanur 	case SIOCGMIIREG:
3627891434b1SRayagond Kokatanur 	case SIOCSMIIREG:
3628d6d50c7eSPhilippe Reynes 		if (!dev->phydev)
36297ac6653aSJeff Kirsher 			return -EINVAL;
3630d6d50c7eSPhilippe Reynes 		ret = phy_mii_ioctl(dev->phydev, rq, cmd);
3631891434b1SRayagond Kokatanur 		break;
3632891434b1SRayagond Kokatanur 	case SIOCSHWTSTAMP:
3633891434b1SRayagond Kokatanur 		ret = stmmac_hwtstamp_ioctl(dev, rq);
3634891434b1SRayagond Kokatanur 		break;
3635891434b1SRayagond Kokatanur 	default:
3636891434b1SRayagond Kokatanur 		break;
3637891434b1SRayagond Kokatanur 	}
36387ac6653aSJeff Kirsher 
36397ac6653aSJeff Kirsher 	return ret;
36407ac6653aSJeff Kirsher }
36417ac6653aSJeff Kirsher 
364250fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
36437ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir;
36447ac29055SGiuseppe CAVALLARO 
3645c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc,
3646c24602efSGiuseppe CAVALLARO 			       struct seq_file *seq)
36477ac29055SGiuseppe CAVALLARO {
36487ac29055SGiuseppe CAVALLARO 	int i;
3649c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
3650c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
36517ac29055SGiuseppe CAVALLARO 
3652c24602efSGiuseppe CAVALLARO 	for (i = 0; i < size; i++) {
3653c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
3654c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
3655c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
3656f8be0d78SMichael Weiser 				   le32_to_cpu(ep->basic.des0),
3657f8be0d78SMichael Weiser 				   le32_to_cpu(ep->basic.des1),
3658f8be0d78SMichael Weiser 				   le32_to_cpu(ep->basic.des2),
3659f8be0d78SMichael Weiser 				   le32_to_cpu(ep->basic.des3));
3660c24602efSGiuseppe CAVALLARO 			ep++;
3661c24602efSGiuseppe CAVALLARO 		} else {
3662c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
3663c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
3664f8be0d78SMichael Weiser 				   le32_to_cpu(p->des0), le32_to_cpu(p->des1),
3665f8be0d78SMichael Weiser 				   le32_to_cpu(p->des2), le32_to_cpu(p->des3));
3666c24602efSGiuseppe CAVALLARO 			p++;
3667c24602efSGiuseppe CAVALLARO 		}
36687ac29055SGiuseppe CAVALLARO 		seq_printf(seq, "\n");
36697ac29055SGiuseppe CAVALLARO 	}
3670c24602efSGiuseppe CAVALLARO }
36717ac29055SGiuseppe CAVALLARO 
3672c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
3673c24602efSGiuseppe CAVALLARO {
3674c24602efSGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
3675c24602efSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
367654139cf3SJoao Pinto 	u32 rx_count = priv->plat->rx_queues_to_use;
3677ce736788SJoao Pinto 	u32 tx_count = priv->plat->tx_queues_to_use;
367854139cf3SJoao Pinto 	u32 queue;
367954139cf3SJoao Pinto 
368054139cf3SJoao Pinto 	for (queue = 0; queue < rx_count; queue++) {
368154139cf3SJoao Pinto 		struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
368254139cf3SJoao Pinto 
368354139cf3SJoao Pinto 		seq_printf(seq, "RX Queue %d:\n", queue);
36847ac29055SGiuseppe CAVALLARO 
3685c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc) {
368654139cf3SJoao Pinto 			seq_printf(seq, "Extended descriptor ring:\n");
368754139cf3SJoao Pinto 			sysfs_display_ring((void *)rx_q->dma_erx,
368854139cf3SJoao Pinto 					   DMA_RX_SIZE, 1, seq);
368954139cf3SJoao Pinto 		} else {
369054139cf3SJoao Pinto 			seq_printf(seq, "Descriptor ring:\n");
369154139cf3SJoao Pinto 			sysfs_display_ring((void *)rx_q->dma_rx,
369254139cf3SJoao Pinto 					   DMA_RX_SIZE, 0, seq);
369354139cf3SJoao Pinto 		}
369454139cf3SJoao Pinto 	}
369554139cf3SJoao Pinto 
3696ce736788SJoao Pinto 	for (queue = 0; queue < tx_count; queue++) {
3697ce736788SJoao Pinto 		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
3698ce736788SJoao Pinto 
3699ce736788SJoao Pinto 		seq_printf(seq, "TX Queue %d:\n", queue);
3700ce736788SJoao Pinto 
370154139cf3SJoao Pinto 		if (priv->extend_desc) {
3702ce736788SJoao Pinto 			seq_printf(seq, "Extended descriptor ring:\n");
3703ce736788SJoao Pinto 			sysfs_display_ring((void *)tx_q->dma_etx,
3704ce736788SJoao Pinto 					   DMA_TX_SIZE, 1, seq);
3705c24602efSGiuseppe CAVALLARO 		} else {
3706ce736788SJoao Pinto 			seq_printf(seq, "Descriptor ring:\n");
3707ce736788SJoao Pinto 			sysfs_display_ring((void *)tx_q->dma_tx,
3708ce736788SJoao Pinto 					   DMA_TX_SIZE, 0, seq);
3709ce736788SJoao Pinto 		}
37107ac29055SGiuseppe CAVALLARO 	}
37117ac29055SGiuseppe CAVALLARO 
37127ac29055SGiuseppe CAVALLARO 	return 0;
37137ac29055SGiuseppe CAVALLARO }
37147ac29055SGiuseppe CAVALLARO 
37157ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
37167ac29055SGiuseppe CAVALLARO {
37177ac29055SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
37187ac29055SGiuseppe CAVALLARO }
37197ac29055SGiuseppe CAVALLARO 
372022d3efe5SPavel Machek /* Debugfs files, should appear in /sys/kernel/debug/stmmaceth/eth0 */
372122d3efe5SPavel Machek 
37227ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = {
37237ac29055SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
37247ac29055SGiuseppe CAVALLARO 	.open = stmmac_sysfs_ring_open,
37257ac29055SGiuseppe CAVALLARO 	.read = seq_read,
37267ac29055SGiuseppe CAVALLARO 	.llseek = seq_lseek,
372774863948SDjalal Harouni 	.release = single_release,
37287ac29055SGiuseppe CAVALLARO };
37297ac29055SGiuseppe CAVALLARO 
3730e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
3731e7434821SGiuseppe CAVALLARO {
3732e7434821SGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
3733e7434821SGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
3734e7434821SGiuseppe CAVALLARO 
373519e30c14SGiuseppe CAVALLARO 	if (!priv->hw_cap_support) {
3736e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "DMA HW features not supported\n");
3737e7434821SGiuseppe CAVALLARO 		return 0;
3738e7434821SGiuseppe CAVALLARO 	}
3739e7434821SGiuseppe CAVALLARO 
3740e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
3741e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tDMA HW features\n");
3742e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
3743e7434821SGiuseppe CAVALLARO 
374422d3efe5SPavel Machek 	seq_printf(seq, "\t10/100 Mbps: %s\n",
3745e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_10_100) ? "Y" : "N");
374622d3efe5SPavel Machek 	seq_printf(seq, "\t1000 Mbps: %s\n",
3747e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_1000) ? "Y" : "N");
374822d3efe5SPavel Machek 	seq_printf(seq, "\tHalf duplex: %s\n",
3749e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.half_duplex) ? "Y" : "N");
3750e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHash Filter: %s\n",
3751e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.hash_filter) ? "Y" : "N");
3752e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tMultiple MAC address registers: %s\n",
3753e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.multi_addr) ? "Y" : "N");
37548d45e42bSLABBE Corentin 	seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfaces): %s\n",
3755e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pcs) ? "Y" : "N");
3756e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
3757e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.sma_mdio) ? "Y" : "N");
3758e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Remote wake up: %s\n",
3759e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
3760e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Magic Frame: %s\n",
3761e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
3762e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRMON module: %s\n",
3763e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rmon) ? "Y" : "N");
3764e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
3765e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.time_stamp) ? "Y" : "N");
3766e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp: %s\n",
3767e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.atime_stamp) ? "Y" : "N");
376822d3efe5SPavel Machek 	seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE): %s\n",
3769e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.eee) ? "Y" : "N");
3770e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
3771e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tChecksum Offload in TX: %s\n",
3772e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.tx_coe) ? "Y" : "N");
3773f748be53SAlexandre TORGUE 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
3774f748be53SAlexandre TORGUE 		seq_printf(seq, "\tIP Checksum Offload in RX: %s\n",
3775f748be53SAlexandre TORGUE 			   (priv->dma_cap.rx_coe) ? "Y" : "N");
3776f748be53SAlexandre TORGUE 	} else {
3777e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
3778e7434821SGiuseppe CAVALLARO 			   (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
3779e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
3780e7434821SGiuseppe CAVALLARO 			   (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
3781f748be53SAlexandre TORGUE 	}
3782e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
3783e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
3784e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
3785e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_rx_channel);
3786e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
3787e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_tx_channel);
3788e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tEnhanced descriptors: %s\n",
3789e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.enh_desc) ? "Y" : "N");
3790e7434821SGiuseppe CAVALLARO 
3791e7434821SGiuseppe CAVALLARO 	return 0;
3792e7434821SGiuseppe CAVALLARO }
3793e7434821SGiuseppe CAVALLARO 
3794e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
3795e7434821SGiuseppe CAVALLARO {
3796e7434821SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
3797e7434821SGiuseppe CAVALLARO }
3798e7434821SGiuseppe CAVALLARO 
3799e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = {
3800e7434821SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
3801e7434821SGiuseppe CAVALLARO 	.open = stmmac_sysfs_dma_cap_open,
3802e7434821SGiuseppe CAVALLARO 	.read = seq_read,
3803e7434821SGiuseppe CAVALLARO 	.llseek = seq_lseek,
380474863948SDjalal Harouni 	.release = single_release,
3805e7434821SGiuseppe CAVALLARO };
3806e7434821SGiuseppe CAVALLARO 
38077ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev)
38087ac29055SGiuseppe CAVALLARO {
3809466c5ac8SMathieu Olivari 	struct stmmac_priv *priv = netdev_priv(dev);
38107ac29055SGiuseppe CAVALLARO 
3811466c5ac8SMathieu Olivari 	/* Create per netdev entries */
3812466c5ac8SMathieu Olivari 	priv->dbgfs_dir = debugfs_create_dir(dev->name, stmmac_fs_dir);
3813466c5ac8SMathieu Olivari 
3814466c5ac8SMathieu Olivari 	if (!priv->dbgfs_dir || IS_ERR(priv->dbgfs_dir)) {
381538ddc59dSLABBE Corentin 		netdev_err(priv->dev, "ERROR failed to create debugfs directory\n");
38167ac29055SGiuseppe CAVALLARO 
38177ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
38187ac29055SGiuseppe CAVALLARO 	}
38197ac29055SGiuseppe CAVALLARO 
38207ac29055SGiuseppe CAVALLARO 	/* Entry to report DMA RX/TX rings */
3821466c5ac8SMathieu Olivari 	priv->dbgfs_rings_status =
3822466c5ac8SMathieu Olivari 		debugfs_create_file("descriptors_status", S_IRUGO,
3823466c5ac8SMathieu Olivari 				    priv->dbgfs_dir, dev,
38247ac29055SGiuseppe CAVALLARO 				    &stmmac_rings_status_fops);
38257ac29055SGiuseppe CAVALLARO 
3826466c5ac8SMathieu Olivari 	if (!priv->dbgfs_rings_status || IS_ERR(priv->dbgfs_rings_status)) {
382738ddc59dSLABBE Corentin 		netdev_err(priv->dev, "ERROR creating stmmac ring debugfs file\n");
3828466c5ac8SMathieu Olivari 		debugfs_remove_recursive(priv->dbgfs_dir);
38297ac29055SGiuseppe CAVALLARO 
38307ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
38317ac29055SGiuseppe CAVALLARO 	}
38327ac29055SGiuseppe CAVALLARO 
3833e7434821SGiuseppe CAVALLARO 	/* Entry to report the DMA HW features */
3834466c5ac8SMathieu Olivari 	priv->dbgfs_dma_cap = debugfs_create_file("dma_cap", S_IRUGO,
3835466c5ac8SMathieu Olivari 					    priv->dbgfs_dir,
3836e7434821SGiuseppe CAVALLARO 					    dev, &stmmac_dma_cap_fops);
3837e7434821SGiuseppe CAVALLARO 
3838466c5ac8SMathieu Olivari 	if (!priv->dbgfs_dma_cap || IS_ERR(priv->dbgfs_dma_cap)) {
383938ddc59dSLABBE Corentin 		netdev_err(priv->dev, "ERROR creating stmmac MMC debugfs file\n");
3840466c5ac8SMathieu Olivari 		debugfs_remove_recursive(priv->dbgfs_dir);
3841e7434821SGiuseppe CAVALLARO 
3842e7434821SGiuseppe CAVALLARO 		return -ENOMEM;
3843e7434821SGiuseppe CAVALLARO 	}
3844e7434821SGiuseppe CAVALLARO 
38457ac29055SGiuseppe CAVALLARO 	return 0;
38467ac29055SGiuseppe CAVALLARO }
38477ac29055SGiuseppe CAVALLARO 
3848466c5ac8SMathieu Olivari static void stmmac_exit_fs(struct net_device *dev)
38497ac29055SGiuseppe CAVALLARO {
3850466c5ac8SMathieu Olivari 	struct stmmac_priv *priv = netdev_priv(dev);
3851466c5ac8SMathieu Olivari 
3852466c5ac8SMathieu Olivari 	debugfs_remove_recursive(priv->dbgfs_dir);
38537ac29055SGiuseppe CAVALLARO }
385450fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */
38557ac29055SGiuseppe CAVALLARO 
38567ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = {
38577ac6653aSJeff Kirsher 	.ndo_open = stmmac_open,
38587ac6653aSJeff Kirsher 	.ndo_start_xmit = stmmac_xmit,
38597ac6653aSJeff Kirsher 	.ndo_stop = stmmac_release,
38607ac6653aSJeff Kirsher 	.ndo_change_mtu = stmmac_change_mtu,
38617ac6653aSJeff Kirsher 	.ndo_fix_features = stmmac_fix_features,
3862d2afb5bdSGiuseppe CAVALLARO 	.ndo_set_features = stmmac_set_features,
386301789349SJiri Pirko 	.ndo_set_rx_mode = stmmac_set_rx_mode,
38647ac6653aSJeff Kirsher 	.ndo_tx_timeout = stmmac_tx_timeout,
38657ac6653aSJeff Kirsher 	.ndo_do_ioctl = stmmac_ioctl,
38667ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
38677ac6653aSJeff Kirsher 	.ndo_poll_controller = stmmac_poll_controller,
38687ac6653aSJeff Kirsher #endif
38697ac6653aSJeff Kirsher 	.ndo_set_mac_address = eth_mac_addr,
38707ac6653aSJeff Kirsher };
38717ac6653aSJeff Kirsher 
38727ac6653aSJeff Kirsher /**
3873cf3f047bSGiuseppe CAVALLARO  *  stmmac_hw_init - Init the MAC device
387432ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
3875732fdf0eSGiuseppe CAVALLARO  *  Description: this function is to configure the MAC device according to
3876732fdf0eSGiuseppe CAVALLARO  *  some platform parameters or the HW capability register. It prepares the
3877732fdf0eSGiuseppe CAVALLARO  *  driver to use either ring or chain modes and to setup either enhanced or
3878732fdf0eSGiuseppe CAVALLARO  *  normal descriptors.
3879cf3f047bSGiuseppe CAVALLARO  */
3880cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv)
3881cf3f047bSGiuseppe CAVALLARO {
3882cf3f047bSGiuseppe CAVALLARO 	struct mac_device_info *mac;
3883cf3f047bSGiuseppe CAVALLARO 
3884cf3f047bSGiuseppe CAVALLARO 	/* Identify the MAC HW device */
388503f2eecdSMarc Kleine-Budde 	if (priv->plat->has_gmac) {
388603f2eecdSMarc Kleine-Budde 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
38873b57de95SVince Bridgers 		mac = dwmac1000_setup(priv->ioaddr,
38883b57de95SVince Bridgers 				      priv->plat->multicast_filter_bins,
3889c623d149SAlexandre TORGUE 				      priv->plat->unicast_filter_entries,
3890c623d149SAlexandre TORGUE 				      &priv->synopsys_id);
3891f748be53SAlexandre TORGUE 	} else if (priv->plat->has_gmac4) {
3892f748be53SAlexandre TORGUE 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
3893f748be53SAlexandre TORGUE 		mac = dwmac4_setup(priv->ioaddr,
3894f748be53SAlexandre TORGUE 				   priv->plat->multicast_filter_bins,
3895f748be53SAlexandre TORGUE 				   priv->plat->unicast_filter_entries,
3896f748be53SAlexandre TORGUE 				   &priv->synopsys_id);
389703f2eecdSMarc Kleine-Budde 	} else {
3898c623d149SAlexandre TORGUE 		mac = dwmac100_setup(priv->ioaddr, &priv->synopsys_id);
389903f2eecdSMarc Kleine-Budde 	}
3900cf3f047bSGiuseppe CAVALLARO 	if (!mac)
3901cf3f047bSGiuseppe CAVALLARO 		return -ENOMEM;
3902cf3f047bSGiuseppe CAVALLARO 
3903cf3f047bSGiuseppe CAVALLARO 	priv->hw = mac;
3904cf3f047bSGiuseppe CAVALLARO 
39054a7d666aSGiuseppe CAVALLARO 	/* To use the chained or ring mode */
3906f748be53SAlexandre TORGUE 	if (priv->synopsys_id >= DWMAC_CORE_4_00) {
3907f748be53SAlexandre TORGUE 		priv->hw->mode = &dwmac4_ring_mode_ops;
3908f748be53SAlexandre TORGUE 	} else {
39094a7d666aSGiuseppe CAVALLARO 		if (chain_mode) {
391029896a67SGiuseppe CAVALLARO 			priv->hw->mode = &chain_mode_ops;
391138ddc59dSLABBE Corentin 			dev_info(priv->device, "Chain mode enabled\n");
39124a7d666aSGiuseppe CAVALLARO 			priv->mode = STMMAC_CHAIN_MODE;
39134a7d666aSGiuseppe CAVALLARO 		} else {
391429896a67SGiuseppe CAVALLARO 			priv->hw->mode = &ring_mode_ops;
391538ddc59dSLABBE Corentin 			dev_info(priv->device, "Ring mode enabled\n");
39164a7d666aSGiuseppe CAVALLARO 			priv->mode = STMMAC_RING_MODE;
39174a7d666aSGiuseppe CAVALLARO 		}
3918f748be53SAlexandre TORGUE 	}
39194a7d666aSGiuseppe CAVALLARO 
3920cf3f047bSGiuseppe CAVALLARO 	/* Get the HW capability (new GMAC newer than 3.50a) */
3921cf3f047bSGiuseppe CAVALLARO 	priv->hw_cap_support = stmmac_get_hw_features(priv);
3922cf3f047bSGiuseppe CAVALLARO 	if (priv->hw_cap_support) {
392338ddc59dSLABBE Corentin 		dev_info(priv->device, "DMA HW capability register supported\n");
3924cf3f047bSGiuseppe CAVALLARO 
3925cf3f047bSGiuseppe CAVALLARO 		/* We can override some gmac/dma configuration fields: e.g.
3926cf3f047bSGiuseppe CAVALLARO 		 * enh_desc, tx_coe (e.g. that are passed through the
3927cf3f047bSGiuseppe CAVALLARO 		 * platform) with the values from the HW capability
3928cf3f047bSGiuseppe CAVALLARO 		 * register (if supported).
3929cf3f047bSGiuseppe CAVALLARO 		 */
3930cf3f047bSGiuseppe CAVALLARO 		priv->plat->enh_desc = priv->dma_cap.enh_desc;
3931cf3f047bSGiuseppe CAVALLARO 		priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
39323fe5cadbSGiuseppe CAVALLARO 		priv->hw->pmt = priv->plat->pmt;
393338912bdbSDeepak SIKRI 
3934a8df35d4SEzequiel Garcia 		/* TXCOE doesn't work in thresh DMA mode */
3935a8df35d4SEzequiel Garcia 		if (priv->plat->force_thresh_dma_mode)
3936a8df35d4SEzequiel Garcia 			priv->plat->tx_coe = 0;
3937a8df35d4SEzequiel Garcia 		else
393838912bdbSDeepak SIKRI 			priv->plat->tx_coe = priv->dma_cap.tx_coe;
3939a8df35d4SEzequiel Garcia 
3940f748be53SAlexandre TORGUE 		/* In case of GMAC4 rx_coe is from HW cap register. */
3941f748be53SAlexandre TORGUE 		priv->plat->rx_coe = priv->dma_cap.rx_coe;
394238912bdbSDeepak SIKRI 
394338912bdbSDeepak SIKRI 		if (priv->dma_cap.rx_coe_type2)
394438912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
394538912bdbSDeepak SIKRI 		else if (priv->dma_cap.rx_coe_type1)
394638912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
394738912bdbSDeepak SIKRI 
394838ddc59dSLABBE Corentin 	} else {
394938ddc59dSLABBE Corentin 		dev_info(priv->device, "No HW DMA feature register supported\n");
395038ddc59dSLABBE Corentin 	}
3951cf3f047bSGiuseppe CAVALLARO 
3952f748be53SAlexandre TORGUE 	/* To use alternate (extended), normal or GMAC4 descriptor structures */
3953f748be53SAlexandre TORGUE 	if (priv->synopsys_id >= DWMAC_CORE_4_00)
3954f748be53SAlexandre TORGUE 		priv->hw->desc = &dwmac4_desc_ops;
3955f748be53SAlexandre TORGUE 	else
395661369d02SByungho An 		stmmac_selec_desc_mode(priv);
395761369d02SByungho An 
3958d2afb5bdSGiuseppe CAVALLARO 	if (priv->plat->rx_coe) {
3959d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
396038ddc59dSLABBE Corentin 		dev_info(priv->device, "RX Checksum Offload Engine supported\n");
3961f748be53SAlexandre TORGUE 		if (priv->synopsys_id < DWMAC_CORE_4_00)
396238ddc59dSLABBE Corentin 			dev_info(priv->device, "COE Type %d\n", priv->hw->rx_csum);
3963d2afb5bdSGiuseppe CAVALLARO 	}
3964cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->tx_coe)
396538ddc59dSLABBE Corentin 		dev_info(priv->device, "TX Checksum insertion supported\n");
3966cf3f047bSGiuseppe CAVALLARO 
3967cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->pmt) {
396838ddc59dSLABBE Corentin 		dev_info(priv->device, "Wake-Up On Lan supported\n");
3969cf3f047bSGiuseppe CAVALLARO 		device_set_wakeup_capable(priv->device, 1);
3970cf3f047bSGiuseppe CAVALLARO 	}
3971cf3f047bSGiuseppe CAVALLARO 
3972f748be53SAlexandre TORGUE 	if (priv->dma_cap.tsoen)
397338ddc59dSLABBE Corentin 		dev_info(priv->device, "TSO supported\n");
3974f748be53SAlexandre TORGUE 
3975c24602efSGiuseppe CAVALLARO 	return 0;
3976cf3f047bSGiuseppe CAVALLARO }
3977cf3f047bSGiuseppe CAVALLARO 
3978cf3f047bSGiuseppe CAVALLARO /**
3979bfab27a1SGiuseppe CAVALLARO  * stmmac_dvr_probe
3980bfab27a1SGiuseppe CAVALLARO  * @device: device pointer
3981ff3dd78cSGiuseppe CAVALLARO  * @plat_dat: platform data pointer
3982e56788cfSJoachim Eastwood  * @res: stmmac resource pointer
3983bfab27a1SGiuseppe CAVALLARO  * Description: this is the main probe function used to
3984bfab27a1SGiuseppe CAVALLARO  * call the alloc_etherdev, allocate the priv structure.
39859afec6efSAndy Shevchenko  * Return:
398615ffac73SJoachim Eastwood  * returns 0 on success, otherwise errno.
39877ac6653aSJeff Kirsher  */
398815ffac73SJoachim Eastwood int stmmac_dvr_probe(struct device *device,
3989cf3f047bSGiuseppe CAVALLARO 		     struct plat_stmmacenet_data *plat_dat,
3990e56788cfSJoachim Eastwood 		     struct stmmac_resources *res)
39917ac6653aSJeff Kirsher {
39925bacd778SLABBE Corentin 	int ret = 0;
3993bfab27a1SGiuseppe CAVALLARO 	struct net_device *ndev = NULL;
3994bfab27a1SGiuseppe CAVALLARO 	struct stmmac_priv *priv;
39957ac6653aSJeff Kirsher 
39965bacd778SLABBE Corentin 	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
399741de8d4cSJoe Perches 	if (!ndev)
399815ffac73SJoachim Eastwood 		return -ENOMEM;
39997ac6653aSJeff Kirsher 
4000bfab27a1SGiuseppe CAVALLARO 	SET_NETDEV_DEV(ndev, device);
40017ac6653aSJeff Kirsher 
4002bfab27a1SGiuseppe CAVALLARO 	priv = netdev_priv(ndev);
4003bfab27a1SGiuseppe CAVALLARO 	priv->device = device;
4004bfab27a1SGiuseppe CAVALLARO 	priv->dev = ndev;
4005bfab27a1SGiuseppe CAVALLARO 
4006bfab27a1SGiuseppe CAVALLARO 	stmmac_set_ethtool_ops(ndev);
4007cf3f047bSGiuseppe CAVALLARO 	priv->pause = pause;
4008cf3f047bSGiuseppe CAVALLARO 	priv->plat = plat_dat;
4009e56788cfSJoachim Eastwood 	priv->ioaddr = res->addr;
4010e56788cfSJoachim Eastwood 	priv->dev->base_addr = (unsigned long)res->addr;
4011e56788cfSJoachim Eastwood 
4012e56788cfSJoachim Eastwood 	priv->dev->irq = res->irq;
4013e56788cfSJoachim Eastwood 	priv->wol_irq = res->wol_irq;
4014e56788cfSJoachim Eastwood 	priv->lpi_irq = res->lpi_irq;
4015e56788cfSJoachim Eastwood 
4016e56788cfSJoachim Eastwood 	if (res->mac)
4017e56788cfSJoachim Eastwood 		memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN);
4018bfab27a1SGiuseppe CAVALLARO 
4019a7a62685SJoachim Eastwood 	dev_set_drvdata(device, priv->dev);
4020803f8fc4SJoachim Eastwood 
4021cf3f047bSGiuseppe CAVALLARO 	/* Verify driver arguments */
4022cf3f047bSGiuseppe CAVALLARO 	stmmac_verify_args();
4023cf3f047bSGiuseppe CAVALLARO 
4024cf3f047bSGiuseppe CAVALLARO 	/* Override with kernel parameters if supplied XXX CRS XXX
4025ceb69499SGiuseppe CAVALLARO 	 * this needs to have multiple instances
4026ceb69499SGiuseppe CAVALLARO 	 */
4027cf3f047bSGiuseppe CAVALLARO 	if ((phyaddr >= 0) && (phyaddr <= 31))
4028cf3f047bSGiuseppe CAVALLARO 		priv->plat->phy_addr = phyaddr;
4029cf3f047bSGiuseppe CAVALLARO 
4030f573c0b9Sjpinto 	if (priv->plat->stmmac_rst)
4031f573c0b9Sjpinto 		reset_control_deassert(priv->plat->stmmac_rst);
4032c5e4ddbdSChen-Yu Tsai 
4033cf3f047bSGiuseppe CAVALLARO 	/* Init MAC and get the capabilities */
4034c24602efSGiuseppe CAVALLARO 	ret = stmmac_hw_init(priv);
4035c24602efSGiuseppe CAVALLARO 	if (ret)
403662866e98SChen-Yu Tsai 		goto error_hw_init;
4037cf3f047bSGiuseppe CAVALLARO 
4038cf3f047bSGiuseppe CAVALLARO 	ndev->netdev_ops = &stmmac_netdev_ops;
4039cf3f047bSGiuseppe CAVALLARO 
4040cf3f047bSGiuseppe CAVALLARO 	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
4041cf3f047bSGiuseppe CAVALLARO 			    NETIF_F_RXCSUM;
4042f748be53SAlexandre TORGUE 
4043f748be53SAlexandre TORGUE 	if ((priv->plat->tso_en) && (priv->dma_cap.tsoen)) {
4044f748be53SAlexandre TORGUE 		ndev->hw_features |= NETIF_F_TSO;
4045f748be53SAlexandre TORGUE 		priv->tso = true;
404638ddc59dSLABBE Corentin 		dev_info(priv->device, "TSO feature enabled\n");
4047f748be53SAlexandre TORGUE 	}
4048bfab27a1SGiuseppe CAVALLARO 	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
4049bfab27a1SGiuseppe CAVALLARO 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
40507ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED
40517ac6653aSJeff Kirsher 	/* Both mac100 and gmac support receive VLAN tag detection */
4052f646968fSPatrick McHardy 	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
40537ac6653aSJeff Kirsher #endif
40547ac6653aSJeff Kirsher 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
40557ac6653aSJeff Kirsher 
405644770e11SJarod Wilson 	/* MTU range: 46 - hw-specific max */
405744770e11SJarod Wilson 	ndev->min_mtu = ETH_ZLEN - ETH_HLEN;
405844770e11SJarod Wilson 	if ((priv->plat->enh_desc) || (priv->synopsys_id >= DWMAC_CORE_4_00))
405944770e11SJarod Wilson 		ndev->max_mtu = JUMBO_LEN;
406044770e11SJarod Wilson 	else
406144770e11SJarod Wilson 		ndev->max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
4062a2cd64f3SKweh, Hock Leong 	/* Will not overwrite ndev->max_mtu if plat->maxmtu > ndev->max_mtu
4063a2cd64f3SKweh, Hock Leong 	 * as well as plat->maxmtu < ndev->min_mtu which is a invalid range.
4064a2cd64f3SKweh, Hock Leong 	 */
4065a2cd64f3SKweh, Hock Leong 	if ((priv->plat->maxmtu < ndev->max_mtu) &&
4066a2cd64f3SKweh, Hock Leong 	    (priv->plat->maxmtu >= ndev->min_mtu))
406744770e11SJarod Wilson 		ndev->max_mtu = priv->plat->maxmtu;
4068a2cd64f3SKweh, Hock Leong 	else if (priv->plat->maxmtu < ndev->min_mtu)
4069b618ab45SHeiner Kallweit 		dev_warn(priv->device,
4070a2cd64f3SKweh, Hock Leong 			 "%s: warning: maxmtu having invalid value (%d)\n",
4071a2cd64f3SKweh, Hock Leong 			 __func__, priv->plat->maxmtu);
407244770e11SJarod Wilson 
40737ac6653aSJeff Kirsher 	if (flow_ctrl)
40747ac6653aSJeff Kirsher 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
40757ac6653aSJeff Kirsher 
407662a2ab93SGiuseppe CAVALLARO 	/* Rx Watchdog is available in the COREs newer than the 3.40.
407762a2ab93SGiuseppe CAVALLARO 	 * In some case, for example on bugged HW this feature
407862a2ab93SGiuseppe CAVALLARO 	 * has to be disable and this can be done by passing the
407962a2ab93SGiuseppe CAVALLARO 	 * riwt_off field from the platform.
408062a2ab93SGiuseppe CAVALLARO 	 */
408162a2ab93SGiuseppe CAVALLARO 	if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
408262a2ab93SGiuseppe CAVALLARO 		priv->use_riwt = 1;
4083b618ab45SHeiner Kallweit 		dev_info(priv->device,
4084b618ab45SHeiner Kallweit 			 "Enable RX Mitigation via HW Watchdog Timer\n");
408562a2ab93SGiuseppe CAVALLARO 	}
408662a2ab93SGiuseppe CAVALLARO 
40875bacd778SLABBE Corentin 	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
40887ac6653aSJeff Kirsher 
40897ac6653aSJeff Kirsher 	spin_lock_init(&priv->lock);
40907ac6653aSJeff Kirsher 
4091cd7201f4SGiuseppe CAVALLARO 	/* If a specific clk_csr value is passed from the platform
4092cd7201f4SGiuseppe CAVALLARO 	 * this means that the CSR Clock Range selection cannot be
4093cd7201f4SGiuseppe CAVALLARO 	 * changed at run-time and it is fixed. Viceversa the driver'll try to
4094cd7201f4SGiuseppe CAVALLARO 	 * set the MDC clock dynamically according to the csr actual
4095cd7201f4SGiuseppe CAVALLARO 	 * clock input.
4096cd7201f4SGiuseppe CAVALLARO 	 */
4097cd7201f4SGiuseppe CAVALLARO 	if (!priv->plat->clk_csr)
4098cd7201f4SGiuseppe CAVALLARO 		stmmac_clk_csr_set(priv);
4099cd7201f4SGiuseppe CAVALLARO 	else
4100cd7201f4SGiuseppe CAVALLARO 		priv->clk_csr = priv->plat->clk_csr;
4101cd7201f4SGiuseppe CAVALLARO 
4102e58bb43fSGiuseppe CAVALLARO 	stmmac_check_pcs_mode(priv);
4103e58bb43fSGiuseppe CAVALLARO 
41043fe5cadbSGiuseppe CAVALLARO 	if (priv->hw->pcs != STMMAC_PCS_RGMII  &&
41053fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_TBI &&
41063fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_RTBI) {
41074bfcbd7aSFrancesco Virlinzi 		/* MDIO bus Registration */
41084bfcbd7aSFrancesco Virlinzi 		ret = stmmac_mdio_register(ndev);
41094bfcbd7aSFrancesco Virlinzi 		if (ret < 0) {
4110b618ab45SHeiner Kallweit 			dev_err(priv->device,
411138ddc59dSLABBE Corentin 				"%s: MDIO bus (id: %d) registration failed",
41124bfcbd7aSFrancesco Virlinzi 				__func__, priv->plat->bus_id);
41136a81c26fSViresh Kumar 			goto error_mdio_register;
41144bfcbd7aSFrancesco Virlinzi 		}
4115e58bb43fSGiuseppe CAVALLARO 	}
41164bfcbd7aSFrancesco Virlinzi 
411757016590SFlorian Fainelli 	ret = register_netdev(ndev);
4118b2eb09afSFlorian Fainelli 	if (ret) {
4119b618ab45SHeiner Kallweit 		dev_err(priv->device, "%s: ERROR %i registering the device\n",
412057016590SFlorian Fainelli 			__func__, ret);
4121b2eb09afSFlorian Fainelli 		goto error_netdev_register;
4122b2eb09afSFlorian Fainelli 	}
41237ac6653aSJeff Kirsher 
412457016590SFlorian Fainelli 	return ret;
41257ac6653aSJeff Kirsher 
41266a81c26fSViresh Kumar error_netdev_register:
4127b2eb09afSFlorian Fainelli 	if (priv->hw->pcs != STMMAC_PCS_RGMII &&
4128b2eb09afSFlorian Fainelli 	    priv->hw->pcs != STMMAC_PCS_TBI &&
4129b2eb09afSFlorian Fainelli 	    priv->hw->pcs != STMMAC_PCS_RTBI)
4130b2eb09afSFlorian Fainelli 		stmmac_mdio_unregister(ndev);
41317ac6653aSJeff Kirsher error_mdio_register:
41325bacd778SLABBE Corentin 	netif_napi_del(&priv->napi);
413362866e98SChen-Yu Tsai error_hw_init:
41347ac6653aSJeff Kirsher 	free_netdev(ndev);
41357ac6653aSJeff Kirsher 
413615ffac73SJoachim Eastwood 	return ret;
41377ac6653aSJeff Kirsher }
4138b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_probe);
41397ac6653aSJeff Kirsher 
41407ac6653aSJeff Kirsher /**
41417ac6653aSJeff Kirsher  * stmmac_dvr_remove
4142f4e7bd81SJoachim Eastwood  * @dev: device pointer
41437ac6653aSJeff Kirsher  * Description: this function resets the TX/RX processes, disables the MAC RX/TX
4144bfab27a1SGiuseppe CAVALLARO  * changes the link status, releases the DMA descriptor rings.
41457ac6653aSJeff Kirsher  */
4146f4e7bd81SJoachim Eastwood int stmmac_dvr_remove(struct device *dev)
41477ac6653aSJeff Kirsher {
4148f4e7bd81SJoachim Eastwood 	struct net_device *ndev = dev_get_drvdata(dev);
41497ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
41507ac6653aSJeff Kirsher 
415138ddc59dSLABBE Corentin 	netdev_info(priv->dev, "%s: removing driver", __func__);
41527ac6653aSJeff Kirsher 
4153ae4f0d46SJoao Pinto 	stmmac_stop_all_dma(priv);
41547ac6653aSJeff Kirsher 
4155270c7759SLABBE Corentin 	priv->hw->mac->set_mac(priv->ioaddr, false);
41567ac6653aSJeff Kirsher 	netif_carrier_off(ndev);
41577ac6653aSJeff Kirsher 	unregister_netdev(ndev);
4158f573c0b9Sjpinto 	if (priv->plat->stmmac_rst)
4159f573c0b9Sjpinto 		reset_control_assert(priv->plat->stmmac_rst);
4160f573c0b9Sjpinto 	clk_disable_unprepare(priv->plat->pclk);
4161f573c0b9Sjpinto 	clk_disable_unprepare(priv->plat->stmmac_clk);
41623fe5cadbSGiuseppe CAVALLARO 	if (priv->hw->pcs != STMMAC_PCS_RGMII &&
41633fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_TBI &&
41643fe5cadbSGiuseppe CAVALLARO 	    priv->hw->pcs != STMMAC_PCS_RTBI)
4165e743471fSBryan O'Donoghue 		stmmac_mdio_unregister(ndev);
41667ac6653aSJeff Kirsher 	free_netdev(ndev);
41677ac6653aSJeff Kirsher 
41687ac6653aSJeff Kirsher 	return 0;
41697ac6653aSJeff Kirsher }
4170b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_remove);
41717ac6653aSJeff Kirsher 
4172732fdf0eSGiuseppe CAVALLARO /**
4173732fdf0eSGiuseppe CAVALLARO  * stmmac_suspend - suspend callback
4174f4e7bd81SJoachim Eastwood  * @dev: device pointer
4175732fdf0eSGiuseppe CAVALLARO  * Description: this is the function to suspend the device and it is called
4176732fdf0eSGiuseppe CAVALLARO  * by the platform driver to stop the network queue, release the resources,
4177732fdf0eSGiuseppe CAVALLARO  * program the PMT register (for WoL), clean and release driver resources.
4178732fdf0eSGiuseppe CAVALLARO  */
4179f4e7bd81SJoachim Eastwood int stmmac_suspend(struct device *dev)
41807ac6653aSJeff Kirsher {
4181f4e7bd81SJoachim Eastwood 	struct net_device *ndev = dev_get_drvdata(dev);
41827ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
4183f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
41847ac6653aSJeff Kirsher 
41857ac6653aSJeff Kirsher 	if (!ndev || !netif_running(ndev))
41867ac6653aSJeff Kirsher 		return 0;
41877ac6653aSJeff Kirsher 
4188d6d50c7eSPhilippe Reynes 	if (ndev->phydev)
4189d6d50c7eSPhilippe Reynes 		phy_stop(ndev->phydev);
4190102463b1SFrancesco Virlinzi 
4191f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
41927ac6653aSJeff Kirsher 
41937ac6653aSJeff Kirsher 	netif_device_detach(ndev);
41945bacd778SLABBE Corentin 	netif_stop_queue(ndev);
41957ac6653aSJeff Kirsher 
41965bacd778SLABBE Corentin 	napi_disable(&priv->napi);
41977ac6653aSJeff Kirsher 
41987ac6653aSJeff Kirsher 	/* Stop TX/RX DMA */
4199ae4f0d46SJoao Pinto 	stmmac_stop_all_dma(priv);
4200c24602efSGiuseppe CAVALLARO 
42017ac6653aSJeff Kirsher 	/* Enable Power down mode by programming the PMT regs */
420289f7f2cfSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
42037ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, priv->wolopts);
420489f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 1;
420589f7f2cfSSrinivas Kandagatla 	} else {
4206270c7759SLABBE Corentin 		priv->hw->mac->set_mac(priv->ioaddr, false);
4207db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_sleep_state(priv->device);
4208ba1377ffSGiuseppe CAVALLARO 		/* Disable clock in case of PWM is off */
4209f573c0b9Sjpinto 		clk_disable(priv->plat->pclk);
4210f573c0b9Sjpinto 		clk_disable(priv->plat->stmmac_clk);
4211ba1377ffSGiuseppe CAVALLARO 	}
4212f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
42132d871aa0SVince Bridgers 
42142d871aa0SVince Bridgers 	priv->oldlink = 0;
4215bd00632cSLABBE Corentin 	priv->speed = SPEED_UNKNOWN;
4216bd00632cSLABBE Corentin 	priv->oldduplex = DUPLEX_UNKNOWN;
42177ac6653aSJeff Kirsher 	return 0;
42187ac6653aSJeff Kirsher }
4219b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_suspend);
42207ac6653aSJeff Kirsher 
4221732fdf0eSGiuseppe CAVALLARO /**
422254139cf3SJoao Pinto  * stmmac_reset_queues_param - reset queue parameters
422354139cf3SJoao Pinto  * @dev: device pointer
422454139cf3SJoao Pinto  */
422554139cf3SJoao Pinto static void stmmac_reset_queues_param(struct stmmac_priv *priv)
422654139cf3SJoao Pinto {
422754139cf3SJoao Pinto 	u32 rx_cnt = priv->plat->rx_queues_to_use;
4228ce736788SJoao Pinto 	u32 tx_cnt = priv->plat->tx_queues_to_use;
422954139cf3SJoao Pinto 	u32 queue;
423054139cf3SJoao Pinto 
423154139cf3SJoao Pinto 	for (queue = 0; queue < rx_cnt; queue++) {
423254139cf3SJoao Pinto 		struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
423354139cf3SJoao Pinto 
423454139cf3SJoao Pinto 		rx_q->cur_rx = 0;
423554139cf3SJoao Pinto 		rx_q->dirty_rx = 0;
423654139cf3SJoao Pinto 	}
423754139cf3SJoao Pinto 
4238ce736788SJoao Pinto 	for (queue = 0; queue < tx_cnt; queue++) {
4239ce736788SJoao Pinto 		struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
4240ce736788SJoao Pinto 
4241ce736788SJoao Pinto 		tx_q->cur_tx = 0;
4242ce736788SJoao Pinto 		tx_q->dirty_tx = 0;
4243ce736788SJoao Pinto 	}
424454139cf3SJoao Pinto }
424554139cf3SJoao Pinto 
424654139cf3SJoao Pinto /**
4247732fdf0eSGiuseppe CAVALLARO  * stmmac_resume - resume callback
4248f4e7bd81SJoachim Eastwood  * @dev: device pointer
4249732fdf0eSGiuseppe CAVALLARO  * Description: when resume this function is invoked to setup the DMA and CORE
4250732fdf0eSGiuseppe CAVALLARO  * in a usable state.
4251732fdf0eSGiuseppe CAVALLARO  */
4252f4e7bd81SJoachim Eastwood int stmmac_resume(struct device *dev)
42537ac6653aSJeff Kirsher {
4254f4e7bd81SJoachim Eastwood 	struct net_device *ndev = dev_get_drvdata(dev);
42557ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
4256f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
42577ac6653aSJeff Kirsher 
42587ac6653aSJeff Kirsher 	if (!netif_running(ndev))
42597ac6653aSJeff Kirsher 		return 0;
42607ac6653aSJeff Kirsher 
42617ac6653aSJeff Kirsher 	/* Power Down bit, into the PM register, is cleared
42627ac6653aSJeff Kirsher 	 * automatically as soon as a magic packet or a Wake-up frame
42637ac6653aSJeff Kirsher 	 * is received. Anyway, it's better to manually clear
42647ac6653aSJeff Kirsher 	 * this bit because it can generate problems while resuming
4265ceb69499SGiuseppe CAVALLARO 	 * from another devices (e.g. serial console).
4266ceb69499SGiuseppe CAVALLARO 	 */
4267623997fbSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
4268f55d84b0SVincent Palatin 		spin_lock_irqsave(&priv->lock, flags);
42697ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, 0);
4270f55d84b0SVincent Palatin 		spin_unlock_irqrestore(&priv->lock, flags);
427189f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 0;
4272623997fbSSrinivas Kandagatla 	} else {
4273db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_default_state(priv->device);
42748d45e42bSLABBE Corentin 		/* enable the clk previously disabled */
4275f573c0b9Sjpinto 		clk_enable(priv->plat->stmmac_clk);
4276f573c0b9Sjpinto 		clk_enable(priv->plat->pclk);
4277623997fbSSrinivas Kandagatla 		/* reset the phy so that it's ready */
4278623997fbSSrinivas Kandagatla 		if (priv->mii)
4279623997fbSSrinivas Kandagatla 			stmmac_mdio_reset(priv->mii);
4280623997fbSSrinivas Kandagatla 	}
42817ac6653aSJeff Kirsher 
42827ac6653aSJeff Kirsher 	netif_device_attach(ndev);
42837ac6653aSJeff Kirsher 
4284f55d84b0SVincent Palatin 	spin_lock_irqsave(&priv->lock, flags);
4285f55d84b0SVincent Palatin 
428654139cf3SJoao Pinto 	stmmac_reset_queues_param(priv);
428754139cf3SJoao Pinto 
4288f748be53SAlexandre TORGUE 	/* reset private mss value to force mss context settings at
4289f748be53SAlexandre TORGUE 	 * next tso xmit (only used for gmac4).
4290f748be53SAlexandre TORGUE 	 */
4291f748be53SAlexandre TORGUE 	priv->mss = 0;
4292f748be53SAlexandre TORGUE 
4293ae79a639SGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
4294ae79a639SGiuseppe CAVALLARO 
4295fe131929SHuacai Chen 	stmmac_hw_setup(ndev, false);
4296777da230SGiuseppe CAVALLARO 	stmmac_init_tx_coalesce(priv);
4297ac316c78SGiuseppe CAVALLARO 	stmmac_set_rx_mode(ndev);
42987ac6653aSJeff Kirsher 
42995bacd778SLABBE Corentin 	napi_enable(&priv->napi);
43007ac6653aSJeff Kirsher 
43015bacd778SLABBE Corentin 	netif_start_queue(ndev);
43027ac6653aSJeff Kirsher 
4303f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
4304102463b1SFrancesco Virlinzi 
4305d6d50c7eSPhilippe Reynes 	if (ndev->phydev)
4306d6d50c7eSPhilippe Reynes 		phy_start(ndev->phydev);
4307102463b1SFrancesco Virlinzi 
43087ac6653aSJeff Kirsher 	return 0;
43097ac6653aSJeff Kirsher }
4310b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_resume);
4311ba27ec66SGiuseppe CAVALLARO 
43127ac6653aSJeff Kirsher #ifndef MODULE
43137ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str)
43147ac6653aSJeff Kirsher {
43157ac6653aSJeff Kirsher 	char *opt;
43167ac6653aSJeff Kirsher 
43177ac6653aSJeff Kirsher 	if (!str || !*str)
43187ac6653aSJeff Kirsher 		return -EINVAL;
43197ac6653aSJeff Kirsher 	while ((opt = strsep(&str, ",")) != NULL) {
43207ac6653aSJeff Kirsher 		if (!strncmp(opt, "debug:", 6)) {
4321ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &debug))
43227ac6653aSJeff Kirsher 				goto err;
43237ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "phyaddr:", 8)) {
4324ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 8, 0, &phyaddr))
43257ac6653aSJeff Kirsher 				goto err;
43267ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "buf_sz:", 7)) {
4327ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 7, 0, &buf_sz))
43287ac6653aSJeff Kirsher 				goto err;
43297ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "tc:", 3)) {
4330ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 3, 0, &tc))
43317ac6653aSJeff Kirsher 				goto err;
43327ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "watchdog:", 9)) {
4333ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 9, 0, &watchdog))
43347ac6653aSJeff Kirsher 				goto err;
43357ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "flow_ctrl:", 10)) {
4336ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &flow_ctrl))
43377ac6653aSJeff Kirsher 				goto err;
43387ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "pause:", 6)) {
4339ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &pause))
43407ac6653aSJeff Kirsher 				goto err;
4341506f669cSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "eee_timer:", 10)) {
4342d765955dSGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &eee_timer))
4343d765955dSGiuseppe CAVALLARO 				goto err;
43444a7d666aSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "chain_mode:", 11)) {
43454a7d666aSGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &chain_mode))
43464a7d666aSGiuseppe CAVALLARO 				goto err;
43477ac6653aSJeff Kirsher 		}
43487ac6653aSJeff Kirsher 	}
43497ac6653aSJeff Kirsher 	return 0;
43507ac6653aSJeff Kirsher 
43517ac6653aSJeff Kirsher err:
43527ac6653aSJeff Kirsher 	pr_err("%s: ERROR broken module parameter conversion", __func__);
43537ac6653aSJeff Kirsher 	return -EINVAL;
43547ac6653aSJeff Kirsher }
43557ac6653aSJeff Kirsher 
43567ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt);
4357ceb69499SGiuseppe CAVALLARO #endif /* MODULE */
43586fc0d0f2SGiuseppe Cavallaro 
4359466c5ac8SMathieu Olivari static int __init stmmac_init(void)
4360466c5ac8SMathieu Olivari {
4361466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS
4362466c5ac8SMathieu Olivari 	/* Create debugfs main directory if it doesn't exist yet */
4363466c5ac8SMathieu Olivari 	if (!stmmac_fs_dir) {
4364466c5ac8SMathieu Olivari 		stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
4365466c5ac8SMathieu Olivari 
4366466c5ac8SMathieu Olivari 		if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
4367466c5ac8SMathieu Olivari 			pr_err("ERROR %s, debugfs create directory failed\n",
4368466c5ac8SMathieu Olivari 			       STMMAC_RESOURCE_NAME);
4369466c5ac8SMathieu Olivari 
4370466c5ac8SMathieu Olivari 			return -ENOMEM;
4371466c5ac8SMathieu Olivari 		}
4372466c5ac8SMathieu Olivari 	}
4373466c5ac8SMathieu Olivari #endif
4374466c5ac8SMathieu Olivari 
4375466c5ac8SMathieu Olivari 	return 0;
4376466c5ac8SMathieu Olivari }
4377466c5ac8SMathieu Olivari 
4378466c5ac8SMathieu Olivari static void __exit stmmac_exit(void)
4379466c5ac8SMathieu Olivari {
4380466c5ac8SMathieu Olivari #ifdef CONFIG_DEBUG_FS
4381466c5ac8SMathieu Olivari 	debugfs_remove_recursive(stmmac_fs_dir);
4382466c5ac8SMathieu Olivari #endif
4383466c5ac8SMathieu Olivari }
4384466c5ac8SMathieu Olivari 
4385466c5ac8SMathieu Olivari module_init(stmmac_init)
4386466c5ac8SMathieu Olivari module_exit(stmmac_exit)
4387466c5ac8SMathieu Olivari 
43886fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
43896fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
43906fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL");
4391