17ac6653aSJeff Kirsher /*******************************************************************************
27ac6653aSJeff Kirsher   This is the driver for the ST MAC 10/100/1000 on-chip Ethernet controllers.
37ac6653aSJeff Kirsher   ST Ethernet IPs are built around a Synopsys IP Core.
47ac6653aSJeff Kirsher 
5286a8372SGiuseppe CAVALLARO 	Copyright(C) 2007-2011 STMicroelectronics Ltd
67ac6653aSJeff Kirsher 
77ac6653aSJeff Kirsher   This program is free software; you can redistribute it and/or modify it
87ac6653aSJeff Kirsher   under the terms and conditions of the GNU General Public License,
97ac6653aSJeff Kirsher   version 2, as published by the Free Software Foundation.
107ac6653aSJeff Kirsher 
117ac6653aSJeff Kirsher   This program is distributed in the hope it will be useful, but WITHOUT
127ac6653aSJeff Kirsher   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
137ac6653aSJeff Kirsher   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
147ac6653aSJeff Kirsher   more details.
157ac6653aSJeff Kirsher 
167ac6653aSJeff Kirsher   You should have received a copy of the GNU General Public License along with
177ac6653aSJeff Kirsher   this program; if not, write to the Free Software Foundation, Inc.,
187ac6653aSJeff Kirsher   51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
197ac6653aSJeff Kirsher 
207ac6653aSJeff Kirsher   The full GNU General Public License is included in this distribution in
217ac6653aSJeff Kirsher   the file called "COPYING".
227ac6653aSJeff Kirsher 
237ac6653aSJeff Kirsher   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
247ac6653aSJeff Kirsher 
257ac6653aSJeff Kirsher   Documentation available at:
267ac6653aSJeff Kirsher 	http://www.stlinux.com
277ac6653aSJeff Kirsher   Support available at:
287ac6653aSJeff Kirsher 	https://bugzilla.stlinux.com/
297ac6653aSJeff Kirsher *******************************************************************************/
307ac6653aSJeff Kirsher 
316a81c26fSViresh Kumar #include <linux/clk.h>
327ac6653aSJeff Kirsher #include <linux/kernel.h>
337ac6653aSJeff Kirsher #include <linux/interrupt.h>
347ac6653aSJeff Kirsher #include <linux/ip.h>
357ac6653aSJeff Kirsher #include <linux/tcp.h>
367ac6653aSJeff Kirsher #include <linux/skbuff.h>
377ac6653aSJeff Kirsher #include <linux/ethtool.h>
387ac6653aSJeff Kirsher #include <linux/if_ether.h>
397ac6653aSJeff Kirsher #include <linux/crc32.h>
407ac6653aSJeff Kirsher #include <linux/mii.h>
4101789349SJiri Pirko #include <linux/if.h>
427ac6653aSJeff Kirsher #include <linux/if_vlan.h>
437ac6653aSJeff Kirsher #include <linux/dma-mapping.h>
447ac6653aSJeff Kirsher #include <linux/slab.h>
457ac6653aSJeff Kirsher #include <linux/prefetch.h>
46db88f10aSSrinivas Kandagatla #include <linux/pinctrl/consumer.h>
477ac29055SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_DEBUG_FS
487ac29055SGiuseppe CAVALLARO #include <linux/debugfs.h>
497ac29055SGiuseppe CAVALLARO #include <linux/seq_file.h>
50ceb69499SGiuseppe CAVALLARO #endif /* CONFIG_STMMAC_DEBUG_FS */
51891434b1SRayagond Kokatanur #include <linux/net_tstamp.h>
52891434b1SRayagond Kokatanur #include "stmmac_ptp.h"
53286a8372SGiuseppe CAVALLARO #include "stmmac.h"
54c5e4ddbdSChen-Yu Tsai #include <linux/reset.h>
557ac6653aSJeff Kirsher 
567ac6653aSJeff Kirsher #define STMMAC_ALIGN(x)	L1_CACHE_ALIGN(x)
577ac6653aSJeff Kirsher 
587ac6653aSJeff Kirsher /* Module parameters */
5932ceabcaSGiuseppe CAVALLARO #define TX_TIMEO	5000
607ac6653aSJeff Kirsher static int watchdog = TX_TIMEO;
617ac6653aSJeff Kirsher module_param(watchdog, int, S_IRUGO | S_IWUSR);
6232ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(watchdog, "Transmit timeout in milliseconds (default 5s)");
637ac6653aSJeff Kirsher 
6432ceabcaSGiuseppe CAVALLARO static int debug = -1;
657ac6653aSJeff Kirsher module_param(debug, int, S_IRUGO | S_IWUSR);
6632ceabcaSGiuseppe CAVALLARO MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)");
677ac6653aSJeff Kirsher 
6847d1f71fSstephen hemminger static int phyaddr = -1;
697ac6653aSJeff Kirsher module_param(phyaddr, int, S_IRUGO);
707ac6653aSJeff Kirsher MODULE_PARM_DESC(phyaddr, "Physical device address");
717ac6653aSJeff Kirsher 
727ac6653aSJeff Kirsher #define DMA_TX_SIZE 256
737ac6653aSJeff Kirsher static int dma_txsize = DMA_TX_SIZE;
747ac6653aSJeff Kirsher module_param(dma_txsize, int, S_IRUGO | S_IWUSR);
757ac6653aSJeff Kirsher MODULE_PARM_DESC(dma_txsize, "Number of descriptors in the TX list");
767ac6653aSJeff Kirsher 
777ac6653aSJeff Kirsher #define DMA_RX_SIZE 256
787ac6653aSJeff Kirsher static int dma_rxsize = DMA_RX_SIZE;
797ac6653aSJeff Kirsher module_param(dma_rxsize, int, S_IRUGO | S_IWUSR);
807ac6653aSJeff Kirsher MODULE_PARM_DESC(dma_rxsize, "Number of descriptors in the RX list");
817ac6653aSJeff Kirsher 
827ac6653aSJeff Kirsher static int flow_ctrl = FLOW_OFF;
837ac6653aSJeff Kirsher module_param(flow_ctrl, int, S_IRUGO | S_IWUSR);
847ac6653aSJeff Kirsher MODULE_PARM_DESC(flow_ctrl, "Flow control ability [on/off]");
857ac6653aSJeff Kirsher 
867ac6653aSJeff Kirsher static int pause = PAUSE_TIME;
877ac6653aSJeff Kirsher module_param(pause, int, S_IRUGO | S_IWUSR);
887ac6653aSJeff Kirsher MODULE_PARM_DESC(pause, "Flow Control Pause Time");
897ac6653aSJeff Kirsher 
907ac6653aSJeff Kirsher #define TC_DEFAULT 64
917ac6653aSJeff Kirsher static int tc = TC_DEFAULT;
927ac6653aSJeff Kirsher module_param(tc, int, S_IRUGO | S_IWUSR);
937ac6653aSJeff Kirsher MODULE_PARM_DESC(tc, "DMA threshold control value");
947ac6653aSJeff Kirsher 
95d916701cSGiuseppe CAVALLARO #define	DEFAULT_BUFSIZE	1536
96d916701cSGiuseppe CAVALLARO static int buf_sz = DEFAULT_BUFSIZE;
977ac6653aSJeff Kirsher module_param(buf_sz, int, S_IRUGO | S_IWUSR);
987ac6653aSJeff Kirsher MODULE_PARM_DESC(buf_sz, "DMA buffer size");
997ac6653aSJeff Kirsher 
1007ac6653aSJeff Kirsher static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
1017ac6653aSJeff Kirsher 				      NETIF_MSG_LINK | NETIF_MSG_IFUP |
1027ac6653aSJeff Kirsher 				      NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
1037ac6653aSJeff Kirsher 
104d765955dSGiuseppe CAVALLARO #define STMMAC_DEFAULT_LPI_TIMER	1000
105d765955dSGiuseppe CAVALLARO static int eee_timer = STMMAC_DEFAULT_LPI_TIMER;
106d765955dSGiuseppe CAVALLARO module_param(eee_timer, int, S_IRUGO | S_IWUSR);
107d765955dSGiuseppe CAVALLARO MODULE_PARM_DESC(eee_timer, "LPI tx expiration time in msec");
108f5351ef7SGiuseppe CAVALLARO #define STMMAC_LPI_T(x) (jiffies + msecs_to_jiffies(x))
109d765955dSGiuseppe CAVALLARO 
1104a7d666aSGiuseppe CAVALLARO /* By default the driver will use the ring mode to manage tx and rx descriptors
1114a7d666aSGiuseppe CAVALLARO  * but passing this value so user can force to use the chain instead of the ring
1124a7d666aSGiuseppe CAVALLARO  */
1134a7d666aSGiuseppe CAVALLARO static unsigned int chain_mode;
1144a7d666aSGiuseppe CAVALLARO module_param(chain_mode, int, S_IRUGO);
1154a7d666aSGiuseppe CAVALLARO MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode");
1164a7d666aSGiuseppe CAVALLARO 
1177ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
1187ac6653aSJeff Kirsher 
119bfab27a1SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_DEBUG_FS
120bfab27a1SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev);
121bfab27a1SGiuseppe CAVALLARO static void stmmac_exit_fs(void);
122bfab27a1SGiuseppe CAVALLARO #endif
123bfab27a1SGiuseppe CAVALLARO 
1249125cdd1SGiuseppe CAVALLARO #define STMMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
1259125cdd1SGiuseppe CAVALLARO 
1267ac6653aSJeff Kirsher /**
1277ac6653aSJeff Kirsher  * stmmac_verify_args - verify the driver parameters.
1287ac6653aSJeff Kirsher  * Description: it verifies if some wrong parameter is passed to the driver.
1297ac6653aSJeff Kirsher  * Note that wrong parameters are replaced with the default values.
1307ac6653aSJeff Kirsher  */
1317ac6653aSJeff Kirsher static void stmmac_verify_args(void)
1327ac6653aSJeff Kirsher {
1337ac6653aSJeff Kirsher 	if (unlikely(watchdog < 0))
1347ac6653aSJeff Kirsher 		watchdog = TX_TIMEO;
1357ac6653aSJeff Kirsher 	if (unlikely(dma_rxsize < 0))
1367ac6653aSJeff Kirsher 		dma_rxsize = DMA_RX_SIZE;
1377ac6653aSJeff Kirsher 	if (unlikely(dma_txsize < 0))
1387ac6653aSJeff Kirsher 		dma_txsize = DMA_TX_SIZE;
139d916701cSGiuseppe CAVALLARO 	if (unlikely((buf_sz < DEFAULT_BUFSIZE) || (buf_sz > BUF_SIZE_16KiB)))
140d916701cSGiuseppe CAVALLARO 		buf_sz = DEFAULT_BUFSIZE;
1417ac6653aSJeff Kirsher 	if (unlikely(flow_ctrl > 1))
1427ac6653aSJeff Kirsher 		flow_ctrl = FLOW_AUTO;
1437ac6653aSJeff Kirsher 	else if (likely(flow_ctrl < 0))
1447ac6653aSJeff Kirsher 		flow_ctrl = FLOW_OFF;
1457ac6653aSJeff Kirsher 	if (unlikely((pause < 0) || (pause > 0xffff)))
1467ac6653aSJeff Kirsher 		pause = PAUSE_TIME;
147d765955dSGiuseppe CAVALLARO 	if (eee_timer < 0)
148d765955dSGiuseppe CAVALLARO 		eee_timer = STMMAC_DEFAULT_LPI_TIMER;
1497ac6653aSJeff Kirsher }
1507ac6653aSJeff Kirsher 
15132ceabcaSGiuseppe CAVALLARO /**
15232ceabcaSGiuseppe CAVALLARO  * stmmac_clk_csr_set - dynamically set the MDC clock
15332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
15432ceabcaSGiuseppe CAVALLARO  * Description: this is to dynamically set the MDC clock according to the csr
15532ceabcaSGiuseppe CAVALLARO  * clock input.
15632ceabcaSGiuseppe CAVALLARO  * Note:
15732ceabcaSGiuseppe CAVALLARO  *	If a specific clk_csr value is passed from the platform
15832ceabcaSGiuseppe CAVALLARO  *	this means that the CSR Clock Range selection cannot be
15932ceabcaSGiuseppe CAVALLARO  *	changed at run-time and it is fixed (as reported in the driver
16032ceabcaSGiuseppe CAVALLARO  *	documentation). Viceversa the driver will try to set the MDC
16132ceabcaSGiuseppe CAVALLARO  *	clock dynamically according to the actual clock input.
16232ceabcaSGiuseppe CAVALLARO  */
163cd7201f4SGiuseppe CAVALLARO static void stmmac_clk_csr_set(struct stmmac_priv *priv)
164cd7201f4SGiuseppe CAVALLARO {
165cd7201f4SGiuseppe CAVALLARO 	u32 clk_rate;
166cd7201f4SGiuseppe CAVALLARO 
167cd7201f4SGiuseppe CAVALLARO 	clk_rate = clk_get_rate(priv->stmmac_clk);
168cd7201f4SGiuseppe CAVALLARO 
169cd7201f4SGiuseppe CAVALLARO 	/* Platform provided default clk_csr would be assumed valid
170ceb69499SGiuseppe CAVALLARO 	 * for all other cases except for the below mentioned ones.
171ceb69499SGiuseppe CAVALLARO 	 * For values higher than the IEEE 802.3 specified frequency
172ceb69499SGiuseppe CAVALLARO 	 * we can not estimate the proper divider as it is not known
173ceb69499SGiuseppe CAVALLARO 	 * the frequency of clk_csr_i. So we do not change the default
174ceb69499SGiuseppe CAVALLARO 	 * divider.
175ceb69499SGiuseppe CAVALLARO 	 */
176cd7201f4SGiuseppe CAVALLARO 	if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) {
177cd7201f4SGiuseppe CAVALLARO 		if (clk_rate < CSR_F_35M)
178cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_20_35M;
179cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M))
180cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_35_60M;
181cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M))
182cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_60_100M;
183cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M))
184cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_100_150M;
185cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M))
186cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_150_250M;
187cd7201f4SGiuseppe CAVALLARO 		else if ((clk_rate >= CSR_F_250M) && (clk_rate < CSR_F_300M))
188cd7201f4SGiuseppe CAVALLARO 			priv->clk_csr = STMMAC_CSR_250_300M;
189ceb69499SGiuseppe CAVALLARO 	}
190cd7201f4SGiuseppe CAVALLARO }
191cd7201f4SGiuseppe CAVALLARO 
1927ac6653aSJeff Kirsher static void print_pkt(unsigned char *buf, int len)
1937ac6653aSJeff Kirsher {
1947ac6653aSJeff Kirsher 	int j;
19583d7af64SGiuseppe CAVALLARO 	pr_debug("len = %d byte, buf addr: 0x%p", len, buf);
1967ac6653aSJeff Kirsher 	for (j = 0; j < len; j++) {
1977ac6653aSJeff Kirsher 		if ((j % 16) == 0)
19883d7af64SGiuseppe CAVALLARO 			pr_debug("\n %03x:", j);
19983d7af64SGiuseppe CAVALLARO 		pr_debug(" %02x", buf[j]);
2007ac6653aSJeff Kirsher 	}
20183d7af64SGiuseppe CAVALLARO 	pr_debug("\n");
2027ac6653aSJeff Kirsher }
2037ac6653aSJeff Kirsher 
2047ac6653aSJeff Kirsher /* minimum number of free TX descriptors required to wake up TX process */
2057ac6653aSJeff Kirsher #define STMMAC_TX_THRESH(x)	(x->dma_tx_size/4)
2067ac6653aSJeff Kirsher 
2077ac6653aSJeff Kirsher static inline u32 stmmac_tx_avail(struct stmmac_priv *priv)
2087ac6653aSJeff Kirsher {
2097ac6653aSJeff Kirsher 	return priv->dirty_tx + priv->dma_tx_size - priv->cur_tx - 1;
2107ac6653aSJeff Kirsher }
2117ac6653aSJeff Kirsher 
21232ceabcaSGiuseppe CAVALLARO /**
21332ceabcaSGiuseppe CAVALLARO  * stmmac_hw_fix_mac_speed: callback for speed selection
21432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
21532ceabcaSGiuseppe CAVALLARO  * Description: on some platforms (e.g. ST), some HW system configuraton
21632ceabcaSGiuseppe CAVALLARO  * registers have to be set according to the link speed negotiated.
2177ac6653aSJeff Kirsher  */
2187ac6653aSJeff Kirsher static inline void stmmac_hw_fix_mac_speed(struct stmmac_priv *priv)
2197ac6653aSJeff Kirsher {
2207ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
2217ac6653aSJeff Kirsher 
2227ac6653aSJeff Kirsher 	if (likely(priv->plat->fix_mac_speed))
223ceb69499SGiuseppe CAVALLARO 		priv->plat->fix_mac_speed(priv->plat->bsp_priv, phydev->speed);
2247ac6653aSJeff Kirsher }
2257ac6653aSJeff Kirsher 
22632ceabcaSGiuseppe CAVALLARO /**
22732ceabcaSGiuseppe CAVALLARO  * stmmac_enable_eee_mode: Check and enter in LPI mode
22832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
22932ceabcaSGiuseppe CAVALLARO  * Description: this function is to verify and enter in LPI mode for EEE.
23032ceabcaSGiuseppe CAVALLARO  */
231d765955dSGiuseppe CAVALLARO static void stmmac_enable_eee_mode(struct stmmac_priv *priv)
232d765955dSGiuseppe CAVALLARO {
233d765955dSGiuseppe CAVALLARO 	/* Check and enter in LPI mode */
234d765955dSGiuseppe CAVALLARO 	if ((priv->dirty_tx == priv->cur_tx) &&
235d765955dSGiuseppe CAVALLARO 	    (priv->tx_path_in_lpi_mode == false))
2367ed24bbeSVince Bridgers 		priv->hw->mac->set_eee_mode(priv->hw);
237d765955dSGiuseppe CAVALLARO }
238d765955dSGiuseppe CAVALLARO 
23932ceabcaSGiuseppe CAVALLARO /**
24032ceabcaSGiuseppe CAVALLARO  * stmmac_disable_eee_mode: disable/exit from EEE
24132ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
24232ceabcaSGiuseppe CAVALLARO  * Description: this function is to exit and disable EEE in case of
24332ceabcaSGiuseppe CAVALLARO  * LPI state is true. This is called by the xmit.
24432ceabcaSGiuseppe CAVALLARO  */
245d765955dSGiuseppe CAVALLARO void stmmac_disable_eee_mode(struct stmmac_priv *priv)
246d765955dSGiuseppe CAVALLARO {
2477ed24bbeSVince Bridgers 	priv->hw->mac->reset_eee_mode(priv->hw);
248d765955dSGiuseppe CAVALLARO 	del_timer_sync(&priv->eee_ctrl_timer);
249d765955dSGiuseppe CAVALLARO 	priv->tx_path_in_lpi_mode = false;
250d765955dSGiuseppe CAVALLARO }
251d765955dSGiuseppe CAVALLARO 
252d765955dSGiuseppe CAVALLARO /**
25332ceabcaSGiuseppe CAVALLARO  * stmmac_eee_ctrl_timer: EEE TX SW timer.
254d765955dSGiuseppe CAVALLARO  * @arg : data hook
255d765955dSGiuseppe CAVALLARO  * Description:
25632ceabcaSGiuseppe CAVALLARO  *  if there is no data transfer and if we are not in LPI state,
257d765955dSGiuseppe CAVALLARO  *  then MAC Transmitter can be moved to LPI state.
258d765955dSGiuseppe CAVALLARO  */
259d765955dSGiuseppe CAVALLARO static void stmmac_eee_ctrl_timer(unsigned long arg)
260d765955dSGiuseppe CAVALLARO {
261d765955dSGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)arg;
262d765955dSGiuseppe CAVALLARO 
263d765955dSGiuseppe CAVALLARO 	stmmac_enable_eee_mode(priv);
264f5351ef7SGiuseppe CAVALLARO 	mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
265d765955dSGiuseppe CAVALLARO }
266d765955dSGiuseppe CAVALLARO 
267d765955dSGiuseppe CAVALLARO /**
26832ceabcaSGiuseppe CAVALLARO  * stmmac_eee_init: init EEE
26932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
270d765955dSGiuseppe CAVALLARO  * Description:
271d765955dSGiuseppe CAVALLARO  *  If the EEE support has been enabled while configuring the driver,
272d765955dSGiuseppe CAVALLARO  *  if the GMAC actually supports the EEE (from the HW cap reg) and the
273d765955dSGiuseppe CAVALLARO  *  phy can also manage EEE, so enable the LPI state and start the timer
274d765955dSGiuseppe CAVALLARO  *  to verify if the tx path can enter in LPI state.
275d765955dSGiuseppe CAVALLARO  */
276d765955dSGiuseppe CAVALLARO bool stmmac_eee_init(struct stmmac_priv *priv)
277d765955dSGiuseppe CAVALLARO {
27856b88c25SGiuseppe CAVALLARO 	char *phy_bus_name = priv->plat->phy_bus_name;
279d765955dSGiuseppe CAVALLARO 	bool ret = false;
280d765955dSGiuseppe CAVALLARO 
281f5351ef7SGiuseppe CAVALLARO 	/* Using PCS we cannot dial with the phy registers at this stage
282f5351ef7SGiuseppe CAVALLARO 	 * so we do not support extra feature like EEE.
283f5351ef7SGiuseppe CAVALLARO 	 */
284f5351ef7SGiuseppe CAVALLARO 	if ((priv->pcs == STMMAC_PCS_RGMII) || (priv->pcs == STMMAC_PCS_TBI) ||
285f5351ef7SGiuseppe CAVALLARO 	    (priv->pcs == STMMAC_PCS_RTBI))
286f5351ef7SGiuseppe CAVALLARO 		goto out;
287f5351ef7SGiuseppe CAVALLARO 
28856b88c25SGiuseppe CAVALLARO 	/* Never init EEE in case of a switch is attached */
28956b88c25SGiuseppe CAVALLARO 	if (phy_bus_name && (!strcmp(phy_bus_name, "fixed")))
29056b88c25SGiuseppe CAVALLARO 		goto out;
29156b88c25SGiuseppe CAVALLARO 
292d765955dSGiuseppe CAVALLARO 	/* MAC core supports the EEE feature. */
293d765955dSGiuseppe CAVALLARO 	if (priv->dma_cap.eee) {
29483bf79b6SGiuseppe CAVALLARO 		int tx_lpi_timer = priv->tx_lpi_timer;
295d765955dSGiuseppe CAVALLARO 
29683bf79b6SGiuseppe CAVALLARO 		/* Check if the PHY supports EEE */
29783bf79b6SGiuseppe CAVALLARO 		if (phy_init_eee(priv->phydev, 1)) {
29883bf79b6SGiuseppe CAVALLARO 			/* To manage at run-time if the EEE cannot be supported
29983bf79b6SGiuseppe CAVALLARO 			 * anymore (for example because the lp caps have been
30083bf79b6SGiuseppe CAVALLARO 			 * changed).
30183bf79b6SGiuseppe CAVALLARO 			 * In that case the driver disable own timers.
30283bf79b6SGiuseppe CAVALLARO 			 */
30383bf79b6SGiuseppe CAVALLARO 			if (priv->eee_active) {
30483bf79b6SGiuseppe CAVALLARO 				pr_debug("stmmac: disable EEE\n");
30583bf79b6SGiuseppe CAVALLARO 				del_timer_sync(&priv->eee_ctrl_timer);
3067ed24bbeSVince Bridgers 				priv->hw->mac->set_eee_timer(priv->hw, 0,
30783bf79b6SGiuseppe CAVALLARO 							     tx_lpi_timer);
30883bf79b6SGiuseppe CAVALLARO 			}
30983bf79b6SGiuseppe CAVALLARO 			priv->eee_active = 0;
31083bf79b6SGiuseppe CAVALLARO 			goto out;
31183bf79b6SGiuseppe CAVALLARO 		}
31283bf79b6SGiuseppe CAVALLARO 		/* Activate the EEE and start timers */
313f5351ef7SGiuseppe CAVALLARO 		if (!priv->eee_active) {
314d765955dSGiuseppe CAVALLARO 			priv->eee_active = 1;
315d765955dSGiuseppe CAVALLARO 			init_timer(&priv->eee_ctrl_timer);
316d765955dSGiuseppe CAVALLARO 			priv->eee_ctrl_timer.function = stmmac_eee_ctrl_timer;
317d765955dSGiuseppe CAVALLARO 			priv->eee_ctrl_timer.data = (unsigned long)priv;
318f5351ef7SGiuseppe CAVALLARO 			priv->eee_ctrl_timer.expires = STMMAC_LPI_T(eee_timer);
319d765955dSGiuseppe CAVALLARO 			add_timer(&priv->eee_ctrl_timer);
320d765955dSGiuseppe CAVALLARO 
3217ed24bbeSVince Bridgers 			priv->hw->mac->set_eee_timer(priv->hw,
322f5351ef7SGiuseppe CAVALLARO 						     STMMAC_DEFAULT_LIT_LS,
32383bf79b6SGiuseppe CAVALLARO 						     tx_lpi_timer);
32471965352SGiuseppe CAVALLARO 		}
325f5351ef7SGiuseppe CAVALLARO 		/* Set HW EEE according to the speed */
32671965352SGiuseppe CAVALLARO 		priv->hw->mac->set_eee_pls(priv->hw, priv->phydev->link);
327d765955dSGiuseppe CAVALLARO 
32883bf79b6SGiuseppe CAVALLARO 		pr_debug("stmmac: Energy-Efficient Ethernet initialized\n");
329d765955dSGiuseppe CAVALLARO 
330d765955dSGiuseppe CAVALLARO 		ret = true;
331d765955dSGiuseppe CAVALLARO 	}
332d765955dSGiuseppe CAVALLARO out:
333d765955dSGiuseppe CAVALLARO 	return ret;
334d765955dSGiuseppe CAVALLARO }
335d765955dSGiuseppe CAVALLARO 
33632ceabcaSGiuseppe CAVALLARO /* stmmac_get_tx_hwtstamp: get HW TX timestamps
33732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
338891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
339891434b1SRayagond Kokatanur  * @skb : the socket buffer
340891434b1SRayagond Kokatanur  * Description :
341891434b1SRayagond Kokatanur  * This function will read timestamp from the descriptor & pass it to stack.
342891434b1SRayagond Kokatanur  * and also perform some sanity checks.
343891434b1SRayagond Kokatanur  */
344891434b1SRayagond Kokatanur static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
345ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
346891434b1SRayagond Kokatanur {
347891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps shhwtstamp;
348891434b1SRayagond Kokatanur 	u64 ns;
349891434b1SRayagond Kokatanur 	void *desc = NULL;
350891434b1SRayagond Kokatanur 
351891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
352891434b1SRayagond Kokatanur 		return;
353891434b1SRayagond Kokatanur 
354ceb69499SGiuseppe CAVALLARO 	/* exit if skb doesn't support hw tstamp */
35575e4364fSdamuzi000 	if (likely(!skb || !(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)))
356891434b1SRayagond Kokatanur 		return;
357891434b1SRayagond Kokatanur 
358891434b1SRayagond Kokatanur 	if (priv->adv_ts)
359891434b1SRayagond Kokatanur 		desc = (priv->dma_etx + entry);
360891434b1SRayagond Kokatanur 	else
361891434b1SRayagond Kokatanur 		desc = (priv->dma_tx + entry);
362891434b1SRayagond Kokatanur 
363891434b1SRayagond Kokatanur 	/* check tx tstamp status */
364891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_tx_timestamp_status((struct dma_desc *)desc))
365891434b1SRayagond Kokatanur 		return;
366891434b1SRayagond Kokatanur 
367891434b1SRayagond Kokatanur 	/* get the valid tstamp */
368891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
369891434b1SRayagond Kokatanur 
370891434b1SRayagond Kokatanur 	memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
371891434b1SRayagond Kokatanur 	shhwtstamp.hwtstamp = ns_to_ktime(ns);
372891434b1SRayagond Kokatanur 	/* pass tstamp to stack */
373891434b1SRayagond Kokatanur 	skb_tstamp_tx(skb, &shhwtstamp);
374891434b1SRayagond Kokatanur 
375891434b1SRayagond Kokatanur 	return;
376891434b1SRayagond Kokatanur }
377891434b1SRayagond Kokatanur 
37832ceabcaSGiuseppe CAVALLARO /* stmmac_get_rx_hwtstamp: get HW RX timestamps
37932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
380891434b1SRayagond Kokatanur  * @entry : descriptor index to be used.
381891434b1SRayagond Kokatanur  * @skb : the socket buffer
382891434b1SRayagond Kokatanur  * Description :
383891434b1SRayagond Kokatanur  * This function will read received packet's timestamp from the descriptor
384891434b1SRayagond Kokatanur  * and pass it to stack. It also perform some sanity checks.
385891434b1SRayagond Kokatanur  */
386891434b1SRayagond Kokatanur static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv,
387ceb69499SGiuseppe CAVALLARO 				   unsigned int entry, struct sk_buff *skb)
388891434b1SRayagond Kokatanur {
389891434b1SRayagond Kokatanur 	struct skb_shared_hwtstamps *shhwtstamp = NULL;
390891434b1SRayagond Kokatanur 	u64 ns;
391891434b1SRayagond Kokatanur 	void *desc = NULL;
392891434b1SRayagond Kokatanur 
393891434b1SRayagond Kokatanur 	if (!priv->hwts_rx_en)
394891434b1SRayagond Kokatanur 		return;
395891434b1SRayagond Kokatanur 
396891434b1SRayagond Kokatanur 	if (priv->adv_ts)
397891434b1SRayagond Kokatanur 		desc = (priv->dma_erx + entry);
398891434b1SRayagond Kokatanur 	else
399891434b1SRayagond Kokatanur 		desc = (priv->dma_rx + entry);
400891434b1SRayagond Kokatanur 
401ceb69499SGiuseppe CAVALLARO 	/* exit if rx tstamp is not valid */
402891434b1SRayagond Kokatanur 	if (!priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts))
403891434b1SRayagond Kokatanur 		return;
404891434b1SRayagond Kokatanur 
405891434b1SRayagond Kokatanur 	/* get valid tstamp */
406891434b1SRayagond Kokatanur 	ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts);
407891434b1SRayagond Kokatanur 	shhwtstamp = skb_hwtstamps(skb);
408891434b1SRayagond Kokatanur 	memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
409891434b1SRayagond Kokatanur 	shhwtstamp->hwtstamp = ns_to_ktime(ns);
410891434b1SRayagond Kokatanur }
411891434b1SRayagond Kokatanur 
412891434b1SRayagond Kokatanur /**
413891434b1SRayagond Kokatanur  *  stmmac_hwtstamp_ioctl - control hardware timestamping.
414891434b1SRayagond Kokatanur  *  @dev: device pointer.
415891434b1SRayagond Kokatanur  *  @ifr: An IOCTL specefic structure, that can contain a pointer to
416891434b1SRayagond Kokatanur  *  a proprietary structure used to pass information to the driver.
417891434b1SRayagond Kokatanur  *  Description:
418891434b1SRayagond Kokatanur  *  This function configures the MAC to enable/disable both outgoing(TX)
419891434b1SRayagond Kokatanur  *  and incoming(RX) packets time stamping based on user input.
420891434b1SRayagond Kokatanur  *  Return Value:
421891434b1SRayagond Kokatanur  *  0 on success and an appropriate -ve integer on failure.
422891434b1SRayagond Kokatanur  */
423891434b1SRayagond Kokatanur static int stmmac_hwtstamp_ioctl(struct net_device *dev, struct ifreq *ifr)
424891434b1SRayagond Kokatanur {
425891434b1SRayagond Kokatanur 	struct stmmac_priv *priv = netdev_priv(dev);
426891434b1SRayagond Kokatanur 	struct hwtstamp_config config;
427891434b1SRayagond Kokatanur 	struct timespec now;
428891434b1SRayagond Kokatanur 	u64 temp = 0;
429891434b1SRayagond Kokatanur 	u32 ptp_v2 = 0;
430891434b1SRayagond Kokatanur 	u32 tstamp_all = 0;
431891434b1SRayagond Kokatanur 	u32 ptp_over_ipv4_udp = 0;
432891434b1SRayagond Kokatanur 	u32 ptp_over_ipv6_udp = 0;
433891434b1SRayagond Kokatanur 	u32 ptp_over_ethernet = 0;
434891434b1SRayagond Kokatanur 	u32 snap_type_sel = 0;
435891434b1SRayagond Kokatanur 	u32 ts_master_en = 0;
436891434b1SRayagond Kokatanur 	u32 ts_event_en = 0;
437891434b1SRayagond Kokatanur 	u32 value = 0;
438891434b1SRayagond Kokatanur 
439891434b1SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->adv_ts)) {
440891434b1SRayagond Kokatanur 		netdev_alert(priv->dev, "No support for HW time stamping\n");
441891434b1SRayagond Kokatanur 		priv->hwts_tx_en = 0;
442891434b1SRayagond Kokatanur 		priv->hwts_rx_en = 0;
443891434b1SRayagond Kokatanur 
444891434b1SRayagond Kokatanur 		return -EOPNOTSUPP;
445891434b1SRayagond Kokatanur 	}
446891434b1SRayagond Kokatanur 
447891434b1SRayagond Kokatanur 	if (copy_from_user(&config, ifr->ifr_data,
448891434b1SRayagond Kokatanur 			   sizeof(struct hwtstamp_config)))
449891434b1SRayagond Kokatanur 		return -EFAULT;
450891434b1SRayagond Kokatanur 
451891434b1SRayagond Kokatanur 	pr_debug("%s config flags:0x%x, tx_type:0x%x, rx_filter:0x%x\n",
452891434b1SRayagond Kokatanur 		 __func__, config.flags, config.tx_type, config.rx_filter);
453891434b1SRayagond Kokatanur 
454891434b1SRayagond Kokatanur 	/* reserved for future extensions */
455891434b1SRayagond Kokatanur 	if (config.flags)
456891434b1SRayagond Kokatanur 		return -EINVAL;
457891434b1SRayagond Kokatanur 
4585f3da328SBen Hutchings 	if (config.tx_type != HWTSTAMP_TX_OFF &&
4595f3da328SBen Hutchings 	    config.tx_type != HWTSTAMP_TX_ON)
460891434b1SRayagond Kokatanur 		return -ERANGE;
461891434b1SRayagond Kokatanur 
462891434b1SRayagond Kokatanur 	if (priv->adv_ts) {
463891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
464891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
465ceb69499SGiuseppe CAVALLARO 			/* time stamp no incoming packet at all */
466891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
467891434b1SRayagond Kokatanur 			break;
468891434b1SRayagond Kokatanur 
469891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
470ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, any kind of event packet */
471891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
472891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
473891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
474891434b1SRayagond Kokatanur 
475891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
476891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
477891434b1SRayagond Kokatanur 			break;
478891434b1SRayagond Kokatanur 
479891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
480ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Sync packet */
481891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_SYNC;
482891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
483891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
484891434b1SRayagond Kokatanur 
485891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
486891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
487891434b1SRayagond Kokatanur 			break;
488891434b1SRayagond Kokatanur 
489891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
490ceb69499SGiuseppe CAVALLARO 			/* PTP v1, UDP, Delay_req packet */
491891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ;
492891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
493891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
494891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
495891434b1SRayagond Kokatanur 
496891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
497891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
498891434b1SRayagond Kokatanur 			break;
499891434b1SRayagond Kokatanur 
500891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
501ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, any kind of event packet */
502891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT;
503891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
504891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
505891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
506891434b1SRayagond Kokatanur 
507891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
508891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
509891434b1SRayagond Kokatanur 			break;
510891434b1SRayagond Kokatanur 
511891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
512ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Sync packet */
513891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_SYNC;
514891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
515891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
516891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
517891434b1SRayagond Kokatanur 
518891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
519891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
520891434b1SRayagond Kokatanur 			break;
521891434b1SRayagond Kokatanur 
522891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
523ceb69499SGiuseppe CAVALLARO 			/* PTP v2, UDP, Delay_req packet */
524891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ;
525891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
526891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
527891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
528891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
529891434b1SRayagond Kokatanur 
530891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
531891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
532891434b1SRayagond Kokatanur 			break;
533891434b1SRayagond Kokatanur 
534891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_EVENT:
535ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1 any layer, any kind of event packet */
536891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT;
537891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
538891434b1SRayagond Kokatanur 			/* take time stamp for all event messages */
539891434b1SRayagond Kokatanur 			snap_type_sel = PTP_TCR_SNAPTYPSEL_1;
540891434b1SRayagond Kokatanur 
541891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
542891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
543891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
544891434b1SRayagond Kokatanur 			break;
545891434b1SRayagond Kokatanur 
546891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_SYNC:
547ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Sync packet */
548891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_SYNC;
549891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
550891434b1SRayagond Kokatanur 			/* take time stamp for SYNC messages only */
551891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
552891434b1SRayagond Kokatanur 
553891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
554891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
555891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
556891434b1SRayagond Kokatanur 			break;
557891434b1SRayagond Kokatanur 
558891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
559ceb69499SGiuseppe CAVALLARO 			/* PTP v2/802.AS1, any layer, Delay_req packet */
560891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V2_DELAY_REQ;
561891434b1SRayagond Kokatanur 			ptp_v2 = PTP_TCR_TSVER2ENA;
562891434b1SRayagond Kokatanur 			/* take time stamp for Delay_Req messages only */
563891434b1SRayagond Kokatanur 			ts_master_en = PTP_TCR_TSMSTRENA;
564891434b1SRayagond Kokatanur 			ts_event_en = PTP_TCR_TSEVNTENA;
565891434b1SRayagond Kokatanur 
566891434b1SRayagond Kokatanur 			ptp_over_ipv4_udp = PTP_TCR_TSIPV4ENA;
567891434b1SRayagond Kokatanur 			ptp_over_ipv6_udp = PTP_TCR_TSIPV6ENA;
568891434b1SRayagond Kokatanur 			ptp_over_ethernet = PTP_TCR_TSIPENA;
569891434b1SRayagond Kokatanur 			break;
570891434b1SRayagond Kokatanur 
571891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_ALL:
572ceb69499SGiuseppe CAVALLARO 			/* time stamp any incoming packet */
573891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_ALL;
574891434b1SRayagond Kokatanur 			tstamp_all = PTP_TCR_TSENALL;
575891434b1SRayagond Kokatanur 			break;
576891434b1SRayagond Kokatanur 
577891434b1SRayagond Kokatanur 		default:
578891434b1SRayagond Kokatanur 			return -ERANGE;
579891434b1SRayagond Kokatanur 		}
580891434b1SRayagond Kokatanur 	} else {
581891434b1SRayagond Kokatanur 		switch (config.rx_filter) {
582891434b1SRayagond Kokatanur 		case HWTSTAMP_FILTER_NONE:
583891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_NONE;
584891434b1SRayagond Kokatanur 			break;
585891434b1SRayagond Kokatanur 		default:
586891434b1SRayagond Kokatanur 			/* PTP v1, UDP, any kind of event packet */
587891434b1SRayagond Kokatanur 			config.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT;
588891434b1SRayagond Kokatanur 			break;
589891434b1SRayagond Kokatanur 		}
590891434b1SRayagond Kokatanur 	}
591891434b1SRayagond Kokatanur 	priv->hwts_rx_en = ((config.rx_filter == HWTSTAMP_FILTER_NONE) ? 0 : 1);
5925f3da328SBen Hutchings 	priv->hwts_tx_en = config.tx_type == HWTSTAMP_TX_ON;
593891434b1SRayagond Kokatanur 
594891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en && !priv->hwts_rx_en)
595891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, 0);
596891434b1SRayagond Kokatanur 	else {
597891434b1SRayagond Kokatanur 		value = (PTP_TCR_TSENA | PTP_TCR_TSCFUPDT | PTP_TCR_TSCTRLSSR |
598891434b1SRayagond Kokatanur 			 tstamp_all | ptp_v2 | ptp_over_ethernet |
599891434b1SRayagond Kokatanur 			 ptp_over_ipv6_udp | ptp_over_ipv4_udp | ts_event_en |
600891434b1SRayagond Kokatanur 			 ts_master_en | snap_type_sel);
601891434b1SRayagond Kokatanur 
602891434b1SRayagond Kokatanur 		priv->hw->ptp->config_hw_tstamping(priv->ioaddr, value);
603891434b1SRayagond Kokatanur 
604891434b1SRayagond Kokatanur 		/* program Sub Second Increment reg */
605891434b1SRayagond Kokatanur 		priv->hw->ptp->config_sub_second_increment(priv->ioaddr);
606891434b1SRayagond Kokatanur 
607891434b1SRayagond Kokatanur 		/* calculate default added value:
608891434b1SRayagond Kokatanur 		 * formula is :
609891434b1SRayagond Kokatanur 		 * addend = (2^32)/freq_div_ratio;
6105566401fSGiuseppe CAVALLARO 		 * where, freq_div_ratio = clk_ptp_ref_i/50MHz
6115566401fSGiuseppe CAVALLARO 		 * hence, addend = ((2^32) * 50MHz)/clk_ptp_ref_i;
6125566401fSGiuseppe CAVALLARO 		 * NOTE: clk_ptp_ref_i should be >= 50MHz to
613891434b1SRayagond Kokatanur 		 *       achive 20ns accuracy.
614891434b1SRayagond Kokatanur 		 *
615891434b1SRayagond Kokatanur 		 * 2^x * y == (y << x), hence
616891434b1SRayagond Kokatanur 		 * 2^32 * 50000000 ==> (50000000 << 32)
617891434b1SRayagond Kokatanur 		 */
618891434b1SRayagond Kokatanur 		temp = (u64) (50000000ULL << 32);
6195566401fSGiuseppe CAVALLARO 		priv->default_addend = div_u64(temp, priv->clk_ptp_rate);
620891434b1SRayagond Kokatanur 		priv->hw->ptp->config_addend(priv->ioaddr,
621891434b1SRayagond Kokatanur 					     priv->default_addend);
622891434b1SRayagond Kokatanur 
623891434b1SRayagond Kokatanur 		/* initialize system time */
624891434b1SRayagond Kokatanur 		getnstimeofday(&now);
625891434b1SRayagond Kokatanur 		priv->hw->ptp->init_systime(priv->ioaddr, now.tv_sec,
626891434b1SRayagond Kokatanur 					    now.tv_nsec);
627891434b1SRayagond Kokatanur 	}
628891434b1SRayagond Kokatanur 
629891434b1SRayagond Kokatanur 	return copy_to_user(ifr->ifr_data, &config,
630891434b1SRayagond Kokatanur 			    sizeof(struct hwtstamp_config)) ? -EFAULT : 0;
631891434b1SRayagond Kokatanur }
632891434b1SRayagond Kokatanur 
63332ceabcaSGiuseppe CAVALLARO /**
63432ceabcaSGiuseppe CAVALLARO  * stmmac_init_ptp: init PTP
63532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
63632ceabcaSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PTPv1 or v2.
63732ceabcaSGiuseppe CAVALLARO  * This is done by looking at the HW cap. register.
63832ceabcaSGiuseppe CAVALLARO  * Also it registers the ptp driver.
63932ceabcaSGiuseppe CAVALLARO  */
64092ba6888SRayagond Kokatanur static int stmmac_init_ptp(struct stmmac_priv *priv)
641891434b1SRayagond Kokatanur {
64292ba6888SRayagond Kokatanur 	if (!(priv->dma_cap.time_stamp || priv->dma_cap.atime_stamp))
64392ba6888SRayagond Kokatanur 		return -EOPNOTSUPP;
64492ba6888SRayagond Kokatanur 
6455566401fSGiuseppe CAVALLARO 	/* Fall-back to main clock in case of no PTP ref is passed */
6465566401fSGiuseppe CAVALLARO 	priv->clk_ptp_ref = devm_clk_get(priv->device, "clk_ptp_ref");
6475566401fSGiuseppe CAVALLARO 	if (IS_ERR(priv->clk_ptp_ref)) {
6485566401fSGiuseppe CAVALLARO 		priv->clk_ptp_rate = clk_get_rate(priv->stmmac_clk);
6495566401fSGiuseppe CAVALLARO 		priv->clk_ptp_ref = NULL;
6505566401fSGiuseppe CAVALLARO 	} else {
6515566401fSGiuseppe CAVALLARO 		clk_prepare_enable(priv->clk_ptp_ref);
6525566401fSGiuseppe CAVALLARO 		priv->clk_ptp_rate = clk_get_rate(priv->clk_ptp_ref);
6535566401fSGiuseppe CAVALLARO 	}
6545566401fSGiuseppe CAVALLARO 
655891434b1SRayagond Kokatanur 	priv->adv_ts = 0;
6567cd01399SVince Bridgers 	if (priv->dma_cap.atime_stamp && priv->extend_desc)
657891434b1SRayagond Kokatanur 		priv->adv_ts = 1;
6587cd01399SVince Bridgers 
6597cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->dma_cap.time_stamp)
6607cd01399SVince Bridgers 		pr_debug("IEEE 1588-2002 Time Stamp supported\n");
6617cd01399SVince Bridgers 
6627cd01399SVince Bridgers 	if (netif_msg_hw(priv) && priv->adv_ts)
6637cd01399SVince Bridgers 		pr_debug("IEEE 1588-2008 Advanced Time Stamp supported\n");
664891434b1SRayagond Kokatanur 
665891434b1SRayagond Kokatanur 	priv->hw->ptp = &stmmac_ptp;
666891434b1SRayagond Kokatanur 	priv->hwts_tx_en = 0;
667891434b1SRayagond Kokatanur 	priv->hwts_rx_en = 0;
66892ba6888SRayagond Kokatanur 
66992ba6888SRayagond Kokatanur 	return stmmac_ptp_register(priv);
67092ba6888SRayagond Kokatanur }
67192ba6888SRayagond Kokatanur 
67292ba6888SRayagond Kokatanur static void stmmac_release_ptp(struct stmmac_priv *priv)
67392ba6888SRayagond Kokatanur {
6745566401fSGiuseppe CAVALLARO 	if (priv->clk_ptp_ref)
6755566401fSGiuseppe CAVALLARO 		clk_disable_unprepare(priv->clk_ptp_ref);
67692ba6888SRayagond Kokatanur 	stmmac_ptp_unregister(priv);
677891434b1SRayagond Kokatanur }
678891434b1SRayagond Kokatanur 
6797ac6653aSJeff Kirsher /**
6807ac6653aSJeff Kirsher  * stmmac_adjust_link
6817ac6653aSJeff Kirsher  * @dev: net device structure
6827ac6653aSJeff Kirsher  * Description: it adjusts the link parameters.
6837ac6653aSJeff Kirsher  */
6847ac6653aSJeff Kirsher static void stmmac_adjust_link(struct net_device *dev)
6857ac6653aSJeff Kirsher {
6867ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
6877ac6653aSJeff Kirsher 	struct phy_device *phydev = priv->phydev;
6887ac6653aSJeff Kirsher 	unsigned long flags;
6897ac6653aSJeff Kirsher 	int new_state = 0;
6907ac6653aSJeff Kirsher 	unsigned int fc = priv->flow_ctrl, pause_time = priv->pause;
6917ac6653aSJeff Kirsher 
6927ac6653aSJeff Kirsher 	if (phydev == NULL)
6937ac6653aSJeff Kirsher 		return;
6947ac6653aSJeff Kirsher 
6957ac6653aSJeff Kirsher 	spin_lock_irqsave(&priv->lock, flags);
696d765955dSGiuseppe CAVALLARO 
6977ac6653aSJeff Kirsher 	if (phydev->link) {
6987ac6653aSJeff Kirsher 		u32 ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
6997ac6653aSJeff Kirsher 
7007ac6653aSJeff Kirsher 		/* Now we make sure that we can be in full duplex mode.
7017ac6653aSJeff Kirsher 		 * If not, we operate in half-duplex mode. */
7027ac6653aSJeff Kirsher 		if (phydev->duplex != priv->oldduplex) {
7037ac6653aSJeff Kirsher 			new_state = 1;
7047ac6653aSJeff Kirsher 			if (!(phydev->duplex))
7057ac6653aSJeff Kirsher 				ctrl &= ~priv->hw->link.duplex;
7067ac6653aSJeff Kirsher 			else
7077ac6653aSJeff Kirsher 				ctrl |= priv->hw->link.duplex;
7087ac6653aSJeff Kirsher 			priv->oldduplex = phydev->duplex;
7097ac6653aSJeff Kirsher 		}
7107ac6653aSJeff Kirsher 		/* Flow Control operation */
7117ac6653aSJeff Kirsher 		if (phydev->pause)
7127ed24bbeSVince Bridgers 			priv->hw->mac->flow_ctrl(priv->hw, phydev->duplex,
7137ac6653aSJeff Kirsher 						 fc, pause_time);
7147ac6653aSJeff Kirsher 
7157ac6653aSJeff Kirsher 		if (phydev->speed != priv->speed) {
7167ac6653aSJeff Kirsher 			new_state = 1;
7177ac6653aSJeff Kirsher 			switch (phydev->speed) {
7187ac6653aSJeff Kirsher 			case 1000:
7197ac6653aSJeff Kirsher 				if (likely(priv->plat->has_gmac))
7207ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7217ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7227ac6653aSJeff Kirsher 				break;
7237ac6653aSJeff Kirsher 			case 100:
7247ac6653aSJeff Kirsher 			case 10:
7257ac6653aSJeff Kirsher 				if (priv->plat->has_gmac) {
7267ac6653aSJeff Kirsher 					ctrl |= priv->hw->link.port;
7277ac6653aSJeff Kirsher 					if (phydev->speed == SPEED_100) {
7287ac6653aSJeff Kirsher 						ctrl |= priv->hw->link.speed;
7297ac6653aSJeff Kirsher 					} else {
7307ac6653aSJeff Kirsher 						ctrl &= ~(priv->hw->link.speed);
7317ac6653aSJeff Kirsher 					}
7327ac6653aSJeff Kirsher 				} else {
7337ac6653aSJeff Kirsher 					ctrl &= ~priv->hw->link.port;
7347ac6653aSJeff Kirsher 				}
7357ac6653aSJeff Kirsher 				stmmac_hw_fix_mac_speed(priv);
7367ac6653aSJeff Kirsher 				break;
7377ac6653aSJeff Kirsher 			default:
7387ac6653aSJeff Kirsher 				if (netif_msg_link(priv))
739ceb69499SGiuseppe CAVALLARO 					pr_warn("%s: Speed (%d) not 10/100\n",
740ceb69499SGiuseppe CAVALLARO 						dev->name, phydev->speed);
7417ac6653aSJeff Kirsher 				break;
7427ac6653aSJeff Kirsher 			}
7437ac6653aSJeff Kirsher 
7447ac6653aSJeff Kirsher 			priv->speed = phydev->speed;
7457ac6653aSJeff Kirsher 		}
7467ac6653aSJeff Kirsher 
7477ac6653aSJeff Kirsher 		writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
7487ac6653aSJeff Kirsher 
7497ac6653aSJeff Kirsher 		if (!priv->oldlink) {
7507ac6653aSJeff Kirsher 			new_state = 1;
7517ac6653aSJeff Kirsher 			priv->oldlink = 1;
7527ac6653aSJeff Kirsher 		}
7537ac6653aSJeff Kirsher 	} else if (priv->oldlink) {
7547ac6653aSJeff Kirsher 		new_state = 1;
7557ac6653aSJeff Kirsher 		priv->oldlink = 0;
7567ac6653aSJeff Kirsher 		priv->speed = 0;
7577ac6653aSJeff Kirsher 		priv->oldduplex = -1;
7587ac6653aSJeff Kirsher 	}
7597ac6653aSJeff Kirsher 
7607ac6653aSJeff Kirsher 	if (new_state && netif_msg_link(priv))
7617ac6653aSJeff Kirsher 		phy_print_status(phydev);
7627ac6653aSJeff Kirsher 
763f5351ef7SGiuseppe CAVALLARO 	/* At this stage, it could be needed to setup the EEE or adjust some
764f5351ef7SGiuseppe CAVALLARO 	 * MAC related HW registers.
765f5351ef7SGiuseppe CAVALLARO 	 */
766f5351ef7SGiuseppe CAVALLARO 	priv->eee_enabled = stmmac_eee_init(priv);
767d765955dSGiuseppe CAVALLARO 
7687ac6653aSJeff Kirsher 	spin_unlock_irqrestore(&priv->lock, flags);
7697ac6653aSJeff Kirsher }
7707ac6653aSJeff Kirsher 
77132ceabcaSGiuseppe CAVALLARO /**
77232ceabcaSGiuseppe CAVALLARO  * stmmac_check_pcs_mode: verify if RGMII/SGMII is supported
77332ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
77432ceabcaSGiuseppe CAVALLARO  * Description: this is to verify if the HW supports the PCS.
77532ceabcaSGiuseppe CAVALLARO  * Physical Coding Sublayer (PCS) interface that can be used when the MAC is
77632ceabcaSGiuseppe CAVALLARO  * configured for the TBI, RTBI, or SGMII PHY interface.
77732ceabcaSGiuseppe CAVALLARO  */
778e58bb43fSGiuseppe CAVALLARO static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
779e58bb43fSGiuseppe CAVALLARO {
780e58bb43fSGiuseppe CAVALLARO 	int interface = priv->plat->interface;
781e58bb43fSGiuseppe CAVALLARO 
782e58bb43fSGiuseppe CAVALLARO 	if (priv->dma_cap.pcs) {
7830d909dcdSByungho An 		if ((interface == PHY_INTERFACE_MODE_RGMII) ||
7840d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_ID) ||
7850d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
7860d909dcdSByungho An 		    (interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
787e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS RGMII support enable\n");
788e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_RGMII;
7890d909dcdSByungho An 		} else if (interface == PHY_INTERFACE_MODE_SGMII) {
790e58bb43fSGiuseppe CAVALLARO 			pr_debug("STMMAC: PCS SGMII support enable\n");
791e58bb43fSGiuseppe CAVALLARO 			priv->pcs = STMMAC_PCS_SGMII;
792e58bb43fSGiuseppe CAVALLARO 		}
793e58bb43fSGiuseppe CAVALLARO 	}
794e58bb43fSGiuseppe CAVALLARO }
795e58bb43fSGiuseppe CAVALLARO 
7967ac6653aSJeff Kirsher /**
7977ac6653aSJeff Kirsher  * stmmac_init_phy - PHY initialization
7987ac6653aSJeff Kirsher  * @dev: net device structure
7997ac6653aSJeff Kirsher  * Description: it initializes the driver's PHY state, and attaches the PHY
8007ac6653aSJeff Kirsher  * to the mac driver.
8017ac6653aSJeff Kirsher  *  Return value:
8027ac6653aSJeff Kirsher  *  0 on success
8037ac6653aSJeff Kirsher  */
8047ac6653aSJeff Kirsher static int stmmac_init_phy(struct net_device *dev)
8057ac6653aSJeff Kirsher {
8067ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
8077ac6653aSJeff Kirsher 	struct phy_device *phydev;
808d765955dSGiuseppe CAVALLARO 	char phy_id_fmt[MII_BUS_ID_SIZE + 3];
8097ac6653aSJeff Kirsher 	char bus_id[MII_BUS_ID_SIZE];
81079ee1dc3SSrinivas Kandagatla 	int interface = priv->plat->interface;
8119cbadf09SSrinivas Kandagatla 	int max_speed = priv->plat->max_speed;
8127ac6653aSJeff Kirsher 	priv->oldlink = 0;
8137ac6653aSJeff Kirsher 	priv->speed = 0;
8147ac6653aSJeff Kirsher 	priv->oldduplex = -1;
8157ac6653aSJeff Kirsher 
816f142af2eSSrinivas Kandagatla 	if (priv->plat->phy_bus_name)
817f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x",
818f142af2eSSrinivas Kandagatla 			 priv->plat->phy_bus_name, priv->plat->bus_id);
819f142af2eSSrinivas Kandagatla 	else
820f142af2eSSrinivas Kandagatla 		snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x",
821f142af2eSSrinivas Kandagatla 			 priv->plat->bus_id);
822f142af2eSSrinivas Kandagatla 
823d765955dSGiuseppe CAVALLARO 	snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id,
8247ac6653aSJeff Kirsher 		 priv->plat->phy_addr);
825d765955dSGiuseppe CAVALLARO 	pr_debug("stmmac_init_phy:  trying to attach to %s\n", phy_id_fmt);
8267ac6653aSJeff Kirsher 
827f9a8f83bSFlorian Fainelli 	phydev = phy_connect(dev, phy_id_fmt, &stmmac_adjust_link, interface);
8287ac6653aSJeff Kirsher 
8297ac6653aSJeff Kirsher 	if (IS_ERR(phydev)) {
8307ac6653aSJeff Kirsher 		pr_err("%s: Could not attach to PHY\n", dev->name);
8317ac6653aSJeff Kirsher 		return PTR_ERR(phydev);
8327ac6653aSJeff Kirsher 	}
8337ac6653aSJeff Kirsher 
83479ee1dc3SSrinivas Kandagatla 	/* Stop Advertising 1000BASE Capability if interface is not GMII */
835c5b9b4e4SSrinivas Kandagatla 	if ((interface == PHY_INTERFACE_MODE_MII) ||
8369cbadf09SSrinivas Kandagatla 	    (interface == PHY_INTERFACE_MODE_RMII) ||
8379cbadf09SSrinivas Kandagatla 		(max_speed < 1000 && max_speed > 0))
838c5b9b4e4SSrinivas Kandagatla 		phydev->advertising &= ~(SUPPORTED_1000baseT_Half |
839c5b9b4e4SSrinivas Kandagatla 					 SUPPORTED_1000baseT_Full);
84079ee1dc3SSrinivas Kandagatla 
8417ac6653aSJeff Kirsher 	/*
8427ac6653aSJeff Kirsher 	 * Broken HW is sometimes missing the pull-up resistor on the
8437ac6653aSJeff Kirsher 	 * MDIO line, which results in reads to non-existent devices returning
8447ac6653aSJeff Kirsher 	 * 0 rather than 0xffff. Catch this here and treat 0 as a non-existent
8457ac6653aSJeff Kirsher 	 * device as well.
8467ac6653aSJeff Kirsher 	 * Note: phydev->phy_id is the result of reading the UID PHY registers.
8477ac6653aSJeff Kirsher 	 */
8487ac6653aSJeff Kirsher 	if (phydev->phy_id == 0) {
8497ac6653aSJeff Kirsher 		phy_disconnect(phydev);
8507ac6653aSJeff Kirsher 		return -ENODEV;
8517ac6653aSJeff Kirsher 	}
8527ac6653aSJeff Kirsher 	pr_debug("stmmac_init_phy:  %s: attached to PHY (UID 0x%x)"
8537ac6653aSJeff Kirsher 		 " Link = %d\n", dev->name, phydev->phy_id, phydev->link);
8547ac6653aSJeff Kirsher 
8557ac6653aSJeff Kirsher 	priv->phydev = phydev;
8567ac6653aSJeff Kirsher 
8577ac6653aSJeff Kirsher 	return 0;
8587ac6653aSJeff Kirsher }
8597ac6653aSJeff Kirsher 
8607ac6653aSJeff Kirsher /**
86132ceabcaSGiuseppe CAVALLARO  * stmmac_display_ring: display ring
86232ceabcaSGiuseppe CAVALLARO  * @head: pointer to the head of the ring passed.
8637ac6653aSJeff Kirsher  * @size: size of the ring.
86432ceabcaSGiuseppe CAVALLARO  * @extend_desc: to verify if extended descriptors are used.
865c24602efSGiuseppe CAVALLARO  * Description: display the control/status and buffer descriptors.
8667ac6653aSJeff Kirsher  */
867c24602efSGiuseppe CAVALLARO static void stmmac_display_ring(void *head, int size, int extend_desc)
8687ac6653aSJeff Kirsher {
8697ac6653aSJeff Kirsher 	int i;
870c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
871c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
872c24602efSGiuseppe CAVALLARO 
8737ac6653aSJeff Kirsher 	for (i = 0; i < size; i++) {
874c24602efSGiuseppe CAVALLARO 		u64 x;
875c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
876c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
877c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
878c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(ep),
879c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
880c24602efSGiuseppe CAVALLARO 				ep->basic.des2, ep->basic.des3);
881c24602efSGiuseppe CAVALLARO 			ep++;
882c24602efSGiuseppe CAVALLARO 		} else {
883c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
884c24602efSGiuseppe CAVALLARO 			pr_info("%d [0x%x]: 0x%x 0x%x 0x%x 0x%x",
885c24602efSGiuseppe CAVALLARO 				i, (unsigned int)virt_to_phys(p),
886c24602efSGiuseppe CAVALLARO 				(unsigned int)x, (unsigned int)(x >> 32),
887c24602efSGiuseppe CAVALLARO 				p->des2, p->des3);
888c24602efSGiuseppe CAVALLARO 			p++;
889c24602efSGiuseppe CAVALLARO 		}
8907ac6653aSJeff Kirsher 		pr_info("\n");
8917ac6653aSJeff Kirsher 	}
8927ac6653aSJeff Kirsher }
8937ac6653aSJeff Kirsher 
894c24602efSGiuseppe CAVALLARO static void stmmac_display_rings(struct stmmac_priv *priv)
895c24602efSGiuseppe CAVALLARO {
896c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
897c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
898c24602efSGiuseppe CAVALLARO 
899c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
900c24602efSGiuseppe CAVALLARO 		pr_info("Extended RX descriptor ring:\n");
901c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
902c24602efSGiuseppe CAVALLARO 		pr_info("Extended TX descriptor ring:\n");
903c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
904c24602efSGiuseppe CAVALLARO 	} else {
905c24602efSGiuseppe CAVALLARO 		pr_info("RX descriptor ring:\n");
906c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
907c24602efSGiuseppe CAVALLARO 		pr_info("TX descriptor ring:\n");
908c24602efSGiuseppe CAVALLARO 		stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
909c24602efSGiuseppe CAVALLARO 	}
910c24602efSGiuseppe CAVALLARO }
911c24602efSGiuseppe CAVALLARO 
912286a8372SGiuseppe CAVALLARO static int stmmac_set_bfsize(int mtu, int bufsize)
913286a8372SGiuseppe CAVALLARO {
914286a8372SGiuseppe CAVALLARO 	int ret = bufsize;
915286a8372SGiuseppe CAVALLARO 
916286a8372SGiuseppe CAVALLARO 	if (mtu >= BUF_SIZE_4KiB)
917286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_8KiB;
918286a8372SGiuseppe CAVALLARO 	else if (mtu >= BUF_SIZE_2KiB)
919286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_4KiB;
920d916701cSGiuseppe CAVALLARO 	else if (mtu > DEFAULT_BUFSIZE)
921286a8372SGiuseppe CAVALLARO 		ret = BUF_SIZE_2KiB;
922286a8372SGiuseppe CAVALLARO 	else
923d916701cSGiuseppe CAVALLARO 		ret = DEFAULT_BUFSIZE;
924286a8372SGiuseppe CAVALLARO 
925286a8372SGiuseppe CAVALLARO 	return ret;
926286a8372SGiuseppe CAVALLARO }
927286a8372SGiuseppe CAVALLARO 
92832ceabcaSGiuseppe CAVALLARO /**
92932ceabcaSGiuseppe CAVALLARO  * stmmac_clear_descriptors: clear descriptors
93032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
93132ceabcaSGiuseppe CAVALLARO  * Description: this function is called to clear the tx and rx descriptors
93232ceabcaSGiuseppe CAVALLARO  * in case of both basic and extended descriptors are used.
93332ceabcaSGiuseppe CAVALLARO  */
934c24602efSGiuseppe CAVALLARO static void stmmac_clear_descriptors(struct stmmac_priv *priv)
935c24602efSGiuseppe CAVALLARO {
936c24602efSGiuseppe CAVALLARO 	int i;
937c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
938c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
939c24602efSGiuseppe CAVALLARO 
940c24602efSGiuseppe CAVALLARO 	/* Clear the Rx/Tx descriptors */
941c24602efSGiuseppe CAVALLARO 	for (i = 0; i < rxsize; i++)
942c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
943c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_erx[i].basic,
944c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
945c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
946c24602efSGiuseppe CAVALLARO 		else
947c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_rx_desc(&priv->dma_rx[i],
948c24602efSGiuseppe CAVALLARO 						     priv->use_riwt, priv->mode,
949c24602efSGiuseppe CAVALLARO 						     (i == rxsize - 1));
950c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
951c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
952c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
953c24602efSGiuseppe CAVALLARO 						     priv->mode,
954c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
955c24602efSGiuseppe CAVALLARO 		else
956c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
957c24602efSGiuseppe CAVALLARO 						     priv->mode,
958c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
959c24602efSGiuseppe CAVALLARO }
960c24602efSGiuseppe CAVALLARO 
961c24602efSGiuseppe CAVALLARO static int stmmac_init_rx_buffers(struct stmmac_priv *priv, struct dma_desc *p,
962c24602efSGiuseppe CAVALLARO 				  int i)
963c24602efSGiuseppe CAVALLARO {
964c24602efSGiuseppe CAVALLARO 	struct sk_buff *skb;
965c24602efSGiuseppe CAVALLARO 
966c24602efSGiuseppe CAVALLARO 	skb = __netdev_alloc_skb(priv->dev, priv->dma_buf_sz + NET_IP_ALIGN,
967c24602efSGiuseppe CAVALLARO 				 GFP_KERNEL);
96856329137SBartlomiej Zolnierkiewicz 	if (!skb) {
969c24602efSGiuseppe CAVALLARO 		pr_err("%s: Rx init fails; skb is NULL\n", __func__);
97056329137SBartlomiej Zolnierkiewicz 		return -ENOMEM;
971c24602efSGiuseppe CAVALLARO 	}
972c24602efSGiuseppe CAVALLARO 	skb_reserve(skb, NET_IP_ALIGN);
973c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff[i] = skb;
974c24602efSGiuseppe CAVALLARO 	priv->rx_skbuff_dma[i] = dma_map_single(priv->device, skb->data,
975c24602efSGiuseppe CAVALLARO 						priv->dma_buf_sz,
976c24602efSGiuseppe CAVALLARO 						DMA_FROM_DEVICE);
97756329137SBartlomiej Zolnierkiewicz 	if (dma_mapping_error(priv->device, priv->rx_skbuff_dma[i])) {
97856329137SBartlomiej Zolnierkiewicz 		pr_err("%s: DMA mapping error\n", __func__);
97956329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(skb);
98056329137SBartlomiej Zolnierkiewicz 		return -EINVAL;
98156329137SBartlomiej Zolnierkiewicz 	}
982c24602efSGiuseppe CAVALLARO 
983c24602efSGiuseppe CAVALLARO 	p->des2 = priv->rx_skbuff_dma[i];
984c24602efSGiuseppe CAVALLARO 
98529896a67SGiuseppe CAVALLARO 	if ((priv->hw->mode->init_desc3) &&
986c24602efSGiuseppe CAVALLARO 	    (priv->dma_buf_sz == BUF_SIZE_16KiB))
98729896a67SGiuseppe CAVALLARO 		priv->hw->mode->init_desc3(p);
988c24602efSGiuseppe CAVALLARO 
989c24602efSGiuseppe CAVALLARO 	return 0;
990c24602efSGiuseppe CAVALLARO }
991c24602efSGiuseppe CAVALLARO 
99256329137SBartlomiej Zolnierkiewicz static void stmmac_free_rx_buffers(struct stmmac_priv *priv, int i)
99356329137SBartlomiej Zolnierkiewicz {
99456329137SBartlomiej Zolnierkiewicz 	if (priv->rx_skbuff[i]) {
99556329137SBartlomiej Zolnierkiewicz 		dma_unmap_single(priv->device, priv->rx_skbuff_dma[i],
99656329137SBartlomiej Zolnierkiewicz 				 priv->dma_buf_sz, DMA_FROM_DEVICE);
99756329137SBartlomiej Zolnierkiewicz 		dev_kfree_skb_any(priv->rx_skbuff[i]);
99856329137SBartlomiej Zolnierkiewicz 	}
99956329137SBartlomiej Zolnierkiewicz 	priv->rx_skbuff[i] = NULL;
100056329137SBartlomiej Zolnierkiewicz }
100156329137SBartlomiej Zolnierkiewicz 
10027ac6653aSJeff Kirsher /**
10037ac6653aSJeff Kirsher  * init_dma_desc_rings - init the RX/TX descriptor rings
10047ac6653aSJeff Kirsher  * @dev: net device structure
10057ac6653aSJeff Kirsher  * Description:  this function initializes the DMA RX/TX descriptors
1006286a8372SGiuseppe CAVALLARO  * and allocates the socket buffers. It suppors the chained and ring
1007286a8372SGiuseppe CAVALLARO  * modes.
10087ac6653aSJeff Kirsher  */
100956329137SBartlomiej Zolnierkiewicz static int init_dma_desc_rings(struct net_device *dev)
10107ac6653aSJeff Kirsher {
10117ac6653aSJeff Kirsher 	int i;
10127ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
10137ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
10147ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
10154a7d666aSGiuseppe CAVALLARO 	unsigned int bfsize = 0;
101656329137SBartlomiej Zolnierkiewicz 	int ret = -ENOMEM;
10177ac6653aSJeff Kirsher 
101829896a67SGiuseppe CAVALLARO 	if (priv->hw->mode->set_16kib_bfsize)
101929896a67SGiuseppe CAVALLARO 		bfsize = priv->hw->mode->set_16kib_bfsize(dev->mtu);
1020286a8372SGiuseppe CAVALLARO 
10214a7d666aSGiuseppe CAVALLARO 	if (bfsize < BUF_SIZE_16KiB)
1022286a8372SGiuseppe CAVALLARO 		bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
10237ac6653aSJeff Kirsher 
10242618abb7SVince Bridgers 	priv->dma_buf_sz = bfsize;
10252618abb7SVince Bridgers 
102683d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv))
102783d7af64SGiuseppe CAVALLARO 		pr_debug("%s: txsize %d, rxsize %d, bfsize %d\n", __func__,
10287ac6653aSJeff Kirsher 			 txsize, rxsize, bfsize);
10297ac6653aSJeff Kirsher 
103083d7af64SGiuseppe CAVALLARO 	if (netif_msg_probe(priv)) {
1031c24602efSGiuseppe CAVALLARO 		pr_debug("(%s) dma_rx_phy=0x%08x dma_tx_phy=0x%08x\n", __func__,
1032c24602efSGiuseppe CAVALLARO 			 (u32) priv->dma_rx_phy, (u32) priv->dma_tx_phy);
10337ac6653aSJeff Kirsher 
10347ac6653aSJeff Kirsher 		/* RX INITIALIZATION */
103583d7af64SGiuseppe CAVALLARO 		pr_debug("\tSKB addresses:\nskb\t\tskb data\tdma data\n");
103683d7af64SGiuseppe CAVALLARO 	}
10377ac6653aSJeff Kirsher 	for (i = 0; i < rxsize; i++) {
1038c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1039c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1040c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_erx + i)->basic);
1041c24602efSGiuseppe CAVALLARO 		else
1042c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + i;
10437ac6653aSJeff Kirsher 
104456329137SBartlomiej Zolnierkiewicz 		ret = stmmac_init_rx_buffers(priv, p, i);
104556329137SBartlomiej Zolnierkiewicz 		if (ret)
104656329137SBartlomiej Zolnierkiewicz 			goto err_init_rx_buffers;
1047286a8372SGiuseppe CAVALLARO 
104883d7af64SGiuseppe CAVALLARO 		if (netif_msg_probe(priv))
104983d7af64SGiuseppe CAVALLARO 			pr_debug("[%p]\t[%p]\t[%x]\n", priv->rx_skbuff[i],
105083d7af64SGiuseppe CAVALLARO 				 priv->rx_skbuff[i]->data,
105183d7af64SGiuseppe CAVALLARO 				 (unsigned int)priv->rx_skbuff_dma[i]);
10527ac6653aSJeff Kirsher 	}
10537ac6653aSJeff Kirsher 	priv->cur_rx = 0;
10547ac6653aSJeff Kirsher 	priv->dirty_rx = (unsigned int)(i - rxsize);
10557ac6653aSJeff Kirsher 	buf_sz = bfsize;
10567ac6653aSJeff Kirsher 
1057c24602efSGiuseppe CAVALLARO 	/* Setup the chained descriptor addresses */
1058c24602efSGiuseppe CAVALLARO 	if (priv->mode == STMMAC_CHAIN_MODE) {
1059c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc) {
106029896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_erx, priv->dma_rx_phy,
1061c24602efSGiuseppe CAVALLARO 					     rxsize, 1);
106229896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_etx, priv->dma_tx_phy,
1063c24602efSGiuseppe CAVALLARO 					     txsize, 1);
1064c24602efSGiuseppe CAVALLARO 		} else {
106529896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_rx, priv->dma_rx_phy,
1066c24602efSGiuseppe CAVALLARO 					     rxsize, 0);
106729896a67SGiuseppe CAVALLARO 			priv->hw->mode->init(priv->dma_tx, priv->dma_tx_phy,
1068c24602efSGiuseppe CAVALLARO 					     txsize, 0);
1069c24602efSGiuseppe CAVALLARO 		}
10707ac6653aSJeff Kirsher 	}
1071286a8372SGiuseppe CAVALLARO 
1072c24602efSGiuseppe CAVALLARO 	/* TX INITIALIZATION */
1073c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++) {
1074c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1075c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1076c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1077c24602efSGiuseppe CAVALLARO 		else
1078c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1079c24602efSGiuseppe CAVALLARO 		p->des2 = 0;
1080362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[i].buf = 0;
1081362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[i].map_as_page = false;
1082c24602efSGiuseppe CAVALLARO 		priv->tx_skbuff[i] = NULL;
10834a7d666aSGiuseppe CAVALLARO 	}
1084c24602efSGiuseppe CAVALLARO 
10857ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
10867ac6653aSJeff Kirsher 	priv->cur_tx = 0;
10877ac6653aSJeff Kirsher 
1088c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
10897ac6653aSJeff Kirsher 
1090c24602efSGiuseppe CAVALLARO 	if (netif_msg_hw(priv))
1091c24602efSGiuseppe CAVALLARO 		stmmac_display_rings(priv);
109256329137SBartlomiej Zolnierkiewicz 
109356329137SBartlomiej Zolnierkiewicz 	return 0;
109456329137SBartlomiej Zolnierkiewicz err_init_rx_buffers:
109556329137SBartlomiej Zolnierkiewicz 	while (--i >= 0)
109656329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
109756329137SBartlomiej Zolnierkiewicz 	return ret;
10987ac6653aSJeff Kirsher }
10997ac6653aSJeff Kirsher 
11007ac6653aSJeff Kirsher static void dma_free_rx_skbufs(struct stmmac_priv *priv)
11017ac6653aSJeff Kirsher {
11027ac6653aSJeff Kirsher 	int i;
11037ac6653aSJeff Kirsher 
110456329137SBartlomiej Zolnierkiewicz 	for (i = 0; i < priv->dma_rx_size; i++)
110556329137SBartlomiej Zolnierkiewicz 		stmmac_free_rx_buffers(priv, i);
11067ac6653aSJeff Kirsher }
11077ac6653aSJeff Kirsher 
11087ac6653aSJeff Kirsher static void dma_free_tx_skbufs(struct stmmac_priv *priv)
11097ac6653aSJeff Kirsher {
11107ac6653aSJeff Kirsher 	int i;
11117ac6653aSJeff Kirsher 
11127ac6653aSJeff Kirsher 	for (i = 0; i < priv->dma_tx_size; i++) {
1113c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
111475e4364fSdamuzi000 
1115c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1116c24602efSGiuseppe CAVALLARO 			p = &((priv->dma_etx + i)->basic);
1117c24602efSGiuseppe CAVALLARO 		else
1118c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + i;
1119c24602efSGiuseppe CAVALLARO 
1120362b37beSGiuseppe CAVALLARO 		if (priv->tx_skbuff_dma[i].buf) {
1121362b37beSGiuseppe CAVALLARO 			if (priv->tx_skbuff_dma[i].map_as_page)
1122362b37beSGiuseppe CAVALLARO 				dma_unmap_page(priv->device,
1123362b37beSGiuseppe CAVALLARO 					       priv->tx_skbuff_dma[i].buf,
11247ac6653aSJeff Kirsher 					       priv->hw->desc->get_tx_len(p),
11257ac6653aSJeff Kirsher 					       DMA_TO_DEVICE);
1126362b37beSGiuseppe CAVALLARO 			else
1127362b37beSGiuseppe CAVALLARO 				dma_unmap_single(priv->device,
1128362b37beSGiuseppe CAVALLARO 						 priv->tx_skbuff_dma[i].buf,
1129362b37beSGiuseppe CAVALLARO 						 priv->hw->desc->get_tx_len(p),
1130362b37beSGiuseppe CAVALLARO 						 DMA_TO_DEVICE);
113175e4364fSdamuzi000 		}
113275e4364fSdamuzi000 
113375e4364fSdamuzi000 		if (priv->tx_skbuff[i] != NULL) {
11347ac6653aSJeff Kirsher 			dev_kfree_skb_any(priv->tx_skbuff[i]);
11357ac6653aSJeff Kirsher 			priv->tx_skbuff[i] = NULL;
1136362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[i].buf = 0;
1137362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[i].map_as_page = false;
11387ac6653aSJeff Kirsher 		}
11397ac6653aSJeff Kirsher 	}
11407ac6653aSJeff Kirsher }
11417ac6653aSJeff Kirsher 
114209f8d696SSrinivas Kandagatla static int alloc_dma_desc_resources(struct stmmac_priv *priv)
114309f8d696SSrinivas Kandagatla {
114409f8d696SSrinivas Kandagatla 	unsigned int txsize = priv->dma_tx_size;
114509f8d696SSrinivas Kandagatla 	unsigned int rxsize = priv->dma_rx_size;
114609f8d696SSrinivas Kandagatla 	int ret = -ENOMEM;
114709f8d696SSrinivas Kandagatla 
114809f8d696SSrinivas Kandagatla 	priv->rx_skbuff_dma = kmalloc_array(rxsize, sizeof(dma_addr_t),
114909f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
115009f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff_dma)
115109f8d696SSrinivas Kandagatla 		return -ENOMEM;
115209f8d696SSrinivas Kandagatla 
115309f8d696SSrinivas Kandagatla 	priv->rx_skbuff = kmalloc_array(rxsize, sizeof(struct sk_buff *),
115409f8d696SSrinivas Kandagatla 					GFP_KERNEL);
115509f8d696SSrinivas Kandagatla 	if (!priv->rx_skbuff)
115609f8d696SSrinivas Kandagatla 		goto err_rx_skbuff;
115709f8d696SSrinivas Kandagatla 
1158362b37beSGiuseppe CAVALLARO 	priv->tx_skbuff_dma = kmalloc_array(txsize,
1159362b37beSGiuseppe CAVALLARO 					    sizeof(*priv->tx_skbuff_dma),
116009f8d696SSrinivas Kandagatla 					    GFP_KERNEL);
116109f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff_dma)
116209f8d696SSrinivas Kandagatla 		goto err_tx_skbuff_dma;
116309f8d696SSrinivas Kandagatla 
116409f8d696SSrinivas Kandagatla 	priv->tx_skbuff = kmalloc_array(txsize, sizeof(struct sk_buff *),
116509f8d696SSrinivas Kandagatla 					GFP_KERNEL);
116609f8d696SSrinivas Kandagatla 	if (!priv->tx_skbuff)
116709f8d696SSrinivas Kandagatla 		goto err_tx_skbuff;
116809f8d696SSrinivas Kandagatla 
116909f8d696SSrinivas Kandagatla 	if (priv->extend_desc) {
117009f8d696SSrinivas Kandagatla 		priv->dma_erx = dma_alloc_coherent(priv->device, rxsize *
117109f8d696SSrinivas Kandagatla 						   sizeof(struct
117209f8d696SSrinivas Kandagatla 							  dma_extended_desc),
117309f8d696SSrinivas Kandagatla 						   &priv->dma_rx_phy,
117409f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
117509f8d696SSrinivas Kandagatla 		if (!priv->dma_erx)
117609f8d696SSrinivas Kandagatla 			goto err_dma;
117709f8d696SSrinivas Kandagatla 
117809f8d696SSrinivas Kandagatla 		priv->dma_etx = dma_alloc_coherent(priv->device, txsize *
117909f8d696SSrinivas Kandagatla 						   sizeof(struct
118009f8d696SSrinivas Kandagatla 							  dma_extended_desc),
118109f8d696SSrinivas Kandagatla 						   &priv->dma_tx_phy,
118209f8d696SSrinivas Kandagatla 						   GFP_KERNEL);
118309f8d696SSrinivas Kandagatla 		if (!priv->dma_etx) {
118409f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
118509f8d696SSrinivas Kandagatla 					sizeof(struct dma_extended_desc),
118609f8d696SSrinivas Kandagatla 					priv->dma_erx, priv->dma_rx_phy);
118709f8d696SSrinivas Kandagatla 			goto err_dma;
118809f8d696SSrinivas Kandagatla 		}
118909f8d696SSrinivas Kandagatla 	} else {
119009f8d696SSrinivas Kandagatla 		priv->dma_rx = dma_alloc_coherent(priv->device, rxsize *
119109f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
119209f8d696SSrinivas Kandagatla 						  &priv->dma_rx_phy,
119309f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
119409f8d696SSrinivas Kandagatla 		if (!priv->dma_rx)
119509f8d696SSrinivas Kandagatla 			goto err_dma;
119609f8d696SSrinivas Kandagatla 
119709f8d696SSrinivas Kandagatla 		priv->dma_tx = dma_alloc_coherent(priv->device, txsize *
119809f8d696SSrinivas Kandagatla 						  sizeof(struct dma_desc),
119909f8d696SSrinivas Kandagatla 						  &priv->dma_tx_phy,
120009f8d696SSrinivas Kandagatla 						  GFP_KERNEL);
120109f8d696SSrinivas Kandagatla 		if (!priv->dma_tx) {
120209f8d696SSrinivas Kandagatla 			dma_free_coherent(priv->device, priv->dma_rx_size *
120309f8d696SSrinivas Kandagatla 					sizeof(struct dma_desc),
120409f8d696SSrinivas Kandagatla 					priv->dma_rx, priv->dma_rx_phy);
120509f8d696SSrinivas Kandagatla 			goto err_dma;
120609f8d696SSrinivas Kandagatla 		}
120709f8d696SSrinivas Kandagatla 	}
120809f8d696SSrinivas Kandagatla 
120909f8d696SSrinivas Kandagatla 	return 0;
121009f8d696SSrinivas Kandagatla 
121109f8d696SSrinivas Kandagatla err_dma:
121209f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff);
121309f8d696SSrinivas Kandagatla err_tx_skbuff:
121409f8d696SSrinivas Kandagatla 	kfree(priv->tx_skbuff_dma);
121509f8d696SSrinivas Kandagatla err_tx_skbuff_dma:
121609f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff);
121709f8d696SSrinivas Kandagatla err_rx_skbuff:
121809f8d696SSrinivas Kandagatla 	kfree(priv->rx_skbuff_dma);
121909f8d696SSrinivas Kandagatla 	return ret;
122009f8d696SSrinivas Kandagatla }
122109f8d696SSrinivas Kandagatla 
12227ac6653aSJeff Kirsher static void free_dma_desc_resources(struct stmmac_priv *priv)
12237ac6653aSJeff Kirsher {
12247ac6653aSJeff Kirsher 	/* Release the DMA TX/RX socket buffers */
12257ac6653aSJeff Kirsher 	dma_free_rx_skbufs(priv);
12267ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
12277ac6653aSJeff Kirsher 
1228ceb69499SGiuseppe CAVALLARO 	/* Free DMA regions of consistent memory previously allocated */
1229c24602efSGiuseppe CAVALLARO 	if (!priv->extend_desc) {
12307ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
12317ac6653aSJeff Kirsher 				  priv->dma_tx_size * sizeof(struct dma_desc),
12327ac6653aSJeff Kirsher 				  priv->dma_tx, priv->dma_tx_phy);
12337ac6653aSJeff Kirsher 		dma_free_coherent(priv->device,
12347ac6653aSJeff Kirsher 				  priv->dma_rx_size * sizeof(struct dma_desc),
12357ac6653aSJeff Kirsher 				  priv->dma_rx, priv->dma_rx_phy);
1236c24602efSGiuseppe CAVALLARO 	} else {
1237c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_tx_size *
1238c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1239c24602efSGiuseppe CAVALLARO 				  priv->dma_etx, priv->dma_tx_phy);
1240c24602efSGiuseppe CAVALLARO 		dma_free_coherent(priv->device, priv->dma_rx_size *
1241c24602efSGiuseppe CAVALLARO 				  sizeof(struct dma_extended_desc),
1242c24602efSGiuseppe CAVALLARO 				  priv->dma_erx, priv->dma_rx_phy);
1243c24602efSGiuseppe CAVALLARO 	}
12447ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff_dma);
12457ac6653aSJeff Kirsher 	kfree(priv->rx_skbuff);
1246cf32deecSRayagond Kokatanur 	kfree(priv->tx_skbuff_dma);
12477ac6653aSJeff Kirsher 	kfree(priv->tx_skbuff);
12487ac6653aSJeff Kirsher }
12497ac6653aSJeff Kirsher 
12507ac6653aSJeff Kirsher /**
12517ac6653aSJeff Kirsher  *  stmmac_dma_operation_mode - HW DMA operation mode
125232ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
12537ac6653aSJeff Kirsher  *  Description: it sets the DMA operation mode: tx/rx DMA thresholds
12547ac6653aSJeff Kirsher  *  or Store-And-Forward capability.
12557ac6653aSJeff Kirsher  */
12567ac6653aSJeff Kirsher static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
12577ac6653aSJeff Kirsher {
1258e2a240c7SSonic Zhang 	if (priv->plat->force_thresh_dma_mode)
1259e2a240c7SSonic Zhang 		priv->hw->dma->dma_mode(priv->ioaddr, tc, tc);
1260e2a240c7SSonic Zhang 	else if (priv->plat->force_sf_dma_mode || priv->plat->tx_coe) {
12617ac6653aSJeff Kirsher 		/*
12627ac6653aSJeff Kirsher 		 * In case of GMAC, SF mode can be enabled
12637ac6653aSJeff Kirsher 		 * to perform the TX COE in HW. This depends on:
12647ac6653aSJeff Kirsher 		 * 1) TX COE if actually supported
12657ac6653aSJeff Kirsher 		 * 2) There is no bugged Jumbo frame support
12667ac6653aSJeff Kirsher 		 *    that needs to not insert csum in the TDES.
12677ac6653aSJeff Kirsher 		 */
1268ceb69499SGiuseppe CAVALLARO 		priv->hw->dma->dma_mode(priv->ioaddr, SF_DMA_MODE, SF_DMA_MODE);
12697ac6653aSJeff Kirsher 		tc = SF_DMA_MODE;
12707ac6653aSJeff Kirsher 	} else
12717ac6653aSJeff Kirsher 		priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
12727ac6653aSJeff Kirsher }
12737ac6653aSJeff Kirsher 
12747ac6653aSJeff Kirsher /**
12759125cdd1SGiuseppe CAVALLARO  * stmmac_tx_clean:
127632ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
12777ac6653aSJeff Kirsher  * Description: it reclaims resources after transmission completes.
12787ac6653aSJeff Kirsher  */
12799125cdd1SGiuseppe CAVALLARO static void stmmac_tx_clean(struct stmmac_priv *priv)
12807ac6653aSJeff Kirsher {
12817ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
12827ac6653aSJeff Kirsher 
1283a9097a96SGiuseppe CAVALLARO 	spin_lock(&priv->tx_lock);
1284a9097a96SGiuseppe CAVALLARO 
12859125cdd1SGiuseppe CAVALLARO 	priv->xstats.tx_clean++;
12869125cdd1SGiuseppe CAVALLARO 
12877ac6653aSJeff Kirsher 	while (priv->dirty_tx != priv->cur_tx) {
12887ac6653aSJeff Kirsher 		int last;
12897ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_tx % txsize;
12907ac6653aSJeff Kirsher 		struct sk_buff *skb = priv->tx_skbuff[entry];
1291c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
1292c24602efSGiuseppe CAVALLARO 
1293c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1294c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_etx + entry);
1295c24602efSGiuseppe CAVALLARO 		else
1296c24602efSGiuseppe CAVALLARO 			p = priv->dma_tx + entry;
12977ac6653aSJeff Kirsher 
12987ac6653aSJeff Kirsher 		/* Check if the descriptor is owned by the DMA. */
12997ac6653aSJeff Kirsher 		if (priv->hw->desc->get_tx_owner(p))
13007ac6653aSJeff Kirsher 			break;
13017ac6653aSJeff Kirsher 
1302c24602efSGiuseppe CAVALLARO 		/* Verify tx error by looking at the last segment. */
13037ac6653aSJeff Kirsher 		last = priv->hw->desc->get_tx_ls(p);
13047ac6653aSJeff Kirsher 		if (likely(last)) {
13057ac6653aSJeff Kirsher 			int tx_error =
13067ac6653aSJeff Kirsher 			    priv->hw->desc->tx_status(&priv->dev->stats,
13077ac6653aSJeff Kirsher 						      &priv->xstats, p,
13087ac6653aSJeff Kirsher 						      priv->ioaddr);
13097ac6653aSJeff Kirsher 			if (likely(tx_error == 0)) {
13107ac6653aSJeff Kirsher 				priv->dev->stats.tx_packets++;
13117ac6653aSJeff Kirsher 				priv->xstats.tx_pkt_n++;
13127ac6653aSJeff Kirsher 			} else
13137ac6653aSJeff Kirsher 				priv->dev->stats.tx_errors++;
1314891434b1SRayagond Kokatanur 
1315891434b1SRayagond Kokatanur 			stmmac_get_tx_hwtstamp(priv, entry, skb);
13167ac6653aSJeff Kirsher 		}
131783d7af64SGiuseppe CAVALLARO 		if (netif_msg_tx_done(priv))
131883d7af64SGiuseppe CAVALLARO 			pr_debug("%s: curr %d, dirty %d\n", __func__,
13197ac6653aSJeff Kirsher 				 priv->cur_tx, priv->dirty_tx);
13207ac6653aSJeff Kirsher 
1321362b37beSGiuseppe CAVALLARO 		if (likely(priv->tx_skbuff_dma[entry].buf)) {
1322362b37beSGiuseppe CAVALLARO 			if (priv->tx_skbuff_dma[entry].map_as_page)
1323362b37beSGiuseppe CAVALLARO 				dma_unmap_page(priv->device,
1324362b37beSGiuseppe CAVALLARO 					       priv->tx_skbuff_dma[entry].buf,
13257ac6653aSJeff Kirsher 					       priv->hw->desc->get_tx_len(p),
13267ac6653aSJeff Kirsher 					       DMA_TO_DEVICE);
1327362b37beSGiuseppe CAVALLARO 			else
1328362b37beSGiuseppe CAVALLARO 				dma_unmap_single(priv->device,
1329362b37beSGiuseppe CAVALLARO 						 priv->tx_skbuff_dma[entry].buf,
1330362b37beSGiuseppe CAVALLARO 						 priv->hw->desc->get_tx_len(p),
1331362b37beSGiuseppe CAVALLARO 						 DMA_TO_DEVICE);
1332362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[entry].buf = 0;
1333362b37beSGiuseppe CAVALLARO 			priv->tx_skbuff_dma[entry].map_as_page = false;
1334cf32deecSRayagond Kokatanur 		}
133529896a67SGiuseppe CAVALLARO 		priv->hw->mode->clean_desc3(priv, p);
13367ac6653aSJeff Kirsher 
13377ac6653aSJeff Kirsher 		if (likely(skb != NULL)) {
13387c565c33SEric W. Biederman 			dev_consume_skb_any(skb);
13397ac6653aSJeff Kirsher 			priv->tx_skbuff[entry] = NULL;
13407ac6653aSJeff Kirsher 		}
13417ac6653aSJeff Kirsher 
13424a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->release_tx_desc(p, priv->mode);
13437ac6653aSJeff Kirsher 
134413497f58SGiuseppe CAVALLARO 		priv->dirty_tx++;
13457ac6653aSJeff Kirsher 	}
13467ac6653aSJeff Kirsher 	if (unlikely(netif_queue_stopped(priv->dev) &&
13477ac6653aSJeff Kirsher 		     stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv))) {
13487ac6653aSJeff Kirsher 		netif_tx_lock(priv->dev);
13497ac6653aSJeff Kirsher 		if (netif_queue_stopped(priv->dev) &&
13507ac6653aSJeff Kirsher 		    stmmac_tx_avail(priv) > STMMAC_TX_THRESH(priv)) {
135183d7af64SGiuseppe CAVALLARO 			if (netif_msg_tx_done(priv))
135283d7af64SGiuseppe CAVALLARO 				pr_debug("%s: restart transmit\n", __func__);
13537ac6653aSJeff Kirsher 			netif_wake_queue(priv->dev);
13547ac6653aSJeff Kirsher 		}
13557ac6653aSJeff Kirsher 		netif_tx_unlock(priv->dev);
13567ac6653aSJeff Kirsher 	}
1357d765955dSGiuseppe CAVALLARO 
1358d765955dSGiuseppe CAVALLARO 	if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
1359d765955dSGiuseppe CAVALLARO 		stmmac_enable_eee_mode(priv);
1360f5351ef7SGiuseppe CAVALLARO 		mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
1361d765955dSGiuseppe CAVALLARO 	}
1362a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
13637ac6653aSJeff Kirsher }
13647ac6653aSJeff Kirsher 
13659125cdd1SGiuseppe CAVALLARO static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv)
13667ac6653aSJeff Kirsher {
13677ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_irq(priv->ioaddr);
13687ac6653aSJeff Kirsher }
13697ac6653aSJeff Kirsher 
13709125cdd1SGiuseppe CAVALLARO static inline void stmmac_disable_dma_irq(struct stmmac_priv *priv)
13717ac6653aSJeff Kirsher {
13727ac6653aSJeff Kirsher 	priv->hw->dma->disable_dma_irq(priv->ioaddr);
13737ac6653aSJeff Kirsher }
13747ac6653aSJeff Kirsher 
13757ac6653aSJeff Kirsher /**
137632ceabcaSGiuseppe CAVALLARO  * stmmac_tx_err: irq tx error mng function
137732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
13787ac6653aSJeff Kirsher  * Description: it cleans the descriptors and restarts the transmission
13797ac6653aSJeff Kirsher  * in case of errors.
13807ac6653aSJeff Kirsher  */
13817ac6653aSJeff Kirsher static void stmmac_tx_err(struct stmmac_priv *priv)
13827ac6653aSJeff Kirsher {
1383c24602efSGiuseppe CAVALLARO 	int i;
1384c24602efSGiuseppe CAVALLARO 	int txsize = priv->dma_tx_size;
13857ac6653aSJeff Kirsher 	netif_stop_queue(priv->dev);
13867ac6653aSJeff Kirsher 
13877ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
13887ac6653aSJeff Kirsher 	dma_free_tx_skbufs(priv);
1389c24602efSGiuseppe CAVALLARO 	for (i = 0; i < txsize; i++)
1390c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1391c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_etx[i].basic,
1392c24602efSGiuseppe CAVALLARO 						     priv->mode,
1393c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
1394c24602efSGiuseppe CAVALLARO 		else
1395c24602efSGiuseppe CAVALLARO 			priv->hw->desc->init_tx_desc(&priv->dma_tx[i],
1396c24602efSGiuseppe CAVALLARO 						     priv->mode,
1397c24602efSGiuseppe CAVALLARO 						     (i == txsize - 1));
13987ac6653aSJeff Kirsher 	priv->dirty_tx = 0;
13997ac6653aSJeff Kirsher 	priv->cur_tx = 0;
14007ac6653aSJeff Kirsher 	priv->hw->dma->start_tx(priv->ioaddr);
14017ac6653aSJeff Kirsher 
14027ac6653aSJeff Kirsher 	priv->dev->stats.tx_errors++;
14037ac6653aSJeff Kirsher 	netif_wake_queue(priv->dev);
14047ac6653aSJeff Kirsher }
14057ac6653aSJeff Kirsher 
140632ceabcaSGiuseppe CAVALLARO /**
140732ceabcaSGiuseppe CAVALLARO  * stmmac_dma_interrupt: DMA ISR
140832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
140932ceabcaSGiuseppe CAVALLARO  * Description: this is the DMA ISR. It is called by the main ISR.
141032ceabcaSGiuseppe CAVALLARO  * It calls the dwmac dma routine to understand which type of interrupt
141132ceabcaSGiuseppe CAVALLARO  * happened. In case of there is a Normal interrupt and either TX or RX
141232ceabcaSGiuseppe CAVALLARO  * interrupt happened so the NAPI is scheduled.
141332ceabcaSGiuseppe CAVALLARO  */
14147ac6653aSJeff Kirsher static void stmmac_dma_interrupt(struct stmmac_priv *priv)
14157ac6653aSJeff Kirsher {
14167ac6653aSJeff Kirsher 	int status;
14177ac6653aSJeff Kirsher 
14187ac6653aSJeff Kirsher 	status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);
14199125cdd1SGiuseppe CAVALLARO 	if (likely((status & handle_rx)) || (status & handle_tx)) {
14209125cdd1SGiuseppe CAVALLARO 		if (likely(napi_schedule_prep(&priv->napi))) {
14219125cdd1SGiuseppe CAVALLARO 			stmmac_disable_dma_irq(priv);
14229125cdd1SGiuseppe CAVALLARO 			__napi_schedule(&priv->napi);
14239125cdd1SGiuseppe CAVALLARO 		}
14249125cdd1SGiuseppe CAVALLARO 	}
14259125cdd1SGiuseppe CAVALLARO 	if (unlikely(status & tx_hard_error_bump_tc)) {
14267ac6653aSJeff Kirsher 		/* Try to bump up the dma threshold on this failure */
14277ac6653aSJeff Kirsher 		if (unlikely(tc != SF_DMA_MODE) && (tc <= 256)) {
14287ac6653aSJeff Kirsher 			tc += 64;
14297ac6653aSJeff Kirsher 			priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
14307ac6653aSJeff Kirsher 			priv->xstats.threshold = tc;
14317ac6653aSJeff Kirsher 		}
14327ac6653aSJeff Kirsher 	} else if (unlikely(status == tx_hard_error))
14337ac6653aSJeff Kirsher 		stmmac_tx_err(priv);
14347ac6653aSJeff Kirsher }
14357ac6653aSJeff Kirsher 
143632ceabcaSGiuseppe CAVALLARO /**
143732ceabcaSGiuseppe CAVALLARO  * stmmac_mmc_setup: setup the Mac Management Counters (MMC)
143832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
143932ceabcaSGiuseppe CAVALLARO  * Description: this masks the MMC irq, in fact, the counters are managed in SW.
144032ceabcaSGiuseppe CAVALLARO  */
14411c901a46SGiuseppe CAVALLARO static void stmmac_mmc_setup(struct stmmac_priv *priv)
14421c901a46SGiuseppe CAVALLARO {
14431c901a46SGiuseppe CAVALLARO 	unsigned int mode = MMC_CNTRL_RESET_ON_READ | MMC_CNTRL_COUNTER_RESET |
14441c901a46SGiuseppe CAVALLARO 	    MMC_CNTRL_PRESET | MMC_CNTRL_FULL_HALF_PRESET;
14451c901a46SGiuseppe CAVALLARO 
14461c901a46SGiuseppe CAVALLARO 	dwmac_mmc_intr_all_mask(priv->ioaddr);
14474f795b25SGiuseppe CAVALLARO 
14484f795b25SGiuseppe CAVALLARO 	if (priv->dma_cap.rmon) {
14491c901a46SGiuseppe CAVALLARO 		dwmac_mmc_ctrl(priv->ioaddr, mode);
14501c901a46SGiuseppe CAVALLARO 		memset(&priv->mmc, 0, sizeof(struct stmmac_counters));
14514f795b25SGiuseppe CAVALLARO 	} else
1452aae54cffSStefan Roese 		pr_info(" No MAC Management Counters available\n");
14531c901a46SGiuseppe CAVALLARO }
14541c901a46SGiuseppe CAVALLARO 
1455f0b9d786SGiuseppe CAVALLARO static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)
1456f0b9d786SGiuseppe CAVALLARO {
1457f0b9d786SGiuseppe CAVALLARO 	u32 hwid = priv->hw->synopsys_uid;
1458f0b9d786SGiuseppe CAVALLARO 
1459ceb69499SGiuseppe CAVALLARO 	/* Check Synopsys Id (not available on old chips) */
1460f0b9d786SGiuseppe CAVALLARO 	if (likely(hwid)) {
1461f0b9d786SGiuseppe CAVALLARO 		u32 uid = ((hwid & 0x0000ff00) >> 8);
1462f0b9d786SGiuseppe CAVALLARO 		u32 synid = (hwid & 0x000000ff);
1463f0b9d786SGiuseppe CAVALLARO 
1464cf3f047bSGiuseppe CAVALLARO 		pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n",
1465f0b9d786SGiuseppe CAVALLARO 			uid, synid);
1466f0b9d786SGiuseppe CAVALLARO 
1467f0b9d786SGiuseppe CAVALLARO 		return synid;
1468f0b9d786SGiuseppe CAVALLARO 	}
1469f0b9d786SGiuseppe CAVALLARO 	return 0;
1470f0b9d786SGiuseppe CAVALLARO }
1471e7434821SGiuseppe CAVALLARO 
147219e30c14SGiuseppe CAVALLARO /**
147332ceabcaSGiuseppe CAVALLARO  * stmmac_selec_desc_mode: to select among: normal/alternate/extend descriptors
147432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
147532ceabcaSGiuseppe CAVALLARO  * Description: select the Enhanced/Alternate or Normal descriptors.
147632ceabcaSGiuseppe CAVALLARO  * In case of Enhanced/Alternate, it looks at the extended descriptors are
147732ceabcaSGiuseppe CAVALLARO  * supported by the HW cap. register.
1478ff3dd78cSGiuseppe CAVALLARO  */
147919e30c14SGiuseppe CAVALLARO static void stmmac_selec_desc_mode(struct stmmac_priv *priv)
148019e30c14SGiuseppe CAVALLARO {
148119e30c14SGiuseppe CAVALLARO 	if (priv->plat->enh_desc) {
148219e30c14SGiuseppe CAVALLARO 		pr_info(" Enhanced/Alternate descriptors\n");
1483c24602efSGiuseppe CAVALLARO 
1484c24602efSGiuseppe CAVALLARO 		/* GMAC older than 3.50 has no extended descriptors */
1485c24602efSGiuseppe CAVALLARO 		if (priv->synopsys_id >= DWMAC_CORE_3_50) {
1486c24602efSGiuseppe CAVALLARO 			pr_info("\tEnabled extended descriptors\n");
1487c24602efSGiuseppe CAVALLARO 			priv->extend_desc = 1;
1488c24602efSGiuseppe CAVALLARO 		} else
1489c24602efSGiuseppe CAVALLARO 			pr_warn("Extended descriptors not supported\n");
1490c24602efSGiuseppe CAVALLARO 
149119e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &enh_desc_ops;
149219e30c14SGiuseppe CAVALLARO 	} else {
149319e30c14SGiuseppe CAVALLARO 		pr_info(" Normal descriptors\n");
149419e30c14SGiuseppe CAVALLARO 		priv->hw->desc = &ndesc_ops;
149519e30c14SGiuseppe CAVALLARO 	}
149619e30c14SGiuseppe CAVALLARO }
149719e30c14SGiuseppe CAVALLARO 
149819e30c14SGiuseppe CAVALLARO /**
149932ceabcaSGiuseppe CAVALLARO  * stmmac_get_hw_features: get MAC capabilities from the HW cap. register.
150032ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
150119e30c14SGiuseppe CAVALLARO  * Description:
150219e30c14SGiuseppe CAVALLARO  *  new GMAC chip generations have a new register to indicate the
1503e7434821SGiuseppe CAVALLARO  *  presence of the optional feature/functions.
150419e30c14SGiuseppe CAVALLARO  *  This can be also used to override the value passed through the
150519e30c14SGiuseppe CAVALLARO  *  platform and necessary for old MAC10/100 and GMAC chips.
1506e7434821SGiuseppe CAVALLARO  */
1507e7434821SGiuseppe CAVALLARO static int stmmac_get_hw_features(struct stmmac_priv *priv)
1508e7434821SGiuseppe CAVALLARO {
15095e6efe88SGiuseppe CAVALLARO 	u32 hw_cap = 0;
15103c20f72fSGiuseppe CAVALLARO 
15115e6efe88SGiuseppe CAVALLARO 	if (priv->hw->dma->get_hw_feature) {
15125e6efe88SGiuseppe CAVALLARO 		hw_cap = priv->hw->dma->get_hw_feature(priv->ioaddr);
1513e7434821SGiuseppe CAVALLARO 
15141db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_10_100 = (hw_cap & DMA_HW_FEAT_MIISEL);
15151db123fbSRayagond Kokatanur 		priv->dma_cap.mbps_1000 = (hw_cap & DMA_HW_FEAT_GMIISEL) >> 1;
15161db123fbSRayagond Kokatanur 		priv->dma_cap.half_duplex = (hw_cap & DMA_HW_FEAT_HDSEL) >> 2;
15171db123fbSRayagond Kokatanur 		priv->dma_cap.hash_filter = (hw_cap & DMA_HW_FEAT_HASHSEL) >> 4;
1518ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.multi_addr = (hw_cap & DMA_HW_FEAT_ADDMAC) >> 5;
15191db123fbSRayagond Kokatanur 		priv->dma_cap.pcs = (hw_cap & DMA_HW_FEAT_PCSSEL) >> 6;
15201db123fbSRayagond Kokatanur 		priv->dma_cap.sma_mdio = (hw_cap & DMA_HW_FEAT_SMASEL) >> 8;
15211db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_remote_wake_up =
15221db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RWKSEL) >> 9;
15231db123fbSRayagond Kokatanur 		priv->dma_cap.pmt_magic_frame =
15241db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_MGKSEL) >> 10;
15251db123fbSRayagond Kokatanur 		/* MMC */
15261db123fbSRayagond Kokatanur 		priv->dma_cap.rmon = (hw_cap & DMA_HW_FEAT_MMCSEL) >> 11;
1527e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2002 */
15281db123fbSRayagond Kokatanur 		priv->dma_cap.time_stamp =
15291db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER1SEL) >> 12;
1530e7434821SGiuseppe CAVALLARO 		/* IEEE 1588-2008 */
15311db123fbSRayagond Kokatanur 		priv->dma_cap.atime_stamp =
15321db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TSVER2SEL) >> 13;
1533e7434821SGiuseppe CAVALLARO 		/* 802.3az - Energy-Efficient Ethernet (EEE) */
15341db123fbSRayagond Kokatanur 		priv->dma_cap.eee = (hw_cap & DMA_HW_FEAT_EEESEL) >> 14;
15351db123fbSRayagond Kokatanur 		priv->dma_cap.av = (hw_cap & DMA_HW_FEAT_AVSEL) >> 15;
1536e7434821SGiuseppe CAVALLARO 		/* TX and RX csum */
15371db123fbSRayagond Kokatanur 		priv->dma_cap.tx_coe = (hw_cap & DMA_HW_FEAT_TXCOESEL) >> 16;
15381db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type1 =
15391db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP1COE) >> 17;
15401db123fbSRayagond Kokatanur 		priv->dma_cap.rx_coe_type2 =
15411db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXTYP2COE) >> 18;
15421db123fbSRayagond Kokatanur 		priv->dma_cap.rxfifo_over_2048 =
15431db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXFIFOSIZE) >> 19;
1544e7434821SGiuseppe CAVALLARO 		/* TX and RX number of channels */
15451db123fbSRayagond Kokatanur 		priv->dma_cap.number_rx_channel =
15461db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_RXCHCNT) >> 20;
15471db123fbSRayagond Kokatanur 		priv->dma_cap.number_tx_channel =
15481db123fbSRayagond Kokatanur 		    (hw_cap & DMA_HW_FEAT_TXCHCNT) >> 22;
1549e7434821SGiuseppe CAVALLARO 		/* Alternate (enhanced) DESC mode */
1550ceb69499SGiuseppe CAVALLARO 		priv->dma_cap.enh_desc = (hw_cap & DMA_HW_FEAT_ENHDESSEL) >> 24;
155119e30c14SGiuseppe CAVALLARO 	}
1552e7434821SGiuseppe CAVALLARO 
1553e7434821SGiuseppe CAVALLARO 	return hw_cap;
1554e7434821SGiuseppe CAVALLARO }
1555e7434821SGiuseppe CAVALLARO 
155632ceabcaSGiuseppe CAVALLARO /**
155732ceabcaSGiuseppe CAVALLARO  * stmmac_check_ether_addr: check if the MAC addr is valid
155832ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
155932ceabcaSGiuseppe CAVALLARO  * Description:
156032ceabcaSGiuseppe CAVALLARO  * it is to verify if the MAC address is valid, in case of failures it
156132ceabcaSGiuseppe CAVALLARO  * generates a random MAC address
156232ceabcaSGiuseppe CAVALLARO  */
1563bfab27a1SGiuseppe CAVALLARO static void stmmac_check_ether_addr(struct stmmac_priv *priv)
1564bfab27a1SGiuseppe CAVALLARO {
1565bfab27a1SGiuseppe CAVALLARO 	if (!is_valid_ether_addr(priv->dev->dev_addr)) {
15667ed24bbeSVince Bridgers 		priv->hw->mac->get_umac_addr(priv->hw,
1567bfab27a1SGiuseppe CAVALLARO 					     priv->dev->dev_addr, 0);
1568bfab27a1SGiuseppe CAVALLARO 		if (!is_valid_ether_addr(priv->dev->dev_addr))
1569f2cedb63SDanny Kukawka 			eth_hw_addr_random(priv->dev);
1570c88460b7SHans de Goede 		pr_info("%s: device MAC address %pM\n", priv->dev->name,
1571bfab27a1SGiuseppe CAVALLARO 			priv->dev->dev_addr);
1572bfab27a1SGiuseppe CAVALLARO 	}
1573c88460b7SHans de Goede }
1574bfab27a1SGiuseppe CAVALLARO 
157532ceabcaSGiuseppe CAVALLARO /**
157632ceabcaSGiuseppe CAVALLARO  * stmmac_init_dma_engine: DMA init.
157732ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
157832ceabcaSGiuseppe CAVALLARO  * Description:
157932ceabcaSGiuseppe CAVALLARO  * It inits the DMA invoking the specific MAC/GMAC callback.
158032ceabcaSGiuseppe CAVALLARO  * Some DMA parameters can be passed from the platform;
158132ceabcaSGiuseppe CAVALLARO  * in case of these are not passed a default is kept for the MAC or GMAC.
158232ceabcaSGiuseppe CAVALLARO  */
15830f1f88a8SGiuseppe CAVALLARO static int stmmac_init_dma_engine(struct stmmac_priv *priv)
15840f1f88a8SGiuseppe CAVALLARO {
15850f1f88a8SGiuseppe CAVALLARO 	int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0;
1586b9cde0a8SGiuseppe CAVALLARO 	int mixed_burst = 0;
1587c24602efSGiuseppe CAVALLARO 	int atds = 0;
15880f1f88a8SGiuseppe CAVALLARO 
15890f1f88a8SGiuseppe CAVALLARO 	if (priv->plat->dma_cfg) {
15900f1f88a8SGiuseppe CAVALLARO 		pbl = priv->plat->dma_cfg->pbl;
15910f1f88a8SGiuseppe CAVALLARO 		fixed_burst = priv->plat->dma_cfg->fixed_burst;
1592b9cde0a8SGiuseppe CAVALLARO 		mixed_burst = priv->plat->dma_cfg->mixed_burst;
15930f1f88a8SGiuseppe CAVALLARO 		burst_len = priv->plat->dma_cfg->burst_len;
15940f1f88a8SGiuseppe CAVALLARO 	}
15950f1f88a8SGiuseppe CAVALLARO 
1596c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
1597c24602efSGiuseppe CAVALLARO 		atds = 1;
1598c24602efSGiuseppe CAVALLARO 
1599b9cde0a8SGiuseppe CAVALLARO 	return priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst,
16000f1f88a8SGiuseppe CAVALLARO 				   burst_len, priv->dma_tx_phy,
1601c24602efSGiuseppe CAVALLARO 				   priv->dma_rx_phy, atds);
16020f1f88a8SGiuseppe CAVALLARO }
16030f1f88a8SGiuseppe CAVALLARO 
1604bfab27a1SGiuseppe CAVALLARO /**
160532ceabcaSGiuseppe CAVALLARO  * stmmac_tx_timer: mitigation sw timer for tx.
16069125cdd1SGiuseppe CAVALLARO  * @data: data pointer
16079125cdd1SGiuseppe CAVALLARO  * Description:
16089125cdd1SGiuseppe CAVALLARO  * This is the timer handler to directly invoke the stmmac_tx_clean.
16099125cdd1SGiuseppe CAVALLARO  */
16109125cdd1SGiuseppe CAVALLARO static void stmmac_tx_timer(unsigned long data)
16119125cdd1SGiuseppe CAVALLARO {
16129125cdd1SGiuseppe CAVALLARO 	struct stmmac_priv *priv = (struct stmmac_priv *)data;
16139125cdd1SGiuseppe CAVALLARO 
16149125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
16159125cdd1SGiuseppe CAVALLARO }
16169125cdd1SGiuseppe CAVALLARO 
16179125cdd1SGiuseppe CAVALLARO /**
161832ceabcaSGiuseppe CAVALLARO  * stmmac_init_tx_coalesce: init tx mitigation options.
161932ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
16209125cdd1SGiuseppe CAVALLARO  * Description:
16219125cdd1SGiuseppe CAVALLARO  * This inits the transmit coalesce parameters: i.e. timer rate,
16229125cdd1SGiuseppe CAVALLARO  * timer handler and default threshold used for enabling the
16239125cdd1SGiuseppe CAVALLARO  * interrupt on completion bit.
16249125cdd1SGiuseppe CAVALLARO  */
16259125cdd1SGiuseppe CAVALLARO static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
16269125cdd1SGiuseppe CAVALLARO {
16279125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_frames = STMMAC_TX_FRAMES;
16289125cdd1SGiuseppe CAVALLARO 	priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
16299125cdd1SGiuseppe CAVALLARO 	init_timer(&priv->txtimer);
16309125cdd1SGiuseppe CAVALLARO 	priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
16319125cdd1SGiuseppe CAVALLARO 	priv->txtimer.data = (unsigned long)priv;
16329125cdd1SGiuseppe CAVALLARO 	priv->txtimer.function = stmmac_tx_timer;
16339125cdd1SGiuseppe CAVALLARO 	add_timer(&priv->txtimer);
16349125cdd1SGiuseppe CAVALLARO }
16359125cdd1SGiuseppe CAVALLARO 
16369125cdd1SGiuseppe CAVALLARO /**
1637523f11b5SSrinivas Kandagatla  * stmmac_hw_setup: setup mac in a usable state.
1638523f11b5SSrinivas Kandagatla  *  @dev : pointer to the device structure.
1639523f11b5SSrinivas Kandagatla  *  Description:
1640523f11b5SSrinivas Kandagatla  *  This function sets up the ip in a usable state.
1641523f11b5SSrinivas Kandagatla  *  Return value:
1642523f11b5SSrinivas Kandagatla  *  0 on success and an appropriate (-)ve integer as defined in errno.h
1643523f11b5SSrinivas Kandagatla  *  file on failure.
1644523f11b5SSrinivas Kandagatla  */
1645523f11b5SSrinivas Kandagatla static int stmmac_hw_setup(struct net_device *dev)
1646523f11b5SSrinivas Kandagatla {
1647523f11b5SSrinivas Kandagatla 	struct stmmac_priv *priv = netdev_priv(dev);
1648523f11b5SSrinivas Kandagatla 	int ret;
1649523f11b5SSrinivas Kandagatla 
1650523f11b5SSrinivas Kandagatla 	ret = init_dma_desc_rings(dev);
1651523f11b5SSrinivas Kandagatla 	if (ret < 0) {
1652523f11b5SSrinivas Kandagatla 		pr_err("%s: DMA descriptors initialization failed\n", __func__);
1653523f11b5SSrinivas Kandagatla 		return ret;
1654523f11b5SSrinivas Kandagatla 	}
1655523f11b5SSrinivas Kandagatla 	/* DMA initialization and SW reset */
1656523f11b5SSrinivas Kandagatla 	ret = stmmac_init_dma_engine(priv);
1657523f11b5SSrinivas Kandagatla 	if (ret < 0) {
1658523f11b5SSrinivas Kandagatla 		pr_err("%s: DMA engine initialization failed\n", __func__);
1659523f11b5SSrinivas Kandagatla 		return ret;
1660523f11b5SSrinivas Kandagatla 	}
1661523f11b5SSrinivas Kandagatla 
1662523f11b5SSrinivas Kandagatla 	/* Copy the MAC addr into the HW  */
16637ed24bbeSVince Bridgers 	priv->hw->mac->set_umac_addr(priv->hw, dev->dev_addr, 0);
1664523f11b5SSrinivas Kandagatla 
1665523f11b5SSrinivas Kandagatla 	/* If required, perform hw setup of the bus. */
1666523f11b5SSrinivas Kandagatla 	if (priv->plat->bus_setup)
1667523f11b5SSrinivas Kandagatla 		priv->plat->bus_setup(priv->ioaddr);
1668523f11b5SSrinivas Kandagatla 
1669523f11b5SSrinivas Kandagatla 	/* Initialize the MAC Core */
16707ed24bbeSVince Bridgers 	priv->hw->mac->core_init(priv->hw, dev->mtu);
1671523f11b5SSrinivas Kandagatla 
1672978aded4SGiuseppe CAVALLARO 	ret = priv->hw->mac->rx_ipc(priv->hw);
1673978aded4SGiuseppe CAVALLARO 	if (!ret) {
1674978aded4SGiuseppe CAVALLARO 		pr_warn(" RX IPC Checksum Offload disabled\n");
1675978aded4SGiuseppe CAVALLARO 		priv->plat->rx_coe = STMMAC_RX_COE_NONE;
1676d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
1677978aded4SGiuseppe CAVALLARO 	}
1678978aded4SGiuseppe CAVALLARO 
1679523f11b5SSrinivas Kandagatla 	/* Enable the MAC Rx/Tx */
1680523f11b5SSrinivas Kandagatla 	stmmac_set_mac(priv->ioaddr, true);
1681523f11b5SSrinivas Kandagatla 
1682523f11b5SSrinivas Kandagatla 	/* Set the HW DMA mode and the COE */
1683523f11b5SSrinivas Kandagatla 	stmmac_dma_operation_mode(priv);
1684523f11b5SSrinivas Kandagatla 
1685523f11b5SSrinivas Kandagatla 	stmmac_mmc_setup(priv);
1686523f11b5SSrinivas Kandagatla 
1687523f11b5SSrinivas Kandagatla 	ret = stmmac_init_ptp(priv);
16887509edd6SHans de Goede 	if (ret && ret != -EOPNOTSUPP)
1689523f11b5SSrinivas Kandagatla 		pr_warn("%s: failed PTP initialisation\n", __func__);
1690523f11b5SSrinivas Kandagatla 
1691523f11b5SSrinivas Kandagatla #ifdef CONFIG_STMMAC_DEBUG_FS
1692523f11b5SSrinivas Kandagatla 	ret = stmmac_init_fs(dev);
1693523f11b5SSrinivas Kandagatla 	if (ret < 0)
1694523f11b5SSrinivas Kandagatla 		pr_warn("%s: failed debugFS registration\n", __func__);
1695523f11b5SSrinivas Kandagatla #endif
1696523f11b5SSrinivas Kandagatla 	/* Start the ball rolling... */
1697523f11b5SSrinivas Kandagatla 	pr_debug("%s: DMA RX/TX processes started...\n", dev->name);
1698523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_tx(priv->ioaddr);
1699523f11b5SSrinivas Kandagatla 	priv->hw->dma->start_rx(priv->ioaddr);
1700523f11b5SSrinivas Kandagatla 
1701523f11b5SSrinivas Kandagatla 	/* Dump DMA/MAC registers */
1702523f11b5SSrinivas Kandagatla 	if (netif_msg_hw(priv)) {
17037ed24bbeSVince Bridgers 		priv->hw->mac->dump_regs(priv->hw);
1704523f11b5SSrinivas Kandagatla 		priv->hw->dma->dump_regs(priv->ioaddr);
1705523f11b5SSrinivas Kandagatla 	}
1706523f11b5SSrinivas Kandagatla 	priv->tx_lpi_timer = STMMAC_DEFAULT_TWT_LS;
1707523f11b5SSrinivas Kandagatla 
1708523f11b5SSrinivas Kandagatla 	priv->eee_enabled = stmmac_eee_init(priv);
1709523f11b5SSrinivas Kandagatla 
1710523f11b5SSrinivas Kandagatla 	stmmac_init_tx_coalesce(priv);
1711523f11b5SSrinivas Kandagatla 
1712523f11b5SSrinivas Kandagatla 	if ((priv->use_riwt) && (priv->hw->dma->rx_watchdog)) {
1713523f11b5SSrinivas Kandagatla 		priv->rx_riwt = MAX_DMA_RIWT;
1714523f11b5SSrinivas Kandagatla 		priv->hw->dma->rx_watchdog(priv->ioaddr, MAX_DMA_RIWT);
1715523f11b5SSrinivas Kandagatla 	}
1716523f11b5SSrinivas Kandagatla 
1717523f11b5SSrinivas Kandagatla 	if (priv->pcs && priv->hw->mac->ctrl_ane)
17187ed24bbeSVince Bridgers 		priv->hw->mac->ctrl_ane(priv->hw, 0);
1719523f11b5SSrinivas Kandagatla 
1720523f11b5SSrinivas Kandagatla 	return 0;
1721523f11b5SSrinivas Kandagatla }
1722523f11b5SSrinivas Kandagatla 
1723523f11b5SSrinivas Kandagatla /**
17247ac6653aSJeff Kirsher  *  stmmac_open - open entry point of the driver
17257ac6653aSJeff Kirsher  *  @dev : pointer to the device structure.
17267ac6653aSJeff Kirsher  *  Description:
17277ac6653aSJeff Kirsher  *  This function is the open entry point of the driver.
17287ac6653aSJeff Kirsher  *  Return value:
17297ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
17307ac6653aSJeff Kirsher  *  file on failure.
17317ac6653aSJeff Kirsher  */
17327ac6653aSJeff Kirsher static int stmmac_open(struct net_device *dev)
17337ac6653aSJeff Kirsher {
17347ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
17357ac6653aSJeff Kirsher 	int ret;
17367ac6653aSJeff Kirsher 
17374bfcbd7aSFrancesco Virlinzi 	stmmac_check_ether_addr(priv);
17384bfcbd7aSFrancesco Virlinzi 
17394d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
17404d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
17417ac6653aSJeff Kirsher 		ret = stmmac_init_phy(dev);
1742e58bb43fSGiuseppe CAVALLARO 		if (ret) {
1743e58bb43fSGiuseppe CAVALLARO 			pr_err("%s: Cannot attach to PHY (error: %d)\n",
1744e58bb43fSGiuseppe CAVALLARO 			       __func__, ret);
174589df20d9SHans de Goede 			return ret;
17467ac6653aSJeff Kirsher 		}
1747e58bb43fSGiuseppe CAVALLARO 	}
17487ac6653aSJeff Kirsher 
1749523f11b5SSrinivas Kandagatla 	/* Extra statistics */
1750523f11b5SSrinivas Kandagatla 	memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
1751523f11b5SSrinivas Kandagatla 	priv->xstats.threshold = tc;
1752523f11b5SSrinivas Kandagatla 
17537ac6653aSJeff Kirsher 	/* Create and initialize the TX/RX descriptors chains. */
17547ac6653aSJeff Kirsher 	priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
17557ac6653aSJeff Kirsher 	priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize);
17567ac6653aSJeff Kirsher 	priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
175756329137SBartlomiej Zolnierkiewicz 
17587262b7b2STobias Klauser 	ret = alloc_dma_desc_resources(priv);
175909f8d696SSrinivas Kandagatla 	if (ret < 0) {
176009f8d696SSrinivas Kandagatla 		pr_err("%s: DMA descriptors allocation failed\n", __func__);
176109f8d696SSrinivas Kandagatla 		goto dma_desc_error;
176209f8d696SSrinivas Kandagatla 	}
176309f8d696SSrinivas Kandagatla 
1764523f11b5SSrinivas Kandagatla 	ret = stmmac_hw_setup(dev);
176556329137SBartlomiej Zolnierkiewicz 	if (ret < 0) {
1766523f11b5SSrinivas Kandagatla 		pr_err("%s: Hw setup failed\n", __func__);
1767c9324d18SGiuseppe CAVALLARO 		goto init_error;
17687ac6653aSJeff Kirsher 	}
17697ac6653aSJeff Kirsher 
1770523f11b5SSrinivas Kandagatla 	if (priv->phydev)
1771523f11b5SSrinivas Kandagatla 		phy_start(priv->phydev);
17727ac6653aSJeff Kirsher 
17737ac6653aSJeff Kirsher 	/* Request the IRQ lines */
17747ac6653aSJeff Kirsher 	ret = request_irq(dev->irq, stmmac_interrupt,
17757ac6653aSJeff Kirsher 			  IRQF_SHARED, dev->name, dev);
17767ac6653aSJeff Kirsher 	if (unlikely(ret < 0)) {
17777ac6653aSJeff Kirsher 		pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
17787ac6653aSJeff Kirsher 		       __func__, dev->irq, ret);
1779c9324d18SGiuseppe CAVALLARO 		goto init_error;
17807ac6653aSJeff Kirsher 	}
17817ac6653aSJeff Kirsher 
17827a13f8f5SFrancesco Virlinzi 	/* Request the Wake IRQ in case of another line is used for WoL */
17837a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq) {
17847a13f8f5SFrancesco Virlinzi 		ret = request_irq(priv->wol_irq, stmmac_interrupt,
17857a13f8f5SFrancesco Virlinzi 				  IRQF_SHARED, dev->name, dev);
17867a13f8f5SFrancesco Virlinzi 		if (unlikely(ret < 0)) {
1787ceb69499SGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the WoL IRQ %d (%d)\n",
1788ceb69499SGiuseppe CAVALLARO 			       __func__, priv->wol_irq, ret);
1789c9324d18SGiuseppe CAVALLARO 			goto wolirq_error;
17907a13f8f5SFrancesco Virlinzi 		}
17917a13f8f5SFrancesco Virlinzi 	}
17927a13f8f5SFrancesco Virlinzi 
1793d765955dSGiuseppe CAVALLARO 	/* Request the IRQ lines */
1794d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0) {
1795d765955dSGiuseppe CAVALLARO 		ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
1796d765955dSGiuseppe CAVALLARO 				  dev->name, dev);
1797d765955dSGiuseppe CAVALLARO 		if (unlikely(ret < 0)) {
1798d765955dSGiuseppe CAVALLARO 			pr_err("%s: ERROR: allocating the LPI IRQ %d (%d)\n",
1799d765955dSGiuseppe CAVALLARO 			       __func__, priv->lpi_irq, ret);
1800c9324d18SGiuseppe CAVALLARO 			goto lpiirq_error;
1801d765955dSGiuseppe CAVALLARO 		}
1802d765955dSGiuseppe CAVALLARO 	}
1803d765955dSGiuseppe CAVALLARO 
18047ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
18057ac6653aSJeff Kirsher 	netif_start_queue(dev);
18067ac6653aSJeff Kirsher 
18077ac6653aSJeff Kirsher 	return 0;
18087ac6653aSJeff Kirsher 
1809c9324d18SGiuseppe CAVALLARO lpiirq_error:
1810d765955dSGiuseppe CAVALLARO 	if (priv->wol_irq != dev->irq)
1811d765955dSGiuseppe CAVALLARO 		free_irq(priv->wol_irq, dev);
1812c9324d18SGiuseppe CAVALLARO wolirq_error:
18137a13f8f5SFrancesco Virlinzi 	free_irq(dev->irq, dev);
18147a13f8f5SFrancesco Virlinzi 
1815c9324d18SGiuseppe CAVALLARO init_error:
1816c9324d18SGiuseppe CAVALLARO 	free_dma_desc_resources(priv);
181756329137SBartlomiej Zolnierkiewicz dma_desc_error:
18187ac6653aSJeff Kirsher 	if (priv->phydev)
18197ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
18204bfcbd7aSFrancesco Virlinzi 
18217ac6653aSJeff Kirsher 	return ret;
18227ac6653aSJeff Kirsher }
18237ac6653aSJeff Kirsher 
18247ac6653aSJeff Kirsher /**
18257ac6653aSJeff Kirsher  *  stmmac_release - close entry point of the driver
18267ac6653aSJeff Kirsher  *  @dev : device pointer.
18277ac6653aSJeff Kirsher  *  Description:
18287ac6653aSJeff Kirsher  *  This is the stop entry point of the driver.
18297ac6653aSJeff Kirsher  */
18307ac6653aSJeff Kirsher static int stmmac_release(struct net_device *dev)
18317ac6653aSJeff Kirsher {
18327ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
18337ac6653aSJeff Kirsher 
1834d765955dSGiuseppe CAVALLARO 	if (priv->eee_enabled)
1835d765955dSGiuseppe CAVALLARO 		del_timer_sync(&priv->eee_ctrl_timer);
1836d765955dSGiuseppe CAVALLARO 
18377ac6653aSJeff Kirsher 	/* Stop and disconnect the PHY */
18387ac6653aSJeff Kirsher 	if (priv->phydev) {
18397ac6653aSJeff Kirsher 		phy_stop(priv->phydev);
18407ac6653aSJeff Kirsher 		phy_disconnect(priv->phydev);
18417ac6653aSJeff Kirsher 		priv->phydev = NULL;
18427ac6653aSJeff Kirsher 	}
18437ac6653aSJeff Kirsher 
18447ac6653aSJeff Kirsher 	netif_stop_queue(dev);
18457ac6653aSJeff Kirsher 
18467ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
18477ac6653aSJeff Kirsher 
18489125cdd1SGiuseppe CAVALLARO 	del_timer_sync(&priv->txtimer);
18499125cdd1SGiuseppe CAVALLARO 
18507ac6653aSJeff Kirsher 	/* Free the IRQ lines */
18517ac6653aSJeff Kirsher 	free_irq(dev->irq, dev);
18527a13f8f5SFrancesco Virlinzi 	if (priv->wol_irq != dev->irq)
18537a13f8f5SFrancesco Virlinzi 		free_irq(priv->wol_irq, dev);
1854d7ec8584SChen-Yu Tsai 	if (priv->lpi_irq > 0)
1855d765955dSGiuseppe CAVALLARO 		free_irq(priv->lpi_irq, dev);
18567ac6653aSJeff Kirsher 
18577ac6653aSJeff Kirsher 	/* Stop TX/RX DMA and clear the descriptors */
18587ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
18597ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
18607ac6653aSJeff Kirsher 
18617ac6653aSJeff Kirsher 	/* Release and free the Rx/Tx resources */
18627ac6653aSJeff Kirsher 	free_dma_desc_resources(priv);
18637ac6653aSJeff Kirsher 
18647ac6653aSJeff Kirsher 	/* Disable the MAC Rx/Tx */
1865bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
18667ac6653aSJeff Kirsher 
18677ac6653aSJeff Kirsher 	netif_carrier_off(dev);
18687ac6653aSJeff Kirsher 
1869bfab27a1SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_DEBUG_FS
1870bfab27a1SGiuseppe CAVALLARO 	stmmac_exit_fs();
1871bfab27a1SGiuseppe CAVALLARO #endif
1872bfab27a1SGiuseppe CAVALLARO 
187392ba6888SRayagond Kokatanur 	stmmac_release_ptp(priv);
187492ba6888SRayagond Kokatanur 
18757ac6653aSJeff Kirsher 	return 0;
18767ac6653aSJeff Kirsher }
18777ac6653aSJeff Kirsher 
18787ac6653aSJeff Kirsher /**
187932ceabcaSGiuseppe CAVALLARO  *  stmmac_xmit: Tx entry point of the driver
18807ac6653aSJeff Kirsher  *  @skb : the socket buffer
18817ac6653aSJeff Kirsher  *  @dev : device pointer
188232ceabcaSGiuseppe CAVALLARO  *  Description : this is the tx entry point of the driver.
188332ceabcaSGiuseppe CAVALLARO  *  It programs the chain or the ring and supports oversized frames
188432ceabcaSGiuseppe CAVALLARO  *  and SG feature.
18857ac6653aSJeff Kirsher  */
18867ac6653aSJeff Kirsher static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
18877ac6653aSJeff Kirsher {
18887ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
18897ac6653aSJeff Kirsher 	unsigned int txsize = priv->dma_tx_size;
18907ac6653aSJeff Kirsher 	unsigned int entry;
18914a7d666aSGiuseppe CAVALLARO 	int i, csum_insertion = 0, is_jumbo = 0;
18927ac6653aSJeff Kirsher 	int nfrags = skb_shinfo(skb)->nr_frags;
18937ac6653aSJeff Kirsher 	struct dma_desc *desc, *first;
1894286a8372SGiuseppe CAVALLARO 	unsigned int nopaged_len = skb_headlen(skb);
189529896a67SGiuseppe CAVALLARO 	unsigned int enh_desc = priv->plat->enh_desc;
18967ac6653aSJeff Kirsher 
189716ee817eSFabrice Gasnier 	spin_lock(&priv->tx_lock);
189816ee817eSFabrice Gasnier 
18997ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) < nfrags + 1)) {
190016ee817eSFabrice Gasnier 		spin_unlock(&priv->tx_lock);
19017ac6653aSJeff Kirsher 		if (!netif_queue_stopped(dev)) {
19027ac6653aSJeff Kirsher 			netif_stop_queue(dev);
19037ac6653aSJeff Kirsher 			/* This is a hard error, log it. */
1904ceb69499SGiuseppe CAVALLARO 			pr_err("%s: Tx Ring full when queue awake\n", __func__);
19057ac6653aSJeff Kirsher 		}
19067ac6653aSJeff Kirsher 		return NETDEV_TX_BUSY;
19077ac6653aSJeff Kirsher 	}
19087ac6653aSJeff Kirsher 
1909d765955dSGiuseppe CAVALLARO 	if (priv->tx_path_in_lpi_mode)
1910d765955dSGiuseppe CAVALLARO 		stmmac_disable_eee_mode(priv);
1911d765955dSGiuseppe CAVALLARO 
19127ac6653aSJeff Kirsher 	entry = priv->cur_tx % txsize;
19137ac6653aSJeff Kirsher 
19147ac6653aSJeff Kirsher 	csum_insertion = (skb->ip_summed == CHECKSUM_PARTIAL);
19157ac6653aSJeff Kirsher 
1916c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc)
1917c24602efSGiuseppe CAVALLARO 		desc = (struct dma_desc *)(priv->dma_etx + entry);
1918c24602efSGiuseppe CAVALLARO 	else
19197ac6653aSJeff Kirsher 		desc = priv->dma_tx + entry;
1920c24602efSGiuseppe CAVALLARO 
19217ac6653aSJeff Kirsher 	first = desc;
19227ac6653aSJeff Kirsher 
19234a7d666aSGiuseppe CAVALLARO 	/* To program the descriptors according to the size of the frame */
192429896a67SGiuseppe CAVALLARO 	if (enh_desc)
192529896a67SGiuseppe CAVALLARO 		is_jumbo = priv->hw->mode->is_jumbo_frm(skb->len, enh_desc);
192629896a67SGiuseppe CAVALLARO 
19274a7d666aSGiuseppe CAVALLARO 	if (likely(!is_jumbo)) {
19287ac6653aSJeff Kirsher 		desc->des2 = dma_map_single(priv->device, skb->data,
19297ac6653aSJeff Kirsher 					    nopaged_len, DMA_TO_DEVICE);
1930362b37beSGiuseppe CAVALLARO 		if (dma_mapping_error(priv->device, desc->des2))
1931362b37beSGiuseppe CAVALLARO 			goto dma_map_err;
1932362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[entry].buf = desc->des2;
19337ac6653aSJeff Kirsher 		priv->hw->desc->prepare_tx_desc(desc, 1, nopaged_len,
19344a7d666aSGiuseppe CAVALLARO 						csum_insertion, priv->mode);
193529896a67SGiuseppe CAVALLARO 	} else {
1936c24602efSGiuseppe CAVALLARO 		desc = first;
193729896a67SGiuseppe CAVALLARO 		entry = priv->hw->mode->jumbo_frm(priv, skb, csum_insertion);
1938362b37beSGiuseppe CAVALLARO 		if (unlikely(entry < 0))
1939362b37beSGiuseppe CAVALLARO 			goto dma_map_err;
194029896a67SGiuseppe CAVALLARO 	}
19417ac6653aSJeff Kirsher 
19427ac6653aSJeff Kirsher 	for (i = 0; i < nfrags; i++) {
19439e903e08SEric Dumazet 		const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
19449e903e08SEric Dumazet 		int len = skb_frag_size(frag);
19457ac6653aSJeff Kirsher 
194675e4364fSdamuzi000 		priv->tx_skbuff[entry] = NULL;
19477ac6653aSJeff Kirsher 		entry = (++priv->cur_tx) % txsize;
1948c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1949c24602efSGiuseppe CAVALLARO 			desc = (struct dma_desc *)(priv->dma_etx + entry);
1950c24602efSGiuseppe CAVALLARO 		else
19517ac6653aSJeff Kirsher 			desc = priv->dma_tx + entry;
19527ac6653aSJeff Kirsher 
1953f722380dSIan Campbell 		desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len,
1954f722380dSIan Campbell 					      DMA_TO_DEVICE);
1955362b37beSGiuseppe CAVALLARO 		if (dma_mapping_error(priv->device, desc->des2))
1956362b37beSGiuseppe CAVALLARO 			goto dma_map_err; /* should reuse desc w/o issues */
1957362b37beSGiuseppe CAVALLARO 
1958362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[entry].buf = desc->des2;
1959362b37beSGiuseppe CAVALLARO 		priv->tx_skbuff_dma[entry].map_as_page = true;
19604a7d666aSGiuseppe CAVALLARO 		priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,
19614a7d666aSGiuseppe CAVALLARO 						priv->mode);
19627ac6653aSJeff Kirsher 		wmb();
19637ac6653aSJeff Kirsher 		priv->hw->desc->set_tx_owner(desc);
19648e839891SDeepak Sikri 		wmb();
19657ac6653aSJeff Kirsher 	}
19667ac6653aSJeff Kirsher 
196775e4364fSdamuzi000 	priv->tx_skbuff[entry] = skb;
196875e4364fSdamuzi000 
19699125cdd1SGiuseppe CAVALLARO 	/* Finalize the latest segment. */
19707ac6653aSJeff Kirsher 	priv->hw->desc->close_tx_desc(desc);
19717ac6653aSJeff Kirsher 
19727ac6653aSJeff Kirsher 	wmb();
19739125cdd1SGiuseppe CAVALLARO 	/* According to the coalesce parameter the IC bit for the latest
19749125cdd1SGiuseppe CAVALLARO 	 * segment could be reset and the timer re-started to invoke the
19759125cdd1SGiuseppe CAVALLARO 	 * stmmac_tx function. This approach takes care about the fragments.
19769125cdd1SGiuseppe CAVALLARO 	 */
19779125cdd1SGiuseppe CAVALLARO 	priv->tx_count_frames += nfrags + 1;
19789125cdd1SGiuseppe CAVALLARO 	if (priv->tx_coal_frames > priv->tx_count_frames) {
19799125cdd1SGiuseppe CAVALLARO 		priv->hw->desc->clear_tx_ic(desc);
19809125cdd1SGiuseppe CAVALLARO 		priv->xstats.tx_reset_ic_bit++;
19819125cdd1SGiuseppe CAVALLARO 		mod_timer(&priv->txtimer,
19829125cdd1SGiuseppe CAVALLARO 			  STMMAC_COAL_TIMER(priv->tx_coal_timer));
19839125cdd1SGiuseppe CAVALLARO 	} else
19849125cdd1SGiuseppe CAVALLARO 		priv->tx_count_frames = 0;
19857ac6653aSJeff Kirsher 
19867ac6653aSJeff Kirsher 	/* To avoid raise condition */
19877ac6653aSJeff Kirsher 	priv->hw->desc->set_tx_owner(first);
19888e839891SDeepak Sikri 	wmb();
19897ac6653aSJeff Kirsher 
19907ac6653aSJeff Kirsher 	priv->cur_tx++;
19917ac6653aSJeff Kirsher 
19927ac6653aSJeff Kirsher 	if (netif_msg_pktdata(priv)) {
199383d7af64SGiuseppe CAVALLARO 		pr_debug("%s: curr %d dirty=%d entry=%d, first=%p, nfrags=%d",
1994ceb69499SGiuseppe CAVALLARO 			__func__, (priv->cur_tx % txsize),
1995ceb69499SGiuseppe CAVALLARO 			(priv->dirty_tx % txsize), entry, first, nfrags);
199683d7af64SGiuseppe CAVALLARO 
1997c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
1998c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_etx, txsize, 1);
1999c24602efSGiuseppe CAVALLARO 		else
2000c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_tx, txsize, 0);
2001c24602efSGiuseppe CAVALLARO 
200283d7af64SGiuseppe CAVALLARO 		pr_debug(">>> frame to be transmitted: ");
20037ac6653aSJeff Kirsher 		print_pkt(skb->data, skb->len);
20047ac6653aSJeff Kirsher 	}
20057ac6653aSJeff Kirsher 	if (unlikely(stmmac_tx_avail(priv) <= (MAX_SKB_FRAGS + 1))) {
200683d7af64SGiuseppe CAVALLARO 		if (netif_msg_hw(priv))
200783d7af64SGiuseppe CAVALLARO 			pr_debug("%s: stop transmitted packets\n", __func__);
20087ac6653aSJeff Kirsher 		netif_stop_queue(dev);
20097ac6653aSJeff Kirsher 	}
20107ac6653aSJeff Kirsher 
20117ac6653aSJeff Kirsher 	dev->stats.tx_bytes += skb->len;
20127ac6653aSJeff Kirsher 
2013891434b1SRayagond Kokatanur 	if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) &&
2014891434b1SRayagond Kokatanur 		     priv->hwts_tx_en)) {
2015891434b1SRayagond Kokatanur 		/* declare that device is doing timestamping */
2016891434b1SRayagond Kokatanur 		skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
2017891434b1SRayagond Kokatanur 		priv->hw->desc->enable_tx_timestamp(first);
2018891434b1SRayagond Kokatanur 	}
2019891434b1SRayagond Kokatanur 
2020891434b1SRayagond Kokatanur 	if (!priv->hwts_tx_en)
20217ac6653aSJeff Kirsher 		skb_tx_timestamp(skb);
20227ac6653aSJeff Kirsher 
20237ac6653aSJeff Kirsher 	priv->hw->dma->enable_dma_transmission(priv->ioaddr);
20247ac6653aSJeff Kirsher 
2025a9097a96SGiuseppe CAVALLARO 	spin_unlock(&priv->tx_lock);
2026362b37beSGiuseppe CAVALLARO 	return NETDEV_TX_OK;
2027a9097a96SGiuseppe CAVALLARO 
2028362b37beSGiuseppe CAVALLARO dma_map_err:
2029362b37beSGiuseppe CAVALLARO 	dev_err(priv->device, "Tx dma map failed\n");
2030362b37beSGiuseppe CAVALLARO 	dev_kfree_skb(skb);
2031362b37beSGiuseppe CAVALLARO 	priv->dev->stats.tx_dropped++;
20327ac6653aSJeff Kirsher 	return NETDEV_TX_OK;
20337ac6653aSJeff Kirsher }
20347ac6653aSJeff Kirsher 
2035b9381985SVince Bridgers static void stmmac_rx_vlan(struct net_device *dev, struct sk_buff *skb)
2036b9381985SVince Bridgers {
2037b9381985SVince Bridgers 	struct ethhdr *ehdr;
2038b9381985SVince Bridgers 	u16 vlanid;
2039b9381985SVince Bridgers 
2040b9381985SVince Bridgers 	if ((dev->features & NETIF_F_HW_VLAN_CTAG_RX) ==
2041b9381985SVince Bridgers 	    NETIF_F_HW_VLAN_CTAG_RX &&
2042b9381985SVince Bridgers 	    !__vlan_get_tag(skb, &vlanid)) {
2043b9381985SVince Bridgers 		/* pop the vlan tag */
2044b9381985SVince Bridgers 		ehdr = (struct ethhdr *)skb->data;
2045b9381985SVince Bridgers 		memmove(skb->data + VLAN_HLEN, ehdr, ETH_ALEN * 2);
2046b9381985SVince Bridgers 		skb_pull(skb, VLAN_HLEN);
2047b9381985SVince Bridgers 		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlanid);
2048b9381985SVince Bridgers 	}
2049b9381985SVince Bridgers }
2050b9381985SVince Bridgers 
2051b9381985SVince Bridgers 
205232ceabcaSGiuseppe CAVALLARO /**
205332ceabcaSGiuseppe CAVALLARO  * stmmac_rx_refill: refill used skb preallocated buffers
205432ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
205532ceabcaSGiuseppe CAVALLARO  * Description : this is to reallocate the skb for the reception process
205632ceabcaSGiuseppe CAVALLARO  * that is based on zero-copy.
205732ceabcaSGiuseppe CAVALLARO  */
20587ac6653aSJeff Kirsher static inline void stmmac_rx_refill(struct stmmac_priv *priv)
20597ac6653aSJeff Kirsher {
20607ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
20617ac6653aSJeff Kirsher 	int bfsize = priv->dma_buf_sz;
20627ac6653aSJeff Kirsher 
20637ac6653aSJeff Kirsher 	for (; priv->cur_rx - priv->dirty_rx > 0; priv->dirty_rx++) {
20647ac6653aSJeff Kirsher 		unsigned int entry = priv->dirty_rx % rxsize;
2065c24602efSGiuseppe CAVALLARO 		struct dma_desc *p;
2066c24602efSGiuseppe CAVALLARO 
2067c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2068c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2069c24602efSGiuseppe CAVALLARO 		else
2070c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2071c24602efSGiuseppe CAVALLARO 
20727ac6653aSJeff Kirsher 		if (likely(priv->rx_skbuff[entry] == NULL)) {
20737ac6653aSJeff Kirsher 			struct sk_buff *skb;
20747ac6653aSJeff Kirsher 
2075acb600deSEric Dumazet 			skb = netdev_alloc_skb_ip_align(priv->dev, bfsize);
20767ac6653aSJeff Kirsher 
20777ac6653aSJeff Kirsher 			if (unlikely(skb == NULL))
20787ac6653aSJeff Kirsher 				break;
20797ac6653aSJeff Kirsher 
20807ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = skb;
20817ac6653aSJeff Kirsher 			priv->rx_skbuff_dma[entry] =
20827ac6653aSJeff Kirsher 			    dma_map_single(priv->device, skb->data, bfsize,
20837ac6653aSJeff Kirsher 					   DMA_FROM_DEVICE);
2084362b37beSGiuseppe CAVALLARO 			if (dma_mapping_error(priv->device,
2085362b37beSGiuseppe CAVALLARO 					      priv->rx_skbuff_dma[entry])) {
2086362b37beSGiuseppe CAVALLARO 				dev_err(priv->device, "Rx dma map failed\n");
2087362b37beSGiuseppe CAVALLARO 				dev_kfree_skb(skb);
2088362b37beSGiuseppe CAVALLARO 				break;
2089362b37beSGiuseppe CAVALLARO 			}
2090c24602efSGiuseppe CAVALLARO 			p->des2 = priv->rx_skbuff_dma[entry];
2091286a8372SGiuseppe CAVALLARO 
209229896a67SGiuseppe CAVALLARO 			priv->hw->mode->refill_desc3(priv, p);
2093286a8372SGiuseppe CAVALLARO 
209483d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv))
209583d7af64SGiuseppe CAVALLARO 				pr_debug("\trefill entry #%d\n", entry);
20967ac6653aSJeff Kirsher 		}
20977ac6653aSJeff Kirsher 		wmb();
2098c24602efSGiuseppe CAVALLARO 		priv->hw->desc->set_rx_owner(p);
20998e839891SDeepak Sikri 		wmb();
21007ac6653aSJeff Kirsher 	}
21017ac6653aSJeff Kirsher }
21027ac6653aSJeff Kirsher 
210332ceabcaSGiuseppe CAVALLARO /**
210432ceabcaSGiuseppe CAVALLARO  * stmmac_rx_refill: refill used skb preallocated buffers
210532ceabcaSGiuseppe CAVALLARO  * @priv: driver private structure
210632ceabcaSGiuseppe CAVALLARO  * @limit: napi bugget.
210732ceabcaSGiuseppe CAVALLARO  * Description :  this the function called by the napi poll method.
210832ceabcaSGiuseppe CAVALLARO  * It gets all the frames inside the ring.
210932ceabcaSGiuseppe CAVALLARO  */
21107ac6653aSJeff Kirsher static int stmmac_rx(struct stmmac_priv *priv, int limit)
21117ac6653aSJeff Kirsher {
21127ac6653aSJeff Kirsher 	unsigned int rxsize = priv->dma_rx_size;
21137ac6653aSJeff Kirsher 	unsigned int entry = priv->cur_rx % rxsize;
21147ac6653aSJeff Kirsher 	unsigned int next_entry;
21157ac6653aSJeff Kirsher 	unsigned int count = 0;
2116d2afb5bdSGiuseppe CAVALLARO 	int coe = priv->hw->rx_csum;
21177ac6653aSJeff Kirsher 
211883d7af64SGiuseppe CAVALLARO 	if (netif_msg_rx_status(priv)) {
211983d7af64SGiuseppe CAVALLARO 		pr_debug("%s: descriptor ring:\n", __func__);
2120c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2121c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_erx, rxsize, 1);
2122c24602efSGiuseppe CAVALLARO 		else
2123c24602efSGiuseppe CAVALLARO 			stmmac_display_ring((void *)priv->dma_rx, rxsize, 0);
21247ac6653aSJeff Kirsher 	}
2125c24602efSGiuseppe CAVALLARO 	while (count < limit) {
21267ac6653aSJeff Kirsher 		int status;
21279401bb5cSGiuseppe CAVALLARO 		struct dma_desc *p;
21287ac6653aSJeff Kirsher 
2129c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
2130c24602efSGiuseppe CAVALLARO 			p = (struct dma_desc *)(priv->dma_erx + entry);
2131c24602efSGiuseppe CAVALLARO 		else
2132c24602efSGiuseppe CAVALLARO 			p = priv->dma_rx + entry;
2133c24602efSGiuseppe CAVALLARO 
2134c24602efSGiuseppe CAVALLARO 		if (priv->hw->desc->get_rx_owner(p))
21357ac6653aSJeff Kirsher 			break;
21367ac6653aSJeff Kirsher 
21377ac6653aSJeff Kirsher 		count++;
21387ac6653aSJeff Kirsher 
21397ac6653aSJeff Kirsher 		next_entry = (++priv->cur_rx) % rxsize;
2140c24602efSGiuseppe CAVALLARO 		if (priv->extend_desc)
21419401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_erx + next_entry);
2142c24602efSGiuseppe CAVALLARO 		else
21439401bb5cSGiuseppe CAVALLARO 			prefetch(priv->dma_rx + next_entry);
21447ac6653aSJeff Kirsher 
21457ac6653aSJeff Kirsher 		/* read the status of the incoming frame */
2146c24602efSGiuseppe CAVALLARO 		status = priv->hw->desc->rx_status(&priv->dev->stats,
2147c24602efSGiuseppe CAVALLARO 						   &priv->xstats, p);
2148c24602efSGiuseppe CAVALLARO 		if ((priv->extend_desc) && (priv->hw->desc->rx_extended_status))
2149c24602efSGiuseppe CAVALLARO 			priv->hw->desc->rx_extended_status(&priv->dev->stats,
2150c24602efSGiuseppe CAVALLARO 							   &priv->xstats,
2151c24602efSGiuseppe CAVALLARO 							   priv->dma_erx +
2152c24602efSGiuseppe CAVALLARO 							   entry);
2153891434b1SRayagond Kokatanur 		if (unlikely(status == discard_frame)) {
21547ac6653aSJeff Kirsher 			priv->dev->stats.rx_errors++;
2155891434b1SRayagond Kokatanur 			if (priv->hwts_rx_en && !priv->extend_desc) {
2156891434b1SRayagond Kokatanur 				/* DESC2 & DESC3 will be overwitten by device
2157891434b1SRayagond Kokatanur 				 * with timestamp value, hence reinitialize
2158891434b1SRayagond Kokatanur 				 * them in stmmac_rx_refill() function so that
2159891434b1SRayagond Kokatanur 				 * device can reuse it.
2160891434b1SRayagond Kokatanur 				 */
2161891434b1SRayagond Kokatanur 				priv->rx_skbuff[entry] = NULL;
2162891434b1SRayagond Kokatanur 				dma_unmap_single(priv->device,
2163891434b1SRayagond Kokatanur 						 priv->rx_skbuff_dma[entry],
2164ceb69499SGiuseppe CAVALLARO 						 priv->dma_buf_sz,
2165ceb69499SGiuseppe CAVALLARO 						 DMA_FROM_DEVICE);
2166891434b1SRayagond Kokatanur 			}
2167891434b1SRayagond Kokatanur 		} else {
21687ac6653aSJeff Kirsher 			struct sk_buff *skb;
21697ac6653aSJeff Kirsher 			int frame_len;
21707ac6653aSJeff Kirsher 
2171ceb69499SGiuseppe CAVALLARO 			frame_len = priv->hw->desc->get_rx_frame_len(p, coe);
2172ceb69499SGiuseppe CAVALLARO 
21737ac6653aSJeff Kirsher 			/* ACS is set; GMAC core strips PAD/FCS for IEEE 802.3
2174ceb69499SGiuseppe CAVALLARO 			 * Type frames (LLC/LLC-SNAP)
2175ceb69499SGiuseppe CAVALLARO 			 */
21767ac6653aSJeff Kirsher 			if (unlikely(status != llc_snap))
21777ac6653aSJeff Kirsher 				frame_len -= ETH_FCS_LEN;
21787ac6653aSJeff Kirsher 
217983d7af64SGiuseppe CAVALLARO 			if (netif_msg_rx_status(priv)) {
21807ac6653aSJeff Kirsher 				pr_debug("\tdesc: %p [entry %d] buff=0x%x\n",
21817ac6653aSJeff Kirsher 					 p, entry, p->des2);
218283d7af64SGiuseppe CAVALLARO 				if (frame_len > ETH_FRAME_LEN)
218383d7af64SGiuseppe CAVALLARO 					pr_debug("\tframe size %d, COE: %d\n",
218483d7af64SGiuseppe CAVALLARO 						 frame_len, status);
218583d7af64SGiuseppe CAVALLARO 			}
21867ac6653aSJeff Kirsher 			skb = priv->rx_skbuff[entry];
21877ac6653aSJeff Kirsher 			if (unlikely(!skb)) {
21887ac6653aSJeff Kirsher 				pr_err("%s: Inconsistent Rx descriptor chain\n",
21897ac6653aSJeff Kirsher 				       priv->dev->name);
21907ac6653aSJeff Kirsher 				priv->dev->stats.rx_dropped++;
21917ac6653aSJeff Kirsher 				break;
21927ac6653aSJeff Kirsher 			}
21937ac6653aSJeff Kirsher 			prefetch(skb->data - NET_IP_ALIGN);
21947ac6653aSJeff Kirsher 			priv->rx_skbuff[entry] = NULL;
21957ac6653aSJeff Kirsher 
2196891434b1SRayagond Kokatanur 			stmmac_get_rx_hwtstamp(priv, entry, skb);
2197891434b1SRayagond Kokatanur 
21987ac6653aSJeff Kirsher 			skb_put(skb, frame_len);
21997ac6653aSJeff Kirsher 			dma_unmap_single(priv->device,
22007ac6653aSJeff Kirsher 					 priv->rx_skbuff_dma[entry],
22017ac6653aSJeff Kirsher 					 priv->dma_buf_sz, DMA_FROM_DEVICE);
220283d7af64SGiuseppe CAVALLARO 
22037ac6653aSJeff Kirsher 			if (netif_msg_pktdata(priv)) {
220483d7af64SGiuseppe CAVALLARO 				pr_debug("frame received (%dbytes)", frame_len);
22057ac6653aSJeff Kirsher 				print_pkt(skb->data, frame_len);
22067ac6653aSJeff Kirsher 			}
220783d7af64SGiuseppe CAVALLARO 
2208b9381985SVince Bridgers 			stmmac_rx_vlan(priv->dev, skb);
2209b9381985SVince Bridgers 
22107ac6653aSJeff Kirsher 			skb->protocol = eth_type_trans(skb, priv->dev);
22117ac6653aSJeff Kirsher 
2212ceb69499SGiuseppe CAVALLARO 			if (unlikely(!coe))
22137ac6653aSJeff Kirsher 				skb_checksum_none_assert(skb);
221462a2ab93SGiuseppe CAVALLARO 			else
22157ac6653aSJeff Kirsher 				skb->ip_summed = CHECKSUM_UNNECESSARY;
221662a2ab93SGiuseppe CAVALLARO 
22177ac6653aSJeff Kirsher 			napi_gro_receive(&priv->napi, skb);
22187ac6653aSJeff Kirsher 
22197ac6653aSJeff Kirsher 			priv->dev->stats.rx_packets++;
22207ac6653aSJeff Kirsher 			priv->dev->stats.rx_bytes += frame_len;
22217ac6653aSJeff Kirsher 		}
22227ac6653aSJeff Kirsher 		entry = next_entry;
22237ac6653aSJeff Kirsher 	}
22247ac6653aSJeff Kirsher 
22257ac6653aSJeff Kirsher 	stmmac_rx_refill(priv);
22267ac6653aSJeff Kirsher 
22277ac6653aSJeff Kirsher 	priv->xstats.rx_pkt_n += count;
22287ac6653aSJeff Kirsher 
22297ac6653aSJeff Kirsher 	return count;
22307ac6653aSJeff Kirsher }
22317ac6653aSJeff Kirsher 
22327ac6653aSJeff Kirsher /**
22337ac6653aSJeff Kirsher  *  stmmac_poll - stmmac poll method (NAPI)
22347ac6653aSJeff Kirsher  *  @napi : pointer to the napi structure.
22357ac6653aSJeff Kirsher  *  @budget : maximum number of packets that the current CPU can receive from
22367ac6653aSJeff Kirsher  *	      all interfaces.
22377ac6653aSJeff Kirsher  *  Description :
22389125cdd1SGiuseppe CAVALLARO  *  To look at the incoming frames and clear the tx resources.
22397ac6653aSJeff Kirsher  */
22407ac6653aSJeff Kirsher static int stmmac_poll(struct napi_struct *napi, int budget)
22417ac6653aSJeff Kirsher {
22427ac6653aSJeff Kirsher 	struct stmmac_priv *priv = container_of(napi, struct stmmac_priv, napi);
22437ac6653aSJeff Kirsher 	int work_done = 0;
22447ac6653aSJeff Kirsher 
22459125cdd1SGiuseppe CAVALLARO 	priv->xstats.napi_poll++;
22469125cdd1SGiuseppe CAVALLARO 	stmmac_tx_clean(priv);
22477ac6653aSJeff Kirsher 
22489125cdd1SGiuseppe CAVALLARO 	work_done = stmmac_rx(priv, budget);
22497ac6653aSJeff Kirsher 	if (work_done < budget) {
22507ac6653aSJeff Kirsher 		napi_complete(napi);
22519125cdd1SGiuseppe CAVALLARO 		stmmac_enable_dma_irq(priv);
22527ac6653aSJeff Kirsher 	}
22537ac6653aSJeff Kirsher 	return work_done;
22547ac6653aSJeff Kirsher }
22557ac6653aSJeff Kirsher 
22567ac6653aSJeff Kirsher /**
22577ac6653aSJeff Kirsher  *  stmmac_tx_timeout
22587ac6653aSJeff Kirsher  *  @dev : Pointer to net device structure
22597ac6653aSJeff Kirsher  *  Description: this function is called when a packet transmission fails to
22607284a3f1SGiuseppe CAVALLARO  *   complete within a reasonable time. The driver will mark the error in the
22617ac6653aSJeff Kirsher  *   netdev structure and arrange for the device to be reset to a sane state
22627ac6653aSJeff Kirsher  *   in order to transmit a new packet.
22637ac6653aSJeff Kirsher  */
22647ac6653aSJeff Kirsher static void stmmac_tx_timeout(struct net_device *dev)
22657ac6653aSJeff Kirsher {
22667ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22677ac6653aSJeff Kirsher 
22687ac6653aSJeff Kirsher 	/* Clear Tx resources and restart transmitting again */
22697ac6653aSJeff Kirsher 	stmmac_tx_err(priv);
22707ac6653aSJeff Kirsher }
22717ac6653aSJeff Kirsher 
22727ac6653aSJeff Kirsher /**
227301789349SJiri Pirko  *  stmmac_set_rx_mode - entry point for multicast addressing
22747ac6653aSJeff Kirsher  *  @dev : pointer to the device structure
22757ac6653aSJeff Kirsher  *  Description:
22767ac6653aSJeff Kirsher  *  This function is a driver entry point which gets called by the kernel
22777ac6653aSJeff Kirsher  *  whenever multicast addresses must be enabled/disabled.
22787ac6653aSJeff Kirsher  *  Return value:
22797ac6653aSJeff Kirsher  *  void.
22807ac6653aSJeff Kirsher  */
228101789349SJiri Pirko static void stmmac_set_rx_mode(struct net_device *dev)
22827ac6653aSJeff Kirsher {
22837ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
22847ac6653aSJeff Kirsher 
22857ac6653aSJeff Kirsher 	spin_lock(&priv->lock);
22863b57de95SVince Bridgers 	priv->hw->mac->set_filter(priv->hw, dev);
22877ac6653aSJeff Kirsher 	spin_unlock(&priv->lock);
22887ac6653aSJeff Kirsher }
22897ac6653aSJeff Kirsher 
22907ac6653aSJeff Kirsher /**
22917ac6653aSJeff Kirsher  *  stmmac_change_mtu - entry point to change MTU size for the device.
22927ac6653aSJeff Kirsher  *  @dev : device pointer.
22937ac6653aSJeff Kirsher  *  @new_mtu : the new MTU size for the device.
22947ac6653aSJeff Kirsher  *  Description: the Maximum Transfer Unit (MTU) is used by the network layer
22957ac6653aSJeff Kirsher  *  to drive packet transmission. Ethernet has an MTU of 1500 octets
22967ac6653aSJeff Kirsher  *  (ETH_DATA_LEN). This value can be changed with ifconfig.
22977ac6653aSJeff Kirsher  *  Return value:
22987ac6653aSJeff Kirsher  *  0 on success and an appropriate (-)ve integer as defined in errno.h
22997ac6653aSJeff Kirsher  *  file on failure.
23007ac6653aSJeff Kirsher  */
23017ac6653aSJeff Kirsher static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
23027ac6653aSJeff Kirsher {
23037ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23047ac6653aSJeff Kirsher 	int max_mtu;
23057ac6653aSJeff Kirsher 
23067ac6653aSJeff Kirsher 	if (netif_running(dev)) {
23077ac6653aSJeff Kirsher 		pr_err("%s: must be stopped to change its MTU\n", dev->name);
23087ac6653aSJeff Kirsher 		return -EBUSY;
23097ac6653aSJeff Kirsher 	}
23107ac6653aSJeff Kirsher 
231148febf7eSGiuseppe CAVALLARO 	if (priv->plat->enh_desc)
23127ac6653aSJeff Kirsher 		max_mtu = JUMBO_LEN;
23137ac6653aSJeff Kirsher 	else
231445db81e1SGiuseppe CAVALLARO 		max_mtu = SKB_MAX_HEAD(NET_SKB_PAD + NET_IP_ALIGN);
23157ac6653aSJeff Kirsher 
23162618abb7SVince Bridgers 	if (priv->plat->maxmtu < max_mtu)
23172618abb7SVince Bridgers 		max_mtu = priv->plat->maxmtu;
23182618abb7SVince Bridgers 
23197ac6653aSJeff Kirsher 	if ((new_mtu < 46) || (new_mtu > max_mtu)) {
23207ac6653aSJeff Kirsher 		pr_err("%s: invalid MTU, max MTU is: %d\n", dev->name, max_mtu);
23217ac6653aSJeff Kirsher 		return -EINVAL;
23227ac6653aSJeff Kirsher 	}
23237ac6653aSJeff Kirsher 
23247ac6653aSJeff Kirsher 	dev->mtu = new_mtu;
23257ac6653aSJeff Kirsher 	netdev_update_features(dev);
23267ac6653aSJeff Kirsher 
23277ac6653aSJeff Kirsher 	return 0;
23287ac6653aSJeff Kirsher }
23297ac6653aSJeff Kirsher 
2330c8f44affSMichał Mirosław static netdev_features_t stmmac_fix_features(struct net_device *dev,
2331c8f44affSMichał Mirosław 					     netdev_features_t features)
23327ac6653aSJeff Kirsher {
23337ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23347ac6653aSJeff Kirsher 
233538912bdbSDeepak SIKRI 	if (priv->plat->rx_coe == STMMAC_RX_COE_NONE)
23367ac6653aSJeff Kirsher 		features &= ~NETIF_F_RXCSUM;
2337d2afb5bdSGiuseppe CAVALLARO 
23387ac6653aSJeff Kirsher 	if (!priv->plat->tx_coe)
23397ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
23407ac6653aSJeff Kirsher 
23417ac6653aSJeff Kirsher 	/* Some GMAC devices have a bugged Jumbo frame support that
23427ac6653aSJeff Kirsher 	 * needs to have the Tx COE disabled for oversized frames
23437ac6653aSJeff Kirsher 	 * (due to limited buffer sizes). In this case we disable
2344ceb69499SGiuseppe CAVALLARO 	 * the TX csum insertionin the TDES and not use SF.
2345ceb69499SGiuseppe CAVALLARO 	 */
23467ac6653aSJeff Kirsher 	if (priv->plat->bugged_jumbo && (dev->mtu > ETH_DATA_LEN))
23477ac6653aSJeff Kirsher 		features &= ~NETIF_F_ALL_CSUM;
23487ac6653aSJeff Kirsher 
23497ac6653aSJeff Kirsher 	return features;
23507ac6653aSJeff Kirsher }
23517ac6653aSJeff Kirsher 
2352d2afb5bdSGiuseppe CAVALLARO static int stmmac_set_features(struct net_device *netdev,
2353d2afb5bdSGiuseppe CAVALLARO 			       netdev_features_t features)
2354d2afb5bdSGiuseppe CAVALLARO {
2355d2afb5bdSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(netdev);
2356d2afb5bdSGiuseppe CAVALLARO 
2357d2afb5bdSGiuseppe CAVALLARO 	/* Keep the COE Type in case of csum is supporting */
2358d2afb5bdSGiuseppe CAVALLARO 	if (features & NETIF_F_RXCSUM)
2359d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
2360d2afb5bdSGiuseppe CAVALLARO 	else
2361d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = 0;
2362d2afb5bdSGiuseppe CAVALLARO 	/* No check needed because rx_coe has been set before and it will be
2363d2afb5bdSGiuseppe CAVALLARO 	 * fixed in case of issue.
2364d2afb5bdSGiuseppe CAVALLARO 	 */
2365d2afb5bdSGiuseppe CAVALLARO 	priv->hw->mac->rx_ipc(priv->hw);
2366d2afb5bdSGiuseppe CAVALLARO 
2367d2afb5bdSGiuseppe CAVALLARO 	return 0;
2368d2afb5bdSGiuseppe CAVALLARO }
2369d2afb5bdSGiuseppe CAVALLARO 
237032ceabcaSGiuseppe CAVALLARO /**
237132ceabcaSGiuseppe CAVALLARO  *  stmmac_interrupt - main ISR
237232ceabcaSGiuseppe CAVALLARO  *  @irq: interrupt number.
237332ceabcaSGiuseppe CAVALLARO  *  @dev_id: to pass the net device pointer.
237432ceabcaSGiuseppe CAVALLARO  *  Description: this is the main driver interrupt service routine.
237532ceabcaSGiuseppe CAVALLARO  *  It calls the DMA ISR and also the core ISR to manage PMT, MMC, LPI
237632ceabcaSGiuseppe CAVALLARO  *  interrupts.
237732ceabcaSGiuseppe CAVALLARO  */
23787ac6653aSJeff Kirsher static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
23797ac6653aSJeff Kirsher {
23807ac6653aSJeff Kirsher 	struct net_device *dev = (struct net_device *)dev_id;
23817ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
23827ac6653aSJeff Kirsher 
238389f7f2cfSSrinivas Kandagatla 	if (priv->irq_wake)
238489f7f2cfSSrinivas Kandagatla 		pm_wakeup_event(priv->device, 0);
238589f7f2cfSSrinivas Kandagatla 
23867ac6653aSJeff Kirsher 	if (unlikely(!dev)) {
23877ac6653aSJeff Kirsher 		pr_err("%s: invalid dev pointer\n", __func__);
23887ac6653aSJeff Kirsher 		return IRQ_NONE;
23897ac6653aSJeff Kirsher 	}
23907ac6653aSJeff Kirsher 
23917ac6653aSJeff Kirsher 	/* To handle GMAC own interrupts */
2392d765955dSGiuseppe CAVALLARO 	if (priv->plat->has_gmac) {
23937ed24bbeSVince Bridgers 		int status = priv->hw->mac->host_irq_status(priv->hw,
23940982a0f6SGiuseppe CAVALLARO 							    &priv->xstats);
2395d765955dSGiuseppe CAVALLARO 		if (unlikely(status)) {
2396d765955dSGiuseppe CAVALLARO 			/* For LPI we need to save the tx status */
23970982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
2398d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = true;
23990982a0f6SGiuseppe CAVALLARO 			if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
2400d765955dSGiuseppe CAVALLARO 				priv->tx_path_in_lpi_mode = false;
2401d765955dSGiuseppe CAVALLARO 		}
2402d765955dSGiuseppe CAVALLARO 	}
2403d765955dSGiuseppe CAVALLARO 
2404d765955dSGiuseppe CAVALLARO 	/* To handle DMA interrupts */
24057ac6653aSJeff Kirsher 	stmmac_dma_interrupt(priv);
24067ac6653aSJeff Kirsher 
24077ac6653aSJeff Kirsher 	return IRQ_HANDLED;
24087ac6653aSJeff Kirsher }
24097ac6653aSJeff Kirsher 
24107ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
24117ac6653aSJeff Kirsher /* Polling receive - used by NETCONSOLE and other diagnostic tools
2412ceb69499SGiuseppe CAVALLARO  * to allow network I/O with interrupts disabled.
2413ceb69499SGiuseppe CAVALLARO  */
24147ac6653aSJeff Kirsher static void stmmac_poll_controller(struct net_device *dev)
24157ac6653aSJeff Kirsher {
24167ac6653aSJeff Kirsher 	disable_irq(dev->irq);
24177ac6653aSJeff Kirsher 	stmmac_interrupt(dev->irq, dev);
24187ac6653aSJeff Kirsher 	enable_irq(dev->irq);
24197ac6653aSJeff Kirsher }
24207ac6653aSJeff Kirsher #endif
24217ac6653aSJeff Kirsher 
24227ac6653aSJeff Kirsher /**
24237ac6653aSJeff Kirsher  *  stmmac_ioctl - Entry point for the Ioctl
24247ac6653aSJeff Kirsher  *  @dev: Device pointer.
24257ac6653aSJeff Kirsher  *  @rq: An IOCTL specefic structure, that can contain a pointer to
24267ac6653aSJeff Kirsher  *  a proprietary structure used to pass information to the driver.
24277ac6653aSJeff Kirsher  *  @cmd: IOCTL command
24287ac6653aSJeff Kirsher  *  Description:
242932ceabcaSGiuseppe CAVALLARO  *  Currently it supports the phy_mii_ioctl(...) and HW time stamping.
24307ac6653aSJeff Kirsher  */
24317ac6653aSJeff Kirsher static int stmmac_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
24327ac6653aSJeff Kirsher {
24337ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(dev);
2434891434b1SRayagond Kokatanur 	int ret = -EOPNOTSUPP;
24357ac6653aSJeff Kirsher 
24367ac6653aSJeff Kirsher 	if (!netif_running(dev))
24377ac6653aSJeff Kirsher 		return -EINVAL;
24387ac6653aSJeff Kirsher 
2439891434b1SRayagond Kokatanur 	switch (cmd) {
2440891434b1SRayagond Kokatanur 	case SIOCGMIIPHY:
2441891434b1SRayagond Kokatanur 	case SIOCGMIIREG:
2442891434b1SRayagond Kokatanur 	case SIOCSMIIREG:
24437ac6653aSJeff Kirsher 		if (!priv->phydev)
24447ac6653aSJeff Kirsher 			return -EINVAL;
24457ac6653aSJeff Kirsher 		ret = phy_mii_ioctl(priv->phydev, rq, cmd);
2446891434b1SRayagond Kokatanur 		break;
2447891434b1SRayagond Kokatanur 	case SIOCSHWTSTAMP:
2448891434b1SRayagond Kokatanur 		ret = stmmac_hwtstamp_ioctl(dev, rq);
2449891434b1SRayagond Kokatanur 		break;
2450891434b1SRayagond Kokatanur 	default:
2451891434b1SRayagond Kokatanur 		break;
2452891434b1SRayagond Kokatanur 	}
24537ac6653aSJeff Kirsher 
24547ac6653aSJeff Kirsher 	return ret;
24557ac6653aSJeff Kirsher }
24567ac6653aSJeff Kirsher 
24577ac29055SGiuseppe CAVALLARO #ifdef CONFIG_STMMAC_DEBUG_FS
24587ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_fs_dir;
24597ac29055SGiuseppe CAVALLARO static struct dentry *stmmac_rings_status;
2460e7434821SGiuseppe CAVALLARO static struct dentry *stmmac_dma_cap;
24617ac29055SGiuseppe CAVALLARO 
2462c24602efSGiuseppe CAVALLARO static void sysfs_display_ring(void *head, int size, int extend_desc,
2463c24602efSGiuseppe CAVALLARO 			       struct seq_file *seq)
24647ac29055SGiuseppe CAVALLARO {
24657ac29055SGiuseppe CAVALLARO 	int i;
2466c24602efSGiuseppe CAVALLARO 	struct dma_extended_desc *ep = (struct dma_extended_desc *)head;
2467c24602efSGiuseppe CAVALLARO 	struct dma_desc *p = (struct dma_desc *)head;
24687ac29055SGiuseppe CAVALLARO 
2469c24602efSGiuseppe CAVALLARO 	for (i = 0; i < size; i++) {
2470c24602efSGiuseppe CAVALLARO 		u64 x;
2471c24602efSGiuseppe CAVALLARO 		if (extend_desc) {
2472c24602efSGiuseppe CAVALLARO 			x = *(u64 *) ep;
2473c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2474c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2475c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2476c24602efSGiuseppe CAVALLARO 				   ep->basic.des2, ep->basic.des3);
2477c24602efSGiuseppe CAVALLARO 			ep++;
2478c24602efSGiuseppe CAVALLARO 		} else {
2479c24602efSGiuseppe CAVALLARO 			x = *(u64 *) p;
2480c24602efSGiuseppe CAVALLARO 			seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
2481c24602efSGiuseppe CAVALLARO 				   i, (unsigned int)virt_to_phys(ep),
2482c24602efSGiuseppe CAVALLARO 				   (unsigned int)x, (unsigned int)(x >> 32),
2483c24602efSGiuseppe CAVALLARO 				   p->des2, p->des3);
2484c24602efSGiuseppe CAVALLARO 			p++;
2485c24602efSGiuseppe CAVALLARO 		}
24867ac29055SGiuseppe CAVALLARO 		seq_printf(seq, "\n");
24877ac29055SGiuseppe CAVALLARO 	}
2488c24602efSGiuseppe CAVALLARO }
24897ac29055SGiuseppe CAVALLARO 
2490c24602efSGiuseppe CAVALLARO static int stmmac_sysfs_ring_read(struct seq_file *seq, void *v)
2491c24602efSGiuseppe CAVALLARO {
2492c24602efSGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2493c24602efSGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2494c24602efSGiuseppe CAVALLARO 	unsigned int txsize = priv->dma_tx_size;
2495c24602efSGiuseppe CAVALLARO 	unsigned int rxsize = priv->dma_rx_size;
24967ac29055SGiuseppe CAVALLARO 
2497c24602efSGiuseppe CAVALLARO 	if (priv->extend_desc) {
2498c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended RX descriptor ring:\n");
2499c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_erx, rxsize, 1, seq);
2500c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "Extended TX descriptor ring:\n");
2501c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_etx, txsize, 1, seq);
2502c24602efSGiuseppe CAVALLARO 	} else {
2503c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "RX descriptor ring:\n");
2504c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_rx, rxsize, 0, seq);
2505c24602efSGiuseppe CAVALLARO 		seq_printf(seq, "TX descriptor ring:\n");
2506c24602efSGiuseppe CAVALLARO 		sysfs_display_ring((void *)priv->dma_tx, txsize, 0, seq);
25077ac29055SGiuseppe CAVALLARO 	}
25087ac29055SGiuseppe CAVALLARO 
25097ac29055SGiuseppe CAVALLARO 	return 0;
25107ac29055SGiuseppe CAVALLARO }
25117ac29055SGiuseppe CAVALLARO 
25127ac29055SGiuseppe CAVALLARO static int stmmac_sysfs_ring_open(struct inode *inode, struct file *file)
25137ac29055SGiuseppe CAVALLARO {
25147ac29055SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_ring_read, inode->i_private);
25157ac29055SGiuseppe CAVALLARO }
25167ac29055SGiuseppe CAVALLARO 
25177ac29055SGiuseppe CAVALLARO static const struct file_operations stmmac_rings_status_fops = {
25187ac29055SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
25197ac29055SGiuseppe CAVALLARO 	.open = stmmac_sysfs_ring_open,
25207ac29055SGiuseppe CAVALLARO 	.read = seq_read,
25217ac29055SGiuseppe CAVALLARO 	.llseek = seq_lseek,
252274863948SDjalal Harouni 	.release = single_release,
25237ac29055SGiuseppe CAVALLARO };
25247ac29055SGiuseppe CAVALLARO 
2525e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_read(struct seq_file *seq, void *v)
2526e7434821SGiuseppe CAVALLARO {
2527e7434821SGiuseppe CAVALLARO 	struct net_device *dev = seq->private;
2528e7434821SGiuseppe CAVALLARO 	struct stmmac_priv *priv = netdev_priv(dev);
2529e7434821SGiuseppe CAVALLARO 
253019e30c14SGiuseppe CAVALLARO 	if (!priv->hw_cap_support) {
2531e7434821SGiuseppe CAVALLARO 		seq_printf(seq, "DMA HW features not supported\n");
2532e7434821SGiuseppe CAVALLARO 		return 0;
2533e7434821SGiuseppe CAVALLARO 	}
2534e7434821SGiuseppe CAVALLARO 
2535e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2536e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tDMA HW features\n");
2537e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "==============================\n");
2538e7434821SGiuseppe CAVALLARO 
2539e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t10/100 Mbps %s\n",
2540e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_10_100) ? "Y" : "N");
2541e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t1000 Mbps %s\n",
2542e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.mbps_1000) ? "Y" : "N");
2543e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHalf duple %s\n",
2544e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.half_duplex) ? "Y" : "N");
2545e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tHash Filter: %s\n",
2546e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.hash_filter) ? "Y" : "N");
2547e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tMultiple MAC address registers: %s\n",
2548e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.multi_addr) ? "Y" : "N");
2549e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPCS (TBI/SGMII/RTBI PHY interfatces): %s\n",
2550e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pcs) ? "Y" : "N");
2551e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tSMA (MDIO) Interface: %s\n",
2552e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.sma_mdio) ? "Y" : "N");
2553e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Remote wake up: %s\n",
2554e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_remote_wake_up) ? "Y" : "N");
2555e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tPMT Magic Frame: %s\n",
2556e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.pmt_magic_frame) ? "Y" : "N");
2557e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRMON module: %s\n",
2558e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rmon) ? "Y" : "N");
2559e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2002 Time Stamp: %s\n",
2560e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.time_stamp) ? "Y" : "N");
2561e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIEEE 1588-2008 Advanced Time Stamp:%s\n",
2562e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.atime_stamp) ? "Y" : "N");
2563e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\t802.3az - Energy-Efficient Ethernet (EEE) %s\n",
2564e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.eee) ? "Y" : "N");
2565e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tAV features: %s\n", (priv->dma_cap.av) ? "Y" : "N");
2566e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tChecksum Offload in TX: %s\n",
2567e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.tx_coe) ? "Y" : "N");
2568e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type1) in RX: %s\n",
2569e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type1) ? "Y" : "N");
2570e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tIP Checksum Offload (type2) in RX: %s\n",
2571e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rx_coe_type2) ? "Y" : "N");
2572e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tRXFIFO > 2048bytes: %s\n",
2573e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.rxfifo_over_2048) ? "Y" : "N");
2574e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional RX channel: %d\n",
2575e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_rx_channel);
2576e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tNumber of Additional TX channel: %d\n",
2577e7434821SGiuseppe CAVALLARO 		   priv->dma_cap.number_tx_channel);
2578e7434821SGiuseppe CAVALLARO 	seq_printf(seq, "\tEnhanced descriptors: %s\n",
2579e7434821SGiuseppe CAVALLARO 		   (priv->dma_cap.enh_desc) ? "Y" : "N");
2580e7434821SGiuseppe CAVALLARO 
2581e7434821SGiuseppe CAVALLARO 	return 0;
2582e7434821SGiuseppe CAVALLARO }
2583e7434821SGiuseppe CAVALLARO 
2584e7434821SGiuseppe CAVALLARO static int stmmac_sysfs_dma_cap_open(struct inode *inode, struct file *file)
2585e7434821SGiuseppe CAVALLARO {
2586e7434821SGiuseppe CAVALLARO 	return single_open(file, stmmac_sysfs_dma_cap_read, inode->i_private);
2587e7434821SGiuseppe CAVALLARO }
2588e7434821SGiuseppe CAVALLARO 
2589e7434821SGiuseppe CAVALLARO static const struct file_operations stmmac_dma_cap_fops = {
2590e7434821SGiuseppe CAVALLARO 	.owner = THIS_MODULE,
2591e7434821SGiuseppe CAVALLARO 	.open = stmmac_sysfs_dma_cap_open,
2592e7434821SGiuseppe CAVALLARO 	.read = seq_read,
2593e7434821SGiuseppe CAVALLARO 	.llseek = seq_lseek,
259474863948SDjalal Harouni 	.release = single_release,
2595e7434821SGiuseppe CAVALLARO };
2596e7434821SGiuseppe CAVALLARO 
25977ac29055SGiuseppe CAVALLARO static int stmmac_init_fs(struct net_device *dev)
25987ac29055SGiuseppe CAVALLARO {
25997ac29055SGiuseppe CAVALLARO 	/* Create debugfs entries */
26007ac29055SGiuseppe CAVALLARO 	stmmac_fs_dir = debugfs_create_dir(STMMAC_RESOURCE_NAME, NULL);
26017ac29055SGiuseppe CAVALLARO 
26027ac29055SGiuseppe CAVALLARO 	if (!stmmac_fs_dir || IS_ERR(stmmac_fs_dir)) {
26037ac29055SGiuseppe CAVALLARO 		pr_err("ERROR %s, debugfs create directory failed\n",
26047ac29055SGiuseppe CAVALLARO 		       STMMAC_RESOURCE_NAME);
26057ac29055SGiuseppe CAVALLARO 
26067ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
26077ac29055SGiuseppe CAVALLARO 	}
26087ac29055SGiuseppe CAVALLARO 
26097ac29055SGiuseppe CAVALLARO 	/* Entry to report DMA RX/TX rings */
26107ac29055SGiuseppe CAVALLARO 	stmmac_rings_status = debugfs_create_file("descriptors_status",
26117ac29055SGiuseppe CAVALLARO 						  S_IRUGO, stmmac_fs_dir, dev,
26127ac29055SGiuseppe CAVALLARO 						  &stmmac_rings_status_fops);
26137ac29055SGiuseppe CAVALLARO 
26147ac29055SGiuseppe CAVALLARO 	if (!stmmac_rings_status || IS_ERR(stmmac_rings_status)) {
26157ac29055SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac ring debugfs file\n");
26167ac29055SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
26177ac29055SGiuseppe CAVALLARO 
26187ac29055SGiuseppe CAVALLARO 		return -ENOMEM;
26197ac29055SGiuseppe CAVALLARO 	}
26207ac29055SGiuseppe CAVALLARO 
2621e7434821SGiuseppe CAVALLARO 	/* Entry to report the DMA HW features */
2622e7434821SGiuseppe CAVALLARO 	stmmac_dma_cap = debugfs_create_file("dma_cap", S_IRUGO, stmmac_fs_dir,
2623e7434821SGiuseppe CAVALLARO 					     dev, &stmmac_dma_cap_fops);
2624e7434821SGiuseppe CAVALLARO 
2625e7434821SGiuseppe CAVALLARO 	if (!stmmac_dma_cap || IS_ERR(stmmac_dma_cap)) {
2626e7434821SGiuseppe CAVALLARO 		pr_info("ERROR creating stmmac MMC debugfs file\n");
2627e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_rings_status);
2628e7434821SGiuseppe CAVALLARO 		debugfs_remove(stmmac_fs_dir);
2629e7434821SGiuseppe CAVALLARO 
2630e7434821SGiuseppe CAVALLARO 		return -ENOMEM;
2631e7434821SGiuseppe CAVALLARO 	}
2632e7434821SGiuseppe CAVALLARO 
26337ac29055SGiuseppe CAVALLARO 	return 0;
26347ac29055SGiuseppe CAVALLARO }
26357ac29055SGiuseppe CAVALLARO 
26367ac29055SGiuseppe CAVALLARO static void stmmac_exit_fs(void)
26377ac29055SGiuseppe CAVALLARO {
26387ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_rings_status);
2639e7434821SGiuseppe CAVALLARO 	debugfs_remove(stmmac_dma_cap);
26407ac29055SGiuseppe CAVALLARO 	debugfs_remove(stmmac_fs_dir);
26417ac29055SGiuseppe CAVALLARO }
26427ac29055SGiuseppe CAVALLARO #endif /* CONFIG_STMMAC_DEBUG_FS */
26437ac29055SGiuseppe CAVALLARO 
26447ac6653aSJeff Kirsher static const struct net_device_ops stmmac_netdev_ops = {
26457ac6653aSJeff Kirsher 	.ndo_open = stmmac_open,
26467ac6653aSJeff Kirsher 	.ndo_start_xmit = stmmac_xmit,
26477ac6653aSJeff Kirsher 	.ndo_stop = stmmac_release,
26487ac6653aSJeff Kirsher 	.ndo_change_mtu = stmmac_change_mtu,
26497ac6653aSJeff Kirsher 	.ndo_fix_features = stmmac_fix_features,
2650d2afb5bdSGiuseppe CAVALLARO 	.ndo_set_features = stmmac_set_features,
265101789349SJiri Pirko 	.ndo_set_rx_mode = stmmac_set_rx_mode,
26527ac6653aSJeff Kirsher 	.ndo_tx_timeout = stmmac_tx_timeout,
26537ac6653aSJeff Kirsher 	.ndo_do_ioctl = stmmac_ioctl,
26547ac6653aSJeff Kirsher #ifdef CONFIG_NET_POLL_CONTROLLER
26557ac6653aSJeff Kirsher 	.ndo_poll_controller = stmmac_poll_controller,
26567ac6653aSJeff Kirsher #endif
26577ac6653aSJeff Kirsher 	.ndo_set_mac_address = eth_mac_addr,
26587ac6653aSJeff Kirsher };
26597ac6653aSJeff Kirsher 
26607ac6653aSJeff Kirsher /**
2661cf3f047bSGiuseppe CAVALLARO  *  stmmac_hw_init - Init the MAC device
266232ceabcaSGiuseppe CAVALLARO  *  @priv: driver private structure
2663cf3f047bSGiuseppe CAVALLARO  *  Description: this function detects which MAC device
2664cf3f047bSGiuseppe CAVALLARO  *  (GMAC/MAC10-100) has to attached, checks the HW capability
2665cf3f047bSGiuseppe CAVALLARO  *  (if supported) and sets the driver's features (for example
2666cf3f047bSGiuseppe CAVALLARO  *  to use the ring or chaine mode or support the normal/enh
2667cf3f047bSGiuseppe CAVALLARO  *  descriptor structure).
2668cf3f047bSGiuseppe CAVALLARO  */
2669cf3f047bSGiuseppe CAVALLARO static int stmmac_hw_init(struct stmmac_priv *priv)
2670cf3f047bSGiuseppe CAVALLARO {
2671cf3f047bSGiuseppe CAVALLARO 	struct mac_device_info *mac;
2672cf3f047bSGiuseppe CAVALLARO 
2673cf3f047bSGiuseppe CAVALLARO 	/* Identify the MAC HW device */
267403f2eecdSMarc Kleine-Budde 	if (priv->plat->has_gmac) {
267503f2eecdSMarc Kleine-Budde 		priv->dev->priv_flags |= IFF_UNICAST_FLT;
26763b57de95SVince Bridgers 		mac = dwmac1000_setup(priv->ioaddr,
26773b57de95SVince Bridgers 				      priv->plat->multicast_filter_bins,
26783b57de95SVince Bridgers 				      priv->plat->unicast_filter_entries);
267903f2eecdSMarc Kleine-Budde 	} else {
2680cf3f047bSGiuseppe CAVALLARO 		mac = dwmac100_setup(priv->ioaddr);
268103f2eecdSMarc Kleine-Budde 	}
2682cf3f047bSGiuseppe CAVALLARO 	if (!mac)
2683cf3f047bSGiuseppe CAVALLARO 		return -ENOMEM;
2684cf3f047bSGiuseppe CAVALLARO 
2685cf3f047bSGiuseppe CAVALLARO 	priv->hw = mac;
2686cf3f047bSGiuseppe CAVALLARO 
2687cf3f047bSGiuseppe CAVALLARO 	/* Get and dump the chip ID */
2688cffb13f4SGiuseppe CAVALLARO 	priv->synopsys_id = stmmac_get_synopsys_id(priv);
2689cf3f047bSGiuseppe CAVALLARO 
26904a7d666aSGiuseppe CAVALLARO 	/* To use the chained or ring mode */
26914a7d666aSGiuseppe CAVALLARO 	if (chain_mode) {
269229896a67SGiuseppe CAVALLARO 		priv->hw->mode = &chain_mode_ops;
26934a7d666aSGiuseppe CAVALLARO 		pr_info(" Chain mode enabled\n");
26944a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_CHAIN_MODE;
26954a7d666aSGiuseppe CAVALLARO 	} else {
269629896a67SGiuseppe CAVALLARO 		priv->hw->mode = &ring_mode_ops;
26974a7d666aSGiuseppe CAVALLARO 		pr_info(" Ring mode enabled\n");
26984a7d666aSGiuseppe CAVALLARO 		priv->mode = STMMAC_RING_MODE;
26994a7d666aSGiuseppe CAVALLARO 	}
27004a7d666aSGiuseppe CAVALLARO 
2701cf3f047bSGiuseppe CAVALLARO 	/* Get the HW capability (new GMAC newer than 3.50a) */
2702cf3f047bSGiuseppe CAVALLARO 	priv->hw_cap_support = stmmac_get_hw_features(priv);
2703cf3f047bSGiuseppe CAVALLARO 	if (priv->hw_cap_support) {
2704cf3f047bSGiuseppe CAVALLARO 		pr_info(" DMA HW capability register supported");
2705cf3f047bSGiuseppe CAVALLARO 
2706cf3f047bSGiuseppe CAVALLARO 		/* We can override some gmac/dma configuration fields: e.g.
2707cf3f047bSGiuseppe CAVALLARO 		 * enh_desc, tx_coe (e.g. that are passed through the
2708cf3f047bSGiuseppe CAVALLARO 		 * platform) with the values from the HW capability
2709cf3f047bSGiuseppe CAVALLARO 		 * register (if supported).
2710cf3f047bSGiuseppe CAVALLARO 		 */
2711cf3f047bSGiuseppe CAVALLARO 		priv->plat->enh_desc = priv->dma_cap.enh_desc;
2712cf3f047bSGiuseppe CAVALLARO 		priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up;
271338912bdbSDeepak SIKRI 
271438912bdbSDeepak SIKRI 		priv->plat->tx_coe = priv->dma_cap.tx_coe;
271538912bdbSDeepak SIKRI 
271638912bdbSDeepak SIKRI 		if (priv->dma_cap.rx_coe_type2)
271738912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE2;
271838912bdbSDeepak SIKRI 		else if (priv->dma_cap.rx_coe_type1)
271938912bdbSDeepak SIKRI 			priv->plat->rx_coe = STMMAC_RX_COE_TYPE1;
272038912bdbSDeepak SIKRI 
2721cf3f047bSGiuseppe CAVALLARO 	} else
2722cf3f047bSGiuseppe CAVALLARO 		pr_info(" No HW DMA feature register supported");
2723cf3f047bSGiuseppe CAVALLARO 
272461369d02SByungho An 	/* To use alternate (extended) or normal descriptor structures */
272561369d02SByungho An 	stmmac_selec_desc_mode(priv);
272661369d02SByungho An 
2727d2afb5bdSGiuseppe CAVALLARO 	if (priv->plat->rx_coe) {
2728d2afb5bdSGiuseppe CAVALLARO 		priv->hw->rx_csum = priv->plat->rx_coe;
272938912bdbSDeepak SIKRI 		pr_info(" RX Checksum Offload Engine supported (type %d)\n",
273038912bdbSDeepak SIKRI 			priv->plat->rx_coe);
2731d2afb5bdSGiuseppe CAVALLARO 	}
2732cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->tx_coe)
2733cf3f047bSGiuseppe CAVALLARO 		pr_info(" TX Checksum insertion supported\n");
2734cf3f047bSGiuseppe CAVALLARO 
2735cf3f047bSGiuseppe CAVALLARO 	if (priv->plat->pmt) {
2736cf3f047bSGiuseppe CAVALLARO 		pr_info(" Wake-Up On Lan supported\n");
2737cf3f047bSGiuseppe CAVALLARO 		device_set_wakeup_capable(priv->device, 1);
2738cf3f047bSGiuseppe CAVALLARO 	}
2739cf3f047bSGiuseppe CAVALLARO 
2740c24602efSGiuseppe CAVALLARO 	return 0;
2741cf3f047bSGiuseppe CAVALLARO }
2742cf3f047bSGiuseppe CAVALLARO 
2743cf3f047bSGiuseppe CAVALLARO /**
2744bfab27a1SGiuseppe CAVALLARO  * stmmac_dvr_probe
2745bfab27a1SGiuseppe CAVALLARO  * @device: device pointer
2746ff3dd78cSGiuseppe CAVALLARO  * @plat_dat: platform data pointer
2747ff3dd78cSGiuseppe CAVALLARO  * @addr: iobase memory address
2748bfab27a1SGiuseppe CAVALLARO  * Description: this is the main probe function used to
2749bfab27a1SGiuseppe CAVALLARO  * call the alloc_etherdev, allocate the priv structure.
27507ac6653aSJeff Kirsher  */
2751bfab27a1SGiuseppe CAVALLARO struct stmmac_priv *stmmac_dvr_probe(struct device *device,
2752cf3f047bSGiuseppe CAVALLARO 				     struct plat_stmmacenet_data *plat_dat,
2753cf3f047bSGiuseppe CAVALLARO 				     void __iomem *addr)
27547ac6653aSJeff Kirsher {
27557ac6653aSJeff Kirsher 	int ret = 0;
2756bfab27a1SGiuseppe CAVALLARO 	struct net_device *ndev = NULL;
2757bfab27a1SGiuseppe CAVALLARO 	struct stmmac_priv *priv;
27587ac6653aSJeff Kirsher 
2759bfab27a1SGiuseppe CAVALLARO 	ndev = alloc_etherdev(sizeof(struct stmmac_priv));
276041de8d4cSJoe Perches 	if (!ndev)
2761bfab27a1SGiuseppe CAVALLARO 		return NULL;
27627ac6653aSJeff Kirsher 
2763bfab27a1SGiuseppe CAVALLARO 	SET_NETDEV_DEV(ndev, device);
27647ac6653aSJeff Kirsher 
2765bfab27a1SGiuseppe CAVALLARO 	priv = netdev_priv(ndev);
2766bfab27a1SGiuseppe CAVALLARO 	priv->device = device;
2767bfab27a1SGiuseppe CAVALLARO 	priv->dev = ndev;
2768bfab27a1SGiuseppe CAVALLARO 
2769bfab27a1SGiuseppe CAVALLARO 	stmmac_set_ethtool_ops(ndev);
2770cf3f047bSGiuseppe CAVALLARO 	priv->pause = pause;
2771cf3f047bSGiuseppe CAVALLARO 	priv->plat = plat_dat;
2772cf3f047bSGiuseppe CAVALLARO 	priv->ioaddr = addr;
2773cf3f047bSGiuseppe CAVALLARO 	priv->dev->base_addr = (unsigned long)addr;
2774bfab27a1SGiuseppe CAVALLARO 
2775cf3f047bSGiuseppe CAVALLARO 	/* Verify driver arguments */
2776cf3f047bSGiuseppe CAVALLARO 	stmmac_verify_args();
2777cf3f047bSGiuseppe CAVALLARO 
2778cf3f047bSGiuseppe CAVALLARO 	/* Override with kernel parameters if supplied XXX CRS XXX
2779ceb69499SGiuseppe CAVALLARO 	 * this needs to have multiple instances
2780ceb69499SGiuseppe CAVALLARO 	 */
2781cf3f047bSGiuseppe CAVALLARO 	if ((phyaddr >= 0) && (phyaddr <= 31))
2782cf3f047bSGiuseppe CAVALLARO 		priv->plat->phy_addr = phyaddr;
2783cf3f047bSGiuseppe CAVALLARO 
278462866e98SChen-Yu Tsai 	priv->stmmac_clk = devm_clk_get(priv->device, STMMAC_RESOURCE_NAME);
278562866e98SChen-Yu Tsai 	if (IS_ERR(priv->stmmac_clk)) {
278662866e98SChen-Yu Tsai 		dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
278762866e98SChen-Yu Tsai 			 __func__);
2788c5bb86c3SKweh, Hock Leong 		/* If failed to obtain stmmac_clk and specific clk_csr value
2789c5bb86c3SKweh, Hock Leong 		 * is NOT passed from the platform, probe fail.
2790c5bb86c3SKweh, Hock Leong 		 */
2791c5bb86c3SKweh, Hock Leong 		if (!priv->plat->clk_csr) {
2792c5e4ddbdSChen-Yu Tsai 			ret = PTR_ERR(priv->stmmac_clk);
279362866e98SChen-Yu Tsai 			goto error_clk_get;
2794c5bb86c3SKweh, Hock Leong 		} else {
2795c5bb86c3SKweh, Hock Leong 			priv->stmmac_clk = NULL;
2796c5bb86c3SKweh, Hock Leong 		}
279762866e98SChen-Yu Tsai 	}
279862866e98SChen-Yu Tsai 	clk_prepare_enable(priv->stmmac_clk);
279962866e98SChen-Yu Tsai 
2800c5e4ddbdSChen-Yu Tsai 	priv->stmmac_rst = devm_reset_control_get(priv->device,
2801c5e4ddbdSChen-Yu Tsai 						  STMMAC_RESOURCE_NAME);
2802c5e4ddbdSChen-Yu Tsai 	if (IS_ERR(priv->stmmac_rst)) {
2803c5e4ddbdSChen-Yu Tsai 		if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
2804c5e4ddbdSChen-Yu Tsai 			ret = -EPROBE_DEFER;
2805c5e4ddbdSChen-Yu Tsai 			goto error_hw_init;
2806c5e4ddbdSChen-Yu Tsai 		}
2807c5e4ddbdSChen-Yu Tsai 		dev_info(priv->device, "no reset control found\n");
2808c5e4ddbdSChen-Yu Tsai 		priv->stmmac_rst = NULL;
2809c5e4ddbdSChen-Yu Tsai 	}
2810c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2811c5e4ddbdSChen-Yu Tsai 		reset_control_deassert(priv->stmmac_rst);
2812c5e4ddbdSChen-Yu Tsai 
2813cf3f047bSGiuseppe CAVALLARO 	/* Init MAC and get the capabilities */
2814c24602efSGiuseppe CAVALLARO 	ret = stmmac_hw_init(priv);
2815c24602efSGiuseppe CAVALLARO 	if (ret)
281662866e98SChen-Yu Tsai 		goto error_hw_init;
2817cf3f047bSGiuseppe CAVALLARO 
2818cf3f047bSGiuseppe CAVALLARO 	ndev->netdev_ops = &stmmac_netdev_ops;
2819cf3f047bSGiuseppe CAVALLARO 
2820cf3f047bSGiuseppe CAVALLARO 	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
2821cf3f047bSGiuseppe CAVALLARO 			    NETIF_F_RXCSUM;
2822bfab27a1SGiuseppe CAVALLARO 	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;
2823bfab27a1SGiuseppe CAVALLARO 	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);
28247ac6653aSJeff Kirsher #ifdef STMMAC_VLAN_TAG_USED
28257ac6653aSJeff Kirsher 	/* Both mac100 and gmac support receive VLAN tag detection */
2826f646968fSPatrick McHardy 	ndev->features |= NETIF_F_HW_VLAN_CTAG_RX;
28277ac6653aSJeff Kirsher #endif
28287ac6653aSJeff Kirsher 	priv->msg_enable = netif_msg_init(debug, default_msg_level);
28297ac6653aSJeff Kirsher 
28307ac6653aSJeff Kirsher 	if (flow_ctrl)
28317ac6653aSJeff Kirsher 		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */
28327ac6653aSJeff Kirsher 
283362a2ab93SGiuseppe CAVALLARO 	/* Rx Watchdog is available in the COREs newer than the 3.40.
283462a2ab93SGiuseppe CAVALLARO 	 * In some case, for example on bugged HW this feature
283562a2ab93SGiuseppe CAVALLARO 	 * has to be disable and this can be done by passing the
283662a2ab93SGiuseppe CAVALLARO 	 * riwt_off field from the platform.
283762a2ab93SGiuseppe CAVALLARO 	 */
283862a2ab93SGiuseppe CAVALLARO 	if ((priv->synopsys_id >= DWMAC_CORE_3_50) && (!priv->plat->riwt_off)) {
283962a2ab93SGiuseppe CAVALLARO 		priv->use_riwt = 1;
284062a2ab93SGiuseppe CAVALLARO 		pr_info(" Enable RX Mitigation via HW Watchdog Timer\n");
284162a2ab93SGiuseppe CAVALLARO 	}
284262a2ab93SGiuseppe CAVALLARO 
2843bfab27a1SGiuseppe CAVALLARO 	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);
28447ac6653aSJeff Kirsher 
28457ac6653aSJeff Kirsher 	spin_lock_init(&priv->lock);
2846a9097a96SGiuseppe CAVALLARO 	spin_lock_init(&priv->tx_lock);
28477ac6653aSJeff Kirsher 
2848bfab27a1SGiuseppe CAVALLARO 	ret = register_netdev(ndev);
28497ac6653aSJeff Kirsher 	if (ret) {
2850cf3f047bSGiuseppe CAVALLARO 		pr_err("%s: ERROR %i registering the device\n", __func__, ret);
28516a81c26fSViresh Kumar 		goto error_netdev_register;
28527ac6653aSJeff Kirsher 	}
28537ac6653aSJeff Kirsher 
2854cd7201f4SGiuseppe CAVALLARO 	/* If a specific clk_csr value is passed from the platform
2855cd7201f4SGiuseppe CAVALLARO 	 * this means that the CSR Clock Range selection cannot be
2856cd7201f4SGiuseppe CAVALLARO 	 * changed at run-time and it is fixed. Viceversa the driver'll try to
2857cd7201f4SGiuseppe CAVALLARO 	 * set the MDC clock dynamically according to the csr actual
2858cd7201f4SGiuseppe CAVALLARO 	 * clock input.
2859cd7201f4SGiuseppe CAVALLARO 	 */
2860cd7201f4SGiuseppe CAVALLARO 	if (!priv->plat->clk_csr)
2861cd7201f4SGiuseppe CAVALLARO 		stmmac_clk_csr_set(priv);
2862cd7201f4SGiuseppe CAVALLARO 	else
2863cd7201f4SGiuseppe CAVALLARO 		priv->clk_csr = priv->plat->clk_csr;
2864cd7201f4SGiuseppe CAVALLARO 
2865e58bb43fSGiuseppe CAVALLARO 	stmmac_check_pcs_mode(priv);
2866e58bb43fSGiuseppe CAVALLARO 
28674d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
28684d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI) {
28694bfcbd7aSFrancesco Virlinzi 		/* MDIO bus Registration */
28704bfcbd7aSFrancesco Virlinzi 		ret = stmmac_mdio_register(ndev);
28714bfcbd7aSFrancesco Virlinzi 		if (ret < 0) {
28724bfcbd7aSFrancesco Virlinzi 			pr_debug("%s: MDIO bus (id: %d) registration failed",
28734bfcbd7aSFrancesco Virlinzi 				 __func__, priv->plat->bus_id);
28746a81c26fSViresh Kumar 			goto error_mdio_register;
28754bfcbd7aSFrancesco Virlinzi 		}
2876e58bb43fSGiuseppe CAVALLARO 	}
28774bfcbd7aSFrancesco Virlinzi 
2878bfab27a1SGiuseppe CAVALLARO 	return priv;
28797ac6653aSJeff Kirsher 
28806a81c26fSViresh Kumar error_mdio_register:
28817ac6653aSJeff Kirsher 	unregister_netdev(ndev);
28826a81c26fSViresh Kumar error_netdev_register:
28836a81c26fSViresh Kumar 	netif_napi_del(&priv->napi);
288462866e98SChen-Yu Tsai error_hw_init:
288562866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
288662866e98SChen-Yu Tsai error_clk_get:
28877ac6653aSJeff Kirsher 	free_netdev(ndev);
28887ac6653aSJeff Kirsher 
2889c5e4ddbdSChen-Yu Tsai 	return ERR_PTR(ret);
28907ac6653aSJeff Kirsher }
28917ac6653aSJeff Kirsher 
28927ac6653aSJeff Kirsher /**
28937ac6653aSJeff Kirsher  * stmmac_dvr_remove
2894bfab27a1SGiuseppe CAVALLARO  * @ndev: net device pointer
28957ac6653aSJeff Kirsher  * Description: this function resets the TX/RX processes, disables the MAC RX/TX
2896bfab27a1SGiuseppe CAVALLARO  * changes the link status, releases the DMA descriptor rings.
28977ac6653aSJeff Kirsher  */
2898bfab27a1SGiuseppe CAVALLARO int stmmac_dvr_remove(struct net_device *ndev)
28997ac6653aSJeff Kirsher {
29007ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
29017ac6653aSJeff Kirsher 
29027ac6653aSJeff Kirsher 	pr_info("%s:\n\tremoving driver", __func__);
29037ac6653aSJeff Kirsher 
29047ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
29057ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
29067ac6653aSJeff Kirsher 
2907bfab27a1SGiuseppe CAVALLARO 	stmmac_set_mac(priv->ioaddr, false);
29084d8f0825SByungho An 	if (priv->pcs != STMMAC_PCS_RGMII && priv->pcs != STMMAC_PCS_TBI &&
29094d8f0825SByungho An 	    priv->pcs != STMMAC_PCS_RTBI)
29104bfcbd7aSFrancesco Virlinzi 		stmmac_mdio_unregister(ndev);
29117ac6653aSJeff Kirsher 	netif_carrier_off(ndev);
29127ac6653aSJeff Kirsher 	unregister_netdev(ndev);
2913c5e4ddbdSChen-Yu Tsai 	if (priv->stmmac_rst)
2914c5e4ddbdSChen-Yu Tsai 		reset_control_assert(priv->stmmac_rst);
291562866e98SChen-Yu Tsai 	clk_disable_unprepare(priv->stmmac_clk);
29167ac6653aSJeff Kirsher 	free_netdev(ndev);
29177ac6653aSJeff Kirsher 
29187ac6653aSJeff Kirsher 	return 0;
29197ac6653aSJeff Kirsher }
29207ac6653aSJeff Kirsher 
29217ac6653aSJeff Kirsher #ifdef CONFIG_PM
2922bfab27a1SGiuseppe CAVALLARO int stmmac_suspend(struct net_device *ndev)
29237ac6653aSJeff Kirsher {
29247ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2925f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
29267ac6653aSJeff Kirsher 
29277ac6653aSJeff Kirsher 	if (!ndev || !netif_running(ndev))
29287ac6653aSJeff Kirsher 		return 0;
29297ac6653aSJeff Kirsher 
2930102463b1SFrancesco Virlinzi 	if (priv->phydev)
2931102463b1SFrancesco Virlinzi 		phy_stop(priv->phydev);
2932102463b1SFrancesco Virlinzi 
2933f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
29347ac6653aSJeff Kirsher 
29357ac6653aSJeff Kirsher 	netif_device_detach(ndev);
29367ac6653aSJeff Kirsher 	netif_stop_queue(ndev);
29377ac6653aSJeff Kirsher 
29387ac6653aSJeff Kirsher 	napi_disable(&priv->napi);
29397ac6653aSJeff Kirsher 
29407ac6653aSJeff Kirsher 	/* Stop TX/RX DMA */
29417ac6653aSJeff Kirsher 	priv->hw->dma->stop_tx(priv->ioaddr);
29427ac6653aSJeff Kirsher 	priv->hw->dma->stop_rx(priv->ioaddr);
2943c24602efSGiuseppe CAVALLARO 
2944c24602efSGiuseppe CAVALLARO 	stmmac_clear_descriptors(priv);
29457ac6653aSJeff Kirsher 
29467ac6653aSJeff Kirsher 	/* Enable Power down mode by programming the PMT regs */
294789f7f2cfSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
29487ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, priv->wolopts);
294989f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 1;
295089f7f2cfSSrinivas Kandagatla 	} else {
2951bfab27a1SGiuseppe CAVALLARO 		stmmac_set_mac(priv->ioaddr, false);
2952db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_sleep_state(priv->device);
2953ba1377ffSGiuseppe CAVALLARO 		/* Disable clock in case of PWM is off */
2954a630844dSStefan Roese 		clk_disable_unprepare(priv->stmmac_clk);
2955ba1377ffSGiuseppe CAVALLARO 	}
2956f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
29572d871aa0SVince Bridgers 
29582d871aa0SVince Bridgers 	priv->oldlink = 0;
29592d871aa0SVince Bridgers 	priv->speed = 0;
29602d871aa0SVince Bridgers 	priv->oldduplex = -1;
29617ac6653aSJeff Kirsher 	return 0;
29627ac6653aSJeff Kirsher }
29637ac6653aSJeff Kirsher 
2964bfab27a1SGiuseppe CAVALLARO int stmmac_resume(struct net_device *ndev)
29657ac6653aSJeff Kirsher {
29667ac6653aSJeff Kirsher 	struct stmmac_priv *priv = netdev_priv(ndev);
2967f8c5a875SGiuseppe CAVALLARO 	unsigned long flags;
29687ac6653aSJeff Kirsher 
29697ac6653aSJeff Kirsher 	if (!netif_running(ndev))
29707ac6653aSJeff Kirsher 		return 0;
29717ac6653aSJeff Kirsher 
2972f8c5a875SGiuseppe CAVALLARO 	spin_lock_irqsave(&priv->lock, flags);
29737ac6653aSJeff Kirsher 
29747ac6653aSJeff Kirsher 	/* Power Down bit, into the PM register, is cleared
29757ac6653aSJeff Kirsher 	 * automatically as soon as a magic packet or a Wake-up frame
29767ac6653aSJeff Kirsher 	 * is received. Anyway, it's better to manually clear
29777ac6653aSJeff Kirsher 	 * this bit because it can generate problems while resuming
2978ceb69499SGiuseppe CAVALLARO 	 * from another devices (e.g. serial console).
2979ceb69499SGiuseppe CAVALLARO 	 */
2980623997fbSSrinivas Kandagatla 	if (device_may_wakeup(priv->device)) {
29817ed24bbeSVince Bridgers 		priv->hw->mac->pmt(priv->hw, 0);
298289f7f2cfSSrinivas Kandagatla 		priv->irq_wake = 0;
2983623997fbSSrinivas Kandagatla 	} else {
2984db88f10aSSrinivas Kandagatla 		pinctrl_pm_select_default_state(priv->device);
2985ba1377ffSGiuseppe CAVALLARO 		/* enable the clk prevously disabled */
2986a630844dSStefan Roese 		clk_prepare_enable(priv->stmmac_clk);
2987623997fbSSrinivas Kandagatla 		/* reset the phy so that it's ready */
2988623997fbSSrinivas Kandagatla 		if (priv->mii)
2989623997fbSSrinivas Kandagatla 			stmmac_mdio_reset(priv->mii);
2990623997fbSSrinivas Kandagatla 	}
29917ac6653aSJeff Kirsher 
29927ac6653aSJeff Kirsher 	netif_device_attach(ndev);
29937ac6653aSJeff Kirsher 
2994623997fbSSrinivas Kandagatla 	stmmac_hw_setup(ndev);
29957ac6653aSJeff Kirsher 
29967ac6653aSJeff Kirsher 	napi_enable(&priv->napi);
29977ac6653aSJeff Kirsher 
29987ac6653aSJeff Kirsher 	netif_start_queue(ndev);
29997ac6653aSJeff Kirsher 
3000f8c5a875SGiuseppe CAVALLARO 	spin_unlock_irqrestore(&priv->lock, flags);
3001102463b1SFrancesco Virlinzi 
3002102463b1SFrancesco Virlinzi 	if (priv->phydev)
3003102463b1SFrancesco Virlinzi 		phy_start(priv->phydev);
3004102463b1SFrancesco Virlinzi 
30057ac6653aSJeff Kirsher 	return 0;
30067ac6653aSJeff Kirsher }
30077ac6653aSJeff Kirsher #endif /* CONFIG_PM */
30087ac6653aSJeff Kirsher 
300933d5e332SGiuseppe CAVALLARO /* Driver can be configured w/ and w/ both PCI and Platf drivers
301033d5e332SGiuseppe CAVALLARO  * depending on the configuration selected.
301133d5e332SGiuseppe CAVALLARO  */
3012ba27ec66SGiuseppe CAVALLARO static int __init stmmac_init(void)
3013ba27ec66SGiuseppe CAVALLARO {
3014493682b8SKonstantin Khlebnikov 	int ret;
3015ba27ec66SGiuseppe CAVALLARO 
3016493682b8SKonstantin Khlebnikov 	ret = stmmac_register_platform();
3017493682b8SKonstantin Khlebnikov 	if (ret)
3018493682b8SKonstantin Khlebnikov 		goto err;
3019493682b8SKonstantin Khlebnikov 	ret = stmmac_register_pci();
3020493682b8SKonstantin Khlebnikov 	if (ret)
3021493682b8SKonstantin Khlebnikov 		goto err_pci;
302233d5e332SGiuseppe CAVALLARO 	return 0;
3023493682b8SKonstantin Khlebnikov err_pci:
3024493682b8SKonstantin Khlebnikov 	stmmac_unregister_platform();
3025493682b8SKonstantin Khlebnikov err:
3026493682b8SKonstantin Khlebnikov 	pr_err("stmmac: driver registration failed\n");
3027493682b8SKonstantin Khlebnikov 	return ret;
3028ba27ec66SGiuseppe CAVALLARO }
3029ba27ec66SGiuseppe CAVALLARO 
3030ba27ec66SGiuseppe CAVALLARO static void __exit stmmac_exit(void)
3031ba27ec66SGiuseppe CAVALLARO {
303233d5e332SGiuseppe CAVALLARO 	stmmac_unregister_platform();
303333d5e332SGiuseppe CAVALLARO 	stmmac_unregister_pci();
3034ba27ec66SGiuseppe CAVALLARO }
3035ba27ec66SGiuseppe CAVALLARO 
3036ba27ec66SGiuseppe CAVALLARO module_init(stmmac_init);
3037ba27ec66SGiuseppe CAVALLARO module_exit(stmmac_exit);
3038ba27ec66SGiuseppe CAVALLARO 
30397ac6653aSJeff Kirsher #ifndef MODULE
30407ac6653aSJeff Kirsher static int __init stmmac_cmdline_opt(char *str)
30417ac6653aSJeff Kirsher {
30427ac6653aSJeff Kirsher 	char *opt;
30437ac6653aSJeff Kirsher 
30447ac6653aSJeff Kirsher 	if (!str || !*str)
30457ac6653aSJeff Kirsher 		return -EINVAL;
30467ac6653aSJeff Kirsher 	while ((opt = strsep(&str, ",")) != NULL) {
30477ac6653aSJeff Kirsher 		if (!strncmp(opt, "debug:", 6)) {
3048ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &debug))
30497ac6653aSJeff Kirsher 				goto err;
30507ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "phyaddr:", 8)) {
3051ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 8, 0, &phyaddr))
30527ac6653aSJeff Kirsher 				goto err;
30537ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_txsize:", 11)) {
3054ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_txsize))
30557ac6653aSJeff Kirsher 				goto err;
30567ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "dma_rxsize:", 11)) {
3057ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &dma_rxsize))
30587ac6653aSJeff Kirsher 				goto err;
30597ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "buf_sz:", 7)) {
3060ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 7, 0, &buf_sz))
30617ac6653aSJeff Kirsher 				goto err;
30627ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "tc:", 3)) {
3063ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 3, 0, &tc))
30647ac6653aSJeff Kirsher 				goto err;
30657ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "watchdog:", 9)) {
3066ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 9, 0, &watchdog))
30677ac6653aSJeff Kirsher 				goto err;
30687ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "flow_ctrl:", 10)) {
3069ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &flow_ctrl))
30707ac6653aSJeff Kirsher 				goto err;
30717ac6653aSJeff Kirsher 		} else if (!strncmp(opt, "pause:", 6)) {
3072ea2ab871SGiuseppe CAVALLARO 			if (kstrtoint(opt + 6, 0, &pause))
30737ac6653aSJeff Kirsher 				goto err;
3074506f669cSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "eee_timer:", 10)) {
3075d765955dSGiuseppe CAVALLARO 			if (kstrtoint(opt + 10, 0, &eee_timer))
3076d765955dSGiuseppe CAVALLARO 				goto err;
30774a7d666aSGiuseppe CAVALLARO 		} else if (!strncmp(opt, "chain_mode:", 11)) {
30784a7d666aSGiuseppe CAVALLARO 			if (kstrtoint(opt + 11, 0, &chain_mode))
30794a7d666aSGiuseppe CAVALLARO 				goto err;
30807ac6653aSJeff Kirsher 		}
30817ac6653aSJeff Kirsher 	}
30827ac6653aSJeff Kirsher 	return 0;
30837ac6653aSJeff Kirsher 
30847ac6653aSJeff Kirsher err:
30857ac6653aSJeff Kirsher 	pr_err("%s: ERROR broken module parameter conversion", __func__);
30867ac6653aSJeff Kirsher 	return -EINVAL;
30877ac6653aSJeff Kirsher }
30887ac6653aSJeff Kirsher 
30897ac6653aSJeff Kirsher __setup("stmmaceth=", stmmac_cmdline_opt);
3090ceb69499SGiuseppe CAVALLARO #endif /* MODULE */
30916fc0d0f2SGiuseppe Cavallaro 
30926fc0d0f2SGiuseppe Cavallaro MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet device driver");
30936fc0d0f2SGiuseppe Cavallaro MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
30946fc0d0f2SGiuseppe Cavallaro MODULE_LICENSE("GPL");
3095