17ac6653aSJeff Kirsher /*******************************************************************************
27ac6653aSJeff Kirsher   This is the driver for the ST MAC 10/100/1000 on-chip Ethernet controllers.
37ac6653aSJeff Kirsher   ST Ethernet IPs are built around a Synopsys IP Core.
47ac6653aSJeff Kirsher 
5286a8372SGiuseppe CAVALLARO 	Copyright(C) 2007-2011 STMicroelectronics Ltd
67ac6653aSJeff Kirsher 
77ac6653aSJeff Kirsher   This program is free software; you can redistribute it and/or modify it
87ac6653aSJeff Kirsher   under the terms and conditions of the GNU General Public License,
97ac6653aSJeff Kirsher   version 2, as published by the Free Software Foundation.
107ac6653aSJeff Kirsher 
117ac6653aSJeff Kirsher   This program is distributed in the hope it will be useful, but WITHOUT
127ac6653aSJeff Kirsher   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
137ac6653aSJeff Kirsher   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
147ac6653aSJeff Kirsher   more details.
157ac6653aSJeff Kirsher 
167ac6653aSJeff Kirsher   You should have received a copy of the GNU General Public License along with
177ac6653aSJeff Kirsher   this program; if not, write to the Free Software Foundation, Inc.,
187ac6653aSJeff Kirsher   51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
197ac6653aSJeff Kirsher 
207ac6653aSJeff Kirsher   The full GNU General Public License is included in this distribution in
217ac6653aSJeff Kirsher   the file called "COPYING".
227ac6653aSJeff Kirsher 
237ac6653aSJeff Kirsher   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
247ac6653aSJeff Kirsher 
257ac6653aSJeff Kirsher   Documentation available at:
267ac6653aSJeff Kirsher 	http://www.stlinux.com
277ac6653aSJeff Kirsher   Support available at:
287ac6653aSJeff Kirsher 	https://bugzilla.stlinux.com/
297ac6653aSJeff Kirsher *******************************************************************************/
307ac6653aSJeff Kirsher 
316a81c26fSViresh Kumar #include <linux/clk.h>
327ac6653aSJeff Kirsher #include <linux/kernel.h>
337ac6653aSJeff Kirsher #include <linux/interrupt.h>
347ac6653aSJeff Kirsher #include <linux/ip.h>
357ac6653aSJeff Kirsher #include <linux/tcp.h>
367ac6653aSJeff Kirsher #include <linux/skbuff.h>
377ac6653aSJeff Kirsher #include <linux/ethtool.h>
387ac6653aSJeff Kirsher #include <linux/if_ether.h>
397ac6653aSJeff Kirsher #include <linux/crc32.h>
407ac6653aSJeff Kirsher #include <linux/mii.h>
4101789349SJiri Pirko #include <linux/if.h>
427ac6653aSJeff Kirsher #include <linux/if_vlan.h>
437ac6653aSJeff Kirsher #include <linux/dma-mapping.h>
447ac6653aSJeff Kirsher #include <linux/slab.h>
457ac6653aSJeff Kirsher #include <linux/prefetch.h>
46db88f10aSSrinivas Kandagatla #include <linux/pinctrl/consumer.h>
4750fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
487ac29055SGiuseppe CAVALLARO #include <linux/debugfs.h>
497ac29055SGiuseppe CAVALLARO #include <linux/seq_file.h>
5050fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */
51891434b1SRayagond Kokatanur #include <linux/net_tstamp.h>
52891434b1SRayagond Kokatanur #include "stmmac_ptp.h"
53286a8372SGiuseppe CAVALLARO #include "stmmac.h"
54c5e4ddbdSChen-Yu Tsai #include <linux/reset.h>
557ac6653aSJeff Kirsher 
567ac6653aSJeff Kirsher #define STMMAC_ALIGN(x)	L1_CACHE_ALIGN(x)
577ac6653aSJeff Kirsher 
587ac6653aSJeff Kirsher /* Module parameters */
5932ceabcaSGiuseppe CAVALLARO #define TX_TIMEO	5000
607ac6653aSJeff Kirsher static int watchdog = TX_TIMEO;
617ac6653aSJeff Kirsher module_param(watchdog, int, S_IRUGO | S_IWUSR);
6232ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(watchdog, "Transmit timeout in milliseconds (default 5s)");
637ac6653aSJeff Kirsher 
6432ceabcaSGiuseppe CAVALLARO static int debug = -1;
657ac6653aSJeff Kirsher module_param(debug, int, S_IRUGO | S_IWUSR);
6632ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)");
677ac6653aSJeff Kirsher 
6847d1f71fSstephen hemminger static int phyaddr = -1;
697ac6653aSJeff Kirsher module_param(phyaddr, int, S_IRUGO);
707ac6653aSJeff Kirsher MODULE_PARM_DESC(phyaddr, "Physical device address");
717ac6653aSJeff Kirsher 
727ac6653aSJeff Kirsher #define DMA_TX_SIZE 256
737ac6653aSJeff Kirsher static int dma_txsize = DMA_TX_SIZE;
747ac6653aSJeff Kirsher module_param(dma_txsize, int, S_IRUGO | S_IWUSR);
757ac6653aSJeff Kirsher MODULE_PARM_DESC(dma_txsize, "Number of descriptors in the TX list");
767ac6653aSJeff Kirsher 
777ac6653aSJeff Kirsher #define DMA_RX_SIZE 256
787ac6653aSJeff Kirsher static int dma_rxsize = DMA_RX_SIZE;
797ac6653aSJeff Kirsher module_param(dma_rxsize, int, S_IRUGO | S_IWUSR);
807ac6653aSJeff Kirsher MODULE_PARM_DESC(dma_rxsize, "Number of descriptors in the RX list");
817ac6653aSJeff Kirsher 
827ac6653aSJeff Kirsher static int flow_ctrl = FLOW_OFF;
837ac6653aSJeff Kirsher module_param(flow_ctrl, int, S_IRUGO | S_IWUSR);
847ac6653aSJeff Kirsher MODULE_PARM_DESC(flow_ctrl, "Flow control ability [on/off]");
857ac6653aSJeff Kirsher 
867ac6653aSJeff Kirsher static int pause = PAUSE_TIME;
877ac6653aSJeff Kirsher module_param(pause, int, S_IRUGO | S_IWUSR);
887ac6653aSJeff Kirsher MODULE_PARM_DESC(pause, "Flow Control Pause Time");
897ac6653aSJeff Kirsher 
907ac6653aSJeff Kirsher #define TC_DEFAULT 64
917ac6653aSJeff Kirsher static int tc = TC_DEFAULT;
927ac6653aSJeff Kirsher module_param(tc, int, S_IRUGO | S_IWUSR);
937ac6653aSJeff Kirsher MODULE_PARM_DESC(tc, "DMA threshold control value");
947ac6653aSJeff Kirsher 
95d916701cSGiuseppe CAVALLARO #define	DEFAULT_BUFSIZE	1536
96d916701cSGiuseppe CAVALLARO static int buf_sz = DEFAULT_BUFSIZE;
977ac6653aSJeff Kirsher module_param(buf_sz, int, S_IRUGO | S_IWUSR);
987ac6653aSJeff Kirsher MODULE_PARM_DESC(buf_sz, "DMA buffer size");
997ac6653aSJeff Kirsher 
1007ac6653aSJeff Kirsher static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
1017ac6653aSJeff Kirsher 				      NETIF_MSG_LINK | NETIF_MSG_IFUP |
1027ac6653aSJeff Kirsher 				      NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
1037ac6653aSJeff Kirsher 
104d765955dSGiuseppe CAVALLARO #define STMMAC_DEFAULT_LPI_TIMER	1000
105d765955dSGiuseppe CAVALLARO static int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
106d765955dSGiuseppe CAVALLARO module_param(eee_timer, int, S_IRUGO | S_IWUSR);
107d765955dSGiuseppe CAVALLARO MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
108f5351ef7SGiuseppe CAVALLARO #define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x))
109d765955dSGiuseppe CAVALLARO 
1104a7d666aSGiuseppe CAVALLARO /* By default the driver will use the ring mode to manage tx and rx descriptors
1114a7d666aSGiuseppe CAVALLARO  * but passing this value so user can force to use the chain instead of the ring
1124a7d666aSGiuseppe CAVALLARO  */
1134a7d666aSGiuseppe CAVALLARO static unsigned int chain_mode;
1144a7d666aSGiuseppe CAVALLARO module_param(chain_mode, int, S_IRUGO);
1154a7d666aSGiuseppe CAVALLARO MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode");
1164a7d666aSGiuseppe CAVALLARO 
1177ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
1187ac6653aSJeff Kirsher 
11950fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
120bfab27a1SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev);
121bfab27a1SGiuseppe CAVALLARO static void stmmac_exit_fs(void);
122bfab27a1SGiuseppe CAVALLARO #endif
123bfab27a1SGiuseppe CAVALLARO 
1249125cdd1SGiuseppe CAVALLARO #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
1259125cdd1SGiuseppe CAVALLARO 
1267ac6653aSJeff Kirsher /**
1277ac6653aSJeff Kirsher  * stmmac_verify_args - verify the driver parameters.
128732fdf0eSGiuseppe CAVALLARO  * Description: it checks the driver parameters and set a default in case of
129732fdf0eSGiuseppe CAVALLARO  * errors.
1307ac6653aSJeff Kirsher  */
1317ac6653aSJeff Kirsher static void stmmac_verify_args(void)
1327ac6653aSJeff Kirsher {
1337ac6653aSJeff Kirsher 	if (unlikely(watchdog < 0))
1347ac6653aSJeff Kirsher 		watchdog = TX_TIMEO;
1357ac6653aSJeff Kirsher 	if (unlikely(dma_rxsize < 0))
1367ac6653aSJeff Kirsher 		dma_rxsize = DMA_RX_SIZE;
1377ac6653aSJeff Kirsher 	if (unlikely(dma_txsize < 0))
1387ac6653aSJeff Kirsher 		dma_txsize = DMA_TX_SIZE;
139d916701cSGiuseppe CAVALLARO 	if (unlikely((buf_sz < DEFAULT_BUFSIZE) || (buf_sz > BUF_SIZE_16KiB)))
140d916701cSGiuseppe CAVALLARO 		buf_sz = DEFAULT_BUFSIZE;
1417ac6653aSJeff Kirsher 	if (unlikely(flow_ctrl > 1))
1427ac6653aSJeff Kirsher 		flow_ctrl = FLOW_AUTO;
1437ac6653aSJeff Kirsher 	else if (likely(flow_ctrl < 0))
1447ac6653aSJeff Kirsher 		flow_ctrl = FLOW_OFF;
1457ac6653aSJeff Kirsher 	if (unlikely((pause < 0) || (pause > 0xffff)))
1467ac6653aSJeff Kirsher 		pause = PAUSE_TIME;
147d765955dSGiuseppe CAVALLARO 	if (eee_timer < 0)
148d765955dSGiuseppe CAVALLARO 		eee_timer = STMMAC_DEFAULT_LPI_TIMER;
1497ac6653aSJeff Kirsher }
1507ac6653aSJeff Kirsher 
15132ceabcaSGiuseppe CAVALLARO /**
15232ceabcaSGiuseppe CAVALLARO  * stmmac_clk_csr_set - dynamically set the MDC clock
15332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
15432ceabcaSGiuseppe CAVALLARO  * Description: this is to dynamically set the MDC clock according to the csr
15532ceabcaSGiuseppe CAVALLARO  * clock input.
15632ceabcaSGiuseppe CAVALLARO  * Note:
15732ceabcaSGiuseppe CAVALLARO  *	If a specific clk_csr value is passed from the platform
15832ceabcaSGiuseppe CAVALLARO  *	this means that the CSR Clock Range selection cannot be
15932ceabcaSGiuseppe CAVALLARO  *	changed at run-time and it is fixed (as reported in the driver
16032ceabcaSGiuseppe CAVALLARO  *	documentation). Viceversa the driver will try to set the MDC
16132ceabcaSGiuseppe CAVALLARO  *	clock dynamically according to the actual clock input.
16232ceabcaSGiuseppe CAVALLARO  */
163cd7201f4SGiuseppe CAVALLARO static void stmmac_clk_csr_set(struct stmmac_priv *priv)
164cd7201f4SGiuseppe CAVALLARO {
165cd7201f4SGiuseppe CAVALLARO 	u32 clk_rate;
166cd7201f4SGiuseppe CAVALLARO 
167cd7201f4SGiuseppe CAVALLARO 	clk_rate = clk_get_rate(priv->stmmac_clk);
168cd7201f4SGiuseppe CAVALLARO 
169cd7201f4SGiuseppe CAVALLARO 	/* Platform provided default clk_csr would be assumed valid
170ceb69499SGiuseppe CAVALLARO 	 * for all other cases except for the below mentioned ones.
171ceb69499SGiuseppe CAVALLARO 	 * For values higher than the IEEE 802.3 specified frequency
172ceb69499SGiuseppe CAVALLARO 	 * we can not estimate the proper divider as it is not known
173ceb69499SGiuseppe CAVALLARO 	 * the frequency of clk_csr_i. So we do not change the default
174ceb69499SGiuseppe CAVALLARO 	 * divider.
175ceb69499SGiuseppe CAVALLARO 	 */
176cd7201f4SGiuseppe CAVALLARO 	if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) {
177cd7201f4SGiuseppe CAVALLARO 		if (clk_rate < CSR_F_35M)
178cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_20_35M;
179cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M))
180cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_35_60M;
181cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M))
182cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_60_100M;
183cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M))
184cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_100_150M;
185cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
186cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_150_250M;
187cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
188cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_250_300M;
189ceb69499SGiuseppe CAVALLARO 	}
190cd7201f4SGiuseppe CAVALLARO }
191cd7201f4SGiuseppe CAVALLARO 
1927ac6653aSJeff Kirsher static void print_pkt(unsigned char *buf, int len)
1937ac6653aSJeff Kirsher {
194424c4f78SAndy Shevchenko 	pr_debug("len = %d byte, buf addr: 0x%p\n", len, buf);
195424c4f78SAndy Shevchenko 	print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
1967ac6653aSJeff Kirsher }
1977ac6653aSJeff Kirsher 
1987ac6653aSJeff Kirsher /* minimum number of free TX descriptors required to wake up TX process */
1997ac6653aSJeff Kirsher #define STMMAC_TX_THRESH(x)	(x->dma_tx_size/4)
2007ac6653aSJeff Kirsher 
2017ac6653aSJeff Kirsher static inline u32 stmmac_tx_avail(struct stmmac_priv *priv)
2027ac6653aSJeff Kirsher {
2037ac6653aSJeff Kirsher 	return priv->dirty_tx + priv->dma_tx_size - priv->cur_tx - 1;
2047ac6653aSJeff Kirsher }
2057ac6653aSJeff Kirsher 
20632ceabcaSGiuseppe CAVALLARO /**
207732fdf0eSGiuseppe CAVALLARO  * stmmac_hw_fix_mac_speed - callback for speed selection
20832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
20932ceabcaSGiuseppe CAVALLARO  * Description: on some platforms (e.g. ST), some HW system configuraton
21032ceabcaSGiuseppe CAVALLARO  * registers have to be set according to the link speed negotiated.
2117ac6653aSJeff Kirsher  */
2127ac6653aSJeff Kirsher static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
2137ac6653aSJeff Kirsher {
2147ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
2157ac6653aSJeff Kirsher 
2167ac6653aSJeff Kirsher 	if (likely(priv->plat->fix_mac_speed))
217ceb69499SGiuseppe CAVALLARO 		priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
2187ac6653aSJeff Kirsher }
2197ac6653aSJeff Kirsher 
22032ceabcaSGiuseppe CAVALLARO /**
221732fdf0eSGiuseppe CAVALLARO  * stmmac_enable_eee_mode - check and enter in LPI mode
22232ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
223732fdf0eSGiuseppe CAVALLARO  * Description: this function is to verify and enter in LPI mode in case of
224732fdf0eSGiuseppe CAVALLARO  * EEE.
22532ceabcaSGiuseppe CAVALLARO  */
226d765955dSGiuseppe CAVALLARO static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
227d765955dSGiuseppe CAVALLARO {
228d765955dSGiuseppe CAVALLARO 	/* Check and enter in LPI mode */
229d765955dSGiuseppe CAVALLARO 	if ((priv->dirty_tx == priv->cur_tx) &&
230d765955dSGiuseppe CAVALLARO 	    (priv->tx_path_in_lpi_mode == false))
2317ed24bbeSVince Bridgers 		priv->hw->mac->set_eee_mode(priv->hw);
232d765955dSGiuseppe CAVALLARO }
233d765955dSGiuseppe CAVALLARO 
23432ceabcaSGiuseppe CAVALLARO /**
235732fdf0eSGiuseppe CAVALLARO  * stmmac_disable_eee_mode - disable and exit from LPI mode
23632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
23732ceabcaSGiuseppe CAVALLARO  * Description: this function is to exit and disable EEE in case of
23832ceabcaSGiuseppe CAVALLARO  * LPI state is true. This is called by the xmit.
23932ceabcaSGiuseppe CAVALLARO  */
240d765955dSGiuseppe CAVALLARO void stmmac_disable_eee_mode(struct stmmac_priv *priv)
241d765955dSGiuseppe CAVALLARO {
2427ed24bbeSVince Bridgers 	priv->hw->mac->reset_eee_mode(priv->hw);
243d765955dSGiuseppe CAVALLARO 	del_timer_sync(&priv->eee_ctrl_timer);
244d765955dSGiuseppe CAVALLARO 	priv->tx_path_in_lpi_mode = false;
245d765955dSGiuseppe CAVALLARO }
246d765955dSGiuseppe CAVALLARO 
247d765955dSGiuseppe CAVALLARO /**
248732fdf0eSGiuseppe CAVALLARO  * stmmac_eee_ctrl_timer - EEE TX SW timer.
249d765955dSGiuseppe CAVALLARO  * @arg : data hook
250d765955dSGiuseppe CAVALLARO  * Description:
25132ceabcaSGiuseppe CAVALLARO  *  if there is no data transfer and if we are not in LPI state,
252d765955dSGiuseppe CAVALLARO  *  then MAC Transmitter can be moved to LPI state.
253d765955dSGiuseppe CAVALLARO  */
254d765955dSGiuseppe CAVALLARO static void stmmac_eee_ctrl_timer(unsigned long arg)
255d765955dSGiuseppe CAVALLARO {
256d765955dSGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)arg;
257d765955dSGiuseppe CAVALLARO 
258d765955dSGiuseppe CAVALLARO 	stmmac_enable_eee_mode(priv);
259f5351ef7SGiuseppe CAVALLARO 	mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
260d765955dSGiuseppe CAVALLARO }
261d765955dSGiuseppe CAVALLARO 
262d765955dSGiuseppe CAVALLARO /**
263732fdf0eSGiuseppe CAVALLARO  * stmmac_eee_init - init EEE
26432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
265d765955dSGiuseppe CAVALLARO  * Description:
266732fdf0eSGiuseppe CAVALLARO  *  if the GMAC supports the EEE (from the HW cap reg) and the phy device
267732fdf0eSGiuseppe CAVALLARO  *  can also manage EEE, this function enable the LPI state and start related
268732fdf0eSGiuseppe CAVALLARO  *  timer.
269d765955dSGiuseppe CAVALLARO  */
270d765955dSGiuseppe CAVALLARO bool stmmac_eee_init(struct stmmac_priv *priv)
271d765955dSGiuseppe CAVALLARO {
27256b88c25SGiuseppe CAVALLARO 	char *phy_bus_name = priv->plat->phy_bus_name;
2734741cf9cSGiuseppe CAVALLARO 	unsigned long flags;
274d765955dSGiuseppe CAVALLARO 	bool ret = false;
275d765955dSGiuseppe CAVALLARO 
276f5351ef7SGiuseppe CAVALLARO 	/* Using PCS we cannot dial with the phy registers at this stage
277f5351ef7SGiuseppe CAVALLARO 	 * so we do not support extra feature like EEE.
278f5351ef7SGiuseppe CAVALLARO 	 */
279f5351ef7SGiuseppe CAVALLARO 	if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) ||
280f5351ef7SGiuseppe CAVALLARO 	    (priv->pcs == STMMAC_PCS_RTBI))
281f5351ef7SGiuseppe CAVALLARO 		goto out;
282f5351ef7SGiuseppe CAVALLARO 
28356b88c25SGiuseppe CAVALLARO 	/* Never init EEE in case of a switch is attached */
28456b88c25SGiuseppe CAVALLARO 	if (phy_bus_name && (!strcmp(phy_bus_name, "fixed")))
28556b88c25SGiuseppe CAVALLARO 		goto out;
28656b88c25SGiuseppe CAVALLARO 
287d765955dSGiuseppe CAVALLARO 	/* MAC core supports the EEE feature. */
288d765955dSGiuseppe CAVALLARO 	if (priv->dma_cap.eee) {
28983bf79b6SGiuseppe CAVALLARO 		int tx_lpi_timer = priv->tx_lpi_timer;
290d765955dSGiuseppe CAVALLARO 
29183bf79b6SGiuseppe CAVALLARO 		/* Check if the PHY supports EEE */
29283bf79b6SGiuseppe CAVALLARO 		if (phy_init_eee(priv->phydev, 1)) {
29383bf79b6SGiuseppe CAVALLARO 			/* To manage at run-time if the EEE cannot be supported
29483bf79b6SGiuseppe CAVALLARO 			 * anymore (for example because the lp caps have been
29583bf79b6SGiuseppe CAVALLARO 			 * changed).
29683bf79b6SGiuseppe CAVALLARO 			 * In that case the driver disable own timers.
29783bf79b6SGiuseppe CAVALLARO 			 */
2984741cf9cSGiuseppe CAVALLARO 			spin_lock_irqsave(&priv->lock, flags);
29983bf79b6SGiuseppe CAVALLARO 			if (priv->eee_active) {
30083bf79b6SGiuseppe CAVALLARO 				pr_debug("stmmac: disable EEE\n");
30183bf79b6SGiuseppe CAVALLARO 				del_timer_sync(&priv->eee_ctrl_timer);
3027ed24bbeSVince Bridgers 				priv->hw->mac->set_eee_timer(priv->hw, 0,
30383bf79b6SGiuseppe CAVALLARO 							     tx_lpi_timer);
30483bf79b6SGiuseppe CAVALLARO 			}
30583bf79b6SGiuseppe CAVALLARO 			priv->eee_active = 0;
3064741cf9cSGiuseppe CAVALLARO 			spin_unlock_irqrestore(&priv->lock, flags);
30783bf79b6SGiuseppe CAVALLARO 			goto out;
30883bf79b6SGiuseppe CAVALLARO 		}
30983bf79b6SGiuseppe CAVALLARO 		/* Activate the EEE and start timers */
3104741cf9cSGiuseppe CAVALLARO 		spin_lock_irqsave(&priv->lock, flags);
311f5351ef7SGiuseppe CAVALLARO 		if (!priv->eee_active) {
312d765955dSGiuseppe CAVALLARO 			priv->eee_active = 1;
313ccb36da1SVaishali Thakkar 			setup_timer(&priv->eee_ctrl_timer,
314ccb36da1SVaishali Thakkar 				    stmmac_eee_ctrl_timer,
315ccb36da1SVaishali Thakkar 				    (unsigned long)priv);
316ccb36da1SVaishali Thakkar 			mod_timer(&priv->eee_ctrl_timer,
317ccb36da1SVaishali Thakkar 				  STMMAC_LPI_T(eee_timer));
318d765955dSGiuseppe CAVALLARO 
3197ed24bbeSVince Bridgers 			priv->hw->mac->set_eee_timer(priv->hw,
320f5351ef7SGiuseppe CAVALLARO 						     STMMAC_DEFAULT_LIT_LS,
32183bf79b6SGiuseppe CAVALLARO 						     tx_lpi_timer);
32271965352SGiuseppe CAVALLARO 		}
323f5351ef7SGiuseppe CAVALLARO 		/* Set HW EEE according to the speed */
32471965352SGiuseppe CAVALLARO 		priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link);
325d765955dSGiuseppe CAVALLARO 
326d765955dSGiuseppe CAVALLARO 		ret = true;
3274741cf9cSGiuseppe CAVALLARO 		spin_unlock_irqrestore(&priv->lock, flags);
3284741cf9cSGiuseppe CAVALLARO 
3294741cf9cSGiuseppe CAVALLARO 		pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
330d765955dSGiuseppe CAVALLARO 	}
331d765955dSGiuseppe CAVALLARO out:
332d765955dSGiuseppe CAVALLARO 	return ret;
333d765955dSGiuseppe CAVALLARO }
334d765955dSGiuseppe CAVALLARO 
335732fdf0eSGiuseppe CAVALLARO /* stmmac_get_tx_hwtstamp - get HW TX timestamps
33632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
337891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
338891434b1SRayagond Kokatanur  * @skb : the socket buffer
339891434b1SRayagond Kokatanur  * Description :
340891434b1SRayagond Kokatanur  * This function will read timestamp from the descriptor & pass it to stack.
341891434b1SRayagond Kokatanur  * and also perform some sanity checks.
342891434b1SRayagond Kokatanur  */
343891434b1SRayagond Kokatanur static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
344ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
345891434b1SRayagond Kokatanur {
346891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps shhwtstamp;
347891434b1SRayagond Kokatanur 	u64 ns;
348891434b1SRayagond Kokatanur 	void *desc = NULL;
349891434b1SRayagond Kokatanur 
350891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
351891434b1SRayagond Kokatanur 		return;
352891434b1SRayagond Kokatanur 
353ceb69499SGiuseppe CAVALLARO 	/* exit if skb doesn't support hw tstamp */
35475e4364fSdamuzi000 	if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
355891434b1SRayagond Kokatanur 		return;
356891434b1SRayagond Kokatanur 
357891434b1SRayagond Kokatanur 	if (priv->adv_ts)
358891434b1SRayagond Kokatanur 		desc = (priv->dma_etx + entry);
359891434b1SRayagond Kokatanur 	else
360891434b1SRayagond Kokatanur 		desc = (priv->dma_tx + entry);
361891434b1SRayagond Kokatanur 
362891434b1SRayagond Kokatanur 	/* check tx tstamp status */
363891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_tx_timestamp_status((struct dma_desc *)desc))
364891434b1SRayagond Kokatanur 		return;
365891434b1SRayagond Kokatanur 
366891434b1SRayagond Kokatanur 	/* get the valid tstamp */
367891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
368891434b1SRayagond Kokatanur 
369891434b1SRayagond Kokatanur 	memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
370891434b1SRayagond Kokatanur 	shhwtstamp.hwtstamp = ns_to_ktime(ns);
371891434b1SRayagond Kokatanur 	/* pass tstamp to stack */
372891434b1SRayagond Kokatanur 	skb_tstamp_tx(skb, &shhwtstamp);
373891434b1SRayagond Kokatanur 
374891434b1SRayagond Kokatanur 	return;
375891434b1SRayagond Kokatanur }
376891434b1SRayagond Kokatanur 
377732fdf0eSGiuseppe CAVALLARO /* stmmac_get_rx_hwtstamp - get HW RX timestamps
37832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
379891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
380891434b1SRayagond Kokatanur  * @skb : the socket buffer
381891434b1SRayagond Kokatanur  * Description :
382891434b1SRayagond Kokatanur  * This function will read received packet's timestamp from the descriptor
383891434b1SRayagond Kokatanur  * and pass it to stack. It also perform some sanity checks.
384891434b1SRayagond Kokatanur  */
385891434b1SRayagond Kokatanur static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv,
386ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
387891434b1SRayagond Kokatanur {
388891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps *shhwtstamp = NULL;
389891434b1SRayagond Kokatanur 	u64 ns;
390891434b1SRayagond Kokatanur 	void *desc = NULL;
391891434b1SRayagond Kokatanur 
392891434b1SRayagond Kokatanur 	if (!priv->hwts_rx_en)
393891434b1SRayagond Kokatanur 		return;
394891434b1SRayagond Kokatanur 
395891434b1SRayagond Kokatanur 	if (priv->adv_ts)
396891434b1SRayagond Kokatanur 		desc = (priv->dma_erx + entry);
397891434b1SRayagond Kokatanur 	else
398891434b1SRayagond Kokatanur 		desc = (priv->dma_rx + entry);
399891434b1SRayagond Kokatanur 
400ceb69499SGiuseppe CAVALLARO 	/* exit if rx tstamp is not valid */
401891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts))
402891434b1SRayagond Kokatanur 		return;
403891434b1SRayagond Kokatanur 
404891434b1SRayagond Kokatanur 	/* get valid tstamp */
405891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
406891434b1SRayagond Kokatanur 	shhwtstamp = skb_hwtstamps(skb);
407891434b1SRayagond Kokatanur 	memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
408891434b1SRayagond Kokatanur 	shhwtstamp->hwtstamp = ns_to_ktime(ns);
409891434b1SRayagond Kokatanur }
410891434b1SRayagond Kokatanur 
411891434b1SRayagond Kokatanur /**
412891434b1SRayagond Kokatanur  *  stmmac_hwtstamp_ioctl - control hardware timestamping.
413891434b1SRayagond Kokatanur  *  @dev: device pointer.
414891434b1SRayagond Kokatanur  *  @ifr: An IOCTL specefic structure, that can contain a pointer to
415891434b1SRayagond Kokatanur  *  a proprietary structure used to pass information to the driver.
416891434b1SRayagond Kokatanur  *  Description:
417891434b1SRayagond Kokatanur  *  This function configures the MAC to enable/disable both outgoing(TX)
418891434b1SRayagond Kokatanur  *  and incoming(RX) packets time stamping based on user input.
419891434b1SRayagond Kokatanur  *  Return Value:
420891434b1SRayagond Kokatanur  *  0 on success and an appropriate -ve integer on failure.
421891434b1SRayagond Kokatanur  */
422891434b1SRayagond Kokatanur static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
423891434b1SRayagond Kokatanur {
424891434b1SRayagond Kokatanur 	struct stmmac_priv *priv = netdev_priv(dev);
425891434b1SRayagond Kokatanur 	struct hwtstamp_config config;
426891434b1SRayagond Kokatanur 	struct timespec now;
427891434b1SRayagond Kokatanur 	u64 temp = 0;
428891434b1SRayagond Kokatanur 	u32 ptp_v2 = 0;
429891434b1SRayagond Kokatanur 	u32 tstamp_all = 0;
430891434b1SRayagond Kokatanur 	u32 ptp_over_ipv4_udp = 0;
431891434b1SRayagond Kokatanur 	u32 ptp_over_ipv6_udp = 0;
432891434b1SRayagond Kokatanur 	u32 ptp_over_ethernet = 0;
433891434b1SRayagond Kokatanur 	u32 snap_type_sel = 0;
434891434b1SRayagond Kokatanur 	u32 ts_master_en = 0;
435891434b1SRayagond Kokatanur 	u32 ts_event_en = 0;
436891434b1SRayagond Kokatanur 	u32 value = 0;
437891434b1SRayagond Kokatanur 
438891434b1SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
439891434b1SRayagond Kokatanur 		netdev_alert(priv->dev, "No support for HW time stamping\n");
440891434b1SRayagond Kokatanur 		priv->hwts_tx_en = 0;
441891434b1SRayagond Kokatanur 		priv->hwts_rx_en = 0;
442891434b1SRayagond Kokatanur 
443891434b1SRayagond Kokatanur 		return -EOPNOTSUPP;
444891434b1SRayagond Kokatanur 	}
445891434b1SRayagond Kokatanur 
446891434b1SRayagond Kokatanur 	if (copy_from_user(&config, ifr->ifr_data,
447891434b1SRayagond Kokatanur 			   sizeof(struct hwtstamp_config)))
448891434b1SRayagond Kokatanur 		return -EFAULT;
449891434b1SRayagond Kokatanur 
450891434b1SRayagond Kokatanur 	pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
451891434b1SRayagond Kokatanur 		 __func__, config.flags, config.tx_type, config.rx_filter);
452891434b1SRayagond Kokatanur 
453891434b1SRayagond Kokatanur 	/* reserved for future extensions */
454891434b1SRayagond Kokatanur 	if (config.flags)
455891434b1SRayagond Kokatanur 		return -EINVAL;
456891434b1SRayagond Kokatanur 
4575f3da328SBen Hutchings 	if (config.tx_type != HWTSTAMP_TX_OFF &&
4585f3da328SBen Hutchings 	    config.tx_type != HWTSTAMP_TX_ON)
459891434b1SRayagond Kokatanur 		return -ERANGE;
460891434b1SRayagond Kokatanur 
461891434b1SRayagond Kokatanur 	if (priv->adv_ts) {
462891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
463891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
464ceb69499SGiuseppe CAVALLARO 			/* time stamp no incoming packet at all */
465891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
466891434b1SRayagond Kokatanur 			break;
467891434b1SRayagond Kokatanur 
468891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
469ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, any kind of event packet */
470891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
471891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
472891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
473891434b1SRayagond Kokatanur 
474891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
475891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
476891434b1SRayagond Kokatanur 			break;
477891434b1SRayagond Kokatanur 
478891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
479ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Sync packet */
480891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
481891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
482891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
483891434b1SRayagond Kokatanur 
484891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
485891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
486891434b1SRayagond Kokatanur 			break;
487891434b1SRayagond Kokatanur 
488891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
489ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Delay_req packet */
490891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
491891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
492891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
493891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
494891434b1SRayagond Kokatanur 
495891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
496891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
497891434b1SRayagond Kokatanur 			break;
498891434b1SRayagond Kokatanur 
499891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
500ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, any kind of event packet */
501891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
502891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
503891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
504891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
505891434b1SRayagond Kokatanur 
506891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
507891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
508891434b1SRayagond Kokatanur 			break;
509891434b1SRayagond Kokatanur 
510891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
511ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Sync packet */
512891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
513891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
514891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
515891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
516891434b1SRayagond Kokatanur 
517891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
518891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
519891434b1SRayagond Kokatanur 			break;
520891434b1SRayagond Kokatanur 
521891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
522ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Delay_req packet */
523891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
524891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
525891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
526891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
527891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
528891434b1SRayagond Kokatanur 
529891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
530891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
531891434b1SRayagond Kokatanur 			break;
532891434b1SRayagond Kokatanur 
533891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_EVENT:
534ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1 any layer, any kind of event packet */
535891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
536891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
537891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
538891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
539891434b1SRayagond Kokatanur 
540891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
541891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
542891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
543891434b1SRayagond Kokatanur 			break;
544891434b1SRayagond Kokatanur 
545891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_SYNC:
546ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Sync packet */
547891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
548891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
549891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
550891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
551891434b1SRayagond Kokatanur 
552891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
553891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
554891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
555891434b1SRayagond Kokatanur 			break;
556891434b1SRayagond Kokatanur 
557891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
558ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Delay_req packet */
559891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
560891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
561891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
562891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
563891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
564891434b1SRayagond Kokatanur 
565891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
566891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
567891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
568891434b1SRayagond Kokatanur 			break;
569891434b1SRayagond Kokatanur 
570891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_ALL:
571ceb69499SGiuseppe CAVALLARO 			/* time stamp any incoming packet */
572891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_ALL;
573891434b1SRayagond Kokatanur 			tstamp_all = PTP_TCR_TSENALL;
574891434b1SRayagond Kokatanur 			break;
575891434b1SRayagond Kokatanur 
576891434b1SRayagond Kokatanur 		default:
577891434b1SRayagond Kokatanur 			return -ERANGE;
578891434b1SRayagond Kokatanur 		}
579891434b1SRayagond Kokatanur 	} else {
580891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
581891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
582891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
583891434b1SRayagond Kokatanur 			break;
584891434b1SRayagond Kokatanur 		default:
585891434b1SRayagond Kokatanur 			/* PTP v1, UDP, any kind of event packet */
586891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
587891434b1SRayagond Kokatanur 			break;
588891434b1SRayagond Kokatanur 		}
589891434b1SRayagond Kokatanur 	}
590891434b1SRayagond Kokatanur 	priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1);
5915f3da328SBen Hutchings 	priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON;
592891434b1SRayagond Kokatanur 
593891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en && !priv->hwts_rx_en)
594891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0);
595891434b1SRayagond Kokatanur 	else {
596891434b1SRayagond Kokatanur 		value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
597891434b1SRayagond Kokatanur 			 tstamp_all | ptp_v2 | ptp_over_ethernet |
598891434b1SRayagond Kokatanur 			 ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
599891434b1SRayagond Kokatanur 			 ts_master_en | snap_type_sel);
600891434b1SRayagond Kokatanur 
601891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
602891434b1SRayagond Kokatanur 
603891434b1SRayagond Kokatanur 		/* program Sub Second Increment reg */
604891434b1SRayagond Kokatanur 		priv->hw->ptp->config_sub_second_increment(priv->ioaddr);
605891434b1SRayagond Kokatanur 
606891434b1SRayagond Kokatanur 		/* calculate default added value:
607891434b1SRayagond Kokatanur 		 * formula is :
608891434b1SRayagond Kokatanur 		 * addend = (2^32)/freq_div_ratio;
6095566401fSGiuseppe CAVALLARO 		 * where, freq_div_ratio = clk_ptp_ref_i/50MHz
6105566401fSGiuseppe CAVALLARO 		 * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
6115566401fSGiuseppe CAVALLARO 		 * NOTE: clk_ptp_ref_i should be >= 50MHz to
612dbedd44eSJoe Perches 		 *       achieve 20ns accuracy.
613891434b1SRayagond Kokatanur 		 *
614891434b1SRayagond Kokatanur 		 * 2^x * y == (y << x), hence
615891434b1SRayagond Kokatanur 		 * 2^32 * 50000000 ==> (50000000 << 32)
616891434b1SRayagond Kokatanur 		 */
617891434b1SRayagond Kokatanur 		temp = (u64) (50000000ULL << 32);
6185566401fSGiuseppe CAVALLARO 		priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
619891434b1SRayagond Kokatanur 		priv->hw->ptp->config_addend(priv->ioaddr,
620891434b1SRayagond Kokatanur 					     priv->default_addend);
621891434b1SRayagond Kokatanur 
622891434b1SRayagond Kokatanur 		/* initialize system time */
623891434b1SRayagond Kokatanur 		getnstimeofday(&now);
624891434b1SRayagond Kokatanur 		priv->hw->ptp->init_systime(priv->ioaddr, now.tv_sec,
625891434b1SRayagond Kokatanur 					    now.tv_nsec);
626891434b1SRayagond Kokatanur 	}
627891434b1SRayagond Kokatanur 
628891434b1SRayagond Kokatanur 	return copy_to_user(ifr->ifr_data, &config,
629891434b1SRayagond Kokatanur 			    sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
630891434b1SRayagond Kokatanur }
631891434b1SRayagond Kokatanur 
63232ceabcaSGiuseppe CAVALLARO /**
633732fdf0eSGiuseppe CAVALLARO  * stmmac_init_ptp - init PTP
63432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
635732fdf0eSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PTPv1 or PTPv2.
63632ceabcaSGiuseppe CAVALLARO  * This is done by looking at the HW cap. register.
637732fdf0eSGiuseppe CAVALLARO  * This function also registers the ptp driver.
63832ceabcaSGiuseppe CAVALLARO  */
63992ba6888SRayagond Kokatanur static int stmmac_init_ptp(struct stmmac_priv *priv)
640891434b1SRayagond Kokatanur {
64192ba6888SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
64292ba6888SRayagond Kokatanur 		return -EOPNOTSUPP;
64392ba6888SRayagond Kokatanur 
6445566401fSGiuseppe CAVALLARO 	/* Fall-back to main clock in case of no PTP ref is passed */
6455566401fSGiuseppe CAVALLARO 	priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref");
6465566401fSGiuseppe CAVALLARO 	if (IS_ERR(priv->clk_ptp_ref)) {
6475566401fSGiuseppe CAVALLARO 		priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk);
6485566401fSGiuseppe CAVALLARO 		priv->clk_ptp_ref = NULL;
6495566401fSGiuseppe CAVALLARO 	} else {
6505566401fSGiuseppe CAVALLARO 		clk_prepare_enable(priv->clk_ptp_ref);
6515566401fSGiuseppe CAVALLARO 		priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref);
6525566401fSGiuseppe CAVALLARO 	}
6535566401fSGiuseppe CAVALLARO 
654891434b1SRayagond Kokatanur 	priv->adv_ts = 0;
6557cd01399SVince Bridgers 	if (priv->dma_cap.atime_stamp && priv->extend_desc)
656891434b1SRayagond Kokatanur 		priv->adv_ts = 1;
6577cd01399SVince Bridgers 
6587cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
6597cd01399SVince Bridgers 		pr_debug("IEEE 1588-2002 Time Stamp supported\n");
6607cd01399SVince Bridgers 
6617cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->adv_ts)
6627cd01399SVince Bridgers 		pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
663891434b1SRayagond Kokatanur 
664891434b1SRayagond Kokatanur 	priv->hw->ptp = &stmmac_ptp;
665891434b1SRayagond Kokatanur 	priv->hwts_tx_en = 0;
666891434b1SRayagond Kokatanur 	priv->hwts_rx_en = 0;
66792ba6888SRayagond Kokatanur 
66892ba6888SRayagond Kokatanur 	return stmmac_ptp_register(priv);
66992ba6888SRayagond Kokatanur }
67092ba6888SRayagond Kokatanur 
67192ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv)
67292ba6888SRayagond Kokatanur {
6735566401fSGiuseppe CAVALLARO 	if (priv->clk_ptp_ref)
6745566401fSGiuseppe CAVALLARO 		clk_disable_unprepare(priv->clk_ptp_ref);
67592ba6888SRayagond Kokatanur 	stmmac_ptp_unregister(priv);
676891434b1SRayagond Kokatanur }
677891434b1SRayagond Kokatanur 
6787ac6653aSJeff Kirsher /**
679732fdf0eSGiuseppe CAVALLARO  * stmmac_adjust_link - adjusts the link parameters
6807ac6653aSJeff Kirsher  * @dev: net device structure
681732fdf0eSGiuseppe CAVALLARO  * Description: this is the helper called by the physical abstraction layer
682732fdf0eSGiuseppe CAVALLARO  * drivers to communicate the phy link status. According the speed and duplex
683732fdf0eSGiuseppe CAVALLARO  * this driver can invoke registered glue-logic as well.
684732fdf0eSGiuseppe CAVALLARO  * It also invoke the eee initialization because it could happen when switch
685732fdf0eSGiuseppe CAVALLARO  * on different networks (that are eee capable).
6867ac6653aSJeff Kirsher  */
6877ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev)
6887ac6653aSJeff Kirsher {
6897ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
6907ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
6917ac6653aSJeff Kirsher 	unsigned long flags;
6927ac6653aSJeff Kirsher 	int new_state = 0;
6937ac6653aSJeff Kirsher 	unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
6947ac6653aSJeff Kirsher 
6957ac6653aSJeff Kirsher 	if (phydev == NULL)
6967ac6653aSJeff Kirsher 		return;
6977ac6653aSJeff Kirsher 
6987ac6653aSJeff Kirsher 	spin_lock_irqsave(&priv->lock, flags);
699d765955dSGiuseppe CAVALLARO 
7007ac6653aSJeff Kirsher 	if (phydev->link) {
7017ac6653aSJeff Kirsher 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
7027ac6653aSJeff Kirsher 
7037ac6653aSJeff Kirsher 		/* Now we make sure that we can be in full duplex mode.
7047ac6653aSJeff Kirsher 		 * If not, we operate in half-duplex mode. */
7057ac6653aSJeff Kirsher 		if (phydev->duplex != priv->oldduplex) {
7067ac6653aSJeff Kirsher 			new_state = 1;
7077ac6653aSJeff Kirsher 			if (!(phydev->duplex))
7087ac6653aSJeff Kirsher 				ctrl &= ~priv->hw->link.duplex;
7097ac6653aSJeff Kirsher 			else
7107ac6653aSJeff Kirsher 				ctrl |= priv->hw->link.duplex;
7117ac6653aSJeff Kirsher 			priv->oldduplex = phydev->duplex;
7127ac6653aSJeff Kirsher 		}
7137ac6653aSJeff Kirsher 		/* Flow Control operation */
7147ac6653aSJeff Kirsher 		if (phydev->pause)
7157ed24bbeSVince Bridgers 			priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex,
7167ac6653aSJeff Kirsher 						 fc, pause_time);
7177ac6653aSJeff Kirsher 
7187ac6653aSJeff Kirsher 		if (phydev->speed != priv->speed) {
7197ac6653aSJeff Kirsher 			new_state = 1;
7207ac6653aSJeff Kirsher 			switch (phydev->speed) {
7217ac6653aSJeff Kirsher 			case 1000:
7227ac6653aSJeff Kirsher 				if (likely(priv->plat->has_gmac))
7237ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7247ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7257ac6653aSJeff Kirsher 				break;
7267ac6653aSJeff Kirsher 			case 100:
7277ac6653aSJeff Kirsher 			case 10:
7287ac6653aSJeff Kirsher 				if (priv->plat->has_gmac) {
7297ac6653aSJeff Kirsher 					ctrl |= priv->hw->link.port;
7307ac6653aSJeff Kirsher 					if (phydev->speed == SPEED_100) {
7317ac6653aSJeff Kirsher 						ctrl |= priv->hw->link.speed;
7327ac6653aSJeff Kirsher 					} else {
7337ac6653aSJeff Kirsher 						ctrl &= ~(priv->hw->link.speed);
7347ac6653aSJeff Kirsher 					}
7357ac6653aSJeff Kirsher 				} else {
7367ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7377ac6653aSJeff Kirsher 				}
7387ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7397ac6653aSJeff Kirsher 				break;
7407ac6653aSJeff Kirsher 			default:
7417ac6653aSJeff Kirsher 				if (netif_msg_link(priv))
742ceb69499SGiuseppe CAVALLARO 					pr_warn("%s: Speed (%d) not 10/100\n",
743ceb69499SGiuseppe CAVALLARO 						dev->name, phydev->speed);
7447ac6653aSJeff Kirsher 				break;
7457ac6653aSJeff Kirsher 			}
7467ac6653aSJeff Kirsher 
7477ac6653aSJeff Kirsher 			priv->speed = phydev->speed;
7487ac6653aSJeff Kirsher 		}
7497ac6653aSJeff Kirsher 
7507ac6653aSJeff Kirsher 		writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
7517ac6653aSJeff Kirsher 
7527ac6653aSJeff Kirsher 		if (!priv->oldlink) {
7537ac6653aSJeff Kirsher 			new_state = 1;
7547ac6653aSJeff Kirsher 			priv->oldlink = 1;
7557ac6653aSJeff Kirsher 		}
7567ac6653aSJeff Kirsher 	} else if (priv->oldlink) {
7577ac6653aSJeff Kirsher 		new_state = 1;
7587ac6653aSJeff Kirsher 		priv->oldlink = 0;
7597ac6653aSJeff Kirsher 		priv->speed = 0;
7607ac6653aSJeff Kirsher 		priv->oldduplex = -1;
7617ac6653aSJeff Kirsher 	}
7627ac6653aSJeff Kirsher 
7637ac6653aSJeff Kirsher 	if (new_state && netif_msg_link(priv))
7647ac6653aSJeff Kirsher 		phy_print_status(phydev);
7657ac6653aSJeff Kirsher 
7664741cf9cSGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
7674741cf9cSGiuseppe CAVALLARO 
768f5351ef7SGiuseppe CAVALLARO 	/* At this stage, it could be needed to setup the EEE or adjust some
769f5351ef7SGiuseppe CAVALLARO 	 * MAC related HW registers.
770f5351ef7SGiuseppe CAVALLARO 	 */
771f5351ef7SGiuseppe CAVALLARO 	priv->eee_enabled = stmmac_eee_init(priv);
7727ac6653aSJeff Kirsher }
7737ac6653aSJeff Kirsher 
77432ceabcaSGiuseppe CAVALLARO /**
775732fdf0eSGiuseppe CAVALLARO  * stmmac_check_pcs_mode - verify if RGMII/SGMII is supported
77632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
77732ceabcaSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PCS.
77832ceabcaSGiuseppe CAVALLARO  * Physical Coding Sublayer (PCS) interface that can be used when the MAC is
77932ceabcaSGiuseppe CAVALLARO  * configured for the TBI, RTBI, or SGMII PHY interface.
78032ceabcaSGiuseppe CAVALLARO  */
781e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
782e58bb43fSGiuseppe CAVALLARO {
783e58bb43fSGiuseppe CAVALLARO 	int interface = priv->plat->interface;
784e58bb43fSGiuseppe CAVALLARO 
785e58bb43fSGiuseppe CAVALLARO 	if (priv->dma_cap.pcs) {
7860d909dcdSByungho An 		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
7870d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
7880d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
7890d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
790e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS RGMII support enable\n");
791e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_RGMII;
7920d909dcdSByungho An 		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
793e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS SGMII support enable\n");
794e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_SGMII;
795e58bb43fSGiuseppe CAVALLARO 		}
796e58bb43fSGiuseppe CAVALLARO 	}
797e58bb43fSGiuseppe CAVALLARO }
798e58bb43fSGiuseppe CAVALLARO 
7997ac6653aSJeff Kirsher /**
8007ac6653aSJeff Kirsher  * stmmac_init_phy - PHY initialization
8017ac6653aSJeff Kirsher  * @dev: net device structure
8027ac6653aSJeff Kirsher  * Description: it initializes the driver's PHY state, and attaches the PHY
8037ac6653aSJeff Kirsher  * to the mac driver.
8047ac6653aSJeff Kirsher  *  Return value:
8057ac6653aSJeff Kirsher  *  0 on success
8067ac6653aSJeff Kirsher  */
8077ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev)
8087ac6653aSJeff Kirsher {
8097ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
8107ac6653aSJeff Kirsher 	struct phy_device *phydev;
811d765955dSGiuseppe CAVALLARO 	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
8127ac6653aSJeff Kirsher 	char bus_id[MII_BUS_ID_SIZE];
81379ee1dc3SSrinivas Kandagatla 	int interface = priv->plat->interface;
8149cbadf09SSrinivas Kandagatla 	int max_speed = priv->plat->max_speed;
8157ac6653aSJeff Kirsher 	priv->oldlink = 0;
8167ac6653aSJeff Kirsher 	priv->speed = 0;
8177ac6653aSJeff Kirsher 	priv->oldduplex = -1;
8187ac6653aSJeff Kirsher 
819f142af2eSSrinivas Kandagatla 	if (priv->plat->phy_bus_name)
820f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
821f142af2eSSrinivas Kandagatla 			 priv->plat->phy_bus_name, priv->plat->bus_id);
822f142af2eSSrinivas Kandagatla 	else
823f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
824f142af2eSSrinivas Kandagatla 			 priv->plat->bus_id);
825f142af2eSSrinivas Kandagatla 
826d765955dSGiuseppe CAVALLARO 	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
8277ac6653aSJeff Kirsher 		 priv->plat->phy_addr);
828d765955dSGiuseppe CAVALLARO 	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
8297ac6653aSJeff Kirsher 
830f9a8f83bSFlorian Fainelli 	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
8317ac6653aSJeff Kirsher 
8327ac6653aSJeff Kirsher 	if (IS_ERR(phydev)) {
8337ac6653aSJeff Kirsher 		pr_err("%s: Could not attach to PHY\n", dev->name);
8347ac6653aSJeff Kirsher 		return PTR_ERR(phydev);
8357ac6653aSJeff Kirsher 	}
8367ac6653aSJeff Kirsher 
83779ee1dc3SSrinivas Kandagatla 	/* Stop Advertising 1000BASE Capability if interface is not GMII */
838c5b9b4e4SSrinivas Kandagatla 	if ((interface == PHY_INTERFACE_MODE_MII) ||
8399cbadf09SSrinivas Kandagatla 	    (interface == PHY_INTERFACE_MODE_RMII) ||
8409cbadf09SSrinivas Kandagatla 		(max_speed < 1000 && max_speed > 0))
841c5b9b4e4SSrinivas Kandagatla 		phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
842c5b9b4e4SSrinivas Kandagatla 					 SUPPORTED_1000baseT_Full);
84379ee1dc3SSrinivas Kandagatla 
8447ac6653aSJeff Kirsher 	/*
8457ac6653aSJeff Kirsher 	 * Broken HW is sometimes missing the pull-up resistor on the
8467ac6653aSJeff Kirsher 	 * MDIO line, which results in reads to non-existent devices returning
8477ac6653aSJeff Kirsher 	 * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
8487ac6653aSJeff Kirsher 	 * device as well.
8497ac6653aSJeff Kirsher 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
8507ac6653aSJeff Kirsher 	 */
8517ac6653aSJeff Kirsher 	if (phydev->phy_id == 0) {
8527ac6653aSJeff Kirsher 		phy_disconnect(phydev);
8537ac6653aSJeff Kirsher 		return -ENODEV;
8547ac6653aSJeff Kirsher 	}
8557ac6653aSJeff Kirsher 	pr_debug("stmmac_init_phy:  %s: attached to PHY (UID 0x%x)"
8567ac6653aSJeff Kirsher 		 " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
8577ac6653aSJeff Kirsher 
8587ac6653aSJeff Kirsher 	priv->phydev = phydev;
8597ac6653aSJeff Kirsher 
8607ac6653aSJeff Kirsher 	return 0;
8617ac6653aSJeff Kirsher }
8627ac6653aSJeff Kirsher 
8637ac6653aSJeff Kirsher /**
864732fdf0eSGiuseppe CAVALLARO  * stmmac_display_ring - display ring
86532ceabcaSGiuseppe CAVALLARO  * @head: pointer to the head of the ring passed.
8667ac6653aSJeff Kirsher  * @size: size of the ring.
86732ceabcaSGiuseppe CAVALLARO  * @extend_desc: to verify if extended descriptors are used.
868c24602efSGiuseppe CAVALLARO  * Description: display the control/status and buffer descriptors.
8697ac6653aSJeff Kirsher  */
870c24602efSGiuseppe CAVALLARO static void stmmac_display_ring(void *head, int size, int extend_desc)
8717ac6653aSJeff Kirsher {
8727ac6653aSJeff Kirsher 	int i;
873c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
874c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
875c24602efSGiuseppe CAVALLARO 
8767ac6653aSJeff Kirsher 	for (i = 0; i < size; i++) {
877c24602efSGiuseppe CAVALLARO 		u64 x;
878c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
879c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
880c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
881c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(ep),
882c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
883c24602efSGiuseppe CAVALLARO 				ep->basic.des2, ep->basic.des3);
884c24602efSGiuseppe CAVALLARO 			ep++;
885c24602efSGiuseppe CAVALLARO 		} else {
886c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
887c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x",
888c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(p),
889c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
890c24602efSGiuseppe CAVALLARO 				p->des2, p->des3);
891c24602efSGiuseppe CAVALLARO 			p++;
892c24602efSGiuseppe CAVALLARO 		}
8937ac6653aSJeff Kirsher 		pr_info("\n");
8947ac6653aSJeff Kirsher 	}
8957ac6653aSJeff Kirsher }
8967ac6653aSJeff Kirsher 
897c24602efSGiuseppe CAVALLARO static void stmmac_display_rings(struct stmmac_priv *priv)
898c24602efSGiuseppe CAVALLARO {
899c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
900c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
901c24602efSGiuseppe CAVALLARO 
902c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
903c24602efSGiuseppe CAVALLARO 		pr_info("Extended RX descriptor ring:\n");
904c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
905c24602efSGiuseppe CAVALLARO 		pr_info("Extended TX descriptor ring:\n");
906c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
907c24602efSGiuseppe CAVALLARO 	} else {
908c24602efSGiuseppe CAVALLARO 		pr_info("RX descriptor ring:\n");
909c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
910c24602efSGiuseppe CAVALLARO 		pr_info("TX descriptor ring:\n");
911c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
912c24602efSGiuseppe CAVALLARO 	}
913c24602efSGiuseppe CAVALLARO }
914c24602efSGiuseppe CAVALLARO 
915286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize)
916286a8372SGiuseppe CAVALLARO {
917286a8372SGiuseppe CAVALLARO 	int ret = bufsize;
918286a8372SGiuseppe CAVALLARO 
919286a8372SGiuseppe CAVALLARO 	if (mtu >= BUF_SIZE_4KiB)
920286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_8KiB;
921286a8372SGiuseppe CAVALLARO 	else if (mtu >= BUF_SIZE_2KiB)
922286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_4KiB;
923d916701cSGiuseppe CAVALLARO 	else if (mtu > DEFAULT_BUFSIZE)
924286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_2KiB;
925286a8372SGiuseppe CAVALLARO 	else
926d916701cSGiuseppe CAVALLARO 		ret = DEFAULT_BUFSIZE;
927286a8372SGiuseppe CAVALLARO 
928286a8372SGiuseppe CAVALLARO 	return ret;
929286a8372SGiuseppe CAVALLARO }
930286a8372SGiuseppe CAVALLARO 
93132ceabcaSGiuseppe CAVALLARO /**
932732fdf0eSGiuseppe CAVALLARO  * stmmac_clear_descriptors - clear descriptors
93332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
93432ceabcaSGiuseppe CAVALLARO  * Description: this function is called to clear the tx and rx descriptors
93532ceabcaSGiuseppe CAVALLARO  * in case of both basic and extended descriptors are used.
93632ceabcaSGiuseppe CAVALLARO  */
937c24602efSGiuseppe CAVALLARO static void stmmac_clear_descriptors(struct stmmac_priv *priv)
938c24602efSGiuseppe CAVALLARO {
939c24602efSGiuseppe CAVALLARO 	int i;
940c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
941c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
942c24602efSGiuseppe CAVALLARO 
943c24602efSGiuseppe CAVALLARO 	/* Clear the Rx/Tx descriptors */
944c24602efSGiuseppe CAVALLARO 	for (i = 0; i < rxsize; i++)
945c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
946c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
947c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
948c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
949c24602efSGiuseppe CAVALLARO 		else
950c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_rx[i],
951c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
952c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
953c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
954c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
955c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
956c24602efSGiuseppe CAVALLARO 						     priv->mode,
957c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
958c24602efSGiuseppe CAVALLARO 		else
959c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
960c24602efSGiuseppe CAVALLARO 						     priv->mode,
961c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
962c24602efSGiuseppe CAVALLARO }
963c24602efSGiuseppe CAVALLARO 
964732fdf0eSGiuseppe CAVALLARO /**
965732fdf0eSGiuseppe CAVALLARO  * stmmac_init_rx_buffers - init the RX descriptor buffer.
966732fdf0eSGiuseppe CAVALLARO  * @priv: driver private structure
967732fdf0eSGiuseppe CAVALLARO  * @p: descriptor pointer
968732fdf0eSGiuseppe CAVALLARO  * @i: descriptor index
969732fdf0eSGiuseppe CAVALLARO  * @flags: gfp flag.
970732fdf0eSGiuseppe CAVALLARO  * Description: this function is called to allocate a receive buffer, perform
971732fdf0eSGiuseppe CAVALLARO  * the DMA mapping and init the descriptor.
972732fdf0eSGiuseppe CAVALLARO  */
973c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
974777da230SGiuseppe CAVALLARO 				  int i, gfp_t flags)
975c24602efSGiuseppe CAVALLARO {
976c24602efSGiuseppe CAVALLARO 	struct sk_buff *skb;
977c24602efSGiuseppe CAVALLARO 
978c24602efSGiuseppe CAVALLARO 	skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
979777da230SGiuseppe CAVALLARO 				 flags);
98056329137SBartlomiej Zolnierkiewicz 	if (!skb) {
981c24602efSGiuseppe CAVALLARO 		pr_err("%s: Rx init fails; skb is NULL\n", __func__);
98256329137SBartlomiej Zolnierkiewicz 		return -ENOMEM;
983c24602efSGiuseppe CAVALLARO 	}
984c24602efSGiuseppe CAVALLARO 	skb_reserve(skb, NET_IP_ALIGN);
985c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff[i] = skb;
986c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
987c24602efSGiuseppe CAVALLARO 						priv->dma_buf_sz,
988c24602efSGiuseppe CAVALLARO 						DMA_FROM_DEVICE);
98956329137SBartlomiej Zolnierkiewicz 	if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) {
99056329137SBartlomiej Zolnierkiewicz 		pr_err("%s: DMA mapping error\n", __func__);
99156329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(skb);
99256329137SBartlomiej Zolnierkiewicz 		return -EINVAL;
99356329137SBartlomiej Zolnierkiewicz 	}
994c24602efSGiuseppe CAVALLARO 
995c24602efSGiuseppe CAVALLARO 	p->des2 = priv->rx_skbuff_dma[i];
996c24602efSGiuseppe CAVALLARO 
99729896a67SGiuseppe CAVALLARO 	if ((priv->hw->mode->init_desc3) &&
998c24602efSGiuseppe CAVALLARO 	    (priv->dma_buf_sz == BUF_SIZE_16KiB))
99929896a67SGiuseppe CAVALLARO 		priv->hw->mode->init_desc3(p);
1000c24602efSGiuseppe CAVALLARO 
1001c24602efSGiuseppe CAVALLARO 	return 0;
1002c24602efSGiuseppe CAVALLARO }
1003c24602efSGiuseppe CAVALLARO 
100456329137SBartlomiej Zolnierkiewicz static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i)
100556329137SBartlomiej Zolnierkiewicz {
100656329137SBartlomiej Zolnierkiewicz 	if (priv->rx_skbuff[i]) {
100756329137SBartlomiej Zolnierkiewicz 		dma_unmap_single(priv->device, priv->rx_skbuff_dma[i],
100856329137SBartlomiej Zolnierkiewicz 				 priv->dma_buf_sz, DMA_FROM_DEVICE);
100956329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(priv->rx_skbuff[i]);
101056329137SBartlomiej Zolnierkiewicz 	}
101156329137SBartlomiej Zolnierkiewicz 	priv->rx_skbuff[i] = NULL;
101256329137SBartlomiej Zolnierkiewicz }
101356329137SBartlomiej Zolnierkiewicz 
10147ac6653aSJeff Kirsher /**
10157ac6653aSJeff Kirsher  * init_dma_desc_rings - init the RX/TX descriptor rings
10167ac6653aSJeff Kirsher  * @dev: net device structure
1017732fdf0eSGiuseppe CAVALLARO  * @flags: gfp flag.
10187ac6653aSJeff Kirsher  * Description: this function initializes the DMA RX/TX descriptors
1019286a8372SGiuseppe CAVALLARO  * and allocates the socket buffers. It suppors the chained and ring
1020286a8372SGiuseppe CAVALLARO  * modes.
10217ac6653aSJeff Kirsher  */
1022777da230SGiuseppe CAVALLARO static int init_dma_desc_rings(struct net_device *dev, gfp_t flags)
10237ac6653aSJeff Kirsher {
10247ac6653aSJeff Kirsher 	int i;
10257ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
10267ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
10277ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
10284a7d666aSGiuseppe CAVALLARO 	unsigned int bfsize = 0;
102956329137SBartlomiej Zolnierkiewicz 	int ret = -ENOMEM;
10307ac6653aSJeff Kirsher 
103129896a67SGiuseppe CAVALLARO 	if (priv->hw->mode->set_16kib_bfsize)
103229896a67SGiuseppe CAVALLARO 		bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu);
1033286a8372SGiuseppe CAVALLARO 
10344a7d666aSGiuseppe CAVALLARO 	if (bfsize < BUF_SIZE_16KiB)
1035286a8372SGiuseppe CAVALLARO 		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
10367ac6653aSJeff Kirsher 
10372618abb7SVince Bridgers 	priv->dma_buf_sz = bfsize;
10382618abb7SVince Bridgers 
103983d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv))
104083d7af64SGiuseppe CAVALLARO 		pr_debug("%s: txsize %d, rxsize %d, bfsize %d\n", __func__,
10417ac6653aSJeff Kirsher 			 txsize, rxsize, bfsize);
10427ac6653aSJeff Kirsher 
104383d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv)) {
1044c24602efSGiuseppe CAVALLARO 		pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
1045c24602efSGiuseppe CAVALLARO 			 (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
10467ac6653aSJeff Kirsher 
10477ac6653aSJeff Kirsher 		/* RX INITIALIZATION */
104883d7af64SGiuseppe CAVALLARO 		pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n");
104983d7af64SGiuseppe CAVALLARO 	}
10507ac6653aSJeff Kirsher 	for (i = 0; i < rxsize; i++) {
1051c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1052c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1053c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_erx + i)->basic);
1054c24602efSGiuseppe CAVALLARO 		else
1055c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + i;
10567ac6653aSJeff Kirsher 
1057777da230SGiuseppe CAVALLARO 		ret = stmmac_init_rx_buffers(priv, p, i, flags);
105856329137SBartlomiej Zolnierkiewicz 		if (ret)
105956329137SBartlomiej Zolnierkiewicz 			goto err_init_rx_buffers;
1060286a8372SGiuseppe CAVALLARO 
106183d7af64SGiuseppe CAVALLARO 		if (netif_msg_probe(priv))
106283d7af64SGiuseppe CAVALLARO 			pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
106383d7af64SGiuseppe CAVALLARO 				 priv->rx_skbuff[i]->data,
106483d7af64SGiuseppe CAVALLARO 				 (unsigned int)priv->rx_skbuff_dma[i]);
10657ac6653aSJeff Kirsher 	}
10667ac6653aSJeff Kirsher 	priv->cur_rx = 0;
10677ac6653aSJeff Kirsher 	priv->dirty_rx = (unsigned int)(i - rxsize);
10687ac6653aSJeff Kirsher 	buf_sz = bfsize;
10697ac6653aSJeff Kirsher 
1070c24602efSGiuseppe CAVALLARO 	/* Setup the chained descriptor addresses */
1071c24602efSGiuseppe CAVALLARO 	if (priv->mode == STMMAC_CHAIN_MODE) {
1072c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc) {
107329896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy,
1074c24602efSGiuseppe CAVALLARO 					     rxsize, 1);
107529896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy,
1076c24602efSGiuseppe CAVALLARO 					     txsize, 1);
1077c24602efSGiuseppe CAVALLARO 		} else {
107829896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy,
1079c24602efSGiuseppe CAVALLARO 					     rxsize, 0);
108029896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy,
1081c24602efSGiuseppe CAVALLARO 					     txsize, 0);
1082c24602efSGiuseppe CAVALLARO 		}
10837ac6653aSJeff Kirsher 	}
1084286a8372SGiuseppe CAVALLARO 
1085c24602efSGiuseppe CAVALLARO 	/* TX INITIALIZATION */
1086c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++) {
1087c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1088c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1089c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1090c24602efSGiuseppe CAVALLARO 		else
1091c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1092c24602efSGiuseppe CAVALLARO 		p->des2 = 0;
1093362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[i].buf = 0;
1094362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[i].map_as_page = false;
1095c24602efSGiuseppe CAVALLARO 		priv->tx_skbuff[i] = NULL;
10964a7d666aSGiuseppe CAVALLARO 	}
1097c24602efSGiuseppe CAVALLARO 
10987ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
10997ac6653aSJeff Kirsher 	priv->cur_tx = 0;
110038979574SBeniamino Galvani 	netdev_reset_queue(priv->dev);
11017ac6653aSJeff Kirsher 
1102c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
11037ac6653aSJeff Kirsher 
1104c24602efSGiuseppe CAVALLARO 	if (netif_msg_hw(priv))
1105c24602efSGiuseppe CAVALLARO 		stmmac_display_rings(priv);
110656329137SBartlomiej Zolnierkiewicz 
110756329137SBartlomiej Zolnierkiewicz 	return 0;
110856329137SBartlomiej Zolnierkiewicz err_init_rx_buffers:
110956329137SBartlomiej Zolnierkiewicz 	while (--i >= 0)
111056329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
111156329137SBartlomiej Zolnierkiewicz 	return ret;
11127ac6653aSJeff Kirsher }
11137ac6653aSJeff Kirsher 
11147ac6653aSJeff Kirsher static void dma_free_rx_skbufs(struct stmmac_priv *priv)
11157ac6653aSJeff Kirsher {
11167ac6653aSJeff Kirsher 	int i;
11177ac6653aSJeff Kirsher 
111856329137SBartlomiej Zolnierkiewicz 	for (i = 0; i < priv->dma_rx_size; i++)
111956329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
11207ac6653aSJeff Kirsher }
11217ac6653aSJeff Kirsher 
11227ac6653aSJeff Kirsher static void dma_free_tx_skbufs(struct stmmac_priv *priv)
11237ac6653aSJeff Kirsher {
11247ac6653aSJeff Kirsher 	int i;
11257ac6653aSJeff Kirsher 
11267ac6653aSJeff Kirsher 	for (i = 0; i < priv->dma_tx_size; i++) {
1127c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
112875e4364fSdamuzi000 
1129c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1130c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1131c24602efSGiuseppe CAVALLARO 		else
1132c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1133c24602efSGiuseppe CAVALLARO 
1134362b37beSGiuseppe CAVALLARO 		if (priv->tx_skbuff_dma[i].buf) {
1135362b37beSGiuseppe CAVALLARO 			if (priv->tx_skbuff_dma[i].map_as_page)
1136362b37beSGiuseppe CAVALLARO 				dma_unmap_page(priv->device,
1137362b37beSGiuseppe CAVALLARO 					       priv->tx_skbuff_dma[i].buf,
11387ac6653aSJeff Kirsher 					       priv->hw->desc->get_tx_len(p),
11397ac6653aSJeff Kirsher 					       DMA_TO_DEVICE);
1140362b37beSGiuseppe CAVALLARO 			else
1141362b37beSGiuseppe CAVALLARO 				dma_unmap_single(priv->device,
1142362b37beSGiuseppe CAVALLARO 						 priv->tx_skbuff_dma[i].buf,
1143362b37beSGiuseppe CAVALLARO 						 priv->hw->desc->get_tx_len(p),
1144362b37beSGiuseppe CAVALLARO 						 DMA_TO_DEVICE);
114575e4364fSdamuzi000 		}
114675e4364fSdamuzi000 
114775e4364fSdamuzi000 		if (priv->tx_skbuff[i] != NULL) {
11487ac6653aSJeff Kirsher 			dev_kfree_skb_any(priv->tx_skbuff[i]);
11497ac6653aSJeff Kirsher 			priv->tx_skbuff[i] = NULL;
1150362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[i].buf = 0;
1151362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[i].map_as_page = false;
11527ac6653aSJeff Kirsher 		}
11537ac6653aSJeff Kirsher 	}
11547ac6653aSJeff Kirsher }
11557ac6653aSJeff Kirsher 
1156732fdf0eSGiuseppe CAVALLARO /**
1157732fdf0eSGiuseppe CAVALLARO  * alloc_dma_desc_resources - alloc TX/RX resources.
1158732fdf0eSGiuseppe CAVALLARO  * @priv: private structure
1159732fdf0eSGiuseppe CAVALLARO  * Description: according to which descriptor can be used (extend or basic)
1160732fdf0eSGiuseppe CAVALLARO  * this function allocates the resources for TX and RX paths. In case of
1161732fdf0eSGiuseppe CAVALLARO  * reception, for example, it pre-allocated the RX socket buffer in order to
1162732fdf0eSGiuseppe CAVALLARO  * allow zero-copy mechanism.
1163732fdf0eSGiuseppe CAVALLARO  */
116409f8d696SSrinivas Kandagatla static int alloc_dma_desc_resources(struct stmmac_priv *priv)
116509f8d696SSrinivas Kandagatla {
116609f8d696SSrinivas Kandagatla 	unsigned int txsize = priv->dma_tx_size;
116709f8d696SSrinivas Kandagatla 	unsigned int rxsize = priv->dma_rx_size;
116809f8d696SSrinivas Kandagatla 	int ret = -ENOMEM;
116909f8d696SSrinivas Kandagatla 
117009f8d696SSrinivas Kandagatla 	priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
117109f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
117209f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff_dma)
117309f8d696SSrinivas Kandagatla 		return -ENOMEM;
117409f8d696SSrinivas Kandagatla 
117509f8d696SSrinivas Kandagatla 	priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
117609f8d696SSrinivas Kandagatla 					GFP_KERNEL);
117709f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff)
117809f8d696SSrinivas Kandagatla 		goto err_rx_skbuff;
117909f8d696SSrinivas Kandagatla 
1180362b37beSGiuseppe CAVALLARO 	priv->tx_skbuff_dma = kmalloc_array(txsize,
1181362b37beSGiuseppe CAVALLARO 					    sizeof(*priv->tx_skbuff_dma),
118209f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
118309f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff_dma)
118409f8d696SSrinivas Kandagatla 		goto err_tx_skbuff_dma;
118509f8d696SSrinivas Kandagatla 
118609f8d696SSrinivas Kandagatla 	priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
118709f8d696SSrinivas Kandagatla 					GFP_KERNEL);
118809f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff)
118909f8d696SSrinivas Kandagatla 		goto err_tx_skbuff;
119009f8d696SSrinivas Kandagatla 
119109f8d696SSrinivas Kandagatla 	if (priv->extend_desc) {
119209f8d696SSrinivas Kandagatla 		priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
119309f8d696SSrinivas Kandagatla 						   sizeof(struct
119409f8d696SSrinivas Kandagatla 							  dma_extended_desc),
119509f8d696SSrinivas Kandagatla 						   &priv->dma_rx_phy,
119609f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
119709f8d696SSrinivas Kandagatla 		if (!priv->dma_erx)
119809f8d696SSrinivas Kandagatla 			goto err_dma;
119909f8d696SSrinivas Kandagatla 
120009f8d696SSrinivas Kandagatla 		priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
120109f8d696SSrinivas Kandagatla 						   sizeof(struct
120209f8d696SSrinivas Kandagatla 							  dma_extended_desc),
120309f8d696SSrinivas Kandagatla 						   &priv->dma_tx_phy,
120409f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
120509f8d696SSrinivas Kandagatla 		if (!priv->dma_etx) {
120609f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
120709f8d696SSrinivas Kandagatla 					sizeof(struct dma_extended_desc),
120809f8d696SSrinivas Kandagatla 					priv->dma_erx, priv->dma_rx_phy);
120909f8d696SSrinivas Kandagatla 			goto err_dma;
121009f8d696SSrinivas Kandagatla 		}
121109f8d696SSrinivas Kandagatla 	} else {
121209f8d696SSrinivas Kandagatla 		priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
121309f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
121409f8d696SSrinivas Kandagatla 						  &priv->dma_rx_phy,
121509f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
121609f8d696SSrinivas Kandagatla 		if (!priv->dma_rx)
121709f8d696SSrinivas Kandagatla 			goto err_dma;
121809f8d696SSrinivas Kandagatla 
121909f8d696SSrinivas Kandagatla 		priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
122009f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
122109f8d696SSrinivas Kandagatla 						  &priv->dma_tx_phy,
122209f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
122309f8d696SSrinivas Kandagatla 		if (!priv->dma_tx) {
122409f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
122509f8d696SSrinivas Kandagatla 					sizeof(struct dma_desc),
122609f8d696SSrinivas Kandagatla 					priv->dma_rx, priv->dma_rx_phy);
122709f8d696SSrinivas Kandagatla 			goto err_dma;
122809f8d696SSrinivas Kandagatla 		}
122909f8d696SSrinivas Kandagatla 	}
123009f8d696SSrinivas Kandagatla 
123109f8d696SSrinivas Kandagatla 	return 0;
123209f8d696SSrinivas Kandagatla 
123309f8d696SSrinivas Kandagatla err_dma:
123409f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff);
123509f8d696SSrinivas Kandagatla err_tx_skbuff:
123609f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff_dma);
123709f8d696SSrinivas Kandagatla err_tx_skbuff_dma:
123809f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff);
123909f8d696SSrinivas Kandagatla err_rx_skbuff:
124009f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff_dma);
124109f8d696SSrinivas Kandagatla 	return ret;
124209f8d696SSrinivas Kandagatla }
124309f8d696SSrinivas Kandagatla 
12447ac6653aSJeff Kirsher static void free_dma_desc_resources(struct stmmac_priv *priv)
12457ac6653aSJeff Kirsher {
12467ac6653aSJeff Kirsher 	/* Release the DMA TX/RX socket buffers */
12477ac6653aSJeff Kirsher 	dma_free_rx_skbufs(priv);
12487ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
12497ac6653aSJeff Kirsher 
1250ceb69499SGiuseppe CAVALLARO 	/* Free DMA regions of consistent memory previously allocated */
1251c24602efSGiuseppe CAVALLARO 	if (!priv->extend_desc) {
12527ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
12537ac6653aSJeff Kirsher 				  priv->dma_tx_size * sizeof(struct dma_desc),
12547ac6653aSJeff Kirsher 				  priv->dma_tx, priv->dma_tx_phy);
12557ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
12567ac6653aSJeff Kirsher 				  priv->dma_rx_size * sizeof(struct dma_desc),
12577ac6653aSJeff Kirsher 				  priv->dma_rx, priv->dma_rx_phy);
1258c24602efSGiuseppe CAVALLARO 	} else {
1259c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_tx_size *
1260c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1261c24602efSGiuseppe CAVALLARO 				  priv->dma_etx, priv->dma_tx_phy);
1262c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_rx_size *
1263c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1264c24602efSGiuseppe CAVALLARO 				  priv->dma_erx, priv->dma_rx_phy);
1265c24602efSGiuseppe CAVALLARO 	}
12667ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff_dma);
12677ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff);
1268cf32deecSRayagond Kokatanur 	kfree(priv->tx_skbuff_dma);
12697ac6653aSJeff Kirsher 	kfree(priv->tx_skbuff);
12707ac6653aSJeff Kirsher }
12717ac6653aSJeff Kirsher 
12727ac6653aSJeff Kirsher /**
12737ac6653aSJeff Kirsher  *  stmmac_dma_operation_mode - HW DMA operation mode
127432ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
1275732fdf0eSGiuseppe CAVALLARO  *  Description: it is used for configuring the DMA operation mode register in
1276732fdf0eSGiuseppe CAVALLARO  *  order to program the tx/rx DMA thresholds or Store-And-Forward mode.
12777ac6653aSJeff Kirsher  */
12787ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
12797ac6653aSJeff Kirsher {
1280e2a240c7SSonic Zhang 	if (priv->plat->force_thresh_dma_mode)
1281e2a240c7SSonic Zhang 		priv->hw->dma->dma_mode(priv->ioaddr, tc, tc);
1282e2a240c7SSonic Zhang 	else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
12837ac6653aSJeff Kirsher 		/*
12847ac6653aSJeff Kirsher 		 * In case of GMAC, SF mode can be enabled
12857ac6653aSJeff Kirsher 		 * to perform the TX COE in HW. This depends on:
12867ac6653aSJeff Kirsher 		 * 1) TX COE if actually supported
12877ac6653aSJeff Kirsher 		 * 2) There is no bugged Jumbo frame support
12887ac6653aSJeff Kirsher 		 *    that needs to not insert csum in the TDES.
12897ac6653aSJeff Kirsher 		 */
1290ceb69499SGiuseppe CAVALLARO 		priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE);
1291b2dec116SSonic Zhang 		priv->xstats.threshold = SF_DMA_MODE;
12927ac6653aSJeff Kirsher 	} else
12937ac6653aSJeff Kirsher 		priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
12947ac6653aSJeff Kirsher }
12957ac6653aSJeff Kirsher 
12967ac6653aSJeff Kirsher /**
1297732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_clean - to manage the transmission completion
129832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
1299732fdf0eSGiuseppe CAVALLARO  * Description: it reclaims the transmit resources after transmission completes.
13007ac6653aSJeff Kirsher  */
13019125cdd1SGiuseppe CAVALLARO static void stmmac_tx_clean(struct stmmac_priv *priv)
13027ac6653aSJeff Kirsher {
13037ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
130438979574SBeniamino Galvani 	unsigned int bytes_compl = 0, pkts_compl = 0;
13057ac6653aSJeff Kirsher 
1306a9097a96SGiuseppe CAVALLARO 	spin_lock(&priv->tx_lock);
1307a9097a96SGiuseppe CAVALLARO 
13089125cdd1SGiuseppe CAVALLARO 	priv->xstats.tx_clean++;
13099125cdd1SGiuseppe CAVALLARO 
13107ac6653aSJeff Kirsher 	while (priv->dirty_tx != priv->cur_tx) {
13117ac6653aSJeff Kirsher 		int last;
13127ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_tx % txsize;
13137ac6653aSJeff Kirsher 		struct sk_buff *skb = priv->tx_skbuff[entry];
1314c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1315c24602efSGiuseppe CAVALLARO 
1316c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1317c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_etx + entry);
1318c24602efSGiuseppe CAVALLARO 		else
1319c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + entry;
13207ac6653aSJeff Kirsher 
13217ac6653aSJeff Kirsher 		/* Check if the descriptor is owned by the DMA. */
13227ac6653aSJeff Kirsher 		if (priv->hw->desc->get_tx_owner(p))
13237ac6653aSJeff Kirsher 			break;
13247ac6653aSJeff Kirsher 
1325c24602efSGiuseppe CAVALLARO 		/* Verify tx error by looking at the last segment. */
13267ac6653aSJeff Kirsher 		last = priv->hw->desc->get_tx_ls(p);
13277ac6653aSJeff Kirsher 		if (likely(last)) {
13287ac6653aSJeff Kirsher 			int tx_error =
13297ac6653aSJeff Kirsher 			    priv->hw->desc->tx_status(&priv->dev->stats,
13307ac6653aSJeff Kirsher 						      &priv->xstats, p,
13317ac6653aSJeff Kirsher 						      priv->ioaddr);
13327ac6653aSJeff Kirsher 			if (likely(tx_error == 0)) {
13337ac6653aSJeff Kirsher 				priv->dev->stats.tx_packets++;
13347ac6653aSJeff Kirsher 				priv->xstats.tx_pkt_n++;
13357ac6653aSJeff Kirsher 			} else
13367ac6653aSJeff Kirsher 				priv->dev->stats.tx_errors++;
1337891434b1SRayagond Kokatanur 
1338891434b1SRayagond Kokatanur 			stmmac_get_tx_hwtstamp(priv, entry, skb);
13397ac6653aSJeff Kirsher 		}
134083d7af64SGiuseppe CAVALLARO 		if (netif_msg_tx_done(priv))
134183d7af64SGiuseppe CAVALLARO 			pr_debug("%s: curr %d, dirty %d\n", __func__,
13427ac6653aSJeff Kirsher 				 priv->cur_tx, priv->dirty_tx);
13437ac6653aSJeff Kirsher 
1344362b37beSGiuseppe CAVALLARO 		if (likely(priv->tx_skbuff_dma[entry].buf)) {
1345362b37beSGiuseppe CAVALLARO 			if (priv->tx_skbuff_dma[entry].map_as_page)
1346362b37beSGiuseppe CAVALLARO 				dma_unmap_page(priv->device,
1347362b37beSGiuseppe CAVALLARO 					       priv->tx_skbuff_dma[entry].buf,
13487ac6653aSJeff Kirsher 					       priv->hw->desc->get_tx_len(p),
13497ac6653aSJeff Kirsher 					       DMA_TO_DEVICE);
1350362b37beSGiuseppe CAVALLARO 			else
1351362b37beSGiuseppe CAVALLARO 				dma_unmap_single(priv->device,
1352362b37beSGiuseppe CAVALLARO 						 priv->tx_skbuff_dma[entry].buf,
1353362b37beSGiuseppe CAVALLARO 						 priv->hw->desc->get_tx_len(p),
1354362b37beSGiuseppe CAVALLARO 						 DMA_TO_DEVICE);
1355362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[entry].buf = 0;
1356362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[entry].map_as_page = false;
1357cf32deecSRayagond Kokatanur 		}
135829896a67SGiuseppe CAVALLARO 		priv->hw->mode->clean_desc3(priv, p);
13597ac6653aSJeff Kirsher 
13607ac6653aSJeff Kirsher 		if (likely(skb != NULL)) {
136138979574SBeniamino Galvani 			pkts_compl++;
136238979574SBeniamino Galvani 			bytes_compl += skb->len;
13637c565c33SEric W. Biederman 			dev_consume_skb_any(skb);
13647ac6653aSJeff Kirsher 			priv->tx_skbuff[entry] = NULL;
13657ac6653aSJeff Kirsher 		}
13667ac6653aSJeff Kirsher 
13674a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->release_tx_desc(p, priv->mode);
13687ac6653aSJeff Kirsher 
136913497f58SGiuseppe CAVALLARO 		priv->dirty_tx++;
13707ac6653aSJeff Kirsher 	}
137138979574SBeniamino Galvani 
137238979574SBeniamino Galvani 	netdev_completed_queue(priv->dev, pkts_compl, bytes_compl);
137338979574SBeniamino Galvani 
13747ac6653aSJeff Kirsher 	if (unlikely(netif_queue_stopped(priv->dev) &&
13757ac6653aSJeff Kirsher 		     stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv))) {
13767ac6653aSJeff Kirsher 		netif_tx_lock(priv->dev);
13777ac6653aSJeff Kirsher 		if (netif_queue_stopped(priv->dev) &&
13787ac6653aSJeff Kirsher 		    stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv)) {
137983d7af64SGiuseppe CAVALLARO 			if (netif_msg_tx_done(priv))
138083d7af64SGiuseppe CAVALLARO 				pr_debug("%s: restart transmit\n", __func__);
13817ac6653aSJeff Kirsher 			netif_wake_queue(priv->dev);
13827ac6653aSJeff Kirsher 		}
13837ac6653aSJeff Kirsher 		netif_tx_unlock(priv->dev);
13847ac6653aSJeff Kirsher 	}
1385d765955dSGiuseppe CAVALLARO 
1386d765955dSGiuseppe CAVALLARO 	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
1387d765955dSGiuseppe CAVALLARO 		stmmac_enable_eee_mode(priv);
1388f5351ef7SGiuseppe CAVALLARO 		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
1389d765955dSGiuseppe CAVALLARO 	}
1390a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
13917ac6653aSJeff Kirsher }
13927ac6653aSJeff Kirsher 
13939125cdd1SGiuseppe CAVALLARO static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv)
13947ac6653aSJeff Kirsher {
13957ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_irq(priv->ioaddr);
13967ac6653aSJeff Kirsher }
13977ac6653aSJeff Kirsher 
13989125cdd1SGiuseppe CAVALLARO static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
13997ac6653aSJeff Kirsher {
14007ac6653aSJeff Kirsher 	priv->hw->dma->disable_dma_irq(priv->ioaddr);
14017ac6653aSJeff Kirsher }
14027ac6653aSJeff Kirsher 
14037ac6653aSJeff Kirsher /**
1404732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_err - to manage the tx error
140532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
14067ac6653aSJeff Kirsher  * Description: it cleans the descriptors and restarts the transmission
1407732fdf0eSGiuseppe CAVALLARO  * in case of transmission errors.
14087ac6653aSJeff Kirsher  */
14097ac6653aSJeff Kirsher static void stmmac_tx_err(struct stmmac_priv *priv)
14107ac6653aSJeff Kirsher {
1411c24602efSGiuseppe CAVALLARO 	int i;
1412c24602efSGiuseppe CAVALLARO 	int txsize = priv->dma_tx_size;
14137ac6653aSJeff Kirsher 	netif_stop_queue(priv->dev);
14147ac6653aSJeff Kirsher 
14157ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
14167ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
1417c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
1418c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1419c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
1420c24602efSGiuseppe CAVALLARO 						     priv->mode,
1421c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
1422c24602efSGiuseppe CAVALLARO 		else
1423c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
1424c24602efSGiuseppe CAVALLARO 						     priv->mode,
1425c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
14267ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
14277ac6653aSJeff Kirsher 	priv->cur_tx = 0;
142838979574SBeniamino Galvani 	netdev_reset_queue(priv->dev);
14297ac6653aSJeff Kirsher 	priv->hw->dma->start_tx(priv->ioaddr);
14307ac6653aSJeff Kirsher 
14317ac6653aSJeff Kirsher 	priv->dev->stats.tx_errors++;
14327ac6653aSJeff Kirsher 	netif_wake_queue(priv->dev);
14337ac6653aSJeff Kirsher }
14347ac6653aSJeff Kirsher 
143532ceabcaSGiuseppe CAVALLARO /**
1436732fdf0eSGiuseppe CAVALLARO  * stmmac_dma_interrupt - DMA ISR
143732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
143832ceabcaSGiuseppe CAVALLARO  * Description: this is the DMA ISR. It is called by the main ISR.
1439732fdf0eSGiuseppe CAVALLARO  * It calls the dwmac dma routine and schedule poll method in case of some
1440732fdf0eSGiuseppe CAVALLARO  * work can be done.
144132ceabcaSGiuseppe CAVALLARO  */
14427ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv)
14437ac6653aSJeff Kirsher {
14447ac6653aSJeff Kirsher 	int status;
14457ac6653aSJeff Kirsher 
14467ac6653aSJeff Kirsher 	status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
14479125cdd1SGiuseppe CAVALLARO 	if (likely((status & handle_rx)) || (status & handle_tx)) {
14489125cdd1SGiuseppe CAVALLARO 		if (likely(napi_schedule_prep(&priv->napi))) {
14499125cdd1SGiuseppe CAVALLARO 			stmmac_disable_dma_irq(priv);
14509125cdd1SGiuseppe CAVALLARO 			__napi_schedule(&priv->napi);
14519125cdd1SGiuseppe CAVALLARO 		}
14529125cdd1SGiuseppe CAVALLARO 	}
14539125cdd1SGiuseppe CAVALLARO 	if (unlikely(status & tx_hard_error_bump_tc)) {
14547ac6653aSJeff Kirsher 		/* Try to bump up the dma threshold on this failure */
1455b2dec116SSonic Zhang 		if (unlikely(priv->xstats.threshold != SF_DMA_MODE) &&
1456b2dec116SSonic Zhang 		    (tc <= 256)) {
14577ac6653aSJeff Kirsher 			tc += 64;
1458c405abe2SSonic Zhang 			if (priv->plat->force_thresh_dma_mode)
1459c405abe2SSonic Zhang 				priv->hw->dma->dma_mode(priv->ioaddr, tc, tc);
1460c405abe2SSonic Zhang 			else
1461c405abe2SSonic Zhang 				priv->hw->dma->dma_mode(priv->ioaddr, tc,
1462c405abe2SSonic Zhang 					SF_DMA_MODE);
14637ac6653aSJeff Kirsher 			priv->xstats.threshold = tc;
14647ac6653aSJeff Kirsher 		}
14657ac6653aSJeff Kirsher 	} else if (unlikely(status == tx_hard_error))
14667ac6653aSJeff Kirsher 		stmmac_tx_err(priv);
14677ac6653aSJeff Kirsher }
14687ac6653aSJeff Kirsher 
146932ceabcaSGiuseppe CAVALLARO /**
147032ceabcaSGiuseppe CAVALLARO  * stmmac_mmc_setup: setup the Mac Management Counters (MMC)
147132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
147232ceabcaSGiuseppe CAVALLARO  * Description: this masks the MMC irq, in fact, the counters are managed in SW.
147332ceabcaSGiuseppe CAVALLARO  */
14741c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv)
14751c901a46SGiuseppe CAVALLARO {
14761c901a46SGiuseppe CAVALLARO 	unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
14771c901a46SGiuseppe CAVALLARO 	    MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
14781c901a46SGiuseppe CAVALLARO 
14791c901a46SGiuseppe CAVALLARO 	dwmac_mmc_intr_all_mask(priv->ioaddr);
14804f795b25SGiuseppe CAVALLARO 
14814f795b25SGiuseppe CAVALLARO 	if (priv->dma_cap.rmon) {
14821c901a46SGiuseppe CAVALLARO 		dwmac_mmc_ctrl(priv->ioaddr, mode);
14831c901a46SGiuseppe CAVALLARO 		memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
14844f795b25SGiuseppe CAVALLARO 	} else
1485aae54cffSStefan Roese 		pr_info(" No MAC Management Counters available\n");
14861c901a46SGiuseppe CAVALLARO }
14871c901a46SGiuseppe CAVALLARO 
1488732fdf0eSGiuseppe CAVALLARO /**
1489732fdf0eSGiuseppe CAVALLARO  * stmmac_get_synopsys_id - return the SYINID.
1490732fdf0eSGiuseppe CAVALLARO  * @priv: driver private structure
1491732fdf0eSGiuseppe CAVALLARO  * Description: this simple function is to decode and return the SYINID
1492732fdf0eSGiuseppe CAVALLARO  * starting from the HW core register.
1493732fdf0eSGiuseppe CAVALLARO  */
1494f0b9d786SGiuseppe CAVALLARO static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
1495f0b9d786SGiuseppe CAVALLARO {
1496f0b9d786SGiuseppe CAVALLARO 	u32 hwid = priv->hw->synopsys_uid;
1497f0b9d786SGiuseppe CAVALLARO 
1498ceb69499SGiuseppe CAVALLARO 	/* Check Synopsys Id (not available on old chips) */
1499f0b9d786SGiuseppe CAVALLARO 	if (likely(hwid)) {
1500f0b9d786SGiuseppe CAVALLARO 		u32 uid = ((hwid & 0x0000ff00) >> 8);
1501f0b9d786SGiuseppe CAVALLARO 		u32 synid = (hwid & 0x000000ff);
1502f0b9d786SGiuseppe CAVALLARO 
1503cf3f047bSGiuseppe CAVALLARO 		pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n",
1504f0b9d786SGiuseppe CAVALLARO 			uid, synid);
1505f0b9d786SGiuseppe CAVALLARO 
1506f0b9d786SGiuseppe CAVALLARO 		return synid;
1507f0b9d786SGiuseppe CAVALLARO 	}
1508f0b9d786SGiuseppe CAVALLARO 	return 0;
1509f0b9d786SGiuseppe CAVALLARO }
1510e7434821SGiuseppe CAVALLARO 
151119e30c14SGiuseppe CAVALLARO /**
1512732fdf0eSGiuseppe CAVALLARO  * stmmac_selec_desc_mode - to select among: normal/alternate/extend descriptors
151332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
151432ceabcaSGiuseppe CAVALLARO  * Description: select the Enhanced/Alternate or Normal descriptors.
1515732fdf0eSGiuseppe CAVALLARO  * In case of Enhanced/Alternate, it checks if the extended descriptors are
1516732fdf0eSGiuseppe CAVALLARO  * supported by the HW capability register.
1517ff3dd78cSGiuseppe CAVALLARO  */
151819e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
151919e30c14SGiuseppe CAVALLARO {
152019e30c14SGiuseppe CAVALLARO 	if (priv->plat->enh_desc) {
152119e30c14SGiuseppe CAVALLARO 		pr_info(" Enhanced/Alternate descriptors\n");
1522c24602efSGiuseppe CAVALLARO 
1523c24602efSGiuseppe CAVALLARO 		/* GMAC older than 3.50 has no extended descriptors */
1524c24602efSGiuseppe CAVALLARO 		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
1525c24602efSGiuseppe CAVALLARO 			pr_info("\tEnabled extended descriptors\n");
1526c24602efSGiuseppe CAVALLARO 			priv->extend_desc = 1;
1527c24602efSGiuseppe CAVALLARO 		} else
1528c24602efSGiuseppe CAVALLARO 			pr_warn("Extended descriptors not supported\n");
1529c24602efSGiuseppe CAVALLARO 
153019e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &enh_desc_ops;
153119e30c14SGiuseppe CAVALLARO 	} else {
153219e30c14SGiuseppe CAVALLARO 		pr_info(" Normal descriptors\n");
153319e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &ndesc_ops;
153419e30c14SGiuseppe CAVALLARO 	}
153519e30c14SGiuseppe CAVALLARO }
153619e30c14SGiuseppe CAVALLARO 
153719e30c14SGiuseppe CAVALLARO /**
1538732fdf0eSGiuseppe CAVALLARO  * stmmac_get_hw_features - get MAC capabilities from the HW cap. register.
153932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
154019e30c14SGiuseppe CAVALLARO  * Description:
154119e30c14SGiuseppe CAVALLARO  *  new GMAC chip generations have a new register to indicate the
1542e7434821SGiuseppe CAVALLARO  *  presence of the optional feature/functions.
154319e30c14SGiuseppe CAVALLARO  *  This can be also used to override the value passed through the
154419e30c14SGiuseppe CAVALLARO  *  platform and necessary for old MAC10/100 and GMAC chips.
1545e7434821SGiuseppe CAVALLARO  */
1546e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv)
1547e7434821SGiuseppe CAVALLARO {
15485e6efe88SGiuseppe CAVALLARO 	u32 hw_cap = 0;
15493c20f72fSGiuseppe CAVALLARO 
15505e6efe88SGiuseppe CAVALLARO 	if (priv->hw->dma->get_hw_feature) {
15515e6efe88SGiuseppe CAVALLARO 		hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
1552e7434821SGiuseppe CAVALLARO 
15531db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
15541db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
15551db123fbSRayagond Kokatanur 		priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
15561db123fbSRayagond Kokatanur 		priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
1557ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
15581db123fbSRayagond Kokatanur 		priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
15591db123fbSRayagond Kokatanur 		priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
15601db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_remote_wake_up =
15611db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
15621db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_magic_frame =
15631db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
15641db123fbSRayagond Kokatanur 		/* MMC */
15651db123fbSRayagond Kokatanur 		priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
1566e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2002 */
15671db123fbSRayagond Kokatanur 		priv->dma_cap.time_stamp =
15681db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
1569e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2008 */
15701db123fbSRayagond Kokatanur 		priv->dma_cap.atime_stamp =
15711db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
1572e7434821SGiuseppe CAVALLARO 		/* 802.3az - Energy-Efficient Ethernet (EEE) */
15731db123fbSRayagond Kokatanur 		priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
15741db123fbSRayagond Kokatanur 		priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
1575e7434821SGiuseppe CAVALLARO 		/* TX and RX csum */
15761db123fbSRayagond Kokatanur 		priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
15771db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type1 =
15781db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
15791db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type2 =
15801db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
15811db123fbSRayagond Kokatanur 		priv->dma_cap.rxfifo_over_2048 =
15821db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
1583e7434821SGiuseppe CAVALLARO 		/* TX and RX number of channels */
15841db123fbSRayagond Kokatanur 		priv->dma_cap.number_rx_channel =
15851db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
15861db123fbSRayagond Kokatanur 		priv->dma_cap.number_tx_channel =
15871db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
1588e7434821SGiuseppe CAVALLARO 		/* Alternate (enhanced) DESC mode */
1589ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
159019e30c14SGiuseppe CAVALLARO 	}
1591e7434821SGiuseppe CAVALLARO 
1592e7434821SGiuseppe CAVALLARO 	return hw_cap;
1593e7434821SGiuseppe CAVALLARO }
1594e7434821SGiuseppe CAVALLARO 
159532ceabcaSGiuseppe CAVALLARO /**
1596732fdf0eSGiuseppe CAVALLARO  * stmmac_check_ether_addr - check if the MAC addr is valid
159732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
159832ceabcaSGiuseppe CAVALLARO  * Description:
159932ceabcaSGiuseppe CAVALLARO  * it is to verify if the MAC address is valid, in case of failures it
160032ceabcaSGiuseppe CAVALLARO  * generates a random MAC address
160132ceabcaSGiuseppe CAVALLARO  */
1602bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv)
1603bfab27a1SGiuseppe CAVALLARO {
1604bfab27a1SGiuseppe CAVALLARO 	if (!is_valid_ether_addr(priv->dev->dev_addr)) {
16057ed24bbeSVince Bridgers 		priv->hw->mac->get_umac_addr(priv->hw,
1606bfab27a1SGiuseppe CAVALLARO 					     priv->dev->dev_addr, 0);
1607bfab27a1SGiuseppe CAVALLARO 		if (!is_valid_ether_addr(priv->dev->dev_addr))
1608f2cedb63SDanny Kukawka 			eth_hw_addr_random(priv->dev);
1609c88460b7SHans de Goede 		pr_info("%s: device MAC address %pM\n", priv->dev->name,
1610bfab27a1SGiuseppe CAVALLARO 			priv->dev->dev_addr);
1611bfab27a1SGiuseppe CAVALLARO 	}
1612c88460b7SHans de Goede }
1613bfab27a1SGiuseppe CAVALLARO 
161432ceabcaSGiuseppe CAVALLARO /**
1615732fdf0eSGiuseppe CAVALLARO  * stmmac_init_dma_engine - DMA init.
161632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
161732ceabcaSGiuseppe CAVALLARO  * Description:
161832ceabcaSGiuseppe CAVALLARO  * It inits the DMA invoking the specific MAC/GMAC callback.
161932ceabcaSGiuseppe CAVALLARO  * Some DMA parameters can be passed from the platform;
162032ceabcaSGiuseppe CAVALLARO  * in case of these are not passed a default is kept for the MAC or GMAC.
162132ceabcaSGiuseppe CAVALLARO  */
16220f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv)
16230f1f88a8SGiuseppe CAVALLARO {
16240f1f88a8SGiuseppe CAVALLARO 	int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0;
1625b9cde0a8SGiuseppe CAVALLARO 	int mixed_burst = 0;
1626c24602efSGiuseppe CAVALLARO 	int atds = 0;
16270f1f88a8SGiuseppe CAVALLARO 
16280f1f88a8SGiuseppe CAVALLARO 	if (priv->plat->dma_cfg) {
16290f1f88a8SGiuseppe CAVALLARO 		pbl = priv->plat->dma_cfg->pbl;
16300f1f88a8SGiuseppe CAVALLARO 		fixed_burst = priv->plat->dma_cfg->fixed_burst;
1631b9cde0a8SGiuseppe CAVALLARO 		mixed_burst = priv->plat->dma_cfg->mixed_burst;
16320f1f88a8SGiuseppe CAVALLARO 		burst_len = priv->plat->dma_cfg->burst_len;
16330f1f88a8SGiuseppe CAVALLARO 	}
16340f1f88a8SGiuseppe CAVALLARO 
1635c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
1636c24602efSGiuseppe CAVALLARO 		atds = 1;
1637c24602efSGiuseppe CAVALLARO 
1638b9cde0a8SGiuseppe CAVALLARO 	return priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst,
16390f1f88a8SGiuseppe CAVALLARO 				   burst_len, priv->dma_tx_phy,
1640c24602efSGiuseppe CAVALLARO 				   priv->dma_rx_phy, atds);
16410f1f88a8SGiuseppe CAVALLARO }
16420f1f88a8SGiuseppe CAVALLARO 
1643bfab27a1SGiuseppe CAVALLARO /**
1644732fdf0eSGiuseppe CAVALLARO  * stmmac_tx_timer - mitigation sw timer for tx.
16459125cdd1SGiuseppe CAVALLARO  * @data: data pointer
16469125cdd1SGiuseppe CAVALLARO  * Description:
16479125cdd1SGiuseppe CAVALLARO  * This is the timer handler to directly invoke the stmmac_tx_clean.
16489125cdd1SGiuseppe CAVALLARO  */
16499125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data)
16509125cdd1SGiuseppe CAVALLARO {
16519125cdd1SGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)data;
16529125cdd1SGiuseppe CAVALLARO 
16539125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
16549125cdd1SGiuseppe CAVALLARO }
16559125cdd1SGiuseppe CAVALLARO 
16569125cdd1SGiuseppe CAVALLARO /**
1657732fdf0eSGiuseppe CAVALLARO  * stmmac_init_tx_coalesce - init tx mitigation options.
165832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
16599125cdd1SGiuseppe CAVALLARO  * Description:
16609125cdd1SGiuseppe CAVALLARO  * This inits the transmit coalesce parameters: i.e. timer rate,
16619125cdd1SGiuseppe CAVALLARO  * timer handler and default threshold used for enabling the
16629125cdd1SGiuseppe CAVALLARO  * interrupt on completion bit.
16639125cdd1SGiuseppe CAVALLARO  */
16649125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
16659125cdd1SGiuseppe CAVALLARO {
16669125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_frames = STMMAC_TX_FRAMES;
16679125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
16689125cdd1SGiuseppe CAVALLARO 	init_timer(&priv->txtimer);
16699125cdd1SGiuseppe CAVALLARO 	priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
16709125cdd1SGiuseppe CAVALLARO 	priv->txtimer.data = (unsigned long)priv;
16719125cdd1SGiuseppe CAVALLARO 	priv->txtimer.function = stmmac_tx_timer;
16729125cdd1SGiuseppe CAVALLARO 	add_timer(&priv->txtimer);
16739125cdd1SGiuseppe CAVALLARO }
16749125cdd1SGiuseppe CAVALLARO 
16759125cdd1SGiuseppe CAVALLARO /**
1676732fdf0eSGiuseppe CAVALLARO  * stmmac_hw_setup - setup mac in a usable state.
1677523f11b5SSrinivas Kandagatla  *  @dev : pointer to the device structure.
1678523f11b5SSrinivas Kandagatla  *  Description:
1679732fdf0eSGiuseppe CAVALLARO  *  this is the main function to setup the HW in a usable state because the
1680732fdf0eSGiuseppe CAVALLARO  *  dma engine is reset, the core registers are configured (e.g. AXI,
1681732fdf0eSGiuseppe CAVALLARO  *  Checksum features, timers). The DMA is ready to start receiving and
1682732fdf0eSGiuseppe CAVALLARO  *  transmitting.
1683523f11b5SSrinivas Kandagatla  *  Return value:
1684523f11b5SSrinivas Kandagatla  *  0 on success and an appropriate (-)ve integer as defined in errno.h
1685523f11b5SSrinivas Kandagatla  *  file on failure.
1686523f11b5SSrinivas Kandagatla  */
1687fe131929SHuacai Chen static int stmmac_hw_setup(struct net_device *dev, bool init_ptp)
1688523f11b5SSrinivas Kandagatla {
1689523f11b5SSrinivas Kandagatla 	struct stmmac_priv *priv = netdev_priv(dev);
1690523f11b5SSrinivas Kandagatla 	int ret;
1691523f11b5SSrinivas Kandagatla 
1692523f11b5SSrinivas Kandagatla 	/* DMA initialization and SW reset */
1693523f11b5SSrinivas Kandagatla 	ret = stmmac_init_dma_engine(priv);
1694523f11b5SSrinivas Kandagatla 	if (ret < 0) {
1695523f11b5SSrinivas Kandagatla 		pr_err("%s: DMA engine initialization failed\n", __func__);
1696523f11b5SSrinivas Kandagatla 		return ret;
1697523f11b5SSrinivas Kandagatla 	}
1698523f11b5SSrinivas Kandagatla 
1699523f11b5SSrinivas Kandagatla 	/* Copy the MAC addr into the HW  */
17007ed24bbeSVince Bridgers 	priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0);
1701523f11b5SSrinivas Kandagatla 
1702523f11b5SSrinivas Kandagatla 	/* If required, perform hw setup of the bus. */
1703523f11b5SSrinivas Kandagatla 	if (priv->plat->bus_setup)
1704523f11b5SSrinivas Kandagatla 		priv->plat->bus_setup(priv->ioaddr);
1705523f11b5SSrinivas Kandagatla 
1706523f11b5SSrinivas Kandagatla 	/* Initialize the MAC Core */
17077ed24bbeSVince Bridgers 	priv->hw->mac->core_init(priv->hw, dev->mtu);
1708523f11b5SSrinivas Kandagatla 
1709978aded4SGiuseppe CAVALLARO 	ret = priv->hw->mac->rx_ipc(priv->hw);
1710978aded4SGiuseppe CAVALLARO 	if (!ret) {
1711978aded4SGiuseppe CAVALLARO 		pr_warn(" RX IPC Checksum Offload disabled\n");
1712978aded4SGiuseppe CAVALLARO 		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
1713d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
1714978aded4SGiuseppe CAVALLARO 	}
1715978aded4SGiuseppe CAVALLARO 
1716523f11b5SSrinivas Kandagatla 	/* Enable the MAC Rx/Tx */
1717523f11b5SSrinivas Kandagatla 	stmmac_set_mac(priv->ioaddr, true);
1718523f11b5SSrinivas Kandagatla 
1719523f11b5SSrinivas Kandagatla 	/* Set the HW DMA mode and the COE */
1720523f11b5SSrinivas Kandagatla 	stmmac_dma_operation_mode(priv);
1721523f11b5SSrinivas Kandagatla 
1722523f11b5SSrinivas Kandagatla 	stmmac_mmc_setup(priv);
1723523f11b5SSrinivas Kandagatla 
1724fe131929SHuacai Chen 	if (init_ptp) {
1725523f11b5SSrinivas Kandagatla 		ret = stmmac_init_ptp(priv);
17267509edd6SHans de Goede 		if (ret && ret != -EOPNOTSUPP)
1727523f11b5SSrinivas Kandagatla 			pr_warn("%s: failed PTP initialisation\n", __func__);
1728fe131929SHuacai Chen 	}
1729523f11b5SSrinivas Kandagatla 
173050fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
1731523f11b5SSrinivas Kandagatla 	ret = stmmac_init_fs(dev);
1732523f11b5SSrinivas Kandagatla 	if (ret < 0)
1733523f11b5SSrinivas Kandagatla 		pr_warn("%s: failed debugFS registration\n", __func__);
1734523f11b5SSrinivas Kandagatla #endif
1735523f11b5SSrinivas Kandagatla 	/* Start the ball rolling... */
1736523f11b5SSrinivas Kandagatla 	pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
1737523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_tx(priv->ioaddr);
1738523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_rx(priv->ioaddr);
1739523f11b5SSrinivas Kandagatla 
1740523f11b5SSrinivas Kandagatla 	/* Dump DMA/MAC registers */
1741523f11b5SSrinivas Kandagatla 	if (netif_msg_hw(priv)) {
17427ed24bbeSVince Bridgers 		priv->hw->mac->dump_regs(priv->hw);
1743523f11b5SSrinivas Kandagatla 		priv->hw->dma->dump_regs(priv->ioaddr);
1744523f11b5SSrinivas Kandagatla 	}
1745523f11b5SSrinivas Kandagatla 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
1746523f11b5SSrinivas Kandagatla 
1747523f11b5SSrinivas Kandagatla 	if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
1748523f11b5SSrinivas Kandagatla 		priv->rx_riwt = MAX_DMA_RIWT;
1749523f11b5SSrinivas Kandagatla 		priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
1750523f11b5SSrinivas Kandagatla 	}
1751523f11b5SSrinivas Kandagatla 
1752523f11b5SSrinivas Kandagatla 	if (priv->pcs && priv->hw->mac->ctrl_ane)
17537ed24bbeSVince Bridgers 		priv->hw->mac->ctrl_ane(priv->hw, 0);
1754523f11b5SSrinivas Kandagatla 
1755523f11b5SSrinivas Kandagatla 	return 0;
1756523f11b5SSrinivas Kandagatla }
1757523f11b5SSrinivas Kandagatla 
1758523f11b5SSrinivas Kandagatla /**
17597ac6653aSJeff Kirsher  *  stmmac_open - open entry point of the driver
17607ac6653aSJeff Kirsher  *  @dev : pointer to the device structure.
17617ac6653aSJeff Kirsher  *  Description:
17627ac6653aSJeff Kirsher  *  This function is the open entry point of the driver.
17637ac6653aSJeff Kirsher  *  Return value:
17647ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
17657ac6653aSJeff Kirsher  *  file on failure.
17667ac6653aSJeff Kirsher  */
17677ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev)
17687ac6653aSJeff Kirsher {
17697ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
17707ac6653aSJeff Kirsher 	int ret;
17717ac6653aSJeff Kirsher 
17724bfcbd7aSFrancesco Virlinzi 	stmmac_check_ether_addr(priv);
17734bfcbd7aSFrancesco Virlinzi 
17744d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
17754d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
17767ac6653aSJeff Kirsher 		ret = stmmac_init_phy(dev);
1777e58bb43fSGiuseppe CAVALLARO 		if (ret) {
1778e58bb43fSGiuseppe CAVALLARO 			pr_err("%s: Cannot attach to PHY (error: %d)\n",
1779e58bb43fSGiuseppe CAVALLARO 			       __func__, ret);
178089df20d9SHans de Goede 			return ret;
17817ac6653aSJeff Kirsher 		}
1782e58bb43fSGiuseppe CAVALLARO 	}
17837ac6653aSJeff Kirsher 
1784523f11b5SSrinivas Kandagatla 	/* Extra statistics */
1785523f11b5SSrinivas Kandagatla 	memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
1786523f11b5SSrinivas Kandagatla 	priv->xstats.threshold = tc;
1787523f11b5SSrinivas Kandagatla 
17887ac6653aSJeff Kirsher 	/* Create and initialize the TX/RX descriptors chains. */
17897ac6653aSJeff Kirsher 	priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
17907ac6653aSJeff Kirsher 	priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
17917ac6653aSJeff Kirsher 	priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
179256329137SBartlomiej Zolnierkiewicz 
17937262b7b2STobias Klauser 	ret = alloc_dma_desc_resources(priv);
179409f8d696SSrinivas Kandagatla 	if (ret < 0) {
179509f8d696SSrinivas Kandagatla 		pr_err("%s: DMA descriptors allocation failed\n", __func__);
179609f8d696SSrinivas Kandagatla 		goto dma_desc_error;
179709f8d696SSrinivas Kandagatla 	}
179809f8d696SSrinivas Kandagatla 
1799777da230SGiuseppe CAVALLARO 	ret = init_dma_desc_rings(dev, GFP_KERNEL);
1800777da230SGiuseppe CAVALLARO 	if (ret < 0) {
1801777da230SGiuseppe CAVALLARO 		pr_err("%s: DMA descriptors initialization failed\n", __func__);
1802777da230SGiuseppe CAVALLARO 		goto init_error;
1803777da230SGiuseppe CAVALLARO 	}
1804777da230SGiuseppe CAVALLARO 
1805fe131929SHuacai Chen 	ret = stmmac_hw_setup(dev, true);
180656329137SBartlomiej Zolnierkiewicz 	if (ret < 0) {
1807523f11b5SSrinivas Kandagatla 		pr_err("%s: Hw setup failed\n", __func__);
1808c9324d18SGiuseppe CAVALLARO 		goto init_error;
18097ac6653aSJeff Kirsher 	}
18107ac6653aSJeff Kirsher 
1811777da230SGiuseppe CAVALLARO 	stmmac_init_tx_coalesce(priv);
1812777da230SGiuseppe CAVALLARO 
1813523f11b5SSrinivas Kandagatla 	if (priv->phydev)
1814523f11b5SSrinivas Kandagatla 		phy_start(priv->phydev);
18157ac6653aSJeff Kirsher 
18167ac6653aSJeff Kirsher 	/* Request the IRQ lines */
18177ac6653aSJeff Kirsher 	ret = request_irq(dev->irq, stmmac_interrupt,
18187ac6653aSJeff Kirsher 			  IRQF_SHARED, dev->name, dev);
18197ac6653aSJeff Kirsher 	if (unlikely(ret < 0)) {
18207ac6653aSJeff Kirsher 		pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
18217ac6653aSJeff Kirsher 		       __func__, dev->irq, ret);
1822c9324d18SGiuseppe CAVALLARO 		goto init_error;
18237ac6653aSJeff Kirsher 	}
18247ac6653aSJeff Kirsher 
18257a13f8f5SFrancesco Virlinzi 	/* Request the Wake IRQ in case of another line is used for WoL */
18267a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq) {
18277a13f8f5SFrancesco Virlinzi 		ret = request_irq(priv->wol_irq, stmmac_interrupt,
18287a13f8f5SFrancesco Virlinzi 				  IRQF_SHARED, dev->name, dev);
18297a13f8f5SFrancesco Virlinzi 		if (unlikely(ret < 0)) {
1830ceb69499SGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n",
1831ceb69499SGiuseppe CAVALLARO 			       __func__, priv->wol_irq, ret);
1832c9324d18SGiuseppe CAVALLARO 			goto wolirq_error;
18337a13f8f5SFrancesco Virlinzi 		}
18347a13f8f5SFrancesco Virlinzi 	}
18357a13f8f5SFrancesco Virlinzi 
1836d765955dSGiuseppe CAVALLARO 	/* Request the IRQ lines */
1837d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0) {
1838d765955dSGiuseppe CAVALLARO 		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
1839d765955dSGiuseppe CAVALLARO 				  dev->name, dev);
1840d765955dSGiuseppe CAVALLARO 		if (unlikely(ret < 0)) {
1841d765955dSGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
1842d765955dSGiuseppe CAVALLARO 			       __func__, priv->lpi_irq, ret);
1843c9324d18SGiuseppe CAVALLARO 			goto lpiirq_error;
1844d765955dSGiuseppe CAVALLARO 		}
1845d765955dSGiuseppe CAVALLARO 	}
1846d765955dSGiuseppe CAVALLARO 
18477ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
18487ac6653aSJeff Kirsher 	netif_start_queue(dev);
18497ac6653aSJeff Kirsher 
18507ac6653aSJeff Kirsher 	return 0;
18517ac6653aSJeff Kirsher 
1852c9324d18SGiuseppe CAVALLARO lpiirq_error:
1853d765955dSGiuseppe CAVALLARO 	if (priv->wol_irq != dev->irq)
1854d765955dSGiuseppe CAVALLARO 		free_irq(priv->wol_irq, dev);
1855c9324d18SGiuseppe CAVALLARO wolirq_error:
18567a13f8f5SFrancesco Virlinzi 	free_irq(dev->irq, dev);
18577a13f8f5SFrancesco Virlinzi 
1858c9324d18SGiuseppe CAVALLARO init_error:
1859c9324d18SGiuseppe CAVALLARO 	free_dma_desc_resources(priv);
186056329137SBartlomiej Zolnierkiewicz dma_desc_error:
18617ac6653aSJeff Kirsher 	if (priv->phydev)
18627ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
18634bfcbd7aSFrancesco Virlinzi 
18647ac6653aSJeff Kirsher 	return ret;
18657ac6653aSJeff Kirsher }
18667ac6653aSJeff Kirsher 
18677ac6653aSJeff Kirsher /**
18687ac6653aSJeff Kirsher  *  stmmac_release - close entry point of the driver
18697ac6653aSJeff Kirsher  *  @dev : device pointer.
18707ac6653aSJeff Kirsher  *  Description:
18717ac6653aSJeff Kirsher  *  This is the stop entry point of the driver.
18727ac6653aSJeff Kirsher  */
18737ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev)
18747ac6653aSJeff Kirsher {
18757ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
18767ac6653aSJeff Kirsher 
1877d765955dSGiuseppe CAVALLARO 	if (priv->eee_enabled)
1878d765955dSGiuseppe CAVALLARO 		del_timer_sync(&priv->eee_ctrl_timer);
1879d765955dSGiuseppe CAVALLARO 
18807ac6653aSJeff Kirsher 	/* Stop and disconnect the PHY */
18817ac6653aSJeff Kirsher 	if (priv->phydev) {
18827ac6653aSJeff Kirsher 		phy_stop(priv->phydev);
18837ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
18847ac6653aSJeff Kirsher 		priv->phydev = NULL;
18857ac6653aSJeff Kirsher 	}
18867ac6653aSJeff Kirsher 
18877ac6653aSJeff Kirsher 	netif_stop_queue(dev);
18887ac6653aSJeff Kirsher 
18897ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
18907ac6653aSJeff Kirsher 
18919125cdd1SGiuseppe CAVALLARO 	del_timer_sync(&priv->txtimer);
18929125cdd1SGiuseppe CAVALLARO 
18937ac6653aSJeff Kirsher 	/* Free the IRQ lines */
18947ac6653aSJeff Kirsher 	free_irq(dev->irq, dev);
18957a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq)
18967a13f8f5SFrancesco Virlinzi 		free_irq(priv->wol_irq, dev);
1897d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0)
1898d765955dSGiuseppe CAVALLARO 		free_irq(priv->lpi_irq, dev);
18997ac6653aSJeff Kirsher 
19007ac6653aSJeff Kirsher 	/* Stop TX/RX DMA and clear the descriptors */
19017ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
19027ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
19037ac6653aSJeff Kirsher 
19047ac6653aSJeff Kirsher 	/* Release and free the Rx/Tx resources */
19057ac6653aSJeff Kirsher 	free_dma_desc_resources(priv);
19067ac6653aSJeff Kirsher 
19077ac6653aSJeff Kirsher 	/* Disable the MAC Rx/Tx */
1908bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
19097ac6653aSJeff Kirsher 
19107ac6653aSJeff Kirsher 	netif_carrier_off(dev);
19117ac6653aSJeff Kirsher 
191250fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
1913bfab27a1SGiuseppe CAVALLARO 	stmmac_exit_fs();
1914bfab27a1SGiuseppe CAVALLARO #endif
1915bfab27a1SGiuseppe CAVALLARO 
191692ba6888SRayagond Kokatanur 	stmmac_release_ptp(priv);
191792ba6888SRayagond Kokatanur 
19187ac6653aSJeff Kirsher 	return 0;
19197ac6653aSJeff Kirsher }
19207ac6653aSJeff Kirsher 
19217ac6653aSJeff Kirsher /**
1922732fdf0eSGiuseppe CAVALLARO  *  stmmac_xmit - Tx entry point of the driver
19237ac6653aSJeff Kirsher  *  @skb : the socket buffer
19247ac6653aSJeff Kirsher  *  @dev : device pointer
192532ceabcaSGiuseppe CAVALLARO  *  Description : this is the tx entry point of the driver.
192632ceabcaSGiuseppe CAVALLARO  *  It programs the chain or the ring and supports oversized frames
192732ceabcaSGiuseppe CAVALLARO  *  and SG feature.
19287ac6653aSJeff Kirsher  */
19297ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
19307ac6653aSJeff Kirsher {
19317ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
19327ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
19337ac6653aSJeff Kirsher 	unsigned int entry;
19344a7d666aSGiuseppe CAVALLARO 	int i, csum_insertion = 0, is_jumbo = 0;
19357ac6653aSJeff Kirsher 	int nfrags = skb_shinfo(skb)->nr_frags;
19367ac6653aSJeff Kirsher 	struct dma_desc *desc, *first;
1937286a8372SGiuseppe CAVALLARO 	unsigned int nopaged_len = skb_headlen(skb);
193829896a67SGiuseppe CAVALLARO 	unsigned int enh_desc = priv->plat->enh_desc;
19397ac6653aSJeff Kirsher 
194016ee817eSFabrice Gasnier 	spin_lock(&priv->tx_lock);
194116ee817eSFabrice Gasnier 
19427ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
194316ee817eSFabrice Gasnier 		spin_unlock(&priv->tx_lock);
19447ac6653aSJeff Kirsher 		if (!netif_queue_stopped(dev)) {
19457ac6653aSJeff Kirsher 			netif_stop_queue(dev);
19467ac6653aSJeff Kirsher 			/* This is a hard error, log it. */
1947ceb69499SGiuseppe CAVALLARO 			pr_err("%s: Tx Ring full when queue awake\n", __func__);
19487ac6653aSJeff Kirsher 		}
19497ac6653aSJeff Kirsher 		return NETDEV_TX_BUSY;
19507ac6653aSJeff Kirsher 	}
19517ac6653aSJeff Kirsher 
1952d765955dSGiuseppe CAVALLARO 	if (priv->tx_path_in_lpi_mode)
1953d765955dSGiuseppe CAVALLARO 		stmmac_disable_eee_mode(priv);
1954d765955dSGiuseppe CAVALLARO 
19557ac6653aSJeff Kirsher 	entry = priv->cur_tx % txsize;
19567ac6653aSJeff Kirsher 
19577ac6653aSJeff Kirsher 	csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
19587ac6653aSJeff Kirsher 
1959c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc)
1960c24602efSGiuseppe CAVALLARO 		desc = (struct dma_desc *)(priv->dma_etx + entry);
1961c24602efSGiuseppe CAVALLARO 	else
19627ac6653aSJeff Kirsher 		desc = priv->dma_tx + entry;
1963c24602efSGiuseppe CAVALLARO 
19647ac6653aSJeff Kirsher 	first = desc;
19657ac6653aSJeff Kirsher 
19664a7d666aSGiuseppe CAVALLARO 	/* To program the descriptors according to the size of the frame */
196729896a67SGiuseppe CAVALLARO 	if (enh_desc)
196829896a67SGiuseppe CAVALLARO 		is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc);
196929896a67SGiuseppe CAVALLARO 
19704a7d666aSGiuseppe CAVALLARO 	if (likely(!is_jumbo)) {
19717ac6653aSJeff Kirsher 		desc->des2 = dma_map_single(priv->device, skb->data,
19727ac6653aSJeff Kirsher 					    nopaged_len, DMA_TO_DEVICE);
1973362b37beSGiuseppe CAVALLARO 		if (dma_mapping_error(priv->device, desc->des2))
1974362b37beSGiuseppe CAVALLARO 			goto dma_map_err;
1975362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[entry].buf = desc->des2;
19767ac6653aSJeff Kirsher 		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
19774a7d666aSGiuseppe CAVALLARO 						csum_insertion, priv->mode);
197829896a67SGiuseppe CAVALLARO 	} else {
1979c24602efSGiuseppe CAVALLARO 		desc = first;
198029896a67SGiuseppe CAVALLARO 		entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion);
1981362b37beSGiuseppe CAVALLARO 		if (unlikely(entry < 0))
1982362b37beSGiuseppe CAVALLARO 			goto dma_map_err;
198329896a67SGiuseppe CAVALLARO 	}
19847ac6653aSJeff Kirsher 
19857ac6653aSJeff Kirsher 	for (i = 0; i < nfrags; i++) {
19869e903e08SEric Dumazet 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
19879e903e08SEric Dumazet 		int len = skb_frag_size(frag);
19887ac6653aSJeff Kirsher 
198975e4364fSdamuzi000 		priv->tx_skbuff[entry] = NULL;
19907ac6653aSJeff Kirsher 		entry = (++priv->cur_tx) % txsize;
1991c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1992c24602efSGiuseppe CAVALLARO 			desc = (struct dma_desc *)(priv->dma_etx + entry);
1993c24602efSGiuseppe CAVALLARO 		else
19947ac6653aSJeff Kirsher 			desc = priv->dma_tx + entry;
19957ac6653aSJeff Kirsher 
1996f722380dSIan Campbell 		desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
1997f722380dSIan Campbell 					      DMA_TO_DEVICE);
1998362b37beSGiuseppe CAVALLARO 		if (dma_mapping_error(priv->device, desc->des2))
1999362b37beSGiuseppe CAVALLARO 			goto dma_map_err; /* should reuse desc w/o issues */
2000362b37beSGiuseppe CAVALLARO 
2001362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[entry].buf = desc->des2;
2002362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[entry].map_as_page = true;
20034a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
20044a7d666aSGiuseppe CAVALLARO 						priv->mode);
20057ac6653aSJeff Kirsher 		wmb();
20067ac6653aSJeff Kirsher 		priv->hw->desc->set_tx_owner(desc);
20078e839891SDeepak Sikri 		wmb();
20087ac6653aSJeff Kirsher 	}
20097ac6653aSJeff Kirsher 
201075e4364fSdamuzi000 	priv->tx_skbuff[entry] = skb;
201175e4364fSdamuzi000 
20129125cdd1SGiuseppe CAVALLARO 	/* Finalize the latest segment. */
20137ac6653aSJeff Kirsher 	priv->hw->desc->close_tx_desc(desc);
20147ac6653aSJeff Kirsher 
20157ac6653aSJeff Kirsher 	wmb();
20169125cdd1SGiuseppe CAVALLARO 	/* According to the coalesce parameter the IC bit for the latest
20179125cdd1SGiuseppe CAVALLARO 	 * segment could be reset and the timer re-started to invoke the
20189125cdd1SGiuseppe CAVALLARO 	 * stmmac_tx function. This approach takes care about the fragments.
20199125cdd1SGiuseppe CAVALLARO 	 */
20209125cdd1SGiuseppe CAVALLARO 	priv->tx_count_frames += nfrags + 1;
20219125cdd1SGiuseppe CAVALLARO 	if (priv->tx_coal_frames > priv->tx_count_frames) {
20229125cdd1SGiuseppe CAVALLARO 		priv->hw->desc->clear_tx_ic(desc);
20239125cdd1SGiuseppe CAVALLARO 		priv->xstats.tx_reset_ic_bit++;
20249125cdd1SGiuseppe CAVALLARO 		mod_timer(&priv->txtimer,
20259125cdd1SGiuseppe CAVALLARO 			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
20269125cdd1SGiuseppe CAVALLARO 	} else
20279125cdd1SGiuseppe CAVALLARO 		priv->tx_count_frames = 0;
20287ac6653aSJeff Kirsher 
20297ac6653aSJeff Kirsher 	/* To avoid raise condition */
20307ac6653aSJeff Kirsher 	priv->hw->desc->set_tx_owner(first);
20318e839891SDeepak Sikri 	wmb();
20327ac6653aSJeff Kirsher 
20337ac6653aSJeff Kirsher 	priv->cur_tx++;
20347ac6653aSJeff Kirsher 
20357ac6653aSJeff Kirsher 	if (netif_msg_pktdata(priv)) {
203683d7af64SGiuseppe CAVALLARO 		pr_debug("%s: curr %d dirty=%d entry=%d, first=%p, nfrags=%d",
2037ceb69499SGiuseppe CAVALLARO 			__func__, (priv->cur_tx % txsize),
2038ceb69499SGiuseppe CAVALLARO 			(priv->dirty_tx % txsize), entry, first, nfrags);
203983d7af64SGiuseppe CAVALLARO 
2040c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2041c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
2042c24602efSGiuseppe CAVALLARO 		else
2043c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
2044c24602efSGiuseppe CAVALLARO 
204583d7af64SGiuseppe CAVALLARO 		pr_debug(">>> frame to be transmitted: ");
20467ac6653aSJeff Kirsher 		print_pkt(skb->data, skb->len);
20477ac6653aSJeff Kirsher 	}
20487ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
204983d7af64SGiuseppe CAVALLARO 		if (netif_msg_hw(priv))
205083d7af64SGiuseppe CAVALLARO 			pr_debug("%s: stop transmitted packets\n", __func__);
20517ac6653aSJeff Kirsher 		netif_stop_queue(dev);
20527ac6653aSJeff Kirsher 	}
20537ac6653aSJeff Kirsher 
20547ac6653aSJeff Kirsher 	dev->stats.tx_bytes += skb->len;
20557ac6653aSJeff Kirsher 
2056891434b1SRayagond Kokatanur 	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
2057891434b1SRayagond Kokatanur 		     priv->hwts_tx_en)) {
2058891434b1SRayagond Kokatanur 		/* declare that device is doing timestamping */
2059891434b1SRayagond Kokatanur 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
2060891434b1SRayagond Kokatanur 		priv->hw->desc->enable_tx_timestamp(first);
2061891434b1SRayagond Kokatanur 	}
2062891434b1SRayagond Kokatanur 
2063891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
20647ac6653aSJeff Kirsher 		skb_tx_timestamp(skb);
20657ac6653aSJeff Kirsher 
206638979574SBeniamino Galvani 	netdev_sent_queue(dev, skb->len);
20677ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_transmission(priv->ioaddr);
20687ac6653aSJeff Kirsher 
2069a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
2070362b37beSGiuseppe CAVALLARO 	return NETDEV_TX_OK;
2071a9097a96SGiuseppe CAVALLARO 
2072362b37beSGiuseppe CAVALLARO dma_map_err:
2073758a0ab5SFabrice Gasnier 	spin_unlock(&priv->tx_lock);
2074362b37beSGiuseppe CAVALLARO 	dev_err(priv->device, "Tx dma map failed\n");
2075362b37beSGiuseppe CAVALLARO 	dev_kfree_skb(skb);
2076362b37beSGiuseppe CAVALLARO 	priv->dev->stats.tx_dropped++;
20777ac6653aSJeff Kirsher 	return NETDEV_TX_OK;
20787ac6653aSJeff Kirsher }
20797ac6653aSJeff Kirsher 
2080b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
2081b9381985SVince Bridgers {
2082b9381985SVince Bridgers 	struct ethhdr *ehdr;
2083b9381985SVince Bridgers 	u16 vlanid;
2084b9381985SVince Bridgers 
2085b9381985SVince Bridgers 	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
2086b9381985SVince Bridgers 	    NETIF_F_HW_VLAN_CTAG_RX &&
2087b9381985SVince Bridgers 	    !__vlan_get_tag(skb, &vlanid)) {
2088b9381985SVince Bridgers 		/* pop the vlan tag */
2089b9381985SVince Bridgers 		ehdr = (struct ethhdr *)skb->data;
2090b9381985SVince Bridgers 		memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
2091b9381985SVince Bridgers 		skb_pull(skb, VLAN_HLEN);
2092b9381985SVince Bridgers 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
2093b9381985SVince Bridgers 	}
2094b9381985SVince Bridgers }
2095b9381985SVince Bridgers 
2096b9381985SVince Bridgers 
209732ceabcaSGiuseppe CAVALLARO /**
2098732fdf0eSGiuseppe CAVALLARO  * stmmac_rx_refill - refill used skb preallocated buffers
209932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
210032ceabcaSGiuseppe CAVALLARO  * Description : this is to reallocate the skb for the reception process
210132ceabcaSGiuseppe CAVALLARO  * that is based on zero-copy.
210232ceabcaSGiuseppe CAVALLARO  */
21037ac6653aSJeff Kirsher static inline void stmmac_rx_refill(struct stmmac_priv *priv)
21047ac6653aSJeff Kirsher {
21057ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
21067ac6653aSJeff Kirsher 	int bfsize = priv->dma_buf_sz;
21077ac6653aSJeff Kirsher 
21087ac6653aSJeff Kirsher 	for (; priv->cur_rx - priv->dirty_rx > 0; priv->dirty_rx++) {
21097ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_rx % rxsize;
2110c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
2111c24602efSGiuseppe CAVALLARO 
2112c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2113c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2114c24602efSGiuseppe CAVALLARO 		else
2115c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2116c24602efSGiuseppe CAVALLARO 
21177ac6653aSJeff Kirsher 		if (likely(priv->rx_skbuff[entry] == NULL)) {
21187ac6653aSJeff Kirsher 			struct sk_buff *skb;
21197ac6653aSJeff Kirsher 
2120acb600deSEric Dumazet 			skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
21217ac6653aSJeff Kirsher 
21227ac6653aSJeff Kirsher 			if (unlikely(skb == NULL))
21237ac6653aSJeff Kirsher 				break;
21247ac6653aSJeff Kirsher 
21257ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = skb;
21267ac6653aSJeff Kirsher 			priv->rx_skbuff_dma[entry] =
21277ac6653aSJeff Kirsher 			    dma_map_single(priv->device, skb->data, bfsize,
21287ac6653aSJeff Kirsher 					   DMA_FROM_DEVICE);
2129362b37beSGiuseppe CAVALLARO 			if (dma_mapping_error(priv->device,
2130362b37beSGiuseppe CAVALLARO 					      priv->rx_skbuff_dma[entry])) {
2131362b37beSGiuseppe CAVALLARO 				dev_err(priv->device, "Rx dma map failed\n");
2132362b37beSGiuseppe CAVALLARO 				dev_kfree_skb(skb);
2133362b37beSGiuseppe CAVALLARO 				break;
2134362b37beSGiuseppe CAVALLARO 			}
2135c24602efSGiuseppe CAVALLARO 			p->des2 = priv->rx_skbuff_dma[entry];
2136286a8372SGiuseppe CAVALLARO 
213729896a67SGiuseppe CAVALLARO 			priv->hw->mode->refill_desc3(priv, p);
2138286a8372SGiuseppe CAVALLARO 
213983d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv))
214083d7af64SGiuseppe CAVALLARO 				pr_debug("\trefill entry #%d\n", entry);
21417ac6653aSJeff Kirsher 		}
21427ac6653aSJeff Kirsher 		wmb();
2143c24602efSGiuseppe CAVALLARO 		priv->hw->desc->set_rx_owner(p);
21448e839891SDeepak Sikri 		wmb();
21457ac6653aSJeff Kirsher 	}
21467ac6653aSJeff Kirsher }
21477ac6653aSJeff Kirsher 
214832ceabcaSGiuseppe CAVALLARO /**
2149732fdf0eSGiuseppe CAVALLARO  * stmmac_rx - manage the receive process
215032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
215132ceabcaSGiuseppe CAVALLARO  * @limit: napi bugget.
215232ceabcaSGiuseppe CAVALLARO  * Description :  this the function called by the napi poll method.
215332ceabcaSGiuseppe CAVALLARO  * It gets all the frames inside the ring.
215432ceabcaSGiuseppe CAVALLARO  */
21557ac6653aSJeff Kirsher static int stmmac_rx(struct stmmac_priv *priv, int limit)
21567ac6653aSJeff Kirsher {
21577ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
21587ac6653aSJeff Kirsher 	unsigned int entry = priv->cur_rx % rxsize;
21597ac6653aSJeff Kirsher 	unsigned int next_entry;
21607ac6653aSJeff Kirsher 	unsigned int count = 0;
2161d2afb5bdSGiuseppe CAVALLARO 	int coe = priv->hw->rx_csum;
21627ac6653aSJeff Kirsher 
216383d7af64SGiuseppe CAVALLARO 	if (netif_msg_rx_status(priv)) {
216483d7af64SGiuseppe CAVALLARO 		pr_debug("%s: descriptor ring:\n", __func__);
2165c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2166c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
2167c24602efSGiuseppe CAVALLARO 		else
2168c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
21697ac6653aSJeff Kirsher 	}
2170c24602efSGiuseppe CAVALLARO 	while (count < limit) {
21717ac6653aSJeff Kirsher 		int status;
21729401bb5cSGiuseppe CAVALLARO 		struct dma_desc *p;
21737ac6653aSJeff Kirsher 
2174c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2175c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2176c24602efSGiuseppe CAVALLARO 		else
2177c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2178c24602efSGiuseppe CAVALLARO 
2179c24602efSGiuseppe CAVALLARO 		if (priv->hw->desc->get_rx_owner(p))
21807ac6653aSJeff Kirsher 			break;
21817ac6653aSJeff Kirsher 
21827ac6653aSJeff Kirsher 		count++;
21837ac6653aSJeff Kirsher 
21847ac6653aSJeff Kirsher 		next_entry = (++priv->cur_rx) % rxsize;
2185c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
21869401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_erx + next_entry);
2187c24602efSGiuseppe CAVALLARO 		else
21889401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_rx + next_entry);
21897ac6653aSJeff Kirsher 
21907ac6653aSJeff Kirsher 		/* read the status of the incoming frame */
2191c24602efSGiuseppe CAVALLARO 		status = priv->hw->desc->rx_status(&priv->dev->stats,
2192c24602efSGiuseppe CAVALLARO 						   &priv->xstats, p);
2193c24602efSGiuseppe CAVALLARO 		if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status))
2194c24602efSGiuseppe CAVALLARO 			priv->hw->desc->rx_extended_status(&priv->dev->stats,
2195c24602efSGiuseppe CAVALLARO 							   &priv->xstats,
2196c24602efSGiuseppe CAVALLARO 							   priv->dma_erx +
2197c24602efSGiuseppe CAVALLARO 							   entry);
2198891434b1SRayagond Kokatanur 		if (unlikely(status == discard_frame)) {
21997ac6653aSJeff Kirsher 			priv->dev->stats.rx_errors++;
2200891434b1SRayagond Kokatanur 			if (priv->hwts_rx_en && !priv->extend_desc) {
2201891434b1SRayagond Kokatanur 				/* DESC2 & DESC3 will be overwitten by device
2202891434b1SRayagond Kokatanur 				 * with timestamp value, hence reinitialize
2203891434b1SRayagond Kokatanur 				 * them in stmmac_rx_refill() function so that
2204891434b1SRayagond Kokatanur 				 * device can reuse it.
2205891434b1SRayagond Kokatanur 				 */
2206891434b1SRayagond Kokatanur 				priv->rx_skbuff[entry] = NULL;
2207891434b1SRayagond Kokatanur 				dma_unmap_single(priv->device,
2208891434b1SRayagond Kokatanur 						 priv->rx_skbuff_dma[entry],
2209ceb69499SGiuseppe CAVALLARO 						 priv->dma_buf_sz,
2210ceb69499SGiuseppe CAVALLARO 						 DMA_FROM_DEVICE);
2211891434b1SRayagond Kokatanur 			}
2212891434b1SRayagond Kokatanur 		} else {
22137ac6653aSJeff Kirsher 			struct sk_buff *skb;
22147ac6653aSJeff Kirsher 			int frame_len;
22157ac6653aSJeff Kirsher 
2216ceb69499SGiuseppe CAVALLARO 			frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
2217ceb69499SGiuseppe CAVALLARO 
22187ac6653aSJeff Kirsher 			/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
2219ceb69499SGiuseppe CAVALLARO 			 * Type frames (LLC/LLC-SNAP)
2220ceb69499SGiuseppe CAVALLARO 			 */
22217ac6653aSJeff Kirsher 			if (unlikely(status != llc_snap))
22227ac6653aSJeff Kirsher 				frame_len -= ETH_FCS_LEN;
22237ac6653aSJeff Kirsher 
222483d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv)) {
22257ac6653aSJeff Kirsher 				pr_debug("\tdesc: %p [entry %d] buff=0x%x\n",
22267ac6653aSJeff Kirsher 					 p, entry, p->des2);
222783d7af64SGiuseppe CAVALLARO 				if (frame_len > ETH_FRAME_LEN)
222883d7af64SGiuseppe CAVALLARO 					pr_debug("\tframe size %d, COE: %d\n",
222983d7af64SGiuseppe CAVALLARO 						 frame_len, status);
223083d7af64SGiuseppe CAVALLARO 			}
22317ac6653aSJeff Kirsher 			skb = priv->rx_skbuff[entry];
22327ac6653aSJeff Kirsher 			if (unlikely(!skb)) {
22337ac6653aSJeff Kirsher 				pr_err("%s: Inconsistent Rx descriptor chain\n",
22347ac6653aSJeff Kirsher 				       priv->dev->name);
22357ac6653aSJeff Kirsher 				priv->dev->stats.rx_dropped++;
22367ac6653aSJeff Kirsher 				break;
22377ac6653aSJeff Kirsher 			}
22387ac6653aSJeff Kirsher 			prefetch(skb->data - NET_IP_ALIGN);
22397ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = NULL;
22407ac6653aSJeff Kirsher 
2241891434b1SRayagond Kokatanur 			stmmac_get_rx_hwtstamp(priv, entry, skb);
2242891434b1SRayagond Kokatanur 
22437ac6653aSJeff Kirsher 			skb_put(skb, frame_len);
22447ac6653aSJeff Kirsher 			dma_unmap_single(priv->device,
22457ac6653aSJeff Kirsher 					 priv->rx_skbuff_dma[entry],
22467ac6653aSJeff Kirsher 					 priv->dma_buf_sz, DMA_FROM_DEVICE);
224783d7af64SGiuseppe CAVALLARO 
22487ac6653aSJeff Kirsher 			if (netif_msg_pktdata(priv)) {
224983d7af64SGiuseppe CAVALLARO 				pr_debug("frame received (%dbytes)", frame_len);
22507ac6653aSJeff Kirsher 				print_pkt(skb->data, frame_len);
22517ac6653aSJeff Kirsher 			}
225283d7af64SGiuseppe CAVALLARO 
2253b9381985SVince Bridgers 			stmmac_rx_vlan(priv->dev, skb);
2254b9381985SVince Bridgers 
22557ac6653aSJeff Kirsher 			skb->protocol = eth_type_trans(skb, priv->dev);
22567ac6653aSJeff Kirsher 
2257ceb69499SGiuseppe CAVALLARO 			if (unlikely(!coe))
22587ac6653aSJeff Kirsher 				skb_checksum_none_assert(skb);
225962a2ab93SGiuseppe CAVALLARO 			else
22607ac6653aSJeff Kirsher 				skb->ip_summed = CHECKSUM_UNNECESSARY;
226162a2ab93SGiuseppe CAVALLARO 
22627ac6653aSJeff Kirsher 			napi_gro_receive(&priv->napi, skb);
22637ac6653aSJeff Kirsher 
22647ac6653aSJeff Kirsher 			priv->dev->stats.rx_packets++;
22657ac6653aSJeff Kirsher 			priv->dev->stats.rx_bytes += frame_len;
22667ac6653aSJeff Kirsher 		}
22677ac6653aSJeff Kirsher 		entry = next_entry;
22687ac6653aSJeff Kirsher 	}
22697ac6653aSJeff Kirsher 
22707ac6653aSJeff Kirsher 	stmmac_rx_refill(priv);
22717ac6653aSJeff Kirsher 
22727ac6653aSJeff Kirsher 	priv->xstats.rx_pkt_n += count;
22737ac6653aSJeff Kirsher 
22747ac6653aSJeff Kirsher 	return count;
22757ac6653aSJeff Kirsher }
22767ac6653aSJeff Kirsher 
22777ac6653aSJeff Kirsher /**
22787ac6653aSJeff Kirsher  *  stmmac_poll - stmmac poll method (NAPI)
22797ac6653aSJeff Kirsher  *  @napi : pointer to the napi structure.
22807ac6653aSJeff Kirsher  *  @budget : maximum number of packets that the current CPU can receive from
22817ac6653aSJeff Kirsher  *	      all interfaces.
22827ac6653aSJeff Kirsher  *  Description :
22839125cdd1SGiuseppe CAVALLARO  *  To look at the incoming frames and clear the tx resources.
22847ac6653aSJeff Kirsher  */
22857ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget)
22867ac6653aSJeff Kirsher {
22877ac6653aSJeff Kirsher 	struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
22887ac6653aSJeff Kirsher 	int work_done = 0;
22897ac6653aSJeff Kirsher 
22909125cdd1SGiuseppe CAVALLARO 	priv->xstats.napi_poll++;
22919125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
22927ac6653aSJeff Kirsher 
22939125cdd1SGiuseppe CAVALLARO 	work_done = stmmac_rx(priv, budget);
22947ac6653aSJeff Kirsher 	if (work_done < budget) {
22957ac6653aSJeff Kirsher 		napi_complete(napi);
22969125cdd1SGiuseppe CAVALLARO 		stmmac_enable_dma_irq(priv);
22977ac6653aSJeff Kirsher 	}
22987ac6653aSJeff Kirsher 	return work_done;
22997ac6653aSJeff Kirsher }
23007ac6653aSJeff Kirsher 
23017ac6653aSJeff Kirsher /**
23027ac6653aSJeff Kirsher  *  stmmac_tx_timeout
23037ac6653aSJeff Kirsher  *  @dev : Pointer to net device structure
23047ac6653aSJeff Kirsher  *  Description: this function is called when a packet transmission fails to
23057284a3f1SGiuseppe CAVALLARO  *   complete within a reasonable time. The driver will mark the error in the
23067ac6653aSJeff Kirsher  *   netdev structure and arrange for the device to be reset to a sane state
23077ac6653aSJeff Kirsher  *   in order to transmit a new packet.
23087ac6653aSJeff Kirsher  */
23097ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev)
23107ac6653aSJeff Kirsher {
23117ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23127ac6653aSJeff Kirsher 
23137ac6653aSJeff Kirsher 	/* Clear Tx resources and restart transmitting again */
23147ac6653aSJeff Kirsher 	stmmac_tx_err(priv);
23157ac6653aSJeff Kirsher }
23167ac6653aSJeff Kirsher 
23177ac6653aSJeff Kirsher /**
231801789349SJiri Pirko  *  stmmac_set_rx_mode - entry point for multicast addressing
23197ac6653aSJeff Kirsher  *  @dev : pointer to the device structure
23207ac6653aSJeff Kirsher  *  Description:
23217ac6653aSJeff Kirsher  *  This function is a driver entry point which gets called by the kernel
23227ac6653aSJeff Kirsher  *  whenever multicast addresses must be enabled/disabled.
23237ac6653aSJeff Kirsher  *  Return value:
23247ac6653aSJeff Kirsher  *  void.
23257ac6653aSJeff Kirsher  */
232601789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev)
23277ac6653aSJeff Kirsher {
23287ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23297ac6653aSJeff Kirsher 
23303b57de95SVince Bridgers 	priv->hw->mac->set_filter(priv->hw, dev);
23317ac6653aSJeff Kirsher }
23327ac6653aSJeff Kirsher 
23337ac6653aSJeff Kirsher /**
23347ac6653aSJeff Kirsher  *  stmmac_change_mtu - entry point to change MTU size for the device.
23357ac6653aSJeff Kirsher  *  @dev : device pointer.
23367ac6653aSJeff Kirsher  *  @new_mtu : the new MTU size for the device.
23377ac6653aSJeff Kirsher  *  Description: the Maximum Transfer Unit (MTU) is used by the network layer
23387ac6653aSJeff Kirsher  *  to drive packet transmission. Ethernet has an MTU of 1500 octets
23397ac6653aSJeff Kirsher  *  (ETH_DATA_LEN). This value can be changed with ifconfig.
23407ac6653aSJeff Kirsher  *  Return value:
23417ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
23427ac6653aSJeff Kirsher  *  file on failure.
23437ac6653aSJeff Kirsher  */
23447ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
23457ac6653aSJeff Kirsher {
23467ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23477ac6653aSJeff Kirsher 	int max_mtu;
23487ac6653aSJeff Kirsher 
23497ac6653aSJeff Kirsher 	if (netif_running(dev)) {
23507ac6653aSJeff Kirsher 		pr_err("%s: must be stopped to change its MTU\n", dev->name);
23517ac6653aSJeff Kirsher 		return -EBUSY;
23527ac6653aSJeff Kirsher 	}
23537ac6653aSJeff Kirsher 
235448febf7eSGiuseppe CAVALLARO 	if (priv->plat->enh_desc)
23557ac6653aSJeff Kirsher 		max_mtu = JUMBO_LEN;
23567ac6653aSJeff Kirsher 	else
235745db81e1SGiuseppe CAVALLARO 		max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
23587ac6653aSJeff Kirsher 
23592618abb7SVince Bridgers 	if (priv->plat->maxmtu < max_mtu)
23602618abb7SVince Bridgers 		max_mtu = priv->plat->maxmtu;
23612618abb7SVince Bridgers 
23627ac6653aSJeff Kirsher 	if ((new_mtu < 46) || (new_mtu > max_mtu)) {
23637ac6653aSJeff Kirsher 		pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
23647ac6653aSJeff Kirsher 		return -EINVAL;
23657ac6653aSJeff Kirsher 	}
23667ac6653aSJeff Kirsher 
23677ac6653aSJeff Kirsher 	dev->mtu = new_mtu;
23687ac6653aSJeff Kirsher 	netdev_update_features(dev);
23697ac6653aSJeff Kirsher 
23707ac6653aSJeff Kirsher 	return 0;
23717ac6653aSJeff Kirsher }
23727ac6653aSJeff Kirsher 
2373c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev,
2374c8f44affSMichał Mirosław 					     netdev_features_t features)
23757ac6653aSJeff Kirsher {
23767ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23777ac6653aSJeff Kirsher 
237838912bdbSDeepak SIKRI 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
23797ac6653aSJeff Kirsher 		features &= ~NETIF_F_RXCSUM;
2380d2afb5bdSGiuseppe CAVALLARO 
23817ac6653aSJeff Kirsher 	if (!priv->plat->tx_coe)
23827ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
23837ac6653aSJeff Kirsher 
23847ac6653aSJeff Kirsher 	/* Some GMAC devices have a bugged Jumbo frame support that
23857ac6653aSJeff Kirsher 	 * needs to have the Tx COE disabled for oversized frames
23867ac6653aSJeff Kirsher 	 * (due to limited buffer sizes). In this case we disable
2387ceb69499SGiuseppe CAVALLARO 	 * the TX csum insertionin the TDES and not use SF.
2388ceb69499SGiuseppe CAVALLARO 	 */
23897ac6653aSJeff Kirsher 	if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
23907ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
23917ac6653aSJeff Kirsher 
23927ac6653aSJeff Kirsher 	return features;
23937ac6653aSJeff Kirsher }
23947ac6653aSJeff Kirsher 
2395d2afb5bdSGiuseppe CAVALLARO static int stmmac_set_features(struct net_device *netdev,
2396d2afb5bdSGiuseppe CAVALLARO 			       netdev_features_t features)
2397d2afb5bdSGiuseppe CAVALLARO {
2398d2afb5bdSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(netdev);
2399d2afb5bdSGiuseppe CAVALLARO 
2400d2afb5bdSGiuseppe CAVALLARO 	/* Keep the COE Type in case of csum is supporting */
2401d2afb5bdSGiuseppe CAVALLARO 	if (features & NETIF_F_RXCSUM)
2402d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
2403d2afb5bdSGiuseppe CAVALLARO 	else
2404d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
2405d2afb5bdSGiuseppe CAVALLARO 	/* No check needed because rx_coe has been set before and it will be
2406d2afb5bdSGiuseppe CAVALLARO 	 * fixed in case of issue.
2407d2afb5bdSGiuseppe CAVALLARO 	 */
2408d2afb5bdSGiuseppe CAVALLARO 	priv->hw->mac->rx_ipc(priv->hw);
2409d2afb5bdSGiuseppe CAVALLARO 
2410d2afb5bdSGiuseppe CAVALLARO 	return 0;
2411d2afb5bdSGiuseppe CAVALLARO }
2412d2afb5bdSGiuseppe CAVALLARO 
241332ceabcaSGiuseppe CAVALLARO /**
241432ceabcaSGiuseppe CAVALLARO  *  stmmac_interrupt - main ISR
241532ceabcaSGiuseppe CAVALLARO  *  @irq: interrupt number.
241632ceabcaSGiuseppe CAVALLARO  *  @dev_id: to pass the net device pointer.
241732ceabcaSGiuseppe CAVALLARO  *  Description: this is the main driver interrupt service routine.
2418732fdf0eSGiuseppe CAVALLARO  *  It can call:
2419732fdf0eSGiuseppe CAVALLARO  *  o DMA service routine (to manage incoming frame reception and transmission
2420732fdf0eSGiuseppe CAVALLARO  *    status)
2421732fdf0eSGiuseppe CAVALLARO  *  o Core interrupts to manage: remote wake-up, management counter, LPI
242232ceabcaSGiuseppe CAVALLARO  *    interrupts.
242332ceabcaSGiuseppe CAVALLARO  */
24247ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
24257ac6653aSJeff Kirsher {
24267ac6653aSJeff Kirsher 	struct net_device *dev = (struct net_device *)dev_id;
24277ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
24287ac6653aSJeff Kirsher 
242989f7f2cfSSrinivas Kandagatla 	if (priv->irq_wake)
243089f7f2cfSSrinivas Kandagatla 		pm_wakeup_event(priv->device, 0);
243189f7f2cfSSrinivas Kandagatla 
24327ac6653aSJeff Kirsher 	if (unlikely(!dev)) {
24337ac6653aSJeff Kirsher 		pr_err("%s: invalid dev pointer\n", __func__);
24347ac6653aSJeff Kirsher 		return IRQ_NONE;
24357ac6653aSJeff Kirsher 	}
24367ac6653aSJeff Kirsher 
24377ac6653aSJeff Kirsher 	/* To handle GMAC own interrupts */
2438d765955dSGiuseppe CAVALLARO 	if (priv->plat->has_gmac) {
24397ed24bbeSVince Bridgers 		int status = priv->hw->mac->host_irq_status(priv->hw,
24400982a0f6SGiuseppe CAVALLARO 							    &priv->xstats);
2441d765955dSGiuseppe CAVALLARO 		if (unlikely(status)) {
2442d765955dSGiuseppe CAVALLARO 			/* For LPI we need to save the tx status */
24430982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
2444d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = true;
24450982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
2446d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = false;
2447d765955dSGiuseppe CAVALLARO 		}
2448d765955dSGiuseppe CAVALLARO 	}
2449d765955dSGiuseppe CAVALLARO 
2450d765955dSGiuseppe CAVALLARO 	/* To handle DMA interrupts */
24517ac6653aSJeff Kirsher 	stmmac_dma_interrupt(priv);
24527ac6653aSJeff Kirsher 
24537ac6653aSJeff Kirsher 	return IRQ_HANDLED;
24547ac6653aSJeff Kirsher }
24557ac6653aSJeff Kirsher 
24567ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
24577ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools
2458ceb69499SGiuseppe CAVALLARO  * to allow network I/O with interrupts disabled.
2459ceb69499SGiuseppe CAVALLARO  */
24607ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev)
24617ac6653aSJeff Kirsher {
24627ac6653aSJeff Kirsher 	disable_irq(dev->irq);
24637ac6653aSJeff Kirsher 	stmmac_interrupt(dev->irq, dev);
24647ac6653aSJeff Kirsher 	enable_irq(dev->irq);
24657ac6653aSJeff Kirsher }
24667ac6653aSJeff Kirsher #endif
24677ac6653aSJeff Kirsher 
24687ac6653aSJeff Kirsher /**
24697ac6653aSJeff Kirsher  *  stmmac_ioctl - Entry point for the Ioctl
24707ac6653aSJeff Kirsher  *  @dev: Device pointer.
24717ac6653aSJeff Kirsher  *  @rq: An IOCTL specefic structure, that can contain a pointer to
24727ac6653aSJeff Kirsher  *  a proprietary structure used to pass information to the driver.
24737ac6653aSJeff Kirsher  *  @cmd: IOCTL command
24747ac6653aSJeff Kirsher  *  Description:
247532ceabcaSGiuseppe CAVALLARO  *  Currently it supports the phy_mii_ioctl(...) and HW time stamping.
24767ac6653aSJeff Kirsher  */
24777ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
24787ac6653aSJeff Kirsher {
24797ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
2480891434b1SRayagond Kokatanur 	int ret = -EOPNOTSUPP;
24817ac6653aSJeff Kirsher 
24827ac6653aSJeff Kirsher 	if (!netif_running(dev))
24837ac6653aSJeff Kirsher 		return -EINVAL;
24847ac6653aSJeff Kirsher 
2485891434b1SRayagond Kokatanur 	switch (cmd) {
2486891434b1SRayagond Kokatanur 	case SIOCGMIIPHY:
2487891434b1SRayagond Kokatanur 	case SIOCGMIIREG:
2488891434b1SRayagond Kokatanur 	case SIOCSMIIREG:
24897ac6653aSJeff Kirsher 		if (!priv->phydev)
24907ac6653aSJeff Kirsher 			return -EINVAL;
24917ac6653aSJeff Kirsher 		ret = phy_mii_ioctl(priv->phydev, rq, cmd);
2492891434b1SRayagond Kokatanur 		break;
2493891434b1SRayagond Kokatanur 	case SIOCSHWTSTAMP:
2494891434b1SRayagond Kokatanur 		ret = stmmac_hwtstamp_ioctl(dev, rq);
2495891434b1SRayagond Kokatanur 		break;
2496891434b1SRayagond Kokatanur 	default:
2497891434b1SRayagond Kokatanur 		break;
2498891434b1SRayagond Kokatanur 	}
24997ac6653aSJeff Kirsher 
25007ac6653aSJeff Kirsher 	return ret;
25017ac6653aSJeff Kirsher }
25027ac6653aSJeff Kirsher 
250350fb4f74SGiuseppe CAVALLARO #ifdef CONFIG_DEBUG_FS
25047ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir;
25057ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_rings_status;
2506e7434821SGiuseppe CAVALLARO static struct dentry *stmmac_dma_cap;
25077ac29055SGiuseppe CAVALLARO 
2508c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc,
2509c24602efSGiuseppe CAVALLARO 			       struct seq_file *seq)
25107ac29055SGiuseppe CAVALLARO {
25117ac29055SGiuseppe CAVALLARO 	int i;
2512c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
2513c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
25147ac29055SGiuseppe CAVALLARO 
2515c24602efSGiuseppe CAVALLARO 	for (i = 0; i < size; i++) {
2516c24602efSGiuseppe CAVALLARO 		u64 x;
2517c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
2518c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
2519c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2520c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2521c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2522c24602efSGiuseppe CAVALLARO 				   ep->basic.des2, ep->basic.des3);
2523c24602efSGiuseppe CAVALLARO 			ep++;
2524c24602efSGiuseppe CAVALLARO 		} else {
2525c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
2526c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2527c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2528c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2529c24602efSGiuseppe CAVALLARO 				   p->des2, p->des3);
2530c24602efSGiuseppe CAVALLARO 			p++;
2531c24602efSGiuseppe CAVALLARO 		}
25327ac29055SGiuseppe CAVALLARO 		seq_printf(seq, "\n");
25337ac29055SGiuseppe CAVALLARO 	}
2534c24602efSGiuseppe CAVALLARO }
25357ac29055SGiuseppe CAVALLARO 
2536c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
2537c24602efSGiuseppe CAVALLARO {
2538c24602efSGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2539c24602efSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2540c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
2541c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
25427ac29055SGiuseppe CAVALLARO 
2543c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
2544c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended RX descriptor ring:\n");
2545c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_erx, rxsize, 1, seq);
2546c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended TX descriptor ring:\n");
2547c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_etx, txsize, 1, seq);
2548c24602efSGiuseppe CAVALLARO 	} else {
2549c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "RX descriptor ring:\n");
2550c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_rx, rxsize, 0, seq);
2551c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "TX descriptor ring:\n");
2552c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_tx, txsize, 0, seq);
25537ac29055SGiuseppe CAVALLARO 	}
25547ac29055SGiuseppe CAVALLARO 
25557ac29055SGiuseppe CAVALLARO 	return 0;
25567ac29055SGiuseppe CAVALLARO }
25577ac29055SGiuseppe CAVALLARO 
25587ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
25597ac29055SGiuseppe CAVALLARO {
25607ac29055SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
25617ac29055SGiuseppe CAVALLARO }
25627ac29055SGiuseppe CAVALLARO 
25637ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = {
25647ac29055SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
25657ac29055SGiuseppe CAVALLARO 	.open = stmmac_sysfs_ring_open,
25667ac29055SGiuseppe CAVALLARO 	.read = seq_read,
25677ac29055SGiuseppe CAVALLARO 	.llseek = seq_lseek,
256874863948SDjalal Harouni 	.release = single_release,
25697ac29055SGiuseppe CAVALLARO };
25707ac29055SGiuseppe CAVALLARO 
2571e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
2572e7434821SGiuseppe CAVALLARO {
2573e7434821SGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2574e7434821SGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2575e7434821SGiuseppe CAVALLARO 
257619e30c14SGiuseppe CAVALLARO 	if (!priv->hw_cap_support) {
2577e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "DMA HW features not supported\n");
2578e7434821SGiuseppe CAVALLARO 		return 0;
2579e7434821SGiuseppe CAVALLARO 	}
2580e7434821SGiuseppe CAVALLARO 
2581e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2582e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tDMA HW features\n");
2583e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2584e7434821SGiuseppe CAVALLARO 
2585e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t10/100 Mbps %s\n",
2586e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_10_100) ? "Y" : "N");
2587e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t1000 Mbps %s\n",
2588e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_1000) ? "Y" : "N");
2589e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHalf duple %s\n",
2590e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.half_duplex) ? "Y" : "N");
2591e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHash Filter: %s\n",
2592e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.hash_filter) ? "Y" : "N");
2593e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tMultiple MAC address registers: %s\n",
2594e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.multi_addr) ? "Y" : "N");
2595e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n",
2596e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pcs) ? "Y" : "N");
2597e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
2598e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.sma_mdio) ? "Y" : "N");
2599e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Remote wake up: %s\n",
2600e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
2601e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Magic Frame: %s\n",
2602e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
2603e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRMON module: %s\n",
2604e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rmon) ? "Y" : "N");
2605e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
2606e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.time_stamp) ? "Y" : "N");
2607e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n",
2608e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.atime_stamp) ? "Y" : "N");
2609e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n",
2610e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.eee) ? "Y" : "N");
2611e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
2612e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tChecksum Offload in TX: %s\n",
2613e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.tx_coe) ? "Y" : "N");
2614e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
2615e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
2616e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
2617e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
2618e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
2619e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
2620e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
2621e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_rx_channel);
2622e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
2623e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_tx_channel);
2624e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tEnhanced descriptors: %s\n",
2625e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.enh_desc) ? "Y" : "N");
2626e7434821SGiuseppe CAVALLARO 
2627e7434821SGiuseppe CAVALLARO 	return 0;
2628e7434821SGiuseppe CAVALLARO }
2629e7434821SGiuseppe CAVALLARO 
2630e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
2631e7434821SGiuseppe CAVALLARO {
2632e7434821SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
2633e7434821SGiuseppe CAVALLARO }
2634e7434821SGiuseppe CAVALLARO 
2635e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = {
2636e7434821SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
2637e7434821SGiuseppe CAVALLARO 	.open = stmmac_sysfs_dma_cap_open,
2638e7434821SGiuseppe CAVALLARO 	.read = seq_read,
2639e7434821SGiuseppe CAVALLARO 	.llseek = seq_lseek,
264074863948SDjalal Harouni 	.release = single_release,
2641e7434821SGiuseppe CAVALLARO };
2642e7434821SGiuseppe CAVALLARO 
26437ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev)
26447ac29055SGiuseppe CAVALLARO {
26457ac29055SGiuseppe CAVALLARO 	/* Create debugfs entries */
26467ac29055SGiuseppe CAVALLARO 	stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
26477ac29055SGiuseppe CAVALLARO 
26487ac29055SGiuseppe CAVALLARO 	if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
26497ac29055SGiuseppe CAVALLARO 		pr_err("ERROR %s, debugfs create directory failed\n",
26507ac29055SGiuseppe CAVALLARO 		       STMMAC_RESOURCE_NAME);
26517ac29055SGiuseppe CAVALLARO 
26527ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
26537ac29055SGiuseppe CAVALLARO 	}
26547ac29055SGiuseppe CAVALLARO 
26557ac29055SGiuseppe CAVALLARO 	/* Entry to report DMA RX/TX rings */
26567ac29055SGiuseppe CAVALLARO 	stmmac_rings_status = debugfs_create_file("descriptors_status",
26577ac29055SGiuseppe CAVALLARO 						  S_IRUGO, stmmac_fs_dir, dev,
26587ac29055SGiuseppe CAVALLARO 						  &stmmac_rings_status_fops);
26597ac29055SGiuseppe CAVALLARO 
26607ac29055SGiuseppe CAVALLARO 	if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
26617ac29055SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac ring debugfs file\n");
26627ac29055SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
26637ac29055SGiuseppe CAVALLARO 
26647ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
26657ac29055SGiuseppe CAVALLARO 	}
26667ac29055SGiuseppe CAVALLARO 
2667e7434821SGiuseppe CAVALLARO 	/* Entry to report the DMA HW features */
2668e7434821SGiuseppe CAVALLARO 	stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
2669e7434821SGiuseppe CAVALLARO 					     dev, &stmmac_dma_cap_fops);
2670e7434821SGiuseppe CAVALLARO 
2671e7434821SGiuseppe CAVALLARO 	if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
2672e7434821SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac MMC debugfs file\n");
2673e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_rings_status);
2674e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
2675e7434821SGiuseppe CAVALLARO 
2676e7434821SGiuseppe CAVALLARO 		return -ENOMEM;
2677e7434821SGiuseppe CAVALLARO 	}
2678e7434821SGiuseppe CAVALLARO 
26797ac29055SGiuseppe CAVALLARO 	return 0;
26807ac29055SGiuseppe CAVALLARO }
26817ac29055SGiuseppe CAVALLARO 
26827ac29055SGiuseppe CAVALLARO static void stmmac_exit_fs(void)
26837ac29055SGiuseppe CAVALLARO {
26847ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_rings_status);
2685e7434821SGiuseppe CAVALLARO 	debugfs_remove(stmmac_dma_cap);
26867ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_fs_dir);
26877ac29055SGiuseppe CAVALLARO }
268850fb4f74SGiuseppe CAVALLARO #endif /* CONFIG_DEBUG_FS */
26897ac29055SGiuseppe CAVALLARO 
26907ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = {
26917ac6653aSJeff Kirsher 	.ndo_open = stmmac_open,
26927ac6653aSJeff Kirsher 	.ndo_start_xmit = stmmac_xmit,
26937ac6653aSJeff Kirsher 	.ndo_stop = stmmac_release,
26947ac6653aSJeff Kirsher 	.ndo_change_mtu = stmmac_change_mtu,
26957ac6653aSJeff Kirsher 	.ndo_fix_features = stmmac_fix_features,
2696d2afb5bdSGiuseppe CAVALLARO 	.ndo_set_features = stmmac_set_features,
269701789349SJiri Pirko 	.ndo_set_rx_mode = stmmac_set_rx_mode,
26987ac6653aSJeff Kirsher 	.ndo_tx_timeout = stmmac_tx_timeout,
26997ac6653aSJeff Kirsher 	.ndo_do_ioctl = stmmac_ioctl,
27007ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
27017ac6653aSJeff Kirsher 	.ndo_poll_controller = stmmac_poll_controller,
27027ac6653aSJeff Kirsher #endif
27037ac6653aSJeff Kirsher 	.ndo_set_mac_address = eth_mac_addr,
27047ac6653aSJeff Kirsher };
27057ac6653aSJeff Kirsher 
27067ac6653aSJeff Kirsher /**
2707cf3f047bSGiuseppe CAVALLARO  *  stmmac_hw_init - Init the MAC device
270832ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
2709732fdf0eSGiuseppe CAVALLARO  *  Description: this function is to configure the MAC device according to
2710732fdf0eSGiuseppe CAVALLARO  *  some platform parameters or the HW capability register. It prepares the
2711732fdf0eSGiuseppe CAVALLARO  *  driver to use either ring or chain modes and to setup either enhanced or
2712732fdf0eSGiuseppe CAVALLARO  *  normal descriptors.
2713cf3f047bSGiuseppe CAVALLARO  */
2714cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv)
2715cf3f047bSGiuseppe CAVALLARO {
2716cf3f047bSGiuseppe CAVALLARO 	struct mac_device_info *mac;
2717cf3f047bSGiuseppe CAVALLARO 
2718cf3f047bSGiuseppe CAVALLARO 	/* Identify the MAC HW device */
271903f2eecdSMarc Kleine-Budde 	if (priv->plat->has_gmac) {
272003f2eecdSMarc Kleine-Budde 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
27213b57de95SVince Bridgers 		mac = dwmac1000_setup(priv->ioaddr,
27223b57de95SVince Bridgers 				      priv->plat->multicast_filter_bins,
27233b57de95SVince Bridgers 				      priv->plat->unicast_filter_entries);
272403f2eecdSMarc Kleine-Budde 	} else {
2725cf3f047bSGiuseppe CAVALLARO 		mac = dwmac100_setup(priv->ioaddr);
272603f2eecdSMarc Kleine-Budde 	}
2727cf3f047bSGiuseppe CAVALLARO 	if (!mac)
2728cf3f047bSGiuseppe CAVALLARO 		return -ENOMEM;
2729cf3f047bSGiuseppe CAVALLARO 
2730cf3f047bSGiuseppe CAVALLARO 	priv->hw = mac;
2731cf3f047bSGiuseppe CAVALLARO 
2732cf3f047bSGiuseppe CAVALLARO 	/* Get and dump the chip ID */
2733cffb13f4SGiuseppe CAVALLARO 	priv->synopsys_id = stmmac_get_synopsys_id(priv);
2734cf3f047bSGiuseppe CAVALLARO 
27354a7d666aSGiuseppe CAVALLARO 	/* To use the chained or ring mode */
27364a7d666aSGiuseppe CAVALLARO 	if (chain_mode) {
273729896a67SGiuseppe CAVALLARO 		priv->hw->mode = &chain_mode_ops;
27384a7d666aSGiuseppe CAVALLARO 		pr_info(" Chain mode enabled\n");
27394a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_CHAIN_MODE;
27404a7d666aSGiuseppe CAVALLARO 	} else {
274129896a67SGiuseppe CAVALLARO 		priv->hw->mode = &ring_mode_ops;
27424a7d666aSGiuseppe CAVALLARO 		pr_info(" Ring mode enabled\n");
27434a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_RING_MODE;
27444a7d666aSGiuseppe CAVALLARO 	}
27454a7d666aSGiuseppe CAVALLARO 
2746cf3f047bSGiuseppe CAVALLARO 	/* Get the HW capability (new GMAC newer than 3.50a) */
2747cf3f047bSGiuseppe CAVALLARO 	priv->hw_cap_support = stmmac_get_hw_features(priv);
2748cf3f047bSGiuseppe CAVALLARO 	if (priv->hw_cap_support) {
2749cf3f047bSGiuseppe CAVALLARO 		pr_info(" DMA HW capability register supported");
2750cf3f047bSGiuseppe CAVALLARO 
2751cf3f047bSGiuseppe CAVALLARO 		/* We can override some gmac/dma configuration fields: e.g.
2752cf3f047bSGiuseppe CAVALLARO 		 * enh_desc, tx_coe (e.g. that are passed through the
2753cf3f047bSGiuseppe CAVALLARO 		 * platform) with the values from the HW capability
2754cf3f047bSGiuseppe CAVALLARO 		 * register (if supported).
2755cf3f047bSGiuseppe CAVALLARO 		 */
2756cf3f047bSGiuseppe CAVALLARO 		priv->plat->enh_desc = priv->dma_cap.enh_desc;
2757cf3f047bSGiuseppe CAVALLARO 		priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
275838912bdbSDeepak SIKRI 
2759dec2165fSSonic Zhang 		/* TXCOE doesn't work in thresh DMA mode */
2760dec2165fSSonic Zhang 		if (priv->plat->force_thresh_dma_mode)
2761dec2165fSSonic Zhang 			priv->plat->tx_coe = 0;
2762dec2165fSSonic Zhang 		else
276338912bdbSDeepak SIKRI 			priv->plat->tx_coe = priv->dma_cap.tx_coe;
276438912bdbSDeepak SIKRI 
276538912bdbSDeepak SIKRI 		if (priv->dma_cap.rx_coe_type2)
276638912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
276738912bdbSDeepak SIKRI 		else if (priv->dma_cap.rx_coe_type1)
276838912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
276938912bdbSDeepak SIKRI 
2770cf3f047bSGiuseppe CAVALLARO 	} else
2771cf3f047bSGiuseppe CAVALLARO 		pr_info(" No HW DMA feature register supported");
2772cf3f047bSGiuseppe CAVALLARO 
277361369d02SByungho An 	/* To use alternate (extended) or normal descriptor structures */
277461369d02SByungho An 	stmmac_selec_desc_mode(priv);
277561369d02SByungho An 
2776d2afb5bdSGiuseppe CAVALLARO 	if (priv->plat->rx_coe) {
2777d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
277838912bdbSDeepak SIKRI 		pr_info(" RX Checksum Offload Engine supported (type %d)\n",
277938912bdbSDeepak SIKRI 			priv->plat->rx_coe);
2780d2afb5bdSGiuseppe CAVALLARO 	}
2781cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->tx_coe)
2782cf3f047bSGiuseppe CAVALLARO 		pr_info(" TX Checksum insertion supported\n");
2783cf3f047bSGiuseppe CAVALLARO 
2784cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->pmt) {
2785cf3f047bSGiuseppe CAVALLARO 		pr_info(" Wake-Up On Lan supported\n");
2786cf3f047bSGiuseppe CAVALLARO 		device_set_wakeup_capable(priv->device, 1);
2787cf3f047bSGiuseppe CAVALLARO 	}
2788cf3f047bSGiuseppe CAVALLARO 
2789c24602efSGiuseppe CAVALLARO 	return 0;
2790cf3f047bSGiuseppe CAVALLARO }
2791cf3f047bSGiuseppe CAVALLARO 
2792cf3f047bSGiuseppe CAVALLARO /**
2793bfab27a1SGiuseppe CAVALLARO  * stmmac_dvr_probe
2794bfab27a1SGiuseppe CAVALLARO  * @device: device pointer
2795ff3dd78cSGiuseppe CAVALLARO  * @plat_dat: platform data pointer
2796ff3dd78cSGiuseppe CAVALLARO  * @addr: iobase memory address
2797bfab27a1SGiuseppe CAVALLARO  * Description: this is the main probe function used to
2798bfab27a1SGiuseppe CAVALLARO  * call the alloc_etherdev, allocate the priv structure.
27999afec6efSAndy Shevchenko  * Return:
28009afec6efSAndy Shevchenko  * on success the new private structure is returned, otherwise the error
28019afec6efSAndy Shevchenko  * pointer.
28027ac6653aSJeff Kirsher  */
2803bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *stmmac_dvr_probe(struct device *device,
2804cf3f047bSGiuseppe CAVALLARO 				     struct plat_stmmacenet_data *plat_dat,
2805cf3f047bSGiuseppe CAVALLARO 				     void __iomem *addr)
28067ac6653aSJeff Kirsher {
28077ac6653aSJeff Kirsher 	int ret = 0;
2808bfab27a1SGiuseppe CAVALLARO 	struct net_device *ndev = NULL;
2809bfab27a1SGiuseppe CAVALLARO 	struct stmmac_priv *priv;
28107ac6653aSJeff Kirsher 
2811bfab27a1SGiuseppe CAVALLARO 	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
281241de8d4cSJoe Perches 	if (!ndev)
28139afec6efSAndy Shevchenko 		return ERR_PTR(-ENOMEM);
28147ac6653aSJeff Kirsher 
2815bfab27a1SGiuseppe CAVALLARO 	SET_NETDEV_DEV(ndev, device);
28167ac6653aSJeff Kirsher 
2817bfab27a1SGiuseppe CAVALLARO 	priv = netdev_priv(ndev);
2818bfab27a1SGiuseppe CAVALLARO 	priv->device = device;
2819bfab27a1SGiuseppe CAVALLARO 	priv->dev = ndev;
2820bfab27a1SGiuseppe CAVALLARO 
2821bfab27a1SGiuseppe CAVALLARO 	stmmac_set_ethtool_ops(ndev);
2822cf3f047bSGiuseppe CAVALLARO 	priv->pause = pause;
2823cf3f047bSGiuseppe CAVALLARO 	priv->plat = plat_dat;
2824cf3f047bSGiuseppe CAVALLARO 	priv->ioaddr = addr;
2825cf3f047bSGiuseppe CAVALLARO 	priv->dev->base_addr = (unsigned long)addr;
2826bfab27a1SGiuseppe CAVALLARO 
2827cf3f047bSGiuseppe CAVALLARO 	/* Verify driver arguments */
2828cf3f047bSGiuseppe CAVALLARO 	stmmac_verify_args();
2829cf3f047bSGiuseppe CAVALLARO 
2830cf3f047bSGiuseppe CAVALLARO 	/* Override with kernel parameters if supplied XXX CRS XXX
2831ceb69499SGiuseppe CAVALLARO 	 * this needs to have multiple instances
2832ceb69499SGiuseppe CAVALLARO 	 */
2833cf3f047bSGiuseppe CAVALLARO 	if ((phyaddr >= 0) && (phyaddr <= 31))
2834cf3f047bSGiuseppe CAVALLARO 		priv->plat->phy_addr = phyaddr;
2835cf3f047bSGiuseppe CAVALLARO 
283662866e98SChen-Yu Tsai 	priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
283762866e98SChen-Yu Tsai 	if (IS_ERR(priv->stmmac_clk)) {
283862866e98SChen-Yu Tsai 		dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
283962866e98SChen-Yu Tsai 			 __func__);
2840c5bb86c3SKweh, Hock Leong 		/* If failed to obtain stmmac_clk and specific clk_csr value
2841c5bb86c3SKweh, Hock Leong 		 * is NOT passed from the platform, probe fail.
2842c5bb86c3SKweh, Hock Leong 		 */
2843c5bb86c3SKweh, Hock Leong 		if (!priv->plat->clk_csr) {
2844c5e4ddbdSChen-Yu Tsai 			ret = PTR_ERR(priv->stmmac_clk);
284562866e98SChen-Yu Tsai 			goto error_clk_get;
2846c5bb86c3SKweh, Hock Leong 		} else {
2847c5bb86c3SKweh, Hock Leong 			priv->stmmac_clk = NULL;
2848c5bb86c3SKweh, Hock Leong 		}
284962866e98SChen-Yu Tsai 	}
285062866e98SChen-Yu Tsai 	clk_prepare_enable(priv->stmmac_clk);
285162866e98SChen-Yu Tsai 
28525f9755d2SAndrew Bresticker 	priv->pclk = devm_clk_get(priv->device, "pclk");
28535f9755d2SAndrew Bresticker 	if (IS_ERR(priv->pclk)) {
28545f9755d2SAndrew Bresticker 		if (PTR_ERR(priv->pclk) == -EPROBE_DEFER) {
28555f9755d2SAndrew Bresticker 			ret = -EPROBE_DEFER;
28565f9755d2SAndrew Bresticker 			goto error_pclk_get;
28575f9755d2SAndrew Bresticker 		}
28585f9755d2SAndrew Bresticker 		priv->pclk = NULL;
28595f9755d2SAndrew Bresticker 	}
28605f9755d2SAndrew Bresticker 	clk_prepare_enable(priv->pclk);
28615f9755d2SAndrew Bresticker 
2862c5e4ddbdSChen-Yu Tsai 	priv->stmmac_rst = devm_reset_control_get(priv->device,
2863c5e4ddbdSChen-Yu Tsai 						  STMMAC_RESOURCE_NAME);
2864c5e4ddbdSChen-Yu Tsai 	if (IS_ERR(priv->stmmac_rst)) {
2865c5e4ddbdSChen-Yu Tsai 		if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
2866c5e4ddbdSChen-Yu Tsai 			ret = -EPROBE_DEFER;
2867c5e4ddbdSChen-Yu Tsai 			goto error_hw_init;
2868c5e4ddbdSChen-Yu Tsai 		}
2869c5e4ddbdSChen-Yu Tsai 		dev_info(priv->device, "no reset control found\n");
2870c5e4ddbdSChen-Yu Tsai 		priv->stmmac_rst = NULL;
2871c5e4ddbdSChen-Yu Tsai 	}
2872c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2873c5e4ddbdSChen-Yu Tsai 		reset_control_deassert(priv->stmmac_rst);
2874c5e4ddbdSChen-Yu Tsai 
2875cf3f047bSGiuseppe CAVALLARO 	/* Init MAC and get the capabilities */
2876c24602efSGiuseppe CAVALLARO 	ret = stmmac_hw_init(priv);
2877c24602efSGiuseppe CAVALLARO 	if (ret)
287862866e98SChen-Yu Tsai 		goto error_hw_init;
2879cf3f047bSGiuseppe CAVALLARO 
2880cf3f047bSGiuseppe CAVALLARO 	ndev->netdev_ops = &stmmac_netdev_ops;
2881cf3f047bSGiuseppe CAVALLARO 
2882cf3f047bSGiuseppe CAVALLARO 	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
2883cf3f047bSGiuseppe CAVALLARO 			    NETIF_F_RXCSUM;
2884bfab27a1SGiuseppe CAVALLARO 	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
2885bfab27a1SGiuseppe CAVALLARO 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
28867ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED
28877ac6653aSJeff Kirsher 	/* Both mac100 and gmac support receive VLAN tag detection */
2888f646968fSPatrick McHardy 	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
28897ac6653aSJeff Kirsher #endif
28907ac6653aSJeff Kirsher 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
28917ac6653aSJeff Kirsher 
28927ac6653aSJeff Kirsher 	if (flow_ctrl)
28937ac6653aSJeff Kirsher 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
28947ac6653aSJeff Kirsher 
289562a2ab93SGiuseppe CAVALLARO 	/* Rx Watchdog is available in the COREs newer than the 3.40.
289662a2ab93SGiuseppe CAVALLARO 	 * In some case, for example on bugged HW this feature
289762a2ab93SGiuseppe CAVALLARO 	 * has to be disable and this can be done by passing the
289862a2ab93SGiuseppe CAVALLARO 	 * riwt_off field from the platform.
289962a2ab93SGiuseppe CAVALLARO 	 */
290062a2ab93SGiuseppe CAVALLARO 	if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
290162a2ab93SGiuseppe CAVALLARO 		priv->use_riwt = 1;
290262a2ab93SGiuseppe CAVALLARO 		pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
290362a2ab93SGiuseppe CAVALLARO 	}
290462a2ab93SGiuseppe CAVALLARO 
2905bfab27a1SGiuseppe CAVALLARO 	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
29067ac6653aSJeff Kirsher 
29077ac6653aSJeff Kirsher 	spin_lock_init(&priv->lock);
2908a9097a96SGiuseppe CAVALLARO 	spin_lock_init(&priv->tx_lock);
29097ac6653aSJeff Kirsher 
2910bfab27a1SGiuseppe CAVALLARO 	ret = register_netdev(ndev);
29117ac6653aSJeff Kirsher 	if (ret) {
2912cf3f047bSGiuseppe CAVALLARO 		pr_err("%s: ERROR %i registering the device\n", __func__, ret);
29136a81c26fSViresh Kumar 		goto error_netdev_register;
29147ac6653aSJeff Kirsher 	}
29157ac6653aSJeff Kirsher 
2916cd7201f4SGiuseppe CAVALLARO 	/* If a specific clk_csr value is passed from the platform
2917cd7201f4SGiuseppe CAVALLARO 	 * this means that the CSR Clock Range selection cannot be
2918cd7201f4SGiuseppe CAVALLARO 	 * changed at run-time and it is fixed. Viceversa the driver'll try to
2919cd7201f4SGiuseppe CAVALLARO 	 * set the MDC clock dynamically according to the csr actual
2920cd7201f4SGiuseppe CAVALLARO 	 * clock input.
2921cd7201f4SGiuseppe CAVALLARO 	 */
2922cd7201f4SGiuseppe CAVALLARO 	if (!priv->plat->clk_csr)
2923cd7201f4SGiuseppe CAVALLARO 		stmmac_clk_csr_set(priv);
2924cd7201f4SGiuseppe CAVALLARO 	else
2925cd7201f4SGiuseppe CAVALLARO 		priv->clk_csr = priv->plat->clk_csr;
2926cd7201f4SGiuseppe CAVALLARO 
2927e58bb43fSGiuseppe CAVALLARO 	stmmac_check_pcs_mode(priv);
2928e58bb43fSGiuseppe CAVALLARO 
29294d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
29304d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
29314bfcbd7aSFrancesco Virlinzi 		/* MDIO bus Registration */
29324bfcbd7aSFrancesco Virlinzi 		ret = stmmac_mdio_register(ndev);
29334bfcbd7aSFrancesco Virlinzi 		if (ret < 0) {
29344bfcbd7aSFrancesco Virlinzi 			pr_debug("%s: MDIO bus (id: %d) registration failed",
29354bfcbd7aSFrancesco Virlinzi 				 __func__, priv->plat->bus_id);
29366a81c26fSViresh Kumar 			goto error_mdio_register;
29374bfcbd7aSFrancesco Virlinzi 		}
2938e58bb43fSGiuseppe CAVALLARO 	}
29394bfcbd7aSFrancesco Virlinzi 
2940bfab27a1SGiuseppe CAVALLARO 	return priv;
29417ac6653aSJeff Kirsher 
29426a81c26fSViresh Kumar error_mdio_register:
29437ac6653aSJeff Kirsher 	unregister_netdev(ndev);
29446a81c26fSViresh Kumar error_netdev_register:
29456a81c26fSViresh Kumar 	netif_napi_del(&priv->napi);
294662866e98SChen-Yu Tsai error_hw_init:
29475f9755d2SAndrew Bresticker 	clk_disable_unprepare(priv->pclk);
29485f9755d2SAndrew Bresticker error_pclk_get:
294962866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
295062866e98SChen-Yu Tsai error_clk_get:
29517ac6653aSJeff Kirsher 	free_netdev(ndev);
29527ac6653aSJeff Kirsher 
2953c5e4ddbdSChen-Yu Tsai 	return ERR_PTR(ret);
29547ac6653aSJeff Kirsher }
2955b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_probe);
29567ac6653aSJeff Kirsher 
29577ac6653aSJeff Kirsher /**
29587ac6653aSJeff Kirsher  * stmmac_dvr_remove
2959bfab27a1SGiuseppe CAVALLARO  * @ndev: net device pointer
29607ac6653aSJeff Kirsher  * Description: this function resets the TX/RX processes, disables the MAC RX/TX
2961bfab27a1SGiuseppe CAVALLARO  * changes the link status, releases the DMA descriptor rings.
29627ac6653aSJeff Kirsher  */
2963bfab27a1SGiuseppe CAVALLARO int stmmac_dvr_remove(struct net_device *ndev)
29647ac6653aSJeff Kirsher {
29657ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
29667ac6653aSJeff Kirsher 
29677ac6653aSJeff Kirsher 	pr_info("%s:\n\tremoving driver", __func__);
29687ac6653aSJeff Kirsher 
29697ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
29707ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
29717ac6653aSJeff Kirsher 
2972bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
29734d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
29744d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI)
29754bfcbd7aSFrancesco Virlinzi 		stmmac_mdio_unregister(ndev);
29767ac6653aSJeff Kirsher 	netif_carrier_off(ndev);
29777ac6653aSJeff Kirsher 	unregister_netdev(ndev);
2978c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2979c5e4ddbdSChen-Yu Tsai 		reset_control_assert(priv->stmmac_rst);
29805f9755d2SAndrew Bresticker 	clk_disable_unprepare(priv->pclk);
298162866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
29827ac6653aSJeff Kirsher 	free_netdev(ndev);
29837ac6653aSJeff Kirsher 
29847ac6653aSJeff Kirsher 	return 0;
29857ac6653aSJeff Kirsher }
2986b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_dvr_remove);
29877ac6653aSJeff Kirsher 
2988732fdf0eSGiuseppe CAVALLARO /**
2989732fdf0eSGiuseppe CAVALLARO  * stmmac_suspend - suspend callback
2990732fdf0eSGiuseppe CAVALLARO  * @ndev: net device pointer
2991732fdf0eSGiuseppe CAVALLARO  * Description: this is the function to suspend the device and it is called
2992732fdf0eSGiuseppe CAVALLARO  * by the platform driver to stop the network queue, release the resources,
2993732fdf0eSGiuseppe CAVALLARO  * program the PMT register (for WoL), clean and release driver resources.
2994732fdf0eSGiuseppe CAVALLARO  */
2995bfab27a1SGiuseppe CAVALLARO int stmmac_suspend(struct net_device *ndev)
29967ac6653aSJeff Kirsher {
29977ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2998f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
29997ac6653aSJeff Kirsher 
30007ac6653aSJeff Kirsher 	if (!ndev || !netif_running(ndev))
30017ac6653aSJeff Kirsher 		return 0;
30027ac6653aSJeff Kirsher 
3003102463b1SFrancesco Virlinzi 	if (priv->phydev)
3004102463b1SFrancesco Virlinzi 		phy_stop(priv->phydev);
3005102463b1SFrancesco Virlinzi 
3006f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
30077ac6653aSJeff Kirsher 
30087ac6653aSJeff Kirsher 	netif_device_detach(ndev);
30097ac6653aSJeff Kirsher 	netif_stop_queue(ndev);
30107ac6653aSJeff Kirsher 
30117ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
30127ac6653aSJeff Kirsher 
30137ac6653aSJeff Kirsher 	/* Stop TX/RX DMA */
30147ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
30157ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
3016c24602efSGiuseppe CAVALLARO 
3017c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
30187ac6653aSJeff Kirsher 
30197ac6653aSJeff Kirsher 	/* Enable Power down mode by programming the PMT regs */
302089f7f2cfSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
30217ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, priv->wolopts);
302289f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 1;
302389f7f2cfSSrinivas Kandagatla 	} else {
3024bfab27a1SGiuseppe CAVALLARO 		stmmac_set_mac(priv->ioaddr, false);
3025db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_sleep_state(priv->device);
3026ba1377ffSGiuseppe CAVALLARO 		/* Disable clock in case of PWM is off */
30275f9755d2SAndrew Bresticker 		clk_disable(priv->pclk);
3028777da230SGiuseppe CAVALLARO 		clk_disable(priv->stmmac_clk);
3029ba1377ffSGiuseppe CAVALLARO 	}
3030f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
30312d871aa0SVince Bridgers 
30322d871aa0SVince Bridgers 	priv->oldlink = 0;
30332d871aa0SVince Bridgers 	priv->speed = 0;
30342d871aa0SVince Bridgers 	priv->oldduplex = -1;
30357ac6653aSJeff Kirsher 	return 0;
30367ac6653aSJeff Kirsher }
3037b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_suspend);
30387ac6653aSJeff Kirsher 
3039732fdf0eSGiuseppe CAVALLARO /**
3040732fdf0eSGiuseppe CAVALLARO  * stmmac_resume - resume callback
3041732fdf0eSGiuseppe CAVALLARO  * @ndev: net device pointer
3042732fdf0eSGiuseppe CAVALLARO  * Description: when resume this function is invoked to setup the DMA and CORE
3043732fdf0eSGiuseppe CAVALLARO  * in a usable state.
3044732fdf0eSGiuseppe CAVALLARO  */
3045bfab27a1SGiuseppe CAVALLARO int stmmac_resume(struct net_device *ndev)
30467ac6653aSJeff Kirsher {
30477ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
3048f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
30497ac6653aSJeff Kirsher 
30507ac6653aSJeff Kirsher 	if (!netif_running(ndev))
30517ac6653aSJeff Kirsher 		return 0;
30527ac6653aSJeff Kirsher 
3053f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
30547ac6653aSJeff Kirsher 
30557ac6653aSJeff Kirsher 	/* Power Down bit, into the PM register, is cleared
30567ac6653aSJeff Kirsher 	 * automatically as soon as a magic packet or a Wake-up frame
30577ac6653aSJeff Kirsher 	 * is received. Anyway, it's better to manually clear
30587ac6653aSJeff Kirsher 	 * this bit because it can generate problems while resuming
3059ceb69499SGiuseppe CAVALLARO 	 * from another devices (e.g. serial console).
3060ceb69499SGiuseppe CAVALLARO 	 */
3061623997fbSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
30627ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, 0);
306389f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 0;
3064623997fbSSrinivas Kandagatla 	} else {
3065db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_default_state(priv->device);
3066ba1377ffSGiuseppe CAVALLARO 		/* enable the clk prevously disabled */
3067777da230SGiuseppe CAVALLARO 		clk_enable(priv->stmmac_clk);
30685f9755d2SAndrew Bresticker 		clk_enable(priv->pclk);
3069623997fbSSrinivas Kandagatla 		/* reset the phy so that it's ready */
3070623997fbSSrinivas Kandagatla 		if (priv->mii)
3071623997fbSSrinivas Kandagatla 			stmmac_mdio_reset(priv->mii);
3072623997fbSSrinivas Kandagatla 	}
30737ac6653aSJeff Kirsher 
30747ac6653aSJeff Kirsher 	netif_device_attach(ndev);
30757ac6653aSJeff Kirsher 
3076777da230SGiuseppe CAVALLARO 	init_dma_desc_rings(ndev, GFP_ATOMIC);
3077fe131929SHuacai Chen 	stmmac_hw_setup(ndev, false);
3078777da230SGiuseppe CAVALLARO 	stmmac_init_tx_coalesce(priv);
30797ac6653aSJeff Kirsher 
30807ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
30817ac6653aSJeff Kirsher 
30827ac6653aSJeff Kirsher 	netif_start_queue(ndev);
30837ac6653aSJeff Kirsher 
3084f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
3085102463b1SFrancesco Virlinzi 
3086102463b1SFrancesco Virlinzi 	if (priv->phydev)
3087102463b1SFrancesco Virlinzi 		phy_start(priv->phydev);
3088102463b1SFrancesco Virlinzi 
30897ac6653aSJeff Kirsher 	return 0;
30907ac6653aSJeff Kirsher }
3091b2e2f0c7SAndy Shevchenko EXPORT_SYMBOL_GPL(stmmac_resume);
3092ba27ec66SGiuseppe CAVALLARO 
30937ac6653aSJeff Kirsher #ifndef MODULE
30947ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str)
30957ac6653aSJeff Kirsher {
30967ac6653aSJeff Kirsher 	char *opt;
30977ac6653aSJeff Kirsher 
30987ac6653aSJeff Kirsher 	if (!str || !*str)
30997ac6653aSJeff Kirsher 		return -EINVAL;
31007ac6653aSJeff Kirsher 	while ((opt = strsep(&str, ",")) != NULL) {
31017ac6653aSJeff Kirsher 		if (!strncmp(opt, "debug:", 6)) {
3102ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &debug))
31037ac6653aSJeff Kirsher 				goto err;
31047ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "phyaddr:", 8)) {
3105ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 8, 0, &phyaddr))
31067ac6653aSJeff Kirsher 				goto err;
31077ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_txsize:", 11)) {
3108ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_txsize))
31097ac6653aSJeff Kirsher 				goto err;
31107ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_rxsize:", 11)) {
3111ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_rxsize))
31127ac6653aSJeff Kirsher 				goto err;
31137ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "buf_sz:", 7)) {
3114ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 7, 0, &buf_sz))
31157ac6653aSJeff Kirsher 				goto err;
31167ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "tc:", 3)) {
3117ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 3, 0, &tc))
31187ac6653aSJeff Kirsher 				goto err;
31197ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "watchdog:", 9)) {
3120ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 9, 0, &watchdog))
31217ac6653aSJeff Kirsher 				goto err;
31227ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "flow_ctrl:", 10)) {
3123ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &flow_ctrl))
31247ac6653aSJeff Kirsher 				goto err;
31257ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "pause:", 6)) {
3126ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &pause))
31277ac6653aSJeff Kirsher 				goto err;
3128506f669cSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "eee_timer:", 10)) {
3129d765955dSGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &eee_timer))
3130d765955dSGiuseppe CAVALLARO 				goto err;
31314a7d666aSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "chain_mode:", 11)) {
31324a7d666aSGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &chain_mode))
31334a7d666aSGiuseppe CAVALLARO 				goto err;
31347ac6653aSJeff Kirsher 		}
31357ac6653aSJeff Kirsher 	}
31367ac6653aSJeff Kirsher 	return 0;
31377ac6653aSJeff Kirsher 
31387ac6653aSJeff Kirsher err:
31397ac6653aSJeff Kirsher 	pr_err("%s: ERROR broken module parameter conversion", __func__);
31407ac6653aSJeff Kirsher 	return -EINVAL;
31417ac6653aSJeff Kirsher }
31427ac6653aSJeff Kirsher 
31437ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt);
3144ceb69499SGiuseppe CAVALLARO #endif /* MODULE */
31456fc0d0f2SGiuseppe Cavallaro 
31466fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
31476fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
31486fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL");
3149