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>
477ac29055SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_DEBUG_FS
487ac29055SGiuseppe CAVALLARO #include <linux/debugfs.h>
497ac29055SGiuseppe CAVALLARO #include <linux/seq_file.h>
50ceb69499SGiuseppe CAVALLARO #endif /* CONFIG_STMMAC_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 
119bfab27a1SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_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.
1287ac6653aSJeff Kirsher  * Description: it verifies if some wrong parameter is passed to the driver.
1297ac6653aSJeff Kirsher  * Note that wrong parameters are replaced with the default values.
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 {
1947ac6653aSJeff Kirsher 	int j;
19583d7af64SGiuseppe CAVALLARO 	pr_debug("len = %d byte, buf addr: 0x%p", len, buf);
1967ac6653aSJeff Kirsher 	for (j = 0; j < len; j++) {
1977ac6653aSJeff Kirsher 		if ((j % 16) == 0)
19883d7af64SGiuseppe CAVALLARO 			pr_debug("\n %03x:", j);
19983d7af64SGiuseppe CAVALLARO 		pr_debug(" %02x", buf[j]);
2007ac6653aSJeff Kirsher 	}
20183d7af64SGiuseppe CAVALLARO 	pr_debug("\n");
2027ac6653aSJeff Kirsher }
2037ac6653aSJeff Kirsher 
2047ac6653aSJeff Kirsher /* minimum number of free TX descriptors required to wake up TX process */
2057ac6653aSJeff Kirsher #define STMMAC_TX_THRESH(x)	(x->dma_tx_size/4)
2067ac6653aSJeff Kirsher 
2077ac6653aSJeff Kirsher static inline u32 stmmac_tx_avail(struct stmmac_priv *priv)
2087ac6653aSJeff Kirsher {
2097ac6653aSJeff Kirsher 	return priv->dirty_tx + priv->dma_tx_size - priv->cur_tx - 1;
2107ac6653aSJeff Kirsher }
2117ac6653aSJeff Kirsher 
21232ceabcaSGiuseppe CAVALLARO /**
21332ceabcaSGiuseppe CAVALLARO  * stmmac_hw_fix_mac_speed: callback for speed selection
21432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
21532ceabcaSGiuseppe CAVALLARO  * Description: on some platforms (e.g. ST), some HW system configuraton
21632ceabcaSGiuseppe CAVALLARO  * registers have to be set according to the link speed negotiated.
2177ac6653aSJeff Kirsher  */
2187ac6653aSJeff Kirsher static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
2197ac6653aSJeff Kirsher {
2207ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
2217ac6653aSJeff Kirsher 
2227ac6653aSJeff Kirsher 	if (likely(priv->plat->fix_mac_speed))
223ceb69499SGiuseppe CAVALLARO 		priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
2247ac6653aSJeff Kirsher }
2257ac6653aSJeff Kirsher 
22632ceabcaSGiuseppe CAVALLARO /**
22732ceabcaSGiuseppe CAVALLARO  * stmmac_enable_eee_mode: Check and enter in LPI mode
22832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
22932ceabcaSGiuseppe CAVALLARO  * Description: this function is to verify and enter in LPI mode for EEE.
23032ceabcaSGiuseppe CAVALLARO  */
231d765955dSGiuseppe CAVALLARO static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
232d765955dSGiuseppe CAVALLARO {
233d765955dSGiuseppe CAVALLARO 	/* Check and enter in LPI mode */
234d765955dSGiuseppe CAVALLARO 	if ((priv->dirty_tx == priv->cur_tx) &&
235d765955dSGiuseppe CAVALLARO 	    (priv->tx_path_in_lpi_mode == false))
236d765955dSGiuseppe CAVALLARO 		priv->hw->mac->set_eee_mode(priv->ioaddr);
237d765955dSGiuseppe CAVALLARO }
238d765955dSGiuseppe CAVALLARO 
23932ceabcaSGiuseppe CAVALLARO /**
24032ceabcaSGiuseppe CAVALLARO  * stmmac_disable_eee_mode: disable/exit from EEE
24132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
24232ceabcaSGiuseppe CAVALLARO  * Description: this function is to exit and disable EEE in case of
24332ceabcaSGiuseppe CAVALLARO  * LPI state is true. This is called by the xmit.
24432ceabcaSGiuseppe CAVALLARO  */
245d765955dSGiuseppe CAVALLARO void stmmac_disable_eee_mode(struct stmmac_priv *priv)
246d765955dSGiuseppe CAVALLARO {
247d765955dSGiuseppe CAVALLARO 	priv->hw->mac->reset_eee_mode(priv->ioaddr);
248d765955dSGiuseppe CAVALLARO 	del_timer_sync(&priv->eee_ctrl_timer);
249d765955dSGiuseppe CAVALLARO 	priv->tx_path_in_lpi_mode = false;
250d765955dSGiuseppe CAVALLARO }
251d765955dSGiuseppe CAVALLARO 
252d765955dSGiuseppe CAVALLARO /**
25332ceabcaSGiuseppe CAVALLARO  * stmmac_eee_ctrl_timer: EEE TX SW timer.
254d765955dSGiuseppe CAVALLARO  * @arg : data hook
255d765955dSGiuseppe CAVALLARO  * Description:
25632ceabcaSGiuseppe CAVALLARO  *  if there is no data transfer and if we are not in LPI state,
257d765955dSGiuseppe CAVALLARO  *  then MAC Transmitter can be moved to LPI state.
258d765955dSGiuseppe CAVALLARO  */
259d765955dSGiuseppe CAVALLARO static void stmmac_eee_ctrl_timer(unsigned long arg)
260d765955dSGiuseppe CAVALLARO {
261d765955dSGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)arg;
262d765955dSGiuseppe CAVALLARO 
263d765955dSGiuseppe CAVALLARO 	stmmac_enable_eee_mode(priv);
264f5351ef7SGiuseppe CAVALLARO 	mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
265d765955dSGiuseppe CAVALLARO }
266d765955dSGiuseppe CAVALLARO 
267d765955dSGiuseppe CAVALLARO /**
26832ceabcaSGiuseppe CAVALLARO  * stmmac_eee_init: init EEE
26932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
270d765955dSGiuseppe CAVALLARO  * Description:
271d765955dSGiuseppe CAVALLARO  *  If the EEE support has been enabled while configuring the driver,
272d765955dSGiuseppe CAVALLARO  *  if the GMAC actually supports the EEE (from the HW cap reg) and the
273d765955dSGiuseppe CAVALLARO  *  phy can also manage EEE, so enable the LPI state and start the timer
274d765955dSGiuseppe CAVALLARO  *  to verify if the tx path can enter in LPI state.
275d765955dSGiuseppe CAVALLARO  */
276d765955dSGiuseppe CAVALLARO bool stmmac_eee_init(struct stmmac_priv *priv)
277d765955dSGiuseppe CAVALLARO {
278d765955dSGiuseppe CAVALLARO 	bool ret = false;
279d765955dSGiuseppe CAVALLARO 
280f5351ef7SGiuseppe CAVALLARO 	/* Using PCS we cannot dial with the phy registers at this stage
281f5351ef7SGiuseppe CAVALLARO 	 * so we do not support extra feature like EEE.
282f5351ef7SGiuseppe CAVALLARO 	 */
283f5351ef7SGiuseppe CAVALLARO 	if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) ||
284f5351ef7SGiuseppe CAVALLARO 	    (priv->pcs == STMMAC_PCS_RTBI))
285f5351ef7SGiuseppe CAVALLARO 		goto out;
286f5351ef7SGiuseppe 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 			 */
29883bf79b6SGiuseppe CAVALLARO 			if (priv->eee_active) {
29983bf79b6SGiuseppe CAVALLARO 				pr_debug("stmmac: disable EEE\n");
30083bf79b6SGiuseppe CAVALLARO 				del_timer_sync(&priv->eee_ctrl_timer);
30183bf79b6SGiuseppe CAVALLARO 				priv->hw->mac->set_eee_timer(priv->ioaddr, 0,
30283bf79b6SGiuseppe CAVALLARO 							     tx_lpi_timer);
30383bf79b6SGiuseppe CAVALLARO 			}
30483bf79b6SGiuseppe CAVALLARO 			priv->eee_active = 0;
30583bf79b6SGiuseppe CAVALLARO 			goto out;
30683bf79b6SGiuseppe CAVALLARO 		}
30783bf79b6SGiuseppe CAVALLARO 		/* Activate the EEE and start timers */
308f5351ef7SGiuseppe CAVALLARO 		if (!priv->eee_active) {
309d765955dSGiuseppe CAVALLARO 			priv->eee_active = 1;
310d765955dSGiuseppe CAVALLARO 			init_timer(&priv->eee_ctrl_timer);
311d765955dSGiuseppe CAVALLARO 			priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer;
312d765955dSGiuseppe CAVALLARO 			priv->eee_ctrl_timer.data = (unsigned long)priv;
313f5351ef7SGiuseppe CAVALLARO 			priv->eee_ctrl_timer.expires = STMMAC_LPI_T(eee_timer);
314d765955dSGiuseppe CAVALLARO 			add_timer(&priv->eee_ctrl_timer);
315d765955dSGiuseppe CAVALLARO 
316d765955dSGiuseppe CAVALLARO 			priv->hw->mac->set_eee_timer(priv->ioaddr,
317f5351ef7SGiuseppe CAVALLARO 						     STMMAC_DEFAULT_LIT_LS,
31883bf79b6SGiuseppe CAVALLARO 						     tx_lpi_timer);
319f5351ef7SGiuseppe CAVALLARO 		} else
320f5351ef7SGiuseppe CAVALLARO 			/* Set HW EEE according to the speed */
321f5351ef7SGiuseppe CAVALLARO 			priv->hw->mac->set_eee_pls(priv->ioaddr,
322f5351ef7SGiuseppe CAVALLARO 						   priv->phydev->link);
323d765955dSGiuseppe CAVALLARO 
32483bf79b6SGiuseppe CAVALLARO 		pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
325d765955dSGiuseppe CAVALLARO 
326d765955dSGiuseppe CAVALLARO 		ret = true;
327d765955dSGiuseppe CAVALLARO 	}
328d765955dSGiuseppe CAVALLARO out:
329d765955dSGiuseppe CAVALLARO 	return ret;
330d765955dSGiuseppe CAVALLARO }
331d765955dSGiuseppe CAVALLARO 
33232ceabcaSGiuseppe CAVALLARO /* stmmac_get_tx_hwtstamp: get HW TX timestamps
33332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
334891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
335891434b1SRayagond Kokatanur  * @skb : the socket buffer
336891434b1SRayagond Kokatanur  * Description :
337891434b1SRayagond Kokatanur  * This function will read timestamp from the descriptor & pass it to stack.
338891434b1SRayagond Kokatanur  * and also perform some sanity checks.
339891434b1SRayagond Kokatanur  */
340891434b1SRayagond Kokatanur static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
341ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
342891434b1SRayagond Kokatanur {
343891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps shhwtstamp;
344891434b1SRayagond Kokatanur 	u64 ns;
345891434b1SRayagond Kokatanur 	void *desc = NULL;
346891434b1SRayagond Kokatanur 
347891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
348891434b1SRayagond Kokatanur 		return;
349891434b1SRayagond Kokatanur 
350ceb69499SGiuseppe CAVALLARO 	/* exit if skb doesn't support hw tstamp */
35175e4364fSdamuzi000 	if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
352891434b1SRayagond Kokatanur 		return;
353891434b1SRayagond Kokatanur 
354891434b1SRayagond Kokatanur 	if (priv->adv_ts)
355891434b1SRayagond Kokatanur 		desc = (priv->dma_etx + entry);
356891434b1SRayagond Kokatanur 	else
357891434b1SRayagond Kokatanur 		desc = (priv->dma_tx + entry);
358891434b1SRayagond Kokatanur 
359891434b1SRayagond Kokatanur 	/* check tx tstamp status */
360891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_tx_timestamp_status((struct dma_desc *)desc))
361891434b1SRayagond Kokatanur 		return;
362891434b1SRayagond Kokatanur 
363891434b1SRayagond Kokatanur 	/* get the valid tstamp */
364891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
365891434b1SRayagond Kokatanur 
366891434b1SRayagond Kokatanur 	memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
367891434b1SRayagond Kokatanur 	shhwtstamp.hwtstamp = ns_to_ktime(ns);
368891434b1SRayagond Kokatanur 	/* pass tstamp to stack */
369891434b1SRayagond Kokatanur 	skb_tstamp_tx(skb, &shhwtstamp);
370891434b1SRayagond Kokatanur 
371891434b1SRayagond Kokatanur 	return;
372891434b1SRayagond Kokatanur }
373891434b1SRayagond Kokatanur 
37432ceabcaSGiuseppe CAVALLARO /* stmmac_get_rx_hwtstamp: get HW RX timestamps
37532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
376891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
377891434b1SRayagond Kokatanur  * @skb : the socket buffer
378891434b1SRayagond Kokatanur  * Description :
379891434b1SRayagond Kokatanur  * This function will read received packet's timestamp from the descriptor
380891434b1SRayagond Kokatanur  * and pass it to stack. It also perform some sanity checks.
381891434b1SRayagond Kokatanur  */
382891434b1SRayagond Kokatanur static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv,
383ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
384891434b1SRayagond Kokatanur {
385891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps *shhwtstamp = NULL;
386891434b1SRayagond Kokatanur 	u64 ns;
387891434b1SRayagond Kokatanur 	void *desc = NULL;
388891434b1SRayagond Kokatanur 
389891434b1SRayagond Kokatanur 	if (!priv->hwts_rx_en)
390891434b1SRayagond Kokatanur 		return;
391891434b1SRayagond Kokatanur 
392891434b1SRayagond Kokatanur 	if (priv->adv_ts)
393891434b1SRayagond Kokatanur 		desc = (priv->dma_erx + entry);
394891434b1SRayagond Kokatanur 	else
395891434b1SRayagond Kokatanur 		desc = (priv->dma_rx + entry);
396891434b1SRayagond Kokatanur 
397ceb69499SGiuseppe CAVALLARO 	/* exit if rx tstamp is not valid */
398891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts))
399891434b1SRayagond Kokatanur 		return;
400891434b1SRayagond Kokatanur 
401891434b1SRayagond Kokatanur 	/* get valid tstamp */
402891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
403891434b1SRayagond Kokatanur 	shhwtstamp = skb_hwtstamps(skb);
404891434b1SRayagond Kokatanur 	memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
405891434b1SRayagond Kokatanur 	shhwtstamp->hwtstamp = ns_to_ktime(ns);
406891434b1SRayagond Kokatanur }
407891434b1SRayagond Kokatanur 
408891434b1SRayagond Kokatanur /**
409891434b1SRayagond Kokatanur  *  stmmac_hwtstamp_ioctl - control hardware timestamping.
410891434b1SRayagond Kokatanur  *  @dev: device pointer.
411891434b1SRayagond Kokatanur  *  @ifr: An IOCTL specefic structure, that can contain a pointer to
412891434b1SRayagond Kokatanur  *  a proprietary structure used to pass information to the driver.
413891434b1SRayagond Kokatanur  *  Description:
414891434b1SRayagond Kokatanur  *  This function configures the MAC to enable/disable both outgoing(TX)
415891434b1SRayagond Kokatanur  *  and incoming(RX) packets time stamping based on user input.
416891434b1SRayagond Kokatanur  *  Return Value:
417891434b1SRayagond Kokatanur  *  0 on success and an appropriate -ve integer on failure.
418891434b1SRayagond Kokatanur  */
419891434b1SRayagond Kokatanur static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
420891434b1SRayagond Kokatanur {
421891434b1SRayagond Kokatanur 	struct stmmac_priv *priv = netdev_priv(dev);
422891434b1SRayagond Kokatanur 	struct hwtstamp_config config;
423891434b1SRayagond Kokatanur 	struct timespec now;
424891434b1SRayagond Kokatanur 	u64 temp = 0;
425891434b1SRayagond Kokatanur 	u32 ptp_v2 = 0;
426891434b1SRayagond Kokatanur 	u32 tstamp_all = 0;
427891434b1SRayagond Kokatanur 	u32 ptp_over_ipv4_udp = 0;
428891434b1SRayagond Kokatanur 	u32 ptp_over_ipv6_udp = 0;
429891434b1SRayagond Kokatanur 	u32 ptp_over_ethernet = 0;
430891434b1SRayagond Kokatanur 	u32 snap_type_sel = 0;
431891434b1SRayagond Kokatanur 	u32 ts_master_en = 0;
432891434b1SRayagond Kokatanur 	u32 ts_event_en = 0;
433891434b1SRayagond Kokatanur 	u32 value = 0;
434891434b1SRayagond Kokatanur 
435891434b1SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
436891434b1SRayagond Kokatanur 		netdev_alert(priv->dev, "No support for HW time stamping\n");
437891434b1SRayagond Kokatanur 		priv->hwts_tx_en = 0;
438891434b1SRayagond Kokatanur 		priv->hwts_rx_en = 0;
439891434b1SRayagond Kokatanur 
440891434b1SRayagond Kokatanur 		return -EOPNOTSUPP;
441891434b1SRayagond Kokatanur 	}
442891434b1SRayagond Kokatanur 
443891434b1SRayagond Kokatanur 	if (copy_from_user(&config, ifr->ifr_data,
444891434b1SRayagond Kokatanur 			   sizeof(struct hwtstamp_config)))
445891434b1SRayagond Kokatanur 		return -EFAULT;
446891434b1SRayagond Kokatanur 
447891434b1SRayagond Kokatanur 	pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
448891434b1SRayagond Kokatanur 		 __func__, config.flags, config.tx_type, config.rx_filter);
449891434b1SRayagond Kokatanur 
450891434b1SRayagond Kokatanur 	/* reserved for future extensions */
451891434b1SRayagond Kokatanur 	if (config.flags)
452891434b1SRayagond Kokatanur 		return -EINVAL;
453891434b1SRayagond Kokatanur 
4545f3da328SBen Hutchings 	if (config.tx_type != HWTSTAMP_TX_OFF &&
4555f3da328SBen Hutchings 	    config.tx_type != HWTSTAMP_TX_ON)
456891434b1SRayagond Kokatanur 		return -ERANGE;
457891434b1SRayagond Kokatanur 
458891434b1SRayagond Kokatanur 	if (priv->adv_ts) {
459891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
460891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
461ceb69499SGiuseppe CAVALLARO 			/* time stamp no incoming packet at all */
462891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
463891434b1SRayagond Kokatanur 			break;
464891434b1SRayagond Kokatanur 
465891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
466ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, any kind of event packet */
467891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
468891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
469891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
470891434b1SRayagond Kokatanur 
471891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
472891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
473891434b1SRayagond Kokatanur 			break;
474891434b1SRayagond Kokatanur 
475891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
476ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Sync packet */
477891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
478891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
479891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
480891434b1SRayagond Kokatanur 
481891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
482891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
483891434b1SRayagond Kokatanur 			break;
484891434b1SRayagond Kokatanur 
485891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
486ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Delay_req packet */
487891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
488891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
489891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
490891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
491891434b1SRayagond Kokatanur 
492891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
493891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
494891434b1SRayagond Kokatanur 			break;
495891434b1SRayagond Kokatanur 
496891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
497ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, any kind of event packet */
498891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
499891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
500891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
501891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
502891434b1SRayagond Kokatanur 
503891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
504891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
505891434b1SRayagond Kokatanur 			break;
506891434b1SRayagond Kokatanur 
507891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
508ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Sync packet */
509891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
510891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
511891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
512891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
513891434b1SRayagond Kokatanur 
514891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
515891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
516891434b1SRayagond Kokatanur 			break;
517891434b1SRayagond Kokatanur 
518891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
519ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Delay_req packet */
520891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
521891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
522891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
523891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
524891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
525891434b1SRayagond Kokatanur 
526891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
527891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
528891434b1SRayagond Kokatanur 			break;
529891434b1SRayagond Kokatanur 
530891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_EVENT:
531ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1 any layer, any kind of event packet */
532891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
533891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
534891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
535891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
536891434b1SRayagond Kokatanur 
537891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
538891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
539891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
540891434b1SRayagond Kokatanur 			break;
541891434b1SRayagond Kokatanur 
542891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_SYNC:
543ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Sync packet */
544891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
545891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
546891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
547891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
548891434b1SRayagond Kokatanur 
549891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
550891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
551891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
552891434b1SRayagond Kokatanur 			break;
553891434b1SRayagond Kokatanur 
554891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
555ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Delay_req packet */
556891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
557891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
558891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
559891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
560891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
561891434b1SRayagond Kokatanur 
562891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
563891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
564891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
565891434b1SRayagond Kokatanur 			break;
566891434b1SRayagond Kokatanur 
567891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_ALL:
568ceb69499SGiuseppe CAVALLARO 			/* time stamp any incoming packet */
569891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_ALL;
570891434b1SRayagond Kokatanur 			tstamp_all = PTP_TCR_TSENALL;
571891434b1SRayagond Kokatanur 			break;
572891434b1SRayagond Kokatanur 
573891434b1SRayagond Kokatanur 		default:
574891434b1SRayagond Kokatanur 			return -ERANGE;
575891434b1SRayagond Kokatanur 		}
576891434b1SRayagond Kokatanur 	} else {
577891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
578891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
579891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
580891434b1SRayagond Kokatanur 			break;
581891434b1SRayagond Kokatanur 		default:
582891434b1SRayagond Kokatanur 			/* PTP v1, UDP, any kind of event packet */
583891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
584891434b1SRayagond Kokatanur 			break;
585891434b1SRayagond Kokatanur 		}
586891434b1SRayagond Kokatanur 	}
587891434b1SRayagond Kokatanur 	priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1);
5885f3da328SBen Hutchings 	priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON;
589891434b1SRayagond Kokatanur 
590891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en && !priv->hwts_rx_en)
591891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0);
592891434b1SRayagond Kokatanur 	else {
593891434b1SRayagond Kokatanur 		value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
594891434b1SRayagond Kokatanur 			 tstamp_all | ptp_v2 | ptp_over_ethernet |
595891434b1SRayagond Kokatanur 			 ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
596891434b1SRayagond Kokatanur 			 ts_master_en | snap_type_sel);
597891434b1SRayagond Kokatanur 
598891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
599891434b1SRayagond Kokatanur 
600891434b1SRayagond Kokatanur 		/* program Sub Second Increment reg */
601891434b1SRayagond Kokatanur 		priv->hw->ptp->config_sub_second_increment(priv->ioaddr);
602891434b1SRayagond Kokatanur 
603891434b1SRayagond Kokatanur 		/* calculate default added value:
604891434b1SRayagond Kokatanur 		 * formula is :
605891434b1SRayagond Kokatanur 		 * addend = (2^32)/freq_div_ratio;
606891434b1SRayagond Kokatanur 		 * where, freq_div_ratio = STMMAC_SYSCLOCK/50MHz
607891434b1SRayagond Kokatanur 		 * hence, addend = ((2^32) * 50MHz)/STMMAC_SYSCLOCK;
608891434b1SRayagond Kokatanur 		 * NOTE: STMMAC_SYSCLOCK should be >= 50MHz to
609891434b1SRayagond Kokatanur 		 *       achive 20ns accuracy.
610891434b1SRayagond Kokatanur 		 *
611891434b1SRayagond Kokatanur 		 * 2^x * y == (y << x), hence
612891434b1SRayagond Kokatanur 		 * 2^32 * 50000000 ==> (50000000 << 32)
613891434b1SRayagond Kokatanur 		 */
614891434b1SRayagond Kokatanur 		temp = (u64) (50000000ULL << 32);
615891434b1SRayagond Kokatanur 		priv->default_addend = div_u64(temp, STMMAC_SYSCLOCK);
616891434b1SRayagond Kokatanur 		priv->hw->ptp->config_addend(priv->ioaddr,
617891434b1SRayagond Kokatanur 					     priv->default_addend);
618891434b1SRayagond Kokatanur 
619891434b1SRayagond Kokatanur 		/* initialize system time */
620891434b1SRayagond Kokatanur 		getnstimeofday(&now);
621891434b1SRayagond Kokatanur 		priv->hw->ptp->init_systime(priv->ioaddr, now.tv_sec,
622891434b1SRayagond Kokatanur 					    now.tv_nsec);
623891434b1SRayagond Kokatanur 	}
624891434b1SRayagond Kokatanur 
625891434b1SRayagond Kokatanur 	return copy_to_user(ifr->ifr_data, &config,
626891434b1SRayagond Kokatanur 			    sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
627891434b1SRayagond Kokatanur }
628891434b1SRayagond Kokatanur 
62932ceabcaSGiuseppe CAVALLARO /**
63032ceabcaSGiuseppe CAVALLARO  * stmmac_init_ptp: init PTP
63132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
63232ceabcaSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PTPv1 or v2.
63332ceabcaSGiuseppe CAVALLARO  * This is done by looking at the HW cap. register.
63432ceabcaSGiuseppe CAVALLARO  * Also it registers the ptp driver.
63532ceabcaSGiuseppe CAVALLARO  */
63692ba6888SRayagond Kokatanur static int stmmac_init_ptp(struct stmmac_priv *priv)
637891434b1SRayagond Kokatanur {
63892ba6888SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
63992ba6888SRayagond Kokatanur 		return -EOPNOTSUPP;
64092ba6888SRayagond Kokatanur 
641891434b1SRayagond Kokatanur 	priv->adv_ts = 0;
6427cd01399SVince Bridgers 	if (priv->dma_cap.atime_stamp && priv->extend_desc)
643891434b1SRayagond Kokatanur 		priv->adv_ts = 1;
6447cd01399SVince Bridgers 
6457cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
6467cd01399SVince Bridgers 		pr_debug("IEEE 1588-2002 Time Stamp supported\n");
6477cd01399SVince Bridgers 
6487cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->adv_ts)
6497cd01399SVince Bridgers 		pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
650891434b1SRayagond Kokatanur 
651891434b1SRayagond Kokatanur 	priv->hw->ptp = &stmmac_ptp;
652891434b1SRayagond Kokatanur 	priv->hwts_tx_en = 0;
653891434b1SRayagond Kokatanur 	priv->hwts_rx_en = 0;
65492ba6888SRayagond Kokatanur 
65592ba6888SRayagond Kokatanur 	return stmmac_ptp_register(priv);
65692ba6888SRayagond Kokatanur }
65792ba6888SRayagond Kokatanur 
65892ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv)
65992ba6888SRayagond Kokatanur {
66092ba6888SRayagond Kokatanur 	stmmac_ptp_unregister(priv);
661891434b1SRayagond Kokatanur }
662891434b1SRayagond Kokatanur 
6637ac6653aSJeff Kirsher /**
6647ac6653aSJeff Kirsher  * stmmac_adjust_link
6657ac6653aSJeff Kirsher  * @dev: net device structure
6667ac6653aSJeff Kirsher  * Description: it adjusts the link parameters.
6677ac6653aSJeff Kirsher  */
6687ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev)
6697ac6653aSJeff Kirsher {
6707ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
6717ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
6727ac6653aSJeff Kirsher 	unsigned long flags;
6737ac6653aSJeff Kirsher 	int new_state = 0;
6747ac6653aSJeff Kirsher 	unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
6757ac6653aSJeff Kirsher 
6767ac6653aSJeff Kirsher 	if (phydev == NULL)
6777ac6653aSJeff Kirsher 		return;
6787ac6653aSJeff Kirsher 
6797ac6653aSJeff Kirsher 	spin_lock_irqsave(&priv->lock, flags);
680d765955dSGiuseppe CAVALLARO 
6817ac6653aSJeff Kirsher 	if (phydev->link) {
6827ac6653aSJeff Kirsher 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
6837ac6653aSJeff Kirsher 
6847ac6653aSJeff Kirsher 		/* Now we make sure that we can be in full duplex mode.
6857ac6653aSJeff Kirsher 		 * If not, we operate in half-duplex mode. */
6867ac6653aSJeff Kirsher 		if (phydev->duplex != priv->oldduplex) {
6877ac6653aSJeff Kirsher 			new_state = 1;
6887ac6653aSJeff Kirsher 			if (!(phydev->duplex))
6897ac6653aSJeff Kirsher 				ctrl &= ~priv->hw->link.duplex;
6907ac6653aSJeff Kirsher 			else
6917ac6653aSJeff Kirsher 				ctrl |= priv->hw->link.duplex;
6927ac6653aSJeff Kirsher 			priv->oldduplex = phydev->duplex;
6937ac6653aSJeff Kirsher 		}
6947ac6653aSJeff Kirsher 		/* Flow Control operation */
6957ac6653aSJeff Kirsher 		if (phydev->pause)
6967ac6653aSJeff Kirsher 			priv->hw->mac->flow_ctrl(priv->ioaddr, phydev->duplex,
6977ac6653aSJeff Kirsher 						 fc, pause_time);
6987ac6653aSJeff Kirsher 
6997ac6653aSJeff Kirsher 		if (phydev->speed != priv->speed) {
7007ac6653aSJeff Kirsher 			new_state = 1;
7017ac6653aSJeff Kirsher 			switch (phydev->speed) {
7027ac6653aSJeff Kirsher 			case 1000:
7037ac6653aSJeff Kirsher 				if (likely(priv->plat->has_gmac))
7047ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7057ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7067ac6653aSJeff Kirsher 				break;
7077ac6653aSJeff Kirsher 			case 100:
7087ac6653aSJeff Kirsher 			case 10:
7097ac6653aSJeff Kirsher 				if (priv->plat->has_gmac) {
7107ac6653aSJeff Kirsher 					ctrl |= priv->hw->link.port;
7117ac6653aSJeff Kirsher 					if (phydev->speed == SPEED_100) {
7127ac6653aSJeff Kirsher 						ctrl |= priv->hw->link.speed;
7137ac6653aSJeff Kirsher 					} else {
7147ac6653aSJeff Kirsher 						ctrl &= ~(priv->hw->link.speed);
7157ac6653aSJeff Kirsher 					}
7167ac6653aSJeff Kirsher 				} else {
7177ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7187ac6653aSJeff Kirsher 				}
7197ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7207ac6653aSJeff Kirsher 				break;
7217ac6653aSJeff Kirsher 			default:
7227ac6653aSJeff Kirsher 				if (netif_msg_link(priv))
723ceb69499SGiuseppe CAVALLARO 					pr_warn("%s: Speed (%d) not 10/100\n",
724ceb69499SGiuseppe CAVALLARO 						dev->name, phydev->speed);
7257ac6653aSJeff Kirsher 				break;
7267ac6653aSJeff Kirsher 			}
7277ac6653aSJeff Kirsher 
7287ac6653aSJeff Kirsher 			priv->speed = phydev->speed;
7297ac6653aSJeff Kirsher 		}
7307ac6653aSJeff Kirsher 
7317ac6653aSJeff Kirsher 		writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
7327ac6653aSJeff Kirsher 
7337ac6653aSJeff Kirsher 		if (!priv->oldlink) {
7347ac6653aSJeff Kirsher 			new_state = 1;
7357ac6653aSJeff Kirsher 			priv->oldlink = 1;
7367ac6653aSJeff Kirsher 		}
7377ac6653aSJeff Kirsher 	} else if (priv->oldlink) {
7387ac6653aSJeff Kirsher 		new_state = 1;
7397ac6653aSJeff Kirsher 		priv->oldlink = 0;
7407ac6653aSJeff Kirsher 		priv->speed = 0;
7417ac6653aSJeff Kirsher 		priv->oldduplex = -1;
7427ac6653aSJeff Kirsher 	}
7437ac6653aSJeff Kirsher 
7447ac6653aSJeff Kirsher 	if (new_state && netif_msg_link(priv))
7457ac6653aSJeff Kirsher 		phy_print_status(phydev);
7467ac6653aSJeff Kirsher 
747f5351ef7SGiuseppe CAVALLARO 	/* At this stage, it could be needed to setup the EEE or adjust some
748f5351ef7SGiuseppe CAVALLARO 	 * MAC related HW registers.
749f5351ef7SGiuseppe CAVALLARO 	 */
750f5351ef7SGiuseppe CAVALLARO 	priv->eee_enabled = stmmac_eee_init(priv);
751d765955dSGiuseppe CAVALLARO 
7527ac6653aSJeff Kirsher 	spin_unlock_irqrestore(&priv->lock, flags);
7537ac6653aSJeff Kirsher }
7547ac6653aSJeff Kirsher 
75532ceabcaSGiuseppe CAVALLARO /**
75632ceabcaSGiuseppe CAVALLARO  * stmmac_check_pcs_mode: verify if RGMII/SGMII is supported
75732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
75832ceabcaSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PCS.
75932ceabcaSGiuseppe CAVALLARO  * Physical Coding Sublayer (PCS) interface that can be used when the MAC is
76032ceabcaSGiuseppe CAVALLARO  * configured for the TBI, RTBI, or SGMII PHY interface.
76132ceabcaSGiuseppe CAVALLARO  */
762e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
763e58bb43fSGiuseppe CAVALLARO {
764e58bb43fSGiuseppe CAVALLARO 	int interface = priv->plat->interface;
765e58bb43fSGiuseppe CAVALLARO 
766e58bb43fSGiuseppe CAVALLARO 	if (priv->dma_cap.pcs) {
7670d909dcdSByungho An 		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
7680d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
7690d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
7700d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
771e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS RGMII support enable\n");
772e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_RGMII;
7730d909dcdSByungho An 		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
774e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS SGMII support enable\n");
775e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_SGMII;
776e58bb43fSGiuseppe CAVALLARO 		}
777e58bb43fSGiuseppe CAVALLARO 	}
778e58bb43fSGiuseppe CAVALLARO }
779e58bb43fSGiuseppe CAVALLARO 
7807ac6653aSJeff Kirsher /**
7817ac6653aSJeff Kirsher  * stmmac_init_phy - PHY initialization
7827ac6653aSJeff Kirsher  * @dev: net device structure
7837ac6653aSJeff Kirsher  * Description: it initializes the driver's PHY state, and attaches the PHY
7847ac6653aSJeff Kirsher  * to the mac driver.
7857ac6653aSJeff Kirsher  *  Return value:
7867ac6653aSJeff Kirsher  *  0 on success
7877ac6653aSJeff Kirsher  */
7887ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev)
7897ac6653aSJeff Kirsher {
7907ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
7917ac6653aSJeff Kirsher 	struct phy_device *phydev;
792d765955dSGiuseppe CAVALLARO 	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
7937ac6653aSJeff Kirsher 	char bus_id[MII_BUS_ID_SIZE];
79479ee1dc3SSrinivas Kandagatla 	int interface = priv->plat->interface;
7959cbadf09SSrinivas Kandagatla 	int max_speed = priv->plat->max_speed;
7967ac6653aSJeff Kirsher 	priv->oldlink = 0;
7977ac6653aSJeff Kirsher 	priv->speed = 0;
7987ac6653aSJeff Kirsher 	priv->oldduplex = -1;
7997ac6653aSJeff Kirsher 
800f142af2eSSrinivas Kandagatla 	if (priv->plat->phy_bus_name)
801f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
802f142af2eSSrinivas Kandagatla 			 priv->plat->phy_bus_name, priv->plat->bus_id);
803f142af2eSSrinivas Kandagatla 	else
804f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
805f142af2eSSrinivas Kandagatla 			 priv->plat->bus_id);
806f142af2eSSrinivas Kandagatla 
807d765955dSGiuseppe CAVALLARO 	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
8087ac6653aSJeff Kirsher 		 priv->plat->phy_addr);
809d765955dSGiuseppe CAVALLARO 	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
8107ac6653aSJeff Kirsher 
811f9a8f83bSFlorian Fainelli 	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
8127ac6653aSJeff Kirsher 
8137ac6653aSJeff Kirsher 	if (IS_ERR(phydev)) {
8147ac6653aSJeff Kirsher 		pr_err("%s: Could not attach to PHY\n", dev->name);
8157ac6653aSJeff Kirsher 		return PTR_ERR(phydev);
8167ac6653aSJeff Kirsher 	}
8177ac6653aSJeff Kirsher 
81879ee1dc3SSrinivas Kandagatla 	/* Stop Advertising 1000BASE Capability if interface is not GMII */
819c5b9b4e4SSrinivas Kandagatla 	if ((interface == PHY_INTERFACE_MODE_MII) ||
8209cbadf09SSrinivas Kandagatla 	    (interface == PHY_INTERFACE_MODE_RMII) ||
8219cbadf09SSrinivas Kandagatla 		(max_speed < 1000 &&  max_speed > 0))
822c5b9b4e4SSrinivas Kandagatla 		phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
823c5b9b4e4SSrinivas Kandagatla 					 SUPPORTED_1000baseT_Full);
82479ee1dc3SSrinivas Kandagatla 
8257ac6653aSJeff Kirsher 	/*
8267ac6653aSJeff Kirsher 	 * Broken HW is sometimes missing the pull-up resistor on the
8277ac6653aSJeff Kirsher 	 * MDIO line, which results in reads to non-existent devices returning
8287ac6653aSJeff Kirsher 	 * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
8297ac6653aSJeff Kirsher 	 * device as well.
8307ac6653aSJeff Kirsher 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
8317ac6653aSJeff Kirsher 	 */
8327ac6653aSJeff Kirsher 	if (phydev->phy_id == 0) {
8337ac6653aSJeff Kirsher 		phy_disconnect(phydev);
8347ac6653aSJeff Kirsher 		return -ENODEV;
8357ac6653aSJeff Kirsher 	}
8367ac6653aSJeff Kirsher 	pr_debug("stmmac_init_phy:  %s: attached to PHY (UID 0x%x)"
8377ac6653aSJeff Kirsher 		 " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
8387ac6653aSJeff Kirsher 
8397ac6653aSJeff Kirsher 	priv->phydev = phydev;
8407ac6653aSJeff Kirsher 
8417ac6653aSJeff Kirsher 	return 0;
8427ac6653aSJeff Kirsher }
8437ac6653aSJeff Kirsher 
8447ac6653aSJeff Kirsher /**
84532ceabcaSGiuseppe CAVALLARO  * stmmac_display_ring: display ring
84632ceabcaSGiuseppe CAVALLARO  * @head: pointer to the head of the ring passed.
8477ac6653aSJeff Kirsher  * @size: size of the ring.
84832ceabcaSGiuseppe CAVALLARO  * @extend_desc: to verify if extended descriptors are used.
849c24602efSGiuseppe CAVALLARO  * Description: display the control/status and buffer descriptors.
8507ac6653aSJeff Kirsher  */
851c24602efSGiuseppe CAVALLARO static void stmmac_display_ring(void *head, int size, int extend_desc)
8527ac6653aSJeff Kirsher {
8537ac6653aSJeff Kirsher 	int i;
854c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
855c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
856c24602efSGiuseppe CAVALLARO 
8577ac6653aSJeff Kirsher 	for (i = 0; i < size; i++) {
858c24602efSGiuseppe CAVALLARO 		u64 x;
859c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
860c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
861c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
862c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(ep),
863c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
864c24602efSGiuseppe CAVALLARO 				ep->basic.des2, ep->basic.des3);
865c24602efSGiuseppe CAVALLARO 			ep++;
866c24602efSGiuseppe CAVALLARO 		} else {
867c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
868c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x",
869c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(p),
870c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
871c24602efSGiuseppe CAVALLARO 				p->des2, p->des3);
872c24602efSGiuseppe CAVALLARO 			p++;
873c24602efSGiuseppe CAVALLARO 		}
8747ac6653aSJeff Kirsher 		pr_info("\n");
8757ac6653aSJeff Kirsher 	}
8767ac6653aSJeff Kirsher }
8777ac6653aSJeff Kirsher 
878c24602efSGiuseppe CAVALLARO static void stmmac_display_rings(struct stmmac_priv *priv)
879c24602efSGiuseppe CAVALLARO {
880c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
881c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
882c24602efSGiuseppe CAVALLARO 
883c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
884c24602efSGiuseppe CAVALLARO 		pr_info("Extended RX descriptor ring:\n");
885c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
886c24602efSGiuseppe CAVALLARO 		pr_info("Extended TX descriptor ring:\n");
887c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
888c24602efSGiuseppe CAVALLARO 	} else {
889c24602efSGiuseppe CAVALLARO 		pr_info("RX descriptor ring:\n");
890c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
891c24602efSGiuseppe CAVALLARO 		pr_info("TX descriptor ring:\n");
892c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
893c24602efSGiuseppe CAVALLARO 	}
894c24602efSGiuseppe CAVALLARO }
895c24602efSGiuseppe CAVALLARO 
896286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize)
897286a8372SGiuseppe CAVALLARO {
898286a8372SGiuseppe CAVALLARO 	int ret = bufsize;
899286a8372SGiuseppe CAVALLARO 
900286a8372SGiuseppe CAVALLARO 	if (mtu >= BUF_SIZE_4KiB)
901286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_8KiB;
902286a8372SGiuseppe CAVALLARO 	else if (mtu >= BUF_SIZE_2KiB)
903286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_4KiB;
904d916701cSGiuseppe CAVALLARO 	else if (mtu > DEFAULT_BUFSIZE)
905286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_2KiB;
906286a8372SGiuseppe CAVALLARO 	else
907d916701cSGiuseppe CAVALLARO 		ret = DEFAULT_BUFSIZE;
908286a8372SGiuseppe CAVALLARO 
909286a8372SGiuseppe CAVALLARO 	return ret;
910286a8372SGiuseppe CAVALLARO }
911286a8372SGiuseppe CAVALLARO 
91232ceabcaSGiuseppe CAVALLARO /**
91332ceabcaSGiuseppe CAVALLARO  * stmmac_clear_descriptors: clear descriptors
91432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
91532ceabcaSGiuseppe CAVALLARO  * Description: this function is called to clear the tx and rx descriptors
91632ceabcaSGiuseppe CAVALLARO  * in case of both basic and extended descriptors are used.
91732ceabcaSGiuseppe CAVALLARO  */
918c24602efSGiuseppe CAVALLARO static void stmmac_clear_descriptors(struct stmmac_priv *priv)
919c24602efSGiuseppe CAVALLARO {
920c24602efSGiuseppe CAVALLARO 	int i;
921c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
922c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
923c24602efSGiuseppe CAVALLARO 
924c24602efSGiuseppe CAVALLARO 	/* Clear the Rx/Tx descriptors */
925c24602efSGiuseppe CAVALLARO 	for (i = 0; i < rxsize; i++)
926c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
927c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
928c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
929c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
930c24602efSGiuseppe CAVALLARO 		else
931c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_rx[i],
932c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
933c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
934c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
935c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
936c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
937c24602efSGiuseppe CAVALLARO 						     priv->mode,
938c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
939c24602efSGiuseppe CAVALLARO 		else
940c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
941c24602efSGiuseppe CAVALLARO 						     priv->mode,
942c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
943c24602efSGiuseppe CAVALLARO }
944c24602efSGiuseppe CAVALLARO 
945c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
946c24602efSGiuseppe CAVALLARO 				  int i)
947c24602efSGiuseppe CAVALLARO {
948c24602efSGiuseppe CAVALLARO 	struct sk_buff *skb;
949c24602efSGiuseppe CAVALLARO 
950c24602efSGiuseppe CAVALLARO 	skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
951c24602efSGiuseppe CAVALLARO 				 GFP_KERNEL);
95256329137SBartlomiej Zolnierkiewicz 	if (!skb) {
953c24602efSGiuseppe CAVALLARO 		pr_err("%s: Rx init fails; skb is NULL\n", __func__);
95456329137SBartlomiej Zolnierkiewicz 		return -ENOMEM;
955c24602efSGiuseppe CAVALLARO 	}
956c24602efSGiuseppe CAVALLARO 	skb_reserve(skb, NET_IP_ALIGN);
957c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff[i] = skb;
958c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
959c24602efSGiuseppe CAVALLARO 						priv->dma_buf_sz,
960c24602efSGiuseppe CAVALLARO 						DMA_FROM_DEVICE);
96156329137SBartlomiej Zolnierkiewicz 	if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) {
96256329137SBartlomiej Zolnierkiewicz 		pr_err("%s: DMA mapping error\n", __func__);
96356329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(skb);
96456329137SBartlomiej Zolnierkiewicz 		return -EINVAL;
96556329137SBartlomiej Zolnierkiewicz 	}
966c24602efSGiuseppe CAVALLARO 
967c24602efSGiuseppe CAVALLARO 	p->des2 = priv->rx_skbuff_dma[i];
968c24602efSGiuseppe CAVALLARO 
96929896a67SGiuseppe CAVALLARO 	if ((priv->hw->mode->init_desc3) &&
970c24602efSGiuseppe CAVALLARO 	    (priv->dma_buf_sz == BUF_SIZE_16KiB))
97129896a67SGiuseppe CAVALLARO 		priv->hw->mode->init_desc3(p);
972c24602efSGiuseppe CAVALLARO 
973c24602efSGiuseppe CAVALLARO 	return 0;
974c24602efSGiuseppe CAVALLARO }
975c24602efSGiuseppe CAVALLARO 
97656329137SBartlomiej Zolnierkiewicz static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i)
97756329137SBartlomiej Zolnierkiewicz {
97856329137SBartlomiej Zolnierkiewicz 	if (priv->rx_skbuff[i]) {
97956329137SBartlomiej Zolnierkiewicz 		dma_unmap_single(priv->device, priv->rx_skbuff_dma[i],
98056329137SBartlomiej Zolnierkiewicz 				 priv->dma_buf_sz, DMA_FROM_DEVICE);
98156329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(priv->rx_skbuff[i]);
98256329137SBartlomiej Zolnierkiewicz 	}
98356329137SBartlomiej Zolnierkiewicz 	priv->rx_skbuff[i] = NULL;
98456329137SBartlomiej Zolnierkiewicz }
98556329137SBartlomiej Zolnierkiewicz 
9867ac6653aSJeff Kirsher /**
9877ac6653aSJeff Kirsher  * init_dma_desc_rings - init the RX/TX descriptor rings
9887ac6653aSJeff Kirsher  * @dev: net device structure
9897ac6653aSJeff Kirsher  * Description:  this function initializes the DMA RX/TX descriptors
990286a8372SGiuseppe CAVALLARO  * and allocates the socket buffers. It suppors the chained and ring
991286a8372SGiuseppe CAVALLARO  * modes.
9927ac6653aSJeff Kirsher  */
99356329137SBartlomiej Zolnierkiewicz static int init_dma_desc_rings(struct net_device *dev)
9947ac6653aSJeff Kirsher {
9957ac6653aSJeff Kirsher 	int i;
9967ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
9977ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
9987ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
9994a7d666aSGiuseppe CAVALLARO 	unsigned int bfsize = 0;
100056329137SBartlomiej Zolnierkiewicz 	int ret = -ENOMEM;
10017ac6653aSJeff Kirsher 
100229896a67SGiuseppe CAVALLARO 	if (priv->hw->mode->set_16kib_bfsize)
100329896a67SGiuseppe CAVALLARO 		bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu);
1004286a8372SGiuseppe CAVALLARO 
10054a7d666aSGiuseppe CAVALLARO 	if (bfsize < BUF_SIZE_16KiB)
1006286a8372SGiuseppe CAVALLARO 		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
10077ac6653aSJeff Kirsher 
10082618abb7SVince Bridgers 	priv->dma_buf_sz = bfsize;
10092618abb7SVince Bridgers 
101083d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv))
101183d7af64SGiuseppe CAVALLARO 		pr_debug("%s: txsize %d, rxsize %d, bfsize %d\n", __func__,
10127ac6653aSJeff Kirsher 			 txsize, rxsize, bfsize);
10137ac6653aSJeff Kirsher 
101483d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv)) {
1015c24602efSGiuseppe CAVALLARO 		pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
1016c24602efSGiuseppe CAVALLARO 			 (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
10177ac6653aSJeff Kirsher 
10187ac6653aSJeff Kirsher 		/* RX INITIALIZATION */
101983d7af64SGiuseppe CAVALLARO 		pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n");
102083d7af64SGiuseppe CAVALLARO 	}
10217ac6653aSJeff Kirsher 	for (i = 0; i < rxsize; i++) {
1022c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1023c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1024c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_erx + i)->basic);
1025c24602efSGiuseppe CAVALLARO 		else
1026c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + i;
10277ac6653aSJeff Kirsher 
102856329137SBartlomiej Zolnierkiewicz 		ret = stmmac_init_rx_buffers(priv, p, i);
102956329137SBartlomiej Zolnierkiewicz 		if (ret)
103056329137SBartlomiej Zolnierkiewicz 			goto err_init_rx_buffers;
1031286a8372SGiuseppe CAVALLARO 
103283d7af64SGiuseppe CAVALLARO 		if (netif_msg_probe(priv))
103383d7af64SGiuseppe CAVALLARO 			pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
103483d7af64SGiuseppe CAVALLARO 				 priv->rx_skbuff[i]->data,
103583d7af64SGiuseppe CAVALLARO 				 (unsigned int)priv->rx_skbuff_dma[i]);
10367ac6653aSJeff Kirsher 	}
10377ac6653aSJeff Kirsher 	priv->cur_rx = 0;
10387ac6653aSJeff Kirsher 	priv->dirty_rx = (unsigned int)(i - rxsize);
10397ac6653aSJeff Kirsher 	buf_sz = bfsize;
10407ac6653aSJeff Kirsher 
1041c24602efSGiuseppe CAVALLARO 	/* Setup the chained descriptor addresses */
1042c24602efSGiuseppe CAVALLARO 	if (priv->mode == STMMAC_CHAIN_MODE) {
1043c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc) {
104429896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy,
1045c24602efSGiuseppe CAVALLARO 					     rxsize, 1);
104629896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy,
1047c24602efSGiuseppe CAVALLARO 					     txsize, 1);
1048c24602efSGiuseppe CAVALLARO 		} else {
104929896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy,
1050c24602efSGiuseppe CAVALLARO 					     rxsize, 0);
105129896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy,
1052c24602efSGiuseppe CAVALLARO 					     txsize, 0);
1053c24602efSGiuseppe CAVALLARO 		}
10547ac6653aSJeff Kirsher 	}
1055286a8372SGiuseppe CAVALLARO 
1056c24602efSGiuseppe CAVALLARO 	/* TX INITIALIZATION */
1057c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++) {
1058c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1059c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1060c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1061c24602efSGiuseppe CAVALLARO 		else
1062c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1063c24602efSGiuseppe CAVALLARO 		p->des2 = 0;
1064cf32deecSRayagond Kokatanur 		priv->tx_skbuff_dma[i] = 0;
1065c24602efSGiuseppe CAVALLARO 		priv->tx_skbuff[i] = NULL;
10664a7d666aSGiuseppe CAVALLARO 	}
1067c24602efSGiuseppe CAVALLARO 
10687ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
10697ac6653aSJeff Kirsher 	priv->cur_tx = 0;
10707ac6653aSJeff Kirsher 
1071c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
10727ac6653aSJeff Kirsher 
1073c24602efSGiuseppe CAVALLARO 	if (netif_msg_hw(priv))
1074c24602efSGiuseppe CAVALLARO 		stmmac_display_rings(priv);
107556329137SBartlomiej Zolnierkiewicz 
107656329137SBartlomiej Zolnierkiewicz 	return 0;
107756329137SBartlomiej Zolnierkiewicz err_init_rx_buffers:
107856329137SBartlomiej Zolnierkiewicz 	while (--i >= 0)
107956329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
108056329137SBartlomiej Zolnierkiewicz 	return ret;
10817ac6653aSJeff Kirsher }
10827ac6653aSJeff Kirsher 
10837ac6653aSJeff Kirsher static void dma_free_rx_skbufs(struct stmmac_priv *priv)
10847ac6653aSJeff Kirsher {
10857ac6653aSJeff Kirsher 	int i;
10867ac6653aSJeff Kirsher 
108756329137SBartlomiej Zolnierkiewicz 	for (i = 0; i < priv->dma_rx_size; i++)
108856329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
10897ac6653aSJeff Kirsher }
10907ac6653aSJeff Kirsher 
10917ac6653aSJeff Kirsher static void dma_free_tx_skbufs(struct stmmac_priv *priv)
10927ac6653aSJeff Kirsher {
10937ac6653aSJeff Kirsher 	int i;
10947ac6653aSJeff Kirsher 
10957ac6653aSJeff Kirsher 	for (i = 0; i < priv->dma_tx_size; i++) {
1096c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
109775e4364fSdamuzi000 
1098c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1099c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1100c24602efSGiuseppe CAVALLARO 		else
1101c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1102c24602efSGiuseppe CAVALLARO 
110375e4364fSdamuzi000 		if (priv->tx_skbuff_dma[i]) {
1104cf32deecSRayagond Kokatanur 			dma_unmap_single(priv->device,
1105cf32deecSRayagond Kokatanur 					 priv->tx_skbuff_dma[i],
11067ac6653aSJeff Kirsher 					 priv->hw->desc->get_tx_len(p),
11077ac6653aSJeff Kirsher 					 DMA_TO_DEVICE);
110875e4364fSdamuzi000 			priv->tx_skbuff_dma[i] = 0;
110975e4364fSdamuzi000 		}
111075e4364fSdamuzi000 
111175e4364fSdamuzi000 		if (priv->tx_skbuff[i] != NULL) {
11127ac6653aSJeff Kirsher 			dev_kfree_skb_any(priv->tx_skbuff[i]);
11137ac6653aSJeff Kirsher 			priv->tx_skbuff[i] = NULL;
11147ac6653aSJeff Kirsher 		}
11157ac6653aSJeff Kirsher 	}
11167ac6653aSJeff Kirsher }
11177ac6653aSJeff Kirsher 
111809f8d696SSrinivas Kandagatla static int alloc_dma_desc_resources(struct stmmac_priv *priv)
111909f8d696SSrinivas Kandagatla {
112009f8d696SSrinivas Kandagatla 	unsigned int txsize = priv->dma_tx_size;
112109f8d696SSrinivas Kandagatla 	unsigned int rxsize = priv->dma_rx_size;
112209f8d696SSrinivas Kandagatla 	int ret = -ENOMEM;
112309f8d696SSrinivas Kandagatla 
112409f8d696SSrinivas Kandagatla 	priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
112509f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
112609f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff_dma)
112709f8d696SSrinivas Kandagatla 		return -ENOMEM;
112809f8d696SSrinivas Kandagatla 
112909f8d696SSrinivas Kandagatla 	priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
113009f8d696SSrinivas Kandagatla 					GFP_KERNEL);
113109f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff)
113209f8d696SSrinivas Kandagatla 		goto err_rx_skbuff;
113309f8d696SSrinivas Kandagatla 
113409f8d696SSrinivas Kandagatla 	priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
113509f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
113609f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff_dma)
113709f8d696SSrinivas Kandagatla 		goto err_tx_skbuff_dma;
113809f8d696SSrinivas Kandagatla 
113909f8d696SSrinivas Kandagatla 	priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
114009f8d696SSrinivas Kandagatla 					GFP_KERNEL);
114109f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff)
114209f8d696SSrinivas Kandagatla 		goto err_tx_skbuff;
114309f8d696SSrinivas Kandagatla 
114409f8d696SSrinivas Kandagatla 	if (priv->extend_desc) {
114509f8d696SSrinivas Kandagatla 		priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
114609f8d696SSrinivas Kandagatla 						   sizeof(struct
114709f8d696SSrinivas Kandagatla 							  dma_extended_desc),
114809f8d696SSrinivas Kandagatla 						   &priv->dma_rx_phy,
114909f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
115009f8d696SSrinivas Kandagatla 		if (!priv->dma_erx)
115109f8d696SSrinivas Kandagatla 			goto err_dma;
115209f8d696SSrinivas Kandagatla 
115309f8d696SSrinivas Kandagatla 		priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
115409f8d696SSrinivas Kandagatla 						   sizeof(struct
115509f8d696SSrinivas Kandagatla 							  dma_extended_desc),
115609f8d696SSrinivas Kandagatla 						   &priv->dma_tx_phy,
115709f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
115809f8d696SSrinivas Kandagatla 		if (!priv->dma_etx) {
115909f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
116009f8d696SSrinivas Kandagatla 					sizeof(struct dma_extended_desc),
116109f8d696SSrinivas Kandagatla 					priv->dma_erx, priv->dma_rx_phy);
116209f8d696SSrinivas Kandagatla 			goto err_dma;
116309f8d696SSrinivas Kandagatla 		}
116409f8d696SSrinivas Kandagatla 	} else {
116509f8d696SSrinivas Kandagatla 		priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
116609f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
116709f8d696SSrinivas Kandagatla 						  &priv->dma_rx_phy,
116809f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
116909f8d696SSrinivas Kandagatla 		if (!priv->dma_rx)
117009f8d696SSrinivas Kandagatla 			goto err_dma;
117109f8d696SSrinivas Kandagatla 
117209f8d696SSrinivas Kandagatla 		priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
117309f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
117409f8d696SSrinivas Kandagatla 						  &priv->dma_tx_phy,
117509f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
117609f8d696SSrinivas Kandagatla 		if (!priv->dma_tx) {
117709f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
117809f8d696SSrinivas Kandagatla 					sizeof(struct dma_desc),
117909f8d696SSrinivas Kandagatla 					priv->dma_rx, priv->dma_rx_phy);
118009f8d696SSrinivas Kandagatla 			goto err_dma;
118109f8d696SSrinivas Kandagatla 		}
118209f8d696SSrinivas Kandagatla 	}
118309f8d696SSrinivas Kandagatla 
118409f8d696SSrinivas Kandagatla 	return 0;
118509f8d696SSrinivas Kandagatla 
118609f8d696SSrinivas Kandagatla err_dma:
118709f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff);
118809f8d696SSrinivas Kandagatla err_tx_skbuff:
118909f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff_dma);
119009f8d696SSrinivas Kandagatla err_tx_skbuff_dma:
119109f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff);
119209f8d696SSrinivas Kandagatla err_rx_skbuff:
119309f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff_dma);
119409f8d696SSrinivas Kandagatla 	return ret;
119509f8d696SSrinivas Kandagatla }
119609f8d696SSrinivas Kandagatla 
11977ac6653aSJeff Kirsher static void free_dma_desc_resources(struct stmmac_priv *priv)
11987ac6653aSJeff Kirsher {
11997ac6653aSJeff Kirsher 	/* Release the DMA TX/RX socket buffers */
12007ac6653aSJeff Kirsher 	dma_free_rx_skbufs(priv);
12017ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
12027ac6653aSJeff Kirsher 
1203ceb69499SGiuseppe CAVALLARO 	/* Free DMA regions of consistent memory previously allocated */
1204c24602efSGiuseppe CAVALLARO 	if (!priv->extend_desc) {
12057ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
12067ac6653aSJeff Kirsher 				  priv->dma_tx_size * sizeof(struct dma_desc),
12077ac6653aSJeff Kirsher 				  priv->dma_tx, priv->dma_tx_phy);
12087ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
12097ac6653aSJeff Kirsher 				  priv->dma_rx_size * sizeof(struct dma_desc),
12107ac6653aSJeff Kirsher 				  priv->dma_rx, priv->dma_rx_phy);
1211c24602efSGiuseppe CAVALLARO 	} else {
1212c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_tx_size *
1213c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1214c24602efSGiuseppe CAVALLARO 				  priv->dma_etx, priv->dma_tx_phy);
1215c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_rx_size *
1216c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1217c24602efSGiuseppe CAVALLARO 				  priv->dma_erx, priv->dma_rx_phy);
1218c24602efSGiuseppe CAVALLARO 	}
12197ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff_dma);
12207ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff);
1221cf32deecSRayagond Kokatanur 	kfree(priv->tx_skbuff_dma);
12227ac6653aSJeff Kirsher 	kfree(priv->tx_skbuff);
12237ac6653aSJeff Kirsher }
12247ac6653aSJeff Kirsher 
12257ac6653aSJeff Kirsher /**
12267ac6653aSJeff Kirsher  *  stmmac_dma_operation_mode - HW DMA operation mode
122732ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
12287ac6653aSJeff Kirsher  *  Description: it sets the DMA operation mode: tx/rx DMA thresholds
12297ac6653aSJeff Kirsher  *  or Store-And-Forward capability.
12307ac6653aSJeff Kirsher  */
12317ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
12327ac6653aSJeff Kirsher {
1233e2a240c7SSonic Zhang 	if (priv->plat->force_thresh_dma_mode)
1234e2a240c7SSonic Zhang 		priv->hw->dma->dma_mode(priv->ioaddr, tc, tc);
1235e2a240c7SSonic Zhang 	else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
12367ac6653aSJeff Kirsher 		/*
12377ac6653aSJeff Kirsher 		 * In case of GMAC, SF mode can be enabled
12387ac6653aSJeff Kirsher 		 * to perform the TX COE in HW. This depends on:
12397ac6653aSJeff Kirsher 		 * 1) TX COE if actually supported
12407ac6653aSJeff Kirsher 		 * 2) There is no bugged Jumbo frame support
12417ac6653aSJeff Kirsher 		 *    that needs to not insert csum in the TDES.
12427ac6653aSJeff Kirsher 		 */
1243ceb69499SGiuseppe CAVALLARO 		priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE);
12447ac6653aSJeff Kirsher 		tc = SF_DMA_MODE;
12457ac6653aSJeff Kirsher 	} else
12467ac6653aSJeff Kirsher 		priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
12477ac6653aSJeff Kirsher }
12487ac6653aSJeff Kirsher 
12497ac6653aSJeff Kirsher /**
12509125cdd1SGiuseppe CAVALLARO  * stmmac_tx_clean:
125132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
12527ac6653aSJeff Kirsher  * Description: it reclaims resources after transmission completes.
12537ac6653aSJeff Kirsher  */
12549125cdd1SGiuseppe CAVALLARO static void stmmac_tx_clean(struct stmmac_priv *priv)
12557ac6653aSJeff Kirsher {
12567ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
12577ac6653aSJeff Kirsher 
1258a9097a96SGiuseppe CAVALLARO 	spin_lock(&priv->tx_lock);
1259a9097a96SGiuseppe CAVALLARO 
12609125cdd1SGiuseppe CAVALLARO 	priv->xstats.tx_clean++;
12619125cdd1SGiuseppe CAVALLARO 
12627ac6653aSJeff Kirsher 	while (priv->dirty_tx != priv->cur_tx) {
12637ac6653aSJeff Kirsher 		int last;
12647ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_tx % txsize;
12657ac6653aSJeff Kirsher 		struct sk_buff *skb = priv->tx_skbuff[entry];
1266c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1267c24602efSGiuseppe CAVALLARO 
1268c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1269c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_etx + entry);
1270c24602efSGiuseppe CAVALLARO 		else
1271c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + entry;
12727ac6653aSJeff Kirsher 
12737ac6653aSJeff Kirsher 		/* Check if the descriptor is owned by the DMA. */
12747ac6653aSJeff Kirsher 		if (priv->hw->desc->get_tx_owner(p))
12757ac6653aSJeff Kirsher 			break;
12767ac6653aSJeff Kirsher 
1277c24602efSGiuseppe CAVALLARO 		/* Verify tx error by looking at the last segment. */
12787ac6653aSJeff Kirsher 		last = priv->hw->desc->get_tx_ls(p);
12797ac6653aSJeff Kirsher 		if (likely(last)) {
12807ac6653aSJeff Kirsher 			int tx_error =
12817ac6653aSJeff Kirsher 			    priv->hw->desc->tx_status(&priv->dev->stats,
12827ac6653aSJeff Kirsher 						      &priv->xstats, p,
12837ac6653aSJeff Kirsher 						      priv->ioaddr);
12847ac6653aSJeff Kirsher 			if (likely(tx_error == 0)) {
12857ac6653aSJeff Kirsher 				priv->dev->stats.tx_packets++;
12867ac6653aSJeff Kirsher 				priv->xstats.tx_pkt_n++;
12877ac6653aSJeff Kirsher 			} else
12887ac6653aSJeff Kirsher 				priv->dev->stats.tx_errors++;
1289891434b1SRayagond Kokatanur 
1290891434b1SRayagond Kokatanur 			stmmac_get_tx_hwtstamp(priv, entry, skb);
12917ac6653aSJeff Kirsher 		}
129283d7af64SGiuseppe CAVALLARO 		if (netif_msg_tx_done(priv))
129383d7af64SGiuseppe CAVALLARO 			pr_debug("%s: curr %d, dirty %d\n", __func__,
12947ac6653aSJeff Kirsher 				 priv->cur_tx, priv->dirty_tx);
12957ac6653aSJeff Kirsher 
1296cf32deecSRayagond Kokatanur 		if (likely(priv->tx_skbuff_dma[entry])) {
1297cf32deecSRayagond Kokatanur 			dma_unmap_single(priv->device,
1298cf32deecSRayagond Kokatanur 					 priv->tx_skbuff_dma[entry],
12997ac6653aSJeff Kirsher 					 priv->hw->desc->get_tx_len(p),
13007ac6653aSJeff Kirsher 					 DMA_TO_DEVICE);
1301cf32deecSRayagond Kokatanur 			priv->tx_skbuff_dma[entry] = 0;
1302cf32deecSRayagond Kokatanur 		}
130329896a67SGiuseppe CAVALLARO 		priv->hw->mode->clean_desc3(priv, p);
13047ac6653aSJeff Kirsher 
13057ac6653aSJeff Kirsher 		if (likely(skb != NULL)) {
13067c565c33SEric W. Biederman 			dev_consume_skb_any(skb);
13077ac6653aSJeff Kirsher 			priv->tx_skbuff[entry] = NULL;
13087ac6653aSJeff Kirsher 		}
13097ac6653aSJeff Kirsher 
13104a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->release_tx_desc(p, priv->mode);
13117ac6653aSJeff Kirsher 
131213497f58SGiuseppe CAVALLARO 		priv->dirty_tx++;
13137ac6653aSJeff Kirsher 	}
13147ac6653aSJeff Kirsher 	if (unlikely(netif_queue_stopped(priv->dev) &&
13157ac6653aSJeff Kirsher 		     stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv))) {
13167ac6653aSJeff Kirsher 		netif_tx_lock(priv->dev);
13177ac6653aSJeff Kirsher 		if (netif_queue_stopped(priv->dev) &&
13187ac6653aSJeff Kirsher 		    stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv)) {
131983d7af64SGiuseppe CAVALLARO 			if (netif_msg_tx_done(priv))
132083d7af64SGiuseppe CAVALLARO 				pr_debug("%s: restart transmit\n", __func__);
13217ac6653aSJeff Kirsher 			netif_wake_queue(priv->dev);
13227ac6653aSJeff Kirsher 		}
13237ac6653aSJeff Kirsher 		netif_tx_unlock(priv->dev);
13247ac6653aSJeff Kirsher 	}
1325d765955dSGiuseppe CAVALLARO 
1326d765955dSGiuseppe CAVALLARO 	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
1327d765955dSGiuseppe CAVALLARO 		stmmac_enable_eee_mode(priv);
1328f5351ef7SGiuseppe CAVALLARO 		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
1329d765955dSGiuseppe CAVALLARO 	}
1330a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
13317ac6653aSJeff Kirsher }
13327ac6653aSJeff Kirsher 
13339125cdd1SGiuseppe CAVALLARO static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv)
13347ac6653aSJeff Kirsher {
13357ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_irq(priv->ioaddr);
13367ac6653aSJeff Kirsher }
13377ac6653aSJeff Kirsher 
13389125cdd1SGiuseppe CAVALLARO static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
13397ac6653aSJeff Kirsher {
13407ac6653aSJeff Kirsher 	priv->hw->dma->disable_dma_irq(priv->ioaddr);
13417ac6653aSJeff Kirsher }
13427ac6653aSJeff Kirsher 
13437ac6653aSJeff Kirsher /**
134432ceabcaSGiuseppe CAVALLARO  * stmmac_tx_err: irq tx error mng function
134532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
13467ac6653aSJeff Kirsher  * Description: it cleans the descriptors and restarts the transmission
13477ac6653aSJeff Kirsher  * in case of errors.
13487ac6653aSJeff Kirsher  */
13497ac6653aSJeff Kirsher static void stmmac_tx_err(struct stmmac_priv *priv)
13507ac6653aSJeff Kirsher {
1351c24602efSGiuseppe CAVALLARO 	int i;
1352c24602efSGiuseppe CAVALLARO 	int txsize = priv->dma_tx_size;
13537ac6653aSJeff Kirsher 	netif_stop_queue(priv->dev);
13547ac6653aSJeff Kirsher 
13557ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
13567ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
1357c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
1358c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1359c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
1360c24602efSGiuseppe CAVALLARO 						     priv->mode,
1361c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
1362c24602efSGiuseppe CAVALLARO 		else
1363c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
1364c24602efSGiuseppe CAVALLARO 						     priv->mode,
1365c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
13667ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
13677ac6653aSJeff Kirsher 	priv->cur_tx = 0;
13687ac6653aSJeff Kirsher 	priv->hw->dma->start_tx(priv->ioaddr);
13697ac6653aSJeff Kirsher 
13707ac6653aSJeff Kirsher 	priv->dev->stats.tx_errors++;
13717ac6653aSJeff Kirsher 	netif_wake_queue(priv->dev);
13727ac6653aSJeff Kirsher }
13737ac6653aSJeff Kirsher 
137432ceabcaSGiuseppe CAVALLARO /**
137532ceabcaSGiuseppe CAVALLARO  * stmmac_dma_interrupt: DMA ISR
137632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
137732ceabcaSGiuseppe CAVALLARO  * Description: this is the DMA ISR. It is called by the main ISR.
137832ceabcaSGiuseppe CAVALLARO  * It calls the dwmac dma routine to understand which type of interrupt
137932ceabcaSGiuseppe CAVALLARO  * happened. In case of there is a Normal interrupt and either TX or RX
138032ceabcaSGiuseppe CAVALLARO  * interrupt happened so the NAPI is scheduled.
138132ceabcaSGiuseppe CAVALLARO  */
13827ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv)
13837ac6653aSJeff Kirsher {
13847ac6653aSJeff Kirsher 	int status;
13857ac6653aSJeff Kirsher 
13867ac6653aSJeff Kirsher 	status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
13879125cdd1SGiuseppe CAVALLARO 	if (likely((status & handle_rx)) || (status & handle_tx)) {
13889125cdd1SGiuseppe CAVALLARO 		if (likely(napi_schedule_prep(&priv->napi))) {
13899125cdd1SGiuseppe CAVALLARO 			stmmac_disable_dma_irq(priv);
13909125cdd1SGiuseppe CAVALLARO 			__napi_schedule(&priv->napi);
13919125cdd1SGiuseppe CAVALLARO 		}
13929125cdd1SGiuseppe CAVALLARO 	}
13939125cdd1SGiuseppe CAVALLARO 	if (unlikely(status & tx_hard_error_bump_tc)) {
13947ac6653aSJeff Kirsher 		/* Try to bump up the dma threshold on this failure */
13957ac6653aSJeff Kirsher 		if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
13967ac6653aSJeff Kirsher 			tc += 64;
13977ac6653aSJeff Kirsher 			priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
13987ac6653aSJeff Kirsher 			priv->xstats.threshold = tc;
13997ac6653aSJeff Kirsher 		}
14007ac6653aSJeff Kirsher 	} else if (unlikely(status == tx_hard_error))
14017ac6653aSJeff Kirsher 		stmmac_tx_err(priv);
14027ac6653aSJeff Kirsher }
14037ac6653aSJeff Kirsher 
140432ceabcaSGiuseppe CAVALLARO /**
140532ceabcaSGiuseppe CAVALLARO  * stmmac_mmc_setup: setup the Mac Management Counters (MMC)
140632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
140732ceabcaSGiuseppe CAVALLARO  * Description: this masks the MMC irq, in fact, the counters are managed in SW.
140832ceabcaSGiuseppe CAVALLARO  */
14091c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv)
14101c901a46SGiuseppe CAVALLARO {
14111c901a46SGiuseppe CAVALLARO 	unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
14121c901a46SGiuseppe CAVALLARO 	    MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
14131c901a46SGiuseppe CAVALLARO 
14141c901a46SGiuseppe CAVALLARO 	dwmac_mmc_intr_all_mask(priv->ioaddr);
14154f795b25SGiuseppe CAVALLARO 
14164f795b25SGiuseppe CAVALLARO 	if (priv->dma_cap.rmon) {
14171c901a46SGiuseppe CAVALLARO 		dwmac_mmc_ctrl(priv->ioaddr, mode);
14181c901a46SGiuseppe CAVALLARO 		memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
14194f795b25SGiuseppe CAVALLARO 	} else
1420aae54cffSStefan Roese 		pr_info(" No MAC Management Counters available\n");
14211c901a46SGiuseppe CAVALLARO }
14221c901a46SGiuseppe CAVALLARO 
1423f0b9d786SGiuseppe CAVALLARO static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
1424f0b9d786SGiuseppe CAVALLARO {
1425f0b9d786SGiuseppe CAVALLARO 	u32 hwid = priv->hw->synopsys_uid;
1426f0b9d786SGiuseppe CAVALLARO 
1427ceb69499SGiuseppe CAVALLARO 	/* Check Synopsys Id (not available on old chips) */
1428f0b9d786SGiuseppe CAVALLARO 	if (likely(hwid)) {
1429f0b9d786SGiuseppe CAVALLARO 		u32 uid = ((hwid & 0x0000ff00) >> 8);
1430f0b9d786SGiuseppe CAVALLARO 		u32 synid = (hwid & 0x000000ff);
1431f0b9d786SGiuseppe CAVALLARO 
1432cf3f047bSGiuseppe CAVALLARO 		pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n",
1433f0b9d786SGiuseppe CAVALLARO 			uid, synid);
1434f0b9d786SGiuseppe CAVALLARO 
1435f0b9d786SGiuseppe CAVALLARO 		return synid;
1436f0b9d786SGiuseppe CAVALLARO 	}
1437f0b9d786SGiuseppe CAVALLARO 	return 0;
1438f0b9d786SGiuseppe CAVALLARO }
1439e7434821SGiuseppe CAVALLARO 
144019e30c14SGiuseppe CAVALLARO /**
144132ceabcaSGiuseppe CAVALLARO  * stmmac_selec_desc_mode: to select among: normal/alternate/extend descriptors
144232ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
144332ceabcaSGiuseppe CAVALLARO  * Description: select the Enhanced/Alternate or Normal descriptors.
144432ceabcaSGiuseppe CAVALLARO  * In case of Enhanced/Alternate, it looks at the extended descriptors are
144532ceabcaSGiuseppe CAVALLARO  * supported by the HW cap. register.
1446ff3dd78cSGiuseppe CAVALLARO  */
144719e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
144819e30c14SGiuseppe CAVALLARO {
144919e30c14SGiuseppe CAVALLARO 	if (priv->plat->enh_desc) {
145019e30c14SGiuseppe CAVALLARO 		pr_info(" Enhanced/Alternate descriptors\n");
1451c24602efSGiuseppe CAVALLARO 
1452c24602efSGiuseppe CAVALLARO 		/* GMAC older than 3.50 has no extended descriptors */
1453c24602efSGiuseppe CAVALLARO 		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
1454c24602efSGiuseppe CAVALLARO 			pr_info("\tEnabled extended descriptors\n");
1455c24602efSGiuseppe CAVALLARO 			priv->extend_desc = 1;
1456c24602efSGiuseppe CAVALLARO 		} else
1457c24602efSGiuseppe CAVALLARO 			pr_warn("Extended descriptors not supported\n");
1458c24602efSGiuseppe CAVALLARO 
145919e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &enh_desc_ops;
146019e30c14SGiuseppe CAVALLARO 	} else {
146119e30c14SGiuseppe CAVALLARO 		pr_info(" Normal descriptors\n");
146219e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &ndesc_ops;
146319e30c14SGiuseppe CAVALLARO 	}
146419e30c14SGiuseppe CAVALLARO }
146519e30c14SGiuseppe CAVALLARO 
146619e30c14SGiuseppe CAVALLARO /**
146732ceabcaSGiuseppe CAVALLARO  * stmmac_get_hw_features: get MAC capabilities from the HW cap. register.
146832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
146919e30c14SGiuseppe CAVALLARO  * Description:
147019e30c14SGiuseppe CAVALLARO  *  new GMAC chip generations have a new register to indicate the
1471e7434821SGiuseppe CAVALLARO  *  presence of the optional feature/functions.
147219e30c14SGiuseppe CAVALLARO  *  This can be also used to override the value passed through the
147319e30c14SGiuseppe CAVALLARO  *  platform and necessary for old MAC10/100 and GMAC chips.
1474e7434821SGiuseppe CAVALLARO  */
1475e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv)
1476e7434821SGiuseppe CAVALLARO {
14775e6efe88SGiuseppe CAVALLARO 	u32 hw_cap = 0;
14783c20f72fSGiuseppe CAVALLARO 
14795e6efe88SGiuseppe CAVALLARO 	if (priv->hw->dma->get_hw_feature) {
14805e6efe88SGiuseppe CAVALLARO 		hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
1481e7434821SGiuseppe CAVALLARO 
14821db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
14831db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
14841db123fbSRayagond Kokatanur 		priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
14851db123fbSRayagond Kokatanur 		priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
1486ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
14871db123fbSRayagond Kokatanur 		priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
14881db123fbSRayagond Kokatanur 		priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
14891db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_remote_wake_up =
14901db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
14911db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_magic_frame =
14921db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
14931db123fbSRayagond Kokatanur 		/* MMC */
14941db123fbSRayagond Kokatanur 		priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
1495e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2002 */
14961db123fbSRayagond Kokatanur 		priv->dma_cap.time_stamp =
14971db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
1498e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2008 */
14991db123fbSRayagond Kokatanur 		priv->dma_cap.atime_stamp =
15001db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
1501e7434821SGiuseppe CAVALLARO 		/* 802.3az - Energy-Efficient Ethernet (EEE) */
15021db123fbSRayagond Kokatanur 		priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
15031db123fbSRayagond Kokatanur 		priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
1504e7434821SGiuseppe CAVALLARO 		/* TX and RX csum */
15051db123fbSRayagond Kokatanur 		priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
15061db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type1 =
15071db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
15081db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type2 =
15091db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
15101db123fbSRayagond Kokatanur 		priv->dma_cap.rxfifo_over_2048 =
15111db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
1512e7434821SGiuseppe CAVALLARO 		/* TX and RX number of channels */
15131db123fbSRayagond Kokatanur 		priv->dma_cap.number_rx_channel =
15141db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
15151db123fbSRayagond Kokatanur 		priv->dma_cap.number_tx_channel =
15161db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
1517e7434821SGiuseppe CAVALLARO 		/* Alternate (enhanced) DESC mode */
1518ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
151919e30c14SGiuseppe CAVALLARO 	}
1520e7434821SGiuseppe CAVALLARO 
1521e7434821SGiuseppe CAVALLARO 	return hw_cap;
1522e7434821SGiuseppe CAVALLARO }
1523e7434821SGiuseppe CAVALLARO 
152432ceabcaSGiuseppe CAVALLARO /**
152532ceabcaSGiuseppe CAVALLARO  * stmmac_check_ether_addr: check if the MAC addr is valid
152632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
152732ceabcaSGiuseppe CAVALLARO  * Description:
152832ceabcaSGiuseppe CAVALLARO  * it is to verify if the MAC address is valid, in case of failures it
152932ceabcaSGiuseppe CAVALLARO  * generates a random MAC address
153032ceabcaSGiuseppe CAVALLARO  */
1531bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv)
1532bfab27a1SGiuseppe CAVALLARO {
1533bfab27a1SGiuseppe CAVALLARO 	if (!is_valid_ether_addr(priv->dev->dev_addr)) {
1534bfab27a1SGiuseppe CAVALLARO 		priv->hw->mac->get_umac_addr((void __iomem *)
1535bfab27a1SGiuseppe CAVALLARO 					     priv->dev->base_addr,
1536bfab27a1SGiuseppe CAVALLARO 					     priv->dev->dev_addr, 0);
1537bfab27a1SGiuseppe CAVALLARO 		if (!is_valid_ether_addr(priv->dev->dev_addr))
1538f2cedb63SDanny Kukawka 			eth_hw_addr_random(priv->dev);
1539c88460b7SHans de Goede 		pr_info("%s: device MAC address %pM\n", priv->dev->name,
1540bfab27a1SGiuseppe CAVALLARO 			priv->dev->dev_addr);
1541bfab27a1SGiuseppe CAVALLARO 	}
1542c88460b7SHans de Goede }
1543bfab27a1SGiuseppe CAVALLARO 
154432ceabcaSGiuseppe CAVALLARO /**
154532ceabcaSGiuseppe CAVALLARO  * stmmac_init_dma_engine: DMA init.
154632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
154732ceabcaSGiuseppe CAVALLARO  * Description:
154832ceabcaSGiuseppe CAVALLARO  * It inits the DMA invoking the specific MAC/GMAC callback.
154932ceabcaSGiuseppe CAVALLARO  * Some DMA parameters can be passed from the platform;
155032ceabcaSGiuseppe CAVALLARO  * in case of these are not passed a default is kept for the MAC or GMAC.
155132ceabcaSGiuseppe CAVALLARO  */
15520f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv)
15530f1f88a8SGiuseppe CAVALLARO {
15540f1f88a8SGiuseppe CAVALLARO 	int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0;
1555b9cde0a8SGiuseppe CAVALLARO 	int mixed_burst = 0;
1556c24602efSGiuseppe CAVALLARO 	int atds = 0;
15570f1f88a8SGiuseppe CAVALLARO 
15580f1f88a8SGiuseppe CAVALLARO 	if (priv->plat->dma_cfg) {
15590f1f88a8SGiuseppe CAVALLARO 		pbl = priv->plat->dma_cfg->pbl;
15600f1f88a8SGiuseppe CAVALLARO 		fixed_burst = priv->plat->dma_cfg->fixed_burst;
1561b9cde0a8SGiuseppe CAVALLARO 		mixed_burst = priv->plat->dma_cfg->mixed_burst;
15620f1f88a8SGiuseppe CAVALLARO 		burst_len = priv->plat->dma_cfg->burst_len;
15630f1f88a8SGiuseppe CAVALLARO 	}
15640f1f88a8SGiuseppe CAVALLARO 
1565c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
1566c24602efSGiuseppe CAVALLARO 		atds = 1;
1567c24602efSGiuseppe CAVALLARO 
1568b9cde0a8SGiuseppe CAVALLARO 	return priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst,
15690f1f88a8SGiuseppe CAVALLARO 				   burst_len, priv->dma_tx_phy,
1570c24602efSGiuseppe CAVALLARO 				   priv->dma_rx_phy, atds);
15710f1f88a8SGiuseppe CAVALLARO }
15720f1f88a8SGiuseppe CAVALLARO 
1573bfab27a1SGiuseppe CAVALLARO /**
157432ceabcaSGiuseppe CAVALLARO  * stmmac_tx_timer: mitigation sw timer for tx.
15759125cdd1SGiuseppe CAVALLARO  * @data: data pointer
15769125cdd1SGiuseppe CAVALLARO  * Description:
15779125cdd1SGiuseppe CAVALLARO  * This is the timer handler to directly invoke the stmmac_tx_clean.
15789125cdd1SGiuseppe CAVALLARO  */
15799125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data)
15809125cdd1SGiuseppe CAVALLARO {
15819125cdd1SGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)data;
15829125cdd1SGiuseppe CAVALLARO 
15839125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
15849125cdd1SGiuseppe CAVALLARO }
15859125cdd1SGiuseppe CAVALLARO 
15869125cdd1SGiuseppe CAVALLARO /**
158732ceabcaSGiuseppe CAVALLARO  * stmmac_init_tx_coalesce: init tx mitigation options.
158832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
15899125cdd1SGiuseppe CAVALLARO  * Description:
15909125cdd1SGiuseppe CAVALLARO  * This inits the transmit coalesce parameters: i.e. timer rate,
15919125cdd1SGiuseppe CAVALLARO  * timer handler and default threshold used for enabling the
15929125cdd1SGiuseppe CAVALLARO  * interrupt on completion bit.
15939125cdd1SGiuseppe CAVALLARO  */
15949125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
15959125cdd1SGiuseppe CAVALLARO {
15969125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_frames = STMMAC_TX_FRAMES;
15979125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
15989125cdd1SGiuseppe CAVALLARO 	init_timer(&priv->txtimer);
15999125cdd1SGiuseppe CAVALLARO 	priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
16009125cdd1SGiuseppe CAVALLARO 	priv->txtimer.data = (unsigned long)priv;
16019125cdd1SGiuseppe CAVALLARO 	priv->txtimer.function = stmmac_tx_timer;
16029125cdd1SGiuseppe CAVALLARO 	add_timer(&priv->txtimer);
16039125cdd1SGiuseppe CAVALLARO }
16049125cdd1SGiuseppe CAVALLARO 
16059125cdd1SGiuseppe CAVALLARO /**
1606523f11b5SSrinivas Kandagatla  * stmmac_hw_setup: setup mac in a usable state.
1607523f11b5SSrinivas Kandagatla  *  @dev : pointer to the device structure.
1608523f11b5SSrinivas Kandagatla  *  Description:
1609523f11b5SSrinivas Kandagatla  *  This function sets up the ip in a usable state.
1610523f11b5SSrinivas Kandagatla  *  Return value:
1611523f11b5SSrinivas Kandagatla  *  0 on success and an appropriate (-)ve integer as defined in errno.h
1612523f11b5SSrinivas Kandagatla  *  file on failure.
1613523f11b5SSrinivas Kandagatla  */
1614523f11b5SSrinivas Kandagatla static int stmmac_hw_setup(struct net_device *dev)
1615523f11b5SSrinivas Kandagatla {
1616523f11b5SSrinivas Kandagatla 	struct stmmac_priv *priv = netdev_priv(dev);
1617523f11b5SSrinivas Kandagatla 	int ret;
1618523f11b5SSrinivas Kandagatla 
1619523f11b5SSrinivas Kandagatla 	ret = init_dma_desc_rings(dev);
1620523f11b5SSrinivas Kandagatla 	if (ret < 0) {
1621523f11b5SSrinivas Kandagatla 		pr_err("%s: DMA descriptors initialization failed\n", __func__);
1622523f11b5SSrinivas Kandagatla 		return ret;
1623523f11b5SSrinivas Kandagatla 	}
1624523f11b5SSrinivas Kandagatla 	/* DMA initialization and SW reset */
1625523f11b5SSrinivas Kandagatla 	ret = stmmac_init_dma_engine(priv);
1626523f11b5SSrinivas Kandagatla 	if (ret < 0) {
1627523f11b5SSrinivas Kandagatla 		pr_err("%s: DMA engine initialization failed\n", __func__);
1628523f11b5SSrinivas Kandagatla 		return ret;
1629523f11b5SSrinivas Kandagatla 	}
1630523f11b5SSrinivas Kandagatla 
1631523f11b5SSrinivas Kandagatla 	/* Copy the MAC addr into the HW  */
1632523f11b5SSrinivas Kandagatla 	priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
1633523f11b5SSrinivas Kandagatla 
1634523f11b5SSrinivas Kandagatla 	/* If required, perform hw setup of the bus. */
1635523f11b5SSrinivas Kandagatla 	if (priv->plat->bus_setup)
1636523f11b5SSrinivas Kandagatla 		priv->plat->bus_setup(priv->ioaddr);
1637523f11b5SSrinivas Kandagatla 
1638523f11b5SSrinivas Kandagatla 	/* Initialize the MAC Core */
16392618abb7SVince Bridgers 	priv->hw->mac->core_init(priv->ioaddr, dev->mtu);
1640523f11b5SSrinivas Kandagatla 
1641523f11b5SSrinivas Kandagatla 	/* Enable the MAC Rx/Tx */
1642523f11b5SSrinivas Kandagatla 	stmmac_set_mac(priv->ioaddr, true);
1643523f11b5SSrinivas Kandagatla 
1644523f11b5SSrinivas Kandagatla 	/* Set the HW DMA mode and the COE */
1645523f11b5SSrinivas Kandagatla 	stmmac_dma_operation_mode(priv);
1646523f11b5SSrinivas Kandagatla 
1647523f11b5SSrinivas Kandagatla 	stmmac_mmc_setup(priv);
1648523f11b5SSrinivas Kandagatla 
1649523f11b5SSrinivas Kandagatla 	ret = stmmac_init_ptp(priv);
16507509edd6SHans de Goede 	if (ret && ret != -EOPNOTSUPP)
1651523f11b5SSrinivas Kandagatla 		pr_warn("%s: failed PTP initialisation\n", __func__);
1652523f11b5SSrinivas Kandagatla 
1653523f11b5SSrinivas Kandagatla #ifdef CONFIG_STMMAC_DEBUG_FS
1654523f11b5SSrinivas Kandagatla 	ret = stmmac_init_fs(dev);
1655523f11b5SSrinivas Kandagatla 	if (ret < 0)
1656523f11b5SSrinivas Kandagatla 		pr_warn("%s: failed debugFS registration\n", __func__);
1657523f11b5SSrinivas Kandagatla #endif
1658523f11b5SSrinivas Kandagatla 	/* Start the ball rolling... */
1659523f11b5SSrinivas Kandagatla 	pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
1660523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_tx(priv->ioaddr);
1661523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_rx(priv->ioaddr);
1662523f11b5SSrinivas Kandagatla 
1663523f11b5SSrinivas Kandagatla 	/* Dump DMA/MAC registers */
1664523f11b5SSrinivas Kandagatla 	if (netif_msg_hw(priv)) {
1665523f11b5SSrinivas Kandagatla 		priv->hw->mac->dump_regs(priv->ioaddr);
1666523f11b5SSrinivas Kandagatla 		priv->hw->dma->dump_regs(priv->ioaddr);
1667523f11b5SSrinivas Kandagatla 	}
1668523f11b5SSrinivas Kandagatla 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
1669523f11b5SSrinivas Kandagatla 
1670523f11b5SSrinivas Kandagatla 	priv->eee_enabled = stmmac_eee_init(priv);
1671523f11b5SSrinivas Kandagatla 
1672523f11b5SSrinivas Kandagatla 	stmmac_init_tx_coalesce(priv);
1673523f11b5SSrinivas Kandagatla 
1674523f11b5SSrinivas Kandagatla 	if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
1675523f11b5SSrinivas Kandagatla 		priv->rx_riwt = MAX_DMA_RIWT;
1676523f11b5SSrinivas Kandagatla 		priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
1677523f11b5SSrinivas Kandagatla 	}
1678523f11b5SSrinivas Kandagatla 
1679523f11b5SSrinivas Kandagatla 	if (priv->pcs && priv->hw->mac->ctrl_ane)
1680523f11b5SSrinivas Kandagatla 		priv->hw->mac->ctrl_ane(priv->ioaddr, 0);
1681523f11b5SSrinivas Kandagatla 
1682523f11b5SSrinivas Kandagatla 	return 0;
1683523f11b5SSrinivas Kandagatla }
1684523f11b5SSrinivas Kandagatla 
1685523f11b5SSrinivas Kandagatla /**
16867ac6653aSJeff Kirsher  *  stmmac_open - open entry point of the driver
16877ac6653aSJeff Kirsher  *  @dev : pointer to the device structure.
16887ac6653aSJeff Kirsher  *  Description:
16897ac6653aSJeff Kirsher  *  This function is the open entry point of the driver.
16907ac6653aSJeff Kirsher  *  Return value:
16917ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
16927ac6653aSJeff Kirsher  *  file on failure.
16937ac6653aSJeff Kirsher  */
16947ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev)
16957ac6653aSJeff Kirsher {
16967ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
16977ac6653aSJeff Kirsher 	int ret;
16987ac6653aSJeff Kirsher 
16994bfcbd7aSFrancesco Virlinzi 	stmmac_check_ether_addr(priv);
17004bfcbd7aSFrancesco Virlinzi 
17014d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
17024d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
17037ac6653aSJeff Kirsher 		ret = stmmac_init_phy(dev);
1704e58bb43fSGiuseppe CAVALLARO 		if (ret) {
1705e58bb43fSGiuseppe CAVALLARO 			pr_err("%s: Cannot attach to PHY (error: %d)\n",
1706e58bb43fSGiuseppe CAVALLARO 			       __func__, ret);
170789df20d9SHans de Goede 			return ret;
17087ac6653aSJeff Kirsher 		}
1709e58bb43fSGiuseppe CAVALLARO 	}
17107ac6653aSJeff Kirsher 
1711523f11b5SSrinivas Kandagatla 	/* Extra statistics */
1712523f11b5SSrinivas Kandagatla 	memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
1713523f11b5SSrinivas Kandagatla 	priv->xstats.threshold = tc;
1714523f11b5SSrinivas Kandagatla 
17157ac6653aSJeff Kirsher 	/* Create and initialize the TX/RX descriptors chains. */
17167ac6653aSJeff Kirsher 	priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
17177ac6653aSJeff Kirsher 	priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
17187ac6653aSJeff Kirsher 	priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
171956329137SBartlomiej Zolnierkiewicz 
17207262b7b2STobias Klauser 	ret = alloc_dma_desc_resources(priv);
172109f8d696SSrinivas Kandagatla 	if (ret < 0) {
172209f8d696SSrinivas Kandagatla 		pr_err("%s: DMA descriptors allocation failed\n", __func__);
172309f8d696SSrinivas Kandagatla 		goto dma_desc_error;
172409f8d696SSrinivas Kandagatla 	}
172509f8d696SSrinivas Kandagatla 
1726523f11b5SSrinivas Kandagatla 	ret = stmmac_hw_setup(dev);
172756329137SBartlomiej Zolnierkiewicz 	if (ret < 0) {
1728523f11b5SSrinivas Kandagatla 		pr_err("%s: Hw setup failed\n", __func__);
1729c9324d18SGiuseppe CAVALLARO 		goto init_error;
17307ac6653aSJeff Kirsher 	}
17317ac6653aSJeff Kirsher 
1732523f11b5SSrinivas Kandagatla 	if (priv->phydev)
1733523f11b5SSrinivas Kandagatla 		phy_start(priv->phydev);
17347ac6653aSJeff Kirsher 
17357ac6653aSJeff Kirsher 	/* Request the IRQ lines */
17367ac6653aSJeff Kirsher 	ret = request_irq(dev->irq, stmmac_interrupt,
17377ac6653aSJeff Kirsher 			  IRQF_SHARED, dev->name, dev);
17387ac6653aSJeff Kirsher 	if (unlikely(ret < 0)) {
17397ac6653aSJeff Kirsher 		pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
17407ac6653aSJeff Kirsher 		       __func__, dev->irq, ret);
1741c9324d18SGiuseppe CAVALLARO 		goto init_error;
17427ac6653aSJeff Kirsher 	}
17437ac6653aSJeff Kirsher 
17447a13f8f5SFrancesco Virlinzi 	/* Request the Wake IRQ in case of another line is used for WoL */
17457a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq) {
17467a13f8f5SFrancesco Virlinzi 		ret = request_irq(priv->wol_irq, stmmac_interrupt,
17477a13f8f5SFrancesco Virlinzi 				  IRQF_SHARED, dev->name, dev);
17487a13f8f5SFrancesco Virlinzi 		if (unlikely(ret < 0)) {
1749ceb69499SGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n",
1750ceb69499SGiuseppe CAVALLARO 			       __func__, priv->wol_irq, ret);
1751c9324d18SGiuseppe CAVALLARO 			goto wolirq_error;
17527a13f8f5SFrancesco Virlinzi 		}
17537a13f8f5SFrancesco Virlinzi 	}
17547a13f8f5SFrancesco Virlinzi 
1755d765955dSGiuseppe CAVALLARO 	/* Request the IRQ lines */
1756d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0) {
1757d765955dSGiuseppe CAVALLARO 		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
1758d765955dSGiuseppe CAVALLARO 				  dev->name, dev);
1759d765955dSGiuseppe CAVALLARO 		if (unlikely(ret < 0)) {
1760d765955dSGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
1761d765955dSGiuseppe CAVALLARO 			       __func__, priv->lpi_irq, ret);
1762c9324d18SGiuseppe CAVALLARO 			goto lpiirq_error;
1763d765955dSGiuseppe CAVALLARO 		}
1764d765955dSGiuseppe CAVALLARO 	}
1765d765955dSGiuseppe CAVALLARO 
17667ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
17677ac6653aSJeff Kirsher 	netif_start_queue(dev);
17687ac6653aSJeff Kirsher 
17697ac6653aSJeff Kirsher 	return 0;
17707ac6653aSJeff Kirsher 
1771c9324d18SGiuseppe CAVALLARO lpiirq_error:
1772d765955dSGiuseppe CAVALLARO 	if (priv->wol_irq != dev->irq)
1773d765955dSGiuseppe CAVALLARO 		free_irq(priv->wol_irq, dev);
1774c9324d18SGiuseppe CAVALLARO wolirq_error:
17757a13f8f5SFrancesco Virlinzi 	free_irq(dev->irq, dev);
17767a13f8f5SFrancesco Virlinzi 
1777c9324d18SGiuseppe CAVALLARO init_error:
1778c9324d18SGiuseppe CAVALLARO 	free_dma_desc_resources(priv);
177956329137SBartlomiej Zolnierkiewicz dma_desc_error:
17807ac6653aSJeff Kirsher 	if (priv->phydev)
17817ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
17824bfcbd7aSFrancesco Virlinzi 
17837ac6653aSJeff Kirsher 	return ret;
17847ac6653aSJeff Kirsher }
17857ac6653aSJeff Kirsher 
17867ac6653aSJeff Kirsher /**
17877ac6653aSJeff Kirsher  *  stmmac_release - close entry point of the driver
17887ac6653aSJeff Kirsher  *  @dev : device pointer.
17897ac6653aSJeff Kirsher  *  Description:
17907ac6653aSJeff Kirsher  *  This is the stop entry point of the driver.
17917ac6653aSJeff Kirsher  */
17927ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev)
17937ac6653aSJeff Kirsher {
17947ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
17957ac6653aSJeff Kirsher 
1796d765955dSGiuseppe CAVALLARO 	if (priv->eee_enabled)
1797d765955dSGiuseppe CAVALLARO 		del_timer_sync(&priv->eee_ctrl_timer);
1798d765955dSGiuseppe CAVALLARO 
17997ac6653aSJeff Kirsher 	/* Stop and disconnect the PHY */
18007ac6653aSJeff Kirsher 	if (priv->phydev) {
18017ac6653aSJeff Kirsher 		phy_stop(priv->phydev);
18027ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
18037ac6653aSJeff Kirsher 		priv->phydev = NULL;
18047ac6653aSJeff Kirsher 	}
18057ac6653aSJeff Kirsher 
18067ac6653aSJeff Kirsher 	netif_stop_queue(dev);
18077ac6653aSJeff Kirsher 
18087ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
18097ac6653aSJeff Kirsher 
18109125cdd1SGiuseppe CAVALLARO 	del_timer_sync(&priv->txtimer);
18119125cdd1SGiuseppe CAVALLARO 
18127ac6653aSJeff Kirsher 	/* Free the IRQ lines */
18137ac6653aSJeff Kirsher 	free_irq(dev->irq, dev);
18147a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq)
18157a13f8f5SFrancesco Virlinzi 		free_irq(priv->wol_irq, dev);
1816d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0)
1817d765955dSGiuseppe CAVALLARO 		free_irq(priv->lpi_irq, dev);
18187ac6653aSJeff Kirsher 
18197ac6653aSJeff Kirsher 	/* Stop TX/RX DMA and clear the descriptors */
18207ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
18217ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
18227ac6653aSJeff Kirsher 
18237ac6653aSJeff Kirsher 	/* Release and free the Rx/Tx resources */
18247ac6653aSJeff Kirsher 	free_dma_desc_resources(priv);
18257ac6653aSJeff Kirsher 
18267ac6653aSJeff Kirsher 	/* Disable the MAC Rx/Tx */
1827bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
18287ac6653aSJeff Kirsher 
18297ac6653aSJeff Kirsher 	netif_carrier_off(dev);
18307ac6653aSJeff Kirsher 
1831bfab27a1SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_DEBUG_FS
1832bfab27a1SGiuseppe CAVALLARO 	stmmac_exit_fs();
1833bfab27a1SGiuseppe CAVALLARO #endif
1834bfab27a1SGiuseppe CAVALLARO 
183592ba6888SRayagond Kokatanur 	stmmac_release_ptp(priv);
183692ba6888SRayagond Kokatanur 
18377ac6653aSJeff Kirsher 	return 0;
18387ac6653aSJeff Kirsher }
18397ac6653aSJeff Kirsher 
18407ac6653aSJeff Kirsher /**
184132ceabcaSGiuseppe CAVALLARO  *  stmmac_xmit: Tx entry point of the driver
18427ac6653aSJeff Kirsher  *  @skb : the socket buffer
18437ac6653aSJeff Kirsher  *  @dev : device pointer
184432ceabcaSGiuseppe CAVALLARO  *  Description : this is the tx entry point of the driver.
184532ceabcaSGiuseppe CAVALLARO  *  It programs the chain or the ring and supports oversized frames
184632ceabcaSGiuseppe CAVALLARO  *  and SG feature.
18477ac6653aSJeff Kirsher  */
18487ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
18497ac6653aSJeff Kirsher {
18507ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
18517ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
18527ac6653aSJeff Kirsher 	unsigned int entry;
18534a7d666aSGiuseppe CAVALLARO 	int i, csum_insertion = 0, is_jumbo = 0;
18547ac6653aSJeff Kirsher 	int nfrags = skb_shinfo(skb)->nr_frags;
18557ac6653aSJeff Kirsher 	struct dma_desc *desc, *first;
1856286a8372SGiuseppe CAVALLARO 	unsigned int nopaged_len = skb_headlen(skb);
185729896a67SGiuseppe CAVALLARO 	unsigned int enh_desc = priv->plat->enh_desc;
18587ac6653aSJeff Kirsher 
18597ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
18607ac6653aSJeff Kirsher 		if (!netif_queue_stopped(dev)) {
18617ac6653aSJeff Kirsher 			netif_stop_queue(dev);
18627ac6653aSJeff Kirsher 			/* This is a hard error, log it. */
1863ceb69499SGiuseppe CAVALLARO 			pr_err("%s: Tx Ring full when queue awake\n", __func__);
18647ac6653aSJeff Kirsher 		}
18657ac6653aSJeff Kirsher 		return NETDEV_TX_BUSY;
18667ac6653aSJeff Kirsher 	}
18677ac6653aSJeff Kirsher 
1868a9097a96SGiuseppe CAVALLARO 	spin_lock(&priv->tx_lock);
1869a9097a96SGiuseppe CAVALLARO 
1870d765955dSGiuseppe CAVALLARO 	if (priv->tx_path_in_lpi_mode)
1871d765955dSGiuseppe CAVALLARO 		stmmac_disable_eee_mode(priv);
1872d765955dSGiuseppe CAVALLARO 
18737ac6653aSJeff Kirsher 	entry = priv->cur_tx % txsize;
18747ac6653aSJeff Kirsher 
18757ac6653aSJeff Kirsher 	csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
18767ac6653aSJeff Kirsher 
1877c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc)
1878c24602efSGiuseppe CAVALLARO 		desc = (struct dma_desc *)(priv->dma_etx + entry);
1879c24602efSGiuseppe CAVALLARO 	else
18807ac6653aSJeff Kirsher 		desc = priv->dma_tx + entry;
1881c24602efSGiuseppe CAVALLARO 
18827ac6653aSJeff Kirsher 	first = desc;
18837ac6653aSJeff Kirsher 
18844a7d666aSGiuseppe CAVALLARO 	/* To program the descriptors according to the size of the frame */
188529896a67SGiuseppe CAVALLARO 	if (enh_desc)
188629896a67SGiuseppe CAVALLARO 		is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc);
188729896a67SGiuseppe CAVALLARO 
18884a7d666aSGiuseppe CAVALLARO 	if (likely(!is_jumbo)) {
18897ac6653aSJeff Kirsher 		desc->des2 = dma_map_single(priv->device, skb->data,
18907ac6653aSJeff Kirsher 					    nopaged_len, DMA_TO_DEVICE);
1891cf32deecSRayagond Kokatanur 		priv->tx_skbuff_dma[entry] = desc->des2;
18927ac6653aSJeff Kirsher 		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
18934a7d666aSGiuseppe CAVALLARO 						csum_insertion, priv->mode);
189429896a67SGiuseppe CAVALLARO 	} else {
1895c24602efSGiuseppe CAVALLARO 		desc = first;
189629896a67SGiuseppe CAVALLARO 		entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion);
189729896a67SGiuseppe CAVALLARO 	}
18987ac6653aSJeff Kirsher 
18997ac6653aSJeff Kirsher 	for (i = 0; i < nfrags; i++) {
19009e903e08SEric Dumazet 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
19019e903e08SEric Dumazet 		int len = skb_frag_size(frag);
19027ac6653aSJeff Kirsher 
190375e4364fSdamuzi000 		priv->tx_skbuff[entry] = NULL;
19047ac6653aSJeff Kirsher 		entry = (++priv->cur_tx) % txsize;
1905c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1906c24602efSGiuseppe CAVALLARO 			desc = (struct dma_desc *)(priv->dma_etx + entry);
1907c24602efSGiuseppe CAVALLARO 		else
19087ac6653aSJeff Kirsher 			desc = priv->dma_tx + entry;
19097ac6653aSJeff Kirsher 
1910f722380dSIan Campbell 		desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
1911f722380dSIan Campbell 					      DMA_TO_DEVICE);
1912cf32deecSRayagond Kokatanur 		priv->tx_skbuff_dma[entry] = desc->des2;
19134a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
19144a7d666aSGiuseppe CAVALLARO 						priv->mode);
19157ac6653aSJeff Kirsher 		wmb();
19167ac6653aSJeff Kirsher 		priv->hw->desc->set_tx_owner(desc);
19178e839891SDeepak Sikri 		wmb();
19187ac6653aSJeff Kirsher 	}
19197ac6653aSJeff Kirsher 
192075e4364fSdamuzi000 	priv->tx_skbuff[entry] = skb;
192175e4364fSdamuzi000 
19229125cdd1SGiuseppe CAVALLARO 	/* Finalize the latest segment. */
19237ac6653aSJeff Kirsher 	priv->hw->desc->close_tx_desc(desc);
19247ac6653aSJeff Kirsher 
19257ac6653aSJeff Kirsher 	wmb();
19269125cdd1SGiuseppe CAVALLARO 	/* According to the coalesce parameter the IC bit for the latest
19279125cdd1SGiuseppe CAVALLARO 	 * segment could be reset and the timer re-started to invoke the
19289125cdd1SGiuseppe CAVALLARO 	 * stmmac_tx function. This approach takes care about the fragments.
19299125cdd1SGiuseppe CAVALLARO 	 */
19309125cdd1SGiuseppe CAVALLARO 	priv->tx_count_frames += nfrags + 1;
19319125cdd1SGiuseppe CAVALLARO 	if (priv->tx_coal_frames > priv->tx_count_frames) {
19329125cdd1SGiuseppe CAVALLARO 		priv->hw->desc->clear_tx_ic(desc);
19339125cdd1SGiuseppe CAVALLARO 		priv->xstats.tx_reset_ic_bit++;
19349125cdd1SGiuseppe CAVALLARO 		mod_timer(&priv->txtimer,
19359125cdd1SGiuseppe CAVALLARO 			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
19369125cdd1SGiuseppe CAVALLARO 	} else
19379125cdd1SGiuseppe CAVALLARO 		priv->tx_count_frames = 0;
19387ac6653aSJeff Kirsher 
19397ac6653aSJeff Kirsher 	/* To avoid raise condition */
19407ac6653aSJeff Kirsher 	priv->hw->desc->set_tx_owner(first);
19418e839891SDeepak Sikri 	wmb();
19427ac6653aSJeff Kirsher 
19437ac6653aSJeff Kirsher 	priv->cur_tx++;
19447ac6653aSJeff Kirsher 
19457ac6653aSJeff Kirsher 	if (netif_msg_pktdata(priv)) {
194683d7af64SGiuseppe CAVALLARO 		pr_debug("%s: curr %d dirty=%d entry=%d, first=%p, nfrags=%d",
1947ceb69499SGiuseppe CAVALLARO 			__func__, (priv->cur_tx % txsize),
1948ceb69499SGiuseppe CAVALLARO 			(priv->dirty_tx % txsize), entry, first, nfrags);
194983d7af64SGiuseppe CAVALLARO 
1950c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1951c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
1952c24602efSGiuseppe CAVALLARO 		else
1953c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
1954c24602efSGiuseppe CAVALLARO 
195583d7af64SGiuseppe CAVALLARO 		pr_debug(">>> frame to be transmitted: ");
19567ac6653aSJeff Kirsher 		print_pkt(skb->data, skb->len);
19577ac6653aSJeff Kirsher 	}
19587ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
195983d7af64SGiuseppe CAVALLARO 		if (netif_msg_hw(priv))
196083d7af64SGiuseppe CAVALLARO 			pr_debug("%s: stop transmitted packets\n", __func__);
19617ac6653aSJeff Kirsher 		netif_stop_queue(dev);
19627ac6653aSJeff Kirsher 	}
19637ac6653aSJeff Kirsher 
19647ac6653aSJeff Kirsher 	dev->stats.tx_bytes += skb->len;
19657ac6653aSJeff Kirsher 
1966891434b1SRayagond Kokatanur 	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
1967891434b1SRayagond Kokatanur 		     priv->hwts_tx_en)) {
1968891434b1SRayagond Kokatanur 		/* declare that device is doing timestamping */
1969891434b1SRayagond Kokatanur 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
1970891434b1SRayagond Kokatanur 		priv->hw->desc->enable_tx_timestamp(first);
1971891434b1SRayagond Kokatanur 	}
1972891434b1SRayagond Kokatanur 
1973891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
19747ac6653aSJeff Kirsher 		skb_tx_timestamp(skb);
19757ac6653aSJeff Kirsher 
19767ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_transmission(priv->ioaddr);
19777ac6653aSJeff Kirsher 
1978a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
1979a9097a96SGiuseppe CAVALLARO 
19807ac6653aSJeff Kirsher 	return NETDEV_TX_OK;
19817ac6653aSJeff Kirsher }
19827ac6653aSJeff Kirsher 
1983b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
1984b9381985SVince Bridgers {
1985b9381985SVince Bridgers 	struct ethhdr *ehdr;
1986b9381985SVince Bridgers 	u16 vlanid;
1987b9381985SVince Bridgers 
1988b9381985SVince Bridgers 	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
1989b9381985SVince Bridgers 	    NETIF_F_HW_VLAN_CTAG_RX &&
1990b9381985SVince Bridgers 	    !__vlan_get_tag(skb, &vlanid)) {
1991b9381985SVince Bridgers 		/* pop the vlan tag */
1992b9381985SVince Bridgers 		ehdr = (struct ethhdr *)skb->data;
1993b9381985SVince Bridgers 		memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
1994b9381985SVince Bridgers 		skb_pull(skb, VLAN_HLEN);
1995b9381985SVince Bridgers 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
1996b9381985SVince Bridgers 	}
1997b9381985SVince Bridgers }
1998b9381985SVince Bridgers 
1999b9381985SVince Bridgers 
200032ceabcaSGiuseppe CAVALLARO /**
200132ceabcaSGiuseppe CAVALLARO  * stmmac_rx_refill: refill used skb preallocated buffers
200232ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
200332ceabcaSGiuseppe CAVALLARO  * Description : this is to reallocate the skb for the reception process
200432ceabcaSGiuseppe CAVALLARO  * that is based on zero-copy.
200532ceabcaSGiuseppe CAVALLARO  */
20067ac6653aSJeff Kirsher static inline void stmmac_rx_refill(struct stmmac_priv *priv)
20077ac6653aSJeff Kirsher {
20087ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
20097ac6653aSJeff Kirsher 	int bfsize = priv->dma_buf_sz;
20107ac6653aSJeff Kirsher 
20117ac6653aSJeff Kirsher 	for (; priv->cur_rx - priv->dirty_rx > 0; priv->dirty_rx++) {
20127ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_rx % rxsize;
2013c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
2014c24602efSGiuseppe CAVALLARO 
2015c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2016c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2017c24602efSGiuseppe CAVALLARO 		else
2018c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2019c24602efSGiuseppe CAVALLARO 
20207ac6653aSJeff Kirsher 		if (likely(priv->rx_skbuff[entry] == NULL)) {
20217ac6653aSJeff Kirsher 			struct sk_buff *skb;
20227ac6653aSJeff Kirsher 
2023acb600deSEric Dumazet 			skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
20247ac6653aSJeff Kirsher 
20257ac6653aSJeff Kirsher 			if (unlikely(skb == NULL))
20267ac6653aSJeff Kirsher 				break;
20277ac6653aSJeff Kirsher 
20287ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = skb;
20297ac6653aSJeff Kirsher 			priv->rx_skbuff_dma[entry] =
20307ac6653aSJeff Kirsher 			    dma_map_single(priv->device, skb->data, bfsize,
20317ac6653aSJeff Kirsher 					   DMA_FROM_DEVICE);
20327ac6653aSJeff Kirsher 
2033c24602efSGiuseppe CAVALLARO 			p->des2 = priv->rx_skbuff_dma[entry];
2034286a8372SGiuseppe CAVALLARO 
203529896a67SGiuseppe CAVALLARO 			priv->hw->mode->refill_desc3(priv, p);
2036286a8372SGiuseppe CAVALLARO 
203783d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv))
203883d7af64SGiuseppe CAVALLARO 				pr_debug("\trefill entry #%d\n", entry);
20397ac6653aSJeff Kirsher 		}
20407ac6653aSJeff Kirsher 		wmb();
2041c24602efSGiuseppe CAVALLARO 		priv->hw->desc->set_rx_owner(p);
20428e839891SDeepak Sikri 		wmb();
20437ac6653aSJeff Kirsher 	}
20447ac6653aSJeff Kirsher }
20457ac6653aSJeff Kirsher 
204632ceabcaSGiuseppe CAVALLARO /**
204732ceabcaSGiuseppe CAVALLARO  * stmmac_rx_refill: refill used skb preallocated buffers
204832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
204932ceabcaSGiuseppe CAVALLARO  * @limit: napi bugget.
205032ceabcaSGiuseppe CAVALLARO  * Description :  this the function called by the napi poll method.
205132ceabcaSGiuseppe CAVALLARO  * It gets all the frames inside the ring.
205232ceabcaSGiuseppe CAVALLARO  */
20537ac6653aSJeff Kirsher static int stmmac_rx(struct stmmac_priv *priv, int limit)
20547ac6653aSJeff Kirsher {
20557ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
20567ac6653aSJeff Kirsher 	unsigned int entry = priv->cur_rx % rxsize;
20577ac6653aSJeff Kirsher 	unsigned int next_entry;
20587ac6653aSJeff Kirsher 	unsigned int count = 0;
2059ceb69499SGiuseppe CAVALLARO 	int coe = priv->plat->rx_coe;
20607ac6653aSJeff Kirsher 
206183d7af64SGiuseppe CAVALLARO 	if (netif_msg_rx_status(priv)) {
206283d7af64SGiuseppe CAVALLARO 		pr_debug("%s: descriptor ring:\n", __func__);
2063c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2064c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
2065c24602efSGiuseppe CAVALLARO 		else
2066c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
20677ac6653aSJeff Kirsher 	}
2068c24602efSGiuseppe CAVALLARO 	while (count < limit) {
20697ac6653aSJeff Kirsher 		int status;
20709401bb5cSGiuseppe CAVALLARO 		struct dma_desc *p;
20717ac6653aSJeff Kirsher 
2072c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2073c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2074c24602efSGiuseppe CAVALLARO 		else
2075c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2076c24602efSGiuseppe CAVALLARO 
2077c24602efSGiuseppe CAVALLARO 		if (priv->hw->desc->get_rx_owner(p))
20787ac6653aSJeff Kirsher 			break;
20797ac6653aSJeff Kirsher 
20807ac6653aSJeff Kirsher 		count++;
20817ac6653aSJeff Kirsher 
20827ac6653aSJeff Kirsher 		next_entry = (++priv->cur_rx) % rxsize;
2083c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
20849401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_erx + next_entry);
2085c24602efSGiuseppe CAVALLARO 		else
20869401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_rx + next_entry);
20877ac6653aSJeff Kirsher 
20887ac6653aSJeff Kirsher 		/* read the status of the incoming frame */
2089c24602efSGiuseppe CAVALLARO 		status = priv->hw->desc->rx_status(&priv->dev->stats,
2090c24602efSGiuseppe CAVALLARO 						   &priv->xstats, p);
2091c24602efSGiuseppe CAVALLARO 		if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status))
2092c24602efSGiuseppe CAVALLARO 			priv->hw->desc->rx_extended_status(&priv->dev->stats,
2093c24602efSGiuseppe CAVALLARO 							   &priv->xstats,
2094c24602efSGiuseppe CAVALLARO 							   priv->dma_erx +
2095c24602efSGiuseppe CAVALLARO 							   entry);
2096891434b1SRayagond Kokatanur 		if (unlikely(status == discard_frame)) {
20977ac6653aSJeff Kirsher 			priv->dev->stats.rx_errors++;
2098891434b1SRayagond Kokatanur 			if (priv->hwts_rx_en && !priv->extend_desc) {
2099891434b1SRayagond Kokatanur 				/* DESC2 & DESC3 will be overwitten by device
2100891434b1SRayagond Kokatanur 				 * with timestamp value, hence reinitialize
2101891434b1SRayagond Kokatanur 				 * them in stmmac_rx_refill() function so that
2102891434b1SRayagond Kokatanur 				 * device can reuse it.
2103891434b1SRayagond Kokatanur 				 */
2104891434b1SRayagond Kokatanur 				priv->rx_skbuff[entry] = NULL;
2105891434b1SRayagond Kokatanur 				dma_unmap_single(priv->device,
2106891434b1SRayagond Kokatanur 						 priv->rx_skbuff_dma[entry],
2107ceb69499SGiuseppe CAVALLARO 						 priv->dma_buf_sz,
2108ceb69499SGiuseppe CAVALLARO 						 DMA_FROM_DEVICE);
2109891434b1SRayagond Kokatanur 			}
2110891434b1SRayagond Kokatanur 		} else {
21117ac6653aSJeff Kirsher 			struct sk_buff *skb;
21127ac6653aSJeff Kirsher 			int frame_len;
21137ac6653aSJeff Kirsher 
2114ceb69499SGiuseppe CAVALLARO 			frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
2115ceb69499SGiuseppe CAVALLARO 
21167ac6653aSJeff Kirsher 			/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
2117ceb69499SGiuseppe CAVALLARO 			 * Type frames (LLC/LLC-SNAP)
2118ceb69499SGiuseppe CAVALLARO 			 */
21197ac6653aSJeff Kirsher 			if (unlikely(status != llc_snap))
21207ac6653aSJeff Kirsher 				frame_len -= ETH_FCS_LEN;
21217ac6653aSJeff Kirsher 
212283d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv)) {
21237ac6653aSJeff Kirsher 				pr_debug("\tdesc: %p [entry %d] buff=0x%x\n",
21247ac6653aSJeff Kirsher 					 p, entry, p->des2);
212583d7af64SGiuseppe CAVALLARO 				if (frame_len > ETH_FRAME_LEN)
212683d7af64SGiuseppe CAVALLARO 					pr_debug("\tframe size %d, COE: %d\n",
212783d7af64SGiuseppe CAVALLARO 						 frame_len, status);
212883d7af64SGiuseppe CAVALLARO 			}
21297ac6653aSJeff Kirsher 			skb = priv->rx_skbuff[entry];
21307ac6653aSJeff Kirsher 			if (unlikely(!skb)) {
21317ac6653aSJeff Kirsher 				pr_err("%s: Inconsistent Rx descriptor chain\n",
21327ac6653aSJeff Kirsher 				       priv->dev->name);
21337ac6653aSJeff Kirsher 				priv->dev->stats.rx_dropped++;
21347ac6653aSJeff Kirsher 				break;
21357ac6653aSJeff Kirsher 			}
21367ac6653aSJeff Kirsher 			prefetch(skb->data - NET_IP_ALIGN);
21377ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = NULL;
21387ac6653aSJeff Kirsher 
2139891434b1SRayagond Kokatanur 			stmmac_get_rx_hwtstamp(priv, entry, skb);
2140891434b1SRayagond Kokatanur 
21417ac6653aSJeff Kirsher 			skb_put(skb, frame_len);
21427ac6653aSJeff Kirsher 			dma_unmap_single(priv->device,
21437ac6653aSJeff Kirsher 					 priv->rx_skbuff_dma[entry],
21447ac6653aSJeff Kirsher 					 priv->dma_buf_sz, DMA_FROM_DEVICE);
214583d7af64SGiuseppe CAVALLARO 
21467ac6653aSJeff Kirsher 			if (netif_msg_pktdata(priv)) {
214783d7af64SGiuseppe CAVALLARO 				pr_debug("frame received (%dbytes)", frame_len);
21487ac6653aSJeff Kirsher 				print_pkt(skb->data, frame_len);
21497ac6653aSJeff Kirsher 			}
215083d7af64SGiuseppe CAVALLARO 
2151b9381985SVince Bridgers 			stmmac_rx_vlan(priv->dev, skb);
2152b9381985SVince Bridgers 
21537ac6653aSJeff Kirsher 			skb->protocol = eth_type_trans(skb, priv->dev);
21547ac6653aSJeff Kirsher 
2155ceb69499SGiuseppe CAVALLARO 			if (unlikely(!coe))
21567ac6653aSJeff Kirsher 				skb_checksum_none_assert(skb);
215762a2ab93SGiuseppe CAVALLARO 			else
21587ac6653aSJeff Kirsher 				skb->ip_summed = CHECKSUM_UNNECESSARY;
215962a2ab93SGiuseppe CAVALLARO 
21607ac6653aSJeff Kirsher 			napi_gro_receive(&priv->napi, skb);
21617ac6653aSJeff Kirsher 
21627ac6653aSJeff Kirsher 			priv->dev->stats.rx_packets++;
21637ac6653aSJeff Kirsher 			priv->dev->stats.rx_bytes += frame_len;
21647ac6653aSJeff Kirsher 		}
21657ac6653aSJeff Kirsher 		entry = next_entry;
21667ac6653aSJeff Kirsher 	}
21677ac6653aSJeff Kirsher 
21687ac6653aSJeff Kirsher 	stmmac_rx_refill(priv);
21697ac6653aSJeff Kirsher 
21707ac6653aSJeff Kirsher 	priv->xstats.rx_pkt_n += count;
21717ac6653aSJeff Kirsher 
21727ac6653aSJeff Kirsher 	return count;
21737ac6653aSJeff Kirsher }
21747ac6653aSJeff Kirsher 
21757ac6653aSJeff Kirsher /**
21767ac6653aSJeff Kirsher  *  stmmac_poll - stmmac poll method (NAPI)
21777ac6653aSJeff Kirsher  *  @napi : pointer to the napi structure.
21787ac6653aSJeff Kirsher  *  @budget : maximum number of packets that the current CPU can receive from
21797ac6653aSJeff Kirsher  *	      all interfaces.
21807ac6653aSJeff Kirsher  *  Description :
21819125cdd1SGiuseppe CAVALLARO  *  To look at the incoming frames and clear the tx resources.
21827ac6653aSJeff Kirsher  */
21837ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget)
21847ac6653aSJeff Kirsher {
21857ac6653aSJeff Kirsher 	struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
21867ac6653aSJeff Kirsher 	int work_done = 0;
21877ac6653aSJeff Kirsher 
21889125cdd1SGiuseppe CAVALLARO 	priv->xstats.napi_poll++;
21899125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
21907ac6653aSJeff Kirsher 
21919125cdd1SGiuseppe CAVALLARO 	work_done = stmmac_rx(priv, budget);
21927ac6653aSJeff Kirsher 	if (work_done < budget) {
21937ac6653aSJeff Kirsher 		napi_complete(napi);
21949125cdd1SGiuseppe CAVALLARO 		stmmac_enable_dma_irq(priv);
21957ac6653aSJeff Kirsher 	}
21967ac6653aSJeff Kirsher 	return work_done;
21977ac6653aSJeff Kirsher }
21987ac6653aSJeff Kirsher 
21997ac6653aSJeff Kirsher /**
22007ac6653aSJeff Kirsher  *  stmmac_tx_timeout
22017ac6653aSJeff Kirsher  *  @dev : Pointer to net device structure
22027ac6653aSJeff Kirsher  *  Description: this function is called when a packet transmission fails to
22037284a3f1SGiuseppe CAVALLARO  *   complete within a reasonable time. The driver will mark the error in the
22047ac6653aSJeff Kirsher  *   netdev structure and arrange for the device to be reset to a sane state
22057ac6653aSJeff Kirsher  *   in order to transmit a new packet.
22067ac6653aSJeff Kirsher  */
22077ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev)
22087ac6653aSJeff Kirsher {
22097ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22107ac6653aSJeff Kirsher 
22117ac6653aSJeff Kirsher 	/* Clear Tx resources and restart transmitting again */
22127ac6653aSJeff Kirsher 	stmmac_tx_err(priv);
22137ac6653aSJeff Kirsher }
22147ac6653aSJeff Kirsher 
22157ac6653aSJeff Kirsher /**
221601789349SJiri Pirko  *  stmmac_set_rx_mode - entry point for multicast addressing
22177ac6653aSJeff Kirsher  *  @dev : pointer to the device structure
22187ac6653aSJeff Kirsher  *  Description:
22197ac6653aSJeff Kirsher  *  This function is a driver entry point which gets called by the kernel
22207ac6653aSJeff Kirsher  *  whenever multicast addresses must be enabled/disabled.
22217ac6653aSJeff Kirsher  *  Return value:
22227ac6653aSJeff Kirsher  *  void.
22237ac6653aSJeff Kirsher  */
222401789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev)
22257ac6653aSJeff Kirsher {
22267ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22277ac6653aSJeff Kirsher 
22287ac6653aSJeff Kirsher 	spin_lock(&priv->lock);
2229cffb13f4SGiuseppe CAVALLARO 	priv->hw->mac->set_filter(dev, priv->synopsys_id);
22307ac6653aSJeff Kirsher 	spin_unlock(&priv->lock);
22317ac6653aSJeff Kirsher }
22327ac6653aSJeff Kirsher 
22337ac6653aSJeff Kirsher /**
22347ac6653aSJeff Kirsher  *  stmmac_change_mtu - entry point to change MTU size for the device.
22357ac6653aSJeff Kirsher  *  @dev : device pointer.
22367ac6653aSJeff Kirsher  *  @new_mtu : the new MTU size for the device.
22377ac6653aSJeff Kirsher  *  Description: the Maximum Transfer Unit (MTU) is used by the network layer
22387ac6653aSJeff Kirsher  *  to drive packet transmission. Ethernet has an MTU of 1500 octets
22397ac6653aSJeff Kirsher  *  (ETH_DATA_LEN). This value can be changed with ifconfig.
22407ac6653aSJeff Kirsher  *  Return value:
22417ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
22427ac6653aSJeff Kirsher  *  file on failure.
22437ac6653aSJeff Kirsher  */
22447ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
22457ac6653aSJeff Kirsher {
22467ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22477ac6653aSJeff Kirsher 	int max_mtu;
22487ac6653aSJeff Kirsher 
22497ac6653aSJeff Kirsher 	if (netif_running(dev)) {
22507ac6653aSJeff Kirsher 		pr_err("%s: must be stopped to change its MTU\n", dev->name);
22517ac6653aSJeff Kirsher 		return -EBUSY;
22527ac6653aSJeff Kirsher 	}
22537ac6653aSJeff Kirsher 
225448febf7eSGiuseppe CAVALLARO 	if (priv->plat->enh_desc)
22557ac6653aSJeff Kirsher 		max_mtu = JUMBO_LEN;
22567ac6653aSJeff Kirsher 	else
225745db81e1SGiuseppe CAVALLARO 		max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
22587ac6653aSJeff Kirsher 
22592618abb7SVince Bridgers 	if (priv->plat->maxmtu < max_mtu)
22602618abb7SVince Bridgers 		max_mtu = priv->plat->maxmtu;
22612618abb7SVince Bridgers 
22627ac6653aSJeff Kirsher 	if ((new_mtu < 46) || (new_mtu > max_mtu)) {
22637ac6653aSJeff Kirsher 		pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
22647ac6653aSJeff Kirsher 		return -EINVAL;
22657ac6653aSJeff Kirsher 	}
22667ac6653aSJeff Kirsher 
22677ac6653aSJeff Kirsher 	dev->mtu = new_mtu;
22687ac6653aSJeff Kirsher 	netdev_update_features(dev);
22697ac6653aSJeff Kirsher 
22707ac6653aSJeff Kirsher 	return 0;
22717ac6653aSJeff Kirsher }
22727ac6653aSJeff Kirsher 
2273c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev,
2274c8f44affSMichał Mirosław 					     netdev_features_t features)
22757ac6653aSJeff Kirsher {
22767ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22777ac6653aSJeff Kirsher 
227838912bdbSDeepak SIKRI 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
22797ac6653aSJeff Kirsher 		features &= ~NETIF_F_RXCSUM;
228038912bdbSDeepak SIKRI 	else if (priv->plat->rx_coe == STMMAC_RX_COE_TYPE1)
228138912bdbSDeepak SIKRI 		features &= ~NETIF_F_IPV6_CSUM;
22827ac6653aSJeff Kirsher 	if (!priv->plat->tx_coe)
22837ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
22847ac6653aSJeff Kirsher 
22857ac6653aSJeff Kirsher 	/* Some GMAC devices have a bugged Jumbo frame support that
22867ac6653aSJeff Kirsher 	 * needs to have the Tx COE disabled for oversized frames
22877ac6653aSJeff Kirsher 	 * (due to limited buffer sizes). In this case we disable
2288ceb69499SGiuseppe CAVALLARO 	 * the TX csum insertionin the TDES and not use SF.
2289ceb69499SGiuseppe CAVALLARO 	 */
22907ac6653aSJeff Kirsher 	if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
22917ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
22927ac6653aSJeff Kirsher 
22937ac6653aSJeff Kirsher 	return features;
22947ac6653aSJeff Kirsher }
22957ac6653aSJeff Kirsher 
229632ceabcaSGiuseppe CAVALLARO /**
229732ceabcaSGiuseppe CAVALLARO  *  stmmac_interrupt - main ISR
229832ceabcaSGiuseppe CAVALLARO  *  @irq: interrupt number.
229932ceabcaSGiuseppe CAVALLARO  *  @dev_id: to pass the net device pointer.
230032ceabcaSGiuseppe CAVALLARO  *  Description: this is the main driver interrupt service routine.
230132ceabcaSGiuseppe CAVALLARO  *  It calls the DMA ISR and also the core ISR to manage PMT, MMC, LPI
230232ceabcaSGiuseppe CAVALLARO  *  interrupts.
230332ceabcaSGiuseppe CAVALLARO  */
23047ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
23057ac6653aSJeff Kirsher {
23067ac6653aSJeff Kirsher 	struct net_device *dev = (struct net_device *)dev_id;
23077ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23087ac6653aSJeff Kirsher 
230989f7f2cfSSrinivas Kandagatla 	if (priv->irq_wake)
231089f7f2cfSSrinivas Kandagatla 		pm_wakeup_event(priv->device, 0);
231189f7f2cfSSrinivas Kandagatla 
23127ac6653aSJeff Kirsher 	if (unlikely(!dev)) {
23137ac6653aSJeff Kirsher 		pr_err("%s: invalid dev pointer\n", __func__);
23147ac6653aSJeff Kirsher 		return IRQ_NONE;
23157ac6653aSJeff Kirsher 	}
23167ac6653aSJeff Kirsher 
23177ac6653aSJeff Kirsher 	/* To handle GMAC own interrupts */
2318d765955dSGiuseppe CAVALLARO 	if (priv->plat->has_gmac) {
2319d765955dSGiuseppe CAVALLARO 		int status = priv->hw->mac->host_irq_status((void __iomem *)
23200982a0f6SGiuseppe CAVALLARO 							    dev->base_addr,
23210982a0f6SGiuseppe CAVALLARO 							    &priv->xstats);
2322d765955dSGiuseppe CAVALLARO 		if (unlikely(status)) {
2323d765955dSGiuseppe CAVALLARO 			/* For LPI we need to save the tx status */
23240982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
2325d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = true;
23260982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
2327d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = false;
2328d765955dSGiuseppe CAVALLARO 		}
2329d765955dSGiuseppe CAVALLARO 	}
2330d765955dSGiuseppe CAVALLARO 
2331d765955dSGiuseppe CAVALLARO 	/* To handle DMA interrupts */
23327ac6653aSJeff Kirsher 	stmmac_dma_interrupt(priv);
23337ac6653aSJeff Kirsher 
23347ac6653aSJeff Kirsher 	return IRQ_HANDLED;
23357ac6653aSJeff Kirsher }
23367ac6653aSJeff Kirsher 
23377ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
23387ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools
2339ceb69499SGiuseppe CAVALLARO  * to allow network I/O with interrupts disabled.
2340ceb69499SGiuseppe CAVALLARO  */
23417ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev)
23427ac6653aSJeff Kirsher {
23437ac6653aSJeff Kirsher 	disable_irq(dev->irq);
23447ac6653aSJeff Kirsher 	stmmac_interrupt(dev->irq, dev);
23457ac6653aSJeff Kirsher 	enable_irq(dev->irq);
23467ac6653aSJeff Kirsher }
23477ac6653aSJeff Kirsher #endif
23487ac6653aSJeff Kirsher 
23497ac6653aSJeff Kirsher /**
23507ac6653aSJeff Kirsher  *  stmmac_ioctl - Entry point for the Ioctl
23517ac6653aSJeff Kirsher  *  @dev: Device pointer.
23527ac6653aSJeff Kirsher  *  @rq: An IOCTL specefic structure, that can contain a pointer to
23537ac6653aSJeff Kirsher  *  a proprietary structure used to pass information to the driver.
23547ac6653aSJeff Kirsher  *  @cmd: IOCTL command
23557ac6653aSJeff Kirsher  *  Description:
235632ceabcaSGiuseppe CAVALLARO  *  Currently it supports the phy_mii_ioctl(...) and HW time stamping.
23577ac6653aSJeff Kirsher  */
23587ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
23597ac6653aSJeff Kirsher {
23607ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
2361891434b1SRayagond Kokatanur 	int ret = -EOPNOTSUPP;
23627ac6653aSJeff Kirsher 
23637ac6653aSJeff Kirsher 	if (!netif_running(dev))
23647ac6653aSJeff Kirsher 		return -EINVAL;
23657ac6653aSJeff Kirsher 
2366891434b1SRayagond Kokatanur 	switch (cmd) {
2367891434b1SRayagond Kokatanur 	case SIOCGMIIPHY:
2368891434b1SRayagond Kokatanur 	case SIOCGMIIREG:
2369891434b1SRayagond Kokatanur 	case SIOCSMIIREG:
23707ac6653aSJeff Kirsher 		if (!priv->phydev)
23717ac6653aSJeff Kirsher 			return -EINVAL;
23727ac6653aSJeff Kirsher 		ret = phy_mii_ioctl(priv->phydev, rq, cmd);
2373891434b1SRayagond Kokatanur 		break;
2374891434b1SRayagond Kokatanur 	case SIOCSHWTSTAMP:
2375891434b1SRayagond Kokatanur 		ret = stmmac_hwtstamp_ioctl(dev, rq);
2376891434b1SRayagond Kokatanur 		break;
2377891434b1SRayagond Kokatanur 	default:
2378891434b1SRayagond Kokatanur 		break;
2379891434b1SRayagond Kokatanur 	}
23807ac6653aSJeff Kirsher 
23817ac6653aSJeff Kirsher 	return ret;
23827ac6653aSJeff Kirsher }
23837ac6653aSJeff Kirsher 
23847ac29055SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_DEBUG_FS
23857ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir;
23867ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_rings_status;
2387e7434821SGiuseppe CAVALLARO static struct dentry *stmmac_dma_cap;
23887ac29055SGiuseppe CAVALLARO 
2389c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc,
2390c24602efSGiuseppe CAVALLARO 			       struct seq_file *seq)
23917ac29055SGiuseppe CAVALLARO {
23927ac29055SGiuseppe CAVALLARO 	int i;
2393c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
2394c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
23957ac29055SGiuseppe CAVALLARO 
2396c24602efSGiuseppe CAVALLARO 	for (i = 0; i < size; i++) {
2397c24602efSGiuseppe CAVALLARO 		u64 x;
2398c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
2399c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
2400c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2401c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2402c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2403c24602efSGiuseppe CAVALLARO 				   ep->basic.des2, ep->basic.des3);
2404c24602efSGiuseppe CAVALLARO 			ep++;
2405c24602efSGiuseppe CAVALLARO 		} else {
2406c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
2407c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2408c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2409c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2410c24602efSGiuseppe CAVALLARO 				   p->des2, p->des3);
2411c24602efSGiuseppe CAVALLARO 			p++;
2412c24602efSGiuseppe CAVALLARO 		}
24137ac29055SGiuseppe CAVALLARO 		seq_printf(seq, "\n");
24147ac29055SGiuseppe CAVALLARO 	}
2415c24602efSGiuseppe CAVALLARO }
24167ac29055SGiuseppe CAVALLARO 
2417c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
2418c24602efSGiuseppe CAVALLARO {
2419c24602efSGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2420c24602efSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2421c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
2422c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
24237ac29055SGiuseppe CAVALLARO 
2424c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
2425c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended RX descriptor ring:\n");
2426c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_erx, rxsize, 1, seq);
2427c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended TX descriptor ring:\n");
2428c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_etx, txsize, 1, seq);
2429c24602efSGiuseppe CAVALLARO 	} else {
2430c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "RX descriptor ring:\n");
2431c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_rx, rxsize, 0, seq);
2432c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "TX descriptor ring:\n");
2433c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_tx, txsize, 0, seq);
24347ac29055SGiuseppe CAVALLARO 	}
24357ac29055SGiuseppe CAVALLARO 
24367ac29055SGiuseppe CAVALLARO 	return 0;
24377ac29055SGiuseppe CAVALLARO }
24387ac29055SGiuseppe CAVALLARO 
24397ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
24407ac29055SGiuseppe CAVALLARO {
24417ac29055SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
24427ac29055SGiuseppe CAVALLARO }
24437ac29055SGiuseppe CAVALLARO 
24447ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = {
24457ac29055SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
24467ac29055SGiuseppe CAVALLARO 	.open = stmmac_sysfs_ring_open,
24477ac29055SGiuseppe CAVALLARO 	.read = seq_read,
24487ac29055SGiuseppe CAVALLARO 	.llseek = seq_lseek,
244974863948SDjalal Harouni 	.release = single_release,
24507ac29055SGiuseppe CAVALLARO };
24517ac29055SGiuseppe CAVALLARO 
2452e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
2453e7434821SGiuseppe CAVALLARO {
2454e7434821SGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2455e7434821SGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2456e7434821SGiuseppe CAVALLARO 
245719e30c14SGiuseppe CAVALLARO 	if (!priv->hw_cap_support) {
2458e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "DMA HW features not supported\n");
2459e7434821SGiuseppe CAVALLARO 		return 0;
2460e7434821SGiuseppe CAVALLARO 	}
2461e7434821SGiuseppe CAVALLARO 
2462e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2463e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tDMA HW features\n");
2464e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2465e7434821SGiuseppe CAVALLARO 
2466e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t10/100 Mbps %s\n",
2467e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_10_100) ? "Y" : "N");
2468e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t1000 Mbps %s\n",
2469e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_1000) ? "Y" : "N");
2470e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHalf duple %s\n",
2471e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.half_duplex) ? "Y" : "N");
2472e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHash Filter: %s\n",
2473e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.hash_filter) ? "Y" : "N");
2474e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tMultiple MAC address registers: %s\n",
2475e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.multi_addr) ? "Y" : "N");
2476e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n",
2477e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pcs) ? "Y" : "N");
2478e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
2479e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.sma_mdio) ? "Y" : "N");
2480e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Remote wake up: %s\n",
2481e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
2482e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Magic Frame: %s\n",
2483e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
2484e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRMON module: %s\n",
2485e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rmon) ? "Y" : "N");
2486e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
2487e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.time_stamp) ? "Y" : "N");
2488e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n",
2489e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.atime_stamp) ? "Y" : "N");
2490e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n",
2491e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.eee) ? "Y" : "N");
2492e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
2493e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tChecksum Offload in TX: %s\n",
2494e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.tx_coe) ? "Y" : "N");
2495e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
2496e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
2497e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
2498e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
2499e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
2500e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
2501e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
2502e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_rx_channel);
2503e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
2504e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_tx_channel);
2505e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tEnhanced descriptors: %s\n",
2506e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.enh_desc) ? "Y" : "N");
2507e7434821SGiuseppe CAVALLARO 
2508e7434821SGiuseppe CAVALLARO 	return 0;
2509e7434821SGiuseppe CAVALLARO }
2510e7434821SGiuseppe CAVALLARO 
2511e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
2512e7434821SGiuseppe CAVALLARO {
2513e7434821SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
2514e7434821SGiuseppe CAVALLARO }
2515e7434821SGiuseppe CAVALLARO 
2516e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = {
2517e7434821SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
2518e7434821SGiuseppe CAVALLARO 	.open = stmmac_sysfs_dma_cap_open,
2519e7434821SGiuseppe CAVALLARO 	.read = seq_read,
2520e7434821SGiuseppe CAVALLARO 	.llseek = seq_lseek,
252174863948SDjalal Harouni 	.release = single_release,
2522e7434821SGiuseppe CAVALLARO };
2523e7434821SGiuseppe CAVALLARO 
25247ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev)
25257ac29055SGiuseppe CAVALLARO {
25267ac29055SGiuseppe CAVALLARO 	/* Create debugfs entries */
25277ac29055SGiuseppe CAVALLARO 	stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
25287ac29055SGiuseppe CAVALLARO 
25297ac29055SGiuseppe CAVALLARO 	if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
25307ac29055SGiuseppe CAVALLARO 		pr_err("ERROR %s, debugfs create directory failed\n",
25317ac29055SGiuseppe CAVALLARO 		       STMMAC_RESOURCE_NAME);
25327ac29055SGiuseppe CAVALLARO 
25337ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
25347ac29055SGiuseppe CAVALLARO 	}
25357ac29055SGiuseppe CAVALLARO 
25367ac29055SGiuseppe CAVALLARO 	/* Entry to report DMA RX/TX rings */
25377ac29055SGiuseppe CAVALLARO 	stmmac_rings_status = debugfs_create_file("descriptors_status",
25387ac29055SGiuseppe CAVALLARO 						  S_IRUGO, stmmac_fs_dir, dev,
25397ac29055SGiuseppe CAVALLARO 						  &stmmac_rings_status_fops);
25407ac29055SGiuseppe CAVALLARO 
25417ac29055SGiuseppe CAVALLARO 	if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
25427ac29055SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac ring debugfs file\n");
25437ac29055SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
25447ac29055SGiuseppe CAVALLARO 
25457ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
25467ac29055SGiuseppe CAVALLARO 	}
25477ac29055SGiuseppe CAVALLARO 
2548e7434821SGiuseppe CAVALLARO 	/* Entry to report the DMA HW features */
2549e7434821SGiuseppe CAVALLARO 	stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
2550e7434821SGiuseppe CAVALLARO 					     dev, &stmmac_dma_cap_fops);
2551e7434821SGiuseppe CAVALLARO 
2552e7434821SGiuseppe CAVALLARO 	if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
2553e7434821SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac MMC debugfs file\n");
2554e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_rings_status);
2555e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
2556e7434821SGiuseppe CAVALLARO 
2557e7434821SGiuseppe CAVALLARO 		return -ENOMEM;
2558e7434821SGiuseppe CAVALLARO 	}
2559e7434821SGiuseppe CAVALLARO 
25607ac29055SGiuseppe CAVALLARO 	return 0;
25617ac29055SGiuseppe CAVALLARO }
25627ac29055SGiuseppe CAVALLARO 
25637ac29055SGiuseppe CAVALLARO static void stmmac_exit_fs(void)
25647ac29055SGiuseppe CAVALLARO {
25657ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_rings_status);
2566e7434821SGiuseppe CAVALLARO 	debugfs_remove(stmmac_dma_cap);
25677ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_fs_dir);
25687ac29055SGiuseppe CAVALLARO }
25697ac29055SGiuseppe CAVALLARO #endif /* CONFIG_STMMAC_DEBUG_FS */
25707ac29055SGiuseppe CAVALLARO 
25717ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = {
25727ac6653aSJeff Kirsher 	.ndo_open = stmmac_open,
25737ac6653aSJeff Kirsher 	.ndo_start_xmit = stmmac_xmit,
25747ac6653aSJeff Kirsher 	.ndo_stop = stmmac_release,
25757ac6653aSJeff Kirsher 	.ndo_change_mtu = stmmac_change_mtu,
25767ac6653aSJeff Kirsher 	.ndo_fix_features = stmmac_fix_features,
257701789349SJiri Pirko 	.ndo_set_rx_mode = stmmac_set_rx_mode,
25787ac6653aSJeff Kirsher 	.ndo_tx_timeout = stmmac_tx_timeout,
25797ac6653aSJeff Kirsher 	.ndo_do_ioctl = stmmac_ioctl,
25807ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
25817ac6653aSJeff Kirsher 	.ndo_poll_controller = stmmac_poll_controller,
25827ac6653aSJeff Kirsher #endif
25837ac6653aSJeff Kirsher 	.ndo_set_mac_address = eth_mac_addr,
25847ac6653aSJeff Kirsher };
25857ac6653aSJeff Kirsher 
25867ac6653aSJeff Kirsher /**
2587cf3f047bSGiuseppe CAVALLARO  *  stmmac_hw_init - Init the MAC device
258832ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
2589cf3f047bSGiuseppe CAVALLARO  *  Description: this function detects which MAC device
2590cf3f047bSGiuseppe CAVALLARO  *  (GMAC/MAC10-100) has to attached, checks the HW capability
2591cf3f047bSGiuseppe CAVALLARO  *  (if supported) and sets the driver's features (for example
2592cf3f047bSGiuseppe CAVALLARO  *  to use the ring or chaine mode or support the normal/enh
2593cf3f047bSGiuseppe CAVALLARO  *  descriptor structure).
2594cf3f047bSGiuseppe CAVALLARO  */
2595cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv)
2596cf3f047bSGiuseppe CAVALLARO {
2597c24602efSGiuseppe CAVALLARO 	int ret;
2598cf3f047bSGiuseppe CAVALLARO 	struct mac_device_info *mac;
2599cf3f047bSGiuseppe CAVALLARO 
2600cf3f047bSGiuseppe CAVALLARO 	/* Identify the MAC HW device */
260103f2eecdSMarc Kleine-Budde 	if (priv->plat->has_gmac) {
260203f2eecdSMarc Kleine-Budde 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
2603cf3f047bSGiuseppe CAVALLARO 		mac = dwmac1000_setup(priv->ioaddr);
260403f2eecdSMarc Kleine-Budde 	} else {
2605cf3f047bSGiuseppe CAVALLARO 		mac = dwmac100_setup(priv->ioaddr);
260603f2eecdSMarc Kleine-Budde 	}
2607cf3f047bSGiuseppe CAVALLARO 	if (!mac)
2608cf3f047bSGiuseppe CAVALLARO 		return -ENOMEM;
2609cf3f047bSGiuseppe CAVALLARO 
2610cf3f047bSGiuseppe CAVALLARO 	priv->hw = mac;
2611cf3f047bSGiuseppe CAVALLARO 
2612cf3f047bSGiuseppe CAVALLARO 	/* Get and dump the chip ID */
2613cffb13f4SGiuseppe CAVALLARO 	priv->synopsys_id = stmmac_get_synopsys_id(priv);
2614cf3f047bSGiuseppe CAVALLARO 
26154a7d666aSGiuseppe CAVALLARO 	/* To use the chained or ring mode */
26164a7d666aSGiuseppe CAVALLARO 	if (chain_mode) {
261729896a67SGiuseppe CAVALLARO 		priv->hw->mode = &chain_mode_ops;
26184a7d666aSGiuseppe CAVALLARO 		pr_info(" Chain mode enabled\n");
26194a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_CHAIN_MODE;
26204a7d666aSGiuseppe CAVALLARO 	} else {
262129896a67SGiuseppe CAVALLARO 		priv->hw->mode = &ring_mode_ops;
26224a7d666aSGiuseppe CAVALLARO 		pr_info(" Ring mode enabled\n");
26234a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_RING_MODE;
26244a7d666aSGiuseppe CAVALLARO 	}
26254a7d666aSGiuseppe CAVALLARO 
2626cf3f047bSGiuseppe CAVALLARO 	/* Get the HW capability (new GMAC newer than 3.50a) */
2627cf3f047bSGiuseppe CAVALLARO 	priv->hw_cap_support = stmmac_get_hw_features(priv);
2628cf3f047bSGiuseppe CAVALLARO 	if (priv->hw_cap_support) {
2629cf3f047bSGiuseppe CAVALLARO 		pr_info(" DMA HW capability register supported");
2630cf3f047bSGiuseppe CAVALLARO 
2631cf3f047bSGiuseppe CAVALLARO 		/* We can override some gmac/dma configuration fields: e.g.
2632cf3f047bSGiuseppe CAVALLARO 		 * enh_desc, tx_coe (e.g. that are passed through the
2633cf3f047bSGiuseppe CAVALLARO 		 * platform) with the values from the HW capability
2634cf3f047bSGiuseppe CAVALLARO 		 * register (if supported).
2635cf3f047bSGiuseppe CAVALLARO 		 */
2636cf3f047bSGiuseppe CAVALLARO 		priv->plat->enh_desc = priv->dma_cap.enh_desc;
2637cf3f047bSGiuseppe CAVALLARO 		priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
263838912bdbSDeepak SIKRI 
263938912bdbSDeepak SIKRI 		priv->plat->tx_coe = priv->dma_cap.tx_coe;
264038912bdbSDeepak SIKRI 
264138912bdbSDeepak SIKRI 		if (priv->dma_cap.rx_coe_type2)
264238912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
264338912bdbSDeepak SIKRI 		else if (priv->dma_cap.rx_coe_type1)
264438912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
264538912bdbSDeepak SIKRI 
2646cf3f047bSGiuseppe CAVALLARO 	} else
2647cf3f047bSGiuseppe CAVALLARO 		pr_info(" No HW DMA feature register supported");
2648cf3f047bSGiuseppe CAVALLARO 
264961369d02SByungho An 	/* To use alternate (extended) or normal descriptor structures */
265061369d02SByungho An 	stmmac_selec_desc_mode(priv);
265161369d02SByungho An 
265238912bdbSDeepak SIKRI 	ret = priv->hw->mac->rx_ipc(priv->ioaddr);
265338912bdbSDeepak SIKRI 	if (!ret) {
2654ceb69499SGiuseppe CAVALLARO 		pr_warn(" RX IPC Checksum Offload not configured.\n");
265538912bdbSDeepak SIKRI 		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
265638912bdbSDeepak SIKRI 	}
265738912bdbSDeepak SIKRI 
265838912bdbSDeepak SIKRI 	if (priv->plat->rx_coe)
265938912bdbSDeepak SIKRI 		pr_info(" RX Checksum Offload Engine supported (type %d)\n",
266038912bdbSDeepak SIKRI 			priv->plat->rx_coe);
2661cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->tx_coe)
2662cf3f047bSGiuseppe CAVALLARO 		pr_info(" TX Checksum insertion supported\n");
2663cf3f047bSGiuseppe CAVALLARO 
2664cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->pmt) {
2665cf3f047bSGiuseppe CAVALLARO 		pr_info(" Wake-Up On Lan supported\n");
2666cf3f047bSGiuseppe CAVALLARO 		device_set_wakeup_capable(priv->device, 1);
2667cf3f047bSGiuseppe CAVALLARO 	}
2668cf3f047bSGiuseppe CAVALLARO 
2669c24602efSGiuseppe CAVALLARO 	return 0;
2670cf3f047bSGiuseppe CAVALLARO }
2671cf3f047bSGiuseppe CAVALLARO 
2672cf3f047bSGiuseppe CAVALLARO /**
2673bfab27a1SGiuseppe CAVALLARO  * stmmac_dvr_probe
2674bfab27a1SGiuseppe CAVALLARO  * @device: device pointer
2675ff3dd78cSGiuseppe CAVALLARO  * @plat_dat: platform data pointer
2676ff3dd78cSGiuseppe CAVALLARO  * @addr: iobase memory address
2677bfab27a1SGiuseppe CAVALLARO  * Description: this is the main probe function used to
2678bfab27a1SGiuseppe CAVALLARO  * call the alloc_etherdev, allocate the priv structure.
26797ac6653aSJeff Kirsher  */
2680bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *stmmac_dvr_probe(struct device *device,
2681cf3f047bSGiuseppe CAVALLARO 				     struct plat_stmmacenet_data *plat_dat,
2682cf3f047bSGiuseppe CAVALLARO 				     void __iomem *addr)
26837ac6653aSJeff Kirsher {
26847ac6653aSJeff Kirsher 	int ret = 0;
2685bfab27a1SGiuseppe CAVALLARO 	struct net_device *ndev = NULL;
2686bfab27a1SGiuseppe CAVALLARO 	struct stmmac_priv *priv;
26877ac6653aSJeff Kirsher 
2688bfab27a1SGiuseppe CAVALLARO 	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
268941de8d4cSJoe Perches 	if (!ndev)
2690bfab27a1SGiuseppe CAVALLARO 		return NULL;
26917ac6653aSJeff Kirsher 
2692bfab27a1SGiuseppe CAVALLARO 	SET_NETDEV_DEV(ndev, device);
26937ac6653aSJeff Kirsher 
2694bfab27a1SGiuseppe CAVALLARO 	priv = netdev_priv(ndev);
2695bfab27a1SGiuseppe CAVALLARO 	priv->device = device;
2696bfab27a1SGiuseppe CAVALLARO 	priv->dev = ndev;
2697bfab27a1SGiuseppe CAVALLARO 
2698bfab27a1SGiuseppe CAVALLARO 	ether_setup(ndev);
2699bfab27a1SGiuseppe CAVALLARO 
2700bfab27a1SGiuseppe CAVALLARO 	stmmac_set_ethtool_ops(ndev);
2701cf3f047bSGiuseppe CAVALLARO 	priv->pause = pause;
2702cf3f047bSGiuseppe CAVALLARO 	priv->plat = plat_dat;
2703cf3f047bSGiuseppe CAVALLARO 	priv->ioaddr = addr;
2704cf3f047bSGiuseppe CAVALLARO 	priv->dev->base_addr = (unsigned long)addr;
2705bfab27a1SGiuseppe CAVALLARO 
2706cf3f047bSGiuseppe CAVALLARO 	/* Verify driver arguments */
2707cf3f047bSGiuseppe CAVALLARO 	stmmac_verify_args();
2708cf3f047bSGiuseppe CAVALLARO 
2709cf3f047bSGiuseppe CAVALLARO 	/* Override with kernel parameters if supplied XXX CRS XXX
2710ceb69499SGiuseppe CAVALLARO 	 * this needs to have multiple instances
2711ceb69499SGiuseppe CAVALLARO 	 */
2712cf3f047bSGiuseppe CAVALLARO 	if ((phyaddr >= 0) && (phyaddr <= 31))
2713cf3f047bSGiuseppe CAVALLARO 		priv->plat->phy_addr = phyaddr;
2714cf3f047bSGiuseppe CAVALLARO 
271562866e98SChen-Yu Tsai 	priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
271662866e98SChen-Yu Tsai 	if (IS_ERR(priv->stmmac_clk)) {
271762866e98SChen-Yu Tsai 		dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
271862866e98SChen-Yu Tsai 			 __func__);
2719c5e4ddbdSChen-Yu Tsai 		ret = PTR_ERR(priv->stmmac_clk);
272062866e98SChen-Yu Tsai 		goto error_clk_get;
272162866e98SChen-Yu Tsai 	}
272262866e98SChen-Yu Tsai 	clk_prepare_enable(priv->stmmac_clk);
272362866e98SChen-Yu Tsai 
2724c5e4ddbdSChen-Yu Tsai 	priv->stmmac_rst = devm_reset_control_get(priv->device,
2725c5e4ddbdSChen-Yu Tsai 						  STMMAC_RESOURCE_NAME);
2726c5e4ddbdSChen-Yu Tsai 	if (IS_ERR(priv->stmmac_rst)) {
2727c5e4ddbdSChen-Yu Tsai 		if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
2728c5e4ddbdSChen-Yu Tsai 			ret = -EPROBE_DEFER;
2729c5e4ddbdSChen-Yu Tsai 			goto error_hw_init;
2730c5e4ddbdSChen-Yu Tsai 		}
2731c5e4ddbdSChen-Yu Tsai 		dev_info(priv->device, "no reset control found\n");
2732c5e4ddbdSChen-Yu Tsai 		priv->stmmac_rst = NULL;
2733c5e4ddbdSChen-Yu Tsai 	}
2734c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2735c5e4ddbdSChen-Yu Tsai 		reset_control_deassert(priv->stmmac_rst);
2736c5e4ddbdSChen-Yu Tsai 
2737cf3f047bSGiuseppe CAVALLARO 	/* Init MAC and get the capabilities */
2738c24602efSGiuseppe CAVALLARO 	ret = stmmac_hw_init(priv);
2739c24602efSGiuseppe CAVALLARO 	if (ret)
274062866e98SChen-Yu Tsai 		goto error_hw_init;
2741cf3f047bSGiuseppe CAVALLARO 
2742cf3f047bSGiuseppe CAVALLARO 	ndev->netdev_ops = &stmmac_netdev_ops;
2743cf3f047bSGiuseppe CAVALLARO 
2744cf3f047bSGiuseppe CAVALLARO 	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
2745cf3f047bSGiuseppe CAVALLARO 			    NETIF_F_RXCSUM;
2746bfab27a1SGiuseppe CAVALLARO 	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
2747bfab27a1SGiuseppe CAVALLARO 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
27487ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED
27497ac6653aSJeff Kirsher 	/* Both mac100 and gmac support receive VLAN tag detection */
2750f646968fSPatrick McHardy 	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
27517ac6653aSJeff Kirsher #endif
27527ac6653aSJeff Kirsher 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
27537ac6653aSJeff Kirsher 
27547ac6653aSJeff Kirsher 	if (flow_ctrl)
27557ac6653aSJeff Kirsher 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
27567ac6653aSJeff Kirsher 
275762a2ab93SGiuseppe CAVALLARO 	/* Rx Watchdog is available in the COREs newer than the 3.40.
275862a2ab93SGiuseppe CAVALLARO 	 * In some case, for example on bugged HW this feature
275962a2ab93SGiuseppe CAVALLARO 	 * has to be disable and this can be done by passing the
276062a2ab93SGiuseppe CAVALLARO 	 * riwt_off field from the platform.
276162a2ab93SGiuseppe CAVALLARO 	 */
276262a2ab93SGiuseppe CAVALLARO 	if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
276362a2ab93SGiuseppe CAVALLARO 		priv->use_riwt = 1;
276462a2ab93SGiuseppe CAVALLARO 		pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
276562a2ab93SGiuseppe CAVALLARO 	}
276662a2ab93SGiuseppe CAVALLARO 
2767bfab27a1SGiuseppe CAVALLARO 	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
27687ac6653aSJeff Kirsher 
27697ac6653aSJeff Kirsher 	spin_lock_init(&priv->lock);
2770a9097a96SGiuseppe CAVALLARO 	spin_lock_init(&priv->tx_lock);
27717ac6653aSJeff Kirsher 
2772bfab27a1SGiuseppe CAVALLARO 	ret = register_netdev(ndev);
27737ac6653aSJeff Kirsher 	if (ret) {
2774cf3f047bSGiuseppe CAVALLARO 		pr_err("%s: ERROR %i registering the device\n", __func__, ret);
27756a81c26fSViresh Kumar 		goto error_netdev_register;
27767ac6653aSJeff Kirsher 	}
27777ac6653aSJeff Kirsher 
2778cd7201f4SGiuseppe CAVALLARO 	/* If a specific clk_csr value is passed from the platform
2779cd7201f4SGiuseppe CAVALLARO 	 * this means that the CSR Clock Range selection cannot be
2780cd7201f4SGiuseppe CAVALLARO 	 * changed at run-time and it is fixed. Viceversa the driver'll try to
2781cd7201f4SGiuseppe CAVALLARO 	 * set the MDC clock dynamically according to the csr actual
2782cd7201f4SGiuseppe CAVALLARO 	 * clock input.
2783cd7201f4SGiuseppe CAVALLARO 	 */
2784cd7201f4SGiuseppe CAVALLARO 	if (!priv->plat->clk_csr)
2785cd7201f4SGiuseppe CAVALLARO 		stmmac_clk_csr_set(priv);
2786cd7201f4SGiuseppe CAVALLARO 	else
2787cd7201f4SGiuseppe CAVALLARO 		priv->clk_csr = priv->plat->clk_csr;
2788cd7201f4SGiuseppe CAVALLARO 
2789e58bb43fSGiuseppe CAVALLARO 	stmmac_check_pcs_mode(priv);
2790e58bb43fSGiuseppe CAVALLARO 
27914d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
27924d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
27934bfcbd7aSFrancesco Virlinzi 		/* MDIO bus Registration */
27944bfcbd7aSFrancesco Virlinzi 		ret = stmmac_mdio_register(ndev);
27954bfcbd7aSFrancesco Virlinzi 		if (ret < 0) {
27964bfcbd7aSFrancesco Virlinzi 			pr_debug("%s: MDIO bus (id: %d) registration failed",
27974bfcbd7aSFrancesco Virlinzi 				 __func__, priv->plat->bus_id);
27986a81c26fSViresh Kumar 			goto error_mdio_register;
27994bfcbd7aSFrancesco Virlinzi 		}
2800e58bb43fSGiuseppe CAVALLARO 	}
28014bfcbd7aSFrancesco Virlinzi 
2802bfab27a1SGiuseppe CAVALLARO 	return priv;
28037ac6653aSJeff Kirsher 
28046a81c26fSViresh Kumar error_mdio_register:
28057ac6653aSJeff Kirsher 	unregister_netdev(ndev);
28066a81c26fSViresh Kumar error_netdev_register:
28076a81c26fSViresh Kumar 	netif_napi_del(&priv->napi);
280862866e98SChen-Yu Tsai error_hw_init:
280962866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
281062866e98SChen-Yu Tsai error_clk_get:
28117ac6653aSJeff Kirsher 	free_netdev(ndev);
28127ac6653aSJeff Kirsher 
2813c5e4ddbdSChen-Yu Tsai 	return ERR_PTR(ret);
28147ac6653aSJeff Kirsher }
28157ac6653aSJeff Kirsher 
28167ac6653aSJeff Kirsher /**
28177ac6653aSJeff Kirsher  * stmmac_dvr_remove
2818bfab27a1SGiuseppe CAVALLARO  * @ndev: net device pointer
28197ac6653aSJeff Kirsher  * Description: this function resets the TX/RX processes, disables the MAC RX/TX
2820bfab27a1SGiuseppe CAVALLARO  * changes the link status, releases the DMA descriptor rings.
28217ac6653aSJeff Kirsher  */
2822bfab27a1SGiuseppe CAVALLARO int stmmac_dvr_remove(struct net_device *ndev)
28237ac6653aSJeff Kirsher {
28247ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
28257ac6653aSJeff Kirsher 
28267ac6653aSJeff Kirsher 	pr_info("%s:\n\tremoving driver", __func__);
28277ac6653aSJeff Kirsher 
28287ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
28297ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
28307ac6653aSJeff Kirsher 
2831bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
28324d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
28334d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI)
28344bfcbd7aSFrancesco Virlinzi 		stmmac_mdio_unregister(ndev);
28357ac6653aSJeff Kirsher 	netif_carrier_off(ndev);
28367ac6653aSJeff Kirsher 	unregister_netdev(ndev);
2837c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2838c5e4ddbdSChen-Yu Tsai 		reset_control_assert(priv->stmmac_rst);
283962866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
28407ac6653aSJeff Kirsher 	free_netdev(ndev);
28417ac6653aSJeff Kirsher 
28427ac6653aSJeff Kirsher 	return 0;
28437ac6653aSJeff Kirsher }
28447ac6653aSJeff Kirsher 
28457ac6653aSJeff Kirsher #ifdef CONFIG_PM
2846bfab27a1SGiuseppe CAVALLARO int stmmac_suspend(struct net_device *ndev)
28477ac6653aSJeff Kirsher {
28487ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2849f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
28507ac6653aSJeff Kirsher 
28517ac6653aSJeff Kirsher 	if (!ndev || !netif_running(ndev))
28527ac6653aSJeff Kirsher 		return 0;
28537ac6653aSJeff Kirsher 
2854102463b1SFrancesco Virlinzi 	if (priv->phydev)
2855102463b1SFrancesco Virlinzi 		phy_stop(priv->phydev);
2856102463b1SFrancesco Virlinzi 
2857f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
28587ac6653aSJeff Kirsher 
28597ac6653aSJeff Kirsher 	netif_device_detach(ndev);
28607ac6653aSJeff Kirsher 	netif_stop_queue(ndev);
28617ac6653aSJeff Kirsher 
28627ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
28637ac6653aSJeff Kirsher 
28647ac6653aSJeff Kirsher 	/* Stop TX/RX DMA */
28657ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
28667ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
2867c24602efSGiuseppe CAVALLARO 
2868c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
28697ac6653aSJeff Kirsher 
28707ac6653aSJeff Kirsher 	/* Enable Power down mode by programming the PMT regs */
287189f7f2cfSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
28727ac6653aSJeff Kirsher 		priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
287389f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 1;
287489f7f2cfSSrinivas Kandagatla 	} else {
2875bfab27a1SGiuseppe CAVALLARO 		stmmac_set_mac(priv->ioaddr, false);
2876db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_sleep_state(priv->device);
2877ba1377ffSGiuseppe CAVALLARO 		/* Disable clock in case of PWM is off */
2878a630844dSStefan Roese 		clk_disable_unprepare(priv->stmmac_clk);
2879ba1377ffSGiuseppe CAVALLARO 	}
2880f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
28812d871aa0SVince Bridgers 
28822d871aa0SVince Bridgers 	priv->oldlink = 0;
28832d871aa0SVince Bridgers 	priv->speed = 0;
28842d871aa0SVince Bridgers 	priv->oldduplex = -1;
28857ac6653aSJeff Kirsher 	return 0;
28867ac6653aSJeff Kirsher }
28877ac6653aSJeff Kirsher 
2888bfab27a1SGiuseppe CAVALLARO int stmmac_resume(struct net_device *ndev)
28897ac6653aSJeff Kirsher {
28907ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2891f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
28927ac6653aSJeff Kirsher 
28937ac6653aSJeff Kirsher 	if (!netif_running(ndev))
28947ac6653aSJeff Kirsher 		return 0;
28957ac6653aSJeff Kirsher 
2896f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
28977ac6653aSJeff Kirsher 
28987ac6653aSJeff Kirsher 	/* Power Down bit, into the PM register, is cleared
28997ac6653aSJeff Kirsher 	 * automatically as soon as a magic packet or a Wake-up frame
29007ac6653aSJeff Kirsher 	 * is received. Anyway, it's better to manually clear
29017ac6653aSJeff Kirsher 	 * this bit because it can generate problems while resuming
2902ceb69499SGiuseppe CAVALLARO 	 * from another devices (e.g. serial console).
2903ceb69499SGiuseppe CAVALLARO 	 */
2904623997fbSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
29057ac6653aSJeff Kirsher 		priv->hw->mac->pmt(priv->ioaddr, 0);
290689f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 0;
2907623997fbSSrinivas Kandagatla 	} else {
2908db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_default_state(priv->device);
2909ba1377ffSGiuseppe CAVALLARO 		/* enable the clk prevously disabled */
2910a630844dSStefan Roese 		clk_prepare_enable(priv->stmmac_clk);
2911623997fbSSrinivas Kandagatla 		/* reset the phy so that it's ready */
2912623997fbSSrinivas Kandagatla 		if (priv->mii)
2913623997fbSSrinivas Kandagatla 			stmmac_mdio_reset(priv->mii);
2914623997fbSSrinivas Kandagatla 	}
29157ac6653aSJeff Kirsher 
29167ac6653aSJeff Kirsher 	netif_device_attach(ndev);
29177ac6653aSJeff Kirsher 
2918623997fbSSrinivas Kandagatla 	stmmac_hw_setup(ndev);
29197ac6653aSJeff Kirsher 
29207ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
29217ac6653aSJeff Kirsher 
29227ac6653aSJeff Kirsher 	netif_start_queue(ndev);
29237ac6653aSJeff Kirsher 
2924f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
2925102463b1SFrancesco Virlinzi 
2926102463b1SFrancesco Virlinzi 	if (priv->phydev)
2927102463b1SFrancesco Virlinzi 		phy_start(priv->phydev);
2928102463b1SFrancesco Virlinzi 
29297ac6653aSJeff Kirsher 	return 0;
29307ac6653aSJeff Kirsher }
29317ac6653aSJeff Kirsher #endif /* CONFIG_PM */
29327ac6653aSJeff Kirsher 
293333d5e332SGiuseppe CAVALLARO /* Driver can be configured w/ and w/ both PCI and Platf drivers
293433d5e332SGiuseppe CAVALLARO  * depending on the configuration selected.
293533d5e332SGiuseppe CAVALLARO  */
2936ba27ec66SGiuseppe CAVALLARO static int __init stmmac_init(void)
2937ba27ec66SGiuseppe CAVALLARO {
2938493682b8SKonstantin Khlebnikov 	int ret;
2939ba27ec66SGiuseppe CAVALLARO 
2940493682b8SKonstantin Khlebnikov 	ret = stmmac_register_platform();
2941493682b8SKonstantin Khlebnikov 	if (ret)
2942493682b8SKonstantin Khlebnikov 		goto err;
2943493682b8SKonstantin Khlebnikov 	ret = stmmac_register_pci();
2944493682b8SKonstantin Khlebnikov 	if (ret)
2945493682b8SKonstantin Khlebnikov 		goto err_pci;
294633d5e332SGiuseppe CAVALLARO 	return 0;
2947493682b8SKonstantin Khlebnikov err_pci:
2948493682b8SKonstantin Khlebnikov 	stmmac_unregister_platform();
2949493682b8SKonstantin Khlebnikov err:
2950493682b8SKonstantin Khlebnikov 	pr_err("stmmac: driver registration failed\n");
2951493682b8SKonstantin Khlebnikov 	return ret;
2952ba27ec66SGiuseppe CAVALLARO }
2953ba27ec66SGiuseppe CAVALLARO 
2954ba27ec66SGiuseppe CAVALLARO static void __exit stmmac_exit(void)
2955ba27ec66SGiuseppe CAVALLARO {
295633d5e332SGiuseppe CAVALLARO 	stmmac_unregister_platform();
295733d5e332SGiuseppe CAVALLARO 	stmmac_unregister_pci();
2958ba27ec66SGiuseppe CAVALLARO }
2959ba27ec66SGiuseppe CAVALLARO 
2960ba27ec66SGiuseppe CAVALLARO module_init(stmmac_init);
2961ba27ec66SGiuseppe CAVALLARO module_exit(stmmac_exit);
2962ba27ec66SGiuseppe CAVALLARO 
29637ac6653aSJeff Kirsher #ifndef MODULE
29647ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str)
29657ac6653aSJeff Kirsher {
29667ac6653aSJeff Kirsher 	char *opt;
29677ac6653aSJeff Kirsher 
29687ac6653aSJeff Kirsher 	if (!str || !*str)
29697ac6653aSJeff Kirsher 		return -EINVAL;
29707ac6653aSJeff Kirsher 	while ((opt = strsep(&str, ",")) != NULL) {
29717ac6653aSJeff Kirsher 		if (!strncmp(opt, "debug:", 6)) {
2972ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &debug))
29737ac6653aSJeff Kirsher 				goto err;
29747ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "phyaddr:", 8)) {
2975ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 8, 0, &phyaddr))
29767ac6653aSJeff Kirsher 				goto err;
29777ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_txsize:", 11)) {
2978ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_txsize))
29797ac6653aSJeff Kirsher 				goto err;
29807ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_rxsize:", 11)) {
2981ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_rxsize))
29827ac6653aSJeff Kirsher 				goto err;
29837ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "buf_sz:", 7)) {
2984ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 7, 0, &buf_sz))
29857ac6653aSJeff Kirsher 				goto err;
29867ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "tc:", 3)) {
2987ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 3, 0, &tc))
29887ac6653aSJeff Kirsher 				goto err;
29897ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "watchdog:", 9)) {
2990ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 9, 0, &watchdog))
29917ac6653aSJeff Kirsher 				goto err;
29927ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "flow_ctrl:", 10)) {
2993ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &flow_ctrl))
29947ac6653aSJeff Kirsher 				goto err;
29957ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "pause:", 6)) {
2996ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &pause))
29977ac6653aSJeff Kirsher 				goto err;
2998506f669cSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "eee_timer:", 10)) {
2999d765955dSGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &eee_timer))
3000d765955dSGiuseppe CAVALLARO 				goto err;
30014a7d666aSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "chain_mode:", 11)) {
30024a7d666aSGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &chain_mode))
30034a7d666aSGiuseppe CAVALLARO 				goto err;
30047ac6653aSJeff Kirsher 		}
30057ac6653aSJeff Kirsher 	}
30067ac6653aSJeff Kirsher 	return 0;
30077ac6653aSJeff Kirsher 
30087ac6653aSJeff Kirsher err:
30097ac6653aSJeff Kirsher 	pr_err("%s: ERROR broken module parameter conversion", __func__);
30107ac6653aSJeff Kirsher 	return -EINVAL;
30117ac6653aSJeff Kirsher }
30127ac6653aSJeff Kirsher 
30137ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt);
3014ceb69499SGiuseppe CAVALLARO #endif /* MODULE */
30156fc0d0f2SGiuseppe Cavallaro 
30166fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
30176fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
30186fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL");
3019