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 
952618abb7SVince Bridgers #define DMA_BUFFER_SIZE	BUF_SIZE_4KiB
967ac6653aSJeff Kirsher static int buf_sz = DMA_BUFFER_SIZE;
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;
1397ac6653aSJeff Kirsher 	if (unlikely((buf_sz < DMA_BUFFER_SIZE) || (buf_sz > BUF_SIZE_16KiB)))
1407ac6653aSJeff Kirsher 		buf_sz = DMA_BUFFER_SIZE;
1417ac6653aSJeff Kirsher 	if (unlikely(flow_ctrl > 1))
1427ac6653aSJeff Kirsher 		flow_ctrl = FLOW_AUTO;
1437ac6653aSJeff Kirsher 	else if (likely(flow_ctrl < 0))
1447ac6653aSJeff Kirsher 		flow_ctrl = FLOW_OFF;
1457ac6653aSJeff Kirsher 	if (unlikely((pause < 0) || (pause > 0xffff)))
1467ac6653aSJeff Kirsher 		pause = PAUSE_TIME;
147d765955dSGiuseppe CAVALLARO 	if (eee_timer < 0)
148d765955dSGiuseppe CAVALLARO 		eee_timer = STMMAC_DEFAULT_LPI_TIMER;
1497ac6653aSJeff Kirsher }
1507ac6653aSJeff Kirsher 
15132ceabcaSGiuseppe CAVALLARO /**
15232ceabcaSGiuseppe CAVALLARO  * stmmac_clk_csr_set - dynamically set the MDC clock
15332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
15432ceabcaSGiuseppe CAVALLARO  * Description: this is to dynamically set the MDC clock according to the csr
15532ceabcaSGiuseppe CAVALLARO  * clock input.
15632ceabcaSGiuseppe CAVALLARO  * Note:
15732ceabcaSGiuseppe CAVALLARO  *	If a specific clk_csr value is passed from the platform
15832ceabcaSGiuseppe CAVALLARO  *	this means that the CSR Clock Range selection cannot be
15932ceabcaSGiuseppe CAVALLARO  *	changed at run-time and it is fixed (as reported in the driver
16032ceabcaSGiuseppe CAVALLARO  *	documentation). Viceversa the driver will try to set the MDC
16132ceabcaSGiuseppe CAVALLARO  *	clock dynamically according to the actual clock input.
16232ceabcaSGiuseppe CAVALLARO  */
163cd7201f4SGiuseppe CAVALLARO static void stmmac_clk_csr_set(struct stmmac_priv *priv)
164cd7201f4SGiuseppe CAVALLARO {
165cd7201f4SGiuseppe CAVALLARO 	u32 clk_rate;
166cd7201f4SGiuseppe CAVALLARO 
167cd7201f4SGiuseppe CAVALLARO 	clk_rate = clk_get_rate(priv->stmmac_clk);
168cd7201f4SGiuseppe CAVALLARO 
169cd7201f4SGiuseppe CAVALLARO 	/* Platform provided default clk_csr would be assumed valid
170ceb69499SGiuseppe CAVALLARO 	 * for all other cases except for the below mentioned ones.
171ceb69499SGiuseppe CAVALLARO 	 * For values higher than the IEEE 802.3 specified frequency
172ceb69499SGiuseppe CAVALLARO 	 * we can not estimate the proper divider as it is not known
173ceb69499SGiuseppe CAVALLARO 	 * the frequency of clk_csr_i. So we do not change the default
174ceb69499SGiuseppe CAVALLARO 	 * divider.
175ceb69499SGiuseppe CAVALLARO 	 */
176cd7201f4SGiuseppe CAVALLARO 	if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) {
177cd7201f4SGiuseppe CAVALLARO 		if (clk_rate < CSR_F_35M)
178cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_20_35M;
179cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M))
180cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_35_60M;
181cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M))
182cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_60_100M;
183cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M))
184cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_100_150M;
185cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
186cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_150_250M;
187cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
188cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_250_300M;
189ceb69499SGiuseppe CAVALLARO 	}
190cd7201f4SGiuseppe CAVALLARO }
191cd7201f4SGiuseppe CAVALLARO 
1927ac6653aSJeff Kirsher static void print_pkt(unsigned char *buf, int len)
1937ac6653aSJeff Kirsher {
1947ac6653aSJeff Kirsher 	int j;
19583d7af64SGiuseppe CAVALLARO 	pr_debug("len = %d byte, buf addr: 0x%p", len, buf);
1967ac6653aSJeff Kirsher 	for (j = 0; j < len; j++) {
1977ac6653aSJeff Kirsher 		if ((j % 16) == 0)
19883d7af64SGiuseppe CAVALLARO 			pr_debug("\n %03x:", j);
19983d7af64SGiuseppe CAVALLARO 		pr_debug(" %02x", buf[j]);
2007ac6653aSJeff Kirsher 	}
20183d7af64SGiuseppe CAVALLARO 	pr_debug("\n");
2027ac6653aSJeff Kirsher }
2037ac6653aSJeff Kirsher 
2047ac6653aSJeff Kirsher /* minimum number of free TX descriptors required to wake up TX process */
2057ac6653aSJeff Kirsher #define STMMAC_TX_THRESH(x)	(x->dma_tx_size/4)
2067ac6653aSJeff Kirsher 
2077ac6653aSJeff Kirsher static inline u32 stmmac_tx_avail(struct stmmac_priv *priv)
2087ac6653aSJeff Kirsher {
2097ac6653aSJeff Kirsher 	return priv->dirty_tx + priv->dma_tx_size - priv->cur_tx - 1;
2107ac6653aSJeff Kirsher }
2117ac6653aSJeff Kirsher 
21232ceabcaSGiuseppe CAVALLARO /**
21332ceabcaSGiuseppe CAVALLARO  * stmmac_hw_fix_mac_speed: callback for speed selection
21432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
21532ceabcaSGiuseppe CAVALLARO  * Description: on some platforms (e.g. ST), some HW system configuraton
21632ceabcaSGiuseppe CAVALLARO  * registers have to be set according to the link speed negotiated.
2177ac6653aSJeff Kirsher  */
2187ac6653aSJeff Kirsher static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
2197ac6653aSJeff Kirsher {
2207ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
2217ac6653aSJeff Kirsher 
2227ac6653aSJeff Kirsher 	if (likely(priv->plat->fix_mac_speed))
223ceb69499SGiuseppe CAVALLARO 		priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
2247ac6653aSJeff Kirsher }
2257ac6653aSJeff Kirsher 
22632ceabcaSGiuseppe CAVALLARO /**
22732ceabcaSGiuseppe CAVALLARO  * stmmac_enable_eee_mode: Check and enter in LPI mode
22832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
22932ceabcaSGiuseppe CAVALLARO  * Description: this function is to verify and enter in LPI mode for EEE.
23032ceabcaSGiuseppe CAVALLARO  */
231d765955dSGiuseppe CAVALLARO static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
232d765955dSGiuseppe CAVALLARO {
233d765955dSGiuseppe CAVALLARO 	/* Check and enter in LPI mode */
234d765955dSGiuseppe CAVALLARO 	if ((priv->dirty_tx == priv->cur_tx) &&
235d765955dSGiuseppe CAVALLARO 	    (priv->tx_path_in_lpi_mode == false))
236d765955dSGiuseppe CAVALLARO 		priv->hw->mac->set_eee_mode(priv->ioaddr);
237d765955dSGiuseppe CAVALLARO }
238d765955dSGiuseppe CAVALLARO 
23932ceabcaSGiuseppe CAVALLARO /**
24032ceabcaSGiuseppe CAVALLARO  * stmmac_disable_eee_mode: disable/exit from EEE
24132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
24232ceabcaSGiuseppe CAVALLARO  * Description: this function is to exit and disable EEE in case of
24332ceabcaSGiuseppe CAVALLARO  * LPI state is true. This is called by the xmit.
24432ceabcaSGiuseppe CAVALLARO  */
245d765955dSGiuseppe CAVALLARO void stmmac_disable_eee_mode(struct stmmac_priv *priv)
246d765955dSGiuseppe CAVALLARO {
247d765955dSGiuseppe CAVALLARO 	priv->hw->mac->reset_eee_mode(priv->ioaddr);
248d765955dSGiuseppe CAVALLARO 	del_timer_sync(&priv->eee_ctrl_timer);
249d765955dSGiuseppe CAVALLARO 	priv->tx_path_in_lpi_mode = false;
250d765955dSGiuseppe CAVALLARO }
251d765955dSGiuseppe CAVALLARO 
252d765955dSGiuseppe CAVALLARO /**
25332ceabcaSGiuseppe CAVALLARO  * stmmac_eee_ctrl_timer: EEE TX SW timer.
254d765955dSGiuseppe CAVALLARO  * @arg : data hook
255d765955dSGiuseppe CAVALLARO  * Description:
25632ceabcaSGiuseppe CAVALLARO  *  if there is no data transfer and if we are not in LPI state,
257d765955dSGiuseppe CAVALLARO  *  then MAC Transmitter can be moved to LPI state.
258d765955dSGiuseppe CAVALLARO  */
259d765955dSGiuseppe CAVALLARO static void stmmac_eee_ctrl_timer(unsigned long arg)
260d765955dSGiuseppe CAVALLARO {
261d765955dSGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)arg;
262d765955dSGiuseppe CAVALLARO 
263d765955dSGiuseppe CAVALLARO 	stmmac_enable_eee_mode(priv);
264f5351ef7SGiuseppe CAVALLARO 	mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
265d765955dSGiuseppe CAVALLARO }
266d765955dSGiuseppe CAVALLARO 
267d765955dSGiuseppe CAVALLARO /**
26832ceabcaSGiuseppe CAVALLARO  * stmmac_eee_init: init EEE
26932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
270d765955dSGiuseppe CAVALLARO  * Description:
271d765955dSGiuseppe CAVALLARO  *  If the EEE support has been enabled while configuring the driver,
272d765955dSGiuseppe CAVALLARO  *  if the GMAC actually supports the EEE (from the HW cap reg) and the
273d765955dSGiuseppe CAVALLARO  *  phy can also manage EEE, so enable the LPI state and start the timer
274d765955dSGiuseppe CAVALLARO  *  to verify if the tx path can enter in LPI state.
275d765955dSGiuseppe CAVALLARO  */
276d765955dSGiuseppe CAVALLARO bool stmmac_eee_init(struct stmmac_priv *priv)
277d765955dSGiuseppe CAVALLARO {
278d765955dSGiuseppe CAVALLARO 	bool ret = false;
279d765955dSGiuseppe CAVALLARO 
280f5351ef7SGiuseppe CAVALLARO 	/* Using PCS we cannot dial with the phy registers at this stage
281f5351ef7SGiuseppe CAVALLARO 	 * so we do not support extra feature like EEE.
282f5351ef7SGiuseppe CAVALLARO 	 */
283f5351ef7SGiuseppe CAVALLARO 	if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) ||
284f5351ef7SGiuseppe CAVALLARO 	    (priv->pcs == STMMAC_PCS_RTBI))
285f5351ef7SGiuseppe CAVALLARO 		goto out;
286f5351ef7SGiuseppe CAVALLARO 
287d765955dSGiuseppe CAVALLARO 	/* MAC core supports the EEE feature. */
288d765955dSGiuseppe CAVALLARO 	if (priv->dma_cap.eee) {
289d765955dSGiuseppe CAVALLARO 		/* Check if the PHY supports EEE */
290d765955dSGiuseppe CAVALLARO 		if (phy_init_eee(priv->phydev, 1))
291d765955dSGiuseppe CAVALLARO 			goto out;
292d765955dSGiuseppe CAVALLARO 
293f5351ef7SGiuseppe CAVALLARO 		if (!priv->eee_active) {
294d765955dSGiuseppe CAVALLARO 			priv->eee_active = 1;
295d765955dSGiuseppe CAVALLARO 			init_timer(&priv->eee_ctrl_timer);
296d765955dSGiuseppe CAVALLARO 			priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer;
297d765955dSGiuseppe CAVALLARO 			priv->eee_ctrl_timer.data = (unsigned long)priv;
298f5351ef7SGiuseppe CAVALLARO 			priv->eee_ctrl_timer.expires = STMMAC_LPI_T(eee_timer);
299d765955dSGiuseppe CAVALLARO 			add_timer(&priv->eee_ctrl_timer);
300d765955dSGiuseppe CAVALLARO 
301d765955dSGiuseppe CAVALLARO 			priv->hw->mac->set_eee_timer(priv->ioaddr,
302f5351ef7SGiuseppe CAVALLARO 						     STMMAC_DEFAULT_LIT_LS,
303d765955dSGiuseppe CAVALLARO 						     priv->tx_lpi_timer);
304f5351ef7SGiuseppe CAVALLARO 		} else
305f5351ef7SGiuseppe CAVALLARO 			/* Set HW EEE according to the speed */
306f5351ef7SGiuseppe CAVALLARO 			priv->hw->mac->set_eee_pls(priv->ioaddr,
307f5351ef7SGiuseppe CAVALLARO 						   priv->phydev->link);
308d765955dSGiuseppe CAVALLARO 
309d765955dSGiuseppe CAVALLARO 		pr_info("stmmac: Energy-Efficient Ethernet initialized\n");
310d765955dSGiuseppe CAVALLARO 
311d765955dSGiuseppe CAVALLARO 		ret = true;
312d765955dSGiuseppe CAVALLARO 	}
313d765955dSGiuseppe CAVALLARO out:
314d765955dSGiuseppe CAVALLARO 	return ret;
315d765955dSGiuseppe CAVALLARO }
316d765955dSGiuseppe CAVALLARO 
31732ceabcaSGiuseppe CAVALLARO /* stmmac_get_tx_hwtstamp: get HW TX timestamps
31832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
319891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
320891434b1SRayagond Kokatanur  * @skb : the socket buffer
321891434b1SRayagond Kokatanur  * Description :
322891434b1SRayagond Kokatanur  * This function will read timestamp from the descriptor & pass it to stack.
323891434b1SRayagond Kokatanur  * and also perform some sanity checks.
324891434b1SRayagond Kokatanur  */
325891434b1SRayagond Kokatanur static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
326ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
327891434b1SRayagond Kokatanur {
328891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps shhwtstamp;
329891434b1SRayagond Kokatanur 	u64 ns;
330891434b1SRayagond Kokatanur 	void *desc = NULL;
331891434b1SRayagond Kokatanur 
332891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
333891434b1SRayagond Kokatanur 		return;
334891434b1SRayagond Kokatanur 
335ceb69499SGiuseppe CAVALLARO 	/* exit if skb doesn't support hw tstamp */
33675e4364fSdamuzi000 	if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
337891434b1SRayagond Kokatanur 		return;
338891434b1SRayagond Kokatanur 
339891434b1SRayagond Kokatanur 	if (priv->adv_ts)
340891434b1SRayagond Kokatanur 		desc = (priv->dma_etx + entry);
341891434b1SRayagond Kokatanur 	else
342891434b1SRayagond Kokatanur 		desc = (priv->dma_tx + entry);
343891434b1SRayagond Kokatanur 
344891434b1SRayagond Kokatanur 	/* check tx tstamp status */
345891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_tx_timestamp_status((struct dma_desc *)desc))
346891434b1SRayagond Kokatanur 		return;
347891434b1SRayagond Kokatanur 
348891434b1SRayagond Kokatanur 	/* get the valid tstamp */
349891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
350891434b1SRayagond Kokatanur 
351891434b1SRayagond Kokatanur 	memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
352891434b1SRayagond Kokatanur 	shhwtstamp.hwtstamp = ns_to_ktime(ns);
353891434b1SRayagond Kokatanur 	/* pass tstamp to stack */
354891434b1SRayagond Kokatanur 	skb_tstamp_tx(skb, &shhwtstamp);
355891434b1SRayagond Kokatanur 
356891434b1SRayagond Kokatanur 	return;
357891434b1SRayagond Kokatanur }
358891434b1SRayagond Kokatanur 
35932ceabcaSGiuseppe CAVALLARO /* stmmac_get_rx_hwtstamp: get HW RX timestamps
36032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
361891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
362891434b1SRayagond Kokatanur  * @skb : the socket buffer
363891434b1SRayagond Kokatanur  * Description :
364891434b1SRayagond Kokatanur  * This function will read received packet's timestamp from the descriptor
365891434b1SRayagond Kokatanur  * and pass it to stack. It also perform some sanity checks.
366891434b1SRayagond Kokatanur  */
367891434b1SRayagond Kokatanur static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv,
368ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
369891434b1SRayagond Kokatanur {
370891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps *shhwtstamp = NULL;
371891434b1SRayagond Kokatanur 	u64 ns;
372891434b1SRayagond Kokatanur 	void *desc = NULL;
373891434b1SRayagond Kokatanur 
374891434b1SRayagond Kokatanur 	if (!priv->hwts_rx_en)
375891434b1SRayagond Kokatanur 		return;
376891434b1SRayagond Kokatanur 
377891434b1SRayagond Kokatanur 	if (priv->adv_ts)
378891434b1SRayagond Kokatanur 		desc = (priv->dma_erx + entry);
379891434b1SRayagond Kokatanur 	else
380891434b1SRayagond Kokatanur 		desc = (priv->dma_rx + entry);
381891434b1SRayagond Kokatanur 
382ceb69499SGiuseppe CAVALLARO 	/* exit if rx tstamp is not valid */
383891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts))
384891434b1SRayagond Kokatanur 		return;
385891434b1SRayagond Kokatanur 
386891434b1SRayagond Kokatanur 	/* get valid tstamp */
387891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
388891434b1SRayagond Kokatanur 	shhwtstamp = skb_hwtstamps(skb);
389891434b1SRayagond Kokatanur 	memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
390891434b1SRayagond Kokatanur 	shhwtstamp->hwtstamp = ns_to_ktime(ns);
391891434b1SRayagond Kokatanur }
392891434b1SRayagond Kokatanur 
393891434b1SRayagond Kokatanur /**
394891434b1SRayagond Kokatanur  *  stmmac_hwtstamp_ioctl - control hardware timestamping.
395891434b1SRayagond Kokatanur  *  @dev: device pointer.
396891434b1SRayagond Kokatanur  *  @ifr: An IOCTL specefic structure, that can contain a pointer to
397891434b1SRayagond Kokatanur  *  a proprietary structure used to pass information to the driver.
398891434b1SRayagond Kokatanur  *  Description:
399891434b1SRayagond Kokatanur  *  This function configures the MAC to enable/disable both outgoing(TX)
400891434b1SRayagond Kokatanur  *  and incoming(RX) packets time stamping based on user input.
401891434b1SRayagond Kokatanur  *  Return Value:
402891434b1SRayagond Kokatanur  *  0 on success and an appropriate -ve integer on failure.
403891434b1SRayagond Kokatanur  */
404891434b1SRayagond Kokatanur static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
405891434b1SRayagond Kokatanur {
406891434b1SRayagond Kokatanur 	struct stmmac_priv *priv = netdev_priv(dev);
407891434b1SRayagond Kokatanur 	struct hwtstamp_config config;
408891434b1SRayagond Kokatanur 	struct timespec now;
409891434b1SRayagond Kokatanur 	u64 temp = 0;
410891434b1SRayagond Kokatanur 	u32 ptp_v2 = 0;
411891434b1SRayagond Kokatanur 	u32 tstamp_all = 0;
412891434b1SRayagond Kokatanur 	u32 ptp_over_ipv4_udp = 0;
413891434b1SRayagond Kokatanur 	u32 ptp_over_ipv6_udp = 0;
414891434b1SRayagond Kokatanur 	u32 ptp_over_ethernet = 0;
415891434b1SRayagond Kokatanur 	u32 snap_type_sel = 0;
416891434b1SRayagond Kokatanur 	u32 ts_master_en = 0;
417891434b1SRayagond Kokatanur 	u32 ts_event_en = 0;
418891434b1SRayagond Kokatanur 	u32 value = 0;
419891434b1SRayagond Kokatanur 
420891434b1SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
421891434b1SRayagond Kokatanur 		netdev_alert(priv->dev, "No support for HW time stamping\n");
422891434b1SRayagond Kokatanur 		priv->hwts_tx_en = 0;
423891434b1SRayagond Kokatanur 		priv->hwts_rx_en = 0;
424891434b1SRayagond Kokatanur 
425891434b1SRayagond Kokatanur 		return -EOPNOTSUPP;
426891434b1SRayagond Kokatanur 	}
427891434b1SRayagond Kokatanur 
428891434b1SRayagond Kokatanur 	if (copy_from_user(&config, ifr->ifr_data,
429891434b1SRayagond Kokatanur 			   sizeof(struct hwtstamp_config)))
430891434b1SRayagond Kokatanur 		return -EFAULT;
431891434b1SRayagond Kokatanur 
432891434b1SRayagond Kokatanur 	pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
433891434b1SRayagond Kokatanur 		 __func__, config.flags, config.tx_type, config.rx_filter);
434891434b1SRayagond Kokatanur 
435891434b1SRayagond Kokatanur 	/* reserved for future extensions */
436891434b1SRayagond Kokatanur 	if (config.flags)
437891434b1SRayagond Kokatanur 		return -EINVAL;
438891434b1SRayagond Kokatanur 
4395f3da328SBen Hutchings 	if (config.tx_type != HWTSTAMP_TX_OFF &&
4405f3da328SBen Hutchings 	    config.tx_type != HWTSTAMP_TX_ON)
441891434b1SRayagond Kokatanur 		return -ERANGE;
442891434b1SRayagond Kokatanur 
443891434b1SRayagond Kokatanur 	if (priv->adv_ts) {
444891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
445891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
446ceb69499SGiuseppe CAVALLARO 			/* time stamp no incoming packet at all */
447891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
448891434b1SRayagond Kokatanur 			break;
449891434b1SRayagond Kokatanur 
450891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
451ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, any kind of event packet */
452891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
453891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
454891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
455891434b1SRayagond Kokatanur 
456891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
457891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
458891434b1SRayagond Kokatanur 			break;
459891434b1SRayagond Kokatanur 
460891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
461ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Sync packet */
462891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
463891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
464891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
465891434b1SRayagond Kokatanur 
466891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
467891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
468891434b1SRayagond Kokatanur 			break;
469891434b1SRayagond Kokatanur 
470891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
471ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Delay_req packet */
472891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
473891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
474891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
475891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
476891434b1SRayagond Kokatanur 
477891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
478891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
479891434b1SRayagond Kokatanur 			break;
480891434b1SRayagond Kokatanur 
481891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
482ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, any kind of event packet */
483891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
484891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
485891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
486891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
487891434b1SRayagond Kokatanur 
488891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
489891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
490891434b1SRayagond Kokatanur 			break;
491891434b1SRayagond Kokatanur 
492891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
493ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Sync packet */
494891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
495891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
496891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
497891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
498891434b1SRayagond Kokatanur 
499891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
500891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
501891434b1SRayagond Kokatanur 			break;
502891434b1SRayagond Kokatanur 
503891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
504ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Delay_req packet */
505891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
506891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
507891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
508891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
509891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
510891434b1SRayagond Kokatanur 
511891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
512891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
513891434b1SRayagond Kokatanur 			break;
514891434b1SRayagond Kokatanur 
515891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_EVENT:
516ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1 any layer, any kind of event packet */
517891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
518891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
519891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
520891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
521891434b1SRayagond Kokatanur 
522891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
523891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
524891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
525891434b1SRayagond Kokatanur 			break;
526891434b1SRayagond Kokatanur 
527891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_SYNC:
528ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Sync packet */
529891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
530891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
531891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
532891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
533891434b1SRayagond Kokatanur 
534891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
535891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
536891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
537891434b1SRayagond Kokatanur 			break;
538891434b1SRayagond Kokatanur 
539891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
540ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Delay_req packet */
541891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
542891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
543891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
544891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
545891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
546891434b1SRayagond Kokatanur 
547891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
548891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
549891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
550891434b1SRayagond Kokatanur 			break;
551891434b1SRayagond Kokatanur 
552891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_ALL:
553ceb69499SGiuseppe CAVALLARO 			/* time stamp any incoming packet */
554891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_ALL;
555891434b1SRayagond Kokatanur 			tstamp_all = PTP_TCR_TSENALL;
556891434b1SRayagond Kokatanur 			break;
557891434b1SRayagond Kokatanur 
558891434b1SRayagond Kokatanur 		default:
559891434b1SRayagond Kokatanur 			return -ERANGE;
560891434b1SRayagond Kokatanur 		}
561891434b1SRayagond Kokatanur 	} else {
562891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
563891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
564891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
565891434b1SRayagond Kokatanur 			break;
566891434b1SRayagond Kokatanur 		default:
567891434b1SRayagond Kokatanur 			/* PTP v1, UDP, any kind of event packet */
568891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
569891434b1SRayagond Kokatanur 			break;
570891434b1SRayagond Kokatanur 		}
571891434b1SRayagond Kokatanur 	}
572891434b1SRayagond Kokatanur 	priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1);
5735f3da328SBen Hutchings 	priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON;
574891434b1SRayagond Kokatanur 
575891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en && !priv->hwts_rx_en)
576891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0);
577891434b1SRayagond Kokatanur 	else {
578891434b1SRayagond Kokatanur 		value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
579891434b1SRayagond Kokatanur 			 tstamp_all | ptp_v2 | ptp_over_ethernet |
580891434b1SRayagond Kokatanur 			 ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
581891434b1SRayagond Kokatanur 			 ts_master_en | snap_type_sel);
582891434b1SRayagond Kokatanur 
583891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
584891434b1SRayagond Kokatanur 
585891434b1SRayagond Kokatanur 		/* program Sub Second Increment reg */
586891434b1SRayagond Kokatanur 		priv->hw->ptp->config_sub_second_increment(priv->ioaddr);
587891434b1SRayagond Kokatanur 
588891434b1SRayagond Kokatanur 		/* calculate default added value:
589891434b1SRayagond Kokatanur 		 * formula is :
590891434b1SRayagond Kokatanur 		 * addend = (2^32)/freq_div_ratio;
591891434b1SRayagond Kokatanur 		 * where, freq_div_ratio = STMMAC_SYSCLOCK/50MHz
592891434b1SRayagond Kokatanur 		 * hence, addend = ((2^32) * 50MHz)/STMMAC_SYSCLOCK;
593891434b1SRayagond Kokatanur 		 * NOTE: STMMAC_SYSCLOCK should be >= 50MHz to
594891434b1SRayagond Kokatanur 		 *       achive 20ns accuracy.
595891434b1SRayagond Kokatanur 		 *
596891434b1SRayagond Kokatanur 		 * 2^x * y == (y << x), hence
597891434b1SRayagond Kokatanur 		 * 2^32 * 50000000 ==> (50000000 << 32)
598891434b1SRayagond Kokatanur 		 */
599891434b1SRayagond Kokatanur 		temp = (u64) (50000000ULL << 32);
600891434b1SRayagond Kokatanur 		priv->default_addend = div_u64(temp, STMMAC_SYSCLOCK);
601891434b1SRayagond Kokatanur 		priv->hw->ptp->config_addend(priv->ioaddr,
602891434b1SRayagond Kokatanur 					     priv->default_addend);
603891434b1SRayagond Kokatanur 
604891434b1SRayagond Kokatanur 		/* initialize system time */
605891434b1SRayagond Kokatanur 		getnstimeofday(&now);
606891434b1SRayagond Kokatanur 		priv->hw->ptp->init_systime(priv->ioaddr, now.tv_sec,
607891434b1SRayagond Kokatanur 					    now.tv_nsec);
608891434b1SRayagond Kokatanur 	}
609891434b1SRayagond Kokatanur 
610891434b1SRayagond Kokatanur 	return copy_to_user(ifr->ifr_data, &config,
611891434b1SRayagond Kokatanur 			    sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
612891434b1SRayagond Kokatanur }
613891434b1SRayagond Kokatanur 
61432ceabcaSGiuseppe CAVALLARO /**
61532ceabcaSGiuseppe CAVALLARO  * stmmac_init_ptp: init PTP
61632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
61732ceabcaSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PTPv1 or v2.
61832ceabcaSGiuseppe CAVALLARO  * This is done by looking at the HW cap. register.
61932ceabcaSGiuseppe CAVALLARO  * Also it registers the ptp driver.
62032ceabcaSGiuseppe CAVALLARO  */
62192ba6888SRayagond Kokatanur static int stmmac_init_ptp(struct stmmac_priv *priv)
622891434b1SRayagond Kokatanur {
62392ba6888SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
62492ba6888SRayagond Kokatanur 		return -EOPNOTSUPP;
62592ba6888SRayagond Kokatanur 
626891434b1SRayagond Kokatanur 	priv->adv_ts = 0;
6277cd01399SVince Bridgers 	if (priv->dma_cap.atime_stamp && priv->extend_desc)
628891434b1SRayagond Kokatanur 		priv->adv_ts = 1;
6297cd01399SVince Bridgers 
6307cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
6317cd01399SVince Bridgers 		pr_debug("IEEE 1588-2002 Time Stamp supported\n");
6327cd01399SVince Bridgers 
6337cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->adv_ts)
6347cd01399SVince Bridgers 		pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
635891434b1SRayagond Kokatanur 
636891434b1SRayagond Kokatanur 	priv->hw->ptp = &stmmac_ptp;
637891434b1SRayagond Kokatanur 	priv->hwts_tx_en = 0;
638891434b1SRayagond Kokatanur 	priv->hwts_rx_en = 0;
63992ba6888SRayagond Kokatanur 
64092ba6888SRayagond Kokatanur 	return stmmac_ptp_register(priv);
64192ba6888SRayagond Kokatanur }
64292ba6888SRayagond Kokatanur 
64392ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv)
64492ba6888SRayagond Kokatanur {
64592ba6888SRayagond Kokatanur 	stmmac_ptp_unregister(priv);
646891434b1SRayagond Kokatanur }
647891434b1SRayagond Kokatanur 
6487ac6653aSJeff Kirsher /**
6497ac6653aSJeff Kirsher  * stmmac_adjust_link
6507ac6653aSJeff Kirsher  * @dev: net device structure
6517ac6653aSJeff Kirsher  * Description: it adjusts the link parameters.
6527ac6653aSJeff Kirsher  */
6537ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev)
6547ac6653aSJeff Kirsher {
6557ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
6567ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
6577ac6653aSJeff Kirsher 	unsigned long flags;
6587ac6653aSJeff Kirsher 	int new_state = 0;
6597ac6653aSJeff Kirsher 	unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
6607ac6653aSJeff Kirsher 
6617ac6653aSJeff Kirsher 	if (phydev == NULL)
6627ac6653aSJeff Kirsher 		return;
6637ac6653aSJeff Kirsher 
6647ac6653aSJeff Kirsher 	spin_lock_irqsave(&priv->lock, flags);
665d765955dSGiuseppe CAVALLARO 
6667ac6653aSJeff Kirsher 	if (phydev->link) {
6677ac6653aSJeff Kirsher 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
6687ac6653aSJeff Kirsher 
6697ac6653aSJeff Kirsher 		/* Now we make sure that we can be in full duplex mode.
6707ac6653aSJeff Kirsher 		 * If not, we operate in half-duplex mode. */
6717ac6653aSJeff Kirsher 		if (phydev->duplex != priv->oldduplex) {
6727ac6653aSJeff Kirsher 			new_state = 1;
6737ac6653aSJeff Kirsher 			if (!(phydev->duplex))
6747ac6653aSJeff Kirsher 				ctrl &= ~priv->hw->link.duplex;
6757ac6653aSJeff Kirsher 			else
6767ac6653aSJeff Kirsher 				ctrl |= priv->hw->link.duplex;
6777ac6653aSJeff Kirsher 			priv->oldduplex = phydev->duplex;
6787ac6653aSJeff Kirsher 		}
6797ac6653aSJeff Kirsher 		/* Flow Control operation */
6807ac6653aSJeff Kirsher 		if (phydev->pause)
6817ac6653aSJeff Kirsher 			priv->hw->mac->flow_ctrl(priv->ioaddr, phydev->duplex,
6827ac6653aSJeff Kirsher 						 fc, pause_time);
6837ac6653aSJeff Kirsher 
6847ac6653aSJeff Kirsher 		if (phydev->speed != priv->speed) {
6857ac6653aSJeff Kirsher 			new_state = 1;
6867ac6653aSJeff Kirsher 			switch (phydev->speed) {
6877ac6653aSJeff Kirsher 			case 1000:
6887ac6653aSJeff Kirsher 				if (likely(priv->plat->has_gmac))
6897ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
6907ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
6917ac6653aSJeff Kirsher 				break;
6927ac6653aSJeff Kirsher 			case 100:
6937ac6653aSJeff Kirsher 			case 10:
6947ac6653aSJeff Kirsher 				if (priv->plat->has_gmac) {
6957ac6653aSJeff Kirsher 					ctrl |= priv->hw->link.port;
6967ac6653aSJeff Kirsher 					if (phydev->speed == SPEED_100) {
6977ac6653aSJeff Kirsher 						ctrl |= priv->hw->link.speed;
6987ac6653aSJeff Kirsher 					} else {
6997ac6653aSJeff Kirsher 						ctrl &= ~(priv->hw->link.speed);
7007ac6653aSJeff Kirsher 					}
7017ac6653aSJeff Kirsher 				} else {
7027ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7037ac6653aSJeff Kirsher 				}
7047ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7057ac6653aSJeff Kirsher 				break;
7067ac6653aSJeff Kirsher 			default:
7077ac6653aSJeff Kirsher 				if (netif_msg_link(priv))
708ceb69499SGiuseppe CAVALLARO 					pr_warn("%s: Speed (%d) not 10/100\n",
709ceb69499SGiuseppe CAVALLARO 						dev->name, phydev->speed);
7107ac6653aSJeff Kirsher 				break;
7117ac6653aSJeff Kirsher 			}
7127ac6653aSJeff Kirsher 
7137ac6653aSJeff Kirsher 			priv->speed = phydev->speed;
7147ac6653aSJeff Kirsher 		}
7157ac6653aSJeff Kirsher 
7167ac6653aSJeff Kirsher 		writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
7177ac6653aSJeff Kirsher 
7187ac6653aSJeff Kirsher 		if (!priv->oldlink) {
7197ac6653aSJeff Kirsher 			new_state = 1;
7207ac6653aSJeff Kirsher 			priv->oldlink = 1;
7217ac6653aSJeff Kirsher 		}
7227ac6653aSJeff Kirsher 	} else if (priv->oldlink) {
7237ac6653aSJeff Kirsher 		new_state = 1;
7247ac6653aSJeff Kirsher 		priv->oldlink = 0;
7257ac6653aSJeff Kirsher 		priv->speed = 0;
7267ac6653aSJeff Kirsher 		priv->oldduplex = -1;
7277ac6653aSJeff Kirsher 	}
7287ac6653aSJeff Kirsher 
7297ac6653aSJeff Kirsher 	if (new_state && netif_msg_link(priv))
7307ac6653aSJeff Kirsher 		phy_print_status(phydev);
7317ac6653aSJeff Kirsher 
732f5351ef7SGiuseppe CAVALLARO 	/* At this stage, it could be needed to setup the EEE or adjust some
733f5351ef7SGiuseppe CAVALLARO 	 * MAC related HW registers.
734f5351ef7SGiuseppe CAVALLARO 	 */
735f5351ef7SGiuseppe CAVALLARO 	priv->eee_enabled = stmmac_eee_init(priv);
736d765955dSGiuseppe CAVALLARO 
7377ac6653aSJeff Kirsher 	spin_unlock_irqrestore(&priv->lock, flags);
7387ac6653aSJeff Kirsher }
7397ac6653aSJeff Kirsher 
74032ceabcaSGiuseppe CAVALLARO /**
74132ceabcaSGiuseppe CAVALLARO  * stmmac_check_pcs_mode: verify if RGMII/SGMII is supported
74232ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
74332ceabcaSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PCS.
74432ceabcaSGiuseppe CAVALLARO  * Physical Coding Sublayer (PCS) interface that can be used when the MAC is
74532ceabcaSGiuseppe CAVALLARO  * configured for the TBI, RTBI, or SGMII PHY interface.
74632ceabcaSGiuseppe CAVALLARO  */
747e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
748e58bb43fSGiuseppe CAVALLARO {
749e58bb43fSGiuseppe CAVALLARO 	int interface = priv->plat->interface;
750e58bb43fSGiuseppe CAVALLARO 
751e58bb43fSGiuseppe CAVALLARO 	if (priv->dma_cap.pcs) {
7520d909dcdSByungho An 		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
7530d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
7540d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
7550d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
756e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS RGMII support enable\n");
757e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_RGMII;
7580d909dcdSByungho An 		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
759e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS SGMII support enable\n");
760e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_SGMII;
761e58bb43fSGiuseppe CAVALLARO 		}
762e58bb43fSGiuseppe CAVALLARO 	}
763e58bb43fSGiuseppe CAVALLARO }
764e58bb43fSGiuseppe CAVALLARO 
7657ac6653aSJeff Kirsher /**
7667ac6653aSJeff Kirsher  * stmmac_init_phy - PHY initialization
7677ac6653aSJeff Kirsher  * @dev: net device structure
7687ac6653aSJeff Kirsher  * Description: it initializes the driver's PHY state, and attaches the PHY
7697ac6653aSJeff Kirsher  * to the mac driver.
7707ac6653aSJeff Kirsher  *  Return value:
7717ac6653aSJeff Kirsher  *  0 on success
7727ac6653aSJeff Kirsher  */
7737ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev)
7747ac6653aSJeff Kirsher {
7757ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
7767ac6653aSJeff Kirsher 	struct phy_device *phydev;
777d765955dSGiuseppe CAVALLARO 	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
7787ac6653aSJeff Kirsher 	char bus_id[MII_BUS_ID_SIZE];
77979ee1dc3SSrinivas Kandagatla 	int interface = priv->plat->interface;
7809cbadf09SSrinivas Kandagatla 	int max_speed = priv->plat->max_speed;
7817ac6653aSJeff Kirsher 	priv->oldlink = 0;
7827ac6653aSJeff Kirsher 	priv->speed = 0;
7837ac6653aSJeff Kirsher 	priv->oldduplex = -1;
7847ac6653aSJeff Kirsher 
785f142af2eSSrinivas Kandagatla 	if (priv->plat->phy_bus_name)
786f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
787f142af2eSSrinivas Kandagatla 			 priv->plat->phy_bus_name, priv->plat->bus_id);
788f142af2eSSrinivas Kandagatla 	else
789f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
790f142af2eSSrinivas Kandagatla 			 priv->plat->bus_id);
791f142af2eSSrinivas Kandagatla 
792d765955dSGiuseppe CAVALLARO 	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
7937ac6653aSJeff Kirsher 		 priv->plat->phy_addr);
794d765955dSGiuseppe CAVALLARO 	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
7957ac6653aSJeff Kirsher 
796f9a8f83bSFlorian Fainelli 	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
7977ac6653aSJeff Kirsher 
7987ac6653aSJeff Kirsher 	if (IS_ERR(phydev)) {
7997ac6653aSJeff Kirsher 		pr_err("%s: Could not attach to PHY\n", dev->name);
8007ac6653aSJeff Kirsher 		return PTR_ERR(phydev);
8017ac6653aSJeff Kirsher 	}
8027ac6653aSJeff Kirsher 
80379ee1dc3SSrinivas Kandagatla 	/* Stop Advertising 1000BASE Capability if interface is not GMII */
804c5b9b4e4SSrinivas Kandagatla 	if ((interface == PHY_INTERFACE_MODE_MII) ||
8059cbadf09SSrinivas Kandagatla 	    (interface == PHY_INTERFACE_MODE_RMII) ||
8069cbadf09SSrinivas Kandagatla 		(max_speed < 1000 &&  max_speed > 0))
807c5b9b4e4SSrinivas Kandagatla 		phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
808c5b9b4e4SSrinivas Kandagatla 					 SUPPORTED_1000baseT_Full);
80979ee1dc3SSrinivas Kandagatla 
8107ac6653aSJeff Kirsher 	/*
8117ac6653aSJeff Kirsher 	 * Broken HW is sometimes missing the pull-up resistor on the
8127ac6653aSJeff Kirsher 	 * MDIO line, which results in reads to non-existent devices returning
8137ac6653aSJeff Kirsher 	 * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
8147ac6653aSJeff Kirsher 	 * device as well.
8157ac6653aSJeff Kirsher 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
8167ac6653aSJeff Kirsher 	 */
8177ac6653aSJeff Kirsher 	if (phydev->phy_id == 0) {
8187ac6653aSJeff Kirsher 		phy_disconnect(phydev);
8197ac6653aSJeff Kirsher 		return -ENODEV;
8207ac6653aSJeff Kirsher 	}
8217ac6653aSJeff Kirsher 	pr_debug("stmmac_init_phy:  %s: attached to PHY (UID 0x%x)"
8227ac6653aSJeff Kirsher 		 " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
8237ac6653aSJeff Kirsher 
8247ac6653aSJeff Kirsher 	priv->phydev = phydev;
8257ac6653aSJeff Kirsher 
8267ac6653aSJeff Kirsher 	return 0;
8277ac6653aSJeff Kirsher }
8287ac6653aSJeff Kirsher 
8297ac6653aSJeff Kirsher /**
83032ceabcaSGiuseppe CAVALLARO  * stmmac_display_ring: display ring
83132ceabcaSGiuseppe CAVALLARO  * @head: pointer to the head of the ring passed.
8327ac6653aSJeff Kirsher  * @size: size of the ring.
83332ceabcaSGiuseppe CAVALLARO  * @extend_desc: to verify if extended descriptors are used.
834c24602efSGiuseppe CAVALLARO  * Description: display the control/status and buffer descriptors.
8357ac6653aSJeff Kirsher  */
836c24602efSGiuseppe CAVALLARO static void stmmac_display_ring(void *head, int size, int extend_desc)
8377ac6653aSJeff Kirsher {
8387ac6653aSJeff Kirsher 	int i;
839c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
840c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
841c24602efSGiuseppe CAVALLARO 
8427ac6653aSJeff Kirsher 	for (i = 0; i < size; i++) {
843c24602efSGiuseppe CAVALLARO 		u64 x;
844c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
845c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
846c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
847c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(ep),
848c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
849c24602efSGiuseppe CAVALLARO 				ep->basic.des2, ep->basic.des3);
850c24602efSGiuseppe CAVALLARO 			ep++;
851c24602efSGiuseppe CAVALLARO 		} else {
852c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
853c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x",
854c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(p),
855c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
856c24602efSGiuseppe CAVALLARO 				p->des2, p->des3);
857c24602efSGiuseppe CAVALLARO 			p++;
858c24602efSGiuseppe CAVALLARO 		}
8597ac6653aSJeff Kirsher 		pr_info("\n");
8607ac6653aSJeff Kirsher 	}
8617ac6653aSJeff Kirsher }
8627ac6653aSJeff Kirsher 
863c24602efSGiuseppe CAVALLARO static void stmmac_display_rings(struct stmmac_priv *priv)
864c24602efSGiuseppe CAVALLARO {
865c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
866c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
867c24602efSGiuseppe CAVALLARO 
868c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
869c24602efSGiuseppe CAVALLARO 		pr_info("Extended RX descriptor ring:\n");
870c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
871c24602efSGiuseppe CAVALLARO 		pr_info("Extended TX descriptor ring:\n");
872c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
873c24602efSGiuseppe CAVALLARO 	} else {
874c24602efSGiuseppe CAVALLARO 		pr_info("RX descriptor ring:\n");
875c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
876c24602efSGiuseppe CAVALLARO 		pr_info("TX descriptor ring:\n");
877c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
878c24602efSGiuseppe CAVALLARO 	}
879c24602efSGiuseppe CAVALLARO }
880c24602efSGiuseppe CAVALLARO 
881286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize)
882286a8372SGiuseppe CAVALLARO {
883286a8372SGiuseppe CAVALLARO 	int ret = bufsize;
884286a8372SGiuseppe CAVALLARO 
885286a8372SGiuseppe CAVALLARO 	if (mtu >= BUF_SIZE_4KiB)
886286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_8KiB;
887286a8372SGiuseppe CAVALLARO 	else if (mtu >= BUF_SIZE_2KiB)
888286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_4KiB;
889286a8372SGiuseppe CAVALLARO 	else if (mtu >= DMA_BUFFER_SIZE)
890286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_2KiB;
891286a8372SGiuseppe CAVALLARO 	else
892286a8372SGiuseppe CAVALLARO 		ret = DMA_BUFFER_SIZE;
893286a8372SGiuseppe CAVALLARO 
894286a8372SGiuseppe CAVALLARO 	return ret;
895286a8372SGiuseppe CAVALLARO }
896286a8372SGiuseppe CAVALLARO 
89732ceabcaSGiuseppe CAVALLARO /**
89832ceabcaSGiuseppe CAVALLARO  * stmmac_clear_descriptors: clear descriptors
89932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
90032ceabcaSGiuseppe CAVALLARO  * Description: this function is called to clear the tx and rx descriptors
90132ceabcaSGiuseppe CAVALLARO  * in case of both basic and extended descriptors are used.
90232ceabcaSGiuseppe CAVALLARO  */
903c24602efSGiuseppe CAVALLARO static void stmmac_clear_descriptors(struct stmmac_priv *priv)
904c24602efSGiuseppe CAVALLARO {
905c24602efSGiuseppe CAVALLARO 	int i;
906c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
907c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
908c24602efSGiuseppe CAVALLARO 
909c24602efSGiuseppe CAVALLARO 	/* Clear the Rx/Tx descriptors */
910c24602efSGiuseppe CAVALLARO 	for (i = 0; i < rxsize; i++)
911c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
912c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
913c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
914c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
915c24602efSGiuseppe CAVALLARO 		else
916c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_rx[i],
917c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
918c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
919c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
920c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
921c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
922c24602efSGiuseppe CAVALLARO 						     priv->mode,
923c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
924c24602efSGiuseppe CAVALLARO 		else
925c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
926c24602efSGiuseppe CAVALLARO 						     priv->mode,
927c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
928c24602efSGiuseppe CAVALLARO }
929c24602efSGiuseppe CAVALLARO 
930c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
931c24602efSGiuseppe CAVALLARO 				  int i)
932c24602efSGiuseppe CAVALLARO {
933c24602efSGiuseppe CAVALLARO 	struct sk_buff *skb;
934c24602efSGiuseppe CAVALLARO 
935c24602efSGiuseppe CAVALLARO 	skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
936c24602efSGiuseppe CAVALLARO 				 GFP_KERNEL);
93756329137SBartlomiej Zolnierkiewicz 	if (!skb) {
938c24602efSGiuseppe CAVALLARO 		pr_err("%s: Rx init fails; skb is NULL\n", __func__);
93956329137SBartlomiej Zolnierkiewicz 		return -ENOMEM;
940c24602efSGiuseppe CAVALLARO 	}
941c24602efSGiuseppe CAVALLARO 	skb_reserve(skb, NET_IP_ALIGN);
942c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff[i] = skb;
943c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
944c24602efSGiuseppe CAVALLARO 						priv->dma_buf_sz,
945c24602efSGiuseppe CAVALLARO 						DMA_FROM_DEVICE);
94656329137SBartlomiej Zolnierkiewicz 	if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) {
94756329137SBartlomiej Zolnierkiewicz 		pr_err("%s: DMA mapping error\n", __func__);
94856329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(skb);
94956329137SBartlomiej Zolnierkiewicz 		return -EINVAL;
95056329137SBartlomiej Zolnierkiewicz 	}
951c24602efSGiuseppe CAVALLARO 
952c24602efSGiuseppe CAVALLARO 	p->des2 = priv->rx_skbuff_dma[i];
953c24602efSGiuseppe CAVALLARO 
954c24602efSGiuseppe CAVALLARO 	if ((priv->mode == STMMAC_RING_MODE) &&
955c24602efSGiuseppe CAVALLARO 	    (priv->dma_buf_sz == BUF_SIZE_16KiB))
956c24602efSGiuseppe CAVALLARO 		priv->hw->ring->init_desc3(p);
957c24602efSGiuseppe CAVALLARO 
958c24602efSGiuseppe CAVALLARO 	return 0;
959c24602efSGiuseppe CAVALLARO }
960c24602efSGiuseppe CAVALLARO 
96156329137SBartlomiej Zolnierkiewicz static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i)
96256329137SBartlomiej Zolnierkiewicz {
96356329137SBartlomiej Zolnierkiewicz 	if (priv->rx_skbuff[i]) {
96456329137SBartlomiej Zolnierkiewicz 		dma_unmap_single(priv->device, priv->rx_skbuff_dma[i],
96556329137SBartlomiej Zolnierkiewicz 				 priv->dma_buf_sz, DMA_FROM_DEVICE);
96656329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(priv->rx_skbuff[i]);
96756329137SBartlomiej Zolnierkiewicz 	}
96856329137SBartlomiej Zolnierkiewicz 	priv->rx_skbuff[i] = NULL;
96956329137SBartlomiej Zolnierkiewicz }
97056329137SBartlomiej Zolnierkiewicz 
9717ac6653aSJeff Kirsher /**
9727ac6653aSJeff Kirsher  * init_dma_desc_rings - init the RX/TX descriptor rings
9737ac6653aSJeff Kirsher  * @dev: net device structure
9747ac6653aSJeff Kirsher  * Description:  this function initializes the DMA RX/TX descriptors
975286a8372SGiuseppe CAVALLARO  * and allocates the socket buffers. It suppors the chained and ring
976286a8372SGiuseppe CAVALLARO  * modes.
9777ac6653aSJeff Kirsher  */
97856329137SBartlomiej Zolnierkiewicz static int init_dma_desc_rings(struct net_device *dev)
9797ac6653aSJeff Kirsher {
9807ac6653aSJeff Kirsher 	int i;
9817ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
9827ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
9837ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
9844a7d666aSGiuseppe CAVALLARO 	unsigned int bfsize = 0;
98556329137SBartlomiej Zolnierkiewicz 	int ret = -ENOMEM;
9867ac6653aSJeff Kirsher 
987286a8372SGiuseppe CAVALLARO 	/* Set the max buffer size according to the DESC mode
988ceb69499SGiuseppe CAVALLARO 	 * and the MTU. Note that RING mode allows 16KiB bsize.
989ceb69499SGiuseppe CAVALLARO 	 */
9904a7d666aSGiuseppe CAVALLARO 	if (priv->mode == STMMAC_RING_MODE)
991286a8372SGiuseppe CAVALLARO 		bfsize = priv->hw->ring->set_16kib_bfsize(dev->mtu);
992286a8372SGiuseppe CAVALLARO 
9934a7d666aSGiuseppe CAVALLARO 	if (bfsize < BUF_SIZE_16KiB)
994286a8372SGiuseppe CAVALLARO 		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
9957ac6653aSJeff Kirsher 
9962618abb7SVince Bridgers 	priv->dma_buf_sz = bfsize;
9972618abb7SVince Bridgers 
99883d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv))
99983d7af64SGiuseppe CAVALLARO 		pr_debug("%s: txsize %d, rxsize %d, bfsize %d\n", __func__,
10007ac6653aSJeff Kirsher 			 txsize, rxsize, bfsize);
10017ac6653aSJeff Kirsher 
100283d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv)) {
1003c24602efSGiuseppe CAVALLARO 		pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
1004c24602efSGiuseppe CAVALLARO 			 (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
10057ac6653aSJeff Kirsher 
10067ac6653aSJeff Kirsher 		/* RX INITIALIZATION */
100783d7af64SGiuseppe CAVALLARO 		pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n");
100883d7af64SGiuseppe CAVALLARO 	}
10097ac6653aSJeff Kirsher 	for (i = 0; i < rxsize; i++) {
1010c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1011c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1012c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_erx + i)->basic);
1013c24602efSGiuseppe CAVALLARO 		else
1014c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + i;
10157ac6653aSJeff Kirsher 
101656329137SBartlomiej Zolnierkiewicz 		ret = stmmac_init_rx_buffers(priv, p, i);
101756329137SBartlomiej Zolnierkiewicz 		if (ret)
101856329137SBartlomiej Zolnierkiewicz 			goto err_init_rx_buffers;
1019286a8372SGiuseppe CAVALLARO 
102083d7af64SGiuseppe CAVALLARO 		if (netif_msg_probe(priv))
102183d7af64SGiuseppe CAVALLARO 			pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
102283d7af64SGiuseppe CAVALLARO 				 priv->rx_skbuff[i]->data,
102383d7af64SGiuseppe CAVALLARO 				 (unsigned int)priv->rx_skbuff_dma[i]);
10247ac6653aSJeff Kirsher 	}
10257ac6653aSJeff Kirsher 	priv->cur_rx = 0;
10267ac6653aSJeff Kirsher 	priv->dirty_rx = (unsigned int)(i - rxsize);
10277ac6653aSJeff Kirsher 	buf_sz = bfsize;
10287ac6653aSJeff Kirsher 
1029c24602efSGiuseppe CAVALLARO 	/* Setup the chained descriptor addresses */
1030c24602efSGiuseppe CAVALLARO 	if (priv->mode == STMMAC_CHAIN_MODE) {
1031c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc) {
1032c24602efSGiuseppe CAVALLARO 			priv->hw->chain->init(priv->dma_erx, priv->dma_rx_phy,
1033c24602efSGiuseppe CAVALLARO 					      rxsize, 1);
1034c24602efSGiuseppe CAVALLARO 			priv->hw->chain->init(priv->dma_etx, priv->dma_tx_phy,
1035c24602efSGiuseppe CAVALLARO 					      txsize, 1);
1036c24602efSGiuseppe CAVALLARO 		} else {
1037c24602efSGiuseppe CAVALLARO 			priv->hw->chain->init(priv->dma_rx, priv->dma_rx_phy,
1038c24602efSGiuseppe CAVALLARO 					      rxsize, 0);
1039c24602efSGiuseppe CAVALLARO 			priv->hw->chain->init(priv->dma_tx, priv->dma_tx_phy,
1040c24602efSGiuseppe CAVALLARO 					      txsize, 0);
1041c24602efSGiuseppe CAVALLARO 		}
10427ac6653aSJeff Kirsher 	}
1043286a8372SGiuseppe CAVALLARO 
1044c24602efSGiuseppe CAVALLARO 	/* TX INITIALIZATION */
1045c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++) {
1046c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1047c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1048c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1049c24602efSGiuseppe CAVALLARO 		else
1050c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1051c24602efSGiuseppe CAVALLARO 		p->des2 = 0;
1052cf32deecSRayagond Kokatanur 		priv->tx_skbuff_dma[i] = 0;
1053c24602efSGiuseppe CAVALLARO 		priv->tx_skbuff[i] = NULL;
10544a7d666aSGiuseppe CAVALLARO 	}
1055c24602efSGiuseppe CAVALLARO 
10567ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
10577ac6653aSJeff Kirsher 	priv->cur_tx = 0;
10587ac6653aSJeff Kirsher 
1059c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
10607ac6653aSJeff Kirsher 
1061c24602efSGiuseppe CAVALLARO 	if (netif_msg_hw(priv))
1062c24602efSGiuseppe CAVALLARO 		stmmac_display_rings(priv);
106356329137SBartlomiej Zolnierkiewicz 
106456329137SBartlomiej Zolnierkiewicz 	return 0;
106556329137SBartlomiej Zolnierkiewicz err_init_rx_buffers:
106656329137SBartlomiej Zolnierkiewicz 	while (--i >= 0)
106756329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
106856329137SBartlomiej Zolnierkiewicz 	return ret;
10697ac6653aSJeff Kirsher }
10707ac6653aSJeff Kirsher 
10717ac6653aSJeff Kirsher static void dma_free_rx_skbufs(struct stmmac_priv *priv)
10727ac6653aSJeff Kirsher {
10737ac6653aSJeff Kirsher 	int i;
10747ac6653aSJeff Kirsher 
107556329137SBartlomiej Zolnierkiewicz 	for (i = 0; i < priv->dma_rx_size; i++)
107656329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
10777ac6653aSJeff Kirsher }
10787ac6653aSJeff Kirsher 
10797ac6653aSJeff Kirsher static void dma_free_tx_skbufs(struct stmmac_priv *priv)
10807ac6653aSJeff Kirsher {
10817ac6653aSJeff Kirsher 	int i;
10827ac6653aSJeff Kirsher 
10837ac6653aSJeff Kirsher 	for (i = 0; i < priv->dma_tx_size; i++) {
1084c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
108575e4364fSdamuzi000 
1086c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1087c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1088c24602efSGiuseppe CAVALLARO 		else
1089c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1090c24602efSGiuseppe CAVALLARO 
109175e4364fSdamuzi000 		if (priv->tx_skbuff_dma[i]) {
1092cf32deecSRayagond Kokatanur 			dma_unmap_single(priv->device,
1093cf32deecSRayagond Kokatanur 					 priv->tx_skbuff_dma[i],
10947ac6653aSJeff Kirsher 					 priv->hw->desc->get_tx_len(p),
10957ac6653aSJeff Kirsher 					 DMA_TO_DEVICE);
109675e4364fSdamuzi000 			priv->tx_skbuff_dma[i] = 0;
109775e4364fSdamuzi000 		}
109875e4364fSdamuzi000 
109975e4364fSdamuzi000 		if (priv->tx_skbuff[i] != NULL) {
11007ac6653aSJeff Kirsher 			dev_kfree_skb_any(priv->tx_skbuff[i]);
11017ac6653aSJeff Kirsher 			priv->tx_skbuff[i] = NULL;
11027ac6653aSJeff Kirsher 		}
11037ac6653aSJeff Kirsher 	}
11047ac6653aSJeff Kirsher }
11057ac6653aSJeff Kirsher 
110609f8d696SSrinivas Kandagatla static int alloc_dma_desc_resources(struct stmmac_priv *priv)
110709f8d696SSrinivas Kandagatla {
110809f8d696SSrinivas Kandagatla 	unsigned int txsize = priv->dma_tx_size;
110909f8d696SSrinivas Kandagatla 	unsigned int rxsize = priv->dma_rx_size;
111009f8d696SSrinivas Kandagatla 	int ret = -ENOMEM;
111109f8d696SSrinivas Kandagatla 
111209f8d696SSrinivas Kandagatla 	priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
111309f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
111409f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff_dma)
111509f8d696SSrinivas Kandagatla 		return -ENOMEM;
111609f8d696SSrinivas Kandagatla 
111709f8d696SSrinivas Kandagatla 	priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
111809f8d696SSrinivas Kandagatla 					GFP_KERNEL);
111909f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff)
112009f8d696SSrinivas Kandagatla 		goto err_rx_skbuff;
112109f8d696SSrinivas Kandagatla 
112209f8d696SSrinivas Kandagatla 	priv->tx_skbuff_dma = kmalloc_array(txsize, sizeof(dma_addr_t),
112309f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
112409f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff_dma)
112509f8d696SSrinivas Kandagatla 		goto err_tx_skbuff_dma;
112609f8d696SSrinivas Kandagatla 
112709f8d696SSrinivas Kandagatla 	priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
112809f8d696SSrinivas Kandagatla 					GFP_KERNEL);
112909f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff)
113009f8d696SSrinivas Kandagatla 		goto err_tx_skbuff;
113109f8d696SSrinivas Kandagatla 
113209f8d696SSrinivas Kandagatla 	if (priv->extend_desc) {
113309f8d696SSrinivas Kandagatla 		priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
113409f8d696SSrinivas Kandagatla 						   sizeof(struct
113509f8d696SSrinivas Kandagatla 							  dma_extended_desc),
113609f8d696SSrinivas Kandagatla 						   &priv->dma_rx_phy,
113709f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
113809f8d696SSrinivas Kandagatla 		if (!priv->dma_erx)
113909f8d696SSrinivas Kandagatla 			goto err_dma;
114009f8d696SSrinivas Kandagatla 
114109f8d696SSrinivas Kandagatla 		priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
114209f8d696SSrinivas Kandagatla 						   sizeof(struct
114309f8d696SSrinivas Kandagatla 							  dma_extended_desc),
114409f8d696SSrinivas Kandagatla 						   &priv->dma_tx_phy,
114509f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
114609f8d696SSrinivas Kandagatla 		if (!priv->dma_etx) {
114709f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
114809f8d696SSrinivas Kandagatla 					sizeof(struct dma_extended_desc),
114909f8d696SSrinivas Kandagatla 					priv->dma_erx, priv->dma_rx_phy);
115009f8d696SSrinivas Kandagatla 			goto err_dma;
115109f8d696SSrinivas Kandagatla 		}
115209f8d696SSrinivas Kandagatla 	} else {
115309f8d696SSrinivas Kandagatla 		priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
115409f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
115509f8d696SSrinivas Kandagatla 						  &priv->dma_rx_phy,
115609f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
115709f8d696SSrinivas Kandagatla 		if (!priv->dma_rx)
115809f8d696SSrinivas Kandagatla 			goto err_dma;
115909f8d696SSrinivas Kandagatla 
116009f8d696SSrinivas Kandagatla 		priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
116109f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
116209f8d696SSrinivas Kandagatla 						  &priv->dma_tx_phy,
116309f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
116409f8d696SSrinivas Kandagatla 		if (!priv->dma_tx) {
116509f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
116609f8d696SSrinivas Kandagatla 					sizeof(struct dma_desc),
116709f8d696SSrinivas Kandagatla 					priv->dma_rx, priv->dma_rx_phy);
116809f8d696SSrinivas Kandagatla 			goto err_dma;
116909f8d696SSrinivas Kandagatla 		}
117009f8d696SSrinivas Kandagatla 	}
117109f8d696SSrinivas Kandagatla 
117209f8d696SSrinivas Kandagatla 	return 0;
117309f8d696SSrinivas Kandagatla 
117409f8d696SSrinivas Kandagatla err_dma:
117509f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff);
117609f8d696SSrinivas Kandagatla err_tx_skbuff:
117709f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff_dma);
117809f8d696SSrinivas Kandagatla err_tx_skbuff_dma:
117909f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff);
118009f8d696SSrinivas Kandagatla err_rx_skbuff:
118109f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff_dma);
118209f8d696SSrinivas Kandagatla 	return ret;
118309f8d696SSrinivas Kandagatla }
118409f8d696SSrinivas Kandagatla 
11857ac6653aSJeff Kirsher static void free_dma_desc_resources(struct stmmac_priv *priv)
11867ac6653aSJeff Kirsher {
11877ac6653aSJeff Kirsher 	/* Release the DMA TX/RX socket buffers */
11887ac6653aSJeff Kirsher 	dma_free_rx_skbufs(priv);
11897ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
11907ac6653aSJeff Kirsher 
1191ceb69499SGiuseppe CAVALLARO 	/* Free DMA regions of consistent memory previously allocated */
1192c24602efSGiuseppe CAVALLARO 	if (!priv->extend_desc) {
11937ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
11947ac6653aSJeff Kirsher 				  priv->dma_tx_size * sizeof(struct dma_desc),
11957ac6653aSJeff Kirsher 				  priv->dma_tx, priv->dma_tx_phy);
11967ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
11977ac6653aSJeff Kirsher 				  priv->dma_rx_size * sizeof(struct dma_desc),
11987ac6653aSJeff Kirsher 				  priv->dma_rx, priv->dma_rx_phy);
1199c24602efSGiuseppe CAVALLARO 	} else {
1200c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_tx_size *
1201c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1202c24602efSGiuseppe CAVALLARO 				  priv->dma_etx, priv->dma_tx_phy);
1203c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_rx_size *
1204c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1205c24602efSGiuseppe CAVALLARO 				  priv->dma_erx, priv->dma_rx_phy);
1206c24602efSGiuseppe CAVALLARO 	}
12077ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff_dma);
12087ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff);
1209cf32deecSRayagond Kokatanur 	kfree(priv->tx_skbuff_dma);
12107ac6653aSJeff Kirsher 	kfree(priv->tx_skbuff);
12117ac6653aSJeff Kirsher }
12127ac6653aSJeff Kirsher 
12137ac6653aSJeff Kirsher /**
12147ac6653aSJeff Kirsher  *  stmmac_dma_operation_mode - HW DMA operation mode
121532ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
12167ac6653aSJeff Kirsher  *  Description: it sets the DMA operation mode: tx/rx DMA thresholds
12177ac6653aSJeff Kirsher  *  or Store-And-Forward capability.
12187ac6653aSJeff Kirsher  */
12197ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
12207ac6653aSJeff Kirsher {
1221e2a240c7SSonic Zhang 	if (priv->plat->force_thresh_dma_mode)
1222e2a240c7SSonic Zhang 		priv->hw->dma->dma_mode(priv->ioaddr, tc, tc);
1223e2a240c7SSonic Zhang 	else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
12247ac6653aSJeff Kirsher 		/*
12257ac6653aSJeff Kirsher 		 * In case of GMAC, SF mode can be enabled
12267ac6653aSJeff Kirsher 		 * to perform the TX COE in HW. This depends on:
12277ac6653aSJeff Kirsher 		 * 1) TX COE if actually supported
12287ac6653aSJeff Kirsher 		 * 2) There is no bugged Jumbo frame support
12297ac6653aSJeff Kirsher 		 *    that needs to not insert csum in the TDES.
12307ac6653aSJeff Kirsher 		 */
1231ceb69499SGiuseppe CAVALLARO 		priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE);
12327ac6653aSJeff Kirsher 		tc = SF_DMA_MODE;
12337ac6653aSJeff Kirsher 	} else
12347ac6653aSJeff Kirsher 		priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
12357ac6653aSJeff Kirsher }
12367ac6653aSJeff Kirsher 
12377ac6653aSJeff Kirsher /**
12389125cdd1SGiuseppe CAVALLARO  * stmmac_tx_clean:
123932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
12407ac6653aSJeff Kirsher  * Description: it reclaims resources after transmission completes.
12417ac6653aSJeff Kirsher  */
12429125cdd1SGiuseppe CAVALLARO static void stmmac_tx_clean(struct stmmac_priv *priv)
12437ac6653aSJeff Kirsher {
12447ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
12457ac6653aSJeff Kirsher 
1246a9097a96SGiuseppe CAVALLARO 	spin_lock(&priv->tx_lock);
1247a9097a96SGiuseppe CAVALLARO 
12489125cdd1SGiuseppe CAVALLARO 	priv->xstats.tx_clean++;
12499125cdd1SGiuseppe CAVALLARO 
12507ac6653aSJeff Kirsher 	while (priv->dirty_tx != priv->cur_tx) {
12517ac6653aSJeff Kirsher 		int last;
12527ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_tx % txsize;
12537ac6653aSJeff Kirsher 		struct sk_buff *skb = priv->tx_skbuff[entry];
1254c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1255c24602efSGiuseppe CAVALLARO 
1256c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1257c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_etx + entry);
1258c24602efSGiuseppe CAVALLARO 		else
1259c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + entry;
12607ac6653aSJeff Kirsher 
12617ac6653aSJeff Kirsher 		/* Check if the descriptor is owned by the DMA. */
12627ac6653aSJeff Kirsher 		if (priv->hw->desc->get_tx_owner(p))
12637ac6653aSJeff Kirsher 			break;
12647ac6653aSJeff Kirsher 
1265c24602efSGiuseppe CAVALLARO 		/* Verify tx error by looking at the last segment. */
12667ac6653aSJeff Kirsher 		last = priv->hw->desc->get_tx_ls(p);
12677ac6653aSJeff Kirsher 		if (likely(last)) {
12687ac6653aSJeff Kirsher 			int tx_error =
12697ac6653aSJeff Kirsher 			    priv->hw->desc->tx_status(&priv->dev->stats,
12707ac6653aSJeff Kirsher 						      &priv->xstats, p,
12717ac6653aSJeff Kirsher 						      priv->ioaddr);
12727ac6653aSJeff Kirsher 			if (likely(tx_error == 0)) {
12737ac6653aSJeff Kirsher 				priv->dev->stats.tx_packets++;
12747ac6653aSJeff Kirsher 				priv->xstats.tx_pkt_n++;
12757ac6653aSJeff Kirsher 			} else
12767ac6653aSJeff Kirsher 				priv->dev->stats.tx_errors++;
1277891434b1SRayagond Kokatanur 
1278891434b1SRayagond Kokatanur 			stmmac_get_tx_hwtstamp(priv, entry, skb);
12797ac6653aSJeff Kirsher 		}
128083d7af64SGiuseppe CAVALLARO 		if (netif_msg_tx_done(priv))
128183d7af64SGiuseppe CAVALLARO 			pr_debug("%s: curr %d, dirty %d\n", __func__,
12827ac6653aSJeff Kirsher 				 priv->cur_tx, priv->dirty_tx);
12837ac6653aSJeff Kirsher 
1284cf32deecSRayagond Kokatanur 		if (likely(priv->tx_skbuff_dma[entry])) {
1285cf32deecSRayagond Kokatanur 			dma_unmap_single(priv->device,
1286cf32deecSRayagond Kokatanur 					 priv->tx_skbuff_dma[entry],
12877ac6653aSJeff Kirsher 					 priv->hw->desc->get_tx_len(p),
12887ac6653aSJeff Kirsher 					 DMA_TO_DEVICE);
1289cf32deecSRayagond Kokatanur 			priv->tx_skbuff_dma[entry] = 0;
1290cf32deecSRayagond Kokatanur 		}
1291891434b1SRayagond Kokatanur 		priv->hw->ring->clean_desc3(priv, p);
12927ac6653aSJeff Kirsher 
12937ac6653aSJeff Kirsher 		if (likely(skb != NULL)) {
12947ac6653aSJeff Kirsher 			dev_kfree_skb(skb);
12957ac6653aSJeff Kirsher 			priv->tx_skbuff[entry] = NULL;
12967ac6653aSJeff Kirsher 		}
12977ac6653aSJeff Kirsher 
12984a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->release_tx_desc(p, priv->mode);
12997ac6653aSJeff Kirsher 
130013497f58SGiuseppe CAVALLARO 		priv->dirty_tx++;
13017ac6653aSJeff Kirsher 	}
13027ac6653aSJeff Kirsher 	if (unlikely(netif_queue_stopped(priv->dev) &&
13037ac6653aSJeff Kirsher 		     stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv))) {
13047ac6653aSJeff Kirsher 		netif_tx_lock(priv->dev);
13057ac6653aSJeff Kirsher 		if (netif_queue_stopped(priv->dev) &&
13067ac6653aSJeff Kirsher 		    stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv)) {
130783d7af64SGiuseppe CAVALLARO 			if (netif_msg_tx_done(priv))
130883d7af64SGiuseppe CAVALLARO 				pr_debug("%s: restart transmit\n", __func__);
13097ac6653aSJeff Kirsher 			netif_wake_queue(priv->dev);
13107ac6653aSJeff Kirsher 		}
13117ac6653aSJeff Kirsher 		netif_tx_unlock(priv->dev);
13127ac6653aSJeff Kirsher 	}
1313d765955dSGiuseppe CAVALLARO 
1314d765955dSGiuseppe CAVALLARO 	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
1315d765955dSGiuseppe CAVALLARO 		stmmac_enable_eee_mode(priv);
1316f5351ef7SGiuseppe CAVALLARO 		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
1317d765955dSGiuseppe CAVALLARO 	}
1318a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
13197ac6653aSJeff Kirsher }
13207ac6653aSJeff Kirsher 
13219125cdd1SGiuseppe CAVALLARO static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv)
13227ac6653aSJeff Kirsher {
13237ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_irq(priv->ioaddr);
13247ac6653aSJeff Kirsher }
13257ac6653aSJeff Kirsher 
13269125cdd1SGiuseppe CAVALLARO static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
13277ac6653aSJeff Kirsher {
13287ac6653aSJeff Kirsher 	priv->hw->dma->disable_dma_irq(priv->ioaddr);
13297ac6653aSJeff Kirsher }
13307ac6653aSJeff Kirsher 
13317ac6653aSJeff Kirsher /**
133232ceabcaSGiuseppe CAVALLARO  * stmmac_tx_err: irq tx error mng function
133332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
13347ac6653aSJeff Kirsher  * Description: it cleans the descriptors and restarts the transmission
13357ac6653aSJeff Kirsher  * in case of errors.
13367ac6653aSJeff Kirsher  */
13377ac6653aSJeff Kirsher static void stmmac_tx_err(struct stmmac_priv *priv)
13387ac6653aSJeff Kirsher {
1339c24602efSGiuseppe CAVALLARO 	int i;
1340c24602efSGiuseppe CAVALLARO 	int txsize = priv->dma_tx_size;
13417ac6653aSJeff Kirsher 	netif_stop_queue(priv->dev);
13427ac6653aSJeff Kirsher 
13437ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
13447ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
1345c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
1346c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1347c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
1348c24602efSGiuseppe CAVALLARO 						     priv->mode,
1349c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
1350c24602efSGiuseppe CAVALLARO 		else
1351c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
1352c24602efSGiuseppe CAVALLARO 						     priv->mode,
1353c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
13547ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
13557ac6653aSJeff Kirsher 	priv->cur_tx = 0;
13567ac6653aSJeff Kirsher 	priv->hw->dma->start_tx(priv->ioaddr);
13577ac6653aSJeff Kirsher 
13587ac6653aSJeff Kirsher 	priv->dev->stats.tx_errors++;
13597ac6653aSJeff Kirsher 	netif_wake_queue(priv->dev);
13607ac6653aSJeff Kirsher }
13617ac6653aSJeff Kirsher 
136232ceabcaSGiuseppe CAVALLARO /**
136332ceabcaSGiuseppe CAVALLARO  * stmmac_dma_interrupt: DMA ISR
136432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
136532ceabcaSGiuseppe CAVALLARO  * Description: this is the DMA ISR. It is called by the main ISR.
136632ceabcaSGiuseppe CAVALLARO  * It calls the dwmac dma routine to understand which type of interrupt
136732ceabcaSGiuseppe CAVALLARO  * happened. In case of there is a Normal interrupt and either TX or RX
136832ceabcaSGiuseppe CAVALLARO  * interrupt happened so the NAPI is scheduled.
136932ceabcaSGiuseppe CAVALLARO  */
13707ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv)
13717ac6653aSJeff Kirsher {
13727ac6653aSJeff Kirsher 	int status;
13737ac6653aSJeff Kirsher 
13747ac6653aSJeff Kirsher 	status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
13759125cdd1SGiuseppe CAVALLARO 	if (likely((status & handle_rx)) || (status & handle_tx)) {
13769125cdd1SGiuseppe CAVALLARO 		if (likely(napi_schedule_prep(&priv->napi))) {
13779125cdd1SGiuseppe CAVALLARO 			stmmac_disable_dma_irq(priv);
13789125cdd1SGiuseppe CAVALLARO 			__napi_schedule(&priv->napi);
13799125cdd1SGiuseppe CAVALLARO 		}
13809125cdd1SGiuseppe CAVALLARO 	}
13819125cdd1SGiuseppe CAVALLARO 	if (unlikely(status & tx_hard_error_bump_tc)) {
13827ac6653aSJeff Kirsher 		/* Try to bump up the dma threshold on this failure */
13837ac6653aSJeff Kirsher 		if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
13847ac6653aSJeff Kirsher 			tc += 64;
13857ac6653aSJeff Kirsher 			priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
13867ac6653aSJeff Kirsher 			priv->xstats.threshold = tc;
13877ac6653aSJeff Kirsher 		}
13887ac6653aSJeff Kirsher 	} else if (unlikely(status == tx_hard_error))
13897ac6653aSJeff Kirsher 		stmmac_tx_err(priv);
13907ac6653aSJeff Kirsher }
13917ac6653aSJeff Kirsher 
139232ceabcaSGiuseppe CAVALLARO /**
139332ceabcaSGiuseppe CAVALLARO  * stmmac_mmc_setup: setup the Mac Management Counters (MMC)
139432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
139532ceabcaSGiuseppe CAVALLARO  * Description: this masks the MMC irq, in fact, the counters are managed in SW.
139632ceabcaSGiuseppe CAVALLARO  */
13971c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv)
13981c901a46SGiuseppe CAVALLARO {
13991c901a46SGiuseppe CAVALLARO 	unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
14001c901a46SGiuseppe CAVALLARO 	    MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
14011c901a46SGiuseppe CAVALLARO 
14021c901a46SGiuseppe CAVALLARO 	dwmac_mmc_intr_all_mask(priv->ioaddr);
14034f795b25SGiuseppe CAVALLARO 
14044f795b25SGiuseppe CAVALLARO 	if (priv->dma_cap.rmon) {
14051c901a46SGiuseppe CAVALLARO 		dwmac_mmc_ctrl(priv->ioaddr, mode);
14061c901a46SGiuseppe CAVALLARO 		memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
14074f795b25SGiuseppe CAVALLARO 	} else
1408aae54cffSStefan Roese 		pr_info(" No MAC Management Counters available\n");
14091c901a46SGiuseppe CAVALLARO }
14101c901a46SGiuseppe CAVALLARO 
1411f0b9d786SGiuseppe CAVALLARO static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
1412f0b9d786SGiuseppe CAVALLARO {
1413f0b9d786SGiuseppe CAVALLARO 	u32 hwid = priv->hw->synopsys_uid;
1414f0b9d786SGiuseppe CAVALLARO 
1415ceb69499SGiuseppe CAVALLARO 	/* Check Synopsys Id (not available on old chips) */
1416f0b9d786SGiuseppe CAVALLARO 	if (likely(hwid)) {
1417f0b9d786SGiuseppe CAVALLARO 		u32 uid = ((hwid & 0x0000ff00) >> 8);
1418f0b9d786SGiuseppe CAVALLARO 		u32 synid = (hwid & 0x000000ff);
1419f0b9d786SGiuseppe CAVALLARO 
1420cf3f047bSGiuseppe CAVALLARO 		pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n",
1421f0b9d786SGiuseppe CAVALLARO 			uid, synid);
1422f0b9d786SGiuseppe CAVALLARO 
1423f0b9d786SGiuseppe CAVALLARO 		return synid;
1424f0b9d786SGiuseppe CAVALLARO 	}
1425f0b9d786SGiuseppe CAVALLARO 	return 0;
1426f0b9d786SGiuseppe CAVALLARO }
1427e7434821SGiuseppe CAVALLARO 
142819e30c14SGiuseppe CAVALLARO /**
142932ceabcaSGiuseppe CAVALLARO  * stmmac_selec_desc_mode: to select among: normal/alternate/extend descriptors
143032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
143132ceabcaSGiuseppe CAVALLARO  * Description: select the Enhanced/Alternate or Normal descriptors.
143232ceabcaSGiuseppe CAVALLARO  * In case of Enhanced/Alternate, it looks at the extended descriptors are
143332ceabcaSGiuseppe CAVALLARO  * supported by the HW cap. register.
1434ff3dd78cSGiuseppe CAVALLARO  */
143519e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
143619e30c14SGiuseppe CAVALLARO {
143719e30c14SGiuseppe CAVALLARO 	if (priv->plat->enh_desc) {
143819e30c14SGiuseppe CAVALLARO 		pr_info(" Enhanced/Alternate descriptors\n");
1439c24602efSGiuseppe CAVALLARO 
1440c24602efSGiuseppe CAVALLARO 		/* GMAC older than 3.50 has no extended descriptors */
1441c24602efSGiuseppe CAVALLARO 		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
1442c24602efSGiuseppe CAVALLARO 			pr_info("\tEnabled extended descriptors\n");
1443c24602efSGiuseppe CAVALLARO 			priv->extend_desc = 1;
1444c24602efSGiuseppe CAVALLARO 		} else
1445c24602efSGiuseppe CAVALLARO 			pr_warn("Extended descriptors not supported\n");
1446c24602efSGiuseppe CAVALLARO 
144719e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &enh_desc_ops;
144819e30c14SGiuseppe CAVALLARO 	} else {
144919e30c14SGiuseppe CAVALLARO 		pr_info(" Normal descriptors\n");
145019e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &ndesc_ops;
145119e30c14SGiuseppe CAVALLARO 	}
145219e30c14SGiuseppe CAVALLARO }
145319e30c14SGiuseppe CAVALLARO 
145419e30c14SGiuseppe CAVALLARO /**
145532ceabcaSGiuseppe CAVALLARO  * stmmac_get_hw_features: get MAC capabilities from the HW cap. register.
145632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
145719e30c14SGiuseppe CAVALLARO  * Description:
145819e30c14SGiuseppe CAVALLARO  *  new GMAC chip generations have a new register to indicate the
1459e7434821SGiuseppe CAVALLARO  *  presence of the optional feature/functions.
146019e30c14SGiuseppe CAVALLARO  *  This can be also used to override the value passed through the
146119e30c14SGiuseppe CAVALLARO  *  platform and necessary for old MAC10/100 and GMAC chips.
1462e7434821SGiuseppe CAVALLARO  */
1463e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv)
1464e7434821SGiuseppe CAVALLARO {
14655e6efe88SGiuseppe CAVALLARO 	u32 hw_cap = 0;
14663c20f72fSGiuseppe CAVALLARO 
14675e6efe88SGiuseppe CAVALLARO 	if (priv->hw->dma->get_hw_feature) {
14685e6efe88SGiuseppe CAVALLARO 		hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
1469e7434821SGiuseppe CAVALLARO 
14701db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
14711db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
14721db123fbSRayagond Kokatanur 		priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
14731db123fbSRayagond Kokatanur 		priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
1474ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
14751db123fbSRayagond Kokatanur 		priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
14761db123fbSRayagond Kokatanur 		priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
14771db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_remote_wake_up =
14781db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
14791db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_magic_frame =
14801db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
14811db123fbSRayagond Kokatanur 		/* MMC */
14821db123fbSRayagond Kokatanur 		priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
1483e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2002 */
14841db123fbSRayagond Kokatanur 		priv->dma_cap.time_stamp =
14851db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
1486e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2008 */
14871db123fbSRayagond Kokatanur 		priv->dma_cap.atime_stamp =
14881db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
1489e7434821SGiuseppe CAVALLARO 		/* 802.3az - Energy-Efficient Ethernet (EEE) */
14901db123fbSRayagond Kokatanur 		priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
14911db123fbSRayagond Kokatanur 		priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
1492e7434821SGiuseppe CAVALLARO 		/* TX and RX csum */
14931db123fbSRayagond Kokatanur 		priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
14941db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type1 =
14951db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
14961db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type2 =
14971db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
14981db123fbSRayagond Kokatanur 		priv->dma_cap.rxfifo_over_2048 =
14991db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
1500e7434821SGiuseppe CAVALLARO 		/* TX and RX number of channels */
15011db123fbSRayagond Kokatanur 		priv->dma_cap.number_rx_channel =
15021db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
15031db123fbSRayagond Kokatanur 		priv->dma_cap.number_tx_channel =
15041db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
1505e7434821SGiuseppe CAVALLARO 		/* Alternate (enhanced) DESC mode */
1506ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
150719e30c14SGiuseppe CAVALLARO 	}
1508e7434821SGiuseppe CAVALLARO 
1509e7434821SGiuseppe CAVALLARO 	return hw_cap;
1510e7434821SGiuseppe CAVALLARO }
1511e7434821SGiuseppe CAVALLARO 
151232ceabcaSGiuseppe CAVALLARO /**
151332ceabcaSGiuseppe CAVALLARO  * stmmac_check_ether_addr: check if the MAC addr is valid
151432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
151532ceabcaSGiuseppe CAVALLARO  * Description:
151632ceabcaSGiuseppe CAVALLARO  * it is to verify if the MAC address is valid, in case of failures it
151732ceabcaSGiuseppe CAVALLARO  * generates a random MAC address
151832ceabcaSGiuseppe CAVALLARO  */
1519bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv)
1520bfab27a1SGiuseppe CAVALLARO {
1521bfab27a1SGiuseppe CAVALLARO 	if (!is_valid_ether_addr(priv->dev->dev_addr)) {
1522bfab27a1SGiuseppe CAVALLARO 		priv->hw->mac->get_umac_addr((void __iomem *)
1523bfab27a1SGiuseppe CAVALLARO 					     priv->dev->base_addr,
1524bfab27a1SGiuseppe CAVALLARO 					     priv->dev->dev_addr, 0);
1525bfab27a1SGiuseppe CAVALLARO 		if (!is_valid_ether_addr(priv->dev->dev_addr))
1526f2cedb63SDanny Kukawka 			eth_hw_addr_random(priv->dev);
1527c88460b7SHans de Goede 		pr_info("%s: device MAC address %pM\n", priv->dev->name,
1528bfab27a1SGiuseppe CAVALLARO 			priv->dev->dev_addr);
1529bfab27a1SGiuseppe CAVALLARO 	}
1530c88460b7SHans de Goede }
1531bfab27a1SGiuseppe CAVALLARO 
153232ceabcaSGiuseppe CAVALLARO /**
153332ceabcaSGiuseppe CAVALLARO  * stmmac_init_dma_engine: DMA init.
153432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
153532ceabcaSGiuseppe CAVALLARO  * Description:
153632ceabcaSGiuseppe CAVALLARO  * It inits the DMA invoking the specific MAC/GMAC callback.
153732ceabcaSGiuseppe CAVALLARO  * Some DMA parameters can be passed from the platform;
153832ceabcaSGiuseppe CAVALLARO  * in case of these are not passed a default is kept for the MAC or GMAC.
153932ceabcaSGiuseppe CAVALLARO  */
15400f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv)
15410f1f88a8SGiuseppe CAVALLARO {
15420f1f88a8SGiuseppe CAVALLARO 	int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0;
1543b9cde0a8SGiuseppe CAVALLARO 	int mixed_burst = 0;
1544c24602efSGiuseppe CAVALLARO 	int atds = 0;
15450f1f88a8SGiuseppe CAVALLARO 
15460f1f88a8SGiuseppe CAVALLARO 	if (priv->plat->dma_cfg) {
15470f1f88a8SGiuseppe CAVALLARO 		pbl = priv->plat->dma_cfg->pbl;
15480f1f88a8SGiuseppe CAVALLARO 		fixed_burst = priv->plat->dma_cfg->fixed_burst;
1549b9cde0a8SGiuseppe CAVALLARO 		mixed_burst = priv->plat->dma_cfg->mixed_burst;
15500f1f88a8SGiuseppe CAVALLARO 		burst_len = priv->plat->dma_cfg->burst_len;
15510f1f88a8SGiuseppe CAVALLARO 	}
15520f1f88a8SGiuseppe CAVALLARO 
1553c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
1554c24602efSGiuseppe CAVALLARO 		atds = 1;
1555c24602efSGiuseppe CAVALLARO 
1556b9cde0a8SGiuseppe CAVALLARO 	return priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst,
15570f1f88a8SGiuseppe CAVALLARO 				   burst_len, priv->dma_tx_phy,
1558c24602efSGiuseppe CAVALLARO 				   priv->dma_rx_phy, atds);
15590f1f88a8SGiuseppe CAVALLARO }
15600f1f88a8SGiuseppe CAVALLARO 
1561bfab27a1SGiuseppe CAVALLARO /**
156232ceabcaSGiuseppe CAVALLARO  * stmmac_tx_timer: mitigation sw timer for tx.
15639125cdd1SGiuseppe CAVALLARO  * @data: data pointer
15649125cdd1SGiuseppe CAVALLARO  * Description:
15659125cdd1SGiuseppe CAVALLARO  * This is the timer handler to directly invoke the stmmac_tx_clean.
15669125cdd1SGiuseppe CAVALLARO  */
15679125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data)
15689125cdd1SGiuseppe CAVALLARO {
15699125cdd1SGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)data;
15709125cdd1SGiuseppe CAVALLARO 
15719125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
15729125cdd1SGiuseppe CAVALLARO }
15739125cdd1SGiuseppe CAVALLARO 
15749125cdd1SGiuseppe CAVALLARO /**
157532ceabcaSGiuseppe CAVALLARO  * stmmac_init_tx_coalesce: init tx mitigation options.
157632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
15779125cdd1SGiuseppe CAVALLARO  * Description:
15789125cdd1SGiuseppe CAVALLARO  * This inits the transmit coalesce parameters: i.e. timer rate,
15799125cdd1SGiuseppe CAVALLARO  * timer handler and default threshold used for enabling the
15809125cdd1SGiuseppe CAVALLARO  * interrupt on completion bit.
15819125cdd1SGiuseppe CAVALLARO  */
15829125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
15839125cdd1SGiuseppe CAVALLARO {
15849125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_frames = STMMAC_TX_FRAMES;
15859125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
15869125cdd1SGiuseppe CAVALLARO 	init_timer(&priv->txtimer);
15879125cdd1SGiuseppe CAVALLARO 	priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
15889125cdd1SGiuseppe CAVALLARO 	priv->txtimer.data = (unsigned long)priv;
15899125cdd1SGiuseppe CAVALLARO 	priv->txtimer.function = stmmac_tx_timer;
15909125cdd1SGiuseppe CAVALLARO 	add_timer(&priv->txtimer);
15919125cdd1SGiuseppe CAVALLARO }
15929125cdd1SGiuseppe CAVALLARO 
15939125cdd1SGiuseppe CAVALLARO /**
1594523f11b5SSrinivas Kandagatla  * stmmac_hw_setup: setup mac in a usable state.
1595523f11b5SSrinivas Kandagatla  *  @dev : pointer to the device structure.
1596523f11b5SSrinivas Kandagatla  *  Description:
1597523f11b5SSrinivas Kandagatla  *  This function sets up the ip in a usable state.
1598523f11b5SSrinivas Kandagatla  *  Return value:
1599523f11b5SSrinivas Kandagatla  *  0 on success and an appropriate (-)ve integer as defined in errno.h
1600523f11b5SSrinivas Kandagatla  *  file on failure.
1601523f11b5SSrinivas Kandagatla  */
1602523f11b5SSrinivas Kandagatla static int stmmac_hw_setup(struct net_device *dev)
1603523f11b5SSrinivas Kandagatla {
1604523f11b5SSrinivas Kandagatla 	struct stmmac_priv *priv = netdev_priv(dev);
1605523f11b5SSrinivas Kandagatla 	int ret;
1606523f11b5SSrinivas Kandagatla 
1607523f11b5SSrinivas Kandagatla 	ret = init_dma_desc_rings(dev);
1608523f11b5SSrinivas Kandagatla 	if (ret < 0) {
1609523f11b5SSrinivas Kandagatla 		pr_err("%s: DMA descriptors initialization failed\n", __func__);
1610523f11b5SSrinivas Kandagatla 		return ret;
1611523f11b5SSrinivas Kandagatla 	}
1612523f11b5SSrinivas Kandagatla 	/* DMA initialization and SW reset */
1613523f11b5SSrinivas Kandagatla 	ret = stmmac_init_dma_engine(priv);
1614523f11b5SSrinivas Kandagatla 	if (ret < 0) {
1615523f11b5SSrinivas Kandagatla 		pr_err("%s: DMA engine initialization failed\n", __func__);
1616523f11b5SSrinivas Kandagatla 		return ret;
1617523f11b5SSrinivas Kandagatla 	}
1618523f11b5SSrinivas Kandagatla 
1619523f11b5SSrinivas Kandagatla 	/* Copy the MAC addr into the HW  */
1620523f11b5SSrinivas Kandagatla 	priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0);
1621523f11b5SSrinivas Kandagatla 
1622523f11b5SSrinivas Kandagatla 	/* If required, perform hw setup of the bus. */
1623523f11b5SSrinivas Kandagatla 	if (priv->plat->bus_setup)
1624523f11b5SSrinivas Kandagatla 		priv->plat->bus_setup(priv->ioaddr);
1625523f11b5SSrinivas Kandagatla 
1626523f11b5SSrinivas Kandagatla 	/* Initialize the MAC Core */
16272618abb7SVince Bridgers 	priv->hw->mac->core_init(priv->ioaddr, dev->mtu);
1628523f11b5SSrinivas Kandagatla 
1629523f11b5SSrinivas Kandagatla 	/* Enable the MAC Rx/Tx */
1630523f11b5SSrinivas Kandagatla 	stmmac_set_mac(priv->ioaddr, true);
1631523f11b5SSrinivas Kandagatla 
1632523f11b5SSrinivas Kandagatla 	/* Set the HW DMA mode and the COE */
1633523f11b5SSrinivas Kandagatla 	stmmac_dma_operation_mode(priv);
1634523f11b5SSrinivas Kandagatla 
1635523f11b5SSrinivas Kandagatla 	stmmac_mmc_setup(priv);
1636523f11b5SSrinivas Kandagatla 
1637523f11b5SSrinivas Kandagatla 	ret = stmmac_init_ptp(priv);
16387509edd6SHans de Goede 	if (ret && ret != -EOPNOTSUPP)
1639523f11b5SSrinivas Kandagatla 		pr_warn("%s: failed PTP initialisation\n", __func__);
1640523f11b5SSrinivas Kandagatla 
1641523f11b5SSrinivas Kandagatla #ifdef CONFIG_STMMAC_DEBUG_FS
1642523f11b5SSrinivas Kandagatla 	ret = stmmac_init_fs(dev);
1643523f11b5SSrinivas Kandagatla 	if (ret < 0)
1644523f11b5SSrinivas Kandagatla 		pr_warn("%s: failed debugFS registration\n", __func__);
1645523f11b5SSrinivas Kandagatla #endif
1646523f11b5SSrinivas Kandagatla 	/* Start the ball rolling... */
1647523f11b5SSrinivas Kandagatla 	pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
1648523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_tx(priv->ioaddr);
1649523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_rx(priv->ioaddr);
1650523f11b5SSrinivas Kandagatla 
1651523f11b5SSrinivas Kandagatla 	/* Dump DMA/MAC registers */
1652523f11b5SSrinivas Kandagatla 	if (netif_msg_hw(priv)) {
1653523f11b5SSrinivas Kandagatla 		priv->hw->mac->dump_regs(priv->ioaddr);
1654523f11b5SSrinivas Kandagatla 		priv->hw->dma->dump_regs(priv->ioaddr);
1655523f11b5SSrinivas Kandagatla 	}
1656523f11b5SSrinivas Kandagatla 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
1657523f11b5SSrinivas Kandagatla 
1658523f11b5SSrinivas Kandagatla 	priv->eee_enabled = stmmac_eee_init(priv);
1659523f11b5SSrinivas Kandagatla 
1660523f11b5SSrinivas Kandagatla 	stmmac_init_tx_coalesce(priv);
1661523f11b5SSrinivas Kandagatla 
1662523f11b5SSrinivas Kandagatla 	if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
1663523f11b5SSrinivas Kandagatla 		priv->rx_riwt = MAX_DMA_RIWT;
1664523f11b5SSrinivas Kandagatla 		priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
1665523f11b5SSrinivas Kandagatla 	}
1666523f11b5SSrinivas Kandagatla 
1667523f11b5SSrinivas Kandagatla 	if (priv->pcs && priv->hw->mac->ctrl_ane)
1668523f11b5SSrinivas Kandagatla 		priv->hw->mac->ctrl_ane(priv->ioaddr, 0);
1669523f11b5SSrinivas Kandagatla 
1670523f11b5SSrinivas Kandagatla 	return 0;
1671523f11b5SSrinivas Kandagatla }
1672523f11b5SSrinivas Kandagatla 
1673523f11b5SSrinivas Kandagatla /**
16747ac6653aSJeff Kirsher  *  stmmac_open - open entry point of the driver
16757ac6653aSJeff Kirsher  *  @dev : pointer to the device structure.
16767ac6653aSJeff Kirsher  *  Description:
16777ac6653aSJeff Kirsher  *  This function is the open entry point of the driver.
16787ac6653aSJeff Kirsher  *  Return value:
16797ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
16807ac6653aSJeff Kirsher  *  file on failure.
16817ac6653aSJeff Kirsher  */
16827ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev)
16837ac6653aSJeff Kirsher {
16847ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
16857ac6653aSJeff Kirsher 	int ret;
16867ac6653aSJeff Kirsher 
16874bfcbd7aSFrancesco Virlinzi 	stmmac_check_ether_addr(priv);
16884bfcbd7aSFrancesco Virlinzi 
16894d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
16904d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
16917ac6653aSJeff Kirsher 		ret = stmmac_init_phy(dev);
1692e58bb43fSGiuseppe CAVALLARO 		if (ret) {
1693e58bb43fSGiuseppe CAVALLARO 			pr_err("%s: Cannot attach to PHY (error: %d)\n",
1694e58bb43fSGiuseppe CAVALLARO 			       __func__, ret);
1695c9324d18SGiuseppe CAVALLARO 			goto phy_error;
16967ac6653aSJeff Kirsher 		}
1697e58bb43fSGiuseppe CAVALLARO 	}
16987ac6653aSJeff Kirsher 
1699523f11b5SSrinivas Kandagatla 	/* Extra statistics */
1700523f11b5SSrinivas Kandagatla 	memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
1701523f11b5SSrinivas Kandagatla 	priv->xstats.threshold = tc;
1702523f11b5SSrinivas Kandagatla 
17037ac6653aSJeff Kirsher 	/* Create and initialize the TX/RX descriptors chains. */
17047ac6653aSJeff Kirsher 	priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
17057ac6653aSJeff Kirsher 	priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
17067ac6653aSJeff Kirsher 	priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
170756329137SBartlomiej Zolnierkiewicz 
17087262b7b2STobias Klauser 	ret = alloc_dma_desc_resources(priv);
170909f8d696SSrinivas Kandagatla 	if (ret < 0) {
171009f8d696SSrinivas Kandagatla 		pr_err("%s: DMA descriptors allocation failed\n", __func__);
171109f8d696SSrinivas Kandagatla 		goto dma_desc_error;
171209f8d696SSrinivas Kandagatla 	}
171309f8d696SSrinivas Kandagatla 
1714523f11b5SSrinivas Kandagatla 	ret = stmmac_hw_setup(dev);
171556329137SBartlomiej Zolnierkiewicz 	if (ret < 0) {
1716523f11b5SSrinivas Kandagatla 		pr_err("%s: Hw setup failed\n", __func__);
1717c9324d18SGiuseppe CAVALLARO 		goto init_error;
17187ac6653aSJeff Kirsher 	}
17197ac6653aSJeff Kirsher 
1720523f11b5SSrinivas Kandagatla 	if (priv->phydev)
1721523f11b5SSrinivas Kandagatla 		phy_start(priv->phydev);
17227ac6653aSJeff Kirsher 
17237ac6653aSJeff Kirsher 	/* Request the IRQ lines */
17247ac6653aSJeff Kirsher 	ret = request_irq(dev->irq, stmmac_interrupt,
17257ac6653aSJeff Kirsher 			  IRQF_SHARED, dev->name, dev);
17267ac6653aSJeff Kirsher 	if (unlikely(ret < 0)) {
17277ac6653aSJeff Kirsher 		pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
17287ac6653aSJeff Kirsher 		       __func__, dev->irq, ret);
1729c9324d18SGiuseppe CAVALLARO 		goto init_error;
17307ac6653aSJeff Kirsher 	}
17317ac6653aSJeff Kirsher 
17327a13f8f5SFrancesco Virlinzi 	/* Request the Wake IRQ in case of another line is used for WoL */
17337a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq) {
17347a13f8f5SFrancesco Virlinzi 		ret = request_irq(priv->wol_irq, stmmac_interrupt,
17357a13f8f5SFrancesco Virlinzi 				  IRQF_SHARED, dev->name, dev);
17367a13f8f5SFrancesco Virlinzi 		if (unlikely(ret < 0)) {
1737ceb69499SGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n",
1738ceb69499SGiuseppe CAVALLARO 			       __func__, priv->wol_irq, ret);
1739c9324d18SGiuseppe CAVALLARO 			goto wolirq_error;
17407a13f8f5SFrancesco Virlinzi 		}
17417a13f8f5SFrancesco Virlinzi 	}
17427a13f8f5SFrancesco Virlinzi 
1743d765955dSGiuseppe CAVALLARO 	/* Request the IRQ lines */
1744d765955dSGiuseppe CAVALLARO 	if (priv->lpi_irq != -ENXIO) {
1745d765955dSGiuseppe CAVALLARO 		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
1746d765955dSGiuseppe CAVALLARO 				  dev->name, dev);
1747d765955dSGiuseppe CAVALLARO 		if (unlikely(ret < 0)) {
1748d765955dSGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
1749d765955dSGiuseppe CAVALLARO 			       __func__, priv->lpi_irq, ret);
1750c9324d18SGiuseppe CAVALLARO 			goto lpiirq_error;
1751d765955dSGiuseppe CAVALLARO 		}
1752d765955dSGiuseppe CAVALLARO 	}
1753d765955dSGiuseppe CAVALLARO 
17547ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
17557ac6653aSJeff Kirsher 	netif_start_queue(dev);
17567ac6653aSJeff Kirsher 
17577ac6653aSJeff Kirsher 	return 0;
17587ac6653aSJeff Kirsher 
1759c9324d18SGiuseppe CAVALLARO lpiirq_error:
1760d765955dSGiuseppe CAVALLARO 	if (priv->wol_irq != dev->irq)
1761d765955dSGiuseppe CAVALLARO 		free_irq(priv->wol_irq, dev);
1762c9324d18SGiuseppe CAVALLARO wolirq_error:
17637a13f8f5SFrancesco Virlinzi 	free_irq(dev->irq, dev);
17647a13f8f5SFrancesco Virlinzi 
1765c9324d18SGiuseppe CAVALLARO init_error:
1766c9324d18SGiuseppe CAVALLARO 	free_dma_desc_resources(priv);
176756329137SBartlomiej Zolnierkiewicz dma_desc_error:
17687ac6653aSJeff Kirsher 	if (priv->phydev)
17697ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
1770c9324d18SGiuseppe CAVALLARO phy_error:
1771a630844dSStefan Roese 	clk_disable_unprepare(priv->stmmac_clk);
17724bfcbd7aSFrancesco Virlinzi 
17737ac6653aSJeff Kirsher 	return ret;
17747ac6653aSJeff Kirsher }
17757ac6653aSJeff Kirsher 
17767ac6653aSJeff Kirsher /**
17777ac6653aSJeff Kirsher  *  stmmac_release - close entry point of the driver
17787ac6653aSJeff Kirsher  *  @dev : device pointer.
17797ac6653aSJeff Kirsher  *  Description:
17807ac6653aSJeff Kirsher  *  This is the stop entry point of the driver.
17817ac6653aSJeff Kirsher  */
17827ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev)
17837ac6653aSJeff Kirsher {
17847ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
17857ac6653aSJeff Kirsher 
1786d765955dSGiuseppe CAVALLARO 	if (priv->eee_enabled)
1787d765955dSGiuseppe CAVALLARO 		del_timer_sync(&priv->eee_ctrl_timer);
1788d765955dSGiuseppe CAVALLARO 
17897ac6653aSJeff Kirsher 	/* Stop and disconnect the PHY */
17907ac6653aSJeff Kirsher 	if (priv->phydev) {
17917ac6653aSJeff Kirsher 		phy_stop(priv->phydev);
17927ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
17937ac6653aSJeff Kirsher 		priv->phydev = NULL;
17947ac6653aSJeff Kirsher 	}
17957ac6653aSJeff Kirsher 
17967ac6653aSJeff Kirsher 	netif_stop_queue(dev);
17977ac6653aSJeff Kirsher 
17987ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
17997ac6653aSJeff Kirsher 
18009125cdd1SGiuseppe CAVALLARO 	del_timer_sync(&priv->txtimer);
18019125cdd1SGiuseppe CAVALLARO 
18027ac6653aSJeff Kirsher 	/* Free the IRQ lines */
18037ac6653aSJeff Kirsher 	free_irq(dev->irq, dev);
18047a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq)
18057a13f8f5SFrancesco Virlinzi 		free_irq(priv->wol_irq, dev);
1806d765955dSGiuseppe CAVALLARO 	if (priv->lpi_irq != -ENXIO)
1807d765955dSGiuseppe CAVALLARO 		free_irq(priv->lpi_irq, dev);
18087ac6653aSJeff Kirsher 
18097ac6653aSJeff Kirsher 	/* Stop TX/RX DMA and clear the descriptors */
18107ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
18117ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
18127ac6653aSJeff Kirsher 
18137ac6653aSJeff Kirsher 	/* Release and free the Rx/Tx resources */
18147ac6653aSJeff Kirsher 	free_dma_desc_resources(priv);
18157ac6653aSJeff Kirsher 
18167ac6653aSJeff Kirsher 	/* Disable the MAC Rx/Tx */
1817bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
18187ac6653aSJeff Kirsher 
18197ac6653aSJeff Kirsher 	netif_carrier_off(dev);
18207ac6653aSJeff Kirsher 
1821bfab27a1SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_DEBUG_FS
1822bfab27a1SGiuseppe CAVALLARO 	stmmac_exit_fs();
1823bfab27a1SGiuseppe CAVALLARO #endif
1824bfab27a1SGiuseppe CAVALLARO 
182592ba6888SRayagond Kokatanur 	stmmac_release_ptp(priv);
182692ba6888SRayagond Kokatanur 
18277ac6653aSJeff Kirsher 	return 0;
18287ac6653aSJeff Kirsher }
18297ac6653aSJeff Kirsher 
18307ac6653aSJeff Kirsher /**
183132ceabcaSGiuseppe CAVALLARO  *  stmmac_xmit: Tx entry point of the driver
18327ac6653aSJeff Kirsher  *  @skb : the socket buffer
18337ac6653aSJeff Kirsher  *  @dev : device pointer
183432ceabcaSGiuseppe CAVALLARO  *  Description : this is the tx entry point of the driver.
183532ceabcaSGiuseppe CAVALLARO  *  It programs the chain or the ring and supports oversized frames
183632ceabcaSGiuseppe CAVALLARO  *  and SG feature.
18377ac6653aSJeff Kirsher  */
18387ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
18397ac6653aSJeff Kirsher {
18407ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
18417ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
18427ac6653aSJeff Kirsher 	unsigned int entry;
18434a7d666aSGiuseppe CAVALLARO 	int i, csum_insertion = 0, is_jumbo = 0;
18447ac6653aSJeff Kirsher 	int nfrags = skb_shinfo(skb)->nr_frags;
18457ac6653aSJeff Kirsher 	struct dma_desc *desc, *first;
1846286a8372SGiuseppe CAVALLARO 	unsigned int nopaged_len = skb_headlen(skb);
18477ac6653aSJeff Kirsher 
18487ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
18497ac6653aSJeff Kirsher 		if (!netif_queue_stopped(dev)) {
18507ac6653aSJeff Kirsher 			netif_stop_queue(dev);
18517ac6653aSJeff Kirsher 			/* This is a hard error, log it. */
1852ceb69499SGiuseppe CAVALLARO 			pr_err("%s: Tx Ring full when queue awake\n", __func__);
18537ac6653aSJeff Kirsher 		}
18547ac6653aSJeff Kirsher 		return NETDEV_TX_BUSY;
18557ac6653aSJeff Kirsher 	}
18567ac6653aSJeff Kirsher 
1857a9097a96SGiuseppe CAVALLARO 	spin_lock(&priv->tx_lock);
1858a9097a96SGiuseppe CAVALLARO 
1859d765955dSGiuseppe CAVALLARO 	if (priv->tx_path_in_lpi_mode)
1860d765955dSGiuseppe CAVALLARO 		stmmac_disable_eee_mode(priv);
1861d765955dSGiuseppe CAVALLARO 
18627ac6653aSJeff Kirsher 	entry = priv->cur_tx % txsize;
18637ac6653aSJeff Kirsher 
18647ac6653aSJeff Kirsher 	csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
18657ac6653aSJeff Kirsher 
1866c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc)
1867c24602efSGiuseppe CAVALLARO 		desc = (struct dma_desc *)(priv->dma_etx + entry);
1868c24602efSGiuseppe CAVALLARO 	else
18697ac6653aSJeff Kirsher 		desc = priv->dma_tx + entry;
1870c24602efSGiuseppe CAVALLARO 
18717ac6653aSJeff Kirsher 	first = desc;
18727ac6653aSJeff Kirsher 
18734a7d666aSGiuseppe CAVALLARO 	/* To program the descriptors according to the size of the frame */
18744a7d666aSGiuseppe CAVALLARO 	if (priv->mode == STMMAC_RING_MODE) {
18754a7d666aSGiuseppe CAVALLARO 		is_jumbo = priv->hw->ring->is_jumbo_frm(skb->len,
18764a7d666aSGiuseppe CAVALLARO 							priv->plat->enh_desc);
18774a7d666aSGiuseppe CAVALLARO 		if (unlikely(is_jumbo))
18784a7d666aSGiuseppe CAVALLARO 			entry = priv->hw->ring->jumbo_frm(priv, skb,
18794a7d666aSGiuseppe CAVALLARO 							  csum_insertion);
18807ac6653aSJeff Kirsher 	} else {
18814a7d666aSGiuseppe CAVALLARO 		is_jumbo = priv->hw->chain->is_jumbo_frm(skb->len,
18824a7d666aSGiuseppe CAVALLARO 							 priv->plat->enh_desc);
18834a7d666aSGiuseppe CAVALLARO 		if (unlikely(is_jumbo))
18844a7d666aSGiuseppe CAVALLARO 			entry = priv->hw->chain->jumbo_frm(priv, skb,
18854a7d666aSGiuseppe CAVALLARO 							   csum_insertion);
18864a7d666aSGiuseppe CAVALLARO 	}
18874a7d666aSGiuseppe CAVALLARO 	if (likely(!is_jumbo)) {
18887ac6653aSJeff Kirsher 		desc->des2 = dma_map_single(priv->device, skb->data,
18897ac6653aSJeff Kirsher 					    nopaged_len, DMA_TO_DEVICE);
1890cf32deecSRayagond Kokatanur 		priv->tx_skbuff_dma[entry] = desc->des2;
18917ac6653aSJeff Kirsher 		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
18924a7d666aSGiuseppe CAVALLARO 						csum_insertion, priv->mode);
18934a7d666aSGiuseppe CAVALLARO 	} else
1894c24602efSGiuseppe CAVALLARO 		desc = first;
18957ac6653aSJeff Kirsher 
18967ac6653aSJeff Kirsher 	for (i = 0; i < nfrags; i++) {
18979e903e08SEric Dumazet 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
18989e903e08SEric Dumazet 		int len = skb_frag_size(frag);
18997ac6653aSJeff Kirsher 
190075e4364fSdamuzi000 		priv->tx_skbuff[entry] = NULL;
19017ac6653aSJeff Kirsher 		entry = (++priv->cur_tx) % txsize;
1902c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1903c24602efSGiuseppe CAVALLARO 			desc = (struct dma_desc *)(priv->dma_etx + entry);
1904c24602efSGiuseppe CAVALLARO 		else
19057ac6653aSJeff Kirsher 			desc = priv->dma_tx + entry;
19067ac6653aSJeff Kirsher 
1907f722380dSIan Campbell 		desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
1908f722380dSIan Campbell 					      DMA_TO_DEVICE);
1909cf32deecSRayagond Kokatanur 		priv->tx_skbuff_dma[entry] = desc->des2;
19104a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
19114a7d666aSGiuseppe CAVALLARO 						priv->mode);
19127ac6653aSJeff Kirsher 		wmb();
19137ac6653aSJeff Kirsher 		priv->hw->desc->set_tx_owner(desc);
19148e839891SDeepak Sikri 		wmb();
19157ac6653aSJeff Kirsher 	}
19167ac6653aSJeff Kirsher 
191775e4364fSdamuzi000 	priv->tx_skbuff[entry] = skb;
191875e4364fSdamuzi000 
19199125cdd1SGiuseppe CAVALLARO 	/* Finalize the latest segment. */
19207ac6653aSJeff Kirsher 	priv->hw->desc->close_tx_desc(desc);
19217ac6653aSJeff Kirsher 
19227ac6653aSJeff Kirsher 	wmb();
19239125cdd1SGiuseppe CAVALLARO 	/* According to the coalesce parameter the IC bit for the latest
19249125cdd1SGiuseppe CAVALLARO 	 * segment could be reset and the timer re-started to invoke the
19259125cdd1SGiuseppe CAVALLARO 	 * stmmac_tx function. This approach takes care about the fragments.
19269125cdd1SGiuseppe CAVALLARO 	 */
19279125cdd1SGiuseppe CAVALLARO 	priv->tx_count_frames += nfrags + 1;
19289125cdd1SGiuseppe CAVALLARO 	if (priv->tx_coal_frames > priv->tx_count_frames) {
19299125cdd1SGiuseppe CAVALLARO 		priv->hw->desc->clear_tx_ic(desc);
19309125cdd1SGiuseppe CAVALLARO 		priv->xstats.tx_reset_ic_bit++;
19319125cdd1SGiuseppe CAVALLARO 		mod_timer(&priv->txtimer,
19329125cdd1SGiuseppe CAVALLARO 			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
19339125cdd1SGiuseppe CAVALLARO 	} else
19349125cdd1SGiuseppe CAVALLARO 		priv->tx_count_frames = 0;
19357ac6653aSJeff Kirsher 
19367ac6653aSJeff Kirsher 	/* To avoid raise condition */
19377ac6653aSJeff Kirsher 	priv->hw->desc->set_tx_owner(first);
19388e839891SDeepak Sikri 	wmb();
19397ac6653aSJeff Kirsher 
19407ac6653aSJeff Kirsher 	priv->cur_tx++;
19417ac6653aSJeff Kirsher 
19427ac6653aSJeff Kirsher 	if (netif_msg_pktdata(priv)) {
194383d7af64SGiuseppe CAVALLARO 		pr_debug("%s: curr %d dirty=%d entry=%d, first=%p, nfrags=%d",
1944ceb69499SGiuseppe CAVALLARO 			__func__, (priv->cur_tx % txsize),
1945ceb69499SGiuseppe CAVALLARO 			(priv->dirty_tx % txsize), entry, first, nfrags);
194683d7af64SGiuseppe CAVALLARO 
1947c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1948c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
1949c24602efSGiuseppe CAVALLARO 		else
1950c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
1951c24602efSGiuseppe CAVALLARO 
195283d7af64SGiuseppe CAVALLARO 		pr_debug(">>> frame to be transmitted: ");
19537ac6653aSJeff Kirsher 		print_pkt(skb->data, skb->len);
19547ac6653aSJeff Kirsher 	}
19557ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
195683d7af64SGiuseppe CAVALLARO 		if (netif_msg_hw(priv))
195783d7af64SGiuseppe CAVALLARO 			pr_debug("%s: stop transmitted packets\n", __func__);
19587ac6653aSJeff Kirsher 		netif_stop_queue(dev);
19597ac6653aSJeff Kirsher 	}
19607ac6653aSJeff Kirsher 
19617ac6653aSJeff Kirsher 	dev->stats.tx_bytes += skb->len;
19627ac6653aSJeff Kirsher 
1963891434b1SRayagond Kokatanur 	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
1964891434b1SRayagond Kokatanur 		     priv->hwts_tx_en)) {
1965891434b1SRayagond Kokatanur 		/* declare that device is doing timestamping */
1966891434b1SRayagond Kokatanur 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
1967891434b1SRayagond Kokatanur 		priv->hw->desc->enable_tx_timestamp(first);
1968891434b1SRayagond Kokatanur 	}
1969891434b1SRayagond Kokatanur 
1970891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
19717ac6653aSJeff Kirsher 		skb_tx_timestamp(skb);
19727ac6653aSJeff Kirsher 
19737ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_transmission(priv->ioaddr);
19747ac6653aSJeff Kirsher 
1975a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
1976a9097a96SGiuseppe CAVALLARO 
19777ac6653aSJeff Kirsher 	return NETDEV_TX_OK;
19787ac6653aSJeff Kirsher }
19797ac6653aSJeff Kirsher 
1980b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
1981b9381985SVince Bridgers {
1982b9381985SVince Bridgers 	struct ethhdr *ehdr;
1983b9381985SVince Bridgers 	u16 vlanid;
1984b9381985SVince Bridgers 
1985b9381985SVince Bridgers 	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
1986b9381985SVince Bridgers 	    NETIF_F_HW_VLAN_CTAG_RX &&
1987b9381985SVince Bridgers 	    !__vlan_get_tag(skb, &vlanid)) {
1988b9381985SVince Bridgers 		/* pop the vlan tag */
1989b9381985SVince Bridgers 		ehdr = (struct ethhdr *)skb->data;
1990b9381985SVince Bridgers 		memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
1991b9381985SVince Bridgers 		skb_pull(skb, VLAN_HLEN);
1992b9381985SVince Bridgers 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
1993b9381985SVince Bridgers 	}
1994b9381985SVince Bridgers }
1995b9381985SVince Bridgers 
1996b9381985SVince Bridgers 
199732ceabcaSGiuseppe CAVALLARO /**
199832ceabcaSGiuseppe CAVALLARO  * stmmac_rx_refill: refill used skb preallocated buffers
199932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
200032ceabcaSGiuseppe CAVALLARO  * Description : this is to reallocate the skb for the reception process
200132ceabcaSGiuseppe CAVALLARO  * that is based on zero-copy.
200232ceabcaSGiuseppe CAVALLARO  */
20037ac6653aSJeff Kirsher static inline void stmmac_rx_refill(struct stmmac_priv *priv)
20047ac6653aSJeff Kirsher {
20057ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
20067ac6653aSJeff Kirsher 	int bfsize = priv->dma_buf_sz;
20077ac6653aSJeff Kirsher 
20087ac6653aSJeff Kirsher 	for (; priv->cur_rx - priv->dirty_rx > 0; priv->dirty_rx++) {
20097ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_rx % rxsize;
2010c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
2011c24602efSGiuseppe CAVALLARO 
2012c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2013c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2014c24602efSGiuseppe CAVALLARO 		else
2015c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2016c24602efSGiuseppe CAVALLARO 
20177ac6653aSJeff Kirsher 		if (likely(priv->rx_skbuff[entry] == NULL)) {
20187ac6653aSJeff Kirsher 			struct sk_buff *skb;
20197ac6653aSJeff Kirsher 
2020acb600deSEric Dumazet 			skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
20217ac6653aSJeff Kirsher 
20227ac6653aSJeff Kirsher 			if (unlikely(skb == NULL))
20237ac6653aSJeff Kirsher 				break;
20247ac6653aSJeff Kirsher 
20257ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = skb;
20267ac6653aSJeff Kirsher 			priv->rx_skbuff_dma[entry] =
20277ac6653aSJeff Kirsher 			    dma_map_single(priv->device, skb->data, bfsize,
20287ac6653aSJeff Kirsher 					   DMA_FROM_DEVICE);
20297ac6653aSJeff Kirsher 
2030c24602efSGiuseppe CAVALLARO 			p->des2 = priv->rx_skbuff_dma[entry];
2031286a8372SGiuseppe CAVALLARO 
2032891434b1SRayagond Kokatanur 			priv->hw->ring->refill_desc3(priv, p);
2033286a8372SGiuseppe CAVALLARO 
203483d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv))
203583d7af64SGiuseppe CAVALLARO 				pr_debug("\trefill entry #%d\n", entry);
20367ac6653aSJeff Kirsher 		}
20377ac6653aSJeff Kirsher 		wmb();
2038c24602efSGiuseppe CAVALLARO 		priv->hw->desc->set_rx_owner(p);
20398e839891SDeepak Sikri 		wmb();
20407ac6653aSJeff Kirsher 	}
20417ac6653aSJeff Kirsher }
20427ac6653aSJeff Kirsher 
204332ceabcaSGiuseppe CAVALLARO /**
204432ceabcaSGiuseppe CAVALLARO  * stmmac_rx_refill: refill used skb preallocated buffers
204532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
204632ceabcaSGiuseppe CAVALLARO  * @limit: napi bugget.
204732ceabcaSGiuseppe CAVALLARO  * Description :  this the function called by the napi poll method.
204832ceabcaSGiuseppe CAVALLARO  * It gets all the frames inside the ring.
204932ceabcaSGiuseppe CAVALLARO  */
20507ac6653aSJeff Kirsher static int stmmac_rx(struct stmmac_priv *priv, int limit)
20517ac6653aSJeff Kirsher {
20527ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
20537ac6653aSJeff Kirsher 	unsigned int entry = priv->cur_rx % rxsize;
20547ac6653aSJeff Kirsher 	unsigned int next_entry;
20557ac6653aSJeff Kirsher 	unsigned int count = 0;
2056ceb69499SGiuseppe CAVALLARO 	int coe = priv->plat->rx_coe;
20577ac6653aSJeff Kirsher 
205883d7af64SGiuseppe CAVALLARO 	if (netif_msg_rx_status(priv)) {
205983d7af64SGiuseppe CAVALLARO 		pr_debug("%s: descriptor ring:\n", __func__);
2060c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2061c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
2062c24602efSGiuseppe CAVALLARO 		else
2063c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
20647ac6653aSJeff Kirsher 	}
2065c24602efSGiuseppe CAVALLARO 	while (count < limit) {
20667ac6653aSJeff Kirsher 		int status;
20679401bb5cSGiuseppe CAVALLARO 		struct dma_desc *p;
20687ac6653aSJeff Kirsher 
2069c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2070c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2071c24602efSGiuseppe CAVALLARO 		else
2072c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2073c24602efSGiuseppe CAVALLARO 
2074c24602efSGiuseppe CAVALLARO 		if (priv->hw->desc->get_rx_owner(p))
20757ac6653aSJeff Kirsher 			break;
20767ac6653aSJeff Kirsher 
20777ac6653aSJeff Kirsher 		count++;
20787ac6653aSJeff Kirsher 
20797ac6653aSJeff Kirsher 		next_entry = (++priv->cur_rx) % rxsize;
2080c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
20819401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_erx + next_entry);
2082c24602efSGiuseppe CAVALLARO 		else
20839401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_rx + next_entry);
20847ac6653aSJeff Kirsher 
20857ac6653aSJeff Kirsher 		/* read the status of the incoming frame */
2086c24602efSGiuseppe CAVALLARO 		status = priv->hw->desc->rx_status(&priv->dev->stats,
2087c24602efSGiuseppe CAVALLARO 						   &priv->xstats, p);
2088c24602efSGiuseppe CAVALLARO 		if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status))
2089c24602efSGiuseppe CAVALLARO 			priv->hw->desc->rx_extended_status(&priv->dev->stats,
2090c24602efSGiuseppe CAVALLARO 							   &priv->xstats,
2091c24602efSGiuseppe CAVALLARO 							   priv->dma_erx +
2092c24602efSGiuseppe CAVALLARO 							   entry);
2093891434b1SRayagond Kokatanur 		if (unlikely(status == discard_frame)) {
20947ac6653aSJeff Kirsher 			priv->dev->stats.rx_errors++;
2095891434b1SRayagond Kokatanur 			if (priv->hwts_rx_en && !priv->extend_desc) {
2096891434b1SRayagond Kokatanur 				/* DESC2 & DESC3 will be overwitten by device
2097891434b1SRayagond Kokatanur 				 * with timestamp value, hence reinitialize
2098891434b1SRayagond Kokatanur 				 * them in stmmac_rx_refill() function so that
2099891434b1SRayagond Kokatanur 				 * device can reuse it.
2100891434b1SRayagond Kokatanur 				 */
2101891434b1SRayagond Kokatanur 				priv->rx_skbuff[entry] = NULL;
2102891434b1SRayagond Kokatanur 				dma_unmap_single(priv->device,
2103891434b1SRayagond Kokatanur 						 priv->rx_skbuff_dma[entry],
2104ceb69499SGiuseppe CAVALLARO 						 priv->dma_buf_sz,
2105ceb69499SGiuseppe CAVALLARO 						 DMA_FROM_DEVICE);
2106891434b1SRayagond Kokatanur 			}
2107891434b1SRayagond Kokatanur 		} else {
21087ac6653aSJeff Kirsher 			struct sk_buff *skb;
21097ac6653aSJeff Kirsher 			int frame_len;
21107ac6653aSJeff Kirsher 
2111ceb69499SGiuseppe CAVALLARO 			frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
2112ceb69499SGiuseppe CAVALLARO 
21137ac6653aSJeff Kirsher 			/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
2114ceb69499SGiuseppe CAVALLARO 			 * Type frames (LLC/LLC-SNAP)
2115ceb69499SGiuseppe CAVALLARO 			 */
21167ac6653aSJeff Kirsher 			if (unlikely(status != llc_snap))
21177ac6653aSJeff Kirsher 				frame_len -= ETH_FCS_LEN;
21187ac6653aSJeff Kirsher 
211983d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv)) {
21207ac6653aSJeff Kirsher 				pr_debug("\tdesc: %p [entry %d] buff=0x%x\n",
21217ac6653aSJeff Kirsher 					 p, entry, p->des2);
212283d7af64SGiuseppe CAVALLARO 				if (frame_len > ETH_FRAME_LEN)
212383d7af64SGiuseppe CAVALLARO 					pr_debug("\tframe size %d, COE: %d\n",
212483d7af64SGiuseppe CAVALLARO 						 frame_len, status);
212583d7af64SGiuseppe CAVALLARO 			}
21267ac6653aSJeff Kirsher 			skb = priv->rx_skbuff[entry];
21277ac6653aSJeff Kirsher 			if (unlikely(!skb)) {
21287ac6653aSJeff Kirsher 				pr_err("%s: Inconsistent Rx descriptor chain\n",
21297ac6653aSJeff Kirsher 				       priv->dev->name);
21307ac6653aSJeff Kirsher 				priv->dev->stats.rx_dropped++;
21317ac6653aSJeff Kirsher 				break;
21327ac6653aSJeff Kirsher 			}
21337ac6653aSJeff Kirsher 			prefetch(skb->data - NET_IP_ALIGN);
21347ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = NULL;
21357ac6653aSJeff Kirsher 
2136891434b1SRayagond Kokatanur 			stmmac_get_rx_hwtstamp(priv, entry, skb);
2137891434b1SRayagond Kokatanur 
21387ac6653aSJeff Kirsher 			skb_put(skb, frame_len);
21397ac6653aSJeff Kirsher 			dma_unmap_single(priv->device,
21407ac6653aSJeff Kirsher 					 priv->rx_skbuff_dma[entry],
21417ac6653aSJeff Kirsher 					 priv->dma_buf_sz, DMA_FROM_DEVICE);
214283d7af64SGiuseppe CAVALLARO 
21437ac6653aSJeff Kirsher 			if (netif_msg_pktdata(priv)) {
214483d7af64SGiuseppe CAVALLARO 				pr_debug("frame received (%dbytes)", frame_len);
21457ac6653aSJeff Kirsher 				print_pkt(skb->data, frame_len);
21467ac6653aSJeff Kirsher 			}
214783d7af64SGiuseppe CAVALLARO 
2148b9381985SVince Bridgers 			stmmac_rx_vlan(priv->dev, skb);
2149b9381985SVince Bridgers 
21507ac6653aSJeff Kirsher 			skb->protocol = eth_type_trans(skb, priv->dev);
21517ac6653aSJeff Kirsher 
2152ceb69499SGiuseppe CAVALLARO 			if (unlikely(!coe))
21537ac6653aSJeff Kirsher 				skb_checksum_none_assert(skb);
215462a2ab93SGiuseppe CAVALLARO 			else
21557ac6653aSJeff Kirsher 				skb->ip_summed = CHECKSUM_UNNECESSARY;
215662a2ab93SGiuseppe CAVALLARO 
21577ac6653aSJeff Kirsher 			napi_gro_receive(&priv->napi, skb);
21587ac6653aSJeff Kirsher 
21597ac6653aSJeff Kirsher 			priv->dev->stats.rx_packets++;
21607ac6653aSJeff Kirsher 			priv->dev->stats.rx_bytes += frame_len;
21617ac6653aSJeff Kirsher 		}
21627ac6653aSJeff Kirsher 		entry = next_entry;
21637ac6653aSJeff Kirsher 	}
21647ac6653aSJeff Kirsher 
21657ac6653aSJeff Kirsher 	stmmac_rx_refill(priv);
21667ac6653aSJeff Kirsher 
21677ac6653aSJeff Kirsher 	priv->xstats.rx_pkt_n += count;
21687ac6653aSJeff Kirsher 
21697ac6653aSJeff Kirsher 	return count;
21707ac6653aSJeff Kirsher }
21717ac6653aSJeff Kirsher 
21727ac6653aSJeff Kirsher /**
21737ac6653aSJeff Kirsher  *  stmmac_poll - stmmac poll method (NAPI)
21747ac6653aSJeff Kirsher  *  @napi : pointer to the napi structure.
21757ac6653aSJeff Kirsher  *  @budget : maximum number of packets that the current CPU can receive from
21767ac6653aSJeff Kirsher  *	      all interfaces.
21777ac6653aSJeff Kirsher  *  Description :
21789125cdd1SGiuseppe CAVALLARO  *  To look at the incoming frames and clear the tx resources.
21797ac6653aSJeff Kirsher  */
21807ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget)
21817ac6653aSJeff Kirsher {
21827ac6653aSJeff Kirsher 	struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
21837ac6653aSJeff Kirsher 	int work_done = 0;
21847ac6653aSJeff Kirsher 
21859125cdd1SGiuseppe CAVALLARO 	priv->xstats.napi_poll++;
21869125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
21877ac6653aSJeff Kirsher 
21889125cdd1SGiuseppe CAVALLARO 	work_done = stmmac_rx(priv, budget);
21897ac6653aSJeff Kirsher 	if (work_done < budget) {
21907ac6653aSJeff Kirsher 		napi_complete(napi);
21919125cdd1SGiuseppe CAVALLARO 		stmmac_enable_dma_irq(priv);
21927ac6653aSJeff Kirsher 	}
21937ac6653aSJeff Kirsher 	return work_done;
21947ac6653aSJeff Kirsher }
21957ac6653aSJeff Kirsher 
21967ac6653aSJeff Kirsher /**
21977ac6653aSJeff Kirsher  *  stmmac_tx_timeout
21987ac6653aSJeff Kirsher  *  @dev : Pointer to net device structure
21997ac6653aSJeff Kirsher  *  Description: this function is called when a packet transmission fails to
22007284a3f1SGiuseppe CAVALLARO  *   complete within a reasonable time. The driver will mark the error in the
22017ac6653aSJeff Kirsher  *   netdev structure and arrange for the device to be reset to a sane state
22027ac6653aSJeff Kirsher  *   in order to transmit a new packet.
22037ac6653aSJeff Kirsher  */
22047ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev)
22057ac6653aSJeff Kirsher {
22067ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22077ac6653aSJeff Kirsher 
22087ac6653aSJeff Kirsher 	/* Clear Tx resources and restart transmitting again */
22097ac6653aSJeff Kirsher 	stmmac_tx_err(priv);
22107ac6653aSJeff Kirsher }
22117ac6653aSJeff Kirsher 
22127ac6653aSJeff Kirsher /* Configuration changes (passed on by ifconfig) */
22137ac6653aSJeff Kirsher static int stmmac_config(struct net_device *dev, struct ifmap *map)
22147ac6653aSJeff Kirsher {
22157ac6653aSJeff Kirsher 	if (dev->flags & IFF_UP)	/* can't act on a running interface */
22167ac6653aSJeff Kirsher 		return -EBUSY;
22177ac6653aSJeff Kirsher 
22187ac6653aSJeff Kirsher 	/* Don't allow changing the I/O address */
22197ac6653aSJeff Kirsher 	if (map->base_addr != dev->base_addr) {
2220ceb69499SGiuseppe CAVALLARO 		pr_warn("%s: can't change I/O address\n", dev->name);
22217ac6653aSJeff Kirsher 		return -EOPNOTSUPP;
22227ac6653aSJeff Kirsher 	}
22237ac6653aSJeff Kirsher 
22247ac6653aSJeff Kirsher 	/* Don't allow changing the IRQ */
22257ac6653aSJeff Kirsher 	if (map->irq != dev->irq) {
2226ceb69499SGiuseppe CAVALLARO 		pr_warn("%s: not change IRQ number %d\n", dev->name, dev->irq);
22277ac6653aSJeff Kirsher 		return -EOPNOTSUPP;
22287ac6653aSJeff Kirsher 	}
22297ac6653aSJeff Kirsher 
22307ac6653aSJeff Kirsher 	return 0;
22317ac6653aSJeff Kirsher }
22327ac6653aSJeff Kirsher 
22337ac6653aSJeff Kirsher /**
223401789349SJiri Pirko  *  stmmac_set_rx_mode - entry point for multicast addressing
22357ac6653aSJeff Kirsher  *  @dev : pointer to the device structure
22367ac6653aSJeff Kirsher  *  Description:
22377ac6653aSJeff Kirsher  *  This function is a driver entry point which gets called by the kernel
22387ac6653aSJeff Kirsher  *  whenever multicast addresses must be enabled/disabled.
22397ac6653aSJeff Kirsher  *  Return value:
22407ac6653aSJeff Kirsher  *  void.
22417ac6653aSJeff Kirsher  */
224201789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev)
22437ac6653aSJeff Kirsher {
22447ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22457ac6653aSJeff Kirsher 
22467ac6653aSJeff Kirsher 	spin_lock(&priv->lock);
2247cffb13f4SGiuseppe CAVALLARO 	priv->hw->mac->set_filter(dev, priv->synopsys_id);
22487ac6653aSJeff Kirsher 	spin_unlock(&priv->lock);
22497ac6653aSJeff Kirsher }
22507ac6653aSJeff Kirsher 
22517ac6653aSJeff Kirsher /**
22527ac6653aSJeff Kirsher  *  stmmac_change_mtu - entry point to change MTU size for the device.
22537ac6653aSJeff Kirsher  *  @dev : device pointer.
22547ac6653aSJeff Kirsher  *  @new_mtu : the new MTU size for the device.
22557ac6653aSJeff Kirsher  *  Description: the Maximum Transfer Unit (MTU) is used by the network layer
22567ac6653aSJeff Kirsher  *  to drive packet transmission. Ethernet has an MTU of 1500 octets
22577ac6653aSJeff Kirsher  *  (ETH_DATA_LEN). This value can be changed with ifconfig.
22587ac6653aSJeff Kirsher  *  Return value:
22597ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
22607ac6653aSJeff Kirsher  *  file on failure.
22617ac6653aSJeff Kirsher  */
22627ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
22637ac6653aSJeff Kirsher {
22647ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22657ac6653aSJeff Kirsher 	int max_mtu;
22667ac6653aSJeff Kirsher 
22677ac6653aSJeff Kirsher 	if (netif_running(dev)) {
22687ac6653aSJeff Kirsher 		pr_err("%s: must be stopped to change its MTU\n", dev->name);
22697ac6653aSJeff Kirsher 		return -EBUSY;
22707ac6653aSJeff Kirsher 	}
22717ac6653aSJeff Kirsher 
227248febf7eSGiuseppe CAVALLARO 	if (priv->plat->enh_desc)
22737ac6653aSJeff Kirsher 		max_mtu = JUMBO_LEN;
22747ac6653aSJeff Kirsher 	else
227545db81e1SGiuseppe CAVALLARO 		max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
22767ac6653aSJeff Kirsher 
22772618abb7SVince Bridgers 	if (priv->plat->maxmtu < max_mtu)
22782618abb7SVince Bridgers 		max_mtu = priv->plat->maxmtu;
22792618abb7SVince Bridgers 
22807ac6653aSJeff Kirsher 	if ((new_mtu < 46) || (new_mtu > max_mtu)) {
22817ac6653aSJeff Kirsher 		pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
22827ac6653aSJeff Kirsher 		return -EINVAL;
22837ac6653aSJeff Kirsher 	}
22847ac6653aSJeff Kirsher 
22857ac6653aSJeff Kirsher 	dev->mtu = new_mtu;
22867ac6653aSJeff Kirsher 	netdev_update_features(dev);
22877ac6653aSJeff Kirsher 
22887ac6653aSJeff Kirsher 	return 0;
22897ac6653aSJeff Kirsher }
22907ac6653aSJeff Kirsher 
2291c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev,
2292c8f44affSMichał Mirosław 					     netdev_features_t features)
22937ac6653aSJeff Kirsher {
22947ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22957ac6653aSJeff Kirsher 
229638912bdbSDeepak SIKRI 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
22977ac6653aSJeff Kirsher 		features &= ~NETIF_F_RXCSUM;
229838912bdbSDeepak SIKRI 	else if (priv->plat->rx_coe == STMMAC_RX_COE_TYPE1)
229938912bdbSDeepak SIKRI 		features &= ~NETIF_F_IPV6_CSUM;
23007ac6653aSJeff Kirsher 	if (!priv->plat->tx_coe)
23017ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
23027ac6653aSJeff Kirsher 
23037ac6653aSJeff Kirsher 	/* Some GMAC devices have a bugged Jumbo frame support that
23047ac6653aSJeff Kirsher 	 * needs to have the Tx COE disabled for oversized frames
23057ac6653aSJeff Kirsher 	 * (due to limited buffer sizes). In this case we disable
2306ceb69499SGiuseppe CAVALLARO 	 * the TX csum insertionin the TDES and not use SF.
2307ceb69499SGiuseppe CAVALLARO 	 */
23087ac6653aSJeff Kirsher 	if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
23097ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
23107ac6653aSJeff Kirsher 
23117ac6653aSJeff Kirsher 	return features;
23127ac6653aSJeff Kirsher }
23137ac6653aSJeff Kirsher 
231432ceabcaSGiuseppe CAVALLARO /**
231532ceabcaSGiuseppe CAVALLARO  *  stmmac_interrupt - main ISR
231632ceabcaSGiuseppe CAVALLARO  *  @irq: interrupt number.
231732ceabcaSGiuseppe CAVALLARO  *  @dev_id: to pass the net device pointer.
231832ceabcaSGiuseppe CAVALLARO  *  Description: this is the main driver interrupt service routine.
231932ceabcaSGiuseppe CAVALLARO  *  It calls the DMA ISR and also the core ISR to manage PMT, MMC, LPI
232032ceabcaSGiuseppe CAVALLARO  *  interrupts.
232132ceabcaSGiuseppe CAVALLARO  */
23227ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
23237ac6653aSJeff Kirsher {
23247ac6653aSJeff Kirsher 	struct net_device *dev = (struct net_device *)dev_id;
23257ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23267ac6653aSJeff Kirsher 
232789f7f2cfSSrinivas Kandagatla 	if (priv->irq_wake)
232889f7f2cfSSrinivas Kandagatla 		pm_wakeup_event(priv->device, 0);
232989f7f2cfSSrinivas Kandagatla 
23307ac6653aSJeff Kirsher 	if (unlikely(!dev)) {
23317ac6653aSJeff Kirsher 		pr_err("%s: invalid dev pointer\n", __func__);
23327ac6653aSJeff Kirsher 		return IRQ_NONE;
23337ac6653aSJeff Kirsher 	}
23347ac6653aSJeff Kirsher 
23357ac6653aSJeff Kirsher 	/* To handle GMAC own interrupts */
2336d765955dSGiuseppe CAVALLARO 	if (priv->plat->has_gmac) {
2337d765955dSGiuseppe CAVALLARO 		int status = priv->hw->mac->host_irq_status((void __iomem *)
23380982a0f6SGiuseppe CAVALLARO 							    dev->base_addr,
23390982a0f6SGiuseppe CAVALLARO 							    &priv->xstats);
2340d765955dSGiuseppe CAVALLARO 		if (unlikely(status)) {
2341d765955dSGiuseppe CAVALLARO 			/* For LPI we need to save the tx status */
23420982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
2343d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = true;
23440982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
2345d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = false;
2346d765955dSGiuseppe CAVALLARO 		}
2347d765955dSGiuseppe CAVALLARO 	}
2348d765955dSGiuseppe CAVALLARO 
2349d765955dSGiuseppe CAVALLARO 	/* To handle DMA interrupts */
23507ac6653aSJeff Kirsher 	stmmac_dma_interrupt(priv);
23517ac6653aSJeff Kirsher 
23527ac6653aSJeff Kirsher 	return IRQ_HANDLED;
23537ac6653aSJeff Kirsher }
23547ac6653aSJeff Kirsher 
23557ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
23567ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools
2357ceb69499SGiuseppe CAVALLARO  * to allow network I/O with interrupts disabled.
2358ceb69499SGiuseppe CAVALLARO  */
23597ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev)
23607ac6653aSJeff Kirsher {
23617ac6653aSJeff Kirsher 	disable_irq(dev->irq);
23627ac6653aSJeff Kirsher 	stmmac_interrupt(dev->irq, dev);
23637ac6653aSJeff Kirsher 	enable_irq(dev->irq);
23647ac6653aSJeff Kirsher }
23657ac6653aSJeff Kirsher #endif
23667ac6653aSJeff Kirsher 
23677ac6653aSJeff Kirsher /**
23687ac6653aSJeff Kirsher  *  stmmac_ioctl - Entry point for the Ioctl
23697ac6653aSJeff Kirsher  *  @dev: Device pointer.
23707ac6653aSJeff Kirsher  *  @rq: An IOCTL specefic structure, that can contain a pointer to
23717ac6653aSJeff Kirsher  *  a proprietary structure used to pass information to the driver.
23727ac6653aSJeff Kirsher  *  @cmd: IOCTL command
23737ac6653aSJeff Kirsher  *  Description:
237432ceabcaSGiuseppe CAVALLARO  *  Currently it supports the phy_mii_ioctl(...) and HW time stamping.
23757ac6653aSJeff Kirsher  */
23767ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
23777ac6653aSJeff Kirsher {
23787ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
2379891434b1SRayagond Kokatanur 	int ret = -EOPNOTSUPP;
23807ac6653aSJeff Kirsher 
23817ac6653aSJeff Kirsher 	if (!netif_running(dev))
23827ac6653aSJeff Kirsher 		return -EINVAL;
23837ac6653aSJeff Kirsher 
2384891434b1SRayagond Kokatanur 	switch (cmd) {
2385891434b1SRayagond Kokatanur 	case SIOCGMIIPHY:
2386891434b1SRayagond Kokatanur 	case SIOCGMIIREG:
2387891434b1SRayagond Kokatanur 	case SIOCSMIIREG:
23887ac6653aSJeff Kirsher 		if (!priv->phydev)
23897ac6653aSJeff Kirsher 			return -EINVAL;
23907ac6653aSJeff Kirsher 		ret = phy_mii_ioctl(priv->phydev, rq, cmd);
2391891434b1SRayagond Kokatanur 		break;
2392891434b1SRayagond Kokatanur 	case SIOCSHWTSTAMP:
2393891434b1SRayagond Kokatanur 		ret = stmmac_hwtstamp_ioctl(dev, rq);
2394891434b1SRayagond Kokatanur 		break;
2395891434b1SRayagond Kokatanur 	default:
2396891434b1SRayagond Kokatanur 		break;
2397891434b1SRayagond Kokatanur 	}
23987ac6653aSJeff Kirsher 
23997ac6653aSJeff Kirsher 	return ret;
24007ac6653aSJeff Kirsher }
24017ac6653aSJeff Kirsher 
24027ac29055SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_DEBUG_FS
24037ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir;
24047ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_rings_status;
2405e7434821SGiuseppe CAVALLARO static struct dentry *stmmac_dma_cap;
24067ac29055SGiuseppe CAVALLARO 
2407c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc,
2408c24602efSGiuseppe CAVALLARO 			       struct seq_file *seq)
24097ac29055SGiuseppe CAVALLARO {
24107ac29055SGiuseppe CAVALLARO 	int i;
2411c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
2412c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
24137ac29055SGiuseppe CAVALLARO 
2414c24602efSGiuseppe CAVALLARO 	for (i = 0; i < size; i++) {
2415c24602efSGiuseppe CAVALLARO 		u64 x;
2416c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
2417c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
2418c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2419c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2420c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2421c24602efSGiuseppe CAVALLARO 				   ep->basic.des2, ep->basic.des3);
2422c24602efSGiuseppe CAVALLARO 			ep++;
2423c24602efSGiuseppe CAVALLARO 		} else {
2424c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
2425c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2426c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2427c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2428c24602efSGiuseppe CAVALLARO 				   p->des2, p->des3);
2429c24602efSGiuseppe CAVALLARO 			p++;
2430c24602efSGiuseppe CAVALLARO 		}
24317ac29055SGiuseppe CAVALLARO 		seq_printf(seq, "\n");
24327ac29055SGiuseppe CAVALLARO 	}
2433c24602efSGiuseppe CAVALLARO }
24347ac29055SGiuseppe CAVALLARO 
2435c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
2436c24602efSGiuseppe CAVALLARO {
2437c24602efSGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2438c24602efSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2439c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
2440c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
24417ac29055SGiuseppe CAVALLARO 
2442c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
2443c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended RX descriptor ring:\n");
2444c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_erx, rxsize, 1, seq);
2445c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended TX descriptor ring:\n");
2446c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_etx, txsize, 1, seq);
2447c24602efSGiuseppe CAVALLARO 	} else {
2448c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "RX descriptor ring:\n");
2449c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_rx, rxsize, 0, seq);
2450c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "TX descriptor ring:\n");
2451c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_tx, txsize, 0, seq);
24527ac29055SGiuseppe CAVALLARO 	}
24537ac29055SGiuseppe CAVALLARO 
24547ac29055SGiuseppe CAVALLARO 	return 0;
24557ac29055SGiuseppe CAVALLARO }
24567ac29055SGiuseppe CAVALLARO 
24577ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
24587ac29055SGiuseppe CAVALLARO {
24597ac29055SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
24607ac29055SGiuseppe CAVALLARO }
24617ac29055SGiuseppe CAVALLARO 
24627ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = {
24637ac29055SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
24647ac29055SGiuseppe CAVALLARO 	.open = stmmac_sysfs_ring_open,
24657ac29055SGiuseppe CAVALLARO 	.read = seq_read,
24667ac29055SGiuseppe CAVALLARO 	.llseek = seq_lseek,
246774863948SDjalal Harouni 	.release = single_release,
24687ac29055SGiuseppe CAVALLARO };
24697ac29055SGiuseppe CAVALLARO 
2470e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
2471e7434821SGiuseppe CAVALLARO {
2472e7434821SGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2473e7434821SGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2474e7434821SGiuseppe CAVALLARO 
247519e30c14SGiuseppe CAVALLARO 	if (!priv->hw_cap_support) {
2476e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "DMA HW features not supported\n");
2477e7434821SGiuseppe CAVALLARO 		return 0;
2478e7434821SGiuseppe CAVALLARO 	}
2479e7434821SGiuseppe CAVALLARO 
2480e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2481e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tDMA HW features\n");
2482e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2483e7434821SGiuseppe CAVALLARO 
2484e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t10/100 Mbps %s\n",
2485e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_10_100) ? "Y" : "N");
2486e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t1000 Mbps %s\n",
2487e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_1000) ? "Y" : "N");
2488e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHalf duple %s\n",
2489e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.half_duplex) ? "Y" : "N");
2490e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHash Filter: %s\n",
2491e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.hash_filter) ? "Y" : "N");
2492e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tMultiple MAC address registers: %s\n",
2493e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.multi_addr) ? "Y" : "N");
2494e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n",
2495e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pcs) ? "Y" : "N");
2496e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
2497e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.sma_mdio) ? "Y" : "N");
2498e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Remote wake up: %s\n",
2499e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
2500e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Magic Frame: %s\n",
2501e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
2502e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRMON module: %s\n",
2503e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rmon) ? "Y" : "N");
2504e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
2505e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.time_stamp) ? "Y" : "N");
2506e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n",
2507e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.atime_stamp) ? "Y" : "N");
2508e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n",
2509e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.eee) ? "Y" : "N");
2510e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
2511e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tChecksum Offload in TX: %s\n",
2512e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.tx_coe) ? "Y" : "N");
2513e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
2514e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
2515e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
2516e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
2517e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
2518e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
2519e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
2520e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_rx_channel);
2521e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
2522e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_tx_channel);
2523e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tEnhanced descriptors: %s\n",
2524e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.enh_desc) ? "Y" : "N");
2525e7434821SGiuseppe CAVALLARO 
2526e7434821SGiuseppe CAVALLARO 	return 0;
2527e7434821SGiuseppe CAVALLARO }
2528e7434821SGiuseppe CAVALLARO 
2529e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
2530e7434821SGiuseppe CAVALLARO {
2531e7434821SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
2532e7434821SGiuseppe CAVALLARO }
2533e7434821SGiuseppe CAVALLARO 
2534e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = {
2535e7434821SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
2536e7434821SGiuseppe CAVALLARO 	.open = stmmac_sysfs_dma_cap_open,
2537e7434821SGiuseppe CAVALLARO 	.read = seq_read,
2538e7434821SGiuseppe CAVALLARO 	.llseek = seq_lseek,
253974863948SDjalal Harouni 	.release = single_release,
2540e7434821SGiuseppe CAVALLARO };
2541e7434821SGiuseppe CAVALLARO 
25427ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev)
25437ac29055SGiuseppe CAVALLARO {
25447ac29055SGiuseppe CAVALLARO 	/* Create debugfs entries */
25457ac29055SGiuseppe CAVALLARO 	stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
25467ac29055SGiuseppe CAVALLARO 
25477ac29055SGiuseppe CAVALLARO 	if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
25487ac29055SGiuseppe CAVALLARO 		pr_err("ERROR %s, debugfs create directory failed\n",
25497ac29055SGiuseppe CAVALLARO 		       STMMAC_RESOURCE_NAME);
25507ac29055SGiuseppe CAVALLARO 
25517ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
25527ac29055SGiuseppe CAVALLARO 	}
25537ac29055SGiuseppe CAVALLARO 
25547ac29055SGiuseppe CAVALLARO 	/* Entry to report DMA RX/TX rings */
25557ac29055SGiuseppe CAVALLARO 	stmmac_rings_status = debugfs_create_file("descriptors_status",
25567ac29055SGiuseppe CAVALLARO 						  S_IRUGO, stmmac_fs_dir, dev,
25577ac29055SGiuseppe CAVALLARO 						  &stmmac_rings_status_fops);
25587ac29055SGiuseppe CAVALLARO 
25597ac29055SGiuseppe CAVALLARO 	if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
25607ac29055SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac ring debugfs file\n");
25617ac29055SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
25627ac29055SGiuseppe CAVALLARO 
25637ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
25647ac29055SGiuseppe CAVALLARO 	}
25657ac29055SGiuseppe CAVALLARO 
2566e7434821SGiuseppe CAVALLARO 	/* Entry to report the DMA HW features */
2567e7434821SGiuseppe CAVALLARO 	stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
2568e7434821SGiuseppe CAVALLARO 					     dev, &stmmac_dma_cap_fops);
2569e7434821SGiuseppe CAVALLARO 
2570e7434821SGiuseppe CAVALLARO 	if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
2571e7434821SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac MMC debugfs file\n");
2572e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_rings_status);
2573e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
2574e7434821SGiuseppe CAVALLARO 
2575e7434821SGiuseppe CAVALLARO 		return -ENOMEM;
2576e7434821SGiuseppe CAVALLARO 	}
2577e7434821SGiuseppe CAVALLARO 
25787ac29055SGiuseppe CAVALLARO 	return 0;
25797ac29055SGiuseppe CAVALLARO }
25807ac29055SGiuseppe CAVALLARO 
25817ac29055SGiuseppe CAVALLARO static void stmmac_exit_fs(void)
25827ac29055SGiuseppe CAVALLARO {
25837ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_rings_status);
2584e7434821SGiuseppe CAVALLARO 	debugfs_remove(stmmac_dma_cap);
25857ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_fs_dir);
25867ac29055SGiuseppe CAVALLARO }
25877ac29055SGiuseppe CAVALLARO #endif /* CONFIG_STMMAC_DEBUG_FS */
25887ac29055SGiuseppe CAVALLARO 
25897ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = {
25907ac6653aSJeff Kirsher 	.ndo_open = stmmac_open,
25917ac6653aSJeff Kirsher 	.ndo_start_xmit = stmmac_xmit,
25927ac6653aSJeff Kirsher 	.ndo_stop = stmmac_release,
25937ac6653aSJeff Kirsher 	.ndo_change_mtu = stmmac_change_mtu,
25947ac6653aSJeff Kirsher 	.ndo_fix_features = stmmac_fix_features,
259501789349SJiri Pirko 	.ndo_set_rx_mode = stmmac_set_rx_mode,
25967ac6653aSJeff Kirsher 	.ndo_tx_timeout = stmmac_tx_timeout,
25977ac6653aSJeff Kirsher 	.ndo_do_ioctl = stmmac_ioctl,
25987ac6653aSJeff Kirsher 	.ndo_set_config = stmmac_config,
25997ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
26007ac6653aSJeff Kirsher 	.ndo_poll_controller = stmmac_poll_controller,
26017ac6653aSJeff Kirsher #endif
26027ac6653aSJeff Kirsher 	.ndo_set_mac_address = eth_mac_addr,
26037ac6653aSJeff Kirsher };
26047ac6653aSJeff Kirsher 
26057ac6653aSJeff Kirsher /**
2606cf3f047bSGiuseppe CAVALLARO  *  stmmac_hw_init - Init the MAC device
260732ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
2608cf3f047bSGiuseppe CAVALLARO  *  Description: this function detects which MAC device
2609cf3f047bSGiuseppe CAVALLARO  *  (GMAC/MAC10-100) has to attached, checks the HW capability
2610cf3f047bSGiuseppe CAVALLARO  *  (if supported) and sets the driver's features (for example
2611cf3f047bSGiuseppe CAVALLARO  *  to use the ring or chaine mode or support the normal/enh
2612cf3f047bSGiuseppe CAVALLARO  *  descriptor structure).
2613cf3f047bSGiuseppe CAVALLARO  */
2614cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv)
2615cf3f047bSGiuseppe CAVALLARO {
2616c24602efSGiuseppe CAVALLARO 	int ret;
2617cf3f047bSGiuseppe CAVALLARO 	struct mac_device_info *mac;
2618cf3f047bSGiuseppe CAVALLARO 
2619cf3f047bSGiuseppe CAVALLARO 	/* Identify the MAC HW device */
262003f2eecdSMarc Kleine-Budde 	if (priv->plat->has_gmac) {
262103f2eecdSMarc Kleine-Budde 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
2622cf3f047bSGiuseppe CAVALLARO 		mac = dwmac1000_setup(priv->ioaddr);
262303f2eecdSMarc Kleine-Budde 	} else {
2624cf3f047bSGiuseppe CAVALLARO 		mac = dwmac100_setup(priv->ioaddr);
262503f2eecdSMarc Kleine-Budde 	}
2626cf3f047bSGiuseppe CAVALLARO 	if (!mac)
2627cf3f047bSGiuseppe CAVALLARO 		return -ENOMEM;
2628cf3f047bSGiuseppe CAVALLARO 
2629cf3f047bSGiuseppe CAVALLARO 	priv->hw = mac;
2630cf3f047bSGiuseppe CAVALLARO 
2631cf3f047bSGiuseppe CAVALLARO 	/* Get and dump the chip ID */
2632cffb13f4SGiuseppe CAVALLARO 	priv->synopsys_id = stmmac_get_synopsys_id(priv);
2633cf3f047bSGiuseppe CAVALLARO 
26344a7d666aSGiuseppe CAVALLARO 	/* To use the chained or ring mode */
26354a7d666aSGiuseppe CAVALLARO 	if (chain_mode) {
26364a7d666aSGiuseppe CAVALLARO 		priv->hw->chain = &chain_mode_ops;
26374a7d666aSGiuseppe CAVALLARO 		pr_info(" Chain mode enabled\n");
26384a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_CHAIN_MODE;
26394a7d666aSGiuseppe CAVALLARO 	} else {
26404a7d666aSGiuseppe CAVALLARO 		priv->hw->ring = &ring_mode_ops;
26414a7d666aSGiuseppe CAVALLARO 		pr_info(" Ring mode enabled\n");
26424a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_RING_MODE;
26434a7d666aSGiuseppe CAVALLARO 	}
26444a7d666aSGiuseppe CAVALLARO 
2645cf3f047bSGiuseppe CAVALLARO 	/* Get the HW capability (new GMAC newer than 3.50a) */
2646cf3f047bSGiuseppe CAVALLARO 	priv->hw_cap_support = stmmac_get_hw_features(priv);
2647cf3f047bSGiuseppe CAVALLARO 	if (priv->hw_cap_support) {
2648cf3f047bSGiuseppe CAVALLARO 		pr_info(" DMA HW capability register supported");
2649cf3f047bSGiuseppe CAVALLARO 
2650cf3f047bSGiuseppe CAVALLARO 		/* We can override some gmac/dma configuration fields: e.g.
2651cf3f047bSGiuseppe CAVALLARO 		 * enh_desc, tx_coe (e.g. that are passed through the
2652cf3f047bSGiuseppe CAVALLARO 		 * platform) with the values from the HW capability
2653cf3f047bSGiuseppe CAVALLARO 		 * register (if supported).
2654cf3f047bSGiuseppe CAVALLARO 		 */
2655cf3f047bSGiuseppe CAVALLARO 		priv->plat->enh_desc = priv->dma_cap.enh_desc;
2656cf3f047bSGiuseppe CAVALLARO 		priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
265738912bdbSDeepak SIKRI 
265838912bdbSDeepak SIKRI 		priv->plat->tx_coe = priv->dma_cap.tx_coe;
265938912bdbSDeepak SIKRI 
266038912bdbSDeepak SIKRI 		if (priv->dma_cap.rx_coe_type2)
266138912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
266238912bdbSDeepak SIKRI 		else if (priv->dma_cap.rx_coe_type1)
266338912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
266438912bdbSDeepak SIKRI 
2665cf3f047bSGiuseppe CAVALLARO 	} else
2666cf3f047bSGiuseppe CAVALLARO 		pr_info(" No HW DMA feature register supported");
2667cf3f047bSGiuseppe CAVALLARO 
266861369d02SByungho An 	/* To use alternate (extended) or normal descriptor structures */
266961369d02SByungho An 	stmmac_selec_desc_mode(priv);
267061369d02SByungho An 
267138912bdbSDeepak SIKRI 	ret = priv->hw->mac->rx_ipc(priv->ioaddr);
267238912bdbSDeepak SIKRI 	if (!ret) {
2673ceb69499SGiuseppe CAVALLARO 		pr_warn(" RX IPC Checksum Offload not configured.\n");
267438912bdbSDeepak SIKRI 		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
267538912bdbSDeepak SIKRI 	}
267638912bdbSDeepak SIKRI 
267738912bdbSDeepak SIKRI 	if (priv->plat->rx_coe)
267838912bdbSDeepak SIKRI 		pr_info(" RX Checksum Offload Engine supported (type %d)\n",
267938912bdbSDeepak SIKRI 			priv->plat->rx_coe);
2680cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->tx_coe)
2681cf3f047bSGiuseppe CAVALLARO 		pr_info(" TX Checksum insertion supported\n");
2682cf3f047bSGiuseppe CAVALLARO 
2683cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->pmt) {
2684cf3f047bSGiuseppe CAVALLARO 		pr_info(" Wake-Up On Lan supported\n");
2685cf3f047bSGiuseppe CAVALLARO 		device_set_wakeup_capable(priv->device, 1);
2686cf3f047bSGiuseppe CAVALLARO 	}
2687cf3f047bSGiuseppe CAVALLARO 
2688c24602efSGiuseppe CAVALLARO 	return 0;
2689cf3f047bSGiuseppe CAVALLARO }
2690cf3f047bSGiuseppe CAVALLARO 
2691cf3f047bSGiuseppe CAVALLARO /**
2692bfab27a1SGiuseppe CAVALLARO  * stmmac_dvr_probe
2693bfab27a1SGiuseppe CAVALLARO  * @device: device pointer
2694ff3dd78cSGiuseppe CAVALLARO  * @plat_dat: platform data pointer
2695ff3dd78cSGiuseppe CAVALLARO  * @addr: iobase memory address
2696bfab27a1SGiuseppe CAVALLARO  * Description: this is the main probe function used to
2697bfab27a1SGiuseppe CAVALLARO  * call the alloc_etherdev, allocate the priv structure.
26987ac6653aSJeff Kirsher  */
2699bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *stmmac_dvr_probe(struct device *device,
2700cf3f047bSGiuseppe CAVALLARO 				     struct plat_stmmacenet_data *plat_dat,
2701cf3f047bSGiuseppe CAVALLARO 				     void __iomem *addr)
27027ac6653aSJeff Kirsher {
27037ac6653aSJeff Kirsher 	int ret = 0;
2704bfab27a1SGiuseppe CAVALLARO 	struct net_device *ndev = NULL;
2705bfab27a1SGiuseppe CAVALLARO 	struct stmmac_priv *priv;
27067ac6653aSJeff Kirsher 
2707bfab27a1SGiuseppe CAVALLARO 	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
270841de8d4cSJoe Perches 	if (!ndev)
2709bfab27a1SGiuseppe CAVALLARO 		return NULL;
27107ac6653aSJeff Kirsher 
2711bfab27a1SGiuseppe CAVALLARO 	SET_NETDEV_DEV(ndev, device);
27127ac6653aSJeff Kirsher 
2713bfab27a1SGiuseppe CAVALLARO 	priv = netdev_priv(ndev);
2714bfab27a1SGiuseppe CAVALLARO 	priv->device = device;
2715bfab27a1SGiuseppe CAVALLARO 	priv->dev = ndev;
2716bfab27a1SGiuseppe CAVALLARO 
2717bfab27a1SGiuseppe CAVALLARO 	ether_setup(ndev);
2718bfab27a1SGiuseppe CAVALLARO 
2719bfab27a1SGiuseppe CAVALLARO 	stmmac_set_ethtool_ops(ndev);
2720cf3f047bSGiuseppe CAVALLARO 	priv->pause = pause;
2721cf3f047bSGiuseppe CAVALLARO 	priv->plat = plat_dat;
2722cf3f047bSGiuseppe CAVALLARO 	priv->ioaddr = addr;
2723cf3f047bSGiuseppe CAVALLARO 	priv->dev->base_addr = (unsigned long)addr;
2724bfab27a1SGiuseppe CAVALLARO 
2725cf3f047bSGiuseppe CAVALLARO 	/* Verify driver arguments */
2726cf3f047bSGiuseppe CAVALLARO 	stmmac_verify_args();
2727cf3f047bSGiuseppe CAVALLARO 
2728cf3f047bSGiuseppe CAVALLARO 	/* Override with kernel parameters if supplied XXX CRS XXX
2729ceb69499SGiuseppe CAVALLARO 	 * this needs to have multiple instances
2730ceb69499SGiuseppe CAVALLARO 	 */
2731cf3f047bSGiuseppe CAVALLARO 	if ((phyaddr >= 0) && (phyaddr <= 31))
2732cf3f047bSGiuseppe CAVALLARO 		priv->plat->phy_addr = phyaddr;
2733cf3f047bSGiuseppe CAVALLARO 
273462866e98SChen-Yu Tsai 	priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
273562866e98SChen-Yu Tsai 	if (IS_ERR(priv->stmmac_clk)) {
273662866e98SChen-Yu Tsai 		dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
273762866e98SChen-Yu Tsai 			 __func__);
2738c5e4ddbdSChen-Yu Tsai 		ret = PTR_ERR(priv->stmmac_clk);
273962866e98SChen-Yu Tsai 		goto error_clk_get;
274062866e98SChen-Yu Tsai 	}
274162866e98SChen-Yu Tsai 	clk_prepare_enable(priv->stmmac_clk);
274262866e98SChen-Yu Tsai 
2743c5e4ddbdSChen-Yu Tsai 	priv->stmmac_rst = devm_reset_control_get(priv->device,
2744c5e4ddbdSChen-Yu Tsai 						  STMMAC_RESOURCE_NAME);
2745c5e4ddbdSChen-Yu Tsai 	if (IS_ERR(priv->stmmac_rst)) {
2746c5e4ddbdSChen-Yu Tsai 		if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
2747c5e4ddbdSChen-Yu Tsai 			ret = -EPROBE_DEFER;
2748c5e4ddbdSChen-Yu Tsai 			goto error_hw_init;
2749c5e4ddbdSChen-Yu Tsai 		}
2750c5e4ddbdSChen-Yu Tsai 		dev_info(priv->device, "no reset control found\n");
2751c5e4ddbdSChen-Yu Tsai 		priv->stmmac_rst = NULL;
2752c5e4ddbdSChen-Yu Tsai 	}
2753c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2754c5e4ddbdSChen-Yu Tsai 		reset_control_deassert(priv->stmmac_rst);
2755c5e4ddbdSChen-Yu Tsai 
2756cf3f047bSGiuseppe CAVALLARO 	/* Init MAC and get the capabilities */
2757c24602efSGiuseppe CAVALLARO 	ret = stmmac_hw_init(priv);
2758c24602efSGiuseppe CAVALLARO 	if (ret)
275962866e98SChen-Yu Tsai 		goto error_hw_init;
2760cf3f047bSGiuseppe CAVALLARO 
2761cf3f047bSGiuseppe CAVALLARO 	ndev->netdev_ops = &stmmac_netdev_ops;
2762cf3f047bSGiuseppe CAVALLARO 
2763cf3f047bSGiuseppe CAVALLARO 	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
2764cf3f047bSGiuseppe CAVALLARO 			    NETIF_F_RXCSUM;
2765bfab27a1SGiuseppe CAVALLARO 	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
2766bfab27a1SGiuseppe CAVALLARO 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
27677ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED
27687ac6653aSJeff Kirsher 	/* Both mac100 and gmac support receive VLAN tag detection */
2769f646968fSPatrick McHardy 	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
27707ac6653aSJeff Kirsher #endif
27717ac6653aSJeff Kirsher 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
27727ac6653aSJeff Kirsher 
27737ac6653aSJeff Kirsher 	if (flow_ctrl)
27747ac6653aSJeff Kirsher 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
27757ac6653aSJeff Kirsher 
277662a2ab93SGiuseppe CAVALLARO 	/* Rx Watchdog is available in the COREs newer than the 3.40.
277762a2ab93SGiuseppe CAVALLARO 	 * In some case, for example on bugged HW this feature
277862a2ab93SGiuseppe CAVALLARO 	 * has to be disable and this can be done by passing the
277962a2ab93SGiuseppe CAVALLARO 	 * riwt_off field from the platform.
278062a2ab93SGiuseppe CAVALLARO 	 */
278162a2ab93SGiuseppe CAVALLARO 	if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
278262a2ab93SGiuseppe CAVALLARO 		priv->use_riwt = 1;
278362a2ab93SGiuseppe CAVALLARO 		pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
278462a2ab93SGiuseppe CAVALLARO 	}
278562a2ab93SGiuseppe CAVALLARO 
2786bfab27a1SGiuseppe CAVALLARO 	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
27877ac6653aSJeff Kirsher 
27887ac6653aSJeff Kirsher 	spin_lock_init(&priv->lock);
2789a9097a96SGiuseppe CAVALLARO 	spin_lock_init(&priv->tx_lock);
27907ac6653aSJeff Kirsher 
2791bfab27a1SGiuseppe CAVALLARO 	ret = register_netdev(ndev);
27927ac6653aSJeff Kirsher 	if (ret) {
2793cf3f047bSGiuseppe CAVALLARO 		pr_err("%s: ERROR %i registering the device\n", __func__, ret);
27946a81c26fSViresh Kumar 		goto error_netdev_register;
27957ac6653aSJeff Kirsher 	}
27967ac6653aSJeff Kirsher 
2797cd7201f4SGiuseppe CAVALLARO 	/* If a specific clk_csr value is passed from the platform
2798cd7201f4SGiuseppe CAVALLARO 	 * this means that the CSR Clock Range selection cannot be
2799cd7201f4SGiuseppe CAVALLARO 	 * changed at run-time and it is fixed. Viceversa the driver'll try to
2800cd7201f4SGiuseppe CAVALLARO 	 * set the MDC clock dynamically according to the csr actual
2801cd7201f4SGiuseppe CAVALLARO 	 * clock input.
2802cd7201f4SGiuseppe CAVALLARO 	 */
2803cd7201f4SGiuseppe CAVALLARO 	if (!priv->plat->clk_csr)
2804cd7201f4SGiuseppe CAVALLARO 		stmmac_clk_csr_set(priv);
2805cd7201f4SGiuseppe CAVALLARO 	else
2806cd7201f4SGiuseppe CAVALLARO 		priv->clk_csr = priv->plat->clk_csr;
2807cd7201f4SGiuseppe CAVALLARO 
2808e58bb43fSGiuseppe CAVALLARO 	stmmac_check_pcs_mode(priv);
2809e58bb43fSGiuseppe CAVALLARO 
28104d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
28114d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
28124bfcbd7aSFrancesco Virlinzi 		/* MDIO bus Registration */
28134bfcbd7aSFrancesco Virlinzi 		ret = stmmac_mdio_register(ndev);
28144bfcbd7aSFrancesco Virlinzi 		if (ret < 0) {
28154bfcbd7aSFrancesco Virlinzi 			pr_debug("%s: MDIO bus (id: %d) registration failed",
28164bfcbd7aSFrancesco Virlinzi 				 __func__, priv->plat->bus_id);
28176a81c26fSViresh Kumar 			goto error_mdio_register;
28184bfcbd7aSFrancesco Virlinzi 		}
2819e58bb43fSGiuseppe CAVALLARO 	}
28204bfcbd7aSFrancesco Virlinzi 
2821bfab27a1SGiuseppe CAVALLARO 	return priv;
28227ac6653aSJeff Kirsher 
28236a81c26fSViresh Kumar error_mdio_register:
28247ac6653aSJeff Kirsher 	unregister_netdev(ndev);
28256a81c26fSViresh Kumar error_netdev_register:
28266a81c26fSViresh Kumar 	netif_napi_del(&priv->napi);
282762866e98SChen-Yu Tsai error_hw_init:
282862866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
282962866e98SChen-Yu Tsai error_clk_get:
28307ac6653aSJeff Kirsher 	free_netdev(ndev);
28317ac6653aSJeff Kirsher 
2832c5e4ddbdSChen-Yu Tsai 	return ERR_PTR(ret);
28337ac6653aSJeff Kirsher }
28347ac6653aSJeff Kirsher 
28357ac6653aSJeff Kirsher /**
28367ac6653aSJeff Kirsher  * stmmac_dvr_remove
2837bfab27a1SGiuseppe CAVALLARO  * @ndev: net device pointer
28387ac6653aSJeff Kirsher  * Description: this function resets the TX/RX processes, disables the MAC RX/TX
2839bfab27a1SGiuseppe CAVALLARO  * changes the link status, releases the DMA descriptor rings.
28407ac6653aSJeff Kirsher  */
2841bfab27a1SGiuseppe CAVALLARO int stmmac_dvr_remove(struct net_device *ndev)
28427ac6653aSJeff Kirsher {
28437ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
28447ac6653aSJeff Kirsher 
28457ac6653aSJeff Kirsher 	pr_info("%s:\n\tremoving driver", __func__);
28467ac6653aSJeff Kirsher 
28477ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
28487ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
28497ac6653aSJeff Kirsher 
2850bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
28514d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
28524d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI)
28534bfcbd7aSFrancesco Virlinzi 		stmmac_mdio_unregister(ndev);
28547ac6653aSJeff Kirsher 	netif_carrier_off(ndev);
28557ac6653aSJeff Kirsher 	unregister_netdev(ndev);
2856c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2857c5e4ddbdSChen-Yu Tsai 		reset_control_assert(priv->stmmac_rst);
285862866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
28597ac6653aSJeff Kirsher 	free_netdev(ndev);
28607ac6653aSJeff Kirsher 
28617ac6653aSJeff Kirsher 	return 0;
28627ac6653aSJeff Kirsher }
28637ac6653aSJeff Kirsher 
28647ac6653aSJeff Kirsher #ifdef CONFIG_PM
2865bfab27a1SGiuseppe CAVALLARO int stmmac_suspend(struct net_device *ndev)
28667ac6653aSJeff Kirsher {
28677ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2868f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
28697ac6653aSJeff Kirsher 
28707ac6653aSJeff Kirsher 	if (!ndev || !netif_running(ndev))
28717ac6653aSJeff Kirsher 		return 0;
28727ac6653aSJeff Kirsher 
2873102463b1SFrancesco Virlinzi 	if (priv->phydev)
2874102463b1SFrancesco Virlinzi 		phy_stop(priv->phydev);
2875102463b1SFrancesco Virlinzi 
2876f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
28777ac6653aSJeff Kirsher 
28787ac6653aSJeff Kirsher 	netif_device_detach(ndev);
28797ac6653aSJeff Kirsher 	netif_stop_queue(ndev);
28807ac6653aSJeff Kirsher 
28817ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
28827ac6653aSJeff Kirsher 
28837ac6653aSJeff Kirsher 	/* Stop TX/RX DMA */
28847ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
28857ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
2886c24602efSGiuseppe CAVALLARO 
2887c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
28887ac6653aSJeff Kirsher 
28897ac6653aSJeff Kirsher 	/* Enable Power down mode by programming the PMT regs */
289089f7f2cfSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
28917ac6653aSJeff Kirsher 		priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
289289f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 1;
289389f7f2cfSSrinivas Kandagatla 	} else {
2894bfab27a1SGiuseppe CAVALLARO 		stmmac_set_mac(priv->ioaddr, false);
2895db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_sleep_state(priv->device);
2896ba1377ffSGiuseppe CAVALLARO 		/* Disable clock in case of PWM is off */
2897a630844dSStefan Roese 		clk_disable_unprepare(priv->stmmac_clk);
2898ba1377ffSGiuseppe CAVALLARO 	}
2899f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
29007ac6653aSJeff Kirsher 	return 0;
29017ac6653aSJeff Kirsher }
29027ac6653aSJeff Kirsher 
2903bfab27a1SGiuseppe CAVALLARO int stmmac_resume(struct net_device *ndev)
29047ac6653aSJeff Kirsher {
29057ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2906f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
29077ac6653aSJeff Kirsher 
29087ac6653aSJeff Kirsher 	if (!netif_running(ndev))
29097ac6653aSJeff Kirsher 		return 0;
29107ac6653aSJeff Kirsher 
2911f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
29127ac6653aSJeff Kirsher 
29137ac6653aSJeff Kirsher 	/* Power Down bit, into the PM register, is cleared
29147ac6653aSJeff Kirsher 	 * automatically as soon as a magic packet or a Wake-up frame
29157ac6653aSJeff Kirsher 	 * is received. Anyway, it's better to manually clear
29167ac6653aSJeff Kirsher 	 * this bit because it can generate problems while resuming
2917ceb69499SGiuseppe CAVALLARO 	 * from another devices (e.g. serial console).
2918ceb69499SGiuseppe CAVALLARO 	 */
2919623997fbSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
29207ac6653aSJeff Kirsher 		priv->hw->mac->pmt(priv->ioaddr, 0);
292189f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 0;
2922623997fbSSrinivas Kandagatla 	} else {
2923db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_default_state(priv->device);
2924ba1377ffSGiuseppe CAVALLARO 		/* enable the clk prevously disabled */
2925a630844dSStefan Roese 		clk_prepare_enable(priv->stmmac_clk);
2926623997fbSSrinivas Kandagatla 		/* reset the phy so that it's ready */
2927623997fbSSrinivas Kandagatla 		if (priv->mii)
2928623997fbSSrinivas Kandagatla 			stmmac_mdio_reset(priv->mii);
2929623997fbSSrinivas Kandagatla 	}
29307ac6653aSJeff Kirsher 
29317ac6653aSJeff Kirsher 	netif_device_attach(ndev);
29327ac6653aSJeff Kirsher 
2933623997fbSSrinivas Kandagatla 	stmmac_hw_setup(ndev);
29347ac6653aSJeff Kirsher 
29357ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
29367ac6653aSJeff Kirsher 
29377ac6653aSJeff Kirsher 	netif_start_queue(ndev);
29387ac6653aSJeff Kirsher 
2939f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
2940102463b1SFrancesco Virlinzi 
2941102463b1SFrancesco Virlinzi 	if (priv->phydev)
2942102463b1SFrancesco Virlinzi 		phy_start(priv->phydev);
2943102463b1SFrancesco Virlinzi 
29447ac6653aSJeff Kirsher 	return 0;
29457ac6653aSJeff Kirsher }
29467ac6653aSJeff Kirsher #endif /* CONFIG_PM */
29477ac6653aSJeff Kirsher 
294833d5e332SGiuseppe CAVALLARO /* Driver can be configured w/ and w/ both PCI and Platf drivers
294933d5e332SGiuseppe CAVALLARO  * depending on the configuration selected.
295033d5e332SGiuseppe CAVALLARO  */
2951ba27ec66SGiuseppe CAVALLARO static int __init stmmac_init(void)
2952ba27ec66SGiuseppe CAVALLARO {
2953493682b8SKonstantin Khlebnikov 	int ret;
2954ba27ec66SGiuseppe CAVALLARO 
2955493682b8SKonstantin Khlebnikov 	ret = stmmac_register_platform();
2956493682b8SKonstantin Khlebnikov 	if (ret)
2957493682b8SKonstantin Khlebnikov 		goto err;
2958493682b8SKonstantin Khlebnikov 	ret = stmmac_register_pci();
2959493682b8SKonstantin Khlebnikov 	if (ret)
2960493682b8SKonstantin Khlebnikov 		goto err_pci;
296133d5e332SGiuseppe CAVALLARO 	return 0;
2962493682b8SKonstantin Khlebnikov err_pci:
2963493682b8SKonstantin Khlebnikov 	stmmac_unregister_platform();
2964493682b8SKonstantin Khlebnikov err:
2965493682b8SKonstantin Khlebnikov 	pr_err("stmmac: driver registration failed\n");
2966493682b8SKonstantin Khlebnikov 	return ret;
2967ba27ec66SGiuseppe CAVALLARO }
2968ba27ec66SGiuseppe CAVALLARO 
2969ba27ec66SGiuseppe CAVALLARO static void __exit stmmac_exit(void)
2970ba27ec66SGiuseppe CAVALLARO {
297133d5e332SGiuseppe CAVALLARO 	stmmac_unregister_platform();
297233d5e332SGiuseppe CAVALLARO 	stmmac_unregister_pci();
2973ba27ec66SGiuseppe CAVALLARO }
2974ba27ec66SGiuseppe CAVALLARO 
2975ba27ec66SGiuseppe CAVALLARO module_init(stmmac_init);
2976ba27ec66SGiuseppe CAVALLARO module_exit(stmmac_exit);
2977ba27ec66SGiuseppe CAVALLARO 
29787ac6653aSJeff Kirsher #ifndef MODULE
29797ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str)
29807ac6653aSJeff Kirsher {
29817ac6653aSJeff Kirsher 	char *opt;
29827ac6653aSJeff Kirsher 
29837ac6653aSJeff Kirsher 	if (!str || !*str)
29847ac6653aSJeff Kirsher 		return -EINVAL;
29857ac6653aSJeff Kirsher 	while ((opt = strsep(&str, ",")) != NULL) {
29867ac6653aSJeff Kirsher 		if (!strncmp(opt, "debug:", 6)) {
2987ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &debug))
29887ac6653aSJeff Kirsher 				goto err;
29897ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "phyaddr:", 8)) {
2990ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 8, 0, &phyaddr))
29917ac6653aSJeff Kirsher 				goto err;
29927ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_txsize:", 11)) {
2993ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_txsize))
29947ac6653aSJeff Kirsher 				goto err;
29957ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_rxsize:", 11)) {
2996ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_rxsize))
29977ac6653aSJeff Kirsher 				goto err;
29987ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "buf_sz:", 7)) {
2999ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 7, 0, &buf_sz))
30007ac6653aSJeff Kirsher 				goto err;
30017ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "tc:", 3)) {
3002ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 3, 0, &tc))
30037ac6653aSJeff Kirsher 				goto err;
30047ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "watchdog:", 9)) {
3005ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 9, 0, &watchdog))
30067ac6653aSJeff Kirsher 				goto err;
30077ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "flow_ctrl:", 10)) {
3008ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &flow_ctrl))
30097ac6653aSJeff Kirsher 				goto err;
30107ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "pause:", 6)) {
3011ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &pause))
30127ac6653aSJeff Kirsher 				goto err;
3013506f669cSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "eee_timer:", 10)) {
3014d765955dSGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &eee_timer))
3015d765955dSGiuseppe CAVALLARO 				goto err;
30164a7d666aSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "chain_mode:", 11)) {
30174a7d666aSGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &chain_mode))
30184a7d666aSGiuseppe CAVALLARO 				goto err;
30197ac6653aSJeff Kirsher 		}
30207ac6653aSJeff Kirsher 	}
30217ac6653aSJeff Kirsher 	return 0;
30227ac6653aSJeff Kirsher 
30237ac6653aSJeff Kirsher err:
30247ac6653aSJeff Kirsher 	pr_err("%s: ERROR broken module parameter conversion", __func__);
30257ac6653aSJeff Kirsher 	return -EINVAL;
30267ac6653aSJeff Kirsher }
30277ac6653aSJeff Kirsher 
30287ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt);
3029ceb69499SGiuseppe CAVALLARO #endif /* MODULE */
30306fc0d0f2SGiuseppe Cavallaro 
30316fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
30326fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
30336fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL");
3034