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))
2367ed24bbeSVince Bridgers 		priv->hw->mac->set_eee_mode(priv->hw);
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 {
2477ed24bbeSVince Bridgers 	priv->hw->mac->reset_eee_mode(priv->hw);
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);
3017ed24bbeSVince Bridgers 				priv->hw->mac->set_eee_timer(priv->hw, 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 
3167ed24bbeSVince Bridgers 			priv->hw->mac->set_eee_timer(priv->hw,
317f5351ef7SGiuseppe CAVALLARO 						     STMMAC_DEFAULT_LIT_LS,
31883bf79b6SGiuseppe CAVALLARO 						     tx_lpi_timer);
319f5351ef7SGiuseppe CAVALLARO 		} else
320f5351ef7SGiuseppe CAVALLARO 			/* Set HW EEE according to the speed */
3217ed24bbeSVince Bridgers 			priv->hw->mac->set_eee_pls(priv->hw,
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;
6065566401fSGiuseppe CAVALLARO 		 * where, freq_div_ratio = clk_ptp_ref_i/50MHz
6075566401fSGiuseppe CAVALLARO 		 * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
6085566401fSGiuseppe CAVALLARO 		 * NOTE: clk_ptp_ref_i 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);
6155566401fSGiuseppe CAVALLARO 		priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
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 
6415566401fSGiuseppe CAVALLARO 	/* Fall-back to main clock in case of no PTP ref is passed */
6425566401fSGiuseppe CAVALLARO 	priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref");
6435566401fSGiuseppe CAVALLARO 	if (IS_ERR(priv->clk_ptp_ref)) {
6445566401fSGiuseppe CAVALLARO 		priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk);
6455566401fSGiuseppe CAVALLARO 		priv->clk_ptp_ref = NULL;
6465566401fSGiuseppe CAVALLARO 	} else {
6475566401fSGiuseppe CAVALLARO 		clk_prepare_enable(priv->clk_ptp_ref);
6485566401fSGiuseppe CAVALLARO 		priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref);
6495566401fSGiuseppe CAVALLARO 	}
6505566401fSGiuseppe CAVALLARO 
651891434b1SRayagond Kokatanur 	priv->adv_ts = 0;
6527cd01399SVince Bridgers 	if (priv->dma_cap.atime_stamp && priv->extend_desc)
653891434b1SRayagond Kokatanur 		priv->adv_ts = 1;
6547cd01399SVince Bridgers 
6557cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
6567cd01399SVince Bridgers 		pr_debug("IEEE 1588-2002 Time Stamp supported\n");
6577cd01399SVince Bridgers 
6587cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->adv_ts)
6597cd01399SVince Bridgers 		pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
660891434b1SRayagond Kokatanur 
661891434b1SRayagond Kokatanur 	priv->hw->ptp = &stmmac_ptp;
662891434b1SRayagond Kokatanur 	priv->hwts_tx_en = 0;
663891434b1SRayagond Kokatanur 	priv->hwts_rx_en = 0;
66492ba6888SRayagond Kokatanur 
66592ba6888SRayagond Kokatanur 	return stmmac_ptp_register(priv);
66692ba6888SRayagond Kokatanur }
66792ba6888SRayagond Kokatanur 
66892ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv)
66992ba6888SRayagond Kokatanur {
6705566401fSGiuseppe CAVALLARO 	if (priv->clk_ptp_ref)
6715566401fSGiuseppe CAVALLARO 		clk_disable_unprepare(priv->clk_ptp_ref);
67292ba6888SRayagond Kokatanur 	stmmac_ptp_unregister(priv);
673891434b1SRayagond Kokatanur }
674891434b1SRayagond Kokatanur 
6757ac6653aSJeff Kirsher /**
6767ac6653aSJeff Kirsher  * stmmac_adjust_link
6777ac6653aSJeff Kirsher  * @dev: net device structure
6787ac6653aSJeff Kirsher  * Description: it adjusts the link parameters.
6797ac6653aSJeff Kirsher  */
6807ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev)
6817ac6653aSJeff Kirsher {
6827ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
6837ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
6847ac6653aSJeff Kirsher 	unsigned long flags;
6857ac6653aSJeff Kirsher 	int new_state = 0;
6867ac6653aSJeff Kirsher 	unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
6877ac6653aSJeff Kirsher 
6887ac6653aSJeff Kirsher 	if (phydev == NULL)
6897ac6653aSJeff Kirsher 		return;
6907ac6653aSJeff Kirsher 
6917ac6653aSJeff Kirsher 	spin_lock_irqsave(&priv->lock, flags);
692d765955dSGiuseppe CAVALLARO 
6937ac6653aSJeff Kirsher 	if (phydev->link) {
6947ac6653aSJeff Kirsher 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
6957ac6653aSJeff Kirsher 
6967ac6653aSJeff Kirsher 		/* Now we make sure that we can be in full duplex mode.
6977ac6653aSJeff Kirsher 		 * If not, we operate in half-duplex mode. */
6987ac6653aSJeff Kirsher 		if (phydev->duplex != priv->oldduplex) {
6997ac6653aSJeff Kirsher 			new_state = 1;
7007ac6653aSJeff Kirsher 			if (!(phydev->duplex))
7017ac6653aSJeff Kirsher 				ctrl &= ~priv->hw->link.duplex;
7027ac6653aSJeff Kirsher 			else
7037ac6653aSJeff Kirsher 				ctrl |= priv->hw->link.duplex;
7047ac6653aSJeff Kirsher 			priv->oldduplex = phydev->duplex;
7057ac6653aSJeff Kirsher 		}
7067ac6653aSJeff Kirsher 		/* Flow Control operation */
7077ac6653aSJeff Kirsher 		if (phydev->pause)
7087ed24bbeSVince Bridgers 			priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex,
7097ac6653aSJeff Kirsher 						 fc, pause_time);
7107ac6653aSJeff Kirsher 
7117ac6653aSJeff Kirsher 		if (phydev->speed != priv->speed) {
7127ac6653aSJeff Kirsher 			new_state = 1;
7137ac6653aSJeff Kirsher 			switch (phydev->speed) {
7147ac6653aSJeff Kirsher 			case 1000:
7157ac6653aSJeff Kirsher 				if (likely(priv->plat->has_gmac))
7167ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7177ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7187ac6653aSJeff Kirsher 				break;
7197ac6653aSJeff Kirsher 			case 100:
7207ac6653aSJeff Kirsher 			case 10:
7217ac6653aSJeff Kirsher 				if (priv->plat->has_gmac) {
7227ac6653aSJeff Kirsher 					ctrl |= priv->hw->link.port;
7237ac6653aSJeff Kirsher 					if (phydev->speed == SPEED_100) {
7247ac6653aSJeff Kirsher 						ctrl |= priv->hw->link.speed;
7257ac6653aSJeff Kirsher 					} else {
7267ac6653aSJeff Kirsher 						ctrl &= ~(priv->hw->link.speed);
7277ac6653aSJeff Kirsher 					}
7287ac6653aSJeff Kirsher 				} else {
7297ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7307ac6653aSJeff Kirsher 				}
7317ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7327ac6653aSJeff Kirsher 				break;
7337ac6653aSJeff Kirsher 			default:
7347ac6653aSJeff Kirsher 				if (netif_msg_link(priv))
735ceb69499SGiuseppe CAVALLARO 					pr_warn("%s: Speed (%d) not 10/100\n",
736ceb69499SGiuseppe CAVALLARO 						dev->name, phydev->speed);
7377ac6653aSJeff Kirsher 				break;
7387ac6653aSJeff Kirsher 			}
7397ac6653aSJeff Kirsher 
7407ac6653aSJeff Kirsher 			priv->speed = phydev->speed;
7417ac6653aSJeff Kirsher 		}
7427ac6653aSJeff Kirsher 
7437ac6653aSJeff Kirsher 		writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
7447ac6653aSJeff Kirsher 
7457ac6653aSJeff Kirsher 		if (!priv->oldlink) {
7467ac6653aSJeff Kirsher 			new_state = 1;
7477ac6653aSJeff Kirsher 			priv->oldlink = 1;
7487ac6653aSJeff Kirsher 		}
7497ac6653aSJeff Kirsher 	} else if (priv->oldlink) {
7507ac6653aSJeff Kirsher 		new_state = 1;
7517ac6653aSJeff Kirsher 		priv->oldlink = 0;
7527ac6653aSJeff Kirsher 		priv->speed = 0;
7537ac6653aSJeff Kirsher 		priv->oldduplex = -1;
7547ac6653aSJeff Kirsher 	}
7557ac6653aSJeff Kirsher 
7567ac6653aSJeff Kirsher 	if (new_state && netif_msg_link(priv))
7577ac6653aSJeff Kirsher 		phy_print_status(phydev);
7587ac6653aSJeff Kirsher 
759f5351ef7SGiuseppe CAVALLARO 	/* At this stage, it could be needed to setup the EEE or adjust some
760f5351ef7SGiuseppe CAVALLARO 	 * MAC related HW registers.
761f5351ef7SGiuseppe CAVALLARO 	 */
762f5351ef7SGiuseppe CAVALLARO 	priv->eee_enabled = stmmac_eee_init(priv);
763d765955dSGiuseppe CAVALLARO 
7647ac6653aSJeff Kirsher 	spin_unlock_irqrestore(&priv->lock, flags);
7657ac6653aSJeff Kirsher }
7667ac6653aSJeff Kirsher 
76732ceabcaSGiuseppe CAVALLARO /**
76832ceabcaSGiuseppe CAVALLARO  * stmmac_check_pcs_mode: verify if RGMII/SGMII is supported
76932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
77032ceabcaSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PCS.
77132ceabcaSGiuseppe CAVALLARO  * Physical Coding Sublayer (PCS) interface that can be used when the MAC is
77232ceabcaSGiuseppe CAVALLARO  * configured for the TBI, RTBI, or SGMII PHY interface.
77332ceabcaSGiuseppe CAVALLARO  */
774e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
775e58bb43fSGiuseppe CAVALLARO {
776e58bb43fSGiuseppe CAVALLARO 	int interface = priv->plat->interface;
777e58bb43fSGiuseppe CAVALLARO 
778e58bb43fSGiuseppe CAVALLARO 	if (priv->dma_cap.pcs) {
7790d909dcdSByungho An 		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
7800d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
7810d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
7820d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
783e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS RGMII support enable\n");
784e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_RGMII;
7850d909dcdSByungho An 		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
786e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS SGMII support enable\n");
787e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_SGMII;
788e58bb43fSGiuseppe CAVALLARO 		}
789e58bb43fSGiuseppe CAVALLARO 	}
790e58bb43fSGiuseppe CAVALLARO }
791e58bb43fSGiuseppe CAVALLARO 
7927ac6653aSJeff Kirsher /**
7937ac6653aSJeff Kirsher  * stmmac_init_phy - PHY initialization
7947ac6653aSJeff Kirsher  * @dev: net device structure
7957ac6653aSJeff Kirsher  * Description: it initializes the driver's PHY state, and attaches the PHY
7967ac6653aSJeff Kirsher  * to the mac driver.
7977ac6653aSJeff Kirsher  *  Return value:
7987ac6653aSJeff Kirsher  *  0 on success
7997ac6653aSJeff Kirsher  */
8007ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev)
8017ac6653aSJeff Kirsher {
8027ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
8037ac6653aSJeff Kirsher 	struct phy_device *phydev;
804d765955dSGiuseppe CAVALLARO 	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
8057ac6653aSJeff Kirsher 	char bus_id[MII_BUS_ID_SIZE];
80679ee1dc3SSrinivas Kandagatla 	int interface = priv->plat->interface;
8079cbadf09SSrinivas Kandagatla 	int max_speed = priv->plat->max_speed;
8087ac6653aSJeff Kirsher 	priv->oldlink = 0;
8097ac6653aSJeff Kirsher 	priv->speed = 0;
8107ac6653aSJeff Kirsher 	priv->oldduplex = -1;
8117ac6653aSJeff Kirsher 
812f142af2eSSrinivas Kandagatla 	if (priv->plat->phy_bus_name)
813f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
814f142af2eSSrinivas Kandagatla 			 priv->plat->phy_bus_name, priv->plat->bus_id);
815f142af2eSSrinivas Kandagatla 	else
816f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
817f142af2eSSrinivas Kandagatla 			 priv->plat->bus_id);
818f142af2eSSrinivas Kandagatla 
819d765955dSGiuseppe CAVALLARO 	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
8207ac6653aSJeff Kirsher 		 priv->plat->phy_addr);
821d765955dSGiuseppe CAVALLARO 	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
8227ac6653aSJeff Kirsher 
823f9a8f83bSFlorian Fainelli 	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
8247ac6653aSJeff Kirsher 
8257ac6653aSJeff Kirsher 	if (IS_ERR(phydev)) {
8267ac6653aSJeff Kirsher 		pr_err("%s: Could not attach to PHY\n", dev->name);
8277ac6653aSJeff Kirsher 		return PTR_ERR(phydev);
8287ac6653aSJeff Kirsher 	}
8297ac6653aSJeff Kirsher 
83079ee1dc3SSrinivas Kandagatla 	/* Stop Advertising 1000BASE Capability if interface is not GMII */
831c5b9b4e4SSrinivas Kandagatla 	if ((interface == PHY_INTERFACE_MODE_MII) ||
8329cbadf09SSrinivas Kandagatla 	    (interface == PHY_INTERFACE_MODE_RMII) ||
8339cbadf09SSrinivas Kandagatla 		(max_speed < 1000 &&  max_speed > 0))
834c5b9b4e4SSrinivas Kandagatla 		phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
835c5b9b4e4SSrinivas Kandagatla 					 SUPPORTED_1000baseT_Full);
83679ee1dc3SSrinivas Kandagatla 
8377ac6653aSJeff Kirsher 	/*
8387ac6653aSJeff Kirsher 	 * Broken HW is sometimes missing the pull-up resistor on the
8397ac6653aSJeff Kirsher 	 * MDIO line, which results in reads to non-existent devices returning
8407ac6653aSJeff Kirsher 	 * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
8417ac6653aSJeff Kirsher 	 * device as well.
8427ac6653aSJeff Kirsher 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
8437ac6653aSJeff Kirsher 	 */
8447ac6653aSJeff Kirsher 	if (phydev->phy_id == 0) {
8457ac6653aSJeff Kirsher 		phy_disconnect(phydev);
8467ac6653aSJeff Kirsher 		return -ENODEV;
8477ac6653aSJeff Kirsher 	}
8487ac6653aSJeff Kirsher 	pr_debug("stmmac_init_phy:  %s: attached to PHY (UID 0x%x)"
8497ac6653aSJeff Kirsher 		 " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
8507ac6653aSJeff Kirsher 
8517ac6653aSJeff Kirsher 	priv->phydev = phydev;
8527ac6653aSJeff Kirsher 
8537ac6653aSJeff Kirsher 	return 0;
8547ac6653aSJeff Kirsher }
8557ac6653aSJeff Kirsher 
8567ac6653aSJeff Kirsher /**
85732ceabcaSGiuseppe CAVALLARO  * stmmac_display_ring: display ring
85832ceabcaSGiuseppe CAVALLARO  * @head: pointer to the head of the ring passed.
8597ac6653aSJeff Kirsher  * @size: size of the ring.
86032ceabcaSGiuseppe CAVALLARO  * @extend_desc: to verify if extended descriptors are used.
861c24602efSGiuseppe CAVALLARO  * Description: display the control/status and buffer descriptors.
8627ac6653aSJeff Kirsher  */
863c24602efSGiuseppe CAVALLARO static void stmmac_display_ring(void *head, int size, int extend_desc)
8647ac6653aSJeff Kirsher {
8657ac6653aSJeff Kirsher 	int i;
866c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
867c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
868c24602efSGiuseppe CAVALLARO 
8697ac6653aSJeff Kirsher 	for (i = 0; i < size; i++) {
870c24602efSGiuseppe CAVALLARO 		u64 x;
871c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
872c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
873c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
874c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(ep),
875c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
876c24602efSGiuseppe CAVALLARO 				ep->basic.des2, ep->basic.des3);
877c24602efSGiuseppe CAVALLARO 			ep++;
878c24602efSGiuseppe CAVALLARO 		} else {
879c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
880c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x",
881c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(p),
882c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
883c24602efSGiuseppe CAVALLARO 				p->des2, p->des3);
884c24602efSGiuseppe CAVALLARO 			p++;
885c24602efSGiuseppe CAVALLARO 		}
8867ac6653aSJeff Kirsher 		pr_info("\n");
8877ac6653aSJeff Kirsher 	}
8887ac6653aSJeff Kirsher }
8897ac6653aSJeff Kirsher 
890c24602efSGiuseppe CAVALLARO static void stmmac_display_rings(struct stmmac_priv *priv)
891c24602efSGiuseppe CAVALLARO {
892c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
893c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
894c24602efSGiuseppe CAVALLARO 
895c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
896c24602efSGiuseppe CAVALLARO 		pr_info("Extended RX descriptor ring:\n");
897c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
898c24602efSGiuseppe CAVALLARO 		pr_info("Extended TX descriptor ring:\n");
899c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
900c24602efSGiuseppe CAVALLARO 	} else {
901c24602efSGiuseppe CAVALLARO 		pr_info("RX descriptor ring:\n");
902c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
903c24602efSGiuseppe CAVALLARO 		pr_info("TX descriptor ring:\n");
904c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
905c24602efSGiuseppe CAVALLARO 	}
906c24602efSGiuseppe CAVALLARO }
907c24602efSGiuseppe CAVALLARO 
908286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize)
909286a8372SGiuseppe CAVALLARO {
910286a8372SGiuseppe CAVALLARO 	int ret = bufsize;
911286a8372SGiuseppe CAVALLARO 
912286a8372SGiuseppe CAVALLARO 	if (mtu >= BUF_SIZE_4KiB)
913286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_8KiB;
914286a8372SGiuseppe CAVALLARO 	else if (mtu >= BUF_SIZE_2KiB)
915286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_4KiB;
916d916701cSGiuseppe CAVALLARO 	else if (mtu > DEFAULT_BUFSIZE)
917286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_2KiB;
918286a8372SGiuseppe CAVALLARO 	else
919d916701cSGiuseppe CAVALLARO 		ret = DEFAULT_BUFSIZE;
920286a8372SGiuseppe CAVALLARO 
921286a8372SGiuseppe CAVALLARO 	return ret;
922286a8372SGiuseppe CAVALLARO }
923286a8372SGiuseppe CAVALLARO 
92432ceabcaSGiuseppe CAVALLARO /**
92532ceabcaSGiuseppe CAVALLARO  * stmmac_clear_descriptors: clear descriptors
92632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
92732ceabcaSGiuseppe CAVALLARO  * Description: this function is called to clear the tx and rx descriptors
92832ceabcaSGiuseppe CAVALLARO  * in case of both basic and extended descriptors are used.
92932ceabcaSGiuseppe CAVALLARO  */
930c24602efSGiuseppe CAVALLARO static void stmmac_clear_descriptors(struct stmmac_priv *priv)
931c24602efSGiuseppe CAVALLARO {
932c24602efSGiuseppe CAVALLARO 	int i;
933c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
934c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
935c24602efSGiuseppe CAVALLARO 
936c24602efSGiuseppe CAVALLARO 	/* Clear the Rx/Tx descriptors */
937c24602efSGiuseppe CAVALLARO 	for (i = 0; i < rxsize; i++)
938c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
939c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
940c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
941c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
942c24602efSGiuseppe CAVALLARO 		else
943c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_rx[i],
944c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
945c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
946c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
947c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
948c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
949c24602efSGiuseppe CAVALLARO 						     priv->mode,
950c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
951c24602efSGiuseppe CAVALLARO 		else
952c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
953c24602efSGiuseppe CAVALLARO 						     priv->mode,
954c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
955c24602efSGiuseppe CAVALLARO }
956c24602efSGiuseppe CAVALLARO 
957c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
958c24602efSGiuseppe CAVALLARO 				  int i)
959c24602efSGiuseppe CAVALLARO {
960c24602efSGiuseppe CAVALLARO 	struct sk_buff *skb;
961c24602efSGiuseppe CAVALLARO 
962c24602efSGiuseppe CAVALLARO 	skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
963c24602efSGiuseppe CAVALLARO 				 GFP_KERNEL);
96456329137SBartlomiej Zolnierkiewicz 	if (!skb) {
965c24602efSGiuseppe CAVALLARO 		pr_err("%s: Rx init fails; skb is NULL\n", __func__);
96656329137SBartlomiej Zolnierkiewicz 		return -ENOMEM;
967c24602efSGiuseppe CAVALLARO 	}
968c24602efSGiuseppe CAVALLARO 	skb_reserve(skb, NET_IP_ALIGN);
969c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff[i] = skb;
970c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
971c24602efSGiuseppe CAVALLARO 						priv->dma_buf_sz,
972c24602efSGiuseppe CAVALLARO 						DMA_FROM_DEVICE);
97356329137SBartlomiej Zolnierkiewicz 	if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) {
97456329137SBartlomiej Zolnierkiewicz 		pr_err("%s: DMA mapping error\n", __func__);
97556329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(skb);
97656329137SBartlomiej Zolnierkiewicz 		return -EINVAL;
97756329137SBartlomiej Zolnierkiewicz 	}
978c24602efSGiuseppe CAVALLARO 
979c24602efSGiuseppe CAVALLARO 	p->des2 = priv->rx_skbuff_dma[i];
980c24602efSGiuseppe CAVALLARO 
98129896a67SGiuseppe CAVALLARO 	if ((priv->hw->mode->init_desc3) &&
982c24602efSGiuseppe CAVALLARO 	    (priv->dma_buf_sz == BUF_SIZE_16KiB))
98329896a67SGiuseppe CAVALLARO 		priv->hw->mode->init_desc3(p);
984c24602efSGiuseppe CAVALLARO 
985c24602efSGiuseppe CAVALLARO 	return 0;
986c24602efSGiuseppe CAVALLARO }
987c24602efSGiuseppe CAVALLARO 
98856329137SBartlomiej Zolnierkiewicz static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i)
98956329137SBartlomiej Zolnierkiewicz {
99056329137SBartlomiej Zolnierkiewicz 	if (priv->rx_skbuff[i]) {
99156329137SBartlomiej Zolnierkiewicz 		dma_unmap_single(priv->device, priv->rx_skbuff_dma[i],
99256329137SBartlomiej Zolnierkiewicz 				 priv->dma_buf_sz, DMA_FROM_DEVICE);
99356329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(priv->rx_skbuff[i]);
99456329137SBartlomiej Zolnierkiewicz 	}
99556329137SBartlomiej Zolnierkiewicz 	priv->rx_skbuff[i] = NULL;
99656329137SBartlomiej Zolnierkiewicz }
99756329137SBartlomiej Zolnierkiewicz 
9987ac6653aSJeff Kirsher /**
9997ac6653aSJeff Kirsher  * init_dma_desc_rings - init the RX/TX descriptor rings
10007ac6653aSJeff Kirsher  * @dev: net device structure
10017ac6653aSJeff Kirsher  * Description:  this function initializes the DMA RX/TX descriptors
1002286a8372SGiuseppe CAVALLARO  * and allocates the socket buffers. It suppors the chained and ring
1003286a8372SGiuseppe CAVALLARO  * modes.
10047ac6653aSJeff Kirsher  */
100556329137SBartlomiej Zolnierkiewicz static int init_dma_desc_rings(struct net_device *dev)
10067ac6653aSJeff Kirsher {
10077ac6653aSJeff Kirsher 	int i;
10087ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
10097ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
10107ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
10114a7d666aSGiuseppe CAVALLARO 	unsigned int bfsize = 0;
101256329137SBartlomiej Zolnierkiewicz 	int ret = -ENOMEM;
10137ac6653aSJeff Kirsher 
101429896a67SGiuseppe CAVALLARO 	if (priv->hw->mode->set_16kib_bfsize)
101529896a67SGiuseppe CAVALLARO 		bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu);
1016286a8372SGiuseppe CAVALLARO 
10174a7d666aSGiuseppe CAVALLARO 	if (bfsize < BUF_SIZE_16KiB)
1018286a8372SGiuseppe CAVALLARO 		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
10197ac6653aSJeff Kirsher 
10202618abb7SVince Bridgers 	priv->dma_buf_sz = bfsize;
10212618abb7SVince Bridgers 
102283d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv))
102383d7af64SGiuseppe CAVALLARO 		pr_debug("%s: txsize %d, rxsize %d, bfsize %d\n", __func__,
10247ac6653aSJeff Kirsher 			 txsize, rxsize, bfsize);
10257ac6653aSJeff Kirsher 
102683d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv)) {
1027c24602efSGiuseppe CAVALLARO 		pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
1028c24602efSGiuseppe CAVALLARO 			 (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
10297ac6653aSJeff Kirsher 
10307ac6653aSJeff Kirsher 		/* RX INITIALIZATION */
103183d7af64SGiuseppe CAVALLARO 		pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n");
103283d7af64SGiuseppe CAVALLARO 	}
10337ac6653aSJeff Kirsher 	for (i = 0; i < rxsize; i++) {
1034c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1035c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1036c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_erx + i)->basic);
1037c24602efSGiuseppe CAVALLARO 		else
1038c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + i;
10397ac6653aSJeff Kirsher 
104056329137SBartlomiej Zolnierkiewicz 		ret = stmmac_init_rx_buffers(priv, p, i);
104156329137SBartlomiej Zolnierkiewicz 		if (ret)
104256329137SBartlomiej Zolnierkiewicz 			goto err_init_rx_buffers;
1043286a8372SGiuseppe CAVALLARO 
104483d7af64SGiuseppe CAVALLARO 		if (netif_msg_probe(priv))
104583d7af64SGiuseppe CAVALLARO 			pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
104683d7af64SGiuseppe CAVALLARO 				 priv->rx_skbuff[i]->data,
104783d7af64SGiuseppe CAVALLARO 				 (unsigned int)priv->rx_skbuff_dma[i]);
10487ac6653aSJeff Kirsher 	}
10497ac6653aSJeff Kirsher 	priv->cur_rx = 0;
10507ac6653aSJeff Kirsher 	priv->dirty_rx = (unsigned int)(i - rxsize);
10517ac6653aSJeff Kirsher 	buf_sz = bfsize;
10527ac6653aSJeff Kirsher 
1053c24602efSGiuseppe CAVALLARO 	/* Setup the chained descriptor addresses */
1054c24602efSGiuseppe CAVALLARO 	if (priv->mode == STMMAC_CHAIN_MODE) {
1055c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc) {
105629896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy,
1057c24602efSGiuseppe CAVALLARO 					     rxsize, 1);
105829896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy,
1059c24602efSGiuseppe CAVALLARO 					     txsize, 1);
1060c24602efSGiuseppe CAVALLARO 		} else {
106129896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy,
1062c24602efSGiuseppe CAVALLARO 					     rxsize, 0);
106329896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy,
1064c24602efSGiuseppe CAVALLARO 					     txsize, 0);
1065c24602efSGiuseppe CAVALLARO 		}
10667ac6653aSJeff Kirsher 	}
1067286a8372SGiuseppe CAVALLARO 
1068c24602efSGiuseppe CAVALLARO 	/* TX INITIALIZATION */
1069c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++) {
1070c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1071c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1072c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1073c24602efSGiuseppe CAVALLARO 		else
1074c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1075c24602efSGiuseppe CAVALLARO 		p->des2 = 0;
1076cf32deecSRayagond Kokatanur 		priv->tx_skbuff_dma[i] = 0;
1077c24602efSGiuseppe CAVALLARO 		priv->tx_skbuff[i] = NULL;
10784a7d666aSGiuseppe CAVALLARO 	}
1079c24602efSGiuseppe CAVALLARO 
10807ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
10817ac6653aSJeff Kirsher 	priv->cur_tx = 0;
10827ac6653aSJeff Kirsher 
1083c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
10847ac6653aSJeff Kirsher 
1085c24602efSGiuseppe CAVALLARO 	if (netif_msg_hw(priv))
1086c24602efSGiuseppe CAVALLARO 		stmmac_display_rings(priv);
108756329137SBartlomiej Zolnierkiewicz 
108856329137SBartlomiej Zolnierkiewicz 	return 0;
108956329137SBartlomiej Zolnierkiewicz err_init_rx_buffers:
109056329137SBartlomiej Zolnierkiewicz 	while (--i >= 0)
109156329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
109256329137SBartlomiej Zolnierkiewicz 	return ret;
10937ac6653aSJeff Kirsher }
10947ac6653aSJeff Kirsher 
10957ac6653aSJeff Kirsher static void dma_free_rx_skbufs(struct stmmac_priv *priv)
10967ac6653aSJeff Kirsher {
10977ac6653aSJeff Kirsher 	int i;
10987ac6653aSJeff Kirsher 
109956329137SBartlomiej Zolnierkiewicz 	for (i = 0; i < priv->dma_rx_size; i++)
110056329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
11017ac6653aSJeff Kirsher }
11027ac6653aSJeff Kirsher 
11037ac6653aSJeff Kirsher static void dma_free_tx_skbufs(struct stmmac_priv *priv)
11047ac6653aSJeff Kirsher {
11057ac6653aSJeff Kirsher 	int i;
11067ac6653aSJeff Kirsher 
11077ac6653aSJeff Kirsher 	for (i = 0; i < priv->dma_tx_size; i++) {
1108c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
110975e4364fSdamuzi000 
1110c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1111c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1112c24602efSGiuseppe CAVALLARO 		else
1113c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1114c24602efSGiuseppe CAVALLARO 
111575e4364fSdamuzi000 		if (priv->tx_skbuff_dma[i]) {
1116cf32deecSRayagond Kokatanur 			dma_unmap_single(priv->device,
1117cf32deecSRayagond Kokatanur 					 priv->tx_skbuff_dma[i],
11187ac6653aSJeff Kirsher 					 priv->hw->desc->get_tx_len(p),
11197ac6653aSJeff Kirsher 					 DMA_TO_DEVICE);
112075e4364fSdamuzi000 			priv->tx_skbuff_dma[i] = 0;
112175e4364fSdamuzi000 		}
112275e4364fSdamuzi000 
112375e4364fSdamuzi000 		if (priv->tx_skbuff[i] != NULL) {
11247ac6653aSJeff Kirsher 			dev_kfree_skb_any(priv->tx_skbuff[i]);
11257ac6653aSJeff Kirsher 			priv->tx_skbuff[i] = NULL;
11267ac6653aSJeff Kirsher 		}
11277ac6653aSJeff Kirsher 	}
11287ac6653aSJeff Kirsher }
11297ac6653aSJeff Kirsher 
113009f8d696SSrinivas Kandagatla static int alloc_dma_desc_resources(struct stmmac_priv *priv)
113109f8d696SSrinivas Kandagatla {
113209f8d696SSrinivas Kandagatla 	unsigned int txsize = priv->dma_tx_size;
113309f8d696SSrinivas Kandagatla 	unsigned int rxsize = priv->dma_rx_size;
113409f8d696SSrinivas Kandagatla 	int ret = -ENOMEM;
113509f8d696SSrinivas Kandagatla 
113609f8d696SSrinivas Kandagatla 	priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
113709f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
113809f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff_dma)
113909f8d696SSrinivas Kandagatla 		return -ENOMEM;
114009f8d696SSrinivas Kandagatla 
114109f8d696SSrinivas Kandagatla 	priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
114209f8d696SSrinivas Kandagatla 					GFP_KERNEL);
114309f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff)
114409f8d696SSrinivas Kandagatla 		goto err_rx_skbuff;
114509f8d696SSrinivas Kandagatla 
114609f8d696SSrinivas Kandagatla 	priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
114709f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
114809f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff_dma)
114909f8d696SSrinivas Kandagatla 		goto err_tx_skbuff_dma;
115009f8d696SSrinivas Kandagatla 
115109f8d696SSrinivas Kandagatla 	priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
115209f8d696SSrinivas Kandagatla 					GFP_KERNEL);
115309f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff)
115409f8d696SSrinivas Kandagatla 		goto err_tx_skbuff;
115509f8d696SSrinivas Kandagatla 
115609f8d696SSrinivas Kandagatla 	if (priv->extend_desc) {
115709f8d696SSrinivas Kandagatla 		priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
115809f8d696SSrinivas Kandagatla 						   sizeof(struct
115909f8d696SSrinivas Kandagatla 							  dma_extended_desc),
116009f8d696SSrinivas Kandagatla 						   &priv->dma_rx_phy,
116109f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
116209f8d696SSrinivas Kandagatla 		if (!priv->dma_erx)
116309f8d696SSrinivas Kandagatla 			goto err_dma;
116409f8d696SSrinivas Kandagatla 
116509f8d696SSrinivas Kandagatla 		priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
116609f8d696SSrinivas Kandagatla 						   sizeof(struct
116709f8d696SSrinivas Kandagatla 							  dma_extended_desc),
116809f8d696SSrinivas Kandagatla 						   &priv->dma_tx_phy,
116909f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
117009f8d696SSrinivas Kandagatla 		if (!priv->dma_etx) {
117109f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
117209f8d696SSrinivas Kandagatla 					sizeof(struct dma_extended_desc),
117309f8d696SSrinivas Kandagatla 					priv->dma_erx, priv->dma_rx_phy);
117409f8d696SSrinivas Kandagatla 			goto err_dma;
117509f8d696SSrinivas Kandagatla 		}
117609f8d696SSrinivas Kandagatla 	} else {
117709f8d696SSrinivas Kandagatla 		priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
117809f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
117909f8d696SSrinivas Kandagatla 						  &priv->dma_rx_phy,
118009f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
118109f8d696SSrinivas Kandagatla 		if (!priv->dma_rx)
118209f8d696SSrinivas Kandagatla 			goto err_dma;
118309f8d696SSrinivas Kandagatla 
118409f8d696SSrinivas Kandagatla 		priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
118509f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
118609f8d696SSrinivas Kandagatla 						  &priv->dma_tx_phy,
118709f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
118809f8d696SSrinivas Kandagatla 		if (!priv->dma_tx) {
118909f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
119009f8d696SSrinivas Kandagatla 					sizeof(struct dma_desc),
119109f8d696SSrinivas Kandagatla 					priv->dma_rx, priv->dma_rx_phy);
119209f8d696SSrinivas Kandagatla 			goto err_dma;
119309f8d696SSrinivas Kandagatla 		}
119409f8d696SSrinivas Kandagatla 	}
119509f8d696SSrinivas Kandagatla 
119609f8d696SSrinivas Kandagatla 	return 0;
119709f8d696SSrinivas Kandagatla 
119809f8d696SSrinivas Kandagatla err_dma:
119909f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff);
120009f8d696SSrinivas Kandagatla err_tx_skbuff:
120109f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff_dma);
120209f8d696SSrinivas Kandagatla err_tx_skbuff_dma:
120309f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff);
120409f8d696SSrinivas Kandagatla err_rx_skbuff:
120509f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff_dma);
120609f8d696SSrinivas Kandagatla 	return ret;
120709f8d696SSrinivas Kandagatla }
120809f8d696SSrinivas Kandagatla 
12097ac6653aSJeff Kirsher static void free_dma_desc_resources(struct stmmac_priv *priv)
12107ac6653aSJeff Kirsher {
12117ac6653aSJeff Kirsher 	/* Release the DMA TX/RX socket buffers */
12127ac6653aSJeff Kirsher 	dma_free_rx_skbufs(priv);
12137ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
12147ac6653aSJeff Kirsher 
1215ceb69499SGiuseppe CAVALLARO 	/* Free DMA regions of consistent memory previously allocated */
1216c24602efSGiuseppe CAVALLARO 	if (!priv->extend_desc) {
12177ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
12187ac6653aSJeff Kirsher 				  priv->dma_tx_size * sizeof(struct dma_desc),
12197ac6653aSJeff Kirsher 				  priv->dma_tx, priv->dma_tx_phy);
12207ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
12217ac6653aSJeff Kirsher 				  priv->dma_rx_size * sizeof(struct dma_desc),
12227ac6653aSJeff Kirsher 				  priv->dma_rx, priv->dma_rx_phy);
1223c24602efSGiuseppe CAVALLARO 	} else {
1224c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_tx_size *
1225c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1226c24602efSGiuseppe CAVALLARO 				  priv->dma_etx, priv->dma_tx_phy);
1227c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_rx_size *
1228c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1229c24602efSGiuseppe CAVALLARO 				  priv->dma_erx, priv->dma_rx_phy);
1230c24602efSGiuseppe CAVALLARO 	}
12317ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff_dma);
12327ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff);
1233cf32deecSRayagond Kokatanur 	kfree(priv->tx_skbuff_dma);
12347ac6653aSJeff Kirsher 	kfree(priv->tx_skbuff);
12357ac6653aSJeff Kirsher }
12367ac6653aSJeff Kirsher 
12377ac6653aSJeff Kirsher /**
12387ac6653aSJeff Kirsher  *  stmmac_dma_operation_mode - HW DMA operation mode
123932ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
12407ac6653aSJeff Kirsher  *  Description: it sets the DMA operation mode: tx/rx DMA thresholds
12417ac6653aSJeff Kirsher  *  or Store-And-Forward capability.
12427ac6653aSJeff Kirsher  */
12437ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
12447ac6653aSJeff Kirsher {
1245e2a240c7SSonic Zhang 	if (priv->plat->force_thresh_dma_mode)
1246e2a240c7SSonic Zhang 		priv->hw->dma->dma_mode(priv->ioaddr, tc, tc);
1247e2a240c7SSonic Zhang 	else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
12487ac6653aSJeff Kirsher 		/*
12497ac6653aSJeff Kirsher 		 * In case of GMAC, SF mode can be enabled
12507ac6653aSJeff Kirsher 		 * to perform the TX COE in HW. This depends on:
12517ac6653aSJeff Kirsher 		 * 1) TX COE if actually supported
12527ac6653aSJeff Kirsher 		 * 2) There is no bugged Jumbo frame support
12537ac6653aSJeff Kirsher 		 *    that needs to not insert csum in the TDES.
12547ac6653aSJeff Kirsher 		 */
1255ceb69499SGiuseppe CAVALLARO 		priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE);
12567ac6653aSJeff Kirsher 		tc = SF_DMA_MODE;
12577ac6653aSJeff Kirsher 	} else
12587ac6653aSJeff Kirsher 		priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
12597ac6653aSJeff Kirsher }
12607ac6653aSJeff Kirsher 
12617ac6653aSJeff Kirsher /**
12629125cdd1SGiuseppe CAVALLARO  * stmmac_tx_clean:
126332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
12647ac6653aSJeff Kirsher  * Description: it reclaims resources after transmission completes.
12657ac6653aSJeff Kirsher  */
12669125cdd1SGiuseppe CAVALLARO static void stmmac_tx_clean(struct stmmac_priv *priv)
12677ac6653aSJeff Kirsher {
12687ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
12697ac6653aSJeff Kirsher 
1270a9097a96SGiuseppe CAVALLARO 	spin_lock(&priv->tx_lock);
1271a9097a96SGiuseppe CAVALLARO 
12729125cdd1SGiuseppe CAVALLARO 	priv->xstats.tx_clean++;
12739125cdd1SGiuseppe CAVALLARO 
12747ac6653aSJeff Kirsher 	while (priv->dirty_tx != priv->cur_tx) {
12757ac6653aSJeff Kirsher 		int last;
12767ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_tx % txsize;
12777ac6653aSJeff Kirsher 		struct sk_buff *skb = priv->tx_skbuff[entry];
1278c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1279c24602efSGiuseppe CAVALLARO 
1280c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1281c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_etx + entry);
1282c24602efSGiuseppe CAVALLARO 		else
1283c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + entry;
12847ac6653aSJeff Kirsher 
12857ac6653aSJeff Kirsher 		/* Check if the descriptor is owned by the DMA. */
12867ac6653aSJeff Kirsher 		if (priv->hw->desc->get_tx_owner(p))
12877ac6653aSJeff Kirsher 			break;
12887ac6653aSJeff Kirsher 
1289c24602efSGiuseppe CAVALLARO 		/* Verify tx error by looking at the last segment. */
12907ac6653aSJeff Kirsher 		last = priv->hw->desc->get_tx_ls(p);
12917ac6653aSJeff Kirsher 		if (likely(last)) {
12927ac6653aSJeff Kirsher 			int tx_error =
12937ac6653aSJeff Kirsher 			    priv->hw->desc->tx_status(&priv->dev->stats,
12947ac6653aSJeff Kirsher 						      &priv->xstats, p,
12957ac6653aSJeff Kirsher 						      priv->ioaddr);
12967ac6653aSJeff Kirsher 			if (likely(tx_error == 0)) {
12977ac6653aSJeff Kirsher 				priv->dev->stats.tx_packets++;
12987ac6653aSJeff Kirsher 				priv->xstats.tx_pkt_n++;
12997ac6653aSJeff Kirsher 			} else
13007ac6653aSJeff Kirsher 				priv->dev->stats.tx_errors++;
1301891434b1SRayagond Kokatanur 
1302891434b1SRayagond Kokatanur 			stmmac_get_tx_hwtstamp(priv, entry, skb);
13037ac6653aSJeff Kirsher 		}
130483d7af64SGiuseppe CAVALLARO 		if (netif_msg_tx_done(priv))
130583d7af64SGiuseppe CAVALLARO 			pr_debug("%s: curr %d, dirty %d\n", __func__,
13067ac6653aSJeff Kirsher 				 priv->cur_tx, priv->dirty_tx);
13077ac6653aSJeff Kirsher 
1308cf32deecSRayagond Kokatanur 		if (likely(priv->tx_skbuff_dma[entry])) {
1309cf32deecSRayagond Kokatanur 			dma_unmap_single(priv->device,
1310cf32deecSRayagond Kokatanur 					 priv->tx_skbuff_dma[entry],
13117ac6653aSJeff Kirsher 					 priv->hw->desc->get_tx_len(p),
13127ac6653aSJeff Kirsher 					 DMA_TO_DEVICE);
1313cf32deecSRayagond Kokatanur 			priv->tx_skbuff_dma[entry] = 0;
1314cf32deecSRayagond Kokatanur 		}
131529896a67SGiuseppe CAVALLARO 		priv->hw->mode->clean_desc3(priv, p);
13167ac6653aSJeff Kirsher 
13177ac6653aSJeff Kirsher 		if (likely(skb != NULL)) {
13187c565c33SEric W. Biederman 			dev_consume_skb_any(skb);
13197ac6653aSJeff Kirsher 			priv->tx_skbuff[entry] = NULL;
13207ac6653aSJeff Kirsher 		}
13217ac6653aSJeff Kirsher 
13224a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->release_tx_desc(p, priv->mode);
13237ac6653aSJeff Kirsher 
132413497f58SGiuseppe CAVALLARO 		priv->dirty_tx++;
13257ac6653aSJeff Kirsher 	}
13267ac6653aSJeff Kirsher 	if (unlikely(netif_queue_stopped(priv->dev) &&
13277ac6653aSJeff Kirsher 		     stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv))) {
13287ac6653aSJeff Kirsher 		netif_tx_lock(priv->dev);
13297ac6653aSJeff Kirsher 		if (netif_queue_stopped(priv->dev) &&
13307ac6653aSJeff Kirsher 		    stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv)) {
133183d7af64SGiuseppe CAVALLARO 			if (netif_msg_tx_done(priv))
133283d7af64SGiuseppe CAVALLARO 				pr_debug("%s: restart transmit\n", __func__);
13337ac6653aSJeff Kirsher 			netif_wake_queue(priv->dev);
13347ac6653aSJeff Kirsher 		}
13357ac6653aSJeff Kirsher 		netif_tx_unlock(priv->dev);
13367ac6653aSJeff Kirsher 	}
1337d765955dSGiuseppe CAVALLARO 
1338d765955dSGiuseppe CAVALLARO 	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
1339d765955dSGiuseppe CAVALLARO 		stmmac_enable_eee_mode(priv);
1340f5351ef7SGiuseppe CAVALLARO 		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
1341d765955dSGiuseppe CAVALLARO 	}
1342a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
13437ac6653aSJeff Kirsher }
13447ac6653aSJeff Kirsher 
13459125cdd1SGiuseppe CAVALLARO static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv)
13467ac6653aSJeff Kirsher {
13477ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_irq(priv->ioaddr);
13487ac6653aSJeff Kirsher }
13497ac6653aSJeff Kirsher 
13509125cdd1SGiuseppe CAVALLARO static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
13517ac6653aSJeff Kirsher {
13527ac6653aSJeff Kirsher 	priv->hw->dma->disable_dma_irq(priv->ioaddr);
13537ac6653aSJeff Kirsher }
13547ac6653aSJeff Kirsher 
13557ac6653aSJeff Kirsher /**
135632ceabcaSGiuseppe CAVALLARO  * stmmac_tx_err: irq tx error mng function
135732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
13587ac6653aSJeff Kirsher  * Description: it cleans the descriptors and restarts the transmission
13597ac6653aSJeff Kirsher  * in case of errors.
13607ac6653aSJeff Kirsher  */
13617ac6653aSJeff Kirsher static void stmmac_tx_err(struct stmmac_priv *priv)
13627ac6653aSJeff Kirsher {
1363c24602efSGiuseppe CAVALLARO 	int i;
1364c24602efSGiuseppe CAVALLARO 	int txsize = priv->dma_tx_size;
13657ac6653aSJeff Kirsher 	netif_stop_queue(priv->dev);
13667ac6653aSJeff Kirsher 
13677ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
13687ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
1369c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
1370c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1371c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
1372c24602efSGiuseppe CAVALLARO 						     priv->mode,
1373c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
1374c24602efSGiuseppe CAVALLARO 		else
1375c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
1376c24602efSGiuseppe CAVALLARO 						     priv->mode,
1377c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
13787ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
13797ac6653aSJeff Kirsher 	priv->cur_tx = 0;
13807ac6653aSJeff Kirsher 	priv->hw->dma->start_tx(priv->ioaddr);
13817ac6653aSJeff Kirsher 
13827ac6653aSJeff Kirsher 	priv->dev->stats.tx_errors++;
13837ac6653aSJeff Kirsher 	netif_wake_queue(priv->dev);
13847ac6653aSJeff Kirsher }
13857ac6653aSJeff Kirsher 
138632ceabcaSGiuseppe CAVALLARO /**
138732ceabcaSGiuseppe CAVALLARO  * stmmac_dma_interrupt: DMA ISR
138832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
138932ceabcaSGiuseppe CAVALLARO  * Description: this is the DMA ISR. It is called by the main ISR.
139032ceabcaSGiuseppe CAVALLARO  * It calls the dwmac dma routine to understand which type of interrupt
139132ceabcaSGiuseppe CAVALLARO  * happened. In case of there is a Normal interrupt and either TX or RX
139232ceabcaSGiuseppe CAVALLARO  * interrupt happened so the NAPI is scheduled.
139332ceabcaSGiuseppe CAVALLARO  */
13947ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv)
13957ac6653aSJeff Kirsher {
13967ac6653aSJeff Kirsher 	int status;
13977ac6653aSJeff Kirsher 
13987ac6653aSJeff Kirsher 	status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
13999125cdd1SGiuseppe CAVALLARO 	if (likely((status & handle_rx)) || (status & handle_tx)) {
14009125cdd1SGiuseppe CAVALLARO 		if (likely(napi_schedule_prep(&priv->napi))) {
14019125cdd1SGiuseppe CAVALLARO 			stmmac_disable_dma_irq(priv);
14029125cdd1SGiuseppe CAVALLARO 			__napi_schedule(&priv->napi);
14039125cdd1SGiuseppe CAVALLARO 		}
14049125cdd1SGiuseppe CAVALLARO 	}
14059125cdd1SGiuseppe CAVALLARO 	if (unlikely(status & tx_hard_error_bump_tc)) {
14067ac6653aSJeff Kirsher 		/* Try to bump up the dma threshold on this failure */
14077ac6653aSJeff Kirsher 		if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
14087ac6653aSJeff Kirsher 			tc += 64;
14097ac6653aSJeff Kirsher 			priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
14107ac6653aSJeff Kirsher 			priv->xstats.threshold = tc;
14117ac6653aSJeff Kirsher 		}
14127ac6653aSJeff Kirsher 	} else if (unlikely(status == tx_hard_error))
14137ac6653aSJeff Kirsher 		stmmac_tx_err(priv);
14147ac6653aSJeff Kirsher }
14157ac6653aSJeff Kirsher 
141632ceabcaSGiuseppe CAVALLARO /**
141732ceabcaSGiuseppe CAVALLARO  * stmmac_mmc_setup: setup the Mac Management Counters (MMC)
141832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
141932ceabcaSGiuseppe CAVALLARO  * Description: this masks the MMC irq, in fact, the counters are managed in SW.
142032ceabcaSGiuseppe CAVALLARO  */
14211c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv)
14221c901a46SGiuseppe CAVALLARO {
14231c901a46SGiuseppe CAVALLARO 	unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
14241c901a46SGiuseppe CAVALLARO 	    MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
14251c901a46SGiuseppe CAVALLARO 
14261c901a46SGiuseppe CAVALLARO 	dwmac_mmc_intr_all_mask(priv->ioaddr);
14274f795b25SGiuseppe CAVALLARO 
14284f795b25SGiuseppe CAVALLARO 	if (priv->dma_cap.rmon) {
14291c901a46SGiuseppe CAVALLARO 		dwmac_mmc_ctrl(priv->ioaddr, mode);
14301c901a46SGiuseppe CAVALLARO 		memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
14314f795b25SGiuseppe CAVALLARO 	} else
1432aae54cffSStefan Roese 		pr_info(" No MAC Management Counters available\n");
14331c901a46SGiuseppe CAVALLARO }
14341c901a46SGiuseppe CAVALLARO 
1435f0b9d786SGiuseppe CAVALLARO static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
1436f0b9d786SGiuseppe CAVALLARO {
1437f0b9d786SGiuseppe CAVALLARO 	u32 hwid = priv->hw->synopsys_uid;
1438f0b9d786SGiuseppe CAVALLARO 
1439ceb69499SGiuseppe CAVALLARO 	/* Check Synopsys Id (not available on old chips) */
1440f0b9d786SGiuseppe CAVALLARO 	if (likely(hwid)) {
1441f0b9d786SGiuseppe CAVALLARO 		u32 uid = ((hwid & 0x0000ff00) >> 8);
1442f0b9d786SGiuseppe CAVALLARO 		u32 synid = (hwid & 0x000000ff);
1443f0b9d786SGiuseppe CAVALLARO 
1444cf3f047bSGiuseppe CAVALLARO 		pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n",
1445f0b9d786SGiuseppe CAVALLARO 			uid, synid);
1446f0b9d786SGiuseppe CAVALLARO 
1447f0b9d786SGiuseppe CAVALLARO 		return synid;
1448f0b9d786SGiuseppe CAVALLARO 	}
1449f0b9d786SGiuseppe CAVALLARO 	return 0;
1450f0b9d786SGiuseppe CAVALLARO }
1451e7434821SGiuseppe CAVALLARO 
145219e30c14SGiuseppe CAVALLARO /**
145332ceabcaSGiuseppe CAVALLARO  * stmmac_selec_desc_mode: to select among: normal/alternate/extend descriptors
145432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
145532ceabcaSGiuseppe CAVALLARO  * Description: select the Enhanced/Alternate or Normal descriptors.
145632ceabcaSGiuseppe CAVALLARO  * In case of Enhanced/Alternate, it looks at the extended descriptors are
145732ceabcaSGiuseppe CAVALLARO  * supported by the HW cap. register.
1458ff3dd78cSGiuseppe CAVALLARO  */
145919e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
146019e30c14SGiuseppe CAVALLARO {
146119e30c14SGiuseppe CAVALLARO 	if (priv->plat->enh_desc) {
146219e30c14SGiuseppe CAVALLARO 		pr_info(" Enhanced/Alternate descriptors\n");
1463c24602efSGiuseppe CAVALLARO 
1464c24602efSGiuseppe CAVALLARO 		/* GMAC older than 3.50 has no extended descriptors */
1465c24602efSGiuseppe CAVALLARO 		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
1466c24602efSGiuseppe CAVALLARO 			pr_info("\tEnabled extended descriptors\n");
1467c24602efSGiuseppe CAVALLARO 			priv->extend_desc = 1;
1468c24602efSGiuseppe CAVALLARO 		} else
1469c24602efSGiuseppe CAVALLARO 			pr_warn("Extended descriptors not supported\n");
1470c24602efSGiuseppe CAVALLARO 
147119e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &enh_desc_ops;
147219e30c14SGiuseppe CAVALLARO 	} else {
147319e30c14SGiuseppe CAVALLARO 		pr_info(" Normal descriptors\n");
147419e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &ndesc_ops;
147519e30c14SGiuseppe CAVALLARO 	}
147619e30c14SGiuseppe CAVALLARO }
147719e30c14SGiuseppe CAVALLARO 
147819e30c14SGiuseppe CAVALLARO /**
147932ceabcaSGiuseppe CAVALLARO  * stmmac_get_hw_features: get MAC capabilities from the HW cap. register.
148032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
148119e30c14SGiuseppe CAVALLARO  * Description:
148219e30c14SGiuseppe CAVALLARO  *  new GMAC chip generations have a new register to indicate the
1483e7434821SGiuseppe CAVALLARO  *  presence of the optional feature/functions.
148419e30c14SGiuseppe CAVALLARO  *  This can be also used to override the value passed through the
148519e30c14SGiuseppe CAVALLARO  *  platform and necessary for old MAC10/100 and GMAC chips.
1486e7434821SGiuseppe CAVALLARO  */
1487e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv)
1488e7434821SGiuseppe CAVALLARO {
14895e6efe88SGiuseppe CAVALLARO 	u32 hw_cap = 0;
14903c20f72fSGiuseppe CAVALLARO 
14915e6efe88SGiuseppe CAVALLARO 	if (priv->hw->dma->get_hw_feature) {
14925e6efe88SGiuseppe CAVALLARO 		hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
1493e7434821SGiuseppe CAVALLARO 
14941db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
14951db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
14961db123fbSRayagond Kokatanur 		priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
14971db123fbSRayagond Kokatanur 		priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
1498ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
14991db123fbSRayagond Kokatanur 		priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
15001db123fbSRayagond Kokatanur 		priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
15011db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_remote_wake_up =
15021db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
15031db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_magic_frame =
15041db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
15051db123fbSRayagond Kokatanur 		/* MMC */
15061db123fbSRayagond Kokatanur 		priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
1507e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2002 */
15081db123fbSRayagond Kokatanur 		priv->dma_cap.time_stamp =
15091db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
1510e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2008 */
15111db123fbSRayagond Kokatanur 		priv->dma_cap.atime_stamp =
15121db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
1513e7434821SGiuseppe CAVALLARO 		/* 802.3az - Energy-Efficient Ethernet (EEE) */
15141db123fbSRayagond Kokatanur 		priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
15151db123fbSRayagond Kokatanur 		priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
1516e7434821SGiuseppe CAVALLARO 		/* TX and RX csum */
15171db123fbSRayagond Kokatanur 		priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
15181db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type1 =
15191db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
15201db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type2 =
15211db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
15221db123fbSRayagond Kokatanur 		priv->dma_cap.rxfifo_over_2048 =
15231db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
1524e7434821SGiuseppe CAVALLARO 		/* TX and RX number of channels */
15251db123fbSRayagond Kokatanur 		priv->dma_cap.number_rx_channel =
15261db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
15271db123fbSRayagond Kokatanur 		priv->dma_cap.number_tx_channel =
15281db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
1529e7434821SGiuseppe CAVALLARO 		/* Alternate (enhanced) DESC mode */
1530ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
153119e30c14SGiuseppe CAVALLARO 	}
1532e7434821SGiuseppe CAVALLARO 
1533e7434821SGiuseppe CAVALLARO 	return hw_cap;
1534e7434821SGiuseppe CAVALLARO }
1535e7434821SGiuseppe CAVALLARO 
153632ceabcaSGiuseppe CAVALLARO /**
153732ceabcaSGiuseppe CAVALLARO  * stmmac_check_ether_addr: check if the MAC addr is valid
153832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
153932ceabcaSGiuseppe CAVALLARO  * Description:
154032ceabcaSGiuseppe CAVALLARO  * it is to verify if the MAC address is valid, in case of failures it
154132ceabcaSGiuseppe CAVALLARO  * generates a random MAC address
154232ceabcaSGiuseppe CAVALLARO  */
1543bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv)
1544bfab27a1SGiuseppe CAVALLARO {
1545bfab27a1SGiuseppe CAVALLARO 	if (!is_valid_ether_addr(priv->dev->dev_addr)) {
15467ed24bbeSVince Bridgers 		priv->hw->mac->get_umac_addr(priv->hw,
1547bfab27a1SGiuseppe CAVALLARO 					     priv->dev->dev_addr, 0);
1548bfab27a1SGiuseppe CAVALLARO 		if (!is_valid_ether_addr(priv->dev->dev_addr))
1549f2cedb63SDanny Kukawka 			eth_hw_addr_random(priv->dev);
1550c88460b7SHans de Goede 		pr_info("%s: device MAC address %pM\n", priv->dev->name,
1551bfab27a1SGiuseppe CAVALLARO 			priv->dev->dev_addr);
1552bfab27a1SGiuseppe CAVALLARO 	}
1553c88460b7SHans de Goede }
1554bfab27a1SGiuseppe CAVALLARO 
155532ceabcaSGiuseppe CAVALLARO /**
155632ceabcaSGiuseppe CAVALLARO  * stmmac_init_dma_engine: DMA init.
155732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
155832ceabcaSGiuseppe CAVALLARO  * Description:
155932ceabcaSGiuseppe CAVALLARO  * It inits the DMA invoking the specific MAC/GMAC callback.
156032ceabcaSGiuseppe CAVALLARO  * Some DMA parameters can be passed from the platform;
156132ceabcaSGiuseppe CAVALLARO  * in case of these are not passed a default is kept for the MAC or GMAC.
156232ceabcaSGiuseppe CAVALLARO  */
15630f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv)
15640f1f88a8SGiuseppe CAVALLARO {
15650f1f88a8SGiuseppe CAVALLARO 	int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0;
1566b9cde0a8SGiuseppe CAVALLARO 	int mixed_burst = 0;
1567c24602efSGiuseppe CAVALLARO 	int atds = 0;
15680f1f88a8SGiuseppe CAVALLARO 
15690f1f88a8SGiuseppe CAVALLARO 	if (priv->plat->dma_cfg) {
15700f1f88a8SGiuseppe CAVALLARO 		pbl = priv->plat->dma_cfg->pbl;
15710f1f88a8SGiuseppe CAVALLARO 		fixed_burst = priv->plat->dma_cfg->fixed_burst;
1572b9cde0a8SGiuseppe CAVALLARO 		mixed_burst = priv->plat->dma_cfg->mixed_burst;
15730f1f88a8SGiuseppe CAVALLARO 		burst_len = priv->plat->dma_cfg->burst_len;
15740f1f88a8SGiuseppe CAVALLARO 	}
15750f1f88a8SGiuseppe CAVALLARO 
1576c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
1577c24602efSGiuseppe CAVALLARO 		atds = 1;
1578c24602efSGiuseppe CAVALLARO 
1579b9cde0a8SGiuseppe CAVALLARO 	return priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst,
15800f1f88a8SGiuseppe CAVALLARO 				   burst_len, priv->dma_tx_phy,
1581c24602efSGiuseppe CAVALLARO 				   priv->dma_rx_phy, atds);
15820f1f88a8SGiuseppe CAVALLARO }
15830f1f88a8SGiuseppe CAVALLARO 
1584bfab27a1SGiuseppe CAVALLARO /**
158532ceabcaSGiuseppe CAVALLARO  * stmmac_tx_timer: mitigation sw timer for tx.
15869125cdd1SGiuseppe CAVALLARO  * @data: data pointer
15879125cdd1SGiuseppe CAVALLARO  * Description:
15889125cdd1SGiuseppe CAVALLARO  * This is the timer handler to directly invoke the stmmac_tx_clean.
15899125cdd1SGiuseppe CAVALLARO  */
15909125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data)
15919125cdd1SGiuseppe CAVALLARO {
15929125cdd1SGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)data;
15939125cdd1SGiuseppe CAVALLARO 
15949125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
15959125cdd1SGiuseppe CAVALLARO }
15969125cdd1SGiuseppe CAVALLARO 
15979125cdd1SGiuseppe CAVALLARO /**
159832ceabcaSGiuseppe CAVALLARO  * stmmac_init_tx_coalesce: init tx mitigation options.
159932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
16009125cdd1SGiuseppe CAVALLARO  * Description:
16019125cdd1SGiuseppe CAVALLARO  * This inits the transmit coalesce parameters: i.e. timer rate,
16029125cdd1SGiuseppe CAVALLARO  * timer handler and default threshold used for enabling the
16039125cdd1SGiuseppe CAVALLARO  * interrupt on completion bit.
16049125cdd1SGiuseppe CAVALLARO  */
16059125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
16069125cdd1SGiuseppe CAVALLARO {
16079125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_frames = STMMAC_TX_FRAMES;
16089125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
16099125cdd1SGiuseppe CAVALLARO 	init_timer(&priv->txtimer);
16109125cdd1SGiuseppe CAVALLARO 	priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
16119125cdd1SGiuseppe CAVALLARO 	priv->txtimer.data = (unsigned long)priv;
16129125cdd1SGiuseppe CAVALLARO 	priv->txtimer.function = stmmac_tx_timer;
16139125cdd1SGiuseppe CAVALLARO 	add_timer(&priv->txtimer);
16149125cdd1SGiuseppe CAVALLARO }
16159125cdd1SGiuseppe CAVALLARO 
16169125cdd1SGiuseppe CAVALLARO /**
1617523f11b5SSrinivas Kandagatla  * stmmac_hw_setup: setup mac in a usable state.
1618523f11b5SSrinivas Kandagatla  *  @dev : pointer to the device structure.
1619523f11b5SSrinivas Kandagatla  *  Description:
1620523f11b5SSrinivas Kandagatla  *  This function sets up the ip in a usable state.
1621523f11b5SSrinivas Kandagatla  *  Return value:
1622523f11b5SSrinivas Kandagatla  *  0 on success and an appropriate (-)ve integer as defined in errno.h
1623523f11b5SSrinivas Kandagatla  *  file on failure.
1624523f11b5SSrinivas Kandagatla  */
1625523f11b5SSrinivas Kandagatla static int stmmac_hw_setup(struct net_device *dev)
1626523f11b5SSrinivas Kandagatla {
1627523f11b5SSrinivas Kandagatla 	struct stmmac_priv *priv = netdev_priv(dev);
1628523f11b5SSrinivas Kandagatla 	int ret;
1629523f11b5SSrinivas Kandagatla 
1630523f11b5SSrinivas Kandagatla 	ret = init_dma_desc_rings(dev);
1631523f11b5SSrinivas Kandagatla 	if (ret < 0) {
1632523f11b5SSrinivas Kandagatla 		pr_err("%s: DMA descriptors initialization failed\n", __func__);
1633523f11b5SSrinivas Kandagatla 		return ret;
1634523f11b5SSrinivas Kandagatla 	}
1635523f11b5SSrinivas Kandagatla 	/* DMA initialization and SW reset */
1636523f11b5SSrinivas Kandagatla 	ret = stmmac_init_dma_engine(priv);
1637523f11b5SSrinivas Kandagatla 	if (ret < 0) {
1638523f11b5SSrinivas Kandagatla 		pr_err("%s: DMA engine initialization failed\n", __func__);
1639523f11b5SSrinivas Kandagatla 		return ret;
1640523f11b5SSrinivas Kandagatla 	}
1641523f11b5SSrinivas Kandagatla 
1642523f11b5SSrinivas Kandagatla 	/* Copy the MAC addr into the HW  */
16437ed24bbeSVince Bridgers 	priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0);
1644523f11b5SSrinivas Kandagatla 
1645523f11b5SSrinivas Kandagatla 	/* If required, perform hw setup of the bus. */
1646523f11b5SSrinivas Kandagatla 	if (priv->plat->bus_setup)
1647523f11b5SSrinivas Kandagatla 		priv->plat->bus_setup(priv->ioaddr);
1648523f11b5SSrinivas Kandagatla 
1649523f11b5SSrinivas Kandagatla 	/* Initialize the MAC Core */
16507ed24bbeSVince Bridgers 	priv->hw->mac->core_init(priv->hw, dev->mtu);
1651523f11b5SSrinivas Kandagatla 
1652978aded4SGiuseppe CAVALLARO 	ret = priv->hw->mac->rx_ipc(priv->hw);
1653978aded4SGiuseppe CAVALLARO 	if (!ret) {
1654978aded4SGiuseppe CAVALLARO 		pr_warn(" RX IPC Checksum Offload disabled\n");
1655978aded4SGiuseppe CAVALLARO 		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
1656978aded4SGiuseppe CAVALLARO 	}
1657978aded4SGiuseppe CAVALLARO 
1658523f11b5SSrinivas Kandagatla 	/* Enable the MAC Rx/Tx */
1659523f11b5SSrinivas Kandagatla 	stmmac_set_mac(priv->ioaddr, true);
1660523f11b5SSrinivas Kandagatla 
1661523f11b5SSrinivas Kandagatla 	/* Set the HW DMA mode and the COE */
1662523f11b5SSrinivas Kandagatla 	stmmac_dma_operation_mode(priv);
1663523f11b5SSrinivas Kandagatla 
1664523f11b5SSrinivas Kandagatla 	stmmac_mmc_setup(priv);
1665523f11b5SSrinivas Kandagatla 
1666523f11b5SSrinivas Kandagatla 	ret = stmmac_init_ptp(priv);
16677509edd6SHans de Goede 	if (ret && ret != -EOPNOTSUPP)
1668523f11b5SSrinivas Kandagatla 		pr_warn("%s: failed PTP initialisation\n", __func__);
1669523f11b5SSrinivas Kandagatla 
1670523f11b5SSrinivas Kandagatla #ifdef CONFIG_STMMAC_DEBUG_FS
1671523f11b5SSrinivas Kandagatla 	ret = stmmac_init_fs(dev);
1672523f11b5SSrinivas Kandagatla 	if (ret < 0)
1673523f11b5SSrinivas Kandagatla 		pr_warn("%s: failed debugFS registration\n", __func__);
1674523f11b5SSrinivas Kandagatla #endif
1675523f11b5SSrinivas Kandagatla 	/* Start the ball rolling... */
1676523f11b5SSrinivas Kandagatla 	pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
1677523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_tx(priv->ioaddr);
1678523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_rx(priv->ioaddr);
1679523f11b5SSrinivas Kandagatla 
1680523f11b5SSrinivas Kandagatla 	/* Dump DMA/MAC registers */
1681523f11b5SSrinivas Kandagatla 	if (netif_msg_hw(priv)) {
16827ed24bbeSVince Bridgers 		priv->hw->mac->dump_regs(priv->hw);
1683523f11b5SSrinivas Kandagatla 		priv->hw->dma->dump_regs(priv->ioaddr);
1684523f11b5SSrinivas Kandagatla 	}
1685523f11b5SSrinivas Kandagatla 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
1686523f11b5SSrinivas Kandagatla 
1687523f11b5SSrinivas Kandagatla 	priv->eee_enabled = stmmac_eee_init(priv);
1688523f11b5SSrinivas Kandagatla 
1689523f11b5SSrinivas Kandagatla 	stmmac_init_tx_coalesce(priv);
1690523f11b5SSrinivas Kandagatla 
1691523f11b5SSrinivas Kandagatla 	if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
1692523f11b5SSrinivas Kandagatla 		priv->rx_riwt = MAX_DMA_RIWT;
1693523f11b5SSrinivas Kandagatla 		priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
1694523f11b5SSrinivas Kandagatla 	}
1695523f11b5SSrinivas Kandagatla 
1696523f11b5SSrinivas Kandagatla 	if (priv->pcs && priv->hw->mac->ctrl_ane)
16977ed24bbeSVince Bridgers 		priv->hw->mac->ctrl_ane(priv->hw, 0);
1698523f11b5SSrinivas Kandagatla 
1699523f11b5SSrinivas Kandagatla 	return 0;
1700523f11b5SSrinivas Kandagatla }
1701523f11b5SSrinivas Kandagatla 
1702523f11b5SSrinivas Kandagatla /**
17037ac6653aSJeff Kirsher  *  stmmac_open - open entry point of the driver
17047ac6653aSJeff Kirsher  *  @dev : pointer to the device structure.
17057ac6653aSJeff Kirsher  *  Description:
17067ac6653aSJeff Kirsher  *  This function is the open entry point of the driver.
17077ac6653aSJeff Kirsher  *  Return value:
17087ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
17097ac6653aSJeff Kirsher  *  file on failure.
17107ac6653aSJeff Kirsher  */
17117ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev)
17127ac6653aSJeff Kirsher {
17137ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
17147ac6653aSJeff Kirsher 	int ret;
17157ac6653aSJeff Kirsher 
17164bfcbd7aSFrancesco Virlinzi 	stmmac_check_ether_addr(priv);
17174bfcbd7aSFrancesco Virlinzi 
17184d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
17194d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
17207ac6653aSJeff Kirsher 		ret = stmmac_init_phy(dev);
1721e58bb43fSGiuseppe CAVALLARO 		if (ret) {
1722e58bb43fSGiuseppe CAVALLARO 			pr_err("%s: Cannot attach to PHY (error: %d)\n",
1723e58bb43fSGiuseppe CAVALLARO 			       __func__, ret);
172489df20d9SHans de Goede 			return ret;
17257ac6653aSJeff Kirsher 		}
1726e58bb43fSGiuseppe CAVALLARO 	}
17277ac6653aSJeff Kirsher 
1728523f11b5SSrinivas Kandagatla 	/* Extra statistics */
1729523f11b5SSrinivas Kandagatla 	memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
1730523f11b5SSrinivas Kandagatla 	priv->xstats.threshold = tc;
1731523f11b5SSrinivas Kandagatla 
17327ac6653aSJeff Kirsher 	/* Create and initialize the TX/RX descriptors chains. */
17337ac6653aSJeff Kirsher 	priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
17347ac6653aSJeff Kirsher 	priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
17357ac6653aSJeff Kirsher 	priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
173656329137SBartlomiej Zolnierkiewicz 
17377262b7b2STobias Klauser 	ret = alloc_dma_desc_resources(priv);
173809f8d696SSrinivas Kandagatla 	if (ret < 0) {
173909f8d696SSrinivas Kandagatla 		pr_err("%s: DMA descriptors allocation failed\n", __func__);
174009f8d696SSrinivas Kandagatla 		goto dma_desc_error;
174109f8d696SSrinivas Kandagatla 	}
174209f8d696SSrinivas Kandagatla 
1743523f11b5SSrinivas Kandagatla 	ret = stmmac_hw_setup(dev);
174456329137SBartlomiej Zolnierkiewicz 	if (ret < 0) {
1745523f11b5SSrinivas Kandagatla 		pr_err("%s: Hw setup failed\n", __func__);
1746c9324d18SGiuseppe CAVALLARO 		goto init_error;
17477ac6653aSJeff Kirsher 	}
17487ac6653aSJeff Kirsher 
1749523f11b5SSrinivas Kandagatla 	if (priv->phydev)
1750523f11b5SSrinivas Kandagatla 		phy_start(priv->phydev);
17517ac6653aSJeff Kirsher 
17527ac6653aSJeff Kirsher 	/* Request the IRQ lines */
17537ac6653aSJeff Kirsher 	ret = request_irq(dev->irq, stmmac_interrupt,
17547ac6653aSJeff Kirsher 			  IRQF_SHARED, dev->name, dev);
17557ac6653aSJeff Kirsher 	if (unlikely(ret < 0)) {
17567ac6653aSJeff Kirsher 		pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
17577ac6653aSJeff Kirsher 		       __func__, dev->irq, ret);
1758c9324d18SGiuseppe CAVALLARO 		goto init_error;
17597ac6653aSJeff Kirsher 	}
17607ac6653aSJeff Kirsher 
17617a13f8f5SFrancesco Virlinzi 	/* Request the Wake IRQ in case of another line is used for WoL */
17627a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq) {
17637a13f8f5SFrancesco Virlinzi 		ret = request_irq(priv->wol_irq, stmmac_interrupt,
17647a13f8f5SFrancesco Virlinzi 				  IRQF_SHARED, dev->name, dev);
17657a13f8f5SFrancesco Virlinzi 		if (unlikely(ret < 0)) {
1766ceb69499SGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n",
1767ceb69499SGiuseppe CAVALLARO 			       __func__, priv->wol_irq, ret);
1768c9324d18SGiuseppe CAVALLARO 			goto wolirq_error;
17697a13f8f5SFrancesco Virlinzi 		}
17707a13f8f5SFrancesco Virlinzi 	}
17717a13f8f5SFrancesco Virlinzi 
1772d765955dSGiuseppe CAVALLARO 	/* Request the IRQ lines */
1773d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0) {
1774d765955dSGiuseppe CAVALLARO 		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
1775d765955dSGiuseppe CAVALLARO 				  dev->name, dev);
1776d765955dSGiuseppe CAVALLARO 		if (unlikely(ret < 0)) {
1777d765955dSGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
1778d765955dSGiuseppe CAVALLARO 			       __func__, priv->lpi_irq, ret);
1779c9324d18SGiuseppe CAVALLARO 			goto lpiirq_error;
1780d765955dSGiuseppe CAVALLARO 		}
1781d765955dSGiuseppe CAVALLARO 	}
1782d765955dSGiuseppe CAVALLARO 
17837ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
17847ac6653aSJeff Kirsher 	netif_start_queue(dev);
17857ac6653aSJeff Kirsher 
17867ac6653aSJeff Kirsher 	return 0;
17877ac6653aSJeff Kirsher 
1788c9324d18SGiuseppe CAVALLARO lpiirq_error:
1789d765955dSGiuseppe CAVALLARO 	if (priv->wol_irq != dev->irq)
1790d765955dSGiuseppe CAVALLARO 		free_irq(priv->wol_irq, dev);
1791c9324d18SGiuseppe CAVALLARO wolirq_error:
17927a13f8f5SFrancesco Virlinzi 	free_irq(dev->irq, dev);
17937a13f8f5SFrancesco Virlinzi 
1794c9324d18SGiuseppe CAVALLARO init_error:
1795c9324d18SGiuseppe CAVALLARO 	free_dma_desc_resources(priv);
179656329137SBartlomiej Zolnierkiewicz dma_desc_error:
17977ac6653aSJeff Kirsher 	if (priv->phydev)
17987ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
17994bfcbd7aSFrancesco Virlinzi 
18007ac6653aSJeff Kirsher 	return ret;
18017ac6653aSJeff Kirsher }
18027ac6653aSJeff Kirsher 
18037ac6653aSJeff Kirsher /**
18047ac6653aSJeff Kirsher  *  stmmac_release - close entry point of the driver
18057ac6653aSJeff Kirsher  *  @dev : device pointer.
18067ac6653aSJeff Kirsher  *  Description:
18077ac6653aSJeff Kirsher  *  This is the stop entry point of the driver.
18087ac6653aSJeff Kirsher  */
18097ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev)
18107ac6653aSJeff Kirsher {
18117ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
18127ac6653aSJeff Kirsher 
1813d765955dSGiuseppe CAVALLARO 	if (priv->eee_enabled)
1814d765955dSGiuseppe CAVALLARO 		del_timer_sync(&priv->eee_ctrl_timer);
1815d765955dSGiuseppe CAVALLARO 
18167ac6653aSJeff Kirsher 	/* Stop and disconnect the PHY */
18177ac6653aSJeff Kirsher 	if (priv->phydev) {
18187ac6653aSJeff Kirsher 		phy_stop(priv->phydev);
18197ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
18207ac6653aSJeff Kirsher 		priv->phydev = NULL;
18217ac6653aSJeff Kirsher 	}
18227ac6653aSJeff Kirsher 
18237ac6653aSJeff Kirsher 	netif_stop_queue(dev);
18247ac6653aSJeff Kirsher 
18257ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
18267ac6653aSJeff Kirsher 
18279125cdd1SGiuseppe CAVALLARO 	del_timer_sync(&priv->txtimer);
18289125cdd1SGiuseppe CAVALLARO 
18297ac6653aSJeff Kirsher 	/* Free the IRQ lines */
18307ac6653aSJeff Kirsher 	free_irq(dev->irq, dev);
18317a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq)
18327a13f8f5SFrancesco Virlinzi 		free_irq(priv->wol_irq, dev);
1833d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0)
1834d765955dSGiuseppe CAVALLARO 		free_irq(priv->lpi_irq, dev);
18357ac6653aSJeff Kirsher 
18367ac6653aSJeff Kirsher 	/* Stop TX/RX DMA and clear the descriptors */
18377ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
18387ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
18397ac6653aSJeff Kirsher 
18407ac6653aSJeff Kirsher 	/* Release and free the Rx/Tx resources */
18417ac6653aSJeff Kirsher 	free_dma_desc_resources(priv);
18427ac6653aSJeff Kirsher 
18437ac6653aSJeff Kirsher 	/* Disable the MAC Rx/Tx */
1844bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
18457ac6653aSJeff Kirsher 
18467ac6653aSJeff Kirsher 	netif_carrier_off(dev);
18477ac6653aSJeff Kirsher 
1848bfab27a1SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_DEBUG_FS
1849bfab27a1SGiuseppe CAVALLARO 	stmmac_exit_fs();
1850bfab27a1SGiuseppe CAVALLARO #endif
1851bfab27a1SGiuseppe CAVALLARO 
185292ba6888SRayagond Kokatanur 	stmmac_release_ptp(priv);
185392ba6888SRayagond Kokatanur 
18547ac6653aSJeff Kirsher 	return 0;
18557ac6653aSJeff Kirsher }
18567ac6653aSJeff Kirsher 
18577ac6653aSJeff Kirsher /**
185832ceabcaSGiuseppe CAVALLARO  *  stmmac_xmit: Tx entry point of the driver
18597ac6653aSJeff Kirsher  *  @skb : the socket buffer
18607ac6653aSJeff Kirsher  *  @dev : device pointer
186132ceabcaSGiuseppe CAVALLARO  *  Description : this is the tx entry point of the driver.
186232ceabcaSGiuseppe CAVALLARO  *  It programs the chain or the ring and supports oversized frames
186332ceabcaSGiuseppe CAVALLARO  *  and SG feature.
18647ac6653aSJeff Kirsher  */
18657ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
18667ac6653aSJeff Kirsher {
18677ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
18687ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
18697ac6653aSJeff Kirsher 	unsigned int entry;
18704a7d666aSGiuseppe CAVALLARO 	int i, csum_insertion = 0, is_jumbo = 0;
18717ac6653aSJeff Kirsher 	int nfrags = skb_shinfo(skb)->nr_frags;
18727ac6653aSJeff Kirsher 	struct dma_desc *desc, *first;
1873286a8372SGiuseppe CAVALLARO 	unsigned int nopaged_len = skb_headlen(skb);
187429896a67SGiuseppe CAVALLARO 	unsigned int enh_desc = priv->plat->enh_desc;
18757ac6653aSJeff Kirsher 
18767ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
18777ac6653aSJeff Kirsher 		if (!netif_queue_stopped(dev)) {
18787ac6653aSJeff Kirsher 			netif_stop_queue(dev);
18797ac6653aSJeff Kirsher 			/* This is a hard error, log it. */
1880ceb69499SGiuseppe CAVALLARO 			pr_err("%s: Tx Ring full when queue awake\n", __func__);
18817ac6653aSJeff Kirsher 		}
18827ac6653aSJeff Kirsher 		return NETDEV_TX_BUSY;
18837ac6653aSJeff Kirsher 	}
18847ac6653aSJeff Kirsher 
1885a9097a96SGiuseppe CAVALLARO 	spin_lock(&priv->tx_lock);
1886a9097a96SGiuseppe CAVALLARO 
1887d765955dSGiuseppe CAVALLARO 	if (priv->tx_path_in_lpi_mode)
1888d765955dSGiuseppe CAVALLARO 		stmmac_disable_eee_mode(priv);
1889d765955dSGiuseppe CAVALLARO 
18907ac6653aSJeff Kirsher 	entry = priv->cur_tx % txsize;
18917ac6653aSJeff Kirsher 
18927ac6653aSJeff Kirsher 	csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
18937ac6653aSJeff Kirsher 
1894c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc)
1895c24602efSGiuseppe CAVALLARO 		desc = (struct dma_desc *)(priv->dma_etx + entry);
1896c24602efSGiuseppe CAVALLARO 	else
18977ac6653aSJeff Kirsher 		desc = priv->dma_tx + entry;
1898c24602efSGiuseppe CAVALLARO 
18997ac6653aSJeff Kirsher 	first = desc;
19007ac6653aSJeff Kirsher 
19014a7d666aSGiuseppe CAVALLARO 	/* To program the descriptors according to the size of the frame */
190229896a67SGiuseppe CAVALLARO 	if (enh_desc)
190329896a67SGiuseppe CAVALLARO 		is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc);
190429896a67SGiuseppe CAVALLARO 
19054a7d666aSGiuseppe CAVALLARO 	if (likely(!is_jumbo)) {
19067ac6653aSJeff Kirsher 		desc->des2 = dma_map_single(priv->device, skb->data,
19077ac6653aSJeff Kirsher 					    nopaged_len, DMA_TO_DEVICE);
1908cf32deecSRayagond Kokatanur 		priv->tx_skbuff_dma[entry] = desc->des2;
19097ac6653aSJeff Kirsher 		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
19104a7d666aSGiuseppe CAVALLARO 						csum_insertion, priv->mode);
191129896a67SGiuseppe CAVALLARO 	} else {
1912c24602efSGiuseppe CAVALLARO 		desc = first;
191329896a67SGiuseppe CAVALLARO 		entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion);
191429896a67SGiuseppe CAVALLARO 	}
19157ac6653aSJeff Kirsher 
19167ac6653aSJeff Kirsher 	for (i = 0; i < nfrags; i++) {
19179e903e08SEric Dumazet 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
19189e903e08SEric Dumazet 		int len = skb_frag_size(frag);
19197ac6653aSJeff Kirsher 
192075e4364fSdamuzi000 		priv->tx_skbuff[entry] = NULL;
19217ac6653aSJeff Kirsher 		entry = (++priv->cur_tx) % txsize;
1922c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1923c24602efSGiuseppe CAVALLARO 			desc = (struct dma_desc *)(priv->dma_etx + entry);
1924c24602efSGiuseppe CAVALLARO 		else
19257ac6653aSJeff Kirsher 			desc = priv->dma_tx + entry;
19267ac6653aSJeff Kirsher 
1927f722380dSIan Campbell 		desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
1928f722380dSIan Campbell 					      DMA_TO_DEVICE);
1929cf32deecSRayagond Kokatanur 		priv->tx_skbuff_dma[entry] = desc->des2;
19304a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
19314a7d666aSGiuseppe CAVALLARO 						priv->mode);
19327ac6653aSJeff Kirsher 		wmb();
19337ac6653aSJeff Kirsher 		priv->hw->desc->set_tx_owner(desc);
19348e839891SDeepak Sikri 		wmb();
19357ac6653aSJeff Kirsher 	}
19367ac6653aSJeff Kirsher 
193775e4364fSdamuzi000 	priv->tx_skbuff[entry] = skb;
193875e4364fSdamuzi000 
19399125cdd1SGiuseppe CAVALLARO 	/* Finalize the latest segment. */
19407ac6653aSJeff Kirsher 	priv->hw->desc->close_tx_desc(desc);
19417ac6653aSJeff Kirsher 
19427ac6653aSJeff Kirsher 	wmb();
19439125cdd1SGiuseppe CAVALLARO 	/* According to the coalesce parameter the IC bit for the latest
19449125cdd1SGiuseppe CAVALLARO 	 * segment could be reset and the timer re-started to invoke the
19459125cdd1SGiuseppe CAVALLARO 	 * stmmac_tx function. This approach takes care about the fragments.
19469125cdd1SGiuseppe CAVALLARO 	 */
19479125cdd1SGiuseppe CAVALLARO 	priv->tx_count_frames += nfrags + 1;
19489125cdd1SGiuseppe CAVALLARO 	if (priv->tx_coal_frames > priv->tx_count_frames) {
19499125cdd1SGiuseppe CAVALLARO 		priv->hw->desc->clear_tx_ic(desc);
19509125cdd1SGiuseppe CAVALLARO 		priv->xstats.tx_reset_ic_bit++;
19519125cdd1SGiuseppe CAVALLARO 		mod_timer(&priv->txtimer,
19529125cdd1SGiuseppe CAVALLARO 			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
19539125cdd1SGiuseppe CAVALLARO 	} else
19549125cdd1SGiuseppe CAVALLARO 		priv->tx_count_frames = 0;
19557ac6653aSJeff Kirsher 
19567ac6653aSJeff Kirsher 	/* To avoid raise condition */
19577ac6653aSJeff Kirsher 	priv->hw->desc->set_tx_owner(first);
19588e839891SDeepak Sikri 	wmb();
19597ac6653aSJeff Kirsher 
19607ac6653aSJeff Kirsher 	priv->cur_tx++;
19617ac6653aSJeff Kirsher 
19627ac6653aSJeff Kirsher 	if (netif_msg_pktdata(priv)) {
196383d7af64SGiuseppe CAVALLARO 		pr_debug("%s: curr %d dirty=%d entry=%d, first=%p, nfrags=%d",
1964ceb69499SGiuseppe CAVALLARO 			__func__, (priv->cur_tx % txsize),
1965ceb69499SGiuseppe CAVALLARO 			(priv->dirty_tx % txsize), entry, first, nfrags);
196683d7af64SGiuseppe CAVALLARO 
1967c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1968c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
1969c24602efSGiuseppe CAVALLARO 		else
1970c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
1971c24602efSGiuseppe CAVALLARO 
197283d7af64SGiuseppe CAVALLARO 		pr_debug(">>> frame to be transmitted: ");
19737ac6653aSJeff Kirsher 		print_pkt(skb->data, skb->len);
19747ac6653aSJeff Kirsher 	}
19757ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
197683d7af64SGiuseppe CAVALLARO 		if (netif_msg_hw(priv))
197783d7af64SGiuseppe CAVALLARO 			pr_debug("%s: stop transmitted packets\n", __func__);
19787ac6653aSJeff Kirsher 		netif_stop_queue(dev);
19797ac6653aSJeff Kirsher 	}
19807ac6653aSJeff Kirsher 
19817ac6653aSJeff Kirsher 	dev->stats.tx_bytes += skb->len;
19827ac6653aSJeff Kirsher 
1983891434b1SRayagond Kokatanur 	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
1984891434b1SRayagond Kokatanur 		     priv->hwts_tx_en)) {
1985891434b1SRayagond Kokatanur 		/* declare that device is doing timestamping */
1986891434b1SRayagond Kokatanur 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
1987891434b1SRayagond Kokatanur 		priv->hw->desc->enable_tx_timestamp(first);
1988891434b1SRayagond Kokatanur 	}
1989891434b1SRayagond Kokatanur 
1990891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
19917ac6653aSJeff Kirsher 		skb_tx_timestamp(skb);
19927ac6653aSJeff Kirsher 
19937ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_transmission(priv->ioaddr);
19947ac6653aSJeff Kirsher 
1995a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
1996a9097a96SGiuseppe CAVALLARO 
19977ac6653aSJeff Kirsher 	return NETDEV_TX_OK;
19987ac6653aSJeff Kirsher }
19997ac6653aSJeff Kirsher 
2000b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
2001b9381985SVince Bridgers {
2002b9381985SVince Bridgers 	struct ethhdr *ehdr;
2003b9381985SVince Bridgers 	u16 vlanid;
2004b9381985SVince Bridgers 
2005b9381985SVince Bridgers 	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
2006b9381985SVince Bridgers 	    NETIF_F_HW_VLAN_CTAG_RX &&
2007b9381985SVince Bridgers 	    !__vlan_get_tag(skb, &vlanid)) {
2008b9381985SVince Bridgers 		/* pop the vlan tag */
2009b9381985SVince Bridgers 		ehdr = (struct ethhdr *)skb->data;
2010b9381985SVince Bridgers 		memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
2011b9381985SVince Bridgers 		skb_pull(skb, VLAN_HLEN);
2012b9381985SVince Bridgers 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
2013b9381985SVince Bridgers 	}
2014b9381985SVince Bridgers }
2015b9381985SVince Bridgers 
2016b9381985SVince Bridgers 
201732ceabcaSGiuseppe CAVALLARO /**
201832ceabcaSGiuseppe CAVALLARO  * stmmac_rx_refill: refill used skb preallocated buffers
201932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
202032ceabcaSGiuseppe CAVALLARO  * Description : this is to reallocate the skb for the reception process
202132ceabcaSGiuseppe CAVALLARO  * that is based on zero-copy.
202232ceabcaSGiuseppe CAVALLARO  */
20237ac6653aSJeff Kirsher static inline void stmmac_rx_refill(struct stmmac_priv *priv)
20247ac6653aSJeff Kirsher {
20257ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
20267ac6653aSJeff Kirsher 	int bfsize = priv->dma_buf_sz;
20277ac6653aSJeff Kirsher 
20287ac6653aSJeff Kirsher 	for (; priv->cur_rx - priv->dirty_rx > 0; priv->dirty_rx++) {
20297ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_rx % rxsize;
2030c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
2031c24602efSGiuseppe CAVALLARO 
2032c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2033c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2034c24602efSGiuseppe CAVALLARO 		else
2035c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2036c24602efSGiuseppe CAVALLARO 
20377ac6653aSJeff Kirsher 		if (likely(priv->rx_skbuff[entry] == NULL)) {
20387ac6653aSJeff Kirsher 			struct sk_buff *skb;
20397ac6653aSJeff Kirsher 
2040acb600deSEric Dumazet 			skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
20417ac6653aSJeff Kirsher 
20427ac6653aSJeff Kirsher 			if (unlikely(skb == NULL))
20437ac6653aSJeff Kirsher 				break;
20447ac6653aSJeff Kirsher 
20457ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = skb;
20467ac6653aSJeff Kirsher 			priv->rx_skbuff_dma[entry] =
20477ac6653aSJeff Kirsher 			    dma_map_single(priv->device, skb->data, bfsize,
20487ac6653aSJeff Kirsher 					   DMA_FROM_DEVICE);
20497ac6653aSJeff Kirsher 
2050c24602efSGiuseppe CAVALLARO 			p->des2 = priv->rx_skbuff_dma[entry];
2051286a8372SGiuseppe CAVALLARO 
205229896a67SGiuseppe CAVALLARO 			priv->hw->mode->refill_desc3(priv, p);
2053286a8372SGiuseppe CAVALLARO 
205483d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv))
205583d7af64SGiuseppe CAVALLARO 				pr_debug("\trefill entry #%d\n", entry);
20567ac6653aSJeff Kirsher 		}
20577ac6653aSJeff Kirsher 		wmb();
2058c24602efSGiuseppe CAVALLARO 		priv->hw->desc->set_rx_owner(p);
20598e839891SDeepak Sikri 		wmb();
20607ac6653aSJeff Kirsher 	}
20617ac6653aSJeff Kirsher }
20627ac6653aSJeff Kirsher 
206332ceabcaSGiuseppe CAVALLARO /**
206432ceabcaSGiuseppe CAVALLARO  * stmmac_rx_refill: refill used skb preallocated buffers
206532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
206632ceabcaSGiuseppe CAVALLARO  * @limit: napi bugget.
206732ceabcaSGiuseppe CAVALLARO  * Description :  this the function called by the napi poll method.
206832ceabcaSGiuseppe CAVALLARO  * It gets all the frames inside the ring.
206932ceabcaSGiuseppe CAVALLARO  */
20707ac6653aSJeff Kirsher static int stmmac_rx(struct stmmac_priv *priv, int limit)
20717ac6653aSJeff Kirsher {
20727ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
20737ac6653aSJeff Kirsher 	unsigned int entry = priv->cur_rx % rxsize;
20747ac6653aSJeff Kirsher 	unsigned int next_entry;
20757ac6653aSJeff Kirsher 	unsigned int count = 0;
2076ceb69499SGiuseppe CAVALLARO 	int coe = priv->plat->rx_coe;
20777ac6653aSJeff Kirsher 
207883d7af64SGiuseppe CAVALLARO 	if (netif_msg_rx_status(priv)) {
207983d7af64SGiuseppe CAVALLARO 		pr_debug("%s: descriptor ring:\n", __func__);
2080c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2081c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
2082c24602efSGiuseppe CAVALLARO 		else
2083c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
20847ac6653aSJeff Kirsher 	}
2085c24602efSGiuseppe CAVALLARO 	while (count < limit) {
20867ac6653aSJeff Kirsher 		int status;
20879401bb5cSGiuseppe CAVALLARO 		struct dma_desc *p;
20887ac6653aSJeff Kirsher 
2089c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2090c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2091c24602efSGiuseppe CAVALLARO 		else
2092c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2093c24602efSGiuseppe CAVALLARO 
2094c24602efSGiuseppe CAVALLARO 		if (priv->hw->desc->get_rx_owner(p))
20957ac6653aSJeff Kirsher 			break;
20967ac6653aSJeff Kirsher 
20977ac6653aSJeff Kirsher 		count++;
20987ac6653aSJeff Kirsher 
20997ac6653aSJeff Kirsher 		next_entry = (++priv->cur_rx) % rxsize;
2100c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
21019401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_erx + next_entry);
2102c24602efSGiuseppe CAVALLARO 		else
21039401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_rx + next_entry);
21047ac6653aSJeff Kirsher 
21057ac6653aSJeff Kirsher 		/* read the status of the incoming frame */
2106c24602efSGiuseppe CAVALLARO 		status = priv->hw->desc->rx_status(&priv->dev->stats,
2107c24602efSGiuseppe CAVALLARO 						   &priv->xstats, p);
2108c24602efSGiuseppe CAVALLARO 		if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status))
2109c24602efSGiuseppe CAVALLARO 			priv->hw->desc->rx_extended_status(&priv->dev->stats,
2110c24602efSGiuseppe CAVALLARO 							   &priv->xstats,
2111c24602efSGiuseppe CAVALLARO 							   priv->dma_erx +
2112c24602efSGiuseppe CAVALLARO 							   entry);
2113891434b1SRayagond Kokatanur 		if (unlikely(status == discard_frame)) {
21147ac6653aSJeff Kirsher 			priv->dev->stats.rx_errors++;
2115891434b1SRayagond Kokatanur 			if (priv->hwts_rx_en && !priv->extend_desc) {
2116891434b1SRayagond Kokatanur 				/* DESC2 & DESC3 will be overwitten by device
2117891434b1SRayagond Kokatanur 				 * with timestamp value, hence reinitialize
2118891434b1SRayagond Kokatanur 				 * them in stmmac_rx_refill() function so that
2119891434b1SRayagond Kokatanur 				 * device can reuse it.
2120891434b1SRayagond Kokatanur 				 */
2121891434b1SRayagond Kokatanur 				priv->rx_skbuff[entry] = NULL;
2122891434b1SRayagond Kokatanur 				dma_unmap_single(priv->device,
2123891434b1SRayagond Kokatanur 						 priv->rx_skbuff_dma[entry],
2124ceb69499SGiuseppe CAVALLARO 						 priv->dma_buf_sz,
2125ceb69499SGiuseppe CAVALLARO 						 DMA_FROM_DEVICE);
2126891434b1SRayagond Kokatanur 			}
2127891434b1SRayagond Kokatanur 		} else {
21287ac6653aSJeff Kirsher 			struct sk_buff *skb;
21297ac6653aSJeff Kirsher 			int frame_len;
21307ac6653aSJeff Kirsher 
2131ceb69499SGiuseppe CAVALLARO 			frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
2132ceb69499SGiuseppe CAVALLARO 
21337ac6653aSJeff Kirsher 			/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
2134ceb69499SGiuseppe CAVALLARO 			 * Type frames (LLC/LLC-SNAP)
2135ceb69499SGiuseppe CAVALLARO 			 */
21367ac6653aSJeff Kirsher 			if (unlikely(status != llc_snap))
21377ac6653aSJeff Kirsher 				frame_len -= ETH_FCS_LEN;
21387ac6653aSJeff Kirsher 
213983d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv)) {
21407ac6653aSJeff Kirsher 				pr_debug("\tdesc: %p [entry %d] buff=0x%x\n",
21417ac6653aSJeff Kirsher 					 p, entry, p->des2);
214283d7af64SGiuseppe CAVALLARO 				if (frame_len > ETH_FRAME_LEN)
214383d7af64SGiuseppe CAVALLARO 					pr_debug("\tframe size %d, COE: %d\n",
214483d7af64SGiuseppe CAVALLARO 						 frame_len, status);
214583d7af64SGiuseppe CAVALLARO 			}
21467ac6653aSJeff Kirsher 			skb = priv->rx_skbuff[entry];
21477ac6653aSJeff Kirsher 			if (unlikely(!skb)) {
21487ac6653aSJeff Kirsher 				pr_err("%s: Inconsistent Rx descriptor chain\n",
21497ac6653aSJeff Kirsher 				       priv->dev->name);
21507ac6653aSJeff Kirsher 				priv->dev->stats.rx_dropped++;
21517ac6653aSJeff Kirsher 				break;
21527ac6653aSJeff Kirsher 			}
21537ac6653aSJeff Kirsher 			prefetch(skb->data - NET_IP_ALIGN);
21547ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = NULL;
21557ac6653aSJeff Kirsher 
2156891434b1SRayagond Kokatanur 			stmmac_get_rx_hwtstamp(priv, entry, skb);
2157891434b1SRayagond Kokatanur 
21587ac6653aSJeff Kirsher 			skb_put(skb, frame_len);
21597ac6653aSJeff Kirsher 			dma_unmap_single(priv->device,
21607ac6653aSJeff Kirsher 					 priv->rx_skbuff_dma[entry],
21617ac6653aSJeff Kirsher 					 priv->dma_buf_sz, DMA_FROM_DEVICE);
216283d7af64SGiuseppe CAVALLARO 
21637ac6653aSJeff Kirsher 			if (netif_msg_pktdata(priv)) {
216483d7af64SGiuseppe CAVALLARO 				pr_debug("frame received (%dbytes)", frame_len);
21657ac6653aSJeff Kirsher 				print_pkt(skb->data, frame_len);
21667ac6653aSJeff Kirsher 			}
216783d7af64SGiuseppe CAVALLARO 
2168b9381985SVince Bridgers 			stmmac_rx_vlan(priv->dev, skb);
2169b9381985SVince Bridgers 
21707ac6653aSJeff Kirsher 			skb->protocol = eth_type_trans(skb, priv->dev);
21717ac6653aSJeff Kirsher 
2172ceb69499SGiuseppe CAVALLARO 			if (unlikely(!coe))
21737ac6653aSJeff Kirsher 				skb_checksum_none_assert(skb);
217462a2ab93SGiuseppe CAVALLARO 			else
21757ac6653aSJeff Kirsher 				skb->ip_summed = CHECKSUM_UNNECESSARY;
217662a2ab93SGiuseppe CAVALLARO 
21777ac6653aSJeff Kirsher 			napi_gro_receive(&priv->napi, skb);
21787ac6653aSJeff Kirsher 
21797ac6653aSJeff Kirsher 			priv->dev->stats.rx_packets++;
21807ac6653aSJeff Kirsher 			priv->dev->stats.rx_bytes += frame_len;
21817ac6653aSJeff Kirsher 		}
21827ac6653aSJeff Kirsher 		entry = next_entry;
21837ac6653aSJeff Kirsher 	}
21847ac6653aSJeff Kirsher 
21857ac6653aSJeff Kirsher 	stmmac_rx_refill(priv);
21867ac6653aSJeff Kirsher 
21877ac6653aSJeff Kirsher 	priv->xstats.rx_pkt_n += count;
21887ac6653aSJeff Kirsher 
21897ac6653aSJeff Kirsher 	return count;
21907ac6653aSJeff Kirsher }
21917ac6653aSJeff Kirsher 
21927ac6653aSJeff Kirsher /**
21937ac6653aSJeff Kirsher  *  stmmac_poll - stmmac poll method (NAPI)
21947ac6653aSJeff Kirsher  *  @napi : pointer to the napi structure.
21957ac6653aSJeff Kirsher  *  @budget : maximum number of packets that the current CPU can receive from
21967ac6653aSJeff Kirsher  *	      all interfaces.
21977ac6653aSJeff Kirsher  *  Description :
21989125cdd1SGiuseppe CAVALLARO  *  To look at the incoming frames and clear the tx resources.
21997ac6653aSJeff Kirsher  */
22007ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget)
22017ac6653aSJeff Kirsher {
22027ac6653aSJeff Kirsher 	struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
22037ac6653aSJeff Kirsher 	int work_done = 0;
22047ac6653aSJeff Kirsher 
22059125cdd1SGiuseppe CAVALLARO 	priv->xstats.napi_poll++;
22069125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
22077ac6653aSJeff Kirsher 
22089125cdd1SGiuseppe CAVALLARO 	work_done = stmmac_rx(priv, budget);
22097ac6653aSJeff Kirsher 	if (work_done < budget) {
22107ac6653aSJeff Kirsher 		napi_complete(napi);
22119125cdd1SGiuseppe CAVALLARO 		stmmac_enable_dma_irq(priv);
22127ac6653aSJeff Kirsher 	}
22137ac6653aSJeff Kirsher 	return work_done;
22147ac6653aSJeff Kirsher }
22157ac6653aSJeff Kirsher 
22167ac6653aSJeff Kirsher /**
22177ac6653aSJeff Kirsher  *  stmmac_tx_timeout
22187ac6653aSJeff Kirsher  *  @dev : Pointer to net device structure
22197ac6653aSJeff Kirsher  *  Description: this function is called when a packet transmission fails to
22207284a3f1SGiuseppe CAVALLARO  *   complete within a reasonable time. The driver will mark the error in the
22217ac6653aSJeff Kirsher  *   netdev structure and arrange for the device to be reset to a sane state
22227ac6653aSJeff Kirsher  *   in order to transmit a new packet.
22237ac6653aSJeff Kirsher  */
22247ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev)
22257ac6653aSJeff Kirsher {
22267ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22277ac6653aSJeff Kirsher 
22287ac6653aSJeff Kirsher 	/* Clear Tx resources and restart transmitting again */
22297ac6653aSJeff Kirsher 	stmmac_tx_err(priv);
22307ac6653aSJeff Kirsher }
22317ac6653aSJeff Kirsher 
22327ac6653aSJeff Kirsher /**
223301789349SJiri Pirko  *  stmmac_set_rx_mode - entry point for multicast addressing
22347ac6653aSJeff Kirsher  *  @dev : pointer to the device structure
22357ac6653aSJeff Kirsher  *  Description:
22367ac6653aSJeff Kirsher  *  This function is a driver entry point which gets called by the kernel
22377ac6653aSJeff Kirsher  *  whenever multicast addresses must be enabled/disabled.
22387ac6653aSJeff Kirsher  *  Return value:
22397ac6653aSJeff Kirsher  *  void.
22407ac6653aSJeff Kirsher  */
224101789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev)
22427ac6653aSJeff Kirsher {
22437ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22447ac6653aSJeff Kirsher 
22457ac6653aSJeff Kirsher 	spin_lock(&priv->lock);
22463b57de95SVince Bridgers 	priv->hw->mac->set_filter(priv->hw, dev);
22477ac6653aSJeff Kirsher 	spin_unlock(&priv->lock);
22487ac6653aSJeff Kirsher }
22497ac6653aSJeff Kirsher 
22507ac6653aSJeff Kirsher /**
22517ac6653aSJeff Kirsher  *  stmmac_change_mtu - entry point to change MTU size for the device.
22527ac6653aSJeff Kirsher  *  @dev : device pointer.
22537ac6653aSJeff Kirsher  *  @new_mtu : the new MTU size for the device.
22547ac6653aSJeff Kirsher  *  Description: the Maximum Transfer Unit (MTU) is used by the network layer
22557ac6653aSJeff Kirsher  *  to drive packet transmission. Ethernet has an MTU of 1500 octets
22567ac6653aSJeff Kirsher  *  (ETH_DATA_LEN). This value can be changed with ifconfig.
22577ac6653aSJeff Kirsher  *  Return value:
22587ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
22597ac6653aSJeff Kirsher  *  file on failure.
22607ac6653aSJeff Kirsher  */
22617ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
22627ac6653aSJeff Kirsher {
22637ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22647ac6653aSJeff Kirsher 	int max_mtu;
22657ac6653aSJeff Kirsher 
22667ac6653aSJeff Kirsher 	if (netif_running(dev)) {
22677ac6653aSJeff Kirsher 		pr_err("%s: must be stopped to change its MTU\n", dev->name);
22687ac6653aSJeff Kirsher 		return -EBUSY;
22697ac6653aSJeff Kirsher 	}
22707ac6653aSJeff Kirsher 
227148febf7eSGiuseppe CAVALLARO 	if (priv->plat->enh_desc)
22727ac6653aSJeff Kirsher 		max_mtu = JUMBO_LEN;
22737ac6653aSJeff Kirsher 	else
227445db81e1SGiuseppe CAVALLARO 		max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
22757ac6653aSJeff Kirsher 
22762618abb7SVince Bridgers 	if (priv->plat->maxmtu < max_mtu)
22772618abb7SVince Bridgers 		max_mtu = priv->plat->maxmtu;
22782618abb7SVince Bridgers 
22797ac6653aSJeff Kirsher 	if ((new_mtu < 46) || (new_mtu > max_mtu)) {
22807ac6653aSJeff Kirsher 		pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
22817ac6653aSJeff Kirsher 		return -EINVAL;
22827ac6653aSJeff Kirsher 	}
22837ac6653aSJeff Kirsher 
22847ac6653aSJeff Kirsher 	dev->mtu = new_mtu;
22857ac6653aSJeff Kirsher 	netdev_update_features(dev);
22867ac6653aSJeff Kirsher 
22877ac6653aSJeff Kirsher 	return 0;
22887ac6653aSJeff Kirsher }
22897ac6653aSJeff Kirsher 
2290c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev,
2291c8f44affSMichał Mirosław 					     netdev_features_t features)
22927ac6653aSJeff Kirsher {
22937ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22947ac6653aSJeff Kirsher 
229538912bdbSDeepak SIKRI 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
22967ac6653aSJeff Kirsher 		features &= ~NETIF_F_RXCSUM;
229738912bdbSDeepak SIKRI 	else if (priv->plat->rx_coe == STMMAC_RX_COE_TYPE1)
229838912bdbSDeepak SIKRI 		features &= ~NETIF_F_IPV6_CSUM;
22997ac6653aSJeff Kirsher 	if (!priv->plat->tx_coe)
23007ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
23017ac6653aSJeff Kirsher 
23027ac6653aSJeff Kirsher 	/* Some GMAC devices have a bugged Jumbo frame support that
23037ac6653aSJeff Kirsher 	 * needs to have the Tx COE disabled for oversized frames
23047ac6653aSJeff Kirsher 	 * (due to limited buffer sizes). In this case we disable
2305ceb69499SGiuseppe CAVALLARO 	 * the TX csum insertionin the TDES and not use SF.
2306ceb69499SGiuseppe CAVALLARO 	 */
23077ac6653aSJeff Kirsher 	if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
23087ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
23097ac6653aSJeff Kirsher 
23107ac6653aSJeff Kirsher 	return features;
23117ac6653aSJeff Kirsher }
23127ac6653aSJeff Kirsher 
231332ceabcaSGiuseppe CAVALLARO /**
231432ceabcaSGiuseppe CAVALLARO  *  stmmac_interrupt - main ISR
231532ceabcaSGiuseppe CAVALLARO  *  @irq: interrupt number.
231632ceabcaSGiuseppe CAVALLARO  *  @dev_id: to pass the net device pointer.
231732ceabcaSGiuseppe CAVALLARO  *  Description: this is the main driver interrupt service routine.
231832ceabcaSGiuseppe CAVALLARO  *  It calls the DMA ISR and also the core ISR to manage PMT, MMC, LPI
231932ceabcaSGiuseppe CAVALLARO  *  interrupts.
232032ceabcaSGiuseppe CAVALLARO  */
23217ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
23227ac6653aSJeff Kirsher {
23237ac6653aSJeff Kirsher 	struct net_device *dev = (struct net_device *)dev_id;
23247ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23257ac6653aSJeff Kirsher 
232689f7f2cfSSrinivas Kandagatla 	if (priv->irq_wake)
232789f7f2cfSSrinivas Kandagatla 		pm_wakeup_event(priv->device, 0);
232889f7f2cfSSrinivas Kandagatla 
23297ac6653aSJeff Kirsher 	if (unlikely(!dev)) {
23307ac6653aSJeff Kirsher 		pr_err("%s: invalid dev pointer\n", __func__);
23317ac6653aSJeff Kirsher 		return IRQ_NONE;
23327ac6653aSJeff Kirsher 	}
23337ac6653aSJeff Kirsher 
23347ac6653aSJeff Kirsher 	/* To handle GMAC own interrupts */
2335d765955dSGiuseppe CAVALLARO 	if (priv->plat->has_gmac) {
23367ed24bbeSVince Bridgers 		int status = priv->hw->mac->host_irq_status(priv->hw,
23370982a0f6SGiuseppe CAVALLARO 							    &priv->xstats);
2338d765955dSGiuseppe CAVALLARO 		if (unlikely(status)) {
2339d765955dSGiuseppe CAVALLARO 			/* For LPI we need to save the tx status */
23400982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
2341d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = true;
23420982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
2343d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = false;
2344d765955dSGiuseppe CAVALLARO 		}
2345d765955dSGiuseppe CAVALLARO 	}
2346d765955dSGiuseppe CAVALLARO 
2347d765955dSGiuseppe CAVALLARO 	/* To handle DMA interrupts */
23487ac6653aSJeff Kirsher 	stmmac_dma_interrupt(priv);
23497ac6653aSJeff Kirsher 
23507ac6653aSJeff Kirsher 	return IRQ_HANDLED;
23517ac6653aSJeff Kirsher }
23527ac6653aSJeff Kirsher 
23537ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
23547ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools
2355ceb69499SGiuseppe CAVALLARO  * to allow network I/O with interrupts disabled.
2356ceb69499SGiuseppe CAVALLARO  */
23577ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev)
23587ac6653aSJeff Kirsher {
23597ac6653aSJeff Kirsher 	disable_irq(dev->irq);
23607ac6653aSJeff Kirsher 	stmmac_interrupt(dev->irq, dev);
23617ac6653aSJeff Kirsher 	enable_irq(dev->irq);
23627ac6653aSJeff Kirsher }
23637ac6653aSJeff Kirsher #endif
23647ac6653aSJeff Kirsher 
23657ac6653aSJeff Kirsher /**
23667ac6653aSJeff Kirsher  *  stmmac_ioctl - Entry point for the Ioctl
23677ac6653aSJeff Kirsher  *  @dev: Device pointer.
23687ac6653aSJeff Kirsher  *  @rq: An IOCTL specefic structure, that can contain a pointer to
23697ac6653aSJeff Kirsher  *  a proprietary structure used to pass information to the driver.
23707ac6653aSJeff Kirsher  *  @cmd: IOCTL command
23717ac6653aSJeff Kirsher  *  Description:
237232ceabcaSGiuseppe CAVALLARO  *  Currently it supports the phy_mii_ioctl(...) and HW time stamping.
23737ac6653aSJeff Kirsher  */
23747ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
23757ac6653aSJeff Kirsher {
23767ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
2377891434b1SRayagond Kokatanur 	int ret = -EOPNOTSUPP;
23787ac6653aSJeff Kirsher 
23797ac6653aSJeff Kirsher 	if (!netif_running(dev))
23807ac6653aSJeff Kirsher 		return -EINVAL;
23817ac6653aSJeff Kirsher 
2382891434b1SRayagond Kokatanur 	switch (cmd) {
2383891434b1SRayagond Kokatanur 	case SIOCGMIIPHY:
2384891434b1SRayagond Kokatanur 	case SIOCGMIIREG:
2385891434b1SRayagond Kokatanur 	case SIOCSMIIREG:
23867ac6653aSJeff Kirsher 		if (!priv->phydev)
23877ac6653aSJeff Kirsher 			return -EINVAL;
23887ac6653aSJeff Kirsher 		ret = phy_mii_ioctl(priv->phydev, rq, cmd);
2389891434b1SRayagond Kokatanur 		break;
2390891434b1SRayagond Kokatanur 	case SIOCSHWTSTAMP:
2391891434b1SRayagond Kokatanur 		ret = stmmac_hwtstamp_ioctl(dev, rq);
2392891434b1SRayagond Kokatanur 		break;
2393891434b1SRayagond Kokatanur 	default:
2394891434b1SRayagond Kokatanur 		break;
2395891434b1SRayagond Kokatanur 	}
23967ac6653aSJeff Kirsher 
23977ac6653aSJeff Kirsher 	return ret;
23987ac6653aSJeff Kirsher }
23997ac6653aSJeff Kirsher 
24007ac29055SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_DEBUG_FS
24017ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir;
24027ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_rings_status;
2403e7434821SGiuseppe CAVALLARO static struct dentry *stmmac_dma_cap;
24047ac29055SGiuseppe CAVALLARO 
2405c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc,
2406c24602efSGiuseppe CAVALLARO 			       struct seq_file *seq)
24077ac29055SGiuseppe CAVALLARO {
24087ac29055SGiuseppe CAVALLARO 	int i;
2409c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
2410c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
24117ac29055SGiuseppe CAVALLARO 
2412c24602efSGiuseppe CAVALLARO 	for (i = 0; i < size; i++) {
2413c24602efSGiuseppe CAVALLARO 		u64 x;
2414c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
2415c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
2416c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2417c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2418c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2419c24602efSGiuseppe CAVALLARO 				   ep->basic.des2, ep->basic.des3);
2420c24602efSGiuseppe CAVALLARO 			ep++;
2421c24602efSGiuseppe CAVALLARO 		} else {
2422c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
2423c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2424c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2425c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2426c24602efSGiuseppe CAVALLARO 				   p->des2, p->des3);
2427c24602efSGiuseppe CAVALLARO 			p++;
2428c24602efSGiuseppe CAVALLARO 		}
24297ac29055SGiuseppe CAVALLARO 		seq_printf(seq, "\n");
24307ac29055SGiuseppe CAVALLARO 	}
2431c24602efSGiuseppe CAVALLARO }
24327ac29055SGiuseppe CAVALLARO 
2433c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
2434c24602efSGiuseppe CAVALLARO {
2435c24602efSGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2436c24602efSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2437c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
2438c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
24397ac29055SGiuseppe CAVALLARO 
2440c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
2441c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended RX descriptor ring:\n");
2442c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_erx, rxsize, 1, seq);
2443c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended TX descriptor ring:\n");
2444c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_etx, txsize, 1, seq);
2445c24602efSGiuseppe CAVALLARO 	} else {
2446c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "RX descriptor ring:\n");
2447c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_rx, rxsize, 0, seq);
2448c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "TX descriptor ring:\n");
2449c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_tx, txsize, 0, seq);
24507ac29055SGiuseppe CAVALLARO 	}
24517ac29055SGiuseppe CAVALLARO 
24527ac29055SGiuseppe CAVALLARO 	return 0;
24537ac29055SGiuseppe CAVALLARO }
24547ac29055SGiuseppe CAVALLARO 
24557ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
24567ac29055SGiuseppe CAVALLARO {
24577ac29055SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
24587ac29055SGiuseppe CAVALLARO }
24597ac29055SGiuseppe CAVALLARO 
24607ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = {
24617ac29055SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
24627ac29055SGiuseppe CAVALLARO 	.open = stmmac_sysfs_ring_open,
24637ac29055SGiuseppe CAVALLARO 	.read = seq_read,
24647ac29055SGiuseppe CAVALLARO 	.llseek = seq_lseek,
246574863948SDjalal Harouni 	.release = single_release,
24667ac29055SGiuseppe CAVALLARO };
24677ac29055SGiuseppe CAVALLARO 
2468e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
2469e7434821SGiuseppe CAVALLARO {
2470e7434821SGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2471e7434821SGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2472e7434821SGiuseppe CAVALLARO 
247319e30c14SGiuseppe CAVALLARO 	if (!priv->hw_cap_support) {
2474e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "DMA HW features not supported\n");
2475e7434821SGiuseppe CAVALLARO 		return 0;
2476e7434821SGiuseppe CAVALLARO 	}
2477e7434821SGiuseppe CAVALLARO 
2478e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2479e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tDMA HW features\n");
2480e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2481e7434821SGiuseppe CAVALLARO 
2482e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t10/100 Mbps %s\n",
2483e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_10_100) ? "Y" : "N");
2484e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t1000 Mbps %s\n",
2485e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_1000) ? "Y" : "N");
2486e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHalf duple %s\n",
2487e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.half_duplex) ? "Y" : "N");
2488e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHash Filter: %s\n",
2489e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.hash_filter) ? "Y" : "N");
2490e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tMultiple MAC address registers: %s\n",
2491e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.multi_addr) ? "Y" : "N");
2492e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n",
2493e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pcs) ? "Y" : "N");
2494e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
2495e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.sma_mdio) ? "Y" : "N");
2496e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Remote wake up: %s\n",
2497e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
2498e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Magic Frame: %s\n",
2499e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
2500e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRMON module: %s\n",
2501e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rmon) ? "Y" : "N");
2502e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
2503e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.time_stamp) ? "Y" : "N");
2504e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n",
2505e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.atime_stamp) ? "Y" : "N");
2506e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n",
2507e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.eee) ? "Y" : "N");
2508e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
2509e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tChecksum Offload in TX: %s\n",
2510e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.tx_coe) ? "Y" : "N");
2511e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
2512e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
2513e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
2514e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
2515e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
2516e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
2517e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
2518e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_rx_channel);
2519e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
2520e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_tx_channel);
2521e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tEnhanced descriptors: %s\n",
2522e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.enh_desc) ? "Y" : "N");
2523e7434821SGiuseppe CAVALLARO 
2524e7434821SGiuseppe CAVALLARO 	return 0;
2525e7434821SGiuseppe CAVALLARO }
2526e7434821SGiuseppe CAVALLARO 
2527e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
2528e7434821SGiuseppe CAVALLARO {
2529e7434821SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
2530e7434821SGiuseppe CAVALLARO }
2531e7434821SGiuseppe CAVALLARO 
2532e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = {
2533e7434821SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
2534e7434821SGiuseppe CAVALLARO 	.open = stmmac_sysfs_dma_cap_open,
2535e7434821SGiuseppe CAVALLARO 	.read = seq_read,
2536e7434821SGiuseppe CAVALLARO 	.llseek = seq_lseek,
253774863948SDjalal Harouni 	.release = single_release,
2538e7434821SGiuseppe CAVALLARO };
2539e7434821SGiuseppe CAVALLARO 
25407ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev)
25417ac29055SGiuseppe CAVALLARO {
25427ac29055SGiuseppe CAVALLARO 	/* Create debugfs entries */
25437ac29055SGiuseppe CAVALLARO 	stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
25447ac29055SGiuseppe CAVALLARO 
25457ac29055SGiuseppe CAVALLARO 	if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
25467ac29055SGiuseppe CAVALLARO 		pr_err("ERROR %s, debugfs create directory failed\n",
25477ac29055SGiuseppe CAVALLARO 		       STMMAC_RESOURCE_NAME);
25487ac29055SGiuseppe CAVALLARO 
25497ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
25507ac29055SGiuseppe CAVALLARO 	}
25517ac29055SGiuseppe CAVALLARO 
25527ac29055SGiuseppe CAVALLARO 	/* Entry to report DMA RX/TX rings */
25537ac29055SGiuseppe CAVALLARO 	stmmac_rings_status = debugfs_create_file("descriptors_status",
25547ac29055SGiuseppe CAVALLARO 						  S_IRUGO, stmmac_fs_dir, dev,
25557ac29055SGiuseppe CAVALLARO 						  &stmmac_rings_status_fops);
25567ac29055SGiuseppe CAVALLARO 
25577ac29055SGiuseppe CAVALLARO 	if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
25587ac29055SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac ring debugfs file\n");
25597ac29055SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
25607ac29055SGiuseppe CAVALLARO 
25617ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
25627ac29055SGiuseppe CAVALLARO 	}
25637ac29055SGiuseppe CAVALLARO 
2564e7434821SGiuseppe CAVALLARO 	/* Entry to report the DMA HW features */
2565e7434821SGiuseppe CAVALLARO 	stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
2566e7434821SGiuseppe CAVALLARO 					     dev, &stmmac_dma_cap_fops);
2567e7434821SGiuseppe CAVALLARO 
2568e7434821SGiuseppe CAVALLARO 	if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
2569e7434821SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac MMC debugfs file\n");
2570e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_rings_status);
2571e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
2572e7434821SGiuseppe CAVALLARO 
2573e7434821SGiuseppe CAVALLARO 		return -ENOMEM;
2574e7434821SGiuseppe CAVALLARO 	}
2575e7434821SGiuseppe CAVALLARO 
25767ac29055SGiuseppe CAVALLARO 	return 0;
25777ac29055SGiuseppe CAVALLARO }
25787ac29055SGiuseppe CAVALLARO 
25797ac29055SGiuseppe CAVALLARO static void stmmac_exit_fs(void)
25807ac29055SGiuseppe CAVALLARO {
25817ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_rings_status);
2582e7434821SGiuseppe CAVALLARO 	debugfs_remove(stmmac_dma_cap);
25837ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_fs_dir);
25847ac29055SGiuseppe CAVALLARO }
25857ac29055SGiuseppe CAVALLARO #endif /* CONFIG_STMMAC_DEBUG_FS */
25867ac29055SGiuseppe CAVALLARO 
25877ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = {
25887ac6653aSJeff Kirsher 	.ndo_open = stmmac_open,
25897ac6653aSJeff Kirsher 	.ndo_start_xmit = stmmac_xmit,
25907ac6653aSJeff Kirsher 	.ndo_stop = stmmac_release,
25917ac6653aSJeff Kirsher 	.ndo_change_mtu = stmmac_change_mtu,
25927ac6653aSJeff Kirsher 	.ndo_fix_features = stmmac_fix_features,
259301789349SJiri Pirko 	.ndo_set_rx_mode = stmmac_set_rx_mode,
25947ac6653aSJeff Kirsher 	.ndo_tx_timeout = stmmac_tx_timeout,
25957ac6653aSJeff Kirsher 	.ndo_do_ioctl = stmmac_ioctl,
25967ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
25977ac6653aSJeff Kirsher 	.ndo_poll_controller = stmmac_poll_controller,
25987ac6653aSJeff Kirsher #endif
25997ac6653aSJeff Kirsher 	.ndo_set_mac_address = eth_mac_addr,
26007ac6653aSJeff Kirsher };
26017ac6653aSJeff Kirsher 
26027ac6653aSJeff Kirsher /**
2603cf3f047bSGiuseppe CAVALLARO  *  stmmac_hw_init - Init the MAC device
260432ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
2605cf3f047bSGiuseppe CAVALLARO  *  Description: this function detects which MAC device
2606cf3f047bSGiuseppe CAVALLARO  *  (GMAC/MAC10-100) has to attached, checks the HW capability
2607cf3f047bSGiuseppe CAVALLARO  *  (if supported) and sets the driver's features (for example
2608cf3f047bSGiuseppe CAVALLARO  *  to use the ring or chaine mode or support the normal/enh
2609cf3f047bSGiuseppe CAVALLARO  *  descriptor structure).
2610cf3f047bSGiuseppe CAVALLARO  */
2611cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv)
2612cf3f047bSGiuseppe CAVALLARO {
2613cf3f047bSGiuseppe CAVALLARO 	struct mac_device_info *mac;
2614cf3f047bSGiuseppe CAVALLARO 
2615cf3f047bSGiuseppe CAVALLARO 	/* Identify the MAC HW device */
261603f2eecdSMarc Kleine-Budde 	if (priv->plat->has_gmac) {
261703f2eecdSMarc Kleine-Budde 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
26183b57de95SVince Bridgers 		mac = dwmac1000_setup(priv->ioaddr,
26193b57de95SVince Bridgers 				      priv->plat->multicast_filter_bins,
26203b57de95SVince Bridgers 				      priv->plat->unicast_filter_entries);
262103f2eecdSMarc Kleine-Budde 	} else {
2622cf3f047bSGiuseppe CAVALLARO 		mac = dwmac100_setup(priv->ioaddr);
262303f2eecdSMarc Kleine-Budde 	}
2624cf3f047bSGiuseppe CAVALLARO 	if (!mac)
2625cf3f047bSGiuseppe CAVALLARO 		return -ENOMEM;
2626cf3f047bSGiuseppe CAVALLARO 
2627cf3f047bSGiuseppe CAVALLARO 	priv->hw = mac;
2628cf3f047bSGiuseppe CAVALLARO 
2629cf3f047bSGiuseppe CAVALLARO 	/* Get and dump the chip ID */
2630cffb13f4SGiuseppe CAVALLARO 	priv->synopsys_id = stmmac_get_synopsys_id(priv);
2631cf3f047bSGiuseppe CAVALLARO 
26324a7d666aSGiuseppe CAVALLARO 	/* To use the chained or ring mode */
26334a7d666aSGiuseppe CAVALLARO 	if (chain_mode) {
263429896a67SGiuseppe CAVALLARO 		priv->hw->mode = &chain_mode_ops;
26354a7d666aSGiuseppe CAVALLARO 		pr_info(" Chain mode enabled\n");
26364a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_CHAIN_MODE;
26374a7d666aSGiuseppe CAVALLARO 	} else {
263829896a67SGiuseppe CAVALLARO 		priv->hw->mode = &ring_mode_ops;
26394a7d666aSGiuseppe CAVALLARO 		pr_info(" Ring mode enabled\n");
26404a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_RING_MODE;
26414a7d666aSGiuseppe CAVALLARO 	}
26424a7d666aSGiuseppe CAVALLARO 
2643cf3f047bSGiuseppe CAVALLARO 	/* Get the HW capability (new GMAC newer than 3.50a) */
2644cf3f047bSGiuseppe CAVALLARO 	priv->hw_cap_support = stmmac_get_hw_features(priv);
2645cf3f047bSGiuseppe CAVALLARO 	if (priv->hw_cap_support) {
2646cf3f047bSGiuseppe CAVALLARO 		pr_info(" DMA HW capability register supported");
2647cf3f047bSGiuseppe CAVALLARO 
2648cf3f047bSGiuseppe CAVALLARO 		/* We can override some gmac/dma configuration fields: e.g.
2649cf3f047bSGiuseppe CAVALLARO 		 * enh_desc, tx_coe (e.g. that are passed through the
2650cf3f047bSGiuseppe CAVALLARO 		 * platform) with the values from the HW capability
2651cf3f047bSGiuseppe CAVALLARO 		 * register (if supported).
2652cf3f047bSGiuseppe CAVALLARO 		 */
2653cf3f047bSGiuseppe CAVALLARO 		priv->plat->enh_desc = priv->dma_cap.enh_desc;
2654cf3f047bSGiuseppe CAVALLARO 		priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
265538912bdbSDeepak SIKRI 
265638912bdbSDeepak SIKRI 		priv->plat->tx_coe = priv->dma_cap.tx_coe;
265738912bdbSDeepak SIKRI 
265838912bdbSDeepak SIKRI 		if (priv->dma_cap.rx_coe_type2)
265938912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
266038912bdbSDeepak SIKRI 		else if (priv->dma_cap.rx_coe_type1)
266138912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
266238912bdbSDeepak SIKRI 
2663cf3f047bSGiuseppe CAVALLARO 	} else
2664cf3f047bSGiuseppe CAVALLARO 		pr_info(" No HW DMA feature register supported");
2665cf3f047bSGiuseppe CAVALLARO 
266661369d02SByungho An 	/* To use alternate (extended) or normal descriptor structures */
266761369d02SByungho An 	stmmac_selec_desc_mode(priv);
266861369d02SByungho An 
266938912bdbSDeepak SIKRI 	if (priv->plat->rx_coe)
267038912bdbSDeepak SIKRI 		pr_info(" RX Checksum Offload Engine supported (type %d)\n",
267138912bdbSDeepak SIKRI 			priv->plat->rx_coe);
2672cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->tx_coe)
2673cf3f047bSGiuseppe CAVALLARO 		pr_info(" TX Checksum insertion supported\n");
2674cf3f047bSGiuseppe CAVALLARO 
2675cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->pmt) {
2676cf3f047bSGiuseppe CAVALLARO 		pr_info(" Wake-Up On Lan supported\n");
2677cf3f047bSGiuseppe CAVALLARO 		device_set_wakeup_capable(priv->device, 1);
2678cf3f047bSGiuseppe CAVALLARO 	}
2679cf3f047bSGiuseppe CAVALLARO 
2680c24602efSGiuseppe CAVALLARO 	return 0;
2681cf3f047bSGiuseppe CAVALLARO }
2682cf3f047bSGiuseppe CAVALLARO 
2683cf3f047bSGiuseppe CAVALLARO /**
2684bfab27a1SGiuseppe CAVALLARO  * stmmac_dvr_probe
2685bfab27a1SGiuseppe CAVALLARO  * @device: device pointer
2686ff3dd78cSGiuseppe CAVALLARO  * @plat_dat: platform data pointer
2687ff3dd78cSGiuseppe CAVALLARO  * @addr: iobase memory address
2688bfab27a1SGiuseppe CAVALLARO  * Description: this is the main probe function used to
2689bfab27a1SGiuseppe CAVALLARO  * call the alloc_etherdev, allocate the priv structure.
26907ac6653aSJeff Kirsher  */
2691bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *stmmac_dvr_probe(struct device *device,
2692cf3f047bSGiuseppe CAVALLARO 				     struct plat_stmmacenet_data *plat_dat,
2693cf3f047bSGiuseppe CAVALLARO 				     void __iomem *addr)
26947ac6653aSJeff Kirsher {
26957ac6653aSJeff Kirsher 	int ret = 0;
2696bfab27a1SGiuseppe CAVALLARO 	struct net_device *ndev = NULL;
2697bfab27a1SGiuseppe CAVALLARO 	struct stmmac_priv *priv;
26987ac6653aSJeff Kirsher 
2699bfab27a1SGiuseppe CAVALLARO 	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
270041de8d4cSJoe Perches 	if (!ndev)
2701bfab27a1SGiuseppe CAVALLARO 		return NULL;
27027ac6653aSJeff Kirsher 
2703bfab27a1SGiuseppe CAVALLARO 	SET_NETDEV_DEV(ndev, device);
27047ac6653aSJeff Kirsher 
2705bfab27a1SGiuseppe CAVALLARO 	priv = netdev_priv(ndev);
2706bfab27a1SGiuseppe CAVALLARO 	priv->device = device;
2707bfab27a1SGiuseppe CAVALLARO 	priv->dev = ndev;
2708bfab27a1SGiuseppe CAVALLARO 
2709bfab27a1SGiuseppe CAVALLARO 	ether_setup(ndev);
2710bfab27a1SGiuseppe CAVALLARO 
2711bfab27a1SGiuseppe CAVALLARO 	stmmac_set_ethtool_ops(ndev);
2712cf3f047bSGiuseppe CAVALLARO 	priv->pause = pause;
2713cf3f047bSGiuseppe CAVALLARO 	priv->plat = plat_dat;
2714cf3f047bSGiuseppe CAVALLARO 	priv->ioaddr = addr;
2715cf3f047bSGiuseppe CAVALLARO 	priv->dev->base_addr = (unsigned long)addr;
2716bfab27a1SGiuseppe CAVALLARO 
2717cf3f047bSGiuseppe CAVALLARO 	/* Verify driver arguments */
2718cf3f047bSGiuseppe CAVALLARO 	stmmac_verify_args();
2719cf3f047bSGiuseppe CAVALLARO 
2720cf3f047bSGiuseppe CAVALLARO 	/* Override with kernel parameters if supplied XXX CRS XXX
2721ceb69499SGiuseppe CAVALLARO 	 * this needs to have multiple instances
2722ceb69499SGiuseppe CAVALLARO 	 */
2723cf3f047bSGiuseppe CAVALLARO 	if ((phyaddr >= 0) && (phyaddr <= 31))
2724cf3f047bSGiuseppe CAVALLARO 		priv->plat->phy_addr = phyaddr;
2725cf3f047bSGiuseppe CAVALLARO 
272662866e98SChen-Yu Tsai 	priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
272762866e98SChen-Yu Tsai 	if (IS_ERR(priv->stmmac_clk)) {
272862866e98SChen-Yu Tsai 		dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
272962866e98SChen-Yu Tsai 			 __func__);
2730c5e4ddbdSChen-Yu Tsai 		ret = PTR_ERR(priv->stmmac_clk);
273162866e98SChen-Yu Tsai 		goto error_clk_get;
273262866e98SChen-Yu Tsai 	}
273362866e98SChen-Yu Tsai 	clk_prepare_enable(priv->stmmac_clk);
273462866e98SChen-Yu Tsai 
2735c5e4ddbdSChen-Yu Tsai 	priv->stmmac_rst = devm_reset_control_get(priv->device,
2736c5e4ddbdSChen-Yu Tsai 						  STMMAC_RESOURCE_NAME);
2737c5e4ddbdSChen-Yu Tsai 	if (IS_ERR(priv->stmmac_rst)) {
2738c5e4ddbdSChen-Yu Tsai 		if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
2739c5e4ddbdSChen-Yu Tsai 			ret = -EPROBE_DEFER;
2740c5e4ddbdSChen-Yu Tsai 			goto error_hw_init;
2741c5e4ddbdSChen-Yu Tsai 		}
2742c5e4ddbdSChen-Yu Tsai 		dev_info(priv->device, "no reset control found\n");
2743c5e4ddbdSChen-Yu Tsai 		priv->stmmac_rst = NULL;
2744c5e4ddbdSChen-Yu Tsai 	}
2745c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2746c5e4ddbdSChen-Yu Tsai 		reset_control_deassert(priv->stmmac_rst);
2747c5e4ddbdSChen-Yu Tsai 
2748cf3f047bSGiuseppe CAVALLARO 	/* Init MAC and get the capabilities */
2749c24602efSGiuseppe CAVALLARO 	ret = stmmac_hw_init(priv);
2750c24602efSGiuseppe CAVALLARO 	if (ret)
275162866e98SChen-Yu Tsai 		goto error_hw_init;
2752cf3f047bSGiuseppe CAVALLARO 
2753cf3f047bSGiuseppe CAVALLARO 	ndev->netdev_ops = &stmmac_netdev_ops;
2754cf3f047bSGiuseppe CAVALLARO 
2755cf3f047bSGiuseppe CAVALLARO 	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
2756cf3f047bSGiuseppe CAVALLARO 			    NETIF_F_RXCSUM;
2757bfab27a1SGiuseppe CAVALLARO 	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
2758bfab27a1SGiuseppe CAVALLARO 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
27597ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED
27607ac6653aSJeff Kirsher 	/* Both mac100 and gmac support receive VLAN tag detection */
2761f646968fSPatrick McHardy 	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
27627ac6653aSJeff Kirsher #endif
27637ac6653aSJeff Kirsher 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
27647ac6653aSJeff Kirsher 
27657ac6653aSJeff Kirsher 	if (flow_ctrl)
27667ac6653aSJeff Kirsher 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
27677ac6653aSJeff Kirsher 
276862a2ab93SGiuseppe CAVALLARO 	/* Rx Watchdog is available in the COREs newer than the 3.40.
276962a2ab93SGiuseppe CAVALLARO 	 * In some case, for example on bugged HW this feature
277062a2ab93SGiuseppe CAVALLARO 	 * has to be disable and this can be done by passing the
277162a2ab93SGiuseppe CAVALLARO 	 * riwt_off field from the platform.
277262a2ab93SGiuseppe CAVALLARO 	 */
277362a2ab93SGiuseppe CAVALLARO 	if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
277462a2ab93SGiuseppe CAVALLARO 		priv->use_riwt = 1;
277562a2ab93SGiuseppe CAVALLARO 		pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
277662a2ab93SGiuseppe CAVALLARO 	}
277762a2ab93SGiuseppe CAVALLARO 
2778bfab27a1SGiuseppe CAVALLARO 	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
27797ac6653aSJeff Kirsher 
27807ac6653aSJeff Kirsher 	spin_lock_init(&priv->lock);
2781a9097a96SGiuseppe CAVALLARO 	spin_lock_init(&priv->tx_lock);
27827ac6653aSJeff Kirsher 
2783bfab27a1SGiuseppe CAVALLARO 	ret = register_netdev(ndev);
27847ac6653aSJeff Kirsher 	if (ret) {
2785cf3f047bSGiuseppe CAVALLARO 		pr_err("%s: ERROR %i registering the device\n", __func__, ret);
27866a81c26fSViresh Kumar 		goto error_netdev_register;
27877ac6653aSJeff Kirsher 	}
27887ac6653aSJeff Kirsher 
2789cd7201f4SGiuseppe CAVALLARO 	/* If a specific clk_csr value is passed from the platform
2790cd7201f4SGiuseppe CAVALLARO 	 * this means that the CSR Clock Range selection cannot be
2791cd7201f4SGiuseppe CAVALLARO 	 * changed at run-time and it is fixed. Viceversa the driver'll try to
2792cd7201f4SGiuseppe CAVALLARO 	 * set the MDC clock dynamically according to the csr actual
2793cd7201f4SGiuseppe CAVALLARO 	 * clock input.
2794cd7201f4SGiuseppe CAVALLARO 	 */
2795cd7201f4SGiuseppe CAVALLARO 	if (!priv->plat->clk_csr)
2796cd7201f4SGiuseppe CAVALLARO 		stmmac_clk_csr_set(priv);
2797cd7201f4SGiuseppe CAVALLARO 	else
2798cd7201f4SGiuseppe CAVALLARO 		priv->clk_csr = priv->plat->clk_csr;
2799cd7201f4SGiuseppe CAVALLARO 
2800e58bb43fSGiuseppe CAVALLARO 	stmmac_check_pcs_mode(priv);
2801e58bb43fSGiuseppe CAVALLARO 
28024d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
28034d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
28044bfcbd7aSFrancesco Virlinzi 		/* MDIO bus Registration */
28054bfcbd7aSFrancesco Virlinzi 		ret = stmmac_mdio_register(ndev);
28064bfcbd7aSFrancesco Virlinzi 		if (ret < 0) {
28074bfcbd7aSFrancesco Virlinzi 			pr_debug("%s: MDIO bus (id: %d) registration failed",
28084bfcbd7aSFrancesco Virlinzi 				 __func__, priv->plat->bus_id);
28096a81c26fSViresh Kumar 			goto error_mdio_register;
28104bfcbd7aSFrancesco Virlinzi 		}
2811e58bb43fSGiuseppe CAVALLARO 	}
28124bfcbd7aSFrancesco Virlinzi 
2813bfab27a1SGiuseppe CAVALLARO 	return priv;
28147ac6653aSJeff Kirsher 
28156a81c26fSViresh Kumar error_mdio_register:
28167ac6653aSJeff Kirsher 	unregister_netdev(ndev);
28176a81c26fSViresh Kumar error_netdev_register:
28186a81c26fSViresh Kumar 	netif_napi_del(&priv->napi);
281962866e98SChen-Yu Tsai error_hw_init:
282062866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
282162866e98SChen-Yu Tsai error_clk_get:
28227ac6653aSJeff Kirsher 	free_netdev(ndev);
28237ac6653aSJeff Kirsher 
2824c5e4ddbdSChen-Yu Tsai 	return ERR_PTR(ret);
28257ac6653aSJeff Kirsher }
28267ac6653aSJeff Kirsher 
28277ac6653aSJeff Kirsher /**
28287ac6653aSJeff Kirsher  * stmmac_dvr_remove
2829bfab27a1SGiuseppe CAVALLARO  * @ndev: net device pointer
28307ac6653aSJeff Kirsher  * Description: this function resets the TX/RX processes, disables the MAC RX/TX
2831bfab27a1SGiuseppe CAVALLARO  * changes the link status, releases the DMA descriptor rings.
28327ac6653aSJeff Kirsher  */
2833bfab27a1SGiuseppe CAVALLARO int stmmac_dvr_remove(struct net_device *ndev)
28347ac6653aSJeff Kirsher {
28357ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
28367ac6653aSJeff Kirsher 
28377ac6653aSJeff Kirsher 	pr_info("%s:\n\tremoving driver", __func__);
28387ac6653aSJeff Kirsher 
28397ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
28407ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
28417ac6653aSJeff Kirsher 
2842bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
28434d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
28444d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI)
28454bfcbd7aSFrancesco Virlinzi 		stmmac_mdio_unregister(ndev);
28467ac6653aSJeff Kirsher 	netif_carrier_off(ndev);
28477ac6653aSJeff Kirsher 	unregister_netdev(ndev);
2848c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2849c5e4ddbdSChen-Yu Tsai 		reset_control_assert(priv->stmmac_rst);
285062866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
28517ac6653aSJeff Kirsher 	free_netdev(ndev);
28527ac6653aSJeff Kirsher 
28537ac6653aSJeff Kirsher 	return 0;
28547ac6653aSJeff Kirsher }
28557ac6653aSJeff Kirsher 
28567ac6653aSJeff Kirsher #ifdef CONFIG_PM
2857bfab27a1SGiuseppe CAVALLARO int stmmac_suspend(struct net_device *ndev)
28587ac6653aSJeff Kirsher {
28597ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2860f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
28617ac6653aSJeff Kirsher 
28627ac6653aSJeff Kirsher 	if (!ndev || !netif_running(ndev))
28637ac6653aSJeff Kirsher 		return 0;
28647ac6653aSJeff Kirsher 
2865102463b1SFrancesco Virlinzi 	if (priv->phydev)
2866102463b1SFrancesco Virlinzi 		phy_stop(priv->phydev);
2867102463b1SFrancesco Virlinzi 
2868f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
28697ac6653aSJeff Kirsher 
28707ac6653aSJeff Kirsher 	netif_device_detach(ndev);
28717ac6653aSJeff Kirsher 	netif_stop_queue(ndev);
28727ac6653aSJeff Kirsher 
28737ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
28747ac6653aSJeff Kirsher 
28757ac6653aSJeff Kirsher 	/* Stop TX/RX DMA */
28767ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
28777ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
2878c24602efSGiuseppe CAVALLARO 
2879c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
28807ac6653aSJeff Kirsher 
28817ac6653aSJeff Kirsher 	/* Enable Power down mode by programming the PMT regs */
288289f7f2cfSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
28837ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, priv->wolopts);
288489f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 1;
288589f7f2cfSSrinivas Kandagatla 	} else {
2886bfab27a1SGiuseppe CAVALLARO 		stmmac_set_mac(priv->ioaddr, false);
2887db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_sleep_state(priv->device);
2888ba1377ffSGiuseppe CAVALLARO 		/* Disable clock in case of PWM is off */
2889a630844dSStefan Roese 		clk_disable_unprepare(priv->stmmac_clk);
2890ba1377ffSGiuseppe CAVALLARO 	}
2891f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
28922d871aa0SVince Bridgers 
28932d871aa0SVince Bridgers 	priv->oldlink = 0;
28942d871aa0SVince Bridgers 	priv->speed = 0;
28952d871aa0SVince Bridgers 	priv->oldduplex = -1;
28967ac6653aSJeff Kirsher 	return 0;
28977ac6653aSJeff Kirsher }
28987ac6653aSJeff Kirsher 
2899bfab27a1SGiuseppe CAVALLARO int stmmac_resume(struct net_device *ndev)
29007ac6653aSJeff Kirsher {
29017ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2902f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
29037ac6653aSJeff Kirsher 
29047ac6653aSJeff Kirsher 	if (!netif_running(ndev))
29057ac6653aSJeff Kirsher 		return 0;
29067ac6653aSJeff Kirsher 
2907f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
29087ac6653aSJeff Kirsher 
29097ac6653aSJeff Kirsher 	/* Power Down bit, into the PM register, is cleared
29107ac6653aSJeff Kirsher 	 * automatically as soon as a magic packet or a Wake-up frame
29117ac6653aSJeff Kirsher 	 * is received. Anyway, it's better to manually clear
29127ac6653aSJeff Kirsher 	 * this bit because it can generate problems while resuming
2913ceb69499SGiuseppe CAVALLARO 	 * from another devices (e.g. serial console).
2914ceb69499SGiuseppe CAVALLARO 	 */
2915623997fbSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
29167ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, 0);
291789f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 0;
2918623997fbSSrinivas Kandagatla 	} else {
2919db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_default_state(priv->device);
2920ba1377ffSGiuseppe CAVALLARO 		/* enable the clk prevously disabled */
2921a630844dSStefan Roese 		clk_prepare_enable(priv->stmmac_clk);
2922623997fbSSrinivas Kandagatla 		/* reset the phy so that it's ready */
2923623997fbSSrinivas Kandagatla 		if (priv->mii)
2924623997fbSSrinivas Kandagatla 			stmmac_mdio_reset(priv->mii);
2925623997fbSSrinivas Kandagatla 	}
29267ac6653aSJeff Kirsher 
29277ac6653aSJeff Kirsher 	netif_device_attach(ndev);
29287ac6653aSJeff Kirsher 
2929623997fbSSrinivas Kandagatla 	stmmac_hw_setup(ndev);
29307ac6653aSJeff Kirsher 
29317ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
29327ac6653aSJeff Kirsher 
29337ac6653aSJeff Kirsher 	netif_start_queue(ndev);
29347ac6653aSJeff Kirsher 
2935f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
2936102463b1SFrancesco Virlinzi 
2937102463b1SFrancesco Virlinzi 	if (priv->phydev)
2938102463b1SFrancesco Virlinzi 		phy_start(priv->phydev);
2939102463b1SFrancesco Virlinzi 
29407ac6653aSJeff Kirsher 	return 0;
29417ac6653aSJeff Kirsher }
29427ac6653aSJeff Kirsher #endif /* CONFIG_PM */
29437ac6653aSJeff Kirsher 
294433d5e332SGiuseppe CAVALLARO /* Driver can be configured w/ and w/ both PCI and Platf drivers
294533d5e332SGiuseppe CAVALLARO  * depending on the configuration selected.
294633d5e332SGiuseppe CAVALLARO  */
2947ba27ec66SGiuseppe CAVALLARO static int __init stmmac_init(void)
2948ba27ec66SGiuseppe CAVALLARO {
2949493682b8SKonstantin Khlebnikov 	int ret;
2950ba27ec66SGiuseppe CAVALLARO 
2951493682b8SKonstantin Khlebnikov 	ret = stmmac_register_platform();
2952493682b8SKonstantin Khlebnikov 	if (ret)
2953493682b8SKonstantin Khlebnikov 		goto err;
2954493682b8SKonstantin Khlebnikov 	ret = stmmac_register_pci();
2955493682b8SKonstantin Khlebnikov 	if (ret)
2956493682b8SKonstantin Khlebnikov 		goto err_pci;
295733d5e332SGiuseppe CAVALLARO 	return 0;
2958493682b8SKonstantin Khlebnikov err_pci:
2959493682b8SKonstantin Khlebnikov 	stmmac_unregister_platform();
2960493682b8SKonstantin Khlebnikov err:
2961493682b8SKonstantin Khlebnikov 	pr_err("stmmac: driver registration failed\n");
2962493682b8SKonstantin Khlebnikov 	return ret;
2963ba27ec66SGiuseppe CAVALLARO }
2964ba27ec66SGiuseppe CAVALLARO 
2965ba27ec66SGiuseppe CAVALLARO static void __exit stmmac_exit(void)
2966ba27ec66SGiuseppe CAVALLARO {
296733d5e332SGiuseppe CAVALLARO 	stmmac_unregister_platform();
296833d5e332SGiuseppe CAVALLARO 	stmmac_unregister_pci();
2969ba27ec66SGiuseppe CAVALLARO }
2970ba27ec66SGiuseppe CAVALLARO 
2971ba27ec66SGiuseppe CAVALLARO module_init(stmmac_init);
2972ba27ec66SGiuseppe CAVALLARO module_exit(stmmac_exit);
2973ba27ec66SGiuseppe CAVALLARO 
29747ac6653aSJeff Kirsher #ifndef MODULE
29757ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str)
29767ac6653aSJeff Kirsher {
29777ac6653aSJeff Kirsher 	char *opt;
29787ac6653aSJeff Kirsher 
29797ac6653aSJeff Kirsher 	if (!str || !*str)
29807ac6653aSJeff Kirsher 		return -EINVAL;
29817ac6653aSJeff Kirsher 	while ((opt = strsep(&str, ",")) != NULL) {
29827ac6653aSJeff Kirsher 		if (!strncmp(opt, "debug:", 6)) {
2983ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &debug))
29847ac6653aSJeff Kirsher 				goto err;
29857ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "phyaddr:", 8)) {
2986ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 8, 0, &phyaddr))
29877ac6653aSJeff Kirsher 				goto err;
29887ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_txsize:", 11)) {
2989ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_txsize))
29907ac6653aSJeff Kirsher 				goto err;
29917ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_rxsize:", 11)) {
2992ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_rxsize))
29937ac6653aSJeff Kirsher 				goto err;
29947ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "buf_sz:", 7)) {
2995ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 7, 0, &buf_sz))
29967ac6653aSJeff Kirsher 				goto err;
29977ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "tc:", 3)) {
2998ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 3, 0, &tc))
29997ac6653aSJeff Kirsher 				goto err;
30007ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "watchdog:", 9)) {
3001ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 9, 0, &watchdog))
30027ac6653aSJeff Kirsher 				goto err;
30037ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "flow_ctrl:", 10)) {
3004ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &flow_ctrl))
30057ac6653aSJeff Kirsher 				goto err;
30067ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "pause:", 6)) {
3007ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &pause))
30087ac6653aSJeff Kirsher 				goto err;
3009506f669cSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "eee_timer:", 10)) {
3010d765955dSGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &eee_timer))
3011d765955dSGiuseppe CAVALLARO 				goto err;
30124a7d666aSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "chain_mode:", 11)) {
30134a7d666aSGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &chain_mode))
30144a7d666aSGiuseppe CAVALLARO 				goto err;
30157ac6653aSJeff Kirsher 		}
30167ac6653aSJeff Kirsher 	}
30177ac6653aSJeff Kirsher 	return 0;
30187ac6653aSJeff Kirsher 
30197ac6653aSJeff Kirsher err:
30207ac6653aSJeff Kirsher 	pr_err("%s: ERROR broken module parameter conversion", __func__);
30217ac6653aSJeff Kirsher 	return -EINVAL;
30227ac6653aSJeff Kirsher }
30237ac6653aSJeff Kirsher 
30247ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt);
3025ceb69499SGiuseppe CAVALLARO #endif /* MODULE */
30266fc0d0f2SGiuseppe Cavallaro 
30276fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
30286fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
30296fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL");
3030